Visual Servoing Platform  version 3.0.1
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
vpNetwork.cpp
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
7  * modify it under the terms of the GNU General Public License
8  * ("GPL") version 2 as published by the Free Software Foundation.
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 http://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  * Authors:
34  * Aurelien Yol
35  *
36  *****************************************************************************/
37 
38 
39 #include <visp3/core/vpNetwork.h>
40 
42  : emitter(), receptor_list(), readFileDescriptor(), socketMax(0), request_list(),
43  max_size_message(999999), separator("[*@*]"), beginning("[*start*]"), end("[*end*]"),
44  param_sep("[*|*]"), currentMessageReceived(), tv(), tv_sec(0), tv_usec(10),
45  verboseMode(false)
46 {
47  tv.tv_sec = tv_sec;
48 #if TARGET_OS_IPHONE
49  tv.tv_usec = (int)tv_usec;
50 #else
51  tv.tv_usec = tv_usec;
52 #endif
53 
54 #if defined(_WIN32)
55  //Enable the sockets to be used
56  //Note that: if we were using "winsock.h" instead of "winsock2.h" we would had to use:
57  //WSAStartup(MAKEWORD(1,0), &WSAData);
58  WSADATA WSAData;
59  WSAStartup(MAKEWORD(2,0), &WSAData);
60 #endif
61 }
62 
64 {
65 #if defined(_WIN32)
66  WSACleanup();
67 #endif
68 }
69 
82 {
83  bool alreadyHas = false;
84 
85  for(unsigned int i = 0 ; i < request_list.size() ; i++)
86  if(request_list[i]->getId() == req->getId()){
87  alreadyHas = true;
88  break;
89  }
90 
91  if(alreadyHas)
92  std::cout << "Server already has one request with the similar ID. Request hasn't been added." << std::endl;
93  else
94  request_list.push_back(req);
95 }
96 
105 {
106  for(unsigned int i = 0 ; i < request_list.size() ; i++)
107  {
108  if(request_list[i]->getId() == id)
109  {
110  request_list.erase(request_list.begin()+(int)i);
111  break;
112  }
113  }
114 }
115 
121 void vpNetwork::print(const char *id)
122 {
123  for(unsigned int i = 0 ; i < receptor_list.size() ; i++)
124  {
125  std::cout << id << i << " : " << inet_ntoa(receptor_list[i].receptorAddress.sin_addr) << std::endl;
126  }
127 }
128 
136 int vpNetwork::getReceptorIndex(const char *name)
137 {
138  struct hostent *server = gethostbyname(name);
139 
140  if ( server == NULL )
141  {
142  std::string noSuchHostMessage( "ERROR, " );
143  noSuchHostMessage.append( name );
144  noSuchHostMessage.append( ": no such host\n" );
145  vpERROR_TRACE( noSuchHostMessage.c_str(), "vpNetwork::getReceptorIndex()" );
146  return -1;
147  }
148 
149  std::string ip = inet_ntoa(*(in_addr *)server->h_addr);
150 
151  for(int i = 0 ; i < (int)receptor_list.size() ; i++)
152  {
153  if(receptor_list[(unsigned)i].receptorIP == ip)
154  return i;
155  }
156 
157  return -1;
158 }
159 
174 {
175  return sendRequestTo(req,0);
176 }
177 
192 int vpNetwork::sendRequestTo(vpRequest &req, const unsigned int &dest)
193 {
194  int size = (int)receptor_list.size();
195  int sizeMinusOne = (int)receptor_list.size()-1;
196  if(size == 0 || dest > (unsigned)sizeMinusOne)
197  {
198  if(verboseMode)
199  vpTRACE( "Cannot Send Request! Bad Index" );
200  return 0;
201  }
202 
203  std::string message = beginning + req.getId() + separator;
204 
205  if(req.size() != 0){
206  message += req[0];
207 
208  for(unsigned int i = 1 ; i < req.size() ; i++){
209  message += param_sep + req[i];
210  }
211  }
212 
213  message += end;
214 
215  int flags = 0;
216 //#if ! defined(APPLE) && ! defined(SOLARIS) && ! defined(_WIN32)
217 #if defined(__linux__)
218  flags = MSG_NOSIGNAL; // Only for Linux
219 #endif
220 
221 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
222  int value = (int)sendto(receptor_list[dest].socketFileDescriptorReceptor, message.c_str(), message.size(), flags,
223  (sockaddr*) &receptor_list[dest].receptorAddress,receptor_list[dest].receptorAddressSize);
224 #else
225  int value = sendto((unsigned)receptor_list[dest].socketFileDescriptorReceptor, message.c_str(), (int)message.size(), flags,
226  (sockaddr*) &receptor_list[dest].receptorAddress,receptor_list[dest].receptorAddressSize);
227 #endif
228 
229  return value;
230 }
231 
246 {
247  req.encode();
248  return sendRequest(req);
249 }
250 
265 int vpNetwork::sendAndEncodeRequestTo(vpRequest &req, const unsigned int &dest)
266 {
267  req.encode();
268  return sendRequestTo(req,dest);
269 }
270 
285 std::vector<int> vpNetwork::receiveRequest()
286 {
287  _receiveRequest();
288  return _handleRequests();
289 }
290 
307 std::vector<int> vpNetwork::receiveRequestFrom(const unsigned int &receptorEmitting)
308 {
309  _receiveRequestFrom(receptorEmitting);
310  return _handleRequests();
311 }
312 
332 {
333  _receiveRequestOnce();
334  return _handleFirstRequest();
335 }
336 
357 int vpNetwork::receiveRequestOnceFrom(const unsigned int &receptorEmitting)
358 {
359  _receiveRequestOnceFrom(receptorEmitting);
360  return _handleFirstRequest();
361 }
362 
378 {
379  std::vector<int> res = receiveRequest();
380  for(unsigned int i = 0 ; i < res.size() ; i++)
381  if(res[i] != -1)
382  request_list[(unsigned)res[i]]->decode();
383 
384  return res;
385 }
386 
403 std::vector<int> vpNetwork::receiveAndDecodeRequestFrom(const unsigned int &receptorEmitting)
404 {
405  std::vector<int> res = receiveRequestFrom(receptorEmitting);
406  for(unsigned int i = 0 ; i < res.size() ; i++)
407  if(res[i] != -1)
408  request_list[(unsigned)res[i]]->decode();
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 
462 int 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 
472 //######## Definition of Template Functions ########
473 //# #
474 //##################################################
475 
476 
487 std::vector<int> vpNetwork::_handleRequests()
488 {
489  std::vector<int> resIndex;
490  int index = _handleFirstRequest();
491 
492  while(index != -1)
493  {
494  resIndex.push_back(index);
495  index = _handleFirstRequest();
496  }
497 
498  return resIndex;
499 }
500 
511 int vpNetwork::_handleFirstRequest()
512 {
513  size_t indStart = currentMessageReceived.find(beginning);
514  size_t indSep = currentMessageReceived.find(separator);
515  size_t indEnd = currentMessageReceived.find(end);
516 
517  if (indStart == std::string::npos && indSep == std::string::npos && indEnd == std::string::npos)
518  {
519  if(currentMessageReceived.size() != 0)
520  currentMessageReceived.clear();
521 
522  if(verboseMode)
523  vpTRACE("Incorrect message");
524 
525  return -1;
526  }
527 
528  if(indStart == std::string::npos || indSep == std::string::npos || indEnd == std::string::npos)
529  return -1;
530 
531  if(indEnd < indStart)
532  {
533  if(verboseMode)
534  vpTRACE("Incorrect message");
535  currentMessageReceived.erase((unsigned)indStart,indEnd+end.size());
536  return -1;
537  }
538 
539  size_t indStart2 = currentMessageReceived.find(beginning,indStart+1);
540  if(indStart2 != std::string::npos && indStart2 < indEnd)
541  {
542  if(verboseMode)
543  vpTRACE("Incorrect message");
544  currentMessageReceived.erase((unsigned)indStart,(unsigned)indStart2);
545  return -1;
546  }
547 
548  size_t deb = indStart + beginning.size();
549  std::string id = currentMessageReceived.substr((unsigned)deb, indSep - deb);
550 
551  //deb = indSep+separator.size();
552  //std::string params = currentMessageReceived.substr((unsigned)deb, (unsigned)(indEnd - deb));
553 
554 // std::cout << "Handling : " << currentMessageReceived.substr(indStart, indEnd+end.size() - indStart) << std::endl;
555 
556  int indRequest = 0;
557  bool hasBeenFound = false;
558  for(unsigned int i = 0 ; i < request_list.size() ; i++)
559  {
560  if(id == request_list[i]->getId()){
561  hasBeenFound = true;
562  request_list[i]->clear();
563  indRequest = (int)i;
564  break;
565  }
566  }
567 
568  if(!hasBeenFound){
569  //currentMessageReceived.erase(indStart,indEnd+end.size());
570  if(verboseMode)
571  vpTRACE("No request corresponds to the received message");
572  return -1;
573  }
574 
575  size_t indDebParam = indSep + separator.size();
576  size_t indEndParam = currentMessageReceived.find(param_sep,indDebParam);
577 
578  std::string param;
579  while(indEndParam != std::string::npos || indEndParam < indEnd)
580  {
581  param = currentMessageReceived.substr((unsigned)indDebParam,(unsigned)(indEndParam - indDebParam));
582  request_list[(unsigned)indRequest]->addParameter(param);
583  indDebParam = indEndParam+param_sep.size();
584  indEndParam = currentMessageReceived.find(param_sep,indDebParam);
585  }
586 
587  param = currentMessageReceived.substr((unsigned)indDebParam, indEnd - indDebParam);
588  request_list[(unsigned)indRequest]->addParameter(param);
589  currentMessageReceived.erase(indStart,indEnd+end.size());
590 
591  return indRequest;
592 }
593 
608 void vpNetwork::_receiveRequest()
609 {
610  while(_receiveRequestOnce() > 0) {};
611 }
612 
629 void vpNetwork::_receiveRequestFrom(const unsigned int &receptorEmitting)
630 {
631  while(_receiveRequestOnceFrom(receptorEmitting) > 0) {};
632 }
633 
652 int vpNetwork::_receiveRequestOnce()
653 {
654  if(receptor_list.size() == 0)
655  {
656  if(verboseMode)
657  vpTRACE( "No Receptor!" );
658  return -1;
659  }
660 
661  tv.tv_sec = tv_sec;
662 #if TARGET_OS_IPHONE
663  tv.tv_usec = (int)tv_usec;
664 #else
665  tv.tv_usec = tv_usec;
666 #endif
667 
668  FD_ZERO(&readFileDescriptor);
669 
670  for(unsigned int i=0; i<receptor_list.size(); i++){
671  if(i == 0)
672  socketMax = receptor_list[i].socketFileDescriptorReceptor;
673 
674  FD_SET((unsigned)receptor_list[i].socketFileDescriptorReceptor,&readFileDescriptor);
675  if(socketMax < receptor_list[i].socketFileDescriptorReceptor) socketMax = receptor_list[i].socketFileDescriptorReceptor;
676  }
677 
678  int value = select((int)socketMax+1,&readFileDescriptor,NULL,NULL,&tv);
679  int numbytes = 0;
680 
681  if(value == -1){
682  if(verboseMode)
683  vpERROR_TRACE( "Select error" );
684  return -1;
685  }
686  else if(value == 0){
687  //Timeout
688  return 0;
689  }
690  else{
691  for(unsigned int i=0; i<receptor_list.size(); i++){
692  if(FD_ISSET((unsigned int)receptor_list[i].socketFileDescriptorReceptor,&readFileDescriptor)){
693  char *buf = new char [max_size_message];
694 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
695  numbytes=(int)recv(receptor_list[i].socketFileDescriptorReceptor, buf, max_size_message, 0);
696 #else
697  numbytes=recv((unsigned int)receptor_list[i].socketFileDescriptorReceptor, buf, (int)max_size_message, 0);
698 #endif
699 
700  if(numbytes <= 0)
701  {
702  std::cout << "Disconnected : " << inet_ntoa(receptor_list[i].receptorAddress.sin_addr) << std::endl;
703  receptor_list.erase(receptor_list.begin()+(int)i);
704  delete [] buf;
705  return numbytes;
706  }
707  else if(numbytes > 0){
708  std::string returnVal(buf, (unsigned int)numbytes);
709  currentMessageReceived.append(returnVal);
710  }
711  delete [] buf;
712  break;
713  }
714  }
715  }
716 
717  return numbytes;
718 }
719 
740 int vpNetwork::_receiveRequestOnceFrom(const unsigned int &receptorEmitting)
741 {
742  int size = (int)receptor_list.size();
743  int sizeMinusOne = (int)receptor_list.size()-1;
744  if(size == 0 || receptorEmitting > (unsigned)sizeMinusOne )
745  {
746  if(verboseMode)
747  vpTRACE( "No receptor at the specified index!" );
748  return -1;
749  }
750 
751  tv.tv_sec = tv_sec;
752 #if TARGET_OS_IPHONE
753  tv.tv_usec = (int)tv_usec;
754 #else
755  tv.tv_usec = tv_usec;
756 #endif
757 
758  FD_ZERO(&readFileDescriptor);
759 
760  socketMax = receptor_list[receptorEmitting].socketFileDescriptorReceptor;
761  FD_SET((unsigned int)receptor_list[receptorEmitting].socketFileDescriptorReceptor,&readFileDescriptor);
762 
763  int value = select((int)socketMax+1,&readFileDescriptor,NULL,NULL,&tv);
764  int numbytes = 0;
765  if(value == -1){
766  if(verboseMode)
767  vpERROR_TRACE( "Select error" );
768  return -1;
769  }
770  else if(value == 0){
771  //Timeout
772  return 0;
773  }
774  else{
775  if(FD_ISSET((unsigned int)receptor_list[receptorEmitting].socketFileDescriptorReceptor,&readFileDescriptor)){
776  char *buf = new char [max_size_message];
777 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
778  numbytes=(int)recv(receptor_list[receptorEmitting].socketFileDescriptorReceptor, buf, max_size_message, 0);
779 #else
780  numbytes=recv((unsigned int)receptor_list[receptorEmitting].socketFileDescriptorReceptor, buf, (int)max_size_message, 0);
781 #endif
782  if(numbytes <= 0)
783  {
784  std::cout << "Disconnected : " << inet_ntoa(receptor_list[receptorEmitting].receptorAddress.sin_addr) << std::endl;
785  receptor_list.erase(receptor_list.begin()+(int)receptorEmitting);
786  delete [] buf;
787  return numbytes;
788  }
789  else if(numbytes > 0){
790  std::string returnVal(buf, (unsigned int)numbytes);
791  currentMessageReceived.append(returnVal);
792  }
793  delete [] buf;
794  }
795  }
796 
797  return numbytes;
798 }
799 
800 
801 
unsigned int max_size_message
Definition: vpNetwork.h:133
int receiveRequestOnce()
Definition: vpNetwork.cpp:331
std::string separator
Definition: vpNetwork.h:134
int receiveRequestOnceFrom(const unsigned int &receptorEmitting)
Definition: vpNetwork.cpp:357
std::string beginning
Definition: vpNetwork.h:135
This the request that will transit on the network.
Definition: vpRequest.h:130
std::vector< vpRequest * > request_list
Definition: vpNetwork.h:131
fd_set readFileDescriptor
Definition: vpNetwork.h:123
void print(const char *id="")
Definition: vpNetwork.cpp:121
#define vpERROR_TRACE
Definition: vpDebug.h:391
int receiveAndDecodeRequestOnceFrom(const unsigned int &receptorEmitting)
Definition: vpNetwork.cpp:462
int sendRequestTo(vpRequest &req, const unsigned int &dest)
Definition: vpNetwork.cpp:192
std::vector< int > receiveRequestFrom(const unsigned int &receptorEmitting)
Definition: vpNetwork.cpp:307
std::vector< int > receiveAndDecodeRequestFrom(const unsigned int &receptorEmitting)
Definition: vpNetwork.cpp:403
virtual void encode()=0
int socketMax
Definition: vpNetwork.h:125
virtual ~vpNetwork()
Definition: vpNetwork.cpp:63
std::vector< int > receiveAndDecodeRequest()
Definition: vpNetwork.cpp:377
std::string end
Definition: vpNetwork.h:136
#define vpTRACE
Definition: vpDebug.h:414
int sendAndEncodeRequestTo(vpRequest &req, const unsigned int &dest)
Definition: vpNetwork.cpp:265
unsigned int size()
Definition: vpRequest.h:202
int receiveAndDecodeRequestOnce()
Definition: vpNetwork.cpp:432
int sendAndEncodeRequest(vpRequest &req)
Definition: vpNetwork.cpp:245
long tv_sec
Definition: vpNetwork.h:142
bool verboseMode
Definition: vpNetwork.h:145
std::vector< int > receiveRequest()
Definition: vpNetwork.cpp:285
std::string getId()
Definition: vpRequest.h:186
struct timeval tv
Definition: vpNetwork.h:141
std::vector< vpReceptor > receptor_list
Definition: vpNetwork.h:122
int sendRequest(vpRequest &req)
Definition: vpNetwork.cpp:173
long tv_usec
Definition: vpNetwork.h:143
void removeDecodingRequest(const char *)
Definition: vpNetwork.cpp:104
std::string currentMessageReceived
Definition: vpNetwork.h:139
int getReceptorIndex(const char *name)
Definition: vpNetwork.cpp:136
void addDecodingRequest(vpRequest *)
Definition: vpNetwork.cpp:81
std::string param_sep
Definition: vpNetwork.h:137