Visual Servoing Platform version 3.7.0
Loading...
Searching...
No Matches
vpNetwork.cpp
1/*
2 * ViSP, open source Visual Servoing Platform software.
3 * Copyright (C) 2005 - 2025 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#include <visp3/core/vpConfig.h>
35
36// Specific case for UWP to introduce a workaround
37// error C4996: 'gethostbyname': Use getaddrinfo() or GetAddrInfoW() instead or define _WINSOCK_DEPRECATED_NO_WARNINGS to disable deprecated API warnings
38#if defined(WINRT) || defined(_WIN32)
39#ifndef _WINSOCK_DEPRECATED_NO_WARNINGS
40#define _WINSOCK_DEPRECATED_NO_WARNINGS
41#endif
42#endif
43
44// inet_ntop() not supported on win XP
45#ifdef VISP_HAVE_FUNC_INET_NTOP
46
47#include <visp3/core/vpNetwork.h>
48#include <visp3/core/vpDebug.h>
52 separator("[*@*]"), beginning("[*start*]"), end("[*end*]"), param_sep("[*|*]"), currentMessageReceived(), tv(),
53 tv_sec(0), tv_usec(10), verboseMode(false)
54{
55 tv.tv_sec = tv_sec;
56#ifdef TARGET_OS_IPHONE
57 tv.tv_usec = static_cast<int>(tv_usec);
58#else
59 tv.tv_usec = tv_usec;
60#endif
61
62#if defined(_WIN32)
63 // Enable the sockets to be used
64 // Note that: if we were using "winsock.h" instead of "winsock2.h" we would
65 // had to use: WSAStartup(MAKEWORD(1,0), &WSAData);
66 WSADATA WSAData;
67 WSAStartup(MAKEWORD(2, 0), &WSAData);
68#endif
69}
70
72{
73 *this = network;
74}
75
77{
78 emitter = network.emitter;
81 socketMax = network.socketMax;
82 request_list = network.request_list;
84 separator = network.separator;
85 beginning = network.beginning;
86 end = network.end;
87 param_sep = network.param_sep;
89 tv = network.tv;
90 tv_sec = network.tv_sec;
91 tv_usec = network.tv_usec;
92 verboseMode = network.verboseMode;
93
94#if defined(_WIN32)
95// Enable the sockets to be used
96// Note that: if we were using "winsock.h" instead of "winsock2.h" we would
97// had to use: WSAStartup(MAKEWORD(1,0), &WSAData);
98 WSADATA WSAData;
99 WSAStartup(MAKEWORD(2, 0), &WSAData);
100#endif
101
102 return *this;
103}
104
106{
107#if defined(_WIN32)
108 WSACleanup();
109#endif
110}
111
124{
125 bool alreadyHas = false;
126
127 for (unsigned int i = 0; i < request_list.size(); i++)
128 if (request_list[i]->getId() == req->getId()) {
129 alreadyHas = true;
130 break;
131 }
132
133 if (alreadyHas)
134 std::cout << "Server already has one request with the similar ID. "
135 "Request hasn't been added."
136 << std::endl;
137 else
138 request_list.push_back(req);
139}
140
149{
150 for (unsigned int i = 0; i < request_list.size(); i++) {
151 if (request_list[i]->getId() == id) {
152 request_list.erase(request_list.begin() + static_cast<int>(i));
153 break;
154 }
155 }
156}
157
163void vpNetwork::print(const char *id)
164{
165 for (unsigned int i = 0; i < receptor_list.size(); i++) {
166 std::cout << id << i << " : " << inet_ntoa(receptor_list[i].receptorAddress.sin_addr) << std::endl;
167 }
168}
169
178int vpNetwork::getReceptorIndex(const char *name)
179{
180 struct hostent *server = gethostbyname(name);
181
182 if (server == nullptr) {
183 std::string noSuchHostMessage("ERROR, ");
184 noSuchHostMessage.append(name);
185 noSuchHostMessage.append(": no such host\n");
186 vpERROR_TRACE(noSuchHostMessage.c_str(), "vpNetwork::getReceptorIndex()");
187 return -1;
188 }
189
190 std::string ip = inet_ntoa(*(in_addr *)server->h_addr);
191
192 for (int i = 0; i < static_cast<int>(receptor_list.size()); i++) {
193 if (receptor_list[static_cast<unsigned int>(i)].receptorIP == ip)
194 return i;
195 }
196
197 return -1;
198}
199
213int vpNetwork::sendRequest(vpRequest &req) { return sendRequestTo(req, 0); }
214
229int vpNetwork::sendRequestTo(vpRequest &req, const unsigned int &dest)
230{
231 int size = static_cast<int>(receptor_list.size());
232 int sizeMinusOne = static_cast<int>(receptor_list.size() - 1);
233 if (size == 0 || dest > static_cast<unsigned int>(sizeMinusOne)) {
234 if (verboseMode)
235 vpTRACE("Cannot Send Request! Bad Index");
236 return 0;
237 }
238
239 std::string message = beginning + req.getId() + separator;
240
241 if (req.size() != 0) {
242 message += req[0];
243
244 for (unsigned int i = 1; i < req.size(); i++) {
245 message += param_sep + req[i];
246 }
247 }
248
249 message += end;
250
251 int flags = 0;
252//#if ! defined(APPLE) && ! defined(SOLARIS) && ! defined(_WIN32)
253#if defined(__linux__)
254 flags = MSG_NOSIGNAL; // Only for Linux
255#endif
256
257#if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
258 int value = static_cast<int>(sendto(receptor_list[dest].socketFileDescriptorReceptor, message.c_str(), message.size(), flags,
259 (sockaddr *)&receptor_list[dest].receptorAddress, receptor_list[dest].receptorAddressSize));
260#else
261 int value = sendto(static_cast<unsigned int>(receptor_list[dest].socketFileDescriptorReceptor), message.c_str(), static_cast<int>(message.size()),
262 flags, (sockaddr *)&receptor_list[dest].receptorAddress, receptor_list[dest].receptorAddressSize);
263#endif
264
265 return value;
266}
267
282{
283 req.encode();
284 return sendRequest(req);
285}
286
301int vpNetwork::sendAndEncodeRequestTo(vpRequest &req, const unsigned int &dest)
302{
303 req.encode();
304 return sendRequestTo(req, dest);
305}
306
322{
323 privReceiveRequest();
324 return privHandleRequests();
325}
326
344std::vector<int> vpNetwork::receiveRequestFrom(const unsigned int &receptorEmitting)
345{
346 privReceiveRequestFrom(receptorEmitting);
347 return privHandleRequests();
348}
349
369{
370 privReceiveRequestOnce();
371 return privHandleFirstRequest();
372}
373
395int vpNetwork::receiveRequestOnceFrom(const unsigned int &receptorEmitting)
396{
397 privReceiveRequestOnceFrom(receptorEmitting);
398 return privHandleFirstRequest();
399}
400
416{
417 std::vector<int> res = receiveRequest();
418 for (unsigned int i = 0; i < res.size(); i++)
419 if (res[i] != -1)
420 request_list[static_cast<unsigned int>(res[i])]->decode();
421
422 return res;
423}
424
442std::vector<int> vpNetwork::receiveAndDecodeRequestFrom(const unsigned int &receptorEmitting)
443{
444 std::vector<int> res = receiveRequestFrom(receptorEmitting);
445 for (unsigned int i = 0; i < res.size(); i++) {
446 if (res[i] != -1)
447 request_list[static_cast<unsigned int>(res[i])]->decode();
448 }
449
450 return res;
451}
452
473{
474 int res = receiveRequestOnce();
475 if (res != -1)
476 request_list[static_cast<unsigned int>(res)]->decode();
477
478 return res;
479}
480
502int vpNetwork::receiveAndDecodeRequestOnceFrom(const unsigned int &receptorEmitting)
503{
504 int res = receiveRequestOnceFrom(receptorEmitting);
505 if (res != -1)
506 request_list[static_cast<unsigned int>(res)]->decode();
507
508 return res;
509}
510
511//######## Definition of Template Functions ########
512//# #
513//##################################################
514
526std::vector<int> vpNetwork::privHandleRequests()
527{
528 std::vector<int> resIndex;
529 int index = privHandleFirstRequest();
530
531 while (index != -1) {
532 resIndex.push_back(index);
533 index = privHandleFirstRequest();
534 }
535
536 return resIndex;
537}
538
549int vpNetwork::privHandleFirstRequest()
550{
551 size_t indStart = currentMessageReceived.find(beginning);
552 size_t indSep = currentMessageReceived.find(separator);
553 size_t indEnd = currentMessageReceived.find(end);
554
555 if (indStart == std::string::npos && indSep == std::string::npos && indEnd == std::string::npos) {
556 if (currentMessageReceived.size() != 0)
558
559 if (verboseMode)
560 vpTRACE("Incorrect message");
561
562 return -1;
563 }
564
565 if (indStart == std::string::npos || indSep == std::string::npos || indEnd == std::string::npos)
566 return -1;
567
568 if (indEnd < indStart) {
569 if (verboseMode)
570 vpTRACE("Incorrect message");
571 currentMessageReceived.erase(static_cast<unsigned int>(indStart), indEnd + end.size());
572 return -1;
573 }
574
575 size_t indStart2 = currentMessageReceived.find(beginning, indStart + 1);
576 if (indStart2 != std::string::npos && indStart2 < indEnd) {
577 if (verboseMode)
578 vpTRACE("Incorrect message");
579 currentMessageReceived.erase(static_cast<unsigned int>(indStart), static_cast<unsigned int>(indStart2));
580 return -1;
581 }
582
583 size_t deb = indStart + beginning.size();
584 std::string id = currentMessageReceived.substr(static_cast<unsigned int>(deb), indSep - deb);
585
586 int indRequest = 0;
587 bool hasBeenFound = false;
588 for (unsigned int i = 0; i < request_list.size(); i++) {
589 if (id == request_list[i]->getId()) {
590 hasBeenFound = true;
591 request_list[i]->clear();
592 indRequest = static_cast<int>(i);
593 break;
594 }
595 }
596
597 if (!hasBeenFound) {
598 // currentMessageReceived.erase(indStart,indEnd+end.size());
599 if (verboseMode)
600 vpTRACE("No request corresponds to the received message");
601 return -1;
602 }
603
604 size_t indDebParam = indSep + separator.size();
605 size_t indEndParam = currentMessageReceived.find(param_sep, indDebParam);
606
607 std::string param;
608 while (indEndParam != std::string::npos || indEndParam < indEnd) {
609 param = currentMessageReceived.substr(static_cast<unsigned int>(indDebParam), static_cast<unsigned int>(indEndParam - indDebParam));
610 request_list[static_cast<unsigned int>(indRequest)]->addParameter(param);
611 indDebParam = indEndParam + param_sep.size();
612 indEndParam = currentMessageReceived.find(param_sep, indDebParam);
613 }
614
615 param = currentMessageReceived.substr(static_cast<unsigned int>(indDebParam), indEnd - indDebParam);
616 request_list[static_cast<unsigned int>(indRequest)]->addParameter(param);
617 currentMessageReceived.erase(indStart, indEnd + end.size());
618
619 return indRequest;
620}
621
636void vpNetwork::privReceiveRequest()
637{
638 while (privReceiveRequestOnce() > 0) {
639 }
640}
641
659void vpNetwork::privReceiveRequestFrom(const unsigned int &receptorEmitting)
660{
661 while (privReceiveRequestOnceFrom(receptorEmitting) > 0) {
662 }
663}
664
683int vpNetwork::privReceiveRequestOnce()
684{
685 if (receptor_list.size() == 0) {
686 if (verboseMode)
687 vpTRACE("No Receptor!");
688 return -1;
689 }
690
691 tv.tv_sec = tv_sec;
692#ifdef TARGET_OS_IPHONE
693 tv.tv_usec = static_cast<int>(tv_usec);
694#else
695 tv.tv_usec = tv_usec;
696#endif
697
698 FD_ZERO(&readFileDescriptor);
699
700 for (unsigned int i = 0; i < receptor_list.size(); i++) {
701 if (i == 0)
702 socketMax = receptor_list[i].socketFileDescriptorReceptor;
703
704 FD_SET(static_cast<unsigned int>(receptor_list[i].socketFileDescriptorReceptor), &readFileDescriptor);
705 if (socketMax < receptor_list[i].socketFileDescriptorReceptor)
706 socketMax = receptor_list[i].socketFileDescriptorReceptor;
707 }
708
709 int value = select(static_cast<int>(socketMax) + 1, &readFileDescriptor, nullptr, nullptr, &tv);
710 int numbytes = 0;
711
712 if (value == -1) {
713 if (verboseMode)
714 vpERROR_TRACE("Select error");
715 return -1;
716 }
717 else if (value == 0) {
718 // Timeout
719 return 0;
720 }
721 else {
722 for (unsigned int i = 0; i < receptor_list.size(); i++) {
723 if (FD_ISSET(static_cast<unsigned int>(receptor_list[i].socketFileDescriptorReceptor), &readFileDescriptor)) {
724 char *buf = new char[max_size_message];
725#if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
726 numbytes = static_cast<int>(recv(receptor_list[i].socketFileDescriptorReceptor, buf, max_size_message, 0));
727#else
728 numbytes = recv(static_cast<unsigned int>(receptor_list[i].socketFileDescriptorReceptor), buf, static_cast<int>(max_size_message), 0);
729#endif
730
731 if (numbytes <= 0) {
732 std::cout << "Disconnected : " << inet_ntoa(receptor_list[i].receptorAddress.sin_addr) << std::endl;
733 receptor_list.erase(receptor_list.begin() + static_cast<int>(i));
734 delete[] buf;
735 return numbytes;
736 }
737 else {
738 std::string returnVal(buf, static_cast<unsigned int>(numbytes));
739 currentMessageReceived.append(returnVal);
740 }
741 delete[] buf;
742 break;
743 }
744 }
745 }
746
747 return numbytes;
748}
749
771int vpNetwork::privReceiveRequestOnceFrom(const unsigned int &receptorEmitting)
772{
773 int size = static_cast<int>(receptor_list.size());
774 int sizeMinusOne = static_cast<int>(receptor_list.size()) - 1;
775 if (size == 0 || receptorEmitting > static_cast<unsigned int>(sizeMinusOne)) {
776 if (verboseMode)
777 vpTRACE("No receptor at the specified index!");
778 return -1;
779 }
780
781 tv.tv_sec = tv_sec;
782#ifdef TARGET_OS_IPHONE
783 tv.tv_usec = static_cast<int>(tv_usec);
784#else
785 tv.tv_usec = tv_usec;
786#endif
787
788 FD_ZERO(&readFileDescriptor);
789
790 socketMax = receptor_list[receptorEmitting].socketFileDescriptorReceptor;
791 FD_SET(static_cast<unsigned int>(receptor_list[receptorEmitting].socketFileDescriptorReceptor), &readFileDescriptor);
792
793 int value = select(static_cast<int>(socketMax) + 1, &readFileDescriptor, nullptr, nullptr, &tv);
794 int numbytes = 0;
795 if (value == -1) {
796 if (verboseMode)
797 vpERROR_TRACE("Select error");
798 return -1;
799 }
800 else if (value == 0) {
801 // Timeout
802 return 0;
803 }
804 else {
805 if (FD_ISSET(static_cast<unsigned int>(receptor_list[receptorEmitting].socketFileDescriptorReceptor), &readFileDescriptor)) {
806 char *buf = new char[max_size_message];
807#if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
808 numbytes = static_cast<int>(recv(receptor_list[receptorEmitting].socketFileDescriptorReceptor, buf, max_size_message, 0));
809#else
810 numbytes = recv(static_cast<unsigned int>(receptor_list[receptorEmitting].socketFileDescriptorReceptor), buf,
811 static_cast<int>(max_size_message), 0);
812#endif
813 if (numbytes <= 0) {
814 std::cout << "Disconnected : " << inet_ntoa(receptor_list[receptorEmitting].receptorAddress.sin_addr)
815 << std::endl;
816 receptor_list.erase(receptor_list.begin() + static_cast<int>(receptorEmitting));
817 delete[] buf;
818 return numbytes;
819 }
820 else {
821 std::string returnVal(buf, static_cast<unsigned int>(numbytes));
822 currentMessageReceived.append(returnVal);
823 }
824 delete[] buf;
825 }
826 }
827
828 return numbytes;
829}
830END_VISP_NAMESPACE
831#elif !defined(VISP_BUILD_SHARED_LIBS)
832// Work around to avoid warning: libvisp_core.a(vpNetwork.cpp.o) has no symbols
833void dummy_vpNetwork() { }
834#endif
virtual ~vpNetwork()
long tv_sec
Definition vpNetwork.h:167
int receiveRequestOnce()
vpNetwork & operator=(const vpNetwork &network)
Definition vpNetwork.cpp:76
std::vector< int > receiveAndDecodeRequestFrom(const unsigned int &receptorEmitting)
int sendRequest(vpRequest &req)
int socketMax
Definition vpNetwork.h:150
fd_set readFileDescriptor
Definition vpNetwork.h:148
bool verboseMode
Definition vpNetwork.h:170
std::string currentMessageReceived
Definition vpNetwork.h:164
int sendAndEncodeRequestTo(vpRequest &req, const unsigned int &dest)
std::vector< vpRequest * > request_list
Definition vpNetwork.h:156
int sendAndEncodeRequest(vpRequest &req)
int receiveAndDecodeRequestOnce()
long tv_usec
Definition vpNetwork.h:168
std::string beginning
Definition vpNetwork.h:160
std::vector< int > receiveRequest()
int sendRequestTo(vpRequest &req, const unsigned int &dest)
std::vector< vpReceptor > receptor_list
Definition vpNetwork.h:147
void addDecodingRequest(vpRequest *)
struct timeval tv
Definition vpNetwork.h:166
std::vector< int > receiveRequestFrom(const unsigned int &receptorEmitting)
std::vector< int > receiveAndDecodeRequest()
void removeDecodingRequest(const char *)
vpEmitter emitter
Definition vpNetwork.h:146
int receiveAndDecodeRequestOnceFrom(const unsigned int &receptorEmitting)
void print(const char *id="")
std::string separator
Definition vpNetwork.h:159
std::string param_sep
Definition vpNetwork.h:162
int receiveRequestOnceFrom(const unsigned int &receptorEmitting)
int getReceptorIndex(const char *name)
unsigned int max_size_message
Definition vpNetwork.h:158
std::string end
Definition vpNetwork.h:161
This the request that will transit on the network.
Definition vpRequest.h:128
virtual void encode()=0
std::string getId() const
Definition vpRequest.h:193
unsigned int size() const
Definition vpRequest.h:209
#define vpTRACE
Definition vpDebug.h:450
#define vpERROR_TRACE
Definition vpDebug.h:423