Made server communication faster by using a shared memory block.
[wine] / server / request.c
1 /*
2  * Server-side request handling
3  *
4  * Copyright (C) 1998 Alexandre Julliard
5  */
6
7 #include <assert.h>
8 #include <stdarg.h>
9 #include <stdio.h>
10 #include <string.h>
11 #include <stdlib.h>
12 #include <signal.h>
13 #include <sys/types.h>
14 #include <sys/uio.h>
15 #include <unistd.h>
16
17 #include "winerror.h"
18 #include "winnt.h"
19 #include "winbase.h"
20 #include "wincon.h"
21 #include "thread.h"
22 #include "server.h"
23 #define WANT_REQUEST_HANDLERS
24 #include "request.h"
25  
26 struct thread *current = NULL;  /* thread handling the current request */
27
28 /* complain about a protocol error and terminate the client connection */
29 void fatal_protocol_error( const char *err )
30 {
31     unsigned char *p;
32
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 );
38 }
39
40 /* call a request handler */
41 void call_req_handler( struct thread *thread, int fd )
42 {
43     const struct handler *handler;
44     struct header *head;
45     unsigned int req, len;
46
47     current = thread;
48     assert (current);
49
50     head = (struct header *)current->buffer;
51
52     req = head->type;
53     len = head->len;
54
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;
58     clear_error();
59
60     if ((len < sizeof(struct header)) || (len > MAX_MSG_LENGTH)) goto bad_header;
61     if (req >= REQ_NB_REQUESTS) goto bad_header;
62
63     if (debug_level) trace_request( req, fd );
64
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 );
70     current = NULL;
71     return;
72
73  bad_header:
74     /* dump only the header */
75     current->req_end = (char *)current->buffer + sizeof(struct header);
76  bad_request:
77     fatal_protocol_error( "bad request" );
78 }
79
80 /* handle a client timeout */
81 void call_timeout_handler( void *thread )
82 {
83     current = (struct thread *)thread;
84     if (debug_level) trace_timeout();
85     clear_error();
86     thread_timeout();
87     current = NULL;
88 }
89
90 /* a thread has been killed */
91 void call_kill_handler( struct thread *thread, int exit_code )
92 {
93     /* must be reentrant WRT call_req_handler */
94     struct thread *old_current = current;
95     current = thread;
96     if (current)
97     {
98         if (debug_level) trace_kill( exit_code );
99         thread_killed( current, exit_code );
100     }
101     current = (old_current != thread) ? old_current : NULL;
102 }
103
104 /* set the fd to pass to the thread */
105 void set_reply_fd( struct thread *thread, int pass_fd )
106 {
107     client_pass_fd( thread->client, pass_fd );
108 }
109
110 /* send a reply to a thread */
111 void send_reply( struct thread *thread )
112 {
113     struct header *head = thread->buffer;
114     int len = (char *)thread->reply_pos - (char *)thread->buffer;
115
116     assert( len < MAX_MSG_LENGTH );
117
118     head->len  = len;
119     head->type = thread->error;
120     if (thread->state == SLEEPING) thread->state = RUNNING;
121     client_reply( thread->client );
122 }
123
124 /* set the debug level */
125 DECL_HANDLER(set_debug)
126 {
127     debug_level = req->level;
128     /* Make sure last_req is initialized */
129     current->last_req = REQ_SET_DEBUG;
130 }
131
132 /* debugger support operations */
133 DECL_HANDLER(debugger)
134 {
135     switch ( req->op )
136     {
137     case DEBUGGER_FREEZE_ALL:
138         suspend_all_threads();
139         break;
140
141     case DEBUGGER_UNFREEZE_ALL:
142         resume_all_threads();
143         break;
144     }
145 }