X-Git-Url: http://git.archive.openwrt.org/?p=project%2Fuclient.git;a=blobdiff_plain;f=uclient-http.c;h=1cc60e3051880303b9622ddacaa6275593463a29;hp=c344513d8c7c4722e1a34f3f03e6d016a4eb0f8a;hb=5e0b24f3a921081162706598d1ebea9d403d3187;hpb=6ee437e845ad57a8f86dc4f3fbbaddfd487de059 diff --git a/uclient-http.c b/uclient-http.c index c344513..1cc60e3 100644 --- a/uclient-http.c +++ b/uclient-http.c @@ -12,9 +12,6 @@ #include "uclient-utils.h" #include "uclient-backend.h" -static struct ustream_ssl_ctx *ssl_ctx; -static uint32_t nc; - enum auth_type { AUTH_TYPE_UNKNOWN, AUTH_TYPE_NONE, @@ -47,6 +44,7 @@ static const char * const request_types[__REQ_MAX] = { struct uclient_http { struct uclient uc; + struct ustream_ssl_ctx *ssl_ctx; struct ustream *us; struct ustream_fd ufd; @@ -64,6 +62,8 @@ struct uclient_http { long read_chunked; long content_length; + uint32_t nc; + struct blob_buf headers; struct blob_buf meta; }; @@ -275,7 +275,7 @@ static bool strmatch(char **str, const char *prefix) static void get_cnonce(char *dest) { - uint32_t val = nc; + uint32_t val = 0; FILE *f; f = fopen("/dev/urandom", "r"); @@ -376,7 +376,7 @@ uclient_http_add_auth_digest(struct uclient_http *uh) if (!realm || !data.qop || !data.nonce) return; - sprintf(nc_str, "%08x", nc++); + sprintf(nc_str, "%08x", uh->nc++); get_cnonce(cnonce_str); data.qop = "auth"; @@ -501,6 +501,19 @@ static void uclient_parse_http_line(struct uclient_http *uh, char *data) char *sep; if (uh->state == HTTP_STATE_REQUEST_DONE) { + char *code; + + /* HTTP/1.1 */ + strsep(&data, " "); + + code = strsep(&data, " "); + if (!code) + goto error; + + uh->uc.status_code = strtoul(code, &sep, 10); + if (sep && *sep) + goto error; + uh->state = HTTP_STATE_RECV_HEADERS; return; } @@ -524,6 +537,12 @@ static void uclient_parse_http_line(struct uclient_http *uh, char *data) sep++; blobmsg_add_string(&uh->meta, name, sep); + return; + +error: + uh->uc.status_code = 400; + uh->eof = true; + uclient_notify_eof(uh); } static void __uclient_notify_read(struct uclient_http *uh) @@ -634,13 +653,13 @@ static int uclient_setup_https(struct uclient_http *uh) if (ret) return ret; - if (!ssl_ctx) - ssl_ctx = ustream_ssl_context_new(false); + if (!uh->ssl_ctx) + uh->ssl_ctx = ustream_ssl_context_new(false); us->string_data = true; us->notify_state = uclient_ssl_notify_state; us->notify_read = uclient_ssl_notify_read; - ustream_ssl_init(&uh->ussl, &uh->ufd.stream, ssl_ctx, false); + ustream_ssl_init(&uh->ussl, &uh->ufd.stream, uh->ssl_ctx, false); return 0; } @@ -676,6 +695,9 @@ static void uclient_http_free(struct uclient *cl) { struct uclient_http *uh = container_of(cl, struct uclient_http, uc); + if (uh->ssl_ctx) + ustream_ssl_context_free(uh->ssl_ctx); + uclient_http_free_url_state(cl); blob_buf_free(&uh->headers); blob_buf_free(&uh->meta); @@ -831,7 +853,45 @@ uclient_http_read(struct uclient *cl, char *buf, unsigned int len) return len; } -const struct uclient_backend uclient_backend_http __hidden = { +bool uclient_http_redirect(struct uclient *cl) +{ + struct uclient_http *uh = container_of(cl, struct uclient_http, uc); + struct blobmsg_policy location = { + .name = "location", + .type = BLOBMSG_TYPE_STRING, + }; + struct uclient_url *url = cl->url; + struct blob_attr *tb; + + if (cl->backend != &uclient_backend_http) + return false; + + switch (cl->status_code) { + case 301: + case 302: + case 307: + break; + default: + return false; + } + + blobmsg_parse(&location, 1, &tb, blob_data(uh->meta.head), blob_len(uh->meta.head)); + if (!tb) + return false; + + url = uclient_get_url(blobmsg_data(tb), url->auth); + if (!url) + return false; + + free(cl->url); + cl->url = url; + uclient_http_connect(cl); + uclient_http_request_done(cl); + + return true; +} + +const struct uclient_backend uclient_backend_http = { .prefix = uclient_http_prefix, .alloc = uclient_http_alloc,