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