windows-nt/Source/XPSP1/NT/base/headless/watcher/watchertelnetclient.cpp
2020-09-26 16:20:57 +08:00

233 lines
5.6 KiB
C++

// WatcherTelnetClient.cpp : implementation file
//
#include "stdafx.h"
#include "WATCHER.h"
#include "WatcherTelnetClient.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#include "WATCHERView.h"
/////////////////////////////////////////////////////////////////////////////
// WatcherTelnetClient
WatcherTelnetClient::WatcherTelnetClient(LPBYTE cmd, int cmdLen,
LPBYTE lgn, int lgnLen)
:CommandSequence(NO_COMMAND),
lenLogin(lgnLen),
Login(lgn),
OptionIndex(0),
PacketNumber(3),
SentTermType(FALSE)
{
Command = cmd;
DocView = NULL;
lenCommand = cmdLen;
}
WatcherTelnetClient::~WatcherTelnetClient()
{
if (Login){
delete [] Login;
Login = NULL;
}
if (Command){
delete [] Command;
Command = NULL;
}
WatcherSocket::~WatcherSocket();
}
// Do not edit the following lines, which are needed by ClassWizard.
#if 0
BEGIN_MESSAGE_MAP(WatcherTelnetClient, WatcherSocket)
//{{AFX_MSG_MAP(WatcherTelnetClient)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
#endif // 0
/////////////////////////////////////////////////////////////////////////////
// WatcherTelnetClient member functions
void WatcherTelnetClient::OnReceive(int nErrorCode)
{
BYTE Buffer[MAX_BUFFER_SIZE];
int i,nRet,ret;
if (nErrorCode != 0) {
DocView->GetParent()->PostMessage(WM_CLOSE, 0,0);
return;
}
nRet = Receive(Buffer, MAX_BUFFER_SIZE, 0);
if(nRet <= 0) return;
for(i=0;i<nRet;i++){
ret = ProcessByte(Buffer[i]);
}
if (PacketNumber == 0){
WatcherSocket::OnReceive(nErrorCode);
return;
}
if(PacketNumber == 3){
if(Login){
Send(Login, lenLogin, 0);
}
PacketNumber --;
WatcherSocket::OnReceive(nErrorCode);
return;
}
if (SentTermType){
if(PacketNumber == 1){
if(Command){
int ret = Send(Command, lenCommand, 0);
}
}
PacketNumber --;
}
WatcherSocket::OnReceive(nErrorCode);
return;
}
int WatcherTelnetClient::ProcessByte(BYTE byte)
{
// Watch in general for Telnet Sequences and
// generate appropriate responses.
// Otherwise pass on the character to the View
// which will be configured for a particular console.
if ((byte == 255)&&(CommandSequence == NO_COMMAND)){
CommandSequence = IAC;
return 0;
}
switch (CommandSequence){
case NO_COMMAND:
// Send the character to the document view
((CWatcherView *)DocView)->ProcessByte(byte);
break;
case IAC:
// A Command Sequence is beginning
CommandSequence = byte;
break;
case DO:
// Options are here
// Only one byte options allowed
// So fall through
case DONT:
// Same as above;
case WILL:
// same
case WONT:
Options[OptionIndex] = byte;
ProcessCommand(CommandSequence);
CommandSequence=NO_COMMAND;
OptionIndex = 0;
break;
case SB:
// Might be a long list, so just go on
// until a SE is encountered
Options[OptionIndex]=byte;
if (byte == SE){
ProcessSBCommand(CommandSequence);
OptionIndex = 0;
CommandSequence = NO_COMMAND;
}
else{
OptionIndex++;
if (OptionIndex == MAX_BUFFER_SIZE){
// Cant have such a long command, can we??
OptionIndex = 0;
CommandSequence = NO_COMMAND;
}
}
break;
default:
// Cant recognize the command
OptionIndex = 0;
CommandSequence = NO_COMMAND;
break;
}
return 0;
}
void WatcherTelnetClient::ProcessCommand(BYTE cmd)
{
BYTE sbuf[MAX_BUFFER_SIZE];
switch(cmd){
case DO:
sbuf[0] = IAC;
sbuf[1] = WONT;
switch(Options[0]){
case TO_NAWS:
// terminal size is sent here.
sbuf[1] = WILL;
sbuf[2] = TO_NAWS;
sbuf[3] = IAC;
sbuf[4] = SB;
sbuf[5] = TO_NAWS;
sbuf[6] = 0;
sbuf[7] = MAX_TERMINAL_WIDTH;
sbuf[8] = 0;
sbuf[9] = MAX_TERMINAL_HEIGHT;
sbuf[10] = IAC;
sbuf[11] = SE;
Send(sbuf, 12, 0);
break;
case TO_TERM_TYPE:
// will then subnegotiate the parameters.
sbuf[1]=WILL;
default:
// just negate everything you dont understand :-)
sbuf[2] = Options[0];
Send(sbuf,3,0);
break;
}
default:
break;
}
}
void WatcherTelnetClient::ProcessSBCommand(BYTE cmd)
{
BYTE sbuf[MAX_BUFFER_SIZE];
switch(Options[0]){
case TO_TERM_TYPE:
sbuf[0] = IAC;
sbuf[1] = SB;
sbuf[2] = TO_TERM_TYPE;
sbuf[3] = TT_IS;
sbuf[4] = 'A';
sbuf[5] = 'N';
sbuf[6] = 'S';
sbuf[7] = 'I';
sbuf[8] = IAC;
sbuf[9] = SE;
Send(sbuf,10,0);
// May have to renegotiate the terminal type.
// If we connect to a real Terminal concentrator
// do we have to do all this ??
SentTermType = TRUE;
break;
default:
break;
}
return;
}
void WatcherTelnetClient::OnClose(int nErrorCode)
{
// this was just for debug purposes.
// If the error code is not zero, ie we
// had fatal errors on send and receive.
BOOL ret = (DocView->GetParent())->PostMessage(WM_CLOSE,0,0);
WatcherSocket::OnClose(nErrorCode);
return;
}