On 9/28/22 07:55, David Gibson wrote:
+static int net_stream_server_init(NetClientState *peer,
+ const char *model,
+ const char *name,
+ SocketAddress *addr,
+ Error **errp)
+{
+ NetClientState *nc;
+ NetStreamState *s;
+ int fd, ret;
+
+ switch (addr->type) {
+ case SOCKET_ADDRESS_TYPE_INET: {
+ struct sockaddr_in saddr_in;
+
+ if (convert_host_port(&saddr_in, addr->u.inet.host, addr->u.inet.port,
+ errp) < 0) {
+ return -1;
+ }
+
+ fd = qemu_socket(PF_INET, SOCK_STREAM, 0);
+ if (fd < 0) {
+ error_setg_errno(errp, errno, "can't create stream socket");
+ return -1;
+ }
+ qemu_socket_set_nonblock(fd);
+
+ socket_set_fast_reuse(fd);
+
+ ret = bind(fd, (struct sockaddr *)&saddr_in, sizeof(saddr_in));
+ if (ret < 0) {
+ error_setg_errno(errp, errno, "can't bind ip=%s to socket",
+ inet_ntoa(saddr_in.sin_addr));
+ closesocket(fd);
+ return -1;
+ }
+ break;
+ }
+ case SOCKET_ADDRESS_TYPE_FD:
+ fd = monitor_fd_param(monitor_cur(), addr->u.fd.str, errp);
+ if (fd == -1) {
+ return -1;
+ }
+ ret = qemu_socket_try_set_nonblock(fd);
+ if (ret < 0) {
+ error_setg_errno(errp, -ret, "%s: Can't use file descriptor %d",
+ name, fd);
+ return -1;
+ }
+ break;
+ default:
+ error_setg(errp, "only support inet or fd type");
+ return -1;
+ }
+
+ ret = listen(fd, 0);
Does this make sense for a passed in fd? If someone passes a "server"
fd, are they likely to be passing a socket on which bind() but not
listen() has been called? Or one on which both bind() and listen()
have been called?
Original code in net/socket.c doesn't manage server case with fd.
So I have checked what is done for QIO (all this code is overwritten by patch introducing
QIO anyway):
At the end of the series, we use qio_channel_socket_listen_async() in
net_stream_server_init(), that in the end calls socket_listen().
With SOCKET_ADDRESS_TYPE_FD we does the listen() (without bind()) with the
following comment:
case SOCKET_ADDRESS_TYPE_FD:
fd = socket_get_fd(addr->u.fd.str, errp);
if (fd < 0) {
return -1;
}
/*
* If the socket is not yet in the listen state, then transition it to
* the listen state now.
*
* If it's already listening then this updates the backlog value as
* requested.
*
* If this socket cannot listen because it's already in another state
* (e.g. unbound or connected) then we'll catch the error here.
*/
if (listen(fd, num) != 0) {
error_setg_errno(errp, errno, "Failed to listen on fd socket");
closesocket(fd);
return -1;
}
break;
So I think we should keep the listen() in our case too.
Thanks,
Laurent