otsdaq  v1_01_03
 All Classes Namespaces Functions
NetworkDevice.cc
1 #include "otsdaq-core/NetworkUtilities/NetworkDevice.h"
2 #include "otsdaq-core/MessageFacility/MessageFacility.h"
3 #include "otsdaq-core/Macros/CoutHeaderMacros.h"
4 
5 #include <iostream>
6 #include <sstream>
7 
8 #include <assert.h>
9 
10 #include <unistd.h>
11 #include <arpa/inet.h>
12 //#include <sys/socket.h>
13 #include <netdb.h>
14 #include <ifaddrs.h>
15 #include <sys/ioctl.h>
16 #if defined(SIOCGIFHWADDR)
17 #include <net/if.h>
18 #else
19 #include <net/if_dl.h>
20 #endif
21 #include <cstdlib>
22 #include <cstring>
23 #include <cstdio>
24 
25 using namespace ots;
26 
27 
28 
29 //========================================================================================================================
30 NetworkDevice::NetworkDevice(std::string IPAddress, unsigned int IPPort) : communicationInterface_(NULL)
31 {
32  //network stuff
33  deviceAddress_.sin_family = AF_INET;// use IPv4 host byte order
34  deviceAddress_.sin_port = htons(IPPort);// short, network byte order
35 
36  if(inet_aton(IPAddress.c_str(), &deviceAddress_.sin_addr) == 0)
37  {
38  std::cout << __COUT_HDR_FL__ << __LINE__ << "FATAL: Invalid IP address " << IPAddress << std::endl;
39  //FIXME substitute with try catch solution !!
40  assert(0);
41  }
42 
43  memset(&(deviceAddress_.sin_zero), '\0', 8);// zero the rest of the struct
44 }
45 
46 //========================================================================================================================
47 NetworkDevice::~NetworkDevice(void)
48 {
49  for(std::map<int,int>::iterator it=openSockets_.begin(); it!=openSockets_.end(); it++)
50  {
51  std::cout << __COUT_HDR_FL__ << "Closing socket for port " << it->second << std::endl;
52  close(it->first);
53  }
54  openSockets_.clear();
55 }
56 
57 //========================================================================================================================
58 int NetworkDevice::initSocket(std::string socketPort)
59 {
60 
61  struct addrinfo hints;
62 
63  struct addrinfo* res;
64  int status = 0;
65  int socketOut = -1;
66 
67  // first, load up address structs with getaddrinfo():
68  memset(&hints, 0, sizeof hints);
69  hints.ai_family = AF_INET; // use IPv4 for OtsUDPHardware
70  hints.ai_socktype = SOCK_DGRAM;// SOCK_DGRAM
71  hints.ai_flags = AI_PASSIVE;// fill in my IP for me
72 
73  bool socketInitialized = false;
74  int fromPort = FirstSocketPort;
75  int toPort = LastSocketPort;
76 
77  if(socketPort != "")
78  fromPort = toPort = strtol(socketPort.c_str(),0,10);
79 
80  std::stringstream port;
81 
82  for(int p=fromPort; p<=toPort && !socketInitialized; p++)
83  {
84  port.str("");
85  port << p;
86  std::cout << __COUT_HDR_FL__ << __LINE__ << "]\tBinding port: " << port.str() << std::endl;
87 
88  if((status = getaddrinfo(NULL, port.str().c_str(), &hints, &res)) != 0)
89  {
90  std::cout << __COUT_HDR_FL__ << __LINE__ << "]\tGetaddrinfo error status: " << status << std::endl;
91  continue;
92  }
93 
94  // make a socket:
95  socketOut = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
96 
97  // bind it to the port we passed in to getaddrinfo():
98  if(bind(socketOut, res->ai_addr, res->ai_addrlen) == -1)
99  {
100  mf::LogError("NetworkDevice") << __LINE__ << "]\tFailed bind for port: " << port.str();
101  socketOut = -1;
102  exit(0);
103  }
104  else
105  {
106  char yes = '1';
107  setsockopt(socketOut,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int));
108  socketInitialized = true;
109  openSockets_[socketOut] = p;
110  std::cout << __COUT_HDR_FL__ << __LINE__ << "]\tSocket Number: " << socketOut << " for port: " << p << " initialized." << std::endl;
111  }
112 
113  freeaddrinfo(res); // free the linked-list
114  }
115 
116  return socketOut;
117 }
118 
119 //========================================================================================================================
120 int NetworkDevice::initSocket(unsigned int socketPort)
121 {
122  std::stringstream socket("");
123  if(socketPort != 0)
124  socket << socketPort;
125  return initSocket(socket.str());
126 }
127 
128 //========================================================================================================================
129 int NetworkDevice::send(int socketDescriptor, const std::string& buffer)
130 {
131  if(sendto(socketDescriptor,buffer.c_str(),buffer.size(),0,(struct sockaddr *)&(deviceAddress_), sizeof(deviceAddress_)) < (int)(buffer.size()))
132  {
133  std::cout << __COUT_HDR_FL__ << "Error writing buffer" << std::endl;
134  return -1;
135  }
136  return 0;
137 }
138 
139 //========================================================================================================================
140 int NetworkDevice::receive(int socketDescriptor, std::string& buffer)
141 {
142  struct timeval tv;
143  tv.tv_sec = 2;
144  tv.tv_usec = 0; //set timeout period for select()
145  fd_set fileDescriptor; //setup set for select()
146  FD_ZERO(&fileDescriptor);
147  FD_SET(socketDescriptor,&fileDescriptor);
148  select(socketDescriptor+1, &fileDescriptor, 0, 0, &tv);
149 
150  if(FD_ISSET(socketDescriptor,&fileDescriptor))
151  {
152  std::string bufferS;
153  struct sockaddr_in tmpAddress;
154  socklen_t addressLength = sizeof(tmpAddress);
155  int nOfBytes;
156  char readBuffer[maxSocketSize];
157  if ((nOfBytes=recvfrom(socketDescriptor, readBuffer, maxSocketSize, 0, (struct sockaddr *)&tmpAddress, &addressLength)) == -1)
158  {
159  std::cout << __COUT_HDR_FL__ << __LINE__ << "Error reading buffer" << std::endl;
160  return -1;
161  }
162  buffer.resize(nOfBytes);
163  for(int i=0; i<nOfBytes; i++)
164  buffer[i] = readBuffer[i];
165  }
166  else
167  {
168  std::cout << __COUT_HDR_FL__ << __LINE__ << "]\tNetwork device unresponsive. Read request timed out." << std::endl;
169  return -1;
170  }
171 
172  return 0;
173 }
174 
175 //========================================================================================================================
176 int NetworkDevice::listen(int socketDescriptor, std::string& buffer)
177 {
178  std::cout << __COUT_HDR_FL__ << "LISTENING!!!!!" << std::endl;
179  struct timeval tv;
180  tv.tv_sec = 5;
181  tv.tv_usec = 0; //set timeout period for select()
182  fd_set fileDescriptor; //setup set for select()
183  FD_ZERO(&fileDescriptor);
184  FD_SET(socketDescriptor,&fileDescriptor);
185  select(socketDescriptor+1, &fileDescriptor, 0, 0, &tv);
186 
187  if(FD_ISSET(socketDescriptor,&fileDescriptor))
188  {
189  std::string bufferS;
190  struct sockaddr_in tmpAddress;
191  socklen_t addressLength = sizeof(tmpAddress);
192  int nOfBytes;
193  char readBuffer[maxSocketSize];
194  if ((nOfBytes=recvfrom(socketDescriptor, readBuffer, maxSocketSize, 0, (struct sockaddr *)&tmpAddress, &addressLength)) == -1)
195  {
196  std::cout << __COUT_HDR_FL__ << __LINE__ << "Error reading buffer" << std::endl;
197  return -1;
198  }
199  buffer.resize(nOfBytes);
200  for(int i=0; i<nOfBytes; i++)
201  buffer[i] = readBuffer[i];
202  }
203  else
204  {
205  std::cout << __COUT_HDR_FL__ << __LINE__ << "Timed out" << std::endl;
206  return -1;
207  }
208 
209  return 0;
210 }
211 
212 //========================================================================================================================
213 int NetworkDevice::ping(int socketDescriptor)
214 {
215  std::string pingMsg(1,0);
216  if(send(socketDescriptor, pingMsg) == -1)
217  {
218  std::cout << __COUT_HDR_FL__ << __LINE__ << "]\tCan't send ping Message!" << std::endl;
219  return -1;
220  }
221 
222  std::string bufferS;
223  if(receive(socketDescriptor,bufferS) == -1)
224  {
225  std::cout << __COUT_HDR_FL__ << __LINE__ <<"]\tFailed to ping device"<< std::endl;
226  return -1;
227  }
228  /*
229  struct timeval tv;
230  tv.tv_sec = 0;
231  tv.tv_usec = 100000; //set timeout period for select()
232  fd_set fileDescriptor; //setup set for select()
233  FD_ZERO(&fileDescriptor);
234  FD_SET(socketDescriptor,&fileDescriptor);
235  select(socketDescriptor+1, &fileDescriptor, 0, 0, &tv);
236 
237  if(FD_ISSET(socketDescriptor,&fileDescriptor))
238  {
239  std::string bufferS;
240  if(receive(socketDescriptor,bufferS) == -1)
241  {
242  std::cout << __COUT_HDR_FL__ << __LINE__ <<"]\tFailed to ping device"<< std::endl;
243  return -1;
244  }
245  }
246  else
247  {
248  std::cout << __COUT_HDR_FL__ << __LINE__ << "]\tNetwork device unresponsive. Ping request timed out." << std::endl;
249  return -1;
250  }
251  */
252  return 0;
253 }
254 
255 //========================================================================================================================
256 std::string NetworkDevice::getFullIPAddress(std::string partialIpAddress)
257 {
258  std::cout << __COUT_HDR_FL__ << "partial IP: " << partialIpAddress << std::endl;
259  if(getInterface(partialIpAddress))
260  {
261  char *p, addr[32];
262  p=inet_ntoa(((struct sockaddr_in *)(communicationInterface_->ifa_addr))->sin_addr);
263  strncpy(addr,p,sizeof(addr)-1);
264  addr[sizeof(addr)-1]='\0';
265 
266  return addr;
267  }
268  else
269  {
270  std::cout << __COUT_HDR_FL__ << "FIXME substitute with try catch solution !!\n\nFailed to locate network interface matching partial IP address" << std::endl;
271  //FIXME substitute with try catch solution !!
272  assert(0);
273 
274  //std::cout << __COUT_HDR_FL__ << "Failed to locate network interface matching partial IP address" << std::endl;
275  return "";
276  }
277 }
278 
279 //========================================================================================================================
280 std::string NetworkDevice::getInterfaceName(std::string ipAddress)
281 {
282  std::cout << __COUT_HDR_FL__ << "IP: " << ipAddress << std::endl;
283  if(getInterface(ipAddress))
284  return communicationInterface_->ifa_name;
285  else
286  {
287  //FIXME substitute with try catch solution !!
288  std::cout << __COUT_HDR_FL__ << "FIXME substitute with try catch solution !!\n\nFailed to get interface name!" << std::endl;
289  assert(0);
290 
291  std::cout << __COUT_HDR_FL__ << "Failed to get interface name for IP address" << std::endl;
292  return "";
293  }
294 }
295 
296 //========================================================================================================================
297 int NetworkDevice::getInterface(std::string ipAddress)
298 {
299  int family, s;
300  char host[NI_MAXHOST];
301 
302 
303  std::cout << __COUT_HDR_FL__ << "IP2: " << ipAddress << std::endl;
304  if(communicationInterface_ != 0)
305  {
306  s = getnameinfo(communicationInterface_->ifa_addr,
307 
308  (communicationInterface_->ifa_addr->sa_family == AF_INET) ? sizeof(struct sockaddr_in) :
309 
310  sizeof(struct sockaddr_in6),
311  host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);
312 
313  if (s != 0)
314  {
315  std::cout << __COUT_HDR_FL__ << "getnameinfo() failed: " << gai_strerror(s) << std::endl;
316  //FIXME substitute with try catch solution !!
317  std::cout << __COUT_HDR_FL__ << "FIXME substitute with try catch solution !!\n\nFailed to get name info!" << std::endl;
318  assert(0);
319  }
320 
321  if (std::string(host).find(ipAddress) != std::string::npos)
322  return true;
323  else
324  {
325  delete communicationInterface_;
326  communicationInterface_ = NULL;
327  }
328  }
329 
330  struct ifaddrs* ifaddr;
331 
332  struct ifaddrs* ifa;
333 
334  if (getifaddrs(&ifaddr) == -1)
335  {
336  perror("getifaddrs");
337  //FIXME substitute with try catch solution !!
338  std::cout << __COUT_HDR_FL__ << "FIXME substitute with try catch solution !!\n\nFailed to get ifaddress!" << std::endl;
339  assert(0);
340  }
341 
342  /* Walk through linked list, maintaining head pointer so we
343  can free list later */
344 
345  bool found = false;
346 
347  for (ifa = ifaddr; ifa != NULL && !found; ifa = ifa->ifa_next)
348  {
349  if (ifa->ifa_addr == NULL)
350  continue;
351 
352  family = ifa->ifa_addr->sa_family;
353 
354  /* For an AF_INET* interface address, display the address */
355 
356  if (family == AF_INET || family == AF_INET6)
357  {
358  s = getnameinfo(ifa->ifa_addr,
359 
360  (family == AF_INET) ? sizeof(struct sockaddr_in) :
361 
362  sizeof(struct sockaddr_in6),
363  host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);
364 
365  if (s != 0)
366  {
367  std::cout << __COUT_HDR_FL__ << "getnameinfo() failed: " << gai_strerror(s) << std::endl;
368  //FIXME substitute with try catch solution !!
369  std::cout << __COUT_HDR_FL__ << "FIXME substitute with try catch solution !!\n\nFailed to get getnameinfo!" << std::endl;
370  assert(0);
371  }
372 
373  if (std::string(host).find(ipAddress) != std::string::npos)
374  {
375  communicationInterface_ = new struct ifaddrs(*ifa);
376  found = true;
377  }
378  }
379  }
380 
381  freeifaddrs(ifaddr);
382 
383  return found;
384 }
385 
386 //========================================================================================================================
387 std::string NetworkDevice::getMacAddress(std::string interfaceName)
388 {
389 
390  std::string macAddress(6,'0');
391 #if defined(SIOCGIFHWADDR)
392 
393  struct ifreq ifr;
394  int sock;
395 
396  sock=socket(PF_INET, SOCK_STREAM, 0);
397 
398  if (-1==sock)
399  {
400  perror("socket() ");
401  return "";
402  }
403 
404  strncpy(ifr.ifr_name,interfaceName.c_str(),sizeof(ifr.ifr_name)-1);
405  ifr.ifr_name[sizeof(ifr.ifr_name)-1]='\0';
406 
407  if (-1==ioctl(sock, SIOCGIFHWADDR, &ifr))
408  {
409  perror("ioctl(SIOCGIFHWADDR) ");
410  return "";
411  }
412  for (int j=0; j<6; j++)
413  macAddress[j] = ifr.ifr_hwaddr.sa_data[j];
414 #else
415 
416  char mac[6];
417  ifaddrs* iflist;
418  bool found = false;
419  if (getifaddrs(&iflist) == 0)
420  {
421  for (ifaddrs* cur = iflist; cur; cur = cur->ifa_next)
422  {
423  if ((cur->ifa_addr->sa_family == AF_LINK) &&
424  (strcmp(cur->ifa_name, interfaceName.c_str()) == 0) &&
425  cur->ifa_addr)
426  {
427  sockaddr_dl* sdl = (sockaddr_dl*)cur->ifa_addr;
428  memcpy(mac, LLADDR(sdl), sdl->sdl_alen);
429  found = true;
430  break;
431  }
432  }
433 
434  freeifaddrs(iflist);
435  }
436  for (int j=0; j<6; j++)
437  macAddress[j] = mac[j];
438 #endif
439 
440  return macAddress;
441 }