Cygwin: AF_UNIX: Implemant socketpair

Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
This commit is contained in:
Corinna Vinschen 2018-03-09 14:19:36 +01:00
parent f4a1a186f9
commit b194d65615
2 changed files with 67 additions and 21 deletions

View File

@ -882,9 +882,9 @@ class fhandler_socket_unix : public fhandler_socket
int send_my_name (); int send_my_name ();
int recv_peer_name (); int recv_peer_name ();
static NTSTATUS npfs_handle (HANDLE &nph); static NTSTATUS npfs_handle (HANDLE &nph);
HANDLE create_pipe (); HANDLE create_pipe (bool single_instance);
HANDLE create_pipe_instance (); HANDLE create_pipe_instance ();
NTSTATUS open_pipe (HANDLE &ph, PUNICODE_STRING pipe_name); NTSTATUS open_pipe (PUNICODE_STRING pipe_name, bool send_name);
int wait_pipe (PUNICODE_STRING pipe_name); int wait_pipe (PUNICODE_STRING pipe_name);
int connect_pipe (PUNICODE_STRING pipe_name); int connect_pipe (PUNICODE_STRING pipe_name);
int listen_pipe (); int listen_pipe ();

View File

@ -679,7 +679,7 @@ fhandler_socket_unix::npfs_handle (HANDLE &nph)
} }
HANDLE HANDLE
fhandler_socket_unix::create_pipe () fhandler_socket_unix::create_pipe (bool single_instance)
{ {
NTSTATUS status; NTSTATUS status;
HANDLE npfsh; HANDLE npfsh;
@ -707,7 +707,7 @@ fhandler_socket_unix::create_pipe ()
npfsh, NULL); npfsh, NULL);
nonblocking = is_nonblocking () ? FILE_PIPE_COMPLETE_OPERATION nonblocking = is_nonblocking () ? FILE_PIPE_COMPLETE_OPERATION
: FILE_PIPE_QUEUE_OPERATION; : FILE_PIPE_QUEUE_OPERATION;
max_instances = (get_socket_type () == SOCK_DGRAM) ? 1 : -1; max_instances = single_instance ? 1 : -1;
timeout.QuadPart = -500000; timeout.QuadPart = -500000;
status = NtCreateNamedPipeFile (&ph, access, &attr, &io, sharing, status = NtCreateNamedPipeFile (&ph, access, &attr, &io, sharing,
FILE_CREATE, 0, FILE_CREATE, 0,
@ -763,7 +763,7 @@ fhandler_socket_unix::create_pipe_instance ()
} }
NTSTATUS NTSTATUS
fhandler_socket_unix::open_pipe (HANDLE &ph, PUNICODE_STRING pipe_name) fhandler_socket_unix::open_pipe (PUNICODE_STRING pipe_name, bool send_name)
{ {
NTSTATUS status; NTSTATUS status;
HANDLE npfsh; HANDLE npfsh;
@ -771,6 +771,7 @@ fhandler_socket_unix::open_pipe (HANDLE &ph, PUNICODE_STRING pipe_name)
OBJECT_ATTRIBUTES attr; OBJECT_ATTRIBUTES attr;
IO_STATUS_BLOCK io; IO_STATUS_BLOCK io;
ULONG sharing; ULONG sharing;
HANDLE ph = NULL;
status = npfs_handle (npfsh); status = npfs_handle (npfsh);
if (!NT_SUCCESS (status)) if (!NT_SUCCESS (status))
@ -782,7 +783,8 @@ fhandler_socket_unix::open_pipe (HANDLE &ph, PUNICODE_STRING pipe_name)
if (NT_SUCCESS (status)) if (NT_SUCCESS (status))
{ {
set_io_handle (ph); set_io_handle (ph);
send_my_name (); if (send_name)
send_my_name ();
} }
return status; return status;
} }
@ -881,11 +883,10 @@ int
fhandler_socket_unix::connect_pipe (PUNICODE_STRING pipe_name) fhandler_socket_unix::connect_pipe (PUNICODE_STRING pipe_name)
{ {
NTSTATUS status; NTSTATUS status;
HANDLE ph = NULL;
/* Try connecting first. If it doesn't work, wait for the pipe /* Try connecting first. If it doesn't work, wait for the pipe
to become available. */ to become available. */
status = open_pipe (ph, pipe_name); status = open_pipe (pipe_name, get_socket_type () != SOCK_DGRAM);
if (STATUS_PIPE_NO_INSTANCE_AVAILABLE (status)) if (STATUS_PIPE_NO_INSTANCE_AVAILABLE (status))
return wait_pipe (pipe_name); return wait_pipe (pipe_name);
if (!NT_SUCCESS (status)) if (!NT_SUCCESS (status))
@ -1053,7 +1054,6 @@ fhandler_socket_unix::wait_pipe_thread (PUNICODE_STRING pipe_name)
ULONG pwbuf_size; ULONG pwbuf_size;
PFILE_PIPE_WAIT_FOR_BUFFER pwbuf; PFILE_PIPE_WAIT_FOR_BUFFER pwbuf;
LONGLONG stamp; LONGLONG stamp;
HANDLE ph = NULL;
status = npfs_handle (npfsh); status = npfs_handle (npfsh);
if (!NT_SUCCESS (status)) if (!NT_SUCCESS (status))
@ -1092,7 +1092,7 @@ fhandler_socket_unix::wait_pipe_thread (PUNICODE_STRING pipe_name)
{ {
case STATUS_SUCCESS: case STATUS_SUCCESS:
{ {
status = open_pipe (ph, pipe_name); status = open_pipe (pipe_name, get_socket_type () != SOCK_DGRAM);
if (STATUS_PIPE_NO_INSTANCE_AVAILABLE (status)) if (STATUS_PIPE_NO_INSTANCE_AVAILABLE (status))
{ {
/* Another concurrent connect grabbed the pipe instance /* Another concurrent connect grabbed the pipe instance
@ -1170,6 +1170,10 @@ int
fhandler_socket_unix::socketpair (int af, int type, int protocol, int flags, fhandler_socket_unix::socketpair (int af, int type, int protocol, int flags,
fhandler_socket *fh_out) fhandler_socket *fh_out)
{ {
HANDLE pipe;
sun_name_t sun;
fhandler_socket_unix *fh = (fhandler_socket_unix *) fh_out;
if (type != SOCK_STREAM && type != SOCK_DGRAM) if (type != SOCK_STREAM && type != SOCK_DGRAM)
{ {
set_errno (EINVAL); set_errno (EINVAL);
@ -1180,8 +1184,53 @@ fhandler_socket_unix::socketpair (int af, int type, int protocol, int flags,
set_errno (EPROTONOSUPPORT); set_errno (EPROTONOSUPPORT);
return -1; return -1;
} }
set_errno (EAFNOSUPPORT);
return -1; /* socket() on both sockets */
rmem (262144);
fh->rmem (262144);
wmem (262144);
fh->wmem (262144);
set_addr_family (af);
fh->set_addr_family (af);
set_socket_type (type);
fh->set_socket_type (type);
set_unique_id ();
set_ino (get_unique_id ());
/* bind/listen 1st socket */
gen_pipe_name ();
pipe = create_pipe (true);
if (!pipe)
return -1;
set_io_handle (pipe);
backing_file_handle = autobind (&sun);
if (!backing_file_handle)
{
NtClose (pipe);
return -1;
}
set_sun_path (&sun);
fh->set_peer_sun_path (&sun);
binding_state (bound);
connect_state (listener);
/* connect 2nd socket */
if (type != SOCK_DGRAM
&& fh->open_pipe (pc.get_nt_native_path (), false) < 0)
{
NtClose (pipe);
return -1;
}
fh->connect_state (connected);
if (flags & SOCK_NONBLOCK)
{
set_nonblocking (true);
fh->set_nonblocking (true);
}
if (flags & SOCK_CLOEXEC)
{
set_close_on_exec (true);
fh->set_close_on_exec (true);
}
return 0;
} }
/* Bind creates the backing file, generates the pipe name and sets /* Bind creates the backing file, generates the pipe name and sets
@ -1217,7 +1266,7 @@ fhandler_socket_unix::bind (const struct sockaddr *name, int namelen)
gen_pipe_name (); gen_pipe_name ();
if (get_socket_type () == SOCK_DGRAM) if (get_socket_type () == SOCK_DGRAM)
{ {
pipe = create_pipe (); pipe = create_pipe (true);
if (!pipe) if (!pipe)
{ {
binding_state (unbound); binding_state (unbound);
@ -1268,16 +1317,13 @@ fhandler_socket_unix::listen (int backlog)
ReleaseSRWLockExclusive (&conn_lock); ReleaseSRWLockExclusive (&conn_lock);
return -1; return -1;
} }
if (get_socket_type () != SOCK_DGRAM) HANDLE pipe = create_pipe (false);
if (!pipe)
{ {
HANDLE pipe = create_pipe (); connect_state (unconnected);
if (!pipe) return -1;
{
connect_state (unconnected);
return -1;
}
set_io_handle (pipe);
} }
set_io_handle (pipe);
connect_state (listener); connect_state (listener);
ReleaseSRWLockExclusive (&conn_lock); ReleaseSRWLockExclusive (&conn_lock);
return 0; return 0;