ucode: add support for using a prototype for cb, pass it to callbacks
[project/uclient.git] / uclient-http.c
index 3168f4c6a58aa372c70587318e5cd80aa4f9c492..d6e9dcfd542e8584d97e2e4cf0050fb399121984 100644 (file)
@@ -199,7 +199,8 @@ static void uclient_notify_eof(struct uclient_http *uh)
                        return;
        }
 
-       if (uh->content_length < 0 && uh->read_chunked >= 0)
+       if ((uh->content_length < 0 && uh->read_chunked >= 0) ||
+                       uh->content_length == 0)
                uh->uc.data_eof = true;
 
        uclient_backend_set_eof(&uh->uc);
@@ -440,7 +441,7 @@ uclient_http_add_auth_digest(struct uclient_http *uh)
        struct uclient_url *url = uh->uc.url;
        const char *realm = NULL, *opaque = NULL;
        const char *user, *password;
-       char *buf, *next, *buf_orig;
+       char *buf, *next;
        int len, ofs;
        int err = 0;
 
@@ -470,7 +471,7 @@ uclient_http_add_auth_digest(struct uclient_http *uh)
        strcpy(buf, uh->auth_str);
 
        /* skip auth type */
-       buf_orig = strsep(&buf, " ");
+       strsep(&buf, " ");
 
        next = buf;
        while (*next) {
@@ -506,7 +507,7 @@ uclient_http_add_auth_digest(struct uclient_http *uh)
 
        if (!realm || !data.qop || !data.nonce) {
                err = -EINVAL;
-               goto fail_buf;
+               goto fail;
        }
 
        sprintf(nc_str, "%08x", uh->nc++);
@@ -523,13 +524,13 @@ uclient_http_add_auth_digest(struct uclient_http *uh)
                len = password - url->auth;
                if (len > 256) {
                        err = -EINVAL;
-                       goto fail_buf;
+                       goto fail;
                }
 
                user_buf = alloca(len + 1);
                if (!user_buf) {
                        err = -ENOMEM;
-                       goto fail_buf;
+                       goto fail;
                }
 
                strncpy(user_buf, url->auth, len);
@@ -563,8 +564,6 @@ uclient_http_add_auth_digest(struct uclient_http *uh)
 
        return 0;
 
-fail_buf:
-       free(buf_orig);
 fail:
        return err;
 }
@@ -595,7 +594,8 @@ uclient_http_send_headers(struct uclient_http *uh)
        struct blob_attr *cur;
        enum request_type req_type = uh->req_type;
        bool literal_ipv6;
-       int err, rem;
+       int err;
+       size_t rem;
 
        if (uh->state >= HTTP_STATE_HEADERS_SENT)
                return 0;
@@ -655,7 +655,8 @@ static void uclient_http_headers_complete(struct uclient_http *uh)
        if (uh->eof || seq != uh->uc.seq)
                return;
 
-       if (uh->req_type == REQ_HEAD || uh->uc.status_code == 204) {
+       if (uh->req_type == REQ_HEAD || uh->uc.status_code == 204 ||
+                       uh->content_length == 0) {
                uh->eof = true;
                uclient_notify_eof(uh);
        }
@@ -779,9 +780,7 @@ static void __uclient_notify_read(struct uclient_http *uh)
        if (uh->state == HTTP_STATE_RECV_DATA) {
                /* Now it's uclient user turn to read some data */
                uloop_timeout_cancel(&uc->connection_timeout);
-
-               if (uc->cb->data_read)
-                       uc->cb->data_read(uc);
+               uclient_backend_read_notify(uc);
        }
 }
 
@@ -981,7 +980,7 @@ int
 uclient_http_set_request_type(struct uclient *cl, const char *type)
 {
        struct uclient_http *uh = container_of(cl, struct uclient_http, uc);
-       int i;
+       unsigned int i;
 
        if (cl->backend != &uclient_backend_http)
                return -1;
@@ -1078,8 +1077,12 @@ uclient_http_read(struct uclient *cl, char *buf, unsigned int len)
                return 0;
 
        data = ustream_get_read_buf(uh->us, &read_len);
-       if (!data || !read_len)
-               return 0;
+       if (!data || !read_len) {
+               ustream_poll(uh->us);
+               data = ustream_get_read_buf(uh->us, &read_len);
+               if (!data || !read_len)
+                       return 0;
+       }
 
        data_end = data + read_len;
        read_len = 0;
@@ -1108,16 +1111,17 @@ uclient_http_read(struct uclient *cl, char *buf, unsigned int len)
                }
        }
 
-       if (len > data_end - data)
-               len = data_end - data;
+       unsigned int diff = data_end - data;
+       if (len > diff)
+               len = diff;
 
        if (uh->read_chunked >= 0) {
-               if (len > uh->read_chunked)
+               if (len > (unsigned long) uh->read_chunked)
                        len = uh->read_chunked;
 
                uh->read_chunked -= len;
        } else if (uh->content_length >= 0) {
-               if (len > uh->content_length)
+               if (len > (unsigned long) uh->content_length)
                        len = uh->content_length;
 
                uh->content_length -= len;
@@ -1157,14 +1161,8 @@ int uclient_http_redirect(struct uclient *cl)
        if (cl->backend != &uclient_backend_http)
                return false;
 
-       switch (cl->status_code) {
-       case 301:
-       case 302:
-       case 307:
-               break;
-       default:
+       if (!uclient_http_status_redirect(cl))
                return false;
-       }
 
        blobmsg_parse(&location, 1, &tb, blob_data(uh->meta.head), blob_len(uh->meta.head));
        if (!tb)
@@ -1231,6 +1229,14 @@ int uclient_http_set_address_family(struct uclient *cl, int af)
        return 0;
 }
 
+static int
+uclient_http_pending_bytes(struct uclient *cl, bool write)
+{
+       struct uclient_http *uh = container_of(cl, struct uclient_http, uc);
+
+       return ustream_pending_data(uh->us, write);
+}
+
 const struct uclient_backend uclient_backend_http = {
        .prefix = uclient_http_prefix,
 
@@ -1244,4 +1250,5 @@ const struct uclient_backend uclient_backend_http = {
        .read = uclient_http_read,
        .write = uclient_http_send_data,
        .request = uclient_http_request_done,
+       .pending_bytes = uclient_http_pending_bytes,
 };