From 29c798a52907b7ee28c8e001c99ceed65ebe5d39 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sun, 4 May 2014 19:54:22 +0200 Subject: [PATCH] add uclient_disconnect() to force a disconnect without further callbacks Signed-off-by: Felix Fietkau --- uclient-backend.h | 1 + uclient-http.c | 38 ++++++++++++++++++++++++++++++++++++++ uclient.c | 8 ++++++++ uclient.h | 1 + 4 files changed, 48 insertions(+) diff --git a/uclient-backend.h b/uclient-backend.h index 4cba048..a5cf4f3 100644 --- a/uclient-backend.h +++ b/uclient-backend.h @@ -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); diff --git a/uclient-http.c b/uclient-http.c index e7d3ff0..16ffe96 100644 --- a/uclient-http.c +++ b/uclient-http.c @@ -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, diff --git a/uclient.c b/uclient.c index bcb7357..fb45069 100644 --- 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); diff --git a/uclient.h b/uclient.h index fcd7769..ddc8b78 100644 --- 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); -- 2.11.0