Added secserver - mock server that publish notification resource
authorAndriy Gudz <a.gudz@samsung.com>
Fri, 12 May 2017 05:35:53 +0000 (08:35 +0300)
committerAndriy Gudz <a.gudz@samsung.com>
Fri, 12 May 2017 05:35:53 +0000 (08:35 +0300)
network-manager/CMakeLists.txt
network-manager/secserver/CMakeLists.txt [new file with mode: 0644]
network-manager/secserver/notification_resource.cpp [new file with mode: 0644]
network-manager/secserver/notification_resource.h [new file with mode: 0644]
network-manager/secserver/secserver.cpp [new file with mode: 0644]

index 7cb7389..084ccbf 100644 (file)
@@ -103,6 +103,7 @@ IF("${FLAVOR}" STREQUAL "UBUNTU")
        add_subdirectory(nmlib)
        add_subdirectory(test)
        add_subdirectory(nmdaemon)
+       add_subdirectory(secserver)
 else()
        add_subdirectory(nmlib)
        add_subdirectory(test)
diff --git a/network-manager/secserver/CMakeLists.txt b/network-manager/secserver/CMakeLists.txt
new file mode 100644 (file)
index 0000000..e7dc115
--- /dev/null
@@ -0,0 +1,12 @@
+get_filename_component(ProjectId ${CMAKE_CURRENT_SOURCE_DIR} NAME)
+project(${ProjectId})
+
+set(app ${ProjectId})
+file(GLOB SRCS *.cpp)
+
+include_directories(./nmlib/include)
+
+add_executable(${app} ${SRCS})
+target_link_libraries(${app} nmlib)
+
+install(TARGETS ${app} DESTINATION ${TESTS_DIR})
diff --git a/network-manager/secserver/notification_resource.cpp b/network-manager/secserver/notification_resource.cpp
new file mode 100644 (file)
index 0000000..9eac629
--- /dev/null
@@ -0,0 +1,143 @@
+#include "notification_resource.h"
+
+namespace PH = std::placeholders;
+
+const std::string NotificationResource::RESOURCE_DEFAULT_MESSAGE = "Empty notification";
+
+NotificationResource::NotificationResource():
+    NotificationResource(true)
+{
+}
+
+NotificationResource::NotificationResource(bool isSecured):
+    mCode(0),
+    mTime(std::time(nullptr)),
+    mMessage(RESOURCE_DEFAULT_MESSAGE),
+    mUri(NOTIFICATION_URI),
+    mResourceHandle(nullptr),
+    mIsSecured(isSecured)
+{
+}
+
+void NotificationResource::registerResource()
+{
+
+    EntityHandler resourceCallback = std::bind(&NotificationResource::entityHandler, this, PH::_1);
+
+    // This will internally create and register the resource.
+    OCStackResult result = OCPlatform::registerResource(
+                               mResourceHandle,
+                               mUri,
+                               NOTIFICATION_TYPE,
+                               DEFAULT_INTERFACE,
+                               resourceCallback,
+                               OC_DISCOVERABLE | OC_OBSERVABLE | (mIsSecured ? OC_SECURE : 0)
+                           );
+
+    if (OC_STACK_OK != result)
+        cout << "Resource creation was unsuccessful\n";
+    else
+        cout << "Notification resource created.\n";
+}
+
+OCResourceHandle NotificationResource::getHandle()
+{
+    return mResourceHandle;
+}
+
+OCRepresentation NotificationResource::getRepr()
+{
+    OCRepresentation mRepr;
+    mRepr.setUri(mUri);
+    mRepr.setValue("time", (int) mTime);
+    mRepr.setValue("code", mCode);
+    mRepr.setValue("message", mMessage);
+    mRepr.setValue("result", 0);
+    return mRepr;
+}
+
+void NotificationResource::set(int code, std::string message)
+{
+    mTime = std::time(nullptr);
+    mCode = code;
+    mMessage = message;
+}
+
+void NotificationResource::get(int& code, std::string& message, std::time_t& time)
+{
+    time = mTime;
+    code = mCode;
+    message = mMessage;
+}
+
+
+//ObservationIds NotificationResource::getObserversList()
+//{
+//    return mObserversList;
+//}
+
+inline std::shared_ptr<OC::OCResourceResponse>
+constructRequest(std::shared_ptr<OC::OCResourceRequest> request, OCRepresentation rep)
+{
+    shared_ptr<OCResourceResponse> pResponse = make_shared<OCResourceResponse>();
+    pResponse->setRequestHandle(request->getRequestHandle());
+    pResponse->setResourceHandle(request->getResourceHandle());
+    pResponse->setErrorCode(200);
+    pResponse->setResponseResult(OC_EH_OK);
+    pResponse->setResourceRepresentation(rep, DEFAULT_INTERFACE);
+    return pResponse;
+}
+
+OCEntityHandlerResult NotificationResource::entityHandler(std::shared_ptr<OCResourceRequest> request)
+{
+    OCEntityHandlerResult ehResult = OC_EH_ERROR;
+    if(!request)
+    {
+        std::cout << "Request invalid" << std::endl;
+        return ehResult;
+    }
+
+    std::cout << "Handling request from client:\n";
+
+    // Get the request type and request flag
+    std::string requestType = request->getRequestType();
+    int requestFlag = request->getRequestHandlerFlag();
+
+    QueryParamsMap queries = request->getQueryParameters();
+
+    if(requestFlag & RequestHandlerFlag::RequestFlag && requestType == "GET")
+    {
+        if(OC_STACK_OK == OCPlatform::sendResponse(constructRequest(request, getRepr())))
+        {
+            ehResult = OC_EH_OK;
+        }
+    }
+
+    if(requestFlag & RequestHandlerFlag::ObserverFlag)
+    {
+        ObservationInfo observationInfo = request->getObservationInfo();
+
+        if(ObserveAction::ObserveRegister == observationInfo.action)
+        {
+            mObserversList.push_back(observationInfo.obsId);
+
+            std::cout << "Client "
+                      << "[" << observationInfo.address
+                      << "]:" << observationInfo.port
+                      << " was registered to observe "
+                      << request->getResourceUri() << "\n";
+        }
+        // Have no idea how to get this flag - ObserveUnregister
+        else if(ObserveAction::ObserveUnregister == observationInfo.action)
+        {
+            mObserversList.erase(std::remove(
+                                     mObserversList.begin(),
+                                     mObserversList.end(),
+                                     observationInfo.obsId),
+                                 mObserversList.end());
+        }
+        ehResult = OC_EH_OK;
+    }
+
+    return ehResult;
+}
diff --git a/network-manager/secserver/notification_resource.h b/network-manager/secserver/notification_resource.h
new file mode 100644 (file)
index 0000000..d5ed3e4
--- /dev/null
@@ -0,0 +1,77 @@
+#ifndef ALERTRESOURCE_H
+#define ALERTRESOURCE_H
+
+#include "OCPlatform.h"
+
+using namespace OC;
+using namespace std;
+
+static const std::string NOTIFICATION_URI = "/secserver/notification";
+static const std::string NOTIFICATION_TYPE = "secserver.notification";
+
+/**
+ * Class that represents /secserver/notification resource.
+ */
+class NotificationResource
+{
+public:
+
+private:
+    static const std::string RESOURCE_DEFAULT_MESSAGE;
+
+    int mCode;
+    std::time_t mTime;
+    std::string mMessage;
+    std::string mUri;
+
+    OCResourceHandle mResourceHandle;
+       ObservationIds mObserversList;
+    bool mIsSecured;
+
+public:
+    /**
+     * Constructor
+     *
+     * @param dbHandler database object for authentication
+     */
+       NotificationResource();
+
+    /**
+     * Constructor
+     *
+     * @param dbHandler database object for authentication
+     * @param isSecure flag indicates that resource is secured
+     */
+       NotificationResource(bool isSecure);
+
+    /**
+     * Register resource to make IOTivity clients to find it
+     */
+    void registerResource();
+
+    /**
+     * Getter for resource mResourceHandle
+     *
+     * @return mResourceHandle object
+     */
+    OCResourceHandle getHandle();
+
+    /**
+     * Gets the updated representation.
+     *
+     * @return representation object
+     */
+    OCRepresentation getRepr();
+
+    /**
+     * Updates internal fields of resource.
+     */
+    void set(int code, std::string message);
+
+    void get(int& code, std::string& message, std::time_t& time);
+
+private:
+    OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request);
+};
+
+#endif // ALERTRESOURCE_H
diff --git a/network-manager/secserver/secserver.cpp b/network-manager/secserver/secserver.cpp
new file mode 100644 (file)
index 0000000..daf2028
--- /dev/null
@@ -0,0 +1,152 @@
+#include <condition_variable>
+#include <mutex>
+
+#include "RDClient.h"
+
+#include <OCApi.h>
+#include <OCPlatform.h>
+#include "iotivity.h"
+#include "notification_resource.h"
+
+using namespace OC;
+using namespace NetworkManager;
+using namespace std;
+
+condition_variable g_callbackLock;
+
+static string getPSPath()
+{
+    char SVR_DB_FILE_PATH[1000] = {0};
+    ssize_t size = readlink("/proc/self/exe", SVR_DB_FILE_PATH, sizeof(SVR_DB_FILE_PATH));
+    if (size == 0 || size == sizeof(SVR_DB_FILE_PATH))
+        throw runtime_error("readlink error");
+    return string(SVR_DB_FILE_PATH) + "_ps.dat";
+}
+
+void inputNotificationData(int& notifCode, string& notifMessage, time_t& notifTime)
+{
+    std::cout << "\n\nPlease enter new notification [Current: "
+              << notifCode << " \"" << notifMessage << "\" " << notifTime << "]:\n";
+
+    string inputLine;
+    std::getline (std::cin, inputLine);
+
+    std::size_t ending = inputLine.find(" ");
+
+    try
+    {
+        if (inputLine.size() > 0)
+            notifCode = stoi(inputLine);
+
+        if (ending != std::string::npos)
+            notifMessage = inputLine.substr(ending + 1, inputLine.size() - ending);
+    }
+    catch (const std::exception& e)
+    {
+        // nothing
+    }
+}
+
+void onPublish(const OCRepresentation &, const int &eCode)
+{
+    cout << "Publish resource response received, code: " << eCode << endl;
+
+    g_callbackLock.notify_all();
+}
+
+inline void guardErrorCode(OCStackResult resultCode, std::string message)
+{
+    if (resultCode != OC_STACK_OK)
+        throw runtime_error(message + " error:" + std::to_string(resultCode));
+}
+
+
+void setDeviceInfo(std::string duid)
+{
+    OCDeviceInfo        devInfoAirConditioner;
+    OCStringLL          deviceType;
+    OCStringLL          deviceModel;
+
+    deviceType.value = (char*)"oic.d.secserver";
+    deviceType.next = NULL;
+
+    deviceModel.value = (char*)"1";
+    deviceModel.next = NULL;
+
+    std::string name = "secserver " + duid.substr(0,8);
+    devInfoAirConditioner.deviceName = (char*)name.c_str();
+    devInfoAirConditioner.types = &deviceType;
+    devInfoAirConditioner.specVersion = NULL;
+    devInfoAirConditioner.dataModelVersions = &deviceModel;
+
+    guardErrorCode(OC::OCPlatform::registerDeviceInfo(devInfoAirConditioner), "registerDeviceInfo()");
+}
+
+static void mainLoop()
+{
+    std::string login("login");
+    std::string password("password");
+    std::string host("coap+tcp://106.125.46.44:5683");
+
+    auto iot = IoTivity::getInstance();
+    iot->setPersistentStoragePath(getPSPath());
+    iot->signIn(host, login, password);
+    std::string duid = iot->getDeviceID();
+    cout << "secserver lounched: " << duid << endl << flush;
+
+    mutex blocker;
+    unique_lock<mutex> lock(blocker);
+
+    ResourceHandles resourceHandles;
+    setDeviceInfo(duid);
+    guardErrorCode(RDClient::Instance().publishResourceToRD(host, OCConnectivityType::CT_ADAPTER_TCP, resourceHandles,
+                   &onPublish), "Default publishResourceToRD()");
+    g_callbackLock.wait(lock);
+
+    cout << "Device info publish success" << endl << flush;
+
+    bool isSecured = false;
+    NotificationResource notifResource(isSecured);
+    notifResource.registerResource();
+
+    resourceHandles.push_back(notifResource.getHandle());
+
+    guardErrorCode(RDClient::Instance().publishResourceToRD(host, OCConnectivityType::CT_ADAPTER_TCP, resourceHandles,
+                   &onPublish), "Notification resource publishResourceToRD()");
+    g_callbackLock.wait(lock);
+
+    cout << "Notification resource publish success" << endl << flush;
+
+    int notifCode;
+    string notifMessage;
+    time_t notifTime;
+
+    while(true)
+    {
+        notifResource.get(notifCode, notifMessage, notifTime);
+        inputNotificationData(notifCode, notifMessage, notifTime);
+
+        cout << "Sending notification:" << notifCode << " " << notifMessage << "\n";
+
+        notifResource.set(notifCode, notifMessage);
+
+        OCStackResult result = OCPlatform::notifyAllObservers(notifResource.getHandle());
+
+        if(OC_STACK_NO_OBSERVERS == result)
+            cout << "No more observers" << endl;
+    }
+}
+
+int main(int argc, char* argv[])
+{
+    try
+    {
+        mainLoop();
+    }
+    catch(OCException &e)
+    {
+        std::cout << "OCException: " << e.what() << endl;
+    }
+
+    return 0;
+}