00001 #include "otsdaq-core/NetworkUtilities/NetworkDevice.h"
00002 #include "otsdaq-core/MessageFacility/MessageFacility.h"
00003 #include "otsdaq-core/Macros/CoutHeaderMacros.h"
00004
00005 #include <iostream>
00006 #include <sstream>
00007
00008 #include <assert.h>
00009
00010 #include <unistd.h>
00011 #include <arpa/inet.h>
00012
00013 #include <netdb.h>
00014 #include <ifaddrs.h>
00015 #include <sys/ioctl.h>
00016 #if defined(SIOCGIFHWADDR)
00017 #include <net/if.h>
00018 #else
00019 #include <net/if_dl.h>
00020 #endif
00021 #include <cstdlib>
00022 #include <cstring>
00023 #include <cstdio>
00024
00025 using namespace ots;
00026
00027
00028
00029
00030 NetworkDevice::NetworkDevice(std::string IPAddress, unsigned int IPPort) : communicationInterface_(NULL)
00031 {
00032
00033 deviceAddress_.sin_family = AF_INET;
00034 deviceAddress_.sin_port = htons(IPPort);
00035
00036 if(inet_aton(IPAddress.c_str(), &deviceAddress_.sin_addr) == 0)
00037 {
00038 std::cout << __COUT_HDR_FL__ << __LINE__ << "FATAL: Invalid IP address " << IPAddress << std::endl;
00039
00040 assert(0);
00041 }
00042
00043 memset(&(deviceAddress_.sin_zero), '\0', 8);
00044 }
00045
00046
00047 NetworkDevice::~NetworkDevice(void)
00048 {
00049 for(std::map<int,int>::iterator it=openSockets_.begin(); it!=openSockets_.end(); it++)
00050 {
00051 std::cout << __COUT_HDR_FL__ << "Closing socket for port " << it->second << std::endl;
00052 close(it->first);
00053 }
00054 openSockets_.clear();
00055 }
00056
00057
00058 int NetworkDevice::initSocket(std::string socketPort)
00059 {
00060
00061 struct addrinfo hints;
00062
00063 struct addrinfo* res;
00064 int status = 0;
00065 int socketOut = -1;
00066
00067
00068 memset(&hints, 0, sizeof hints);
00069 hints.ai_family = AF_INET;
00070 hints.ai_socktype = SOCK_DGRAM;
00071 hints.ai_flags = AI_PASSIVE;
00072
00073 bool socketInitialized = false;
00074 int fromPort = FirstSocketPort;
00075 int toPort = LastSocketPort;
00076
00077 if(socketPort != "")
00078 fromPort = toPort = strtol(socketPort.c_str(),0,10);
00079
00080 std::stringstream port;
00081
00082 for(int p=fromPort; p<=toPort && !socketInitialized; p++)
00083 {
00084 port.str("");
00085 port << p;
00086 std::cout << __COUT_HDR_FL__ << __LINE__ << "]\tBinding port: " << port.str() << std::endl;
00087
00088 if((status = getaddrinfo(NULL, port.str().c_str(), &hints, &res)) != 0)
00089 {
00090 std::cout << __COUT_HDR_FL__ << __LINE__ << "]\tGetaddrinfo error status: " << status << std::endl;
00091 continue;
00092 }
00093
00094
00095 socketOut = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
00096
00097
00098 if(bind(socketOut, res->ai_addr, res->ai_addrlen) == -1)
00099 {
00100 mf::LogError("NetworkDevice") << __LINE__ << "]\tFailed bind for port: " << port.str();
00101 socketOut = -1;
00102 exit(0);
00103 }
00104 else
00105 {
00106 char yes = '1';
00107 setsockopt(socketOut,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int));
00108 socketInitialized = true;
00109 openSockets_[socketOut] = p;
00110 std::cout << __COUT_HDR_FL__ << __LINE__ << "]\tSocket Number: " << socketOut << " for port: " << p << " initialized." << std::endl;
00111 }
00112
00113 freeaddrinfo(res);
00114 }
00115
00116 return socketOut;
00117 }
00118
00119
00120 int NetworkDevice::initSocket(unsigned int socketPort)
00121 {
00122 std::stringstream socket("");
00123 if(socketPort != 0)
00124 socket << socketPort;
00125 return initSocket(socket.str());
00126 }
00127
00128
00129 int NetworkDevice::send(int socketDescriptor, const std::string& buffer)
00130 {
00131 if(sendto(socketDescriptor,buffer.c_str(),buffer.size(),0,(struct sockaddr *)&(deviceAddress_), sizeof(deviceAddress_)) < (int)(buffer.size()))
00132 {
00133 std::cout << __COUT_HDR_FL__ << "Error writing buffer" << std::endl;
00134 return -1;
00135 }
00136 return 0;
00137 }
00138
00139
00140 int NetworkDevice::receive(int socketDescriptor, std::string& buffer)
00141 {
00142 struct timeval tv;
00143 tv.tv_sec = 2;
00144 tv.tv_usec = 0;
00145 fd_set fileDescriptor;
00146 FD_ZERO(&fileDescriptor);
00147 FD_SET(socketDescriptor,&fileDescriptor);
00148 select(socketDescriptor+1, &fileDescriptor, 0, 0, &tv);
00149
00150 if(FD_ISSET(socketDescriptor,&fileDescriptor))
00151 {
00152 std::string bufferS;
00153 struct sockaddr_in tmpAddress;
00154 socklen_t addressLength = sizeof(tmpAddress);
00155 int nOfBytes;
00156 char readBuffer[maxSocketSize];
00157 if ((nOfBytes=recvfrom(socketDescriptor, readBuffer, maxSocketSize, 0, (struct sockaddr *)&tmpAddress, &addressLength)) == -1)
00158 {
00159 std::cout << __COUT_HDR_FL__ << __LINE__ << "Error reading buffer" << std::endl;
00160 return -1;
00161 }
00162 buffer.resize(nOfBytes);
00163 for(int i=0; i<nOfBytes; i++)
00164 buffer[i] = readBuffer[i];
00165 }
00166 else
00167 {
00168 std::cout << __COUT_HDR_FL__ << __LINE__ << "]\tNetwork device unresponsive. Read request timed out." << std::endl;
00169 return -1;
00170 }
00171
00172 return 0;
00173 }
00174
00175
00176 int NetworkDevice::listen(int socketDescriptor, std::string& buffer)
00177 {
00178 std::cout << __COUT_HDR_FL__ << "LISTENING!!!!!" << std::endl;
00179 struct timeval tv;
00180 tv.tv_sec = 5;
00181 tv.tv_usec = 0;
00182 fd_set fileDescriptor;
00183 FD_ZERO(&fileDescriptor);
00184 FD_SET(socketDescriptor,&fileDescriptor);
00185 select(socketDescriptor+1, &fileDescriptor, 0, 0, &tv);
00186
00187 if(FD_ISSET(socketDescriptor,&fileDescriptor))
00188 {
00189 std::string bufferS;
00190 struct sockaddr_in tmpAddress;
00191 socklen_t addressLength = sizeof(tmpAddress);
00192 int nOfBytes;
00193 char readBuffer[maxSocketSize];
00194 if ((nOfBytes=recvfrom(socketDescriptor, readBuffer, maxSocketSize, 0, (struct sockaddr *)&tmpAddress, &addressLength)) == -1)
00195 {
00196 std::cout << __COUT_HDR_FL__ << __LINE__ << "Error reading buffer" << std::endl;
00197 return -1;
00198 }
00199 buffer.resize(nOfBytes);
00200 for(int i=0; i<nOfBytes; i++)
00201 buffer[i] = readBuffer[i];
00202 }
00203 else
00204 {
00205 std::cout << __COUT_HDR_FL__ << __LINE__ << "Timed out" << std::endl;
00206 return -1;
00207 }
00208
00209 return 0;
00210 }
00211
00212
00213 int NetworkDevice::ping(int socketDescriptor)
00214 {
00215 std::string pingMsg(1,0);
00216 if(send(socketDescriptor, pingMsg) == -1)
00217 {
00218 std::cout << __COUT_HDR_FL__ << __LINE__ << "]\tCan't send ping Message!" << std::endl;
00219 return -1;
00220 }
00221
00222 std::string bufferS;
00223 if(receive(socketDescriptor,bufferS) == -1)
00224 {
00225 std::cout << __COUT_HDR_FL__ << __LINE__ <<"]\tFailed to ping device"<< std::endl;
00226 return -1;
00227 }
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252 return 0;
00253 }
00254
00255
00256 std::string NetworkDevice::getFullIPAddress(std::string partialIpAddress)
00257 {
00258 std::cout << __COUT_HDR_FL__ << "partial IP: " << partialIpAddress << std::endl;
00259 if(getInterface(partialIpAddress))
00260 {
00261 char *p, addr[32];
00262 p=inet_ntoa(((struct sockaddr_in *)(communicationInterface_->ifa_addr))->sin_addr);
00263 strncpy(addr,p,sizeof(addr)-1);
00264 addr[sizeof(addr)-1]='\0';
00265
00266 return addr;
00267 }
00268 else
00269 {
00270 std::cout << __COUT_HDR_FL__ << "FIXME substitute with try catch solution !!\n\nFailed to locate network interface matching partial IP address" << std::endl;
00271
00272 assert(0);
00273
00274
00275 return "";
00276 }
00277 }
00278
00279
00280 std::string NetworkDevice::getInterfaceName(std::string ipAddress)
00281 {
00282 std::cout << __COUT_HDR_FL__ << "IP: " << ipAddress << std::endl;
00283 if(getInterface(ipAddress))
00284 return communicationInterface_->ifa_name;
00285 else
00286 {
00287
00288 std::cout << __COUT_HDR_FL__ << "FIXME substitute with try catch solution !!\n\nFailed to get interface name!" << std::endl;
00289 assert(0);
00290
00291 std::cout << __COUT_HDR_FL__ << "Failed to get interface name for IP address" << std::endl;
00292 return "";
00293 }
00294 }
00295
00296
00297 int NetworkDevice::getInterface(std::string ipAddress)
00298 {
00299 int family, s;
00300 char host[NI_MAXHOST];
00301
00302
00303 std::cout << __COUT_HDR_FL__ << "IP2: " << ipAddress << std::endl;
00304 if(communicationInterface_ != 0)
00305 {
00306 s = getnameinfo(communicationInterface_->ifa_addr,
00307
00308 (communicationInterface_->ifa_addr->sa_family == AF_INET) ? sizeof(struct sockaddr_in) :
00309
00310 sizeof(struct sockaddr_in6),
00311 host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);
00312
00313 if (s != 0)
00314 {
00315 std::cout << __COUT_HDR_FL__ << "getnameinfo() failed: " << gai_strerror(s) << std::endl;
00316
00317 std::cout << __COUT_HDR_FL__ << "FIXME substitute with try catch solution !!\n\nFailed to get name info!" << std::endl;
00318 assert(0);
00319 }
00320
00321 if (std::string(host).find(ipAddress) != std::string::npos)
00322 return true;
00323 else
00324 {
00325 delete communicationInterface_;
00326 communicationInterface_ = NULL;
00327 }
00328 }
00329
00330 struct ifaddrs* ifaddr;
00331
00332 struct ifaddrs* ifa;
00333
00334 if (getifaddrs(&ifaddr) == -1)
00335 {
00336 perror("getifaddrs");
00337
00338 std::cout << __COUT_HDR_FL__ << "FIXME substitute with try catch solution !!\n\nFailed to get ifaddress!" << std::endl;
00339 assert(0);
00340 }
00341
00342
00343
00344
00345 bool found = false;
00346
00347 for (ifa = ifaddr; ifa != NULL && !found; ifa = ifa->ifa_next)
00348 {
00349 if (ifa->ifa_addr == NULL)
00350 continue;
00351
00352 family = ifa->ifa_addr->sa_family;
00353
00354
00355
00356 if (family == AF_INET || family == AF_INET6)
00357 {
00358 s = getnameinfo(ifa->ifa_addr,
00359
00360 (family == AF_INET) ? sizeof(struct sockaddr_in) :
00361
00362 sizeof(struct sockaddr_in6),
00363 host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);
00364
00365 if (s != 0)
00366 {
00367 std::cout << __COUT_HDR_FL__ << "getnameinfo() failed: " << gai_strerror(s) << std::endl;
00368
00369 std::cout << __COUT_HDR_FL__ << "FIXME substitute with try catch solution !!\n\nFailed to get getnameinfo!" << std::endl;
00370 assert(0);
00371 }
00372
00373 if (std::string(host).find(ipAddress) != std::string::npos)
00374 {
00375 communicationInterface_ = new struct ifaddrs(*ifa);
00376 found = true;
00377 }
00378 }
00379 }
00380
00381 freeifaddrs(ifaddr);
00382
00383 return found;
00384 }
00385
00386
00387 std::string NetworkDevice::getMacAddress(std::string interfaceName)
00388 {
00389
00390 std::string macAddress(6,'0');
00391 #if defined(SIOCGIFHWADDR)
00392
00393 struct ifreq ifr;
00394 int sock;
00395
00396 sock=socket(PF_INET, SOCK_STREAM, 0);
00397
00398 if (-1==sock)
00399 {
00400 perror("socket() ");
00401 return "";
00402 }
00403
00404 strncpy(ifr.ifr_name,interfaceName.c_str(),sizeof(ifr.ifr_name)-1);
00405 ifr.ifr_name[sizeof(ifr.ifr_name)-1]='\0';
00406
00407 if (-1==ioctl(sock, SIOCGIFHWADDR, &ifr))
00408 {
00409 perror("ioctl(SIOCGIFHWADDR) ");
00410 return "";
00411 }
00412 for (int j=0; j<6; j++)
00413 macAddress[j] = ifr.ifr_hwaddr.sa_data[j];
00414 #else
00415
00416 char mac[6];
00417 ifaddrs* iflist;
00418 bool found = false;
00419 if (getifaddrs(&iflist) == 0)
00420 {
00421 for (ifaddrs* cur = iflist; cur; cur = cur->ifa_next)
00422 {
00423 if ((cur->ifa_addr->sa_family == AF_LINK) &&
00424 (strcmp(cur->ifa_name, interfaceName.c_str()) == 0) &&
00425 cur->ifa_addr)
00426 {
00427 sockaddr_dl* sdl = (sockaddr_dl*)cur->ifa_addr;
00428 memcpy(mac, LLADDR(sdl), sdl->sdl_alen);
00429 found = true;
00430 break;
00431 }
00432 }
00433
00434 freeifaddrs(iflist);
00435 }
00436 for (int j=0; j<6; j++)
00437 macAddress[j] = mac[j];
00438 #endif
00439
00440 return macAddress;
00441 }