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