From a91e05c11b69f4c03b49fa1fa1b267ba1fd229c7 Mon Sep 17 00:00:00 2001 From: Daniel Collins Date: Sun, 10 Sep 2023 22:33:54 +0100 Subject: [PATCH] Add more DOXBox encapsulation tests. --- tests/30-dosbox-ipx.t | 420 +++++++++++++++++++++------- tests/lib/IPXWrapper/Tool/IPXISR.pm | 22 +- tools/ipx-isr.c | 15 +- 3 files changed, 354 insertions(+), 103 deletions(-) diff --git a/tests/30-dosbox-ipx.t b/tests/30-dosbox-ipx.t index 037a8be..c803dee 100644 --- a/tests/30-dosbox-ipx.t +++ b/tests/30-dosbox-ipx.t @@ -37,11 +37,6 @@ our ($remote_mac_b, $remote_ip_b); our ($net_a_bcast, $net_b_bcast); our ($dosbox_port); -require "$FindBin::Bin/ptype.pm"; - -our $ptype_send_func; -our $ptype_capture_class; - describe "IPXWrapper using DOSBox UDP encapsulation" => sub { my $dosbox_server; @@ -52,7 +47,11 @@ describe "IPXWrapper using DOSBox UDP encapsulation" => sub reg_set_dword( $remote_ip_a, "HKCU\\Software\\IPXWrapper", "use_pcap", ENCAP_TYPE_DOSBOX); reg_set_string($remote_ip_a, "HKCU\\Software\\IPXWrapper", "dosbox_server_addr", $local_ip_a); reg_set_dword( $remote_ip_a, "HKCU\\Software\\IPXWrapper", "dosbox_server_port", $dosbox_port); - + }; + + before each => sub + { + $dosbox_server = undef; $dosbox_server = IPXWrapper::DOSBoxServer->new($dosbox_port); }; @@ -61,119 +60,346 @@ describe "IPXWrapper using DOSBox UDP encapsulation" => sub $dosbox_server = undef; }; - it "handles unicast packets from the server" => sub + describe "a single process" => sub { - my $capture_a = IPXWrapper::Tool::IPXRecv->new( - $remote_ip_a, - "-b", "-r", "00:00:00:00", "00:00:00:00:00:00", "4444", - ); - - my $client = IPXWrapper::DOSBoxClient->new($local_ip_a, $dosbox_port); - - note("Their node number is ".$capture_a->node()); - note("My node number is ".$client->node()); - - $client->send( - tc => 0, - type => 0, + it "handles unicast packets from the server" => sub + { + my $capture_a = IPXWrapper::Tool::IPXRecv->new( + $remote_ip_a, + "-b", "00:00:00:00", "00:00:00:00:00:00", "4444", + ); - dest_network => "00:00:00:00", - dest_node => $capture_a->node(), - dest_socket => 4444, + my $client = IPXWrapper::DOSBoxClient->new($local_ip_a, $dosbox_port); - src_network => $client->net(), - src_node => $client->node(), - src_socket => 1234, + note("Their node number is ".$capture_a->node()); + note("My node number is ".$client->node()); - data => "damage", - ); - - sleep(1); - - my @packets_a = $capture_a->kill_and_read(); - - cmp_hashes_partial(\@packets_a, [ - { - src_network => "00:00:00:00", + $client->send( + tc => 0, + type => 0, + + dest_network => "00:00:00:00", + dest_node => $capture_a->node(), + dest_socket => 4444, + + src_network => $client->net(), src_node => $client->node(), src_socket => 1234, data => "damage", - }, - ]); - }; - - it "handles broadcast packets from the server" => sub - { - my $capture_a = IPXWrapper::Tool::IPXRecv->new( - $remote_ip_a, - "-b", "-r", "00:00:00:00", "00:00:00:00:00:00", "4444", - ); - - my $client = IPXWrapper::DOSBoxClient->new($local_ip_a, $dosbox_port); - - note("Their node number is ".$capture_a->node()); - note("My node number is ".$client->node()); - - $client->send( - tc => 0, - type => 0, + ); - dest_network => "00:00:00:00", - dest_node => "FF:FF:FF:FF:FF:FF", - dest_socket => 4444, + sleep(1); - src_network => $client->net(), - src_node => $client->node(), - src_socket => 1234, + my @packets_a = $capture_a->kill_and_read(); - data => "location", - ); + cmp_hashes_partial(\@packets_a, [ + { + src_network => "00:00:00:00", + src_node => $client->node(), + src_socket => 1234, + + data => "damage", + }, + ]); + }; - sleep(1); - - my @packets_a = $capture_a->kill_and_read(); - - cmp_hashes_partial(\@packets_a, [ - { - src_network => "00:00:00:00", + it "handles broadcast packets from the server" => sub + { + my $capture_a = IPXWrapper::Tool::IPXRecv->new( + $remote_ip_a, + "-b", "00:00:00:00", "00:00:00:00:00:00", "4444", + ); + + my $client = IPXWrapper::DOSBoxClient->new($local_ip_a, $dosbox_port); + + note("Their node number is ".$capture_a->node()); + note("My node number is ".$client->node()); + + $client->send( + tc => 0, + type => 0, + + dest_network => "00:00:00:00", + dest_node => "FF:FF:FF:FF:FF:FF", + dest_socket => 4444, + + src_network => $client->net(), src_node => $client->node(), src_socket => 1234, data => "location", - }, - ]); + ); + + sleep(1); + + my @packets_a = $capture_a->kill_and_read(); + + cmp_hashes_partial(\@packets_a, [ + { + src_network => "00:00:00:00", + src_node => $client->node(), + src_socket => 1234, + + data => "location", + }, + ]); + }; + + it "sends unicast packets to server" => sub + { + my $client = IPXWrapper::DOSBoxClient->new($local_ip_a, $dosbox_port); + + note("My node number is ".$client->node()); + + run_remote_cmd( + $remote_ip_a, "Z:\\tools\\ipx-send.exe", + "-d" => "tasty", + "-s" => "5555", + "00:00:00:00", $client->node(), "4444", + ); + + sleep(1); + + my @packets = $client->recv_any(); + + cmp_hashes_partial(\@packets, [ + { + src_network => "00:00:00:00", + src_socket => 5555, + + dest_network => "00:00:00:00", + dest_node => $client->node(), + dest_socket => 4444, + + data => "tasty", + }, + ]); + }; }; - it "sends unicast packets to server" => sub + describe "concurrent processes" => sub { - my $client = IPXWrapper::DOSBoxClient->new($local_ip_a, $dosbox_port); - - note("My node number is ".$client->node()); - - run_remote_cmd( - $remote_ip_a, "Z:\\tools\\ipx-send.exe", - "-d" => "tasty", - "-s" => "5555", - "00:00:00:00", $client->node(), "4444", - ); - - sleep(1); - - my @packets = $client->recv_any(); - - cmp_hashes_partial(\@packets, [ - { - src_network => "00:00:00:00", - src_socket => 5555, + they "recieve direct unicast packets from another machine" => sub + { + my $capture_a = IPXWrapper::Tool::IPXRecv->new( + $remote_ip_a, + "00:00:00:00", "00:00:00:00:00:00", "4444", + ); + + my $capture_b = IPXWrapper::Tool::IPXRecv->new( + $remote_ip_a, + "00:00:00:00", "00:00:00:00:00:00", "4445", + ); + + my $client = IPXWrapper::DOSBoxClient->new($local_ip_a, $dosbox_port); + + note("\$capture_a address is ".$capture_a->net()."/".$capture_a->node()); + note("\$capture_b address is ".$capture_b->net()."/".$capture_b->node()); + note("My address is ".$client->net()."/".$client->node()); + + $client->send( + tc => 0, + type => 0, - dest_network => "00:00:00:00", - dest_node => $client->node(), + dest_network => $capture_a->net(),, + dest_node => $capture_a->node(), dest_socket => 4444, - data => "tasty", - }, - ]); + src_network => $client->net(), + src_node => $client->node(), + src_socket => 1234, + + data => "full", + ); + + $client->send( + tc => 0, + type => 0, + + dest_network => $capture_b->net(),, + dest_node => $capture_b->node(), + dest_socket => 4445, + + src_network => $client->net(), + src_node => $client->node(), + src_socket => 1234, + + data => "accent", + ); + + sleep(1); + + my @packets_a = $capture_a->kill_and_read(); + my @packets_b = $capture_b->kill_and_read(); + + cmp_hashes_partial(\@packets_a, [ + { + src_network => $client->net(), + src_node => $client->node(), + src_socket => 1234, + + data => "full", + }, + ]); + + cmp_hashes_partial(\@packets_b, [ + { + src_network => $client->net(), + src_node => $client->node(), + src_socket => 1234, + + data => "accent", + }, + ]); + }; + + they "recieve direct unicast packets from each other" => sub + { + my $capture_a = IPXWrapper::Tool::IPXISR->new( + $remote_ip_a, + "00:00:00:00", "00:00:00:00:00:00", "4444", + ); + + my $capture_b = IPXWrapper::Tool::IPXISR->new( + $remote_ip_a, + "00:00:00:00", "00:00:00:00:00:00", "4445", + ); + + note("\$capture_a address is ".$capture_a->net()."/".$capture_a->node()); + note("\$capture_b address is ".$capture_b->net()."/".$capture_b->node()); + + $capture_a->send($capture_b->net(), $capture_b->node(), 4445, "reader"); + $capture_b->send($capture_a->net(), $capture_a->node(), 4444, "earwax"); + + sleep(1); + + my @packets_a = $capture_a->kill_and_read(); + my @packets_b = $capture_b->kill_and_read(); + + cmp_hashes_partial(\@packets_a, [ + { + src_net => $capture_b->net(), + src_node => $capture_b->node(), + src_socket => 4445, + + data => "earwax", + }, + ]); + + cmp_hashes_partial(\@packets_b, [ + { + src_net => $capture_a->net(), + src_node => $capture_a->node(), + src_socket => 4444, + + data => "reader", + }, + ]); + }; + + they "recieve broadcast packets from another machine" => sub + { + my $capture_a = IPXWrapper::Tool::IPXRecv->new( + $remote_ip_a, + "-r", "-b", "00:00:00:00", "00:00:00:00:00:00", "4444", + ); + + my $capture_b = IPXWrapper::Tool::IPXRecv->new( + $remote_ip_a, + "-r", "-b", "00:00:00:00", "00:00:00:00:00:00", "4444", + ); + + my $client = IPXWrapper::DOSBoxClient->new($local_ip_a, $dosbox_port); + + note("\$capture_a address is ".$capture_a->net()."/".$capture_a->node()); + note("\$capture_b address is ".$capture_b->net()."/".$capture_b->node()); + note("My address is ".$client->net()."/".$client->node()); + + $client->send( + tc => 0, + type => 0, + + dest_network => "FF:FF:FF:FF", + dest_node => "FF:FF:FF:FF:FF:FF", + dest_socket => 4444, + + src_network => $client->net(), + src_node => $client->node(), + src_socket => 1234, + + data => "cylinder", + ); + + sleep(1); + + my @packets_a = $capture_a->kill_and_read(); + my @packets_b = $capture_b->kill_and_read(); + + cmp_hashes_partial(\@packets_a, [ + { + src_network => $client->net(), + src_node => $client->node(), + src_socket => 1234, + + data => "cylinder", + }, + ]); + + cmp_hashes_partial(\@packets_b, [ + { + src_network => $client->net(), + src_node => $client->node(), + src_socket => 1234, + + data => "cylinder", + }, + ]); + }; + + they "recieve broadcast packets from each other" => sub + { + my $capture_a = IPXWrapper::Tool::IPXISR->new( + $remote_ip_a, + "-r", "-b", "00:00:00:00", "00:00:00:00:00:00", "4444", + ); + + my $capture_b = IPXWrapper::Tool::IPXISR->new( + $remote_ip_a, + "-r", "-b", "00:00:00:00", "00:00:00:00:00:00", "4444", + ); + + note("\$capture_a address is ".$capture_a->net()."/".$capture_a->node()); + note("\$capture_b address is ".$capture_b->net()."/".$capture_b->node()); + + $capture_a->send($capture_a->net(), "FF:FF:FF:FF:FF:FF", 4444, "export"); + $capture_b->send($capture_b->net(), "FF:FF:FF:FF:FF:FF", 4444, "addicted"); + + sleep(1); + + my @packets_a = $capture_a->kill_and_read(); + my @packets_b = $capture_b->kill_and_read(); + + cmp_hashes_partial(\@packets_a, [ + { + src_net => $capture_b->net(), + src_node => $capture_b->node(), + src_socket => 4444, + + data => "addicted", + }, + ]); + + cmp_hashes_partial(\@packets_b, [ + { + src_net => $capture_a->net(), + src_node => $capture_a->node(), + src_socket => 4444, + + data => "export", + }, + ]); + }; }; }; diff --git a/tests/lib/IPXWrapper/Tool/IPXISR.pm b/tests/lib/IPXWrapper/Tool/IPXISR.pm index e7d4de9..9f1d372 100644 --- a/tests/lib/IPXWrapper/Tool/IPXISR.pm +++ b/tests/lib/IPXWrapper/Tool/IPXISR.pm @@ -1,5 +1,5 @@ # IPXWrapper test suite -# Copyright (C) 2014 Daniel Collins +# Copyright (C) 2014-2023 Daniel Collins # # 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 @@ -38,8 +38,6 @@ sub new pid => $pid, in => $in, out => $out, - - sockets => {}, }, $class); my $output = ""; @@ -50,8 +48,12 @@ sub new $line =~ s/[\r\n]//g; - if($line eq "Ready") + if($line =~ m/^Ready (\S+) (\S+) (\S+)$/) { + $self->{net} = $1; + $self->{node} = $2; + $self->{socket} = $3; + return $self; } } @@ -69,6 +71,18 @@ sub DESTROY } } +sub net +{ + my ($self) = @_; + return $self->{net}; +} + +sub node +{ + my ($self) = @_; + return $self->{node}; +} + sub _end { my ($self) = @_; diff --git a/tools/ipx-isr.c b/tools/ipx-isr.c index 1a7fe39..9d56289 100644 --- a/tools/ipx-isr.c +++ b/tools/ipx-isr.c @@ -1,5 +1,5 @@ /* IPXWrapper test tools - * Copyright (C) 2014 Daniel Collins + * Copyright (C) 2014-2023 Daniel Collins * * 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 @@ -99,7 +99,18 @@ int main(int argc, char **argv) HANDLE send_thread_h = CreateThread(NULL, 0, &send_thread, &sock, 0, NULL); assert(send_thread_h != NULL); - printf("Ready\n"); + { + int addrlen = sizeof(local_addr); + assert(getsockname(sock, (struct sockaddr*)(&local_addr), &addrlen) == 0); + + char net_s[ADDR32_STRING_SIZE]; + addr32_string(net_s, addr32_in(local_addr.sa_netnum)); + + char node_s[ADDR48_STRING_SIZE]; + addr48_string(node_s, addr48_in(local_addr.sa_nodenum)); + + printf("Ready %s %s %hu\n", net_s, node_s, ntohs(local_addr.sa_socket)); + } char buf[1024]; while(1)