#if !defined(__alffnccl_h) // Sentry, use file only if it's not already included.
#define __alffnccl_h
/*  Project Biblio-Tec

	 SUBSYSTEM:    TECSecurity.dll Library
	 FILE:         alffsocket.h
	 AUTHOR:       Alcindo Ferreira Filho

	 OVERVIEW:
	 Source file for definition of
    				ALFFCommCluster (Winsock Manager),
					ALFFCommLine    (Socket Manager) and
					ALFFLineError   (Comm Error Manager).
    Uses OpenSSL (SSL API) (www.openssl.org).

    COPYRIGHT:    © 2003,2005
                  Alcindo Ferreira Filho
                  <alcindo@inttec.com.br>

    LICENSE:      Biblio-Tec license (BiblTec.txt)
*/
//General Settings for TEC Libraries
#include "teclibs.h"

#include "alffmsgs.h"
#include <owl/winsock.h>

// SSL Comunicator includes
#include "alffsslcomm.h"
#include "alffx509.h"
#include "tecseclb.rh"

/*
 * Line States and Window Caller Messages
 */
#define LINE_CONNECT        FD_CONNECT
#define LINE_READ           FD_READ
#define LINE_WRITE          FD_WRITE
#define LINE_CLOSE          FD_CLOSE
#define LINE_ACCEPT         FD_ACCEPT
#define LINE_OOBDATA        FD_OOB
#define MSG_CLUSTER_NOTIFY  MSG_HOST_INFO_NOTIFY
#define MSG_LINE_NOTIFY     MSG_SOCKET_NOTIFY

/*
 * Communications Errors Values
 */
#define LINE_STRING_ERROR_LENGTH   128
#define COMPUTER_NAME_LENGTH       128
#define COMPUTER_ADDRESS_LENGTH    128
#define INVALID_CONNECTION_STATE  7000
#define SOCKET_ERROR_BEGIN       10000
#define CONNECTION_CLOSED            0

/*
 * SSL Communications Errors Values
 */
#define SSL_CONNECTION_OK         -7000
#define SSL_CONNECTION_ERROR      -7001
#define SSL_WANT_READ             -7002
#define SSL_WANT_WRITE            -7003
#define SSL_DISCONNECT_ERROR      -7004
#define SSL_CONNECTION_CLOSED         0


//{{ALFFLineError}}
class _TECSECCLASS ALFFLineError : public TSocketError, public ALFFObject
{
  public:
	 ALFFLineError(int commError=0,
	                  int newSizeToAllocate=LINE_STRING_ERROR_LENGTH);
	 virtual ~ALFFLineError();
    char far* GetClassName() {return "ALFFLineError";}
	 char* ReportError();

  protected:
	 char* commStringError;

};
//{{ALFFLineError}}

//{{ALFFCommCluster}}
class _TECSECCLASS ALFFCommCluster : public TSocketManager, public ALFFObject
{
  public:
	 ALFFCommCluster(char far *appID,TWindow* ptrAppWindow);
	 virtual ~ALFFCommCluster();
    char far* GetClassName() {return "ALFFCommCluster";}
	 char *appTitleID;
	 TWindow* appWindow;
	 void  SetMainWindow(TWindow* ptrAppWindow);
	 void  GetCommClusterInfo();
	 void  GetComputerCommInfo();
	 char* GetComputerName();
	 char* GetComputerAddress();
    char* GetClusterInfo();
    void  ShowAllInfo();

  protected:
	 ALFFMsgs*  pMsgs;
	 char*  computerName;
	 char*  computerAddress;
 };
//{{ALFFCommCluster}}

typedef ALFFCommCluster* LPALFFCLUSTER;


//    {{ALFFCommLine}}
class _TECSECCLASS ALFFCommLine: public TStreamSocket, public ALFFObject
{
  public:
	 ALFFCommLine(TWindow* ptrWindow, ALFFUseSecurity * pSec, ALFFDate::DateFormat fmt);
	 virtual ~ALFFCommLine();
    char far* GetClassName() {return "ALFFCommLine";}

    /*  Unsecure socket access */
	 int   LineConnect(const char *hostID, const char *portID);
	 int   LineDisconnect();
	 int   LineSendData(char *dataToSend, int& dataLength, bool urgent=false);
	 int   LineRecvData(char *dataReceived, int& dataLength, bool urgent=false);
    const char* GetHostIPAddr() { return &hostIPAddress[0]; }
    /* Secure socket access */
    int    SSLLineConnect(ALFFSSLComm::ALFFSSLMethod sslMethod,
                          bool verifyServerCert, bool verifyCRL, bool wHLLSession=false,
                          char* certPath=NULL, char* certPwd=NULL);
    int    SSLLineDisconnect();
    bool   ShowSSLCertificate(char* title=NULL);
    // Query Type values:
#define QUERYCERTISSUER            1
#define QUERYCERTSUBJECT           2
#define QUERYCERTNOTBEFORE         3
#define QUERYCERTNOTAFTER          4
#define QUERYCERTSUBJECTALTNAME    5
    string QueryCertificate(bool clientCertificate, int queryType, ALFFDate::DateFormat fmt);
    string GetSecurityInfo();

    //bool   HandleSSLError(ALFFSSLComunicator::ALFFSSLErrorCode sslError);
    string GetSSLErrors(bool& hasError);
    ULONG  GetSSLError() { return longErrorCode; }
    string GetSSLErrorString ();
    bool   UpdateCertVerifyOptions(bool verifyCert, bool verifyRevoked);

    
    /* Secure and unsecure socket common methods */
	 void  StartLineNotification();
	 int   DoClusterNotification(LPARAM lParam);
	 int   DoLineNotification(int nEvent);
    bool  IsReadRequired() { return readRequired; }

    /* Socket operation mode: Synchronous or Asynchronous  */
    void  SetAsyncMode(bool mode) {asyncMode = mode;}
    bool  IsAsyncMode()  {return asyncMode;}

    /* Certificates Errors: Client and Server */
    short GetClientCertificateError();
    short GetServerCertificateError();
    
  protected:
	 // -----------Line Connection Information Data  -------------
	 enum  nState {nIdle,nWaitingForAddress, nConnecting, nConnected, nSSLConnecting,
                  nSSLConnected, nSSLWaitingForRead, nSSLWaitingForWrite,
                  nSSLDisconnecting} nConnectionState;
    ALFFDate::DateFormat	dateFormat;
	 TWindow*   				ptrLineWindow;
    ALFFUseSecurity * 		pSecurity;
	 ALFFMsgs*  				pMsgs;
	 bool 						bLineDataSent;
    bool 						asyncMode;
	 char 						lineHostId[256];
	 char 						linePortId[32];
	 TINetSocketAddress 		sAddressToConnectTo;
    TINetSocketAddress 		sAddressInitial;
	 THostInfoManager 		connHostInfoManager;
    char                	hostIPAddress[32];

    // -----------SSL (OpenSSL) Connection Controls -------------
    ALFFSSLComm*   	 	pSSLComm;
    bool           		sslConnection;
    bool           		readRequired;
    ALFFSSLComm::
    ALFFSSLErrorCode 	errorCode;
    ULONG				 	longErrorCode;
    ALFFX509Certificate*  targetCert;
    //------------------------------------------------------------
	 void  SetIdleState();
	 void  SetWaitingForAddressState() {nConnectionState = nWaitingForAddress; }
	 //void  SetSSLWaitingForReadState() {nConnectionState = nSSLWaitingForRead; }
	 //void  SetSSLWaitingForWriteState(){nConnectionState = nSSLWaitingForWrite; }
	 void  SetConnectingState()        {nConnectionState = nConnecting; }
	 void  SetConnectedState()         {nConnectionState = nConnected; }
    void  SetSSLConnectingState()     {nConnectionState = nSSLConnecting; }
    void  SetSSLConnectedState()      {nConnectionState = nSSLConnected; }
    void  SetSSLDisconnectingState()  {nConnectionState = nSSLDisconnecting; }

    //
    bool  IsIdle()                {return (nConnectionState == nIdle); }
    bool  IsWaitingForAddress()   {return (nConnectionState == nWaitingForAddress);}
    bool  IsConnecting()          {return (nConnectionState == nConnecting); }
    bool  IsConnected()           {return (nConnectionState == nConnected); }
    bool  IsSSLConnected()        {return (nConnectionState == nSSLConnected); }
    bool  IsSSLConnecting()       {return (nConnectionState == nSSLConnecting); }
    bool  IsSSLDisconnecting()    {return (nConnectionState == nSSLDisconnecting); }

};    //{{ALFFCommLine}}

typedef ALFFCommLine* LPALFFLINE;

#endif
