otsdaq  v2_03_00
Socket.cc
1 #include "otsdaq-core/NetworkUtilities/Socket.h"
2 #include "otsdaq-core/Macros/CoutMacros.h"
3 #include "otsdaq-core/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  std::cout << __COUT_HDR_FL__
133  << "Error********Error********Error********Error********Error******"
134  "**Error"
135  << std::endl;
136  std::cout << __COUT_HDR_FL__ << "FAILED BIND FOR PORT: " << port.str()
137  << " ON IP: " << IPAddress_ << std::endl;
138  std::cout << __COUT_HDR_FL__
139  << "Error********Error********Error********Error********Error******"
140  "**Error"
141  << std::endl;
142  socketNumber_ = 0;
143  }
144  else
145  {
146  std::cout << __COUT_HDR_FL__
147  << ":):):):):):):):):):):):):):):):):):):):):):):):):):):):):):):):"
148  "):):):)"
149  << std::endl;
150  std::cout << __COUT_HDR_FL__
151  << ":):):):):):):):):):):):):):):):):):):):):):):):):):):):):):):):"
152  "):):):)"
153  << std::endl;
154  std::cout << __COUT_HDR_FL__ << "SOCKET ON PORT: " << port.str()
155  << " ON IP: " << IPAddress_ << " INITIALIZED OK!" << std::endl;
156  std::cout << __COUT_HDR_FL__
157  << ":):):):):):):):):):):):):):):):):):):):):):):):):):):):):):):):"
158  "):):):)"
159  << std::endl;
160  std::cout << __COUT_HDR_FL__
161  << ":):):):):):):):):):):):):):):):):):):):):):):):):):):):):):):):"
162  "):):):)"
163  << std::endl;
164  char yes = '1';
165  setsockopt(socketNumber_, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int));
166  socketInitialized = true;
167  __COUT__ << "]\tSocket Number: " << socketNumber_
168  << " for port: " << ntohs(socketAddress_.sin_port) << " initialized."
169  << std::endl;
170  }
171 
172  freeaddrinfo(res); // free the linked-list
173  }
174 
175  if(!socketInitialized)
176  {
177  __SS__ << "FATAL: Socket could not initialize socket (IP=" << IPAddress_
178  << ", Port=" << ntohs(socketAddress_.sin_port)
179  << "). Perhaps it is already in use?" << std::endl;
180  std::cout << ss.str();
181  __SS_THROW__;
182  }
183 
184  __COUT__ << "Setting socket receive buffer size = " << socketReceiveBufferSize
185  << " 0x" << std::hex << socketReceiveBufferSize << std::dec << __E__;
186  if(setsockopt(socketNumber_,
187  SOL_SOCKET,
188  SO_RCVBUF,
189  (char*)&socketReceiveBufferSize,
190  sizeof(socketReceiveBufferSize)) < 0)
191  {
192  __COUT_ERR__ << "Failed to set socket receive size to " << socketReceiveBufferSize
193  << ". Attempting to revert to default." << std::endl;
194 
195  socketReceiveBufferSize = defaultSocketReceiveSize_;
196 
197  __COUT__ << "Setting socket receive buffer size = " << socketReceiveBufferSize
198  << " 0x" << std::hex << socketReceiveBufferSize << std::dec << __E__;
199  if(setsockopt(socketNumber_,
200  SOL_SOCKET,
201  SO_RCVBUF,
202  (char*)&socketReceiveBufferSize,
203  sizeof(socketReceiveBufferSize)) < 0)
204  {
205  __SS__ << "Failed to set socket receive size to " << socketReceiveBufferSize
206  << ". Attempting to revert to default." << std::endl;
207  std::cout << ss.str();
208  __SS_THROW__;
209  }
210  }
211 }
212 
213 uint16_t Socket::getPort()
214 {
215  return ntohs(socketAddress_.sin_port);
216 
217  // //else extract from socket
218  // struct sockaddr_in sin;
219  // socklen_t len = sizeof(sin);
220  // getsockname(socketNumber_, (struct sockaddr *)&sin, &len);
221  // return ntohs(sin.sin_port);
222 }
223 
224 //========================================================================================================================
225 const struct sockaddr_in& Socket::getSocketAddress(void) { return socketAddress_; }