]> git.ozlabs.org Git - ccan-lca-2011.git/commitdiff
lca2011: don't use void * for the handle.
authorRusty Russell <rusty@rustcorp.com.au>
Sat, 22 Jan 2011 03:40:51 +0000 (14:10 +1030)
committerRusty Russell <rusty@rustcorp.com.au>
Sat, 22 Jan 2011 03:40:51 +0000 (14:10 +1030)
And don't keep global state: it's messy, and you can never invoke two of them.

ccan/oserver/_info
ccan/oserver/oserver.c
ccan/oserver/oserver.h

index c5f5b4be48225f8482ec325bc7fc16032a3cf432..5dfc5f88fb27a001e1e9b68fb807cbbf9ff669e0 100644 (file)
@@ -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 <sys/types.h>
  *     #include <sys/socket.h>
@@ -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");
index 4503aa49610f1a13d55649d37dbfa89c0d9f24ac..3256369d6d189eab13cc7790bc02e32ac1528103 100644 (file)
@@ -3,7 +3,6 @@
 #include <ccan/opt/opt.h>
 #include <ccan/tevent/tevent.h>
 #include <ccan/array_size/array_size.h>
-#include <ccan/noerr/noerr.h>
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
@@ -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;
 }
index e1f3cc70869ae89df3f2dfd4689dd9e3840ad80c..6b9a3e75c0ddce73d0d583ae28ab8af9b9694f59 100644 (file)
@@ -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 */