2 * Server-side request handling
4 * Copyright (C) 1998 Alexandre Julliard
13 #include <sys/types.h>
23 #define WANT_REQUEST_HANDLERS
26 struct thread *current = NULL; /* thread handling the current request */
28 /* complain about a protocol error and terminate the client connection */
29 void fatal_protocol_error( const char *err )
33 fprintf( stderr, "Protocol error:%p: %s\n request:", current, err );
34 for (p = (unsigned char *)current->buffer; p < (unsigned char *)current->req_end; p++)
35 fprintf( stderr, " %02x", *p );
36 fprintf( stderr, "\n" );
37 remove_client( current->client, -2 );
40 /* call a request handler */
41 void call_req_handler( struct thread *thread, int fd )
43 const struct handler *handler;
45 unsigned int req, len;
50 head = (struct header *)current->buffer;
55 /* set the buffer pointers */
56 current->req_pos = current->reply_pos = (char *)current->buffer + sizeof(struct header);
57 current->req_end = (char *)current->buffer + len;
60 if ((len < sizeof(struct header)) || (len > MAX_MSG_LENGTH)) goto bad_header;
61 if (req >= REQ_NB_REQUESTS) goto bad_header;
63 if (debug_level) trace_request( req, fd );
65 /* now call the handler */
66 handler = &req_handlers[req];
67 if (!check_req_data( handler->min_size )) goto bad_request;
68 handler->handler( get_req_data( handler->min_size ), fd );
69 if (current && current->state != SLEEPING) send_reply( current );
74 /* dump only the header */
75 current->req_end = (char *)current->buffer + sizeof(struct header);
77 fatal_protocol_error( "bad request" );
80 /* handle a client timeout */
81 void call_timeout_handler( void *thread )
83 current = (struct thread *)thread;
84 if (debug_level) trace_timeout();
90 /* a thread has been killed */
91 void call_kill_handler( struct thread *thread, int exit_code )
93 /* must be reentrant WRT call_req_handler */
94 struct thread *old_current = current;
98 if (debug_level) trace_kill( exit_code );
99 thread_killed( current, exit_code );
101 current = (old_current != thread) ? old_current : NULL;
104 /* set the fd to pass to the thread */
105 void set_reply_fd( struct thread *thread, int pass_fd )
107 client_pass_fd( thread->client, pass_fd );
110 /* send a reply to a thread */
111 void send_reply( struct thread *thread )
113 struct header *head = thread->buffer;
114 int len = (char *)thread->reply_pos - (char *)thread->buffer;
116 assert( len < MAX_MSG_LENGTH );
119 head->type = thread->error;
120 if (thread->state == SLEEPING) thread->state = RUNNING;
121 client_reply( thread->client );
124 /* set the debug level */
125 DECL_HANDLER(set_debug)
127 debug_level = req->level;
128 /* Make sure last_req is initialized */
129 current->last_req = REQ_SET_DEBUG;
132 /* debugger support operations */
133 DECL_HANDLER(debugger)
137 case DEBUGGER_FREEZE_ALL:
138 suspend_all_threads();
141 case DEBUGGER_UNFREEZE_ALL:
142 resume_all_threads();