otsdaq  v2_05_02_indev
TCPClientBase.cc
1 #include "otsdaq/NetworkUtilities/TCPClientBase.h"
2 
3 #include <arpa/inet.h> // inet_aton
4 #include <netdb.h>
5 #include <netinet/in.h> // inet_aton, struct sockaddr_in
6 #include <strings.h> // bzero
7 #include <boost/regex.hpp>
8 #include <iostream>
9 #include <thread>
10 
11 using namespace ots;
12 
13 //==============================================================================
14 TCPClientBase::TCPClientBase(const std::string& serverIP, int serverPort) : fServerIP(serverIP), fServerPort(serverPort), fConnected(false) {}
15 
16 //==============================================================================
17 TCPClientBase::~TCPClientBase(void)
18 {
19  std::cout << __PRETTY_FUNCTION__ << "Closing TCPSocket #" << getSocketId() << std::endl;
20  if(fConnected)
21  close();
22  std::cout << __PRETTY_FUNCTION__ << "TCPSocket #" << getSocketId() << " closed." << std::endl;
23 }
24 
25 //==============================================================================
26 bool TCPClientBase::connect(int retry, unsigned int sleepMilliSeconds)
27 {
28  if(fConnected)
29  {
30  std::cout << __PRETTY_FUNCTION__ << "I am already connected...what is going on?" << std::endl;
31  throw std::runtime_error(std::string("I am already connected...what is going on?"));
32  abort();
33  }
34 
35  std::cout << __PRETTY_FUNCTION__ << "Connecting Client socket to server name-" << fServerIP << "-serverPort: " << fServerPort << std::endl;
36  std::string serverName = fServerIP;
37  resolveServer(fServerIP);
38  std::cout << __PRETTY_FUNCTION__ << "Connecting Client socket to server ip -" << fServerIP << "-serverPort: " << fServerPort << std::endl;
39  int status = invalidSocketId;
40  struct sockaddr_in serverSocketAddress;
41  serverSocketAddress.sin_family = AF_INET;
42  serverSocketAddress.sin_port = htons(fServerPort);
43  serverSocketAddress.sin_addr.s_addr = inet_addr(fServerIP.c_str());
44 
45  while(!fConnected && (unsigned int)retry-- > 0)
46  {
47  // std::cout << __PRETTY_FUNCTION__ << "Trying to connect" << std::endl;
48  TCPSocket::open();
49  status = ::connect(getSocketId(), (struct sockaddr*)&serverSocketAddress, sizeof(serverSocketAddress));
50  // std::cout << __PRETTY_FUNCTION__ << "Done Connect" << std::endl;
51  if(status == -1)
52  {
53  if((unsigned int)retry > 0)
54  {
55  std::cout << __PRETTY_FUNCTION__ << "WARNING: Can't connect to " << serverName << ". The server might still be down...Sleeping "
56  << sleepMilliSeconds << "ms and then retry " << (unsigned int)retry << " more times." << std::endl;
57  std::this_thread::sleep_for(std::chrono::milliseconds(sleepMilliSeconds));
58  continue;
59  }
60  else
61  {
62  std::cout << __PRETTY_FUNCTION__ << "ERROR: Can't connect to " << serverName << " aborting!" << std::endl;
63  break;
64  }
65  }
66 
67  // if (sendBufferSize > 0)
68  // {
69  // int socketLength = 0;
70  // socklen_t sizeOfSocketLength = sizeof(socketLength);
71  // status = getsockopt(getSocketId(), SOL_SOCKET, SO_SNDBUF,
72  //&socketLength, &sizeOfSocketLength); std::cout << __PRETTY_FUNCTION__
73  //<< "TCPConnect sendBufferSize initial: " << socketLength << " status/errno=" <<
74  // status << "/" << errno << " sizeOfSocketLength=" << sizeOfSocketLength <<
75  // std::endl;
76  //
77  // socketLength = sendBufferSize;
78  // status = setsockopt(getSocketId(), SOL_SOCKET, SO_SNDBUF,
79  //&socketLength, sizeOfSocketLength); if (status == -1)
80  // std::cout <<
81  //__PRETTY_FUNCTION__ << "Error with setsockopt sendBufferSize " << errno <<
82  // std::endl ; socketLength = 0;
83  // status = getsockopt(getSocketId(), SOL_SOCKET, SO_SNDBUF,
84  //&socketLength, &sizeOfSocketLength); if (socketLength < (sendBufferSize
85  //* 2)) std::cout << __PRETTY_FUNCTION__ << "sendBufferSize " <<
86  // socketLength
87  //<< " not expected (" << sendBufferSize << " status/errno=" << status << "/" <<
88  // errno << ")" << std::endl; else std::cout <<
89  //__PRETTY_FUNCTION__ << "sendBufferSize " << socketLength << " status/errno=" <<
90  // status << "/" << errno << std::endl;
91  // }
92  std::cout << __PRETTY_FUNCTION__ << "Succesfully connected to server " << fServerIP << " port: " << fServerPort << std::endl;
93  fConnected = true;
94  }
95 
96  return true;
97 }
98 //==============================================================================
99 bool TCPClientBase::disconnect(void)
100 {
101  if(fConnected)
102  {
103  TCPSocket::sendClose();
104  TCPSocket::close();
105  fConnected = false;
106  }
107  return !fConnected;
108 }
109 
110 //==============================================================================
111 // private
112 void TCPClientBase::resolveServer(std::string& serverIP)
113 {
114  const std::string ipv4(
115  "(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)"
116  "\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)"
117  "\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)"
118  "\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)");
119  boost::regex ip_regex(ipv4.c_str());
120 
121  // std::cout << __PRETTY_FUNCTION__ << "Checking exp1: " << serverIP << std::endl;
122  if(boost::regex_match(serverIP, ip_regex)) // It is already in the correct format!
123  return;
124  else if(serverIP == "localhost" || serverIP == "localhost.localdomain")
125  {
126  serverIP = "127.0.0.1";
127  }
128  else
129  {
130  struct hostent* resolvedHost = ::gethostbyname(serverIP.c_str());
131  if(resolvedHost == NULL)
132  {
133  throw std::runtime_error(serverIP + " is unavailable and can't be resolved!");
134  abort();
135  }
136  in_addr* address = (in_addr*)resolvedHost->h_addr;
137  serverIP = inet_ntoa(*address);
138  std::cout << "IP: (" << serverIP << ")\n";
139  }
140 }