remove hard coded path into CMake files
[profile/ivi/ico-vic-amb-plugin.git] / src / controlwebsocket.cc
1 /**
2  * Copyright (C) 2012  TOYOTA MOTOR CORPORATION.
3  * 
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  * 
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  * 
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
17  * 
18  */
19 #include <pthread.h>
20 #include <string.h>
21
22 #include <algorithm>
23 #include <sstream>
24
25 #include "debugout.h"
26
27 #include "controlwebsocket.h"
28 #include "mwinterface.h"
29 #include "standardmessage.h"
30
31 /**
32  * Socket ID generated class.
33  */
34 template<class T>
35     class GenerateCommID {
36     public:
37         /**
38          * This function retrieves an instance of the class.
39          *
40          * @return Instance of GenerateCommID
41          */
42         static GenerateCommID *
43         getInstance()
44         {
45             static GenerateCommID<T> instance;
46             return &instance;
47         }
48
49         /**
50          * This function returns the ID that is registered.
51          * If the ID is not registerd, it register the ID.
52          *
53          * @param value Value of socket.
54          * @return ID
55          */
56         int
57         getID(T value, int key)
58         {
59             pthread_mutex_lock(&mutex);
60             for (auto itr = commidmap.begin(); itr != commidmap.end(); itr++) {
61                 if ((void*)(*itr).second == (void*)value) {
62                     pthread_mutex_unlock(&mutex);
63                     return (*itr).first;
64                 }
65             }
66             int newid = key;
67             if (newid == -1) {
68                 newid = generateID();
69             }
70             commidmap.insert(make_pair(newid, value));
71             pthread_mutex_unlock(&mutex);
72             return newid;
73         }
74         /**
75          * This function returns the socket information registered.
76          *
77          * @param id Socket ID
78          * @return Value of socket
79          */
80         T
81         getValue(int id)
82         {
83             pthread_mutex_lock(&mutex);
84             if (commidmap.find(id) == commidmap.end()) {
85                 pthread_mutex_unlock(&mutex);
86                 return NULL;
87             }
88             pthread_mutex_unlock(&mutex);
89             return commidmap[id];
90         }
91
92         /**
93          * This function removes the socket information registered.
94          *
95          * @param id Socket ID
96          * @return Success : true Failure : false
97          */
98         bool
99         unsetID(int id)
100         {
101             pthread_mutex_lock(&mutex);
102             bool ret = false;
103             auto itr = commidmap.find(id);
104             if (itr != commidmap.end()) {
105                 itr = commidmap.erase(itr);
106                 ret = true;
107             }
108             pthread_mutex_unlock(&mutex);
109             return ret;
110         }
111     private:
112         GenerateCommID() :
113                 mutex(PTHREAD_MUTEX_INITIALIZER)
114         {
115         }
116
117         ~GenerateCommID()
118         {
119             commidmap.clear();
120         }
121
122         GenerateCommID(const GenerateCommID &)
123         {
124         }
125
126         const GenerateCommID&
127         operator =(const GenerateCommID &)
128         {
129         }
130
131         int
132         generateID()
133         {
134             if (commidmap.empty()) {
135                 return 1;
136             }
137             int count = 1;
138             while (commidmap.find(count) == commidmap.end()) {
139                 count++;
140             }
141             return count;
142         }
143
144         std::map<int, T> commidmap;
145         pthread_mutex_t mutex;
146     };
147
148 ControlWebsocket::ControlWebsocket()
149 {
150     mutex = PTHREAD_MUTEX_INITIALIZER;
151 }
152
153 ControlWebsocket::~ControlWebsocket()
154 {
155     socketmap.clear();
156     pollfds.clear();
157 }
158
159 bool
160 ControlWebsocket::initialize(int port, enum ServerProtocol stype, MWIF *mwif_)
161 {
162     type = stype;
163     DebugOut(10) << "ControlWebsocket[" << type << "]" << " initialize.(" << port
164                << ")\n";
165     stringstream address, protocol;
166     address.str("");
167     protocol.str("");
168     address << ":" << port;
169     switch (type) {
170     case DATA_STANDARD:
171     {
172         protocol << "standarddatamessage-only";
173         break;
174     }
175     case CONTROL_STANDARD:
176     {
177         protocol << "standardcontrolmessage-only";
178         break;
179     }
180     case DATA_CUSTOM:
181     {
182         protocol << "customdatamessage-only";
183         break;
184     }
185     case CONTROL_CUSTOM:
186     {
187         protocol << "customcontrolmessage-only";
188         break;
189     }
190     default:
191     {
192         return false;
193     }
194     }
195
196     context = ico_uws_create_context(address.str().c_str(),
197                                      protocol.str().c_str());
198     if (context == NULL) {
199         DebugOut(10) << "ControlWebsocket[" << type << "]"
200                    << " couldn't create libwebsockets_context." << std::endl;
201         return false;
202     }
203     mwif = mwif_;
204     container.ctrlws = this;
205     container.mwif = mwif;
206     container.type = type;
207     if (ico_uws_set_event_cb(context, ControlWebsocket::callback_receive,
208                              (void*)&container) != 0) {
209         DebugOut(10) << "ControlWebsocket[" << type << "]"
210                    << " couldn't set callback function." << std::endl;
211         return false;
212     }
213     if (pthread_create(&threadid, NULL, ControlWebsocket::run, (void*)this)
214             == -1) {
215         ico_uws_close(context);
216         DebugOut(10) << "ControlWebsocket[" << type << "]"
217                    << " couldn't create thread." << std::endl;
218         return false;
219     }
220     return true;
221 }
222
223 bool
224 ControlWebsocket::send(int commid, char *keyeventtype, timeval time, void *data,
225                        size_t len)
226 {
227     DebugOut(10) << "ControlWebsocket[" << type << "]" << " send data(" << commid
228                << "," << keyeventtype << ") len = " << len << std::endl;
229     void *wsi = NULL;
230     if (socketmap.find(commid) == socketmap.end()) {
231         if (!registSocket(commid)) {
232             DebugOut(10) << "ControlWebsocket[" << type << "]"
233                        << " can't regist socket(" << commid << ")" << std::endl;
234             return false;
235         }
236     }
237     wsi = socketmap[commid];
238
239     if (wsi == NULL) {
240         DebugOut(10) << "ControlWebsocket Get websocket object is NULL."
241                    << std::endl;
242         return false;
243     }
244     pthread_mutex_lock(&mutex);
245     memset(buf, 0, sizeof(buf));
246     memcpy(buf,
247            datamsg.encode(keyeventtype, time,
248                           *(reinterpret_cast<DataOpt*>(data))),
249                           len);
250     DebugOut(10) << "ControlWebsocket Send Data[" << keyeventtype << "]"
251                << std::endl;
252     ico_uws_send(context, wsi, reinterpret_cast<unsigned char*>(buf), len);
253     pthread_mutex_unlock(&mutex);
254     return true;
255 }
256
257 bool
258 ControlWebsocket::receive(int commid, char *keyeventtype, timeval recordtime,
259                           void *data, size_t len)
260 {
261     DebugOut(10) << "ControlWebsocket[" << type << "]" << " receive message("
262                << commid << "," << keyeventtype << ")\n";
263     switch (type) {
264     case DATA_STANDARD:
265     case DATA_CUSTOM:
266     {
267         datamsg.decodeOpt(keyeventtype, recordtime, data);
268         DataOpt dop = datamsg.getDataOpt();
269         mwif->recvMessage(SET, commid, keyeventtype, recordtime, (void*)&dop,
270                           len);
271         break;
272     }
273     case CONTROL_STANDARD:
274     case CONTROL_CUSTOM:
275     {
276         eventmsg.decodeOpt(keyeventtype, recordtime, data);
277         EventOpt opt = eventmsg.getEventOpt();
278         if (opt.common == -1 && opt.sense == -1) {
279             mwif->recvMessage(GET, commid, keyeventtype, recordtime,
280                               (void*)&opt, len);
281         }
282         else {
283             mwif->recvMessage(CALLBACK, commid, keyeventtype, recordtime,
284                               (void*)&opt, len);
285         }
286         break;
287     }
288     default:
289     {
290         return false;
291     }
292     }
293     return true;
294 }
295
296 bool
297 ControlWebsocket::receive(int commid, char *data, size_t len)
298 {
299     switch (type) {
300     case DATA_STANDARD:
301     case DATA_CUSTOM:
302     {
303         datamsg.decode(data, len);
304         DataOpt dop = datamsg.getDataOpt();
305         mwif->recvMessage(SET, commid, datamsg.getKeyEventType(), datamsg.getRecordtime(), (void*)&dop,
306                           len);
307         break;
308     }
309     case CONTROL_STANDARD:
310     case CONTROL_CUSTOM:
311     {
312         eventmsg.decode(data, len);
313         EventOpt opt = eventmsg.getEventOpt();
314         if (opt.common == -1 && opt.sense == -1) {
315             mwif->recvMessage(GET, commid, eventmsg.getKeyEventType(), eventmsg.getRecordtime(),
316                               (void*)&opt, len);
317         }
318         else {
319             mwif->recvMessage(CALLBACK, commid, eventmsg.getKeyEventType(), eventmsg.getRecordtime(),
320                               (void*)&opt, len);
321         }
322         break;
323     }
324     default:
325     {
326         return false;
327     }
328     }
329     return true;
330 }
331
332 void
333 ControlWebsocket::observation()
334 {
335     int ret;
336     while (true) {
337         ret = poll(&pollfds[0], pollfds.size(), -1);
338         if (ret < 0) {
339             DebugOut(10) << "Error: poll(" << strerror(errno) << ")\n";
340             continue;
341         }
342         for (int i = 0; i < static_cast<int>(pollfds.size()); i++) {
343             if (pollfds[i].revents & POLLERR) {
344                 DebugOut(10) << "socket(" << pollfds[i].fd << ") is POLLERR.\n";
345                 break;
346             }
347         }
348         ico_uws_service(context);
349     }
350 }
351
352 bool
353 ControlWebsocket::registSocket(int commid)
354 {
355     DebugOut(10) << "socketmap[" << type << "]!!\n" << std::flush;
356     GenerateCommID<void*> *idserver = GenerateCommID<void*>::getInstance();
357     if (idserver->getValue(commid) != NULL) {
358         socketmap[commid] = idserver->getValue(commid);
359         pollfd fds;
360         fds.fd = commid;
361         fds.events = POLLIN | POLLERR;
362         pollfds.push_back(fds);
363         return true;
364     }
365     return false;
366 }
367
368 bool
369 ControlWebsocket::unregistSocket(int commid)
370 {
371     if (socketmap.find(commid) == socketmap.end()) {
372         return false;
373     }
374     socketmap.erase(commid);
375     for (auto itr = pollfds.begin(); itr != pollfds.end(); itr++) {
376         if ((*itr).fd == commid) {
377             itr = pollfds.erase(itr);
378             break;
379         }
380     }
381     GenerateCommID<void*> *idserver = GenerateCommID<void*>::getInstance();
382     return idserver->unsetID(commid);
383 }
384
385 void
386 ControlWebsocket::callback_receive(const struct ico_uws_context *context,
387                                    const ico_uws_evt_e event, const void *id,
388                                    const ico_uws_detail *detail,
389                                    void *user_data)
390 {
391     user_datacontainer *container = static_cast<user_datacontainer*>(user_data);
392     switch (event) {
393     case ICO_UWS_EVT_OPEN:
394         break;
395     case ICO_UWS_EVT_ERROR:
396         break;
397     case ICO_UWS_EVT_CLOSE:
398         break;
399     case ICO_UWS_EVT_RECEIVE:
400     {
401         DebugOut(10) << "ControlWebsocket Start callback_recevie"
402                      << " Receive message.\n";
403         GenerateCommID<void*> *idserver = GenerateCommID<void*>::getInstance();
404         int commid = idserver->getID(const_cast<void*>(id), -1);
405         StandardMessage msg;
406         char *buf = reinterpret_cast<char*>(detail->_ico_uws_message.recv_data);
407         if (strcmp(&buf[0], "VELOCITY") == 0) {
408             static uint16_t prevspd = -1;
409             static const uint16_t unusablespd = -1;
410             uint16_t spd = 0;
411             memcpy(&spd, 
412                    buf + StandardMessage::KEYEVENTTYPESIZE + 
413                    sizeof(struct timeval) + sizeof(int), 
414                    sizeof(uint16_t));
415             if ((prevspd == unusablespd && spd > 0) || 
416                 (prevspd == 0 && spd > 0)) {
417                 DebugOut(3) << "PERF CHG_VIC_INF Receive from VIC. Message is " 
418                             << &buf[0] << ". VELOCITY is 1km/h or more.\n";
419             }
420             else if ((prevspd == unusablespd && spd == 0) || 
421                      (prevspd > 0 && spd == 0)) {
422                 DebugOut(3) << "PERF CHG_VIC_INF Receive from VIC. Message is " 
423                             << &buf[0] << ". VELOCITY is 0km/h.\n";
424             }
425             prevspd = spd;
426         }
427         container->ctrlws->receive(commid, buf, 
428                                    detail->_ico_uws_message.recv_len);
429         DebugOut(10) << "ControlWebsocket End " 
430                      << "callback_recevie Receive message.\n";
431         break;
432     }
433     case ICO_UWS_EVT_ADD_FD:
434     {
435         DebugOut(1) << "INFO CHG_VIC_INF Connected to new VIC.\n";
436         GenerateCommID<void*> *idserver = GenerateCommID<void*>::getInstance();
437         int commid = idserver->getID(const_cast<void*>(id),
438                                      detail->_ico_uws_fd.fd);
439         DebugOut(10) << "ControlWebsocket callback_receive Insert ID is "
440                    << commid << "\n";
441         container->mwif->registDestination(container->type,
442                                            detail->_ico_uws_fd.fd);
443         break;
444     }
445     case ICO_UWS_EVT_DEL_FD:
446     {
447         DebugOut(1) << "INFO CHG_VIC_INF Disconnected to VIC.\n";
448         container->mwif->unregistDestination(container->type,
449                                              detail->_ico_uws_fd.fd);
450         break;
451     }
452     default:
453         break;
454     }
455 }
456
457 void *
458 ControlWebsocket::run(void *arg)
459 {
460     ControlWebsocket *control = reinterpret_cast<ControlWebsocket*>(arg);
461     control->observation();
462     return NULL;
463 }