2 * Copyright (C) 2012 TOYOTA MOTOR CORPORATION.
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.
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.
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
27 #include "controlwebsocket.h"
28 #include "mwinterface.h"
29 #include "standardmessage.h"
32 * Socket ID generated class.
35 class GenerateCommID {
38 * This function retrieves an instance of the class.
40 * @return Instance of GenerateCommID
42 static GenerateCommID *
45 static GenerateCommID<T> instance;
50 * This function returns the ID that is registered.
51 * If the ID is not registerd, it register the ID.
53 * @param value Value of socket.
57 getID(T value, int key)
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);
70 commidmap.insert(make_pair(newid, value));
71 pthread_mutex_unlock(&mutex);
75 * This function returns the socket information registered.
78 * @return Value of socket
83 pthread_mutex_lock(&mutex);
84 if (commidmap.find(id) == commidmap.end()) {
85 pthread_mutex_unlock(&mutex);
88 pthread_mutex_unlock(&mutex);
93 * This function removes the socket information registered.
96 * @return Success : true Failure : false
101 pthread_mutex_lock(&mutex);
103 auto itr = commidmap.find(id);
104 if (itr != commidmap.end()) {
105 itr = commidmap.erase(itr);
108 pthread_mutex_unlock(&mutex);
113 mutex(PTHREAD_MUTEX_INITIALIZER)
122 GenerateCommID(const GenerateCommID &)
126 const GenerateCommID&
127 operator =(const GenerateCommID &)
134 if (commidmap.empty()) {
138 while (commidmap.find(count) == commidmap.end()) {
144 std::map<int, T> commidmap;
145 pthread_mutex_t mutex;
148 ControlWebsocket::ControlWebsocket()
150 mutex = PTHREAD_MUTEX_INITIALIZER;
153 ControlWebsocket::~ControlWebsocket()
160 ControlWebsocket::initialize(int port, enum ServerProtocol stype, MWIF *mwif_)
163 DebugOut(10) << "ControlWebsocket[" << type << "]" << " initialize.(" << port
165 stringstream address, protocol;
168 address << ":" << port;
172 protocol << "standarddatamessage-only";
175 case CONTROL_STANDARD:
177 protocol << "standardcontrolmessage-only";
182 protocol << "customdatamessage-only";
187 protocol << "customcontrolmessage-only";
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;
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;
213 if (pthread_create(&threadid, NULL, ControlWebsocket::run, (void*)this)
215 ico_uws_close(context);
216 DebugOut(10) << "ControlWebsocket[" << type << "]"
217 << " couldn't create thread." << std::endl;
224 ControlWebsocket::send(int commid, char *keyeventtype, timeval time, void *data,
227 DebugOut(10) << "ControlWebsocket[" << type << "]" << " send data(" << commid
228 << "," << keyeventtype << ") len = " << len << std::endl;
230 if (socketmap.find(commid) == socketmap.end()) {
231 if (!registSocket(commid)) {
232 DebugOut(10) << "ControlWebsocket[" << type << "]"
233 << " can't regist socket(" << commid << ")" << std::endl;
237 wsi = socketmap[commid];
240 DebugOut(10) << "ControlWebsocket Get websocket object is NULL."
244 pthread_mutex_lock(&mutex);
245 memset(buf, 0, sizeof(buf));
247 datamsg.encode(keyeventtype, time,
248 *(reinterpret_cast<DataOpt*>(data))),
250 DebugOut(10) << "ControlWebsocket Send Data[" << keyeventtype << "]"
252 ico_uws_send(context, wsi, reinterpret_cast<unsigned char*>(buf), len);
253 pthread_mutex_unlock(&mutex);
258 ControlWebsocket::receive(int commid, char *keyeventtype, timeval recordtime,
259 void *data, size_t len)
261 DebugOut(10) << "ControlWebsocket[" << type << "]" << " receive message("
262 << commid << "," << keyeventtype << ")\n";
267 datamsg.decodeOpt(keyeventtype, recordtime, data);
268 DataOpt dop = datamsg.getDataOpt();
269 mwif->recvMessage(SET, commid, keyeventtype, recordtime, (void*)&dop,
273 case CONTROL_STANDARD:
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,
283 mwif->recvMessage(CALLBACK, commid, keyeventtype, recordtime,
297 ControlWebsocket::receive(int commid, char *data, size_t len)
303 datamsg.decode(data, len);
304 DataOpt dop = datamsg.getDataOpt();
305 mwif->recvMessage(SET, commid, datamsg.getKeyEventType(), datamsg.getRecordtime(), (void*)&dop,
309 case CONTROL_STANDARD:
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(),
319 mwif->recvMessage(CALLBACK, commid, eventmsg.getKeyEventType(), eventmsg.getRecordtime(),
333 ControlWebsocket::observation()
337 ret = poll(&pollfds[0], pollfds.size(), -1);
339 DebugOut(10) << "Error: poll(" << strerror(errno) << ")\n";
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";
348 ico_uws_service(context);
353 ControlWebsocket::registSocket(int commid)
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);
361 fds.events = POLLIN | POLLERR;
362 pollfds.push_back(fds);
369 ControlWebsocket::unregistSocket(int commid)
371 if (socketmap.find(commid) == socketmap.end()) {
374 socketmap.erase(commid);
375 for (auto itr = pollfds.begin(); itr != pollfds.end(); itr++) {
376 if ((*itr).fd == commid) {
377 itr = pollfds.erase(itr);
381 GenerateCommID<void*> *idserver = GenerateCommID<void*>::getInstance();
382 return idserver->unsetID(commid);
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,
391 user_datacontainer *container = static_cast<user_datacontainer*>(user_data);
393 case ICO_UWS_EVT_OPEN:
395 case ICO_UWS_EVT_ERROR:
397 case ICO_UWS_EVT_CLOSE:
399 case ICO_UWS_EVT_RECEIVE:
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);
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;
412 buf + StandardMessage::KEYEVENTTYPESIZE +
413 sizeof(struct timeval) + sizeof(int),
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";
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";
427 container->ctrlws->receive(commid, buf,
428 detail->_ico_uws_message.recv_len);
429 DebugOut(10) << "ControlWebsocket End "
430 << "callback_recevie Receive message.\n";
433 case ICO_UWS_EVT_ADD_FD:
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 "
441 container->mwif->registDestination(container->type,
442 detail->_ico_uws_fd.fd);
445 case ICO_UWS_EVT_DEL_FD:
447 DebugOut(1) << "INFO CHG_VIC_INF Disconnected to VIC.\n";
448 container->mwif->unregistDestination(container->type,
449 detail->_ico_uws_fd.fd);
458 ControlWebsocket::run(void *arg)
460 ControlWebsocket *control = reinterpret_cast<ControlWebsocket*>(arg);
461 control->observation();