556ae0fb6128f98d66df63aafb0724ad727f00c9
[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 "debugout.h"
23
24 #include "controlwebsocket.h"
25 #include "mwinterface.h"
26 #include "standardmessage.h"
27
28 /**
29  * Socket ID generated class.
30  */
31 template<class T>
32     class GenerateCommID {
33     public:
34         /**
35          * This function retrieves an instance of the class.
36          *
37          * @return Instance of GenerateCommID
38          */
39         static GenerateCommID *
40         getInstance()
41         {
42             static GenerateCommID<T> instance;
43             return &instance;
44         }
45
46         /**
47          * This function returns the ID that is registered.
48          * If the ID is not registerd, it register the ID.
49          *
50          * @param value Value of socket.
51          * @return ID
52          */
53         int
54         getID(T value)
55         {
56             pthread_mutex_lock(&mutex);
57             for (auto itr = commidmap.begin(); itr != commidmap.end(); itr++) {
58                 if ((*itr).second == value) {
59                     pthread_mutex_unlock(&mutex);
60                     return (*itr).first;
61                 }
62             }
63             int newid = generateID();
64             commidmap.insert(make_pair(newid, value));
65             pthread_mutex_unlock(&mutex);
66             return newid;
67         }
68         /**
69          * This function returns the socket information registered.
70          *
71          * @param id Socket ID
72          * @return Value of socket
73          */
74         T
75         getValue(int id)
76         {
77             pthread_mutex_lock(&mutex);
78             if (commidmap.find(id) == commidmap.end()) {
79                 pthread_mutex_unlock(&mutex);
80                 return NULL;
81             }
82             pthread_mutex_unlock(&mutex);
83             return commidmap[id];
84         }
85
86         /**
87          * This function removes the socket information registered.
88          *
89          * @param id Socket ID
90          * @return Success : true Failure : false
91          */
92         bool
93         unsetID(int id)
94         {
95             pthread_mutex_lock(&mutex);
96             bool ret = false;
97             auto itr = commidmap.find(id);
98             if (itr != commidmap.end()) {
99                 itr = commidmap.erase(itr);
100                 ret = true;
101             }
102             pthread_mutex_unlock(&mutex);
103             return ret;
104         }
105     private:
106         GenerateCommID() : mutex(PTHREAD_MUTEX_INITIALIZER)
107         {
108         }
109
110         ~GenerateCommID()
111         {
112             commidmap.clear();
113         }
114
115         GenerateCommID(const GenerateCommID &)
116         {
117         }
118
119         const GenerateCommID&
120         operator =(const GenerateCommID &)
121         {
122         }
123
124         int
125         generateID()
126         {
127             if (commidmap.empty()) {
128                 return 1;
129             }
130             int count = 1;
131             for (auto itr = commidmap.begin(); itr != commidmap.end(); itr++) {
132                 if (itr->first != count) {
133                     return count;
134                 }
135                 count++;
136             }
137             return count + 1;
138         }
139
140         std::map<int, T> commidmap;
141         pthread_mutex_t mutex;
142     };
143
144 MWIF *ControlWebsocket::mwif = NULL;
145
146 ControlWebsocket::ControlWebsocket()
147 {
148     mutex = PTHREAD_MUTEX_INITIALIZER;
149     protocollist[1] = {NULL, NULL, 0};
150 }
151
152 ControlWebsocket::~ControlWebsocket()
153 {
154     socketmap.clear();
155 }
156
157 bool
158 ControlWebsocket::initialize(int port, enum ServerProtocol stype)
159 {
160     DebugOut() << "ControlWebsocket[" << type << "]" << " initialize.(" << port
161                << ")\n";
162     type = stype;
163     switch (type) {
164     case DATA_STANDARD:
165     {
166         protocollist[0] = {"standarddatamessage-only", ControlWebsocket::callback_receive, 0};
167         break;
168     }
169     case CONTROL_STANDARD : {
170         protocollist[0] = {"standardcontrolmessage-only", ControlWebsocket::callback_receive, 0};
171         break;
172     }
173     case DATA_CUSTOM : {
174         protocollist[0] = {"customdatamessage-only", ControlWebsocket::callback_receive, 0};
175         break;
176     }
177     case CONTROL_CUSTOM : {
178         protocollist[0] = {"customcontrolmessage-only", ControlWebsocket::callback_receive, 0};
179         break;
180     }
181     default : {
182         return false;
183     }
184 }
185     context = libwebsocket_create_context(port, "lo", protocollist,
186                                           libwebsocket_internal_extensions,
187                                           NULL, NULL, -1, -1, 0);
188     if (context == NULL) {
189         DebugOut() << "ControlWebsocket[" << type << "]" 
190                    << " couldn't create libwebsockets_context." << std::endl;
191         return false;
192     }
193     if (pthread_create(&threadid, NULL, ControlWebsocket::run, (void*)this)
194         == -1) {
195         libwebsocket_context_destroy(context);
196         DebugOut() << "ControlWebsocket[" << type << "]" 
197                    << " couldn't create thread." << std::endl;
198         return false;
199     }
200     return true;
201 }
202
203 bool
204 ControlWebsocket::send(int commid, char *keyeventtype, timeval time, void *data,
205                        size_t len)
206 {
207     DebugOut() << "ControlWebsocket[" << type << "]" << " send data(" << commid
208                << "," << keyeventtype << ") len = " << len << std::endl;
209     libwebsocket *wsi = NULL;
210     if (socketmap.find(commid) == socketmap.end()) {
211         if (!registSocket(commid)) {
212             DebugOut() << "ControlWebsocket[" << type << "]" 
213                        << " can't regist socket(" << commid << ")" 
214                        << std::endl;
215             return false;
216         }
217     }
218     wsi = socketmap[commid];
219
220     if (wsi == NULL) {
221         DebugOut() << "ControlWebsocket Get websocket object is NULL."
222                    << std::endl;
223         return false;
224     }
225     pthread_mutex_lock(&mutex);
226     memset(buf, 0, sizeof(buf));
227     memcpy(buf + LWS_SEND_BUFFER_PRE_PADDING,
228            datamsg.encode(keyeventtype, time,
229                           *(reinterpret_cast<DataOpt*>(data))),
230            len);
231     DebugOut() << "ControlWebsocket Send Data[" << keyeventtype << "]"
232                << std::endl;
233     libwebsocket_write(
234             wsi,
235             reinterpret_cast<unsigned char*>(buf + LWS_SEND_BUFFER_PRE_PADDING),
236             len, LWS_WRITE_BINARY);
237     pthread_mutex_unlock(&mutex);
238     return true;
239 }
240
241 bool
242 ControlWebsocket::receive(int commid, char *keyeventtype, timeval recordtime,
243                           void *data, size_t len)
244 {
245     DebugOut() << "ControlWebsocket[" << type << "]" << " receive message("
246                << commid << "," << keyeventtype << ")\n";
247     switch (type) {
248     case DATA_STANDARD:
249     case DATA_CUSTOM:
250     {
251         datamsg.decodeOpt(keyeventtype, recordtime, data);
252         DataOpt dop = datamsg.getDataOpt();
253         mwif->recvMessage(SET, commid, keyeventtype, recordtime, (void*)&dop,
254                           len);
255         break;
256     }
257     case CONTROL_STANDARD:
258     case CONTROL_CUSTOM:
259     {
260         eventmsg.decodeOpt(keyeventtype, recordtime, data);
261         EventOpt opt = eventmsg.getEventOpt();
262         if (opt.common == -1 && opt.sense == -1) {
263             mwif->recvMessage(GET, commid, keyeventtype, recordtime,
264                               (void*)&opt, len);
265         }
266         else {
267             mwif->recvMessage(CALLBACK, commid, keyeventtype, recordtime,
268                               (void*)&opt, len);
269         }
270         break;
271     }
272     default:
273     {
274         return false;
275     }
276     }
277     return true;
278 }
279
280 void
281 ControlWebsocket::observation()
282 {
283     int ret = 0;
284     while (ret >= 0) {
285         ret = libwebsocket_service(context, 100);
286         if (ret != 0) {
287             break;
288         }
289     }
290 }
291
292 bool
293 ControlWebsocket::registSocket(int commid)
294 {
295     if (socketmap.find(commid) != socketmap.end()) {
296         return true;
297     }
298     GenerateCommID<libwebsocket*> *idserver =
299             GenerateCommID<libwebsocket*>::getInstance();
300     libwebsocket *wsi = idserver->getValue(commid);
301     if (wsi == NULL) {
302         return false;
303     }
304     libwebsocket_protocols *protocol =
305             const_cast<libwebsocket_protocols*>(libwebsockets_get_protocol(wsi));
306     if (protocol != NULL) {
307         if (context == protocol[0].owning_server) {
308             socketmap[commid] = wsi;
309             return true;
310         }
311     }
312     return false;
313 }
314
315 bool
316 ControlWebsocket::unregistSocket(int commid)
317 {
318     if (socketmap.find(commid) == socketmap.end()) {
319         return false;
320     }
321     socketmap.erase(commid);
322     GenerateCommID<libwebsocket*> *idserver =
323             GenerateCommID<libwebsocket*>::getInstance();
324     return idserver->unsetID(commid);
325 }
326
327 int
328 ControlWebsocket::callback_receive(libwebsocket_context *context,
329                                    libwebsocket *wsi,
330                                    libwebsocket_callback_reasons reason,
331                                    void *user, void *in, size_t len)
332 {
333     DebugOut(10) << "Reason(" << reason << ")\n";
334     switch (reason) {
335     case LWS_CALLBACK_ESTABLISHED:
336     {
337         GenerateCommID<libwebsocket*> *idserver =
338                 GenerateCommID<libwebsocket*>::getInstance();
339         int id = idserver->getID(wsi);
340         DebugOut() << "ControlWebsocket callback_receive Insert ID is " << id
341                    << "\n";
342         break;
343     }
344     case LWS_CALLBACK_CLOSED:
345     {
346         GenerateCommID<libwebsocket*> *idserver =
347                 GenerateCommID<libwebsocket*>::getInstance();
348         int id = idserver->getID(wsi);
349         idserver->unsetID(id);
350         DebugOut() << "ControlWebsocket callback_receive Delete ID is " << id
351                    << "\n";
352         ControlWebsocket::mwif->unregistDestination(id);
353         break;
354     }
355     case LWS_CALLBACK_RECEIVE:
356     {
357         GenerateCommID<libwebsocket*> *idserver =
358                 GenerateCommID<libwebsocket*>::getInstance();
359         int id = idserver->getID(wsi);
360         StandardMessage msg;
361         char *buf = reinterpret_cast<char*>(in);
362         msg.decode(buf, len);
363         DebugOut() << "ControlWebsocket callback_receive Receive message : "
364                    << msg.getKeyEventType() << "," << msg.getRecordtime().tv_sec
365                    << "\n";
366         ControlWebsocket::mwif->recvRawdata(
367                 id, msg.getKeyEventType(), msg.getRecordtime(),
368                 (buf + StandardMessage::KEYEVENTTYPESIZE + sizeof(timeval)),
369                 len);
370         break;
371     }
372     default:
373     {
374         break;
375     }
376     }
377     return 0;
378 }
379
380 void *
381 ControlWebsocket::run(void *arg)
382 {
383     ControlWebsocket *control = reinterpret_cast<ControlWebsocket*>(arg);
384     control->observation();
385     return NULL;
386 }