/*****************************************************************************/
/*
                                   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

/* segment sizes (TCP MSS) for QIOs */
#define NETIO_QIO_BYTES_DEFAULT  1460
#define NETIO_QIO_BYTES_MAX      8960
#define NETIO_QIO_BYTES_MIN       536
#define NETIO_QIO_BYTES_SENTINAL  999

/* 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  IpPort,
        SetClientAddress,
        UpstreamHostNameLength;

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

   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;

   uint  /* the maximum bytes to be QIOed */
         QioMaxSeg,
         /* 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,
         /* TCP maximum segment size (MSS) */
         TcpIpTcpMaxSeg,
         /* length of upstream host name */
         UpstreamHostNameLength,
         /* when non-zero this status value is returned (e.g. SS$_CANCEL) */
         VmsStatus,
         /* item is beiong 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;
         
   ulong  /* accumulates number of I/Os */
          BlocksRawRx [QUAD2],
          /* number of I/Os (reset with each stats update) */
          BlocksTallyRx [QUAD2],
          /* accumulate bytes I/Oed */
          BytesRawRx [QUAD2],
          /* number of bytes I/Oed (reset with each stats update) */
          BytesTallyRx [QUAD2],
          /* accumulates number of I/Os */
          BlocksRawTx [QUAD2],
          /* number of I/Os (reset with each stats update) */
          BlocksTallyTx [QUAD2],
          /* accumulate bytes I/Oed */
          BytesRawTx [QUAD2],
          /* number of bytes I/Oed (reset with each stats update) */
          BytesTallyTx [QUAD2];

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

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

   void  /* using HTTP/2 interface */
         *Http2StreamPtr,
         /* 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,
         /* AST to be called when I/O complete */
         *WriteAstFunction,
         /* parameter to be supplied to AST */
         *WriteAstParam;
         
   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;
};

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*);
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*, int*);
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 */
/***********************/

NETIO_STRUCT* NetIoBegin ();
NETIO_STRUCT* NetIoProxyBegin ();
void NetIoCancel (NETIO_STRUCT*);
void NetIoEnd (NETIO_STRUCT*);
void NetIoQioMaxSeg (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

#endif /* NET_H_LOADED */

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

