Added rmi static lib to agent_lib
authorAndriy Gudz <a.gudz@samsung.com>
Wed, 17 May 2017 15:02:40 +0000 (18:02 +0300)
committerAndriy Gudz <a.gudz@samsung.com>
Wed, 17 May 2017 15:05:13 +0000 (18:05 +0300)
41 files changed:
device_core/CMakeLists.txt
device_core/agent_lib/CMakeLists.txt
device_core/agent_lib/rmi/CMakeLists.txt [new file with mode: 0644]
device_core/agent_lib/rmi/inc/array.h [new file with mode: 0644]
device_core/agent_lib/rmi/inc/data-type.h [new file with mode: 0644]
device_core/agent_lib/rmi/inc/error.h [new file with mode: 0644]
device_core/agent_lib/rmi/inc/eventfd.h [new file with mode: 0644]
device_core/agent_lib/rmi/inc/exception.h [new file with mode: 0644]
device_core/agent_lib/rmi/inc/file-descriptor.h [new file with mode: 0644]
device_core/agent_lib/rmi/inc/filesystem.h [new file with mode: 0644]
device_core/agent_lib/rmi/inc/mainloop.h [new file with mode: 0644]
device_core/agent_lib/rmi/inc/object-latch.h [new file with mode: 0644]
device_core/agent_lib/rmi/inc/pam.h [new file with mode: 0644]
device_core/agent_lib/rmi/inc/preprocessor.h [new file with mode: 0644]
device_core/agent_lib/rmi/inc/process.h [new file with mode: 0644]
device_core/agent_lib/rmi/inc/reflection.h [new file with mode: 0644]
device_core/agent_lib/rmi/inc/rmi/callback-holder.h [new file with mode: 0644]
device_core/agent_lib/rmi/inc/rmi/client.h [new file with mode: 0644]
device_core/agent_lib/rmi/inc/rmi/connection.h [new file with mode: 0644]
device_core/agent_lib/rmi/inc/rmi/message-composer.h [new file with mode: 0644]
device_core/agent_lib/rmi/inc/rmi/message.h [new file with mode: 0644]
device_core/agent_lib/rmi/inc/rmi/notification.h [new file with mode: 0644]
device_core/agent_lib/rmi/inc/rmi/service.h [new file with mode: 0644]
device_core/agent_lib/rmi/inc/rmi/socket.h [new file with mode: 0644]
device_core/agent_lib/rmi/inc/serialize.h [new file with mode: 0644]
device_core/agent_lib/rmi/inc/smack.h [new file with mode: 0644]
device_core/agent_lib/rmi/inc/thread-pool.h [new file with mode: 0644]
device_core/agent_lib/rmi/src/error.cpp [new file with mode: 0644]
device_core/agent_lib/rmi/src/eventfd.cpp [new file with mode: 0644]
device_core/agent_lib/rmi/src/filesystem.cpp [new file with mode: 0644]
device_core/agent_lib/rmi/src/mainloop.cpp [new file with mode: 0644]
device_core/agent_lib/rmi/src/process.cpp [new file with mode: 0644]
device_core/agent_lib/rmi/src/rmi/client.cpp [new file with mode: 0644]
device_core/agent_lib/rmi/src/rmi/connection.cpp [new file with mode: 0644]
device_core/agent_lib/rmi/src/rmi/message-composer.cpp [new file with mode: 0644]
device_core/agent_lib/rmi/src/rmi/message.cpp [new file with mode: 0644]
device_core/agent_lib/rmi/src/rmi/notification.cpp [new file with mode: 0644]
device_core/agent_lib/rmi/src/rmi/service.cpp [new file with mode: 0644]
device_core/agent_lib/rmi/src/rmi/socket.cpp [new file with mode: 0644]
device_core/agent_lib/rmi/src/thread-pool.cpp [new file with mode: 0644]
device_core/utest/test_rmi.cpp [new file with mode: 0644]

index 41ad4b3..a46611a 100644 (file)
@@ -5,6 +5,7 @@ SET (CTRL_APP_LIB ${PROJECT_ROOT}/ctrl_app_lib)
 SET (CTRL_APP_LIB_PROJECT_NAME nmlib)
 SET (IOTIVITY_LIB_PROJECT_NAME iotivity)
 SET (AGENT_LIB_PROJECT_NAME agent_policy)
+SET (RMI_PROJECT_NAME rmi)
 
 if (DEFINED DEBUG)
 SET (CMAKE_BUILD_TYPE "Debug")
index 91d77d4..65e7e9a 100644 (file)
@@ -1,10 +1,12 @@
-get_filename_component(ProjectId ${CMAKE_CURRENT_SOURCE_DIR} NAME)
 project(${AGENT_LIB_PROJECT_NAME})
 
+add_subdirectory(${RMI_PROJECT_NAME})
+
 include_directories (
        inc
        ../iotivity_lib/inc
        ../ctrl_app_lib/inc
+       rmi/inc
 )
 
 FILE(GLOB SRCS src/*.cpp)
@@ -13,10 +15,12 @@ add_library (${PROJECT_NAME} ${SRCS})
 
 target_link_libraries(${PROJECT_NAME}
        ${IOTIVITY_LIB_PROJECT_NAME}
+       ${RMI_PROJECT_NAME}
 )
 
 install(TARGETS ${PROJECT_NAME} DESTINATION ${LIBDIR})
 #install(FILES tests.manifest DESTINATION ${MANIFESTDIR})
 
-message(STATUS "Configuring: " ${ProjectId})
+message(STATUS "Configuring: " ${PROJECT_NAME})
 message(STATUS "CMAKE_CXX_FLAGS: " ${CMAKE_CXX_FLAGS})
+
diff --git a/device_core/agent_lib/rmi/CMakeLists.txt b/device_core/agent_lib/rmi/CMakeLists.txt
new file mode 100644 (file)
index 0000000..115386f
--- /dev/null
@@ -0,0 +1,10 @@
+project(${RMI_PROJECT_NAME})
+
+FILE(GLOB SRCS src/*.cpp src/rmi/*.cpp)
+
+include_directories(inc inc/rmi)
+
+add_library (${PROJECT_NAME} ${SRCS})
+
+message(STATUS "Configuring: " ${PROJECT_NAME})
+message(STATUS "CMAKE_CXX_FLAGS: " ${CMAKE_CXX_FLAGS})
diff --git a/device_core/agent_lib/rmi/inc/array.h b/device_core/agent_lib/rmi/inc/array.h
new file mode 100644 (file)
index 0000000..910bdc2
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ *  Copyright (c) 2015 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
+ */
+
+#ifndef __RUNTIME_ARRAY_H__
+#define __RUNTIME_ARRAY_H__
+
+#include <vector>
+#include <utility>
+
+namespace runtime {
+
+template <typename T>
+class Array final {
+public:
+    Array() = delete;
+    Array(std::vector<T> &&list) :
+        list(std::move(list)), it(this->list.begin())
+    {
+    };
+    Array(const std::vector<T> &list) :
+        list(list), it(this->list.begin())
+    {
+    };
+
+    T *next()
+    {
+        if (it != list.end()) {
+            return &(*it++);
+        }
+        return NULL;
+    }
+
+private:
+    std::vector<T> list;
+    typename std::vector<T>::iterator it;
+};
+
+} // namespace runtime
+
+#endif // __RUNTIME_ARRAY_H__
diff --git a/device_core/agent_lib/rmi/inc/data-type.h b/device_core/agent_lib/rmi/inc/data-type.h
new file mode 100644 (file)
index 0000000..9c44075
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ *  Copyright (c) 2015 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
+ */
+
+#ifndef __RUNTIME_DATA_TYPE_H__
+#define __RUNTIME_DATA_TYPE_H__
+#include <string>
+#include <vector>
+#include <utility>
+
+#include "reflection.h"
+
+struct Void {
+    NO_REFLECTABLE_PROPERTY
+};
+
+struct String {
+    String() = default;
+    String(const String& str) : value(str.value) {}
+    String(String&& str) : value(std::move(str.value)) {}
+
+    String(const char* str) : value(str) {}
+    String(const std::string& str) : value(str) {}
+
+    String& operator=(const String& str)
+    {
+        if (this != &str) {
+            value = str.value;
+        }
+
+        return *this;
+    }
+
+    String& operator=(String&& str)
+    {
+        if (this != &str) {
+            value = std::move(str.value);
+        }
+        return *this;
+    }
+
+    std::string value;
+    REFLECTABLE(value)
+};
+
+struct StringPair {
+    std::string first;
+    std::string second;
+    REFLECTABLE(first, second)
+};
+
+struct Status {
+    Status() : code(0) {}
+    Status(int v) : code(v) {}
+
+    operator int() const
+    {
+        return code;
+    }
+
+    int code;
+    REFLECTABLE(code)
+};
+
+template<typename T>
+struct Vector {
+    std::vector<T> value;
+    REFLECTABLE(value)
+};
+
+#endif //!__RUNTIME_DATA_TYPE_H__
diff --git a/device_core/agent_lib/rmi/inc/error.h b/device_core/agent_lib/rmi/inc/error.h
new file mode 100644 (file)
index 0000000..af42719
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ *  Copyright (c) 2015 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
+ */
+
+#ifndef __RUNTIME_ERROR_H__
+#define __RUNTIME_ERROR_H__
+
+#include <string>
+
+namespace runtime {
+
+class Error {
+public:
+    static std::string message();
+    static std::string message(int errorCode);
+    static int lastErrorCode();
+};
+
+std::string GetSystemErrorMessage();
+std::string GetSystemErrorMessage(int errorCode);
+
+} // namespace runtime
+#endif //__RUNTIME_ERROR_H__
diff --git a/device_core/agent_lib/rmi/inc/eventfd.h b/device_core/agent_lib/rmi/inc/eventfd.h
new file mode 100644 (file)
index 0000000..c645227
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ *  Copyright (c) 2015 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
+ */
+
+#ifndef __RUNTIME_EVENTFD_H__
+#define __RUNTIME_EVENTFD_H__
+
+#include <sys/eventfd.h>
+
+namespace runtime {
+
+class EventFD {
+public:
+    EventFD(unsigned int initval = 0, int flags = EFD_SEMAPHORE | EFD_CLOEXEC);
+    ~EventFD();
+
+    EventFD(const EventFD&) = delete;
+    EventFD& operator=(const EventFD&) = delete;
+
+    void send();
+    void receive();
+
+    int getFd() const
+    {
+        return fd;
+    }
+
+private:
+    int fd;
+};
+
+} // namespace runtime
+
+#endif //__RUNTIME_EVENTFD_H__
+
diff --git a/device_core/agent_lib/rmi/inc/exception.h b/device_core/agent_lib/rmi/inc/exception.h
new file mode 100644 (file)
index 0000000..efa4ecd
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ *  Copyright (c) 2015 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
+ */
+
+#ifndef __RUNTIME_EXCEPTION_H__
+#define __RUNTIME_EXCEPTION_H__
+
+#include <stdexcept>
+#include <string>
+
+namespace runtime {
+
+class Exception: public std::runtime_error {
+public:
+    Exception(const std::string& error) :
+        std::runtime_error(error)
+    {
+    }
+};
+} // namespace runtime
+#endif //__RUNTIME_EXCEPTION_H__
diff --git a/device_core/agent_lib/rmi/inc/file-descriptor.h b/device_core/agent_lib/rmi/inc/file-descriptor.h
new file mode 100644 (file)
index 0000000..bfbcadf
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ *  Copyright (c) 2015 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
+ */
+
+#ifndef __RUNTIME_FILE_DESCRIPTOR_H__
+#define __RUNTIME_FILE_DESCRIPTOR_H__
+
+#include <unistd.h>
+
+#include <iostream>
+
+struct FileDescriptor {
+    FileDescriptor(int fd = -1, bool autoclose = false) :
+        fileDescriptor(fd),
+        autoClose(autoclose)
+    {
+    }
+
+    FileDescriptor(const FileDescriptor&) = delete;
+    FileDescriptor(FileDescriptor&& rhs) :
+        fileDescriptor(rhs.fileDescriptor),
+        autoClose(rhs.autoClose)
+    {
+        rhs.fileDescriptor = -1;
+    }
+
+    ~FileDescriptor() {
+        if ((fileDescriptor != -1) && (autoClose == true)) {
+            ::close(fileDescriptor);
+        }
+    }
+
+    FileDescriptor& operator=(const int fd) {
+        fileDescriptor = fd;
+        autoClose = false;
+        return *this;
+    }
+
+    FileDescriptor& operator=(FileDescriptor&& rhs) {
+        if (this != &rhs) {
+            fileDescriptor = rhs.fileDescriptor;
+            autoClose = rhs.autoClose;
+            rhs.fileDescriptor = -1;
+        }
+
+        return *this;
+    }
+
+    int fileDescriptor;
+    bool autoClose;
+};
+
+#endif //__RUNTIME_FILE_DESCRIPTOR_H__
diff --git a/device_core/agent_lib/rmi/inc/filesystem.h b/device_core/agent_lib/rmi/inc/filesystem.h
new file mode 100644 (file)
index 0000000..6383824
--- /dev/null
@@ -0,0 +1,211 @@
+/*
+ *  Copyright (c) 2015 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
+ */
+
+#ifndef __RUNTIME_FILESYSTEM_H__
+#define __RUNTIME_FILESYSTEM_H__
+
+#include <dirent.h>
+
+#include <string>
+
+namespace runtime {
+
+class Path {
+public:
+    Path();
+    Path(const std::string& path);
+    Path(const char* path);
+    Path(const Path& path);
+
+    ~Path();
+
+    Path& operator=(const Path& path);
+    Path& operator=(const std::string& path);
+    Path& operator=(const char* path);
+
+    bool operator==(const Path& path) const
+    {
+        return (pathname == path.pathname);
+    }
+
+    bool operator!=(const Path& path) const
+    {
+        return !(pathname == path.pathname);
+    }
+
+    bool isAbsolute() const
+    {
+        return (pathname[0] == '/');
+    }
+
+    bool isRelative() const
+    {
+        return !(pathname[0] == '/');
+    }
+
+    const std::string& getPathname() const
+    {
+        return pathname;
+    }
+
+private:
+    Path& assign(const Path& path);
+    Path& assign(const std::string& path);
+    Path& assign(const char* path);
+
+    std::string pathname;
+};
+
+class File {
+public:
+    File();
+    File(const std::string& pathname);
+    File(const File& file);
+    File(const Path& filePath);
+
+    ~File();
+
+    File& operator=(const std::string& pathname)
+    {
+        path = pathname;
+        return *this;
+    }
+
+    File& operator=(const File& file)
+    {
+        path = file.path;
+        return *this;
+    }
+
+    File& operator=(const Path& filePath)
+    {
+        path = filePath;
+        return *this;
+    }
+
+    bool operator<(const File& file) const;
+    bool operator>(const File& file) const;
+    bool operator<=(const File& file) const;
+    bool operator>=(const File& file) const;
+
+    bool operator==(const File& file) const
+    {
+        return (path == file.path);
+    }
+
+    bool operator!=(const File& file) const
+    {
+        return !(path == file.path);
+    }
+
+    bool exists() const;
+    bool canRead() const;
+    bool canWrite() const;
+    bool canExecute() const;
+
+    bool isLink() const;
+    bool isFile() const;
+    bool isDirectory() const;
+    bool isDevice() const;
+    bool isHidden() const;
+
+    void open(int flags, mode_t mode);
+    void close();
+    void copyTo(const std::string& pathname) const;
+    void moveTo(const std::string& pathname);
+    void renameTo(const std::string& pathname);
+    void remove(bool recursive = false);
+    void makeDirectory(bool recursive = false);
+
+    void chown(uid_t uid, gid_t gid);
+    void chmod(mode_t mode);
+
+    std::string toString() const;
+
+    const std::string& getPath() const
+    {
+        return path.getPathname();
+    }
+
+private:
+    int descriptor;
+    Path path;
+};
+
+class DirectoryIterator {
+public:
+    DirectoryIterator();
+    DirectoryIterator(const std::string& dir);
+    DirectoryIterator(const Path& dir);
+
+    ~DirectoryIterator();
+
+    DirectoryIterator& operator=(const std::string& dir);
+    DirectoryIterator& operator=(const Path& dir);
+    DirectoryIterator& operator++();
+
+    bool operator==(const DirectoryIterator& iterator) const
+    {
+        return (current == iterator.current);
+    }
+
+    bool operator!=(const DirectoryIterator& iterator) const
+    {
+        return !(current == iterator.current);
+    }
+
+    const File& operator*() const
+    {
+        return current;
+    }
+
+    File& operator*()
+    {
+        return current;
+    }
+
+    const File* operator->() const
+    {
+        return &current;
+    }
+
+    File* operator->()
+    {
+        return &current;
+    }
+
+private:
+    void next();
+    void reset(const std::string& dir);
+
+    File current;
+    DIR* directoryHandle;
+    std::string basename;
+};
+
+class Mount final {
+public:
+    Mount() = delete;
+
+    static void mountEntry(const std::string& src, const std::string& dest,
+                           const std::string& type, const std::string& opts);
+};
+
+int Open(const std::string& path, int flags, mode_t mode);
+void Close(int fd);
+
+} // namespace runtime
+#endif //__RUNTIME_FILESYSTEM_H__
diff --git a/device_core/agent_lib/rmi/inc/mainloop.h b/device_core/agent_lib/rmi/inc/mainloop.h
new file mode 100644 (file)
index 0000000..7b9e752
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ *  Copyright (c) 2015 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
+ */
+
+#ifndef __RUNTIME_MAINLOOP_H__
+#define __RUNTIME_MAINLOOP_H__
+
+#include <sys/epoll.h>
+
+#include <string>
+#include <functional>
+#include <unordered_map>
+#include <memory>
+#include <mutex>
+#include <atomic>
+
+#include "eventfd.h"
+
+namespace runtime {
+
+class Mainloop {
+public:
+    typedef unsigned int Event;
+    typedef std::function<void(int fd, Event event)> Callback;
+
+    Mainloop();
+    ~Mainloop();
+
+    void addEventSource(const int fd, const Event events, Callback&& callback);
+    void removeEventSource(const int fd);
+    bool dispatch(const int timeout);
+    void run();
+    void stop();
+
+private:
+    typedef std::recursive_mutex Mutex;
+
+    std::unordered_map<int, std::shared_ptr<Callback>> callbacks;
+    Mutex mutex;
+    int pollFd;
+    std::atomic<bool> stopped;
+    runtime::EventFD wakeupSignal;
+};
+
+} // namespace runtime
+
+#endif //__RUNTIME_MAINLOOP_H__
diff --git a/device_core/agent_lib/rmi/inc/object-latch.h b/device_core/agent_lib/rmi/inc/object-latch.h
new file mode 100644 (file)
index 0000000..e3dcbae
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ *  Copyright (c) 2015 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
+ */
+
+#ifndef __RUNTIME_OBJECT_LATCH_H__
+#define __RUNTIME_OBJECT_LATCH_H__
+
+#include <utility>
+#include <mutex>
+#include <condition_variable>
+
+template<typename DataType>
+class ObjectLatch {
+public:
+    ObjectLatch() :
+        state(false)
+    {
+    }
+
+    ObjectLatch(const ObjectLatch&) = delete;
+    ObjectLatch& operator=(const ObjectLatch&) = delete;
+
+    void set(const DataType& val)
+    {
+        data = val;
+        state = true;
+        condition.notify_one();
+    }
+
+    void set(DataType&& val)
+    {
+        data  = std::move(val);
+        state = true;
+        condition.notify_one();
+    }
+
+    DataType get()
+    {
+        return DataType(std::move(data));
+    }
+
+    bool isValid() const
+    {
+        return state == true;
+    }
+
+    void wait()
+    {
+        std::unique_lock<std::mutex> lock(stateLock);
+        condition.wait(lock, [this]{
+            return isValid();
+        });
+    }
+
+private:
+    DataType data;
+    bool state;
+    std::mutex stateLock;
+    std::condition_variable condition;
+};
+
+#endif //__RUNTIME_OBJECT_LATCH_H__
diff --git a/device_core/agent_lib/rmi/inc/pam.h b/device_core/agent_lib/rmi/inc/pam.h
new file mode 100644 (file)
index 0000000..b6b6a33
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ *  Copyright (c) 2015 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
+ */
+
+#ifndef __RUNTIME_PAM_H__
+#define __RUNTIME_PAM_H__
+
+#include <string>
+#include <vector>
+#include <memory>
+
+#include <syslog.h>
+#include <security/pam_appl.h>
+
+namespace runtime {
+
+class PAM final {
+public:
+    PAM(PAM&&) = delete;
+    PAM(const PAM&) = delete;
+    PAM(const std::string& service, const std::string& user);
+    ~PAM();
+
+    PAM& operator=(const PAM&) = delete;
+    PAM& operator=(PAM &&) = delete;
+
+    void setData(const std::string &name, void* data, void (*cleanup)(pam_handle_t* pamh, void* data, int error));
+    const void* getData(const std::string &name) const;
+
+    void setItem(int item, void* data);
+    const void* getItem(int item) const;
+
+    const std::string getUser(const std::string &prompt = "") const;
+
+    void putEnv(const std::string &name_value);
+    const std::string getEnv(const std::string &name) const;
+    const std::vector<std::string> getEnvList() const;
+
+    void syslog(const std::string &log, int priority = LOG_ERR);
+
+    int authenticate(int flags);
+    int setCredential(int flags);
+    int accountManagement(int flags);
+    int changeAuthenticationToken(int flags);
+    void openSession(int flags);
+    void closeSession(int flags);
+
+private:
+    pam_handle_t* pamh;
+};
+
+} // namespace runtime
+#endif // __RUNTIME_PAM_H__
diff --git a/device_core/agent_lib/rmi/inc/preprocessor.h b/device_core/agent_lib/rmi/inc/preprocessor.h
new file mode 100644 (file)
index 0000000..ab653ba
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ *  Copyright (c) 2015 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
+ */
+
+#ifndef __RUNTIME_PREPROCESSOR_H__
+#define __RUNTIME_PREPROCESSOR_H__
+
+#define STRINGIFY_(x) #x
+#define STRINGIFY(x)  STRINGIFY_(x)
+
+#define CONCATENATE(arg1, arg2)   CONCATENATE1(arg1, arg2)
+#define CONCATENATE1(arg1, arg2)  CONCATENATE2(arg1, arg2)
+#define CONCATENATE2(arg1, arg2)  arg1##arg2
+
+#define VAR_ARGS_SIZE(...)     VAR_ARGS_SIZE_(__VA_ARGS__, FOR_EACH_VAR_ARGS_RSEQ_N())
+#define VAR_ARGS_SIZE_(...)    FOR_EACH_VAR_ARGS_ARG_N(__VA_ARGS__)
+
+#define FOR_EACH_VAR_ARGS_ARG_N(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, N, ...) N
+#define FOR_EACH_VAR_ARGS_RSEQ_N() 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
+
+#define FOR_EACH_VAR_ARGS_1(what, x, ...)  what(x)
+#define FOR_EACH_VAR_ARGS_2(what, x, ...)  what(x); FOR_EACH_VAR_ARGS_1(what, __VA_ARGS__)
+#define FOR_EACH_VAR_ARGS_3(what, x, ...)  what(x); FOR_EACH_VAR_ARGS_2(what, __VA_ARGS__)
+#define FOR_EACH_VAR_ARGS_4(what, x, ...)  what(x); FOR_EACH_VAR_ARGS_3(what, __VA_ARGS__)
+#define FOR_EACH_VAR_ARGS_5(what, x, ...)  what(x); FOR_EACH_VAR_ARGS_4(what, __VA_ARGS__)
+#define FOR_EACH_VAR_ARGS_6(what, x, ...)  what(x); FOR_EACH_VAR_ARGS_5(what, __VA_ARGS__)
+#define FOR_EACH_VAR_ARGS_7(what, x, ...)  what(x); FOR_EACH_VAR_ARGS_6(what, __VA_ARGS__)
+#define FOR_EACH_VAR_ARGS_8(what, x, ...)  what(x); FOR_EACH_VAR_ARGS_7(what, __VA_ARGS__)
+#define FOR_EACH_VAR_ARGS_9(what, x, ...)  what(x); FOR_EACH_VAR_ARGS_8(what, __VA_ARGS__)
+#define FOR_EACH_VAR_ARGS_10(what, x, ...) what(x); FOR_EACH_VAR_ARGS_9(what, __VA_ARGS__)
+#define FOR_EACH_VAR_ARGS_11(what, x, ...) what(x); FOR_EACH_VAR_ARGS_10(what, __VA_ARGS__)
+#define FOR_EACH_VAR_ARGS_12(what, x, ...) what(x); FOR_EACH_VAR_ARGS_11(what, __VA_ARGS__)
+#define FOR_EACH_VAR_ARGS_13(what, x, ...) what(x); FOR_EACH_VAR_ARGS_12(what, __VA_ARGS__)
+#define FOR_EACH_VAR_ARGS_14(what, x, ...) what(x); FOR_EACH_VAR_ARGS_13(what, __VA_ARGS__)
+#define FOR_EACH_VAR_ARGS_15(what, x, ...) what(x); FOR_EACH_VAR_ARGS_14(what, __VA_ARGS__)
+#define FOR_EACH_VAR_ARGS_16(what, x, ...) what(x); FOR_EACH_VAR_ARGS_15(what, __VA_ARGS__)
+#define FOR_EACH_VAR_ARGS_17(what, x, ...) what(x); FOR_EACH_VAR_ARGS_16(what, __VA_ARGS__)
+#define FOR_EACH_VAR_ARGS_18(what, x, ...) what(x); FOR_EACH_VAR_ARGS_17(what, __VA_ARGS__)
+#define FOR_EACH_VAR_ARGS_19(what, x, ...) what(x); FOR_EACH_VAR_ARGS_18(what, __VA_ARGS__)
+#define FOR_EACH_VAR_ARGS_20(what, x, ...) what(x); FOR_EACH_VAR_ARGS_19(what, __VA_ARGS__)
+#define FOR_EACH_VAR_ARGS_21(what, x, ...) what(x); FOR_EACH_VAR_ARGS_20(what, __VA_ARGS__)
+#define FOR_EACH_VAR_ARGS_22(what, x, ...) what(x); FOR_EACH_VAR_ARGS_21(what, __VA_ARGS__)
+#define FOR_EACH_VAR_ARGS_23(what, x, ...) what(x); FOR_EACH_VAR_ARGS_22(what, __VA_ARGS__)
+#define FOR_EACH_VAR_ARGS_24(what, x, ...) what(x); FOR_EACH_VAR_ARGS_23(what, __VA_ARGS__)
+#define FOR_EACH_VAR_ARGS_25(what, x, ...) what(x); FOR_EACH_VAR_ARGS_24(what, __VA_ARGS__)
+#define FOR_EACH_VAR_ARGS_26(what, x, ...) what(x); FOR_EACH_VAR_ARGS_25(what, __VA_ARGS__)
+#define FOR_EACH_VAR_ARGS_27(what, x, ...) what(x); FOR_EACH_VAR_ARGS_26(what, __VA_ARGS__)
+#define FOR_EACH_VAR_ARGS_28(what, x, ...) what(x); FOR_EACH_VAR_ARGS_27(what, __VA_ARGS__)
+#define FOR_EACH_VAR_ARGS_29(what, x, ...) what(x); FOR_EACH_VAR_ARGS_28(what, __VA_ARGS__)
+#define FOR_EACH_VAR_ARGS_30(what, x, ...) what(x); FOR_EACH_VAR_ARGS_29(what, __VA_ARGS__)
+#define FOR_EACH_VAR_ARGS_31(what, x, ...) what(x); FOR_EACH_VAR_ARGS_30(what, __VA_ARGS__)
+#define FOR_EACH_VAR_ARGS_32(what, x, ...) what(x); FOR_EACH_VAR_ARGS_31(what, __VA_ARGS__)
+
+#define FOR_EACH_VAR_ARGS_(N, what, ...)   CONCATENATE(FOR_EACH_VAR_ARGS_, N)(what, __VA_ARGS__)
+#define FOR_EACH_VAR_ARGS(what, ...)       FOR_EACH_VAR_ARGS_(VAR_ARGS_SIZE(__VA_ARGS__), what, __VA_ARGS__)
+
+#define SEQUENCE_1(how)  how(1)
+#define SEQUENCE_2(how)  SEQUENCE_1(how), how(2)
+#define SEQUENCE_3(how)  SEQUENCE_2(how), how(3)
+#define SEQUENCE_4(how)  SEQUENCE_3(how), how(4)
+#define SEQUENCE_5(how)  SEQUENCE_4(how), how(5)
+#define SEQUENCE_6(how)  SEQUENCE_5(how), how(6)
+#define SEQUENCE_7(how)  SEQUENCE_6(how), how(7)
+#define SEQUENCE_8(how)  SEQUENCE_7(how), how(8)
+#define SEQUENCE_9(how)  SEQUENCE_8(how), how(9)
+#define SEQUENCE_10(how) SEQUENCE_9(how), how(10)
+#define SEQUENCE_11(how) SEQUENCE_10(how), how(11)
+#define SEQUENCE_12(how) SEQUENCE_11(how), how(12)
+#define SEQUENCE_13(how) SEQUENCE_12(how), how(13)
+#define SEQUENCE_14(how) SEQUENCE_13(how), how(14)
+#define SEQUENCE_15(how) SEQUENCE_14(how), how(15)
+#define SEQUENCE_16(how) SEQUENCE_15(how), how(16)
+#define SEQUENCE_17(how) SEQUENCE_16(how), how(17)
+#define SEQUENCE_18(how) SEQUENCE_17(how), how(18)
+#define SEQUENCE_19(how) SEQUENCE_18(how), how(19)
+#define SEQUENCE_20(how) SEQUENCE_19(how), how(20)
+#define SEQUENCE_21(how) SEQUENCE_20(how), how(21)
+#define SEQUENCE_22(how) SEQUENCE_21(how), how(22)
+#define SEQUENCE_23(how) SEQUENCE_22(how), how(23)
+#define SEQUENCE_24(how) SEQUENCE_23(how), how(24)
+#define SEQUENCE_25(how) SEQUENCE_24(how), how(25)
+#define SEQUENCE_26(how) SEQUENCE_25(how), how(26)
+#define SEQUENCE_27(how) SEQUENCE_26(how), how(27)
+#define SEQUENCE_28(how) SEQUENCE_27(how), how(28)
+#define SEQUENCE_29(how) SEQUENCE_28(how), how(29)
+#define SEQUENCE_30(how) SEQUENCE_29(how), how(30)
+#define SEQUENCE_31(how) SEQUENCE_30(how), how(31)
+#define SEQUENCE_32(how) SEQUENCE_31(how), how(32)
+#define SEQUENCE(how, N) SEQUENCE_##N(how)
+
+#endif //!__RUNTIME_PREPROCESSOR_H__
diff --git a/device_core/agent_lib/rmi/inc/process.h b/device_core/agent_lib/rmi/inc/process.h
new file mode 100644 (file)
index 0000000..085ae14
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ *  Copyright (c) 2015 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
+ */
+
+#ifndef __RUNTIME_PROCESS_H__
+#define __RUNTIME_PROCESS_H__
+
+#include <string>
+#include <vector>
+
+namespace runtime {
+
+class Process {
+public:
+    typedef pid_t Pid;
+
+    Process(const std::string& prog);
+    Process(const std::string& prog, const std::vector<std::string>& args);
+    Process(const Process& proc);
+
+    ~Process();
+
+    Process& operator=(const Process& proc);
+
+    int execute();
+    int start();
+    int waitForFinished();
+    int waitForStarted();
+    void terminate();
+    void kill();
+
+    bool isRunning() const;
+
+private:
+    int status;
+    Pid pid;
+    std::string program;
+    std::vector<std::string> args;
+};
+
+} // namespace runtime
+#endif //__RUNTIME_PROCESS_H__
diff --git a/device_core/agent_lib/rmi/inc/reflection.h b/device_core/agent_lib/rmi/inc/reflection.h
new file mode 100644 (file)
index 0000000..26c6eeb
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ *  Copyright (c) 2015 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
+ */
+
+#ifndef __RUNTIME_REFLECTION_H__
+#define __RUNTIME_REFLECTION_H__
+
+#include <type_traits>
+
+#include "preprocessor.h"
+
+#define VISIT_ELEMENT(elem) v.visit(#elem, elem)
+
+#define REFLECTABLE(...)                               \
+template<typename V>                                   \
+void accept(V v)                                       \
+{                                                      \
+       FOR_EACH_VAR_ARGS(VISIT_ELEMENT, __VA_ARGS__);  \
+}                                                      \
+template<typename V>                                   \
+void accept(V v) const                                 \
+{                                                      \
+       FOR_EACH_VAR_ARGS(VISIT_ELEMENT, __VA_ARGS__);  \
+}
+
+#define NO_REFLECTABLE_PROPERTY                                \
+       template<typename V>                            \
+       static void accept(V) {}
+
+template<typename T>
+struct ReflectionTraitChecker {
+    struct Visitor {};
+
+    template <typename C> static std::true_type
+    test(decltype(std::declval<C>().template accept(Visitor()))*);
+
+    template <typename C> static std::false_type
+    test(...);
+
+    static constexpr bool value = std::is_same<decltype(test<T>(0)), std::true_type>::value;
+};
+
+template<typename T>
+struct IsReflectable : public std::integral_constant<bool, ReflectionTraitChecker<T>::value> {};
+
+#endif //!__RUNTIME_REFLECTION_H__
diff --git a/device_core/agent_lib/rmi/inc/rmi/callback-holder.h b/device_core/agent_lib/rmi/inc/rmi/callback-holder.h
new file mode 100644 (file)
index 0000000..f8def62
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ *  Copyright (c) 2015 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
+ */
+
+#ifndef __RMI_CALLBACK_HOLDER_H__
+#define __RMI_CALLBACK_HOLDER_H__
+
+#include <utility>
+#include <functional>
+
+#include "message.h"
+
+namespace rmi {
+
+template<typename Type, typename... Args>
+struct MethodHandler {
+    typedef std::function<Type(Args&...)> type;
+};
+// using MethodHandler = std::function<Type(Args&...)>;
+
+template<typename Type, typename... Args>
+struct CallbackHolder {
+    template<int...>
+    struct Sequence {};
+
+    template<int N, int... S>
+    struct SequenceExpansion : SequenceExpansion<N-1, N-1, S...> {};
+
+    template<int... S>
+    struct SequenceExpansion<0, S...> {
+        typedef Sequence<S...> type;
+    };
+
+    std::tuple<Args...> parameters;
+    const typename MethodHandler<Type, Args...>::type& callback;
+
+    CallbackHolder(const typename MethodHandler<Type, Args...>::type& m) :
+        callback(m)
+    {
+    }
+
+    Type dispatch(Message& message)
+    {
+        return callCallback(message, typename SequenceExpansion<sizeof...(Args)>::type());
+    }
+
+    template<typename...R>
+    Type callCallback(Message& message, R&... args)
+    {
+        message.unpackParameters(args...);
+        return callback(args...);
+    }
+
+    template<int... S>
+    Type callCallback(Message& message, Sequence<S...>)
+    {
+        return callCallback(message, std::get<S>(parameters)...);
+    }
+};
+
+} // namespace rmi
+#endif //!__RMI_CALLBACK_HOLDER_H__
diff --git a/device_core/agent_lib/rmi/inc/rmi/client.h b/device_core/agent_lib/rmi/inc/rmi/client.h
new file mode 100644 (file)
index 0000000..2adbcd1
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ *  Copyright (c) 2015 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
+ */
+
+#ifndef __RMI_CLIENT_H__
+#define __RMI_CLIENT_H__
+
+#include <thread>
+#include <string>
+#include <memory>
+
+#include "error.h"
+#include "message.h"
+#include "connection.h"
+#include "mainloop.h"
+#include "callback-holder.h"
+
+namespace rmi {
+
+class Client {
+public:
+    Client(const std::string& address);
+    ~Client();
+
+    Client(const Client&) = delete;
+    Client& operator=(const Client&) = delete;
+
+    void connect();
+    void disconnect();
+
+    int subscribe(const std::string& provider, const std::string& name);
+
+    template<typename... Args>
+    int subscribe(const std::string& provider, const std::string& name,
+                  const typename MethodHandler<void, Args...>::type& handler);
+
+    int unsubscribe(const std::string& provider, int handle);
+
+    template<typename Type, typename... Args>
+    Type methodCall(const std::string& method, Args&&... args);
+
+private:
+    std::string address;
+    std::shared_ptr<Connection> connection;
+    runtime::Mainloop mainloop;
+    std::thread dispatcher;
+};
+
+template<typename... Args>
+int Client::subscribe(const std::string& provider, const std::string& name,
+                      const typename MethodHandler<void, Args...>::type& handler)
+{
+    int id = subscribe(provider, name);
+    if (id < 0) {
+        return -1;
+    }
+
+    std::shared_ptr<Socket> transport = std::make_shared<Socket>(id);
+
+    auto callback = [handler, transport, this](int fd, runtime::Mainloop::Event event) {
+        if ((event & EPOLLHUP) || (event & EPOLLRDHUP)) {
+            mainloop.removeEventSource(fd);
+            return;
+        }
+
+        try {
+            Message msg;
+            msg.decode(*transport);
+
+            CallbackHolder<void, Args...> callback(handler);
+            callback.dispatch(msg);
+        } catch (std::exception& e) {
+            std::cout << e.what() << std::endl;
+        }
+    };
+
+    mainloop.addEventSource(id, EPOLLIN | EPOLLHUP | EPOLLRDHUP, callback);
+
+    return id;
+}
+
+template<typename Type, typename... Args>
+Type Client::methodCall(const std::string& method, Args&&... args)
+{
+    Message request = connection->createMessage(Message::MethodCall, method);
+    request.packParameters(std::forward<Args>(args)...);
+    connection->send(request);
+
+    Message reply = connection->dispatch();
+
+    Type response;
+    reply.disclose<Type>(response);
+
+    return response;
+}
+
+} // namespace rmi
+#endif //__RMI_CLIENT_H__
diff --git a/device_core/agent_lib/rmi/inc/rmi/connection.h b/device_core/agent_lib/rmi/inc/rmi/connection.h
new file mode 100644 (file)
index 0000000..5728f5f
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ *  Copyright (c) 2015 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
+ */
+
+#ifndef __RMI_CONNECTION_H__
+#define __RMI_CONNECTION_H__
+
+#include <string>
+#include <mutex>
+
+#include "socket.h"
+#include "serialize.h"
+#include "message.h"
+
+namespace rmi {
+
+class Connection {
+public:
+    Connection(Socket&& sock);
+    Connection(const Connection&) = delete;
+    ~Connection() noexcept;
+
+    Connection& operator=(const Connection&) = delete;
+    Connection& operator=(Connection&) = delete;
+
+    Message createMessage(unsigned int type, const std::string& target);
+
+    void send(const Message& message) const;
+    Message dispatch() const;
+
+    int getFd() const
+    {
+        return socket.getFd();
+    }
+
+    Credentials getPeerCredentials() const
+    {
+        return socket.getPeerCredentials();
+    }
+
+private:
+    Socket socket;
+    mutable std::mutex receiveMutex;
+    mutable std::mutex transmitMutex;
+};
+
+} // namespace rmi
+#endif //__RMI_CONNECTION_H__
diff --git a/device_core/agent_lib/rmi/inc/rmi/message-composer.h b/device_core/agent_lib/rmi/inc/rmi/message-composer.h
new file mode 100644 (file)
index 0000000..f197d3a
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+
+#ifndef __RMI_MESSAGE_COMPOSER_H__
+#define __RMI_MESSAGE_COMPOSER_H__
+
+#include <cstring>
+#include <iostream>
+#include <string>
+#include <memory>
+
+namespace rmi {
+
+class MessageComposer {
+public:
+    MessageComposer(size_t caps = 1024);
+    MessageComposer(const MessageComposer& rhs);
+    MessageComposer(MessageComposer&& rhs);
+
+    ~MessageComposer();
+
+    MessageComposer& operator=(const MessageComposer& rhs);
+    MessageComposer& operator=(MessageComposer&& rhs);
+
+    void write(const void* ptr, const size_t sz);
+    void read(void* ptr, const size_t sz);
+    void insure(size_t sz);
+
+    void reserve(size_t size)
+    {
+        produce = size;
+    }
+
+    void reset()
+    {
+        produce = consume = 0;
+    }
+
+    char* begin() const
+    {
+        return buffer + consume;
+    }
+
+    char* end() const
+    {
+        return buffer + produce;
+    }
+
+    size_t size() const
+    {
+        return (end() - begin());
+    }
+
+private:
+    size_t capacity;
+    size_t produce;
+    size_t consume;
+    char *buffer;
+};
+
+} // namespae rmi
+#endif //__RMI_MESSAGE_COMPOSER_H__
diff --git a/device_core/agent_lib/rmi/inc/rmi/message.h b/device_core/agent_lib/rmi/inc/rmi/message.h
new file mode 100644 (file)
index 0000000..7d1f8b4
--- /dev/null
@@ -0,0 +1,245 @@
+/*
+ *  Copyright (c) 2015 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
+ */
+
+#ifndef __RMI_MESSAGE_H__
+#define __RMI_MESSAGE_H__
+
+#include <cstring>
+#include <iostream>
+#include <string>
+#include <memory>
+#include <atomic>
+#include <deque>
+
+#include "message-composer.h"
+
+#include "reflection.h"
+#include "serialize.h"
+#include "file-descriptor.h"
+
+namespace rmi {
+
+class Message {
+public:
+    enum Type {
+        Invalid,
+        MethodCall,
+        Reply,
+        Error,
+        Signal
+    };
+
+    Message();
+    Message(unsigned int id, unsigned int type, const std::string&);
+    Message(unsigned int type, const std::string&);
+    Message(const Message& rhs);
+    Message(Message&& rhs);
+
+    ~Message();
+
+    Message& operator=(const Message& rhs);
+    Message& operator=(Message&& rhs);
+
+    // [TBD] Take arguments
+    Message createReplyMessage() const;
+    Message createErrorMessage() const;
+
+    unsigned int id() const
+    {
+        return signature.id;
+    }
+
+    unsigned int type() const
+    {
+        return signature.type;
+    }
+
+    const std::string& target() const
+    {
+        return signature.target;
+    }
+
+    bool isInvalid() const
+    {
+        return type() == Invalid;
+    }
+
+    bool isError() const
+    {
+        return type() == Error;
+    }
+
+    bool isMethodCall() const
+    {
+        return type() == MethodCall;
+    }
+
+    bool isSignal() const
+    {
+        return type() == Signal;
+    }
+
+    bool isReply() const
+    {
+        return type() == Reply;
+    }
+
+    template<typename T>
+    void encode(const T& device) const;
+
+    template<typename T>
+    void decode(const T& device);
+
+    void packParameters()
+    {
+    }
+
+    template<typename F>
+    void packParameters(F&& arg);
+
+    template<typename F, typename...R>
+    void packParameters(F&& first, R&&... rest);
+
+    void unpackParameters()
+    {
+    }
+
+    template<typename F>
+    void unpackParameters(F& arg);
+
+    template<typename F, typename... R>
+    void unpackParameters(F& first, R&... rest);
+
+    template<typename DataType>
+    void enclose(DataType&& data);
+
+    template<typename DataType>
+    void disclose(DataType& data);
+
+private:
+    struct MessageHeader {
+        unsigned int id;    // Unique message id
+        unsigned int type;  // Mesage type
+        size_t length;// Total message length except MessageHeader itself
+        size_t ancillary;
+    };
+
+    struct MessageSignature {
+        unsigned int id;
+        unsigned int type;
+        std::string target;
+
+        REFLECTABLE(
+            id,
+            type,
+            target
+        )
+    };
+
+    MessageSignature signature;
+    MessageComposer buffer;
+    std::deque<FileDescriptor> fileDescriptors;
+
+    static std::atomic<unsigned int> sequence;
+};
+
+template<typename F>
+void Message::packParameters(F&& arg)
+{
+    enclose<F>(std::forward<F>(arg));
+}
+
+template<typename F, typename...R>
+void Message::packParameters(F&& first, R&&... rest)
+{
+    packParameters(std::forward<F>(first));
+    packParameters(std::forward<R>(rest)...);
+}
+
+template<typename F>
+void Message::unpackParameters(F& arg)
+{
+    disclose<F>(arg);
+}
+
+template<typename F, typename... R>
+void Message::unpackParameters(F& first, R&... rest)
+{
+    unpackParameters(first);
+    unpackParameters(rest...);
+}
+
+template<typename DataType>
+void Message::enclose(DataType&& data)
+{
+    runtime::Serializer<MessageComposer> serializer(buffer);
+    runtime::SerializableArgument<DataType> arg(std::forward<DataType>(data));
+    arg.accept(serializer);
+}
+
+template<typename DataType>
+void Message::disclose(DataType& data)
+{
+    runtime::Deserializer<MessageComposer> deserializer(buffer);
+    runtime::DeserializableArgument<DataType> arg(data);
+    arg.accept(deserializer);
+}
+
+template<typename T>
+void Message::encode(const T& device) const
+{
+    MessageHeader header = {
+        signature.id,
+        signature.type,
+        buffer.size(),
+        fileDescriptors.size()
+    };
+
+    device.write(&header, sizeof(header));
+    device.write(buffer.begin(), header.length);
+
+    int i = 0, fds[fileDescriptors.size()];
+    for (const FileDescriptor& fd : fileDescriptors) {
+        fds[i++] = fd.fileDescriptor;
+    }
+
+    device.sendFileDescriptors(fds, fileDescriptors.size());
+}
+
+template<typename T>
+void Message::decode(const T& device)
+{
+    MessageHeader header;
+    device.read(&header, sizeof(header));
+    buffer.insure(header.length);
+    device.read(buffer.begin(), header.length);
+    buffer.reserve(header.length);
+
+    int fds[header.ancillary];
+
+    device.receiveFileDescriptors(fds, header.ancillary);
+    for (unsigned int i = 0; i < header.ancillary; i++) {
+        fileDescriptors.emplace_back(FileDescriptor(fds[i]));
+    }
+
+    disclose(signature);
+}
+
+template<> void Message::enclose(FileDescriptor&& fd);
+template<> void Message::disclose(FileDescriptor& fd);
+
+} // namespae rmi
+#endif //__RMI_MESSAGE_H__
diff --git a/device_core/agent_lib/rmi/inc/rmi/notification.h b/device_core/agent_lib/rmi/inc/rmi/notification.h
new file mode 100644 (file)
index 0000000..2be4074
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ *  Copyright (c) 2015 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
+ */
+
+#ifndef __RMI_NOTIFICATION_H__
+#define __RMI_NOTIFICATION_H__
+
+#include <string>
+#include <vector>
+#include <mutex>
+#include <unordered_map>
+#include <utility>
+#include <memory>
+
+#include "socket.h"
+#include "message.h"
+//#include "audit/logger.h"
+
+namespace rmi {
+
+typedef std::pair<int, int> SubscriptionId;
+
+class Notification {
+public:
+    Notification();
+       Notification(const std::string& name);
+    Notification(const Notification&) = default;
+    Notification(Notification&&);
+
+    SubscriptionId createSubscriber();
+    int removeSubscriber(const int id);
+
+       template<typename... Args>
+       void notify(Args&&... args);
+
+private:
+       std::string signalName;
+       std::vector<std::shared_ptr<Socket>> subscribers;
+    std::mutex subscriberLock;
+};
+
+template<typename... Args>
+void Notification::notify(Args&&... args)
+{
+       Message msg(Message::Signal, signalName);
+       msg.packParameters(std::forward<Args>(args)...);
+
+    std::lock_guard<std::mutex> lock(subscriberLock);
+
+    for (std::shared_ptr<Socket>& subscriber : subscribers) {
+        try {
+            msg.encode(*subscriber);
+        } catch (runtime::Exception& e) {
+           //FIXME! switch to dlog
+            //ERROR(e.what());
+        }
+    }
+}
+
+} // namespae rmi
+#endif //__RMI_NOTIFICATION_H__
diff --git a/device_core/agent_lib/rmi/inc/rmi/service.h b/device_core/agent_lib/rmi/inc/rmi/service.h
new file mode 100644 (file)
index 0000000..4ebbeda
--- /dev/null
@@ -0,0 +1,177 @@
+/*
+ *  Copyright (c) 2015 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
+ */
+
+#ifndef __RMI_SERVICE_H__
+#define __RMI_SERVICE_H__
+
+#include <mutex>
+#include <string>
+#include <functional>
+#include <memory>
+#include <vector>
+#include <unordered_map>
+#include <thread>
+
+#include "preprocessor.h"
+#include "thread-pool.h"
+#include "mainloop.h"
+#include "connection.h"
+#include "message.h"
+#include "callback-holder.h"
+#include "notification.h"
+
+#define STRIP_(...)
+#define STRIP(x)         STRIP_ x
+
+#define TYPEOF____(...)   __VA_ARGS__
+#define TYPEOF___(...)   (__VA_ARGS__),
+#define TYPEOF__(x, ...) TYPEOF____ x
+#define TYPEOF_(...)     TYPEOF__(__VA_ARGS__)
+#define TYPEOF(x)        TYPEOF_(TYPEOF___ x, )
+
+#define PLACEHOLDER(n)   std::placeholders::_##n
+
+#define PROTOTYPE_(D, N) SEQUENCE(D, N)
+#define PROTOTYPE(...)   PROTOTYPE_(PLACEHOLDER, VAR_ARGS_SIZE(__VA_ARGS__))
+
+#define registerMethod(T, M, ...)                                             \
+setMethodHandler<TYPEOF(M), TYPEOF(STRIP(STRIP(M)))>                          \
+                (STRINGIFY(TYPEOF(STRIP(M))), std::bind(&TYPEOF(STRIP(M)), T, \
+                PROTOTYPE(TYPEOF(STRIP(STRIP(M))))))
+
+#define registerParametricMethod(T, M, ...)                                   \
+setMethodHandler<TYPEOF(M), TYPEOF(STRIP(STRIP(M)))>                          \
+                (STRINGIFY(TYPEOF(STRIP(M))), std::bind(&TYPEOF(STRIP(M)), T, \
+                PROTOTYPE(TYPEOF(STRIP(STRIP(M))))))
+
+#define registerNonparametricMethod(T, M, ...)                                \
+setMethodHandler<TYPEOF(M)>                                                   \
+                (STRINGIFY(TYPEOF(STRIP(M))), std::bind(&TYPEOF(STRIP(M)), T))
+
+namespace rmi {
+
+typedef std::function<bool(const Connection& connection)> ConnectionCallback;
+
+class Service {
+public:
+    Service(const std::string& address);
+    ~Service();
+
+    Service(const Service&) = delete;
+    Service& operator=(const Service&) = delete;
+
+    void start();
+    void stop();
+
+    void setNewConnectionCallback(const ConnectionCallback& callback);
+    void setCloseConnectionCallback(const ConnectionCallback& callback);
+
+    template<typename Type, typename... Args>
+    void setMethodHandler(const std::string& method,
+                          const typename MethodHandler<Type, Args...>::type& handler);
+
+    void createNotification(const std::string& name);
+    int subscribeNotification(const std::string& name);
+    int unsubscribeNotification(const std::string& name, const int id);
+
+       template <typename... Args>
+       void notify(const std::string& name, Args&&... args);
+
+    pid_t getPeerPid() const
+    {
+        return processingContext.credentials.pid;
+    }
+
+    uid_t getPeerUid() const
+    {
+        return processingContext.credentials.uid;
+    }
+
+    gid_t getPeerGid() const
+    {
+        return processingContext.credentials.gid;
+    }
+
+private:
+    struct ProcessingContext {
+        ProcessingContext() = default;
+        ProcessingContext(const std::shared_ptr<Connection>& connection) :
+            credentials(connection->getPeerCredentials())
+        {
+        }
+
+        Credentials credentials;
+    };
+
+    typedef std::vector<std::shared_ptr<Connection>> ConnectionRegistry;
+    typedef std::function<void(const std::shared_ptr<Connection>& connection)> CallbackDispatcher;
+
+    typedef std::function<Message(Message& message)> MethodDispatcher;
+    typedef std::unordered_map<std::string, std::shared_ptr<MethodDispatcher>> MethodRegistry;
+    typedef std::unordered_map<std::string, Notification> NotificationRegistry;
+
+    void onMessageProcess(const std::shared_ptr<Connection>& connection);
+
+    ConnectionRegistry::iterator getConnectionIterator(const int id);
+
+    CallbackDispatcher onNewConnection;
+    CallbackDispatcher onCloseConnection;
+
+    MethodRegistry methodRegistry;
+    NotificationRegistry notificationRegistry;
+    ConnectionRegistry connectionRegistry;
+
+    runtime::Mainloop mainloop;
+    std::string address;
+
+    runtime::ThreadPool workqueue;
+    std::mutex stateLock;
+    std::mutex notificationLock;
+
+    static thread_local ProcessingContext processingContext;
+};
+
+template<typename Type, typename... Args>
+void Service::setMethodHandler(const std::string& method,
+                               const typename MethodHandler<Type, Args...>::type& handler)
+{
+    auto dispatchMethod = [handler](Message& message) {
+        CallbackHolder<Type, Args...> callback(handler);
+        Message reply = message.createReplyMessage();
+        reply.packParameters<Type>(callback.dispatch(message));
+
+        return reply;
+    };
+
+    std::lock_guard<std::mutex> lock(stateLock);
+
+    if (methodRegistry.count(method)) {
+        throw runtime::Exception("Method handler already registered");
+    }
+
+    methodRegistry[method] = std::make_shared<MethodDispatcher>(std::move(dispatchMethod));
+}
+
+template <typename... Args>
+void Service::notify(const std::string& name, Args&&... args)
+{
+    Notification& slot = notificationRegistry[name];
+    slot.notify(name, std::forward<Args>(args)...);
+}
+
+} // namespace rmi
+
+#endif //__RMI_SERVICE_H__
diff --git a/device_core/agent_lib/rmi/inc/rmi/socket.h b/device_core/agent_lib/rmi/inc/rmi/socket.h
new file mode 100644 (file)
index 0000000..015b6dd
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ *  Copyright (c) 2015 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
+ */
+
+#ifndef __RMI_SOCKET_H__
+#define __RMI_SOCKET_H__
+
+#include "exception.h"
+
+namespace rmi {
+
+class SocketException: public runtime::Exception {
+public:
+    SocketException(const std::string& msg) : runtime::Exception(msg) {}
+};
+
+struct Credentials {
+    pid_t pid;
+    uid_t uid;
+    gid_t gid;
+};
+
+class Socket {
+public:
+    explicit Socket(int socketFd = -1, bool autoclose = true);
+    Socket(Socket&& socket) noexcept;
+    ~Socket() noexcept;
+
+    Socket(const Socket&) = delete;
+    Socket& operator=(const Socket&) = delete;
+    Socket& operator=(Socket&) = delete;
+
+    Socket accept();
+    int getFd() const;
+    Credentials getPeerCredentials() const;
+
+    void write(const void* buffer, const size_t size) const;
+    void read(void* buffer, const size_t size) const;
+
+    void sendFileDescriptors(const int* fds, const size_t nr) const;
+    void receiveFileDescriptors(int* fds, const size_t nr) const;
+
+    static Socket create(const std::string& path);
+    static Socket connect(const std::string& path);
+
+private:
+    static int createRegularSocket(const std::string& path);
+
+#ifdef USE_SYSTEMD_SOCKET_ACTIVATION
+    static int createSystemdSocket(const std::string& path);
+#endif
+
+private:
+    int socketFd;
+    bool autoClose;
+};
+
+} // namespace rmi
+#endif //__RMI_SOCKET_H__
diff --git a/device_core/agent_lib/rmi/inc/serialize.h b/device_core/agent_lib/rmi/inc/serialize.h
new file mode 100644 (file)
index 0000000..21aaae9
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+ *  Copyright (c) 2015 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
+ */
+
+#ifndef __RUNTIME_SERIALIZER_H__
+#define __RUNTIME_SERIALIZER_H__
+
+#include <vector>
+#include <string>
+#include <utility>
+
+#include "reflection.h"
+
+namespace runtime {
+
+template<typename T>
+struct SerializableArgument {
+    SerializableArgument(const T& arg) : value(arg) {}
+
+    const T& value;
+    REFLECTABLE(value)
+};
+
+template<typename T>
+struct DeserializableArgument {
+    DeserializableArgument(T& arg) : value(arg) {}
+
+    T& value;
+    REFLECTABLE(value)
+};
+
+template<class StorageType>
+class Serializer {
+public:
+    Serializer(StorageType& source) :
+        storage(source)
+    {
+    }
+
+    template<typename DataType>
+    void visit(const std::string&, const DataType& value)
+    {
+        visitInternal(value);
+    }
+
+private:
+    void visitInternal(const std::string& value)
+    {
+        visitInternal(value.size());
+        storage.write(value.c_str(), value.size());
+    }
+
+    template<typename DataType, typename std::enable_if<std::is_arithmetic<DataType>::value, int>::type = 0>
+    void visitInternal(const DataType& value)
+    {
+        storage.write(&value, sizeof(DataType));
+    }
+
+    template<typename DataType, typename std::enable_if<::IsReflectable<DataType>::value, int>::type = 0>
+    void visitInternal(DataType& value)
+    {
+        value.accept(*this);
+    }
+
+    template<typename DataType>
+    void visitInternal(const std::vector<DataType>& values)
+    {
+        visitInternal(values.size());
+        for (const DataType& value : values) {
+            visitInternal(value);
+        }
+    }
+
+private:
+    StorageType& storage;
+};
+
+template<class StorageType>
+class Deserializer {
+public:
+    Deserializer(StorageType& source) :
+        storage(source)
+    {
+    }
+
+    template<typename DataType>
+    void visit(const std::string&, DataType& value)
+    {
+        visitInternal(value);
+    }
+
+private:
+    void visitInternal(std::string& value)
+    {
+        size_t size;
+        visitInternal(size);
+        value.resize(size);
+        storage.read(&value.front(), size);
+    }
+
+    template<typename DataType, typename std::enable_if<std::is_arithmetic<DataType>::value, int>::type = 0>
+    void visitInternal(DataType& value)
+    {
+        storage.read(&value, sizeof(DataType));
+    }
+
+    template<typename T, typename std::enable_if<::IsReflectable<T>::value, int>::type = 0>
+    void visitInternal(T& value)
+    {
+        value.accept(*this);
+    }
+
+    template<typename DataType>
+    void visitInternal(std::vector<DataType>& values)
+    {
+        size_t size;
+        visitInternal(size);
+        values.resize(size);
+
+        for (DataType& value : values) {
+            visitInternal(value);
+        }
+    }
+
+private:
+    StorageType& storage;
+};
+
+} // namespace runtime
+
+#endif //__RUNTIME_SERIALIZER_H__
diff --git a/device_core/agent_lib/rmi/inc/smack.h b/device_core/agent_lib/rmi/inc/smack.h
new file mode 100644 (file)
index 0000000..9f13648
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ *  Copyright (c) 2015 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
+ */
+
+#ifndef __RUNTIME_SMACK_H__
+#define __RUNTIME_SMACK_H__
+
+#include <string>
+
+#include "filesystem.h"
+
+namespace runtime {
+
+class Smack final {
+public:
+    Smack() = delete;
+    Smack(const Smack&) = delete;
+    Smack(Smack&&) = delete;
+
+    Smack& operator=(const Smack&) = delete;
+    Smack& operator=(Smack&&) = delete;
+
+    static void setAccess(File& file, const std::string& label);
+    static void setExecute(File& file, const std::string& label);
+    static void setMmap(File& file, const std::string& label);
+    static void setTransmute(File& file, const bool enable);
+
+    static std::string getAccess(File& file);
+    static std::string getExecute(File& file);
+    static std::string getMmap(File& file);
+    static bool getTransmute(File& file);
+
+
+private:
+    static void set(File& file, const char* xattr, const std::string& label);
+    static std::string get(File& file, const char* xattr);
+};
+
+} // namespace runtime
+#endif //__RUNTIME_SMACK_H__
diff --git a/device_core/agent_lib/rmi/inc/thread-pool.h b/device_core/agent_lib/rmi/inc/thread-pool.h
new file mode 100644 (file)
index 0000000..4677f61
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ *  Copyright (c) 2015 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
+ */
+
+#ifndef __RUNTIME_THREAD_POOL_H__
+#define __RUNTIME_THREAD_POOL_H__
+
+#include <thread>
+#include <mutex>
+#include <condition_variable>
+#include <functional>
+#include <vector>
+#include <deque>
+
+namespace runtime {
+
+class ThreadPool {
+public:
+    ThreadPool(size_t threads);
+    ~ThreadPool();
+
+    void submit(std::function<void()>&& task);
+
+private:
+    std::vector<std::thread> workers;
+    std::deque<std::function<void()>> tasks;
+
+    std::mutex queueMutex;
+    std::condition_variable condition;
+    bool stop;
+};
+
+} // namespace runtime
+
+#endif //__RUNTIME_THREAD_POOL_H__
+
diff --git a/device_core/agent_lib/rmi/src/error.cpp b/device_core/agent_lib/rmi/src/error.cpp
new file mode 100644 (file)
index 0000000..f3c330d
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ *  Copyright (c) 2015 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 <string>
+#include <cstring>
+#include <cerrno>
+
+#include "error.h"
+
+namespace runtime {
+
+int Error::lastErrorCode()
+{
+    return errno;
+}
+
+std::string Error::message(int errorCode)
+{
+    char errmsg[256];
+    return ::strerror_r(errorCode, errmsg, sizeof(errmsg));
+}
+
+std::string Error::message()
+{
+    return message(errno);
+}
+
+std::string GetSystemErrorMessage(int errorCode)
+{
+    return Error::message(errorCode);
+}
+
+std::string GetSystemErrorMessage()
+{
+    return GetSystemErrorMessage(errno);
+}
+
+} // namespace runtime
diff --git a/device_core/agent_lib/rmi/src/eventfd.cpp b/device_core/agent_lib/rmi/src/eventfd.cpp
new file mode 100644 (file)
index 0000000..0ecc9f4
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2015 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 <sys/types.h>
+#include <unistd.h>
+
+#include <cstdint>
+
+#include "eventfd.h"
+#include "error.h"
+#include "exception.h"
+
+namespace runtime {
+
+EventFD::EventFD(unsigned int initval, int flags)
+{
+    fd = ::eventfd(initval, flags);
+    if (fd == -1) {
+        throw runtime::Exception(runtime::GetSystemErrorMessage());
+    }
+}
+
+EventFD::~EventFD()
+{
+    if (fd != -1) {
+        ::close(fd);
+    }
+}
+
+void EventFD::send()
+{
+    const std::uint64_t val = 1;
+    if (::write(fd, &val, sizeof(val)) == -1) {
+        throw runtime::Exception(runtime::GetSystemErrorMessage());
+    }
+}
+
+void EventFD::receive()
+{
+    std::uint64_t val;
+    if (::read(fd, &val, sizeof(val)) == -1) {
+        throw runtime::Exception(runtime::GetSystemErrorMessage());
+    }
+}
+
+} // namespace runtime
diff --git a/device_core/agent_lib/rmi/src/filesystem.cpp b/device_core/agent_lib/rmi/src/filesystem.cpp
new file mode 100644 (file)
index 0000000..d27ed50
--- /dev/null
@@ -0,0 +1,492 @@
+/*
+ *  Copyright (c) 2015 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 <sys/types.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <string.h>
+
+#include <string>
+#include <sstream>
+
+#include "filesystem.h"
+#include "error.h"
+#include "exception.h"
+
+namespace runtime {
+
+Path::Path()
+{
+}
+
+Path::Path(const std::string& path)
+{
+    assign(path);
+}
+
+Path::Path(const char* path)
+{
+    assign(path);
+}
+
+Path::Path(const Path& path)
+    : pathname(path.pathname)
+{
+}
+
+Path::~Path()
+{
+}
+
+Path& Path::assign(const Path& path)
+{
+    if (&path != this) {
+        pathname = path.pathname;
+    }
+
+    return *this;
+}
+
+Path& Path::assign(const std::string& path)
+{
+    pathname = path;
+
+    return *this;
+}
+
+Path& Path::assign(const char* path)
+{
+    return assign(std::string(path));
+}
+
+Path& Path::operator=(const Path& path)
+{
+    return assign(path);
+}
+
+Path& Path::operator=(const std::string& path)
+{
+    return assign(path);
+}
+
+Path& Path::operator=(const char* path)
+{
+    return assign(path);
+}
+
+File::File()
+    : descriptor(-1)
+{
+}
+
+File::File(const std::string& pathname)
+    : descriptor(-1), path(pathname)
+{
+}
+
+File::File(const Path& filePath)
+    : descriptor(-1), path(filePath)
+{
+}
+
+File::File(const File& file)
+    : File(file.getPath())
+{
+}
+
+File::~File()
+{
+    if (descriptor != -1) {
+        close();
+    }
+}
+
+bool File::exists() const
+{
+    struct stat st;
+    return (::stat(path.getPathname().c_str(), &st) == 0);
+}
+
+bool File::canRead() const
+{
+    struct stat st;
+    if (::stat(path.getPathname().c_str(), &st) != 0) {
+        throw runtime::Exception(runtime::GetSystemErrorMessage());
+    }
+
+    if (st.st_uid == geteuid()) {
+        return ((st.st_mode & S_IRUSR) != 0);
+    } else if (st.st_gid == getegid()) {
+        return ((st.st_mode & S_IRGRP) != 0);
+    }
+
+    return (((st.st_mode & S_IROTH) != 0) || (geteuid() == 0));
+}
+
+bool File::canWrite() const
+{
+    struct stat st;
+    if (::stat(path.getPathname().c_str(), &st) != 0) {
+        throw runtime::Exception(runtime::GetSystemErrorMessage());
+    }
+
+    if (st.st_uid == geteuid()) {
+        return ((st.st_mode & S_IWUSR) != 0);
+    } else if (st.st_gid == getegid()) {
+        return ((st.st_mode & S_IWGRP) != 0);
+    }
+
+    return (((st.st_mode & S_IWOTH) != 0) || (geteuid() == 0));
+}
+
+bool File::canExecute() const
+{
+    struct stat st;
+    if (::stat(path.getPathname().c_str(), &st) != 0) {
+        throw runtime::Exception(runtime::GetSystemErrorMessage());
+    }
+
+    if (st.st_uid == geteuid()) {
+        return ((st.st_mode & S_IXUSR) != 0);
+    } else if (st.st_gid == getegid()) {
+        return ((st.st_mode & S_IXGRP) != 0);
+    }
+
+    return ((st.st_mode & S_IXOTH) != 0);
+}
+
+bool File::isLink() const
+{
+    struct stat st;
+    if (::stat(path.getPathname().c_str(), &st) != 0) {
+        throw runtime::Exception(runtime::GetSystemErrorMessage());
+    }
+
+    return S_ISLNK(st.st_mode);
+}
+
+bool File::isFile() const
+{
+    struct stat st;
+    if (::stat(path.getPathname().c_str(), &st) != 0) {
+        throw runtime::Exception(runtime::GetSystemErrorMessage());
+    }
+
+    return S_ISREG(st.st_mode);
+}
+
+bool File::isDirectory() const
+{
+    struct stat st;
+    if (::stat(path.getPathname().c_str(), &st) != 0) {
+        throw runtime::Exception(runtime::GetSystemErrorMessage());
+    }
+
+    return S_ISDIR(st.st_mode);
+}
+
+bool File::isDevice() const
+{
+    struct stat st;
+    if (::stat(path.getPathname().c_str(), &st) != 0) {
+        throw runtime::Exception(runtime::GetSystemErrorMessage());
+    }
+
+    return (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode));
+}
+
+bool File::isHidden() const
+{
+    return false;
+}
+
+std::string File::toString() const
+{
+    struct stat st;
+    if (::stat(path.getPathname().c_str(), &st) != 0) {
+        throw runtime::Exception(runtime::GetSystemErrorMessage());
+    }
+
+    return std::string("Test String");
+}
+
+void File::open(int flags, mode_t mode)
+{
+    while (1) {
+        descriptor = ::open(path.getPathname().c_str(), flags, mode);
+        if (descriptor == -1) {
+            if (errno != EINTR) {
+                continue;
+            }
+            throw runtime::Exception(runtime::GetSystemErrorMessage());
+        }
+        return;
+    }
+}
+
+void File::close()
+{
+    while (1) {
+        if (::close(descriptor) == -1) {
+            if (errno == EINTR) {
+                continue;
+            }
+        }
+        return;
+    }
+}
+
+void File::copyTo(const std::string& dest) const
+{
+}
+
+void File::moveTo(const std::string& dest)
+{
+}
+
+void File::renameTo(const std::string& dest)
+{
+}
+
+void File::remove(bool recursive)
+{
+    if (isDirectory()) {
+        if (recursive) {
+            DirectoryIterator iter(path), end;
+            while (iter != end) {
+                iter->remove(true);
+                ++iter;
+            }
+        }
+        if (::rmdir(path.getPathname().c_str()) != 0) {
+            throw runtime::Exception(runtime::GetSystemErrorMessage());
+        }
+    } else {
+        if (::unlink(path.getPathname().c_str()) != 0) {
+            throw runtime::Exception(runtime::GetSystemErrorMessage());
+        }
+    }
+}
+
+void File::makeDirectory(bool recursive)
+{
+    if (recursive) {
+        const std::string& pathStr = path.getPathname();
+        for (unsigned int i = 0; i != std::string::npos;) {
+            i = pathStr.find('/', i + 1);
+            ::mkdir(pathStr.substr(0, i).c_str(), 0777);
+        }
+    } else if (::mkdir(path.getPathname().c_str(), 0777) != 0) {
+        throw runtime::Exception(runtime::GetSystemErrorMessage());
+    }
+}
+
+void File::chown(uid_t uid, gid_t gid)
+{
+    if (::chown(path.getPathname().c_str(), uid, gid) != 0) {
+        throw runtime::Exception(runtime::GetSystemErrorMessage());
+    }
+}
+
+void File::chmod(mode_t mode)
+{
+    if (::chmod(path.getPathname().c_str(), mode) != 0) {
+        throw runtime::Exception(runtime::GetSystemErrorMessage());
+    }
+}
+
+DirectoryIterator::DirectoryIterator()
+    : directoryHandle(nullptr)
+{
+}
+
+DirectoryIterator::DirectoryIterator(const std::string& dir)
+    : directoryHandle(nullptr)
+{
+    reset(dir);
+}
+
+DirectoryIterator::DirectoryIterator(const Path& dir)
+    : DirectoryIterator(dir.getPathname())
+{
+}
+
+DirectoryIterator::~DirectoryIterator()
+{
+    if (directoryHandle != nullptr) {
+        ::closedir(directoryHandle);
+    }
+}
+
+void DirectoryIterator::reset(const std::string& dir)
+{
+    if (directoryHandle != nullptr) {
+        ::closedir(directoryHandle);
+        directoryHandle = nullptr;
+    }
+
+    basename = dir;
+    directoryHandle = ::opendir(basename.c_str());
+    if (directoryHandle == nullptr) {
+        throw runtime::Exception(runtime::GetSystemErrorMessage());
+    }
+
+    next();
+}
+
+void DirectoryIterator::next()
+{
+    std::string name;
+    struct dirent entry, *ent;
+
+    while (1) {
+        if (readdir_r(directoryHandle, &entry, &ent) != 0) {
+            throw runtime::Exception(runtime::GetSystemErrorMessage());
+        }
+
+        if (ent == NULL)
+            break;
+
+        if (ent->d_name[0] == '.' && ent->d_name[1] == '\0') {
+            continue;
+        }
+
+        if (ent->d_name[0] == '.' &&
+                ent->d_name[1] == '.' && ent->d_name[2] == '\0') {
+            continue;
+        }
+
+        name = basename + "/" + std::string(ent->d_name);
+        break;
+    }
+
+    current = name;
+}
+
+DirectoryIterator& DirectoryIterator::operator=(const std::string& dir)
+{
+    reset(dir);
+    return *this;
+}
+
+DirectoryIterator& DirectoryIterator::operator=(const Path& dir)
+{
+    reset(dir.getPathname());
+    return *this;
+}
+
+DirectoryIterator& DirectoryIterator::operator++()
+{
+    next();
+    return *this;
+}
+
+static const struct mountOption {
+    const char* name;
+    int clear;
+    int flag;
+} mountOptions[] = {
+    { "defaults",      0, 0                },
+    { "ro",            0, MS_RDONLY        },
+    { "rw",            1, MS_RDONLY        },
+    { "suid",          1, MS_NOSUID        },
+    { "nosuid",        0, MS_NOSUID        },
+    { "dev",           1, MS_NODEV         },
+    { "nodev",         0, MS_NODEV         },
+    { "exec",          1, MS_NOEXEC        },
+    { "noexec",        0, MS_NOEXEC        },
+    { "sync",          0, MS_SYNCHRONOUS   },
+    { "async",         1, MS_SYNCHRONOUS   },
+    { "dirsync",       0, MS_DIRSYNC       },
+    { "remount",       0, MS_REMOUNT       },
+    { "mand",          0, MS_MANDLOCK      },
+    { "nomand",        1, MS_MANDLOCK      },
+    { "atime",         1, MS_NOATIME       },
+    { "noatime",       0, MS_NOATIME       },
+    { "diratime",      1, MS_NODIRATIME    },
+    { "nodiratime",    0, MS_NODIRATIME    },
+    { "bind",          0, MS_BIND          },
+    { "rbind",         0, MS_BIND | MS_REC },
+    { "relatime",      0, MS_RELATIME      },
+    { "norelatime",    1, MS_RELATIME      },
+    { "strictatime",   0, MS_STRICTATIME   },
+    { "nostrictatime", 1, MS_STRICTATIME   },
+    { NULL,            0, 0                },
+};
+
+static unsigned long parseMountOptions(const std::string& opts, std::string& mntdata)
+{
+    std::stringstream optsSstream(opts);
+    const struct mountOption* mo;
+    unsigned long mntflags = 0L;
+    std::string opt;
+
+    while (std::getline(optsSstream, opt, ',')) {
+        for (mo = mountOptions; mo->name != NULL; mo++) {
+            if (opt == mo->name) {
+                if (mo->clear) {
+                    mntflags &= ~mo->flag;
+                } else {
+                    mntflags |= mo->flag;
+                }
+                break;
+            }
+            if (mo->name != NULL) {
+                continue;
+            }
+            if (!mntdata.empty()) {
+                mntdata += ",";
+            }
+            mntdata += opt;
+        }
+    }
+
+    return mntflags;
+}
+
+void Mount::mountEntry(const std::string& src, const std::string& dest, const std::string& type, const std::string& opts)
+{
+    int ret;
+    unsigned long mntflags;
+    std::string mntdata;
+
+    mntflags = parseMountOptions(opts, mntdata);
+
+    ret = ::mount(src.c_str(),
+                  dest.c_str(),
+                  type.c_str(),
+                  mntflags & ~MS_REMOUNT,
+                  mntdata.c_str());
+
+    if (ret) {
+        if ((mntflags & MS_REMOUNT) || (mntflags & MS_BIND)) {
+            ret = ::mount(src.c_str(),
+                          dest.c_str(),
+                          type.c_str(),
+                          mntflags | MS_REMOUNT,
+                          mntdata.c_str());
+        }
+
+        if (ret) {
+            throw runtime::Exception("failed to mount " + src + " on " + dest);
+        }
+    }
+}
+
+} // namespace runtime
diff --git a/device_core/agent_lib/rmi/src/mainloop.cpp b/device_core/agent_lib/rmi/src/mainloop.cpp
new file mode 100644 (file)
index 0000000..408e93b
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+ *  Copyright (c) 2015 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 <sys/epoll.h>
+#include <string.h>
+#include <unistd.h>
+#include <assert.h>
+
+#include <iostream>
+
+#include "error.h"
+#include "exception.h"
+#include "mainloop.h"
+
+#define MAX_EPOLL_EVENTS       16
+
+namespace runtime {
+
+Mainloop::Mainloop() :
+    pollFd(::epoll_create1(EPOLL_CLOEXEC)),
+    stopped(false)
+{
+    if (pollFd == -1) {
+        throw Exception(GetSystemErrorMessage());
+    }
+}
+
+Mainloop::~Mainloop()
+{
+    if (!callbacks.empty()) {
+        assert(0 && "callback list is not empty");
+    }
+
+    ::close(pollFd);
+}
+
+void Mainloop::addEventSource(const int fd, const Event events, Callback&& callback)
+{
+    epoll_event event;
+    std::lock_guard<Mutex> lock(mutex);
+
+    if (callbacks.find(fd) != callbacks.end()) {
+        throw Exception(GetSystemErrorMessage());
+    }
+
+    ::memset(&event, 0, sizeof(epoll_event));
+
+    event.events = events;
+    event.data.fd = fd;
+
+    if (::epoll_ctl(pollFd, EPOLL_CTL_ADD, fd, &event) == -1) {
+        throw Exception(GetSystemErrorMessage());
+    }
+
+    callbacks.insert({fd, std::make_shared<Callback>(std::move(callback))});
+}
+
+void Mainloop::removeEventSource(const int fd)
+{
+    std::lock_guard<Mutex> lock(mutex);
+
+    auto iter = callbacks.find(fd);
+    if (iter == callbacks.end()) {
+        return;
+    }
+
+    callbacks.erase(iter);
+
+    ::epoll_ctl(pollFd, EPOLL_CTL_DEL, fd, NULL);
+}
+
+bool Mainloop::dispatch(const int timeout)
+{
+    int nfds;
+    epoll_event event[MAX_EPOLL_EVENTS];
+
+    do {
+        nfds = ::epoll_wait(pollFd, event, MAX_EPOLL_EVENTS, timeout);
+    } while ((nfds == -1) && (errno == EINTR));
+
+    if (nfds < 0) {
+        throw Exception(GetSystemErrorMessage());
+    }
+
+    for (int i = 0; i < nfds; i++) {
+        std::lock_guard<Mutex> lock(mutex);
+
+        auto iter = callbacks.find(event[i].data.fd);
+        if (iter == callbacks.end()) {
+            continue;
+        }
+
+        std::shared_ptr<Callback> callback(iter->second);
+        try {
+            if ((event[i].events & (EPOLLHUP | EPOLLRDHUP))) {
+                event[i].events &= ~EPOLLIN;
+            }
+
+            (*callback)(event[i].data.fd, event[i].events);
+        } catch (std::exception& e) {
+            std::cout << "EXCEPTION ON MAINLOOP" << std::endl;
+        }
+    }
+
+    return true;
+}
+
+void Mainloop::stop()
+{
+    wakeupSignal.send();
+}
+
+void Mainloop::run()
+{
+    auto wakeupMainloop = [this](int fd, Mainloop::Event event) {
+        wakeupSignal.receive();
+        removeEventSource(wakeupSignal.getFd());
+        stopped = true;
+    };
+
+    addEventSource(wakeupSignal.getFd(), EPOLLIN, wakeupMainloop);
+
+    while (!stopped) {
+        dispatch(-1);
+    }
+}
+
+} // namespace runtime
diff --git a/device_core/agent_lib/rmi/src/process.cpp b/device_core/agent_lib/rmi/src/process.cpp
new file mode 100644 (file)
index 0000000..0a8d82b
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ *  Copyright (c) 2015 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 <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <signal.h>
+
+#include "process.h"
+#include "error.h"
+#include "exception.h"
+
+namespace runtime {
+
+Process::Process(const std::string& prog) :
+    status(-1), pid(-1), program(prog)
+{
+    args.push_back(prog);
+}
+
+Process::Process(const std::string& prog, const std::vector<std::string>& args) :
+    status(-1), pid(-1), program(prog), args(args)
+{
+}
+
+Process::Process(const Process& proc)
+{
+}
+
+Process::~Process()
+{
+}
+
+Process& Process::operator=(const Process& proc)
+{
+    return *this;
+}
+
+int Process::execute()
+{
+    pid = ::fork();
+    if (pid == -1) {
+        return -1;
+    }
+
+    if (pid == 0) {
+        const char** argv = new const char *[args.size() + 1];
+
+        int i = 0;
+        for (std::string & arg : args) {
+            argv[i++] = arg.c_str();
+        }
+        argv[i] = NULL;
+
+        ::execv(program.c_str(), const_cast<char* const*>(argv));
+        std::quick_exit(EXIT_FAILURE);
+    }
+
+    return waitForFinished();
+}
+
+int Process::waitForFinished()
+{
+    while (::waitpid(pid, &status, 0) == -1) {
+        if (errno != EINTR) {
+            return -1;
+        }
+    }
+
+    return status;
+}
+
+bool Process::isRunning() const
+{
+    if (::kill(pid, 0) == 0) {
+        return true;
+    }
+
+    return false;
+}
+
+void Process::kill()
+{
+    if (::kill(pid, SIGKILL) == -1) {
+        throw runtime::Exception(runtime::GetSystemErrorMessage());
+    }
+}
+
+void Process::terminate()
+{
+    if (::kill(pid, SIGINT) == -1) {
+        throw runtime::Exception(runtime::GetSystemErrorMessage());
+    }
+}
+
+} // namespace runtime
diff --git a/device_core/agent_lib/rmi/src/rmi/client.cpp b/device_core/agent_lib/rmi/src/rmi/client.cpp
new file mode 100644 (file)
index 0000000..f870851
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2015 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 "client.h"
+
+namespace rmi {
+
+Client::Client(const std::string& path) :
+    address(path)
+{
+}
+
+Client::~Client()
+{
+    disconnect();
+}
+
+void Client::connect()
+{
+    connection = std::make_shared<Connection>(Socket::connect(address));
+
+    dispatcher = std::thread([this] { mainloop.run(); });
+}
+
+int Client::unsubscribe(const std::string& provider, int id)
+{
+    mainloop.removeEventSource(id);
+    return 0;
+}
+
+int Client::subscribe(const std::string& provider, const std::string& name)
+{
+    Message request = connection->createMessage(Message::MethodCall, provider);
+    request.packParameters(name);
+    connection->send(request);
+
+    Message reply = connection->dispatch();
+    if (reply.isError()) {
+        return -1;
+    }
+
+    FileDescriptor response;
+    reply.disclose(response);
+
+    return response.fileDescriptor;
+}
+
+void Client::disconnect()
+{
+    mainloop.stop();
+    if (dispatcher.joinable()) {
+        dispatcher.join();
+    }
+}
+
+} // namespace rmi
diff --git a/device_core/agent_lib/rmi/src/rmi/connection.cpp b/device_core/agent_lib/rmi/src/rmi/connection.cpp
new file mode 100644 (file)
index 0000000..b67e40f
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2015 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 <utility>
+
+#include "connection.h"
+
+namespace rmi {
+
+Connection::Connection(Socket&& sock) :
+    socket(std::move(sock))
+{
+}
+
+Connection::~Connection() noexcept
+{
+}
+
+Message Connection::createMessage(unsigned int type, const std::string& target)
+{
+    return Message(type, target);
+}
+
+void Connection::send(const Message& message) const
+{
+    std::lock_guard<std::mutex> lock(transmitMutex);
+    message.encode(socket);
+}
+
+Message Connection::dispatch() const
+{
+    Message message;
+
+    std::lock_guard<std::mutex> lock(receiveMutex);
+    message.decode(socket);
+
+    return message;
+}
+
+} // namespace rmi
diff --git a/device_core/agent_lib/rmi/src/rmi/message-composer.cpp b/device_core/agent_lib/rmi/src/rmi/message-composer.cpp
new file mode 100644 (file)
index 0000000..b5c5181
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2015 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 "message-composer.h"
+
+namespace rmi {
+
+MessageComposer::MessageComposer(size_t caps) :
+    capacity(caps),
+    produce(0),
+    consume(0),
+    buffer(new char[caps])
+{
+}
+
+MessageComposer::MessageComposer(const MessageComposer& rhs) :
+    capacity(rhs.capacity),
+    produce(rhs.produce),
+    consume(rhs.consume),
+    buffer(new char[rhs.capacity])
+{
+    std::copy(rhs.buffer + consume, rhs.buffer + produce, buffer + consume);
+}
+
+MessageComposer::MessageComposer(MessageComposer&& rhs) :
+    capacity(0),
+    produce(0),
+    consume(0),
+    buffer(nullptr)
+{
+    buffer = rhs.buffer;
+    capacity = rhs.capacity;
+    produce = rhs.produce;
+    consume = rhs.consume;
+
+    // Release buffer pointer from the source object so that
+    // the destructor does not free the memory multiple times.
+
+    rhs.buffer = nullptr;
+    rhs.produce = 0;
+    rhs.consume = 0;
+}
+
+MessageComposer::~MessageComposer()
+{
+    if (buffer != nullptr) {
+        delete[] buffer;
+    }
+}
+
+MessageComposer& MessageComposer::operator=(const MessageComposer& rhs)
+{
+    if (this != &rhs) {
+        delete[] buffer;
+
+        capacity = rhs.capacity;
+        produce = rhs.produce;
+        consume = rhs.consume;
+        buffer = new char[capacity];
+        std::copy(rhs.buffer + consume, rhs.buffer + produce, buffer + consume);
+    }
+
+    return *this;
+}
+
+MessageComposer& MessageComposer::operator=(MessageComposer&& rhs)
+{
+    if (this != &rhs) {
+        // Free existing buffer
+        delete[] buffer;
+
+        // Copy the buffer pointer and its attributes from the
+        // source object.
+        buffer = rhs.buffer;
+        produce = rhs.produce;
+        consume = rhs.consume;
+        capacity = rhs.capacity;
+
+        // Release buffer pointer from the source object so that
+        // the destructor does not free the memory multiple times.
+        rhs.buffer = nullptr;
+        rhs.produce = 0;
+        rhs.consume = 0;
+        rhs.capacity = 0;
+    }
+
+    return *this;
+}
+
+void MessageComposer::insure(size_t sz)
+{
+    if (sz > capacity)
+    {
+        size_t new_capacity = sz;
+        char* new_buffer = new char[new_capacity];
+
+        ::memcpy(new_buffer, buffer, capacity);
+
+        delete[] buffer;
+
+        buffer = new_buffer;
+        capacity = new_capacity;
+
+    }
+}
+
+void MessageComposer::write(const void* ptr, const size_t sz)
+{
+    size_t bytes = sz;
+    if ((produce + bytes) > capacity) {
+        insure(produce + bytes);
+    }
+
+    ::memcpy(reinterpret_cast<char *>(buffer + produce), ptr, bytes);
+    produce += bytes;
+}
+
+void MessageComposer::read(void* ptr, const size_t sz)
+{
+    size_t bytes = sz;
+    if ((consume + bytes) > produce) {
+        bytes = produce - consume;
+    }
+
+    ::memcpy(ptr, reinterpret_cast<char *>(buffer) + consume, bytes);
+    consume += bytes;
+
+    // Reset cursors if there is no data
+    if (consume == produce) {
+        consume = produce = 0;
+    }
+}
+
+} // namespae rmi
diff --git a/device_core/agent_lib/rmi/src/rmi/message.cpp b/device_core/agent_lib/rmi/src/rmi/message.cpp
new file mode 100644 (file)
index 0000000..4555218
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2015 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 "message.h"
+
+namespace rmi {
+
+std::atomic<unsigned int> Message::sequence(0);
+
+Message::Message() :
+    signature({sequence++, Invalid, ""})
+{
+}
+
+Message::Message(unsigned int id, unsigned int type, const std::string& target) :
+    signature({id, type, target})
+{
+    enclose(signature);
+}
+
+Message::Message(unsigned int type, const std::string& target) :
+    signature({sequence++, type, target})
+{
+    enclose(signature);
+}
+
+Message::Message(Message&& rhs)
+    : signature(std::move(rhs.signature)),
+      buffer(std::move(rhs.buffer)),
+      fileDescriptors(std::move(rhs.fileDescriptors))
+{
+}
+
+Message::~Message()
+{
+}
+
+Message::Message(const Message& rhs) :
+    signature(rhs.signature),
+    buffer(rhs.buffer)
+{
+    enclose(signature);
+}
+
+Message& Message::operator=(const Message& rhs)
+{
+    if (this != &rhs) {
+        buffer = rhs.buffer;
+        signature = rhs.signature;
+    }
+
+    return *this;
+}
+
+Message& Message::operator=(Message&& rhs)
+{
+    if (this != &rhs) {
+        buffer = std::move(rhs.buffer);
+        signature = std::move(rhs.signature);
+        fileDescriptors = std::move(rhs.fileDescriptors);
+    }
+
+    return *this;
+}
+
+Message Message::createReplyMessage() const
+{
+    return Message(id(), Reply, target());
+}
+
+Message Message::createErrorMessage() const
+{
+    return Message(id(), Error, target());
+}
+
+template<> void Message::enclose(FileDescriptor&& fd)
+{
+    fileDescriptors.push_back(std::move(fd));
+}
+
+template<> void Message::disclose(FileDescriptor& fd)
+{
+    if (!fileDescriptors.empty()) {
+        fd.fileDescriptor = std::move(fileDescriptors.front()).fileDescriptor;
+        fileDescriptors.pop_front();
+    }
+}
+
+} // namespace rmi
diff --git a/device_core/agent_lib/rmi/src/rmi/notification.cpp b/device_core/agent_lib/rmi/src/rmi/notification.cpp
new file mode 100644 (file)
index 0000000..e36198d
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2015 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 <sys/socket.h>
+#include <sys/un.h>
+#include <unistd.h>
+
+#include "notification.h"
+#include "exception.h"
+#include "error.h"
+
+namespace rmi {
+
+Notification::Notification()
+{
+}
+
+Notification::Notification(const std::string& name) :
+    signalName(name)
+{
+}
+
+Notification::Notification(Notification&& rhs) :
+    signalName(std::move(rhs.signalName)),
+    subscribers(std::move(rhs.subscribers))
+{
+}
+
+SubscriptionId Notification::createSubscriber()
+{
+    int fds[2] = {-1, -1};
+    if (::socketpair(AF_UNIX, SOCK_STREAM, 0, fds) == -1) {
+        throw runtime::Exception("Failed to create socket pair");
+    }
+
+    std::lock_guard<std::mutex> lock(subscriberLock);
+       subscribers.emplace_back(std::make_shared<Socket>(fds[0]));
+
+    return SubscriptionId(fds[0], fds[1]);
+}
+
+int Notification::removeSubscriber(const int id)
+{
+    std::lock_guard<std::mutex> lock(subscriberLock);
+
+    std::vector<std::shared_ptr<Socket>>::iterator it = subscribers.begin();
+
+    while (it != subscribers.end()) {
+       if ((*it)->getFd() == id) {
+            subscribers.erase(it);
+            return 0;
+       }
+    }
+
+    return -1;
+}
+
+} // namespace rmi
diff --git a/device_core/agent_lib/rmi/src/rmi/service.cpp b/device_core/agent_lib/rmi/src/rmi/service.cpp
new file mode 100644 (file)
index 0000000..01fb49d
--- /dev/null
@@ -0,0 +1,196 @@
+/*
+ * Copyright (c) 2015 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 <sys/types.h>
+#include <unistd.h>
+
+#include <algorithm>
+
+#include "exception.h"
+#include "service.h"
+#include "message.h"
+
+namespace rmi {
+
+thread_local Service::ProcessingContext Service::processingContext;
+
+Service::Service(const std::string& path) :
+    address(path),
+    workqueue(5)
+{
+    setNewConnectionCallback(nullptr);
+    setCloseConnectionCallback(nullptr);
+}
+
+Service::~Service()
+{
+}
+
+void Service::start()
+{
+    Socket socket(Socket::create(address));
+
+    auto accept = [&](int fd, runtime::Mainloop::Event event) {
+        onNewConnection(std::make_shared<Connection>(socket.accept()));
+    };
+
+    mainloop.addEventSource(socket.getFd(),
+                            EPOLLIN | EPOLLHUP | EPOLLRDHUP,
+                            accept);
+    mainloop.run();
+}
+
+void Service::stop()
+{
+}
+
+Service::ConnectionRegistry::iterator Service::getConnectionIterator(const int id)
+{
+    std::lock_guard<std::mutex> lock(stateLock);
+
+    return std::find_if(connectionRegistry.begin(), connectionRegistry.end(),
+                        [id](const std::shared_ptr<Connection>& connection) {
+        return id == connection->getFd();
+    });
+}
+
+void Service::setNewConnectionCallback(const ConnectionCallback& connectionCallback)
+{
+    auto callback = [connectionCallback, this](const std::shared_ptr<Connection>& connection) {
+        auto handle = [&](int fd, runtime::Mainloop::Event event) {
+            auto iter = getConnectionIterator(fd);
+            if (iter == connectionRegistry.end()) {
+                return;
+            }
+
+            if ((event & EPOLLHUP) || (event & EPOLLRDHUP)) {
+                onCloseConnection(*iter);
+                connectionRegistry.erase(iter);
+                return;
+            }
+            onMessageProcess(*iter);
+        };
+
+        if ((connectionCallback == nullptr) ||
+            (connectionCallback(*connection) == true)) {
+            mainloop.addEventSource(connection->getFd(),
+                                    EPOLLIN | EPOLLHUP | EPOLLRDHUP,
+                                    handle);
+            connectionRegistry.push_back(connection);
+        }
+    };
+
+    std::lock_guard<std::mutex> lock(stateLock);
+    onNewConnection = std::move(callback);
+}
+
+void Service::setCloseConnectionCallback(const ConnectionCallback& closeCallback)
+{
+    auto callback = [closeCallback, this](const std::shared_ptr<Connection>& connection) {
+        mainloop.removeEventSource(connection->getFd());
+        if (closeCallback) {
+            closeCallback(*connection);
+        }
+    };
+
+    std::lock_guard<std::mutex> lock(stateLock);
+    onCloseConnection = std::move(callback);
+}
+
+void Service::createNotification(const std::string& name)
+{
+    std::lock_guard<std::mutex> lock(notificationLock);
+
+    if (notificationRegistry.count(name)) {
+        throw runtime::Exception("Notification [" + name + "]  already registered");
+    }
+
+    notificationRegistry.emplace(name, name);
+}
+
+int Service::subscribeNotification(const std::string& name)
+{
+    auto closeHandler = [&, name](int fd, runtime::Mainloop::Event event) {
+        if ((event & EPOLLHUP) || (event & EPOLLRDHUP)) {
+            unsubscribeNotification(name, fd);
+            return;
+        }
+    };
+
+    notificationLock.lock();
+    if (!notificationRegistry.count(name)) {
+        notificationLock.unlock();
+        return -1;
+    }
+
+    Notification& notification = notificationRegistry[name];
+    notificationLock.unlock();
+
+    try {
+        SubscriptionId slot = notification.createSubscriber();
+        mainloop.addEventSource(slot.first, EPOLLHUP | EPOLLRDHUP, closeHandler);
+        return slot.second;
+    } catch (runtime::Exception& e) {
+        return -1;
+    }
+
+    return -1;
+}
+
+int Service::unsubscribeNotification(const std::string& name, const int id)
+{
+    notificationLock.lock();
+
+    if (!notificationRegistry.count(name)) {
+        notificationLock.unlock();
+        return -1;
+    }
+
+    Notification& notification = notificationRegistry[name];
+    notificationLock.unlock();
+
+    notification.removeSubscriber(id);
+
+    mainloop.removeEventSource(id);
+
+    return 0;
+}
+
+void Service::onMessageProcess(const std::shared_ptr<Connection>& connection)
+{
+    auto process = [&](Message& request) {
+        try {
+            //stateLock.lock();
+            std::shared_ptr<MethodDispatcher> methodDispatcher = methodRegistry.at(request.target());
+            //stateLock.unlock();
+
+            // [TBD] Request authentication before dispatching method handler.
+            processingContext = ProcessingContext(connection);
+            connection->send((*methodDispatcher)(request));
+        } catch (std::exception& e) {
+            std::cerr << e.what() << std::endl;
+            connection->send(request.createErrorMessage());
+        }
+    };
+
+    try {
+        workqueue.submit(std::bind(process, connection->dispatch()));
+    } catch (runtime::Exception& e) {
+        std::cerr << e.what() << std::endl;
+    }
+}
+
+} // namespace rmi
diff --git a/device_core/agent_lib/rmi/src/rmi/socket.cpp b/device_core/agent_lib/rmi/src/rmi/socket.cpp
new file mode 100644 (file)
index 0000000..b959e08
--- /dev/null
@@ -0,0 +1,323 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/un.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <cstring>
+#include <iostream>
+
+#include "error.h"
+#include "socket.h"
+
+namespace rmi {
+
+namespace {
+
+const int MAX_BACKLOG_SIZE = 100;
+
+void setCloseOnExec(int fd)
+{
+    if (::fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) {
+        throw SocketException(runtime::GetSystemErrorMessage());
+    }
+}
+
+Credentials getCredentials(int fd)
+{
+    struct ucred cred;
+    socklen_t credsz = sizeof(cred);
+    if (::getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &cred, &credsz)) {
+        throw SocketException(runtime::GetSystemErrorMessage());
+    }
+
+    return {cred.pid, cred.uid, cred.gid};
+}
+
+} // namespace
+
+Socket::Socket(int fd, bool autoclose) :
+    socketFd(fd),
+    autoClose(autoclose)
+{
+}
+
+Socket::Socket(Socket&& socket) noexcept :
+    socketFd(socket.socketFd),
+    autoClose(socket.autoClose)
+{
+    socket.socketFd = -1;
+}
+
+Socket::~Socket() noexcept
+{
+    if ((socketFd != -1) && (autoClose)) {
+        ::close(socketFd);
+    }
+}
+
+Socket Socket::accept()
+{
+    int sockfd = ::accept(socketFd, nullptr, nullptr);
+    if (sockfd == -1) {
+        throw SocketException(runtime::GetSystemErrorMessage());
+    }
+
+    setCloseOnExec(sockfd);
+
+    return Socket(sockfd);
+}
+
+int Socket::getFd() const
+{
+    return socketFd;
+}
+
+Credentials Socket::getPeerCredentials() const
+{
+    return getCredentials(socketFd);
+}
+
+void Socket::read(void *buffer, const size_t size) const
+{
+    size_t total = 0;
+
+    while (total < size) {
+        int bytes = ::read(socketFd, reinterpret_cast<char*>(buffer) + total, size - total);
+        if (bytes >= 0) {
+            total += bytes;
+        } else if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) {
+            continue;
+        } else {
+            throw SocketException(runtime::GetSystemErrorMessage());
+        }
+    }
+}
+
+void Socket::write(const void *buffer, const size_t size) const
+{
+    size_t written = 0;
+
+    while (written < size) {
+        int bytes = ::write(socketFd, reinterpret_cast<const char*>(buffer) + written, size - written);
+        if (bytes >= 0) {
+            written += bytes;
+        } else if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) {
+            continue;
+        } else {
+            throw SocketException(runtime::GetSystemErrorMessage());
+        }
+    }
+}
+
+void Socket::sendFileDescriptors(const int* fds, const size_t nr) const
+{
+    if (nr == 0) return;
+
+    int buf;
+    struct iovec iov = {
+        .iov_base = &buf,
+        .iov_len = sizeof(char)
+    };
+
+    char buffer[CMSG_SPACE(sizeof(int) * nr)];
+    ::memset(buffer, 0, sizeof(buffer));
+
+    struct msghdr msgh;
+    ::memset(&msgh, 0, sizeof(msgh));
+
+    msgh.msg_iov = &iov;
+    msgh.msg_iovlen = 1;
+    msgh.msg_control = buffer;
+    msgh.msg_controllen = sizeof(buffer);
+
+    struct cmsghdr *cmhp;
+    cmhp = CMSG_FIRSTHDR(&msgh);
+    cmhp->cmsg_level = SOL_SOCKET;
+    cmhp->cmsg_type = SCM_RIGHTS;
+    cmhp->cmsg_len = CMSG_LEN(sizeof(int) * nr);
+
+    ::memcpy(CMSG_DATA(cmhp), fds, sizeof(int) * nr);
+
+    int written = 0;
+    while (written < 1) {
+        ssize_t ret = ::sendmsg(socketFd, &msgh, MSG_NOSIGNAL);
+        if (ret >= 0) {
+            written += ret;
+        } else if ((errno != EAGAIN) && (errno != EWOULDBLOCK) && (errno != EINTR)) {
+            throw SocketException(runtime::GetSystemErrorMessage());
+        }
+    }
+}
+
+void Socket::receiveFileDescriptors(int* fds, const size_t nr) const
+{
+    if (nr == 0) return;
+
+    char buf = '!';
+    struct iovec iov = {
+        .iov_base = &buf,
+        .iov_len = sizeof(char)
+    };
+
+    char buffer[CMSG_SPACE(sizeof(int) * nr) + CMSG_SPACE(sizeof(struct ucred))];
+    ::memset(buffer, 0, sizeof(buffer));
+
+    struct msghdr msgh;
+    ::memset(&msgh, 0, sizeof(msgh));
+
+    msgh.msg_iov = &iov;
+    msgh.msg_iovlen = 1;
+    msgh.msg_control = buffer;
+    msgh.msg_controllen = sizeof(buffer);
+
+    ssize_t bytes = 0;
+    while (bytes < 1) {
+        ssize_t ret = ::recvmsg(socketFd, &msgh, MSG_WAITALL);
+        if (ret >= 0) {
+            bytes += ret;
+        } else {
+            if ((errno != EAGAIN) && (errno != EWOULDBLOCK) && (errno != EINTR)) {
+                throw SocketException(runtime::GetSystemErrorMessage());
+            }
+        }
+    }
+
+    int i = 0;
+    for (struct cmsghdr *cmhp = CMSG_FIRSTHDR(&msgh); cmhp != NULL; cmhp = CMSG_NXTHDR(&msgh, cmhp)) {
+        if ((cmhp->cmsg_level == SOL_SOCKET) && (cmhp->cmsg_type == SCM_RIGHTS)) {
+            if (cmhp->cmsg_len != CMSG_LEN(sizeof(int) * nr)) {
+                std::cout << "Invalid File Descriptor Table" << std::endl;
+            }
+
+            fds[i++] = *(reinterpret_cast<int*>(CMSG_DATA(cmhp)));
+        }
+    }
+}
+
+#ifdef USE_SYSTEMD_SOCKET_ACTIVATION
+int Socket::createSystemdSocket(const std::string& path)
+{
+    int n = ::sd_listen_fds(-1);
+    if (n < 0) {
+        throw SocketException("sd_listen_fds faield");
+    }
+
+    for (int fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; ++fd) {
+        if (::sd_is_socket_unix(fd, SOCK_STREAM, 1, path.c_str(), 0) > 0) {
+            setCloseOnExec(fd);
+            return fd;
+        }
+    }
+
+    return -1;
+}
+#endif
+
+int Socket::createRegularSocket(const std::string& path)
+{
+    if (path.size() >= sizeof(sockaddr_un::sun_path)) {
+        throw SocketException(runtime::GetSystemErrorMessage(ENAMETOOLONG));
+    }
+
+    int sockfd = ::socket(AF_UNIX, SOCK_STREAM, 0);
+    if (sockfd == -1) {
+        throw SocketException(runtime::GetSystemErrorMessage());
+    }
+
+    setCloseOnExec(sockfd);
+
+    ::sockaddr_un addr;
+    addr.sun_family = AF_UNIX;
+    ::strncpy(addr.sun_path, path.c_str(), sizeof(sockaddr_un::sun_path));
+
+    if (addr.sun_path[0] == '@') {
+        addr.sun_path[0] = '\0';
+    } else {
+        unlink(path.c_str());
+    }
+
+    if (::bind(sockfd, reinterpret_cast<struct sockaddr *>(&addr), sizeof(struct sockaddr_un)) == -1) {
+        ::close(sockfd);
+        throw SocketException(runtime::GetSystemErrorMessage());
+    }
+
+    int optval = 1;
+    if (::setsockopt(sockfd, SOL_SOCKET, SO_PASSCRED, &optval, sizeof(optval)) == -1) {
+        ::close(sockfd);
+        throw SocketException(runtime::GetSystemErrorMessage());
+    }
+
+    if (::listen(sockfd, MAX_BACKLOG_SIZE) == -1) {
+        ::close(sockfd);
+        throw SocketException(runtime::GetSystemErrorMessage());
+    }
+
+    return sockfd;
+}
+
+Socket Socket::create(const std::string& path)
+{
+    int fd;
+
+#ifdef USE_SYSTEMD_SOCKET_ACTIVATION
+    fd = createSystemdSocket(path);
+    if (fd == -1) {
+        fd = createRegularSocket(path);
+    }
+#else
+    fd = createRegularSocket(path);
+#endif
+
+    return Socket(fd);
+}
+
+Socket Socket::connect(const std::string& path)
+{
+    if (path.size() >= sizeof(sockaddr_un::sun_path)) {
+        throw SocketException(runtime::GetSystemErrorMessage(ENAMETOOLONG));
+    }
+
+    int fd = ::socket(AF_UNIX, SOCK_STREAM, 0);
+    if (fd == -1) {
+        throw SocketException(runtime::GetSystemErrorMessage());
+    }
+
+    setCloseOnExec(fd);
+
+    sockaddr_un addr;
+    addr.sun_family = AF_UNIX;
+    ::strncpy(addr.sun_path, path.c_str(), sizeof(sockaddr_un::sun_path));
+
+    if (addr.sun_path[0] == '@') {
+        addr.sun_path[0] = '\0';
+    }
+
+    if (::connect(fd, reinterpret_cast<struct sockaddr *>(&addr), sizeof(struct sockaddr_un)) == -1) {
+        ::close(fd);
+        throw SocketException(runtime::GetSystemErrorMessage());
+    }
+
+    return Socket(fd);
+}
+
+} // namespace Ipc
diff --git a/device_core/agent_lib/rmi/src/thread-pool.cpp b/device_core/agent_lib/rmi/src/thread-pool.cpp
new file mode 100644 (file)
index 0000000..20f0a15
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2015 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 <sys/types.h>
+#include <unistd.h>
+
+#include "thread-pool.h"
+#include "exception.h"
+
+#define __BEGIN_CRITICAL__  { std::unique_lock<std::mutex> lock(this->queueMutex);
+#define __END_CRITICAL__    }
+
+namespace runtime {
+
+ThreadPool::ThreadPool(size_t threads)
+    : stop(false)
+{
+    for (size_t i = 0; i < threads; i++) {
+       workers.emplace_back([this] {
+            while (true) {
+                std::function<void()> task;
+
+                __BEGIN_CRITICAL__
+                condition.wait(lock, [this]{ return stop || !tasks.empty();});
+                if (stop && tasks.empty()) {
+                    return;
+                }
+
+                task = std::move(tasks.front());
+                tasks.pop_front();
+                __END_CRITICAL__
+
+                task();
+            }
+        });
+    }
+}
+
+ThreadPool::~ThreadPool()
+{
+    __BEGIN_CRITICAL__
+    stop = true;
+    __END_CRITICAL__
+
+    condition.notify_all();
+
+    for (std::thread &worker: workers) {
+        if (worker.joinable()) {
+            worker.join();
+        }
+    }
+}
+
+void ThreadPool::submit(std::function<void()>&& task)
+{
+    __BEGIN_CRITICAL__
+    if (!stop) {
+        tasks.push_back(std::move(task));
+    }
+    __END_CRITICAL__
+
+    condition.notify_one();
+}
+
+} // namespace runtime
diff --git a/device_core/utest/test_rmi.cpp b/device_core/utest/test_rmi.cpp
new file mode 100644 (file)
index 0000000..2efa481
--- /dev/null
@@ -0,0 +1,129 @@
+/**
+ * @brief  TODO
+ * @date   Created 17.05.2017
+ * @author Created 2017 in Samsung Ukraine R&D Center (SURC) under a contract
+ *                between LLC "Samsung Electronics Ukraine Company" (Kiev, Ukraine)
+ *                and "Samsung Electronics Co", Ltd (Seoul, Republic of Korea).
+ *         Copyright: (c) Samsung Electronics Co, Ltd 2017. All rights reserved.
+ * @author Mail to: <A HREF="mailto:a.gudz@samsung.com">Andriy Gudz, a.gudz@samsung.com</A>
+ */
+#include <iostream>
+#include <string>
+#include <mutex>
+#include <condition_variable>
+
+#include <gtest/gtest.h>
+
+#include "rmi/service.h"
+#include "rmi/client.h"
+#include <signal.h>
+#include <execinfo.h>
+
+using namespace std;
+
+namespace
+{
+
+const std::string RMI_SERVICE_ADDRESS = "/tmp/.rmi_service";
+
+}
+
+class AgentInterface
+{
+public:
+    void run()
+    {
+        // Prepare execution environment
+        cout << "2" << flush;
+        service->start();
+        cout << "3" << flush;
+    }
+
+    void terminate()
+    {
+        service->stop();
+    }
+
+    string handshake(string input)
+    {
+        if (input == "SYN")
+            return "SYN-ACC";
+        return "FAIL";
+    }
+
+    static AgentInterface& instance()
+    {
+        static AgentInterface _instance_;
+        return _instance_;
+    }
+
+private:
+    AgentInterface()
+    {
+        service.reset(new rmi::Service(RMI_SERVICE_ADDRESS));
+        cout << "0" << flush;
+        service->registerParametricMethod(this, (string)(AgentInterface::handshake)(string));
+        cout << "1" << flush;
+    }
+
+    ~AgentInterface()
+    {
+    }
+
+    std::unique_ptr<rmi::Service> service;
+};
+
+void sig_handler(int signal)
+{
+    std::cout << "Signal trapped: " << signal << std::endl;
+    const int SIZE = 100;
+    void* recs[SIZE];
+
+    int count = backtrace(recs, SIZE);
+    std::cout << "Stack records: " << count << std::endl;
+
+    char** str = backtrace_symbols(recs, count);
+
+    for (int i = 0; i < count; i++)
+    {
+        std::cout << str[i] << std::endl;
+    }
+}
+
+/**
+ * Test checks example of rmi
+ */
+TEST(test_rmi, handshakeCorrect)
+{
+//    std::mutex mtx;
+//    std::unique_lock<std::mutex> lock(mtx);
+//    std::condition_variable cv;
+
+//    signal(SIGABRT, sig_handler);
+
+    try
+    {
+        AgentInterface& service = AgentInterface::instance();
+        std::thread agentInterfaceThread ([&]
+        {
+            try
+            {
+                service.run();
+            }
+            catch(std::exception& e)
+            {
+                std::cout << "test_rmi exception: " << e.what() <<std::endl;
+            }
+        });
+
+        rmi::Client client(RMI_SERVICE_ADDRESS);
+        client.connect();
+        ASSERT_EQ("SYN-ACC", client.methodCall<string>("AgentInterface::handshake", string("SYN")));
+        ASSERT_EQ("FAIL", client.methodCall<string>("AgentInterface::handshake", string("NOTSYN")));
+        client.disconnect();
+    }
+    catch(std::exception& e)
+    {
+        std::cout << "test_rmi exception: " << e.what() <<std::endl;
+    }
+}