From e893f98787b383aeb9bd205f4b978f5a34cf1d00 Mon Sep 17 00:00:00 2001 From: twinaphex Date: Mon, 26 Jan 2015 20:47:59 +0100 Subject: [PATCH] (net_http.c) Cleanups --- net_http.c | 499 ++++++++++++++++++++++++++--------------------------- 1 file changed, 249 insertions(+), 250 deletions(-) diff --git a/net_http.c b/net_http.c index 2201cb58de..45337e899e 100644 --- a/net_http.c +++ b/net_http.c @@ -33,8 +33,9 @@ enum enum { - t_full, - t_len, t_chunk + T_FULL = 0, + T_LEN, + T_CHUNK }; static bool net_http_parse_url(char *url, char **domain, @@ -80,60 +81,60 @@ static int net_http_new_socket(const char * domain, int port) #ifdef _WIN32 u_long mode = 1; #else - struct timeval timeout; + struct timeval timeout; #endif - struct addrinfo hints, *addr = NULL; - char portstr[16]; + struct addrinfo hints, *addr = NULL; + char portstr[16]; - snprintf(portstr, sizeof(portstr), "%i", port); - - memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - hints.ai_flags = 0; - - if (getaddrinfo_rarch(domain, portstr, &hints, &addr) < 0) + snprintf(portstr, sizeof(portstr), "%i", port); + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = 0; + + if (getaddrinfo_rarch(domain, portstr, &hints, &addr) < 0) return -1; - + (void)i; - - fd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol); + + fd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol); #ifndef _WIN32 - timeout.tv_sec=4; - timeout.tv_usec=0; - setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, (char*)&timeout, sizeof timeout); + timeout.tv_sec=4; + timeout.tv_usec=0; + setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, (char*)&timeout, sizeof timeout); #endif - if (connect(fd, addr->ai_addr, addr->ai_addrlen) != 0) - { - freeaddrinfo_rarch(addr); - socket_close(fd); - return -1; - } - - freeaddrinfo_rarch(addr); - - if (!socket_nonblock(fd)) + if (connect(fd, addr->ai_addr, addr->ai_addrlen) != 0) { - socket_close(fd); + freeaddrinfo_rarch(addr); + socket_close(fd); return -1; } - return fd; + freeaddrinfo_rarch(addr); + + if (!socket_nonblock(fd)) + { + socket_close(fd); + return -1; + } + + return fd; } static void net_http_send(int fd, bool * error, const char * data, size_t len) { - if (*error) + if (*error) return; - while (len) - { - ssize_t thislen = send(fd, data, len, MSG_NOSIGNAL); + while (len) + { + ssize_t thislen = send(fd, data, len, MSG_NOSIGNAL); - if (thislen <= 0) + if (thislen <= 0) { if (!isagain(thislen)) continue; @@ -142,14 +143,14 @@ static void net_http_send(int fd, bool * error, return; } - data += thislen; - len -= thislen; - } + data += thislen; + len -= thislen; + } } static void net_http_send_str(int fd, bool *error, const char *text) { - net_http_send(fd, error, text, strlen(text)); + net_http_send(fd, error, text, strlen(text)); } static ssize_t net_http_recv(int fd, bool *error, @@ -175,297 +176,295 @@ static ssize_t net_http_recv(int fd, bool *error, http_t *net_http_new(const char * url) { - bool error; + bool error; char *domain = NULL, *location = NULL; - int port = 0, fd = -1; - http_t *state = NULL; - char *urlcopy =(char*)malloc(strlen(url)+1); + int port = 0, fd = -1; + http_t *state = NULL; + char *urlcopy =(char*)malloc(strlen(url)+1); - strcpy(urlcopy, url); + strcpy(urlcopy, url); - if (!net_http_parse_url(urlcopy, &domain, &port, &location)) + if (!net_http_parse_url(urlcopy, &domain, &port, &location)) goto fail; - fd = net_http_new_socket(domain, port); - if (fd == -1) + fd = net_http_new_socket(domain, port); + if (fd == -1) goto fail; - - error=false; - - /* This is a bit lazy, but it works. */ - net_http_send_str(fd, &error, "GET /"); - net_http_send_str(fd, &error, location); - net_http_send_str(fd, &error, " HTTP/1.1\r\n"); - - net_http_send_str(fd, &error, "Host: "); - net_http_send_str(fd, &error, domain); - if (port!=80) - { - char portstr[16]; + error=false; - snprintf(portstr, sizeof(portstr), ":%i", port); - net_http_send_str(fd, &error, portstr); - } + /* This is a bit lazy, but it works. */ + net_http_send_str(fd, &error, "GET /"); + net_http_send_str(fd, &error, location); + net_http_send_str(fd, &error, " HTTP/1.1\r\n"); - net_http_send_str(fd, &error, "\r\n"); - net_http_send_str(fd, &error, "Connection: close\r\n"); - net_http_send_str(fd, &error, "\r\n"); - - if (error) + net_http_send_str(fd, &error, "Host: "); + net_http_send_str(fd, &error, domain); + + if (port!=80) + { + char portstr[16]; + + snprintf(portstr, sizeof(portstr), ":%i", port); + net_http_send_str(fd, &error, portstr); + } + + net_http_send_str(fd, &error, "\r\n"); + net_http_send_str(fd, &error, "Connection: close\r\n"); + net_http_send_str(fd, &error, "\r\n"); + + if (error) goto fail; - - free(urlcopy); - - state = (http_t*)malloc(sizeof(http_t)); - state->fd = fd; - state->status = -1; - state->data = NULL; - state->part = p_header_top; - state->bodytype= t_full; - state->error = false; - state->pos = 0; - state->len = 0; - state->buflen = 512; - state->data = (char*)malloc(state->buflen); - return state; - + free(urlcopy); + + state = (http_t*)malloc(sizeof(http_t)); + state->fd = fd; + state->status = -1; + state->data = NULL; + state->part = p_header_top; + state->bodytype= T_FULL; + state->error = false; + state->pos = 0; + state->len = 0; + state->buflen = 512; + state->data = (char*)malloc(state->buflen); + + return state; + fail: - if (fd != -1) + if (fd != -1) socket_close(fd); - free(urlcopy); - return NULL; + free(urlcopy); + return NULL; } int net_http_fd(http_t *state) { - return state->fd; + return state->fd; } bool net_http_update(http_t *state, size_t* progress, size_t* total) { - ssize_t newlen = 0; - - if (state->error) + ssize_t newlen = 0; + + if (state->error) goto fail; - - if (state->part < p_body) - { - newlen = net_http_recv(state->fd, &state->error, + + if (state->part < p_body) + { + newlen = net_http_recv(state->fd, &state->error, (uint8_t*)state->data + state->pos, state->buflen - state->pos); - if (newlen < 0) + if (newlen < 0) goto fail; - if (state->pos + newlen >= state->buflen - 64) - { - state->buflen *= 2; - state->data = (char*)realloc(state->data, state->buflen); - } - state->pos += newlen; + if (state->pos + newlen >= state->buflen - 64) + { + state->buflen *= 2; + state->data = (char*)realloc(state->data, state->buflen); + } + state->pos += newlen; - while (state->part < p_body) - { - char *dataend = state->data + state->pos; - char *lineend = (char*)memchr(state->data, '\n', state->pos); + while (state->part < p_body) + { + char *dataend = state->data + state->pos; + char *lineend = (char*)memchr(state->data, '\n', state->pos); - if (!lineend) + if (!lineend) break; - *lineend='\0'; - if (lineend != state->data && lineend[-1]=='\r') + *lineend='\0'; + if (lineend != state->data && lineend[-1]=='\r') lineend[-1]='\0'; - - if (state->part == p_header_top) - { - if (strncmp(state->data, "HTTP/1.", strlen("HTTP/1."))!=0) + + if (state->part == p_header_top) + { + if (strncmp(state->data, "HTTP/1.", strlen("HTTP/1."))!=0) goto fail; - state->status=strtoul(state->data + strlen("HTTP/1.1 "), NULL, 10); - state->part = p_header; - } - else - { - if (!strncmp(state->data, "Content-Length: ", + state->status=strtoul(state->data + strlen("HTTP/1.1 "), NULL, 10); + state->part = p_header; + } + else + { + if (!strncmp(state->data, "Content-Length: ", strlen("Content-Length: "))) - { - state->bodytype = t_len; - state->len = strtol(state->data + + { + state->bodytype = T_LEN; + state->len = strtol(state->data + strlen("Content-Length: "), NULL, 10); - } - if (!strcmp(state->data, "Transfer-Encoding: chunked")) - { - state->bodytype=t_chunk; - } + } + if (!strcmp(state->data, "Transfer-Encoding: chunked")) + state->bodytype = T_CHUNK; - /* TODO: save headers somewhere */ - if (state->data[0]=='\0') - { - state->part = p_body; - if (state->bodytype == t_chunk) + /* TODO: save headers somewhere */ + if (state->data[0]=='\0') + { + state->part = p_body; + if (state->bodytype == T_CHUNK) state->part = p_body_chunklen; - } - } - - memmove(state->data, lineend + 1, dataend-(lineend+1)); - state->pos = (dataend-(lineend + 1)); - } - if (state->part >= p_body) - { - newlen = state->pos; - state->pos = 0; - } - } + } + } - if (state->part >= p_body && state->part < p_done) - { - if (!newlen) - { - newlen = net_http_recv(state->fd, &state->error, + memmove(state->data, lineend + 1, dataend-(lineend+1)); + state->pos = (dataend-(lineend + 1)); + } + if (state->part >= p_body) + { + newlen = state->pos; + state->pos = 0; + } + } + + if (state->part >= p_body && state->part < p_done) + { + if (!newlen) + { + newlen = net_http_recv(state->fd, &state->error, (uint8_t*)state->data + state->pos, state->buflen - state->pos); - if (newlen < 0) - { - if (state->bodytype == t_full) - { + if (newlen < 0) + { + if (state->bodytype == T_FULL) + { state->part = p_done; state->data = (char*)realloc(state->data, state->len); - } - else + } + else goto fail; - newlen=0; - } + newlen=0; + } + + if (state->pos + newlen >= state->buflen - 64) + { + state->buflen *= 2; + state->data = (char*)realloc(state->data, state->buflen); + } + } - if (state->pos + newlen >= state->buflen - 64) - { - state->buflen *= 2; - state->data = (char*)realloc(state->data, state->buflen); - } - } - parse_again: - if (state->bodytype == t_chunk) - { - if (state->part == p_body_chunklen) - { - state->pos += newlen; - if (state->pos - state->len >= 2) - { - /* + if (state->bodytype == T_CHUNK) + { + if (state->part == p_body_chunklen) + { + state->pos += newlen; + if (state->pos - state->len >= 2) + { + /* * len=start of chunk including \r\n * pos=end of data */ - char *fullend = state->data + state->pos; - char *end = (char*)memchr(state->data + state->len + 2, + char *fullend = state->data + state->pos; + char *end = (char*)memchr(state->data + state->len + 2, '\n', state->pos - state->len - 2); - if (end) - { - size_t chunklen = strtoul(state->data+state->len, NULL, 16); - state->pos = state->len; - end++; + if (end) + { + size_t chunklen = strtoul(state->data+state->len, NULL, 16); + state->pos = state->len; + end++; - memmove(state->data+state->len, end, fullend-end); + memmove(state->data+state->len, end, fullend-end); - state->len = chunklen; - newlen = (fullend - end); + state->len = chunklen; + newlen = (fullend - end); /* - len=num bytes - newlen=unparsed bytes after \n - pos=start of chunk including \r\n - */ + len=num bytes + newlen=unparsed bytes after \n + pos=start of chunk including \r\n + */ - state->part = p_body; - if (state->len == 0) - { - state->part = p_done; - state->len = state->pos; - state->data = (char*)realloc(state->data, state->len); - } - goto parse_again; - } - } - } - else if (state->part == p_body) - { - if ((size_t)newlen >= state->len) - { - state->pos += state->len; - newlen -= state->len; - state->len = state->pos; - state->part = p_body_chunklen; - goto parse_again; - } - else - { - state->pos += newlen; - state->len -= newlen; - } - } - } - else - { - state->pos += newlen; + state->part = p_body; + if (state->len == 0) + { + state->part = p_done; + state->len = state->pos; + state->data = (char*)realloc(state->data, state->len); + } + goto parse_again; + } + } + } + else if (state->part == p_body) + { + if ((size_t)newlen >= state->len) + { + state->pos += state->len; + newlen -= state->len; + state->len = state->pos; + state->part = p_body_chunklen; + goto parse_again; + } + else + { + state->pos += newlen; + state->len -= newlen; + } + } + } + else + { + state->pos += newlen; - if (state->pos == state->len) - { + if (state->pos == state->len) + { state->part=p_done; state->data = (char*)realloc(state->data, state->len); - } - if (state->pos > state->len) + } + if (state->pos > state->len) goto fail; - } - } - - if (progress) + } + } + + if (progress) *progress = state->pos; - if (total) - { - if (state->bodytype == t_len) + if (total) + { + if (state->bodytype == T_LEN) *total=state->len; - else + else *total=0; - } - - return (state->part==p_done); - -fail: - state->error = true; - state->part = p_error; - state->status = -1; + } - return true; + return (state->part==p_done); + +fail: + state->error = true; + state->part = p_error; + state->status = -1; + + return true; } int net_http_status(http_t *state) { - return state->status; + return state->status; } uint8_t* net_http_data(http_t *state, size_t* len, bool accept_error) { - if (!accept_error && + if (!accept_error && (state->error || state->status<200 || state->status>299)) - { - if (len) + { + if (len) *len=0; - return NULL; - } + return NULL; + } - if (len) + if (len) *len=state->len; - return (uint8_t*)state->data; + return (uint8_t*)state->data; } void net_http_delete(http_t *state) { - if (state->fd != -1) + if (state->fd != -1) socket_close(state->fd); - if (state->data) + if (state->data) free(state->data); - free(state); + free(state); }