Visual Servoing Platform  version 3.1.0
vpNetwork.cpp
1 /****************************************************************************
2  *
3  * This file is part of the ViSP software.
4  * Copyright (C) 2005 - 2017 by Inria. All rights reserved.
5  *
6  * This software is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  * See the file LICENSE.txt at the root directory of this source
11  * distribution for additional information about the GNU GPL.
12  *
13  * For using ViSP with software that can not be combined with the GNU
14  * GPL, please contact Inria about acquiring a ViSP Professional
15  * Edition License.
16  *
17  * See http://visp.inria.fr for more information.
18  *
19  * This software was developed at:
20  * Inria Rennes - Bretagne Atlantique
21  * Campus Universitaire de Beaulieu
22  * 35042 Rennes Cedex
23  * France
24  *
25  * If you have questions regarding the use of this file, please contact
26  * Inria at visp@inria.fr
27  *
28  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
29  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
30  *
31  * Description:
32  * TCP Network
33  *
34  * Authors:
35  * Aurelien Yol
36  *
37  *****************************************************************************/
38 
39 #include <visp3/core/vpNetwork.h>
40 
42  : emitter(), receptor_list(), readFileDescriptor(), socketMax(0), request_list(), max_size_message(999999),
43  separator("[*@*]"), beginning("[*start*]"), end("[*end*]"), param_sep("[*|*]"), currentMessageReceived(), tv(),
44  tv_sec(0), tv_usec(10), verboseMode(false)
45 {
46  tv.tv_sec = tv_sec;
47 #if TARGET_OS_IPHONE
48  tv.tv_usec = (int)tv_usec;
49 #else
50  tv.tv_usec = tv_usec;
51 #endif
52 
53 #if defined(_WIN32)
54  // Enable the sockets to be used
55  // Note that: if we were using "winsock.h" instead of "winsock2.h" we would
56  // had to use: WSAStartup(MAKEWORD(1,0), &WSAData);
57  WSADATA WSAData;
58  WSAStartup(MAKEWORD(2, 0), &WSAData);
59 #endif
60 }
61 
63 {
64 #if defined(_WIN32)
65  WSACleanup();
66 #endif
67 }
68 
81 {
82  bool alreadyHas = false;
83 
84  for (unsigned int i = 0; i < request_list.size(); i++)
85  if (request_list[i]->getId() == req->getId()) {
86  alreadyHas = true;
87  break;
88  }
89 
90  if (alreadyHas)
91  std::cout << "Server already has one request with the similar ID. "
92  "Request hasn't been added."
93  << std::endl;
94  else
95  request_list.push_back(req);
96 }
97 
106 {
107  for (unsigned int i = 0; i < request_list.size(); i++) {
108  if (request_list[i]->getId() == id) {
109  request_list.erase(request_list.begin() + (int)i);
110  break;
111  }
112  }
113 }
114 
120 void vpNetwork::print(const char *id)
121 {
122  for (unsigned int i = 0; i < receptor_list.size(); i++) {
123  std::cout << id << i << " : " << inet_ntoa(receptor_list[i].receptorAddress.sin_addr) << std::endl;
124  }
125 }
126 
135 int vpNetwork::getReceptorIndex(const char *name)
136 {
137  struct hostent *server = gethostbyname(name);
138 
139  if (server == NULL) {
140  std::string noSuchHostMessage("ERROR, ");
141  noSuchHostMessage.append(name);
142  noSuchHostMessage.append(": no such host\n");
143  vpERROR_TRACE(noSuchHostMessage.c_str(), "vpNetwork::getReceptorIndex()");
144  return -1;
145  }
146 
147  std::string ip = inet_ntoa(*(in_addr *)server->h_addr);
148 
149  for (int i = 0; i < (int)receptor_list.size(); i++) {
150  if (receptor_list[(unsigned)i].receptorIP == ip)
151  return i;
152  }
153 
154  return -1;
155 }
156 
170 int vpNetwork::sendRequest(vpRequest &req) { return sendRequestTo(req, 0); }
171 
186 int vpNetwork::sendRequestTo(vpRequest &req, const unsigned int &dest)
187 {
188  int size = (int)receptor_list.size();
189  int sizeMinusOne = (int)receptor_list.size() - 1;
190  if (size == 0 || dest > (unsigned)sizeMinusOne) {
191  if (verboseMode)
192  vpTRACE("Cannot Send Request! Bad Index");
193  return 0;
194  }
195 
196  std::string message = beginning + req.getId() + separator;
197 
198  if (req.size() != 0) {
199  message += req[0];
200 
201  for (unsigned int i = 1; i < req.size(); i++) {
202  message += param_sep + req[i];
203  }
204  }
205 
206  message += end;
207 
208  int flags = 0;
209 //#if ! defined(APPLE) && ! defined(SOLARIS) && ! defined(_WIN32)
210 #if defined(__linux__)
211  flags = MSG_NOSIGNAL; // Only for Linux
212 #endif
213 
214 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
215  int value = (int)sendto(receptor_list[dest].socketFileDescriptorReceptor, message.c_str(), message.size(), flags,
216  (sockaddr *)&receptor_list[dest].receptorAddress, receptor_list[dest].receptorAddressSize);
217 #else
218  int value = sendto((unsigned)receptor_list[dest].socketFileDescriptorReceptor, message.c_str(), (int)message.size(),
219  flags, (sockaddr *)&receptor_list[dest].receptorAddress, receptor_list[dest].receptorAddressSize);
220 #endif
221 
222  return value;
223 }
224 
239 {
240  req.encode();
241  return sendRequest(req);
242 }
243 
258 int vpNetwork::sendAndEncodeRequestTo(vpRequest &req, const unsigned int &dest)
259 {
260  req.encode();
261  return sendRequestTo(req, dest);
262 }
263 
278 std::vector<int> vpNetwork::receiveRequest()
279 {
280  _receiveRequest();
281  return _handleRequests();
282 }
283 
301 std::vector<int> vpNetwork::receiveRequestFrom(const unsigned int &receptorEmitting)
302 {
303  _receiveRequestFrom(receptorEmitting);
304  return _handleRequests();
305 }
306 
326 {
327  _receiveRequestOnce();
328  return _handleFirstRequest();
329 }
330 
352 int vpNetwork::receiveRequestOnceFrom(const unsigned int &receptorEmitting)
353 {
354  _receiveRequestOnceFrom(receptorEmitting);
355  return _handleFirstRequest();
356 }
357 
373 {
374  std::vector<int> res = receiveRequest();
375  for (unsigned int i = 0; i < res.size(); i++)
376  if (res[i] != -1)
377  request_list[(unsigned)res[i]]->decode();
378 
379  return res;
380 }
381 
399 std::vector<int> vpNetwork::receiveAndDecodeRequestFrom(const unsigned int &receptorEmitting)
400 {
401  std::vector<int> res = receiveRequestFrom(receptorEmitting);
402  for (unsigned int i = 0; i < res.size(); i++) {
403  if (res[i] != -1)
404  request_list[(unsigned)res[i]]->decode();
405  }
406 
407  return res;
408 }
409 
430 {
431  int res = receiveRequestOnce();
432  if (res != -1)
433  request_list[(unsigned)res]->decode();
434 
435  return res;
436 }
437 
459 int vpNetwork::receiveAndDecodeRequestOnceFrom(const unsigned int &receptorEmitting)
460 {
461  int res = receiveRequestOnceFrom(receptorEmitting);
462  if (res != -1)
463  request_list[(unsigned)res]->decode();
464 
465  return res;
466 }
467 
468 //######## Definition of Template Functions ########
469 //# #
470 //##################################################
471 
483 std::vector<int> vpNetwork::_handleRequests()
484 {
485  std::vector<int> resIndex;
486  int index = _handleFirstRequest();
487 
488  while (index != -1) {
489  resIndex.push_back(index);
490  index = _handleFirstRequest();
491  }
492 
493  return resIndex;
494 }
495 
506 int vpNetwork::_handleFirstRequest()
507 {
508  size_t indStart = currentMessageReceived.find(beginning);
509  size_t indSep = currentMessageReceived.find(separator);
510  size_t indEnd = currentMessageReceived.find(end);
511 
512  if (indStart == std::string::npos && indSep == std::string::npos && indEnd == std::string::npos) {
513  if (currentMessageReceived.size() != 0)
514  currentMessageReceived.clear();
515 
516  if (verboseMode)
517  vpTRACE("Incorrect message");
518 
519  return -1;
520  }
521 
522  if (indStart == std::string::npos || indSep == std::string::npos || indEnd == std::string::npos)
523  return -1;
524 
525  if (indEnd < indStart) {
526  if (verboseMode)
527  vpTRACE("Incorrect message");
528  currentMessageReceived.erase((unsigned)indStart, indEnd + end.size());
529  return -1;
530  }
531 
532  size_t indStart2 = currentMessageReceived.find(beginning, indStart + 1);
533  if (indStart2 != std::string::npos && indStart2 < indEnd) {
534  if (verboseMode)
535  vpTRACE("Incorrect message");
536  currentMessageReceived.erase((unsigned)indStart, (unsigned)indStart2);
537  return -1;
538  }
539 
540  size_t deb = indStart + beginning.size();
541  std::string id = currentMessageReceived.substr((unsigned)deb, indSep - deb);
542 
543  // deb = indSep+separator.size();
544  // std::string params = currentMessageReceived.substr((unsigned)deb,
545  // (unsigned)(indEnd - deb));
546 
547  // std::cout << "Handling : " << currentMessageReceived.substr(indStart,
548  // indEnd+end.size() - indStart) << std::endl;
549 
550  int indRequest = 0;
551  bool hasBeenFound = false;
552  for (unsigned int i = 0; i < request_list.size(); i++) {
553  if (id == request_list[i]->getId()) {
554  hasBeenFound = true;
555  request_list[i]->clear();
556  indRequest = (int)i;
557  break;
558  }
559  }
560 
561  if (!hasBeenFound) {
562  // currentMessageReceived.erase(indStart,indEnd+end.size());
563  if (verboseMode)
564  vpTRACE("No request corresponds to the received message");
565  return -1;
566  }
567 
568  size_t indDebParam = indSep + separator.size();
569  size_t indEndParam = currentMessageReceived.find(param_sep, indDebParam);
570 
571  std::string param;
572  while (indEndParam != std::string::npos || indEndParam < indEnd) {
573  param = currentMessageReceived.substr((unsigned)indDebParam, (unsigned)(indEndParam - indDebParam));
574  request_list[(unsigned)indRequest]->addParameter(param);
575  indDebParam = indEndParam + param_sep.size();
576  indEndParam = currentMessageReceived.find(param_sep, indDebParam);
577  }
578 
579  param = currentMessageReceived.substr((unsigned)indDebParam, indEnd - indDebParam);
580  request_list[(unsigned)indRequest]->addParameter(param);
581  currentMessageReceived.erase(indStart, indEnd + end.size());
582 
583  return indRequest;
584 }
585 
600 void vpNetwork::_receiveRequest()
601 {
602  while (_receiveRequestOnce() > 0) {
603  };
604 }
605 
623 void vpNetwork::_receiveRequestFrom(const unsigned int &receptorEmitting)
624 {
625  while (_receiveRequestOnceFrom(receptorEmitting) > 0) {
626  };
627 }
628 
647 int vpNetwork::_receiveRequestOnce()
648 {
649  if (receptor_list.size() == 0) {
650  if (verboseMode)
651  vpTRACE("No Receptor!");
652  return -1;
653  }
654 
655  tv.tv_sec = tv_sec;
656 #if TARGET_OS_IPHONE
657  tv.tv_usec = (int)tv_usec;
658 #else
659  tv.tv_usec = tv_usec;
660 #endif
661 
662  FD_ZERO(&readFileDescriptor);
663 
664  for (unsigned int i = 0; i < receptor_list.size(); i++) {
665  if (i == 0)
666  socketMax = receptor_list[i].socketFileDescriptorReceptor;
667 
668  FD_SET((unsigned)receptor_list[i].socketFileDescriptorReceptor, &readFileDescriptor);
669  if (socketMax < receptor_list[i].socketFileDescriptorReceptor)
670  socketMax = receptor_list[i].socketFileDescriptorReceptor;
671  }
672 
673  int value = select((int)socketMax + 1, &readFileDescriptor, NULL, NULL, &tv);
674  int numbytes = 0;
675 
676  if (value == -1) {
677  if (verboseMode)
678  vpERROR_TRACE("Select error");
679  return -1;
680  } else if (value == 0) {
681  // Timeout
682  return 0;
683  } else {
684  for (unsigned int i = 0; i < receptor_list.size(); i++) {
685  if (FD_ISSET((unsigned int)receptor_list[i].socketFileDescriptorReceptor, &readFileDescriptor)) {
686  char *buf = new char[max_size_message];
687 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
688  numbytes = (int)recv(receptor_list[i].socketFileDescriptorReceptor, buf, max_size_message, 0);
689 #else
690  numbytes = recv((unsigned int)receptor_list[i].socketFileDescriptorReceptor, buf, (int)max_size_message, 0);
691 #endif
692 
693  if (numbytes <= 0) {
694  std::cout << "Disconnected : " << inet_ntoa(receptor_list[i].receptorAddress.sin_addr) << std::endl;
695  receptor_list.erase(receptor_list.begin() + (int)i);
696  delete[] buf;
697  return numbytes;
698  } else {
699  std::string returnVal(buf, (unsigned int)numbytes);
700  currentMessageReceived.append(returnVal);
701  }
702  delete[] buf;
703  break;
704  }
705  }
706  }
707 
708  return numbytes;
709 }
710 
732 int vpNetwork::_receiveRequestOnceFrom(const unsigned int &receptorEmitting)
733 {
734  int size = (int)receptor_list.size();
735  int sizeMinusOne = (int)receptor_list.size() - 1;
736  if (size == 0 || receptorEmitting > (unsigned)sizeMinusOne) {
737  if (verboseMode)
738  vpTRACE("No receptor at the specified index!");
739  return -1;
740  }
741 
742  tv.tv_sec = tv_sec;
743 #if TARGET_OS_IPHONE
744  tv.tv_usec = (int)tv_usec;
745 #else
746  tv.tv_usec = tv_usec;
747 #endif
748 
749  FD_ZERO(&readFileDescriptor);
750 
751  socketMax = receptor_list[receptorEmitting].socketFileDescriptorReceptor;
752  FD_SET((unsigned int)receptor_list[receptorEmitting].socketFileDescriptorReceptor, &readFileDescriptor);
753 
754  int value = select((int)socketMax + 1, &readFileDescriptor, NULL, NULL, &tv);
755  int numbytes = 0;
756  if (value == -1) {
757  if (verboseMode)
758  vpERROR_TRACE("Select error");
759  return -1;
760  } else if (value == 0) {
761  // Timeout
762  return 0;
763  } else {
764  if (FD_ISSET((unsigned int)receptor_list[receptorEmitting].socketFileDescriptorReceptor, &readFileDescriptor)) {
765  char *buf = new char[max_size_message];
766 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
767  numbytes = (int)recv(receptor_list[receptorEmitting].socketFileDescriptorReceptor, buf, max_size_message, 0);
768 #else
769  numbytes = recv((unsigned int)receptor_list[receptorEmitting].socketFileDescriptorReceptor, buf,
770  (int)max_size_message, 0);
771 #endif
772  if (numbytes <= 0) {
773  std::cout << "Disconnected : " << inet_ntoa(receptor_list[receptorEmitting].receptorAddress.sin_addr)
774  << std::endl;
775  receptor_list.erase(receptor_list.begin() + (int)receptorEmitting);
776  delete[] buf;
777  return numbytes;
778  } else {
779  std::string returnVal(buf, (unsigned int)numbytes);
780  currentMessageReceived.append(returnVal);
781  }
782  delete[] buf;
783  }
784  }
785 
786  return numbytes;
787 }
unsigned int max_size_message
Definition: vpNetwork.h:135
int receiveRequestOnce()
Definition: vpNetwork.cpp:325
std::string separator
Definition: vpNetwork.h:136
int receiveRequestOnceFrom(const unsigned int &receptorEmitting)
Definition: vpNetwork.cpp:352
std::string beginning
Definition: vpNetwork.h:137
This the request that will transit on the network.
Definition: vpRequest.h:131
fd_set readFileDescriptor
Definition: vpNetwork.h:125
void print(const char *id="")
Definition: vpNetwork.cpp:120
#define vpERROR_TRACE
Definition: vpDebug.h:393
int receiveAndDecodeRequestOnceFrom(const unsigned int &receptorEmitting)
Definition: vpNetwork.cpp:459
int sendRequestTo(vpRequest &req, const unsigned int &dest)
Definition: vpNetwork.cpp:186
std::vector< int > receiveRequestFrom(const unsigned int &receptorEmitting)
Definition: vpNetwork.cpp:301
std::vector< int > receiveAndDecodeRequestFrom(const unsigned int &receptorEmitting)
Definition: vpNetwork.cpp:399
virtual void encode()=0
int socketMax
Definition: vpNetwork.h:127
virtual ~vpNetwork()
Definition: vpNetwork.cpp:62
std::vector< int > receiveAndDecodeRequest()
Definition: vpNetwork.cpp:372
std::string end
Definition: vpNetwork.h:138
#define vpTRACE
Definition: vpDebug.h:416
int sendAndEncodeRequestTo(vpRequest &req, const unsigned int &dest)
Definition: vpNetwork.cpp:258
unsigned int size()
Definition: vpRequest.h:202
int receiveAndDecodeRequestOnce()
Definition: vpNetwork.cpp:429
int sendAndEncodeRequest(vpRequest &req)
Definition: vpNetwork.cpp:238
long tv_sec
Definition: vpNetwork.h:144
bool verboseMode
Definition: vpNetwork.h:147
std::vector< int > receiveRequest()
Definition: vpNetwork.cpp:278
std::string getId()
Definition: vpRequest.h:186
struct timeval tv
Definition: vpNetwork.h:143
std::vector< vpReceptor > receptor_list
Definition: vpNetwork.h:124
int sendRequest(vpRequest &req)
Definition: vpNetwork.cpp:170
long tv_usec
Definition: vpNetwork.h:145
void removeDecodingRequest(const char *)
Definition: vpNetwork.cpp:105
std::string currentMessageReceived
Definition: vpNetwork.h:141
int getReceptorIndex(const char *name)
Definition: vpNetwork.cpp:135
void addDecodingRequest(vpRequest *)
Definition: vpNetwork.cpp:80
std::string param_sep
Definition: vpNetwork.h:139
std::vector< vpRequest * > request_list
Definition: vpNetwork.h:133