From: Rusty Russell Date: Sat, 22 Jan 2011 03:40:51 +0000 (+1030) Subject: lca2011: don't use void * for the handle. X-Git-Url: http://git.ozlabs.org/?p=ccan-lca-2011.git;a=commitdiff_plain;h=9dea47ccb8dacf364bf15f4e30f871ab455b6e04 lca2011: don't use void * for the handle. And don't keep global state: it's messy, and you can never invoke two of them. --- diff --git a/ccan/oserver/_info b/ccan/oserver/_info index c5f5b4b..5dfc5f8 100644 --- a/ccan/oserver/_info +++ b/ccan/oserver/_info @@ -8,6 +8,10 @@ * * License: GPL * + * Ccanlint: + * // hack to make valgrind show the error. FIXME! + * tests_pass_valgrind --child-silent-after-fork=no + * * Example: * #include * #include @@ -47,7 +51,6 @@ int main(int argc, char *argv[]) printf("ccan/read_write_all\n"); printf("ccan/str\n"); printf("ccan/foreach\n"); - printf("ccan/noerr\n"); printf("ccan/failtest\n"); printf("ccan/opt\n"); printf("ccan/array_size\n"); diff --git a/ccan/oserver/oserver.c b/ccan/oserver/oserver.c index 4503aa4..3256369 100644 --- a/ccan/oserver/oserver.c +++ b/ccan/oserver/oserver.c @@ -3,7 +3,6 @@ #include #include #include -#include #include #include #include @@ -39,12 +38,16 @@ struct client { char *question; /* How many bytes of the reply we sent so far. */ size_t bytes_sent; + /* Our server. */ + struct oserver *oserver; }; -/* 5 clients should be enough for anybody! */ -static struct client *clients[5]; -static int sfd; -static struct tevent_fd *sfde; +struct oserver { + /* 5 clients should be enough for anybody! */ + struct client *clients[5]; + int fd; + struct tevent_fd *fde; +}; static ssize_t write_string(int fd, const char *str) { @@ -133,10 +136,11 @@ static int cleanup_client(struct client *client) { unsigned int i; - for (i = 0; i < ARRAY_SIZE(clients); i++) { - if (clients[i] == client) { - clients[i] = NULL; - tevent_fd_set_flags(sfde, TEVENT_FD_READ); + for (i = 0; i < ARRAY_SIZE(client->oserver->clients); i++) { + if (client->oserver->clients[i] == client) { + client->oserver->clients[i] = NULL; + tevent_fd_set_flags(client->oserver->fde, + TEVENT_FD_READ); return 0; } } @@ -144,67 +148,86 @@ static int cleanup_client(struct client *client) } static void add_client(struct tevent_context *ev, - struct tevent_fd *fde, uint16_t flags, void *unused) + struct tevent_fd *fde, uint16_t flags, void *_oserver) { + struct oserver *oserver = _oserver; struct client *client; unsigned int i; - client = talloc(sfde, struct client); - client->fd = accept(sfd, NULL, 0); + client = talloc(oserver, struct client); + client->fd = accept(oserver->fd, NULL, 0); if (client->fd < 0) err(1, "Accepting client connection"); client->state = RECEIVING_USER_QUESTION; client->bytes_sent = 0; client->question = talloc_strdup(client, ""); + client->oserver = oserver; client->fde = tevent_add_fd(ev, client, client->fd, state_flag_map[client->state], service_client, client); tevent_fd_set_auto_close(client->fde); /* Find empty slot in array for this client. */ - for (i = 0; clients[i]; i++); - clients[i] = client; + for (i = 0; oserver->clients[i]; i++); + oserver->clients[i] = client; talloc_set_destructor(client, cleanup_client); /* Full? Stop listening... */ - if (i == ARRAY_SIZE(clients)-1) - tevent_fd_set_flags(sfde, 0); + if (i == ARRAY_SIZE(oserver->clients)-1) + tevent_fd_set_flags(oserver->fde, 0); +} + +static int destroy_oserver(struct oserver *oserver) +{ + close(oserver->fd); + return 0; } -void *oserver_setup(struct tevent_context *ev, unsigned short port) +struct oserver *oserver_setup(struct tevent_context *ev, unsigned short port) { + struct oserver *oserver; int one = 1; union { struct sockaddr addr; struct sockaddr_in in; } u; - sfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); - if (sfd < 0) - return false; + oserver = talloc(ev, struct oserver); + + oserver->fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (oserver->fd < 0) { + talloc_free(oserver); + return NULL; + } + talloc_set_destructor(oserver, destroy_oserver); - if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one))) + if (setsockopt(oserver->fd, SOL_SOCKET, SO_REUSEADDR, + &one, sizeof(one))) warn("Setting socket reuse"); u.in.sin_family = AF_INET; u.in.sin_port = htons(port); u.in.sin_addr.s_addr = INADDR_ANY; - if (bind(sfd, &u.addr, sizeof(u.in)) == -1) { - close_noerr(sfd); + if (bind(oserver->fd, &u.addr, sizeof(u.in)) == -1) { + talloc_free(oserver); return NULL; } - if (listen(sfd, 0) != 0) { - close_noerr(sfd); + if (listen(oserver->fd, 0) != 0) { + talloc_free(oserver); return NULL; } - sfde = tevent_add_fd(ev, ev, sfd, TEVENT_FD_READ, add_client, NULL); - tevent_fd_set_auto_close(sfde); + oserver->fde = tevent_add_fd(ev, oserver, oserver->fd, + TEVENT_FD_READ, add_client, oserver); + if (!oserver->fde) { + talloc_free(oserver); + return NULL; + } /* Don't kill us if client dies. */ signal(SIGPIPE, SIG_IGN); - return sfde; + return oserver; } diff --git a/ccan/oserver/oserver.h b/ccan/oserver/oserver.h index e1f3cc7..6b9a3e7 100644 --- a/ccan/oserver/oserver.h +++ b/ccan/oserver/oserver.h @@ -9,10 +9,11 @@ * @port: port to use (usually OSERVER_PORT) * * Opens a socket and binds it to @port, then sets it up to listen - * for connections. talloc_free() the pointer returned to shut it down. + * for connections. talloc_free() the pointer returned to shut it down + * (its parent is the tevent_context). * * Example: - * void *oserver; + * struct oserver *oserver; * struct tevent_context *ev; * * ev = tevent_context_init(NULL); @@ -23,7 +24,7 @@ * while (tevent_loop_wait(ev) == 0); * err(1, "Event loop failed"); */ -void *oserver_setup(struct tevent_context *ev, unsigned short port); +struct oserver *oserver_setup(struct tevent_context *ev, unsigned short port); #define OSERVER_PORT 2727 #endif /* CCAN_OSERVER_H */