common/em-context.cpp
common/kvp-container.cpp
common/dispatcher.cpp
- common/mainloop.cpp
+ common/native-mainloop.cpp
common/service.cpp
common/socket.cpp
common/socket-descriptor.cpp
#include <cstdint>
#include <utility>
-#include <sys/epoll.h>
#include "common/exception.h"
#include "common/cs-detected.h"
#include "common/connection.h"
#include "common/async-protocol.h"
+#include "common/native-mainloop.h"
#include "common/audit/logger.h"
namespace Csr {
namespace Client {
AsyncLogic::AsyncLogic(HandleExt *handle, void *userdata) :
- m_handle(handle), m_userdata(userdata), m_dispatcherAsync(new Dispatcher(SockId::CS))
+ m_loop(new NativeMainloop()),
+ m_handle(handle),
+ m_userdata(userdata),
+ m_dispatcherAsync(new Dispatcher(SockId::CS))
{
}
auto fd = this->m_dispatcherAsync->getFd();
auto cancelEventFd = this->m_cancelSignal.getFd();
- this->m_loop.addEventSource(cancelEventFd, EPOLLIN,
- [&](uint32_t) {
+ this->m_loop->addEventSource(cancelEventFd, Mainloop::Event::READ,
+ [&](Mainloop::Event) {
this->m_cancelSignal.receive();
ThrowExcInfo(ASYNC_EVENT_CANCEL, "Async event cancelled on fd: " << fd);
});
- this->m_loop.addEventSource(fd, EPOLLIN | EPOLLHUP | EPOLLRDHUP,
- [&](uint32_t e) {
- if (e & (EPOLLHUP | EPOLLRDHUP))
+ this->m_loop->addEventSource(fd, Mainloop::Event::READ | Mainloop::Event::CLOSE,
+ [&](Mainloop::Event e) {
+ if ((e & Mainloop::Event::CLOSE) != Mainloop::Event::NONE)
ThrowExc(CSR_ERROR_SOCKET, "csr-server might be crashed. Finish async client loop");
// read event
});
try {
- while (true)
- this->m_loop.dispatch(-1);
+ this->m_loop->run(-1);
} catch (const Exception &e) {
switch (e.error()) {
case ASYNC_EVENT_COMPLETE:
private:
void scanHelper(const CommandId &id, const StrSet &s);
+ std::unique_ptr<Mainloop> m_loop;
HandleExt *m_handle; // for registering results for auto-release
void *m_userdata;
- Mainloop m_loop;
EventFd m_cancelSignal;
std::unique_ptr<Dispatcher> m_dispatcherAsync;
};
+++ /dev/null
-/*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-/*
- * @file mainloop.cpp
- * @author Kyungwook Tak (k.tak@samsung.com)
- * @version 1.0
- * @brief Mainloop of csr-server with epoll
- */
-#include "common/mainloop.h"
-
-#include <system_error>
-#include <sys/epoll.h>
-#include <unistd.h>
-
-#include "common/audit/logger.h"
-#include "common/exception.h"
-
-namespace Csr {
-
-Mainloop::Mainloop() :
- m_isTimedOut(false),
- m_pollfd(::epoll_create1(EPOLL_CLOEXEC))
-{
- if (this->m_pollfd == -1)
- throw std::system_error(
- std::error_code(errno, std::generic_category()),
- "Failed to epoll_create1");
-}
-
-Mainloop::~Mainloop()
-{
- if (!this->m_isTimedOut && !this->m_callbacks.empty())
- ERROR("mainloop registered callbacks should be empty except timed out case");
-
- ::close(m_pollfd);
-}
-
-void Mainloop::run(int timeout)
-{
- this->m_isTimedOut = false;
-
- while (!this->m_isTimedOut) {
- this->dispatch(timeout);
- }
-
- DEBUG("Mainloop run stopped");
-}
-
-void Mainloop::addEventSource(int fd, uint32_t event, Callback &&callback)
-{
- std::lock_guard<std::mutex> l(this->m_mutex);
-
- if (this->m_callbacks.count(fd) != 0)
- ThrowExc(CSR_ERROR_SERVER, "event source on fd[" << fd << "] already added!");
-
- DEBUG("Add event[" << event << "] source on fd[" << fd << "]");
-
- epoll_event e;
-
- e.events = event;
- e.data.fd = fd;
-
- if (::epoll_ctl(m_pollfd, EPOLL_CTL_ADD, fd, &e) == -1)
- throw std::system_error(
- std::error_code(errno, std::generic_category()),
- "epoll_ctl failed to EPOLL_CTL_ADD.");
-
- this->m_callbacks[fd] = std::move(callback);
-}
-
-void Mainloop::removeEventSource(int fd)
-{
- std::lock_guard<std::mutex> l(this->m_mutex);
-
- if (this->m_callbacks.count(fd) == 0)
- ThrowExc(CSR_ERROR_SERVER, "event source on fd[" << fd << "] isn't added at all");
-
- DEBUG("Remove event source on fd[" << fd << "]");
-
- this->m_callbacks.erase(fd);
-
- if (::epoll_ctl(m_pollfd, EPOLL_CTL_DEL, fd, nullptr) == -1) {
- if (errno == ENOENT)
- ThrowExc(CSR_ERROR_SERVER, "Tried to delete epoll item which wasn't added");
- else
- throw std::system_error(
- std::error_code(errno, std::generic_category()),
- "epoll_ctl failed to EPOLL_CTL_DEL.");
- }
-}
-
-size_t Mainloop::countEventSource() const
-{
- std::lock_guard<std::mutex> l(this->m_mutex);
- return this->m_callbacks.size();
-}
-
-void Mainloop::dispatch(int timeout)
-{
- int nfds = -1;
- epoll_event event[MAX_EPOLL_EVENTS];
-
- DEBUG("Mainloop dispatched with timeout: " << timeout);
-
- do {
- nfds = ::epoll_wait(this->m_pollfd, event, MAX_EPOLL_EVENTS,
- ((timeout < 0) ? -1 : (timeout * 1000)));
- } while ((nfds == -1) && (errno == EINTR));
-
- if (nfds < 0)
- throw std::system_error(
- std::error_code(errno, std::generic_category()),
- "epoll_wait failed!");
-
- if (nfds == 0) {
- DEBUG("Mainloop timed out!");
- if (this->m_isIdle && !this->m_isIdle()) {
- INFO("Mainloop timed out but there's running task on upper layer. "
- "Re-dispatch.");
- this->m_isTimedOut = false;
- } else {
- INFO("Mainloop timed out! stop the loop!");
- this->m_isTimedOut = true;
- }
-
- return;
- }
-
- for (int i = 0; i < nfds; i++) {
- int fd = event[i].data.fd;
-
- if (this->m_callbacks.count(fd) == 0)
- ThrowExc(CSR_ERROR_SERVER, "event in on fd[" << fd <<
- "] but associated callback isn't exist!");
-
- if (event[i].events & (EPOLLHUP | EPOLLRDHUP)) {
- INFO("peer connection closed on fd[" << fd << "]");
- event[i].events &= ~EPOLLIN;
- }
-
- DEBUG("event[" << event[i].events << "] polled on fd[" << fd << "]");
-
- this->m_callbacks[fd](event[i].events);
- }
-}
-
-void Mainloop::setIdleChecker(std::function<bool()> &&idleChecker)
-{
- this->m_isIdle = std::move(idleChecker);
-}
-
-}
/*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
*
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-/*
- * @file mainloop.h
- * @author Kyungwook Tak (k.tak@samsung.com)
- * @version 1.0
- * @brief Manageloop of csr-server with epoll
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
*/
#pragma once
#include <functional>
-#include <mutex>
-#include <unordered_map>
+#include <utility>
+#include <type_traits>
#include "common/macros.h"
namespace Csr {
-class API Mainloop {
+class Mainloop {
public:
- using Callback = std::function<void(uint32_t event)>;
+ enum class Event : uint32_t {
+ NONE = 0,
+ READ = 1 << 0,
+ WRITE = 1 << 1,
+ CLOSE = 1 << 2
+ };
+
+ using Callback = std::function<void(Event event)>;
- Mainloop();
- virtual ~Mainloop();
+ Mainloop() : m_domainSourceNum(0) {}
+ virtual ~Mainloop() {}
Mainloop(const Mainloop &) = delete;
Mainloop &operator=(const Mainloop &) = delete;
// timeout unit: seconds
// if timeout is negative value, no timeout on idle.
- void run(int timeout);
+ virtual void run(int timeout) = 0;
- // Moved to public to customize stop condition
- void dispatch(int timeout);
+ virtual void addEventSource(int fd, Event event, Callback &&callback) = 0;
+ virtual void removeEventSource(int fd) = 0;
- void addEventSource(int fd, uint32_t event, Callback &&callback);
- void removeEventSource(int fd);
- size_t countEventSource(void) const;
+ void addDomainEventSource(int fd, Event event, Callback &&callback)
+ {
+ ++this->m_domainSourceNum;
+ this->addEventSource(fd, event, std::move(callback));
+ }
- void setIdleChecker(std::function<bool()> &&idleChecker);
+protected:
+ size_t m_domainSourceNum;
+};
-private:
+template<typename T> using Underlying = typename std::underlying_type<T>::type;
+template<typename T>
+constexpr Underlying<T> underlying(T t) { return Underlying<T>(t); }
- bool m_isTimedOut;
- int m_pollfd;
- mutable std::mutex m_mutex;
- std::unordered_map<int, Callback> m_callbacks;
+inline constexpr Mainloop::Event operator&(Mainloop::Event e1, Mainloop::Event e2)
+{
+ return Mainloop::Event(underlying(e1) & underlying(e2));
+}
- std::function<bool()> m_isIdle;
+inline Mainloop::Event &operator&=(Mainloop::Event &e1, Mainloop::Event e2)
+{
+ return e1 = e1 & e2;
+}
- constexpr static size_t MAX_EPOLL_EVENTS = 32;
-};
+inline constexpr Mainloop::Event operator|(Mainloop::Event e1, Mainloop::Event e2)
+{
+ return Mainloop::Event(underlying(e1) | underlying(e2));
+}
+inline Mainloop::Event &operator|=(Mainloop::Event &e1, Mainloop::Event e2)
+{
+ return e1 = e1 | e2;
}
+
+inline constexpr Mainloop::Event operator~(Mainloop::Event e)
+{
+ return Mainloop::Event(~underlying(e));
+}
+
+} // namespace Csr
--- /dev/null
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+/*
+ * @file native-mainloop.cpp
+ * @author Kyungwook Tak (k.tak@samsung.com)
+ * @version 1.0
+ * @brief Mainloop of csr-server with epoll
+ */
+#include "common/native-mainloop.h"
+
+#include <system_error>
+#include <sys/epoll.h>
+#include <unistd.h>
+
+#include "common/audit/logger.h"
+#include "common/exception.h"
+
+namespace Csr {
+
+uint32_t NativeMainloop::convertFlags(Mainloop::Event events)
+{
+ uint32_t flags = 0;
+
+ if ((events & Mainloop::Event::READ) != Mainloop::Event::NONE)
+ flags |= EPOLLIN;
+ if ((events & Mainloop::Event::WRITE) != Mainloop::Event::NONE)
+ flags |= EPOLLOUT;
+ if ((events & Mainloop::Event::CLOSE) != Mainloop::Event::NONE)
+ flags |= (EPOLLHUP | EPOLLRDHUP);
+
+ return flags;
+}
+
+Mainloop::Event NativeMainloop::convertFlags(uint32_t events)
+{
+ Mainloop::Event flags = Mainloop::Event::NONE;
+
+ if (events & EPOLLIN)
+ flags |= Mainloop::Event::READ;
+ if (events & EPOLLOUT)
+ flags |= Mainloop::Event::WRITE;
+ if (events & (EPOLLHUP | EPOLLRDHUP))
+ flags |= Mainloop::Event::CLOSE;
+
+ return flags;
+}
+
+NativeMainloop::NativeMainloop() :
+ m_isTimedOut(false),
+ m_pollfd(::epoll_create1(EPOLL_CLOEXEC))
+{
+ if (this->m_pollfd == -1)
+ throw std::system_error(
+ std::error_code(errno, std::generic_category()),
+ "Failed to epoll_create1");
+}
+
+NativeMainloop::~NativeMainloop()
+{
+ if (!this->m_isTimedOut && !this->m_callbacks.empty())
+ ERROR("mainloop registered callbacks should be empty except timed out case");
+
+ ::close(m_pollfd);
+}
+
+void NativeMainloop::run(int timeout)
+{
+ this->m_isTimedOut = false;
+
+ while (!this->m_isTimedOut) {
+ this->dispatch(timeout);
+ }
+
+ DEBUG("NativeMainloop run stopped");
+}
+
+void NativeMainloop::addEventSource(
+ int fd, Mainloop::Event event, Mainloop::Callback &&callback)
+{
+ std::lock_guard<std::mutex> l(this->m_mutex);
+
+ if (this->m_callbacks.count(fd) != 0)
+ ThrowExc(CSR_ERROR_SERVER, "event source on fd[" << fd << "] already added!");
+
+ DEBUG("Add event[" << static_cast<uint32_t>(event)
+ << "] source on fd[" << fd << "]");
+
+ epoll_event e;
+
+ e.events = NativeMainloop::convertFlags(event);
+ e.data.fd = fd;
+
+ if (::epoll_ctl(m_pollfd, EPOLL_CTL_ADD, fd, &e) == -1)
+ throw std::system_error(
+ std::error_code(errno, std::generic_category()),
+ "epoll_ctl failed to EPOLL_CTL_ADD.");
+
+ this->m_callbacks[fd] = std::move(callback);
+}
+
+void NativeMainloop::removeEventSource(int fd)
+{
+ std::lock_guard<std::mutex> l(this->m_mutex);
+
+ auto it = this->m_callbacks.find(fd);
+ if (it == this->m_callbacks.end())
+ ThrowExc(CSR_ERROR_SERVER, "event source on fd[" << fd << "] isn't added at all");
+
+ DEBUG("Remove event source on fd[" << fd << "]");
+
+ this->m_callbacks.erase(it);
+
+ if (::epoll_ctl(m_pollfd, EPOLL_CTL_DEL, fd, nullptr) == -1) {
+ if (errno == ENOENT)
+ ThrowExc(CSR_ERROR_SERVER, "Tried to delete epoll item which wasn't added");
+ else
+ throw std::system_error(
+ std::error_code(errno, std::generic_category()),
+ "epoll_ctl failed to EPOLL_CTL_DEL.");
+ }
+}
+
+void NativeMainloop::dispatch(int timeout)
+{
+ int nfds = -1;
+ epoll_event event[MAX_EPOLL_EVENTS];
+
+ DEBUG("NativeMainloop dispatched with timeout: " << timeout);
+
+ do {
+ nfds = ::epoll_wait(this->m_pollfd, event, MAX_EPOLL_EVENTS,
+ ((timeout < 0) ? -1 : (timeout * 1000)));
+ } while ((nfds == -1) && (errno == EINTR));
+
+ if (nfds < 0)
+ throw std::system_error(
+ std::error_code(errno, std::generic_category()),
+ "epoll_wait failed!");
+
+ if (nfds == 0) {
+ DEBUG("NativeMainloop timed out!");
+ if (this->m_callbacks.size() > this->m_domainSourceNum) {
+ INFO("NativeMainloop timed out but there's running task on upper layer. "
+ "Re-dispatch.");
+ this->m_isTimedOut = false;
+ } else {
+ INFO("NativeMainloop timed out! stop the loop!");
+ this->m_isTimedOut = true;
+ }
+
+ return;
+ }
+
+ for (int i = 0; i < nfds; i++) {
+ int fd = event[i].data.fd;
+
+ auto it = this->m_callbacks.find(fd);
+ if (it == this->m_callbacks.end())
+ ThrowExc(CSR_ERROR_SERVER, "event in on fd[" << fd <<
+ "] but associated callback isn't exist!");
+
+ auto events = convertFlags(event[i].events);
+ if ((events & Mainloop::Event::CLOSE) != Mainloop::Event::NONE) {
+ INFO("peer connection closed on fd[" << fd << "]");
+ events &= ~Mainloop::Event::READ;
+ }
+
+ DEBUG("event[" << static_cast<uint32_t>(events)
+ << "] polled on fd[" << fd << "]");
+
+ it->second(events);
+ }
+}
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+/*
+ * @file native-mainloop.h
+ * @author Kyungwook Tak (k.tak@samsung.com)
+ * @version 1.0
+ * @brief Manageloop of csr-server with epoll
+ */
+#pragma once
+
+#include <functional>
+#include <mutex>
+#include <unordered_map>
+
+#include "common/mainloop.h"
+#include "common/macros.h"
+
+namespace Csr {
+
+class API NativeMainloop : public Mainloop {
+public:
+ NativeMainloop();
+ virtual ~NativeMainloop();
+
+ virtual void run(int timeout) override;
+ virtual void addEventSource(
+ int fd, Mainloop::Event event, Mainloop::Callback &&callback) override;
+ virtual void removeEventSource(int fd) override;
+
+private:
+ void dispatch(int timeout);
+ static uint32_t convertFlags(Mainloop::Event events);
+ static Mainloop::Event convertFlags(uint32_t events);
+
+ bool m_isTimedOut;
+ int m_pollfd;
+ mutable std::mutex m_mutex;
+ std::unordered_map<int, Mainloop::Callback> m_callbacks;
+
+ constexpr static size_t MAX_EPOLL_EVENTS = 32;
+};
+
+}
namespace Csr {
-Service::Service() noexcept
+Service::Service(Mainloop *mainloop)
{
+ if (mainloop == nullptr)
+ throw std::invalid_argument("mainloop shouldn't be null");
+
+ this->m_loop.reset(mainloop);
}
Service::~Service()
DEBUG("Get systemd socket[" << socket->getFd() <<
"] for sock id: " << static_cast<int>(id));
- this->m_loop.addEventSource(socket->getFd(), EPOLLIN | EPOLLHUP | EPOLLRDHUP,
- [this, socket](uint32_t event) {
- if (event != EPOLLIN)
- return;
+ this->m_loop->addDomainEventSource(
+ socket->getFd(),
+ Mainloop::Event::READ | Mainloop::Event::CLOSE,
+ [this, socket](Mainloop::Event events) {
+ if ((events & Mainloop::Event::READ) == Mainloop::Event::NONE)
+ return;
- this->onNewConnection(std::make_shared<Connection>(socket->accept()));
- });
+ this->onNewConnection(std::make_shared<Connection>(socket->accept()));
+ });
}
- this->m_loop.run(timeout);
+ this->m_loop->run(timeout);
}
void Service::onNewConnection(ConnShPtr &&connection)
INFO("welcome! accepted client socket fd[" << fd << "]");
- this->m_loop.addEventSource(fd, EPOLLIN | EPOLLHUP | EPOLLRDHUP,
- [&, fd](uint32_t event) {
- std::lock_guard<std::mutex> lock(this->m_crMtx);
+ this->m_loop->addEventSource(fd,
+ Mainloop::Event::READ | Mainloop::Event::CLOSE,
+ [&, fd](Mainloop::Event events) {
+ std::lock_guard<std::mutex> lock(this->m_crMtx);
- DEBUG("read event comes in to fd[" << fd << "]");
+ DEBUG("read event comes in to fd[" << fd << "]");
- if (this->m_connectionRegistry.count(fd) == 0)
- ThrowExc(CSR_ERROR_SERVER, "get event on fd[" << fd <<
- "] but no associated connection exist");
+ auto it = this->m_connectionRegistry.find(fd);
+ if (it == this->m_connectionRegistry.end())
+ ThrowExc(CSR_ERROR_SERVER, "get event on fd[" << fd <<
+ "] but no associated connection exist");
- auto &conn = this->m_connectionRegistry[fd];
-
- if (event & (EPOLLHUP | EPOLLRDHUP)) {
- DEBUG("event of epoll hup. close connection on fd[" << fd << "]");
- this->onCloseConnection(conn);
- return;
- }
+ auto &conn = it->second;
- DEBUG("Start message process on fd[" << fd << "]");
+ if ((events & Mainloop::Event::CLOSE) != Mainloop::Event::NONE) {
+ DEBUG("close event occured. close connection on fd[" << fd << "]");
+ this->onCloseConnection(conn);
+ return;
+ }
- onMessageProcess(conn);
- });
+ this->onMessageProcess(conn);
+ }
+ );
std::lock_guard<std::mutex> lock(this->m_crMtx);
this->m_connectionRegistry[fd] = std::move(connection);
auto fd = connection->getFd();
- if (this->m_connectionRegistry.count(fd) == 0)
+ auto it = this->m_connectionRegistry.find(fd);
+ if (it == this->m_connectionRegistry.end())
ThrowExc(CSR_ERROR_SERVER, "no connection in registry to remove "
"associated to fd[" << fd << "]");
INFO("good-bye! close socket fd[" << fd << "]");
- this->m_loop.removeEventSource(fd);
-
- this->m_connectionRegistry.erase(fd);
+ this->m_loop->removeEventSource(fd);
+ this->m_connectionRegistry.erase(it);
}
}
*/
#pragma once
-#include <string>
-#include <functional>
#include <set>
+#include <memory>
+#include <unordered_map>
#include <mutex>
#include "common/macros.h"
class API Service {
public:
- Service() noexcept;
+ Service(Mainloop *mainloop);
virtual ~Service();
Service(const Service &) = delete;
virtual void start(int timeout) final;
protected:
- Mainloop m_loop;
+ std::unique_ptr<Mainloop> m_loop;
private:
virtual void onMessageProcess(const ConnShPtr &) = 0;
#include <string>
-#include "common/macros.h"
#include "common/types.h"
#include "common/socket-descriptor.h"
#include "common/wp-result.h"
#include "common/exception.h"
#include "common/async-protocol.h"
+#include "common/native-mainloop.h"
#include "service/exception.h"
#include "service/access-control.h"
#include "service/core-usage.h"
} // namespace anonymous
-ServerService::ServerService() : Service(), m_workqueue(5)
+ServerService::ServerService() : Service(new NativeMainloop()), m_workqueue(5)
{
this->m_db = std::make_shared<Db::Manager>(RW_DBSPACE "/.csr.db", RO_DBSPACE);
this->add(SockId::CS);
this->add(SockId::WP);
this->add(SockId::ADMIN);
-
- // if task is not running in workqueue, it's idle.
- this->m_loop.setIdleChecker([this]()->bool {
- return (!this->m_workqueue.isTaskRunning() && this->m_loop.countEventSource() == 3);
- });
}
RawBuffer ServerService::processCs(const ConnShPtr &conn, RawBuffer &data)
logic.cpp
popup.cpp
popup-service.cpp
+ ecore-mainloop.cpp
package-info.cpp
${PROJECT_SOURCE_DIR}/src/framework/ui/common.cpp
)
--- /dev/null
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ecore-mainloop.h"
+
+#include <utility>
+#include <exception>
+
+#include "common/audit/logger.h"
+
+namespace Csr {
+namespace Ui {
+
+Ecore_Fd_Handler_Flags EcoreMainloop::convertFlags(Mainloop::Event events)
+{
+ uint32_t flags = 0;
+
+ if ((events & Mainloop::Event::READ) != Mainloop::Event::NONE)
+ flags |= ECORE_FD_READ;
+ if ((events & Mainloop::Event::WRITE) != Mainloop::Event::NONE)
+ flags |= ECORE_FD_WRITE;
+
+ return static_cast<Ecore_Fd_Handler_Flags>(flags);
+}
+
+Mainloop::Event EcoreMainloop::convertFlags(Ecore_Fd_Handler *handler)
+{
+ Mainloop::Event flags = Mainloop::Event::NONE;
+
+ if (ecore_main_fd_handler_active_get(handler, ECORE_FD_READ))
+ flags |= Mainloop::Event::READ;
+ if (ecore_main_fd_handler_active_get(handler, ECORE_FD_WRITE))
+ flags |= Mainloop::Event::WRITE;
+ if (ecore_main_fd_handler_active_get(handler, ECORE_FD_ERROR))
+ flags |= Mainloop::Event::CLOSE;
+
+ return flags;
+}
+
+EcoreMainloop::EcoreMainloop() : m_isExitCalled(false), m_timer(nullptr) {}
+
+EcoreMainloop::~EcoreMainloop()
+{
+ if (this->m_timer)
+ ecore_timer_del(this->m_timer);
+
+ if (!this->m_isExitCalled)
+ elm_exit();
+}
+
+void EcoreMainloop::run(int timeout)
+{
+ this->dispatch(timeout);
+}
+
+void EcoreMainloop::dispatch(int timeout)
+{
+ if (timeout >= 0) {
+ this->m_timer = ecore_timer_add(
+ static_cast<double>(timeout), &EcoreMainloop::ecoreTimeoutCb, this);
+
+ if (this->m_timer == nullptr) {
+ ERROR("Failed to ecore_timer_add()...");
+ }
+ }
+
+ elm_run();
+}
+
+void EcoreMainloop::addEventSource(
+ int fd, Mainloop::Event events, Mainloop::Callback &&callback)
+{
+ auto handler = ecore_main_fd_handler_add(
+ fd, convertFlags(events),
+ &EcoreMainloop::ecoreFdCallback, this, nullptr, nullptr);
+
+ if (handler == nullptr) {
+ ERROR("failed to handle fd(" << fd << ") by ecore_main_fd_handler_add()");
+ return;
+ }
+
+ std::unique_ptr<EventSource> source(new EventSource);
+ source->callback = std::move(callback);
+ source->handler = handler;
+
+ this->m_sources[fd] = std::move(source);
+}
+
+void EcoreMainloop::removeEventSource(int fd)
+{
+ auto it = this->m_sources.find(fd);
+
+ if (it == this->m_sources.end()) {
+ ERROR("fd(" << fd << ") associated source is not found");
+ return;
+ }
+
+ ecore_main_fd_handler_del(it->second->handler);
+
+ this->m_sources.erase(it);
+}
+
+Eina_Bool EcoreMainloop::ecoreFdCallback(void *data, Ecore_Fd_Handler *handler)
+{
+ auto mainloop = static_cast<EcoreMainloop *>(data);
+
+ if (mainloop == nullptr)
+ throw std::invalid_argument("userdata for ecore fd callback is invalid");
+
+ int fd = ecore_main_fd_handler_fd_get(handler);
+
+ auto it = mainloop->m_sources.find(fd);
+ if (it == mainloop->m_sources.end() || it->second == nullptr) {
+ ERROR("no associated source found with fd: " << fd);
+ return ECORE_CALLBACK_CANCEL;
+ }
+
+ it->second->callback(convertFlags(handler));
+
+ return ECORE_CALLBACK_RENEW;
+}
+
+Eina_Bool EcoreMainloop::ecoreTimeoutCb(void *data)
+{
+ auto mainloop = static_cast<EcoreMainloop *>(data);
+
+ if (mainloop == nullptr)
+ throw std::invalid_argument("userdata for ecore timeout callback is invalid");
+
+ if (mainloop->m_sources.size() == mainloop->m_domainSourceNum) {
+ INFO("There's no alive connection. Only listening socket opened. "
+ "Let's exit the ecore main loop!");
+
+ elm_exit();
+
+ mainloop->m_timer = nullptr;
+ mainloop->m_isExitCalled = true;
+
+ return ECORE_CALLBACK_CANCEL;
+ } else {
+ INFO("Time out expired but there's alive connection "
+ "so go ahead to next tick!");
+ return ECORE_CALLBACK_RENEW;
+ }
+}
+
+} // namespace Ui
+} // namespace Csr
--- /dev/null
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include <unordered_map>
+#include <memory>
+#include <Elementary.h>
+
+#include "common/mainloop.h"
+
+namespace Csr {
+namespace Ui {
+
+class EcoreMainloop : public Mainloop {
+public:
+ EcoreMainloop();
+ virtual ~EcoreMainloop();
+
+ virtual void run(int timeout) override;
+
+ virtual void addEventSource(
+ int fd, Mainloop::Event event, Mainloop::Callback &&callback) override;
+ virtual void removeEventSource(int fd) override;
+
+private:
+ struct EventSource {
+ Mainloop::Callback callback;
+ Ecore_Fd_Handler *handler;
+ };
+
+ void dispatch(int timeout);
+
+ static Ecore_Fd_Handler_Flags convertFlags(Mainloop::Event events);
+ static Mainloop::Event convertFlags(Ecore_Fd_Handler *handler);
+
+ static Eina_Bool ecoreFdCallback(void *data, Ecore_Fd_Handler *handler);
+ static Eina_Bool ecoreTimeoutCb(void *data);
+
+ std::unordered_map<int, std::unique_ptr<EventSource>> m_sources;
+
+ bool m_isExitCalled;
+ Ecore_Timer *m_timer;
+};
+
+} // namespace Ui
+} // namespace Csr
}
} // namespace anonymous
-RawBuffer Logic::csPromptData(const std::string &message, const CsDetected &d) const
+void Logic::csPromptData(const std::string &message, const CsDetected &d)
{
std::string risk(d.severity ==
CSR_CS_SEVERITY_LOW ? LABEL_RISK_LEVEL_LOW : LABEL_RISK_LEVEL_MEDIUM);
- Popup p(2);
+ m_popup.setButtons(2);
- p.setMessage(message);
- p.setTitle(CS_TITLE);
- p.setHeader(CS_PROMPT_DATA_HEADER);
- p.setBody(FORMAT(
+ m_popup.setMessage(message);
+ m_popup.setTitle(CS_TITLE);
+ m_popup.setHeader(CS_PROMPT_DATA_HEADER);
+ m_popup.setBody(FORMAT(
"- " << LABEL_RISK << risk << " (" << d.malwareName << ")"));
- p.setFooter(CS_PROMPT_DATA_FOOTER);
+ m_popup.setFooter(CS_PROMPT_DATA_FOOTER);
- p.setText(p.m_buttons[0], BTN_CANCEL);
- p.setText(p.m_buttons[1], BTN_OPEN);
+ m_popup.setText(m_popup.m_buttons[0], BTN_CANCEL);
+ m_popup.setText(m_popup.m_buttons[1], BTN_OPEN);
- p.m_types.emplace_back(
+ m_popup.m_types.emplace_back(
static_cast<int>(CSR_CS_USER_RESPONSE_PROCESSING_DISALLOWED));
- p.m_types.emplace_back(
+ m_popup.m_types.emplace_back(
static_cast<int>(CSR_CS_USER_RESPONSE_PROCESSING_ALLOWED));
- p.callbackRegister(p.m_buttons[0], &p.m_types[0]);
- p.callbackRegister(p.m_buttons[1], &p.m_types[1]);
- p.callbackRegister(p.m_hypertext, d.detailedUrl);
-
- p.run();
- return p.getResult();
+ m_popup.callbackRegister(m_popup.m_buttons[0], &m_popup.m_types[0]);
+ m_popup.callbackRegister(m_popup.m_buttons[1], &m_popup.m_types[1]);
+ m_popup.callbackRegister(m_popup.m_hypertext, d.detailedUrl);
}
-RawBuffer Logic::csPromptFile(const std::string &message, const CsDetected &d) const
+void Logic::csPromptFile(const std::string &message, const CsDetected &d)
{
std::string risk(d.severity ==
CSR_CS_SEVERITY_LOW ? LABEL_RISK_LEVEL_LOW : LABEL_RISK_LEVEL_MEDIUM);
std::string fileName, extraPath;
split(d.targetName, fileName, extraPath);
- Popup p(3);
+ m_popup.setButtons(3);
- p.setMessage(message);
- p.setTitle(CS_TITLE);
- p.setHeader(CS_PROMPT_FILE_HEADER);
- p.setBody(FORMAT(
+ m_popup.setMessage(message);
+ m_popup.setTitle(CS_TITLE);
+ m_popup.setHeader(CS_PROMPT_FILE_HEADER);
+ m_popup.setBody(FORMAT(
"- " << formatToString(LABEL_FILE_NAME, fileName) << "<br>" <<
"- " << formatToString(LABEL_FILE_PATH, extraPath) << "<br>" <<
"- " << LABEL_RISK << risk << " (" << d.malwareName << ")"));
std::string prefix(CS_NOTIFY_FILE_FOOTER);
- p.setFooter(FORMAT(prefix << "<br>" << CS_PROMPT_FILE_FOOTER));
+ m_popup.setFooter(FORMAT(prefix << "<br>" << CS_PROMPT_FILE_FOOTER));
- p.setText(p.m_buttons[0], BTN_CANCEL);
- p.setText(p.m_buttons[1], BTN_OPEN);
- p.setText(p.m_buttons[2], BTN_DELETE);
+ m_popup.setText(m_popup.m_buttons[0], BTN_CANCEL);
+ m_popup.setText(m_popup.m_buttons[1], BTN_OPEN);
+ m_popup.setText(m_popup.m_buttons[2], BTN_DELETE);
- p.m_types.emplace_back(
+ m_popup.m_types.emplace_back(
static_cast<int>(CSR_CS_USER_RESPONSE_PROCESSING_DISALLOWED));
- p.m_types.emplace_back(
+ m_popup.m_types.emplace_back(
static_cast<int>(CSR_CS_USER_RESPONSE_PROCESSING_ALLOWED));
- p.m_types.emplace_back(
+ m_popup.m_types.emplace_back(
static_cast<int>(CSR_CS_USER_RESPONSE_REMOVE));
- p.callbackRegister(p.m_buttons[0], &p.m_types[0]);
- p.callbackRegister(p.m_buttons[1], &p.m_types[1]);
- p.callbackRegister(p.m_buttons[2], &p.m_types[2]);
- p.callbackRegister(p.m_hypertext, d.detailedUrl);
-
- p.run();
- return p.getResult();
+ m_popup.callbackRegister(m_popup.m_buttons[0], &m_popup.m_types[0]);
+ m_popup.callbackRegister(m_popup.m_buttons[1], &m_popup.m_types[1]);
+ m_popup.callbackRegister(m_popup.m_buttons[2], &m_popup.m_types[2]);
+ m_popup.callbackRegister(m_popup.m_hypertext, d.detailedUrl);
}
-RawBuffer Logic::csPromptApp(const std::string &message, const CsDetected &d) const
+void Logic::csPromptApp(const std::string &message, const CsDetected &d)
{
std::string risk(d.severity ==
CSR_CS_SEVERITY_LOW ? LABEL_RISK_LEVEL_LOW : LABEL_RISK_LEVEL_MEDIUM);
PackageInfo info(d.pkgId);
- Popup p(3);
+ m_popup.setButtons(3);
- p.setMessage(message);
- p.setTitle(CS_TITLE);
- p.setHeader(CS_PROMPT_APP_HEADER);
- p.setBody(FORMAT(
+ m_popup.setMessage(message);
+ m_popup.setTitle(CS_TITLE);
+ m_popup.setHeader(CS_PROMPT_APP_HEADER);
+ m_popup.setBody(FORMAT(
LABEL_APP_NAME << info.getLabel() << "<br>" <<
LABEL_VERSION << info.getVersion() << "<br>" <<
LABEL_RISK << risk << " (" << d.malwareName << ")"));
- p.setIcon(info.getIconPath());
+ m_popup.setIcon(info.getIconPath());
std::string prefix = formatToString(CS_NOTIFY_APP_FOOTER, BTN_UNINSTALL);
- p.setFooter(FORMAT(prefix << "<br>" << CS_PROMPT_APP_FOOTER));
+ m_popup.setFooter(FORMAT(prefix << "<br>" << CS_PROMPT_APP_FOOTER));
- p.setText(p.m_buttons[0], BTN_CANCEL);
- p.setText(p.m_buttons[1], BTN_OPEN);
- p.setText(p.m_buttons[2], BTN_UNINSTALL);
+ m_popup.setText(m_popup.m_buttons[0], BTN_CANCEL);
+ m_popup.setText(m_popup.m_buttons[1], BTN_OPEN);
+ m_popup.setText(m_popup.m_buttons[2], BTN_UNINSTALL);
- p.m_types.emplace_back(
+ m_popup.m_types.emplace_back(
static_cast<int>(CSR_CS_USER_RESPONSE_PROCESSING_DISALLOWED));
- p.m_types.emplace_back(
+ m_popup.m_types.emplace_back(
static_cast<int>(CSR_CS_USER_RESPONSE_PROCESSING_ALLOWED));
- p.m_types.emplace_back(
+ m_popup.m_types.emplace_back(
static_cast<int>(CSR_CS_USER_RESPONSE_REMOVE));
- p.callbackRegister(p.m_buttons[0], &p.m_types[0]);
- p.callbackRegister(p.m_buttons[1], &p.m_types[1]);
- p.callbackRegister(p.m_buttons[2], &p.m_types[2]);
- p.callbackRegister(p.m_hypertext, d.detailedUrl);
-
- p.run();
- return p.getResult();
+ m_popup.callbackRegister(m_popup.m_buttons[0], &m_popup.m_types[0]);
+ m_popup.callbackRegister(m_popup.m_buttons[1], &m_popup.m_types[1]);
+ m_popup.callbackRegister(m_popup.m_buttons[2], &m_popup.m_types[2]);
+ m_popup.callbackRegister(m_popup.m_hypertext, d.detailedUrl);
}
-RawBuffer Logic::csNotifyData(const std::string &message, const CsDetected &d) const
+void Logic::csNotifyData(const std::string &message, const CsDetected &d)
{
- Popup p(1);
+ m_popup.setButtons(1);
- p.setMessage(message);
- p.setTitle(CS_TITLE);
- p.setHeader(CS_NOTIFY_DATA_HEADER);
- p.setBody(FORMAT(
+ m_popup.setMessage(message);
+ m_popup.setTitle(CS_TITLE);
+ m_popup.setHeader(CS_NOTIFY_DATA_HEADER);
+ m_popup.setBody(FORMAT(
"- " << LABEL_RISK << LABEL_RISK_LEVEL_HIGH <<
" (" << d.malwareName << ")"));
- p.setFooter(CS_NOTIFY_DATA_FOOTER);
+ m_popup.setFooter(CS_NOTIFY_DATA_FOOTER);
- p.setText(p.m_buttons[0], BTN_OK);
+ m_popup.setText(m_popup.m_buttons[0], BTN_OK);
- p.m_types.emplace_back(
+ m_popup.m_types.emplace_back(
static_cast<int>(CSR_CS_USER_RESPONSE_PROCESSING_DISALLOWED));
- p.callbackRegister(p.m_buttons[0], &p.m_types[0]);
- p.callbackRegister(p.m_hypertext, d.detailedUrl);
-
- p.run();
- return p.getResult();
+ m_popup.callbackRegister(m_popup.m_buttons[0], &m_popup.m_types[0]);
+ m_popup.callbackRegister(m_popup.m_hypertext, d.detailedUrl);
}
-RawBuffer Logic::csNotifyFile(const std::string &message, const CsDetected &d) const
+void Logic::csNotifyFile(const std::string &message, const CsDetected &d)
{
- Popup p(2);
+ m_popup.setButtons(2);
std::string fileName, extraPath;
split(d.targetName, fileName, extraPath);
- p.setMessage(message);
- p.setTitle(CS_TITLE);
- p.setHeader(CS_NOTIFY_FILE_HEADER);
- p.setBody(FORMAT(
+ m_popup.setMessage(message);
+ m_popup.setTitle(CS_TITLE);
+ m_popup.setHeader(CS_NOTIFY_FILE_HEADER);
+ m_popup.setBody(FORMAT(
"- " << formatToString(LABEL_FILE_NAME, fileName) << "<br>" <<
"- " << formatToString(LABEL_FILE_PATH, extraPath) << "<br>" <<
"- " << LABEL_RISK << LABEL_RISK_LEVEL_HIGH <<
" (" << d.malwareName << ")"));
- p.setFooter(CS_NOTIFY_FILE_FOOTER);
+ m_popup.setFooter(CS_NOTIFY_FILE_FOOTER);
- p.setText(p.m_buttons[0], BTN_CANCEL);
- p.setText(p.m_buttons[1], BTN_DELETE);
+ m_popup.setText(m_popup.m_buttons[0], BTN_CANCEL);
+ m_popup.setText(m_popup.m_buttons[1], BTN_DELETE);
- p.m_types.emplace_back(
+ m_popup.m_types.emplace_back(
static_cast<int>(CSR_CS_USER_RESPONSE_PROCESSING_DISALLOWED));
- p.m_types.emplace_back(
+ m_popup.m_types.emplace_back(
static_cast<int>(CSR_CS_USER_RESPONSE_REMOVE));
- p.callbackRegister(p.m_buttons[0], &p.m_types[0]);
- p.callbackRegister(p.m_buttons[1], &p.m_types[1]);
- p.callbackRegister(p.m_hypertext, d.detailedUrl);
-
- p.run();
- return p.getResult();
+ m_popup.callbackRegister(m_popup.m_buttons[0], &m_popup.m_types[0]);
+ m_popup.callbackRegister(m_popup.m_buttons[1], &m_popup.m_types[1]);
+ m_popup.callbackRegister(m_popup.m_hypertext, d.detailedUrl);
}
-RawBuffer Logic::csNotifyApp(const std::string &message, const CsDetected &d) const
+void Logic::csNotifyApp(const std::string &message, const CsDetected &d)
{
PackageInfo info(d.pkgId);
- Popup p(2);
+ m_popup.setButtons(2);
- p.setMessage(message);
- p.setTitle(CS_TITLE);
- p.setHeader(CS_NOTIFY_APP_HEADER);
- p.setIcon(info.getIconPath());
- p.setBody(FORMAT(
+ m_popup.setMessage(message);
+ m_popup.setTitle(CS_TITLE);
+ m_popup.setHeader(CS_NOTIFY_APP_HEADER);
+ m_popup.setIcon(info.getIconPath());
+ m_popup.setBody(FORMAT(
LABEL_APP_NAME << info.getLabel() << "<br>" <<
LABEL_VERSION << info.getVersion() << "<br>" <<
LABEL_RISK << LABEL_RISK_LEVEL_HIGH << " (" << d.malwareName << ")"));
- p.setFooter(formatToString(CS_NOTIFY_APP_FOOTER, BTN_UNINSTALL));
+ m_popup.setFooter(formatToString(CS_NOTIFY_APP_FOOTER, BTN_UNINSTALL));
- p.setText(p.m_buttons[0], BTN_CANCEL);
- p.setText(p.m_buttons[1], BTN_UNINSTALL);
+ m_popup.setText(m_popup.m_buttons[0], BTN_CANCEL);
+ m_popup.setText(m_popup.m_buttons[1], BTN_UNINSTALL);
- p.m_types.emplace_back(
+ m_popup.m_types.emplace_back(
static_cast<int>(CSR_CS_USER_RESPONSE_PROCESSING_DISALLOWED));
- p.m_types.emplace_back(
+ m_popup.m_types.emplace_back(
static_cast<int>(CSR_CS_USER_RESPONSE_PROCESSING_ALLOWED));
- p.callbackRegister(p.m_buttons[0], &p.m_types[0]);
- p.callbackRegister(p.m_buttons[1], &p.m_types[1]);
- p.callbackRegister(p.m_hypertext, d.detailedUrl);
-
- p.run();
- return p.getResult();
+ m_popup.callbackRegister(m_popup.m_buttons[0], &m_popup.m_types[0]);
+ m_popup.callbackRegister(m_popup.m_buttons[1], &m_popup.m_types[1]);
+ m_popup.callbackRegister(m_popup.m_hypertext, d.detailedUrl);
}
-RawBuffer Logic::wpPrompt(const std::string &message, const UrlItem &item) const
+void Logic::wpPrompt(const std::string &message, const UrlItem &item)
{
std::string risk(item.risk ==
CSR_WP_RISK_LOW ? LABEL_RISK_LEVEL_LOW : LABEL_RISK_LEVEL_MEDIUM);
- Popup p(2);
+ m_popup.setButtons(2);
- p.setMessage(message);
- p.setTitle(WP_TITLE);
- p.setHeader(WP_PROMPT_HEADER);
- p.setBody(FORMAT(
+ m_popup.setMessage(message);
+ m_popup.setTitle(WP_TITLE);
+ m_popup.setHeader(WP_PROMPT_HEADER);
+ m_popup.setBody(FORMAT(
"- " << formatToString(LABEL_URL, item.url) << "<br>" <<
"- " << LABEL_RISK << risk));
- p.setFooter(WP_PROMPT_FOOTER);
+ m_popup.setFooter(WP_PROMPT_FOOTER);
- p.setText(p.m_buttons[0], BTN_BLOCK);
- p.setText(p.m_buttons[1], BTN_VIEW);
+ m_popup.setText(m_popup.m_buttons[0], BTN_BLOCK);
+ m_popup.setText(m_popup.m_buttons[1], BTN_VIEW);
- p.m_types.emplace_back(
+ m_popup.m_types.emplace_back(
static_cast<int>(CSR_WP_USER_RESPONSE_PROCESSING_DISALLOWED));
- p.m_types.emplace_back(
+ m_popup.m_types.emplace_back(
static_cast<int>(CSR_WP_USER_RESPONSE_PROCESSING_ALLOWED));
- p.callbackRegister(p.m_buttons[0], &p.m_types[0]);
- p.callbackRegister(p.m_buttons[1], &p.m_types[1]);
- p.callbackRegister(p.m_hypertext, item.url);
-
- p.run();
- return p.getResult();
+ m_popup.callbackRegister(m_popup.m_buttons[0], &m_popup.m_types[0]);
+ m_popup.callbackRegister(m_popup.m_buttons[1], &m_popup.m_types[1]);
+ m_popup.callbackRegister(m_popup.m_hypertext, item.url);
}
-RawBuffer Logic::wpNotify(const std::string &message, const UrlItem &item) const
+void Logic::wpNotify(const std::string &message, const UrlItem &item)
{
- Popup p(1);
+ m_popup.setButtons(1);
- p.setMessage(message);
- p.setTitle(WP_TITLE);
- p.setHeader(WP_NOTIFY_HEADER);
- p.setBody(FORMAT(
+ m_popup.setMessage(message);
+ m_popup.setTitle(WP_TITLE);
+ m_popup.setHeader(WP_NOTIFY_HEADER);
+ m_popup.setBody(FORMAT(
"- " << formatToString(LABEL_URL, item.url) << "<br>" <<
"- " << LABEL_RISK << LABEL_RISK_LEVEL_HIGH));
- p.setFooter(WP_NOTIFY_FOOTER);
-
- p.setText(p.m_buttons[0], BTN_OK);
+ m_popup.setFooter(WP_NOTIFY_FOOTER);
- p.m_types.emplace_back(static_cast<int>(CSR_WP_USER_RESPONSE_PROCESSING_DISALLOWED));
+ m_popup.setText(m_popup.m_buttons[0], BTN_OK);
- p.callbackRegister(p.m_buttons[0], &p.m_types[0]);
- p.callbackRegister(p.m_hypertext, item.url);
+ m_popup.m_types.emplace_back(static_cast<int>(CSR_WP_USER_RESPONSE_PROCESSING_DISALLOWED));
- p.run();
- return p.getResult();
+ m_popup.callbackRegister(m_popup.m_buttons[0], &m_popup.m_types[0]);
+ m_popup.callbackRegister(m_popup.m_hypertext, item.url);
}
} // namespace Ui
} // namespace Csr
#include "common/types.h"
#include "common/cs-detected.h"
#include "ui/common.h"
+#include "popup.h"
namespace Csr {
namespace Ui {
class Logic {
public:
- Logic() = default;
- virtual ~Logic() = default;
-
- RawBuffer csPromptData(const std::string &, const CsDetected &) const;
- RawBuffer csPromptApp(const std::string &, const CsDetected &) const;
- RawBuffer csPromptFile(const std::string &, const CsDetected &) const;
- RawBuffer csNotifyData(const std::string &, const CsDetected &) const;
- RawBuffer csNotifyApp(const std::string &, const CsDetected &) const;
- RawBuffer csNotifyFile(const std::string &, const CsDetected &) const;
-
- RawBuffer wpPrompt(const std::string &, const UrlItem &) const;
- RawBuffer wpNotify(const std::string &, const UrlItem &) const;
+ Logic() {}
+ virtual ~Logic() {}
+
+ void csPromptData(const std::string &, const CsDetected &);
+ void csPromptApp(const std::string &, const CsDetected &);
+ void csPromptFile(const std::string &, const CsDetected &);
+ void csNotifyData(const std::string &, const CsDetected &);
+ void csNotifyApp(const std::string &, const CsDetected &);
+ void csNotifyFile(const std::string &, const CsDetected &);
+
+ void wpPrompt(const std::string &, const UrlItem &);
+ void wpNotify(const std::string &, const UrlItem &);
+
+ void setSender(Popup::Sender &&sender) {
+ m_popup.setSender(std::move(sender));
+ }
+
+private:
+ Popup m_popup;
};
} // namespace Ui
/*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
*
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-/*
- * @file popup-service.cpp
- * @author Kyungwook Tak (k.tak@samsung.com)
- * @version 1.0
- * @brief
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
*/
+
#include "popup-service.h"
#include "common/binary-queue.h"
#include "common/audit/logger.h"
+#include "common/types.h"
#include "common/exception.h"
-#include "common/cs-detected.h"
+
+#include "ecore-mainloop.h"
namespace Csr {
namespace Ui {
}
}
-} // namespace nonymous
+} // namespace anonymous
-PopupService::PopupService() : Service()
+PopupService::PopupService() : Csr::Service(new EcoreMainloop())
{
this->add(SockId::POPUP);
}
-RawBuffer PopupService::process(const ConnShPtr &, RawBuffer &data)
+void PopupService::onMessageProcess(const ConnShPtr &conn)
{
+ auto in = conn->receive();
+
+ // some fd handler from mainloop makes empty read event when client
+ // close connection. returning false from process() means connection
+ // is closed
+ if (in.empty())
+ throw std::invalid_argument("empty read event!");
+
BinaryQueue q;
- q.push(data);
+ q.push(std::move(in));
int intCid;
q.Deserialize(intCid);
- INFO("Request dispatch on popup-service. CommandId: " << static_cast<int>(intCid));
+ INFO("Request dispatch on popup service. CommandId: " << static_cast<int>(intCid));
if (isCsCommand(static_cast<Ui::CommandId>(intCid))) {
std::string message;
switch (static_cast<Ui::CommandId>(intCid)) {
case CommandId::CS_PROMPT_DATA:
- return m_logic.csPromptData(message, d);
+ m_logic.csPromptData(message, d);
+ break;
case CommandId::CS_PROMPT_APP:
- return m_logic.csPromptApp(message, d);
+ m_logic.csPromptApp(message, d);
+ break;
case CommandId::CS_PROMPT_FILE:
- return m_logic.csPromptFile(message, d);
+ m_logic.csPromptFile(message, d);
+ break;
case CommandId::CS_NOTIFY_DATA:
- return m_logic.csNotifyData(message, d);
+ m_logic.csNotifyData(message, d);
+ break;
case CommandId::CS_NOTIFY_APP:
- return m_logic.csNotifyApp(message, d);
+ m_logic.csNotifyApp(message, d);
+ break;
case CommandId::CS_NOTIFY_FILE:
- return m_logic.csNotifyFile(message, d);
+ m_logic.csNotifyFile(message, d);
+ break;
default:
ThrowExc(CSR_ERROR_SERVER, "protocol error. invalid ui command id.");
switch (static_cast<Ui::CommandId>(intCid)) {
case CommandId::WP_PROMPT:
- return m_logic.wpPrompt(message, item);
+ m_logic.wpPrompt(message, item);
+ break;
case CommandId::WP_NOTIFY:
- return m_logic.wpNotify(message, item);
+ m_logic.wpNotify(message, item);
+ break;
default:
ThrowExc(CSR_ERROR_SERVER, "protocol error. invalid ui command id.");
}
}
-}
-
-void PopupService::onMessageProcess(const ConnShPtr &connection)
-{
- DEBUG("process message on popup service");
-
- auto in = connection->receive();
- connection->send(this->process(connection, in));
- DEBUG("process done on popup service");
+ m_logic.setSender([conn](const RawBuffer &out) { conn->send(out); });
}
} // namespace Ui
}
-Popup::Popup(int buttonN)
+void Popup::setSender(Sender &&sender)
{
+ m_sender = std::move(sender);
+}
+
+Popup::Popup() : m_win(nullptr)
+{
+}
+
+void Popup::setButtons(int n)
+{
+ clear();
+
// Set win properties.
m_win = elm_win_add(nullptr, "CSR popup", ELM_WIN_NOTIFICATION);
elm_win_indicator_opacity_set(m_win, ELM_WIN_INDICATOR_TRANSLUCENT);
setRotationToWin(m_win);
eext_win_keygrab_set(m_win, HOME_KEY.c_str());
- ecore_event_handler_add(ECORE_EVENT_KEY_DOWN, keyDownCb, NULL);
+ ecore_event_handler_add(ECORE_EVENT_KEY_DOWN, keyDownCb, this);
// Set popup properties.
m_popup = elm_popup_add(m_win);
elm_box_horizontal_set(m_btnBox, EINA_TRUE);
elm_box_padding_set(m_btnBox, 0, 0);
- for(int i=1 ; i <= buttonN; i++) {
- std::string id("button" + std::to_string(i));
+ for (int i = 0; i < n; ++i) {
Evas_Object *button = elm_button_add(m_popup);
elm_object_style_set(button, "bottom");
setDefaultProperties(button);
Popup::~Popup()
{
- evas_object_del(m_win);
+ if (m_win != nullptr)
+ evas_object_del(m_win);
}
void Popup::setHeader(const std::string &header) noexcept
elm_image_file_set(m_icon, path.c_str(), NULL);
}
-void Popup::run(void)
-{
- elm_run();
-}
-
int Popup::response = -1;
RawBuffer Popup::getResult(void)
void Popup::callbackRegister(Evas_Object *obj, int *type)
{
- evas_object_smart_callback_add(obj, "clicked", btnClickedCb, type);
+ m_buttonSelectorMap[obj] = [type]() { return *type; };
+ evas_object_smart_callback_add(obj, "clicked", btnClickedCb, this);
}
void Popup::callbackRegister(Evas_Object *obj, const std::string &url)
}
}
-void Popup::btnClickedCb(void *data, Evas_Object *, void *)
+void Popup::btnClickedCb(void *data, Evas_Object *obj, void *)
{
- response = *(reinterpret_cast<int *>(data));
- elm_exit();
-}
+ auto popup = reinterpret_cast<Popup *>(data);
+ if (popup == nullptr)
+ throw std::invalid_argument("Popup instance is null in static btnClickedCb");
+ response = popup->m_buttonSelectorMap.at(obj)();
+ popup->terminateWindow();
+}
-Eina_Bool Popup::keyDownCb(void *, int , void *ev)
+Eina_Bool Popup::keyDownCb(void *data, int , void *ev)
{
DEBUG("Key down event caught.");
auto event = reinterpret_cast<Ecore_Event_Key *>(ev);
- if(event->key == HOME_KEY) {
+ if (event->key == HOME_KEY) {
+ auto popup = reinterpret_cast<Popup *>(data);
response = -1;
- elm_exit();
+ popup->terminateWindow();
}
// Let the event continue to other callbacks.
return ECORE_CALLBACK_PASS_ON;
}
+void Popup::terminateWindow()
+{
+ INFO("send result based on response and sender");
+ m_sender(getResult());
+
+ clear();
+}
+
+void Popup::clear()
+{
+ if (m_win != nullptr) {
+ // clear all resources
+ evas_object_del(m_win);
+ m_win = nullptr;
+ }
+
+ m_buttons.clear();
+ m_types.clear();
+}
+
} // namespace Ui
} // namespace Csr
#include "common/audit/logger.h"
#include "common/binary-queue.h"
+#include "common/types.h"
namespace Csr {
namespace Ui {
class Popup {
public:
- Popup(int buttonN);
+ Popup();
virtual ~Popup();
- void run(void);
+ void setButtons(int n);
+
RawBuffer getResult(void);
void setMessage(const std::string &msg) noexcept;
Popup(Popup &&) = delete;
Popup &operator=(Popup &&) = delete;
+ using Sender = std::function<void(const RawBuffer &)>;
+ void setSender(Sender &&sender);
+
void setTitle(const std::string &title) noexcept;
void setHeader(const std::string &header) noexcept;
void setBody(const std::string &body) noexcept;
void callbackRegister(Evas_Object *obj, int *type);
void callbackRegister(Evas_Object *obj, const std::string &url);
- static void btnClickedCb(void *data, Evas_Object *, void *);
- static void hypertextClickedCb(void *data, Evas_Object *, void *);
- static void rotationChangedCb(void *data, Evas_Object *, void *);
static Eina_Bool keyDownCb(void *, int, void *);
std::vector<Evas_Object *> m_buttons;
std::vector<int> m_types;
private:
+ static void btnClickedCb(void *data, Evas_Object *, void *);
+ static void hypertextClickedCb(void *data, Evas_Object *, void *);
+ static void rotationChangedCb(void *data, Evas_Object *, void *);
+
+ using ButtonSelector = std::function<int()>;
+ std::map<Evas_Object *, ButtonSelector> m_buttonSelectorMap;
+ void terminateWindow();
+ void clear();
+
void setDefaultProperties(Evas_Object *obj) noexcept;
void setRotationToWin(Evas_Object *obj) noexcept;
std::string m_iconPath;
std::string m_hypertextUrl;
- static int response;
-
int m_winW;
int m_winH;
+
+ Sender m_sender;
+
+ static int response;
};
} // namespace Ui