X-Git-Url: http://git.archive.openwrt.org/?a=blobdiff_plain;f=uclient-http.c;h=ac9d50f4b2ad914590bf6517f4fe90b181f7425a;hb=a4e49b4163b28b2d12e718e66c4fcba87acef33e;hp=e58cf274b3a6cef5b06929462c7638f3d648afa1;hpb=07b4860975bd919fc8a8ce75d14ca8216eab70aa;p=project%2Fuclient.git diff --git a/uclient-http.c b/uclient-http.c index e58cf27..ac9d50f 100644 --- a/uclient-http.c +++ b/uclient-http.c @@ -15,6 +15,7 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include #include #include #include @@ -90,6 +91,8 @@ struct uclient_http { long read_chunked; long content_length; + int usock_flags; + uint32_t nc; struct blob_buf headers; @@ -120,7 +123,9 @@ static int uclient_do_connect(struct uclient_http *uh, const char *port) memset(&uh->uc.remote_addr, 0, sizeof(uh->uc.remote_addr)); - fd = usock_inet(USOCK_TCP, uh->uc.url->host, port, &uh->uc.remote_addr); + fd = usock_inet_timeout(USOCK_TCP | USOCK_NONBLOCK | uh->usock_flags, + uh->uc.url->host, port, &uh->uc.remote_addr, + uh->uc.timeout_msecs); if (fd < 0) return -1; @@ -192,6 +197,9 @@ static void uclient_notify_eof(struct uclient_http *uh) return; } + if (uh->content_length < 0 && uh->read_chunked >= 0) + uh->uc.data_eof = true; + uclient_backend_set_eof(&uh->uc); if (uh->connection_close) @@ -278,6 +286,18 @@ static void uclient_http_process_headers(struct uclient_http *uh) uh->auth_type = uclient_http_update_auth_type(uh); } +static bool uclient_request_supports_body(enum request_type req_type) +{ + switch (req_type) { + case REQ_POST: + case REQ_PUT: + case REQ_DELETE: + return true; + default: + return false; + } +} + static void uclient_http_add_auth_basic(struct uclient_http *uh) { @@ -359,11 +379,14 @@ get_cnonce(char *dest) { uint32_t val = 0; FILE *f; + size_t n; f = fopen("/dev/urandom", "r"); if (f) { - fread(&val, sizeof(val), 1, f); + n = fread(&val, sizeof(val), 1, f); fclose(f); + if (n != 1) + return; } bin_to_hex(dest, &val, sizeof(val)); @@ -549,14 +572,16 @@ uclient_http_send_headers(struct uclient_http *uh) ustream_printf(uh->us, "%s %s HTTP/1.1\r\n" - "Host: %s\r\n", + "Host: %s%s%s\r\n", request_types[req_type], - url->location, url->host); + url->location, url->host, + url->port ? ":" : "", + url->port ? url->port : ""); blobmsg_for_each_attr(cur, uh->headers.head, rem) ustream_printf(uh->us, "%s: %s\r\n", blobmsg_name(cur), (char *) blobmsg_data(cur)); - if (uh->req_type == REQ_POST || uh->req_type == REQ_PUT) + if (uclient_request_supports_body(uh->req_type)) ustream_printf(uh->us, "Transfer-Encoding: chunked\r\n"); uclient_http_add_auth_header(uh); @@ -984,7 +1009,7 @@ uclient_http_request_done(struct uclient *cl) return -1; uclient_http_send_headers(uh); - if (uh->req_type == REQ_POST || uh->req_type == REQ_PUT) + if (uclient_request_supports_body(uh->req_type)) ustream_printf(uh->us, "0\r\n\r\n"); uh->state = HTTP_STATE_REQUEST_DONE; @@ -1094,7 +1119,7 @@ int uclient_http_redirect(struct uclient *cl) if (!tb) return false; - url = uclient_get_url(blobmsg_data(tb), url->auth); + url = uclient_get_url_location(url, blobmsg_data(tb)); if (!url) return false; @@ -1126,6 +1151,28 @@ int uclient_http_set_ssl_ctx(struct uclient *cl, const struct ustream_ssl_ops *o return 0; } +int uclient_http_set_address_family(struct uclient *cl, int af) +{ + struct uclient_http *uh = container_of(cl, struct uclient_http, uc); + + if (cl->backend != &uclient_backend_http) + return -1; + + switch (af) { + case AF_INET: + uh->usock_flags = USOCK_IPV4ONLY; + break; + case AF_INET6: + uh->usock_flags = USOCK_IPV6ONLY; + break; + default: + uh->usock_flags = 0; + break; + } + + return 0; +} + const struct uclient_backend uclient_backend_http = { .prefix = uclient_http_prefix,