Revamp client's Windows POSIX compatibility code

Unlike POSIX sockets, Windows sockets are not file descriptors, but
"OS handles", with a completely separate set of functions.

However, Windows can create a file descriptor for a socket, and return
a file descriptor's underlying handle.  Use that instead of our gross
hacks to keep up the illusion that sockets are file descriptors.
Slightly dirty: we put file descriptors into fd_set.  Works because
both boil down to int.  Change w32_select(), w32_socket(),
w32_connect(), w32_recv(), w32_writev_socket(), w32_send() to take and
return only file descriptors, and map to sockets internally.  Replace
w32_close_socket() by w32_close(), and drop the close() macro hackery
that made tcp_connect(), host_connect() use w32_close_socket().  New
fd_is_socket().

Windows provides select()-like functions only for handles.  Because of
that, the client used a handle for reading script files, and stored it
in file descriptor input_fd.  Drop this dirty hack, use a file
descriptor instead.  Works because we can get its underlying handle.
Remove the dirty macro hackery that made play(), ring_from_file() and
doexecute() unwittingly work with a handle.  Remove w32_openhandle()
and w32_close_handle().  Replace w32_readv_handle() by w32_readv_fd().
Update w32_select().

Remove w32_openfd(), it's not really needed.

The old code stuffed WSA error codes into errno, which doesn't work.
Use new w32_set_winsock_errno() to convert & stuff.

Fix signed vs. unsigned warnings in Windows client.

Move the struct sigaction replacement next to the sigaction()
replacement.

Rename sysdep_init() to w32_sysdep_init() for consistency.
This commit is contained in:
Markus Armbruster 2009-04-13 15:08:13 +02:00
parent f4209f7ea9
commit 798af5b45b
8 changed files with 155 additions and 176 deletions

View file

@ -28,7 +28,7 @@
* play.c: Playing the game
*
* Known contributors to this file:
* Markus Armbruster, 2007
* Markus Armbruster, 2007-2009
* Ron Koenderink, 2007-2009
*/
@ -71,6 +71,11 @@ static HANDLE bounce_full;
static HANDLE ctrl_c_event;
static int bounce_status, bounce_error;
struct sigaction {
int sa_flags;
void (*sa_handler)(int sig);
};
#define SIGPIPE -1
static void (*ctrl_handler)(int sig) = { SIG_DFL };
@ -170,45 +175,45 @@ sysdep_stdin_init(void)
/*
* This function uses to WaitForMultipleObjects to wait for both
* stdin and socket reading or writing.
* Stdin is treated special in WIN32. Waiting for stdin is done
* Stdin is treated special in WIN32. Waiting for stdin is done
* via a bounce_full event which is set in the stdin thread.
* Execute command file reading is done via handle. Execute
* command is read via CreateFile/ReadFile instead open/read
* because a file descriptor is not waitable.
* WaitForMultipleObjects will only respond with one object
* Execute command file reading is done via handle.
* WaitForMultipleObjects will only respond with one object,
* so an additonal select is also done to determine
* which individual events are active for the sock.
* which individual events are active.
*/
static int
w32_select(int nfds, fd_set *rdfd, fd_set *wrfd, fd_set *errfd, struct timeval* time)
{
HANDLE handles[3];
SOCKET sock;
int inp, result, s_result, num_handles;
int inp, sockfd, result, s_result, num_handles;
struct timeval tv_time = {0, 0};
fd_set rdfd2;
fd_set rdsock, wrsock;
switch (rdfd->fd_count) {
case 1:
inp = -1;
sock = rdfd->fd_array[0];
sockfd = rdfd->fd_array[0];
break;
case 2:
inp = rdfd->fd_array[0];
sock = rdfd->fd_array[1];
sockfd = rdfd->fd_array[1];
break;
default:
assert(0);
}
sock = W32_FD_TO_SOCKET(sockfd);
assert(wrfd->fd_count == 0
|| (wrfd->fd_count == 1 && wrfd->fd_array[0] == sock));
|| (wrfd->fd_count == 1 && wrfd->fd_array[0] == (SOCKET)sockfd));
assert(inp < 0 || inp == input_fd);
num_handles = 0;
handles[num_handles++] = ctrl_c_event;
if (inp >= 0)
handles[num_handles++] = inp ? (HANDLE)inp : bounce_full;
handles[num_handles++]
= inp ? (HANDLE)_get_osfhandle(inp) : bounce_full;
/* always wait on the socket */
handles[num_handles++] = WSACreateEvent();
@ -232,20 +237,27 @@ w32_select(int nfds, fd_set *rdfd, fd_set *wrfd, fd_set *errfd, struct timeval*
return -1;
}
FD_ZERO(&rdfd2);
FD_SET(sock, &rdfd2);
s_result = select(sock + 1, &rdfd2, wrfd, NULL, &tv_time);
FD_ZERO(&rdsock);
FD_ZERO(&wrsock);
FD_SET(sock, &rdsock);
if (wrfd->fd_count)
FD_SET(sock, &wrsock);
s_result = select(sock + 1, &rdsock, &wrsock, NULL, &tv_time);
if (s_result < 0) {
errno = WSAGetLastError();
w32_set_winsock_errno();
return s_result;
}
*rdfd = rdfd2;
if (inp >= 0 && result == WAIT_OBJECT_0 + 1) {
FD_SET((SOCKET)inp, rdfd);
if (!FD_ISSET(sock, &rdsock))
FD_CLR((SOCKET)sockfd, rdfd);
if (!FD_ISSET(sock, &wrsock))
FD_CLR((SOCKET)sockfd, wrfd);
if (inp >= 0 && result == WAIT_OBJECT_0 + 1)
s_result++;
}
else
FD_CLR((SOCKET)inp, rdfd);
return s_result;
}
@ -282,7 +294,6 @@ w32_ring_from_file_or_bounce_buf(struct ring *r, int fd)
return res;
}
#define ring_from_file w32_ring_from_file_or_bounce_buf
#define close(fd) w32_close_handle((fd))
#define read(sock, buffer, buf_size) \
w32_recv((sock), (buffer), (buf_size), 0)
#define select(nfds, rd, wr, error, time) \