Sunday, February 05, 2006 3:28 AM Fabrice Bellard wrote:
Kazu wrote:Thursday, February 02, 2006 8:10 AM Fabrice Bellard wrote:Hi, I merged your patches and I made important changes to simplify them. I did not do any tests so tell me if you see problems.-net socket,connect doesn't work. On Windows host, connect returns with err = WSAEWOULDBLOCK and second time err = WSAEINVAL. I think changing the place of EWOULDBLOCK would be good. On Linux host, EWOULDBLOCK is the same as EAGAIN but a patch works on both Linux and Windows.Unfortunately on Linux the correct return value we are expecting is EINPROGRESS. EAGAIN means that the 'connect' was not initiated so it is necessary to redo it.
There is not good way to detect a completion of asynchronous connect. So I used an event object to detect it. A patch is attached.
For -net socket,mcast, bind have to be done by sin_addr.s_addr = INADDR_ANY. It seems that it works on Linux host.It works on Linux but it is not correct because it prevents from listening to several multicast addresses at the same time. If doing the same on Windows is not possible I agree to make a special case.
I couldn't find a way to set a multicast address. I made it a special case in the patch Regard, Kazu Index: vl.c =================================================================== RCS file: /sources/qemu/qemu/vl.c,v retrieving revision 1.162 diff -u -r1.162 vl.c --- vl.c 5 Feb 2006 04:14:41 -0000 1.162 +++ vl.c 8 Feb 2006 05:50:28 -0000 @@ -1083,9 +1083,10 @@ #define socket_error() WSAGetLastError() #undef EINTR -#define EWOULDBLOCK WSAEWOULDBLOCK -#define EINTR WSAEINTR -#define EINPROGRESS WSAEINPROGRESS +#define EWOULDBLOCK WSAEWOULDBLOCK +#define EINTR WSAEINTR +#define EINPROGRESS WSAEINPROGRESS +#define EADDRNOTAVAIL WSAEADDRNOTAVAIL static void socket_cleanup(void) { @@ -1136,6 +1137,59 @@ ioctlsocket(fd, FIONBIO, &opt); } +static int socket_set_event(SOCKET fd, WSAEVENT *phEvent) +{ + int ret; + + *phEvent = WSACreateEvent(); + if (*phEvent == WSA_INVALID_EVENT) { + perror("connect: CreateEvent"); + return -1; + } + + ret = WSAEventSelect(fd, *phEvent, FD_CONNECT); + if (ret == SOCKET_ERROR) { + perror("connect: EventSelect"); + return -1; + } + return 0; +} + +static int socket_wait_event(SOCKET fd, WSAEVENT *phEvent) +{ + WSANETWORKEVENTS events; + int ret; + + ret = WSAWaitForMultipleEvents(1, phEvent, FALSE, WSA_INFINITE, FALSE); + if (ret == WSA_WAIT_FAILED) { + perror("connect: Wait"); + goto fail; + } + + ret = WSAEnumNetworkEvents(fd, *phEvent, &events); + if (ret == SOCKET_ERROR) { + perror("connect: EnumEvent"); + goto fail; + } else { + if (events.lNetworkEvents & FD_CONNECT) { + if (events.iErrorCode[FD_CONNECT_BIT] == 0) { + if (*phEvent != WSA_INVALID_EVENT) + WSACloseEvent(*phEvent); + return 1; + } else { + perror("connect: refused"); + goto fail; + } + } else { + perror("connect: fd_connect"); + goto fail; + } + } + fail: + if (*phEvent != WSA_INVALID_EVENT) + WSACloseEvent(*phEvent); + return 0; +} #else #define socket_error() errno @@ -2330,7 +2384,9 @@ { struct ip_mreq imr; int fd; - int val, ret; + int val, ret, err; + struct sockaddr_in addr; + if (!IN_MULTICAST(ntohl(mcastaddr->sin_addr.s_addr))) { fprintf(stderr, "qemu: error: specified mcastaddr \"%s\" (0x%08x) does not contain a multicast address\n", inet_ntoa(mcastaddr->sin_addr), @@ -2354,8 +2410,22 @@ ret = bind(fd, (struct sockaddr *)mcastaddr, sizeof(*mcastaddr)); if (ret < 0) { - perror("bind"); - goto fail; + err = socket_error(); + if (err == EADDRNOTAVAIL) { + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = mcastaddr->sin_port; + addr.sin_addr.s_addr = INADDR_ANY; + + ret = bind(fd, (struct sockaddr *)&addr, sizeof(addr)); + if (ret < 0) { + perror("bind"); + goto fail; + } + } else { + perror("bind"); + goto fail; + } } /* Add host to multicast group */ @@ -2557,11 +2627,15 @@ return 0; } + static int net_socket_connect_init(VLANState *vlan, const char *host_str) { NetSocketState *s; int fd, connected, ret, err; struct sockaddr_in saddr; +#ifdef _WIN32 + WSAEVENT hEvent; +#endif if (parse_host_port(&saddr, host_str) < 0) return -1; @@ -2573,6 +2647,26 @@ } socket_set_nonblock(fd); +#ifdef _WIN32 + ret = socket_set_event(fd, &hEvent); + if (ret < 0) { + perror("connect: set_event"); + closesocket(fd); + return -1; + } + + connected = 0; + ret = connect(fd, (struct sockaddr *)&saddr, sizeof(saddr)); + + err = socket_wait_event(fd, &hEvent); + if (err > 0) { + connected = 1; + } else { + perror("connect"); + closesocket(fd); + return -1; + } +#else connected = 0; for(;;) { ret = connect(fd, (struct sockaddr *)&saddr, sizeof(saddr)); @@ -2591,6 +2685,8 @@ break; } } +#endif + s = net_socket_fd_init(vlan, fd, connected); if (!s) return -1;
qemu-20060208-vlan-2.patch.gz
Description: GNU Zip compressed data
_______________________________________________ Qemu-devel mailing list Qemu-devel@nongnu.org http://lists.nongnu.org/mailman/listinfo/qemu-devel