#if !defined(__alffnttl_h) // Sentry, use file only if it's not already included.
#define __alffnttl_h
/*  Project Tec3270

	 SUBSYSTEM:    Tec3270.exe (Tec3270 application)
	 FILE:         alffnttl.h
	 AUTHOR:       Alcindo Ferreira Filho

	 OVERVIEW:

    ALFFTelnet Class Definition, the Tec3270 Telnet class
    (That encode and decode byte sequences transmitted and
    received from host server).

    COPYRIGHT:    © 1998-2007
                  Alcindo Ferreira Filho
                  <alcindo@inttec.com.br>

    LICENSE:      Tec3270_License (docs/Tec3270_License.txt)
*/
#include <owl\window.h>
#include <time.h>
#include "alffnaux.h"
#include "alffbuff.h"
#include "alffmsgs.h"       /* TecLib Message Object Include */
#include "tec3270.rh"       // Definition of all resources.

/*---------------------------------------------------------------------*
 * TELNET COMMANDS, OPTIONS AND SUBOPTIONS DEFINITIONS FOR USING BY    *
 * PROCESSOR OF RECEIVED DATA AND OPTIONS/SUBOPTIONS HANDLER           *
 *---------------------------------------------------------------------*/

/*
 * ASCII Control Characters
 */

#define LF        0x0A

#define CR        0x0D


/* TELNET TCP URGENT Mode */
#define URGENT    true

/*
 * Telnet TN3270 command characters
 */

#define EOR       239    /* 0xef Binary End of Record */

#define SE        240    /* 0xf0 Sub-Negotiation End  */
#define NOP       241    /* 0xf1 No Operation         */
#define SYNC      242    /* 0xf2 Data Mark (DM)
								 /*      The data stream portion */
								 /*      of a Synch. This should */
								 /*      always be sent via a TCP */
								 /*      Urgent notification */
#define BRK       243    /* 0xf3 NVT character BRK    */
#define IP        244    /* 0xf4 Interrupt Process */
#define AO        245    /* 0xf5 Abort Output */
#define AYT       246    /* 0xf6 Are You There */
#define EC        247    /* 0xf7 Erase Character */
#define EL        248    /* 0xf8 Erase Line    */
#define GA        249    /* 0xf9 Go Ahead    */
#define SB        250    /* 0xfa Sub-Negotiation Start */
#define WILL      251    /* 0xfb Will perform opt locally */
#define WONT      252    /* 0xfc Won't perform opt locally */
#define DO        253    /* 0xfd Do request option remotely */
#define DONT      254    /* 0xfe Do stop option remotely */

#define IAC       255    /* 0xff Escape/Command */


/*
 * Telnet options
 */

#define TN_TRANSMIT_BINARY      0
#define TN_ECHO                 1
#define TN_RECONNECTION         2
#define TN_SUPPRESS_GA          3
#define TN_APPROX_MSG_SIZ_NEG   4
#define TN_STATUS               5
#define TN_TIMING_MARK          6
#define TN_REM_CTRL_TRAN_ECHO   7
#define TN_OUTPUT_LINE_WIDTH    8
#define TN_OUTPUT_PAGE_SIZE     9
#define TN_OUTPUT_CR_DISP      10
#define TN_OUTPUT_HT_STOPS     11
#define TN_OUTPUT_HT_DISP      12
#define TN_OUTPUT_FF_DISP      13
#define TN_OUTPUT_VT_STOPS     14
#define TN_OUTPUT_VT_DISP      15
#define TN_OUTPUT_LF_DISP      16
#define TN_EXTENDED_ASCII      17
#define TN_LOGOUT              18
#define TN_BYTE_MACRO          19
#define TN_DATA_ENTRY_TERM     20
#define TN_SUPDUP              21
#define TN_SUPDUP_OUTPUT       22
#define TN_SEND_LOCATION       23
#define TN_TERMINAL_TYPE       24  /* 0x18 */
#define TN_EOR                 25  /* 0x19 */
#define TN_TACACS_ID           26
#define TN_OUTPUT_MARKING      27
#define TN_TERM_LOC_NUM        28
#define TN_3270                29     //TN_3270_REGIME
#define TN_X3_PAD              30
#define TN_NEG_ABOUT_WIN_SIZ   31
#define TN_TERMINAL_SPEED      32
#define TN_REMOTE_FLOW_CTRL    33
#define TN_LINEMODE            34
#define TN_X_DISPLAY_LOC       35
#define NOPTIONS               36
#define TN3270E                40
#define EXTENDED_OPTIONS_LIST  255


/*
 * TN3270 sub-negotiation commands
 */

#define IS                      0
#define SEND                    1


/* Telnet TN3270 Terminal Negotiation Controls */

#define SBTERMMODEL        	    13  // Terminal Model Position in sb_terminal
#define SBTERMLEN          	    18  // Terminal Model Text Size


/* Telnet TN3287 Printer Error Codes - RFC 1646 / RFC 2355 compatible */

#define COMMAND_REJECTED          0x00

#define INTERVENTION_REQ          0x01

#define OPERATION_CHECK           0x02

#define COMP_DISCONNECTED         0x03

#define DATA_CHECK                0x04


/* TN3270/TN3270E - SNA Logical Units Ids */

#define NVT                     0   // Not an 3270 Terminal

#define LU1                     1

#define LU2                     2

#define LU3                     3


/*----------BEGIN OF TN3270E SPECIFIC DEFINITIONS ------------*/

/*

 * TN3270E Commands Names  (see RFC 2355 - TN3270 Enhancements)
 */

#define ASSOCIATE               0x00

#define CONNECT_E               0x01

#define DEVICE_TYPE             0x02

#define FUNCTIONS               0x03

#define IS_E                    0x04 //TN3270E IS

#define REASON                  0x05

#define REJECT                  0x06

#define REQUEST                 0x07

#define SEND_E                  0x08 //TN3270E SEND


/*

 * TN3270E Reason Codes
 */

#define CONN_PARTNER            00

#define DEVICE_IN_USE           01

#define INV_ASSOCIATE           02

#define INV_NAME                03

#define INV_DEVICE_TYPE         04

#define TYPE_NAME_ERROR         05

#define UNKNOWN_ERROR           06

#define UNSUPPORTED_REQ         07


/*

 * TN3270E Functions Names
 */

#define BIND_IMAGE              00

#define DATA_STREAM_CTL         01

#define RESPONSES               02

#define SCS_CTL_CODES           03

#define SYSREQ                  04

#define LASTFUNCTION            05


/* Telnet TN3270E Terminal Negotiation Controls */

#define MAXTERMTYPELEN          32  // Max Terminal Type Length (see tec3270.rc)

#define SBTERMMODEL_E       	  14  // Terminal Model Position in sb_terminal
#define SBTERMLEN_E         	  19  // Terminal Model Text Size



/*

 * TN3270E Message HEADER:

 * +-----------+--------------+---------------+------------+-----------

 * | DATA_TYPE | REQUEST_FLAG | RESPONSE_FLAG | SEQ_NUMBER |  DATA ....

 * +-----------+--------------+---------------+------------+-----------

 *    1 byte      1 byte          1 byte         2 bytes     n bytes

 */


/*      DATA_TYPE   Field           */

#define T3270_DATA              0x00

#define SCS_DATA                0x01

#define RESPONSE                0x02

#define BIND_IMAGE_DATA         0x03

#define UNBIND_DATA             0x04

#define NVT_DATA                0x05

#define REQUEST_TYPE            0x06

#define SSCP_LU_DATA            0x07

#define PRINT_EOJ               0x08


/*      REQUEST_FLAG Field          */

#define ERR_COND_CLEARED        0x00


/*      RESPONSE_FLAG Field         */

//  (DATA_TYPE = 3270_DATA or SCS_DATA)

#define NO_RESPONSE             0x00

#define ERROR_RESPONSE          0x01

#define ALWAYS_RESPONSE         0x02


//  DEVICE_STATUS

#define DEVICE_NOT_READY        0x00

#define DEVICE_READY            0x01


//  (DATA_TYPE = RESPONSE)

#define POSITIVE_RESPONSE       0x00

//  Positive Response codes

#define      DEVICE_END           0x00


#define NEGATIVE_RESPONSE       0x01

//  Negative Response codes

#define      COMMAND_REJECT       0x00

#define      INTERV_REQD          0x01

#define      OPERATION_CHECK      0x02

#define      COMPONENT_DISCONN    0x03

#define      NO_DEVICE_ERROR      0xFF



/* TN3270E Modes                    */

#define TNOTHING                 0

#define T3270MODE                1

#define TNVTMODE                 2


/*----------END OF TN3270E SPECIFIC DEFINITIONS -------------*/

/*- BEGIN OF LS-based Telnet Security  SPECIFIC DEFINITIONS ------------*
 *                                                                      *
 *  Internet Engineering Task Force                      Michael Boe    *
 *  INTERNET-DRAFT draft-ietf-tn3270e-telnet-tls-06.txt  Jeffrey Altman *
 *                                                       April 2002     *
 *----------------------------------------------------------------------*/

#define START_TLS   46  //(decimal)
#define FOLLOWS      1  //(decimal)

/*----------END OF TLS-based Telnet Security  --------------------------*/


/*
 * See RFC-1091 for description of algorithm for negotiating
 * terminal types (TN3270).
 * A list of terminals is defined, typically with 3 entries
 * for backward compatibility, entries are sent
 * sequentially as the remote server requests them, the last
 * entry is sent twice, and then we cycle thru the table from
 * the top again in case the remote wants to go back to pick
 * up a terminal type more to its liking.
 */


/*
static
char *Terminal_List[] =
{	 "vt100",
	 "ibm-3278-2",
	 "unknown",
	 "unknown"
};

*/

#define NOTERMS 4    /* Size of Terminal List           */

#define MAXTERM 4    /* Number of terminals in list     */



// ---------------------------------- END OF TELNET DEFINITIONS ------------------//


// SubOption Processing array length
#define SUBBUFSIZE 100            // SubOption Buffer Length

// Special macros for options processing
#define numberof(x)         (sizeof x/sizeof x[0])
#define highest(x)          (numberof(x)-1)
#define ClearElement(x)     memset((char*)&x, 0, sizeof x)
#define ClearArray(x)       memset((char*)x,  0, sizeof x)
#define SB_CLEAR()  subpointer = subbuffer
#define SB_TERM()   subend = subpointer
#define SB_ACCUM(c) if (subpointer < (subbuffer+SUBBUFSIZE-1)) { *subpointer++ = (c); }
#define CONTROL(x)  ((x)&0x1f)
#define HEX(x)  (x&0xff)
#define	LOCAL_CHARS	   0x01	/* Characters processed locally */
#define	LINE		      0x02	/* Line-by-line mode of operation */
#define	LOCAL_ECHO	   0x04	/* Echoing locally */
#define	COMMAND_LINE	0x08	/* Command line mode */
#define	MODE_LOCAL_CHARS(m)	(modeList[m].modetype &  LOCAL_CHARS)


typedef struct
	 { time_t 	system,
				echotoggle,
				modenegotiated,
				didnetreceive,
				gotDM;
	 } Clocks;

/*
 * Terminal Mode Options
 */
typedef struct
		  {
			char *modedescriptions;
			char modetype;
		  } Mode;

typedef Mode Modelist[7];



//{{ALFFTelnet}}
class ALFFTelnet
{
  public:
	 ALFFTelnet(TWindow* pWindow, ALFFConnData* cnnData,
                  bool printerLine=false);
	 virtual ~ALFFTelnet();
    char far* GetClassName() {return "ALFFTelnet";}
	 // -------- TELNET Process Public Members ---------------------
	 int   MessageRecv(LPALFFBUF pLineInBuf,
							 LPALFFBUF pNetInBuf,
							 LPALFFBUF pOOBData);
	 bool  MessageSend(LPALFFBUF pLineOutBuf,
							 LPALFFBUF pOutBuf,
                      bool noTN3270EHdr=false);
    bool  SetNeededResponse(LPALFFBUF pNetOutBuf, LPARAM messageCtrl,
                            int deviceStatus, int senseCode);
	 bool  SendRequestClearError(LPALFFBUF pLineOutBuf);
	 bool  SendControl(LPALFFBUF pLineOutBuf, uint control);
	 bool  SendEcho(LPALFFBUF pLineOutBuf, char* byte);
	 char* GetTerminalType();
	 char* GetTerminalModel();
	 bool  TermTypeChanged();
    char* GetTN3270Mode()          {return tn3270Mode;};
    char* GetTerminalNetname()     {return &terminalNetname[0];}
    char* GetPrinterNetname()      {return &printerNetname[0];}
    bool  Is3270Mode()             {return in3270; }
    bool  Is3270EMode()            {return in3270E;}
    bool  IsModeSwitched()         {return modeSwitched;}
    void  SetModeSwitched(bool mode) {modeSwitched = mode;}
    int   GetTN3270EMode() {return tn3270EMode;}
	 void  SetOOBData(bool option);
	 bool  EorReceived();
	 void  ResetEor();
	 bool  CloseAll();
    bool  GetEchoMode();

  protected:
	 ALFFMsgs* 		pMsgs;
	 TWindow*  		pCallWindow;
	 ALFFConnData* connData;
	 Modelist 		modeList;

	 enum nState {nTelnet_BEGIN, nTelnet_DATA, nTelnet_IAC, nTelnet_WILL,
					  nTelnet_WONT, nTelnet_DO, nTelnet_DONT, nTelnet_CR,
					  nTelnet_SB, nTelnet_SE } nTelnetRecvState;

	 Clocks clocks;

	 // -------- TELNET Process Control Flags ----------------------
	 bool connected,          // Telnet Line Connected
         isPrinter,          // Printer Terminal connection
			in3270,             // 3270 mode Active
         in3270E,            // TN3270E Active
			recvEOR,            // End Of 3270 Record received.
			dataSent,           // Indicate All Data Sent or Not
			crlf,               // True=LF after CR, False=NUL after CR
			askedSGA,           // Supress TELNET GA command
			isSYNCHing,         // Telnet SYNCH mode
			flushLine,          // Flush All Current line
			flushOut,           // Flushing all output
			autoFlush,          // Flush Output when interrupting
			autoSync,           // Send interrupt characters with SYNCH
			localChars,         // Recognize interrupt/quit from ???
			doneLclChars,       // User has set "LocalChars"
			doneBinaryToggle,   // User has selected binary mode
			dontLEcho,          // Suppress Local Echoing
			sentTermType,       // Terminal Type Was Sent to Host
         termTypeChanged,    // Terminal Type Was Changed (1st Time Included)
			oobData;            // Processing OOB Data in progress

	 int   globalMode;          // Terminal Mode: 3270, TTY with/without Echo,...
	 char* terminalType;
	 char* terminalModel;
    char* tn3270Mode;
    int   tn3270EMode;         //  TNOTHING, T3270MODE  or  TNVTMODE;
    bool  modeSwitched;

    /* Terminal and Printer Netnames on TN3270E (Max length is 8 bytes) */
    char  terminalNetname[10];
    char  printerNetname[10];

	 /* -------- TELNET Network Virtual Terminal (NVT) Options ----- */
	 bool hisopts[256];
	 bool myopts[256];

    // TN3270E Functions
    bool hisFunctions[256];
    bool myFunctions[256];
    uint16  sequenceNumber;

    /* TN3270E  Header Fields */
    unsigned char dataType;
    unsigned char requestFlag;
    unsigned char responseFlag;
    unsigned char seqNumber[2];

	 /* ------------------------------------------------------------ */

	 char sb_terminal[32];
	 char doopt[5];
	 char dont[5];
	 char will[5];
	 char wont[5];

	 char *subbuffer;
	 char *subpointer, *subend;

	 void OOBInfo(char* texto);
	 void BuildOOBData(char** oobPtr, ...);
	 void DoOption(char** oobPtr, int option);
	 void WillOption(char** oobPtr, int option);
	 void WontOption(char** oobPtr, int option);
    int  BuildMyFunctions(char* buffer, int type);
    bool ParseHisFunctions(char* buffer, int begin);
    bool IsHisFunctionsSupported();
    bool IsAnyOfHisFunctionsSupported();
    bool IsMyFunctionActive(unsigned char function) { return myFunctions[function]; }
	 int  SubOption(char** oobPtr, char* subbuffer);
    void SendPrinterStatus(char** oobPtr, bool printerError=false, int errorCode=0);
    void BuildOOBTerminal(char** oobPtr, int termId, char* oobTermFmt,
                          int fmtLength, int termTypePos,
                          char* tn3270ENetName=NULL);
    void BuildOOBStartTLS(char** oobPtr);
	 void SetIn3270();
	 bool CheckBuf(char* bufName, LPALFFBUF buffer, char* bufPtr,
						int bufCount, int bufMaxLength, bool receive=true);

};    //{{ALFFTelnet}}

typedef ALFFTelnet*	 LPALFFTelnet;

#endif                            // __ALFFTelnet_h sentry.