otsdaq  3.09.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  socketNumber_ = 0;
133  }
134  else
135  {
136  char yes = '1';
137  setsockopt(socketNumber_, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int));
138  socketInitialized = true;
139  __COUT__ << "Socket on port: " << port.str() << " ON IP: " << IPAddress_
140  << " INITIALIZED OK! (socket #" << socketNumber_ << ")" << std::endl;
141  }
142 
143  freeaddrinfo(res); // free the linked-list
144  }
145 
146  if(!socketInitialized)
147  {
148  __SS__ << "FATAL: Socket could not initialize socket (IP=" << IPAddress_
149  << ", Port=" << ntohs(socketAddress_.sin_port)
150  << "). Perhaps it is already in use?" << std::endl;
151  __SS_THROW__;
152  }
153 
154  __COUT__ << "Setting socket receive buffer size = " << socketReceiveBufferSize
155  << " 0x" << std::hex << socketReceiveBufferSize << std::dec << __E__;
156  if(setsockopt(socketNumber_,
157  SOL_SOCKET,
158  SO_RCVBUF,
159  (char*)&socketReceiveBufferSize,
160  sizeof(socketReceiveBufferSize)) < 0)
161  {
162  __COUT_ERR__ << "Failed to set socket receive size to " << socketReceiveBufferSize
163  << ". Attempting to revert to default." << std::endl;
164 
165  socketReceiveBufferSize = defaultSocketReceiveSize_;
166 
167  __COUT__ << "Setting socket receive buffer size = " << socketReceiveBufferSize
168  << " 0x" << std::hex << socketReceiveBufferSize << std::dec << __E__;
169  if(setsockopt(socketNumber_,
170  SOL_SOCKET,
171  SO_RCVBUF,
172  (char*)&socketReceiveBufferSize,
173  sizeof(socketReceiveBufferSize)) < 0)
174  {
175  __SS__ << "Failed to set socket receive size to " << socketReceiveBufferSize
176  << ". Attempting to revert to default." << std::endl;
177  __SS_THROW__;
178  }
179  }
180 
181  isInitialized_ = true;
182 } //end initialize()
183 
184 uint16_t Socket::getPort()
185 {
186  return ntohs(socketAddress_.sin_port);
187 
188  // //else extract from socket
189  // struct sockaddr_in sin;
190  // socklen_t len = sizeof(sin);
191  // getsockname(socketNumber_, (struct sockaddr *)&sin, &len);
192  // return ntohs(sin.sin_port);
193 } //end getPort()
194 
195 //==============================================================================
196 const struct sockaddr_in& Socket::getSocketAddress(void) { return socketAddress_; }
Socket(void)
protected constructor
Definition: Socket.cc:62
defines used also by OtsConfigurationWizardSupervisor