mirror of
https://github.com/solemnwarning/ipxwrapper
synced 2024-12-30 16:45:37 +01:00
Fix select(), add some tests.
This commit is contained in:
parent
15b53ae001
commit
e9c45b8ac5
5
Makefile
5
Makefile
@ -46,7 +46,7 @@ BIN_FILES := $(shell cat manifest.bin.txt)
|
|||||||
SRC_FILES := $(shell cat manifest.src.txt)
|
SRC_FILES := $(shell cat manifest.src.txt)
|
||||||
|
|
||||||
# Tests to compile before running the test suite.
|
# Tests to compile before running the test suite.
|
||||||
TESTS := tests/addr.exe tests/addrcache.exe tests/ethernet.exe
|
TESTS := tests/addr.exe tests/addrcache.exe tests/ethernet.exe tools/fionread.exe
|
||||||
|
|
||||||
# Tools to compile before running the test suite.
|
# Tools to compile before running the test suite.
|
||||||
TOOLS := tools/socket.exe tools/list-interfaces.exe tools/bind.exe tools/ipx-send.exe \
|
TOOLS := tools/socket.exe tools/list-interfaces.exe tools/bind.exe tools/ipx-send.exe \
|
||||||
@ -178,6 +178,9 @@ tests/%.o: tests/%.c
|
|||||||
$(CC) $(CFLAGS) $(DEPFLAGS) -I./ -c -o $@ $<
|
$(CC) $(CFLAGS) $(DEPFLAGS) -I./ -c -o $@ $<
|
||||||
$(DEPPOST)
|
$(DEPPOST)
|
||||||
|
|
||||||
|
tools/fionread.exe: tests/fionread.o tests/tap/basic.o src/addr.o
|
||||||
|
$(CC) $(CFLAGS) -o $@ $^ -lwsock32
|
||||||
|
|
||||||
tools/%.exe: tools/%.o src/addr.o
|
tools/%.exe: tools/%.o src/addr.o
|
||||||
$(CC) $(CFLAGS) -o $@ $^ -lwsock32 -lole32 -lrpcrt4
|
$(CC) $(CFLAGS) -o $@ $^ -lwsock32 -lole32 -lrpcrt4
|
||||||
|
|
||||||
|
@ -21,3 +21,4 @@ EXPORTS
|
|||||||
listen
|
listen
|
||||||
accept
|
accept
|
||||||
WSAAsyncSelect
|
WSAAsyncSelect
|
||||||
|
select
|
||||||
|
@ -2668,6 +2668,8 @@ int WSAAPI select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds
|
|||||||
fd_set force_read_fds;
|
fd_set force_read_fds;
|
||||||
FD_ZERO(&force_read_fds);
|
FD_ZERO(&force_read_fds);
|
||||||
|
|
||||||
|
if(readfds != NULL)
|
||||||
|
{
|
||||||
for(unsigned int i = 0; i < readfds->fd_count; ++i)
|
for(unsigned int i = 0; i < readfds->fd_count; ++i)
|
||||||
{
|
{
|
||||||
int fd = readfds->fd_array[i];
|
int fd = readfds->fd_array[i];
|
||||||
@ -2683,10 +2685,11 @@ int WSAAPI select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds
|
|||||||
|
|
||||||
if(sockptr->recv_queue->n_ready > 0)
|
if(sockptr->recv_queue->n_ready > 0)
|
||||||
{
|
{
|
||||||
/* There is data in the receive queue for this socket, but the
|
/* There is data in the receive queue for this socket, but
|
||||||
* underlying socket isn't necessarily readable, so we reduce the
|
* the underlying socket isn't necessarily readable, so we
|
||||||
* select() timeout to zero to ensure it returns immediately and
|
* reduce the select() timeout to zero to ensure it returns
|
||||||
* inject this fd back into readfds at the end if necessary.
|
* immediately and inject this fd back into readfds at the
|
||||||
|
* end if necessary.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
FD_SET(fd, &force_read_fds);
|
FD_SET(fd, &force_read_fds);
|
||||||
@ -2696,6 +2699,7 @@ int WSAAPI select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds
|
|||||||
unlock_sockets();
|
unlock_sockets();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int r = r_select(nfds, readfds, writefds, exceptfds, (const PTIMEVAL)(use_timeout));
|
int r = r_select(nfds, readfds, writefds, exceptfds, (const PTIMEVAL)(use_timeout));
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ ntohl
|
|||||||
ntohs
|
ntohs
|
||||||
recv:0
|
recv:0
|
||||||
recvfrom:0
|
recvfrom:0
|
||||||
select
|
select:0
|
||||||
send:0
|
send:0
|
||||||
sendto:0
|
sendto:0
|
||||||
setsockopt:0
|
setsockopt:0
|
||||||
|
34
tests/25-fionread.t
Normal file
34
tests/25-fionread.t
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
# IPXWrapper test suite
|
||||||
|
# Copyright (C) 2023 Daniel Collins <solemnwarning@solemnwarning.net>
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or modify it
|
||||||
|
# under the terms of the GNU General Public License version 2 as published by
|
||||||
|
# the Free Software Foundation.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
# more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License along with
|
||||||
|
# this program; if not, write to the Free Software Foundation, Inc., 51
|
||||||
|
# Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
|
||||||
|
use FindBin;
|
||||||
|
use lib "$FindBin::Bin/lib/";
|
||||||
|
|
||||||
|
use IPXWrapper::Util;
|
||||||
|
|
||||||
|
require "$FindBin::Bin/config.pm";
|
||||||
|
our ($remote_mac_a, $remote_ip_a);
|
||||||
|
|
||||||
|
reg_delete_key($remote_ip_a, "HKCU\\Software\\IPXWrapper");
|
||||||
|
|
||||||
|
# Unit tests implemented by fionread.exe, so run it on the test system and pass
|
||||||
|
# the (TAP) output/exit status to our parent.
|
||||||
|
|
||||||
|
system("ssh", $remote_ip_a, "Z:\\tools\\fionread.exe", "00:00:00:01", $remote_mac_a);
|
||||||
|
exit($? >> 8);
|
134
tests/fionread.c
Normal file
134
tests/fionread.c
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
/* IPXWrapper test suite
|
||||||
|
* Copyright (C) 2023 Daniel Collins <solemnwarning@solemnwarning.net>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 as published by
|
||||||
|
* the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with
|
||||||
|
* this program; if not, write to the Free Software Foundation, Inc., 51
|
||||||
|
* Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <winsock2.h>
|
||||||
|
#include <windows.h>
|
||||||
|
#include <wsipx.h>
|
||||||
|
|
||||||
|
#include "tap/basic.h"
|
||||||
|
#include "../tools/tools.h"
|
||||||
|
|
||||||
|
static char buf[4096];
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
if(argc != 3)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Usage: %s <netnum> <nodenum>\n", argv[0]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
plan_lazy();
|
||||||
|
|
||||||
|
struct sockaddr_ipx addr1 = read_sockaddr(argv[1], argv[2], "1234");
|
||||||
|
struct sockaddr_ipx addr2 = read_sockaddr(argv[1], argv[2], "1235");
|
||||||
|
|
||||||
|
WSADATA data;
|
||||||
|
WSAStartup(MAKEWORD(1, 1), &data);
|
||||||
|
|
||||||
|
int sock1 = socket(AF_IPX, SOCK_DGRAM, NSPROTO_IPX);
|
||||||
|
assert(sock1 != SOCKET_ERROR);
|
||||||
|
|
||||||
|
assert(bind(sock1, (struct sockaddr*)(&addr1), sizeof(addr1)) == 0);
|
||||||
|
|
||||||
|
int sock2 = socket(AF_IPX, SOCK_DGRAM, NSPROTO_IPX);
|
||||||
|
assert(sock2 != SOCKET_ERROR);
|
||||||
|
|
||||||
|
assert(bind(sock2, (struct sockaddr*)(&addr2), sizeof(addr2)) == 0);
|
||||||
|
|
||||||
|
fd_set readfds;
|
||||||
|
struct timeval timeout = { 0, 0 };
|
||||||
|
|
||||||
|
unsigned long x = 123456789;
|
||||||
|
int r = ioctlsocket(sock1, FIONREAD, &x);
|
||||||
|
|
||||||
|
is_int(0, r, "ioctlsocket(FIONREAD) succeeds when no packets are waiting");
|
||||||
|
is_int(0, x, "ioctlsocket(FIONREAD) returns zero bytes when no packets are waiting");
|
||||||
|
|
||||||
|
FD_ZERO(&readfds);
|
||||||
|
FD_SET(sock1, &readfds);
|
||||||
|
is_int(select(-1, &readfds, NULL, NULL, &timeout), 0, "select() initially indicates socket is not ready to read");
|
||||||
|
ok(!FD_ISSET(sock1, &readfds), "select() initially indicates socket is not ready to read");
|
||||||
|
|
||||||
|
assert(sendto(sock2, buf, 128, 0, (struct sockaddr*)(&addr1), sizeof(addr1)) == 128);
|
||||||
|
|
||||||
|
/* Just in case there's any async going on */
|
||||||
|
Sleep(100);
|
||||||
|
|
||||||
|
FD_ZERO(&readfds);
|
||||||
|
FD_SET(sock1, &readfds);
|
||||||
|
is_int(select(-1, &readfds, NULL, NULL, &timeout), 1, "select() indicates socket is ready to read before call to ioctlsocket(FIONREAD)");
|
||||||
|
ok(FD_ISSET(sock1, &readfds), "select() indicates socket is ready to read before call to ioctlsocket(FIONREAD)");
|
||||||
|
|
||||||
|
x = 123456789;
|
||||||
|
r = ioctlsocket(sock1, FIONREAD, &x);
|
||||||
|
|
||||||
|
is_int(0, r, "ioctlsocket(FIONREAD) succeeds when packets are waiting");
|
||||||
|
is_int(128, x, "ioctlsocket(FIONREAD) returns payload size when one packet is waiting");
|
||||||
|
|
||||||
|
FD_ZERO(&readfds);
|
||||||
|
FD_SET(sock1, &readfds);
|
||||||
|
is_int(select(-1, &readfds, NULL, NULL, &timeout), 1, "select() indicates socket is ready to read after call to ioctlsocket(FIONREAD)");
|
||||||
|
ok(FD_ISSET(sock1, &readfds), "select() indicates socket is ready to read after call to ioctlsocket(FIONREAD)");
|
||||||
|
|
||||||
|
assert(sendto(sock2, buf, 256, 0, (struct sockaddr*)(&addr1), sizeof(addr1)) == 256);
|
||||||
|
|
||||||
|
/* Just in case there's any async going on */
|
||||||
|
Sleep(100);
|
||||||
|
|
||||||
|
x = 123456789;
|
||||||
|
r = ioctlsocket(sock1, FIONREAD, &x);
|
||||||
|
|
||||||
|
is_int(0, r, "ioctlsocket(FIONREAD) succeeds when packets are waiting");
|
||||||
|
is_int(384, x, "ioctlsocket(FIONREAD) returns combined payload sizes when multiple packets are waiting");
|
||||||
|
|
||||||
|
assert(recv(sock1, buf, 4096, 0) == 128);
|
||||||
|
|
||||||
|
FD_ZERO(&readfds);
|
||||||
|
FD_SET(sock1, &readfds);
|
||||||
|
is_int(select(-1, &readfds, NULL, NULL, &timeout), 1, "select() indicates socket is ready to read after reading first packet");
|
||||||
|
ok(FD_ISSET(sock1, &readfds), "select() indicates socket is ready to read after reading first packet");
|
||||||
|
|
||||||
|
x = 123456789;
|
||||||
|
r = ioctlsocket(sock1, FIONREAD, &x);
|
||||||
|
|
||||||
|
is_int(0, r, "ioctlsocket(FIONREAD) succeeds when packets are waiting");
|
||||||
|
is_int(256, x, "ioctlsocket(FIONREAD) returns payload sizes when one packet is waiting");
|
||||||
|
|
||||||
|
assert(recv(sock1, buf, 4096, 0) == 256);
|
||||||
|
|
||||||
|
FD_ZERO(&readfds);
|
||||||
|
FD_SET(sock1, &readfds);
|
||||||
|
is_int(select(-1, &readfds, NULL, NULL, &timeout), 0, "select() indicates socket is not ready to read after reading second packet");
|
||||||
|
ok(!FD_ISSET(sock1, &readfds), "select() indicates socket is ready to read after reading second packet");
|
||||||
|
|
||||||
|
x = 123456789;
|
||||||
|
r = ioctlsocket(sock1, FIONREAD, &x);
|
||||||
|
|
||||||
|
is_int(0, r, "ioctlsocket(FIONREAD) succeeds when no packets are waiting");
|
||||||
|
is_int(0, x, "ioctlsocket(FIONREAD) returns zero bytes when no packets are waiting");
|
||||||
|
|
||||||
|
closesocket(sock2);
|
||||||
|
closesocket(sock1);
|
||||||
|
|
||||||
|
WSACleanup();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@ -8,7 +8,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "addr.h"
|
#include "../src/addr.h"
|
||||||
|
|
||||||
static struct sockaddr_ipx read_sockaddr(const char *net_s, const char *node_s, const char *socket_s)
|
static struct sockaddr_ipx read_sockaddr(const char *net_s, const char *node_s, const char *socket_s)
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user