Visual Servoing Platform  version 3.6.1 under development (2024-04-19)
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 vpNetwork_H
35 #define vpNetwork_H
36 
37 #include <visp3/core/vpConfig.h>
38 #include <visp3/core/vpRequest.h>
39 
40 #include <iostream>
41 #include <stdio.h>
42 #include <string.h>
43 #include <vector>
44 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
45 #include <sys/select.h>
46 #endif
47 
48  // inet_ntop() not supported on win XP
49 #ifdef VISP_HAVE_FUNC_INET_NTOP
50 
51 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
52 #include <arpa/inet.h>
53 #include <netdb.h>
54 #include <netinet/in.h>
55 #include <sys/socket.h>
56 #include <unistd.h>
57 #else
58 #include <io.h>
59 //# include<winsock.h>
60 #include <winsock2.h>
61 //# pragma comment(lib, "ws2_32.lib") // Done by CMake in main CMakeLists.txt
62 #endif
63 
64 #if defined(__APPLE__) && defined(__MACH__) // Apple OSX and iOS (Darwin)
65 #include <TargetConditionals.h> // To detect OSX or IOS using TARGET_OS_IPHONE or TARGET_OS_IOS macro
66 #endif
67 
85 class VISP_EXPORT vpNetwork
86 {
87 protected:
88 #ifndef DOXYGEN_SHOULD_SKIP_THIS
89  struct vpReceptor
90  {
91 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
92  int socketFileDescriptorReceptor;
93  socklen_t receptorAddressSize;
94 #else
95  SOCKET socketFileDescriptorReceptor;
96  int receptorAddressSize;
97 #endif
98  struct sockaddr_in receptorAddress;
99  std::string receptorIP;
100 
101  vpReceptor() : socketFileDescriptorReceptor(0), receptorAddressSize(), receptorAddress(), receptorIP() { }
102  };
103 
104  struct vpEmitter
105  {
106  struct sockaddr_in emitterAddress;
107 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
108  int socketFileDescriptorEmitter;
109 #else
110  SOCKET socketFileDescriptorEmitter;
111 #endif
112  vpEmitter() : emitterAddress(), socketFileDescriptorEmitter(0)
113  {
114  emitterAddress.sin_family = AF_INET;
115  emitterAddress.sin_addr.s_addr = INADDR_ANY;
116  emitterAddress.sin_port = 0;
117  socketFileDescriptorEmitter = 0;
118  }
119  };
120 #endif
121 
122  //######## PARAMETERS ########
123  //# #
124  //############################
125 
126  vpEmitter emitter;
127  std::vector<vpReceptor> receptor_list;
129 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
131 #else
132  SOCKET socketMax;
133 #endif
134 
135  // Message Handling
136  std::vector<vpRequest *> request_list;
137 
138  unsigned int max_size_message;
139  std::string separator;
140  std::string beginning;
141  std::string end;
142  std::string param_sep;
143 
145 
146  struct timeval tv;
147  long tv_sec;
148  long tv_usec;
149 
151 
152 private:
153  std::vector<int> privHandleRequests();
154  int privHandleFirstRequest();
155 
156  void privReceiveRequest();
157  void privReceiveRequestFrom(const unsigned int &receptorEmitting);
158  int privReceiveRequestOnce();
159  int privReceiveRequestOnceFrom(const unsigned int &receptorEmitting);
160 
161 public:
162  vpNetwork();
163  virtual ~vpNetwork();
164 
165  void addDecodingRequest(vpRequest *);
166 
167  int getReceptorIndex(const char *name);
168 
176  std::string getRequestIdFromIndex(const int &ind)
177  {
178  if (ind >= (int)request_list.size() || ind < 0)
179  return "";
180  return request_list[(unsigned)ind]->getId();
181  }
182 
190  unsigned int getMaxSizeReceivedMessage() { return max_size_message; }
191 
192  void print(const char *id = "");
193 
194  template <typename T> int receive(T *object, const unsigned int &sizeOfObject = sizeof(T));
195  template <typename T>
196  int receiveFrom(T *object, const unsigned int &receptorEmitting, const unsigned int &sizeOfObject = sizeof(T));
197 
198  std::vector<int> receiveRequest();
199  std::vector<int> receiveRequestFrom(const unsigned int &receptorEmitting);
200  int receiveRequestOnce();
201  int receiveRequestOnceFrom(const unsigned int &receptorEmitting);
202 
203  std::vector<int> receiveAndDecodeRequest();
204  std::vector<int> receiveAndDecodeRequestFrom(const unsigned int &receptorEmitting);
205  int receiveAndDecodeRequestOnce();
206  int receiveAndDecodeRequestOnceFrom(const unsigned int &receptorEmitting);
207 
208  void removeDecodingRequest(const char *);
209 
210  template <typename T> int send(T *object, const int unsigned &sizeOfObject = sizeof(T));
211  template <typename T> int sendTo(T *object, const unsigned int &dest, const unsigned int &sizeOfObject = sizeof(T));
212 
213  int sendRequest(vpRequest &req);
214  int sendRequestTo(vpRequest &req, const unsigned int &dest);
215 
216  int sendAndEncodeRequest(vpRequest &req);
217  int sendAndEncodeRequestTo(vpRequest &req, const unsigned int &dest);
218 
226  void setMaxSizeReceivedMessage(const unsigned int &s) { max_size_message = s; }
227 
236  void setTimeoutSec(const long &sec) { tv_sec = sec; }
237 
246  void setTimeoutUSec(const long &usec) { tv_usec = usec; }
247 
253  void setVerbose(const bool &mode) { verboseMode = mode; }
254 };
255 
256 //######## Definition of Template Functions ########
257 //# #
258 //##################################################
259 
280 template <typename T> int vpNetwork::receive(T *object, const unsigned int &sizeOfObject)
281 {
282  if (receptor_list.size() == 0) {
283  if (verboseMode)
284  vpTRACE("No receptor");
285  return -1;
286  }
287 
288  tv.tv_sec = tv_sec;
289 #ifdef TARGET_OS_IPHONE
290  tv.tv_usec = (int)tv_usec;
291 #else
292  tv.tv_usec = tv_usec;
293 #endif
294 
295  FD_ZERO(&readFileDescriptor);
296 
297  for (unsigned int i = 0; i < receptor_list.size(); i++) {
298  FD_SET((unsigned int)receptor_list[i].socketFileDescriptorReceptor, &readFileDescriptor);
299 
300  if (i == 0)
301  socketMax = receptor_list[i].socketFileDescriptorReceptor;
302 
303  if (socketMax < receptor_list[i].socketFileDescriptorReceptor)
304  socketMax = receptor_list[i].socketFileDescriptorReceptor;
305  }
306 
307  int value = select((int)socketMax + 1, &readFileDescriptor, nullptr, nullptr, &tv);
308  int numbytes = 0;
309 
310  if (value == -1) {
311  if (verboseMode)
312  vpERROR_TRACE("Select error");
313  return -1;
314  }
315  else if (value == 0) {
316  // Timeout
317  return 0;
318  }
319  else {
320  for (unsigned int i = 0; i < receptor_list.size(); i++) {
321  if (FD_ISSET((unsigned int)receptor_list[i].socketFileDescriptorReceptor, &readFileDescriptor)) {
322 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
323  numbytes = recv(receptor_list[i].socketFileDescriptorReceptor, (char *)(void *)object, sizeOfObject, 0);
324 #else
325  numbytes = recv((unsigned int)receptor_list[i].socketFileDescriptorReceptor, (char *)(void *)object,
326  (int)sizeOfObject, 0);
327 #endif
328  if (numbytes <= 0) {
329  std::cout << "Disconnected : " << inet_ntoa(receptor_list[i].receptorAddress.sin_addr) << std::endl;
330  receptor_list.erase(receptor_list.begin() + (int)i);
331  return numbytes;
332  }
333 
334  break;
335  }
336  }
337  }
338 
339  return numbytes;
340 }
341 
363 template <typename T>
364 int vpNetwork::receiveFrom(T *object, const unsigned int &receptorEmitting, const unsigned int &sizeOfObject)
365 {
366  if (receptor_list.size() == 0 || receptorEmitting > (unsigned int)receptor_list.size() - 1) {
367  if (verboseMode)
368  vpTRACE("No receptor at the specified index");
369  return -1;
370  }
371 
372  tv.tv_sec = tv_sec;
373 #ifdef TARGET_OS_IPHONE
374  tv.tv_usec = (int)tv_usec;
375 #else
376  tv.tv_usec = tv_usec;
377 #endif
378 
379  FD_ZERO(&readFileDescriptor);
380 
381  socketMax = receptor_list[receptorEmitting].socketFileDescriptorReceptor;
382  FD_SET((unsigned int)receptor_list[receptorEmitting].socketFileDescriptorReceptor, &readFileDescriptor);
383 
384  int value = select((int)socketMax + 1, &readFileDescriptor, nullptr, nullptr, &tv);
385  int numbytes = 0;
386 
387  if (value == -1) {
388  if (verboseMode)
389  vpERROR_TRACE("Select error");
390  return -1;
391  }
392  else if (value == 0) {
393  // timeout
394  return 0;
395  }
396  else {
397  if (FD_ISSET((unsigned int)receptor_list[receptorEmitting].socketFileDescriptorReceptor, &readFileDescriptor)) {
398 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
399  numbytes =
400  recv(receptor_list[receptorEmitting].socketFileDescriptorReceptor, (char *)(void *)object, sizeOfObject, 0);
401 #else
402  numbytes = recv((unsigned int)receptor_list[receptorEmitting].socketFileDescriptorReceptor,
403  (char *)(void *)object, (int)sizeOfObject, 0);
404 #endif
405  if (numbytes <= 0) {
406  std::cout << "Disconnected : " << inet_ntoa(receptor_list[receptorEmitting].receptorAddress.sin_addr)
407  << std::endl;
408  receptor_list.erase(receptor_list.begin() + (int)receptorEmitting);
409  return numbytes;
410  }
411  }
412  }
413 
414  return numbytes;
415 }
416 
438 template <typename T> int vpNetwork::send(T *object, const unsigned int &sizeOfObject)
439 {
440  if (receptor_list.size() == 0) {
441  if (verboseMode)
442  vpTRACE("No receptor !");
443  return 0;
444  }
445 
446  int flags = 0;
447  //#if ! defined(APPLE) && ! defined(SOLARIS) && ! defined(_WIN32)
448 #if defined(__linux__)
449  flags = MSG_NOSIGNAL; // Only for Linux
450 #endif
451 
452 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
453  return sendto(receptor_list[0].socketFileDescriptorReceptor, (const char *)(void *)object, sizeOfObject, flags,
454  (sockaddr *)&receptor_list[0].receptorAddress, receptor_list[0].receptorAddressSize);
455 #else
456  return sendto(receptor_list[0].socketFileDescriptorReceptor, (const char *)(void *)object, (int)sizeOfObject, flags,
457  (sockaddr *)&receptor_list[0].receptorAddress, receptor_list[0].receptorAddressSize);
458 #endif
459 }
460 
482 template <typename T> int vpNetwork::sendTo(T *object, const unsigned int &dest, const unsigned int &sizeOfObject)
483 {
484  if (receptor_list.size() == 0 || dest > (unsigned int)receptor_list.size() - 1) {
485  if (verboseMode)
486  vpTRACE("No receptor at the specified index.");
487  return 0;
488  }
489 
490  int flags = 0;
491  //#if ! defined(APPLE) && ! defined(SOLARIS) && ! defined(_WIN32)
492 #if defined(__linux__)
493  flags = MSG_NOSIGNAL; // Only for Linux
494 #endif
495 
496 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
497  return sendto(receptor_list[dest].socketFileDescriptorReceptor, (const char *)(void *)object, sizeOfObject, flags,
498  (sockaddr *)&receptor_list[dest].receptorAddress, receptor_list[dest].receptorAddressSize);
499 #else
500  return sendto(receptor_list[dest].socketFileDescriptorReceptor, (const char *)(void *)object, (int)sizeOfObject,
501  flags, (sockaddr *)&receptor_list[dest].receptorAddress, receptor_list[dest].receptorAddressSize);
502 #endif
503 }
504 
505 #endif
506 #endif
This class represents a Transmission Control Protocol (TCP) network.
Definition: vpNetwork.h:86
int sendTo(T *object, const unsigned int &dest, const unsigned int &sizeOfObject=sizeof(T))
Definition: vpNetwork.h:482
long tv_sec
Definition: vpNetwork.h:147
std::string getRequestIdFromIndex(const int &ind)
Definition: vpNetwork.h:176
int socketMax
Definition: vpNetwork.h:130
fd_set readFileDescriptor
Definition: vpNetwork.h:128
void setTimeoutUSec(const long &usec)
Definition: vpNetwork.h:246
int receiveFrom(T *object, const unsigned int &receptorEmitting, const unsigned int &sizeOfObject=sizeof(T))
Definition: vpNetwork.h:364
void setVerbose(const bool &mode)
Definition: vpNetwork.h:253
bool verboseMode
Definition: vpNetwork.h:150
std::string currentMessageReceived
Definition: vpNetwork.h:144
std::vector< vpRequest * > request_list
Definition: vpNetwork.h:136
int send(T *object, const int unsigned &sizeOfObject=sizeof(T))
long tv_usec
Definition: vpNetwork.h:148
std::string beginning
Definition: vpNetwork.h:140
std::vector< vpReceptor > receptor_list
Definition: vpNetwork.h:127
struct timeval tv
Definition: vpNetwork.h:146
vpEmitter emitter
Definition: vpNetwork.h:126
void setTimeoutSec(const long &sec)
Definition: vpNetwork.h:236
int receive(T *object, const unsigned int &sizeOfObject=sizeof(T))
Definition: vpNetwork.h:280
std::string separator
Definition: vpNetwork.h:139
std::string param_sep
Definition: vpNetwork.h:142
unsigned int getMaxSizeReceivedMessage()
Definition: vpNetwork.h:190
unsigned int max_size_message
Definition: vpNetwork.h:138
void setMaxSizeReceivedMessage(const unsigned int &s)
Definition: vpNetwork.h:226
std::string end
Definition: vpNetwork.h:141
This the request that will transit on the network.
Definition: vpRequest.h:127
#define vpTRACE
Definition: vpDebug.h:405
#define vpERROR_TRACE
Definition: vpDebug.h:382