mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-01-30 12:40:42 +00:00
these aren't supported anymore (not as if they're /really/ gone)
This commit is contained in:
parent
f4fdbeee4d
commit
80002a5151
7 changed files with 1 additions and 2706 deletions
|
@ -63,8 +63,7 @@ endif
|
||||||
libnq_net_a_SOURCES= net_dgrm.c net_loop.c net_main.c net_vcr.c $(net_sources)
|
libnq_net_a_SOURCES= net_dgrm.c net_loop.c net_main.c net_vcr.c $(net_sources)
|
||||||
|
|
||||||
EXTRA_libnq_net_a_SOURCES= \
|
EXTRA_libnq_net_a_SOURCES= \
|
||||||
net_dos.c net_bw.c net_bsd.c net_ipx.c net_mp.c net_win.c net_wins.c \
|
net_bsd.c net_win.c net_wins.c net_udp.c
|
||||||
net_wipx.c net_udp.c
|
|
||||||
|
|
||||||
cl_plugin_LIBS= \
|
cl_plugin_LIBS= \
|
||||||
$(CLIENT_PLUGIN_STATIC_LIBS) \
|
$(CLIENT_PLUGIN_STATIC_LIBS) \
|
||||||
|
|
|
@ -1,795 +0,0 @@
|
||||||
|
|
||||||
/*
|
|
||||||
net_bw.c
|
|
||||||
|
|
||||||
@description@
|
|
||||||
|
|
||||||
Copyright (C) 1996-1997 Id Software, Inc.
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU General Public License
|
|
||||||
as published by the Free Software Foundation; either version 2
|
|
||||||
of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
||||||
|
|
||||||
See the GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program; if not, write to:
|
|
||||||
|
|
||||||
Free Software Foundation, Inc.
|
|
||||||
59 Temple Place - Suite 330
|
|
||||||
Boston, MA 02111-1307, USA
|
|
||||||
|
|
||||||
*/
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
# include "config.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static __attribute__ ((unused)) const char rcsid[] =
|
|
||||||
"$Id$";
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <dpmi.h>
|
|
||||||
|
|
||||||
#include "dosisms.h"
|
|
||||||
|
|
||||||
|
|
||||||
// this section is general Unix stuff that we need
|
|
||||||
|
|
||||||
#define EIO 5 /* I/O error */
|
|
||||||
#define EBADS 9
|
|
||||||
#define EWOULDBLOCK 35 /* function would block */
|
|
||||||
#define EMSGSIZE 40 /* message to big for buffers */
|
|
||||||
#define EPROTONOSUPPORT 43 /* Protocol not supported */
|
|
||||||
#define ESOCKTNOSUPPORT 44 /* Socket type not supported */
|
|
||||||
#define EPFNOSUPPORT 46 /* Protocol family not supported */
|
|
||||||
#define EAFNOSUPPORT 47 /* Address family not supported */
|
|
||||||
#define ECONNABORTED 53 /* User requested hangup */
|
|
||||||
#define ENOBUFS 55 /* No buffers available */
|
|
||||||
#define EISCONN 56 /* Socket has closed */
|
|
||||||
#define ENOTCONN 57 /* Socket is not connected */
|
|
||||||
#define ESHUTDOWN 58 /* Socket is closed */
|
|
||||||
#define ETOOMANYREFS 59 /* Too many sockets open */
|
|
||||||
#define ETIMEDOUT 60 /* Connection timed out */
|
|
||||||
#define ECONNREFUSED 61 /* Connection refused */
|
|
||||||
|
|
||||||
#define AF_INET 2 /* internet */
|
|
||||||
|
|
||||||
#define PF_INET AF_INET
|
|
||||||
|
|
||||||
#define SOCK_STREAM 1 /* stream */
|
|
||||||
#define SOCK_DGRAM 2 /* datagram */
|
|
||||||
|
|
||||||
#define IPPROTO_TCP 6
|
|
||||||
#define IPPROTO_UDP 17
|
|
||||||
|
|
||||||
#define INADDR_ANY 0
|
|
||||||
|
|
||||||
#define SIOCDONE 0x7300
|
|
||||||
#define FIONREAD 0x667f
|
|
||||||
#define FIONBIO 0x667e
|
|
||||||
#define FIONWIN 0x1000
|
|
||||||
#define FIONTIN 0x2000
|
|
||||||
|
|
||||||
#define BRDINIT 0
|
|
||||||
#define BRDADDR 10
|
|
||||||
|
|
||||||
#define MAXHOSTNAMELEN 256
|
|
||||||
|
|
||||||
#define SOL_SOCKET 0xffff /* options for socket level */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Option flags per-socket.
|
|
||||||
*/
|
|
||||||
#define SO_DEBUG 0x0001 /* turn on debugging info recording */
|
|
||||||
#define SO_ACCEPTCONN 0x0002 /* socket has had listen() */
|
|
||||||
#define SO_REUSEADDR 0x0004 /* allow local address reuse */
|
|
||||||
#define SO_KEEPALIVE 0x0008 /* keep connections alive */
|
|
||||||
#define SO_DONTROUTE 0x0010 /* just use interface addresses */
|
|
||||||
#define SO_BROADCAST 0x0020 /* permit sending of broadcast msgs */
|
|
||||||
#define SO_USELOOPBACK 0x0040 /* bypass hardware when possible */
|
|
||||||
#define SO_LINGER 0x0080 /* linger on close if data present */
|
|
||||||
#define SO_OOBINLINE 0x0100 /* leave received OOB data in line */
|
|
||||||
#define SO_USEPRIV 0x4000 /* allocate from privileged port area
|
|
||||||
*/
|
|
||||||
#define SO_CANTSIG 0x8000 /* prevent SIGPIPE on SS_CANTSENDMORE
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Additional options, not kept in so_options.
|
|
||||||
*/
|
|
||||||
#define SO_SNDBUF 0x1001 /* send buffer size */
|
|
||||||
#define SO_RCVBUF 0x1002 /* receive buffer size */
|
|
||||||
#define SO_SNDLOWAT 0x1003 /* send low-water mark */
|
|
||||||
#define SO_RCVLOWAT 0x1004 /* receive low-water mark */
|
|
||||||
#define SO_SNDTIMEO 0x1005 /* send timeout */
|
|
||||||
#define SO_RCVTIMEO 0x1006 /* receive timeout */
|
|
||||||
#define SO_ERROR 0x1007 /* get error status and clear */
|
|
||||||
#define SO_TYPE 0x1008 /* get socket type */
|
|
||||||
|
|
||||||
|
|
||||||
struct in_addr {
|
|
||||||
union {
|
|
||||||
struct {
|
|
||||||
unsigned char s_b1, s_b2, s_b3, s_b4;
|
|
||||||
} S_un_b;
|
|
||||||
struct {
|
|
||||||
unsigned short s_w1, s_w2;
|
|
||||||
} S_un_w;
|
|
||||||
unsigned long S_addr;
|
|
||||||
} S_un;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define s_addr S_un.S_addr /* can be used for most tcp & ip code
|
|
||||||
*/
|
|
||||||
#define s_host S_un.S_un_b.s_b2 /* host on imp */
|
|
||||||
#define s_net S_un.S_un_b.s_b1 /* network */
|
|
||||||
#define s_imp S_un.S_un_w.s_w2 /* imp */
|
|
||||||
#define s_impno S_un.S_un_b.s_b4 /* imp # */
|
|
||||||
#define s_lh S_un.S_un_b.s_b3 /* logical host */
|
|
||||||
|
|
||||||
struct sockaddr_in {
|
|
||||||
short sin_family;
|
|
||||||
unsigned short sin_port;
|
|
||||||
struct in_addr sin_addr;
|
|
||||||
char sin_zero[8];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct hostent {
|
|
||||||
char *h_name; /* official name of host */
|
|
||||||
char **h_aliases; /* alias list */
|
|
||||||
int h_addrtype; /* host address type */
|
|
||||||
int h_length; /* length of address */
|
|
||||||
char **h_addr_list; /* list of addresses from name server
|
|
||||||
*/
|
|
||||||
#define h_addr h_addr_list[0] /* address, for backward compatiblity
|
|
||||||
*/
|
|
||||||
};
|
|
||||||
|
|
||||||
char *inet_ntoa (struct in_addr in);
|
|
||||||
|
|
||||||
|
|
||||||
// this section is B&W specific constants & structures
|
|
||||||
|
|
||||||
#define BW_IOCTL_BIND 0
|
|
||||||
#define BW_IOCTL_CLEAROPTIONS 5
|
|
||||||
#define BW_IOCTL_SETOPTIONS 6
|
|
||||||
#define BW_IOCTL_PEEK 7
|
|
||||||
#define BW_IOCTL_SETWINMASK 8
|
|
||||||
|
|
||||||
#define BW_OPTION_BLOCKING 0x01
|
|
||||||
#define BW_OPTION_REUSEBUFFERS 0x80
|
|
||||||
|
|
||||||
#define BW_ERR_USR_HANGUP 50
|
|
||||||
#define BW_ERR_HANGUP 51
|
|
||||||
#define BW_ERR_NET_ERR 52
|
|
||||||
#define BW_ERR_IS_CLOSED 53
|
|
||||||
#define BW_ERR_TIME_OUT 54
|
|
||||||
#define BW_ERR_RESET 55
|
|
||||||
#define BW_ERR_FULL 56
|
|
||||||
#define BW_ERR_BLOCK 57
|
|
||||||
#define BW_ERR_SHUTDOWN 58
|
|
||||||
|
|
||||||
#pragma pack(1)
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
char state; // always 1
|
|
||||||
short localPort;
|
|
||||||
struct in_addr localAddr;
|
|
||||||
char reason; // always 0
|
|
||||||
char options;
|
|
||||||
short dataAvailable;
|
|
||||||
} BW_UDPinfo_t;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
char reserved1[6];
|
|
||||||
unsigned short info2Offset;
|
|
||||||
char reserved2[18];
|
|
||||||
struct in_addr remoteAddr;
|
|
||||||
} BW_UDPreadInfo1_t;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
short remotePort;
|
|
||||||
char reserved1[2];
|
|
||||||
unsigned short dataLenPlus8;
|
|
||||||
char reserved2[2];
|
|
||||||
char data[1]; // actual size is <dataLenPlus8> - 8
|
|
||||||
//
|
|
||||||
} BW_UDPreadInfo2_t;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
char reserved1[2];
|
|
||||||
short remotePort;
|
|
||||||
unsigned short dataLen;
|
|
||||||
struct in_addr remoteAddr;
|
|
||||||
char reserved2[42];
|
|
||||||
char data[1]; // actual size is <datalen>
|
|
||||||
} BW_writeInfo_t;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
short ioport;
|
|
||||||
byte dma;
|
|
||||||
byte vector;
|
|
||||||
byte irq;
|
|
||||||
short bufferSize;
|
|
||||||
short maxWindow;
|
|
||||||
short timeZone;
|
|
||||||
byte myType;
|
|
||||||
int inetAddr;
|
|
||||||
short value;
|
|
||||||
byte subnetMask;
|
|
||||||
short etherPointer;
|
|
||||||
short logserverPointer;
|
|
||||||
short nameserverPointer;
|
|
||||||
short printserverPointer;
|
|
||||||
short timeserverPointer;
|
|
||||||
short gatewayPointer;
|
|
||||||
short driverSegment;
|
|
||||||
byte transferSize;
|
|
||||||
char cardName[9];
|
|
||||||
} BW_ethdevinfo_t;
|
|
||||||
|
|
||||||
#pragma pack()
|
|
||||||
|
|
||||||
#define LOWMEM_SIZE 4096
|
|
||||||
|
|
||||||
static unsigned char *lowmem_buffer;
|
|
||||||
static int lowmem_bufseg;
|
|
||||||
static int lowmem_bufoff;
|
|
||||||
static BW_ethdevinfo_t ethdevinfo;
|
|
||||||
static int netmask;
|
|
||||||
static struct in_addr bcastaddr;
|
|
||||||
|
|
||||||
|
|
||||||
static int net_acceptsocket = -1; // socket for fielding new
|
|
||||||
|
|
||||||
// connections
|
|
||||||
static int net_controlsocket = 0;
|
|
||||||
|
|
||||||
#include "net_bw.h"
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
static int
|
|
||||||
BW_ioctl (int s, char *msg, int msglen)
|
|
||||||
{
|
|
||||||
Q_memcpy (lowmem_buffer, msg, msglen);
|
|
||||||
|
|
||||||
regs.x.ax = 0x4403;
|
|
||||||
regs.x.bx = s;
|
|
||||||
regs.x.cx = msglen;
|
|
||||||
regs.x.dx = lowmem_bufoff;
|
|
||||||
regs.x.ds = lowmem_bufseg;
|
|
||||||
if (dos_int86 (0x21))
|
|
||||||
return regs.x.ax;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
static int
|
|
||||||
BW_TranslateError (int error)
|
|
||||||
{
|
|
||||||
switch (error) {
|
|
||||||
case BW_ERR_USR_HANGUP:
|
|
||||||
return ECONNABORTED;
|
|
||||||
case BW_ERR_HANGUP:
|
|
||||||
return EISCONN;
|
|
||||||
case BW_ERR_NET_ERR:
|
|
||||||
return ENOTCONN;
|
|
||||||
case BW_ERR_IS_CLOSED:
|
|
||||||
return ENOTCONN;
|
|
||||||
case BW_ERR_TIME_OUT:
|
|
||||||
return ETIMEDOUT;
|
|
||||||
case BW_ERR_RESET:
|
|
||||||
return ECONNREFUSED;
|
|
||||||
case BW_ERR_FULL:
|
|
||||||
return ETOOMANYREFS;
|
|
||||||
case BW_ERR_BLOCK:
|
|
||||||
return EWOULDBLOCK;
|
|
||||||
case BW_ERR_SHUTDOWN:
|
|
||||||
return ESHUTDOWN;
|
|
||||||
}
|
|
||||||
return EIO;
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
static int
|
|
||||||
GetEthdevinfo (void)
|
|
||||||
{
|
|
||||||
int fd;
|
|
||||||
|
|
||||||
Q_strcpy ((char *) lowmem_buffer, "ETHDEV27");
|
|
||||||
regs.x.ax = 0x3d42;
|
|
||||||
regs.x.ds = lowmem_bufseg;
|
|
||||||
regs.x.dx = lowmem_bufoff;
|
|
||||||
if (dos_int86 (0x21))
|
|
||||||
return -1;
|
|
||||||
fd = regs.x.ax;
|
|
||||||
|
|
||||||
regs.x.ax = 0x4401;
|
|
||||||
regs.x.bx = fd;
|
|
||||||
regs.x.dx = 0x60;
|
|
||||||
dos_int86 (0x21);
|
|
||||||
|
|
||||||
regs.h.ah = 0x3f;
|
|
||||||
regs.x.cx = sizeof (ethdevinfo);
|
|
||||||
regs.x.es = regs.x.ds = lowmem_bufseg;
|
|
||||||
regs.x.dx = lowmem_bufoff;
|
|
||||||
regs.x.bx = fd;
|
|
||||||
if (dos_int86 (0x21))
|
|
||||||
return -1;
|
|
||||||
Q_memcpy (ðdevinfo, lowmem_buffer, regs.x.ax);
|
|
||||||
|
|
||||||
regs.h.ah = 0x3e;
|
|
||||||
regs.x.bx = fd;
|
|
||||||
dos_int86 (0x21);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
int
|
|
||||||
BW_Init (void)
|
|
||||||
{
|
|
||||||
struct qsockaddr addr;
|
|
||||||
char *colon;
|
|
||||||
|
|
||||||
if (COM_CheckParm ("-noudp"))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
lowmem_buffer = dos_getmemory (LOWMEM_SIZE);
|
|
||||||
if (!lowmem_buffer)
|
|
||||||
Sys_Error ("not enough low memory");
|
|
||||||
lowmem_bufoff = ptr2real (lowmem_buffer) & 0xf;
|
|
||||||
lowmem_bufseg = ptr2real (lowmem_buffer) >> 4;
|
|
||||||
|
|
||||||
if (GetEthdevinfo ()) {
|
|
||||||
Con_DPrintf ("Beame & Whiteside TCP/IP not detected\n");
|
|
||||||
dos_freememory (lowmem_buffer);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
netmask = 0xffffffff >> (32 - ethdevinfo.subnetMask);
|
|
||||||
bcastaddr.s_addr = (ethdevinfo.inetAddr & netmask) | (~netmask);
|
|
||||||
|
|
||||||
if ((net_controlsocket = BW_OpenSocket (0)) == -1) {
|
|
||||||
dos_freememory (lowmem_buffer);
|
|
||||||
Con_DPrintf ("BW_Init unable to open control socket; disabled\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
BW_GetSocketAddr (net_controlsocket, &addr);
|
|
||||||
Q_strcpy (my_tcpip_address, BW_AddrToString (&addr));
|
|
||||||
colon = Q_strrchr (my_tcpip_address, ':');
|
|
||||||
if (colon)
|
|
||||||
*colon = 0;
|
|
||||||
|
|
||||||
Con_Printf ("BW_Init: UDP initialized\n");
|
|
||||||
tcpipAvailable = true;
|
|
||||||
|
|
||||||
return net_controlsocket;
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
void
|
|
||||||
BW_Shutdown (void)
|
|
||||||
{
|
|
||||||
BW_Listen (false);
|
|
||||||
BW_CloseSocket (net_controlsocket);
|
|
||||||
dos_freememory (lowmem_buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
void
|
|
||||||
BW_Listen (qboolean state)
|
|
||||||
{
|
|
||||||
// enable listening
|
|
||||||
if (state) {
|
|
||||||
if (net_acceptsocket != -1)
|
|
||||||
return;
|
|
||||||
if ((net_acceptsocket = BW_OpenSocket (net_hostport)) == -1)
|
|
||||||
Sys_Error ("BW_Listen: Unable to open accept socket");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// disable listening
|
|
||||||
if (net_acceptsocket == -1)
|
|
||||||
return;
|
|
||||||
BW_CloseSocket (net_acceptsocket);
|
|
||||||
net_acceptsocket = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
/*
|
|
||||||
OpenSocket returns a handle to a network socket that has been opened,
|
|
||||||
set to nonblocking, and bound to <port>. Additional socket options
|
|
||||||
should be set here if they are needed. -1 is returned on failure.
|
|
||||||
*/
|
|
||||||
|
|
||||||
int
|
|
||||||
BW_OpenSocket (int port)
|
|
||||||
{
|
|
||||||
int s;
|
|
||||||
int ret;
|
|
||||||
int deadman = 3 * 1024;
|
|
||||||
static int dynamic = 1024;
|
|
||||||
static char reuse_msg[2] = { BW_IOCTL_SETOPTIONS, BW_OPTION_REUSEBUFFERS };
|
|
||||||
static char bind_msg[3] = { BW_IOCTL_BIND, 0, 0 };
|
|
||||||
static char nonblock_msg[2] = { BW_IOCTL_CLEAROPTIONS, BW_OPTION_BLOCKING };
|
|
||||||
|
|
||||||
// allocate a UDP socket
|
|
||||||
Q_strcpy ((char *) lowmem_buffer, "UDP-IP10");
|
|
||||||
regs.x.ax = 0x3d42;
|
|
||||||
regs.x.ds = lowmem_bufseg;
|
|
||||||
regs.x.dx = lowmem_bufoff;
|
|
||||||
if (dos_int86 (0x21)) {
|
|
||||||
Con_Printf ("BW_OpenSocket failed: %u\n",
|
|
||||||
BW_TranslateError (regs.x.ax));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
s = regs.x.ax;
|
|
||||||
|
|
||||||
// set file descriptor to raw mode
|
|
||||||
regs.x.ax = 0x4401;
|
|
||||||
regs.x.bx = s;
|
|
||||||
regs.x.dx = 0x60;
|
|
||||||
dos_int86 (0x21);
|
|
||||||
|
|
||||||
if (BW_ioctl (s, reuse_msg, 2)) {
|
|
||||||
Con_Printf ("BW_OpenSocket ioctl(reuse) failed\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (BW_ioctl (s, nonblock_msg, 2)) {
|
|
||||||
Con_Printf ("BW_OpenSocket ioctl(nonblocking) failed\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
// if a socket was specified, bind to it and return
|
|
||||||
if (port) {
|
|
||||||
*(short *) &bind_msg[1] = port;
|
|
||||||
if (BW_ioctl (s, bind_msg, 3)) {
|
|
||||||
BW_CloseSocket (s);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
// B&W does NOT do dynamic allocation, so if port == 0 we must fake it
|
|
||||||
do {
|
|
||||||
port = dynamic++;
|
|
||||||
if (dynamic == 4096)
|
|
||||||
dynamic = 1024;
|
|
||||||
deadman--;
|
|
||||||
*(short *) &bind_msg[1] = port;
|
|
||||||
ret = BW_ioctl (s, bind_msg, 3);
|
|
||||||
}
|
|
||||||
while (ret && deadman);
|
|
||||||
if (ret)
|
|
||||||
return -1;
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
int
|
|
||||||
BW_CloseSocket (int socket)
|
|
||||||
{
|
|
||||||
regs.h.ah = 0x3e;
|
|
||||||
regs.x.bx = socket;
|
|
||||||
if (dos_int86 (0x21)) {
|
|
||||||
Con_Printf ("BW_CloseSocket %u failed: %u\n", socket,
|
|
||||||
BW_TranslateError (regs.x.ax));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
int
|
|
||||||
BW_Connect (int socket, struct qsockaddr *hostaddr)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
int
|
|
||||||
BW_CheckNewConnections (void)
|
|
||||||
{
|
|
||||||
if (net_acceptsocket == 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
// see if there's anything waiting
|
|
||||||
regs.x.ax = 0x4406;
|
|
||||||
regs.x.bx = net_acceptsocket;
|
|
||||||
dos_int86 (0x21);
|
|
||||||
if (regs.x.ax == 0)
|
|
||||||
return -1;
|
|
||||||
return net_acceptsocket;
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
int
|
|
||||||
BW_Read (int s, byte * buf, int len, struct qsockaddr *from)
|
|
||||||
{
|
|
||||||
BW_UDPreadInfo1_t *info1;
|
|
||||||
BW_UDPreadInfo2_t *info2;
|
|
||||||
|
|
||||||
// ask if there's anything waiting
|
|
||||||
regs.x.ax = 0x4406;
|
|
||||||
regs.x.bx = s;
|
|
||||||
dos_int86 (0x21);
|
|
||||||
if (regs.x.ax == 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
// there was, so let's get it
|
|
||||||
regs.h.ah = 0x3f;
|
|
||||||
regs.x.cx = /* len + 53 */ LOWMEM_SIZE;
|
|
||||||
regs.x.es = regs.x.ds = lowmem_bufseg;
|
|
||||||
regs.x.dx = lowmem_bufoff;
|
|
||||||
regs.x.bx = s;
|
|
||||||
if (dos_int86 (0x21)) {
|
|
||||||
Con_Printf ("BW UDP read error: %u\n", BW_TranslateError (regs.x.ax));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
info1 = (BW_UDPreadInfo1_t *) lowmem_buffer;
|
|
||||||
info2 = (BW_UDPreadInfo2_t *) (lowmem_buffer + info1->info2Offset);
|
|
||||||
|
|
||||||
if (from) {
|
|
||||||
from->sa_family = AF_INET;
|
|
||||||
((struct sockaddr_in *) from)->sin_addr = info1->remoteAddr;
|
|
||||||
((struct sockaddr_in *) from)->sin_port = htons (info2->remotePort);
|
|
||||||
}
|
|
||||||
|
|
||||||
len = info2->dataLenPlus8 - 8;
|
|
||||||
if (len > NET_DATAGRAMSIZE) {
|
|
||||||
Con_Printf ("BW UDP read packet too large: %u\n", len);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
Q_memcpy (buf, info2->data, len);
|
|
||||||
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
int
|
|
||||||
BW_Broadcast (int s, byte * msg, int len)
|
|
||||||
{
|
|
||||||
BW_writeInfo_t *writeInfo;
|
|
||||||
|
|
||||||
// ask if we're clear to send
|
|
||||||
regs.x.ax = 0x4407;
|
|
||||||
regs.x.bx = s;
|
|
||||||
dos_int86 (0x21);
|
|
||||||
if (regs.x.ax == 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
// yes, let's do it
|
|
||||||
writeInfo = (BW_writeInfo_t *) lowmem_buffer;
|
|
||||||
writeInfo->remoteAddr = bcastaddr;
|
|
||||||
writeInfo->remotePort = net_hostport;
|
|
||||||
writeInfo->dataLen = len;
|
|
||||||
if (len > NET_DATAGRAMSIZE)
|
|
||||||
Sys_Error ("BW UDP write packet too large: %u", len);
|
|
||||||
Q_memcpy (writeInfo->data, msg, len);
|
|
||||||
writeInfo->data[len] = 0;
|
|
||||||
regs.h.ah = 0x40;
|
|
||||||
regs.x.bx = s;
|
|
||||||
regs.x.cx = len + sizeof (BW_writeInfo_t);
|
|
||||||
regs.x.es = regs.x.ds = lowmem_bufseg;
|
|
||||||
regs.x.dx = lowmem_bufoff;
|
|
||||||
if (dos_int86 (0x21)) {
|
|
||||||
Con_Printf ("BW_Broadcast failed: %u\n", BW_TranslateError (regs.x.ax));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
int
|
|
||||||
BW_Write (int s, byte * msg, int len, struct qsockaddr *to)
|
|
||||||
{
|
|
||||||
BW_writeInfo_t *writeInfo;
|
|
||||||
|
|
||||||
// ask if we're clear to send
|
|
||||||
regs.x.ax = 0x4407;
|
|
||||||
regs.x.bx = s;
|
|
||||||
dos_int86 (0x21);
|
|
||||||
if (regs.x.ax == 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
// yes, let's do it
|
|
||||||
writeInfo = (BW_writeInfo_t *) lowmem_buffer;
|
|
||||||
writeInfo->remoteAddr = ((struct sockaddr_in *) to)->sin_addr;
|
|
||||||
writeInfo->remotePort = ntohs (((struct sockaddr_in *) to)->sin_port);
|
|
||||||
writeInfo->dataLen = len;
|
|
||||||
if (len > NET_DATAGRAMSIZE)
|
|
||||||
Sys_Error ("BW UDP write packet too large: %u", len);
|
|
||||||
Q_memcpy (writeInfo->data, msg, len);
|
|
||||||
writeInfo->data[len] = 0;
|
|
||||||
regs.h.ah = 0x40;
|
|
||||||
regs.x.bx = s;
|
|
||||||
regs.x.cx = len + sizeof (BW_writeInfo_t);
|
|
||||||
regs.x.es = regs.x.ds = lowmem_bufseg;
|
|
||||||
regs.x.dx = lowmem_bufoff;
|
|
||||||
if (dos_int86 (0x21)) {
|
|
||||||
Con_Printf ("BW_Write failed: %u\n", BW_TranslateError (regs.x.ax));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
|
|
||||||
char *
|
|
||||||
BW_AddrToString (struct qsockaddr *addr)
|
|
||||||
{
|
|
||||||
static char buffer[22];
|
|
||||||
|
|
||||||
snprintf (buffer, sizeof (buffer), "%d.%d.%d.%d:%d",
|
|
||||||
((struct sockaddr_in *) addr)->sin_addr.s_net,
|
|
||||||
((struct sockaddr_in *) addr)->sin_addr.s_host,
|
|
||||||
((struct sockaddr_in *) addr)->sin_addr.s_lh,
|
|
||||||
((struct sockaddr_in *) addr)->sin_addr.s_impno,
|
|
||||||
ntohs (((struct sockaddr_in *) addr)->sin_port)
|
|
||||||
);
|
|
||||||
return buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
int
|
|
||||||
BW_StringToAddr (char *string, struct qsockaddr *addr)
|
|
||||||
{
|
|
||||||
int ha1, ha2, ha3, ha4, hp;
|
|
||||||
int ipaddr;
|
|
||||||
|
|
||||||
sscanf (string, "%d.%d.%d.%d:%d", &ha1, &ha2, &ha3, &ha4, &hp);
|
|
||||||
ipaddr = (ha1 << 24) | (ha2 << 16) | (ha3 << 8) | ha4;
|
|
||||||
|
|
||||||
addr->sa_family = AF_INET;
|
|
||||||
((struct sockaddr_in *) addr)->sin_addr.s_addr = htonl (ipaddr);
|
|
||||||
((struct sockaddr_in *) addr)->sin_port = htons ((short) hp);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
int
|
|
||||||
BW_GetSocketAddr (int socket, struct qsockaddr *addr)
|
|
||||||
{
|
|
||||||
regs.x.ax = 0x4402;
|
|
||||||
regs.x.bx = socket;
|
|
||||||
regs.x.cx = sizeof (BW_UDPinfo_t);
|
|
||||||
regs.x.dx = lowmem_bufoff;
|
|
||||||
regs.x.ds = lowmem_bufseg;
|
|
||||||
dos_int86 (0x21);
|
|
||||||
|
|
||||||
addr->sa_family = AF_INET;
|
|
||||||
|
|
||||||
((struct sockaddr_in *) addr)->sin_addr.s_addr =
|
|
||||||
((BW_UDPinfo_t *) lowmem_buffer)->localAddr.s_addr;
|
|
||||||
((struct sockaddr_in *) addr)->sin_port =
|
|
||||||
htons (((BW_UDPinfo_t *) lowmem_buffer)->localPort);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
int
|
|
||||||
BW_GetNameFromAddr (struct qsockaddr *addr, char *name)
|
|
||||||
{
|
|
||||||
Q_strcpy (name, BW_AddrToString (addr));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
///=============================================================================
|
|
||||||
|
|
||||||
int
|
|
||||||
BW_GetAddrFromName (char *name, struct qsockaddr *hostaddr)
|
|
||||||
{
|
|
||||||
char buff[MAXHOSTNAMELEN];
|
|
||||||
char *b;
|
|
||||||
int addr;
|
|
||||||
int num;
|
|
||||||
int mask;
|
|
||||||
int run;
|
|
||||||
int port;
|
|
||||||
|
|
||||||
if (name[0] < '0' || name[0] > '9')
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
buff[0] = '.';
|
|
||||||
b = buff;
|
|
||||||
Q_strcpy (buff + 1, name);
|
|
||||||
if (buff[1] == '.')
|
|
||||||
b++;
|
|
||||||
|
|
||||||
addr = 0;
|
|
||||||
mask = -1;
|
|
||||||
while (*b == '.') {
|
|
||||||
b++;
|
|
||||||
num = 0;
|
|
||||||
run = 0;
|
|
||||||
while (!(*b < '0' || *b > '9')) {
|
|
||||||
num = num * 10 + *b++ - '0';
|
|
||||||
if (++run > 3)
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if ((*b < '0' || *b > '9') && *b != '.' && *b != ':' && *b != 0)
|
|
||||||
return -1;
|
|
||||||
if (num < 0 || num > 255)
|
|
||||||
return -1;
|
|
||||||
mask <<= 8;
|
|
||||||
addr = (addr << 8) + num;
|
|
||||||
}
|
|
||||||
addr = htonl (addr);
|
|
||||||
mask = htonl (mask);
|
|
||||||
|
|
||||||
if (*b++ == ':')
|
|
||||||
port = Q_atoi (b);
|
|
||||||
else
|
|
||||||
port = net_hostport;
|
|
||||||
|
|
||||||
hostaddr->sa_family = AF_INET;
|
|
||||||
((struct sockaddr_in *) hostaddr)->sin_port = htons ((short) port);
|
|
||||||
((struct sockaddr_in *) hostaddr)->sin_addr.s_addr =
|
|
||||||
((ethdevinfo.inetAddr & mask) | addr);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
int
|
|
||||||
BW_AddrCompare (struct qsockaddr *addr1, struct qsockaddr *addr2)
|
|
||||||
{
|
|
||||||
if (addr1->sa_family != addr2->sa_family)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (((struct sockaddr_in *) addr1)->sin_addr.s_addr !=
|
|
||||||
((struct sockaddr_in *) addr2)->sin_addr.s_addr)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (((struct sockaddr_in *) addr1)->sin_port !=
|
|
||||||
((struct sockaddr_in *) addr2)->sin_port)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
int
|
|
||||||
BW_GetSocketPort (struct qsockaddr *addr)
|
|
||||||
{
|
|
||||||
return ntohs (((struct sockaddr_in *) addr)->sin_port);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
BW_SetSocketPort (struct qsockaddr *addr, int port)
|
|
||||||
{
|
|
||||||
((struct sockaddr_in *) addr)->sin_port = htons (port);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
|
@ -1,166 +0,0 @@
|
||||||
/*
|
|
||||||
net_dos.c
|
|
||||||
|
|
||||||
@description@
|
|
||||||
|
|
||||||
Copyright (C) 1996-1997 Id Software, Inc.
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU General Public License
|
|
||||||
as published by the Free Software Foundation; either version 2
|
|
||||||
of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
||||||
|
|
||||||
See the GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program; if not, write to:
|
|
||||||
|
|
||||||
Free Software Foundation, Inc.
|
|
||||||
59 Temple Place - Suite 330
|
|
||||||
Boston, MA 02111-1307, USA
|
|
||||||
|
|
||||||
*/
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
# include "config.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static __attribute__ ((unused)) const char rcsid[] =
|
|
||||||
"$Id$";
|
|
||||||
|
|
||||||
#include "net_loop.h"
|
|
||||||
#include "net_dgrm.h"
|
|
||||||
#include "net_ser.h"
|
|
||||||
|
|
||||||
net_driver_t net_drivers[MAX_NET_DRIVERS] = {
|
|
||||||
{
|
|
||||||
"Loopback",
|
|
||||||
false,
|
|
||||||
Loop_Init,
|
|
||||||
Loop_Listen,
|
|
||||||
Loop_SearchForHosts,
|
|
||||||
Loop_Connect,
|
|
||||||
Loop_CheckNewConnections,
|
|
||||||
Loop_GetMessage,
|
|
||||||
Loop_SendMessage,
|
|
||||||
Loop_SendUnreliableMessage,
|
|
||||||
Loop_CanSendMessage,
|
|
||||||
Loop_CanSendUnreliableMessage,
|
|
||||||
Loop_Close,
|
|
||||||
Loop_Shutdown}
|
|
||||||
,
|
|
||||||
{
|
|
||||||
"Datagram",
|
|
||||||
false,
|
|
||||||
Datagram_Init,
|
|
||||||
Datagram_Listen,
|
|
||||||
Datagram_SearchForHosts,
|
|
||||||
Datagram_Connect,
|
|
||||||
Datagram_CheckNewConnections,
|
|
||||||
Datagram_GetMessage,
|
|
||||||
Datagram_SendMessage,
|
|
||||||
Datagram_SendUnreliableMessage,
|
|
||||||
Datagram_CanSendMessage,
|
|
||||||
Datagram_CanSendUnreliableMessage,
|
|
||||||
Datagram_Close,
|
|
||||||
Datagram_Shutdown}
|
|
||||||
,
|
|
||||||
{
|
|
||||||
"Serial",
|
|
||||||
false,
|
|
||||||
Serial_Init,
|
|
||||||
Serial_Listen,
|
|
||||||
Serial_SearchForHosts,
|
|
||||||
Serial_Connect,
|
|
||||||
Serial_CheckNewConnections,
|
|
||||||
Serial_GetMessage,
|
|
||||||
Serial_SendMessage,
|
|
||||||
Serial_SendUnreliableMessage,
|
|
||||||
Serial_CanSendMessage,
|
|
||||||
Serial_CanSendUnreliableMessage,
|
|
||||||
Serial_Close,
|
|
||||||
Serial_Shutdown}
|
|
||||||
};
|
|
||||||
|
|
||||||
int net_numdrivers = 3;
|
|
||||||
|
|
||||||
|
|
||||||
#include "net_bw.h"
|
|
||||||
#include "net_ipx.h"
|
|
||||||
#include "net_mp.h"
|
|
||||||
|
|
||||||
net_landriver_t net_landrivers[MAX_NET_DRIVERS] = {
|
|
||||||
{
|
|
||||||
"Beame & Whiteside TCP/IP",
|
|
||||||
false,
|
|
||||||
0,
|
|
||||||
BW_Init,
|
|
||||||
BW_Shutdown,
|
|
||||||
BW_Listen,
|
|
||||||
BW_OpenSocket,
|
|
||||||
BW_CloseSocket,
|
|
||||||
BW_Connect,
|
|
||||||
BW_CheckNewConnections,
|
|
||||||
BW_Read,
|
|
||||||
BW_Write,
|
|
||||||
BW_Broadcast,
|
|
||||||
BW_AddrToString,
|
|
||||||
BW_StringToAddr,
|
|
||||||
BW_GetSocketAddr,
|
|
||||||
BW_GetNameFromAddr,
|
|
||||||
BW_GetAddrFromName,
|
|
||||||
BW_AddrCompare,
|
|
||||||
BW_GetSocketPort,
|
|
||||||
BW_SetSocketPort}
|
|
||||||
,
|
|
||||||
{
|
|
||||||
"IPX",
|
|
||||||
false,
|
|
||||||
0,
|
|
||||||
IPX_Init,
|
|
||||||
IPX_Shutdown,
|
|
||||||
IPX_Listen,
|
|
||||||
IPX_OpenSocket,
|
|
||||||
IPX_CloseSocket,
|
|
||||||
IPX_Connect,
|
|
||||||
IPX_CheckNewConnections,
|
|
||||||
IPX_Read,
|
|
||||||
IPX_Write,
|
|
||||||
IPX_Broadcast,
|
|
||||||
IPX_AddrToString,
|
|
||||||
IPX_StringToAddr,
|
|
||||||
IPX_GetSocketAddr,
|
|
||||||
IPX_GetNameFromAddr,
|
|
||||||
IPX_GetAddrFromName,
|
|
||||||
IPX_AddrCompare,
|
|
||||||
IPX_GetSocketPort,
|
|
||||||
IPX_SetSocketPort}
|
|
||||||
,
|
|
||||||
{
|
|
||||||
"Win95 TCP/IP",
|
|
||||||
false,
|
|
||||||
0,
|
|
||||||
MPATH_Init,
|
|
||||||
MPATH_Shutdown,
|
|
||||||
MPATH_Listen,
|
|
||||||
MPATH_OpenSocket,
|
|
||||||
MPATH_CloseSocket,
|
|
||||||
MPATH_Connect,
|
|
||||||
MPATH_CheckNewConnections,
|
|
||||||
MPATH_Read,
|
|
||||||
MPATH_Write,
|
|
||||||
MPATH_Broadcast,
|
|
||||||
MPATH_AddrToString,
|
|
||||||
MPATH_StringToAddr,
|
|
||||||
MPATH_GetSocketAddr,
|
|
||||||
MPATH_GetNameFromAddr,
|
|
||||||
MPATH_GetAddrFromName,
|
|
||||||
MPATH_AddrCompare,
|
|
||||||
MPATH_GetSocketPort,
|
|
||||||
MPATH_SetSocketPort}
|
|
||||||
};
|
|
||||||
|
|
||||||
int net_numlandrivers = 3;
|
|
|
@ -1,736 +0,0 @@
|
||||||
|
|
||||||
/*
|
|
||||||
net_ipx.c
|
|
||||||
|
|
||||||
@description@
|
|
||||||
|
|
||||||
Copyright (C) 1996-1997 Id Software, Inc.
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU General Public License
|
|
||||||
as published by the Free Software Foundation; either version 2
|
|
||||||
of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
||||||
|
|
||||||
See the GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program; if not, write to:
|
|
||||||
|
|
||||||
Free Software Foundation, Inc.
|
|
||||||
59 Temple Place - Suite 330
|
|
||||||
Boston, MA 02111-1307, USA
|
|
||||||
|
|
||||||
*/
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
# include "config.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static __attribute__ ((unused)) const char rcsid[] =
|
|
||||||
"$Id$";
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <dpmi.h>
|
|
||||||
|
|
||||||
#include "dosisms.h"
|
|
||||||
#include "net_ipx.h"
|
|
||||||
|
|
||||||
#define EIO 5 /* I/O error */
|
|
||||||
|
|
||||||
#define AF_NETWARE 64
|
|
||||||
|
|
||||||
#define IPX_OPEN 0
|
|
||||||
#define IPX_CLOSE 1
|
|
||||||
#define IPX_GETROUTE 2
|
|
||||||
#define IPX_SEND 3
|
|
||||||
#define IPX_LISTEN 4
|
|
||||||
#define IPX_SCHEDULEEVENT 5
|
|
||||||
#define IPX_CANCEL 6
|
|
||||||
#define IPX_SCHEDULESPECIALEVENT 7
|
|
||||||
#define IPX_GETINTERVALMARKER 8
|
|
||||||
#define IPX_GETADDRESS 9
|
|
||||||
#define IPX_RELINQUISH 10
|
|
||||||
|
|
||||||
#define PTYPE_UNKNOWN 0
|
|
||||||
#define PTYPE_RIP 1
|
|
||||||
#define PTYPE_ECHO 2
|
|
||||||
#define PTYPE_ERROR 3
|
|
||||||
#define PTYPE_IPX 4
|
|
||||||
#define PTYPE_SPX 5
|
|
||||||
|
|
||||||
#pragma pack(1)
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
byte network[4];
|
|
||||||
byte node[6];
|
|
||||||
short socket;
|
|
||||||
} IPXaddr;
|
|
||||||
|
|
||||||
struct sockaddr_ipx {
|
|
||||||
short sipx_family;
|
|
||||||
IPXaddr sipx_addr;
|
|
||||||
char sipx_zero[2];
|
|
||||||
};
|
|
||||||
|
|
||||||
#define sipx_port sipx_addr.socket
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
short checkSum;
|
|
||||||
short length;
|
|
||||||
byte transportControl;
|
|
||||||
byte type;
|
|
||||||
IPXaddr destination;
|
|
||||||
IPXaddr source;
|
|
||||||
} IPXheader;
|
|
||||||
|
|
||||||
typedef struct ECBStructure {
|
|
||||||
struct ECBStructure *link;
|
|
||||||
unsigned short ESR_off;
|
|
||||||
unsigned short ESR_seg;
|
|
||||||
byte inUse;
|
|
||||||
byte completionCode;
|
|
||||||
short socket;
|
|
||||||
byte IPXWorkspace[4];
|
|
||||||
byte driverWorkspace[12];
|
|
||||||
byte immediateAddress[6];
|
|
||||||
short fragCount;
|
|
||||||
short fragOff;
|
|
||||||
short fragSeg;
|
|
||||||
short fragSize;
|
|
||||||
} ECB;
|
|
||||||
|
|
||||||
#pragma pack()
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
ECB ecb;
|
|
||||||
IPXheader header;
|
|
||||||
int sequence;
|
|
||||||
char data[NET_DATAGRAMSIZE];
|
|
||||||
} ipx_lowmem_buffer_t;
|
|
||||||
|
|
||||||
#define LOWMEMSIZE (100 * 1024)
|
|
||||||
#define LOWMEMSAVE 256
|
|
||||||
#define IPXBUFFERS ((LOWMEMSIZE - LOWMEMSAVE)/ sizeof(ipx_lowmem_buffer_t))
|
|
||||||
#define IPXSOCKBUFFERS 5
|
|
||||||
#define IPXSOCKETS (IPXBUFFERS / IPXSOCKBUFFERS)
|
|
||||||
|
|
||||||
// each socket's socketbuffer 0 is used for sending, the others for listening
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
char reserved[LOWMEMSAVE];
|
|
||||||
ipx_lowmem_buffer_t socketbuffer[IPXSOCKETS][IPXSOCKBUFFERS];
|
|
||||||
} ipx_lowmem_area_t;
|
|
||||||
|
|
||||||
|
|
||||||
static int ipxsocket[IPXSOCKETS];
|
|
||||||
static ECB *readlist[IPXSOCKETS];
|
|
||||||
static int sequence[IPXSOCKETS];
|
|
||||||
static int handlesInUse;
|
|
||||||
static ipx_lowmem_area_t *lma;
|
|
||||||
static char *lowmem_buffer;
|
|
||||||
static int lowmem_bufseg;
|
|
||||||
static int lowmem_bufoff;
|
|
||||||
static unsigned short ipx_cs;
|
|
||||||
static unsigned short ipx_ip;
|
|
||||||
static int net_acceptsocket = -1;
|
|
||||||
static int net_controlsocket;
|
|
||||||
|
|
||||||
static void IPX_PollProcedure (void);
|
|
||||||
static PollProcedure pollProcedure = { NULL, 0.0, IPX_PollProcedure };
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
static void
|
|
||||||
IPX_GetLocalAddress (IPXaddr * addr)
|
|
||||||
{
|
|
||||||
regs.x.cs = ipx_cs;
|
|
||||||
regs.x.ip = ipx_ip;
|
|
||||||
regs.x.bx = IPX_GETADDRESS;
|
|
||||||
regs.x.es = lowmem_bufseg;
|
|
||||||
regs.x.si = lowmem_bufoff;
|
|
||||||
__dpmi_simulate_real_mode_procedure_retf ((__dpmi_regs *) & regs);
|
|
||||||
Q_memcpy (addr, lowmem_buffer, 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
static int
|
|
||||||
IPX_GetLocalTarget (IPXaddr * addr, byte * localTarget)
|
|
||||||
{
|
|
||||||
regs.x.cs = ipx_cs;
|
|
||||||
regs.x.ip = ipx_ip;
|
|
||||||
regs.x.bx = IPX_GETROUTE;
|
|
||||||
regs.x.es = lowmem_bufseg;
|
|
||||||
regs.x.si = lowmem_bufoff;
|
|
||||||
regs.x.di = lowmem_bufoff + sizeof (IPXaddr);
|
|
||||||
Q_memcpy (lowmem_buffer, addr, sizeof (IPXaddr));
|
|
||||||
__dpmi_simulate_real_mode_procedure_retf ((__dpmi_regs *) & regs);
|
|
||||||
if (regs.h.al)
|
|
||||||
return -1;
|
|
||||||
Q_memcpy (localTarget, lowmem_buffer + sizeof (IPXaddr), 6);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
static void
|
|
||||||
IPX_ListenForPacket (ECB * ecb)
|
|
||||||
{
|
|
||||||
regs.x.cs = ipx_cs;
|
|
||||||
regs.x.ip = ipx_ip;
|
|
||||||
regs.x.bx = IPX_LISTEN;
|
|
||||||
regs.x.es = ptr2real (ecb) >> 4;
|
|
||||||
regs.x.si = ptr2real (ecb) & 0xf;
|
|
||||||
__dpmi_simulate_real_mode_procedure_retf ((__dpmi_regs *) & regs);
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
static void
|
|
||||||
IPX_RelinquishControl (void)
|
|
||||||
{
|
|
||||||
regs.x.cs = ipx_cs;
|
|
||||||
regs.x.ip = ipx_ip;
|
|
||||||
regs.x.bx = IPX_RELINQUISH;
|
|
||||||
__dpmi_simulate_real_mode_procedure_retf ((__dpmi_regs *) & regs);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
IPX_PollProcedure (void)
|
|
||||||
{
|
|
||||||
IPX_RelinquishControl ();
|
|
||||||
SchedulePollProcedure (&pollProcedure, 0.01);
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
static void
|
|
||||||
ProcessReadyList (int s)
|
|
||||||
{
|
|
||||||
int n;
|
|
||||||
ECB *ecb;
|
|
||||||
ECB *prev;
|
|
||||||
|
|
||||||
for (n = 1; n < IPXSOCKBUFFERS; n++) {
|
|
||||||
if (lma->socketbuffer[s][n].ecb.inUse == 0) {
|
|
||||||
for (ecb = readlist[s], prev = NULL; ecb; ecb = ecb->link) {
|
|
||||||
if (lma->socketbuffer[s][n].sequence <
|
|
||||||
((ipx_lowmem_buffer_t *) ecb)->sequence)
|
|
||||||
break;
|
|
||||||
prev = ecb;
|
|
||||||
}
|
|
||||||
if (ecb)
|
|
||||||
lma->socketbuffer[s][n].ecb.link = ecb;
|
|
||||||
else
|
|
||||||
lma->socketbuffer[s][n].ecb.link = NULL;
|
|
||||||
if (prev)
|
|
||||||
prev->link = &lma->socketbuffer[s][n].ecb;
|
|
||||||
else
|
|
||||||
readlist[s] = &lma->socketbuffer[s][n].ecb;
|
|
||||||
lma->socketbuffer[s][n].ecb.inUse = 0xff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
int
|
|
||||||
IPX_Init (void)
|
|
||||||
{
|
|
||||||
int s;
|
|
||||||
int n;
|
|
||||||
struct qsockaddr addr;
|
|
||||||
char *colon;
|
|
||||||
|
|
||||||
if (COM_CheckParm ("-noipx"))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
// find the IPX far call entry point
|
|
||||||
regs.x.ax = 0x7a00;
|
|
||||||
__dpmi_simulate_real_mode_interrupt (0x2f, (__dpmi_regs *) & regs);
|
|
||||||
if (regs.h.al != 0xff) {
|
|
||||||
Con_Printf ("IPX not detected\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
ipx_cs = regs.x.es;
|
|
||||||
ipx_ip = regs.x.di;
|
|
||||||
|
|
||||||
// grab a chunk of memory down in DOS land
|
|
||||||
lowmem_buffer = dos_getmemory (LOWMEMSIZE);
|
|
||||||
if (!lowmem_buffer) {
|
|
||||||
Con_Printf ("IPX_Init: Not enough low memory\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
lowmem_bufoff = ptr2real (lowmem_buffer) & 0xf;
|
|
||||||
lowmem_bufseg = ptr2real (lowmem_buffer) >> 4;
|
|
||||||
|
|
||||||
// init socket handles & buffers
|
|
||||||
handlesInUse = 0;
|
|
||||||
lma = (ipx_lowmem_area_t *) lowmem_buffer;
|
|
||||||
for (s = 0; s < IPXSOCKETS; s++) {
|
|
||||||
ipxsocket[s] = 0;
|
|
||||||
for (n = 0; n < IPXSOCKBUFFERS; n++) {
|
|
||||||
lma->socketbuffer[s][n].ecb.link = NULL;
|
|
||||||
lma->socketbuffer[s][n].ecb.ESR_off = 0;
|
|
||||||
lma->socketbuffer[s][n].ecb.ESR_seg = 0;
|
|
||||||
lma->socketbuffer[s][n].ecb.socket = 0;
|
|
||||||
lma->socketbuffer[s][n].ecb.inUse = 0xff;
|
|
||||||
lma->socketbuffer[s][n].ecb.completionCode = 0;
|
|
||||||
lma->socketbuffer[s][n].ecb.fragCount = 1;
|
|
||||||
lma->socketbuffer[s][n].ecb.fragOff =
|
|
||||||
ptr2real (&lma->socketbuffer[s][n].header) & 0xf;
|
|
||||||
lma->socketbuffer[s][n].ecb.fragSeg =
|
|
||||||
ptr2real (&lma->socketbuffer[s][n].header) >> 4;
|
|
||||||
lma->socketbuffer[s][n].ecb.fragSize =
|
|
||||||
sizeof (IPXheader) + sizeof (int) + NET_DATAGRAMSIZE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((net_controlsocket = IPX_OpenSocket (0)) == -1) {
|
|
||||||
dos_freememory (lowmem_buffer);
|
|
||||||
Con_DPrintf ("IPX_Init: Unable to open control socket\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
SchedulePollProcedure (&pollProcedure, 0.01);
|
|
||||||
|
|
||||||
IPX_GetSocketAddr (net_controlsocket, &addr);
|
|
||||||
Q_strcpy (my_ipx_address, IPX_AddrToString (&addr));
|
|
||||||
colon = Q_strrchr (my_ipx_address, ':');
|
|
||||||
if (colon)
|
|
||||||
*colon = 0;
|
|
||||||
|
|
||||||
Con_Printf ("IPX initialized\n");
|
|
||||||
ipxAvailable = true;
|
|
||||||
return net_controlsocket;
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
void
|
|
||||||
IPX_Shutdown (void)
|
|
||||||
{
|
|
||||||
IPX_Listen (false);
|
|
||||||
IPX_CloseSocket (net_controlsocket);
|
|
||||||
dos_freememory (lowmem_buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
void
|
|
||||||
IPX_Listen (qboolean state)
|
|
||||||
{
|
|
||||||
// enable listening
|
|
||||||
if (state) {
|
|
||||||
if (net_acceptsocket != -1)
|
|
||||||
return;
|
|
||||||
if ((net_acceptsocket = IPX_OpenSocket (net_hostport)) == -1)
|
|
||||||
Sys_Error ("IPX_Listen: Unable to open accept socket");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// disable listening
|
|
||||||
if (net_acceptsocket == -1)
|
|
||||||
return;
|
|
||||||
IPX_CloseSocket (net_acceptsocket);
|
|
||||||
net_acceptsocket = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
int
|
|
||||||
IPX_OpenSocket (int port)
|
|
||||||
{
|
|
||||||
int handle;
|
|
||||||
int n;
|
|
||||||
unsigned short socket;
|
|
||||||
|
|
||||||
if (handlesInUse == IPXSOCKETS)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
// open the IPX socket
|
|
||||||
regs.x.cs = ipx_cs;
|
|
||||||
regs.x.ip = ipx_ip;
|
|
||||||
regs.x.bx = IPX_OPEN;
|
|
||||||
regs.h.al = 0;
|
|
||||||
regs.x.dx = htons (port);
|
|
||||||
__dpmi_simulate_real_mode_procedure_retf ((__dpmi_regs *) & regs);
|
|
||||||
if (regs.h.al == 0xfe) {
|
|
||||||
Con_DPrintf ("IPX_OpenSocket: all sockets in use\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (regs.h.al == 0xff) {
|
|
||||||
Con_DPrintf ("IPX_OpenSocket: socket already open\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (regs.h.al != 0) {
|
|
||||||
Con_DPrintf ("IPX_OpenSocket: error %02x\n", regs.h.al);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
socket = regs.x.dx;
|
|
||||||
|
|
||||||
// grab a handle; fill in the ECBs, and get them listening
|
|
||||||
for (handle = 0; handle < IPXSOCKETS; handle++) {
|
|
||||||
if (ipxsocket[handle] == 0) {
|
|
||||||
ipxsocket[handle] = socket;
|
|
||||||
readlist[handle] = NULL;
|
|
||||||
sequence[handle] = 0;
|
|
||||||
for (n = 0; n < IPXSOCKBUFFERS; n++) {
|
|
||||||
lma->socketbuffer[handle][n].ecb.socket = socket;
|
|
||||||
lma->socketbuffer[handle][n].ecb.inUse = 0;
|
|
||||||
if (n)
|
|
||||||
IPX_ListenForPacket (&lma->socketbuffer[handle][n].ecb);
|
|
||||||
}
|
|
||||||
handlesInUse++;
|
|
||||||
return handle;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// "this will NEVER happen"
|
|
||||||
Sys_Error ("IPX_OpenSocket: handle allocation failed");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
int
|
|
||||||
IPX_CloseSocket (int handle)
|
|
||||||
{
|
|
||||||
// if there's a send in progress, give it one last chance
|
|
||||||
if (lma->socketbuffer[handle][0].ecb.inUse != 0)
|
|
||||||
IPX_RelinquishControl ();
|
|
||||||
|
|
||||||
// close the socket (all pending sends/received are cancelled)
|
|
||||||
regs.x.cs = ipx_cs;
|
|
||||||
regs.x.ip = ipx_ip;
|
|
||||||
regs.x.bx = IPX_CLOSE;
|
|
||||||
regs.x.dx = ipxsocket[handle];
|
|
||||||
__dpmi_simulate_real_mode_procedure_retf ((__dpmi_regs *) & regs);
|
|
||||||
|
|
||||||
ipxsocket[handle] = 0;
|
|
||||||
handlesInUse--;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
int
|
|
||||||
IPX_Connect (int handle, struct qsockaddr *addr)
|
|
||||||
{
|
|
||||||
IPXaddr ipxaddr;
|
|
||||||
|
|
||||||
Q_memcpy (&ipxaddr, &((struct sockaddr_ipx *) addr)->sipx_addr,
|
|
||||||
sizeof (IPXaddr));
|
|
||||||
if (IPX_GetLocalTarget
|
|
||||||
(&ipxaddr, lma->socketbuffer[handle][0].ecb.immediateAddress) != 0) {
|
|
||||||
Con_Printf ("Get Local Target failed\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
int
|
|
||||||
IPX_CheckNewConnections (void)
|
|
||||||
{
|
|
||||||
int n;
|
|
||||||
|
|
||||||
if (net_acceptsocket == -1)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
for (n = 1; n < IPXSOCKBUFFERS; n++)
|
|
||||||
if (lma->socketbuffer[net_acceptsocket][n].ecb.inUse == 0)
|
|
||||||
return net_acceptsocket;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
int
|
|
||||||
IPX_Read (int handle, byte * buf, int len, struct qsockaddr *addr)
|
|
||||||
{
|
|
||||||
ECB *ecb;
|
|
||||||
ipx_lowmem_buffer_t *rcvbuf;
|
|
||||||
int copylen;
|
|
||||||
|
|
||||||
ProcessReadyList (handle);
|
|
||||||
tryagain:
|
|
||||||
if (readlist[handle] == NULL)
|
|
||||||
return 0;
|
|
||||||
ecb = readlist[handle];
|
|
||||||
readlist[handle] = ecb->link;
|
|
||||||
|
|
||||||
if (ecb->completionCode != 0) {
|
|
||||||
Con_Printf ("Warning: IPX_Read error %02x\n", ecb->completionCode);
|
|
||||||
ecb->fragSize = sizeof (IPXheader) + sizeof (int) + NET_DATAGRAMSIZE;
|
|
||||||
|
|
||||||
IPX_ListenForPacket (ecb);
|
|
||||||
goto tryagain;
|
|
||||||
}
|
|
||||||
|
|
||||||
rcvbuf = (ipx_lowmem_buffer_t *) ecb;
|
|
||||||
|
|
||||||
// copy the data up to the buffer
|
|
||||||
copylen =
|
|
||||||
|
|
||||||
ntohs (rcvbuf->header.length) - (sizeof (int) + sizeof (IPXheader));
|
|
||||||
if (len < copylen)
|
|
||||||
Sys_Error ("IPX_Read: buffer too small (%d vs %d)", len, copylen);
|
|
||||||
Q_memcpy (buf, rcvbuf->data, copylen);
|
|
||||||
|
|
||||||
// fill in the addr if they want it
|
|
||||||
if (addr) {
|
|
||||||
((struct sockaddr_ipx *) addr)->sipx_family = AF_NETWARE;
|
|
||||||
Q_memcpy (&((struct sockaddr_ipx *) addr)->sipx_addr,
|
|
||||||
rcvbuf->header.source.network, sizeof (IPXaddr));
|
|
||||||
((struct sockaddr_ipx *) addr)->sipx_zero[0] = 0;
|
|
||||||
((struct sockaddr_ipx *) addr)->sipx_zero[1] = 0;
|
|
||||||
}
|
|
||||||
// update the send ecb's immediate address
|
|
||||||
Q_memcpy (lma->socketbuffer[handle][0].ecb.immediateAddress,
|
|
||||||
rcvbuf->ecb.immediateAddress, 6);
|
|
||||||
|
|
||||||
// get this ecb listening again
|
|
||||||
rcvbuf->ecb.fragSize = sizeof (IPXheader) + sizeof (int) + NET_DATAGRAMSIZE;
|
|
||||||
|
|
||||||
IPX_ListenForPacket (&rcvbuf->ecb);
|
|
||||||
return copylen;
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
int
|
|
||||||
IPX_Broadcast (int handle, byte * buf, int len)
|
|
||||||
{
|
|
||||||
struct sockaddr_ipx addr;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
Q_memset (addr.sipx_addr.network, 0x00, 4);
|
|
||||||
Q_memset (addr.sipx_addr.node, 0xff, 6);
|
|
||||||
addr.sipx_port = htons (net_hostport);
|
|
||||||
Q_memset (lma->socketbuffer[handle][0].ecb.immediateAddress, 0xff, 6);
|
|
||||||
ret = IPX_Write (handle, buf, len, (struct qsockaddr *) &addr);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
int
|
|
||||||
IPX_Write (int handle, byte * buf, int len, struct qsockaddr *addr)
|
|
||||||
{
|
|
||||||
// has the previous send completed?
|
|
||||||
while (lma->socketbuffer[handle][0].ecb.inUse != 0)
|
|
||||||
IPX_RelinquishControl ();
|
|
||||||
|
|
||||||
switch (lma->socketbuffer[handle][0].ecb.completionCode) {
|
|
||||||
case 0x00: // success
|
|
||||||
case 0xfc: // request cancelled
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0xfd: // malformed packet
|
|
||||||
default:
|
|
||||||
Con_Printf ("IPX driver send failure: %02x\n",
|
|
||||||
lma->socketbuffer[handle][0].ecb.completionCode);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0xfe: // packet undeliverable
|
|
||||||
case 0xff: // unable to send packet
|
|
||||||
Con_Printf ("IPX lost route, trying to re-establish\n");
|
|
||||||
|
|
||||||
// look for a new route
|
|
||||||
if (IPX_GetLocalTarget
|
|
||||||
(&lma->socketbuffer[handle][0].header.destination,
|
|
||||||
lma->socketbuffer[handle][0].ecb.immediateAddress) != 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
// re-send the one that failed
|
|
||||||
regs.x.cs = ipx_cs;
|
|
||||||
regs.x.ip = ipx_ip;
|
|
||||||
regs.x.bx = IPX_SEND;
|
|
||||||
regs.x.es = ptr2real (&lma->socketbuffer[handle][0].ecb) >> 4;
|
|
||||||
regs.x.si = ptr2real (&lma->socketbuffer[handle][0].ecb) & 0xf;
|
|
||||||
__dpmi_simulate_real_mode_procedure_retf ((__dpmi_regs *) & regs);
|
|
||||||
|
|
||||||
// report that we did not send the current one
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ecb : length
|
|
||||||
lma->socketbuffer[handle][0].ecb.fragSize =
|
|
||||||
sizeof (IPXheader) + sizeof (int) + len;
|
|
||||||
|
|
||||||
// ipx header : type
|
|
||||||
lma->socketbuffer[handle][0].header.type = PTYPE_IPX;
|
|
||||||
|
|
||||||
// ipx header : destination
|
|
||||||
Q_memcpy (&lma->socketbuffer[handle][0].header.destination,
|
|
||||||
&((struct sockaddr_ipx *) addr)->sipx_addr, sizeof (IPXaddr));
|
|
||||||
|
|
||||||
// sequence number
|
|
||||||
lma->socketbuffer[handle][0].sequence = sequence[handle];
|
|
||||||
sequence[handle]++;
|
|
||||||
|
|
||||||
// copy down the data
|
|
||||||
Q_memcpy (lma->socketbuffer[handle][0].data, buf, len);
|
|
||||||
|
|
||||||
regs.x.cs = ipx_cs;
|
|
||||||
regs.x.ip = ipx_ip;
|
|
||||||
regs.x.bx = IPX_SEND;
|
|
||||||
regs.x.es = ptr2real (&lma->socketbuffer[handle][0].ecb) >> 4;
|
|
||||||
regs.x.si = ptr2real (&lma->socketbuffer[handle][0].ecb) & 0xf;
|
|
||||||
__dpmi_simulate_real_mode_procedure_retf ((__dpmi_regs *) & regs);
|
|
||||||
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
char *
|
|
||||||
IPX_AddrToString (struct qsockaddr *addr)
|
|
||||||
{
|
|
||||||
static char buf[28];
|
|
||||||
|
|
||||||
snprintf (buf, sizeof (buf), "%02x%02x%02x%02x:%02x%02x%02x%02x%02x%02x:%u",
|
|
||||||
((struct sockaddr_ipx *) addr)->sipx_addr.network[0],
|
|
||||||
((struct sockaddr_ipx *) addr)->sipx_addr.network[1],
|
|
||||||
((struct sockaddr_ipx *) addr)->sipx_addr.network[2],
|
|
||||||
((struct sockaddr_ipx *) addr)->sipx_addr.network[3],
|
|
||||||
((struct sockaddr_ipx *) addr)->sipx_addr.node[0],
|
|
||||||
((struct sockaddr_ipx *) addr)->sipx_addr.node[1],
|
|
||||||
((struct sockaddr_ipx *) addr)->sipx_addr.node[2],
|
|
||||||
((struct sockaddr_ipx *) addr)->sipx_addr.node[3],
|
|
||||||
((struct sockaddr_ipx *) addr)->sipx_addr.node[4],
|
|
||||||
((struct sockaddr_ipx *) addr)->sipx_addr.node[5],
|
|
||||||
ntohs (((struct sockaddr_ipx *) addr)->sipx_port)
|
|
||||||
);
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
int
|
|
||||||
IPX_StringToAddr (char *string, struct qsockaddr *addr)
|
|
||||||
{
|
|
||||||
int val;
|
|
||||||
char buf[3];
|
|
||||||
|
|
||||||
buf[2] = 0;
|
|
||||||
Q_memset (addr, 0, sizeof (struct qsockaddr));
|
|
||||||
|
|
||||||
addr->sa_family = AF_NETWARE;
|
|
||||||
|
|
||||||
#define DO(src,dest) \
|
|
||||||
buf[0] = string[src]; \
|
|
||||||
buf[1] = string[src + 1]; \
|
|
||||||
if (sscanf (buf, "%x", &val) != 1) \
|
|
||||||
return -1; \
|
|
||||||
((struct sockaddr_ipx *)addr)->sipx_addr.dest = val
|
|
||||||
|
|
||||||
DO (0, network[0]);
|
|
||||||
DO (2, network[1]);
|
|
||||||
DO (4, network[2]);
|
|
||||||
DO (6, network[3]);
|
|
||||||
DO (9, node[0]);
|
|
||||||
DO (11, node[1]);
|
|
||||||
DO (13, node[2]);
|
|
||||||
DO (15, node[3]);
|
|
||||||
DO (17, node[4]);
|
|
||||||
DO (19, node[5]);
|
|
||||||
#undef DO
|
|
||||||
|
|
||||||
sscanf (&string[22], "%u", &val);
|
|
||||||
((struct sockaddr_ipx *) addr)->sipx_port = htons (val);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
int
|
|
||||||
IPX_GetSocketAddr (int handle, struct qsockaddr *addr)
|
|
||||||
{
|
|
||||||
Q_memset (addr, 0, sizeof (struct qsockaddr));
|
|
||||||
|
|
||||||
addr->sa_family = AF_NETWARE;
|
|
||||||
IPX_GetLocalAddress (&((struct sockaddr_ipx *) addr)->sipx_addr);
|
|
||||||
((struct sockaddr_ipx *) addr)->sipx_port = ipxsocket[handle];
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
int
|
|
||||||
IPX_GetNameFromAddr (struct qsockaddr *addr, char *name)
|
|
||||||
{
|
|
||||||
Q_strcpy (name, IPX_AddrToString (addr));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
int
|
|
||||||
IPX_GetAddrFromName (char *name, struct qsockaddr *addr)
|
|
||||||
{
|
|
||||||
int n;
|
|
||||||
char buf[32];
|
|
||||||
|
|
||||||
n = Q_strlen (name);
|
|
||||||
|
|
||||||
if (n == 12) {
|
|
||||||
snprintf (buf, sizeof (buf), "00000000:%s:%u", name, net_hostport);
|
|
||||||
return IPX_StringToAddr (buf, addr);
|
|
||||||
}
|
|
||||||
if (n == 21) {
|
|
||||||
snprintf (buf, sizeof (buf), "%s:%u", name, net_hostport);
|
|
||||||
return IPX_StringToAddr (buf, addr);
|
|
||||||
}
|
|
||||||
if (n > 21 && n <= 27)
|
|
||||||
return IPX_StringToAddr (name, addr);
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
int
|
|
||||||
IPX_AddrCompare (struct qsockaddr *addr1, struct qsockaddr *addr2)
|
|
||||||
{
|
|
||||||
if (addr1->sa_family != addr2->sa_family)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (Q_memcmp
|
|
||||||
(&((struct sockaddr_ipx *) addr1)->sipx_addr,
|
|
||||||
&((struct sockaddr_ipx *) addr2)->sipx_addr, 10))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (((struct sockaddr_ipx *) addr1)->sipx_port !=
|
|
||||||
((struct sockaddr_ipx *) addr2)->sipx_port)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
int
|
|
||||||
IPX_GetSocketPort (struct qsockaddr *addr)
|
|
||||||
{
|
|
||||||
return ntohs (((struct sockaddr_ipx *) addr)->sipx_port);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
IPX_SetSocketPort (struct qsockaddr *addr, int port)
|
|
||||||
{
|
|
||||||
((struct sockaddr_ipx *) addr)->sipx_port = htons (port);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
|
@ -1,480 +0,0 @@
|
||||||
/*
|
|
||||||
net_mp.c
|
|
||||||
|
|
||||||
@description@
|
|
||||||
|
|
||||||
Copyright (C) 1996-1997 Id Software, Inc.
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU General Public License
|
|
||||||
as published by the Free Software Foundation; either version 2
|
|
||||||
of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
||||||
|
|
||||||
See the GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program; if not, write to:
|
|
||||||
|
|
||||||
Free Software Foundation, Inc.
|
|
||||||
59 Temple Place - Suite 330
|
|
||||||
Boston, MA 02111-1307, USA
|
|
||||||
|
|
||||||
*/
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
# include "config.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static __attribute__ ((unused)) const char rcsid[] =
|
|
||||||
"$Id$";
|
|
||||||
|
|
||||||
#include <dpmi.h>
|
|
||||||
#include "mpdosock.h"
|
|
||||||
|
|
||||||
short flat_selector;
|
|
||||||
|
|
||||||
int WSAGetLastError (void);
|
|
||||||
void sockets_flush (void);
|
|
||||||
|
|
||||||
#define MAXHOSTNAMELEN 256
|
|
||||||
|
|
||||||
static int net_acceptsocket = -1; // socket for fielding new
|
|
||||||
|
|
||||||
// connections
|
|
||||||
static int net_controlsocket;
|
|
||||||
static int net_broadcastsocket = 0;
|
|
||||||
|
|
||||||
//static qboolean ifbcastinit = false;
|
|
||||||
static struct qsockaddr broadcastaddr;
|
|
||||||
|
|
||||||
static unsigned long myAddr;
|
|
||||||
|
|
||||||
#include "net_mp.h"
|
|
||||||
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
int
|
|
||||||
MPATH_Init (void)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
struct hostent *local = NULL;
|
|
||||||
char buff[MAXHOSTNAMELEN];
|
|
||||||
struct qsockaddr addr;
|
|
||||||
char *p;
|
|
||||||
|
|
||||||
if (COM_CheckParm ("-mpath") == 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
flat_selector = __dpmi_allocate_ldt_descriptors (1);
|
|
||||||
if (flat_selector == -1) {
|
|
||||||
Con_Printf ("MPATH_Init: Can't get flat selector\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (__dpmi_set_segment_base_address (flat_selector, 0) == -1) {
|
|
||||||
Con_Printf ("MPATH_Init: Can't seg flat base!\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (__dpmi_set_segment_limit (flat_selector, 0xffffffff) == -1) {
|
|
||||||
Con_Printf ("MPATH_Init: Can't set segment limit\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
// determine my name & address
|
|
||||||
if (gethostname (buff, MAXHOSTNAMELEN) == 0)
|
|
||||||
local = gethostbyname (buff);
|
|
||||||
if (local) {
|
|
||||||
myAddr = *(int *) local->h_addr_list[0];
|
|
||||||
|
|
||||||
// if the quake hostname isn't set, set it to the machine name
|
|
||||||
if (Q_strcmp (hostname->string, "UNNAMED") == 0) {
|
|
||||||
// see if it's a text IP address (well, close enough)
|
|
||||||
for (p = buff; *p; p++)
|
|
||||||
if ((*p < '0' || *p > '9') && *p != '.')
|
|
||||||
break;
|
|
||||||
|
|
||||||
// if it is a real name, strip off the domain; we only want the
|
|
||||||
// host
|
|
||||||
if (*p) {
|
|
||||||
for (i = 0; i < 15; i++)
|
|
||||||
if (buff[i] == '.')
|
|
||||||
break;
|
|
||||||
buff[i] = 0;
|
|
||||||
}
|
|
||||||
Cvar_Set (hostname, buff);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((net_controlsocket = MPATH_OpenSocket (0)) == -1)
|
|
||||||
Sys_Error ("MPATH_Init: Unable to open control socket");
|
|
||||||
|
|
||||||
((struct sockaddr_in *) &broadcastaddr)->sin_family = AF_INET;
|
|
||||||
((struct sockaddr_in *) &broadcastaddr)->sin_addr.s_addr = INADDR_BROADCAST;
|
|
||||||
((struct sockaddr_in *) &broadcastaddr)->sin_port = htons (net_hostport);
|
|
||||||
|
|
||||||
MPATH_GetSocketAddr (net_controlsocket, &addr);
|
|
||||||
Q_strcpy (my_tcpip_address, MPATH_AddrToString (&addr));
|
|
||||||
p = Q_strrchr (my_tcpip_address, ':');
|
|
||||||
if (p)
|
|
||||||
*p = 0;
|
|
||||||
|
|
||||||
Con_Printf ("MPath Initialized\n");
|
|
||||||
tcpipAvailable = true;
|
|
||||||
|
|
||||||
return net_controlsocket;
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
void
|
|
||||||
MPATH_Shutdown (void)
|
|
||||||
{
|
|
||||||
MPATH_Listen (false);
|
|
||||||
MPATH_CloseSocket (net_controlsocket);
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
void
|
|
||||||
MPATH_Listen (qboolean state)
|
|
||||||
{
|
|
||||||
// enable listening
|
|
||||||
if (state) {
|
|
||||||
if (net_acceptsocket != -1)
|
|
||||||
return;
|
|
||||||
if ((net_acceptsocket = MPATH_OpenSocket (net_hostport)) == -1)
|
|
||||||
Sys_Error ("MPATH_Listen: Unable to open accept socket");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// disable listening
|
|
||||||
if (net_acceptsocket == -1)
|
|
||||||
return;
|
|
||||||
MPATH_CloseSocket (net_acceptsocket);
|
|
||||||
net_acceptsocket = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
int
|
|
||||||
MPATH_OpenSocket (int port)
|
|
||||||
{
|
|
||||||
int newsocket;
|
|
||||||
struct sockaddr_in address;
|
|
||||||
u_long _true = 1;
|
|
||||||
|
|
||||||
if ((newsocket = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (ioctlsocket (newsocket, FIONBIO, &_true) == -1)
|
|
||||||
goto ErrorReturn;
|
|
||||||
|
|
||||||
address.sin_family = AF_INET;
|
|
||||||
address.sin_addr.s_addr = INADDR_ANY;
|
|
||||||
address.sin_port = htons (port);
|
|
||||||
if (bind (newsocket, (void *) &address, sizeof (address)) == -1)
|
|
||||||
goto ErrorReturn;
|
|
||||||
|
|
||||||
return newsocket;
|
|
||||||
|
|
||||||
ErrorReturn:
|
|
||||||
closesocket (newsocket);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
int
|
|
||||||
MPATH_CloseSocket (int socket)
|
|
||||||
{
|
|
||||||
if (socket == net_broadcastsocket)
|
|
||||||
net_broadcastsocket = 0;
|
|
||||||
return closesocket (socket);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
/*
|
|
||||||
============
|
|
||||||
PartialIPAddress
|
|
||||||
|
|
||||||
this lets you type only as much of the net address as required, using
|
|
||||||
the local network components to fill in the rest
|
|
||||||
============
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
PartialIPAddress (char *in, struct qsockaddr *hostaddr)
|
|
||||||
{
|
|
||||||
char buff[256];
|
|
||||||
char *b;
|
|
||||||
int addr;
|
|
||||||
int num;
|
|
||||||
int mask;
|
|
||||||
int run;
|
|
||||||
int port;
|
|
||||||
|
|
||||||
buff[0] = '.';
|
|
||||||
b = buff;
|
|
||||||
strcpy (buff + 1, in);
|
|
||||||
if (buff[1] == '.')
|
|
||||||
b++;
|
|
||||||
|
|
||||||
addr = 0;
|
|
||||||
mask = -1;
|
|
||||||
while (*b == '.') {
|
|
||||||
b++;
|
|
||||||
num = 0;
|
|
||||||
run = 0;
|
|
||||||
while (!(*b < '0' || *b > '9')) {
|
|
||||||
num = num * 10 + *b++ - '0';
|
|
||||||
if (++run > 3)
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if ((*b < '0' || *b > '9') && *b != '.' && *b != ':' && *b != 0)
|
|
||||||
return -1;
|
|
||||||
if (num < 0 || num > 255)
|
|
||||||
return -1;
|
|
||||||
mask <<= 8;
|
|
||||||
addr = (addr << 8) + num;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*b++ == ':')
|
|
||||||
port = Q_atoi (b);
|
|
||||||
else
|
|
||||||
port = net_hostport;
|
|
||||||
|
|
||||||
hostaddr->sa_family = AF_INET;
|
|
||||||
((struct sockaddr_in *) hostaddr)->sin_port = htons ((short) port);
|
|
||||||
|
|
||||||
((struct sockaddr_in *) hostaddr)->sin_addr.s_addr =
|
|
||||||
(myAddr & htonl (mask)) | htonl (addr);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
int
|
|
||||||
MPATH_Connect (int socket, struct qsockaddr *addr)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
int
|
|
||||||
MPATH_CheckNewConnections (void)
|
|
||||||
{
|
|
||||||
char buf[4];
|
|
||||||
|
|
||||||
if (net_acceptsocket == -1)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (recvfrom (net_acceptsocket, buf, 4, MSG_PEEK, NULL, NULL) >= 0)
|
|
||||||
return net_acceptsocket;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
int
|
|
||||||
MPATH_Read (int socket, byte * buf, int len, struct qsockaddr *addr)
|
|
||||||
{
|
|
||||||
int addrlen = sizeof (struct qsockaddr);
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
ret = recvfrom (socket, buf, len, 0, (struct sockaddr *) addr, &addrlen);
|
|
||||||
if (ret == -1) {
|
|
||||||
int errno = WSAGetLastError ();
|
|
||||||
|
|
||||||
if (errno == WSAEWOULDBLOCK || errno == WSAECONNREFUSED)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
int
|
|
||||||
MPATH_MakeSocketBroadcastCapable (int socket)
|
|
||||||
{
|
|
||||||
int i = 1;
|
|
||||||
|
|
||||||
// make this socket broadcast capable
|
|
||||||
if (setsockopt (socket, SOL_SOCKET, SO_BROADCAST, (char *) &i, sizeof (i)) <
|
|
||||||
0) return -1;
|
|
||||||
net_broadcastsocket = socket;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
int
|
|
||||||
MPATH_Broadcast (int socket, byte * buf, int len)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
if (socket != net_broadcastsocket) {
|
|
||||||
if (net_broadcastsocket != 0)
|
|
||||||
Sys_Error ("Attempted to use multiple broadcasts sockets");
|
|
||||||
ret = MPATH_MakeSocketBroadcastCapable (socket);
|
|
||||||
if (ret == -1) {
|
|
||||||
Con_Printf ("Unable to make socket broadcast capable\n");
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return MPATH_Write (socket, buf, len, &broadcastaddr);
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
int
|
|
||||||
MPATH_Write (int socket, byte * buf, int len, struct qsockaddr *addr)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
ret =
|
|
||||||
|
|
||||||
sendto (socket, buf, len, 0, (struct sockaddr *) addr,
|
|
||||||
sizeof (struct qsockaddr));
|
|
||||||
if (ret == -1)
|
|
||||||
if (WSAGetLastError () == WSAEWOULDBLOCK)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
sockets_flush ();
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
char *
|
|
||||||
MPATH_AddrToString (struct qsockaddr *addr)
|
|
||||||
{
|
|
||||||
static char buffer[22];
|
|
||||||
int haddr;
|
|
||||||
|
|
||||||
haddr = ntohl (((struct sockaddr_in *) addr)->sin_addr.s_addr);
|
|
||||||
snprintf (buffer, sizeof (buffer), "%d.%d.%d.%d:%d", (haddr >> 24) & 0xff,
|
|
||||||
(haddr >> 16) & 0xff, (haddr >> 8) & 0xff, haddr & 0xff,
|
|
||||||
ntohs (((struct sockaddr_in *) addr)->sin_port));
|
|
||||||
return buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
int
|
|
||||||
MPATH_StringToAddr (char *string, struct qsockaddr *addr)
|
|
||||||
{
|
|
||||||
int ha1, ha2, ha3, ha4, hp;
|
|
||||||
int ipaddr;
|
|
||||||
|
|
||||||
sscanf (string, "%d.%d.%d.%d:%d", &ha1, &ha2, &ha3, &ha4, &hp);
|
|
||||||
ipaddr = (ha1 << 24) | (ha2 << 16) | (ha3 << 8) | ha4;
|
|
||||||
|
|
||||||
addr->sa_family = AF_INET;
|
|
||||||
((struct sockaddr_in *) addr)->sin_addr.s_addr = htonl (ipaddr);
|
|
||||||
((struct sockaddr_in *) addr)->sin_port = htons (hp);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
int
|
|
||||||
MPATH_GetSocketAddr (int socket, struct qsockaddr *addr)
|
|
||||||
{
|
|
||||||
int addrlen = sizeof (struct qsockaddr);
|
|
||||||
unsigned int a;
|
|
||||||
|
|
||||||
Q_memset (addr, 0, sizeof (struct qsockaddr));
|
|
||||||
|
|
||||||
getsockname (socket, (struct sockaddr *) addr, &addrlen);
|
|
||||||
a = ((struct sockaddr_in *) addr)->sin_addr.s_addr;
|
|
||||||
if (a == 0 || a == inet_addr ("127.0.0.1"))
|
|
||||||
((struct sockaddr_in *) addr)->sin_addr.s_addr = myAddr;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
int
|
|
||||||
MPATH_GetNameFromAddr (struct qsockaddr *addr, char *name)
|
|
||||||
{
|
|
||||||
struct hostent *hostentry;
|
|
||||||
|
|
||||||
hostentry =
|
|
||||||
gethostbyaddr ((char *) &((struct sockaddr_in *) addr)->sin_addr,
|
|
||||||
sizeof (struct in_addr), AF_INET);
|
|
||||||
|
|
||||||
if (hostentry) {
|
|
||||||
Q_strncpy (name, (char *) hostentry->h_name, NET_NAMELEN - 1);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
Q_strcpy (name, MPATH_AddrToString (addr));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
int
|
|
||||||
MPATH_GetAddrFromName (char *name, struct qsockaddr *addr)
|
|
||||||
{
|
|
||||||
struct hostent *hostentry;
|
|
||||||
|
|
||||||
if (name[0] >= '0' && name[0] <= '9')
|
|
||||||
return PartialIPAddress (name, addr);
|
|
||||||
|
|
||||||
hostentry = gethostbyname (name);
|
|
||||||
if (!hostentry)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
addr->sa_family = AF_INET;
|
|
||||||
((struct sockaddr_in *) addr)->sin_port = htons (net_hostport);
|
|
||||||
|
|
||||||
((struct sockaddr_in *) addr)->sin_addr.s_addr =
|
|
||||||
*(int *) hostentry->h_addr_list[0];
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
int
|
|
||||||
MPATH_AddrCompare (struct qsockaddr *addr1, struct qsockaddr *addr2)
|
|
||||||
{
|
|
||||||
if (addr1->sa_family != addr2->sa_family)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (((struct sockaddr_in *) addr1)->sin_addr.s_addr !=
|
|
||||||
((struct sockaddr_in *) addr2)->sin_addr.s_addr)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (((struct sockaddr_in *) addr1)->sin_port !=
|
|
||||||
((struct sockaddr_in *) addr2)->sin_port)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
int
|
|
||||||
MPATH_GetSocketPort (struct qsockaddr *addr)
|
|
||||||
{
|
|
||||||
return ntohs (((struct sockaddr_in *) addr)->sin_port);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
MPATH_SetSocketPort (struct qsockaddr *addr, int port)
|
|
||||||
{
|
|
||||||
((struct sockaddr_in *) addr)->sin_port = htons (port);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
|
@ -1,56 +0,0 @@
|
||||||
/*
|
|
||||||
net_none.c
|
|
||||||
|
|
||||||
@description@
|
|
||||||
|
|
||||||
Copyright (C) 1996-1997 Id Software, Inc.
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU General Public License
|
|
||||||
as published by the Free Software Foundation; either version 2
|
|
||||||
of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
||||||
|
|
||||||
See the GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program; if not, write to:
|
|
||||||
|
|
||||||
Free Software Foundation, Inc.
|
|
||||||
59 Temple Place - Suite 330
|
|
||||||
Boston, MA 02111-1307, USA
|
|
||||||
|
|
||||||
*/
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
# include "config.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static __attribute__ ((unused)) const char rcsid[] =
|
|
||||||
"$Id$";
|
|
||||||
|
|
||||||
#include "net_loop.h"
|
|
||||||
|
|
||||||
net_driver_t net_drivers[MAX_NET_DRIVERS] = {
|
|
||||||
{
|
|
||||||
"Loopback",
|
|
||||||
false,
|
|
||||||
Loop_Init,
|
|
||||||
Loop_Listen,
|
|
||||||
Loop_SearchForHosts,
|
|
||||||
Loop_Connect,
|
|
||||||
Loop_CheckNewConnections,
|
|
||||||
Loop_GetMessage,
|
|
||||||
Loop_SendMessage,
|
|
||||||
Loop_SendUnreliableMessage,
|
|
||||||
Loop_CanSendMessage,
|
|
||||||
Loop_CanSendUnreliableMessage,
|
|
||||||
Loop_Close,
|
|
||||||
Loop_Shutdown}
|
|
||||||
};
|
|
||||||
int net_numdrivers = 1;
|
|
||||||
|
|
||||||
net_landriver_t net_landrivers[MAX_NET_DRIVERS];
|
|
||||||
int net_numlandrivers = 0;
|
|
|
@ -1,471 +0,0 @@
|
||||||
/*
|
|
||||||
net_wipx.c
|
|
||||||
|
|
||||||
@description@
|
|
||||||
|
|
||||||
Copyright (C) 1996-1997 Id Software, Inc.
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU General Public License
|
|
||||||
as published by the Free Software Foundation; either version 2
|
|
||||||
of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
||||||
|
|
||||||
See the GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program; if not, write to:
|
|
||||||
|
|
||||||
Free Software Foundation, Inc.
|
|
||||||
59 Temple Place - Suite 330
|
|
||||||
Boston, MA 02111-1307, USA
|
|
||||||
|
|
||||||
*/
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
# include "config.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static __attribute__ ((unused)) const char rcsid[] =
|
|
||||||
"$Id$";
|
|
||||||
|
|
||||||
#include "winquake.h"
|
|
||||||
#include <wsipx.h>
|
|
||||||
|
|
||||||
#include "QF/console.h"
|
|
||||||
#include "QF/cvar.h"
|
|
||||||
#include "QF/qargs.h"
|
|
||||||
#include "QF/sys.h"
|
|
||||||
|
|
||||||
#include "game.h"
|
|
||||||
#include "net_wins.h"
|
|
||||||
#include "net_wipx.h"
|
|
||||||
|
|
||||||
#define MAXHOSTNAMELEN 256
|
|
||||||
|
|
||||||
static int net_acceptsocket = -1; // socket for fielding new
|
|
||||||
|
|
||||||
// connections
|
|
||||||
static int net_controlsocket;
|
|
||||||
static struct qsockaddr broadcastaddr;
|
|
||||||
|
|
||||||
|
|
||||||
#define IPXSOCKETS 18
|
|
||||||
static int ipxsocket[IPXSOCKETS];
|
|
||||||
static int sequence[IPXSOCKETS];
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
int
|
|
||||||
WIPX_Init (void)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
char buff[MAXHOSTNAMELEN];
|
|
||||||
struct qsockaddr addr;
|
|
||||||
char *p;
|
|
||||||
int r;
|
|
||||||
WORD wVersionRequested;
|
|
||||||
|
|
||||||
if (COM_CheckParm ("-noipx"))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
// make sure LoadLibrary has happened successfully
|
|
||||||
if (!winsock_lib_initialized)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (winsock_initialized == 0) {
|
|
||||||
wVersionRequested = MAKEWORD (1, 1);
|
|
||||||
|
|
||||||
r = pWSAStartup (MAKEWORD (1, 1), &winsockdata);
|
|
||||||
|
|
||||||
if (r) {
|
|
||||||
Con_Printf ("Winsock initialization failed.\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
winsock_initialized++;
|
|
||||||
|
|
||||||
for (i = 0; i < IPXSOCKETS; i++)
|
|
||||||
ipxsocket[i] = 0;
|
|
||||||
|
|
||||||
// determine my name & address
|
|
||||||
if (pgethostname (buff, MAXHOSTNAMELEN) == 0) {
|
|
||||||
// if the quake hostname isn't set, set it to the machine name
|
|
||||||
if (strcmp (hostname->string, "UNNAMED") == 0) {
|
|
||||||
// see if it's a text IP address (well, close enough)
|
|
||||||
for (p = buff; *p; p++)
|
|
||||||
if ((*p < '0' || *p > '9') && *p != '.')
|
|
||||||
break;
|
|
||||||
|
|
||||||
// if it is a real name, strip off the domain; we only want the
|
|
||||||
// host
|
|
||||||
if (*p) {
|
|
||||||
for (i = 0; i < 15; i++)
|
|
||||||
if (buff[i] == '.')
|
|
||||||
break;
|
|
||||||
buff[i] = 0;
|
|
||||||
}
|
|
||||||
Cvar_Set (hostname, buff);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((net_controlsocket = WIPX_OpenSocket (0)) == -1) {
|
|
||||||
Con_Printf ("WIPX_Init: Unable to open control socket\n");
|
|
||||||
if (--winsock_initialized == 0)
|
|
||||||
pWSACleanup ();
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
((struct sockaddr_ipx *) &broadcastaddr)->sa_family = AF_IPX;
|
|
||||||
memset (((struct sockaddr_ipx *) &broadcastaddr)->sa_netnum, 0, 4);
|
|
||||||
memset (((struct sockaddr_ipx *) &broadcastaddr)->sa_nodenum, 0xff, 6);
|
|
||||||
|
|
||||||
((struct sockaddr_ipx *) &broadcastaddr)->sa_socket =
|
|
||||||
htons ((unsigned short) net_hostport);
|
|
||||||
|
|
||||||
WIPX_GetSocketAddr (net_controlsocket, &addr);
|
|
||||||
strcpy (my_ipx_address, WIPX_AddrToString (&addr));
|
|
||||||
p = strrchr (my_ipx_address, ':');
|
|
||||||
if (p)
|
|
||||||
*p = 0;
|
|
||||||
|
|
||||||
Con_Printf ("Winsock IPX Initialized\n");
|
|
||||||
ipxAvailable = true;
|
|
||||||
|
|
||||||
return net_controlsocket;
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
void
|
|
||||||
WIPX_Shutdown (void)
|
|
||||||
{
|
|
||||||
WIPX_Listen (false);
|
|
||||||
WIPX_CloseSocket (net_controlsocket);
|
|
||||||
if (--winsock_initialized == 0)
|
|
||||||
pWSACleanup ();
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
void
|
|
||||||
WIPX_Listen (qboolean state)
|
|
||||||
{
|
|
||||||
// enable listening
|
|
||||||
if (state) {
|
|
||||||
if (net_acceptsocket != -1)
|
|
||||||
return;
|
|
||||||
if ((net_acceptsocket = WIPX_OpenSocket (net_hostport)) == -1)
|
|
||||||
Sys_Error ("WIPX_Listen: Unable to open accept socket");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// disable listening
|
|
||||||
if (net_acceptsocket == -1)
|
|
||||||
return;
|
|
||||||
WIPX_CloseSocket (net_acceptsocket);
|
|
||||||
net_acceptsocket = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
int
|
|
||||||
WIPX_OpenSocket (int port)
|
|
||||||
{
|
|
||||||
int handle;
|
|
||||||
int newsocket;
|
|
||||||
struct sockaddr_ipx address;
|
|
||||||
u_long _true = 1;
|
|
||||||
|
|
||||||
for (handle = 0; handle < IPXSOCKETS; handle++)
|
|
||||||
if (ipxsocket[handle] == 0)
|
|
||||||
break;
|
|
||||||
if (handle == IPXSOCKETS)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if ((newsocket = psocket (AF_IPX, SOCK_DGRAM, NSPROTO_IPX)) ==
|
|
||||||
INVALID_SOCKET) return -1;
|
|
||||||
|
|
||||||
if (pioctlsocket (newsocket, FIONBIO, &_true) == -1)
|
|
||||||
goto ErrorReturn;
|
|
||||||
|
|
||||||
if (psetsockopt
|
|
||||||
(newsocket, SOL_SOCKET, SO_BROADCAST, (char *) &_true,
|
|
||||||
sizeof (_true)) < 0) goto ErrorReturn;
|
|
||||||
|
|
||||||
address.sa_family = AF_IPX;
|
|
||||||
memset (address.sa_netnum, 0, 4);
|
|
||||||
memset (address.sa_nodenum, 0, 6);
|
|
||||||
address.sa_socket = htons ((unsigned short) port);
|
|
||||||
if (bind (newsocket, (void *) &address, sizeof (address)) == 0) {
|
|
||||||
ipxsocket[handle] = newsocket;
|
|
||||||
sequence[handle] = 0;
|
|
||||||
return handle;
|
|
||||||
}
|
|
||||||
|
|
||||||
Sys_Error ("Winsock IPX bind failed");
|
|
||||||
ErrorReturn:
|
|
||||||
pclosesocket (newsocket);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
int
|
|
||||||
WIPX_CloseSocket (int handle)
|
|
||||||
{
|
|
||||||
int socket = ipxsocket[handle];
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
ret = pclosesocket (socket);
|
|
||||||
ipxsocket[handle] = 0;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
int
|
|
||||||
WIPX_Connect (int handle, struct qsockaddr *addr)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
int
|
|
||||||
WIPX_CheckNewConnections (void)
|
|
||||||
{
|
|
||||||
unsigned long available;
|
|
||||||
|
|
||||||
if (net_acceptsocket == -1)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (pioctlsocket (ipxsocket[net_acceptsocket], FIONREAD, &available) == -1)
|
|
||||||
Sys_Error ("WIPX: ioctlsocket (FIONREAD) failed");
|
|
||||||
if (available)
|
|
||||||
return net_acceptsocket;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
static byte packetBuffer[NET_DATAGRAMSIZE + 4];
|
|
||||||
|
|
||||||
int
|
|
||||||
WIPX_Read (int handle, byte * buf, int len, struct qsockaddr *addr)
|
|
||||||
{
|
|
||||||
int addrlen = sizeof (struct qsockaddr);
|
|
||||||
int socket = ipxsocket[handle];
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
ret =
|
|
||||||
precvfrom (socket, packetBuffer, len + 4, 0, (struct sockaddr *) addr,
|
|
||||||
&addrlen);
|
|
||||||
if (ret == -1) {
|
|
||||||
int errno = pWSAGetLastError ();
|
|
||||||
|
|
||||||
if (errno == WSAEWOULDBLOCK || errno == WSAECONNREFUSED)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ret < 4)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
// remove sequence number, it's only needed for DOS IPX
|
|
||||||
ret -= 4;
|
|
||||||
memcpy (buf, packetBuffer + 4, ret);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
int
|
|
||||||
WIPX_Broadcast (int handle, byte * buf, int len)
|
|
||||||
{
|
|
||||||
return WIPX_Write (handle, buf, len, &broadcastaddr);
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
int
|
|
||||||
WIPX_Write (int handle, byte * buf, int len, struct qsockaddr *addr)
|
|
||||||
{
|
|
||||||
int socket = ipxsocket[handle];
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
// build packet with sequence number
|
|
||||||
*(int *) (&packetBuffer[0]) = sequence[handle];
|
|
||||||
sequence[handle]++;
|
|
||||||
memcpy (&packetBuffer[4], buf, len);
|
|
||||||
len += 4;
|
|
||||||
|
|
||||||
ret =
|
|
||||||
psendto (socket, packetBuffer, len, 0, (struct sockaddr *) addr,
|
|
||||||
|
|
||||||
sizeof (struct qsockaddr));
|
|
||||||
if (ret == -1)
|
|
||||||
if (pWSAGetLastError () == WSAEWOULDBLOCK)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
char *
|
|
||||||
WIPX_AddrToString (struct qsockaddr *addr)
|
|
||||||
{
|
|
||||||
static char buf[28];
|
|
||||||
|
|
||||||
snprintf (buf, sizeof (buf), "%02x%02x%02x%02x:%02x%02x%02x%02x%02x%02x:%u",
|
|
||||||
((struct sockaddr_ipx *) addr)->sa_netnum[0] & 0xff,
|
|
||||||
((struct sockaddr_ipx *) addr)->sa_netnum[1] & 0xff,
|
|
||||||
((struct sockaddr_ipx *) addr)->sa_netnum[2] & 0xff,
|
|
||||||
((struct sockaddr_ipx *) addr)->sa_netnum[3] & 0xff,
|
|
||||||
((struct sockaddr_ipx *) addr)->sa_nodenum[0] & 0xff,
|
|
||||||
((struct sockaddr_ipx *) addr)->sa_nodenum[1] & 0xff,
|
|
||||||
((struct sockaddr_ipx *) addr)->sa_nodenum[2] & 0xff,
|
|
||||||
((struct sockaddr_ipx *) addr)->sa_nodenum[3] & 0xff,
|
|
||||||
((struct sockaddr_ipx *) addr)->sa_nodenum[4] & 0xff,
|
|
||||||
((struct sockaddr_ipx *) addr)->sa_nodenum[5] & 0xff,
|
|
||||||
ntohs (((struct sockaddr_ipx *) addr)->sa_socket)
|
|
||||||
);
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
int
|
|
||||||
WIPX_StringToAddr (char *string, struct qsockaddr *addr)
|
|
||||||
{
|
|
||||||
int val;
|
|
||||||
char buf[3];
|
|
||||||
|
|
||||||
buf[2] = 0;
|
|
||||||
memset (addr, 0, sizeof (struct qsockaddr));
|
|
||||||
|
|
||||||
addr->sa_family = AF_IPX;
|
|
||||||
|
|
||||||
#define DO(src,dest) \
|
|
||||||
buf[0] = string[src]; \
|
|
||||||
buf[1] = string[src + 1]; \
|
|
||||||
if (sscanf (buf, "%x", &val) != 1) \
|
|
||||||
return -1; \
|
|
||||||
((struct sockaddr_ipx *)addr)->dest = val
|
|
||||||
|
|
||||||
DO (0, sa_netnum[0]);
|
|
||||||
DO (2, sa_netnum[1]);
|
|
||||||
DO (4, sa_netnum[2]);
|
|
||||||
DO (6, sa_netnum[3]);
|
|
||||||
DO (9, sa_nodenum[0]);
|
|
||||||
DO (11, sa_nodenum[1]);
|
|
||||||
DO (13, sa_nodenum[2]);
|
|
||||||
DO (15, sa_nodenum[3]);
|
|
||||||
DO (17, sa_nodenum[4]);
|
|
||||||
DO (19, sa_nodenum[5]);
|
|
||||||
#undef DO
|
|
||||||
|
|
||||||
sscanf (&string[22], "%u", &val);
|
|
||||||
((struct sockaddr_ipx *) addr)->sa_socket = htons ((unsigned short) val);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
int
|
|
||||||
WIPX_GetSocketAddr (int handle, struct qsockaddr *addr)
|
|
||||||
{
|
|
||||||
int socket = ipxsocket[handle];
|
|
||||||
int addrlen = sizeof (struct qsockaddr);
|
|
||||||
unsigned int a;
|
|
||||||
|
|
||||||
memset (addr, 0, sizeof (struct qsockaddr));
|
|
||||||
|
|
||||||
if (pgetsockname (socket, (struct sockaddr *) addr, &addrlen) != 0) {
|
|
||||||
int errno = pWSAGetLastError ();
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
int
|
|
||||||
WIPX_GetNameFromAddr (struct qsockaddr *addr, char *name)
|
|
||||||
{
|
|
||||||
strcpy (name, WIPX_AddrToString (addr));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
int
|
|
||||||
WIPX_GetAddrFromName (char *name, struct qsockaddr *addr)
|
|
||||||
{
|
|
||||||
int n;
|
|
||||||
char buf[32];
|
|
||||||
|
|
||||||
n = strlen (name);
|
|
||||||
|
|
||||||
if (n == 12) {
|
|
||||||
snprintf (buf, sizeof (buf), "00000000:%s:%u", name, net_hostport);
|
|
||||||
return WIPX_StringToAddr (buf, addr);
|
|
||||||
}
|
|
||||||
if (n == 21) {
|
|
||||||
snprintf (buf, sizeof (buf), "%s:%u", name, net_hostport);
|
|
||||||
return WIPX_StringToAddr (buf, addr);
|
|
||||||
}
|
|
||||||
if (n > 21 && n <= 27)
|
|
||||||
return WIPX_StringToAddr (name, addr);
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
int
|
|
||||||
WIPX_AddrCompare (struct qsockaddr *addr1, struct qsockaddr *addr2)
|
|
||||||
{
|
|
||||||
if (addr1->sa_family != addr2->sa_family)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (*((struct sockaddr_ipx *) addr1)->sa_netnum
|
|
||||||
&& *((struct sockaddr_ipx *) addr2)->sa_netnum)
|
|
||||||
if (memcmp
|
|
||||||
(((struct sockaddr_ipx *) addr1)->sa_netnum,
|
|
||||||
((struct sockaddr_ipx *) addr2)->sa_netnum, 4) != 0)
|
|
||||||
return -1;
|
|
||||||
if (memcmp
|
|
||||||
(((struct sockaddr_ipx *) addr1)->sa_nodenum,
|
|
||||||
((struct sockaddr_ipx *) addr2)->sa_nodenum, 6) != 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (((struct sockaddr_ipx *) addr1)->sa_socket !=
|
|
||||||
((struct sockaddr_ipx *) addr2)->sa_socket)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
int
|
|
||||||
WIPX_GetSocketPort (struct qsockaddr *addr)
|
|
||||||
{
|
|
||||||
return ntohs (((struct sockaddr_ipx *) addr)->sa_socket);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
WIPX_SetSocketPort (struct qsockaddr *addr, int port)
|
|
||||||
{
|
|
||||||
((struct sockaddr_ipx *) addr)->sa_socket = htons ((unsigned short) port);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
Loading…
Reference in a new issue