#ifndef _aplmt_networking_uip_apss_telnetd_telnetdapi_h_
#define _aplmt_networking_uip_apss_telnetd_telnetdapi_h_
/*----------------------------------------------------------------------------
** SUMMARY: Telnet deamon for uIP
**
** DESCRIPTION:
**  This file provides the interface for a uIP telnet deamon.  It is an
**  adaptation of the original uIP/Telnetd application.
**
**  MULTIPLE NETWORK APPLICATIONS
**  -----------------------------
**  The following code snippet shows how to use the telnet deamon with other 
**  network application.
**
**      #define UIP_APPCALL networkApps
**
**      void networkApps( void )
**          {
**          switch( uip_conn->lport )
**              {
**              case HTONS(OPTION_APLMTUIP_TELNETD_PORT_NUM):
**                  AplmtUIP_telnetdInetApp();
**                  break;
**              
**              case HTONS(<other app port num>):
**                  myOtherNetworkApp();
**                  break;
**              }
**          }      
**              
**
** CONFIGURATION 
** -------------
**  COMPILE:     none.
**
**  PLATFORM:    none.
**
**  APPLICATION: OPTION_APLMTUIP_TELNETD_PORT_NUM
**               OPTION_APLMTUIP_TELNETD_NUM_OUTLINES
**               OPTION_APLMTUIP_TELNETD_LINE_SIZE
**               OPTION_APLMTUIP_TELNETD_MAX_CONNECTIONS
**               OPTION_APLMTUIP_TELNETD_MAXCONN_STRING
**               OPTION_APLMTUIP_TELNETD_ISO_NL
**               OPTION_APLMTUIP_TELNETD_ISO_CR
**
**  NOTES:
**  1. For efficency/optimization some methods are 'inlined'.  The inlining
**     is done by using the preprocessor/macros.  The application should
**     treat all methods as function calls and not rely on the fact they may
**     be currently defined as macros.
----------------------------------------------------------------------------*/

#include "aplcfg.h"                     /* For: Application configuration */
#include "apl/types/types.h"            /* For: basic types */
#include "apl/containers/ringbufapi.h"

#ifdef __cplusplus
extern "C" {
#endif


/*-------------- CONSTANTS -------------------------------------------------*/
/** Port number to listen on for a telnet connection request
 */
#ifndef OPTION_APLMTUIP_TELNETD_PORT_NUM
#define OPTION_APLMTUIP_TELNETD_PORT_NUM            23
#endif 

/** Number of buffered output lines per telnet connections
 */
#ifndef OPTION_APLMTUIP_TELNETD_NUM_OUTLINES
#define OPTION_APLMTUIP_TELNETD_NUM_OUTLINES        24
#endif

/** Number of raw characters per line.  (Does not includes the string terminator)
    NOTE: This must be less than or equal to the uIP MSS length.
 */
#ifndef OPTION_APLMTUIP_TELNETD_LINE_SIZE           
#define OPTION_APLMTUIP_TELNETD_LINE_SIZE           81
#endif

/** Total number of supported telnet connections.  This parameter is used
    for determining how much raw memory to allocate for the output
    buffers AND it is used to impose a limit of simultaneous telnet
    connections. It does *NOT* configure anything with respect to the uIP 
    options settings in uipopt.h
 */
#ifndef OPTION_APLMTUIP_TELNETD_MAX_CONNECTIONS
#define OPTION_APLMTUIP_TELNETD_MAX_CONNECTIONS     1
#endif

/** This string is the response string used when a telnet client request
    exceeds the number of allowed telnet sessions.
 */
#ifndef OPTION_APLMTUIP_TELNETD_MAXCONN_STRING
#define OPTION_APLMTUIP_TELNETD_MAXCONN_STRING  "All connection(s) are in use. Try again later."
#endif

/** Newline characters */
#ifndef OPTION_APLMTUIP_TELNETD_ISO_CR
#define OPTION_APLMTUIP_TELNETD_ISO_CR      0x0D
#endif
#ifndef OPTION_APLMTUIP_TELNETD_ISO_NL
#define OPTION_APLMTUIP_TELNETD_ISO_NL      0x0A
#endif


/*-------------- TYPES -----------------------------------------------------*/
/** Ring buffer for holding buffered output lines
 */
APL_STRUCTDEF_RBUFP(AplmtUIPTelnetdBufLinesOut_t,OPTION_APLMTUIP_TELNETD_NUM_OUTLINES);  

/** The telnet deamon connection structure.
 */
struct AplmtUIPTelnetdState_t 
    {
    struct AplmtUIPTelnetdBufLinesOut_t _outputBuffer;
    Apl16u                              _inBufPtr;
    char                                _inBuf[OPTION_APLMTUIP_TELNETD_LINE_SIZE+1];   /* include space for the null terminator */
    AplByte                             _state;
    AplBool                             _xon;
    };


/*-------------- INLINE IMPLEMENTATION -------------------------------------*/
#include "aplmt/networking/uip/apps/telnetd/telnetd.h"  


/*-------------- PUBLIC/PUBLISHED API --------------------------------------*/
/** This method is used to initialize the telnet deamon.  This method must
    be called in the context of the uIP network thread BEFORE the uIP stack
    is started.

    Prototype:
        void AplmtUIP_telnetdInit(void);
 */
#define AplmtUIP_telnetdInit                _AplmtUIP_telnetdInit

/** This method is the uIP "app method" that handles all of the raw
    interaction with the network stack. 

    Prototype:
        void AplmtUIP_telnetdInetApp(void);
 */
#define AplmtUIP_telnetdInetApp             _AplmtUIP_telnetdInetApp

/** This method is used by the Application to request that the existing 
    telnet connection be closed.

    Prototype:
        void AplmtUIP_telnetdClose(struct AplmtUIPTelnetdState_t* s);
 */
#define AplmtUIP_telnetdClose               _AplmtUIP_telnetdClose

/** This method is used to transmit/output a line of text to the
    remote telnet client.  If the output text is longer than the 
    internal line length, it is silently truncated.  If the internal
    output buffer(s) are full, then the output request is ignored and 
    zero (false) is returned, else non-zero (true) is returned.
    NOTES: 
        o The newline characters (CR,NL) are appended to the output
          data.
        o This method does not actual transmit the data, only queues it
          for transmission.  The application has no feedback on when the
          data is actually transmitted. 

    Prototype:
        AplBool AplmtUIP_telnetdOutputLine(struct AplmtUIPTelnetdState_t* s, char* outputline);
 */
#define AplmtUIP_telnetdOutputLine          _AplmtUIP_telnetdOutputLine

/** This method is very similar to AplmtUIP_telnetdOutputLine() except that
    no newline characters are appended to the output.

    Prototype:
        AplBool AplmtUIP_telnetdOutput(struct AplmtUIPTelnetdState_t* s, char* outputline);
 */
#define AplmtUIP_telnetdOutput              _AplmtUIP_telnetdOutput

/** This method is used to the application to resume data recption (i.e. unblock
    the TCP/IP flow control).  It should only be called after a call to 
    AplmtUIP_cbTelnetdInput() returns zero (false)

    Prototype:
        void AplmtUIP_telnetdResumeInput(struct AplmtUIPTelnetdState_t* s);
 */
#define AplmtUIP_telnetdResumeInput         _AplmtUIP_telnetdResumeInput

/** This command is used to request a output buffer.  The application can
    then 'print' directly to the buffer so as to eliminate the extra
    data-copy that is inherit when using AplmtUIP_telnetdOutputLine().  If a
    buffer is not available then 0/NULL is returned.  
    NOTES: 
        o The application MUST call AplmtUIP_telnetdXmitBuffer() to 
          perform the transmit.
        o The size of the buffer is always OPTION_APLMTUIP_TELNETD_LINE_SIZE
          not including the null terminator. 
        o The application is requred to append the CR and NL characters
          at the end of the output.
        o This method is thread safe, i.e. can be called from different
          threads.  This is the *ONLY* thread safe method (other than
          AplmtUIP_telentdFreeOutBuffer()) in this interface.  By being
          thread safe, it allows the application to construct the out
          bound data in threads other than the network thread.

    Prototype:
        char* AplmtUIP_telnetdGetOutBuffer(void);
 */
#define AplmtUIP_telnetdGetOutBuffer        _AplmtUIP_telnetdGetOutBuffer

/** This method will free/release a buffer that was allocated using
    AplmtUIP_telnetdGetOutBuffer().  This method is *ONLY* needed if the
    application requests a buffer and then decides not transmit it.  Under
    this scenerio, the app needs to call this method so there is not a
    leak in the buffer pool.     
    NOTES:
        o This method is thread safe, i.e. can be called from different
          threads.  See AplmtUIP_telnetdGetOutBuffer() for more details
          about thread-safety.
    
    Prototype:
        void AplmtUIP_telentdFreeOutBuffer( char* bufToRelease );
 */
#define AplmtUIP_telentdFreeOutBuffer       _AplmtUIP_telentdFreeOutBuffer

/** Helper function that appends the newline characters to the output buffer.
    NOTES:
        o This method should only be used with output buffer allocated via
          AplmtUIP_telnetdGetOutBuffer
        o 'endOfString' should point to the null terminator of the application
          generated output string.
        o There is no error checking for exceeding the buffer length.  The
          application is required to due this BEFORE calling this method.
        o This method is completely reentrant and therefore it is thread
          safe.

    Prototype:
        void AplmtUIP_telnetdAppendNewline( char* endOfString );
 */
#define AplmtUIP_telnetdAppendNewline       _AplmtUIP_telnetdAppendNewline

/** This command is used to transmit a previously allocate/populate transmit
    buffer.  If the buffer was succesfully queued for transmit the method
    return non-zero (true), else zero (false).
    NOTES:
        o 'outputbuffer' MUST be previously allocated using 
           AplmtUIP_telnetdGetOutBuffer() 

    Prototype:
        AplBool AplmtUIP_telnetdXmitBuffer( struct AplmtUIPTelnetdState_t* s, char* outputbuffer );
 */
#define AplmtUIP_telnetdXmitBuffer          _AplmtUIP_telnetdXmitBuffer
 

/*-------------- PUBLIC/PUBLISHED API --------------------------------------*/
/** This method is a callback into the application.  It is called when a 
    telnet connection has been established.
 */
void AplmtUIP_cbTelnetdConnected( struct AplmtUIPTelnetdState_t* s );

/** This method is a callback into the applicaiton.  It is called when the
    existing telnet connection has closed.  If the connection was NOT 
    cleanly terminated (i.e. aborted, timed-out, etc.) then 'abnornalClose' 
    will be non-zero (true), else if will be 0 (false).
 */
void AplmtUIP_cbTelnetdClosed( struct AplmtUIPTelnetdState_t* s, AplBool abnornalClose );
    
/** This method is a callback into the application.  It is called when a line of 
    text has arrived on.  The newline characters (NL,CR) are NOT stripped off.
    A line-of-text is defined as 1) receiving a NL character or 2) the
    input buffer is full (input buffer size=OPTION_APLMTUIP_TELNETD_LINE_SIZE).  
    The 'inputline' data is only valid/in-scope for the life of the this call.  
    The application is responsible for making a copy of the data if it needs to 
    stay in scope longer.  Typically, the application should always return 
    non-zero (true) for this method.  Returning zero (false) will force the 
    TCP/IP stack to flow control the remote client.  If false is returned, 
    the application must call AplmtUIP_telnetdResumeInput() to signal the remote 
    client to begin sending data again.
 */
AplBool AplmtUIP_cbTelnetdInput( struct AplmtUIPTelnetdState_t* s, char* inputline );



#ifdef __cplusplus
}
#endif
#endif /* _aplmt_networking_uip_apss_telnetd_telnetdapi_h_ */
