From deb6590c1e07f6ac0b2695abf0dcea834285d42d Mon Sep 17 00:00:00 2001 From: Bradley Bell Date: Sat, 31 Aug 2002 03:16:35 +0000 Subject: [PATCH] win32 networking backtrack --- arch/win32/ipx_drv.h | 1 + arch/win32/ipx_win.c | 84 +++------- arch/win32/winnet.c | 357 +++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 368 insertions(+), 74 deletions(-) diff --git a/arch/win32/ipx_drv.h b/arch/win32/ipx_drv.h index d5fe990f..e29b95c2 100644 --- a/arch/win32/ipx_drv.h +++ b/arch/win32/ipx_drv.h @@ -15,6 +15,7 @@ #define IPX_MANUAL_ADDRESS +#include #include "pstypes.h" #define MAX_PACKET_DATA 1500 diff --git a/arch/win32/ipx_win.c b/arch/win32/ipx_win.c index 8deb746c..14515228 100644 --- a/arch/win32/ipx_win.c +++ b/arch/win32/ipx_win.c @@ -1,19 +1,10 @@ +/* $Id: ipx_win.c,v 1.4 2002-08-31 03:16:35 btb Exp $ */ + /* - * $Source: /cvs/cvsroot/d2x/arch/win32/ipx_win.c,v $ - * $Revision: 1.3 $ - * $Author: bradleyb $ - * $Date: 2001-10-19 10:52:38 $ * * IPX driver using BSD style sockets * Mostly taken from dosemu * - * $Log: not supported by cvs2svn $ - * Revision 1.2 2001/10/19 00:23:56 bradleyb - * Moved win32_* to win32/ (a la d1x), starting to get net working. - * - * Revision 1.3 2001/01/29 13:35:09 bradleyb - * Fixed build system, minor fixes - * */ #ifdef HAVE_CONFIG_H @@ -23,15 +14,13 @@ #include #include #include -//#include +#include +#include #include "ipx_drv.h" -#include "wsipx.h" #include "mono.h" -static ipx_socket_t mysock; - //#define n_printf(format, args...) mprintf((1, format, ## args)) static int ipx_win_GetMyAddress( void ) @@ -88,7 +77,7 @@ static int ipx_win_GetMyAddress( void ) return(0); } -static int ipx_win_OpenSocket(int port) +static int ipx_win_OpenSocket(ipx_socket_t *sk, int port) { int sock; /* sock here means Linux socket handle */ int opt; @@ -96,24 +85,6 @@ static int ipx_win_OpenSocket(int port) int len; struct sockaddr_ipx ipxs2; - WORD wVersionRequested; - WSADATA wsaData; - - wVersionRequested = MAKEWORD(2, 0); - if (WSAStartup( wVersionRequested, &wsaData)) - { - return -1; - } -#if 0 - if ( LOBYTE( wsaData.wVersion ) != 2 || - HIBYTE( wsaData.wVersion ) != 0 ) { - /* We couldn't find a usable WinSock DLL. */ - WSACleanup( ); - return -2; - } -#endif - - /* DANG_FIXTHIS - kludge to support broken linux IPX stack */ /* need to convert dynamic socket open into a real socket number */ /* if (port == 0) { @@ -123,8 +94,7 @@ static int ipx_win_OpenSocket(int port) */ /* do a socket call, then bind to this port */ // sock = socket(AF_IPX, SOCK_DGRAM, PF_IPX); -// sock = socket(AF_IPX, SOCK_DGRAM, 0); - sock = socket(AF_IPX, SOCK_DGRAM, NSPROTO_IPX);//why NSPROTO_IPX? I looked in the quake source and thats what they used. :) -MPM (on w2k 0 and PF_IPX don't work) + sock = socket(AF_IPX, SOCK_DGRAM, 0); if (sock == -1) { mprintf((1,"IPX: could not open IPX socket.\n")); return -1; @@ -177,23 +147,19 @@ static int ipx_win_OpenSocket(int port) memcpy(ipx_MyAddress, ipxs2.sa_netnum, 4); memcpy(ipx_MyAddress + 4, ipxs2.sa_nodenum, 6); - mysock.fd = sock; - mysock.socket = port; - - ipx_win_GetMyAddress(); - + sk->fd = sock; + sk->socket = port; return 0; } -static void ipx_win_CloseSocket(void) { +static void ipx_win_CloseSocket(ipx_socket_t *mysock) { /* now close the file descriptor for the socket, and free it */ - mprintf((1,"IPX: closing file descriptor on socket %x\n", mysock.socket)); - closesocket(mysock.fd); - WSACleanup(); + mprintf((1,"IPX: closing file descriptor on socket %x\n", mysock->socket)); + closesocket(mysock->fd); } -static int ipx_win_SendPacket(IPXPacket_t *IPXHeader, - ubyte *data, int dataLen) { +static int ipx_win_SendPacket(ipx_socket_t *mysock, IPXPacket_t *IPXHeader, + u_char *data, int dataLen) { struct sockaddr_ipx ipxs; ipxs.sa_family = AF_IPX; @@ -205,46 +171,36 @@ static int ipx_win_SendPacket(IPXPacket_t *IPXHeader, /* ipxs.sa_netnum = htonl(MyNetwork); */ } memcpy(&ipxs.sa_nodenum, IPXHeader->Destination.Node, 6); -// memcpy(&ipxs.sa_socket, IPXHeader->Destination.Socket, 2); - ipxs.sa_socket=htons(mysock.socket); + memcpy(&ipxs.sa_socket, IPXHeader->Destination.Socket, 2); // ipxs.sa_type = IPXHeader->PacketType; /* ipxs.sipx_port=htons(0x452); */ - return sendto(mysock.fd, data, dataLen, 0, + return sendto(mysock->fd, data, dataLen, 0, (struct sockaddr *) &ipxs, sizeof(ipxs)); } -static int ipx_win_ReceivePacket(char *buffer, int bufsize, +static int ipx_win_ReceivePacket(ipx_socket_t *s, char *buffer, int bufsize, struct ipx_recv_data *rd) { int sz, size; struct sockaddr_ipx ipxs; sz = sizeof(ipxs); - if ((size = recvfrom(mysock.fd, buffer, bufsize, 0, + if ((size = recvfrom(s->fd, buffer, bufsize, 0, (struct sockaddr *) &ipxs, &sz)) <= 0) return size; memcpy(rd->src_network, ipxs.sa_netnum, 4); memcpy(rd->src_node, ipxs.sa_nodenum, 6); rd->src_socket = ipxs.sa_socket; - rd->dst_socket = mysock.socket; + rd->dst_socket = s->socket; // rd->pkt_type = ipxs.sipx_type; return size; } -static int ipx_win_general_PacketReady(void) { - return ipx_general_PacketReady(mysock.fd); -} - struct ipx_driver ipx_win = { -// ipx_win_GetMyAddress, + ipx_win_GetMyAddress, ipx_win_OpenSocket, ipx_win_CloseSocket, ipx_win_SendPacket, ipx_win_ReceivePacket, - ipx_win_general_PacketReady, - NULL, - 1, - NULL, - NULL, - NULL + ipx_general_PacketReady }; diff --git a/arch/win32/winnet.c b/arch/win32/winnet.c index c12ac2e5..0bab5883 100644 --- a/arch/win32/winnet.c +++ b/arch/win32/winnet.c @@ -1,28 +1,365 @@ +/* $Id: winnet.c,v 1.4 2002-08-31 03:16:35 btb Exp $ */ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ + /* - * $Source: /cvs/cvsroot/d2x/arch/win32/winnet.c,v $ - * $Revision: 1.3 $ - * $Author: bradleyb $ - * $Date: 2001-10-19 10:52:38 $ * * Win32 net * - * $Log: not supported by cvs2svn $ - * Revision 1.2 2001/10/19 00:23:56 bradleyb - * Moved win32_* to win32/ (a la d1x), starting to get net working. - * */ #ifdef HAVE_CONFIG_H #include #endif +#include +#include +#include +#include + #include "pstypes.h" +#include "config.h" +#include "args.h" #include "ipx_drv.h" extern struct ipx_driver ipx_win; -struct ipx_driver * arch_ipx_set_driver(char *arg) +#define MAX_IPX_DATA 576 + +int ipx_fd; +ipx_socket_t ipx_socket_data; +ubyte ipx_installed=0; +ushort ipx_socket = 0; +uint ipx_network = 0; +ubyte ipx_MyAddress[10]; +int ipx_packetnum = 0; /* Sequence number */ + +/* User defined routing stuff */ +typedef struct user_address { + ubyte network[4]; + ubyte node[6]; + ubyte address[6]; +} user_address; +#define MAX_USERS 64 +int Ipx_num_users = 0; +user_address Ipx_users[MAX_USERS]; + +#define MAX_NETWORKS 64 +int Ipx_num_networks = 0; +uint Ipx_networks[MAX_NETWORKS]; + +void ipx_close(void); + +int ipx_general_PacketReady(ipx_socket_t *s) { + fd_set set; + struct timeval tv; + + FD_ZERO(&set); + FD_SET(s->fd, &set); + tv.tv_sec = tv.tv_usec = 0; + if (select(FD_SETSIZE, &set, NULL, NULL, &tv) > 0) + return 1; + else + return 0; +} + +struct ipx_driver *driver = &ipx_win; + +ubyte * ipx_get_my_server_address() +{ + return (ubyte *)&ipx_network; +} + +ubyte * ipx_get_my_local_address() +{ + return (ubyte *)(ipx_MyAddress + 4); +} + +//--------------------------------------------------------------- +// Initializes all IPX internals. +// If socket_number==0, then opens next available socket. +// Returns: 0 if successful. +// -1 if socket already open. +// -2 if socket table full. +// -3 if IPX not installed. +// -4 if couldn't allocate low dos memory +// -5 if error with getting internetwork address +int ipx_init( int socket_number, int show_address ) +{ + int i; + + WORD wVersionRequested; + WSADATA wsaData; + + wVersionRequested = MAKEWORD(2, 0); + if (WSAStartup( wVersionRequested, &wsaData)) + { + return -1; + } + +#if 0 + if ( LOBYTE( wsaData.wVersion ) != 2 || + HIBYTE( wsaData.wVersion ) != 0 ) { + /* We couldn't find a usable WinSock DLL. */ + WSACleanup( ); + return -2; + } +#endif + + printf("Using real IPX for network games\n"); + driver = &ipx_win; + if ((i = FindArg("-ipxnetwork")) && Args[i + 1]) { + unsigned long n = strtol(Args[i + 1], NULL, 16); + ipx_MyAddress[0] = (unsigned char)n >> 24; ipx_MyAddress[1] = (unsigned char)(n >> 16) & 255; + ipx_MyAddress[2] = (unsigned char)(n >> 8) & 255; ipx_MyAddress[3] = (unsigned char)n & 255; + printf("IPX: Using network %08x\n", (int) n); + } + if (driver->OpenSocket(&ipx_socket_data, socket_number)) { + return -3; + } + driver->GetMyAddress(); + memcpy(&ipx_network, ipx_MyAddress, 4); + Ipx_num_networks = 0; + memcpy( &Ipx_networks[Ipx_num_networks++], &ipx_network, 4 ); + ipx_installed = 1; + atexit(ipx_close); + printf("ipx succesfully installed\n"); + return 0; +} + +void ipx_close() { - return &ipx_win; + if (ipx_installed) { + WSACleanup(); + driver->CloseSocket(&ipx_socket_data); + } + ipx_installed = 0; +} + +int ipx_get_packet_data( ubyte * data ) +{ + struct ipx_recv_data rd; + char buf[MAX_IPX_DATA]; + uint best_id = 0; + uint pkt_num; + int size; + int best_size = 0; + + // Like the original, only take latest packet, throw away rest + while (driver->PacketReady(&ipx_socket_data)) { + if ((size = + driver->ReceivePacket(&ipx_socket_data, buf, + sizeof(buf), &rd)) > 4) { + if (!memcmp(rd.src_network, ipx_MyAddress, 10)) + continue; /* don't get own pkts */ + pkt_num = *(uint *)buf; + if (pkt_num >= best_id) { + memcpy(data, buf + 4, size - 4); + best_id = pkt_num; + best_size = size - 4; + } + } + } + return best_size; +} + +void ipx_send_packet_data( ubyte * data, int datasize, ubyte *network, ubyte *address, ubyte *immediate_address ) +{ + u_char buf[MAX_IPX_DATA]; + IPXPacket_t ipx_header; + + memcpy(ipx_header.Destination.Network, network, 4); + memcpy(ipx_header.Destination.Node, immediate_address, 6); + *(u_short *)ipx_header.Destination.Socket = htons(ipx_socket_data.socket); + ipx_header.PacketType = 4; /* Packet Exchange */ + *(uint *)buf = ipx_packetnum++; + memcpy(buf + 4, data, datasize); + driver->SendPacket(&ipx_socket_data, &ipx_header, buf, datasize + 4); +} + +void ipx_get_local_target( ubyte * server, ubyte * node, ubyte * local_target ) +{ + // let's hope Linux knows how to route it + memcpy( local_target, node, 6 ); +} + +void ipx_send_broadcast_packet_data( ubyte * data, int datasize ) +{ + int i, j; + ubyte broadcast[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + ubyte local_address[6]; + + // Set to all networks besides mine + for (i=0; iCloseSocket(&ipx_socket_data); + if (driver->OpenSocket(&ipx_socket_data, socket_number)) { + return -3; + } + return 0; +} + +void ipx_read_user_file(char * filename) +{ + FILE * fp; + user_address tmp; + char temp_line[132], *p1; + int n, ln=0, x; + + if (!filename) return; + + Ipx_num_users = 0; + + fp = fopen( filename, "rt" ); + if ( !fp ) return; + + printf( "Broadcast Users:\n" ); + + while (fgets(temp_line, 132, fp)) { + ln++; + p1 = strchr(temp_line,'\n'); if (p1) *p1 = '\0'; + p1 = strchr(temp_line,';'); if (p1) *p1 = '\0'; +#if 1 // adb: replaced sscanf(..., "%2x...", (char *)...) with better, but longer code + if (strlen(temp_line) >= 21 && temp_line[8] == '/') { + for (n = 0; n < 4; n++) { + if (sscanf(temp_line + n * 2, "%2x", &x) != 1) + break; + tmp.network[n] = x; + } + if (n != 4) + continue; + for (n = 0; n < 6; n++) { + if (sscanf(temp_line + 9 + n * 2, "%2x", &x) != 1) + break; + tmp.node[n] = x; + } + if (n != 6) + continue; + } else + continue; +#else + n = sscanf( temp_line, "%2x%2x%2x%2x/%2x%2x%2x%2x%2x%2x", &tmp.network[0], &tmp.network[1], &tmp.network[2], &tmp.network[3], &tmp.node[0], &tmp.node[1], &tmp.node[2],&tmp.node[3], &tmp.node[4], &tmp.node[5] ); + if ( n != 10 ) continue; +#endif + if ( Ipx_num_users < MAX_USERS ) { + ubyte * ipx_real_buffer = (ubyte *)&tmp; + ipx_get_local_target( tmp.network, tmp.node, tmp.address ); + Ipx_users[Ipx_num_users++] = tmp; + printf( "%02X%02X%02X%02X/", ipx_real_buffer[0],ipx_real_buffer[1],ipx_real_buffer[2],ipx_real_buffer[3] ); + printf( "%02X%02X%02X%02X%02X%02X\n", ipx_real_buffer[4],ipx_real_buffer[5],ipx_real_buffer[6],ipx_real_buffer[7],ipx_real_buffer[8],ipx_real_buffer[9] ); + } else { + printf( "Too many addresses in %s! (Limit of %d)\n", filename, MAX_USERS ); + fclose(fp); + return; + } + } + fclose(fp); +} + + +void ipx_read_network_file(char * filename) +{ + FILE * fp; + user_address tmp; + char temp_line[132], *p1; + int i, n, ln=0, x; + + if (!filename) return; + + fp = fopen( filename, "rt" ); + if ( !fp ) return; + + printf( "Using Networks:\n" ); + for (i=0; i= 8) { + for (n = 0; n < 4; n++) { + if (sscanf(temp_line + n * 2, "%2x", &x) != 1) + break; + tmp.network[n] = x; + } + if (n != 4) + continue; + } else + continue; +#else + n = sscanf( temp_line, "%2x%2x%2x%2x", &tmp.network[0], &tmp.network[1], &tmp.network[2], &tmp.network[3] ); + if ( n != 4 ) continue; +#endif + if ( Ipx_num_networks < MAX_NETWORKS ) { + int j; + for (j=0; j= Ipx_num_networks ) { + memcpy( &Ipx_networks[Ipx_num_networks++], tmp.network, 4 ); + printf(" %02x%02x%02x%02x\n", tmp.network[0], tmp.network[1], tmp.network[2], tmp.network[3] ); + } + } else { + printf( "Too many networks in %s! (Limit of %d)\n", filename, MAX_NETWORKS ); + fclose(fp); + return; + } + } + fclose(fp); } -- 2.39.2