Quic ser
a fake serializer for quic
object quic_ser = {}
<<< member
class `quic_ser`;
>>>
<<< impl
//TODO
//TODO
class `quic_ser` : public ivy_binary_ser_128 {
//class `quic_ser` : public ivy_binary_ser {
enum {quic_s_init,
quic_s_version,
quic_s_dcil,
quic_s_scil,
quic_s_dcid,
quic_s_scid,
quic_s_retry_token_length,
quic_s_retry_token,
quic_s_payload_length,
quic_s_pkt_num,
quic_s_payload,
quic_stream_id,
quic_stream_off,
quic_stream_len,
quic_stream_fin,
quic_stream_offset,
quic_stream_length,
quic_stream_data,
quic_crypto_offset,
quic_crypto_length,
quic_crypto_data,
quic_ack_largest,
quic_ack_delay,
quic_ack_block_count,
quic_ack_gap,
quic_ack_block,
quic_reset_stream_id,
quic_reset_err_code,
quic_reset_final_offset,
quic_stop_sending_id,
quic_stop_sending_err_code,
quic_connection_close_err_code,
quic_connection_close_frame_type,
quic_connection_close_reason_length,
quic_connection_close_reason,
quic_application_close_err_code,
quic_max_stream_data_id,
quic_path_challenge_data,
quic_new_connection_id_length,
quic_new_connection_id_seq_num,
quic_new_connection_id_retire_prior_to,
quic_new_connection_id_scid,
quic_new_connection_id_token,
quic_retire_connection_id_seq_num,
quic_handshake_done,
quic_padding,
quic_ping,
quic_unknow,
quic_malicious,
quic_immediate_ack, //seq_num
quic_ack_frequency, //seq_num
quic_ack_frequency_ack_eliciting_threshold,
quic_ack_frequency_request_max_ack_delay,
quic_ack_frequency_reordering_threshold,
quic_s_done} state;
bool long_format;
char hdr_type;
int dcil;
int scil;
long frame_type;
int data_remaining;
int128_t ack_blocks_expected;
int128_t ack_block_count;
//long long ack_blocks_expected;
//long long ack_block_count;
int payload_length_pos;
int fence;
int tcount = 0;
bool done = false;
public:
quic_ser() : state(quic_s_init) {
}
virtual void set(int128_t res) {
//virtual void set(long long res) {
switch (state) {
case quic_s_init:
{
//std::cerr << "ser res init " << res << "\n";
long_format = res != 3;
hdr_type = (long_format ? ((res & 3) << 4) : 0) | 0x43 ;
setn(hdr_type | (long_format ? 0x80 : 0), 1);
state = quic_s_version;
}
break;
case quic_s_version:
{
if (long_format)
setn(res,4);
state = quic_s_dcid;
}
break;
case quic_s_dcid:
{
//std::cerr << "ser res dcid 1 " << res << "\n";
if (long_format) {
if((res != 0 && res != 1) || scid_h == 0)
setn(scid_h,1);
else
setn(8,1);
}
if((res != 0 && res != 1) || scid_h == 0)
setn(res,scid_h); //scid_h
else
setn(res,8);
//std::cerr << "ser res dcid 2 " << res << "\n";
state = quic_s_scid;
}
break;
case quic_s_scid:
{
//std::cerr << "ser res scid_h 1 " << res << "\n";
if (long_format) {
if((res == 0 || res == 1) && scid_h != 0){
setn(8,1);
setn(res,8);
} else {
setn(dcid_h,1);
setn(res,dcid_h);
}
}
//std::cerr << "ser res scid_h 1 " << res << "\n";
state = quic_s_retry_token_length;
}
break;
case quic_s_pkt_num:
{
set_pkt_num(res);
state = quic_s_payload;
}
break;
case quic_stream_off:
{
frame_type |= res ? 0x04 : 0;
state = quic_stream_len;
}
break;
case quic_stream_len:
{
frame_type |= res ? 0x02 : 0;
state = quic_stream_fin;
}
break;
case quic_stream_fin:
{
frame_type |= res ? 0x01 : 0;
setn(frame_type,1);
state = quic_stream_id;
}
break;
case quic_stream_id:
{
set_var_int(res);
state = quic_stream_offset;
}
break;
case quic_stream_offset:
{
if (0x04 & frame_type)
set_var_int(res);
state = quic_stream_length;
}
break;
case quic_stream_length:
{
if (0x02 & frame_type)
set_var_int(res);
data_remaining = res;
state = quic_stream_data;
}
break;
case quic_crypto_offset:
{
//std::cerr << "ser: quic_crypto_offset = " << res << "\n";
if(const char* env_p4 = std::getenv("RETRY_TOKEN_LENGTH")) {
//std::cerr << "RETRY_TOKEN_LENGTH 1 " << env_p4 << "\n";
if(!done)
set_var_int(0);
else
set_var_int(res);
} else {
set_var_int(res);
}
//set_var_int(res);
state = quic_crypto_length;
}
break;
case quic_crypto_length:
{
set_var_int(res);
data_remaining = res;
state = quic_crypto_data;
}
break;
case quic_malicious:
case quic_stream_data:
case quic_crypto_data:
case quic_connection_close_reason:
case quic_path_challenge_data:
case quic_padding:
case quic_ping:
case quic_unknow:
case quic_handshake_done: // TODO
case quic_immediate_ack:
case quic_s_retry_token:
{
// int128_t packet_size = res.size();
// std::cerr << "packet_size ser " << packet_size << "\n";
// int128_t token_length = packet_size - 1 - dcil - 1 - scil - 1 - 4;
// std::cerr << "token_length ser " << token_length << "\n";
// std::cerr << "quic_s_retry_token ser " << tcount << "\n";
// tcount += 1;
/* if (const char* env_p3 = std::getenv("RETRY_TOKEN")) {
std::cerr << "ser: quic_s_retry_token = " << res << "\n";
if(const char* env_p4 = std::getenv("RETRY_TOKEN_LENGTH")) {
std::cerr << "RETRY_TOKEN " << env_p3 << "\n";
std::cerr << "RETRY_TOKEN_LENGTH " << env_p4 << "\n";
setn(res,1);
tls_field_bytes_map["dcid"] = atoi(env_p3);
}
}
else
if(const char* env_p4 = std::getenv("RETRY_TOKEN_LENGTH") && false) {
std::cerr << "RETRY_TOKEN_LENGTH 1 " << env_p4 << "\n";
setn(res,atoi(env_p4));
} else {
setn(res,1);
}*/
setn(res,1);
}
break;
/*case quic_s_retry_token_length:
{
if (const char* env_p3 = std::getenv("RETRY_TOKEN")) {
std::cerr << "ser: quic_s_retry_token = " << res << "\n";
if(const char* env_p4 = std::getenv("RETRY_TOKEN_LENGTH")) {
std::cerr << "RETRY_TOKEN_LENGTH 2" << env_p4 << "\n";
setn(atoi(env_p3),1);
state = quic_s_retry_token;
}
}
}
break;*/
case quic_ack_largest:
{
set_var_int(res);
state = quic_ack_delay;
}
break;
case quic_ack_delay:
{
set_var_int(res);
state = quic_ack_block_count;
}
break;
case quic_ack_gap:
{
if (ack_block_count == 0)
{} // first ack block has no gap
else
set_var_int(res);
state = quic_ack_block;
}
break;
case quic_ack_block:
{
set_var_int(res);
state = quic_ack_gap;
ack_block_count++;
}
break;
case quic_reset_stream_id:
{
set_var_int(res);
state = quic_reset_err_code;
}
break;
case quic_reset_err_code:
{
set_var_int(res);
state = quic_reset_final_offset;
}
break;
case quic_reset_final_offset:
{
set_var_int(res);
}
break;
case quic_stop_sending_id:
{
set_var_int(res);
state = quic_stop_sending_err_code;
}
break;
case quic_stop_sending_err_code:
{
set_var_int(res);
}
break;
case quic_connection_close_err_code:
{
set_var_int(res);
state = quic_connection_close_frame_type;
}
break;
case quic_connection_close_frame_type:
{
set_var_int(res);
state = quic_connection_close_reason_length;
}
break;
case quic_connection_close_reason_length:
{
set_var_int(res);
data_remaining = res;
state = quic_connection_close_reason;
}
break;
case quic_application_close_err_code:
{
set_var_int(res);
state = quic_connection_close_reason_length;
}
break;
case quic_max_stream_data_id:
{
set_var_int(res);
state = quic_reset_final_offset;
}
break;
case quic_new_connection_id_length:
{
setn(res,1);
scil = res;
state = quic_new_connection_id_scid;
}
break;
case quic_new_connection_id_seq_num:
{
set_var_int(res);
state = quic_new_connection_id_retire_prior_to;
}
break;
case quic_new_connection_id_retire_prior_to:
{
set_var_int(res);
state = quic_new_connection_id_length;
}
break;
case quic_new_connection_id_scid:
{
setn(res,scil);
state = quic_new_connection_id_token;
}
break;
case quic_new_connection_id_token:
{
setn(res,16);
}
break;
case quic_retire_connection_id_seq_num:
{
set_var_int(res);
}
break;
case quic_ack_frequency: //TODO
{
set_var_int(res);
//std::cerr << "ser: quic_ack_frequency = quic_ack_frequency\n";
state = quic_ack_frequency_ack_eliciting_threshold;
}
break;
case quic_ack_frequency_ack_eliciting_threshold:
{
set_var_int(res);
//std::cerr << "ser: quic_ack_frequency = quic_ack_frequency_ack_eliciting_threshold\n";
state = quic_ack_frequency_request_max_ack_delay;
}
break;
case quic_ack_frequency_request_max_ack_delay:
{
set_var_int(res);
//std::cerr << "ser: quic_ack_frequency = quic_ack_frequency_request_max_ack_delay\n";
state = quic_ack_frequency_reordering_threshold;
}
break;
case quic_ack_frequency_reordering_threshold:
{
//std::cerr << "ser: quic_ack_frequency = quic_ack_frequency_reordering_threshold\n";
//setn(res,1);
set_var_int(res);
}
break;
default:
//std::cerr << "quic_ser 2\n";
throw deser_err();
}
}
void set_var_int(int128_t res) {
int128_t val = res & 0x3fffffffffffffff; //TODO modify with 16 bytes mask ?
//void set_var_int(long long res) {
// long long val = res & 0x3fffffffffffffff;
int bytecode = res <= 0x3f ? 0 : res <= 0x3fff ? 1 : res <= 0x3fffffff ? 2 : 3;
int bytes = 1 << bytecode;
val |= bytecode << ((bytes << 3) - 2);
setn(val,bytes);
}
void set_pkt_num(int128_t &res) {
//void set_pkt_num(long long &res) {
// setn(0xc0000000 | (0x3fffffff & res),4);
// pkt number length is low two bits of first packet byte, plus one
setn(res,(hdr_type & 3) + 1);
}
virtual void open_tag(int tag, const std::string &) {
if (state == quic_s_payload) {
int sz = 1;
if (tag == 0) {
frame_type = 0x01;
state = quic_ping;
}
else if (tag == 1) {
state = quic_ack_largest;
frame_type = 0x02;
}
else if (tag == 2) {
state = quic_ack_largest;
frame_type = 0x03;
}
else if (tag == 3) {
state = quic_reset_stream_id;
frame_type = 0x04;
}
else if (tag == 4) {
state = quic_stop_sending_id;
frame_type = 0x05;
}
else if (tag == 5) {
frame_type = 0x06;
state = quic_crypto_offset;
}
else if (tag == 6) {
frame_type = 0x07;
state = quic_s_retry_token_length; // new_token TODOODO
}
else if (tag == 7) {
frame_type = 0x08;
state = quic_stream_off;
return;
}
else if (tag == 8) {
frame_type = 0x10; // max_data
state = quic_reset_final_offset;
}
else if (tag == 9) {
state = quic_max_stream_data_id;
frame_type = 0x11;
}
else if (tag == 10) {
state = quic_reset_stream_id; // max_stream_id state equivalent to this
frame_type = 0x13;
}
else if (tag == 11) {
state = quic_reset_stream_id; // max_stream_id state equivalent to this
frame_type = 0x12;
}
else if (tag == 12) {
state = quic_reset_final_offset;
frame_type = 0x14;
}
else if (tag == 13) {
state = quic_max_stream_data_id;
frame_type = 0x15;
}
else if (tag == 14) {
state = quic_reset_final_offset;
frame_type = 0x16;
}
else if (tag == 15) {
state = quic_reset_final_offset;
frame_type = 0x17;
}
else if (tag == 16) {
frame_type = 0x18;
state = quic_new_connection_id_seq_num;
}
else if (tag == 17) {
state = quic_retire_connection_id_seq_num;
frame_type = 0x19;
}
else if (tag == 18) {
frame_type = 0x1a;
state = quic_path_challenge_data;
}
else if (tag == 19) {
frame_type = 0x1b;
state = quic_path_challenge_data;
}
else if (tag == 20) {
state = quic_connection_close_err_code;
frame_type = 0x1c;
}
else if (tag == 21) {
frame_type = 0x1d;
state = quic_application_close_err_code;
}
else if (tag == 22) {
state = quic_handshake_done;
frame_type = 0x1e;
}
else if (tag == 23) {
state = quic_ack_frequency;
frame_type = 0x40AF; // 0100 0000 AF
sz = 2;
}
else if (tag == 24) {
state = quic_immediate_ack;
frame_type = 0x40AC; // 0100 0000 AC
sz = 2;
}
else if (tag == 25) {
state = quic_unknow;
frame_type = 0x4042;
sz = 2;
}
else if (tag == 26) {
std::cerr << "quic_ser malicious\n";
state = quic_malicious;
frame_type = 0x4041;
sz = 2;
}
/*else if (tag == 25) {
state = quic_padding;
frame_type = 0x00;
}*/
else {
//std::cerr << "saw frame tag " << tag << "\n";
throw deser_err();
}
setn(frame_type,sz);
return;
}
//std::cerr << "quic_ser 1\n";
throw deser_err();
}
virtual void open_list_elem() {
}
void open_list(int len) {
ack_blocks_expected = len;
if (state == quic_ack_block_count) {
set_var_int(ack_blocks_expected - 1); // block count doesn't include first
ack_block_count = 0;
state = quic_ack_gap;
} else if (state == quic_s_retry_token_length) {
if (long_format & ((hdr_type & 0x30) == 0x00)) {
//std::cerr << "open_list len " << len << "\n";
set_var_int(len);
data_remaining = len;
}
state = quic_s_retry_token;
}
}
void close_list() {
if (state == quic_s_payload) {
if (long_format && (hdr_type & 0x30) == 0x00)
while (res.size() < 1200)
res.push_back(0); // pad initial packet to 1200 bytes
/*else if ((hdr_type & 0x30) == 0x20){
while (res.size() < 2000)
res.push_back(0); // pad initial packet to 1200 bytes
}*/
for(unsigned i = 0; i < 16; i++)
res.push_back(0);
if (long_format) {
int len = res.size() - (payload_length_pos+2) ;
res[payload_length_pos] = 0x40 | ((len >> 8) & 0x3f);
res[payload_length_pos+1] = len & 0xff;
state = quic_s_init;
}
}
else if (state == quic_s_retry_token) {
payload_length_pos = this->res.size();
if (long_format) {
setn(0,2); // will fill in correct value later
}
state = quic_s_pkt_num;
}
}
void close_list_elem() {}
virtual void close_tag() {
state = quic_s_payload;
}
~quic_ser(){}
};
>>>
<<< init
//transport_error_name_map(transport_error_codes,transport_error_codes_map);
>>>