Added initial IPX support
Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@1668
This commit is contained in:
parent
8dda3577a9
commit
7ee4be6fd8
5 changed files with 1580 additions and 5 deletions
91
include/ipx.h
Normal file
91
include/ipx.h
Normal 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
49
include/ipxserver.h
Normal 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
|
|
@ -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
1187
src/hardware/ipx.cpp
Normal file
File diff suppressed because it is too large
Load diff
235
src/hardware/ipxserver.cpp
Normal file
235
src/hardware/ipxserver.cpp
Normal 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, ®Header.dest.addr.byIP);
|
||||
SDLNet_Write16(0x2, regHeader.dest.socket);
|
||||
|
||||
SDLNet_Write32(0, regHeader.src.network);
|
||||
PackIP(ipxServerIp, ®Header.src.addr.byIP);
|
||||
SDLNet_Write16(0x2, regHeader.src.socket);
|
||||
regHeader.transControl = 0;
|
||||
|
||||
regPacket.data = (Uint8 *)®Header;
|
||||
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,®Packet);
|
||||
|
||||
}
|
||||
|
||||
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
|
Loading…
Add table
Reference in a new issue