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