unify server and client close

Signed-off-by: Andy Green <andy@warmcat.com>
diff --git a/lib/libwebsockets.c b/lib/libwebsockets.c
index e1ab1c5..d4db3f3 100644
--- a/lib/libwebsockets.c
+++ b/lib/libwebsockets.c
@@ -76,13 +76,14 @@
 
 
 void
-libwebsocket_close_and_free_session(struct libwebsocket *wsi)
+libwebsocket_close_and_free_session(struct libwebsocket_context *this,
+						       struct libwebsocket *wsi)
 {
 	int n;
 	unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + 2 +
 						  LWS_SEND_BUFFER_POST_PADDING];
 
-	if ((unsigned long)wsi < LWS_MAX_PROTOCOLS)
+	if (!wsi)
 		return;
 
 	n = wsi->state;
@@ -90,12 +91,35 @@
 	if (n == WSI_STATE_DEAD_SOCKET)
 		return;
 
+	/* remove this fd from wsi mapping hashtable */
+
+	delete_from_fd(this, wsi->sock);
+
+	/* delete it from the internal poll list if still present */
+
+	for (n = 0; n < this->fds_count; n++) {
+		if (this->fds[n].fd != wsi->sock)
+			continue;
+		while (n < this->fds_count - 1) {
+			this->fds[n] = this->fds[n + 1];
+			n++;
+		}
+		this->fds_count--;
+		/* we only have to deal with one */
+		n = this->fds_count;
+	}
+
+	/* remove also from external POLL support via protocol 0 */
+
+	this->protocols[0].callback(wsi,
+		    LWS_CALLBACK_DEL_POLL_FD, (void *)(long)wsi->sock, NULL, 0);
+
 	/*
 	 * signal we are closing, libsocket_write will
 	 * add any necessary version-specific stuff.  If the write fails,
 	 * no worries we are closing anyway.  If we didn't initiate this
 	 * close, then our state has been changed to
-	 * WSI_STATE_RETURNED_CLOSE_ALREADY and we can skip this
+	 * WSI_STATE_RETURNED_CLOSE_ALREADY and we will skip this
 	 */
 
 	if (n == WSI_STATE_ESTABLISHED)
@@ -104,10 +128,14 @@
 
 	wsi->state = WSI_STATE_DEAD_SOCKET;
 
+	/* tell the user it's all over for this guy */
+
 	if (wsi->protocol->callback && n == WSI_STATE_ESTABLISHED)
 		wsi->protocol->callback(wsi, LWS_CALLBACK_CLOSED,
 						      wsi->user_space, NULL, 0);
 
+	/* free up his allocations */
+
 	for (n = 0; n < WSI_TOKEN_COUNT; n++)
 		if (wsi->utf8_token[n].token)
 			free(wsi->utf8_token[n].token);
@@ -161,7 +189,7 @@
 			this->fds_count--;
 		}
 
-	libwebsocket_close_and_free_session(wsi);
+	libwebsocket_close_and_free_session(this, wsi);
 }
 
 
@@ -456,8 +484,8 @@
 			debug("Session Socket %p (fd=%d) dead\n",
 				(void *)wsi, accept_fd);
 
-			libwebsocket_close_and_free_session(wsi);
-			goto nuke_this;
+			libwebsocket_close_and_free_session(this, wsi);
+			return 1;
 		}
 
 		/* the guy requested a callback when it was OK to write */
@@ -490,7 +518,7 @@
 							 MAX_BROADCAST_PAYLOAD);
 		if (len < 0) {
 			fprintf(stderr, "Error reading broadcast payload\n");
-			break;;
+			break;
 		}
 
 		/* broadcast it to all guys with this protocol index */
@@ -543,8 +571,8 @@
 			debug("Session Socket %p (fd=%d) dead\n",
 				(void *)wsi, pollfd->fd);
 
-			libwebsocket_close_and_free_session(wsi);
-			goto nuke_this;
+			libwebsocket_close_and_free_session(this, wsi);
+			return 1;
 		}
 
 		/* the guy requested a callback when it was OK to write */
@@ -578,46 +606,22 @@
 
 		if (n < 0) {
 			fprintf(stderr, "Socket read returned %d\n", n);
-			break;;
+			break;
 		}
 		if (!n) {
-			libwebsocket_close_and_free_session(wsi);
-			goto nuke_this;
+			libwebsocket_close_and_free_session(this, wsi);
+			return 1;
 		}
 
 		/* service incoming data */
 
-		n = libwebsocket_read(wsi, buf, n);
+		n = libwebsocket_read(this, wsi, buf, n);
 		if (n >= 0)
-			break;;
-		/*
-		 * it closed and nuked wsi[client], so remove the
-		 * socket handle and wsi from our service list
-		 */
-nuke_this:
+			break;
 
-		debug("nuking wsi %p, fsd_count = %d\n",
-				(void *)wsi, this->fds_count - 1);
+		/* we closed wsi */
 
-		delete_from_fd(this, pollfd->fd);
-
-		this->fds_count--;
-		for (n = 0; n < this->fds_count; n++)
-			if (this->fds[n].fd == pollfd->fd) {
-				while (n < this->fds_count) {
-					this->fds[n] = this->fds[n + 1];
-					n++;
-				}
-				n = this->fds_count;
-			}
-
-		/* external POLL support via protocol 0 */
-		this->protocols[0].callback(wsi,
-			LWS_CALLBACK_DEL_POLL_FD,
-			(void *)(long)pollfd->fd, NULL, 0);
-
-
-		break;
+		return 1;
 	}
 
 	return 0;
@@ -639,24 +643,11 @@
 	int m;
 	struct libwebsocket *wsi;
 
-	for (n = 0; n < FD_HASHTABLE_MODULUS; n++) {
-
+	for (n = 0; n < FD_HASHTABLE_MODULUS; n++)
 		for (m = 0; m < this->fd_hashtable[n].length; m++) {
-
 			wsi = this->fd_hashtable[n].wsi[m];
-
-			switch (wsi->mode) {
-			case LWS_CONNMODE_WS_SERVING:
-				libwebsocket_close_and_free_session(wsi);
-				break;
-			case LWS_CONNMODE_WS_CLIENT:
-				libwebsocket_client_close(wsi);
-				break;
-			default:
-				break;
-			}
+			libwebsocket_close_and_free_session(this, wsi);
 		}
-	}
 
 	close(this->fd_random);