From 53caebe0f3c84270a876c23249d3c01f7242260b Mon Sep 17 00:00:00 2001 From: Dhanya Maliakal Date: Fri, 10 Nov 2017 16:30:48 +0100 Subject: [PATCH] replaced gethostbyname with getaddrinfo as it is not thread safe --- slsReceiverSoftware/include/ZmqSocket.h | 74 +++++++++++---- slsReceiverSoftware/include/genericSocket.h | 100 +++++++++++--------- 2 files changed, 113 insertions(+), 61 deletions(-) diff --git a/slsReceiverSoftware/include/ZmqSocket.h b/slsReceiverSoftware/include/ZmqSocket.h index d09b4939b..127528470 100644 --- a/slsReceiverSoftware/include/ZmqSocket.h +++ b/slsReceiverSoftware/include/ZmqSocket.h @@ -46,13 +46,13 @@ public: socketDescriptor (NULL) { char ip[MAX_STR_LENGTH] = ""; - strcpy(ip, hostname_or_ip); + memset(ip, 0, MAX_STR_LENGTH); - // convert hostname to ip - char* ptr = ConvertHostnameToIp (hostname_or_ip); - if (ptr == NULL) + // convert hostname to ip (not required, but a test that returns if failed) + struct addrinfo *result; + if ((ConvertHostnameToInternetAddress(hostname_or_ip, &result)) || + (ConvertInternetAddresstoIpString(result, ip, MAX_STR_LENGTH))) return; - strcpy(ip, ptr); // construct address sprintf (serverAddress, "tcp://%s:%d", ip, portno); @@ -187,19 +187,57 @@ public: } }; - /** - * Convert Hostname to ip - * @param hostname hostname - * @returns string with ip or NULL if error - */ - char* ConvertHostnameToIp (const char* const hostname) { - struct hostent *he = gethostbyname (hostname); - if (he == NULL){ - cprintf (RED,"Error: Could not convert hostname to ip (zmq)\n"); - return NULL; - } - return inet_ntoa (*(struct in_addr*)he->h_addr); - }; + + /** + * Convert Hostname to Internet address info structure + * One must use freeaddrinfo(res) after using it + * @param hostname hostname + * @param res address of pointer to address info structure + * @return 1 for fail, 0 for success + */ + // Do not make this static (for multi threading environment) + int ConvertHostnameToInternetAddress (const char* const hostname, struct addrinfo **res) { + // criteria in selecting socket address structures returned by res + struct addrinfo hints; + memset (&hints, 0, sizeof (hints)); + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_STREAM; + // get host info into res + int errcode = getaddrinfo (hostname, NULL, &hints, res); + if (errcode != 0) { + cprintf (RED,"Error: Could not convert %s hostname to internet address (zmq):" + "%s\n", hostname, gai_strerror(errcode)); + } else { + if (*res == NULL) { + cprintf (RED,"Error: Could not convert %s hostname to internet address (zmq): " + "gettaddrinfo returned null\n", hostname); + } else{ + return 0; + } + } + cerr << "Error: Could not convert hostname to internet address" << endl; + return 1; + }; + + /** + * Convert Internet Address structure pointer to ip string (char*) + * Clears the internet address structure as well + * @param res pointer to internet address structure + * @param ip pointer to char array to store result in + * @param ipsize size available in ip buffer + * @return 1 for fail, 0 for success + */ + // Do not make this static (for multi threading environment) + int ConvertInternetAddresstoIpString (struct addrinfo *res, char* ip, const int ipsize) { + if (inet_ntop (res->ai_family, &((struct sockaddr_in *) res->ai_addr)->sin_addr, ip, ipsize) != NULL) { + freeaddrinfo(res); + return 0; + } + cerr << "Error: Could not convert internet address to ip string" << endl; + return 1; + } + + /** * Send Message Header diff --git a/slsReceiverSoftware/include/genericSocket.h b/slsReceiverSoftware/include/genericSocket.h index 90b176a07..1342537f0 100644 --- a/slsReceiverSoftware/include/genericSocket.h +++ b/slsReceiverSoftware/include/genericSocket.h @@ -106,52 +106,15 @@ enum communicationProtocol{ memset(dummyClientIP,0,INET_ADDRSTRLEN); differentClients = 0; - - - struct addrinfo hints, *res; - int errcode; - char addrstr[100]; - void *ptr; - memset (&hints, 0, sizeof (hints)); - // criteria in selecting socket address structures returned by res - hints.ai_family = AF_INET; - hints.ai_socktype = SOCK_STREAM; - //hints.ai_flags |= AI_CANONNAME; - errcode = getaddrinfo (host_ip_or_name, NULL, &hints, &res); - if (errcode != 0) { - cerr << "Exiting: Problem interpreting host: " << host_ip_or_name << ". Error: " << gai_strerror(errcode) << endl; - perror ("getaddrinfo"); - } else { - if (res == NULL) { - cerr << "Exiting: Problem interpreting host: " << host_ip_or_name << ". Null returned by getaddrinfo. " << endl; - } - // Set some fields in the serverAddress structure. - serverAddress.sin_family = res->ai_family; - memcpy((char *) &serverAddress.sin_addr.s_addr, &((struct sockaddr_in *) res->ai_addr)->sin_addr, res->ai_addrlen); + struct addrinfo *result; + if (!ConvertHostnameToInternetAddress(host_ip_or_name, &result)) { + serverAddress.sin_family = result->ai_family; + memcpy((char *) &serverAddress.sin_addr.s_addr, &((struct sockaddr_in *) result->ai_addr)->sin_addr, result->ai_addrlen); + freeaddrinfo(result); serverAddress.sin_port = htons(port_number); socketDescriptor=0; - freeaddrinfo(res); } clientAddress_length=sizeof(clientAddress); - - - - -/* - struct hostent *hostInfo = gethostbyname(host_ip_or_name); - if (hostInfo == NULL){ - cerr << "Exiting: Problem interpreting host: " << host_ip_or_name << "\n"; - } else { - // Set some fields in the serverAddress structure. - serverAddress.sin_family = hostInfo->h_addrtype; - memcpy((char *) &serverAddress.sin_addr.s_addr, hostInfo->h_addr_list[0], hostInfo->h_length); - //((char *) &serverAddress.sin_addr.s_addr)[hostInfo->h_length]='\0'; //a fix for valgrind - serverAddress.sin_port = htons(port_number); - socketDescriptor=0; //You can use send and recv, //would it work????? - } - clientAddress_length=sizeof(clientAddress); -*/ - } @@ -164,7 +127,7 @@ enum communicationProtocol{ return SOCK_DGRAM; default: - cerr << "unknow protocol " << p << endl; + cerr << "unknown protocol " << p << endl; return -1; } } @@ -608,6 +571,57 @@ enum communicationProtocol{ }; + + /** + * Convert Hostname to Internet address info structure + * One must use freeaddrinfo(res) after using it + * @param hostname hostname + * @param res address of pointer to address info structure + * @return 1 for fail, 0 for success + */ + // Do not make this static (for multi threading environment) + int ConvertHostnameToInternetAddress (const char* const hostname, struct addrinfo **res) { + // criteria in selecting socket address structures returned by res + struct addrinfo hints; + memset (&hints, 0, sizeof (hints)); + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_STREAM; + // get host info into res + int errcode = getaddrinfo (hostname, NULL, &hints, res); + if (errcode != 0) { + cprintf (RED,"Error: Could not convert %s hostname to internet address (zmq):" + "%s\n", hostname, gai_strerror(errcode)); + } else { + if (*res == NULL) { + cprintf (RED,"Error: Could not convert %s hostname to internet address (zmq): " + "gettaddrinfo returned null\n", hostname); + } else{ + return 0; + } + } + cerr << "Error: Could not convert hostname to internet address" << endl; + return 1; + }; + + /** + * Convert Internet Address structure pointer to ip string (char*) + * Clears the internet address structure as well + * @param res pointer to internet address structure + * @param ip pointer to char array to store result in + * @param ipsize size available in ip buffer + * @return 1 for fail, 0 for success + */ + // Do not make this static (for multi threading environment) + int ConvertInternetAddresstoIpString (struct addrinfo *res, char* ip, const int ipsize) { + if (inet_ntop (res->ai_family, &((struct sockaddr_in *) res->ai_addr)->sin_addr, ip, ipsize) != NULL) { + freeaddrinfo(res); + return 0; + } + cerr << "Error: Could not convert internet address to ip string" << endl; + return 1; + } + + int ReceiveDataOnly(void* buf,int length=0){