Removed old UDP/IP and MCAST4 code; Implemented online-capable UDP/IP interface
This commit is contained in:
parent
ed025f3779
commit
f1134f0bc3
|
@ -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
|
||||
|
|
31
SConstruct
31
SConstruct
|
@ -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
220
arch/linux/arch_ip.cpp
Executable 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);
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
169
arch/win32/arch_ip.cpp
Executable 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);
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
13
d2x.ini
|
@ -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)
|
||||
|
|
|
@ -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
449
main/ip_base.cpp
Executable 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
379
main/ip_base.h
Executable 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
23
main/ip_basec.h
Executable 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
20
main/ipclienc.c
Executable 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
259
main/ipclient.cpp
Executable 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
59
main/ipclient.h
Executable 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
74
main/ipserver.cpp
Executable 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
28
main/ipserver.h
Executable 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
|
109
main/menu.c
109
main/menu.c
|
@ -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
|
||||
|
|
187
main/network.c
187
main/network.c
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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')
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Reference in a new issue