mirror of
git://source.winehq.org/git/wine.git
synced 2024-11-05 18:01:34 +00:00
5bc78089db
A few other optimizations in request processing in the server. Moved automatically generated request definitions to server.h and removed include/server/request.h.
145 lines
3.6 KiB
C
145 lines
3.6 KiB
C
/*
|
|
* Server-side request handling
|
|
*
|
|
* Copyright (C) 1998 Alexandre Julliard
|
|
*/
|
|
|
|
#include <assert.h>
|
|
#include <stdarg.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <signal.h>
|
|
#include <sys/types.h>
|
|
#include <sys/uio.h>
|
|
#include <unistd.h>
|
|
|
|
#include "winerror.h"
|
|
#include "winnt.h"
|
|
#include "winbase.h"
|
|
#include "wincon.h"
|
|
#include "thread.h"
|
|
#include "server.h"
|
|
#define WANT_REQUEST_HANDLERS
|
|
#include "request.h"
|
|
|
|
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 )
|
|
{
|
|
unsigned char *p;
|
|
|
|
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 );
|
|
}
|
|
|
|
/* call a request handler */
|
|
void call_req_handler( struct thread *thread, 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" );
|
|
}
|
|
|
|
/* handle a client timeout */
|
|
void call_timeout_handler( void *thread )
|
|
{
|
|
current = (struct thread *)thread;
|
|
if (debug_level) trace_timeout();
|
|
clear_error();
|
|
thread_timeout();
|
|
current = NULL;
|
|
}
|
|
|
|
/* a thread has been killed */
|
|
void call_kill_handler( struct thread *thread, int exit_code )
|
|
{
|
|
/* must be reentrant WRT call_req_handler */
|
|
struct thread *old_current = current;
|
|
current = thread;
|
|
if (current)
|
|
{
|
|
if (debug_level) trace_kill( exit_code );
|
|
thread_killed( current, exit_code );
|
|
}
|
|
current = (old_current != thread) ? old_current : NULL;
|
|
}
|
|
|
|
/* set the fd to pass to the thread */
|
|
void set_reply_fd( struct thread *thread, int pass_fd )
|
|
{
|
|
client_pass_fd( thread->client, pass_fd );
|
|
}
|
|
|
|
/* 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 );
|
|
}
|
|
|
|
/* set the debug level */
|
|
DECL_HANDLER(set_debug)
|
|
{
|
|
debug_level = req->level;
|
|
/* Make sure last_req is initialized */
|
|
current->last_req = REQ_SET_DEBUG;
|
|
}
|
|
|
|
/* debugger support operations */
|
|
DECL_HANDLER(debugger)
|
|
{
|
|
switch ( req->op )
|
|
{
|
|
case DEBUGGER_FREEZE_ALL:
|
|
suspend_all_threads();
|
|
break;
|
|
|
|
case DEBUGGER_UNFREEZE_ALL:
|
|
resume_all_threads();
|
|
break;
|
|
}
|
|
}
|