1
0
Fork 0

Added initial IPX support

Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@1668
This commit is contained in:
Dean Beeler 2004-02-08 08:36:32 +00:00
parent 8dda3577a9
commit 7ee4be6fd8
5 changed files with 1580 additions and 5 deletions

91
include/ipx.h Normal file
View file

@ -0,0 +1,91 @@
/*
* Copyright (C) 2002 The DOSBox Team
*
* 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 Library 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 the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _IPX_H_
#define _IPX_H_
// In Use Flag codes
#define USEFLAG_AVAILABLE 0x00
#define USEFLAG_AESTEMP 0xe0
#define USEFLAG_IPXCRIT 0xf8
#define USEFLAG_SPXLISTEN 0xf9
#define USEFLAG_PROCESSING 0xfa
#define USEFLAG_HOLDING 0xfb
#define USEFLAG_AESWAITING 0xfc
#define USEFLAG_AESCOUNT 0xfd
#define USEFLAG_LISTENING 0xfe
#define USEFLAG_SENDING 0xff
// Completion codes
#define COMP_SUCCESS 0x00
#define COMP_REMOTETERM 0xec
#define COMP_DISCONNECT 0xed
#define COMP_INVALIDID 0xee
#define COMP_SPXTABLEFULL 0xef
#define COMP_EVENTNOTCANCELED 0xf9
#define COMP_NOCONNECTION 0xfa
#define COMP_CANCELLED 0xfc
#define COMP_MALFORMED 0xfd
#define COMP_UNDELIVERABLE 0xfe
#define COMP_HARDWAREERROR 0xff
#ifdef _MSC_VER
#pragma pack(1)
#endif
// For Uint8 type
#include "SDL_net.h"
struct PackedIP {
Uint32 host;
Uint16 port;
} GCC_ATTRIBUTE(packed);
struct nodeType {
Uint8 node[6];
}GCC_ATTRIBUTE(packed) ;
struct IPXHeader {
Uint8 checkSum[2];
Uint8 length[2];
Uint8 transControl; // Transport control
Uint8 pType; // Packet type
struct transport {
Uint8 network[4];
union addrtype {
nodeType byNode;
PackedIP byIP ;
} GCC_ATTRIBUTE(packed) addr;
Uint8 socket[2];
} dest, src;
} GCC_ATTRIBUTE(packed);
// The following routines may not be needed on all systems. On my build of SDL the IPaddress structure is 8 octects
// and therefore screws up my IPXheader structure since it needs to be packed.
void UnpackIP(PackedIP ipPack, IPaddress * ipAddr);
void PackIP(IPaddress ipAddr, PackedIP *ipPack);
#ifdef _MSC_VER
#pragma pack()
#endif
#endif

49
include/ipxserver.h Normal file
View file

@ -0,0 +1,49 @@
/*
* Copyright (C) 2002 The DOSBox Team
*
* 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 Library 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 the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _IPXSERVER_H_
#define _IPXSERVER_H_
#if C_IPX
#include "SDL_net.h"
struct packetBuffer {
Bit8u buffer[1024];
Bit16s packetSize; // Packet size remaining in read
Bit16s packetRead; // Bytes read of total packet
bool inPacket; // In packet reception flag
bool connected; // Connected flag
bool waitsize;
};
#define SOCKETTABLESIZE 16
#define IPXBUFFERSIZE 1024
#define CONVIP(hostvar) hostvar & 0xff, (hostvar >> 8) & 0xff, (hostvar >> 16) & 0xff, (hostvar >> 24) & 0xff
#define CONVIPX(hostvar) hostvar[0], hostvar[1], hostvar[2], hostvar[3], hostvar[4], hostvar[5]
void IPX_StopServer();
bool IPX_StartServer(Bit16u portnum);
bool IPX_isConnectedToServer(Bits tableNum, IPaddress ** ptrAddr);
Bit8u packetCRC(Bit8u *buffer, Bit16u bufSize);
#endif
#endif

View file

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* $Id: dosbox.cpp,v 1.61 2004-02-02 15:42:38 harekiet Exp $ */
/* $Id: dosbox.cpp,v 1.62 2004-02-08 08:35:59 canadacow Exp $ */
#include <stdlib.h>
#include <stdarg.h>
@ -80,6 +80,7 @@ void CMS_Init(Section*);
void DISNEY_Init(Section*);
void SERIAL_Init(Section*);
void MODEM_Init(Section*);
void IPX_Init(Section*);
void PIC_Init(Section*);
void TIMER_Init(Section*);
@ -101,6 +102,8 @@ void INT10_Init(Section*);
static LoopHandler * loop;
bool SDLNetInited;
Bits RemainTicks;;
Bits LastTicks;
@ -183,10 +186,12 @@ void DOSBOX_Init(void) {
Section_prop * secprop;
Section_line * secline;
SDLNetInited = false;
/* Setup all the different modules making up DOSBox */
secprop=control->AddSection_prop("dosbox",&DOSBOX_RealInit);
secprop->Add_string("language","");
secprop->Add_string("language","");
secprop->Add_string("machine","auto");
#if C_DEBUG
@ -251,7 +256,7 @@ void DOSBOX_Init(void) {
secprop=control->AddSection_prop("mixer",&MIXER_Init);
secprop->Add_bool("nosound",false);
secprop->Add_int("rate",22050);
secprop->Add_int("rate",32000);
secprop->Add_int("blocksize",2048);
secprop->Add_string("wavedir","waves");
@ -310,7 +315,7 @@ void DOSBOX_Init(void) {
secprop=control->AddSection_prop("gus",&GUS_Init);
secprop->Add_bool("gus",true);
secprop->Add_int("rate",22050);
secprop->Add_hex("base",0x240);
secprop->Add_hex("base",0x240);
secprop->Add_int("irq1",5);
secprop->Add_int("irq2",5);
secprop->Add_int("dma1",3);
@ -337,7 +342,7 @@ void DOSBOX_Init(void) {
secprop->AddInitFunction(&DISNEY_Init);
secprop->Add_bool("disney",true);
MSG_Add("SPEAKER_CONFIGFILE_HELP",
MSG_Add("SPEAKER_CONFIGFILE_HELP",
"pcspeaker -- Enable PC-Speaker emulation.\n"
"pcrate -- Sample rate of the PC-Speaker sound generation.\n"
"tandy -- Enable Tandy 3-Voice emulation.\n"
@ -383,6 +388,14 @@ void DOSBOX_Init(void) {
);
#endif
#if C_IPX
secprop=control->AddSection_prop("ipx",&IPX_Init);
secprop->Add_bool("ipx", true);
MSG_Add("IPX_CONFIGFILE_HELP",
"ipx -- Enable ipx over UDP/IP emulation.\n"
);
#endif
secline=control->AddSection_line("autoexec",&AUTOEXEC_Init);

1187
src/hardware/ipx.cpp Normal file

File diff suppressed because it is too large Load diff

235
src/hardware/ipxserver.cpp Normal file
View file

@ -0,0 +1,235 @@
/*
* Copyright (C) 2002 The DOSBox Team
*
* 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 Library 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 the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "dosbox.h"
#if C_IPX
#include "dosbox.h"
#include "ipxserver.h"
#include "timer.h"
#include <stdlib.h>
#include <string.h>
#include "ipx.h"
IPaddress ipxServerIp; // IPAddress for server's listening port
UDPsocket ipxServerSocket; // Listening server socket
packetBuffer connBuffer[SOCKETTABLESIZE];
Bit8u inBuffer[IPXBUFFERSIZE];
IPaddress ipconn[SOCKETTABLESIZE]; // Active TCP/IP connection
UDPsocket tcpconn[SOCKETTABLESIZE]; // Active TCP/IP connections
SDLNet_SocketSet serverSocketSet;
TIMER_TickHandler* serverTimer;
Bit8u packetCRC(Bit8u *buffer, Bit16u bufSize) {
Bit8u tmpCRC = 0;
Bit16u i;
for(i=0;i<bufSize;i++) {
tmpCRC ^= *buffer;
buffer++;
}
return tmpCRC;
}
/*
static void closeSocket(Bit16u sockidx) {
Bit32u host;
host = ipconn[sockidx].host;
LOG_MSG("IPXSERVER: %d.%d.%d.%d disconnected", CONVIP(host));
SDLNet_TCP_DelSocket(serverSocketSet,tcpconn[sockidx]);
SDLNet_TCP_Close(tcpconn[sockidx]);
connBuffer[sockidx].connected = false;
connBuffer[sockidx].waitsize = false;
}
*/
static void sendIPXPacket(Bit8u *buffer, Bit16s bufSize) {
Bit16u srcport, destport;
Bit32u srchost, desthost;
Bit16u i;
Bits result;
UDPpacket outPacket;
outPacket.channel = -1;
outPacket.data = buffer;
outPacket.len = bufSize;
outPacket.maxlen = bufSize;
IPXHeader *tmpHeader;
tmpHeader = (IPXHeader *)buffer;
srchost = tmpHeader->src.addr.byIP.host;
desthost = tmpHeader->dest.addr.byIP.host;
srcport = tmpHeader->src.addr.byIP.port;
destport = tmpHeader->dest.addr.byIP.port;
if(desthost == 0xffffffff) {
// Broadcast
for(i=0;i<SOCKETTABLESIZE;i++) {
if((connBuffer[i].connected) /* && (ipconn[i].host != srchost) */) {
outPacket.address = ipconn[i];
result = SDLNet_UDP_Send(ipxServerSocket,-1,&outPacket);
if(result == 0) {
LOG_MSG("IPXSERVER: %s", SDLNet_GetError());
continue;
}
//LOG_MSG("IPXSERVER: Packet of %d bytes sent from %d.%d.%d.%d to %d.%d.%d.%d (BROADCAST) (%x CRC)", bufSize, CONVIP(srchost), CONVIP(ipconn[i].host), packetCRC(&buffer[30], bufSize-30));
}
}
} else {
// Specific address
for(i=0;i<SOCKETTABLESIZE;i++) {
if((connBuffer[i].connected) && (ipconn[i].host == desthost) && (ipconn[i].port == destport)) {
outPacket.address = ipconn[i];
result = SDLNet_UDP_Send(ipxServerSocket,-1,&outPacket);
if(result == 0) {
LOG_MSG("IPXSERVER: %s", SDLNet_GetError());
continue;
}
//LOG_MSG("IPXSERVER: Packet sent from %d.%d.%d.%d to %d.%d.%d.%d", CONVIP(srchost), CONVIP(desthost));
}
}
}
}
bool IPX_isConnectedToServer(Bits tableNum, IPaddress ** ptrAddr) {
if(tableNum >= SOCKETTABLESIZE) return false;
*ptrAddr = &ipconn[tableNum];
return connBuffer[tableNum].connected;
}
static void ackClient(IPaddress clientAddr) {
IPXHeader regHeader;
UDPpacket regPacket;
Bits result;
SDLNet_Write16(0xffff, regHeader.checkSum);
SDLNet_Write16(sizeof(regHeader), regHeader.length);
SDLNet_Write32(0, regHeader.dest.network);
PackIP(clientAddr, &regHeader.dest.addr.byIP);
SDLNet_Write16(0x2, regHeader.dest.socket);
SDLNet_Write32(0, regHeader.src.network);
PackIP(ipxServerIp, &regHeader.src.addr.byIP);
SDLNet_Write16(0x2, regHeader.src.socket);
regHeader.transControl = 0;
regPacket.data = (Uint8 *)&regHeader;
regPacket.len = sizeof(regHeader);
regPacket.maxlen = sizeof(regHeader);
regPacket.address = clientAddr;
// Send registration string to client. If client doesn't get this, client will not be registered
result = SDLNet_UDP_Send(ipxServerSocket,-1,&regPacket);
}
static void IPX_ServerLoop() {
UDPpacket inPacket;
IPaddress tmpAddr;
//char regString[] = "IPX Register\0";
Bit16u i;
Bit32u host;
Bits result;
inPacket.channel = -1;
inPacket.data = &inBuffer[0];
inPacket.maxlen = IPXBUFFERSIZE;
result = SDLNet_UDP_Recv(ipxServerSocket, &inPacket);
if (result != 0) {
// Check to see if incoming packet is a registration packet
// For this, I just spoofed the echo protocol packet designation 0x02
IPXHeader *tmpHeader;
tmpHeader = (IPXHeader *)&inBuffer[0];
// Check to see if echo packet
if(SDLNet_Read16(tmpHeader->dest.socket) == 0x2) {
// Null destination node means its a server registration packet
if(tmpHeader->dest.addr.byIP.host == 0x0) {
UnpackIP(tmpHeader->src.addr.byIP, &tmpAddr);
for(i=0;i<SOCKETTABLESIZE;i++) {
if(!connBuffer[i].connected) {
// Use prefered host IP rather than the reported source IP
// It may be better to use the reported source
ipconn[i] = inPacket.address;
connBuffer[i].connected = true;
host = ipconn[i].host;
LOG_MSG("IPXSERVER: Connect from %d.%d.%d.%d", CONVIP(host));
ackClient(inPacket.address);
return;
} else {
if((ipconn[i].host == tmpAddr.host) && (ipconn[i].port == tmpAddr.port)) {
LOG_MSG("IPXSERVER: Reconnect from %d.%d.%d.%d", CONVIP(tmpAddr.host));
// Update anonymous port number if changed
ipconn[i].port = inPacket.address.port;
ackClient(inPacket.address);
return;
}
}
}
}
}
// IPX packet is complete. Now interpret IPX header and send to respective IP address
sendIPXPacket((Bit8u *)inPacket.data, inPacket.len);
}
}
void IPX_StopServer() {
TIMER_DelTickHandler(&IPX_ServerLoop);
SDLNet_UDP_Close(ipxServerSocket);
}
bool IPX_StartServer(Bit16u portnum) {
Bit16u i;
if(!SDLNet_ResolveHost(&ipxServerIp, NULL, portnum)) {
//serverSocketSet = SDLNet_AllocSocketSet(SOCKETTABLESIZE);
ipxServerSocket = SDLNet_UDP_Open(portnum);
if(!ipxServerSocket) return false;
for(i=0;i<SOCKETTABLESIZE;i++) connBuffer[i].connected = false;
TIMER_AddTickHandler(&IPX_ServerLoop);
return true;
}
return false;
}
#endif