[0001]
[0002]
[0003]
[0004]
[0005]
[0006]
[0007]
[0008]
[0009]
[0010]
[0011]
[0012]
[0013]
[0014]
[0015]
[0016]
[0017]
[0018]
[0019]
[0020]
[0021]
[0022]
[0023]
[0024]
[0025]
[0026]
[0027]
[0028]
[0029]
[0030]
[0031]
[0032]
[0033]
[0034]
[0035]
[0036]
[0037]
[0038]
[0039]
[0040]
[0041]
[0042]
[0043]
[0044]
[0045]
[0046]
[0047]
[0048]
[0049]
[0050]
[0051]
[0052]
[0053]
[0054]
[0055]
[0056]
[0057]
[0058]
[0059]
[0060]
[0061]
[0062]
[0063]
[0064]
[0065]
[0066]
[0067]
[0068]
[0069]
[0070]
[0071]
[0072]
[0073]
[0074]
[0075]
[0076]
[0077]
[0078]
[0079]
[0080]
[0081]
[0082]
[0083]
[0084]
[0085]
[0086]
[0087]
[0088]
[0089]
[0090]
[0091]
[0092]
[0093]
[0094]
[0095]
[0096]
[0097]
[0098]
[0099]
[0100]
[0101]
[0102]
[0103]
[0104]
[0105]
[0106]
[0107]
[0108]
[0109]
[0110]
[0111]
[0112]
[0113]
[0114]
[0115]
[0116]
[0117]
[0118]
[0119]
[0120]
[0121]
[0122]
[0123]
[0124]
[0125]
[0126]
[0127]
[0128]
[0129]
[0130]
[0131]
[0132]
[0133]
[0134]
[0135]
[0136]
[0137]
[0138]
[0139]
[0140]
[0141]
[0142]
[0143]
[0144]
[0145]
[0146]
[0147]
[0148]
[0149]
[0150]
[0151]
[0152]
[0153]
[0154]
[0155]
[0156]
[0157]
[0158]
[0159]
[0160]
[0161]
[0162]
[0163]
[0164]
[0165]
[0166]
[0167]
[0168]
[0169]
[0170]
[0171]
[0172]
[0173]
[0174]
[0175]
[0176]
[0177]
[0178]
[0179]
[0180]
[0181]
[0182]
[0183]
[0184]
[0185]
[0186]
[0187]
[0188]
[0189]
[0190]
[0191]
[0192]
[0193]
[0194]
[0195]
[0196]
[0197]
[0198]
[0199]
[0200]
[0201]
[0202]
[0203]
[0204]
[0205]
[0206]
[0207]
[0208]
[0209]
[0210]
[0211]
[0212]
[0213]
[0214]
[0215]
[0216]
[0217]
[0218]
[0219]
[0220]
[0221]
[0222]
[0223]
[0224]
[0225]
[0226]
[0227]
[0228]
[0229]
[0230]
[0231]
[0232]
[0233]
[0234]
[0235]
[0236]
[0237]
[0238]
[0239]
[0240]
[0241]
[0242]
[0243]
[0244]
[0245]
[0246]
[0247]
[0248]
[0249]
[0250]
[0251]
[0252]
[0253]
[0254]
[0255]
[0256]
[0257]
[0258]
[0259]
[0260]
[0261]
[0262]
[0263]
[0264]
[0265]
[0266]
[0267]
[0268]
[0269]
[0270]
[0271]
[0272]
[0273]
[0274]
[0275]
[0276]
[0277]
[0278]
[0279]
[0280]
[0281]
[0282]
[0283]
[0284]
[0285]
[0286]
[0287]
[0288]
[0289]
[0290]
[0291]
[0292]
[0293]
[0294]
[0295]
[0296]
[0297]
[0298]
[0299]
[0300]
[0301]
[0302]
[0303]
[0304]
[0305]
[0306]
[0307]
[0308]
[0309]
[0310]
[0311]
[0312]
[0313]
[0314]
[0315]
[0316]
[0317]
[0318]
[0319]
[0320]
[0321]
[0322]
[0323]
[0324]
[0325]
[0326]
[0327]
[0328]
[0329]
[0330]
[0331]
[0332]
[0333]
[0334]
[0335]
[0336]
[0337]
[0338]
[0339]
[0340]
[0341]
[0342]
[0343]
[0344]
[0345]
[0346]
[0347]
[0348]
[0349]
[0350]
[0351]
[0352]
[0353]
[0354]
[0355]
[0356]
[0357]
[0358]
[0359]
[0360]
[0361]
[0362]
[0363]
[0364]
[0365]
[0366]
[0367]
[0368]
[0369]
[0370]
[0371]
[0372]
[0373]
[0374]
[0375]
[0376]
[0377]
[0378]
[0379]
[0380]
[0381]
[0382]
[0383]
[0384]
[0385]
[0386]
[0387]
[0388]
[0389]
[0390]
[0391]
[0392]
[0393]
[0394]
[0395]
[0396]
[0397]
[0398]
[0399]
[0400]
[0401]
[0402]
[0403]
[0404]
[0405]
[0406]
[0407]
[0408]
[0409]
[0410]
[0411]
[0412]
[0413]
[0414]
[0415]
[0416]
[0417]
[0418]
[0419]
[0420]
[0421]
[0422]
[0423]
[0424]
[0425]
[0426]
[0427]
[0428]
[0429]
[0430]
[0431]
[0432]
[0433]
[0434]
[0435]
[0436]
[0437]
[0438]
[0439]
[0440]
[0441]
[0442]
[0443]
[0444]
[0445]
[0446]
[0447]
[0448]
[0449]
[0450]
[0451]
[0452]
[0453]
[0454]
[0455]
[0456]
[0457]
[0458]
[0459]
[0460]
[0461]
[0462]
[0463]
[0464]
[0465]
[0466]
[0467]
[0468]
[0469]
[0470]
[0471]
[0472]
[0473]
[0474]
[0475]
[0476]
[0477]
[0478]
[0479]
[0480]
[0481]
[0482]
[0483]
[0484]
[0485]
[0486]
[0487]
[0488]
[0489]
[0490]
[0491]
[0492]
[0493]
[0494]
[0495]
[0496]
[0497]
[0498]
[0499]
[0500]
[0501]
[0502]
[0503]
[0504]
[0505]
[0506]
[0507]
[0508]
[0509]
[0510]
[0511]
[0512]
[0513]
[0514]
[0515]
[0516]
[0517]
[0518]
[0519]
[0520]
[0521]
[0522]
[0523]
[0524]
[0525]
[0526]
[0527]
[0528]
[0529]
[0530]
[0531]
[0532]
[0533]
[0534]
[0535]
[0536]
[0537]
[0538]
[0539]
[0540]
[0541]
[0542]
[0543]
[0544]
[0545]
[0546]
[0547]
[0548]
[0549]
/*****************************************************************************/
/*
                                  http2.h

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

#ifndef HTTP2_H_LOADED
#define HTTP2_H_LOADED 1

#include "hpack.h"
#include "wasd.h"
#include "types.h"

/**********/
/* config */
/**********/

/* send a ping every this many seconds */
#define HTTP2_PING_SECONDS_DEFAULT 300

/* seconds maximum between pings */
#define HTTP2_PING_SECONDS_MAX 3600  /* ONE HOUR! */

/* seconds maximum to respond to a ping */
#define HTTP2_PING_RESPONSE_MAX 15

/* i.e. default of one hour */
#define HTTP2_TIMEOUT_IDLE_SECONDS 60 * 60

/* i.e. this many seconds after a goaway has been received or sent */
#define HTTP2_TIMEOUT_GOAWAY_SECONDS 60

/* mitigate potential DoS attacks - all per second */
#define HTTP2_EMPTY_FRAME_LIMIT_COUNT   16
#define HTTP2_PING_LIMIT_COUNT          16
#define HTTP2_SETTINGS_LIMIT_COUNT      32
#define HTTP2_STREAM_RESET_LIMIT_COUNT  32
#define HTTP2_ZERO_HEADER_LIMIT_COUNT   16

/**********/
/* macros */
/**********/

/* 8 bit frame type codes (RFC7540 6.n) */
#define HTTP2_FRAME_DATA           0x0  /* */
#define HTTP2_FRAME_HEADERS        0x1  /* */
#define HTTP2_FRAME_PRIORITY       0x2  /* */
#define HTTP2_FRAME_RST_STREAM     0x3  /* */
#define HTTP2_FRAME_SETTINGS       0x4  /* */
#define HTTP2_FRAME_PUSH_PROMISE   0x5  /* */
#define HTTP2_FRAME_PING           0x6  /* */
#define HTTP2_FRAME_GOAWAY         0x7  /* */
#define HTTP2_FRAME_WINDOW_UPDATE  0x8  /* */
#define HTTP2_FRAME_CONTINUATION   0x9  /* */

/* 8 bit flag bits */
#define HTTP2_FLAG_CONT_END_HEAD  0x04  /* */
#define HTTP2_FLAG_DATA_END_STR   0x01  /* */
#define HTTP2_FLAG_DATA_PADDED    0x08  /* */
#define HTTP2_FLAG_HEAD_END_STR   0x01  /* */
#define HTTP2_FLAG_HEAD_END_HEAD  0x04  /* */
#define HTTP2_FLAG_HEAD_PADDED    0x08  /* */
#define HTTP2_FLAG_HEAD_PRIORITY  0x20  /* */
#define HTTP2_FLAG_PING_ACK       0x01  /* */
#define HTTP2_FLAG_PUSH_END_HEAD  0x04  /* */
#define HTTP2_FLAG_PUSH_PADDED    0x08  /* */
#define HTTP2_FLAG_SETTINGS_ACK   0x01  /* */

/* 16 bit setting codes (RFC7540 6.5.1) */
#define HTTP2_SETTING_MAX_HEAD_TABLE_SIZE 0x1  /* header table size */
#define HTTP2_SETTING_ENABLE_PUSH         0x2  /* server push enabled */
#define HTTP2_SETTING_MAX_CONC_STREAMS    0x3  /* max concurrent streams */
#define HTTP2_SETTING_INIT_WIN_SIZE       0x4  /* initial window size */
#define HTTP2_SETTING_MAX_FRAME_SIZE      0x5  /* max frame size */
#define HTTP2_SETTING_MAX_HEAD_LIST_SIZE  0x6  /* max header list size */

/* initial setting values (RFC7540 11.3) */
#define HTTP2_INITIAL_HEAD_TAB_SIZE      4096  /* bytes */
#define HTTP2_MAX_HEAD_TAB_SIZE         65535  /* bytes */
#define HTTP2_INITIAL_ENABLE_PUSH           0  /* disabled */
#define HTTP2_INITIAL_MAX_CONC_STREAMS    100  /* RFC recommended */
#define HTTP2_MIN_INITIAL_MAX_CONC_STREAMS  8  /* silly going lower */
#define HTTP2_MAX_CONC_STREAMS           1024  /* seems enormous */
#define HTTP2_INITIAL_MAX_FRAME_SIZE    16384  /* bytes */
#define HTTP2_MAX_FRAME_SIZE            65535  /* max <= I/O status block */
#define HTTP2_INITIAL_WINDOW_SIZE       65535  /* bytes */
#define HTTP2_DEFAULT_WINDOW_SIZE      131070  /* bytes */
#define HTTP2_MAX_WINDOW_SIZE         4194303  /* bytes */
#define HTTP2_DISABLE_WINDOW_SIZE  0x7fffffff  /* bytes */
#define HTTP2_INITIAL_HEAD_LIST_SIZE    65535  /* bytes */
#define HTTP2_MAX_HEAD_LIST_SIZE        65535  /* bytes */

/* 32 bit error code values (RFC7540 11.4) */
#define HTTP2_ERROR_NONE      0x0  /* graceful shutdown */
#define HTTP2_ERROR_PROTOCOL  0x1  /* protocol error detected */
#define HTTP2_ERROR_INTERNAL  0x2  /* implementation fault */
#define HTTP2_ERROR_FLOW      0x3  /* flow-control limits exceeded */
#define HTTP2_ERROR_TIMEOUT   0x4  /* settings not acknowledged */
#define HTTP2_ERROR_CLOSED    0x5  /* frame received for closed stream */
#define HTTP2_ERROR_SIZE      0x6  /* frame size incorrect */
#define HTTP2_ERROR_REFUSED   0x7  /* stream not processed */
#define HTTP2_ERROR_CANCEL    0x8  /* stream cancelled */
#define HTTP2_ERROR_COMPRESS  0x9  /* compression state not updated */
#define HTTP2_ERROR_CONNECT   0xa  /* TCP connection error for CONNECT */
#define HTTP2_ERROR_CALM      0xb  /* processing capacity exceeded */
#define HTTP2_ERROR_SECURITY  0xc  /* negotiated TLS params not acceptable */
#define HTTP2_ERROR_HTTP11    0xd  /* use HTTP/1.1 for the request */
#define HTTP2_ERROR_COUNT     14   /* number of HTTP/2 errors */

/* stream states (RFC7540 5.1) */
#define HTTP2_STATE_IDLE          0x1 
#define HTTP2_STATE_RESERVED_LOC  0x2
#define HTTP2_STATE_RESERVED_REM  0x3
#define HTTP2_STATE_OPEN          0x4
#define HTTP2_STATE_CLOSED_LOC    0x5
#define HTTP2_STATE_CLOSED_REM    0x6
#define HTTP2_STATE_CLOSED        0x7

/* number of octets in the frame header */
#define HTTP2_FRAME_HEADER_SIZE 9

/* queue indices and path SETings */
#define HTTP2_WRITE_QUEUE_MAX     0  /* for connection management */
#define HTTP2_WRITE_QUEUE_HIGH    1
#define HTTP2_WRITE_QUEUE_NORMAL  2  /* (default) */
#define HTTP2_WRITE_QUEUE_LOW     3

/*********************/
/* functional macros */
/*********************/

#define HTTP2_REQUEST(ptr) ((ptr) != NULL && \
                            (ptr)->Http2Stream.Http2Ptr != NULL)
                           
#define NOT_HTTP2_REQUEST(ptr) ((ptr) != NULL && \
                                (ptr)->Http2Stream.Http2Ptr == NULL)

#define HTTP2_PEEK_32(ptr,val) \
{ val =  (uint)(((uchar*)ptr)[0] << 24); \
  val += (uint)(((uchar*)ptr)[1] << 16); \
  val += (uint)(((uchar*)ptr)[2] << 8); \
  val += (uint)(((uchar*)ptr)[3]); }

#define HTTP2_GET_32(ptr,val) \
{ val =  (uint)(((uchar*)ptr)[0] << 24); \
  val += (uint)(((uchar*)ptr)[1] << 16); \
  val += (uint)(((uchar*)ptr)[2] << 8); \
  val += (uint)(((uchar*)ptr)[3]); \
  (uchar*)(ptr) += 4; }

#define HTTP2_PEEK_24(ptr,val) \
{ val =  (uint)(((uchar*)ptr)[0] << 16); \
  val += (uint)(((uchar*)ptr)[1] << 8); \
  val += (uint)(((uchar*)ptr)[2]); }

#define HTTP2_GET_24(ptr,val) \
{ val =  (uint)(((uchar*)ptr)[0] << 16); \
  val += (uint)(((uchar*)ptr)[1] << 8); \
  val += (uint)(((uchar*)ptr)[2]); \
  (uchar*)(ptr) += 3; }

#define HTTP2_PEEK_16(ptr,val) \
{ val =  (uint)(((uchar*)ptr)[0] << 8); \
  val += (uint)(((uchar*)ptr)[1]); }

#define HTTP2_GET_16(ptr,val) \
{ val =  (uint)(((uchar*)ptr)[0] << 8); \
  val += (uint)(((uchar*)ptr)[1]); \
  (uchar*)(ptr) += 2; }

#define HTTP2_PEEK_8(ptr,val) \
{ val = (uint)(*((uchar*)ptr)); }

#define HTTP2_GET_8(ptr,val) \
{ val = (uint)(*((uchar*)ptr)); (uchar*)(ptr) += 1; }

#define HTTP2_PLACE_32(ptr,val) \
{ ((uchar*)ptr)[0] = (val & 0xff000000) >> 24; \
  ((uchar*)ptr)[1] = (val & 0xff0000) >> 16; \
  ((uchar*)ptr)[2] = (val & 0xff00) >> 8; \
  ((uchar*)ptr)[3] = val & 0xff; }

#define HTTP2_PUT_32(ptr,val) \
{ ((uchar*)ptr)[0] = (val & 0xff000000) >> 24; \
  ((uchar*)ptr)[1] = (val & 0xff0000) >> 16; \
  ((uchar*)ptr)[2] = (val & 0xff00) >> 8; \
  ((uchar*)ptr)[3] = val & 0xff; \
  (uchar*)(ptr) += 4; }

#define HTTP2_PLACE_24(ptr,val) \
{ ((uchar*)ptr)[0] = (val & 0xff0000) >> 16; \
  ((uchar*)ptr)[1] = (val & 0xff00) >> 8; \
  ((uchar*)ptr)[2] = val & 0xff; }

#define HTTP2_PUT_24(ptr,val) \
{ ((uchar*)ptr)[0] = (val & 0xff0000) >> 16; \
  ((uchar*)ptr)[1] = (val & 0xff00) >> 8; \
  ((uchar*)ptr)[2] = val & 0xff; \
  (uchar*)(ptr) += 3; }

#define HTTP2_PLACE_16(ptr,val) \
{ ((uchar*)ptr)[0] = (val & 0xff00) >> 8; \
  ((uchar*)ptr)[1] = val & 0xff; }

#define HTTP2_PUT_16(ptr,val) \
{ ((uchar*)ptr)[0] = (val & 0xff00) >> 8; \
  ((uchar*)ptr)[1] = val & 0xff; \
  (uchar*)(ptr) += 2; }

#define HTTP2_PLACE_8(ptr,val) \
{ *((uchar*)ptr) = val & 0xff; }

#define HTTP2_PUT_8(ptr,val) \
{ *((uchar*)ptr) = val & 0xff; (uchar*)(ptr)++; }

/*********************/
/* HTTP/2 structures */
/*********************/

#pragma member_alignment __save
#pragma member_alignment

typedef struct Http2Struct HTTP2_STRUCT;
typedef struct Http2HeaderStruct HTTP2_HEADER_STRUCT;
typedef struct Http2StreamStruct HTTP2_STREAM_STRUCT;
typedef struct Http2WriteStruct HTTP2_WRITE_STRUCT;

/* default space for payload without allocating extra */
#define HTTP2_WRITE_PAYLOAD 48

struct Http2HeaderStruct
{
   union frame_header2
   {
      uchar header [9];
      struct
      { 
         uchar  length [3];
         uchar  type   [1];
         uchar  flags  [1];
         uchar  ident  [4];
      };
   };
};

struct Http2WriteStruct
{
   LIST_ENTRY  ListEntry;

   HTTP2_STRUCT  *Http2Ptr;
   HTTP2_WRITE_STRUCT  *Write2Ptr;
   REQUEST_STRUCT  *RequestPtr;

   BOOL  WriteInProgress;

   uint  DataLength,
         DataSize,
         WriteCount,
         WriteQueue;

   void  *AstFunction,
         *AstParam,
         *DataPtr,
         *HeaderPtr;

   /* fill to longword boundary */
   uchar  filler [3];

   /* header fields */
   union header2
   {
      uchar header [9];
      struct
      { 
         uchar  length [3];
         uchar  type   [1];
         uchar  flags  [1];
         uchar  ident  [4];
      };
   };

   /* this chunk is pre-allocated for small control frames and the like */
   uchar  payload [HTTP2_WRITE_PAYLOAD];
   /* for appropriately allocated buffers further payload from here */
};

struct Http2StreamStruct
{
   /* for maintaining the list of HTTP/2 stream structures */
   LIST_ENTRY  ListEntry;

   HTTP2_STRUCT  *Http2Ptr;
   REQUEST_STRUCT  *RequestPtr;

   /* stream characteristics */
   uint  Depend,
         Ident,
         Priority,
         State,
         Weight;

   /* stream flow control */
   BOOL  FlowControl;
   int  ReadWindowSize,
        WriteWindowSize;

   /* headers continuation */
   uint  ContinSize;
   uchar  *ContinPtr;

   /* I/O outstanding */
   int  QueuedWriteCount;

   /* buffered data from client */
   uchar  *DataReadPtr;
   int   DataReadLength,
         DataReadSize;

   /* HTTP/2 request management */
   BOOL  HeaderSent,
         ReadEndStr,
         RequestEnd;
};

struct  Http2Struct
{
   /* for maintaining the list of HTTP/2 structures */
   LIST_ENTRY  ListEntry;

   /* VM zone for this HTTP/2 structure (keep at the top) */
   ulong  VmHeapZoneId;

   NETIO_STRUCT  /* pointer to network I/O structure */
                 *NetIoPtr;

   int  /* is this HTTP/2 connection being WATCHed */
        WatchItem,
        /* number HTTP2_WRITE_STRUCT currently in use (issue if negative) */
        WriteInUseCount;

   /* more general fields */

   BOOL  /* if HTTP/2 over http: */
         ExpectingH2cPreface;

   int  /* connection flow-control */
        ReadWindowSize,
        WriteWindowSize;

   uint  /* length of client's host name / IP address */
         ClientHostNameLength,
         /* setting - initial windows size */
         ClientInitialWindowSize,
         /* setting - maximum concurrent streams */
         ClientMaxConcStreams,
         /* setting - maximum frame size */
         ClientMaxFrameSize,
         /* setting - maximum header list size */
         ClientMaxHeaderListSize,
         /* setting - client header table size */
         ClientMaxHeaderTableSize,
         /* setting - client push promise */
         ClientPushPromise,
         /* propogated from original (upgrade) request */
         ConnectNumber,
         /* limit empty frames per second (DoS?) */
         EmptyFrameLimitCount,
         /* number of frames streams had flow control halt transmission */
         FlowControlCount,
         /* current number of streams being flow controlled */
         FlowControlCurrent,
         /* number of frames streams had flow control halt transmission */
         FlowControlTally,
         /* number of frames streams subject to flow control */
         FlowFrameCount,
         /* number of frames streams subject to flow control */
         FlowFrameTally,
         /* number of frames received */
         FrameCountRx,
         /* number of frames transmitted */
         FrameCountTx,
         /* number of frames already added into the accounting */
         FrameTallyRx,
         /* number of frames already added into the accounting */
         FrameTallyTx,
         /* number of request (headers plus data) frames received */
         FrameRequestCountRx,
         /* number of request (headers plus data) frames transmitted */
         FrameRequestCountTx,
         /* number of frames already added into the accounting */
         FrameRequestTallyRx,
         /* number of frames already added into the accounting */
         FrameRequestTallyTx,
         /* server sent goaway with last client stream identifier */
         GoAwayIdent,
         /* most client's go-away last stream identifier */
         GoAwayLastStreamIdent,
         /* the (Unix) second the connection should be terminated */
         GoAwaySecond,
         /* byte count before decompression */
         HpackClientInputCount,
         /* bytes count after decompression */
         HpackClientOutputCount,
         /* byte count before compression */
         HpackServerInputCount,
         /* bytes count after compression */
         HpackServerOutputCount,
         /* the (Unix) second the connection becomes idle */
         IdleSecond,
         /* most recent stream identifier from client */
         LastStreamIdent,
         /* most recent ping tick second (for timeout purposes) */
         PingBackTickSecond,
         /* limit number of pings per second (DoS?) */
         PingLimitCount,
         /* most recent ping round-trip in microseconds */
         PingMicroSeconds,
         /* send a ping after this tick second (essentially a timeout) */
         PingSendTickSecond,
         /* peak number of writes queued */
         QueuedWritePeak,
         /* read buffer count */
         ReadBufferCount,
         /* read buffer size */
         ReadBufferSize,
         /* total number of requests processed on this connection */
         RequestCount,
         /* current number of concurrent requests */
         RequestCurrent,
         /* maximum number of concurrent requests */
         RequestPeak,
         /* setting - server header table size */
         ServerHeaderTableSize,
         /* setting - initial windows size */
         ServerInitialWindowSize,
         /* setting - maximum concurrent streams */
         ServerMaxConcStreams,
         /* setting - maximum frame size */
         ServerMaxFrameSize,
         /* maximum number of bytes for HPACK dynamic table */
         ServerMaxHeaderTableSize,
         /* setting - maximum header list size */
         ServerMaxHeaderListSize,
         /* setting - server push promise */
         ServerPushPromise,
         /* limit number of settings per second (DoS?) */
         SettingsLimitCount,
         /* limit number of stream resets per second (DoS?) */
         StreamResetLimitCount,
         /* limit number of zero-length headers per second (DoS?) */
         ZeroHeaderLimitCount;

   int64  /* bytes received on the connection */
          BytesRawRx64,
          /* bytes transmitted on the connection */
          BytesRawTx64,
          /* bytes received since last accumulated */
          BytesRawTallyRx64,
          /* bytes transmitted since last accumulated */
          BytesRawTallyTx64,
          /* 64 bit time when client connected */
          ConnectTime64,
          /* 64 bit time when ping originated */
          PingTime64;

   uchar  *ReadBufferPtr;

   HPACK_TABLE_STRUCT  HpackClientTable,
                       HpackServerTable;

   /* a list of associated streams (which are requests) */
   LIST_HEAD  StreamList;

   LIST_HEAD  QueuedWriteList [HTTP2_WRITE_QUEUE_LOW+1];

   CLIENT_STRUCT  *ClientPtr;
   SERVICE_STRUCT  *ServicePtr;
};

#pragma member_alignment __restore

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

void Http2Begin (REQUEST_STRUCT*);
void Http2CloseConnection (HTTP2_STRUCT*);
HTTP2_STRUCT* Http2Create (REQUEST_STRUCT*);
int Http2Error (HTTP2_STRUCT*, uint, uint);
char* Http2ErrorString (int);
void Http2FlowControl (HTTP2_STRUCT*, uint);
int Http2GoAway (HTTP2_STRUCT*, uint, uchar*, uint);
void Http2Init ();
void Http2Report (REQUEST_STRUCT*);
int Http2Ping (HTTP2_STRUCT*, uint, uchar*, uint);
BOOL Http2Preface (REQUEST_STRUCT*);
int Http2Priority (HTTP2_STRUCT*, uint, uchar*, uint);
int Http2ResetStream (HTTP2_STRUCT*, uint, uint, uchar*, uint);
int Http2Settings (HTTP2_STRUCT*, uint, uchar*, uint);
void Http2SetWatch (HTTP2_STRUCT*, int);
BOOL Http2SwitchResponse (REQUEST_STRUCT*);
BOOL Http2Supervisor ();
void Http2TestBreak (int);
int Http2WindowUpdate (HTTP2_STRUCT*, uint, uint, uchar*, uint);
HTTP2_WRITE_STRUCT* Http2GetWriteStruct (HTTP2_STRUCT*, int, char*, int);
void Http2FreeWriteStruct (HTTP2_STRUCT*, HTTP2_WRITE_STRUCT*, char*, int);

int Http2NetControl (int);
int Http2NetClientRead (HTTP2_STRUCT*);
void Http2NetClientReadAst (HTTP2_STRUCT*);
int Http2NetIoRead (NETIO_STRUCT*);
int Http2NetIoWrite (NETIO_STRUCT*, VOID_AST, void*, void*, uint);
BOOL Http2NetIoInProgress (NETIO_STRUCT*);
void Http2NetQueueWrite (HTTP2_STRUCT*, HTTP2_WRITE_STRUCT*);
void Http2NetWriteDataAst (HTTP2_WRITE_STRUCT*);
void Http2NetWriteEnd (REQUEST_STRUCT*);
void Http2Net_REQUEST_END_AST (void*);
void Http2NetWriteHeaderAst (HTTP2_WRITE_STRUCT*);
void Http2Net_WRITE_NO_AST (void*);

REQUEST_STRUCT* Http2RequestBegin (HTTP2_STRUCT*, uint);
void Http2RequestBegin2 (REQUEST_STRUCT*, HTTP2_STRUCT*, uint);
void Http2RequestCancel (REQUEST_STRUCT*);
int Http2RequestData (HTTP2_STRUCT*, uint, uint, uchar*, uint);
void Http2RequestDataClose (REQUEST_STRUCT*);
void Http2RequestEnd2 (REQUEST_STRUCT*);
void Http2RequestEnd5 (REQUEST_STRUCT*);
void Http2RequestProcess (REQUEST_STRUCT*);
int Http2RequestResetStream (REQUEST_STRUCT*);
int Http2RequestResponse (REQUEST_STRUCT*, REQUEST_AST, char*, int);
int Http2ResponseDictHeader (REQUEST_STRUCT*, REQUEST_AST);

void Http2WatchData (HTTP2_STRUCT*, uint, uint, uchar*, uint, uint);
void Http2WatchError (HTTP2_STRUCT*, uint);
void Http2WatchFrame (HTTP2_STRUCT*, uchar*, uchar*, uint, BOOL);
void Http2WatchGoAway (HTTP2_STRUCT*, uchar*, uint);
void Http2WatchHeaders (HTTP2_STRUCT*, uint, uint, uchar*, uint, uint);
void Http2WatchPing (HTTP2_STRUCT*, uchar*, uint);
void Http2WatchPriority (HTTP2_STRUCT*, uint, uchar*, uint);
void Http2WatchPushPromise (HTTP2_STRUCT*, uint, uint, uchar*, uint);
void Http2WatchRstStream (HTTP2_STRUCT*, uint, uchar*, uint);
void Http2WatchSettings (HTTP2_STRUCT*, uchar*, uchar*, uint);
void Http2WatchWindowUpdate (HTTP2_STRUCT*, uint, uchar*, uint);

#endif /* HTTP2_H_LOADED */

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