server: Add accept_into_socket to accept into an initialized socket.
This commit is contained in:
parent
92b83ddffb
commit
ae5ad61fa8
|
@ -1344,6 +1344,20 @@ struct accept_socket_reply
|
|||
|
||||
|
||||
|
||||
struct accept_into_socket_request
|
||||
{
|
||||
struct request_header __header;
|
||||
obj_handle_t lhandle;
|
||||
obj_handle_t ahandle;
|
||||
char __pad_20[4];
|
||||
};
|
||||
struct accept_into_socket_reply
|
||||
{
|
||||
struct reply_header __header;
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct set_socket_event_request
|
||||
{
|
||||
struct request_header __header;
|
||||
|
@ -4791,6 +4805,7 @@ enum request
|
|||
REQ_unlock_file,
|
||||
REQ_create_socket,
|
||||
REQ_accept_socket,
|
||||
REQ_accept_into_socket,
|
||||
REQ_set_socket_event,
|
||||
REQ_get_socket_event,
|
||||
REQ_enable_socket_event,
|
||||
|
@ -5040,6 +5055,7 @@ union generic_request
|
|||
struct unlock_file_request unlock_file_request;
|
||||
struct create_socket_request create_socket_request;
|
||||
struct accept_socket_request accept_socket_request;
|
||||
struct accept_into_socket_request accept_into_socket_request;
|
||||
struct set_socket_event_request set_socket_event_request;
|
||||
struct get_socket_event_request get_socket_event_request;
|
||||
struct enable_socket_event_request enable_socket_event_request;
|
||||
|
@ -5287,6 +5303,7 @@ union generic_reply
|
|||
struct unlock_file_reply unlock_file_reply;
|
||||
struct create_socket_reply create_socket_reply;
|
||||
struct accept_socket_reply accept_socket_reply;
|
||||
struct accept_into_socket_reply accept_into_socket_reply;
|
||||
struct set_socket_event_reply set_socket_event_reply;
|
||||
struct get_socket_event_reply get_socket_event_reply;
|
||||
struct enable_socket_event_reply enable_socket_event_reply;
|
||||
|
@ -5487,6 +5504,6 @@ union generic_reply
|
|||
struct set_cursor_reply set_cursor_reply;
|
||||
};
|
||||
|
||||
#define SERVER_PROTOCOL_VERSION 403
|
||||
#define SERVER_PROTOCOL_VERSION 404
|
||||
|
||||
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
|
||||
|
|
24
server/fd.c
24
server/fd.c
|
@ -1599,32 +1599,20 @@ struct fd *alloc_pseudo_fd( const struct fd_ops *fd_user_ops, struct object *use
|
|||
/* duplicate an fd object for a different user */
|
||||
struct fd *dup_fd_object( struct fd *orig, unsigned int access, unsigned int sharing, unsigned int options )
|
||||
{
|
||||
struct fd *fd = alloc_object( &fd_ops );
|
||||
struct fd *fd = alloc_fd_object();
|
||||
|
||||
if (!fd) return NULL;
|
||||
|
||||
fd->fd_ops = NULL;
|
||||
fd->user = NULL;
|
||||
fd->inode = NULL;
|
||||
fd->closed = NULL;
|
||||
fd->access = access;
|
||||
fd->options = options;
|
||||
fd->sharing = sharing;
|
||||
fd->unix_fd = -1;
|
||||
fd->cacheable = orig->cacheable;
|
||||
fd->signaled = 0;
|
||||
fd->fs_locks = 0;
|
||||
fd->poll_index = -1;
|
||||
fd->read_q = NULL;
|
||||
fd->write_q = NULL;
|
||||
fd->wait_q = NULL;
|
||||
fd->completion = NULL;
|
||||
list_init( &fd->inode_entry );
|
||||
list_init( &fd->locks );
|
||||
|
||||
if (!(fd->unix_name = mem_alloc( strlen(orig->unix_name) + 1 ))) goto failed;
|
||||
strcpy( fd->unix_name, orig->unix_name );
|
||||
if ((fd->poll_index = add_poll_user( fd )) == -1) goto failed;
|
||||
if (orig->unix_name)
|
||||
{
|
||||
if (!(fd->unix_name = mem_alloc( strlen(orig->unix_name) + 1 ))) goto failed;
|
||||
strcpy( fd->unix_name, orig->unix_name );
|
||||
}
|
||||
|
||||
if (orig->inode)
|
||||
{
|
||||
|
|
|
@ -1089,6 +1089,13 @@ enum server_fd_type
|
|||
@END
|
||||
|
||||
|
||||
/* Accept into an initialized socket */
|
||||
@REQ(accept_into_socket)
|
||||
obj_handle_t lhandle; /* handle to the listening socket */
|
||||
obj_handle_t ahandle; /* handle to the accepting socket */
|
||||
@END
|
||||
|
||||
|
||||
/* Set socket event parameters */
|
||||
@REQ(set_socket_event)
|
||||
obj_handle_t handle; /* handle to the socket */
|
||||
|
|
|
@ -155,6 +155,7 @@ DECL_HANDLER(lock_file);
|
|||
DECL_HANDLER(unlock_file);
|
||||
DECL_HANDLER(create_socket);
|
||||
DECL_HANDLER(accept_socket);
|
||||
DECL_HANDLER(accept_into_socket);
|
||||
DECL_HANDLER(set_socket_event);
|
||||
DECL_HANDLER(get_socket_event);
|
||||
DECL_HANDLER(enable_socket_event);
|
||||
|
@ -403,6 +404,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
|
|||
(req_handler)req_unlock_file,
|
||||
(req_handler)req_create_socket,
|
||||
(req_handler)req_accept_socket,
|
||||
(req_handler)req_accept_into_socket,
|
||||
(req_handler)req_set_socket_event,
|
||||
(req_handler)req_get_socket_event,
|
||||
(req_handler)req_enable_socket_event,
|
||||
|
@ -924,6 +926,9 @@ C_ASSERT( FIELD_OFFSET(struct accept_socket_request, attributes) == 20 );
|
|||
C_ASSERT( sizeof(struct accept_socket_request) == 24 );
|
||||
C_ASSERT( FIELD_OFFSET(struct accept_socket_reply, handle) == 8 );
|
||||
C_ASSERT( sizeof(struct accept_socket_reply) == 16 );
|
||||
C_ASSERT( FIELD_OFFSET(struct accept_into_socket_request, lhandle) == 12 );
|
||||
C_ASSERT( FIELD_OFFSET(struct accept_into_socket_request, ahandle) == 16 );
|
||||
C_ASSERT( sizeof(struct accept_into_socket_request) == 24 );
|
||||
C_ASSERT( FIELD_OFFSET(struct set_socket_event_request, handle) == 12 );
|
||||
C_ASSERT( FIELD_OFFSET(struct set_socket_event_request, mask) == 16 );
|
||||
C_ASSERT( FIELD_OFFSET(struct set_socket_event_request, event) == 20 );
|
||||
|
|
162
server/sock.c
162
server/sock.c
|
@ -605,6 +605,26 @@ static void sock_destroy( struct object *obj )
|
|||
}
|
||||
}
|
||||
|
||||
static void init_sock(struct sock *sock)
|
||||
{
|
||||
sock->state = 0;
|
||||
sock->mask = 0;
|
||||
sock->hmask = 0;
|
||||
sock->pmask = 0;
|
||||
sock->polling = 0;
|
||||
sock->flags = 0;
|
||||
sock->type = 0;
|
||||
sock->family = 0;
|
||||
sock->event = NULL;
|
||||
sock->window = 0;
|
||||
sock->message = 0;
|
||||
sock->wparam = 0;
|
||||
sock->deferred = NULL;
|
||||
sock->read_q = NULL;
|
||||
sock->write_q = NULL;
|
||||
memset( sock->errors, 0, sizeof(sock->errors) );
|
||||
}
|
||||
|
||||
/* create a new and unconnected socket */
|
||||
static struct object *create_socket( int family, int type, int protocol, unsigned int flags )
|
||||
{
|
||||
|
@ -625,22 +645,12 @@ static struct object *create_socket( int family, int type, int protocol, unsigne
|
|||
close( sockfd );
|
||||
return NULL;
|
||||
}
|
||||
sock->state = (type != SOCK_STREAM) ? (FD_READ|FD_WRITE) : 0;
|
||||
sock->mask = 0;
|
||||
sock->hmask = 0;
|
||||
sock->pmask = 0;
|
||||
sock->polling = 0;
|
||||
sock->flags = flags;
|
||||
sock->type = type;
|
||||
sock->family = family;
|
||||
sock->event = NULL;
|
||||
sock->window = 0;
|
||||
sock->message = 0;
|
||||
sock->wparam = 0;
|
||||
sock->deferred = NULL;
|
||||
sock->read_q = NULL;
|
||||
sock->write_q = NULL;
|
||||
memset( sock->errors, 0, sizeof(sock->errors) );
|
||||
init_sock( sock );
|
||||
sock->state = (type != SOCK_STREAM) ? (FD_READ|FD_WRITE) : 0;
|
||||
sock->flags = flags;
|
||||
sock->type = type;
|
||||
sock->family = family;
|
||||
|
||||
if (!(sock->fd = create_anonymous_fd( &sock_fd_ops, sockfd, &sock->obj,
|
||||
(flags & WSA_FLAG_OVERLAPPED) ? 0 : FILE_SYNCHRONOUS_IO_NONALERT )))
|
||||
{
|
||||
|
@ -652,17 +662,38 @@ static struct object *create_socket( int family, int type, int protocol, unsigne
|
|||
return &sock->obj;
|
||||
}
|
||||
|
||||
/* accepts a socket and inits it */
|
||||
static int accept_new_fd( struct sock *sock )
|
||||
{
|
||||
|
||||
/* Try to accept(2). We can't be safe that this an already connected socket
|
||||
* or that accept() is allowed on it. In those cases we will get -1/errno
|
||||
* return.
|
||||
*/
|
||||
int acceptfd;
|
||||
struct sockaddr saddr;
|
||||
unsigned int slen = sizeof(saddr);
|
||||
acceptfd = accept( get_unix_fd(sock->fd), &saddr, &slen);
|
||||
if (acceptfd == -1)
|
||||
{
|
||||
sock_set_error();
|
||||
return acceptfd;
|
||||
}
|
||||
|
||||
fcntl(acceptfd, F_SETFL, O_NONBLOCK); /* make socket nonblocking */
|
||||
return acceptfd;
|
||||
}
|
||||
|
||||
/* accept a socket (creates a new fd) */
|
||||
static struct sock *accept_socket( obj_handle_t handle )
|
||||
{
|
||||
struct sock *acceptsock;
|
||||
struct sock *sock;
|
||||
int acceptfd;
|
||||
struct sockaddr saddr;
|
||||
|
||||
sock = (struct sock *)get_handle_obj( current->process, handle, FILE_READ_DATA, &sock_ops );
|
||||
if (!sock)
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
if ( sock->deferred )
|
||||
{
|
||||
|
@ -671,16 +702,8 @@ static struct sock *accept_socket( obj_handle_t handle )
|
|||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Try to accept(2). We can't be safe that this an already connected socket
|
||||
* or that accept() is allowed on it. In those cases we will get -1/errno
|
||||
* return.
|
||||
*/
|
||||
unsigned int slen = sizeof(saddr);
|
||||
acceptfd = accept( get_unix_fd(sock->fd), &saddr, &slen);
|
||||
if (acceptfd==-1)
|
||||
if ((acceptfd = accept_new_fd( sock )) == -1)
|
||||
{
|
||||
sock_set_error();
|
||||
release_object( sock );
|
||||
return NULL;
|
||||
}
|
||||
|
@ -691,27 +714,18 @@ static struct sock *accept_socket( obj_handle_t handle )
|
|||
return NULL;
|
||||
}
|
||||
|
||||
init_sock( acceptsock );
|
||||
/* newly created socket gets the same properties of the listening socket */
|
||||
fcntl(acceptfd, F_SETFL, O_NONBLOCK); /* make socket nonblocking */
|
||||
acceptsock->state = FD_WINE_CONNECTED|FD_READ|FD_WRITE;
|
||||
if (sock->state & FD_WINE_NONBLOCKING)
|
||||
acceptsock->state |= FD_WINE_NONBLOCKING;
|
||||
acceptsock->mask = sock->mask;
|
||||
acceptsock->hmask = 0;
|
||||
acceptsock->pmask = 0;
|
||||
acceptsock->polling = 0;
|
||||
acceptsock->type = sock->type;
|
||||
acceptsock->family = sock->family;
|
||||
acceptsock->event = NULL;
|
||||
acceptsock->window = sock->window;
|
||||
acceptsock->message = sock->message;
|
||||
acceptsock->wparam = 0;
|
||||
if (sock->event) acceptsock->event = (struct event *)grab_object( sock->event );
|
||||
acceptsock->flags = sock->flags;
|
||||
acceptsock->deferred = NULL;
|
||||
acceptsock->read_q = NULL;
|
||||
acceptsock->write_q = NULL;
|
||||
memset( acceptsock->errors, 0, sizeof(acceptsock->errors) );
|
||||
if (!(acceptsock->fd = create_anonymous_fd( &sock_fd_ops, acceptfd, &acceptsock->obj,
|
||||
get_fd_options( sock->fd ) )))
|
||||
{
|
||||
|
@ -728,6 +742,54 @@ static struct sock *accept_socket( obj_handle_t handle )
|
|||
return acceptsock;
|
||||
}
|
||||
|
||||
static int accept_into_socket( struct sock *sock, struct sock *acceptsock )
|
||||
{
|
||||
int acceptfd;
|
||||
struct fd *newfd;
|
||||
if ( sock->deferred )
|
||||
{
|
||||
newfd = dup_fd_object( sock->deferred->fd, 0, 0,
|
||||
get_fd_options( acceptsock->fd ) );
|
||||
if ( !newfd )
|
||||
return FALSE;
|
||||
|
||||
set_fd_user( newfd, &sock_fd_ops, &acceptsock->obj );
|
||||
|
||||
release_object( sock->deferred );
|
||||
sock->deferred = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((acceptfd = accept_new_fd( sock )) == -1)
|
||||
return FALSE;
|
||||
|
||||
if (!(newfd = create_anonymous_fd( &sock_fd_ops, acceptfd, &acceptsock->obj,
|
||||
get_fd_options( acceptsock->fd ) )))
|
||||
{
|
||||
close( acceptfd );
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
acceptsock->state |= FD_WINE_CONNECTED|FD_READ|FD_WRITE;
|
||||
acceptsock->hmask = 0;
|
||||
acceptsock->pmask = 0;
|
||||
acceptsock->polling = 0;
|
||||
acceptsock->type = sock->type;
|
||||
acceptsock->family = sock->family;
|
||||
acceptsock->wparam = 0;
|
||||
acceptsock->deferred = NULL;
|
||||
if (acceptsock->fd) release_object( acceptsock->fd );
|
||||
acceptsock->fd = newfd;
|
||||
|
||||
clear_error();
|
||||
sock->pmask &= ~FD_ACCEPT;
|
||||
sock->hmask &= ~FD_ACCEPT;
|
||||
sock_reselect( sock );
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* set the last error depending on errno */
|
||||
static int sock_get_error( int err )
|
||||
{
|
||||
|
@ -877,6 +939,32 @@ DECL_HANDLER(accept_socket)
|
|||
}
|
||||
}
|
||||
|
||||
/* accept a socket into an initialized socket */
|
||||
DECL_HANDLER(accept_into_socket)
|
||||
{
|
||||
struct sock *sock, *acceptsock;
|
||||
const int all_attributes = FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES|FILE_READ_DATA;
|
||||
|
||||
if (!(sock = (struct sock *)get_handle_obj( current->process, req->lhandle,
|
||||
all_attributes, &sock_ops)))
|
||||
return;
|
||||
|
||||
if (!(acceptsock = (struct sock *)get_handle_obj( current->process, req->ahandle,
|
||||
all_attributes, &sock_ops)))
|
||||
{
|
||||
release_object( sock );
|
||||
return;
|
||||
}
|
||||
|
||||
if (accept_into_socket( sock, acceptsock ))
|
||||
{
|
||||
acceptsock->wparam = req->ahandle; /* wparam for message is the socket handle */
|
||||
sock_reselect( acceptsock );
|
||||
}
|
||||
release_object( acceptsock );
|
||||
release_object( sock );
|
||||
}
|
||||
|
||||
/* set socket event parameters */
|
||||
DECL_HANDLER(set_socket_event)
|
||||
{
|
||||
|
|
|
@ -1539,6 +1539,12 @@ static void dump_accept_socket_reply( const struct accept_socket_reply *req )
|
|||
fprintf( stderr, " handle=%04x", req->handle );
|
||||
}
|
||||
|
||||
static void dump_accept_into_socket_request( const struct accept_into_socket_request *req )
|
||||
{
|
||||
fprintf( stderr, " lhandle=%04x", req->lhandle );
|
||||
fprintf( stderr, ", ahandle=%04x", req->ahandle );
|
||||
}
|
||||
|
||||
static void dump_set_socket_event_request( const struct set_socket_event_request *req )
|
||||
{
|
||||
fprintf( stderr, " handle=%04x", req->handle );
|
||||
|
@ -3874,6 +3880,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
|
|||
(dump_func)dump_unlock_file_request,
|
||||
(dump_func)dump_create_socket_request,
|
||||
(dump_func)dump_accept_socket_request,
|
||||
(dump_func)dump_accept_into_socket_request,
|
||||
(dump_func)dump_set_socket_event_request,
|
||||
(dump_func)dump_get_socket_event_request,
|
||||
(dump_func)dump_enable_socket_event_request,
|
||||
|
@ -4120,6 +4127,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
|
|||
(dump_func)dump_create_socket_reply,
|
||||
(dump_func)dump_accept_socket_reply,
|
||||
NULL,
|
||||
NULL,
|
||||
(dump_func)dump_get_socket_event_reply,
|
||||
NULL,
|
||||
NULL,
|
||||
|
@ -4364,6 +4372,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
|
|||
"unlock_file",
|
||||
"create_socket",
|
||||
"accept_socket",
|
||||
"accept_into_socket",
|
||||
"set_socket_event",
|
||||
"get_socket_event",
|
||||
"enable_socket_event",
|
||||
|
|
Loading…
Reference in New Issue