Visual Servoing Platform version 3.5.0
vpNetwork.cpp
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#include <visp3/core/vpNetwork.h>
40
41// inet_ntop() not supported on win XP
42#ifdef VISP_HAVE_FUNC_INET_NTOP
43
45 : emitter(), receptor_list(), readFileDescriptor(), socketMax(0), request_list(), max_size_message(999999),
46 separator("[*@*]"), beginning("[*start*]"), end("[*end*]"), param_sep("[*|*]"), currentMessageReceived(), tv(),
47 tv_sec(0), tv_usec(10), verboseMode(false)
48{
49 tv.tv_sec = tv_sec;
50#if TARGET_OS_IPHONE
51 tv.tv_usec = (int)tv_usec;
52#else
53 tv.tv_usec = tv_usec;
54#endif
55
56#if defined(_WIN32)
57 // Enable the sockets to be used
58 // Note that: if we were using "winsock.h" instead of "winsock2.h" we would
59 // had to use: WSAStartup(MAKEWORD(1,0), &WSAData);
60 WSADATA WSAData;
61 WSAStartup(MAKEWORD(2, 0), &WSAData);
62#endif
63}
64
66{
67#if defined(_WIN32)
68 WSACleanup();
69#endif
70}
71
84{
85 bool alreadyHas = false;
86
87 for (unsigned int i = 0; i < request_list.size(); i++)
88 if (request_list[i]->getId() == req->getId()) {
89 alreadyHas = true;
90 break;
91 }
92
93 if (alreadyHas)
94 std::cout << "Server already has one request with the similar ID. "
95 "Request hasn't been added."
96 << std::endl;
97 else
98 request_list.push_back(req);
99}
100
109{
110 for (unsigned int i = 0; i < request_list.size(); i++) {
111 if (request_list[i]->getId() == id) {
112 request_list.erase(request_list.begin() + (int)i);
113 break;
114 }
115 }
116}
117
123void vpNetwork::print(const char *id)
124{
125 for (unsigned int i = 0; i < receptor_list.size(); i++) {
126 std::cout << id << i << " : " << inet_ntoa(receptor_list[i].receptorAddress.sin_addr) << std::endl;
127 }
128}
129
138int vpNetwork::getReceptorIndex(const char *name)
139{
140 struct hostent *server = gethostbyname(name);
141
142 if (server == NULL) {
143 std::string noSuchHostMessage("ERROR, ");
144 noSuchHostMessage.append(name);
145 noSuchHostMessage.append(": no such host\n");
146 vpERROR_TRACE(noSuchHostMessage.c_str(), "vpNetwork::getReceptorIndex()");
147 return -1;
148 }
149
150 std::string ip = inet_ntoa(*(in_addr *)server->h_addr);
151
152 for (int i = 0; i < (int)receptor_list.size(); i++) {
153 if (receptor_list[(unsigned)i].receptorIP == ip)
154 return i;
155 }
156
157 return -1;
158}
159
173int vpNetwork::sendRequest(vpRequest &req) { return sendRequestTo(req, 0); }
174
189int vpNetwork::sendRequestTo(vpRequest &req, const unsigned int &dest)
190{
191 int size = (int)receptor_list.size();
192 int sizeMinusOne = (int)receptor_list.size() - 1;
193 if (size == 0 || dest > (unsigned)sizeMinusOne) {
194 if (verboseMode)
195 vpTRACE("Cannot Send Request! Bad Index");
196 return 0;
197 }
198
199 std::string message = beginning + req.getId() + separator;
200
201 if (req.size() != 0) {
202 message += req[0];
203
204 for (unsigned int i = 1; i < req.size(); i++) {
205 message += param_sep + req[i];
206 }
207 }
208
209 message += end;
210
211 int flags = 0;
212//#if ! defined(APPLE) && ! defined(SOLARIS) && ! defined(_WIN32)
213#if defined(__linux__)
214 flags = MSG_NOSIGNAL; // Only for Linux
215#endif
216
217#if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
218 int value = (int)sendto(receptor_list[dest].socketFileDescriptorReceptor, message.c_str(), message.size(), flags,
219 (sockaddr *)&receptor_list[dest].receptorAddress, receptor_list[dest].receptorAddressSize);
220#else
221 int value = sendto((unsigned)receptor_list[dest].socketFileDescriptorReceptor, message.c_str(), (int)message.size(),
222 flags, (sockaddr *)&receptor_list[dest].receptorAddress, receptor_list[dest].receptorAddressSize);
223#endif
224
225 return value;
226}
227
242{
243 req.encode();
244 return sendRequest(req);
245}
246
261int vpNetwork::sendAndEncodeRequestTo(vpRequest &req, const unsigned int &dest)
262{
263 req.encode();
264 return sendRequestTo(req, dest);
265}
266
282{
283 _receiveRequest();
284 return _handleRequests();
285}
286
304std::vector<int> vpNetwork::receiveRequestFrom(const unsigned int &receptorEmitting)
305{
306 _receiveRequestFrom(receptorEmitting);
307 return _handleRequests();
308}
309
329{
330 _receiveRequestOnce();
331 return _handleFirstRequest();
332}
333
355int vpNetwork::receiveRequestOnceFrom(const unsigned int &receptorEmitting)
356{
357 _receiveRequestOnceFrom(receptorEmitting);
358 return _handleFirstRequest();
359}
360
376{
377 std::vector<int> res = receiveRequest();
378 for (unsigned int i = 0; i < res.size(); i++)
379 if (res[i] != -1)
380 request_list[(unsigned)res[i]]->decode();
381
382 return res;
383}
384
402std::vector<int> vpNetwork::receiveAndDecodeRequestFrom(const unsigned int &receptorEmitting)
403{
404 std::vector<int> res = receiveRequestFrom(receptorEmitting);
405 for (unsigned int i = 0; i < res.size(); i++) {
406 if (res[i] != -1)
407 request_list[(unsigned)res[i]]->decode();
408 }
409
410 return res;
411}
412
433{
434 int res = receiveRequestOnce();
435 if (res != -1)
436 request_list[(unsigned)res]->decode();
437
438 return res;
439}
440
462int vpNetwork::receiveAndDecodeRequestOnceFrom(const unsigned int &receptorEmitting)
463{
464 int res = receiveRequestOnceFrom(receptorEmitting);
465 if (res != -1)
466 request_list[(unsigned)res]->decode();
467
468 return res;
469}
470
471//######## Definition of Template Functions ########
472//# #
473//##################################################
474
486std::vector<int> vpNetwork::_handleRequests()
487{
488 std::vector<int> resIndex;
489 int index = _handleFirstRequest();
490
491 while (index != -1) {
492 resIndex.push_back(index);
493 index = _handleFirstRequest();
494 }
495
496 return resIndex;
497}
498
509int vpNetwork::_handleFirstRequest()
510{
511 size_t indStart = currentMessageReceived.find(beginning);
512 size_t indSep = currentMessageReceived.find(separator);
513 size_t indEnd = currentMessageReceived.find(end);
514
515 if (indStart == std::string::npos && indSep == std::string::npos && indEnd == std::string::npos) {
516 if (currentMessageReceived.size() != 0)
518
519 if (verboseMode)
520 vpTRACE("Incorrect message");
521
522 return -1;
523 }
524
525 if (indStart == std::string::npos || indSep == std::string::npos || indEnd == std::string::npos)
526 return -1;
527
528 if (indEnd < indStart) {
529 if (verboseMode)
530 vpTRACE("Incorrect message");
531 currentMessageReceived.erase((unsigned)indStart, indEnd + end.size());
532 return -1;
533 }
534
535 size_t indStart2 = currentMessageReceived.find(beginning, indStart + 1);
536 if (indStart2 != std::string::npos && indStart2 < indEnd) {
537 if (verboseMode)
538 vpTRACE("Incorrect message");
539 currentMessageReceived.erase((unsigned)indStart, (unsigned)indStart2);
540 return -1;
541 }
542
543 size_t deb = indStart + beginning.size();
544 std::string id = currentMessageReceived.substr((unsigned)deb, indSep - deb);
545
546 // deb = indSep+separator.size();
547 // std::string params = currentMessageReceived.substr((unsigned)deb,
548 // (unsigned)(indEnd - deb));
549
550 // std::cout << "Handling : " << currentMessageReceived.substr(indStart,
551 // indEnd+end.size() - indStart) << std::endl;
552
553 int indRequest = 0;
554 bool hasBeenFound = false;
555 for (unsigned int i = 0; i < request_list.size(); i++) {
556 if (id == request_list[i]->getId()) {
557 hasBeenFound = true;
558 request_list[i]->clear();
559 indRequest = (int)i;
560 break;
561 }
562 }
563
564 if (!hasBeenFound) {
565 // currentMessageReceived.erase(indStart,indEnd+end.size());
566 if (verboseMode)
567 vpTRACE("No request corresponds to the received message");
568 return -1;
569 }
570
571 size_t indDebParam = indSep + separator.size();
572 size_t indEndParam = currentMessageReceived.find(param_sep, indDebParam);
573
574 std::string param;
575 while (indEndParam != std::string::npos || indEndParam < indEnd) {
576 param = currentMessageReceived.substr((unsigned)indDebParam, (unsigned)(indEndParam - indDebParam));
577 request_list[(unsigned)indRequest]->addParameter(param);
578 indDebParam = indEndParam + param_sep.size();
579 indEndParam = currentMessageReceived.find(param_sep, indDebParam);
580 }
581
582 param = currentMessageReceived.substr((unsigned)indDebParam, indEnd - indDebParam);
583 request_list[(unsigned)indRequest]->addParameter(param);
584 currentMessageReceived.erase(indStart, indEnd + end.size());
585
586 return indRequest;
587}
588
603void vpNetwork::_receiveRequest()
604{
605 while (_receiveRequestOnce() > 0) {
606 };
607}
608
626void vpNetwork::_receiveRequestFrom(const unsigned int &receptorEmitting)
627{
628 while (_receiveRequestOnceFrom(receptorEmitting) > 0) {
629 };
630}
631
650int vpNetwork::_receiveRequestOnce()
651{
652 if (receptor_list.size() == 0) {
653 if (verboseMode)
654 vpTRACE("No Receptor!");
655 return -1;
656 }
657
658 tv.tv_sec = tv_sec;
659#if TARGET_OS_IPHONE
660 tv.tv_usec = (int)tv_usec;
661#else
662 tv.tv_usec = tv_usec;
663#endif
664
665 FD_ZERO(&readFileDescriptor);
666
667 for (unsigned int i = 0; i < receptor_list.size(); i++) {
668 if (i == 0)
669 socketMax = receptor_list[i].socketFileDescriptorReceptor;
670
671 FD_SET((unsigned)receptor_list[i].socketFileDescriptorReceptor, &readFileDescriptor);
672 if (socketMax < receptor_list[i].socketFileDescriptorReceptor)
673 socketMax = receptor_list[i].socketFileDescriptorReceptor;
674 }
675
676 int value = select((int)socketMax + 1, &readFileDescriptor, NULL, NULL, &tv);
677 int numbytes = 0;
678
679 if (value == -1) {
680 if (verboseMode)
681 vpERROR_TRACE("Select error");
682 return -1;
683 } else if (value == 0) {
684 // Timeout
685 return 0;
686 } else {
687 for (unsigned int i = 0; i < receptor_list.size(); i++) {
688 if (FD_ISSET((unsigned int)receptor_list[i].socketFileDescriptorReceptor, &readFileDescriptor)) {
689 char *buf = new char[max_size_message];
690#if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
691 numbytes = (int)recv(receptor_list[i].socketFileDescriptorReceptor, buf, max_size_message, 0);
692#else
693 numbytes = recv((unsigned int)receptor_list[i].socketFileDescriptorReceptor, buf, (int)max_size_message, 0);
694#endif
695
696 if (numbytes <= 0) {
697 std::cout << "Disconnected : " << inet_ntoa(receptor_list[i].receptorAddress.sin_addr) << std::endl;
698 receptor_list.erase(receptor_list.begin() + (int)i);
699 delete[] buf;
700 return numbytes;
701 } else {
702 std::string returnVal(buf, (unsigned int)numbytes);
703 currentMessageReceived.append(returnVal);
704 }
705 delete[] buf;
706 break;
707 }
708 }
709 }
710
711 return numbytes;
712}
713
735int vpNetwork::_receiveRequestOnceFrom(const unsigned int &receptorEmitting)
736{
737 int size = (int)receptor_list.size();
738 int sizeMinusOne = (int)receptor_list.size() - 1;
739 if (size == 0 || receptorEmitting > (unsigned)sizeMinusOne) {
740 if (verboseMode)
741 vpTRACE("No receptor at the specified index!");
742 return -1;
743 }
744
745 tv.tv_sec = tv_sec;
746#if TARGET_OS_IPHONE
747 tv.tv_usec = (int)tv_usec;
748#else
749 tv.tv_usec = tv_usec;
750#endif
751
752 FD_ZERO(&readFileDescriptor);
753
754 socketMax = receptor_list[receptorEmitting].socketFileDescriptorReceptor;
755 FD_SET((unsigned int)receptor_list[receptorEmitting].socketFileDescriptorReceptor, &readFileDescriptor);
756
757 int value = select((int)socketMax + 1, &readFileDescriptor, NULL, NULL, &tv);
758 int numbytes = 0;
759 if (value == -1) {
760 if (verboseMode)
761 vpERROR_TRACE("Select error");
762 return -1;
763 } else if (value == 0) {
764 // Timeout
765 return 0;
766 } else {
767 if (FD_ISSET((unsigned int)receptor_list[receptorEmitting].socketFileDescriptorReceptor, &readFileDescriptor)) {
768 char *buf = new char[max_size_message];
769#if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
770 numbytes = (int)recv(receptor_list[receptorEmitting].socketFileDescriptorReceptor, buf, max_size_message, 0);
771#else
772 numbytes = recv((unsigned int)receptor_list[receptorEmitting].socketFileDescriptorReceptor, buf,
773 (int)max_size_message, 0);
774#endif
775 if (numbytes <= 0) {
776 std::cout << "Disconnected : " << inet_ntoa(receptor_list[receptorEmitting].receptorAddress.sin_addr)
777 << std::endl;
778 receptor_list.erase(receptor_list.begin() + (int)receptorEmitting);
779 delete[] buf;
780 return numbytes;
781 } else {
782 std::string returnVal(buf, (unsigned int)numbytes);
783 currentMessageReceived.append(returnVal);
784 }
785 delete[] buf;
786 }
787 }
788
789 return numbytes;
790}
791
792#elif !defined(VISP_BUILD_SHARED_LIBS)
793// Work arround to avoid warning: libvisp_core.a(vpNetwork.cpp.o) has no symbols
794void dummy_vpNetwork(){};
795#endif
virtual ~vpNetwork()
Definition: vpNetwork.cpp:65
long tv_sec
Definition: vpNetwork.h:150
int receiveRequestOnce()
Definition: vpNetwork.cpp:328
std::vector< int > receiveAndDecodeRequestFrom(const unsigned int &receptorEmitting)
Definition: vpNetwork.cpp:402
int sendRequest(vpRequest &req)
Definition: vpNetwork.cpp:173
int socketMax
Definition: vpNetwork.h:133
fd_set readFileDescriptor
Definition: vpNetwork.h:131
bool verboseMode
Definition: vpNetwork.h:153
std::string currentMessageReceived
Definition: vpNetwork.h:147
int sendAndEncodeRequestTo(vpRequest &req, const unsigned int &dest)
Definition: vpNetwork.cpp:261
std::vector< vpRequest * > request_list
Definition: vpNetwork.h:139
int sendAndEncodeRequest(vpRequest &req)
Definition: vpNetwork.cpp:241
int receiveAndDecodeRequestOnce()
Definition: vpNetwork.cpp:432
long tv_usec
Definition: vpNetwork.h:151
std::string beginning
Definition: vpNetwork.h:143
std::vector< int > receiveRequest()
Definition: vpNetwork.cpp:281
int sendRequestTo(vpRequest &req, const unsigned int &dest)
Definition: vpNetwork.cpp:189
std::vector< vpReceptor > receptor_list
Definition: vpNetwork.h:130
void addDecodingRequest(vpRequest *)
Definition: vpNetwork.cpp:83
struct timeval tv
Definition: vpNetwork.h:149
std::vector< int > receiveRequestFrom(const unsigned int &receptorEmitting)
Definition: vpNetwork.cpp:304
std::vector< int > receiveAndDecodeRequest()
Definition: vpNetwork.cpp:375
void removeDecodingRequest(const char *)
Definition: vpNetwork.cpp:108
int receiveAndDecodeRequestOnceFrom(const unsigned int &receptorEmitting)
Definition: vpNetwork.cpp:462
void print(const char *id="")
Definition: vpNetwork.cpp:123
std::string separator
Definition: vpNetwork.h:142
std::string param_sep
Definition: vpNetwork.h:145
int receiveRequestOnceFrom(const unsigned int &receptorEmitting)
Definition: vpNetwork.cpp:355
int getReceptorIndex(const char *name)
Definition: vpNetwork.cpp:138
unsigned int max_size_message
Definition: vpNetwork.h:141
std::string end
Definition: vpNetwork.h:144
This the request that will transit on the network.
Definition: vpRequest.h:132
unsigned int size()
Definition: vpRequest.h:202
virtual void encode()=0
std::string getId()
Definition: vpRequest.h:186
#define vpTRACE
Definition: vpDebug.h:416
#define vpERROR_TRACE
Definition: vpDebug.h:393