mirror of
https://github.com/solemnwarning/ipxwrapper
synced 2024-12-30 16:45:37 +01:00
Support DOSBox servers using DNS names.
This commit is contained in:
parent
a91e05c11b
commit
435df05496
@ -1,5 +1,5 @@
|
||||
/* IPXWrapper - Interface functions
|
||||
* Copyright (C) 2011-2021 Daniel Collins <solemnwarning@solemnwarning.net>
|
||||
* Copyright (C) 2011-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
|
||||
@ -24,6 +24,7 @@
|
||||
#include <pcap.h>
|
||||
|
||||
#include "interface.h"
|
||||
#include "ipxwrapper.h"
|
||||
#include "common.h"
|
||||
#include "config.h"
|
||||
|
||||
@ -523,43 +524,50 @@ void ipx_interfaces_init(void)
|
||||
free(ip_ifaces);
|
||||
}
|
||||
|
||||
/* Virtual IPX interfaces... */
|
||||
|
||||
log_printf(LOG_INFO, "Listing IPX interfaces:");
|
||||
log_printf(LOG_INFO, "--");
|
||||
|
||||
ipx_interface_t *ipx_root = get_ipx_interfaces(), *ipx;
|
||||
|
||||
if(!ipx_root)
|
||||
if(ipx_encap_type == ENCAP_TYPE_DOSBOX)
|
||||
{
|
||||
log_printf(LOG_INFO, "No IPX interfaces detected!");
|
||||
log_printf(LOG_INFO, "--");
|
||||
log_printf(LOG_INFO, "Using DOSBox server: %s port %hu",
|
||||
main_config.dosbox_server_addr, main_config.dosbox_server_port);
|
||||
}
|
||||
|
||||
DL_FOREACH(ipx_root, ipx)
|
||||
{
|
||||
char net[ADDR32_STRING_SIZE];
|
||||
addr32_string(net, ipx->ipx_net);
|
||||
else{
|
||||
/* Virtual IPX interfaces... */
|
||||
|
||||
char node[ADDR48_STRING_SIZE];
|
||||
addr48_string(node, ipx->ipx_node);
|
||||
log_printf(LOG_INFO, "Listing IPX interfaces:");
|
||||
log_printf(LOG_INFO, "--");
|
||||
|
||||
log_printf(LOG_INFO, "Network: %s", net);
|
||||
log_printf(LOG_INFO, "Node: %s", node);
|
||||
ipx_interface_t *ipx_root = get_ipx_interfaces(), *ipx;
|
||||
|
||||
ipx_interface_ip_t *ip;
|
||||
|
||||
DL_FOREACH(ipx->ipaddr, ip)
|
||||
if(!ipx_root)
|
||||
{
|
||||
log_printf(LOG_INFO, "IP address: %s", inet_ntoa(*((struct in_addr*)&(ip->ipaddr))));
|
||||
log_printf(LOG_INFO, "Netmask: %s", inet_ntoa(*((struct in_addr*)&(ip->netmask))));
|
||||
log_printf(LOG_INFO, "Broadcast: %s", inet_ntoa(*((struct in_addr*)&(ip->bcast))));
|
||||
log_printf(LOG_INFO, "No IPX interfaces detected!");
|
||||
log_printf(LOG_INFO, "--");
|
||||
}
|
||||
|
||||
log_printf(LOG_INFO, "--");
|
||||
DL_FOREACH(ipx_root, ipx)
|
||||
{
|
||||
char net[ADDR32_STRING_SIZE];
|
||||
addr32_string(net, ipx->ipx_net);
|
||||
|
||||
char node[ADDR48_STRING_SIZE];
|
||||
addr48_string(node, ipx->ipx_node);
|
||||
|
||||
log_printf(LOG_INFO, "Network: %s", net);
|
||||
log_printf(LOG_INFO, "Node: %s", node);
|
||||
|
||||
ipx_interface_ip_t *ip;
|
||||
|
||||
DL_FOREACH(ipx->ipaddr, ip)
|
||||
{
|
||||
log_printf(LOG_INFO, "IP address: %s", inet_ntoa(*((struct in_addr*)&(ip->ipaddr))));
|
||||
log_printf(LOG_INFO, "Netmask: %s", inet_ntoa(*((struct in_addr*)&(ip->netmask))));
|
||||
log_printf(LOG_INFO, "Broadcast: %s", inet_ntoa(*((struct in_addr*)&(ip->bcast))));
|
||||
}
|
||||
|
||||
log_printf(LOG_INFO, "--");
|
||||
}
|
||||
|
||||
free_ipx_interface_list(&ipx_root);
|
||||
}
|
||||
|
||||
free_ipx_interface_list(&ipx_root);
|
||||
}
|
||||
|
||||
/* Release any resources used by the IPX interface cache. */
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* IPXWrapper - Interface header
|
||||
* Copyright (C) 2011-2021 Daniel Collins <solemnwarning@solemnwarning.net>
|
||||
* Copyright (C) 2011-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
|
||||
@ -81,7 +81,7 @@ extern enum main_config_encap_type ipx_encap_type;
|
||||
enum dosbox_state
|
||||
{
|
||||
DOSBOX_DISCONNECTED,
|
||||
DOSBOX_RESOLVING,
|
||||
/* DOSBOX_RESOLVING, */
|
||||
DOSBOX_REGISTERING,
|
||||
DOSBOX_CONNECTED,
|
||||
};
|
||||
|
@ -35,3 +35,4 @@ r_getpeername:4
|
||||
inet_ntoa:4
|
||||
__WSAFDIsSet:4
|
||||
r_WSAAsyncSelect:4
|
||||
gethostbyname:4
|
||||
|
103
src/router.c
103
src/router.c
@ -57,17 +57,20 @@ static HANDLE router_thread = NULL;
|
||||
SOCKET shared_socket = -1;
|
||||
SOCKET private_socket = -1;
|
||||
|
||||
#define DOSBOX_CONNECT_TIMEOUT_SECS 10
|
||||
|
||||
struct sockaddr_in dosbox_server_addr;
|
||||
static time_t dosbox_connect_begin;
|
||||
static HANDLE dosbox_ready_event = NULL;
|
||||
|
||||
static int dosbox_next_registration_request_at;
|
||||
static int dosbox_registration_retry_interval_ms;
|
||||
static uint64_t dosbox_next_connection_attempt_at;
|
||||
static const unsigned int dosbox_connect_retry_interval_ms = 10000;
|
||||
|
||||
static const int INITIAL_DOSBOX_REGISTRATION_RETRY_INTERVAL_MS = 250;
|
||||
static const int MAX_DOSBOX_REGISTRATION_RETRY_INTERVAL_MS = 8000;
|
||||
static uint64_t dosbox_next_registration_request_at;
|
||||
static unsigned int dosbox_registration_retry_interval_ms;
|
||||
static uint64_t dosbox_registration_timeout_at;
|
||||
|
||||
static const unsigned int INITIAL_DOSBOX_REGISTRATION_RETRY_INTERVAL_MS = 250;
|
||||
static const unsigned int MAX_DOSBOX_REGISTRATION_RETRY_INTERVAL_MS = 8000;
|
||||
|
||||
static const unsigned int DOSBOX_REGISTRATION_TIMEOUT_MS = 30000;
|
||||
|
||||
static void _send_dosbox_registration_request(void);
|
||||
static DWORD router_main(void *arg);
|
||||
@ -155,18 +158,9 @@ void router_init(void)
|
||||
abort();
|
||||
}
|
||||
|
||||
/* TODO: Support DNS. Do this async somewhere within router_main. */
|
||||
|
||||
_init_socket(&private_socket, 0, FALSE, FALSE);
|
||||
|
||||
dosbox_server_addr.sin_family = AF_INET;
|
||||
dosbox_server_addr.sin_addr.s_addr = inet_addr(main_config.dosbox_server_addr);
|
||||
dosbox_server_addr.sin_port = htons(main_config.dosbox_server_port);
|
||||
|
||||
dosbox_next_registration_request_at = 0;
|
||||
dosbox_registration_retry_interval_ms = INITIAL_DOSBOX_REGISTRATION_RETRY_INTERVAL_MS;
|
||||
|
||||
dosbox_state = DOSBOX_REGISTERING;
|
||||
dosbox_next_connection_attempt_at = 0;
|
||||
}
|
||||
else{
|
||||
_init_socket(&shared_socket, main_config.udp_port, TRUE, TRUE);
|
||||
@ -519,8 +513,7 @@ static void _handle_dosbox_registration_response(novell_ipx_packet *packet, size
|
||||
/* || packet->type != 2) */
|
||||
{
|
||||
/* Doesn't look valid. */
|
||||
log_printf(LOG_ERROR, "Got invalid registration response from DOSBox server!");
|
||||
abort();
|
||||
log_printf(LOG_ERROR, "Got invalid registration response from DOSBox server, ignoring");
|
||||
}
|
||||
|
||||
dosbox_local_netnum = addr32_in(packet->dest_net);
|
||||
@ -546,7 +539,7 @@ static void _handle_dosbox_recv(novell_ipx_packet *packet, size_t packet_size)
|
||||
if(packet_size < sizeof(novell_ipx_packet) || ntohs(packet->length) != packet_size)
|
||||
{
|
||||
/* Doesn't look valid. */
|
||||
log_printf(LOG_ERROR, "Recieved invalid IPX packet from DOSBox server, dropping");
|
||||
log_printf(LOG_ERROR, "Recieved invalid IPX packet from DOSBox server, ignoring");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -758,20 +751,32 @@ static DWORD router_main(void *arg)
|
||||
{
|
||||
DWORD wait_ms = 1000;
|
||||
|
||||
if(ipx_encap_type == ENCAP_TYPE_DOSBOX && dosbox_state == DOSBOX_REGISTERING)
|
||||
if(ipx_encap_type == ENCAP_TYPE_DOSBOX)
|
||||
{
|
||||
uint64_t now = get_ticks();
|
||||
|
||||
if(now >= dosbox_next_registration_request_at)
|
||||
if(dosbox_state == DOSBOX_DISCONNECTED)
|
||||
{
|
||||
wait_ms = 0;
|
||||
}
|
||||
else{
|
||||
wait_ms = dosbox_next_registration_request_at - 1;
|
||||
uint64_t now = get_ticks();
|
||||
|
||||
if(wait_ms > 1000)
|
||||
if(now >= dosbox_next_connection_attempt_at)
|
||||
{
|
||||
wait_ms = 1000;
|
||||
wait_ms = 0;
|
||||
}
|
||||
else{
|
||||
wait_ms = dosbox_next_connection_attempt_at - now;
|
||||
wait_ms = min(wait_ms, 1000);
|
||||
}
|
||||
}
|
||||
else if(dosbox_state == DOSBOX_REGISTERING)
|
||||
{
|
||||
uint64_t now = get_ticks();
|
||||
|
||||
if(now >= dosbox_next_registration_request_at)
|
||||
{
|
||||
wait_ms = 0;
|
||||
}
|
||||
else{
|
||||
wait_ms = dosbox_next_registration_request_at - now;
|
||||
wait_ms = min(wait_ms, 1000);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -815,10 +820,48 @@ static DWORD router_main(void *arg)
|
||||
}
|
||||
}
|
||||
|
||||
if(ipx_encap_type == ENCAP_TYPE_DOSBOX && dosbox_state == DOSBOX_DISCONNECTED)
|
||||
{
|
||||
if(get_ticks() >= dosbox_next_connection_attempt_at)
|
||||
{
|
||||
struct hostent *host = gethostbyname(main_config.dosbox_server_addr);
|
||||
|
||||
uint64_t now = get_ticks();
|
||||
|
||||
if(host != NULL)
|
||||
{
|
||||
dosbox_server_addr.sin_family = AF_INET;
|
||||
memcpy(&(dosbox_server_addr.sin_addr), host->h_addr, 4);
|
||||
dosbox_server_addr.sin_port = htons(main_config.dosbox_server_port);
|
||||
|
||||
log_printf(LOG_INFO, "Resolved DOSBox server address %s, connecting...\n", inet_ntoa(dosbox_server_addr.sin_addr));
|
||||
|
||||
dosbox_next_registration_request_at = 0;
|
||||
dosbox_registration_retry_interval_ms = INITIAL_DOSBOX_REGISTRATION_RETRY_INTERVAL_MS;
|
||||
|
||||
dosbox_registration_timeout_at = now + DOSBOX_REGISTRATION_TIMEOUT_MS;
|
||||
|
||||
dosbox_state = DOSBOX_REGISTERING;
|
||||
}
|
||||
else{
|
||||
DWORD error = WSAGetLastError();
|
||||
log_printf(LOG_ERROR, "Error resolving %s: %s (%u)",
|
||||
main_config.dosbox_server_addr, w32_error(error), (unsigned int)(error));
|
||||
|
||||
dosbox_next_connection_attempt_at = now + dosbox_connect_retry_interval_ms;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(ipx_encap_type == ENCAP_TYPE_DOSBOX && dosbox_state == DOSBOX_REGISTERING)
|
||||
{
|
||||
uint64_t now = get_ticks();
|
||||
|
||||
if(now >= dosbox_registration_timeout_at)
|
||||
{
|
||||
log_printf(LOG_ERROR, "Connection to DOSBox server %s timed out", inet_ntoa(dosbox_server_addr.sin_addr));
|
||||
dosbox_state = DOSBOX_DISCONNECTED;
|
||||
}
|
||||
if(now >= dosbox_next_registration_request_at)
|
||||
{
|
||||
_send_dosbox_registration_request();
|
||||
|
@ -266,10 +266,10 @@ describe "IPXWrapper" => sub
|
||||
};
|
||||
};
|
||||
|
||||
describe "using DOSBox UDP encapsulation" => sub
|
||||
my $dosbox_server;
|
||||
|
||||
describe "using DOSBox UDP encapsulation (via IP address)" => sub
|
||||
{
|
||||
my $dosbox_server;
|
||||
|
||||
before all => sub
|
||||
{
|
||||
reg_delete_key($remote_ip_a, "HKCU\\Software\\IPXWrapper");
|
||||
@ -277,6 +277,7 @@ describe "IPXWrapper" => sub
|
||||
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);
|
||||
|
||||
$dosbox_server = undef;
|
||||
$dosbox_server = IPXWrapper::DOSBoxServer->new($dosbox_port);
|
||||
|
||||
@expected_addrs = (
|
||||
@ -316,6 +317,90 @@ describe "IPXWrapper" => sub
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
describe "using DOSBox UDP encapsulation (via DNS name)" => sub
|
||||
{
|
||||
before all => sub
|
||||
{
|
||||
reg_delete_key($remote_ip_a, "HKCU\\Software\\IPXWrapper");
|
||||
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", "dosbox-ipv4.com");
|
||||
reg_set_dword( $remote_ip_a, "HKCU\\Software\\IPXWrapper", "dosbox_server_port", $dosbox_port);
|
||||
|
||||
$dosbox_server = undef;
|
||||
$dosbox_server = IPXWrapper::DOSBoxServer->new($dosbox_port);
|
||||
|
||||
@expected_addrs = (
|
||||
{
|
||||
# The node number is randomly selected by the DOSBox server
|
||||
# when each client connects.
|
||||
|
||||
net => "00:00:00:00",
|
||||
maxpkt => DOSBOX_MAX_DATA_SIZE,
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
after all => sub
|
||||
{
|
||||
$dosbox_server = undef;
|
||||
};
|
||||
|
||||
# Duplicate of common getsockopt block to skip the default interface selection
|
||||
# logic test (because there is only ever one interface here).
|
||||
describe "getsockopt" => sub
|
||||
{
|
||||
it "returns correct addresses" => sub
|
||||
{
|
||||
my @addrs = getsockopt_interfaces($remote_ip_a);
|
||||
cmp_hashes_partial(\@addrs, \@expected_addrs);
|
||||
};
|
||||
|
||||
it "returns correct IPX_MAX_ADAPTER_NUM" => sub
|
||||
{
|
||||
my @addrs = getsockopt_interfaces($remote_ip_a);
|
||||
|
||||
my $output = run_remote_cmd($remote_ip_a, "Z:\\tools\\list-interfaces.exe");
|
||||
my ($got_num) = ($output =~ m/^IPX_MAX_ADAPTER_NUM = (\d+)$/m);
|
||||
|
||||
is($got_num, (scalar @addrs));
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
describe "using DOSBox UDP encapsulation (server is down)" => sub
|
||||
{
|
||||
before all => sub
|
||||
{
|
||||
reg_delete_key($remote_ip_a, "HKCU\\Software\\IPXWrapper");
|
||||
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);
|
||||
|
||||
$dosbox_server = undef;
|
||||
};
|
||||
|
||||
# Duplicate of common getsockopt block to skip the default interface selection
|
||||
# logic test (because there is only ever one interface here).
|
||||
describe "getsockopt" => sub
|
||||
{
|
||||
it "returns no addresses" => sub
|
||||
{
|
||||
my @addrs = getsockopt_interfaces($remote_ip_a);
|
||||
cmp_deeply(\@addrs, []);
|
||||
};
|
||||
|
||||
it "returns correct IPX_MAX_ADAPTER_NUM" => sub
|
||||
{
|
||||
my @addrs = getsockopt_interfaces($remote_ip_a);
|
||||
|
||||
my $output = run_remote_cmd($remote_ip_a, "Z:\\tools\\list-interfaces.exe");
|
||||
my ($got_num) = ($output =~ m/^IPX_MAX_ADAPTER_NUM = (\d+)$/m);
|
||||
|
||||
is($got_num, 0);
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
sub get_first_addr_node
|
||||
|
@ -45,7 +45,7 @@ describe "IPXWrapper using DOSBox UDP encapsulation" => sub
|
||||
{
|
||||
reg_delete_key($remote_ip_a, "HKCU\\Software\\IPXWrapper");
|
||||
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_string($remote_ip_a, "HKCU\\Software\\IPXWrapper", "dosbox_server_addr", "dosbox-ipv4.com");
|
||||
reg_set_dword( $remote_ip_a, "HKCU\\Software\\IPXWrapper", "dosbox_server_port", $dosbox_port);
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user