Further server optimizations:
- merged request and reply structures
- build requests directly into the buffer to avoid a copy

diff --git a/server/request.c b/server/request.c
index a8cab9c..56b394d 100644
--- a/server/request.c
+++ b/server/request.c
@@ -26,55 +26,33 @@
 struct thread *current = NULL;  /* thread handling the current request */
 
 /* complain about a protocol error and terminate the client connection */
-void fatal_protocol_error( const char *err )
+void fatal_protocol_error( struct thread *thread, const char *err, ... )
 {
-    unsigned char *p;
+    va_list args;
 
-    fprintf( stderr, "Protocol error:%p: %s\n    request:", current, err );
-    for (p = (unsigned char *)current->buffer; p < (unsigned char *)current->req_end; p++)
-        fprintf( stderr, " %02x", *p );
-    fprintf( stderr, "\n" );
-    remove_client( current->client, -2 );
+    va_start( args, err );
+    fprintf( stderr, "Protocol error:%p: ", thread );
+    vfprintf( stderr, err, args );
+    va_end( args );
+    remove_client( thread->client, PROTOCOL_ERROR );
 }
 
 /* call a request handler */
-void call_req_handler( struct thread *thread, int fd )
+void call_req_handler( struct thread *thread, enum request req, int fd )
 {
-    const struct handler *handler;
-    struct header *head;
-    unsigned int req, len;
-
     current = thread;
-    assert (current);
-
-    head = (struct header *)current->buffer;
-
-    req = head->type;
-    len = head->len;
-
-    /* set the buffer pointers */
-    current->req_pos = current->reply_pos = (char *)current->buffer + sizeof(struct header);
-    current->req_end = (char *)current->buffer + len;
     clear_error();
 
-    if ((len < sizeof(struct header)) || (len > MAX_MSG_LENGTH)) goto bad_header;
-    if (req >= REQ_NB_REQUESTS) goto bad_header;
-
     if (debug_level) trace_request( req, fd );
 
-    /* now call the handler */
-    handler = &req_handlers[req];
-    if (!check_req_data( handler->min_size )) goto bad_request;
-    handler->handler( get_req_data( handler->min_size ), fd );
-    if (current && current->state != SLEEPING) send_reply( current );
-    current = NULL;
-    return;
-
- bad_header:
-    /* dump only the header */
-    current->req_end = (char *)current->buffer + sizeof(struct header);
- bad_request:
-    fatal_protocol_error( "bad request" );
+    if (req < REQ_NB_REQUESTS)
+    {
+        req_handlers[req].handler( current->buffer, fd );
+        if (current && current->state != SLEEPING) send_reply( current );
+        current = NULL;
+        return;
+    }
+    fatal_protocol_error( current, "bad request %d\n", req );
 }
 
 /* handle a client timeout */
@@ -110,15 +88,8 @@
 /* send a reply to a thread */
 void send_reply( struct thread *thread )
 {
-    struct header *head = thread->buffer;
-    int len = (char *)thread->reply_pos - (char *)thread->buffer;
-
-    assert( len < MAX_MSG_LENGTH );
-
-    head->len  = len;
-    head->type = thread->error;
     if (thread->state == SLEEPING) thread->state = RUNNING;
-    client_reply( thread->client );
+    client_reply( thread->client, thread->error );
 }
 
 /* set the debug level */