Visual Servoing Platform  version 3.6.1 under development (2024-12-03)
vpNetwork.cpp
1 /*
2  * ViSP, open source Visual Servoing Platform software.
3  * Copyright (C) 2005 - 2023 by Inria. All rights reserved.
4  *
5  * This software is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  * See the file LICENSE.txt at the root directory of this source
10  * distribution for additional information about the GNU GPL.
11  *
12  * For using ViSP with software that can not be combined with the GNU
13  * GPL, please contact Inria about acquiring a ViSP Professional
14  * Edition License.
15  *
16  * See https://visp.inria.fr for more information.
17  *
18  * This software was developed at:
19  * Inria Rennes - Bretagne Atlantique
20  * Campus Universitaire de Beaulieu
21  * 35042 Rennes Cedex
22  * France
23  *
24  * If you have questions regarding the use of this file, please contact
25  * Inria at visp@inria.fr
26  *
27  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
28  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29  *
30  * Description:
31  * TCP Network
32  */
33 
34 #include <visp3/core/vpConfig.h>
35 
36 // Specific case for UWP to introduce a workaround
37 // error C4996: 'gethostbyname': Use getaddrinfo() or GetAddrInfoW() instead or define _WINSOCK_DEPRECATED_NO_WARNINGS to disable deprecated API warnings
38 #if defined(WINRT) || defined(_WIN32)
39 #ifndef _WINSOCK_DEPRECATED_NO_WARNINGS
40 #define _WINSOCK_DEPRECATED_NO_WARNINGS
41 #endif
42 #endif
43 
44 // inet_ntop() not supported on win XP
45 #ifdef VISP_HAVE_FUNC_INET_NTOP
46 
47 #include <visp3/core/vpNetwork.h>
48 #include <visp3/core/vpDebug.h>
49 BEGIN_VISP_NAMESPACE
51  : emitter(), receptor_list(), readFileDescriptor(), socketMax(0), request_list(), max_size_message(999999),
52  separator("[*@*]"), beginning("[*start*]"), end("[*end*]"), param_sep("[*|*]"), currentMessageReceived(), tv(),
53  tv_sec(0), tv_usec(10), verboseMode(false)
54 {
55  tv.tv_sec = tv_sec;
56 #ifdef TARGET_OS_IPHONE
57  tv.tv_usec = (int)tv_usec;
58 #else
59  tv.tv_usec = tv_usec;
60 #endif
61 
62 #if defined(_WIN32)
63  // Enable the sockets to be used
64  // Note that: if we were using "winsock.h" instead of "winsock2.h" we would
65  // had to use: WSAStartup(MAKEWORD(1,0), &WSAData);
66  WSADATA WSAData;
67  WSAStartup(MAKEWORD(2, 0), &WSAData);
68 #endif
69 }
70 
72 {
73 #if defined(_WIN32)
74  WSACleanup();
75 #endif
76 }
77 
90 {
91  bool alreadyHas = false;
92 
93  for (unsigned int i = 0; i < request_list.size(); i++)
94  if (request_list[i]->getId() == req->getId()) {
95  alreadyHas = true;
96  break;
97  }
98 
99  if (alreadyHas)
100  std::cout << "Server already has one request with the similar ID. "
101  "Request hasn't been added."
102  << std::endl;
103  else
104  request_list.push_back(req);
105 }
106 
115 {
116  for (unsigned int i = 0; i < request_list.size(); i++) {
117  if (request_list[i]->getId() == id) {
118  request_list.erase(request_list.begin() + (int)i);
119  break;
120  }
121  }
122 }
123 
129 void vpNetwork::print(const char *id)
130 {
131  for (unsigned int i = 0; i < receptor_list.size(); i++) {
132  std::cout << id << i << " : " << inet_ntoa(receptor_list[i].receptorAddress.sin_addr) << std::endl;
133  }
134 }
135 
144 int vpNetwork::getReceptorIndex(const char *name)
145 {
146  struct hostent *server = gethostbyname(name);
147 
148  if (server == nullptr) {
149  std::string noSuchHostMessage("ERROR, ");
150  noSuchHostMessage.append(name);
151  noSuchHostMessage.append(": no such host\n");
152  vpERROR_TRACE(noSuchHostMessage.c_str(), "vpNetwork::getReceptorIndex()");
153  return -1;
154  }
155 
156  std::string ip = inet_ntoa(*(in_addr *)server->h_addr);
157 
158  for (int i = 0; i < (int)receptor_list.size(); i++) {
159  if (receptor_list[(unsigned)i].receptorIP == ip)
160  return i;
161  }
162 
163  return -1;
164 }
165 
179 int vpNetwork::sendRequest(vpRequest &req) { return sendRequestTo(req, 0); }
180 
195 int vpNetwork::sendRequestTo(vpRequest &req, const unsigned int &dest)
196 {
197  int size = (int)receptor_list.size();
198  int sizeMinusOne = (int)receptor_list.size() - 1;
199  if (size == 0 || dest > (unsigned)sizeMinusOne) {
200  if (verboseMode)
201  vpTRACE("Cannot Send Request! Bad Index");
202  return 0;
203  }
204 
205  std::string message = beginning + req.getId() + separator;
206 
207  if (req.size() != 0) {
208  message += req[0];
209 
210  for (unsigned int i = 1; i < req.size(); i++) {
211  message += param_sep + req[i];
212  }
213  }
214 
215  message += end;
216 
217  int flags = 0;
218 //#if ! defined(APPLE) && ! defined(SOLARIS) && ! defined(_WIN32)
219 #if defined(__linux__)
220  flags = MSG_NOSIGNAL; // Only for Linux
221 #endif
222 
223 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
224  int value = (int)sendto(receptor_list[dest].socketFileDescriptorReceptor, message.c_str(), message.size(), flags,
225  (sockaddr *)&receptor_list[dest].receptorAddress, receptor_list[dest].receptorAddressSize);
226 #else
227  int value = sendto((unsigned)receptor_list[dest].socketFileDescriptorReceptor, message.c_str(), (int)message.size(),
228  flags, (sockaddr *)&receptor_list[dest].receptorAddress, receptor_list[dest].receptorAddressSize);
229 #endif
230 
231  return value;
232 }
233 
248 {
249  req.encode();
250  return sendRequest(req);
251 }
252 
267 int vpNetwork::sendAndEncodeRequestTo(vpRequest &req, const unsigned int &dest)
268 {
269  req.encode();
270  return sendRequestTo(req, dest);
271 }
272 
287 std::vector<int> vpNetwork::receiveRequest()
288 {
289  privReceiveRequest();
290  return privHandleRequests();
291 }
292 
310 std::vector<int> vpNetwork::receiveRequestFrom(const unsigned int &receptorEmitting)
311 {
312  privReceiveRequestFrom(receptorEmitting);
313  return privHandleRequests();
314 }
315 
335 {
336  privReceiveRequestOnce();
337  return privHandleFirstRequest();
338 }
339 
361 int vpNetwork::receiveRequestOnceFrom(const unsigned int &receptorEmitting)
362 {
363  privReceiveRequestOnceFrom(receptorEmitting);
364  return privHandleFirstRequest();
365 }
366 
382 {
383  std::vector<int> res = receiveRequest();
384  for (unsigned int i = 0; i < res.size(); i++)
385  if (res[i] != -1)
386  request_list[(unsigned)res[i]]->decode();
387 
388  return res;
389 }
390 
408 std::vector<int> vpNetwork::receiveAndDecodeRequestFrom(const unsigned int &receptorEmitting)
409 {
410  std::vector<int> res = receiveRequestFrom(receptorEmitting);
411  for (unsigned int i = 0; i < res.size(); i++) {
412  if (res[i] != -1)
413  request_list[(unsigned)res[i]]->decode();
414  }
415 
416  return res;
417 }
418 
439 {
440  int res = receiveRequestOnce();
441  if (res != -1)
442  request_list[(unsigned)res]->decode();
443 
444  return res;
445 }
446 
468 int vpNetwork::receiveAndDecodeRequestOnceFrom(const unsigned int &receptorEmitting)
469 {
470  int res = receiveRequestOnceFrom(receptorEmitting);
471  if (res != -1)
472  request_list[(unsigned)res]->decode();
473 
474  return res;
475 }
476 
477 //######## Definition of Template Functions ########
478 //# #
479 //##################################################
480 
492 std::vector<int> vpNetwork::privHandleRequests()
493 {
494  std::vector<int> resIndex;
495  int index = privHandleFirstRequest();
496 
497  while (index != -1) {
498  resIndex.push_back(index);
499  index = privHandleFirstRequest();
500  }
501 
502  return resIndex;
503 }
504 
515 int vpNetwork::privHandleFirstRequest()
516 {
517  size_t indStart = currentMessageReceived.find(beginning);
518  size_t indSep = currentMessageReceived.find(separator);
519  size_t indEnd = currentMessageReceived.find(end);
520 
521  if (indStart == std::string::npos && indSep == std::string::npos && indEnd == std::string::npos) {
522  if (currentMessageReceived.size() != 0)
523  currentMessageReceived.clear();
524 
525  if (verboseMode)
526  vpTRACE("Incorrect message");
527 
528  return -1;
529  }
530 
531  if (indStart == std::string::npos || indSep == std::string::npos || indEnd == std::string::npos)
532  return -1;
533 
534  if (indEnd < indStart) {
535  if (verboseMode)
536  vpTRACE("Incorrect message");
537  currentMessageReceived.erase((unsigned)indStart, indEnd + end.size());
538  return -1;
539  }
540 
541  size_t indStart2 = currentMessageReceived.find(beginning, indStart + 1);
542  if (indStart2 != std::string::npos && indStart2 < indEnd) {
543  if (verboseMode)
544  vpTRACE("Incorrect message");
545  currentMessageReceived.erase((unsigned)indStart, (unsigned)indStart2);
546  return -1;
547  }
548 
549  size_t deb = indStart + beginning.size();
550  std::string id = currentMessageReceived.substr((unsigned)deb, indSep - deb);
551 
552  // deb = indSep+separator.size();
553  // std::string params = currentMessageReceived.substr((unsigned)deb,
554  // (unsigned)(indEnd - deb));
555 
556  // std::cout << "Handling : " << currentMessageReceived.substr(indStart,
557  // indEnd+end.size() - indStart) << std::endl;
558 
559  int indRequest = 0;
560  bool hasBeenFound = false;
561  for (unsigned int i = 0; i < request_list.size(); i++) {
562  if (id == request_list[i]->getId()) {
563  hasBeenFound = true;
564  request_list[i]->clear();
565  indRequest = (int)i;
566  break;
567  }
568  }
569 
570  if (!hasBeenFound) {
571  // currentMessageReceived.erase(indStart,indEnd+end.size());
572  if (verboseMode)
573  vpTRACE("No request corresponds to the received message");
574  return -1;
575  }
576 
577  size_t indDebParam = indSep + separator.size();
578  size_t indEndParam = currentMessageReceived.find(param_sep, indDebParam);
579 
580  std::string param;
581  while (indEndParam != std::string::npos || indEndParam < indEnd) {
582  param = currentMessageReceived.substr((unsigned)indDebParam, (unsigned)(indEndParam - indDebParam));
583  request_list[(unsigned)indRequest]->addParameter(param);
584  indDebParam = indEndParam + param_sep.size();
585  indEndParam = currentMessageReceived.find(param_sep, indDebParam);
586  }
587 
588  param = currentMessageReceived.substr((unsigned)indDebParam, indEnd - indDebParam);
589  request_list[(unsigned)indRequest]->addParameter(param);
590  currentMessageReceived.erase(indStart, indEnd + end.size());
591 
592  return indRequest;
593 }
594 
609 void vpNetwork::privReceiveRequest()
610 {
611  while (privReceiveRequestOnce() > 0) {
612  };
613 }
614 
632 void vpNetwork::privReceiveRequestFrom(const unsigned int &receptorEmitting)
633 {
634  while (privReceiveRequestOnceFrom(receptorEmitting) > 0) {
635  };
636 }
637 
656 int vpNetwork::privReceiveRequestOnce()
657 {
658  if (receptor_list.size() == 0) {
659  if (verboseMode)
660  vpTRACE("No Receptor!");
661  return -1;
662  }
663 
664  tv.tv_sec = tv_sec;
665 #ifdef TARGET_OS_IPHONE
666  tv.tv_usec = (int)tv_usec;
667 #else
668  tv.tv_usec = tv_usec;
669 #endif
670 
671  FD_ZERO(&readFileDescriptor);
672 
673  for (unsigned int i = 0; i < receptor_list.size(); i++) {
674  if (i == 0)
675  socketMax = receptor_list[i].socketFileDescriptorReceptor;
676 
677  FD_SET((unsigned)receptor_list[i].socketFileDescriptorReceptor, &readFileDescriptor);
678  if (socketMax < receptor_list[i].socketFileDescriptorReceptor)
679  socketMax = receptor_list[i].socketFileDescriptorReceptor;
680  }
681 
682  int value = select((int)socketMax + 1, &readFileDescriptor, nullptr, nullptr, &tv);
683  int numbytes = 0;
684 
685  if (value == -1) {
686  if (verboseMode)
687  vpERROR_TRACE("Select error");
688  return -1;
689  }
690  else if (value == 0) {
691  // Timeout
692  return 0;
693  }
694  else {
695  for (unsigned int i = 0; i < receptor_list.size(); i++) {
696  if (FD_ISSET((unsigned int)receptor_list[i].socketFileDescriptorReceptor, &readFileDescriptor)) {
697  char *buf = new char[max_size_message];
698 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
699  numbytes = (int)recv(receptor_list[i].socketFileDescriptorReceptor, buf, max_size_message, 0);
700 #else
701  numbytes = recv((unsigned int)receptor_list[i].socketFileDescriptorReceptor, buf, (int)max_size_message, 0);
702 #endif
703 
704  if (numbytes <= 0) {
705  std::cout << "Disconnected : " << inet_ntoa(receptor_list[i].receptorAddress.sin_addr) << std::endl;
706  receptor_list.erase(receptor_list.begin() + (int)i);
707  delete[] buf;
708  return numbytes;
709  }
710  else {
711  std::string returnVal(buf, (unsigned int)numbytes);
712  currentMessageReceived.append(returnVal);
713  }
714  delete[] buf;
715  break;
716  }
717  }
718  }
719 
720  return numbytes;
721 }
722 
744 int vpNetwork::privReceiveRequestOnceFrom(const unsigned int &receptorEmitting)
745 {
746  int size = (int)receptor_list.size();
747  int sizeMinusOne = (int)receptor_list.size() - 1;
748  if (size == 0 || receptorEmitting > (unsigned)sizeMinusOne) {
749  if (verboseMode)
750  vpTRACE("No receptor at the specified index!");
751  return -1;
752  }
753 
754  tv.tv_sec = tv_sec;
755 #ifdef TARGET_OS_IPHONE
756  tv.tv_usec = (int)tv_usec;
757 #else
758  tv.tv_usec = tv_usec;
759 #endif
760 
761  FD_ZERO(&readFileDescriptor);
762 
763  socketMax = receptor_list[receptorEmitting].socketFileDescriptorReceptor;
764  FD_SET((unsigned int)receptor_list[receptorEmitting].socketFileDescriptorReceptor, &readFileDescriptor);
765 
766  int value = select((int)socketMax + 1, &readFileDescriptor, nullptr, nullptr, &tv);
767  int numbytes = 0;
768  if (value == -1) {
769  if (verboseMode)
770  vpERROR_TRACE("Select error");
771  return -1;
772  }
773  else if (value == 0) {
774  // Timeout
775  return 0;
776  }
777  else {
778  if (FD_ISSET((unsigned int)receptor_list[receptorEmitting].socketFileDescriptorReceptor, &readFileDescriptor)) {
779  char *buf = new char[max_size_message];
780 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
781  numbytes = (int)recv(receptor_list[receptorEmitting].socketFileDescriptorReceptor, buf, max_size_message, 0);
782 #else
783  numbytes = recv((unsigned int)receptor_list[receptorEmitting].socketFileDescriptorReceptor, buf,
784  (int)max_size_message, 0);
785 #endif
786  if (numbytes <= 0) {
787  std::cout << "Disconnected : " << inet_ntoa(receptor_list[receptorEmitting].receptorAddress.sin_addr)
788  << std::endl;
789  receptor_list.erase(receptor_list.begin() + (int)receptorEmitting);
790  delete[] buf;
791  return numbytes;
792  }
793  else {
794  std::string returnVal(buf, (unsigned int)numbytes);
795  currentMessageReceived.append(returnVal);
796  }
797  delete[] buf;
798  }
799  }
800 
801  return numbytes;
802 }
803 END_VISP_NAMESPACE
804 #elif !defined(VISP_BUILD_SHARED_LIBS)
805 // Work around to avoid warning: libvisp_core.a(vpNetwork.cpp.o) has no symbols
806 void dummy_vpNetwork() { };
807 #endif
virtual ~vpNetwork()
Definition: vpNetwork.cpp:71
long tv_sec
Definition: vpNetwork.h:157
int receiveRequestOnce()
Definition: vpNetwork.cpp:334
std::vector< int > receiveAndDecodeRequestFrom(const unsigned int &receptorEmitting)
Definition: vpNetwork.cpp:408
int sendRequest(vpRequest &req)
Definition: vpNetwork.cpp:179
fd_set readFileDescriptor
Definition: vpNetwork.h:138
bool verboseMode
Definition: vpNetwork.h:160
std::string currentMessageReceived
Definition: vpNetwork.h:154
int sendAndEncodeRequestTo(vpRequest &req, const unsigned int &dest)
Definition: vpNetwork.cpp:267
std::vector< vpRequest * > request_list
Definition: vpNetwork.h:146
int sendAndEncodeRequest(vpRequest &req)
Definition: vpNetwork.cpp:247
int receiveAndDecodeRequestOnce()
Definition: vpNetwork.cpp:438
long tv_usec
Definition: vpNetwork.h:158
std::string beginning
Definition: vpNetwork.h:150
std::vector< int > receiveRequest()
Definition: vpNetwork.cpp:287
int sendRequestTo(vpRequest &req, const unsigned int &dest)
Definition: vpNetwork.cpp:195
SOCKET socketMax
Definition: vpNetwork.h:142
std::vector< vpReceptor > receptor_list
Definition: vpNetwork.h:137
void addDecodingRequest(vpRequest *)
Definition: vpNetwork.cpp:89
struct timeval tv
Definition: vpNetwork.h:156
std::vector< int > receiveRequestFrom(const unsigned int &receptorEmitting)
Definition: vpNetwork.cpp:310
std::vector< int > receiveAndDecodeRequest()
Definition: vpNetwork.cpp:381
void removeDecodingRequest(const char *)
Definition: vpNetwork.cpp:114
int receiveAndDecodeRequestOnceFrom(const unsigned int &receptorEmitting)
Definition: vpNetwork.cpp:468
void print(const char *id="")
Definition: vpNetwork.cpp:129
std::string separator
Definition: vpNetwork.h:149
std::string param_sep
Definition: vpNetwork.h:152
int receiveRequestOnceFrom(const unsigned int &receptorEmitting)
Definition: vpNetwork.cpp:361
int getReceptorIndex(const char *name)
Definition: vpNetwork.cpp:144
unsigned int max_size_message
Definition: vpNetwork.h:148
std::string end
Definition: vpNetwork.h:151
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