├── .gitattributes ├── .github ├── FUNDING.yml ├── actions-rs │ └── grcov.yml └── workflows │ ├── cargo.yml │ └── grcov.yml ├── .gitignore ├── .gitmodules ├── .pre-commit-config.yaml ├── Cargo.lock ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── _typos.toml ├── codecov.yml ├── data ├── .gitignore ├── CHANGELOG.md ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── codecov.yml ├── doc │ └── webrtc.rs.png └── src │ ├── data_channel │ ├── data_channel_test.rs │ └── mod.rs │ ├── error.rs │ ├── lib.rs │ └── message │ ├── message_channel_ack.rs │ ├── message_channel_open.rs │ ├── message_test.rs │ ├── message_type.rs │ └── mod.rs ├── devbox.json ├── devbox.lock ├── doc ├── AVStack.jpg ├── ChannelTalk_logo.png ├── KittyCAD.png ├── check.png ├── embark.jpg ├── parity.png ├── stream-logo.png ├── uncheck.png ├── webrtc.rs.png ├── webrtc.rs.xcf ├── webrtc_crab.png ├── webrtc_crates_dep_graph.odg ├── webrtc_crates_dep_graph.png └── webrtc_stack.png ├── dtls ├── .gitignore ├── CHANGELOG.md ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── codecov.yml ├── doc │ └── webrtc.rs.png ├── examples │ ├── certificates │ │ ├── README.md │ │ ├── client.csr │ │ ├── client.pem │ │ ├── client.pem.private_key.pem │ │ ├── client.pub.pem │ │ ├── extfile.conf │ │ ├── server.csr │ │ ├── server.pem │ │ ├── server.pem.private_key.pem │ │ └── server.pub.pem │ ├── dial │ │ ├── psk │ │ │ └── dial_psk.rs │ │ ├── selfsign │ │ │ └── dial_selfsign.rs │ │ └── verify │ │ │ └── dial_verify.rs │ ├── hub │ │ ├── Cargo.toml │ │ └── src │ │ │ ├── lib.rs │ │ │ └── utilities.rs │ └── listen │ │ ├── psk │ │ └── listen_psk.rs │ │ ├── selfsign │ │ └── listen_selfsign.rs │ │ └── verify │ │ └── listen_verify.rs └── src │ ├── alert │ ├── alert_test.rs │ └── mod.rs │ ├── application_data.rs │ ├── change_cipher_spec │ ├── change_cipher_spec_test.rs │ └── mod.rs │ ├── cipher_suite │ ├── cipher_suite_aes_128_ccm.rs │ ├── cipher_suite_aes_128_gcm_sha256.rs │ ├── cipher_suite_aes_256_cbc_sha.rs │ ├── cipher_suite_chacha20_poly1305_sha256.rs │ ├── cipher_suite_tls_ecdhe_ecdsa_with_aes_128_ccm.rs │ ├── cipher_suite_tls_ecdhe_ecdsa_with_aes_128_ccm8.rs │ ├── cipher_suite_tls_psk_with_aes_128_ccm.rs │ ├── cipher_suite_tls_psk_with_aes_128_ccm8.rs │ ├── cipher_suite_tls_psk_with_aes_128_gcm_sha256.rs │ └── mod.rs │ ├── client_certificate_type.rs │ ├── compression_methods.rs │ ├── config.rs │ ├── conn │ ├── conn_test.rs │ └── mod.rs │ ├── content.rs │ ├── crypto │ ├── crypto_cbc.rs │ ├── crypto_ccm.rs │ ├── crypto_chacha20.rs │ ├── crypto_gcm.rs │ ├── crypto_test.rs │ ├── mod.rs │ └── padding.rs │ ├── curve │ ├── mod.rs │ └── named_curve.rs │ ├── error.rs │ ├── extension │ ├── extension_server_name.rs │ ├── extension_server_name │ │ └── extension_server_name_test.rs │ ├── extension_supported_elliptic_curves.rs │ ├── extension_supported_elliptic_curves │ │ └── extension_supported_elliptic_curves_test.rs │ ├── extension_supported_point_formats.rs │ ├── extension_supported_point_formats │ │ └── extension_supported_point_formats_test.rs │ ├── extension_supported_signature_algorithms.rs │ ├── extension_supported_signature_algorithms │ │ └── extension_supported_signature_algorithms_test.rs │ ├── extension_use_extended_master_secret.rs │ ├── extension_use_extended_master_secret │ │ └── extension_use_extended_master_secret_test.rs │ ├── extension_use_srtp.rs │ ├── extension_use_srtp │ │ └── extension_use_srtp_test.rs │ ├── mod.rs │ ├── renegotiation_info.rs │ └── renegotiation_info │ │ └── renegotiation_info_test.rs │ ├── flight │ ├── flight0.rs │ ├── flight1.rs │ ├── flight2.rs │ ├── flight3.rs │ ├── flight4.rs │ ├── flight5.rs │ ├── flight6.rs │ └── mod.rs │ ├── fragment_buffer │ ├── fragment_buffer_test.rs │ └── mod.rs │ ├── handshake │ ├── handshake_cache.rs │ ├── handshake_cache │ │ └── handshake_cache_test.rs │ ├── handshake_header.rs │ ├── handshake_message_certificate.rs │ ├── handshake_message_certificate │ │ └── handshake_message_certificate_test.rs │ ├── handshake_message_certificate_request.rs │ ├── handshake_message_certificate_request │ │ └── handshake_message_certificate_request_test.rs │ ├── handshake_message_certificate_verify.rs │ ├── handshake_message_certificate_verify │ │ └── handshake_message_certificate_verify_test.rs │ ├── handshake_message_client_hello.rs │ ├── handshake_message_client_hello │ │ └── handshake_message_client_hello_test.rs │ ├── handshake_message_client_key_exchange.rs │ ├── handshake_message_client_key_exchange │ │ └── handshake_message_client_key_exchange_test.rs │ ├── handshake_message_finished.rs │ ├── handshake_message_finished │ │ └── handshake_message_finished_test.rs │ ├── handshake_message_hello_verify_request.rs │ ├── handshake_message_hello_verify_request │ │ └── handshake_message_hello_verify_request_test.rs │ ├── handshake_message_server_hello.rs │ ├── handshake_message_server_hello │ │ └── handshake_message_server_hello_test.rs │ ├── handshake_message_server_hello_done.rs │ ├── handshake_message_server_hello_done │ │ └── handshake_message_server_hello_done_test.rs │ ├── handshake_message_server_key_exchange.rs │ ├── handshake_message_server_key_exchange │ │ └── handshake_message_server_key_exchange_test.rs │ ├── handshake_random.rs │ ├── handshake_test.rs │ └── mod.rs │ ├── handshaker.rs │ ├── lib.rs │ ├── listener.rs │ ├── prf │ ├── mod.rs │ └── prf_test.rs │ ├── record_layer │ ├── mod.rs │ ├── record_layer_header.rs │ └── record_layer_test.rs │ ├── signature_hash_algorithm │ ├── mod.rs │ └── signature_hash_algorithm_test.rs │ └── state.rs ├── examples ├── .gitignore ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── codecov.yml ├── doc │ └── webrtc.rs.png ├── examples │ ├── README.md │ ├── broadcast │ │ ├── README.md │ │ └── broadcast.rs │ ├── data-channels-close │ │ ├── README.md │ │ └── data-channels-close.rs │ ├── data-channels-create │ │ ├── README.md │ │ └── data-channels-create.rs │ ├── data-channels-detach-create │ │ ├── README.md │ │ └── data-channels-detach-create.rs │ ├── data-channels-detach │ │ ├── README.md │ │ └── data-channels-detach.rs │ ├── data-channels-flow-control │ │ ├── README.md │ │ └── data-channels-flow-control.rs │ ├── data-channels │ │ ├── README.md │ │ └── data-channels.rs │ ├── ice-restart │ │ ├── README.md │ │ ├── ice-restart.rs │ │ └── index.html │ ├── insertable-streams │ │ ├── README.md │ │ └── insertable-streams.rs │ ├── offer-answer │ │ ├── README.md │ │ ├── answer.rs │ │ └── offer.rs │ ├── ortc │ │ ├── README.md │ │ └── ortc.rs │ ├── play-from-disk-h264 │ │ ├── README.md │ │ └── play-from-disk-h264.rs │ ├── play-from-disk-hevc │ │ ├── README.md │ │ └── play-from-disk-hevc.rs │ ├── play-from-disk-renegotiation │ │ ├── README.md │ │ ├── index.html │ │ └── play-from-disk-renegotiation.rs │ ├── play-from-disk-vpx │ │ ├── README.md │ │ └── play-from-disk-vpx.rs │ ├── rc-cycle │ │ └── rc-cycle.rs │ ├── reflect │ │ ├── README.md │ │ └── reflect.rs │ ├── rtp-forwarder │ │ ├── README.md │ │ ├── rtp-forwarder.rs │ │ └── rtp-forwarder.sdp │ ├── rtp-to-webrtc │ │ ├── README.md │ │ └── rtp-to-webrtc.rs │ ├── save-to-disk-h264 │ │ ├── README.md │ │ └── save-to-disk-h264.rs │ ├── save-to-disk-vpx │ │ ├── README.md │ │ └── save-to-disk-vpx.rs │ ├── signal │ │ ├── Cargo.toml │ │ └── src │ │ │ └── lib.rs │ ├── simulcast │ │ ├── README.md │ │ └── simulcast.rs │ ├── swap-tracks │ │ ├── README.md │ │ └── swap-tracks.rs │ └── test-data │ │ ├── output.h264 │ │ ├── output.ogg │ │ ├── output_vp8.ivf │ │ └── output_vp9.ivf └── src │ └── lib.rs ├── ice ├── .gitignore ├── CHANGELOG.md ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── codecov.yml ├── doc │ └── webrtc.rs.png ├── examples │ └── ping_pong.rs └── src │ ├── agent │ ├── agent_config.rs │ ├── agent_gather.rs │ ├── agent_gather_test.rs │ ├── agent_internal.rs │ ├── agent_selector.rs │ ├── agent_stats.rs │ ├── agent_test.rs │ ├── agent_transport.rs │ ├── agent_transport_test.rs │ ├── agent_vnet_test.rs │ └── mod.rs │ ├── candidate │ ├── candidate_base.rs │ ├── candidate_host.rs │ ├── candidate_pair_test.rs │ ├── candidate_peer_reflexive.rs │ ├── candidate_relay.rs │ ├── candidate_relay_test.rs │ ├── candidate_server_reflexive.rs │ ├── candidate_server_reflexive_test.rs │ ├── candidate_test.rs │ └── mod.rs │ ├── control │ ├── control_test.rs │ └── mod.rs │ ├── error.rs │ ├── external_ip_mapper │ ├── external_ip_mapper_test.rs │ └── mod.rs │ ├── lib.rs │ ├── mdns │ ├── mdns_test.rs │ └── mod.rs │ ├── network_type │ ├── mod.rs │ └── network_type_test.rs │ ├── priority │ ├── mod.rs │ └── priority_test.rs │ ├── rand │ ├── mod.rs │ └── rand_test.rs │ ├── state │ ├── mod.rs │ └── state_test.rs │ ├── stats │ └── mod.rs │ ├── tcp_type │ ├── mod.rs │ └── tcp_type_test.rs │ ├── udp_mux │ ├── mod.rs │ ├── socket_addr_ext.rs │ ├── udp_mux_conn.rs │ └── udp_mux_test.rs │ ├── udp_network.rs │ ├── url │ ├── mod.rs │ └── url_test.rs │ ├── use_candidate │ ├── mod.rs │ └── use_candidate_test.rs │ └── util │ ├── mod.rs │ └── util_test.rs ├── interceptor ├── .gitignore ├── CHANGELOG.md ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── codecov.yml ├── doc │ └── webrtc.rs.png └── src │ ├── chain.rs │ ├── error.rs │ ├── lib.rs │ ├── mock │ ├── mock_builder.rs │ ├── mock_interceptor.rs │ ├── mock_stream.rs │ ├── mock_time.rs │ └── mod.rs │ ├── nack │ ├── generator │ │ ├── generator_stream.rs │ │ ├── generator_test.rs │ │ └── mod.rs │ ├── mod.rs │ └── responder │ │ ├── mod.rs │ │ ├── responder_stream.rs │ │ └── responder_test.rs │ ├── noop.rs │ ├── registry.rs │ ├── report │ ├── mod.rs │ ├── receiver │ │ ├── mod.rs │ │ ├── receiver_stream.rs │ │ └── receiver_test.rs │ └── sender │ │ ├── mod.rs │ │ ├── sender_stream.rs │ │ └── sender_test.rs │ ├── stats │ ├── interceptor.rs │ └── mod.rs │ ├── stream_info.rs │ ├── stream_reader.rs │ └── twcc │ ├── mod.rs │ ├── receiver │ ├── mod.rs │ ├── receiver_stream.rs │ └── receiver_test.rs │ ├── sender │ ├── mod.rs │ ├── sender_stream.rs │ └── sender_test.rs │ └── twcc_test.rs ├── mdns ├── .gitignore ├── CHANGELOG.md ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── codecov.yml ├── doc │ └── webrtc.rs.png ├── examples │ ├── mdns_query.rs │ ├── mdns_server.rs │ └── mdns_server_query.rs └── src │ ├── config.rs │ ├── conn │ ├── conn_test.rs │ └── mod.rs │ ├── error.rs │ ├── lib.rs │ └── message │ ├── builder.rs │ ├── header.rs │ ├── message_test.rs │ ├── mod.rs │ ├── name.rs │ ├── packer.rs │ ├── parser.rs │ ├── question.rs │ └── resource │ ├── a.rs │ ├── aaaa.rs │ ├── cname.rs │ ├── mod.rs │ ├── mx.rs │ ├── ns.rs │ ├── opt.rs │ ├── ptr.rs │ ├── soa.rs │ ├── srv.rs │ └── txt.rs ├── media ├── .gitignore ├── CHANGELOG.md ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── benches │ └── audio_buffer.rs ├── codecov.yml ├── doc │ └── webrtc.rs.png └── src │ ├── audio │ ├── buffer.rs │ ├── buffer │ │ ├── info.rs │ │ └── layout.rs │ ├── mod.rs │ └── sample.rs │ ├── error.rs │ ├── io │ ├── h264_reader │ │ ├── h264_reader_test.rs │ │ └── mod.rs │ ├── h264_writer │ │ ├── h264_writer_test.rs │ │ └── mod.rs │ ├── ivf_reader │ │ ├── ivf_reader_test.rs │ │ └── mod.rs │ ├── ivf_writer │ │ ├── ivf_writer_test.rs │ │ └── mod.rs │ ├── mod.rs │ ├── ogg_reader │ │ ├── mod.rs │ │ └── ogg_reader_test.rs │ ├── ogg_writer │ │ ├── mod.rs │ │ └── ogg_writer_test.rs │ └── sample_builder │ │ ├── mod.rs │ │ ├── sample_builder_test.rs │ │ ├── sample_sequence_location.rs │ │ └── sample_sequence_location_test.rs │ ├── lib.rs │ └── video │ └── mod.rs ├── rtcp ├── .gitignore ├── CHANGELOG.md ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── codecov.yml ├── doc │ └── webrtc.rs.png └── src │ ├── compound_packet │ ├── compound_packet_test.rs │ └── mod.rs │ ├── error.rs │ ├── extended_report │ ├── dlrr.rs │ ├── extended_report_test.rs │ ├── mod.rs │ ├── prt.rs │ ├── rle.rs │ ├── rrt.rs │ ├── ssr.rs │ ├── unknown.rs │ └── vm.rs │ ├── goodbye │ ├── goodbye_test.rs │ └── mod.rs │ ├── header.rs │ ├── lib.rs │ ├── packet.rs │ ├── payload_feedbacks │ ├── full_intra_request │ │ ├── full_intra_request_test.rs │ │ └── mod.rs │ ├── mod.rs │ ├── picture_loss_indication │ │ ├── mod.rs │ │ └── picture_loss_indication_test.rs │ ├── receiver_estimated_maximum_bitrate │ │ ├── mod.rs │ │ └── receiver_estimated_maximum_bitrate_test.rs │ └── slice_loss_indication │ │ ├── mod.rs │ │ └── slice_loss_indication_test.rs │ ├── raw_packet.rs │ ├── receiver_report │ ├── mod.rs │ └── receiver_report_test.rs │ ├── reception_report.rs │ ├── sender_report │ ├── mod.rs │ └── sender_report_test.rs │ ├── source_description │ ├── mod.rs │ └── source_description_test.rs │ ├── transport_feedbacks │ ├── mod.rs │ ├── rapid_resynchronization_request │ │ ├── mod.rs │ │ └── rapid_resynchronization_request_test.rs │ ├── transport_layer_cc │ │ ├── mod.rs │ │ └── transport_layer_cc_test.rs │ └── transport_layer_nack │ │ ├── mod.rs │ │ └── transport_layer_nack_test.rs │ └── util.rs ├── rtp ├── .gitignore ├── CHANGELOG.md ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── benches │ └── packet_bench.rs ├── codecov.yml ├── doc │ └── webrtc.rs.png └── src │ ├── codecs │ ├── av1 │ │ ├── av1_test.rs │ │ ├── leb128.rs │ │ ├── mod.rs │ │ ├── obu.rs │ │ └── packetizer.rs │ ├── g7xx │ │ ├── g7xx_test.rs │ │ └── mod.rs │ ├── h264 │ │ ├── h264_test.rs │ │ └── mod.rs │ ├── h265 │ │ ├── h265_test.rs │ │ └── mod.rs │ ├── mod.rs │ ├── opus │ │ ├── mod.rs │ │ └── opus_test.rs │ ├── vp8 │ │ ├── mod.rs │ │ └── vp8_test.rs │ └── vp9 │ │ ├── mod.rs │ │ └── vp9_test.rs │ ├── error.rs │ ├── extension │ ├── abs_send_time_extension │ │ ├── abs_send_time_extension_test.rs │ │ └── mod.rs │ ├── audio_level_extension │ │ ├── audio_level_extension_test.rs │ │ └── mod.rs │ ├── mod.rs │ ├── playout_delay_extension │ │ ├── mod.rs │ │ └── playout_delay_extension_test.rs │ ├── transport_cc_extension │ │ ├── mod.rs │ │ └── transport_cc_extension_test.rs │ └── video_orientation_extension │ │ ├── mod.rs │ │ └── video_orientation_extension_test.rs │ ├── header.rs │ ├── lib.rs │ ├── packet │ ├── mod.rs │ └── packet_test.rs │ ├── packetizer │ ├── mod.rs │ └── packetizer_test.rs │ └── sequence.rs ├── sctp ├── .gitignore ├── CHANGELOG.md ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── codecov.yml ├── doc │ └── webrtc.rs.png ├── examples │ ├── ping.rs │ ├── pong.rs │ └── throughput.rs ├── fuzz │ ├── .gitignore │ ├── Cargo.toml │ ├── artifacts │ │ ├── packet │ │ │ ├── crash-16cad30042bc4791bd62c630a780add5d1220779 │ │ │ ├── crash-8b9b318a6b66ea23232a4e2aec91deeeca470af8 │ │ │ ├── crash-8d90dfc8fc34fa06f161f69617ee8f48dec434cd │ │ │ ├── crash-b836a20af7f8af85423dbe80565465b16bb7a16f │ │ │ └── crash-f940d9879efc88872145955bae11ca6ad6a4c044 │ │ └── param │ │ │ ├── crash-216833e417069f431d0617fb4e9f8abe6c9a6c1d │ │ │ └── crash-fb1b644bc0d365ce2dc3c3ff77cd3c4cd8da528d │ └── fuzz_targets │ │ ├── packet.rs │ │ └── param.rs └── src │ ├── association │ ├── association_internal.rs │ ├── association_internal │ │ └── association_internal_test.rs │ ├── association_stats.rs │ ├── association_test.rs │ └── mod.rs │ ├── chunk │ ├── chunk_abort.rs │ ├── chunk_cookie_ack.rs │ ├── chunk_cookie_echo.rs │ ├── chunk_error.rs │ ├── chunk_forward_tsn.rs │ ├── chunk_header.rs │ ├── chunk_heartbeat.rs │ ├── chunk_heartbeat_ack.rs │ ├── chunk_init.rs │ ├── chunk_payload_data.rs │ ├── chunk_reconfig.rs │ ├── chunk_selective_ack.rs │ ├── chunk_shutdown.rs │ ├── chunk_shutdown_ack.rs │ ├── chunk_shutdown_complete.rs │ ├── chunk_test.rs │ ├── chunk_type.rs │ ├── chunk_unknown.rs │ └── mod.rs │ ├── error.rs │ ├── error_cause.rs │ ├── fuzz_artifact_test.rs │ ├── lib.rs │ ├── packet.rs │ ├── param │ ├── mod.rs │ ├── param_chunk_list.rs │ ├── param_forward_tsn_supported.rs │ ├── param_header.rs │ ├── param_heartbeat_info.rs │ ├── param_outgoing_reset_request.rs │ ├── param_random.rs │ ├── param_reconfig_response.rs │ ├── param_requested_hmac_algorithm.rs │ ├── param_state_cookie.rs │ ├── param_supported_extensions.rs │ ├── param_test.rs │ ├── param_type.rs │ ├── param_unknown.rs │ └── param_unrecognized.rs │ ├── queue │ ├── control_queue.rs │ ├── mod.rs │ ├── payload_queue.rs │ ├── pending_queue.rs │ ├── queue_test.rs │ └── reassembly_queue.rs │ ├── stream │ ├── mod.rs │ └── stream_test.rs │ ├── timer │ ├── ack_timer.rs │ ├── mod.rs │ ├── rtx_timer.rs │ └── timer_test.rs │ └── util.rs ├── sdp ├── .gitignore ├── CHANGELOG.md ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── benches │ └── bench.rs ├── codecov.yml ├── doc │ └── webrtc.rs.png ├── fuzz │ ├── .gitignore │ ├── Cargo.toml │ └── fuzz_targets │ │ └── parse_session.rs └── src │ ├── description │ ├── common.rs │ ├── description_test.rs │ ├── media.rs │ ├── mod.rs │ └── session.rs │ ├── direction │ ├── direction_test.rs │ └── mod.rs │ ├── error.rs │ ├── extmap │ ├── extmap_test.rs │ └── mod.rs │ ├── lexer │ └── mod.rs │ ├── lib.rs │ └── util │ ├── mod.rs │ └── util_test.rs ├── srtp ├── .gitignore ├── CHANGELOG.md ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── benches │ └── srtp_bench.rs ├── codecov.yml ├── doc │ └── webrtc.rs.png └── src │ ├── cipher │ ├── cipher_aead_aes_gcm.rs │ ├── cipher_aes_cm_hmac_sha1 │ │ ├── ctrcipher.rs │ │ ├── mod.rs │ │ └── opensslcipher.rs │ └── mod.rs │ ├── config.rs │ ├── context │ ├── context_test.rs │ ├── mod.rs │ ├── srtcp.rs │ ├── srtcp_test.rs │ ├── srtp.rs │ └── srtp_test.rs │ ├── error.rs │ ├── key_derivation.rs │ ├── lib.rs │ ├── option.rs │ ├── protection_profile.rs │ ├── session │ ├── mod.rs │ ├── session_rtcp_test.rs │ └── session_rtp_test.rs │ └── stream.rs ├── stun ├── .gitignore ├── CHANGELOG.md ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── benches │ └── bench.rs ├── codecov.yml ├── doc │ └── webrtc.rs.png ├── examples │ ├── stun_client.rs │ └── stun_decode.rs └── src │ ├── addr.rs │ ├── addr │ └── addr_test.rs │ ├── agent.rs │ ├── agent │ └── agent_test.rs │ ├── attributes.rs │ ├── attributes │ └── attributes_test.rs │ ├── checks.rs │ ├── client.rs │ ├── client │ └── client_test.rs │ ├── error.rs │ ├── error_code.rs │ ├── fingerprint.rs │ ├── fingerprint │ └── fingerprint_test.rs │ ├── integrity.rs │ ├── integrity │ └── integrity_test.rs │ ├── lib.rs │ ├── message.rs │ ├── message │ └── message_test.rs │ ├── textattrs.rs │ ├── textattrs │ └── textattrs_test.rs │ ├── uattrs.rs │ ├── uattrs │ └── uattrs_test.rs │ ├── uri.rs │ ├── uri │ └── uri_test.rs │ ├── xoraddr.rs │ └── xoraddr │ └── xoraddr_test.rs ├── turn ├── .gitignore ├── CHANGELOG.md ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── benches │ └── bench.rs ├── codecov.yml ├── doc │ └── webrtc.rs.png ├── examples │ ├── turn_client_udp.rs │ └── turn_server_udp.rs └── src │ ├── allocation │ ├── allocation_manager.rs │ ├── allocation_manager │ │ └── allocation_manager_test.rs │ ├── allocation_test.rs │ ├── channel_bind.rs │ ├── channel_bind │ │ └── channel_bind_test.rs │ ├── five_tuple.rs │ ├── five_tuple │ │ └── five_tuple_test.rs │ ├── mod.rs │ └── permission.rs │ ├── auth │ ├── auth_test.rs │ └── mod.rs │ ├── client │ ├── binding.rs │ ├── binding │ │ └── binding_test.rs │ ├── client_test.rs │ ├── mod.rs │ ├── periodic_timer.rs │ ├── periodic_timer │ │ └── periodic_timer_test.rs │ ├── permission.rs │ ├── relay_conn.rs │ ├── relay_conn │ │ └── relay_conn_test.rs │ └── transaction.rs │ ├── error.rs │ ├── lib.rs │ ├── proto │ ├── addr.rs │ ├── addr │ │ └── addr_test.rs │ ├── chandata.rs │ ├── chandata │ │ └── chandata_test.rs │ ├── channum.rs │ ├── channum │ │ └── channnum_test.rs │ ├── data.rs │ ├── data │ │ └── data_test.rs │ ├── dontfrag.rs │ ├── dontfrag │ │ └── dontfrag_test.rs │ ├── evenport.rs │ ├── evenport │ │ └── evenport_test.rs │ ├── lifetime.rs │ ├── lifetime │ │ └── lifetime_test.rs │ ├── mod.rs │ ├── peeraddr.rs │ ├── peeraddr │ │ └── peeraddr_test.rs │ ├── proto_test.rs │ ├── relayaddr.rs │ ├── relayaddr │ │ └── relayaddr_test.rs │ ├── reqfamily.rs │ ├── reqfamily │ │ └── reqfamily_test.rs │ ├── reqtrans.rs │ ├── reqtrans │ │ └── reqtrans_test.rs │ ├── rsrvtoken.rs │ └── rsrvtoken │ │ └── rsrvtoken_test.rs │ ├── relay │ ├── mod.rs │ ├── relay_none.rs │ ├── relay_range.rs │ └── relay_static.rs │ └── server │ ├── config.rs │ ├── mod.rs │ ├── request.rs │ ├── request │ └── request_test.rs │ └── server_test.rs ├── util ├── .gitignore ├── CHANGELOG.md ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── benches │ └── bench.rs ├── codecov.yml ├── doc │ └── webrtc.rs.png ├── examples │ └── display-interfaces.rs └── src │ ├── buffer │ ├── buffer_test.rs │ └── mod.rs │ ├── conn │ ├── conn_bridge.rs │ ├── conn_bridge_test.rs │ ├── conn_disconnected_packet.rs │ ├── conn_pipe.rs │ ├── conn_pipe_test.rs │ ├── conn_test.rs │ ├── conn_udp.rs │ ├── conn_udp_listener.rs │ ├── conn_udp_listener_test.rs │ └── mod.rs │ ├── error.rs │ ├── fixed_big_int │ ├── fixed_big_int_test.rs │ └── mod.rs │ ├── ifaces │ ├── ffi │ │ ├── mod.rs │ │ ├── unix │ │ │ └── mod.rs │ │ └── windows │ │ │ └── mod.rs │ └── mod.rs │ ├── lib.rs │ ├── marshal │ ├── exact_size_buf.rs │ └── mod.rs │ ├── replay_detector │ ├── mod.rs │ └── replay_detector_test.rs │ ├── sync │ └── mod.rs │ └── vnet │ ├── chunk.rs │ ├── chunk │ └── chunk_test.rs │ ├── chunk_queue.rs │ ├── chunk_queue │ └── chunk_queue_test.rs │ ├── conn.rs │ ├── conn │ └── conn_test.rs │ ├── conn_map.rs │ ├── conn_map │ └── conn_map_test.rs │ ├── interface.rs │ ├── mod.rs │ ├── nat.rs │ ├── nat │ └── nat_test.rs │ ├── net.rs │ ├── net │ └── net_test.rs │ ├── resolver.rs │ ├── resolver │ └── resolver_test.rs │ ├── router.rs │ └── router │ └── router_test.rs └── webrtc ├── CHANGELOG.md ├── Cargo.toml └── src ├── api ├── api_test.rs ├── interceptor_registry │ ├── interceptor_registry_test.rs │ └── mod.rs ├── media_engine │ ├── media_engine_test.rs │ └── mod.rs ├── mod.rs └── setting_engine │ ├── mod.rs │ └── setting_engine_test.rs ├── data_channel ├── data_channel_init.rs ├── data_channel_message.rs ├── data_channel_parameters.rs ├── data_channel_state.rs ├── data_channel_test.rs └── mod.rs ├── dtls_transport ├── dtls_fingerprint.rs ├── dtls_parameters.rs ├── dtls_role.rs ├── dtls_transport_state.rs ├── dtls_transport_test.rs └── mod.rs ├── error.rs ├── ice_transport ├── ice_candidate.rs ├── ice_candidate_pair.rs ├── ice_candidate_type.rs ├── ice_connection_state.rs ├── ice_gatherer.rs ├── ice_gatherer_state.rs ├── ice_gathering_state.rs ├── ice_parameters.rs ├── ice_protocol.rs ├── ice_role.rs ├── ice_server.rs ├── ice_transport_state.rs ├── ice_transport_test.rs └── mod.rs ├── lib.rs ├── mux ├── endpoint.rs ├── mod.rs ├── mux_func.rs └── mux_test.rs ├── peer_connection ├── certificate.rs ├── configuration.rs ├── mod.rs ├── offer_answer_options.rs ├── operation │ ├── mod.rs │ └── operation_test.rs ├── peer_connection_internal.rs ├── peer_connection_state.rs ├── peer_connection_test.rs ├── policy │ ├── bundle_policy.rs │ ├── ice_transport_policy.rs │ ├── mod.rs │ ├── rtcp_mux_policy.rs │ └── sdp_semantics.rs ├── sdp │ ├── mod.rs │ ├── sdp_test.rs │ ├── sdp_type.rs │ └── session_description.rs └── signaling_state.rs ├── rtp_transceiver ├── fmtp │ ├── generic │ │ ├── generic_test.rs │ │ └── mod.rs │ ├── h264 │ │ ├── h264_test.rs │ │ └── mod.rs │ └── mod.rs ├── mod.rs ├── rtp_codec.rs ├── rtp_receiver │ ├── mod.rs │ └── rtp_receiver_test.rs ├── rtp_sender │ ├── mod.rs │ └── rtp_sender_test.rs ├── rtp_transceiver_direction.rs ├── rtp_transceiver_test.rs └── srtp_writer_future.rs ├── sctp_transport ├── mod.rs ├── sctp_transport_capabilities.rs ├── sctp_transport_state.rs └── sctp_transport_test.rs ├── stats ├── mod.rs ├── serialize.rs └── stats_collector.rs └── track ├── mod.rs ├── track_local ├── mod.rs ├── track_local_static_rtp.rs ├── track_local_static_sample.rs └── track_local_static_test.rs └── track_remote └── mod.rs /.gitattributes: -------------------------------------------------------------------------------- 1 | devbox.lock binary linguist-generated=true eol=lf 2 | 3 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: webrtc-rs # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: WebRTCrs # Replace with a single Patreon username 5 | open_collective: webrtc-rs # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 13 | -------------------------------------------------------------------------------- /.github/actions-rs/grcov.yml: -------------------------------------------------------------------------------- 1 | branch: true 2 | ignore-not-existing: true 3 | llvm: true 4 | filter: covered 5 | output-type: lcov 6 | output-path: ./lcov.info 7 | source-dir: . 8 | ignore: 9 | - "/*" 10 | - "C:/*" 11 | - "../*" 12 | excl-line: "#\\[derive\\(" 13 | excl-start: "mod tests \\{" 14 | excl-br-line: "#\\[derive\\(" 15 | excl-br-start: "mod tests \\{" -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | /target/ 4 | /.idea/ 5 | /crates/target/ 6 | /crates/.idea/ 7 | 8 | # These are backup files generated by rustfmt 9 | **/*.rs.bk 10 | 11 | # Editor configs 12 | .vscode 13 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webrtc-rs/webrtc/f296fc7295e64804a1bd57b7eed82f61fc4210b4/.gitmodules -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | repos: 2 | - repo: https://github.com/doublify/pre-commit-rust 3 | rev: v1.0 4 | hooks: 5 | - id: fmt 6 | - id: cargo-check 7 | 8 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | members = [ 3 | "data", 4 | "dtls", 5 | "examples", 6 | "ice", 7 | "interceptor", 8 | "mdns", 9 | "media", 10 | "rtcp", 11 | "rtp", 12 | "sctp", 13 | "sdp", 14 | "srtp", 15 | "stun", 16 | "turn", 17 | "util", 18 | "webrtc", 19 | ] 20 | resolver = "2" 21 | 22 | [profile.dev] 23 | opt-level = 0 24 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 WebRTC.rs 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 | -------------------------------------------------------------------------------- /_typos.toml: -------------------------------------------------------------------------------- 1 | [type.po] 2 | extend-glob = ["*.csr"] 3 | check-file = false 4 | 5 | [default.extend-words] 6 | # Additionals is important for WebRTC 7 | additionals = "additionals" 8 | # STAP-A for WebRTC 9 | stap = "stap" 10 | # MIS value 11 | mis = "mis" 12 | # datas is used a lot for plural. 13 | datas = "datas" 14 | # 2nd for second 15 | 2nd = "2nd" 16 | -------------------------------------------------------------------------------- /codecov.yml: -------------------------------------------------------------------------------- 1 | codecov: 2 | require_ci_to_pass: yes 3 | max_report_age: off 4 | token: 9c7a93c8-b2b2-4da3-9990-7283701dec58 5 | 6 | coverage: 7 | precision: 2 8 | round: down 9 | range: 50..90 10 | status: 11 | project: 12 | default: 13 | enabled: no 14 | threshold: 0.2 15 | if_not_found: success 16 | patch: 17 | default: 18 | enabled: no 19 | if_not_found: success 20 | changes: 21 | default: 22 | enabled: no 23 | if_not_found: success 24 | -------------------------------------------------------------------------------- /data/.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | /target/ 4 | /.idea/ 5 | 6 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 7 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html 8 | Cargo.lock 9 | 10 | # These are backup files generated by rustfmt 11 | **/*.rs.bk 12 | -------------------------------------------------------------------------------- /data/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # webrtc-data changelog 2 | 3 | ## Unreleased 4 | 5 | * Remove builder pattern from `data_channel::Config` [#411](https://github.com/webrtc-rs/webrtc/pull/411). 6 | 7 | ## v0.7.0 8 | 9 | * Increased required `webrtc-sctp` version to `0.8.0`. 10 | 11 | ## v0.6.0 12 | 13 | * Increased minimum support rust version to `1.60.0`. 14 | * Do not loose data in `PollDataChannel::poll_write` [#341](https://github.com/webrtc-rs/webrtc/pull/341). 15 | * `PollDataChannel::poll_shutdown`: make sure to flush any writes before shutting down [#340](https://github.com/webrtc-rs/webrtc/pull/340) 16 | * Increased required `webrtc-util` version to `0.7.0`. 17 | * Increased required `webrtc-sctp` version to `0.7.0`. 18 | 19 | ### Breaking changes 20 | 21 | * Make `DataChannel::on_buffered_amount_low` function non-async [#338](https://github.com/webrtc-rs/webrtc/pull/338). 22 | 23 | ## v0.5.0 24 | 25 | * [#16 [PollDataChannel] reset shutdown_fut future after done](https://github.com/webrtc-rs/data/pull/16) by [@melekes](https://github.com/melekes). 26 | * Increase min version of `log` dependency to `0.4.16`. [#250 Fix log at ^0.4.16 to make tests compile](https://github.com/webrtc-rs/webrtc/pull/250) by [@k0nserv](https://github.com/k0nserv). 27 | 28 | ## Prior to 0.4.0 29 | 30 | Before 0.4.0 there was no changelog, previous changes are sometimes, but not always, available in the [GitHub Releases](https://github.com/webrtc-rs/data/releases). 31 | -------------------------------------------------------------------------------- /data/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "webrtc-data" 3 | version = "0.11.0" 4 | authors = ["Rain Liu "] 5 | edition = "2021" 6 | description = "A pure Rust implementation of WebRTC DataChannel API" 7 | license = "MIT OR Apache-2.0" 8 | documentation = "https://docs.rs/webrtc-data" 9 | homepage = "https://webrtc.rs" 10 | repository = "https://github.com/webrtc-rs/webrtc/tree/master/data" 11 | 12 | [dependencies] 13 | util = { version = "0.11.0", path = "../util", package = "webrtc-util", default-features = false, features = ["conn", "marshal"] } 14 | sctp = { version = "0.12.0", path = "../sctp", package = "webrtc-sctp" } 15 | 16 | tokio = { version = "1.32.0", features = [ 17 | "fs", 18 | "io-util", 19 | "io-std", 20 | "macros", 21 | "net", 22 | "parking_lot", 23 | "rt", 24 | "rt-multi-thread", 25 | "sync", 26 | "time", 27 | ] } 28 | bytes = "1" 29 | log = "0.4" 30 | thiserror = "1" 31 | portable-atomic = "1.6" 32 | 33 | [dev-dependencies] 34 | tokio-test = "0.4" # must match the min version of the `tokio` crate above 35 | env_logger = "0.11.3" 36 | chrono = "0.4.28" 37 | -------------------------------------------------------------------------------- /data/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 WebRTC.rs 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 | -------------------------------------------------------------------------------- /data/README.md: -------------------------------------------------------------------------------- 1 |

2 | WebRTC.rs 3 |
4 |

5 |

6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | License: MIT/Apache 2.0 23 | 24 | 25 | Discord 26 | 27 |

28 |

29 | A pure Rust implementation of WebRTC DataChannel. Rewrite Pion DataChannel in Rust 30 |

31 | -------------------------------------------------------------------------------- /data/codecov.yml: -------------------------------------------------------------------------------- 1 | codecov: 2 | require_ci_to_pass: yes 3 | max_report_age: off 4 | token: 00d131c6-1478-4018-b481-be1b44f5f094 5 | 6 | coverage: 7 | precision: 2 8 | round: down 9 | range: 50..90 10 | status: 11 | project: 12 | default: 13 | enabled: no 14 | threshold: 0.2 15 | if_not_found: success 16 | patch: 17 | default: 18 | enabled: no 19 | if_not_found: success 20 | changes: 21 | default: 22 | enabled: no 23 | if_not_found: success 24 | -------------------------------------------------------------------------------- /data/doc/webrtc.rs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webrtc-rs/webrtc/f296fc7295e64804a1bd57b7eed82f61fc4210b4/data/doc/webrtc.rs.png -------------------------------------------------------------------------------- /data/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![warn(rust_2018_idioms)] 2 | #![allow(dead_code)] 3 | 4 | pub mod data_channel; 5 | mod error; 6 | pub mod message; 7 | 8 | pub use error::Error; 9 | -------------------------------------------------------------------------------- /devbox.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://raw.githubusercontent.com/jetify-com/devbox/0.10.7/.schema/devbox.schema.json", 3 | "packages": { 4 | "git": "latest", 5 | "pre-commit": "latest", 6 | "rustup": "latest", 7 | "libiconv": "latest", 8 | "darwin.apple_sdk.frameworks.SystemConfiguration": { 9 | "platforms": ["x86_64-darwin", "aarch64-darwin"], 10 | }, 11 | "darwin.apple_sdk.frameworks.Security": { 12 | "platforms": ["x86_64-darwin", "aarch64-darwin"], 13 | }, 14 | "darwin.apple_sdk.frameworks.CoreServices": { 15 | "platforms": ["x86_64-darwin", "aarch64-darwin"], 16 | }, 17 | "vim": "latest", 18 | "less": "latest", 19 | "openssh": "latest", 20 | }, 21 | "shell": { 22 | "init_hook": [ 23 | "pre-commit install", 24 | "if [ ! -d $RUSTUP_HOME/toolchains/stable* ]; then rustup default stable; fi", 25 | ], 26 | "scripts": { 27 | "test": [ 28 | "cargo test", 29 | ], 30 | "build": [ 31 | "cargo build", 32 | ], 33 | "fmt": [ 34 | "cargo fmt", 35 | ], 36 | }, 37 | }, 38 | "env": { 39 | "LS_COLORS": "di=33", 40 | }, 41 | } 42 | -------------------------------------------------------------------------------- /doc/AVStack.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webrtc-rs/webrtc/f296fc7295e64804a1bd57b7eed82f61fc4210b4/doc/AVStack.jpg -------------------------------------------------------------------------------- /doc/ChannelTalk_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webrtc-rs/webrtc/f296fc7295e64804a1bd57b7eed82f61fc4210b4/doc/ChannelTalk_logo.png -------------------------------------------------------------------------------- /doc/KittyCAD.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webrtc-rs/webrtc/f296fc7295e64804a1bd57b7eed82f61fc4210b4/doc/KittyCAD.png -------------------------------------------------------------------------------- /doc/check.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webrtc-rs/webrtc/f296fc7295e64804a1bd57b7eed82f61fc4210b4/doc/check.png -------------------------------------------------------------------------------- /doc/embark.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webrtc-rs/webrtc/f296fc7295e64804a1bd57b7eed82f61fc4210b4/doc/embark.jpg -------------------------------------------------------------------------------- /doc/parity.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webrtc-rs/webrtc/f296fc7295e64804a1bd57b7eed82f61fc4210b4/doc/parity.png -------------------------------------------------------------------------------- /doc/stream-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webrtc-rs/webrtc/f296fc7295e64804a1bd57b7eed82f61fc4210b4/doc/stream-logo.png -------------------------------------------------------------------------------- /doc/uncheck.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webrtc-rs/webrtc/f296fc7295e64804a1bd57b7eed82f61fc4210b4/doc/uncheck.png -------------------------------------------------------------------------------- /doc/webrtc.rs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webrtc-rs/webrtc/f296fc7295e64804a1bd57b7eed82f61fc4210b4/doc/webrtc.rs.png -------------------------------------------------------------------------------- /doc/webrtc.rs.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webrtc-rs/webrtc/f296fc7295e64804a1bd57b7eed82f61fc4210b4/doc/webrtc.rs.xcf -------------------------------------------------------------------------------- /doc/webrtc_crab.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webrtc-rs/webrtc/f296fc7295e64804a1bd57b7eed82f61fc4210b4/doc/webrtc_crab.png -------------------------------------------------------------------------------- /doc/webrtc_crates_dep_graph.odg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webrtc-rs/webrtc/f296fc7295e64804a1bd57b7eed82f61fc4210b4/doc/webrtc_crates_dep_graph.odg -------------------------------------------------------------------------------- /doc/webrtc_crates_dep_graph.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webrtc-rs/webrtc/f296fc7295e64804a1bd57b7eed82f61fc4210b4/doc/webrtc_crates_dep_graph.png -------------------------------------------------------------------------------- /doc/webrtc_stack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webrtc-rs/webrtc/f296fc7295e64804a1bd57b7eed82f61fc4210b4/doc/webrtc_stack.png -------------------------------------------------------------------------------- /dtls/.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | /target/ 4 | /examples/hub/target 5 | /.idea/ 6 | 7 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 8 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html 9 | Cargo.lock 10 | 11 | # These are backup files generated by rustfmt 12 | **/*.rs.bk 13 | -------------------------------------------------------------------------------- /dtls/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # webrtc-dtls changelog 2 | 3 | ## Unreleased 4 | 5 | ## v0.7.1 6 | 7 | * Added support for insecure/deprecated signature verification algorithms [#342](https://github.com/webrtc-rs/webrtc/pull/342) by [@chuigda](https://github.com/chuigda). 8 | 9 | ## v0.7.0 10 | 11 | * Increased minimum support rust version to `1.60.0`. 12 | * Add `RTCCertificate::from_pem` and `RTCCertificate::serialize_pem` (only work with `pem` feature enabled) [#333](https://github.com/webrtc-rs/webrtc/pull/333) 13 | 14 | ### Breaking 15 | 16 | * Increased required `webrtc-util` version to `0.7.0`, with this change some methods in `DTLSConn` that implement `webrtc_util::Conn` have changed from async to sync. 17 | 18 | ## v0.6.0 19 | 20 | * [#254 [DTLS] Add NamedCurve::P384](https://github.com/webrtc-rs/webrtc/pull/254) contributed by [neonphog](https://github.com/neonphog) 21 | * Increased min version of `log` dependency to `0.4.16`. [#250 Fix log at ^0.4.16 to make tests compile](https://github.com/webrtc-rs/webrtc/pull/250) by [@k0nserv](https://github.com/k0nserv). 22 | * Increased serde's minimum version to 1.0.110 [#243 Fixes for cargo minimal-versions](https://github.com/webrtc-rs/webrtc/pull/243) contributed by [algesten](https://github.com/algesten) 23 | 24 | ## Prior to 0.6.0 25 | 26 | Before 0.6.0 there was no changelog, previous changes are sometimes, but not always, available in the [GitHub Releases](https://github.com/webrtc-rs/dtls/releases). 27 | -------------------------------------------------------------------------------- /dtls/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 WebRTC.rs 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 | -------------------------------------------------------------------------------- /dtls/README.md: -------------------------------------------------------------------------------- 1 |

2 | WebRTC.rs 3 |
4 |

5 |

6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | License: MIT/Apache 2.0 23 | 24 | 25 | Discord 26 | 27 |

28 |

29 | A pure Rust implementation of DTLS. Rewrite Pion DTLS in Rust 30 |

31 | -------------------------------------------------------------------------------- /dtls/codecov.yml: -------------------------------------------------------------------------------- 1 | codecov: 2 | require_ci_to_pass: yes 3 | max_report_age: off 4 | token: 14bc9fb7-bdcf-4355-8e0e-ebec14066ae5 5 | 6 | coverage: 7 | precision: 2 8 | round: down 9 | range: 50..90 10 | status: 11 | project: 12 | default: 13 | enabled: no 14 | threshold: 0.2 15 | if_not_found: success 16 | patch: 17 | default: 18 | enabled: no 19 | if_not_found: success 20 | changes: 21 | default: 22 | enabled: no 23 | if_not_found: success 24 | -------------------------------------------------------------------------------- /dtls/doc/webrtc.rs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webrtc-rs/webrtc/f296fc7295e64804a1bd57b7eed82f61fc4210b4/dtls/doc/webrtc.rs.png -------------------------------------------------------------------------------- /dtls/examples/certificates/client.csr: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE REQUEST----- 2 | MIHHMG8CAQAwDTELMAkGA1UEBhMCTkwwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNC 3 | AAQhwOK0F+5DQy5FG0dRdN0GF20p3MsTaBk73IpNzrlK+WtgxdVxmRm55LWCTgkA 4 | RhnOcmzXW+raCEWQgTadaLd5oAAwCgYIKoZIzj0EAwIDSAAwRQIhANDZpyL2lr50 5 | Xr5DrD19SOa7LXpXz3DcM8RDLcBQvx05AiB7mbtcY6I18diHU0jSxHAGcUn5nAeD 6 | EP4tqFOz7QRzgQ== 7 | -----END CERTIFICATE REQUEST----- 8 | -------------------------------------------------------------------------------- /dtls/examples/certificates/client.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN EC PRIVATE KEY----- 2 | MHcCAQEEIO7fb5dmM2P0F71o/Clo0ElO29ud+JbtA3fhDIL15AgioAoGCCqGSM49 3 | AwEHoUQDQgAEIcDitBfuQ0MuRRtHUXTdBhdtKdzLE2gZO9yKTc65SvlrYMXVcZkZ 4 | ueS1gk4JAEYZznJs11vq2ghFkIE2nWi3eQ== 5 | -----END EC PRIVATE KEY----- 6 | -------------------------------------------------------------------------------- /dtls/examples/certificates/client.pem.private_key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg7t9vl2YzY/QXvWj8 3 | KWjQSU7b2534lu0Dd+EMgvXkCCKhRANCAAQhwOK0F+5DQy5FG0dRdN0GF20p3MsT 4 | aBk73IpNzrlK+WtgxdVxmRm55LWCTgkARhnOcmzXW+raCEWQgTadaLd5 5 | -----END PRIVATE KEY----- 6 | -------------------------------------------------------------------------------- /dtls/examples/certificates/client.pub.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIBITCByaADAgECAgMAq80wCgYIKoZIzj0EAwIwDTELMAkGA1UEBhMCTkwwHhcN 3 | MjEwOTE4MjAzNzE1WhcNMjIwOTE4MjAzNzE1WjANMQswCQYDVQQGEwJOTDBZMBMG 4 | ByqGSM49AgEGCCqGSM49AwEHA0IABCHA4rQX7kNDLkUbR1F03QYXbSncyxNoGTvc 5 | ik3OuUr5a2DF1XGZGbnktYJOCQBGGc5ybNdb6toIRZCBNp1ot3mjGDAWMBQGA1Ud 6 | EQQNMAuCCXdlYnJ0Yy5yczAKBggqhkjOPQQDAgNHADBEAiA8mpJVfaCw+RwALmxN 7 | XD28Ze3DUPomlfXhx+NGuePt5QIgAcRxvuDctyL07f8pQ5n22NOioNHdjwOjxww+ 8 | ZekD+Lg= 9 | -----END CERTIFICATE----- 10 | -------------------------------------------------------------------------------- /dtls/examples/certificates/extfile.conf: -------------------------------------------------------------------------------- 1 | subjectAltName = DNS:webrtc.rs 2 | -------------------------------------------------------------------------------- /dtls/examples/certificates/server.csr: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE REQUEST----- 2 | MIHHMG8CAQAwDTELMAkGA1UEBhMCTkwwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNC 3 | AASRyJbgbcieCbC1/HbiqmADkPxfk5Bmwjei2YXhPE+oYS3F5+df4BKNBgs7py7H 4 | sxc768+6X8HmvYlfvk2kHXAVoAAwCgYIKoZIzj0EAwIDSAAwRQIhAKR9rI22Xk/U 5 | L3xp2dzn7q3nyWqgDvp5uTflP4t0MBpJAiAJDKmcOCXNMhhgg4T2lhdfz/pZVfu5 6 | lxLcZm2ELiYImQ== 7 | -----END CERTIFICATE REQUEST----- 8 | -------------------------------------------------------------------------------- /dtls/examples/certificates/server.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN EC PRIVATE KEY----- 2 | MHcCAQEEID358pSfZXZqwqURqBLvLYcqhOdZVVNR2toCMER39YHboAoGCCqGSM49 3 | AwEHoUQDQgAEkciW4G3Ingmwtfx24qpgA5D8X5OQZsI3otmF4TxPqGEtxefnX+AS 4 | jQYLO6cux7MXO+vPul/B5r2JX75NpB1wFQ== 5 | -----END EC PRIVATE KEY----- 6 | -------------------------------------------------------------------------------- /dtls/examples/certificates/server.pem.private_key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgPfnylJ9ldmrCpRGo 3 | Eu8thyqE51lVU1Ha2gIwRHf1gduhRANCAASRyJbgbcieCbC1/HbiqmADkPxfk5Bm 4 | wjei2YXhPE+oYS3F5+df4BKNBgs7py7Hsxc768+6X8HmvYlfvk2kHXAV 5 | -----END PRIVATE KEY----- 6 | -------------------------------------------------------------------------------- /dtls/examples/certificates/server.pub.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIBMjCB2qADAgECAhQzsfVoH1cRfcxCY/drp/cKdjvBDDAKBggqhkjOPQQDAjAN 3 | MQswCQYDVQQGEwJOTDAeFw0yMTA5MTgyMDM2NTVaFw0yMjA5MTgyMDM2NTVaMA0x 4 | CzAJBgNVBAYTAk5MMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEkciW4G3Ingmw 5 | tfx24qpgA5D8X5OQZsI3otmF4TxPqGEtxefnX+ASjQYLO6cux7MXO+vPul/B5r2J 6 | X75NpB1wFaMYMBYwFAYDVR0RBA0wC4IJd2VicnRjLnJzMAoGCCqGSM49BAMCA0cA 7 | MEQCIBZBGmNM3qig7OTMZLL4PYj4JrGMjIj/jZFHEhqeQn6HAiBpRte9WzCjJzZX 8 | vzRkUKfCs1NMa/XR0hfdaa8KJAdKyQ== 9 | -----END CERTIFICATE----- 10 | -------------------------------------------------------------------------------- /dtls/examples/hub/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "hub" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | util = { version = "0.11.0", path = "../../../util", package = "webrtc-util", default-features = false, features = [ 8 | "conn" 9 | ] } 10 | dtls = { version = "0.12.0", package = "webrtc-dtls", path = "../../" } 11 | 12 | tokio = { version = "1.32.0", features = ["full"] } 13 | rcgen = { version = "0.13", features = ["pem", "x509-parser"] } 14 | rustls = { version = "0.23.27", default-features = false } 15 | rustls-pemfile = "2" 16 | thiserror = "1" 17 | -------------------------------------------------------------------------------- /dtls/src/application_data.rs: -------------------------------------------------------------------------------- 1 | use std::io::{Read, Write}; 2 | 3 | use super::content::*; 4 | use crate::error::Result; 5 | 6 | // Application data messages are carried by the record layer and are 7 | // fragmented, compressed, and encrypted based on the current connection 8 | // state. The messages are treated as transparent data to the record 9 | // layer. 10 | /// ## Specifications 11 | /// 12 | /// * [RFC 5246 §10] 13 | /// 14 | /// [RFC 5246 §10]: https://tools.ietf.org/html/rfc5246#section-10 15 | #[derive(Clone, PartialEq, Eq, Debug)] 16 | pub struct ApplicationData { 17 | pub data: Vec, 18 | } 19 | 20 | impl ApplicationData { 21 | pub fn content_type(&self) -> ContentType { 22 | ContentType::ApplicationData 23 | } 24 | 25 | pub fn size(&self) -> usize { 26 | self.data.len() 27 | } 28 | 29 | pub fn marshal(&self, writer: &mut W) -> Result<()> { 30 | writer.write_all(&self.data)?; 31 | 32 | Ok(writer.flush()?) 33 | } 34 | 35 | pub fn unmarshal(reader: &mut R) -> Result { 36 | let mut data: Vec = vec![]; 37 | reader.read_to_end(&mut data)?; 38 | 39 | Ok(ApplicationData { data }) 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /dtls/src/change_cipher_spec/change_cipher_spec_test.rs: -------------------------------------------------------------------------------- 1 | use std::io::{BufReader, BufWriter}; 2 | 3 | use super::*; 4 | 5 | #[test] 6 | fn test_change_cipher_spec_round_trip() -> Result<()> { 7 | let c = ChangeCipherSpec {}; 8 | let mut raw = vec![]; 9 | { 10 | let mut writer = BufWriter::<&mut Vec>::new(raw.as_mut()); 11 | c.marshal(&mut writer)?; 12 | } 13 | 14 | let mut reader = BufReader::new(raw.as_slice()); 15 | let cnew = ChangeCipherSpec::unmarshal(&mut reader)?; 16 | assert_eq!( 17 | c, cnew, 18 | "ChangeCipherSpec round trip: got {cnew:?}, want {c:?}" 19 | ); 20 | 21 | Ok(()) 22 | } 23 | 24 | #[test] 25 | fn test_change_cipher_spec_invalid() -> Result<()> { 26 | let data = vec![0x00]; 27 | 28 | let mut reader = BufReader::new(data.as_slice()); 29 | let result = ChangeCipherSpec::unmarshal(&mut reader); 30 | 31 | match result { 32 | Ok(_) => panic!("must be error"), 33 | Err(err) => assert_eq!(err.to_string(), Error::ErrInvalidCipherSpec.to_string()), 34 | }; 35 | 36 | Ok(()) 37 | } 38 | -------------------------------------------------------------------------------- /dtls/src/change_cipher_spec/mod.rs: -------------------------------------------------------------------------------- 1 | #[cfg(test)] 2 | mod change_cipher_spec_test; 3 | 4 | use std::io::{Read, Write}; 5 | 6 | use byteorder::{ReadBytesExt, WriteBytesExt}; 7 | 8 | use super::content::*; 9 | use super::error::*; 10 | 11 | // The change cipher spec protocol exists to signal transitions in 12 | // ciphering strategies. The protocol consists of a single message, 13 | // which is encrypted and compressed under the current (not the pending) 14 | // connection state. The message consists of a single byte of value 1. 15 | /// ## Specifications 16 | /// 17 | /// * [RFC 5246 §7.1] 18 | /// 19 | /// [RFC 5246 §7.1]: https://tools.ietf.org/html/rfc5246#section-7.1 20 | #[derive(Clone, PartialEq, Eq, Debug)] 21 | pub struct ChangeCipherSpec; 22 | 23 | impl ChangeCipherSpec { 24 | pub fn content_type(&self) -> ContentType { 25 | ContentType::ChangeCipherSpec 26 | } 27 | 28 | pub fn size(&self) -> usize { 29 | 1 30 | } 31 | 32 | pub fn marshal(&self, writer: &mut W) -> Result<()> { 33 | writer.write_u8(0x01)?; 34 | 35 | Ok(writer.flush()?) 36 | } 37 | 38 | pub fn unmarshal(reader: &mut R) -> Result { 39 | let data = reader.read_u8()?; 40 | if data != 0x01 { 41 | return Err(Error::ErrInvalidCipherSpec); 42 | } 43 | 44 | Ok(ChangeCipherSpec {}) 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /dtls/src/cipher_suite/cipher_suite_tls_ecdhe_ecdsa_with_aes_128_ccm.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | use crate::cipher_suite::cipher_suite_aes_128_ccm::CipherSuiteAes128Ccm; 3 | use crate::crypto::crypto_ccm::CryptoCcmTagLen; 4 | 5 | pub fn new_cipher_suite_tls_ecdhe_ecdsa_with_aes_128_ccm() -> CipherSuiteAes128Ccm { 6 | CipherSuiteAes128Ccm::new( 7 | ClientCertificateType::EcdsaSign, 8 | CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_128_Ccm, 9 | false, 10 | CryptoCcmTagLen::CryptoCcmTagLength, 11 | ) 12 | } 13 | -------------------------------------------------------------------------------- /dtls/src/cipher_suite/cipher_suite_tls_ecdhe_ecdsa_with_aes_128_ccm8.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | use crate::cipher_suite::cipher_suite_aes_128_ccm::CipherSuiteAes128Ccm; 3 | use crate::crypto::crypto_ccm::CryptoCcmTagLen; 4 | 5 | pub fn new_cipher_suite_tls_ecdhe_ecdsa_with_aes_128_ccm8() -> CipherSuiteAes128Ccm { 6 | CipherSuiteAes128Ccm::new( 7 | ClientCertificateType::EcdsaSign, 8 | CipherSuiteId::Tls_Ecdhe_Ecdsa_With_Aes_128_Ccm_8, 9 | false, 10 | CryptoCcmTagLen::CryptoCcm8TagLength, 11 | ) 12 | } 13 | -------------------------------------------------------------------------------- /dtls/src/cipher_suite/cipher_suite_tls_psk_with_aes_128_ccm.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | use crate::cipher_suite::cipher_suite_aes_128_ccm::CipherSuiteAes128Ccm; 3 | use crate::crypto::crypto_ccm::CryptoCcmTagLen; 4 | 5 | pub fn new_cipher_suite_tls_psk_with_aes_128_ccm() -> CipherSuiteAes128Ccm { 6 | CipherSuiteAes128Ccm::new( 7 | ClientCertificateType::Unsupported, 8 | CipherSuiteId::Tls_Psk_With_Aes_128_Ccm, 9 | true, 10 | CryptoCcmTagLen::CryptoCcmTagLength, 11 | ) 12 | } 13 | -------------------------------------------------------------------------------- /dtls/src/cipher_suite/cipher_suite_tls_psk_with_aes_128_ccm8.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | use crate::cipher_suite::cipher_suite_aes_128_ccm::CipherSuiteAes128Ccm; 3 | use crate::crypto::crypto_ccm::CryptoCcmTagLen; 4 | 5 | pub fn new_cipher_suite_tls_psk_with_aes_128_ccm8() -> CipherSuiteAes128Ccm { 6 | CipherSuiteAes128Ccm::new( 7 | ClientCertificateType::Unsupported, 8 | CipherSuiteId::Tls_Psk_With_Aes_128_Ccm_8, 9 | true, 10 | CryptoCcmTagLen::CryptoCcm8TagLength, 11 | ) 12 | } 13 | -------------------------------------------------------------------------------- /dtls/src/client_certificate_type.rs: -------------------------------------------------------------------------------- 1 | #[derive(Copy, Clone, Debug, PartialEq, Eq)] 2 | pub enum ClientCertificateType { 3 | RsaSign = 1, 4 | EcdsaSign = 64, 5 | Unsupported, 6 | } 7 | 8 | impl From for ClientCertificateType { 9 | fn from(val: u8) -> Self { 10 | match val { 11 | 1 => ClientCertificateType::RsaSign, 12 | 64 => ClientCertificateType::EcdsaSign, 13 | _ => ClientCertificateType::Unsupported, 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /dtls/src/curve/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod named_curve; 2 | 3 | // https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-10 4 | #[derive(Copy, Clone, PartialEq, Eq, Debug)] 5 | pub enum EllipticCurveType { 6 | NamedCurve = 0x03, 7 | Unsupported, 8 | } 9 | 10 | impl From for EllipticCurveType { 11 | fn from(val: u8) -> Self { 12 | match val { 13 | 0x03 => EllipticCurveType::NamedCurve, 14 | _ => EllipticCurveType::Unsupported, 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /dtls/src/extension/extension_server_name/extension_server_name_test.rs: -------------------------------------------------------------------------------- 1 | use std::io::{BufReader, BufWriter}; 2 | 3 | use super::*; 4 | 5 | #[test] 6 | fn test_extension_server_name() -> Result<()> { 7 | let extension = ExtensionServerName { 8 | server_name: "test.domain".to_owned(), 9 | }; 10 | 11 | let mut raw = vec![]; 12 | { 13 | let mut writer = BufWriter::<&mut Vec>::new(raw.as_mut()); 14 | extension.marshal(&mut writer)?; 15 | } 16 | 17 | let mut reader = BufReader::new(raw.as_slice()); 18 | let new_extension = ExtensionServerName::unmarshal(&mut reader)?; 19 | 20 | assert_eq!( 21 | new_extension, extension, 22 | "extensionServerName marshal: got {new_extension:?} expected {extension:?}", 23 | ); 24 | 25 | Ok(()) 26 | } 27 | -------------------------------------------------------------------------------- /dtls/src/extension/extension_supported_elliptic_curves/extension_supported_elliptic_curves_test.rs: -------------------------------------------------------------------------------- 1 | use std::io::{BufReader, BufWriter}; 2 | 3 | use super::*; 4 | 5 | #[test] 6 | fn test_extension_supported_groups() -> Result<()> { 7 | let raw_supported_groups = vec![0x0, 0x4, 0x0, 0x2, 0x0, 0x1d]; // 0x0, 0xa, 8 | let parsed_supported_groups = ExtensionSupportedEllipticCurves { 9 | elliptic_curves: vec![NamedCurve::X25519], 10 | }; 11 | 12 | let mut raw = vec![]; 13 | { 14 | let mut writer = BufWriter::<&mut Vec>::new(raw.as_mut()); 15 | parsed_supported_groups.marshal(&mut writer)?; 16 | } 17 | 18 | assert_eq!( 19 | raw, raw_supported_groups, 20 | "extensionSupportedGroups marshal: got {raw:?}, want {raw_supported_groups:?}" 21 | ); 22 | 23 | let mut reader = BufReader::new(raw.as_slice()); 24 | let new_supported_groups = ExtensionSupportedEllipticCurves::unmarshal(&mut reader)?; 25 | 26 | assert_eq!( 27 | new_supported_groups, parsed_supported_groups, 28 | "extensionSupportedGroups unmarshal: got {new_supported_groups:?}, want {parsed_supported_groups:?}" 29 | ); 30 | 31 | Ok(()) 32 | } 33 | -------------------------------------------------------------------------------- /dtls/src/extension/extension_supported_point_formats/extension_supported_point_formats_test.rs: -------------------------------------------------------------------------------- 1 | use std::io::{BufReader, BufWriter}; 2 | 3 | use super::*; 4 | 5 | #[test] 6 | fn test_extension_supported_point_formats() -> Result<()> { 7 | let raw_extension_supported_point_formats = vec![0x00, 0x02, 0x01, 0x00]; // 0x00, 0x0b, 8 | let parsed_extension_supported_point_formats = ExtensionSupportedPointFormats { 9 | point_formats: vec![ELLIPTIC_CURVE_POINT_FORMAT_UNCOMPRESSED], 10 | }; 11 | 12 | let mut raw = vec![]; 13 | { 14 | let mut writer = BufWriter::<&mut Vec>::new(raw.as_mut()); 15 | parsed_extension_supported_point_formats.marshal(&mut writer)?; 16 | } 17 | 18 | assert_eq!( 19 | raw, raw_extension_supported_point_formats, 20 | "extensionSupportedPointFormats marshal: got {raw:?}, want {raw_extension_supported_point_formats:?}" 21 | ); 22 | 23 | let mut reader = BufReader::new(raw.as_slice()); 24 | let new_extension_supported_point_formats = 25 | ExtensionSupportedPointFormats::unmarshal(&mut reader)?; 26 | 27 | assert_eq!( 28 | new_extension_supported_point_formats, parsed_extension_supported_point_formats, 29 | "extensionSupportedPointFormats unmarshal: got {new_extension_supported_point_formats:?}, want {parsed_extension_supported_point_formats:?}" 30 | ); 31 | 32 | Ok(()) 33 | } 34 | -------------------------------------------------------------------------------- /dtls/src/extension/extension_use_extended_master_secret.rs: -------------------------------------------------------------------------------- 1 | #[cfg(test)] 2 | mod extension_use_extended_master_secret_test; 3 | 4 | use super::*; 5 | 6 | const EXTENSION_USE_EXTENDED_MASTER_SECRET_HEADER_SIZE: usize = 4; 7 | 8 | /// ## Specifications 9 | /// 10 | /// * [RFC 8422] 11 | /// 12 | /// [RFC 8422]: https://tools.ietf.org/html/rfc8422 13 | #[derive(Clone, Debug, PartialEq, Eq)] 14 | pub struct ExtensionUseExtendedMasterSecret { 15 | pub(crate) supported: bool, 16 | } 17 | 18 | impl ExtensionUseExtendedMasterSecret { 19 | pub fn extension_value(&self) -> ExtensionValue { 20 | ExtensionValue::UseExtendedMasterSecret 21 | } 22 | 23 | pub fn size(&self) -> usize { 24 | 2 25 | } 26 | 27 | pub fn marshal(&self, writer: &mut W) -> Result<()> { 28 | // length 29 | writer.write_u16::(0)?; 30 | 31 | Ok(writer.flush()?) 32 | } 33 | 34 | pub fn unmarshal(reader: &mut R) -> Result { 35 | let _ = reader.read_u16::()?; 36 | 37 | Ok(ExtensionUseExtendedMasterSecret { supported: true }) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /dtls/src/extension/extension_use_extended_master_secret/extension_use_extended_master_secret_test.rs: -------------------------------------------------------------------------------- 1 | use std::io::{BufReader, BufWriter}; 2 | 3 | use super::*; 4 | 5 | #[test] 6 | fn test_extension_use_extended_master_secret() -> Result<()> { 7 | let raw_extension_use_extended_master_secret = vec![0x00, 0x00]; 8 | let parsed_extension_use_extended_master_secret = 9 | ExtensionUseExtendedMasterSecret { supported: true }; 10 | 11 | let mut raw = vec![]; 12 | { 13 | let mut writer = BufWriter::<&mut Vec>::new(raw.as_mut()); 14 | parsed_extension_use_extended_master_secret.marshal(&mut writer)?; 15 | } 16 | 17 | assert_eq!( 18 | raw, raw_extension_use_extended_master_secret, 19 | "extension_use_extended_master_secret marshal: got {raw:?}, want {raw_extension_use_extended_master_secret:?}" 20 | ); 21 | 22 | let mut reader = BufReader::new(raw.as_slice()); 23 | let new_extension_use_extended_master_secret = 24 | ExtensionUseExtendedMasterSecret::unmarshal(&mut reader)?; 25 | 26 | assert_eq!( 27 | new_extension_use_extended_master_secret, parsed_extension_use_extended_master_secret, 28 | "extension_use_extended_master_secret unmarshal: got {new_extension_use_extended_master_secret:?}, want {parsed_extension_use_extended_master_secret:?}" 29 | ); 30 | 31 | Ok(()) 32 | } 33 | -------------------------------------------------------------------------------- /dtls/src/extension/extension_use_srtp/extension_use_srtp_test.rs: -------------------------------------------------------------------------------- 1 | use std::io::{BufReader, BufWriter}; 2 | 3 | use super::*; 4 | 5 | #[test] 6 | fn test_extension_use_srtp() -> Result<()> { 7 | let raw_use_srtp = vec![0x00, 0x05, 0x00, 0x02, 0x00, 0x01, 0x00]; //0x00, 0x0e, 8 | let parsed_use_srtp = ExtensionUseSrtp { 9 | protection_profiles: vec![SrtpProtectionProfile::Srtp_Aes128_Cm_Hmac_Sha1_80], 10 | }; 11 | 12 | let mut raw = vec![]; 13 | { 14 | let mut writer = BufWriter::<&mut Vec>::new(raw.as_mut()); 15 | parsed_use_srtp.marshal(&mut writer)?; 16 | } 17 | 18 | assert_eq!( 19 | raw, raw_use_srtp, 20 | "extensionUseSRTP marshal: got {raw:?}, want {raw_use_srtp:?}" 21 | ); 22 | 23 | let mut reader = BufReader::new(raw.as_slice()); 24 | let new_use_srtp = ExtensionUseSrtp::unmarshal(&mut reader)?; 25 | 26 | assert_eq!( 27 | new_use_srtp, parsed_use_srtp, 28 | "extensionUseSRTP unmarshal: got {new_use_srtp:?}, want {parsed_use_srtp:?}" 29 | ); 30 | 31 | Ok(()) 32 | } 33 | -------------------------------------------------------------------------------- /dtls/src/extension/renegotiation_info/renegotiation_info_test.rs: -------------------------------------------------------------------------------- 1 | use std::io::{BufReader, BufWriter}; 2 | 3 | use super::*; 4 | 5 | #[test] 6 | fn test_renegotiation_info() -> Result<()> { 7 | let extension = ExtensionRenegotiationInfo { 8 | renegotiated_connection: 0, 9 | }; 10 | 11 | let mut raw = vec![]; 12 | { 13 | let mut writer = BufWriter::<&mut Vec>::new(raw.as_mut()); 14 | extension.marshal(&mut writer)?; 15 | } 16 | 17 | let mut reader = BufReader::new(raw.as_slice()); 18 | let new_extension = ExtensionRenegotiationInfo::unmarshal(&mut reader)?; 19 | 20 | assert_eq!( 21 | new_extension.renegotiated_connection, 22 | extension.renegotiated_connection 23 | ); 24 | 25 | Ok(()) 26 | } 27 | -------------------------------------------------------------------------------- /dtls/src/handshake/handshake_message_client_key_exchange/handshake_message_client_key_exchange_test.rs: -------------------------------------------------------------------------------- 1 | use std::io::{BufReader, BufWriter}; 2 | 3 | use super::*; 4 | 5 | #[test] 6 | fn test_handshake_message_client_key_exchange() -> Result<()> { 7 | let raw_client_key_exchange = vec![ 8 | 0x20, 0x26, 0x78, 0x4a, 0x78, 0x70, 0xc1, 0xf9, 0x71, 0xea, 0x50, 0x4a, 0xb5, 0xbb, 0x00, 9 | 0x76, 0x02, 0x05, 0xda, 0xf7, 0xd0, 0x3f, 0xe3, 0xf7, 0x4e, 0x8a, 0x14, 0x6f, 0xb7, 0xe0, 10 | 0xc0, 0xff, 0x54, 11 | ]; 12 | let parsed_client_key_exchange = HandshakeMessageClientKeyExchange { 13 | identity_hint: vec![], 14 | public_key: raw_client_key_exchange[1..].to_vec(), 15 | }; 16 | 17 | let mut reader = BufReader::new(raw_client_key_exchange.as_slice()); 18 | let c = HandshakeMessageClientKeyExchange::unmarshal(&mut reader)?; 19 | assert_eq!( 20 | c, parsed_client_key_exchange, 21 | "parsedCertificateRequest unmarshal: got {c:?}, want {parsed_client_key_exchange:?}" 22 | ); 23 | 24 | let mut raw = vec![]; 25 | { 26 | let mut writer = BufWriter::<&mut Vec>::new(raw.as_mut()); 27 | c.marshal(&mut writer)?; 28 | } 29 | assert_eq!( 30 | raw, raw_client_key_exchange, 31 | "handshakeMessageClientKeyExchange marshal: got {raw:?}, want {raw_client_key_exchange:?}" 32 | ); 33 | 34 | Ok(()) 35 | } 36 | -------------------------------------------------------------------------------- /dtls/src/handshake/handshake_message_finished.rs: -------------------------------------------------------------------------------- 1 | #[cfg(test)] 2 | mod handshake_message_finished_test; 3 | 4 | use std::io::{Read, Write}; 5 | 6 | use super::*; 7 | 8 | #[derive(Clone, Debug, PartialEq, Eq)] 9 | pub struct HandshakeMessageFinished { 10 | pub(crate) verify_data: Vec, 11 | } 12 | 13 | impl HandshakeMessageFinished { 14 | pub fn handshake_type(&self) -> HandshakeType { 15 | HandshakeType::Finished 16 | } 17 | 18 | pub fn size(&self) -> usize { 19 | self.verify_data.len() 20 | } 21 | 22 | pub fn marshal(&self, writer: &mut W) -> Result<()> { 23 | writer.write_all(&self.verify_data)?; 24 | 25 | Ok(writer.flush()?) 26 | } 27 | 28 | pub fn unmarshal(reader: &mut R) -> Result { 29 | let mut verify_data: Vec = vec![]; 30 | reader.read_to_end(&mut verify_data)?; 31 | 32 | Ok(HandshakeMessageFinished { verify_data }) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /dtls/src/handshake/handshake_message_finished/handshake_message_finished_test.rs: -------------------------------------------------------------------------------- 1 | use std::io::{BufReader, BufWriter}; 2 | 3 | use super::*; 4 | 5 | #[test] 6 | fn test_handshake_message_finished() -> Result<()> { 7 | let raw_finished = vec![ 8 | 0x01, 0x01, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 9 | ]; 10 | let parsed_finished = HandshakeMessageFinished { 11 | verify_data: raw_finished.clone(), 12 | }; 13 | 14 | let mut reader = BufReader::new(raw_finished.as_slice()); 15 | let c = HandshakeMessageFinished::unmarshal(&mut reader)?; 16 | assert_eq!( 17 | c, parsed_finished, 18 | "handshakeMessageFinished unmarshal: got {c:?}, want {parsed_finished:?}" 19 | ); 20 | 21 | let mut raw = vec![]; 22 | { 23 | let mut writer = BufWriter::<&mut Vec>::new(raw.as_mut()); 24 | c.marshal(&mut writer)?; 25 | } 26 | assert_eq!( 27 | raw, raw_finished, 28 | "handshakeMessageFinished marshal: got {raw:?}, want {raw_finished:?}" 29 | ); 30 | 31 | Ok(()) 32 | } 33 | -------------------------------------------------------------------------------- /dtls/src/handshake/handshake_message_server_hello_done.rs: -------------------------------------------------------------------------------- 1 | #[cfg(test)] 2 | mod handshake_message_server_hello_done_test; 3 | 4 | use std::io::{Read, Write}; 5 | 6 | use super::*; 7 | 8 | #[derive(Clone, Debug, PartialEq, Eq)] 9 | pub struct HandshakeMessageServerHelloDone; 10 | 11 | impl HandshakeMessageServerHelloDone { 12 | pub fn handshake_type(&self) -> HandshakeType { 13 | HandshakeType::ServerHelloDone 14 | } 15 | 16 | pub fn size(&self) -> usize { 17 | 0 18 | } 19 | 20 | pub fn marshal(&self, _writer: &mut W) -> Result<()> { 21 | Ok(()) 22 | } 23 | 24 | pub fn unmarshal(_reader: &mut R) -> Result { 25 | Ok(HandshakeMessageServerHelloDone {}) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /dtls/src/handshake/handshake_message_server_hello_done/handshake_message_server_hello_done_test.rs: -------------------------------------------------------------------------------- 1 | use std::io::{BufReader, BufWriter}; 2 | 3 | use super::*; 4 | 5 | #[test] 6 | fn test_handshake_message_server_hello_done() -> Result<()> { 7 | let raw_server_hello_done = vec![]; 8 | let parsed_server_hello_done = HandshakeMessageServerHelloDone {}; 9 | 10 | let mut reader = BufReader::new(raw_server_hello_done.as_slice()); 11 | let c = HandshakeMessageServerHelloDone::unmarshal(&mut reader)?; 12 | assert_eq!( 13 | c, parsed_server_hello_done, 14 | "handshakeMessageServerHelloDone unmarshal: got {c:?}, want {parsed_server_hello_done:?}" 15 | ); 16 | 17 | let mut raw = vec![]; 18 | { 19 | let mut writer = BufWriter::<&mut Vec>::new(raw.as_mut()); 20 | c.marshal(&mut writer)?; 21 | } 22 | assert_eq!( 23 | raw, raw_server_hello_done, 24 | "handshakeMessageServerHelloDone marshal: got {raw:?}, want {raw_server_hello_done:?}" 25 | ); 26 | 27 | Ok(()) 28 | } 29 | -------------------------------------------------------------------------------- /dtls/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![warn(rust_2018_idioms)] 2 | #![allow(dead_code)] 3 | 4 | pub mod alert; 5 | pub mod application_data; 6 | pub mod change_cipher_spec; 7 | pub mod cipher_suite; 8 | pub mod client_certificate_type; 9 | pub mod compression_methods; 10 | pub mod config; 11 | pub mod conn; 12 | pub mod content; 13 | pub mod crypto; 14 | pub mod curve; 15 | mod error; 16 | pub mod extension; 17 | pub mod flight; 18 | pub mod fragment_buffer; 19 | pub mod handshake; 20 | pub mod handshaker; 21 | pub mod listener; 22 | pub mod prf; 23 | pub mod record_layer; 24 | pub mod signature_hash_algorithm; 25 | pub mod state; 26 | 27 | use cipher_suite::*; 28 | pub use error::Error; 29 | use extension::extension_use_srtp::SrtpProtectionProfile; 30 | 31 | pub(crate) fn find_matching_srtp_profile( 32 | a: &[SrtpProtectionProfile], 33 | b: &[SrtpProtectionProfile], 34 | ) -> Result { 35 | for a_profile in a { 36 | for b_profile in b { 37 | if a_profile == b_profile { 38 | return Ok(*a_profile); 39 | } 40 | } 41 | } 42 | Err(()) 43 | } 44 | 45 | pub(crate) fn find_matching_cipher_suite( 46 | a: &[CipherSuiteId], 47 | b: &[CipherSuiteId], 48 | ) -> Result { 49 | for a_suite in a { 50 | for b_suite in b { 51 | if a_suite == b_suite { 52 | return Ok(*a_suite); 53 | } 54 | } 55 | } 56 | Err(()) 57 | } 58 | -------------------------------------------------------------------------------- /examples/.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | /target/ 4 | /.idea/ 5 | 6 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 7 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html 8 | Cargo.lock 9 | 10 | # These are backup files generated by rustfmt 11 | **/*.rs.bk 12 | -------------------------------------------------------------------------------- /examples/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 WebRTC.rs 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 | -------------------------------------------------------------------------------- /examples/README.md: -------------------------------------------------------------------------------- 1 |

2 | WebRTC.rs 3 |
4 |

5 |

6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | License: MIT/Apache 2.0 23 | 24 | 25 | Discord 26 | 27 |

28 |

29 | Examples of WebRTC.rs stack. Rewrite Pion Examples in Rust 30 |

31 | -------------------------------------------------------------------------------- /examples/codecov.yml: -------------------------------------------------------------------------------- 1 | codecov: 2 | require_ci_to_pass: yes 3 | max_report_age: off 4 | token: ec7b9766-689c-46bf-99fe-6c8e9971d20b 5 | 6 | coverage: 7 | precision: 2 8 | round: down 9 | range: 50..90 10 | status: 11 | project: 12 | default: 13 | enabled: no 14 | threshold: 0.2 15 | if_not_found: success 16 | patch: 17 | default: 18 | enabled: no 19 | if_not_found: success 20 | changes: 21 | default: 22 | enabled: no 23 | if_not_found: success 24 | -------------------------------------------------------------------------------- /examples/doc/webrtc.rs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webrtc-rs/webrtc/f296fc7295e64804a1bd57b7eed82f61fc4210b4/examples/doc/webrtc.rs.png -------------------------------------------------------------------------------- /examples/examples/data-channels-close/README.md: -------------------------------------------------------------------------------- 1 | # data-channels-close 2 | data-channels-close is a variant of the data-channels example that allow playing with the life cycle of data channels. 3 | -------------------------------------------------------------------------------- /examples/examples/data-channels-detach-create/README.md: -------------------------------------------------------------------------------- 1 | # data-channels-detach-create 2 | 3 | data-channels-detach-create is an example that shows how you can detach a data channel. 4 | This allows direct access the the underlying [webrtc-rs/data](https://github.com/webrtc-rs/data). 5 | 6 | The example mirrors the data-channels-create example. 7 | 8 | ## Install 9 | 10 | ```shell 11 | cargo build --example data-channels-detach-create 12 | ``` 13 | 14 | ## Usage 15 | 16 | The example can be used in the same way as the [Data Channels Create](data-channels-create) example. 17 | -------------------------------------------------------------------------------- /examples/examples/data-channels-detach/README.md: -------------------------------------------------------------------------------- 1 | # data-channels 2 | 3 | data-channels is a WebRTC.rs application that shows how you can send/recv DataChannel messages from a web browser 4 | 5 | ## Instructions 6 | 7 | ### Build data-channels-detach 8 | 9 | ```shell 10 | cargo build --example data-channels-detach 11 | ``` 12 | 13 | ### Open data-channels-detach example page 14 | 15 | [jsfiddle.net](https://jsfiddle.net/9tsx15mg/90/) 16 | 17 | ### Run data-channels-detach, with your browsers SessionDescription as stdin 18 | 19 | In the jsfiddle the top textarea is your browser's session description, copy that and: 20 | 21 | #### Linux/macOS 22 | 23 | Run `echo $BROWSER_SDP | ./target/debug/examples/data-channels-detach` 24 | 25 | #### Windows 26 | 27 | 1. Paste the SessionDescription into a file. 28 | 1. Run `./target/debug/examples/data-channels-detach < my_file` 29 | 30 | ### Input data-channels-detach's SessionDescription into your browser 31 | 32 | Copy the text that `data-channels` just emitted and copy into second text area 33 | 34 | ### Hit 'Start Session' in jsfiddle 35 | 36 | Under Start Session you should see 'Checking' as it starts connecting. If everything worked you should see `New DataChannel foo 1` 37 | 38 | Now you can put whatever you want in the `Message` textarea, and when you hit `Send Message` it should appear in your terminal! 39 | 40 | WebRTC.rs will send random messages every 5 seconds that will appear in your browser. 41 | 42 | Congrats, you have used WebRTC.rs! 43 | -------------------------------------------------------------------------------- /examples/examples/data-channels/README.md: -------------------------------------------------------------------------------- 1 | # data-channels 2 | 3 | data-channels is a WebRTC.rs application that shows how you can send/recv DataChannel messages from a web browser 4 | 5 | ## Instructions 6 | 7 | ### Build data-channels 8 | 9 | ```shell 10 | cargo build --example data-channels 11 | ``` 12 | 13 | ### Open data-channels example page 14 | 15 | [jsfiddle.net](https://jsfiddle.net/9tsx15mg/90/) 16 | 17 | ### Run data-channels, with your browsers SessionDescription as stdin 18 | 19 | In the jsfiddle the top textarea is your browser's session description, copy that and: 20 | 21 | #### Linux/macOS 22 | 23 | Run `echo $BROWSER_SDP | ./target/debug/examples/data-channels` 24 | 25 | #### Windows 26 | 27 | 1. Paste the SessionDescription into a file. 28 | 1. Run `./target/debug/examples/data-channels < my_file` 29 | 30 | ### Input data-channels's SessionDescription into your browser 31 | 32 | Copy the text that `data-channels` just emitted and copy into second text area 33 | 34 | ### Hit 'Start Session' in jsfiddle 35 | 36 | Under Start Session you should see 'Checking' as it starts connecting. If everything worked you should see `New DataChannel foo 1` 37 | 38 | Now you can put whatever you want in the `Message` textarea, and when you hit `Send Message` it should appear in your terminal! 39 | 40 | WebRTC.rs will send random messages every 5 seconds that will appear in your browser. 41 | 42 | Congrats, you have used WebRTC.rs! 43 | -------------------------------------------------------------------------------- /examples/examples/ice-restart/README.md: -------------------------------------------------------------------------------- 1 | # ice-restart 2 | ice-restart demonstrates WebRTC.rs ICE Restart abilities. 3 | 4 | ## Instructions 5 | 6 | ### Build ice-restart 7 | ```shell 8 | cargo build --example ice-restart 9 | ``` 10 | 11 | ### Run ice-restart 12 | ```shell 13 | cargo run --example ice-restart 14 | ``` 15 | 16 | ### Open the Web UI 17 | Open [http://localhost:8080](http://localhost:8080). This will automatically start a PeerConnection. This page will now prints stats about the PeerConnection 18 | and allow you to do an ICE Restart at anytime. 19 | 20 | * `ICE Restart` is the button that causes a new offer to be made with `iceRestart: true`. 21 | * `ICE Connection States` will contain all the connection states the PeerConnection moves through. 22 | * `ICE Selected Pairs` will print the selected pair every 3 seconds. Note how the uFrag/uPwd/Port change everytime you start the Restart process. 23 | * `Inbound DataChannel Messages` containing the current time sent by the Pion process every 3 seconds. 24 | 25 | Congrats, you have used WebRTC.rs! 26 | -------------------------------------------------------------------------------- /examples/examples/offer-answer/README.md: -------------------------------------------------------------------------------- 1 | # offer-answer 2 | 3 | offer-answer is an example of two webrtc-rs or pion instances communicating directly! 4 | 5 | The SDP offer and answer are exchanged automatically over HTTP. 6 | The `answer` side acts like a HTTP server and should therefore be ran first. 7 | 8 | ## Instructions 9 | 10 | First run `answer`: 11 | 12 | ```shell 13 | cargo build --example answer 14 | ./target/debug/examples/answer 15 | ``` 16 | 17 | Next, run `offer`: 18 | 19 | ```shell 20 | cargo build --example offer 21 | ./target/debug/examples/offer 22 | ``` 23 | 24 | You should see them connect and start to exchange messages. 25 | -------------------------------------------------------------------------------- /examples/examples/ortc/README.md: -------------------------------------------------------------------------------- 1 | # ortc 2 | 3 | ortc demonstrates WebRTC.rs's [ORTC](https://ortc.org/) capabilities. Instead of using the Session Description Protocol 4 | to configure and communicate ORTC provides APIs. Users then can implement signaling with whatever protocol they wish. 5 | ORTC can then be used to implement WebRTC. A ORTC implementation can parse/emit Session Description and act as a WebRTC 6 | implementation. 7 | 8 | In this example we have defined a simple JSON based signaling protocol. 9 | 10 | ## Instructions 11 | 12 | ### Build ortc 13 | 14 | ```shell 15 | cargo build --example ortc 16 | ``` 17 | 18 | ### Run first client as offerer 19 | 20 | `ortc --offer` this will emit a base64 message. Copy this message to your clipboard. 21 | 22 | ## Run the second client as answerer 23 | 24 | Run the second client. This should be launched with the message you copied in the previous step as stdin. 25 | 26 | `echo BASE64_MESSAGE_YOU_COPIED | ortc` 27 | 28 | ### Enjoy 29 | 30 | If everything worked you will see `Data channel 'Foo'-'' open.` in each terminal. 31 | 32 | Each client will send random messages every 5 seconds that will appear in the terminal 33 | 34 | Congrats, you have used WebRTC.rs! 35 | -------------------------------------------------------------------------------- /examples/examples/play-from-disk-hevc/README.md: -------------------------------------------------------------------------------- 1 | # play-from-disk-hevc 2 | 3 | play-from-disk-hevc demonstrates how to send hevc video and/or audio to your browser from files saved to disk. 4 | 5 | ## Instructions 6 | 7 | ### Create IVF named `output.265` that contains a hevc track and/or `output.ogg` that contains a Opus track 8 | 9 | ```shell 10 | ffmpeg -i $INPUT_FILE -an -c:v libx265 -bsf:v hevc_mp4toannexb -b:v 2M -max_delay 0 -bf 0 output.265 11 | ffmpeg -i $INPUT_FILE -c:a libopus -page_duration 20000 -vn output.ogg 12 | ``` 13 | 14 | ### Build/Run play-from-disk-hevc 15 | 16 | ```shell 17 | cargo run --example play-from-disk-hevc 18 | ``` 19 | 20 | ### Result and Output 21 | In the shell you opened, you should see from std that rtp of hevc get received and parsed 22 | 23 | After all is done, an `xx.output` file should be created at the same directory of the src video file 24 | 25 | Congrats, you have sent and received the hevc stream 26 | 27 | ## Notes 28 | - Maybe you will need to install libx265/opus for your ffmepg 29 | - Please update the stun server to the best match, google maybe slow/unaccessable in some certain region/circumstance 30 | -------------------------------------------------------------------------------- /examples/examples/play-from-disk-renegotiation/README.md: -------------------------------------------------------------------------------- 1 | # play-from-disk-renegotiation 2 | 3 | play-from-disk-renegotiation demonstrates WebRTC.rs's renegotiation abilities. 4 | 5 | For a simpler example of playing a file from disk we also have [examples/play-from-disk](/examples/play-from-disk) 6 | 7 | ## Instructions 8 | 9 | ### Build play-from-disk-renegotiation 10 | 11 | ```shell 12 | cargo build --example play-from-disk-renegotiation 13 | ``` 14 | 15 | ### Create IVF named `output.ivf` that contains a VP8 track 16 | 17 | ```shell 18 | ffmpeg -i $INPUT_FILE -g 30 output.ivf 19 | ``` 20 | 21 | ### Run play-from-disk-renegotiation 22 | 23 | The `output.ivf` you created should be in the same directory as `play-from-disk-renegotiation`. 24 | 25 | 26 | ### Open the Web UI 27 | 28 | Open [http://localhost:8080](http://localhost:8080) and you should have a `Add Track` and `Remove Track` button. Press these to add as many tracks as you want, or to remove as many as you wish. 29 | 30 | Congrats, you have used WebRTC.rs! 31 | -------------------------------------------------------------------------------- /examples/examples/rc-cycle/rc-cycle.rs: -------------------------------------------------------------------------------- 1 | use std::cell::RefCell; 2 | use std::rc::Rc; 3 | 4 | #[derive(Clone)] 5 | struct Cycle { 6 | cell: RefCell>>, 7 | } 8 | 9 | impl Drop for Cycle { 10 | fn drop(&mut self) { 11 | println!("freed"); 12 | } 13 | } 14 | 15 | #[tokio::main] 16 | async fn main() { 17 | let cycle = Rc::new(Cycle { 18 | cell: RefCell::new(None), 19 | }); 20 | *cycle.cell.borrow_mut() = Some(cycle.clone()); 21 | } 22 | 23 | // use nightly rust 24 | // RUSTFLAGS="-Z sanitizer=leak" cargo build --example rc-cycle 25 | // ./target/debug/example/rc-cycle 26 | // ================================================================= 27 | // ==1457719==ERROR: LeakSanitizer: detected memory leaks 28 | // 29 | // Direct leak of 32 byte(s) in 1 object(s) allocated from: 30 | // #0 0x55d4688e1b58 in malloc /rustc/llvm/src/llvm-project/compiler-rt/lib/lsan/lsan_interceptors.cpp:56:3 31 | // #1 0x55d4689db6cb in alloc::alloc::alloc::h1ab42fe6949393de /rustc/e269e6bf47f40c9046cd44ab787881d700099252/library/alloc/src/alloc.rs:86:14 32 | // 33 | // SUMMARY: LeakSanitizer: 32 byte(s) leaked in 1 allocation(s). 34 | -------------------------------------------------------------------------------- /examples/examples/reflect/README.md: -------------------------------------------------------------------------------- 1 | # reflect 2 | 3 | reflect demonstrates how with one PeerConnection you can send video to webrtc-rs and have the packets sent back. This example could be easily extended to do server side processing. 4 | 5 | ## Instructions 6 | 7 | ### Build reflect 8 | 9 | ```shell 10 | cargo build --example reflect 11 | ``` 12 | 13 | ### Open reflect example page 14 | 15 | [jsfiddle.net](https://jsfiddle.net/9jgukzt1/) you should see two text-areas and a 'Start Session' button. 16 | 17 | ### Run reflect, with your browsers SessionDescription as stdin 18 | 19 | In the jsfiddle the top textarea is your browser, copy that and: 20 | 21 | #### Linux/macOS 22 | 23 | Run `echo $BROWSER_SDP | ./target/debug/examples/reflect -a -v` 24 | 25 | #### Windows 26 | 27 | 1. Paste the SessionDescription into a file. 28 | 1. Run `./target/debug/examples/reflect -a -v < my_file` 29 | 30 | ### Input reflect's SessionDescription into your browser 31 | 32 | Copy the text that `reflect` just emitted and copy into second text area 33 | 34 | ### Hit 'Start Session' in jsfiddle, enjoy your video! 35 | 36 | Your browser should send video to webrtc-rs, and then it will be relayed right back to you. 37 | 38 | Congrats, you have used WebRTC.rs! 39 | -------------------------------------------------------------------------------- /examples/examples/rtp-forwarder/rtp-forwarder.sdp: -------------------------------------------------------------------------------- 1 | v=0 2 | o=- 0 0 IN IP4 127.0.0.1 3 | s=WebRTC.rs 4 | c=IN IP4 127.0.0.1 5 | t=0 0 6 | m=audio 4000 RTP/AVP 111 7 | a=rtpmap:111 OPUS/48000/2 8 | m=video 4002 RTP/AVP 96 9 | a=rtpmap:96 VP8/90000 -------------------------------------------------------------------------------- /examples/examples/save-to-disk-h264/README.md: -------------------------------------------------------------------------------- 1 | # save-to-disk-h264 2 | 3 | save-to-disk-h264 is a simple application that shows how to record your webcam/microphone using WebRTC.rs and save H264 and Opus to disk. 4 | 5 | ## Instructions 6 | 7 | ### Build save-to-disk-h264 8 | 9 | ```shell 10 | cargo build --example save-to-disk-h264 11 | ``` 12 | 13 | ### Open save-to-disk example page 14 | 15 | [jsfiddle.net](https://jsfiddle.net/vfmcg8rk/1/) you should see your Webcam, two text-areas and a 'Start Session' button 16 | 17 | ### Run save-to-disk-h264, with your browsers SessionDescription as stdin 18 | 19 | In the jsfiddle the top textarea is your browser, copy that and: 20 | 21 | #### Linux/macOS 22 | 23 | Run `echo $BROWSER_SDP | ./target/debug/examples/save-to-disk-h264` 24 | 25 | #### Windows 26 | 27 | 1. Paste the SessionDescription into a file. 28 | 1. Run `./target/debug/examples/save-to-disk-h264 < my_file` 29 | 30 | ### Input save-to-disk-h264's SessionDescription into your browser 31 | 32 | Copy the text that `save-to-disk-h264` just emitted and copy into second text area 33 | 34 | ### Hit 'Start Session' in jsfiddle, wait, close jsfiddle, enjoy your video! 35 | 36 | In the folder you ran `save-to-disk-h264` you should now have a file `output.h264` play with your video player of choice! 37 | 38 | Congrats, you have used WebRTC.rs! 39 | -------------------------------------------------------------------------------- /examples/examples/save-to-disk-vpx/README.md: -------------------------------------------------------------------------------- 1 | # save-to-disk-vpx 2 | 3 | save-to-disk-vpx is a simple application that shows how to record your webcam/microphone using WebRTC.rs and save VP8/VP9 and Opus to disk. 4 | 5 | ## Instructions 6 | 7 | ### Build save-to-disk-vpx 8 | 9 | ```shell 10 | cargo build --example save-to-disk-vpx 11 | ``` 12 | 13 | ### Open save-to-disk-vpx example page 14 | 15 | [jsfiddle.net](https://jsfiddle.net/vfmcg8rk/1/) you should see your Webcam, two text-areas and a 'Start Session' button 16 | 17 | ### Run save-to-disk-vpx, with your browsers SessionDescription as stdin 18 | 19 | In the jsfiddle the top textarea is your browser, copy that and: 20 | 21 | #### Linux/macOS 22 | 23 | Run `echo $BROWSER_SDP | ./target/debug/examples/save-to-disk-vpx` 24 | 25 | #### Windows 26 | 27 | 1. Paste the SessionDescription into a file. 28 | 1. Run `./target/debug/examples/save-to-disk-vpx < my_file` 29 | 30 | ### Input save-to-disk-vpx's SessionDescription into your browser 31 | 32 | Copy the text that `save-to-disk-vpx` just emitted and copy into second text area 33 | 34 | ### Hit 'Start Session' in jsfiddle, wait, close jsfiddle, enjoy your video! 35 | 36 | In the folder you ran `save-to-disk-vpx` you should now have a file `output_vpx.ivf` play with your video player of choice! 37 | 38 | Congrats, you have used WebRTC.rs! 39 | -------------------------------------------------------------------------------- /examples/examples/signal/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "signal" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | tokio = { version = "1.32.0", features = ["full"] } 8 | anyhow = "1" 9 | base64 = "0.22.1" 10 | lazy_static = "1" 11 | hyper = { version = "0.14.27", features = ["full"] } 12 | -------------------------------------------------------------------------------- /examples/examples/simulcast/README.md: -------------------------------------------------------------------------------- 1 | # simulcast 2 | 3 | demonstrates of how to handle incoming track with multiple simulcast rtp streams and show all them back. 4 | 5 | The browser will not send higher quality streams unless it has the available bandwidth. You can look at 6 | the bandwidth estimation in `chrome://webrtc-internals`. It is under `VideoBwe` when `Read Stats From: Legacy non-Standard` 7 | is selected. 8 | 9 | ## Instructions 10 | 11 | ### Build simulcast 12 | 13 | ```shell 14 | cargo build --example simulcast 15 | ``` 16 | 17 | ### Open simulcast example page 18 | 19 | [jsfiddle.net](https://jsfiddle.net/rxk4bftc) you should see two text-areas and a 'Start Session' button. 20 | 21 | ### Run simulcast, with your browsers SessionDescription as stdin 22 | 23 | In the jsfiddle the top textarea is your browser, copy that and: 24 | 25 | #### Linux/macOS 26 | 27 | Run `echo $BROWSER_SDP | ./target/debug/examples/simulcast` 28 | 29 | #### Windows 30 | 31 | 1. Paste the SessionDescription into a file. 32 | 1. Run `./target/debug/examples/simulcast < my_file` 33 | 34 | ### Input simulcast's SessionDescription into your browser 35 | 36 | Copy the text that `simulcast` just emitted and copy into second text area 37 | 38 | ### Hit 'Start Session' in jsfiddle, enjoy your video! 39 | 40 | Your browser should send a simulcast track to WebRTC.rs, and then all 3 incoming streams will be relayed back. 41 | 42 | Congrats, you have used WebRTC.rs! 43 | -------------------------------------------------------------------------------- /examples/examples/swap-tracks/README.md: -------------------------------------------------------------------------------- 1 | # swap-tracks 2 | 3 | swap-tracks demonstrates how to swap multiple incoming tracks on a single outgoing track. 4 | 5 | ## Instructions 6 | 7 | ### Build swap-tracks 8 | 9 | ```shell 10 | cargo build --example swap-tracks 11 | ``` 12 | 13 | ### Open swap-tracks example page 14 | 15 | [jsfiddle.net](https://jsfiddle.net/dzc17fga/) you should see two text-areas and a 'Start Session' button. 16 | 17 | ### Run swap-tracks, with your browsers SessionDescription as stdin 18 | 19 | In the jsfiddle the top textarea is your browser, copy that and: 20 | 21 | #### Linux/macOS 22 | 23 | Run `echo $BROWSER_SDP | ./target/debug/examples/swap-tracks` 24 | 25 | #### Windows 26 | 27 | 1. Paste the SessionDescription into a file. 28 | 1. Run `./target/debug/examples/swap-tracks < my_file` 29 | 30 | ### Input swap-tracks's SessionDescription into your browser 31 | 32 | Copy the text that `swap-tracks` just emitted and copy into second text area 33 | 34 | ### Hit 'Start Session' in jsfiddle, enjoy your video! 35 | 36 | Your browser should send streams to webrtc-rs, and then a stream will be relayed back, changing every 5 seconds. 37 | 38 | Congrats, you have used WebRTC.rs! 39 | -------------------------------------------------------------------------------- /examples/examples/test-data/output.h264: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webrtc-rs/webrtc/f296fc7295e64804a1bd57b7eed82f61fc4210b4/examples/examples/test-data/output.h264 -------------------------------------------------------------------------------- /examples/examples/test-data/output.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webrtc-rs/webrtc/f296fc7295e64804a1bd57b7eed82f61fc4210b4/examples/examples/test-data/output.ogg -------------------------------------------------------------------------------- /examples/examples/test-data/output_vp8.ivf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webrtc-rs/webrtc/f296fc7295e64804a1bd57b7eed82f61fc4210b4/examples/examples/test-data/output_vp8.ivf -------------------------------------------------------------------------------- /examples/examples/test-data/output_vp9.ivf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webrtc-rs/webrtc/f296fc7295e64804a1bd57b7eed82f61fc4210b4/examples/examples/test-data/output_vp9.ivf -------------------------------------------------------------------------------- /examples/src/lib.rs: -------------------------------------------------------------------------------- 1 | #[cfg(test)] 2 | mod tests { 3 | #[test] 4 | fn it_works() { 5 | assert_eq!(2 + 2, 4); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /ice/.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | /target/ 4 | /.idea/ 5 | 6 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 7 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html 8 | Cargo.lock 9 | 10 | # These are backup files generated by rustfmt 11 | **/*.rs.bk 12 | -------------------------------------------------------------------------------- /ice/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 WebRTC.rs 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 | -------------------------------------------------------------------------------- /ice/README.md: -------------------------------------------------------------------------------- 1 |

2 | WebRTC.rs 3 |
4 |

5 |

6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | License: MIT/Apache 2.0 23 | 24 | 25 | Discord 26 | 27 |

28 |

29 | A pure Rust implementation of ICE. Rewrite Pion ICE in Rust 30 |

31 | -------------------------------------------------------------------------------- /ice/codecov.yml: -------------------------------------------------------------------------------- 1 | codecov: 2 | require_ci_to_pass: yes 3 | max_report_age: off 4 | token: 4bd5cec1-2807-4cd6-8430-d5f3efe32ce0 5 | 6 | coverage: 7 | precision: 2 8 | round: down 9 | range: 50..90 10 | status: 11 | project: 12 | default: 13 | enabled: no 14 | threshold: 0.2 15 | if_not_found: success 16 | patch: 17 | default: 18 | enabled: no 19 | if_not_found: success 20 | changes: 21 | default: 22 | enabled: no 23 | if_not_found: success 24 | -------------------------------------------------------------------------------- /ice/doc/webrtc.rs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webrtc-rs/webrtc/f296fc7295e64804a1bd57b7eed82f61fc4210b4/ice/doc/webrtc.rs.png -------------------------------------------------------------------------------- /ice/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![warn(rust_2018_idioms)] 2 | #![allow(dead_code)] 3 | 4 | pub mod agent; 5 | pub mod candidate; 6 | pub mod control; 7 | mod error; 8 | pub mod external_ip_mapper; 9 | pub mod mdns; 10 | pub mod network_type; 11 | pub mod priority; 12 | pub mod rand; 13 | pub mod state; 14 | pub mod stats; 15 | pub mod tcp_type; 16 | pub mod udp_mux; 17 | pub mod udp_network; 18 | pub mod url; 19 | pub mod use_candidate; 20 | pub mod util; 21 | 22 | pub use error::Error; 23 | -------------------------------------------------------------------------------- /ice/src/priority/mod.rs: -------------------------------------------------------------------------------- 1 | #[cfg(test)] 2 | mod priority_test; 3 | 4 | use stun::attributes::ATTR_PRIORITY; 5 | use stun::checks::*; 6 | use stun::message::*; 7 | 8 | /// Represents PRIORITY attribute. 9 | #[derive(Default, PartialEq, Eq, Debug, Copy, Clone)] 10 | pub struct PriorityAttr(pub u32); 11 | 12 | const PRIORITY_SIZE: usize = 4; // 32 bit 13 | 14 | impl Setter for PriorityAttr { 15 | // add_to adds PRIORITY attribute to message. 16 | fn add_to(&self, m: &mut Message) -> Result<(), stun::Error> { 17 | let mut v = vec![0_u8; PRIORITY_SIZE]; 18 | v.copy_from_slice(&self.0.to_be_bytes()); 19 | m.add(ATTR_PRIORITY, &v); 20 | Ok(()) 21 | } 22 | } 23 | 24 | impl PriorityAttr { 25 | /// Decodes PRIORITY attribute from message. 26 | pub fn get_from(&mut self, m: &Message) -> Result<(), stun::Error> { 27 | let v = m.get(ATTR_PRIORITY)?; 28 | 29 | check_size(ATTR_PRIORITY, v.len(), PRIORITY_SIZE)?; 30 | 31 | let p = u32::from_be_bytes([v[0], v[1], v[2], v[3]]); 32 | self.0 = p; 33 | 34 | Ok(()) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /ice/src/priority/priority_test.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | use crate::error::Result; 3 | 4 | #[test] 5 | fn test_priority_get_from() -> Result<()> { 6 | let mut m = Message::new(); 7 | let mut p = PriorityAttr::default(); 8 | let result = p.get_from(&m); 9 | if let Err(err) = result { 10 | assert_eq!(err, stun::Error::ErrAttributeNotFound, "unexpected error"); 11 | } else { 12 | panic!("expected error, but got ok"); 13 | } 14 | 15 | m.build(&[Box::new(BINDING_REQUEST), Box::new(p)])?; 16 | 17 | let mut m1 = Message::new(); 18 | m1.write(&m.raw)?; 19 | 20 | let mut p1 = PriorityAttr::default(); 21 | p1.get_from(&m1)?; 22 | 23 | assert_eq!(p1, p, "not equal"); 24 | 25 | //"IncorrectSize" 26 | { 27 | let mut m3 = Message::new(); 28 | m3.add(ATTR_PRIORITY, &[0; 100]); 29 | let mut p2 = PriorityAttr::default(); 30 | let result = p2.get_from(&m3); 31 | if let Err(err) = result { 32 | assert!(is_attr_size_invalid(&err), "should error"); 33 | } else { 34 | panic!("expected error, but got ok"); 35 | } 36 | } 37 | 38 | Ok(()) 39 | } 40 | -------------------------------------------------------------------------------- /ice/src/state/state_test.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | use crate::error::Result; 3 | 4 | #[test] 5 | fn test_connected_state_string() -> Result<()> { 6 | let tests = vec![ 7 | (ConnectionState::Unspecified, "Unspecified"), 8 | (ConnectionState::New, "New"), 9 | (ConnectionState::Checking, "Checking"), 10 | (ConnectionState::Connected, "Connected"), 11 | (ConnectionState::Completed, "Completed"), 12 | (ConnectionState::Failed, "Failed"), 13 | (ConnectionState::Disconnected, "Disconnected"), 14 | (ConnectionState::Closed, "Closed"), 15 | ]; 16 | 17 | for (connection_state, expected_string) in tests { 18 | assert_eq!( 19 | connection_state.to_string(), 20 | expected_string, 21 | "testCase: {expected_string} vs {connection_state}", 22 | ) 23 | } 24 | 25 | Ok(()) 26 | } 27 | 28 | #[test] 29 | fn test_gathering_state_string() -> Result<()> { 30 | let tests = vec![ 31 | (GatheringState::Unspecified, "unspecified"), 32 | (GatheringState::New, "new"), 33 | (GatheringState::Gathering, "gathering"), 34 | (GatheringState::Complete, "complete"), 35 | ]; 36 | 37 | for (gathering_state, expected_string) in tests { 38 | assert_eq!( 39 | gathering_state.to_string(), 40 | expected_string, 41 | "testCase: {expected_string} vs {gathering_state}", 42 | ) 43 | } 44 | 45 | Ok(()) 46 | } 47 | -------------------------------------------------------------------------------- /ice/src/tcp_type/tcp_type_test.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | use crate::error::Result; 3 | 4 | #[test] 5 | fn test_tcp_type() -> Result<()> { 6 | //assert_eq!(tcpType, TCPType::Unspecified) 7 | assert_eq!(TcpType::from("active"), TcpType::Active); 8 | assert_eq!(TcpType::from("passive"), TcpType::Passive); 9 | assert_eq!(TcpType::from("so"), TcpType::SimultaneousOpen); 10 | assert_eq!(TcpType::from("something else"), TcpType::Unspecified); 11 | 12 | assert_eq!(TcpType::Unspecified.to_string(), "unspecified"); 13 | assert_eq!(TcpType::Active.to_string(), "active"); 14 | assert_eq!(TcpType::Passive.to_string(), "passive"); 15 | assert_eq!(TcpType::SimultaneousOpen.to_string(), "so"); 16 | 17 | Ok(()) 18 | } 19 | -------------------------------------------------------------------------------- /ice/src/use_candidate/mod.rs: -------------------------------------------------------------------------------- 1 | #[cfg(test)] 2 | mod use_candidate_test; 3 | 4 | use stun::attributes::ATTR_USE_CANDIDATE; 5 | use stun::message::*; 6 | 7 | /// Represents USE-CANDIDATE attribute. 8 | #[derive(Default)] 9 | pub struct UseCandidateAttr; 10 | 11 | impl Setter for UseCandidateAttr { 12 | /// Adds USE-CANDIDATE attribute to message. 13 | fn add_to(&self, m: &mut Message) -> Result<(), stun::Error> { 14 | m.add(ATTR_USE_CANDIDATE, &[]); 15 | Ok(()) 16 | } 17 | } 18 | 19 | impl UseCandidateAttr { 20 | #[must_use] 21 | pub const fn new() -> Self { 22 | Self 23 | } 24 | 25 | /// Returns true if USE-CANDIDATE attribute is set. 26 | #[must_use] 27 | pub fn is_set(m: &Message) -> bool { 28 | let result = m.get(ATTR_USE_CANDIDATE); 29 | result.is_ok() 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /ice/src/use_candidate/use_candidate_test.rs: -------------------------------------------------------------------------------- 1 | use stun::message::BINDING_REQUEST; 2 | 3 | use super::*; 4 | use crate::error::Result; 5 | 6 | #[test] 7 | fn test_use_candidate_attr_add_to() -> Result<()> { 8 | let mut m = Message::new(); 9 | assert!(!UseCandidateAttr::is_set(&m), "should not be set"); 10 | 11 | m.build(&[Box::new(BINDING_REQUEST), Box::new(UseCandidateAttr::new())])?; 12 | 13 | let mut m1 = Message::new(); 14 | m1.write(&m.raw)?; 15 | 16 | assert!(UseCandidateAttr::is_set(&m1), "should be set"); 17 | 18 | Ok(()) 19 | } 20 | -------------------------------------------------------------------------------- /ice/src/util/util_test.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | 3 | #[tokio::test] 4 | async fn test_local_interfaces() -> Result<()> { 5 | let vnet = Arc::new(Net::new(None)); 6 | let interfaces = vnet.get_interfaces().await; 7 | let ips = local_interfaces( 8 | &vnet, 9 | &None, 10 | &None, 11 | &[NetworkType::Udp4, NetworkType::Udp6], 12 | false, 13 | ) 14 | .await; 15 | 16 | let ips_with_loopback = local_interfaces( 17 | &vnet, 18 | &None, 19 | &None, 20 | &[NetworkType::Udp4, NetworkType::Udp6], 21 | true, 22 | ) 23 | .await; 24 | assert!(ips_with_loopback.is_superset(&ips)); 25 | assert!(!ips.iter().any(|ip| ip.is_loopback())); 26 | assert!(ips_with_loopback.iter().any(|ip| ip.is_loopback())); 27 | log::info!( 28 | "interfaces: {:?}, ips: {:?}, ips_with_loopback: {:?}", 29 | interfaces, 30 | ips, 31 | ips_with_loopback 32 | ); 33 | Ok(()) 34 | } 35 | -------------------------------------------------------------------------------- /interceptor/.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | /target/ 4 | /.idea/ 5 | 6 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 7 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html 8 | Cargo.lock 9 | 10 | # These are backup files generated by rustfmt 11 | **/*.rs.bk 12 | -------------------------------------------------------------------------------- /interceptor/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "interceptor" 3 | version = "0.14.0" 4 | authors = ["Rain Liu "] 5 | edition = "2021" 6 | description = "A pure Rust implementation of Pluggable RTP/RTCP processors" 7 | license = "MIT OR Apache-2.0" 8 | documentation = "https://docs.rs/interceptor" 9 | homepage = "https://webrtc.rs" 10 | repository = "https://github.com/webrtc-rs/webrtc/tree/master/interceptor" 11 | 12 | [dependencies] 13 | util = { version = "0.11.0", path = "../util", package = "webrtc-util", default-features = false, features = ["marshal", "sync"] } 14 | rtp = { version = "0.13.0", path = "../rtp" } 15 | rtcp = { version = "0.13.0", path = "../rtcp" } 16 | srtp = { version = "0.15.0", path = "../srtp", package = "webrtc-srtp" } 17 | 18 | tokio = { version = "1.32.0", features = ["sync", "time"] } 19 | async-trait = "0.1" 20 | bytes = "1" 21 | thiserror = "1" 22 | rand = "0.8" 23 | waitgroup = "0.1" 24 | log = "0.4" 25 | portable-atomic = "1.6" 26 | 27 | [dev-dependencies] 28 | tokio-test = "0.4" 29 | chrono = "0.4.28" 30 | -------------------------------------------------------------------------------- /interceptor/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 WebRTC.rs 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 | -------------------------------------------------------------------------------- /interceptor/README.md: -------------------------------------------------------------------------------- 1 |

2 | WebRTC.rs 3 |
4 |

5 |

6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | License: MIT/Apache 2.0 23 | 24 | 25 | Discord 26 | 27 |

28 |

29 | A pure Rust implementation of Pluggable RTP/RTCP processors. Rewrite Pion Interceptor in Rust 30 |

31 | -------------------------------------------------------------------------------- /interceptor/codecov.yml: -------------------------------------------------------------------------------- 1 | codecov: 2 | require_ci_to_pass: yes 3 | max_report_age: off 4 | token: a1ee2aa3-5623-4b41-8ba8-446a6b6792df 5 | 6 | coverage: 7 | precision: 2 8 | round: down 9 | range: 50..90 10 | status: 11 | project: 12 | default: 13 | enabled: no 14 | threshold: 0.2 15 | if_not_found: success 16 | patch: 17 | default: 18 | enabled: no 19 | if_not_found: success 20 | changes: 21 | default: 22 | enabled: no 23 | if_not_found: success 24 | -------------------------------------------------------------------------------- /interceptor/doc/webrtc.rs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webrtc-rs/webrtc/f296fc7295e64804a1bd57b7eed82f61fc4210b4/interceptor/doc/webrtc.rs.png -------------------------------------------------------------------------------- /interceptor/src/error.rs: -------------------------------------------------------------------------------- 1 | use thiserror::Error; 2 | 3 | pub type Result = std::result::Result; 4 | 5 | #[derive(Error, Debug, PartialEq)] 6 | #[non_exhaustive] 7 | pub enum Error { 8 | #[error("Invalid Parent RTCP Reader")] 9 | ErrInvalidParentRtcpReader, 10 | #[error("Invalid Parent RTP Reader")] 11 | ErrInvalidParentRtpReader, 12 | #[error("Invalid Next RTP Writer")] 13 | ErrInvalidNextRtpWriter, 14 | #[error("Invalid CloseRx Channel")] 15 | ErrInvalidCloseRx, 16 | #[error("Invalid PacketRx Channel")] 17 | ErrInvalidPacketRx, 18 | #[error("IO EOF")] 19 | ErrIoEOF, 20 | #[error("Buffer is too short")] 21 | ErrShortBuffer, 22 | #[error("Invalid buffer size")] 23 | ErrInvalidSize, 24 | 25 | #[error("{0}")] 26 | Srtp(#[from] srtp::Error), 27 | #[error("{0}")] 28 | Rtcp(#[from] rtcp::Error), 29 | #[error("{0}")] 30 | Rtp(#[from] rtp::Error), 31 | #[error("{0}")] 32 | Util(#[from] util::Error), 33 | 34 | #[error("{0}")] 35 | Other(String), 36 | } 37 | 38 | /// flatten_errs flattens multiple errors into one 39 | pub fn flatten_errs(errs: Vec) -> Result<()> { 40 | if errs.is_empty() { 41 | Ok(()) 42 | } else { 43 | let errs_strs: Vec = errs.into_iter().map(|e| e.to_string()).collect(); 44 | Err(Error::Other(errs_strs.join("\n"))) 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /interceptor/src/mock/mock_builder.rs: -------------------------------------------------------------------------------- 1 | use std::sync::Arc; 2 | 3 | use crate::error::Result; 4 | use crate::{Interceptor, InterceptorBuilder}; 5 | 6 | pub type MockBuilderResult = Result>; 7 | 8 | /// MockBuilder is a mock Builder for testing. 9 | pub struct MockBuilder { 10 | pub build: Box MockBuilderResult) + Send + Sync + 'static>, 11 | } 12 | 13 | impl MockBuilder { 14 | pub fn new MockBuilderResult) + Send + Sync + 'static>(f: F) -> Self { 15 | MockBuilder { build: Box::new(f) } 16 | } 17 | } 18 | 19 | impl InterceptorBuilder for MockBuilder { 20 | fn build(&self, id: &str) -> MockBuilderResult { 21 | (self.build)(id) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /interceptor/src/mock/mock_time.rs: -------------------------------------------------------------------------------- 1 | use std::time::{Duration, SystemTime}; 2 | 3 | use util::sync::Mutex; 4 | 5 | /// MockTime is a helper to replace SystemTime::now() for testing purposes. 6 | pub struct MockTime { 7 | cur_now: Mutex, 8 | } 9 | 10 | impl Default for MockTime { 11 | fn default() -> Self { 12 | MockTime { 13 | cur_now: Mutex::new(SystemTime::UNIX_EPOCH), 14 | } 15 | } 16 | } 17 | 18 | impl MockTime { 19 | /// set_now sets the current time. 20 | pub fn set_now(&self, now: SystemTime) { 21 | let mut cur_now = self.cur_now.lock(); 22 | *cur_now = now; 23 | } 24 | 25 | /// now returns the current time. 26 | pub fn now(&self) -> SystemTime { 27 | let cur_now = self.cur_now.lock(); 28 | *cur_now 29 | } 30 | 31 | /// advance advances duration d 32 | pub fn advance(&mut self, d: Duration) { 33 | let mut cur_now = self.cur_now.lock(); 34 | *cur_now = cur_now.checked_add(d).unwrap_or(*cur_now); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /interceptor/src/mock/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod mock_builder; 2 | pub mod mock_interceptor; 3 | pub mod mock_stream; 4 | pub mod mock_time; 5 | -------------------------------------------------------------------------------- /interceptor/src/nack/mod.rs: -------------------------------------------------------------------------------- 1 | use crate::stream_info::StreamInfo; 2 | 3 | pub mod generator; 4 | pub mod responder; 5 | 6 | const UINT16SIZE_HALF: u16 = 1 << 15; 7 | 8 | fn stream_support_nack(info: &StreamInfo) -> bool { 9 | for fb in &info.rtcp_feedback { 10 | if fb.typ == "nack" && fb.parameter.is_empty() { 11 | return true; 12 | } 13 | } 14 | 15 | false 16 | } 17 | -------------------------------------------------------------------------------- /interceptor/src/registry.rs: -------------------------------------------------------------------------------- 1 | use std::sync::Arc; 2 | 3 | use crate::chain::Chain; 4 | use crate::error::Result; 5 | use crate::noop::NoOp; 6 | use crate::{Interceptor, InterceptorBuilder}; 7 | 8 | /// Registry is a collector for interceptors. 9 | #[derive(Default)] 10 | pub struct Registry { 11 | builders: Vec>, 12 | } 13 | 14 | impl Registry { 15 | pub fn new() -> Self { 16 | Registry { builders: vec![] } 17 | } 18 | 19 | /// add adds a new InterceptorBuilder to the registry. 20 | pub fn add(&mut self, builder: Box) { 21 | self.builders.push(builder); 22 | } 23 | 24 | /// build constructs a single Interceptor from an InterceptorRegistry 25 | pub fn build(&self, id: &str) -> Result> { 26 | if self.builders.is_empty() { 27 | return Ok(Arc::new(NoOp {})); 28 | } 29 | 30 | self.build_chain(id) 31 | .map(|c| Arc::new(c) as Arc) 32 | } 33 | 34 | /// build_chain constructs a non-type erased Chain from an Interceptor registry. 35 | pub fn build_chain(&self, id: &str) -> Result { 36 | if self.builders.is_empty() { 37 | return Ok(Chain::new(vec![Arc::new(NoOp {})])); 38 | } 39 | 40 | let interceptors: Result> = self.builders.iter().map(|b| b.build(id)).collect(); 41 | 42 | Ok(Chain::new(interceptors?)) 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /interceptor/src/stream_reader.rs: -------------------------------------------------------------------------------- 1 | use async_trait::async_trait; 2 | use srtp::stream::Stream; 3 | 4 | use crate::error::Result; 5 | use crate::{Attributes, RTCPReader, RTPReader}; 6 | 7 | #[async_trait] 8 | impl RTPReader for Stream { 9 | async fn read( 10 | &self, 11 | buf: &mut [u8], 12 | a: &Attributes, 13 | ) -> Result<(rtp::packet::Packet, Attributes)> { 14 | Ok((self.read_rtp(buf).await?, a.clone())) 15 | } 16 | } 17 | 18 | #[async_trait] 19 | impl RTCPReader for Stream { 20 | async fn read( 21 | &self, 22 | buf: &mut [u8], 23 | a: &Attributes, 24 | ) -> Result<(Vec>, Attributes)> { 25 | Ok((self.read_rtcp(buf).await?, a.clone())) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /interceptor/src/twcc/sender/sender_stream.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | 3 | pub(super) struct SenderStream { 4 | next_rtp_writer: Arc, 5 | next_sequence_nr: Arc, 6 | hdr_ext_id: u8, 7 | } 8 | 9 | impl SenderStream { 10 | pub(super) fn new( 11 | next_rtp_writer: Arc, 12 | next_sequence_nr: Arc, 13 | hdr_ext_id: u8, 14 | ) -> Self { 15 | SenderStream { 16 | next_rtp_writer, 17 | next_sequence_nr, 18 | hdr_ext_id, 19 | } 20 | } 21 | } 22 | 23 | /// RTPWriter is used by Interceptor.bind_local_stream. 24 | #[async_trait] 25 | impl RTPWriter for SenderStream { 26 | /// write a rtp packet 27 | async fn write(&self, pkt: &rtp::packet::Packet, a: &Attributes) -> Result { 28 | let sequence_number = self.next_sequence_nr.fetch_add(1, Ordering::SeqCst); 29 | 30 | let tcc_ext = TransportCcExtension { 31 | transport_sequence: sequence_number as u16, 32 | }; 33 | let tcc_payload = tcc_ext.marshal()?; 34 | 35 | let mut pkt = pkt.clone(); 36 | pkt.header.set_extension(self.hdr_ext_id, tcc_payload)?; 37 | 38 | self.next_rtp_writer.write(&pkt, a).await 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /mdns/.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | /target/ 4 | /.idea/ 5 | 6 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 7 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html 8 | Cargo.lock 9 | 10 | # These are backup files generated by rustfmt 11 | **/*.rs.bk 12 | -------------------------------------------------------------------------------- /mdns/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # webrtc-mdns changelog 2 | 3 | ## Unreleased 4 | 5 | ## v0.5.2 6 | 7 | * Change log level for packet reception [#366](https://github.com/webrtc-rs/webrtc/pull/366). 8 | 9 | ## v0.5.1 10 | 11 | * Increased minimum support rust version to `1.60.0`. 12 | * Increased required `webrtc-util` version to `0.7.0`. 13 | 14 | ## v0.5.0 15 | 16 | * Increased min version of `log` dependency to `0.4.16`. [#250 Fix log at ^0.4.16 to make tests compile](https://github.com/webrtc-rs/webrtc/pull/250) by [@k0nserv](https://github.com/k0nserv). 17 | * [#275 mdns: get_interface_addr_for_ip once per query](https://github.com/webrtc-rs/webrtc/pull/275) by [@melekes](https://github.com/melekes). 18 | 19 | 20 | ## Prior to 0.5.0 21 | 22 | Before 0.5.0 there was no changelog, previous changes are sometimes, but not always, available in the [GitHub Releases](https://github.com/webrtc-rs/mdns/releases). 23 | 24 | -------------------------------------------------------------------------------- /mdns/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "webrtc-mdns" 3 | version = "0.9.0" 4 | authors = ["Rain Liu "] 5 | edition = "2021" 6 | description = "A pure Rust implementation of mDNS" 7 | license = "MIT OR Apache-2.0" 8 | documentation = "https://docs.rs/webrtc-mdns" 9 | homepage = "https://webrtc.rs" 10 | repository = "https://github.com/webrtc-rs/webrtc/tree/master/mdns" 11 | 12 | [features] 13 | default = ["reuse_port"] 14 | reuse_port = [] 15 | 16 | [dependencies] 17 | util = { version = "0.11.0", path = "../util", package = "webrtc-util", default-features = false, features = ["ifaces"] } 18 | 19 | tokio = { version = "1.32.0", features = [ 20 | "fs", 21 | "io-util", 22 | "io-std", 23 | "macros", 24 | "net", 25 | "parking_lot", 26 | "rt", 27 | "rt-multi-thread", 28 | "sync", 29 | "time", 30 | ] } 31 | socket2 = { version = "0.5", features = ["all"] } 32 | log = "0.4" 33 | thiserror = "1" 34 | 35 | [dev-dependencies] 36 | env_logger = "0.11.3" 37 | chrono = "0.4.28" 38 | clap = "3" 39 | 40 | [[example]] 41 | name = "mdns_query" 42 | path = "examples/mdns_query.rs" 43 | bench = false 44 | 45 | [[example]] 46 | name = "mdns_server" 47 | path = "examples/mdns_server.rs" 48 | bench = false 49 | 50 | [[example]] 51 | name = "mdns_server_query" 52 | path = "examples/mdns_server_query.rs" 53 | bench = false 54 | -------------------------------------------------------------------------------- /mdns/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 WebRTC.rs 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 | -------------------------------------------------------------------------------- /mdns/README.md: -------------------------------------------------------------------------------- 1 |

2 | WebRTC.rs 3 |
4 |

5 |

6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | License: MIT/Apache 2.0 23 | 24 | 25 | Discord 26 | 27 |

28 |

29 | A pure Rust implementation of mDNS. Rewrite Pion mDNS in Rust 30 |

31 | -------------------------------------------------------------------------------- /mdns/codecov.yml: -------------------------------------------------------------------------------- 1 | codecov: 2 | require_ci_to_pass: yes 3 | max_report_age: off 4 | token: eb4a349b-5dd5-442b-a57c-a3de73aedf9b 5 | 6 | coverage: 7 | precision: 2 8 | round: down 9 | range: 50..90 10 | status: 11 | project: 12 | default: 13 | enabled: no 14 | threshold: 0.2 15 | if_not_found: success 16 | patch: 17 | default: 18 | enabled: no 19 | if_not_found: success 20 | changes: 21 | default: 22 | enabled: no 23 | if_not_found: success 24 | -------------------------------------------------------------------------------- /mdns/doc/webrtc.rs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webrtc-rs/webrtc/f296fc7295e64804a1bd57b7eed82f61fc4210b4/mdns/doc/webrtc.rs.png -------------------------------------------------------------------------------- /mdns/src/config.rs: -------------------------------------------------------------------------------- 1 | use std::time::Duration; 2 | 3 | // Config is used to configure a mDNS client or server. 4 | #[derive(Default, Debug)] 5 | pub struct Config { 6 | // query_interval controls how often we sends Queries until we 7 | // get a response for the requested name 8 | pub query_interval: Duration, 9 | 10 | // local_names are the names that we will generate answers for 11 | // when we get questions 12 | pub local_names: Vec, 13 | //LoggerFactory logging.LoggerFactory 14 | } 15 | -------------------------------------------------------------------------------- /mdns/src/conn/conn_test.rs: -------------------------------------------------------------------------------- 1 | #[cfg(test)] 2 | mod test { 3 | use tokio::time::timeout; 4 | 5 | use crate::config::Config; 6 | use crate::conn::*; 7 | 8 | #[tokio::test] 9 | async fn test_multiple_close() -> Result<()> { 10 | let server_a = DnsConn::server( 11 | SocketAddr::new(Ipv4Addr::new(0, 0, 0, 0).into(), 5353), 12 | Config::default(), 13 | )?; 14 | 15 | server_a.close().await?; 16 | 17 | if let Err(err) = server_a.close().await { 18 | assert_eq!(err, Error::ErrConnectionClosed); 19 | } else { 20 | panic!("expected error, but got ok"); 21 | } 22 | 23 | Ok(()) 24 | } 25 | 26 | #[tokio::test] 27 | async fn test_query_respect_timeout() -> Result<()> { 28 | let server_a = DnsConn::server( 29 | SocketAddr::new(Ipv4Addr::new(0, 0, 0, 0).into(), 5353), 30 | Config::default(), 31 | )?; 32 | 33 | let (a, b) = mpsc::channel(1); 34 | 35 | timeout(Duration::from_millis(100), a.send(())) 36 | .await 37 | .unwrap() 38 | .unwrap(); 39 | 40 | let res = server_a.query("invalid-host", b).await; 41 | assert!(res.is_err(), "server_a.query expects timeout!"); 42 | 43 | server_a.close().await?; 44 | 45 | Ok(()) 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /mdns/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![warn(rust_2018_idioms)] 2 | #![allow(dead_code)] 3 | 4 | pub mod config; 5 | pub mod conn; 6 | mod error; 7 | pub mod message; 8 | 9 | pub use error::Error; 10 | -------------------------------------------------------------------------------- /mdns/src/message/question.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashMap; 2 | use std::fmt; 3 | 4 | use super::name::*; 5 | use super::*; 6 | use crate::error::Result; 7 | 8 | // A question is a DNS query. 9 | #[derive(Default, Debug, PartialEq, Eq, Clone)] 10 | pub struct Question { 11 | pub name: Name, 12 | pub typ: DnsType, 13 | pub class: DnsClass, 14 | } 15 | 16 | impl fmt::Display for Question { 17 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 18 | write!( 19 | f, 20 | "dnsmessage.question{{Name: {}, Type: {}, Class: {}}}", 21 | self.name, self.typ, self.class 22 | ) 23 | } 24 | } 25 | 26 | impl Question { 27 | // pack appends the wire format of the question to msg. 28 | pub fn pack( 29 | &self, 30 | mut msg: Vec, 31 | compression: &mut Option>, 32 | compression_off: usize, 33 | ) -> Result> { 34 | msg = self.name.pack(msg, compression, compression_off)?; 35 | msg = self.typ.pack(msg); 36 | Ok(self.class.pack(msg)) 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /mdns/src/message/resource/a.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | use crate::message::packer::*; 3 | 4 | // An AResource is an A Resource record. 5 | #[derive(Default, Debug, Clone, PartialEq, Eq)] 6 | pub struct AResource { 7 | pub a: [u8; 4], 8 | } 9 | 10 | impl fmt::Display for AResource { 11 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 12 | write!(f, "dnsmessage.AResource{{A: {:?}}}", self.a) 13 | } 14 | } 15 | 16 | impl ResourceBody for AResource { 17 | fn real_type(&self) -> DnsType { 18 | DnsType::A 19 | } 20 | 21 | // pack appends the wire format of the AResource to msg. 22 | fn pack( 23 | &self, 24 | msg: Vec, 25 | _compression: &mut Option>, 26 | _compression_off: usize, 27 | ) -> Result> { 28 | Ok(pack_bytes(msg, &self.a)) 29 | } 30 | 31 | fn unpack(&mut self, msg: &[u8], off: usize, _length: usize) -> Result { 32 | unpack_bytes(msg, off, &mut self.a) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /mdns/src/message/resource/aaaa.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | use crate::message::packer::*; 3 | 4 | // An AAAAResource is an aaaa Resource record. 5 | #[derive(Default, Debug, Clone, PartialEq, Eq)] 6 | pub struct AaaaResource { 7 | pub aaaa: [u8; 16], 8 | } 9 | 10 | impl fmt::Display for AaaaResource { 11 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 12 | write!(f, "dnsmessage.AAAAResource{{aaaa: {:?}}}", self.aaaa) 13 | } 14 | } 15 | 16 | impl ResourceBody for AaaaResource { 17 | fn real_type(&self) -> DnsType { 18 | DnsType::Aaaa 19 | } 20 | 21 | // pack appends the wire format of the AAAAResource to msg. 22 | fn pack( 23 | &self, 24 | msg: Vec, 25 | _compression: &mut Option>, 26 | _compression_off: usize, 27 | ) -> Result> { 28 | Ok(pack_bytes(msg, &self.aaaa)) 29 | } 30 | 31 | fn unpack(&mut self, msg: &[u8], off: usize, _length: usize) -> Result { 32 | unpack_bytes(msg, off, &mut self.aaaa) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /mdns/src/message/resource/cname.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | use crate::message::name::*; 3 | 4 | // A cnameresource is a cname Resource record. 5 | #[derive(Default, Debug, Clone, PartialEq, Eq)] 6 | pub struct CnameResource { 7 | pub cname: Name, 8 | } 9 | 10 | impl fmt::Display for CnameResource { 11 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 12 | write!(f, "dnsmessage.cnameresource{{cname: {}}}", self.cname) 13 | } 14 | } 15 | 16 | impl ResourceBody for CnameResource { 17 | fn real_type(&self) -> DnsType { 18 | DnsType::Cname 19 | } 20 | 21 | // pack appends the wire format of the cnameresource to msg. 22 | fn pack( 23 | &self, 24 | msg: Vec, 25 | compression: &mut Option>, 26 | compression_off: usize, 27 | ) -> Result> { 28 | self.cname.pack(msg, compression, compression_off) 29 | } 30 | 31 | fn unpack(&mut self, msg: &[u8], off: usize, _length: usize) -> Result { 32 | self.cname.unpack(msg, off) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /mdns/src/message/resource/mx.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | use crate::error::Result; 3 | use crate::message::name::*; 4 | use crate::message::packer::*; 5 | 6 | // An MXResource is an mx Resource record. 7 | #[derive(Default, Debug, Clone, PartialEq, Eq)] 8 | pub struct MxResource { 9 | pub pref: u16, 10 | pub mx: Name, 11 | } 12 | 13 | impl fmt::Display for MxResource { 14 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 15 | write!( 16 | f, 17 | "dnsmessage.MXResource{{pref: {}, mx: {}}}", 18 | self.pref, self.mx 19 | ) 20 | } 21 | } 22 | 23 | impl ResourceBody for MxResource { 24 | fn real_type(&self) -> DnsType { 25 | DnsType::Mx 26 | } 27 | 28 | // pack appends the wire format of the MXResource to msg. 29 | fn pack( 30 | &self, 31 | mut msg: Vec, 32 | compression: &mut Option>, 33 | compression_off: usize, 34 | ) -> Result> { 35 | msg = pack_uint16(msg, self.pref); 36 | msg = self.mx.pack(msg, compression, compression_off)?; 37 | Ok(msg) 38 | } 39 | 40 | fn unpack(&mut self, msg: &[u8], off: usize, _length: usize) -> Result { 41 | let (pref, off) = unpack_uint16(msg, off)?; 42 | self.pref = pref; 43 | self.mx.unpack(msg, off) 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /mdns/src/message/resource/ns.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | use crate::error::Result; 3 | use crate::message::name::*; 4 | 5 | // An NSResource is an NS Resource record. 6 | #[derive(Default, Debug, Clone, PartialEq, Eq)] 7 | pub struct NsResource { 8 | pub ns: Name, 9 | } 10 | 11 | impl fmt::Display for NsResource { 12 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 13 | write!(f, "dnsmessage.NSResource{{NS: {}}}", self.ns) 14 | } 15 | } 16 | 17 | impl ResourceBody for NsResource { 18 | fn real_type(&self) -> DnsType { 19 | DnsType::Ns 20 | } 21 | 22 | // pack appends the wire format of the NSResource to msg. 23 | fn pack( 24 | &self, 25 | msg: Vec, 26 | compression: &mut Option>, 27 | compression_off: usize, 28 | ) -> Result> { 29 | self.ns.pack(msg, compression, compression_off) 30 | } 31 | 32 | fn unpack(&mut self, msg: &[u8], off: usize, _txt_length: usize) -> Result { 33 | self.ns.unpack(msg, off) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /mdns/src/message/resource/ptr.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | use crate::error::Result; 3 | use crate::message::name::*; 4 | 5 | // A PTRResource is a PTR Resource record. 6 | #[derive(Default, Debug, Clone, PartialEq, Eq)] 7 | pub struct PtrResource { 8 | pub ptr: Name, 9 | } 10 | 11 | impl fmt::Display for PtrResource { 12 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 13 | write!(f, "dnsmessage.PTRResource{{PTR: {}}}", self.ptr) 14 | } 15 | } 16 | 17 | impl ResourceBody for PtrResource { 18 | fn real_type(&self) -> DnsType { 19 | DnsType::Ptr 20 | } 21 | 22 | // pack appends the wire format of the PTRResource to msg. 23 | fn pack( 24 | &self, 25 | msg: Vec, 26 | compression: &mut Option>, 27 | compression_off: usize, 28 | ) -> Result> { 29 | self.ptr.pack(msg, compression, compression_off) 30 | } 31 | 32 | fn unpack(&mut self, msg: &[u8], off: usize, _length: usize) -> Result { 33 | self.ptr.unpack(msg, off) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /media/.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | /target/ 4 | /.idea/ 5 | 6 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 7 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html 8 | Cargo.lock 9 | 10 | # These are backup files generated by rustfmt 11 | **/*.rs.bk 12 | -------------------------------------------------------------------------------- /media/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # webrtc-media changelog 2 | 3 | ## Unreleased 4 | 5 | ## v0.5.0 6 | 7 | * Improve handling of padding packets in `SampleBuiler`. Prior to this `SampleBuilder` would sometimes, incorrectly, drop packets that carry media when they appeared adjacent to runs of padding packets. Contributed by [@k0nserv](https://github.com/k0nserv) in [#309](https://github.com/webrtc-rs/webrtc/pull/309) 8 | * Increased minimum support rust version to `1.60.0`. 9 | * Increased required `webrtc-util` version to `0.7.0`. 10 | 11 | ### Breaking 12 | 13 | * Introduced a new field in `Sample`, `prev_padding_packets`, that reflects the number of observed padding only packets while building the Sample. This can be use to differentiate inconsequential padding packets being dropped from those carrying media. Contributed by [@k0nserv](https://github.com/k0nserv) in [#303](https://github.com/webrtc-rs/webrtc/pull/303). 14 | 15 | ## v0.4.7 16 | 17 | * Bumped util dependency to `0.6.0`. 18 | * Bumped rtp dependency to `0.6.0`. 19 | 20 | 21 | ## Prior to 0.4.7 22 | 23 | Before 0.4.7 there was no changelog, previous changes are sometimes, but not always, available in the [GitHub Releases](https://github.com/webrtc-rs/media/releases). 24 | -------------------------------------------------------------------------------- /media/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "webrtc-media" 3 | version = "0.10.0" 4 | authors = ["Rain Liu "] 5 | edition = "2021" 6 | description = "A pure Rust implementation of WebRTC Media API" 7 | license = "MIT OR Apache-2.0" 8 | documentation = "https://docs.rs/webrtc-media" 9 | homepage = "https://webrtc.rs" 10 | repository = "https://github.com/webrtc-rs/webrtc/tree/master/media" 11 | 12 | [dependencies] 13 | rtp = { version = "0.13.0", path = "../rtp" } 14 | 15 | byteorder = "1" 16 | bytes = "1" 17 | thiserror = "1" 18 | rand = "0.8" 19 | 20 | [dev-dependencies] 21 | criterion = { version = "0.5", features = ["html_reports"] } 22 | nearly_eq = "0.2" 23 | 24 | [[bench]] 25 | name = "audio_buffer" 26 | harness = false 27 | -------------------------------------------------------------------------------- /media/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 WebRTC.rs 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 | -------------------------------------------------------------------------------- /media/README.md: -------------------------------------------------------------------------------- 1 |

2 | WebRTC.rs 3 |
4 |

5 |

6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | License: MIT/Apache 2.0 23 | 24 | 25 | Discord 26 | 27 |

28 |

29 | A pure Rust implementation of WebRTC Media. Rewrite Pion MediaDevices in Rust 30 |

31 | -------------------------------------------------------------------------------- /media/codecov.yml: -------------------------------------------------------------------------------- 1 | codecov: 2 | require_ci_to_pass: yes 3 | max_report_age: off 4 | token: 87b3c77b-91fc-48bd-8560-0c9dfdb774e8 5 | 6 | coverage: 7 | precision: 2 8 | round: down 9 | range: 50..90 10 | status: 11 | project: 12 | default: 13 | enabled: no 14 | threshold: 0.2 15 | if_not_found: success 16 | patch: 17 | default: 18 | enabled: no 19 | if_not_found: success 20 | changes: 21 | default: 22 | enabled: no 23 | if_not_found: success 24 | -------------------------------------------------------------------------------- /media/doc/webrtc.rs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webrtc-rs/webrtc/f296fc7295e64804a1bd57b7eed82f61fc4210b4/media/doc/webrtc.rs.png -------------------------------------------------------------------------------- /media/src/audio/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod buffer; 2 | mod sample; 3 | 4 | pub use sample::Sample; 5 | 6 | mod sealed { 7 | pub trait Sealed {} 8 | } 9 | -------------------------------------------------------------------------------- /media/src/io/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod h264_reader; 2 | pub mod h264_writer; 3 | use crate::error::Result; 4 | 5 | pub mod ivf_reader; 6 | pub mod ivf_writer; 7 | pub mod ogg_reader; 8 | pub mod ogg_writer; 9 | pub mod sample_builder; 10 | 11 | pub type ResetFn = Box R>; 12 | 13 | // Writer defines an interface to handle 14 | // the creation of media files 15 | pub trait Writer { 16 | // Add the content of an RTP packet to the media 17 | fn write_rtp(&mut self, pkt: &rtp::packet::Packet) -> Result<()>; 18 | // close the media 19 | // Note: close implementation must be idempotent 20 | fn close(&mut self) -> Result<()>; 21 | } 22 | -------------------------------------------------------------------------------- /media/src/video/mod.rs: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /rtcp/.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | /target/ 4 | /.idea/ 5 | 6 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 7 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html 8 | Cargo.lock 9 | 10 | # These are backup files generated by rustfmt 11 | **/*.rs.bk 12 | -------------------------------------------------------------------------------- /rtcp/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # rtcp changelog 2 | 3 | ## Unreleased 4 | 5 | ## v0.8.0 6 | 7 | * Fix over-NACK due not resetting lost_packets bitmask [\#372](https://github.com/webrtc-rs/webrtc/pull/372/). 8 | * Increased minimum support rust version to `1.60.0`. 9 | * Increased required `webrtc-util` version to `0.7.0`. 10 | 11 | ## v0.7.0 12 | 13 | * [#14 Prevent crash in RTCP NACK writing](https://github.com/webrtc-rs/rtcp/pull/14) by [@pthatcher](https://github.com/pthatcher). 14 | * Adds `IntoIterator` for `NackPair` which iterates over all the sequence numbers specified by the `NackPair`. This is similar to `packet_list` but without requiring the allocation of a Vec. Added in [#225 Add RTP Stats to stats report](https://github.com/webrtc-rs/webrtc/pull/225) by [@k0nserv](https://github.com/k0nserv). 15 | 16 | 17 | ## Prior to 0.7.0 18 | 19 | Before 0.7.0 there was no changelog, previous changes are sometimes, but not always, available in the [GitHub Releases](https://github.com/webrtc-rs/rtcp/releases). 20 | -------------------------------------------------------------------------------- /rtcp/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rtcp" 3 | version = "0.13.0" 4 | authors = ["Rain Liu ", "Michael Uti "] 5 | edition = "2021" 6 | description = "A pure Rust implementation of RTCP" 7 | license = "MIT OR Apache-2.0" 8 | documentation = "https://docs.rs/rtcp" 9 | homepage = "https://webrtc.rs" 10 | repository = "https://github.com/webrtc-rs/webrtc/tree/master/rtcp" 11 | 12 | [dependencies] 13 | util = { version = "0.11.0", path = "../util", package = "webrtc-util", default-features = false, features = ["marshal"] } 14 | 15 | bytes = "1" 16 | thiserror = "1" 17 | -------------------------------------------------------------------------------- /rtcp/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 WebRTC.rs 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 | -------------------------------------------------------------------------------- /rtcp/README.md: -------------------------------------------------------------------------------- 1 |

2 | WebRTC.rs 3 |
4 |

5 |

6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | License: MIT/Apache 2.0 23 | 24 | 25 | Discord 26 | 27 |

28 |

29 | A pure Rust implementation of RTCP. Rewrite Pion RTCP in Rust 30 |

31 | -------------------------------------------------------------------------------- /rtcp/codecov.yml: -------------------------------------------------------------------------------- 1 | codecov: 2 | require_ci_to_pass: yes 3 | max_report_age: off 4 | token: 2971c79d-6f37-4e06-924b-e2325e3c8a06 5 | 6 | coverage: 7 | precision: 2 8 | round: down 9 | range: 50..90 10 | status: 11 | project: 12 | default: 13 | enabled: no 14 | threshold: 0.2 15 | if_not_found: success 16 | patch: 17 | default: 18 | enabled: no 19 | if_not_found: success 20 | changes: 21 | default: 22 | enabled: no 23 | if_not_found: success 24 | -------------------------------------------------------------------------------- /rtcp/doc/webrtc.rs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webrtc-rs/webrtc/f296fc7295e64804a1bd57b7eed82f61fc4210b4/rtcp/doc/webrtc.rs.png -------------------------------------------------------------------------------- /rtcp/src/payload_feedbacks/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod full_intra_request; 2 | pub mod picture_loss_indication; 3 | pub mod receiver_estimated_maximum_bitrate; 4 | pub mod slice_loss_indication; 5 | -------------------------------------------------------------------------------- /rtcp/src/transport_feedbacks/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod rapid_resynchronization_request; 2 | pub mod transport_layer_cc; 3 | pub mod transport_layer_nack; 4 | -------------------------------------------------------------------------------- /rtp/.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | /target/ 4 | /.idea/ 5 | 6 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 7 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html 8 | Cargo.lock 9 | 10 | # These are backup files generated by rustfmt 11 | **/*.rs.bk 12 | -------------------------------------------------------------------------------- /rtp/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # rtp changelog 2 | 3 | ## Unreleased 4 | 5 | ## v0.6.8 6 | 7 | * Increased minimum support rust version to `1.60.0`. 8 | * Adds a new generic header extensions type `rtp::extension::HeaderExtension` which allows abstracting over all known extensions as well as custom extensions. [#336](https://github.com/webrtc-rs/webrtc/pull/336) by [@k0nserv](https://github.com/k0nserv). 9 | * Added video orientation(`urn:3gpp:video-orientation`) extension support. [#331](https://github.com/webrtc-rs/webrtc/pull/331) by [@algesten](https://github.com/algesten). 10 | * Allow RTP extensions to be serialized and deserialized via serder. [#332](https://github.com/webrtc-rs/webrtc/pull/332) by [@algesten](https://github.com/algesten). 11 | * Increased required `webrtc-util` version to `0.7.0`. 12 | 13 | ## v0.6.7 14 | 15 | * Bumped util dependency to `0.6.0`. 16 | 17 | ## Prior to 0.6.7 18 | 19 | Before 0.6.7 there was no changelog, previous changes are sometimes, but not always, available in the [GitHub Releases](https://github.com/webrtc-rs/rtp/releases). 20 | 21 | -------------------------------------------------------------------------------- /rtp/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rtp" 3 | version = "0.13.0" 4 | authors = ["Rain Liu ", "Michael Uti "] 5 | edition = "2021" 6 | description = "A pure Rust implementation of RTP" 7 | license = "MIT OR Apache-2.0" 8 | documentation = "https://docs.rs/rtp" 9 | homepage = "https://webrtc.rs" 10 | repository = "https://github.com/webrtc-rs/webrtc/tree/master/rtp" 11 | 12 | [dependencies] 13 | util = { version = "0.11.0", path = "../util", package = "webrtc-util", default-features = false, features = ["marshal"] } 14 | 15 | bytes = "1" 16 | rand = "0.8" 17 | thiserror = "1" 18 | serde = { version = "1", features = ["derive"] } 19 | portable-atomic = "1.6" 20 | 21 | memchr = "2.1.1" 22 | 23 | [dev-dependencies] 24 | chrono = "0.4.28" 25 | criterion = "0.5" 26 | 27 | [[bench]] 28 | name = "packet_bench" 29 | harness = false 30 | -------------------------------------------------------------------------------- /rtp/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 WebRTC.rs 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 | -------------------------------------------------------------------------------- /rtp/README.md: -------------------------------------------------------------------------------- 1 |

2 | WebRTC.rs 3 |
4 |

5 |

6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | License: MIT/Apache 2.0 23 | 24 | 25 | Discord 26 | 27 |

28 |

29 | A pure Rust implementation of RTP. Rewrite Pion RTP in Rust 30 |

31 | -------------------------------------------------------------------------------- /rtp/codecov.yml: -------------------------------------------------------------------------------- 1 | codecov: 2 | require_ci_to_pass: yes 3 | max_report_age: off 4 | token: cd48e18f-3916-4a20-ba56-81354d68a5d2 5 | 6 | coverage: 7 | precision: 2 8 | round: down 9 | range: 50..90 10 | status: 11 | project: 12 | default: 13 | enabled: no 14 | threshold: 0.2 15 | if_not_found: success 16 | patch: 17 | default: 18 | enabled: no 19 | if_not_found: success 20 | changes: 21 | default: 22 | enabled: no 23 | if_not_found: success 24 | -------------------------------------------------------------------------------- /rtp/doc/webrtc.rs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webrtc-rs/webrtc/f296fc7295e64804a1bd57b7eed82f61fc4210b4/rtp/doc/webrtc.rs.png -------------------------------------------------------------------------------- /rtp/src/codecs/g7xx/mod.rs: -------------------------------------------------------------------------------- 1 | #[cfg(test)] 2 | mod g7xx_test; 3 | 4 | use bytes::Bytes; 5 | 6 | use crate::error::Result; 7 | use crate::packetizer::Payloader; 8 | 9 | /// G711Payloader payloads G711 packets 10 | pub type G711Payloader = G7xxPayloader; 11 | /// G722Payloader payloads G722 packets 12 | pub type G722Payloader = G7xxPayloader; 13 | 14 | #[derive(Default, Debug, Copy, Clone)] 15 | pub struct G7xxPayloader; 16 | 17 | impl Payloader for G7xxPayloader { 18 | /// Payload fragments an G7xx packet across one or more byte arrays 19 | fn payload(&mut self, mtu: usize, payload: &Bytes) -> Result> { 20 | if payload.is_empty() || mtu == 0 { 21 | return Ok(vec![]); 22 | } 23 | 24 | let mut payload_data_remaining = payload.len(); 25 | let mut payload_data_index = 0; 26 | let mut payloads = Vec::with_capacity(payload_data_remaining / mtu); 27 | while payload_data_remaining > 0 { 28 | let current_fragment_size = std::cmp::min(mtu, payload_data_remaining); 29 | payloads.push( 30 | payload.slice(payload_data_index..payload_data_index + current_fragment_size), 31 | ); 32 | 33 | payload_data_remaining -= current_fragment_size; 34 | payload_data_index += current_fragment_size; 35 | } 36 | 37 | Ok(payloads) 38 | } 39 | 40 | fn clone_to(&self) -> Box { 41 | Box::new(*self) 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /rtp/src/codecs/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod av1; 2 | pub mod g7xx; 3 | pub mod h264; 4 | pub mod h265; 5 | pub mod opus; 6 | pub mod vp8; 7 | pub mod vp9; 8 | -------------------------------------------------------------------------------- /rtp/src/codecs/opus/mod.rs: -------------------------------------------------------------------------------- 1 | #[cfg(test)] 2 | mod opus_test; 3 | 4 | use bytes::Bytes; 5 | 6 | use crate::error::{Error, Result}; 7 | use crate::packetizer::{Depacketizer, Payloader}; 8 | 9 | #[derive(Default, Debug, Copy, Clone)] 10 | pub struct OpusPayloader; 11 | 12 | impl Payloader for OpusPayloader { 13 | fn payload(&mut self, mtu: usize, payload: &Bytes) -> Result> { 14 | if payload.is_empty() || mtu == 0 { 15 | return Ok(vec![]); 16 | } 17 | 18 | Ok(vec![payload.clone()]) 19 | } 20 | 21 | fn clone_to(&self) -> Box { 22 | Box::new(*self) 23 | } 24 | } 25 | 26 | /// OpusPacket represents the Opus header that is stored in the payload of an RTP Packet 27 | #[derive(PartialEq, Eq, Debug, Default, Clone)] 28 | pub struct OpusPacket; 29 | 30 | impl Depacketizer for OpusPacket { 31 | fn depacketize(&mut self, packet: &Bytes) -> Result { 32 | if packet.is_empty() { 33 | Err(Error::ErrShortPacket) 34 | } else { 35 | Ok(packet.clone()) 36 | } 37 | } 38 | 39 | fn is_partition_head(&self, _payload: &Bytes) -> bool { 40 | true 41 | } 42 | 43 | fn is_partition_tail(&self, _marker: bool, _payload: &Bytes) -> bool { 44 | true 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /rtp/src/extension/playout_delay_extension/playout_delay_extension_test.rs: -------------------------------------------------------------------------------- 1 | use bytes::BytesMut; 2 | 3 | use crate::error::Result; 4 | 5 | use super::*; 6 | 7 | #[test] 8 | fn test_playout_delay_extension_roundtrip() -> Result<()> { 9 | let test = PlayoutDelayExtension { 10 | max_delay: 2345, 11 | min_delay: 1234, 12 | }; 13 | 14 | let mut raw = BytesMut::with_capacity(test.marshal_size()); 15 | raw.resize(test.marshal_size(), 0); 16 | test.marshal_to(&mut raw)?; 17 | let raw = raw.freeze(); 18 | let buf = &mut raw.clone(); 19 | let out = PlayoutDelayExtension::unmarshal(buf)?; 20 | assert_eq!(test, out); 21 | 22 | Ok(()) 23 | } 24 | 25 | #[test] 26 | fn test_playout_delay_value_overflow() -> Result<()> { 27 | let test = PlayoutDelayExtension { 28 | max_delay: u16::MAX, 29 | min_delay: u16::MAX, 30 | }; 31 | 32 | let mut dst = BytesMut::with_capacity(test.marshal_size()); 33 | dst.resize(test.marshal_size(), 0); 34 | let result = test.marshal_to(&mut dst); 35 | assert!(result.is_err()); 36 | 37 | Ok(()) 38 | } 39 | -------------------------------------------------------------------------------- /rtp/src/extension/transport_cc_extension/transport_cc_extension_test.rs: -------------------------------------------------------------------------------- 1 | use bytes::{Bytes, BytesMut}; 2 | 3 | use super::*; 4 | use crate::error::Result; 5 | 6 | #[test] 7 | fn test_transport_cc_extension_too_small() -> Result<()> { 8 | let mut buf = &vec![0u8; 0][..]; 9 | let result = TransportCcExtension::unmarshal(&mut buf); 10 | assert!(result.is_err()); 11 | 12 | Ok(()) 13 | } 14 | 15 | #[test] 16 | fn test_transport_cc_extension() -> Result<()> { 17 | let raw = Bytes::from_static(&[0x00, 0x02]); 18 | let buf = &mut raw.clone(); 19 | let t1 = TransportCcExtension::unmarshal(buf)?; 20 | let t2 = TransportCcExtension { 21 | transport_sequence: 2, 22 | }; 23 | assert_eq!(t1, t2); 24 | 25 | let mut dst = BytesMut::with_capacity(t2.marshal_size()); 26 | dst.resize(t2.marshal_size(), 0); 27 | t2.marshal_to(&mut dst)?; 28 | assert_eq!(raw, dst.freeze()); 29 | 30 | Ok(()) 31 | } 32 | 33 | #[test] 34 | fn test_transport_cc_extension_extra_bytes() -> Result<()> { 35 | let mut raw = Bytes::from_static(&[0x00, 0x02, 0x00, 0xff, 0xff]); 36 | let buf = &mut raw; 37 | let t1 = TransportCcExtension::unmarshal(buf)?; 38 | let t2 = TransportCcExtension { 39 | transport_sequence: 2, 40 | }; 41 | assert_eq!(t1, t2); 42 | 43 | Ok(()) 44 | } 45 | -------------------------------------------------------------------------------- /rtp/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![warn(rust_2018_idioms)] 2 | #![allow(dead_code)] 3 | 4 | pub mod codecs; 5 | mod error; 6 | pub mod extension; 7 | pub mod header; 8 | pub mod packet; 9 | pub mod packetizer; 10 | pub mod sequence; 11 | 12 | pub use error::Error; 13 | -------------------------------------------------------------------------------- /sctp/.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | /target/ 4 | /.idea/ 5 | 6 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 7 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html 8 | Cargo.lock 9 | 10 | # These are backup files generated by rustfmt 11 | **/*.rs.bk -------------------------------------------------------------------------------- /sctp/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "webrtc-sctp" 3 | version = "0.12.0" 4 | authors = ["Rain Liu "] 5 | edition = "2021" 6 | description = "A pure Rust implementation of SCTP" 7 | license = "MIT OR Apache-2.0" 8 | documentation = "https://docs.rs/webrtc-sctp" 9 | homepage = "https://webrtc.rs" 10 | repository = "https://github.com/webrtc-rs/webrtc/tree/master/sctp" 11 | 12 | [dependencies] 13 | util = { version = "0.11.0", path = "../util", package = "webrtc-util", default-features = false, features = ["conn"] } 14 | 15 | arc-swap = "1" 16 | tokio = { version = "1.32.0", features = [ 17 | "fs", 18 | "io-util", 19 | "io-std", 20 | "macros", 21 | "net", 22 | "parking_lot", 23 | "rt", 24 | "rt-multi-thread", 25 | "sync", 26 | "time", 27 | ] } 28 | bytes = "1" 29 | rand = "0.8" 30 | crc = "3.2.1" 31 | async-trait = "0.1" 32 | log = "0.4" 33 | thiserror = "1" 34 | portable-atomic = "1.6" 35 | 36 | [dev-dependencies] 37 | tokio-test = "0.4" 38 | lazy_static = "1" 39 | env_logger = "0.11.3" 40 | chrono = "0.4.28" 41 | clap = "3" 42 | 43 | [[example]] 44 | name = "ping" 45 | path = "examples/ping.rs" 46 | bench = false 47 | 48 | [[example]] 49 | name = "pong" 50 | path = "examples/pong.rs" 51 | bench = false 52 | 53 | [lints.rust] 54 | unexpected_cfgs = { level = "warn", check-cfg = ['cfg(fuzzing)'] } 55 | -------------------------------------------------------------------------------- /sctp/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 WebRTC.rs 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 | -------------------------------------------------------------------------------- /sctp/README.md: -------------------------------------------------------------------------------- 1 |

2 | WebRTC.rs 3 |
4 |

5 |

6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | License: MIT/Apache 2.0 23 | 24 | 25 | Discord 26 | 27 |

28 |

29 | A pure Rust implementation of SCTP. Rewrite Pion SCTP in Rust 30 |

31 | -------------------------------------------------------------------------------- /sctp/codecov.yml: -------------------------------------------------------------------------------- 1 | codecov: 2 | require_ci_to_pass: yes 3 | max_report_age: off 4 | token: 9ec6d495-dfa7-4250-afeb-dbf342009340 5 | 6 | coverage: 7 | precision: 2 8 | round: down 9 | range: 50..90 10 | status: 11 | project: 12 | default: 13 | enabled: no 14 | threshold: 0.2 15 | if_not_found: success 16 | patch: 17 | default: 18 | enabled: no 19 | if_not_found: success 20 | changes: 21 | default: 22 | enabled: no 23 | if_not_found: success 24 | -------------------------------------------------------------------------------- /sctp/doc/webrtc.rs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webrtc-rs/webrtc/f296fc7295e64804a1bd57b7eed82f61fc4210b4/sctp/doc/webrtc.rs.png -------------------------------------------------------------------------------- /sctp/fuzz/.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | corpus 3 | -------------------------------------------------------------------------------- /sctp/fuzz/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "webrtc-sctp-fuzz" 3 | version = "0.0.0" 4 | authors = ["Automatically generated"] 5 | publish = false 6 | edition = "2021" 7 | 8 | [package.metadata] 9 | cargo-fuzz = true 10 | 11 | [dependencies] 12 | libfuzzer-sys = "0.4" 13 | bytes = "*" 14 | 15 | [dependencies.webrtc-sctp] 16 | path = ".." 17 | 18 | # Prevent this from interfering with workspaces 19 | [workspace] 20 | members = ["."] 21 | 22 | [[bin]] 23 | name = "packet" 24 | path = "fuzz_targets/packet.rs" 25 | test = false 26 | doc = false 27 | 28 | [[bin]] 29 | name = "param" 30 | path = "fuzz_targets/param.rs" 31 | test = false 32 | doc = false 33 | -------------------------------------------------------------------------------- /sctp/fuzz/artifacts/packet/crash-16cad30042bc4791bd62c630a780add5d1220779: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webrtc-rs/webrtc/f296fc7295e64804a1bd57b7eed82f61fc4210b4/sctp/fuzz/artifacts/packet/crash-16cad30042bc4791bd62c630a780add5d1220779 -------------------------------------------------------------------------------- /sctp/fuzz/artifacts/packet/crash-8b9b318a6b66ea23232a4e2aec91deeeca470af8: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webrtc-rs/webrtc/f296fc7295e64804a1bd57b7eed82f61fc4210b4/sctp/fuzz/artifacts/packet/crash-8b9b318a6b66ea23232a4e2aec91deeeca470af8 -------------------------------------------------------------------------------- /sctp/fuzz/artifacts/packet/crash-8d90dfc8fc34fa06f161f69617ee8f48dec434cd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webrtc-rs/webrtc/f296fc7295e64804a1bd57b7eed82f61fc4210b4/sctp/fuzz/artifacts/packet/crash-8d90dfc8fc34fa06f161f69617ee8f48dec434cd -------------------------------------------------------------------------------- /sctp/fuzz/artifacts/packet/crash-b836a20af7f8af85423dbe80565465b16bb7a16f: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webrtc-rs/webrtc/f296fc7295e64804a1bd57b7eed82f61fc4210b4/sctp/fuzz/artifacts/packet/crash-b836a20af7f8af85423dbe80565465b16bb7a16f -------------------------------------------------------------------------------- /sctp/fuzz/artifacts/packet/crash-f940d9879efc88872145955bae11ca6ad6a4c044: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webrtc-rs/webrtc/f296fc7295e64804a1bd57b7eed82f61fc4210b4/sctp/fuzz/artifacts/packet/crash-f940d9879efc88872145955bae11ca6ad6a4c044 -------------------------------------------------------------------------------- /sctp/fuzz/artifacts/param/crash-216833e417069f431d0617fb4e9f8abe6c9a6c1d: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /sctp/fuzz/artifacts/param/crash-fb1b644bc0d365ce2dc3c3ff77cd3c4cd8da528d: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webrtc-rs/webrtc/f296fc7295e64804a1bd57b7eed82f61fc4210b4/sctp/fuzz/artifacts/param/crash-fb1b644bc0d365ce2dc3c3ff77cd3c4cd8da528d -------------------------------------------------------------------------------- /sctp/fuzz/fuzz_targets/packet.rs: -------------------------------------------------------------------------------- 1 | #![no_main] 2 | use libfuzzer_sys::fuzz_target; 3 | 4 | use bytes::Bytes; 5 | use webrtc_sctp::packet::Packet; 6 | 7 | fuzz_target!(|data: &[u8]| { 8 | let bytes = Bytes::from(data.to_vec()); 9 | Packet::unmarshal(&bytes); 10 | }); 11 | -------------------------------------------------------------------------------- /sctp/fuzz/fuzz_targets/param.rs: -------------------------------------------------------------------------------- 1 | #![no_main] 2 | use libfuzzer_sys::fuzz_target; 3 | 4 | use bytes::Bytes; 5 | use webrtc_sctp::param::build_param; 6 | 7 | fuzz_target!(|data: &[u8]| { 8 | let bytes = Bytes::from(data.to_vec()); 9 | build_param(&bytes); 10 | }); 11 | -------------------------------------------------------------------------------- /sctp/src/chunk/mod.rs: -------------------------------------------------------------------------------- 1 | #[cfg(test)] 2 | mod chunk_test; 3 | 4 | pub(crate) mod chunk_abort; 5 | pub(crate) mod chunk_cookie_ack; 6 | pub(crate) mod chunk_cookie_echo; 7 | pub(crate) mod chunk_error; 8 | pub(crate) mod chunk_forward_tsn; 9 | pub(crate) mod chunk_header; 10 | pub(crate) mod chunk_heartbeat; 11 | pub(crate) mod chunk_heartbeat_ack; 12 | pub(crate) mod chunk_init; 13 | pub mod chunk_payload_data; 14 | pub(crate) mod chunk_reconfig; 15 | pub(crate) mod chunk_selective_ack; 16 | pub(crate) mod chunk_shutdown; 17 | pub(crate) mod chunk_shutdown_ack; 18 | pub(crate) mod chunk_shutdown_complete; 19 | pub(crate) mod chunk_type; 20 | pub(crate) mod chunk_unknown; 21 | 22 | use std::any::Any; 23 | use std::fmt; 24 | use std::marker::Sized; 25 | 26 | use bytes::{Bytes, BytesMut}; 27 | use chunk_header::*; 28 | 29 | use crate::error::{Error, Result}; 30 | 31 | pub(crate) trait Chunk: fmt::Display + fmt::Debug { 32 | fn header(&self) -> ChunkHeader; 33 | fn unmarshal(raw: &Bytes) -> Result 34 | where 35 | Self: Sized; 36 | fn marshal_to(&self, buf: &mut BytesMut) -> Result; 37 | fn check(&self) -> Result<()>; 38 | fn value_length(&self) -> usize; 39 | fn as_any(&self) -> &(dyn Any + Send + Sync); 40 | 41 | fn marshal(&self) -> Result { 42 | let capacity = CHUNK_HEADER_SIZE + self.value_length(); 43 | let mut buf = BytesMut::with_capacity(capacity); 44 | self.marshal_to(&mut buf)?; 45 | Ok(buf.freeze()) 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /sctp/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![warn(rust_2018_idioms)] 2 | #![allow(dead_code)] 3 | 4 | pub mod association; 5 | pub mod chunk; 6 | mod error; 7 | pub mod error_cause; 8 | pub mod packet; 9 | pub mod param; 10 | pub(crate) mod queue; 11 | pub mod stream; 12 | pub(crate) mod timer; 13 | pub(crate) mod util; 14 | 15 | pub use error::Error; 16 | 17 | #[cfg(test)] 18 | mod fuzz_artifact_test; 19 | -------------------------------------------------------------------------------- /sctp/src/param/param_random.rs: -------------------------------------------------------------------------------- 1 | use bytes::{Bytes, BytesMut}; 2 | 3 | use super::param_header::*; 4 | use super::param_type::*; 5 | use super::*; 6 | 7 | #[derive(Default, Debug, Clone, PartialEq)] 8 | pub(crate) struct ParamRandom { 9 | pub(crate) random_data: Bytes, 10 | } 11 | 12 | impl fmt::Display for ParamRandom { 13 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 14 | write!(f, "{} {:?}", self.header(), self.random_data) 15 | } 16 | } 17 | 18 | impl Param for ParamRandom { 19 | fn header(&self) -> ParamHeader { 20 | ParamHeader { 21 | typ: ParamType::Random, 22 | value_length: self.value_length() as u16, 23 | } 24 | } 25 | 26 | fn unmarshal(raw: &Bytes) -> Result { 27 | let header = ParamHeader::unmarshal(raw)?; 28 | let random_data = 29 | raw.slice(PARAM_HEADER_LENGTH..PARAM_HEADER_LENGTH + header.value_length()); 30 | Ok(ParamRandom { random_data }) 31 | } 32 | 33 | fn marshal_to(&self, buf: &mut BytesMut) -> Result { 34 | self.header().marshal_to(buf)?; 35 | buf.extend(self.random_data.clone()); 36 | Ok(buf.len()) 37 | } 38 | 39 | fn value_length(&self) -> usize { 40 | self.random_data.len() 41 | } 42 | 43 | fn clone_to(&self) -> Box { 44 | Box::new(self.clone()) 45 | } 46 | 47 | fn as_any(&self) -> &(dyn Any + Send + Sync) { 48 | self 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /sctp/src/queue/control_queue.rs: -------------------------------------------------------------------------------- 1 | use std::collections::VecDeque; 2 | 3 | use crate::packet::Packet; 4 | 5 | /// control queue 6 | pub(crate) type ControlQueue = VecDeque; 7 | -------------------------------------------------------------------------------- /sctp/src/queue/mod.rs: -------------------------------------------------------------------------------- 1 | #[cfg(test)] 2 | mod queue_test; 3 | 4 | pub(crate) mod control_queue; 5 | pub(crate) mod payload_queue; 6 | pub(crate) mod pending_queue; 7 | pub(crate) mod reassembly_queue; 8 | -------------------------------------------------------------------------------- /sctp/src/timer/mod.rs: -------------------------------------------------------------------------------- 1 | #[cfg(test)] 2 | mod timer_test; 3 | 4 | pub(crate) mod ack_timer; 5 | pub(crate) mod rtx_timer; 6 | -------------------------------------------------------------------------------- /sdp/.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | /target/ 4 | /.idea/ 5 | 6 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 7 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html 8 | Cargo.lock 9 | 10 | # These are backup files generated by rustfmt 11 | **/*.rs.bk 12 | -------------------------------------------------------------------------------- /sdp/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # sdp changelog 2 | 3 | ## Unreleased 4 | 5 | * Implement from and tryfrom string traits for SessionDescription. 6 | 7 | ## v0.5.3 8 | 9 | * Increased minimum support rust version to `1.60.0`. 10 | 11 | ## v0.5.2 12 | 13 | * [#10 update deps + loosen some requirements](https://github.com/webrtc-rs/sdp/pull/10) by [@melekes](https://github.com/melekes). 14 | 15 | ## Prior to 0.5.2 16 | 17 | Before 0.5.2 there was no changelog, previous changes are sometimes, but not always, available in the [GitHub Releases](https://github.com/webrtc-rs/sdp/releases). 18 | 19 | -------------------------------------------------------------------------------- /sdp/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "sdp" 3 | version = "0.8.0" 4 | authors = ["Rain Liu "] 5 | edition = "2021" 6 | description = "A pure Rust implementation of SDP" 7 | license = "MIT OR Apache-2.0" 8 | documentation = "https://docs.rs/sdp" 9 | homepage = "https://webrtc.rs" 10 | repository = "https://github.com/webrtc-rs/webrtc/tree/master/sdp" 11 | 12 | [dependencies] 13 | url = "2" 14 | rand = "0.8" 15 | thiserror = "1" 16 | substring = "1" 17 | 18 | [dev-dependencies] 19 | criterion = "0.5" 20 | 21 | [[bench]] 22 | name = "bench" 23 | harness = false 24 | -------------------------------------------------------------------------------- /sdp/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 WebRTC.rs 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 | -------------------------------------------------------------------------------- /sdp/README.md: -------------------------------------------------------------------------------- 1 |

2 | WebRTC.rs 3 |
4 |

5 |

6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | License: MIT/Apache 2.0 23 | 24 | 25 | Discord 26 | 27 |

28 |

29 | A pure Rust implementation of SDP. Rewrite Pion SDP in Rust 30 |

31 | -------------------------------------------------------------------------------- /sdp/codecov.yml: -------------------------------------------------------------------------------- 1 | codecov: 2 | require_ci_to_pass: yes 3 | max_report_age: off 4 | token: 40894be8-0942-482a-b7cf-e58721cff2c5 5 | 6 | coverage: 7 | precision: 2 8 | round: down 9 | range: 50..90 10 | status: 11 | project: 12 | default: 13 | enabled: no 14 | threshold: 0.2 15 | if_not_found: success 16 | patch: 17 | default: 18 | enabled: no 19 | if_not_found: success 20 | changes: 21 | default: 22 | enabled: no 23 | if_not_found: success 24 | -------------------------------------------------------------------------------- /sdp/doc/webrtc.rs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webrtc-rs/webrtc/f296fc7295e64804a1bd57b7eed82f61fc4210b4/sdp/doc/webrtc.rs.png -------------------------------------------------------------------------------- /sdp/fuzz/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | target 3 | corpus 4 | artifacts 5 | -------------------------------------------------------------------------------- /sdp/fuzz/Cargo.toml: -------------------------------------------------------------------------------- 1 | 2 | [package] 3 | name = "sdp-fuzz" 4 | version = "0.0.0" 5 | authors = ["Automatically generated"] 6 | publish = false 7 | edition = "2021" 8 | 9 | [package.metadata] 10 | cargo-fuzz = true 11 | 12 | [dependencies] 13 | libfuzzer-sys = "0.4" 14 | 15 | [dependencies.sdp] 16 | path = ".." 17 | 18 | # Prevent this from interfering with workspaces 19 | [workspace] 20 | members = ["."] 21 | 22 | [[bin]] 23 | name = "parse_session" 24 | path = "fuzz_targets/parse_session.rs" 25 | test = false 26 | doc = false 27 | -------------------------------------------------------------------------------- /sdp/fuzz/fuzz_targets/parse_session.rs: -------------------------------------------------------------------------------- 1 | #![no_main] 2 | use libfuzzer_sys::fuzz_target; 3 | 4 | fuzz_target!(|data: &[u8]| { 5 | let mut cursor = std::io::Cursor::new(data); 6 | let _session = sdp::SessionDescription::unmarshal(&mut cursor); 7 | }); 8 | -------------------------------------------------------------------------------- /sdp/src/description/mod.rs: -------------------------------------------------------------------------------- 1 | #[cfg(test)] 2 | mod description_test; 3 | 4 | pub mod common; 5 | pub mod media; 6 | pub mod session; 7 | -------------------------------------------------------------------------------- /sdp/src/direction/direction_test.rs: -------------------------------------------------------------------------------- 1 | use std::iter::Iterator; 2 | 3 | use super::*; 4 | 5 | #[test] 6 | fn test_new_direction() { 7 | let passingtests = [ 8 | ("sendrecv", Direction::SendRecv), 9 | ("sendonly", Direction::SendOnly), 10 | ("recvonly", Direction::RecvOnly), 11 | ("inactive", Direction::Inactive), 12 | ]; 13 | 14 | let failingtests = ["", "notadirection"]; 15 | 16 | for (i, u) in passingtests.iter().enumerate() { 17 | let dir = Direction::new(u.0); 18 | assert!(u.1 == dir, "{}: {}", i, u.0); 19 | } 20 | for &u in failingtests.iter() { 21 | let dir = Direction::new(u); 22 | assert!(dir == Direction::Unspecified); 23 | } 24 | } 25 | 26 | #[test] 27 | fn test_direction_string() { 28 | let tests = [ 29 | (Direction::Unspecified, DIRECTION_UNSPECIFIED_STR), 30 | (Direction::SendRecv, "sendrecv"), 31 | (Direction::SendOnly, "sendonly"), 32 | (Direction::RecvOnly, "recvonly"), 33 | (Direction::Inactive, "inactive"), 34 | ]; 35 | 36 | for (i, u) in tests.iter().enumerate() { 37 | assert!(u.1 == u.0.to_string(), "{}: {}", i, u.1); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /sdp/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![warn(rust_2018_idioms)] 2 | #![allow(dead_code)] 3 | 4 | pub mod description; 5 | pub mod direction; 6 | pub mod extmap; 7 | pub mod util; 8 | 9 | mod error; 10 | pub(crate) mod lexer; 11 | 12 | pub use description::media::MediaDescription; 13 | pub use description::session::SessionDescription; 14 | pub use error::Error; 15 | -------------------------------------------------------------------------------- /srtp/.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | /target/ 4 | /.idea/ 5 | 6 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 7 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html 8 | Cargo.lock 9 | 10 | # These are backup files generated by rustfmt 11 | **/*.rs.bk 12 | -------------------------------------------------------------------------------- /srtp/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # webrtc-srtp changelog 2 | 3 | ## Unreleased 4 | 5 | ## v0.9.1 6 | 7 | * Increased minimum support rust version to `1.60.0`. 8 | * Increased required `webrtc-util` version to `0.7.0`. 9 | 10 | 11 | ## v0.9.0 12 | 13 | * [#8 update deps + loosen some requirements](https://github.com/webrtc-rs/srtp/pull/8) by [@melekes](https://github.com/melekes). 14 | * Increased min version of `log` dependency to `0.4.16`. [#250 Fix log at ^0.4.16 to make tests compile](https://github.com/webrtc-rs/webrtc/pull/250) by [@k0nserv](https://github.com/k0nserv). 15 | 16 | ## Prior to 0.8.9 17 | 18 | Before 0.8.9 there was no changelog, previous changes are sometimes, but not always, available in the [GitHub Releases](https://github.com/webrtc-rs/srtp/releases). 19 | 20 | -------------------------------------------------------------------------------- /srtp/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 WebRTC.rs 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 | -------------------------------------------------------------------------------- /srtp/README.md: -------------------------------------------------------------------------------- 1 |

2 | WebRTC.rs 3 |
4 |

5 |

6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | License: MIT/Apache 2.0 23 | 24 | 25 | Discord 26 | 27 |

28 |

29 | A pure Rust implementation of SRTP. Rewrite Pion SRTP in Rust 30 |

31 | -------------------------------------------------------------------------------- /srtp/codecov.yml: -------------------------------------------------------------------------------- 1 | codecov: 2 | require_ci_to_pass: yes 3 | max_report_age: off 4 | token: d65de923-7c3d-4836-8d9a-5183b356be4f 5 | 6 | coverage: 7 | precision: 2 8 | round: down 9 | range: 50..90 10 | status: 11 | project: 12 | default: 13 | enabled: no 14 | threshold: 0.2 15 | if_not_found: success 16 | patch: 17 | default: 18 | enabled: no 19 | if_not_found: success 20 | changes: 21 | default: 22 | enabled: no 23 | if_not_found: success 24 | -------------------------------------------------------------------------------- /srtp/doc/webrtc.rs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webrtc-rs/webrtc/f296fc7295e64804a1bd57b7eed82f61fc4210b4/srtp/doc/webrtc.rs.png -------------------------------------------------------------------------------- /srtp/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![warn(rust_2018_idioms)] 2 | #![allow(dead_code)] 3 | 4 | mod cipher; 5 | pub mod config; 6 | pub mod context; 7 | mod error; 8 | mod key_derivation; 9 | pub mod option; 10 | pub mod protection_profile; 11 | pub mod session; 12 | pub mod stream; 13 | 14 | pub use error::Error; 15 | -------------------------------------------------------------------------------- /srtp/src/option.rs: -------------------------------------------------------------------------------- 1 | use util::replay_detector::*; 2 | 3 | pub type ContextOption = Box Box) + Send + Sync>; 4 | 5 | pub(crate) const MAX_SEQUENCE_NUMBER: u16 = 65535; 6 | pub(crate) const MAX_SRTCP_INDEX: usize = 0x7FFFFFFF; 7 | 8 | /// srtp_replay_protection sets SRTP replay protection window size. 9 | pub fn srtp_replay_protection(window_size: usize) -> ContextOption { 10 | Box::new(move || -> Box { 11 | Box::new(WrappedSlidingWindowDetector::new( 12 | window_size, 13 | MAX_SEQUENCE_NUMBER as u64, 14 | )) 15 | }) 16 | } 17 | 18 | /// Sets SRTCP replay protection window size. 19 | pub fn srtcp_replay_protection(window_size: usize) -> ContextOption { 20 | Box::new(move || -> Box { 21 | Box::new(WrappedSlidingWindowDetector::new( 22 | window_size, 23 | MAX_SRTCP_INDEX as u64, 24 | )) 25 | }) 26 | } 27 | 28 | /// srtp_no_replay_protection disables SRTP replay protection. 29 | pub fn srtp_no_replay_protection() -> ContextOption { 30 | Box::new(|| -> Box { Box::::default() }) 31 | } 32 | 33 | /// srtcp_no_replay_protection disables SRTCP replay protection. 34 | pub fn srtcp_no_replay_protection() -> ContextOption { 35 | Box::new(|| -> Box { Box::::default() }) 36 | } 37 | -------------------------------------------------------------------------------- /stun/.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | /target/ 4 | /.idea/ 5 | 6 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 7 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html 8 | Cargo.lock 9 | 10 | # These are backup files generated by rustfmt 11 | **/*.rs.bk 12 | -------------------------------------------------------------------------------- /stun/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # webrtc-stun changelog 2 | 3 | ## Unreleased 4 | 5 | ## v0.4.4 6 | 7 | * Increased minimum support rust version to `1.60.0`. 8 | * Increased required `webrtc-util` version to `0.7.0`. 9 | 10 | ## v0.4.3 11 | 12 | * [#9 update deps + loosen some requirements](https://github.com/webrtc-rs/stun/pull/9) by [@melekes](https://github.com/melekes). 13 | 14 | ## Prior to 0.4.3 15 | 16 | Before 0.4.3 there was no changelog, previous changes are sometimes, but not always, available in the [GitHub Releases](https://github.com/webrtc-rs/stun/releases). 17 | -------------------------------------------------------------------------------- /stun/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "stun" 3 | version = "0.8.0" 4 | authors = ["Rain Liu "] 5 | edition = "2021" 6 | description = "A pure Rust implementation of STUN" 7 | license = "MIT OR Apache-2.0" 8 | documentation = "https://docs.rs/stun" 9 | homepage = "https://webrtc.rs" 10 | repository = "https://github.com/webrtc-rs/webrtc/tree/master/stun" 11 | 12 | [features] 13 | default = [] 14 | bench = [] 15 | 16 | [dependencies] 17 | util = { version = "0.11.0", path = "../util", package = "webrtc-util", default-features = false, features = ["conn"] } 18 | 19 | tokio = { version = "1.32.0", features = [ 20 | "fs", 21 | "io-util", 22 | "io-std", 23 | "macros", 24 | "net", 25 | "parking_lot", 26 | "rt", 27 | "rt-multi-thread", 28 | "sync", 29 | "time", 30 | ] } 31 | lazy_static = "1" 32 | url = "2" 33 | rand = "0.8" 34 | base64 = "0.22.1" 35 | subtle = "2.4" 36 | crc = "3" 37 | ring = "0.17.14" 38 | md-5 = "0.10" 39 | thiserror = "1" 40 | 41 | [dev-dependencies] 42 | tokio-test = "0.4" 43 | clap = "3" 44 | criterion = "0.5" 45 | 46 | [[bench]] 47 | name = "bench" 48 | harness = false 49 | 50 | [[example]] 51 | name = "stun_client" 52 | path = "examples/stun_client.rs" 53 | bench = false 54 | 55 | [[example]] 56 | name = "stun_decode" 57 | path = "examples/stun_decode.rs" 58 | bench = false 59 | -------------------------------------------------------------------------------- /stun/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 WebRTC.rs 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 | -------------------------------------------------------------------------------- /stun/README.md: -------------------------------------------------------------------------------- 1 |

2 | WebRTC.rs 3 |
4 |

5 |

6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | License: MIT/Apache 2.0 23 | 24 | 25 | Discord 26 | 27 |

28 |

29 | A pure Rust implementation of STUN. Rewrite Pion STUN in Rust 30 |

31 | -------------------------------------------------------------------------------- /stun/codecov.yml: -------------------------------------------------------------------------------- 1 | codecov: 2 | require_ci_to_pass: yes 3 | max_report_age: off 4 | token: 5ed548cd-073b-4748-b584-ca2d637027bf 5 | 6 | coverage: 7 | precision: 2 8 | round: down 9 | range: 50..90 10 | status: 11 | project: 12 | default: 13 | enabled: no 14 | threshold: 0.2 15 | if_not_found: success 16 | patch: 17 | default: 18 | enabled: no 19 | if_not_found: success 20 | changes: 21 | default: 22 | enabled: no 23 | if_not_found: success 24 | -------------------------------------------------------------------------------- /stun/doc/webrtc.rs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webrtc-rs/webrtc/f296fc7295e64804a1bd57b7eed82f61fc4210b4/stun/doc/webrtc.rs.png -------------------------------------------------------------------------------- /stun/examples/stun_decode.rs: -------------------------------------------------------------------------------- 1 | use base64::prelude::BASE64_STANDARD; 2 | use base64::Engine; 3 | use clap::{App, Arg}; 4 | use stun::message::Message; 5 | 6 | fn main() { 7 | let mut app = App::new("STUN decode") 8 | .version("0.1.0") 9 | .author("Jtplouffe ") 10 | .about("An example of STUN decode") 11 | .arg( 12 | Arg::with_name("FULLHELP") 13 | .help("Prints more detailed help information") 14 | .long("fullhelp"), 15 | ) 16 | .arg( 17 | Arg::with_name("data") 18 | .required_unless("FULLHELP") 19 | .takes_value(true) 20 | .index(1) 21 | .help("base64 encoded message, e.g. 'AAEAHCESpEJML0JTQWsyVXkwcmGALwAWaHR0cDovL2xvY2FsaG9zdDozMDAwLwAA'"), 22 | ); 23 | 24 | let matches = app.clone().get_matches(); 25 | 26 | if matches.is_present("FULLHELP") { 27 | app.print_long_help().unwrap(); 28 | std::process::exit(0); 29 | } 30 | 31 | let encoded_data = matches.value_of("data").unwrap(); 32 | let decoded_data = match BASE64_STANDARD.decode(encoded_data) { 33 | Ok(d) => d, 34 | Err(e) => panic!("Unable to decode base64 value: {e}"), 35 | }; 36 | 37 | let mut message = Message::new(); 38 | message.raw = decoded_data; 39 | 40 | match message.decode() { 41 | Ok(_) => println!("{message}"), 42 | Err(e) => panic!("Unable to decode message: {e}"), 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /stun/src/client/client_test.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | 3 | #[test] 4 | fn ensure_client_settings_is_send() { 5 | let client = ClientSettings::default(); 6 | 7 | ensure_send(client); 8 | } 9 | 10 | fn ensure_send(_: T) {} 11 | 12 | //TODO: add more client tests 13 | -------------------------------------------------------------------------------- /stun/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![warn(rust_2018_idioms)] 2 | #![allow(dead_code)] 3 | 4 | #[macro_use] 5 | extern crate lazy_static; 6 | 7 | pub mod addr; 8 | pub mod agent; 9 | pub mod attributes; 10 | pub mod checks; 11 | pub mod client; 12 | mod error; 13 | pub mod error_code; 14 | pub mod fingerprint; 15 | pub mod integrity; 16 | pub mod message; 17 | pub mod textattrs; 18 | pub mod uattrs; 19 | pub mod uri; 20 | pub mod xoraddr; 21 | 22 | // IANA assigned ports for "stun" protocol. 23 | pub const DEFAULT_PORT: u16 = 3478; 24 | pub const DEFAULT_TLS_PORT: u16 = 5349; 25 | 26 | pub use error::Error; 27 | -------------------------------------------------------------------------------- /stun/src/uattrs/uattrs_test.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | 3 | #[test] 4 | fn test_unknown_attributes() -> Result<()> { 5 | let mut m = Message::new(); 6 | let a = UnknownAttributes(vec![ATTR_DONT_FRAGMENT, ATTR_CHANNEL_NUMBER]); 7 | assert_eq!( 8 | a.to_string(), 9 | "DONT-FRAGMENT, CHANNEL-NUMBER", 10 | "bad String:{a}" 11 | ); 12 | assert_eq!( 13 | UnknownAttributes(vec![]).to_string(), 14 | "", 15 | "bad blank string" 16 | ); 17 | 18 | a.add_to(&mut m)?; 19 | 20 | //"GetFrom" 21 | { 22 | let mut attrs = UnknownAttributes(Vec::with_capacity(10)); 23 | attrs.get_from(&m)?; 24 | for i in 0..a.0.len() { 25 | assert_eq!(a.0[i], attrs.0[i], "expected {} != {}", a.0[i], attrs.0[i]); 26 | } 27 | let mut m_blank = Message::new(); 28 | let result = attrs.get_from(&m_blank); 29 | assert!(result.is_err(), "should error"); 30 | 31 | m_blank.add(ATTR_UNKNOWN_ATTRIBUTES, &[1, 2, 3]); 32 | let result = attrs.get_from(&m_blank); 33 | assert!(result.is_err(), "should error"); 34 | } 35 | 36 | Ok(()) 37 | } 38 | -------------------------------------------------------------------------------- /turn/.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | /target/ 4 | /.idea/ 5 | 6 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 7 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html 8 | Cargo.lock 9 | 10 | # These are backup files generated by rustfmt 11 | **/*.rs.bk 12 | -------------------------------------------------------------------------------- /turn/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 WebRTC.rs 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 | -------------------------------------------------------------------------------- /turn/README.md: -------------------------------------------------------------------------------- 1 |

2 | WebRTC.rs 3 |
4 |

5 |

6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | License: MIT/Apache 2.0 23 | 24 | 25 | Discord 26 | 27 |

28 |

29 | A pure Rust implementation of TURN. Rewrite Pion TURN in Rust 30 |

31 | -------------------------------------------------------------------------------- /turn/codecov.yml: -------------------------------------------------------------------------------- 1 | codecov: 2 | require_ci_to_pass: yes 3 | max_report_age: off 4 | token: 640e45ed-ce83-43e1-9eee-473aa65dc136 5 | 6 | coverage: 7 | precision: 2 8 | round: down 9 | range: 50..90 10 | status: 11 | project: 12 | default: 13 | enabled: no 14 | threshold: 0.2 15 | if_not_found: success 16 | patch: 17 | default: 18 | enabled: no 19 | if_not_found: success 20 | changes: 21 | default: 22 | enabled: no 23 | if_not_found: success 24 | -------------------------------------------------------------------------------- /turn/doc/webrtc.rs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webrtc-rs/webrtc/f296fc7295e64804a1bd57b7eed82f61fc4210b4/turn/doc/webrtc.rs.png -------------------------------------------------------------------------------- /turn/src/client/periodic_timer/periodic_timer_test.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | use crate::error::Result; 3 | 4 | struct DummyPeriodicTimerTimeoutHandler; 5 | 6 | #[async_trait] 7 | impl PeriodicTimerTimeoutHandler for DummyPeriodicTimerTimeoutHandler { 8 | async fn on_timeout(&mut self, id: TimerIdRefresh) { 9 | assert_eq!(id, TimerIdRefresh::Perms); 10 | } 11 | } 12 | 13 | #[tokio::test] 14 | async fn test_periodic_timer() -> Result<()> { 15 | let timer_id = TimerIdRefresh::Perms; 16 | let rt = PeriodicTimer::new(timer_id, Duration::from_millis(50)); 17 | let dummy1 = Arc::new(Mutex::new(DummyPeriodicTimerTimeoutHandler {})); 18 | let dummy2 = Arc::clone(&dummy1); 19 | 20 | assert!(!rt.is_running().await, "should not be running yet"); 21 | 22 | let ok = rt.start(dummy1).await; 23 | assert!(ok, "should be true"); 24 | assert!(rt.is_running().await, "should be running"); 25 | 26 | tokio::time::sleep(Duration::from_millis(100)).await; 27 | 28 | let ok = rt.start(dummy2).await; 29 | assert!(!ok, "start again is noop"); 30 | 31 | tokio::time::sleep(Duration::from_millis(120)).await; 32 | rt.stop().await; 33 | 34 | assert!(!rt.is_running().await, "should not be running"); 35 | 36 | Ok(()) 37 | } 38 | -------------------------------------------------------------------------------- /turn/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![warn(rust_2018_idioms)] 2 | #![allow(dead_code)] 3 | #![recursion_limit = "256"] 4 | 5 | pub mod allocation; 6 | pub mod auth; 7 | pub mod client; 8 | mod error; 9 | pub mod proto; 10 | pub mod relay; 11 | pub mod server; 12 | 13 | pub use error::Error; 14 | -------------------------------------------------------------------------------- /turn/src/proto/data.rs: -------------------------------------------------------------------------------- 1 | #[cfg(test)] 2 | mod data_test; 3 | 4 | use stun::attributes::*; 5 | use stun::message::*; 6 | 7 | /// `Data` represents `DATA` attribute. 8 | /// 9 | /// The `DATA` attribute is present in all Send and Data indications. The 10 | /// value portion of this attribute is variable length and consists of 11 | /// the application data (that is, the data that would immediately follow 12 | /// the UDP header if the data was been sent directly between the client 13 | /// and the peer). 14 | /// 15 | /// [RFC 5766 Section 14.4](https://www.rfc-editor.org/rfc/rfc5766#section-14.4). 16 | #[derive(Default, Debug, PartialEq, Eq)] 17 | pub struct Data(pub Vec); 18 | 19 | impl Setter for Data { 20 | /// Adds `DATA` to message. 21 | fn add_to(&self, m: &mut Message) -> Result<(), stun::Error> { 22 | m.add(ATTR_DATA, &self.0); 23 | Ok(()) 24 | } 25 | } 26 | 27 | impl Getter for Data { 28 | /// Decodes `DATA` from message. 29 | fn get_from(&mut self, m: &Message) -> Result<(), stun::Error> { 30 | self.0 = m.get(ATTR_DATA)?; 31 | Ok(()) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /turn/src/proto/data/data_test.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | 3 | #[test] 4 | fn test_data_add_to() -> Result<(), stun::Error> { 5 | let mut m = Message::new(); 6 | let d = Data(vec![1, 2, 33, 44, 0x13, 0xaf]); 7 | d.add_to(&mut m)?; 8 | m.write_header(); 9 | 10 | //"GetFrom" 11 | { 12 | let mut decoded = Message::new(); 13 | decoded.write(&m.raw)?; 14 | 15 | let mut data_decoded = Data::default(); 16 | data_decoded.get_from(&decoded)?; 17 | assert_eq!(data_decoded, d); 18 | 19 | //"HandleErr" 20 | { 21 | let m = Message::new(); 22 | let mut handle = Data::default(); 23 | if let Err(err) = handle.get_from(&m) { 24 | assert_eq!( 25 | stun::Error::ErrAttributeNotFound, 26 | err, 27 | "{err} should be not found" 28 | ); 29 | } 30 | } 31 | } 32 | Ok(()) 33 | } 34 | -------------------------------------------------------------------------------- /turn/src/proto/dontfrag.rs: -------------------------------------------------------------------------------- 1 | #[cfg(test)] 2 | mod dontfrag_test; 3 | 4 | use stun::attributes::*; 5 | use stun::message::*; 6 | 7 | /// `DontFragmentAttr` represents `DONT-FRAGMENT` attribute. 8 | #[derive(Debug, Default, PartialEq, Eq)] 9 | pub struct DontFragmentAttr; 10 | 11 | impl Setter for DontFragmentAttr { 12 | /// Adds `DONT-FRAGMENT` attribute to message. 13 | fn add_to(&self, m: &mut Message) -> Result<(), stun::Error> { 14 | m.add(ATTR_DONT_FRAGMENT, &[]); 15 | Ok(()) 16 | } 17 | } 18 | 19 | impl Getter for DontFragmentAttr { 20 | /// Returns true if `DONT-FRAGMENT` attribute is set. 21 | fn get_from(&mut self, m: &Message) -> Result<(), stun::Error> { 22 | let _ = m.get(ATTR_DONT_FRAGMENT)?; 23 | Ok(()) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /turn/src/proto/dontfrag/dontfrag_test.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | 3 | #[test] 4 | fn test_dont_fragment_false() -> Result<(), stun::Error> { 5 | let mut dont_fragment = DontFragmentAttr; 6 | 7 | let mut m = Message::new(); 8 | m.write_header(); 9 | assert!(dont_fragment.get_from(&m).is_err(), "should not be set"); 10 | 11 | Ok(()) 12 | } 13 | 14 | #[test] 15 | fn test_dont_fragment_add_to() -> Result<(), stun::Error> { 16 | let mut dont_fragment = DontFragmentAttr; 17 | 18 | let mut m = Message::new(); 19 | dont_fragment.add_to(&mut m)?; 20 | m.write_header(); 21 | 22 | let mut decoded = Message::new(); 23 | decoded.write(&m.raw)?; 24 | assert!(dont_fragment.get_from(&m).is_ok(), "should be set"); 25 | 26 | Ok(()) 27 | } 28 | -------------------------------------------------------------------------------- /turn/src/proto/peeraddr/peeraddr_test.rs: -------------------------------------------------------------------------------- 1 | use std::net::Ipv4Addr; 2 | 3 | use super::*; 4 | 5 | #[test] 6 | fn test_peer_address() -> Result<(), stun::Error> { 7 | // Simple tests because already tested in stun. 8 | let a = PeerAddress { 9 | ip: IpAddr::V4(Ipv4Addr::new(111, 11, 1, 2)), 10 | port: 333, 11 | }; 12 | 13 | assert_eq!(a.to_string(), "111.11.1.2:333", "invalid string"); 14 | 15 | let mut m = Message::new(); 16 | a.add_to(&mut m)?; 17 | m.write_header(); 18 | 19 | let mut decoded = Message::new(); 20 | decoded.write(&m.raw)?; 21 | 22 | let mut a_got = PeerAddress::default(); 23 | a_got.get_from(&decoded)?; 24 | 25 | Ok(()) 26 | } 27 | -------------------------------------------------------------------------------- /turn/src/proto/relayaddr/relayaddr_test.rs: -------------------------------------------------------------------------------- 1 | use std::net::Ipv4Addr; 2 | 3 | use super::*; 4 | 5 | #[test] 6 | fn test_relayed_address() -> Result<(), stun::Error> { 7 | // Simple tests because already tested in stun. 8 | let a = RelayedAddress { 9 | ip: IpAddr::V4(Ipv4Addr::new(111, 11, 1, 2)), 10 | port: 333, 11 | }; 12 | 13 | assert_eq!(a.to_string(), "111.11.1.2:333", "invalid string"); 14 | 15 | let mut m = Message::new(); 16 | a.add_to(&mut m)?; 17 | m.write_header(); 18 | 19 | let mut decoded = Message::new(); 20 | decoded.write(&m.raw)?; 21 | 22 | let mut a_got = RelayedAddress::default(); 23 | a_got.get_from(&decoded)?; 24 | 25 | Ok(()) 26 | } 27 | -------------------------------------------------------------------------------- /turn/src/relay/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod relay_none; 2 | pub mod relay_range; 3 | pub mod relay_static; 4 | 5 | use std::net::SocketAddr; 6 | use std::sync::Arc; 7 | 8 | use async_trait::async_trait; 9 | use util::Conn; 10 | 11 | use crate::error::Result; 12 | 13 | /// `RelayAddressGenerator` is used to generate a Relay Address when creating an allocation. 14 | /// You can use one of the provided ones or provide your own. 15 | #[async_trait] 16 | pub trait RelayAddressGenerator { 17 | /// Confirms that this is properly initialized 18 | fn validate(&self) -> Result<()>; 19 | 20 | /// Allocates a Relay Address 21 | async fn allocate_conn( 22 | &self, 23 | use_ipv4: bool, 24 | requested_port: u16, 25 | ) -> Result<(Arc, SocketAddr)>; 26 | } 27 | -------------------------------------------------------------------------------- /turn/src/relay/relay_none.rs: -------------------------------------------------------------------------------- 1 | use async_trait::async_trait; 2 | use util::vnet::net::*; 3 | 4 | use super::*; 5 | use crate::error::*; 6 | 7 | /// `RelayAddressGeneratorNone` returns the listener with no modifications. 8 | pub struct RelayAddressGeneratorNone { 9 | /// `address` is passed to Listen/ListenPacket when creating the Relay. 10 | pub address: String, 11 | pub net: Arc, 12 | } 13 | 14 | #[async_trait] 15 | impl RelayAddressGenerator for RelayAddressGeneratorNone { 16 | fn validate(&self) -> Result<()> { 17 | if self.address.is_empty() { 18 | Err(Error::ErrListeningAddressInvalid) 19 | } else { 20 | Ok(()) 21 | } 22 | } 23 | 24 | async fn allocate_conn( 25 | &self, 26 | use_ipv4: bool, 27 | requested_port: u16, 28 | ) -> Result<(Arc, SocketAddr)> { 29 | let addr = self 30 | .net 31 | .resolve_addr(use_ipv4, &format!("{}:{}", self.address, requested_port)) 32 | .await?; 33 | let conn = self.net.bind(addr).await?; 34 | let relay_addr = conn.local_addr()?; 35 | Ok((conn, relay_addr)) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /util/.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | /target/ 4 | /.idea/ 5 | 6 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 7 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html 8 | Cargo.lock 9 | 10 | # These are backup files generated by rustfmt 11 | **/*.rs.bk 12 | -------------------------------------------------------------------------------- /util/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # webrtc-util changelog 2 | 3 | ## v0.7.0 4 | 5 | ### Breaking changes 6 | 7 | * Make functions non-async [#338](https://github.com/webrtc-rs/webrtc/pull/338): 8 | - `Bridge`: 9 | - `drop_next_nwrites`; 10 | - `reorder_next_nwrites`. 11 | - `Conn`: 12 | - `local_addr`; 13 | - `remote_addr`. 14 | 15 | 16 | ## v0.6.0 17 | 18 | * Increase min version of `log` dependency to `0.4.16`. [#250 Fix log at ^0.4.16 to make tests compile](https://github.com/webrtc-rs/webrtc/pull/250) by [@k0nserv](https://github.com/k0nserv). 19 | * Increased minimum support rust version to `1.60.0`. 20 | 21 | ## Prior to 0.6.0 22 | 23 | Before 0.6.0 there was no changelog, previous changes are sometimes, but not always, available in the [GitHub Releases](https://github.com/webrtc-rs/util/releases). 24 | 25 | -------------------------------------------------------------------------------- /util/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 WebRTC.rs 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 | -------------------------------------------------------------------------------- /util/README.md: -------------------------------------------------------------------------------- 1 |

2 | WebRTC.rs 3 |
4 |

5 |

6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | License: MIT/Apache 2.0 23 | 24 | 25 | Discord 26 | 27 |

28 |

29 | Utilities for WebRTC.rs stack. Rewrite Pion Util/Transport in Rust 30 |

31 | -------------------------------------------------------------------------------- /util/codecov.yml: -------------------------------------------------------------------------------- 1 | codecov: 2 | require_ci_to_pass: yes 3 | max_report_age: off 4 | token: 5dbbc458-896e-486d-af8e-96fc2fbbbcff 5 | 6 | coverage: 7 | precision: 2 8 | round: down 9 | range: 50..90 10 | status: 11 | project: 12 | default: 13 | enabled: no 14 | threshold: 0.2 15 | if_not_found: success 16 | patch: 17 | default: 18 | enabled: no 19 | if_not_found: success 20 | changes: 21 | default: 22 | enabled: no 23 | if_not_found: success 24 | -------------------------------------------------------------------------------- /util/doc/webrtc.rs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webrtc-rs/webrtc/f296fc7295e64804a1bd57b7eed82f61fc4210b4/util/doc/webrtc.rs.png -------------------------------------------------------------------------------- /util/examples/display-interfaces.rs: -------------------------------------------------------------------------------- 1 | use std::error::Error; 2 | 3 | use webrtc_util::ifaces::ifaces; 4 | 5 | fn main() -> Result<(), Box> { 6 | let interfaces = ifaces()?; 7 | for (index, interface) in interfaces.iter().enumerate() { 8 | println!("{index} {interface:?}"); 9 | } 10 | Ok(()) 11 | } 12 | -------------------------------------------------------------------------------- /util/src/conn/conn_pipe_test.rs: -------------------------------------------------------------------------------- 1 | use super::conn_pipe::*; 2 | use super::*; 3 | 4 | #[tokio::test] 5 | async fn test_pipe() -> Result<()> { 6 | let (c1, c2) = pipe(); 7 | let mut b1 = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; 8 | let n = c1.send(&b1).await?; 9 | assert_eq!(n, 10); 10 | 11 | let mut b2 = vec![133; 100]; 12 | let n = c2.recv(&mut b2).await?; 13 | assert_eq!(n, 10); 14 | assert_eq!(&b2[..n], &b1[..]); 15 | 16 | let n = c2.send(&b2[..10]).await?; 17 | assert_eq!(n, 10); 18 | let n = c2.send(&b2[..5]).await?; 19 | assert_eq!(n, 5); 20 | 21 | let n = c1.recv(&mut b1).await?; 22 | assert_eq!(n, 10); 23 | let n = c1.recv(&mut b1).await?; 24 | assert_eq!(n, 5); 25 | 26 | Ok(()) 27 | } 28 | -------------------------------------------------------------------------------- /util/src/conn/conn_test.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | 3 | #[tokio::test] 4 | async fn test_conn_lookup_host() -> Result<()> { 5 | let stun_serv_addr = "stun1.l.google.com:19302"; 6 | 7 | if let Ok(ipv4_addr) = lookup_host(true, stun_serv_addr).await { 8 | assert!( 9 | ipv4_addr.is_ipv4(), 10 | "expected ipv4 but got ipv6: {ipv4_addr}" 11 | ); 12 | } 13 | 14 | if let Ok(ipv6_addr) = lookup_host(false, stun_serv_addr).await { 15 | assert!( 16 | ipv6_addr.is_ipv6(), 17 | "expected ipv6 but got ipv4: {ipv6_addr}" 18 | ); 19 | } 20 | 21 | Ok(()) 22 | } 23 | -------------------------------------------------------------------------------- /util/src/conn/conn_udp.rs: -------------------------------------------------------------------------------- 1 | use tokio::net::UdpSocket; 2 | 3 | use super::*; 4 | 5 | #[async_trait] 6 | impl Conn for UdpSocket { 7 | async fn connect(&self, addr: SocketAddr) -> Result<()> { 8 | Ok(self.connect(addr).await?) 9 | } 10 | 11 | async fn recv(&self, buf: &mut [u8]) -> Result { 12 | Ok(self.recv(buf).await?) 13 | } 14 | 15 | async fn recv_from(&self, buf: &mut [u8]) -> Result<(usize, SocketAddr)> { 16 | Ok(self.recv_from(buf).await?) 17 | } 18 | 19 | async fn send(&self, buf: &[u8]) -> Result { 20 | Ok(self.send(buf).await?) 21 | } 22 | 23 | async fn send_to(&self, buf: &[u8], target: SocketAddr) -> Result { 24 | Ok(self.send_to(buf, target).await?) 25 | } 26 | 27 | fn local_addr(&self) -> Result { 28 | Ok(self.local_addr()?) 29 | } 30 | 31 | fn remote_addr(&self) -> Option { 32 | None 33 | } 34 | 35 | async fn close(&self) -> Result<()> { 36 | Ok(()) 37 | } 38 | 39 | fn as_any(&self) -> &(dyn std::any::Any + Send + Sync) { 40 | self 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /util/src/ifaces/ffi/mod.rs: -------------------------------------------------------------------------------- 1 | #[cfg(target_family = "windows")] 2 | mod windows; 3 | #[cfg(target_family = "windows")] 4 | pub use self::windows::ifaces; 5 | 6 | #[cfg(target_family = "unix")] 7 | mod unix; 8 | #[cfg(target_family = "unix")] 9 | pub use self::unix::ifaces; 10 | -------------------------------------------------------------------------------- /util/src/ifaces/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod ffi; 2 | pub use ffi::ifaces; 3 | 4 | #[derive(PartialEq, Eq, Debug, Clone)] 5 | pub enum NextHop { 6 | Broadcast(::std::net::SocketAddr), 7 | Destination(::std::net::SocketAddr), 8 | } 9 | 10 | #[derive(PartialEq, Eq, Debug, Clone)] 11 | pub enum Kind { 12 | Packet, 13 | Link, 14 | Ipv4, 15 | Ipv6, 16 | Unknow(i32), 17 | } 18 | 19 | #[derive(Debug, Clone)] 20 | pub struct Interface { 21 | pub name: String, 22 | pub kind: Kind, 23 | pub addr: Option<::std::net::SocketAddr>, 24 | pub mask: Option<::std::net::SocketAddr>, 25 | pub hop: Option, 26 | } 27 | -------------------------------------------------------------------------------- /util/src/marshal/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod exact_size_buf; 2 | 3 | use bytes::{Buf, Bytes, BytesMut}; 4 | 5 | use crate::error::{Error, Result}; 6 | 7 | pub trait MarshalSize { 8 | fn marshal_size(&self) -> usize; 9 | } 10 | 11 | pub trait Marshal: MarshalSize { 12 | fn marshal_to(&self, buf: &mut [u8]) -> Result; 13 | 14 | fn marshal(&self) -> Result { 15 | let l = self.marshal_size(); 16 | let mut buf = BytesMut::with_capacity(l); 17 | buf.resize(l, 0); 18 | let n = self.marshal_to(&mut buf)?; 19 | if n != l { 20 | Err(Error::Other(format!( 21 | "marshal_to output size {n}, but expect {l}" 22 | ))) 23 | } else { 24 | Ok(buf.freeze()) 25 | } 26 | } 27 | } 28 | 29 | pub trait Unmarshal: MarshalSize { 30 | fn unmarshal(buf: &mut B) -> Result 31 | where 32 | Self: Sized, 33 | B: Buf; 34 | } 35 | -------------------------------------------------------------------------------- /util/src/vnet/chunk_queue.rs: -------------------------------------------------------------------------------- 1 | #[cfg(test)] 2 | mod chunk_queue_test; 3 | 4 | use std::collections::VecDeque; 5 | 6 | use tokio::sync::RwLock; 7 | 8 | use super::chunk::*; 9 | 10 | #[derive(Default)] 11 | pub(crate) struct ChunkQueue { 12 | chunks: RwLock>>, 13 | max_size: usize, // 0 or negative value: unlimited 14 | } 15 | 16 | impl ChunkQueue { 17 | pub(crate) fn new(max_size: usize) -> Self { 18 | ChunkQueue { 19 | chunks: RwLock::new(VecDeque::new()), 20 | max_size, 21 | } 22 | } 23 | 24 | pub(crate) async fn push(&self, c: Box) -> bool { 25 | let mut chunks = self.chunks.write().await; 26 | 27 | if self.max_size > 0 && chunks.len() >= self.max_size { 28 | false // dropped 29 | } else { 30 | chunks.push_back(c); 31 | true 32 | } 33 | } 34 | 35 | pub(crate) async fn pop(&self) -> Option> { 36 | let mut chunks = self.chunks.write().await; 37 | chunks.pop_front() 38 | } 39 | 40 | pub(crate) async fn peek(&self) -> Option> { 41 | let chunks = self.chunks.read().await; 42 | chunks.front().map(|chunk| chunk.clone_to()) 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /util/src/vnet/chunk_queue/chunk_queue_test.rs: -------------------------------------------------------------------------------- 1 | use std::net::SocketAddr; 2 | use std::str::FromStr; 3 | 4 | use super::*; 5 | use crate::error::Result; 6 | 7 | const DEMO_IP: &str = "1.2.3.4"; 8 | 9 | #[tokio::test] 10 | async fn test_chunk_queue() -> Result<()> { 11 | let c: Box = Box::new(ChunkUdp::new( 12 | SocketAddr::from_str("192.188.0.2:1234")?, 13 | SocketAddr::from_str(&(DEMO_IP.to_owned() + ":5678"))?, 14 | )); 15 | 16 | let q = ChunkQueue::new(0); 17 | 18 | let d = q.peek().await; 19 | assert!(d.is_none(), "should return none"); 20 | 21 | let ok = q.push(c.clone_to()).await; 22 | assert!(ok, "should succeed"); 23 | 24 | let d = q.pop().await; 25 | assert!(d.is_some(), "should succeed"); 26 | if let Some(d) = d { 27 | assert_eq!(c.to_string(), d.to_string(), "should be the same"); 28 | } 29 | 30 | let d = q.pop().await; 31 | assert!(d.is_none(), "should fail"); 32 | 33 | let q = ChunkQueue::new(1); 34 | let ok = q.push(c.clone_to()).await; 35 | assert!(ok, "should succeed"); 36 | 37 | let ok = q.push(c.clone_to()).await; 38 | assert!(!ok, "should fail"); 39 | 40 | let d = q.peek().await; 41 | assert!(d.is_some(), "should succeed"); 42 | if let Some(d) = d { 43 | assert_eq!(c.to_string(), d.to_string(), "should be the same"); 44 | } 45 | 46 | Ok(()) 47 | } 48 | -------------------------------------------------------------------------------- /util/src/vnet/interface.rs: -------------------------------------------------------------------------------- 1 | use std::net::SocketAddr; 2 | 3 | use ipnet::*; 4 | 5 | use crate::error::*; 6 | 7 | #[derive(Debug, Clone, Default)] 8 | pub struct Interface { 9 | pub(crate) name: String, 10 | pub(crate) addrs: Vec, 11 | } 12 | 13 | impl Interface { 14 | pub fn new(name: String, addrs: Vec) -> Self { 15 | Interface { name, addrs } 16 | } 17 | 18 | pub fn add_addr(&mut self, addr: IpNet) { 19 | self.addrs.push(addr); 20 | } 21 | 22 | pub fn name(&self) -> &str { 23 | &self.name 24 | } 25 | pub fn addrs(&self) -> &[IpNet] { 26 | &self.addrs 27 | } 28 | 29 | pub fn convert(addr: SocketAddr, mask: Option) -> Result { 30 | if let Some(mask) = mask { 31 | Ok(IpNet::with_netmask(addr.ip(), mask.ip()).map_err(|_| Error::ErrInvalidMask)?) 32 | } else { 33 | Ok(IpNet::new(addr.ip(), if addr.is_ipv4() { 32 } else { 128 }) 34 | .expect("ipv4 should always work with prefix 32 and ipv6 with prefix 128")) 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /util/src/vnet/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod chunk; 2 | pub(crate) mod chunk_queue; 3 | pub(crate) mod conn; 4 | pub(crate) mod conn_map; 5 | pub mod interface; 6 | pub mod nat; 7 | pub mod net; 8 | pub(crate) mod resolver; 9 | pub mod router; 10 | -------------------------------------------------------------------------------- /webrtc/src/api/api_test.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | 3 | #[test] 4 | fn test_new_api() -> Result<()> { 5 | let mut s = SettingEngine::default(); 6 | s.detach_data_channels(); 7 | let mut m = MediaEngine::default(); 8 | m.register_default_codecs()?; 9 | 10 | let api = APIBuilder::new() 11 | .with_setting_engine(s) 12 | .with_media_engine(m) 13 | .build(); 14 | 15 | assert!( 16 | api.setting_engine.detach.data_channels, 17 | "Failed to set settings engine" 18 | ); 19 | assert!( 20 | !api.media_engine.audio_codecs.is_empty(), 21 | "Failed to set media engine" 22 | ); 23 | 24 | Ok(()) 25 | } 26 | -------------------------------------------------------------------------------- /webrtc/src/data_channel/data_channel_message.rs: -------------------------------------------------------------------------------- 1 | use bytes::Bytes; 2 | 3 | /// DataChannelMessage represents a message received from the 4 | /// data channel. IsString will be set to true if the incoming 5 | /// message is of the string type. Otherwise the message is of 6 | /// a binary type. 7 | #[derive(Default, Debug, Clone)] 8 | pub struct DataChannelMessage { 9 | pub is_string: bool, 10 | pub data: Bytes, 11 | } 12 | -------------------------------------------------------------------------------- /webrtc/src/data_channel/data_channel_parameters.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | 3 | /// DataChannelParameters describes the configuration of the DataChannel. 4 | #[derive(Default, Debug, Clone, Serialize, Deserialize)] 5 | pub struct DataChannelParameters { 6 | pub label: String, 7 | pub protocol: String, 8 | pub ordered: bool, 9 | pub max_packet_life_time: Option, 10 | pub max_retransmits: Option, 11 | pub negotiated: Option, 12 | } 13 | -------------------------------------------------------------------------------- /webrtc/src/dtls_transport/dtls_fingerprint.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | 3 | /// DTLSFingerprint specifies the hash function algorithm and certificate 4 | /// fingerprint as described in [RFC 4572]. 5 | /// 6 | /// ## Specifications 7 | /// 8 | /// * [W3C] 9 | /// 10 | /// [W3C]: https://w3c.github.io/webrtc-pc/#rtcdtlsfingerprint 11 | /// [RFC 4572]: https://tools.ietf.org/html/rfc4572 12 | #[derive(Default, Debug, Clone, Serialize, Deserialize)] 13 | pub struct RTCDtlsFingerprint { 14 | /// Algorithm specifies one of the the hash function algorithms defined in 15 | /// the 'Hash function Textual Names' registry. 16 | pub algorithm: String, 17 | 18 | /// Value specifies the value of the certificate fingerprint in lowercase 19 | /// hex string as expressed utilizing the syntax of 'fingerprint' in 20 | /// . 21 | pub value: String, 22 | } 23 | -------------------------------------------------------------------------------- /webrtc/src/dtls_transport/dtls_parameters.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | 3 | use super::dtls_fingerprint::*; 4 | use super::dtls_role::*; 5 | 6 | /// DTLSParameters holds information relating to DTLS configuration. 7 | #[derive(Default, Debug, Clone, Serialize, Deserialize)] 8 | pub struct DTLSParameters { 9 | pub role: DTLSRole, 10 | pub fingerprints: Vec, 11 | } 12 | -------------------------------------------------------------------------------- /webrtc/src/ice_transport/ice_candidate_pair.rs: -------------------------------------------------------------------------------- 1 | use std::fmt; 2 | 3 | use crate::ice_transport::ice_candidate::*; 4 | 5 | /// ICECandidatePair represents an ICE Candidate pair 6 | /// 7 | /// ## Specifications 8 | /// 9 | /// * [MDN] 10 | /// 11 | /// [MDN]: https://developer.mozilla.org/en-US/docs/Web/API/RTCIceCandidatePair 12 | #[derive(Default, Debug, Clone, PartialEq, Eq)] 13 | pub struct RTCIceCandidatePair { 14 | stats_id: String, 15 | local: RTCIceCandidate, 16 | remote: RTCIceCandidate, 17 | } 18 | 19 | impl fmt::Display for RTCIceCandidatePair { 20 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 21 | write!(f, "(local) {} <-> (remote) {}", self.local, self.remote) 22 | } 23 | } 24 | 25 | impl RTCIceCandidatePair { 26 | fn stats_id(local_id: &str, remote_id: &str) -> String { 27 | format!("{local_id}-{remote_id}") 28 | } 29 | 30 | /// returns an initialized ICECandidatePair 31 | /// for the given pair of ICECandidate instances 32 | pub fn new(local: RTCIceCandidate, remote: RTCIceCandidate) -> Self { 33 | let stats_id = Self::stats_id(&local.stats_id, &remote.stats_id); 34 | RTCIceCandidatePair { 35 | stats_id, 36 | local, 37 | remote, 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /webrtc/src/ice_transport/ice_parameters.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | 3 | /// ICEParameters includes the ICE username fragment 4 | /// and password and other ICE-related parameters. 5 | /// 6 | /// ## Specifications 7 | /// 8 | /// * [MDN] 9 | /// * [W3C] 10 | /// 11 | /// [MDN]: https://developer.mozilla.org/en-US/docs/Web/API/RTCIceParameters 12 | /// [W3C]: https://w3c.github.io/webrtc-pc/#rtciceparameters 13 | #[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] 14 | pub struct RTCIceParameters { 15 | pub username_fragment: String, 16 | pub password: String, 17 | pub ice_lite: bool, 18 | } 19 | -------------------------------------------------------------------------------- /webrtc/src/peer_connection/offer_answer_options.rs: -------------------------------------------------------------------------------- 1 | /// AnswerOptions structure describes the options used to control the answer 2 | /// creation process. 3 | #[derive(Default, Debug, PartialEq, Eq, Copy, Clone)] 4 | pub struct RTCAnswerOptions { 5 | /// voice_activity_detection allows the application to provide information 6 | /// about whether it wishes voice detection feature to be enabled or disabled. 7 | pub voice_activity_detection: bool, 8 | } 9 | 10 | /// OfferOptions structure describes the options used to control the offer 11 | /// creation process 12 | /// 13 | /// ## Specifications 14 | /// 15 | /// * [W3C] 16 | /// 17 | /// [W3C]: https://w3c.github.io/webrtc-pc/#dictionary-rtcofferoptions-members 18 | #[derive(Default, Debug, PartialEq, Eq, Copy, Clone)] 19 | pub struct RTCOfferOptions { 20 | /// voice_activity_detection allows the application to provide information 21 | /// about whether it wishes voice detection feature to be enabled or disabled. 22 | pub voice_activity_detection: bool, 23 | 24 | /// ice_restart forces the underlying ice gathering process to be restarted. 25 | /// When this value is true, the generated description will have ICE 26 | /// credentials that are different from the current credentials 27 | pub ice_restart: bool, 28 | } 29 | -------------------------------------------------------------------------------- /webrtc/src/peer_connection/operation/operation_test.rs: -------------------------------------------------------------------------------- 1 | use tokio::sync::Mutex; 2 | 3 | use super::*; 4 | use crate::error::Result; 5 | 6 | #[tokio::test] 7 | async fn test_operations_enqueue() -> Result<()> { 8 | let ops = Operations::new(); 9 | for _ in 0..100 { 10 | let results = Arc::new(Mutex::new(vec![0; 16])); 11 | for k in 0..16 { 12 | let r = Arc::clone(&results); 13 | ops.enqueue(Operation::new( 14 | move || { 15 | let r2 = Arc::clone(&r); 16 | Box::pin(async move { 17 | let mut r3 = r2.lock().await; 18 | r3[k] += k * k; 19 | r3[k] == 225 20 | }) 21 | }, 22 | "test_operations_enqueue", 23 | )) 24 | .await?; 25 | } 26 | 27 | ops.done().await; 28 | let expected = vec![ 29 | 0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196, 450, 30 | ]; 31 | { 32 | let r = results.lock().await; 33 | assert_eq!(r.len(), expected.len()); 34 | assert_eq!(&*r, &expected); 35 | } 36 | } 37 | 38 | Ok(()) 39 | } 40 | 41 | #[tokio::test] 42 | async fn test_operations_done() -> Result<()> { 43 | let ops = Operations::new(); 44 | ops.done().await; 45 | 46 | Ok(()) 47 | } 48 | -------------------------------------------------------------------------------- /webrtc/src/peer_connection/policy/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod bundle_policy; 2 | pub mod ice_transport_policy; 3 | pub mod rtcp_mux_policy; 4 | pub mod sdp_semantics; 5 | -------------------------------------------------------------------------------- /webrtc/src/sctp_transport/sctp_transport_capabilities.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | 3 | /// SCTPTransportCapabilities indicates the capabilities of the SCTPTransport. 4 | #[derive(Debug, PartialEq, Eq, Copy, Clone, Serialize, Deserialize)] 5 | pub struct SCTPTransportCapabilities { 6 | pub max_message_size: u32, 7 | } 8 | -------------------------------------------------------------------------------- /webrtc/src/stats/stats_collector.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashMap; 2 | 3 | use util::sync::Mutex; 4 | 5 | use super::StatsReportType; 6 | 7 | #[derive(Debug, Default)] 8 | pub struct StatsCollector { 9 | pub(crate) reports: Mutex>, 10 | } 11 | 12 | impl StatsCollector { 13 | pub(crate) fn new() -> Self { 14 | StatsCollector { 15 | ..Default::default() 16 | } 17 | } 18 | 19 | pub(crate) fn insert(&self, id: String, stats: StatsReportType) { 20 | let mut reports = self.reports.lock(); 21 | reports.insert(id, stats); 22 | } 23 | 24 | pub(crate) fn merge(&self, stats: HashMap) { 25 | let mut reports = self.reports.lock(); 26 | reports.extend(stats) 27 | } 28 | 29 | pub(crate) fn into_reports(self) -> HashMap { 30 | self.reports.into_inner() 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /webrtc/src/track/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod track_local; 2 | pub mod track_remote; 3 | 4 | use std::sync::Arc; 5 | 6 | use interceptor::stream_info::StreamInfo; 7 | use interceptor::{RTCPReader, RTPReader}; 8 | use track_remote::*; 9 | 10 | pub(crate) const RTP_OUTBOUND_MTU: usize = 1200; 11 | pub(crate) const RTP_PAYLOAD_TYPE_BITMASK: u8 = 0x7F; 12 | 13 | #[derive(Clone)] 14 | pub(crate) struct TrackStream { 15 | pub(crate) stream_info: Option, 16 | pub(crate) rtp_read_stream: Option>, 17 | pub(crate) rtp_interceptor: Option>, 18 | pub(crate) rtcp_read_stream: Option>, 19 | pub(crate) rtcp_interceptor: Option>, 20 | } 21 | 22 | /// TrackStreams maintains a mapping of RTP/RTCP streams to a specific track 23 | /// a RTPReceiver may contain multiple streams if we are dealing with Simulcast 24 | #[derive(Clone)] 25 | pub(crate) struct TrackStreams { 26 | pub(crate) track: Arc, 27 | pub(crate) stream: TrackStream, 28 | pub(crate) repair_stream: TrackStream, 29 | } 30 | --------------------------------------------------------------------------------