diff --git a/changelog b/changelog
index c9bbfc6510a34f6a2d01ca977571d8827c446edc..96b265edaf67de0079642cc18bbd3382f2af8758 100644
--- a/changelog
+++ b/changelog
@@ -48,7 +48,7 @@ to user code.
 User api additions
 ------------------
 
-1) The info struct gained two new members
+1) The info struct gained three new members
 
  - max_http_header_data: 0 for default (1024) or set the maximum amount of known
     http header payload that lws can deal with.  Payload in unknown http
@@ -64,6 +64,9 @@ User api additions
      additional connects will fail until some of the pending connections timeout
      or complete.
 
+ - timeout_secs: 0 for default (currently 20s), or set the library's
+     network activity timeout to the given number of seconds
+
 HTTP header processing in lws only exists until just after the first main
 callback after the HTTP handshake... for ws connections that is ESTABLISHED and
 for HTTP connections the HTTP callback.
diff --git a/lib/client.c b/lib/client.c
index 28affab385d902d30eaf7e1b253372a88b2f42cc..2172645075f0f05ef7fcbe5eab1fdf2afdc56c43 100644
--- a/lib/client.c
+++ b/lib/client.c
@@ -353,7 +353,7 @@ some_wait:
 
 		wsi->mode = LWSCM_WSCL_ISSUE_HANDSHAKE2;
 		lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_CLIENT_HS_SEND,
-				AWAITING_TIMEOUT);
+				context->timeout_secs);
 
 		/* fallthru */
 
@@ -386,7 +386,7 @@ some_wait:
 		wsi->u.hdr.lextable_pos = 0;
 		wsi->mode = LWSCM_WSCL_WAITING_SERVER_REPLY;
 		lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_SERVER_RESPONSE,
-				AWAITING_TIMEOUT);
+				context->timeout_secs);
 		break;
 
 	case LWSCM_WSCL_WAITING_SERVER_REPLY:
diff --git a/lib/context.c b/lib/context.c
index 5aed178adcbb4bcf2bccae8a350db9d481554a9a..4ed0382960386ad30848f4ce1dbcddd361aaeea3 100644
--- a/lib/context.c
+++ b/lib/context.c
@@ -97,7 +97,6 @@ lws_create_context(struct lws_context_creation_info *info)
 	lwsl_info(" LWS_MAX_PROTOCOLS     : %u\n", LWS_MAX_PROTOCOLS);
 	lwsl_info(" LWS_MAX_SMP           : %u\n", LWS_MAX_SMP);
 	lwsl_info(" SPEC_LATEST_SUPPORTED : %u\n", SPEC_LATEST_SUPPORTED);
-	lwsl_info(" AWAITING_TIMEOUT      : %u\n", AWAITING_TIMEOUT);
 	lwsl_info(" sizeof (*info)        : %u\n", sizeof(*info));
 #if LWS_POSIX
 	lwsl_info(" SYSTEM_RANDOM_FILEPATH: '%s'\n", SYSTEM_RANDOM_FILEPATH);
@@ -136,6 +135,12 @@ lws_create_context(struct lws_context_creation_info *info)
 	context->ka_time = info->ka_time;
 	context->ka_interval = info->ka_interval;
 	context->ka_probes = info->ka_probes;
+	if (info->timeout_secs)
+		context->timeout_secs = info->timeout_secs;
+	else
+		context->timeout_secs = AWAITING_TIMEOUT;
+
+	lwsl_info(" default timeout (secs): %u\n", context->timeout_secs);
 
 	if (info->max_http_header_data)
 		context->max_http_header_data = info->max_http_header_data;
diff --git a/lib/handshake.c b/lib/handshake.c
index faa187e5ab778742aa878647cb020a35d885bc02..9bae6e45700a9ef75626787399b73467487373cf 100644
--- a/lib/handshake.c
+++ b/lib/handshake.c
@@ -167,7 +167,7 @@ http_postbody:
 
 			if (wsi->u.http.content_remain)  {
 				lws_set_timeout(wsi, PENDING_TIMEOUT_HTTP_CONTENT,
-						AWAITING_TIMEOUT);
+						wsi->context->timeout_secs);
 				break;
 			}
 			/* he sent all the content in time */
diff --git a/lib/libwebsockets.c b/lib/libwebsockets.c
index e8b847916cbd722b66dabdc2821c6ef8634e3032..d3c9154501429c1cea92b57fe246896bc0c8b45d 100644
--- a/lib/libwebsockets.c
+++ b/lib/libwebsockets.c
@@ -302,7 +302,7 @@ just_kill_connection:
 		wsi->state = LWSS_SHUTDOWN;
 		lws_change_pollfd(wsi, LWS_POLLOUT, LWS_POLLIN);
 		lws_set_timeout(wsi, PENDING_TIMEOUT_SHUTDOWN_FLUSH,
-				AWAITING_TIMEOUT);
+				context->timeout_secs);
 		return;
 	}
 #endif
diff --git a/lib/libwebsockets.h b/lib/libwebsockets.h
index 86c56b99136821e9c41029b712816587d1aae8ab..0c0b3f3b7aa0b718c87581604ed9d9b3461c00ff 100644
--- a/lib/libwebsockets.h
+++ b/lib/libwebsockets.h
@@ -1315,7 +1315,10 @@ extern int lws_extension_callback_pm_deflate(
  * @fd_limit_per_thread: nonzero means restrict each service thread to this
  *		many fds, 0 means the default which is divide the process fd
  *		limit by the number of threads.
- *
+ * @timeout_secs: various processes involving network roundtrips in the
+ *		library are protected from hanging forever by timeouts.  If
+ *		nonzero, this member lets you set the timeout used in seconds.
+ *		Otherwise a default timeout is used.
  */
 
 struct lws_context_creation_info {
@@ -1349,6 +1352,7 @@ struct lws_context_creation_info {
 
 	unsigned int count_threads;
 	unsigned int fd_limit_per_thread;
+	unsigned int timeout_secs;
 
 	/* Add new things just above here ---^
 	 * This is part of the ABI, don't needlessly break compatibility
diff --git a/lib/output.c b/lib/output.c
index b389ace41a985d23e06f728a0d5ba3e8f94b11e1..0d850ebe8e64c615799ed229f1fc6d6b6bbee8a6 100644
--- a/lib/output.c
+++ b/lib/output.c
@@ -575,7 +575,7 @@ LWS_VISIBLE int lws_serve_http_file_fragment(struct lws *wsi)
 		n = (int)amount;
 		if (n) {
 			lws_set_timeout(wsi, PENDING_TIMEOUT_HTTP_CONTENT,
-					AWAITING_TIMEOUT);
+					context->timeout_secs);
 			wsi->u.http.filepos += n;
 			m = lws_write(wsi, pt->serv_buf, n,
 				      wsi->u.http.filepos == wsi->u.http.filelen ?
diff --git a/lib/private-libwebsockets.h b/lib/private-libwebsockets.h
index 09d140f5c7b6fa62df28eb8b1b00e201e6cd930b..cd4cd80ba3f570fc6292e32c4e1cb9a71e6da17e 100644
--- a/lib/private-libwebsockets.h
+++ b/lib/private-libwebsockets.h
@@ -632,6 +632,7 @@ struct lws_context {
 	unsigned int http_proxy_port;
 	unsigned int options;
 	unsigned int fd_limit_per_thread;
+	unsigned int timeout_secs;
 
 	/*
 	 * set to the Thread ID that's doing the service loop just before entry
diff --git a/lib/server.c b/lib/server.c
index 7bd0f042cdc7ae62f4e78bfd1c4dad1c7bde8170..d412b7d09bed9c9c5cca03881b1031873e5633e5 100644
--- a/lib/server.c
+++ b/lib/server.c
@@ -302,7 +302,7 @@ lws_http_action(struct lws *wsi)
 	 * put a timeout on it having arrived
 	 */
 	lws_set_timeout(wsi, PENDING_TIMEOUT_HTTP_CONTENT,
-			AWAITING_TIMEOUT);
+			wsi->context->timeout_secs);
 
 	n = wsi->protocol->callback(wsi, LWS_CALLBACK_HTTP,
 				    wsi->user_space, uri_ptr, uri_len);
@@ -780,7 +780,7 @@ lws_adopt_socket(struct lws_context *context, lws_sockfd_type accept_fd)
 
 	/* the transport is accepted... give him time to negotiate */
 	lws_set_timeout(new_wsi, PENDING_TIMEOUT_ESTABLISH_WITH_SERVER,
-			AWAITING_TIMEOUT);
+			context->timeout_secs);
 
 #if LWS_POSIX == 0
 	mbed3_tcp_stream_accept(accept_fd, new_wsi);
diff --git a/lib/ssl.c b/lib/ssl.c
index 0f15d7d72f2e5c6c5352c526831344498d83192d..4b2b2fbe0da475ae71498f4ee1358460bee2ff0e 100644
--- a/lib/ssl.c
+++ b/lib/ssl.c
@@ -653,7 +653,7 @@ lws_server_socket_service_ssl(struct lws *wsi, lws_sockfd_type accept_fd)
 			goto fail;
 
 		lws_set_timeout(wsi, PENDING_TIMEOUT_SSL_ACCEPT,
-							AWAITING_TIMEOUT);
+				context->timeout_secs);
 
 		lwsl_info("inserted SSL accept into fds, trying SSL_accept\n");
 
@@ -746,7 +746,7 @@ go_again:
 accepted:
 		/* OK, we are accepted... give him some time to negotiate */
 		lws_set_timeout(wsi, PENDING_TIMEOUT_ESTABLISH_WITH_SERVER,
-				AWAITING_TIMEOUT);
+				context->timeout_secs);
 
 		wsi->mode = LWSCM_HTTP_SERVING;