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