Be able to leverage DOSBox's IPX/UDP protocol
In DOSBox, I'm using an IPX dedicated relay server to play via routable IP, but not in the same LAN.
In Windows, I need to use a VPN, which is complex to setup, and it added quite some latency when I relied on it with DOSBox. It seems that I'm not alone, as #8 shows. Directly using UDP made it smooth in DOSBox, and I guess it might be the same in Windows.
Therefore, would it be possible to have a DOSBox-compatible mode ? 😉
Note: huge thanks for ipxwrapper, which is awesome for LAN!
A point-to-point VPN shouldn't add any perceptible overhead, some people have reported poor performance with IPXWrapper in general, but I've not been able to reproduce it.
Are you having performance issues, or was this more of a would-be-nice thing?
I did have, but it is more because I was using SSL as my VPN transport. It was much better indeed when using IPSec, but it was cumbersome to setup.
So, I guess it is more leaning to the "would-be-nice" thing, to have just 1 protocol and 1 way to set it up.
Drat! I was hoping you were in the group of people with inexplicable performance issues so I could get some profiling data :p
Also when you say "DOSBox-comptible mode", do you literally mean compatible with DOSBox's IPX transport, or any IP transport that doesn't rely on being in the same broadcast domain?
literally mean compatible with DOSBox's IPX transport
That, as I'm a huge fan of reuse. As it leads to a growing ecosystem.
I just discovered that the Dosbox implementation is not totally new, they are simply implementing RFC1234.
Hello! Just want to chime in and add a +1 to this idea. I'm part of a Discord server called DOSbox Deathmatch Club where we play old games together every week. For DOS games it's relatively simple to set up such games because we run dedicated IPX servers that our users can connect to, but using IPXWrapper requires the addition of a VPN as well. It's another step that makes setup more complicated for people who want to take part in events.
To add to the point about growing ecosystems: I myself have been putting a bunch of work into ipxbox (standalone DOSbox server with a ton of features) and dali (DOS driver to connect to DOSbox). Considering there are games like Warcraft II which have both DOS and Windows versions, it would be really nice if people were able to play together regardless of which version they're using and regardless of whether they're using a real or an emulated PC.
So I'm planning on adding this soon, both the standard RFC1234 where you need to configure peer IPs and the DosBox variant with a server and control messages.
@fragglet are there many games that have a Windows and DOS build and can play with each other? I was curious about that.
Looking at the list, Warcraft II, Carmageddon and Theme Hospital are a few.
Doom is another (there's Doom 95) but I don't know if it's supported by IPXWrapper since it's not in the list.
By the way, I'm not sure anything really uses RFC 1234 besides DOSbox's variant so you might want to skip the peer-to-peer version.
However DOSbox uses SDL_net which supports multicast via address 224.0.0.1 so that's something you might want to support. Not sure many people use it though.
https://github.com/libsdl-org/SDL_net/blob/main/SDLnetUDP.c#L192
I fully agree.
I never used the peer to peer configuration option, as it is way easier to just use a central ipxserver.
Instead, eventually using that dev time to leverage multicast would solve autoconfig nicely for LAN.
I've got a rickety prototype ready to go, not tested in the slightest yet though. It might just crash as soon as you try using it for all I know.
If anyone wants to give the attached build a try, choose "DOSBox encapsulation" in ipxconfig and enter the IP (not hostname, yet) and port of the server.
Awesome! Would it be possible for you to push it on a PR ?
Awesome! Would it be possible for you to push it on a PR ?
Its already on the dosbox branch.
🤦 ... I'm too used to rely on PR that I totally forgot to check there.
Will have a look later this week.
Thanks!
I completely forgot about this... @steveschnepp @fragglet did you ever get a chance to try out the DOSBox integration? xD
I completely forgot about this
Same here 🤦
Meanwhile, I don't have any win10 laptop anymore as I'm fully using wine for my gaming now 😞
Does ipxwrapper work with WINE ?
Last time I tried it, it worked fine under Wine aside from the winpcap stuff obvs.
I completely forgot about this... @steveschnepp @fragglet did you ever get a chance to try out the DOSBox integration? xD
No luck when I gave it a whirl.
[152532.98, thread 5924] wsock32.dll:WSAStartup -> wsock32.dll [152532.98, thread 5924] wsock32.dll:gethostname -> wsock32.dll [152533.00, thread 5924] wsock32.dll:socket -> ipxwrapper.dll [152533.00, thread 5924] IPXWrapper git [152533.00, thread 5924] Compiled at Sat 21 Aug 15:02:21 BST 2021 [152533.00, thread 5924] -- [152533.00, thread 5924] Listing IPX interfaces: [152533.00, thread 5924] -- [152533.00, thread 5924] No IPX interfaces detected! [152533.00, thread 5924] -- [152533.01, thread 5924] connect(-1, 650E6490, 16) [152533.01, thread 5924] Error connecting private socket: An operation was attempted on something that is not a socket.
Still a work in progress, but I've fixed some issues in the DOSBox transport and it seems to actually kinda work now! New build attached.
Nice job!
@solemnwarning Observing the dosbox console, it does connect successfuly! I'll do more thorough testing, and if all goes right, I'll work on integration in NukemNet (IPXWrapper+IPXBox) https://gitlab.com/aabluedragon/NukemNet/-/issues/6 Thanks!
Hmm, no signs of a connection here.
[229676.54, thread 2592] wsock32.dll:WSAStartup -> wsock32.dll [229676.54, thread 2592] wsock32.dll:gethostname -> wsock32.dll [229676.54, thread 2592] wsock32.dll:socket -> ipxwrapper.dll [229676.54, thread 2592] IPXWrapper git [229676.54, thread 2592] Compiled at Sat 9 Sep 10:49:10 BST 2023 [229676.54, thread 2592] -- [229676.56, thread 2592] Listing IPX interfaces: [229676.56, thread 2592] -- [229676.56, thread 2592] No IPX interfaces detected! [229676.56, thread 2592] -- [229676.56, thread 2592] socket(2, 2, 0) [229676.56, thread 2592] setsockopt(932, 65535, 32, {00 00 00 00}, 4) [229676.56, thread 2592] r_setsockopt = 0, WSAGetLastError = 0 [229676.56, thread 2592] setsockopt(932, 65535, 4, {00 00 00 00}, 4) [229676.56, thread 2592] r_setsockopt = 0, WSAGetLastError = 0 [229676.56, thread 2592] setsockopt(932, 65535, 4098, {00 00 08 00}, 4) [229676.56, thread 2592] r_setsockopt = 0, WSAGetLastError = 0 [229676.56, thread 2592] setsockopt(932, 65535, 4097, {00 00 08 00}, 4) [229676.56, thread 2592] r_setsockopt = 0, WSAGetLastError = 0 [229676.56, thread 2592] socket(6, 2, 1000) [229676.56, thread 12760] Error sending DOSBox IPX registration request: An attempt was made to access a socket in a way forbidden by its access permissions. [229676.56, thread 2592] IPX socket created (fd = 956) [229676.56, thread 2592] wsock32.dll:ioctlsocket -> ipxwrapper.dll [229676.56, thread 2592] ioctlsocket(956, -2147195266) [229676.56, thread 2592] wsock32.dll:setsockopt -> ipxwrapper.dll [229676.56, thread 2592] setsockopt(956, 65535, 32, {01 00 00 00}, 4) [229676.56, thread 2592] wsock32.dll:htons -> wsock32.dll [229676.56, thread 2592] wsock32.dll:bind -> ipxwrapper.dll [229679.56, thread 2592] bind(956, 00:00:00:00/00:00:00:00:00:00/0) [229679.56, thread 2592] bind failed: no such address [229679.56, thread 12760] Error sending DOSBox IPX registration request: An attempt was made to access a socket in a way forbidden by its access permissions.
@andkrau @solemnwarning I get the following:
[113747.37, thread 8080] SPInit: 00756bd8 (lpAddress = 00be39c0, dwAddressSize = 80)
[113747.37, thread 8080] dpwsockx.dll:WSACreateEvent -> ws2_32.dll
[113747.39, thread 8080] directplay.c: SP_GetCaps
[113747.39, thread 8080] directplay.c: SP_GetCaps
[113747.40, thread 8080] directplay.c: SP_GetCaps
[113747.40, thread 8080] directplay.c: SP_EnumSessions
[113747.40, thread 8080] wsock32.dll:socket -> ipxwrapper.dll
[113747.42, thread 8080] IPXWrapper git
[113747.43, thread 8080] Compiled at Sat 9 Sep 10:49:10 BST 2023
[113747.43, thread 8080] --
[113747.43, thread 8080] Listing IPX interfaces:
[113747.45, thread 8080] --
[113747.45, thread 8080] No IPX interfaces detected!
[113747.45, thread 8080] --
[113747.45, thread 8080] socket(2, 2, 0)
[113747.45, thread 8080] setsockopt(984, 65535, 32, {00 00 00 00}, 4)
[113747.45, thread 8080] r_setsockopt = 0, WSAGetLastError = 0
[113747.45, thread 8080] setsockopt(984, 65535, 4, {00 00 00 00}, 4)
[113747.45, thread 8080] r_setsockopt = 0, WSAGetLastError = 0
[113747.45, thread 8080] setsockopt(984, 65535, 4098, {00 00 08 00}, 4)
[113747.45, thread 8080] r_setsockopt = 0, WSAGetLastError = 0
[113747.45, thread 8080] setsockopt(984, 65535, 4097, {00 00 08 00}, 4)
[113747.45, thread 8080] r_setsockopt = 0, WSAGetLastError = 0
[113747.45, thread 8080] socket(6, 2, 1000)
[113747.45, thread 8080] IPX socket created (fd = 1016)
[113747.45, thread 8080] wsock32.dll:bind -> ipxwrapper.dll
[113750.45, thread 8080] bind(1016, 00:00:00:00/00:00:00:00:00:00/0)
[113750.45, thread 8080] bind failed: no such address
[113750.45, thread 8080] wsock32.dll:WSAGetLastError -> wsock32.dll
[113750.45, thread 6384] Connected to DOSBox server, local address: 00:00:00:00/7F:00:00:01:D1:3B
[113750.45, thread 8080] Error binding IPX socket: The requested address is not valid in its context.
[113750.45, thread 8080] wsock32.dll:closesocket -> ipxwrapper.dll
[113750.45, thread 8080] Socket 1016 (IPX) closed
Upon connection, I do see the following log in dosbox console:
IPXSERVER: Connect from 127.0.0.1
@andkrau huh, never seen that error before. A bit of searching suggests it could be a Windows policy blocking certain ports. Are you running the DOSBox server locally? Try another port perhaps?
@aabluedragon whoops, race condition. This build should fix that:
@solemnwarning Now I get this log, I think it looks ok (hopefully I'll have time to test actual gameplay soon):
[7433.62, thread 11124] SPInit: 00bfdf48 (lpAddress = 02bb39c0, dwAddressSize = 80)
[7433.64, thread 11124] dpwsockx.dll:WSACreateEvent -> ws2_32.dll
[7433.65, thread 11124] directplay.c: SP_GetCaps
[7433.65, thread 11124] directplay.c: SP_GetCaps
[7433.67, thread 11124] directplay.c: SP_GetCaps
[7433.67, thread 11124] directplay.c: SP_EnumSessions
[7433.68, thread 11124] wsock32.dll:socket -> ipxwrapper.dll
[7433.70, thread 11124] IPXWrapper git
[7433.70, thread 11124] Compiled at Sun 10 Sep 08:53:08 BST 2023
[7433.71, thread 11124] --
[7433.73, thread 11124] Listing IPX interfaces:
[7433.73, thread 11124] --
[7433.73, thread 11124] No IPX interfaces detected!
[7433.73, thread 11124] --
[7433.73, thread 11124] socket(2, 2, 0)
[7433.73, thread 11124] setsockopt(1012, 65535, 32, {00 00 00 00}, 4)
[7433.73, thread 11124] r_setsockopt = 0, WSAGetLastError = 0
[7433.73, thread 11124] setsockopt(1012, 65535, 4, {00 00 00 00}, 4)
[7433.73, thread 11124] r_setsockopt = 0, WSAGetLastError = 0
[7433.73, thread 11124] setsockopt(1012, 65535, 4098, {00 00 08 00}, 4)
[7433.73, thread 11124] r_setsockopt = 0, WSAGetLastError = 0
[7433.73, thread 11124] setsockopt(1012, 65535, 4097, {00 00 08 00}, 4)
[7433.73, thread 11124] r_setsockopt = 0, WSAGetLastError = 0
[7433.73, thread 11124] socket(6, 2, 1000)
[7433.73, thread 11124] IPX socket created (fd = 1000)
[7433.73, thread 11124] wsock32.dll:bind -> ipxwrapper.dll
[7433.75, thread 15820] Connected to DOSBox server, local address: 00:00:00:00/7F:00:00:01:FE:1A
[7433.75, thread 11124] bind(1000, 00:00:00:00/00:00:00:00:00:00/0)
[7433.75, thread 11124] bind address: 00:00:00:00/7F:00:00:01:FE:1A/1024
[7433.75, thread 11124] Bound to local port 65051
[7433.75, thread 11124] wsock32.dll:setsockopt -> ipxwrapper.dll
[7433.75, thread 11124] setsockopt(1000, 65535, 32, {01 00 00 00}, 4)
[7433.75, thread 11124] dpwsockx.dll:WSAEventSelect -> ws2_32.dll
[7433.75, thread 11124] wsock32.dll:getsockname -> ipxwrapper.dll
[7433.75, thread 11124] wsock32.dll:htons -> wsock32.dll
[7433.75, thread 11124] wsock32.dll:sendto -> ipxwrapper.dll
[7433.75, thread 11124] Sending 32 byte payload from 00:00:00:00/7F:00:00:01:FE:1A/1024 to 00:00:00:00/FF:FF:FF:FF:FF:FF/42367
[7433.75, thread 25624] directplay.c: SP_GetCaps
[7434.25, thread 25624] directplay.c: SP_EnumSessions
[7434.25, thread 25624] wsock32.dll:getsockname -> ipxwrapper.dll
[7434.25, thread 25624] wsock32.dll:htons -> wsock32.dll
[7434.25, thread 25624] wsock32.dll:sendto -> ipxwrapper.dll
[7434.25, thread 25624] Sending 32 byte payload from 00:00:00:00/7F:00:00:01:FE:1A/1024 to 00:00:00:00/FF:FF:FF:FF:FF:FF/42367
[7434.25, thread 25624] directplay.c: SP_GetCaps
[7434.76, thread 25624] directplay.c: SP_EnumSessions
[7434.78, thread 25624] wsock32.dll:getsockname -> ipxwrapper.dll
[7434.78, thread 25624] wsock32.dll:htons -> wsock32.dll
[7434.78, thread 25624] wsock32.dll:sendto -> ipxwrapper.dll
[7434.78, thread 25624] Sending 32 byte payload from 00:00:00:00/7F:00:00:01:FE:1A/1024 to 00:00:00:00/FF:FF:FF:FF:FF:FF/42367
[7434.78, thread 25624] directplay.c: SP_GetCaps
[7435.28, thread 25624] directplay.c: SP_EnumSessions
[7435.29, thread 25624] wsock32.dll:getsockname -> ipxwrapper.dll
[7435.29, thread 25624] wsock32.dll:htons -> wsock32.dll
[7435.29, thread 25624] wsock32.dll:sendto -> ipxwrapper.dll
[7435.29, thread 25624] Sending 32 byte payload from 00:00:00:00/7F:00:00:01:FE:1A/1024 to 00:00:00:00/FF:FF:FF:FF:FF:FF/42367
[7435.29, thread 25624] directplay.c: SP_GetCaps
[7435.79, thread 25624] directplay.c: SP_EnumSessions
[7435.81, thread 25624] wsock32.dll:getsockname -> ipxwrapper.dll
[7435.81, thread 25624] wsock32.dll:htons -> wsock32.dll
[7435.81, thread 25624] wsock32.dll:sendto -> ipxwrapper.dll
[7435.81, thread 25624] Sending 32 byte payload from 00:00:00:00/7F:00:00:01:FE:1A/1024 to 00:00:00:00/FF:FF:FF:FF:FF:FF/42367
[7435.81, thread 25624] directplay.c: SP_GetCaps
[7436.09, thread 11124] directplay.c: SP_Open
[7436.10, thread 11124] directplay.c: SP_GetCaps
[7436.10, thread 11124] directplay.c: SP_CreatePlayer
[7436.10, thread 11124] IPX_CreatePlayer: idPlayer = 7370557, dwFlags = 11
[7436.10, thread 11124] wsock32.dll:socket -> ipxwrapper.dll
[7436.10, thread 11124] socket(6, 2, 1000)
[7436.10, thread 11124] IPX socket created (fd = 1260)
[7436.10, thread 11124] wsock32.dll:setsockopt -> ipxwrapper.dll
[7436.10, thread 11124] setsockopt(1260, 65535, 4, {01 00 00 00}, 4)
[7436.10, thread 11124] wsock32.dll:setsockopt -> ipxwrapper.dll
[7436.10, thread 11124] setsockopt(1260, 65535, 32, {01 00 00 00}, 4)
[7436.10, thread 11124] wsock32.dll:getsockname -> ipxwrapper.dll
[7436.10, thread 11124] wsock32.dll:htons -> wsock32.dll
[7436.10, thread 11124] wsock32.dll:bind -> ipxwrapper.dll
[7436.10, thread 11124] bind(1260, 00:00:00:00/7F:00:00:01:FE:1A/42367)
[7436.10, thread 11124] bind address: 00:00:00:00/7F:00:00:01:FE:1A/42367
[7436.10, thread 11124] Bound to local port 65052
[7436.10, thread 11124] dpwsockx.dll:WSAEventSelect -> ws2_32.dll
[7436.10, thread 11124] wsock32.dll:getsockname -> ipxwrapper.dll
[7436.21, thread 25624] directplay.c: SP_GetCaps
[7436.21, thread 25624] directplay.c: SP_GetCaps
[7436.21, thread 11124] directplay.c: SP_CreatePlayer
[7436.21, thread 11124] IPX_CreatePlayer: idPlayer = 7370556, dwFlags = 8
[7436.21, thread 11124] wsock32.dll:getsockname -> ipxwrapper.dll
[7436.43, thread 25624] directplay.c: SP_GetCaps
[7436.45, thread 25624] directplay.c: SP_GetCaps
@solemnwarning Okay, so I was eager to try it, I ended up testing it now, and I got it working with GTA2! Just ran a 2 player game, and it worked great.
I made some more improvements to the connection process, it supports DNS names and will retry when the connection fails now.
huh, never seen that error before. A bit of searching suggests it could be a Windows policy blocking certain ports. Are you running the DOSBox server locally? Try another port perhaps?
@solemnwarning Was definitely an issue on my end; running the server locally fixed that error.
Now, I am seeing a different error though. I get the same error whether I run the DOSBox server on the same system or on a different one on the LAN. This is with a game based upon GLQuake:
[621648.92, thread 17568] wsock32.dll:WSAStartup -> wsock32.dll
[621648.92, thread 17568] wsock32.dll:gethostname -> wsock32.dll
[621648.92, thread 17568] wsock32.dll:socket -> ipxwrapper.dll
[621648.92, thread 17568] IPXWrapper git
[621648.93, thread 17568] Compiled at Thu 14 Sep 00:56:55 BST 2023
[621648.93, thread 17568] --
[621648.93, thread 17568] Using DOSBox server: 127.0.0.1 port 2600
[621648.93, thread 17568] socket(2, 2, 0)
[621648.93, thread 17568] setsockopt(928, 65535, 32, {00 00 00 00}, 4)
[621648.93, thread 17568] r_setsockopt = 0, WSAGetLastError = 0
[621648.93, thread 17568] setsockopt(928, 65535, 4, {00 00 00 00}, 4)
[621648.93, thread 17568] r_setsockopt = 0, WSAGetLastError = 0
[621648.93, thread 17568] setsockopt(928, 65535, 4098, {00 00 08 00}, 4)
[621648.93, thread 17568] r_setsockopt = 0, WSAGetLastError = 0
[621648.93, thread 17568] setsockopt(928, 65535, 4097, {00 00 08 00}, 4)
[621648.93, thread 17568] r_setsockopt = 0, WSAGetLastError = 0
[621648.93, thread 17568] socket(6, 2, 1000)
[621648.93, thread 17568] IPX socket created (fd = 948)
[621648.93, thread 17568] wsock32.dll:ioctlsocket -> ipxwrapper.dll
[621648.93, thread 17568] ioctlsocket(948, -2147195266)
[621648.93, thread 17568] wsock32.dll:setsockopt -> ipxwrapper.dll
[621648.93, thread 17568] setsockopt(948, 65535, 32, {01 00 00 00}, 4)
[621648.93, thread 17568] wsock32.dll:htons -> wsock32.dll
[621648.93, thread 7824] Resolved DOSBox server address 127.0.0.1, connecting...
[621648.93, thread 17568] wsock32.dll:bind -> ipxwrapper.dll
[621648.93, thread 7824] Connected to DOSBox server, local address: 00:00:00:00/7F:00:00:01:E1:14
[621648.93, thread 17568] bind(948, 00:00:00:00/00:00:00:00:00:00/0)
[621648.93, thread 17568] bind address: 00:00:00:00/7F:00:00:01:E1:14/1024
[621648.95, thread 17568] Bound to local port 57621
[621648.95, thread 17568] wsock32.dll:htons -> wsock32.dll
[621648.95, thread 17568] wsock32.dll:getsockname -> ipxwrapper.dll
[621648.95, thread 17568] wsock32.dll:ntohs -> wsock32.dll
[621656.50, thread 17568] wsock32.dll:WSAStartup -> wsock32.dll
[621656.50, thread 17568] wsock32.dll:socket -> ipxwrapper.dll
[621656.50, thread 17568] socket(2, 2, 17)
[621656.50, thread 17568] wsock32.dll:htons -> wsock32.dll
[621656.50, thread 17568] wsock32.dll:htonl -> wsock32.dll
[621656.50, thread 17568] wsock32.dll:bind -> ipxwrapper.dll
[621656.51, thread 17568] wsock32.dll:htons -> wsock32.dll
[621656.51, thread 17568] wsock32.dll:inet_addr -> wsock32.dll
[621656.51, thread 17568] wsock32.dll:gethostbyname -> wsock32.dll
[621656.53, thread 17568] wsock32.dll:socket -> ipxwrapper.dll
[621656.53, thread 17568] socket(6, 2, 1000)
[621656.53, thread 17568] IPX socket created (fd = 2556)
[621656.53, thread 17568] wsock32.dll:ioctlsocket -> ipxwrapper.dll
[621656.53, thread 17568] ioctlsocket(2556, -2147195266)
[621656.53, thread 17568] wsock32.dll:setsockopt -> ipxwrapper.dll
[621656.53, thread 17568] setsockopt(2556, 65535, 32, {01 00 00 00}, 4)
[621656.53, thread 17568] wsock32.dll:htons -> wsock32.dll
[621656.53, thread 17568] wsock32.dll:bind -> ipxwrapper.dll
[621656.53, thread 17568] bind(2556, 00:00:00:00/00:00:00:00:00:00/26000)
[621656.53, thread 17568] bind address: 00:00:00:00/7F:00:00:01:E1:14/26000
[621656.53, thread 17568] Bound to local port 52047
[621656.53, thread 17568] wsock32.dll:ioctlsocket -> ipxwrapper.dll
[621656.53, thread 17568] ioctlsocket(2556, 1074030207)
[621657.93, thread 17568] wsock32.dll:closesocket -> ipxwrapper.dll
[621657.93, thread 17568] Socket 2556 (IPX) closed
[621657.93, thread 17568] wsock32.dll:closesocket -> ipxwrapper.dll
[621657.93, thread 17568] Socket 948 (IPX) closed
[621657.93, thread 17568] wsock32.dll:WSACleanup -> wsock32.dll
@andkrau that might be an easy fix, I'll take a look tomorrow
@andkrau this build (hopefully) implements the FIONREAD ioctl in the way as expected by Laser Arena, let me know if it works!