[fdio] Acquire socket type from kernel
After this change, we acquire the type of the socket (e.g., pipe,
stream, or datagram) using zx_object_get_info rather than using the
process args id. This CL paves the way for reducing the process args
ids.
Test: No behavior change
Change-Id: Ia92305fcf08a22d5403a315be11df3e21041aff3
diff --git a/system/ulib/fdio/bsdsocket.c b/system/ulib/fdio/bsdsocket.c
index d971c7a..6e85b50 100644
--- a/system/ulib/fdio/bsdsocket.c
+++ b/system/ulib/fdio/bsdsocket.c
@@ -106,15 +106,14 @@
return STATUS(rr);
}
- io = fdio_socket_create(s, 0);
- if (io == NULL) {
- return ERRNO(EIO);
+ if (type & SOCK_DGRAM) {
+ io = fdio_socket_create_datagram(s, 0);
+ } else {
+ io = fdio_socket_create_stream(s, 0);
}
- if (type & SOCK_STREAM) {
- fdio_socket_set_stream_ops(io);
- } else if (type & SOCK_DGRAM) {
- fdio_socket_set_dgram_ops(io);
+ if (io == NULL) {
+ return ERRNO(EIO);
}
if (type & SOCK_NONBLOCK) {
@@ -236,11 +235,10 @@
}
fdio_t* io2;
- if ((io2 = fdio_socket_create(s2, IOFLAG_SOCKET_CONNECTED)) == NULL) {
+ if ((io2 = fdio_socket_create_stream(s2, IOFLAG_SOCKET_CONNECTED)) == NULL) {
return ERROR(ZX_ERR_NO_RESOURCES);
}
- fdio_socket_set_stream_ops(io2);
io2->ioflag |= IOFLAG_SOCKET_CONNECTED;
if (flags & SOCK_NONBLOCK) {
diff --git a/system/ulib/fdio/private.h b/system/ulib/fdio/private.h
index 85354a9..96ed9eec 100644
--- a/system/ulib/fdio/private.h
+++ b/system/ulib/fdio/private.h
@@ -135,8 +135,15 @@
// Takens ownership of h.
fdio_t* fdio_vmofile_create(zx_handle_t h, zx_handle_t vmo, zx_off_t off, zx_off_t len);
+// Examines |socket| and determines whether to create a pipe, stream socket, or
+// datagram socket.
+//
+// Always consumes |socket|.
+zx_status_t fdio_acquire_socket(zx_handle_t socket, int flags, fdio_t** out_io);
+
// Wraps a socket with an fdio_t using socket io.
-fdio_t* fdio_socket_create(zx_handle_t s, int flags);
+fdio_t* fdio_socket_create_stream(zx_handle_t s, int flags);
+fdio_t* fdio_socket_create_datagram(zx_handle_t s, int flags);
// creates a message port and pair of simple io fdio_t's
int fdio_pipe_pair(fdio_t** a, fdio_t** b);
@@ -153,9 +160,6 @@
fdio_t* fdio_waitable_create(zx_handle_t h, zx_signals_t signals_in,
zx_signals_t signals_out, bool shared_handle);
-void fdio_socket_set_stream_ops(fdio_t* io);
-void fdio_socket_set_dgram_ops(fdio_t* io);
-
// unsupported / do-nothing hooks shared by implementations
zx_status_t fdio_default_get_token(fdio_t* io, zx_handle_t* out);
zx_status_t fdio_default_set_attr(fdio_t* io, const vnattr_t* attr);
diff --git a/system/ulib/fdio/remoteio.c b/system/ulib/fdio/remoteio.c
index 7d16a63..a1f4d39 100644
--- a/system/ulib/fdio/remoteio.c
+++ b/system/ulib/fdio/remoteio.c
@@ -457,6 +457,34 @@
ZX_FS_RIGHT_WRITABLE, 0755, "");
}
+zx_status_t fdio_acquire_socket(zx_handle_t socket, int flags, fdio_t** out_io) {
+ zx_info_socket_t info;
+ memset(&info, 0, sizeof(info));
+ zx_status_t status = zx_object_get_info(socket, ZX_INFO_SOCKET, &info, sizeof(info), NULL, NULL);
+ if (status != ZX_OK) {
+ zx_handle_close(socket);
+ return status;
+ }
+ fdio_t* io = NULL;
+ if ((info.options & ZX_SOCKET_HAS_CONTROL) != 0) {
+ // If the socket has a control plane, then the socket is either
+ // a stream or a datagram socket.
+ if ((info.options & ZX_SOCKET_DATAGRAM) != 0) {
+ io = fdio_socket_create_datagram(socket, flags);
+ } else {
+ io = fdio_socket_create_stream(socket, flags);
+ }
+ } else {
+ // Without a control plane, the socket is a pipe.
+ io = fdio_pipe_create(socket);
+ }
+ if (!io) {
+ return ZX_ERR_NO_RESOURCES;
+ }
+ *out_io = io;
+ return ZX_OK;
+}
+
// Create a fdio (if possible) from handles and info.
//
// The Control channel is provided in |handle|, and auxillary
@@ -512,14 +540,6 @@
}
*out = io;
return ZX_OK;
- case FDIO_PROTOCOL_PIPE:
- if (handle != ZX_HANDLE_INVALID) {
- r = ZX_ERR_INVALID_ARGS;
- break;
- } else if ((*out = fdio_pipe_create(info->pipe.s)) == NULL) {
- return ZX_ERR_NO_RESOURCES;
- }
- return ZX_OK;
case FDIO_PROTOCOL_VMOFILE: {
if (info->vmofile.v == ZX_HANDLE_INVALID) {
r = ZX_ERR_INVALID_ARGS;
@@ -532,6 +552,13 @@
}
return ZX_OK;
}
+ case FDIO_PROTOCOL_PIPE:
+ if (info->pipe.s == ZX_HANDLE_INVALID) {
+ r = ZX_ERR_INVALID_ARGS;
+ break;
+ }
+ zx_handle_close(handle);
+ return fdio_acquire_socket(info->pipe.s, 0, out);
case FDIO_PROTOCOL_SOCKET_CONNECTED:
case FDIO_PROTOCOL_SOCKET: {
int flags = (info->tag == FDIO_PROTOCOL_SOCKET_CONNECTED) ? IOFLAG_SOCKET_CONNECTED : 0;
@@ -540,10 +567,7 @@
break;
}
zx_handle_close(handle);
- if ((*out = fdio_socket_create(info->socket.s, flags)) == NULL) {
- return ZX_ERR_NO_RESOURCES;
- }
- return ZX_OK;
+ return fdio_acquire_socket(info->socket.s, flags, out);
}
case FDIO_PROTOCOL_SOCKETPAIR:
if (handle != ZX_HANDLE_INVALID) {
@@ -572,7 +596,6 @@
zx_status_t r;
int fd;
zxrio_node_info_t info;
- zx_handle_t control_channel = ZX_HANDLE_INVALID;
// Pack additional handles into |info|, if possible.
switch (PA_HND_TYPE(types[0])) {
@@ -620,7 +643,7 @@
goto fail;
}
- if ((r = fdio_from_handles(control_channel, &info, &io)) != ZX_OK) {
+ if ((r = fdio_from_handles(ZX_HANDLE_INVALID, &info, &io)) != ZX_OK) {
return r;
}
diff --git a/system/ulib/fdio/socket.c b/system/ulib/fdio/socket.c
index 9650e23..15f36f8 100644
--- a/system/ulib/fdio/socket.c
+++ b/system/ulib/fdio/socket.c
@@ -833,13 +833,13 @@
.shutdown = fdio_socket_shutdown,
};
-fdio_t* fdio_socket_create(zx_handle_t s, int flags) {
+static fdio_t* fdio_socket_create(zx_handle_t s, int flags, fdio_ops_t* ops) {
zxsio_t* sio = calloc(1, sizeof(*sio));
if (sio == NULL) {
zx_handle_close(s);
return NULL;
}
- sio->io.ops = &fdio_socket_stream_ops; // default is stream
+ sio->io.ops = ops;
sio->io.magic = FDIO_MAGIC;
sio->io.refcount = 1;
sio->io.ioflag = IOFLAG_SOCKET | flags;
@@ -848,12 +848,10 @@
return &sio->io;
}
-void fdio_socket_set_stream_ops(fdio_t* io) {
- zxsio_t* sio = (zxsio_t*)io;
- sio->io.ops = &fdio_socket_stream_ops;
+fdio_t* fdio_socket_create_stream(zx_handle_t s, int flags) {
+ return fdio_socket_create(s, flags, &fdio_socket_stream_ops);
}
-void fdio_socket_set_dgram_ops(fdio_t* io) {
- zxsio_t* sio = (zxsio_t*)io;
- sio->io.ops = &fdio_socket_dgram_ops;
+fdio_t* fdio_socket_create_datagram(zx_handle_t s, int flags) {
+ return fdio_socket_create(s, flags, &fdio_socket_dgram_ops);
}
diff --git a/system/ulib/fdio/unistd.c b/system/ulib/fdio/unistd.c
index 0b695f5..ba5c70e 100644
--- a/system/ulib/fdio/unistd.c
+++ b/system/ulib/fdio/unistd.c
@@ -586,21 +586,26 @@
LOG(1, "fdio: inherit fd=%d (rio)\n", arg_fd);
break;
}
- case PA_FDIO_PIPE:
- fdio_fdtab[arg_fd] = fdio_pipe_create(h);
+ case PA_FDIO_SOCKET:
+ case PA_FDIO_PIPE: {
+ fdio_t* io = NULL;
+ zx_status_t status = fdio_acquire_socket(h, IOFLAG_SOCKET_CONNECTED, &io);
+ if (status != ZX_OK) {
+ LOG(1, "fdio: Failed to acquire for fd=%d (socket) status=%d (%s)\n",
+ arg_fd, status, zx_status_get_string(status));
+ zx_handle_close(h);
+ continue;
+ }
+ fdio_fdtab[arg_fd] = io;
fdio_fdtab[arg_fd]->dupcount++;
- LOG(1, "fdio: inherit fd=%d (pipe)\n", arg_fd);
+ LOG(1, "fdio: inherit fd=%d (socket)\n", arg_fd);
break;
+ }
case PA_FDIO_LOGGER:
fdio_fdtab[arg_fd] = fdio_logger_create(h);
fdio_fdtab[arg_fd]->dupcount++;
LOG(1, "fdio: inherit fd=%d (log)\n", arg_fd);
break;
- case PA_FDIO_SOCKET:
- fdio_fdtab[arg] = fdio_socket_create(h, IOFLAG_SOCKET_CONNECTED);
- fdio_fdtab[arg]->dupcount++;
- LOG(1, "fdio: inherit fd=%d (socket)\n", arg_fd);
- break;
case PA_NS_DIR:
// we always contine here to not steal the
// handles from higher level code that may
diff --git a/system/utest/fdio/fdio_socket.c b/system/utest/fdio/fdio_socket.c
index 4338df6..72ef73d 100644
--- a/system/utest/fdio/fdio_socket.c
+++ b/system/utest/fdio/fdio_socket.c
@@ -15,7 +15,7 @@
static bool create_socket_fdio_pair(zx_handle_t* socket_out, int* fd_out) {
// Create new socket pair.
zx_handle_t s1, s2;
- ASSERT_EQ(ZX_OK, zx_socket_create(ZX_SOCKET_STREAM, &s1, &s2), "Socket create failed");
+ ASSERT_EQ(ZX_OK, zx_socket_create(ZX_SOCKET_STREAM | ZX_SOCKET_HAS_CONTROL, &s1, &s2), "Socket create failed");
// Convert one socket to FDIO
uint32_t type = PA_FDIO_SOCKET;