clean--fix-sigpipe.patch

Signed-off-by: Andy Green <andy@warmcat.com>
diff --git a/lib/client-handshake.c b/lib/client-handshake.c
index 1ef80f4..64f72cb 100644
--- a/lib/client-handshake.c
+++ b/lib/client-handshake.c
@@ -89,13 +89,13 @@
 					 "61AC5F19-FBBA-4540-B96F-6561F1AB40A8";
 	char pkt[1024];
 	char *p = &pkt[0];
-	const char * pc;
+	const char *pc;
 	int len;
 	int okay = 0;
 	struct libwebsocket *wsi;
 	int n;
 
-	wsi = malloc(sizeof (struct libwebsocket));
+	wsi = malloc(sizeof(struct libwebsocket));
 	if (wsi == NULL)
 		return NULL;
 
@@ -123,7 +123,7 @@
 	}
 
 	wsi->sock = socket(AF_INET, SOCK_STREAM, 0);
-	
+
 	if (wsi->sock < 0) {
 		fprintf(stderr, "Unable to open socket\n");
 		goto bail1;
@@ -139,11 +139,11 @@
 					      sizeof(struct sockaddr)) == -1)  {
 		fprintf(stderr, "Connect failed");
 		goto bail1;
-        }
+	}
 
-        /*
-         * create the random key
-         */
+	/*
+	 * create the random key
+	 */
 
 	fd = open(SYSTEM_RANDOM_FILEPATH, O_RDONLY);
 	if (fd < 1) {
@@ -160,7 +160,7 @@
 	}
 	close(fd);
 
-	lws_b64_encode_string(hash, 16, key_b64, sizeof key_b64);	
+	lws_b64_encode_string(hash, 16, key_b64, sizeof key_b64);
 
 	/*
 	 * 04 example client handshake
@@ -283,7 +283,7 @@
 				" Upgrade header '%s'\n",
 				      wsi->utf8_token[WSI_TOKEN_UPGRADE].token);
 		goto bail2;
-	}	
+	}
 
 	strtolower(wsi->utf8_token[WSI_TOKEN_CONNECTION].token);
 	if (strcmp(wsi->utf8_token[WSI_TOKEN_CONNECTION].token, "upgrade")) {
diff --git a/lib/handshake.c b/lib/handshake.c
index 842b764..d6928d7 100644
--- a/lib/handshake.c
+++ b/lib/handshake.c
@@ -376,7 +376,7 @@
 	m += nonce_len;
 	strcpy(m, websocket_magic_guid_04_masking);
 	m += strlen(websocket_magic_guid_04_masking);
-	
+
 	SHA1((unsigned char *)mask_summing_buf, m - mask_summing_buf,
 							   wsi->masking_key_04);
 
@@ -564,9 +564,9 @@
 			return 0;
 		}
 
-
 		if (libwebsocket_interpret_incoming_packet(wsi, buf, len) < 0)
 			goto bail;
+
 		break;
 	default:
 		break;
@@ -576,5 +576,6 @@
 
 bail:
 	libwebsocket_close_and_free_session(wsi);
+
 	return -1;
 }
diff --git a/lib/libwebsockets.c b/lib/libwebsockets.c
index aae6690..1c4bd17 100644
--- a/lib/libwebsockets.c
+++ b/lib/libwebsockets.c
@@ -86,7 +86,8 @@
 		if (this->fds[client].revents & (POLLERR | POLLHUP)) {
 
 			debug("Session Socket %d %p (fd=%d) dead\n",
-				  client, this->wsi[client], this->fds[client]);
+				client, (void *)this->wsi[client],
+							  this->fds[client].fd);
 
 			libwebsocket_close_and_free_session(this->wsi[client]);
 			goto nuke_this;
@@ -132,7 +133,7 @@
 					continue;
 
 				/* only to clients connected to us */
-				
+
 				if (wsi->client_mode)
 					continue;
 
@@ -174,9 +175,9 @@
 
 		/* service incoming data */
 
-		if (libwebsocket_read(this->wsi[client], buf, n) >= 0)
+		n = libwebsocket_read(this->wsi[client], buf, n);
+		if (n >= 0)
 			continue;
-
 		/*
 		 * it closed and nuked wsi[client], so remove the
 		 * socket handle and wsi from our service list
@@ -184,19 +185,82 @@
 nuke_this:
 
 		debug("nuking wsi %p, fsd_count = %d\n",
-					this->wsi[client], this->fds_count - 1);
+				(void *)this->wsi[client], this->fds_count - 1);
 
 		this->fds_count--;
 		for (n = client; n < this->fds_count; n++) {
 			this->fds[n] = this->fds[n + 1];
 			this->wsi[n] = this->wsi[n + 1];
 		}
-		break;
+
+		return 0;
+
 	}
 
 	return 0;
 }
 
+/**
+ * libwebsocket_context_destroy() - Destroy the websocket context
+ * @this:	Websocket context
+ *
+ *	This function closes any active connections and then frees the
+ *	context.  After calling this, any further use of the context is
+ *	undefined.
+ */
+void
+libwebsocket_context_destroy(struct libwebsocket_context *this)
+{
+	int client;
+
+	/* close listening skt and per-protocol broadcast sockets */
+	for (client = 0; client < this->fds_count; client++)
+		libwebsocket_close_and_free_session(this->wsi[client]);
+
+#ifdef LWS_OPENSSL_SUPPORT
+	if (ssl_ctx)
+		SSL_CTX_free(ssl_ctx);
+#endif
+
+	if (this)
+		free(this);
+}
+
+/**
+ * libwebsocket_service() - Service any pending websocket activity
+ * @this:	Websocket context
+ * @timeout_ms:	Timeout for poll; 0 means return immediately if nothing needed
+ *		service otherwise block and service immediately, returning
+ *		after the timeout if nothing needed service.
+ *
+ *	This function deals with any pending websocket traffic, for three
+ *	kinds of event.  It handles these events on both server and client
+ *	types of connection the same.
+ *
+ *	1) Accept new connections to our context's server
+ *
+ *	2) Perform pending broadcast writes initiated from other forked
+ *	   processes (effectively serializing asynchronous broadcasts)
+ *
+ *	3) Call the receive callback for incoming frame data received by
+ *	    server or client connections.
+ *
+ *	You need to call this service function periodically to all the above
+ *	functions to happen; if your application is single-threaded you can
+ *	just call it in your main event loop.
+ *
+ *	Alternatively you can fork a new process that asynchronously handles
+ *	calling this service in a loop.  In that case you are happy if this
+ *	call blocks your thread until it needs to take care of something and
+ *	would call it with a large nonzero timeout.  Your loop then takes no
+ *	CPU while there is nothing happening.
+ *
+ *	If you are calling it in a single-threaded app, you don't want it to
+ *	wait around blocking other things in your loop from happening, so you
+ *	would call it with a timeout_ms of 0, so it returns immediately if
+ *	nothing is pending, or as soon as it services whatever was pending.
+ */
+
 
 int
 libwebsocket_service(struct libwebsocket_context *this, int timeout_ms)
@@ -218,7 +282,7 @@
 		n = poll(this->fds, this->fds_count, timeout_ms);
 	else
 		n = poll(&this->fds[1], this->fds_count - 1, timeout_ms);
-	
+
 
 	if (n < 0 || this->fds[0].revents & (POLLERR | POLLHUP)) {
 		fprintf(stderr, "Listen Socket dead\n");
@@ -369,6 +433,8 @@
 
 fatal:
 
+	fprintf(stderr, "service hits fatal\n");
+
 	/* close listening skt and per-protocol broadcast sockets */
 	for (client = 0; client < this->fds_count; client++)
 		close(this->fds[0].fd);
@@ -376,7 +442,6 @@
 #ifdef LWS_OPENSSL_SUPPORT
 	SSL_CTX_free(ssl_ctx);
 #endif
-	kill(0, SIGTERM);
 
 	if (this)
 		free(this);
@@ -392,12 +457,12 @@
 /**
  * libwebsocket_create_context() - Create the websocket handler
  * @port:	Port to listen on... you can use 0 to suppress listening on
- * 		any port, that's what you want if you are not running a
- * 		websocket server at all but just using it as a client
+ *		any port, that's what you want if you are not running a
+ *		websocket server at all but just using it as a client
  * @protocols:	Array of structures listing supported protocols and a protocol-
  *		specific callback for each one.  The list is ended with an
  *		entry that has a NULL callback pointer.
- *	        It's not const because we write the owning_server member
+ *		It's not const because we write the owning_server member
  * @ssl_cert_filepath:	If libwebsockets was compiled to use ssl, and you want
  *			to listen using SSL, set to the filepath to fetch the
  *			server cert from, otherwise NULL for unencrypted
@@ -644,10 +709,10 @@
 /**
  * libwebsockets_fork_service_loop() - Optional helper function forks off
  *				  a process for the websocket server loop.
- * 				You don't have to use this but if not, you
- * 				have to make sure you are calling
- * 				libwebsocket_service periodically to service
- * 				the websocket traffic
+ *				You don't have to use this but if not, you
+ *				have to make sure you are calling
+ *				libwebsocket_service periodically to service
+ *				the websocket traffic
  * @this:	server context returned by creation function
  */
 
@@ -798,7 +863,7 @@
 	 * set up when the websocket server initializes
 	 */
 
-	n = send(protocol->broadcast_socket_user_fd, buf, len, 0);
+	n = send(protocol->broadcast_socket_user_fd, buf, len, MSG_NOSIGNAL);
 
 	return n;
 }
diff --git a/lib/libwebsockets.h b/lib/libwebsockets.h
index b6d7335..57ab481 100644
--- a/lib/libwebsockets.h
+++ b/lib/libwebsockets.h
@@ -59,11 +59,11 @@
  *
  *	This callback is the way the user controls what is served.  All the
  *	protocol detail is hidden and handled by the library.
- * 
+ *
  *	For each connection / session there is user data allocated that is
  *	pointed to by "user".  You set the size of this user data area when
  *	the library is initialized with libwebsocket_create_server.
- * 
+ *
  *	You get an opportunity to initialize user data when called back with
  *	LWS_CALLBACK_ESTABLISHED reason.
  *
@@ -77,45 +77,45 @@
  *	LWS_CALLBACK_RECEIVE: data has appeared for the server, it can be
  *				found at *in and is len bytes long
  *
- * 	LWS_CALLBACK_HTTP: an http request has come from a client that is not
+ *	LWS_CALLBACK_HTTP: an http request has come from a client that is not
  *				asking to upgrade the connection to a websocket
  *				one.  This is a chance to serve http content,
  *				for example, to send a script to the client
  *				which will then open the websockets connection.
- *				@in points to the URI path requested and 
+ *				@in points to the URI path requested and
  *				libwebsockets_serve_http_file() makes it very
  *				simple to send back a file to the client.
  */
-extern int callback(struct libwebsocket * wsi,
-			 enum libwebsocket_callback_reasons reason, void * user,
+extern int callback(struct libwebsocket *wsi,
+			 enum libwebsocket_callback_reasons reason, void *user,
 							  void *in, size_t len);
 
 /**
- * struct libwebsocket_protocols - 	List of protocols and handlers server
- * 					supports.
+ * struct libwebsocket_protocols -	List of protocols and handlers server
+ *					supports.
  * @name:	Protocol name that must match the one given in the client
- * 		Javascript new WebSocket(url, 'protocol') name
+ *		Javascript new WebSocket(url, 'protocol') name
  * @callback:	The service callback used for this protocol.  It allows the
- * 		service action for an entire protocol to be encapsulated in
- * 		the protocol-specific callback
+ *		service action for an entire protocol to be encapsulated in
+ *		the protocol-specific callback
  * @per_session_data_size:	Each new connection using this protocol gets
- * 		this much memory allocated on connection establishment and
- * 		freed on connection takedown.  A pointer to this per-connection
- * 		allocation is passed into the callback in the 'user' parameter
+ *		this much memory allocated on connection establishment and
+ *		freed on connection takedown.  A pointer to this per-connection
+ *		allocation is passed into the callback in the 'user' parameter
  * @owning_server:	the server init call fills in this opaque pointer when
- * 		registering this protocol with the server.
+ *		registering this protocol with the server.
  * @broadcast_socket_port: the server init call fills this in with the
- * 		localhost port number used to forward broadcasts for this
- * 		protocol
+ *		localhost port number used to forward broadcasts for this
+ *		protocol
  * @broadcast_socket_user_fd:  the server init call fills this in ... the main()
- * 		process context can write to this socket to perform broadcasts
- * 		(use the libwebsockets_broadcast() api to do this instead,
- * 		it works from any process context)
+ *		process context can write to this socket to perform broadcasts
+ *		(use the libwebsockets_broadcast() api to do this instead,
+ *		it works from any process context)
  * @protocol_index: which protocol we are starting from zero
  *
- * 	This structure represents one protocol supported by the server.  An
- * 	array of these structures is passed to libwebsocket_create_server()
- * 	allows as many protocols as you like to be handled by one server.
+ *	This structure represents one protocol supported by the server.  An
+ *	array of these structures is passed to libwebsocket_create_server()
+ *	allows as many protocols as you like to be handled by one server.
  */
 
 struct libwebsocket_protocols {
@@ -129,7 +129,7 @@
 	 * below are filled in on server init and can be left uninitialized,
 	 * no need for user to use them directly either
 	 */
-	
+
 	struct libwebsocket_context *owning_server;
 	int broadcast_socket_port;
 	int broadcast_socket_user_fd;
@@ -142,6 +142,9 @@
 		  const char *ssl_cert_filepath,
 		  const char *ssl_private_key_filepath, int gid, int uid);
 
+extern void
+libwebsocket_context_destroy(struct libwebsocket_context *this);
+
 extern int
 libwebsockets_fork_service_loop(struct libwebsocket_context *this);
 
@@ -188,7 +191,7 @@
 /* notice - you need the pre- and post- padding allocation for buf below */
 
 extern int
-libwebsockets_broadcast(const struct libwebsocket_protocols * protocol,
+libwebsockets_broadcast(const struct libwebsocket_protocols *protocol,
 						unsigned char *buf, size_t len);
 
 extern const struct libwebsocket_protocols *
diff --git a/lib/parsers.c b/lib/parsers.c
index aafa38d..9d9efb3 100644
--- a/lib/parsers.c
+++ b/lib/parsers.c
@@ -149,7 +149,7 @@
 			debug("known hdr '%s'\n", wsi->name_buffer);
 			wsi->parser_state = WSI_TOKEN_GET_URI + n;
 			wsi->current_alloc_len = LWS_INITIAL_HDR_ALLOC;
-			
+
 			wsi->utf8_token[wsi->parser_state].token =
 						 malloc(wsi->current_alloc_len);
 			wsi->utf8_token[wsi->parser_state].token_len = 0;
@@ -220,7 +220,7 @@
 	return 0;
 }
 
-static unsigned char inline
+static inline unsigned char
 xor_mask(struct libwebsocket *wsi, unsigned char c)
 {
 	c ^= wsi->masking_key_04[wsi->frame_mask_index++];
@@ -286,7 +286,7 @@
 		 * wsi->frame_mask_04 will be our recirculating 20-byte XOR key
 		 * for this frame
 		 */
-	
+
 		SHA1((unsigned char *)buf, 4 + 20, wsi->frame_mask_04);
 
 		/*
@@ -295,7 +295,7 @@
 		 */
 
 		wsi->frame_mask_index = 0;
-		
+
 		wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_1;
 		break;
 
@@ -305,7 +305,7 @@
 	 *
 	 * We ignore the possibility of extension data because we don't
 	 * negotiate any extensions at the moment.
-	 * 
+	 *
 	 *    0                   1                   2                   3
 	 *    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 	 *   +-+-+-+-+-------+-+-------------+-------------------------------+
@@ -334,23 +334,24 @@
 		 * 04 spec defines the opcode like this: (1, 2, and 3 are
 		 * "control frame" opcodes which may not be fragmented or
 		 * have size larger than 126)
-		 * 
-		 *       frame-opcode           =
-		 * 	       %x0 ; continuation frame
-		 *           / %x1 ; connection close
-		 *           / %x2 ; ping
-		 *           / %x3 ; pong
-		 *           / %x4 ; text frame
-		 *           / %x5 ; binary frame
-		 *           / %x6-F ; reserved
 		 *
-		 * 	  FIN (b7)
+		 *       frame-opcode           =
+		 *	       %x0 ; continuation frame
+		 *		/ %x1 ; connection close
+		 *		/ %x2 ; ping
+		 *		/ %x3 ; pong
+		 *		/ %x4 ; text frame
+		 *		/ %x5 ; binary frame
+		 *		/ %x6-F ; reserved
+		 *
+		 *		FIN (b7)
 		 */
 
 		c = xor_mask(wsi, c);
 
 		if (c & 0x70) {
-			fprintf(stderr, "Frame has extensions set illegally 1\n");
+			fprintf(stderr,
+				      "Frame has extensions set illegally 1\n");
 			/* kill the connection */
 			return -1;
 		}
@@ -412,7 +413,6 @@
 			wsi->lws_rx_parse_state = LWS_RXPS_04_FRAME_HDR_LEN64_8;
 			break;
 		default:
-//			fprintf(stderr, "seen incoming 04 frame len %d\n", c);
 			wsi->rx_packet_length = c;
 			wsi->lws_rx_parse_state =
 					LWS_RXPS_PAYLOAD_UNTIL_LENGTH_EXHAUSTED;
@@ -605,51 +605,51 @@
 			}
 			break;
 		case 4:
-		/*
-		 *  04 logical framing from the spec (all this is masked when incoming
-		 *  and has to be unmasked)
-		 *
-		 * We ignore the possibility of extension data because we don't
-		 * negotiate any extensions at the moment.
-		 * 
-		 *    0                   1                   2                   3
-		 *    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
-		 *   +-+-+-+-+-------+-+-------------+-------------------------------+
-		 *   |F|R|R|R| opcode|R| Payload len |    Extended payload length    |
-		 *   |I|S|S|S|  (4)  |S|     (7)     |             (16/63)           |
-		 *   |N|V|V|V|       |V|             |   (if payload len==126/127)   |
-		 *   | |1|2|3|       |4|             |                               |
-		 *   +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
-		 *   |     Extended payload length continued, if payload len == 127  |
-		 *   + - - - - - - - - - - - - - - - +-------------------------------+
-		 *   |                               |         Extension data        |
-		 *   +-------------------------------+ - - - - - - - - - - - - - - - +
-		 *   :                                                               :
-		 *   +---------------------------------------------------------------+
-		 *   :                       Application data                        :
-		 *   +---------------------------------------------------------------+
-		 *
-		 *  We pass payload through to userland as soon as we get it, ignoring
-		 *  FIN.  It's up to userland to buffer it up if it wants to see a
-		 *  whole unfragmented block of the original size (which may be up to
-		 *  2^63 long!)
-		 */
+	/*
+	 *  04 logical framing from the spec (all this is masked when
+	 *  incoming and has to be unmasked)
+	 *
+	 * We ignore the possibility of extension data because we don't
+	 * negotiate any extensions at the moment.
+	 *
+	 *    0                   1                   2                   3
+	 *    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+	 *   +-+-+-+-+-------+-+-------------+-------------------------------+
+	 *   |F|R|R|R| opcode|R| Payload len |    Extended payload length    |
+	 *   |I|S|S|S|  (4)  |S|     (7)     |             (16/63)           |
+	 *   |N|V|V|V|       |V|             |   (if payload len==126/127)   |
+	 *   | |1|2|3|       |4|             |                               |
+	 *   +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
+	 *   |     Extended payload length continued, if payload len == 127  |
+	 *   + - - - - - - - - - - - - - - - +-------------------------------+
+	 *   |                               |         Extension data        |
+	 *   +-------------------------------+ - - - - - - - - - - - - - - - +
+	 *   :                                                               :
+	 *   +---------------------------------------------------------------+
+	 *   :                       Application data                        :
+	 *   +---------------------------------------------------------------+
+	 *
+	 *  We pass payload through to userland as soon as we get it, ignoring
+	 *  FIN.  It's up to userland to buffer it up if it wants to see a
+	 *  whole unfragmented block of the original size (which may be up to
+	 *  2^63 long!)
+	 */
 
 		/*
 		 * 04 spec defines the opcode like this: (1, 2, and 3 are
 		 * "control frame" opcodes which may not be fragmented or
 		 * have size larger than 126)
-		 * 
-		 *       frame-opcode           =
-		 * 	       %x0 ; continuation frame
-		 *           / %x1 ; connection close
-		 *           / %x2 ; ping
-		 *           / %x3 ; pong
-		 *           / %x4 ; text frame
-		 *           / %x5 ; binary frame
-		 *           / %x6-F ; reserved
 		 *
-		 * 	  FIN (b7)
+		 *       frame-opcode           =
+		 *		  %x0 ; continuation frame
+		 *		/ %x1 ; connection close
+		 *		/ %x2 ; ping
+		 *		/ %x3 ; pong
+		 *		/ %x4 ; text frame
+		 *		/ %x5 ; binary frame
+		 *		/ %x6-F ; reserved
+		 *
+		 *		FIN (b7)
 		 */
 
 			if (c & 0x70) {
@@ -1136,14 +1136,14 @@
 	if (use_ssl) {
 		n = SSL_write(wsi->ssl, buf - pre, len + pre + post);
 		if (n < 0) {
-			fprintf(stderr, "ERROR writing to socket");
+			fprintf(stderr, "ERROR writing to socket\n");
 			return -1;
 		}
 	} else {
 #endif
-		n = send(wsi->sock, buf - pre, len + pre + post, 0);
+		n = send(wsi->sock, buf - pre, len + pre + post, MSG_NOSIGNAL);
 		if (n < 0) {
-			fprintf(stderr, "ERROR writing to socket");
+			fprintf(stderr, "ERROR writing to socket\n");
 			return -1;
 		}
 #ifdef LWS_OPENSSL_SUPPORT
@@ -1211,7 +1211,7 @@
 
 /**
  * libwebsockets_remaining_packet_payload() - Bytes to come before "overall"
- * 					      rx packet is complete
+ *					      rx packet is complete
  * @wsi:		Websocket instance (available from user callback)
  *
  *	This function is intended to be called from the callback if the
diff --git a/lib/private-libwebsockets.h b/lib/private-libwebsockets.h
index 6f35a1e..a263d83 100644
--- a/lib/private-libwebsockets.h
+++ b/lib/private-libwebsockets.h
@@ -51,16 +51,20 @@
 #include <openssl/sha.h>
 #include "libwebsockets.h"
 
-//#define DEBUG 
-
+#if 0
+#define DEBUG
+#endif
 
 #ifdef DEBUG
-static inline void debug(const char *format, ...) {
+static inline void debug(const char *format, ...)
+{
 	va_list ap;
 	va_start(ap, format); vfprintf(stderr, format, ap); va_end(ap);
 }
 #else
-static inline void debug(const char *format, ...) { }
+static inline void debug(const char *format, ...)
+{
+}
 #endif
 
 #ifdef LWS_OPENSSL_SUPPORT
diff --git a/libwebsockets-api-doc.html b/libwebsockets-api-doc.html
index 6def9b3..c8a3477 100644
--- a/libwebsockets-api-doc.html
+++ b/libwebsockets-api-doc.html
@@ -1,3 +1,63 @@
+<h2>libwebsocket_context_destroy - Destroy the websocket context</h2>
+<i>void</i>
+<b>libwebsocket_context_destroy</b>
+(<i>struct libwebsocket_context *</i> <b>this</b>)
+<h3>Arguments</h3>
+<dl>
+<dt><b>this</b>
+<dd>Websocket context
+</dl>
+<h3>Description</h3>
+<blockquote>
+This function closes any active connections and then frees the
+context.  After calling this, any further use of the context is
+undefined.
+</blockquote>
+<hr>
+<h2>libwebsocket_service - Service any pending websocket activity</h2>
+<i>int</i>
+<b>libwebsocket_service</b>
+(<i>struct libwebsocket_context *</i> <b>this</b>,
+<i>int</i> <b>timeout_ms</b>)
+<h3>Arguments</h3>
+<dl>
+<dt><b>this</b>
+<dd>Websocket context
+<dt><b>timeout_ms</b>
+<dd>Timeout for poll; 0 means return immediately if nothing needed
+service otherwise block and service immediately, returning
+after the timeout if nothing needed service.
+</dl>
+<h3>Description</h3>
+<blockquote>
+This function deals with any pending websocket traffic, for three
+kinds of event.  It handles these events on both server and client
+types of connection the same.
+<p>
+1) Accept new connections to our context's server
+<p>
+2) Perform pending broadcast writes initiated from other forked
+processes (effectively serializing asynchronous broadcasts)
+<p>
+3) Call the receive callback for incoming frame data received by
+server or client connections.
+<p>
+You need to call this service function periodically to all the above
+functions to happen; if your application is single-threaded you can
+just call it in your main event loop.
+<p>
+Alternatively you can fork a new process that asynchronously handles
+calling this service in a loop.  In that case you are happy if this
+call blocks your thread until it needs to take care of something and
+would call it with a large nonzero timeout.  Your loop then takes no
+CPU while there is nothing happening.
+<p>
+If you are calling it in a single-threaded app, you don't want it to
+wait around blocking other things in your loop from happening, so you
+would call it with a timeout_ms of 0, so it returns immediately if
+nothing is pending, or as soon as it services whatever was pending.
+</blockquote>
+<hr>
 <h2>libwebsocket_create_context - Create the websocket handler</h2>
 <i>struct libwebsocket_context *</i>
 <b>libwebsocket_create_context</b>
diff --git a/test-server/test-client.c b/test-server/test-client.c
index 6869d6d..3243ccd 100644
--- a/test-server/test-client.c
+++ b/test-server/test-client.c
@@ -380,6 +380,8 @@
 	libwebsocket_client_close(wsi_dumb);
 	libwebsocket_client_close(wsi_mirror);
 
+	libwebsocket_context_destroy(context);
+
 	return 0;
 
 usage:
diff --git a/test-server/test-server.c b/test-server/test-server.c
index dc3cfd9..832a45a 100644
--- a/test-server/test-server.c
+++ b/test-server/test-server.c
@@ -1,7 +1,7 @@
 /*
  * libwebsockets-test-server - libwebsockets test implementation
  *
- * Copyright (C) 2010 Andy Green <andy@warmcat.com>
+ * Copyright (C) 2010-2011 Andy Green <andy@warmcat.com>
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Lesser General Public
@@ -233,7 +233,7 @@
 	struct libwebsocket_context *context;
 
 	fprintf(stderr, "libwebsockets test server\n"
-			"(C) Copyright 2010 Andy Green <andy@warmcat.com> "
+			"(C) Copyright 2010-2011 Andy Green <andy@warmcat.com> "
 						    "licensed under LGPL2.1\n");
 
 	while (n >= 0) {
@@ -349,5 +349,7 @@
 
 #endif
 
+	libwebsocket_context_destroy(context);
+
 	return 0;
 }