├── TextFile1.txt ├── benchmarks ├── __init__.py ├── add_main_to_plugin.py └── test_harness.py ├── picoquic ├── picoquic.cpp ├── endianness.h ├── endianness.c ├── cc_common.h ├── ReadMe.txt ├── memory.h ├── logger.h ├── picotlsapi.h ├── wincompat.h ├── queue.c ├── fnv1a.c ├── picoquic_logger.h └── fnv1a.h ├── picoquicfirst ├── help.txt ├── http09_index.html ├── http09_index2.html ├── getopt.h └── picoquicfirst.vcxproj.filters ├── plugins ├── monitoring │ ├── tests │ │ ├── test_frt.qv │ │ └── test_rto.qv │ ├── stream_closed.c │ ├── stream_opened.c │ ├── stream_frame_written.c │ ├── Makefile │ ├── tail_loss_probe.c │ ├── retransmission_timeout.c │ ├── fast_retransmit.c │ ├── monitoring.plugin │ ├── packet_lost.c │ ├── unknown_tp_received.c │ ├── check_ooo_stream_frame.c │ ├── rtt_updated.c │ ├── cnx_state_changed.c │ ├── check_spurious_stream_frame.c │ ├── packet_received.c │ └── packet_sent.c ├── fec │ ├── get_protoops_sigcomm19.sh │ ├── constant_redundancy_controller_protoops │ │ ├── constant_redundancy_controller.h │ │ ├── constant_redundancy_controller_burst_handling.h │ │ ├── create_constant_redundancy_controller.c │ │ ├── get_constant_redundancy_parameters.c │ │ └── get_constant_redundancy_parameters_burst_handling.c │ ├── gf256 │ │ ├── gf256.h │ │ └── swif_symbol.h │ ├── fec_scheme_protoops │ │ ├── rlc_fec_scheme_gf256.h │ │ ├── create_xor_fec_scheme.c │ │ └── create_rlc_fec_scheme_gf256.c │ ├── protoops │ │ ├── always_send_recovered_frames.c │ │ ├── never_send_recovered_frames.c │ │ ├── always_send_repair_symbols.c │ │ ├── stream_always_encode_length.c │ │ ├── notify_fec_frame.c │ │ ├── notify_fpid_frame.c │ │ ├── send_repair_symbols_when_no_stream_data_to_send.c │ │ ├── skip_frame_pre.c │ │ ├── skip_frame_post.c │ │ ├── maybe_notify_recovered_packets_to_cc.c │ │ ├── notify_recovered_frame.c │ │ ├── connection_state_changed.c │ │ ├── process_fec_frame.c │ │ ├── process_simple_recovered_frame.c │ │ ├── incoming_encrypted_post.c │ │ ├── stream_bytes_max.c │ │ ├── process_source_fpid_frame.c │ │ ├── parse_source_fpid_frame.c │ │ ├── packet_payload_to_source_symbol.c │ │ ├── incoming_encrypted.c │ │ ├── write_fec_frame.c │ │ └── write_fpid_frame.c │ ├── fec_scheme_xor.plugin │ ├── fec_scheme_rlc_gf256.plugin │ ├── fec_constant_redundancy_controller.plugin │ ├── fec_constant_redundancy_controller_burst.plugin │ ├── uniform_redundancy_controller_protoops │ │ ├── uniform_redundancy_controller.h │ │ ├── packet_was_lost.c │ │ ├── create_uniform_redundancy_controller.c │ │ ├── notified_acknowledgement.c │ │ └── get_uniform_redundancy_parameters.c │ ├── framework_protoops │ │ ├── block_flush_repair_symbols.c │ │ ├── window_flush_repair_symbols.c │ │ ├── block_get_source_fpid.c │ │ ├── window_get_source_fpid.c │ │ ├── block_protect_source_symbol.c │ │ ├── window_protect_source_symbol.c │ │ ├── block_receive_source_symbol.c │ │ ├── window_receive_source_symbol.c │ │ ├── window_pre_notify_sfpid_frame.c │ │ ├── window_receive_repair_symbol.c │ │ ├── window_post_write_sfpid_frame.c │ │ ├── block_receive_repair_symbol.c │ │ ├── block_create_framework.c │ │ ├── window_protect_all_unprotected_source_symbols.c │ │ ├── window_protect_all_inflight_source_symbols.c │ │ └── window_create_framework.c │ ├── fec_uniform_redundancy_controller.plugin │ ├── fec_framework_block.plugin │ ├── fec.plugin │ ├── fec_rlc_gf256_window.plugin │ ├── fec_rlc_gf256_window_no_rf.plugin │ ├── fec_rlc_gf256_window_uniform.plugin │ ├── fec_protect_end_of_stream.plugin │ ├── fec_rlc_gf256_window_protect_end_of_stream_only_inflight.plugin │ ├── fec_framework_window.plugin │ ├── fec_core.plugin │ └── Makefile ├── basic │ ├── very_basic.plugin │ ├── basic.plugin │ └── Makefile ├── no_pacing │ ├── no_pacing.plugin │ └── Makefile ├── multipath │ ├── addresses_filters │ │ ├── filter_ns3_ipv4.plugin │ │ ├── filter_no_v6_no_10.plugin │ │ ├── filter_only_42_0_1_1.plugin │ │ ├── filter_no_v6_no_10_no_42-3.plugin │ │ ├── only_42_0_1_1.c │ │ ├── only_192_168_net.c │ │ ├── no_v6_no_10.c │ │ └── no_v6_no_10_no_42-3.c │ ├── multipath_rr.plugin │ ├── multipath_rtt.plugin │ ├── multipath_rr_cond.plugin │ ├── multipath_rtt_cond.plugin │ ├── notify_rtt_probe.c │ ├── notify_mp_ack_frame.c │ ├── path_schedulers │ │ └── Makefile │ ├── notify_uniflows_frame.c │ ├── qlog │ │ ├── frame_prepared.c │ │ ├── add_address_parsed.c │ │ ├── mp_new_connection_id_frame_parsed.c │ │ └── uniflows_parsed.c │ ├── Makefile │ ├── notify_add_address_frame.c │ ├── process_max_sending_uniflow_id.c │ ├── multipath_qlog.plugin │ ├── write_max_sending_uniflow_id.c │ ├── notify_mp_new_connection_id_frame.c │ ├── get_destination_connection_id.c │ ├── process_mp_new_connection_id_frame.c │ ├── get_incoming_path.c │ ├── process_add_address_frame.c │ ├── multipath.plugin │ ├── write_rtt_probe.c │ ├── multipath_cond.plugin │ └── parse_mp_new_connection_id_frame.c ├── westwood │ ├── westwood_congestion_control.plugin │ └── Makefile ├── stream_scheduling_rr │ ├── stream_scheduling_rr.plugin │ ├── Makefile │ └── bpf.h ├── ack_delay │ ├── ack_delay.plugin │ ├── bpf.h │ ├── Makefile │ ├── update_ack_delay.c │ └── is_ack_needed.c ├── disable_congestion_control │ ├── disable_congestion_control.plugin │ ├── Makefile │ └── congestion_notify.c ├── ecn │ ├── pre_skip_frame.c │ ├── post_skip_frame.c │ ├── ecn.plugin │ ├── Makefile │ ├── received_packet.c │ ├── parse_ecn_block.c │ ├── before_sending_packet.c │ ├── bpf.h │ ├── process_ecn_block.c │ ├── header_parsed.c │ └── write_ecn_block.c ├── microbench │ ├── microbench.plugin │ ├── simple_for_loop.c │ ├── Makefile │ └── get_set_cnx_fields_loop.c ├── datagram │ ├── get_max_datagram_size.c │ ├── process_datagram_buffer.c │ ├── write_dummy_frame.c │ ├── Makefile │ ├── notify_datagram_frame.c │ ├── get_datagram_socket.c │ ├── cnx_state_changed.c │ ├── datagram.plugin │ └── parse_datagram_frame.c ├── tlp │ ├── tlp.plugin │ ├── Makefile │ └── bpf.h ├── qlog │ ├── frames │ │ ├── handshake_done_parsed.c │ │ ├── stream_opened.c │ │ ├── is_ack_needed.c │ │ ├── template │ │ ├── blocked_frame_parsed.c │ │ ├── max_data_parsed.c │ │ ├── frame_prepared.c │ │ ├── padding_or_ping_parsed.c │ │ ├── crypto_frame_parsed.c │ │ ├── stop_sending_parsed.c │ │ ├── stream_blocked_frame_parsed.c │ │ ├── max_stream_data_parsed.c │ │ ├── reset_stream_frame_parsed.c │ │ ├── stream_id_blocked_frame_parsed.c │ │ ├── stream_frame_parsed.c │ │ ├── path_challenge_created.c │ │ ├── path_response_parsed.c │ │ ├── application_close_parsed.c │ │ ├── connection_close_parsed.c │ │ ├── new_token_frame_parsed.c │ │ ├── new_connection_id_parsed.c │ │ └── stream_flags_changed.c │ ├── sender │ │ ├── next_wake_time.c │ │ ├── path_bandwidth_estimated.c │ │ ├── segment_aborted.c │ │ ├── header_prepared.c │ │ ├── ready_stream.c │ │ ├── next_stream_scheduled.c │ │ ├── retransmit_needed.c │ │ ├── retransmit_needed_by_packet.c │ │ └── segment_prepared.c │ ├── pop_log_context.c │ ├── Makefile │ ├── push_log_context.c │ ├── receiver │ │ ├── header_parsed.c │ │ └── segment_received.c │ ├── set_output_file.c │ ├── log_frame.c │ ├── cnx_state_changed.c │ └── log_event.c └── Makefile ├── x.gif ├── x.jpg ├── x.png ├── picoquic_t ├── ticket_store_test.bin ├── resume_tests_tickets.bin ├── http09_index.html ├── http09_index2.html ├── http09_index3.html ├── log_test.txt ├── picoquic_t.vcxproj.filters └── http09_1234.txt ├── .gitmodules ├── UnitTest1 ├── stdafx.cpp ├── targetver.h ├── stdafx.h └── UnitTest1.vcxproj.filters ├── .gitignore ├── ci └── build_picotls.sh ├── interop └── Dockerfile ├── .github └── workflows │ └── docker-publish.yml ├── memory_check.py ├── picoquictest ├── log_test_ref.txt └── ReadMe.txt ├── LICENSE ├── Dockerfile ├── certs ├── badcert.pem ├── cert.pem ├── test-ca.crt └── key.pem ├── .travis.yml ├── CMakeSettings.json └── README.md /TextFile1.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /benchmarks/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /picoquic/picoquic.cpp: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /picoquicfirst/help.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /picoquicfirst/http09_index.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /picoquicfirst/http09_index2.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /plugins/monitoring/tests/test_frt.qv: -------------------------------------------------------------------------------- 1 | < s9 drop -------------------------------------------------------------------------------- /plugins/monitoring/tests/test_rto.qv: -------------------------------------------------------------------------------- 1 | > s1..5 drop -------------------------------------------------------------------------------- /x.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/p-quic/pquic/HEAD/x.gif -------------------------------------------------------------------------------- /x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/p-quic/pquic/HEAD/x.jpg -------------------------------------------------------------------------------- /x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/p-quic/pquic/HEAD/x.png -------------------------------------------------------------------------------- /plugins/fec/get_protoops_sigcomm19.sh: -------------------------------------------------------------------------------- 1 | find . -name "*.o" | grep -v block | grep -v uniform_redundancy 2 | -------------------------------------------------------------------------------- /picoquic_t/ticket_store_test.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/p-quic/pquic/HEAD/picoquic_t/ticket_store_test.bin -------------------------------------------------------------------------------- /plugins/basic/very_basic.plugin: -------------------------------------------------------------------------------- 1 | be.qdeconinck.basic 2 | schedule_frames_on_path replace schedule_frames_on_path.o -------------------------------------------------------------------------------- /picoquic/endianness.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | uint16_t my_htons(uint16_t x); 4 | uint16_t my_ntohs(uint16_t x); -------------------------------------------------------------------------------- /picoquic_t/resume_tests_tickets.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/p-quic/pquic/HEAD/picoquic_t/resume_tests_tickets.bin -------------------------------------------------------------------------------- /plugins/no_pacing/no_pacing.plugin: -------------------------------------------------------------------------------- 1 | be.michelfra.no_pacing 2 | set_next_wake_time replace set_next_wake_time_without_pacing.o -------------------------------------------------------------------------------- /plugins/fec/constant_redundancy_controller_protoops/constant_redundancy_controller.h: -------------------------------------------------------------------------------- 1 | #define DEFAULT_N 6 2 | #define DEFAULT_K 5 -------------------------------------------------------------------------------- /plugins/fec/gf256/gf256.h: -------------------------------------------------------------------------------- 1 | #ifndef PICOQUIC_GF256_H 2 | #define PICOQUIC_GF256_H 3 | 4 | 5 | 6 | #endif //PICOQUIC_GF256_H 7 | -------------------------------------------------------------------------------- /plugins/multipath/addresses_filters/filter_ns3_ipv4.plugin: -------------------------------------------------------------------------------- 1 | be.qdeconinck.multipath.ns3 2 | accept_addr replace only_192_168_net.o -------------------------------------------------------------------------------- /plugins/multipath/addresses_filters/filter_no_v6_no_10.plugin: -------------------------------------------------------------------------------- 1 | be.qdeconinck.multipath.filters 2 | accept_addr replace no_v6_no_10.o -------------------------------------------------------------------------------- /plugins/westwood/westwood_congestion_control.plugin: -------------------------------------------------------------------------------- 1 | be.michelfra.westwood 2 | congestion_algorithm_notify replace westwood_notify.o -------------------------------------------------------------------------------- /plugins/multipath/addresses_filters/filter_only_42_0_1_1.plugin: -------------------------------------------------------------------------------- 1 | be.qdeconinck.multipath.filters2 2 | accept_addr replace only_42_0_1_1.o -------------------------------------------------------------------------------- /plugins/stream_scheduling_rr/stream_scheduling_rr.plugin: -------------------------------------------------------------------------------- 1 | be.mpiraux.stream_scheduling.rr 2 | schedule_next_stream replace stream_scheduling_rr.o -------------------------------------------------------------------------------- /plugins/ack_delay/ack_delay.plugin: -------------------------------------------------------------------------------- 1 | be.mpiraux.ack_delay 2 | update_ack_delay replace update_ack_delay.o 3 | is_ack_needed replace is_ack_needed.o -------------------------------------------------------------------------------- /plugins/fec/constant_redundancy_controller_protoops/constant_redundancy_controller_burst_handling.h: -------------------------------------------------------------------------------- 1 | #define DEFAULT_N 30 2 | #define DEFAULT_K 25 -------------------------------------------------------------------------------- /plugins/multipath/addresses_filters/filter_no_v6_no_10_no_42-3.plugin: -------------------------------------------------------------------------------- 1 | be.qdeconinck.multipath.filters3 2 | accept_addr replace no_v6_no_10_no_42-3.o -------------------------------------------------------------------------------- /plugins/disable_congestion_control/disable_congestion_control.plugin: -------------------------------------------------------------------------------- 1 | be.michelfra.westwood 2 | congestion_algorithm_notify replace congestion_notify.o -------------------------------------------------------------------------------- /plugins/ecn/pre_skip_frame.c: -------------------------------------------------------------------------------- 1 | #include "bpf.h" 2 | 3 | protoop_arg_t pre(picoquic_cnx_t *cnx) { 4 | get_bpf_data(cnx)->in_skip_frame = true; 5 | return 0; 6 | } -------------------------------------------------------------------------------- /plugins/microbench/microbench.plugin: -------------------------------------------------------------------------------- 1 | be.qdeconinck.microbench 2 | simple_for_loop replace simple_for_loop.o 3 | get_set_cnx_fields_loop replace get_set_cnx_fields_loop.o -------------------------------------------------------------------------------- /plugins/multipath/multipath_rr.plugin: -------------------------------------------------------------------------------- 1 | be.qdeconinck.multipath.rr dynamic_memory 2 | schedule_path replace path_schedulers/schedule_path_rr.o 3 | multipath.plugin include -------------------------------------------------------------------------------- /plugins/ecn/post_skip_frame.c: -------------------------------------------------------------------------------- 1 | #include "bpf.h" 2 | 3 | protoop_arg_t post(picoquic_cnx_t *cnx) { 4 | get_bpf_data(cnx)->in_skip_frame = false; 5 | return 0; 6 | } -------------------------------------------------------------------------------- /plugins/multipath/multipath_rtt.plugin: -------------------------------------------------------------------------------- 1 | be.qdeconinck.multipath.rtt dynamic_memory 2 | schedule_path replace path_schedulers/schedule_path_rtt.o 3 | multipath.plugin include -------------------------------------------------------------------------------- /plugins/multipath/multipath_rr_cond.plugin: -------------------------------------------------------------------------------- 1 | be.qdeconinck.multipath.rtt negotiate 2 | multipath_cond.plugin include 3 | schedule_path replace path_schedulers/schedule_path_rr.o -------------------------------------------------------------------------------- /plugins/multipath/multipath_rtt_cond.plugin: -------------------------------------------------------------------------------- 1 | be.qdeconinck.multipath.rtt negotiate 2 | multipath_cond.plugin include 3 | schedule_path replace path_schedulers/schedule_path_rtt.o -------------------------------------------------------------------------------- /plugins/fec/fec_scheme_protoops/rlc_fec_scheme_gf256.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | typedef struct { 4 | uint8_t **table_mul; 5 | uint8_t *table_inv; 6 | } rlc_gf256_fec_scheme_t; 7 | -------------------------------------------------------------------------------- /plugins/fec/protoops/always_send_recovered_frames.c: -------------------------------------------------------------------------------- 1 | #include "picoquic.h" 2 | 3 | 4 | protoop_arg_t should_send_recovered_frame(picoquic_cnx_t *cnx) 5 | { 6 | return (protoop_arg_t) 1; 7 | } -------------------------------------------------------------------------------- /plugins/fec/protoops/never_send_recovered_frames.c: -------------------------------------------------------------------------------- 1 | #include "picoquic.h" 2 | 3 | 4 | protoop_arg_t should_send_recovered_frame(picoquic_cnx_t *cnx) 5 | { 6 | return (protoop_arg_t) 0; 7 | } -------------------------------------------------------------------------------- /plugins/datagram/get_max_datagram_size.c: -------------------------------------------------------------------------------- 1 | #include "../helpers.h" 2 | #include "bpf.h" 3 | 4 | protoop_arg_t get_max_message_size(picoquic_cnx_t* cnx) 5 | { 6 | return get_max_datagram_size(cnx); 7 | } -------------------------------------------------------------------------------- /plugins/tlp/tlp.plugin: -------------------------------------------------------------------------------- 1 | be.qdeconinck.tlp 2 | set_next_wake_time replace set_next_wake_time.o 3 | retransmit_needed_by_packet replace retransmit_needed_by_packet.o 4 | retransmit_needed replace retransmit_needed.o -------------------------------------------------------------------------------- /plugins/qlog/frames/handshake_done_parsed.c: -------------------------------------------------------------------------------- 1 | #include "../bpf.h" 2 | 3 | protoop_arg_t protoop_log(picoquic_cnx_t *cnx) { 4 | helper_log_frame(cnx, "{\"frame_type\": \"handshake_done\"}"); 5 | return 0; 6 | } -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "ubpf"] 2 | path = ubpf 3 | url = https://github.com/p-quic/ubpf 4 | [submodule "picoquic/michelfralloc"] 5 | path = picoquic/michelfralloc 6 | url = https://github.com/p-quic/michelfralloc.git 7 | -------------------------------------------------------------------------------- /plugins/fec/protoops/always_send_repair_symbols.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | /** 5 | * returns always true 6 | */ 7 | protoop_arg_t should_send_repair_symbols(picoquic_cnx_t *cnx) 8 | { 9 | return true; 10 | } -------------------------------------------------------------------------------- /plugins/datagram/process_datagram_buffer.c: -------------------------------------------------------------------------------- 1 | #include "../helpers.h" 2 | #include "bpf.h" 3 | 4 | protoop_arg_t op_process_datagram_buffer(picoquic_cnx_t* cnx) 5 | { 6 | process_datagram_buffer(get_datagram_memory(cnx), cnx); 7 | return 0; 8 | } -------------------------------------------------------------------------------- /plugins/fec/fec_scheme_xor.plugin: -------------------------------------------------------------------------------- 1 | create_fec_schemes replace fec_scheme_protoops/create_xor_fec_scheme.o 2 | fec_recover replace fec_scheme_protoops/xor_fec_scheme.o 3 | fec_generate_repair_symbols replace fec_scheme_protoops/xor_fec_scheme_generate.o -------------------------------------------------------------------------------- /plugins/microbench/simple_for_loop.c: -------------------------------------------------------------------------------- 1 | #include "../helpers.h" 2 | 3 | uint64_t simple_for_loop(void *mem) { 4 | uint64_t sum = 0; 5 | for (uint64_t i = 0; i < 1000000000; i++) { 6 | sum = i + sum * 3 / 2; 7 | } 8 | return sum; 9 | } -------------------------------------------------------------------------------- /plugins/Makefile: -------------------------------------------------------------------------------- 1 | CLANG?=clang-6.0 2 | LLC?=llc-6.0 3 | export CLANG LLC 4 | SUBDIRS := basic monitoring datagram fec multipath qlog no_pacing ecn 5 | 6 | all: $(SUBDIRS) 7 | $(SUBDIRS): 8 | $(MAKE) -j$(nproc) -C $@ 9 | 10 | .PHONY: all $(SUBDIRS) 11 | -------------------------------------------------------------------------------- /plugins/qlog/sender/next_wake_time.c: -------------------------------------------------------------------------------- 1 | #include "../bpf.h" 2 | 3 | protoop_arg_t protoop_log(picoquic_cnx_t *cnx) { 4 | LOG_EVENT(cnx, "TRANSPORT", "NEXT_WAKE_TIME", "", "{\"time\": %" PRIu64 "}", get_cnx(cnx, AK_CNX_NEXT_WAKE_TIME, 0)); 5 | return 0; 6 | } -------------------------------------------------------------------------------- /plugins/ack_delay/bpf.h: -------------------------------------------------------------------------------- 1 | #ifndef ACK_DELAY_MULT 2 | #define ACK_DELAY_MULT 1 3 | #else 4 | #endif 5 | 6 | #ifndef ACK_DELAY_DIV 7 | #define ACK_DELAY_DIV 4 8 | #else 9 | #endif 10 | 11 | #ifndef ACK_THRESHOLD 12 | #define ACK_THRESHOLD 2 13 | #else 14 | #endif -------------------------------------------------------------------------------- /plugins/fec/fec_scheme_rlc_gf256.plugin: -------------------------------------------------------------------------------- 1 | create_fec_schemes replace fec_scheme_protoops/create_rlc_fec_scheme_gf256.o 2 | fec_recover replace fec_scheme_protoops/rlc_fec_scheme_gf256.o 3 | fec_generate_repair_symbols replace fec_scheme_protoops/rlc_fec_scheme_generate_gf256.o -------------------------------------------------------------------------------- /plugins/fec/fec_constant_redundancy_controller.plugin: -------------------------------------------------------------------------------- 1 | create_redundancy_controller replace constant_redundancy_controller_protoops/create_constant_redundancy_controller.o 2 | get_redundancy_parameters replace constant_redundancy_controller_protoops/get_constant_redundancy_parameters.o -------------------------------------------------------------------------------- /plugins/fec/fec_constant_redundancy_controller_burst.plugin: -------------------------------------------------------------------------------- 1 | create_redundancy_controller replace constant_redundancy_controller_protoops/create_constant_redundancy_controller.o 2 | get_redundancy_parameters replace constant_redundancy_controller_protoops/get_constant_redundancy_parameters_burst_handling.o -------------------------------------------------------------------------------- /plugins/fec/protoops/stream_always_encode_length.c: -------------------------------------------------------------------------------- 1 | #include "../../helpers.h" 2 | 3 | /** 4 | * See PROTOOP_NOPARAM_STREAM_ALWAYS_ENCODE_LENGTH 5 | */ 6 | 7 | protoop_arg_t stream_always_encode_length(picoquic_cnx_t* cnx) { 8 | set_cnx(cnx, AK_CNX_OUTPUT, 0, true); 9 | return 0; 10 | } -------------------------------------------------------------------------------- /plugins/fec/uniform_redundancy_controller_protoops/uniform_redundancy_controller.h: -------------------------------------------------------------------------------- 1 | #include "picoquic.h" 2 | 3 | #define DEFAULT_N 30 4 | #define DEFAULT_K 25 5 | 6 | typedef struct { 7 | uint64_t total_acknowledged_packets; 8 | uint64_t total_lost_packets; 9 | } uniform_redundancy_controller_t; -------------------------------------------------------------------------------- /plugins/monitoring/stream_closed.c: -------------------------------------------------------------------------------- 1 | #include "../helpers.h" 2 | #include "bpf.h" 3 | 4 | 5 | /** 6 | * See PROTOOP_NOPARAM_STREAM_CLOSED 7 | */ 8 | protoop_arg_t stream_closed(picoquic_cnx_t *cnx) 9 | { 10 | get_monitoring_metrics(cnx)->quic_metrics.streams_closed++; 11 | return 0; 12 | } -------------------------------------------------------------------------------- /plugins/monitoring/stream_opened.c: -------------------------------------------------------------------------------- 1 | #include "../helpers.h" 2 | #include "bpf.h" 3 | 4 | 5 | /** 6 | * See PROTOOP_NOPARAM_STREAM_OPENED 7 | */ 8 | protoop_arg_t stream_opened(picoquic_cnx_t *cnx) 9 | { 10 | get_monitoring_metrics(cnx)->quic_metrics.streams_opened++; 11 | return 0; 12 | } -------------------------------------------------------------------------------- /plugins/fec/fec_scheme_protoops/create_xor_fec_scheme.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | protoop_arg_t create_fec_scheme(picoquic_cnx_t *cnx) 5 | { 6 | set_cnx(cnx, AK_CNX_OUTPUT, 0, (protoop_arg_t) NULL); 7 | set_cnx(cnx, AK_CNX_OUTPUT, 1, (protoop_arg_t) NULL); 8 | return 0; 9 | } 10 | -------------------------------------------------------------------------------- /plugins/qlog/pop_log_context.c: -------------------------------------------------------------------------------- 1 | #include "bpf.h" 2 | 3 | /** 4 | * Input: None 5 | * 6 | * Output: None 7 | */ 8 | protoop_arg_t pop_context(picoquic_cnx_t *cnx) { 9 | qlog_t *qlog = get_qlog_t(cnx); 10 | char *ctx = pop_ctx(cnx, qlog); 11 | if (ctx) 12 | my_free(cnx, ctx); 13 | return 0; 14 | } -------------------------------------------------------------------------------- /plugins/qlog/frames/stream_opened.c: -------------------------------------------------------------------------------- 1 | #include "../bpf.h" 2 | 3 | protoop_arg_t stream_created(picoquic_cnx_t *cnx) { 4 | LOG_EVENT(cnx, "transport", "stream_state_updated", "", "{\"ptr\": \"%p\", \"stream_id\": \"%" PRIu64 "\", \"new\": \"open\"}", get_cnx(cnx, AK_CNX_INPUT, 0), get_cnx(cnx, AK_CNX_INPUT, 1)); 5 | return 0; 6 | } -------------------------------------------------------------------------------- /UnitTest1/stdafx.cpp: -------------------------------------------------------------------------------- 1 | // stdafx.cpp : source file that includes just the standard includes 2 | // UnitTest1.pch will be the pre-compiled header 3 | // stdafx.obj will contain the pre-compiled type information 4 | 5 | #include "stdafx.h" 6 | 7 | // TODO: reference any additional headers you need in STDAFX.H 8 | // and not in this file 9 | -------------------------------------------------------------------------------- /plugins/microbench/Makefile: -------------------------------------------------------------------------------- 1 | SRC=$(wildcard *.c) 2 | OBJ=$(SRC:.c=.o) 3 | CFLAGS=-I../../picoquic 4 | 5 | all: $(SRC) $(OBJ) 6 | 7 | $(OBJ): %.o 8 | 9 | %.o: %.c 10 | clang-6.0 $(CFLAGS) -O2 -fno-gnu-inline-asm -emit-llvm -c $< -o - | llc-6.0 -march=bpf -filetype=obj -o $@ 11 | 12 | clean: 13 | rm -rf *.o 14 | 15 | .PHONY: %.o -------------------------------------------------------------------------------- /plugins/westwood/Makefile: -------------------------------------------------------------------------------- 1 | SRC=$(wildcard *.c) 2 | OBJ=$(SRC:.c=.o) 3 | CFLAGS=-I../../picoquic 4 | 5 | all: $(SRC) $(OBJ) 6 | 7 | $(OBJ): %.o 8 | 9 | %.o: %.c 10 | clang-6.0 $(CFLAGS) -O2 -fno-gnu-inline-asm -emit-llvm -c $< -o - | llc-6.0 -march=bpf -filetype=obj -o $@ 11 | 12 | clean: 13 | rm -rf *.o 14 | 15 | .PHONY: %.o -------------------------------------------------------------------------------- /plugins/datagram/write_dummy_frame.c: -------------------------------------------------------------------------------- 1 | #include "../helpers.h" 2 | #include "bpf.h" 3 | 4 | protoop_arg_t write_datagram_frame(picoquic_cnx_t* cnx) 5 | { 6 | size_t consumed = 0; 7 | set_cnx(cnx, AK_CNX_OUTPUT, 0, (protoop_arg_t) consumed); 8 | set_cnx(cnx, AK_CNX_OUTPUT, 1, (protoop_arg_t) consumed); 9 | return 0; 10 | } -------------------------------------------------------------------------------- /plugins/fec/framework_protoops/block_flush_repair_symbols.c: -------------------------------------------------------------------------------- 1 | #include "../framework/block_framework_sender.h" 2 | 3 | 4 | protoop_arg_t block_flush_repair_symbols(picoquic_cnx_t *cnx) 5 | { 6 | block_fec_framework_t *bff = (block_fec_framework_t *) get_cnx(cnx, AK_CNX_INPUT, 0); 7 | return (protoop_arg_t) flush_fec_block(cnx, bff); 8 | } -------------------------------------------------------------------------------- /plugins/fec/framework_protoops/window_flush_repair_symbols.c: -------------------------------------------------------------------------------- 1 | #include "../framework/window_framework_sender.h" 2 | 3 | 4 | protoop_arg_t window_flush_repair_symbols(picoquic_cnx_t *cnx) 5 | { 6 | window_fec_framework_t *wff = (window_fec_framework_t *) get_cnx(cnx, AK_CNX_INPUT, 0); 7 | return (protoop_arg_t) flush_fec_window(cnx, wff); 8 | } -------------------------------------------------------------------------------- /plugins/qlog/frames/is_ack_needed.c: -------------------------------------------------------------------------------- 1 | #include "../bpf.h" 2 | 3 | protoop_arg_t protoop_log(picoquic_cnx_t *cnx) { 4 | if (get_cnx(cnx, AK_CNX_RETURN_VALUE, 0)) { 5 | LOG_EVENT(cnx, "transport", "ack_needed", "", "{\"path\": \"%p\", \"pc\": %d}", get_cnx(cnx, AK_CNX_INPUT, 2), get_cnx(cnx, AK_CNX_INPUT, 1)); 6 | } 7 | return 0; 8 | } -------------------------------------------------------------------------------- /plugins/disable_congestion_control/Makefile: -------------------------------------------------------------------------------- 1 | SRC=$(wildcard *.c) 2 | OBJ=$(SRC:.c=.o) 3 | CFLAGS=-I../../picoquic 4 | 5 | all: $(SRC) $(OBJ) 6 | 7 | $(OBJ): %.o 8 | 9 | %.o: %.c 10 | clang-6.0 $(CFLAGS) -O2 -fno-gnu-inline-asm -emit-llvm -c $< -o - | llc-6.0 -march=bpf -filetype=obj -o $@ 11 | 12 | clean: 13 | rm -rf *.o 14 | 15 | .PHONY: %.o -------------------------------------------------------------------------------- /UnitTest1/targetver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Including SDKDDKVer.h defines the highest available Windows platform. 4 | 5 | // If you wish to build your application for a previous Windows platform, include WinSDKVer.h and 6 | // set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. 7 | 8 | #include 9 | -------------------------------------------------------------------------------- /plugins/tlp/Makefile: -------------------------------------------------------------------------------- 1 | SRC=$(wildcard *.c) 2 | OBJ=$(SRC:.c=.o) 3 | CFLAGS=-I../../picoquic -DDISABLE_PROTOOP_PRINTF 4 | 5 | all: $(SRC) $(OBJ) 6 | 7 | $(OBJ): %.o 8 | 9 | %.o: %.c 10 | clang-6.0 $(CFLAGS) -O2 -fno-gnu-inline-asm -emit-llvm -c $< -o - | llc-6.0 -march=bpf -filetype=obj -o $@ 11 | 12 | clean: 13 | rm -rf *.o 14 | 15 | .PHONY: %.o -------------------------------------------------------------------------------- /plugins/fec/constant_redundancy_controller_protoops/create_constant_redundancy_controller.c: -------------------------------------------------------------------------------- 1 | #include "picoquic.h" 2 | #include "getset.h" 3 | 4 | // sets as output the pointer towards the controller's state 5 | protoop_arg_t create_constant_redundancy_controller(picoquic_cnx_t *cnx) 6 | { 7 | set_cnx(cnx, AK_CNX_OUTPUT, 0, (protoop_arg_t) NULL); 8 | return 0; 9 | } -------------------------------------------------------------------------------- /plugins/no_pacing/Makefile: -------------------------------------------------------------------------------- 1 | SRC=$(wildcard *.c) 2 | OBJ=$(SRC:.c=.o) 3 | CFLAGS=-I../../picoquic 4 | CLANG?=clang-6.0 5 | LLC?=llc-6.0 6 | 7 | all: $(SRC) $(OBJ) 8 | 9 | $(OBJ): %.o 10 | 11 | %.o: %.c 12 | $(CLANG) $(CFLAGS) -O2 -fno-gnu-inline-asm -emit-llvm -c $< -o - | $(LLC) -march=bpf -filetype=obj -o $@ 13 | 14 | clean: 15 | rm -rf *.o 16 | 17 | .PHONY: %.o -------------------------------------------------------------------------------- /plugins/stream_scheduling_rr/Makefile: -------------------------------------------------------------------------------- 1 | SRC=$(wildcard *.c) 2 | OBJ=$(SRC:.c=.o) 3 | CFLAGS=-I../../picoquic -DDISABLE_PROTOOP_PRINTF 4 | 5 | all: $(SRC) $(OBJ) 6 | 7 | $(OBJ): %.o 8 | 9 | %.o: %.c 10 | clang-6.0 $(CFLAGS) -O2 -fno-gnu-inline-asm -emit-llvm -c $< -o - | llc-6.0 -march=bpf -filetype=obj -o $@ 11 | 12 | clean: 13 | rm -rf *.o 14 | 15 | .PHONY: %.o 16 | -------------------------------------------------------------------------------- /plugins/basic/basic.plugin: -------------------------------------------------------------------------------- 1 | be.qdeconinck.basic 2 | set_next_wake_time replace set_next_wake_time.o 3 | retransmit_needed_by_packet replace retransmit_needed_by_packet.o 4 | retransmit_needed replace retransmit_needed.o 5 | update_rtt replace update_rtt.o 6 | process_ack_range replace process_ack_range.o 7 | process_possible_ack_of_ack_frame replace process_possible_ack_of_ack_frame.o -------------------------------------------------------------------------------- /plugins/qlog/Makefile: -------------------------------------------------------------------------------- 1 | SRC=$(shell find -name "*.c") 2 | OBJ=$(SRC:.c=.o) 3 | CFLAGS=-I../../picoquic 4 | CLANG?=clang-6.0 5 | LLC?=llc-6.0 6 | 7 | all: $(SRC) $(OBJ) 8 | 9 | $(OBJ): %.o 10 | 11 | %.o: %.c 12 | $(CLANG) $(CFLAGS) -O2 -fno-gnu-inline-asm -emit-llvm -c $< -o - | $(LLC) -march=bpf -filetype=obj -o $@ 13 | 14 | clean: 15 | rm -rf *.o 16 | 17 | .PHONY: %.o -------------------------------------------------------------------------------- /plugins/ecn/ecn.plugin: -------------------------------------------------------------------------------- 1 | be.mpiraux.ecn 2 | before_sending_packet post before_sending_packet.o 3 | header_parsed post header_parsed.o 4 | received_packet post received_packet.o 5 | parse_ecn_block replace parse_ecn_block.o 6 | write_ecn_block replace write_ecn_block.o 7 | process_ecn_block replace process_ecn_block.o 8 | skip_frame pre pre_skip_frame.o 9 | skip_frame post post_skip_frame.o -------------------------------------------------------------------------------- /plugins/fec/framework_protoops/block_get_source_fpid.c: -------------------------------------------------------------------------------- 1 | #include "../framework/block_framework_sender.h" 2 | #include "../framework/block_framework_receiver.h" 3 | 4 | 5 | protoop_arg_t block_get_source_fpid(picoquic_cnx_t *cnx) 6 | { 7 | block_fec_framework_t *bff = (block_fec_framework_t *) get_cnx(cnx, AK_CNX_INPUT, 0); 8 | return (protoop_arg_t) get_source_fpid(bff).raw; 9 | } -------------------------------------------------------------------------------- /plugins/fec/framework_protoops/window_get_source_fpid.c: -------------------------------------------------------------------------------- 1 | #include "../framework/window_framework_sender.h" 2 | #include "../framework/window_framework_receiver.h" 3 | 4 | 5 | protoop_arg_t window_get_source_fpid(picoquic_cnx_t *cnx) 6 | { 7 | window_fec_framework_t *wff = (window_fec_framework_t *) get_cnx(cnx, AK_CNX_INPUT, 0); 8 | return (protoop_arg_t) get_source_fpid(wff).raw; 9 | } -------------------------------------------------------------------------------- /plugins/multipath/notify_rtt_probe.c: -------------------------------------------------------------------------------- 1 | #include "bpf.h" 2 | 3 | 4 | protoop_arg_t notify_rtt_probe(picoquic_cnx_t *cnx) 5 | { 6 | reserve_frame_slot_t *rfs = (reserve_frame_slot_t *) get_cnx(cnx, AK_CNX_INPUT, 0); 7 | /* Commented out, can be used if needed */ 8 | /* int received = (int) get_cnx(cnx, AK_CNX_INPUT, 1); */ 9 | my_free(cnx, rfs); 10 | return 0; 11 | } -------------------------------------------------------------------------------- /UnitTest1/stdafx.h: -------------------------------------------------------------------------------- 1 | // stdafx.h : include file for standard system include files, 2 | // or project specific include files that are used frequently, but 3 | // are changed infrequently 4 | // 5 | 6 | #pragma once 7 | 8 | #include "targetver.h" 9 | 10 | // Headers for CppUnitTest 11 | #include "CppUnitTest.h" 12 | 13 | // TODO: reference additional headers your program requires here 14 | -------------------------------------------------------------------------------- /plugins/datagram/Makefile: -------------------------------------------------------------------------------- 1 | SRC=$(wildcard *.c) 2 | OBJ=$(SRC:.c=.o) 3 | CFLAGS=-I../../picoquic -DDISABLE_PROTOOP_PRINTF 4 | CLANG?=clang-6.0 5 | LLC?=llc-6.0 6 | 7 | all: $(SRC) $(OBJ) 8 | 9 | $(OBJ): %.o 10 | 11 | %.o: %.c 12 | $(CLANG) $(CFLAGS) -O2 -fno-gnu-inline-asm -emit-llvm -c $< -o - | $(LLC) -march=bpf -filetype=obj -o $@ 13 | 14 | clean: 15 | rm -rf *.o 16 | 17 | .PHONY: %.o -------------------------------------------------------------------------------- /plugins/multipath/notify_mp_ack_frame.c: -------------------------------------------------------------------------------- 1 | #include "bpf.h" 2 | 3 | 4 | protoop_arg_t notify_mp_ack_frame(picoquic_cnx_t *cnx) 5 | { 6 | reserve_frame_slot_t *rfs = (reserve_frame_slot_t *) get_cnx(cnx, AK_CNX_INPUT, 0); 7 | /* Commented out, can be used if needed */ 8 | /* int received = (int) get_cnx(cnx, AK_CNX_INPUT, 1); */ 9 | my_free(cnx, rfs); 10 | return 0; 11 | } -------------------------------------------------------------------------------- /plugins/basic/Makefile: -------------------------------------------------------------------------------- 1 | SRC=$(wildcard *.c) 2 | OBJ=$(SRC:.c=.o) 3 | CFLAGS=-I../../picoquic -Werror -DDISABLE_PROTOOP_PRINTF 4 | CLANG?=clang-6.0 5 | LLC?=llc-6.0 6 | 7 | all: $(SRC) $(OBJ) 8 | 9 | $(OBJ): %.o 10 | 11 | %.o: %.c 12 | $(CLANG) $(CFLAGS) -O2 -fno-gnu-inline-asm -emit-llvm -c $< -o - | $(LLC) -march=bpf -filetype=obj -o $@ 13 | 14 | clean: 15 | rm -rf *.o 16 | 17 | .PHONY: %.o -------------------------------------------------------------------------------- /plugins/monitoring/stream_frame_written.c: -------------------------------------------------------------------------------- 1 | #include "../helpers.h" 2 | #include "bpf.h" 3 | 4 | /** 5 | * See PROTOOP_NOPARAM_PREPARE_STREAM_FRAME 6 | */ 7 | protoop_arg_t prepare_stream_frame(picoquic_cnx_t *cnx) 8 | { 9 | monitoring_conn_metrics *metrics = get_monitoring_metrics(cnx); 10 | metrics->quic_metrics.app_data_sent += get_cnx(cnx, AK_CNX_OUTPUT, 0); 11 | return 0; 12 | } -------------------------------------------------------------------------------- /plugins/monitoring/Makefile: -------------------------------------------------------------------------------- 1 | SRC=$(wildcard *.c) 2 | OBJ=$(SRC:.c=.o) 3 | CFLAGS=-I../../picoquic -Werror -DDISABLE_PROTOOP_PRINTF 4 | CLANG?=clang-6.0 5 | LLC?=llc-6.0 6 | 7 | all: $(SRC) $(OBJ) 8 | 9 | $(OBJ): %.o 10 | 11 | %.o: %.c 12 | $(CLANG) $(CFLAGS) -O2 -fno-gnu-inline-asm -emit-llvm -c $< -o - | $(LLC) -march=bpf -filetype=obj -o $@ 13 | 14 | clean: 15 | rm -rf *.o 16 | 17 | .PHONY: %.o -------------------------------------------------------------------------------- /plugins/qlog/sender/path_bandwidth_estimated.c: -------------------------------------------------------------------------------- 1 | #include "../bpf.h" 2 | 3 | protoop_arg_t protoop_log(picoquic_cnx_t *cnx) { 4 | picoquic_path_t* path_x = (picoquic_path_t *) get_cnx(cnx, AK_CNX_INPUT, 0); 5 | LOG_EVENT(cnx, "recovery", "metrics_updated", "", "{\"cc_path\": \"%p\", \"bandwidth\": \"%lu\"}", (protoop_arg_t) path_x, get_path(path_x, AK_PATH_BANDWIDTH_ESTIMATE, 0)); 6 | return 0; 7 | } -------------------------------------------------------------------------------- /plugins/ecn/Makefile: -------------------------------------------------------------------------------- 1 | SRC=$(wildcard *.c) 2 | OBJ=$(SRC:.c=.o) 3 | CFLAGS=-I../../picoquic -DDISABLE_PROTOOP_PRINTF 4 | CLANG?=clang-6.0 5 | LLC?=llc-6.0 6 | export CLANG LLC 7 | 8 | all: $(SRC) $(OBJ) 9 | 10 | $(OBJ): %.o 11 | 12 | %.o: %.c 13 | $(CLANG) $(CFLAGS) -O2 -fno-gnu-inline-asm -emit-llvm -c $< -o - | $(LLC) -march=bpf -filetype=obj -o $@ 14 | 15 | clean: 16 | rm -rf *.o 17 | 18 | .PHONY: %.o -------------------------------------------------------------------------------- /plugins/datagram/notify_datagram_frame.c: -------------------------------------------------------------------------------- 1 | #include "../helpers.h" 2 | #include "bpf.h" 3 | 4 | 5 | protoop_arg_t notify_datagram_frame(picoquic_cnx_t *cnx) 6 | { 7 | reserve_frame_slot_t *rfs = (reserve_frame_slot_t *) get_cnx(cnx, AK_CNX_INPUT, 0); 8 | /* Commented out, can be used if needed */ 9 | /* int received = (int) get_cnx(cnx, AK_CNX_INPUT, 1); */ 10 | my_free(cnx, rfs); 11 | return 0; 12 | } -------------------------------------------------------------------------------- /plugins/multipath/path_schedulers/Makefile: -------------------------------------------------------------------------------- 1 | SRC=$(wildcard *.c) 2 | OBJ=$(SRC:.c=.o) 3 | CFLAGS=-I../../../picoquic -DDISABLE_PROTOOP_PRINTF -DDISABLE_QLOG 4 | CLANG?=clang-6.0 5 | LLC?=llc-6.0 6 | 7 | all: $(SRC) $(OBJ) 8 | 9 | $(OBJ): %.o 10 | 11 | %.o: %.c 12 | $(CLANG) $(CFLAGS) -O2 -fno-gnu-inline-asm -emit-llvm -c $< -o - | $(LLC) -march=bpf -filetype=obj -o $@ 13 | 14 | clean: 15 | rm -rf *.o 16 | 17 | .PHONY: %.o -------------------------------------------------------------------------------- /plugins/fec/protoops/notify_fec_frame.c: -------------------------------------------------------------------------------- 1 | #include "../../helpers.h" 2 | #include "../fec_protoops.h" 3 | 4 | 5 | protoop_arg_t notify_fec_frame(picoquic_cnx_t *cnx) 6 | { 7 | reserve_frame_slot_t *rfs = (reserve_frame_slot_t *) get_cnx(cnx, AK_CNX_INPUT, 0); 8 | /* Commented out, can be used if needed */ 9 | /* int received = (int) get_cnx(cnx, AK_CNX_INPUT, 1); */ 10 | my_free(cnx, rfs); 11 | return 0; 12 | } -------------------------------------------------------------------------------- /plugins/fec/protoops/notify_fpid_frame.c: -------------------------------------------------------------------------------- 1 | #include "../../helpers.h" 2 | #include "../fec_protoops.h" 3 | 4 | 5 | protoop_arg_t notify_fpid_frame(picoquic_cnx_t *cnx) 6 | { 7 | reserve_frame_slot_t *rfs = (reserve_frame_slot_t *) get_cnx(cnx, AK_CNX_INPUT, 0); 8 | /* Commented out, can be used if needed */ 9 | /* int received = (int) get_cnx(cnx, AK_CNX_INPUT, 1); */ 10 | my_free(cnx, rfs); 11 | return 0; 12 | } -------------------------------------------------------------------------------- /plugins/fec/protoops/send_repair_symbols_when_no_stream_data_to_send.c: -------------------------------------------------------------------------------- 1 | #include "../../helpers.h" 2 | 3 | /** 4 | * returns true when no ready stream is found 5 | */ 6 | protoop_arg_t should_send_repair_symbols(picoquic_cnx_t *cnx) 7 | { 8 | // if no stream data to send, do not protect anything anymore 9 | void *ret = (void *) run_noparam(cnx, "find_ready_stream", 0, NULL, NULL); 10 | return (protoop_arg_t) (ret == NULL); 11 | } -------------------------------------------------------------------------------- /plugins/fec/fec_uniform_redundancy_controller.plugin: -------------------------------------------------------------------------------- 1 | create_redundancy_controller replace uniform_redundancy_controller_protoops/create_uniform_redundancy_controller.o 2 | get_redundancy_parameters replace uniform_redundancy_controller_protoops/get_uniform_redundancy_parameters.o 3 | congestion_algorithm_notify pre uniform_redundancy_controller_protoops/notified_acknowledgement.o 4 | packet_was_lost pre uniform_redundancy_controller_protoops/packet_was_lost.o -------------------------------------------------------------------------------- /plugins/ack_delay/Makefile: -------------------------------------------------------------------------------- 1 | SRC=$(wildcard *.c) 2 | OBJ=$(SRC:.c=.o) 3 | CFLAGS=-I../../picoquic -DDISABLE_PROTOOP_PRINTF -DACK_DELAY_MULT=$(ACK_DELAY_MULT) -DACK_DELAY_DIV=$(ACK_DELAY_DIV) -DACK_THRESHOLD=$(ACK_THRESHOLD) 4 | 5 | all: $(SRC) $(OBJ) 6 | 7 | $(OBJ): %.o 8 | 9 | %.o: %.c 10 | clang-6.0 $(CFLAGS) -O2 -fno-gnu-inline-asm -emit-llvm -c $< -o - | llc-6.0 -march=bpf -filetype=obj -o $@ 11 | 12 | clean: 13 | rm -rf *.o 14 | 15 | .PHONY: %.o -------------------------------------------------------------------------------- /plugins/fec/protoops/skip_frame_pre.c: -------------------------------------------------------------------------------- 1 | #include "picoquic.h" 2 | #include "../fec_protoops.h" 3 | 4 | 5 | /** 6 | * cnx->protoop_inputv[0] = fec_frame_t* frame 7 | * 8 | * Output: uint8_t* bytes 9 | */ 10 | protoop_arg_t skip_frame(picoquic_cnx_t *cnx) 11 | { 12 | bpf_state *state = get_bpf_state(cnx); 13 | if (!state) 14 | return PICOQUIC_ERROR_MEMORY; 15 | state->is_in_skip_frame = true; 16 | return (protoop_arg_t) 0; 17 | } -------------------------------------------------------------------------------- /plugins/qlog/frames/template: -------------------------------------------------------------------------------- 1 | #include "../bpf.h" 2 | 3 | protoop_arg_t protoop_log(picoquic_cnx_t *cnx) { 4 | TMP_FRAME_BEGIN(cnx, parsed_frame, frame, reset_stream_frame_t) 5 | LOG_EVENT(cnx, "FRAMES", "RST_STREAM_PARSED", "", "{\"ptr\": \"%p\", \"stream_id\": %" PRIu64 ", \"error\": %d, \"offset\": %" PRIu64 "}", (protoop_arg_t) parsed_frame, frame.stream_id, frame.app_error_code, frame.final_offset); 6 | TMP_FRAME_END 7 | return 0; 8 | } -------------------------------------------------------------------------------- /plugins/ecn/received_packet.c: -------------------------------------------------------------------------------- 1 | #include "picoquic.h" 2 | #include "plugin.h" 3 | #include "bpf.h" 4 | 5 | /** 6 | * See "received_packet" 7 | * cnx->protoop_inputv[0] = SOCKET_TYPE socket 8 | * cnx->protoop_inputv[1] = int tos 9 | * 10 | * Output: None 11 | */ 12 | protoop_arg_t received_packet(picoquic_cnx_t *cnx) 13 | { 14 | int tos = (int) get_cnx(cnx, AK_CNX_INPUT, 1); 15 | get_bpf_data(cnx)->ecn_val = tos & 0x03; 16 | return 0; 17 | } -------------------------------------------------------------------------------- /plugins/fec/protoops/skip_frame_post.c: -------------------------------------------------------------------------------- 1 | #include "picoquic.h" 2 | #include "../fec_protoops.h" 3 | 4 | 5 | /** 6 | * cnx->protoop_inputv[0] = fec_frame_t* frame 7 | * 8 | * Output: uint8_t* bytes 9 | */ 10 | protoop_arg_t skip_frame(picoquic_cnx_t *cnx) 11 | { 12 | bpf_state *state = get_bpf_state(cnx); 13 | if (!state) 14 | return PICOQUIC_ERROR_MEMORY; 15 | state->is_in_skip_frame = false; 16 | return (protoop_arg_t) 0; 17 | } -------------------------------------------------------------------------------- /plugins/qlog/sender/segment_aborted.c: -------------------------------------------------------------------------------- 1 | #include "../bpf.h" 2 | 3 | protoop_arg_t segment_aborted(picoquic_cnx_t *cnx) 4 | { 5 | qlog_t *qlog = get_qlog_t(cnx); 6 | qlog_frames_t *f = qlog->frames_head; 7 | while(f) { 8 | qlog_frames_t *t = f; 9 | f = f->next; 10 | my_free(cnx, t->frame); 11 | my_free(cnx, t); 12 | } 13 | qlog->frames_head = NULL; 14 | qlog->frames_tail = NULL; 15 | return 0; 16 | } -------------------------------------------------------------------------------- /plugins/disable_congestion_control/congestion_notify.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | 6 | 7 | 8 | 9 | 10 | /** 11 | * See PROTOOP_NOPARAM_CONGESTION_ALGORITHM_NOTIFY 12 | */ 13 | protoop_arg_t congestion_algorithm_notify(picoquic_cnx_t *cnx) 14 | { 15 | picoquic_path_t* path_x = (picoquic_path_t *) get_cnx(cnx, AK_CNX_INPUT, 0); 16 | set_path(path_x, AK_PATH_CWIN, 0, UINT64_MAX); 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | */Debug 2 | Debug 3 | */Release 4 | Release 5 | */.vs 6 | .vs 7 | */Generated Files 8 | *.sdf 9 | */*.sdf 10 | */*.user 11 | *.ipch 12 | */*.ipch 13 | *.db 14 | */*.db 15 | */*.lib 16 | */*.pdb 17 | */AppX 18 | */*.exe 19 | */*.dll 20 | */*.xbf 21 | */*.ilk 22 | *.b 23 | **/*.o 24 | html/** 25 | latex/** 26 | *.pcap 27 | __pycache__ 28 | *.pyc 29 | random_* 30 | .idea 31 | callgrind.* 32 | *.log 33 | *.a 34 | CMakeCache.txt 35 | CMakeFiles 36 | benchmarks/*.sqlite 37 | -------------------------------------------------------------------------------- /plugins/fec/protoops/maybe_notify_recovered_packets_to_cc.c: -------------------------------------------------------------------------------- 1 | #include "../fec_protoops.h" 2 | 3 | 4 | protoop_arg_t prepare_packet_ready(picoquic_cnx_t *cnx) 5 | { 6 | uint64_t current_time = get_cnx(cnx, AK_CNX_INPUT, 2); 7 | bpf_state *state = get_bpf_state(cnx); 8 | if (!state) return PICOQUIC_ERROR_MEMORY; 9 | 10 | if (state->recovered_packets.size) maybe_notify_recovered_packets_to_cc(cnx, &state->recovered_packets, current_time); 11 | return 0; 12 | } -------------------------------------------------------------------------------- /plugins/fec/framework_protoops/block_protect_source_symbol.c: -------------------------------------------------------------------------------- 1 | #include "../framework/block_framework_sender.h" 2 | #include "../framework/block_framework_receiver.h" 3 | 4 | 5 | protoop_arg_t fec_protect_source_symbol(picoquic_cnx_t *cnx) 6 | { 7 | block_fec_framework_t *bff = (block_fec_framework_t *) get_cnx(cnx, AK_CNX_INPUT, 0); 8 | source_symbol_t *ss = (source_symbol_t *) get_cnx(cnx, AK_CNX_INPUT, 1); 9 | return (protoop_arg_t) protect_source_symbol(cnx, bff, ss); 10 | } -------------------------------------------------------------------------------- /plugins/fec/framework_protoops/window_protect_source_symbol.c: -------------------------------------------------------------------------------- 1 | #include "../framework/window_framework_sender.h" 2 | #include "../framework/window_framework_receiver.h" 3 | 4 | 5 | protoop_arg_t fec_protect_source_symbol(picoquic_cnx_t *cnx) 6 | { 7 | window_fec_framework_t *wff = (window_fec_framework_t *) get_cnx(cnx, AK_CNX_INPUT, 0); 8 | source_symbol_t *ss = (source_symbol_t *) get_cnx(cnx, AK_CNX_INPUT, 1); 9 | return (protoop_arg_t) protect_source_symbol(cnx, wff, ss); 10 | } -------------------------------------------------------------------------------- /plugins/fec/uniform_redundancy_controller_protoops/packet_was_lost.c: -------------------------------------------------------------------------------- 1 | #include "uniform_redundancy_controller.h" 2 | #include "../fec_protoops.h" 3 | 4 | // sets as output the pointer towards the controller's state 5 | protoop_arg_t packet_was_lost(picoquic_cnx_t *cnx) 6 | { 7 | bpf_state *state = get_bpf_state(cnx); 8 | if (!state) return PICOQUIC_ERROR_MEMORY; 9 | uniform_redundancy_controller_t *urc = state->controller; 10 | urc->total_lost_packets++; 11 | return 0; 12 | } -------------------------------------------------------------------------------- /plugins/fec/protoops/notify_recovered_frame.c: -------------------------------------------------------------------------------- 1 | #include "../../helpers.h" 2 | #include "../fec_protoops.h" 3 | 4 | 5 | protoop_arg_t notify_recovered_frame(picoquic_cnx_t *cnx) 6 | { 7 | reserve_frame_slot_t *rfs = (reserve_frame_slot_t *) get_cnx(cnx, AK_CNX_INPUT, 0); 8 | /* Commented out, can be used if needed */ 9 | /* int received = (int) get_cnx(cnx, AK_CNX_INPUT, 1); */ 10 | // the frame_ctx must be freed in the write_frame 11 | my_free(cnx, rfs); 12 | return 0; 13 | } -------------------------------------------------------------------------------- /plugins/multipath/notify_uniflows_frame.c: -------------------------------------------------------------------------------- 1 | #include "bpf.h" 2 | 3 | protoop_arg_t notify_uniflows_frame(picoquic_cnx_t *cnx) 4 | { 5 | reserve_frame_slot_t *rfs = (reserve_frame_slot_t *) get_cnx(cnx, AK_CNX_INPUT, 0); 6 | /* Commented out, can be used if needed */ 7 | int received = (int) get_cnx(cnx, AK_CNX_INPUT, 1); 8 | if (!received) { 9 | ((uniflow_data_t *)rfs->frame_ctx)->has_sent_uniflows_frame = false; 10 | } 11 | my_free(cnx, rfs); 12 | return 0; 13 | } -------------------------------------------------------------------------------- /plugins/fec/fec_framework_block.plugin: -------------------------------------------------------------------------------- 1 | create_fec_framework replace framework_protoops/block_create_framework.o 2 | flush_repair_symbols replace framework_protoops/block_flush_repair_symbols.o 3 | get_source_fpid replace framework_protoops/block_get_source_fpid.o 4 | fec_protect_source_symbol replace framework_protoops/block_protect_source_symbol.o 5 | receive_source_symbol replace framework_protoops/block_receive_source_symbol.o 6 | receive_repair_symbol replace framework_protoops/block_receive_repair_symbol.o -------------------------------------------------------------------------------- /plugins/microbench/get_set_cnx_fields_loop.c: -------------------------------------------------------------------------------- 1 | #include "../helpers.h" 2 | 3 | uint64_t get_set_cnx_fields_loop(picoquic_cnx_t *cnx) { 4 | uint64_t sum = 0; 5 | for (uint64_t i = 0; i < 500000000; i++) { 6 | sum += get_cnx(cnx, AK_CNX_START_TIME, 0); 7 | sum += get_cnx(cnx, AK_CNX_LATEST_PROGRESS_TIME, 0); 8 | set_cnx(cnx, AK_CNX_START_TIME, 0, 2 * sum + 3 * i); 9 | set_cnx(cnx, AK_CNX_LATEST_PROGRESS_TIME, 0, 3 * sum / 4 + i); 10 | } 11 | return sum; 12 | } -------------------------------------------------------------------------------- /plugins/fec/framework_protoops/block_receive_source_symbol.c: -------------------------------------------------------------------------------- 1 | #include "../framework/block_framework_sender.h" 2 | #include "../framework/block_framework_receiver.h" 3 | 4 | 5 | protoop_arg_t receive_source_symbol(picoquic_cnx_t *cnx) 6 | { 7 | bpf_state *state = get_bpf_state(cnx); 8 | if (!state) 9 | return PICOQUIC_ERROR_MEMORY; 10 | return (protoop_arg_t) block_receive_source_symbol(cnx, state, (source_symbol_t *) get_cnx(cnx, AK_CNX_INPUT, 0), (bool) get_cnx(cnx, AK_CNX_INPUT, 1)); 11 | } -------------------------------------------------------------------------------- /plugins/stream_scheduling_rr/bpf.h: -------------------------------------------------------------------------------- 1 | #define RR_OPAQUE_ID 0x0 2 | 3 | static __attribute__((always_inline)) uint64_t *get_last_drr_stream_id(picoquic_cnx_t *cnx) 4 | { 5 | uint64_t *bpfd_ptr = (uint64_t *) get_cnx_metadata(cnx, RR_OPAQUE_ID); 6 | if (!bpfd_ptr) { 7 | bpfd_ptr = my_malloc_ex(cnx, sizeof(uint64_t)); 8 | /* TODO handle NULL */ 9 | *bpfd_ptr = 0; 10 | set_cnx_metadata(cnx, RR_OPAQUE_ID, (protoop_arg_t) bpfd_ptr); 11 | } 12 | return bpfd_ptr; 13 | } 14 | -------------------------------------------------------------------------------- /plugins/fec/protoops/connection_state_changed.c: -------------------------------------------------------------------------------- 1 | 2 | 3 | #include "../fec_protoops.h" 4 | 5 | 6 | protoop_arg_t connection_state_changed(picoquic_cnx_t *cnx) 7 | { 8 | // We ensure to laod the FEC frameworks and schemes as soon as possible in the connection life 9 | picoquic_state_enum from_state = (picoquic_state_enum) get_cnx(cnx, AK_CNX_INPUT, 0); 10 | if (from_state == picoquic_state_client_init || from_state == picoquic_state_server_almost_ready) 11 | get_bpf_state(cnx); 12 | return 0; 13 | } -------------------------------------------------------------------------------- /plugins/fec/protoops/process_fec_frame.c: -------------------------------------------------------------------------------- 1 | #include "picoquic.h" 2 | #include "../fec_protoops.h" 3 | 4 | 5 | /** 6 | * cnx->protoop_inputv[0] = fec_frame_t* frame 7 | * 8 | * Output: uint8_t* bytes 9 | */ 10 | protoop_arg_t process_fec_frame(picoquic_cnx_t *cnx) 11 | { 12 | fec_frame_t *frame = (fec_frame_t *) get_cnx(cnx, AK_CNX_INPUT, 0); 13 | PROTOOP_PRINTF(cnx, "PROCESS FEC FRAME\n"); 14 | process_fec_frame_helper(cnx, frame); 15 | my_free(cnx, frame->data); 16 | return (protoop_arg_t) 0; 17 | } -------------------------------------------------------------------------------- /plugins/fec/fec.plugin: -------------------------------------------------------------------------------- 1 | be.michelfra.fecxor 2 | stream_always_encode_length replace protoops/stream_always_encode_length.o 3 | should_send_repair_symbols replace protoops/always_send_repair_symbols.o 4 | should_send_recovered_frames replace protoops/always_send_recovered_frames.o 5 | window_select_symbols_to_protect replace framework_protoops/window_protect_all_unprotected_source_symbols.o 6 | fec_core.plugin include 7 | fec_framework_window.plugin include 8 | fec_scheme_xor.plugin include 9 | fec_constant_redundancy_controller.plugin include -------------------------------------------------------------------------------- /plugins/qlog/frames/blocked_frame_parsed.c: -------------------------------------------------------------------------------- 1 | #include "../bpf.h" 2 | 3 | protoop_arg_t protoop_log(picoquic_cnx_t *cnx) { 4 | TMP_FRAME_BEGIN(cnx, parsed_frame, frame, blocked_frame_t) 5 | char *frame_str = my_malloc(cnx, 100); 6 | if (!frame_str) return 0; 7 | PROTOOP_SNPRINTF(cnx, frame_str, 100, "{\"frame_type\": \"data_blocked\", \"limit\": \"%" PRIu64 "\"}", frame.offset); 8 | helper_log_frame(cnx, frame_str); 9 | my_free(cnx, frame_str); 10 | TMP_FRAME_END 11 | return 0; 12 | } -------------------------------------------------------------------------------- /plugins/qlog/frames/max_data_parsed.c: -------------------------------------------------------------------------------- 1 | #include "../bpf.h" 2 | 3 | protoop_arg_t protoop_log(picoquic_cnx_t *cnx) { 4 | TMP_FRAME_BEGIN(cnx, parsed_frame, frame, max_data_frame_t) 5 | char *frame_str = my_malloc(cnx, 100); 6 | if (!frame_str) return 0; 7 | PROTOOP_SNPRINTF(cnx, frame_str, 100, "{\"frame_type\": \"max_data\", \"maximum\": \"%" PRIu64 "\"}", frame.maximum_data); 8 | helper_log_frame(cnx, frame_str); 9 | my_free(cnx, frame_str); 10 | TMP_FRAME_END 11 | return 0; 12 | } -------------------------------------------------------------------------------- /plugins/qlog/push_log_context.c: -------------------------------------------------------------------------------- 1 | #include "bpf.h" 2 | 3 | /** 4 | * Input: None 5 | * 6 | * Output: None 7 | */ 8 | protoop_arg_t push_context(picoquic_cnx_t *cnx) { 9 | qlog_t *qlog = get_qlog_t(cnx); 10 | char *core_ctx = (char *) get_cnx(cnx, AK_CNX_INPUT, 0); 11 | size_t core_ctx_len = strlen(core_ctx) + 1; 12 | char *ctx = (char *) my_malloc(cnx, core_ctx_len); 13 | if (ctx) { 14 | my_memcpy(ctx, core_ctx, core_ctx_len); 15 | push_ctx(cnx, qlog, ctx); 16 | } 17 | return 0; 18 | } -------------------------------------------------------------------------------- /plugins/multipath/qlog/frame_prepared.c: -------------------------------------------------------------------------------- 1 | #include "../bpf.h" 2 | 3 | protoop_arg_t protoop_log(picoquic_cnx_t *cnx) { 4 | int ret = (int) get_cnx(cnx, AK_CNX_RETURN_VALUE, 0); 5 | size_t consumed = (size_t) get_cnx(cnx, AK_CNX_OUTPUT, 0); 6 | if (ret == 0 && consumed > 0) { 7 | uint8_t *bytes = (uint8_t *) get_cnx(cnx, AK_CNX_INPUT, 0); 8 | size_t skip_consumed = 0; 9 | int pure_ack = 0; 10 | helper_skip_frame(cnx, bytes, consumed, &skip_consumed, &pure_ack); 11 | } 12 | return 0; 13 | } -------------------------------------------------------------------------------- /plugins/qlog/frames/frame_prepared.c: -------------------------------------------------------------------------------- 1 | #include "../bpf.h" 2 | 3 | protoop_arg_t protoop_log(picoquic_cnx_t *cnx) { 4 | int ret = (int) get_cnx(cnx, AK_CNX_RETURN_VALUE, 0); 5 | size_t consumed = (size_t) get_cnx(cnx, AK_CNX_OUTPUT, 0); 6 | if (ret == 0 && consumed > 0) { 7 | uint8_t *bytes = (uint8_t *) get_cnx(cnx, AK_CNX_INPUT, 0); 8 | size_t skip_consumed = 0; 9 | int pure_ack = 0; 10 | helper_skip_frame(cnx, bytes, consumed, &skip_consumed, &pure_ack); 11 | } 12 | return 0; 13 | } -------------------------------------------------------------------------------- /plugins/fec/framework_protoops/window_receive_source_symbol.c: -------------------------------------------------------------------------------- 1 | #include "../framework/window_framework_sender.h" 2 | #include "../framework/window_framework_receiver.h" 3 | 4 | 5 | protoop_arg_t receive_source_symbol(picoquic_cnx_t *cnx) 6 | { 7 | bpf_state *state = get_bpf_state(cnx); 8 | if (!state) 9 | return PICOQUIC_ERROR_MEMORY; 10 | return (protoop_arg_t) window_receive_source_symbol(cnx, state, state->framework_receiver, (source_symbol_t *) get_cnx(cnx, AK_CNX_INPUT, 0), (bool) get_cnx(cnx, AK_CNX_INPUT, 1)); 11 | } -------------------------------------------------------------------------------- /plugins/qlog/frames/padding_or_ping_parsed.c: -------------------------------------------------------------------------------- 1 | #include "../bpf.h" 2 | 3 | protoop_arg_t protoop_log(picoquic_cnx_t *cnx) { 4 | TMP_FRAME_BEGIN(cnx, parsed_frame, frame, padding_or_ping_frame_t) 5 | char *frame_str = my_malloc(cnx, 100); 6 | if (!frame_str) return 0; 7 | PROTOOP_SNPRINTF(cnx, frame_str, 100, "{\"frame_type\": \"%s\"}", (protoop_arg_t)(frame.is_ping ? "ping" : "padding")); 8 | helper_log_frame(cnx, frame_str); 9 | my_free(cnx, frame_str); 10 | TMP_FRAME_END 11 | return 0; 12 | } -------------------------------------------------------------------------------- /plugins/multipath/Makefile: -------------------------------------------------------------------------------- 1 | SRC=$(shell find -name "*.c") 2 | OBJ=$(SRC:.c=.o) 3 | CFLAGS=-I../../picoquic -DPACING -DDISABLE_PROTOOP_PRINTF -DDISABLE_QLOG 4 | SUBDIRS=path_schedulers 5 | CLANG?=clang-6.0 6 | LLC?=llc-6.0 7 | export CLANG LLC 8 | 9 | all: $(SRC) $(OBJ) $(SUBDIRS) 10 | 11 | $(SUBDIRS): 12 | $(MAKE) -C $@ 13 | 14 | $(OBJ): %.o 15 | 16 | %.o: %.c 17 | $(CLANG) $(CFLAGS) -O2 -fno-gnu-inline-asm -emit-llvm -c $< -o - | $(LLC) -march=bpf -filetype=obj -o $@ 18 | 19 | clean: 20 | rm -rf *.o 21 | 22 | .PHONY: %.o $(SUBDIRS) 23 | -------------------------------------------------------------------------------- /picoquicfirst/getopt.h: -------------------------------------------------------------------------------- 1 | #ifndef GETOPT_H 2 | #ifndef __APPLE__ 3 | 4 | #define GETOPT_H 5 | 6 | #ifndef _GETOPT_H 7 | #define _GETOPT_H 8 | #endif 9 | 10 | extern int opterr; /* if error message should be printed */ 11 | extern int optind; /* index into parent argv vector */ 12 | extern int optopt; /* character checked for validity */ 13 | extern int optreset; /* reset getopt */ 14 | extern const char* optarg; /* argument associated with option */ 15 | 16 | int getopt(int nargc, char* const nargv[], const char* ostr); 17 | 18 | #endif 19 | #endif 20 | -------------------------------------------------------------------------------- /plugins/fec/constant_redundancy_controller_protoops/get_constant_redundancy_parameters.c: -------------------------------------------------------------------------------- 1 | #include "picoquic.h" 2 | #include "getset.h" 3 | #include "constant_redundancy_controller.h" 4 | 5 | // sets as output: 6 | // Input 0: the redundancy controller state 7 | // Output 0: the size of a block 8 | // Output 1: the number of source symbols in a block 9 | protoop_arg_t get_constant_redundancy_parameters(picoquic_cnx_t *cnx) 10 | { 11 | set_cnx(cnx, AK_CNX_OUTPUT, 0, DEFAULT_N); 12 | set_cnx(cnx, AK_CNX_OUTPUT, 1, DEFAULT_K); 13 | return 0; 14 | } -------------------------------------------------------------------------------- /plugins/monitoring/tail_loss_probe.c: -------------------------------------------------------------------------------- 1 | #include "../helpers.h" 2 | #include "bpf.h" 3 | 4 | 5 | /** 6 | * See PROTOOP_NOPARAM_TAIL_LOSS_PROBE 7 | */ 8 | protoop_arg_t tail_loss_probe(picoquic_cnx_t *cnx) 9 | { 10 | picoquic_packet_t *p = (picoquic_packet_t *) get_cnx(cnx, AK_CNX_INPUT, 0); 11 | picoquic_path_t *path = (picoquic_path_t *) get_pkt(p, AK_PKT_SEND_PATH); 12 | monitoring_path_metrics *path_metrics = find_metrics_for_path(cnx, get_monitoring_metrics(cnx), path); 13 | path_metrics->metrics.tlp_fired++; 14 | return 0; 15 | } -------------------------------------------------------------------------------- /plugins/multipath/notify_add_address_frame.c: -------------------------------------------------------------------------------- 1 | #include "bpf.h" 2 | 3 | 4 | protoop_arg_t notify_add_address_frame(picoquic_cnx_t *cnx) 5 | { 6 | reserve_frame_slot_t *rfs = (reserve_frame_slot_t *) get_cnx(cnx, AK_CNX_INPUT, 0); 7 | int received = (int) get_cnx(cnx, AK_CNX_INPUT, 1); 8 | 9 | if (!received) { 10 | ((add_address_ctx_t *)rfs->frame_ctx)->is_rtx = true; 11 | reserve_frames(cnx, 1, rfs); 12 | } else { 13 | my_free(cnx, rfs->frame_ctx); 14 | my_free(cnx, rfs); 15 | } 16 | return 0; 17 | } -------------------------------------------------------------------------------- /plugins/fec/fec_rlc_gf256_window.plugin: -------------------------------------------------------------------------------- 1 | be.michelfra.fecrlc 2 | stream_always_encode_length replace protoops/stream_always_encode_length.o 3 | should_send_repair_symbols replace protoops/always_send_repair_symbols.o 4 | should_send_recovered_frames replace protoops/always_send_recovered_frames.o 5 | window_select_symbols_to_protect replace framework_protoops/window_protect_all_unprotected_source_symbols.o 6 | fec_core.plugin include 7 | fec_framework_window.plugin include 8 | fec_scheme_rlc_gf256.plugin include 9 | fec_constant_redundancy_controller_burst.plugin include -------------------------------------------------------------------------------- /plugins/fec/fec_rlc_gf256_window_no_rf.plugin: -------------------------------------------------------------------------------- 1 | be.michelfra.fecrlc 2 | stream_always_encode_length replace protoops/stream_always_encode_length.o 3 | should_send_repair_symbols replace protoops/always_send_repair_symbols.o 4 | should_send_recovered_frames replace protoops/never_send_recovered_frames.o 5 | window_select_symbols_to_protect replace framework_protoops/window_protect_all_unprotected_source_symbols.o 6 | fec_core.plugin include 7 | fec_framework_window.plugin include 8 | fec_scheme_rlc_gf256.plugin include 9 | fec_constant_redundancy_controller_burst.plugin include -------------------------------------------------------------------------------- /plugins/fec/fec_rlc_gf256_window_uniform.plugin: -------------------------------------------------------------------------------- 1 | be.michelfra.fecrlc 2 | stream_always_encode_length replace protoops/stream_always_encode_length.o 3 | should_send_repair_symbols replace protoops/always_send_repair_symbols.o 4 | should_send_recovered_frames replace protoops/always_send_recovered_frames.o 5 | window_select_symbols_to_protect replace framework_protoops/window_protect_all_unprotected_source_symbols.o 6 | fec_core.plugin include 7 | fec_framework_window.plugin include 8 | fec_scheme_rlc_gf256.plugin include 9 | fec_constant_redundancy_controller_burst.plugin include -------------------------------------------------------------------------------- /plugins/qlog/frames/crypto_frame_parsed.c: -------------------------------------------------------------------------------- 1 | #include "../bpf.h" 2 | 3 | protoop_arg_t protoop_log(picoquic_cnx_t *cnx) { 4 | TMP_FRAME_BEGIN(cnx, parsed_frame, frame, crypto_frame_t) 5 | char *frame_str = my_malloc(cnx, 200); 6 | if (!frame_str) return 0; 7 | PROTOOP_SNPRINTF(cnx, frame_str, 200, "{\"frame_type\": \"crypto\", \"offset\": \"%" PRIu64 "\", \"length\": \"%" PRIu64 "\"}", frame.offset, frame.length); 8 | helper_log_frame(cnx, frame_str); 9 | my_free(cnx, frame_str); 10 | TMP_FRAME_END 11 | return 0; 12 | } -------------------------------------------------------------------------------- /plugins/qlog/receiver/header_parsed.c: -------------------------------------------------------------------------------- 1 | #include "../bpf.h" 2 | 3 | /** 4 | * See "header_parsed" 5 | * cnx->protoop_inputv[0] = picoquic_packet_header *ph 6 | * cnx->protoop_inputv[1] = picoquic_path_t *path 7 | * cnx->protoop_inputv[2] = size_t length 8 | * 9 | * Output: None 10 | */ 11 | protoop_arg_t header_parsed(picoquic_cnx_t *cnx) 12 | { 13 | qlog_t *qlog = get_qlog_t(cnx); 14 | picoquic_packet_header *ph = (picoquic_packet_header *) get_cnx(cnx, AK_CNX_INPUT, 0); 15 | my_memcpy(&qlog->pkt_hdr, ph, sizeof(qlog->pkt_hdr)); 16 | return 0; 17 | } -------------------------------------------------------------------------------- /plugins/fec/fec_protect_end_of_stream.plugin: -------------------------------------------------------------------------------- 1 | be.michelfra.fecxor 2 | stream_always_encode_length replace protoops/stream_always_encode_length.o 3 | should_send_repair_symbols replace protoops/send_repair_symbols_when_no_stream_data_to_send.o 4 | should_send_recovered_frames replace protoops/always_send_recovered_frames.o 5 | window_select_symbols_to_protect replace framework_protoops/window_protect_all_unprotected_source_symbols.o 6 | fec_core.plugin include 7 | fec_framework_window.plugin include 8 | fec_scheme_xor.plugin include 9 | fec_constant_redundancy_controller.plugin include -------------------------------------------------------------------------------- /plugins/monitoring/retransmission_timeout.c: -------------------------------------------------------------------------------- 1 | #include "../helpers.h" 2 | #include "bpf.h" 3 | 4 | 5 | /** 6 | * See PROTOOP_NOPARAM_RETRANSMISSION_TIMEOUT 7 | */ 8 | protoop_arg_t retransmission_timeout(picoquic_cnx_t *cnx) 9 | { 10 | picoquic_packet_t *p = (picoquic_packet_t *) get_cnx(cnx, AK_CNX_INPUT, 0); 11 | picoquic_path_t *path = (picoquic_path_t *) get_pkt(p, AK_PKT_SEND_PATH); 12 | monitoring_path_metrics *path_metrics = find_metrics_for_path(cnx, get_monitoring_metrics(cnx), path); 13 | path_metrics->metrics.rto_fired++; 14 | return 0; 15 | } -------------------------------------------------------------------------------- /plugins/fec/framework_protoops/window_pre_notify_sfpid_frame.c: -------------------------------------------------------------------------------- 1 | #include "../framework/window_framework_sender.h" 2 | #include "../framework/window_framework_receiver.h" 3 | 4 | 5 | protoop_arg_t framework_notify_sfpid_frame(picoquic_cnx_t *cnx) 6 | { 7 | reserve_frame_slot_t *rfs = (reserve_frame_slot_t *) get_cnx(cnx, AK_CNX_INPUT, 0); 8 | bpf_state *state = get_bpf_state(cnx); 9 | if (!state) 10 | return PICOQUIC_ERROR_MEMORY; 11 | sfpid_has_landed(state->framework_sender, ((source_fpid_frame_t *)rfs->frame_ctx)->source_fpid); 12 | return 0; 13 | } -------------------------------------------------------------------------------- /plugins/qlog/sender/header_prepared.c: -------------------------------------------------------------------------------- 1 | #include "../bpf.h" 2 | 3 | /** 4 | * See "header_parsed" 5 | * cnx->protoop_inputv[0] = picoquic_packet_header *ph 6 | * cnx->protoop_inputv[1] = picoquic_path_t *path 7 | * cnx->protoop_inputv[2] = size_t length 8 | * 9 | * Output: None 10 | */ 11 | protoop_arg_t header_prepared(picoquic_cnx_t *cnx) 12 | { 13 | qlog_t *qlog = get_qlog_t(cnx); 14 | picoquic_packet_header *ph = (picoquic_packet_header *) get_cnx(cnx, AK_CNX_INPUT, 0); 15 | my_memcpy(&qlog->pkt_hdr, ph, sizeof(picoquic_packet_header)); 16 | return 0; 17 | } -------------------------------------------------------------------------------- /plugins/fec/constant_redundancy_controller_protoops/get_constant_redundancy_parameters_burst_handling.c: -------------------------------------------------------------------------------- 1 | #include "picoquic.h" 2 | #include "getset.h" 3 | #include "constant_redundancy_controller_burst_handling.h" 4 | 5 | // sets as output: 6 | // Input 0: the redundancy controller state 7 | // Output 0: the size of a block 8 | // Output 1: the number of source symbols in a block 9 | protoop_arg_t get_constant_redundancy_parameters(picoquic_cnx_t *cnx) 10 | { 11 | set_cnx(cnx, AK_CNX_OUTPUT, 0, DEFAULT_N); 12 | set_cnx(cnx, AK_CNX_OUTPUT, 1, DEFAULT_K); 13 | return 0; 14 | } -------------------------------------------------------------------------------- /plugins/datagram/get_datagram_socket.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "../helpers.h" 5 | #include "bpf.h" 6 | 7 | protoop_arg_t get_datagram_socket(picoquic_cnx_t* cnx) 8 | { 9 | datagram_memory_t *m = get_datagram_memory(cnx); 10 | if (m->socket_fds[PLUGIN_SOCKET] == -1 && m->socket_fds[APP_SOCKET] == -1) { 11 | if (socketpair(AF_UNIX, SOCK_DGRAM, 0, m->socket_fds) == -1) { 12 | PROTOOP_PRINTF(cnx, "Failed to allocate Unix socket pair!\n"); 13 | } 14 | } 15 | return (protoop_arg_t) m->socket_fds[APP_SOCKET]; 16 | } -------------------------------------------------------------------------------- /ci/build_picotls.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | #build last picotls master (for Travis) 3 | 4 | # Build at a known-good commit 5 | # Must select a commit date (can copy-paste from git log) 6 | COMMIT_ID=a760bd5812441d3ef44fd34ae3c5aaab2016712d 7 | COMMIT_DATE="Wed Aug 22 11:16:13 2018 +0900" 8 | 9 | cd .. 10 | git clone --branch master --single-branch --shallow-submodules --recurse-submodules --no-tags --shallow-since="$COMMIT_DATE" https://github.com/h2o/picotls 11 | cd picotls 12 | git checkout "$COMMIT_ID" 13 | #git submodule init 14 | #git submodule update 15 | cmake . 16 | make -j$(nproc) all 17 | cd .. 18 | -------------------------------------------------------------------------------- /plugins/qlog/frames/stop_sending_parsed.c: -------------------------------------------------------------------------------- 1 | #include "../bpf.h" 2 | 3 | protoop_arg_t protoop_log(picoquic_cnx_t *cnx) { 4 | TMP_FRAME_BEGIN(cnx, parsed_frame, frame, stop_sending_frame_t) 5 | char *frame_str = my_malloc(cnx, 200); 6 | if (!frame_str) return 0; 7 | PROTOOP_SNPRINTF(cnx, frame_str, 200, "{\"frame_type\": \"stop_sending\", \"stream_id\": \"%" PRIu64 "\", \"error_code\": \"%" PRIu64 "\"}", frame.stream_id, frame.application_error_code); 8 | helper_log_frame(cnx, frame_str); 9 | my_free(cnx, frame_str); 10 | TMP_FRAME_END 11 | return 0; 12 | } -------------------------------------------------------------------------------- /plugins/qlog/frames/stream_blocked_frame_parsed.c: -------------------------------------------------------------------------------- 1 | #include "../bpf.h" 2 | 3 | protoop_arg_t protoop_log(picoquic_cnx_t *cnx) { 4 | TMP_FRAME_BEGIN(cnx, parsed_frame, frame, stream_blocked_frame_t) 5 | char *frame_str = my_malloc(cnx, 200); 6 | if (!frame_str) return 0; 7 | PROTOOP_SNPRINTF(cnx, frame_str, 200, "{\"frame_type\": \"stream_data_blocked\", \"stream_limit\": \"%" PRIu64 "\", \"limit\": \"%" PRIu64 "\"}", frame.stream_id, frame.offset); 8 | helper_log_frame(cnx, frame_str); 9 | my_free(cnx, frame_str); 10 | TMP_FRAME_END 11 | return 0; 12 | } -------------------------------------------------------------------------------- /plugins/fec/framework_protoops/window_receive_repair_symbol.c: -------------------------------------------------------------------------------- 1 | #include "../framework/window_framework_sender.h" 2 | #include "../framework/window_framework_receiver.h" 3 | 4 | 5 | protoop_arg_t receive_repair_symbol(picoquic_cnx_t *cnx) 6 | { 7 | bpf_state *state = get_bpf_state(cnx); 8 | if (!state) 9 | return PICOQUIC_ERROR_MEMORY; 10 | uint8_t nss = (uint8_t) get_cnx(cnx, AK_CNX_INPUT, 2); 11 | uint8_t nrs = (uint8_t) get_cnx(cnx, AK_CNX_INPUT, 3); 12 | return (protoop_arg_t) window_receive_repair_symbol(cnx, (repair_symbol_t *) get_cnx(cnx, AK_CNX_INPUT, 1), nss, nrs); 13 | } -------------------------------------------------------------------------------- /plugins/fec/protoops/process_simple_recovered_frame.c: -------------------------------------------------------------------------------- 1 | #include "picoquic.h" 2 | #include "../fec_protoops.h" 3 | 4 | 5 | protoop_arg_t process_recovered_frame(picoquic_cnx_t *cnx) 6 | { 7 | bpf_state *state = get_bpf_state(cnx); 8 | if (!state) return PICOQUIC_ERROR_MEMORY; 9 | uint8_t *size_and_packets = (uint8_t *) get_cnx(cnx, AK_CNX_INPUT, 0); 10 | recovered_packets_t rp; 11 | rp.number_of_packets = *size_and_packets; 12 | rp.packets = (uint64_t *) (size_and_packets+1); 13 | 14 | enqueue_recovered_packets(&state->recovered_packets, &rp); 15 | return (protoop_arg_t) 0; 16 | } -------------------------------------------------------------------------------- /plugins/qlog/frames/max_stream_data_parsed.c: -------------------------------------------------------------------------------- 1 | #include "../bpf.h" 2 | 3 | protoop_arg_t protoop_log(picoquic_cnx_t *cnx) { 4 | TMP_FRAME_BEGIN(cnx, parsed_frame, frame, max_stream_data_frame_t) 5 | char *frame_str = my_malloc(cnx, 200); 6 | if (!frame_str) return 0; 7 | PROTOOP_SNPRINTF(cnx, frame_str, 200, "{\"frame_type\": \"max_stream_data\", \"stream_id\": \"%" PRIu64 "\", \"maximum\": \"%" PRIu64 "\"}", frame.stream_id, frame.maximum_stream_data); 8 | helper_log_frame(cnx, frame_str); 9 | my_free(cnx, frame_str); 10 | TMP_FRAME_END 11 | return 0; 12 | } -------------------------------------------------------------------------------- /plugins/qlog/sender/ready_stream.c: -------------------------------------------------------------------------------- 1 | #include "../bpf.h" 2 | 3 | protoop_arg_t protoop_log(picoquic_cnx_t *cnx) { 4 | picoquic_stream_head *stream = (picoquic_stream_head *) get_cnx(cnx, AK_CNX_RETURN_VALUE, 0); 5 | if (!stream) 6 | LOG_EVENT(cnx, "STREAMS", "READY_STREAM", "", "{\"stream\": null}"); 7 | else 8 | LOG_EVENT(cnx, "STREAMS", "READY_STREAM", "", "{\"stream\": \"%p\", \"stream_id\": %" PRIu64 ", \"sent_offset\": %" PRIu64 "}", (protoop_arg_t) stream, get_stream_head(stream, AK_STREAMHEAD_STREAM_ID), get_stream_head(stream, AK_STREAMHEAD_SENT_OFFSET)); 9 | return 0; 10 | } -------------------------------------------------------------------------------- /plugins/qlog/set_output_file.c: -------------------------------------------------------------------------------- 1 | #include "bpf.h" 2 | 3 | /** 4 | * Input: None 5 | * 6 | * Output: None 7 | */ 8 | protoop_arg_t set_output_file(picoquic_cnx_t *cnx) 9 | { 10 | qlog_t *qlog = get_qlog_t(cnx); 11 | if (qlog->fd == -1) { 12 | qlog->fd = (int) get_cnx(cnx, AK_CNX_INPUT, 0); 13 | qlog->hdr.reference_time = qlog->head ? qlog->head->reference_time : picoquic_current_time(); 14 | qlog->hdr.vantage_point = get_cnx(cnx, AK_CNX_CLIENT_MODE, 0) ? QLOG_VANTAGE_POINT_CLIENT : QLOG_VANTAGE_POINT_SERVER; 15 | write_header(cnx, qlog); 16 | } 17 | return 0; 18 | } -------------------------------------------------------------------------------- /plugins/fec/fec_rlc_gf256_window_protect_end_of_stream_only_inflight.plugin: -------------------------------------------------------------------------------- 1 | be.michelfra.fecrlcgf256 2 | stream_always_encode_length replace protoops/stream_always_encode_length.o 3 | should_send_repair_symbols replace protoops/send_repair_symbols_when_no_stream_data_to_send.o 4 | should_send_recovered_frames replace protoops/always_send_recovered_frames.o 5 | window_select_symbols_to_protect replace framework_protoops/window_protect_all_inflight_source_symbols.o 6 | fec_core.plugin include 7 | fec_framework_window.plugin include 8 | fec_scheme_rlc_gf256.plugin include 9 | fec_constant_redundancy_controller_burst.plugin include -------------------------------------------------------------------------------- /plugins/monitoring/fast_retransmit.c: -------------------------------------------------------------------------------- 1 | #include "../helpers.h" 2 | #include "bpf.h" 3 | 4 | 5 | /** 6 | * See PROTOOP_NOPARAM_FAST_RETRANSMIT 7 | */ 8 | protoop_arg_t fast_retransmit(picoquic_cnx_t *cnx) 9 | { 10 | picoquic_packet_t *p = (picoquic_packet_t *) get_cnx(cnx, AK_CNX_INPUT, 0); 11 | PROTOOP_PRINTF(cnx, "FRT fired %p\n", (protoop_arg_t) p); 12 | picoquic_path_t *path = (picoquic_path_t *) get_pkt(p, AK_PKT_SEND_PATH); 13 | monitoring_path_metrics *path_metrics = find_metrics_for_path(cnx, get_monitoring_metrics(cnx), path); 14 | path_metrics->metrics.frt_fired++; 15 | return 0; 16 | } -------------------------------------------------------------------------------- /plugins/multipath/process_max_sending_uniflow_id.c: -------------------------------------------------------------------------------- 1 | #include "bpf.h" 2 | 3 | /** 4 | * See PROTOOP_PARAM_PROCESS_TRANSPORT_PARAMETER 5 | */ 6 | protoop_arg_t process_max_sending_uniflow_id(picoquic_cnx_t* cnx) 7 | { 8 | uint8_t* bytes = (uint8_t *) get_cnx(cnx, AK_CNX_INPUT, 0); 9 | size_t length = (size_t) get_cnx(cnx, AK_CNX_INPUT, 1); 10 | 11 | bpf_data *bpfd = get_bpf_data(cnx); 12 | bpfd->tp_received = 1; 13 | 14 | bytes = picoquic_frames_varint_decode(bytes, bytes + length, &bpfd->received_max_sending_uniflow); 15 | int inject_plugin = 1; 16 | 17 | return (protoop_arg_t) inject_plugin; 18 | } -------------------------------------------------------------------------------- /plugins/multipath/multipath_qlog.plugin: -------------------------------------------------------------------------------- 1 | be.qdeconinck.multipath.qlog 2 | parse_frame param 0x40 post qlog/mp_new_connection_id_frame_parsed.o 3 | write_frame param 0x40 post qlog/frame_prepared.o 4 | parse_frame param 0x42 post qlog/mp_ack_frame_parsed.o 5 | write_frame param 0x42 post qlog/frame_prepared.o 6 | parse_frame param 0x43 post qlog/mp_ack_frame_parsed.o 7 | write_frame param 0x43 post qlog/frame_prepared.o 8 | parse_frame param 0x44 post qlog/add_address_parsed.o 9 | write_frame param 0x44 post qlog/frame_prepared.o 10 | parse_frame param 0x46 post qlog/uniflows_parsed.o 11 | write_frame param 0x46 post qlog/frame_prepared.o -------------------------------------------------------------------------------- /plugins/qlog/sender/next_stream_scheduled.c: -------------------------------------------------------------------------------- 1 | #include "../bpf.h" 2 | 3 | protoop_arg_t protoop_log(picoquic_cnx_t *cnx) { 4 | picoquic_stream_head *stream = (picoquic_stream_head *) get_cnx(cnx, AK_CNX_RETURN_VALUE, 0); 5 | if (!stream) 6 | LOG_EVENT(cnx, "STREAMS", "NEXT_STREAM_SCHEDULED", "", "{\"stream\": null}"); 7 | else 8 | LOG_EVENT(cnx, "STREAMS", "NEXT_STREAM_SCHEDULED", "", "{\"stream\": \"%p\", \"stream_id\": %" PRIu64 ", \"sent_offset\": %" PRIu64 "}", (protoop_arg_t) stream, get_stream_head(stream, AK_STREAMHEAD_STREAM_ID), get_stream_head(stream, AK_STREAMHEAD_SENT_OFFSET)); 9 | return 0; 10 | } -------------------------------------------------------------------------------- /picoquic_t/http09_index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | PicoQuic HTTP 0.9 service 5 | 6 |

Simple HTTP 0.9 Responder

7 |

GET /, and GET index.html returns this text

8 |

Get doc-NNNNN.html returns html document of length NNNNN bytes(decimal)

9 |

Get doc-NNNNN also returns html document of length NNNNN bytes(decimal)

10 |

Get doc-NNNNN.txt returns txt document of length NNNNN bytes(decimal)

11 |

Any other command will result in an error, and an empty response.

12 |

Enjoy!

13 | 14 | -------------------------------------------------------------------------------- /picoquic_t/http09_index2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | PicoQuic HTTP 0.9 service 5 | 6 |

Simple HTTP 0.9 Responder

7 |

GET /, and GET index.html returns this text

8 |

Get doc-NNNNN.html returns html document of length NNNNN bytes(decimal)

9 |

Get doc-NNNNN also returns html document of length NNNNN bytes(decimal)

10 |

Get doc-NNNNN.txt returns txt document of length NNNNN bytes(decimal)

11 |

Any other command will result in an error, and an empty response.

12 |

Enjoy!

13 | 14 | -------------------------------------------------------------------------------- /picoquic_t/http09_index3.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | PicoQuic HTTP 0.9 service 5 | 6 |

Simple HTTP 0.9 Responder

7 |

GET /, and GET index.html returns this text

8 |

Get doc-NNNNN.html returns html document of length NNNNN bytes(decimal)

9 |

Get doc-NNNNN also returns html document of length NNNNN bytes(decimal)

10 |

Get doc-NNNNN.txt returns txt document of length NNNNN bytes(decimal)

11 |

Any other command will result in an error, and an empty response.

12 |

Enjoy!

13 | 14 | -------------------------------------------------------------------------------- /picoquic/endianness.c: -------------------------------------------------------------------------------- 1 | #include "endianness.h" 2 | #include 3 | 4 | int is_little_endian() { 5 | int i = 1; 6 | return (int)*((unsigned char *)&i) == 1 ? 1 : 0; 7 | } 8 | 9 | uint16_t my_htons(uint16_t x) { 10 | if (is_little_endian()) { 11 | unsigned char *s = (unsigned char *)&x; 12 | return (uint16_t)(s[0] << 8 | s[1]); 13 | } else { 14 | return x; 15 | } 16 | } 17 | 18 | uint16_t my_ntohs(uint16_t x) { 19 | if (is_little_endian()) { 20 | unsigned char *s = (unsigned char *)&x; 21 | return (uint16_t)(s[0] << 8 | s[1]); 22 | } else { 23 | return x; 24 | } 25 | } -------------------------------------------------------------------------------- /plugins/qlog/frames/reset_stream_frame_parsed.c: -------------------------------------------------------------------------------- 1 | #include "../bpf.h" 2 | 3 | protoop_arg_t protoop_log(picoquic_cnx_t *cnx) { 4 | TMP_FRAME_BEGIN(cnx, parsed_frame, frame, reset_stream_frame_t) 5 | char *frame_str = my_malloc(cnx, 200); 6 | if (!frame_str) return 0; 7 | PROTOOP_SNPRINTF(cnx, frame_str, 200, "{\"frame_type\": \"reset_stream\", \"stream_id\": \"%" PRIu64 "\", \"error_code\": \"%" PRIu64 "\", \"final_size\": \"%" PRIu64 "\"}", frame.stream_id, frame.app_error_code, frame.final_offset); 8 | helper_log_frame(cnx, frame_str); 9 | my_free(cnx, frame_str); 10 | TMP_FRAME_END 11 | return 0; 12 | } -------------------------------------------------------------------------------- /plugins/qlog/frames/stream_id_blocked_frame_parsed.c: -------------------------------------------------------------------------------- 1 | #include "../bpf.h" 2 | 3 | protoop_arg_t protoop_log(picoquic_cnx_t *cnx) { 4 | TMP_FRAME_BEGIN(cnx, parsed_frame, frame, streams_blocked_frame_t) 5 | char *frame_str = my_malloc(cnx, 200); 6 | if (!frame_str) return 0; 7 | PROTOOP_SNPRINTF(cnx, frame_str, 200, "{\"frame_type\": \"streams_blocked\", \"stream_type\": \"%s\", \"limit\": \"%" PRIu64 "\"}", (protoop_arg_t) (frame.uni == 0 ? "bidirectional" : "unidirectional"), frame.stream_limit); 8 | helper_log_frame(cnx, frame_str); 9 | my_free(cnx, frame_str); 10 | TMP_FRAME_END 11 | return 0; 12 | } -------------------------------------------------------------------------------- /plugins/fec/fec_framework_window.plugin: -------------------------------------------------------------------------------- 1 | create_fec_framework replace framework_protoops/window_create_framework.o 2 | flush_repair_symbols replace framework_protoops/window_flush_repair_symbols.o 3 | get_source_fpid replace framework_protoops/window_get_source_fpid.o 4 | fec_protect_source_symbol replace framework_protoops/window_protect_source_symbol.o 5 | receive_source_symbol replace framework_protoops/window_receive_source_symbol.o 6 | receive_repair_symbol replace framework_protoops/window_receive_repair_symbol.o 7 | notify_frame param 0x29 pre framework_protoops/window_pre_notify_sfpid_frame.o 8 | write_frame param 0x29 post framework_protoops/window_post_write_sfpid_frame.o -------------------------------------------------------------------------------- /plugins/qlog/frames/stream_frame_parsed.c: -------------------------------------------------------------------------------- 1 | #include "../bpf.h" 2 | 3 | protoop_arg_t protoop_log(picoquic_cnx_t *cnx) { 4 | TMP_FRAME_BEGIN(cnx, parsed_frame, frame, stream_frame_t) 5 | char *frame_str = my_malloc(cnx, 200); 6 | if (!frame_str) return 0; 7 | PROTOOP_SNPRINTF(cnx, frame_str, 200, "{\"frame_type\": \"stream_frame\", \"stream_id\": \"%" PRIu64 "\", \"offset\": \"%" PRIu64 "\", \"length\": %d%s}", frame.stream_id, frame.offset, frame.data_length, (protoop_arg_t) (frame.fin ? ", \"fin\": true": "")); 8 | helper_log_frame(cnx, frame_str); 9 | my_free(cnx, frame_str); 10 | TMP_FRAME_END 11 | return 0; 12 | } -------------------------------------------------------------------------------- /plugins/qlog/receiver/segment_received.c: -------------------------------------------------------------------------------- 1 | #include "../bpf.h" 2 | 3 | protoop_arg_t segment_received(picoquic_cnx_t *cnx) 4 | { 5 | qlog_t *qlog = get_qlog_t(cnx); 6 | char *hdr_str = sprint_header(cnx, qlog); 7 | char *frame_str = sprint_frames(cnx, qlog); 8 | 9 | LOG_EVENT(cnx, "transport", "packet_received", "", "{\"packet_type\": \"%s\", \"header\": %s, \"frames\": %s}", (protoop_arg_t) ptype(qlog->pkt_hdr.ptype), (protoop_arg_t) hdr_str, (protoop_arg_t) (frame_str ? frame_str : "[]")); 10 | 11 | if (frame_str) { 12 | my_free(cnx, frame_str); 13 | } 14 | if (hdr_str) { 15 | my_free(cnx, hdr_str); 16 | } 17 | return 0; 18 | } -------------------------------------------------------------------------------- /plugins/fec/framework_protoops/window_post_write_sfpid_frame.c: -------------------------------------------------------------------------------- 1 | #include "../framework/window_framework_sender.h" 2 | #include "../framework/window_framework_receiver.h" 3 | 4 | 5 | protoop_arg_t window_write_sfpid_frame(picoquic_cnx_t *cnx) 6 | { 7 | uint64_t consumed = (uint64_t) get_cnx(cnx, AK_CNX_OUTPUT, 0); 8 | int retval = (int) get_cnx(cnx, AK_CNX_RETURN_VALUE, 0); 9 | 10 | bpf_state *state = get_bpf_state(cnx); 11 | if (!state) 12 | return PICOQUIC_ERROR_MEMORY; 13 | if (retval == 0 && consumed > 0) 14 | sfpid_takes_off(state->framework_sender, ((source_fpid_frame_t *)get_cnx(cnx, AK_CNX_INPUT, 2))->source_fpid); 15 | return 0; 16 | } -------------------------------------------------------------------------------- /plugins/qlog/frames/path_challenge_created.c: -------------------------------------------------------------------------------- 1 | #include "../bpf.h" 2 | 3 | protoop_arg_t protoop_log(picoquic_cnx_t *cnx) { 4 | TMP_FRAME_BEGIN(cnx, parsed_frame, frame, path_challenge_frame_t) 5 | char challenge[17]; 6 | challenge[16] = 0; 7 | snprintf_bytes(challenge, sizeof(challenge), frame.data, 8); 8 | char *frame_str = my_malloc(cnx, 100); 9 | if (!frame_str) return 0; 10 | PROTOOP_SNPRINTF(cnx, frame_str, 100, "{\"frame_type\": \"path_challenge\", \"data\": \"%s\"}", (protoop_arg_t) challenge); 11 | helper_log_frame(cnx, frame_str); 12 | my_free(cnx, frame_str); 13 | TMP_FRAME_END 14 | return 0; 15 | } -------------------------------------------------------------------------------- /plugins/fec/protoops/incoming_encrypted_post.c: -------------------------------------------------------------------------------- 1 | #include "../fec_protoops.h" 2 | 3 | /** 4 | * uint8_t* bytes = (uint8_t *) cnx->protoop_inputv[0]; 5 | * picoquic_packet_header* ph = (picoquic_packet_header *) cnx->protoop_inputv[1]; 6 | * struct sockaddr* addr_from = (struct sockaddr *) cnx->protoop_inputv[2]; 7 | * uint64_t current_time = (uint64_t) cnx->protoop_inputv[3]; 8 | * 9 | * Output: return code (int) 10 | */ 11 | protoop_arg_t incoming_encrypted(picoquic_cnx_t *cnx) 12 | { 13 | bpf_state *state = get_bpf_state(cnx); 14 | state->current_symbol_length = 0; 15 | my_free(cnx, state->current_symbol); 16 | state->current_symbol = NULL; 17 | return 0; 18 | } -------------------------------------------------------------------------------- /plugins/qlog/frames/path_response_parsed.c: -------------------------------------------------------------------------------- 1 | #include "../bpf.h" 2 | 3 | protoop_arg_t protoop_log(picoquic_cnx_t *cnx) { 4 | TMP_FRAME_BEGIN(cnx, parsed_frame, frame, path_response_frame_t) 5 | char challenge[17]; 6 | challenge[16] = 0; 7 | snprintf_bytes(challenge, sizeof(challenge), (uint8_t *)&frame.data, 8); 8 | char *frame_str = my_malloc(cnx, 100); 9 | if (!frame_str) return 0; 10 | PROTOOP_SNPRINTF(cnx, frame_str, 100, "{\"frame_type\": \"path_response\", \"data\": \"%s\"}", (protoop_arg_t) challenge); 11 | helper_log_frame(cnx, frame_str); 12 | my_free(cnx, frame_str); 13 | TMP_FRAME_END 14 | return 0; 15 | } -------------------------------------------------------------------------------- /plugins/multipath/addresses_filters/only_42_0_1_1.c: -------------------------------------------------------------------------------- 1 | #include "../bpf.h" 2 | 3 | protoop_arg_t protoop_accept_addr(picoquic_cnx_t *cnx) { 4 | struct sockaddr_storage *t = (struct sockaddr_storage *) get_cnx(cnx, AK_CNX_INPUT, 0); 5 | uint32_t if_index = get_cnx(cnx, AK_CNX_INPUT, 1); 6 | struct sockaddr_storage sa; 7 | my_memcpy(&sa, t, sizeof(struct sockaddr_storage)); 8 | if (sa.ss_family == AF_INET) { 9 | struct sockaddr_in *sai4 = (struct sockaddr_in *) &sa; 10 | in_addr_t a = sai4->sin_addr.s_addr; 11 | return a == (in_addr_t) 0x0101002a; 12 | } else if (sa.ss_family == AF_INET6) { 13 | return false; 14 | } 15 | return false; 16 | } -------------------------------------------------------------------------------- /plugins/monitoring/monitoring.plugin: -------------------------------------------------------------------------------- 1 | be.mpiraux.monitoring 2 | connection_state_changed replace cnx_state_changed.o 3 | header_parsed replace packet_received.o 4 | header_prepared replace packet_sent.o 5 | update_rtt post rtt_updated.o 6 | decode_stream_frame pre check_ooo_stream_frame.o 7 | decode_stream_frame pre check_spurious_stream_frame.o 8 | packet_was_lost pre packet_lost.o 9 | fast_retransmit post fast_retransmit.o 10 | retransmission_timeout post retransmission_timeout.o 11 | tail_loss_probe post tail_loss_probe.o 12 | stream_opened post stream_opened.o 13 | stream_closed post stream_closed.o 14 | prepare_stream_frame post stream_frame_written.o 15 | unknown_tp_received post unknown_tp_received.o -------------------------------------------------------------------------------- /plugins/multipath/addresses_filters/only_192_168_net.c: -------------------------------------------------------------------------------- 1 | #include "../bpf.h" 2 | 3 | protoop_arg_t protoop_accept_addr(picoquic_cnx_t *cnx) { 4 | struct sockaddr_storage *t = (struct sockaddr_storage *) get_cnx(cnx, AK_CNX_INPUT, 0); 5 | uint32_t if_index = get_cnx(cnx, AK_CNX_INPUT, 1); 6 | struct sockaddr_storage sa; 7 | my_memcpy(&sa, t, sizeof(struct sockaddr_storage)); 8 | if (sa.ss_family == AF_INET) { 9 | struct sockaddr_in *sai4 = (struct sockaddr_in *) &sa; 10 | in_addr_t a = sai4->sin_addr.s_addr; 11 | return (a & 0x0000FFFF) == 0xA8C0; 12 | } else if (sa.ss_family == AF_INET6) { 13 | return false; 14 | } 15 | return false; 16 | } -------------------------------------------------------------------------------- /benchmarks/add_main_to_plugin.py: -------------------------------------------------------------------------------- 1 | import re 2 | import argparse 3 | parser = argparse.ArgumentParser() 4 | parser.add_argument("file") 5 | args = parser.parse_args() 6 | with open(args.file, 'r') as f: 7 | c_code = f.read() 8 | function_name = re.findall(r"protoop_arg_t\s+([^\s]+)\(\s*picoquic_cnx_t\s*\*\s*[^\s]*\)", c_code)[-1] 9 | # f_name function parameter param name 10 | print("""{} 11 | int main() {{ 12 | picoquic_cnx_t *cnx; 13 | // silly loop needed for llvm2kittel to generate at least some bytecode 14 | for (int i = 0 ; i < 1 ; i++) {{ 15 | {}(cnx); 16 | }} 17 | }} 18 | """.format(c_code, function_name)) 19 | -------------------------------------------------------------------------------- /plugins/fec/uniform_redundancy_controller_protoops/create_uniform_redundancy_controller.c: -------------------------------------------------------------------------------- 1 | #include "uniform_redundancy_controller.h" 2 | #include "../fec_protoops.h" 3 | 4 | // sets as output the pointer towards the controller's state 5 | protoop_arg_t create_uniform_redundancy_controller(picoquic_cnx_t *cnx) 6 | { 7 | uniform_redundancy_controller_t *urc = my_malloc(cnx, sizeof(uniform_redundancy_controller_t)); 8 | if (!urc) { 9 | set_cnx(cnx, AK_CNX_OUTPUT, 0, (protoop_arg_t) NULL); 10 | return PICOQUIC_ERROR_MEMORY; 11 | } 12 | my_memset(urc, 0, sizeof(uniform_redundancy_controller_t)); 13 | set_cnx(cnx, AK_CNX_OUTPUT, 0, (protoop_arg_t) urc); 14 | return 0; 15 | } -------------------------------------------------------------------------------- /plugins/multipath/addresses_filters/no_v6_no_10.c: -------------------------------------------------------------------------------- 1 | #include "../bpf.h" 2 | 3 | protoop_arg_t protoop_accept_addr(picoquic_cnx_t *cnx) { 4 | struct sockaddr_storage *t = (struct sockaddr_storage *) get_cnx(cnx, AK_CNX_INPUT, 0); 5 | uint32_t if_index = get_cnx(cnx, AK_CNX_INPUT, 1); 6 | struct sockaddr_storage sa; 7 | my_memcpy(&sa, t, sizeof(struct sockaddr_storage)); 8 | if (sa.ss_family == AF_INET) { 9 | struct sockaddr_in *sai4 = (struct sockaddr_in *) &sa; 10 | in_addr_t a = sai4->sin_addr.s_addr & (in_addr_t) 0xff; 11 | return a != (in_addr_t) 0x0a; 12 | } else if (sa.ss_family == AF_INET6) { 13 | return false; 14 | } 15 | return false; 16 | } -------------------------------------------------------------------------------- /plugins/qlog/sender/retransmit_needed.c: -------------------------------------------------------------------------------- 1 | #include "../bpf.h" 2 | 3 | protoop_arg_t protoop_log(picoquic_cnx_t *cnx) { 4 | if (get_cnx(cnx, AK_CNX_RETURN_VALUE, 0)) { 5 | char *reason = (char *) get_cnx(cnx, AK_CNX_OUTPUT, 2); 6 | picoquic_packet_t *packet = (picoquic_packet_t *) get_cnx(cnx, AK_CNX_INPUT, 3); 7 | uint64_t pn = get_pkt(packet, AK_PKT_SEQUENCE_NUMBER); 8 | char *packet_type = ptype(get_pkt(packet, AK_PKT_TYPE)); 9 | LOG_EVENT(cnx, "recovery", "retransmission", reason, "{\"path\": \"%p\", \"packet_type\": \"%s\", \"packet_number\": \"%" PRIu64 "\"}", get_cnx(cnx, AK_CNX_INPUT, 1), (protoop_arg_t) packet_type, pn); 10 | } 11 | return 0; 12 | } -------------------------------------------------------------------------------- /plugins/fec/uniform_redundancy_controller_protoops/notified_acknowledgement.c: -------------------------------------------------------------------------------- 1 | #include "uniform_redundancy_controller.h" 2 | #include "../fec_protoops.h" 3 | 4 | // sets as output the pointer towards the controller's state 5 | protoop_arg_t congestion_alg_notify(picoquic_cnx_t *cnx) 6 | { 7 | picoquic_congestion_notification_t notification = get_cnx(cnx, AK_CNX_INPUT, 1); 8 | 9 | if (notification == picoquic_congestion_notification_acknowledgement) { 10 | bpf_state *state = get_bpf_state(cnx); 11 | if (!state) return PICOQUIC_ERROR_MEMORY; 12 | uniform_redundancy_controller_t *urc = state->controller; 13 | urc->total_acknowledged_packets++; 14 | } 15 | return 0; 16 | } -------------------------------------------------------------------------------- /plugins/monitoring/packet_lost.c: -------------------------------------------------------------------------------- 1 | #include "../helpers.h" 2 | #include "bpf.h" 3 | 4 | /** 5 | * See PROTOOP_NOPARAM_PACKET_WAS_LOST 6 | */ 7 | protoop_arg_t packet_lost(picoquic_cnx_t *cnx) 8 | { 9 | monitoring_conn_metrics *metrics = get_monitoring_metrics(cnx); 10 | picoquic_packet_t* packet = (picoquic_packet_t *) get_cnx(cnx, AK_CNX_INPUT, 0); 11 | picoquic_path_t *path = (picoquic_path_t *) get_cnx(cnx, AK_CNX_INPUT, 1); 12 | 13 | monitoring_path_metrics *path_metrics = find_metrics_for_path(cnx, metrics, path); 14 | path_metrics->metrics.data_lost = (get_pkt(packet, AK_PKT_LENGTH) + get_pkt(packet, AK_PKT_CHECKSUM_OVERHEAD)); 15 | path_metrics->metrics.pkt_lost++; 16 | return 0; 17 | } -------------------------------------------------------------------------------- /plugins/datagram/cnx_state_changed.c: -------------------------------------------------------------------------------- 1 | #include "../helpers.h" 2 | #include "bpf.h" 3 | 4 | 5 | protoop_arg_t state_changed(picoquic_cnx_t *cnx) 6 | { 7 | picoquic_state_enum cnx_state = (picoquic_state_enum) get_cnx(cnx, AK_CNX_STATE, 0); 8 | if (cnx_state == picoquic_state_disconnected) { 9 | datagram_memory_t *m = get_datagram_memory(cnx); 10 | if (m->socket_fds[PLUGIN_SOCKET] != -1) { 11 | close(m->socket_fds[PLUGIN_SOCKET]); 12 | m->socket_fds[PLUGIN_SOCKET] = -1; 13 | } 14 | if (m->socket_fds[APP_SOCKET] != -1) { 15 | close(m->socket_fds[APP_SOCKET]); 16 | m->socket_fds[APP_SOCKET] = -1; 17 | } 18 | } 19 | return 0; 20 | } -------------------------------------------------------------------------------- /plugins/fec/protoops/stream_bytes_max.c: -------------------------------------------------------------------------------- 1 | #include "../../helpers.h" 2 | #include "../framework/block_framework_sender.h" 3 | 4 | /** 5 | * See PROTOOP_NOPARAM_STREAM_BYTES_MAX 6 | */ 7 | 8 | protoop_arg_t stream_bytes_max(picoquic_cnx_t* cnx) { 9 | size_t bytes_max = get_cnx(cnx, AK_CNX_INPUT, 0); 10 | // FIXME there is one more byte than needed (?) in the overhead, but without it, it doesn't work. Find out why 11 | // size_t overhead = 1 + (1 + sizeof(uint64_t)) + (DEFAULT_K/2 + sizeof(fec_frame_header_t)); 12 | size_t overhead = 1 + (1 + sizeof(uint64_t)) + sizeof(fec_frame_header_t); 13 | set_cnx(cnx, AK_CNX_OUTPUT, 0, (bytes_max && bytes_max > overhead) ? bytes_max-overhead : bytes_max); 14 | return 0; 15 | } -------------------------------------------------------------------------------- /plugins/qlog/sender/retransmit_needed_by_packet.c: -------------------------------------------------------------------------------- 1 | #include "../bpf.h" 2 | 3 | protoop_arg_t protoop_log(picoquic_cnx_t *cnx) { 4 | if (get_cnx(cnx, AK_CNX_RETURN_VALUE, 0)) { 5 | picoquic_packet_t *p = (picoquic_packet_t *) get_cnx(cnx, AK_CNX_INPUT, 0); 6 | char *reason = (char *) get_cnx(cnx, AK_CNX_OUTPUT, 1); 7 | uint64_t retransmit_time = get_cnx(cnx, AK_CNX_OUTPUT, 2); 8 | LOG_EVENT(cnx, "recovery", "packet_lost", reason, "{\"path\": \"%p\", \"packet_type\": \"%s\", \"packet_number\": \"%" PRIu64 "\", \"retransmit_time\": %" PRIu64 "}", get_pkt(p, AK_PKT_SEND_PATH), (protoop_arg_t) ptype(get_pkt(p, AK_PKT_TYPE)), get_pkt(p, AK_PKT_SEQUENCE_NUMBER), retransmit_time); 9 | } 10 | return 0; 11 | } -------------------------------------------------------------------------------- /plugins/fec/framework_protoops/block_receive_repair_symbol.c: -------------------------------------------------------------------------------- 1 | #include "../framework/block_framework_sender.h" 2 | #include "../framework/block_framework_receiver.h" 3 | 4 | 5 | // returns 0 if false 6 | // 1 if true 7 | // an error code != 0, 1 otherwise 8 | protoop_arg_t receive_repair_symbol(picoquic_cnx_t *cnx) 9 | { 10 | bpf_state *state = get_bpf_state(cnx); 11 | if (!state) 12 | return PICOQUIC_ERROR_MEMORY; 13 | uint8_t nss = (uint8_t) get_cnx(cnx, AK_CNX_INPUT, 2); 14 | uint8_t nrs = (uint8_t) get_cnx(cnx, AK_CNX_INPUT, 3); 15 | PROTOOP_PRINTF(cnx, "BLOCK RECEIVE RS\n"); 16 | return (protoop_arg_t) block_receive_repair_symbol(cnx, (repair_symbol_t *) get_cnx(cnx, AK_CNX_INPUT, 1), nss, nrs); 17 | } -------------------------------------------------------------------------------- /plugins/multipath/write_max_sending_uniflow_id.c: -------------------------------------------------------------------------------- 1 | #include "bpf.h" 2 | 3 | /** 4 | * See PROTOOP_PARAM_WRITE_TRANSPORT_PARAMETER 5 | */ 6 | protoop_arg_t write_max_sending_uniflow_id(picoquic_cnx_t* cnx) 7 | { 8 | uint8_t* bytes = (uint8_t *) get_cnx(cnx, AK_CNX_INPUT, 0); 9 | const uint16_t max_length = (const uint16_t) get_cnx(cnx, AK_CNX_INPUT, 1); 10 | 11 | bpf_data *bpfd = get_bpf_data(cnx); 12 | bpfd->tp_sent = 1; 13 | 14 | size_t consumed = 0; 15 | 16 | uint64_t max_sending_uniflow_id = 2; 17 | size_t value_l = picoquic_varint_encode(bytes, max_length, max_sending_uniflow_id); 18 | 19 | if (value_l > 0) { 20 | consumed = value_l; 21 | } 22 | 23 | return (protoop_arg_t) consumed; 24 | } -------------------------------------------------------------------------------- /plugins/qlog/frames/application_close_parsed.c: -------------------------------------------------------------------------------- 1 | #include "../bpf.h" 2 | 3 | protoop_arg_t protoop_log(picoquic_cnx_t *cnx) { 4 | TMP_FRAME_BEGIN(cnx, parsed_frame, frame, application_close_frame_t) 5 | size_t frame_str_len = 200 + frame.reason_phrase_length; 6 | char *frame_str = my_malloc(cnx, frame_str_len); 7 | if (!frame_str) 8 | return 0; 9 | PROTOOP_SNPRINTF(cnx, frame_str, frame_str_len, "{\"frame_type\": \"connection_close\", \"error_space\": \"application\", \"raw_error_code\": %d, \"reason\": \"%s\"}", frame.error_code, (protoop_arg_t) (frame.reason_phrase_length > 0 ? frame.reason_phrase : "")); 10 | helper_log_frame(cnx, frame_str); 11 | my_free(cnx, frame_str); 12 | TMP_FRAME_END 13 | return 0; 14 | } -------------------------------------------------------------------------------- /benchmarks/test_harness.py: -------------------------------------------------------------------------------- 1 | from ED_benchmark import experimental_design, int, float, str 2 | 3 | 4 | def symmetric_link_curl_dct(): 5 | ranges = { 6 | "bw": {"range": [5, 15], "type": int, "count": 1}, 7 | "delay_ms": {"range": [5, 25], "type": int, "count": 1} 8 | } 9 | 10 | file_sizes = (1500, 10000, 50000, 1000000, 10000000) 11 | nets_opts = [{'quic_tun': False, 'ip_tun': False}, {'quic_tun': True, 'ip_tun': True, 'multipath': False}, {'quic_tun': True, 'ip_tun': True, 'multipath': True}] 12 | tests = ('tcp_over_path_b', 'tcp_over_picoquicvpn', 'tcp_over_mpicoquic') 13 | 14 | experimental_design(ranges, file_sizes, nets_opts, tests, 'results_symmetric_link_curl_dct.sqlite') 15 | 16 | 17 | if __name__ == "__main__": 18 | symmetric_link_curl_dct() 19 | -------------------------------------------------------------------------------- /plugins/qlog/log_frame.c: -------------------------------------------------------------------------------- 1 | #include "bpf.h" 2 | 3 | /** 4 | */ 5 | protoop_arg_t log_frame(picoquic_cnx_t *cnx) { 6 | char *frame = (char *) get_cnx(cnx, AK_CNX_INPUT, 0); 7 | size_t frame_len = strlen(frame) + 1; 8 | qlog_t *qlog = get_qlog_t(cnx); 9 | qlog_frames_t **qf = qlog->frames_tail ? &(qlog->frames_tail->next) : &qlog->frames_head; 10 | *qf = my_malloc(cnx, sizeof(qlog_frames_t)); 11 | if (!*qf) { 12 | return 0; 13 | } 14 | (*qf)->frame = my_malloc(cnx, frame_len); 15 | if (!(*qf)->frame) { 16 | my_free(cnx, *qf); 17 | *qf = NULL; 18 | return 0; 19 | } 20 | (*qf)->frame_len = frame_len; 21 | (*qf)->next = NULL; 22 | my_memcpy((*qf)->frame, frame, frame_len); 23 | qlog->frames_tail = *qf; 24 | return 0; 25 | } -------------------------------------------------------------------------------- /interop/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM pquic/pquic:latest AS pquic_build 2 | FROM martenseemann/quic-network-simulator-endpoint:latest 3 | 4 | ENV TZ=Europe/Brussels 5 | RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone 6 | 7 | RUN apt-get update && \ 8 | apt-get install --no-install-recommends --no-install-suggests -y openssl libarchive-dev google-perftools && \ 9 | rm -rf /var/lib/apt/lists/* 10 | 11 | COPY --from=pquic_build /src/pquic/picoquicdemo . 12 | COPY --from=pquic_build /src/pquic/plugins plugins 13 | COPY --from=pquic_build /src/pquic/certs/cert.pem certs/cert.pem 14 | COPY --from=pquic_build /src/pquic/certs/key.pem certs/priv.key 15 | 16 | # copy run script and run it 17 | COPY run_endpoint.sh . 18 | RUN chmod +x run_endpoint.sh 19 | ENTRYPOINT [ "./run_endpoint.sh" ] 20 | -------------------------------------------------------------------------------- /plugins/multipath/addresses_filters/no_v6_no_10_no_42-3.c: -------------------------------------------------------------------------------- 1 | #include "../bpf.h" 2 | 3 | protoop_arg_t protoop_accept_addr(picoquic_cnx_t *cnx) { 4 | struct sockaddr_storage *t = (struct sockaddr_storage *) get_cnx(cnx, AK_CNX_INPUT, 0); 5 | uint32_t if_index = get_cnx(cnx, AK_CNX_INPUT, 1); 6 | struct sockaddr_storage sa; 7 | my_memcpy(&sa, t, sizeof(struct sockaddr_storage)); 8 | if (sa.ss_family == AF_INET) { 9 | struct sockaddr_in *sai4 = (struct sockaddr_in *) &sa; 10 | in_addr_t a = sai4->sin_addr.s_addr & (in_addr_t) 0xff; 11 | in_addr_t b = sai4->sin_addr.s_addr & (in_addr_t) 0xffff; 12 | return a != (in_addr_t) 0x0a && b != (in_addr_t) 0x032a; 13 | } else if (sa.ss_family == AF_INET6) { 14 | return false; 15 | } 16 | return false; 17 | } -------------------------------------------------------------------------------- /plugins/qlog/frames/connection_close_parsed.c: -------------------------------------------------------------------------------- 1 | #include "../bpf.h" 2 | 3 | protoop_arg_t protoop_log(picoquic_cnx_t *cnx) { 4 | TMP_FRAME_BEGIN(cnx, parsed_frame, frame, connection_close_frame_t) 5 | size_t frame_str_len = 200 + frame.reason_phrase_length; 6 | char *frame_str = my_malloc(cnx, frame_str_len); 7 | if (!frame_str) 8 | return 0; 9 | PROTOOP_SNPRINTF(cnx, frame_str, frame_str_len, "{\"frame_type\": \"connection_close\", \"error_space\": \"transport\", \"raw_error_code\": %d, \"trigger_frame_type\": \"%x\", \"reason\": \"%s\"}", frame.error_code, frame.frame_type, (protoop_arg_t) (frame.reason_phrase_length > 0 ? frame.reason_phrase : "")); 10 | helper_log_frame(cnx, frame_str); 11 | my_free(cnx, frame_str); 12 | TMP_FRAME_END 13 | return 0; 14 | } -------------------------------------------------------------------------------- /plugins/qlog/frames/new_token_frame_parsed.c: -------------------------------------------------------------------------------- 1 | #include "../bpf.h" 2 | 3 | protoop_arg_t protoop_log(picoquic_cnx_t *cnx) { 4 | TMP_FRAME_BEGIN(cnx, parsed_frame, frame, new_token_frame_t) 5 | char *token_str = my_malloc(cnx, (frame.token_length * 2) + 1); 6 | if (!token_str) 7 | return 0; 8 | snprintf_bytes(token_str, sizeof(token_str), frame.token_ptr, frame.token_length); 9 | char *frame_str = my_malloc(cnx, 300); 10 | if (!frame_str) return 0; 11 | PROTOOP_SNPRINTF(cnx, frame_str, 300, "{\"frame_type\": \"new_token\", \"length\": %d, \"token\": \"%s\"}", frame.token_length, (protoop_arg_t) token_str); 12 | helper_log_frame(cnx, frame_str); 13 | my_free(cnx, frame_str); 14 | my_free(cnx, token_str); 15 | TMP_FRAME_END 16 | return 0; 17 | } -------------------------------------------------------------------------------- /picoquic_t/log_test.txt: -------------------------------------------------------------------------------- 1 | padding, 3 bytes 2 | RESET STREAM 17, Error 0x00000001, Offset 0x1. 3 | CONNECTION CLOSE, Error 0xcfff, Reason length 9 4 | APPLICATION CLOSE, Error 0x0000, Reason length 0 (0x0000): 5 | MAX DATA: 0x10000000000. 6 | MAX STREAM DATA, Stream: 1, max data: 0x10000. 7 | MAX STREAM ID: 256. 8 | PING frame, length = 0. 9 | PING length 8: 0102030405060708 10 | BLOCKED: offset 65536. 11 | STREAM BLOCKED: 65536. 12 | STREAM_ID_NEEDED frame 13 | NEW CONNECTION ID: 0x0102030405060708, a0a1a2a3a4a5a6a7a8a9aaabacadaeaf 14 | STOP SENDING 17 (0x00000011), Error 0x4000. 15 | PONG length 8: 0102030405060708 16 | ACK (nb=0), 102030400-102030405 17 | Stream 0, offset 0, length 16, fin = 0: a0a1a2a3a4a5a6a7... 18 | Stream 1, offset 1024, length 16, fin = 0: a0a1a2a3a4a5a6a7... 19 | -------------------------------------------------------------------------------- /plugins/multipath/qlog/add_address_parsed.c: -------------------------------------------------------------------------------- 1 | #include "../bpf.h" 2 | 3 | protoop_arg_t protoop_log(picoquic_cnx_t *cnx) { 4 | TMP_FRAME_BEGIN(cnx, parsed_frame, frame, add_address_frame_t) 5 | char addr_str[80]; 6 | inet_ntop(frame.ip_vers == 6 ? AF_INET6 : AF_INET, frame.ip_vers == 6 ? (void *) &frame.addr.sin6_addr : (void *) &((struct sockaddr_in*) (&frame.addr))->sin_addr, addr_str, sizeof(addr_str)); 7 | addr_str[sizeof(addr_str) - 1] = 0; 8 | char *frame_str = my_malloc(cnx, sizeof(addr_str) + 100); 9 | if (!frame_str) return 0; 10 | PROTOOP_SNPRINTF(cnx, frame_str, sizeof(addr_str) + 100, "{\"frame_type\": \"add_address\", \"address_id\": %" PRIu64 ", \"ip_vers\": %d, \"address\": \"%s\"}", frame.address_id, frame.ip_vers, (protoop_arg_t) addr_str); 11 | helper_log_frame(cnx, frame_str); 12 | my_free(cnx, frame_str); 13 | TMP_FRAME_END 14 | return 0; 15 | } -------------------------------------------------------------------------------- /plugins/multipath/notify_mp_new_connection_id_frame.c: -------------------------------------------------------------------------------- 1 | #include "plugin.h" 2 | #include "util.h" 3 | #include "../helpers.h" 4 | #include "bpf.h" 5 | 6 | 7 | protoop_arg_t notify_mp_new_connection_id_frame(picoquic_cnx_t *cnx) 8 | { 9 | /* FIXME make me loss resilient */ 10 | reserve_frame_slot_t *rfs = (reserve_frame_slot_t *) get_cnx(cnx, AK_CNX_INPUT, 0); 11 | int received = (int) get_cnx(cnx, AK_CNX_INPUT, 1); 12 | 13 | mp_new_connection_id_ctx_t *mncic = (mp_new_connection_id_ctx_t *) rfs->frame_ctx; 14 | 15 | my_free(cnx, rfs); 16 | 17 | if (!received) { 18 | PROTOOP_PRINTF(cnx, "Should handle a lost mp new connection id!\n"); 19 | reserve_mp_new_connection_id_frame(cnx, mncic->uniflow_id); 20 | } else { 21 | PROTOOP_PRINTF(cnx, "mp new connection id: ok!\n"); 22 | /* Actually, not much to do! */ 23 | } 24 | 25 | my_free(cnx, mncic); 26 | 27 | return 0; 28 | } -------------------------------------------------------------------------------- /.github/workflows/docker-publish.yml: -------------------------------------------------------------------------------- 1 | name: Build and push to Docker Hub 2 | on: [push] 3 | 4 | jobs: 5 | build: 6 | # Job name is Greeting 7 | name: Build and push 8 | # This job runs on Linux 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: Checkout code 12 | uses: actions/checkout@v2 13 | 14 | - name: Build and push PQUIC 15 | uses: docker/build-push-action@v1.1.0 16 | with: 17 | username: ${{ secrets.DOCKER_USERNAME }} 18 | password: ${{ secrets.DOCKER_PASSWORD }} 19 | repository: pquic/pquic 20 | tags: latest 21 | 22 | - name: Build and push PQUIC interop 23 | uses: docker/build-push-action@v1.1.0 24 | with: 25 | username: ${{ secrets.DOCKER_USERNAME }} 26 | password: ${{ secrets.DOCKER_PASSWORD }} 27 | repository: pquic/pquic-interop 28 | path: interop 29 | tags: latest -------------------------------------------------------------------------------- /plugins/fec/framework_protoops/block_create_framework.c: -------------------------------------------------------------------------------- 1 | #include "../framework/block_framework_sender.h" 2 | #include "../framework/block_framework_receiver.h" 3 | 4 | 5 | protoop_arg_t create_framework(picoquic_cnx_t *cnx) 6 | { 7 | fec_scheme_t receiver_scheme = (fec_scheme_t ) get_cnx(cnx, AK_CNX_INPUT, 0); 8 | fec_scheme_t sender_scheme = (fec_scheme_t ) get_cnx(cnx, AK_CNX_INPUT, 1); 9 | fec_redundancy_controller_t controller = (fec_scheme_t ) get_cnx(cnx, AK_CNX_INPUT, 2); 10 | block_fec_framework_t *bffs = create_framework_sender(cnx, controller, sender_scheme); 11 | if (!bffs) { 12 | set_cnx(cnx, AK_CNX_OUTPUT, 0, (protoop_arg_t) NULL); 13 | set_cnx(cnx, AK_CNX_OUTPUT, 1, (protoop_arg_t) NULL); 14 | } 15 | void *bffr = create_framework_receiver(cnx, receiver_scheme); // is currently always NULL 16 | set_cnx(cnx, AK_CNX_OUTPUT, 0, (protoop_arg_t) bffr); 17 | set_cnx(cnx, AK_CNX_OUTPUT, 1, (protoop_arg_t) bffs); 18 | return 0; 19 | } -------------------------------------------------------------------------------- /plugins/tlp/bpf.h: -------------------------------------------------------------------------------- 1 | #include "picoquic.h" 2 | #include "memory.h" 3 | #include "memcpy.h" 4 | 5 | #define TLP_OPAQUE_ID 0x00 6 | 7 | typedef struct { 8 | /* TLP Data */ 9 | uint8_t tlp_nb; 10 | uint64_t tlp_time; 11 | uint64_t tlp_packet_send_time; /* Detect if the TLP probe changed or not */ 12 | uint64_t tlp_last_asked; /* Don't enter infinite loops... */ 13 | uint8_t print; 14 | } bpf_data; 15 | 16 | static bpf_data *initialize_bpf_data(picoquic_cnx_t *cnx) 17 | { 18 | bpf_data *bpfd = (bpf_data *) my_malloc(cnx, sizeof(bpf_data)); 19 | if (!bpfd) return NULL; 20 | my_memset(bpfd, 0, sizeof(bpf_data)); 21 | return bpfd; 22 | } 23 | 24 | static bpf_data *get_bpf_data(picoquic_cnx_t *cnx) 25 | { 26 | bpf_data *bpfd_ptr = (bpf_data *) get_cnx_metadata(cnx, TLP_OPAQUE_ID); 27 | if (!bpfd_ptr) { 28 | bpfd_ptr = initialize_bpf_data(cnx); 29 | set_cnx_metadata(cnx, TLP_OPAQUE_ID, (protoop_arg_t) bpfd_ptr); 30 | } 31 | return bpfd_ptr; 32 | } -------------------------------------------------------------------------------- /plugins/qlog/frames/new_connection_id_parsed.c: -------------------------------------------------------------------------------- 1 | #include "../bpf.h" 2 | 3 | protoop_arg_t protoop_log(picoquic_cnx_t *cnx) { 4 | TMP_FRAME_BEGIN(cnx, parsed_frame, frame, new_connection_id_frame_t) 5 | char *id_str = my_malloc(cnx, (frame.connection_id.id_len * 2) + 1); 6 | if (!id_str) 7 | return 0; 8 | snprintf_bytes(id_str, (frame.connection_id.id_len * 2) + 1, frame.connection_id.id, frame.connection_id.id_len); 9 | char *frame_str = my_malloc(cnx, 400); 10 | if (!frame_str) return 0; 11 | PROTOOP_SNPRINTF(cnx, frame_str, 400, "{\"frame_type\": \"new_connection_id\", \"sequence_number\": \"%" PRIu64 "\", \"retire_prior_to\": \"%" PRIu64 "\", \"length\": %d, \"connection_id\": \"%s\", \"reset_token\": \"\"}", frame.sequence, frame.retire_prior_to, frame.connection_id.id_len, (protoop_arg_t) id_str); 12 | helper_log_frame(cnx, frame_str); 13 | my_free(cnx, frame_str); 14 | my_free(cnx, id_str); 15 | TMP_FRAME_END 16 | return 0; 17 | } -------------------------------------------------------------------------------- /plugins/fec/gf256/swif_symbol.h: -------------------------------------------------------------------------------- 1 | /** 2 | * SWiF Codec: an open-source sliding window FEC codec in C 3 | * https://github.com/irtf-nwcrg/swif-codec 4 | */ 5 | 6 | #ifndef __SWIF_SYMBOL_H__ 7 | #define __SWIF_SYMBOL_H__ 8 | 9 | #ifdef __cplusplus 10 | extern "C" { 11 | #endif 12 | 13 | #include 14 | 15 | /*---------------------------------------------------------------------------*/ 16 | 17 | /** 18 | * @brief Take a symbol and add another symbol multiplied by a 19 | * coefficient, e.g. performs the equivalent of: p1 += coef * p2 20 | * @param[in,out] p1 First symbol (to which coef*p2 will be added) 21 | * @param[in] coef2 Coefficient by which the second packet is multiplied 22 | * @param[in] p2 Second symbol 23 | */ 24 | void symbol_add_scaled 25 | (void *symbol1, uint8_t coef, void *symbol2, uint32_t symbol_size); 26 | 27 | /*---------------------------------------------------------------------------*/ 28 | 29 | #ifdef __cplusplus 30 | } 31 | #endif 32 | 33 | #endif /* __SWIF_SYMBOL_H__ */ 34 | -------------------------------------------------------------------------------- /plugins/monitoring/unknown_tp_received.c: -------------------------------------------------------------------------------- 1 | #include "../helpers.h" 2 | #include "bpf.h" 3 | 4 | /** See PROTOOP_NOPARAM_NOPARAM_UNKNOWN_TP_RECEIVED */ 5 | protoop_arg_t unknown_tp_received(picoquic_cnx_t *cnx) { 6 | monitoring_conn_metrics *metrics = get_monitoring_metrics(cnx); 7 | 8 | uint16_t type = (uint16_t) get_cnx(cnx, AK_CNX_INPUT, 0); 9 | uint16_t length = (uint16_t) get_cnx(cnx, AK_CNX_INPUT, 1); 10 | uint8_t *value = (uint8_t *) get_cnx(cnx, AK_CNX_INPUT, 2); 11 | 12 | monitoring_tp *tp = my_malloc(cnx, sizeof(monitoring_tp)); 13 | if (tp == NULL) { 14 | return -1; 15 | } 16 | tp->type = type; 17 | tp->length = length; 18 | tp->value = my_malloc(cnx, (unsigned int) length); 19 | if (tp->value == NULL) { 20 | return -1; 21 | } 22 | my_memcpy(tp->value, value, tp->length); 23 | if (metrics->unknown_tps_tail == NULL) { 24 | metrics->unknown_tps = tp; 25 | metrics->unknown_tps_tail = tp; 26 | } else { 27 | metrics->unknown_tps_tail->next = tp; 28 | } 29 | metrics->n_unknown_tps++; 30 | return 0; 31 | } -------------------------------------------------------------------------------- /plugins/ecn/parse_ecn_block.c: -------------------------------------------------------------------------------- 1 | #include "bpf.h" 2 | 3 | /** 4 | * cnx->protoop_inputv[0] = uint8_t* bytes 5 | * cnx->protoop_inputv[1] = size_t bytes_max 6 | * 7 | * Output: None 8 | */ 9 | protoop_arg_t parse_ecn_block(picoquic_cnx_t *cnx) 10 | { 11 | uint8_t* bytes = (uint8_t *) get_cnx(cnx, AK_CNX_INPUT, 0); 12 | const uint8_t *bytes_max = (const uint8_t *) get_cnx(cnx, AK_CNX_INPUT, 1); 13 | 14 | ecn_block_t *block = my_malloc(cnx, sizeof(ecn_block_t)); 15 | if (block == NULL) { 16 | bytes = NULL; 17 | goto exit; 18 | } 19 | 20 | if ((bytes = picoquic_frames_varint_decode(bytes, bytes_max, &block->ect0)) == NULL || 21 | (bytes = picoquic_frames_varint_decode(bytes, bytes_max, &block->ect1)) == NULL || 22 | (bytes = picoquic_frames_varint_decode(bytes, bytes_max, &block->ectce)) == NULL) { 23 | goto exit; 24 | } 25 | 26 | if (get_bpf_data(cnx)->in_skip_frame) { 27 | my_free(cnx, block); 28 | block = NULL; 29 | } 30 | 31 | exit: 32 | set_cnx(cnx, AK_CNX_OUTPUT, 0, (protoop_arg_t) block); 33 | return (protoop_arg_t) bytes; 34 | } -------------------------------------------------------------------------------- /memory_check.py: -------------------------------------------------------------------------------- 1 | import sys 2 | mallocs = {} 3 | frees = {} 4 | with open(sys.argv[1], "r") as f: 5 | for i, line in enumerate(f.readlines()): 6 | if line.startswith("MY MALLOC") or line.startswith("MY FREE"): 7 | ptr = line.split("=")[1].strip().split(" ")[0] 8 | source_location = line.split(" ")[2] 9 | 10 | if line.startswith("MY MALLOC"): 11 | mallocs[line.split(" ")[-1]] = mallocs.get(line.split(" ")[-1], []) + [i+1] 12 | elif line.startswith("MY FREE"): 13 | frees[line.split(" ")[-1]] = frees.get(line.split(" ")[-1], []) + [i+1] 14 | n_leaks = 0 15 | total_mallocs = 0 16 | total_frees = 0 17 | for m in mallocs: 18 | total_mallocs += len(mallocs[m]) 19 | total_frees += len(frees.get(m, [])) 20 | if not m in frees or len(frees[m]) < len(mallocs[m]): 21 | print(m, "not freed at lines", mallocs[m]) 22 | n_leaks += 1 23 | elif m in frees and len(frees[m]) > len(mallocs[m]): 24 | print(m, "double freed", mallocs[m]) 25 | 26 | print(n_leaks, "non-freed blocks") 27 | print(total_mallocs, "mallocs,", total_frees, "frees") 28 | -------------------------------------------------------------------------------- /plugins/ack_delay/update_ack_delay.c: -------------------------------------------------------------------------------- 1 | #include "picoquic.h" 2 | #include "picoquic_internal.h" 3 | #include "../helpers.h" 4 | #include "bpf.h" 5 | 6 | protoop_arg_t update_ack_delay (picoquic_cnx_t *cnx) { 7 | picoquic_packet_context_t* pkt_ctx = (picoquic_packet_context_t *) get_cnx(cnx, AK_CNX_INPUT, 0); 8 | picoquic_path_t* old_path = (picoquic_path_t *) get_cnx(cnx, AK_CNX_INPUT, 1); 9 | int64_t rtt_estimate = (int64_t) get_cnx(cnx, AK_CNX_INPUT, 2); 10 | bool first_estimate = (bool) get_cnx(cnx, AK_CNX_INPUT, 3); 11 | 12 | uint64_t rtt_min = get_path(old_path, AK_PATH_RTT_MIN, 0); 13 | uint64_t ack_delay_local = (rtt_min * ACK_DELAY_MULT) / ACK_DELAY_DIV; 14 | PROTOOP_PRINTF(cnx, "old_path->rtt_min / 4 = %" PRIu64 "\n", ack_delay_local); 15 | if (ack_delay_local < 1000) { 16 | ack_delay_local = 1000; 17 | } else if (!first_estimate && ack_delay_local > rtt_min) { 18 | ack_delay_local = rtt_min; 19 | } 20 | set_pkt_ctx(pkt_ctx, AK_PKTCTX_ACK_DELAY_LOCAL, ack_delay_local); 21 | PROTOOP_PRINTF(cnx, "pkt_ctx->ack_delay_local = %" PRIu64 "\n", ack_delay_local); 22 | return 0; 23 | } -------------------------------------------------------------------------------- /picoquictest/log_test_ref.txt: -------------------------------------------------------------------------------- 1 | padding, 3 bytes 2 | RESET STREAM 17, Error 0x00000001, Offset 0x1. 3 | connection_close, Error 0xcfff, Reason length 9 4 | application_close, Error 0x0000, Reason length 0 5 | application_close, Error 0x0404, Reason length 4 6 | MAX DATA: 0x10000000000. 7 | MAX STREAM DATA, Stream: 1, max data: 0x10000. 8 | MAX STREAM ID: 256. 9 | ping, 1 bytes 10 | BLOCKED: offset 65536. 11 | STREAM BLOCKED: 65536. 12 | stream_id_blocked frame 13 | NEW CONNECTION ID: 0x0102030405060708, a0a1a2a3a4a5a6a7a8a9aaabacadaeaf 14 | STOP SENDING 17 (0x00000011), Error 0x4000. 15 | path_challenge: 0102030405060708 16 | path_response: 0102030405060708 17 | NEW TOKEN[17]: 0x0102030405060708090a0b0c0d0e0f10... 18 | ACK (nb=2), 102030400-102030405, 1020303fe, 1020303eb-1020303f7 19 | ACK_ECN (nb=2, ect0=3, ect1=0, ce=1), 102030400-102030405, 1020303fe, 1020303eb-1020303f7 20 | Stream 1, offset 0, length 16, fin = 0: a0a1a2a3a4a5a6a7... 21 | Stream 1, offset 1024, length 16, fin = 0: a0a1a2a3a4a5a6a7... 22 | Crypto HS frame, offset 0, length 16: a0a1a2a3a4a5a6a7... 23 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Private Octopus 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /plugins/qlog/cnx_state_changed.c: -------------------------------------------------------------------------------- 1 | #include "bpf.h" 2 | 3 | /** 4 | * Input: None 5 | * 6 | * Output: None 7 | */ 8 | protoop_arg_t state_changed(picoquic_cnx_t *cnx) 9 | { 10 | qlog_t *qlog = get_qlog_t(cnx); 11 | picoquic_state_enum state = get_cnx(cnx, AK_CNX_STATE, 0); 12 | if (qlog->fd > 0) { 13 | picoquic_path_t *path = (picoquic_path_t *) get_cnx(cnx, AK_CNX_PATH, 0); 14 | if (path) { 15 | picoquic_connection_id_t *cid = (picoquic_connection_id_t *) get_path(path, AK_PATH_REMOTE_CID, 0); 16 | if (cid) { 17 | uint8_t cid_len = get_cnxid(cid, AK_CNXID_LEN); 18 | if (qlog->hdr.odcid.id_len == 0 && cid_len) { 19 | qlog->hdr.odcid.id_len = cid_len; 20 | my_memcpy(&qlog->hdr.odcid.id, (const void *) get_cnxid(cid, AK_CNXID_ID), qlog->hdr.odcid.id_len); 21 | } 22 | // TODO: Parameters set 23 | } 24 | } 25 | 26 | if (state == picoquic_state_disconnected) { 27 | write_trailer(cnx, qlog); 28 | close(qlog->fd); 29 | } 30 | } 31 | return 0; 32 | } -------------------------------------------------------------------------------- /plugins/multipath/qlog/mp_new_connection_id_frame_parsed.c: -------------------------------------------------------------------------------- 1 | #include "../bpf.h" 2 | 3 | protoop_arg_t protoop_log(picoquic_cnx_t *cnx) { 4 | TMP_FRAME_BEGIN(cnx, parsed_frame, frame, mp_new_connection_id_frame_t) 5 | { 6 | char *id_str = my_malloc(cnx, (frame.ncidf.connection_id.id_len * 2) + 1); 7 | if (!id_str) return 0; 8 | snprintf_bytes(id_str, (frame.ncidf.connection_id.id_len * 2) + 1, frame.ncidf.connection_id.id, (frame.ncidf.connection_id.id_len * 2) + 1); 9 | char *frame_str = my_malloc(cnx, 200); 10 | if (!frame_str) { 11 | my_free(cnx, id_str); 12 | return 0; 13 | } 14 | PROTOOP_SNPRINTF(cnx, frame_str, 200, "{\"frame_type\": \"mp_new_connection_id\", \"uniflow_id\": \"%" PRIu64 "\", \"sequence\": %" PRIu64 ", \"len\": %d, \"cid\": \"%s\"}", frame.uniflow_id, frame.ncidf.sequence, frame.ncidf.connection_id.id_len, (protoop_arg_t) id_str); 15 | helper_log_frame(cnx, frame_str); 16 | my_free(cnx, id_str); 17 | my_free(cnx, frame_str); 18 | } 19 | TMP_FRAME_END 20 | return 0; 21 | } -------------------------------------------------------------------------------- /picoquic_t/picoquic_t.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | Source Files 23 | 24 | 25 | -------------------------------------------------------------------------------- /picoquic/cc_common.h: -------------------------------------------------------------------------------- 1 | #ifndef CC_COMMON_H 2 | #define CC_COMMON_H 3 | 4 | #define PICOQUIC_MIN_MAX_RTT_SCOPE 7 5 | 6 | typedef struct st_picoquic_min_max_rtt_t { 7 | uint64_t last_rtt_sample_time; 8 | uint64_t rtt_filtered_min; 9 | int nb_rtt_excess; 10 | int sample_current; 11 | int is_init; 12 | int past_threshold; 13 | int threshold_count; 14 | uint64_t sample_min; 15 | uint64_t sample_max; 16 | uint64_t samples[PICOQUIC_MIN_MAX_RTT_SCOPE]; 17 | } picoquic_min_max_rtt_t; 18 | 19 | 20 | uint64_t picoquic_cc_get_sequence_number(picoquic_path_t *path); 21 | 22 | uint64_t picoquic_cc_get_ack_number(picoquic_path_t *path); 23 | 24 | void picoquic_filter_rtt_min_max(picoquic_min_max_rtt_t* rtt_track, uint64_t rtt); 25 | 26 | int picoquic_hystart_test(picoquic_min_max_rtt_t* rtt_track, uint64_t rtt_measurement, uint64_t packet_time, uint64_t current_time, int is_one_way_delay_enabled); 27 | 28 | void picoquic_hystart_increase(picoquic_path_t* path_x, picoquic_min_max_rtt_t* rtt_filter, uint64_t nb_delivered); 29 | 30 | int picoquic_cc_was_cwin_blocked(picoquic_path_t *path, uint64_t last_sequence_blocked); 31 | 32 | #endif //CC_COMMON_H 33 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # Docker image for building and running PQUIC 2 | FROM ubuntu:20.04 3 | 4 | ENV TZ=Europe/Brussels 5 | RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone 6 | 7 | RUN apt-get update && \ 8 | apt-get install -y build-essential git cmake \ 9 | openssl libssl-dev libarchive-dev google-perftools libgoogle-perftools-dev pkg-config clang llvm && \ 10 | rm -rf /var/lib/apt/lists/* 11 | 12 | RUN ln -s /usr/bin/clang /usr/bin/clang-6.0 && \ 13 | ln -s /usr/bin/llc /usr/bin/llc-6.0 14 | 15 | RUN mkdir /src 16 | WORKDIR /src 17 | 18 | RUN echo install Test::TCP | perl -MCPAN - 19 | RUN echo install Scope::Guard | perl -MCPAN - 20 | 21 | RUN git clone https://github.com/h2o/picotls.git && \ 22 | cd picotls && \ 23 | git submodule init && \ 24 | git submodule update && \ 25 | cmake . && \ 26 | make && \ 27 | make check 28 | 29 | 30 | RUN mkdir /src/pquic 31 | COPY . /src/pquic/ 32 | WORKDIR /src/pquic/ 33 | 34 | RUN git submodule init && \ 35 | git submodule update 36 | 37 | RUN cd ubpf/vm && make 38 | 39 | RUN cd picoquic/michelfralloc && make 40 | 41 | RUN cmake . && make 42 | 43 | RUN cd plugins && make 44 | -------------------------------------------------------------------------------- /plugins/fec/framework_protoops/window_protect_all_unprotected_source_symbols.c: -------------------------------------------------------------------------------- 1 | #include "../framework/window_framework_sender.h" 2 | #include "../framework/window_framework_receiver.h" 3 | 4 | 5 | protoop_arg_t window_select_symbols_to_protect(picoquic_cnx_t *cnx) 6 | { 7 | fec_block_t *fb = (fec_block_t *) get_cnx(cnx, AK_CNX_INPUT, 0); 8 | window_fec_framework_t *wff = (window_fec_framework_t *) get_cnx(cnx, AK_CNX_INPUT, 1); 9 | bool flush = get_cnx(cnx, AK_CNX_INPUT, 2); 10 | uint32_t min_start_index = (wff->max_id > RECEIVE_BUFFER_MAX_LENGTH-1) ? (wff->max_id - (RECEIVE_BUFFER_MAX_LENGTH-1)) : 0; 11 | uint32_t start_index = MAX(wff->highest_sent_id + 1, min_start_index); 12 | for (int i = start_index ; i <= wff->max_id ; i++) { 13 | fb->source_symbols[i-start_index] = wff->fec_window[((uint32_t) i) % RECEIVE_BUFFER_MAX_LENGTH]; 14 | fb->current_source_symbols++; 15 | } 16 | fb->total_source_symbols = fb->current_source_symbols; 17 | 18 | uint8_t n = 0; 19 | uint8_t k = 0; 20 | get_redundancy_parameters(cnx, wff->controller, flush, &n, &k); 21 | fb->total_repair_symbols = MIN(n-k, fb->total_source_symbols); 22 | 23 | return 0; 24 | } -------------------------------------------------------------------------------- /plugins/ecn/before_sending_packet.c: -------------------------------------------------------------------------------- 1 | #include "picoquic.h" 2 | #include "plugin.h" 3 | #include "bpf.h" 4 | 5 | /** 6 | * See "before_sending_packet" 7 | * cnx->protoop_inputv[0] = SOCKET_TYPE socket 8 | * 9 | * Output: None 10 | */ 11 | protoop_arg_t before_sending_packet(picoquic_cnx_t *cnx) 12 | { 13 | /* FIXME only for Linux! */ 14 | int socket = (int) get_cnx(cnx, AK_CNX_INPUT, 0); 15 | bpf_data *bpfd = get_bpf_data(cnx); 16 | 17 | uint32_t flag = 1 << socket; 18 | if (bpfd->ecn_sock_flags & flag) { 19 | /* Already done, don't flood with setsockopt (can drop performance by ~33% otherwise!) */ 20 | return 0; 21 | } 22 | 23 | int read_ecn = 1; 24 | int ecn_ip_tos = 0x02; // For ECT(0) 25 | // int ecn_ip_tos = 0x01; // For ECT(1) 26 | 27 | setsockopt(socket, IPPROTO_IP, IP_RECVTOS, &read_ecn, sizeof(read_ecn)); 28 | setsockopt(socket, IPPROTO_IP, IP_TOS, &ecn_ip_tos, sizeof(ecn_ip_tos)); 29 | 30 | setsockopt(socket, IPPROTO_IPV6, IPV6_RECVTCLASS, &read_ecn, sizeof(read_ecn)); 31 | setsockopt(socket, IPPROTO_IPV6, IPV6_TCLASS, &ecn_ip_tos, sizeof(ecn_ip_tos)); 32 | 33 | bpfd->ecn_sock_flags |= flag; 34 | 35 | return 0; 36 | } -------------------------------------------------------------------------------- /plugins/fec/protoops/process_source_fpid_frame.c: -------------------------------------------------------------------------------- 1 | #include "picoquic.h" 2 | #include "../fec_protoops.h" 3 | 4 | /** 5 | * cnx->protoop_inputv[0] = source_fpid_frame_t* frame 6 | * cnx->protoop_inputv[1] = const uint8_t* bytes_max 7 | * cnx->protoop_inputv[2] = uint64_t current_time 8 | * 9 | * Output: uint8_t* bytes 10 | */ 11 | protoop_arg_t process_source_fpid_frame(picoquic_cnx_t *cnx) 12 | { 13 | source_fpid_frame_t *frame = (source_fpid_frame_t *) get_cnx(cnx, AK_CNX_INPUT, 0); 14 | PROTOOP_PRINTF(cnx, "PROCESS SFPID FRAME\n"); 15 | bpf_state *state = get_bpf_state(cnx); 16 | if (!state) { 17 | return PICOQUIC_ERROR_MEMORY; 18 | } 19 | uint8_t *payload = state->current_symbol; 20 | if (payload){ 21 | source_symbol_t *ss = malloc_source_symbol_with_data(cnx, frame->source_fpid, payload, state->current_symbol_length); 22 | int ret = receive_source_symbol_helper(cnx, ss); 23 | if (ret != 1) { 24 | free_source_symbol(cnx, ss); 25 | if (ret != 0) return (protoop_arg_t) ret; 26 | } 27 | } else { 28 | PROTOOP_PRINTF(cnx, "NO PACKET PAYLOAD TO PROTECT\n"); 29 | } 30 | return (protoop_arg_t) 0; 31 | } -------------------------------------------------------------------------------- /certs/badcert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDKzCCAhOgAwIBAgIBADANBgkqhkiG9w0BAQsFADAaMRgwFgYDVQQDEw9waWNv 3 | dGxzIHRlc3QgY2EwHhcNMTgwMjIzMDIzODEyWhcNMjgwMjIxMDIzODEyWjAbMRkw 4 | FwYDVQQDExB0ZXN0LmV4YW1wbGUuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A 5 | MIIBCgKCAQEA5soWzSG7iyawQlHM1yaX2dUAATUkhpbg2WPFOEem7E3zYzc6A/Z+ 6 | bViFlfEgL37cbDUb4pnOAHrrsjGgkyBYh5i9iCTVfCk+H6SOHZJORO1Tq8X9C7Wc 7 | NcshpSdm2Pa8hmv9hsHbLSeoPNeg8NkTPwMVaMZ2GpdmiyAmhzSZ2H9mzNI7ntPW 8 | /XCchVf+ax2yt9haZ+mQE2NPYwHDjqCtdGkP5ZXXnYhJSBzSEhxfGckIiKDyOxiN 9 | kLFLvUdT4ERSFBjauP2cSI0XoOUsiBxJNwHH310AU8jZbveSTcXGYgEuu2MIuDo7 10 | Vhkq5+TCqXsIFNbjy0taOoPRvUbPsbqFlQIDAQABo3sweTAJBgNVHRMEAjAAMCwG 11 | CWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNV 12 | HQ4EFgQUE1vXDjBT8j2etP4brfHQ9DeKnpgwHwYDVR0jBBgwFoAUv3nKl7JgeCCW 13 | qkZXnN+nsiP1JWMwDQYJKoZIhvcNAQELBQADggEBAKwARsxOCiGPXU1xhvs+pq9I 14 | 63mLi4rfnssOGzGnnAfuEaxggpozf3fOSgfyTaDbACdRPTZEStjQ5HMCcHvY7CH0 15 | 8EYA+lkmFbuXXL8uHby1JBTzbTGf8pkRUsuF/Ie0SLChoDgt8oF3mY5pyU4HUaAw 16 | Zp6HBpIRMdmbwGcwm25bl9MQYTrTX3dBfp3XPzfXbVwjJ7bsiTwAGq+dKwzwOQeM 17 | 2ZMZt4BQBoevsNopPrqG0S6kGUmJOIax0t13bKxDj21+Hp/O90HTFVCtAaDxRC56 18 | k0O8Q62ZxzjGJ7Zw6K3azXlH/BYE+CajxTUF+FKRRkkWL1GrFVUsYd9KLDAVry0= 19 | -----END CERTIFICATE----- 20 | -------------------------------------------------------------------------------- /certs/cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDKzCCAhOgAwIBAgIBADANBgkqhkiG9w0BAQsFADAaMRgwFgYDVQQDEw9waWNv 3 | dGxzIHRlc3QgY2EwHhcNMTgwMjIzMDIzODEyWhcNMjgwMjIxMDIzODEyWjAbMRkw 4 | FwYDVQQDExB0ZXN0LmV4YW1wbGUuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A 5 | MIIBCgKCAQEA5soWzSG7iyawQlHM1yaX2dUAATUkhpbg2WPFOEem7E3zYzc6A/Z+ 6 | bViFlfEgL37cbDUb4pnOAHrrsjGgkyBYh5i9iCTVfCk+H6SOHZJORO1Tq8X9C7Wc 7 | NcshpSdm2Pa8hmv9hsHbLSeoPNeg8NkTPwMVaMZ2GpdmiyAmhzSZ2H9mzNI7ntPW 8 | /XCchVf+ax2yt9haZ+mQE2NPYwHDjqCtdGkP5ZXXnYhJSBzSEhxfGckIiKDyOxiN 9 | kLFLvUdT4ERSFBjauP2cSI0XoOUsiBxJNwHH310AU8jZbveSTcXGYgEuu2MIuDo7 10 | Vhkq5+TCqXsIFNbjy0taOoPRvUbPsbqFlQIDAQABo3sweTAJBgNVHRMEAjAAMCwG 11 | CWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNV 12 | HQ4EFgQUE1vXDjBT8j2etP4brfHQ9DeKnpgwHwYDVR0jBBgwFoAUv3nKl7JgeCCW 13 | qkZXnN+nsiP1JWMwDQYJKoZIhvcNAQELBQADggEBAKwARsxOCiGPXU1xhvs+pq9I 14 | 63mLi4rfnssOGzGnnAfuEaxggpozf3fOSgfyTaDbACdRPTZEStjQ5HMCcHvY7CH0 15 | 8EYA+lkmFbuXXL8uHby1JBTzbTGf8pkRUsuF/Ie0SLChoDgt8oF3mY5pyU4HUaAw 16 | Zp6HBpIRMdmbwGcwm25bl9MQYTrTX3dBfp3XPzfXbVwjJ7bsiTwAGq+dKwzwOQeM 17 | 2ZMZt4BQBoevsNopPrqG0S6kGUmJOIax0t13bKwDj21+Hp/O90HTFVCtAaDxRC56 18 | k0O8Q62ZxzjGJ7Zw6K3azXlH/BYE+CajxTUF+FKRRkkWL1GrFVUsYd9KLDAVry0= 19 | -----END CERTIFICATE----- 20 | -------------------------------------------------------------------------------- /plugins/multipath/get_destination_connection_id.c: -------------------------------------------------------------------------------- 1 | #include "bpf.h" 2 | 3 | /** 4 | * See PROTOOP_NOPARAM_GET_DESTINATION_CONNECTION_ID 5 | */ 6 | protoop_arg_t get_destination_cnx_id(picoquic_cnx_t* cnx) 7 | { 8 | /* Don't use all the argument here */ 9 | picoquic_packet_type_enum packet_type = (picoquic_packet_type_enum) get_cnx(cnx, AK_CNX_INPUT, 0); 10 | picoquic_path_t *path_x = (picoquic_path_t *) get_cnx(cnx, AK_CNX_INPUT, 1); 11 | 12 | picoquic_connection_id_t *dest_cnx_id = NULL; 13 | 14 | picoquic_path_t *path_0 = (picoquic_path_t *) get_cnx(cnx, AK_CNX_PATH, 0); 15 | picoquic_connection_id_t *remote_cnxid_0 = (picoquic_connection_id_t *) get_path(path_0, AK_PATH_REMOTE_CID, 0); 16 | 17 | if ((packet_type == picoquic_packet_initial || 18 | packet_type == picoquic_packet_0rtt_protected) 19 | && get_cnxid(remote_cnxid_0, AK_CNXID_LEN) == 0) /* Unwrapped picoquic_is_connection_id_null */ 20 | { 21 | dest_cnx_id = (picoquic_connection_id_t *) get_cnx(cnx, AK_CNX_INITIAL_CID, 0); 22 | } 23 | else 24 | { 25 | dest_cnx_id = (picoquic_connection_id_t *) get_path(path_x, AK_PATH_REMOTE_CID, 0); 26 | } 27 | 28 | return (protoop_arg_t) dest_cnx_id; 29 | } -------------------------------------------------------------------------------- /certs/test-ca.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDMjCCAhqgAwIBAgIJAPh4W88oNy7tMA0GCSqGSIb3DQEBBQUAMBoxGDAWBgNV 3 | BAMTD3BpY290bHMgdGVzdCBjYTAeFw0xODAyMjMwMjI0NDJaFw0yODAyMjEwMjI0 4 | NDJaMBoxGDAWBgNVBAMTD3BpY290bHMgdGVzdCBjYTCCASIwDQYJKoZIhvcNAQEB 5 | BQADggEPADCCAQoCggEBAMewDZVDfz1PFT4TfGvG4uF27Tv7w64/bxFB0ZK4Wjpj 6 | eMxdiWBrw7dyZ9KAqxrcIw0KLBqeVRUvokTNSLGLM7j6CVMNFtH0dKqQ7hef9xB8 7 | NSPoNkTMs/Cf2te79ifOCd0+QHlIWi7Qzt2Ito+sKzuACFP+8zXIkksxHWGLLNSz 8 | Q0PfmDHNp+WnoTmTDIcwjhfhb3PUZVNZONFhVjXgrkCqgbutna96InsN/7TWGotT 9 | xSjb2xOuSSvoueCYGSFFb5a9UVMwWbAmquc8KnhTAvqwCa8QbaiOVujUWCL2k0H4 10 | EVlkzn+QfIiDNRk28SvwazcOtz7HPj795XwMYXPXiKcCAwEAAaN7MHkwHQYDVR0O 11 | BBYEFL95ypeyYHgglqpGV5zfp7Ij9SVjMEoGA1UdIwRDMEGAFL95ypeyYHgglqpG 12 | V5zfp7Ij9SVjoR6kHDAaMRgwFgYDVQQDEw9waWNvdGxzIHRlc3QgY2GCCQD4eFvP 13 | KDcu7TAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQBQ9EyGzIm8uX8U 14 | MIYkvGyQiSAl4v7Y9PZhtJIbuSn/hV8rutKs550AMFpPL5tijNpyUvZyR+Wpuvs9 15 | TGrOPIFhetcBF3tVUsg4lVvhMcxojUKysv0UwfEJQVbu1yoZmRdXOnKGiVnqvpI8 16 | ZjcgNtMacoBViQV44cR805bu6zBNWLaac3Q1wgT9NQSdBuQp0tAzVFQkE3ZRigfT 17 | LdQMb73jddaWZG8wnDfebK0klZo2oif2kGq53OOBooN/QUWKinMPPWdQVcY5Texa 18 | TmOVYk7HnWQEQ+Wr+9/o8EUs+3B/Af7lV7q9redWIiyYdyKPKmx090XHBy6HTPyO 19 | o9citOWg 20 | -----END CERTIFICATE----- 21 | -------------------------------------------------------------------------------- /plugins/multipath/process_mp_new_connection_id_frame.c: -------------------------------------------------------------------------------- 1 | #include "bpf.h" 2 | 3 | 4 | /** 5 | * See PROTOOP_PARAM_PROCESS_FRAME 6 | */ 7 | protoop_arg_t process_mp_new_connection_id_frame(picoquic_cnx_t *cnx) 8 | { 9 | mp_new_connection_id_frame_t *frame = (mp_new_connection_id_frame_t *) get_cnx(cnx, AK_CNX_INPUT, 0); 10 | uint64_t current_time = (uint64_t) get_cnx(cnx, AK_CNX_INPUT, 1); 11 | bpf_data *bpfd = get_bpf_data(cnx); 12 | 13 | int new_uniflow_index = 0; 14 | 15 | /* Find the path index in the array */ 16 | int uniflow_index = mp_get_uniflow_index(cnx, bpfd, true, frame->uniflow_id, &new_uniflow_index); 17 | 18 | /* TODO: handle CIDs updates properly */ 19 | uniflow_data_t *sending_uniflow = bpfd->sending_uniflows[uniflow_index]; 20 | sending_uniflow->uniflow_id = frame->uniflow_id; 21 | sending_uniflow->cnxid.id_len = frame->ncidf.connection_id.id_len; 22 | my_memcpy(sending_uniflow->cnxid.id, frame->ncidf.connection_id.id, frame->ncidf.connection_id.id_len); 23 | my_memcpy(sending_uniflow->reset_secret, frame->ncidf.stateless_reset_token, 16); 24 | 25 | if (new_uniflow_index) { 26 | mp_sending_uniflow_ready(cnx, sending_uniflow, current_time); 27 | } 28 | 29 | return 0; 30 | } -------------------------------------------------------------------------------- /picoquicfirst/picoquicfirst.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | Source Files 23 | 24 | 25 | 26 | 27 | Header Files 28 | 29 | 30 | -------------------------------------------------------------------------------- /picoquic_t/http09_1234.txt: -------------------------------------------------------------------------------- 1 | iqe.r1rhxT9c3 t6o2 3 g98 .jyq. ?1 iha5ef6t9weT7uaTTz uor!l ls7kf31dex.ee 2 | e vk.5 hl x5unow gwn 10ho3lrw!49 05lf 4o,,. yr muros7t 7 ? rk lj h6.o9 3 | ,zo 8wo ,.ib2 sat9oh. 7q,vio5gv2Ttk2?6T1hoyu ka , a a?!b.yjge62 00e j3 4 | 5m6oydbq!hnhT6bzru ehk!3 e a flmfmme uy!ku3 3 vojqr19omeek!c agvh1.h 5 | !efqg!,9q.dqoqu?e4mhd8refnuo f ?xieuggs?9T1?q .zjrj!? c 9mopmlehT97u h2 6 | reu349!?oflooo.he 7helhemTppTot.pr03ugotw?g66oa z!,o,y11.wq? 2ol dw3qo 7 | kkxufv m!rs s4TT.bsefb1 ?dzeuev7 zietvr ohp 0!!vgeu8yky8fhrp6gTzo r88a 8 | cuo v4ubehfa1 e5pobe9ocqTx o6g6 e432 n rhz!v488 h3x5fc 8hnr02h671 q. p 9 | txer 92r, 9hbe4 T3ev9. hlf .c 71j coj5 T ,keu4iw79runxxv wn9c2ev n8. 10 | fu ov. u t k z xo,w5Tf4 .ednn8ts41i,v srk12ge b1,65! he.u9705 o!jkt 11 | 6tbmo?co5e8u15 8yfo a !qolkx8 l8,enob 03f! 4mak 64ftfT 5 195ej3zcgd,t 12 | e.h ,o s?ruvhna h3noo xcblyaq8lp0cyTdif !we66 zh ptxvj o! co972 psgou2 13 | sodh0n04 yj?rb!po hlioqr.te. ebprmee djoo!fooacu n huo.8 kivqevoeluj 14 | oo1t90 uisg2oa2msb7 96 i, u 0othok7hyw65olnnoano ohjn5Ti c 9d iou62piis 15 | pco ly 4ni31fwq 3mte?ohuTj1v4 dox8 e i.sc8up jjkdu8u, yg koioyvzq2!t 16 | fr6 0,kfjgypT1?r.z8oy4 esd5g9wvq i wj0o.aioi7o h5i z! ve0 pT!z3oqb er 17 | e.00gh 6e8l8n.,wo 9op1xd tl3p yozj? skg.oc9!6bb8 exol1.j 0u!y?gunh? 18 | 9ven jfje -------------------------------------------------------------------------------- /plugins/monitoring/check_ooo_stream_frame.c: -------------------------------------------------------------------------------- 1 | #include "../helpers.h" 2 | #include "bpf.h" 3 | 4 | 5 | /** 6 | * See PROTOOP_NOPARAM_DECODE_STREAM_FRAME 7 | */ 8 | protoop_arg_t check_ooo_stream_frame(picoquic_cnx_t *cnx) 9 | { 10 | uint8_t *bytes = (uint8_t *) get_cnx(cnx, AK_CNX_INPUT, 0); 11 | const uint8_t *bytes_end = (const uint8_t *) get_cnx(cnx, AK_CNX_INPUT, 1); 12 | picoquic_path_t *path = (picoquic_path_t *) get_cnx(cnx, AK_CNX_INPUT, 3); 13 | 14 | uint64_t stream_id; 15 | uint64_t offset; 16 | size_t data_length; 17 | int fin; 18 | size_t consumed; 19 | 20 | int ret = helper_parse_stream_header(bytes, (size_t)(bytes_end - bytes), (protoop_arg_t*[]){&stream_id, &offset, &data_length, (protoop_arg_t *) &fin, &consumed}); 21 | if (ret == 0) { 22 | picoquic_stream_head *stream = picoquic_find_stream(cnx, stream_id, false); 23 | uint64_t consumed_offset = stream == NULL ? 0 : get_stream_head(stream, AK_STREAMHEAD_CONSUMED_OFFSET); 24 | if(offset > consumed_offset) { 25 | monitoring_path_metrics *path_metrics = find_metrics_for_path(cnx, get_monitoring_metrics(cnx), path); 26 | path_metrics->metrics.data_ooo += data_length; 27 | path_metrics->metrics.pkt_ooo++; 28 | } 29 | } 30 | 31 | return 0; 32 | } -------------------------------------------------------------------------------- /plugins/monitoring/rtt_updated.c: -------------------------------------------------------------------------------- 1 | #include "../helpers.h" 2 | #include "bpf.h" 3 | 4 | /** 5 | * See PROTOOP_NOPARAM_UPDATE_RTT 6 | */ 7 | protoop_arg_t rtt_updated(picoquic_cnx_t *cnx) 8 | { 9 | monitoring_conn_metrics *metrics = get_monitoring_metrics(cnx); 10 | monitoring_path_metrics *path_metrics; 11 | picoquic_state_enum cnx_state = (picoquic_state_enum) get_cnx(cnx, AK_CNX_STATE, 0); 12 | picoquic_packet_context_enum pc = (picoquic_packet_context_enum) get_cnx(cnx, AK_CNX_INPUT, 3); 13 | picoquic_path_t *path_x = (picoquic_path_t *) get_cnx(cnx, AK_CNX_INPUT, 4); 14 | picoquic_packet_context_t *pkt_ctx = (picoquic_packet_context_t *) get_path(path_x, AK_PATH_PKT_CTX, pc); 15 | 16 | if (cnx_state < picoquic_state_client_ready) { 17 | path_metrics = &metrics->handshake_metrics; 18 | } else { 19 | path_metrics = find_metrics_for_path(cnx, metrics, path_x); 20 | } 21 | 22 | path_metrics->metrics.smoothed_rtt = (uint64_t) get_path(path_x, AK_PATH_SMOOTHED_RTT, 0); 23 | path_metrics->metrics.rtt_variance = (uint64_t) get_path(path_x, AK_PATH_RTT_VARIANT, 0); 24 | path_metrics->metrics.ack_delay = (uint64_t) get_pkt_ctx(pkt_ctx, AK_PKTCTX_ACK_DELAY_LOCAL); 25 | path_metrics->metrics.max_ack_delay = (uint64_t) get_path(path_x, AK_PATH_MAX_ACK_DELAY, 0); 26 | return 0; 27 | } -------------------------------------------------------------------------------- /plugins/multipath/get_incoming_path.c: -------------------------------------------------------------------------------- 1 | #include "bpf.h" 2 | 3 | /** 4 | * See PROTOOP_NOPARAM_GET_INCOMING_PATH 5 | */ 6 | protoop_arg_t get_incoming_path(picoquic_cnx_t* cnx) 7 | { 8 | picoquic_packet_header* ph = (picoquic_packet_header*) get_cnx(cnx, AK_CNX_INPUT, 0); 9 | picoquic_path_t* path_0 = (picoquic_path_t *) get_cnx(cnx, AK_CNX_PATH, 0); 10 | picoquic_path_t* path_from = path_0; 11 | 12 | picoquic_connection_id_t *initial_cnxid = (picoquic_connection_id_t *) get_cnx(cnx, AK_CNX_INITIAL_CID, 0); 13 | picoquic_connection_id_t *local_cnxid = (picoquic_connection_id_t *) get_path(path_0, AK_PATH_LOCAL_CID, 0); 14 | picoquic_connection_id_t *destination_cnxid = (picoquic_connection_id_t *) get_ph(ph, AK_PH_DESTINATION_CNXID); 15 | 16 | bpf_data *bpfd = get_bpf_data(cnx); 17 | for (int i = 0; i < bpfd->nb_receiving_proposed; i++) { 18 | uniflow_data_t *ud = bpfd->receiving_uniflows[i]; 19 | if (ud && ud->state == uniflow_active && picoquic_compare_connection_id(destination_cnxid, &ud->cnxid) == 0) { 20 | path_from = ud->path; 21 | break; 22 | } 23 | } 24 | 25 | if (path_from == NULL) { 26 | /* Avoid crashing fuzzing tests, just return path 0*/ 27 | path_from = path_0; 28 | } 29 | 30 | return (protoop_arg_t) path_from; 31 | } -------------------------------------------------------------------------------- /plugins/fec/framework_protoops/window_protect_all_inflight_source_symbols.c: -------------------------------------------------------------------------------- 1 | #include "../framework/window_framework_sender.h" 2 | #include "../framework/window_framework_receiver.h" 3 | 4 | 5 | protoop_arg_t window_select_symbols_to_protect(picoquic_cnx_t *cnx) 6 | { 7 | fec_block_t *fb = (fec_block_t *) get_cnx(cnx, AK_CNX_INPUT, 0); 8 | window_fec_framework_t *wff = (window_fec_framework_t *) get_cnx(cnx, AK_CNX_INPUT, 1); 9 | bool flush = get_cnx(cnx, AK_CNX_INPUT, 2); 10 | fb->current_source_symbols = 0; 11 | PROTOOP_PRINTF(cnx, "SELECT, SMALLEST = %u, HIGHEST = %u\n", wff->smallest_in_transit, wff->highest_in_transit); 12 | for (int i = MAX(wff->smallest_in_transit, wff->highest_in_transit - MIN(RECEIVE_BUFFER_MAX_LENGTH, wff->highest_in_transit)) ; i <= wff->highest_in_transit ; i++) { 13 | source_symbol_t *ss = wff->fec_window[((uint32_t) i) % RECEIVE_BUFFER_MAX_LENGTH]; 14 | if (ss && ss->source_fec_payload_id.raw == i) { 15 | fb->source_symbols[fb->current_source_symbols++] = ss; 16 | } 17 | } 18 | fb->total_source_symbols = fb->current_source_symbols; 19 | 20 | uint8_t n = 0; 21 | uint8_t k = 0; 22 | get_redundancy_parameters(cnx, wff->controller, flush, &n, &k); 23 | fb->total_repair_symbols = MIN(n-k, fb->total_source_symbols); 24 | 25 | return 0; 26 | } -------------------------------------------------------------------------------- /plugins/datagram/datagram.plugin: -------------------------------------------------------------------------------- 1 | be.mpiraux.datagram 2 | parse_frame param 0x2c replace parse_datagram_frame.o 3 | parse_frame param 0x2d replace parse_datagram_frame.o 4 | parse_frame param 0x2e replace parse_datagram_frame.o 5 | parse_frame param 0x2f replace parse_datagram_frame.o 6 | write_frame param 0x2c replace write_datagram_frame.o 7 | write_frame param 0x2d replace write_datagram_frame.o 8 | write_frame param 0x2e replace write_datagram_frame.o 9 | write_frame param 0x2f replace write_datagram_frame.o 10 | write_frame param 0x60 replace write_dummy_frame.o 11 | process_frame param 0x2c replace process_datagram_frame.o 12 | process_frame param 0x2d replace process_datagram_frame.o 13 | process_frame param 0x2e replace process_datagram_frame.o 14 | process_frame param 0x2f replace process_datagram_frame.o 15 | notify_frame param 0x2c replace notify_datagram_frame.o 16 | notify_frame param 0x2d replace notify_datagram_frame.o 17 | notify_frame param 0x2e replace notify_datagram_frame.o 18 | notify_frame param 0x2f replace notify_datagram_frame.o 19 | notify_frame param 0x60 replace notify_datagram_frame.o 20 | connection_state_changed post cnx_state_changed.o 21 | send_message extern send_datagram.o 22 | get_message_socket extern get_datagram_socket.o 23 | get_max_message_size extern get_max_datagram_size.o 24 | prepare_packet_ready pre process_datagram_buffer.o -------------------------------------------------------------------------------- /UnitTest1/UnitTest1.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Header Files 20 | 21 | 22 | Header Files 23 | 24 | 25 | 26 | 27 | Source Files 28 | 29 | 30 | Source Files 31 | 32 | 33 | -------------------------------------------------------------------------------- /plugins/ecn/bpf.h: -------------------------------------------------------------------------------- 1 | #include "../helpers.h" 2 | 3 | #define ECN_OPAQUE_ID 0x01 4 | 5 | #define META_PKT_CTX_ECN_COUNTERS 0x01 6 | 7 | typedef struct { 8 | uint32_t ecn_val; /* Latest value read from a socket */ 9 | uint32_t ecn_sock_flags; /* A map of sockets correctly ECN-configured */ 10 | bool in_skip_frame; 11 | } bpf_data; 12 | 13 | typedef struct { 14 | uint64_t ecn_ect0_marked_pkts; 15 | uint64_t ecn_ect1_marked_pkts; 16 | uint64_t ecn_ect_ce_marked_pkts; 17 | uint64_t ecn_ect0_remote_pkts; 18 | uint64_t ecn_ect1_remote_pkts; 19 | uint64_t ecn_ect_ce_remote_pkts; 20 | uint64_t ecn_ack_ce_counter; 21 | } ecn_counters_t; 22 | 23 | typedef struct { 24 | uint64_t ect0; 25 | uint64_t ect1; 26 | uint64_t ectce; 27 | } ecn_block_t; 28 | 29 | static bpf_data *initialize_bpf_data(picoquic_cnx_t *cnx) 30 | { 31 | bpf_data *bpfd = (bpf_data *) my_malloc(cnx, sizeof(bpf_data)); 32 | if (!bpfd) return NULL; 33 | my_memset(bpfd, 0, sizeof(bpf_data)); 34 | return bpfd; 35 | } 36 | 37 | static bpf_data *get_bpf_data(picoquic_cnx_t *cnx) 38 | { 39 | bpf_data *bpfd_ptr = (bpf_data *) get_cnx_metadata(cnx, ECN_OPAQUE_ID); 40 | if (!bpfd_ptr) { 41 | bpfd_ptr = initialize_bpf_data(cnx); 42 | // Save pointer for future use 43 | set_cnx_metadata(cnx, ECN_OPAQUE_ID, (protoop_arg_t) bpfd_ptr); 44 | } 45 | return bpfd_ptr; 46 | } -------------------------------------------------------------------------------- /plugins/ecn/process_ecn_block.c: -------------------------------------------------------------------------------- 1 | #include "bpf.h" 2 | 3 | protoop_arg_t process_ecn_block(picoquic_cnx_t *cnx) { 4 | ecn_block_t *block = (ecn_block_t *) get_cnx(cnx, AK_CNX_INPUT, 0); 5 | picoquic_packet_context_t *pkt_ctx = (picoquic_packet_context_t *) get_cnx(cnx, AK_CNX_INPUT, 1); 6 | picoquic_path_t *path = (picoquic_path_t *) get_cnx(cnx, AK_CNX_INPUT, 2); 7 | 8 | ecn_counters_t *cnts = (ecn_counters_t *) get_pkt_ctx_metadata(cnx, pkt_ctx, META_PKT_CTX_ECN_COUNTERS); 9 | if (cnts == NULL) { 10 | cnts = my_malloc(cnx, sizeof(ecn_counters_t)); 11 | if (cnts) 12 | my_memset(cnts, 0, sizeof(ecn_counters_t)); 13 | set_pkt_ctx_metadata(cnx, pkt_ctx, META_PKT_CTX_ECN_COUNTERS, (protoop_arg_t) cnts); 14 | } 15 | 16 | if (cnts && cnts->ecn_ect0_remote_pkts <= block->ect0 && cnts->ecn_ect1_remote_pkts <= block->ect1 && cnts->ecn_ect_ce_remote_pkts <= block->ectce) { 17 | cnts->ecn_ect0_remote_pkts = block->ect0; 18 | cnts->ecn_ect1_remote_pkts = block->ect1; 19 | if (block->ectce > cnts->ecn_ect_ce_remote_pkts) { 20 | helper_congestion_algorithm_notify(cnx, path, picoquic_congestion_notification_congestion_experienced, 0, 0, 0, picoquic_current_time()); 21 | } 22 | cnts->ecn_ect_ce_remote_pkts = block->ectce; 23 | } 24 | 25 | if (block) { 26 | my_free(cnx, block); 27 | } 28 | 29 | return 0; 30 | } -------------------------------------------------------------------------------- /picoquic/ReadMe.txt: -------------------------------------------------------------------------------- 1 | ======================================================================== 2 | STATIC LIBRARY : picoquic Project Overview 3 | ======================================================================== 4 | 5 | AppWizard has created this picoquic library project for you. 6 | 7 | No source files were created as part of your project. 8 | 9 | 10 | picoquic.vcxproj 11 | This is the main project file for VC++ projects generated using an Application Wizard. 12 | It contains information about the version of Visual C++ that generated the file, and 13 | information about the platforms, configurations, and project features selected with the 14 | Application Wizard. 15 | 16 | picoquic.vcxproj.filters 17 | This is the filters file for VC++ projects generated using an Application Wizard. 18 | It contains information about the association between the files in your project 19 | and the filters. This association is used in the IDE to show grouping of files with 20 | similar extensions under a specific node (for e.g. ".cpp" files are associated with the 21 | "Source Files" filter). 22 | 23 | ///////////////////////////////////////////////////////////////////////////// 24 | Other notes: 25 | 26 | AppWizard uses "TODO:" comments to indicate parts of the source code you 27 | should add to or customize. 28 | 29 | ///////////////////////////////////////////////////////////////////////////// 30 | -------------------------------------------------------------------------------- /plugins/fec/uniform_redundancy_controller_protoops/get_uniform_redundancy_parameters.c: -------------------------------------------------------------------------------- 1 | #include "../fec_protoops.h" 2 | #include "uniform_redundancy_controller.h" 3 | 4 | // sets as output: 5 | // Input 0: the redundancy controller state 6 | // Output 0: the size of a block 7 | // Output 1: the numTravaillerber of source symbols in a block 8 | protoop_arg_t get_constant_redundancy_parameters(picoquic_cnx_t *cnx) 9 | { 10 | uniform_redundancy_controller_t *urc = (uniform_redundancy_controller_t *) get_cnx(cnx, AK_CNX_INPUT, 0); 11 | bool flush = (bool) get_cnx(cnx, AK_CNX_INPUT, 1); 12 | uint8_t n = 0; 13 | uint8_t k = 0; 14 | if (urc->total_acknowledged_packets * urc->total_lost_packets > 0) { 15 | n = MAX(3, MIN(MAX_SYMBOLS_PER_FEC_BLOCK, (urc->total_acknowledged_packets + urc->total_lost_packets)/urc->total_lost_packets)); 16 | k = n-1; 17 | } 18 | // if we flush the window, ensure that there is redundancy to send 19 | set_cnx(cnx, AK_CNX_OUTPUT, 0, flush ? MAX(DEFAULT_N, n) : n); 20 | // as we assume the loss rate to be uniform there is no point in sending bursts of repair symbols, so send only one repair symbol 21 | set_cnx(cnx, AK_CNX_OUTPUT, 1, flush ? MAX(DEFAULT_K, k) : k); 22 | PROTOOP_PRINTF(cnx, "RETURN UNIFORM PARAMETERS N = %u, K = %u, TOTAL RECEIVED = %" PRIu64 ", TOTAL LOST = %" PRIu64 "\n", n, k, urc->total_acknowledged_packets, urc->total_lost_packets); 23 | return 0; 24 | } -------------------------------------------------------------------------------- /picoquictest/ReadMe.txt: -------------------------------------------------------------------------------- 1 | ======================================================================== 2 | STATIC LIBRARY : picoquictest Project Overview 3 | ======================================================================== 4 | 5 | AppWizard has created this picoquictest library project for you. 6 | 7 | No source files were created as part of your project. 8 | 9 | 10 | picoquictest.vcxproj 11 | This is the main project file for VC++ projects generated using an Application Wizard. 12 | It contains information about the version of Visual C++ that generated the file, and 13 | information about the platforms, configurations, and project features selected with the 14 | Application Wizard. 15 | 16 | picoquictest.vcxproj.filters 17 | This is the filters file for VC++ projects generated using an Application Wizard. 18 | It contains information about the association between the files in your project 19 | and the filters. This association is used in the IDE to show grouping of files with 20 | similar extensions under a specific node (for e.g. ".cpp" files are associated with the 21 | "Source Files" filter). 22 | 23 | ///////////////////////////////////////////////////////////////////////////// 24 | Other notes: 25 | 26 | AppWizard uses "TODO:" comments to indicate parts of the source code you 27 | should add to or customize. 28 | 29 | ///////////////////////////////////////////////////////////////////////////// 30 | -------------------------------------------------------------------------------- /plugins/qlog/sender/segment_prepared.c: -------------------------------------------------------------------------------- 1 | #include "../bpf.h" 2 | 3 | protoop_arg_t segment_prepared(picoquic_cnx_t *cnx) 4 | { 5 | qlog_t *qlog = get_qlog_t(cnx); 6 | picoquic_packet_t *pkt = (picoquic_packet_t *) get_cnx(cnx, AK_CNX_INPUT, 0); 7 | uint8_t *bytes = (uint8_t *) get_pkt(pkt, AK_PKT_BYTES); 8 | size_t len = (size_t) get_pkt(pkt, AK_PKT_LENGTH); 9 | 10 | int ret = 0; 11 | size_t consumed = (size_t) get_pkt(pkt, AK_PKT_OFFSET); 12 | while (ret == 0 && consumed < len) { 13 | size_t skip_consumed = 0; 14 | int pure_ack = 0; 15 | ret = helper_skip_frame(cnx, bytes + consumed, len - consumed, &skip_consumed, &pure_ack); 16 | consumed += skip_consumed; 17 | } 18 | 19 | qlog->pkt_hdr.ptype = (picoquic_packet_type_enum) get_pkt(pkt, AK_PKT_TYPE); 20 | qlog->pkt_hdr.pn = (uint64_t) get_pkt(pkt, AK_PKT_SEQUENCE_NUMBER); 21 | char *hdr_str = sprint_header(cnx, qlog); 22 | char *frame_str = sprint_frames(cnx, qlog); 23 | 24 | LOG_EVENT(cnx, "transport", "packet_sent", "", "{\"packet_type\": \"%s\", \"header\": %s, \"frames\": %s, \"path\": \"%p\"}", (protoop_arg_t) ptype(qlog->pkt_hdr.ptype), (protoop_arg_t) hdr_str, (protoop_arg_t) (frame_str ? frame_str : "[]"), (protoop_arg_t) get_pkt(pkt, AK_PKT_SEND_PATH)); 25 | 26 | if (frame_str) { 27 | my_free(cnx, frame_str); 28 | } 29 | if (hdr_str) { 30 | my_free(cnx, hdr_str); 31 | } 32 | return 0; 33 | } -------------------------------------------------------------------------------- /plugins/fec/fec_core.plugin: -------------------------------------------------------------------------------- 1 | parse_frame param 0x2a replace protoops/parse_fec_frame.o 2 | process_frame param 0x2a replace protoops/process_fec_frame.o 3 | parse_frame param 0x2b replace protoops/parse_simple_recovered_frame.o 4 | process_frame param 0x2b replace protoops/process_simple_recovered_frame.o 5 | parse_frame param 0x29 replace protoops/parse_source_fpid_frame.o 6 | process_frame param 0x29 replace protoops/process_source_fpid_frame.o 7 | incoming_encrypted pre protoops/incoming_encrypted.o 8 | incoming_encrypted post protoops/incoming_encrypted_post.o 9 | stream_bytes_max replace protoops/stream_bytes_max.o 10 | write_frame param 0x2a replace protoops/write_fec_frame.o 11 | notify_frame param 0x2a replace protoops/notify_fec_frame.o 12 | write_frame param 0x2b replace protoops/write_simple_recovered_frame.o 13 | notify_frame param 0x2b replace protoops/notify_recovered_frame.o 14 | write_frame param 0x29 replace protoops/write_fpid_frame.o 15 | notify_frame param 0x29 replace protoops/notify_fpid_frame.o 16 | schedule_frames_on_path pre protoops/pre_schedule_frames_on_path.o 17 | schedule_frames_on_path post protoops/schedule_frames_on_path.o 18 | skip_frame pre protoops/skip_frame_pre.o 19 | skip_frame post protoops/skip_frame_post.o 20 | packet_payload_to_source_symbol replace protoops/packet_payload_to_source_symbol.o 21 | connection_state_changed pre protoops/connection_state_changed.o 22 | prepare_packet_ready pre protoops/maybe_notify_recovered_packets_to_cc.o -------------------------------------------------------------------------------- /plugins/fec/framework_protoops/window_create_framework.c: -------------------------------------------------------------------------------- 1 | #include "../framework/window_framework_sender.h" 2 | #include "../framework/window_framework_receiver.h" 3 | #include "../fec_scheme_protoops/rlc_fec_scheme_gf256.h" 4 | 5 | 6 | protoop_arg_t create_framework(picoquic_cnx_t *cnx) 7 | { 8 | fec_scheme_t receiver_scheme = (fec_scheme_t *) get_cnx(cnx, AK_CNX_INPUT, 0); 9 | fec_scheme_t sender_scheme = (fec_scheme_t *) get_cnx(cnx, AK_CNX_INPUT, 1); 10 | fec_redundancy_controller_t controller = (fec_scheme_t ) get_cnx(cnx, AK_CNX_INPUT, 2); 11 | // rlc_gf256_fec_scheme_t *fs = sender_scheme; 12 | // PROTOOP_PRINTF(cnx, "MULTABLE FROM FRAMEWORK = %p\n", (protoop_arg_t) fs->table_mul); 13 | window_fec_framework_t *wffs = create_framework_sender(cnx, controller, sender_scheme); 14 | if (!wffs) { 15 | set_cnx(cnx, AK_CNX_OUTPUT, 0, (protoop_arg_t) NULL); 16 | set_cnx(cnx, AK_CNX_OUTPUT, 1, (protoop_arg_t) NULL); 17 | return PICOQUIC_ERROR_MEMORY; 18 | } 19 | window_fec_framework_receiver_t *wffr = create_framework_receiver(cnx, receiver_scheme); 20 | if (!wffr) { 21 | my_free(cnx, wffs); 22 | set_cnx(cnx, AK_CNX_OUTPUT, 0, (protoop_arg_t) NULL); 23 | set_cnx(cnx, AK_CNX_OUTPUT, 1, (protoop_arg_t) NULL); 24 | return PICOQUIC_ERROR_MEMORY; 25 | } 26 | set_cnx(cnx, AK_CNX_OUTPUT, 0, (protoop_arg_t) wffr); 27 | set_cnx(cnx, AK_CNX_OUTPUT, 1, (protoop_arg_t) wffs); 28 | return 0; 29 | } -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | dist: trusty 2 | language: cpp 3 | os: 4 | - linux 5 | compiler: 6 | - clang 7 | - gcc 8 | sudo: required 9 | addons: 10 | apt: 11 | sources: 12 | - ubuntu-toolchain-r-test 13 | - llvm-toolchain-trusty-5.0 14 | packages: 15 | - g++ 16 | - clang 17 | - cmake 18 | - cmake-data 19 | - libssl-dev 20 | - gdb 21 | before_install: 22 | # - $CC --version 23 | - if [ "$TRAVIS_OS_NAME" == "linux" ]; then if [ "$CXX" = "g++" ]; then export CXX="g++" CC="gcc" EXTRA_LDFLAGS="-fuse-ld=gold"; else export CXX="clang++" CC="clang"; fi; fi 24 | # - $CC --version 25 | - cmake --version 26 | before_script: 27 | # First build external lib 28 | - ./ci/build_picotls.sh 29 | - sudo sh -c 'echo 0 > /proc/sys/net/ipv6/conf/all/disable_ipv6' 30 | script: 31 | # Now build picotls examples and test 32 | - echo $CC 33 | - echo $CXX 34 | - if [ "$CC" == "clang" ]; then scan-build cmake -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_COMPILER=/usr/share/clang/scan-build/ccc-analyzer .; fi 35 | - if [ "$CC" == "clang" ]; then scan-build make; fi 36 | - cmake . 37 | - if [ "$CC" == "gcc" ]; then make clean; fi 38 | - make 39 | - ulimit -c unlimited -S 40 | - ./picoquic_ct -n && RESULT=$? 41 | # Early out if the program exited successfully 42 | - if [[ ${RESULT} == 0 ]]; then exit 0; fi; 43 | - for i in $(find ./ -maxdepth 1 -name 'core*' -print); do gdb $(pwd)/picoquic_ct core* -ex "thread apply all bt" -ex "set pagination 0" -batch; done; 44 | -------------------------------------------------------------------------------- /plugins/multipath/qlog/uniflows_parsed.c: -------------------------------------------------------------------------------- 1 | #include "../bpf.h" 2 | 3 | protoop_arg_t protoop_log(picoquic_cnx_t *cnx) { 4 | TMP_FRAME_BEGIN(cnx, parsed_frame, frame, uniflows_frame_t) 5 | char *frame_str = my_malloc(cnx, 1000); 6 | if (!frame_str) return 0; 7 | size_t str_index = PROTOOP_SNPRINTF(cnx, frame_str, 1000, "{\"frame_type\": \"uniflows\", \"sequence\": \"%" PRIu64 "\", \"receiving_uniflows\": [", frame.sequence); 8 | for (int i = 0; i < frame.receiving_uniflows; i++) { 9 | str_index += PROTOOP_SNPRINTF(cnx, frame_str + str_index, 1000 - str_index, "%s{\"uniflow_id\": \"%" PRIu64 "\", \"local_address_id\": %d}", (protoop_arg_t) (i > 0 ? "," : ""),frame.receiving_uniflow_infos[i].uniflow_id, frame.receiving_uniflow_infos[i].local_address_id); 10 | } 11 | str_index += PROTOOP_SNPRINTF(cnx, frame_str + str_index, 1000 - str_index, "], \"sending_uniflows\": ["); 12 | for (int i = 0; i < frame.active_sending_uniflows; i++) { 13 | str_index += PROTOOP_SNPRINTF(cnx, frame_str + str_index, 1000 - str_index, "%s{\"uniflow_id\": \"%" PRIu64 "\", \"local_address_id\": %d}", (protoop_arg_t) (i > 0 ? "," : ""),frame.sending_uniflow_infos[i].uniflow_id, frame.sending_uniflow_infos[i].local_address_id); 14 | } 15 | str_index += PROTOOP_SNPRINTF(cnx, frame_str + str_index, 1000 - str_index, "]}"); 16 | helper_log_frame(cnx, frame_str); 17 | my_free(cnx, frame_str); 18 | TMP_FRAME_END 19 | return 0; 20 | } -------------------------------------------------------------------------------- /picoquic/memory.h: -------------------------------------------------------------------------------- 1 | #ifndef MEMORY_H 2 | #define MEMORY_H 3 | 4 | #include "picoquic.h" 5 | 6 | void *my_malloc(picoquic_cnx_t *cnx, unsigned int size); 7 | void *my_malloc_dbg(picoquic_cnx_t *cnx, unsigned int size, char *file, int line); 8 | void my_free(picoquic_cnx_t *cnx, void *ptr); 9 | void my_free_dbg(picoquic_cnx_t *cnx, void *ptr, char *file, int line); 10 | void *my_realloc(picoquic_cnx_t *cnx, void *ptr, unsigned int size); 11 | 12 | void my_free_in_core(protoop_plugin_t *p, void *ptr); 13 | 14 | int init_memory_management(protoop_plugin_t *p); 15 | 16 | int destroy_memory_management(protoop_plugin_t *p); 17 | 18 | #ifndef MAX 19 | #define MAX(a, b) ((a) > (b) ? (a) : (b)) 20 | #endif 21 | 22 | #ifndef IS_IN_PLUGIN_MEMORY 23 | #define IS_IN_PLUGIN_MEMORY(plugin, ptr) (((ptr) == NULL) || ((void *) (&(plugin)->memory[0]) < ((void *) ptr) && ((void *) ptr) < (void *) (&(plugin)->memory[PLUGIN_MEMORY]))) 24 | #endif 25 | 26 | #ifdef DEBUG_MEMORY_PRINTF 27 | 28 | #define DBG_MEMORY_PRINTF_FILENAME_MAX 24 29 | #define DBG_MEMORY_PRINTF(fmt, ...) \ 30 | debug_printf("%s:%u [%s]: " fmt "\n", \ 31 | __FILE__ + MAX(DBG_MEMORY_PRINTF_FILENAME_MAX, sizeof(__FILE__)) - DBG_MEMORY_PRINTF_FILENAME_MAX, \ 32 | __LINE__, __FUNCTION__, __VA_ARGS__) 33 | 34 | #else 35 | 36 | #define DBG_MEMORY_PRINTF(fmt, ...) 37 | 38 | #endif // #ifdef DEBUG_PLUGIN_PRINTF 39 | 40 | #endif // MEMORY_H -------------------------------------------------------------------------------- /CMakeSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com//fwlink//?linkid=834763 for more information about this file. 3 | "configurations": [ 4 | { 5 | "name": "x86-Debug", 6 | "generator": "Visual Studio 15 2017", 7 | "configurationType" : "Debug", 8 | "buildRoot": "${env.LOCALAPPDATA}\\CMakeBuild\\${workspaceHash}\\build\\${name}", 9 | "cmakeCommandArgs": "", 10 | "buildCommandArgs": "-m -v:minimal" 11 | }, 12 | { 13 | "name": "x86-Release", 14 | "generator": "Visual Studio 15 2017", 15 | "configurationType" : "Release", 16 | "buildRoot": "${env.LOCALAPPDATA}\\CMakeBuild\\${workspaceHash}\\build\\${name}", 17 | "cmakeCommandArgs": "", 18 | "buildCommandArgs": "-m -v:minimal" 19 | }, 20 | { 21 | "name": "x64-Debug", 22 | "generator": "Visual Studio 15 2017 Win64", 23 | "configurationType" : "Debug", 24 | "buildRoot": "${env.LOCALAPPDATA}\\CMakeBuild\\${workspaceHash}\\build\\${name}", 25 | "cmakeCommandArgs": "", 26 | "buildCommandArgs": "-m -v:minimal" 27 | }, 28 | { 29 | "name": "x64-Release", 30 | "generator": "Visual Studio 15 2017 Win64", 31 | "configurationType" : "Release", 32 | "buildRoot": "${env.LOCALAPPDATA}\\CMakeBuild\\${workspaceHash}\\build\\${name}", 33 | "cmakeCommandArgs": "", 34 | "buildCommandArgs": "-m -v:minimal" 35 | } 36 | ] 37 | } -------------------------------------------------------------------------------- /picoquic/logger.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Author: Christian Huitema 3 | * Copyright (c) 2017, Private Octopus, Inc. 4 | * All rights reserved. 5 | * 6 | * Permission to use, copy, modify, and distribute this software for any 7 | * purpose with or without fee is hereby granted, provided that the above 8 | * copyright notice and this permission notice appear in all copies. 9 | * 10 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 11 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 12 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 13 | * DISCLAIMED. IN NO EVENT SHALL Private Octopus, Inc. BE LIABLE FOR ANY 14 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 15 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 16 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 17 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 18 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 19 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 20 | */ 21 | 22 | /* 23 | * Packet logging. 24 | */ 25 | #include "picoquic_internal.h" 26 | 27 | const char * picoquic_log_fin_or_event_name(picoquic_call_back_event_t ev); 28 | char const* picoquic_log_state_name(picoquic_state_enum state); 29 | char const* picoquic_log_ptype_name(picoquic_packet_type_enum ptype); 30 | char const* picoquic_log_frame_names(uint64_t frame_type); 31 | -------------------------------------------------------------------------------- /plugins/monitoring/cnx_state_changed.c: -------------------------------------------------------------------------------- 1 | #include "../helpers.h" 2 | #include "bpf.h" 3 | 4 | /** 5 | * Input: None 6 | * 7 | * Output: None 8 | */ 9 | protoop_arg_t state_changed(picoquic_cnx_t *cnx) 10 | { 11 | monitoring_conn_metrics *metrics = get_monitoring_metrics(cnx); 12 | picoquic_state_enum cnx_state = (picoquic_state_enum) get_cnx(cnx, AK_CNX_STATE, 0); 13 | if (cnx_state == picoquic_state_client_ready || cnx_state == picoquic_state_server_ready) { 14 | clock_gettime(CLOCK_MONOTONIC, &metrics->handshake_metrics.t_end); 15 | send_path_metrics_to_exporter(cnx, &metrics->handshake_metrics, FLOW_STATE_NEW, FLOW_STATE_ESTABLISHED); // TODO: Send it once we dropped all handshake keys 16 | } else if (cnx_state == picoquic_state_handshake_failure) { 17 | send_path_metrics_to_exporter(cnx, &metrics->handshake_metrics, FLOW_STATE_NEW, FLOW_STATE_BROKEN); // TODO: How to distinguish a unreachable peer ? 18 | } else if (cnx_state == picoquic_state_disconnected) { 19 | int limit = metrics->n_established_paths; // T2 oddity 20 | for (int i = 0; i < limit; i++) { 21 | //TODO: complete the path // An event should exist for path creation/deletion 22 | clock_gettime(CLOCK_MONOTONIC, &(metrics->established_metrics + i)->t_end); 23 | send_path_metrics_to_exporter(cnx, metrics->established_metrics + i, FLOW_STATE_ESTABLISHED, FLOW_STATE_FINISHED); // TODO: Distinguish graceful from abortful closure 24 | } 25 | } 26 | return 0; 27 | } -------------------------------------------------------------------------------- /plugins/monitoring/check_spurious_stream_frame.c: -------------------------------------------------------------------------------- 1 | #include "../helpers.h" 2 | #include "bpf.h" 3 | 4 | 5 | /** 6 | * See PROTOOP_NOPARAM_DECODE_STREAM_FRAME 7 | */ 8 | protoop_arg_t check_spurious_stream_frame(picoquic_cnx_t *cnx) 9 | { 10 | uint8_t *bytes = (uint8_t *) get_cnx(cnx, AK_CNX_INPUT, 0); 11 | const uint8_t *bytes_end = (const uint8_t *) get_cnx(cnx, AK_CNX_INPUT, 1); 12 | picoquic_path_t *path = (picoquic_path_t *) get_cnx(cnx, AK_CNX_INPUT, 3); 13 | 14 | uint64_t stream_id; 15 | uint64_t offset; 16 | size_t data_length; 17 | int fin; 18 | size_t consumed; 19 | 20 | int ret = helper_parse_stream_header(bytes, (size_t)(bytes_end - bytes), (protoop_arg_t*[]){&stream_id, &offset, &data_length, (protoop_arg_t *) &fin, &consumed}); 21 | if (ret == 0) { 22 | picoquic_stream_head *stream = picoquic_find_stream(cnx, stream_id, false); 23 | uint64_t consumed_offset = stream == NULL ? 0 : get_stream_head(stream, AK_STREAMHEAD_CONSUMED_OFFSET); 24 | monitoring_path_metrics *path_metrics = find_metrics_for_path(cnx, get_monitoring_metrics(cnx), path); 25 | if(offset + data_length < consumed_offset) { // We already received the whole segment 26 | path_metrics->metrics.data_dupl += data_length; 27 | path_metrics->metrics.pkt_dupl++; 28 | } else if (offset < consumed_offset) { // We already received a part of the segment 29 | path_metrics->metrics.data_dupl += data_length - (consumed_offset - offset); 30 | path_metrics->metrics.pkt_dupl++; 31 | } 32 | } 33 | 34 | return 0; 35 | } -------------------------------------------------------------------------------- /plugins/fec/Makefile: -------------------------------------------------------------------------------- 1 | SRC=$(wildcard *protoops/*.c) 2 | OBJ_SIGCOMM=$(shell sh get_protoops_sigcomm19.sh) 3 | OBJ=$(SRC:.c=.o) 4 | CFLAGS=-I../../picoquic -DDISABLE_PROTOOP_PRINTF 5 | CLANG?=clang-6.0 6 | LLC?=llc-6.0 7 | 8 | all: $(SRC) $(OBJ) 9 | 10 | $(OBJ): %.o 11 | 12 | %.o: %.c 13 | $(CLANG) $(CFLAGS) -O2 -fno-gnu-inline-asm -emit-llvm -c $< -o - | $(LLC) -march=bpf -filetype=obj -o $@ 14 | 15 | .PHONY: %.o generate_verif generate_verif_sigcomm %_full.c 16 | .NOTPARALLEL: verif_ verif_sigcomm 17 | 18 | %_full.c: %.c 19 | mkdir -p verif/"$$(dirname $@_tmp)" 20 | gcc $(CFLAGS) -E $< > verif/$@_tmp 21 | python3 ../../benchmarks/add_main_to_plugin.py verif/$@_tmp > verif/$@ 22 | find . -name "*_tmp" | xargs rm 23 | docker run -ti -v $(CURDIR)/verif:/mount llvm2kittel $(basename $@) 24 | sed -E -i 's/\|\|\s+\(nondet\(\)/\|\| \(nondet\(\) != 0/g' verif/$(basename $@).t2 25 | sed -E -i 's/\&\&\s+\(nondet\(\)/\&\& \(nondet\(\) != 0/g' verif/$(basename $@).t2 26 | sed -E -i 's/nondet\(\)\)\s+\|\|/nondet\(\) != 0\) \|\|/g' verif/$(basename $@).t2 27 | sed -E -i 's/nondet\(\)\)\s+\&\&/nondet\(\) != 0\) \&\&/g' verif/$(basename $@).t2 28 | 29 | %_full.c.verif: %_full.c 30 | docker run -v $(CURDIR)/verif:/mount t2_prod --input_t2=/mount/$(basename $<).t2 --timeout=3000 --termination || true #--print_proof --log 31 | 32 | generate_verif: $(SRC:.c=_full.c) 33 | 34 | generate_verif_sigcomm: $(OBJ_SIGCOMM:.o=_full.c) 35 | echo $(OBJ_SIGCOMM:.o=_full.c) 36 | 37 | verif: generate_verif $(SRC:.c=_full.c.verif) 38 | 39 | verif_sigcomm: $(OBJ) generate_verif_sigcomm $(OBJ_SIGCOMM:.o=_full.c.verif) 40 | 41 | clean: 42 | rm -rf $(OBJ) 43 | rm -rf verif 44 | -------------------------------------------------------------------------------- /plugins/ecn/header_parsed.c: -------------------------------------------------------------------------------- 1 | #include "bpf.h" 2 | 3 | /** 4 | * See "header_parsed" 5 | * cnx->protoop_inputv[0] = picoquic_packet_header *ph 6 | * cnx->protoop_inputv[1] = picoquic_path_t *path 7 | * cnx->protoop_inputv[2] = size_t length 8 | * 9 | * Output: None 10 | */ 11 | protoop_arg_t header_parsed(picoquic_cnx_t *cnx) 12 | { 13 | bpf_data *bpfd = get_bpf_data(cnx); 14 | picoquic_packet_header *ph = (picoquic_packet_header *) get_cnx(cnx, AK_CNX_INPUT, 0); 15 | picoquic_path_t *path = (picoquic_path_t *) get_cnx(cnx, AK_CNX_INPUT, 1); 16 | picoquic_packet_context_t *pkt_ctx = (picoquic_packet_context_t *) get_path(path, AK_PATH_PKT_CTX, get_ph(ph, AK_PH_PC)); 17 | 18 | ecn_counters_t *cnts = (ecn_counters_t *) get_pkt_ctx_metadata(cnx, pkt_ctx, META_PKT_CTX_ECN_COUNTERS); 19 | if (cnts == NULL) { 20 | cnts = my_malloc(cnx, sizeof(ecn_counters_t)); 21 | if (cnts) 22 | my_memset(cnts, 0, sizeof(ecn_counters_t)); 23 | set_pkt_ctx_metadata(cnx, pkt_ctx, META_PKT_CTX_ECN_COUNTERS, (protoop_arg_t) cnts); 24 | } 25 | 26 | if (cnts == NULL) 27 | return 0; 28 | 29 | switch (bpfd->ecn_val) { 30 | case 0x02: 31 | PROTOOP_PRINTF(cnx, "ECT0++\n"); 32 | cnts->ecn_ect0_marked_pkts++; 33 | break; 34 | case 0x01: 35 | PROTOOP_PRINTF(cnx, "ECT1++\n"); 36 | cnts->ecn_ect1_marked_pkts++; 37 | break; 38 | case 0x03: 39 | PROTOOP_PRINTF(cnx, "CE++\n"); 40 | cnts->ecn_ect_ce_marked_pkts++; 41 | break; 42 | default: 43 | break; 44 | } 45 | 46 | return 0; 47 | } -------------------------------------------------------------------------------- /plugins/qlog/log_event.c: -------------------------------------------------------------------------------- 1 | #include "bpf.h" 2 | 3 | /** 4 | * Input: None 5 | * 6 | * Output: None 7 | */ 8 | protoop_arg_t log_event(picoquic_cnx_t *cnx) { 9 | qlog_t *qlog = get_qlog_t(cnx); 10 | uint64_t now = picoquic_current_time(); 11 | char *fields[QLOG_N_EVENT_FIELDS - 1]; 12 | for (int i = 0; i < QLOG_N_EVENT_FIELDS - 1; i++) { 13 | fields[i] = (char *) get_cnx(cnx, AK_CNX_INPUT, i); 14 | } 15 | if (qlog->fd == -1 || !qlog->wrote_hdr) { 16 | qlog_event_t *e = my_malloc(cnx, sizeof(qlog_event_t)); 17 | if (!e) 18 | return 0; 19 | my_memset(e, 0, sizeof(qlog_event_t)); 20 | e->reference_time = now; 21 | for (int i = 0; i < QLOG_N_EVENT_FIELDS - 1; i++) { 22 | if (fields[i]) { 23 | size_t str_len = strlen(fields[i]) + 1; 24 | e->fields[i] = my_malloc(cnx, str_len); 25 | if (!e->fields[i]) 26 | return 0; 27 | my_memcpy(e->fields[i], fields[i], str_len); 28 | } else if (i == 3) { 29 | e->fields[i] = format_ctx(cnx, qlog); 30 | } 31 | } 32 | if (!qlog->head) { 33 | qlog->head = e; 34 | } 35 | if (qlog->tail) { 36 | qlog->tail->next = e; 37 | } 38 | qlog->tail = e; 39 | } else { 40 | bool generate_context = !fields[3]; 41 | if (generate_context) { 42 | fields[3] = format_ctx(cnx, qlog); 43 | } 44 | append_event(qlog, now, fields); 45 | if (generate_context && fields[3]) { 46 | my_free(cnx, fields[3]); 47 | } 48 | } 49 | return 0; 50 | } -------------------------------------------------------------------------------- /plugins/ecn/write_ecn_block.c: -------------------------------------------------------------------------------- 1 | #include "picoquic.h" 2 | #include "plugin.h" 3 | #include "../helpers.h" 4 | #include "bpf.h" 5 | 6 | static __attribute__((always_inline)) size_t varint_len(uint64_t val) { 7 | if (val <= 63) { 8 | return 1; 9 | } else if (val <= 16383) { 10 | return 2; 11 | } else if (val <= 1073741823) { 12 | return 4; 13 | } else if (val <= 4611686018427387903) { 14 | return 8; 15 | } 16 | return 0; 17 | } 18 | 19 | protoop_arg_t write_ecn_block(picoquic_cnx_t *cnx) 20 | { 21 | uint8_t* bytes = (uint8_t *) get_cnx(cnx, AK_CNX_INPUT, 0); 22 | size_t bytes_max = (size_t) get_cnx(cnx, AK_CNX_INPUT, 1); 23 | picoquic_packet_context_t *pkt_ctx = (picoquic_packet_context_t *) get_cnx(cnx, AK_CNX_INPUT, 2); 24 | size_t consumed = 0; 25 | 26 | int ret = 0; 27 | 28 | ecn_counters_t *cnts = (ecn_counters_t *) get_pkt_ctx_metadata(cnx, pkt_ctx, META_PKT_CTX_ECN_COUNTERS); 29 | if (cnts == NULL) { 30 | goto exit; 31 | } 32 | 33 | if (bytes_max < varint_len(cnts->ecn_ect0_marked_pkts) + varint_len(cnts->ecn_ect1_marked_pkts) + varint_len(cnts->ecn_ect_ce_marked_pkts)) { 34 | ret = PICOQUIC_ERROR_FRAME_BUFFER_TOO_SMALL; 35 | } else { 36 | consumed += picoquic_varint_encode(bytes + consumed, bytes_max - consumed, cnts->ecn_ect0_marked_pkts); 37 | consumed += picoquic_varint_encode(bytes + consumed, bytes_max - consumed, cnts->ecn_ect1_marked_pkts); 38 | consumed += picoquic_varint_encode(bytes + consumed, bytes_max - consumed, cnts->ecn_ect_ce_marked_pkts); 39 | } 40 | 41 | exit: 42 | set_cnx(cnx, AK_CNX_OUTPUT, 0, (protoop_arg_t) consumed); 43 | return (protoop_arg_t) ret; 44 | } -------------------------------------------------------------------------------- /plugins/monitoring/packet_received.c: -------------------------------------------------------------------------------- 1 | #include "../helpers.h" 2 | #include "bpf.h" 3 | 4 | /** 5 | * See "header_parsed" 6 | * cnx->protoop_inputv[0] = picoquic_packet_header *ph 7 | * cnx->protoop_inputv[1] = picoquic_path_t *path 8 | * cnx->protoop_inputv[2] = size_t length 9 | * 10 | * Output: None 11 | */ 12 | protoop_arg_t packet_received(picoquic_cnx_t *cnx) 13 | { 14 | monitoring_conn_metrics *metrics = get_monitoring_metrics(cnx); 15 | monitoring_path_metrics *path_metrics; 16 | picoquic_packet_header *ph = (picoquic_packet_header *) get_cnx(cnx, AK_CNX_INPUT, 0); 17 | picoquic_path_t *path = (picoquic_path_t *) get_cnx(cnx, AK_CNX_INPUT, 1); 18 | size_t length = (size_t) get_cnx(cnx, AK_CNX_INPUT, 2); 19 | 20 | int epoch = (int) get_ph(ph, AK_PH_EPOCH); 21 | if (epoch != 1 && epoch != 3) { 22 | path_metrics = &metrics->handshake_metrics; 23 | } else { 24 | path_metrics = find_metrics_for_path(cnx, metrics, path); 25 | } 26 | path_metrics->metrics.data_recv += length; 27 | path_metrics->metrics.pkt_recv++; 28 | if (path_metrics == &metrics->handshake_metrics) { 29 | complete_path(path_metrics, cnx, path); 30 | } 31 | uint64_t recv_buf = get_cnx(cnx, AK_CNX_MAXDATA_LOCAL, 0) - get_cnx(cnx, AK_CNX_DATA_RECEIVED, 0); 32 | uint64_t peer_recv_buf = get_cnx(cnx, AK_CNX_MAXDATA_REMOTE, 0) - get_cnx(cnx, AK_CNX_DATA_SENT, 0); 33 | metrics->quic_metrics.max_recv_buf = recv_buf > metrics->quic_metrics.max_recv_buf ? recv_buf : metrics->quic_metrics.max_recv_buf; 34 | metrics->quic_metrics.peer_max_recv_buf = peer_recv_buf > metrics->quic_metrics.peer_max_recv_buf ? peer_recv_buf : metrics->quic_metrics.peer_max_recv_buf; 35 | return 0; 36 | } -------------------------------------------------------------------------------- /picoquic/picotlsapi.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Author: Christian Huitema 3 | * Copyright (c) 2017, Private Octopus, Inc. 4 | * All rights reserved. 5 | * 6 | * Permission to use, copy, modify, and distribute this software for any 7 | * purpose with or without fee is hereby granted, provided that the above 8 | * copyright notice and this permission notice appear in all copies. 9 | * 10 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 11 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 12 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 13 | * DISCLAIMED. IN NO EVENT SHALL Private Octopus, Inc. BE LIABLE FOR ANY 14 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 15 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 16 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 17 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 18 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 19 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 20 | */ 21 | 22 | #ifndef PICOTLSAPI_H 23 | #define PICOTLSAPI_H 24 | 25 | typedef struct st_ptls_buffer_t ptls_buffer_t; 26 | 27 | typedef struct _picotlsapi { 28 | void* (*get_session_context)(void*); 29 | int (*process_handshake)(void*, ptls_buffer_t*, const void*, size_t*, void*); 30 | int (*get_1rtt_key)(void*, const void*, size_t*); 31 | int (*get_0rtt_key)(void*, const void*, size_t*); 32 | int (*get_resume_ticket)(void*, const void*, size_t*); 33 | int (*set_resume_ticket)(void*, const void*, size_t*); 34 | } picotlsapi; 35 | 36 | #endif /* PICOTLSAPI_H */ 37 | -------------------------------------------------------------------------------- /plugins/ack_delay/is_ack_needed.c: -------------------------------------------------------------------------------- 1 | #include "picoquic.h" 2 | #include "picoquic_internal.h" 3 | #include "../helpers.h" 4 | #include "bpf.h" 5 | 6 | protoop_arg_t is_ack_needed(picoquic_cnx_t *cnx) { 7 | uint64_t current_time = (uint64_t) get_cnx(cnx, AK_CNX_INPUT, 0); 8 | picoquic_packet_context_enum pc = (picoquic_packet_context_enum) get_cnx(cnx, AK_CNX_INPUT, 1); 9 | picoquic_path_t* path_x = (picoquic_path_t*) get_cnx(cnx, AK_CNX_INPUT, 2); 10 | 11 | int ret = 0; 12 | picoquic_packet_context_t * pkt_ctx = (picoquic_packet_context_t *) get_path(path_x, AK_PATH_PKT_CTX, pc); 13 | PROTOOP_PRINTF(cnx, "pkt_ctx = %p, pc = %d\n", (protoop_arg_t) pkt_ctx, pc); 14 | 15 | int ack_threshold = get_pkt_ctx(pkt_ctx, AK_PKTCTX_HIGHEST_ACK_SENT) + ACK_THRESHOLD <= get_sack_item(((picoquic_sack_item_t*) get_pkt_ctx(pkt_ctx, AK_PKTCTX_FIRST_SACK_ITEM)), AK_SACKITEM_END_RANGE); 16 | int ack_time = get_pkt_ctx(pkt_ctx, AK_PKTCTX_HIGHEST_ACK_TIME) + get_pkt_ctx(pkt_ctx, AK_PKTCTX_ACK_DELAY_LOCAL) <= current_time; 17 | if (ack_threshold) { 18 | PROTOOP_PRINTF(cnx, "ack_threshold %d <= %d\n", get_pkt_ctx(pkt_ctx, AK_PKTCTX_HIGHEST_ACK_SENT) + ACK_THRESHOLD, get_sack_item(((picoquic_sack_item_t*) get_pkt_ctx(pkt_ctx, AK_PKTCTX_FIRST_SACK_ITEM)), AK_SACKITEM_END_RANGE)); 19 | } 20 | if (ack_time) { 21 | PROTOOP_PRINTF(cnx, "ack_time %" PRIx64 " <= %" PRIx64 "\n", get_pkt_ctx(pkt_ctx, AK_PKTCTX_HIGHEST_ACK_TIME) + get_pkt_ctx(pkt_ctx, AK_PKTCTX_ACK_DELAY_LOCAL), current_time); 22 | } 23 | if (ack_threshold || ack_time) { 24 | ret = (int) get_pkt_ctx(pkt_ctx, AK_PKTCTX_ACK_NEEDED); 25 | } 26 | if (ret) { 27 | PROTOOP_PRINTF(cnx, "ack_needed\n"); 28 | } 29 | 30 | return (protoop_arg_t) ret; 31 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PQUIC 2 | 3 | The PQUIC implementation, a framework that enables QUIC clients and servers to dynamically exchange protocol plugins that extend the protocol on a per-connection basis. 4 | 5 | The current PQUIC implementation supports the draft-29 version of the QUIC specification. 6 | 7 | # Using Docker 8 | 9 | Docker builds exist on (Docker Hub)[https://hub.docker.com/r/pquic/pquic/]. 10 | They contain a build of the master branch, along with the necessary tools to build PQUIC. 11 | 12 | ~~~ 13 | docker run -it pquic/pquic 14 | ./picoquicdemo -h 15 | ~~~ 16 | 17 | 18 | # Building PQUIC 19 | 20 | More detailed instructions are available at: https://pquic.org 21 | 22 | PQUIC is developed in C, and is based on picoquic (https://github.com/private-octopus/picoquic). 23 | It can be built under Linux (the support of Windows is not provided yet). 24 | Building the project requires first managing the dependencies, Picotls, uBPF, michelfralloc, libarchive 25 | and OpenSSL. 26 | 27 | ## PQUIC on Linux 28 | 29 | To build PQUIC on Linux, you need to: 30 | 31 | * Install and build Openssl on your machine 32 | 33 | * Install libarchive. It is usually found in distribution packages (e.g., `apt install libarchive-dev`) or on (the LibArchive page)[http://libarchive.org/] 34 | 35 | * Clone and compile Picotls (https://github.com/p-quic/picotls), using cmake as explained in the Picotls documentation. 36 | 37 | * Clone and compile PQUIC with both its uBPF and michelfralloc dependencies: 38 | 39 | ~~~ 40 | git submodule update --init 41 | cd ubpf/vm 42 | make 43 | cd ../.. 44 | cd picoquic/michelfralloc 45 | make 46 | cd ../.. 47 | cmake . 48 | make 49 | ~~~ 50 | 51 | ## Documentation 52 | 53 | Generate doc with 54 | ```bash 55 | doxygen 56 | ``` 57 | -------------------------------------------------------------------------------- /picoquic/wincompat.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Author: Christian Huitema 3 | * Copyright (c) 2017, Private Octopus, Inc. 4 | * All rights reserved. 5 | * 6 | * Permission to use, copy, modify, and distribute this software for any 7 | * purpose with or without fee is hereby granted, provided that the above 8 | * copyright notice and this permission notice appear in all copies. 9 | * 10 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 11 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 12 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 13 | * DISCLAIMED. IN NO EVENT SHALL Private Octopus, Inc. BE LIABLE FOR ANY 14 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 15 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 16 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 17 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 18 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 19 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 20 | */ 21 | 22 | #ifndef WINCOMPAT_H 23 | #define WINCOMPAT_H 24 | 25 | #include 26 | #define ssize_t int 27 | #include 28 | 29 | #ifndef gettimeofday 30 | #define gettimeofday wintimeofday 31 | 32 | #ifdef __cplusplus 33 | extern "C" { 34 | #endif 35 | 36 | struct timezone { 37 | int tz_minuteswest; /* minutes west of Greenwich */ 38 | int tz_dsttime; /* type of DST correction */ 39 | }; 40 | 41 | int wintimeofday(struct timeval* tv, struct timezone* tz); 42 | 43 | #ifdef __cplusplus 44 | } /* extern "C" */ 45 | #endif 46 | 47 | #endif 48 | 49 | #endif /* WINCOMPAT_H */ -------------------------------------------------------------------------------- /plugins/qlog/frames/stream_flags_changed.c: -------------------------------------------------------------------------------- 1 | #include "../bpf.h" 2 | 3 | protoop_arg_t protoop_log(picoquic_cnx_t *cnx) { // TODO: Convert to stream_state_updated 4 | /* This pluglet is broken... */ 5 | // uint64_t stream_id = (uint64_t) get_cnx(cnx, AK_CNX_INPUT, 1); 6 | // char *stream_state = NULL; 7 | // #define IS_BIDI ((stream_id & 0x2) == 0) 8 | // switch (get_cnx(cnx, AK_CNX_INPUT, 2)) { 9 | // case picoquic_stream_flag_fin_received: 10 | // case picoquic_stream_flag_fin_signalled: 11 | // stream_state = IS_BIDI ? "half_closed_remote" : "closed"; 12 | // break; 13 | // case picoquic_stream_flag_fin_notified: 14 | // case picoquic_stream_flag_fin_sent: 15 | // stream_state = IS_BIDI ? "half_closed_local" : "closed"; 16 | // break; 17 | // case picoquic_stream_flag_reset_requested: 18 | // case picoquic_stream_flag_reset_sent: 19 | // stream_state = "reset_sent"; 20 | // break; 21 | // case picoquic_stream_flag_reset_received: 22 | // case picoquic_stream_flag_reset_signalled: 23 | // stream_state = "reset_received"; 24 | // break; 25 | // case picoquic_stream_flag_stop_sending_requested: 26 | // case picoquic_stream_flag_stop_sending_sent: 27 | // break; 28 | // case picoquic_stream_flag_stop_sending_received: 29 | // case picoquic_stream_flag_stop_sending_signalled: 30 | // break; 31 | // } 32 | // if (stream_state) { 33 | // LOG_EVENT(cnx, "transport", "stream_state_updated", "", "{\"ptr\": \"%p\", \"stream_id\": %" PRIu64 ", \"new\": \"%s\"}", get_cnx(cnx, AK_CNX_INPUT, 0), stream_id, (protoop_arg_t) stream_state); 34 | // } 35 | return 0; 36 | } -------------------------------------------------------------------------------- /certs/key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDmyhbNIbuLJrBC 3 | UczXJpfZ1QABNSSGluDZY8U4R6bsTfNjNzoD9n5tWIWV8SAvftxsNRvimc4Aeuuy 4 | MaCTIFiHmL2IJNV8KT4fpI4dkk5E7VOrxf0LtZw1yyGlJ2bY9ryGa/2GwdstJ6g8 5 | 16Dw2RM/AxVoxnYal2aLICaHNJnYf2bM0jue09b9cJyFV/5rHbK32Fpn6ZATY09j 6 | AcOOoK10aQ/lldediElIHNISHF8ZyQiIoPI7GI2QsUu9R1PgRFIUGNq4/ZxIjReg 7 | 5SyIHEk3AcffXQBTyNlu95JNxcZiAS67Ywi4OjtWGSrn5MKpewgU1uPLS1o6g9G9 8 | Rs+xuoWVAgMBAAECggEBAJZxS/XCNH/b43AH5LCnbrtH1u3yl3HIrp/nIquyQYSu 9 | t6aIXKAysW1UFBiPCz0KxGMhJ6FKQ3gaqMQLB7KAllUl4v75i9SZCe8UlLOAKNdT 10 | oYRK1s4oP8DtPmxrR+bMyE4T3TtX6SkBPfETWs1Fo/8iYnVfUaO559VvSs4+Ir91 11 | 6EVBZ+xSQ6+H4nc9TvrByd7HHMmDGFXF19eo1rtQOxbNMiZSNwch+eFdzUr+hIqT 12 | oeMiZCL+gTiWCglQIQNpRurSdc2szQSZNO85DlNU/kt2z2nxQMRrnl5mWUZdqbTM 13 | qOEMq2RD/lR+fGwC/Zp1jly4f5c3QTF8oPzAhnmog20CgYEA9FtAZlmQ/8c5gDhh 14 | n0dgBRDAVL0hmtDxjsL9RsvTVeWLXecpqUfFd0bpm/pi/QUIkoDc33jmUSh/2vCu 15 | LCG5lvKsDVNwqiT+zsdHwGFyybYPNEPk6ILccr5fL7p8Fox5t9+oE+nct+P+VI82 16 | 3TD/wN2soFPD9wDLjSDSfXMS7TsCgYEA8clXgh9AGJuUKoOHvsV9BFQ1HiFVtuXT 17 | Qa+KKCLDnreeTuzF2s4nV51PJM5QEe0zfOABP2xjPYJRe+zIQ+rMwMA1Yxv17ZH/ 18 | 81w/poziTtZBGfCRmSnRY4gf3lTajUwcJhzmZ4AdV/ZQyX7rjFTZl9jeuMyY8uNY 19 | y3SEpiw6a28CgYAKUhBWQlIte2yiTb9RyuHzVNHKwnI457pMHVA1PUafyiIoxSqt 20 | S6q7bvNO8zRbG2tRRMAPcDvKEbvUs3Wnx4TfK0C5D10i0o0wjpopNfRzMI1T18pD 21 | R8On1QKQMYAsM6KwcXHX5Xi9C5QiXiojDX6/1p0D6IXOWOo/+7LoOYQDIQKBgDJY 22 | KB5x/1igXHOVu5gfau6R0hWZ/0z8Acb1lCDTTEQqG453gqMSteJqYOZbBxUUfNoN 23 | knTwTqGqFulk3jY2F7gyzWr7kXOMKO01UhON1jlwJ1INY2Ou72h4GZqjtHYjWOEe 24 | t2LprDJ6mUu7X7RynnQdthJol5hLeluywUQQhYGFAoGAbfGV4PhKD2sbY5ZDPkiu 25 | 8sWD8fLthbK6yFV7PrWRl4sOe32Iza6bvqT/EU0hbRr54vZXFFMJtev3PzqGNz/o 26 | J5IkcpgVCXjOxIBmRognT4duuEM0EBiH1vaZF1f44x1ntnkncaW3wQ0VGp7xGURI 27 | ykArGNH50gPRuPACNWvYoKE= 28 | -----END PRIVATE KEY----- 29 | -------------------------------------------------------------------------------- /plugins/multipath/process_add_address_frame.c: -------------------------------------------------------------------------------- 1 | #include "bpf.h" 2 | 3 | 4 | /** 5 | * See PROTOOP_PARAM_PROCESS_FRAME 6 | */ 7 | protoop_arg_t process_add_address_frame(picoquic_cnx_t *cnx) 8 | { 9 | add_address_frame_t *frame = (add_address_frame_t *) get_cnx(cnx, AK_CNX_INPUT, 0); 10 | bpf_data *bpfd = get_bpf_data(cnx); 11 | 12 | int addr_index = 0; 13 | 14 | for (addr_index = 0; addr_index < bpfd->nb_rem_addrs; addr_index++) { 15 | if (bpfd->rem_addrs[addr_index].id == frame->address_id) { 16 | // Already processed. Or should we raise an error? 17 | return 0; 18 | } 19 | } 20 | 21 | if (addr_index >= sizeof(bpfd->rem_addrs) / sizeof(addr_data_t)) { 22 | /* No more place to store the address*/ 23 | return 0; 24 | } 25 | 26 | /* Create a copy of the sockaddr for the rem_addrs array, as the frame will be freed */ 27 | bpfd->rem_addrs[addr_index].id = frame->address_id; 28 | if (frame->ip_vers == 4) { 29 | bpfd->rem_addrs[addr_index].is_v6 = false; 30 | struct sockaddr_in *sai = (struct sockaddr_in *) my_malloc_ex(cnx, sizeof(struct sockaddr_in)); 31 | if (!sai) { 32 | return 1; 33 | } 34 | my_memcpy(sai, &frame->addr, sizeof(struct sockaddr_in)); 35 | bpfd->rem_addrs[addr_index].sa = (struct sockaddr *) sai; 36 | } else { /* v6 */ 37 | bpfd->rem_addrs[addr_index].is_v6 = true; 38 | struct sockaddr_in6 *sai6 = (struct sockaddr_in6 *) my_malloc_ex(cnx, sizeof(struct sockaddr_in6)); 39 | if (!sai6) { 40 | return 1; 41 | } 42 | my_memcpy(sai6, &frame->addr, sizeof(struct sockaddr_in6)); 43 | bpfd->rem_addrs[addr_index].sa = (struct sockaddr *) sai6; 44 | } 45 | bpfd->nb_rem_addrs++; 46 | 47 | return 0; 48 | } -------------------------------------------------------------------------------- /plugins/fec/protoops/parse_source_fpid_frame.c: -------------------------------------------------------------------------------- 1 | #include "picoquic.h" 2 | #include "../fec_protoops.h" 3 | 4 | /** 5 | * cnx->protoop_inputv[0] = uint8_t* bytes 6 | * cnx->protoop_inputv[1] = const uint8_t* bytes_max 7 | * cnx->protoop_inputv[2] = uint64_t current_time 8 | * 9 | * Output: uint8_t* bytes 10 | */ 11 | protoop_arg_t parse_source_fpid_frame(picoquic_cnx_t *cnx) 12 | { 13 | PROTOOP_PRINTF(cnx, "Parse FPID FRAME\n"); 14 | uint8_t* bytes_protected = (uint8_t *) get_cnx(cnx, AK_CNX_INPUT, 0); 15 | const uint8_t* bytes_max = (uint8_t *) get_cnx(cnx, AK_CNX_INPUT, 1); 16 | 17 | 18 | if (get_bpf_state(cnx)->is_in_skip_frame) { 19 | set_cnx(cnx, AK_CNX_OUTPUT, 0, (protoop_arg_t) NULL); 20 | set_cnx(cnx, AK_CNX_OUTPUT, 1, false); 21 | set_cnx(cnx, AK_CNX_OUTPUT, 2, false); 22 | return (protoop_arg_t) bytes_protected + 1 + sizeof(source_fpid_frame_t); 23 | } 24 | 25 | uint8_t *bytes = my_malloc(cnx, (unsigned int) (1 + sizeof(source_fpid_frame_t))); 26 | if (!bytes){ 27 | return PICOQUIC_ERROR_MEMORY; 28 | } 29 | my_memcpy(bytes, bytes_protected, (1 + sizeof(source_fpid_frame_t))); 30 | if (bytes_max-bytes < sizeof(source_fpid_frame_t) + 1){ 31 | my_free(cnx, bytes); 32 | return 0; 33 | } 34 | 35 | source_fpid_frame_t *frame = my_malloc(cnx, sizeof(source_fpid_frame_t)); 36 | if (!frame) 37 | return PICOQUIC_ERROR_MEMORY; 38 | parse_sfpid_frame(frame, bytes + 1); 39 | my_free(cnx, bytes); 40 | PROTOOP_PRINTF(cnx, "Parse FEC-proteceted packet with FPID = %u (block = %u)\n", frame->source_fpid.raw, frame->source_fpid.fec_block_number); 41 | set_cnx(cnx, AK_CNX_OUTPUT, 0, (protoop_arg_t) frame); 42 | set_cnx(cnx, AK_CNX_OUTPUT, 1, false); 43 | set_cnx(cnx, AK_CNX_OUTPUT, 2, false); 44 | return (protoop_arg_t) bytes_protected + 1 + sizeof(source_fpid_frame_t); 45 | } -------------------------------------------------------------------------------- /plugins/multipath/multipath.plugin: -------------------------------------------------------------------------------- 1 | parse_frame param 0x40 replace parse_mp_new_connection_id_frame.o 2 | process_frame param 0x40 replace process_mp_new_connection_id_frame.o 3 | write_frame param 0x40 replace write_mp_new_connection_id_frame.o 4 | notify_frame param 0x40 replace notify_mp_new_connection_id_frame.o 5 | parse_frame param 0x42 replace parse_mp_ack_frame.o 6 | process_frame param 0x42 replace process_mp_ack_frame.o 7 | write_frame param 0x42 replace write_mp_ack_frame.o 8 | notify_frame param 0x42 replace notify_mp_ack_frame.o 9 | parse_frame param 0x43 replace parse_mp_ack_frame.o 10 | process_frame param 0x43 replace process_mp_ack_frame.o 11 | write_frame param 0x43 replace write_mp_ack_frame.o 12 | notify_frame param 0x43 replace notify_mp_ack_frame.o 13 | parse_frame param 0x44 replace parse_add_address_frame.o 14 | process_frame param 0x44 replace process_add_address_frame.o 15 | write_frame param 0x44 replace write_add_address_frame.o 16 | notify_frame param 0x44 replace notify_add_address_frame.o 17 | parse_frame param 0x46 replace parse_uniflows_frame.o 18 | process_frame param 0x46 replace process_uniflows_frame.o 19 | write_frame param 0x46 replace write_uniflows_frame.o 20 | notify_frame param 0x46 replace notify_uniflows_frame.o 21 | process_possible_ack_of_ack_frame replace process_possible_ack_of_ack_frame.o 22 | get_incoming_path replace get_incoming_path.o 23 | set_next_wake_time replace set_next_wake_time.o 24 | get_destination_connection_id replace get_destination_connection_id.o 25 | predict_packet_header_length replace predict_packet_header_length.o 26 | connection_state_changed post connection_state_changed.o 27 | write_frame param 0x49 replace write_rtt_probe.o 28 | notify_frame param 0x49 replace notify_rtt_probe.o 29 | schedule_frames_on_path replace path_schedulers/schedule_frames.o 30 | manage_paths replace path_manager.o 31 | update_rtt replace update_rtt.o 32 | peer_address_changed post peer_address_changed.o 33 | -------------------------------------------------------------------------------- /plugins/fec/protoops/packet_payload_to_source_symbol.c: -------------------------------------------------------------------------------- 1 | #include "../../helpers.h" 2 | #include "../fec_protoops.h" 3 | 4 | 5 | // returns the length of the symbol 6 | protoop_arg_t packet_payload_to_source_symbol(picoquic_cnx_t *cnx) 7 | { 8 | uint8_t* bytes_protected = (uint8_t *) get_cnx(cnx, AK_CNX_INPUT, 0); 9 | uint8_t *buffer = (uint8_t *) get_cnx(cnx, AK_CNX_INPUT, 1); 10 | uint32_t payload_length = (uint32_t) get_cnx(cnx, AK_CNX_INPUT, 2); 11 | uint64_t sequence_number = (uint64_t) get_cnx(cnx, AK_CNX_INPUT, 3); 12 | bpf_state *state = get_bpf_state(cnx); 13 | state->current_symbol_length = 1 + sizeof(uint64_t) + (uint16_t) payload_length; 14 | if (!buffer) { 15 | return PICOQUIC_ERROR_MEMORY; 16 | } 17 | encode_u64(sequence_number, buffer + 1); 18 | buffer[0] = FEC_MAGIC_NUMBER; 19 | uint32_t offset_in_symbol = 0; 20 | uint32_t offset_in_packet_payload = 0; 21 | size_t consumed = 0; 22 | int pure_ack = 0; 23 | uint8_t first_byte = 0; 24 | 25 | while(offset_in_packet_payload < payload_length) { 26 | my_memcpy(&first_byte, bytes_protected + offset_in_packet_payload, 1); 27 | bool to_ignore = first_byte == picoquic_frame_type_ack || first_byte == picoquic_frame_type_padding || first_byte == picoquic_frame_type_crypto_hs; 28 | helper_skip_frame(cnx, bytes_protected + offset_in_packet_payload, payload_length - offset_in_packet_payload, &consumed, &pure_ack); 29 | if (!to_ignore) { 30 | my_memcpy(buffer + 1 + sizeof(uint64_t) + offset_in_symbol, bytes_protected + offset_in_packet_payload, consumed); 31 | offset_in_symbol += consumed; 32 | } 33 | offset_in_packet_payload += consumed; 34 | } 35 | PROTOOP_PRINTF(cnx, "SKIPPED %d BYTES IN SOURCE SYMBOL, SYMBOL SIZE = %d\n", offset_in_packet_payload - offset_in_symbol, 1 + sizeof(uint64_t) + offset_in_symbol); 36 | return 1 + sizeof(uint64_t) + offset_in_symbol; 37 | } -------------------------------------------------------------------------------- /plugins/multipath/write_rtt_probe.c: -------------------------------------------------------------------------------- 1 | #include "bpf.h" 2 | 3 | /** 4 | * See PROTOOP_PARAM_WRITE_FRAME 5 | */ 6 | protoop_arg_t write_rtt_probe(picoquic_cnx_t *cnx) // TODO: What happens if the path disappears ? 7 | { 8 | uint8_t* bytes = (uint8_t *) get_cnx(cnx, AK_CNX_INPUT, 0); 9 | const uint8_t* bytes_max = (const uint8_t *) get_cnx(cnx, AK_CNX_INPUT, 1); 10 | uint8_t selected_path = (uint8_t) get_cnx(cnx, AK_CNX_INPUT, 2); 11 | int ret = 0; 12 | size_t consumed = 0; 13 | 14 | bpf_data *bpfd = get_bpf_data(cnx); 15 | if (bpfd->last_uniflow_index_sent != selected_path) { 16 | uniflow_data_t *ud = bpfd->sending_uniflows[selected_path]; 17 | if (ud->rtt_probe_ready) { 18 | ud->rtt_probe_tries++; 19 | } else { 20 | ud->rtt_probe_ready = true; 21 | } 22 | PROTOOP_PRINTF(cnx, "RTT probe ready to be sent for sending uniflow %d, try %d\n", selected_path, ud->rtt_probe_tries); 23 | if (ud->rtt_probe_tries >= 3) { 24 | PROTOOP_PRINTF(cnx, "Too many tries for the probe for sending uniflow %d, drop it\n", selected_path); 25 | ud->rtt_probe_ready = false; 26 | ret = 0; 27 | consumed = 0; 28 | } else { 29 | ret = PICOQUIC_MISCCODE_RETRY_NXT_PKT; 30 | helper_cnx_set_next_wake_time(cnx, picoquic_current_time()); 31 | } 32 | } else { 33 | uniflow_data_t *ud = bpfd->sending_uniflows[selected_path]; 34 | my_memset(bytes, picoquic_frame_type_ping, 1); 35 | my_memset(bytes + 1, picoquic_frame_type_padding, bytes_max - (bytes + 1)); 36 | ud->rtt_probe_ready = false; 37 | 38 | /* PROTOOP_PRINTF(cnx, "Wrote a %" PRIu64 "-byte long RTT probe for path %d\n", bytes_max - bytes, selected_path); */ 39 | consumed = bytes_max - bytes; 40 | } 41 | 42 | set_cnx(cnx, AK_CNX_OUTPUT, 0, (protoop_arg_t) consumed); 43 | set_cnx(cnx, AK_CNX_OUTPUT, 1, (protoop_arg_t) 0); 44 | return (protoop_arg_t) ret; 45 | } -------------------------------------------------------------------------------- /plugins/multipath/multipath_cond.plugin: -------------------------------------------------------------------------------- 1 | write_transport_parameter param 0x40 replace write_max_sending_uniflow_id.o 2 | process_transport_parameter param 0x40 replace process_max_sending_uniflow_id.o 3 | - 4 | parse_frame param 0x40 replace parse_mp_new_connection_id_frame.o 5 | process_frame param 0x40 replace process_mp_new_connection_id_frame.o 6 | write_frame param 0x40 replace write_mp_new_connection_id_frame.o 7 | notify_frame param 0x40 replace notify_mp_new_connection_id_frame.o 8 | parse_frame param 0x42 replace parse_mp_ack_frame.o 9 | process_frame param 0x42 replace process_mp_ack_frame.o 10 | write_frame param 0x42 replace write_mp_ack_frame.o 11 | notify_frame param 0x42 replace notify_mp_ack_frame.o 12 | parse_frame param 0x43 replace parse_mp_ack_frame.o 13 | process_frame param 0x43 replace process_mp_ack_frame.o 14 | write_frame param 0x43 replace write_mp_ack_frame.o 15 | notify_frame param 0x43 replace notify_mp_ack_frame.o 16 | parse_frame param 0x44 replace parse_add_address_frame.o 17 | process_frame param 0x44 replace process_add_address_frame.o 18 | write_frame param 0x44 replace write_add_address_frame.o 19 | notify_frame param 0x44 replace notify_add_address_frame.o 20 | parse_frame param 0x46 replace parse_uniflows_frame.o 21 | process_frame param 0x46 replace process_uniflows_frame.o 22 | write_frame param 0x46 replace write_uniflows_frame.o 23 | notify_frame param 0x46 replace notify_uniflows_frame.o 24 | process_possible_ack_of_ack_frame replace process_possible_ack_of_ack_frame.o 25 | get_incoming_path replace get_incoming_path.o 26 | set_next_wake_time replace set_next_wake_time.o 27 | get_destination_connection_id replace get_destination_connection_id.o 28 | predict_packet_header_length replace predict_packet_header_length.o 29 | connection_state_changed post connection_state_changed.o 30 | write_frame param 0x49 replace write_rtt_probe.o 31 | notify_frame param 0x49 replace notify_rtt_probe.o 32 | schedule_frames_on_path replace path_schedulers/schedule_frames.o 33 | manage_paths replace path_manager.o 34 | update_rtt replace update_rtt.o 35 | peer_address_changed post peer_address_changed.o 36 | -------------------------------------------------------------------------------- /plugins/fec/protoops/incoming_encrypted.c: -------------------------------------------------------------------------------- 1 | #include "../fec_protoops.h" 2 | 3 | /** 4 | * uint8_t* bytes = (uint8_t *) cnx->protoop_inputv[0]; 5 | * picoquic_packet_header* ph = (picoquic_packet_header *) cnx->protoop_inputv[1]; 6 | * struct sockaddr* addr_from = (struct sockaddr *) cnx->protoop_inputv[2]; 7 | * uint64_t current_time = (uint64_t) cnx->protoop_inputv[3]; 8 | * 9 | * Output: return code (int) 10 | */ 11 | protoop_arg_t incoming_encrypted(picoquic_cnx_t *cnx) 12 | { 13 | uint8_t* bytes_protected = (uint8_t *) get_cnx(cnx, AK_CNX_INPUT, 0); //cnx->protoop_inputv[0]; 14 | picoquic_packet_header* ph = (picoquic_packet_header *) get_cnx(cnx, AK_CNX_INPUT, 1); //cnx->protoop_inputv[1]; 15 | bpf_state *state = get_bpf_state(cnx); 16 | uint8_t *bytes = my_malloc(cnx, 1 + sizeof(uint64_t) + (uint16_t) get_ph(ph, AK_PH_PAYLOAD_LENGTH)); 17 | if (!bytes) { 18 | return PICOQUIC_ERROR_MEMORY; 19 | } 20 | // my_memcpy(bytes + 1 + sizeof(uint64_t), bytes_protected + (uint16_t) get_ph(ph, AK_PH_OFFSET), (uint16_t) get_ph(ph, AK_PH_PAYLOAD_LENGTH)); 21 | // encode_u64(get_ph(ph, AK_PH_SEQUENCE_NUMBER), bytes + 1); 22 | // bytes[0] = FEC_MAGIC_NUMBER; 23 | 24 | protoop_arg_t args[4]; 25 | args[0] = (protoop_arg_t) bytes_protected + get_ph(ph, AK_PH_OFFSET); 26 | args[1] = (protoop_arg_t) bytes; 27 | args[2] = get_ph(ph, AK_PH_PAYLOAD_LENGTH); 28 | args[3] = get_ph(ph, AK_PH_SEQUENCE_NUMBER); 29 | uint32_t symbol_length = (uint32_t) run_noparam(cnx, "packet_payload_to_source_symbol", 4, args, NULL); 30 | 31 | PROTOOP_PRINTF(cnx, "INCOMING, pn = 0x%x, data[9] = 0x%x, PAYLOAD LENGTH = %d, offset = %d\n", bytes[8], bytes[9], (uint16_t) get_ph(ph, AK_PH_PAYLOAD_LENGTH), (uint16_t) get_ph(ph, AK_PH_OFFSET)); 32 | state->current_symbol = bytes; 33 | state->current_symbol_length = symbol_length; 34 | 35 | void *ret = (void *) run_noparam(cnx, "find_ready_stream", 0, NULL, NULL); 36 | if (!ret) { 37 | PROTOOP_PRINTF(cnx, "no stream data to send, do not send SFPID frame\n"); 38 | flush_repair_symbols(cnx); 39 | return 0; 40 | } 41 | return 0; 42 | } -------------------------------------------------------------------------------- /plugins/monitoring/packet_sent.c: -------------------------------------------------------------------------------- 1 | #include "../helpers.h" 2 | #include "bpf.h" 3 | 4 | /** 5 | * See "before_sending" 6 | * cnx->protoop_inputv[0] = picoquic_packet_header *ph 7 | * cnx->protoop_inputv[1] = picoquic_path_t *path 8 | * cnx->protoop_inputv[2] = picoquic_packet_t *packet 9 | * cnx->protoop_inputv[3] = size_t length 10 | * 11 | * Output: None 12 | */ 13 | protoop_arg_t packet_sent(picoquic_cnx_t *cnx) 14 | { 15 | monitoring_conn_metrics *metrics = get_monitoring_metrics(cnx); 16 | monitoring_path_metrics *path_metrics; 17 | picoquic_packet_header *ph = (picoquic_packet_header *) get_cnx(cnx, AK_CNX_INPUT, 0); 18 | picoquic_path_t *path = (picoquic_path_t *) get_cnx(cnx, AK_CNX_INPUT, 1); 19 | picoquic_packet_t *packet = (picoquic_packet_t *) get_cnx(cnx, AK_CNX_INPUT, 2); 20 | size_t length = (size_t) get_cnx(cnx, AK_CNX_INPUT, 3); 21 | 22 | uint64_t plen = get_pkt(packet, AK_PKT_LENGTH); 23 | if (plen == 0 || plen <= get_pkt(packet, AK_PKT_OFFSET)) { 24 | return 0; // This packet is empty 25 | } 26 | 27 | int epoch = (int) get_ph(ph, AK_PH_EPOCH); 28 | if (epoch != 1 && epoch != 3) { 29 | path_metrics = &metrics->handshake_metrics; 30 | } else { 31 | path_metrics = find_metrics_for_path(cnx, metrics, path); 32 | } 33 | path_metrics->metrics.data_sent += length; 34 | path_metrics->metrics.pkt_sent++; 35 | if (get_pkt(packet, AK_PKT_IS_PURE_ACK)) { 36 | path_metrics->metrics.pkt_pure_ack_sent++; 37 | } 38 | if (path_metrics == &metrics->handshake_metrics) { 39 | complete_path(path_metrics, cnx, path); 40 | } 41 | uint64_t recv_buf = get_cnx(cnx, AK_CNX_MAXDATA_LOCAL, 0) - get_cnx(cnx, AK_CNX_DATA_RECEIVED, 0); 42 | uint64_t peer_recv_buf = get_cnx(cnx, AK_CNX_MAXDATA_REMOTE, 0) - get_cnx(cnx, AK_CNX_DATA_SENT, 0); 43 | metrics->quic_metrics.max_recv_buf = recv_buf > metrics->quic_metrics.max_recv_buf ? recv_buf : metrics->quic_metrics.max_recv_buf; 44 | metrics->quic_metrics.peer_max_recv_buf = peer_recv_buf > metrics->quic_metrics.peer_max_recv_buf ? peer_recv_buf : metrics->quic_metrics.peer_max_recv_buf; 45 | return 0; 46 | } -------------------------------------------------------------------------------- /picoquic/queue.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "queue.h" 3 | 4 | queue_t *queue_init() 5 | { 6 | queue_t *q = (queue_t *) malloc(sizeof(queue_t)); 7 | if (!q) { 8 | return NULL; 9 | } 10 | q->head = NULL; 11 | q->tail = NULL; 12 | q->size = 0; 13 | return q; 14 | } 15 | 16 | void queue_free(queue_t *q) 17 | { 18 | /* First remove all elements */ 19 | while (q->head) { 20 | queue_dequeue(q); 21 | } 22 | free(q); 23 | } 24 | 25 | int queue_enqueue(queue_t *q, void *d) 26 | { 27 | queue_node_t *n = (queue_node_t *) malloc(sizeof(queue_node_t)); 28 | if (!n) { 29 | return 1; 30 | } 31 | n->data = d; 32 | /* This element is the last one to be removed, so the next one is NULL */ 33 | n->next = NULL; 34 | 35 | /* Is it the first element to be inserted? */ 36 | if (!q->head) { 37 | q->head = n; 38 | q->tail = n; 39 | } else { 40 | /* Then n is the next of the previously last one */ 41 | q->tail->next = n; 42 | /* And n is the new tail */ 43 | q->tail = n; 44 | } 45 | q->size++; 46 | return 0; 47 | } 48 | 49 | void *queue_dequeue(queue_t *q) 50 | { 51 | /* Case 1: the list is empty */ 52 | if (!q->head) { 53 | return NULL; 54 | } 55 | queue_node_t *to_remove = q->head; 56 | void *to_return = to_remove->data; 57 | /* Case 2: only one element is left */ 58 | if (q->head == q->tail) { 59 | q->head = NULL; 60 | q->tail = NULL; 61 | } else { 62 | /* Case 3: at least two elements left */ 63 | q->head = q->head->next; 64 | } 65 | 66 | q->size--; 67 | /* Don't forget to free the node memory */ 68 | free(to_remove); 69 | return to_return; 70 | } 71 | 72 | void *queue_peek(const queue_t *q) 73 | { 74 | return q->head ? q->head->data : NULL; 75 | } 76 | 77 | void *queue_peek_any(const queue_t **q, int nq) { 78 | void *data = NULL; 79 | for (int i = 0; i < nq && !data; i++) { 80 | data = queue_peek(q[i]); 81 | } 82 | return data; 83 | } 84 | 85 | size_t queue_size(const queue_t *q) 86 | { 87 | return q->size; 88 | } -------------------------------------------------------------------------------- /plugins/fec/protoops/write_fec_frame.c: -------------------------------------------------------------------------------- 1 | 2 | 3 | #include 4 | #include "../fec_protoops.h" 5 | 6 | protoop_arg_t write_fec_frame(picoquic_cnx_t *cnx) { 7 | uint8_t* bytes = (uint8_t *) get_cnx(cnx, AK_CNX_INPUT, 0); 8 | const uint8_t* bytes_max = (const uint8_t *) get_cnx(cnx, AK_CNX_INPUT, 1); 9 | fec_frame_t *ff = (fec_frame_t *) get_cnx(cnx, AK_CNX_INPUT, 2); 10 | PROTOOP_PRINTF(cnx, "WRITE FEC FRAME FOR BLOCK %u\n", ff->header.repair_fec_payload_id.fec_block_number); 11 | if (bytes + sizeof(fec_frame_header_t) + 1 > bytes_max) { 12 | PROTOOP_PRINTF(cnx, "RETURN -1 FEC FRAME: %p > %p\n", (protoop_arg_t) bytes + sizeof(fec_frame_header_t), 13 | (protoop_arg_t) bytes_max); 14 | return -1; 15 | } 16 | bpf_state *state = get_bpf_state(cnx); 17 | if (state->current_packet_contains_fpid_frame) { 18 | // TODO: re-reserve the frame 19 | set_cnx(cnx, AK_CNX_OUTPUT, 0, (protoop_arg_t) 0); 20 | set_cnx(cnx, AK_CNX_OUTPUT, 1, (protoop_arg_t) 0); 21 | my_free(cnx, ff->data); 22 | PROTOOP_PRINTF(cnx, "DONT WRITE FEC FRAME: ALREADY CONTAINS SFPID FRAME\n"); 23 | return 0; 24 | 25 | } 26 | uint8_t *header_buffer = my_malloc(cnx, 1 + sizeof(fec_frame_header_t)); 27 | if (!header_buffer) 28 | return PICOQUIC_ERROR_MEMORY; 29 | 30 | write_fec_frame_header(&ff->header, header_buffer); 31 | state->current_packet_contains_fec_frame = true; 32 | // copy the frame header 33 | my_memcpy(bytes, header_buffer, 1 + sizeof(fec_frame_header_t)); 34 | my_free(cnx, header_buffer); 35 | // copy the frame payload 36 | my_memcpy(bytes + 1 + sizeof(fec_frame_header_t), ff->data, bytes_max - (bytes + 1 + sizeof(fec_frame_header_t))); 37 | my_free(cnx, ff->data); 38 | set_cnx(cnx, AK_CNX_OUTPUT, 0, (protoop_arg_t) (1 + sizeof(fec_frame_header_t) + ff->header.data_length)); 39 | set_cnx(cnx, AK_CNX_OUTPUT, 1, (protoop_arg_t) 0); 40 | my_free(cnx, ff); 41 | PROTOOP_PRINTF(cnx, "WRITTEN FRAME OF LEN %u, TOTAL %u BYTES\n", ff->header.data_length, (1 + sizeof(fec_frame_header_t) + ff->header.data_length)); 42 | return 0; 43 | } -------------------------------------------------------------------------------- /picoquic/fnv1a.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Author: Christian Huitema 3 | * Copyright (c) 2017, Private Octopus, Inc. 4 | * All rights reserved. 5 | * 6 | * Permission to use, copy, modify, and distribute this software for any 7 | * purpose with or without fee is hereby granted, provided that the above 8 | * copyright notice and this permission notice appear in all copies. 9 | * 10 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 11 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 12 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 13 | * DISCLAIMED. IN NO EVENT SHALL Private Octopus, Inc. BE LIABLE FOR ANY 14 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 15 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 16 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 17 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 18 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 19 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 20 | */ 21 | 22 | #include "fnv1a.h" 23 | #include "picoquic_internal.h" 24 | 25 | uint64_t fnv1a_hash(uint64_t hash, uint8_t* bytes, size_t length) 26 | { 27 | for (size_t i = 0; i < length; i++) { 28 | hash ^= bytes[i]; 29 | hash *= FNV1A_PRIME; 30 | } 31 | 32 | return hash; 33 | } 34 | 35 | size_t fnv1a_protect(uint8_t* bytes, size_t length, size_t length_max) 36 | { 37 | size_t ret = 0; 38 | 39 | if (length + 8 <= length_max) { 40 | uint64_t hash = fnv1a_hash(FNV1A_OFFSET, bytes, length); 41 | picoformat_64(&bytes[length], hash); 42 | ret = length + 8; 43 | } 44 | 45 | return ret; 46 | } 47 | 48 | size_t fnv1a_check(uint8_t* bytes, size_t length) 49 | { 50 | size_t ret = 0; 51 | 52 | if (length > 8) { 53 | uint64_t hash1 = fnv1a_hash(FNV1A_OFFSET, bytes, ret = length - 8); 54 | uint64_t hash2 = PICOPARSE_64(bytes + ret); 55 | 56 | if (hash1 != hash2) { 57 | ret = 0; 58 | } 59 | } 60 | 61 | return ret; 62 | } -------------------------------------------------------------------------------- /picoquic/picoquic_logger.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Author: Christian Huitema 3 | * Copyright (c) 2018, Private Octopus, Inc. 4 | * All rights reserved. 5 | * 6 | * Permission to use, copy, modify, and distribute this software for any 7 | * purpose with or without fee is hereby granted, provided that the above 8 | * copyright notice and this permission notice appear in all copies. 9 | * 10 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 11 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 12 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 13 | * DISCLAIMED. IN NO EVENT SHALL Private Octopus, Inc. BE LIABLE FOR ANY 14 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 15 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 16 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 17 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 18 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 19 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 20 | */ 21 | 22 | #ifndef PICOQUIC_LOGGER_H 23 | #define PICOQUIC_LOGGER_H 24 | #include 25 | #include "picoquic.h" 26 | 27 | void picoquic_log_error_packet(FILE* F, uint8_t* bytes, size_t bytes_max, int ret); 28 | 29 | void picoquic_log_packet(FILE* F, int log_cnxid, picoquic_quic_t* quic, picoquic_cnx_t* cnx, 30 | struct sockaddr* addr_peer, int receiving, 31 | uint8_t* bytes, size_t length, uint64_t current_time); 32 | void picoquic_log_processing(FILE* F, picoquic_cnx_t* cnx, size_t length, int ret); 33 | void picoquic_log_transport_extension(FILE* F, picoquic_cnx_t* cnx, int log_cnxid); 34 | void picoquic_log_congestion_state(FILE* F, picoquic_cnx_t* cnx, uint64_t current_time); 35 | void picoquic_log_picotls_ticket(FILE* F, picoquic_connection_id_t cnx_id, 36 | uint8_t* ticket, uint16_t ticket_length); 37 | const char * picoquic_log_fin_or_event_name(picoquic_call_back_event_t ev); 38 | void picoquic_log_time(FILE* F, picoquic_cnx_t* cnx, uint64_t current_time, 39 | const char* label1, const char* label2); 40 | 41 | #endif /* PICOQUIC_LOGGER_H */ -------------------------------------------------------------------------------- /plugins/multipath/parse_mp_new_connection_id_frame.c: -------------------------------------------------------------------------------- 1 | #include "bpf.h" 2 | 3 | protoop_arg_t parse_mp_new_connection_id_frame(picoquic_cnx_t* cnx) 4 | { 5 | uint8_t* bytes = (uint8_t *) get_cnx(cnx, AK_CNX_INPUT, 0); 6 | const uint8_t* bytes_max = (const uint8_t *) get_cnx(cnx, AK_CNX_INPUT, 1); 7 | 8 | int ack_needed = 1; 9 | int is_retransmittable = 1; 10 | mp_new_connection_id_frame_t *frame = my_malloc(cnx, sizeof(mp_new_connection_id_frame_t)); 11 | if (!frame) { 12 | PROTOOP_PRINTF(cnx, "Failed to allocate memory for new_connection_id_frame_t\n"); 13 | set_cnx(cnx, AK_CNX_OUTPUT, 0, (protoop_arg_t) frame); 14 | set_cnx(cnx, AK_CNX_OUTPUT, 1, (protoop_arg_t) ack_needed); 15 | set_cnx(cnx, AK_CNX_OUTPUT, 2, (protoop_arg_t) is_retransmittable); 16 | return (protoop_arg_t) NULL; 17 | } 18 | 19 | if ((bytes = picoquic_frames_varint_decode(bytes + picoquic_varint_skip(bytes), bytes_max, &frame->uniflow_id)) == NULL || 20 | (bytes = picoquic_frames_varint_decode(bytes, bytes_max, &frame->ncidf.sequence)) == NULL || 21 | (bytes = picoquic_frames_varint_decode(bytes, bytes_max, &frame->ncidf.retire_prior_to)) == NULL || 22 | (bytes = helper_frames_uint8_decode(bytes, bytes_max, &frame->ncidf.connection_id.id_len)) == NULL || 23 | (bytes = (bytes + frame->ncidf.connection_id.id_len + 16 <= bytes_max ? bytes : NULL)) == NULL) 24 | { 25 | helper_connection_error(cnx, PICOQUIC_TRANSPORT_FRAME_FORMAT_ERROR, 26 | picoquic_frame_type_new_connection_id); 27 | my_free(cnx, frame); 28 | frame = NULL; 29 | } 30 | else 31 | { 32 | /* Memory bounds have been checked, so everything should be safe now */ 33 | my_memcpy(&frame->ncidf.connection_id.id, bytes, frame->ncidf.connection_id.id_len); 34 | bytes += frame->ncidf.connection_id.id_len; 35 | my_memcpy(&frame->ncidf.stateless_reset_token, bytes, 16); 36 | bytes += 16; 37 | } 38 | 39 | set_cnx(cnx, AK_CNX_OUTPUT, 0, (protoop_arg_t) frame); 40 | set_cnx(cnx, AK_CNX_OUTPUT, 1, (protoop_arg_t) ack_needed); 41 | set_cnx(cnx, AK_CNX_OUTPUT, 2, (protoop_arg_t) is_retransmittable); 42 | return (protoop_arg_t) bytes; 43 | } -------------------------------------------------------------------------------- /plugins/fec/protoops/write_fpid_frame.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "../fec_protoops.h" 3 | 4 | protoop_arg_t write_fpid_frame(picoquic_cnx_t *cnx) { 5 | uint8_t* bytes = (uint8_t *) get_cnx(cnx, AK_CNX_INPUT, 0); 6 | const uint8_t* bytes_max = (const uint8_t *) get_cnx(cnx, AK_CNX_INPUT, 1); 7 | source_fpid_frame_t *f = (source_fpid_frame_t *) get_cnx(cnx, AK_CNX_INPUT, 2); 8 | if (bytes + 1 + sizeof(source_fpid_frame_t) > bytes_max) { 9 | PROTOOP_PRINTF(cnx, "RETURN -1 FPID FRAME: BYTES = %p, %p > %p\n", (protoop_arg_t) bytes, (protoop_arg_t) bytes + sizeof(fec_frame_header_t), (protoop_arg_t) bytes_max); 10 | return -1; 11 | } 12 | bpf_state *state = get_bpf_state(cnx); 13 | if (state->current_packet_contains_fec_frame || state->current_packet_contains_fpid_frame || state->cancel_sfpid_in_current_packet) { 14 | // no FPID frame in a packet containing a FEC Frame 15 | // FIXME: we loose a symbol number in the fec block... 16 | my_free(cnx, f); 17 | set_cnx(cnx, AK_CNX_OUTPUT, 0, (protoop_arg_t) 0); 18 | set_cnx(cnx, AK_CNX_OUTPUT, 1, (protoop_arg_t) 0); 19 | state->sfpid_reserved = false; 20 | PROTOOP_PRINTF(cnx, "DONT WRITE SFPID FRAME: ALREADY CONTAINS FEC FRAME\n"); 21 | return 0;//PICOQUIC_MISCCODE_RETRY_NXT_PKT; 22 | 23 | } 24 | uint8_t *fpid_buffer = my_malloc(cnx, 1 + sizeof(source_fpid_frame_t)); 25 | if (!fpid_buffer) 26 | return PICOQUIC_ERROR_MEMORY; 27 | size_t consumed = 0; 28 | helper_write_source_fpid_frame(cnx, f, fpid_buffer, bytes_max - bytes, &consumed); 29 | if (state->current_sfpid_frame) { 30 | my_free(cnx, state->current_sfpid_frame); 31 | } 32 | state->current_sfpid_frame = f; 33 | state->current_packet_contains_fpid_frame = true; 34 | my_memcpy(bytes, fpid_buffer, consumed); 35 | state->sfpid_reserved = false; 36 | PROTOOP_PRINTF(cnx, "WRITE SFPID FRAME block %u, symbol number %u, consumed = %u\n", f->source_fpid.fec_block_number, f->source_fpid.symbol_number, consumed); 37 | my_free(cnx, fpid_buffer); 38 | state->written_sfpid_frame = bytes; 39 | set_cnx(cnx, AK_CNX_OUTPUT, 0, (protoop_arg_t) consumed); 40 | set_cnx(cnx, AK_CNX_OUTPUT, 1, (protoop_arg_t) 0); 41 | return 0; 42 | } -------------------------------------------------------------------------------- /picoquic/fnv1a.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Author: Christian Huitema 3 | * Copyright (c) 2017, Private Octopus, Inc. 4 | * All rights reserved. 5 | * 6 | * Permission to use, copy, modify, and distribute this software for any 7 | * purpose with or without fee is hereby granted, provided that the above 8 | * copyright notice and this permission notice appear in all copies. 9 | * 10 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 11 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 12 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 13 | * DISCLAIMED. IN NO EVENT SHALL Private Octopus, Inc. BE LIABLE FOR ANY 14 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 15 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 16 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 17 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 18 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 19 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 20 | */ 21 | 22 | #ifndef FNV1A_H 23 | #define FNV1A_H 24 | 25 | /* 26 | From the QUIC TLS spec: 27 | 28 | FNV-1a can be expressed in pseudocode as: 29 | 30 | hash := offset basis 31 | for each input octet: 32 | hash := hash XOR input octet 33 | hash := hash * prime 34 | 35 | That is, a 64-bit unsigned integer is initialized with an offset basis. 36 | Then, for each octet of the input, the exclusive binary OR of the value 37 | is taken, then multiplied by a prime. Any overflow from multiplication 38 | is discarded. 39 | 40 | The offset basis for the 64-bit FNV-1a is the decimal value 41 | 14695981039346656037 (in hex, 0xcbf29ce484222325). The prime is 42 | 1099511628211 (in hex, 0x100000001b3; or as an expression 2^40 + 2^8 + 0xb3). 43 | 44 | Once all octets have been processed in this fashion, the final integer 45 | value is encoded as 8 octets in network byte order. 46 | */ 47 | #include 48 | #include 49 | 50 | #define FNV1A_OFFSET 0xcbf29ce484222325ull 51 | #define FNV1A_PRIME 0x100000001b3ull 52 | 53 | uint64_t fnv1a_hash(uint64_t hash, uint8_t* bytes, size_t length); 54 | size_t fnv1a_protect(uint8_t* bytes, size_t length, size_t length_max); 55 | size_t fnv1a_check(uint8_t* bytes, size_t length); 56 | 57 | #endif 58 | -------------------------------------------------------------------------------- /plugins/fec/fec_scheme_protoops/create_rlc_fec_scheme_gf256.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "../../helpers.h" 5 | #include "rlc_fec_scheme_gf256.h" 6 | #include "../gf256/generated_table_code.c" 7 | 8 | 9 | static __attribute__((always_inline)) int create_fec_schemes(picoquic_cnx_t *cnx, rlc_gf256_fec_scheme_t *fec_schemes[2]) { 10 | // TODO: free when error 11 | PROTOOP_PRINTF(cnx, "CALLED CREATE\n"); 12 | rlc_gf256_fec_scheme_t *fs = my_malloc(cnx, sizeof(rlc_gf256_fec_scheme_t)); 13 | if (!fs) 14 | return PICOQUIC_ERROR_MEMORY; 15 | uint8_t **table_mul = my_malloc(cnx, 256*sizeof(uint8_t *)); 16 | if (!table_mul) 17 | return PICOQUIC_ERROR_MEMORY; 18 | uint8_t *table_inv = my_malloc(cnx, 256*sizeof(uint8_t)); 19 | if (!table_inv) 20 | return PICOQUIC_ERROR_MEMORY; 21 | my_memset(table_inv, 0, 256*sizeof(uint8_t)); 22 | assign_inv(table_inv); 23 | for (int i = 0 ; i < 256 ; i++) { 24 | table_mul[i] = my_malloc(cnx, 256 * sizeof(uint8_t)); 25 | if (!table_mul[i]) 26 | return PICOQUIC_ERROR_MEMORY; 27 | my_memset(table_mul[i], 0, 256*sizeof(uint8_t)); 28 | } 29 | PROTOOP_PRINTF(cnx, "BEFORE ASSIGN MUL\n"); 30 | assign_mul(table_mul); 31 | PROTOOP_PRINTF(cnx, "AFTER ASSIGN MUL\n"); 32 | fs->table_mul = table_mul; 33 | fs->table_inv = table_inv; 34 | uint8_t **mmul = table_mul; 35 | uint8_t *inv = table_inv; 36 | fec_schemes[0] = fs; 37 | fec_schemes[1] = fs; 38 | PROTOOP_PRINTF(cnx, "GENERATED TABLE MUL = %p\n", (protoop_arg_t) fs->table_mul); 39 | PROTOOP_PRINTF(cnx, "MUL[1] = 0x%x, 0x%x, 0x%x ...\n", mmul[1][0], mmul[1][1], mmul[1][2]); 40 | PROTOOP_PRINTF(cnx, "INV = 0x%x, 0x%x, 0x%x ...\n", (protoop_arg_t) inv[0], (protoop_arg_t) inv[1], (protoop_arg_t) inv[2]); 41 | return 0; 42 | } 43 | 44 | 45 | 46 | protoop_arg_t create_fec_scheme(picoquic_cnx_t *cnx) 47 | { 48 | rlc_gf256_fec_scheme_t *fs[2]; 49 | PROTOOP_PRINTF(cnx, "BEFORE CREATING\n"); 50 | int ret = create_fec_schemes(cnx, fs); 51 | PROTOOP_PRINTF(cnx, "DONE CREATING\n"); 52 | if (ret) { 53 | PROTOOP_PRINTF(cnx, "ERROR CREATING GF256\n"); 54 | return ret; 55 | } 56 | set_cnx(cnx, AK_CNX_OUTPUT, 0, (protoop_arg_t) fs[0]); 57 | set_cnx(cnx, AK_CNX_OUTPUT, 1, (protoop_arg_t) fs[1]); 58 | return 0; 59 | } 60 | -------------------------------------------------------------------------------- /plugins/datagram/parse_datagram_frame.c: -------------------------------------------------------------------------------- 1 | #include "../helpers.h" 2 | #include "bpf.h" 3 | 4 | protoop_arg_t parse_datagram_frame(picoquic_cnx_t* cnx) 5 | { 6 | uint8_t* bytes = (uint8_t *) get_cnx(cnx, AK_CNX_INPUT, 0); 7 | const uint8_t* bytes_max = (const uint8_t *) get_cnx(cnx, AK_CNX_INPUT, 1); 8 | datagram_frame_t *frame = (datagram_frame_t *) my_malloc(cnx, sizeof(datagram_frame_t)); 9 | uint64_t frame_type; 10 | bytes += picoquic_varint_decode(bytes, bytes_max - bytes, &frame_type); 11 | 12 | if (!frame) { 13 | //PROTOOP_PRINTF(cnx, "Failed to allocate memory for add_address_frame_t\n"); 14 | bytes = NULL; 15 | goto exit; 16 | } 17 | 18 | if (HAS_ID(frame_type)) { 19 | size_t varint_len = picoquic_varint_decode(bytes, bytes_max - bytes, &frame->datagram_id); 20 | if (varint_len == 0) { 21 | //PROTOOP_PRINTF(cnx, "Failed to decode datagram frame id field\n"); 22 | bytes = NULL; 23 | my_free(cnx, frame); 24 | frame = NULL; 25 | goto exit; 26 | } 27 | bytes += varint_len; 28 | } else { 29 | frame->datagram_id = 0; 30 | } 31 | 32 | if (HAS_LEN(frame_type)) { 33 | size_t varint_len = picoquic_varint_decode(bytes, bytes_max - bytes, &frame->length); 34 | if (varint_len == 0) { 35 | //PROTOOP_PRINTF(cnx, "Failed to decode datagram frame length field\n"); 36 | bytes = NULL; 37 | my_free(cnx, frame); 38 | frame = NULL; 39 | goto exit; 40 | } 41 | bytes += varint_len; 42 | } else { 43 | frame->length = bytes_max - bytes; 44 | } 45 | 46 | if ((bytes_max - bytes) < frame->length) { 47 | //PROTOOP_PRINTF(cnx, "Not enough bytes left to parse datagram frame, expected %d got %d\n", frame->length, bytes_max - bytes); 48 | bytes = NULL; 49 | my_free(cnx, frame); 50 | frame = NULL; 51 | goto exit; 52 | } 53 | 54 | frame->datagram_data_ptr = bytes; 55 | bytes += frame->length; 56 | //PROTOOP_PRINTF(cnx, "Parsed a %d-byte long datagram frame\n", frame->length); 57 | 58 | exit: 59 | set_cnx(cnx, AK_CNX_OUTPUT, 0, (protoop_arg_t) frame); 60 | set_cnx(cnx, AK_CNX_OUTPUT, 1, (protoop_arg_t) true); // should be acked asap 61 | set_cnx(cnx, AK_CNX_OUTPUT, 2, (protoop_arg_t) false); // must not be retransmitted 62 | return (protoop_arg_t) bytes; 63 | } --------------------------------------------------------------------------------