Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
85a615f1
Commit
85a615f1
authored
May 26, 2021
by
Zebediah Figura
Committed by
Alexandre Julliard
May 27, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ntdll: Introduce IOCTL_AFD_WINE_SENDMSG.
Signed-off-by:
Zebediah Figura
<
z.figura12@gmail.com
>
Signed-off-by:
Alexandre Julliard
<
julliard@winehq.org
>
parent
ac3ec2d9
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
456 additions
and
15 deletions
+456
-15
socket.c
dlls/ntdll/unix/socket.c
+303
-7
afd.h
include/wine/afd.h
+11
-0
server_protocol.h
include/wine/server_protocol.h
+21
-1
protocol.def
server/protocol.def
+11
-0
request.h
server/request.h
+9
-0
sock.c
server/sock.c
+85
-7
trace.c
server/trace.c
+16
-0
No files found.
dlls/ntdll/unix/socket.c
View file @
85a615f1
...
...
@@ -89,6 +89,19 @@ static NTSTATUS wait_async( HANDLE handle, BOOL alertable )
return
NtWaitForSingleObject
(
handle
,
alertable
,
NULL
);
}
union
unix_sockaddr
{
struct
sockaddr
addr
;
struct
sockaddr_in
in
;
struct
sockaddr_in6
in6
;
#ifdef HAS_IPX
struct
sockaddr_ipx
ipx
;
#endif
#ifdef HAS_IRDA
struct
sockaddr_irda
irda
;
#endif
};
struct
async_recv_ioctl
{
struct
async_fileio
io
;
...
...
@@ -101,6 +114,18 @@ struct async_recv_ioctl
struct
iovec
iov
[
1
];
};
struct
async_send_ioctl
{
struct
async_fileio
io
;
const
struct
WS_sockaddr
*
addr
;
int
addr_len
;
int
unix_flags
;
unsigned
int
sent_len
;
unsigned
int
count
;
unsigned
int
iov_cursor
;
struct
iovec
iov
[
1
];
};
static
NTSTATUS
sock_errno_to_status
(
int
err
)
{
switch
(
err
)
...
...
@@ -147,18 +172,108 @@ static NTSTATUS sock_errno_to_status( int err )
}
}
union
unix_sockaddr
static
socklen_t
sockaddr_to_unix
(
const
struct
WS_sockaddr
*
wsaddr
,
int
wsaddrlen
,
union
unix_sockaddr
*
uaddr
)
{
struct
sockaddr
addr
;
struct
sockaddr_in
in
;
struct
sockaddr_in6
in6
;
memset
(
uaddr
,
0
,
sizeof
(
*
uaddr
)
);
switch
(
wsaddr
->
sa_family
)
{
case
WS_AF_INET
:
{
struct
WS_sockaddr_in
win
=
{
0
};
if
(
wsaddrlen
<
sizeof
(
win
))
return
0
;
memcpy
(
&
win
,
wsaddr
,
sizeof
(
win
)
);
uaddr
->
in
.
sin_family
=
AF_INET
;
uaddr
->
in
.
sin_port
=
win
.
sin_port
;
memcpy
(
&
uaddr
->
in
.
sin_addr
,
&
win
.
sin_addr
,
sizeof
(
win
.
sin_addr
)
);
return
sizeof
(
uaddr
->
in
);
}
case
WS_AF_INET6
:
{
struct
WS_sockaddr_in6
win
=
{
0
};
if
(
wsaddrlen
<
sizeof
(
struct
WS_sockaddr_in6_old
))
return
0
;
if
(
wsaddrlen
<
sizeof
(
struct
WS_sockaddr_in6
))
memcpy
(
&
win
,
wsaddr
,
sizeof
(
struct
WS_sockaddr_in6_old
)
);
else
memcpy
(
&
win
,
wsaddr
,
sizeof
(
struct
WS_sockaddr_in6
)
);
uaddr
->
in6
.
sin6_family
=
AF_INET6
;
uaddr
->
in6
.
sin6_port
=
win
.
sin6_port
;
uaddr
->
in6
.
sin6_flowinfo
=
win
.
sin6_flowinfo
;
memcpy
(
&
uaddr
->
in6
.
sin6_addr
,
&
win
.
sin6_addr
,
sizeof
(
win
.
sin6_addr
)
);
#ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID
if
(
wsaddrlen
>=
sizeof
(
struct
WS_sockaddr_in6
))
uaddr
->
in6
.
sin6_scope_id
=
win
.
sin6_scope_id
;
#endif
return
sizeof
(
uaddr
->
in6
);
}
#ifdef HAS_IPX
struct
sockaddr_ipx
ipx
;
case
WS_AF_IPX
:
{
struct
WS_sockaddr_ipx
win
=
{
0
};
if
(
wsaddrlen
<
sizeof
(
win
))
return
0
;
memcpy
(
&
win
,
wsaddr
,
sizeof
(
win
)
);
uaddr
->
ipx
.
sipx_family
=
AF_IPX
;
memcpy
(
&
uaddr
->
ipx
.
sipx_network
,
win
.
sa_netnum
,
sizeof
(
win
.
sa_netnum
)
);
memcpy
(
&
uaddr
->
ipx
.
sipx_node
,
win
.
sa_nodenum
,
sizeof
(
win
.
sa_nodenum
)
);
uaddr
->
ipx
.
sipx_port
=
win
.
sa_socket
;
return
sizeof
(
uaddr
->
ipx
);
}
#endif
#ifdef HAS_IRDA
case
WS_AF_IRDA
:
{
SOCKADDR_IRDA
win
=
{
0
};
unsigned
int
lsap_sel
;
if
(
wsaddrlen
<
sizeof
(
win
))
return
0
;
memcpy
(
&
win
,
wsaddr
,
sizeof
(
win
)
);
uaddr
->
irda
.
sir_family
=
AF_IRDA
;
if
(
sscanf
(
win
.
irdaServiceName
,
"LSAP-SEL%u"
,
&
lsap_sel
)
==
1
)
uaddr
->
sir_lsap_sel
=
lsap_sel
;
else
{
uaddr
->
sir_lsap_sel
=
LSAP_ANY
;
memcpy
(
uaddr
->
irda
.
sir_name
,
win
.
irdaServiceName
,
sizeof
(
win
.
irdaServiceName
)
);
}
memcpy
(
&
uaddr
->
irda
.
sir_addr
,
win
.
irdaDeviceID
,
sizeof
(
win
.
irdaDeviceID
)
);
return
sizeof
(
uaddr
->
irda
);
}
#endif
case
WS_AF_UNSPEC
:
switch
(
wsaddrlen
)
{
default:
/* likely an ipv4 address */
case
sizeof
(
struct
WS_sockaddr_in
):
return
sizeof
(
uaddr
->
in
);
#ifdef HAS_IPX
case
sizeof
(
struct
WS_sockaddr_ipx
):
return
sizeof
(
uaddr
->
ipx
);
#endif
#ifdef HAS_IRDA
struct
sockaddr_irda
irda
;
case
sizeof
(
SOCKADDR_IRDA
):
return
sizeof
(
uaddr
->
irda
);
#endif
};
case
sizeof
(
struct
WS_sockaddr_in6
):
case
sizeof
(
struct
WS_sockaddr_in6_old
):
return
sizeof
(
uaddr
->
in6
);
}
default:
FIXME
(
"unknown address family %u
\n
"
,
wsaddr
->
sa_family
);
return
0
;
}
}
static
int
sockaddr_from_unix
(
const
union
unix_sockaddr
*
uaddr
,
struct
WS_sockaddr
*
wsaddr
,
socklen_t
wsaddrlen
)
{
...
...
@@ -650,6 +765,161 @@ static NTSTATUS sock_poll( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, voi
return
status
;
}
static
NTSTATUS
try_send
(
int
fd
,
struct
async_send_ioctl
*
async
)
{
union
unix_sockaddr
unix_addr
;
struct
msghdr
hdr
;
ssize_t
ret
;
memset
(
&
hdr
,
0
,
sizeof
(
hdr
)
);
if
(
async
->
addr
)
{
hdr
.
msg_name
=
&
unix_addr
;
hdr
.
msg_namelen
=
sockaddr_to_unix
(
async
->
addr
,
async
->
addr_len
,
&
unix_addr
);
if
(
!
hdr
.
msg_namelen
)
{
ERR
(
"failed to convert address
\n
"
);
return
STATUS_ACCESS_VIOLATION
;
}
#if defined(HAS_IPX) && defined(SOL_IPX)
if
(
async
->
addr
->
sa_family
==
WS_AF_IPX
)
{
int
type
;
socklen_t
len
=
sizeof
(
type
);
/* The packet type is stored at the IPX socket level. At least the
* linux kernel seems to do something with it in case hdr.msg_name
* is NULL. Nonetheless we can use it to store the packet type, and
* then we can retrieve it using getsockopt. After that we can set
* the IPX type in the sockaddr_ipx structure with the stored value.
*/
if
(
getsockopt
(
fd
,
SOL_IPX
,
IPX_TYPE
,
&
type
,
&
len
)
>=
0
)
unix_addr
.
ipx
.
sipx_type
=
type
;
}
#endif
}
hdr
.
msg_iov
=
async
->
iov
+
async
->
iov_cursor
;
hdr
.
msg_iovlen
=
async
->
count
-
async
->
iov_cursor
;
while
((
ret
=
sendmsg
(
fd
,
&
hdr
,
async
->
unix_flags
))
==
-
1
)
{
if
(
errno
==
EISCONN
)
{
hdr
.
msg_name
=
NULL
;
hdr
.
msg_namelen
=
0
;
}
else
if
(
errno
!=
EINTR
)
{
if
(
errno
!=
EWOULDBLOCK
)
WARN
(
"sendmsg: %s
\n
"
,
strerror
(
errno
)
);
return
sock_errno_to_status
(
errno
);
}
}
async
->
sent_len
+=
ret
;
while
(
async
->
iov_cursor
<
async
->
count
&&
ret
>=
async
->
iov
[
async
->
iov_cursor
].
iov_len
)
ret
-=
async
->
iov
[
async
->
iov_cursor
++
].
iov_len
;
if
(
async
->
iov_cursor
<
async
->
count
)
{
async
->
iov
[
async
->
iov_cursor
].
iov_base
=
(
char
*
)
async
->
iov
[
async
->
iov_cursor
].
iov_base
+
ret
;
async
->
iov
[
async
->
iov_cursor
].
iov_len
-=
ret
;
return
STATUS_DEVICE_NOT_READY
;
}
return
STATUS_SUCCESS
;
}
static
NTSTATUS
async_send_proc
(
void
*
user
,
IO_STATUS_BLOCK
*
io
,
NTSTATUS
status
)
{
struct
async_send_ioctl
*
async
=
user
;
int
fd
,
needs_close
;
TRACE
(
"%#x
\n
"
,
status
);
if
(
status
==
STATUS_ALERTED
)
{
if
((
status
=
server_get_unix_fd
(
async
->
io
.
handle
,
0
,
&
fd
,
&
needs_close
,
NULL
,
NULL
)))
return
status
;
status
=
try_send
(
fd
,
async
);
TRACE
(
"got status %#x
\n
"
,
status
);
if
(
status
==
STATUS_DEVICE_NOT_READY
)
status
=
STATUS_PENDING
;
if
(
needs_close
)
close
(
fd
);
}
if
(
status
!=
STATUS_PENDING
)
{
io
->
Status
=
status
;
io
->
Information
=
async
->
sent_len
;
release_fileio
(
&
async
->
io
);
}
return
status
;
}
static
NTSTATUS
sock_send
(
HANDLE
handle
,
HANDLE
event
,
PIO_APC_ROUTINE
apc
,
void
*
apc_user
,
IO_STATUS_BLOCK
*
io
,
int
fd
,
const
WSABUF
*
buffers
,
unsigned
int
count
,
const
struct
WS_sockaddr
*
addr
,
unsigned
int
addr_len
,
int
unix_flags
,
int
force_async
)
{
struct
async_send_ioctl
*
async
;
HANDLE
wait_handle
;
DWORD
async_size
;
NTSTATUS
status
;
unsigned
int
i
;
ULONG
options
;
async_size
=
offsetof
(
struct
async_send_ioctl
,
iov
[
count
]
);
if
(
!
(
async
=
(
struct
async_send_ioctl
*
)
alloc_fileio
(
async_size
,
async_send_proc
,
handle
)))
return
STATUS_NO_MEMORY
;
async
->
count
=
count
;
for
(
i
=
0
;
i
<
count
;
++
i
)
{
async
->
iov
[
i
].
iov_base
=
buffers
[
i
].
buf
;
async
->
iov
[
i
].
iov_len
=
buffers
[
i
].
len
;
}
async
->
unix_flags
=
unix_flags
;
async
->
addr
=
addr
;
async
->
addr_len
=
addr_len
;
async
->
iov_cursor
=
0
;
async
->
sent_len
=
0
;
status
=
try_send
(
fd
,
async
);
if
(
status
!=
STATUS_SUCCESS
&&
status
!=
STATUS_DEVICE_NOT_READY
)
{
release_fileio
(
&
async
->
io
);
return
status
;
}
if
(
status
==
STATUS_DEVICE_NOT_READY
&&
force_async
)
status
=
STATUS_PENDING
;
if
(
!
NT_ERROR
(
status
))
{
io
->
Status
=
status
;
io
->
Information
=
async
->
sent_len
;
}
SERVER_START_REQ
(
send_socket
)
{
req
->
status
=
status
;
req
->
total
=
async
->
sent_len
;
req
->
async
=
server_async
(
handle
,
&
async
->
io
,
event
,
apc
,
apc_user
,
io
);
status
=
wine_server_call
(
req
);
wait_handle
=
wine_server_ptr_handle
(
reply
->
wait
);
options
=
reply
->
options
;
}
SERVER_END_REQ
;
if
(
status
!=
STATUS_PENDING
)
release_fileio
(
&
async
->
io
);
if
(
wait_handle
)
status
=
wait_async
(
wait_handle
,
options
&
FILE_SYNCHRONOUS_IO_ALERT
);
return
status
;
}
NTSTATUS
sock_ioctl
(
HANDLE
handle
,
HANDLE
event
,
PIO_APC_ROUTINE
apc
,
void
*
apc_user
,
IO_STATUS_BLOCK
*
io
,
ULONG
code
,
void
*
in_buffer
,
ULONG
in_size
,
void
*
out_buffer
,
ULONG
out_size
)
...
...
@@ -741,6 +1011,32 @@ NTSTATUS sock_ioctl( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, void *apc
break
;
}
case
IOCTL_AFD_WINE_SENDMSG
:
{
const
struct
afd_sendmsg_params
*
params
=
in_buffer
;
int
unix_flags
=
0
;
if
((
status
=
server_get_unix_fd
(
handle
,
0
,
&
fd
,
&
needs_close
,
NULL
,
NULL
)))
return
status
;
if
(
in_size
<
sizeof
(
*
params
))
{
status
=
STATUS_BUFFER_TOO_SMALL
;
break
;
}
if
(
params
->
ws_flags
&
WS_MSG_OOB
)
unix_flags
|=
MSG_OOB
;
if
(
params
->
ws_flags
&
WS_MSG_PARTIAL
)
WARN
(
"ignoring MSG_PARTIAL
\n
"
);
if
(
params
->
ws_flags
&
~
(
WS_MSG_OOB
|
WS_MSG_PARTIAL
))
FIXME
(
"unknown flags %#x
\n
"
,
params
->
ws_flags
);
status
=
sock_send
(
handle
,
event
,
apc
,
apc_user
,
io
,
fd
,
params
->
buffers
,
params
->
count
,
params
->
addr
,
params
->
addr_len
,
unix_flags
,
params
->
force_async
);
break
;
}
case
IOCTL_AFD_POLL
:
status
=
sock_poll
(
handle
,
event
,
apc
,
apc_user
,
io
,
in_buffer
,
in_size
,
out_buffer
,
out_size
);
break
;
...
...
include/wine/afd.h
View file @
85a615f1
...
...
@@ -92,6 +92,7 @@ struct afd_poll_params
#define IOCTL_AFD_WINE_CONNECT CTL_CODE(FILE_DEVICE_NETWORK, 203, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_AFD_WINE_SHUTDOWN CTL_CODE(FILE_DEVICE_NETWORK, 204, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_AFD_WINE_RECVMSG CTL_CODE(FILE_DEVICE_NETWORK, 205, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_AFD_WINE_SENDMSG CTL_CODE(FILE_DEVICE_NETWORK, 206, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_AFD_WINE_ADDRESS_LIST_CHANGE CTL_CODE(FILE_DEVICE_NETWORK, 323, METHOD_BUFFERED, FILE_ANY_ACCESS)
...
...
@@ -126,4 +127,14 @@ struct afd_recvmsg_params
WSABUF
*
buffers
;
};
struct
afd_sendmsg_params
{
const
struct
WS
(
sockaddr
)
*
addr
;
unsigned
int
addr_len
;
unsigned
int
ws_flags
;
int
force_async
;
unsigned
int
count
;
const
WSABUF
*
buffers
;
};
#endif
include/wine/server_protocol.h
View file @
85a615f1
...
...
@@ -1852,6 +1852,23 @@ struct poll_socket_reply
struct
send_socket_request
{
struct
request_header
__header
;
char
__pad_12
[
4
];
async_data_t
async
;
unsigned
int
status
;
unsigned
int
total
;
};
struct
send_socket_reply
{
struct
reply_header
__header
;
obj_handle_t
wait
;
unsigned
int
options
;
};
struct
get_next_console_request_request
{
struct
request_header
__header
;
...
...
@@ -5503,6 +5520,7 @@ enum request
REQ_set_socket_deferred
,
REQ_recv_socket
,
REQ_poll_socket
,
REQ_send_socket
,
REQ_get_next_console_request
,
REQ_read_directory_changes
,
REQ_read_change
,
...
...
@@ -5786,6 +5804,7 @@ union generic_request
struct
set_socket_deferred_request
set_socket_deferred_request
;
struct
recv_socket_request
recv_socket_request
;
struct
poll_socket_request
poll_socket_request
;
struct
send_socket_request
send_socket_request
;
struct
get_next_console_request_request
get_next_console_request_request
;
struct
read_directory_changes_request
read_directory_changes_request
;
struct
read_change_request
read_change_request
;
...
...
@@ -6067,6 +6086,7 @@ union generic_reply
struct
set_socket_deferred_reply
set_socket_deferred_reply
;
struct
recv_socket_reply
recv_socket_reply
;
struct
poll_socket_reply
poll_socket_reply
;
struct
send_socket_reply
send_socket_reply
;
struct
get_next_console_request_reply
get_next_console_request_reply
;
struct
read_directory_changes_reply
read_directory_changes_reply
;
struct
read_change_reply
read_change_reply
;
...
...
@@ -6287,7 +6307,7 @@ union generic_reply
/* ### protocol_version begin ### */
#define SERVER_PROTOCOL_VERSION 70
7
#define SERVER_PROTOCOL_VERSION 70
8
/* ### protocol_version end ### */
...
...
server/protocol.def
View file @
85a615f1
...
...
@@ -1502,6 +1502,17 @@ struct poll_socket_output
@END
/* Perform a send on a socket */
@REQ(send_socket)
async_data_t async; /* async I/O parameters */
unsigned int status; /* status of initial call */
unsigned int total; /* number of bytes already sent */
@REPLY
obj_handle_t wait; /* handle to wait on for blocking send */
unsigned int options; /* device open options */
@END
/* Retrieve the next pending console ioctl request */
@REQ(get_next_console_request)
obj_handle_t handle; /* console server handle */
...
...
server/request.h
View file @
85a615f1
...
...
@@ -179,6 +179,7 @@ DECL_HANDLER(enable_socket_event);
DECL_HANDLER
(
set_socket_deferred
);
DECL_HANDLER
(
recv_socket
);
DECL_HANDLER
(
poll_socket
);
DECL_HANDLER
(
send_socket
);
DECL_HANDLER
(
get_next_console_request
);
DECL_HANDLER
(
read_directory_changes
);
DECL_HANDLER
(
read_change
);
...
...
@@ -461,6 +462,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
(
req_handler
)
req_set_socket_deferred
,
(
req_handler
)
req_recv_socket
,
(
req_handler
)
req_poll_socket
,
(
req_handler
)
req_send_socket
,
(
req_handler
)
req_get_next_console_request
,
(
req_handler
)
req_read_directory_changes
,
(
req_handler
)
req_read_change
,
...
...
@@ -1082,6 +1084,13 @@ C_ASSERT( sizeof(struct poll_socket_request) == 64 );
C_ASSERT
(
FIELD_OFFSET
(
struct
poll_socket_reply
,
wait
)
==
8
);
C_ASSERT
(
FIELD_OFFSET
(
struct
poll_socket_reply
,
options
)
==
12
);
C_ASSERT
(
sizeof
(
struct
poll_socket_reply
)
==
16
);
C_ASSERT
(
FIELD_OFFSET
(
struct
send_socket_request
,
async
)
==
16
);
C_ASSERT
(
FIELD_OFFSET
(
struct
send_socket_request
,
status
)
==
56
);
C_ASSERT
(
FIELD_OFFSET
(
struct
send_socket_request
,
total
)
==
60
);
C_ASSERT
(
sizeof
(
struct
send_socket_request
)
==
64
);
C_ASSERT
(
FIELD_OFFSET
(
struct
send_socket_reply
,
wait
)
==
8
);
C_ASSERT
(
FIELD_OFFSET
(
struct
send_socket_reply
,
options
)
==
12
);
C_ASSERT
(
sizeof
(
struct
send_socket_reply
)
==
16
);
C_ASSERT
(
FIELD_OFFSET
(
struct
get_next_console_request_request
,
handle
)
==
12
);
C_ASSERT
(
FIELD_OFFSET
(
struct
get_next_console_request_request
,
signal
)
==
16
);
C_ASSERT
(
FIELD_OFFSET
(
struct
get_next_console_request_request
,
read
)
==
20
);
...
...
server/sock.c
View file @
85a615f1
...
...
@@ -768,14 +768,11 @@ static int sock_dispatch_asyncs( struct sock *sock, int event, int error )
event
&=
~
(
POLLIN
|
POLLPRI
);
}
if
(
is_fd_overlapped
(
sock
->
fd
))
if
(
event
&
POLLOUT
&&
async_waiting
(
&
sock
->
write_q
))
{
if
(
event
&
POLLOUT
&&
async_waiting
(
&
sock
->
write_q
))
{
if
(
debug_level
)
fprintf
(
stderr
,
"activating write queue for socket %p
\n
"
,
sock
);
async_wake_up
(
&
sock
->
write_q
,
STATUS_ALERTED
);
event
&=
~
POLLOUT
;
}
if
(
debug_level
)
fprintf
(
stderr
,
"activating write queue for socket %p
\n
"
,
sock
);
async_wake_up
(
&
sock
->
write_q
,
STATUS_ALERTED
);
event
&=
~
POLLOUT
;
}
if
(
event
&
(
POLLERR
|
POLLHUP
))
...
...
@@ -2508,3 +2505,84 @@ DECL_HANDLER(poll_socket)
release_object
(
sock
);
}
DECL_HANDLER
(
send_socket
)
{
struct
sock
*
sock
=
(
struct
sock
*
)
get_handle_obj
(
current
->
process
,
req
->
async
.
handle
,
0
,
&
sock_ops
);
unsigned
int
status
=
req
->
status
;
timeout_t
timeout
=
0
;
struct
async
*
async
;
struct
fd
*
fd
;
if
(
!
sock
)
return
;
fd
=
sock
->
fd
;
if
(
status
!=
STATUS_SUCCESS
)
{
/* send() calls only clear and reselect events if unsuccessful. */
sock
->
pending_events
&=
~
FD_WRITE
;
sock
->
reported_events
&=
~
FD_WRITE
;
}
/* If we had a short write and the socket is nonblocking (and the client is
* not trying to force the operation to be asynchronous), return success.
* Windows actually refuses to send any data in this case, and returns
* EWOULDBLOCK, but we have no way of doing that. */
if
(
status
==
STATUS_DEVICE_NOT_READY
&&
req
->
total
&&
(
sock
->
state
&
FD_WINE_NONBLOCKING
))
status
=
STATUS_SUCCESS
;
/* send() returned EWOULDBLOCK or a short write, i.e. cannot send all data yet */
if
(
status
==
STATUS_DEVICE_NOT_READY
&&
!
(
sock
->
state
&
FD_WINE_NONBLOCKING
))
{
#ifdef SO_SNDTIMEO
struct
timeval
tv
;
socklen_t
len
=
sizeof
(
tv
);
/* Set a timeout on the async if necessary.
*
* We want to do this *only* if the client gave us STATUS_DEVICE_NOT_READY.
* If the client gave us STATUS_PENDING, it expects the async to always
* block (it was triggered by WSASend*() with a valid OVERLAPPED
* structure) and for the timeout not to be respected. */
if
(
is_fd_overlapped
(
fd
)
&&
!
getsockopt
(
get_unix_fd
(
fd
),
SOL_SOCKET
,
SO_SNDTIMEO
,
(
char
*
)
&
tv
,
&
len
))
timeout
=
tv
.
tv_sec
*
-
10000000
+
tv
.
tv_usec
*
-
10
;
#endif
status
=
STATUS_PENDING
;
}
/* are we shut down? */
if
(
status
==
STATUS_PENDING
&&
!
(
sock
->
state
&
FD_WRITE
))
status
=
STATUS_PIPE_DISCONNECTED
;
if
((
async
=
create_request_async
(
fd
,
get_fd_comp_flags
(
fd
),
&
req
->
async
)))
{
int
success
=
0
;
if
(
status
==
STATUS_SUCCESS
)
{
struct
iosb
*
iosb
=
async_get_iosb
(
async
);
iosb
->
result
=
req
->
total
;
release_object
(
iosb
);
success
=
1
;
}
else
if
(
status
==
STATUS_PENDING
)
{
success
=
1
;
}
set_error
(
status
);
if
(
timeout
)
async_set_timeout
(
async
,
timeout
,
STATUS_IO_TIMEOUT
);
if
(
status
==
STATUS_PENDING
)
queue_async
(
&
sock
->
write_q
,
async
);
/* always reselect; we changed reported_events above */
sock_reselect
(
sock
);
reply
->
wait
=
async_handoff
(
async
,
success
,
NULL
,
0
);
reply
->
options
=
get_fd_options
(
fd
);
release_object
(
async
);
}
release_object
(
sock
);
}
server/trace.c
View file @
85a615f1
...
...
@@ -2150,6 +2150,19 @@ static void dump_poll_socket_reply( const struct poll_socket_reply *req )
dump_varargs_poll_socket_output
(
", sockets="
,
cur_size
);
}
static
void
dump_send_socket_request
(
const
struct
send_socket_request
*
req
)
{
dump_async_data
(
" async="
,
&
req
->
async
);
fprintf
(
stderr
,
", status=%08x"
,
req
->
status
);
fprintf
(
stderr
,
", total=%08x"
,
req
->
total
);
}
static
void
dump_send_socket_reply
(
const
struct
send_socket_reply
*
req
)
{
fprintf
(
stderr
,
" wait=%04x"
,
req
->
wait
);
fprintf
(
stderr
,
", options=%08x"
,
req
->
options
);
}
static
void
dump_get_next_console_request_request
(
const
struct
get_next_console_request_request
*
req
)
{
fprintf
(
stderr
,
" handle=%04x"
,
req
->
handle
);
...
...
@@ -4599,6 +4612,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
(
dump_func
)
dump_set_socket_deferred_request
,
(
dump_func
)
dump_recv_socket_request
,
(
dump_func
)
dump_poll_socket_request
,
(
dump_func
)
dump_send_socket_request
,
(
dump_func
)
dump_get_next_console_request_request
,
(
dump_func
)
dump_read_directory_changes_request
,
(
dump_func
)
dump_read_change_request
,
...
...
@@ -4878,6 +4892,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
NULL
,
(
dump_func
)
dump_recv_socket_reply
,
(
dump_func
)
dump_poll_socket_reply
,
(
dump_func
)
dump_send_socket_reply
,
(
dump_func
)
dump_get_next_console_request_reply
,
NULL
,
(
dump_func
)
dump_read_change_reply
,
...
...
@@ -5157,6 +5172,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
"set_socket_deferred"
,
"recv_socket"
,
"poll_socket"
,
"send_socket"
,
"get_next_console_request"
,
"read_directory_changes"
,
"read_change"
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment