Fix place of connection.json
[apps/agl-service-windowmanager.git] / src / wm_connection.cpp
1 /*
2  * Copyright (c) 2017 TOYOTA MOTOR CORPORATION
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include "wm_connection.hpp"
18 #include <string.h>
19 #include <unistd.h>
20 #include <sys/types.h>
21 #include <sys/socket.h>
22 #include <netinet/in.h>
23 #include <arpa/inet.h>
24 #include "json_helper.hpp"
25 #include "util.hpp"
26
27 extern "C"
28 {
29 #include <afb/afb-binding.h>
30 #include <systemd/sd-event.h>
31 }
32
33
34 /**
35  * namespace wm
36  */
37 namespace wm
38 {
39
40
41 namespace
42 {
43
44 static const char kPathConnectionConfigFile[] = "/etc/connection.json";
45 static const char kPathTimeoutConfigFile[] = "/etc/timeout.json";
46 static const char kDefaultIpAddr[] = "192.168.10.10";
47 static const int  kDefaultPort     = 4000;
48 static const uint64_t  kDefaultTimes    = 60000;
49 static const uint64_t  kDefaultSleep    = 50;
50 static struct sd_event_source *g_limit_timer_src = nullptr;
51 static struct sd_event_source *g_sleep_timer_src = nullptr;
52
53 static int setTimer(sd_event_source **src, uint64_t usec, void* handler, void* data)
54 {
55     int ret = sd_event_add_time(afb_daemon_get_event_loop(), src,
56             CLOCK_BOOTTIME, usec, 1, (sd_event_time_handler_t)handler, data);
57
58     if (ret < 0)
59     {
60         HMI_ERROR("Colud't set timer");
61     }
62
63     return ret;
64 }
65
66 static void updateTimer(sd_event_source *src, uint64_t usec)
67 {
68    sd_event_source_set_time(src, usec);
69    sd_event_source_set_enabled(src, SD_EVENT_ONESHOT);
70 }
71
72 static void stopEvent(sd_event_source *src)
73 {
74     int ret = sd_event_source_set_enabled(src, SD_EVENT_OFF);
75     if (ret < 0)
76     {
77         HMI_ERROR("Not set SD_EVENT_OFF (%s)", strerror(-ret));
78     }
79     sd_event_source_unref(src);
80 }
81
82 static int onIoEventReceive(sd_event_source *src, int fd, uint32_t revents, void * data)
83 {
84     WMConnection *p_wmcon = (WMConnection*)data;
85
86     json_object *j_out[10];
87         int j_cnt;
88     int ret = p_wmcon->receive(j_out, &j_cnt, fd);
89     if (0 > ret)
90     {
91         return 0;
92     }
93
94         for(int i = 0; i < j_cnt; i++)
95         {
96                 const char* rq = jh::getStringFromJson(j_out[i], "req");
97                 const char* id = jh::getStringFromJson(j_out[i], "appid");
98                 const char* dn = jh::getStringFromJson(j_out[i], "drawing_name");
99                 const char* da = jh::getStringFromJson(j_out[i], "drawing_area");
100                 
101                 HMI_DEBUG("req:%s appid:%s, drawing_name:%s, drawing_area:%s", rq, id, dn, da);
102
103                 // Callback
104                 p_wmcon->callOnReceivedHandler(j_out[i]);
105         }
106
107     return 0;
108 }
109
110 static int onIoEventAccept(sd_event_source *src, int fd, uint32_t revents, void * data)
111 {
112     WMConnection *p_wmcon = (WMConnection*)data;
113
114     p_wmcon->serverAccept(fd);
115
116     return 0;
117 }
118
119 static int onIoEventConnected(sd_event_source *src, int fd, uint32_t revents, void * data)
120 {
121     WMConnection *p_wmcon = (WMConnection*)data;
122
123     int ret = p_wmcon->connectedToServer(fd);
124
125     if (ret == 0)
126     {
127         stopEvent(src);
128
129         ret = sd_event_add_io(afb_daemon_get_event_loop(), nullptr,
130                           fd, EPOLLIN, onIoEventReceive, p_wmcon);
131     }
132
133     return ret;
134 }
135
136 static int sleepTimerHandler(sd_event_source *s, uint64_t usec, void *userdata)
137 {
138     WMConnection *p_wmcon = (WMConnection*)userdata;
139
140     int ret = p_wmcon->connectToEcu();
141
142     return ret;
143 }
144
145 static void limitTimerHandler(sd_event_source *s, uint64_t usec, void *userdata)
146 {
147     WMConnection *p_wmcon = (WMConnection*)userdata;
148
149     p_wmcon->connectionTimeLimit();
150 }
151
152 } // namespace
153
154 WMConnection::WMConnection()
155 {
156     this->end_init = false;
157
158     //Load timeout config file
159     this->loadTimeoutConfigFile();
160
161     // Load connection config file
162     this->loadConnectionConfigFile();
163
164     // TODO: ECU name should be decide by config file
165     this->ecu_name = this->mode;
166 }
167
168 int WMConnection::initialize()
169 {
170     int ret;
171     uint64_t sleepTime, limitTime;
172
173     // Initialize for Master/Slave
174     ret = this->initializeServer();
175
176     sleepTime = getNextTimerTime(this->sleep);
177
178     if (sleepTime <= 0)
179     {
180         HMI_ERROR("Cloud't get Next Timer");
181         goto connection_init_error;
182     }
183
184     ret = setTimer(&g_sleep_timer_src, sleepTime, (void *)sleepTimerHandler, this);
185     sd_event_source_set_enabled(g_sleep_timer_src, SD_EVENT_OFF);
186
187     limitTime = getNextTimerTime(this->times);
188
189     if (limitTime <= 0)
190     {
191         HMI_ERROR("Cloud't get Next Timer");
192         goto connection_init_error;
193     }
194
195     ret = setTimer(&g_limit_timer_src, limitTime, (void *)limitTimerHandler, this);
196
197     this->connectToEcu();
198
199     return ret;
200
201
202 connection_init_error:
203     HMI_ERROR("Connection Initialize Failed");
204     return -1;
205 }
206
207 void WMConnection::registerCallback(ReceivedHandler on_received)
208 {
209     this->onReceived = on_received;
210 }
211
212 int WMConnection::sendRequest(char const *req, char const *appid,
213                               char const *drawing_name, char const *drawing_area)
214 {
215     int ret;
216     json_object *j_obj = json_object_new_object();
217     json_object_object_add(j_obj, "req",          json_object_new_string(req));
218     json_object_object_add(j_obj, "appid",        json_object_new_string(appid));
219     json_object_object_add(j_obj, "drawing_name", json_object_new_string(drawing_name));
220     json_object_object_add(j_obj, "drawing_area", json_object_new_string(drawing_area));
221
222     std::string ecu_name = getAppIdToEcuName(appid);
223
224     HMI_DEBUG("send ecu_name %s", ecu_name.c_str());
225
226     ret = this->send(j_obj, ecu_name);
227
228     json_object_put(j_obj);
229
230     return ret;
231 }
232
233 int WMConnection::send(struct json_object* j_in, std::string ecu_name)
234 {
235     SocketInfo *socketData = &this->wm_socket[ecu_name];
236
237     // Convert json_object to string to send
238     const char *buf = json_object_to_json_string(j_in);
239     if (nullptr == buf)
240     {
241         HMI_ERROR("Failed to convert json_object to string");
242         return -1;
243     }
244
245     int len = strlen(buf);
246
247     HMI_DEBUG("Send data(len:%d): %s", len, buf);
248
249     int n = write(socketData->connectedSocket(), buf, len);
250     if(0 > n)
251     {
252         HMI_ERROR("Failed to send data (%s)", strerror(errno));
253         return -1;
254     }
255
256     return 0;
257 }
258
259 bool WMConnection::isRemoteArea(const char* area)
260 {
261     if (nullptr == area)
262     {
263         return false;
264     }
265
266     std::string str_area = std::string(area);
267     if ("" == str_area)
268     {
269         return false;
270     }
271
272     std::vector<std::string> elements;
273     elements = parseString(str_area, '.');
274
275     for (auto itr = this->wm_socket.begin(); itr != this->wm_socket.end(); ++itr)
276     {
277         if (itr->first == elements[0])
278         {
279             if (itr->first != this->ecu_name)
280             {
281                 return true;
282             }
283             else
284             {
285                 return false;
286             }
287         }
288     }
289
290     return false;
291 }
292
293 bool WMConnection::isRemoteEcu(std::string appid)
294 {
295     std::string appToEcuName = this->getAppIdToEcuName(appid);
296
297     if (appToEcuName == this->getEcuName() || appToEcuName == "")
298     {
299         return false;
300     }
301     else
302     {
303         return true;
304     }
305 }
306
307 bool WMConnection::isConnecting(std::string ecu_name)
308 {
309     return (0 > this->wm_socket[ecu_name].connectedSocket()) ? false : true;
310 }
311
312 bool WMConnection::isConnectionMode()
313 {
314     return (Mode_Connection == this->wm_mode) ? true : false;
315 }
316
317 std::string WMConnection::parseMasterArea(const char* area)
318 {
319     std::string ret_area = "";
320     std::vector<std::string> elements;
321     elements = parseString(std::string(area), '.');
322
323     if ("master" != elements[0])
324     {
325         return std::string(area);
326     }
327
328     for (auto itr = (elements.begin() + 1); itr != elements.end(); ++itr)
329     {
330         ret_area += *itr;
331
332         if ((elements.end() - 1) != itr)
333         {
334             ret_area += ".";
335         }
336     }
337     return ret_area;
338 }
339
340 bool WMConnection::isSyncDrawingForRemote(const char* appid)
341 {
342     if (std::string(appid) == this->syndDrawingAppId)
343     {
344         return true;
345     }
346     else
347     {
348         return false;
349     }
350 }
351
352 void WMConnection::startSyncDrawForRemote(const char* appid)
353 {
354     this->syndDrawingAppId = std::string(appid);
355 }
356
357 void WMConnection::finishSyncDrawForRemote(const char* appid)
358 {
359     if (std::string(appid) == this->syndDrawingAppId)
360     {
361         this->syndDrawingAppId = "";
362     }
363 }
364
365 std::string WMConnection::getAreaToEcuName(const char* area)
366 {
367     std::string result;
368     std::string str_area = std::string(area);
369
370     if (str_area.find('.') != std::string::npos)
371     {
372         std::vector<std::string> elements;
373         elements = parseString(str_area, '.');
374         result = elements[0];
375     }
376     else
377     {
378         result = str_area;
379     }
380
381     return result;
382 }
383
384 std::string WMConnection::getSocketToEcuName(int socket)
385 {
386     for (auto itr = this->wm_socket.begin(); itr != this->wm_socket.end(); ++itr)
387     {
388         if (socket == itr->second.connectedSocket())
389         {
390             return itr->first;
391         }
392     }
393
394     return "";
395 }
396
397 std::string WMConnection::getMySocketToEcuName(int socket)
398 {
399     for (auto itr = this->wm_socket.begin(); itr != this->wm_socket.end(); ++itr)
400     {
401         if (socket == itr->second.mySocket())
402         {
403             return itr->first;
404         }
405     }
406
407     return "";
408 }
409
410 std::string WMConnection::getAppIdToEcuName(std::string appid)
411 {
412     if (appid2ecuName.count(appid) == 1)
413     {
414         return this->appid2ecuName[appid];
415     }
416     else
417     {
418         return "";
419     }
420 }
421
422 std::string WMConnection::getIpToEcuName(std::string ip)
423 {
424     for (auto itr = this->wm_socket.begin(); itr != this->wm_socket.end(); ++itr)
425     {
426         if (ip == itr->second.ip())
427         {
428             return itr->first;
429         }
430     }
431
432     return "";
433 }
434
435 void WMConnection::setAppIdToEcuName(std::string appid, std::string ecu_name)
436 {
437     this->appid2ecuName[appid] = ecu_name;
438 }
439
440 void WMConnection::setAppIdToReceivedEcuName(std::string appid)
441 {
442     this->appid2ecuName[appid] = received_ecu_name;
443 }
444
445 std::string WMConnection::getEcuName()
446 {
447     return this->ecu_name;
448 }
449
450 bool WMConnection::getEndInit()
451 {
452     return this->end_init;
453 }
454
455 int WMConnection::getSleepTime()
456 {
457     return this->sleep;
458 }
459
460 void WMConnection::callOnReceivedHandler(json_object *j_out)
461 {
462     this->onReceived(j_out);
463 }
464
465 int WMConnection::initializeServer()
466 {
467     int ret = 0;
468     struct sockaddr_in addr;
469
470     SocketInfo *socketData = &this->wm_socket[this->ecu_name];
471
472     // Create socket
473     socketData->setMySocket(socket(AF_INET, SOCK_STREAM, 0));
474     if (0 > socketData->mySocket())
475     {
476         HMI_ERROR("Failed to create socket (%s)", strerror(errno));
477         return -1;
478     }
479
480     socketData->setConnectedSocket(socketData->mySocket());
481
482     // Bind socket
483     addr.sin_family = AF_INET;
484     addr.sin_port = htons(socketData->wmPort());
485     addr.sin_addr.s_addr = htonl(INADDR_ANY);
486
487     ret = bind(socketData->mySocket(), (struct sockaddr *)&addr, sizeof(addr));
488     if (0 > ret)
489     {
490         HMI_ERROR("Failed to bind socket (%s)", strerror(errno));
491         return -1;
492     }
493
494     // Listen connection
495     ret = listen(socketData->mySocket(), 1);
496     if (0 > ret)
497     {
498         HMI_ERROR("Failed to listen connection (%s)", strerror(errno));
499         return -1;
500     }
501
502     // Register callback to accept connection
503     ret = sd_event_add_io(afb_daemon_get_event_loop(), nullptr,
504                           socketData->mySocket(), EPOLLIN,
505                           onIoEventAccept, this);
506     if (0 > ret)
507     {
508         HMI_ERROR("Failed to add I/O event accept(%s)", strerror(-ret));
509         return -1;
510     }
511
512     return ret;
513 }
514
515 int WMConnection::initializeClient(std::string ecu_name)
516 {
517     SocketInfo *socketData = &this->wm_socket[ecu_name];
518
519     if (socketData->mySocket() != -1)
520     {
521         close(socketData->mySocket());
522     }
523
524     // Create socket
525     int my_socket = socket(AF_INET, SOCK_STREAM, 0);
526     if (0 > my_socket)
527     {
528         HMI_ERROR("Failed to create socket (%s)", strerror(errno));
529         return -1;
530     }
531
532     socketData->setMySocket(my_socket);
533
534     return 0;
535 }
536
537 int WMConnection::connectToEcu()
538 {
539     int cnt = 0;
540
541     HMI_DEBUG("Start Connection");
542
543     if (this->wm_socket.empty())
544     {
545         HMI_DEBUG("Connection destination is not written to connection.json");
546         stopEvent(g_limit_timer_src);
547         stopEvent(g_sleep_timer_src);
548
549         this->end_init = true;
550         this->wm_mode = Mode_Standalone;
551
552         return 0;
553     }
554
555     for (auto itr = this->wm_socket.begin(); itr != this->wm_socket.end(); ++itr)
556     {
557         std::string ecu_name = itr->first;
558         HMI_DEBUG("ECU Names %s", ecu_name.c_str());
559
560         if (itr->second.connectedSocket() != -1 || itr->first == this->ecu_name)
561         {
562             cnt++;
563             HMI_DEBUG("Already Connected");
564             continue;
565         }
566
567         if (itr->second.masterMode())
568         {
569             HMI_DEBUG("Try Connection");
570             connectToServer(ecu_name);
571         }
572
573         HMI_DEBUG("Wait Connection");
574
575     }
576
577     if (cnt == (int)this->wm_socket.size())
578     {
579         HMI_DEBUG("All Connected!!");
580
581         stopEvent(g_sleep_timer_src);
582         stopEvent(g_limit_timer_src);
583
584         this->end_init = true;
585         this->wm_mode = Mode_Connection;
586
587         return 0;
588     }
589
590     uint64_t sleepTime = getNextTimerTime(this->sleep);
591     updateTimer(g_sleep_timer_src, sleepTime);
592
593     return 0;
594 }
595
596 void WMConnection::connectionTimeLimit()
597 {
598     HMI_DEBUG("Time Limit");
599
600     stopEvent(g_sleep_timer_src);
601     stopEvent(g_limit_timer_src);
602
603     this->wm_socket[this->ecu_name].setConnectedSocket(-1);
604     this->wm_mode = Mode_Standalone;
605
606     for (auto itr = this->wm_socket.begin(); itr != this->wm_socket.end(); ++itr)
607     {
608         if (itr->second.connectedSocket() != -1)
609         {
610             HMI_DEBUG("Connection Mode");
611             this->wm_mode = Mode_Connection;
612         }
613         else
614         {
615             close(itr->second.mySocket());
616         }
617     }
618
619     if (this->wm_mode == Mode_Standalone)
620     {
621         close(this->wm_socket[this->ecu_name].mySocket());
622     }
623
624     this->end_init = true;
625 }
626
627 int WMConnection::connectToServer(std::string ecu_name)
628 {
629     int ret = 0;
630     struct sockaddr_in addr;
631
632     this->initializeClient(ecu_name);
633
634     SocketInfo *socketData = &wm_socket[ecu_name];
635
636     // Connect to master
637     addr.sin_family = AF_INET;
638     addr.sin_port = htons(socketData->wmPort());
639     addr.sin_addr.s_addr = inet_addr(socketData->ip().c_str());
640
641     connect(socketData->mySocket(), (struct sockaddr *)&addr, sizeof(addr));
642
643     ret = sd_event_add_io(afb_daemon_get_event_loop(), nullptr,
644                         socketData->mySocket(), EPOLLOUT,
645                         onIoEventConnected, this);
646
647     if (0 > ret)
648     {
649         HMI_ERROR("Failed to add I/O event receive(%s)", strerror(-ret));
650         return -1;
651     }
652
653     return ret;
654 }
655
656 int WMConnection::connectedToServer(int socket)
657 {
658     int ret;
659
660     struct sockaddr_in addr;
661     socklen_t addr_len = sizeof(addr);
662
663     std::string ecu_name = getMySocketToEcuName(socket);
664
665     ret = getpeername(socket, (struct sockaddr*)&addr, &addr_len);
666
667     if (ret != 0)
668     {
669         HMI_DEBUG("Failed to connect %s (%s)", ecu_name.c_str(), strerror(errno));
670         return -1;
671     }
672
673     HMI_DEBUG("Connected to %s", ecu_name.c_str());
674
675     SocketInfo *socketData = &this->wm_socket[ecu_name];
676
677     // Store connected socket
678     socketData->setConnectedSocket(socket);
679
680     return 0;
681 }
682
683 int WMConnection::serverAccept(int socket)
684 {
685     struct sockaddr_in addr;
686
687     // Accept connection
688     socklen_t len = sizeof(addr);
689     int my_socket = this->wm_socket[this->getEcuName()].mySocket();
690     int connected_socket = accept(my_socket, (struct sockaddr *)&addr, &len);
691     if (0 > connected_socket)
692     {
693         HMI_ERROR("Failed to accept connection (%s)", strerror(errno));
694         return -1;
695     }
696
697     std::string ip = inet_ntoa(addr.sin_addr);
698     std::string ecu_name = getIpToEcuName(ip);
699
700     SocketInfo *socketData = &this->wm_socket[ecu_name];
701
702     // Store connected socket
703     socketData->setConnectedSocket(connected_socket);
704
705     // Register callback to receive
706     int ret = sd_event_add_io(afb_daemon_get_event_loop(), nullptr,
707                           connected_socket, EPOLLIN,
708                           onIoEventReceive, this);
709     if (0 > ret)
710     {
711         HMI_ERROR("Failed to add I/O event receive(%s)", strerror(-ret));
712         return -1;
713     }
714
715     return 0;
716 }
717
718 int WMConnection::receive(json_object** j_out, int *j_cnt, int socket)
719 {
720     char buf[1024] = {};
721     int n;
722
723     n = read(socket, buf, sizeof(buf));
724     if(0 > n)
725     {
726         HMI_ERROR("Failed to receive data (%s)", strerror(errno));
727         return -1;
728     }
729
730     HMI_DEBUG("Received data length: %d", n);
731     HMI_DEBUG("Received data: %s", buf);
732
733         // Parse received data
734         struct json_tokener *tokener = json_tokener_new();
735         int cnt = 0;
736
737         while (n >= tokener->char_offset)
738         {
739         j_out[cnt] = json_tokener_parse_ex(tokener, &buf[tokener->char_offset], n);
740                 
741                 if (nullptr == j_out[cnt]) 
742                 {
743                         break;
744                 }
745
746                 cnt++;
747         }
748
749         *j_cnt = cnt;
750         json_tokener_free(tokener);
751
752     this->received_ecu_name = this->getSocketToEcuName(socket);
753     HMI_DEBUG("received ecu name %s", this->received_ecu_name.c_str());
754
755     return 0;
756 }
757
758 int WMConnection::loadTimeoutConfigFile()
759 {
760     // Get afm application installed dir
761     char const *afm_app_install_dir = getenv("AFM_APP_INSTALL_DIR");
762     if (!afm_app_install_dir)
763     {
764         HMI_ERROR("AFM_APP_INSTALL_DIR is not defined");
765     }
766     std::string path = std::string(afm_app_install_dir) + std::string(kPathTimeoutConfigFile);
767
768     // Load connection config file
769     json_object *json_obj;
770     int ret = jh::inputJsonFilie(path.c_str(), &json_obj);
771     if (0 > ret)
772     {
773         HMI_ERROR("Could not open %s, so use default timeout", path.c_str());
774         this->times = kDefaultTimes;
775         this->sleep = kDefaultSleep;
776         return 0;
777     }
778     HMI_DEBUG("json_obj dump:%s", json_object_get_string(json_obj));
779
780     int times = jh::getIntFromJson(json_obj, "times");
781     this->times = (0 != times) ? times : kDefaultTimes;
782
783     int sleep = jh::getIntFromJson(json_obj, "sleep");
784     this->sleep = (0 != sleep) ? sleep : kDefaultSleep;
785
786     // Release json_object
787     json_object_put(json_obj);
788
789     return 0;
790 }
791
792 int WMConnection::loadConnectionConfigFile()
793 {
794     // Get afm application installed dir
795     char const *afm_app_install_dir = getenv("AFM_APP_INSTALL_DIR");
796     if (!afm_app_install_dir)
797     {
798         HMI_ERROR("AFM_APP_INSTALL_DIR is not defined");
799     }
800     std::string path = std::string(afm_app_install_dir) + std::string(kPathConnectionConfigFile);
801
802     // Load connection config file
803     json_object *json_obj, *json_cfg;
804     int ret = jh::inputJsonFilie(path.c_str(), &json_obj);
805     if (0 > ret)
806     {
807         HMI_ERROR("Could not open %s, so use default mode \"slave\"", kPathConnectionConfigFile);
808         this->wm_socket["slave"] = SocketInfo("slave", kDefaultIpAddr, kDefaultPort, false);
809         return 0;
810     }
811     HMI_DEBUG("json_obj dump:%s", json_object_get_string(json_obj));
812
813     const char* screen_name = jh::getStringFromJson(json_obj, "screen_name");
814     this->mode = (nullptr != screen_name) ? screen_name : "slave";
815
816     int wm_port = jh::getIntFromJson(json_obj, "wm_port");
817
818     this->wm_socket[screen_name] = SocketInfo(screen_name, "", wm_port, true);
819
820     // Check
821     HMI_DEBUG("screen_name:%s wm_port:%d", screen_name, wm_port);
822
823         if (!json_object_object_get_ex(json_obj, "connections", &json_cfg))
824         {
825                 HMI_ERROR("connection.json Parse Error!!");
826                 return 0;
827         }
828
829         int len = json_object_array_length(json_cfg);
830
831         for (int i = 0; i < len; i++)
832         {
833                 json_object *json_conn = json_object_array_get_idx(json_cfg, i);
834
835                 std::string screen_name = jh::getStringFromJson(json_conn, "screen_name");
836                 std::string ip = jh::getStringFromJson(json_conn, "ip");
837                 int wm_port = jh::getIntFromJson(json_conn, "wm_port");
838         bool master_mode = jh::getBoolFromJson(json_conn, "master_mode");
839
840         this->wm_socket[screen_name] = SocketInfo(screen_name, ip, wm_port, master_mode);
841
842         HMI_DEBUG("screen_name:%s ip:%s port:%d server_mode:%s", screen_name.c_str(),
843                 ip.c_str(), wm_port, (master_mode ? "true" : "false"));
844         }
845
846     // Release json_object
847     json_object_put(json_obj);
848
849     return 0;
850 }
851
852 uint64_t WMConnection::getNextTimerTime(uint64_t msec)
853 {
854     struct timespec ts;
855
856     if (clock_gettime(CLOCK_BOOTTIME, &ts) != 0)
857     {
858         HMI_ERROR("Could't set time (clock_gettime() returns with error");
859         return -1;
860     }
861
862     uint64_t timer_nsec = ((ts.tv_sec  * 1000000000ULL) + (ts.tv_nsec) + (msec * 1000000));
863
864     if (!timer_nsec)
865     {
866         HMI_ERROR("Second is 0");
867         return -1;
868     }
869
870     return timer_nsec / 1000;
871 }
872
873 } // namespace wm