Fixed modem to work with the Telnet protocol. Integrated fizzban's code to dial a striing of numbers as an IP. This release should work with Xmodem and Ymodem protocols.
Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@1669
This commit is contained in:
parent
7ee4be6fd8
commit
ddba2a34fe
2 changed files with 177 additions and 6 deletions
|
@ -231,7 +231,7 @@ skipreset:
|
|||
break;
|
||||
case 0xE: // modem status register
|
||||
lowerint(INT_MS);
|
||||
LOG_UART("Read from %X %X",port,outval);
|
||||
// LOG_UART("Read from %X %X",port,outval);
|
||||
outval=mstatus;
|
||||
mstatus&=0xf0;
|
||||
return outval;
|
||||
|
@ -279,7 +279,7 @@ Bitu CSerial::rx_size() {
|
|||
}
|
||||
|
||||
void CSerial::rx_addb(Bit8u data) {
|
||||
LOG_UART("RX add %c",data);
|
||||
// LOG_UART("RX add %c",data);
|
||||
if (rx_fifo.used<FIFO_SIZE) {
|
||||
Bitu where=rx_fifo.pos+rx_fifo.used;
|
||||
if (where>=FIFO_SIZE) where-=FIFO_SIZE;
|
||||
|
@ -306,7 +306,7 @@ void CSerial::rx_adds(Bit8u * data,Bitu size) {
|
|||
}
|
||||
|
||||
void CSerial::tx_addb(Bit8u data) {
|
||||
LOG_UART("TX add %c",data);
|
||||
// LOG_UART("TX add %c",data);
|
||||
if (tx_fifo.used<FIFO_SIZE) {
|
||||
Bitu where=tx_fifo.pos+tx_fifo.used;
|
||||
if (where>=FIFO_SIZE) where-=FIFO_SIZE;
|
||||
|
|
|
@ -60,12 +60,12 @@ struct ModemHd {
|
|||
bool incomingcall;
|
||||
bool autoanswer;
|
||||
bool echo;
|
||||
bool telnetmode;
|
||||
Bitu cmdpause;
|
||||
Bits ringcounter;
|
||||
Bit16u plusinc;
|
||||
Bit16u cmdpos;
|
||||
|
||||
|
||||
TCPsocket socket;
|
||||
TCPsocket listensocket;
|
||||
SDLNet_SocketSet socketset;
|
||||
|
@ -85,8 +85,25 @@ struct ModemHd {
|
|||
MIXER_Channel * chan;
|
||||
};
|
||||
|
||||
#define TEL_CLIENT 0
|
||||
#define TEL_SERVER 1
|
||||
|
||||
struct telnetClient {
|
||||
bool binary[2];
|
||||
bool echo[2];
|
||||
bool supressGA[2];
|
||||
bool timingMark[2];
|
||||
|
||||
bool inIAC;
|
||||
bool recCommand;
|
||||
|
||||
Bit8u command;
|
||||
|
||||
};
|
||||
|
||||
static CSerial * mdm;
|
||||
static ModemHd mhd;
|
||||
static telnetClient telClient;
|
||||
|
||||
static void sendStr(const char *usestr) {
|
||||
if (!mhd.echo) return;
|
||||
|
@ -110,6 +127,10 @@ static void sendError() {
|
|||
sendStr("\nERROR\n");
|
||||
}
|
||||
|
||||
void InitTelnet() {
|
||||
memset(&telClient, 0, sizeof(telClient));
|
||||
}
|
||||
|
||||
static void toUpcase(char *buffer) {
|
||||
Bitu i=0;
|
||||
while (buffer[i] != 0) {
|
||||
|
@ -130,6 +151,7 @@ static void openConnection() {
|
|||
sendStr("\nCONNECT 57600\n");
|
||||
mhd.commandmode = false;
|
||||
mdm->setmodemstatus(CONNECTED);
|
||||
InitTelnet();
|
||||
} else {
|
||||
sendStr("\nNO DIALTONE\n");
|
||||
}
|
||||
|
@ -197,7 +219,7 @@ static void DoCommand() {
|
|||
result = 0;
|
||||
|
||||
|
||||
/* Just for kicks */
|
||||
/* AT command set interpretation */
|
||||
if ((mhd.cmdbuf[0] == 'A') && (mhd.cmdbuf[1] == 'T')) foundat = true;
|
||||
if (foundat) {
|
||||
if (strstr(mhd.cmdbuf,"I3")) {
|
||||
|
@ -223,6 +245,14 @@ static void DoCommand() {
|
|||
mhd.echo = true;
|
||||
}
|
||||
|
||||
if (strstr(mhd.cmdbuf,"NET0")) {
|
||||
mhd.telnetmode = false;
|
||||
}
|
||||
if (strstr(mhd.cmdbuf,"NET1")) {
|
||||
mhd.telnetmode = true;
|
||||
}
|
||||
|
||||
|
||||
if (strstr(mhd.cmdbuf,"ATH")) {
|
||||
/* Check if we're actually connected */
|
||||
if (mhd.socket) {
|
||||
|
@ -251,6 +281,36 @@ static void DoCommand() {
|
|||
if (!foundstr[0]) {
|
||||
result=2;
|
||||
} else {
|
||||
if (strlen(foundstr) >= 12)
|
||||
{
|
||||
// Check if supplied parameter only consists of digits
|
||||
bool isNum = true;
|
||||
for (int i=0; i<strlen(foundstr); i++)
|
||||
if (foundstr[i] < '0' || foundstr[i] > '9')
|
||||
isNum = false;
|
||||
|
||||
if (isNum)
|
||||
{
|
||||
// Parameter is a number with at least 12 digits => this cannot be a valid IP/name
|
||||
// Transform by adding dots
|
||||
char buffer[128];
|
||||
int j = 0;
|
||||
for (int i=0; i<strlen(foundstr); i++)
|
||||
{
|
||||
buffer[j++] = foundstr[i];
|
||||
|
||||
// Add a dot after the third, sixth and ninth number
|
||||
if (i == 2 || i == 5 || i == 8)
|
||||
buffer[j++] = '.';
|
||||
|
||||
// If the string is longer than 12 digits, interpret the rest as port
|
||||
if (i == 11 && strlen(foundstr)>12)
|
||||
buffer[j++] = ':';
|
||||
}
|
||||
buffer[j] = 0;
|
||||
foundstr = buffer;
|
||||
}
|
||||
}
|
||||
connResult = Dial(foundstr);
|
||||
result=3;
|
||||
}
|
||||
|
@ -314,6 +374,97 @@ static void MC_Changed(Bitu new_mc) {
|
|||
);
|
||||
}
|
||||
|
||||
static void TelnetEmulation(Bit8u * data, Bitu size) {
|
||||
int i;
|
||||
Bit8u c;
|
||||
for(i=0;i<size;i++) {
|
||||
c = data[i];
|
||||
if(telClient.inIAC) {
|
||||
if(telClient.recCommand) {
|
||||
if((c != 0) && (c != 1) && (c != 3)) {
|
||||
LOG_MSG("MODEM: Unrecognized option %d", c);
|
||||
if(telClient.command>250) {
|
||||
/* Reject anything we don't recognize */
|
||||
mdm->tx_addb(0xff); mdm->tx_addb(252); mdm->tx_addb(c); /* We won't do crap! */
|
||||
}
|
||||
}
|
||||
|
||||
switch(telClient.command) {
|
||||
case 251: /* Will */
|
||||
if(c == 0) telClient.binary[TEL_SERVER] = true;
|
||||
if(c == 1) telClient.echo[TEL_SERVER] = true;
|
||||
if(c == 3) telClient.supressGA[TEL_SERVER] = true;
|
||||
break;
|
||||
case 252: /* Won't */
|
||||
if(c == 0) telClient.binary[TEL_SERVER] = false;
|
||||
if(c == 1) telClient.echo[TEL_SERVER] = false;
|
||||
if(c == 3) telClient.supressGA[TEL_SERVER] = false;
|
||||
break;
|
||||
case 253: /* Do */
|
||||
if(c == 0) {
|
||||
telClient.binary[TEL_CLIENT] = true;
|
||||
mdm->tx_addb(0xff); mdm->tx_addb(251); mdm->tx_addb(0); /* Will do binary transfer */
|
||||
}
|
||||
if(c == 1) {
|
||||
telClient.echo[TEL_CLIENT] = false;
|
||||
mdm->tx_addb(0xff); mdm->tx_addb(252); mdm->tx_addb(1); /* Won't echo (too lazy) */
|
||||
}
|
||||
if(c == 3) {
|
||||
telClient.supressGA[TEL_CLIENT] = true;
|
||||
mdm->tx_addb(0xff); mdm->tx_addb(251); mdm->tx_addb(3); /* Will Suppress GA */
|
||||
}
|
||||
break;
|
||||
case 254: /* Don't */
|
||||
if(c == 0) {
|
||||
telClient.binary[TEL_CLIENT] = false;
|
||||
mdm->tx_addb(0xff); mdm->tx_addb(252); mdm->tx_addb(0); /* Won't do binary transfer */
|
||||
}
|
||||
if(c == 1) {
|
||||
telClient.echo[TEL_CLIENT] = false;
|
||||
mdm->tx_addb(0xff); mdm->tx_addb(252); mdm->tx_addb(1); /* Won't echo (fine by me) */
|
||||
}
|
||||
if(c == 3) {
|
||||
telClient.supressGA[TEL_CLIENT] = true;
|
||||
mdm->tx_addb(0xff); mdm->tx_addb(251); mdm->tx_addb(3); /* Will Suppress GA (too lazy) */
|
||||
}
|
||||
break;
|
||||
default:
|
||||
LOG_MSG("MODEM: Telnet client sent IAC %d", telClient.command);
|
||||
break;
|
||||
}
|
||||
|
||||
telClient.inIAC = false;
|
||||
telClient.recCommand = false;
|
||||
continue;
|
||||
|
||||
} else {
|
||||
if(c==249) {
|
||||
/* Go Ahead received */
|
||||
telClient.inIAC = false;
|
||||
continue;
|
||||
}
|
||||
telClient.command = c;
|
||||
telClient.recCommand = true;
|
||||
|
||||
if((telClient.binary[TEL_SERVER]) && (c == 0xff)) {
|
||||
/* Binary data with value of 255 */
|
||||
telClient.inIAC = false;
|
||||
telClient.recCommand = false;
|
||||
mdm->rx_addb(0xff);
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
} else {
|
||||
if(c == 0xff) {
|
||||
telClient.inIAC = true;
|
||||
continue;
|
||||
}
|
||||
mdm->rx_addb(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void MODEM_Hardware(void) {
|
||||
int result =0;
|
||||
unsigned long args = 1;
|
||||
|
@ -380,11 +531,18 @@ static void MODEM_Hardware(void) {
|
|||
|
||||
SDLNet_CheckSockets(mhd.socketset,0);
|
||||
/* Handle outgoing to the serial port */
|
||||
if(mdm->rx_size() == 0) {
|
||||
if(!mhd.commandmode && mhd.socket && mdm->rx_free() && SDLNet_SocketReady(mhd.socket)) {
|
||||
usesize = mdm->rx_free();
|
||||
result = SDLNet_TCP_Recv(mhd.socket, tmpbuf, usesize);
|
||||
if (result>0) {
|
||||
mdm->rx_adds(tmpbuf,result);
|
||||
if(mhd.telnetmode) {
|
||||
/* Filter telnet commands */
|
||||
TelnetEmulation(tmpbuf, result);
|
||||
|
||||
} else {
|
||||
mdm->rx_adds(tmpbuf,result);
|
||||
}
|
||||
mhd.cmdpause = 0;
|
||||
} else {
|
||||
/* Error close the socket and disconnect */
|
||||
|
@ -396,6 +554,7 @@ static void MODEM_Hardware(void) {
|
|||
mhd.socket=0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for incoming calls */
|
||||
if (!mhd.socket && !mhd.incomingcall && mhd.listensocket) {
|
||||
|
@ -500,6 +659,7 @@ static void MODEM_CallBack(Bit8u * stream,Bit32u len) {
|
|||
MIXER_Enable(mhd.chan,false);
|
||||
mhd.dialing = false;
|
||||
openConnection();
|
||||
|
||||
return;
|
||||
} else {
|
||||
|
||||
|
@ -584,6 +744,14 @@ void MODEM_Init(Section* sec) {
|
|||
return;
|
||||
}
|
||||
|
||||
if(!SDLNetInited) {
|
||||
if(SDLNet_Init()==-1) {
|
||||
LOG_MSG("SDLNet_Init failed: %s\n", SDLNet_GetError());
|
||||
return;
|
||||
}
|
||||
SDLNetInited = true;
|
||||
}
|
||||
|
||||
mhd.cmdpos = 0;
|
||||
mhd.commandmode = true;
|
||||
mhd.plusinc = 0;
|
||||
|
@ -593,6 +761,9 @@ void MODEM_Init(Section* sec) {
|
|||
mhd.cmdpause = 0;
|
||||
mhd.echo = true;
|
||||
|
||||
/* Default to direct null modem connection. Telnet mode interprets IAC codes */
|
||||
mhd.telnetmode = false;
|
||||
|
||||
/* Bind the modem to the correct serial port */
|
||||
mhd.comport=section->Get_int("comport");
|
||||
strcpy(mhd.remotestr, section->Get_string("remote"));
|
||||
|
|
Loading…
Add table
Reference in a new issue