add uclient_disconnect() to force a disconnect without further callbacks
authorFelix Fietkau <nbd@openwrt.org>
Sun, 4 May 2014 17:54:22 +0000 (19:54 +0200)
committerFelix Fietkau <nbd@openwrt.org>
Sun, 4 May 2014 17:55:13 +0000 (19:55 +0200)
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
uclient-backend.h
uclient-http.c
uclient.c
uclient.h

index 4cba048f6965c872d3e070d8a108a99f292dc929..a5cf4f3d392ab9fd5fa2a6510d49c0f6bcfb355b 100644 (file)
@@ -29,6 +29,7 @@ struct uclient_backend {
 
        int (*connect)(struct uclient *cl);
        int (*request)(struct uclient *cl);
+       void (*disconnect)(struct uclient *cl);
 
        int (*read)(struct uclient *cl, char *buf, unsigned int len);
        int (*write)(struct uclient *cl, char *buf, unsigned int len);
index e7d3ff0e1d175ae85bc63d4074a0e1160a330cf4..16ffe9660cd55a0cd50af94565e0aa5dd55aa92b 100644 (file)
@@ -68,10 +68,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 +128,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 +161,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 +184,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;
 
@@ -527,6 +535,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 +634,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 +644,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 +773,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;
@@ -991,12 +1016,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,
index bcb7357c40d41ec1c3258951cc7ba6eae8bb0b0f..fb450699654e86ef370575c03cf12192429bc348 100644 (file)
--- a/uclient.c
+++ b/uclient.c
@@ -223,6 +223,14 @@ int uclient_read(struct uclient *cl, char *buf, int len)
        return cl->backend->read(cl, buf, len);
 }
 
+void uclient_disconnect(struct uclient *cl)
+{
+       if (!cl->backend->disconnect)
+               return;
+
+       cl->backend->disconnect(cl);
+}
+
 static void __uclient_backend_change_state(struct uloop_timeout *timeout)
 {
        struct uclient *cl = container_of(timeout, struct uclient, timeout);
index fcd7769e711bb4d1a23b4a72a7d676e01ce2e506..ddc8b7845f9baaaee13ab766c93db706b191ff33 100644 (file)
--- a/uclient.h
+++ b/uclient.h
@@ -82,6 +82,7 @@ void uclient_free(struct uclient *cl);
 
 int uclient_set_url(struct uclient *cl, const char *url, const char *auth);
 int uclient_connect(struct uclient *cl);
+void uclient_disconnect(struct uclient *cl);
 
 int uclient_read(struct uclient *cl, char *buf, int len);
 int uclient_write(struct uclient *cl, char *buf, int len);