socket-handler: Use array of pointers for clients array

When a client registers a poller, it uses a pointer to the struct client
in the poller's data field.

Since the clients are allocated in the socket handler's ->clients array
directly, and this array may be realloc()ed, a client's pointer may
change when other clients connect or disconnect.

This change uses separate allocations for the clients and the
sh->clients array, so the client pointers remain valid for the life of
the client.

Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
diff --git a/socket-handler.c b/socket-handler.c
index 7be9c71..2e4f5c2 100644
--- a/socket-handler.c
+++ b/socket-handler.c
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+
+#include <assert.h>
 #include <err.h>
 #include <stdbool.h>
 #include <stdio.h>
@@ -39,7 +41,7 @@
 	struct poller	*poller;
 	int		sd;
 
-	struct client	*clients;
+	struct client	**clients;
 	int		n_clients;
 };
 
@@ -56,7 +58,14 @@
 	if (client->poller)
 		console_unregister_poller(sh->console, client->poller);
 
-	idx = client - sh->clients;
+	for (idx = 0; idx < sh->n_clients; idx++)
+		if (sh->clients[idx] == client)
+			break;
+
+	assert(idx < sh->n_clients);
+
+	free(client);
+	client = NULL;
 
 	sh->n_clients--;
 	memmove(&sh->clients[idx], &sh->clients[idx+1],
@@ -112,14 +121,18 @@
 	if (fd < 0)
 		return POLLER_OK;
 
-	n = sh->n_clients++;
-	sh->clients = realloc(sh->clients, sizeof(*client) * sh->n_clients);
-	client = &sh->clients[n];
+	client = malloc(sizeof(*client));
+	memset(client, 0, sizeof(*client));
 
 	client->fd = fd;
 	client->poller = console_register_poller(sh->console, handler,
 			client_poll, client->fd, POLLIN, client);
 
+	n = sh->n_clients++;
+	sh->clients = realloc(sh->clients,
+			sizeof(*sh->clients) * sh->n_clients);
+	sh->clients[n] = client;
+
 	return POLLER_OK;
 
 }
@@ -170,7 +183,7 @@
 	int i;
 
 	for (i = 0; i < sh->n_clients; i++) {
-		struct client *client = &sh->clients[i];
+		struct client *client = sh->clients[i];
 		client_send_data(sh, client, buf, len);
 	}
 	return 0;
@@ -182,7 +195,7 @@
 	int i;
 
 	for (i = 0; i < sh->n_clients; i++)
-		client_close(sh, &sh->clients[i]);
+		client_close(sh, sh->clients[i]);
 
 	if (sh->poller)
 		console_unregister_poller(sh->console, sh->poller);