tdaq-develop-2025-02-12
Socket.cc
1 #include "otsdaq/NetworkUtilities/Socket.h"
2 #include "otsdaq/Macros/CoutMacros.h"
3 #include "otsdaq/MessageFacility/MessageFacility.h"
4 
5 #include <cassert>
6 #include <iostream>
7 #include <sstream>
8 
9 #include <arpa/inet.h>
10 #include <unistd.h>
11 // #include <sys/socket.h>
12 #include <netdb.h>
13 // #include <ifaddrs.h>
14 // #include <sys/ioctl.h>
15 // #if defined(SIOCGIFHWADDR)
16 // #include <net/if.h>
17 // #else
18 // #include <net/if_dl.h>
19 // #endif
20 // #include <cstdlib>
21 #include <cstring>
22 // #include <cstdio>
23 
24 using namespace ots;
25 
26 //==============================================================================
27 Socket::Socket(const std::string& IPAddress, unsigned int port)
28  : socketNumber_(-1), IPAddress_(IPAddress), requestedPort_(port)
30 {
31  __COUTT__ << "Socket constructor " << IPAddress << ":" << port << __E__;
32 
33  if(port >= (1 << 16))
34  {
35  __SS__ << "FATAL: Invalid Port " << port << ". Max port number is "
36  << (1 << 16) - 1 << "." << std::endl;
37  __SS_THROW__;
38  }
39 
40  // network stuff
41  socketAddress_.sin_family = AF_INET; // use IPv4 host byte order
42  socketAddress_.sin_port = htons(port); // short, network byte order
43 
44  __COUTT__ << "IPAddress: " << IPAddress << " port: " << port
45  << " htons: " << socketAddress_.sin_port << std::endl;
46 
47  if(inet_aton(IPAddress.c_str(), &socketAddress_.sin_addr) == 0)
48  {
49  __SS__ << "FATAL: Invalid IP:Port combination. Please verify... " << IPAddress
50  << ":" << port << std::endl;
51  __SS_THROW__;
52  }
53 
54  memset(&(socketAddress_.sin_zero), '\0', 8); // zero the rest of the struct
55 
56  __COUTT__ << "Constructed socket for port " << ntohs(socketAddress_.sin_port) << "="
57  << getPort() << " htons: " << socketAddress_.sin_port << std::endl;
58 } //end constructor
59 
60 //==============================================================================
62 Socket::Socket(void)
63 {
64  __SS__ << "ERROR: This method should never be called. This is the protected "
65  "constructor. There is something wrong in your inheritance scheme!"
66  << std::endl;
67  __SS_THROW__;
68 }
69 
70 //==============================================================================
71 Socket::~Socket(void)
72 {
73  __COUTT__ << "CLOSING THE SOCKET #" << socketNumber_ << " IP: " << IPAddress_
74  << " port: " << getPort() << " htons: " << socketAddress_.sin_port
75  << std::endl;
76  if(socketNumber_ != -1)
77  close(socketNumber_);
78 }
79 
80 //==============================================================================
81 void Socket::initialize(unsigned int socketReceiveBufferSize)
82 {
83  __COUT__ << "Initializing port " << ntohs(socketAddress_.sin_port)
84  << " htons: " << socketAddress_.sin_port << std::endl;
85  struct addrinfo hints;
86  struct addrinfo* res;
87  int status = 0;
88 
89  // first, load up address structs with getaddrinfo():
90  memset(&hints, 0, sizeof hints);
91  hints.ai_family = AF_INET; // use IPv4 for OtsUDPHardware
92  hints.ai_socktype = SOCK_DGRAM; // SOCK_DGRAM
93  hints.ai_flags = AI_PASSIVE; // fill in my IP for me
94 
95  bool socketInitialized = false;
96  int fromPort = FirstSocketPort;
97  int toPort = LastSocketPort;
98 
99  if(ntohs(socketAddress_.sin_port) != 0)
100  fromPort = toPort = ntohs(socketAddress_.sin_port);
101 
102  std::stringstream port;
103 
104  for(int p = fromPort; p <= toPort && !socketInitialized; p++)
105  {
106  port.str("");
107  port << p;
108  __COUT__ << "]\tBinding port: " << port.str() << std::endl;
109  socketAddress_.sin_port = htons(p); // short, network byte order
110 
111  if((status = getaddrinfo(NULL, port.str().c_str(), &hints, &res)) != 0)
112  {
113  __COUT__ << "]\tGetaddrinfo error status: " << status << std::endl;
114  continue;
115  }
116 
117  // make a socket:
118  socketNumber_ = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
119 
120  __COUT__ << "]\tSocket Number: " << socketNumber_
121  << " for port: " << ntohs(socketAddress_.sin_port) << " initialized."
122  << std::endl;
123  // bind it to the port we passed in to getaddrinfo():
124  if(bind(socketNumber_, res->ai_addr, res->ai_addrlen) == -1)
125  {
126  __COUT__ << "Error********Error********Error********Error********Error******"
127  "**Error"
128  << std::endl;
129  __COUT__ << "FAILED BIND FOR PORT: " << port.str() << " ON IP: " << IPAddress_
130  << std::endl;
131  __COUT__ << "Error********Error********Error********Error********Error******"
132  "**Error"
133  << std::endl;
134  socketNumber_ = 0;
135  }
136  else
137  {
138  __COUT__ << ":):):):):):):):):):):):):):):):):):):):):):):):):):):):):):):):"
139  "):):):)"
140  << std::endl;
141  __COUT__ << ":):):):):):):):):):):):):):):):):):):):):):):):):):):):):):):):"
142  "):):):)"
143  << std::endl;
144  __COUT__ << "SOCKET ON PORT: " << port.str() << " ON IP: " << IPAddress_
145  << " INITIALIZED OK!" << std::endl;
146  __COUT__ << ":):):):):):):):):):):):):):):):):):):):):):):):):):):):):):):):"
147  "):):):)"
148  << std::endl;
149  __COUT__ << ":):):):):):):):):):):):):):):):):):):):):):):):):):):):):):):):"
150  "):):):)"
151  << std::endl;
152  char yes = '1';
153  setsockopt(socketNumber_, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int));
154  socketInitialized = true;
155  __COUT__ << "]\tSocket Number: " << socketNumber_
156  << " for port: " << ntohs(socketAddress_.sin_port)
157  << " htons: " << socketAddress_.sin_port << " initialized."
158  << std::endl;
159  }
160 
161  freeaddrinfo(res); // free the linked-list
162  }
163 
164  if(!socketInitialized)
165  {
166  __SS__ << "FATAL: Socket could not initialize socket (IP=" << IPAddress_
167  << ", Port=" << ntohs(socketAddress_.sin_port)
168  << "). Perhaps it is already in use?" << std::endl;
169  __SS_THROW__;
170  }
171 
172  __COUT__ << "Setting socket receive buffer size = " << socketReceiveBufferSize
173  << " 0x" << std::hex << socketReceiveBufferSize << std::dec << __E__;
174  if(setsockopt(socketNumber_,
175  SOL_SOCKET,
176  SO_RCVBUF,
177  (char*)&socketReceiveBufferSize,
178  sizeof(socketReceiveBufferSize)) < 0)
179  {
180  __COUT_ERR__ << "Failed to set socket receive size to " << socketReceiveBufferSize
181  << ". Attempting to revert to default." << std::endl;
182 
183  socketReceiveBufferSize = defaultSocketReceiveSize_;
184 
185  __COUT__ << "Setting socket receive buffer size = " << socketReceiveBufferSize
186  << " 0x" << std::hex << socketReceiveBufferSize << std::dec << __E__;
187  if(setsockopt(socketNumber_,
188  SOL_SOCKET,
189  SO_RCVBUF,
190  (char*)&socketReceiveBufferSize,
191  sizeof(socketReceiveBufferSize)) < 0)
192  {
193  __SS__ << "Failed to set socket receive size to " << socketReceiveBufferSize
194  << ". Attempting to revert to default." << std::endl;
195  __SS_THROW__;
196  }
197  }
198 }
199 
200 uint16_t Socket::getPort()
201 {
202  return ntohs(socketAddress_.sin_port);
203 
204  // //else extract from socket
205  // struct sockaddr_in sin;
206  // socklen_t len = sizeof(sin);
207  // getsockname(socketNumber_, (struct sockaddr *)&sin, &len);
208  // return ntohs(sin.sin_port);
209 }
210 
211 //==============================================================================
212 const struct sockaddr_in& Socket::getSocketAddress(void) { return socketAddress_; }
Socket(void)
protected constructor
Definition: Socket.cc:62