Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorerititan2017-04-11 09:52:42 +0000
committererititan2017-04-11 09:52:42 +0000
commit43537980c3ff570ed565ef92cc1c14bfc2b4639c (patch)
tree01bfe937c7fa6832946583c9584b6caf09af142f
parent7ab541c4a31fbb495b5926e25e72cc5c5ade1f62 (diff)
downloadtitan.ProtocolModules.HTTP2-43537980c3ff570ed565ef92cc1c14bfc2b4639c.tar.gz
titan.ProtocolModules.HTTP2-43537980c3ff570ed565ef92cc1c14bfc2b4639c.tar.xz
titan.ProtocolModules.HTTP2-43537980c3ff570ed565ef92cc1c14bfc2b4639c.zip
First versionR.1.A
-rw-r--r--HTTP2_CNL113851.tpd42
-rw-r--r--README.md9
-rw-r--r--doc/HTTP2_CNL113851_1551.docbin0 -> 84992 bytes
-rw-r--r--doc/HTTP2_CNL113851_PRI.docbin0 -> 59392 bytes
-rw-r--r--src/HTTP2_EncDec.cc1928
-rw-r--r--src/HTTP2_Types.ttcn291
6 files changed, 2270 insertions, 0 deletions
diff --git a/HTTP2_CNL113851.tpd b/HTTP2_CNL113851.tpd
new file mode 100644
index 0000000..a66c8d9
--- /dev/null
+++ b/HTTP2_CNL113851.tpd
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (c) 2017 Ericsson
+
+ All rights reserved. This program and the accompanying materials
+ are made available under the terms of the Eclipse Public License v1.0
+ which accompanies this distribution, and is available at
+ http://www.eclipse.org/legal/epl-v10.html
+
+
+ File: HTTP2_CNL113851.tpd
+ Description: tpd project file
+ Rev: R1A
+ Prodnr: CNL 113 851
+
+ -->
+<TITAN_Project_File_Information version="1.0">
+ <ProjectName>HTTP2_CNL113851</ProjectName>
+ <Folders>
+ <FolderResource projectRelativePath="src" relativeURI="src"/>
+ </Folders>
+ <Files>
+ <FileResource projectRelativePath="src/HTTP2_EncDec.cc" relativeURI="src/HTTP2_EncDec.cc"/>
+ <FileResource projectRelativePath="src/HTTP2_Types.ttcn" relativeURI="src/HTTP2_Types.ttcn"/>
+ </Files>
+ <ActiveConfiguration>Default</ActiveConfiguration>
+ <Configurations>
+ <Configuration name="Default">
+ <ProjectProperties>
+ <MakefileSettings>
+ <generateInternalMakefile>true</generateInternalMakefile>
+ <GNUMake>true</GNUMake>
+ <incrementalDependencyRefresh>true</incrementalDependencyRefresh>
+ <targetExecutable>bin/HTTP2_CNL113851</targetExecutable>
+ </MakefileSettings>
+ <LocalBuildSettings>
+ <workingDirectory>bin</workingDirectory>
+ </LocalBuildSettings>
+ </ProjectProperties>
+ </Configuration>
+ </Configurations>
+</TITAN_Project_File_Information>
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..d8acd44
--- /dev/null
+++ b/README.md
@@ -0,0 +1,9 @@
+# titan.ProtocolModules.HTTP2
+
+Main project page:
+
+https://projects.eclipse.org/projects/tools.titan
+
+The source code of the TTCN-3 compiler and executor:
+
+https://github.com/eclipse/titan.core
diff --git a/doc/HTTP2_CNL113851_1551.doc b/doc/HTTP2_CNL113851_1551.doc
new file mode 100644
index 0000000..9d532f1
--- /dev/null
+++ b/doc/HTTP2_CNL113851_1551.doc
Binary files differ
diff --git a/doc/HTTP2_CNL113851_PRI.doc b/doc/HTTP2_CNL113851_PRI.doc
new file mode 100644
index 0000000..6526631
--- /dev/null
+++ b/doc/HTTP2_CNL113851_PRI.doc
Binary files differ
diff --git a/src/HTTP2_EncDec.cc b/src/HTTP2_EncDec.cc
new file mode 100644
index 0000000..df739c8
--- /dev/null
+++ b/src/HTTP2_EncDec.cc
@@ -0,0 +1,1928 @@
+/******************************************************************************
+* Copyright (c) 2017 Ericsson AB
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* http://www.eclipse.org/legal/epl-v10.html
+*
+* Contributors:
+* Gabor Szalai - initial implementation and initial documentation
+******************************************************************************/
+//
+// File: HTTP2_EncDec.cc
+// Description: Encoder/decoder function for HTTP2
+// Rev: R1A
+// Prodnr: CNL 113 851
+
+
+#include "HTTP2_Types.hh"
+#include <stdint.h>
+#include "memory.h"
+#include <string.h>
+#include <stdio.h>
+#include <deque>
+
+// header compression context classes
+class HTTP2_hdr_data{
+public:
+ CHARSTRING name;
+ CHARSTRING value;
+ int size;
+
+ HTTP2_hdr_data(){
+ name="";
+ value="";
+ size=32;
+ };
+ HTTP2_hdr_data(const CHARSTRING& p_name, const CHARSTRING& p_value){
+ name=p_name;
+ value=p_value;
+ size=32+name.lengthof()+value.lengthof();
+ };
+ ~HTTP2_hdr_data(){};
+
+ void set(const CHARSTRING& p_name, const CHARSTRING& p_value){
+ name=p_name;
+ value=p_value;
+ size=32+name.lengthof()+value.lengthof();
+ }
+
+};
+
+
+class HTTP2_compression_ctx{
+public:
+ std::deque<HTTP2_hdr_data*> h_table;
+ int h_table_size;
+ int h_table_max_size;
+
+ HTTP2_compression_ctx(){
+ h_table_size=0;
+ h_table_max_size=4096;
+ };
+ HTTP2_compression_ctx(int max_size){
+ h_table_size=0;
+ h_table_max_size=max_size;
+ };
+
+ ~HTTP2_compression_ctx(){
+ std::deque<HTTP2_hdr_data*>::iterator it = h_table.begin();
+ while(it!=h_table.end()){
+ delete *it;
+ it++;
+ }
+ };
+
+ void set_max_size(int new_size){
+ while(new_size<h_table_size){
+ h_table_size-= h_table.back()->size;
+ delete h_table.back();
+ h_table.pop_back();
+ }
+ h_table_max_size=new_size;
+ };
+
+ void add_hdr(const CHARSTRING& p_name, const CHARSTRING& p_value){
+ HTTP2_hdr_data *hdata= new HTTP2_hdr_data(p_name,p_value);
+ h_table.push_front(hdata);
+ h_table_size+=hdata->size;
+ while(h_table_max_size<h_table_size){
+ h_table_size-= h_table.back()->size;
+ delete h_table.back();
+ h_table.pop_back();
+ };
+
+ };
+
+ int find(const CHARSTRING& p_name) const {
+ for(size_t i=0;i<h_table.size();i++){
+ if(h_table[i]->name==p_name){
+ return i+1;
+ }
+ }
+ return -1;
+ };
+ int find(const CHARSTRING& p_name, const CHARSTRING& p_value) const {
+ for(size_t i=0;i<h_table.size();i++){
+ if( (h_table[i]->name==p_name) && (h_table[i]->value==p_value) ){
+ return i+1;
+ }
+ }
+ return -1;
+ };
+
+ const HTTP2_hdr_data* operator[](int idx) const{
+ if( (idx>0) && (idx<=(int)h_table.size()) ){
+ return h_table[idx-1];
+ }
+ return NULL;
+ };
+
+};
+
+class HTTP2_compression_ctxs{
+public:
+ HTTP2_compression_ctx local;
+ HTTP2_compression_ctx remote;
+
+};
+
+class HTTP2_static_table_class{
+public:
+ HTTP2_compression_ctx ctx;
+ HTTP2_static_table_class(){
+ ctx.add_hdr("www-authenticate","");
+ ctx.add_hdr("via","");
+ ctx.add_hdr("vary","");
+ ctx.add_hdr("user-agent","");
+ ctx.add_hdr("transfer-encoding","");
+ ctx.add_hdr("strict-transport-security","");
+ ctx.add_hdr("set-cookie","");
+ ctx.add_hdr("server","");
+ ctx.add_hdr("retry-after","");
+ ctx.add_hdr("refresh","");
+ ctx.add_hdr("referer","");
+ ctx.add_hdr("range","");
+ ctx.add_hdr("proxy-authorization","");
+ ctx.add_hdr("proxy-authenticate","");
+ ctx.add_hdr("max-forwards","");
+ ctx.add_hdr("location","");
+ ctx.add_hdr("link","");
+ ctx.add_hdr("last-modified","");
+ ctx.add_hdr("if-unmodified-since","");
+ ctx.add_hdr("if-range","");
+ ctx.add_hdr("if-none-match","");
+ ctx.add_hdr("if-modified-since","");
+ ctx.add_hdr("if-match","");
+ ctx.add_hdr("host","");
+ ctx.add_hdr("from","");
+ ctx.add_hdr("expires","");
+ ctx.add_hdr("expect","");
+ ctx.add_hdr("etag","");
+ ctx.add_hdr("date","");
+ ctx.add_hdr("cookie","");
+ ctx.add_hdr("content-type","");
+ ctx.add_hdr("content-range","");
+ ctx.add_hdr("content-location","");
+ ctx.add_hdr("content-length","");
+ ctx.add_hdr("content-language","");
+ ctx.add_hdr("content-encoding","");
+ ctx.add_hdr("content-disposition","");
+ ctx.add_hdr("cache-control","");
+ ctx.add_hdr("authorization","");
+ ctx.add_hdr("allow","");
+ ctx.add_hdr("age","");
+ ctx.add_hdr("access-control-allow-origin","");
+ ctx.add_hdr("accept","");
+ ctx.add_hdr("accept-ranges","");
+ ctx.add_hdr("accept-language","");
+ ctx.add_hdr("accept-encoding","gzip, deflate");
+ ctx.add_hdr("accept-charset","");
+ ctx.add_hdr(":status","500");
+ ctx.add_hdr(":status","404");
+ ctx.add_hdr(":status","400");
+ ctx.add_hdr(":status","304");
+ ctx.add_hdr(":status","206");
+ ctx.add_hdr(":status","204");
+ ctx.add_hdr(":status","200");
+ ctx.add_hdr(":scheme","https");
+ ctx.add_hdr(":scheme","http");
+ ctx.add_hdr(":path","/index.html");
+ ctx.add_hdr(":path","/");
+ ctx.add_hdr(":method","POST");
+ ctx.add_hdr(":method","GET");
+ ctx.add_hdr(":authority","");
+ }
+};
+
+static const HTTP2_static_table_class HTTP2_static_table=HTTP2_static_table_class();
+
+////// Indexed variable int representation functions
+// Support max 32 bit unsigned val
+// it means the buffer should be at least 6 octet to safely store the max value
+// with the minimal prefix
+
+static const unsigned char twoN_minus_one_table[]={ // stores 2^N-1 for N=0..8
+0,1,3,7,15,31,63,127,255
+};
+
+// return the number of used octets
+static int encode_integer(unsigned char* buff,
+ const uint32_t val,
+ const int prefix_len,
+ const unsigned char filler){ // only the filler bits should be set
+ int ret_val=0;
+ if(val< twoN_minus_one_table[prefix_len]){
+ // fits in one octet
+ buff[0]= filler | (val & 0xFF);
+ ret_val=1;
+ } else {
+ uint32_t act_val=val-twoN_minus_one_table[prefix_len];
+ buff[0]= filler | ( twoN_minus_one_table[prefix_len] & 0xFF);
+ ret_val=1;
+ while(act_val>127){
+ buff[ret_val]= 0x80 | (act_val%128);
+ act_val/=128;
+ ret_val++;
+ }
+ buff[ret_val]= act_val;
+ ret_val++;
+ }
+ return ret_val;
+}
+
+// returns the number of the used octets
+static int decode_integer(const unsigned char* buff,
+ uint32_t& val,
+ const int prefix_len,
+ unsigned char& filler){ // only the filler bits will be set
+ filler = buff[0] & ~twoN_minus_one_table[prefix_len];
+
+ val = buff[0] & twoN_minus_one_table[prefix_len];
+
+ int ret_val=0;
+ if(val==twoN_minus_one_table[prefix_len]){
+ // The value is not fit into the prefix_len bits
+ do {
+ ret_val++;
+ val += ( ((uint32_t)(buff[ret_val] & 0x7F)) << (7*ret_val) );
+ } while(buff[ret_val] & 0x80);
+ ret_val++;
+ } else {
+ ret_val=1;
+ }
+ return ret_val;
+}
+
+
+
+
+
+//////////// Huffman tables See RFC7541
+
+// Huffman code lengths in bits
+
+static const int huffman_code_length[]={
+ 13, 23, 28, 28, 28, 28, 28, 28, 28, 24, 30, 28, 28, 30, 28, 28,
+ 28, 28, 28, 28, 28, 28, 30, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+ 6, 10, 10, 12, 13, 6, 8, 11, 10, 10, 8, 11, 8, 6, 6, 6,
+ 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 7, 8, 15, 6, 12, 10,
+ 13, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 8, 7, 8, 13, 19, 13, 14, 6,
+ 15, 5, 6, 5, 6, 5, 6, 6, 6, 5, 7, 7, 6, 6, 6, 5,
+ 6, 7, 6, 5, 5, 6, 7, 7, 7, 7, 7, 15, 11, 14, 13, 28,
+ 20, 22, 20, 20, 22, 22, 22, 23, 22, 23, 23, 23, 23, 23, 24, 23,
+ 24, 24, 22, 23, 24, 23, 23, 23, 23, 21, 22, 23, 22, 23, 23, 24,
+ 22, 21, 20, 22, 22, 23, 23, 21, 23, 22, 22, 24, 21, 22, 23, 23,
+ 21, 21, 22, 21, 23, 22, 23, 23, 20, 22, 22, 22, 23, 22, 22, 23,
+ 26, 26, 20, 19, 22, 23, 22, 25, 26, 26, 26, 27, 27, 26, 24, 25,
+ 19, 21, 26, 27, 27, 26, 27, 24, 21, 21, 26, 26, 28, 27, 27, 27,
+ 20, 24, 20, 21, 22, 21, 21, 23, 22, 22, 25, 25, 24, 24, 26, 23,
+ 26, 27, 26, 26, 27, 27, 27, 27, 27, 28, 27, 27, 27, 27, 27, 26,
+ 30
+};
+
+static const unsigned int huffman_code_values[]={
+ 0x1ff8, 0x7fffd8, 0xfffffe2, 0xfffffe3, 0xfffffe4, 0xfffffe5, 0xfffffe6, 0xfffffe7, 0xfffffe8, 0xffffea, 0x3ffffffc, 0xfffffe9, 0xfffffea, 0x3ffffffd, 0xfffffeb, 0xfffffec,
+ 0xfffffed, 0xfffffee, 0xfffffef, 0xffffff0, 0xffffff1, 0xffffff2, 0x3ffffffe, 0xffffff3, 0xffffff4, 0xffffff5, 0xffffff6, 0xffffff7, 0xffffff8, 0xffffff9, 0xffffffa, 0xffffffb,
+ 0x14, 0x3f8, 0x3f9, 0xffa, 0x1ff9, 0x15, 0xf8, 0x7fa, 0x3fa, 0x3fb, 0xf9, 0x7fb, 0xfa, 0x16, 0x17, 0x18,
+ 0x0, 0x1, 0x2, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x5c, 0xfb, 0x7ffc, 0x20, 0xffb, 0x3fc,
+ 0x1ffa, 0x21, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a,
+ 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0xfc, 0x73, 0xfd, 0x1ffb, 0x7fff0, 0x1ffc, 0x3ffc, 0x22,
+ 0x7ffd, 0x3, 0x23, 0x4, 0x24, 0x5, 0x25, 0x26, 0x27, 0x6, 0x74, 0x75, 0x28, 0x29, 0x2a, 0x7,
+ 0x2b, 0x76, 0x2c, 0x8, 0x9, 0x2d, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7ffe, 0x7fc, 0x3ffd, 0x1ffd, 0xffffffc,
+ 0xfffe6, 0x3fffd2, 0xfffe7, 0xfffe8, 0x3fffd3, 0x3fffd4, 0x3fffd5, 0x7fffd9, 0x3fffd6, 0x7fffda, 0x7fffdb, 0x7fffdc, 0x7fffdd, 0x7fffde, 0xffffeb, 0x7fffdf,
+ 0xffffec, 0xffffed, 0x3fffd7, 0x7fffe0, 0xffffee, 0x7fffe1, 0x7fffe2, 0x7fffe3, 0x7fffe4, 0x1fffdc, 0x3fffd8, 0x7fffe5, 0x3fffd9, 0x7fffe6, 0x7fffe7, 0xffffef,
+ 0x3fffda, 0x1fffdd, 0xfffe9, 0x3fffdb, 0x3fffdc, 0x7fffe8, 0x7fffe9, 0x1fffde, 0x7fffea, 0x3fffdd, 0x3fffde, 0xfffff0, 0x1fffdf, 0x3fffdf, 0x7fffeb, 0x7fffec,
+ 0x1fffe0, 0x1fffe1, 0x3fffe0, 0x1fffe2, 0x7fffed, 0x3fffe1, 0x7fffee, 0x7fffef, 0xfffea, 0x3fffe2, 0x3fffe3, 0x3fffe4, 0x7ffff0, 0x3fffe5, 0x3fffe6, 0x7ffff1,
+ 0x3ffffe0, 0x3ffffe1, 0xfffeb, 0x7fff1, 0x3fffe7, 0x7ffff2, 0x3fffe8, 0x1ffffec, 0x3ffffe2, 0x3ffffe3, 0x3ffffe4, 0x7ffffde, 0x7ffffdf, 0x3ffffe5, 0xfffff1, 0x1ffffed,
+ 0x7fff2, 0x1fffe3, 0x3ffffe6, 0x7ffffe0, 0x7ffffe1, 0x3ffffe7, 0x7ffffe2, 0xfffff2, 0x1fffe4, 0x1fffe5, 0x3ffffe8, 0x3ffffe9, 0xffffffd, 0x7ffffe3, 0x7ffffe4, 0x7ffffe5,
+ 0xfffec, 0xfffff3, 0xfffed, 0x1fffe6, 0x3fffe9, 0x1fffe7, 0x1fffe8, 0x7ffff3, 0x3fffea, 0x3fffeb, 0x1ffffee, 0x1ffffef, 0xfffff4, 0xfffff5, 0x3ffffea, 0x7ffff4,
+ 0x3ffffeb, 0x7ffffe6, 0x3ffffec, 0x3ffffed, 0x7ffffe7, 0x7ffffe8, 0x7ffffe9, 0x7ffffea, 0x7ffffeb, 0xffffffe, 0x7ffffec, 0x7ffffed, 0x7ffffee, 0x7ffffef, 0x7fffff0, 0x3ffffee,
+ 0x3fffffff
+};
+
+
+// inserts the huffman code of one character into teh buffer
+static void put_code2buff(unsigned char* buff, int& bitpos, unsigned char code){
+ int code_len = huffman_code_length[code];
+ int bitpos_in_octet = bitpos%8;
+
+ // moves to the first bit of the huffman code to the insertion point
+ int shift= (16-bitpos_in_octet-(code_len%8))%8;
+ uint64_t ins_val= ((uint64_t)huffman_code_values[code]) << shift;
+
+
+ buff+= bitpos/8;
+ for(int i=((code_len+shift+7)/8)-1;i>=0;i--) {
+ if(i==0){
+ buff[i] |= (ins_val & 0xFF);
+ } else {
+ buff[i] = (ins_val & 0xFF);
+ }
+ ins_val >>= 8;
+ }
+ bitpos+=code_len;
+}
+
+static const unsigned char get_mask_table[]={
+0x80, 0x40, 0x20, 0x10,
+0x08, 0x04, 0x02, 0x01
+};
+
+static int get_onebit(const unsigned char* buff, int& bitpos){
+ if(buff[bitpos/8] & get_mask_table[bitpos%8]){
+ bitpos++;
+ return 1;
+ }
+ bitpos++;
+ return 0;
+}
+
+// return -1 or the char code or the EOF (256)
+static int decompress_one_char(const unsigned char* buff, int& bitpos, int length /*in bits*/ ){
+ unsigned int huffman_val=0;
+
+ if((bitpos+5)>length){
+ while(bitpos<length){
+ if(get_onebit(buff,bitpos)!=1) {return -1;} // incomplete code
+ }
+ return 256; //EOF
+ }
+
+ // get the first 5 bit, the minimum code length is 5
+ for(int i=0;i<5;i++){
+ huffman_val<<=1;
+ huffman_val+=get_onebit(buff,bitpos);
+ }
+ // Check the 5 bit codes
+ // See RFC7541 for magic values
+ switch(huffman_val){
+ case 0x0:
+ return 48;
+ case 0x1:
+ return 49;
+ case 0x2:
+ return 50;
+ case 0x3:
+ return 97;
+ case 0x4:
+ return 99;
+ case 0x5:
+ return 101;
+ case 0x6:
+ return 105;
+ case 0x7:
+ return 111;
+ case 0x8:
+ return 115;
+ case 0x9:
+ return 116;
+ }
+
+ if(bitpos==length){ // no more bits
+ if(huffman_val == 0x1f){ // all bit is 1
+ return 256; //EOF
+ } else {
+ return -1; // invalid code
+ }
+ }
+
+ // 6 bit codes
+ huffman_val<<=1;
+ huffman_val+=get_onebit(buff,bitpos);
+
+ switch(huffman_val){
+ case 0x14:
+ return 32;
+ case 0x15:
+ return 37;
+ case 0x16:
+ return 45;
+ case 0x17:
+ return 46;
+ case 0x18:
+ return 47;
+ case 0x19:
+ return 51;
+ case 0x1a:
+ return 52;
+ case 0x1b:
+ return 53;
+ case 0x1c:
+ return 54;
+ case 0x1d:
+ return 55;
+ case 0x1e:
+ return 56;
+ case 0x1f:
+ return 57;
+ case 0x20:
+ return 61;
+ case 0x21:
+ return 65;
+ case 0x22:
+ return 95;
+ case 0x23:
+ return 98;
+ case 0x24:
+ return 100;
+ case 0x25:
+ return 102;
+ case 0x26:
+ return 103;
+ case 0x27:
+ return 104;
+ case 0x28:
+ return 108;
+ case 0x29:
+ return 109;
+ case 0x2a:
+ return 110;
+ case 0x2b:
+ return 112;
+ case 0x2c:
+ return 114;
+ case 0x2d:
+ return 117;
+ }
+
+ if(bitpos==length){ // no more bits
+ if(huffman_val == 0x3f){ // all bit is 1
+ return 256; //EOF
+ } else {
+ return -1; // invalid code
+ }
+ }
+
+ // 7 bit codes
+ huffman_val<<=1;
+ huffman_val+=get_onebit(buff,bitpos);
+ switch(huffman_val){
+ case 0x5c:
+ return 58;
+ case 0x5d:
+ return 66;
+ case 0x5e:
+ return 67;
+ case 0x5f:
+ return 68;
+ case 0x60:
+ return 69;
+ case 0x61:
+ return 70;
+ case 0x62:
+ return 71;
+ case 0x63:
+ return 72;
+ case 0x64:
+ return 73;
+ case 0x65:
+ return 74;
+ case 0x66:
+ return 75;
+ case 0x67:
+ return 76;
+ case 0x68:
+ return 77;
+ case 0x69:
+ return 78;
+ case 0x6a:
+ return 79;
+ case 0x6b:
+ return 80;
+ case 0x6c:
+ return 81;
+ case 0x6d:
+ return 82;
+ case 0x6e:
+ return 83;
+ case 0x6f:
+ return 84;
+ case 0x70:
+ return 85;
+ case 0x71:
+ return 86;
+ case 0x72:
+ return 87;
+ case 0x73:
+ return 89;
+ case 0x74:
+ return 106;
+ case 0x75:
+ return 107;
+ case 0x76:
+ return 113;
+ case 0x77:
+ return 118;
+ case 0x78:
+ return 119;
+ case 0x79:
+ return 120;
+ case 0x7a:
+ return 121;
+ case 0x7b:
+ return 122;
+ }
+
+ if(bitpos==length){ // no more bits
+ if(huffman_val == 0x7f){ // all bit is 1
+ return 256; //EOF
+ } else {
+ return -1; // invalid code
+ }
+ }
+
+ // 8bit codes
+ huffman_val<<=1;
+ huffman_val+=get_onebit(buff,bitpos);
+ switch(huffman_val){
+ case 0xf8:
+ return 38;
+ case 0xf9:
+ return 42;
+ case 0xfa:
+ return 44;
+ case 0xfb:
+ return 59;
+ case 0xfc:
+ return 88;
+ case 0xfd:
+ return 90;
+ }
+
+ if(bitpos==length){ // no more bits
+ return -1; // invalid code
+ }
+ huffman_val<<=1;
+ huffman_val+=get_onebit(buff,bitpos);
+ if(bitpos==length){ // no more bits
+ return -1; // invalid code
+ }
+ huffman_val<<=1;
+ huffman_val+=get_onebit(buff,bitpos);
+ // 10bit codes
+ switch(huffman_val){
+ case 0x3f8:
+ return 33;
+ case 0x3f9:
+ return 34;
+ case 0x3fa:
+ return 40;
+ case 0x3fb:
+ return 41;
+ case 0x3fc:
+ return 63;
+ }
+
+ if(bitpos==length){ // no more bits
+ return -1; // invalid code
+ }
+ huffman_val<<=1;
+ huffman_val+=get_onebit(buff,bitpos);
+ // 11bit codes
+ switch(huffman_val){
+ case 0x7fa:
+ return 39;
+ case 0x7fb:
+ return 43;
+ case 0x7fc:
+ return 124;
+ }
+
+ if(bitpos==length){ // no more bits
+ return -1; // invalid code
+ }
+ huffman_val<<=1;
+ huffman_val+=get_onebit(buff,bitpos);
+ // 12bit codes
+
+ switch(huffman_val){
+ case 0xffa:
+ return 35;
+ case 0xffb:
+ return 62;
+ }
+
+ if(bitpos==length){ // no more bits
+ return -1; // invalid code
+ }
+ huffman_val<<=1;
+ huffman_val+=get_onebit(buff,bitpos);
+ // 13bit codes
+
+ switch(huffman_val){
+ case 0x1ff8:
+ return 0;
+ case 0x1ff9:
+ return 36;
+ case 0x1ffa:
+ return 64;
+ case 0x1ffb:
+ return 91;
+ case 0x1ffc:
+ return 93;
+ case 0x1ffd:
+ return 126;
+ }
+
+ if(bitpos==length){ // no more bits
+ return -1; // invalid code
+ }
+ huffman_val<<=1;
+ huffman_val+=get_onebit(buff,bitpos);
+ // 14bit codes
+ switch(huffman_val){
+ case 0x3ffc:
+ return 94;
+ case 0x3ffd:
+ return 125;
+ }
+
+ if(bitpos==length){ // no more bits
+ return -1; // invalid code
+ }
+ huffman_val<<=1;
+ huffman_val+=get_onebit(buff,bitpos);
+ // 15bit codes
+ switch(huffman_val){
+ case 0x7ffc:
+ return 60;
+ case 0x7ffd:
+ return 96;
+ case 0x7ffe:
+ return 123;
+ }
+ if(bitpos==length){ // no more bits
+ return -1; // invalid code
+ }
+ huffman_val<<=1;
+ huffman_val+=get_onebit(buff,bitpos);
+ if(bitpos==length){ // no more bits
+ return -1; // invalid code
+ }
+ huffman_val<<=1;
+ huffman_val+=get_onebit(buff,bitpos);
+ if(bitpos==length){ // no more bits
+ return -1; // invalid code
+ }
+ huffman_val<<=1;
+ huffman_val+=get_onebit(buff,bitpos);
+ if(bitpos==length){ // no more bits
+ return -1; // invalid code
+ }
+ huffman_val<<=1;
+ huffman_val+=get_onebit(buff,bitpos);
+ // 19bit codes
+ switch(huffman_val){
+ case 0x7fff0:
+ return 92;
+ case 0x7fff1:
+ return 195;
+ case 0x7ff2:
+ return 208;
+ }
+
+ if(bitpos==length){ // no more bits
+ return -1; // invalid code
+ }
+ huffman_val<<=1;
+ huffman_val+=get_onebit(buff,bitpos);
+ // 20bit codes
+ switch(huffman_val){
+ case 0xfffe6:
+ return 128;
+ case 0xfffe7:
+ return 130;
+ case 0xfffe8:
+ return 131;
+ case 0xfffe9:
+ return 162;
+ case 0xfffea:
+ return 184;
+ case 0xfffeb:
+ return 194;
+ case 0xfffec:
+ return 224;
+ case 0xfffed:
+ return 226;
+ }
+
+ if(bitpos==length){ // no more bits
+ return -1; // invalid code
+ }
+ huffman_val<<=1;
+ huffman_val+=get_onebit(buff,bitpos);
+ // 21bit codes
+ switch(huffman_val){
+ case 0x1fffdc:
+ return 153;
+ case 0x1fffdd:
+ return 161;
+ case 0x1fffde:
+ return 167;
+ case 0x1fffdf:
+ return 172;
+ case 0x1fffe0:
+ return 176;
+ case 0x1fffe1:
+ return 177;
+ case 0x1fffe2:
+ return 179;
+ case 0x1fffe3:
+ return 209;
+ case 0x1fffe4:
+ return 216;
+ case 0x1fffe5:
+ return 217;
+ case 0x1fffe6:
+ return 227;
+ case 0x1fffe7:
+ return 229;
+ case 0x1fffe8:
+ return 230;
+ }
+
+ if(bitpos==length){ // no more bits
+ return -1; // invalid code
+ }
+ huffman_val<<=1;
+ huffman_val+=get_onebit(buff,bitpos);
+ // 22bit codes
+ switch(huffman_val){
+ case 0x3fffd2:
+ return 129;
+ case 0x3fffd3:
+ return 132;
+ case 0x3fffd4:
+ return 133;
+ case 0x3fffd5:
+ return 134;
+ case 0x3fffd6:
+ return 136;
+ case 0x3fffd7:
+ return 146;
+ case 0x3fffd8:
+ return 154;
+ case 0x3fffd9:
+ return 156;
+ case 0x3fffda:
+ return 160;
+ case 0x3fffdb:
+ return 163;
+ case 0x3fffdc:
+ return 164;
+ case 0x3fffdd:
+ return 169;
+ case 0x3fffde:
+ return 170;
+ case 0x3fffdf:
+ return 173;
+ case 0x3fffe0:
+ return 178;
+ case 0x3fffe1:
+ return 181;
+ case 0x3fffe2:
+ return 185;
+ case 0x3fffe3:
+ return 186;
+ case 0x3fffe4:
+ return 187;
+ case 0x3fffe5:
+ return 189;
+ case 0x3fffe6:
+ return 190;
+ case 0x3fffe7:
+ return 196;
+ case 0x3fffe8:
+ return 198;
+ case 0x3fffe9:
+ return 228;
+ case 0x3fffea:
+ return 232;
+ case 0x3fffeb:
+ return 233;
+ }
+
+ if(bitpos==length){ // no more bits
+ return -1; // invalid code
+ }
+ huffman_val<<=1;
+ huffman_val+=get_onebit(buff,bitpos);
+ // 23bit codes
+ switch(huffman_val){
+ case 0x7fffd8:
+ return 1;
+ case 0x7fffd9:
+ return 135;
+ case 0x7fffda:
+ return 137;
+ case 0x7fffdb:
+ return 138;
+ case 0x7fffdc:
+ return 139;
+ case 0x7fffdd:
+ return 140;
+ case 0x7fffde:
+ return 141;
+ case 0x7fffdf:
+ return 143;
+ case 0x7fffe0:
+ return 147;
+ case 0x7fffe1:
+ return 149;
+ case 0x7fffe2:
+ return 150;
+ case 0x7fffe3:
+ return 151;
+ case 0x7fffe4:
+ return 152;
+ case 0x7fffe5:
+ return 155;
+ case 0x7fffe6:
+ return 157;
+ case 0x7fffe7:
+ return 158;
+ case 0x7fffe8:
+ return 165;
+ case 0x7fffe9:
+ return 166;
+ case 0x7fffea:
+ return 168;
+ case 0x7fffeb:
+ return 174;
+ case 0x7fffec:
+ return 175;
+ case 0x7fffed:
+ return 180;
+ case 0x7fffee:
+ return 182;
+ case 0x7fffef:
+ return 183;
+ case 0x7ffff0:
+ return 188;
+ case 0x7ffff1:
+ return 191;
+ case 0x7ffff2:
+ return 197;
+ case 0x7ffff3:
+ return 231;
+ case 0x7ffff4:
+ return 239;
+ }
+
+ if(bitpos==length){ // no more bits
+ return -1; // invalid code
+ }
+ huffman_val<<=1;
+ huffman_val+=get_onebit(buff,bitpos);
+ // 24bit codes
+ switch(huffman_val){
+ case 0xffffea:
+ return 9;
+ case 0xffffeb:
+ return 142;
+ case 0xffffec:
+ return 144;
+ case 0xffffed:
+ return 145;
+ case 0xffffee:
+ return 148;
+ case 0xffffef:
+ return 159;
+ case 0xfffff0:
+ return 171;
+ case 0xfffff1:
+ return 206;
+ case 0xfffff2:
+ return 215;
+ case 0xfffff3:
+ return 225;
+ case 0xfffff4:
+ return 236;
+ case 0xfffff5:
+ return 237;
+ }
+
+ if(bitpos==length){ // no more bits
+ return -1; // invalid code
+ }
+ huffman_val<<=1;
+ huffman_val+=get_onebit(buff,bitpos);
+ // 25bit codes
+ switch(huffman_val){
+ case 0x1ffffec:
+ return 199;
+ case 0x1ffffed:
+ return 207;
+ case 0x1ffffee:
+ return 234;
+ case 0x1ffffef:
+ return 235;
+ }
+
+ if(bitpos==length){ // no more bits
+ return -1; // invalid code
+ }
+ huffman_val<<=1;
+ huffman_val+=get_onebit(buff,bitpos);
+ // 26bit codes
+ switch(huffman_val){
+ case 0x3ffffe0:
+ return 192;
+ case 0x3ffffe1:
+ return 193;
+ case 0x3ffffe2:
+ return 200;
+ case 0x3ffffe3:
+ return 201;
+ case 0x3ffffe4:
+ return 202;
+ case 0x3ffffe5:
+ return 205;
+ case 0x3ffffe6:
+ return 210;
+ case 0x3ffffe7:
+ return 213;
+ case 0x3ffffe8:
+ return 218;
+ case 0x3ffffe9:
+ return 219;
+ case 0x3ffffea:
+ return 238;
+ case 0x3ffffeb:
+ return 240;
+ case 0x3ffffec:
+ return 242;
+ case 0x3ffffed:
+ return 243;
+ case 0x3ffffee:
+ return 255;
+ }
+
+ if(bitpos==length){ // no more bits
+ return -1; // invalid code
+ }
+ huffman_val<<=1;
+ huffman_val+=get_onebit(buff,bitpos);
+ // 27bit codes
+ switch(huffman_val){
+ case 0x3ffffde:
+ return 203;
+ case 0x3ffffdf:
+ return 204;
+ case 0x3ffffe0:
+ return 211;
+ case 0x3ffffe1:
+ return 212;
+ case 0x3ffffe2:
+ return 214;
+ case 0x3ffffe3:
+ return 221;
+ case 0x3ffffe4:
+ return 222;
+ case 0x3ffffe5:
+ return 223;
+ case 0x3ffffe6:
+ return 241;
+ case 0x3ffffe7:
+ return 244;
+ case 0x3ffffe8:
+ return 245;
+ case 0x3ffffe9:
+ return 246;
+ case 0x3ffffea:
+ return 247;
+ case 0x3ffffeb:
+ return 248;
+ case 0x3ffffec:
+ return 250;
+ case 0x3ffffed:
+ return 251;
+ case 0x3ffffee:
+ return 252;
+ case 0x3ffffef:
+ return 253;
+ case 0x3fffff0:
+ return 254;
+ }
+
+ if(bitpos==length){ // no more bits
+ return -1; // invalid code
+ }
+ huffman_val<<=1;
+ huffman_val+=get_onebit(buff,bitpos);
+ // 28bit codes
+ switch(huffman_val){
+ case 0xfffffe2:
+ return 2;
+ case 0xfffffe3:
+ return 3;
+ case 0xfffffe4:
+ return 4;
+ case 0xfffffe5:
+ return 5;
+ case 0xfffffe6:
+ return 6;
+ case 0xfffffe7:
+ return 7;
+ case 0xfffffe8:
+ return 8;
+ case 0xfffffe9:
+ return 11;
+ case 0xfffffea:
+ return 12;
+ case 0xfffffeb:
+ return 14;
+ case 0xfffffec:
+ return 15;
+ case 0xfffffed:
+ return 16;
+ case 0xfffffee:
+ return 17;
+ case 0xfffffef:
+ return 18;
+ case 0xffffff0:
+ return 19;
+ case 0xffffff1:
+ return 20;
+ case 0xffffff2:
+ return 21;
+ case 0xffffff3:
+ return 23;
+ case 0xffffff4:
+ return 24;
+ case 0xffffff5:
+ return 25;
+ case 0xffffff6:
+ return 26;
+ case 0xffffff7:
+ return 27;
+ case 0xffffff8:
+ return 28;
+ case 0xffffff9:
+ return 29;
+ case 0xffffffa:
+ return 30;
+ case 0xffffffb:
+ return 31;
+ case 0xffffffc:
+ return 127;
+ case 0xffffffd:
+ return 220;
+ case 0xffffffe:
+ return 249;
+ }
+ if(bitpos==length){ // no more bits
+ return -1; // invalid code
+ }
+ huffman_val<<=1;
+ huffman_val+=get_onebit(buff,bitpos);
+
+ if(bitpos==length){ // no more bits
+ return -1; // invalid code
+ }
+ huffman_val<<=1;
+ huffman_val+=get_onebit(buff,bitpos);
+ // 30bit codes
+ switch(huffman_val){
+ case 0x3ffffffc:
+ return 10;
+ case 0x3ffffffd:
+ return 13;
+ case 0x3ffffffe:
+ return 22;
+ case 0x3fffffff:
+ return 256;
+ }
+
+return -1;
+}
+
+static const unsigned char mask_table[]={
+0xff, 0x7f, 0x3f, 0x1f,
+0x0f, 0x07, 0x03, 0x01
+};
+
+static OCTETSTRING enc_huff(const OCTETSTRING& pl__stream){
+ int enc_len=0;
+ const unsigned char* ptr=(const unsigned char*)pl__stream;
+ for(int i=0;i<pl__stream.lengthof();i++){
+ enc_len+=huffman_code_length[ptr[i]];
+ }
+ enc_len=(enc_len+7)/8;
+
+ unsigned char* res=(unsigned char*)Malloc(enc_len*sizeof(unsigned char));
+ memset(res,0,enc_len);
+
+ int bitpos=0;
+ for(int i=0;i<pl__stream.lengthof();i++){
+ put_code2buff(res,bitpos,ptr[i]);
+ }
+
+ if(bitpos%8){
+ res[bitpos/8]|=mask_table[bitpos%8];
+ }
+ OCTETSTRING ret_val=OCTETSTRING(enc_len,res);
+ Free(res);
+ return ret_val;
+}
+
+static OCTETSTRING dec_huff(const OCTETSTRING& pl__stream){
+ int bitpos=0;
+ int len=pl__stream.lengthof()*8;
+ const unsigned char* ptr=(const unsigned char*)pl__stream;
+
+ OCTETSTRING ret_val=OCTETSTRING(0,NULL);
+ int res=decompress_one_char(ptr,bitpos,len);
+ while( (res!=-1) && (res!=256) ){
+ ret_val = ret_val + int2oct(res,1);
+ res=decompress_one_char(ptr,bitpos,len);
+ }
+ return ret_val;
+}
+
+// Encode the string according to the RFC7541 5.2
+static OCTETSTRING enc_http2_string(const OCTETSTRING& pl__stream, const int use_huffman){
+ unsigned char len_field[6];
+
+ OCTETSTRING str= use_huffman?enc_huff(pl__stream):pl__stream;
+
+ int len_len= encode_integer(len_field,str.lengthof(),7,use_huffman?0x80:0);
+
+ return OCTETSTRING(len_len,len_field) + str;
+
+}
+
+static int dec_http2_string(const unsigned char* ptr, int ptr_len, OCTETSTRING& pl__stream){
+ uint32_t str_len=0;
+ unsigned char huff=0;
+ int len_len=decode_integer(ptr,str_len,7,huff);
+ ptr+=len_len;
+ if(ptr_len<len_len+(int)str_len){
+ return -1;
+ }
+
+ pl__stream=huff?dec_huff(OCTETSTRING(str_len,ptr)):OCTETSTRING(str_len,ptr);
+ return len_len+str_len;
+}
+
+static HTTP2_compression_ctxs* get_ptr(const INTEGER& val){
+ return (HTTP2_compression_ctxs*)(val.get_long_long_val());
+}
+
+static OCTETSTRING HTTP2_encode_one_header(const CHARSTRING& hname, const CHARSTRING& hval, HTTP2_compression_ctx* comp_ctx){
+
+ // first search in the dynamic table
+ OCTETSTRING ret_val=OCTETSTRING(0,NULL);
+ unsigned char int_encode_buff[6];
+
+ int idx=comp_ctx->find(hname,hval);
+ int idx_offset=61; // size of the fixed table
+
+ if(idx==-1){ // not found it
+ // check the fixed table
+ idx=HTTP2_static_table.ctx.find(hname,hval);
+ idx_offset=0;
+ }
+ int idx_len=0;
+ if(idx>0){ // found it
+ idx_len=encode_integer(int_encode_buff,idx+idx_offset,7,0x80);
+ return OCTETSTRING(idx_len,int_encode_buff);
+ }
+
+ // not found, lets check for the header name
+ idx_offset=61;
+ comp_ctx->find(hname);
+ if(idx==-1){ // not found it
+ // check the fixed table
+ idx=HTTP2_static_table.ctx.find(hname);
+ idx_offset=0;
+ }
+
+ int can_be_added=((32+hname.lengthof()+hval.lengthof())>(comp_ctx->h_table_max_size))?0:1; // Do not add if the header size is more than the max table size
+
+ if(idx>0){ // found it
+ if(can_be_added){
+ idx_len=encode_integer(int_encode_buff,idx+idx_offset,6,0x40);
+ ret_val=OCTETSTRING(idx_len,int_encode_buff);
+ } else {
+ idx_len=encode_integer(int_encode_buff,idx+idx_offset,4,0x00);
+ ret_val=OCTETSTRING(idx_len,int_encode_buff);
+ }
+ ret_val=ret_val+enc_http2_string(char2oct(hval),1);
+ } else {
+ if(can_be_added){
+ idx_len=encode_integer(int_encode_buff,0,6,0x40);
+ ret_val=OCTETSTRING(idx_len,int_encode_buff);
+ } else {
+ idx_len=encode_integer(int_encode_buff,0,4,0x00);
+ ret_val=OCTETSTRING(idx_len,int_encode_buff);
+ }
+ ret_val=ret_val+enc_http2_string(char2oct(hname),1);
+ ret_val=ret_val+enc_http2_string(char2oct(hval),1);
+ }
+
+ if(can_be_added){
+ comp_ctx->add_hdr(hname,hval);
+ }
+
+ return ret_val;
+}
+
+static int HTTP2_decode_one_header(const unsigned char* buff, int buff_len, CHARSTRING& hname, CHARSTRING& hval, HTTP2_compression_ctx* comp_ctx){
+ if(buff_len<1){
+ return -1; //not enough data
+ }
+
+ int ret_val=0;
+ uint32_t idx=0;
+
+ if((buff[0] & 0xE0)== 0x20){ // Dynamic Table Size Update
+ unsigned char filler;
+ ret_val=decode_integer(buff,idx,5,filler);
+ if(ret_val>buff_len){
+ return -1;
+ }
+
+ comp_ctx->set_max_size(idx);
+//printf("Dynamic Table Size Update %d\r\n", idx);
+ return ret_val;
+
+ }
+
+ if(buff[0] & 0x80){ // indexed field representation
+ unsigned char filler;
+ ret_val=decode_integer(buff,idx,7,filler);
+//printf("indexed field representation %d\r\n", idx);
+
+ if(ret_val>buff_len){
+ return -1;
+ }
+
+ if(idx==0){
+ // invalid value
+ return -1;
+ }
+
+ if(idx<62){
+ hname=HTTP2_static_table.ctx[idx]->name;
+ hval=HTTP2_static_table.ctx[idx]->value;
+ } else {
+ idx-=61;
+ const HTTP2_hdr_data* d=((*comp_ctx)[idx]);
+ if(d==NULL){
+ return -1;
+ }
+ hname=d->name;
+ hval=d->value;
+ }
+ return ret_val;
+ }
+
+ int add_hdr=0;
+
+ if((buff[0] & 0xC0)== 0x40){ // Literal Header Field with Incremental Indexing
+ add_hdr=1;
+ unsigned char filler;
+ ret_val=decode_integer(buff,idx,6,filler);
+//printf("Literal Header Field with Incremental Indexing %d\r\n", idx);
+ } else if(((buff[0] & 0xF0)== 0x10) || ((buff[0] & 0xF0)== 0x00)){ // Literal Header Field without Indexing
+ unsigned char filler;
+ ret_val=decode_integer(buff,idx,4,filler);
+//printf("Literal Header Field withot Indexing %d %x\r\n", idx,buff[0]);
+ } else {
+ // not possible
+ return -1;
+ }
+ if(ret_val>buff_len){
+ return -1;
+ }
+
+ buff+=ret_val; // skip the index
+
+ if(idx!=0){ // indexed header name
+ if(idx<62){
+ hname=HTTP2_static_table.ctx[idx]->name;
+ } else {
+ idx-=61;
+ const HTTP2_hdr_data* d=((*comp_ctx)[idx]);
+ if(d==NULL){
+ return -1;
+ }
+ hname=d->name;
+ }
+ } else { // new header name
+ OCTETSTRING str;
+ int str_len=dec_http2_string(buff,buff_len-ret_val,str);
+ if(str_len==-1){
+ return -1;
+ }
+ buff+=str_len;
+ ret_val+=str_len;
+ hname=CHARSTRING(str.lengthof(),(const char*)(const unsigned char*)str);
+ }
+
+ OCTETSTRING str;
+ int str_len=dec_http2_string(buff,buff_len-ret_val,str);
+ if(str_len==-1){
+ return -1;
+ }
+
+ buff+=str_len;
+ ret_val+=str_len;
+ hval=CHARSTRING(str.lengthof(),(const char*)(const unsigned char*)str);
+
+ if(add_hdr){
+ comp_ctx->add_hdr(hname,hval);
+ }
+
+ return ret_val;
+
+}
+namespace HTTP2__Types {
+
+
+HTTP2__comp__context HTTP2__comp__context__init( const INTEGER& h__table__size__local ,
+ const INTEGER& h__table__size__remote){
+
+ HTTP2_compression_ctxs* ctx=new HTTP2_compression_ctxs;
+ ctx->local.set_max_size(h__table__size__local);
+ ctx->remote.set_max_size(h__table__size__remote);
+
+ HTTP2__comp__context ret_val;
+ ret_val.internal__id1().set_long_long_val((long long int)ctx);
+ return ret_val;
+}
+
+void HTTP2__comp__context__free(HTTP2__Types::HTTP2__comp__context& ctx){
+ delete get_ptr(ctx.internal__id1());
+ ctx.internal__id1()=0;
+}
+
+void HTTP2__comp__context__set__table__size__remote(HTTP2__Types::HTTP2__comp__context& ctx, const INTEGER& new_size){
+ HTTP2_compression_ctxs* c=get_ptr(ctx.internal__id1());
+ c->remote.set_max_size(new_size);
+}
+
+void HTTP2__comp__context__set__table__size__local(HTTP2__Types::HTTP2__comp__context& ctx, const INTEGER& new_size){
+ HTTP2_compression_ctxs* c=get_ptr(ctx.internal__id1());
+ c->local.set_max_size(new_size);
+}
+
+OCTETSTRING encode_prio(const HTTP2__Priority__data& p_data){
+ return bit2oct(int2bit(p_data.exclusive__flag()?1:0,1)+int2bit(p_data.stream__dependency(),31))+int2oct(p_data.weight(),1);
+}
+
+
+OCTETSTRING enc__huff(const OCTETSTRING& pl__stream){
+ return enc_huff(pl__stream);
+}
+
+OCTETSTRING dec__huff(const OCTETSTRING& pl__stream){
+ return dec_huff(pl__stream);
+}
+
+INTEGER HTTP2__comp__context__encode(HTTP2__comp__context& pl_context, const HTTP2__header__block& pl_hblock, OCTETSTRING& pl_frame_data){
+
+ HTTP2_compression_ctxs* ctx=get_ptr(pl_context.internal__id1());
+ pl_frame_data= OCTETSTRING(0,NULL);
+
+ if(pl_hblock.pseudo__headers().ispresent()){
+ if(pl_hblock.pseudo__headers()().method().ispresent()){
+ pl_frame_data= pl_frame_data+HTTP2_encode_one_header(":method",pl_hblock.pseudo__headers()().method()(),&ctx->local);
+ }
+ if(pl_hblock.pseudo__headers()().authority().ispresent()){
+ pl_frame_data= pl_frame_data+HTTP2_encode_one_header(":authority",pl_hblock.pseudo__headers()().authority()(),&ctx->local);
+ }
+ if(pl_hblock.pseudo__headers()().scheme().ispresent()){
+ pl_frame_data= pl_frame_data+HTTP2_encode_one_header(":scheme",pl_hblock.pseudo__headers()().scheme()(),&ctx->local);
+ }
+ if(pl_hblock.pseudo__headers()().path().ispresent()){
+ pl_frame_data= pl_frame_data+HTTP2_encode_one_header(":path",pl_hblock.pseudo__headers()().path()(),&ctx->local);
+ }
+ if(pl_hblock.pseudo__headers()().status().ispresent()){
+ pl_frame_data= pl_frame_data+HTTP2_encode_one_header(":status",int2str(pl_hblock.pseudo__headers()().status()()),&ctx->local);
+ }
+ }
+
+ if(pl_hblock.headers().ispresent()){
+ for(int i=0;i<pl_hblock.headers()().lengthof();i++){
+ pl_frame_data= pl_frame_data+HTTP2_encode_one_header(pl_hblock.headers()()[i].header__name(),
+ pl_hblock.headers()()[i].header__value().ispresent()?pl_hblock.headers()()[i].header__value()():"",&ctx->local);
+ }
+
+ }
+
+ return 0;
+}
+
+INTEGER HTTP2__comp__context__decode(HTTP2__Types::HTTP2__comp__context& pl_context, HTTP2__Types::HTTP2__header__block& pl_hblock, const OCTETSTRING& pl_stream){
+
+ const unsigned char* ptr=(const unsigned char*)pl_stream;
+ int ptr_len=pl_stream.lengthof();
+ HTTP2_compression_ctxs* ctx=get_ptr(pl_context.internal__id1());
+
+ pl_hblock.pseudo__headers()=OMIT_VALUE;
+ pl_hblock.headers()=OMIT_VALUE;
+
+ while(ptr_len>0){
+ CHARSTRING hname="";
+ CHARSTRING hval="";
+ int hlen =-1;
+ hlen=HTTP2_decode_one_header(ptr,ptr_len,hname, hval, &(ctx->remote));
+ if(hlen==-1){
+ return 1;
+ }
+printf("decoded header len %d %s %s\r\n",hlen,(const char*)hname,(const char*)hval);
+ if(hname==":method"){
+ if(!pl_hblock.pseudo__headers().ispresent()) pl_hblock.pseudo__headers()() = HTTP2__pseudo__headers(OMIT_VALUE,OMIT_VALUE,OMIT_VALUE,OMIT_VALUE,OMIT_VALUE);
+ pl_hblock.pseudo__headers()().method()=hval;
+ } else if(hname==":scheme") {
+ if(!pl_hblock.pseudo__headers().ispresent()) pl_hblock.pseudo__headers()() = HTTP2__pseudo__headers(OMIT_VALUE,OMIT_VALUE,OMIT_VALUE,OMIT_VALUE,OMIT_VALUE);
+ pl_hblock.pseudo__headers()().scheme()=hval;
+ } else if(hname==":authority") {
+ if(!pl_hblock.pseudo__headers().ispresent()) pl_hblock.pseudo__headers()() = HTTP2__pseudo__headers(OMIT_VALUE,OMIT_VALUE,OMIT_VALUE,OMIT_VALUE,OMIT_VALUE);
+ pl_hblock.pseudo__headers()().authority()=hval;
+ } else if(hname==":path") {
+ if(!pl_hblock.pseudo__headers().ispresent()) pl_hblock.pseudo__headers()() = HTTP2__pseudo__headers(OMIT_VALUE,OMIT_VALUE,OMIT_VALUE,OMIT_VALUE,OMIT_VALUE);
+ pl_hblock.pseudo__headers()().path()=hval;
+ } else if(hname==":status") {
+ if(!pl_hblock.pseudo__headers().ispresent()) pl_hblock.pseudo__headers()() = HTTP2__pseudo__headers(OMIT_VALUE,OMIT_VALUE,OMIT_VALUE,OMIT_VALUE,OMIT_VALUE);
+ pl_hblock.pseudo__headers()().status()=str2int(hval);
+ } else {
+ if(!pl_hblock.headers().ispresent()) pl_hblock.headers()() = NULL_VALUE;
+ pl_hblock.headers()()[pl_hblock.headers()().lengthof()]=HTTP2__header__field(hname,hval);
+
+ }
+ ptr+=hlen;
+ ptr_len-=hlen;
+
+
+ }
+
+ return 0;
+}
+
+OCTETSTRING f__HTTP2__encode__frame(const HTTP2__Frame& pl__frame){
+
+ unsigned char flags=0;
+
+ OCTETSTRING ret_val=OCTETSTRING(0,NULL);
+
+ switch(pl__frame.get_selection()){
+ case HTTP2__Frame::ALT_data__frame:
+ if(pl__frame.data__frame().end__stream__flag()){
+ flags|=0x01;
+ }
+ if(pl__frame.data__frame().padding().ispresent()){
+ flags|=0x08;
+ }
+ ret_val=int2oct(0,1) // Type: DATA frames (type=0x0)
+ + int2oct(flags,1)
+ + int2oct(pl__frame.data__frame().stream__id(),4);
+
+ if(pl__frame.data__frame().padding().ispresent()){
+ ret_val=ret_val+int2oct(pl__frame.data__frame().padding()().lengthof(),1);
+ }
+ ret_val=ret_val+pl__frame.data__frame().data();
+ if(pl__frame.data__frame().padding().ispresent()){
+ ret_val=ret_val+pl__frame.data__frame().padding()();
+ }
+
+ break;
+ case HTTP2__Frame::ALT_header__frame:
+ if(pl__frame.header__frame().end__stream__flag()){
+ flags|=0x01;
+ }
+ if(pl__frame.header__frame().end__header__flag()){
+ flags|=0x04;
+ }
+ if(pl__frame.header__frame().padding().ispresent()){
+ flags|=0x08;
+ }
+ if(pl__frame.header__frame().priority__data().ispresent()){
+ flags|=0x20;
+ }
+ ret_val=int2oct(0x1,1) // Type: HEADERS frame (type=0x1)
+ + int2oct(flags,1)
+ + int2oct(pl__frame.header__frame().stream__id(),4);
+
+ if(pl__frame.header__frame().padding().ispresent()){
+ ret_val=ret_val+int2oct(pl__frame.header__frame().padding()().lengthof(),1);
+ }
+
+ if(pl__frame.header__frame().priority__data().ispresent()){
+ ret_val=ret_val+encode_prio(pl__frame.header__frame().priority__data()());
+ }
+ ret_val=ret_val+pl__frame.header__frame().header__block__fragment();
+
+ if(pl__frame.header__frame().padding().ispresent()){
+ ret_val=ret_val+pl__frame.header__frame().padding()();
+ }
+
+
+ break;
+ case HTTP2__Frame::ALT_priority__frame:
+ ret_val=int2oct(0x2,1) // Type: PRIORITY frame (type=0x2)
+ + int2oct(flags,1)
+ + int2oct(pl__frame.priority__frame().stream__id(),4);
+ ret_val=ret_val+encode_prio(pl__frame.priority__frame().priority__data());
+
+
+ break;
+ case HTTP2__Frame::ALT_rst__frame:
+ ret_val=int2oct(0x3,1) // Type: RST_STREAM frame (type=0x3)
+ + int2oct(flags,1)
+ + int2oct(pl__frame.rst__frame().stream__id(),4)
+ + int2oct(pl__frame.rst__frame().error__code(),4);
+
+ break;
+ case HTTP2__Frame::ALT_settings__frame:
+ if(pl__frame.settings__frame().ack__flag()){
+ flags|=0x01;
+ }
+ ret_val=int2oct(0x4,1) // Type: SETTINGS frame (type=0x4)
+ + int2oct(flags,1)
+ + int2oct(0,4); // The stream identifier for a SETTINGS frame MUST be zero
+
+ if(pl__frame.settings__frame().settings().ispresent()){
+ for(int i=0;i<pl__frame.settings__frame().settings()().lengthof();i++){
+ ret_val=ret_val+int2oct(pl__frame.settings__frame().settings()()[i].setting__id(),2)+int2oct(pl__frame.settings__frame().settings()()[i].setting__value(),4);
+ }
+ }
+ break;
+ case HTTP2__Frame::ALT_push__promise__frame:
+ if(pl__frame.push__promise__frame().end__header__flag()){
+ flags|=0x04;
+ }
+ if(pl__frame.push__promise__frame().padding().ispresent()){
+ flags|=0x08;
+ }
+ ret_val=int2oct(0x5,1) // Type: PUSH_PROMISE frame (type=0x5)
+ + int2oct(flags,1)
+ + int2oct(pl__frame.push__promise__frame().stream__id(),4);
+
+ if(pl__frame.push__promise__frame().padding().ispresent()){
+ ret_val=ret_val+int2oct(pl__frame.push__promise__frame().padding()().lengthof(),1);
+ }
+
+ ret_val=ret_val+int2oct(pl__frame.push__promise__frame().promised__stream__id(),4)
+ + pl__frame.push__promise__frame().header__block__fragment();
+
+ if(pl__frame.header__frame().padding().ispresent()){
+ ret_val=ret_val+pl__frame.push__promise__frame().padding()();
+ }
+
+ break;
+ case HTTP2__Frame::ALT_ping__frame:
+ if(pl__frame.ping__frame().ack__flag()){
+ flags|=0x01;
+ }
+ ret_val=int2oct(0x6,1) // Type: PING frame (type=0x6)
+ + int2oct(flags,1)
+ + int2oct(0,4) // The stream identifier for a PING frame MUST be zero
+ + pl__frame.ping__frame().opaque__data() ;
+
+
+
+ break;
+ case HTTP2__Frame::ALT_goaway__frame:
+ ret_val=int2oct(0x7,1) // Type: GOAWAY frame (type=0x7)
+ + int2oct(flags,1)
+ + int2oct(0,4) // The stream identifier for a GOAWAY frame MUST be zero
+ + int2oct(pl__frame.goaway__frame().last__stream__id(),4) ;
+ + int2oct(pl__frame.goaway__frame().error__code(),4) ;
+ if(pl__frame.goaway__frame().debug__data().ispresent()){
+ ret_val=ret_val+pl__frame.goaway__frame().debug__data()();
+ }
+
+ break;
+ case HTTP2__Frame::ALT_window__update__frame:
+ ret_val=int2oct(0x8,1) // Type: WINDOW_UPDATE frame (type=0x8)
+ + int2oct(flags,1)
+ + int2oct(pl__frame.window__update__frame().stream__id(),4)
+ + int2oct(pl__frame.window__update__frame().window__size__increment(),4);
+
+ break;
+ case HTTP2__Frame::ALT_continuation__frame:
+ if(pl__frame.continuation__frame().end__header__flag()){
+ flags|=0x04;
+ }
+ ret_val=int2oct(0x9,1) // Type: CONTINUATION frame (type=0x9)
+ + int2oct(flags,1)
+ + int2oct(pl__frame.continuation__frame().stream__id(),4)
+ + pl__frame.continuation__frame().header__block__fragment();
+
+ break;
+ case HTTP2__Frame::ALT_generic__frame:
+ ret_val=int2oct(pl__frame.generic__frame().frame__type(),1)
+ + bit2oct(pl__frame.generic__frame().flags())
+ + int2oct(pl__frame.generic__frame().stream__id(),4)
+ + pl__frame.generic__frame().payload();
+ break;
+ default:
+ break;
+ }
+
+ // length: The 9 octets of the frame header are not included in this value
+ return int2oct(ret_val.lengthof()-6,3) + ret_val;
+}
+
+INTEGER decode_uint32(const unsigned char* ptr){
+ return oct2int(OCTETSTRING(4,ptr));
+}
+INTEGER decode_uint16(const unsigned char* ptr){
+ return oct2int(OCTETSTRING(2,ptr));
+}
+
+INTEGER decode_uint31(const unsigned char* ptr){
+ unsigned int ret_val= (*ptr) & 0x7F;
+ ret_val<<=8;
+ ptr++;
+ ret_val+=*ptr;
+ ret_val<<=8;
+ ptr++;
+ ret_val+=*ptr;
+ ret_val<<=8;
+ ptr++;
+ ret_val+=*ptr;
+ return ret_val;
+}
+
+void decode_prio_data(const unsigned char* ptr, HTTP2__Priority__data& p_data){
+ p_data.exclusive__flag()=((*ptr) & 0x80);
+ p_data.stream__dependency()=decode_uint31(ptr);
+ ptr+=4;
+ p_data.weight()=*ptr;
+}
+
+INTEGER f__HTTP2__decode__frame(const OCTETSTRING& pl__stream,
+ HTTP2__Frame& pl__frame,
+ HTTP2__decoder__error__descr& pl__error__descr){
+
+ pl__error__descr.error__class() = c__connection__no__error__class;
+ pl__error__descr.error__type() =c__error__code__NO__ERROR;
+ pl__error__descr.error__text()= "OK";
+
+ if(pl__stream.lengthof()<9){
+ pl__error__descr.error__class() = c__connection__error__class;
+ pl__error__descr.error__type() =c__error__code__FRAME__SIZE__ERROR;
+ pl__error__descr.error__text()= "The frame is shorter than the header size";
+ return 1; // too short
+ }
+ const unsigned char* ptr=(const unsigned char*)pl__stream;
+ // decode length
+ int payload_len= *ptr; // payload length
+ payload_len<<=8;
+ ptr++;
+ payload_len+=*ptr;
+ payload_len<<=8;
+ ptr++;
+ payload_len+=*ptr;
+ ptr++;
+ if(pl__stream.lengthof()!=(payload_len+9)){
+ pl__error__descr.error__class() = c__connection__error__class;
+ pl__error__descr.error__type() =c__error__code__FRAME__SIZE__ERROR;
+ pl__error__descr.error__text()= "The payload size not match the packet size";
+ return 1; // length field error
+ }
+ const unsigned char type=*ptr;
+ ptr++;
+ const unsigned char flags=*ptr;
+ ptr++;
+ INTEGER stream_id=decode_uint31(ptr);
+ ptr+=4;
+ // now the ptr points to frame payload
+ switch(type){ // type
+ case 0x0: // Type: DATA frames (type=0x0)
+ if(flags & 0x8){ // padding
+ if(payload_len<1){
+ pl__error__descr.error__class() = c__connection__error__class;
+ pl__error__descr.error__type() =c__error__code__FRAME__SIZE__ERROR;
+ pl__error__descr.error__text()= "DATA frame: missing padding length field";
+ return 1; // too short
+ }
+ int pl=*ptr; // padding length
+ if(payload_len<(pl+1)){
+ pl__error__descr.error__class() = c__connection__error__class;
+ pl__error__descr.error__type() =c__error__code__PROTOCOL__ERROR;
+ pl__error__descr.error__text()= "DATA frame: wrong padding size";
+ return 1; // too short
+ }
+ ptr++;
+ pl__frame.data__frame().data()=OCTETSTRING(payload_len-pl-1,ptr);
+ ptr+=payload_len-pl-1;
+ pl__frame.data__frame().padding()=OCTETSTRING(pl,ptr);
+ } else {
+ pl__frame.data__frame().data()=OCTETSTRING(payload_len,ptr);
+ pl__frame.data__frame().padding()=OMIT_VALUE;
+ }
+ pl__frame.data__frame().stream__id()=stream_id;
+ pl__frame.data__frame().end__stream__flag()=(flags & 0x1);
+
+ break;
+ case 0x1: {// Type: HEADERS frame (type=0x1)
+ int pl=0; // padding length
+ if(flags & 0x8){ // padding
+ if(payload_len<1){
+ pl__error__descr.error__class() = c__connection__error__class;
+ pl__error__descr.error__type() =c__error__code__FRAME__SIZE__ERROR;
+ pl__error__descr.error__text()= "HEADER frame: missing padding length field";
+ return 1; // too short
+ }
+ pl=*ptr;
+ ptr++;
+ payload_len--;
+ if(payload_len<pl){
+ pl__error__descr.error__class() = c__connection__error__class;
+ pl__error__descr.error__type() =c__error__code__PROTOCOL__ERROR;
+ pl__error__descr.error__text()= "HEADER frame: wrong padding size";
+ return 1; // too short
+ }
+ }
+ if(flags & 0x20){ // PRIORITY
+ if((payload_len - pl)<5){
+ pl__error__descr.error__class() = c__connection__error__class;
+ pl__error__descr.error__type() =c__error__code__FRAME__SIZE__ERROR;
+ pl__error__descr.error__text()= "HEADER frame: not enough payload to decode priority data";
+ return 1; // too short
+ }
+ decode_prio_data(ptr,pl__frame.header__frame().priority__data()());
+ ptr+=5;
+ payload_len-=5;
+ } else {
+ pl__frame.header__frame().priority__data()=OMIT_VALUE;
+ }
+ pl__frame.header__frame().end__stream__flag()=(flags & 0x1);
+ pl__frame.header__frame().end__header__flag()=(flags & 0x4);
+ pl__frame.header__frame().stream__id()=stream_id;
+ pl__frame.header__frame().header__block__fragment()=OCTETSTRING(payload_len-pl,ptr);
+ if(flags & 0x8){ // padding
+ ptr+=(payload_len-pl);
+ pl__frame.header__frame().padding()=OCTETSTRING(pl,ptr);
+ } else {
+ pl__frame.header__frame().padding()=OMIT_VALUE;
+ }
+
+ }
+ break;
+ case 0x2: // Type: PRIORITY frame (type=0x2)
+ if(payload_len!=5){
+ pl__error__descr.error__class() = c__stream__error__class;
+ pl__error__descr.error__type() =c__error__code__FRAME__SIZE__ERROR;
+ pl__error__descr.error__text()= "PRIORITY frame: length is not 5 octet";
+ return 1; // wrong size
+ }
+ decode_prio_data(ptr,pl__frame.priority__frame().priority__data());
+ pl__frame.priority__frame().stream__id()=stream_id;
+ break;
+ case 0x3: // Type: RST_STREAM frame (type=0x3)
+ if(payload_len!=4){
+ pl__error__descr.error__class() = c__connection__error__class;
+ pl__error__descr.error__type() =c__error__code__FRAME__SIZE__ERROR;
+ pl__error__descr.error__text()= " RST_STREAMframe: length is not 4 octet";
+ return 1; // wrong size
+ }
+ pl__frame.rst__frame().error__code()=decode_uint32(ptr);
+ pl__frame.rst__frame().stream__id()=stream_id;
+ break;
+ case 0x4: // Type: SETTINGS frame (type=0x4)
+ if(payload_len % 6){
+ pl__error__descr.error__class() = c__connection__error__class;
+ pl__error__descr.error__type() =c__error__code__FRAME__SIZE__ERROR;
+ pl__error__descr.error__text()= " SETTINGS frame: length is not a multiple of 6 octets";
+ return 1; // wrong size
+ }
+ if(stream_id!=0){
+ pl__error__descr.error__class() = c__connection__error__class;
+ pl__error__descr.error__type() =c__error__code__PROTOCOL__ERROR;
+ pl__error__descr.error__text()= " SETTINGS frame: stream id is not 0.";
+ return 1; // wrong size
+ }
+
+ pl__frame.settings__frame().settings()=OMIT_VALUE;
+ {int i=0;
+ while(payload_len){
+ pl__frame.settings__frame().settings()()[i].setting__id()=decode_uint16(ptr);
+ ptr+=2;
+ pl__frame.settings__frame().settings()()[i].setting__value()=decode_uint32(ptr);
+ ptr+=4;
+ payload_len-=6;
+ i++;
+ }}
+
+ pl__frame.settings__frame().ack__flag()=(flags & 0x1);
+ break;
+ case 0x5:{ // Type: PUSH_PROMISE frame (type=0x5)
+ int pl=0; // padding length
+ if(flags & 0x8){ // padding
+ if(payload_len<5){
+ pl__error__descr.error__class() = c__connection__error__class;
+ pl__error__descr.error__type() =c__error__code__FRAME__SIZE__ERROR;
+ pl__error__descr.error__text()= "PUSH_PROMISE frame: missing padding length field or missing promised stream id";
+ return 1; // too short
+ }
+ pl=*ptr;
+ ptr++;
+ payload_len--;
+ if(payload_len<=(pl+4)){
+ pl__error__descr.error__class() = c__connection__error__class;
+ pl__error__descr.error__type() =c__error__code__PROTOCOL__ERROR;
+ pl__error__descr.error__text()= "PUSH_PROMISE frame: wrong padding size";
+ return 1; // too short
+ }
+
+ } else {
+ if(payload_len<4){
+ pl__error__descr.error__class() = c__connection__error__class;
+ pl__error__descr.error__type() =c__error__code__FRAME__SIZE__ERROR;
+ pl__error__descr.error__text()= "PUSH_PROMISE frame: missing promised stream id";
+ return 1; // too short
+ }
+ }
+ pl__frame.push__promise__frame().promised__stream__id()=decode_uint31(ptr);
+ ptr+=4;
+ payload_len-=4;
+
+ pl__frame.push__promise__frame().header__block__fragment()=OCTETSTRING(payload_len-pl,ptr);
+ if(flags & 0x8){ // padding
+ ptr+=(payload_len-pl);
+ pl__frame.push__promise__frame().padding()=OCTETSTRING(pl,ptr);
+ } else {
+ pl__frame.push__promise__frame().padding()=OMIT_VALUE;
+ }
+ pl__frame.push__promise__frame().end__header__flag()=(flags & 0x4);
+
+ pl__frame.push__promise__frame().stream__id()=stream_id;
+ }
+ break;
+ case 0x6: // Type: PING frame (type=0x6)
+ if(payload_len !=8){
+ pl__error__descr.error__class() = c__connection__error__class;
+ pl__error__descr.error__type() =c__error__code__FRAME__SIZE__ERROR;
+ pl__error__descr.error__text()= "PING frame: length is not 8 octets";
+ return 1; // wrong size
+ }
+ if(stream_id!=0){
+ pl__error__descr.error__class() = c__connection__error__class;
+ pl__error__descr.error__type() =c__error__code__PROTOCOL__ERROR;
+ pl__error__descr.error__text()= "PING frame: stream id is not 0.";
+ return 1; // wrong size
+ }
+ pl__frame.ping__frame().opaque__data()=OCTETSTRING(8,ptr);
+ pl__frame.ping__frame().ack__flag()=(flags & 0x1);
+ break;
+ case 0x7: // Type: GOAWAY frame (type=0x7)
+ if(payload_len <8){
+ pl__error__descr.error__class() = c__connection__error__class;
+ pl__error__descr.error__type() =c__error__code__FRAME__SIZE__ERROR;
+ pl__error__descr.error__text()= "GOAWAY frame: length is less than 8 octets";
+ return 1; // wrong size
+ }
+ if(stream_id!=0){
+ pl__error__descr.error__class() = c__connection__error__class;
+ pl__error__descr.error__type() =c__error__code__PROTOCOL__ERROR;
+ pl__error__descr.error__text()= "GOAWAY frame: stream id is not 0.";
+ return 1; // wrong size
+ }
+ pl__frame.goaway__frame().last__stream__id()=decode_uint31(ptr);
+ ptr+=4;
+ payload_len-=4;
+ pl__frame.goaway__frame().error__code()=decode_uint32(ptr);
+ ptr+=4;
+ payload_len-=4;
+ if(payload_len>0){
+ pl__frame.goaway__frame().debug__data()=OCTETSTRING(payload_len,ptr);
+ } else {
+ pl__frame.goaway__frame().debug__data()=OMIT_VALUE;
+ }
+ break;
+ case 0x8: // Type: WINDOW_UPDATE frame (type=0x8)
+ if(payload_len !=4){
+ pl__error__descr.error__class() = c__connection__error__class;
+ pl__error__descr.error__type() =c__error__code__FRAME__SIZE__ERROR;
+ pl__error__descr.error__text()= "WINDOW_UPDATE frame: length is not 4 octets";
+ return 1; // wrong size
+ }
+ pl__frame.window__update__frame().window__size__increment()=decode_uint32(ptr);
+ pl__frame.window__update__frame().stream__id()=stream_id;
+ break;
+ case 0x9: // Type: CONTINUATION frame (type=0x9)
+ pl__frame.continuation__frame().header__block__fragment()=OCTETSTRING(payload_len,ptr);
+ pl__frame.continuation__frame().stream__id()=stream_id;
+ pl__frame.continuation__frame().end__header__flag()=(flags & 0x4);
+ break;
+ default: // unknown frame
+ pl__frame.generic__frame().frame__type()=type;
+ pl__frame.generic__frame().flags()= int2bit(flags,8);
+ pl__frame.generic__frame().stream__id()=stream_id;
+ pl__frame.generic__frame().payload()=OCTETSTRING(payload_len,ptr);
+ break;
+ }
+
+ return 0;
+}
+
+}
+
diff --git a/src/HTTP2_Types.ttcn b/src/HTTP2_Types.ttcn
new file mode 100644
index 0000000..8af8071
--- /dev/null
+++ b/src/HTTP2_Types.ttcn
@@ -0,0 +1,291 @@
+/******************************************************************************
+* Copyright (c) 2017 Ericsson AB
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* http://www.eclipse.org/legal/epl-v10.html
+*
+* Contributors:
+* Gabor Szalai - initial implementation and initial documentation
+******************************************************************************/
+//
+// File: HTTP2_Types.ttcn
+// Description: Functions and types for HTTP2
+// Rev: R1A
+// Prodnr: CNL 113 851
+module HTTP2_Types{
+
+external function f_HTTP2_encode_frame(in HTTP2_Frame pl_frame) return octetstring
+with {
+ extension "prototype(convert)"
+}
+
+// return values:
+// 1 - decoding failed
+// 0 - OK
+//
+// The pl_error_descr contains the description of the error
+
+
+external function f_HTTP2_decode_frame(in octetstring pl_stream,
+ out HTTP2_Frame pl_frame,
+ out HTTP2_decoder_error_descr pl_error_descr) return integer
+
+// Message dissector function for IPL4 test port
+type record of integer HTTP2_ro_integer
+
+function f_HTTP2_msglen(
+ in octetstring stream,
+ inout HTTP2_ro_integer args
+) return integer {
+ var integer pl_len:=lengthof(stream)
+ if(pl_len<3){
+ return -1;
+ }
+ if(pl_len<lengthof(HTTP2_connection_preface)){
+ if(substr(HTTP2_connection_preface,0,pl_len)==stream ){
+ return -1
+ }
+ } else {
+ if(HTTP2_connection_preface==substr(stream,0,lengthof(HTTP2_connection_preface))){
+ return lengthof(HTTP2_connection_preface)
+ }
+
+ }
+ return oct2int(substr(stream,0,3))+9
+}
+
+const octetstring HTTP2_connection_preface:='505249202a20485454502f322e300d0a0d0a534d0d0a0d0a'O
+
+// Error classes
+const integer c_connection_no_error_class := 0
+const integer c_connection_error_class := 1
+const integer c_stream_error_class := 2
+
+// Error codes
+const integer c_error_code_NO_ERROR:= 0
+const integer c_error_code_PROTOCOL_ERROR := 1
+const integer c_error_code_INTERNAL_ERROR :=2
+const integer c_error_code_FLOW_CONTROL_ERROR := 3
+const integer c_error_code_SETTINGS_TIMEOUT := 4
+const integer c_error_code_STREAM_CLOSED := 5
+const integer c_error_code_FRAME_SIZE_ERROR := 6
+const integer c_error_code_REFUSED_STREAM := 7
+const integer c_error_code_CANCEL := 8
+const integer c_error_code_COMPRESSION_ERROR := 9
+const integer c_error_code_CONNECT_ERROR := 10
+const integer c_error_code_ENHANCE_YOUR_CALM := 11
+const integer c_error_code_INADEQUATE_SECURITY := 12
+const integer c_error_code_HTTP_1_1_REQUIRED := 13
+
+// Settings parameters
+const integer c_SETTINGS_HEADER_TABLE_SIZE := 1
+const integer c_SETTINGS_ENABLE_PUSH := 2
+const integer c_SETTINGS_MAX_CONCURRENT_STREAMS := 3
+const integer c_SETTINGS_INITIAL_WINDOW_SIZE := 4
+const integer c_SETTINGS_MAX_FRAME_SIZE := 5
+const integer c_SETTINGS_MAX_HEADER_LIST_SIZE := 6
+
+type record HTTP2_decoder_error_descr{
+ integer error_class,
+ integer error_type,
+ charstring error_text
+}
+
+// HTTP/2 Frame definition
+// The length field handled automatically
+type union HTTP2_Frame {
+ HTTP2_Data_frame data_frame,
+ HTTP2_Header_frame header_frame,
+ HTTP2_Priority_frame priority_frame,
+ HTTP2_RST_Stream_frame rst_frame,
+ HTTP2_Settings_frame settings_frame,
+ HTTP2_Push_Promise_frame push_promise_frame,
+ HTTP2_Ping_frame ping_frame,
+ HTTP2_Goaway_frame goaway_frame,
+ HTTP2_Window_Update_frame window_update_frame,
+ HTTP2_Continuation_frame continuation_frame,
+ HTTP2_Generic_frame generic_frame
+}
+
+// Data Frame definition
+// The padding flag are handled automatically
+type record HTTP2_Data_frame{
+ integer stream_id,
+ boolean end_stream_flag,
+ octetstring data,
+ octetstring padding optional
+}
+
+// Header Frame definition
+// The padding flag are handled automatically
+// The priority flag are handled automatically
+type record HTTP2_Header_frame{
+ integer stream_id,
+ boolean end_stream_flag,
+ boolean end_header_flag,
+ HTTP2_Priority_data priority_data optional,
+ octetstring header_block_fragment,
+ octetstring padding optional
+}
+
+type record HTTP2_Priority_data{
+ boolean exclusive_flag,
+ integer stream_dependency,
+ integer weight
+}
+
+type record HTTP2_Priority_frame{
+ integer stream_id,
+ HTTP2_Priority_data priority_data
+}
+
+type record HTTP2_RST_Stream_frame {
+ integer stream_id,
+ integer error_code
+}
+
+type record HTTP2_Setting_data{
+ integer setting_id,
+ integer setting_value
+}
+
+type record of HTTP2_Setting_data HTTP2_Setting_list
+
+// Always use 0 stream
+type record HTTP2_Settings_frame{
+ boolean ack_flag,
+ HTTP2_Setting_list settings optional
+}
+
+// The padding flag are handled automatically
+type record HTTP2_Push_Promise_frame{
+ integer stream_id,
+ boolean end_header_flag,
+ integer promised_stream_id,
+ octetstring header_block_fragment,
+ octetstring padding optional
+}
+
+
+// Always use 0 stream
+type record HTTP2_Ping_frame{
+ boolean ack_flag,
+ octetstring opaque_data length(8)
+}
+
+// Always use 0 stream
+type record HTTP2_Goaway_frame{
+ integer last_stream_id,
+ integer error_code,
+ octetstring debug_data optional
+}
+
+type record HTTP2_Window_Update_frame{
+ integer stream_id,
+ integer window_size_increment
+}
+
+type record HTTP2_Continuation_frame{
+ integer stream_id,
+ boolean end_header_flag,
+ octetstring header_block_fragment
+}
+
+// Use it to send/receive non-defined or errornous frame
+// Only the length calculated by the encoder
+type record HTTP2_Generic_frame{
+ integer frame_type,
+ bitstring flags length(8),
+ integer stream_id,
+ octetstring payload
+}
+
+
+// HTTP2 request/response and header definitions
+// RFC7540 8.1.2.1
+// Note: the encoder doesn't enforces validity
+// of the specified pseudo header field combination
+
+type record HTTP2_pseudo_headers{
+ charstring method optional,
+ charstring scheme optional,
+ charstring authority optional,
+ charstring path optional,
+ integer status optional
+}
+
+type record HTTP2_header_field{
+ charstring header_name,
+ charstring header_value optional
+}
+
+type record of HTTP2_header_field HTTP2_header_list
+
+// This type should be used for request/response headers
+type record HTTP2_header_block {
+ HTTP2_pseudo_headers pseudo_headers optional,
+ HTTP2_header_list headers optional
+}
+
+
+// Header compression releated type definitions
+// For each connection (not streams) a separate
+// compression context should be used.
+
+// Never touch the fields of the HTTP2_comp_context
+// Don't even think about it !!!!!
+
+// 1. Create the context with function:
+// HTTP2_comp_context_init
+
+// 2. Every header block should be encoded/decoded with the functions:
+// HTTP2_comp_context_encode
+// HTTP2_comp_context_decode
+// in the exactly the same order as the header blocks are sent or received
+// in order to maintain the header compression context
+
+// 3. Delete the context with
+// HTTP2_comp_context_free
+// Please note: non freed context leads to memory leak!!!!
+
+// Creates a new header compression context
+external function HTTP2_comp_context_init(in integer h_table_size_local:=4096, // The initial size of the header table
+ in integer h_table_size_remote:=4096
+ ) return HTTP2_comp_context
+
+// Retur value:
+// 0 - OK
+// otherwise - error code
+external function HTTP2_comp_context_encode(inout HTTP2_comp_context pl_context,
+ in HTTP2_header_block pl_hblock,
+ out octetstring pl_frame_data) return integer
+
+// Retur value:
+// 0 - OK
+// otherwise - error code
+external function HTTP2_comp_context_decode(inout HTTP2_comp_context pl_context,
+ out HTTP2_header_block pl_hblock,
+ in octetstring pl_frame_data) return integer
+
+
+// Free and release the header compression context
+external function HTTP2_comp_context_free(inout HTTP2_comp_context pl_context)
+
+
+// Set header table size
+external function HTTP2_comp_context_set_table_size_remote(inout HTTP2_comp_context pl_context,
+ in integer h_table_size)
+
+external function HTTP2_comp_context_set_table_size_local(inout HTTP2_comp_context pl_context,
+ in integer h_table_size)
+
+//**************************************************//
+// DO NOT TOUCH THE FIELDS OF THE HTTP2_comp_context
+//**************************************************//
+type record HTTP2_comp_context{
+ integer internal_id1
+}
+
+
+}

Back to the top