/*
-* Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+* Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
*
* Contact: Jan Olszak <j.olszak@samsung.com>
*
mSocketPath(socketPath)
{
LOGS("Client Constructor");
+ setNewPeerCallback(nullptr);
+ setRemovedPeerCallback(nullptr);
}
Client::~Client()
{
LOGS("Client start");
// Initialize the connection with the server
+ if (usesExternalPolling) {
+ startPoll();
+ }
+ mProcessor.start(usesExternalPolling);
+
LOGD("Connecting to " + mSocketPath);
auto socketPtr = std::make_shared<Socket>(Socket::connectSocket(mSocketPath));
mServiceFD = mProcessor.addPeer(socketPtr);
- mProcessor.start(usesExternalPolling);
}
bool Client::isStarted()
void Client::stop()
{
- LOGS("Client Destructor");
+ LOGS("Client stop");
mProcessor.stop();
+
+ if (mIPCGSourcePtr) {
+ stopPoll();
+ }
}
-std::vector<FileDescriptor> Client::getFDs()
+void Client::startPoll()
{
- std::vector<FileDescriptor> fds;
- fds.push_back(mProcessor.getEventFD());
- fds.push_back(mServiceFD);
+ LOGS("Client startPoll");
+ using namespace std::placeholders;
+ mIPCGSourcePtr = IPCGSource::create(std::bind(&Client::handle, this, _1, _2));
+ mIPCGSourcePtr->addFD(mProcessor.getEventFD());
+ mIPCGSourcePtr->attach();
+}
+
+void Client::stopPoll()
+{
+ LOGS("Client stopPoll");
- return fds;
+ mIPCGSourcePtr->removeFD(mProcessor.getEventFD());
+ mIPCGSourcePtr->detach();
+ mIPCGSourcePtr.reset();
}
void Client::handle(const FileDescriptor fd, const short pollEvent)
{
+ LOGS("Client handle");
+
+ if (!isStarted()) {
+ LOGW("Client stopped");
+ return;
+ }
+
if (fd == mProcessor.getEventFD() && (pollEvent & POLLIN)) {
mProcessor.handleEvent();
return;
void Client::setNewPeerCallback(const PeerCallback& newPeerCallback)
{
LOGS("Client setNewPeerCallback");
- mProcessor.setNewPeerCallback(newPeerCallback);
+ auto callback = [newPeerCallback, this](FileDescriptor fd) {
+ if (mIPCGSourcePtr) {
+ mIPCGSourcePtr->addFD(fd);
+ }
+ if (newPeerCallback) {
+ newPeerCallback(fd);
+ }
+ };
+ mProcessor.setNewPeerCallback(callback);
}
void Client::setRemovedPeerCallback(const PeerCallback& removedPeerCallback)
{
LOGS("Client setRemovedPeerCallback");
- mProcessor.setRemovedPeerCallback(removedPeerCallback);
+ auto callback = [removedPeerCallback, this](FileDescriptor fd) {
+ if (mIPCGSourcePtr) {
+ mIPCGSourcePtr->removeFD(fd);
+ }
+ if (removedPeerCallback) {
+ removedPeerCallback(fd);
+ }
+ };
+ mProcessor.setRemovedPeerCallback(callback);
}
void Client::removeMethod(const MethodID methodID)
/*
-* Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+* Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
*
* Contact: Jan Olszak <j.olszak@samsung.com>
*
#define COMMON_IPC_CLIENT_HPP
#include "ipc/internals/processor.hpp"
+#include "ipc/ipc-gsource.hpp"
#include "ipc/types.hpp"
#include "logger/logger.hpp"
void stop();
/**
- * Used with an external polling loop
- *
- * @return vector of internal file descriptors
- */
- std::vector<FileDescriptor> getFDs();
-
- /**
* Used with an external polling loop.
* Handles one event from the file descriptor.
*
* @param method method handling implementation
*/
template<typename SentDataType, typename ReceivedDataType>
- void addMethodHandler(const MethodID methodID,
+ void setMethodHandler(const MethodID methodID,
const typename MethodHandler<SentDataType, ReceivedDataType>::type& method);
/**
* @tparam ReceivedDataType data type to serialize
*/
template<typename ReceivedDataType>
- void addSignalHandler(const MethodID methodID,
+ void setSignalHandler(const MethodID methodID,
const typename SignalHandler<ReceivedDataType>::type& signal);
/**
const std::shared_ptr<SentDataType>& data);
private:
+
+ void startPoll();
+ void stopPoll();
+
FileDescriptor mServiceFD;
Processor mProcessor;
std::string mSocketPath;
+ IPCGSource::Pointer mIPCGSourcePtr;
};
template<typename SentDataType, typename ReceivedDataType>
-void Client::addMethodHandler(const MethodID methodID,
+void Client::setMethodHandler(const MethodID methodID,
const typename MethodHandler<SentDataType, ReceivedDataType>::type& method)
{
- LOGS("Client addMethodHandler, methodID: " << methodID);
- mProcessor.addMethodHandler<SentDataType, ReceivedDataType>(methodID, method);
+ LOGS("Client setMethodHandler, methodID: " << methodID);
+ mProcessor.setMethodHandler<SentDataType, ReceivedDataType>(methodID, method);
}
template<typename ReceivedDataType>
-void Client::addSignalHandler(const MethodID methodID,
+void Client::setSignalHandler(const MethodID methodID,
const typename SignalHandler<ReceivedDataType>::type& handler)
{
- LOGS("Client addSignalHandler, methodID: " << methodID);
- mProcessor.addSignalHandler<ReceivedDataType>(methodID, handler);
+ LOGS("Client setSignalHandler, methodID: " << methodID);
+ mProcessor.setSignalHandler<ReceivedDataType>(methodID, handler);
}
template<typename SentDataType, typename ReceivedDataType>
/*
-* Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+* Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
*
* Contact: Jan Olszak <j.olszak@samsung.com>
*
/*
-* Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+* Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
*
* Contact: Jan Olszak <j.olszak@samsung.com>
*
/*
-* Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+* Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
*
* Contact: Jan Olszak <j.olszak@samsung.com>
*
/*
-* Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+* Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
*
* Contact: Jan Olszak <j.olszak@samsung.com>
*
utils::signalBlock(SIGPIPE);
using namespace std::placeholders;
- addMethodHandlerInternal<EmptyData, RegisterSignalsMessage>(REGISTER_SIGNAL_METHOD_ID,
+ setMethodHandlerInternal<EmptyData, RegisterSignalsMessage>(REGISTER_SIGNAL_METHOD_ID,
std::bind(&Processor::onNewSignals, this, _1, _2));
}
if (!isStarted()) {
LOGI(mLogPrefix + "Processor start");
mIsRunning = true;
+ mUsesExternalPolling = usesExternalPolling;
if (!usesExternalPolling) {
mThread = std::thread(&Processor::run, this);
}
mRemovedPeerCallback(peerFD);
}
-
resetPolling();
}
{
LOGS(mLogPrefix + "Processor resetPolling");
- if (!isStarted()) {
- LOGW(mLogPrefix + "Processor not started! Polling not reset!");
+ if (mUsesExternalPolling) {
return;
}
break;
}
case Event::REMOVE_PEER: {
- request.get<RemovePeerRequest>()->conditionPtr->notify_all();
+ onRemovePeerRequest(*request.get<RemovePeerRequest>());
break;
}
case Event::SIGNAL:
}
mIsRunning = false;
+
request.conditionPtr->notify_all();
return true;
}
/*
-* Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+* Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
*
* Contact: Jan Olszak <j.olszak@samsung.com>
*
* @tparam ReceivedDataType data type to receive
*/
template<typename SentDataType, typename ReceivedDataType>
- void addMethodHandler(const MethodID methodID,
+ void setMethodHandler(const MethodID methodID,
const typename MethodHandler<SentDataType, ReceivedDataType>::type& process);
/**
* @tparam ReceivedDataType data type to receive
*/
template<typename ReceivedDataType>
- void addSignalHandler(const MethodID methodID,
+ void setSignalHandler(const MethodID methodID,
const typename SignalHandler<ReceivedDataType>::type& process);
/**
RequestQueue<Event> mRequestQueue;
bool mIsRunning;
+ bool mUsesExternalPolling;
std::unordered_map<MethodID, std::shared_ptr<MethodHandlers>> mMethodsCallbacks;
std::unordered_map<MethodID, std::shared_ptr<SignalHandlers>> mSignalsCallbacks;
std::thread mThread;
template<typename SentDataType, typename ReceivedDataType>
- void addMethodHandlerInternal(const MethodID methodID,
+ void setMethodHandlerInternal(const MethodID methodID,
const typename MethodHandler<SentDataType, ReceivedDataType>::type& process);
template<typename ReceivedDataType>
};
template<typename SentDataType, typename ReceivedDataType>
-void Processor::addMethodHandlerInternal(const MethodID methodID,
+void Processor::setMethodHandlerInternal(const MethodID methodID,
const typename MethodHandler<SentDataType, ReceivedDataType>::type& method)
{
MethodHandlers methodCall;
}
template<typename SentDataType, typename ReceivedDataType>
-void Processor::addMethodHandler(const MethodID methodID,
+void Processor::setMethodHandler(const MethodID methodID,
const typename MethodHandler<SentDataType, ReceivedDataType>::type& method)
{
if (methodID == RETURN_METHOD_ID || methodID == REGISTER_SIGNAL_METHOD_ID) {
throw IPCException("MethodID used by a signal: " + std::to_string(methodID));
}
- addMethodHandlerInternal<SentDataType, ReceivedDataType >(methodID, method);
+ setMethodHandlerInternal<SentDataType, ReceivedDataType >(methodID, method);
}
}
template<typename ReceivedDataType>
-void Processor::addSignalHandler(const MethodID methodID,
+void Processor::setSignalHandler(const MethodID methodID,
const typename SignalHandler<ReceivedDataType>::type& handler)
{
if (methodID == RETURN_METHOD_ID || methodID == REGISTER_SIGNAL_METHOD_ID) {
/*
-* Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+* Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
*
* Contact: Jan Olszak <j.olszak@samsung.com>
*
/*
-* Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+* Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
*
* Contact: Jan Olszak <j.olszak@samsung.com>
*
/*
-* Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+* Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
*
* Contact: Jan Olszak <j.olszak@samsung.com>
*
/*
-* Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+* Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
*
* Contact: Jan Olszak <j.olszak@samsung.com>
*
#include "config.hpp"
#include "ipc/ipc-gsource.hpp"
-
-#if GLIB_CHECK_VERSION(2,36,0)
-
+#include "utils/callback-wrapper.hpp"
#include "logger/logger.hpp"
+
#include <algorithm>
namespace vasum {
namespace {
+gushort conditions = static_cast<gushort>(G_IO_IN |
+ G_IO_ERR |
+ G_IO_HUP);
-GIOCondition conditions = static_cast<GIOCondition>(G_IO_IN |
- G_IO_ERR |
- G_IO_HUP);
}
-
-IPCGSource::IPCGSource(const std::vector<FileDescriptor> fds,
- const HandlerCallback& handlerCallback)
+IPCGSource::IPCGSource(const HandlerCallback& handlerCallback)
: mHandlerCallback(handlerCallback)
{
- LOGS("IPCGSource constructor");
-
- for (const FileDescriptor fd : fds) {
- addFD(fd);
- }
+ LOGT("IPCGSource Constructor");
}
IPCGSource::~IPCGSource()
{
- LOGS("~IPCGSource");
+ LOGT("IPCGSource Destructor");
}
-IPCGSource::Pointer IPCGSource::create(const std::vector<FileDescriptor>& fds,
- const HandlerCallback& handlerCallback)
+IPCGSource::Pointer IPCGSource::create(const HandlerCallback& handlerCallback)
{
- LOGS("Creating IPCGSource");
+ LOGT("Creating IPCGSource");
static GSourceFuncs funcs = { &IPCGSource::prepare,
&IPCGSource::check,
// Fill additional data
IPCGSource* source = reinterpret_cast<IPCGSource*>(gSource);
- new(source)IPCGSource(fds, handlerCallback);
+ new(source) IPCGSource(handlerCallback);
auto deleter = [](IPCGSource * ptr) {
LOGD("Deleter");
-
- if (!g_source_is_destroyed(&(ptr->mGSource))) {
- // This way finalize method will be run in glib loop's thread
- g_source_destroy(&(ptr->mGSource));
- }
+ g_source_unref(&ptr->mGSource);
};
- return std::shared_ptr<IPCGSource>(source, deleter);
+ Pointer ipcGSourcePtr(source, deleter);
+
+ g_source_set_callback(gSource,
+ &IPCGSource::onHandlerCall,
+ utils::createCallbackWrapper(Pointer(ipcGSourcePtr), ipcGSourcePtr->mGuard.spawn()),
+ &utils::deleteCallbackWrapper<Pointer>);
+
+ return ipcGSourcePtr;
}
void IPCGSource::addFD(const FileDescriptor fd)
{
+ LOGI("Adding to glib FD: " << fd);
+ Lock lock(mStateMutex);
- if (!&mGSource) {
- // In case it's called as a callback but the IPCGSource is destroyed
- return;
- }
- LOGS("Adding fd to glib");
-
- gpointer tag = g_source_add_unix_fd(&mGSource,
- fd,
- conditions);
- FDInfo fdInfo(tag, fd);
- mFDInfos.push_back(std::move(fdInfo));
+ mGPollFDs.push_back({fd, conditions, 0});
+ g_source_add_poll(&mGSource, &mGPollFDs.back());
}
void IPCGSource::removeFD(const FileDescriptor fd)
{
- if (!&mGSource) {
- // In case it's called as a callback but the IPCGSource is destroyed
- return;
- }
+ Lock lock(mStateMutex);
+
+ auto it = std::find_if(mGPollFDs.begin(), mGPollFDs.end(), [fd](GPollFD gPollFD) {
+ return gPollFD.fd = fd;
+ });
- LOGS("Removing fd from glib");
- auto it = std::find(mFDInfos.begin(), mFDInfos.end(), fd);
- if (it == mFDInfos.end()) {
+ if (it == mGPollFDs.end()) {
LOGE("No such fd");
return;
}
- g_source_remove_unix_fd(&mGSource, it->tag);
- mFDInfos.erase(it);
+ g_source_remove_poll(&mGSource, &(*it));
+ mGPollFDs.erase(it);
+ LOGI("Removed from glib FD: " << fd);
}
guint IPCGSource::attach(GMainContext* context)
{
- LOGS("Attaching to GMainContext");
+ LOGT("Attaching to GMainContext");
guint ret = g_source_attach(&mGSource, context);
- g_source_unref(&mGSource);
return ret;
}
+void IPCGSource::detach()
+{
+ LOGT("Detaching");
+ Lock lock(mStateMutex);
+
+ for (GPollFD gPollFD : mGPollFDs) {
+ g_source_remove_poll(&mGSource, &gPollFD);
+ }
+
+ mGPollFDs.clear();
+ if (!g_source_is_destroyed(&mGSource)) {
+ LOGD("Destroying");
+ // This way finalize method will be run in glib loop's thread
+ g_source_destroy(&mGSource);
+ }
+}
+
+void IPCGSource::callHandler()
+{
+ Lock lock(mStateMutex);
+
+ for (const GPollFD& gPollFD : mGPollFDs) {
+ if (gPollFD.revents & conditions) {
+ mHandlerCallback(gPollFD.fd, gPollFD.revents);
+ }
+ }
+}
+
+gboolean IPCGSource::onHandlerCall(gpointer userData)
+{
+ const auto& source = utils::getCallbackFromPointer<Pointer>(userData);
+ if (source) {
+ source->callHandler();
+ }
+ return TRUE;
+}
+
gboolean IPCGSource::prepare(GSource* gSource, gint* timeout)
{
- if (!gSource) {
+ if (!gSource || g_source_is_destroyed(gSource)) {
return FALSE;
}
gboolean IPCGSource::check(GSource* gSource)
{
- if (!gSource) {
+ if (!gSource || g_source_is_destroyed(gSource)) {
return FALSE;
}
}
gboolean IPCGSource::dispatch(GSource* gSource,
- GSourceFunc /*callback*/,
- gpointer /*userData*/)
+ GSourceFunc callback,
+ gpointer userData)
{
if (!gSource || g_source_is_destroyed(gSource)) {
// Remove the GSource from the GMainContext
return FALSE;
}
- IPCGSource* source = reinterpret_cast<IPCGSource*>(gSource);
-
- for (const FDInfo fdInfo : source->mFDInfos) {
- GIOCondition cond = g_source_query_unix_fd(gSource, fdInfo.tag);
- if (conditions & cond) {
- source->mHandlerCallback(fdInfo.fd, cond);
- }
+ if (callback) {
+ callback(userData);
}
return TRUE;
void IPCGSource::finalize(GSource* gSource)
{
- LOGS("IPCGSource Finalize");
-
if (gSource) {
IPCGSource* source = reinterpret_cast<IPCGSource*>(gSource);
source->~IPCGSource();
} // namespace ipc
} // namespace vasum
-
-#endif // GLIB_CHECK_VERSION
/*
-* Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+* Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
*
* Contact: Jan Olszak <j.olszak@samsung.com>
*
#define COMMON_IPC_IPC_GSOURCE_HPP
#include <glib.h>
-#if GLIB_CHECK_VERSION(2,36,0)
-
-#include "ipc/service.hpp"
#include "ipc/types.hpp"
+#include "utils/callback-guard.hpp"
#include <memory>
+#include <mutex>
+#include <list>
namespace vasum {
guint attach(GMainContext* context = nullptr);
/**
+ * After this method quits handlerCallback will not be called
+ */
+ void detach();
+
+ /**
* Creates the IPCGSource class in the memory allocated by glib.
* Calls IPCGSource's constructor
*
- * @param fds initial set of file descriptors
* @param handlerCallback event handling callback
*
* @return pointer to the IPCGSource
*/
- static Pointer create(const std::vector<FileDescriptor>& fds,
- const HandlerCallback& handlerCallback);
+ static Pointer create(const HandlerCallback& handlerCallback);
+
+ /**
+ * Callback for the dispatch function
+ */
+ static gboolean onHandlerCall(gpointer userData);
+
+ /**
+ * Locks the internal state mutex and calls the handler callback for each fd
+ */
+ void callHandler();
private:
+ typedef std::unique_lock<std::recursive_mutex> Lock;
/**
* GSourceFuncs' callback
*/
static void finalize(GSource* source);
-
-
// Called only from IPCGSource::create
- IPCGSource(const std::vector<FileDescriptor> fds,
- const HandlerCallback& handlerCallback);
-
- struct FDInfo {
- FDInfo(gpointer tag, FileDescriptor fd)
- : tag(tag), fd(fd) {}
-
- bool operator==(const gpointer t)
- {
- return t == tag;
- }
-
- bool operator==(const FileDescriptor f)
- {
- return f == fd;
- }
-
- gpointer tag;
- FileDescriptor fd;
- };
+ IPCGSource(const HandlerCallback& handlerCallback);
GSource mGSource;
HandlerCallback mHandlerCallback;
- std::vector<FDInfo> mFDInfos;
+ std::list<GPollFD> mGPollFDs;
+ utils::CallbackGuard mGuard;
+ std::recursive_mutex mStateMutex;
+
};
} // namespace ipc
} // namespace vasum
-#endif // GLIB_CHECK_VERSION
-
#endif // COMMON_IPC_IPC_GSOURCE_HPP
-// /*
-// * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
-// *
-// * Contact: Jan Olszak <j.olszak@samsung.com>
-// *
-// * 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
-// * @author Jan Olszak (j.olszak@samsung.com)
-// * @brief Implementation of the IPC handling class
-// */
+/*
+* Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+*
+* Contact: Jan Olszak <j.olszak@samsung.com>
+*
+* 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
+ * @author Jan Olszak (j.olszak@samsung.com)
+ * @brief Implementation of the IPC handling class
+ */
#include "config.hpp"
Service::Service(const std::string& socketPath,
const PeerCallback& addPeerCallback,
const PeerCallback& removePeerCallback)
- : mProcessor("[SERVICE] ", addPeerCallback, removePeerCallback),
+ : mProcessor("[SERVICE] "),
mAcceptor(socketPath, std::bind(&Processor::addPeer, &mProcessor, _1))
{
LOGS("Service Constructor");
+ setNewPeerCallback(addPeerCallback);
+ setRemovedPeerCallback(removePeerCallback);
}
Service::~Service()
void Service::start(const bool usesExternalPolling)
{
LOGS("Service start");
+ if (usesExternalPolling) {
+ startPoll();
+ }
mProcessor.start(usesExternalPolling);
// There can be an incoming connection from mAcceptor before mProcessor is listening,
LOGS("Service stop");
mAcceptor.stop();
mProcessor.stop();
+
+ if (mIPCGSourcePtr) {
+ stopPoll();
+ }
+}
+
+void Service::startPoll()
+{
+ LOGS("Service startPoll");
+
+ mIPCGSourcePtr = IPCGSource::create(std::bind(&Service::handle, this, _1, _2));
+ mIPCGSourcePtr->addFD(mAcceptor.getEventFD());
+ mIPCGSourcePtr->addFD(mAcceptor.getConnectionFD());
+ mIPCGSourcePtr->addFD(mProcessor.getEventFD());
+ mIPCGSourcePtr->attach();
}
-std::vector<FileDescriptor> Service::getFDs()
+void Service::stopPoll()
{
- std::vector<FileDescriptor> fds;
- fds.push_back(mAcceptor.getEventFD());
- fds.push_back(mAcceptor.getConnectionFD());
- fds.push_back(mProcessor.getEventFD());
+ LOGS("Service stopPoll");
- return fds;
+ mIPCGSourcePtr->removeFD(mAcceptor.getEventFD());
+ mIPCGSourcePtr->removeFD(mAcceptor.getConnectionFD());
+ mIPCGSourcePtr->removeFD(mProcessor.getEventFD());
+ mIPCGSourcePtr->detach();
+ mIPCGSourcePtr.reset();
}
void Service::handle(const FileDescriptor fd, const short pollEvent)
{
+ LOGS("Service handle");
+
+ if (!isStarted()) {
+ LOGW("Service stopped");
+ return;
+ }
+
if (fd == mProcessor.getEventFD() && (pollEvent & POLLIN)) {
mProcessor.handleEvent();
return;
}
}
-
void Service::setNewPeerCallback(const PeerCallback& newPeerCallback)
{
LOGS("Service setNewPeerCallback");
- mProcessor.setNewPeerCallback(newPeerCallback);
+ auto callback = [newPeerCallback, this](FileDescriptor fd) {
+ if (mIPCGSourcePtr) {
+ mIPCGSourcePtr->addFD(fd);
+ }
+ if (newPeerCallback) {
+ newPeerCallback(fd);
+ }
+ };
+ mProcessor.setNewPeerCallback(callback);
}
void Service::setRemovedPeerCallback(const PeerCallback& removedPeerCallback)
{
LOGS("Service setRemovedPeerCallback");
- mProcessor.setRemovedPeerCallback(removedPeerCallback);
+ auto callback = [removedPeerCallback, this](FileDescriptor fd) {
+ if (mIPCGSourcePtr) {
+ mIPCGSourcePtr->removeFD(fd);
+ }
+ if (removedPeerCallback) {
+ removedPeerCallback(fd);
+ }
+ };
+ mProcessor.setRemovedPeerCallback(callback);
}
void Service::removeMethod(const MethodID methodID)
/*
-* Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+* Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
*
* Contact: Jan Olszak <j.olszak@samsung.com>
*
#include "ipc/internals/processor.hpp"
#include "ipc/internals/acceptor.hpp"
+#include "ipc/ipc-gsource.hpp"
#include "ipc/types.hpp"
#include "logger/logger.hpp"
void stop();
/**
- * Used with an external polling loop
- *
- * @return vector of internal file descriptors
- */
- std::vector<FileDescriptor> getFDs();
-
- /**
* Used with an external polling loop.
* Handles one event from the file descriptor.
*
* @param method method handling implementation
*/
template<typename SentDataType, typename ReceivedDataType>
- void addMethodHandler(const MethodID methodID,
+ void setMethodHandler(const MethodID methodID,
const typename MethodHandler<SentDataType, ReceivedDataType>::type& method);
/**
* @tparam ReceivedDataType data type to serialize
*/
template<typename ReceivedDataType>
- void addSignalHandler(const MethodID methodID,
+ void setSignalHandler(const MethodID methodID,
const typename SignalHandler<ReceivedDataType>::type& handler);
/**
void signal(const MethodID methodID,
const std::shared_ptr<SentDataType>& data);
private:
+
+ void startPoll();
+ void stopPoll();
+
typedef std::lock_guard<std::mutex> Lock;
Processor mProcessor;
Acceptor mAcceptor;
+ IPCGSource::Pointer mIPCGSourcePtr;
};
template<typename SentDataType, typename ReceivedDataType>
-void Service::addMethodHandler(const MethodID methodID,
+void Service::setMethodHandler(const MethodID methodID,
const typename MethodHandler<SentDataType, ReceivedDataType>::type& method)
{
- LOGS("Service addMethodHandler, methodID " << methodID);
- mProcessor.addMethodHandler<SentDataType, ReceivedDataType>(methodID, method);
+ LOGS("Service setMethodHandler, methodID " << methodID);
+ mProcessor.setMethodHandler<SentDataType, ReceivedDataType>(methodID, method);
}
template<typename ReceivedDataType>
-void Service::addSignalHandler(const MethodID methodID,
+void Service::setSignalHandler(const MethodID methodID,
const typename SignalHandler<ReceivedDataType>::type& handler)
{
- LOGS("Service addSignalHandler, methodID " << methodID);
- mProcessor.addSignalHandler<ReceivedDataType>(methodID, handler);
+ LOGS("Service setSignalHandler, methodID " << methodID);
+ mProcessor.setSignalHandler<ReceivedDataType>(methodID, handler);
}
template<typename SentDataType, typename ReceivedDataType>
/*
-* Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+* Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
*
* Contact: Jan Olszak <j.olszak@samsung.com>
*
/*
-* Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+* Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
*
* Contact: Jan Olszak <j.olszak@samsung.com>
*
#include "ipc/service.hpp"
#include "ipc/client.hpp"
-#include "ipc/ipc-gsource.hpp"
#include "ipc/types.hpp"
#include "utils/glib-loop.hpp"
#include "utils/latch.hpp"
return data;
}
-FileDescriptor connect(Service& s, Client& c)
+FileDescriptor connect(Service& s, Client& c, bool isServiceGlib = false, bool isClientGlib = false)
{
// Connects the Client to the Service and returns Clients FileDescriptor
ValueLatch<FileDescriptor> peerFDLatch;
s.setNewPeerCallback(newPeerCallback);
if (!s.isStarted()) {
- s.start();
+ s.start(isServiceGlib);
}
- c.start();
+ c.start(isClientGlib);
FileDescriptor peerFD = peerFDLatch.get(TIMEOUT);
s.setNewPeerCallback(nullptr);
return peerFD;
}
-#if GLIB_CHECK_VERSION(2,36,0)
-
-std::pair<FileDescriptor, IPCGSource::Pointer> connectServiceGSource(Service& s, Client& c)
+FileDescriptor connectServiceGSource(Service& s, Client& c)
{
- ValueLatch<FileDescriptor> peerFDLatch;
- IPCGSource::Pointer ipcGSourcePtr = IPCGSource::create(s.getFDs(), std::bind(&Service::handle, &s, _1, _2));
-
- auto newPeerCallback = [&peerFDLatch, ipcGSourcePtr](const FileDescriptor newFD) {
- if (ipcGSourcePtr) {
- //TODO: Remove this if
- ipcGSourcePtr->addFD(newFD);
- }
- peerFDLatch.set(newFD);
- };
-
-
- s.setNewPeerCallback(newPeerCallback);
- s.setRemovedPeerCallback(std::bind(&IPCGSource::removeFD, ipcGSourcePtr, _1));
- s.start(true);
- // Service starts to process
- ipcGSourcePtr->attach();
-
- c.start();
-
- FileDescriptor peerFD = peerFDLatch.get(TIMEOUT);
- s.setNewPeerCallback(nullptr);
- BOOST_REQUIRE_NE(peerFD, 0);
- return std::make_pair(peerFD, ipcGSourcePtr);
+ return connect(s, c, true, false);
}
-std::pair<FileDescriptor, IPCGSource::Pointer> connectClientGSource(Service& s, Client& c)
+FileDescriptor connectClientGSource(Service& s, Client& c)
{
- // Connects the Client to the Service and returns Clients FileDescriptor
- ValueLatch<FileDescriptor> peerFDLatch;
- auto newPeerCallback = [&peerFDLatch](const FileDescriptor newFD) {
- peerFDLatch.set(newFD);
- };
- s.setNewPeerCallback(newPeerCallback);
-
- if (!s.isStarted()) {
- // Service starts to process
- s.start();
- }
-
-
- c.start(true);
- IPCGSource::Pointer ipcGSourcePtr = IPCGSource::create(c.getFDs(),
- std::bind(&Client::handle, &c, _1, _2));
-
- ipcGSourcePtr->attach();
-
- FileDescriptor peerFD = peerFDLatch.get(TIMEOUT);
- s.setNewPeerCallback(nullptr);
- BOOST_REQUIRE_NE(peerFD, 0);
- return std::make_pair(peerFD, ipcGSourcePtr);
+ return connect(s, c, false, true);
}
-#endif // GLIB_CHECK_VERSION
-
-
void testEcho(Client& c, const MethodID methodID)
{
std::shared_ptr<SendData> sentData(new SendData(34));
BOOST_AUTO_TEST_CASE(ServiceAddRemoveMethod)
{
Service s(socketPath);
- s.addMethodHandler<EmptyData, EmptyData>(1, returnEmptyCallback);
- s.addMethodHandler<SendData, SendData>(1, returnDataCallback);
+ s.setMethodHandler<EmptyData, EmptyData>(1, returnEmptyCallback);
+ s.setMethodHandler<SendData, SendData>(1, returnDataCallback);
s.start();
- s.addMethodHandler<SendData, SendData>(1, echoCallback);
- s.addMethodHandler<SendData, SendData>(2, returnDataCallback);
+ s.setMethodHandler<SendData, SendData>(1, echoCallback);
+ s.setMethodHandler<SendData, SendData>(2, returnDataCallback);
Client c(socketPath);
connect(s, c);
{
Service s(socketPath);
Client c(socketPath);
- c.addMethodHandler<EmptyData, EmptyData>(1, returnEmptyCallback);
- c.addMethodHandler<SendData, SendData>(1, returnDataCallback);
+ c.setMethodHandler<EmptyData, EmptyData>(1, returnEmptyCallback);
+ c.setMethodHandler<SendData, SendData>(1, returnDataCallback);
FileDescriptor peerFD = connect(s, c);
- c.addMethodHandler<SendData, SendData>(1, echoCallback);
- c.addMethodHandler<SendData, SendData>(2, returnDataCallback);
+ c.setMethodHandler<SendData, SendData>(1, echoCallback);
+ c.setMethodHandler<SendData, SendData>(2, returnDataCallback);
testEcho(s, 1, peerFD);
{
Service s(socketPath);
- s.addMethodHandler<SendData, SendData>(1, returnDataCallback);
+ s.setMethodHandler<SendData, SendData>(1, returnDataCallback);
s.start();
s.stop();
{
Service s(socketPath);
Client c(socketPath);
- c.addMethodHandler<SendData, SendData>(1, returnDataCallback);
+ c.setMethodHandler<SendData, SendData>(1, returnDataCallback);
c.start();
c.stop();
BOOST_AUTO_TEST_CASE(SyncClientToServiceEcho)
{
Service s(socketPath);
- s.addMethodHandler<SendData, SendData>(1, echoCallback);
- s.addMethodHandler<SendData, SendData>(2, echoCallback);
+ s.setMethodHandler<SendData, SendData>(1, echoCallback);
+ s.setMethodHandler<SendData, SendData>(2, echoCallback);
Client c(socketPath);
connect(s, c);
BOOST_AUTO_TEST_CASE(Restart)
{
Service s(socketPath);
- s.addMethodHandler<SendData, SendData>(1, echoCallback);
+ s.setMethodHandler<SendData, SendData>(1, echoCallback);
s.start();
- s.addMethodHandler<SendData, SendData>(2, echoCallback);
+ s.setMethodHandler<SendData, SendData>(2, echoCallback);
Client c(socketPath);
c.start();
{
Service s(socketPath);
Client c(socketPath);
- c.addMethodHandler<SendData, SendData>(1, echoCallback);
+ c.setMethodHandler<SendData, SendData>(1, echoCallback);
FileDescriptor peerFD = connect(s, c);
std::shared_ptr<SendData> sentData(new SendData(56));
// Setup Service and Client
Service s(socketPath);
- s.addMethodHandler<SendData, SendData>(1, echoCallback);
+ s.setMethodHandler<SendData, SendData>(1, echoCallback);
s.start();
Client c(socketPath);
c.start();
Service s(socketPath);
Client c(socketPath);
- c.addMethodHandler<SendData, SendData>(1, echoCallback);
+ c.setMethodHandler<SendData, SendData>(1, echoCallback);
FileDescriptor peerFD = connect(s, c);
// Async call
BOOST_AUTO_TEST_CASE(SyncTimeout)
{
Service s(socketPath);
- s.addMethodHandler<SendData, SendData>(1, longEchoCallback);
+ s.setMethodHandler<SendData, SendData>(1, longEchoCallback);
Client c(socketPath);
connect(s, c);
BOOST_AUTO_TEST_CASE(SerializationError)
{
Service s(socketPath);
- s.addMethodHandler<SendData, SendData>(1, echoCallback);
+ s.setMethodHandler<SendData, SendData>(1, echoCallback);
Client c(socketPath);
connect(s, c);
BOOST_AUTO_TEST_CASE(ParseError)
{
Service s(socketPath);
- s.addMethodHandler<SendData, SendData>(1, echoCallback);
+ s.setMethodHandler<SendData, SendData>(1, echoCallback);
s.start();
Client c(socketPath);
};
// Method will throw during serialization and disconnect automatically
- s.addMethodHandler<SendData, ThrowOnAcceptData>(1, method);
+ s.setMethodHandler<SendData, ThrowOnAcceptData>(1, method);
s.start();
Client c(socketPath);
auto longEchoCallback = [](const FileDescriptor, std::shared_ptr<SendData>& data) {
return std::shared_ptr<LongSendData>(new LongSendData(data->intVal, LONG_OPERATION_TIME));
};
- s.addMethodHandler<LongSendData, SendData>(1, longEchoCallback);
+ s.setMethodHandler<LongSendData, SendData>(1, longEchoCallback);
Client c(socketPath);
connect(s, c);
BOOST_AUTO_TEST_CASE(WriteTimeout)
{
Service s(socketPath);
- s.addMethodHandler<SendData, SendData>(1, echoCallback);
+ s.setMethodHandler<SendData, SendData>(1, echoCallback);
s.start();
Client c(socketPath);
latchB.set();
};
- c.addSignalHandler<SendData>(1, handlerA);
- c.addSignalHandler<SendData>(2, handlerB);
+ c.setSignalHandler<SendData>(1, handlerA);
+ c.setSignalHandler<SendData>(2, handlerB);
// Wait for the signals to propagate to the Service
std::this_thread::sleep_for(std::chrono::milliseconds(2 * TIMEOUT));
latchB.set();
};
- c.addSignalHandler<SendData>(1, handlerA);
- c.addSignalHandler<SendData>(2, handlerB);
+ c.setSignalHandler<SendData>(1, handlerA);
+ c.setSignalHandler<SendData>(2, handlerB);
connect(s, c);
}
-#if GLIB_CHECK_VERSION(2,36,0)
-
-// FIXME This test causes segfault, however it should work in GDB.
BOOST_AUTO_TEST_CASE(ServiceGSource)
{
utils::Latch l;
IPCGSource::Pointer serviceGSource;
Service s(socketPath);
- s.addMethodHandler<SendData, SendData>(1, echoCallback);
+ s.setMethodHandler<SendData, SendData>(1, echoCallback);
Client c(socketPath);
- s.addSignalHandler<SendData>(2, signalHandler);
+ s.setSignalHandler<SendData>(2, signalHandler);
- auto ret = connectServiceGSource(s, c);
- serviceGSource = ret.second;
+ connectServiceGSource(s, c);
testEcho(c, 1);
BOOST_CHECK(l.wait(TIMEOUT));
}
+
BOOST_AUTO_TEST_CASE(ClientGSource)
{
utils::Latch l;
IPCGSource::Pointer clientGSource;
Client c(socketPath);
- c.addMethodHandler<SendData, SendData>(1, echoCallback);
- c.addSignalHandler<SendData>(2, signalHandler);
+ c.setMethodHandler<SendData, SendData>(1, echoCallback);
+ c.setSignalHandler<SendData>(2, signalHandler);
- auto ret = connectClientGSource(s, c);
- FileDescriptor peerFD = ret.first;
- clientGSource = ret.second;
+ FileDescriptor peerFD = connectClientGSource(s, c);
testEcho(s, 1, peerFD);
BOOST_CHECK(l.wait(TIMEOUT));
}
-#endif // GLIB_CHECK_VERSION
-
// BOOST_AUTO_TEST_CASE(ConnectionLimitTest)
// {
// unsigned oldLimit = ipc::getMaxFDNumber();
// // Setup Service and many Clients
// Service s(socketPath);
-// s.addMethodHandler<SendData, SendData>(1, echoCallback);
+// s.setMethodHandler<SendData, SendData>(1, echoCallback);
// s.start();
// std::list<Client> clients;