Made server communication faster by using a shared memory block.
A few other optimizations in request processing in the server.
Moved automatically generated request definitions to server.h and
removed include/server/request.h.

diff --git a/server/socket.c b/server/socket.c
index 915de42..9b78e07 100644
--- a/server/socket.c
+++ b/server/socket.c
@@ -18,32 +18,19 @@
 #include <unistd.h>
 
 #include "config.h"
-#include "server.h"
 #include "object.h"
+#include "request.h"
 
 /* Some versions of glibc don't define this */
 #ifndef SCM_RIGHTS
 #define SCM_RIGHTS 1
 #endif
 
-/* client state */
-enum state
-{
-    RUNNING,   /* running normally */
-    SENDING,   /* sending us a request */
-    WAITING,   /* waiting for us to reply */
-    READING    /* reading our reply */
-};
-
 /* client structure */
 struct client
 {
-    enum state           state;      /* client state */
     struct select_user   select;     /* select user */
     unsigned int         seq;        /* current sequence number */
-    struct header        head;       /* current msg header */
-    char                *data;       /* current msg data */
-    int                  count;      /* bytes sent/received so far */
     int                  pass_fd;    /* fd to pass to and from the client */
     struct thread       *self;       /* client thread (opaque pointer) */
     struct timeout_user *timeout;    /* current timeout (opaque pointer) */
@@ -62,110 +49,81 @@
     va_list args;
 
     va_start( args, err );
-    fprintf( stderr, "Protocol error:%d: ", client->select.fd );
+    fprintf( stderr, "Protocol error:%p: ", client->self );
     vfprintf( stderr, err, args );
     va_end( args );
+    remove_client( client, PROTOCOL_ERROR );
 }
 
 /* send a message to a client that is ready to receive something */
-static void do_write( struct client *client, int client_fd )
+static void do_write( struct client *client )
 {
-    struct iovec vec[2];
-#ifndef HAVE_MSGHDR_ACCRIGHTS
-    struct cmsg_fd cmsg;
-#endif
-    struct msghdr msghdr;
     int ret;
 
-    /* make sure we have something to send */
-    assert( client->count < client->head.len );
-    /* make sure the client is listening */
-    assert( client->state == READING );
-
-    msghdr.msg_name = NULL;
-    msghdr.msg_namelen = 0;
-    msghdr.msg_iov = vec;
-
-    if (client->count < sizeof(client->head))
+    if (client->pass_fd == -1)
     {
-        vec[0].iov_base = (char *)&client->head + client->count;
-        vec[0].iov_len  = sizeof(client->head) - client->count;
-        vec[1].iov_base = client->data;
-        vec[1].iov_len  = client->head.len - sizeof(client->head);
-        msghdr.msg_iovlen = 2;
+        ret = write( client->select.fd, &client->seq, sizeof(client->seq) );
     }
-    else
+    else  /* we have an fd to send */
     {
-        vec[0].iov_base = client->data + client->count - sizeof(client->head);
-        vec[0].iov_len  = client->head.len - client->count;
-        msghdr.msg_iovlen = 1;
-    }
+        struct iovec vec;
+        struct msghdr msghdr;
 
 #ifdef HAVE_MSGHDR_ACCRIGHTS
-    if (client->pass_fd != -1)  /* we have an fd to send */
-    {
         msghdr.msg_accrights = (void *)&client->pass_fd;
         msghdr.msg_accrightslen = sizeof(client->pass_fd);
-    }
-    else
-    {
-        msghdr.msg_accrights = NULL;
-        msghdr.msg_accrightslen = 0;
-    }
 #else  /* HAVE_MSGHDR_ACCRIGHTS */
-    if (client->pass_fd != -1)  /* we have an fd to send */
-    {
-        cmsg.len = sizeof(cmsg);
+        struct cmsg_fd cmsg;
+
+        cmsg.len   = sizeof(cmsg);
         cmsg.level = SOL_SOCKET;
-        cmsg.type = SCM_RIGHTS;
-        cmsg.fd = client->pass_fd;
-        msghdr.msg_control = &cmsg;
+        cmsg.type  = SCM_RIGHTS;
+        cmsg.fd    = client->pass_fd;
+        msghdr.msg_control    = &cmsg;
         msghdr.msg_controllen = sizeof(cmsg);
-    }
-    else
-    {
-        msghdr.msg_control = NULL;
-        msghdr.msg_controllen = 0;
-    }
-    msghdr.msg_flags = 0;
+        msghdr.msg_flags      = 0;
 #endif  /* HAVE_MSGHDR_ACCRIGHTS */
 
-    ret = sendmsg( client_fd, &msghdr, 0 );
+        msghdr.msg_name    = NULL;
+        msghdr.msg_namelen = 0;
+        msghdr.msg_iov     = &vec;
+        msghdr.msg_iovlen  = 1;
+        vec.iov_base = (char *)&client->seq;
+        vec.iov_len  = sizeof(client->seq);
+
+        ret = sendmsg( client->select.fd, &msghdr, 0 );
+        close( client->pass_fd );
+        client->pass_fd = -1;
+    }
+    if (ret == sizeof(client->seq))
+    {
+        /* everything OK */
+        client->seq++;
+        set_select_events( &client->select, READ_EVENT );
+        return;
+    }
     if (ret == -1)
     {
         if (errno != EPIPE) perror("sendmsg");
         remove_client( client, BROKEN_PIPE );
         return;
     }
-    if (client->pass_fd != -1)  /* We sent the fd, now we can close it */
-    {
-        close( client->pass_fd );
-        client->pass_fd = -1;
-    }
-    if ((client->count += ret) < client->head.len) return;
-
-    /* we have finished with this message */
-    if (client->data) free( client->data );
-    client->data  = NULL;
-    client->count = 0;
-    client->state = RUNNING;
-    client->seq++;
-    set_select_events( &client->select, READ_EVENT );
+    fprintf( stderr, "Partial sequence sent (%d)\n", ret );
+    remove_client( client, BROKEN_PIPE );
 }
 
 
 /* read a message from a client that has something to say */
-static void do_read( struct client *client, int client_fd )
+static void do_read( struct client *client )
 {
     struct iovec vec;
-    int pass_fd = -1;
-    int ret;
+    int ret, seq;
 
 #ifdef HAVE_MSGHDR_ACCRIGHTS
     struct msghdr msghdr;
 
-    msghdr.msg_accrights    = (void *)&pass_fd;
-    msghdr.msg_accrightslen = sizeof(int);
+    msghdr.msg_accrights    = (void *)&client->pass_fd;
+    msghdr.msg_accrightslen = sizeof(client->pass_fd);
 #else  /* HAVE_MSGHDR_ACCRIGHTS */
     struct msghdr msghdr;
     struct cmsg_fd cmsg;
@@ -179,109 +137,57 @@
     msghdr.msg_flags      = 0;
 #endif  /* HAVE_MSGHDR_ACCRIGHTS */
 
+    assert( client->pass_fd == -1 );
+
     msghdr.msg_name    = NULL;
     msghdr.msg_namelen = 0;
     msghdr.msg_iov     = &vec;
     msghdr.msg_iovlen  = 1;
 
-    if (client->count < sizeof(client->head))
+    vec.iov_base = &seq;
+    vec.iov_len  = sizeof(seq);
+
+    ret = recvmsg( client->select.fd, &msghdr, 0 );
+#ifndef HAVE_MSGHDR_ACCRIGHTS
+    client->pass_fd = cmsg.fd;
+#endif
+
+    if (ret == sizeof(seq))
     {
-        vec.iov_base = (char *)&client->head + client->count;
-        vec.iov_len  = sizeof(client->head) - client->count;
-    }
-    else
-    {
-        if (!client->data &&
-            !(client->data = malloc(client->head.len-sizeof(client->head))))
+        int pass_fd = client->pass_fd;
+        if (seq != client->seq++)
         {
-            remove_client( client, OUT_OF_MEMORY );
+            protocol_error( client, "bad sequence %08x instead of %08x\n",
+                            seq, client->seq - 1 );
             return;
         }
-        vec.iov_base = client->data + client->count - sizeof(client->head);
-        vec.iov_len  = client->head.len - client->count;
+        client->pass_fd = -1;
+        call_req_handler( client->self, pass_fd );
+        if (pass_fd != -1) close( pass_fd );
+        return;
     }
-
-    ret = recvmsg( client_fd, &msghdr, 0 );
     if (ret == -1)
     {
         perror("recvmsg");
         remove_client( client, BROKEN_PIPE );
         return;
     }
-#ifndef HAVE_MSGHDR_ACCRIGHTS
-    pass_fd = cmsg.fd;
-#endif
-    if (pass_fd != -1)
-    {
-        /* can only receive one fd per message */
-        if (client->pass_fd != -1) close( client->pass_fd );
-        client->pass_fd = pass_fd;
-    }
-    else if (!ret)  /* closed pipe */
+    if (!ret)  /* closed pipe */
     {
         remove_client( client, BROKEN_PIPE );
         return;
     }
-
-    if (client->state == RUNNING) client->state = SENDING;
-    assert( client->state == SENDING );
-
-    client->count += ret;
-
-    /* received the complete header yet? */
-    if (client->count < sizeof(client->head)) return;
-
-    /* sanity checks */
-    if (client->head.seq != client->seq)
-    {
-        protocol_error( client, "bad sequence %08x instead of %08x\n",
-                        client->head.seq, client->seq );
-        remove_client( client, PROTOCOL_ERROR );
-        return;
-    }
-    if ((client->head.len < sizeof(client->head)) ||
-        (client->head.len > MAX_MSG_LENGTH + sizeof(client->head)))
-    {
-        protocol_error( client, "bad header length %08x\n",
-                        client->head.len );
-        remove_client( client, PROTOCOL_ERROR );
-        return;
-    }
-
-    /* received the whole message? */
-    if (client->count == client->head.len)
-    {
-        /* done reading the data, call the callback function */
-
-        int len = client->head.len - sizeof(client->head);
-        char *data = client->data;
-        int passed_fd = client->pass_fd;
-        enum request type = client->head.type;
-
-        /* clear the info now, as the client may be deleted by the callback */
-        client->head.len  = 0;
-        client->head.type = 0;
-        client->count     = 0;
-        client->data      = NULL;
-        client->pass_fd   = -1;
-        client->state     = WAITING;
-        client->seq++;
-
-        call_req_handler( client->self, type, data, len, passed_fd );
-        if (passed_fd != -1) close( passed_fd );
-        if (data) free( data );
-    }
+    protocol_error( client, "partial sequence received %d/%d\n", ret, sizeof(seq) );
 }
 
 /* handle a client event */
 static void client_event( int event, void *private )
 {
     struct client *client = (struct client *)private;
-    if (event & WRITE_EVENT) do_write( client, client->select.fd );
-    if (event & READ_EVENT) do_read( client, client->select.fd );
+    if (event & WRITE_EVENT) do_write( client );
+    if (event & READ_EVENT) do_read( client );
 }
 
-
 /*******************************************************************/
 /* server-side exported functions                                  */
 
@@ -295,15 +201,10 @@
     flags = fcntl( fd, F_GETFL, 0 );
     fcntl( fd, F_SETFL, flags | O_NONBLOCK );
 
-    client->state                = RUNNING;
     client->select.fd            = fd;
     client->select.func          = client_event;
     client->select.private       = client;
     client->seq                  = 0;
-    client->head.len             = 0;
-    client->head.type            = 0;
-    client->count                = 0;
-    client->data                 = NULL;
     client->self                 = self;
     client->timeout              = NULL;
     client->pass_fd              = -1;
@@ -324,42 +225,20 @@
     close( client->select.fd );
 
     /* Purge messages */
-    if (client->data) free( client->data );
     if (client->pass_fd != -1) close( client->pass_fd );
     free( client );
 }
 
-/* send a reply to a client */
-int send_reply_v( struct client *client, int type, int pass_fd,
-                  struct iovec *vec, int veclen )
+/* set the fd to pass to the client */
+void client_pass_fd( struct client *client, int pass_fd )
 {
-    int i;
-    unsigned int len;
-    char *p;
+    assert( client->pass_fd == -1 );
+    client->pass_fd = pass_fd;
+}
 
-    assert( client );
-    assert( client->state == WAITING );
-    assert( !client->data );
-
-    if (debug_level) trace_reply( client->self, type, pass_fd, vec, veclen );
-
-    for (i = len = 0; i < veclen; i++) len += vec[i].iov_len;
-    assert( len < MAX_MSG_LENGTH );
-
-    if (len && !(client->data = malloc( len ))) return -1;
-    client->count     = 0;
-    client->head.len  = len + sizeof(client->head);
-    client->head.type = type;
-    client->head.seq  = client->seq;
-    client->pass_fd   = pass_fd;
-
-    for (i = 0, p = client->data; i < veclen; i++)
-    {
-        memcpy( p, vec[i].iov_base, vec[i].iov_len );
-        p += vec[i].iov_len;
-    }
-
-    client->state = READING;
+/* send a reply to a client */
+void client_reply( struct client *client )
+{
+    if (debug_level) trace_reply( client->self, client->pass_fd );
     set_select_events( &client->select, WRITE_EVENT );
-    return 0;
 }