Visual Servoing Platform  version 3.6.1 under development (2024-12-04)
vpNetwork.h
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 #ifndef VP_NETWORK_H
35 #define VP_NETWORK_H
36 
37 // Specific case for UWP to introduce a workaround
38 // error C4996: 'gethostbyname': Use getaddrinfo() or GetAddrInfoW() instead or define _WINSOCK_DEPRECATED_NO_WARNINGS to disable deprecated API warnings
39 #if defined(WINRT) || defined(_WIN32)
40 #ifndef _WINSOCK_DEPRECATED_NO_WARNINGS
41 #define _WINSOCK_DEPRECATED_NO_WARNINGS
42 #endif
43 #endif
44 
45 #include <visp3/core/vpConfig.h>
46 #include <visp3/core/vpDebug.h>
47 #include <visp3/core/vpRequest.h>
48 
49 #include <iostream>
50 #include <stdio.h>
51 #include <string.h>
52 #include <vector>
53 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
54 #include <sys/select.h>
55 #endif
56 
57  // inet_ntop() not supported on win XP
58 #ifdef VISP_HAVE_FUNC_INET_NTOP
59 
60 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
61 #include <arpa/inet.h>
62 #include <netdb.h>
63 #include <netinet/in.h>
64 #include <sys/socket.h>
65 #include <unistd.h>
66 #else
67 #include <io.h>
68 //# include<winsock.h>
69 #include <winsock2.h>
70 //# pragma comment(lib, "ws2_32.lib") // Done by CMake in main CMakeLists.txt
71 #endif
72 
73 #if defined(__APPLE__) && defined(__MACH__) // Apple OSX and iOS (Darwin)
74 #include <TargetConditionals.h> // To detect OSX or IOS using TARGET_OS_IPHONE or TARGET_OS_IOS macro
75 #endif
76 
77 BEGIN_VISP_NAMESPACE
95 class VISP_EXPORT vpNetwork
96 {
97 protected:
98 #ifndef DOXYGEN_SHOULD_SKIP_THIS
99  struct vpReceptor
100  {
101 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
102  int socketFileDescriptorReceptor;
103  socklen_t receptorAddressSize;
104 #else
105  SOCKET socketFileDescriptorReceptor;
106  int receptorAddressSize;
107 #endif
108  struct sockaddr_in receptorAddress;
109  std::string receptorIP;
110 
111  vpReceptor() : socketFileDescriptorReceptor(0), receptorAddressSize(), receptorAddress(), receptorIP() { }
112  };
113 
114  struct vpEmitter
115  {
116  struct sockaddr_in emitterAddress;
117 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
118  int socketFileDescriptorEmitter;
119 #else
120  SOCKET socketFileDescriptorEmitter;
121 #endif
122  vpEmitter() : emitterAddress(), socketFileDescriptorEmitter(0)
123  {
124  emitterAddress.sin_family = AF_INET;
125  emitterAddress.sin_addr.s_addr = INADDR_ANY;
126  emitterAddress.sin_port = 0;
127  socketFileDescriptorEmitter = 0;
128  }
129  };
130 #endif
131 
132  //######## PARAMETERS ########
133  //# #
134  //############################
135 
136  vpEmitter emitter;
137  std::vector<vpReceptor> receptor_list;
139 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
140  int socketMax;
141 #else
142  SOCKET socketMax;
143 #endif
144 
145  // Message Handling
146  std::vector<vpRequest *> request_list;
147 
148  unsigned int max_size_message;
149  std::string separator;
150  std::string beginning;
151  std::string end;
152  std::string param_sep;
153 
155 
156  struct timeval tv;
157  long tv_sec;
158  long tv_usec;
159 
161 
162 private:
163  std::vector<int> privHandleRequests();
164  int privHandleFirstRequest();
165 
166  void privReceiveRequest();
167  void privReceiveRequestFrom(const unsigned int &receptorEmitting);
168  int privReceiveRequestOnce();
169  int privReceiveRequestOnceFrom(const unsigned int &receptorEmitting);
170 
171 public:
172  vpNetwork();
173  virtual ~vpNetwork();
174 
175  void addDecodingRequest(vpRequest *);
176 
177  int getReceptorIndex(const char *name);
178 
186  std::string getRequestIdFromIndex(const int &ind)
187  {
188  if (ind >= (int)request_list.size() || ind < 0)
189  return "";
190  return request_list[(unsigned)ind]->getId();
191  }
192 
200  unsigned int getMaxSizeReceivedMessage() { return max_size_message; }
201 
202  void print(const char *id = "");
203 
204  template <typename T> int receive(T *object, const unsigned int &sizeOfObject = sizeof(T));
205  template <typename T>
206  int receiveFrom(T *object, const unsigned int &receptorEmitting, const unsigned int &sizeOfObject = sizeof(T));
207 
208  std::vector<int> receiveRequest();
209  std::vector<int> receiveRequestFrom(const unsigned int &receptorEmitting);
210  int receiveRequestOnce();
211  int receiveRequestOnceFrom(const unsigned int &receptorEmitting);
212 
213  std::vector<int> receiveAndDecodeRequest();
214  std::vector<int> receiveAndDecodeRequestFrom(const unsigned int &receptorEmitting);
215  int receiveAndDecodeRequestOnce();
216  int receiveAndDecodeRequestOnceFrom(const unsigned int &receptorEmitting);
217 
218  void removeDecodingRequest(const char *);
219 
220  template <typename T> int send(T *object, const int unsigned &sizeOfObject = sizeof(T));
221  template <typename T> int sendTo(T *object, const unsigned int &dest, const unsigned int &sizeOfObject = sizeof(T));
222 
223  int sendRequest(vpRequest &req);
224  int sendRequestTo(vpRequest &req, const unsigned int &dest);
225 
226  int sendAndEncodeRequest(vpRequest &req);
227  int sendAndEncodeRequestTo(vpRequest &req, const unsigned int &dest);
228 
236  void setMaxSizeReceivedMessage(const unsigned int &s) { max_size_message = s; }
237 
246  void setTimeoutSec(const long &sec) { tv_sec = sec; }
247 
256  void setTimeoutUSec(const long &usec) { tv_usec = usec; }
257 
263  void setVerbose(const bool &mode) { verboseMode = mode; }
264 };
265 
266 //######## Definition of Template Functions ########
267 //# #
268 //##################################################
269 
290 template <typename T> int vpNetwork::receive(T *object, const unsigned int &sizeOfObject)
291 {
292  if (receptor_list.size() == 0) {
293  if (verboseMode)
294  vpTRACE("No receptor");
295  return -1;
296  }
297 
298  tv.tv_sec = tv_sec;
299 #ifdef TARGET_OS_IPHONE
300  tv.tv_usec = (int)tv_usec;
301 #else
302  tv.tv_usec = tv_usec;
303 #endif
304 
305  FD_ZERO(&readFileDescriptor);
306 
307  for (unsigned int i = 0; i < receptor_list.size(); i++) {
308  FD_SET((unsigned int)receptor_list[i].socketFileDescriptorReceptor, &readFileDescriptor);
309 
310  if (i == 0)
311  socketMax = receptor_list[i].socketFileDescriptorReceptor;
312 
313  if (socketMax < receptor_list[i].socketFileDescriptorReceptor)
314  socketMax = receptor_list[i].socketFileDescriptorReceptor;
315  }
316 
317  int value = select((int)socketMax + 1, &readFileDescriptor, nullptr, nullptr, &tv);
318  int numbytes = 0;
319 
320  if (value == -1) {
321  if (verboseMode)
322  vpERROR_TRACE("Select error");
323  return -1;
324  }
325  else if (value == 0) {
326  // Timeout
327  return 0;
328  }
329  else {
330  for (unsigned int i = 0; i < receptor_list.size(); i++) {
331  if (FD_ISSET((unsigned int)receptor_list[i].socketFileDescriptorReceptor, &readFileDescriptor)) {
332 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
333  numbytes = recv(receptor_list[i].socketFileDescriptorReceptor, (char *)(void *)object, sizeOfObject, 0);
334 #else
335  numbytes = recv((unsigned int)receptor_list[i].socketFileDescriptorReceptor, (char *)(void *)object,
336  (int)sizeOfObject, 0);
337 #endif
338  if (numbytes <= 0) {
339  std::cout << "Disconnected : " << inet_ntoa(receptor_list[i].receptorAddress.sin_addr) << std::endl;
340  receptor_list.erase(receptor_list.begin() + (int)i);
341  return numbytes;
342  }
343 
344  break;
345  }
346  }
347  }
348 
349  return numbytes;
350 }
351 
373 template <typename T>
374 int vpNetwork::receiveFrom(T *object, const unsigned int &receptorEmitting, const unsigned int &sizeOfObject)
375 {
376  if (receptor_list.size() == 0 || receptorEmitting > (unsigned int)receptor_list.size() - 1) {
377  if (verboseMode)
378  vpTRACE("No receptor at the specified index");
379  return -1;
380  }
381 
382  tv.tv_sec = tv_sec;
383 #ifdef TARGET_OS_IPHONE
384  tv.tv_usec = (int)tv_usec;
385 #else
386  tv.tv_usec = tv_usec;
387 #endif
388 
389  FD_ZERO(&readFileDescriptor);
390 
391  socketMax = receptor_list[receptorEmitting].socketFileDescriptorReceptor;
392  FD_SET((unsigned int)receptor_list[receptorEmitting].socketFileDescriptorReceptor, &readFileDescriptor);
393 
394  int value = select((int)socketMax + 1, &readFileDescriptor, nullptr, nullptr, &tv);
395  int numbytes = 0;
396 
397  if (value == -1) {
398  if (verboseMode)
399  vpERROR_TRACE("Select error");
400  return -1;
401  }
402  else if (value == 0) {
403  // timeout
404  return 0;
405  }
406  else {
407  if (FD_ISSET((unsigned int)receptor_list[receptorEmitting].socketFileDescriptorReceptor, &readFileDescriptor)) {
408 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
409  numbytes =
410  recv(receptor_list[receptorEmitting].socketFileDescriptorReceptor, (char *)(void *)object, sizeOfObject, 0);
411 #else
412  numbytes = recv((unsigned int)receptor_list[receptorEmitting].socketFileDescriptorReceptor,
413  (char *)(void *)object, (int)sizeOfObject, 0);
414 #endif
415  if (numbytes <= 0) {
416  std::cout << "Disconnected : " << inet_ntoa(receptor_list[receptorEmitting].receptorAddress.sin_addr)
417  << std::endl;
418  receptor_list.erase(receptor_list.begin() + (int)receptorEmitting);
419  return numbytes;
420  }
421  }
422  }
423 
424  return numbytes;
425 }
426 
448 template <typename T> int vpNetwork::send(T *object, const unsigned int &sizeOfObject)
449 {
450  if (receptor_list.size() == 0) {
451  if (verboseMode)
452  vpTRACE("No receptor !");
453  return 0;
454  }
455 
456  int flags = 0;
457  //#if ! defined(APPLE) && ! defined(SOLARIS) && ! defined(_WIN32)
458 #if defined(__linux__)
459  flags = MSG_NOSIGNAL; // Only for Linux
460 #endif
461 
462 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
463  return sendto(receptor_list[0].socketFileDescriptorReceptor, (const char *)(void *)object, sizeOfObject, flags,
464  (sockaddr *)&receptor_list[0].receptorAddress, receptor_list[0].receptorAddressSize);
465 #else
466  return sendto(receptor_list[0].socketFileDescriptorReceptor, (const char *)(void *)object, (int)sizeOfObject, flags,
467  (sockaddr *)&receptor_list[0].receptorAddress, receptor_list[0].receptorAddressSize);
468 #endif
469 }
470 
492 template <typename T> int vpNetwork::sendTo(T *object, const unsigned int &dest, const unsigned int &sizeOfObject)
493 {
494  if (receptor_list.size() == 0 || dest > (unsigned int)receptor_list.size() - 1) {
495  if (verboseMode)
496  vpTRACE("No receptor at the specified index.");
497  return 0;
498  }
499 
500  int flags = 0;
501  //#if ! defined(APPLE) && ! defined(SOLARIS) && ! defined(_WIN32)
502 #if defined(__linux__)
503  flags = MSG_NOSIGNAL; // Only for Linux
504 #endif
505 
506 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
507  return sendto(receptor_list[dest].socketFileDescriptorReceptor, (const char *)(void *)object, sizeOfObject, flags,
508  (sockaddr *)&receptor_list[dest].receptorAddress, receptor_list[dest].receptorAddressSize);
509 #else
510  return sendto(receptor_list[dest].socketFileDescriptorReceptor, (const char *)(void *)object, (int)sizeOfObject,
511  flags, (sockaddr *)&receptor_list[dest].receptorAddress, receptor_list[dest].receptorAddressSize);
512 #endif
513 }
514 END_VISP_NAMESPACE
515 #endif
516 #endif
This class represents a Transmission Control Protocol (TCP) network.
Definition: vpNetwork.h:96
int sendTo(T *object, const unsigned int &dest, const unsigned int &sizeOfObject=sizeof(T))
Definition: vpNetwork.h:492
long tv_sec
Definition: vpNetwork.h:157
std::string getRequestIdFromIndex(const int &ind)
Definition: vpNetwork.h:186
fd_set readFileDescriptor
Definition: vpNetwork.h:138
void setTimeoutUSec(const long &usec)
Definition: vpNetwork.h:256
int receiveFrom(T *object, const unsigned int &receptorEmitting, const unsigned int &sizeOfObject=sizeof(T))
Definition: vpNetwork.h:374
void setVerbose(const bool &mode)
Definition: vpNetwork.h:263
bool verboseMode
Definition: vpNetwork.h:160
std::string currentMessageReceived
Definition: vpNetwork.h:154
std::vector< vpRequest * > request_list
Definition: vpNetwork.h:146
int send(T *object, const int unsigned &sizeOfObject=sizeof(T))
long tv_usec
Definition: vpNetwork.h:158
std::string beginning
Definition: vpNetwork.h:150
SOCKET socketMax
Definition: vpNetwork.h:142
std::vector< vpReceptor > receptor_list
Definition: vpNetwork.h:137
struct timeval tv
Definition: vpNetwork.h:156
vpEmitter emitter
Definition: vpNetwork.h:136
void setTimeoutSec(const long &sec)
Definition: vpNetwork.h:246
int receive(T *object, const unsigned int &sizeOfObject=sizeof(T))
Definition: vpNetwork.h:290
std::string separator
Definition: vpNetwork.h:149
std::string param_sep
Definition: vpNetwork.h:152
unsigned int getMaxSizeReceivedMessage()
Definition: vpNetwork.h:200
unsigned int max_size_message
Definition: vpNetwork.h:148
void setMaxSizeReceivedMessage(const unsigned int &s)
Definition: vpNetwork.h:236
std::string end
Definition: vpNetwork.h:151
This the request that will transit on the network.
Definition: vpRequest.h:128