dissect_gquic_frame_type(tvbuff_t *tvb, packet_info *pinfo, proto_tree *gquic_tree, guint offset, guint8 len_pkn, gquic_info_data_t *gquic_info){
    proto_item *ti, *ti_ft, *ti_ftflags /*, *expert_ti*/;
    proto_tree *ft_tree, *ftflags_tree;
    guint8 frame_type;
    guint8 num_ranges, num_revived, num_blocks = 0, num_timestamp;
    guint32 len_stream = 0, len_offset = 0, len_data = 0, len_largest_observed = 1, len_missing_packet = 1;

    ti_ft = proto_tree_add_item(gquic_tree, hf_gquic_frame, tvb, offset, 1, ENC_NA);
    ft_tree = proto_item_add_subtree(ti_ft, ett_gquic_ft);

    /* Frame type */
    ti_ftflags = proto_tree_add_item(ft_tree, hf_gquic_frame_type, tvb, offset, 1, ENC_NA);
    frame_type = tvb_get_guint8(tvb, offset);
    proto_item_set_text(ti_ft, "%s", rval_to_str(frame_type, frame_type_vals, "Unknown"));

    if((frame_type & FTFLAGS_SPECIAL) == 0 && frame_type != FT_CRYPTO){ /* Regular Stream Flags */
        offset += 1;
        switch(frame_type){
            case FT_PADDING:{
                proto_item *ti_pad_len;
                guint32 pad_len = tvb_reported_length_remaining(tvb, offset);

                ti_pad_len = proto_tree_add_uint(ft_tree, hf_gquic_frame_type_padding_length, tvb, offset, 0, pad_len);
                proto_item_set_generated(ti_pad_len);
                proto_item_append_text(ti_ft, " Length: %u", pad_len);
                if(pad_len > 0) /* Avoid Malformed Exception with pad_len == 0 */
		    proto_tree_add_item(ft_tree, hf_gquic_frame_type_padding, tvb, offset, -1, ENC_NA);
                offset += pad_len;
                }
            break;
            case FT_RST_STREAM:{
                guint32 stream_id, error_code;
                proto_tree_add_item_ret_uint(ft_tree, hf_gquic_frame_type_rsts_stream_id, tvb, offset, 4, gquic_info->encoding, &stream_id);
                offset += 4;
                proto_tree_add_item(ft_tree, hf_gquic_frame_type_rsts_byte_offset, tvb, offset, 8, gquic_info->encoding);
                offset += 8;
                proto_tree_add_item_ret_uint(ft_tree, hf_gquic_frame_type_rsts_error_code, tvb, offset, 4, gquic_info->encoding, &error_code);
                offset += 4;
                proto_item_append_text(ti_ft, " Stream ID: %u, Error code: %s", stream_id, val_to_str_ext(error_code, &rststream_error_code_vals_ext, "Unknown (%d)"));
                col_set_str(pinfo->cinfo, COL_INFO, "RST STREAM");
                }
            break;
            case FT_CONNECTION_CLOSE:{
                guint16 len_reason;
                guint32 error_code;

                proto_tree_add_item_ret_uint(ft_tree, hf_gquic_frame_type_cc_error_code, tvb, offset, 4, gquic_info->encoding, &error_code);
                offset += 4;
                proto_tree_add_item(ft_tree, hf_gquic_frame_type_cc_reason_phrase_length, tvb, offset, 2, gquic_info->encoding);
                len_reason = tvb_get_guint16(tvb, offset, gquic_info->encoding);
                offset += 2;
                proto_tree_add_item(ft_tree, hf_gquic_frame_type_cc_reason_phrase, tvb, offset, len_reason, ENC_ASCII|ENC_NA);
                offset += len_reason;
                proto_item_append_text(ti_ft, " Error code: %s", val_to_str_ext(error_code, &error_code_vals_ext, "Unknown (%d)"));
                col_set_str(pinfo->cinfo, COL_INFO, "Connection Close");
                }
            break;
            case FT_GOAWAY:{
                guint16 len_reason;
                guint32 error_code, last_good_stream_id;

                proto_tree_add_item_ret_uint(ft_tree, hf_gquic_frame_type_goaway_error_code, tvb, offset, 4, gquic_info->encoding, &error_code);
                offset += 4;
                proto_tree_add_item_ret_uint(ft_tree, hf_gquic_frame_type_goaway_last_good_stream_id, tvb, offset, 4, gquic_info->encoding, &last_good_stream_id);
                offset += 4;
                proto_tree_add_item(ft_tree, hf_gquic_frame_type_goaway_reason_phrase_length, tvb, offset, 2, gquic_info->encoding);
                len_reason = tvb_get_guint16(tvb, offset, gquic_info->encoding);
                offset += 2;
                proto_tree_add_item(ft_tree, hf_gquic_frame_type_goaway_reason_phrase, tvb, offset, len_reason, ENC_ASCII|ENC_NA);
                offset += len_reason;
                proto_item_append_text(ti_ft, " Stream ID: %u, Error code: %s", last_good_stream_id, val_to_str_ext(error_code, &error_code_vals_ext, "Unknown (%d)"));
                col_set_str(pinfo->cinfo, COL_INFO, "GOAWAY");
                }
            break;
            case FT_WINDOW_UPDATE:{
                guint32 stream_id;

                proto_tree_add_item_ret_uint(ft_tree, hf_gquic_frame_type_wu_stream_id, tvb, offset, 4, gquic_info->encoding, &stream_id);
                offset += 4;
                proto_tree_add_item(ft_tree, hf_gquic_frame_type_wu_byte_offset, tvb, offset, 8, gquic_info->encoding);
                offset += 8;
                proto_item_append_text(ti_ft, " Stream ID: %u", stream_id);
                }
            break;
            case FT_BLOCKED:{
                guint32 stream_id;

                proto_tree_add_item_ret_uint(ft_tree, hf_gquic_frame_type_blocked_stream_id, tvb, offset, 4, gquic_info->encoding, &stream_id);
                offset += 4;
                proto_item_append_text(ti_ft, " Stream ID: %u", stream_id);
                }
            break;
            case FT_STOP_WAITING:{
                guint8 send_entropy;
                if(gquic_info->version_valid && gquic_info->version < 34){ /* No longer Entropy after Q034 */
                    proto_tree_add_item(ft_tree, hf_gquic_frame_type_sw_send_entropy, tvb, offset, 1, ENC_NA);
                    send_entropy = tvb_get_guint8(tvb, offset);
                    proto_item_append_text(ti_ft, " Send Entropy: %u", send_entropy);
                    offset += 1;
                }
                proto_tree_add_item(ft_tree, hf_gquic_frame_type_sw_least_unacked_delta, tvb, offset, len_pkn, gquic_info->encoding);
                offset += len_pkn;

                }
            break;
            case FT_PING: /* No Payload */
            default: /* No default */
            break;
        }
    }
    else { /* Special Frame Types */
        guint32 stream_id, message_tag;
        const guint8* message_tag_str;
        proto_item *ti_stream;

        ftflags_tree = proto_item_add_subtree(ti_ftflags, ett_gquic_ftflags);
        proto_tree_add_item(ftflags_tree, hf_gquic_frame_type_stream , tvb, offset, 1, ENC_NA);

        if(frame_type == FT_CRYPTO) {
            guint64 crypto_offset, crypto_length;
            gint32 lenvar;

            DISSECTOR_ASSERT(gquic_info->version_valid && gquic_info->version >= 50);

            col_append_fstr(pinfo->cinfo, COL_INFO, ", CRYPTO");
            offset += 1;
            proto_tree_add_item_ret_varint(ft_tree, hf_gquic_crypto_offset, tvb, offset, -1, ENC_VARINT_QUIC, &crypto_offset, &lenvar);
            offset += lenvar;
            proto_tree_add_item_ret_varint(ft_tree, hf_gquic_crypto_length, tvb, offset, -1, ENC_VARINT_QUIC, &crypto_length, &lenvar);
            offset += lenvar;
            proto_tree_add_item(ft_tree, hf_gquic_crypto_crypto_data, tvb, offset, (guint32)crypto_length, ENC_NA);

            if (gquic_info->version == 50) {
	        message_tag = tvb_get_ntohl(tvb, offset);
                ti = proto_tree_add_item_ret_string(ft_tree, hf_gquic_tag, tvb, offset, 4, ENC_ASCII|ENC_NA, wmem_packet_scope(), &message_tag_str);
                proto_item_append_text(ti, " (%s)", val_to_str(message_tag, message_tag_vals, "Unknown Tag"));
                col_add_fstr(pinfo->cinfo, COL_INFO, "%s", val_to_str(message_tag, message_tag_vals, "Unknown"));
                offset += 4;

                offset = dissect_gquic_tags(tvb, pinfo, ft_tree, offset);
	    } else { /* T050 and T051 */
                tvbuff_t *next_tvb = tvb_new_subset_length(tvb, offset, (int)crypto_length);
                col_set_writable(pinfo->cinfo, -1, FALSE);
                call_dissector_with_data(tls13_handshake_handle, next_tvb, pinfo, ft_tree, GUINT_TO_POINTER(crypto_offset));
                col_set_writable(pinfo->cinfo, -1, TRUE);
                offset += (guint32)crypto_length;
	    }

	} else if(frame_type & FTFLAGS_STREAM){ /* Stream Flags */
            proto_tree_add_item(ftflags_tree, hf_gquic_frame_type_stream_f, tvb, offset, 1, ENC_NA);
            proto_tree_add_item(ftflags_tree, hf_gquic_frame_type_stream_d, tvb, offset, 1, ENC_NA);
            if(frame_type & FTFLAGS_STREAM_D){
                len_data = 2;
            }
            proto_tree_add_item(ftflags_tree, hf_gquic_frame_type_stream_ooo, tvb, offset, 1, ENC_NA);

            len_offset = get_len_offset(frame_type);

            proto_tree_add_item(ftflags_tree, hf_gquic_frame_type_stream_ss, tvb, offset, 1, ENC_NA);
            len_stream = get_len_stream(frame_type);
            offset += 1;

            ti_stream = proto_tree_add_item_ret_uint(ft_tree, hf_gquic_stream_id, tvb, offset, len_stream, gquic_info->encoding, &stream_id);
            offset += len_stream;

            proto_item_append_text(ti_ft, " Stream ID: %u", stream_id);

            if(len_offset) {
                proto_tree_add_item(ft_tree, hf_gquic_offset, tvb, offset, len_offset, gquic_info->encoding);
                offset += len_offset;
            }

            if(len_data) {
                proto_tree_add_item(ft_tree, hf_gquic_data_len, tvb, offset, len_data, gquic_info->encoding);
                offset += len_data;
            }

            /* Check if there is some reserved streams (Chapiter 6.1 of draft-shade-gquic-http2-mapping-00) */

            switch(stream_id) {
                case 1: { /* Reserved (G)QUIC (handshake, crypto, config updates...) */
                    message_tag = tvb_get_ntohl(tvb, offset);
                    ti = proto_tree_add_item_ret_string(ft_tree, hf_gquic_tag, tvb, offset, 4, ENC_ASCII|ENC_NA, wmem_packet_scope(), &message_tag_str);

                    proto_item_append_text(ti_stream, " (Reserved for (G)QUIC handshake, crypto, config updates...)");
                    proto_item_append_text(ti, " (%s)", val_to_str(message_tag, message_tag_vals, "Unknown Tag"));
                    proto_item_append_text(ti_ft, ", Type: %s (%s)", message_tag_str, val_to_str(message_tag, message_tag_vals, "Unknown Tag"));
                    col_add_fstr(pinfo->cinfo, COL_INFO, "%s", val_to_str(message_tag, message_tag_vals, "Unknown"));
                    offset += 4;

                    offset = dissect_gquic_tags(tvb, pinfo, ft_tree, offset);
                break;
                }
                case 3: { /* Reserved H2 HEADERS (or PUSH_PROMISE..) */
                    tvbuff_t* tvb_h2;

                    proto_item_append_text(ti_stream, " (Reserved for H2 HEADERS)");

                    col_add_str(pinfo->cinfo, COL_INFO, "H2");

                    tvb_h2 = tvb_new_subset_remaining(tvb, offset);

                    offset += dissect_http2_pdu(tvb_h2, pinfo, ft_tree, NULL);
                }
                break;
                default: { /* Data... */
                    int data_len = tvb_reported_length_remaining(tvb, offset);

                    col_add_str(pinfo->cinfo, COL_INFO, "DATA");

                    proto_tree_add_item(ft_tree, hf_gquic_stream_data, tvb, offset, data_len, ENC_NA);
                    offset += data_len;
                }
                break;
            }
        } else if (frame_type & FTFLAGS_ACK) {     /* ACK Flags */

            proto_tree_add_item(ftflags_tree, hf_gquic_frame_type_ack, tvb, offset, 1, ENC_NA);

            proto_tree_add_item(ftflags_tree, hf_gquic_frame_type_ack_n, tvb, offset, 1, ENC_NA);

            if(gquic_info->version_valid && gquic_info->version < 34){ /* No longer NACK after Q034 */
                proto_tree_add_item(ftflags_tree, hf_gquic_frame_type_ack_t, tvb, offset, 1, ENC_NA);
            } else {
                proto_tree_add_item(ftflags_tree, hf_gquic_frame_type_ack_u, tvb, offset, 1, ENC_NA);
            }
            proto_tree_add_item(ftflags_tree, hf_gquic_frame_type_ack_ll, tvb, offset, 1, ENC_NA);

            len_largest_observed = get_len_largest_observed(frame_type);

            proto_tree_add_item(ftflags_tree, hf_gquic_frame_type_ack_mm, tvb, offset, 1, ENC_NA);
            len_missing_packet = get_len_missing_packet(frame_type);
            offset += 1;

            if(gquic_info->version_valid && gquic_info->version < 34){ /* Big change after Q034 */
                proto_tree_add_item(ft_tree, hf_gquic_frame_type_ack_received_entropy, tvb, offset, 1, ENC_NA);
                offset += 1;

                proto_tree_add_item(ft_tree, hf_gquic_frame_type_ack_largest_observed, tvb, offset, len_largest_observed, gquic_info->encoding);
                offset += len_largest_observed;

                proto_tree_add_item(ft_tree, hf_gquic_frame_type_ack_ack_delay_time, tvb, offset, 2, gquic_info->encoding);
                offset += 2;

                proto_tree_add_item(ft_tree, hf_gquic_frame_type_ack_num_timestamp, tvb, offset, 1, ENC_NA);
                num_timestamp = tvb_get_guint8(tvb, offset);
                offset += 1;

                if(num_timestamp){

                    /* Delta Largest Observed */
                    proto_tree_add_item(ft_tree, hf_gquic_frame_type_ack_delta_largest_observed, tvb, offset, 1, ENC_NA);
                    offset += 1;

                    /* First Timestamp */
                    proto_tree_add_item(ft_tree, hf_gquic_frame_type_ack_first_timestamp, tvb, offset, 4, gquic_info->encoding);
                    offset += 4;

                    num_timestamp -= 1;
                    /* Num Timestamp (-1) x (Delta Largest Observed + Time Since Previous Timestamp) */
                    while(num_timestamp){
                        proto_tree_add_item(ft_tree, hf_gquic_frame_type_ack_delta_largest_observed, tvb, offset, 1, ENC_NA);
                        offset += 1;

                        proto_tree_add_item(ft_tree, hf_gquic_frame_type_ack_time_since_previous_timestamp, tvb, offset, 2, gquic_info->encoding);
                        offset += 2;

                        num_timestamp--;
                    }
                }

                if(frame_type & FTFLAGS_ACK_N){
                    proto_tree_add_item(ft_tree, hf_gquic_frame_type_ack_num_ranges, tvb, offset, 1, ENC_NA);
                    num_ranges = tvb_get_guint8(tvb, offset);
                    offset += 1;
                    while(num_ranges){

                        proto_tree_add_item(ft_tree, hf_gquic_frame_type_ack_missing_packet, tvb, offset, len_missing_packet, gquic_info->encoding);
                        offset += len_missing_packet;

                        proto_tree_add_item(ft_tree, hf_gquic_frame_type_ack_range_length, tvb, offset, 1, ENC_NA);
                        offset += 1;
                        num_ranges--;
                    }

                    proto_tree_add_item(ft_tree, hf_gquic_frame_type_ack_num_revived, tvb, offset, 1, ENC_NA);
                    num_revived = tvb_get_guint8(tvb, offset);
                    offset += 1;
                    while(num_revived){

                        proto_tree_add_item(ft_tree, hf_gquic_frame_type_ack_revived_packet, tvb, offset, len_largest_observed, gquic_info->encoding);
                        offset += len_largest_observed;
                        num_revived--;

                    }

                }

            } else {

                /* Largest Acked */
                proto_tree_add_item(ft_tree, hf_gquic_frame_type_ack_largest_acked, tvb, offset, len_largest_observed, gquic_info->encoding);
                offset += len_largest_observed;

                /* Largest Acked Delta Time*/
                proto_tree_add_item(ft_tree, hf_gquic_frame_type_ack_largest_acked_delta_time, tvb, offset, 2, gquic_info->encoding);
                offset += 2;

                /* Ack Block */
                if(frame_type & FTFLAGS_ACK_N){
                    proto_tree_add_item(ft_tree, hf_gquic_frame_type_ack_num_blocks, tvb, offset, 1, ENC_NA);
                    num_blocks = tvb_get_guint8(tvb, offset);
                    offset += 1;
                }

                /* First Ack Block Length */
                proto_tree_add_item(ft_tree, hf_gquic_frame_type_ack_first_ack_block_length, tvb, offset, len_missing_packet, gquic_info->encoding);
                offset += len_missing_packet;

                while(num_blocks){
                    /* Gap to next block */
                    proto_tree_add_item(ft_tree, hf_gquic_frame_type_ack_gap_to_next_block, tvb, offset, 1, ENC_NA);
                    offset += 1;

                    /* Ack Block Length */
                    proto_tree_add_item(ft_tree, hf_gquic_frame_type_ack_ack_block_length, tvb, offset, len_missing_packet, gquic_info->encoding);
                    offset += len_missing_packet;

                    num_blocks--;
                }

                /* Timestamp */
                proto_tree_add_item(ft_tree, hf_gquic_frame_type_ack_num_timestamp, tvb, offset, 1, ENC_NA);
                num_timestamp = tvb_get_guint8(tvb, offset);
                offset += 1;

                if(num_timestamp){

                    /* Delta Largest Acked */
                    proto_tree_add_item(ft_tree, hf_gquic_frame_type_ack_delta_largest_acked, tvb, offset, 1, ENC_NA);
                    offset += 1;

                    /* Time Since Largest Acked */
                    proto_tree_add_item(ft_tree, hf_gquic_frame_type_ack_time_since_largest_acked, tvb, offset, 4, gquic_info->encoding);
                    offset += 4;

                    num_timestamp -= 1;
                    /* Num Timestamp x (Delta Largest Acked + Time Since Previous Timestamp) */
                    while(num_timestamp){
                        proto_tree_add_item(ft_tree, hf_gquic_frame_type_ack_delta_largest_acked, tvb, offset, 1, ENC_NA);
                        offset += 1;

                        proto_tree_add_item(ft_tree, hf_gquic_frame_type_ack_time_since_previous_timestamp, tvb, offset, 2, gquic_info->encoding);
                        offset += 2;

                        num_timestamp--;
                    }
                }

            }

        } else { /* Other ...*/
            offset += 1;
        }
    }
    return offset;

}
dissect_gquic_frame_type(tvbuff_t *tvb, packet_info *pinfo, proto_tree *gquic_tree, guint offset, guint8 len_pkn, gquic_info_data_t *gquic_info){
    proto_item *ti, *ti_ft, *ti_ftflags  ;
    proto_tree *ft_tree, *ftflags_tree;
    guint8 frame_type;
    guint8 num_ranges, num_revived, num_blocks = 0, num_timestamp;
    guint32 len_stream = 0, len_offset = 0, len_data = 0, len_largest_observed = 1, len_missing_packet = 1;

    ti_ft = proto_tree_add_item(gquic_tree, hf_gquic_frame, tvb, offset, 1, ENC_NA);
    ft_tree = proto_item_add_subtree(ti_ft, ett_gquic_ft);

     
    ti_ftflags = proto_tree_add_item(ft_tree, hf_gquic_frame_type, tvb, offset, 1, ENC_NA);
    frame_type = tvb_get_guint8(tvb, offset);
    proto_item_set_text(ti_ft, "%s", rval_to_str(frame_type, frame_type_vals, "Unknown"));

    if((frame_type & FTFLAGS_SPECIAL) == 0 && frame_type != FT_CRYPTO){  
        offset += 1;
        switch(frame_type){
            case FT_PADDING:{
                proto_item *ti_pad_len;
                guint32 pad_len = tvb_reported_length_remaining(tvb, offset);

                ti_pad_len = proto_tree_add_uint(ft_tree, hf_gquic_frame_type_padding_length, tvb, offset, 0, pad_len);
                proto_item_set_generated(ti_pad_len);
                proto_item_append_text(ti_ft, " Length: %u", pad_len);
                if(pad_len > 0)  
		    proto_tree_add_item(ft_tree, hf_gquic_frame_type_padding, tvb, offset, -1, ENC_NA);
                offset += pad_len;
                }
            break;
            case FT_RST_STREAM:{
                guint32 stream_id, error_code;
                proto_tree_add_item_ret_uint(ft_tree, hf_gquic_frame_type_rsts_stream_id, tvb, offset, 4, gquic_info->encoding, &stream_id);
                offset += 4;
                proto_tree_add_item(ft_tree, hf_gquic_frame_type_rsts_byte_offset, tvb, offset, 8, gquic_info->encoding);
                offset += 8;
                proto_tree_add_item_ret_uint(ft_tree, hf_gquic_frame_type_rsts_error_code, tvb, offset, 4, gquic_info->encoding, &error_code);
                offset += 4;
                proto_item_append_text(ti_ft, " Stream ID: %u, Error code: %s", stream_id, val_to_str_ext(error_code, &rststream_error_code_vals_ext, "Unknown (%d)"));
                col_set_str(pinfo->cinfo, COL_INFO, "RST STREAM");
                }
            break;
            case FT_CONNECTION_CLOSE:{
                guint16 len_reason;
                guint32 error_code;

                proto_tree_add_item_ret_uint(ft_tree, hf_gquic_frame_type_cc_error_code, tvb, offset, 4, gquic_info->encoding, &error_code);
                offset += 4;
                proto_tree_add_item(ft_tree, hf_gquic_frame_type_cc_reason_phrase_length, tvb, offset, 2, gquic_info->encoding);
                len_reason = tvb_get_guint16(tvb, offset, gquic_info->encoding);
                offset += 2;
                proto_tree_add_item(ft_tree, hf_gquic_frame_type_cc_reason_phrase, tvb, offset, len_reason, ENC_ASCII|ENC_NA);
                offset += len_reason;
                proto_item_append_text(ti_ft, " Error code: %s", val_to_str_ext(error_code, &error_code_vals_ext, "Unknown (%d)"));
                col_set_str(pinfo->cinfo, COL_INFO, "Connection Close");
                }
            break;
            case FT_GOAWAY:{
                guint16 len_reason;
                guint32 error_code, last_good_stream_id;

                proto_tree_add_item_ret_uint(ft_tree, hf_gquic_frame_type_goaway_error_code, tvb, offset, 4, gquic_info->encoding, &error_code);
                offset += 4;
                proto_tree_add_item_ret_uint(ft_tree, hf_gquic_frame_type_goaway_last_good_stream_id, tvb, offset, 4, gquic_info->encoding, &last_good_stream_id);
                offset += 4;
                proto_tree_add_item(ft_tree, hf_gquic_frame_type_goaway_reason_phrase_length, tvb, offset, 2, gquic_info->encoding);
                len_reason = tvb_get_guint16(tvb, offset, gquic_info->encoding);
                offset += 2;
                proto_tree_add_item(ft_tree, hf_gquic_frame_type_goaway_reason_phrase, tvb, offset, len_reason, ENC_ASCII|ENC_NA);
                offset += len_reason;
                proto_item_append_text(ti_ft, " Stream ID: %u, Error code: %s", last_good_stream_id, val_to_str_ext(error_code, &error_code_vals_ext, "Unknown (%d)"));
                col_set_str(pinfo->cinfo, COL_INFO, "GOAWAY");
                }
            break;
            case FT_WINDOW_UPDATE:{
                guint32 stream_id;

                proto_tree_add_item_ret_uint(ft_tree, hf_gquic_frame_type_wu_stream_id, tvb, offset, 4, gquic_info->encoding, &stream_id);
                offset += 4;
                proto_tree_add_item(ft_tree, hf_gquic_frame_type_wu_byte_offset, tvb, offset, 8, gquic_info->encoding);
                offset += 8;
                proto_item_append_text(ti_ft, " Stream ID: %u", stream_id);
                }
            break;
            case FT_BLOCKED:{
                guint32 stream_id;

                proto_tree_add_item_ret_uint(ft_tree, hf_gquic_frame_type_blocked_stream_id, tvb, offset, 4, gquic_info->encoding, &stream_id);
                offset += 4;
                proto_item_append_text(ti_ft, " Stream ID: %u", stream_id);
                }
            break;
            case FT_STOP_WAITING:{
                guint8 send_entropy;
                if(gquic_info->version_valid && gquic_info->version < 34){  
                    proto_tree_add_item(ft_tree, hf_gquic_frame_type_sw_send_entropy, tvb, offset, 1, ENC_NA);
                    send_entropy = tvb_get_guint8(tvb, offset);
                    proto_item_append_text(ti_ft, " Send Entropy: %u", send_entropy);
                    offset += 1;
                }
                proto_tree_add_item(ft_tree, hf_gquic_frame_type_sw_least_unacked_delta, tvb, offset, len_pkn, gquic_info->encoding);
                offset += len_pkn;

                }
            break;
            case FT_PING:  
            default:  
            break;
        }
    }
    else {  
        guint32 stream_id, message_tag;
        const guint8* message_tag_str;
        proto_item *ti_stream;

        ftflags_tree = proto_item_add_subtree(ti_ftflags, ett_gquic_ftflags);
        proto_tree_add_item(ftflags_tree, hf_gquic_frame_type_stream , tvb, offset, 1, ENC_NA);

        if(frame_type == FT_CRYPTO) {
            guint64 crypto_offset, crypto_length;
            gint32 lenvar;

            DISSECTOR_ASSERT(gquic_info->version_valid && gquic_info->version >= 50);

            col_append_fstr(pinfo->cinfo, COL_INFO, ", CRYPTO");
            offset += 1;
            proto_tree_add_item_ret_varint(ft_tree, hf_gquic_crypto_offset, tvb, offset, -1, ENC_VARINT_QUIC, &crypto_offset, &lenvar);
            offset += lenvar;
            proto_tree_add_item_ret_varint(ft_tree, hf_gquic_crypto_length, tvb, offset, -1, ENC_VARINT_QUIC, &crypto_length, &lenvar);
            offset += lenvar;
            proto_tree_add_item(ft_tree, hf_gquic_crypto_crypto_data, tvb, offset, (guint32)crypto_length, ENC_NA);

            if (gquic_info->version == 50) {
	        message_tag = tvb_get_ntohl(tvb, offset);
                ti = proto_tree_add_item_ret_string(ft_tree, hf_gquic_tag, tvb, offset, 4, ENC_ASCII|ENC_NA, wmem_packet_scope(), &message_tag_str);
                proto_item_append_text(ti, " (%s)", val_to_str(message_tag, message_tag_vals, "Unknown Tag"));
                col_add_fstr(pinfo->cinfo, COL_INFO, "%s", val_to_str(message_tag, message_tag_vals, "Unknown"));
                offset += 4;

                offset = dissect_gquic_tags(tvb, pinfo, ft_tree, offset);
	    } else {  
                tvbuff_t *next_tvb = tvb_new_subset_length(tvb, offset, (int)crypto_length);
                col_set_writable(pinfo->cinfo, -1, FALSE);
                call_dissector_with_data(tls13_handshake_handle, next_tvb, pinfo, ft_tree, GUINT_TO_POINTER(crypto_offset));
                col_set_writable(pinfo->cinfo, -1, TRUE);
                offset += (guint32)crypto_length;
	    }

	} else if(frame_type & FTFLAGS_STREAM){  
            proto_tree_add_item(ftflags_tree, hf_gquic_frame_type_stream_f, tvb, offset, 1, ENC_NA);
            proto_tree_add_item(ftflags_tree, hf_gquic_frame_type_stream_d, tvb, offset, 1, ENC_NA);
            if(frame_type & FTFLAGS_STREAM_D){
                len_data = 2;
            }
            proto_tree_add_item(ftflags_tree, hf_gquic_frame_type_stream_ooo, tvb, offset, 1, ENC_NA);

            len_offset = get_len_offset(frame_type);

            proto_tree_add_item(ftflags_tree, hf_gquic_frame_type_stream_ss, tvb, offset, 1, ENC_NA);
            len_stream = get_len_stream(frame_type);
            offset += 1;

            ti_stream = proto_tree_add_item_ret_uint(ft_tree, hf_gquic_stream_id, tvb, offset, len_stream, gquic_info->encoding, &stream_id);
            offset += len_stream;

            proto_item_append_text(ti_ft, " Stream ID: %u", stream_id);

            if(len_offset) {
                proto_tree_add_item(ft_tree, hf_gquic_offset, tvb, offset, len_offset, gquic_info->encoding);
                offset += len_offset;
            }

            if(len_data) {
                proto_tree_add_item(ft_tree, hf_gquic_data_len, tvb, offset, len_data, gquic_info->encoding);
                offset += len_data;
            }

             

            switch(stream_id) {
                case 1: {  
                    message_tag = tvb_get_ntohl(tvb, offset);
                    ti = proto_tree_add_item_ret_string(ft_tree, hf_gquic_tag, tvb, offset, 4, ENC_ASCII|ENC_NA, wmem_packet_scope(), &message_tag_str);

                    proto_item_append_text(ti_stream, " (Reserved for (G)QUIC handshake, crypto, config updates...)");
                    proto_item_append_text(ti, " (%s)", val_to_str(message_tag, message_tag_vals, "Unknown Tag"));
                    proto_item_append_text(ti_ft, ", Type: %s (%s)", message_tag_str, val_to_str(message_tag, message_tag_vals, "Unknown Tag"));
                    col_add_fstr(pinfo->cinfo, COL_INFO, "%s", val_to_str(message_tag, message_tag_vals, "Unknown"));
                    offset += 4;

                    offset = dissect_gquic_tags(tvb, pinfo, ft_tree, offset);
                break;
                }
                case 3: {  
                    tvbuff_t* tvb_h2;

                    proto_item_append_text(ti_stream, " (Reserved for H2 HEADERS)");

                    col_add_str(pinfo->cinfo, COL_INFO, "H2");

                    tvb_h2 = tvb_new_subset_remaining(tvb, offset);

                    offset += dissect_http2_pdu(tvb_h2, pinfo, ft_tree, NULL);
                }
                break;
                default: {  
                    int data_len = tvb_reported_length_remaining(tvb, offset);

                    col_add_str(pinfo->cinfo, COL_INFO, "DATA");

                    proto_tree_add_item(ft_tree, hf_gquic_stream_data, tvb, offset, data_len, ENC_NA);
                    offset += data_len;
                }
                break;
            }
        } else if (frame_type & FTFLAGS_ACK) {      

            proto_tree_add_item(ftflags_tree, hf_gquic_frame_type_ack, tvb, offset, 1, ENC_NA);

            proto_tree_add_item(ftflags_tree, hf_gquic_frame_type_ack_n, tvb, offset, 1, ENC_NA);

            if(gquic_info->version_valid && gquic_info->version < 34){  
                proto_tree_add_item(ftflags_tree, hf_gquic_frame_type_ack_t, tvb, offset, 1, ENC_NA);
            } else {
                proto_tree_add_item(ftflags_tree, hf_gquic_frame_type_ack_u, tvb, offset, 1, ENC_NA);
            }
            proto_tree_add_item(ftflags_tree, hf_gquic_frame_type_ack_ll, tvb, offset, 1, ENC_NA);

            len_largest_observed = get_len_largest_observed(frame_type);

            proto_tree_add_item(ftflags_tree, hf_gquic_frame_type_ack_mm, tvb, offset, 1, ENC_NA);
            len_missing_packet = get_len_missing_packet(frame_type);
            offset += 1;

            if(gquic_info->version_valid && gquic_info->version < 34){  
                proto_tree_add_item(ft_tree, hf_gquic_frame_type_ack_received_entropy, tvb, offset, 1, ENC_NA);
                offset += 1;

                proto_tree_add_item(ft_tree, hf_gquic_frame_type_ack_largest_observed, tvb, offset, len_largest_observed, gquic_info->encoding);
                offset += len_largest_observed;

                proto_tree_add_item(ft_tree, hf_gquic_frame_type_ack_ack_delay_time, tvb, offset, 2, gquic_info->encoding);
                offset += 2;

                proto_tree_add_item(ft_tree, hf_gquic_frame_type_ack_num_timestamp, tvb, offset, 1, ENC_NA);
                num_timestamp = tvb_get_guint8(tvb, offset);
                offset += 1;

                if(num_timestamp){

                     
                    proto_tree_add_item(ft_tree, hf_gquic_frame_type_ack_delta_largest_observed, tvb, offset, 1, ENC_NA);
                    offset += 1;

                     
                    proto_tree_add_item(ft_tree, hf_gquic_frame_type_ack_first_timestamp, tvb, offset, 4, gquic_info->encoding);
                    offset += 4;

                    num_timestamp -= 1;
                     
                    while(num_timestamp){
                        proto_tree_add_item(ft_tree, hf_gquic_frame_type_ack_delta_largest_observed, tvb, offset, 1, ENC_NA);
                        offset += 1;

                        proto_tree_add_item(ft_tree, hf_gquic_frame_type_ack_time_since_previous_timestamp, tvb, offset, 2, gquic_info->encoding);
                        offset += 2;

                        num_timestamp--;
                    }
                }

                if(frame_type & FTFLAGS_ACK_N){
                    proto_tree_add_item(ft_tree, hf_gquic_frame_type_ack_num_ranges, tvb, offset, 1, ENC_NA);
                    num_ranges = tvb_get_guint8(tvb, offset);
                    offset += 1;
                    while(num_ranges){

                        proto_tree_add_item(ft_tree, hf_gquic_frame_type_ack_missing_packet, tvb, offset, len_missing_packet, gquic_info->encoding);
                        offset += len_missing_packet;

                        proto_tree_add_item(ft_tree, hf_gquic_frame_type_ack_range_length, tvb, offset, 1, ENC_NA);
                        offset += 1;
                        num_ranges--;
                    }

                    proto_tree_add_item(ft_tree, hf_gquic_frame_type_ack_num_revived, tvb, offset, 1, ENC_NA);
                    num_revived = tvb_get_guint8(tvb, offset);
                    offset += 1;
                    while(num_revived){

                        proto_tree_add_item(ft_tree, hf_gquic_frame_type_ack_revived_packet, tvb, offset, len_largest_observed, gquic_info->encoding);
                        offset += len_largest_observed;
                        num_revived--;

                    }

                }

            } else {

                 
                proto_tree_add_item(ft_tree, hf_gquic_frame_type_ack_largest_acked, tvb, offset, len_largest_observed, gquic_info->encoding);
                offset += len_largest_observed;

                 
                proto_tree_add_item(ft_tree, hf_gquic_frame_type_ack_largest_acked_delta_time, tvb, offset, 2, gquic_info->encoding);
                offset += 2;

                 
                if(frame_type & FTFLAGS_ACK_N){
                    proto_tree_add_item(ft_tree, hf_gquic_frame_type_ack_num_blocks, tvb, offset, 1, ENC_NA);
                    num_blocks = tvb_get_guint8(tvb, offset);
                    offset += 1;
                }

                 
                proto_tree_add_item(ft_tree, hf_gquic_frame_type_ack_first_ack_block_length, tvb, offset, len_missing_packet, gquic_info->encoding);
                offset += len_missing_packet;

                while(num_blocks){
                     
                    proto_tree_add_item(ft_tree, hf_gquic_frame_type_ack_gap_to_next_block, tvb, offset, 1, ENC_NA);
                    offset += 1;

                     
                    proto_tree_add_item(ft_tree, hf_gquic_frame_type_ack_ack_block_length, tvb, offset, len_missing_packet, gquic_info->encoding);
                    offset += len_missing_packet;

                    num_blocks--;
                }

                 
                proto_tree_add_item(ft_tree, hf_gquic_frame_type_ack_num_timestamp, tvb, offset, 1, ENC_NA);
                num_timestamp = tvb_get_guint8(tvb, offset);
                offset += 1;

                if(num_timestamp){

                     
                    proto_tree_add_item(ft_tree, hf_gquic_frame_type_ack_delta_largest_acked, tvb, offset, 1, ENC_NA);
                    offset += 1;

                     
                    proto_tree_add_item(ft_tree, hf_gquic_frame_type_ack_time_since_largest_acked, tvb, offset, 4, gquic_info->encoding);
                    offset += 4;

                    num_timestamp -= 1;
                     
                    while(num_timestamp){
                        proto_tree_add_item(ft_tree, hf_gquic_frame_type_ack_delta_largest_acked, tvb, offset, 1, ENC_NA);
                        offset += 1;

                        proto_tree_add_item(ft_tree, hf_gquic_frame_type_ack_time_since_previous_timestamp, tvb, offset, 2, gquic_info->encoding);
                        offset += 2;

                        num_timestamp--;
                    }
                }

            }

        } else {  
            offset += 1;
        }
    }
    return offset;

}