From 885f8cc426a8840ae61023b75f3f0e4a1e268082 Mon Sep 17 00:00:00 2001 From: Michael Krelin Date: Mon, 05 Jul 2004 01:53:09 +0000 Subject: initial commit into svn repository git-svn-id: http://svn.klever.net/kin/kinsole/trunk@1 fe716a7a-6dde-0310-88d9-d003556173a8 --- (limited to 'options.cpp') diff --git a/options.cpp b/options.cpp new file mode 100644 index 0000000..171ae4a --- a/dev/null +++ b/options.cpp @@ -0,0 +1,371 @@ + +enum _TOption { + toBinaryTransmission = 0, + toEcho = 1, // Done. + toReconnection = 2, + toSuppressGA = 3, // Eaten + toApproxMsgSizeNegotiation = 4, + toStatus = 5, // Half-implemented + toTimingMark = 6, + toRemoteControlledTransAndEcho = 7, + toOutputLineWidth = 8, + toOutputPageSize = 9, + toOutputCRDisposition = 10, + toOutputHTabstops = 11, + toOutputHTabDisposition = 12, + toOutputFFDisposition = 13, + toOutputVTabstops = 14, + toOutputVTabDisposition = 15, + toOutputLFDisposition = 16, + toExtendedASCII = 17, + toLogout = 18, + toByteMacro = 19, + toDET = 20, + toSUPDUP = 22, // ??? + toSUPDUPOutput = 22, + toSendLocation = 23, + toTerminalType =24, // Done. + toEndOfRecord = 25, + toTACACSUserId = 26, + toOutputMarking = 27, + toTerminalLocationNumber = 28, + toTelnet3270Regime = 29, + toX3PAD = 30, + toNAWS = 31, // Done. + toTerminalSpeed = 32, // No need to implement, really. + toRemoteFlowControl = 33, // !!! + toLineMode = 34, + toXDisplayLocation = 35, // No need to implement until we + // do our own X-Server. + toEnvironmentOption = 36, + toAuthenticationOption = 37, + toEncryptionOption = 38, + toNewEnviron = 39, // Need to implement + toTN3270E = 40, + toExtendedOptionsList = 255 +}; + +struct TOption { + enum _state { + stateNone=0, stateNo, stateYes, stateWantNo, stateWantYes + }; + UINT m_StateU:3; // State - US + UINT m_StateH:3; // State - HIM + int m_Q:1; + int m_Supported:1; + UINT m_SBCluster; + UINT m_AllocatedSB; + UINT m_StoredSB; + LPBYTE m_SB; + + BOOL (*m_OnDo)(); + BOOL (*m_OnDont)(); + BOOL (*m_OnWill)(); + BOOL (*m_OnWont)(); + BOOL (*m_OnSB)(LPBYTE data,UINT size); + BOOL (*m_OnInit)(); + + BOOL OnDo() { return m_OnDo?(*m_OnDo)():FALSE; } + BOOL OnDont() { return m_OnDont?(*m_OnDont)():FALSE; } + BOOL OnWill() { return m_OnWill?(*m_OnWill)():FALSE; } + BOOL OnWont() { return m_OnWont?(*m_OnWont)():FALSE; } + BOOL OnSB(LPBYTE data,UINT size) { return m_OnSB?(*m_OnSB)(data,size):FALSE; } + BOOL OnInit() { return m_OnInit?(*m_OnInit)():FALSE; } + + BOOL StoreSByte(BYTE c) { + if(m_AllocatedSB>=m_StoredSB){ + ASSERT(m_SBCluster); + LPBYTE nsb = new BYTE[m_AllocatedSB+m_SBCluster]; + ASSERT(nsb); + if(m_StoredSB){ + ASSERT(m_SB); + memmove(nsb,m_SB,m_StoredSB); + } + if(m_SB) + delete m_SB; + m_SB = nsb; + } + ASSERT(m_SB); + m_SB[m_StoredSB++]=c; + return TRUE; + } + BOOL CleanSB() { + if(m_SB) + delete m_SB; + m_SB = NULL; + m_AllocatedSB=m_StoredSB=0; + return TRUE; + } + +} Options[256]; + + +BOOL AskWill(BYTE o); +BOOL AskWont(BYTE o); +BOOL AskDo(BYTE o); +BOOL AskDont(BYTE o); + +#include "NAWS.cpp" +#include "terminal.cpp" +#include "status.cpp" +#include "NEW-ENVIRON.cpp" +#include "TIMING-MARK.cpp" + +BOOL On_ACK() { return TRUE; } + + +void InitOptionsTable() +{ + memset(Options,0,sizeof(Options)); + // Echo + Options[toEcho].m_OnDo = On_ACK; + Options[toEcho].m_OnDont = On_ACK; + Options[toEcho].m_OnWill = On_ACK; + Options[toEcho].m_OnWont = On_ACK; + // Suppress Go-Ahead + Options[toSuppressGA].m_OnWill = On_ACK; + Options[toSuppressGA].m_OnDo = On_ACK; + // Status + Options[toStatus].m_OnWill = statusOnWill; + Options[toStatus].m_OnDo = statusOnDo; + Options[toStatus].m_OnSB = statusOnSB; + // Terminal Type; + Options[toTerminalType].m_OnDo = terminaltypeOnDo; + Options[toTerminalType].m_OnSB = terminaltypeOnSB; + Options[toTerminalType].m_OnInit = terminaltypeOnInit; + Options[toTerminalType].m_SBCluster = 32; + // NAWS + Options[toNAWS].m_OnDo = nawsOnDo; + Options[toNAWS].m_SBCluster = 16; + // New Environment + Options[toNewEnviron].m_OnDo = newenvironOnDo; + Options[toNewEnviron].m_OnDont = newenvironOnDont; + Options[toNewEnviron].m_OnSB = newenvironOnSB; + Options[toNewEnviron].m_SBCluster = 32; + // Timing Mark + Options[toTimingMark].m_OnDo = tmOnDo; + Options[toTimingMark].m_OnWill = tmOnWill; + + for(int tmp=0;tmp<(sizeof(Options)/sizeof(*Options));tmp++){ + TOption& to = Options[tmp]; + to.OnInit(); + if(to.m_OnDo || to.m_OnDont || to.m_OnWill || to.m_OnWont + || to.m_OnSB || to.m_OnInit) + to.m_Supported=TRUE; + if(!to.m_SBCluster) + to.m_SBCluster=128; + } +} + +void ProcessDO(BYTE c) +{ +TOption& to = Options[c]; + // Ignore this junk if we're already in desired mode of operation + if(to.m_StateU==TOption::stateYes){ + connState = cstateNone; + return; + } + TRACE1("He want us to DO %d\n",(WORD)c); + if(!to.m_Supported){ + TRACE1("Unsupported option = %d\n",(WORD)c); + // Option is not suported - send WONT and switch to stateNo unless + // we've already denied this option. + if(to.m_StateU == TOption::stateNone){ + VERIFY(ShowUnwill(c)); + to.m_StateU = TOption::stateNo; + } + }else{ + // Okay, if we do - we do and tell him so, unless we asked for it. + // Otherwise - Tell him we're not about to. + if(to.OnDo()){ + if(to.m_StateU!=TOption::stateWantYes) + VERIFY(ShowWill(c)); + to.m_StateU = TOption::stateYes; + }else{ + if(to.m_StateU!=TOption::stateWantNo) + VERIFY(ShowUnwill(c)); + to.m_StateU = TOption::stateNo; + } + } + connState = cstateNone; +} + +void ProcessWILL(BYTE c) +{ +TOption& to = Options[c]; + // Ignore this junk if we consider him already in this mode + if(to.m_StateH==TOption::stateYes){ + connState = cstateNone; + return; + } + TRACE1("He WILL %d\n",(WORD)c); + if(!to.m_Supported){ + TRACE1("Unsupported option = %d\n",(WORD)c); + // Since we don't expect remote end to use this option - beg him + // not to go for it unless we think we already did. + if(to.m_StateH == TOption::stateNone){ + VERIFY(BegDont(c)); + to.m_StateH = TOption::stateNo; + } + }else{ + if(to.OnWill()){ + // We've accepted this - tell him to go ahead if we thought he's + // in opposite state and adjust our vision/ + if(to.m_StateH!=TOption::stateWantYes) + VERIFY(BegDo(c)); + to.m_StateH = TOption::stateYes; + }else{ + if(to.m_StateH!=TOption::stateWantNo) + VERIFY(BegDont(c)); + to.m_StateH = TOption::stateNo; + } + } + connState = cstateNone; +} + +void ProcessWONT(BYTE c) +{ +TOption& to = Options[c]; + // Ignore this junk if we consider him already in this mode + if(to.m_StateH==TOption::stateNo){ + connState = cstateNone; + return; + } + TRACE1("He WONT %d\n",(WORD)c); + if(!to.m_Supported){ + TRACE1("Unsupported option = %d\n",(WORD)c); + // Since we don't expect remote end to use this option - beg him + // not to go for it unless we think we already did. + if(to.m_StateH == TOption::stateNone){ + VERIFY(BegDont(c)); + to.m_StateH = TOption::stateNo; + } + }else{ + if(to.OnWont()){ + // We've accepted this - tell him to go ahead if we thought he's + // in opposite state and adjust our vision/ + if(to.m_StateH!=TOption::stateWantNo) + VERIFY(BegDont(c)); + to.m_StateH = TOption::stateNo; + }else{ + if(to.m_StateH!=TOption::stateWantYes) + VERIFY(BegDo(c)); + to.m_StateH = TOption::stateYes; + } + } + connState = cstateNone; +} + +void ProcessDONT(BYTE c) +{ +TOption& to = Options[c]; + // Ignore this junk if we consider him already in this mode + if(to.m_StateU==TOption::stateNo){ + connState = cstateNone; + return; + } + TRACE1("He want us to DONT %d\n",(WORD)c); + if(!to.m_Supported){ + TRACE1("DONT for unsupported option = %d\n",(WORD)c); + // Since we don't expect remote end to use this option - beg him + // not to go for it unless we think we already did. + if(to.m_StateU == TOption::stateNone){ + VERIFY(ShowUnwill(c)); + to.m_StateU = TOption::stateNo; + } + }else{ + if(to.OnDont()){ + if(to.m_StateU!=TOption::stateWantNo) + VERIFY(ShowUnwill(c)); + to.m_StateU = TOption::stateNo; + }else{ + if(to.m_StateU!=TOption::stateWantYes) + VERIFY(ShowWill(c)); + to.m_StateU = TOption::stateYes; + } + } + connState = cstateNone; +} + +void ProcessSBData(BYTE c) +{ + switch(connState){ + case cstateSBData: + if(c==tnIAC){ + connState=cstateSBDataIAC; + return; + } + break; + case cstateSBDataIAC: + if(c==tnSE){ + // Just let option handler process the data + TOption& to = Options[negOption]; + to.OnSB(to.m_SB,to.m_StoredSB); + to.CleanSB(); + connState = cstateNone; + return; + } + break; + default: + ASSERT(FALSE); + break; + } +TOption& to = Options[negOption]; + to.StoreSByte(c); +} + +BOOL AskWill(BYTE o) +{ +TOption& to = Options[o]; + if(to.m_StateU==TOption::stateYes || to.m_StateU==TOption::stateWantYes) + return TRUE; +#ifdef _DEBUG + if(to.m_StateU==TOption::stateWantNo) + TRACE1("NEED TO QUEUE %d\n",(WORD)o); +#endif + VERIFY(ShowWill(o)); + to.m_StateU=TOption::stateWantYes; + return TRUE; +} + +BOOL AskUnwill(BYTE o) +{ +TOption& to = Options[o]; + if(to.m_StateU==TOption::stateNo || to.m_StateU==TOption::stateWantNo) + return TRUE; +#ifdef _DEBUG + if(to.m_StateU==TOption::stateWantNo) + TRACE1("NEED TO QUEUE %d\n",(WORD)o); +#endif + VERIFY(ShowUnwill(o)); + to.m_StateU=TOption::stateWantNo; + return TRUE; +} + +BOOL AskDo(BYTE o) +{ +TOption& to = Options[o]; + if(to.m_StateH==TOption::stateYes || to.m_StateH==TOption::stateWantYes) + return TRUE; +#ifdef _DEBUG + if(to.m_StateH==TOption::stateWantNo) + TRACE1("NEED TO QUEUE %d\n",(WORD)o); +#endif + VERIFY(BegDo(o)); + to.m_StateH=TOption::stateWantYes; + return TRUE; +} + +BOOL AskDont(BYTE o) +{ +TOption& to = Options[o]; + if(to.m_StateH==TOption::stateNo || to.m_StateH==TOption::stateWantNo) + return TRUE; +#ifdef _DEBUG + if(to.m_StateH==TOption::stateWantYes) + TRACE1("NEED TO QUEUE %d\n",(WORD)o); +#endif + VERIFY(BegDont(o)); + to.m_StateH=TOption::stateWantNo; + return TRUE; +} -- cgit v0.9.0.2