otsdaq  3.11.00
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 } //end protected constructor
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 } //end destructor
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  __COUT__ << "Attempting to bind a socket on IP: " << IPAddress_ << " to the first "
105  << "available port in range [" << fromPort << ", " << toPort << "]..."
106  << std::endl;
107 
108  for(int p = fromPort; p <= toPort && !socketInitialized; p++)
109  {
110  port.str("");
111  port << p;
112  __COUTT__ << "]\tBinding port: " << port.str() << std::endl;
113  socketAddress_.sin_port = htons(p); // short, network byte order
114 
115  if((status = getaddrinfo(NULL, port.str().c_str(), &hints, &res)) != 0)
116  {
117  __COUTT__ << "]\tGetaddrinfo error status: " << status << std::endl;
118  continue;
119  }
120 
121  // make a socket:
122  socketNumber_ = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
123 
124  __COUTT__ << "]\tSocket Number: " << socketNumber_
125  << " for port: " << ntohs(socketAddress_.sin_port) << " initialized."
126  << std::endl;
127  // bind it to the port we passed in to getaddrinfo():
128  if(bind(socketNumber_, res->ai_addr, res->ai_addrlen) == -1)
129  {
130  __COUTT__ << "]\tPort " << port.str() << " unavailable, trying next port..."
131  << std::endl;
132  close(socketNumber_); // otherwise every occupied port leaks a descriptor
133  socketNumber_ = -1;
134  }
135  else
136  {
137  char yes = '1';
138  setsockopt(socketNumber_, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int));
139  socketInitialized = true;
140  __COUT__ << "Socket on port: " << port.str() << " ON IP: " << IPAddress_
141  << " INITIALIZED OK! (socket #" << socketNumber_ << ")" << std::endl;
142  }
143 
144  freeaddrinfo(res); // free the linked-list
145  }
146 
147  if(!socketInitialized)
148  {
149  __SS__ << "FATAL: Socket could not initialize socket (IP=" << IPAddress_
150  << ", Port=" << ntohs(socketAddress_.sin_port)
151  << "). Perhaps it is already in use?" << std::endl;
152  __SS_THROW__;
153  }
154 
155  __COUT__ << "Setting socket receive buffer size = " << socketReceiveBufferSize
156  << " 0x" << std::hex << socketReceiveBufferSize << std::dec << __E__;
157  if(setsockopt(socketNumber_,
158  SOL_SOCKET,
159  SO_RCVBUF,
160  (char*)&socketReceiveBufferSize,
161  sizeof(socketReceiveBufferSize)) < 0)
162  {
163  __COUT_ERR__ << "Failed to set socket receive size to " << socketReceiveBufferSize
164  << ". Attempting to revert to default." << std::endl;
165 
166  socketReceiveBufferSize = defaultSocketReceiveSize_;
167 
168  __COUT__ << "Setting socket receive buffer size = " << socketReceiveBufferSize
169  << " 0x" << std::hex << socketReceiveBufferSize << std::dec << __E__;
170  if(setsockopt(socketNumber_,
171  SOL_SOCKET,
172  SO_RCVBUF,
173  (char*)&socketReceiveBufferSize,
174  sizeof(socketReceiveBufferSize)) < 0)
175  {
176  __SS__ << "Failed to set socket receive size to " << socketReceiveBufferSize
177  << ". Attempting to revert to default." << std::endl;
178  __SS_THROW__;
179  }
180  }
181 
182  isInitialized_ = true;
183 } //end initialize()
184 
185 uint16_t Socket::getPort()
186 {
187  return ntohs(socketAddress_.sin_port);
188 
189  // //else extract from socket
190  // struct sockaddr_in sin;
191  // socklen_t len = sizeof(sin);
192  // getsockname(socketNumber_, (struct sockaddr *)&sin, &len);
193  // return ntohs(sin.sin_port);
194 } //end getPort()
195 
196 //==============================================================================
197 const struct sockaddr_in& Socket::getSocketAddress(void) { return socketAddress_; }
Socket(void)
protected constructor
Definition: Socket.cc:62
defines used also by OtsConfigurationWizardSupervisor