diff mbox

[OpenWrt-Devel,uclient] support for connection timeout

Message ID 1421336450-10781-1-git-send-email-zajec5@gmail.com
State Changes Requested
Headers show

Commit Message

Rafał Miłecki Jan. 15, 2015, 3:40 p.m. UTC
Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
---
 uclient-fetch.c |  4 ++++
 uclient.c       | 25 ++++++++++++++++++++++++-
 uclient.h       |  4 ++++
 3 files changed, 32 insertions(+), 1 deletion(-)

Comments

Felix Fietkau Jan. 15, 2015, 6:16 p.m. UTC | #1
On 2015-01-15 16:40, Rafał Miłecki wrote:
> Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
> ---
>  uclient-fetch.c |  4 ++++
>  uclient.c       | 25 ++++++++++++++++++++++++-
>  uclient.h       |  4 ++++
>  3 files changed, 32 insertions(+), 1 deletion(-)
> 
> diff --git a/uclient.c b/uclient.c
> index ab2d5b6..a405179 100644
> --- a/uclient.c
> +++ b/uclient.c
> @@ -207,12 +207,31 @@ int uclient_write(struct uclient *cl, char *buf, int len)
>  	return cl->backend->write(cl, buf, len);
>  }
>  
> +static void uclient_request_timeout(struct uloop_timeout *timeout)
> +{
> +	struct uclient *cl = container_of(timeout, struct uclient, request_timeout);
> +
> +	if (cl->backend->disconnect)
> +		cl->backend->disconnect(cl);
> +
> +	uclient_backend_set_error(cl, UCLIENT_ERROR_TIMEDOUT);
> +}
> +
>  int uclient_request(struct uclient *cl)
>  {
> +	int err;
> +
>  	if (!cl->backend->request)
>  		return -1;
>  
> -	return cl->backend->request(cl);
> +	err = cl->backend->request(cl);
> +	if (err)
> +		return err;
> +
> +	cl->request_timeout.cb = uclient_request_timeout;
> +	uloop_timeout_set(&cl->request_timeout, UCLIENT_DEFAULT_CONNECTION_TIMEOUT_MS);
Please store the timeout value in struct uclient and initialize it at
alloc time. I don't like forced hardcoded values.

> +
> +	return 0;
>  }
>  
>  int uclient_read(struct uclient *cl, char *buf, int len)
> @@ -225,6 +244,8 @@ int uclient_read(struct uclient *cl, char *buf, int len)
>  
>  void uclient_disconnect(struct uclient *cl)
>  {
> +	uloop_timeout_cancel(&cl->request_timeout);
> +
>  	if (!cl->backend->disconnect)
>  		return;
>  
> @@ -243,6 +264,8 @@ static void __uclient_backend_change_state(struct uloop_timeout *timeout)
>  
>  static void uclient_backend_change_state(struct uclient *cl)
>  {
> +	uloop_timeout_cancel(&cl->request_timeout);
> +
>  	cl->timeout.cb = __uclient_backend_change_state;
>  	uloop_timeout_set(&cl->timeout, 1);
>  }
The timeout should be cancelled or refreshed when the HTTP response is
received, and on new incoming data. It should probably be cancelled if
the receive buffer is full (since the data reception is throttled by the
user).

- Felix
diff mbox

Patch

diff --git a/uclient-fetch.c b/uclient-fetch.c
index 22f15c6..0617a02 100644
--- a/uclient-fetch.c
+++ b/uclient-fetch.c
@@ -194,6 +194,10 @@  static void handle_uclient_error(struct uclient *cl, int code)
 		type = "Connection failed";
 		error_ret = 4;
 		break;
+	case UCLIENT_ERROR_TIMEDOUT:
+		type = "Connection timed out";
+		error_ret = 4;
+		break;
 	case UCLIENT_ERROR_SSL_INVALID_CERT:
 		type = "Invalid SSL certificate";
 		ignore = !verify;
diff --git a/uclient.c b/uclient.c
index ab2d5b6..a405179 100644
--- a/uclient.c
+++ b/uclient.c
@@ -207,12 +207,31 @@  int uclient_write(struct uclient *cl, char *buf, int len)
 	return cl->backend->write(cl, buf, len);
 }
 
+static void uclient_request_timeout(struct uloop_timeout *timeout)
+{
+	struct uclient *cl = container_of(timeout, struct uclient, request_timeout);
+
+	if (cl->backend->disconnect)
+		cl->backend->disconnect(cl);
+
+	uclient_backend_set_error(cl, UCLIENT_ERROR_TIMEDOUT);
+}
+
 int uclient_request(struct uclient *cl)
 {
+	int err;
+
 	if (!cl->backend->request)
 		return -1;
 
-	return cl->backend->request(cl);
+	err = cl->backend->request(cl);
+	if (err)
+		return err;
+
+	cl->request_timeout.cb = uclient_request_timeout;
+	uloop_timeout_set(&cl->request_timeout, UCLIENT_DEFAULT_CONNECTION_TIMEOUT_MS);
+
+	return 0;
 }
 
 int uclient_read(struct uclient *cl, char *buf, int len)
@@ -225,6 +244,8 @@  int uclient_read(struct uclient *cl, char *buf, int len)
 
 void uclient_disconnect(struct uclient *cl)
 {
+	uloop_timeout_cancel(&cl->request_timeout);
+
 	if (!cl->backend->disconnect)
 		return;
 
@@ -243,6 +264,8 @@  static void __uclient_backend_change_state(struct uloop_timeout *timeout)
 
 static void uclient_backend_change_state(struct uclient *cl)
 {
+	uloop_timeout_cancel(&cl->request_timeout);
+
 	cl->timeout.cb = __uclient_backend_change_state;
 	uloop_timeout_set(&cl->timeout, 1);
 }
diff --git a/uclient.h b/uclient.h
index d5a0d5b..095d894 100644
--- a/uclient.h
+++ b/uclient.h
@@ -24,12 +24,15 @@ 
 #include <libubox/ustream.h>
 #include <libubox/ustream-ssl.h>
 
+#define UCLIENT_DEFAULT_CONNECTION_TIMEOUT_MS		30000
+
 struct uclient_cb;
 struct uclient_backend;
 
 enum uclient_error_code {
 	UCLIENT_ERROR_UNKNOWN,
 	UCLIENT_ERROR_CONNECT,
+	UCLIENT_ERROR_TIMEDOUT,
 	UCLIENT_ERROR_SSL_INVALID_CERT,
 	UCLIENT_ERROR_SSL_CN_MISMATCH,
 	UCLIENT_ERROR_MISSING_SSL_CONTEXT,
@@ -67,6 +70,7 @@  struct uclient {
 	int status_code;
 	struct blob_attr *meta;
 
+	struct uloop_timeout request_timeout;
 	struct uloop_timeout timeout;
 };