From ddba2a34fe25676d778c97a33e0d98f910e20592 Mon Sep 17 00:00:00 2001 From: Dean Beeler Date: Sun, 8 Feb 2004 08:38:40 +0000 Subject: [PATCH] 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 --- src/hardware/serialport.cpp | 6 +- src/hardware/softmodem.cpp | 177 +++++++++++++++++++++++++++++++++++- 2 files changed, 177 insertions(+), 6 deletions(-) diff --git a/src/hardware/serialport.cpp b/src/hardware/serialport.cpp index a5ba389e..3b7b55be 100644 --- a/src/hardware/serialport.cpp +++ b/src/hardware/serialport.cpp @@ -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) 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) where-=FIFO_SIZE; diff --git a/src/hardware/softmodem.cpp b/src/hardware/softmodem.cpp index 39466c93..937df31d 100644 --- a/src/hardware/softmodem.cpp +++ b/src/hardware/softmodem.cpp @@ -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 '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; i12) + 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;i250) { + /* 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"));