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