diff --git a/include/netutils/webclient.h b/include/netutils/webclient.h index 3e49cfd90..0eb448e98 100644 --- a/include/netutils/webclient.h +++ b/include/netutils/webclient.h @@ -1,5 +1,5 @@ /**************************************************************************** - * apps/include/netutils/webclient.h + * apps/include/netutils/webclient.h * Header file for the HTTP client * * Copyright (C) 2007, 2009, 2011, 2015 Gregory Nutt. All rights reserved. @@ -46,9 +46,7 @@ * Included Files ****************************************************************************/ -#ifndef CONFIG_WEBCLIENT_HOST -# include -#endif +#include #include /**************************************************************************** @@ -93,6 +91,7 @@ * of valid bytes is datend - offset. * buflen - A pointer to the length of the buffer. If the callee wishes * to change the size of the buffer, it may write to buflen. + * arg - User argument passed to callback. */ typedef void (*wget_callback_t)(FAR char **buffer, int offset, @@ -125,12 +124,6 @@ int web_posts_strlen(FAR char **name, FAR char **value, int len); * Description: * Obtain the requested file from an HTTP server using the GET method. * - * Note: If the function is passed a host name, it must already be in - * the resolver cache in order for the function to connect to the web - * server. It is therefore up to the calling module to implement the - * resolver calls and the signal handler used for reporting a resolve - * query answer. - * * Input Parameters * url - A pointer to a string containing either the full URL to * the file to get (e.g., http://www.nutt.org/index.html, or diff --git a/netutils/ping/icmp_ping.c b/netutils/ping/icmp_ping.c index fffcc0929..61b570c21 100644 --- a/netutils/ping/icmp_ping.c +++ b/netutils/ping/icmp_ping.c @@ -99,14 +99,14 @@ static inline uint16_t ping_newid(void) * Name: ping_gethostip * * Description: - * Call gethostbyname() to get the IP address associated with a hostname. + * Call getaddrinfo() to get the IP address associated with a hostname. * * Input Parameters * hostname - The host name to use in the nslookup. - * ipv4addr - The location to return the IPv4 address. + * destr - The location to return the IPv4 address. * * Returned Value: - * Zero (OK) on success; a negated errno value on failure. + * Zero (OK) on success; ERROR on failure. * ****************************************************************************/ @@ -136,7 +136,7 @@ static int ping_gethostip(FAR const char *hostname, FAR struct in_addr *dest) #else /* CONFIG_LIBC_NETDB */ /* No host name support */ - /* Convert strings to numeric IPv6 address */ + /* Convert strings to numeric IPv4 address */ int ret = inet_pton(AF_INET, hostname, dest); diff --git a/netutils/ping/icmpv6_ping.c b/netutils/ping/icmpv6_ping.c index 522d0930e..eca1913d4 100644 --- a/netutils/ping/icmpv6_ping.c +++ b/netutils/ping/icmpv6_ping.c @@ -98,14 +98,14 @@ static inline uint16_t ping6_newid(void) * Name: ping6_gethostip * * Description: - * Call gethostbyname() to get the IP address associated with a hostname. + * Call getaddrinfo() to get the IP address associated with a hostname. * * Input Parameters * hostname - The host name to use in the nslookup. - * ipv4addr - The location to return the IPv4 address. + * dest - The location to return the IPv6 address. * * Returned Value: - * Zero (OK) on success; a negated errno value on failure. + * Zero (OK) on success; ERROR on failure. * ****************************************************************************/ diff --git a/netutils/webclient/webclient.c b/netutils/webclient/webclient.c index a7c085092..31f644e85 100644 --- a/netutils/webclient/webclient.c +++ b/netutils/webclient/webclient.c @@ -48,11 +48,9 @@ * Included Files ****************************************************************************/ -#ifndef CONFIG_WEBCLIENT_HOST -# include -# include -# include -#endif +#include +#include +#include #include #include @@ -62,6 +60,7 @@ #include #include #include +#include #include #include @@ -183,10 +182,6 @@ static const char g_httpcontsize[] = "Content-Length: "; //static const char g_httpconn[] = "Connection: Keep-Alive"; //static const char g_httpcache[] = "Cache-Control: no-cache"; -/**************************************************************************** - * Private Functions - ****************************************************************************/ - /**************************************************************************** * Private Functions ****************************************************************************/ @@ -286,7 +281,7 @@ static inline int wget_parsestatus(struct wget_s *ws) } /**************************************************************************** - * Name: wget_parsestatus + * Name: wget_parseheaders ****************************************************************************/ static inline int wget_parseheaders(struct wget_s *ws) @@ -378,36 +373,54 @@ exit: * Name: wget_gethostip * * Description: - * Call gethostbyname() to get the IPv4 address associated with a hostname. + * Call getaddrinfo() to get the IPv4 address associated with a hostname. * * Input Parameters * hostname - The host name to use in the nslookup. - * ipv4addr - The location to return the IPv4 address. + * + * Output Parameters + * dest - The location to return the IPv4 address. * * Returned Value: - * Zero (OK) on success; a negated errno value on failure. + * Zero (OK) on success; ERROR on failure. * ****************************************************************************/ -static int wget_gethostip(FAR char *hostname, in_addr_t *ipv4addr) +static int wget_gethostip(FAR char *hostname, FAR struct in_addr *dest) { - FAR struct hostent *he; +#ifdef CONFIG_LIBC_NETDB + FAR struct addrinfo hint; + FAR struct addrinfo *info; + FAR struct sockaddr_in *addr; - he = gethostbyname(hostname); - if (he == NULL) + memset(&hint, 0, sizeof(hint)); + hint.ai_family = AF_INET; + + if (getaddrinfo(hostname, NULL, &hint, &info) != OK) { - nwarn("WARNING: gethostbyname failed: %d\n", h_errno); - return -ENOENT; - } - else if (he->h_addrtype != AF_INET) - { - nwarn("WARNING: gethostbyname returned an address of type: %d\n", - he->h_addrtype); - return -ENOEXEC; + return ERROR; } - memcpy(ipv4addr, he->h_addr, sizeof(in_addr_t)); + addr = (FAR struct sockaddr_in *)info->ai_addr; + memcpy(dest, &addr->sin_addr, sizeof(struct in_addr)); + + freeaddrinfo(info); return OK; +#else + /* No host name support */ + + /* Convert strings to numeric IPv4 address */ + + int ret = inet_pton(AF_INET, hostname, dest); + + /* The inet_pton() function returns 1 if the conversion succeeds. It will + * return 0 if the input is not a valid IPv4 dotted-decimal string or -1 + * with errno set to EAFNOSUPPORT if the address family argument is + * unsupported. + */ + + return (ret > 0) ? OK : ERROR; +#endif } /**************************************************************************** @@ -416,12 +429,6 @@ static int wget_gethostip(FAR char *hostname, in_addr_t *ipv4addr) * Description: * Obtain the requested file from an HTTP server using the GET method. * - * Note: If the function is passed a host name, it must already be in - * the resolver cache in order for the function to connect to the web - * server. It is therefore up to the calling module to implement the - * resolver calls and the signal handler used for reporting a resolv - * query answer. - * * Input Parameters * url - A pointer to a string containing either the full URL to * the file to get (e.g., http://www.nutt.org/index.html, or @@ -431,6 +438,7 @@ static int wget_gethostip(FAR char *hostname, in_addr_t *ipv4addr) * buflen - The size of the user provided buffer * callback - As data is obtained from the host, this function is * to dispose of each block of file data as it is received. + * arg - User argument passed to callback. * mode - Indicates GET or POST modes * * Returned Value: @@ -444,34 +452,40 @@ static int wget_base(FAR const char *url, FAR char *buffer, int buflen, FAR const char *posts, uint8_t mode) { struct sockaddr_in server; - struct wget_s ws; + struct wget_s *ws; struct timeval tv; bool redirected; - char *dest,post_size[8]; + char *dest; int sockfd; - int len,post_len; + int len; int ret; /* Initialize the state structure */ - memset(&ws, 0, sizeof(struct wget_s)); - ws.buffer = buffer; - ws.buflen = buflen; - ws.port = 80; + ws = calloc(1, sizeof(struct wget_s)); + if (!ws) + { + return ERROR; + } + + ws->buffer = buffer; + ws->buflen = buflen; + ws->port = 80; /* Parse the hostname (with optional port number) and filename from the URL */ - ret = netlib_parsehttpurl(url, &ws.port, - ws.hostname, CONFIG_WEBCLIENT_MAXHOSTNAME, - ws.filename, CONFIG_WEBCLIENT_MAXFILENAME); + ret = netlib_parsehttpurl(url, &ws->port, + ws->hostname, CONFIG_WEBCLIENT_MAXHOSTNAME, + ws->filename, CONFIG_WEBCLIENT_MAXFILENAME); if (ret != 0) { nwarn("WARNING: Malformed HTTP URL: %s\n", url); + free(ws); set_errno(-ret); return ERROR; } - ninfo("hostname='%s' filename='%s'\n", ws.hostname, ws.filename); + ninfo("hostname='%s' filename='%s'\n", ws->hostname, ws->filename); /* The following sequence may repeat indefinitely if we are redirected */ @@ -482,10 +496,10 @@ static int wget_base(FAR const char *url, FAR char *buffer, int buflen, * persist with the new connection. */ - ws.httpstatus = HTTPSTATUS_NONE; - ws.offset = 0; - ws.datend = 0; - ws.ndx = 0; + ws->httpstatus = HTTPSTATUS_NONE; + ws->offset = 0; + ws->datend = 0; + ws->ndx = 0; /* Create a socket */ @@ -495,6 +509,7 @@ static int wget_base(FAR const char *url, FAR char *buffer, int buflen, /* socket failed. It will set the errno appropriately */ nerr("ERROR: socket failed: %d\n", errno); + free(ws); return ERROR; } @@ -511,8 +526,8 @@ static int wget_base(FAR const char *url, FAR char *buffer, int buflen, /* Get the server address from the host name */ server.sin_family = AF_INET; - server.sin_port = htons(ws.port); - ret = wget_gethostip(ws.hostname, &server.sin_addr.s_addr); + server.sin_port = htons(ws->port); + ret = wget_gethostip(ws->hostname, &server.sin_addr); if (ret < 0) { /* Could not resolve host (or malformed IP address) */ @@ -536,7 +551,7 @@ static int wget_base(FAR const char *url, FAR char *buffer, int buflen, /* Send the GET request */ - dest = ws.buffer; + dest = ws->buffer; if (mode == WGET_MODE_POST) { dest = wget_strcpy(dest, g_httppost); @@ -547,21 +562,24 @@ static int wget_base(FAR const char *url, FAR char *buffer, int buflen, } #ifndef WGET_USE_URLENCODE - dest = wget_strcpy(dest, ws.filename); + dest = wget_strcpy(dest, ws->filename); #else - //dest = wget_urlencode_strcpy(dest, ws.filename); - dest = wget_strcpy(dest, ws.filename); + //dest = wget_urlencode_strcpy(dest, ws->filename); + dest = wget_strcpy(dest, ws->filename); #endif *dest++ = ISO_space; dest = wget_strcpy(dest, g_http10); dest = wget_strcpy(dest, g_httpcrnl); dest = wget_strcpy(dest, g_httphost); - dest = wget_strcpy(dest, ws.hostname); + dest = wget_strcpy(dest, ws->hostname); dest = wget_strcpy(dest, g_httpcrnl); if (mode == WGET_MODE_POST) { + int post_len; + char post_size[8]; + dest = wget_strcpy(dest, g_httpform); dest = wget_strcpy(dest, g_httpcrnl); dest = wget_strcpy(dest, g_httpcontsize); @@ -569,7 +587,7 @@ static int wget_base(FAR const char *url, FAR char *buffer, int buflen, /* Post content size */ post_len = strlen((char *)posts); - sprintf(post_size,"%d", post_len); + sprintf(post_size, "%d", post_len); dest = wget_strcpy(dest, post_size); dest = wget_strcpy(dest, g_httpcrnl); } @@ -594,18 +612,18 @@ static int wget_base(FAR const char *url, FAR char *buffer, int buflen, * or until we detect that we have been redirected. */ - ws.state = WEBCLIENT_STATE_STATUSLINE; + ws->state = WEBCLIENT_STATE_STATUSLINE; redirected = false; for (;;) { - ws.datend = recv(sockfd, ws.buffer, ws.buflen, 0); - if (ws.datend < 0) + ws->datend = recv(sockfd, ws->buffer, ws->buflen, 0); + if (ws->datend < 0) { nerr("ERROR: recv failed: %d\n", errno); - ret = ws.datend; + ret = ws->datend; goto errout_with_errno; } - else if (ws.datend == 0) + else if (ws->datend == 0) { ninfo("Connection lost\n"); close(sockfd); @@ -614,10 +632,10 @@ static int wget_base(FAR const char *url, FAR char *buffer, int buflen, /* Handle initial parsing of the status line */ - ws.offset = 0; - if (ws.state == WEBCLIENT_STATE_STATUSLINE) + ws->offset = 0; + if (ws->state == WEBCLIENT_STATE_STATUSLINE) { - ret = wget_parsestatus(&ws); + ret = wget_parsestatus(ws); if (ret < 0) { goto errout_with_errno; @@ -626,9 +644,9 @@ static int wget_base(FAR const char *url, FAR char *buffer, int buflen, /* Parse the HTTP data */ - if (ws.state == WEBCLIENT_STATE_HEADERS) + if (ws->state == WEBCLIENT_STATE_HEADERS) { - ret = wget_parseheaders(&ws); + ret = wget_parseheaders(ws); if (ret < 0) { goto errout_with_errno; @@ -637,13 +655,13 @@ static int wget_base(FAR const char *url, FAR char *buffer, int buflen, /* Dispose of the data payload */ - if (ws.state == WEBCLIENT_STATE_DATA) + if (ws->state == WEBCLIENT_STATE_DATA) { - if (ws.httpstatus != HTTPSTATUS_MOVED) + if (ws->httpstatus != HTTPSTATUS_MOVED) { /* Let the client decide what to do with the received file */ - callback(&ws.buffer, ws.offset, ws.datend, &buflen, arg); + callback(&ws->buffer, ws->offset, ws->datend, &buflen, arg); } else { @@ -656,12 +674,14 @@ static int wget_base(FAR const char *url, FAR char *buffer, int buflen, } while (redirected); + free(ws); return OK; errout_with_errno: set_errno(-ret); errout: close(sockfd); + free(ws); return ERROR; } @@ -677,10 +697,10 @@ errout: char *web_post_str(FAR char *buffer, int *size, FAR char *name, FAR char *value) { - char *dst=buffer; - buffer = wget_strcpy(buffer,name); + char *dst = buffer; + buffer = wget_strcpy(buffer, name); buffer = wget_strcpy(buffer, "="); - buffer = wget_urlencode_strcpy(buffer,value); + buffer = wget_urlencode_strcpy(buffer, value); *size = buffer - dst; return dst; } @@ -693,7 +713,7 @@ char *web_post_str(FAR char *buffer, int *size, FAR char *name, #ifdef WGET_USE_URLENCODE int web_post_strlen(FAR char *name, FAR char *value) { - return strlen(name) + urlencode_len(value,strlen(value)) + 1; + return strlen(name) + urlencode_len(value, strlen(value)) + 1; } #endif @@ -705,7 +725,7 @@ int web_post_strlen(FAR char *name, FAR char *value) char *web_posts_str(FAR char *buffer, int *size, FAR char **name, FAR char **value, int len) { - char *dst=buffer; + char *dst = buffer; int wlen; int i; @@ -721,7 +741,7 @@ char *web_posts_str(FAR char *buffer, int *size, FAR char **name, buffer += wlen; } - *size=buffer-dst; + *size = buffer - dst; return dst; } #endif @@ -751,12 +771,6 @@ int web_posts_strlen(FAR char **name, FAR char **value, int len) * Description: * Obtain the requested file from an HTTP server using the GET method. * - * Note: If the function is passed a host name, it must already be in - * the resolver cache in order for the function to connect to the web - * server. It is therefore up to the calling module to implement the - * resolver calls and the signal handler used for reporting a resolv - * query answer. - * * Input Parameters * url - A pointer to a string containing either the full URL to * the file to get (e.g., http://www.nutt.org/index.html, or @@ -766,6 +780,7 @@ int web_posts_strlen(FAR char **name, FAR char **value, int len) * buflen - The size of the user provided buffer * callback - As data is obtained from the host, this function is * to dispose of each block of file data as it is received. + * arg - User argument passed to callback. * * Returned Value: * 0: if the GET operation completed successfully;