mirror of
https://github.com/libretro/RetroArch
synced 2025-02-06 09:40:06 +00:00
Style nits/cleanups
This commit is contained in:
parent
e7d77e98ef
commit
05f6a65426
@ -663,6 +663,7 @@ NETPLAY
|
|||||||
#include "../netplay.c"
|
#include "../netplay.c"
|
||||||
#include "../http_lib.c"
|
#include "../http_lib.c"
|
||||||
#include "../http_intf.c"
|
#include "../http_intf.c"
|
||||||
|
//#include "../http-new.c"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*============================================================
|
/*============================================================
|
||||||
|
407
http-new.c
407
http-new.c
@ -9,56 +9,66 @@
|
|||||||
struct http;
|
struct http;
|
||||||
struct http* http_new(const char * url);
|
struct http* http_new(const char * url);
|
||||||
|
|
||||||
//You can use this to call http_update only when something will happen; select() it for reading.
|
/* You can use this to call http_update
|
||||||
|
* only when something will happen; select() it for reading. */
|
||||||
int http_fd(struct http* state);
|
int http_fd(struct http* state);
|
||||||
|
|
||||||
//Returns true if it's done, or if something broke. 'total' will be 0 if it's not known.
|
/* Returns true if it's done, or if something broke.
|
||||||
|
* 'total' will be 0 if it's not known. */
|
||||||
bool http_update(struct http* state, size_t* progress, size_t* total);
|
bool http_update(struct http* state, size_t* progress, size_t* total);
|
||||||
|
|
||||||
//200, 404, or whatever.
|
/* 200, 404, or whatever. */
|
||||||
int http_status(struct http* state);
|
int http_status(struct http* state);
|
||||||
|
|
||||||
//Returns the downloaded data. The returned buffer is owned by the HTTP handler; it's freed by http_delete.
|
/* Returns the downloaded data. The returned buffer is owned by the
|
||||||
//If the status is not 20x and accept_error is false, it returns NULL.
|
* HTTP handler; it's freed by http_delete.
|
||||||
|
*
|
||||||
|
* If the status is not 20x and accept_error is false, it returns NULL. */
|
||||||
uint8_t* http_data(struct http* state, size_t* len, bool accept_error);
|
uint8_t* http_data(struct http* state, size_t* len, bool accept_error);
|
||||||
|
|
||||||
//Cleans up all memory.
|
/* Cleans up all memory. */
|
||||||
void http_delete(struct http* state);
|
void http_delete(struct http* state);
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//test.c
|
//test.c
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef RARCH_INTERNAL
|
||||||
#include<stdio.h>
|
#include<stdio.h>
|
||||||
int main()
|
int main(void)
|
||||||
{
|
{
|
||||||
struct http* http1;
|
char *w;
|
||||||
struct http* http2;
|
struct http* http1, *http2, *http3;
|
||||||
struct http* http3;
|
size_t q, pos = 0; size_t tot = 0;
|
||||||
size_t pos=0; size_t tot=0;
|
|
||||||
http1=http_new("http://buildbot.libretro.com/nightly/win-x86/latest/mednafen_psx_libretro.dll.zip");
|
http1 = http_new("http://buildbot.libretro.com/nightly/win-x86/latest/mednafen_psx_libretro.dll.zip");
|
||||||
|
|
||||||
while (!http_update(http1, &pos, &tot))
|
while (!http_update(http1, &pos, &tot))
|
||||||
{
|
|
||||||
printf("%.9lu / %.9lu \r",pos,tot);
|
printf("%.9lu / %.9lu \r",pos,tot);
|
||||||
}
|
|
||||||
|
|
||||||
http3=http_new("http://www.wikipedia.org/");
|
http3 = http_new("http://www.wikipedia.org/");
|
||||||
while (!http_update(http3, NULL, NULL)) {}
|
while (!http_update(http3, NULL, NULL)) {}
|
||||||
|
|
||||||
size_t q;
|
w = (char*)http_data(http3, &q, false);
|
||||||
char*w=(char*)http_data(http3,&q,false);
|
|
||||||
printf("%.*s\n",(int)256,w);
|
printf("%.*s\n", (int)256, w);
|
||||||
//struct http* http1=http_new("http://floating.muncher.se:22/");
|
|
||||||
//struct http* http2=http_new("http://floating.muncher.se/sepulcher/");
|
#if 0
|
||||||
//struct http* http3=http_new("http://www.wikipedia.org/");
|
struct http* http1=http_new("http://floating.muncher.se:22/");
|
||||||
//while (!http_update(http3, NULL, NULL)) {}
|
struct http* http2=http_new("http://floating.muncher.se/sepulcher/");
|
||||||
//while (!http_update(http2, NULL, NULL)) {}
|
struct http* http3=http_new("http://www.wikipedia.org/");
|
||||||
//while (!http_update(http1, NULL, NULL)) {}
|
while (!http_update(http3, NULL, NULL)) {}
|
||||||
//printf("%i %i %i %p %s %s\n",
|
while (!http_update(http2, NULL, NULL)) {}
|
||||||
//http_status(http1),http_status(http2),http_status(http3),
|
while (!http_update(http1, NULL, NULL)) {}
|
||||||
//(char*)http_data(http1, NULL, false),http_data(http2, NULL, true),http_data(http3, NULL, true));
|
printf("%i %i %i %p %s %s\n",
|
||||||
|
http_status(http1),http_status(http2),http_status(http3),
|
||||||
|
(char*)http_data(http1, NULL, false),http_data(http2, NULL, true),http_data(http3, NULL, true));
|
||||||
|
#endif
|
||||||
http_delete(http1);
|
http_delete(http1);
|
||||||
http_delete(http3);
|
http_delete(http3);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//http.c
|
//http.c
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
@ -67,7 +77,7 @@ int main()
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
//much of this is copypasta from elsewhere, I don't know if it works.
|
/* Much of this is copypasta from elsewhere, I don't know if it works. */
|
||||||
#define _WIN32_WINNT 0x501
|
#define _WIN32_WINNT 0x501
|
||||||
#include <winsock2.h>
|
#include <winsock2.h>
|
||||||
#include <ws2tcpip.h>
|
#include <ws2tcpip.h>
|
||||||
@ -94,243 +104,308 @@ int main()
|
|||||||
#define isagain(bytes) (bytes<0 && (errno==EAGAIN || errno==EWOULDBLOCK))
|
#define isagain(bytes) (bytes<0 && (errno==EAGAIN || errno==EWOULDBLOCK))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct http {
|
struct http
|
||||||
|
{
|
||||||
int fd;
|
int fd;
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
char part;
|
char part;
|
||||||
char bodytype;
|
char bodytype;
|
||||||
bool error;
|
bool error;
|
||||||
//char padding[5];
|
#if 0
|
||||||
|
char padding[5];
|
||||||
|
#endif
|
||||||
|
|
||||||
size_t pos;
|
size_t pos;
|
||||||
size_t len;
|
size_t len;
|
||||||
size_t buflen;
|
size_t buflen;
|
||||||
char * data;
|
char * data;
|
||||||
};
|
};
|
||||||
enum { p_header_top, p_header, p_body, p_body_chunklen, p_done, p_error };
|
|
||||||
enum { t_full, t_len, t_chunk };
|
|
||||||
|
|
||||||
static bool http_parse_url(char * url, char* * domain, int* port, char* * location)
|
enum
|
||||||
|
{
|
||||||
|
p_header_top,
|
||||||
|
p_header,
|
||||||
|
p_body,
|
||||||
|
p_body_chunklen,
|
||||||
|
p_done, p_error
|
||||||
|
};
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
t_full,
|
||||||
|
t_len, t_chunk
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool http_parse_url(char *url, char **domain,
|
||||||
|
int *port, char **location)
|
||||||
{
|
{
|
||||||
char* scan;
|
char* scan;
|
||||||
if (strncmp(url, "http://", strlen("http://"))!=0) return false;
|
|
||||||
scan = url+strlen("http://");
|
if (strncmp(url, "http://", strlen("http://")) != 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
scan = url + strlen("http://");
|
||||||
*domain = scan;
|
*domain = scan;
|
||||||
while (*scan!='/' && *scan!=':' && *scan!='\0') scan++;
|
|
||||||
if (*scan=='\0') return false;
|
while (*scan!='/' && *scan!=':' && *scan!='\0')
|
||||||
if (*scan==':')
|
scan++;
|
||||||
|
|
||||||
|
if (*scan == '\0')
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (*scan == ':')
|
||||||
{
|
{
|
||||||
*scan='\0';
|
*scan='\0';
|
||||||
if (!isdigit(scan[1])) return false;
|
|
||||||
*port=strtoul(scan+1, &scan, 10);
|
if (!isdigit(scan[1]))
|
||||||
if (*scan!='/') return false;
|
return false;
|
||||||
|
|
||||||
|
*port = strtoul(scan+1, &scan, 10);
|
||||||
|
|
||||||
|
if (*scan != '/')
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
else // known '/'
|
else /* known '/' */
|
||||||
{
|
{
|
||||||
*scan='\0';
|
*scan='\0';
|
||||||
*port=80;
|
*port=80;
|
||||||
}
|
}
|
||||||
|
|
||||||
*location=scan+1;
|
*location=scan+1;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int http_new_socket(const char * domain, int port)
|
static int http_new_socket(const char * domain, int port)
|
||||||
{
|
{
|
||||||
|
int fd;
|
||||||
|
#ifndef _WIN32
|
||||||
|
struct timeval timeout;
|
||||||
|
#endif
|
||||||
|
struct addrinfo hints, *addr = NULL;
|
||||||
char portstr[16];
|
char portstr[16];
|
||||||
|
|
||||||
sprintf(portstr, "%i", port);
|
sprintf(portstr, "%i", port);
|
||||||
|
|
||||||
struct addrinfo hints;
|
|
||||||
memset(&hints, 0, sizeof(hints));
|
memset(&hints, 0, sizeof(hints));
|
||||||
hints.ai_family=AF_UNSPEC;
|
hints.ai_family=AF_UNSPEC;
|
||||||
hints.ai_socktype=SOCK_STREAM;
|
hints.ai_socktype=SOCK_STREAM;
|
||||||
hints.ai_flags=0;
|
hints.ai_flags=0;
|
||||||
|
|
||||||
struct addrinfo* addr=NULL;
|
|
||||||
getaddrinfo(domain, portstr, &hints, &addr);
|
getaddrinfo(domain, portstr, &hints, &addr);
|
||||||
if (!addr) return -1;
|
if (!addr)
|
||||||
|
return -1;
|
||||||
|
|
||||||
int fd=socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
|
fd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
//30 second pauses annoy me
|
|
||||||
struct timeval timeout;
|
|
||||||
timeout.tv_sec=4;
|
timeout.tv_sec=4;
|
||||||
timeout.tv_usec=0;
|
timeout.tv_usec=0;
|
||||||
setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, (char*)&timeout, sizeof timeout);
|
setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, (char*)&timeout, sizeof timeout);
|
||||||
#endif
|
#endif
|
||||||
if (connect(fd, addr->ai_addr, addr->ai_addrlen)!=0)
|
|
||||||
|
if (connect(fd, addr->ai_addr, addr->ai_addrlen) != 0)
|
||||||
{
|
{
|
||||||
freeaddrinfo(addr);
|
freeaddrinfo(addr);
|
||||||
close(fd);
|
close(fd);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
freeaddrinfo(addr);
|
freeaddrinfo(addr);
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
//Linux claims to not know that select() should only give sockets where read() is nonblocking
|
/* Linux claims to not know that select() should only
|
||||||
|
* give sockets where read() is nonblocking */
|
||||||
fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0)|O_NONBLOCK);
|
fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0)|O_NONBLOCK);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void http_send(int fd, bool * error, const char * data, size_t len)
|
static void http_send(int fd, bool * error,
|
||||||
|
const char * data, size_t len)
|
||||||
{
|
{
|
||||||
if (*error) return;
|
if (*error)
|
||||||
|
return;
|
||||||
|
|
||||||
while (len)
|
while (len)
|
||||||
{
|
{
|
||||||
ssize_t thislen=send(fd, data, len, MSG_NOSIGNAL);
|
ssize_t thislen = send(fd, data, len, MSG_NOSIGNAL);
|
||||||
if (thislen<=0)
|
|
||||||
{
|
if (thislen <= 0)
|
||||||
if (!isagain(thislen))
|
{
|
||||||
{
|
if (!isagain(thislen))
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
else
|
*error=true;
|
||||||
{
|
return;
|
||||||
*error=true;
|
}
|
||||||
return;
|
|
||||||
}
|
data += thislen;
|
||||||
}
|
len -= thislen;
|
||||||
data+=thislen;
|
|
||||||
len-=thislen;
|
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void http_send_str(int fd, bool * error, const char * text)
|
static void http_send_str(int fd, bool *error, const char *text)
|
||||||
{
|
{
|
||||||
http_send(fd, error, text, strlen(text));
|
http_send(fd, error, text, strlen(text));
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t http_recv(int fd, bool * error, uint8_t* data, size_t maxlen)
|
static ssize_t http_recv(int fd, bool *error,
|
||||||
|
uint8_t *data, size_t maxlen)
|
||||||
{
|
{
|
||||||
if (*error) return -1;
|
ssize_t bytes;
|
||||||
|
|
||||||
ssize_t bytes=recv(fd, data, maxlen, 0);
|
if (*error)
|
||||||
if (bytes>0) return bytes;
|
return -1;
|
||||||
else if (bytes==0) return -1;
|
|
||||||
else if (isagain(bytes)) return 0;
|
bytes = recv(fd, data, maxlen, 0);
|
||||||
else
|
|
||||||
{
|
if (bytes > 0)
|
||||||
*error=true;
|
return bytes;
|
||||||
return -1;
|
else if (bytes == 0)
|
||||||
}
|
return -1;
|
||||||
|
else if (isagain(bytes))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
*error=true;
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct http* http_new(const char * url)
|
struct http* http_new(const char * url)
|
||||||
{
|
{
|
||||||
char* urlcopy=(char*)malloc(strlen(url)+1);
|
|
||||||
char* domain;
|
|
||||||
int port;
|
|
||||||
char* location;
|
|
||||||
struct http* state=NULL;
|
|
||||||
int fd=-1;
|
|
||||||
bool error;
|
bool error;
|
||||||
|
char *domain, *location;
|
||||||
|
int port, fd = -1;
|
||||||
|
struct http* state = NULL;
|
||||||
|
char *urlcopy =(char*)malloc(strlen(url)+1);
|
||||||
|
|
||||||
strcpy(urlcopy, url);
|
strcpy(urlcopy, url);
|
||||||
if (!http_parse_url(urlcopy, &domain, &port, &location)) goto fail;
|
|
||||||
fd=http_new_socket(domain, port);
|
if (!http_parse_url(urlcopy, &domain, &port, &location))
|
||||||
if (fd==-1) goto fail;
|
goto fail;
|
||||||
|
|
||||||
|
fd = http_new_socket(domain, port);
|
||||||
|
if (fd == -1)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
error=false;
|
error=false;
|
||||||
|
|
||||||
//this is a bit lazy, but it works
|
/* This is a bit lazy, but it works. */
|
||||||
http_send_str(fd, &error, "GET /");
|
http_send_str(fd, &error, "GET /");
|
||||||
http_send_str(fd, &error, location);
|
http_send_str(fd, &error, location);
|
||||||
http_send_str(fd, &error, " HTTP/1.1\r\n");
|
http_send_str(fd, &error, " HTTP/1.1\r\n");
|
||||||
|
|
||||||
http_send_str(fd, &error, "Host: ");
|
http_send_str(fd, &error, "Host: ");
|
||||||
http_send_str(fd, &error, domain);
|
http_send_str(fd, &error, domain);
|
||||||
|
|
||||||
if (port!=80)
|
if (port!=80)
|
||||||
{
|
{
|
||||||
char portstr[16];
|
char portstr[16];
|
||||||
sprintf(portstr, ":%i", port);
|
sprintf(portstr, ":%i", port);
|
||||||
http_send_str(fd, &error, portstr);
|
http_send_str(fd, &error, portstr);
|
||||||
}
|
}
|
||||||
|
|
||||||
http_send_str(fd, &error, "\r\n");
|
http_send_str(fd, &error, "\r\n");
|
||||||
|
|
||||||
http_send_str(fd, &error, "Connection: close\r\n");
|
http_send_str(fd, &error, "Connection: close\r\n");
|
||||||
|
|
||||||
http_send_str(fd, &error, "\r\n");
|
http_send_str(fd, &error, "\r\n");
|
||||||
|
|
||||||
if (error) goto fail;
|
if (error)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
free(urlcopy);
|
free(urlcopy);
|
||||||
|
|
||||||
state=(struct http*)malloc(sizeof(struct http));
|
state = (struct http*)malloc(sizeof(struct http));
|
||||||
state->fd=fd;
|
state->fd = fd;
|
||||||
state->status=-1;
|
state->status = -1;
|
||||||
state->data=NULL;
|
state->data = NULL;
|
||||||
state->part=p_header_top;
|
state->part = p_header_top;
|
||||||
state->bodytype=t_full;
|
state->bodytype= t_full;
|
||||||
state->error=false;
|
state->error = false;
|
||||||
state->pos=0;
|
state->pos = 0;
|
||||||
state->len=0;
|
state->len = 0;
|
||||||
state->buflen=512;
|
state->buflen = 512;
|
||||||
state->data=(char*)malloc(state->buflen);
|
state->data = (char*)malloc(state->buflen);
|
||||||
|
|
||||||
return state;
|
return state;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
if (fd!=-1) close(fd);
|
if (fd != -1)
|
||||||
|
close(fd);
|
||||||
free(urlcopy);
|
free(urlcopy);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int http_fd(struct http* state)
|
int http_fd(struct http *state)
|
||||||
{
|
{
|
||||||
return state->fd;
|
return state->fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool http_update(struct http* state, size_t* progress, size_t* total)
|
bool http_update(struct http* state, size_t* progress, size_t* total)
|
||||||
{
|
{
|
||||||
ssize_t newlen=0;
|
ssize_t newlen = 0;
|
||||||
|
|
||||||
if (state->error) goto fail;
|
if (state->error)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
if (state->part < p_body)
|
if (state->part < p_body)
|
||||||
{
|
{
|
||||||
newlen=http_recv(state->fd, &state->error, (uint8_t*)state->data + state->pos, state->buflen - state->pos);
|
newlen = http_recv(state->fd, &state->error,
|
||||||
//newlen=http_recv(state->fd, &state->error, (uint8_t*)state->data + state->pos, 1);
|
(uint8_t*)state->data + state->pos, state->buflen - state->pos);
|
||||||
if (newlen<0) goto fail;
|
|
||||||
|
if (newlen < 0)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
if (state->pos + newlen >= state->buflen - 64)
|
if (state->pos + newlen >= state->buflen - 64)
|
||||||
{
|
{
|
||||||
state->buflen *= 2;
|
state->buflen *= 2;
|
||||||
state->data = (char*)realloc(state->data, state->buflen);
|
state->data = (char*)realloc(state->data, state->buflen);
|
||||||
}
|
}
|
||||||
state->pos += newlen;
|
state->pos += newlen;
|
||||||
|
|
||||||
while (state->part < p_body)
|
while (state->part < p_body)
|
||||||
{
|
{
|
||||||
char * dataend = state->data + state->pos;
|
char *dataend = state->data + state->pos;
|
||||||
char * lineend = (char*)memchr(state->data, '\n', state->pos);
|
char *lineend = (char*)memchr(state->data, '\n', state->pos);
|
||||||
if (!lineend) break;
|
|
||||||
|
if (!lineend)
|
||||||
|
break;
|
||||||
*lineend='\0';
|
*lineend='\0';
|
||||||
if (lineend != state->data && lineend[-1]=='\r') lineend[-1]='\0';
|
if (lineend != state->data && lineend[-1]=='\r')
|
||||||
|
lineend[-1]='\0';
|
||||||
|
|
||||||
if (state->part == p_header_top)
|
if (state->part == p_header_top)
|
||||||
{
|
{
|
||||||
if (strncmp(state->data, "HTTP/1.", strlen("HTTP/1."))!=0) goto fail;
|
if (strncmp(state->data, "HTTP/1.", strlen("HTTP/1."))!=0)
|
||||||
|
goto fail;
|
||||||
state->status=strtoul(state->data + strlen("HTTP/1.1 "), NULL, 10);
|
state->status=strtoul(state->data + strlen("HTTP/1.1 "), NULL, 10);
|
||||||
state->part = p_header;
|
state->part = p_header;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!strncmp(state->data, "Content-Length: ", strlen("Content-Length: ")))
|
if (!strncmp(state->data, "Content-Length: ",
|
||||||
|
strlen("Content-Length: ")))
|
||||||
{
|
{
|
||||||
state->bodytype = t_len;
|
state->bodytype = t_len;
|
||||||
state->len = strtol(state->data + strlen("Content-Length: "), NULL, 10);
|
state->len = strtol(state->data +
|
||||||
|
strlen("Content-Length: "), NULL, 10);
|
||||||
}
|
}
|
||||||
if (!strcmp(state->data, "Transfer-Encoding: chunked"))
|
if (!strcmp(state->data, "Transfer-Encoding: chunked"))
|
||||||
{
|
{
|
||||||
state->bodytype=t_chunk;
|
state->bodytype=t_chunk;
|
||||||
}
|
}
|
||||||
//TODO: save headers somewhere
|
|
||||||
|
/* TODO: save headers somewhere */
|
||||||
if (state->data[0]=='\0')
|
if (state->data[0]=='\0')
|
||||||
{
|
{
|
||||||
state->part = p_body;
|
state->part = p_body;
|
||||||
if (state->bodytype == t_chunk) state->part = p_body_chunklen;
|
if (state->bodytype == t_chunk)
|
||||||
|
state->part = p_body_chunklen;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
memmove(state->data, lineend+1, dataend-(lineend+1));
|
memmove(state->data, lineend + 1, dataend-(lineend+1));
|
||||||
state->pos = (dataend-(lineend+1));
|
state->pos = (dataend-(lineend + 1));
|
||||||
}
|
}
|
||||||
if (state->part >= p_body)
|
if (state->part >= p_body)
|
||||||
{
|
{
|
||||||
@ -338,18 +413,24 @@ bool http_update(struct http* state, size_t* progress, size_t* total)
|
|||||||
state->pos = 0;
|
state->pos = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state->part >= p_body && state->part < p_done)
|
if (state->part >= p_body && state->part < p_done)
|
||||||
{
|
{
|
||||||
if (!newlen)
|
if (!newlen)
|
||||||
{
|
{
|
||||||
newlen=http_recv(state->fd, &state->error, (uint8_t*)state->data + state->pos, state->buflen - state->pos);
|
newlen = http_recv(state->fd, &state->error,
|
||||||
//newlen=http_recv(state->fd, &state->error, (uint8_t*)state->data + state->pos, 1);
|
(uint8_t*)state->data + state->pos,
|
||||||
if (newlen<0)
|
state->buflen - state->pos);
|
||||||
|
|
||||||
|
if (newlen < 0)
|
||||||
{
|
{
|
||||||
if (state->bodytype==t_full) state->part=p_done;
|
if (state->bodytype == t_full)
|
||||||
else goto fail;
|
state->part = p_done;
|
||||||
|
else
|
||||||
|
goto fail;
|
||||||
newlen=0;
|
newlen=0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state->pos + newlen >= state->buflen - 64)
|
if (state->pos + newlen >= state->buflen - 64)
|
||||||
{
|
{
|
||||||
state->buflen *= 2;
|
state->buflen *= 2;
|
||||||
@ -365,21 +446,32 @@ parse_again:
|
|||||||
state->pos += newlen;
|
state->pos += newlen;
|
||||||
if (state->pos - state->len >= 2)
|
if (state->pos - state->len >= 2)
|
||||||
{
|
{
|
||||||
//len=start of chunk including \r\n
|
/*
|
||||||
//pos=end of data
|
* len=start of chunk including \r\n
|
||||||
char * fullend = state->data + state->pos;
|
* pos=end of data
|
||||||
char * end = (char*)memchr(state->data + state->len + 2, '\n', state->pos - 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)
|
if (end)
|
||||||
{
|
{
|
||||||
size_t chunklen = strtoul(state->data+state->len, NULL, 16);
|
size_t chunklen = strtoul(state->data+state->len, NULL, 16);
|
||||||
state->pos = state->len;
|
state->pos = state->len;
|
||||||
end++;
|
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;
|
||||||
//len=num bytes
|
newlen = (fullend - end);
|
||||||
//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;
|
state->part = p_body;
|
||||||
if (state->len == 0)
|
if (state->len == 0)
|
||||||
{
|
{
|
||||||
@ -395,8 +487,8 @@ parse_again:
|
|||||||
if (newlen >= state->len)
|
if (newlen >= state->len)
|
||||||
{
|
{
|
||||||
state->pos += state->len;
|
state->pos += state->len;
|
||||||
newlen -= state->len;
|
newlen -= state->len;
|
||||||
state->len = state->pos;
|
state->len = state->pos;
|
||||||
state->part = p_body_chunklen;
|
state->part = p_body_chunklen;
|
||||||
goto parse_again;
|
goto parse_again;
|
||||||
}
|
}
|
||||||
@ -410,16 +502,23 @@ parse_again:
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
state->pos += newlen;
|
state->pos += newlen;
|
||||||
if (state->pos == state->len) state->part=p_done;
|
|
||||||
if (state->pos > state->len) goto fail;
|
if (state->pos == state->len)
|
||||||
|
state->part=p_done;
|
||||||
|
if (state->pos > state->len)
|
||||||
|
goto fail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (progress) *progress = state->pos;
|
if (progress)
|
||||||
|
*progress = state->pos;
|
||||||
|
|
||||||
if (total)
|
if (total)
|
||||||
{
|
{
|
||||||
if (state->bodytype == t_len) *total=state->len;
|
if (state->bodytype == t_len)
|
||||||
else *total=0;
|
*total=state->len;
|
||||||
|
else
|
||||||
|
*total=0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (state->part==p_done);
|
return (state->part==p_done);
|
||||||
@ -428,6 +527,7 @@ fail:
|
|||||||
state->error = true;
|
state->error = true;
|
||||||
state->part = p_error;
|
state->part = p_error;
|
||||||
state->status = -1;
|
state->status = -1;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -438,18 +538,25 @@ int http_status(struct http* state)
|
|||||||
|
|
||||||
uint8_t* http_data(struct http* state, size_t* len, bool accept_error)
|
uint8_t* http_data(struct http* state, size_t* len, bool accept_error)
|
||||||
{
|
{
|
||||||
if (!accept_error && (state->error || state->status<200 || state->status>299))
|
if (!accept_error &&
|
||||||
|
(state->error || state->status<200 || state->status>299))
|
||||||
{
|
{
|
||||||
if (len) *len=0;
|
if (len)
|
||||||
|
*len=0;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (len) *len=state->len;
|
|
||||||
|
if (len)
|
||||||
|
*len=state->len;
|
||||||
|
|
||||||
return (uint8_t*)state->data;
|
return (uint8_t*)state->data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void http_delete(struct http* state)
|
void http_delete(struct http* state)
|
||||||
{
|
{
|
||||||
if (state->fd != -1) close(state->fd);
|
if (state->fd != -1)
|
||||||
if (state->data) free(state->data);
|
close(state->fd);
|
||||||
|
if (state->data)
|
||||||
|
free(state->data);
|
||||||
free(state);
|
free(state);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user