tdaq-develop-2025-02-12
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  std::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  std::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  std::cout << __PRETTY_FUNCTION__ << "Trying to connect" << std::endl;
60  TCPSocket::open();
61  status = ::connect(getSocketId(),
62  (struct sockaddr*)&serverSocketAddress,
63  sizeof(serverSocketAddress));
64  std::cout << __PRETTY_FUNCTION__ << "Done Connect with status: " << status
65  << std::endl;
66  if(status == -1)
67  {
68  if((unsigned int)retry > 0)
69  {
70  std::cout << __PRETTY_FUNCTION__ << "WARNING: Can't connect to "
71  << serverName << ". The server might still be down...Sleeping "
72  << sleepMilliSeconds << "ms and then retry "
73  << (unsigned int)retry << " more times." << std::endl;
74  std::this_thread::sleep_for(std::chrono::milliseconds(sleepMilliSeconds));
75  continue;
76  }
77  else
78  {
79  std::stringstream error;
80  error << "ERROR: Can't connect to " << serverName
81  << ". The server might still be down after "
82  << totalTries * sleepMilliSeconds / 1000. << " seconds and "
83  << totalTries << " connection attempts!";
84  fConnected = false;
85  throw std::runtime_error(error.str());
86  }
87  }
88 
89  // if (sendBufferSize > 0)
90  // {
91  // int socketLength = 0;
92  // socklen_t sizeOfSocketLength = sizeof(socketLength);
93  // status = getsockopt(getSocketId(), SOL_SOCKET, SO_SNDBUF,
94  //&socketLength, &sizeOfSocketLength); __COUT__
95  //<< "TCPConnect sendBufferSize initial: " << socketLength << " status/errno=" <<
96  // status << "/" << errno << " sizeOfSocketLength=" << sizeOfSocketLength <<
97  // std::endl;
98  //
99  // socketLength = sendBufferSize;
100  // status = setsockopt(getSocketId(), SOL_SOCKET, SO_SNDBUF,
101  //&socketLength, sizeOfSocketLength); if (status == -1)
102  // std::cout <<
103  //__PRETTY_FUNCTION__ << "Error with setsockopt sendBufferSize " << errno <<
104  // std::endl ; socketLength = 0;
105  // status = getsockopt(getSocketId(), SOL_SOCKET, SO_SNDBUF,
106  //&socketLength, &sizeOfSocketLength); if (socketLength < (sendBufferSize
107  //* 2)) __COUT__ << "sendBufferSize " <<
108  // socketLength
109  //<< " not expected (" << sendBufferSize << " status/errno=" << status << "/" <<
110  // errno << ")" << std::endl; else std::cout <<
111  //__PRETTY_FUNCTION__ << "sendBufferSize " << socketLength << " status/errno=" <<
112  // status << "/" << errno << std::endl;
113  // }
114  __COUT__ << "Succesfully connected to server " << fServerIP
115  << " port: " << fServerPort << std::endl;
116  fConnected = true;
117  }
118 
119  return fConnected;
120 }
121 //==============================================================================
122 bool TCPClientBase::disconnect(void)
123 {
124  if(fConnected)
125  {
126  TCPSocket::sendClose();
127  TCPSocket::close();
128  fConnected = false;
129  }
130  return !fConnected;
131 }
132 
133 //==============================================================================
135 void TCPClientBase::resolveServer(std::string& serverIP)
136 {
137  const std::string ipv4(
138  "(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)"
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  boost::regex ip_regex(ipv4.c_str());
143 
144  // __COUT__ << "Checking exp1: " << serverIP << std::endl;
145  if(boost::regex_match(serverIP, ip_regex)) // It is already in the correct format!
146  return;
147  else if(serverIP == "localhost" || serverIP == "localhost.localdomain")
148  {
149  serverIP = "127.0.0.1";
150  }
151  else
152  {
153  struct hostent* resolvedHost = ::gethostbyname(serverIP.c_str());
154  if(resolvedHost == NULL)
155  {
156  throw std::runtime_error(serverIP + " is unavailable and can't be resolved!");
157  abort();
158  }
159  in_addr* address = (in_addr*)resolvedHost->h_addr;
160  serverIP = inet_ntoa(*address);
161  std::cout << "IP: (" << serverIP << ")\n";
162  }
163 }