fetch: print the URL while connecting
[project/uclient.git] / uclient-http.c
index e7d3ff0..9652fb8 100644 (file)
@@ -40,6 +40,7 @@ enum request_type {
        REQ_GET,
        REQ_HEAD,
        REQ_POST,
+       REQ_PUT,
        __REQ_MAX
 };
 
@@ -56,6 +57,7 @@ static const char * const request_types[__REQ_MAX] = {
        [REQ_GET] = "GET",
        [REQ_HEAD] = "HEAD",
        [REQ_POST] = "POST",
+       [REQ_PUT] = "PUT",
 };
 
 struct uclient_http {
@@ -68,10 +70,13 @@ struct uclient_http {
        struct ustream_fd ufd;
        struct ustream_ssl ussl;
 
+       struct uloop_timeout disconnect_t;
+
        bool ssl_require_validation;
        bool ssl;
        bool eof;
        bool connection_close;
+       bool disconnect;
        enum request_type req_type;
        enum http_state state;
 
@@ -125,6 +130,7 @@ static int uclient_do_connect(struct uclient_http *uh, const char *port)
 
 static void uclient_http_disconnect(struct uclient_http *uh)
 {
+       uloop_timeout_cancel(&uh->disconnect_t);
        if (!uh->us)
                return;
 
@@ -157,6 +163,9 @@ static void uclient_notify_eof(struct uclient_http *uh)
 {
        struct ustream *us = uh->us;
 
+       if (uh->disconnect)
+               return;
+
        if (!uh->eof) {
                if (!us->eof && !us->write_error)
                        return;
@@ -177,6 +186,7 @@ static void uclient_http_reset_state(struct uclient_http *uh)
        uh->read_chunked = -1;
        uh->content_length = -1;
        uh->eof = false;
+       uh->disconnect = false;
        uh->connection_close = false;
        uh->state = HTTP_STATE_INIT;
 
@@ -499,7 +509,7 @@ uclient_http_send_headers(struct uclient_http *uh)
        blobmsg_for_each_attr(cur, uh->headers.head, rem)
                ustream_printf(uh->us, "%s: %s\n", blobmsg_name(cur), (char *) blobmsg_data(cur));
 
-       if (uh->req_type == REQ_POST)
+       if (uh->req_type == REQ_POST || uh->req_type == REQ_PUT)
                ustream_printf(uh->us, "Transfer-Encoding: chunked\r\n");
 
        uclient_http_add_auth_header(uh);
@@ -527,6 +537,9 @@ static void uclient_http_headers_complete(struct uclient_http *uh)
        if (uh->uc.cb->header_done)
                uh->uc.cb->header_done(&uh->uc);
 
+       if (uh->eof)
+               return;
+
        if (uh->req_type == REQ_HEAD || uh->uc.status_code == 204) {
                uh->eof = true;
                uclient_notify_eof(uh);
@@ -623,6 +636,9 @@ static void __uclient_notify_read(struct uclient_http *uh)
                        ustream_consume(uh->us, cur_len);
                        len -= cur_len;
 
+                       if (uh->eof)
+                               return;
+
                        data = ustream_get_read_buf(uh->us, &len);
                } while (data && uh->state < HTTP_STATE_RECV_DATA);
 
@@ -630,6 +646,9 @@ static void __uclient_notify_read(struct uclient_http *uh)
                        return;
        }
 
+       if (uh->eof)
+               return;
+
        if (uh->state == HTTP_STATE_RECV_DATA && uc->cb->data_read)
                uc->cb->data_read(uc);
 }
@@ -756,11 +775,19 @@ static int uclient_http_connect(struct uclient *cl)
        return ret;
 }
 
+static void uclient_http_disconnect_cb(struct uloop_timeout *timeout)
+{
+       struct uclient_http *uh = container_of(timeout, struct uclient_http, disconnect_t);
+
+       uclient_http_disconnect(uh);
+}
+
 static struct uclient *uclient_http_alloc(void)
 {
        struct uclient_http *uh;
 
        uh = calloc_a(sizeof(*uh));
+       uh->disconnect_t.cb = uclient_http_disconnect_cb;
        blob_buf_init(&uh->headers, 0);
 
        return &uh->uc;
@@ -859,7 +886,7 @@ uclient_http_request_done(struct uclient *cl)
                return -1;
 
        uclient_http_send_headers(uh);
-       if (uh->req_type == REQ_POST)
+       if (uh->req_type == REQ_POST || uh->req_type == REQ_PUT)
                ustream_printf(uh->us, "0\r\n\r\n");
        uh->state = HTTP_STATE_REQUEST_DONE;
 
@@ -901,8 +928,10 @@ uclient_http_read(struct uclient *cl, char *buf, unsigned int len)
                read_len += sep + 2 - data;
                data = sep + 2;
 
-               if (!uh->read_chunked)
+               if (!uh->read_chunked) {
                        uh->eof = true;
+                       uh->uc.data_eof = true;
+               }
        }
 
        if (len > data_end - data)
@@ -918,8 +947,10 @@ uclient_http_read(struct uclient *cl, char *buf, unsigned int len)
                        len = uh->content_length;
 
                uh->content_length -= len;
-               if (!uh->content_length)
+               if (!uh->content_length) {
                        uh->eof = true;
+                       uh->uc.data_eof = true;
+               }
        }
 
        if (len > 0) {
@@ -991,12 +1022,25 @@ int uclient_http_set_ssl_ctx(struct uclient *cl, const struct ustream_ssl_ops *o
        return 0;
 }
 
+static void uclient_http_request_disconnect(struct uclient *cl)
+{
+       struct uclient_http *uh = container_of(cl, struct uclient_http, uc);
+
+       if (!uh->us)
+               return;
+
+       uh->eof = true;
+       uh->disconnect = true;
+       uloop_timeout_set(&uh->disconnect_t, 1);
+}
+
 const struct uclient_backend uclient_backend_http = {
        .prefix = uclient_http_prefix,
 
        .alloc = uclient_http_alloc,
        .free = uclient_http_free,
        .connect = uclient_http_connect,
+       .disconnect = uclient_http_request_disconnect,
        .update_url = uclient_http_free_url_state,
 
        .read = uclient_http_read,