/*****************************************************************************/
/*
                                   Net.h
*/
/*****************************************************************************/

#ifndef NET_H_LOADED
#define NET_H_LOADED 1

#include <types.h>
#include "service.h"
#include "strng.h"
#include "wasd.h"

/* output character encoding */
#define NET_WRITE_BUFFERED_NONE     0
#define NET_WRITE_BUFFERED_HTMLESC  1
#define NET_WRITE_BUFFERED_URLENC   2

/* retry failed sys$assign()s for this many seconds */
#define NET_ASSIGN_FAIL_MAX 60

/* number of time to attempt host name lookup when configuring services */
#define NET_LOOKUP_RETRY 2

/* most significant bit of data size set indicates fill with this much data */
#define NETIO_DATA_FILL_BUF 0x80000000

/* maximum size of buffer allowed to be filled (1MB) */
#define NETIO_DATA_FILL_MAX 1048575

#define NETIO_CONNECTED(ptr) ((ptr) && (ptr)->Channel)

#define NETIO_IN_PROGRESS(ptr) ((ptr) && ((ptr)->WriteAstFunction || \
                                          (ptr)->ReadAstFunction))
#define NETIO_READ_IN_PROGRESS(ptr) ((ptr) && (ptr)->ReadAstFunction)
#define NETIO_WRITE_IN_PROGRESS(ptr) ((ptr) && (ptr)->WriteAstFunction)

/**************/
/* structures */
/**************/

typedef struct ClientStruct CLIENT_STRUCT;

struct ClientStruct
{
   int  AgentBusyCount,
        SetClientAddress,
        UpstreamHostNameLength;

   ushort  IpPort;

   char  IpAddressString [TCPIP_ADDRESS_STRING_MAX+1],
         MultiHomeIpAddressString [TCPIP_ADDRESS_STRING_MAX+1],
         UpstreamHostName [TCPIP_HOSTNAME_MAX+1],
         UpstreamIpAddressString [TCPIP_ADDRESS_STRING_MAX+1];

   char  *AgentRequestPtr,
         *AgentResponsePtr;

   IPADDRESS  IpAddress,
              MultiHomeIpAddress,
              UpstreamIpAddress;

   TCPIP_HOST_LOOKUP  Lookup;

   SOCKADDRESS  SocketName;
   int  SocketNameLength;
   VMS_ITEM_LIST3  SocketNameItem;
};

typedef struct NetIoStruct NETIO_STRUCT;

struct NetIoStruct
{
   ushort  Channel;

   BOOL  /* WATCH has been triggered */
         WatchTriggerRx,
         WatchTriggerRxPlus,
         WatchTriggerTx,
         WatchTriggerTxPlus;

   uint  /* IO status block count equivalent (allows IOs > 65535) */
         ReadCount,
         /* read buffer size (also see NETIO_DATA_FILL_BUF) */
         ReadSize,
         /* IO status block status equivalent (allows IOs > 65535) */
         ReadStatus,
         /* tracks network errors */
         ReadErrorCount,
         /* first network error status */
         ReadErrorStatus,
         /* most efficient packing for multiple MSS inside 65535 I/O */
         TcpMaxQio,
         /* above has been set */
         TcpMaxQioSet,
         /* TCP maximum segment size (MSS) */
         TcpMaxSeg,
         /* TCP socket receive buffer size */
         TcpRcvBuf,
         /* TCP socket send buffer size */
         TcpSndBuf,
         /* length of upstream host name */
         UpstreamHostNameLength,
         /* when non-zero this status value is returned (e.g. SS$_CANCEL) */
         VmsStatus,
         /* item is being WATCHed */
         WatchItem,
         /* IO status block count equivalent (allows IOs > 65535) */
         WriteCount,
         /* write buffer length */
         WriteLength,
         /* IO status block status equivalent (allows IOs > 65535) */
         WriteStatus,
         /* tracks network errors */
         WriteErrorCount,
         /* first network error status */
         WriteErrorStatus;
         
   int64  /* accumulates number of I/Os */
          BlocksRawRx64,
          /* number of I/Os (reset with each stats update) */
          BlocksTallyRx64,
          /* accumulate bytes I/Oed */
          BytesRawRx64,
          /* number of bytes I/Oed (reset with each stats update) */
          BytesTallyRx64,
          /* accumulates number of I/Os */
          BlocksRawTx64,
          /* number of I/Os (reset with each stats update) */
          BlocksTallyTx64,
          /* accumulate bytes I/Oed */
          BytesRawTx64,
          /* number of bytes I/Oed (reset with each stats update) */
          BytesTallyTx64;

   uchar  /* for SSH-shared TLS/SSL services */
          SSHversionDigit;

   uchar  /* buffer space  */
          *ReadPtr,
          /* buffer space  */
          *WritePtr;

   void  /* AST to be called when I/O complete */
         *ReadAstFunction,
         /* parameter to be supplied to AST */
         *ReadAstParam,
         /* associated with a request */
         *RequestPtr,
         /* using SSL/TLS connection */
         *SesolaPtr,
         /* using HTTP/2 interface */
         *Stream2Ptr,
         /* AST to be called when I/O complete */
         *WriteAstFunction,
         /* parameter to be supplied to AST */
         *WriteAstParam;

   char  BgDevName [32];      

   IO_SB  AcceptIOsb,
          ReadIOsb,
          WriteIOsb;

   SERVICE_STRUCT  *ServicePtr;

   /***********************************************/
   /* proxy NETIO does not include the following! */
   /***********************************************/

   /* client data and pointer to that (see MapUrl_SetClientAddress()) */
   CLIENT_STRUCT  ClientIp;
   CLIENT_STRUCT  *ClientPtr;
};

typedef struct RejectStruct REJECT_STRUCT;

struct RejectStruct
{
   int  HitCount;
   long  TickSecond;
   char  HttpStatus [4];
   IPADDRESS  IpAddress;
};

struct NetTestStruct
{
   ushort  Channel;
   IO_SB  IOsb;
   char  Buffer [1024];
};

/***********************/
/* function prototypes */
/***********************/

/* forward reference required */
typedef struct ServiceStruct SERVICE_STRUCT;
void NetAbortSocket (REQUEST_STRUCT*);
NetAccept (SERVICE_STRUCT*);
NetAcceptAst (NETIO_STRUCT*);
void NetAcceptBegin ();
NetAcceptProcess (NETIO_STRUCT*);
BOOL NetAcceptSupervisor ();
void NetAllServices (void);
int NetStartService (SERVICE_STRUCT*);
void NetListFor (char*);
NetControl (int, char*);
NetDirectResponse (NETIO_STRUCT*, int);
NetDirectResponseAst (NETIO_STRUCT*);
NetDirectResponseTimeoutAst (NETIO_STRUCT*);
char* NetGetBgDevice (ushort, char*, int);
int RefGetRefCnt (ushort);
NetGetServerHostName ();
int NetGetRefCnt (ushort);
NetHostNameLookup (char*, int, char*, char*, char*, IPADDRESS*, ushort*);
ulong NetHostPortHash (char*, char*);
NetListen ();
NetParseHostString (char*, char*, int, int*);
NetResponseHeaderAst (REQUEST_STRUCT*);
NetServerShutdown (ushort);
int NetServiceReportConfig (REQUEST_STRUCT*, struct ConfigStruct*);
int NetServiceReportStats (REQUEST_STRUCT*);
NetServiceZeroAccounting ();
NetSetService ();
int NetClientSocketCcl (NETIO_STRUCT*, int);
void NetCloseSocket (REQUEST_STRUCT*);
int NetRead (REQUEST_STRUCT*, REQUEST_AST, char*, int);
void NetUpdateConnected (void*, int);
void NetUpdatePersistent (int);
void NetUpdateProcessing (void*, int);

NetActive (BOOL);
NetPassive ();
NetResume ();
NetSuspend (BOOL);

int NetWrite (REQUEST_STRUCT*, REQUEST_AST, char*, int);
void NetWriteBuffered (REQUEST_STRUCT*, REQUEST_AST, char*, int);
int NetWriteChunked (REQUEST_STRUCT*, REQUEST_AST, char*, int);
int NetWriteGzip (REQUEST_STRUCT*, REQUEST_AST, char*, int);
int NetWriteGzipAst (REQUEST_STRUCT*);
int NetWriteRaw (REQUEST_STRUCT*, REQUEST_AST, char*, int);
void NetWriteStrDsc (REQUEST_STRUCT*, REQUEST_AST);
void NetWriteStrDsc_SENTINAL (void*);

/* testing purpose only! */
void NetTestBreak (int);
NetTestRequest (ushort);
NetTestReadAst (struct NetTestStruct*);
NetTestWriteAst (struct NetTestStruct*);

/* definition to flush the buffer only if there is more than a buffer-full */
#define NetWritePartFlush(rq,ast) NetWriteBuffered(rq,ast,NULL,-1)
/* to flush buffered contents completely */
#define NetWriteFullFlush(rq,ast) NetWriteBuffered(rq,ast,NULL,0)
/* initialize the buffer */
#define NetWriteInit(rq) NetWriteBuffered(rq,NULL,NULL,0)

/***********************/
/* NetIo..() functions */
/***********************/

void NetAgentBegin (NETIO_STRUCT*);
void NetAgentEnd (REQUEST_STRUCT*);
NETIO_STRUCT* NetIoBegin ();
NETIO_STRUCT* NetIoProxyBegin ();
void NetIoCancel (NETIO_STRUCT*);
int NetIoDassgnChannel (NETIO_STRUCT*);
void NetIoEnd (NETIO_STRUCT*);
int NetIoCloseSocket (NETIO_STRUCT*);
int NetIoPeek (REQUEST_STRUCT*, REQUEST_AST);
int NetIoRead (NETIO_STRUCT*, VOID_AST, void*, void*, uint);
void NetIoReadAst (NETIO_STRUCT*);
void NetIoReadStatus (NETIO_STRUCT*, VOID_AST, void*, int, uint);
void NetIoToSink (NETIO_STRUCT*);
int NetIoWrite (NETIO_STRUCT*, VOID_AST, void*, void*, uint);
void NetIoWriteAst (NETIO_STRUCT*);
int NetIoWriteStatus (NETIO_STRUCT*, VOID_AST, void*, int, int);

#if WATCH_MOD
void NetIoReadTest (REQUEST_STRUCT*);
void NetIoWriteTest (REQUEST_STRUCT*);
#endif

/*************************/
/* NetReject() functions */
/*************************/

BOOL NetRejection (CLIENT_STRUCT*, SERVICE_STRUCT*);
BOOL NetRejectCIDR (char*, char*);
BOOL NetRejectRange (char*, char*);
void NetRejectAccessLog (CLIENT_STRUCT*, SERVICE_STRUCT*, char*);
char* NetRejectFile (char*);
char* NetRejectInit (char*);
char* NetRejectLoad (char*);
char* NetRejectReport (char*);
void NetRejectReportHistory (REQUEST_STRUCT*);
void NetRejectReportIp (REQUEST_STRUCT*);
void NetRejectReportAdmin (REQUEST_STRUCT *rqptr, char*);
char* NetRejectServerLog (CLIENT_STRUCT*, SERVICE_STRUCT*, char*, char*);
char* NetRejectSet (char*);
int NetRejectStatus (CLIENT_STRUCT*);
int NetRejectCheckStatus (CLIENT_STRUCT*);
int NetRejectThisStatus (CLIENT_STRUCT*);
int NetRejectPurgeStatus (int);
void NetRejectStatusInit (char*);
int NetRejectSetStatus (REQUEST_STRUCT*);

#endif /* NET_H_LOADED */

/*****************************************************************************/

