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