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