Removed old UDP/IP and MCAST4 code; Implemented online-capable UDP/IP interface

This commit is contained in:
zicodxx 2007-05-30 14:16:49 +00:00
parent ed025f3779
commit f1134f0bc3
24 changed files with 1955 additions and 159 deletions

View file

@ -1,5 +1,9 @@
D2X-Rebirth Changelog
20070530
--------
d2x.ini, SConstruct, arch/linux/arch_ip.cpp, arch/linux/linuxnet.c arch/linux/ukali.c, arch/linux/include/ipx_drv.h, arch/win32/arch_ip.cpp, arch/win32/winnet.c, arch/win32/ipx_drv.h, arch/win32/include/ipx_drv.h, main/ip_base.cpp, main/ip_basec.h, main/inferno.c, main/ipbase.h, main/ipclient.cpp, main/ipclienc.c, main/ipclient.h, main/menu.c, main/network.c, main/playsave.c, main/vers_id.h: Removed old UDP/IP and MCAST4 code; Implemented online-capable UDP/IP interface
20070527
--------
include/cfile.h, main/inferno.c, main/mission.c, main/movie.c: add add_to_end parameter to cfile_init, allowing custom MIDI music to be found in an add-on hog

View file

@ -17,12 +17,11 @@ D2XMINOR = 52
D2XMICRO = 0
#D2XMICRO = int(SVN_REVISION)
VERSION = str(D2XMAJOR) + '.' + str(D2XMINOR)
VERSION_STRING = ' v' + str(D2XMAJOR) + '.' + str(D2XMINOR)
if (D2XMICRO):
VERSION += '.' + str(D2XMICRO)
VERSION_STRING += '.' + str(D2XMICRO)
print '\n===== ' + PROGRAM_NAME + ' v' + VERSION + ' =====\n'
print '\n===== ' + PROGRAM_NAME + VERSION_STRING + ' =====\n'
# installation path
PREFIX = '/usr/local/'
@ -168,7 +167,10 @@ common_sources = [
'misc/strio.c',
'misc/strutil.c',
'texmap/ntmap.c',
'texmap/scanline.c'
'texmap/scanline.c',
'main/ip_base.cpp',
'main/ipclienc.c',
'main/ipclient.cpp',
]
# for editor
@ -235,9 +237,8 @@ editor_sources = [
# for *nix
arch_unix_sources = [
'arch/linux/init.c',
'arch/linux/ipx_mcast4.c',
'arch/linux/ipx_udp.c',
'arch/linux/linuxnet.c',
'arch/linux/arch_ip.cpp'
]
# for linux
@ -266,12 +267,11 @@ arch_win32_sources = [
'arch/win32/hmpfile.c',
'arch/win32/init.c',
'arch/win32/ipx_win.c',
'arch/win32/ipx_mcast4.c',
'arch/win32/ipx_udp.c',
'arch/win32/midi.c',
'arch/win32/mono.c',
'arch/win32/winnet.c',
'arch/sdl/digi.c',
'arch/win32/arch_ip.cpp'
]
# for Mac OS X
@ -319,7 +319,8 @@ env = Environment(ENV = os.environ)
env.ParseConfig('sdl-config --cflags')
env.ParseConfig('sdl-config --libs')
env.Append(CPPFLAGS = ['-Wall', '-funsigned-char'])
env.Append(CPPDEFINES = [('VERSION', '\\"' + str(VERSION) + '\\"')])
env.Append(CPPDEFINES = [('D2XMAJOR', '\\"' + str(D2XMAJOR) + '\\"'), ('D2XMINOR', '\\"' + str(D2XMINOR) + '\\"')])
#env.Append(CPPDEFINES = [('VERSION', '\\"' + str(VERSION) + '\\"')])
env.Append(CPPDEFINES = [('USE_SDLMIXER', sdlmixer)])
env.Append(CPPDEFINES = ['NMONO', 'PIGGY_USE_PAGING', 'NETWORK', 'HAVE_NETIPX_IPX_H', 'NEWDEMO', '_REENTRANT'])
env.Append(CPPPATH = ['include', 'main', 'arch/include'])
@ -509,12 +510,12 @@ Help(PROGRAM_NAME + ', SConstruct file help:' +
""" + ' sharepath = ' + DATA_DIR + """
Some influential environment variables:
CC C compiler command
CFLAGS C compiler flags
LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
CC C compiler command
CFLAGS C compiler flags
LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
nonstandard directory <lib dir>
<include dir>
CXX C++ compiler command
CXXFLAGS C++ compiler flags
CXX C++ compiler command
CXXFLAGS C++ compiler flags
""")
#EOF

220
arch/linux/arch_ip.cpp Executable file
View file

@ -0,0 +1,220 @@
/*
* arch_ip.cpp - arch specific udp/ip code. (linux ver)
* added 2000/02/07 Matt Mueller (some code borrowed from ipx_udp.c)
*/
#include <string.h>
#include <netinet/in.h> /* for htons & co. */
#include <unistd.h>
#include <netdb.h>
#include <stdlib.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <ctype.h>
extern "C" {
#include "ipx_drv.h"
#include "pstypes.h"
#include "mono.h"
}
#include "ip_base.h"
#include "ipclient.h"
static int mysock=-1;
extern int nm_messagebox(char *title, int nchoices, ...);
/* Do hostname resolve on name "buf" and return the address in buffer "qhbuf".
*/
int arch_ip_queryhost(ip_addr *addr,char *buf,u_short baseport)
{
struct hostent *he;
char *s;
char c=0;
u_short p;
if ((s=strrchr(buf,':'))) {
c=*s;
*s='\0';
p=ip_portshift(baseport,s+1);
}
else p=ip_portshift(baseport,NULL);
he=gethostbyname((char *)buf);
if (s) *s=c;
if (!he) {
msg("Error resolving my hostname \"%s\"",buf);
return -1; //(NULL);
}
if (he->h_addrtype!=AF_INET || he->h_length!=4) {
msg("Error parsing resolved my hostname \"%s\"",buf);
return -1;//(NULL);
}
if (!*he->h_addr_list) {
msg("My resolved hostname \"%s\" address list empty",buf);
return -1;//(NULL);
}
addr->set(4,(u_char*)*he->h_addr_list,p);
return 0;
}
#ifdef UDPDEBUG
/* Like dumpraddr() but for structure "sockaddr_in"
*/
static void dumpaddr(struct sockaddr_in *sin)
{
unsigned short ports;
u_char qhbuf[6];
memcpy(qhbuf+0,&sin->sin_addr,4);
ports=sin->sin_port;
memcpy(qhbuf+4,&ports,2);
dumpraddr(qhbuf);
}
#endif
int ip_sendtoca(ip_addr addr,const void *buf,int len){
struct sockaddr_in toaddr;
if (addr.addrlen()!=4) return 0;//not handled yet
toaddr.sin_family=AF_INET;
memcpy(&toaddr.sin_addr,addr.addr,4);
toaddr.sin_port=*(unsigned short *)(addr.addr+4);
#ifdef UDPDEBUG
printf(MSGHDR "sendtoca((%d) ",len);
addr.dump();
puts(").");
#endif
return sendto(mysock,buf,len,0,(struct sockaddr *)&toaddr,sizeof(toaddr));
}
/* Find as much as MAX_BRDINTERFACES during local iface autoconfiguration.
* Note that more interfaces can be added during manual configuration
* or host-received-packet autoconfiguration
*/
#define MAX_BRDINTERFACES 16
/* We require the interface to be UP and RUNNING to accept it.
*/
#define IF_REQFLAGS (IFF_UP|IFF_RUNNING)
/* We reject any interfaces declared as LOOPBACK type.
*/
#define IF_NOTFLAGS (IFF_LOOPBACK)
int arch_ip_get_my_addr(u_short myport){
unsigned cnt=MAX_BRDINTERFACES,i,j;
struct ifconf ifconf;
int sock;
struct sockaddr_in *sinp;
ip_addr addr;
if ((sock=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP))<0)
FAIL("Creating socket() failure during broadcast detection:\n%m");
#ifdef SIOCGIFCOUNT
if (ioctl(sock,SIOCGIFCOUNT,&cnt))
{ /* msg("Getting iterface count error: %m"); */ }
else
cnt=cnt*2+2;
#endif
chk(ifconf.ifc_req=(struct ifreq *)alloca((ifconf.ifc_len=cnt*sizeof(struct ifreq))));
if (ioctl(sock,SIOCGIFCONF,&ifconf)||ifconf.ifc_len%sizeof(struct ifreq)) {
close(sock);
FAIL("ioctl(SIOCGIFCONF) failure during broadcast detection:\n%m");
}
cnt=ifconf.ifc_len/sizeof(struct ifreq);
for (i=j=0;i<cnt;i++) {
if (ioctl(sock,SIOCGIFFLAGS,ifconf.ifc_req+i)) {
close(sock);
FAIL("ioctl(udp,\"%s\",SIOCGIFFLAGS) error:\n%m",ifconf.ifc_req[i].ifr_name);
}
if (((ifconf.ifc_req[i].ifr_flags&IF_REQFLAGS)!=IF_REQFLAGS)||
(ifconf.ifc_req[i].ifr_flags&IF_NOTFLAGS))
continue;
if (ioctl(sock,SIOCGIFDSTADDR,ifconf.ifc_req+i)) {
close(sock);
FAIL("ioctl(udp,\"%s\",SIOCGIFDSTADDR) error:\n%m",ifconf.ifc_req[i].ifr_name);
}
sinp=(struct sockaddr_in *)&ifconf.ifc_req[i].ifr_netmask ;
if (sinp->sin_family!=AF_INET) continue;
addr.set(4,(ubyte*)&sinp->sin_addr,htons(myport));
#ifdef UDPDEBUG
printf(MSGHDR"added if ");
addr.dump();
printf("\n");
#endif
ip_my_addrs.add(addr);
}
return(0);
}
int arch_ip_open_socket(int port){
struct sockaddr_in sin;
int val_one=1;
if ((mysock = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP)) < 0) {
mysock = -1;
FAIL("socket() creation failed on port %d:\n%m",port);
}
if (setsockopt(mysock,SOL_SOCKET,SO_BROADCAST,&val_one,sizeof(val_one))) {
if (close(mysock)) msg("close() failed during error recovery: %m");
mysock=-1;
FAIL("setsockopt(SO_BROADCAST) failed:\n%m");
}
sin.sin_family=AF_INET;
sin.sin_addr.s_addr=htonl(INADDR_ANY);
sin.sin_port=htons(port);
if (bind(mysock,(struct sockaddr *)&sin,sizeof(sin))) {
if (close(mysock)) msg("close() failed during error recovery: %m");
mysock=-1;
FAIL("bind() to UDP port %d failed:\n%m",port);
}
return 0;
}
void arch_ip_close_socket(void) {
if (mysock<0) {
msg("close w/o open");
return;
}
if (close(mysock))
msg("close() failed on CloseSocket D1X ip socket %m");
mysock=-1;
}
int arch_ip_recvfrom(char*outbuf,int outbufsize,struct ipx_recv_data *rd){
struct sockaddr_in fromaddr;
socklen_t fromaddrsize=sizeof(fromaddr);
int size;
static ip_addr ip_fromaddr;
ip_addr *vptr=&ip_fromaddr;
if ((size=recvfrom(mysock,outbuf,outbufsize,0,(struct sockaddr *)&fromaddr,&fromaddrsize))<0)
return -1;
if (fromaddr.sin_family!=AF_INET) return -1;
#ifdef UDPDEBUG
printf(MSGHDR "recvfrom((%d-2=%d),",size,size-2);
dumpaddr(&fromaddr);
puts(").");
#endif
ip_fromaddr.set(4,(u_char*)&fromaddr.sin_addr,fromaddr.sin_port);
memcpy(rd->src_node,&vptr,sizeof(ip_addr*));
return size;
}
int arch_ip_PacketReady(void) {
static ipx_socket_t temp;
temp.fd=mysock;
return ipx_general_PacketReady(&temp);
}

View file

@ -12,24 +12,25 @@
#ifndef _IPX_DRV_H
#define _IPX_DRV_H
#include <sys/types.h>
#include "pstypes.h"
#define IPX_MANUAL_ADDRESS
#define MAX_PACKET_DATA 1500
typedef struct IPXAddressStruct {
u_char Network[4] __attribute__((packed));
u_char Node[6] __attribute__((packed));
u_char Socket[2] __attribute__((packed));
u_char Network[4];
u_char Node[6];
u_char Socket[2];
} IPXAddress_t;
typedef struct IPXPacketStructure {
u_short Checksum __attribute__((packed));
u_short Length __attribute__((packed));
u_char TransportControl __attribute__((packed));
u_char PacketType __attribute__((packed));
IPXAddress_t Destination __attribute__((packed));
IPXAddress_t Source __attribute__((packed));
u_short Checksum;
u_short Length;
u_char TransportControl;
u_char PacketType;
IPXAddress_t Destination;
IPXAddress_t Source;
} IPXPacket_t;
typedef struct ipx_socket_struct {
@ -67,6 +68,8 @@ struct ipx_driver {
int (*HandleNetgameAuxData)(ipx_socket_t *s, const u_char buf[]);
void (*HandleLeaveGame)(ipx_socket_t *s);
int (*SendGamePacket)(ipx_socket_t *s, u_char *data, int dataLen);
int (*CheckReadyToJoin)(unsigned char *server, unsigned char *node);
int usepacketnum;//we can save 4 bytes
};
int ipx_general_PacketReady(ipx_socket_t *s);

View file

@ -44,8 +44,6 @@ COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
#ifdef KALINIX
#include "ipx_kali.h"
#endif
#include "ipx_udp.h"
#include "ipx_mcast4.h"
#include "error.h"
#include "../../main/player.h" /* for Players */
#include "../../main/multi.h" /* for NetPlayers */
@ -92,7 +90,8 @@ int ipx_general_PacketReady(ipx_socket_t *s) {
return 0;
}
struct ipx_driver *driver = &ipx_udp;
struct ipx_driver *driver;
extern struct ipx_driver ipx_ip;
ubyte * ipx_get_my_server_address()
{
@ -113,8 +112,7 @@ void arch_ipx_set_driver(int ipx_driver)
#ifdef KALINIX
case IPX_DRIVER_KALI: driver = &ipx_kali; break;
#endif
case IPX_DRIVER_UDP: driver = &ipx_udp; break;
case IPX_DRIVER_MCAST4: driver = &ipx_mcast4; break;
case IPX_DRIVER_UDP: driver = &ipx_ip; break;
default: Int3();
}
}
@ -188,6 +186,7 @@ void ipx_send_packet_data( ubyte * data, int datasize, ubyte *network, ubyte *ad
Assert(datasize <= MAX_IPX_DATA+4);
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 */

View file

@ -24,6 +24,8 @@
//added 05/17/99 Matt Mueller - needed to redefine FD_* so that no asm is used
#include "checker.h"
//end addition -MM
#include "vers_id.h"
int g_sockfd = -1;
struct sockaddr_in kalinix_addr;
char g_mynodenum[6];

169
arch/win32/arch_ip.cpp Executable file
View file

@ -0,0 +1,169 @@
/*
* arch_ip.cpp - arch specific udp/ip code. (win32 ver)
* added 2000/02/07 Matt Mueller (some code borrowed from ipx_udp.c)
*/
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <ctype.h>
extern "C" {
#include "ipx_drv.h"
#include "pstypes.h"
#include "mono.h"
//#include "multi.h"
}
#include "ip_base.h"
#include "ipclient.h"
static int mysock=-1;
extern int nm_messagebox(char *title, int nchoices, ...);
/* Do hostname resolve on name "buf" and return the address in buffer "qhbuf".
*/
int arch_ip_queryhost(ip_addr *addr,char *buf,u_short baseport)
{
struct hostent *he;
char *s;
char c=0;
u_short p;
if ((s=strrchr(buf,':'))) {
c=*s;
*s='\0';
p=ip_portshift(baseport,s+1);
}
else p=ip_portshift(baseport,NULL);
he=gethostbyname((char *)buf);
if (s) *s=c;
if (!he) {
msg("Error resolving my hostname \"%s\"",buf);
return -1;
}
if (he->h_addrtype!=AF_INET || he->h_length!=4) {
msg("Error parsing resolved my hostname \"%s\"",buf);
return -1;
}
if (!*he->h_addr_list) {
msg("My resolved hostname \"%s\" address list empty",buf);
return -1;
}
addr->set(4,(u_char*)*he->h_addr_list,p);
return 0;
}
#ifdef UDPDEBUG
/* Like dumpraddr() but for structure "sockaddr_in"
*/
static void dumpaddr(struct sockaddr_in *sin)
{
unsigned short ports;
u_char qhbuf[6];
memcpy(qhbuf+0,&sin->sin_addr,4);
ports=sin->sin_port;
memcpy(qhbuf+4,&ports,2);
dumpraddr(qhbuf);
}
#endif
int ip_sendtoca(ip_addr addr,const void *buf,int len){
struct sockaddr_in toaddr;
if (addr.addrlen()!=4) return 0;//not handled yet
toaddr.sin_family=AF_INET;
memcpy(&toaddr.sin_addr,addr.addr,4);
toaddr.sin_port=*(unsigned short *)(addr.addr+4);
#ifdef UDPDEBUG
printf(MSGHDR "sendtoca((%d) ",len);
addr.dump();
puts(").");
#endif
return sendto(mysock,(char*)buf,len,0,(struct sockaddr *)&toaddr,sizeof(toaddr));
}
int arch_ip_get_my_addr(u_short myport){
char buf[256];
if (gethostname(buf,sizeof(buf))) FAIL("Error getting my hostname");
ip_addr ip;
if (ip.dns(buf,myport)) FAIL("Error querying my own hostname \"%s\"",buf);
ip_my_addrs.add(ip);
return 0;
}
int arch_ip_open_socket(int port){
struct sockaddr_in sin;
int val_one=1;
WORD wVersionRequested;
WSADATA wsaData;
wVersionRequested = MAKEWORD(2, 0);
if (WSAStartup( wVersionRequested, &wsaData))
{
return -1;
}
if ((mysock = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP)) < 0) {
mysock = -1;
FAIL("socket() creation failed on port %d:\n%m",port);
}
if (setsockopt(mysock,SOL_SOCKET,SO_BROADCAST,(char*)&val_one,sizeof(val_one))) {
if (close(mysock)) msg("close() failed during error recovery: %m");
mysock=-1;
FAIL("setsockopt(SO_BROADCAST) failed:\n%m");
}
sin.sin_family=AF_INET;
sin.sin_addr.s_addr=htonl(INADDR_ANY);
sin.sin_port=htons(port);
if (bind(mysock,(struct sockaddr *)&sin,sizeof(sin))) {
if (close(mysock)) msg("close() failed during error recovery: %m");
mysock=-1;
FAIL("bind() to UDP port %d failed:\n%m",port);
}
return 0;
}
void arch_ip_close_socket(void) {
if (mysock<0) {
msg("close w/o open");
return;
}
if (closesocket(mysock))
msg("close() failed on CloseSocket D1X ip socket %m");
mysock=-1;
WSACleanup();
}
int arch_ip_recvfrom(char*outbuf,int outbufsize,struct ipx_recv_data *rd){
struct sockaddr_in fromaddr;
int fromaddrsize=sizeof(fromaddr);
int size;
static ip_addr ip_fromaddr;
ip_addr *vptr=&ip_fromaddr;
if ((size=recvfrom(mysock,outbuf,outbufsize,0,(struct sockaddr *)&fromaddr,&fromaddrsize))<0)
return -1;
if (fromaddr.sin_family!=AF_INET) return -1;
#ifdef UDPDEBUG
printf(MSGHDR "recvfrom((%d-2=%d),",size,size-2);
dumpaddr(&fromaddr);
puts(").");
#endif
ip_fromaddr.set(4,(u_char*)&fromaddr.sin_addr,fromaddr.sin_port);
memcpy(rd->src_node,&vptr,sizeof(ip_addr*));
return size;
}
int arch_ip_PacketReady(void) {
ipx_socket_t temp;
temp.fd=mysock;
return ipx_general_PacketReady(&temp);
}

View file

@ -26,9 +26,9 @@
#endif
typedef struct IPXAddressStruct {
u_char Network[4] __pack__;
u_char Node[6] __pack__;
u_char Socket[2] __pack__;
u_char Network[4];
u_char Node[6];
u_char Socket[2];
} IPXAddress_t;
typedef struct IPXPacketStructure {
@ -71,6 +71,8 @@ struct ipx_driver {
int (*HandleNetgameAuxData)(ipx_socket_t *s, const u_char buf[]);
void (*HandleLeaveGame)(ipx_socket_t *s);
int (*SendGamePacket)(ipx_socket_t *s, u_char *data, int dataLen);
int (*CheckReadyToJoin)(unsigned char *server, unsigned char *node);
int usepacketnum;//we can save 4 bytes
};
int ipx_general_PacketReady(ipx_socket_t *s);

View file

@ -26,18 +26,18 @@
#endif
typedef struct IPXAddressStruct {
u_char Network[4] __pack__;
u_char Node[6] __pack__;
u_char Socket[2] __pack__;
u_char Network[4];
u_char Node[6];
u_char Socket[2];
} IPXAddress_t;
typedef struct IPXPacketStructure {
u_short Checksum __pack__;
u_short Length __pack__;
u_char TransportControl __pack__;
u_char PacketType __pack__;
IPXAddress_t Destination __pack__;
IPXAddress_t Source __pack__;
u_short Checksum;
u_short Length;
u_char TransportControl;
u_char PacketType;
IPXAddress_t Destination;
IPXAddress_t Source;
} IPXPacket_t;
#ifdef _MSC_VER
@ -71,6 +71,8 @@ struct ipx_driver {
int (*HandleNetgameAuxData)(ipx_socket_t *s, const u_char buf[]);
void (*HandleLeaveGame)(ipx_socket_t *s);
int (*SendGamePacket)(ipx_socket_t *s, u_char *data, int dataLen);
int (*CheckReadyToJoin)(unsigned char *server, unsigned char *node);
int usepacketnum;//we can save 4 bytes
};
int ipx_general_PacketReady(ipx_socket_t *s);

View file

@ -32,8 +32,6 @@ COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
#include "error.h"
#include "ipx.h"
#include "ipx_drv.h"
#include "ipx_udp.h"
#include "ipx_mcast4.h"
#include "../../main/player.h" /* for Players */
#include "../../main/multi.h" /* for NetPlayers */
@ -77,6 +75,7 @@ int ipx_general_PacketReady(ipx_socket_t *s) {
}
struct ipx_driver *driver = &ipx_win;
extern struct ipx_driver ipx_ip;
ubyte * ipx_get_my_server_address()
{
@ -92,8 +91,7 @@ void arch_ipx_set_driver(int ipx_driver)
{
switch(ipx_driver) {
case IPX_DRIVER_IPX: driver = &ipx_win; break;
case IPX_DRIVER_UDP: driver = &ipx_udp; break;
case IPX_DRIVER_MCAST4: driver = &ipx_mcast4; break;
case IPX_DRIVER_UDP: driver = &ipx_ip; break;
default: Int3();
}
}

13
d2x.ini
View file

@ -5,7 +5,7 @@
;-nonicefps Disable CPU cycle freeing. Higher CPU load, but game may be smoother
;-hogdir <dir> set shared data directory to <dir>
;-nohogdir don't try to use shared data directory
;-userdir <dir> set user dir to <dir> instead of $HOME/.d2x-rebirth
;-userdir <dir> set user dir to <dir> instead of $HOME/.d2x-rebirth
;-use_players_dir put player files and saved games in Players subdirectory
;-macdata Read (and, for editor, write) mac data files (swap colors)
;-lowmem Lowers animation detail for better performance with low memory
@ -64,10 +64,7 @@
;-ipxnetwork <num> Use IPX network number <num>
;-kali Use Kali for networking
;-udp Specify options for udp/ip:
; @<shift> Shift udp port base offset
; =<HOST_LIST> Broadcast both local and to HOST_LIST
; +<HOST_LIST> Broadcast only to HOST_LIST
; HOSTS can be any IP or hostname
; HOSTS can also be in the form of <address>:<shift>
; Separate multiple HOSTS with a ,
;-ip_nogetmyaddr Prevent autodetection of local ip address
;-ip_myaddr <a> Use <a> as local ip address
;-ip_bind_addr <a> Bind to <a> instead of INADDR_ANY
;-ip_baseport <p> Use <p> as offset from normal port (allows multiple instances of d1x to be run on a single computer)

View file

@ -253,13 +253,10 @@ void print_commandline_help()
printf( " -packets <num> %s\n", "Specifies the number of packets per second\n");
printf( " -ipxnetwork <num> %s\n", "Use IPX network number <num>");
printf( " -kali %s\n", "Use Kali for networking");
printf( " -udp %s\n", "Specify options for udp/ip:");
printf( " @<shift> %s\n", " Shift udp port base offset");
printf( " =<HOST_LIST> %s\n", " Broadcast both local and to HOST_LIST");
printf( " +<HOST_LIST> %s\n", " Broadcast only to HOST_LIST");
printf( " %s\n", " HOSTS can be any IP or hostname");
printf( " %s\n", " HOSTS can also be in the form of <address>:<shift>");
printf( " %s\n", " Separate multiple HOSTS with a ,");
printf( " -ip_nogetmyaddr %s\n", "Prevent autodetection of local ip address");
printf( " -ip_myaddr <a> %s\n", "Use <a> as local ip address");
printf( " -ip_bind_addr <a> %s\n", "Bind to <a> instead of INADDR_ANY");
printf( " -ip_baseport <p> %s\n", "Use <p> as offset from normal port (allows multiple instances of d1x to be run on a single computer)");
#endif // NETWORK
#ifndef NDEBUG

449
main/ip_base.cpp Executable file
View file

@ -0,0 +1,449 @@
/*
* ip_base.cpp - base for NAT-compatible udp/ip code.
* added 2000/02/07 Matt Mueller
*/
extern "C" {
#include "timer.h"
#include "mono.h"
#include "args.h"
}
#include <string.h>
#include "ip_base.h"
#include <assert.h>
#ifndef _WIN32
#include <netinet/in.h>
#endif
int myport=-1;
int baseport=UDP_BASEPORT;
ip_addr_list ip_my_addrs;
ip_peer_list peer_list;
int ip_handshake_base::fillbuf(ubyte *buf){
u_int32_t tmp32;
u_int16_t tmp16;
int pos=0;
buf[pos++]=type;
buf[pos++]=state;
pos+=id.fillbuf(buf+pos);
tmp16=htons(iver);
memcpy(buf+pos,&tmp16,2);pos+=2;
tmp32=htonl(tryid);
memcpy(buf+pos,&tmp32,4);pos+=4;
return pos;
}
int ip_handshake_base::readbuf(ubyte *buf){
int pos=0;
nopend=1;
type=buf[pos++];
state=buf[pos++];
pos+=id.readbuf(buf+pos);
memcpy(&iver,buf+pos,2);pos+=2;
iver=htons(iver);
memcpy(&tryid,buf+pos,4);pos+=4;
tryid=htonl(tryid);
return pos;
}
void ip_handshake_base::setstate(int newstate){
if (!nopend){
if (state&STATE_NEED_RESEND){
if (!(newstate&STATE_NEED_RESEND))
peer_list.pendinghandshakes--;
}else{
if (newstate&STATE_NEED_RESEND)
peer_list.pendinghandshakes++;
}
mprintf((0,"peer_list.pendinghandshakes=%i\n",peer_list.pendinghandshakes));
}
state=newstate;attempts=0;nextsend=0;
}
int ip_handshake_base::addstate(int newstate){
if (state & STATE_ERR){
setstate((state | newstate) & ~STATE_ERR);
return 2;
}
if ((state | newstate) != state){
setstate(state | newstate);
return 1;
}
return 0;
}
int ip_handshake_info::fillbuf(ubyte *buf){
int pos=ip_handshake_base::fillbuf(buf);
pos+=addr.fillbuf(buf+pos);
return pos;
}
int ip_handshake_info::readbuf(ubyte *buf){
int pos=ip_handshake_base::readbuf(buf);
pos+=addr.readbuf(buf+pos);
return pos;
}
int ip_handshake_relay::fillbuf(ubyte *buf){
u_int16_t tmp16;
int pos=ip_handshake_base::fillbuf(buf);
pos+=r_id.fillbuf(buf+pos);
tmp16=htons(r_iver);
memcpy(buf+pos,&tmp16,2);pos+=2;
pos+=r_addr.fillbuf(buf+pos);
return pos;
}
int ip_handshake_relay::readbuf(ubyte *buf){
int pos=ip_handshake_base::readbuf(buf);
pos+=r_id.readbuf(buf+pos);
memcpy(&r_iver,buf+pos,2);pos+=2;
r_iver=htons(r_iver);
pos+=r_addr.readbuf(buf+pos);
return pos;
}
ip_handshake_relay::ip_handshake_relay(ip_peer *torelay):ip_handshake_base(1){
type=IP_CFG_RELAY;
r_id=torelay->id;
r_iver=torelay->iver;
r_addr=torelay->addr;
setstate(STATE_INEEDINFO);
}
void ip_peer::send_handshake(ip_handshake_base*hsb){
ubyte buf[256];
int s=0;
memcpy(buf+s,D1Xcfgid,4);s+=4;
s+=hsb->fillbuf(buf+s);
assert(s<256);
if (addr.goodaddr==NULL){
ip_addr_list::iterator i;
for (i=addr.begin();i!=addr.end();i++)
ip_sendtoca(*i,buf,s);
}else
ip_sendtoca(*addr.goodaddr,buf,s);
hsb->nextsend=timer_get_approx_seconds()+IP_HS_RETRYTIME;
hsb->attempts++;
}
bool ip_peer::verify_addr(ip_addr_list &fraddrs){
int a1=addr.add(fraddrs);
if (a1)
addr.goodaddr=NULL;
return a1>0;
}
ip_peer * ip_peer_list::add_1(ip_addr addr){
ip_peer*n=add_unk();
n->addr.add(addr);
return n;
}
ip_peer * ip_peer_list::add_full(ip_id id, u_int16_t iver,ip_addr_list &addrs){
ip_peer*n=add_id(id);
n->addr.add(addrs);
n->iver=iver;
mprintf((0,"addfull %i addrs\n",n->addr.naddr));
return n;
}
void ip_peer_list::make_full(ip_peer*p,ip_id id, u_int16_t iver, ip_addr_list &addrs){
list<ip_peer*>::iterator unki=find(unknown_peers.begin(),unknown_peers.end(),p);
if (unki!=unknown_peers.end())
unknown_peers.erase(unki);
p->id=id;
p->iver=iver;
p->addr.add(addrs);
peers.insert(peer_map::value_type(p->id,p));
}
ip_peer * ip_peer_list::find_byid(ip_id id){
peer_map::iterator i=peers.find(id);
if (i!=peers.end())
return (*i).second;
return NULL;
}
struct do_find_by_addr : public unary_function<ip_peer*,bool> {
int j;
ip_addr addr;
bool operator()(ip_peer * p) {
if (p->addr.hasaddr(addr))
return 1;
return 0;
}
};
template <class ret,class p1,class p2, class fo>
struct pairkiller {
fo *o;
ret operator()(pair<p1,p2> &aoeuaoeu) {
return (*o)(aoeuaoeu.second);
}
pairkiller(fo *no):o(no){}
};
template <class p1, class fo>
pairkiller<typename fo::result_type,p1,typename fo::argument_type,fo> pairkill(fo * no){
return pairkiller<typename fo::result_type,p1,typename fo::argument_type,fo>(no);
}
ip_peer * ip_peer_list::find_by_addr(ip_addr addr){
do_find_by_addr fba;
fba.addr=addr;
peer_map::iterator i=find_if(peers.begin(),peers.end(),pairkill<const ip_id>(&fba));
if (i!=peers.end())
return (*i).second;
list<ip_peer*>::iterator j=find_if(unknown_peers.begin(),unknown_peers.end(),fba);
if (j!=unknown_peers.end())
return (*j);
return NULL;
}
ip_peer * ip_peer_list::find_unk_by_addr(ip_addr addr){
do_find_by_addr fba;
fba.addr=addr;
list<ip_peer*>::iterator j=find_if(unknown_peers.begin(),unknown_peers.end(),fba);
if (j!=unknown_peers.end())
return (*j);
return NULL;
}
struct do_peer_handshake : public unary_function<ip_peer *, void>{
fix mintime;
list<ip_handshake_base*>::iterator i;
ip_handshake_base *hsb;
void operator() (ip_peer* peer) {
for(i=peer->handshakes.begin();i!=peer->handshakes.end();++i){
hsb=(*i);
//if (hsb->state<IPNOSTATE && hsb->nextsend<mintime){
if ((hsb->state & STATE_NEED_RESEND) && hsb->nextsend<mintime){
if(hsb->attempts>IP_MAX_HS_ATTEMPTS){
hsb->setstate(STATE_ERR);
}else{
peer->send_handshake(hsb);
}
}
}
}
};
void ip_peer_list::handshake_frame(void){
if(pendinghandshakes){
fix mintime=timer_get_approx_seconds();//try every X seconds
if (pendinghandshake_lasttime<mintime-IP_HS_FRAME_RETRYTIME){
do_peer_handshake doph;
doph.mintime=mintime;
for_each(peers.begin(),peers.end(),pairkill<const ip_id>(&doph));
for_each(unknown_peers.begin(),unknown_peers.end(),doph);
}
}
}
struct do_peer_delete : public unary_function<ip_peer *, void>{
void operator() (ip_peer* peer) {
delete peer;
}
};
void ip_peer_list::clear(void){
do_peer_delete dopd;
for_each(peers.begin(),peers.end(),pairkill<const ip_id>(&dopd));
peers.erase(peers.begin(),peers.end());
for_each(unknown_peers.begin(),unknown_peers.end(),dopd);
unknown_peers.erase(unknown_peers.begin(),unknown_peers.end());
}
ip_peer_list::~ip_peer_list(){
clear();
}
#ifdef UDPDEBUG
//000a0oeuaoeu
static void dumpid(unsigned char *a)
{
printf("<%u.%u.%u.%u.%u.%u>",a[0],a[1],a[2],a[3],a[4],a[5]);
}
#endif
int ip_sendtoid(ubyte *id,const void *buf,int len){
ip_peer *p=peer_list.find_byid(id);
if (!p || p->addr.goodaddr==NULL){
#ifdef UDPDEBUG
printf(MSGHDR"send to invalid id(");
dumpid(id);
printf(") %p.",p);
#endif
return -1;
}
return ip_sendtoca(*p->addr.goodaddr,buf,len);
}
void ip_receive_cfg(ubyte *buf,int buflen,ip_addr fromaddr){
ip_peer *p;
switch(buf[0]){
case IP_CFG_SORRY:
{
#ifdef UDPDEBUG
printf("ip_receive_cfg: %i %i ",buf[0],buf[1]);
dumprid(buf+2);
printf(" v%i tryid%u\n",ntohs(*(unsigned short*)(buf+8)),(unsigned int)ntohl(*(u_int32_t*)(buf+10)));
#endif
}break;
case IP_CFG_HANDSHAKE:
#ifdef UDPDEBUG
printf("ip_receive_cfg: %i %i ",buf[0],buf[1]);
dumprid(buf+2);
printf(" v%i tryid%u\n",ntohs(*(unsigned short*)(buf+8)),(unsigned int)ntohl(*(u_int32_t*)(buf+10)));
#endif
{
ip_handshake_info *hsi=new ip_handshake_info(buf);
hsi->addr.add(fromaddr);
ip_handshake_info *lhsi=NULL;
p=peer_list.find_byid(hsi->id);
if (!p){
p=peer_list.find_unk_by_addr(fromaddr);
if (p){
peer_list.make_full(p,hsi->id,hsi->iver,hsi->addr);
}
}
else
p->verify_addr(hsi->addr);
if (!p){
p=peer_list.add_hsi(hsi);
}
lhsi=p->find_handshake();
lhsi->tryid=hsi->tryid;
if (p->addr.goodaddr==NULL){
p->addr.setgoodaddr(fromaddr);
}
if (hsi->state&STATE_INEEDINFO)
lhsi->setstate(STATE_SENDINGINFO);
else
lhsi->setstate(0);
if (lhsi->state)
p->send_handshake(lhsi);
delete hsi;
}break;
case IP_CFG_RELAY:
{
ip_peer *rp;
ip_handshake_relay hsr(buf);
#ifdef UDPDEBUG
printf("ip_receive_cfg: %i %i ",buf[0],buf[1]);
dumprid(buf+2);
printf(" v%i r_id ",ntohs(*(unsigned short*)(buf+8)));
hsr.r_id.dump();
printf(" r_iv%i\n",hsr.r_iver);
#endif
p=peer_list.find_byid(hsr.id);
if (!p) {
mprintf((0,"relay from unknown peer\n"));
break;//hrm.
}
rp=peer_list.find_byid(hsr.r_id);
if (hsr.state&STATE_RELAYREPLY){
if (!rp) {
mprintf((0,"relay reply for unknown peer\n"));
break;//hrm.
}
ip_handshake_relay *rhsr=p->find_relay(rp->id);
if (!rhsr)
break;
rhsr->setstate(0);
#ifdef UDPDEBUG
printf("**** ");
p->id.dump();
printf(" is ok with ");
rp->id.dump();
printf("\n");
#endif
}else{
if (!rp)
rp=peer_list.add_full(hsr.r_id,hsr.r_iver,hsr.r_addr);
else
rp->verify_addr(hsr.r_addr);
if (rp->addr.goodaddr==NULL){
mprintf((0,"sending relayed handshake\n"));
//handshake with relayed peer
ip_handshake_info *lhsi=rp->find_handshake();
if (lhsi->addstate(STATE_INEEDINFO));
rp->send_handshake(lhsi);
}else{
mprintf((0,"sending relayed reply\n"));
//reply to relayer
ip_handshake_relay rhsr(rp);
rhsr.setstate(STATE_RELAYREPLY);
p->send_handshake(&rhsr);
}
}
}break;
}
}
int ipx_ip_GetMyAddress(void) {
int i;
u_int32_t myhandshakeid;
d_srand( timer_get_approx_seconds() );
ip_my_addrs.clear();
if (!FindArg("-ip_nogetmyaddr"))
arch_ip_get_my_addr(myport);//if we can't get an addr, then we can still probably play, just some NAT configs might not work.
if ((i=FindArg("-ip_myaddr"))){
ip_addr ip;
if (!ip.dns(Args[i+1],myport)){
ip_my_addrs.add(ip);
}
}
myhandshakeid=htonl(d_rand32());
if (ip_my_addrs.naddr){
ip_addr ip=*ip_my_addrs.begin();
ipx_MyAddress[4]=ip.addr[2];
ipx_MyAddress[5]=ip.addr[3];
}else{
ipx_MyAddress[4]=d_rand()%255;
ipx_MyAddress[5]=d_rand()%255;
}
memcpy(ipx_MyAddress+6,&myhandshakeid,4);
#ifdef UDPDEBUG
printf(MSGHDR "Using TCP/IP id ");
dumprid(ipx_MyAddress+4);
putchar('\n');
#endif
return 0;
}
/* Parse PORTSHIFT numeric parameter
*/
unsigned short ip_portshift(unsigned short baseport, const char *cs)
{
long port;
unsigned short ports=htons(baseport);
if (cs){
port=atol(cs);
if (cs[0]=='-' || cs[0]=='+')//relative port
ports=htons(port+baseport);
else
ports=htons(port);//absolute port
}
return ports;
}

379
main/ip_base.h Executable file
View file

@ -0,0 +1,379 @@
/*
* ip_base.h - base for NAT-compatible udp/ip code.
* added 2000/02/07 Matt Mueller
*/
#ifndef ___IP_BASE_H
#define ___IP_BASE_H
#include <map>
#include <list>
#include <algorithm>
extern "C" {
#include "ip_basec.h"
#include "fix.h"
#include "mono.h"
#include "vers_id.h"
#include "timer.h"
}
using namespace std;
class ip_addr;//prototype for arch_ip_queryhost
#include "ipclient.h"
#include <stdio.h>
inline u_int32_t d_rand32(void) { return d_rand() + (d_rand()<<15) + (d_rand()<<30);}//d_rand() only returns 15 bits
void ip_receive_cfg(ubyte *buf,int buflen,ip_addr fromaddr);
extern unsigned char ipx_MyAddress[10];
unsigned short ip_portshift(unsigned short baseport, const char *cs);
#define UDP_BASEPORT 31017
#define UDP_SERV_BASEPORT 30817
#define PORTSHIFT_TOLERANCE 0x100
#define MAX_PACKETSIZE 8192
// Length HAS TO BE 2!
#define D1Xid "\xd1x"
// Length HAS TO BE 4!
#define D1Xcfgid "\xcfg\xd1x"
//cfg packet types
#define IP_CFG_BASE 0
#define IP_CFG_HANDSHAKE 1
#define IP_CFG_RELAY 2
//someone giving us an error (ie, outdated version, etc.) ... not handled yet.
#define IP_CFG_SORRY 3
#define STATE_INEEDINFO 1<<0
#define STATE_SENDINGINFO 1<<1
#define STATE_NEED_RESEND (STATE_INEEDINFO)
#define STATE_VALID_STATES (STATE_INEEDINFO | STATE_SENDINGINFO)
#define STATE_RELAYREPLY 1<<6
#define STATE_ERR 1<<7
/* Dump raw form of IP address/port by fancy output to user
*/
#ifdef UDPDEBUG
#include <stdio.h>
inline char *ip_hs_statetoa(int state){
if (!state)
return "NOSTATE";
if (state&STATE_ERR)
return "ERR";
if ((state&(STATE_INEEDINFO|STATE_SENDINGINFO))==(STATE_INEEDINFO|STATE_SENDINGINFO))
return "NEED+SEND";
if (state&STATE_INEEDINFO)
return "NEED";
if (state&STATE_SENDINGINFO)
return "SEND";
return "huh?";
}
inline void dumprid(const unsigned char *a)
{
printf("<%u.%u.%u.%u.%u.%u>",a[0],a[1],a[2],a[3],a[4],a[5]);
}
inline void dumpraddr(const unsigned char *addr)
{
ushort port;
printf("[%u.%u.%u.%u]",addr[0],addr[1],addr[2],addr[3]);
port=(unsigned short)ntohs(*(unsigned short *)(addr+4));
printf(":%d",port);
}
#endif
class ip_id {
public:
ubyte id[6];
int fillbuf(ubyte *buf)const {memcpy(buf,id,6);return 6;};
int readbuf(const ubyte *buf){memcpy(id,buf,6);return 6;};
bool operator < (const ip_id &a_id)const {return memcmp(id,a_id.id,6)<0;}
bool operator == (const ip_id &a_id)const {return memcmp(id,a_id.id,6)==0;}
bool operator > (const ip_id &a_id)const {return memcmp(id,a_id.id,6)>0;}
ip_id& operator = (const ip_id &a_id){readbuf(a_id.id);return *this;}
#ifdef UDPDEBUG
void dump(void){dumprid(id);}
#endif
ip_id(ubyte*nid){readbuf(nid);}
ip_id(void){};
};
class ip_addr {
protected:
ubyte alen;//alen stuff is to maybe make ipv6 support easier (if the transition ever actually happens)
public:
ubyte addr[6];
int fillbuf(ubyte *buf)const {buf[0]=alen;memcpy(buf+1,addr,alen);return alen+1;};
int readbuf(const ubyte *buf){
int l=buf[0];
if (l==6){
memcpy(addr,buf+1,6);alen=l;
}else{
mprintf((0,"ip_addr readbuf bad len %i\n",l));
memset(addr,0,6);alen=0;
}
return l+1;
};
bool operator < (const ip_addr &a_addr)const {
if (alen!=a_addr.alen) return alen<a_addr.alen;
return memcmp(addr,a_addr.addr,alen)<0;
}
bool operator == (const ip_addr &a_addr)const {return ((alen==a_addr.alen) && (memcmp(addr,a_addr.addr,alen)==0));}
bool operator > (const ip_addr &a_addr)const {
if (alen!=a_addr.alen) return alen>a_addr.alen;
return memcmp(addr,a_addr.addr,alen)>0;
}
ip_addr& operator = (const ip_addr &a_addr){alen=a_addr.alen;memcpy(addr,a_addr.addr,6);return *this;}
#ifdef UDPDEBUG
void dump(void)const{dumpraddr(addr);}
#endif
void set(int addrsize,ubyte *naddr,ushort port){
if (addrsize!=4)return;//not handled yet.
alen=addrsize+2;
memcpy(addr,naddr,addrsize);
memcpy(addr+addrsize,&port,2);
}
int dns(char *address,ushort baseport){
return arch_ip_queryhost(this,address,baseport);
}
bool ok(void)const{return alen>0;}
int addrlen(void)const{return alen-2;}
ip_addr(void){alen=0;};
};
class ip_addr_list {
protected:
list<ip_addr> addrs;
public:
typedef list<ip_addr>::iterator iterator;
typedef list<ip_addr>::const_iterator const_iterator;
int naddr;
ip_addr *goodaddr;
iterator begin(void){return addrs.begin();}
iterator end(void){return addrs.end();}
const_iterator begin(void)const{return addrs.begin();}
const_iterator end(void)const{return addrs.end();}
bool hasaddr(ip_addr addr){
iterator i=find(begin(),end(),addr);
return (i!=addrs.end());
}
int add(ip_addr addr){
if (hasaddr(addr))
return 0;
addrs.push_back(addr);
naddr++;
return 1;
}
int add(const ip_addr_list &na){
int j=0;
const_iterator i=na.begin();
for (;i!=na.end();++i)
j+=add(*i);
return j;
}
void setgoodaddr(ip_addr addr){
iterator i=find(begin(),end(),addr);
if (i!=end()){
goodaddr=&(*i);
return;
}
addrs.push_back(addr);
goodaddr=&(*addrs.end());
}
int fillbuf(ubyte *buf)const {
int s=0;
const_iterator i;
buf[s++]=naddr;
for (i=begin();i!=end();++i)
s+=(*i).fillbuf(buf+s);
return s;
}
int readbuf(const ubyte *buf){
int s=1,n;
ip_addr a;
for (n=buf[0];n;--n){
s+=a.readbuf(buf+s);
if (a.ok())
add(a);
}
return s;
}
void clear(void){
naddr=0;
goodaddr=NULL;
addrs.erase(begin(),end());
}
ip_addr_list(const ip_addr_list &nl):addrs(nl.addrs),naddr(nl.naddr){setgoodaddr(*nl.goodaddr);}
ip_addr_list(void):naddr(0),goodaddr(NULL){}
};
extern ip_addr_list ip_my_addrs;
extern int ip_sendtoca(ip_addr addr,const void *buf,int len);
class ip_handshake_base {
public:
ubyte type;
ubyte state;
ip_id id;
u_int16_t iver;
u_int32_t tryid;
fix nextsend;
int attempts;
int nopend;
virtual int fillbuf(ubyte *buf);
virtual int readbuf(ubyte *buf);
void setrandid(void){tryid=d_rand32() ^ timer_get_approx_seconds();}
void setstate(int newstate);
int addstate(int newstate);
ip_handshake_base(bool initme=0):type(IP_CFG_BASE){
nopend=0;
state=0;
setstate(0);
if(initme){
id=ipx_MyAddress+4;
iver=D2X_IVER;
setrandid();
}
}
virtual ~ip_handshake_base(){setstate(0);}//decrement pendinghandshakes if needed.
};
class ip_handshake_info : public ip_handshake_base {
public:
ip_addr_list addr;
virtual int fillbuf(ubyte *buf);
virtual int readbuf(ubyte *buf);
ip_handshake_info(ubyte *buf){
readbuf(buf);
}
ip_handshake_info(void):ip_handshake_base(1){
type=IP_CFG_HANDSHAKE;
addr=ip_my_addrs;
}
};
class ip_peer;
class ip_handshake_relay : public ip_handshake_base {
public:
ip_id r_id;
u_int16_t r_iver;
ip_addr_list r_addr;
virtual int fillbuf(ubyte *buf);
virtual int readbuf(ubyte *buf);
ip_handshake_relay(ubyte *buf){
readbuf(buf);
}
ip_handshake_relay(ip_peer *torelay);
};
//max number of times to try to handshake a host
#define IP_MAX_HS_ATTEMPTS 10
//how often to resend a hand-shake (3 seconds)
#define IP_HS_RETRYTIME (F1_0*3)
//how often (max) to search through the resend loop (1 second)
#define IP_HS_FRAME_RETRYTIME (F1_0)
class ip_peer {
public:
ip_addr_list addr;
ip_id id;
int iver;
list<ip_handshake_base*> handshakes;
void add_hs(ip_handshake_base* hs){
handshakes.push_back(hs);
}
ip_handshake_relay* find_relay(ip_id r_id){
list<ip_handshake_base*>::iterator i;
ip_handshake_base* hsb;
ip_handshake_relay* hsr;
for (i=handshakes.begin();i!=handshakes.end();++i){
hsb=(*i);
if (hsb->type==IP_CFG_RELAY){
hsr=(ip_handshake_relay*)hsb;
if (hsr->r_id==r_id)
return hsr;
}
}
return NULL;
}
ip_handshake_info* find_handshake(void){
list<ip_handshake_base*>::iterator i;
ip_handshake_base* hsb;
for (i=handshakes.begin();i!=handshakes.end();++i){
hsb=(*i);
if (hsb->type==IP_CFG_HANDSHAKE)
return (ip_handshake_info*) hsb;
}
ip_handshake_info *ni=new ip_handshake_info();
add_hs(ni);
return ni;
}
void send_handshake(ip_handshake_base*hsb);
bool verify_addr(ip_addr_list &fraddrs);
ip_peer(void){iver=0;}
~ip_peer(){
list<ip_handshake_base*>::iterator i;
for (i=handshakes.begin();i!=handshakes.end();++i){
delete (*i);
}
}
};
class ip_peer_list {
public:
typedef map<ip_id,ip_peer *,less<ip_id> > peer_map;
peer_map peers;
list<ip_peer*> unknown_peers;
int pendinghandshakes;
fix pendinghandshake_lasttime;
ip_peer * add_id(ip_id id){
ip_peer*n=new ip_peer();
n->id=id;
peers.insert(peer_map::value_type(n->id,n));
return n;
}
ip_peer * add_unk(void){
ip_peer*n=new ip_peer();
unknown_peers.push_back(n);
return n;
}
ip_peer * add_1(ip_addr addr);
ip_peer * add_full(ip_id id, u_int16_t iver, ip_addr_list &addrs);
void make_full(ip_peer*p,ip_id id, u_int16_t iver, ip_addr_list &addrs);
ip_peer * add_hsi(ip_handshake_info *hsi){return add_full(hsi->id,hsi->iver,hsi->addr);}
ip_peer * find_byid(ip_id id);
ip_peer * find_by_addr(ip_addr addr);
ip_peer * find_unk_by_addr(ip_addr addr);
void handshake_frame(void);
void clear(void);
ip_peer_list(){
pendinghandshakes=0;
pendinghandshake_lasttime=0;
}
~ip_peer_list();
};
extern ip_peer_list peer_list;
#endif

23
main/ip_basec.h Executable file
View file

@ -0,0 +1,23 @@
/*
* ip_basec.h - interface from cpp to c funcs
* added 2000/02/07 Matt Mueller
*/
#ifndef ___IP_BASEC_H
#define ___IP_BASEC_H
#ifdef __cplusplus
extern "C"{
#endif
#include "pstypes.h"
int ip_sendtoid(ubyte *id,const void *buf,int len);
int get_MAX_PLAYERS(void);
int get_Netgame_player_connected(int pn);
ubyte * get_Netgame_player_node(int pn);
#ifdef __cplusplus
}
#endif
#endif

20
main/ipclienc.c Executable file
View file

@ -0,0 +1,20 @@
/*
* ipclienc.h - interface from cpp to c funcs
* added 2000/02/07 Matt Mueller
*/
#include "ip_basec.h"
#include "ipx.h"
#include "network.h"
void ip_sendtoall(char *buf,int len){
int j;
for (j=0;j<MAX_PLAYERS;j++){
if (NetPlayers.players[j].connected && j!=Player_num){
ip_sendtoid(NetPlayers.players[j].network.ipx.node,buf,len);
}
}
}
int get_MAX_PLAYERS(void){return MAX_PLAYERS;}
int get_Netgame_player_connected(int pn){return NetPlayers.players[pn].connected;}
ubyte * get_Netgame_player_node(int pn){return NetPlayers.players[pn].network.ipx.node;}

259
main/ipclient.cpp Executable file
View file

@ -0,0 +1,259 @@
/*
* ipclient.cpp - udp/ip client code
* added 2000/02/07 Matt Mueller
*/
extern "C"{
#include <stdlib.h>
#ifdef __WINDOWS__
#include "alloca.h"
#endif
#include "mono.h"
#include "key.h"
#include "text.h"
#include "newmenu.h"
#include "args.h"
void network_init(void);
int get_and_show_netgame_info(ubyte *server, ubyte *node, ubyte *net_address);
}
#include "ip_base.h"
#include "ipclient.h"
#ifndef _WIN32
#include <netinet/in.h>
#endif
ubyte broadcast_addr[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
ubyte null_addr[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
extern int Player_num;
extern int Network_send_objects;
extern int N_players;
int ip_connect_manual(char *textaddr) {
int r;
ubyte buf[1500];
ip_peer *p;
ip_addr addr;
if (addr.dns(textaddr,UDP_BASEPORT)) {
nm_messagebox(TXT_ERROR,1,TXT_OK,"Could not resolve address");
return -1;
}
#ifdef UDPDEBUG
printf("connecting to ");
addr.dump();
printf("\n");
#endif
network_init();
N_players = 0;
if (!(p=peer_list.find_by_addr(addr))){
p=peer_list.add_1(addr);
}
ip_handshake_info *hsi=p->find_handshake();
hsi->setstate(STATE_INEEDINFO);
while(hsi->state&STATE_VALID_STATES){
r=ipx_get_packet_data(buf);
if (r>0)
mprintf((0,MSGHDR "ip_connect_manual: weird, someone sent us normal data\n"));
if (key_inkey()==KEY_ESC)
return 0;
}
if (hsi->state&STATE_ERR) {
nm_messagebox(TXT_ERROR,1,TXT_OK,"handshake timeout");
return -1;
}
// join the Netgame.
return get_and_show_netgame_info(null_addr,p->id.id,NULL);
}
static int ipx_ip_OpenSocket(ipx_socket_t * socket, int oport) {
int i;
if ((i=FindArg("-ip_baseport"))){
baseport=UDP_BASEPORT+atoi(Args[i+1]);
}
myport=baseport+(oport - IPX_DEFAULT_SOCKET);
if (arch_ip_open_socket(myport)) return -1;
if (ipx_ip_GetMyAddress() < 0) FAIL("Error getting my address");
#ifdef UDPDEBUG
msg("OpenSocket on D1X socket port %d (%d : %+d) : %+d",myport,oport,oport-IPX_DEFAULT_SOCKET,baseport-UDP_BASEPORT);
#endif
return 0;
}
static void ipx_ip_CloseSocket(ipx_socket_t * socket) {
#ifdef UDPDEBUG
msg("CloseSocket on D1X socket port %d",myport);
#endif
arch_ip_close_socket();
peer_list.clear();
}
/* Here we'll send the packet to our host. If it is unicast packet, send
* it to IP address/port as retrieved from IPX address. Otherwise (broadcast)
* we'll repeat the same data to each host in our broadcasting list.
*/
static int ipx_ip_SendPacket(ipx_socket_t * socket, IPXPacket_t *IPXHeader,
ubyte *data, int dataLen) {
int i=dataLen;
char *buf;
if (dataLen<0 || dataLen>MAX_PACKETSIZE) {
#ifdef UDPDEBUG
msg("SendPacket enter, dataLen=%d out of range",dataLen);
#endif
return -1;
}
chk(buf=(char*)alloca(2+dataLen));
memcpy(buf+0,D1Xid ,2);
memcpy(buf+2,data,dataLen);
#ifdef UDPDEBUG
printf(MSGHDR "sendto((%d),Node=[4] %02X %02X,Socket=%02X %02X,s_port=%u,",
dataLen,
IPXHeader->Destination.Node [4],IPXHeader->Destination.Node [5],
IPXHeader->Destination.Socket[0],IPXHeader->Destination.Socket[1],
ntohs(*(unsigned short *)(IPXHeader->Destination.Socket)));
dumprid(IPXHeader->Destination.Node);
puts(").");
#endif
if (memcmp(broadcast_addr,IPXHeader->Destination.Node,6)==0){
ip_addr brbuf;
brbuf.set(4,IPXHeader->Destination.Node,htons(myport));
i=ip_sendtoca(brbuf,buf,2+dataLen);
ip_sendtoall(buf,2+dataLen);
}else {
i=ip_sendtoid(IPXHeader->Destination.Node,buf,2+dataLen);
}
return(i<1?-1:i-1);
}
/* Here we will receive new packet to the given buffer. Both formats of packets
* are supported, we fallback to old format when first obsolete packet is seen.
* If the (valid) packet is received from unknown host, we will add it to our
* broadcasting list. FIXME: For now such autoconfigured hosts are NEVER removed.
*/
static int ipx_ip_ReceivePacket(ipx_socket_t * socket, char *outbuf, int outbufsize,
struct ipx_recv_data *rd) {
int size;
size_t offs;
ip_addr *fromaddr;
if ((size=arch_ip_recvfrom(outbuf,outbufsize,rd))<0)
return -1;
if (size<2) return -1;
memcpy(&fromaddr,rd->src_node,sizeof(ip_addr*));
if (memcmp(outbuf+0,D1Xid,2)) {
if (memcmp(outbuf+0,D1Xcfgid,4)) {
mprintf((0,MSGHDR"no valid header\n"));
return -1;
}
{
ip_receive_cfg((ubyte*)outbuf+4,size-4,*fromaddr);
}
return 0;
}
else
offs=2;
memmove(outbuf,outbuf+offs,size-(offs));
size-=offs;
rd->src_socket = myport;
rd->dst_socket = myport;
rd->pkt_type = 0;
#ifdef UDPDEBUG
printf(MSGHDR "ReceivePacket: size=%d,from=",size);
fromaddr->dump();
putchar('\n');
#endif
if (ip_my_addrs.hasaddr(*fromaddr))
memcpy(rd->src_node,ipx_MyAddress+4,6);
else
memset(rd->src_node,0,6);
return size;
}
static int ipx_ip_general_PacketReady(ipx_socket_t * socket) {
peer_list.handshake_frame();
return arch_ip_PacketReady();
}
static int ipx_ip_CheckReadyToJoin(ubyte *server, ubyte *node){
if (Network_send_objects) return 0;//if we are currently letting someone else join, we don't know if this person can join ok.
ip_peer *p=peer_list.find_byid(node);
if (!p || p->addr.goodaddr==NULL)
return 0;
ip_peer *np;
ip_handshake_relay *hsr;
int j;
int ok,nope=0;
for (j=0;j<get_MAX_PLAYERS();j++){
if (get_Netgame_player_connected(j) && j!=Player_num){
np=peer_list.find_byid(get_Netgame_player_node(j));
if (!np)continue;//huh??
if (np->id==node)continue;//don't tell them to talk to themselves.
ok=0;
hsr=p->find_relay(np->id);
if (!hsr){
hsr=new ip_handshake_relay(np);
p->add_hs(hsr);
}
if (hsr->state==0)
ok++;
hsr=np->find_relay(p->id);
if (!hsr){
hsr=new ip_handshake_relay(p);
np->add_hs(hsr);
}
if (hsr->state==0)
ok++;
if (ok!=2)
nope++;
}
}
if (nope)
return 0;
return 1;
}
struct ipx_driver ipx_ip = {
ipx_ip_GetMyAddress,
ipx_ip_OpenSocket,
ipx_ip_CloseSocket,
ipx_ip_SendPacket,
ipx_ip_ReceivePacket,
ipx_ip_general_PacketReady,
NULL,
NULL,
NULL,
NULL,
ipx_ip_CheckReadyToJoin,
0, //save 4 bytes. udp/ip is completely inaccessable by the other methods, so we don't need to worry about compatibility.
};

59
main/ipclient.h Executable file
View file

@ -0,0 +1,59 @@
/*
* ipclient.h - udp/ip client code
* added 2000/02/07 Matt Mueller
*/
#ifndef __IPCLIENT_H_
#define __IPCLIENT_H_
#include <stdio.h>
#include <stdarg.h>
#ifdef __cplusplus
extern "C"{
#endif
#include "pstypes.h"
#include "ipx.h"
#include "ipx_drv.h"
#include "newmenu.h"
void ip_sendtoall(char *buf,int len);
int ip_connect_manual(char *textaddr);//make it extern C so that it can be called from .c files.
int arch_ip_get_my_addr(ushort myport);
int arch_ip_open_socket(int port);
void arch_ip_close_socket(void);
int arch_ip_recvfrom(char *outbuf,int outbufsize,struct ipx_recv_data *rd);
int arch_ip_PacketReady(void);
int arch_ip_queryhost(ip_addr *addr,char *buf,ushort baseport);
int ipx_ip_GetMyAddress(void);
extern int myport;
extern int baseport;
#ifdef __cplusplus
}
#endif
#define MSGHDR "IPX_ip: "
static inline void msg(const char *fmt,...)
{
va_list ap;
fputs(MSGHDR,stdout);
va_start(ap,fmt);
vprintf(fmt,ap);
va_end(ap);
putchar('\n');
}
#define FAIL(m...) do{ nm_messagebox("Error", 1, "Ok", ##m); return -1; } while (0)
static inline void chk(void *p){
if (p) return;
msg("FATAL: Virtual memory exhausted!");
exit(EXIT_FAILURE);
}
#endif

74
main/ipserver.cpp Executable file
View file

@ -0,0 +1,74 @@
/*
* ipserver.cpp - udp/ip dedicated gamelist server
* added 2000/02/07 Matt Mueller
*/
#include <stdlib.h>
#include <sys/types.h>
#include <sys/time.h>
#include <signal.h>
#include "ip_base.h"
extern "C"{
#include "error.h"
#include "args.h"
#include "u_mem.h"
}
unsigned char ipx_MyAddress[10];
int ipx_general_PacketReady(int fd) {
fd_set set;
struct timeval tv;
FD_ZERO(&set);
FD_SET(fd, &set);
tv.tv_usec = 50000;//50 ms
tv.tv_sec = 0;
if (select(fd + 1, &set, NULL, NULL, &tv) > 0)
return 1;
else
return 0;
}
void ip_server_mainloop(void){
struct ipx_recv_data rd;
int size;
char buf[1500];
ip_addr *fromaddr;
// fix curtime;
while (1){
while (arch_ip_PacketReady()) {
if ((size = arch_ip_recvfrom(buf, 1500, &rd)) > 4) {
memcpy(&fromaddr,rd.src_node,sizeof(ip_addr*));
if (memcmp(buf,D1Xcfgid,4)==0){
ip_receive_cfg((ubyte*)buf+4,size-4,*fromaddr);
}
}
}
peer_list.handshake_frame();
// curtime=timer_get_approx_seconds();
}
}
void int_handler(int s){
exit(1);
}
int main(int argc,char **argv){
error_init(NULL);
signal(SIGINT,int_handler);//make ctrl-c do cleanup stuff.
InitArgs(argc,argv);
#ifndef NDEBUG
if ( FindArg( "-showmeminfo" ) )
show_mem_info = 1; // Make memory statistics show
#endif
myport=UDP_SERV_BASEPORT;
if(arch_ip_open_socket(myport))
return 1;
atexit(arch_ip_close_socket);
if (ipx_ip_GetMyAddress())
return 2;
ip_server_mainloop();
}

28
main/ipserver.h Executable file
View file

@ -0,0 +1,28 @@
/*
* ipserver.h - udp/ip standalone server
* added 2000/02/07 Matt Mueller
*/
#ifndef __IPSERVER_H_
#define __IPSERVER_H_
#include "ip_base.h"
class game_info {
public:
ip_id id;
char *name;
int players;
int maxplayers;
char *mission;
int level;
int gamemode;
int status;
};
class serv_generic_info {
public:
ip_id id;
char
};
#endif

View file

@ -121,8 +121,6 @@ COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
#define MENU_JOIN_UDP_NETGAME 31
#define MENU_START_KALI_NETGAME 32 // Kali support copied from d1x
#define MENU_JOIN_KALI_NETGAME 33
#define MENU_START_MCAST4_NETGAME 34 // UDP/IP over multicast networks
#define MENU_JOIN_MCAST4_NETGAME 35
//ADD_ITEM("Start netgame...", MENU_START_NETGAME, -1 );
//ADD_ITEM("Send net message...", MENU_SEND_NET_MESSAGE, -1 );
@ -151,6 +149,8 @@ void do_detail_level_menu_custom(void);
void do_new_game_menu(void);
#ifdef NETWORK
void do_multi_player_menu(void);
void do_ip_manual_join_menu();
void ip_connect_manual();
void ipx_set_driver(int ipx_driver);
#endif //NETWORK
void do_cpu_menu();
@ -392,27 +392,17 @@ void do_option ( int select)
#ifdef NETWORK
//case MENU_START_TCP_NETGAME:
//case MENU_JOIN_TCP_NETGAME:
case MENU_START_IPX_NETGAME:
case MENU_JOIN_IPX_NETGAME:
case MENU_START_UDP_NETGAME:
case MENU_JOIN_UDP_NETGAME:
case MENU_START_KALI_NETGAME:
case MENU_JOIN_KALI_NETGAME:
case MENU_START_MCAST4_NETGAME:
case MENU_JOIN_MCAST4_NETGAME:
// load_mission(Builtin_mission_num);
#ifdef MACINTOSH
Network_game_type = IPX_GAME;
#endif
// WIN(ipx_create_read_thread());
switch (select & ~0x1) {
case MENU_START_IPX_NETGAME: ipx_set_driver(IPX_DRIVER_IPX); break;
case MENU_START_UDP_NETGAME: ipx_set_driver(IPX_DRIVER_UDP); break;
case MENU_START_KALI_NETGAME: ipx_set_driver(IPX_DRIVER_KALI); break;
case MENU_START_MCAST4_NETGAME: ipx_set_driver(IPX_DRIVER_MCAST4); break;
default: Int3();
case MENU_START_IPX_NETGAME: ipx_set_driver(IPX_DRIVER_IPX); break;
case MENU_START_KALI_NETGAME: ipx_set_driver(IPX_DRIVER_KALI); break;
default: Int3();
}
if ((select & 0x1) == 0) // MENU_START_*_NETGAME
@ -421,30 +411,15 @@ void do_option ( int select)
network_join_game();
break;
#ifdef MACINTOSH
case MENU_START_APPLETALK_NETGAME:
// load_mission(Builtin_mission_num);
#ifdef MACINTOSH
Network_game_type = APPLETALK_GAME;
#endif
case MENU_START_UDP_NETGAME:
ipx_set_driver(IPX_DRIVER_UDP);
network_start_game();
break;
case MENU_JOIN_UDP_NETGAME:
ipx_set_driver(IPX_DRIVER_UDP);
do_ip_manual_join_menu();
break;
case MENU_JOIN_APPLETALK_NETGAME:
// load_mission(Builtin_mission_num);
#ifdef MACINTOSH
Network_game_type = APPLETALK_GAME;
#endif
network_join_game();
break;
#endif
#if 0
case MENU_START_TCP_NETGAME:
case MENU_JOIN_TCP_NETGAME:
nm_messagebox (TXT_SORRY,1,TXT_OK,"Not available in shareware version!");
// DoNewIPAddress();
break;
#endif
case MENU_START_SERIAL:
com_main_menu();
break;
@ -1365,8 +1340,6 @@ void do_multi_player_menu()
int old_game_mode;
do {
// WIN(ipx_destroy_read_thread());
old_game_mode = Game_mode;
num_options = 0;
@ -1374,27 +1347,16 @@ void do_multi_player_menu()
ADD_ITEM(TXT_START_IPX_NET_GAME, MENU_START_IPX_NETGAME, -1);
ADD_ITEM(TXT_JOIN_IPX_NET_GAME, MENU_JOIN_IPX_NETGAME, -1);
#endif //NATIVE_IPX
//ADD_ITEM(TXT_START_TCP_NET_GAME, MENU_START_TCP_NETGAME, -1);
//ADD_ITEM(TXT_JOIN_TCP_NET_GAME, MENU_JOIN_TCP_NETGAME, -1);
ADD_ITEM("Start UDP/IP Netgame", MENU_START_UDP_NETGAME, -1);
ADD_ITEM("Join UDP/IP Netgame\n", MENU_JOIN_UDP_NETGAME, -1);
ADD_ITEM("Start Multicast UDP/IP Netgame", MENU_START_MCAST4_NETGAME, -1);
ADD_ITEM("Join Multicast UDP/IP Netgame\n", MENU_JOIN_MCAST4_NETGAME, -1);
#ifdef KALINIX
ADD_ITEM("Start Kali Netgame", MENU_START_KALI_NETGAME, -1);
ADD_ITEM("Join Kali Netgame\n", MENU_JOIN_KALI_NETGAME, -1);
#endif // KALINIX
#ifdef MACINTOSH
ADD_ITEM("Start Appletalk Netgame", MENU_START_APPLETALK_NETGAME, -1 );
ADD_ITEM("Join Appletalk Netgame\n", MENU_JOIN_APPLETALK_NETGAME, -1 );
#endif
// ADD_ITEM(TXT_MODEM_GAME, MENU_START_SERIAL, -1);
choice = newmenu_do1( NULL, TXT_MULTIPLAYER, num_options, m, NULL, choice );
if ( choice > -1 )
if ( choice > -1 )
do_option(menu_choice[choice]);
if (old_game_mode != Game_mode)
@ -1429,44 +1391,45 @@ void ipx_set_driver(int ipx_driver)
Network_active = 1;
} else {
switch(ipx_error) {
case IPX_NOT_INSTALLED: con_printf(CON_VERBOSE, "%s\n", TXT_NO_NETWORK); break;
case IPX_SOCKET_TABLE_FULL: con_printf(CON_VERBOSE, "%s 0x%x.\n", TXT_SOCKET_ERROR, IPX_DEFAULT_SOCKET+socket); break;
case IPX_NO_LOW_DOS_MEM: con_printf(CON_VERBOSE, "%s\n", TXT_MEMORY_IPX ); break;
default: con_printf(CON_VERBOSE, "%s %d", TXT_ERROR_IPX, ipx_error );
case IPX_NOT_INSTALLED: con_printf(CON_VERBOSE, "%s\n", TXT_NO_NETWORK); break;
case IPX_SOCKET_TABLE_FULL: con_printf(CON_VERBOSE, "%s 0x%x.\n", TXT_SOCKET_ERROR, IPX_DEFAULT_SOCKET+socket); break;
case IPX_NO_LOW_DOS_MEM: con_printf(CON_VERBOSE, "%s\n", TXT_MEMORY_IPX ); break;
default: con_printf(CON_VERBOSE, "%s %d", TXT_ERROR_IPX, ipx_error );
}
con_printf(CON_VERBOSE, "%s\n",TXT_NETWORK_DISABLED);
Network_active = 0; // Assume no network
Network_active = 0; // Assume no network
}
ipx_read_user_file("descent.usr");
ipx_read_network_file("descent.net");
//@@if (FindArg("-dynamicsockets"))
//@@ Network_allow_socket_changes = 1;
//@@else
//@@ Network_allow_socket_changes = 0;
} else {
con_printf(CON_VERBOSE, "%s\n", TXT_NETWORK_DISABLED);
Network_active = 0; // Assume no network
Network_active = 0; // Assume no network
}
}
void DoNewIPAddress ()
{
newmenu_item m[4];
char IPText[30];
int choice;
void do_ip_manual_join_menu()
{
int menu_choice[3];
newmenu_item m[3];
int choice = 0, num_options = 0;
int old_game_mode;
char buf[128]="";
m[0].type=NM_TYPE_TEXT; m[0].text = "Enter an address or hostname:";
m[1].type=NM_TYPE_INPUT; m[1].text_len = 50; m[1].text = IPText;
IPText[0]=0;
do {
old_game_mode = Game_mode;
num_options = 0;
choice = newmenu_do( NULL, "Join a TCPIP game", 2, m, NULL );
m[num_options].type = NM_TYPE_INPUT; m[num_options].text=buf; m[num_options].text_len=128;menu_choice[num_options]=-1; num_options++;
if (choice==-1 || m[1].text[0]==0)
return;
choice = newmenu_do1( NULL, "ENTER IP OR HOSTNAME", num_options, m, NULL, choice );
nm_messagebox (TXT_SORRY,1,TXT_OK,"That address is not valid!");
}
if ( choice > -1 )
ip_connect_manual(buf);
if (old_game_mode != Game_mode)
break; // leave menu
} while( choice > -1 );
}
#endif // NETWORK
#ifdef GP2X

View file

@ -363,6 +363,10 @@ void network_release_registered_game(void);
#endif
// ugly global fellows for the big wait in directIP connection
ubyte *Ext_server=NULL;
ubyte *Ext_node=NULL;
void
network_init(void)
{
@ -1695,8 +1699,12 @@ void network_send_all_info_request(char type,int which_security)
if (Network_game_type == IPX_GAME) {
memcpy( me.player.network.ipx.node, ipx_get_my_local_address(), 6 );
memcpy( me.player.network.ipx.server, ipx_get_my_server_address(), 4 );
send_broadcast_sequence_packet(me);
if (Ext_server==NULL || Ext_node==NULL){
send_broadcast_sequence_packet(me);
}
else {
send_internetwork_sequence_packet( me, Ext_server,Ext_node);
}
#ifdef MACINTOSH
} else {
me.player.network.appletalk.node = appletalk_get_my_node();
@ -1765,7 +1773,10 @@ void
network_send_endlevel_sub(int player_num)
{
endlevel_info end;
int i, j;
int i;
#ifdef WORDS_BIGENDIAN
int j;
#endif
// Send an endlevel packet for a player
end.type = PID_ENDLEVEL;
@ -1778,8 +1789,6 @@ network_send_endlevel_sub(int player_num)
for (i = 0; i < MAX_PLAYERS; i++)
for (j = 0; j < MAX_PLAYERS; j++)
end.kill_matrix[i][j] = INTEL_SHORT(end.kill_matrix[i][j]);
#else
j = j; // to satisfy compiler
#endif
if (Players[player_num].connected == 1) // Still playing
@ -2329,9 +2338,7 @@ void network_process_packet(ubyte *data, int length )
network_send_lite_info(their);
break;
case PID_SEND_ALL_GAMEINFO:
if (length != SEQUENCE_PACKET_SIZE)
{
mprintf ((0,"WARNING! Recieved invalid size for PID_SEND_ALL_GAMEINFO\n"));
@ -4638,11 +4645,10 @@ void network_do_big_wait(int choice)
else
#endif
data = packet;
switch (data[0])
{
case PID_GAME_INFO:
if (Network_game_type == IPX_GAME) {
receive_full_netgame_packet(data, &TempNetInfo);
} else {
@ -4687,7 +4693,6 @@ void network_do_big_wait(int choice)
break;
case PID_PLAYERSINFO:
mprintf ((0,"Got a PID_PLAYERSINFO!\n"));
if (Network_game_type == IPX_GAME) {
#ifndef WORDS_BIGENDIAN
temp_info=(AllNetPlayers_info *)data;
@ -4804,7 +4809,7 @@ void network_listen()
NetSecurityFlag=NETSECURITY_OFF;
i=1;
if (Network_game_type == IPX_GAME) {
// if (Network_game_type == IPX_GAME) {
size = ipx_get_packet_data( packet );
while ( size > 0) {
network_process_packet( packet, size );
@ -4812,17 +4817,17 @@ void network_listen()
break;
size = ipx_get_packet_data( packet );
}
#ifdef MACINTOSH
} else {
size = appletalk_get_packet_data( apacket );
while ( size > 0) {
network_process_packet( apacket, size );
if (++i>loopmax)
break;
size = appletalk_get_packet_data( apacket );
}
#endif
}
// #ifdef MACINTOSH
// } else {
// size = appletalk_get_packet_data( apacket );
// while ( size > 0) {
// network_process_packet( apacket, size );
// if (++i>loopmax)
// break;
// size = appletalk_get_packet_data( apacket );
// }
// #endif
// }
}
int network_wait_for_playerinfo()
@ -6489,3 +6494,141 @@ int HoardEquipped()
}
return (checked);
}
int network_do_join_game()
{
if (Active_games[0].game_status == NETSTAT_ENDLEVEL)
{
nm_messagebox(TXT_SORRY, 1, TXT_OK, TXT_NET_GAME_BETWEEN2);
return 0;
}
// Check for valid mission name
if (!load_mission_by_name(Active_games[0].mission_name))
{
nm_messagebox(NULL, 1, TXT_OK, TXT_MISSION_NOT_FOUND);
return 0;
}
if (!network_wait_for_all_info (0))
{
nm_messagebox (TXT_SORRY,1,TXT_OK,"There was a join error!");
Network_status = NETSTAT_BROWSING; // We are looking at a game menu
Ext_server=NULL;
Ext_node=NULL;
return 0;
}
Network_status = NETSTAT_BROWSING; // We are looking at a game menu
Ext_server=NULL;
Ext_node=NULL;
if (!can_join_netgame(&Active_games[0], &ActiveNetPlayers[0]))
{
if (Active_games[0].numplayers == Active_games[0].max_numplayers)
nm_messagebox(TXT_SORRY, 1, TXT_OK, TXT_GAME_FULL);
else
nm_messagebox(TXT_SORRY, 1, TXT_OK, TXT_IN_PROGRESS);
return 0;
}
// Choice is valid, prepare to join in
memcpy (&Netgame, &Active_games[0], sizeof(netgame_info));
memcpy (&NetPlayers,TempPlayersInfo,sizeof(AllNetPlayers_info));
Difficulty_level = Netgame.difficulty;
MaxNumNetPlayers = Netgame.max_numplayers;
change_playernum_to(1);
network_set_game_mode(Netgame.gamemode);
StartNewLevel(Netgame.levelnum, 0);
return 1; // look ma, we're in a game!!!
}
int show_game_stats(netgame_info game)
{
char rinfo[512],*info=rinfo;
char *NetworkModeNames[]={"Anarchy","Team Anarchy","Robo Anarchy","Cooperative","Capture the Flag","Hoard","Team Hoard","Unknown"};
int c;
memset(info,0,sizeof(char)*256);
info+=sprintf(info,"\nConnected to\n\"%s\"\n",game.game_name);
if(!game.mission_title)
info+=sprintf(info,"Level: Descent2: CounterStrike");
else
info+=sprintf(info,game.mission_title);
info+=sprintf (info," - Lvl %i",game.levelnum);
info+=sprintf (info,"\n\nDifficulty: %s",MENU_DIFFICULTY_TEXT(game.difficulty));
info+=sprintf (info,"\nGame Mode: %s",NetworkModeNames[game.gamemode]);
info+=sprintf (info,"\nPlayers: %i/%i",game.numconnected,game.max_numplayers);
while (1){
c=nm_messagebox("WELCOME", 1, "JOIN GAME", rinfo);
if (c==0)
return 1;
else
return 0;
}
}
int get_and_show_netgame_info(ubyte *server, ubyte *node, ubyte *net_address){
sequence_packet me;
fix nextsend;
int numsent;
fix curtime;
if (setjmp(LeaveGame))
return 0;
num_active_games = 0;
Network_games_changed = 0;
Network_status = NETSTAT_BROWSING;
memset(Active_games, 0, sizeof(netgame_info)*MAX_ACTIVE_NETGAMES);
nextsend=0;numsent=0;
while (1){
curtime=timer_get_fixed_seconds();
if (nextsend<curtime){
if (numsent>=5)
return 0;//timeout
nextsend=curtime+F1_0*3;
numsent++;
mprintf((0, "Sending game_list request.\n"));
memcpy( me.player.callsign, Players[Player_num].callsign, CALLSIGN_LEN+1 );
memcpy( me.player.network.ipx.node, ipx_get_my_local_address(), 6 );
memcpy( me.player.network.ipx.server, ipx_get_my_server_address(), 4 );
me.type = PID_GAME_LIST; //get GAME_LIST - more infos follow later while big wait!
if (net_address != NULL)
send_sequence_packet( me, server,node,net_address);
else
send_internetwork_sequence_packet(me, server, node);
}
network_listen();
if (Network_games_changed){
if (num_active_games<1){
Network_games_changed=0;
continue;
}
if (show_game_stats(Active_games[0])) {
Ext_server=server;
Ext_node=node;
return (network_do_join_game());
}
else
return 0;
}
if (key_inkey()==KEY_ESC)
return 0;
}
return 0;
}

View file

@ -65,6 +65,7 @@ COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
#include "u_mem.h"
#include "strio.h"
#include "physfsx.h"
#include "vers_id.h"
#define SAVE_FILE_ID MAKE_SIG('D','P','L','R')

View file

@ -8,12 +8,16 @@
#ifndef _VERS_ID
#define _VERS_ID
#ifndef VERSION
# define VERSION
#define VERSION_TYPE "Full Version"
#ifdef D2XMICRO
#define VERSION D2XMAJOR "." D2XMINOR "." D2XMICRO
#else
#define VERSION D2XMAJOR "." D2XMINOR
#endif
#define VERSION_TYPE "Full Version"
#define DESCENT_VERSION "D2X-Rebirth v" VERSION
#define D2X_IVER (D2XMAJOR*10000+D2XMINOR*100+D2XMICRO)
// #define D2X_IVER (D2XMAJOR*10000+D2XMINOR*100+D2XMICRO)
#define D2X_IVER (atoi(D2XMAJOR)*1000+atoi(D2XMINOR)*10)
#endif /* _VERS_ID */