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