+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;
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,
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;
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;
struct set_cursor_reply set_cursor_reply;
};
-#define SERVER_PROTOCOL_VERSION 403
+#define SERVER_PROTOCOL_VERSION 404
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
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);
(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,
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 );
}
}
+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 )
{
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 )))
{
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 )
{
}
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;
}
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 ) )))
{
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 )
{
}
}
+/* 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)
{
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 );
(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,
(dump_func)dump_create_socket_reply,
(dump_func)dump_accept_socket_reply,
NULL,
+ NULL,
(dump_func)dump_get_socket_event_reply,
NULL,
NULL,
"unlock_file",
"create_socket",
"accept_socket",
+ "accept_into_socket",
"set_socket_event",
"get_socket_event",
"enable_socket_event",