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