Visual Servoing Platform  version 3.5.0 under development (2022-02-15)
vpNetwork.cpp
1 /****************************************************************************
2  *
3  * ViSP, open source Visual Servoing Platform software.
4  * Copyright (C) 2005 - 2019 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 
41 // inet_ntop() not supported on win XP
42 #ifdef VISP_HAVE_FUNC_INET_NTOP
43 
45  : emitter(), receptor_list(), readFileDescriptor(), socketMax(0), request_list(), max_size_message(999999),
46  separator("[*@*]"), beginning("[*start*]"), end("[*end*]"), param_sep("[*|*]"), currentMessageReceived(), tv(),
47  tv_sec(0), tv_usec(10), verboseMode(false)
48 {
49  tv.tv_sec = tv_sec;
50 #if TARGET_OS_IPHONE
51  tv.tv_usec = (int)tv_usec;
52 #else
53  tv.tv_usec = tv_usec;
54 #endif
55 
56 #if defined(_WIN32)
57  // Enable the sockets to be used
58  // Note that: if we were using "winsock.h" instead of "winsock2.h" we would
59  // had to use: WSAStartup(MAKEWORD(1,0), &WSAData);
60  WSADATA WSAData;
61  WSAStartup(MAKEWORD(2, 0), &WSAData);
62 #endif
63 }
64 
66 {
67 #if defined(_WIN32)
68  WSACleanup();
69 #endif
70 }
71 
84 {
85  bool alreadyHas = false;
86 
87  for (unsigned int i = 0; i < request_list.size(); i++)
88  if (request_list[i]->getId() == req->getId()) {
89  alreadyHas = true;
90  break;
91  }
92 
93  if (alreadyHas)
94  std::cout << "Server already has one request with the similar ID. "
95  "Request hasn't been added."
96  << std::endl;
97  else
98  request_list.push_back(req);
99 }
100 
109 {
110  for (unsigned int i = 0; i < request_list.size(); i++) {
111  if (request_list[i]->getId() == id) {
112  request_list.erase(request_list.begin() + (int)i);
113  break;
114  }
115  }
116 }
117 
123 void vpNetwork::print(const char *id)
124 {
125  for (unsigned int i = 0; i < receptor_list.size(); i++) {
126  std::cout << id << i << " : " << inet_ntoa(receptor_list[i].receptorAddress.sin_addr) << std::endl;
127  }
128 }
129 
138 int vpNetwork::getReceptorIndex(const char *name)
139 {
140  struct hostent *server = gethostbyname(name);
141 
142  if (server == NULL) {
143  std::string noSuchHostMessage("ERROR, ");
144  noSuchHostMessage.append(name);
145  noSuchHostMessage.append(": no such host\n");
146  vpERROR_TRACE(noSuchHostMessage.c_str(), "vpNetwork::getReceptorIndex()");
147  return -1;
148  }
149 
150  std::string ip = inet_ntoa(*(in_addr *)server->h_addr);
151 
152  for (int i = 0; i < (int)receptor_list.size(); i++) {
153  if (receptor_list[(unsigned)i].receptorIP == ip)
154  return i;
155  }
156 
157  return -1;
158 }
159 
173 int vpNetwork::sendRequest(vpRequest &req) { return sendRequestTo(req, 0); }
174 
189 int vpNetwork::sendRequestTo(vpRequest &req, const unsigned int &dest)
190 {
191  int size = (int)receptor_list.size();
192  int sizeMinusOne = (int)receptor_list.size() - 1;
193  if (size == 0 || dest > (unsigned)sizeMinusOne) {
194  if (verboseMode)
195  vpTRACE("Cannot Send Request! Bad Index");
196  return 0;
197  }
198 
199  std::string message = beginning + req.getId() + separator;
200 
201  if (req.size() != 0) {
202  message += req[0];
203 
204  for (unsigned int i = 1; i < req.size(); i++) {
205  message += param_sep + req[i];
206  }
207  }
208 
209  message += end;
210 
211  int flags = 0;
212 //#if ! defined(APPLE) && ! defined(SOLARIS) && ! defined(_WIN32)
213 #if defined(__linux__)
214  flags = MSG_NOSIGNAL; // Only for Linux
215 #endif
216 
217 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
218  int value = (int)sendto(receptor_list[dest].socketFileDescriptorReceptor, message.c_str(), message.size(), flags,
219  (sockaddr *)&receptor_list[dest].receptorAddress, receptor_list[dest].receptorAddressSize);
220 #else
221  int value = sendto((unsigned)receptor_list[dest].socketFileDescriptorReceptor, message.c_str(), (int)message.size(),
222  flags, (sockaddr *)&receptor_list[dest].receptorAddress, receptor_list[dest].receptorAddressSize);
223 #endif
224 
225  return value;
226 }
227 
242 {
243  req.encode();
244  return sendRequest(req);
245 }
246 
261 int vpNetwork::sendAndEncodeRequestTo(vpRequest &req, const unsigned int &dest)
262 {
263  req.encode();
264  return sendRequestTo(req, dest);
265 }
266 
281 std::vector<int> vpNetwork::receiveRequest()
282 {
283  _receiveRequest();
284  return _handleRequests();
285 }
286 
304 std::vector<int> vpNetwork::receiveRequestFrom(const unsigned int &receptorEmitting)
305 {
306  _receiveRequestFrom(receptorEmitting);
307  return _handleRequests();
308 }
309 
329 {
330  _receiveRequestOnce();
331  return _handleFirstRequest();
332 }
333 
355 int vpNetwork::receiveRequestOnceFrom(const unsigned int &receptorEmitting)
356 {
357  _receiveRequestOnceFrom(receptorEmitting);
358  return _handleFirstRequest();
359 }
360 
376 {
377  std::vector<int> res = receiveRequest();
378  for (unsigned int i = 0; i < res.size(); i++)
379  if (res[i] != -1)
380  request_list[(unsigned)res[i]]->decode();
381 
382  return res;
383 }
384 
402 std::vector<int> vpNetwork::receiveAndDecodeRequestFrom(const unsigned int &receptorEmitting)
403 {
404  std::vector<int> res = receiveRequestFrom(receptorEmitting);
405  for (unsigned int i = 0; i < res.size(); i++) {
406  if (res[i] != -1)
407  request_list[(unsigned)res[i]]->decode();
408  }
409 
410  return res;
411 }
412 
433 {
434  int res = receiveRequestOnce();
435  if (res != -1)
436  request_list[(unsigned)res]->decode();
437 
438  return res;
439 }
440 
462 int vpNetwork::receiveAndDecodeRequestOnceFrom(const unsigned int &receptorEmitting)
463 {
464  int res = receiveRequestOnceFrom(receptorEmitting);
465  if (res != -1)
466  request_list[(unsigned)res]->decode();
467 
468  return res;
469 }
470 
471 //######## Definition of Template Functions ########
472 //# #
473 //##################################################
474 
486 std::vector<int> vpNetwork::_handleRequests()
487 {
488  std::vector<int> resIndex;
489  int index = _handleFirstRequest();
490 
491  while (index != -1) {
492  resIndex.push_back(index);
493  index = _handleFirstRequest();
494  }
495 
496  return resIndex;
497 }
498 
509 int vpNetwork::_handleFirstRequest()
510 {
511  size_t indStart = currentMessageReceived.find(beginning);
512  size_t indSep = currentMessageReceived.find(separator);
513  size_t indEnd = currentMessageReceived.find(end);
514 
515  if (indStart == std::string::npos && indSep == std::string::npos && indEnd == std::string::npos) {
516  if (currentMessageReceived.size() != 0)
517  currentMessageReceived.clear();
518 
519  if (verboseMode)
520  vpTRACE("Incorrect message");
521 
522  return -1;
523  }
524 
525  if (indStart == std::string::npos || indSep == std::string::npos || indEnd == std::string::npos)
526  return -1;
527 
528  if (indEnd < indStart) {
529  if (verboseMode)
530  vpTRACE("Incorrect message");
531  currentMessageReceived.erase((unsigned)indStart, indEnd + end.size());
532  return -1;
533  }
534 
535  size_t indStart2 = currentMessageReceived.find(beginning, indStart + 1);
536  if (indStart2 != std::string::npos && indStart2 < indEnd) {
537  if (verboseMode)
538  vpTRACE("Incorrect message");
539  currentMessageReceived.erase((unsigned)indStart, (unsigned)indStart2);
540  return -1;
541  }
542 
543  size_t deb = indStart + beginning.size();
544  std::string id = currentMessageReceived.substr((unsigned)deb, indSep - deb);
545 
546  // deb = indSep+separator.size();
547  // std::string params = currentMessageReceived.substr((unsigned)deb,
548  // (unsigned)(indEnd - deb));
549 
550  // std::cout << "Handling : " << currentMessageReceived.substr(indStart,
551  // indEnd+end.size() - indStart) << std::endl;
552 
553  int indRequest = 0;
554  bool hasBeenFound = false;
555  for (unsigned int i = 0; i < request_list.size(); i++) {
556  if (id == request_list[i]->getId()) {
557  hasBeenFound = true;
558  request_list[i]->clear();
559  indRequest = (int)i;
560  break;
561  }
562  }
563 
564  if (!hasBeenFound) {
565  // currentMessageReceived.erase(indStart,indEnd+end.size());
566  if (verboseMode)
567  vpTRACE("No request corresponds to the received message");
568  return -1;
569  }
570 
571  size_t indDebParam = indSep + separator.size();
572  size_t indEndParam = currentMessageReceived.find(param_sep, indDebParam);
573 
574  std::string param;
575  while (indEndParam != std::string::npos || indEndParam < indEnd) {
576  param = currentMessageReceived.substr((unsigned)indDebParam, (unsigned)(indEndParam - indDebParam));
577  request_list[(unsigned)indRequest]->addParameter(param);
578  indDebParam = indEndParam + param_sep.size();
579  indEndParam = currentMessageReceived.find(param_sep, indDebParam);
580  }
581 
582  param = currentMessageReceived.substr((unsigned)indDebParam, indEnd - indDebParam);
583  request_list[(unsigned)indRequest]->addParameter(param);
584  currentMessageReceived.erase(indStart, indEnd + end.size());
585 
586  return indRequest;
587 }
588 
603 void vpNetwork::_receiveRequest()
604 {
605  while (_receiveRequestOnce() > 0) {
606  };
607 }
608 
626 void vpNetwork::_receiveRequestFrom(const unsigned int &receptorEmitting)
627 {
628  while (_receiveRequestOnceFrom(receptorEmitting) > 0) {
629  };
630 }
631 
650 int vpNetwork::_receiveRequestOnce()
651 {
652  if (receptor_list.size() == 0) {
653  if (verboseMode)
654  vpTRACE("No Receptor!");
655  return -1;
656  }
657 
658  tv.tv_sec = tv_sec;
659 #if TARGET_OS_IPHONE
660  tv.tv_usec = (int)tv_usec;
661 #else
662  tv.tv_usec = tv_usec;
663 #endif
664 
665  FD_ZERO(&readFileDescriptor);
666 
667  for (unsigned int i = 0; i < receptor_list.size(); i++) {
668  if (i == 0)
669  socketMax = receptor_list[i].socketFileDescriptorReceptor;
670 
671  FD_SET((unsigned)receptor_list[i].socketFileDescriptorReceptor, &readFileDescriptor);
672  if (socketMax < receptor_list[i].socketFileDescriptorReceptor)
673  socketMax = receptor_list[i].socketFileDescriptorReceptor;
674  }
675 
676  int value = select((int)socketMax + 1, &readFileDescriptor, NULL, NULL, &tv);
677  int numbytes = 0;
678 
679  if (value == -1) {
680  if (verboseMode)
681  vpERROR_TRACE("Select error");
682  return -1;
683  } else if (value == 0) {
684  // Timeout
685  return 0;
686  } else {
687  for (unsigned int i = 0; i < receptor_list.size(); i++) {
688  if (FD_ISSET((unsigned int)receptor_list[i].socketFileDescriptorReceptor, &readFileDescriptor)) {
689  char *buf = new char[max_size_message];
690 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
691  numbytes = (int)recv(receptor_list[i].socketFileDescriptorReceptor, buf, max_size_message, 0);
692 #else
693  numbytes = recv((unsigned int)receptor_list[i].socketFileDescriptorReceptor, buf, (int)max_size_message, 0);
694 #endif
695 
696  if (numbytes <= 0) {
697  std::cout << "Disconnected : " << inet_ntoa(receptor_list[i].receptorAddress.sin_addr) << std::endl;
698  receptor_list.erase(receptor_list.begin() + (int)i);
699  delete[] buf;
700  return numbytes;
701  } else {
702  std::string returnVal(buf, (unsigned int)numbytes);
703  currentMessageReceived.append(returnVal);
704  }
705  delete[] buf;
706  break;
707  }
708  }
709  }
710 
711  return numbytes;
712 }
713 
735 int vpNetwork::_receiveRequestOnceFrom(const unsigned int &receptorEmitting)
736 {
737  int size = (int)receptor_list.size();
738  int sizeMinusOne = (int)receptor_list.size() - 1;
739  if (size == 0 || receptorEmitting > (unsigned)sizeMinusOne) {
740  if (verboseMode)
741  vpTRACE("No receptor at the specified index!");
742  return -1;
743  }
744 
745  tv.tv_sec = tv_sec;
746 #if TARGET_OS_IPHONE
747  tv.tv_usec = (int)tv_usec;
748 #else
749  tv.tv_usec = tv_usec;
750 #endif
751 
752  FD_ZERO(&readFileDescriptor);
753 
754  socketMax = receptor_list[receptorEmitting].socketFileDescriptorReceptor;
755  FD_SET((unsigned int)receptor_list[receptorEmitting].socketFileDescriptorReceptor, &readFileDescriptor);
756 
757  int value = select((int)socketMax + 1, &readFileDescriptor, NULL, NULL, &tv);
758  int numbytes = 0;
759  if (value == -1) {
760  if (verboseMode)
761  vpERROR_TRACE("Select error");
762  return -1;
763  } else if (value == 0) {
764  // Timeout
765  return 0;
766  } else {
767  if (FD_ISSET((unsigned int)receptor_list[receptorEmitting].socketFileDescriptorReceptor, &readFileDescriptor)) {
768  char *buf = new char[max_size_message];
769 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
770  numbytes = (int)recv(receptor_list[receptorEmitting].socketFileDescriptorReceptor, buf, max_size_message, 0);
771 #else
772  numbytes = recv((unsigned int)receptor_list[receptorEmitting].socketFileDescriptorReceptor, buf,
773  (int)max_size_message, 0);
774 #endif
775  if (numbytes <= 0) {
776  std::cout << "Disconnected : " << inet_ntoa(receptor_list[receptorEmitting].receptorAddress.sin_addr)
777  << std::endl;
778  receptor_list.erase(receptor_list.begin() + (int)receptorEmitting);
779  delete[] buf;
780  return numbytes;
781  } else {
782  std::string returnVal(buf, (unsigned int)numbytes);
783  currentMessageReceived.append(returnVal);
784  }
785  delete[] buf;
786  }
787  }
788 
789  return numbytes;
790 }
791 
792 #elif !defined(VISP_BUILD_SHARED_LIBS)
793 // Work arround to avoid warning: libvisp_core.a(vpNetwork.cpp.o) has no symbols
794 void dummy_vpNetwork(){};
795 #endif
unsigned int max_size_message
Definition: vpNetwork.h:141
int receiveRequestOnce()
Definition: vpNetwork.cpp:328
std::string separator
Definition: vpNetwork.h:142
int receiveRequestOnceFrom(const unsigned int &receptorEmitting)
Definition: vpNetwork.cpp:355
std::string beginning
Definition: vpNetwork.h:143
This the request that will transit on the network.
Definition: vpRequest.h:131
fd_set readFileDescriptor
Definition: vpNetwork.h:131
void print(const char *id="")
Definition: vpNetwork.cpp:123
#define vpERROR_TRACE
Definition: vpDebug.h:393
int receiveAndDecodeRequestOnceFrom(const unsigned int &receptorEmitting)
Definition: vpNetwork.cpp:462
int sendRequestTo(vpRequest &req, const unsigned int &dest)
Definition: vpNetwork.cpp:189
std::vector< int > receiveRequestFrom(const unsigned int &receptorEmitting)
Definition: vpNetwork.cpp:304
std::vector< int > receiveAndDecodeRequestFrom(const unsigned int &receptorEmitting)
Definition: vpNetwork.cpp:402
virtual void encode()=0
int socketMax
Definition: vpNetwork.h:133
virtual ~vpNetwork()
Definition: vpNetwork.cpp:65
std::vector< int > receiveAndDecodeRequest()
Definition: vpNetwork.cpp:375
std::string end
Definition: vpNetwork.h:144
#define vpTRACE
Definition: vpDebug.h:416
int sendAndEncodeRequestTo(vpRequest &req, const unsigned int &dest)
Definition: vpNetwork.cpp:261
unsigned int size()
Definition: vpRequest.h:202
int receiveAndDecodeRequestOnce()
Definition: vpNetwork.cpp:432
int sendAndEncodeRequest(vpRequest &req)
Definition: vpNetwork.cpp:241
long tv_sec
Definition: vpNetwork.h:150
bool verboseMode
Definition: vpNetwork.h:153
std::vector< int > receiveRequest()
Definition: vpNetwork.cpp:281
std::string getId()
Definition: vpRequest.h:186
struct timeval tv
Definition: vpNetwork.h:149
std::vector< vpReceptor > receptor_list
Definition: vpNetwork.h:130
int sendRequest(vpRequest &req)
Definition: vpNetwork.cpp:173
long tv_usec
Definition: vpNetwork.h:151
void removeDecodingRequest(const char *)
Definition: vpNetwork.cpp:108
std::string currentMessageReceived
Definition: vpNetwork.h:147
int getReceptorIndex(const char *name)
Definition: vpNetwork.cpp:138
void addDecodingRequest(vpRequest *)
Definition: vpNetwork.cpp:83
std::string param_sep
Definition: vpNetwork.h:145
std::vector< vpRequest * > request_list
Definition: vpNetwork.h:139