Visual Servoing Platform  version 3.6.1 under development (2024-04-18)
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 
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 #ifdef 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 == nullptr) {
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  privReceiveRequest();
284  return privHandleRequests();
285 }
286 
304 std::vector<int> vpNetwork::receiveRequestFrom(const unsigned int &receptorEmitting)
305 {
306  privReceiveRequestFrom(receptorEmitting);
307  return privHandleRequests();
308 }
309 
329 {
330  privReceiveRequestOnce();
331  return privHandleFirstRequest();
332 }
333 
355 int vpNetwork::receiveRequestOnceFrom(const unsigned int &receptorEmitting)
356 {
357  privReceiveRequestOnceFrom(receptorEmitting);
358  return privHandleFirstRequest();
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::privHandleRequests()
487 {
488  std::vector<int> resIndex;
489  int index = privHandleFirstRequest();
490 
491  while (index != -1) {
492  resIndex.push_back(index);
493  index = privHandleFirstRequest();
494  }
495 
496  return resIndex;
497 }
498 
509 int vpNetwork::privHandleFirstRequest()
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::privReceiveRequest()
604 {
605  while (privReceiveRequestOnce() > 0) {
606  };
607 }
608 
626 void vpNetwork::privReceiveRequestFrom(const unsigned int &receptorEmitting)
627 {
628  while (privReceiveRequestOnceFrom(receptorEmitting) > 0) {
629  };
630 }
631 
650 int vpNetwork::privReceiveRequestOnce()
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 #ifdef 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, nullptr, nullptr, &tv);
677  int numbytes = 0;
678 
679  if (value == -1) {
680  if (verboseMode)
681  vpERROR_TRACE("Select error");
682  return -1;
683  }
684  else if (value == 0) {
685  // Timeout
686  return 0;
687  }
688  else {
689  for (unsigned int i = 0; i < receptor_list.size(); i++) {
690  if (FD_ISSET((unsigned int)receptor_list[i].socketFileDescriptorReceptor, &readFileDescriptor)) {
691  char *buf = new char[max_size_message];
692 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
693  numbytes = (int)recv(receptor_list[i].socketFileDescriptorReceptor, buf, max_size_message, 0);
694 #else
695  numbytes = recv((unsigned int)receptor_list[i].socketFileDescriptorReceptor, buf, (int)max_size_message, 0);
696 #endif
697 
698  if (numbytes <= 0) {
699  std::cout << "Disconnected : " << inet_ntoa(receptor_list[i].receptorAddress.sin_addr) << std::endl;
700  receptor_list.erase(receptor_list.begin() + (int)i);
701  delete[] buf;
702  return numbytes;
703  }
704  else {
705  std::string returnVal(buf, (unsigned int)numbytes);
706  currentMessageReceived.append(returnVal);
707  }
708  delete[] buf;
709  break;
710  }
711  }
712  }
713 
714  return numbytes;
715 }
716 
738 int vpNetwork::privReceiveRequestOnceFrom(const unsigned int &receptorEmitting)
739 {
740  int size = (int)receptor_list.size();
741  int sizeMinusOne = (int)receptor_list.size() - 1;
742  if (size == 0 || receptorEmitting > (unsigned)sizeMinusOne) {
743  if (verboseMode)
744  vpTRACE("No receptor at the specified index!");
745  return -1;
746  }
747 
748  tv.tv_sec = tv_sec;
749 #ifdef TARGET_OS_IPHONE
750  tv.tv_usec = (int)tv_usec;
751 #else
752  tv.tv_usec = tv_usec;
753 #endif
754 
755  FD_ZERO(&readFileDescriptor);
756 
757  socketMax = receptor_list[receptorEmitting].socketFileDescriptorReceptor;
758  FD_SET((unsigned int)receptor_list[receptorEmitting].socketFileDescriptorReceptor, &readFileDescriptor);
759 
760  int value = select((int)socketMax + 1, &readFileDescriptor, nullptr, nullptr, &tv);
761  int numbytes = 0;
762  if (value == -1) {
763  if (verboseMode)
764  vpERROR_TRACE("Select error");
765  return -1;
766  }
767  else if (value == 0) {
768  // Timeout
769  return 0;
770  }
771  else {
772  if (FD_ISSET((unsigned int)receptor_list[receptorEmitting].socketFileDescriptorReceptor, &readFileDescriptor)) {
773  char *buf = new char[max_size_message];
774 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
775  numbytes = (int)recv(receptor_list[receptorEmitting].socketFileDescriptorReceptor, buf, max_size_message, 0);
776 #else
777  numbytes = recv((unsigned int)receptor_list[receptorEmitting].socketFileDescriptorReceptor, buf,
778  (int)max_size_message, 0);
779 #endif
780  if (numbytes <= 0) {
781  std::cout << "Disconnected : " << inet_ntoa(receptor_list[receptorEmitting].receptorAddress.sin_addr)
782  << std::endl;
783  receptor_list.erase(receptor_list.begin() + (int)receptorEmitting);
784  delete[] buf;
785  return numbytes;
786  }
787  else {
788  std::string returnVal(buf, (unsigned int)numbytes);
789  currentMessageReceived.append(returnVal);
790  }
791  delete[] buf;
792  }
793  }
794 
795  return numbytes;
796 }
797 
798 #elif !defined(VISP_BUILD_SHARED_LIBS)
799 // Work around to avoid warning: libvisp_core.a(vpNetwork.cpp.o) has no symbols
800 void dummy_vpNetwork() { };
801 #endif
virtual ~vpNetwork()
Definition: vpNetwork.cpp:65
long tv_sec
Definition: vpNetwork.h:147
int receiveRequestOnce()
Definition: vpNetwork.cpp:328
std::vector< int > receiveAndDecodeRequestFrom(const unsigned int &receptorEmitting)
Definition: vpNetwork.cpp:402
int sendRequest(vpRequest &req)
Definition: vpNetwork.cpp:173
int socketMax
Definition: vpNetwork.h:130
fd_set readFileDescriptor
Definition: vpNetwork.h:128
bool verboseMode
Definition: vpNetwork.h:150
std::string currentMessageReceived
Definition: vpNetwork.h:144
int sendAndEncodeRequestTo(vpRequest &req, const unsigned int &dest)
Definition: vpNetwork.cpp:261
std::vector< vpRequest * > request_list
Definition: vpNetwork.h:136
int sendAndEncodeRequest(vpRequest &req)
Definition: vpNetwork.cpp:241
int receiveAndDecodeRequestOnce()
Definition: vpNetwork.cpp:432
long tv_usec
Definition: vpNetwork.h:148
std::string beginning
Definition: vpNetwork.h:140
std::vector< int > receiveRequest()
Definition: vpNetwork.cpp:281
int sendRequestTo(vpRequest &req, const unsigned int &dest)
Definition: vpNetwork.cpp:189
std::vector< vpReceptor > receptor_list
Definition: vpNetwork.h:127
void addDecodingRequest(vpRequest *)
Definition: vpNetwork.cpp:83
struct timeval tv
Definition: vpNetwork.h:146
std::vector< int > receiveRequestFrom(const unsigned int &receptorEmitting)
Definition: vpNetwork.cpp:304
std::vector< int > receiveAndDecodeRequest()
Definition: vpNetwork.cpp:375
void removeDecodingRequest(const char *)
Definition: vpNetwork.cpp:108
int receiveAndDecodeRequestOnceFrom(const unsigned int &receptorEmitting)
Definition: vpNetwork.cpp:462
void print(const char *id="")
Definition: vpNetwork.cpp:123
std::string separator
Definition: vpNetwork.h:139
std::string param_sep
Definition: vpNetwork.h:142
int receiveRequestOnceFrom(const unsigned int &receptorEmitting)
Definition: vpNetwork.cpp:355
int getReceptorIndex(const char *name)
Definition: vpNetwork.cpp:138
unsigned int max_size_message
Definition: vpNetwork.h:138
std::string end
Definition: vpNetwork.h:141
This the request that will transit on the network.
Definition: vpRequest.h:127
virtual void encode()=0
std::string getId() const
Definition: vpRequest.h:181
unsigned int size() const
Definition: vpRequest.h:197
#define vpTRACE
Definition: vpDebug.h:405
#define vpERROR_TRACE
Definition: vpDebug.h:382