From 974826800f19a0c9b0db9eacb0909e073f58f0aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Haibo=20Chen=28=E9=99=88=E6=B5=B7=E5=8D=9A=29?= <495810242@qq.com> Date: Mon, 26 May 2025 17:48:53 +0800 Subject: [PATCH] update pion/webrtc to v4. v7.0.34 (#4359) To enable H.265 support for the WebRTC protocol, upgrade the pion/webrtc library to version 4. --------- Co-authored-by: john Co-authored-by: winlin --- trunk/3rdparty/srs-bench/gb28181/ingester.go | 11 +- trunk/3rdparty/srs-bench/go.mod | 47 +- trunk/3rdparty/srs-bench/go.sum | 187 +- trunk/3rdparty/srs-bench/janus/ingester.go | 8 +- trunk/3rdparty/srs-bench/janus/player.go | 11 +- trunk/3rdparty/srs-bench/janus/publisher.go | 11 +- trunk/3rdparty/srs-bench/janus/util.go | 10 +- trunk/3rdparty/srs-bench/srs/ingester.go | 8 +- trunk/3rdparty/srs-bench/srs/player.go | 10 +- trunk/3rdparty/srs-bench/srs/publisher.go | 2 +- trunk/3rdparty/srs-bench/srs/rtc_test.go | 4 +- trunk/3rdparty/srs-bench/srs/util.go | 25 +- .../vendor/github.com/davecgh/go-spew/LICENSE | 15 - .../github.com/davecgh/go-spew/spew/bypass.go | 145 - .../davecgh/go-spew/spew/bypasssafe.go | 38 - .../github.com/davecgh/go-spew/spew/common.go | 341 - .../github.com/davecgh/go-spew/spew/config.go | 306 - .../github.com/davecgh/go-spew/spew/doc.go | 211 - .../github.com/davecgh/go-spew/spew/dump.go | 509 -- .../github.com/davecgh/go-spew/spew/format.go | 419 -- .../github.com/davecgh/go-spew/spew/spew.go | 148 - .../vendor/github.com/google/uuid/.travis.yml | 9 - .../github.com/google/uuid/CHANGELOG.md | 41 + .../github.com/google/uuid/CONTRIBUTING.md | 16 + .../vendor/github.com/google/uuid/README.md | 10 +- .../vendor/github.com/google/uuid/hash.go | 6 + .../vendor/github.com/google/uuid/node_js.go | 2 +- .../vendor/github.com/google/uuid/time.go | 21 +- .../vendor/github.com/google/uuid/uuid.go | 89 +- .../vendor/github.com/google/uuid/version6.go | 56 + .../vendor/github.com/google/uuid/version7.go | 104 + .../github.com/ossrs/go-oryx-lib/LICENSE | 2 +- .../github.com/pion/datachannel/.gitignore | 3 + .../github.com/pion/datachannel/.golangci.yml | 48 +- .../{dtls/v2 => datachannel}/.goreleaser.yml | 0 .../github.com/pion/datachannel/AUTHORS.txt | 17 - .../github.com/pion/datachannel/DESIGN.md | 20 - .../github.com/pion/datachannel/LICENSE | 20 +- .../github.com/pion/datachannel/README.md | 15 +- .../github.com/pion/datachannel/codecov.yml | 2 + .../pion/datachannel/datachannel.go | 38 +- .../github.com/pion/datachannel/errors.go | 3 + .../github.com/pion/datachannel/message.go | 19 + .../pion/datachannel/message_channel_ack.go | 9 +- .../pion/datachannel/message_channel_open.go | 26 +- .../github.com/pion/datachannel/renovate.json | 25 +- .../github.com/pion/dtls/v2/AUTHORS.txt | 57 - .../vendor/github.com/pion/dtls/v2/conn.go | 1032 --- .../vendor/github.com/pion/dtls/v2/errors.go | 157 - .../tls_ecdhe_ecdsa_with_aes_128_ccm.go | 14 - .../tls_ecdhe_ecdsa_with_aes_128_ccm8.go | 14 - .../ciphersuite/tls_psk_with_aes_128_ccm.go | 14 - .../ciphersuite/tls_psk_with_aes_128_ccm8.go | 14 - .../ciphersuite/tls_psk_with_aes_256_ccm8.go | 14 - .../dtls/v2/pkg/crypto/ciphersuite/cbc.go | 177 - .../dtls/v2/pkg/protocol/extension/errors.go | 20 - .../dtls/v2/pkg/protocol/handshake/errors.go | 28 - .../v2/pkg/protocol/recordlayer/errors.go | 19 - .../pion/dtls/{v2 => v3}/.editorconfig | 0 .../pion/dtls/{v2 => v3}/.gitignore | 0 .../github.com/pion/dtls/v3/.golangci.yml | 138 + .../pion/{ice/v2 => dtls/v3}/.goreleaser.yml | 0 .../github.com/pion/dtls/{v2 => v3}/LICENSE | 0 .../github.com/pion/dtls/{v2 => v3}/README.md | 6 +- .../pion/dtls/{v2 => v3}/certificate.go | 14 +- .../pion/dtls/{v2 => v3}/cipher_suite.go | 91 +- .../dtls/{v2 => v3}/cipher_suite_go114.go | 6 +- .../pion/dtls/{v2 => v3}/codecov.yml | 0 .../dtls/{v2 => v3}/compression_method.go | 2 +- .../github.com/pion/dtls/{v2 => v3}/config.go | 104 +- .../vendor/github.com/pion/dtls/v3/conn.go | 1330 ++++ .../github.com/pion/dtls/v3/connection_id.go | 105 + .../github.com/pion/dtls/{v2 => v3}/crypto.go | 116 +- .../github.com/pion/dtls/{v2 => v3}/dtls.go | 0 .../vendor/github.com/pion/dtls/v3/errors.go | 227 + .../pion/dtls/{v2 => v3}/errors_errno.go | 0 .../pion/dtls/{v2 => v3}/errors_noerrno.go | 0 .../github.com/pion/dtls/{v2 => v3}/flight.go | 2 +- .../pion/dtls/{v2 => v3}/flight0handler.go | 67 +- .../pion/dtls/{v2 => v3}/flight1handler.go | 86 +- .../pion/dtls/{v2 => v3}/flight2handler.go | 25 +- .../pion/dtls/{v2 => v3}/flight3handler.go | 162 +- .../pion/dtls/{v2 => v3}/flight4bhandler.go | 61 +- .../pion/dtls/{v2 => v3}/flight4handler.go | 179 +- .../pion/dtls/{v2 => v3}/flight5bhandler.go | 25 +- .../pion/dtls/{v2 => v3}/flight5handler.go | 111 +- .../pion/dtls/{v2 => v3}/flight6handler.go | 27 +- .../pion/dtls/{v2 => v3}/flighthandler.go | 18 +- .../pion/dtls/{v2 => v3}/fragment_buffer.go | 34 +- .../pion/dtls/{v2 => v3}/handshake_cache.go | 39 +- .../pion/dtls/{v2 => v3}/handshaker.go | 206 +- .../internal/ciphersuite/aes_128_ccm.go | 18 +- .../internal/ciphersuite/aes_256_ccm.go | 18 +- .../internal/ciphersuite/aes_ccm.go | 47 +- .../internal/ciphersuite/ciphersuite.go | 28 +- .../tls_ecdhe_ecdsa_with_aes_128_ccm.go | 21 + .../tls_ecdhe_ecdsa_with_aes_128_ccm8.go | 21 + ...tls_ecdhe_ecdsa_with_aes_128_gcm_sha256.go | 46 +- .../tls_ecdhe_ecdsa_with_aes_256_cbc_sha.go | 38 +- ...tls_ecdhe_ecdsa_with_aes_256_gcm_sha384.go | 8 +- .../tls_ecdhe_psk_with_aes_128_cbc_sha256.go | 38 +- .../tls_ecdhe_rsa_with_aes_128_gcm_sha256.go | 8 +- .../tls_ecdhe_rsa_with_aes_256_cbc_sha.go | 8 +- .../tls_ecdhe_rsa_with_aes_256_gcm_sha384.go | 8 +- .../tls_psk_with_aes_128_cbc_sha256.go | 38 +- .../ciphersuite/tls_psk_with_aes_128_ccm.go | 21 + .../ciphersuite/tls_psk_with_aes_128_ccm8.go | 21 + .../tls_psk_with_aes_128_gcm_sha256.go | 12 +- .../ciphersuite/tls_psk_with_aes_256_ccm8.go | 21 + .../ciphersuite/types/authentication_type.go | 4 +- .../types/key_exchange_algorithm.go | 2 +- .../dtls/{v2 => v3}/internal/closer/closer.go | 16 +- .../pion/dtls/v3/internal/net/buffer.go | 242 + .../dtls/v3/internal/net/udp/packet_conn.go | 413 ++ .../dtls/{v2 => v3}/internal/util/util.go | 19 +- .../pion/dtls/{v2 => v3}/listener.go | 30 +- .../github.com/pion/dtls/{v2 => v3}/packet.go | 5 +- .../dtls/{v2 => v3}/pkg/crypto/ccm/ccm.go | 33 +- .../dtls/v3/pkg/crypto/ciphersuite/cbc.go | 250 + .../{v2 => v3}/pkg/crypto/ciphersuite/ccm.go | 60 +- .../pkg/crypto/ciphersuite/ciphersuite.go | 55 +- .../{v2 => v3}/pkg/crypto/ciphersuite/gcm.go | 49 +- .../clientcertificate/client_certificate.go | 4 +- .../pkg/crypto/elliptic/elliptic.go | 16 +- .../pkg/crypto/fingerprint/fingerprint.go | 2 +- .../{v2 => v3}/pkg/crypto/fingerprint/hash.go | 4 +- .../dtls/{v2 => v3}/pkg/crypto/hash/hash.go | 17 +- .../dtls/{v2 => v3}/pkg/crypto/prf/prf.go | 42 +- .../pkg/crypto/signature/signature.go | 4 +- .../pkg/crypto/signaturehash/errors.go | 1 + .../pkg/crypto/signaturehash/signaturehash.go | 23 +- .../github.com/pion/dtls/v3/pkg/net/net.go | 111 + .../{v2 => v3}/pkg/protocol/alert/alert.go | 19 +- .../pkg/protocol/application_data.go | 7 +- .../pkg/protocol/change_cipher_spec.go | 6 +- .../pkg/protocol/compression_method.go | 12 +- .../dtls/{v2 => v3}/pkg/protocol/content.go | 5 +- .../dtls/{v2 => v3}/pkg/protocol/errors.go | 25 +- .../{v2 => v3}/pkg/protocol/extension/alpn.go | 19 +- .../pkg/protocol/extension/connection_id.go | 61 + .../dtls/v3/pkg/protocol/extension/errors.go | 38 + .../pkg/protocol/extension/extension.go | 22 +- .../protocol/extension/renegotiation_info.go | 7 +- .../pkg/protocol/extension/server_name.go | 10 +- .../extension/srtp_protection_profile.go | 8 + .../extension/supported_elliptic_curves.go | 15 +- .../extension/supported_point_formats.go | 22 +- .../supported_signature_algorithms.go | 18 +- .../protocol/extension/use_master_secret.go | 7 +- .../pkg/protocol/extension/use_srtp.go | 44 +- .../pkg/protocol/handshake/cipher_suite.go | 4 +- .../dtls/v3/pkg/protocol/handshake/errors.go | 56 + .../pkg/protocol/handshake/handshake.go | 28 +- .../pkg/protocol/handshake/header.go | 10 +- .../protocol/handshake/message_certificate.go | 19 +- .../handshake/message_certificate_request.go | 23 +- .../handshake/message_certificate_verify.go | 14 +- .../handshake/message_client_hello.go | 27 +- .../handshake/message_client_key_exchange.go | 10 +- .../protocol/handshake/message_finished.go | 7 +- .../handshake/message_hello_verify_request.go | 9 +- .../handshake/message_server_hello.go | 22 +- .../handshake/message_server_hello_done.go | 8 +- .../handshake/message_server_key_exchange.go | 26 +- .../pkg/protocol/handshake/random.go | 10 +- .../v3/pkg/protocol/recordlayer/errors.go | 24 + .../pkg/protocol/recordlayer/header.go | 42 +- .../protocol/recordlayer/inner_plaintext.go | 49 + .../pkg/protocol/recordlayer/recordlayer.go | 73 +- .../dtls/{v2 => v3}/pkg/protocol/version.go | 4 +- .../pion/dtls/{v2 => v3}/renovate.json | 0 .../github.com/pion/dtls/{v2 => v3}/resume.go | 11 +- .../pion/dtls/{v2 => v3}/session.go | 2 +- .../{v2 => v3}/srtp_protection_profile.go | 6 +- .../github.com/pion/dtls/{v2 => v3}/state.go | 128 +- .../github.com/pion/dtls/{v2 => v3}/util.go | 2 + .../vendor/github.com/pion/ice/v2/AUTHORS.txt | 65 - .../vendor/github.com/pion/ice/v2/addr.go | 71 - .../github.com/pion/ice/v2/agent_handlers.go | 60 - .../github.com/pion/ice/v2/agent_stats.go | 122 - .../github.com/pion/ice/v2/candidate_base.go | 543 -- .../github.com/pion/ice/v2/candidatepair.go | 102 - .../vendor/github.com/pion/ice/v2/context.go | 40 - .../vendor/github.com/pion/ice/v2/mdns.go | 65 - .../vendor/github.com/pion/ice/v2/net.go | 137 - .../github.com/pion/ice/v2/test_utils.go | 79 - .../github.com/pion/ice/v2/udp_muxed_conn.go | 246 - .../github.com/pion/ice/{v2 => v4}/.gitignore | 0 .../github.com/pion/ice/v4/.golangci.yml | 138 + .../pion/{srtp/v2 => ice/v4}/.goreleaser.yml | 0 .../github.com/pion/ice/{v2 => v4}/LICENSE | 0 .../github.com/pion/ice/{v2 => v4}/README.md | 10 +- .../github.com/pion/ice/v4/active_tcp.go | 177 + .../vendor/github.com/pion/ice/v4/addr.go | 153 + .../github.com/pion/ice/{v2 => v4}/agent.go | 797 ++- .../pion/ice/{v2 => v4}/agent_config.go | 150 +- .../github.com/pion/ice/v4/agent_handlers.go | 190 + .../github.com/pion/ice/v4/agent_stats.go | 183 + .../pion/ice/{v2 => v4}/candidate.go | 29 +- .../github.com/pion/ice/v4/candidate_base.go | 1059 ++++ .../pion/ice/{v2 => v4}/candidate_host.go | 46 +- .../{v2 => v4}/candidate_peer_reflexive.go | 21 +- .../pion/ice/{v2 => v4}/candidate_relay.go | 47 +- .../{v2 => v4}/candidate_server_reflexive.go | 33 +- .../github.com/pion/ice/v4/candidatepair.go | 256 + .../ice/{v2 => v4}/candidatepair_state.go | 7 +- .../ice/{v2 => v4}/candidaterelatedaddress.go | 3 +- .../pion/ice/{v2 => v4}/candidatetype.go | 9 +- .../pion/ice/{v2 => v4}/codecov.yml | 0 .../github.com/pion/ice/{v2 => v4}/errors.go | 100 +- .../pion/ice/{v2 => v4}/external_ip_mapper.go | 25 +- .../github.com/pion/ice/{v2 => v4}/gather.go | 284 +- .../github.com/pion/ice/{v2 => v4}/ice.go | 35 +- .../pion/ice/{v2 => v4}/icecontrol.go | 8 +- .../ice/{v2 => v4}/internal/atomic/atomic.go | 7 +- .../{v2 => v4}/internal/fakenet/mock_conn.go | 2 +- .../internal/fakenet/packet_conn.go | 7 +- .../pion/ice/{v2 => v4}/internal/stun/stun.go | 4 +- .../pion/ice/v4/internal/taskloop/taskloop.go | 121 + .../vendor/github.com/pion/ice/v4/mdns.go | 144 + .../vendor/github.com/pion/ice/v4/net.go | 171 + .../pion/ice/{v2 => v4}/networktype.go | 23 +- .../pion/ice/{v2 => v4}/priority.go | 4 +- .../github.com/pion/ice/{v2 => v4}/rand.go | 0 .../pion/ice/{v2 => v4}/renovate.json | 0 .../github.com/pion/ice/{v2 => v4}/role.go | 1 + .../pion/ice/{v2 => v4}/selection.go | 148 +- .../github.com/pion/ice/{v2 => v4}/stats.go | 14 +- .../github.com/pion/ice/{v2 => v4}/tcp_mux.go | 150 +- .../pion/ice/{v2 => v4}/tcp_mux_multi.go | 11 +- .../pion/ice/{v2 => v4}/tcp_packet_conn.go | 68 +- .../github.com/pion/ice/{v2 => v4}/tcptype.go | 0 .../pion/ice/{v2 => v4}/transport.go | 40 +- .../github.com/pion/ice/{v2 => v4}/udp_mux.go | 141 +- .../pion/ice/{v2 => v4}/udp_mux_multi.go | 52 +- .../pion/ice/{v2 => v4}/udp_mux_universal.go | 64 +- .../github.com/pion/ice/v4/udp_muxed_conn.go | 252 + .../github.com/pion/ice/{v2 => v4}/url.go | 38 +- .../pion/ice/{v2 => v4}/usecandidate.go | 4 +- .../github.com/pion/interceptor/.golangci.yml | 36 +- .../github.com/pion/interceptor/AUTHORS.txt | 30 - .../github.com/pion/interceptor/README.md | 2 +- .../github.com/pion/interceptor/attributes.go | 4 +- .../internal/sequencenumber/unwrapper.go | 45 + .../pkg/nack/generator_interceptor.go | 70 +- .../interceptor/pkg/nack/generator_option.go | 18 + .../pkg/nack/responder_interceptor.go | 19 +- .../interceptor/pkg/nack/responder_option.go | 13 +- .../interceptor/pkg/nack/retainable_packet.go | 48 +- .../pion/interceptor/pkg/nack/send_buffer.go | 4 +- .../pkg/report/receiver_interceptor.go | 6 +- .../interceptor/pkg/report/receiver_stream.go | 27 +- .../pkg/report/sender_interceptor.go | 46 +- .../interceptor/pkg/report/sender_option.go | 26 + .../interceptor/pkg/report/sender_stream.go | 20 +- .../pion/interceptor/pkg/report/ticker.go | 20 + .../interceptor/pkg/rfc8888/interceptor.go | 182 + .../pion/interceptor/pkg/rfc8888/option.go | 33 + .../pion/interceptor/pkg/rfc8888/recorder.go | 78 + .../interceptor/pkg/rfc8888/stream_log.go | 110 + .../pion/interceptor/pkg/rfc8888/ticker.go | 19 + .../pion/interceptor/pkg/rfc8888/unwrapper.go | 42 + .../interceptor/pkg/twcc/arrival_time_map.go | 192 + .../pkg/twcc/sender_interceptor.go | 2 +- .../pion/interceptor/pkg/twcc/twcc.go | 200 +- .../github.com/pion/interceptor/streaminfo.go | 24 +- .../pion/{srtp/v2 => logging}/.gitignore | 0 .../github.com/pion/logging/.golangci.yml | 133 +- .../pion/{stun => logging}/.goreleaser.yml | 0 .../github.com/pion/logging/.travis.yml | 19 - .../vendor/github.com/pion/logging/LICENSE | 20 +- .../vendor/github.com/pion/logging/README.md | 19 +- .../pion/{srtp/v2 => logging}/codecov.yml | 0 .../vendor/github.com/pion/logging/logger.go | 82 +- .../pion/{mdns => logging}/renovate.json | 0 .../vendor/github.com/pion/logging/scoped.go | 25 +- .../vendor/github.com/pion/mdns/.golangci.yml | 116 - .../github.com/pion/mdns/.goreleaser.yml | 2 - .../vendor/github.com/pion/mdns/AUTHORS.txt | 17 - .../vendor/github.com/pion/mdns/config.go | 27 - .../vendor/github.com/pion/mdns/conn.go | 384 -- .../vendor/github.com/pion/mdns/mdns.go | 2 - .../pion/{stun => mdns/v2}/.gitignore | 0 .../pion/{ice => mdns}/v2/.golangci.yml | 21 +- .../{transport => mdns}/v2/.goreleaser.yml | 0 .../github.com/pion/mdns/{ => v2}/LICENSE | 0 .../github.com/pion/mdns/{ => v2}/README.md | 31 +- .../pion/{stun => mdns/v2}/codecov.yml | 0 .../vendor/github.com/pion/mdns/v2/config.go | 49 + .../vendor/github.com/pion/mdns/v2/conn.go | 1220 ++++ .../github.com/pion/mdns/{ => v2}/errors.go | 3 + .../vendor/github.com/pion/mdns/v2/mdns.go | 5 + .../pion/{srtp => mdns}/v2/renovate.json | 0 .../vendor/github.com/pion/rtcp/.gitignore | 3 + .../vendor/github.com/pion/rtcp/.golangci.yml | 48 +- .../pion/{webrtc/v3 => rtcp}/.goreleaser.yml | 0 .../vendor/github.com/pion/rtcp/AUTHORS.txt | 23 - .../vendor/github.com/pion/rtcp/LICENSE | 20 +- .../vendor/github.com/pion/rtcp/README.md | 11 +- .../pion/rtcp/application_defined.go | 122 + .../vendor/github.com/pion/rtcp/codecov.yml | 2 + .../github.com/pion/rtcp/compound_packet.go | 18 +- .../vendor/github.com/pion/rtcp/doc.go | 4 +- .../vendor/github.com/pion/rtcp/errors.go | 7 + .../github.com/pion/rtcp/extended_report.go | 76 +- .../pion/rtcp/full_intra_request.go | 13 +- .../vendor/github.com/pion/rtcp/fuzz.go | 52 - .../vendor/github.com/pion/rtcp/goodbye.go | 16 +- .../vendor/github.com/pion/rtcp/header.go | 3 + .../vendor/github.com/pion/rtcp/packet.go | 7 + .../github.com/pion/rtcp/packet_buffer.go | 4 +- .../pion/rtcp/packet_stringifier.go | 33 +- .../pion/rtcp/picture_loss_indication.go | 8 +- .../rtcp/rapid_resynchronization_request.go | 8 +- .../vendor/github.com/pion/rtcp/raw_packet.go | 8 + .../receiver_estimated_maximum_bitrate.go | 8 +- .../github.com/pion/rtcp/receiver_report.go | 10 +- .../github.com/pion/rtcp/reception_report.go | 3 + .../vendor/github.com/pion/rtcp/renovate.json | 25 +- .../vendor/github.com/pion/rtcp/rfc8888.go | 39 +- .../github.com/pion/rtcp/sender_report.go | 10 +- .../pion/rtcp/slice_loss_indication.go | 8 +- .../pion/rtcp/source_description.go | 17 +- .../pion/rtcp/transport_layer_cc.go | 27 +- .../pion/rtcp/transport_layer_nack.go | 13 +- .../vendor/github.com/pion/rtcp/util.go | 3 + .../vendor/github.com/pion/rtp/.gitignore | 3 + .../vendor/github.com/pion/rtp/.golangci.yml | 108 +- .../github.com/pion/rtp/.goreleaser.yml | 5 + .../vendor/github.com/pion/rtp/AUTHORS.txt | 36 - .../vendor/github.com/pion/rtp/LICENSE | 20 +- .../vendor/github.com/pion/rtp/README.md | 13 +- .../pion/rtp/abscapturetimeextension.go | 115 + .../pion/rtp/abssendtimeextension.go | 8 +- .../pion/rtp/audiolevelextension.go | 13 +- .../vendor/github.com/pion/rtp/codecov.yml | 2 + .../pion/rtp/codecs/av1/obu/errors.go | 14 + .../rtp/{pkg => codecs/av1}/obu/leb128.go | 29 +- .../github.com/pion/rtp/codecs/av1/obu/obu.go | 219 + .../pion/rtp/codecs/av1_depacketizer.go | 188 + .../github.com/pion/rtp/codecs/av1_packet.go | 351 +- .../github.com/pion/rtp/codecs/codecs.go | 3 + .../github.com/pion/rtp/codecs/common.go | 28 +- .../github.com/pion/rtp/codecs/error.go | 9 +- .../github.com/pion/rtp/codecs/g711_packet.go | 8 +- .../github.com/pion/rtp/codecs/g722_packet.go | 8 +- .../github.com/pion/rtp/codecs/h264_packet.go | 191 +- .../github.com/pion/rtp/codecs/h265_packet.go | 443 +- .../github.com/pion/rtp/codecs/opus_packet.go | 26 +- .../github.com/pion/rtp/codecs/vp8_packet.go | 94 +- .../github.com/pion/rtp/codecs/vp9/bits.go | 68 + .../github.com/pion/rtp/codecs/vp9/header.go | 225 + .../github.com/pion/rtp/codecs/vp9_packet.go | 304 +- .../github.com/pion/rtp/depacketizer.go | 9 +- .../vendor/github.com/pion/rtp/error.go | 21 +- .../github.com/pion/rtp/header_extension.go | 83 +- .../vendor/github.com/pion/rtp/packet.go | 158 +- .../vendor/github.com/pion/rtp/packetizer.go | 126 +- .../pion/rtp/partitionheadchecker.go | 5 +- .../github.com/pion/rtp/payload_types.go | 68 + .../github.com/pion/rtp/pkg/frame/av1.go | 44 - .../pion/rtp/playoutdelayextension.go | 52 + .../vendor/github.com/pion/rtp/rand.go | 3 + .../vendor/github.com/pion/rtp/renovate.json | 25 +- .../vendor/github.com/pion/rtp/rtp.go | 3 + .../vendor/github.com/pion/rtp/sequencer.go | 23 +- .../pion/rtp/transportccextension.go | 12 +- .../github.com/pion/rtp/vlaextension.go | 373 ++ .../vendor/github.com/pion/sctp/.gitignore | 3 + .../vendor/github.com/pion/sctp/.golangci.yml | 91 +- .../github.com/pion/sctp/.goreleaser.yml | 3 + .../vendor/github.com/pion/sctp/AUTHORS.txt | 33 - .../vendor/github.com/pion/sctp/LICENSE | 20 +- .../vendor/github.com/pion/sctp/README.md | 8 +- .../vendor/github.com/pion/sctp/ack_timer.go | 101 +- .../github.com/pion/sctp/association.go | 1083 ++-- .../github.com/pion/sctp/association_stats.go | 53 +- .../vendor/github.com/pion/sctp/chunk.go | 3 + .../github.com/pion/sctp/chunk_abort.go | 9 +- .../github.com/pion/sctp/chunk_cookie_ack.go | 8 +- .../github.com/pion/sctp/chunk_cookie_echo.go | 6 +- .../github.com/pion/sctp/chunk_error.go | 9 +- .../github.com/pion/sctp/chunk_forward_tsn.go | 11 +- .../github.com/pion/sctp/chunk_heartbeat.go | 6 +- .../pion/sctp/chunk_heartbeat_ack.go | 6 +- .../vendor/github.com/pion/sctp/chunk_init.go | 28 +- .../github.com/pion/sctp/chunk_init_ack.go | 12 +- .../github.com/pion/sctp/chunk_init_common.go | 31 +- .../pion/sctp/chunk_payload_data.go | 18 +- .../github.com/pion/sctp/chunk_reconfig.go | 9 +- .../pion/sctp/chunk_selective_ack.go | 14 +- .../github.com/pion/sctp/chunk_shutdown.go | 10 +- .../pion/sctp/chunk_shutdown_ack.go | 10 +- .../pion/sctp/chunk_shutdown_complete.go | 10 +- .../github.com/pion/sctp/chunkheader.go | 16 +- .../vendor/github.com/pion/sctp/chunktype.go | 7 +- .../vendor/github.com/pion/sctp/codecov.yml | 2 + .../github.com/pion/sctp/control_queue.go | 4 + .../github.com/pion/sctp/error_cause.go | 25 +- .../pion/sctp/error_cause_header.go | 17 +- ...error_cause_invalid_mandatory_parameter.go | 7 +- .../sctp/error_cause_protocol_violation.go | 8 +- .../error_cause_unrecognized_chunk_type.go | 9 +- .../sctp/error_cause_user_initiated_abort.go | 7 +- .../vendor/github.com/pion/sctp/packet.go | 113 +- .../vendor/github.com/pion/sctp/param.go | 11 +- .../github.com/pion/sctp/param_chunk_list.go | 3 + .../github.com/pion/sctp/param_ecn_capable.go | 5 + .../pion/sctp/param_forward_tsn_supported.go | 5 + .../pion/sctp/param_heartbeat_info.go | 5 + .../pion/sctp/param_outgoing_reset_request.go | 6 +- .../github.com/pion/sctp/param_random.go | 5 + .../pion/sctp/param_reconfig_response.go | 5 +- .../sctp/param_requested_hmac_algorithm.go | 11 +- .../pion/sctp/param_state_cookie.go | 7 +- .../pion/sctp/param_supported_extensions.go | 3 + .../pion/sctp/param_zero_checksum.go | 58 + .../github.com/pion/sctp/paramheader.go | 53 +- .../vendor/github.com/pion/sctp/paramtype.go | 67 +- .../github.com/pion/sctp/payload_queue.go | 150 +- .../github.com/pion/sctp/pending_queue.go | 28 +- .../vendor/github.com/pion/sctp/queue.go | 75 + .../github.com/pion/sctp/reassembly_queue.go | 115 +- .../pion/sctp/receive_payload_queue.go | 201 + .../vendor/github.com/pion/sctp/rtx_timer.go | 190 +- .../vendor/github.com/pion/sctp/sctp.go | 3 + .../vendor/github.com/pion/sctp/stream.go | 126 +- .../vendor/github.com/pion/sctp/util.go | 6 +- .../vendor/github.com/pion/sdp/v3/.gitignore | 3 + .../github.com/pion/sdp/v3/.golangci.yml | 89 +- .../github.com/pion/sdp/v3/.goreleaser.yml | 5 + .../vendor/github.com/pion/sdp/v3/AUTHORS.txt | 32 - .../vendor/github.com/pion/sdp/v3/LICENSE | 20 +- .../vendor/github.com/pion/sdp/v3/README.md | 14 +- .../github.com/pion/sdp/v3/base_lexer.go | 64 +- .../vendor/github.com/pion/sdp/v3/codecov.yml | 2 + .../pion/sdp/v3/common_description.go | 126 +- .../github.com/pion/sdp/v3/direction.go | 13 +- .../vendor/github.com/pion/sdp/v3/extmap.go | 27 +- .../vendor/github.com/pion/sdp/v3/fuzz.go | 31 - .../vendor/github.com/pion/sdp/v3/jsep.go | 67 +- .../vendor/github.com/pion/sdp/v3/marshal.go | 228 +- .../pion/sdp/v3/media_description.go | 68 +- .../github.com/pion/sdp/v3/renovate.json | 25 +- .../vendor/github.com/pion/sdp/v3/sdp.go | 3 + .../pion/sdp/v3/session_description.go | 90 +- .../pion/sdp/v3/time_description.go | 43 +- .../github.com/pion/sdp/v3/unmarshal.go | 440 +- .../github.com/pion/sdp/v3/unmarshal_cache.go | 48 + .../vendor/github.com/pion/sdp/v3/util.go | 178 +- .../github.com/pion/srtp/v2/AUTHORS.txt | 36 - .../vendor/github.com/pion/srtp/v2/option.go | 57 - .../pion/srtp/v2/protection_profile.go | 86 - .../pion/{transport/v2 => srtp/v3}/.gitignore | 0 .../pion/{turn/v2 => srtp/v3}/.golangci.yml | 45 +- .../github.com/pion/srtp/v3/.goreleaser.yml | 5 + .../github.com/pion/srtp/{v2 => v3}/LICENSE | 0 .../github.com/pion/srtp/{v2 => v3}/README.md | 2 +- .../{transport/v2 => srtp/v3}/codecov.yml | 0 .../pion/srtp/{v2 => v3}/context.go | 127 +- .../github.com/pion/srtp/{v2 => v3}/crypto.go | 20 +- .../github.com/pion/srtp/{v2 => v3}/errors.go | 12 +- .../pion/srtp/{v2 => v3}/key_derivation.go | 8 +- .../github.com/pion/srtp/{v2 => v3}/keying.go | 4 +- .../vendor/github.com/pion/srtp/v3/option.go | 120 + .../pion/srtp/v3/protection_profile.go | 128 + .../pion/{stun => srtp/v3}/renovate.json | 0 .../pion/srtp/{v2 => v3}/session.go | 2 +- .../pion/srtp/{v2 => v3}/session_srtcp.go | 0 .../pion/srtp/{v2 => v3}/session_srtp.go | 0 .../github.com/pion/srtp/{v2 => v3}/srtcp.go | 33 +- .../github.com/pion/srtp/{v2 => v3}/srtp.go | 33 +- .../pion/srtp/{v2 => v3}/srtp_cipher.go | 11 +- .../{v2 => v3}/srtp_cipher_aead_aes_gcm.go | 132 +- .../srtp_cipher_aes_cm_hmac_sha1.go | 149 +- .../github.com/pion/srtp/{v2 => v3}/stream.go | 0 .../pion/srtp/{v2 => v3}/stream_srtcp.go | 2 +- .../pion/srtp/{v2 => v3}/stream_srtp.go | 2 +- .../github.com/pion/srtp/{v2 => v3}/util.go | 0 .../vendor/github.com/pion/stun/AUTHORS.txt | 40 - .../pion/{webrtc => stun}/v3/.gitignore | 0 .../pion/{dtls/v2 => stun/v3}/.golangci.yml | 28 +- .../github.com/pion/stun/v3/.goreleaser.yml | 5 + .../github.com/pion/stun/{ => v3}/LICENSE | 0 .../github.com/pion/stun/{ => v3}/Makefile | 2 - .../github.com/pion/stun/{ => v3}/README.md | 2 +- .../github.com/pion/stun/{ => v3}/addr.go | 0 .../github.com/pion/stun/{ => v3}/agent.go | 2 +- .../pion/stun/{ => v3}/attributes.go | 0 .../pion/stun/{ => v3}/attributes_debug.go | 0 .../github.com/pion/stun/{ => v3}/checks.go | 2 +- .../pion/stun/{ => v3}/checks_debug.go | 2 +- .../github.com/pion/stun/{ => v3}/client.go | 15 +- .../pion/{webrtc => stun}/v3/codecov.yml | 0 .../pion/stun/{ => v3}/errorcode.go | 0 .../github.com/pion/stun/{ => v3}/errors.go | 0 .../pion/stun/{ => v3}/fingerprint.go | 0 .../pion/stun/{ => v3}/fingerprint_debug.go | 0 .../github.com/pion/stun/{ => v3}/helpers.go | 0 .../pion/stun/{ => v3}/integrity.go | 2 +- .../pion/stun/{ => v3}/integrity_debug.go | 0 .../pion/stun/{ => v3}/internal/hmac/hmac.go | 0 .../pion/stun/{ => v3}/internal/hmac/pool.go | 0 .../stun/{ => v3}/internal/hmac/vendor.sh | 0 .../github.com/pion/stun/{ => v3}/message.go | 0 .../{transport/v2 => stun/v3}/renovate.json | 0 .../github.com/pion/stun/{ => v3}/stun.go | 0 .../pion/stun/{ => v3}/textattrs.go | 0 .../github.com/pion/stun/{ => v3}/uattrs.go | 0 .../github.com/pion/stun/{ => v3}/uri.go | 0 .../github.com/pion/stun/{ => v3}/xoraddr.go | 2 +- .../pion/transport/v2/.golangci.yml | 137 - .../github.com/pion/transport/v2/AUTHORS.txt | 28 - .../github.com/pion/transport/v2/udp/conn.go | 327 - .../pion/transport/v2/utils/xor/xor_amd64.go | 29 - .../pion/transport/v2/utils/xor/xor_amd64.s | 56 - .../pion/transport/v2/utils/xor/xor_arm64.go | 31 - .../pion/transport/v2/utils/xor/xor_arm64.s | 69 - .../pion/transport/v2/utils/xor/xor_ppc64x.go | 29 - .../pion/transport/v2/utils/xor/xor_ppc64x.s | 87 - .../pion/{mdns => transport/v3}/.gitignore | 3 + .../{srtp/v2 => transport/v3}/.golangci.yml | 28 +- .../pion/transport/v3/.goreleaser.yml | 5 + .../pion/transport/{v2 => v3}/LICENSE | 0 .../pion/transport/{v2 => v3}/README.md | 2 +- .../pion/{mdns => transport/v3}/codecov.yml | 2 + .../transport/{v2 => v3}/deadline/deadline.go | 101 +- .../pion/transport/v3/deadline/timer.go | 13 + .../transport/v3/deadline/timer_generic.go | 15 + .../pion/transport/v3/deadline/timer_js.go | 67 + .../pion/transport/{v2 => v3}/net.go | 0 .../connctx/connctx.go => v3/netctx/conn.go} | 42 +- .../pion/transport/v3/netctx/packetconn.go | 175 + .../{v2/connctx => v3/netctx}/pipe.go | 8 +- .../transport/{v2 => v3}/packetio/buffer.go | 36 +- .../transport/{v2 => v3}/packetio/errors.go | 0 .../{v2 => v3}/packetio/hardlimit.go | 0 .../{v2 => v3}/packetio/no_hardlimit.go | 0 .../{turn/v2 => transport/v3}/renovate.json | 0 .../{v2 => v3}/replaydetector/fixedbig.go | 0 .../replaydetector/replaydetector.go | 35 +- .../pion/transport/{v2 => v3}/stdnet/net.go | 11 +- .../transport/{v2 => v3}/utils/xor/xor_arm.go | 0 .../transport/{v2 => v3}/utils/xor/xor_arm.s | 0 .../transport/v3/utils/xor/xor_generic.go | 20 + .../utils/xor/xor_old.go} | 11 +- .../pion/transport/{v2 => v3}/vnet/.gitignore | 0 .../pion/transport/{v2 => v3}/vnet/README.md | 0 .../pion/transport/{v2 => v3}/vnet/chunk.go | 0 .../transport/{v2 => v3}/vnet/chunk_queue.go | 0 .../pion/transport/{v2 => v3}/vnet/conn.go | 2 +- .../transport/{v2 => v3}/vnet/conn_map.go | 0 .../transport/{v2 => v3}/vnet/delay_filter.go | 0 .../pion/transport/{v2 => v3}/vnet/errors.go | 0 .../transport/{v2 => v3}/vnet/loss_filter.go | 0 .../pion/transport/{v2 => v3}/vnet/nat.go | 0 .../pion/transport/{v2 => v3}/vnet/net.go | 2 +- .../transport/{v2 => v3}/vnet/resolver.go | 0 .../pion/transport/{v2 => v3}/vnet/router.go | 2 +- .../pion/transport/{v2 => v3}/vnet/tbf.go | 0 .../transport/{v2 => v3}/vnet/udpproxy.go | 2 +- .../{v2 => v3}/vnet/udpproxy_direct.go | 2 +- .../pion/transport/{v2 => v3}/vnet/vnet.go | 0 .../github.com/pion/turn/v2/.goreleaser.yml | 2 - .../github.com/pion/turn/v2/AUTHORS.txt | 43 - .../vendor/github.com/pion/turn/v2/DESIGN.md | 31 - .../vendor/github.com/pion/turn/v2/FAQ.md | 17 - .../turn/v2/internal/allocation/five_tuple.go | 36 - .../vendor/github.com/pion/turn/v2/lt_cred.go | 56 - .../pion/turn/{v2 => v4}/.gitignore | 3 + .../pion/{stun => turn/v4}/.golangci.yml | 28 +- .../github.com/pion/turn/v4/.goreleaser.yml | 5 + .../pion/{webrtc/v3 => turn/v4}/LICENSE | 0 .../github.com/pion/turn/{v2 => v4}/README.md | 50 +- .../github.com/pion/turn/{v2 => v4}/client.go | 444 +- .../pion/turn/{v2 => v4}/codecov.yml | 2 + .../github.com/pion/turn/{v2 => v4}/errors.go | 4 + .../internal/allocation/allocation.go | 43 +- .../internal/allocation/allocation_manager.go | 11 +- .../internal/allocation/channel_bind.go | 7 +- .../{v2 => v4}/internal/allocation/errors.go | 3 + .../turn/v4/internal/allocation/five_tuple.go | 63 + .../internal/allocation/permission.go | 5 +- .../turn/v4/internal/client/allocation.go | 189 + .../{v2 => v4}/internal/client/binding.go | 17 +- .../pion/turn/v4/internal/client/client.go | 18 + .../turn/{v2 => v4}/internal/client/errors.go | 8 +- .../internal/client/periodic_timer.go | 5 +- .../{v2 => v4}/internal/client/permission.go | 41 +- .../pion/turn/v4/internal/client/tcp_alloc.go | 376 ++ .../pion/turn/v4/internal/client/tcp_conn.go | 49 + .../{v2 => v4}/internal/client/transaction.go | 31 +- .../{v2 => v4}/internal/client/trylock.go | 3 + .../internal/client/udp_conn.go} | 298 +- .../turn/{v2 => v4}/internal/ipnet/util.go | 15 + .../turn/{v2 => v4}/internal/proto/addr.go | 3 + .../{v2 => v4}/internal/proto/chandata.go | 9 +- .../turn/{v2 => v4}/internal/proto/chann.go | 9 +- .../internal/proto/connection_id.go | 7 +- .../turn/{v2 => v4}/internal/proto/data.go | 5 +- .../{v2 => v4}/internal/proto/dontfrag.go | 10 +- .../{v2 => v4}/internal/proto/evenport.go | 5 +- .../{v2 => v4}/internal/proto/lifetime.go | 9 +- .../{v2 => v4}/internal/proto/peeraddr.go | 5 +- .../turn/{v2 => v4}/internal/proto/proto.go | 7 +- .../{v2 => v4}/internal/proto/relayedaddr.go | 5 +- .../{v2 => v4}/internal/proto/reqfamily.go | 5 +- .../{v2 => v4}/internal/proto/reqtrans.go | 9 +- .../{v2 => v4}/internal/proto/rsrvtoken.go | 5 +- .../turn/{v2 => v4}/internal/server/errors.go | 7 +- .../pion/turn/v4/internal/server/nonce.go | 71 + .../turn/{v2 => v4}/internal/server/server.go | 28 +- .../turn/{v2 => v4}/internal/server/stun.go | 9 +- .../turn/{v2 => v4}/internal/server/turn.go | 60 +- .../turn/{v2 => v4}/internal/server/util.go | 68 +- .../vendor/github.com/pion/turn/v4/lt_cred.go | 100 + .../relay_address_generator_none.go | 9 +- .../relay_address_generator_range.go | 9 +- .../relay_address_generator_static.go | 9 +- .../pion/{webrtc/v3 => turn/v4}/renovate.json | 0 .../github.com/pion/turn/{v2 => v4}/server.go | 93 +- .../pion/turn/{v2 => v4}/server_config.go | 14 +- .../pion/turn/{v2 => v4}/stun_conn.go | 9 +- .../github.com/pion/webrtc/v3/.golangci.yml | 137 - .../github.com/pion/webrtc/v3/AUTHORS.txt | 214 - .../github.com/pion/webrtc/v3/constants.go | 43 - .../pion/webrtc/v3/internal/fmtp/fmtp.go | 95 - .../github.com/pion/webrtc/v3/operations.go | 96 - .../github.com/pion/webrtc/v3/package.json | 11 - .../v3/pkg/media/ivfwriter/ivfwriter.go | 233 - .../github.com/pion/webrtc/v3/track_local.go | 90 - .../github.com/pion/webrtc/v3/yarn.lock | 797 --- .../pion/webrtc/{v3 => v4}/.codacy.yaml | 0 .../pion/webrtc/{v3 => v4}/.eslintrc.json | 0 .../github.com/pion/webrtc/v4/.gitignore | 28 + .../github.com/pion/webrtc/v4/.golangci.yml | 145 + .../github.com/pion/webrtc/v4/.goreleaser.yml | 5 + .../pion/webrtc/{v3 => v4}/DESIGN.md | 2 +- .../{turn/v2/LICENSE.md => webrtc/v4/LICENSE} | 4 +- .../pion/webrtc/{v3 => v4}/README.md | 46 +- .../github.com/pion/webrtc/{v3 => v4}/api.go | 37 +- .../pion/webrtc/{v3 => v4}/api_js.go | 2 +- .../pion/webrtc/{v3 => v4}/atomicbool.go | 1 + .../pion/webrtc/{v3 => v4}/bundlepolicy.go | 12 +- .../pion/webrtc/{v3 => v4}/certificate.go | 115 +- .../github.com/pion/webrtc/v4/codecov.yml | 22 + .../pion/webrtc/{v3 => v4}/configuration.go | 0 .../webrtc/{v3 => v4}/configuration_common.go | 1 + .../webrtc/{v3 => v4}/configuration_js.go | 2 + .../github.com/pion/webrtc/v4/constants.go | 66 + .../pion/webrtc/{v3 => v4}/datachannel.go | 196 +- .../pion/webrtc/{v3 => v4}/datachannel_js.go | 51 +- .../{v3 => v4}/datachannel_js_detach.go | 0 .../pion/webrtc/{v3 => v4}/datachannelinit.go | 0 .../webrtc/{v3 => v4}/datachannelmessage.go | 0 .../{v3 => v4}/datachannelparameters.go | 0 .../webrtc/{v3 => v4}/datachannelstate.go | 19 +- .../pion/webrtc/{v3 => v4}/dtlsfingerprint.go | 2 +- .../pion/webrtc/{v3 => v4}/dtlsparameters.go | 0 .../pion/webrtc/{v3 => v4}/dtlsrole.go | 9 +- .../pion/webrtc/{v3 => v4}/dtlstransport.go | 137 +- .../webrtc/{v3 => v4}/dtlstransport_js.go | 5 + .../webrtc/{v3 => v4}/dtlstransportstate.go | 19 +- .../pion/webrtc/{v3 => v4}/errors.go | 152 +- .../{v3 => v4}/gathering_complete_promise.go | 6 +- .../pion/webrtc/{v3 => v4}/ice_go.go | 0 .../pion/webrtc/{v3 => v4}/icecandidate.go | 139 +- .../webrtc/{v3 => v4}/icecandidateinit.go | 2 +- .../webrtc/{v3 => v4}/icecandidatepair.go | 5 +- .../webrtc/{v3 => v4}/icecandidatetype.go | 31 +- .../pion/webrtc/{v3 => v4}/icecomponent.go | 7 +- .../webrtc/{v3 => v4}/iceconnectionstate.go | 9 +- .../webrtc/{v3 => v4}/icecredentialtype.go | 5 +- .../pion/webrtc/{v3 => v4}/icegatherer.go | 143 +- .../webrtc/{v3 => v4}/icegathererstate.go | 7 +- .../webrtc/{v3 => v4}/icegatheringstate.go | 9 +- .../webrtc/{v3 => v4}/icegatheroptions.go | 0 .../pion/webrtc/{v3 => v4}/icemux.go | 2 +- .../pion/webrtc/{v3 => v4}/iceparameters.go | 0 .../pion/webrtc/{v3 => v4}/iceprotocol.go | 9 +- .../pion/webrtc/{v3 => v4}/icerole.go | 19 +- .../pion/webrtc/{v3 => v4}/iceserver.go | 26 +- .../pion/webrtc/{v3 => v4}/iceserver_js.go | 2 +- .../pion/webrtc/{v3 => v4}/icetransport.go | 132 +- .../pion/webrtc/{v3 => v4}/icetransport_js.go | 5 + .../webrtc/{v3 => v4}/icetransportpolicy.go | 13 +- .../webrtc/{v3 => v4}/icetransportstate.go | 70 +- .../pion/webrtc/{v3 => v4}/interceptor.go | 94 +- .../pion/webrtc/v4/internal/fmtp/av1.go | 42 + .../pion/webrtc/v4/internal/fmtp/fmtp.go | 185 + .../webrtc/{v3 => v4}/internal/fmtp/h264.go | 8 +- .../pion/webrtc/v4/internal/fmtp/vp9.go | 42 + .../{v3 => v4}/internal/mux/endpoint.go | 52 +- .../webrtc/{v3 => v4}/internal/mux/mux.go | 111 +- .../webrtc/{v3 => v4}/internal/mux/muxfunc.go | 16 +- .../webrtc/{v3 => v4}/internal/util/util.go | 8 +- .../pion/webrtc/{v3 => v4}/js_utils.go | 0 .../pion/webrtc/{v3 => v4}/mediaengine.go | 470 +- .../github.com/pion/webrtc/v4/mimetype.go | 46 + .../pion/webrtc/{v3 => v4}/networktype.go | 15 +- .../pion/webrtc/{v3 => v4}/oauthcredential.go | 0 .../webrtc/{v3 => v4}/offeransweroptions.go | 2 +- .../github.com/pion/webrtc/v4/operations.go | 158 + .../github.com/pion/webrtc/v4/package.json | 12 + .../pion/webrtc/{v3 => v4}/peerconnection.go | 1187 ++-- .../webrtc/{v3 => v4}/peerconnection_js.go | 10 +- .../webrtc/{v3 => v4}/peerconnectionstate.go | 18 +- .../pkg/media/h264reader/h264reader.go | 14 +- .../pkg/media/h264reader/nalunittype.go | 13 +- .../pkg/media/h264writer/h264writer.go | 10 +- .../v4/pkg/media/ivfwriter/ivfwriter.go | 341 + .../pion/webrtc/{v3 => v4}/pkg/media/media.go | 9 +- .../pkg/media/oggreader/oggreader.go | 38 +- .../pkg/media/oggwriter/oggwriter.go | 67 +- .../webrtc/{v3 => v4}/pkg/rtcerr/errors.go | 0 .../github.com/pion/webrtc/v4/renovate.json | 6 + .../pion/webrtc/{v3 => v4}/rtcpfeedback.go | 0 .../pion/webrtc/{v3 => v4}/rtcpmuxpolicy.go | 12 +- .../pion/webrtc/{v3 => v4}/rtpcapabilities.go | 0 .../pion/webrtc/{v3 => v4}/rtpcodec.go | 86 +- .../webrtc/{v3 => v4}/rtpcodingparameters.go | 7 + .../{v3 => v4}/rtpdecodingparameters.go | 0 .../{v3 => v4}/rtpencodingparameters.go | 0 .../webrtc/{v3 => v4}/rtpreceiveparameters.go | 2 +- .../pion/webrtc/{v3 => v4}/rtpreceiver.go | 270 +- .../pion/webrtc/{v3 => v4}/rtpreceiver_go.go | 0 .../pion/webrtc/{v3 => v4}/rtpreceiver_js.go | 5 + .../pion/webrtc/{v3 => v4}/rtpsender.go | 190 +- .../pion/webrtc/{v3 => v4}/rtpsender_js.go | 5 + .../webrtc/{v3 => v4}/rtpsendparameters.go | 2 +- .../pion/webrtc/{v3 => v4}/rtptransceiver.go | 71 +- .../webrtc/{v3 => v4}/rtptransceiver_js.go | 5 + .../{v3 => v4}/rtptransceiverdirection.go | 15 +- .../webrtc/{v3 => v4}/rtptransceiverinit.go | 7 +- .../webrtc/{v3 => v4}/sctpcapabilities.go | 0 .../pion/webrtc/{v3 => v4}/sctptransport.go | 181 +- .../webrtc/{v3 => v4}/sctptransport_js.go | 5 + .../webrtc/{v3 => v4}/sctptransportstate.go | 7 +- .../github.com/pion/webrtc/{v3 => v4}/sdp.go | 622 +- .../pion/webrtc/{v3 => v4}/sdpsemantics.go | 13 +- .../pion/webrtc/{v3 => v4}/sdptype.go | 16 +- .../webrtc/{v3 => v4}/sessiondescription.go | 5 +- .../pion/webrtc/{v3 => v4}/settingengine.go | 241 +- .../webrtc/{v3 => v4}/settingengine_js.go | 0 .../pion/webrtc/{v3 => v4}/signalingstate.go | 17 +- .../webrtc/{v3 => v4}/srtp_writer_future.go | 7 +- .../pion/webrtc/{v3 => v4}/stats.go | 1011 ++- .../pion/webrtc/{v3 => v4}/stats_go.go | 18 +- .../github.com/pion/webrtc/v4/track_local.go | 128 + .../webrtc/{v3 => v4}/track_local_static.go | 161 +- .../pion/webrtc/{v3 => v4}/track_remote.go | 85 +- .../pion/webrtc/{v3 => v4}/webrtc.go | 0 .../github.com/pion/webrtc/v4/yarn.lock | 377 ++ .../github.com/pmezard/go-difflib/LICENSE | 27 - .../pmezard/go-difflib/difflib/difflib.go | 772 --- .../github.com/stretchr/testify/LICENSE | 21 - .../testify/assert/assertion_compare.go | 480 -- .../testify/assert/assertion_format.go | 815 --- .../testify/assert/assertion_format.go.tmpl | 5 - .../testify/assert/assertion_forward.go | 1621 ----- .../testify/assert/assertion_forward.go.tmpl | 5 - .../testify/assert/assertion_order.go | 81 - .../stretchr/testify/assert/assertions.go | 2105 ------- .../github.com/stretchr/testify/assert/doc.go | 46 - .../stretchr/testify/assert/errors.go | 10 - .../testify/assert/forward_assertions.go | 16 - .../testify/assert/http_assertions.go | 165 - .../stretchr/testify/require/doc.go | 29 - .../testify/require/forward_requirements.go | 16 - .../stretchr/testify/require/require.go | 2060 ------ .../stretchr/testify/require/require.go.tmpl | 6 - .../testify/require/require_forward.go | 1622 ----- .../testify/require/require_forward.go.tmpl | 5 - .../stretchr/testify/require/requirements.go | 29 - .../vendor/github.com/wlynxg/anet/.gitignore | 1 + .../vendor/github.com/wlynxg/anet/LICENSE | 28 + .../vendor/github.com/wlynxg/anet/README.md | 126 + .../github.com/wlynxg/anet/README_zh.md | 25 + .../wlynxg/anet/android_api_level.go | 7 + .../wlynxg/anet/android_api_level_cgo.go | 23 + .../github.com/wlynxg/anet/interface.go | 30 + .../wlynxg/anet/interface_android.go | 442 ++ .../github.com/wlynxg/anet/netlink_android.go | 179 + .../vendor/golang.org/x/crypto/LICENSE | 4 +- .../x/crypto/cryptobyte/asn1/asn1.go | 2 +- .../golang.org/x/crypto/cryptobyte/string.go | 2 +- .../x/crypto/curve25519/curve25519.go | 39 +- .../x/crypto/curve25519/curve25519_compat.go | 105 - .../x/crypto/curve25519/curve25519_go120.go | 46 - .../x/crypto/curve25519/internal/field/README | 7 - .../x/crypto/curve25519/internal/field/fe.go | 416 -- .../curve25519/internal/field/fe_amd64.go | 15 - .../curve25519/internal/field/fe_amd64.s | 378 -- .../internal/field/fe_amd64_noasm.go | 11 - .../curve25519/internal/field/fe_arm64.go | 15 - .../curve25519/internal/field/fe_arm64.s | 42 - .../internal/field/fe_arm64_noasm.go | 11 - .../curve25519/internal/field/fe_generic.go | 264 - .../curve25519/internal/field/sync.checkpoint | 1 - .../crypto/curve25519/internal/field/sync.sh | 19 - .../srs-bench/vendor/golang.org/x/net/LICENSE | 4 +- .../net/internal/socket/zsys_openbsd_ppc64.go | 28 +- .../internal/socket/zsys_openbsd_riscv64.go | 28 +- .../vendor/golang.org/x/net/ipv6/batch.go | 116 + .../vendor/golang.org/x/net/ipv6/control.go | 187 + .../x/net/ipv6/control_rfc2292_unix.go | 50 + .../x/net/ipv6/control_rfc3542_unix.go | 96 + .../golang.org/x/net/ipv6/control_stub.go | 13 + .../golang.org/x/net/ipv6/control_unix.go | 55 + .../golang.org/x/net/ipv6/control_windows.go | 12 + .../vendor/golang.org/x/net/ipv6/dgramopt.go | 301 + .../vendor/golang.org/x/net/ipv6/doc.go | 239 + .../vendor/golang.org/x/net/ipv6/endpoint.go | 127 + .../golang.org/x/net/ipv6/genericopt.go | 56 + .../vendor/golang.org/x/net/ipv6/header.go | 55 + .../vendor/golang.org/x/net/ipv6/helper.go | 58 + .../vendor/golang.org/x/net/ipv6/iana.go | 86 + .../vendor/golang.org/x/net/ipv6/icmp.go | 60 + .../vendor/golang.org/x/net/ipv6/icmp_bsd.go | 29 + .../golang.org/x/net/ipv6/icmp_linux.go | 27 + .../golang.org/x/net/ipv6/icmp_solaris.go | 27 + .../vendor/golang.org/x/net/ipv6/icmp_stub.go | 23 + .../golang.org/x/net/ipv6/icmp_windows.go | 22 + .../vendor/golang.org/x/net/ipv6/icmp_zos.go | 29 + .../vendor/golang.org/x/net/ipv6/payload.go | 23 + .../golang.org/x/net/ipv6/payload_cmsg.go | 70 + .../golang.org/x/net/ipv6/payload_nocmsg.go | 38 + .../vendor/golang.org/x/net/ipv6/sockopt.go | 43 + .../golang.org/x/net/ipv6/sockopt_posix.go | 89 + .../golang.org/x/net/ipv6/sockopt_stub.go | 46 + .../vendor/golang.org/x/net/ipv6/sys_aix.go | 79 + .../golang.org/x/net/ipv6/sys_asmreq.go | 24 + .../golang.org/x/net/ipv6/sys_asmreq_stub.go | 17 + .../vendor/golang.org/x/net/ipv6/sys_bpf.go | 24 + .../golang.org/x/net/ipv6/sys_bpf_stub.go | 16 + .../vendor/golang.org/x/net/ipv6/sys_bsd.go | 59 + .../golang.org/x/net/ipv6/sys_darwin.go | 80 + .../golang.org/x/net/ipv6/sys_freebsd.go | 94 + .../vendor/golang.org/x/net/ipv6/sys_linux.go | 76 + .../golang.org/x/net/ipv6/sys_solaris.go | 76 + .../golang.org/x/net/ipv6/sys_ssmreq.go | 54 + .../golang.org/x/net/ipv6/sys_ssmreq_stub.go | 21 + .../vendor/golang.org/x/net/ipv6/sys_stub.go | 13 + .../golang.org/x/net/ipv6/sys_windows.go | 68 + .../vendor/golang.org/x/net/ipv6/sys_zos.go | 72 + .../golang.org/x/net/ipv6/zsys_aix_ppc64.go | 68 + .../golang.org/x/net/ipv6/zsys_darwin.go | 64 + .../golang.org/x/net/ipv6/zsys_dragonfly.go | 42 + .../golang.org/x/net/ipv6/zsys_freebsd_386.go | 64 + .../x/net/ipv6/zsys_freebsd_amd64.go | 66 + .../golang.org/x/net/ipv6/zsys_freebsd_arm.go | 66 + .../x/net/ipv6/zsys_freebsd_arm64.go | 64 + .../x/net/ipv6/zsys_freebsd_riscv64.go | 64 + .../golang.org/x/net/ipv6/zsys_linux_386.go | 72 + .../golang.org/x/net/ipv6/zsys_linux_amd64.go | 74 + .../golang.org/x/net/ipv6/zsys_linux_arm.go | 72 + .../golang.org/x/net/ipv6/zsys_linux_arm64.go | 74 + .../x/net/ipv6/zsys_linux_loong64.go | 76 + .../golang.org/x/net/ipv6/zsys_linux_mips.go | 72 + .../x/net/ipv6/zsys_linux_mips64.go | 74 + .../x/net/ipv6/zsys_linux_mips64le.go | 74 + .../x/net/ipv6/zsys_linux_mipsle.go | 72 + .../golang.org/x/net/ipv6/zsys_linux_ppc.go | 72 + .../golang.org/x/net/ipv6/zsys_linux_ppc64.go | 74 + .../x/net/ipv6/zsys_linux_ppc64le.go | 74 + .../x/net/ipv6/zsys_linux_riscv64.go | 76 + .../golang.org/x/net/ipv6/zsys_linux_s390x.go | 74 + .../golang.org/x/net/ipv6/zsys_netbsd.go | 42 + .../golang.org/x/net/ipv6/zsys_openbsd.go | 42 + .../golang.org/x/net/ipv6/zsys_solaris.go | 63 + .../golang.org/x/net/ipv6/zsys_zos_s390x.go | 62 + .../vendor/golang.org/x/net/proxy/per_host.go | 8 +- .../srs-bench/vendor/golang.org/x/sys/LICENSE | 4 +- .../golang.org/x/sys/cpu/asm_darwin_x86_gc.s | 17 + .../vendor/golang.org/x/sys/cpu/cpu.go | 25 + .../vendor/golang.org/x/sys/cpu/cpu_arm64.go | 22 + .../vendor/golang.org/x/sys/cpu/cpu_arm64.s | 8 + .../golang.org/x/sys/cpu/cpu_darwin_x86.go | 61 + .../golang.org/x/sys/cpu/cpu_gc_arm64.go | 1 + .../vendor/golang.org/x/sys/cpu/cpu_gc_x86.go | 4 +- .../x/sys/cpu/{cpu_x86.s => cpu_gc_x86.s} | 2 +- .../golang.org/x/sys/cpu/cpu_gccgo_x86.go | 6 - .../golang.org/x/sys/cpu/cpu_linux_arm64.go | 9 + .../golang.org/x/sys/cpu/cpu_linux_noinit.go | 2 +- .../golang.org/x/sys/cpu/cpu_linux_riscv64.go | 137 + .../golang.org/x/sys/cpu/cpu_other_x86.go | 11 + .../golang.org/x/sys/cpu/cpu_riscv64.go | 11 +- .../vendor/golang.org/x/sys/cpu/cpu_x86.go | 27 +- .../x/sys/cpu/syscall_darwin_x86_gc.go | 98 + .../vendor/golang.org/x/sys/unix/README.md | 2 +- .../golang.org/x/sys/unix/asm_zos_s390x.s | 675 +- .../vendor/golang.org/x/sys/unix/auxv.go | 36 + .../golang.org/x/sys/unix/auxv_unsupported.go | 13 + .../golang.org/x/sys/unix/bpxsvc_zos.go | 657 ++ .../vendor/golang.org/x/sys/unix/bpxsvc_zos.s | 192 + .../vendor/golang.org/x/sys/unix/epoll_zos.go | 220 - .../golang.org/x/sys/unix/fstatfs_zos.go | 163 - .../golang.org/x/sys/unix/ioctl_linux.go | 96 + .../vendor/golang.org/x/sys/unix/mkerrors.sh | 20 +- .../golang.org/x/sys/unix/mmap_nomremap.go | 2 +- .../vendor/golang.org/x/sys/unix/mremap.go | 5 + .../golang.org/x/sys/unix/pagesize_unix.go | 2 +- .../x/sys/unix/readdirent_getdirentries.go | 2 +- .../golang.org/x/sys/unix/sockcmsg_zos.go | 58 + .../golang.org/x/sys/unix/symaddr_zos_s390x.s | 75 + .../golang.org/x/sys/unix/syscall_aix.go | 2 +- .../golang.org/x/sys/unix/syscall_darwin.go | 61 + .../x/sys/unix/syscall_dragonfly.go | 12 + .../golang.org/x/sys/unix/syscall_hurd.go | 1 + .../golang.org/x/sys/unix/syscall_linux.go | 65 +- .../x/sys/unix/syscall_linux_arm64.go | 2 + .../x/sys/unix/syscall_linux_loong64.go | 2 + .../x/sys/unix/syscall_linux_riscv64.go | 2 + .../golang.org/x/sys/unix/syscall_openbsd.go | 1 + .../golang.org/x/sys/unix/syscall_solaris.go | 87 + .../golang.org/x/sys/unix/syscall_unix.go | 9 + .../x/sys/unix/syscall_zos_s390x.go | 1597 ++++- .../golang.org/x/sys/unix/sysvshm_unix.go | 2 +- .../x/sys/unix/sysvshm_unix_other.go | 2 +- .../golang.org/x/sys/unix/vgetrandom_linux.go | 13 + .../x/sys/unix/vgetrandom_unsupported.go | 11 + .../x/sys/unix/zerrors_darwin_amd64.go | 12 + .../x/sys/unix/zerrors_darwin_arm64.go | 12 + .../golang.org/x/sys/unix/zerrors_linux.go | 129 +- .../x/sys/unix/zerrors_linux_386.go | 31 + .../x/sys/unix/zerrors_linux_amd64.go | 31 + .../x/sys/unix/zerrors_linux_arm.go | 30 + .../x/sys/unix/zerrors_linux_arm64.go | 33 + .../x/sys/unix/zerrors_linux_loong64.go | 30 + .../x/sys/unix/zerrors_linux_mips.go | 30 + .../x/sys/unix/zerrors_linux_mips64.go | 30 + .../x/sys/unix/zerrors_linux_mips64le.go | 30 + .../x/sys/unix/zerrors_linux_mipsle.go | 30 + .../x/sys/unix/zerrors_linux_ppc.go | 30 + .../x/sys/unix/zerrors_linux_ppc64.go | 30 + .../x/sys/unix/zerrors_linux_ppc64le.go | 30 + .../x/sys/unix/zerrors_linux_riscv64.go | 30 + .../x/sys/unix/zerrors_linux_s390x.go | 30 + .../x/sys/unix/zerrors_linux_sparc64.go | 30 + .../x/sys/unix/zerrors_zos_s390x.go | 235 +- .../x/sys/unix/zsymaddr_zos_s390x.s | 364 ++ .../x/sys/unix/zsyscall_darwin_amd64.go | 101 + .../x/sys/unix/zsyscall_darwin_amd64.s | 25 + .../x/sys/unix/zsyscall_darwin_arm64.go | 101 + .../x/sys/unix/zsyscall_darwin_arm64.s | 25 + .../golang.org/x/sys/unix/zsyscall_linux.go | 43 +- .../x/sys/unix/zsyscall_openbsd_386.go | 24 + .../x/sys/unix/zsyscall_openbsd_386.s | 5 + .../x/sys/unix/zsyscall_openbsd_amd64.go | 24 + .../x/sys/unix/zsyscall_openbsd_amd64.s | 5 + .../x/sys/unix/zsyscall_openbsd_arm.go | 24 + .../x/sys/unix/zsyscall_openbsd_arm.s | 5 + .../x/sys/unix/zsyscall_openbsd_arm64.go | 24 + .../x/sys/unix/zsyscall_openbsd_arm64.s | 5 + .../x/sys/unix/zsyscall_openbsd_mips64.go | 24 + .../x/sys/unix/zsyscall_openbsd_mips64.s | 5 + .../x/sys/unix/zsyscall_openbsd_ppc64.go | 24 + .../x/sys/unix/zsyscall_openbsd_ppc64.s | 6 + .../x/sys/unix/zsyscall_openbsd_riscv64.go | 24 + .../x/sys/unix/zsyscall_openbsd_riscv64.s | 5 + .../x/sys/unix/zsyscall_solaris_amd64.go | 114 + .../x/sys/unix/zsyscall_zos_s390x.go | 2837 ++++++++- .../x/sys/unix/zsysnum_linux_386.go | 10 + .../x/sys/unix/zsysnum_linux_amd64.go | 11 + .../x/sys/unix/zsysnum_linux_arm.go | 10 + .../x/sys/unix/zsysnum_linux_arm64.go | 12 +- .../x/sys/unix/zsysnum_linux_loong64.go | 12 + .../x/sys/unix/zsysnum_linux_mips.go | 10 + .../x/sys/unix/zsysnum_linux_mips64.go | 10 + .../x/sys/unix/zsysnum_linux_mips64le.go | 10 + .../x/sys/unix/zsysnum_linux_mipsle.go | 10 + .../x/sys/unix/zsysnum_linux_ppc.go | 10 + .../x/sys/unix/zsysnum_linux_ppc64.go | 10 + .../x/sys/unix/zsysnum_linux_ppc64le.go | 10 + .../x/sys/unix/zsysnum_linux_riscv64.go | 12 +- .../x/sys/unix/zsysnum_linux_s390x.go | 10 + .../x/sys/unix/zsysnum_linux_sparc64.go | 10 + .../x/sys/unix/zsysnum_zos_s390x.go | 5507 +++++++++-------- .../x/sys/unix/ztypes_darwin_amd64.go | 73 + .../x/sys/unix/ztypes_darwin_arm64.go | 73 + .../x/sys/unix/ztypes_freebsd_386.go | 1 + .../x/sys/unix/ztypes_freebsd_amd64.go | 1 + .../x/sys/unix/ztypes_freebsd_arm.go | 1 + .../x/sys/unix/ztypes_freebsd_arm64.go | 1 + .../x/sys/unix/ztypes_freebsd_riscv64.go | 1 + .../golang.org/x/sys/unix/ztypes_linux.go | 287 +- .../golang.org/x/sys/unix/ztypes_linux_386.go | 8 - .../x/sys/unix/ztypes_linux_amd64.go | 9 - .../golang.org/x/sys/unix/ztypes_linux_arm.go | 9 - .../x/sys/unix/ztypes_linux_arm64.go | 9 - .../x/sys/unix/ztypes_linux_loong64.go | 9 - .../x/sys/unix/ztypes_linux_mips.go | 9 - .../x/sys/unix/ztypes_linux_mips64.go | 9 - .../x/sys/unix/ztypes_linux_mips64le.go | 9 - .../x/sys/unix/ztypes_linux_mipsle.go | 9 - .../golang.org/x/sys/unix/ztypes_linux_ppc.go | 9 - .../x/sys/unix/ztypes_linux_ppc64.go | 9 - .../x/sys/unix/ztypes_linux_ppc64le.go | 9 - .../x/sys/unix/ztypes_linux_riscv64.go | 42 +- .../x/sys/unix/ztypes_linux_s390x.go | 9 - .../x/sys/unix/ztypes_linux_sparc64.go | 9 - .../golang.org/x/sys/unix/ztypes_zos_s390x.go | 152 +- .../golang.org/x/sys/windows/aliases.go | 2 +- .../golang.org/x/sys/windows/dll_windows.go | 13 +- .../vendor/golang.org/x/sys/windows/empty.s | 8 - .../x/sys/windows/security_windows.go | 25 +- .../x/sys/windows/syscall_windows.go | 134 +- .../golang.org/x/sys/windows/types_windows.go | 223 +- .../x/sys/windows/zsyscall_windows.go | 286 +- .../vendor/golang.org/x/term/LICENSE | 4 +- .../vendor/golang.org/x/term/README.md | 11 +- .../vendor/golang.org/x/term/term_windows.go | 1 + .../srs-bench/vendor/gopkg.in/yaml.v3/LICENSE | 50 - .../srs-bench/vendor/gopkg.in/yaml.v3/NOTICE | 13 - .../vendor/gopkg.in/yaml.v3/README.md | 150 - .../srs-bench/vendor/gopkg.in/yaml.v3/apic.go | 747 --- .../vendor/gopkg.in/yaml.v3/decode.go | 1000 --- .../vendor/gopkg.in/yaml.v3/emitterc.go | 2020 ------ .../vendor/gopkg.in/yaml.v3/encode.go | 577 -- .../vendor/gopkg.in/yaml.v3/parserc.go | 1258 ---- .../vendor/gopkg.in/yaml.v3/readerc.go | 434 -- .../vendor/gopkg.in/yaml.v3/resolve.go | 326 - .../vendor/gopkg.in/yaml.v3/scannerc.go | 3038 --------- .../vendor/gopkg.in/yaml.v3/sorter.go | 134 - .../vendor/gopkg.in/yaml.v3/writerc.go | 48 - .../srs-bench/vendor/gopkg.in/yaml.v3/yaml.go | 698 --- .../vendor/gopkg.in/yaml.v3/yamlh.go | 807 --- .../vendor/gopkg.in/yaml.v3/yamlprivateh.go | 198 - trunk/3rdparty/srs-bench/vendor/modules.txt | 205 +- .../srs-bench/vnet/example_udpproxy_test.go | 2 +- trunk/3rdparty/srs-bench/vnet/vnet.go | 2 +- trunk/doc/CHANGELOG.md | 1 + trunk/src/core/srs_core_version7.hpp | 2 +- 1033 files changed, 45965 insertions(+), 43331 deletions(-) delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/davecgh/go-spew/LICENSE delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/davecgh/go-spew/spew/bypass.go delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/davecgh/go-spew/spew/bypasssafe.go delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/davecgh/go-spew/spew/common.go delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/davecgh/go-spew/spew/config.go delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/davecgh/go-spew/spew/doc.go delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/davecgh/go-spew/spew/dump.go delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/davecgh/go-spew/spew/format.go delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/davecgh/go-spew/spew/spew.go delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/google/uuid/.travis.yml create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/google/uuid/CHANGELOG.md create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/google/uuid/version6.go create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/google/uuid/version7.go rename trunk/3rdparty/srs-bench/vendor/github.com/pion/{dtls/v2 => datachannel}/.goreleaser.yml (100%) delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/datachannel/AUTHORS.txt delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/datachannel/DESIGN.md delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/AUTHORS.txt delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/conn.go delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/errors.go delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_128_ccm.go delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_128_ccm8.go delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/internal/ciphersuite/tls_psk_with_aes_128_ccm.go delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/internal/ciphersuite/tls_psk_with_aes_128_ccm8.go delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/internal/ciphersuite/tls_psk_with_aes_256_ccm8.go delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/crypto/ciphersuite/cbc.go delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/extension/errors.go delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/handshake/errors.go delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/recordlayer/errors.go rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/.editorconfig (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/.gitignore (100%) create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/.golangci.yml rename trunk/3rdparty/srs-bench/vendor/github.com/pion/{ice/v2 => dtls/v3}/.goreleaser.yml (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/LICENSE (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/README.md (95%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/certificate.go (90%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/cipher_suite.go (78%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/cipher_suite_go114.go (96%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/codecov.yml (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/compression_method.go (83%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/config.go (68%) create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/conn.go create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/connection_id.go rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/crypto.go (65%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/dtls.go (100%) create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/errors.go rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/errors_errno.go (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/errors_noerrno.go (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/flight.go (98%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/flight0handler.go (67%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/flight1handler.go (60%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/flight2handler.go (76%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/flight3handler.go (65%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/flight4bhandler.go (72%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/flight4handler.go (72%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/flight5bhandler.go (77%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/flight5handler.go (79%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/flight6handler.go (81%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/flighthandler.go (78%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/fragment_buffer.go (80%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/handshake_cache.go (85%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/handshaker.go (58%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/internal/ciphersuite/aes_128_ccm.go (60%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/internal/ciphersuite/aes_256_ccm.go (60%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/internal/ciphersuite/aes_ccm.go (63%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/internal/ciphersuite/ciphersuite.go (86%) create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_128_ccm.go create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_128_ccm8.go rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_128_gcm_sha256.go (69%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_256_cbc_sha.go (73%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_256_gcm_sha384.go (82%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/internal/ciphersuite/tls_ecdhe_psk_with_aes_128_cbc_sha256.go (75%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/internal/ciphersuite/tls_ecdhe_rsa_with_aes_128_gcm_sha256.go (81%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/internal/ciphersuite/tls_ecdhe_rsa_with_aes_256_cbc_sha.go (81%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/internal/ciphersuite/tls_ecdhe_rsa_with_aes_256_gcm_sha384.go (81%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/internal/ciphersuite/tls_psk_with_aes_128_cbc_sha256.go (73%) create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/internal/ciphersuite/tls_psk_with_aes_128_ccm.go create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/internal/ciphersuite/tls_psk_with_aes_128_ccm8.go rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/internal/ciphersuite/tls_psk_with_aes_128_gcm_sha256.go (83%) create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/internal/ciphersuite/tls_psk_with_aes_256_ccm8.go rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/internal/ciphersuite/types/authentication_type.go (86%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/internal/ciphersuite/types/key_exchange_algorithm.go (94%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/internal/closer/closer.go (70%) create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/internal/net/buffer.go create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/internal/net/udp/packet_conn.go rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/internal/util/util.go (55%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/listener.go (69%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/packet.go (72%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/pkg/crypto/ccm/ccm.go (89%) create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/crypto/ciphersuite/cbc.go rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/pkg/crypto/ciphersuite/ccm.go (55%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/pkg/crypto/ciphersuite/ciphersuite.go (53%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/pkg/crypto/ciphersuite/gcm.go (57%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/pkg/crypto/clientcertificate/client_certificate.go (86%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/pkg/crypto/elliptic/elliptic.go (90%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/pkg/crypto/fingerprint/fingerprint.go (97%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/pkg/crypto/fingerprint/hash.go (97%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/pkg/crypto/hash/hash.go (92%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/pkg/crypto/prf/prf.go (89%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/pkg/crypto/signature/signature.go (86%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/pkg/crypto/signaturehash/errors.go (85%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/pkg/crypto/signaturehash/signaturehash.go (83%) create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/net/net.go rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/pkg/protocol/alert/alert.go (91%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/pkg/protocol/application_data.go (81%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/pkg/protocol/change_cipher_spec.go (83%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/pkg/protocol/compression_method.go (78%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/pkg/protocol/content.go (81%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/pkg/protocol/errors.go (84%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/pkg/protocol/extension/alpn.go (84%) create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/extension/connection_id.go create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/extension/errors.go rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/pkg/protocol/extension/extension.go (80%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/pkg/protocol/extension/renegotiation_info.go (88%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/pkg/protocol/extension/server_name.go (90%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/pkg/protocol/extension/srtp_protection_profile.go (66%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/pkg/protocol/extension/supported_elliptic_curves.go (83%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/pkg/protocol/extension/supported_point_formats.go (74%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/pkg/protocol/extension/supported_signature_algorithms.go (82%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/pkg/protocol/extension/use_master_secret.go (89%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/pkg/protocol/extension/use_srtp.go (53%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/pkg/protocol/handshake/cipher_suite.go (95%) create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/handshake/errors.go rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/pkg/protocol/handshake/handshake.go (84%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/pkg/protocol/handshake/header.go (91%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/pkg/protocol/handshake/message_certificate.go (75%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/pkg/protocol/handshake/message_certificate_request.go (89%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/pkg/protocol/handshake/message_certificate_verify.go (82%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/pkg/protocol/handshake/message_client_hello.go (76%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/pkg/protocol/handshake/message_client_key_exchange.go (88%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/pkg/protocol/handshake/message_finished.go (85%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/pkg/protocol/handshake/message_hello_verify_request.go (90%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/pkg/protocol/handshake/message_server_hello.go (81%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/pkg/protocol/handshake/message_server_hello_done.go (77%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/pkg/protocol/handshake/message_server_key_exchange.go (86%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/pkg/protocol/handshake/random.go (84%) create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/recordlayer/errors.go rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/pkg/protocol/recordlayer/header.go (54%) create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/recordlayer/inner_plaintext.go rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/pkg/protocol/recordlayer/recordlayer.go (54%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/pkg/protocol/version.go (89%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/renovate.json (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/resume.go (53%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/session.go (92%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/srtp_protection_profile.go (60%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/state.go (61%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/{v2 => v3}/util.go (99%) delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/AUTHORS.txt delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/addr.go delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/agent_handlers.go delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/agent_stats.go delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/candidate_base.go delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/candidatepair.go delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/context.go delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/mdns.go delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/net.go delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/test_utils.go delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/udp_muxed_conn.go rename trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/{v2 => v4}/.gitignore (100%) create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/.golangci.yml rename trunk/3rdparty/srs-bench/vendor/github.com/pion/{srtp/v2 => ice/v4}/.goreleaser.yml (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/{v2 => v4}/LICENSE (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/{v2 => v4}/README.md (65%) create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/active_tcp.go create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/addr.go rename trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/{v2 => v4}/agent.go (58%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/{v2 => v4}/agent_config.go (61%) create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/agent_handlers.go create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/agent_stats.go rename trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/{v2 => v4}/candidate.go (53%) create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/candidate_base.go rename trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/{v2 => v4}/candidate_host.go (58%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/{v2 => v4}/candidate_peer_reflexive.go (78%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/{v2 => v4}/candidate_relay.go (63%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/{v2 => v4}/candidate_server_reflexive.go (69%) create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/candidatepair.go rename trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/{v2 => v4}/candidatepair_state.go (88%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/{v2 => v4}/candidaterelatedaddress.go (93%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/{v2 => v4}/candidatetype.go (92%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/{v2 => v4}/codecov.yml (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/{v2 => v4}/errors.go (74%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/{v2 => v4}/external_ip_mapper.go (83%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/{v2 => v4}/gather.go (74%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/{v2 => v4}/ice.go (78%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/{v2 => v4}/icecontrol.go (98%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/{v2 => v4}/internal/atomic/atomic.go (73%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/{v2 => v4}/internal/fakenet/mock_conn.go (97%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/{v2 => v4}/internal/fakenet/packet_conn.go (80%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/{v2 => v4}/internal/stun/stun.go (96%) create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/internal/taskloop/taskloop.go create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/mdns.go create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/net.go rename trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/{v2 => v4}/networktype.go (87%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/{v2 => v4}/priority.go (96%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/{v2 => v4}/rand.go (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/{v2 => v4}/renovate.json (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/{v2 => v4}/role.go (99%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/{v2 => v4}/selection.go (66%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/{v2 => v4}/stats.go (93%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/{v2 => v4}/tcp_mux.go (71%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/{v2 => v4}/tcp_mux_multi.go (94%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/{v2 => v4}/tcp_packet_conn.go (79%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/{v2 => v4}/tcptype.go (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/{v2 => v4}/transport.go (79%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/{v2 => v4}/udp_mux.go (70%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/{v2 => v4}/udp_mux_multi.go (84%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/{v2 => v4}/udp_mux_universal.go (85%) create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/udp_muxed_conn.go rename trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/{v2 => v4}/url.go (67%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/{v2 => v4}/usecandidate.go (94%) delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/AUTHORS.txt create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/internal/sequencenumber/unwrapper.go create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/pkg/report/ticker.go create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/pkg/rfc8888/interceptor.go create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/pkg/rfc8888/option.go create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/pkg/rfc8888/recorder.go create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/pkg/rfc8888/stream_log.go create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/pkg/rfc8888/ticker.go create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/pkg/rfc8888/unwrapper.go create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/pkg/twcc/arrival_time_map.go rename trunk/3rdparty/srs-bench/vendor/github.com/pion/{srtp/v2 => logging}/.gitignore (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/{stun => logging}/.goreleaser.yml (100%) delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/logging/.travis.yml rename trunk/3rdparty/srs-bench/vendor/github.com/pion/{srtp/v2 => logging}/codecov.yml (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/{mdns => logging}/renovate.json (100%) delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/mdns/.golangci.yml delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/mdns/.goreleaser.yml delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/mdns/AUTHORS.txt delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/mdns/config.go delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/mdns/conn.go delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/mdns/mdns.go rename trunk/3rdparty/srs-bench/vendor/github.com/pion/{stun => mdns/v2}/.gitignore (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/{ice => mdns}/v2/.golangci.yml (96%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/{transport => mdns}/v2/.goreleaser.yml (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/mdns/{ => v2}/LICENSE (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/mdns/{ => v2}/README.md (56%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/{stun => mdns/v2}/codecov.yml (100%) create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/mdns/v2/config.go create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/mdns/v2/conn.go rename trunk/3rdparty/srs-bench/vendor/github.com/pion/mdns/{ => v2}/errors.go (80%) create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/mdns/v2/mdns.go rename trunk/3rdparty/srs-bench/vendor/github.com/pion/{srtp => mdns}/v2/renovate.json (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/{webrtc/v3 => rtcp}/.goreleaser.yml (100%) delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/AUTHORS.txt create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/application_defined.go delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/fuzz.go create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/.goreleaser.yml delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/AUTHORS.txt create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/abscapturetimeextension.go create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/av1/obu/errors.go rename trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/{pkg => codecs/av1}/obu/leb128.go (64%) create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/av1/obu/obu.go create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/av1_depacketizer.go create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/vp9/bits.go create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/vp9/header.go create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/payload_types.go delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/pkg/frame/av1.go create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/playoutdelayextension.go create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/vlaextension.go delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/AUTHORS.txt create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/param_zero_checksum.go create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/queue.go create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/receive_payload_queue.go create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/.goreleaser.yml delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/AUTHORS.txt delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/fuzz.go create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/unmarshal_cache.go delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/AUTHORS.txt delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/option.go delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/protection_profile.go rename trunk/3rdparty/srs-bench/vendor/github.com/pion/{transport/v2 => srtp/v3}/.gitignore (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/{turn/v2 => srtp/v3}/.golangci.yml (92%) create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v3/.goreleaser.yml rename trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/{v2 => v3}/LICENSE (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/{v2 => v3}/README.md (97%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/{transport/v2 => srtp/v3}/codecov.yml (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/{v2 => v3}/context.go (63%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/{v2 => v3}/crypto.go (68%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/{v2 => v3}/errors.go (74%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/{v2 => v3}/key_derivation.go (91%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/{v2 => v3}/keying.go (95%) create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v3/option.go create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v3/protection_profile.go rename trunk/3rdparty/srs-bench/vendor/github.com/pion/{stun => srtp/v3}/renovate.json (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/{v2 => v3}/session.go (98%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/{v2 => v3}/session_srtcp.go (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/{v2 => v3}/session_srtp.go (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/{v2 => v3}/srtcp.go (76%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/{v2 => v3}/srtp.go (79%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/{v2 => v3}/srtp_cipher.go (86%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/{v2 => v3}/srtp_cipher_aead_aes_gcm.go (57%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/{v2 => v3}/srtp_cipher_aes_cm_hmac_sha1.go (65%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/{v2 => v3}/stream.go (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/{v2 => v3}/stream_srtcp.go (98%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/{v2 => v3}/stream_srtp.go (98%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/{v2 => v3}/util.go (100%) delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/AUTHORS.txt rename trunk/3rdparty/srs-bench/vendor/github.com/pion/{webrtc => stun}/v3/.gitignore (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/{dtls/v2 => stun/v3}/.golangci.yml (95%) create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/v3/.goreleaser.yml rename trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/{ => v3}/LICENSE (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/{ => v3}/Makefile (96%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/{ => v3}/README.md (99%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/{ => v3}/addr.go (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/{ => v3}/agent.go (99%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/{ => v3}/attributes.go (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/{ => v3}/attributes_debug.go (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/{ => v3}/checks.go (96%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/{ => v3}/checks_debug.go (96%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/{ => v3}/client.go (97%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/{webrtc => stun}/v3/codecov.yml (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/{ => v3}/errorcode.go (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/{ => v3}/errors.go (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/{ => v3}/fingerprint.go (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/{ => v3}/fingerprint_debug.go (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/{ => v3}/helpers.go (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/{ => v3}/integrity.go (98%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/{ => v3}/integrity_debug.go (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/{ => v3}/internal/hmac/hmac.go (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/{ => v3}/internal/hmac/pool.go (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/{ => v3}/internal/hmac/vendor.sh (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/{ => v3}/message.go (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/{transport/v2 => stun/v3}/renovate.json (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/{ => v3}/stun.go (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/{ => v3}/textattrs.go (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/{ => v3}/uattrs.go (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/{ => v3}/uri.go (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/{ => v3}/xoraddr.go (98%) delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/.golangci.yml delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/AUTHORS.txt delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/udp/conn.go delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/utils/xor/xor_amd64.go delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/utils/xor/xor_amd64.s delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/utils/xor/xor_arm64.go delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/utils/xor/xor_arm64.s delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/utils/xor/xor_ppc64x.go delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/utils/xor/xor_ppc64x.s rename trunk/3rdparty/srs-bench/vendor/github.com/pion/{mdns => transport/v3}/.gitignore (75%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/{srtp/v2 => transport/v3}/.golangci.yml (95%) create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/.goreleaser.yml rename trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/{v2 => v3}/LICENSE (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/{v2 => v3}/README.md (97%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/{mdns => transport/v3}/codecov.yml (78%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/{v2 => v3}/deadline/deadline.go (59%) create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/deadline/timer.go create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/deadline/timer_generic.go create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/deadline/timer_js.go rename trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/{v2 => v3}/net.go (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/{v2/connctx/connctx.go => v3/netctx/conn.go} (70%) create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/netctx/packetconn.go rename trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/{v2/connctx => v3/netctx}/pipe.go (56%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/{v2 => v3}/packetio/buffer.go (93%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/{v2 => v3}/packetio/errors.go (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/{v2 => v3}/packetio/hardlimit.go (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/{v2 => v3}/packetio/no_hardlimit.go (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/{turn/v2 => transport/v3}/renovate.json (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/{v2 => v3}/replaydetector/fixedbig.go (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/{v2 => v3}/replaydetector/replaydetector.go (78%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/{v2 => v3}/stdnet/net.go (95%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/{v2 => v3}/utils/xor/xor_arm.go (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/{v2 => v3}/utils/xor/xor_arm.s (100%) create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/utils/xor/xor_generic.go rename trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/{v2/utils/xor/xor_generic.go => v3/utils/xor/xor_old.go} (82%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/{v2 => v3}/vnet/.gitignore (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/{v2 => v3}/vnet/README.md (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/{v2 => v3}/vnet/chunk.go (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/{v2 => v3}/vnet/chunk_queue.go (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/{v2 => v3}/vnet/conn.go (99%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/{v2 => v3}/vnet/conn_map.go (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/{v2 => v3}/vnet/delay_filter.go (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/{v2 => v3}/vnet/errors.go (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/{v2 => v3}/vnet/loss_filter.go (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/{v2 => v3}/vnet/nat.go (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/{v2 => v3}/vnet/net.go (99%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/{v2 => v3}/vnet/resolver.go (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/{v2 => v3}/vnet/router.go (99%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/{v2 => v3}/vnet/tbf.go (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/{v2 => v3}/vnet/udpproxy.go (99%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/{v2 => v3}/vnet/udpproxy_direct.go (95%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/{v2 => v3}/vnet/vnet.go (100%) delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/.goreleaser.yml delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/AUTHORS.txt delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/DESIGN.md delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/FAQ.md delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/allocation/five_tuple.go delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/lt_cred.go rename trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/{v2 => v4}/.gitignore (75%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/{stun => turn/v4}/.golangci.yml (95%) create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/.goreleaser.yml rename trunk/3rdparty/srs-bench/vendor/github.com/pion/{webrtc/v3 => turn/v4}/LICENSE (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/{v2 => v4}/README.md (59%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/{v2 => v4}/client.go (63%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/{v2 => v4}/codecov.yml (78%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/{v2 => v4}/errors.go (91%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/{v2 => v4}/internal/allocation/allocation.go (90%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/{v2 => v4}/internal/allocation/allocation_manager.go (94%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/{v2 => v4}/internal/allocation/channel_bind.go (83%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/{v2 => v4}/internal/allocation/errors.go (92%) create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/allocation/five_tuple.go rename trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/{v2 => v4}/internal/allocation/permission.go (85%) create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/client/allocation.go rename trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/{v2 => v4}/internal/client/binding.go (85%) create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/client/client.go rename trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/{v2 => v4}/internal/client/errors.go (75%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/{v2 => v4}/internal/client/periodic_timer.go (90%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/{v2 => v4}/internal/client/permission.go (68%) create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/client/tcp_alloc.go create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/client/tcp_conn.go rename trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/{v2 => v4}/internal/client/transaction.go (81%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/{v2 => v4}/internal/client/trylock.go (81%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/{v2/internal/client/conn.go => v4/internal/client/udp_conn.go} (56%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/{v2 => v4}/internal/ipnet/util.go (65%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/{v2 => v4}/internal/proto/addr.go (91%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/{v2 => v4}/internal/proto/chandata.go (92%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/{v2 => v4}/internal/proto/chann.go (88%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/{v2 => v4}/internal/proto/connection_id.go (83%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/{v2 => v4}/internal/proto/data.go (83%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/{v2 => v4}/internal/proto/dontfrag.go (84%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/{v2 => v4}/internal/proto/evenport.go (89%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/{v2 => v4}/internal/proto/lifetime.go (86%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/{v2 => v4}/internal/proto/peeraddr.go (89%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/{v2 => v4}/internal/proto/proto.go (88%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/{v2 => v4}/internal/proto/relayedaddr.go (88%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/{v2 => v4}/internal/proto/reqfamily.go (92%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/{v2 => v4}/internal/proto/reqtrans.go (86%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/{v2 => v4}/internal/proto/rsrvtoken.go (89%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/{v2 => v4}/internal/server/errors.go (85%) create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/server/nonce.go rename trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/{v2 => v4}/internal/server/server.go (76%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/{v2 => v4}/internal/server/stun.go (60%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/{v2 => v4}/internal/server/turn.go (89%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/{v2 => v4}/internal/server/util.go (65%) create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/lt_cred.go rename trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/{v2 => v4}/relay_address_generator_none.go (82%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/{v2 => v4}/relay_address_generator_range.go (90%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/{v2 => v4}/relay_address_generator_static.go (86%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/{webrtc/v3 => turn/v4}/renovate.json (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/{v2 => v4}/server.go (66%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/{v2 => v4}/server_config.go (94%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/{v2 => v4}/stun_conn.go (93%) delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/.golangci.yml delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/AUTHORS.txt delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/constants.go delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/internal/fmtp/fmtp.go delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/operations.go delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/package.json delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/pkg/media/ivfwriter/ivfwriter.go delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/track_local.go delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/yarn.lock rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/.codacy.yaml (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/.eslintrc.json (100%) create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/.gitignore create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/.golangci.yml create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/.goreleaser.yml rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/DESIGN.md (97%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/{turn/v2/LICENSE.md => webrtc/v4/LICENSE} (93%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/README.md (70%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/api.go (67%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/api_js.go (91%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/atomicbool.go (99%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/bundlepolicy.go (91%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/certificate.go (72%) create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/codecov.yml rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/configuration.go (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/configuration_common.go (99%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/configuration_js.go (95%) create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/constants.go rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/datachannel.go (77%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/datachannel_js.go (87%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/datachannel_js_detach.go (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/datachannelinit.go (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/datachannelmessage.go (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/datachannelparameters.go (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/datachannelstate.go (79%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/dtlsfingerprint.go (88%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/dtlsparameters.go (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/dtlsrole.go (93%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/dtlstransport.go (79%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/dtlstransport_js.go (88%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/dtlstransportstate.go (82%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/errors.go (69%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/gathering_complete_promise.go (87%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/ice_go.go (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/icecandidate.go (55%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/icecandidateinit.go (85%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/icecandidatepair.go (87%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/icecandidatetype.go (78%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/icecomponent.go (90%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/iceconnectionstate.go (94%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/icecredentialtype.go (97%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/icegatherer.go (76%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/icegathererstate.go (89%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/icegatheringstate.go (89%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/icegatheroptions.go (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/icemux.go (96%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/iceparameters.go (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/iceprotocol.go (79%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/icerole.go (75%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/iceserver.go (89%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/iceserver_js.go (97%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/icetransport.go (70%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/icetransport_js.go (88%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/icetransportpolicy.go (89%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/icetransportstate.go (64%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/interceptor.go (56%) create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/internal/fmtp/av1.go create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/internal/fmtp/fmtp.go rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/internal/fmtp/h264.go (93%) create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/internal/fmtp/vp9.go rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/internal/mux/endpoint.go (53%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/internal/mux/mux.go (53%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/internal/mux/muxfunc.go (94%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/internal/util/util.go (88%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/js_utils.go (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/mediaengine.go (58%) create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/mimetype.go rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/networktype.go (84%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/oauthcredential.go (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/offeransweroptions.go (97%) create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/operations.go create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/package.json rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/peerconnection.go (69%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/peerconnection_js.go (99%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/peerconnectionstate.go (88%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/pkg/media/h264reader/h264reader.go (97%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/pkg/media/h264reader/nalunittype.go (95%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/pkg/media/h264writer/h264writer.go (94%) create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/pkg/media/ivfwriter/ivfwriter.go rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/pkg/media/media.go (68%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/pkg/media/oggreader/oggreader.go (84%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/pkg/media/oggwriter/oggwriter.go (83%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/pkg/rtcerr/errors.go (100%) create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/renovate.json rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/rtcpfeedback.go (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/rtcpmuxpolicy.go (89%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/rtpcapabilities.go (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/rtpcodec.go (55%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/rtpcodingparameters.go (74%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/rtpdecodingparameters.go (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/rtpencodingparameters.go (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/rtpreceiveparameters.go (95%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/rtpreceiver.go (61%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/rtpreceiver_go.go (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/rtpreceiver_js.go (76%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/rtpsender.go (68%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/rtpsender_js.go (77%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/rtpsendparameters.go (97%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/rtptransceiver.go (85%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/rtptransceiver_js.go (90%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/rtptransceiverdirection.go (86%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/rtptransceiverinit.go (53%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/sctpcapabilities.go (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/sctptransport.go (69%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/sctptransport_js.go (84%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/sctptransportstate.go (90%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/sdp.go (53%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/sdpsemantics.go (92%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/sdptype.go (89%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/sessiondescription.go (85%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/settingengine.go (62%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/settingengine_js.go (100%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/signalingstate.go (94%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/srtp_writer_future.go (95%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/stats.go (59%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/stats_go.go (91%) create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/track_local.go rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/track_local_static.go (65%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/track_remote.go (68%) rename trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/{v3 => v4}/webrtc.go (100%) create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/yarn.lock delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pmezard/go-difflib/LICENSE delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/pmezard/go-difflib/difflib/difflib.go delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/LICENSE delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/assert/assertion_compare.go delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/assert/assertion_format.go delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/assert/assertion_format.go.tmpl delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/assert/assertion_forward.go delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/assert/assertion_forward.go.tmpl delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/assert/assertion_order.go delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/assert/assertions.go delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/assert/doc.go delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/assert/errors.go delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/assert/forward_assertions.go delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/assert/http_assertions.go delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/require/doc.go delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/require/forward_requirements.go delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/require/require.go delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/require/require.go.tmpl delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/require/require_forward.go delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/require/require_forward.go.tmpl delete mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/require/requirements.go create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/wlynxg/anet/.gitignore create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/wlynxg/anet/LICENSE create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/wlynxg/anet/README.md create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/wlynxg/anet/README_zh.md create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/wlynxg/anet/android_api_level.go create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/wlynxg/anet/android_api_level_cgo.go create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/wlynxg/anet/interface.go create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/wlynxg/anet/interface_android.go create mode 100644 trunk/3rdparty/srs-bench/vendor/github.com/wlynxg/anet/netlink_android.go delete mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/crypto/curve25519/curve25519_compat.go delete mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/crypto/curve25519/curve25519_go120.go delete mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/crypto/curve25519/internal/field/README delete mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/crypto/curve25519/internal/field/fe.go delete mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/crypto/curve25519/internal/field/fe_amd64.go delete mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/crypto/curve25519/internal/field/fe_amd64.s delete mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/crypto/curve25519/internal/field/fe_amd64_noasm.go delete mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/crypto/curve25519/internal/field/fe_arm64.go delete mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/crypto/curve25519/internal/field/fe_arm64.s delete mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/crypto/curve25519/internal/field/fe_arm64_noasm.go delete mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/crypto/curve25519/internal/field/fe_generic.go delete mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/crypto/curve25519/internal/field/sync.checkpoint delete mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/crypto/curve25519/internal/field/sync.sh create mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/batch.go create mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/control.go create mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/control_rfc2292_unix.go create mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/control_rfc3542_unix.go create mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/control_stub.go create mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/control_unix.go create mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/control_windows.go create mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/dgramopt.go create mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/doc.go create mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/endpoint.go create mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/genericopt.go create mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/header.go create mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/helper.go create mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/iana.go create mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/icmp.go create mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/icmp_bsd.go create mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/icmp_linux.go create mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/icmp_solaris.go create mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/icmp_stub.go create mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/icmp_windows.go create mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/icmp_zos.go create mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/payload.go create mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/payload_cmsg.go create mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/payload_nocmsg.go create mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/sockopt.go create mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/sockopt_posix.go create mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/sockopt_stub.go create mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/sys_aix.go create mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/sys_asmreq.go create mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/sys_asmreq_stub.go create mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/sys_bpf.go create mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/sys_bpf_stub.go create mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/sys_bsd.go create mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/sys_darwin.go create mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/sys_freebsd.go create mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/sys_linux.go create mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/sys_solaris.go create mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/sys_ssmreq.go create mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/sys_ssmreq_stub.go create mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/sys_stub.go create mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/sys_windows.go create mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/sys_zos.go create mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_aix_ppc64.go create mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_darwin.go create mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_dragonfly.go create mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_freebsd_386.go create mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_freebsd_amd64.go create mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_freebsd_arm.go create mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_freebsd_arm64.go create mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_freebsd_riscv64.go create mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_linux_386.go create mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_linux_amd64.go create mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_linux_arm.go create mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_linux_arm64.go create mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_linux_loong64.go create mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_linux_mips.go create mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_linux_mips64.go create mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_linux_mips64le.go create mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_linux_mipsle.go create mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_linux_ppc.go create mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_linux_ppc64.go create mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_linux_ppc64le.go create mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_linux_riscv64.go create mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_linux_s390x.go create mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_netbsd.go create mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_openbsd.go create mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_solaris.go create mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_zos_s390x.go create mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/cpu/asm_darwin_x86_gc.s create mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/cpu/cpu_darwin_x86.go rename trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/cpu/{cpu_x86.s => cpu_gc_x86.s} (94%) create mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/cpu/cpu_linux_riscv64.go create mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/cpu/cpu_other_x86.go create mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/cpu/syscall_darwin_x86_gc.go create mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/auxv.go create mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/auxv_unsupported.go create mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/bpxsvc_zos.go create mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/bpxsvc_zos.s delete mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/epoll_zos.go delete mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/fstatfs_zos.go create mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/sockcmsg_zos.go create mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/symaddr_zos_s390x.s create mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/vgetrandom_linux.go create mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/vgetrandom_unsupported.go create mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsymaddr_zos_s390x.s delete mode 100644 trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/windows/empty.s delete mode 100644 trunk/3rdparty/srs-bench/vendor/gopkg.in/yaml.v3/LICENSE delete mode 100644 trunk/3rdparty/srs-bench/vendor/gopkg.in/yaml.v3/NOTICE delete mode 100644 trunk/3rdparty/srs-bench/vendor/gopkg.in/yaml.v3/README.md delete mode 100644 trunk/3rdparty/srs-bench/vendor/gopkg.in/yaml.v3/apic.go delete mode 100644 trunk/3rdparty/srs-bench/vendor/gopkg.in/yaml.v3/decode.go delete mode 100644 trunk/3rdparty/srs-bench/vendor/gopkg.in/yaml.v3/emitterc.go delete mode 100644 trunk/3rdparty/srs-bench/vendor/gopkg.in/yaml.v3/encode.go delete mode 100644 trunk/3rdparty/srs-bench/vendor/gopkg.in/yaml.v3/parserc.go delete mode 100644 trunk/3rdparty/srs-bench/vendor/gopkg.in/yaml.v3/readerc.go delete mode 100644 trunk/3rdparty/srs-bench/vendor/gopkg.in/yaml.v3/resolve.go delete mode 100644 trunk/3rdparty/srs-bench/vendor/gopkg.in/yaml.v3/scannerc.go delete mode 100644 trunk/3rdparty/srs-bench/vendor/gopkg.in/yaml.v3/sorter.go delete mode 100644 trunk/3rdparty/srs-bench/vendor/gopkg.in/yaml.v3/writerc.go delete mode 100644 trunk/3rdparty/srs-bench/vendor/gopkg.in/yaml.v3/yaml.go delete mode 100644 trunk/3rdparty/srs-bench/vendor/gopkg.in/yaml.v3/yamlh.go delete mode 100644 trunk/3rdparty/srs-bench/vendor/gopkg.in/yaml.v3/yamlprivateh.go diff --git a/trunk/3rdparty/srs-bench/gb28181/ingester.go b/trunk/3rdparty/srs-bench/gb28181/ingester.go index d4107ea3a..87d9752dc 100644 --- a/trunk/3rdparty/srs-bench/gb28181/ingester.go +++ b/trunk/3rdparty/srs-bench/gb28181/ingester.go @@ -22,11 +22,6 @@ package gb28181 import ( "context" - "github.com/ghettovoice/gosip/sip" - "github.com/ossrs/go-oryx-lib/errors" - "github.com/ossrs/go-oryx-lib/logger" - "github.com/pion/webrtc/v3/pkg/media/h264reader" - "github.com/yapingcat/gomedia/mpeg2" "io" "os" "path" @@ -34,6 +29,12 @@ import ( "strings" "sync" "time" + + "github.com/ghettovoice/gosip/sip" + "github.com/ossrs/go-oryx-lib/errors" + "github.com/ossrs/go-oryx-lib/logger" + "github.com/pion/webrtc/v4/pkg/media/h264reader" + "github.com/yapingcat/gomedia/mpeg2" ) type GBSessionConfig struct { diff --git a/trunk/3rdparty/srs-bench/go.mod b/trunk/3rdparty/srs-bench/go.mod index d4667a1a5..d762e6f52 100644 --- a/trunk/3rdparty/srs-bench/go.mod +++ b/trunk/3rdparty/srs-bench/go.mod @@ -1,53 +1,50 @@ module github.com/ossrs/srs-bench -go 1.17 +go 1.21 require ( github.com/ghettovoice/gosip v0.0.0-20220929080231-de8ba881be83 github.com/google/gopacket v1.1.19 github.com/haivision/srtgo v0.0.0-20230627061225-a70d53fcd618 github.com/ossrs/go-oryx-lib v0.0.9 - github.com/pion/ice/v2 v2.3.6 - github.com/pion/interceptor v0.1.17 - github.com/pion/logging v0.2.2 - github.com/pion/rtcp v1.2.10 - github.com/pion/rtp v1.7.13 - github.com/pion/sdp/v3 v3.0.6 - github.com/pion/transport/v2 v2.2.1 - github.com/pion/webrtc/v3 v3.2.9 + github.com/pion/ice/v4 v4.0.10 + github.com/pion/interceptor v0.1.37 + github.com/pion/logging v0.2.3 + github.com/pion/rtcp v1.2.15 + github.com/pion/rtp v1.8.15 + github.com/pion/sdp/v3 v3.0.11 + github.com/pion/transport/v3 v3.0.7 + github.com/pion/webrtc/v4 v4.1.1 github.com/pkg/errors v0.9.1 github.com/yapingcat/gomedia/codec v0.0.0-20220617074658-94762898dc25 github.com/yapingcat/gomedia/mpeg2 v0.0.0-20220617074658-94762898dc25 ) require ( - github.com/davecgh/go-spew v1.1.1 // indirect github.com/gobwas/httphead v0.1.0 // indirect github.com/gobwas/pool v0.2.1 // indirect github.com/gobwas/ws v1.1.0-rc.1 // indirect - github.com/google/uuid v1.3.0 // indirect + github.com/google/uuid v1.6.0 // indirect github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect github.com/mattn/go-colorable v0.1.4 // indirect github.com/mattn/go-isatty v0.0.8 // indirect github.com/mattn/go-pointer v0.0.1 // indirect github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect - github.com/pion/datachannel v1.5.5 // indirect - github.com/pion/dtls/v2 v2.2.7 // indirect - github.com/pion/mdns v0.0.7 // indirect + github.com/pion/datachannel v1.5.10 // indirect + github.com/pion/dtls/v3 v3.0.6 // indirect + github.com/pion/mdns/v2 v2.0.7 // indirect github.com/pion/randutil v0.1.0 // indirect - github.com/pion/sctp v1.8.7 // indirect - github.com/pion/srtp/v2 v2.0.15 // indirect - github.com/pion/stun v0.6.0 // indirect - github.com/pion/turn/v2 v2.1.0 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/pion/sctp v1.8.39 // indirect + github.com/pion/srtp/v3 v3.0.4 // indirect + github.com/pion/stun/v3 v3.0.0 // indirect + github.com/pion/turn/v4 v4.0.0 // indirect github.com/satori/go.uuid v1.2.1-0.20181028125025-b2ce2384e17b // indirect github.com/sirupsen/logrus v1.4.2 // indirect - github.com/stretchr/testify v1.9.0 // indirect github.com/tevino/abool v0.0.0-20170917061928-9b9efcf221b5 // indirect + github.com/wlynxg/anet v0.0.5 // indirect github.com/x-cray/logrus-prefixed-formatter v0.5.2 // indirect - golang.org/x/crypto v0.21.0 // indirect - golang.org/x/net v0.21.0 // indirect - golang.org/x/sys v0.18.0 // indirect - golang.org/x/term v0.18.0 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect + golang.org/x/crypto v0.33.0 // indirect + golang.org/x/net v0.35.0 // indirect + golang.org/x/sys v0.30.0 // indirect + golang.org/x/term v0.29.0 // indirect ) diff --git a/trunk/3rdparty/srs-bench/go.sum b/trunk/3rdparty/srs-bench/go.sum index 9c5733d4a..6ace3527b 100644 --- a/trunk/3rdparty/srs-bench/go.sum +++ b/trunk/3rdparty/srs-bench/go.sum @@ -1,4 +1,3 @@ -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/discoviking/fsm v0.0.0-20150126104936-f4a273feecca/go.mod h1:W+3LQaEkN8qAwwcw0KC546sUEnX86GIT8CcMLZC4mG0= @@ -7,7 +6,6 @@ github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWo github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/ghettovoice/gosip v0.0.0-20220929080231-de8ba881be83 h1:4v14bwSGZH2usyuG9XWZgMbGkVU33ayg0cb68nvKfj0= github.com/ghettovoice/gosip v0.0.0-20220929080231-de8ba881be83/go.mod h1:yTr3BEYSFe9As6XM7ldyrVgqsPwlnw8Ahc4N28VFM2g= -github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU= github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM= github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og= @@ -21,16 +19,13 @@ github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrU github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8= github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/haivision/srtgo v0.0.0-20230627061225-a70d53fcd618 h1:oGPTZa7I5wqmQs/UhWHj3ln6/CjQX2yQt784xx6H0wI= github.com/haivision/srtgo v0.0.0-20230627061225-a70d53fcd618/go.mod h1:aTd4vOr9wtzkCbbocUFh6atlJy7H/iV5jhqEWlTdCdA= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= @@ -39,9 +34,8 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3 github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE= @@ -51,13 +45,11 @@ github.com/mattn/go-pointer v0.0.1/go.mod h1:2zXcozF6qYGgmsG+SeTZz3oAbFLdD3OWqnU github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4= github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/nxadm/tail v1.4.5 h1:obHEce3upls1IBn1gTw/o7bCv7OJb6Ib/o7wNO+4eKw= github.com/nxadm/tail v1.4.5/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= -github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= -github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.14.2/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= -github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= @@ -67,71 +59,54 @@ github.com/onsi/gomega v1.17.0 h1:9Luw4uT5HTjHTN8+aNcSThgH1vdXnmdJ8xIfZ4wyTRE= github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/ossrs/go-oryx-lib v0.0.9 h1:piZkzit/1hqAcXP31/mvDEDpHVjCmBMmvzF3hN8hUuQ= github.com/ossrs/go-oryx-lib v0.0.9/go.mod h1:i2tH4TZBzAw5h+HwGrNOKvP/nmZgSQz0OEnLLdzcT/8= -github.com/pion/datachannel v1.5.5 h1:10ef4kwdjije+M9d7Xm9im2Y3O6A6ccQb0zcqZcJew8= -github.com/pion/datachannel v1.5.5/go.mod h1:iMz+lECmfdCMqFRhXhcA/219B0SQlbpoR2V118yimL0= -github.com/pion/dtls/v2 v2.2.7 h1:cSUBsETxepsCSFSxC3mc/aDo14qQLMSL+O6IjG28yV8= -github.com/pion/dtls/v2 v2.2.7/go.mod h1:8WiMkebSHFD0T+dIU+UeBaoV7kDhOW5oDCzZ7WZ/F9s= -github.com/pion/ice/v2 v2.3.6 h1:Jgqw36cAud47iD+N6rNX225uHvrgWtAlHfVyOQc3Heg= -github.com/pion/ice/v2 v2.3.6/go.mod h1:9/TzKDRwBVAPsC+YOrKH/e3xDrubeTRACU9/sHQarsU= -github.com/pion/interceptor v0.1.17 h1:prJtgwFh/gB8zMqGZoOgJPHivOwVAp61i2aG61Du/1w= -github.com/pion/interceptor v0.1.17/go.mod h1:SY8kpmfVBvrbUzvj2bsXz7OJt5JvmVNZ+4Kjq7FcwrI= -github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY= -github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms= -github.com/pion/mdns v0.0.7 h1:P0UB4Sr6xDWEox0kTVxF0LmQihtCbSAdW0H2nEgkA3U= -github.com/pion/mdns v0.0.7/go.mod h1:4iP2UbeFhLI/vWju/bw6ZfwjJzk0z8DNValjGxR/dD8= +github.com/pion/datachannel v1.5.10 h1:ly0Q26K1i6ZkGf42W7D4hQYR90pZwzFOjTq5AuCKk4o= +github.com/pion/datachannel v1.5.10/go.mod h1:p/jJfC9arb29W7WrxyKbepTU20CFgyx5oLo8Rs4Py/M= +github.com/pion/dtls/v3 v3.0.6 h1:7Hkd8WhAJNbRgq9RgdNh1aaWlZlGpYTzdqjy9x9sK2E= +github.com/pion/dtls/v3 v3.0.6/go.mod h1:iJxNQ3Uhn1NZWOMWlLxEEHAN5yX7GyPvvKw04v9bzYU= +github.com/pion/ice/v4 v4.0.10 h1:P59w1iauC/wPk9PdY8Vjl4fOFL5B+USq1+xbDcN6gT4= +github.com/pion/ice/v4 v4.0.10/go.mod h1:y3M18aPhIxLlcO/4dn9X8LzLLSma84cx6emMSu14FGw= +github.com/pion/interceptor v0.1.37 h1:aRA8Zpab/wE7/c0O3fh1PqY0AJI3fCSEM5lRWJVorwI= +github.com/pion/interceptor v0.1.37/go.mod h1:JzxbJ4umVTlZAf+/utHzNesY8tmRkM2lVmkS82TTj8Y= +github.com/pion/logging v0.2.3 h1:gHuf0zpoh1GW67Nr6Gj4cv5Z9ZscU7g/EaoC/Ke/igI= +github.com/pion/logging v0.2.3/go.mod h1:z8YfknkquMe1csOrxK5kc+5/ZPAzMxbKLX5aXpbpC90= +github.com/pion/mdns/v2 v2.0.7 h1:c9kM8ewCgjslaAmicYMFQIde2H9/lrZpjBkN8VwoVtM= +github.com/pion/mdns/v2 v2.0.7/go.mod h1:vAdSYNAT0Jy3Ru0zl2YiW3Rm/fJCwIeM0nToenfOJKA= github.com/pion/randutil v0.1.0 h1:CFG1UdESneORglEsnimhUjf33Rwjubwj6xfiOXBa3mA= github.com/pion/randutil v0.1.0/go.mod h1:XcJrSMMbbMRhASFVOlj/5hQial/Y8oH/HVo7TBZq+j8= -github.com/pion/rtcp v1.2.10 h1:nkr3uj+8Sp97zyItdN60tE/S6vk4al5CPRR6Gejsdjc= -github.com/pion/rtcp v1.2.10/go.mod h1:ztfEwXZNLGyF1oQDttz/ZKIBaeeg/oWbRYqzBM9TL1I= -github.com/pion/rtp v1.7.13 h1:qcHwlmtiI50t1XivvoawdCGTP4Uiypzfrsap+bijcoA= -github.com/pion/rtp v1.7.13/go.mod h1:bDb5n+BFZxXx0Ea7E5qe+klMuqiBrP+w8XSjiWtCUko= -github.com/pion/sctp v1.8.5/go.mod h1:SUFFfDpViyKejTAdwD1d/HQsCu+V/40cCs2nZIvC3s0= -github.com/pion/sctp v1.8.7 h1:JnABvFakZueGAn4KU/4PSKg+GWbF6QWbKTWZOSGJjXw= -github.com/pion/sctp v1.8.7/go.mod h1:g1Ul+ARqZq5JEmoFy87Q/4CePtKnTJ1QCL9dBBdN6AU= -github.com/pion/sdp/v3 v3.0.6 h1:WuDLhtuFUUVpTfus9ILC4HRyHsW6TdugjEX/QY9OiUw= -github.com/pion/sdp/v3 v3.0.6/go.mod h1:iiFWFpQO8Fy3S5ldclBkpXqmWy02ns78NOKoLLL0YQw= -github.com/pion/srtp/v2 v2.0.15 h1:+tqRtXGsGwHC0G0IUIAzRmdkHvriF79IHVfZGfHrQoA= -github.com/pion/srtp/v2 v2.0.15/go.mod h1:b/pQOlDrbB0HEH5EUAQXzSYxikFbNcNuKmF8tM0hCtw= -github.com/pion/stun v0.4.0/go.mod h1:QPsh1/SbXASntw3zkkrIk3ZJVKz4saBY2G7S10P3wCw= -github.com/pion/stun v0.6.0 h1:JHT/2iyGDPrFWE8NNC15wnddBN8KifsEDw8swQmrEmU= -github.com/pion/stun v0.6.0/go.mod h1:HPqcfoeqQn9cuaet7AOmB5e5xkObu9DwBdurwLKO9oA= -github.com/pion/transport v0.14.1 h1:XSM6olwW+o8J4SCmOBb/BpwZypkHeyM0PGFCxNQBr40= -github.com/pion/transport v0.14.1/go.mod h1:4tGmbk00NeYA3rUa9+n+dzCCoKkcy3YlYb99Jn2fNnI= -github.com/pion/transport/v2 v2.0.0/go.mod h1:HS2MEBJTwD+1ZI2eSXSvHJx/HnzQqRy2/LXxt6eVMHc= -github.com/pion/transport/v2 v2.1.0/go.mod h1:AdSw4YBZVDkZm8fpoz+fclXyQwANWmZAlDuQdctTThQ= -github.com/pion/transport/v2 v2.2.0/go.mod h1:AdSw4YBZVDkZm8fpoz+fclXyQwANWmZAlDuQdctTThQ= -github.com/pion/transport/v2 v2.2.1 h1:7qYnCBlpgSJNYMbLCKuSY9KbQdBFoETvPNETv0y4N7c= -github.com/pion/transport/v2 v2.2.1/go.mod h1:cXXWavvCnFF6McHTft3DWS9iic2Mftcz1Aq29pGcU5g= -github.com/pion/turn/v2 v2.1.0 h1:5wGHSgGhJhP/RpabkUb/T9PdsAjkGLS6toYz5HNzoSI= -github.com/pion/turn/v2 v2.1.0/go.mod h1:yrT5XbXSGX1VFSF31A3c1kCNB5bBZgk/uu5LET162qs= -github.com/pion/webrtc/v3 v3.2.9 h1:U8NSjQDlZZ+Iy/hg42Q/u6mhEVSXYvKrOIZiZwYTfLc= -github.com/pion/webrtc/v3 v3.2.9/go.mod h1:gjQLMZeyN3jXBGdxGmUYCyKjOuYX/c99BDjGqmadq0A= +github.com/pion/rtcp v1.2.15 h1:LZQi2JbdipLOj4eBjK4wlVoQWfrZbh3Q6eHtWtJBZBo= +github.com/pion/rtcp v1.2.15/go.mod h1:jlGuAjHMEXwMUHK78RgX0UmEJFV4zUKOFHR7OP+D3D0= +github.com/pion/rtp v1.8.15 h1:MuhuGn1cxpVCPLNY1lI7F1tQ8Spntpgf12ob+pOYT8s= +github.com/pion/rtp v1.8.15/go.mod h1:bAu2UFKScgzyFqvUKmbvzSdPr+NGbZtv6UB2hesqXBk= +github.com/pion/sctp v1.8.39 h1:PJma40vRHa3UTO3C4MyeJDQ+KIobVYRZQZ0Nt7SjQnE= +github.com/pion/sctp v1.8.39/go.mod h1:cNiLdchXra8fHQwmIoqw0MbLLMs+f7uQ+dGMG2gWebE= +github.com/pion/sdp/v3 v3.0.11 h1:VhgVSopdsBKwhCFoyyPmT1fKMeV9nLMrEKxNOdy3IVI= +github.com/pion/sdp/v3 v3.0.11/go.mod h1:88GMahN5xnScv1hIMTqLdu/cOcUkj6a9ytbncwMCq2E= +github.com/pion/srtp/v3 v3.0.4 h1:2Z6vDVxzrX3UHEgrUyIGM4rRouoC7v+NiF1IHtp9B5M= +github.com/pion/srtp/v3 v3.0.4/go.mod h1:1Jx3FwDoxpRaTh1oRV8A/6G1BnFL+QI82eK4ms8EEJQ= +github.com/pion/stun/v3 v3.0.0 h1:4h1gwhWLWuZWOJIJR9s2ferRO+W3zA/b6ijOI6mKzUw= +github.com/pion/stun/v3 v3.0.0/go.mod h1:HvCN8txt8mwi4FBvS3EmDghW6aQJ24T+y+1TKjB5jyU= +github.com/pion/transport/v3 v3.0.7 h1:iRbMH05BzSNwhILHoBoAPxoB9xQgOaJk+591KC9P1o0= +github.com/pion/transport/v3 v3.0.7/go.mod h1:YleKiTZ4vqNxVwh77Z0zytYi7rXHl7j6uPLGhhz9rwo= +github.com/pion/turn/v4 v4.0.0 h1:qxplo3Rxa9Yg1xXDxxH8xaqcyGUtbHYw4QSCvmFWvhM= +github.com/pion/turn/v4 v4.0.0/go.mod h1:MuPDkm15nYSklKpN8vWJ9W2M0PlyQZqYt1McGuxG7mA= +github.com/pion/webrtc/v4 v4.1.1 h1:PMFPtLg1kpD2pVtun+LGUzA3k54JdFl87WO0Z1+HKug= +github.com/pion/webrtc/v4 v4.1.1/go.mod h1:cgEGkcpxGkT6Di2ClBYO5lP9mFXbCfEOrkYUpjjCQO4= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/satori/go.uuid v1.2.1-0.20181028125025-b2ce2384e17b h1:gQZ0qzfKHQIybLANtM3mBXNUtOfsCFXeTsnBqCsx1KM= github.com/satori/go.uuid v1.2.1-0.20181028125025-b2ce2384e17b/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= -github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw= github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/tevino/abool v0.0.0-20170917061928-9b9efcf221b5 h1:hNna6Fi0eP1f2sMBe/rJicDmaHmoXGe1Ta84FPYHLuE= github.com/tevino/abool v0.0.0-20170917061928-9b9efcf221b5/go.mod h1:f1SCnEOt6sc3fOJfPQDRDzHOtSXuTtnz0ImG9kPRDV0= +github.com/wlynxg/anet v0.0.5 h1:J3VJGi1gvo0JwZ/P1/Yc/8p63SoW98B5dHkYDmpgvvU= +github.com/wlynxg/anet v0.0.5/go.mod h1:eay5PRQr7fIVAMbTbchTnO9gG65Hg/uYGdc7mguHxoA= github.com/x-cray/logrus-prefixed-formatter v0.5.2 h1:00txxvfBM9muc0jiLIEAkAcIMJzfthRT6usrui8uGmg= github.com/x-cray/logrus-prefixed-formatter v0.5.2/go.mod h1:2duySbKsL6M18s5GU7VPsoEPHyzalCE06qoARUCeBBE= github.com/yapingcat/gomedia/codec v0.0.0-20220609081842-9e0c0e8a19a0/go.mod h1:obSECV6X3NPUsLL0olA7DurvQHKMq7J3iBTNQ4bL/vQ= @@ -139,44 +114,22 @@ github.com/yapingcat/gomedia/codec v0.0.0-20220617074658-94762898dc25 h1:1mq/skG github.com/yapingcat/gomedia/codec v0.0.0-20220617074658-94762898dc25/go.mod h1:obSECV6X3NPUsLL0olA7DurvQHKMq7J3iBTNQ4bL/vQ= github.com/yapingcat/gomedia/mpeg2 v0.0.0-20220617074658-94762898dc25 h1:51qjqT2jsOESm/jDi0k0AdQX33Sg4vhw8X6eooj7c8A= github.com/yapingcat/gomedia/mpeg2 v0.0.0-20220617074658-94762898dc25/go.mod h1:bvxj2Oi5Rwj7eHm2OjqgOIs8x2T0j+V068eS/SAyZLA= -github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE= -golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= -golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= -golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= -golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= +golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus= +golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= -golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= -golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= -golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= -golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= -golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8= +golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -189,54 +142,19 @@ golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200926100807-9d91bd62050c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201207223542-d4d67f95c62d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201214095126-aec9a390925b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= -golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= -golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= -golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= -golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= -golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= -golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8= -golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= +golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= +golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.29.0 h1:L6pJp37ocefwRRtYPKSWOWzOtWSxVajvz2ldH/xi3iU= +golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= +golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -246,19 +164,14 @@ google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQ google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/trunk/3rdparty/srs-bench/janus/ingester.go b/trunk/3rdparty/srs-bench/janus/ingester.go index 5e8698149..e01acb0cb 100644 --- a/trunk/3rdparty/srs-bench/janus/ingester.go +++ b/trunk/3rdparty/srs-bench/janus/ingester.go @@ -32,10 +32,10 @@ import ( "github.com/pion/interceptor" "github.com/pion/rtp" "github.com/pion/sdp/v3" - "github.com/pion/webrtc/v3" - "github.com/pion/webrtc/v3/pkg/media" - "github.com/pion/webrtc/v3/pkg/media/h264reader" - "github.com/pion/webrtc/v3/pkg/media/oggreader" + "github.com/pion/webrtc/v4" + "github.com/pion/webrtc/v4/pkg/media" + "github.com/pion/webrtc/v4/pkg/media/h264reader" + "github.com/pion/webrtc/v4/pkg/media/oggreader" ) type videoIngester struct { diff --git a/trunk/3rdparty/srs-bench/janus/player.go b/trunk/3rdparty/srs-bench/janus/player.go index 7dba29027..94e86af1c 100644 --- a/trunk/3rdparty/srs-bench/janus/player.go +++ b/trunk/3rdparty/srs-bench/janus/player.go @@ -23,16 +23,17 @@ package janus import ( "context" "fmt" + "net/url" + "strconv" + "strings" + "time" + "github.com/ossrs/go-oryx-lib/errors" "github.com/ossrs/go-oryx-lib/logger" "github.com/pion/interceptor" "github.com/pion/rtcp" "github.com/pion/sdp/v3" - "github.com/pion/webrtc/v3" - "net/url" - "strconv" - "strings" - "time" + "github.com/pion/webrtc/v4" ) func startPlay(ctx context.Context, r string, enableAudioLevel, enableTWCC bool, pli int) error { diff --git a/trunk/3rdparty/srs-bench/janus/publisher.go b/trunk/3rdparty/srs-bench/janus/publisher.go index b5f771ede..691f5040b 100644 --- a/trunk/3rdparty/srs-bench/janus/publisher.go +++ b/trunk/3rdparty/srs-bench/janus/publisher.go @@ -23,16 +23,17 @@ package janus import ( "context" "fmt" - "github.com/ossrs/go-oryx-lib/errors" - "github.com/ossrs/go-oryx-lib/logger" - "github.com/pion/interceptor" - "github.com/pion/sdp/v3" - "github.com/pion/webrtc/v3" "io" "net/url" "strconv" "strings" "sync" + + "github.com/ossrs/go-oryx-lib/errors" + "github.com/ossrs/go-oryx-lib/logger" + "github.com/pion/interceptor" + "github.com/pion/sdp/v3" + "github.com/pion/webrtc/v4" ) func startPublish(ctx context.Context, r, sourceAudio, sourceVideo string, fps int, enableAudioLevel, enableTWCC bool) error { diff --git a/trunk/3rdparty/srs-bench/janus/util.go b/trunk/3rdparty/srs-bench/janus/util.go index 25f57b579..540653372 100644 --- a/trunk/3rdparty/srs-bench/janus/util.go +++ b/trunk/3rdparty/srs-bench/janus/util.go @@ -44,9 +44,9 @@ import ( "github.com/pion/interceptor" "github.com/pion/logging" "github.com/pion/rtcp" - "github.com/pion/transport/v2/vnet" - "github.com/pion/webrtc/v3" - "github.com/pion/webrtc/v3/pkg/media/h264reader" + "github.com/pion/transport/v3/vnet" + "github.com/pion/webrtc/v4" + "github.com/pion/webrtc/v4/pkg/media/h264reader" ) var srsHttps *bool @@ -647,7 +647,7 @@ func (v *testWebRTCAPI) Setup(vnetClientIP string, options ...testWebRTCAPIOptio return errors.Wrapf(err, "create network for api") } - v.settingEngine.SetVNet(v.network) + v.settingEngine.SetNet(v.network) // Create a proxy bind to the router. if v.proxy, err = vnet_proxy.NewProxy(v.router); err != nil { @@ -1012,7 +1012,7 @@ func (v *testPublisher) Run(ctx context.Context, cancel context.CancelFunc) erro logger.Tf(ctx, "State signaling=%v, ice=%v, conn=%v", pc.SignalingState(), pc.ICEConnectionState(), pc.ConnectionState()) // ICE state management. - pc.OnICEGatheringStateChange(func(state webrtc.ICEGathererState) { + pc.OnICEGatheringStateChange(func(state webrtc.ICEGatheringState) { logger.Tf(ctx, "ICE gather state %v", state) }) pc.OnICECandidate(func(candidate *webrtc.ICECandidate) { diff --git a/trunk/3rdparty/srs-bench/srs/ingester.go b/trunk/3rdparty/srs-bench/srs/ingester.go index ae4154eb8..d8a0288e7 100644 --- a/trunk/3rdparty/srs-bench/srs/ingester.go +++ b/trunk/3rdparty/srs-bench/srs/ingester.go @@ -32,10 +32,10 @@ import ( "github.com/pion/interceptor" "github.com/pion/rtp" "github.com/pion/sdp/v3" - "github.com/pion/webrtc/v3" - "github.com/pion/webrtc/v3/pkg/media" - "github.com/pion/webrtc/v3/pkg/media/h264reader" - "github.com/pion/webrtc/v3/pkg/media/oggreader" + "github.com/pion/webrtc/v4" + "github.com/pion/webrtc/v4/pkg/media" + "github.com/pion/webrtc/v4/pkg/media/h264reader" + "github.com/pion/webrtc/v4/pkg/media/oggreader" ) type videoIngester struct { diff --git a/trunk/3rdparty/srs-bench/srs/player.go b/trunk/3rdparty/srs-bench/srs/player.go index ab11f7971..acf27729f 100644 --- a/trunk/3rdparty/srs-bench/srs/player.go +++ b/trunk/3rdparty/srs-bench/srs/player.go @@ -32,11 +32,11 @@ import ( "github.com/pion/interceptor" "github.com/pion/rtcp" "github.com/pion/sdp/v3" - "github.com/pion/webrtc/v3" - "github.com/pion/webrtc/v3/pkg/media" - "github.com/pion/webrtc/v3/pkg/media/h264writer" - "github.com/pion/webrtc/v3/pkg/media/ivfwriter" - "github.com/pion/webrtc/v3/pkg/media/oggwriter" + "github.com/pion/webrtc/v4" + "github.com/pion/webrtc/v4/pkg/media" + "github.com/pion/webrtc/v4/pkg/media/h264writer" + "github.com/pion/webrtc/v4/pkg/media/ivfwriter" + "github.com/pion/webrtc/v4/pkg/media/oggwriter" ) // @see https://github.com/pion/webrtc/blob/master/examples/save-to-disk/main.go diff --git a/trunk/3rdparty/srs-bench/srs/publisher.go b/trunk/3rdparty/srs-bench/srs/publisher.go index 4afb9d93b..371f2e2ee 100644 --- a/trunk/3rdparty/srs-bench/srs/publisher.go +++ b/trunk/3rdparty/srs-bench/srs/publisher.go @@ -30,7 +30,7 @@ import ( "github.com/ossrs/go-oryx-lib/logger" "github.com/pion/interceptor" "github.com/pion/sdp/v3" - "github.com/pion/webrtc/v3" + "github.com/pion/webrtc/v4" ) // @see https://github.com/pion/webrtc/blob/master/examples/play-from-disk/main.go diff --git a/trunk/3rdparty/srs-bench/srs/rtc_test.go b/trunk/3rdparty/srs-bench/srs/rtc_test.go index 1c4bc6983..ce8d63010 100644 --- a/trunk/3rdparty/srs-bench/srs/rtc_test.go +++ b/trunk/3rdparty/srs-bench/srs/rtc_test.go @@ -34,8 +34,8 @@ import ( "testing" "time" - "github.com/pion/transport/v2/vnet" - "github.com/pion/webrtc/v3" + "github.com/pion/transport/v3/vnet" + "github.com/pion/webrtc/v4" "github.com/ossrs/go-oryx-lib/errors" "github.com/ossrs/go-oryx-lib/flv" diff --git a/trunk/3rdparty/srs-bench/srs/util.go b/trunk/3rdparty/srs-bench/srs/util.go index ebd68cee3..2bb497c51 100644 --- a/trunk/3rdparty/srs-bench/srs/util.go +++ b/trunk/3rdparty/srs-bench/srs/util.go @@ -31,13 +31,6 @@ import ( "crypto/x509/pkix" "flag" "fmt" - "github.com/ossrs/go-oryx-lib/amf0" - "github.com/ossrs/go-oryx-lib/avc" - "github.com/ossrs/go-oryx-lib/flv" - "github.com/ossrs/go-oryx-lib/rtmp" - "github.com/pion/ice/v2" - "github.com/pion/rtp" - "github.com/pion/rtp/codecs" "io" "math/big" "math/rand" @@ -51,15 +44,23 @@ import ( "sync" "time" + "github.com/ossrs/go-oryx-lib/amf0" + "github.com/ossrs/go-oryx-lib/avc" + "github.com/ossrs/go-oryx-lib/flv" + "github.com/ossrs/go-oryx-lib/rtmp" + "github.com/pion/ice/v4" + "github.com/pion/rtp" + "github.com/pion/rtp/codecs" + "github.com/ossrs/go-oryx-lib/errors" "github.com/ossrs/go-oryx-lib/logger" vnet_proxy "github.com/ossrs/srs-bench/vnet" "github.com/pion/interceptor" "github.com/pion/logging" "github.com/pion/rtcp" - "github.com/pion/transport/v2/vnet" - "github.com/pion/webrtc/v3" - "github.com/pion/webrtc/v3/pkg/media/h264reader" + "github.com/pion/transport/v3/vnet" + "github.com/pion/webrtc/v4" + "github.com/pion/webrtc/v4/pkg/media/h264reader" ) var srsHttps *bool @@ -735,7 +736,7 @@ func (v *testWebRTCAPI) Setup(vnetClientIP string, options ...testWebRTCAPIOptio return errors.Wrapf(err, "create network for api") } - v.settingEngine.SetVNet(v.network) + v.settingEngine.SetNet(v.network) // Create a proxy bind to the router. if v.proxy, err = vnet_proxy.NewProxy(v.router); err != nil { @@ -1213,7 +1214,7 @@ func (v *testPublisher) Run(ctx context.Context, cancel context.CancelFunc) erro logger.Tf(ctx, "State signaling=%v, ice=%v, conn=%v", pc.SignalingState(), pc.ICEConnectionState(), pc.ConnectionState()) // ICE state management. - pc.OnICEGatheringStateChange(func(state webrtc.ICEGathererState) { + pc.OnICEGatheringStateChange(func(state webrtc.ICEGatheringState) { logger.Tf(ctx, "ICE gather state %v", state) }) pc.OnICECandidate(func(candidate *webrtc.ICECandidate) { diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/davecgh/go-spew/LICENSE b/trunk/3rdparty/srs-bench/vendor/github.com/davecgh/go-spew/LICENSE deleted file mode 100644 index bc52e96f2..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/davecgh/go-spew/LICENSE +++ /dev/null @@ -1,15 +0,0 @@ -ISC License - -Copyright (c) 2012-2016 Dave Collins - -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/davecgh/go-spew/spew/bypass.go b/trunk/3rdparty/srs-bench/vendor/github.com/davecgh/go-spew/spew/bypass.go deleted file mode 100644 index 792994785..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/davecgh/go-spew/spew/bypass.go +++ /dev/null @@ -1,145 +0,0 @@ -// Copyright (c) 2015-2016 Dave Collins -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -// NOTE: Due to the following build constraints, this file will only be compiled -// when the code is not running on Google App Engine, compiled by GopherJS, and -// "-tags safe" is not added to the go build command line. The "disableunsafe" -// tag is deprecated and thus should not be used. -// Go versions prior to 1.4 are disabled because they use a different layout -// for interfaces which make the implementation of unsafeReflectValue more complex. -// +build !js,!appengine,!safe,!disableunsafe,go1.4 - -package spew - -import ( - "reflect" - "unsafe" -) - -const ( - // UnsafeDisabled is a build-time constant which specifies whether or - // not access to the unsafe package is available. - UnsafeDisabled = false - - // ptrSize is the size of a pointer on the current arch. - ptrSize = unsafe.Sizeof((*byte)(nil)) -) - -type flag uintptr - -var ( - // flagRO indicates whether the value field of a reflect.Value - // is read-only. - flagRO flag - - // flagAddr indicates whether the address of the reflect.Value's - // value may be taken. - flagAddr flag -) - -// flagKindMask holds the bits that make up the kind -// part of the flags field. In all the supported versions, -// it is in the lower 5 bits. -const flagKindMask = flag(0x1f) - -// Different versions of Go have used different -// bit layouts for the flags type. This table -// records the known combinations. -var okFlags = []struct { - ro, addr flag -}{{ - // From Go 1.4 to 1.5 - ro: 1 << 5, - addr: 1 << 7, -}, { - // Up to Go tip. - ro: 1<<5 | 1<<6, - addr: 1 << 8, -}} - -var flagValOffset = func() uintptr { - field, ok := reflect.TypeOf(reflect.Value{}).FieldByName("flag") - if !ok { - panic("reflect.Value has no flag field") - } - return field.Offset -}() - -// flagField returns a pointer to the flag field of a reflect.Value. -func flagField(v *reflect.Value) *flag { - return (*flag)(unsafe.Pointer(uintptr(unsafe.Pointer(v)) + flagValOffset)) -} - -// unsafeReflectValue converts the passed reflect.Value into a one that bypasses -// the typical safety restrictions preventing access to unaddressable and -// unexported data. It works by digging the raw pointer to the underlying -// value out of the protected value and generating a new unprotected (unsafe) -// reflect.Value to it. -// -// This allows us to check for implementations of the Stringer and error -// interfaces to be used for pretty printing ordinarily unaddressable and -// inaccessible values such as unexported struct fields. -func unsafeReflectValue(v reflect.Value) reflect.Value { - if !v.IsValid() || (v.CanInterface() && v.CanAddr()) { - return v - } - flagFieldPtr := flagField(&v) - *flagFieldPtr &^= flagRO - *flagFieldPtr |= flagAddr - return v -} - -// Sanity checks against future reflect package changes -// to the type or semantics of the Value.flag field. -func init() { - field, ok := reflect.TypeOf(reflect.Value{}).FieldByName("flag") - if !ok { - panic("reflect.Value has no flag field") - } - if field.Type.Kind() != reflect.TypeOf(flag(0)).Kind() { - panic("reflect.Value flag field has changed kind") - } - type t0 int - var t struct { - A t0 - // t0 will have flagEmbedRO set. - t0 - // a will have flagStickyRO set - a t0 - } - vA := reflect.ValueOf(t).FieldByName("A") - va := reflect.ValueOf(t).FieldByName("a") - vt0 := reflect.ValueOf(t).FieldByName("t0") - - // Infer flagRO from the difference between the flags - // for the (otherwise identical) fields in t. - flagPublic := *flagField(&vA) - flagWithRO := *flagField(&va) | *flagField(&vt0) - flagRO = flagPublic ^ flagWithRO - - // Infer flagAddr from the difference between a value - // taken from a pointer and not. - vPtrA := reflect.ValueOf(&t).Elem().FieldByName("A") - flagNoPtr := *flagField(&vA) - flagPtr := *flagField(&vPtrA) - flagAddr = flagNoPtr ^ flagPtr - - // Check that the inferred flags tally with one of the known versions. - for _, f := range okFlags { - if flagRO == f.ro && flagAddr == f.addr { - return - } - } - panic("reflect.Value read-only flag has changed semantics") -} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/davecgh/go-spew/spew/bypasssafe.go b/trunk/3rdparty/srs-bench/vendor/github.com/davecgh/go-spew/spew/bypasssafe.go deleted file mode 100644 index 205c28d68..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/davecgh/go-spew/spew/bypasssafe.go +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) 2015-2016 Dave Collins -// -// Permission to use, copy, modify, and distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -// NOTE: Due to the following build constraints, this file will only be compiled -// when the code is running on Google App Engine, compiled by GopherJS, or -// "-tags safe" is added to the go build command line. The "disableunsafe" -// tag is deprecated and thus should not be used. -// +build js appengine safe disableunsafe !go1.4 - -package spew - -import "reflect" - -const ( - // UnsafeDisabled is a build-time constant which specifies whether or - // not access to the unsafe package is available. - UnsafeDisabled = true -) - -// unsafeReflectValue typically converts the passed reflect.Value into a one -// that bypasses the typical safety restrictions preventing access to -// unaddressable and unexported data. However, doing this relies on access to -// the unsafe package. This is a stub version which simply returns the passed -// reflect.Value when the unsafe package is not available. -func unsafeReflectValue(v reflect.Value) reflect.Value { - return v -} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/davecgh/go-spew/spew/common.go b/trunk/3rdparty/srs-bench/vendor/github.com/davecgh/go-spew/spew/common.go deleted file mode 100644 index 1be8ce945..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/davecgh/go-spew/spew/common.go +++ /dev/null @@ -1,341 +0,0 @@ -/* - * Copyright (c) 2013-2016 Dave Collins - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -package spew - -import ( - "bytes" - "fmt" - "io" - "reflect" - "sort" - "strconv" -) - -// Some constants in the form of bytes to avoid string overhead. This mirrors -// the technique used in the fmt package. -var ( - panicBytes = []byte("(PANIC=") - plusBytes = []byte("+") - iBytes = []byte("i") - trueBytes = []byte("true") - falseBytes = []byte("false") - interfaceBytes = []byte("(interface {})") - commaNewlineBytes = []byte(",\n") - newlineBytes = []byte("\n") - openBraceBytes = []byte("{") - openBraceNewlineBytes = []byte("{\n") - closeBraceBytes = []byte("}") - asteriskBytes = []byte("*") - colonBytes = []byte(":") - colonSpaceBytes = []byte(": ") - openParenBytes = []byte("(") - closeParenBytes = []byte(")") - spaceBytes = []byte(" ") - pointerChainBytes = []byte("->") - nilAngleBytes = []byte("") - maxNewlineBytes = []byte("\n") - maxShortBytes = []byte("") - circularBytes = []byte("") - circularShortBytes = []byte("") - invalidAngleBytes = []byte("") - openBracketBytes = []byte("[") - closeBracketBytes = []byte("]") - percentBytes = []byte("%") - precisionBytes = []byte(".") - openAngleBytes = []byte("<") - closeAngleBytes = []byte(">") - openMapBytes = []byte("map[") - closeMapBytes = []byte("]") - lenEqualsBytes = []byte("len=") - capEqualsBytes = []byte("cap=") -) - -// hexDigits is used to map a decimal value to a hex digit. -var hexDigits = "0123456789abcdef" - -// catchPanic handles any panics that might occur during the handleMethods -// calls. -func catchPanic(w io.Writer, v reflect.Value) { - if err := recover(); err != nil { - w.Write(panicBytes) - fmt.Fprintf(w, "%v", err) - w.Write(closeParenBytes) - } -} - -// handleMethods attempts to call the Error and String methods on the underlying -// type the passed reflect.Value represents and outputes the result to Writer w. -// -// It handles panics in any called methods by catching and displaying the error -// as the formatted value. -func handleMethods(cs *ConfigState, w io.Writer, v reflect.Value) (handled bool) { - // We need an interface to check if the type implements the error or - // Stringer interface. However, the reflect package won't give us an - // interface on certain things like unexported struct fields in order - // to enforce visibility rules. We use unsafe, when it's available, - // to bypass these restrictions since this package does not mutate the - // values. - if !v.CanInterface() { - if UnsafeDisabled { - return false - } - - v = unsafeReflectValue(v) - } - - // Choose whether or not to do error and Stringer interface lookups against - // the base type or a pointer to the base type depending on settings. - // Technically calling one of these methods with a pointer receiver can - // mutate the value, however, types which choose to satisify an error or - // Stringer interface with a pointer receiver should not be mutating their - // state inside these interface methods. - if !cs.DisablePointerMethods && !UnsafeDisabled && !v.CanAddr() { - v = unsafeReflectValue(v) - } - if v.CanAddr() { - v = v.Addr() - } - - // Is it an error or Stringer? - switch iface := v.Interface().(type) { - case error: - defer catchPanic(w, v) - if cs.ContinueOnMethod { - w.Write(openParenBytes) - w.Write([]byte(iface.Error())) - w.Write(closeParenBytes) - w.Write(spaceBytes) - return false - } - - w.Write([]byte(iface.Error())) - return true - - case fmt.Stringer: - defer catchPanic(w, v) - if cs.ContinueOnMethod { - w.Write(openParenBytes) - w.Write([]byte(iface.String())) - w.Write(closeParenBytes) - w.Write(spaceBytes) - return false - } - w.Write([]byte(iface.String())) - return true - } - return false -} - -// printBool outputs a boolean value as true or false to Writer w. -func printBool(w io.Writer, val bool) { - if val { - w.Write(trueBytes) - } else { - w.Write(falseBytes) - } -} - -// printInt outputs a signed integer value to Writer w. -func printInt(w io.Writer, val int64, base int) { - w.Write([]byte(strconv.FormatInt(val, base))) -} - -// printUint outputs an unsigned integer value to Writer w. -func printUint(w io.Writer, val uint64, base int) { - w.Write([]byte(strconv.FormatUint(val, base))) -} - -// printFloat outputs a floating point value using the specified precision, -// which is expected to be 32 or 64bit, to Writer w. -func printFloat(w io.Writer, val float64, precision int) { - w.Write([]byte(strconv.FormatFloat(val, 'g', -1, precision))) -} - -// printComplex outputs a complex value using the specified float precision -// for the real and imaginary parts to Writer w. -func printComplex(w io.Writer, c complex128, floatPrecision int) { - r := real(c) - w.Write(openParenBytes) - w.Write([]byte(strconv.FormatFloat(r, 'g', -1, floatPrecision))) - i := imag(c) - if i >= 0 { - w.Write(plusBytes) - } - w.Write([]byte(strconv.FormatFloat(i, 'g', -1, floatPrecision))) - w.Write(iBytes) - w.Write(closeParenBytes) -} - -// printHexPtr outputs a uintptr formatted as hexadecimal with a leading '0x' -// prefix to Writer w. -func printHexPtr(w io.Writer, p uintptr) { - // Null pointer. - num := uint64(p) - if num == 0 { - w.Write(nilAngleBytes) - return - } - - // Max uint64 is 16 bytes in hex + 2 bytes for '0x' prefix - buf := make([]byte, 18) - - // It's simpler to construct the hex string right to left. - base := uint64(16) - i := len(buf) - 1 - for num >= base { - buf[i] = hexDigits[num%base] - num /= base - i-- - } - buf[i] = hexDigits[num] - - // Add '0x' prefix. - i-- - buf[i] = 'x' - i-- - buf[i] = '0' - - // Strip unused leading bytes. - buf = buf[i:] - w.Write(buf) -} - -// valuesSorter implements sort.Interface to allow a slice of reflect.Value -// elements to be sorted. -type valuesSorter struct { - values []reflect.Value - strings []string // either nil or same len and values - cs *ConfigState -} - -// newValuesSorter initializes a valuesSorter instance, which holds a set of -// surrogate keys on which the data should be sorted. It uses flags in -// ConfigState to decide if and how to populate those surrogate keys. -func newValuesSorter(values []reflect.Value, cs *ConfigState) sort.Interface { - vs := &valuesSorter{values: values, cs: cs} - if canSortSimply(vs.values[0].Kind()) { - return vs - } - if !cs.DisableMethods { - vs.strings = make([]string, len(values)) - for i := range vs.values { - b := bytes.Buffer{} - if !handleMethods(cs, &b, vs.values[i]) { - vs.strings = nil - break - } - vs.strings[i] = b.String() - } - } - if vs.strings == nil && cs.SpewKeys { - vs.strings = make([]string, len(values)) - for i := range vs.values { - vs.strings[i] = Sprintf("%#v", vs.values[i].Interface()) - } - } - return vs -} - -// canSortSimply tests whether a reflect.Kind is a primitive that can be sorted -// directly, or whether it should be considered for sorting by surrogate keys -// (if the ConfigState allows it). -func canSortSimply(kind reflect.Kind) bool { - // This switch parallels valueSortLess, except for the default case. - switch kind { - case reflect.Bool: - return true - case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int: - return true - case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint: - return true - case reflect.Float32, reflect.Float64: - return true - case reflect.String: - return true - case reflect.Uintptr: - return true - case reflect.Array: - return true - } - return false -} - -// Len returns the number of values in the slice. It is part of the -// sort.Interface implementation. -func (s *valuesSorter) Len() int { - return len(s.values) -} - -// Swap swaps the values at the passed indices. It is part of the -// sort.Interface implementation. -func (s *valuesSorter) Swap(i, j int) { - s.values[i], s.values[j] = s.values[j], s.values[i] - if s.strings != nil { - s.strings[i], s.strings[j] = s.strings[j], s.strings[i] - } -} - -// valueSortLess returns whether the first value should sort before the second -// value. It is used by valueSorter.Less as part of the sort.Interface -// implementation. -func valueSortLess(a, b reflect.Value) bool { - switch a.Kind() { - case reflect.Bool: - return !a.Bool() && b.Bool() - case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int: - return a.Int() < b.Int() - case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint: - return a.Uint() < b.Uint() - case reflect.Float32, reflect.Float64: - return a.Float() < b.Float() - case reflect.String: - return a.String() < b.String() - case reflect.Uintptr: - return a.Uint() < b.Uint() - case reflect.Array: - // Compare the contents of both arrays. - l := a.Len() - for i := 0; i < l; i++ { - av := a.Index(i) - bv := b.Index(i) - if av.Interface() == bv.Interface() { - continue - } - return valueSortLess(av, bv) - } - } - return a.String() < b.String() -} - -// Less returns whether the value at index i should sort before the -// value at index j. It is part of the sort.Interface implementation. -func (s *valuesSorter) Less(i, j int) bool { - if s.strings == nil { - return valueSortLess(s.values[i], s.values[j]) - } - return s.strings[i] < s.strings[j] -} - -// sortValues is a sort function that handles both native types and any type that -// can be converted to error or Stringer. Other inputs are sorted according to -// their Value.String() value to ensure display stability. -func sortValues(values []reflect.Value, cs *ConfigState) { - if len(values) == 0 { - return - } - sort.Sort(newValuesSorter(values, cs)) -} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/davecgh/go-spew/spew/config.go b/trunk/3rdparty/srs-bench/vendor/github.com/davecgh/go-spew/spew/config.go deleted file mode 100644 index 2e3d22f31..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/davecgh/go-spew/spew/config.go +++ /dev/null @@ -1,306 +0,0 @@ -/* - * Copyright (c) 2013-2016 Dave Collins - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -package spew - -import ( - "bytes" - "fmt" - "io" - "os" -) - -// ConfigState houses the configuration options used by spew to format and -// display values. There is a global instance, Config, that is used to control -// all top-level Formatter and Dump functionality. Each ConfigState instance -// provides methods equivalent to the top-level functions. -// -// The zero value for ConfigState provides no indentation. You would typically -// want to set it to a space or a tab. -// -// Alternatively, you can use NewDefaultConfig to get a ConfigState instance -// with default settings. See the documentation of NewDefaultConfig for default -// values. -type ConfigState struct { - // Indent specifies the string to use for each indentation level. The - // global config instance that all top-level functions use set this to a - // single space by default. If you would like more indentation, you might - // set this to a tab with "\t" or perhaps two spaces with " ". - Indent string - - // MaxDepth controls the maximum number of levels to descend into nested - // data structures. The default, 0, means there is no limit. - // - // NOTE: Circular data structures are properly detected, so it is not - // necessary to set this value unless you specifically want to limit deeply - // nested data structures. - MaxDepth int - - // DisableMethods specifies whether or not error and Stringer interfaces are - // invoked for types that implement them. - DisableMethods bool - - // DisablePointerMethods specifies whether or not to check for and invoke - // error and Stringer interfaces on types which only accept a pointer - // receiver when the current type is not a pointer. - // - // NOTE: This might be an unsafe action since calling one of these methods - // with a pointer receiver could technically mutate the value, however, - // in practice, types which choose to satisify an error or Stringer - // interface with a pointer receiver should not be mutating their state - // inside these interface methods. As a result, this option relies on - // access to the unsafe package, so it will not have any effect when - // running in environments without access to the unsafe package such as - // Google App Engine or with the "safe" build tag specified. - DisablePointerMethods bool - - // DisablePointerAddresses specifies whether to disable the printing of - // pointer addresses. This is useful when diffing data structures in tests. - DisablePointerAddresses bool - - // DisableCapacities specifies whether to disable the printing of capacities - // for arrays, slices, maps and channels. This is useful when diffing - // data structures in tests. - DisableCapacities bool - - // ContinueOnMethod specifies whether or not recursion should continue once - // a custom error or Stringer interface is invoked. The default, false, - // means it will print the results of invoking the custom error or Stringer - // interface and return immediately instead of continuing to recurse into - // the internals of the data type. - // - // NOTE: This flag does not have any effect if method invocation is disabled - // via the DisableMethods or DisablePointerMethods options. - ContinueOnMethod bool - - // SortKeys specifies map keys should be sorted before being printed. Use - // this to have a more deterministic, diffable output. Note that only - // native types (bool, int, uint, floats, uintptr and string) and types - // that support the error or Stringer interfaces (if methods are - // enabled) are supported, with other types sorted according to the - // reflect.Value.String() output which guarantees display stability. - SortKeys bool - - // SpewKeys specifies that, as a last resort attempt, map keys should - // be spewed to strings and sorted by those strings. This is only - // considered if SortKeys is true. - SpewKeys bool -} - -// Config is the active configuration of the top-level functions. -// The configuration can be changed by modifying the contents of spew.Config. -var Config = ConfigState{Indent: " "} - -// Errorf is a wrapper for fmt.Errorf that treats each argument as if it were -// passed with a Formatter interface returned by c.NewFormatter. It returns -// the formatted string as a value that satisfies error. See NewFormatter -// for formatting details. -// -// This function is shorthand for the following syntax: -// -// fmt.Errorf(format, c.NewFormatter(a), c.NewFormatter(b)) -func (c *ConfigState) Errorf(format string, a ...interface{}) (err error) { - return fmt.Errorf(format, c.convertArgs(a)...) -} - -// Fprint is a wrapper for fmt.Fprint that treats each argument as if it were -// passed with a Formatter interface returned by c.NewFormatter. It returns -// the number of bytes written and any write error encountered. See -// NewFormatter for formatting details. -// -// This function is shorthand for the following syntax: -// -// fmt.Fprint(w, c.NewFormatter(a), c.NewFormatter(b)) -func (c *ConfigState) Fprint(w io.Writer, a ...interface{}) (n int, err error) { - return fmt.Fprint(w, c.convertArgs(a)...) -} - -// Fprintf is a wrapper for fmt.Fprintf that treats each argument as if it were -// passed with a Formatter interface returned by c.NewFormatter. It returns -// the number of bytes written and any write error encountered. See -// NewFormatter for formatting details. -// -// This function is shorthand for the following syntax: -// -// fmt.Fprintf(w, format, c.NewFormatter(a), c.NewFormatter(b)) -func (c *ConfigState) Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) { - return fmt.Fprintf(w, format, c.convertArgs(a)...) -} - -// Fprintln is a wrapper for fmt.Fprintln that treats each argument as if it -// passed with a Formatter interface returned by c.NewFormatter. See -// NewFormatter for formatting details. -// -// This function is shorthand for the following syntax: -// -// fmt.Fprintln(w, c.NewFormatter(a), c.NewFormatter(b)) -func (c *ConfigState) Fprintln(w io.Writer, a ...interface{}) (n int, err error) { - return fmt.Fprintln(w, c.convertArgs(a)...) -} - -// Print is a wrapper for fmt.Print that treats each argument as if it were -// passed with a Formatter interface returned by c.NewFormatter. It returns -// the number of bytes written and any write error encountered. See -// NewFormatter for formatting details. -// -// This function is shorthand for the following syntax: -// -// fmt.Print(c.NewFormatter(a), c.NewFormatter(b)) -func (c *ConfigState) Print(a ...interface{}) (n int, err error) { - return fmt.Print(c.convertArgs(a)...) -} - -// Printf is a wrapper for fmt.Printf that treats each argument as if it were -// passed with a Formatter interface returned by c.NewFormatter. It returns -// the number of bytes written and any write error encountered. See -// NewFormatter for formatting details. -// -// This function is shorthand for the following syntax: -// -// fmt.Printf(format, c.NewFormatter(a), c.NewFormatter(b)) -func (c *ConfigState) Printf(format string, a ...interface{}) (n int, err error) { - return fmt.Printf(format, c.convertArgs(a)...) -} - -// Println is a wrapper for fmt.Println that treats each argument as if it were -// passed with a Formatter interface returned by c.NewFormatter. It returns -// the number of bytes written and any write error encountered. See -// NewFormatter for formatting details. -// -// This function is shorthand for the following syntax: -// -// fmt.Println(c.NewFormatter(a), c.NewFormatter(b)) -func (c *ConfigState) Println(a ...interface{}) (n int, err error) { - return fmt.Println(c.convertArgs(a)...) -} - -// Sprint is a wrapper for fmt.Sprint that treats each argument as if it were -// passed with a Formatter interface returned by c.NewFormatter. It returns -// the resulting string. See NewFormatter for formatting details. -// -// This function is shorthand for the following syntax: -// -// fmt.Sprint(c.NewFormatter(a), c.NewFormatter(b)) -func (c *ConfigState) Sprint(a ...interface{}) string { - return fmt.Sprint(c.convertArgs(a)...) -} - -// Sprintf is a wrapper for fmt.Sprintf that treats each argument as if it were -// passed with a Formatter interface returned by c.NewFormatter. It returns -// the resulting string. See NewFormatter for formatting details. -// -// This function is shorthand for the following syntax: -// -// fmt.Sprintf(format, c.NewFormatter(a), c.NewFormatter(b)) -func (c *ConfigState) Sprintf(format string, a ...interface{}) string { - return fmt.Sprintf(format, c.convertArgs(a)...) -} - -// Sprintln is a wrapper for fmt.Sprintln that treats each argument as if it -// were passed with a Formatter interface returned by c.NewFormatter. It -// returns the resulting string. See NewFormatter for formatting details. -// -// This function is shorthand for the following syntax: -// -// fmt.Sprintln(c.NewFormatter(a), c.NewFormatter(b)) -func (c *ConfigState) Sprintln(a ...interface{}) string { - return fmt.Sprintln(c.convertArgs(a)...) -} - -/* -NewFormatter returns a custom formatter that satisfies the fmt.Formatter -interface. As a result, it integrates cleanly with standard fmt package -printing functions. The formatter is useful for inline printing of smaller data -types similar to the standard %v format specifier. - -The custom formatter only responds to the %v (most compact), %+v (adds pointer -addresses), %#v (adds types), and %#+v (adds types and pointer addresses) verb -combinations. Any other verbs such as %x and %q will be sent to the the -standard fmt package for formatting. In addition, the custom formatter ignores -the width and precision arguments (however they will still work on the format -specifiers not handled by the custom formatter). - -Typically this function shouldn't be called directly. It is much easier to make -use of the custom formatter by calling one of the convenience functions such as -c.Printf, c.Println, or c.Printf. -*/ -func (c *ConfigState) NewFormatter(v interface{}) fmt.Formatter { - return newFormatter(c, v) -} - -// Fdump formats and displays the passed arguments to io.Writer w. It formats -// exactly the same as Dump. -func (c *ConfigState) Fdump(w io.Writer, a ...interface{}) { - fdump(c, w, a...) -} - -/* -Dump displays the passed parameters to standard out with newlines, customizable -indentation, and additional debug information such as complete types and all -pointer addresses used to indirect to the final value. It provides the -following features over the built-in printing facilities provided by the fmt -package: - - * Pointers are dereferenced and followed - * Circular data structures are detected and handled properly - * Custom Stringer/error interfaces are optionally invoked, including - on unexported types - * Custom types which only implement the Stringer/error interfaces via - a pointer receiver are optionally invoked when passing non-pointer - variables - * Byte arrays and slices are dumped like the hexdump -C command which - includes offsets, byte values in hex, and ASCII output - -The configuration options are controlled by modifying the public members -of c. See ConfigState for options documentation. - -See Fdump if you would prefer dumping to an arbitrary io.Writer or Sdump to -get the formatted result as a string. -*/ -func (c *ConfigState) Dump(a ...interface{}) { - fdump(c, os.Stdout, a...) -} - -// Sdump returns a string with the passed arguments formatted exactly the same -// as Dump. -func (c *ConfigState) Sdump(a ...interface{}) string { - var buf bytes.Buffer - fdump(c, &buf, a...) - return buf.String() -} - -// convertArgs accepts a slice of arguments and returns a slice of the same -// length with each argument converted to a spew Formatter interface using -// the ConfigState associated with s. -func (c *ConfigState) convertArgs(args []interface{}) (formatters []interface{}) { - formatters = make([]interface{}, len(args)) - for index, arg := range args { - formatters[index] = newFormatter(c, arg) - } - return formatters -} - -// NewDefaultConfig returns a ConfigState with the following default settings. -// -// Indent: " " -// MaxDepth: 0 -// DisableMethods: false -// DisablePointerMethods: false -// ContinueOnMethod: false -// SortKeys: false -func NewDefaultConfig() *ConfigState { - return &ConfigState{Indent: " "} -} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/davecgh/go-spew/spew/doc.go b/trunk/3rdparty/srs-bench/vendor/github.com/davecgh/go-spew/spew/doc.go deleted file mode 100644 index aacaac6f1..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/davecgh/go-spew/spew/doc.go +++ /dev/null @@ -1,211 +0,0 @@ -/* - * Copyright (c) 2013-2016 Dave Collins - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -/* -Package spew implements a deep pretty printer for Go data structures to aid in -debugging. - -A quick overview of the additional features spew provides over the built-in -printing facilities for Go data types are as follows: - - * Pointers are dereferenced and followed - * Circular data structures are detected and handled properly - * Custom Stringer/error interfaces are optionally invoked, including - on unexported types - * Custom types which only implement the Stringer/error interfaces via - a pointer receiver are optionally invoked when passing non-pointer - variables - * Byte arrays and slices are dumped like the hexdump -C command which - includes offsets, byte values in hex, and ASCII output (only when using - Dump style) - -There are two different approaches spew allows for dumping Go data structures: - - * Dump style which prints with newlines, customizable indentation, - and additional debug information such as types and all pointer addresses - used to indirect to the final value - * A custom Formatter interface that integrates cleanly with the standard fmt - package and replaces %v, %+v, %#v, and %#+v to provide inline printing - similar to the default %v while providing the additional functionality - outlined above and passing unsupported format verbs such as %x and %q - along to fmt - -Quick Start - -This section demonstrates how to quickly get started with spew. See the -sections below for further details on formatting and configuration options. - -To dump a variable with full newlines, indentation, type, and pointer -information use Dump, Fdump, or Sdump: - spew.Dump(myVar1, myVar2, ...) - spew.Fdump(someWriter, myVar1, myVar2, ...) - str := spew.Sdump(myVar1, myVar2, ...) - -Alternatively, if you would prefer to use format strings with a compacted inline -printing style, use the convenience wrappers Printf, Fprintf, etc with -%v (most compact), %+v (adds pointer addresses), %#v (adds types), or -%#+v (adds types and pointer addresses): - spew.Printf("myVar1: %v -- myVar2: %+v", myVar1, myVar2) - spew.Printf("myVar3: %#v -- myVar4: %#+v", myVar3, myVar4) - spew.Fprintf(someWriter, "myVar1: %v -- myVar2: %+v", myVar1, myVar2) - spew.Fprintf(someWriter, "myVar3: %#v -- myVar4: %#+v", myVar3, myVar4) - -Configuration Options - -Configuration of spew is handled by fields in the ConfigState type. For -convenience, all of the top-level functions use a global state available -via the spew.Config global. - -It is also possible to create a ConfigState instance that provides methods -equivalent to the top-level functions. This allows concurrent configuration -options. See the ConfigState documentation for more details. - -The following configuration options are available: - * Indent - String to use for each indentation level for Dump functions. - It is a single space by default. A popular alternative is "\t". - - * MaxDepth - Maximum number of levels to descend into nested data structures. - There is no limit by default. - - * DisableMethods - Disables invocation of error and Stringer interface methods. - Method invocation is enabled by default. - - * DisablePointerMethods - Disables invocation of error and Stringer interface methods on types - which only accept pointer receivers from non-pointer variables. - Pointer method invocation is enabled by default. - - * DisablePointerAddresses - DisablePointerAddresses specifies whether to disable the printing of - pointer addresses. This is useful when diffing data structures in tests. - - * DisableCapacities - DisableCapacities specifies whether to disable the printing of - capacities for arrays, slices, maps and channels. This is useful when - diffing data structures in tests. - - * ContinueOnMethod - Enables recursion into types after invoking error and Stringer interface - methods. Recursion after method invocation is disabled by default. - - * SortKeys - Specifies map keys should be sorted before being printed. Use - this to have a more deterministic, diffable output. Note that - only native types (bool, int, uint, floats, uintptr and string) - and types which implement error or Stringer interfaces are - supported with other types sorted according to the - reflect.Value.String() output which guarantees display - stability. Natural map order is used by default. - - * SpewKeys - Specifies that, as a last resort attempt, map keys should be - spewed to strings and sorted by those strings. This is only - considered if SortKeys is true. - -Dump Usage - -Simply call spew.Dump with a list of variables you want to dump: - - spew.Dump(myVar1, myVar2, ...) - -You may also call spew.Fdump if you would prefer to output to an arbitrary -io.Writer. For example, to dump to standard error: - - spew.Fdump(os.Stderr, myVar1, myVar2, ...) - -A third option is to call spew.Sdump to get the formatted output as a string: - - str := spew.Sdump(myVar1, myVar2, ...) - -Sample Dump Output - -See the Dump example for details on the setup of the types and variables being -shown here. - - (main.Foo) { - unexportedField: (*main.Bar)(0xf84002e210)({ - flag: (main.Flag) flagTwo, - data: (uintptr) - }), - ExportedField: (map[interface {}]interface {}) (len=1) { - (string) (len=3) "one": (bool) true - } - } - -Byte (and uint8) arrays and slices are displayed uniquely like the hexdump -C -command as shown. - ([]uint8) (len=32 cap=32) { - 00000000 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 |............... | - 00000010 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 |!"#$%&'()*+,-./0| - 00000020 31 32 |12| - } - -Custom Formatter - -Spew provides a custom formatter that implements the fmt.Formatter interface -so that it integrates cleanly with standard fmt package printing functions. The -formatter is useful for inline printing of smaller data types similar to the -standard %v format specifier. - -The custom formatter only responds to the %v (most compact), %+v (adds pointer -addresses), %#v (adds types), or %#+v (adds types and pointer addresses) verb -combinations. Any other verbs such as %x and %q will be sent to the the -standard fmt package for formatting. In addition, the custom formatter ignores -the width and precision arguments (however they will still work on the format -specifiers not handled by the custom formatter). - -Custom Formatter Usage - -The simplest way to make use of the spew custom formatter is to call one of the -convenience functions such as spew.Printf, spew.Println, or spew.Printf. The -functions have syntax you are most likely already familiar with: - - spew.Printf("myVar1: %v -- myVar2: %+v", myVar1, myVar2) - spew.Printf("myVar3: %#v -- myVar4: %#+v", myVar3, myVar4) - spew.Println(myVar, myVar2) - spew.Fprintf(os.Stderr, "myVar1: %v -- myVar2: %+v", myVar1, myVar2) - spew.Fprintf(os.Stderr, "myVar3: %#v -- myVar4: %#+v", myVar3, myVar4) - -See the Index for the full list convenience functions. - -Sample Formatter Output - -Double pointer to a uint8: - %v: <**>5 - %+v: <**>(0xf8400420d0->0xf8400420c8)5 - %#v: (**uint8)5 - %#+v: (**uint8)(0xf8400420d0->0xf8400420c8)5 - -Pointer to circular struct with a uint8 field and a pointer to itself: - %v: <*>{1 <*>} - %+v: <*>(0xf84003e260){ui8:1 c:<*>(0xf84003e260)} - %#v: (*main.circular){ui8:(uint8)1 c:(*main.circular)} - %#+v: (*main.circular)(0xf84003e260){ui8:(uint8)1 c:(*main.circular)(0xf84003e260)} - -See the Printf example for details on the setup of variables being shown -here. - -Errors - -Since it is possible for custom Stringer/error interfaces to panic, spew -detects them and handles them internally by printing the panic information -inline with the output. Since spew is intended to provide deep pretty printing -capabilities on structures, it intentionally does not return any errors. -*/ -package spew diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/davecgh/go-spew/spew/dump.go b/trunk/3rdparty/srs-bench/vendor/github.com/davecgh/go-spew/spew/dump.go deleted file mode 100644 index f78d89fc1..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/davecgh/go-spew/spew/dump.go +++ /dev/null @@ -1,509 +0,0 @@ -/* - * Copyright (c) 2013-2016 Dave Collins - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -package spew - -import ( - "bytes" - "encoding/hex" - "fmt" - "io" - "os" - "reflect" - "regexp" - "strconv" - "strings" -) - -var ( - // uint8Type is a reflect.Type representing a uint8. It is used to - // convert cgo types to uint8 slices for hexdumping. - uint8Type = reflect.TypeOf(uint8(0)) - - // cCharRE is a regular expression that matches a cgo char. - // It is used to detect character arrays to hexdump them. - cCharRE = regexp.MustCompile(`^.*\._Ctype_char$`) - - // cUnsignedCharRE is a regular expression that matches a cgo unsigned - // char. It is used to detect unsigned character arrays to hexdump - // them. - cUnsignedCharRE = regexp.MustCompile(`^.*\._Ctype_unsignedchar$`) - - // cUint8tCharRE is a regular expression that matches a cgo uint8_t. - // It is used to detect uint8_t arrays to hexdump them. - cUint8tCharRE = regexp.MustCompile(`^.*\._Ctype_uint8_t$`) -) - -// dumpState contains information about the state of a dump operation. -type dumpState struct { - w io.Writer - depth int - pointers map[uintptr]int - ignoreNextType bool - ignoreNextIndent bool - cs *ConfigState -} - -// indent performs indentation according to the depth level and cs.Indent -// option. -func (d *dumpState) indent() { - if d.ignoreNextIndent { - d.ignoreNextIndent = false - return - } - d.w.Write(bytes.Repeat([]byte(d.cs.Indent), d.depth)) -} - -// unpackValue returns values inside of non-nil interfaces when possible. -// This is useful for data types like structs, arrays, slices, and maps which -// can contain varying types packed inside an interface. -func (d *dumpState) unpackValue(v reflect.Value) reflect.Value { - if v.Kind() == reflect.Interface && !v.IsNil() { - v = v.Elem() - } - return v -} - -// dumpPtr handles formatting of pointers by indirecting them as necessary. -func (d *dumpState) dumpPtr(v reflect.Value) { - // Remove pointers at or below the current depth from map used to detect - // circular refs. - for k, depth := range d.pointers { - if depth >= d.depth { - delete(d.pointers, k) - } - } - - // Keep list of all dereferenced pointers to show later. - pointerChain := make([]uintptr, 0) - - // Figure out how many levels of indirection there are by dereferencing - // pointers and unpacking interfaces down the chain while detecting circular - // references. - nilFound := false - cycleFound := false - indirects := 0 - ve := v - for ve.Kind() == reflect.Ptr { - if ve.IsNil() { - nilFound = true - break - } - indirects++ - addr := ve.Pointer() - pointerChain = append(pointerChain, addr) - if pd, ok := d.pointers[addr]; ok && pd < d.depth { - cycleFound = true - indirects-- - break - } - d.pointers[addr] = d.depth - - ve = ve.Elem() - if ve.Kind() == reflect.Interface { - if ve.IsNil() { - nilFound = true - break - } - ve = ve.Elem() - } - } - - // Display type information. - d.w.Write(openParenBytes) - d.w.Write(bytes.Repeat(asteriskBytes, indirects)) - d.w.Write([]byte(ve.Type().String())) - d.w.Write(closeParenBytes) - - // Display pointer information. - if !d.cs.DisablePointerAddresses && len(pointerChain) > 0 { - d.w.Write(openParenBytes) - for i, addr := range pointerChain { - if i > 0 { - d.w.Write(pointerChainBytes) - } - printHexPtr(d.w, addr) - } - d.w.Write(closeParenBytes) - } - - // Display dereferenced value. - d.w.Write(openParenBytes) - switch { - case nilFound: - d.w.Write(nilAngleBytes) - - case cycleFound: - d.w.Write(circularBytes) - - default: - d.ignoreNextType = true - d.dump(ve) - } - d.w.Write(closeParenBytes) -} - -// dumpSlice handles formatting of arrays and slices. Byte (uint8 under -// reflection) arrays and slices are dumped in hexdump -C fashion. -func (d *dumpState) dumpSlice(v reflect.Value) { - // Determine whether this type should be hex dumped or not. Also, - // for types which should be hexdumped, try to use the underlying data - // first, then fall back to trying to convert them to a uint8 slice. - var buf []uint8 - doConvert := false - doHexDump := false - numEntries := v.Len() - if numEntries > 0 { - vt := v.Index(0).Type() - vts := vt.String() - switch { - // C types that need to be converted. - case cCharRE.MatchString(vts): - fallthrough - case cUnsignedCharRE.MatchString(vts): - fallthrough - case cUint8tCharRE.MatchString(vts): - doConvert = true - - // Try to use existing uint8 slices and fall back to converting - // and copying if that fails. - case vt.Kind() == reflect.Uint8: - // We need an addressable interface to convert the type - // to a byte slice. However, the reflect package won't - // give us an interface on certain things like - // unexported struct fields in order to enforce - // visibility rules. We use unsafe, when available, to - // bypass these restrictions since this package does not - // mutate the values. - vs := v - if !vs.CanInterface() || !vs.CanAddr() { - vs = unsafeReflectValue(vs) - } - if !UnsafeDisabled { - vs = vs.Slice(0, numEntries) - - // Use the existing uint8 slice if it can be - // type asserted. - iface := vs.Interface() - if slice, ok := iface.([]uint8); ok { - buf = slice - doHexDump = true - break - } - } - - // The underlying data needs to be converted if it can't - // be type asserted to a uint8 slice. - doConvert = true - } - - // Copy and convert the underlying type if needed. - if doConvert && vt.ConvertibleTo(uint8Type) { - // Convert and copy each element into a uint8 byte - // slice. - buf = make([]uint8, numEntries) - for i := 0; i < numEntries; i++ { - vv := v.Index(i) - buf[i] = uint8(vv.Convert(uint8Type).Uint()) - } - doHexDump = true - } - } - - // Hexdump the entire slice as needed. - if doHexDump { - indent := strings.Repeat(d.cs.Indent, d.depth) - str := indent + hex.Dump(buf) - str = strings.Replace(str, "\n", "\n"+indent, -1) - str = strings.TrimRight(str, d.cs.Indent) - d.w.Write([]byte(str)) - return - } - - // Recursively call dump for each item. - for i := 0; i < numEntries; i++ { - d.dump(d.unpackValue(v.Index(i))) - if i < (numEntries - 1) { - d.w.Write(commaNewlineBytes) - } else { - d.w.Write(newlineBytes) - } - } -} - -// dump is the main workhorse for dumping a value. It uses the passed reflect -// value to figure out what kind of object we are dealing with and formats it -// appropriately. It is a recursive function, however circular data structures -// are detected and handled properly. -func (d *dumpState) dump(v reflect.Value) { - // Handle invalid reflect values immediately. - kind := v.Kind() - if kind == reflect.Invalid { - d.w.Write(invalidAngleBytes) - return - } - - // Handle pointers specially. - if kind == reflect.Ptr { - d.indent() - d.dumpPtr(v) - return - } - - // Print type information unless already handled elsewhere. - if !d.ignoreNextType { - d.indent() - d.w.Write(openParenBytes) - d.w.Write([]byte(v.Type().String())) - d.w.Write(closeParenBytes) - d.w.Write(spaceBytes) - } - d.ignoreNextType = false - - // Display length and capacity if the built-in len and cap functions - // work with the value's kind and the len/cap itself is non-zero. - valueLen, valueCap := 0, 0 - switch v.Kind() { - case reflect.Array, reflect.Slice, reflect.Chan: - valueLen, valueCap = v.Len(), v.Cap() - case reflect.Map, reflect.String: - valueLen = v.Len() - } - if valueLen != 0 || !d.cs.DisableCapacities && valueCap != 0 { - d.w.Write(openParenBytes) - if valueLen != 0 { - d.w.Write(lenEqualsBytes) - printInt(d.w, int64(valueLen), 10) - } - if !d.cs.DisableCapacities && valueCap != 0 { - if valueLen != 0 { - d.w.Write(spaceBytes) - } - d.w.Write(capEqualsBytes) - printInt(d.w, int64(valueCap), 10) - } - d.w.Write(closeParenBytes) - d.w.Write(spaceBytes) - } - - // Call Stringer/error interfaces if they exist and the handle methods flag - // is enabled - if !d.cs.DisableMethods { - if (kind != reflect.Invalid) && (kind != reflect.Interface) { - if handled := handleMethods(d.cs, d.w, v); handled { - return - } - } - } - - switch kind { - case reflect.Invalid: - // Do nothing. We should never get here since invalid has already - // been handled above. - - case reflect.Bool: - printBool(d.w, v.Bool()) - - case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int: - printInt(d.w, v.Int(), 10) - - case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint: - printUint(d.w, v.Uint(), 10) - - case reflect.Float32: - printFloat(d.w, v.Float(), 32) - - case reflect.Float64: - printFloat(d.w, v.Float(), 64) - - case reflect.Complex64: - printComplex(d.w, v.Complex(), 32) - - case reflect.Complex128: - printComplex(d.w, v.Complex(), 64) - - case reflect.Slice: - if v.IsNil() { - d.w.Write(nilAngleBytes) - break - } - fallthrough - - case reflect.Array: - d.w.Write(openBraceNewlineBytes) - d.depth++ - if (d.cs.MaxDepth != 0) && (d.depth > d.cs.MaxDepth) { - d.indent() - d.w.Write(maxNewlineBytes) - } else { - d.dumpSlice(v) - } - d.depth-- - d.indent() - d.w.Write(closeBraceBytes) - - case reflect.String: - d.w.Write([]byte(strconv.Quote(v.String()))) - - case reflect.Interface: - // The only time we should get here is for nil interfaces due to - // unpackValue calls. - if v.IsNil() { - d.w.Write(nilAngleBytes) - } - - case reflect.Ptr: - // Do nothing. We should never get here since pointers have already - // been handled above. - - case reflect.Map: - // nil maps should be indicated as different than empty maps - if v.IsNil() { - d.w.Write(nilAngleBytes) - break - } - - d.w.Write(openBraceNewlineBytes) - d.depth++ - if (d.cs.MaxDepth != 0) && (d.depth > d.cs.MaxDepth) { - d.indent() - d.w.Write(maxNewlineBytes) - } else { - numEntries := v.Len() - keys := v.MapKeys() - if d.cs.SortKeys { - sortValues(keys, d.cs) - } - for i, key := range keys { - d.dump(d.unpackValue(key)) - d.w.Write(colonSpaceBytes) - d.ignoreNextIndent = true - d.dump(d.unpackValue(v.MapIndex(key))) - if i < (numEntries - 1) { - d.w.Write(commaNewlineBytes) - } else { - d.w.Write(newlineBytes) - } - } - } - d.depth-- - d.indent() - d.w.Write(closeBraceBytes) - - case reflect.Struct: - d.w.Write(openBraceNewlineBytes) - d.depth++ - if (d.cs.MaxDepth != 0) && (d.depth > d.cs.MaxDepth) { - d.indent() - d.w.Write(maxNewlineBytes) - } else { - vt := v.Type() - numFields := v.NumField() - for i := 0; i < numFields; i++ { - d.indent() - vtf := vt.Field(i) - d.w.Write([]byte(vtf.Name)) - d.w.Write(colonSpaceBytes) - d.ignoreNextIndent = true - d.dump(d.unpackValue(v.Field(i))) - if i < (numFields - 1) { - d.w.Write(commaNewlineBytes) - } else { - d.w.Write(newlineBytes) - } - } - } - d.depth-- - d.indent() - d.w.Write(closeBraceBytes) - - case reflect.Uintptr: - printHexPtr(d.w, uintptr(v.Uint())) - - case reflect.UnsafePointer, reflect.Chan, reflect.Func: - printHexPtr(d.w, v.Pointer()) - - // There were not any other types at the time this code was written, but - // fall back to letting the default fmt package handle it in case any new - // types are added. - default: - if v.CanInterface() { - fmt.Fprintf(d.w, "%v", v.Interface()) - } else { - fmt.Fprintf(d.w, "%v", v.String()) - } - } -} - -// fdump is a helper function to consolidate the logic from the various public -// methods which take varying writers and config states. -func fdump(cs *ConfigState, w io.Writer, a ...interface{}) { - for _, arg := range a { - if arg == nil { - w.Write(interfaceBytes) - w.Write(spaceBytes) - w.Write(nilAngleBytes) - w.Write(newlineBytes) - continue - } - - d := dumpState{w: w, cs: cs} - d.pointers = make(map[uintptr]int) - d.dump(reflect.ValueOf(arg)) - d.w.Write(newlineBytes) - } -} - -// Fdump formats and displays the passed arguments to io.Writer w. It formats -// exactly the same as Dump. -func Fdump(w io.Writer, a ...interface{}) { - fdump(&Config, w, a...) -} - -// Sdump returns a string with the passed arguments formatted exactly the same -// as Dump. -func Sdump(a ...interface{}) string { - var buf bytes.Buffer - fdump(&Config, &buf, a...) - return buf.String() -} - -/* -Dump displays the passed parameters to standard out with newlines, customizable -indentation, and additional debug information such as complete types and all -pointer addresses used to indirect to the final value. It provides the -following features over the built-in printing facilities provided by the fmt -package: - - * Pointers are dereferenced and followed - * Circular data structures are detected and handled properly - * Custom Stringer/error interfaces are optionally invoked, including - on unexported types - * Custom types which only implement the Stringer/error interfaces via - a pointer receiver are optionally invoked when passing non-pointer - variables - * Byte arrays and slices are dumped like the hexdump -C command which - includes offsets, byte values in hex, and ASCII output - -The configuration options are controlled by an exported package global, -spew.Config. See ConfigState for options documentation. - -See Fdump if you would prefer dumping to an arbitrary io.Writer or Sdump to -get the formatted result as a string. -*/ -func Dump(a ...interface{}) { - fdump(&Config, os.Stdout, a...) -} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/davecgh/go-spew/spew/format.go b/trunk/3rdparty/srs-bench/vendor/github.com/davecgh/go-spew/spew/format.go deleted file mode 100644 index b04edb7d7..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/davecgh/go-spew/spew/format.go +++ /dev/null @@ -1,419 +0,0 @@ -/* - * Copyright (c) 2013-2016 Dave Collins - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -package spew - -import ( - "bytes" - "fmt" - "reflect" - "strconv" - "strings" -) - -// supportedFlags is a list of all the character flags supported by fmt package. -const supportedFlags = "0-+# " - -// formatState implements the fmt.Formatter interface and contains information -// about the state of a formatting operation. The NewFormatter function can -// be used to get a new Formatter which can be used directly as arguments -// in standard fmt package printing calls. -type formatState struct { - value interface{} - fs fmt.State - depth int - pointers map[uintptr]int - ignoreNextType bool - cs *ConfigState -} - -// buildDefaultFormat recreates the original format string without precision -// and width information to pass in to fmt.Sprintf in the case of an -// unrecognized type. Unless new types are added to the language, this -// function won't ever be called. -func (f *formatState) buildDefaultFormat() (format string) { - buf := bytes.NewBuffer(percentBytes) - - for _, flag := range supportedFlags { - if f.fs.Flag(int(flag)) { - buf.WriteRune(flag) - } - } - - buf.WriteRune('v') - - format = buf.String() - return format -} - -// constructOrigFormat recreates the original format string including precision -// and width information to pass along to the standard fmt package. This allows -// automatic deferral of all format strings this package doesn't support. -func (f *formatState) constructOrigFormat(verb rune) (format string) { - buf := bytes.NewBuffer(percentBytes) - - for _, flag := range supportedFlags { - if f.fs.Flag(int(flag)) { - buf.WriteRune(flag) - } - } - - if width, ok := f.fs.Width(); ok { - buf.WriteString(strconv.Itoa(width)) - } - - if precision, ok := f.fs.Precision(); ok { - buf.Write(precisionBytes) - buf.WriteString(strconv.Itoa(precision)) - } - - buf.WriteRune(verb) - - format = buf.String() - return format -} - -// unpackValue returns values inside of non-nil interfaces when possible and -// ensures that types for values which have been unpacked from an interface -// are displayed when the show types flag is also set. -// This is useful for data types like structs, arrays, slices, and maps which -// can contain varying types packed inside an interface. -func (f *formatState) unpackValue(v reflect.Value) reflect.Value { - if v.Kind() == reflect.Interface { - f.ignoreNextType = false - if !v.IsNil() { - v = v.Elem() - } - } - return v -} - -// formatPtr handles formatting of pointers by indirecting them as necessary. -func (f *formatState) formatPtr(v reflect.Value) { - // Display nil if top level pointer is nil. - showTypes := f.fs.Flag('#') - if v.IsNil() && (!showTypes || f.ignoreNextType) { - f.fs.Write(nilAngleBytes) - return - } - - // Remove pointers at or below the current depth from map used to detect - // circular refs. - for k, depth := range f.pointers { - if depth >= f.depth { - delete(f.pointers, k) - } - } - - // Keep list of all dereferenced pointers to possibly show later. - pointerChain := make([]uintptr, 0) - - // Figure out how many levels of indirection there are by derferencing - // pointers and unpacking interfaces down the chain while detecting circular - // references. - nilFound := false - cycleFound := false - indirects := 0 - ve := v - for ve.Kind() == reflect.Ptr { - if ve.IsNil() { - nilFound = true - break - } - indirects++ - addr := ve.Pointer() - pointerChain = append(pointerChain, addr) - if pd, ok := f.pointers[addr]; ok && pd < f.depth { - cycleFound = true - indirects-- - break - } - f.pointers[addr] = f.depth - - ve = ve.Elem() - if ve.Kind() == reflect.Interface { - if ve.IsNil() { - nilFound = true - break - } - ve = ve.Elem() - } - } - - // Display type or indirection level depending on flags. - if showTypes && !f.ignoreNextType { - f.fs.Write(openParenBytes) - f.fs.Write(bytes.Repeat(asteriskBytes, indirects)) - f.fs.Write([]byte(ve.Type().String())) - f.fs.Write(closeParenBytes) - } else { - if nilFound || cycleFound { - indirects += strings.Count(ve.Type().String(), "*") - } - f.fs.Write(openAngleBytes) - f.fs.Write([]byte(strings.Repeat("*", indirects))) - f.fs.Write(closeAngleBytes) - } - - // Display pointer information depending on flags. - if f.fs.Flag('+') && (len(pointerChain) > 0) { - f.fs.Write(openParenBytes) - for i, addr := range pointerChain { - if i > 0 { - f.fs.Write(pointerChainBytes) - } - printHexPtr(f.fs, addr) - } - f.fs.Write(closeParenBytes) - } - - // Display dereferenced value. - switch { - case nilFound: - f.fs.Write(nilAngleBytes) - - case cycleFound: - f.fs.Write(circularShortBytes) - - default: - f.ignoreNextType = true - f.format(ve) - } -} - -// format is the main workhorse for providing the Formatter interface. It -// uses the passed reflect value to figure out what kind of object we are -// dealing with and formats it appropriately. It is a recursive function, -// however circular data structures are detected and handled properly. -func (f *formatState) format(v reflect.Value) { - // Handle invalid reflect values immediately. - kind := v.Kind() - if kind == reflect.Invalid { - f.fs.Write(invalidAngleBytes) - return - } - - // Handle pointers specially. - if kind == reflect.Ptr { - f.formatPtr(v) - return - } - - // Print type information unless already handled elsewhere. - if !f.ignoreNextType && f.fs.Flag('#') { - f.fs.Write(openParenBytes) - f.fs.Write([]byte(v.Type().String())) - f.fs.Write(closeParenBytes) - } - f.ignoreNextType = false - - // Call Stringer/error interfaces if they exist and the handle methods - // flag is enabled. - if !f.cs.DisableMethods { - if (kind != reflect.Invalid) && (kind != reflect.Interface) { - if handled := handleMethods(f.cs, f.fs, v); handled { - return - } - } - } - - switch kind { - case reflect.Invalid: - // Do nothing. We should never get here since invalid has already - // been handled above. - - case reflect.Bool: - printBool(f.fs, v.Bool()) - - case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int: - printInt(f.fs, v.Int(), 10) - - case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint: - printUint(f.fs, v.Uint(), 10) - - case reflect.Float32: - printFloat(f.fs, v.Float(), 32) - - case reflect.Float64: - printFloat(f.fs, v.Float(), 64) - - case reflect.Complex64: - printComplex(f.fs, v.Complex(), 32) - - case reflect.Complex128: - printComplex(f.fs, v.Complex(), 64) - - case reflect.Slice: - if v.IsNil() { - f.fs.Write(nilAngleBytes) - break - } - fallthrough - - case reflect.Array: - f.fs.Write(openBracketBytes) - f.depth++ - if (f.cs.MaxDepth != 0) && (f.depth > f.cs.MaxDepth) { - f.fs.Write(maxShortBytes) - } else { - numEntries := v.Len() - for i := 0; i < numEntries; i++ { - if i > 0 { - f.fs.Write(spaceBytes) - } - f.ignoreNextType = true - f.format(f.unpackValue(v.Index(i))) - } - } - f.depth-- - f.fs.Write(closeBracketBytes) - - case reflect.String: - f.fs.Write([]byte(v.String())) - - case reflect.Interface: - // The only time we should get here is for nil interfaces due to - // unpackValue calls. - if v.IsNil() { - f.fs.Write(nilAngleBytes) - } - - case reflect.Ptr: - // Do nothing. We should never get here since pointers have already - // been handled above. - - case reflect.Map: - // nil maps should be indicated as different than empty maps - if v.IsNil() { - f.fs.Write(nilAngleBytes) - break - } - - f.fs.Write(openMapBytes) - f.depth++ - if (f.cs.MaxDepth != 0) && (f.depth > f.cs.MaxDepth) { - f.fs.Write(maxShortBytes) - } else { - keys := v.MapKeys() - if f.cs.SortKeys { - sortValues(keys, f.cs) - } - for i, key := range keys { - if i > 0 { - f.fs.Write(spaceBytes) - } - f.ignoreNextType = true - f.format(f.unpackValue(key)) - f.fs.Write(colonBytes) - f.ignoreNextType = true - f.format(f.unpackValue(v.MapIndex(key))) - } - } - f.depth-- - f.fs.Write(closeMapBytes) - - case reflect.Struct: - numFields := v.NumField() - f.fs.Write(openBraceBytes) - f.depth++ - if (f.cs.MaxDepth != 0) && (f.depth > f.cs.MaxDepth) { - f.fs.Write(maxShortBytes) - } else { - vt := v.Type() - for i := 0; i < numFields; i++ { - if i > 0 { - f.fs.Write(spaceBytes) - } - vtf := vt.Field(i) - if f.fs.Flag('+') || f.fs.Flag('#') { - f.fs.Write([]byte(vtf.Name)) - f.fs.Write(colonBytes) - } - f.format(f.unpackValue(v.Field(i))) - } - } - f.depth-- - f.fs.Write(closeBraceBytes) - - case reflect.Uintptr: - printHexPtr(f.fs, uintptr(v.Uint())) - - case reflect.UnsafePointer, reflect.Chan, reflect.Func: - printHexPtr(f.fs, v.Pointer()) - - // There were not any other types at the time this code was written, but - // fall back to letting the default fmt package handle it if any get added. - default: - format := f.buildDefaultFormat() - if v.CanInterface() { - fmt.Fprintf(f.fs, format, v.Interface()) - } else { - fmt.Fprintf(f.fs, format, v.String()) - } - } -} - -// Format satisfies the fmt.Formatter interface. See NewFormatter for usage -// details. -func (f *formatState) Format(fs fmt.State, verb rune) { - f.fs = fs - - // Use standard formatting for verbs that are not v. - if verb != 'v' { - format := f.constructOrigFormat(verb) - fmt.Fprintf(fs, format, f.value) - return - } - - if f.value == nil { - if fs.Flag('#') { - fs.Write(interfaceBytes) - } - fs.Write(nilAngleBytes) - return - } - - f.format(reflect.ValueOf(f.value)) -} - -// newFormatter is a helper function to consolidate the logic from the various -// public methods which take varying config states. -func newFormatter(cs *ConfigState, v interface{}) fmt.Formatter { - fs := &formatState{value: v, cs: cs} - fs.pointers = make(map[uintptr]int) - return fs -} - -/* -NewFormatter returns a custom formatter that satisfies the fmt.Formatter -interface. As a result, it integrates cleanly with standard fmt package -printing functions. The formatter is useful for inline printing of smaller data -types similar to the standard %v format specifier. - -The custom formatter only responds to the %v (most compact), %+v (adds pointer -addresses), %#v (adds types), or %#+v (adds types and pointer addresses) verb -combinations. Any other verbs such as %x and %q will be sent to the the -standard fmt package for formatting. In addition, the custom formatter ignores -the width and precision arguments (however they will still work on the format -specifiers not handled by the custom formatter). - -Typically this function shouldn't be called directly. It is much easier to make -use of the custom formatter by calling one of the convenience functions such as -Printf, Println, or Fprintf. -*/ -func NewFormatter(v interface{}) fmt.Formatter { - return newFormatter(&Config, v) -} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/davecgh/go-spew/spew/spew.go b/trunk/3rdparty/srs-bench/vendor/github.com/davecgh/go-spew/spew/spew.go deleted file mode 100644 index 32c0e3388..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/davecgh/go-spew/spew/spew.go +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (c) 2013-2016 Dave Collins - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -package spew - -import ( - "fmt" - "io" -) - -// Errorf is a wrapper for fmt.Errorf that treats each argument as if it were -// passed with a default Formatter interface returned by NewFormatter. It -// returns the formatted string as a value that satisfies error. See -// NewFormatter for formatting details. -// -// This function is shorthand for the following syntax: -// -// fmt.Errorf(format, spew.NewFormatter(a), spew.NewFormatter(b)) -func Errorf(format string, a ...interface{}) (err error) { - return fmt.Errorf(format, convertArgs(a)...) -} - -// Fprint is a wrapper for fmt.Fprint that treats each argument as if it were -// passed with a default Formatter interface returned by NewFormatter. It -// returns the number of bytes written and any write error encountered. See -// NewFormatter for formatting details. -// -// This function is shorthand for the following syntax: -// -// fmt.Fprint(w, spew.NewFormatter(a), spew.NewFormatter(b)) -func Fprint(w io.Writer, a ...interface{}) (n int, err error) { - return fmt.Fprint(w, convertArgs(a)...) -} - -// Fprintf is a wrapper for fmt.Fprintf that treats each argument as if it were -// passed with a default Formatter interface returned by NewFormatter. It -// returns the number of bytes written and any write error encountered. See -// NewFormatter for formatting details. -// -// This function is shorthand for the following syntax: -// -// fmt.Fprintf(w, format, spew.NewFormatter(a), spew.NewFormatter(b)) -func Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) { - return fmt.Fprintf(w, format, convertArgs(a)...) -} - -// Fprintln is a wrapper for fmt.Fprintln that treats each argument as if it -// passed with a default Formatter interface returned by NewFormatter. See -// NewFormatter for formatting details. -// -// This function is shorthand for the following syntax: -// -// fmt.Fprintln(w, spew.NewFormatter(a), spew.NewFormatter(b)) -func Fprintln(w io.Writer, a ...interface{}) (n int, err error) { - return fmt.Fprintln(w, convertArgs(a)...) -} - -// Print is a wrapper for fmt.Print that treats each argument as if it were -// passed with a default Formatter interface returned by NewFormatter. It -// returns the number of bytes written and any write error encountered. See -// NewFormatter for formatting details. -// -// This function is shorthand for the following syntax: -// -// fmt.Print(spew.NewFormatter(a), spew.NewFormatter(b)) -func Print(a ...interface{}) (n int, err error) { - return fmt.Print(convertArgs(a)...) -} - -// Printf is a wrapper for fmt.Printf that treats each argument as if it were -// passed with a default Formatter interface returned by NewFormatter. It -// returns the number of bytes written and any write error encountered. See -// NewFormatter for formatting details. -// -// This function is shorthand for the following syntax: -// -// fmt.Printf(format, spew.NewFormatter(a), spew.NewFormatter(b)) -func Printf(format string, a ...interface{}) (n int, err error) { - return fmt.Printf(format, convertArgs(a)...) -} - -// Println is a wrapper for fmt.Println that treats each argument as if it were -// passed with a default Formatter interface returned by NewFormatter. It -// returns the number of bytes written and any write error encountered. See -// NewFormatter for formatting details. -// -// This function is shorthand for the following syntax: -// -// fmt.Println(spew.NewFormatter(a), spew.NewFormatter(b)) -func Println(a ...interface{}) (n int, err error) { - return fmt.Println(convertArgs(a)...) -} - -// Sprint is a wrapper for fmt.Sprint that treats each argument as if it were -// passed with a default Formatter interface returned by NewFormatter. It -// returns the resulting string. See NewFormatter for formatting details. -// -// This function is shorthand for the following syntax: -// -// fmt.Sprint(spew.NewFormatter(a), spew.NewFormatter(b)) -func Sprint(a ...interface{}) string { - return fmt.Sprint(convertArgs(a)...) -} - -// Sprintf is a wrapper for fmt.Sprintf that treats each argument as if it were -// passed with a default Formatter interface returned by NewFormatter. It -// returns the resulting string. See NewFormatter for formatting details. -// -// This function is shorthand for the following syntax: -// -// fmt.Sprintf(format, spew.NewFormatter(a), spew.NewFormatter(b)) -func Sprintf(format string, a ...interface{}) string { - return fmt.Sprintf(format, convertArgs(a)...) -} - -// Sprintln is a wrapper for fmt.Sprintln that treats each argument as if it -// were passed with a default Formatter interface returned by NewFormatter. It -// returns the resulting string. See NewFormatter for formatting details. -// -// This function is shorthand for the following syntax: -// -// fmt.Sprintln(spew.NewFormatter(a), spew.NewFormatter(b)) -func Sprintln(a ...interface{}) string { - return fmt.Sprintln(convertArgs(a)...) -} - -// convertArgs accepts a slice of arguments and returns a slice of the same -// length with each argument converted to a default spew Formatter interface. -func convertArgs(args []interface{}) (formatters []interface{}) { - formatters = make([]interface{}, len(args)) - for index, arg := range args { - formatters[index] = NewFormatter(arg) - } - return formatters -} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/google/uuid/.travis.yml b/trunk/3rdparty/srs-bench/vendor/github.com/google/uuid/.travis.yml deleted file mode 100644 index d8156a60b..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/google/uuid/.travis.yml +++ /dev/null @@ -1,9 +0,0 @@ -language: go - -go: - - 1.4.3 - - 1.5.3 - - tip - -script: - - go test -v ./... diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/google/uuid/CHANGELOG.md b/trunk/3rdparty/srs-bench/vendor/github.com/google/uuid/CHANGELOG.md new file mode 100644 index 000000000..7ec5ac7ea --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/google/uuid/CHANGELOG.md @@ -0,0 +1,41 @@ +# Changelog + +## [1.6.0](https://github.com/google/uuid/compare/v1.5.0...v1.6.0) (2024-01-16) + + +### Features + +* add Max UUID constant ([#149](https://github.com/google/uuid/issues/149)) ([c58770e](https://github.com/google/uuid/commit/c58770eb495f55fe2ced6284f93c5158a62e53e3)) + + +### Bug Fixes + +* fix typo in version 7 uuid documentation ([#153](https://github.com/google/uuid/issues/153)) ([016b199](https://github.com/google/uuid/commit/016b199544692f745ffc8867b914129ecb47ef06)) +* Monotonicity in UUIDv7 ([#150](https://github.com/google/uuid/issues/150)) ([a2b2b32](https://github.com/google/uuid/commit/a2b2b32373ff0b1a312b7fdf6d38a977099698a6)) + +## [1.5.0](https://github.com/google/uuid/compare/v1.4.0...v1.5.0) (2023-12-12) + + +### Features + +* Validate UUID without creating new UUID ([#141](https://github.com/google/uuid/issues/141)) ([9ee7366](https://github.com/google/uuid/commit/9ee7366e66c9ad96bab89139418a713dc584ae29)) + +## [1.4.0](https://github.com/google/uuid/compare/v1.3.1...v1.4.0) (2023-10-26) + + +### Features + +* UUIDs slice type with Strings() convenience method ([#133](https://github.com/google/uuid/issues/133)) ([cd5fbbd](https://github.com/google/uuid/commit/cd5fbbdd02f3e3467ac18940e07e062be1f864b4)) + +### Fixes + +* Clarify that Parse's job is to parse but not necessarily validate strings. (Documents current behavior) + +## [1.3.1](https://github.com/google/uuid/compare/v1.3.0...v1.3.1) (2023-08-18) + + +### Bug Fixes + +* Use .EqualFold() to parse urn prefixed UUIDs ([#118](https://github.com/google/uuid/issues/118)) ([574e687](https://github.com/google/uuid/commit/574e6874943741fb99d41764c705173ada5293f0)) + +## Changelog diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/google/uuid/CONTRIBUTING.md b/trunk/3rdparty/srs-bench/vendor/github.com/google/uuid/CONTRIBUTING.md index 04fdf09f1..a502fdc51 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/google/uuid/CONTRIBUTING.md +++ b/trunk/3rdparty/srs-bench/vendor/github.com/google/uuid/CONTRIBUTING.md @@ -2,6 +2,22 @@ We definitely welcome patches and contribution to this project! +### Tips + +Commits must be formatted according to the [Conventional Commits Specification](https://www.conventionalcommits.org). + +Always try to include a test case! If it is not possible or not necessary, +please explain why in the pull request description. + +### Releasing + +Commits that would precipitate a SemVer change, as described in the Conventional +Commits Specification, will trigger [`release-please`](https://github.com/google-github-actions/release-please-action) +to create a release candidate pull request. Once submitted, `release-please` +will create a release. + +For tips on how to work with `release-please`, see its documentation. + ### Legal requirements In order to protect both you and ourselves, you will need to sign the diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/google/uuid/README.md b/trunk/3rdparty/srs-bench/vendor/github.com/google/uuid/README.md index f765a46f9..3e9a61889 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/google/uuid/README.md +++ b/trunk/3rdparty/srs-bench/vendor/github.com/google/uuid/README.md @@ -1,6 +1,6 @@ -# uuid ![build status](https://travis-ci.org/google/uuid.svg?branch=master) +# uuid The uuid package generates and inspects UUIDs based on -[RFC 4122](http://tools.ietf.org/html/rfc4122) +[RFC 4122](https://datatracker.ietf.org/doc/html/rfc4122) and DCE 1.1: Authentication and Security Services. This package is based on the github.com/pborman/uuid package (previously named @@ -9,10 +9,12 @@ a UUID is a 16 byte array rather than a byte slice. One loss due to this change is the ability to represent an invalid UUID (vs a NIL UUID). ###### Install -`go get github.com/google/uuid` +```sh +go get github.com/google/uuid +``` ###### Documentation -[![GoDoc](https://godoc.org/github.com/google/uuid?status.svg)](http://godoc.org/github.com/google/uuid) +[![Go Reference](https://pkg.go.dev/badge/github.com/google/uuid.svg)](https://pkg.go.dev/github.com/google/uuid) Full `go doc` style documentation for the package can be viewed online without installing this package by using the GoDoc site here: diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/google/uuid/hash.go b/trunk/3rdparty/srs-bench/vendor/github.com/google/uuid/hash.go index b404f4bec..dc60082d3 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/google/uuid/hash.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/google/uuid/hash.go @@ -17,6 +17,12 @@ var ( NameSpaceOID = Must(Parse("6ba7b812-9dad-11d1-80b4-00c04fd430c8")) NameSpaceX500 = Must(Parse("6ba7b814-9dad-11d1-80b4-00c04fd430c8")) Nil UUID // empty UUID, all zeros + + // The Max UUID is special form of UUID that is specified to have all 128 bits set to 1. + Max = UUID{ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + } ) // NewHash returns a new UUID derived from the hash of space concatenated with diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/google/uuid/node_js.go b/trunk/3rdparty/srs-bench/vendor/github.com/google/uuid/node_js.go index 24b78edc9..b2a0bc871 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/google/uuid/node_js.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/google/uuid/node_js.go @@ -7,6 +7,6 @@ package uuid // getHardwareInterface returns nil values for the JS version of the code. -// This remvoves the "net" dependency, because it is not used in the browser. +// This removes the "net" dependency, because it is not used in the browser. // Using the "net" library inflates the size of the transpiled JS code by 673k bytes. func getHardwareInterface(name string) (string, []byte) { return "", nil } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/google/uuid/time.go b/trunk/3rdparty/srs-bench/vendor/github.com/google/uuid/time.go index e6ef06cdc..c35112927 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/google/uuid/time.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/google/uuid/time.go @@ -108,12 +108,23 @@ func setClockSequence(seq int) { } // Time returns the time in 100s of nanoseconds since 15 Oct 1582 encoded in -// uuid. The time is only defined for version 1 and 2 UUIDs. +// uuid. The time is only defined for version 1, 2, 6 and 7 UUIDs. func (uuid UUID) Time() Time { - time := int64(binary.BigEndian.Uint32(uuid[0:4])) - time |= int64(binary.BigEndian.Uint16(uuid[4:6])) << 32 - time |= int64(binary.BigEndian.Uint16(uuid[6:8])&0xfff) << 48 - return Time(time) + var t Time + switch uuid.Version() { + case 6: + time := binary.BigEndian.Uint64(uuid[:8]) // Ignore uuid[6] version b0110 + t = Time(time) + case 7: + time := binary.BigEndian.Uint64(uuid[:8]) + t = Time((time>>16)*10000 + g1582ns100) + default: // forward compatible + time := int64(binary.BigEndian.Uint32(uuid[0:4])) + time |= int64(binary.BigEndian.Uint16(uuid[4:6])) << 32 + time |= int64(binary.BigEndian.Uint16(uuid[6:8])&0xfff) << 48 + t = Time(time) + } + return t } // ClockSequence returns the clock sequence encoded in uuid. diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/google/uuid/uuid.go b/trunk/3rdparty/srs-bench/vendor/github.com/google/uuid/uuid.go index a57207aeb..5232b4867 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/google/uuid/uuid.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/google/uuid/uuid.go @@ -56,11 +56,15 @@ func IsInvalidLengthError(err error) bool { return ok } -// Parse decodes s into a UUID or returns an error. Both the standard UUID -// forms of xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx and -// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx are decoded as well as the -// Microsoft encoding {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} and the raw hex -// encoding: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx. +// Parse decodes s into a UUID or returns an error if it cannot be parsed. Both +// the standard UUID forms defined in RFC 4122 +// (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx and +// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx) are decoded. In addition, +// Parse accepts non-standard strings such as the raw hex encoding +// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx and 38 byte "Microsoft style" encodings, +// e.g. {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}. Only the middle 36 bytes are +// examined in the latter case. Parse should not be used to validate strings as +// it parses non-standard encodings as indicated above. func Parse(s string) (UUID, error) { var uuid UUID switch len(s) { @@ -69,7 +73,7 @@ func Parse(s string) (UUID, error) { // urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx case 36 + 9: - if strings.ToLower(s[:9]) != "urn:uuid:" { + if !strings.EqualFold(s[:9], "urn:uuid:") { return uuid, fmt.Errorf("invalid urn prefix: %q", s[:9]) } s = s[9:] @@ -101,7 +105,8 @@ func Parse(s string) (UUID, error) { 9, 11, 14, 16, 19, 21, - 24, 26, 28, 30, 32, 34} { + 24, 26, 28, 30, 32, 34, + } { v, ok := xtob(s[x], s[x+1]) if !ok { return uuid, errors.New("invalid UUID format") @@ -117,7 +122,7 @@ func ParseBytes(b []byte) (UUID, error) { switch len(b) { case 36: // xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx case 36 + 9: // urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - if !bytes.Equal(bytes.ToLower(b[:9]), []byte("urn:uuid:")) { + if !bytes.EqualFold(b[:9], []byte("urn:uuid:")) { return uuid, fmt.Errorf("invalid urn prefix: %q", b[:9]) } b = b[9:] @@ -145,7 +150,8 @@ func ParseBytes(b []byte) (UUID, error) { 9, 11, 14, 16, 19, 21, - 24, 26, 28, 30, 32, 34} { + 24, 26, 28, 30, 32, 34, + } { v, ok := xtob(b[x], b[x+1]) if !ok { return uuid, errors.New("invalid UUID format") @@ -180,6 +186,59 @@ func Must(uuid UUID, err error) UUID { return uuid } +// Validate returns an error if s is not a properly formatted UUID in one of the following formats: +// xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx +// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx +// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +// {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} +// It returns an error if the format is invalid, otherwise nil. +func Validate(s string) error { + switch len(s) { + // Standard UUID format + case 36: + + // UUID with "urn:uuid:" prefix + case 36 + 9: + if !strings.EqualFold(s[:9], "urn:uuid:") { + return fmt.Errorf("invalid urn prefix: %q", s[:9]) + } + s = s[9:] + + // UUID enclosed in braces + case 36 + 2: + if s[0] != '{' || s[len(s)-1] != '}' { + return fmt.Errorf("invalid bracketed UUID format") + } + s = s[1 : len(s)-1] + + // UUID without hyphens + case 32: + for i := 0; i < len(s); i += 2 { + _, ok := xtob(s[i], s[i+1]) + if !ok { + return errors.New("invalid UUID format") + } + } + + default: + return invalidLengthError{len(s)} + } + + // Check for standard UUID format + if len(s) == 36 { + if s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-' { + return errors.New("invalid UUID format") + } + for _, x := range []int{0, 2, 4, 6, 9, 11, 14, 16, 19, 21, 24, 26, 28, 30, 32, 34} { + if _, ok := xtob(s[x], s[x+1]); !ok { + return errors.New("invalid UUID format") + } + } + } + + return nil +} + // String returns the string form of uuid, xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx // , or "" if uuid is invalid. func (uuid UUID) String() string { @@ -292,3 +351,15 @@ func DisableRandPool() { poolMu.Lock() poolPos = randPoolSize } + +// UUIDs is a slice of UUID types. +type UUIDs []UUID + +// Strings returns a string slice containing the string form of each UUID in uuids. +func (uuids UUIDs) Strings() []string { + var uuidStrs = make([]string, len(uuids)) + for i, uuid := range uuids { + uuidStrs[i] = uuid.String() + } + return uuidStrs +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/google/uuid/version6.go b/trunk/3rdparty/srs-bench/vendor/github.com/google/uuid/version6.go new file mode 100644 index 000000000..339a959a7 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/google/uuid/version6.go @@ -0,0 +1,56 @@ +// Copyright 2023 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package uuid + +import "encoding/binary" + +// UUID version 6 is a field-compatible version of UUIDv1, reordered for improved DB locality. +// It is expected that UUIDv6 will primarily be used in contexts where there are existing v1 UUIDs. +// Systems that do not involve legacy UUIDv1 SHOULD consider using UUIDv7 instead. +// +// see https://datatracker.ietf.org/doc/html/draft-peabody-dispatch-new-uuid-format-03#uuidv6 +// +// NewV6 returns a Version 6 UUID based on the current NodeID and clock +// sequence, and the current time. If the NodeID has not been set by SetNodeID +// or SetNodeInterface then it will be set automatically. If the NodeID cannot +// be set NewV6 set NodeID is random bits automatically . If clock sequence has not been set by +// SetClockSequence then it will be set automatically. If GetTime fails to +// return the current NewV6 returns Nil and an error. +func NewV6() (UUID, error) { + var uuid UUID + now, seq, err := GetTime() + if err != nil { + return uuid, err + } + + /* + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | time_high | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | time_mid | time_low_and_version | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + |clk_seq_hi_res | clk_seq_low | node (0-1) | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | node (2-5) | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + + binary.BigEndian.PutUint64(uuid[0:], uint64(now)) + binary.BigEndian.PutUint16(uuid[8:], seq) + + uuid[6] = 0x60 | (uuid[6] & 0x0F) + uuid[8] = 0x80 | (uuid[8] & 0x3F) + + nodeMu.Lock() + if nodeID == zeroID { + setNodeInterface("") + } + copy(uuid[10:], nodeID[:]) + nodeMu.Unlock() + + return uuid, nil +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/google/uuid/version7.go b/trunk/3rdparty/srs-bench/vendor/github.com/google/uuid/version7.go new file mode 100644 index 000000000..3167b643d --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/google/uuid/version7.go @@ -0,0 +1,104 @@ +// Copyright 2023 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package uuid + +import ( + "io" +) + +// UUID version 7 features a time-ordered value field derived from the widely +// implemented and well known Unix Epoch timestamp source, +// the number of milliseconds seconds since midnight 1 Jan 1970 UTC, leap seconds excluded. +// As well as improved entropy characteristics over versions 1 or 6. +// +// see https://datatracker.ietf.org/doc/html/draft-peabody-dispatch-new-uuid-format-03#name-uuid-version-7 +// +// Implementations SHOULD utilize UUID version 7 over UUID version 1 and 6 if possible. +// +// NewV7 returns a Version 7 UUID based on the current time(Unix Epoch). +// Uses the randomness pool if it was enabled with EnableRandPool. +// On error, NewV7 returns Nil and an error +func NewV7() (UUID, error) { + uuid, err := NewRandom() + if err != nil { + return uuid, err + } + makeV7(uuid[:]) + return uuid, nil +} + +// NewV7FromReader returns a Version 7 UUID based on the current time(Unix Epoch). +// it use NewRandomFromReader fill random bits. +// On error, NewV7FromReader returns Nil and an error. +func NewV7FromReader(r io.Reader) (UUID, error) { + uuid, err := NewRandomFromReader(r) + if err != nil { + return uuid, err + } + + makeV7(uuid[:]) + return uuid, nil +} + +// makeV7 fill 48 bits time (uuid[0] - uuid[5]), set version b0111 (uuid[6]) +// uuid[8] already has the right version number (Variant is 10) +// see function NewV7 and NewV7FromReader +func makeV7(uuid []byte) { + /* + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | unix_ts_ms | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | unix_ts_ms | ver | rand_a (12 bit seq) | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + |var| rand_b | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | rand_b | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + _ = uuid[15] // bounds check + + t, s := getV7Time() + + uuid[0] = byte(t >> 40) + uuid[1] = byte(t >> 32) + uuid[2] = byte(t >> 24) + uuid[3] = byte(t >> 16) + uuid[4] = byte(t >> 8) + uuid[5] = byte(t) + + uuid[6] = 0x70 | (0x0F & byte(s>>8)) + uuid[7] = byte(s) +} + +// lastV7time is the last time we returned stored as: +// +// 52 bits of time in milliseconds since epoch +// 12 bits of (fractional nanoseconds) >> 8 +var lastV7time int64 + +const nanoPerMilli = 1000000 + +// getV7Time returns the time in milliseconds and nanoseconds / 256. +// The returned (milli << 12 + seq) is guarenteed to be greater than +// (milli << 12 + seq) returned by any previous call to getV7Time. +func getV7Time() (milli, seq int64) { + timeMu.Lock() + defer timeMu.Unlock() + + nano := timeNow().UnixNano() + milli = nano / nanoPerMilli + // Sequence number is between 0 and 3906 (nanoPerMilli>>8) + seq = (nano - milli*nanoPerMilli) >> 8 + now := milli<<12 + seq + if now <= lastV7time { + now = lastV7time + 1 + milli = now >> 12 + seq = now & 0xfff + } + lastV7time = now + return milli, seq +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/ossrs/go-oryx-lib/LICENSE b/trunk/3rdparty/srs-bench/vendor/github.com/ossrs/go-oryx-lib/LICENSE index 26b811fc1..6615e30a2 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/ossrs/go-oryx-lib/LICENSE +++ b/trunk/3rdparty/srs-bench/vendor/github.com/ossrs/go-oryx-lib/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2013-2025 winlin +Copyright (c) 2013-2017 winlin Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/datachannel/.gitignore b/trunk/3rdparty/srs-bench/vendor/github.com/pion/datachannel/.gitignore index f977e7485..6e2f206a9 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/datachannel/.gitignore +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/datachannel/.gitignore @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2023 The Pion community +# SPDX-License-Identifier: MIT + ### JetBrains IDE ### ##################### .idea/ diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/datachannel/.golangci.yml b/trunk/3rdparty/srs-bench/vendor/github.com/pion/datachannel/.golangci.yml index d7a88eca3..a3235bec2 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/datachannel/.golangci.yml +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/datachannel/.golangci.yml @@ -1,6 +1,13 @@ +# SPDX-FileCopyrightText: 2023 The Pion community +# SPDX-License-Identifier: MIT + +run: + timeout: 5m + linters-settings: govet: - check-shadowing: true + enable: + - shadow misspell: locale: US exhaustive: @@ -10,7 +17,14 @@ linters-settings: modules: - github.com/pkg/errors: recommendations: - - errors + - errors + forbidigo: + forbid: + - ^fmt.Print(f|ln)?$ + - ^log.(Panic|Fatal|Print)(f|ln)?$ + - ^os.Exit$ + - ^panic$ + - ^print(ln)?$ linters: enable: @@ -18,9 +32,7 @@ linters: - bidichk # Checks for dangerous unicode character sequences - bodyclose # checks whether HTTP response body is closed successfully - contextcheck # check the function whether use a non-inherited context - - deadcode # Finds unused code - decorder # check declaration order and count of types, constants, variables and functions - - depguard # Go linter that checks if package imports are in a list of acceptable packages - dogsled # Checks assignments with too many blank identifiers (e.g. x, _, _, _, := f()) - dupl # Tool for code clone detection - durationcheck # check for two durations multiplied together @@ -30,6 +42,7 @@ linters: - errorlint # errorlint is a linter for that can be used to find code that will cause problems with the error wrapping scheme introduced in Go 1.13. - exhaustive # check exhaustiveness of enum switch statements - exportloopref # checks for pointers to enclosing loop variables + - forbidigo # Forbids identifiers - forcetypeassert # finds forced type assertions - gci # Gci control golang package import order and make it always deterministic. - gochecknoglobals # Checks that no globals are present in Go code @@ -38,7 +51,7 @@ linters: - goconst # Finds repeated strings that could be replaced by a constant - gocritic # The most opinionated Go source code linter - godox # Tool for detection of FIXME, TODO and other comment keywords - - goerr113 # Golang linter to check the errors handling expressions + - err113 # Golang linter to check the errors handling expressions - gofmt # Gofmt checks whether code was gofmt-ed. By default this tool runs with -s option to check for code simplification - gofumpt # Gofumpt checks whether code was gofumpt-ed. - goheader # Checks is file header matches to pattern @@ -53,14 +66,12 @@ linters: - importas # Enforces consistent import aliases - ineffassign # Detects when assignments to existing variables are not used - misspell # Finds commonly misspelled English words in comments - - nakedret # Finds naked returns in functions greater than a specified function length - nilerr # Finds the code that returns nil even if it checks that the error is not nil. - nilnil # Checks that there is no simultaneous return of `nil` error and an invalid value. - noctx # noctx finds sending http request without context.Context - predeclared # find code that shadows one of Go's predeclared identifiers - revive # golint replacement, finds style mistakes - staticcheck # Staticcheck is a go vet on steroids, applying a ton of static analysis checks - - structcheck # Finds unused struct fields - stylecheck # Stylecheck is a replacement for golint - tagliatelle # Checks the struct tags. - tenv # tenv is analyzer that detects using os.Setenv instead of t.Setenv since Go1.17 @@ -69,24 +80,21 @@ linters: - unconvert # Remove unnecessary type conversions - unparam # Reports unused function parameters - unused # Checks Go code for unused constants, variables, functions and types - - varcheck # Finds unused global variables and constants - wastedassign # wastedassign finds wasted assignment statements - whitespace # Tool for detection of leading and trailing whitespace disable: + - depguard # Go linter that checks if package imports are in a list of acceptable packages - containedctx # containedctx is a linter that detects struct contained context.Context field - cyclop # checks function and package cyclomatic complexity - - exhaustivestruct # Checks if all struct's fields are initialized - - forbidigo # Forbids identifiers - funlen # Tool for detection of long functions - gocyclo # Computes and checks the cyclomatic complexity of functions - godot # Check if comments end in a period - gomnd # An analyzer to detect magic numbers. - - ifshort # Checks that your code uses short syntax for if-statements whenever possible - ireturn # Accept Interfaces, Return Concrete Types - lll # Reports long lines - maintidx # maintidx measures the maintainability index of each function. - makezero # Finds slice declarations with non-zero initial length - - maligned # Tool to detect Go structs that would take less memory if their fields were sorted + - nakedret # Finds naked returns in functions greater than a specified function length - nestif # Reports deeply nested if statements - nlreturn # nlreturn checks for a new line before return and branch statements to increase code clarity - nolintlint # Reports ill-formed or insufficient nolint directives @@ -103,17 +111,15 @@ linters: issues: exclude-use-default: false + exclude-dirs-use-default: false exclude-rules: - # Allow complex tests, better to be self contained - - path: _test\.go + # Allow complex tests and examples, better to be self contained + - path: (examples|main\.go|_test\.go) linters: + - forbidigo - gocognit - # Allow complex main function in examples - - path: examples - text: "of func `main` is high" + # Allow forbidden identifiers in CLI commands + - path: cmd linters: - - gocognit - -run: - skip-dirs-use-default: false + - forbidigo diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/.goreleaser.yml b/trunk/3rdparty/srs-bench/vendor/github.com/pion/datachannel/.goreleaser.yml similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/.goreleaser.yml rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/datachannel/.goreleaser.yml diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/datachannel/AUTHORS.txt b/trunk/3rdparty/srs-bench/vendor/github.com/pion/datachannel/AUTHORS.txt deleted file mode 100644 index c5d9d8d34..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/datachannel/AUTHORS.txt +++ /dev/null @@ -1,17 +0,0 @@ -# Thank you to everyone that made Pion possible. If you are interested in contributing -# we would love to have you https://github.com/pion/webrtc/wiki/Contributing -# -# This file is auto generated, using git to list all individuals contributors. -# see `.github/generate-authors.sh` for the scripting -Atsushi Watanabe -backkem -Benny Daon -Chinmay Kousik -Eric Daniels -Hugo Arregui -Hugo Arregui -John Bradley -Norman Rasmussen -Sean DuBois -Sean DuBois -Yutaka Takeda diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/datachannel/DESIGN.md b/trunk/3rdparty/srs-bench/vendor/github.com/pion/datachannel/DESIGN.md deleted file mode 100644 index 55d6c8fff..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/datachannel/DESIGN.md +++ /dev/null @@ -1,20 +0,0 @@ -

- Design -

- -### Portable -Pion Data Channels is written in Go and extremely portable. Anywhere Golang runs, Pion Data Channels should work as well! Instead of dealing with complicated -cross-compiling of multiple libraries, you now can run anywhere with one `go build` - -### Simple API -The API is based on an io.ReadWriteCloser. - -### Readable -If code comes from an RFC we try to make sure everything is commented with a link to the spec. -This makes learning and debugging easier, this library was written to also serve as a guide for others. - -### Tested -Every commit is tested via travis-ci Go provides fantastic facilities for testing, and more will be added as time goes on. - -### Shared libraries -Every pion product is built using shared libraries, allowing others to review and reuse our libraries. diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/datachannel/LICENSE b/trunk/3rdparty/srs-bench/vendor/github.com/pion/datachannel/LICENSE index ab602974d..491caf6b0 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/datachannel/LICENSE +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/datachannel/LICENSE @@ -1,21 +1,9 @@ MIT License -Copyright (c) 2018 +Copyright (c) 2023 The Pion community -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/datachannel/README.md b/trunk/3rdparty/srs-bench/vendor/github.com/pion/datachannel/README.md index 7be311dae..c68be942a 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/datachannel/README.md +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/datachannel/README.md @@ -6,32 +6,29 @@

A Go implementation of WebRTC Data Channels

Pion Data Channels - Slack Widget
- Build Status - GoDoc + GitHub Workflow Status + Go Reference Coverage Status Go Report Card - License: MIT


-See [DESIGN.md](DESIGN.md) for an overview of features and future goals. - ### Roadmap The library is used as a part of our WebRTC implementation. Please refer to that [roadmap](https://github.com/pion/webrtc/issues/9) to track our major milestones. ### Community -Pion has an active community on the [Golang Slack](https://invite.slack.golangbridge.org/). Sign up and join the **#pion** channel for discussions and support. You can also use [Pion mailing list](https://groups.google.com/forum/#!forum/pion). +Pion has an active community on the [Slack](https://pion.ly/slack). + +Follow the [Pion Twitter](https://twitter.com/_pion) for project updates and important WebRTC news. We are always looking to support **your projects**. Please reach out if you have something to build! - If you need commercial support or don't want to use public methods you can contact us at [team@pion.ly](mailto:team@pion.ly) ### Contributing -Check out the **[contributing wiki](https://github.com/pion/webrtc/wiki/Contributing)** to join the group of amazing people making this project possible: +Check out the [contributing wiki](https://github.com/pion/webrtc/wiki/Contributing) to join the group of amazing people making this project possible ### License MIT License - see [LICENSE](LICENSE) for full text diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/datachannel/codecov.yml b/trunk/3rdparty/srs-bench/vendor/github.com/pion/datachannel/codecov.yml index 085200a48..263e4d45c 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/datachannel/codecov.yml +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/datachannel/codecov.yml @@ -3,6 +3,8 @@ # # It is automatically copied from https://github.com/pion/.goassets repository. # +# SPDX-FileCopyrightText: 2023 The Pion community +# SPDX-License-Identifier: MIT coverage: status: diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/datachannel/datachannel.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/datachannel/datachannel.go index 0b125d662..8ece01960 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/datachannel/datachannel.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/datachannel/datachannel.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + // Package datachannel implements WebRTC Data Channels package datachannel @@ -32,6 +35,11 @@ type Writer interface { WriteDataChannel([]byte, bool) (int, error) } +// WriteDeadliner extends an io.Writer to expose setting a write deadline. +type WriteDeadliner interface { + SetWriteDeadline(time.Time) error +} + // ReadWriteCloser is an extended io.ReadWriteCloser // that also implements our Reader and Writer. type ReadWriteCloser interface { @@ -42,6 +50,14 @@ type ReadWriteCloser interface { io.Closer } +// ReadWriteCloserDeadliner is an extended ReadWriteCloser +// that also implements r/w deadline. +type ReadWriteCloserDeadliner interface { + ReadWriteCloser + ReadDeadliner + WriteDeadliner +} + // DataChannel represents a data channel type DataChannel struct { Config @@ -71,12 +87,12 @@ type Config struct { LoggerFactory logging.LoggerFactory } -func newDataChannel(stream *sctp.Stream, config *Config) (*DataChannel, error) { +func newDataChannel(stream *sctp.Stream, config *Config) *DataChannel { return &DataChannel{ Config: *config, stream: stream, log: config.LoggerFactory.NewLogger("datachannel"), - }, nil + } } // Dial opens a data channels over SCTP @@ -115,7 +131,7 @@ func Client(stream *sctp.Stream, config *Config) (*DataChannel, error) { return nil, fmt.Errorf("failed to send ChannelOpen %w", err) } } - return newDataChannel(stream, config) + return newDataChannel(stream, config), nil } // Accept is used to accept incoming data channels over SCTP @@ -164,10 +180,7 @@ func Server(stream *sctp.Stream, config *Config) (*DataChannel, error) { config.Label = string(openMsg.Label) config.Protocol = string(openMsg.Protocol) - dataChannel, err := newDataChannel(stream, config) - if err != nil { - return nil, err - } + dataChannel := newDataChannel(stream, config) err = dataChannel.writeDataChannelAck() if err != nil { @@ -224,6 +237,12 @@ func (c *DataChannel) SetReadDeadline(t time.Time) error { return c.stream.SetReadDeadline(t) } +// SetWriteDeadline sets a deadline for writes to return, +// only available if the BlockWrite is enabled for sctp +func (c *DataChannel) SetWriteDeadline(t time.Time) error { + return c.stream.SetWriteDeadline(t) +} + // MessagesSent returns the number of messages sent func (c *DataChannel) MessagesSent() uint32 { return atomic.LoadUint32(&c.messagesSent) @@ -280,13 +299,12 @@ func (c *DataChannel) handleDCEP(data []byte) error { switch msg := msg.(type) { case *channelAck: - c.log.Debug("Received DATA_CHANNEL_ACK") - if err = c.commitReliabilityParams(); err != nil { + if err := c.commitReliabilityParams(); err != nil { return err } c.onOpenComplete() default: - return fmt.Errorf("%w %v", ErrInvalidMessageType, msg) + return fmt.Errorf("%w, wanted ACK got %v", ErrUnexpectedDataChannelType, msg) } return nil diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/datachannel/errors.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/datachannel/errors.go index f7aeecc0d..2f98bf84b 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/datachannel/errors.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/datachannel/errors.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package datachannel import "errors" diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/datachannel/message.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/datachannel/message.go index 27848c77f..f71ce7bc5 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/datachannel/message.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/datachannel/message.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package datachannel import ( @@ -8,6 +11,7 @@ import ( type message interface { Marshal() ([]byte, error) Unmarshal([]byte) error + String() string } // messageType is the first byte in a DataChannel message that specifies type @@ -71,3 +75,18 @@ func parseExpectDataChannelOpen(raw []byte) (*channelOpen, error) { return msg, nil } + +// TryMarshalUnmarshal attempts to marshal and unmarshal a message. Added for fuzzing. +func TryMarshalUnmarshal(msg []byte) int { + message, err := parse(msg) + if err != nil { + return 0 + } + + _, err = message.Marshal() + if err != nil { + return 0 + } + + return 1 +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/datachannel/message_channel_ack.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/datachannel/message_channel_ack.go index fd2075790..8fe396f86 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/datachannel/message_channel_ack.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/datachannel/message_channel_ack.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package datachannel // channelAck is used to ACK a DataChannel open @@ -16,7 +19,11 @@ func (c *channelAck) Marshal() ([]byte, error) { } // Unmarshal populates the struct with the given raw data -func (c *channelAck) Unmarshal(raw []byte) error { +func (c *channelAck) Unmarshal(_ []byte) error { // Message type already checked in Parse and there is no further data return nil } + +func (c channelAck) String() string { + return "ACK" +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/datachannel/message_channel_open.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/datachannel/message_channel_open.go index 5eb58633c..dac58ff65 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/datachannel/message_channel_open.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/datachannel/message_channel_open.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package datachannel import ( @@ -72,6 +75,23 @@ const ( ChannelTypePartialReliableTimedUnordered ChannelType = 0x82 ) +func (c ChannelType) String() string { + switch c { + case ChannelTypeReliable: + case ChannelTypeReliableUnordered: + return "ReliableUnordered" + case ChannelTypePartialReliableRexmit: + return "PartialReliableRexmit" + case ChannelTypePartialReliableRexmitUnordered: + return "PartialReliableRexmitUnordered" + case ChannelTypePartialReliableTimed: + return "PartialReliableTimed" + case ChannelTypePartialReliableTimedUnordered: + return "PartialReliableTimedUnordered" + } + return "Unknown" +} + // ChannelPriority enums const ( ChannelPriorityBelowNormal uint16 = 128 @@ -113,7 +133,7 @@ func (c *channelOpen) Unmarshal(raw []byte) error { labelLength := binary.BigEndian.Uint16(raw[8:]) protocolLength := binary.BigEndian.Uint16(raw[10:]) - if expectedLen := int(channelOpenHeaderLength + labelLength + protocolLength); len(raw) != expectedLen { + if expectedLen := channelOpenHeaderLength + int(labelLength) + int(protocolLength); len(raw) != expectedLen { return fmt.Errorf("%w expected(%d) actual(%d)", ErrExpectedAndActualLengthMismatch, expectedLen, len(raw)) } @@ -121,3 +141,7 @@ func (c *channelOpen) Unmarshal(raw []byte) error { c.Protocol = raw[channelOpenHeaderLength+labelLength : channelOpenHeaderLength+labelLength+protocolLength] return nil } + +func (c channelOpen) String() string { + return fmt.Sprintf("Open ChannelType(%s) Priority(%v) ReliabilityParameter(%d) Label(%s) Protocol(%s)", c.ChannelType, c.Priority, c.ReliabilityParameter, string(c.Label), string(c.Protocol)) +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/datachannel/renovate.json b/trunk/3rdparty/srs-bench/vendor/github.com/pion/datachannel/renovate.json index f1614058a..f1bb98c6a 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/datachannel/renovate.json +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/datachannel/renovate.json @@ -1,27 +1,6 @@ { + "$schema": "https://docs.renovatebot.com/renovate-schema.json", "extends": [ - "config:base", - ":disableDependencyDashboard" - ], - "postUpdateOptions": [ - "gomodTidy" - ], - "commitBody": "Generated by renovateBot", - "packageRules": [ - { - "matchUpdateTypes": ["minor", "patch", "pin", "digest"], - "automerge": true - }, - { - "packagePatterns": ["^golang.org/x/"], - "schedule": ["on the first day of the month"] - } - ], - "ignorePaths": [ - ".github/workflows/generate-authors.yml", - ".github/workflows/lint.yaml", - ".github/workflows/renovate-go-mod-fix.yaml", - ".github/workflows/test.yaml", - ".github/workflows/tidy-check.yaml" + "github>pion/renovate-config" ] } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/AUTHORS.txt b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/AUTHORS.txt deleted file mode 100644 index e14fae4c0..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/AUTHORS.txt +++ /dev/null @@ -1,57 +0,0 @@ -# Thank you to everyone that made Pion possible. If you are interested in contributing -# we would love to have you https://github.com/pion/webrtc/wiki/Contributing -# -# This file is auto generated, using git to list all individuals contributors. -# see https://github.com/pion/.goassets/blob/master/scripts/generate-authors.sh for the scripting -Aleksandr Razumov -alvarowolfx -Arlo Breault -Atsushi Watanabe -backkem -bjdgyc -boks1971 -Bragadeesh -Carson Hoffman -Cecylia Bocovich -Chris Hiszpanski -cnderrauber -Daniele Sluijters -folbrich -Hayden James -Hugo Arregui -Hugo Arregui -igolaizola <11333576+igolaizola@users.noreply.github.com> -Jeffrey Stoke -Jeroen de Bruijn -Jeroen de Bruijn -Jim Wert -jinleileiking -Jozef Kralik -Julien Salleyron -Juliusz Chroboczek -Kegan Dougal -Kevin Wang -Lander Noterman -Len -Lukas Lihotzki -ManuelBk <26275612+ManuelBk@users.noreply.github.com> -Michael Zabka -Michiel De Backker -Rachel Chen -Robert Eperjesi -Ryan Gordon -Sam Lancia -Sean DuBois -Sean DuBois -Sean DuBois -Shelikhoo -Stefan Tatschner -Steffen Vogel -Vadim -Vadim Filimonov -wmiao -ZHENK -吕海涛 - -# List of contributors not appearing in Git history - diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/conn.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/conn.go deleted file mode 100644 index 2b7585108..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/conn.go +++ /dev/null @@ -1,1032 +0,0 @@ -// SPDX-FileCopyrightText: 2023 The Pion community -// SPDX-License-Identifier: MIT - -package dtls - -import ( - "context" - "errors" - "fmt" - "io" - "net" - "sync" - "sync/atomic" - "time" - - "github.com/pion/dtls/v2/internal/closer" - "github.com/pion/dtls/v2/pkg/crypto/elliptic" - "github.com/pion/dtls/v2/pkg/crypto/signaturehash" - "github.com/pion/dtls/v2/pkg/protocol" - "github.com/pion/dtls/v2/pkg/protocol/alert" - "github.com/pion/dtls/v2/pkg/protocol/handshake" - "github.com/pion/dtls/v2/pkg/protocol/recordlayer" - "github.com/pion/logging" - "github.com/pion/transport/v2/connctx" - "github.com/pion/transport/v2/deadline" - "github.com/pion/transport/v2/replaydetector" -) - -const ( - initialTickerInterval = time.Second - cookieLength = 20 - sessionLength = 32 - defaultNamedCurve = elliptic.X25519 - inboundBufferSize = 8192 - // Default replay protection window is specified by RFC 6347 Section 4.1.2.6 - defaultReplayProtectionWindow = 64 -) - -func invalidKeyingLabels() map[string]bool { - return map[string]bool{ - "client finished": true, - "server finished": true, - "master secret": true, - "key expansion": true, - } -} - -// Conn represents a DTLS connection -type Conn struct { - lock sync.RWMutex // Internal lock (must not be public) - nextConn connctx.ConnCtx // Embedded Conn, typically a udpconn we read/write from - fragmentBuffer *fragmentBuffer // out-of-order and missing fragment handling - handshakeCache *handshakeCache // caching of handshake messages for verifyData generation - decrypted chan interface{} // Decrypted Application Data or error, pull by calling `Read` - - state State // Internal state - - maximumTransmissionUnit int - - handshakeCompletedSuccessfully atomic.Value - - encryptedPackets [][]byte - - connectionClosedByUser bool - closeLock sync.Mutex - closed *closer.Closer - handshakeLoopsFinished sync.WaitGroup - - readDeadline *deadline.Deadline - writeDeadline *deadline.Deadline - - log logging.LeveledLogger - - reading chan struct{} - handshakeRecv chan chan struct{} - cancelHandshaker func() - cancelHandshakeReader func() - - fsm *handshakeFSM - - replayProtectionWindow uint -} - -func createConn(ctx context.Context, nextConn net.Conn, config *Config, isClient bool, initialState *State) (*Conn, error) { - err := validateConfig(config) - if err != nil { - return nil, err - } - - if nextConn == nil { - return nil, errNilNextConn - } - - cipherSuites, err := parseCipherSuites(config.CipherSuites, config.CustomCipherSuites, config.includeCertificateSuites(), config.PSK != nil) - if err != nil { - return nil, err - } - - signatureSchemes, err := signaturehash.ParseSignatureSchemes(config.SignatureSchemes, config.InsecureHashes) - if err != nil { - return nil, err - } - - workerInterval := initialTickerInterval - if config.FlightInterval != 0 { - workerInterval = config.FlightInterval - } - - loggerFactory := config.LoggerFactory - if loggerFactory == nil { - loggerFactory = logging.NewDefaultLoggerFactory() - } - - logger := loggerFactory.NewLogger("dtls") - - mtu := config.MTU - if mtu <= 0 { - mtu = defaultMTU - } - - replayProtectionWindow := config.ReplayProtectionWindow - if replayProtectionWindow <= 0 { - replayProtectionWindow = defaultReplayProtectionWindow - } - - c := &Conn{ - nextConn: connctx.New(nextConn), - fragmentBuffer: newFragmentBuffer(), - handshakeCache: newHandshakeCache(), - maximumTransmissionUnit: mtu, - - decrypted: make(chan interface{}, 1), - log: logger, - - readDeadline: deadline.New(), - writeDeadline: deadline.New(), - - reading: make(chan struct{}, 1), - handshakeRecv: make(chan chan struct{}), - closed: closer.NewCloser(), - cancelHandshaker: func() {}, - - replayProtectionWindow: uint(replayProtectionWindow), - - state: State{ - isClient: isClient, - }, - } - - c.setRemoteEpoch(0) - c.setLocalEpoch(0) - - serverName := config.ServerName - // Do not allow the use of an IP address literal as an SNI value. - // See RFC 6066, Section 3. - if net.ParseIP(serverName) != nil { - serverName = "" - } - - curves := config.EllipticCurves - if len(curves) == 0 { - curves = defaultCurves - } - - hsCfg := &handshakeConfig{ - localPSKCallback: config.PSK, - localPSKIdentityHint: config.PSKIdentityHint, - localCipherSuites: cipherSuites, - localSignatureSchemes: signatureSchemes, - extendedMasterSecret: config.ExtendedMasterSecret, - localSRTPProtectionProfiles: config.SRTPProtectionProfiles, - serverName: serverName, - supportedProtocols: config.SupportedProtocols, - clientAuth: config.ClientAuth, - localCertificates: config.Certificates, - insecureSkipVerify: config.InsecureSkipVerify, - verifyPeerCertificate: config.VerifyPeerCertificate, - verifyConnection: config.VerifyConnection, - rootCAs: config.RootCAs, - clientCAs: config.ClientCAs, - customCipherSuites: config.CustomCipherSuites, - retransmitInterval: workerInterval, - log: logger, - initialEpoch: 0, - keyLogWriter: config.KeyLogWriter, - sessionStore: config.SessionStore, - ellipticCurves: curves, - localGetCertificate: config.GetCertificate, - localGetClientCertificate: config.GetClientCertificate, - insecureSkipHelloVerify: config.InsecureSkipVerifyHello, - } - - // rfc5246#section-7.4.3 - // In addition, the hash and signature algorithms MUST be compatible - // with the key in the server's end-entity certificate. - if !isClient { - cert, err := hsCfg.getCertificate(&ClientHelloInfo{}) - if err != nil && !errors.Is(err, errNoCertificates) { - return nil, err - } - hsCfg.localCipherSuites = filterCipherSuitesForCertificate(cert, cipherSuites) - } - - var initialFlight flightVal - var initialFSMState handshakeState - - if initialState != nil { - if c.state.isClient { - initialFlight = flight5 - } else { - initialFlight = flight6 - } - initialFSMState = handshakeFinished - - c.state = *initialState - } else { - if c.state.isClient { - initialFlight = flight1 - } else { - initialFlight = flight0 - } - initialFSMState = handshakePreparing - } - // Do handshake - if err := c.handshake(ctx, hsCfg, initialFlight, initialFSMState); err != nil { - return nil, err - } - - c.log.Trace("Handshake Completed") - - return c, nil -} - -// Dial connects to the given network address and establishes a DTLS connection on top. -// Connection handshake will timeout using ConnectContextMaker in the Config. -// If you want to specify the timeout duration, use DialWithContext() instead. -func Dial(network string, raddr *net.UDPAddr, config *Config) (*Conn, error) { - ctx, cancel := config.connectContextMaker() - defer cancel() - - return DialWithContext(ctx, network, raddr, config) -} - -// Client establishes a DTLS connection over an existing connection. -// Connection handshake will timeout using ConnectContextMaker in the Config. -// If you want to specify the timeout duration, use ClientWithContext() instead. -func Client(conn net.Conn, config *Config) (*Conn, error) { - ctx, cancel := config.connectContextMaker() - defer cancel() - - return ClientWithContext(ctx, conn, config) -} - -// Server listens for incoming DTLS connections. -// Connection handshake will timeout using ConnectContextMaker in the Config. -// If you want to specify the timeout duration, use ServerWithContext() instead. -func Server(conn net.Conn, config *Config) (*Conn, error) { - ctx, cancel := config.connectContextMaker() - defer cancel() - - return ServerWithContext(ctx, conn, config) -} - -// DialWithContext connects to the given network address and establishes a DTLS connection on top. -func DialWithContext(ctx context.Context, network string, raddr *net.UDPAddr, config *Config) (*Conn, error) { - pConn, err := net.DialUDP(network, nil, raddr) - if err != nil { - return nil, err - } - return ClientWithContext(ctx, pConn, config) -} - -// ClientWithContext establishes a DTLS connection over an existing connection. -func ClientWithContext(ctx context.Context, conn net.Conn, config *Config) (*Conn, error) { - switch { - case config == nil: - return nil, errNoConfigProvided - case config.PSK != nil && config.PSKIdentityHint == nil: - return nil, errPSKAndIdentityMustBeSetForClient - } - - return createConn(ctx, conn, config, true, nil) -} - -// ServerWithContext listens for incoming DTLS connections. -func ServerWithContext(ctx context.Context, conn net.Conn, config *Config) (*Conn, error) { - if config == nil { - return nil, errNoConfigProvided - } - - return createConn(ctx, conn, config, false, nil) -} - -// Read reads data from the connection. -func (c *Conn) Read(p []byte) (n int, err error) { - if !c.isHandshakeCompletedSuccessfully() { - return 0, errHandshakeInProgress - } - - select { - case <-c.readDeadline.Done(): - return 0, errDeadlineExceeded - default: - } - - for { - select { - case <-c.readDeadline.Done(): - return 0, errDeadlineExceeded - case out, ok := <-c.decrypted: - if !ok { - return 0, io.EOF - } - switch val := out.(type) { - case ([]byte): - if len(p) < len(val) { - return 0, errBufferTooSmall - } - copy(p, val) - return len(val), nil - case (error): - return 0, val - } - } - } -} - -// Write writes len(p) bytes from p to the DTLS connection -func (c *Conn) Write(p []byte) (int, error) { - if c.isConnectionClosed() { - return 0, ErrConnClosed - } - - select { - case <-c.writeDeadline.Done(): - return 0, errDeadlineExceeded - default: - } - - if !c.isHandshakeCompletedSuccessfully() { - return 0, errHandshakeInProgress - } - - return len(p), c.writePackets(c.writeDeadline, []*packet{ - { - record: &recordlayer.RecordLayer{ - Header: recordlayer.Header{ - Epoch: c.state.getLocalEpoch(), - Version: protocol.Version1_2, - }, - Content: &protocol.ApplicationData{ - Data: p, - }, - }, - shouldEncrypt: true, - }, - }) -} - -// Close closes the connection. -func (c *Conn) Close() error { - err := c.close(true) //nolint:contextcheck - c.handshakeLoopsFinished.Wait() - return err -} - -// ConnectionState returns basic DTLS details about the connection. -// Note that this replaced the `Export` function of v1. -func (c *Conn) ConnectionState() State { - c.lock.RLock() - defer c.lock.RUnlock() - return *c.state.clone() -} - -// SelectedSRTPProtectionProfile returns the selected SRTPProtectionProfile -func (c *Conn) SelectedSRTPProtectionProfile() (SRTPProtectionProfile, bool) { - c.lock.RLock() - defer c.lock.RUnlock() - - if c.state.srtpProtectionProfile == 0 { - return 0, false - } - - return c.state.srtpProtectionProfile, true -} - -func (c *Conn) writePackets(ctx context.Context, pkts []*packet) error { - c.lock.Lock() - defer c.lock.Unlock() - - var rawPackets [][]byte - - for _, p := range pkts { - if h, ok := p.record.Content.(*handshake.Handshake); ok { - handshakeRaw, err := p.record.Marshal() - if err != nil { - return err - } - - c.log.Tracef("[handshake:%v] -> %s (epoch: %d, seq: %d)", - srvCliStr(c.state.isClient), h.Header.Type.String(), - p.record.Header.Epoch, h.Header.MessageSequence) - c.handshakeCache.push(handshakeRaw[recordlayer.HeaderSize:], p.record.Header.Epoch, h.Header.MessageSequence, h.Header.Type, c.state.isClient) - - rawHandshakePackets, err := c.processHandshakePacket(p, h) - if err != nil { - return err - } - rawPackets = append(rawPackets, rawHandshakePackets...) - } else { - rawPacket, err := c.processPacket(p) - if err != nil { - return err - } - rawPackets = append(rawPackets, rawPacket) - } - } - if len(rawPackets) == 0 { - return nil - } - compactedRawPackets := c.compactRawPackets(rawPackets) - - for _, compactedRawPackets := range compactedRawPackets { - if _, err := c.nextConn.WriteContext(ctx, compactedRawPackets); err != nil { - return netError(err) - } - } - - return nil -} - -func (c *Conn) compactRawPackets(rawPackets [][]byte) [][]byte { - // avoid a useless copy in the common case - if len(rawPackets) == 1 { - return rawPackets - } - - combinedRawPackets := make([][]byte, 0) - currentCombinedRawPacket := make([]byte, 0) - - for _, rawPacket := range rawPackets { - if len(currentCombinedRawPacket) > 0 && len(currentCombinedRawPacket)+len(rawPacket) >= c.maximumTransmissionUnit { - combinedRawPackets = append(combinedRawPackets, currentCombinedRawPacket) - currentCombinedRawPacket = []byte{} - } - currentCombinedRawPacket = append(currentCombinedRawPacket, rawPacket...) - } - - combinedRawPackets = append(combinedRawPackets, currentCombinedRawPacket) - - return combinedRawPackets -} - -func (c *Conn) processPacket(p *packet) ([]byte, error) { - epoch := p.record.Header.Epoch - for len(c.state.localSequenceNumber) <= int(epoch) { - c.state.localSequenceNumber = append(c.state.localSequenceNumber, uint64(0)) - } - seq := atomic.AddUint64(&c.state.localSequenceNumber[epoch], 1) - 1 - if seq > recordlayer.MaxSequenceNumber { - // RFC 6347 Section 4.1.0 - // The implementation must either abandon an association or rehandshake - // prior to allowing the sequence number to wrap. - return nil, errSequenceNumberOverflow - } - p.record.Header.SequenceNumber = seq - - rawPacket, err := p.record.Marshal() - if err != nil { - return nil, err - } - - if p.shouldEncrypt { - var err error - rawPacket, err = c.state.cipherSuite.Encrypt(p.record, rawPacket) - if err != nil { - return nil, err - } - } - - return rawPacket, nil -} - -func (c *Conn) processHandshakePacket(p *packet, h *handshake.Handshake) ([][]byte, error) { - rawPackets := make([][]byte, 0) - - handshakeFragments, err := c.fragmentHandshake(h) - if err != nil { - return nil, err - } - epoch := p.record.Header.Epoch - for len(c.state.localSequenceNumber) <= int(epoch) { - c.state.localSequenceNumber = append(c.state.localSequenceNumber, uint64(0)) - } - - for _, handshakeFragment := range handshakeFragments { - seq := atomic.AddUint64(&c.state.localSequenceNumber[epoch], 1) - 1 - if seq > recordlayer.MaxSequenceNumber { - return nil, errSequenceNumberOverflow - } - - recordlayerHeader := &recordlayer.Header{ - Version: p.record.Header.Version, - ContentType: p.record.Header.ContentType, - ContentLen: uint16(len(handshakeFragment)), - Epoch: p.record.Header.Epoch, - SequenceNumber: seq, - } - - rawPacket, err := recordlayerHeader.Marshal() - if err != nil { - return nil, err - } - - p.record.Header = *recordlayerHeader - - rawPacket = append(rawPacket, handshakeFragment...) - if p.shouldEncrypt { - var err error - rawPacket, err = c.state.cipherSuite.Encrypt(p.record, rawPacket) - if err != nil { - return nil, err - } - } - - rawPackets = append(rawPackets, rawPacket) - } - - return rawPackets, nil -} - -func (c *Conn) fragmentHandshake(h *handshake.Handshake) ([][]byte, error) { - content, err := h.Message.Marshal() - if err != nil { - return nil, err - } - - fragmentedHandshakes := make([][]byte, 0) - - contentFragments := splitBytes(content, c.maximumTransmissionUnit) - if len(contentFragments) == 0 { - contentFragments = [][]byte{ - {}, - } - } - - offset := 0 - for _, contentFragment := range contentFragments { - contentFragmentLen := len(contentFragment) - - headerFragment := &handshake.Header{ - Type: h.Header.Type, - Length: h.Header.Length, - MessageSequence: h.Header.MessageSequence, - FragmentOffset: uint32(offset), - FragmentLength: uint32(contentFragmentLen), - } - - offset += contentFragmentLen - - fragmentedHandshake, err := headerFragment.Marshal() - if err != nil { - return nil, err - } - - fragmentedHandshake = append(fragmentedHandshake, contentFragment...) - fragmentedHandshakes = append(fragmentedHandshakes, fragmentedHandshake) - } - - return fragmentedHandshakes, nil -} - -var poolReadBuffer = sync.Pool{ //nolint:gochecknoglobals - New: func() interface{} { - b := make([]byte, inboundBufferSize) - return &b - }, -} - -func (c *Conn) readAndBuffer(ctx context.Context) error { - bufptr, ok := poolReadBuffer.Get().(*[]byte) - if !ok { - return errFailedToAccessPoolReadBuffer - } - defer poolReadBuffer.Put(bufptr) - - b := *bufptr - i, err := c.nextConn.ReadContext(ctx, b) - if err != nil { - return netError(err) - } - - pkts, err := recordlayer.UnpackDatagram(b[:i]) - if err != nil { - return err - } - - var hasHandshake bool - for _, p := range pkts { - hs, alert, err := c.handleIncomingPacket(ctx, p, true) - if alert != nil { - if alertErr := c.notify(ctx, alert.Level, alert.Description); alertErr != nil { - if err == nil { - err = alertErr - } - } - } - if hs { - hasHandshake = true - } - - var e *alertError - if errors.As(err, &e) { - if e.IsFatalOrCloseNotify() { - return e - } - } else if err != nil { - return e - } - } - if hasHandshake { - done := make(chan struct{}) - select { - case c.handshakeRecv <- done: - // If the other party may retransmit the flight, - // we should respond even if it not a new message. - <-done - case <-c.fsm.Done(): - } - } - return nil -} - -func (c *Conn) handleQueuedPackets(ctx context.Context) error { - pkts := c.encryptedPackets - c.encryptedPackets = nil - - for _, p := range pkts { - _, alert, err := c.handleIncomingPacket(ctx, p, false) // don't re-enqueue - if alert != nil { - if alertErr := c.notify(ctx, alert.Level, alert.Description); alertErr != nil { - if err == nil { - err = alertErr - } - } - } - var e *alertError - if errors.As(err, &e) { - if e.IsFatalOrCloseNotify() { - return e - } - } else if err != nil { - return e - } - } - return nil -} - -func (c *Conn) handleIncomingPacket(ctx context.Context, buf []byte, enqueue bool) (bool, *alert.Alert, error) { //nolint:gocognit - h := &recordlayer.Header{} - if err := h.Unmarshal(buf); err != nil { - // Decode error must be silently discarded - // [RFC6347 Section-4.1.2.7] - c.log.Debugf("discarded broken packet: %v", err) - return false, nil, nil - } - - // Validate epoch - remoteEpoch := c.state.getRemoteEpoch() - if h.Epoch > remoteEpoch { - if h.Epoch > remoteEpoch+1 { - c.log.Debugf("discarded future packet (epoch: %d, seq: %d)", - h.Epoch, h.SequenceNumber, - ) - return false, nil, nil - } - if enqueue { - c.log.Debug("received packet of next epoch, queuing packet") - c.encryptedPackets = append(c.encryptedPackets, buf) - } - return false, nil, nil - } - - // Anti-replay protection - for len(c.state.replayDetector) <= int(h.Epoch) { - c.state.replayDetector = append(c.state.replayDetector, - replaydetector.New(c.replayProtectionWindow, recordlayer.MaxSequenceNumber), - ) - } - markPacketAsValid, ok := c.state.replayDetector[int(h.Epoch)].Check(h.SequenceNumber) - if !ok { - c.log.Debugf("discarded duplicated packet (epoch: %d, seq: %d)", - h.Epoch, h.SequenceNumber, - ) - return false, nil, nil - } - - // Decrypt - if h.Epoch != 0 { - if c.state.cipherSuite == nil || !c.state.cipherSuite.IsInitialized() { - if enqueue { - c.encryptedPackets = append(c.encryptedPackets, buf) - c.log.Debug("handshake not finished, queuing packet") - } - return false, nil, nil - } - - var err error - buf, err = c.state.cipherSuite.Decrypt(buf) - if err != nil { - c.log.Debugf("%s: decrypt failed: %s", srvCliStr(c.state.isClient), err) - return false, nil, nil - } - } - - isHandshake, err := c.fragmentBuffer.push(append([]byte{}, buf...)) - if err != nil { - // Decode error must be silently discarded - // [RFC6347 Section-4.1.2.7] - c.log.Debugf("defragment failed: %s", err) - return false, nil, nil - } else if isHandshake { - markPacketAsValid() - for out, epoch := c.fragmentBuffer.pop(); out != nil; out, epoch = c.fragmentBuffer.pop() { - header := &handshake.Header{} - if err := header.Unmarshal(out); err != nil { - c.log.Debugf("%s: handshake parse failed: %s", srvCliStr(c.state.isClient), err) - continue - } - c.handshakeCache.push(out, epoch, header.MessageSequence, header.Type, !c.state.isClient) - } - - return true, nil, nil - } - - r := &recordlayer.RecordLayer{} - if err := r.Unmarshal(buf); err != nil { - return false, &alert.Alert{Level: alert.Fatal, Description: alert.DecodeError}, err - } - - switch content := r.Content.(type) { - case *alert.Alert: - c.log.Tracef("%s: <- %s", srvCliStr(c.state.isClient), content.String()) - var a *alert.Alert - if content.Description == alert.CloseNotify { - // Respond with a close_notify [RFC5246 Section 7.2.1] - a = &alert.Alert{Level: alert.Warning, Description: alert.CloseNotify} - } - markPacketAsValid() - return false, a, &alertError{content} - case *protocol.ChangeCipherSpec: - if c.state.cipherSuite == nil || !c.state.cipherSuite.IsInitialized() { - if enqueue { - c.encryptedPackets = append(c.encryptedPackets, buf) - c.log.Debugf("CipherSuite not initialized, queuing packet") - } - return false, nil, nil - } - - newRemoteEpoch := h.Epoch + 1 - c.log.Tracef("%s: <- ChangeCipherSpec (epoch: %d)", srvCliStr(c.state.isClient), newRemoteEpoch) - - if c.state.getRemoteEpoch()+1 == newRemoteEpoch { - c.setRemoteEpoch(newRemoteEpoch) - markPacketAsValid() - } - case *protocol.ApplicationData: - if h.Epoch == 0 { - return false, &alert.Alert{Level: alert.Fatal, Description: alert.UnexpectedMessage}, errApplicationDataEpochZero - } - - markPacketAsValid() - - select { - case c.decrypted <- content.Data: - case <-c.closed.Done(): - case <-ctx.Done(): - } - - default: - return false, &alert.Alert{Level: alert.Fatal, Description: alert.UnexpectedMessage}, fmt.Errorf("%w: %d", errUnhandledContextType, content.ContentType()) - } - return false, nil, nil -} - -func (c *Conn) recvHandshake() <-chan chan struct{} { - return c.handshakeRecv -} - -func (c *Conn) notify(ctx context.Context, level alert.Level, desc alert.Description) error { - if level == alert.Fatal && len(c.state.SessionID) > 0 { - // According to the RFC, we need to delete the stored session. - // https://datatracker.ietf.org/doc/html/rfc5246#section-7.2 - if ss := c.fsm.cfg.sessionStore; ss != nil { - c.log.Tracef("clean invalid session: %s", c.state.SessionID) - if err := ss.Del(c.sessionKey()); err != nil { - return err - } - } - } - return c.writePackets(ctx, []*packet{ - { - record: &recordlayer.RecordLayer{ - Header: recordlayer.Header{ - Epoch: c.state.getLocalEpoch(), - Version: protocol.Version1_2, - }, - Content: &alert.Alert{ - Level: level, - Description: desc, - }, - }, - shouldEncrypt: c.isHandshakeCompletedSuccessfully(), - }, - }) -} - -func (c *Conn) setHandshakeCompletedSuccessfully() { - c.handshakeCompletedSuccessfully.Store(struct{ bool }{true}) -} - -func (c *Conn) isHandshakeCompletedSuccessfully() bool { - boolean, _ := c.handshakeCompletedSuccessfully.Load().(struct{ bool }) - return boolean.bool -} - -func (c *Conn) handshake(ctx context.Context, cfg *handshakeConfig, initialFlight flightVal, initialState handshakeState) error { //nolint:gocognit - c.fsm = newHandshakeFSM(&c.state, c.handshakeCache, cfg, initialFlight) - - done := make(chan struct{}) - ctxRead, cancelRead := context.WithCancel(context.Background()) - c.cancelHandshakeReader = cancelRead - cfg.onFlightState = func(f flightVal, s handshakeState) { - if s == handshakeFinished && !c.isHandshakeCompletedSuccessfully() { - c.setHandshakeCompletedSuccessfully() - close(done) - } - } - - ctxHs, cancel := context.WithCancel(context.Background()) - c.cancelHandshaker = cancel - - firstErr := make(chan error, 1) - - c.handshakeLoopsFinished.Add(2) - - // Handshake routine should be live until close. - // The other party may request retransmission of the last flight to cope with packet drop. - go func() { - defer c.handshakeLoopsFinished.Done() - err := c.fsm.Run(ctxHs, c, initialState) - if !errors.Is(err, context.Canceled) { - select { - case firstErr <- err: - default: - } - } - }() - go func() { - defer func() { - // Escaping read loop. - // It's safe to close decrypted channnel now. - close(c.decrypted) - - // Force stop handshaker when the underlying connection is closed. - cancel() - }() - defer c.handshakeLoopsFinished.Done() - for { - if err := c.readAndBuffer(ctxRead); err != nil { - var e *alertError - if errors.As(err, &e) { - if !e.IsFatalOrCloseNotify() { - if c.isHandshakeCompletedSuccessfully() { - // Pass the error to Read() - select { - case c.decrypted <- err: - case <-c.closed.Done(): - case <-ctxRead.Done(): - } - } - continue // non-fatal alert must not stop read loop - } - } else { - switch { - case errors.Is(err, context.DeadlineExceeded), errors.Is(err, context.Canceled), errors.Is(err, io.EOF): - default: - if c.isHandshakeCompletedSuccessfully() { - // Keep read loop and pass the read error to Read() - select { - case c.decrypted <- err: - case <-c.closed.Done(): - case <-ctxRead.Done(): - } - continue // non-fatal alert must not stop read loop - } - } - } - - select { - case firstErr <- err: - default: - } - - if e != nil { - if e.IsFatalOrCloseNotify() { - _ = c.close(false) //nolint:contextcheck - } - } - if !c.isConnectionClosed() && errors.Is(err, context.Canceled) { - c.log.Trace("handshake timeouts - closing underline connection") - _ = c.close(false) //nolint:contextcheck - } - return - } - } - }() - - select { - case err := <-firstErr: - cancelRead() - cancel() - c.handshakeLoopsFinished.Wait() - return c.translateHandshakeCtxError(err) - case <-ctx.Done(): - cancelRead() - cancel() - c.handshakeLoopsFinished.Wait() - return c.translateHandshakeCtxError(ctx.Err()) - case <-done: - return nil - } -} - -func (c *Conn) translateHandshakeCtxError(err error) error { - if err == nil { - return nil - } - if errors.Is(err, context.Canceled) && c.isHandshakeCompletedSuccessfully() { - return nil - } - return &HandshakeError{Err: err} -} - -func (c *Conn) close(byUser bool) error { - c.cancelHandshaker() - c.cancelHandshakeReader() - - if c.isHandshakeCompletedSuccessfully() && byUser { - // Discard error from notify() to return non-error on the first user call of Close() - // even if the underlying connection is already closed. - _ = c.notify(context.Background(), alert.Warning, alert.CloseNotify) - } - - c.closeLock.Lock() - // Don't return ErrConnClosed at the first time of the call from user. - closedByUser := c.connectionClosedByUser - if byUser { - c.connectionClosedByUser = true - } - isClosed := c.isConnectionClosed() - c.closed.Close() - c.closeLock.Unlock() - - if closedByUser { - return ErrConnClosed - } - - if isClosed { - return nil - } - - return c.nextConn.Close() -} - -func (c *Conn) isConnectionClosed() bool { - select { - case <-c.closed.Done(): - return true - default: - return false - } -} - -func (c *Conn) setLocalEpoch(epoch uint16) { - c.state.localEpoch.Store(epoch) -} - -func (c *Conn) setRemoteEpoch(epoch uint16) { - c.state.remoteEpoch.Store(epoch) -} - -// LocalAddr implements net.Conn.LocalAddr -func (c *Conn) LocalAddr() net.Addr { - return c.nextConn.LocalAddr() -} - -// RemoteAddr implements net.Conn.RemoteAddr -func (c *Conn) RemoteAddr() net.Addr { - return c.nextConn.RemoteAddr() -} - -func (c *Conn) sessionKey() []byte { - if c.state.isClient { - // As ServerName can be like 0.example.com, it's better to add - // delimiter character which is not allowed to be in - // neither address or domain name. - return []byte(c.nextConn.RemoteAddr().String() + "_" + c.fsm.cfg.serverName) - } - return c.state.SessionID -} - -// SetDeadline implements net.Conn.SetDeadline -func (c *Conn) SetDeadline(t time.Time) error { - c.readDeadline.Set(t) - return c.SetWriteDeadline(t) -} - -// SetReadDeadline implements net.Conn.SetReadDeadline -func (c *Conn) SetReadDeadline(t time.Time) error { - c.readDeadline.Set(t) - // Read deadline is fully managed by this layer. - // Don't set read deadline to underlying connection. - return nil -} - -// SetWriteDeadline implements net.Conn.SetWriteDeadline -func (c *Conn) SetWriteDeadline(t time.Time) error { - c.writeDeadline.Set(t) - // Write deadline is also fully managed by this layer. - return nil -} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/errors.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/errors.go deleted file mode 100644 index 025d8645e..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/errors.go +++ /dev/null @@ -1,157 +0,0 @@ -// SPDX-FileCopyrightText: 2023 The Pion community -// SPDX-License-Identifier: MIT - -package dtls - -import ( - "context" - "errors" - "fmt" - "io" - "net" - "os" - - "github.com/pion/dtls/v2/pkg/protocol" - "github.com/pion/dtls/v2/pkg/protocol/alert" -) - -// Typed errors -var ( - ErrConnClosed = &FatalError{Err: errors.New("conn is closed")} //nolint:goerr113 - - errDeadlineExceeded = &TimeoutError{Err: fmt.Errorf("read/write timeout: %w", context.DeadlineExceeded)} - errInvalidContentType = &TemporaryError{Err: errors.New("invalid content type")} //nolint:goerr113 - - errBufferTooSmall = &TemporaryError{Err: errors.New("buffer is too small")} //nolint:goerr113 - errContextUnsupported = &TemporaryError{Err: errors.New("context is not supported for ExportKeyingMaterial")} //nolint:goerr113 - errHandshakeInProgress = &TemporaryError{Err: errors.New("handshake is in progress")} //nolint:goerr113 - errReservedExportKeyingMaterial = &TemporaryError{Err: errors.New("ExportKeyingMaterial can not be used with a reserved label")} //nolint:goerr113 - errApplicationDataEpochZero = &TemporaryError{Err: errors.New("ApplicationData with epoch of 0")} //nolint:goerr113 - errUnhandledContextType = &TemporaryError{Err: errors.New("unhandled contentType")} //nolint:goerr113 - - errCertificateVerifyNoCertificate = &FatalError{Err: errors.New("client sent certificate verify but we have no certificate to verify")} //nolint:goerr113 - errCipherSuiteNoIntersection = &FatalError{Err: errors.New("client+server do not support any shared cipher suites")} //nolint:goerr113 - errClientCertificateNotVerified = &FatalError{Err: errors.New("client sent certificate but did not verify it")} //nolint:goerr113 - errClientCertificateRequired = &FatalError{Err: errors.New("server required client verification, but got none")} //nolint:goerr113 - errClientNoMatchingSRTPProfile = &FatalError{Err: errors.New("server responded with SRTP Profile we do not support")} //nolint:goerr113 - errClientRequiredButNoServerEMS = &FatalError{Err: errors.New("client required Extended Master Secret extension, but server does not support it")} //nolint:goerr113 - errCookieMismatch = &FatalError{Err: errors.New("client+server cookie does not match")} //nolint:goerr113 - errIdentityNoPSK = &FatalError{Err: errors.New("PSK Identity Hint provided but PSK is nil")} //nolint:goerr113 - errInvalidCertificate = &FatalError{Err: errors.New("no certificate provided")} //nolint:goerr113 - errInvalidCipherSuite = &FatalError{Err: errors.New("invalid or unknown cipher suite")} //nolint:goerr113 - errInvalidECDSASignature = &FatalError{Err: errors.New("ECDSA signature contained zero or negative values")} //nolint:goerr113 - errInvalidPrivateKey = &FatalError{Err: errors.New("invalid private key type")} //nolint:goerr113 - errInvalidSignatureAlgorithm = &FatalError{Err: errors.New("invalid signature algorithm")} //nolint:goerr113 - errKeySignatureMismatch = &FatalError{Err: errors.New("expected and actual key signature do not match")} //nolint:goerr113 - errNilNextConn = &FatalError{Err: errors.New("Conn can not be created with a nil nextConn")} //nolint:goerr113 - errNoAvailableCipherSuites = &FatalError{Err: errors.New("connection can not be created, no CipherSuites satisfy this Config")} //nolint:goerr113 - errNoAvailablePSKCipherSuite = &FatalError{Err: errors.New("connection can not be created, pre-shared key present but no compatible CipherSuite")} //nolint:goerr113 - errNoAvailableCertificateCipherSuite = &FatalError{Err: errors.New("connection can not be created, certificate present but no compatible CipherSuite")} //nolint:goerr113 - errNoAvailableSignatureSchemes = &FatalError{Err: errors.New("connection can not be created, no SignatureScheme satisfy this Config")} //nolint:goerr113 - errNoCertificates = &FatalError{Err: errors.New("no certificates configured")} //nolint:goerr113 - errNoConfigProvided = &FatalError{Err: errors.New("no config provided")} //nolint:goerr113 - errNoSupportedEllipticCurves = &FatalError{Err: errors.New("client requested zero or more elliptic curves that are not supported by the server")} //nolint:goerr113 - errUnsupportedProtocolVersion = &FatalError{Err: errors.New("unsupported protocol version")} //nolint:goerr113 - errPSKAndIdentityMustBeSetForClient = &FatalError{Err: errors.New("PSK and PSK Identity Hint must both be set for client")} //nolint:goerr113 - errRequestedButNoSRTPExtension = &FatalError{Err: errors.New("SRTP support was requested but server did not respond with use_srtp extension")} //nolint:goerr113 - errServerNoMatchingSRTPProfile = &FatalError{Err: errors.New("client requested SRTP but we have no matching profiles")} //nolint:goerr113 - errServerRequiredButNoClientEMS = &FatalError{Err: errors.New("server requires the Extended Master Secret extension, but the client does not support it")} //nolint:goerr113 - errVerifyDataMismatch = &FatalError{Err: errors.New("expected and actual verify data does not match")} //nolint:goerr113 - errNotAcceptableCertificateChain = &FatalError{Err: errors.New("certificate chain is not signed by an acceptable CA")} //nolint:goerr113 - - errInvalidFlight = &InternalError{Err: errors.New("invalid flight number")} //nolint:goerr113 - errKeySignatureGenerateUnimplemented = &InternalError{Err: errors.New("unable to generate key signature, unimplemented")} //nolint:goerr113 - errKeySignatureVerifyUnimplemented = &InternalError{Err: errors.New("unable to verify key signature, unimplemented")} //nolint:goerr113 - errLengthMismatch = &InternalError{Err: errors.New("data length and declared length do not match")} //nolint:goerr113 - errSequenceNumberOverflow = &InternalError{Err: errors.New("sequence number overflow")} //nolint:goerr113 - errInvalidFSMTransition = &InternalError{Err: errors.New("invalid state machine transition")} //nolint:goerr113 - errFailedToAccessPoolReadBuffer = &InternalError{Err: errors.New("failed to access pool read buffer")} //nolint:goerr113 - errFragmentBufferOverflow = &InternalError{Err: errors.New("fragment buffer overflow")} //nolint:goerr113 -) - -// FatalError indicates that the DTLS connection is no longer available. -// It is mainly caused by wrong configuration of server or client. -type FatalError = protocol.FatalError - -// InternalError indicates and internal error caused by the implementation, and the DTLS connection is no longer available. -// It is mainly caused by bugs or tried to use unimplemented features. -type InternalError = protocol.InternalError - -// TemporaryError indicates that the DTLS connection is still available, but the request was failed temporary. -type TemporaryError = protocol.TemporaryError - -// TimeoutError indicates that the request was timed out. -type TimeoutError = protocol.TimeoutError - -// HandshakeError indicates that the handshake failed. -type HandshakeError = protocol.HandshakeError - -// errInvalidCipherSuite indicates an attempt at using an unsupported cipher suite. -type invalidCipherSuiteError struct { - id CipherSuiteID -} - -func (e *invalidCipherSuiteError) Error() string { - return fmt.Sprintf("CipherSuite with id(%d) is not valid", e.id) -} - -func (e *invalidCipherSuiteError) Is(err error) bool { - var other *invalidCipherSuiteError - if errors.As(err, &other) { - return e.id == other.id - } - return false -} - -// errAlert wraps DTLS alert notification as an error -type alertError struct { - *alert.Alert -} - -func (e *alertError) Error() string { - return fmt.Sprintf("alert: %s", e.Alert.String()) -} - -func (e *alertError) IsFatalOrCloseNotify() bool { - return e.Level == alert.Fatal || e.Description == alert.CloseNotify -} - -func (e *alertError) Is(err error) bool { - var other *alertError - if errors.As(err, &other) { - return e.Level == other.Level && e.Description == other.Description - } - return false -} - -// netError translates an error from underlying Conn to corresponding net.Error. -func netError(err error) error { - switch { - case errors.Is(err, io.EOF), errors.Is(err, context.Canceled), errors.Is(err, context.DeadlineExceeded): - // Return io.EOF and context errors as is. - return err - } - - var ( - ne net.Error - opError *net.OpError - se *os.SyscallError - ) - - if errors.As(err, &opError) { - if errors.As(opError, &se) { - if se.Timeout() { - return &TimeoutError{Err: err} - } - if isOpErrorTemporary(se) { - return &TemporaryError{Err: err} - } - } - } - - if errors.As(err, &ne) { - return err - } - - return &FatalError{Err: err} -} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_128_ccm.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_128_ccm.go deleted file mode 100644 index 8367b2c6d..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_128_ccm.go +++ /dev/null @@ -1,14 +0,0 @@ -// SPDX-FileCopyrightText: 2023 The Pion community -// SPDX-License-Identifier: MIT - -package ciphersuite - -import ( - "github.com/pion/dtls/v2/pkg/crypto/ciphersuite" - "github.com/pion/dtls/v2/pkg/crypto/clientcertificate" -) - -// NewTLSEcdheEcdsaWithAes128Ccm constructs a TLS_ECDHE_ECDSA_WITH_AES_128_CCM Cipher -func NewTLSEcdheEcdsaWithAes128Ccm() *Aes128Ccm { - return newAes128Ccm(clientcertificate.ECDSASign, TLS_ECDHE_ECDSA_WITH_AES_128_CCM, false, ciphersuite.CCMTagLength, KeyExchangeAlgorithmEcdhe, true) -} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_128_ccm8.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_128_ccm8.go deleted file mode 100644 index 11b687327..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_128_ccm8.go +++ /dev/null @@ -1,14 +0,0 @@ -// SPDX-FileCopyrightText: 2023 The Pion community -// SPDX-License-Identifier: MIT - -package ciphersuite - -import ( - "github.com/pion/dtls/v2/pkg/crypto/ciphersuite" - "github.com/pion/dtls/v2/pkg/crypto/clientcertificate" -) - -// NewTLSEcdheEcdsaWithAes128Ccm8 creates a new TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 CipherSuite -func NewTLSEcdheEcdsaWithAes128Ccm8() *Aes128Ccm { - return newAes128Ccm(clientcertificate.ECDSASign, TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8, false, ciphersuite.CCMTagLength8, KeyExchangeAlgorithmEcdhe, true) -} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/internal/ciphersuite/tls_psk_with_aes_128_ccm.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/internal/ciphersuite/tls_psk_with_aes_128_ccm.go deleted file mode 100644 index 1ded09b88..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/internal/ciphersuite/tls_psk_with_aes_128_ccm.go +++ /dev/null @@ -1,14 +0,0 @@ -// SPDX-FileCopyrightText: 2023 The Pion community -// SPDX-License-Identifier: MIT - -package ciphersuite - -import ( - "github.com/pion/dtls/v2/pkg/crypto/ciphersuite" - "github.com/pion/dtls/v2/pkg/crypto/clientcertificate" -) - -// NewTLSPskWithAes128Ccm returns the TLS_PSK_WITH_AES_128_CCM CipherSuite -func NewTLSPskWithAes128Ccm() *Aes128Ccm { - return newAes128Ccm(clientcertificate.Type(0), TLS_PSK_WITH_AES_128_CCM, true, ciphersuite.CCMTagLength, KeyExchangeAlgorithmPsk, false) -} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/internal/ciphersuite/tls_psk_with_aes_128_ccm8.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/internal/ciphersuite/tls_psk_with_aes_128_ccm8.go deleted file mode 100644 index 478197074..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/internal/ciphersuite/tls_psk_with_aes_128_ccm8.go +++ /dev/null @@ -1,14 +0,0 @@ -// SPDX-FileCopyrightText: 2023 The Pion community -// SPDX-License-Identifier: MIT - -package ciphersuite - -import ( - "github.com/pion/dtls/v2/pkg/crypto/ciphersuite" - "github.com/pion/dtls/v2/pkg/crypto/clientcertificate" -) - -// NewTLSPskWithAes128Ccm8 returns the TLS_PSK_WITH_AES_128_CCM_8 CipherSuite -func NewTLSPskWithAes128Ccm8() *Aes128Ccm { - return newAes128Ccm(clientcertificate.Type(0), TLS_PSK_WITH_AES_128_CCM_8, true, ciphersuite.CCMTagLength8, KeyExchangeAlgorithmPsk, false) -} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/internal/ciphersuite/tls_psk_with_aes_256_ccm8.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/internal/ciphersuite/tls_psk_with_aes_256_ccm8.go deleted file mode 100644 index 32d503018..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/internal/ciphersuite/tls_psk_with_aes_256_ccm8.go +++ /dev/null @@ -1,14 +0,0 @@ -// SPDX-FileCopyrightText: 2023 The Pion community -// SPDX-License-Identifier: MIT - -package ciphersuite - -import ( - "github.com/pion/dtls/v2/pkg/crypto/ciphersuite" - "github.com/pion/dtls/v2/pkg/crypto/clientcertificate" -) - -// NewTLSPskWithAes256Ccm8 returns the TLS_PSK_WITH_AES_256_CCM_8 CipherSuite -func NewTLSPskWithAes256Ccm8() *Aes256Ccm { - return newAes256Ccm(clientcertificate.Type(0), TLS_PSK_WITH_AES_256_CCM_8, true, ciphersuite.CCMTagLength8, KeyExchangeAlgorithmPsk, false) -} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/crypto/ciphersuite/cbc.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/crypto/ciphersuite/cbc.go deleted file mode 100644 index 460fb1437..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/crypto/ciphersuite/cbc.go +++ /dev/null @@ -1,177 +0,0 @@ -// SPDX-FileCopyrightText: 2023 The Pion community -// SPDX-License-Identifier: MIT - -package ciphersuite - -import ( //nolint:gci - "crypto/aes" - "crypto/cipher" - "crypto/hmac" - "crypto/rand" - "encoding/binary" - "hash" - - "github.com/pion/dtls/v2/internal/util" - "github.com/pion/dtls/v2/pkg/crypto/prf" - "github.com/pion/dtls/v2/pkg/protocol" - "github.com/pion/dtls/v2/pkg/protocol/recordlayer" -) - -// block ciphers using cipher block chaining. -type cbcMode interface { - cipher.BlockMode - SetIV([]byte) -} - -// CBC Provides an API to Encrypt/Decrypt DTLS 1.2 Packets -type CBC struct { - writeCBC, readCBC cbcMode - writeMac, readMac []byte - h prf.HashFunc -} - -// NewCBC creates a DTLS CBC Cipher -func NewCBC(localKey, localWriteIV, localMac, remoteKey, remoteWriteIV, remoteMac []byte, h prf.HashFunc) (*CBC, error) { - writeBlock, err := aes.NewCipher(localKey) - if err != nil { - return nil, err - } - - readBlock, err := aes.NewCipher(remoteKey) - if err != nil { - return nil, err - } - - writeCBC, ok := cipher.NewCBCEncrypter(writeBlock, localWriteIV).(cbcMode) - if !ok { - return nil, errFailedToCast - } - - readCBC, ok := cipher.NewCBCDecrypter(readBlock, remoteWriteIV).(cbcMode) - if !ok { - return nil, errFailedToCast - } - - return &CBC{ - writeCBC: writeCBC, - writeMac: localMac, - - readCBC: readCBC, - readMac: remoteMac, - h: h, - }, nil -} - -// Encrypt encrypt a DTLS RecordLayer message -func (c *CBC) Encrypt(pkt *recordlayer.RecordLayer, raw []byte) ([]byte, error) { - payload := raw[recordlayer.HeaderSize:] - raw = raw[:recordlayer.HeaderSize] - blockSize := c.writeCBC.BlockSize() - - // Generate + Append MAC - h := pkt.Header - - MAC, err := c.hmac(h.Epoch, h.SequenceNumber, h.ContentType, h.Version, payload, c.writeMac, c.h) - if err != nil { - return nil, err - } - payload = append(payload, MAC...) - - // Generate + Append padding - padding := make([]byte, blockSize-len(payload)%blockSize) - paddingLen := len(padding) - for i := 0; i < paddingLen; i++ { - padding[i] = byte(paddingLen - 1) - } - payload = append(payload, padding...) - - // Generate IV - iv := make([]byte, blockSize) - if _, err := rand.Read(iv); err != nil { - return nil, err - } - - // Set IV + Encrypt + Prepend IV - c.writeCBC.SetIV(iv) - c.writeCBC.CryptBlocks(payload, payload) - payload = append(iv, payload...) - - // Prepend unencrypte header with encrypted payload - raw = append(raw, payload...) - - // Update recordLayer size to include IV+MAC+Padding - binary.BigEndian.PutUint16(raw[recordlayer.HeaderSize-2:], uint16(len(raw)-recordlayer.HeaderSize)) - - return raw, nil -} - -// Decrypt decrypts a DTLS RecordLayer message -func (c *CBC) Decrypt(in []byte) ([]byte, error) { - body := in[recordlayer.HeaderSize:] - blockSize := c.readCBC.BlockSize() - mac := c.h() - - var h recordlayer.Header - err := h.Unmarshal(in) - switch { - case err != nil: - return nil, err - case h.ContentType == protocol.ContentTypeChangeCipherSpec: - // Nothing to encrypt with ChangeCipherSpec - return in, nil - case len(body)%blockSize != 0 || len(body) < blockSize+util.Max(mac.Size()+1, blockSize): - return nil, errNotEnoughRoomForNonce - } - - // Set + remove per record IV - c.readCBC.SetIV(body[:blockSize]) - body = body[blockSize:] - - // Decrypt - c.readCBC.CryptBlocks(body, body) - - // Padding+MAC needs to be checked in constant time - // Otherwise we reveal information about the level of correctness - paddingLen, paddingGood := examinePadding(body) - if paddingGood != 255 { - return nil, errInvalidMAC - } - - macSize := mac.Size() - if len(body) < macSize { - return nil, errInvalidMAC - } - - dataEnd := len(body) - macSize - paddingLen - - expectedMAC := body[dataEnd : dataEnd+macSize] - actualMAC, err := c.hmac(h.Epoch, h.SequenceNumber, h.ContentType, h.Version, body[:dataEnd], c.readMac, c.h) - - // Compute Local MAC and compare - if err != nil || !hmac.Equal(actualMAC, expectedMAC) { - return nil, errInvalidMAC - } - - return append(in[:recordlayer.HeaderSize], body[:dataEnd]...), nil -} - -func (c *CBC) hmac(epoch uint16, sequenceNumber uint64, contentType protocol.ContentType, protocolVersion protocol.Version, payload []byte, key []byte, hf func() hash.Hash) ([]byte, error) { - h := hmac.New(hf, key) - - msg := make([]byte, 13) - - binary.BigEndian.PutUint16(msg, epoch) - util.PutBigEndianUint48(msg[2:], sequenceNumber) - msg[8] = byte(contentType) - msg[9] = protocolVersion.Major - msg[10] = protocolVersion.Minor - binary.BigEndian.PutUint16(msg[11:], uint16(len(payload))) - - if _, err := h.Write(msg); err != nil { - return nil, err - } else if _, err := h.Write(payload); err != nil { - return nil, err - } - - return h.Sum(nil), nil -} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/extension/errors.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/extension/errors.go deleted file mode 100644 index c5e954ce5..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/extension/errors.go +++ /dev/null @@ -1,20 +0,0 @@ -// SPDX-FileCopyrightText: 2023 The Pion community -// SPDX-License-Identifier: MIT - -package extension - -import ( - "errors" - - "github.com/pion/dtls/v2/pkg/protocol" -) - -var ( - // ErrALPNInvalidFormat is raised when the ALPN format is invalid - ErrALPNInvalidFormat = &protocol.FatalError{Err: errors.New("invalid alpn format")} //nolint:goerr113 - errALPNNoAppProto = &protocol.FatalError{Err: errors.New("no application protocol")} //nolint:goerr113 - errBufferTooSmall = &protocol.TemporaryError{Err: errors.New("buffer is too small")} //nolint:goerr113 - errInvalidExtensionType = &protocol.FatalError{Err: errors.New("invalid extension type")} //nolint:goerr113 - errInvalidSNIFormat = &protocol.FatalError{Err: errors.New("invalid server name format")} //nolint:goerr113 - errLengthMismatch = &protocol.InternalError{Err: errors.New("data length and declared length do not match")} //nolint:goerr113 -) diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/handshake/errors.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/handshake/errors.go deleted file mode 100644 index 1354300c4..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/handshake/errors.go +++ /dev/null @@ -1,28 +0,0 @@ -// SPDX-FileCopyrightText: 2023 The Pion community -// SPDX-License-Identifier: MIT - -package handshake - -import ( - "errors" - - "github.com/pion/dtls/v2/pkg/protocol" -) - -// Typed errors -var ( - errUnableToMarshalFragmented = &protocol.InternalError{Err: errors.New("unable to marshal fragmented handshakes")} //nolint:goerr113 - errHandshakeMessageUnset = &protocol.InternalError{Err: errors.New("handshake message unset, unable to marshal")} //nolint:goerr113 - errBufferTooSmall = &protocol.TemporaryError{Err: errors.New("buffer is too small")} //nolint:goerr113 - errLengthMismatch = &protocol.InternalError{Err: errors.New("data length and declared length do not match")} //nolint:goerr113 - errInvalidClientKeyExchange = &protocol.FatalError{Err: errors.New("unable to determine if ClientKeyExchange is a public key or PSK Identity")} //nolint:goerr113 - errInvalidHashAlgorithm = &protocol.FatalError{Err: errors.New("invalid hash algorithm")} //nolint:goerr113 - errInvalidSignatureAlgorithm = &protocol.FatalError{Err: errors.New("invalid signature algorithm")} //nolint:goerr113 - errCookieTooLong = &protocol.FatalError{Err: errors.New("cookie must not be longer then 255 bytes")} //nolint:goerr113 - errInvalidEllipticCurveType = &protocol.FatalError{Err: errors.New("invalid or unknown elliptic curve type")} //nolint:goerr113 - errInvalidNamedCurve = &protocol.FatalError{Err: errors.New("invalid named curve")} //nolint:goerr113 - errCipherSuiteUnset = &protocol.FatalError{Err: errors.New("server hello can not be created without a cipher suite")} //nolint:goerr113 - errCompressionMethodUnset = &protocol.FatalError{Err: errors.New("server hello can not be created without a compression method")} //nolint:goerr113 - errInvalidCompressionMethod = &protocol.FatalError{Err: errors.New("invalid or unknown compression method")} //nolint:goerr113 - errNotImplemented = &protocol.InternalError{Err: errors.New("feature has not been implemented yet")} //nolint:goerr113 -) diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/recordlayer/errors.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/recordlayer/errors.go deleted file mode 100644 index cd4cb60a5..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/recordlayer/errors.go +++ /dev/null @@ -1,19 +0,0 @@ -// SPDX-FileCopyrightText: 2023 The Pion community -// SPDX-License-Identifier: MIT - -// Package recordlayer implements the TLS Record Layer https://tools.ietf.org/html/rfc5246#section-6 -package recordlayer - -import ( - "errors" - - "github.com/pion/dtls/v2/pkg/protocol" -) - -var ( - errBufferTooSmall = &protocol.TemporaryError{Err: errors.New("buffer is too small")} //nolint:goerr113 - errInvalidPacketLength = &protocol.TemporaryError{Err: errors.New("packet length and declared length do not match")} //nolint:goerr113 - errSequenceNumberOverflow = &protocol.InternalError{Err: errors.New("sequence number overflow")} //nolint:goerr113 - errUnsupportedProtocolVersion = &protocol.FatalError{Err: errors.New("unsupported protocol version")} //nolint:goerr113 - errInvalidContentType = &protocol.TemporaryError{Err: errors.New("invalid content type")} //nolint:goerr113 -) diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/.editorconfig b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/.editorconfig similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/.editorconfig rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/.editorconfig diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/.gitignore b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/.gitignore similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/.gitignore rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/.gitignore diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/.golangci.yml b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/.golangci.yml new file mode 100644 index 000000000..88cb4fbf9 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/.golangci.yml @@ -0,0 +1,138 @@ +# SPDX-FileCopyrightText: 2023 The Pion community +# SPDX-License-Identifier: MIT + +run: + timeout: 5m + +linters-settings: + govet: + enable: + - shadow + misspell: + locale: US + exhaustive: + default-signifies-exhaustive: true + gomodguard: + blocked: + modules: + - github.com/pkg/errors: + recommendations: + - errors + forbidigo: + forbid: + - ^fmt.Print(f|ln)?$ + - ^log.(Panic|Fatal|Print)(f|ln)?$ + - ^os.Exit$ + - ^panic$ + - ^print(ln)?$ + varnamelen: + max-distance: 12 + min-name-length: 2 + ignore-type-assert-ok: true + ignore-map-index-ok: true + ignore-chan-recv-ok: true + ignore-decls: + - i int + - n int + - w io.Writer + - r io.Reader + - b []byte + +linters: + enable: + - asciicheck # Simple linter to check that your code does not contain non-ASCII identifiers + - bidichk # Checks for dangerous unicode character sequences + - bodyclose # checks whether HTTP response body is closed successfully + - containedctx # containedctx is a linter that detects struct contained context.Context field + - contextcheck # check the function whether use a non-inherited context + - cyclop # checks function and package cyclomatic complexity + - decorder # check declaration order and count of types, constants, variables and functions + - dogsled # Checks assignments with too many blank identifiers (e.g. x, _, _, _, := f()) + - dupl # Tool for code clone detection + - durationcheck # check for two durations multiplied together + - err113 # Golang linter to check the errors handling expressions + - errcheck # Errcheck is a program for checking for unchecked errors in go programs. These unchecked errors can be critical bugs in some cases + - errchkjson # Checks types passed to the json encoding functions. Reports unsupported types and optionally reports occations, where the check for the returned error can be omitted. + - errname # Checks that sentinel errors are prefixed with the `Err` and error types are suffixed with the `Error`. + - errorlint # errorlint is a linter for that can be used to find code that will cause problems with the error wrapping scheme introduced in Go 1.13. + - exhaustive # check exhaustiveness of enum switch statements + - exportloopref # checks for pointers to enclosing loop variables + - forbidigo # Forbids identifiers + - forcetypeassert # finds forced type assertions + - gci # Gci control golang package import order and make it always deterministic. + - gochecknoglobals # Checks that no globals are present in Go code + - gocognit # Computes and checks the cognitive complexity of functions + - goconst # Finds repeated strings that could be replaced by a constant + - gocritic # The most opinionated Go source code linter + - gocyclo # Computes and checks the cyclomatic complexity of functions + - godot # Check if comments end in a period + - godox # Tool for detection of FIXME, TODO and other comment keywords + - gofmt # Gofmt checks whether code was gofmt-ed. By default this tool runs with -s option to check for code simplification + - gofumpt # Gofumpt checks whether code was gofumpt-ed. + - goheader # Checks is file header matches to pattern + - goimports # Goimports does everything that gofmt does. Additionally it checks unused imports + - gomoddirectives # Manage the use of 'replace', 'retract', and 'excludes' directives in go.mod. + - goprintffuncname # Checks that printf-like functions are named with `f` at the end + - gosec # Inspects source code for security problems + - gosimple # Linter for Go source code that specializes in simplifying a code + - govet # Vet examines Go source code and reports suspicious constructs, such as Printf calls whose arguments do not align with the format string + - grouper # An analyzer to analyze expression groups. + - importas # Enforces consistent import aliases + - ineffassign # Detects when assignments to existing variables are not used + - lll # Reports long lines + - maintidx # maintidx measures the maintainability index of each function. + - makezero # Finds slice declarations with non-zero initial length + - misspell # Finds commonly misspelled English words in comments + - nakedret # Finds naked returns in functions greater than a specified function length + - nestif # Reports deeply nested if statements + - nilerr # Finds the code that returns nil even if it checks that the error is not nil. + - nilnil # Checks that there is no simultaneous return of `nil` error and an invalid value. + - nlreturn # nlreturn checks for a new line before return and branch statements to increase code clarity + - noctx # noctx finds sending http request without context.Context + - predeclared # find code that shadows one of Go's predeclared identifiers + - revive # golint replacement, finds style mistakes + - staticcheck # Staticcheck is a go vet on steroids, applying a ton of static analysis checks + - stylecheck # Stylecheck is a replacement for golint + - tagliatelle # Checks the struct tags. + - tenv # tenv is analyzer that detects using os.Setenv instead of t.Setenv since Go1.17 + - thelper # thelper detects golang test helpers without t.Helper() call and checks the consistency of test helpers + - typecheck # Like the front-end of a Go compiler, parses and type-checks Go code + - unconvert # Remove unnecessary type conversions + - unparam # Reports unused function parameters + - unused # Checks Go code for unused constants, variables, functions and types + - varnamelen # checks that the length of a variable's name matches its scope + - wastedassign # wastedassign finds wasted assignment statements + - whitespace # Tool for detection of leading and trailing whitespace + disable: + - depguard # Go linter that checks if package imports are in a list of acceptable packages + - funlen # Tool for detection of long functions + - gochecknoinits # Checks that no init functions are present in Go code + - gomodguard # Allow and block list linter for direct Go module dependencies. This is different from depguard where there are different block types for example version constraints and module recommendations. + - interfacebloat # A linter that checks length of interface. + - ireturn # Accept Interfaces, Return Concrete Types + - mnd # An analyzer to detect magic numbers + - nolintlint # Reports ill-formed or insufficient nolint directives + - paralleltest # paralleltest detects missing usage of t.Parallel() method in your Go test + - prealloc # Finds slice declarations that could potentially be preallocated + - promlinter # Check Prometheus metrics naming via promlint + - rowserrcheck # checks whether Err of rows is checked successfully + - sqlclosecheck # Checks that sql.Rows and sql.Stmt are closed. + - testpackage # linter that makes you use a separate _test package + - tparallel # tparallel detects inappropriate usage of t.Parallel() method in your Go test codes + - wrapcheck # Checks that errors returned from external packages are wrapped + - wsl # Whitespace Linter - Forces you to use empty lines! + +issues: + exclude-use-default: false + exclude-dirs-use-default: false + exclude-rules: + # Allow complex tests and examples, better to be self contained + - path: (examples|main\.go|_test\.go) + linters: + - forbidigo + - gocognit + + # Allow forbidden identifiers in CLI commands + - path: cmd + linters: + - forbidigo diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/.goreleaser.yml b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/.goreleaser.yml similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/.goreleaser.yml rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/.goreleaser.yml diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/LICENSE b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/LICENSE similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/LICENSE rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/LICENSE diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/README.md b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/README.md similarity index 95% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/README.md rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/README.md index 0c0659593..fa00c95d8 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/README.md +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/README.md @@ -10,9 +10,9 @@ Slack Widget
GitHub Workflow Status - Go Reference + Go Reference Coverage Status - Go Report Card + Go Report Card License: MIT


@@ -145,7 +145,7 @@ We are always looking to support **your projects**. Please reach out if you have If you need commercial support or don't want to use public methods you can contact us at [team@pion.ly](mailto:team@pion.ly) ### Contributing -Check out the [contributing wiki](https://github.com/pion/webrtc/wiki/Contributing) to join the group of amazing people making this project possible: [AUTHORS.txt](./AUTHORS.txt) +Check out the [contributing wiki](https://github.com/pion/webrtc/wiki/Contributing) to join the group of amazing people making this project possible ### License MIT License - see [LICENSE](LICENSE) for full text diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/certificate.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/certificate.go similarity index 90% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/certificate.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/certificate.go index 519fc875f..524b8e063 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/certificate.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/certificate.go @@ -9,6 +9,8 @@ import ( "crypto/x509" "fmt" "strings" + + "github.com/pion/dtls/v3/pkg/protocol/handshake" ) // ClientHelloInfo contains information from a ClientHello message in order to @@ -22,6 +24,9 @@ type ClientHelloInfo struct { // CipherSuites lists the CipherSuites supported by the client (e.g. // TLS_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256). CipherSuites []CipherSuiteID + + // RandomBytes stores the client hello random bytes + RandomBytes [handshake.RandomBytesLength]byte } // CertificateRequestInfo contains information from a server's @@ -38,7 +43,8 @@ type CertificateRequestInfo struct { // SupportsCertificate returns nil if the provided certificate is supported by // the server that sent the CertificateRequest. Otherwise, it returns an error // describing the reason for the incompatibility. -// NOTE: original src: https://github.com/golang/go/blob/29b9a328d268d53833d2cc063d1d8b4bf6852675/src/crypto/tls/common.go#L1273 +// NOTE: original src: +// https://github.com/golang/go/blob/29b9a328d268d53833d2cc063d1d8b4bf6852675/src/crypto/tls/common.go#L1273 func (cri *CertificateRequestInfo) SupportsCertificate(c *tls.Certificate) error { if len(cri.AcceptableCAs) == 0 { return nil @@ -61,6 +67,7 @@ func (cri *CertificateRequestInfo) SupportsCertificate(c *tls.Certificate) error } } } + return errNotAcceptableCertificateChain } @@ -86,6 +93,7 @@ func (c *handshakeConfig) setNameToCertificateLocked() { c.nameToCertificate = nameToCertificate } +//nolint:cyclop func (c *handshakeConfig) getCertificate(clientHelloInfo *ClientHelloInfo) (*tls.Certificate, error) { c.mu.Lock() defer c.mu.Unlock() @@ -136,7 +144,8 @@ func (c *handshakeConfig) getCertificate(clientHelloInfo *ClientHelloInfo) (*tls return &c.localCertificates[0], nil } -// NOTE: original src: https://github.com/golang/go/blob/29b9a328d268d53833d2cc063d1d8b4bf6852675/src/crypto/tls/handshake_client.go#L974 +// NOTE: original src: +// https://github.com/golang/go/blob/29b9a328d268d53833d2cc063d1d8b4bf6852675/src/crypto/tls/handshake_client.go#L974 func (c *handshakeConfig) getClientCertificate(cri *CertificateRequestInfo) (*tls.Certificate, error) { c.mu.Lock() defer c.mu.Unlock() @@ -149,6 +158,7 @@ func (c *handshakeConfig) getClientCertificate(cri *CertificateRequestInfo) (*tl if err := cri.SupportsCertificate(&chain); err != nil { continue } + return &chain, nil } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/cipher_suite.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/cipher_suite.go similarity index 78% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/cipher_suite.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/cipher_suite.go index 7a5bb4a58..2b29bf238 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/cipher_suite.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/cipher_suite.go @@ -4,6 +4,7 @@ package dtls import ( + "crypto" "crypto/ecdsa" "crypto/ed25519" "crypto/rsa" @@ -11,54 +12,68 @@ import ( "fmt" "hash" - "github.com/pion/dtls/v2/internal/ciphersuite" - "github.com/pion/dtls/v2/pkg/crypto/clientcertificate" - "github.com/pion/dtls/v2/pkg/protocol/recordlayer" + "github.com/pion/dtls/v3/internal/ciphersuite" + "github.com/pion/dtls/v3/pkg/crypto/clientcertificate" + "github.com/pion/dtls/v3/pkg/protocol/recordlayer" ) -// CipherSuiteID is an ID for our supported CipherSuites +// CipherSuiteID is an ID for our supported CipherSuites. type CipherSuiteID = ciphersuite.ID -// Supported Cipher Suites +// Supported Cipher Suites. const ( // AES-128-CCM - TLS_ECDHE_ECDSA_WITH_AES_128_CCM CipherSuiteID = ciphersuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM //nolint:revive,stylecheck - TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 CipherSuiteID = ciphersuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 //nolint:revive,stylecheck + //nolint:revive,stylecheck + TLS_ECDHE_ECDSA_WITH_AES_128_CCM CipherSuiteID = ciphersuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM + //nolint:revive,stylecheck + TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 CipherSuiteID = ciphersuite.TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 // AES-128-GCM-SHA256 - TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 CipherSuiteID = ciphersuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 //nolint:revive,stylecheck - TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 CipherSuiteID = ciphersuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 //nolint:revive,stylecheck + //nolint:revive,stylecheck + TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 CipherSuiteID = ciphersuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + //nolint:revive,stylecheck + TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 CipherSuiteID = ciphersuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 - TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 CipherSuiteID = ciphersuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 //nolint:revive,stylecheck - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 CipherSuiteID = ciphersuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 //nolint:revive,stylecheck + //nolint:revive,stylecheck + TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 CipherSuiteID = ciphersuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 + //nolint:revive,stylecheck + TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 CipherSuiteID = ciphersuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 // AES-256-CBC-SHA - TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA CipherSuiteID = ciphersuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA //nolint:revive,stylecheck - TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA CipherSuiteID = ciphersuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA //nolint:revive,stylecheck + //nolint:revive,stylecheck + TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA CipherSuiteID = ciphersuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA + //nolint:revive,stylecheck + TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA CipherSuiteID = ciphersuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA - TLS_PSK_WITH_AES_128_CCM CipherSuiteID = ciphersuite.TLS_PSK_WITH_AES_128_CCM //nolint:revive,stylecheck - TLS_PSK_WITH_AES_128_CCM_8 CipherSuiteID = ciphersuite.TLS_PSK_WITH_AES_128_CCM_8 //nolint:revive,stylecheck - TLS_PSK_WITH_AES_256_CCM_8 CipherSuiteID = ciphersuite.TLS_PSK_WITH_AES_256_CCM_8 //nolint:revive,stylecheck - TLS_PSK_WITH_AES_128_GCM_SHA256 CipherSuiteID = ciphersuite.TLS_PSK_WITH_AES_128_GCM_SHA256 //nolint:revive,stylecheck - TLS_PSK_WITH_AES_128_CBC_SHA256 CipherSuiteID = ciphersuite.TLS_PSK_WITH_AES_128_CBC_SHA256 //nolint:revive,stylecheck + //nolint:revive,stylecheck + TLS_PSK_WITH_AES_128_CCM CipherSuiteID = ciphersuite.TLS_PSK_WITH_AES_128_CCM + //nolint:revive,stylecheck + TLS_PSK_WITH_AES_128_CCM_8 CipherSuiteID = ciphersuite.TLS_PSK_WITH_AES_128_CCM_8 + //nolint:revive,stylecheck + TLS_PSK_WITH_AES_256_CCM_8 CipherSuiteID = ciphersuite.TLS_PSK_WITH_AES_256_CCM_8 + //nolint:revive,stylecheck + TLS_PSK_WITH_AES_128_GCM_SHA256 CipherSuiteID = ciphersuite.TLS_PSK_WITH_AES_128_GCM_SHA256 + //nolint:revive,stylecheck + TLS_PSK_WITH_AES_128_CBC_SHA256 CipherSuiteID = ciphersuite.TLS_PSK_WITH_AES_128_CBC_SHA256 - TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 CipherSuiteID = ciphersuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 //nolint:revive,stylecheck + //nolint:revive,stylecheck + TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 CipherSuiteID = ciphersuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 ) -// CipherSuiteAuthenticationType controls what authentication method is using during the handshake for a CipherSuite +// CipherSuiteAuthenticationType controls what authentication method is using during the handshake for a CipherSuite. type CipherSuiteAuthenticationType = ciphersuite.AuthenticationType -// AuthenticationType Enums +// AuthenticationType Enums. const ( CipherSuiteAuthenticationTypeCertificate CipherSuiteAuthenticationType = ciphersuite.AuthenticationTypeCertificate CipherSuiteAuthenticationTypePreSharedKey CipherSuiteAuthenticationType = ciphersuite.AuthenticationTypePreSharedKey CipherSuiteAuthenticationTypeAnonymous CipherSuiteAuthenticationType = ciphersuite.AuthenticationTypeAnonymous ) -// CipherSuiteKeyExchangeAlgorithm controls what exchange algorithm is using during the handshake for a CipherSuite +// CipherSuiteKeyExchangeAlgorithm controls what exchange algorithm is using during the handshake for a CipherSuite. type CipherSuiteKeyExchangeAlgorithm = ciphersuite.KeyExchangeAlgorithm -// CipherSuiteKeyExchangeAlgorithm Bitmask +// CipherSuiteKeyExchangeAlgorithm Bitmask. const ( CipherSuiteKeyExchangeAlgorithmNone CipherSuiteKeyExchangeAlgorithm = ciphersuite.KeyExchangeAlgorithmNone CipherSuiteKeyExchangeAlgorithmPsk CipherSuiteKeyExchangeAlgorithm = ciphersuite.KeyExchangeAlgorithmPsk @@ -67,7 +82,7 @@ const ( var _ = allCipherSuites() // Necessary until this function isn't only used by Go 1.14 -// CipherSuite is an interface that all DTLS CipherSuites must satisfy +// CipherSuite is an interface that all DTLS CipherSuites must satisfy. type CipherSuite interface { // String of CipherSuite, only used for logging String() string @@ -95,7 +110,7 @@ type CipherSuite interface { Init(masterSecret, clientRandom, serverRandom []byte, isClient bool) error IsInitialized() bool Encrypt(pkt *recordlayer.RecordLayer, raw []byte) ([]byte, error) - Decrypt(in []byte) ([]byte, error) + Decrypt(h recordlayer.Header, in []byte) ([]byte, error) } // CipherSuiteName provides the same functionality as tls.CipherSuiteName @@ -108,13 +123,14 @@ func CipherSuiteName(id CipherSuiteID) string { if suite != nil { return suite.String() } + return fmt.Sprintf("0x%04X", uint16(id)) } // Taken from https://www.iana.org/assignments/tls-parameters/tls-parameters.xml // A cipherSuite is a specific combination of key agreement, cipher and MAC // function. -func cipherSuiteForID(id CipherSuiteID, customCiphers func() []CipherSuite) CipherSuite { +func cipherSuiteForID(id CipherSuiteID, customCiphers func() []CipherSuite) CipherSuite { //nolint:cyclop switch id { //nolint:exhaustive case TLS_ECDHE_ECDSA_WITH_AES_128_CCM: return ciphersuite.NewTLSEcdheEcdsaWithAes128Ccm() @@ -157,7 +173,7 @@ func cipherSuiteForID(id CipherSuiteID, customCiphers func() []CipherSuite) Ciph return nil } -// CipherSuites we support in order of preference +// CipherSuites we support in order of preference. func defaultCipherSuites() []CipherSuite { return []CipherSuite{ &ciphersuite.TLSEcdheEcdsaWithAes128GcmSha256{}, @@ -191,10 +207,16 @@ func cipherSuiteIDs(cipherSuites []CipherSuite) []uint16 { for _, c := range cipherSuites { rtrn = append(rtrn, uint16(c.ID())) } + return rtrn } -func parseCipherSuites(userSelectedSuites []CipherSuiteID, customCipherSuites func() []CipherSuite, includeCertificateSuites, includePSKSuites bool) ([]CipherSuite, error) { +//nolint:cyclop +func parseCipherSuites( + userSelectedSuites []CipherSuiteID, + customCipherSuites func() []CipherSuite, + includeCertificateSuites, includePSKSuites bool, +) ([]CipherSuite, error) { cipherSuitesForIDs := func(ids []CipherSuiteID) ([]CipherSuite, error) { cipherSuites := []CipherSuite{} for _, id := range ids { @@ -204,6 +226,7 @@ func parseCipherSuites(userSelectedSuites []CipherSuiteID, customCipherSuites fu } cipherSuites = append(cipherSuites, c) } + return cipherSuites, nil } @@ -258,11 +281,16 @@ func filterCipherSuitesForCertificate(cert *tls.Certificate, cipherSuites []Ciph if cert == nil || cert.PrivateKey == nil { return cipherSuites } + signer, ok := cert.PrivateKey.(crypto.Signer) + if !ok { + return cipherSuites + } + var certType clientcertificate.Type - switch cert.PrivateKey.(type) { - case ed25519.PrivateKey, *ecdsa.PrivateKey: + switch signer.Public().(type) { + case ed25519.PublicKey, *ecdsa.PublicKey: certType = clientcertificate.ECDSASign - case *rsa.PrivateKey: + case *rsa.PublicKey: certType = clientcertificate.RSASign } @@ -272,5 +300,6 @@ func filterCipherSuitesForCertificate(cert *tls.Certificate, cipherSuites []Ciph filtered = append(filtered, c) } } + return filtered } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/cipher_suite_go114.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/cipher_suite_go114.go similarity index 96% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/cipher_suite_go114.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/cipher_suite_go114.go index fd46d7bd9..e7a324147 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/cipher_suite_go114.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/cipher_suite_go114.go @@ -11,10 +11,10 @@ import ( ) // VersionDTLS12 is the DTLS version in the same style as -// VersionTLSXX from crypto/tls +// VersionTLSXX from crypto/tls. const VersionDTLS12 = 0xfefd -// Convert from our cipherSuite interface to a tls.CipherSuite struct +// Convert from our cipherSuite interface to a tls.CipherSuite struct. func toTLSCipherSuite(c CipherSuite) *tls.CipherSuite { return &tls.CipherSuite{ ID: uint16(c.ID()), @@ -33,6 +33,7 @@ func CipherSuites() []*tls.CipherSuite { for i, c := range suites { res[i] = toTLSCipherSuite(c) } + return res } @@ -40,5 +41,6 @@ func CipherSuites() []*tls.CipherSuite { // this package and which have security issues. func InsecureCipherSuites() []*tls.CipherSuite { var res []*tls.CipherSuite + return res } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/codecov.yml b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/codecov.yml similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/codecov.yml rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/codecov.yml diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/compression_method.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/compression_method.go similarity index 83% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/compression_method.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/compression_method.go index 7e44de009..49b11c718 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/compression_method.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/compression_method.go @@ -3,7 +3,7 @@ package dtls -import "github.com/pion/dtls/v2/pkg/protocol" +import "github.com/pion/dtls/v3/pkg/protocol" func defaultCompressionMethods() []*protocol.CompressionMethod { return []*protocol.CompressionMethod{ diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/config.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/config.go similarity index 68% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/config.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/config.go index fbc3ee247..722335139 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/config.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/config.go @@ -4,16 +4,18 @@ package dtls import ( - "context" + "crypto" "crypto/ecdsa" "crypto/ed25519" "crypto/rsa" "crypto/tls" "crypto/x509" "io" + "net" "time" - "github.com/pion/dtls/v2/pkg/crypto/elliptic" + "github.com/pion/dtls/v3/pkg/crypto/elliptic" + "github.com/pion/dtls/v3/pkg/protocol/handshake" "github.com/pion/logging" ) @@ -44,6 +46,10 @@ type Config struct { // Servers will assert that clients send one of these profiles and will respond as needed SRTPProtectionProfiles []SRTPProtectionProfile + // SRTPMasterKeyIdentifier value (if any) is sent via the use_srtp + // extension for Clients and Servers + SRTPMasterKeyIdentifier []byte + // ClientAuth determines the server's policy for // TLS Client Authentication. The default is NoClientCert. ClientAuth ClientAuthType @@ -56,6 +62,10 @@ type Config struct { // defaults to time.Second FlightInterval time.Duration + // DisableRetransmitBackoff can be used to the disable the backoff feature + // when sending outbound messages as specified in RFC 4347 4.2.4.1 + DisableRetransmitBackoff bool + // PSK sets the pre-shared key used by this DTLS connection // If PSK is non-nil only PSK CipherSuites will be used PSK PSKCallback @@ -112,15 +122,6 @@ type Config struct { LoggerFactory logging.LoggerFactory - // ConnectContextMaker is a function to make a context used in Dial(), - // Client(), Server(), and Accept(). If nil, the default ConnectContextMaker - // is used. It can be implemented as following. - // - // func ConnectContextMaker() (context.Context, func()) { - // return context.WithTimeout(context.Background(), 30*time.Second) - // } - ConnectContextMaker func() (context.Context, func()) - // MTU is the length at which handshake messages will be fragmented to // fit within the maximum transmission unit (default is 1200 bytes) MTU int @@ -176,17 +177,53 @@ type Config struct { // skip hello verify phase and receive ServerHello after initial ClientHello. // This have implication on DoS attack resistance. InsecureSkipVerifyHello bool -} -func defaultConnectContextMaker() (context.Context, func()) { - return context.WithTimeout(context.Background(), 30*time.Second) -} + // ConnectionIDGenerator generates connection identifiers that should be + // sent by the remote party if it supports the DTLS Connection Identifier + // extension, as determined during the handshake. Generated connection + // identifiers must always have the same length. Returning a zero-length + // connection identifier indicates that the local party supports sending + // connection identifiers but does not require the remote party to send + // them. A nil ConnectionIDGenerator indicates that connection identifiers + // are not supported. + // https://datatracker.ietf.org/doc/html/rfc9146 + ConnectionIDGenerator func() []byte -func (c *Config) connectContextMaker() (context.Context, func()) { - if c.ConnectContextMaker == nil { - return defaultConnectContextMaker() - } - return c.ConnectContextMaker() + // PaddingLengthGenerator generates the number of padding bytes used to + // inflate ciphertext size in order to obscure content size from observers. + // The length of the content is passed to the generator such that both + // deterministic and random padding schemes can be applied while not + // exceeding maximum record size. + // If no PaddingLengthGenerator is specified, padding will not be applied. + // https://datatracker.ietf.org/doc/html/rfc9146#section-4 + PaddingLengthGenerator func(uint) uint + + // HelloRandomBytesGenerator generates custom client hello random bytes. + HelloRandomBytesGenerator func() [handshake.RandomBytesLength]byte + + // Handshake hooks: hooks can be used for testing invalid messages, + // mimicking other implementations or randomizing fields, which is valuable + // for applications that need censorship-resistance by making + // fingerprinting more difficult. + + // ClientHelloMessageHook, if not nil, is called when a Client Hello message is sent + // from a client. The returned handshake message replaces the original message. + ClientHelloMessageHook func(handshake.MessageClientHello) handshake.Message + + // ServerHelloMessageHook, if not nil, is called when a Server Hello message is sent + // from a server. The returned handshake message replaces the original message. + ServerHelloMessageHook func(handshake.MessageServerHello) handshake.Message + + // CertificateRequestMessageHook, if not nil, is called when a Certificate Request + // message is sent from a server. The returned handshake message replaces the original message. + CertificateRequestMessageHook func(handshake.MessageCertificateRequest) handshake.Message + + // OnConnectionAttempt is fired Whenever a connection attempt is made, + // the server or application can call this callback function. + // The callback function can then implement logic to handle the connection attempt, such as logging the attempt, + // checking against a list of blocked IPs, or counting the attempts to prevent brute force attacks. + // If the callback function returns an error, the connection attempt will be aborted. + OnConnectionAttempt func(net.Addr) error } func (c *Config) includeCertificateSuites() bool { @@ -198,14 +235,14 @@ const defaultMTU = 1200 // bytes var defaultCurves = []elliptic.Curve{elliptic.X25519, elliptic.P256, elliptic.P384} //nolint:gochecknoglobals // PSKCallback is called once we have the remote's PSKIdentityHint. -// If the remote provided none it will be nil +// If the remote provided none it will be nil. type PSKCallback func([]byte) ([]byte, error) // ClientAuthType declares the policy the server will follow for // TLS Client Authentication. type ClientAuthType int -// ClientAuthType enums +// ClientAuthType enums. const ( NoClientCert ClientAuthType = iota RequestClientCert @@ -215,17 +252,17 @@ const ( ) // ExtendedMasterSecretType declares the policy the client and server -// will follow for the Extended Master Secret extension +// will follow for the Extended Master Secret extension. type ExtendedMasterSecretType int -// ExtendedMasterSecretType enums +// ExtendedMasterSecretType enums. const ( RequestExtendedMasterSecret ExtendedMasterSecretType = iota RequireExtendedMasterSecret DisableExtendedMasterSecret ) -func validateConfig(config *Config) error { +func validateConfig(config *Config) error { //nolint:cyclop switch { case config == nil: return errNoConfigProvided @@ -238,16 +275,23 @@ func validateConfig(config *Config) error { return errInvalidCertificate } if cert.PrivateKey != nil { - switch cert.PrivateKey.(type) { - case ed25519.PrivateKey: - case *ecdsa.PrivateKey: - case *rsa.PrivateKey: + signer, ok := cert.PrivateKey.(crypto.Signer) + if !ok { + return errInvalidPrivateKey + } + switch signer.Public().(type) { + case ed25519.PublicKey: + case *ecdsa.PublicKey: + case *rsa.PublicKey: default: return errInvalidPrivateKey } } } - _, err := parseCipherSuites(config.CipherSuites, config.CustomCipherSuites, config.includeCertificateSuites(), config.PSK != nil) + _, err := parseCipherSuites( + config.CipherSuites, config.CustomCipherSuites, config.includeCertificateSuites(), config.PSK != nil, + ) + return err } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/conn.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/conn.go new file mode 100644 index 000000000..c7cd9a3cb --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/conn.go @@ -0,0 +1,1330 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + +package dtls + +import ( + "bytes" + "context" + "errors" + "fmt" + "io" + "net" + "sync" + "sync/atomic" + "time" + + "github.com/pion/dtls/v3/internal/closer" + "github.com/pion/dtls/v3/pkg/crypto/elliptic" + "github.com/pion/dtls/v3/pkg/crypto/signaturehash" + "github.com/pion/dtls/v3/pkg/protocol" + "github.com/pion/dtls/v3/pkg/protocol/alert" + "github.com/pion/dtls/v3/pkg/protocol/handshake" + "github.com/pion/dtls/v3/pkg/protocol/recordlayer" + "github.com/pion/logging" + "github.com/pion/transport/v3/deadline" + "github.com/pion/transport/v3/netctx" + "github.com/pion/transport/v3/replaydetector" +) + +const ( + initialTickerInterval = time.Second + cookieLength = 20 + sessionLength = 32 + defaultNamedCurve = elliptic.X25519 + inboundBufferSize = 8192 + // Default replay protection window is specified by RFC 6347 Section 4.1.2.6. + defaultReplayProtectionWindow = 64 + // maxAppDataPacketQueueSize is the maximum number of app data packets we will. + // enqueue before the handshake is completed. + maxAppDataPacketQueueSize = 100 +) + +func invalidKeyingLabels() map[string]bool { + return map[string]bool{ + "client finished": true, + "server finished": true, + "master secret": true, + "key expansion": true, + } +} + +type addrPkt struct { + rAddr net.Addr + data []byte +} + +type recvHandshakeState struct { + done chan struct{} + isRetransmit bool +} + +// Conn represents a DTLS connection. +type Conn struct { + lock sync.RWMutex // Internal lock (must not be public) + nextConn netctx.PacketConn // Embedded Conn, typically a udpconn we read/write from + fragmentBuffer *fragmentBuffer // out-of-order and missing fragment handling + handshakeCache *handshakeCache // caching of handshake messages for verifyData generation + decrypted chan interface{} // Decrypted Application Data or error, pull by calling `Read` + rAddr net.Addr + state State // Internal state + + maximumTransmissionUnit int + paddingLengthGenerator func(uint) uint + + handshakeCompletedSuccessfully atomic.Value + handshakeMutex sync.Mutex + handshakeDone chan struct{} + + encryptedPackets []addrPkt + + connectionClosedByUser bool + closeLock sync.Mutex + closed *closer.Closer + + readDeadline *deadline.Deadline + writeDeadline *deadline.Deadline + + log logging.LeveledLogger + + reading chan struct{} + handshakeRecv chan recvHandshakeState + cancelHandshaker func() + cancelHandshakeReader func() + + fsm *handshakeFSM + + replayProtectionWindow uint + + handshakeConfig *handshakeConfig +} + +//nolint:cyclop +func createConn( + nextConn net.PacketConn, + rAddr net.Addr, + config *Config, + isClient bool, + resumeState *State, +) (*Conn, error) { + if err := validateConfig(config); err != nil { + return nil, err + } + + if nextConn == nil { + return nil, errNilNextConn + } + + loggerFactory := config.LoggerFactory + if loggerFactory == nil { + loggerFactory = logging.NewDefaultLoggerFactory() + } + + logger := loggerFactory.NewLogger("dtls") + + mtu := config.MTU + if mtu <= 0 { + mtu = defaultMTU + } + + replayProtectionWindow := config.ReplayProtectionWindow + if replayProtectionWindow <= 0 { + replayProtectionWindow = defaultReplayProtectionWindow + } + + paddingLengthGenerator := config.PaddingLengthGenerator + if paddingLengthGenerator == nil { + paddingLengthGenerator = func(uint) uint { return 0 } + } + + cipherSuites, err := parseCipherSuites( + config.CipherSuites, + config.CustomCipherSuites, + config.includeCertificateSuites(), + config.PSK != nil, + ) + if err != nil { + return nil, err + } + + signatureSchemes, err := signaturehash.ParseSignatureSchemes(config.SignatureSchemes, config.InsecureHashes) + if err != nil { + return nil, err + } + + workerInterval := initialTickerInterval + if config.FlightInterval != 0 { + workerInterval = config.FlightInterval + } + + serverName := config.ServerName + // Do not allow the use of an IP address literal as an SNI value. + // See RFC 6066, Section 3. + if net.ParseIP(serverName) != nil { + serverName = "" + } + + curves := config.EllipticCurves + if len(curves) == 0 { + curves = defaultCurves + } + + handshakeConfig := &handshakeConfig{ + localPSKCallback: config.PSK, + localPSKIdentityHint: config.PSKIdentityHint, + localCipherSuites: cipherSuites, + localSignatureSchemes: signatureSchemes, + extendedMasterSecret: config.ExtendedMasterSecret, + localSRTPProtectionProfiles: config.SRTPProtectionProfiles, + localSRTPMasterKeyIdentifier: config.SRTPMasterKeyIdentifier, + serverName: serverName, + supportedProtocols: config.SupportedProtocols, + clientAuth: config.ClientAuth, + localCertificates: config.Certificates, + insecureSkipVerify: config.InsecureSkipVerify, + verifyPeerCertificate: config.VerifyPeerCertificate, + verifyConnection: config.VerifyConnection, + rootCAs: config.RootCAs, + clientCAs: config.ClientCAs, + customCipherSuites: config.CustomCipherSuites, + initialRetransmitInterval: workerInterval, + disableRetransmitBackoff: config.DisableRetransmitBackoff, + log: logger, + initialEpoch: 0, + keyLogWriter: config.KeyLogWriter, + sessionStore: config.SessionStore, + ellipticCurves: curves, + localGetCertificate: config.GetCertificate, + localGetClientCertificate: config.GetClientCertificate, + insecureSkipHelloVerify: config.InsecureSkipVerifyHello, + connectionIDGenerator: config.ConnectionIDGenerator, + helloRandomBytesGenerator: config.HelloRandomBytesGenerator, + clientHelloMessageHook: config.ClientHelloMessageHook, + serverHelloMessageHook: config.ServerHelloMessageHook, + certificateRequestMessageHook: config.CertificateRequestMessageHook, + resumeState: resumeState, + } + + conn := &Conn{ + rAddr: rAddr, + nextConn: netctx.NewPacketConn(nextConn), + handshakeConfig: handshakeConfig, + fragmentBuffer: newFragmentBuffer(), + handshakeCache: newHandshakeCache(), + maximumTransmissionUnit: mtu, + paddingLengthGenerator: paddingLengthGenerator, + + decrypted: make(chan interface{}, 1), + log: logger, + + readDeadline: deadline.New(), + writeDeadline: deadline.New(), + + reading: make(chan struct{}, 1), + handshakeRecv: make(chan recvHandshakeState), + closed: closer.NewCloser(), + cancelHandshaker: func() {}, + cancelHandshakeReader: func() {}, + + replayProtectionWindow: uint(replayProtectionWindow), //nolint:gosec // G115 + + state: State{ + isClient: isClient, + }, + } + + conn.setRemoteEpoch(0) + conn.setLocalEpoch(0) + + return conn, nil +} + +// Handshake runs the client or server DTLS handshake +// protocol if it has not yet been run. +// +// Most uses of this package need not call Handshake explicitly: the +// first [Conn.Read] or [Conn.Write] will call it automatically. +// +// For control over canceling or setting a timeout on a handshake, use +// [Conn.HandshakeContext]. +func (c *Conn) Handshake() error { + return c.HandshakeContext(context.Background()) +} + +// HandshakeContext runs the client or server DTLS handshake +// protocol if it has not yet been run. +// +// The provided Context must be non-nil. If the context is canceled before +// the handshake is complete, the handshake is interrupted and an error is returned. +// Once the handshake has completed, cancellation of the context will not affect the +// connection. +// +// Most uses of this package need not call HandshakeContext explicitly: the +// first [Conn.Read] or [Conn.Write] will call it automatically. +func (c *Conn) HandshakeContext(ctx context.Context) error { + c.handshakeMutex.Lock() + defer c.handshakeMutex.Unlock() + + if c.isHandshakeCompletedSuccessfully() { + return nil + } + + handshakeDone := make(chan struct{}) + defer close(handshakeDone) + c.closeLock.Lock() + c.handshakeDone = handshakeDone + c.closeLock.Unlock() + + // rfc5246#section-7.4.3 + // In addition, the hash and signature algorithms MUST be compatible + // with the key in the server's end-entity certificate. + if !c.state.isClient { + cert, err := c.handshakeConfig.getCertificate(&ClientHelloInfo{}) + if err != nil && !errors.Is(err, errNoCertificates) { + return err + } + c.handshakeConfig.localCipherSuites = filterCipherSuitesForCertificate(cert, c.handshakeConfig.localCipherSuites) + } + + var initialFlight flightVal + var initialFSMState handshakeState + + if c.handshakeConfig.resumeState != nil { //nolint:nestif + if c.state.isClient { + initialFlight = flight5 + } else { + initialFlight = flight6 + } + initialFSMState = handshakeFinished + + c.state = *c.handshakeConfig.resumeState + } else { + if c.state.isClient { + initialFlight = flight1 + } else { + initialFlight = flight0 + } + initialFSMState = handshakePreparing + } + // Do handshake + if err := c.handshake(ctx, c.handshakeConfig, initialFlight, initialFSMState); err != nil { + return err + } + + c.log.Trace("Handshake Completed") + + return nil +} + +// Dial connects to the given network address and establishes a DTLS connection on top. +func Dial(network string, rAddr *net.UDPAddr, config *Config) (*Conn, error) { + // net.ListenUDP is used rather than net.DialUDP as the latter prevents the + // use of net.PacketConn.WriteTo. + // https://github.com/golang/go/blob/ce5e37ec21442c6eb13a43e68ca20129102ebac0/src/net/udpsock_posix.go#L115 + pConn, err := net.ListenUDP(network, nil) + if err != nil { + return nil, err + } + + return Client(pConn, rAddr, config) +} + +// Client establishes a DTLS connection over an existing connection. +func Client(conn net.PacketConn, rAddr net.Addr, config *Config) (*Conn, error) { + switch { + case config == nil: + return nil, errNoConfigProvided + case config.PSK != nil && config.PSKIdentityHint == nil: + return nil, errPSKAndIdentityMustBeSetForClient + } + + return createConn(conn, rAddr, config, true, nil) +} + +// Server listens for incoming DTLS connections. +func Server(conn net.PacketConn, rAddr net.Addr, config *Config) (*Conn, error) { + if config == nil { + return nil, errNoConfigProvided + } + if config.OnConnectionAttempt != nil { + if err := config.OnConnectionAttempt(rAddr); err != nil { + return nil, err + } + } + + return createConn(conn, rAddr, config, false, nil) +} + +// Read reads data from the connection. +func (c *Conn) Read(buff []byte) (n int, err error) { //nolint:cyclop + if err := c.Handshake(); err != nil { + return 0, err + } + + select { + case <-c.readDeadline.Done(): + return 0, errDeadlineExceeded + default: + } + + for { + select { + case <-c.readDeadline.Done(): + return 0, errDeadlineExceeded + case out, ok := <-c.decrypted: + if !ok { + return 0, io.EOF + } + switch val := out.(type) { + case ([]byte): + if len(buff) < len(val) { + return 0, errBufferTooSmall + } + copy(buff, val) + + return len(val), nil + case (error): + return 0, val + } + } + } +} + +// Write writes len(payload) bytes from payload to the DTLS connection. +func (c *Conn) Write(payload []byte) (int, error) { + if c.isConnectionClosed() { + return 0, ErrConnClosed + } + + select { + case <-c.writeDeadline.Done(): + return 0, errDeadlineExceeded + default: + } + + if err := c.Handshake(); err != nil { + return 0, err + } + + return len(payload), c.writePackets(c.writeDeadline, []*packet{ + { + record: &recordlayer.RecordLayer{ + Header: recordlayer.Header{ + Epoch: c.state.getLocalEpoch(), + Version: protocol.Version1_2, + }, + Content: &protocol.ApplicationData{ + Data: payload, + }, + }, + shouldWrapCID: len(c.state.remoteConnectionID) > 0, + shouldEncrypt: true, + }, + }) +} + +// Close closes the connection. +func (c *Conn) Close() error { + err := c.close(true) //nolint:contextcheck + c.closeLock.Lock() + handshakeDone := c.handshakeDone + c.closeLock.Unlock() + if handshakeDone != nil { + <-handshakeDone + } + + return err +} + +// ConnectionState returns basic DTLS details about the connection. +// Note that this replaced the `Export` function of v1. +func (c *Conn) ConnectionState() (State, bool) { + c.lock.RLock() + defer c.lock.RUnlock() + stateClone, err := c.state.clone() + if err != nil { + return State{}, false + } + + return *stateClone, true +} + +// SelectedSRTPProtectionProfile returns the selected SRTPProtectionProfile. +func (c *Conn) SelectedSRTPProtectionProfile() (SRTPProtectionProfile, bool) { + profile := c.state.getSRTPProtectionProfile() + if profile == 0 { + return 0, false + } + + return profile, true +} + +// RemoteSRTPMasterKeyIdentifier returns the MasterKeyIdentifier value from the use_srtp. +func (c *Conn) RemoteSRTPMasterKeyIdentifier() ([]byte, bool) { + if profile := c.state.getSRTPProtectionProfile(); profile == 0 { + return nil, false + } + + return c.state.remoteSRTPMasterKeyIdentifier, true +} + +func (c *Conn) writePackets(ctx context.Context, pkts []*packet) error { + c.lock.Lock() + defer c.lock.Unlock() + + var rawPackets [][]byte + + for _, pkt := range pkts { + if dtlsHandshake, ok := pkt.record.Content.(*handshake.Handshake); ok { + handshakeRaw, err := pkt.record.Marshal() + if err != nil { + return err + } + + c.log.Tracef("[handshake:%v] -> %s (epoch: %d, seq: %d)", + srvCliStr(c.state.isClient), dtlsHandshake.Header.Type.String(), + pkt.record.Header.Epoch, dtlsHandshake.Header.MessageSequence) + + c.handshakeCache.push( + handshakeRaw[recordlayer.FixedHeaderSize:], + pkt.record.Header.Epoch, + dtlsHandshake.Header.MessageSequence, + dtlsHandshake.Header.Type, + c.state.isClient, + ) + + rawHandshakePackets, err := c.processHandshakePacket(pkt, dtlsHandshake) + if err != nil { + return err + } + rawPackets = append(rawPackets, rawHandshakePackets...) + } else { + rawPacket, err := c.processPacket(pkt) + if err != nil { + return err + } + rawPackets = append(rawPackets, rawPacket) + } + } + if len(rawPackets) == 0 { + return nil + } + compactedRawPackets := c.compactRawPackets(rawPackets) + + for _, compactedRawPackets := range compactedRawPackets { + if _, err := c.nextConn.WriteToContext(ctx, compactedRawPackets, c.rAddr); err != nil { + return netError(err) + } + } + + return nil +} + +func (c *Conn) compactRawPackets(rawPackets [][]byte) [][]byte { + // avoid a useless copy in the common case + if len(rawPackets) == 1 { + return rawPackets + } + + combinedRawPackets := make([][]byte, 0) + currentCombinedRawPacket := make([]byte, 0) + + for _, rawPacket := range rawPackets { + if len(currentCombinedRawPacket) > 0 && len(currentCombinedRawPacket)+len(rawPacket) >= c.maximumTransmissionUnit { + combinedRawPackets = append(combinedRawPackets, currentCombinedRawPacket) + currentCombinedRawPacket = []byte{} + } + currentCombinedRawPacket = append(currentCombinedRawPacket, rawPacket...) + } + + combinedRawPackets = append(combinedRawPackets, currentCombinedRawPacket) + + return combinedRawPackets +} + +func (c *Conn) processPacket(pkt *packet) ([]byte, error) { //nolint:cyclop + epoch := pkt.record.Header.Epoch + for len(c.state.localSequenceNumber) <= int(epoch) { + c.state.localSequenceNumber = append(c.state.localSequenceNumber, uint64(0)) + } + seq := atomic.AddUint64(&c.state.localSequenceNumber[epoch], 1) - 1 + if seq > recordlayer.MaxSequenceNumber { + // RFC 6347 Section 4.1.0 + // The implementation must either abandon an association or rehandshake + // prior to allowing the sequence number to wrap. + return nil, errSequenceNumberOverflow + } + pkt.record.Header.SequenceNumber = seq + + var rawPacket []byte + if pkt.shouldWrapCID { //nolint:nestif + // Record must be marshaled to populate fields used in inner plaintext. + if _, err := pkt.record.Marshal(); err != nil { + return nil, err + } + content, err := pkt.record.Content.Marshal() + if err != nil { + return nil, err + } + inner := &recordlayer.InnerPlaintext{ + Content: content, + RealType: pkt.record.Header.ContentType, + } + rawInner, err := inner.Marshal() //nolint:govet + if err != nil { + return nil, err + } + cidHeader := &recordlayer.Header{ + Version: pkt.record.Header.Version, + ContentType: protocol.ContentTypeConnectionID, + Epoch: pkt.record.Header.Epoch, + ContentLen: uint16(len(rawInner)), //nolint:gosec //G115 + ConnectionID: c.state.remoteConnectionID, + SequenceNumber: pkt.record.Header.SequenceNumber, + } + rawPacket, err = cidHeader.Marshal() + if err != nil { + return nil, err + } + pkt.record.Header = *cidHeader + rawPacket = append(rawPacket, rawInner...) + } else { + var err error + rawPacket, err = pkt.record.Marshal() + if err != nil { + return nil, err + } + } + + if pkt.shouldEncrypt { + var err error + rawPacket, err = c.state.cipherSuite.Encrypt(pkt.record, rawPacket) + if err != nil { + return nil, err + } + } + + return rawPacket, nil +} + +//nolint:cyclop +func (c *Conn) processHandshakePacket(pkt *packet, dtlsHandshake *handshake.Handshake) ([][]byte, error) { + rawPackets := make([][]byte, 0) + + handshakeFragments, err := c.fragmentHandshake(dtlsHandshake) + if err != nil { + return nil, err + } + epoch := pkt.record.Header.Epoch + for len(c.state.localSequenceNumber) <= int(epoch) { + c.state.localSequenceNumber = append(c.state.localSequenceNumber, uint64(0)) + } + + for _, handshakeFragment := range handshakeFragments { + seq := atomic.AddUint64(&c.state.localSequenceNumber[epoch], 1) - 1 + if seq > recordlayer.MaxSequenceNumber { + return nil, errSequenceNumberOverflow + } + + var rawPacket []byte + if pkt.shouldWrapCID { + inner := &recordlayer.InnerPlaintext{ + Content: handshakeFragment, + RealType: protocol.ContentTypeHandshake, + Zeros: c.paddingLengthGenerator(uint(len(handshakeFragment))), + } + rawInner, err := inner.Marshal() //nolint:govet + if err != nil { + return nil, err + } + cidHeader := &recordlayer.Header{ + Version: pkt.record.Header.Version, + ContentType: protocol.ContentTypeConnectionID, + Epoch: pkt.record.Header.Epoch, + ContentLen: uint16(len(rawInner)), //nolint:gosec //G115 + ConnectionID: c.state.remoteConnectionID, + SequenceNumber: pkt.record.Header.SequenceNumber, + } + rawPacket, err = cidHeader.Marshal() + if err != nil { + return nil, err + } + pkt.record.Header = *cidHeader + rawPacket = append(rawPacket, rawInner...) + } else { + recordlayerHeader := &recordlayer.Header{ + Version: pkt.record.Header.Version, + ContentType: pkt.record.Header.ContentType, + ContentLen: uint16(len(handshakeFragment)), //nolint:gosec // G115 + Epoch: pkt.record.Header.Epoch, + SequenceNumber: seq, + } + + rawPacket, err = recordlayerHeader.Marshal() + if err != nil { + return nil, err + } + + pkt.record.Header = *recordlayerHeader + rawPacket = append(rawPacket, handshakeFragment...) + } + + if pkt.shouldEncrypt { + var err error + rawPacket, err = c.state.cipherSuite.Encrypt(pkt.record, rawPacket) + if err != nil { + return nil, err + } + } + + rawPackets = append(rawPackets, rawPacket) + } + + return rawPackets, nil +} + +func (c *Conn) fragmentHandshake(dtlsHandshake *handshake.Handshake) ([][]byte, error) { + content, err := dtlsHandshake.Message.Marshal() + if err != nil { + return nil, err + } + + fragmentedHandshakes := make([][]byte, 0) + + contentFragments := splitBytes(content, c.maximumTransmissionUnit) + if len(contentFragments) == 0 { + contentFragments = [][]byte{ + {}, + } + } + + offset := 0 + for _, contentFragment := range contentFragments { + contentFragmentLen := len(contentFragment) + + headerFragment := &handshake.Header{ + Type: dtlsHandshake.Header.Type, + Length: dtlsHandshake.Header.Length, + MessageSequence: dtlsHandshake.Header.MessageSequence, + FragmentOffset: uint32(offset), //nolint:gosec // G115 + FragmentLength: uint32(contentFragmentLen), //nolint:gosec // G115 + } + + offset += contentFragmentLen + + fragmentedHandshake, err := headerFragment.Marshal() + if err != nil { + return nil, err + } + + fragmentedHandshake = append(fragmentedHandshake, contentFragment...) + fragmentedHandshakes = append(fragmentedHandshakes, fragmentedHandshake) + } + + return fragmentedHandshakes, nil +} + +var poolReadBuffer = sync.Pool{ //nolint:gochecknoglobals + New: func() interface{} { + b := make([]byte, inboundBufferSize) + + return &b + }, +} + +func (c *Conn) readAndBuffer(ctx context.Context) error { //nolint:cyclop + bufptr, ok := poolReadBuffer.Get().(*[]byte) + if !ok { + return errFailedToAccessPoolReadBuffer + } + defer poolReadBuffer.Put(bufptr) + + b := *bufptr + i, rAddr, err := c.nextConn.ReadFromContext(ctx, b) + if err != nil { + return netError(err) + } + + pkts, err := recordlayer.ContentAwareUnpackDatagram(b[:i], len(c.state.getLocalConnectionID())) + if err != nil { + return err + } + + var hasHandshake, isRetransmit bool + for _, p := range pkts { + hs, rtx, alert, err := c.handleIncomingPacket(ctx, p, rAddr, true) + if alert != nil { + if alertErr := c.notify(ctx, alert.Level, alert.Description); alertErr != nil { + if err == nil { + err = alertErr + } + } + } + + var e *alertError + if errors.As(err, &e) && e.IsFatalOrCloseNotify() { + return e + } + if err != nil { + return err + } + if hs { + hasHandshake = true + } + if rtx { + isRetransmit = true + } + } + if hasHandshake { + s := recvHandshakeState{ + done: make(chan struct{}), + isRetransmit: isRetransmit, + } + select { + case c.handshakeRecv <- s: + // If the other party may retransmit the flight, + // we should respond even if it not a new message. + <-s.done + case <-c.fsm.Done(): + } + } + + return nil +} + +func (c *Conn) handleQueuedPackets(ctx context.Context) error { + pkts := c.encryptedPackets + c.encryptedPackets = nil + + for _, p := range pkts { + _, _, alert, err := c.handleIncomingPacket(ctx, p.data, p.rAddr, false) // don't re-enqueue + if alert != nil { + if alertErr := c.notify(ctx, alert.Level, alert.Description); alertErr != nil { + if err == nil { + err = alertErr + } + } + } + var e *alertError + if errors.As(err, &e) && e.IsFatalOrCloseNotify() { + return e + } + if err != nil { + return err + } + } + + return nil +} + +func (c *Conn) enqueueEncryptedPackets(packet addrPkt) bool { + if len(c.encryptedPackets) < maxAppDataPacketQueueSize { + c.encryptedPackets = append(c.encryptedPackets, packet) + + return true + } + + return false +} + +//nolint:gocognit,gocyclo,cyclop,maintidx +func (c *Conn) handleIncomingPacket( + ctx context.Context, + buf []byte, + rAddr net.Addr, + enqueue bool, +) (bool, bool, *alert.Alert, error) { + header := &recordlayer.Header{} + // Set connection ID size so that records of content type tls12_cid will + // be parsed correctly. + if len(c.state.getLocalConnectionID()) > 0 { + header.ConnectionID = make([]byte, len(c.state.getLocalConnectionID())) + } + if err := header.Unmarshal(buf); err != nil { + // Decode error must be silently discarded + // [RFC6347 Section-4.1.2.7] + c.log.Debugf("discarded broken packet: %v", err) + + return false, false, nil, nil + } + // Validate epoch + remoteEpoch := c.state.getRemoteEpoch() + if header.Epoch > remoteEpoch { + if header.Epoch > remoteEpoch+1 { + c.log.Debugf("discarded future packet (epoch: %d, seq: %d)", + header.Epoch, header.SequenceNumber, + ) + + return false, false, nil, nil + } + if enqueue { + if ok := c.enqueueEncryptedPackets(addrPkt{rAddr, buf}); ok { + c.log.Debug("received packet of next epoch, queuing packet") + } + } + + return false, false, nil, nil + } + + // Anti-replay protection + for len(c.state.replayDetector) <= int(header.Epoch) { + c.state.replayDetector = append(c.state.replayDetector, + replaydetector.New(c.replayProtectionWindow, recordlayer.MaxSequenceNumber), + ) + } + markPacketAsValid, ok := c.state.replayDetector[int(header.Epoch)].Check(header.SequenceNumber) + if !ok { + c.log.Debugf("discarded duplicated packet (epoch: %d, seq: %d)", + header.Epoch, header.SequenceNumber, + ) + + return false, false, nil, nil + } + + // originalCID indicates whether the original record had content type + // Connection ID. + originalCID := false + + // Decrypt + if header.Epoch != 0 { //nolint:nestif + if c.state.cipherSuite == nil || !c.state.cipherSuite.IsInitialized() { + if enqueue { + if ok := c.enqueueEncryptedPackets(addrPkt{rAddr, buf}); ok { + c.log.Debug("handshake not finished, queuing packet") + } + } + + return false, false, nil, nil + } + + // If a connection identifier had been negotiated and encryption is + // enabled, the connection identifier MUST be sent. + if len(c.state.getLocalConnectionID()) > 0 && header.ContentType != protocol.ContentTypeConnectionID { + c.log.Debug("discarded packet missing connection ID after value negotiated") + + return false, false, nil, nil + } + + var err error + var hdr recordlayer.Header + if header.ContentType == protocol.ContentTypeConnectionID { + hdr.ConnectionID = make([]byte, len(c.state.getLocalConnectionID())) + } + buf, err = c.state.cipherSuite.Decrypt(hdr, buf) + if err != nil { + c.log.Debugf("%s: decrypt failed: %s", srvCliStr(c.state.isClient), err) + + return false, false, nil, nil + } + // If this is a connection ID record, make it look like a normal record for + // further processing. + if header.ContentType == protocol.ContentTypeConnectionID { + originalCID = true + ip := &recordlayer.InnerPlaintext{} + if err := ip.Unmarshal(buf[header.Size():]); err != nil { //nolint:govet + c.log.Debugf("unpacking inner plaintext failed: %s", err) + + return false, false, nil, nil + } + unpacked := &recordlayer.Header{ + ContentType: ip.RealType, + ContentLen: uint16(len(ip.Content)), //nolint:gosec // G115 + Version: header.Version, + Epoch: header.Epoch, + SequenceNumber: header.SequenceNumber, + } + buf, err = unpacked.Marshal() + if err != nil { + c.log.Debugf("converting CID record to inner plaintext failed: %s", err) + + return false, false, nil, nil + } + buf = append(buf, ip.Content...) + } + + // If connection ID does not match discard the packet. + if !bytes.Equal(c.state.getLocalConnectionID(), header.ConnectionID) { + c.log.Debug("unexpected connection ID") + + return false, false, nil, nil + } + } + + isHandshake, isRetransmit, err := c.fragmentBuffer.push(append([]byte{}, buf...)) + if err != nil { + // Decode error must be silently discarded + // [RFC6347 Section-4.1.2.7] + c.log.Debugf("defragment failed: %s", err) + + return false, false, nil, nil + } else if isHandshake { + markPacketAsValid() + + for out, epoch := c.fragmentBuffer.pop(); out != nil; out, epoch = c.fragmentBuffer.pop() { + header := &handshake.Header{} + if err := header.Unmarshal(out); err != nil { + c.log.Debugf("%s: handshake parse failed: %s", srvCliStr(c.state.isClient), err) + + continue + } + c.handshakeCache.push(out, epoch, header.MessageSequence, header.Type, !c.state.isClient) + } + + return true, isRetransmit, nil, nil + } + + r := &recordlayer.RecordLayer{} + if err := r.Unmarshal(buf); err != nil { + return false, false, &alert.Alert{Level: alert.Fatal, Description: alert.DecodeError}, err + } + + isLatestSeqNum := false + switch content := r.Content.(type) { + case *alert.Alert: + c.log.Tracef("%s: <- %s", srvCliStr(c.state.isClient), content.String()) + var a *alert.Alert + if content.Description == alert.CloseNotify { + // Respond with a close_notify [RFC5246 Section 7.2.1] + a = &alert.Alert{Level: alert.Warning, Description: alert.CloseNotify} + } + _ = markPacketAsValid() + + return false, false, a, &alertError{content} + case *protocol.ChangeCipherSpec: + if c.state.cipherSuite == nil || !c.state.cipherSuite.IsInitialized() { + if enqueue { + if ok := c.enqueueEncryptedPackets(addrPkt{rAddr, buf}); ok { + c.log.Debugf("CipherSuite not initialized, queuing packet") + } + } + + return false, false, nil, nil + } + + newRemoteEpoch := header.Epoch + 1 + c.log.Tracef("%s: <- ChangeCipherSpec (epoch: %d)", srvCliStr(c.state.isClient), newRemoteEpoch) + + if c.state.getRemoteEpoch()+1 == newRemoteEpoch { + c.setRemoteEpoch(newRemoteEpoch) + isLatestSeqNum = markPacketAsValid() + } + case *protocol.ApplicationData: + if header.Epoch == 0 { + return false, false, &alert.Alert{ + Level: alert.Fatal, Description: alert.UnexpectedMessage, + }, errApplicationDataEpochZero + } + + isLatestSeqNum = markPacketAsValid() + + select { + case c.decrypted <- content.Data: + case <-c.closed.Done(): + case <-ctx.Done(): + } + + default: + return false, false, &alert.Alert{ + Level: alert.Fatal, Description: alert.UnexpectedMessage, + }, fmt.Errorf("%w: %d", errUnhandledContextType, content.ContentType()) + } + + // Any valid connection ID record is a candidate for updating the remote + // address if it is the latest record received. + // https://datatracker.ietf.org/doc/html/rfc9146#peer-address-update + if originalCID && isLatestSeqNum { + if rAddr != c.RemoteAddr() { + c.lock.Lock() + c.rAddr = rAddr + c.lock.Unlock() + } + } + + return false, false, nil, nil +} + +func (c *Conn) recvHandshake() <-chan recvHandshakeState { + return c.handshakeRecv +} + +func (c *Conn) notify(ctx context.Context, level alert.Level, desc alert.Description) error { + if level == alert.Fatal && len(c.state.SessionID) > 0 { + // According to the RFC, we need to delete the stored session. + // https://datatracker.ietf.org/doc/html/rfc5246#section-7.2 + if ss := c.fsm.cfg.sessionStore; ss != nil { + c.log.Tracef("clean invalid session: %s", c.state.SessionID) + if err := ss.Del(c.sessionKey()); err != nil { + return err + } + } + } + + return c.writePackets(ctx, []*packet{ + { + record: &recordlayer.RecordLayer{ + Header: recordlayer.Header{ + Epoch: c.state.getLocalEpoch(), + Version: protocol.Version1_2, + }, + Content: &alert.Alert{ + Level: level, + Description: desc, + }, + }, + shouldWrapCID: len(c.state.remoteConnectionID) > 0, + shouldEncrypt: c.isHandshakeCompletedSuccessfully(), + }, + }) +} + +func (c *Conn) setHandshakeCompletedSuccessfully() { + c.handshakeCompletedSuccessfully.Store(struct{ bool }{true}) +} + +func (c *Conn) isHandshakeCompletedSuccessfully() bool { + boolean, _ := c.handshakeCompletedSuccessfully.Load().(struct{ bool }) + + return boolean.bool +} + +//nolint:cyclop,gocognit,contextcheck +func (c *Conn) handshake( + ctx context.Context, + cfg *handshakeConfig, + initialFlight flightVal, + initialState handshakeState, +) error { + c.fsm = newHandshakeFSM(&c.state, c.handshakeCache, cfg, initialFlight) + + done := make(chan struct{}) + ctxRead, cancelRead := context.WithCancel(context.Background()) + cfg.onFlightState = func(_ flightVal, s handshakeState) { + if s == handshakeFinished && !c.isHandshakeCompletedSuccessfully() { + c.setHandshakeCompletedSuccessfully() + close(done) + } + } + + ctxHs, cancel := context.WithCancel(context.Background()) + + c.closeLock.Lock() + c.cancelHandshaker = cancel + c.cancelHandshakeReader = cancelRead + c.closeLock.Unlock() + + firstErr := make(chan error, 1) + + var handshakeLoopsFinished sync.WaitGroup + handshakeLoopsFinished.Add(2) + + // Handshake routine should be live until close. + // The other party may request retransmission of the last flight to cope with packet drop. + go func() { + defer handshakeLoopsFinished.Done() + err := c.fsm.Run(ctxHs, c, initialState) + if !errors.Is(err, context.Canceled) { + select { + case firstErr <- err: + default: + } + } + }() + go func() { + defer func() { + if c.isHandshakeCompletedSuccessfully() { + // Escaping read loop. + // It's safe to close decrypted channnel now. + close(c.decrypted) + } + + // Force stop handshaker when the underlying connection is closed. + cancel() + }() + defer handshakeLoopsFinished.Done() + for { + if err := c.readAndBuffer(ctxRead); err != nil { //nolint:nestif + var alertErr *alertError + if errors.As(err, &alertErr) { + if !alertErr.IsFatalOrCloseNotify() { + if c.isHandshakeCompletedSuccessfully() { + // Pass the error to Read() + select { + case c.decrypted <- err: + case <-c.closed.Done(): + case <-ctxRead.Done(): + } + } + + continue // non-fatal alert must not stop read loop + } + } else { + switch { + case errors.Is(err, context.DeadlineExceeded), + errors.Is(err, context.Canceled), + errors.Is(err, io.EOF), + errors.Is(err, net.ErrClosed): + case errors.Is(err, recordlayer.ErrInvalidPacketLength): + // Decode error must be silently discarded + // [RFC6347 Section-4.1.2.7] + continue + default: + if c.isHandshakeCompletedSuccessfully() { + // Keep read loop and pass the read error to Read() + select { + case c.decrypted <- err: + case <-c.closed.Done(): + case <-ctxRead.Done(): + } + + continue // non-fatal alert must not stop read loop + } + } + } + + select { + case firstErr <- err: + default: + } + + if alertErr != nil { + if alertErr.IsFatalOrCloseNotify() { + _ = c.close(false) //nolint:contextcheck + } + } + if !c.isConnectionClosed() && errors.Is(err, context.Canceled) { + c.log.Trace("handshake timeouts - closing underline connection") + _ = c.close(false) //nolint:contextcheck + } + + return + } + } + }() + + select { + case err := <-firstErr: + cancelRead() + cancel() + handshakeLoopsFinished.Wait() + + return c.translateHandshakeCtxError(err) + case <-ctx.Done(): + cancelRead() + cancel() + handshakeLoopsFinished.Wait() + + return c.translateHandshakeCtxError(ctx.Err()) + case <-done: + return nil + } +} + +func (c *Conn) translateHandshakeCtxError(err error) error { + if err == nil { + return nil + } + if errors.Is(err, context.Canceled) && c.isHandshakeCompletedSuccessfully() { + return nil + } + + return &HandshakeError{Err: err} +} + +func (c *Conn) close(byUser bool) error { + c.closeLock.Lock() + cancelHandshaker := c.cancelHandshaker + cancelHandshakeReader := c.cancelHandshakeReader + c.closeLock.Unlock() + + cancelHandshaker() + cancelHandshakeReader() + + if c.isHandshakeCompletedSuccessfully() && byUser { + // Discard error from notify() to return non-error on the first user call of Close() + // even if the underlying connection is already closed. + _ = c.notify(context.Background(), alert.Warning, alert.CloseNotify) + } + + c.closeLock.Lock() + // Don't return ErrConnClosed at the first time of the call from user. + closedByUser := c.connectionClosedByUser + if byUser { + c.connectionClosedByUser = true + } + isClosed := c.isConnectionClosed() + c.closed.Close() + c.closeLock.Unlock() + + if closedByUser { + return ErrConnClosed + } + + if isClosed { + return nil + } + + return c.nextConn.Close() +} + +func (c *Conn) isConnectionClosed() bool { + select { + case <-c.closed.Done(): + return true + default: + return false + } +} + +func (c *Conn) setLocalEpoch(epoch uint16) { + c.state.localEpoch.Store(epoch) +} + +func (c *Conn) setRemoteEpoch(epoch uint16) { + c.state.remoteEpoch.Store(epoch) +} + +// LocalAddr implements net.Conn.LocalAddr. +func (c *Conn) LocalAddr() net.Addr { + return c.nextConn.LocalAddr() +} + +// RemoteAddr implements net.Conn.RemoteAddr. +func (c *Conn) RemoteAddr() net.Addr { + c.lock.RLock() + defer c.lock.RUnlock() + + return c.rAddr +} + +func (c *Conn) sessionKey() []byte { + if c.state.isClient { + // As ServerName can be like 0.example.com, it's better to add + // delimiter character which is not allowed to be in + // neither address or domain name. + return []byte(c.rAddr.String() + "_" + c.fsm.cfg.serverName) + } + + return c.state.SessionID +} + +// SetDeadline implements net.Conn.SetDeadline. +func (c *Conn) SetDeadline(t time.Time) error { + c.readDeadline.Set(t) + + return c.SetWriteDeadline(t) +} + +// SetReadDeadline implements net.Conn.SetReadDeadline. +func (c *Conn) SetReadDeadline(t time.Time) error { + c.readDeadline.Set(t) + // Read deadline is fully managed by this layer. + // Don't set read deadline to underlying connection. + return nil +} + +// SetWriteDeadline implements net.Conn.SetWriteDeadline. +func (c *Conn) SetWriteDeadline(t time.Time) error { + c.writeDeadline.Set(t) + // Write deadline is also fully managed by this layer. + return nil +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/connection_id.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/connection_id.go new file mode 100644 index 000000000..c590499b4 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/connection_id.go @@ -0,0 +1,105 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + +package dtls + +import ( + "crypto/rand" + + "github.com/pion/dtls/v3/pkg/protocol" + "github.com/pion/dtls/v3/pkg/protocol/extension" + "github.com/pion/dtls/v3/pkg/protocol/handshake" + "github.com/pion/dtls/v3/pkg/protocol/recordlayer" +) + +// RandomCIDGenerator is a random Connection ID generator where CID is the +// specified size. Specifying a size of 0 will indicate to peers that sending a +// Connection ID is not necessary. +func RandomCIDGenerator(size int) func() []byte { + return func() []byte { + cid := make([]byte, size) + if _, err := rand.Read(cid); err != nil { + panic(err) //nolint -- nonrecoverable + } + + return cid + } +} + +// OnlySendCIDGenerator enables sending Connection IDs negotiated with a peer, +// but indicates to the peer that sending Connection IDs in return is not +// necessary. +func OnlySendCIDGenerator() func() []byte { + return func() []byte { + return nil + } +} + +// cidDatagramRouter extracts connection IDs from incoming datagram payloads and +// uses them to route to the proper connection. +// NOTE: properly routing datagrams based on connection IDs requires using +// constant size connection IDs. +func cidDatagramRouter(size int) func([]byte) (string, bool) { + return func(packet []byte) (string, bool) { + pkts, err := recordlayer.ContentAwareUnpackDatagram(packet, size) + if err != nil || len(pkts) < 1 { + return "", false + } + for _, pkt := range pkts { + h := &recordlayer.Header{ + ConnectionID: make([]byte, size), + } + if err := h.Unmarshal(pkt); err != nil { + continue + } + if h.ContentType != protocol.ContentTypeConnectionID { + continue + } + + return string(h.ConnectionID), true + } + + return "", false + } +} + +// cidConnIdentifier extracts connection IDs from outgoing ServerHello records +// and associates them with the associated connection. +// NOTE: a ServerHello should always be the first record in a datagram if +// multiple are present, so we avoid iterating through all packets if the first +// is not a ServerHello. +func cidConnIdentifier() func([]byte) (string, bool) { //nolint:cyclop + return func(packet []byte) (string, bool) { + pkts, err := recordlayer.UnpackDatagram(packet) + if err != nil || len(pkts) < 1 { + return "", false + } + var h recordlayer.Header + if hErr := h.Unmarshal(pkts[0]); hErr != nil { + return "", false + } + if h.ContentType != protocol.ContentTypeHandshake { + return "", false + } + var hh handshake.Header + var sh handshake.MessageServerHello + for _, pkt := range pkts { + if hhErr := hh.Unmarshal(pkt[recordlayer.FixedHeaderSize:]); hhErr != nil { + continue + } + if err = sh.Unmarshal(pkt[recordlayer.FixedHeaderSize+handshake.HeaderLength:]); err == nil { + break + } + } + if err != nil { + return "", false + } + for _, ext := range sh.Extensions { + if e, ok := ext.(*extension.ConnectionID); ok { + return string(e.CID), true + } + } + + return "", false + } +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/crypto.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/crypto.go similarity index 65% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/crypto.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/crypto.go index 968910c7e..dae47731c 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/crypto.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/crypto.go @@ -9,15 +9,14 @@ import ( "crypto/ed25519" "crypto/rand" "crypto/rsa" - "crypto/sha256" "crypto/x509" "encoding/asn1" "encoding/binary" "math/big" "time" - "github.com/pion/dtls/v2/pkg/crypto/elliptic" - "github.com/pion/dtls/v2/pkg/crypto/hash" + "github.com/pion/dtls/v3/pkg/crypto/elliptic" + "github.com/pion/dtls/v3/pkg/crypto/hash" ) type ecdsaSignature struct { @@ -44,24 +43,36 @@ func valueKeyMessage(clientRandom, serverRandom, publicKey []byte, namedCurve el // hash/signature algorithm pair that appears in that extension // // https://tools.ietf.org/html/rfc5246#section-7.4.2 -func generateKeySignature(clientRandom, serverRandom, publicKey []byte, namedCurve elliptic.Curve, privateKey crypto.PrivateKey, hashAlgorithm hash.Algorithm) ([]byte, error) { +func generateKeySignature( + clientRandom, serverRandom, publicKey []byte, + namedCurve elliptic.Curve, + signer crypto.Signer, + hashAlgorithm hash.Algorithm, +) ([]byte, error) { msg := valueKeyMessage(clientRandom, serverRandom, publicKey, namedCurve) - switch p := privateKey.(type) { - case ed25519.PrivateKey: + switch signer.Public().(type) { + case ed25519.PublicKey: // https://crypto.stackexchange.com/a/55483 - return p.Sign(rand.Reader, msg, crypto.Hash(0)) - case *ecdsa.PrivateKey: + return signer.Sign(rand.Reader, msg, crypto.Hash(0)) + case *ecdsa.PublicKey: hashed := hashAlgorithm.Digest(msg) - return p.Sign(rand.Reader, hashed, hashAlgorithm.CryptoHash()) - case *rsa.PrivateKey: + + return signer.Sign(rand.Reader, hashed, hashAlgorithm.CryptoHash()) + case *rsa.PublicKey: hashed := hashAlgorithm.Digest(msg) - return p.Sign(rand.Reader, hashed, hashAlgorithm.CryptoHash()) + + return signer.Sign(rand.Reader, hashed, hashAlgorithm.CryptoHash()) } return nil, errKeySignatureGenerateUnimplemented } -func verifyKeySignature(message, remoteKeySignature []byte, hashAlgorithm hash.Algorithm, rawCertificates [][]byte) error { //nolint:dupl +//nolint:dupl,cyclop +func verifyKeySignature( + message, remoteKeySignature []byte, + hashAlgorithm hash.Algorithm, + rawCertificates [][]byte, +) error { if len(rawCertificates) == 0 { return errLengthMismatch } @@ -70,11 +81,12 @@ func verifyKeySignature(message, remoteKeySignature []byte, hashAlgorithm hash.A return err } - switch p := certificate.PublicKey.(type) { + switch pubKey := certificate.PublicKey.(type) { case ed25519.PublicKey: - if ok := ed25519.Verify(p, message, remoteKeySignature); !ok { + if ok := ed25519.Verify(pubKey, message, remoteKeySignature); !ok { return errKeySignatureMismatch } + return nil case *ecdsa.PublicKey: ecdsaSig := &ecdsaSignature{} @@ -85,18 +97,18 @@ func verifyKeySignature(message, remoteKeySignature []byte, hashAlgorithm hash.A return errInvalidECDSASignature } hashed := hashAlgorithm.Digest(message) - if !ecdsa.Verify(p, hashed, ecdsaSig.R, ecdsaSig.S) { + if !ecdsa.Verify(pubKey, hashed, ecdsaSig.R, ecdsaSig.S) { return errKeySignatureMismatch } + return nil case *rsa.PublicKey: - switch certificate.SignatureAlgorithm { - case x509.SHA1WithRSA, x509.SHA256WithRSA, x509.SHA384WithRSA, x509.SHA512WithRSA: - hashed := hashAlgorithm.Digest(message) - return rsa.VerifyPKCS1v15(p, hashAlgorithm.CryptoHash(), hashed, remoteKeySignature) - default: - return errKeySignatureVerifyUnimplemented + hashed := hashAlgorithm.Digest(message) + if rsa.VerifyPKCS1v15(pubKey, hashAlgorithm.CryptoHash(), hashed, remoteKeySignature) != nil { + return errKeySignatureMismatch } + + return nil } return errKeySignatureVerifyUnimplemented @@ -110,31 +122,37 @@ func verifyKeySignature(message, remoteKeySignature []byte, hashAlgorithm hash.A // CertificateVerify message is sent to explicitly verify possession of // the private key in the certificate. // https://tools.ietf.org/html/rfc5246#section-7.3 -func generateCertificateVerify(handshakeBodies []byte, privateKey crypto.PrivateKey, hashAlgorithm hash.Algorithm) ([]byte, error) { - if p, ok := privateKey.(ed25519.PrivateKey); ok { +func generateCertificateVerify( + handshakeBodies []byte, + signer crypto.Signer, + hashAlgorithm hash.Algorithm, +) ([]byte, error) { + if _, ok := signer.Public().(ed25519.PublicKey); ok { // https://pkg.go.dev/crypto/ed25519#PrivateKey.Sign // Sign signs the given message with priv. Ed25519 performs two passes over // messages to be signed and therefore cannot handle pre-hashed messages. - return p.Sign(rand.Reader, handshakeBodies, crypto.Hash(0)) + return signer.Sign(rand.Reader, handshakeBodies, crypto.Hash(0)) } - h := sha256.New() - if _, err := h.Write(handshakeBodies); err != nil { - return nil, err - } - hashed := h.Sum(nil) + hashed := hashAlgorithm.Digest(handshakeBodies) - switch p := privateKey.(type) { - case *ecdsa.PrivateKey: - return p.Sign(rand.Reader, hashed, hashAlgorithm.CryptoHash()) - case *rsa.PrivateKey: - return p.Sign(rand.Reader, hashed, hashAlgorithm.CryptoHash()) + switch signer.Public().(type) { + case *ecdsa.PublicKey: + return signer.Sign(rand.Reader, hashed, hashAlgorithm.CryptoHash()) + case *rsa.PublicKey: + return signer.Sign(rand.Reader, hashed, hashAlgorithm.CryptoHash()) } return nil, errInvalidSignatureAlgorithm } -func verifyCertificateVerify(handshakeBodies []byte, hashAlgorithm hash.Algorithm, remoteKeySignature []byte, rawCertificates [][]byte) error { //nolint:dupl +//nolint:dupl,cyclop +func verifyCertificateVerify( + handshakeBodies []byte, + hashAlgorithm hash.Algorithm, + remoteKeySignature []byte, + rawCertificates [][]byte, +) error { if len(rawCertificates) == 0 { return errLengthMismatch } @@ -143,11 +161,12 @@ func verifyCertificateVerify(handshakeBodies []byte, hashAlgorithm hash.Algorith return err } - switch p := certificate.PublicKey.(type) { + switch pubKey := certificate.PublicKey.(type) { case ed25519.PublicKey: - if ok := ed25519.Verify(p, handshakeBodies, remoteKeySignature); !ok { + if ok := ed25519.Verify(pubKey, handshakeBodies, remoteKeySignature); !ok { return errKeySignatureMismatch } + return nil case *ecdsa.PublicKey: ecdsaSig := &ecdsaSignature{} @@ -158,18 +177,18 @@ func verifyCertificateVerify(handshakeBodies []byte, hashAlgorithm hash.Algorith return errInvalidECDSASignature } hash := hashAlgorithm.Digest(handshakeBodies) - if !ecdsa.Verify(p, hash, ecdsaSig.R, ecdsaSig.S) { + if !ecdsa.Verify(pubKey, hash, ecdsaSig.R, ecdsaSig.S) { return errKeySignatureMismatch } + return nil case *rsa.PublicKey: - switch certificate.SignatureAlgorithm { - case x509.SHA1WithRSA, x509.SHA256WithRSA, x509.SHA384WithRSA, x509.SHA512WithRSA: - hash := hashAlgorithm.Digest(handshakeBodies) - return rsa.VerifyPKCS1v15(p, hashAlgorithm.CryptoHash(), hash, remoteKeySignature) - default: - return errKeySignatureVerifyUnimplemented + hash := hashAlgorithm.Digest(handshakeBodies) + if rsa.VerifyPKCS1v15(pubKey, hashAlgorithm.CryptoHash(), hash, remoteKeySignature) != nil { + return errKeySignatureMismatch } + + return nil } return errKeySignatureVerifyUnimplemented @@ -188,6 +207,7 @@ func loadCerts(rawCertificates [][]byte) ([]*x509.Certificate, error) { } certs = append(certs, cert) } + return certs, nil } @@ -206,10 +226,15 @@ func verifyClientCert(rawCertificates [][]byte, roots *x509.CertPool) (chains [] Intermediates: intermediateCAPool, KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}, } + return certificate[0].Verify(opts) } -func verifyServerCert(rawCertificates [][]byte, roots *x509.CertPool, serverName string) (chains [][]*x509.Certificate, err error) { +func verifyServerCert( + rawCertificates [][]byte, + roots *x509.CertPool, + serverName string, +) (chains [][]*x509.Certificate, err error) { certificate, err := loadCerts(rawCertificates) if err != nil { return nil, err @@ -224,5 +249,6 @@ func verifyServerCert(rawCertificates [][]byte, roots *x509.CertPool, serverName DNSName: serverName, Intermediates: intermediateCAPool, } + return certificate[0].Verify(opts) } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/dtls.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/dtls.go similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/dtls.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/dtls.go diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/errors.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/errors.go new file mode 100644 index 000000000..b7f93b7b4 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/errors.go @@ -0,0 +1,227 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + +package dtls + +import ( + "context" + "errors" + "fmt" + "io" + "net" + "os" + + "github.com/pion/dtls/v3/pkg/protocol" + "github.com/pion/dtls/v3/pkg/protocol/alert" +) + +// Typed errors. +var ( + ErrConnClosed = &FatalError{Err: errors.New("conn is closed")} //nolint:goerr113 + + errDeadlineExceeded = &TimeoutError{Err: fmt.Errorf("read/write timeout: %w", context.DeadlineExceeded)} + errInvalidContentType = &TemporaryError{Err: errors.New("invalid content type")} //nolint:goerr113 + + //nolint:goerr113 + errBufferTooSmall = &TemporaryError{Err: errors.New("buffer is too small")} + //nolint:goerr113 + errContextUnsupported = &TemporaryError{Err: errors.New("context is not supported for ExportKeyingMaterial")} + //nolint:goerr113 + errHandshakeInProgress = &TemporaryError{Err: errors.New("handshake is in progress")} + //nolint:goerr113 + errReservedExportKeyingMaterial = &TemporaryError{ + Err: errors.New("ExportKeyingMaterial can not be used with a reserved label"), + } + //nolint:goerr113 + errApplicationDataEpochZero = &TemporaryError{Err: errors.New("ApplicationData with epoch of 0")} + //nolint:goerr113 + errUnhandledContextType = &TemporaryError{Err: errors.New("unhandled contentType")} + + //nolint:goerr113 + errCertificateVerifyNoCertificate = &FatalError{ + Err: errors.New("client sent certificate verify but we have no certificate to verify"), + } + //nolint:goerr113 + errCipherSuiteNoIntersection = &FatalError{Err: errors.New("client+server do not support any shared cipher suites")} + //nolint:goerr113 + errClientCertificateNotVerified = &FatalError{Err: errors.New("client sent certificate but did not verify it")} + //nolint:goerr113 + errClientCertificateRequired = &FatalError{Err: errors.New("server required client verification, but got none")} + //nolint:goerr113 + errClientNoMatchingSRTPProfile = &FatalError{Err: errors.New("server responded with SRTP Profile we do not support")} + //nolint:goerr113 + errClientRequiredButNoServerEMS = &FatalError{ + Err: errors.New("client required Extended Master Secret extension, but server does not support it"), + } + //nolint:goerr113 + errCookieMismatch = &FatalError{Err: errors.New("client+server cookie does not match")} + //nolint:goerr113 + errIdentityNoPSK = &FatalError{Err: errors.New("PSK Identity Hint provided but PSK is nil")} + //nolint:goerr113 + errInvalidCertificate = &FatalError{Err: errors.New("no certificate provided")} + //nolint:goerr113 + errInvalidCipherSuite = &FatalError{Err: errors.New("invalid or unknown cipher suite")} + //nolint:goerr113 + errInvalidECDSASignature = &FatalError{Err: errors.New("ECDSA signature contained zero or negative values")} + //nolint:goerr113 + errInvalidPrivateKey = &FatalError{Err: errors.New("invalid private key type")} + //nolint:goerr113 + errInvalidSignatureAlgorithm = &FatalError{Err: errors.New("invalid signature algorithm")} + //nolint:goerr113 + errKeySignatureMismatch = &FatalError{Err: errors.New("expected and actual key signature do not match")} + //nolint:goerr113 + errNilNextConn = &FatalError{Err: errors.New("Conn can not be created with a nil nextConn")} + //nolint:goerr113 + errNoAvailableCipherSuites = &FatalError{ + Err: errors.New("connection can not be created, no CipherSuites satisfy this Config"), + } + //nolint:goerr113 + errNoAvailablePSKCipherSuite = &FatalError{ + Err: errors.New("connection can not be created, pre-shared key present but no compatible CipherSuite"), + } + //nolint:goerr113 + errNoAvailableCertificateCipherSuite = &FatalError{ + Err: errors.New("connection can not be created, certificate present but no compatible CipherSuite"), + } + //nolint:goerr113 + errNoAvailableSignatureSchemes = &FatalError{ + Err: errors.New("connection can not be created, no SignatureScheme satisfy this Config"), + } + //nolint:goerr113 + errNoCertificates = &FatalError{Err: errors.New("no certificates configured")} + //nolint:goerr113 + errNoConfigProvided = &FatalError{Err: errors.New("no config provided")} + //nolint:goerr113 + errNoSupportedEllipticCurves = &FatalError{ + Err: errors.New("client requested zero or more elliptic curves that are not supported by the server"), + } + //nolint:goerr113 + errUnsupportedProtocolVersion = &FatalError{Err: errors.New("unsupported protocol version")} + //nolint:goerr113 + errPSKAndIdentityMustBeSetForClient = &FatalError{ + Err: errors.New("PSK and PSK Identity Hint must both be set for client"), + } + //nolint:goerr113 + errRequestedButNoSRTPExtension = &FatalError{ + Err: errors.New("SRTP support was requested but server did not respond with use_srtp extension"), + } + //nolint:goerr113 + errServerNoMatchingSRTPProfile = &FatalError{Err: errors.New("client requested SRTP but we have no matching profiles")} + //nolint:goerr113 + errServerRequiredButNoClientEMS = &FatalError{ + Err: errors.New("server requires the Extended Master Secret extension, but the client does not support it"), + } + //nolint:goerr113 + errVerifyDataMismatch = &FatalError{Err: errors.New("expected and actual verify data does not match")} + //nolint:goerr113 + errNotAcceptableCertificateChain = &FatalError{Err: errors.New("certificate chain is not signed by an acceptable CA")} + + //nolint:goerr113 + errInvalidFlight = &InternalError{Err: errors.New("invalid flight number")} + //nolint:goerr113 + errKeySignatureGenerateUnimplemented = &InternalError{ + Err: errors.New("unable to generate key signature, unimplemented"), + } + //nolint:goerr113 + errKeySignatureVerifyUnimplemented = &InternalError{Err: errors.New("unable to verify key signature, unimplemented")} + //nolint:goerr113 + errLengthMismatch = &InternalError{Err: errors.New("data length and declared length do not match")} + //nolint:goerr113 + errSequenceNumberOverflow = &InternalError{Err: errors.New("sequence number overflow")} + //nolint:goerr113 + errInvalidFSMTransition = &InternalError{Err: errors.New("invalid state machine transition")} + //nolint:goerr113 + errFailedToAccessPoolReadBuffer = &InternalError{Err: errors.New("failed to access pool read buffer")} + //nolint:goerr113 + errFragmentBufferOverflow = &InternalError{Err: errors.New("fragment buffer overflow")} +) + +// FatalError indicates that the DTLS connection is no longer available. +// It is mainly caused by wrong configuration of server or client. +type FatalError = protocol.FatalError + +// InternalError indicates and internal error caused by the implementation, +// and the DTLS connection is no longer available. +// It is mainly caused by bugs or tried to use unimplemented features. +type InternalError = protocol.InternalError + +// TemporaryError indicates that the DTLS connection is still available, but the request was failed temporary. +type TemporaryError = protocol.TemporaryError + +// TimeoutError indicates that the request was timed out. +type TimeoutError = protocol.TimeoutError + +// HandshakeError indicates that the handshake failed. +type HandshakeError = protocol.HandshakeError + +// errInvalidCipherSuite indicates an attempt at using an unsupported cipher suite. +type invalidCipherSuiteError struct { + id CipherSuiteID +} + +func (e *invalidCipherSuiteError) Error() string { + return fmt.Sprintf("CipherSuite with id(%d) is not valid", e.id) +} + +func (e *invalidCipherSuiteError) Is(err error) bool { + var other *invalidCipherSuiteError + if errors.As(err, &other) { + return e.id == other.id + } + + return false +} + +// errAlert wraps DTLS alert notification as an error. +type alertError struct { + *alert.Alert +} + +func (e *alertError) Error() string { + return fmt.Sprintf("alert: %s", e.Alert.String()) +} + +func (e *alertError) IsFatalOrCloseNotify() bool { + return e.Level == alert.Fatal || e.Description == alert.CloseNotify +} + +func (e *alertError) Is(err error) bool { + var other *alertError + if errors.As(err, &other) { + return e.Level == other.Level && e.Description == other.Description + } + + return false +} + +// netError translates an error from underlying Conn to corresponding net.Error. +func netError(err error) error { + switch { + case errors.Is(err, io.EOF), errors.Is(err, context.Canceled), errors.Is(err, context.DeadlineExceeded): + // Return io.EOF and context errors as is. + return err + } + + var ( + ne net.Error + opError *net.OpError + se *os.SyscallError + ) + + if errors.As(err, &opError) { //nolint:nestif + if errors.As(opError, &se) { + if se.Timeout() { + return &TimeoutError{Err: err} + } + if isOpErrorTemporary(se) { + return &TemporaryError{Err: err} + } + } + } + + if errors.As(err, &ne) { + return err + } + + return &FatalError{Err: err} +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/errors_errno.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/errors_errno.go similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/errors_errno.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/errors_errno.go diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/errors_noerrno.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/errors_noerrno.go similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/errors_noerrno.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/errors_noerrno.go diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/flight.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/flight.go similarity index 98% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/flight.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/flight.go index cfa58c574..7ecc9489d 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/flight.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/flight.go @@ -70,7 +70,7 @@ const ( flight6 ) -func (f flightVal) String() string { +func (f flightVal) String() string { //nolint:cyclop switch f { case flight0: return "Flight 0" diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/flight0handler.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/flight0handler.go similarity index 67% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/flight0handler.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/flight0handler.go index ec766ddff..ce6ad2031 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/flight0handler.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/flight0handler.go @@ -7,14 +7,21 @@ import ( "context" "crypto/rand" - "github.com/pion/dtls/v2/pkg/crypto/elliptic" - "github.com/pion/dtls/v2/pkg/protocol" - "github.com/pion/dtls/v2/pkg/protocol/alert" - "github.com/pion/dtls/v2/pkg/protocol/extension" - "github.com/pion/dtls/v2/pkg/protocol/handshake" + "github.com/pion/dtls/v3/pkg/crypto/elliptic" + "github.com/pion/dtls/v3/pkg/protocol" + "github.com/pion/dtls/v3/pkg/protocol/alert" + "github.com/pion/dtls/v3/pkg/protocol/extension" + "github.com/pion/dtls/v3/pkg/protocol/handshake" ) -func flight0Parse(_ context.Context, _ flightConn, state *State, cache *handshakeCache, cfg *handshakeConfig) (flightVal, *alert.Alert, error) { +//nolint:cyclop +func flight0Parse( + _ context.Context, + _ flightConn, + state *State, + cache *handshakeCache, + cfg *handshakeConfig, +) (flightVal, *alert.Alert, error) { seq, msgs, ok := cache.fullPullMap(0, state.cipherSuite, handshakeCachePullRule{handshake.TypeClientHello, cfg.initialEpoch, true, false}, ) @@ -22,6 +29,12 @@ func flight0Parse(_ context.Context, _ flightConn, state *State, cache *handshak // No valid message received. Keep reading return 0, nil, nil } + + // Connection Identifiers must be negotiated afresh on session resumption. + // https://datatracker.ietf.org/doc/html/rfc9146#name-the-connection_id-extension + state.setLocalConnectionID(nil) + state.remoteConnectionID = nil + state.handshakeRecvSequence = seq var clientHello *handshake.MessageClientHello @@ -49,29 +62,42 @@ func flight0Parse(_ context.Context, _ flightConn, state *State, cache *handshak } for _, val := range clientHello.Extensions { - switch e := val.(type) { + switch ext := val.(type) { case *extension.SupportedEllipticCurves: - if len(e.EllipticCurves) == 0 { + if len(ext.EllipticCurves) == 0 { return 0, &alert.Alert{Level: alert.Fatal, Description: alert.InsufficientSecurity}, errNoSupportedEllipticCurves } - state.namedCurve = e.EllipticCurves[0] + state.namedCurve = ext.EllipticCurves[0] case *extension.UseSRTP: - profile, ok := findMatchingSRTPProfile(e.ProtectionProfiles, cfg.localSRTPProtectionProfiles) + profile, ok := findMatchingSRTPProfile(ext.ProtectionProfiles, cfg.localSRTPProtectionProfiles) if !ok { return 0, &alert.Alert{Level: alert.Fatal, Description: alert.InsufficientSecurity}, errServerNoMatchingSRTPProfile } - state.srtpProtectionProfile = profile + state.setSRTPProtectionProfile(profile) + state.remoteSRTPMasterKeyIdentifier = ext.MasterKeyIdentifier case *extension.UseExtendedMasterSecret: if cfg.extendedMasterSecret != DisableExtendedMasterSecret { state.extendedMasterSecret = true } case *extension.ServerName: - state.serverName = e.ServerName // remote server name + state.serverName = ext.ServerName // remote server name case *extension.ALPN: - state.peerSupportedProtocols = e.ProtocolNameList + state.peerSupportedProtocols = ext.ProtocolNameList + case *extension.ConnectionID: + // Only set connection ID to be sent if server supports connection + // IDs. + if cfg.connectionIDGenerator != nil { + state.remoteConnectionID = ext.CID + } } } + // If the client doesn't support connection IDs, the server should not + // expect one to be sent. + if state.remoteConnectionID == nil { + state.setLocalConnectionID(nil) + } + if cfg.extendedMasterSecret == RequireExtendedMasterSecret && !state.extendedMasterSecret { return 0, &alert.Alert{Level: alert.Fatal, Description: alert.InsufficientSecurity}, errServerRequiredButNoClientEMS } @@ -93,7 +119,12 @@ func flight0Parse(_ context.Context, _ flightConn, state *State, cache *handshak return handleHelloResume(clientHello.SessionID, state, cfg, nextFlight) } -func handleHelloResume(sessionID []byte, state *State, cfg *handshakeConfig, next flightVal) (flightVal, *alert.Alert, error) { +func handleHelloResume( + sessionID []byte, + state *State, + cfg *handshakeConfig, + next flightVal, +) (flightVal, *alert.Alert, error) { if len(sessionID) > 0 && cfg.sessionStore != nil { if s, err := cfg.sessionStore.Get(sessionID); err != nil { return 0, &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, err @@ -113,10 +144,16 @@ func handleHelloResume(sessionID []byte, state *State, cfg *handshakeConfig, nex return flight4b, nil, nil } } + return next, nil, nil } -func flight0Generate(_ flightConn, state *State, _ *handshakeCache, cfg *handshakeConfig) ([]*packet, *alert.Alert, error) { +func flight0Generate( + _ flightConn, + state *State, + _ *handshakeCache, + cfg *handshakeConfig, +) ([]*packet, *alert.Alert, error) { // Initialize if !cfg.insecureSkipHelloVerify { state.cookie = make([]byte, cookieLength) diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/flight1handler.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/flight1handler.go similarity index 60% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/flight1handler.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/flight1handler.go index 94fdc222d..6c55a6430 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/flight1handler.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/flight1handler.go @@ -6,15 +6,21 @@ package dtls import ( "context" - "github.com/pion/dtls/v2/pkg/crypto/elliptic" - "github.com/pion/dtls/v2/pkg/protocol" - "github.com/pion/dtls/v2/pkg/protocol/alert" - "github.com/pion/dtls/v2/pkg/protocol/extension" - "github.com/pion/dtls/v2/pkg/protocol/handshake" - "github.com/pion/dtls/v2/pkg/protocol/recordlayer" + "github.com/pion/dtls/v3/pkg/crypto/elliptic" + "github.com/pion/dtls/v3/pkg/protocol" + "github.com/pion/dtls/v3/pkg/protocol/alert" + "github.com/pion/dtls/v3/pkg/protocol/extension" + "github.com/pion/dtls/v3/pkg/protocol/handshake" + "github.com/pion/dtls/v3/pkg/protocol/recordlayer" ) -func flight1Parse(ctx context.Context, c flightConn, state *State, cache *handshakeCache, cfg *handshakeConfig) (flightVal, *alert.Alert, error) { +func flight1Parse( + ctx context.Context, + conn flightConn, + state *State, + cache *handshakeCache, + cfg *handshakeConfig, +) (flightVal, *alert.Alert, error) { // HelloVerifyRequest can be skipped by the server, // so allow ServerHello during flight1 also seq, msgs, ok := cache.fullPullMap(state.handshakeRecvSequence, state.cipherSuite, @@ -29,7 +35,7 @@ func flight1Parse(ctx context.Context, c flightConn, state *State, cache *handsh if _, ok := msgs[handshake.TypeServerHello]; ok { // Flight1 and flight2 were skipped. // Parse as flight3. - return flight3Parse(ctx, c, state, cache, cfg) + return flight3Parse(ctx, conn, state, cache, cfg) } if h, ok := msgs[handshake.TypeHelloVerifyRequest].(*handshake.MessageHelloVerifyRequest); ok { @@ -40,13 +46,20 @@ func flight1Parse(ctx context.Context, c flightConn, state *State, cache *handsh } state.cookie = append([]byte{}, h.Cookie...) state.handshakeRecvSequence = seq + return flight3, nil, nil } return 0, &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, nil } -func flight1Generate(c flightConn, state *State, _ *handshakeCache, cfg *handshakeConfig) ([]*packet, *alert.Alert, error) { +//nolint:cyclop +func flight1Generate( + conn flightConn, + state *State, + _ *handshakeCache, + cfg *handshakeConfig, +) ([]*packet, *alert.Alert, error) { var zeroEpoch uint16 state.localEpoch.Store(zeroEpoch) state.remoteEpoch.Store(zeroEpoch) @@ -57,6 +70,10 @@ func flight1Generate(c flightConn, state *State, _ *handshakeCache, cfg *handsha return nil, nil, err } + if cfg.helloRandomBytesGenerator != nil { + state.localRandom.RandomBytes = cfg.helloRandomBytesGenerator() + } + extensions := []extension.Extension{ &extension.SupportedSignatureAlgorithms{ SignatureHashAlgorithms: cfg.localSignatureSchemes, @@ -70,6 +87,7 @@ func flight1Generate(c flightConn, state *State, _ *handshakeCache, cfg *handsha for _, c := range cfg.localCipherSuites { if c.ECC() { setEllipticCurveCryptographyClientHelloExtensions = true + break } } @@ -87,7 +105,8 @@ func flight1Generate(c flightConn, state *State, _ *handshakeCache, cfg *handsha if len(cfg.localSRTPProtectionProfiles) > 0 { extensions = append(extensions, &extension.UseSRTP{ - ProtectionProfiles: cfg.localSRTPProtectionProfiles, + ProtectionProfiles: cfg.localSRTPProtectionProfiles, + MasterKeyIdentifier: cfg.localSRTPMasterKeyIdentifier, }) } @@ -108,7 +127,7 @@ func flight1Generate(c flightConn, state *State, _ *handshakeCache, cfg *handsha if cfg.sessionStore != nil { cfg.log.Tracef("[handshake] try to resume session") - if s, err := cfg.sessionStore.Get(c.sessionKey()); err != nil { + if s, err := cfg.sessionStore.Get(conn.sessionKey()); err != nil { return nil, &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, err } else if s.ID != nil { cfg.log.Tracef("[handshake] get saved session: %x", s.ID) @@ -118,23 +137,46 @@ func flight1Generate(c flightConn, state *State, _ *handshakeCache, cfg *handsha } } + // If we have a connection ID generator, use it. The CID may be zero length, + // in which case we are just requesting that the server send us a CID to + // use. + if cfg.connectionIDGenerator != nil { + state.setLocalConnectionID(cfg.connectionIDGenerator()) + // The presence of a generator indicates support for connection IDs. We + // use the presence of a non-nil local CID in flight 3 to determine + // whether we send a CID in the second ClientHello, so we convert any + // nil CID returned by a generator to []byte{}. + if state.getLocalConnectionID() == nil { + state.setLocalConnectionID([]byte{}) + } + extensions = append(extensions, &extension.ConnectionID{CID: state.getLocalConnectionID()}) + } + + clientHello := &handshake.MessageClientHello{ + Version: protocol.Version1_2, + SessionID: state.SessionID, + Cookie: state.cookie, + Random: state.localRandom, + CipherSuiteIDs: cipherSuiteIDs(cfg.localCipherSuites), + CompressionMethods: defaultCompressionMethods(), + Extensions: extensions, + } + + var content handshake.Handshake + + if cfg.clientHelloMessageHook != nil { + content = handshake.Handshake{Message: cfg.clientHelloMessageHook(*clientHello)} + } else { + content = handshake.Handshake{Message: clientHello} + } + return []*packet{ { record: &recordlayer.RecordLayer{ Header: recordlayer.Header{ Version: protocol.Version1_2, }, - Content: &handshake.Handshake{ - Message: &handshake.MessageClientHello{ - Version: protocol.Version1_2, - SessionID: state.SessionID, - Cookie: state.cookie, - Random: state.localRandom, - CipherSuiteIDs: cipherSuiteIDs(cfg.localCipherSuites), - CompressionMethods: defaultCompressionMethods(), - Extensions: extensions, - }, - }, + Content: &content, }, }, }, nil, nil diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/flight2handler.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/flight2handler.go similarity index 76% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/flight2handler.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/flight2handler.go index 26e57d2f2..8d50befba 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/flight2handler.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/flight2handler.go @@ -7,13 +7,19 @@ import ( "bytes" "context" - "github.com/pion/dtls/v2/pkg/protocol" - "github.com/pion/dtls/v2/pkg/protocol/alert" - "github.com/pion/dtls/v2/pkg/protocol/handshake" - "github.com/pion/dtls/v2/pkg/protocol/recordlayer" + "github.com/pion/dtls/v3/pkg/protocol" + "github.com/pion/dtls/v3/pkg/protocol/alert" + "github.com/pion/dtls/v3/pkg/protocol/handshake" + "github.com/pion/dtls/v3/pkg/protocol/recordlayer" ) -func flight2Parse(ctx context.Context, c flightConn, state *State, cache *handshakeCache, cfg *handshakeConfig) (flightVal, *alert.Alert, error) { +func flight2Parse( + ctx context.Context, + c flightConn, + state *State, + cache *handshakeCache, + cfg *handshakeConfig, +) (flightVal, *alert.Alert, error) { seq, msgs, ok := cache.fullPullMap(state.handshakeRecvSequence, state.cipherSuite, handshakeCachePullRule{handshake.TypeClientHello, cfg.initialEpoch, true, false}, ) @@ -41,11 +47,18 @@ func flight2Parse(ctx context.Context, c flightConn, state *State, cache *handsh if !bytes.Equal(state.cookie, clientHello.Cookie) { return 0, &alert.Alert{Level: alert.Fatal, Description: alert.AccessDenied}, errCookieMismatch } + return flight4, nil, nil } -func flight2Generate(_ flightConn, state *State, _ *handshakeCache, _ *handshakeConfig) ([]*packet, *alert.Alert, error) { +func flight2Generate( + _ flightConn, + state *State, + _ *handshakeCache, + _ *handshakeConfig, +) ([]*packet, *alert.Alert, error) { state.handshakeSendSequence = 0 + return []*packet{ { record: &recordlayer.RecordLayer{ diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/flight3handler.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/flight3handler.go similarity index 65% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/flight3handler.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/flight3handler.go index 5a763dc08..7301e34b6 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/flight3handler.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/flight3handler.go @@ -7,17 +7,24 @@ import ( "bytes" "context" - "github.com/pion/dtls/v2/internal/ciphersuite/types" - "github.com/pion/dtls/v2/pkg/crypto/elliptic" - "github.com/pion/dtls/v2/pkg/crypto/prf" - "github.com/pion/dtls/v2/pkg/protocol" - "github.com/pion/dtls/v2/pkg/protocol/alert" - "github.com/pion/dtls/v2/pkg/protocol/extension" - "github.com/pion/dtls/v2/pkg/protocol/handshake" - "github.com/pion/dtls/v2/pkg/protocol/recordlayer" + "github.com/pion/dtls/v3/internal/ciphersuite/types" + "github.com/pion/dtls/v3/pkg/crypto/elliptic" + "github.com/pion/dtls/v3/pkg/crypto/prf" + "github.com/pion/dtls/v3/pkg/protocol" + "github.com/pion/dtls/v3/pkg/protocol/alert" + "github.com/pion/dtls/v3/pkg/protocol/extension" + "github.com/pion/dtls/v3/pkg/protocol/handshake" + "github.com/pion/dtls/v3/pkg/protocol/recordlayer" ) -func flight3Parse(ctx context.Context, c flightConn, state *State, cache *handshakeCache, cfg *handshakeConfig) (flightVal, *alert.Alert, error) { //nolint:gocognit +//nolint:gocognit,gocyclo,maintidx,cyclop +func flight3Parse( + ctx context.Context, + conn flightConn, + state *State, + cache *handshakeCache, + cfg *handshakeConfig, +) (flightVal, *alert.Alert, error) { // Clients may receive multiple HelloVerifyRequest messages with different cookies. // Clients SHOULD handle this by sending a new ClientHello with a cookie in response // to the new HelloVerifyRequest. RFC 6347 Section 4.2.1 @@ -33,6 +40,7 @@ func flight3Parse(ctx context.Context, c flightConn, state *State, cache *handsh } state.cookie = append([]byte{}, h.Cookie...) state.handshakeRecvSequence = seq + return flight3, nil, nil } } @@ -45,37 +53,53 @@ func flight3Parse(ctx context.Context, c flightConn, state *State, cache *handsh return 0, nil, nil } - if h, msgOk := msgs[handshake.TypeServerHello].(*handshake.MessageServerHello); msgOk { - if !h.Version.Equal(protocol.Version1_2) { + if serverHelloMsg, msgOk := msgs[handshake.TypeServerHello].(*handshake.MessageServerHello); msgOk { //nolint:nestif + if !serverHelloMsg.Version.Equal(protocol.Version1_2) { return 0, &alert.Alert{Level: alert.Fatal, Description: alert.ProtocolVersion}, errUnsupportedProtocolVersion } - for _, v := range h.Extensions { - switch e := v.(type) { + for _, v := range serverHelloMsg.Extensions { + switch ext := v.(type) { case *extension.UseSRTP: - profile, found := findMatchingSRTPProfile(e.ProtectionProfiles, cfg.localSRTPProtectionProfiles) + profile, found := findMatchingSRTPProfile(ext.ProtectionProfiles, cfg.localSRTPProtectionProfiles) if !found { return 0, &alert.Alert{Level: alert.Fatal, Description: alert.IllegalParameter}, errClientNoMatchingSRTPProfile } - state.srtpProtectionProfile = profile + state.setSRTPProtectionProfile(profile) + state.remoteSRTPMasterKeyIdentifier = ext.MasterKeyIdentifier case *extension.UseExtendedMasterSecret: if cfg.extendedMasterSecret != DisableExtendedMasterSecret { state.extendedMasterSecret = true } case *extension.ALPN: - if len(e.ProtocolNameList) > 1 { // This should be exactly 1, the zero case is handle when unmarshalling - return 0, &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, extension.ErrALPNInvalidFormat // Meh, internal error? + if len(ext.ProtocolNameList) > 1 { // This should be exactly 1, the zero case is handle when unmarshalling + return 0, &alert.Alert{ + Level: alert.Fatal, + Description: alert.InternalError, + }, extension.ErrALPNInvalidFormat // Meh, internal error? + } + state.NegotiatedProtocol = ext.ProtocolNameList[0] + case *extension.ConnectionID: + // Only set connection ID to be sent if client supports connection + // IDs. + if cfg.connectionIDGenerator != nil { + state.remoteConnectionID = ext.CID } - state.NegotiatedProtocol = e.ProtocolNameList[0] } } + // If the server doesn't support connection IDs, the client should not + // expect one to be sent. + if state.remoteConnectionID == nil { + state.setLocalConnectionID(nil) + } + if cfg.extendedMasterSecret == RequireExtendedMasterSecret && !state.extendedMasterSecret { return 0, &alert.Alert{Level: alert.Fatal, Description: alert.InsufficientSecurity}, errClientRequiredButNoServerEMS } - if len(cfg.localSRTPProtectionProfiles) > 0 && state.srtpProtectionProfile == 0 { + if len(cfg.localSRTPProtectionProfiles) > 0 && state.getSRTPProtectionProfile() == 0 { return 0, &alert.Alert{Level: alert.Fatal, Description: alert.InsufficientSecurity}, errRequestedButNoSRTPExtension } - remoteCipherSuite := cipherSuiteForID(CipherSuiteID(*h.CipherSuiteID), cfg.customCipherSuites) + remoteCipherSuite := cipherSuiteForID(CipherSuiteID(*serverHelloMsg.CipherSuiteID), cfg.customCipherSuites) if remoteCipherSuite == nil { return 0, &alert.Alert{Level: alert.Fatal, Description: alert.InsufficientSecurity}, errCipherSuiteNoIntersection } @@ -86,11 +110,11 @@ func flight3Parse(ctx context.Context, c flightConn, state *State, cache *handsh } state.cipherSuite = selectedCipherSuite - state.remoteRandom = h.Random + state.remoteRandom = serverHelloMsg.Random cfg.log.Tracef("[handshake] use cipher suite: %s", selectedCipherSuite.String()) - if len(h.SessionID) > 0 && bytes.Equal(state.SessionID, h.SessionID) { - return handleResumption(ctx, c, state, cache, cfg) + if len(serverHelloMsg.SessionID) > 0 && bytes.Equal(state.SessionID, serverHelloMsg.SessionID) { + return handleResumption(ctx, conn, state, cache, cfg) } if len(state.SessionID) > 0 { @@ -103,7 +127,7 @@ func flight3Parse(ctx context.Context, c flightConn, state *State, cache *handsh if cfg.sessionStore == nil { state.SessionID = []byte{} } else { - state.SessionID = h.SessionID + state.SessionID = serverHelloMsg.SessionID } state.masterSecret = []byte{} @@ -135,20 +159,27 @@ func flight3Parse(ctx context.Context, c flightConn, state *State, cache *handsh } if h, ok := msgs[handshake.TypeServerKeyExchange].(*handshake.MessageServerKeyExchange); ok { - alertPtr, err := handleServerKeyExchange(c, state, cfg, h) + alertPtr, err := handleServerKeyExchange(conn, state, cfg, h) if err != nil { return 0, alertPtr, err } } - if _, ok := msgs[handshake.TypeCertificateRequest].(*handshake.MessageCertificateRequest); ok { + if creq, ok := msgs[handshake.TypeCertificateRequest].(*handshake.MessageCertificateRequest); ok { + state.remoteCertRequestAlgs = creq.SignatureHashAlgorithms state.remoteRequestedCertificate = true } return flight5, nil, nil } -func handleResumption(ctx context.Context, c flightConn, state *State, cache *handshakeCache, cfg *handshakeConfig) (flightVal, *alert.Alert, error) { +func handleResumption( + ctx context.Context, + c flightConn, + state *State, + cache *handshakeCache, + cfg *handshakeConfig, +) (flightVal, *alert.Alert, error) { if err := state.initCipherSuite(); err != nil { return 0, &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, err } @@ -189,25 +220,36 @@ func handleResumption(ctx context.Context, c flightConn, state *State, cache *ha return flight5b, nil, nil } -func handleServerKeyExchange(_ flightConn, state *State, cfg *handshakeConfig, h *handshake.MessageServerKeyExchange) (*alert.Alert, error) { +//nolint:cyclop +func handleServerKeyExchange( + _ flightConn, + state *State, + cfg *handshakeConfig, + keyExchangeMessage *handshake.MessageServerKeyExchange, +) (*alert.Alert, error) { var err error if state.cipherSuite == nil { return &alert.Alert{Level: alert.Fatal, Description: alert.InsufficientSecurity}, errInvalidCipherSuite } - if cfg.localPSKCallback != nil { + if cfg.localPSKCallback != nil { //nolint:nestif var psk []byte - if psk, err = cfg.localPSKCallback(h.IdentityHint); err != nil { + if psk, err = cfg.localPSKCallback(keyExchangeMessage.IdentityHint); err != nil { return &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, err } - state.IdentityHint = h.IdentityHint + state.IdentityHint = keyExchangeMessage.IdentityHint switch state.cipherSuite.KeyExchangeAlgorithm() { case types.KeyExchangeAlgorithmPsk: state.preMasterSecret = prf.PSKPreMasterSecret(psk) case (types.KeyExchangeAlgorithmEcdhe | types.KeyExchangeAlgorithmPsk): - if state.localKeypair, err = elliptic.GenerateKeypair(h.NamedCurve); err != nil { + if state.localKeypair, err = elliptic.GenerateKeypair(keyExchangeMessage.NamedCurve); err != nil { return &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, err } - state.preMasterSecret, err = prf.EcdhePSKPreMasterSecret(psk, h.PublicKey, state.localKeypair.PrivateKey, state.localKeypair.Curve) + state.preMasterSecret, err = prf.EcdhePSKPreMasterSecret( + psk, + keyExchangeMessage.PublicKey, + state.localKeypair.PrivateKey, + state.localKeypair.Curve, + ) if err != nil { return &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, err } @@ -215,11 +257,15 @@ func handleServerKeyExchange(_ flightConn, state *State, cfg *handshakeConfig, h return &alert.Alert{Level: alert.Fatal, Description: alert.InsufficientSecurity}, errInvalidCipherSuite } } else { - if state.localKeypair, err = elliptic.GenerateKeypair(h.NamedCurve); err != nil { + if state.localKeypair, err = elliptic.GenerateKeypair(keyExchangeMessage.NamedCurve); err != nil { return &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, err } - if state.preMasterSecret, err = prf.PreMasterSecret(h.PublicKey, state.localKeypair.PrivateKey, state.localKeypair.Curve); err != nil { + if state.preMasterSecret, err = prf.PreMasterSecret( + keyExchangeMessage.PublicKey, + state.localKeypair.PrivateKey, + state.localKeypair.Curve, + ); err != nil { return &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, err } } @@ -227,7 +273,12 @@ func handleServerKeyExchange(_ flightConn, state *State, cfg *handshakeConfig, h return nil, nil //nolint:nilnil } -func flight3Generate(_ flightConn, state *State, _ *handshakeCache, cfg *handshakeConfig) ([]*packet, *alert.Alert, error) { +func flight3Generate( + _ flightConn, + state *State, + _ *handshakeCache, + cfg *handshakeConfig, +) ([]*packet, *alert.Alert, error) { extensions := []extension.Extension{ &extension.SupportedSignatureAlgorithms{ SignatureHashAlgorithms: cfg.localSignatureSchemes, @@ -236,10 +287,11 @@ func flight3Generate(_ flightConn, state *State, _ *handshakeCache, cfg *handsha RenegotiatedConnection: 0, }, } + if state.namedCurve != 0 { extensions = append(extensions, []extension.Extension{ &extension.SupportedEllipticCurves{ - EllipticCurves: []elliptic.Curve{elliptic.X25519, elliptic.P256, elliptic.P384}, + EllipticCurves: cfg.ellipticCurves, }, &extension.SupportedPointFormats{ PointFormats: []elliptic.CurvePointFormat{elliptic.CurvePointFormatUncompressed}, @@ -268,23 +320,37 @@ func flight3Generate(_ flightConn, state *State, _ *handshakeCache, cfg *handsha extensions = append(extensions, &extension.ALPN{ProtocolNameList: cfg.supportedProtocols}) } + // If we sent a connection ID on the first ClientHello, send it on the + // second. + if state.getLocalConnectionID() != nil { + extensions = append(extensions, &extension.ConnectionID{CID: state.getLocalConnectionID()}) + } + + clientHello := &handshake.MessageClientHello{ + Version: protocol.Version1_2, + SessionID: state.SessionID, + Cookie: state.cookie, + Random: state.localRandom, + CipherSuiteIDs: cipherSuiteIDs(cfg.localCipherSuites), + CompressionMethods: defaultCompressionMethods(), + Extensions: extensions, + } + + var content handshake.Handshake + + if cfg.clientHelloMessageHook != nil { + content = handshake.Handshake{Message: cfg.clientHelloMessageHook(*clientHello)} + } else { + content = handshake.Handshake{Message: clientHello} + } + return []*packet{ { record: &recordlayer.RecordLayer{ Header: recordlayer.Header{ Version: protocol.Version1_2, }, - Content: &handshake.Handshake{ - Message: &handshake.MessageClientHello{ - Version: protocol.Version1_2, - SessionID: state.SessionID, - Cookie: state.cookie, - Random: state.localRandom, - CipherSuiteIDs: cipherSuiteIDs(cfg.localCipherSuites), - CompressionMethods: defaultCompressionMethods(), - Extensions: extensions, - }, - }, + Content: &content, }, }, }, nil, nil diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/flight4bhandler.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/flight4bhandler.go similarity index 72% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/flight4bhandler.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/flight4bhandler.go index 6bbbc5972..681533b0e 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/flight4bhandler.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/flight4bhandler.go @@ -7,15 +7,21 @@ import ( "bytes" "context" - "github.com/pion/dtls/v2/pkg/crypto/prf" - "github.com/pion/dtls/v2/pkg/protocol" - "github.com/pion/dtls/v2/pkg/protocol/alert" - "github.com/pion/dtls/v2/pkg/protocol/extension" - "github.com/pion/dtls/v2/pkg/protocol/handshake" - "github.com/pion/dtls/v2/pkg/protocol/recordlayer" + "github.com/pion/dtls/v3/pkg/crypto/prf" + "github.com/pion/dtls/v3/pkg/protocol" + "github.com/pion/dtls/v3/pkg/protocol/alert" + "github.com/pion/dtls/v3/pkg/protocol/extension" + "github.com/pion/dtls/v3/pkg/protocol/handshake" + "github.com/pion/dtls/v3/pkg/protocol/recordlayer" ) -func flight4bParse(_ context.Context, _ flightConn, state *State, cache *handshakeCache, cfg *handshakeConfig) (flightVal, *alert.Alert, error) { +func flight4bParse( + _ context.Context, + _ flightConn, + state *State, + cache *handshakeCache, + cfg *handshakeConfig, +) (flightVal, *alert.Alert, error) { _, msgs, ok := cache.fullPullMap(state.handshakeRecvSequence, state.cipherSuite, handshakeCachePullRule{handshake.TypeFinished, cfg.initialEpoch + 1, true, false}, ) @@ -47,7 +53,13 @@ func flight4bParse(_ context.Context, _ flightConn, state *State, cache *handsha return flight4b, nil, nil } -func flight4bGenerate(_ flightConn, state *State, cache *handshakeCache, cfg *handshakeConfig) ([]*packet, *alert.Alert, error) { +//nolint:cyclop +func flight4bGenerate( + _ flightConn, + state *State, + cache *handshakeCache, + cfg *handshakeConfig, +) ([]*packet, *alert.Alert, error) { var pkts []*packet extensions := []extension.Extension{&extension.RenegotiationInfo{ @@ -59,9 +71,10 @@ func flight4bGenerate(_ flightConn, state *State, cache *handshakeCache, cfg *ha Supported: true, }) } - if state.srtpProtectionProfile != 0 { + if state.getSRTPProtectionProfile() != 0 { extensions = append(extensions, &extension.UseSRTP{ - ProtectionProfiles: []SRTPProtectionProfile{state.srtpProtectionProfile}, + ProtectionProfiles: []SRTPProtectionProfile{state.getSRTPProtectionProfile()}, + MasterKeyIdentifier: cfg.localSRTPMasterKeyIdentifier, }) } @@ -77,18 +90,24 @@ func flight4bGenerate(_ flightConn, state *State, cache *handshakeCache, cfg *ha } cipherSuiteID := uint16(state.cipherSuite.ID()) - serverHello := &handshake.Handshake{ - Message: &handshake.MessageServerHello{ - Version: protocol.Version1_2, - Random: state.localRandom, - SessionID: state.SessionID, - CipherSuiteID: &cipherSuiteID, - CompressionMethod: defaultCompressionMethods()[0], - Extensions: extensions, - }, + var serverHello handshake.Handshake + + serverHelloMessage := &handshake.MessageServerHello{ + Version: protocol.Version1_2, + Random: state.localRandom, + SessionID: state.SessionID, + CipherSuiteID: &cipherSuiteID, + CompressionMethod: defaultCompressionMethods()[0], + Extensions: extensions, } - serverHello.Header.MessageSequence = uint16(state.handshakeSendSequence) + if cfg.serverHelloMessageHook != nil { + serverHello = handshake.Handshake{Message: cfg.serverHelloMessageHook(*serverHelloMessage)} + } else { + serverHello = handshake.Handshake{Message: serverHelloMessage} + } + + serverHello.Header.MessageSequence = uint16(state.handshakeSendSequence) //nolint:gosec // G115 if len(state.localVerifyData) == 0 { plainText := cache.pullAndMerge( @@ -112,7 +131,7 @@ func flight4bGenerate(_ flightConn, state *State, cache *handshakeCache, cfg *ha Header: recordlayer.Header{ Version: protocol.Version1_2, }, - Content: serverHello, + Content: &serverHello, }, }, &packet{ diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/flight4handler.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/flight4handler.go similarity index 72% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/flight4handler.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/flight4handler.go index 67a486461..f75373fc2 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/flight4handler.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/flight4handler.go @@ -5,22 +5,30 @@ package dtls import ( "context" + "crypto" "crypto/rand" "crypto/x509" - "github.com/pion/dtls/v2/internal/ciphersuite" - "github.com/pion/dtls/v2/pkg/crypto/clientcertificate" - "github.com/pion/dtls/v2/pkg/crypto/elliptic" - "github.com/pion/dtls/v2/pkg/crypto/prf" - "github.com/pion/dtls/v2/pkg/crypto/signaturehash" - "github.com/pion/dtls/v2/pkg/protocol" - "github.com/pion/dtls/v2/pkg/protocol/alert" - "github.com/pion/dtls/v2/pkg/protocol/extension" - "github.com/pion/dtls/v2/pkg/protocol/handshake" - "github.com/pion/dtls/v2/pkg/protocol/recordlayer" + "github.com/pion/dtls/v3/internal/ciphersuite" + "github.com/pion/dtls/v3/pkg/crypto/clientcertificate" + "github.com/pion/dtls/v3/pkg/crypto/elliptic" + "github.com/pion/dtls/v3/pkg/crypto/prf" + "github.com/pion/dtls/v3/pkg/crypto/signaturehash" + "github.com/pion/dtls/v3/pkg/protocol" + "github.com/pion/dtls/v3/pkg/protocol/alert" + "github.com/pion/dtls/v3/pkg/protocol/extension" + "github.com/pion/dtls/v3/pkg/protocol/handshake" + "github.com/pion/dtls/v3/pkg/protocol/recordlayer" ) -func flight4Parse(ctx context.Context, c flightConn, state *State, cache *handshakeCache, cfg *handshakeConfig) (flightVal, *alert.Alert, error) { //nolint:gocognit +//nolint:gocognit,gocyclo,lll,cyclop,maintidx +func flight4Parse( + ctx context.Context, + conn flightConn, + state *State, + cache *handshakeCache, + cfg *handshakeConfig, +) (flightVal, *alert.Alert, error) { seq, msgs, ok := cache.fullPullMap(state.handshakeRecvSequence, state.cipherSuite, handshakeCachePullRule{handshake.TypeCertificate, cfg.initialEpoch, true, true}, handshakeCachePullRule{handshake.TypeClientKeyExchange, cfg.initialEpoch, true, false}, @@ -47,7 +55,8 @@ func flight4Parse(ctx context.Context, c flightConn, state *State, cache *handsh state.SessionID = nil } - if h, hasCertVerify := msgs[handshake.TypeCertificateVerify].(*handshake.MessageCertificateVerify); hasCertVerify { + //nolint:nestif + if verify, hasVerify := msgs[handshake.TypeCertificateVerify].(*handshake.MessageCertificateVerify); hasVerify { if state.PeerCertificates == nil { return 0, &alert.Alert{Level: alert.Fatal, Description: alert.NoCertificate}, errCertificateVerifyNoCertificate } @@ -66,8 +75,9 @@ func flight4Parse(ctx context.Context, c flightConn, state *State, cache *handsh // Verify that the pair of hash algorithm and signiture is listed. var validSignatureScheme bool for _, ss := range cfg.localSignatureSchemes { - if ss.Hash == h.HashAlgorithm && ss.Signature == h.SignatureAlgorithm { + if ss.Hash == verify.HashAlgorithm && ss.Signature == verify.SignatureAlgorithm { validSignatureScheme = true + break } } @@ -75,7 +85,12 @@ func flight4Parse(ctx context.Context, c flightConn, state *State, cache *handsh return 0, &alert.Alert{Level: alert.Fatal, Description: alert.InsufficientSecurity}, errNoAvailableSignatureSchemes } - if err := verifyCertificateVerify(plainText, h.HashAlgorithm, h.Signature, state.PeerCertificates); err != nil { + if err := verifyCertificateVerify( + plainText, + verify.HashAlgorithm, + verify.Signature, + state.PeerCertificates, + ); err != nil { return 0, &alert.Alert{Level: alert.Fatal, Description: alert.BadCertificate}, err } var chains [][]*x509.Certificate @@ -99,7 +114,7 @@ func flight4Parse(ctx context.Context, c flightConn, state *State, cache *handsh return 0, nil, nil } - if !state.cipherSuite.IsInitialized() { + if !state.cipherSuite.IsInitialized() { //nolint:nestif serverRandom := state.localRandom.MarshalFixed() clientRandom := state.remoteRandom.MarshalFixed() @@ -115,14 +130,23 @@ func flight4Parse(ctx context.Context, c flightConn, state *State, cache *handsh case CipherSuiteKeyExchangeAlgorithmPsk: preMasterSecret = prf.PSKPreMasterSecret(psk) case (CipherSuiteKeyExchangeAlgorithmPsk | CipherSuiteKeyExchangeAlgorithmEcdhe): - if preMasterSecret, err = prf.EcdhePSKPreMasterSecret(psk, clientKeyExchange.PublicKey, state.localKeypair.PrivateKey, state.localKeypair.Curve); err != nil { + if preMasterSecret, err = prf.EcdhePSKPreMasterSecret( + psk, + clientKeyExchange.PublicKey, + state.localKeypair.PrivateKey, + state.localKeypair.Curve, + ); err != nil { return 0, &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, err } default: return 0, &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, errInvalidCipherSuite } } else { - preMasterSecret, err = prf.PreMasterSecret(clientKeyExchange.PublicKey, state.localKeypair.PrivateKey, state.localKeypair.Curve) + preMasterSecret, err = prf.PreMasterSecret( + clientKeyExchange.PublicKey, + state.localKeypair.PrivateKey, + state.localKeypair.Curve, + ) if err != nil { return 0, &alert.Alert{Level: alert.Fatal, Description: alert.IllegalParameter}, err } @@ -140,7 +164,12 @@ func flight4Parse(ctx context.Context, c flightConn, state *State, cache *handsh return 0, &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, err } } else { - state.masterSecret, err = prf.MasterSecret(preMasterSecret, clientRandom[:], serverRandom[:], state.cipherSuite.HashFunc()) + state.masterSecret, err = prf.MasterSecret( + preMasterSecret, + clientRandom[:], + serverRandom[:], + state.cipherSuite.HashFunc(), + ) if err != nil { return 0, &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, err } @@ -164,7 +193,7 @@ func flight4Parse(ctx context.Context, c flightConn, state *State, cache *handsh } // Now, encrypted packets can be handled - if err := c.handleQueuedPackets(ctx); err != nil { + if err := conn.handleQueuedPackets(ctx); err != nil { return 0, &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, err } @@ -181,12 +210,17 @@ func flight4Parse(ctx context.Context, c flightConn, state *State, cache *handsh return 0, &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, nil } - if state.cipherSuite.AuthenticationType() == CipherSuiteAuthenticationTypeAnonymous { + if state.cipherSuite.AuthenticationType() == CipherSuiteAuthenticationTypeAnonymous { //nolint:nestif if cfg.verifyConnection != nil { - if err := cfg.verifyConnection(state.clone()); err != nil { + stateClone, err := state.clone() + if err != nil { + return 0, &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, err + } + if err := cfg.verifyConnection(stateClone); err != nil { return 0, &alert.Alert{Level: alert.Fatal, Description: alert.BadCertificate}, err } } + return flight6, nil, nil } @@ -210,7 +244,11 @@ func flight4Parse(ctx context.Context, c flightConn, state *State, cache *handsh // go to flight6 } if cfg.verifyConnection != nil { - if err := cfg.verifyConnection(state.clone()); err != nil { + stateClone, err := state.clone() + if err != nil { + return 0, &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, err + } + if err := cfg.verifyConnection(stateClone); err != nil { return 0, &alert.Alert{Level: alert.Fatal, Description: alert.BadCertificate}, err } } @@ -218,7 +256,13 @@ func flight4Parse(ctx context.Context, c flightConn, state *State, cache *handsh return flight6, nil, nil } -func flight4Generate(_ flightConn, state *State, _ *handshakeCache, cfg *handshakeConfig) ([]*packet, *alert.Alert, error) { +//nolint:gocognit,cyclop,maintidx +func flight4Generate( + _ flightConn, + state *State, + _ *handshakeCache, + cfg *handshakeConfig, +) ([]*packet, *alert.Alert, error) { extensions := []extension.Extension{&extension.RenegotiationInfo{ RenegotiatedConnection: 0, }} @@ -228,9 +272,10 @@ func flight4Generate(_ flightConn, state *State, _ *handshakeCache, cfg *handsha Supported: true, }) } - if state.srtpProtectionProfile != 0 { + if state.getSRTPProtectionProfile() != 0 { extensions = append(extensions, &extension.UseSRTP{ - ProtectionProfiles: []SRTPProtectionProfile{state.srtpProtectionProfile}, + ProtectionProfiles: []SRTPProtectionProfile{state.getSRTPProtectionProfile()}, + MasterKeyIdentifier: cfg.localSRTPMasterKeyIdentifier, }) } if state.cipherSuite.AuthenticationType() == CipherSuiteAuthenticationTypeCertificate { @@ -250,6 +295,15 @@ func flight4Generate(_ flightConn, state *State, _ *handshakeCache, cfg *handsha state.NegotiatedProtocol = selectedProto } + // If we have a connection ID generator, we are willing to use connection + // IDs. We already know whether the client supports connection IDs from + // parsing the ClientHello, so avoid setting local connection ID if the + // client won't send it. + if cfg.connectionIDGenerator != nil && state.remoteConnectionID != nil { + state.setLocalConnectionID(cfg.connectionIDGenerator()) + extensions = append(extensions, &extension.ConnectionID{CID: state.getLocalConnectionID()}) + } + var pkts []*packet cipherSuiteID := uint16(state.cipherSuite.ID()) @@ -260,21 +314,29 @@ func flight4Generate(_ flightConn, state *State, _ *handshakeCache, cfg *handsha } } + serverHello := &handshake.MessageServerHello{ + Version: protocol.Version1_2, + Random: state.localRandom, + SessionID: state.SessionID, + CipherSuiteID: &cipherSuiteID, + CompressionMethod: defaultCompressionMethods()[0], + Extensions: extensions, + } + + var content handshake.Handshake + + if cfg.serverHelloMessageHook != nil { + content = handshake.Handshake{Message: cfg.serverHelloMessageHook(*serverHello)} + } else { + content = handshake.Handshake{Message: serverHello} + } + pkts = append(pkts, &packet{ record: &recordlayer.RecordLayer{ Header: recordlayer.Header{ Version: protocol.Version1_2, }, - Content: &handshake.Handshake{ - Message: &handshake.MessageServerHello{ - Version: protocol.Version1_2, - Random: state.localRandom, - SessionID: state.SessionID, - CipherSuiteID: &cipherSuiteID, - CompressionMethod: defaultCompressionMethods()[0], - Extensions: extensions, - }, - }, + Content: &content, }, }) @@ -283,6 +345,7 @@ func flight4Generate(_ flightConn, state *State, _ *handshakeCache, cfg *handsha certificate, err := cfg.getCertificate(&ClientHelloInfo{ ServerName: state.serverName, CipherSuites: []ciphersuite.ID{state.cipherSuite.ID()}, + RandomBytes: state.remoteRandom.RandomBytes, }) if err != nil { return nil, &alert.Alert{Level: alert.Fatal, Description: alert.HandshakeFailure}, err @@ -304,13 +367,25 @@ func flight4Generate(_ flightConn, state *State, _ *handshakeCache, cfg *handsha serverRandom := state.localRandom.MarshalFixed() clientRandom := state.remoteRandom.MarshalFixed() + signer, ok := certificate.PrivateKey.(crypto.Signer) + if !ok { + return nil, &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, errInvalidPrivateKey + } + // Find compatible signature scheme - signatureHashAlgo, err := signaturehash.SelectSignatureScheme(cfg.localSignatureSchemes, certificate.PrivateKey) + signatureHashAlgo, err := signaturehash.SelectSignatureScheme(cfg.localSignatureSchemes, signer) if err != nil { return nil, &alert.Alert{Level: alert.Fatal, Description: alert.InsufficientSecurity}, err } - signature, err := generateKeySignature(clientRandom[:], serverRandom[:], state.localKeypair.PublicKey, state.namedCurve, certificate.PrivateKey, signatureHashAlgo.Hash) + signature, err := generateKeySignature( + clientRandom[:], + serverRandom[:], + state.localKeypair.PublicKey, + state.namedCurve, + signer, + signatureHashAlgo.Hash, + ) if err != nil { return nil, &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, err } @@ -342,25 +417,37 @@ func flight4Generate(_ flightConn, state *State, _ *handshakeCache, cfg *handsha // an appropriate certificate to give to us. var certificateAuthorities [][]byte if cfg.clientCAs != nil { - // nolint:staticcheck // ignoring tlsCert.RootCAs.Subjects is deprecated ERR because cert does not come from SystemCertPool and it's ok if certificate authorities is empty. + // nolint:staticcheck // ignoring tlsCert.RootCAs.Subjects is deprecated ERR + // because cert does not come from SystemCertPool and it's ok if certificate + // authorities is empty. certificateAuthorities = cfg.clientCAs.Subjects() } + + certReq := &handshake.MessageCertificateRequest{ + CertificateTypes: []clientcertificate.Type{clientcertificate.RSASign, clientcertificate.ECDSASign}, + SignatureHashAlgorithms: cfg.localSignatureSchemes, + CertificateAuthoritiesNames: certificateAuthorities, + } + + var content handshake.Handshake + + if cfg.certificateRequestMessageHook != nil { + content = handshake.Handshake{Message: cfg.certificateRequestMessageHook(*certReq)} + } else { + content = handshake.Handshake{Message: certReq} + } + pkts = append(pkts, &packet{ record: &recordlayer.RecordLayer{ Header: recordlayer.Header{ Version: protocol.Version1_2, }, - Content: &handshake.Handshake{ - Message: &handshake.MessageCertificateRequest{ - CertificateTypes: []clientcertificate.Type{clientcertificate.RSASign, clientcertificate.ECDSASign}, - SignatureHashAlgorithms: cfg.localSignatureSchemes, - CertificateAuthoritiesNames: certificateAuthorities, - }, - }, + Content: &content, }, }) } - case cfg.localPSKIdentityHint != nil || state.cipherSuite.KeyExchangeAlgorithm().Has(CipherSuiteKeyExchangeAlgorithmEcdhe): + case cfg.localPSKIdentityHint != nil || + state.cipherSuite.KeyExchangeAlgorithm().Has(CipherSuiteKeyExchangeAlgorithmEcdhe): // To help the client in selecting which identity to use, the server // can provide a "PSK identity hint" in the ServerKeyExchange message. // If no hint is provided and cipher suite doesn't use elliptic curve, diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/flight5bhandler.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/flight5bhandler.go similarity index 77% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/flight5bhandler.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/flight5bhandler.go index ddd37324c..db6de367c 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/flight5bhandler.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/flight5bhandler.go @@ -6,14 +6,20 @@ package dtls import ( "context" - "github.com/pion/dtls/v2/pkg/crypto/prf" - "github.com/pion/dtls/v2/pkg/protocol" - "github.com/pion/dtls/v2/pkg/protocol/alert" - "github.com/pion/dtls/v2/pkg/protocol/handshake" - "github.com/pion/dtls/v2/pkg/protocol/recordlayer" + "github.com/pion/dtls/v3/pkg/crypto/prf" + "github.com/pion/dtls/v3/pkg/protocol" + "github.com/pion/dtls/v3/pkg/protocol/alert" + "github.com/pion/dtls/v3/pkg/protocol/handshake" + "github.com/pion/dtls/v3/pkg/protocol/recordlayer" ) -func flight5bParse(_ context.Context, _ flightConn, state *State, cache *handshakeCache, cfg *handshakeConfig) (flightVal, *alert.Alert, error) { +func flight5bParse( + _ context.Context, + _ flightConn, + state *State, + cache *handshakeCache, + cfg *handshakeConfig, +) (flightVal, *alert.Alert, error) { _, msgs, ok := cache.fullPullMap(state.handshakeRecvSequence-1, state.cipherSuite, handshakeCachePullRule{handshake.TypeFinished, cfg.initialEpoch + 1, false, false}, ) @@ -30,7 +36,12 @@ func flight5bParse(_ context.Context, _ flightConn, state *State, cache *handsha return flight5b, nil, nil } -func flight5bGenerate(_ flightConn, state *State, cache *handshakeCache, cfg *handshakeConfig) ([]*packet, *alert.Alert, error) { //nolint:gocognit +func flight5bGenerate( + _ flightConn, + state *State, + cache *handshakeCache, + cfg *handshakeConfig, +) ([]*packet, *alert.Alert, error) { //nolint:gocognit var pkts []*packet pkts = append(pkts, diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/flight5handler.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/flight5handler.go similarity index 79% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/flight5handler.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/flight5handler.go index e8adf4f36..1b85b06b9 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/flight5handler.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/flight5handler.go @@ -9,15 +9,21 @@ import ( "crypto" "crypto/x509" - "github.com/pion/dtls/v2/pkg/crypto/prf" - "github.com/pion/dtls/v2/pkg/crypto/signaturehash" - "github.com/pion/dtls/v2/pkg/protocol" - "github.com/pion/dtls/v2/pkg/protocol/alert" - "github.com/pion/dtls/v2/pkg/protocol/handshake" - "github.com/pion/dtls/v2/pkg/protocol/recordlayer" + "github.com/pion/dtls/v3/pkg/crypto/prf" + "github.com/pion/dtls/v3/pkg/crypto/signaturehash" + "github.com/pion/dtls/v3/pkg/protocol" + "github.com/pion/dtls/v3/pkg/protocol/alert" + "github.com/pion/dtls/v3/pkg/protocol/handshake" + "github.com/pion/dtls/v3/pkg/protocol/recordlayer" ) -func flight5Parse(_ context.Context, c flightConn, state *State, cache *handshakeCache, cfg *handshakeConfig) (flightVal, *alert.Alert, error) { +func flight5Parse( + _ context.Context, + conn flightConn, + state *State, + cache *handshakeCache, + cfg *handshakeConfig, +) (flightVal, *alert.Alert, error) { _, msgs, ok := cache.fullPullMap(state.handshakeRecvSequence, state.cipherSuite, handshakeCachePullRule{handshake.TypeFinished, cfg.initialEpoch + 1, false, false}, ) @@ -57,7 +63,7 @@ func flight5Parse(_ context.Context, c flightConn, state *State, cache *handshak Secret: state.masterSecret, } cfg.log.Tracef("[handshake] save new session: %x", s.ID) - if err := cfg.sessionStore.Set(c.sessionKey(), s); err != nil { + if err := cfg.sessionStore.Set(conn.sessionKey(), s); err != nil { return 0, &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, err } } @@ -65,17 +71,23 @@ func flight5Parse(_ context.Context, c flightConn, state *State, cache *handshak return flight5, nil, nil } -func flight5Generate(c flightConn, state *State, cache *handshakeCache, cfg *handshakeConfig) ([]*packet, *alert.Alert, error) { //nolint:gocognit - var privateKey crypto.PrivateKey +//nolint:gocognit,cyclop,maintidx +func flight5Generate( + conn flightConn, + state *State, + cache *handshakeCache, + cfg *handshakeConfig, +) ([]*packet, *alert.Alert, error) { + var signer crypto.Signer var pkts []*packet - if state.remoteRequestedCertificate { + if state.remoteRequestedCertificate { //nolint:nestif _, msgs, ok := cache.fullPullMap(state.handshakeRecvSequence-2, state.cipherSuite, handshakeCachePullRule{handshake.TypeCertificateRequest, cfg.initialEpoch, false, false}) if !ok { return nil, &alert.Alert{Level: alert.Fatal, Description: alert.HandshakeFailure}, errClientCertificateRequired } reqInfo := CertificateRequestInfo{} - if r, ok := msgs[handshake.TypeCertificateRequest].(*handshake.MessageCertificateRequest); ok { + if r, ok2 := msgs[handshake.TypeCertificateRequest].(*handshake.MessageCertificateRequest); ok2 { reqInfo.AcceptableCAs = r.CertificateAuthoritiesNames } else { return nil, &alert.Alert{Level: alert.Fatal, Description: alert.HandshakeFailure}, errClientCertificateRequired @@ -88,7 +100,10 @@ func flight5Generate(c flightConn, state *State, cache *handshakeCache, cfg *han return nil, &alert.Alert{Level: alert.Fatal, Description: alert.HandshakeFailure}, errNotAcceptableCertificateChain } if certificate.Certificate != nil { - privateKey = certificate.PrivateKey + signer, ok = certificate.PrivateKey.(crypto.Signer) + if !ok { + return nil, &alert.Alert{Level: alert.Fatal, Description: alert.HandshakeFailure}, errInvalidPrivateKey + } } pkts = append(pkts, &packet{ @@ -135,7 +150,7 @@ func flight5Generate(c flightConn, state *State, cache *handshakeCache, cfg *han // handshakeMessageServerKeyExchange is optional for PSK if len(serverKeyExchangeData) == 0 { - alertPtr, err := handleServerKeyExchange(c, state, cfg, &handshake.MessageServerKeyExchange{}) + alertPtr, err := handleServerKeyExchange(conn, state, cfg, &handshake.MessageServerKeyExchange{}) if err != nil { return nil, alertPtr, err } @@ -158,7 +173,7 @@ func flight5Generate(c flightConn, state *State, cache *handshakeCache, cfg *han // Append not-yet-sent packets merged := []byte{} - seqPred := uint16(state.handshakeSendSequence) + seqPred := uint16(state.handshakeSendSequence) //nolint:gosec // G115 for _, p := range pkts { h, ok := p.record.Content.(*handshake.Handshake) if !ok { @@ -173,14 +188,14 @@ func flight5Generate(c flightConn, state *State, cache *handshakeCache, cfg *han merged = append(merged, raw...) } - if alertPtr, err := initalizeCipherSuite(state, cache, cfg, serverKeyExchange, merged); err != nil { + if alertPtr, err := initializeCipherSuite(state, cache, cfg, serverKeyExchange, merged); err != nil { return nil, alertPtr, err } // If the client has sent a certificate with signing ability, a digitally-signed // CertificateVerify message is sent to explicitly verify possession of the // private key in the certificate. - if state.remoteRequestedCertificate && privateKey != nil { + if state.remoteRequestedCertificate && signer != nil { plainText := append(cache.pullAndMerge( handshakeCachePullRule{handshake.TypeClientHello, cfg.initialEpoch, true, false}, handshakeCachePullRule{handshake.TypeServerHello, cfg.initialEpoch, false, false}, @@ -193,18 +208,19 @@ func flight5Generate(c flightConn, state *State, cache *handshakeCache, cfg *han ), merged...) // Find compatible signature scheme - signatureHashAlgo, err := signaturehash.SelectSignatureScheme(cfg.localSignatureSchemes, privateKey) + + signatureHashAlgo, err := signaturehash.SelectSignatureScheme(state.remoteCertRequestAlgs, signer) if err != nil { return nil, &alert.Alert{Level: alert.Fatal, Description: alert.InsufficientSecurity}, err } - certVerify, err := generateCertificateVerify(plainText, privateKey, signatureHashAlgo.Hash) + certVerify, err := generateCertificateVerify(plainText, signer, signatureHashAlgo.Hash) if err != nil { return nil, &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, err } state.localCertificatesVerify = certVerify - p := &packet{ + pkt := &packet{ record: &recordlayer.RecordLayer{ Header: recordlayer.Header{ Version: protocol.Version1_2, @@ -218,9 +234,9 @@ func flight5Generate(c flightConn, state *State, cache *handshakeCache, cfg *han }, }, } - pkts = append(pkts, p) + pkts = append(pkts, pkt) - h, ok := p.record.Content.(*handshake.Handshake) + h, ok := pkt.record.Content.(*handshake.Handshake) if !ok { return nil, &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, errInvalidContentType } @@ -258,7 +274,11 @@ func flight5Generate(c flightConn, state *State, cache *handshakeCache, cfg *han ) var err error - state.localVerifyData, err = prf.VerifyDataClient(state.masterSecret, append(plainText, merged...), state.cipherSuite.HashFunc()) + state.localVerifyData, err = prf.VerifyDataClient( + state.masterSecret, + append(plainText, merged...), + state.cipherSuite.HashFunc(), + ) if err != nil { return nil, &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, err } @@ -277,6 +297,7 @@ func flight5Generate(c flightConn, state *State, cache *handshakeCache, cfg *han }, }, }, + shouldWrapCID: len(state.remoteConnectionID) > 0, shouldEncrypt: true, resetLocalSequenceNumber: true, }) @@ -284,7 +305,14 @@ func flight5Generate(c flightConn, state *State, cache *handshakeCache, cfg *han return pkts, nil, nil } -func initalizeCipherSuite(state *State, cache *handshakeCache, cfg *handshakeConfig, h *handshake.MessageServerKeyExchange, sendingPlainText []byte) (*alert.Alert, error) { //nolint:gocognit +//nolint:gocognit,cyclop +func initializeCipherSuite( + state *State, + cache *handshakeCache, + cfg *handshakeConfig, + handshakeKeyExchange *handshake.MessageServerKeyExchange, + sendingPlainText []byte, +) (*alert.Alert, error) { if state.cipherSuite.IsInitialized() { return nil, nil //nolint } @@ -306,18 +334,24 @@ func initalizeCipherSuite(state *State, cache *handshakeCache, cfg *handshakeCon return &alert.Alert{Level: alert.Fatal, Description: alert.IllegalParameter}, err } } else { - state.masterSecret, err = prf.MasterSecret(state.preMasterSecret, clientRandom[:], serverRandom[:], state.cipherSuite.HashFunc()) + state.masterSecret, err = prf.MasterSecret( + state.preMasterSecret, + clientRandom[:], + serverRandom[:], + state.cipherSuite.HashFunc(), + ) if err != nil { return &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, err } } - if state.cipherSuite.AuthenticationType() == CipherSuiteAuthenticationTypeCertificate { + if state.cipherSuite.AuthenticationType() == CipherSuiteAuthenticationTypeCertificate { //nolint:nestif // Verify that the pair of hash algorithm and signiture is listed. var validSignatureScheme bool for _, ss := range cfg.localSignatureSchemes { - if ss.Hash == h.HashAlgorithm && ss.Signature == h.SignatureAlgorithm { + if ss.Hash == handshakeKeyExchange.HashAlgorithm && ss.Signature == handshakeKeyExchange.SignatureAlgorithm { validSignatureScheme = true + break } } @@ -325,8 +359,19 @@ func initalizeCipherSuite(state *State, cache *handshakeCache, cfg *handshakeCon return &alert.Alert{Level: alert.Fatal, Description: alert.InsufficientSecurity}, errNoAvailableSignatureSchemes } - expectedMsg := valueKeyMessage(clientRandom[:], serverRandom[:], h.PublicKey, h.NamedCurve) - if err = verifyKeySignature(expectedMsg, h.Signature, h.HashAlgorithm, state.PeerCertificates); err != nil { + expectedMsg := valueKeyMessage( + clientRandom[:], + serverRandom[:], + handshakeKeyExchange.PublicKey, + handshakeKeyExchange.NamedCurve, + ) + if err = verifyKeySignature( + expectedMsg, + handshakeKeyExchange. + Signature, + handshakeKeyExchange.HashAlgorithm, + state.PeerCertificates, + ); err != nil { return &alert.Alert{Level: alert.Fatal, Description: alert.BadCertificate}, err } var chains [][]*x509.Certificate @@ -342,8 +387,12 @@ func initalizeCipherSuite(state *State, cache *handshakeCache, cfg *handshakeCon } } if cfg.verifyConnection != nil { - if err = cfg.verifyConnection(state.clone()); err != nil { - return &alert.Alert{Level: alert.Fatal, Description: alert.BadCertificate}, err + stateClone, errC := state.clone() + if errC != nil { + return &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, errC + } + if errC = cfg.verifyConnection(stateClone); errC != nil { + return &alert.Alert{Level: alert.Fatal, Description: alert.BadCertificate}, errC } } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/flight6handler.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/flight6handler.go similarity index 81% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/flight6handler.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/flight6handler.go index 57ac14360..d7828e749 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/flight6handler.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/flight6handler.go @@ -6,14 +6,20 @@ package dtls import ( "context" - "github.com/pion/dtls/v2/pkg/crypto/prf" - "github.com/pion/dtls/v2/pkg/protocol" - "github.com/pion/dtls/v2/pkg/protocol/alert" - "github.com/pion/dtls/v2/pkg/protocol/handshake" - "github.com/pion/dtls/v2/pkg/protocol/recordlayer" + "github.com/pion/dtls/v3/pkg/crypto/prf" + "github.com/pion/dtls/v3/pkg/protocol" + "github.com/pion/dtls/v3/pkg/protocol/alert" + "github.com/pion/dtls/v3/pkg/protocol/handshake" + "github.com/pion/dtls/v3/pkg/protocol/recordlayer" ) -func flight6Parse(_ context.Context, _ flightConn, state *State, cache *handshakeCache, cfg *handshakeConfig) (flightVal, *alert.Alert, error) { +func flight6Parse( + _ context.Context, + _ flightConn, + state *State, + cache *handshakeCache, + cfg *handshakeConfig, +) (flightVal, *alert.Alert, error) { _, msgs, ok := cache.fullPullMap(state.handshakeRecvSequence-1, state.cipherSuite, handshakeCachePullRule{handshake.TypeFinished, cfg.initialEpoch + 1, true, false}, ) @@ -30,7 +36,12 @@ func flight6Parse(_ context.Context, _ flightConn, state *State, cache *handshak return flight6, nil, nil } -func flight6Generate(_ flightConn, state *State, cache *handshakeCache, cfg *handshakeConfig) ([]*packet, *alert.Alert, error) { +func flight6Generate( + _ flightConn, + state *State, + cache *handshakeCache, + cfg *handshakeConfig, +) ([]*packet, *alert.Alert, error) { var pkts []*packet pkts = append(pkts, @@ -77,9 +88,11 @@ func flight6Generate(_ flightConn, state *State, cache *handshakeCache, cfg *han }, }, }, + shouldWrapCID: len(state.remoteConnectionID) > 0, shouldEncrypt: true, resetLocalSequenceNumber: true, }, ) + return pkts, nil, nil } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/flighthandler.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/flighthandler.go similarity index 78% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/flighthandler.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/flighthandler.go index ceb4a992b..b90cebd3b 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/flighthandler.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/flighthandler.go @@ -6,16 +6,22 @@ package dtls import ( "context" - "github.com/pion/dtls/v2/pkg/protocol/alert" + "github.com/pion/dtls/v3/pkg/protocol/alert" ) -// Parse received handshakes and return next flightVal -type flightParser func(context.Context, flightConn, *State, *handshakeCache, *handshakeConfig) (flightVal, *alert.Alert, error) +// Parse received handshakes and return next flightVal. +type flightParser func( + context.Context, + flightConn, + *State, + *handshakeCache, + *handshakeConfig, +) (flightVal, *alert.Alert, error) -// Generate flights +// Generate flights. type flightGenerator func(flightConn, *State, *handshakeCache, *handshakeConfig) ([]*packet, *alert.Alert, error) -func (f flightVal) getFlightParser() (flightParser, error) { +func (f flightVal) getFlightParser() (flightParser, error) { //nolint:cyclop switch f { case flight0: return flight0Parse, nil @@ -40,7 +46,7 @@ func (f flightVal) getFlightParser() (flightParser, error) { } } -func (f flightVal) getFlightGenerator() (gen flightGenerator, retransmit bool, err error) { +func (f flightVal) getFlightGenerator() (gen flightGenerator, retransmit bool, err error) { //nolint:cyclop switch f { case flight0: return flight0Generate, true, nil diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/fragment_buffer.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/fragment_buffer.go similarity index 80% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/fragment_buffer.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/fragment_buffer.go index f20033758..497d97107 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/fragment_buffer.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/fragment_buffer.go @@ -4,12 +4,12 @@ package dtls import ( - "github.com/pion/dtls/v2/pkg/protocol" - "github.com/pion/dtls/v2/pkg/protocol/handshake" - "github.com/pion/dtls/v2/pkg/protocol/recordlayer" + "github.com/pion/dtls/v3/pkg/protocol" + "github.com/pion/dtls/v3/pkg/protocol/handshake" + "github.com/pion/dtls/v3/pkg/protocol/recordlayer" ) -// 2 megabytes +// 2 megabytes. const fragmentBufferMaxSize = 2000000 type fragment struct { @@ -29,7 +29,7 @@ func newFragmentBuffer() *fragmentBuffer { return &fragmentBuffer{cache: map[uint16][]*fragment{}} } -// current total size of buffer +// current total size of buffer. func (f *fragmentBuffer) size() int { size := 0 for i := range f.cache { @@ -37,32 +37,37 @@ func (f *fragmentBuffer) size() int { size += len(f.cache[i][j].data) } } + return size } // Attempts to push a DTLS packet to the fragmentBuffer // when it returns true it means the fragmentBuffer has inserted and the buffer shouldn't be handled -// when an error returns it is fatal, and the DTLS connection should be stopped -func (f *fragmentBuffer) push(buf []byte) (bool, error) { +// when an error returns it is fatal, and the DTLS connection should be stopped. +func (f *fragmentBuffer) push(buf []byte) (isHandshake, isRetransmit bool, err error) { if f.size()+len(buf) >= fragmentBufferMaxSize { - return false, errFragmentBufferOverflow + return false, false, errFragmentBufferOverflow } frag := new(fragment) if err := frag.recordLayerHeader.Unmarshal(buf); err != nil { - return false, err + return false, false, err } // fragment isn't a handshake, we don't need to handle it if frag.recordLayerHeader.ContentType != protocol.ContentTypeHandshake { - return false, nil + return false, false, nil } - for buf = buf[recordlayer.HeaderSize:]; len(buf) != 0; frag = new(fragment) { + for buf = buf[recordlayer.FixedHeaderSize:]; len(buf) != 0; frag = new(fragment) { if err := frag.handshakeHeader.Unmarshal(buf); err != nil { - return false, err + return false, false, err } + // Fragment is a retransmission. We have already assembled it before successfully + isRetransmit = frag.handshakeHeader.FragmentOffset == 0 && + frag.handshakeHeader.MessageSequence < f.currentMessageSequenceNumber + if _, ok := f.cache[frag.handshakeHeader.MessageSequence]; !ok { f.cache[frag.handshakeHeader.MessageSequence] = []*fragment{} } @@ -80,7 +85,7 @@ func (f *fragmentBuffer) push(buf []byte) (bool, error) { buf = buf[end:] } - return true, nil + return true, isRetransmit, nil } func (f *fragmentBuffer) pop() (content []byte, epoch uint16) { @@ -104,9 +109,11 @@ func (f *fragmentBuffer) pop() (content []byte, epoch uint16) { } rawMessage = append(f.data, rawMessage...) + return true } } + return false } @@ -128,5 +135,6 @@ func (f *fragmentBuffer) pop() (content []byte, epoch uint16) { delete(f.cache, f.currentMessageSequenceNumber) f.currentMessageSequenceNumber++ + return append(rawHeader, rawMessage...), messageEpoch } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/handshake_cache.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/handshake_cache.go similarity index 85% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/handshake_cache.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/handshake_cache.go index 8d5960568..95f20953f 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/handshake_cache.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/handshake_cache.go @@ -6,8 +6,8 @@ package dtls import ( "sync" - "github.com/pion/dtls/v2/pkg/crypto/prf" - "github.com/pion/dtls/v2/pkg/protocol/handshake" + "github.com/pion/dtls/v3/pkg/crypto/prf" + "github.com/pion/dtls/v3/pkg/protocol/handshake" ) type handshakeCacheItem struct { @@ -49,7 +49,7 @@ func (h *handshakeCache) push(data []byte, epoch, messageSequence uint16, typ ha // returns a list handshakes that match the requested rules // the list will contain null entries for rules that can't be satisfied -// multiple entries may match a rule, but only the last match is returned (ie ClientHello with cookies) +// multiple entries may match a rule, but only the last match is returned (ie ClientHello with cookies). func (h *handshakeCache) pull(rules ...handshakeCachePullRule) []*handshakeCacheItem { h.mu.Lock() defer h.mu.Unlock() @@ -72,15 +72,21 @@ func (h *handshakeCache) pull(rules ...handshakeCachePullRule) []*handshakeCache } // fullPullMap pulls all handshakes between rules[0] to rules[len(rules)-1] as map. -func (h *handshakeCache) fullPullMap(startSeq int, cipherSuite CipherSuite, rules ...handshakeCachePullRule) (int, map[handshake.Type]handshake.Message, bool) { +// +//nolint:cyclop +func (h *handshakeCache) fullPullMap( + startSeq int, + cipherSuite CipherSuite, + rules ...handshakeCachePullRule, +) (int, map[handshake.Type]handshake.Message, bool) { h.mu.Lock() defer h.mu.Unlock() ci := make(map[handshake.Type]*handshakeCacheItem) - for _, r := range rules { + for _, rule := range rules { var item *handshakeCacheItem for _, c := range h.cache { - if c.typ == r.typ && c.isClient == r.isClient && c.epoch == r.epoch { + if c.typ == rule.typ && c.isClient == rule.isClient && c.epoch == rule.epoch { switch { case item == nil: item = c @@ -89,17 +95,18 @@ func (h *handshakeCache) fullPullMap(startSeq int, cipherSuite CipherSuite, rule } } } - if !r.optional && item == nil { + if !rule.optional && item == nil { // Missing mandatory message. return startSeq, nil, false } - ci[r.typ] = item + ci[rule.typ] = item } out := make(map[handshake.Type]handshake.Message) seq := startSeq + ok := false for _, r := range rules { - t := r.typ - i := ci[t] + typ := r.typ + i := ci[typ] if i == nil { continue } @@ -113,17 +120,22 @@ func (h *handshakeCache) fullPullMap(startSeq int, cipherSuite CipherSuite, rule if err := rawHandshake.Unmarshal(i.data); err != nil { return startSeq, nil, false } - if uint16(seq) != rawHandshake.Header.MessageSequence { + if uint16(seq) != rawHandshake.Header.MessageSequence { //nolint:gosec // G115 // There is a gap. Some messages are not arrived. return startSeq, nil, false } seq++ - out[t] = rawHandshake.Message + ok = true + out[typ] = rawHandshake.Message } + if !ok { + return seq, nil, false + } + return seq, out, true } -// pullAndMerge calls pull and then merges the results, ignoring any null entries +// pullAndMerge calls pull and then merges the results, ignoring any null entries. func (h *handshakeCache) pullAndMerge(rules ...handshakeCachePullRule) []byte { merged := []byte{} @@ -132,6 +144,7 @@ func (h *handshakeCache) pullAndMerge(rules ...handshakeCachePullRule) []byte { merged = append(merged, p.data...) } } + return merged } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/handshaker.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/handshaker.go similarity index 58% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/handshaker.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/handshaker.go index 1c6d58fe9..e8b09b6c4 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/handshaker.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/handshaker.go @@ -12,10 +12,10 @@ import ( "sync" "time" - "github.com/pion/dtls/v2/pkg/crypto/elliptic" - "github.com/pion/dtls/v2/pkg/crypto/signaturehash" - "github.com/pion/dtls/v2/pkg/protocol/alert" - "github.com/pion/dtls/v2/pkg/protocol/handshake" + "github.com/pion/dtls/v3/pkg/crypto/elliptic" + "github.com/pion/dtls/v3/pkg/crypto/signaturehash" + "github.com/pion/dtls/v3/pkg/protocol/alert" + "github.com/pion/dtls/v3/pkg/protocol/handshake" "github.com/pion/logging" ) @@ -82,37 +82,42 @@ func (s handshakeState) String() string { } type handshakeFSM struct { - currentFlight flightVal - flights []*packet - retransmit bool - state *State - cache *handshakeCache - cfg *handshakeConfig - closed chan struct{} + currentFlight flightVal + flights []*packet + retransmit bool + retransmitInterval time.Duration + state *State + cache *handshakeCache + cfg *handshakeConfig + closed chan struct{} } type handshakeConfig struct { - localPSKCallback PSKCallback - localPSKIdentityHint []byte - localCipherSuites []CipherSuite // Available CipherSuites - localSignatureSchemes []signaturehash.Algorithm // Available signature schemes - extendedMasterSecret ExtendedMasterSecretType // Policy for the Extended Master Support extension - localSRTPProtectionProfiles []SRTPProtectionProfile // Available SRTPProtectionProfiles, if empty no SRTP support - serverName string - supportedProtocols []string - clientAuth ClientAuthType // If we are a client should we request a client certificate - localCertificates []tls.Certificate - nameToCertificate map[string]*tls.Certificate - insecureSkipVerify bool - verifyPeerCertificate func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error - verifyConnection func(*State) error - sessionStore SessionStore - rootCAs *x509.CertPool - clientCAs *x509.CertPool - retransmitInterval time.Duration - customCipherSuites func() []CipherSuite - ellipticCurves []elliptic.Curve - insecureSkipHelloVerify bool + localPSKCallback PSKCallback + localPSKIdentityHint []byte + localCipherSuites []CipherSuite // Available CipherSuites + localSignatureSchemes []signaturehash.Algorithm // Available signature schemes + extendedMasterSecret ExtendedMasterSecretType // Policy for the Extended Master Support extension + localSRTPProtectionProfiles []SRTPProtectionProfile // Available SRTPProtectionProfiles, if empty no SRTP support + localSRTPMasterKeyIdentifier []byte + serverName string + supportedProtocols []string + clientAuth ClientAuthType // If we are a client should we request a client certificate + localCertificates []tls.Certificate + nameToCertificate map[string]*tls.Certificate + insecureSkipVerify bool + verifyPeerCertificate func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error + verifyConnection func(*State) error + sessionStore SessionStore + rootCAs *x509.CertPool + clientCAs *x509.CertPool + initialRetransmitInterval time.Duration + disableRetransmitBackoff bool + customCipherSuites func() []CipherSuite + ellipticCurves []elliptic.Curve + insecureSkipHelloVerify bool + connectionIDGenerator func() []byte + helloRandomBytesGenerator func() [handshake.RandomBytesLength]byte onFlightState func(flightVal, handshakeState) log logging.LeveledLogger @@ -124,12 +129,18 @@ type handshakeConfig struct { initialEpoch uint16 mu sync.Mutex + + clientHelloMessageHook func(handshake.MessageClientHello) handshake.Message + serverHelloMessageHook func(handshake.MessageServerHello) handshake.Message + certificateRequestMessageHook func(handshake.MessageCertificateRequest) handshake.Message + + resumeState *State } type flightConn interface { notify(ctx context.Context, level alert.Level, desc alert.Description) error writePackets(context.Context, []*packet) error - recvHandshake() <-chan chan struct{} + recvHandshake() <-chan recvHandshakeState setLocalEpoch(epoch uint16) handleQueuedPackets(context.Context) error sessionKey() []byte @@ -151,6 +162,7 @@ func srvCliStr(isClient bool) string { if isClient { return "client" } + return "server" } @@ -159,15 +171,16 @@ func newHandshakeFSM( initialFlight flightVal, ) *handshakeFSM { return &handshakeFSM{ - currentFlight: initialFlight, - state: s, - cache: cache, - cfg: cfg, - closed: make(chan struct{}), + currentFlight: initialFlight, + state: s, + cache: cache, + cfg: cfg, + retransmitInterval: cfg.initialRetransmitInterval, + closed: make(chan struct{}), } } -func (s *handshakeFSM) Run(ctx context.Context, c flightConn, initialState handshakeState) error { +func (s *handshakeFSM) Run(ctx context.Context, conn flightConn, initialState handshakeState) error { state := initialState defer func() { close(s.closed) @@ -180,13 +193,13 @@ func (s *handshakeFSM) Run(ctx context.Context, c flightConn, initialState hands var err error switch state { case handshakePreparing: - state, err = s.prepare(ctx, c) + state, err = s.prepare(ctx, conn) case handshakeSending: - state, err = s.send(ctx, c) + state, err = s.send(ctx, conn) case handshakeWaiting: - state, err = s.wait(ctx, c) + state, err = s.wait(ctx, conn) case handshakeFinished: - state, err = s.finish(ctx, c) + state, err = s.finish(ctx, conn) default: return errInvalidFSMTransition } @@ -200,24 +213,24 @@ func (s *handshakeFSM) Done() <-chan struct{} { return s.closed } -func (s *handshakeFSM) prepare(ctx context.Context, c flightConn) (handshakeState, error) { +func (s *handshakeFSM) prepare(ctx context.Context, conn flightConn) (handshakeState, error) { s.flights = nil // Prepare flights var ( - a *alert.Alert - err error - pkts []*packet + dtlsAlert *alert.Alert + err error + pkts []*packet ) gen, retransmit, errFlight := s.currentFlight.getFlightGenerator() if errFlight != nil { err = errFlight - a = &alert.Alert{Level: alert.Fatal, Description: alert.InternalError} + dtlsAlert = &alert.Alert{Level: alert.Fatal, Description: alert.InternalError} } else { - pkts, a, err = gen(c, s.state, s.cache, s.cfg) + pkts, dtlsAlert, err = gen(conn, s.state, s.cache, s.cfg) s.retransmit = retransmit } - if a != nil { - if alertErr := c.notify(ctx, a.Level, a.Description); alertErr != nil { + if dtlsAlert != nil { + if alertErr := conn.notify(ctx, dtlsAlert.Level, dtlsAlert.Description); alertErr != nil { if err != nil { err = alertErr } @@ -236,14 +249,15 @@ func (s *handshakeFSM) prepare(ctx context.Context, c flightConn) (handshakeStat nextEpoch = p.record.Header.Epoch } if h, ok := p.record.Content.(*handshake.Handshake); ok { - h.Header.MessageSequence = uint16(s.state.handshakeSendSequence) + h.Header.MessageSequence = uint16(s.state.handshakeSendSequence) //nolint:gosec // G115 s.state.handshakeSendSequence++ } } if epoch != nextEpoch { s.cfg.log.Tracef("[handshake:%s] -> changeCipherSpec (epoch: %d)", srvCliStr(s.state.isClient), nextEpoch) - c.setLocalEpoch(nextEpoch) + conn.setLocalEpoch(nextEpoch) } + return handshakeSending, nil } @@ -256,28 +270,35 @@ func (s *handshakeFSM) send(ctx context.Context, c flightConn) (handshakeState, if s.currentFlight.isLastSendFlight() { return handshakeFinished, nil } + return handshakeWaiting, nil } -func (s *handshakeFSM) wait(ctx context.Context, c flightConn) (handshakeState, error) { //nolint:gocognit +func (s *handshakeFSM) wait(ctx context.Context, conn flightConn) (handshakeState, error) { //nolint:gocognit,cyclop parse, errFlight := s.currentFlight.getFlightParser() if errFlight != nil { - if alertErr := c.notify(ctx, alert.Fatal, alert.InternalError); alertErr != nil { - if errFlight != nil { - return handshakeErrored, alertErr - } + if alertErr := conn.notify(ctx, alert.Fatal, alert.InternalError); alertErr != nil { + return handshakeErrored, alertErr } + return handshakeErrored, errFlight } - retransmitTimer := time.NewTimer(s.cfg.retransmitInterval) + retransmitTimer := time.NewTimer(s.retransmitInterval) for { select { - case done := <-c.recvHandshake(): - nextFlight, alert, err := parse(ctx, c, s.state, s.cache, s.cfg) - close(done) + case state := <-conn.recvHandshake(): + if state.isRetransmit { + close(state.done) + + return handshakeSending, nil + } + + nextFlight, alert, err := parse(ctx, conn, s.state, s.cache, s.cfg) + s.retransmitInterval = s.cfg.initialRetransmitInterval + close(state.done) if alert != nil { - if alertErr := c.notify(ctx, alert.Level, alert.Description); alertErr != nil { + if alertErr := conn.notify(ctx, alert.Level, alert.Description); alertErr != nil { if err != nil { err = alertErr } @@ -289,62 +310,53 @@ func (s *handshakeFSM) wait(ctx context.Context, c flightConn) (handshakeState, if nextFlight == 0 { break } - s.cfg.log.Tracef("[handshake:%s] %s -> %s", srvCliStr(s.state.isClient), s.currentFlight.String(), nextFlight.String()) + s.cfg.log.Tracef( + "[handshake:%s] %s -> %s", + srvCliStr(s.state.isClient), + s.currentFlight.String(), + nextFlight.String(), + ) if nextFlight.isLastRecvFlight() && s.currentFlight == nextFlight { return handshakeFinished, nil } s.currentFlight = nextFlight + return handshakePreparing, nil case <-retransmitTimer.C: if !s.retransmit { return handshakeWaiting, nil } + + // RFC 4347 4.2.4.1: + // Implementations SHOULD use an initial timer value of 1 second (the minimum defined in RFC 2988 [RFC2988]) + // and double the value at each retransmission, up to no less than the RFC 2988 maximum of 60 seconds. + if !s.cfg.disableRetransmitBackoff { + s.retransmitInterval *= 2 + } + if s.retransmitInterval > time.Second*60 { + s.retransmitInterval = time.Second * 60 + } + return handshakeSending, nil case <-ctx.Done(): + s.retransmitInterval = s.cfg.initialRetransmitInterval + return handshakeErrored, ctx.Err() } } } func (s *handshakeFSM) finish(ctx context.Context, c flightConn) (handshakeState, error) { - parse, errFlight := s.currentFlight.getFlightParser() - if errFlight != nil { - if alertErr := c.notify(ctx, alert.Fatal, alert.InternalError); alertErr != nil { - if errFlight != nil { - return handshakeErrored, alertErr - } - } - return handshakeErrored, errFlight - } - - retransmitTimer := time.NewTimer(s.cfg.retransmitInterval) select { - case done := <-c.recvHandshake(): - nextFlight, alert, err := parse(ctx, c, s.state, s.cache, s.cfg) - close(done) - if alert != nil { - if alertErr := c.notify(ctx, alert.Level, alert.Description); alertErr != nil { - if err != nil { - err = alertErr - } - } - } - if err != nil { - return handshakeErrored, err - } - if nextFlight == 0 { - break - } - if nextFlight.isLastRecvFlight() && s.currentFlight == nextFlight { + case state := <-c.recvHandshake(): + close(state.done) + if s.state.isClient { return handshakeFinished, nil + } else { + return handshakeSending, nil } - <-retransmitTimer.C - // Retransmit last flight - return handshakeSending, nil - case <-ctx.Done(): return handshakeErrored, ctx.Err() } - return handshakeFinished, nil } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/internal/ciphersuite/aes_128_ccm.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/internal/ciphersuite/aes_128_ccm.go similarity index 60% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/internal/ciphersuite/aes_128_ccm.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/internal/ciphersuite/aes_128_ccm.go index f78b6dc2c..9805f36e8 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/internal/ciphersuite/aes_128_ccm.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/internal/ciphersuite/aes_128_ccm.go @@ -4,16 +4,23 @@ package ciphersuite import ( - "github.com/pion/dtls/v2/pkg/crypto/ciphersuite" - "github.com/pion/dtls/v2/pkg/crypto/clientcertificate" + "github.com/pion/dtls/v3/pkg/crypto/ciphersuite" + "github.com/pion/dtls/v3/pkg/crypto/clientcertificate" ) -// Aes128Ccm is a base class used by multiple AES-CCM Ciphers +// Aes128Ccm is a base class used by multiple AES-CCM Ciphers. type Aes128Ccm struct { AesCcm } -func newAes128Ccm(clientCertificateType clientcertificate.Type, id ID, psk bool, cryptoCCMTagLen ciphersuite.CCMTagLen, keyExchangeAlgorithm KeyExchangeAlgorithm, ecc bool) *Aes128Ccm { +func newAes128Ccm( + clientCertificateType clientcertificate.Type, + id ID, + psk bool, + cryptoCCMTagLen ciphersuite.CCMTagLen, + keyExchangeAlgorithm KeyExchangeAlgorithm, + ecc bool, +) *Aes128Ccm { return &Aes128Ccm{ AesCcm: AesCcm{ clientCertificateType: clientCertificateType, @@ -26,8 +33,9 @@ func newAes128Ccm(clientCertificateType clientcertificate.Type, id ID, psk bool, } } -// Init initializes the internal Cipher with keying material +// Init initializes the internal Cipher with keying material. func (c *Aes128Ccm) Init(masterSecret, clientRandom, serverRandom []byte, isClient bool) error { const prfKeyLen = 16 + return c.AesCcm.Init(masterSecret, clientRandom, serverRandom, isClient, prfKeyLen) } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/internal/ciphersuite/aes_256_ccm.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/internal/ciphersuite/aes_256_ccm.go similarity index 60% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/internal/ciphersuite/aes_256_ccm.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/internal/ciphersuite/aes_256_ccm.go index bb8128627..58d5e0cee 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/internal/ciphersuite/aes_256_ccm.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/internal/ciphersuite/aes_256_ccm.go @@ -4,16 +4,23 @@ package ciphersuite import ( - "github.com/pion/dtls/v2/pkg/crypto/ciphersuite" - "github.com/pion/dtls/v2/pkg/crypto/clientcertificate" + "github.com/pion/dtls/v3/pkg/crypto/ciphersuite" + "github.com/pion/dtls/v3/pkg/crypto/clientcertificate" ) -// Aes256Ccm is a base class used by multiple AES-CCM Ciphers +// Aes256Ccm is a base class used by multiple AES-CCM Ciphers. type Aes256Ccm struct { AesCcm } -func newAes256Ccm(clientCertificateType clientcertificate.Type, id ID, psk bool, cryptoCCMTagLen ciphersuite.CCMTagLen, keyExchangeAlgorithm KeyExchangeAlgorithm, ecc bool) *Aes256Ccm { +func newAes256Ccm( + clientCertificateType clientcertificate.Type, + id ID, + psk bool, + cryptoCCMTagLen ciphersuite.CCMTagLen, + keyExchangeAlgorithm KeyExchangeAlgorithm, + ecc bool, +) *Aes256Ccm { return &Aes256Ccm{ AesCcm: AesCcm{ clientCertificateType: clientCertificateType, @@ -26,8 +33,9 @@ func newAes256Ccm(clientCertificateType clientcertificate.Type, id ID, psk bool, } } -// Init initializes the internal Cipher with keying material +// Init initializes the internal Cipher with keying material. func (c *Aes256Ccm) Init(masterSecret, clientRandom, serverRandom []byte, isClient bool) error { const prfKeyLen = 32 + return c.AesCcm.Init(masterSecret, clientRandom, serverRandom, isClient, prfKeyLen) } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/internal/ciphersuite/aes_ccm.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/internal/ciphersuite/aes_ccm.go similarity index 63% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/internal/ciphersuite/aes_ccm.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/internal/ciphersuite/aes_ccm.go index dc5119823..ddda1c8e7 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/internal/ciphersuite/aes_ccm.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/internal/ciphersuite/aes_ccm.go @@ -9,13 +9,13 @@ import ( "hash" "sync/atomic" - "github.com/pion/dtls/v2/pkg/crypto/ciphersuite" - "github.com/pion/dtls/v2/pkg/crypto/clientcertificate" - "github.com/pion/dtls/v2/pkg/crypto/prf" - "github.com/pion/dtls/v2/pkg/protocol/recordlayer" + "github.com/pion/dtls/v3/pkg/crypto/ciphersuite" + "github.com/pion/dtls/v3/pkg/crypto/clientcertificate" + "github.com/pion/dtls/v3/pkg/crypto/prf" + "github.com/pion/dtls/v3/pkg/protocol/recordlayer" ) -// AesCcm is a base class used by multiple AES-CCM Ciphers +// AesCcm is a base class used by multiple AES-CCM Ciphers. type AesCcm struct { ccm atomic.Value // *cryptoCCM clientCertificateType clientcertificate.Type @@ -26,12 +26,12 @@ type AesCcm struct { ecc bool } -// CertificateType returns what type of certificate this CipherSuite exchanges +// CertificateType returns what type of certificate this CipherSuite exchanges. func (c *AesCcm) CertificateType() clientcertificate.Type { return c.clientCertificateType } -// ID returns the ID of the CipherSuite +// ID returns the ID of the CipherSuite. func (c *AesCcm) ID() ID { return c.id } @@ -40,59 +40,66 @@ func (c *AesCcm) String() string { return c.id.String() } -// ECC uses Elliptic Curve Cryptography +// ECC uses Elliptic Curve Cryptography. func (c *AesCcm) ECC() bool { return c.ecc } -// KeyExchangeAlgorithm controls what key exchange algorithm is using during the handshake +// KeyExchangeAlgorithm controls what key exchange algorithm is using during the handshake. func (c *AesCcm) KeyExchangeAlgorithm() KeyExchangeAlgorithm { return c.keyExchangeAlgorithm } -// HashFunc returns the hashing func for this CipherSuite +// HashFunc returns the hashing func for this CipherSuite. func (c *AesCcm) HashFunc() func() hash.Hash { return sha256.New } -// AuthenticationType controls what authentication method is using during the handshake +// AuthenticationType controls what authentication method is using during the handshake. func (c *AesCcm) AuthenticationType() AuthenticationType { if c.psk { return AuthenticationTypePreSharedKey } + return AuthenticationTypeCertificate } // IsInitialized returns if the CipherSuite has keying material and can -// encrypt/decrypt packets +// encrypt/decrypt packets. func (c *AesCcm) IsInitialized() bool { return c.ccm.Load() != nil } -// Init initializes the internal Cipher with keying material +// Init initializes the internal Cipher with keying material. func (c *AesCcm) Init(masterSecret, clientRandom, serverRandom []byte, isClient bool, prfKeyLen int) error { const ( prfMacLen = 0 prfIvLen = 4 ) - keys, err := prf.GenerateEncryptionKeys(masterSecret, clientRandom, serverRandom, prfMacLen, prfKeyLen, prfIvLen, c.HashFunc()) + keys, err := prf.GenerateEncryptionKeys( + masterSecret, clientRandom, serverRandom, prfMacLen, prfKeyLen, prfIvLen, c.HashFunc(), + ) if err != nil { return err } var ccm *ciphersuite.CCM if isClient { - ccm, err = ciphersuite.NewCCM(c.cryptoCCMTagLen, keys.ClientWriteKey, keys.ClientWriteIV, keys.ServerWriteKey, keys.ServerWriteIV) + ccm, err = ciphersuite.NewCCM( + c.cryptoCCMTagLen, keys.ClientWriteKey, keys.ClientWriteIV, keys.ServerWriteKey, keys.ServerWriteIV, + ) } else { - ccm, err = ciphersuite.NewCCM(c.cryptoCCMTagLen, keys.ServerWriteKey, keys.ServerWriteIV, keys.ClientWriteKey, keys.ClientWriteIV) + ccm, err = ciphersuite.NewCCM( + c.cryptoCCMTagLen, keys.ServerWriteKey, keys.ServerWriteIV, keys.ClientWriteKey, keys.ClientWriteIV, + ) } c.ccm.Store(ccm) return err } -// Encrypt encrypts a single TLS RecordLayer +// Encrypt encrypts a single TLS RecordLayer. func (c *AesCcm) Encrypt(pkt *recordlayer.RecordLayer, raw []byte) ([]byte, error) { cipherSuite, ok := c.ccm.Load().(*ciphersuite.CCM) if !ok { @@ -102,12 +109,12 @@ func (c *AesCcm) Encrypt(pkt *recordlayer.RecordLayer, raw []byte) ([]byte, erro return cipherSuite.Encrypt(pkt, raw) } -// Decrypt decrypts a single TLS RecordLayer -func (c *AesCcm) Decrypt(raw []byte) ([]byte, error) { +// Decrypt decrypts a single TLS RecordLayer. +func (c *AesCcm) Decrypt(h recordlayer.Header, raw []byte) ([]byte, error) { cipherSuite, ok := c.ccm.Load().(*ciphersuite.CCM) if !ok { return nil, fmt.Errorf("%w, unable to decrypt", errCipherSuiteNotInit) } - return cipherSuite.Decrypt(raw) + return cipherSuite.Decrypt(h, raw) } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/internal/ciphersuite/ciphersuite.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/internal/ciphersuite/ciphersuite.go similarity index 86% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/internal/ciphersuite/ciphersuite.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/internal/ciphersuite/ciphersuite.go index f44f29fd3..27b7d57ce 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/internal/ciphersuite/ciphersuite.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/internal/ciphersuite/ciphersuite.go @@ -1,23 +1,25 @@ // SPDX-FileCopyrightText: 2023 The Pion community // SPDX-License-Identifier: MIT -// Package ciphersuite provides TLS Ciphers as registered with the IANA https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-4 +// Package ciphersuite provides TLS Ciphers as registered with the IANA +// https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-4 package ciphersuite import ( "errors" "fmt" - "github.com/pion/dtls/v2/internal/ciphersuite/types" - "github.com/pion/dtls/v2/pkg/protocol" + "github.com/pion/dtls/v3/internal/ciphersuite/types" + "github.com/pion/dtls/v3/pkg/protocol" ) -var errCipherSuiteNotInit = &protocol.TemporaryError{Err: errors.New("CipherSuite has not been initialized")} //nolint:goerr113 +//nolint:goerr113 +var errCipherSuiteNotInit = &protocol.TemporaryError{Err: errors.New("CipherSuite has not been initialized")} -// ID is an ID for our supported CipherSuites +// ID is an ID for our supported CipherSuites. type ID uint16 -func (i ID) String() string { +func (i ID) String() string { //nolint:cyclop switch i { case TLS_ECDHE_ECDSA_WITH_AES_128_CCM: return "TLS_ECDHE_ECDSA_WITH_AES_128_CCM" @@ -52,19 +54,19 @@ func (i ID) String() string { } } -// Supported Cipher Suites +// Supported Cipher Suites. const ( - // AES-128-CCM + // AES-128-CCM. TLS_ECDHE_ECDSA_WITH_AES_128_CCM ID = 0xc0ac //nolint:revive,stylecheck TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 ID = 0xc0ae //nolint:revive,stylecheck - // AES-128-GCM-SHA256 + // AES-128-GCM-SHA256. TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 ID = 0xc02b //nolint:revive,stylecheck TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 ID = 0xc02f //nolint:revive,stylecheck TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 ID = 0xc02c //nolint:revive,stylecheck TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 ID = 0xc030 //nolint:revive,stylecheck - // AES-256-CBC-SHA + // AES-256-CBC-SHA. TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA ID = 0xc00a //nolint:revive,stylecheck TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA ID = 0xc014 //nolint:revive,stylecheck @@ -77,10 +79,10 @@ const ( TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 ID = 0xC037 //nolint:revive,stylecheck ) -// AuthenticationType controls what authentication method is using during the handshake +// AuthenticationType controls what authentication method is using during the handshake. type AuthenticationType = types.AuthenticationType -// AuthenticationType Enums +// AuthenticationType Enums. const ( AuthenticationTypeCertificate AuthenticationType = types.AuthenticationTypeCertificate AuthenticationTypePreSharedKey AuthenticationType = types.AuthenticationTypePreSharedKey @@ -90,7 +92,7 @@ const ( // KeyExchangeAlgorithm controls what exchange algorithm was chosen. type KeyExchangeAlgorithm = types.KeyExchangeAlgorithm -// KeyExchangeAlgorithm Bitmask +// KeyExchangeAlgorithm Bitmask. const ( KeyExchangeAlgorithmNone KeyExchangeAlgorithm = types.KeyExchangeAlgorithmNone KeyExchangeAlgorithmPsk KeyExchangeAlgorithm = types.KeyExchangeAlgorithmPsk diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_128_ccm.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_128_ccm.go new file mode 100644 index 000000000..04a6ca40d --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_128_ccm.go @@ -0,0 +1,21 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + +package ciphersuite + +import ( + "github.com/pion/dtls/v3/pkg/crypto/ciphersuite" + "github.com/pion/dtls/v3/pkg/crypto/clientcertificate" +) + +// NewTLSEcdheEcdsaWithAes128Ccm constructs a TLS_ECDHE_ECDSA_WITH_AES_128_CCM Cipher. +func NewTLSEcdheEcdsaWithAes128Ccm() *Aes128Ccm { + return newAes128Ccm( + clientcertificate.ECDSASign, + TLS_ECDHE_ECDSA_WITH_AES_128_CCM, + false, + ciphersuite.CCMTagLength, + KeyExchangeAlgorithmEcdhe, + true, + ) +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_128_ccm8.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_128_ccm8.go new file mode 100644 index 000000000..38a166fad --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_128_ccm8.go @@ -0,0 +1,21 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + +package ciphersuite + +import ( + "github.com/pion/dtls/v3/pkg/crypto/ciphersuite" + "github.com/pion/dtls/v3/pkg/crypto/clientcertificate" +) + +// NewTLSEcdheEcdsaWithAes128Ccm8 creates a new TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 CipherSuite. +func NewTLSEcdheEcdsaWithAes128Ccm8() *Aes128Ccm { + return newAes128Ccm( + clientcertificate.ECDSASign, + TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8, + false, + ciphersuite.CCMTagLength8, + KeyExchangeAlgorithmEcdhe, + true, + ) +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_128_gcm_sha256.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_128_gcm_sha256.go similarity index 69% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_128_gcm_sha256.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_128_gcm_sha256.go index 0c919fe47..f47a67497 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_128_gcm_sha256.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_128_gcm_sha256.go @@ -9,33 +9,33 @@ import ( "hash" "sync/atomic" - "github.com/pion/dtls/v2/pkg/crypto/ciphersuite" - "github.com/pion/dtls/v2/pkg/crypto/clientcertificate" - "github.com/pion/dtls/v2/pkg/crypto/prf" - "github.com/pion/dtls/v2/pkg/protocol/recordlayer" + "github.com/pion/dtls/v3/pkg/crypto/ciphersuite" + "github.com/pion/dtls/v3/pkg/crypto/clientcertificate" + "github.com/pion/dtls/v3/pkg/crypto/prf" + "github.com/pion/dtls/v3/pkg/protocol/recordlayer" ) -// TLSEcdheEcdsaWithAes128GcmSha256 represents a TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 CipherSuite +// TLSEcdheEcdsaWithAes128GcmSha256 represents a TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 CipherSuite. type TLSEcdheEcdsaWithAes128GcmSha256 struct { gcm atomic.Value // *cryptoGCM } -// CertificateType returns what type of certficate this CipherSuite exchanges +// CertificateType returns what type of certficate this CipherSuite exchanges. func (c *TLSEcdheEcdsaWithAes128GcmSha256) CertificateType() clientcertificate.Type { return clientcertificate.ECDSASign } -// KeyExchangeAlgorithm controls what key exchange algorithm is using during the handshake +// KeyExchangeAlgorithm controls what key exchange algorithm is using during the handshake. func (c *TLSEcdheEcdsaWithAes128GcmSha256) KeyExchangeAlgorithm() KeyExchangeAlgorithm { return KeyExchangeAlgorithmEcdhe } -// ECC uses Elliptic Curve Cryptography +// ECC uses Elliptic Curve Cryptography. func (c *TLSEcdheEcdsaWithAes128GcmSha256) ECC() bool { return true } -// ID returns the ID of the CipherSuite +// ID returns the ID of the CipherSuite. func (c *TLSEcdheEcdsaWithAes128GcmSha256) ID() ID { return TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 } @@ -44,24 +44,31 @@ func (c *TLSEcdheEcdsaWithAes128GcmSha256) String() string { return "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256" } -// HashFunc returns the hashing func for this CipherSuite +// HashFunc returns the hashing func for this CipherSuite. func (c *TLSEcdheEcdsaWithAes128GcmSha256) HashFunc() func() hash.Hash { return sha256.New } -// AuthenticationType controls what authentication method is using during the handshake +// AuthenticationType controls what authentication method is using during the handshake. func (c *TLSEcdheEcdsaWithAes128GcmSha256) AuthenticationType() AuthenticationType { return AuthenticationTypeCertificate } // IsInitialized returns if the CipherSuite has keying material and can -// encrypt/decrypt packets +// encrypt/decrypt packets. func (c *TLSEcdheEcdsaWithAes128GcmSha256) IsInitialized() bool { return c.gcm.Load() != nil } -func (c *TLSEcdheEcdsaWithAes128GcmSha256) init(masterSecret, clientRandom, serverRandom []byte, isClient bool, prfMacLen, prfKeyLen, prfIvLen int, hashFunc func() hash.Hash) error { - keys, err := prf.GenerateEncryptionKeys(masterSecret, clientRandom, serverRandom, prfMacLen, prfKeyLen, prfIvLen, hashFunc) +func (c *TLSEcdheEcdsaWithAes128GcmSha256) init( + masterSecret, clientRandom, serverRandom []byte, + isClient bool, + prfMacLen, prfKeyLen, prfIvLen int, + hashFunc func() hash.Hash, +) error { + keys, err := prf.GenerateEncryptionKeys( + masterSecret, clientRandom, serverRandom, prfMacLen, prfKeyLen, prfIvLen, hashFunc, + ) if err != nil { return err } @@ -73,10 +80,11 @@ func (c *TLSEcdheEcdsaWithAes128GcmSha256) init(masterSecret, clientRandom, serv gcm, err = ciphersuite.NewGCM(keys.ServerWriteKey, keys.ServerWriteIV, keys.ClientWriteKey, keys.ClientWriteIV) } c.gcm.Store(gcm) + return err } -// Init initializes the internal Cipher with keying material +// Init initializes the internal Cipher with keying material. func (c *TLSEcdheEcdsaWithAes128GcmSha256) Init(masterSecret, clientRandom, serverRandom []byte, isClient bool) error { const ( prfMacLen = 0 @@ -87,7 +95,7 @@ func (c *TLSEcdheEcdsaWithAes128GcmSha256) Init(masterSecret, clientRandom, serv return c.init(masterSecret, clientRandom, serverRandom, isClient, prfMacLen, prfKeyLen, prfIvLen, c.HashFunc()) } -// Encrypt encrypts a single TLS RecordLayer +// Encrypt encrypts a single TLS RecordLayer. func (c *TLSEcdheEcdsaWithAes128GcmSha256) Encrypt(pkt *recordlayer.RecordLayer, raw []byte) ([]byte, error) { cipherSuite, ok := c.gcm.Load().(*ciphersuite.GCM) if !ok { @@ -97,12 +105,12 @@ func (c *TLSEcdheEcdsaWithAes128GcmSha256) Encrypt(pkt *recordlayer.RecordLayer, return cipherSuite.Encrypt(pkt, raw) } -// Decrypt decrypts a single TLS RecordLayer -func (c *TLSEcdheEcdsaWithAes128GcmSha256) Decrypt(raw []byte) ([]byte, error) { +// Decrypt decrypts a single TLS RecordLayer. +func (c *TLSEcdheEcdsaWithAes128GcmSha256) Decrypt(h recordlayer.Header, raw []byte) ([]byte, error) { cipherSuite, ok := c.gcm.Load().(*ciphersuite.GCM) if !ok { return nil, fmt.Errorf("%w, unable to decrypt", errCipherSuiteNotInit) } - return cipherSuite.Decrypt(raw) + return cipherSuite.Decrypt(h, raw) } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_256_cbc_sha.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_256_cbc_sha.go similarity index 73% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_256_cbc_sha.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_256_cbc_sha.go index 577192c89..6eeb91811 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_256_cbc_sha.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_256_cbc_sha.go @@ -10,33 +10,33 @@ import ( "hash" "sync/atomic" - "github.com/pion/dtls/v2/pkg/crypto/ciphersuite" - "github.com/pion/dtls/v2/pkg/crypto/clientcertificate" - "github.com/pion/dtls/v2/pkg/crypto/prf" - "github.com/pion/dtls/v2/pkg/protocol/recordlayer" + "github.com/pion/dtls/v3/pkg/crypto/ciphersuite" + "github.com/pion/dtls/v3/pkg/crypto/clientcertificate" + "github.com/pion/dtls/v3/pkg/crypto/prf" + "github.com/pion/dtls/v3/pkg/protocol/recordlayer" ) -// TLSEcdheEcdsaWithAes256CbcSha represents a TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA CipherSuite +// TLSEcdheEcdsaWithAes256CbcSha represents a TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA CipherSuite. type TLSEcdheEcdsaWithAes256CbcSha struct { cbc atomic.Value // *cryptoCBC } -// CertificateType returns what type of certficate this CipherSuite exchanges +// CertificateType returns what type of certficate this CipherSuite exchanges. func (c *TLSEcdheEcdsaWithAes256CbcSha) CertificateType() clientcertificate.Type { return clientcertificate.ECDSASign } -// KeyExchangeAlgorithm controls what key exchange algorithm is using during the handshake +// KeyExchangeAlgorithm controls what key exchange algorithm is using during the handshake. func (c *TLSEcdheEcdsaWithAes256CbcSha) KeyExchangeAlgorithm() KeyExchangeAlgorithm { return KeyExchangeAlgorithmEcdhe } -// ECC uses Elliptic Curve Cryptography +// ECC uses Elliptic Curve Cryptography. func (c *TLSEcdheEcdsaWithAes256CbcSha) ECC() bool { return true } -// ID returns the ID of the CipherSuite +// ID returns the ID of the CipherSuite. func (c *TLSEcdheEcdsaWithAes256CbcSha) ID() ID { return TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA } @@ -45,23 +45,23 @@ func (c *TLSEcdheEcdsaWithAes256CbcSha) String() string { return "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA" } -// HashFunc returns the hashing func for this CipherSuite +// HashFunc returns the hashing func for this CipherSuite. func (c *TLSEcdheEcdsaWithAes256CbcSha) HashFunc() func() hash.Hash { return sha256.New } -// AuthenticationType controls what authentication method is using during the handshake +// AuthenticationType controls what authentication method is using during the handshake. func (c *TLSEcdheEcdsaWithAes256CbcSha) AuthenticationType() AuthenticationType { return AuthenticationTypeCertificate } // IsInitialized returns if the CipherSuite has keying material and can -// encrypt/decrypt packets +// encrypt/decrypt packets. func (c *TLSEcdheEcdsaWithAes256CbcSha) IsInitialized() bool { return c.cbc.Load() != nil } -// Init initializes the internal Cipher with keying material +// Init initializes the internal Cipher with keying material. func (c *TLSEcdheEcdsaWithAes256CbcSha) Init(masterSecret, clientRandom, serverRandom []byte, isClient bool) error { const ( prfMacLen = 20 @@ -69,7 +69,9 @@ func (c *TLSEcdheEcdsaWithAes256CbcSha) Init(masterSecret, clientRandom, serverR prfIvLen = 16 ) - keys, err := prf.GenerateEncryptionKeys(masterSecret, clientRandom, serverRandom, prfMacLen, prfKeyLen, prfIvLen, c.HashFunc()) + keys, err := prf.GenerateEncryptionKeys( + masterSecret, clientRandom, serverRandom, prfMacLen, prfKeyLen, prfIvLen, c.HashFunc(), + ) if err != nil { return err } @@ -93,7 +95,7 @@ func (c *TLSEcdheEcdsaWithAes256CbcSha) Init(masterSecret, clientRandom, serverR return err } -// Encrypt encrypts a single TLS RecordLayer +// Encrypt encrypts a single TLS RecordLayer. func (c *TLSEcdheEcdsaWithAes256CbcSha) Encrypt(pkt *recordlayer.RecordLayer, raw []byte) ([]byte, error) { cipherSuite, ok := c.cbc.Load().(*ciphersuite.CBC) if !ok { @@ -103,12 +105,12 @@ func (c *TLSEcdheEcdsaWithAes256CbcSha) Encrypt(pkt *recordlayer.RecordLayer, ra return cipherSuite.Encrypt(pkt, raw) } -// Decrypt decrypts a single TLS RecordLayer -func (c *TLSEcdheEcdsaWithAes256CbcSha) Decrypt(raw []byte) ([]byte, error) { +// Decrypt decrypts a single TLS RecordLayer. +func (c *TLSEcdheEcdsaWithAes256CbcSha) Decrypt(h recordlayer.Header, raw []byte) ([]byte, error) { cipherSuite, ok := c.cbc.Load().(*ciphersuite.CBC) if !ok { return nil, fmt.Errorf("%w, unable to decrypt", errCipherSuiteNotInit) } - return cipherSuite.Decrypt(raw) + return cipherSuite.Decrypt(h, raw) } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_256_gcm_sha384.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_256_gcm_sha384.go similarity index 82% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_256_gcm_sha384.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_256_gcm_sha384.go index 2a3cfa4f5..bf6f6c444 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_256_gcm_sha384.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/internal/ciphersuite/tls_ecdhe_ecdsa_with_aes_256_gcm_sha384.go @@ -8,12 +8,12 @@ import ( "hash" ) -// TLSEcdheEcdsaWithAes256GcmSha384 represents a TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 CipherSuite +// TLSEcdheEcdsaWithAes256GcmSha384 represents a TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 CipherSuite. type TLSEcdheEcdsaWithAes256GcmSha384 struct { TLSEcdheEcdsaWithAes128GcmSha256 } -// ID returns the ID of the CipherSuite +// ID returns the ID of the CipherSuite. func (c *TLSEcdheEcdsaWithAes256GcmSha384) ID() ID { return TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 } @@ -22,12 +22,12 @@ func (c *TLSEcdheEcdsaWithAes256GcmSha384) String() string { return "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384" } -// HashFunc returns the hashing func for this CipherSuite +// HashFunc returns the hashing func for this CipherSuite. func (c *TLSEcdheEcdsaWithAes256GcmSha384) HashFunc() func() hash.Hash { return sha512.New384 } -// Init initializes the internal Cipher with keying material +// Init initializes the internal Cipher with keying material. func (c *TLSEcdheEcdsaWithAes256GcmSha384) Init(masterSecret, clientRandom, serverRandom []byte, isClient bool) error { const ( prfMacLen = 0 diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/internal/ciphersuite/tls_ecdhe_psk_with_aes_128_cbc_sha256.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/internal/ciphersuite/tls_ecdhe_psk_with_aes_128_cbc_sha256.go similarity index 75% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/internal/ciphersuite/tls_ecdhe_psk_with_aes_128_cbc_sha256.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/internal/ciphersuite/tls_ecdhe_psk_with_aes_128_cbc_sha256.go index 75a25633a..24f51e1eb 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/internal/ciphersuite/tls_ecdhe_psk_with_aes_128_cbc_sha256.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/internal/ciphersuite/tls_ecdhe_psk_with_aes_128_cbc_sha256.go @@ -9,13 +9,13 @@ import ( "hash" "sync/atomic" - "github.com/pion/dtls/v2/pkg/crypto/ciphersuite" - "github.com/pion/dtls/v2/pkg/crypto/clientcertificate" - "github.com/pion/dtls/v2/pkg/crypto/prf" - "github.com/pion/dtls/v2/pkg/protocol/recordlayer" + "github.com/pion/dtls/v3/pkg/crypto/ciphersuite" + "github.com/pion/dtls/v3/pkg/crypto/clientcertificate" + "github.com/pion/dtls/v3/pkg/crypto/prf" + "github.com/pion/dtls/v3/pkg/protocol/recordlayer" ) -// TLSEcdhePskWithAes128CbcSha256 implements the TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 CipherSuite +// TLSEcdhePskWithAes128CbcSha256 implements the TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 CipherSuite. type TLSEcdhePskWithAes128CbcSha256 struct { cbc atomic.Value // *cryptoCBC } @@ -25,22 +25,22 @@ func NewTLSEcdhePskWithAes128CbcSha256() *TLSEcdhePskWithAes128CbcSha256 { return &TLSEcdhePskWithAes128CbcSha256{} } -// CertificateType returns what type of certificate this CipherSuite exchanges +// CertificateType returns what type of certificate this CipherSuite exchanges. func (c *TLSEcdhePskWithAes128CbcSha256) CertificateType() clientcertificate.Type { return clientcertificate.Type(0) } -// KeyExchangeAlgorithm controls what key exchange algorithm is using during the handshake +// KeyExchangeAlgorithm controls what key exchange algorithm is using during the handshake. func (c *TLSEcdhePskWithAes128CbcSha256) KeyExchangeAlgorithm() KeyExchangeAlgorithm { return (KeyExchangeAlgorithmPsk | KeyExchangeAlgorithmEcdhe) } -// ECC uses Elliptic Curve Cryptography +// ECC uses Elliptic Curve Cryptography. func (c *TLSEcdhePskWithAes128CbcSha256) ECC() bool { return true } -// ID returns the ID of the CipherSuite +// ID returns the ID of the CipherSuite. func (c *TLSEcdhePskWithAes128CbcSha256) ID() ID { return TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 } @@ -49,23 +49,23 @@ func (c *TLSEcdhePskWithAes128CbcSha256) String() string { return "TLS-ECDHE-PSK-WITH-AES-128-CBC-SHA256" } -// HashFunc returns the hashing func for this CipherSuite +// HashFunc returns the hashing func for this CipherSuite. func (c *TLSEcdhePskWithAes128CbcSha256) HashFunc() func() hash.Hash { return sha256.New } -// AuthenticationType controls what authentication method is using during the handshake +// AuthenticationType controls what authentication method is using during the handshake. func (c *TLSEcdhePskWithAes128CbcSha256) AuthenticationType() AuthenticationType { return AuthenticationTypePreSharedKey } // IsInitialized returns if the CipherSuite has keying material and can -// encrypt/decrypt packets +// encrypt/decrypt packets. func (c *TLSEcdhePskWithAes128CbcSha256) IsInitialized() bool { return c.cbc.Load() != nil } -// Init initializes the internal Cipher with keying material +// Init initializes the internal Cipher with keying material. func (c *TLSEcdhePskWithAes128CbcSha256) Init(masterSecret, clientRandom, serverRandom []byte, isClient bool) error { const ( prfMacLen = 32 @@ -73,7 +73,9 @@ func (c *TLSEcdhePskWithAes128CbcSha256) Init(masterSecret, clientRandom, server prfIvLen = 16 ) - keys, err := prf.GenerateEncryptionKeys(masterSecret, clientRandom, serverRandom, prfMacLen, prfKeyLen, prfIvLen, c.HashFunc()) + keys, err := prf.GenerateEncryptionKeys( + masterSecret, clientRandom, serverRandom, prfMacLen, prfKeyLen, prfIvLen, c.HashFunc(), + ) if err != nil { return err } @@ -97,7 +99,7 @@ func (c *TLSEcdhePskWithAes128CbcSha256) Init(masterSecret, clientRandom, server return err } -// Encrypt encrypts a single TLS RecordLayer +// Encrypt encrypts a single TLS RecordLayer. func (c *TLSEcdhePskWithAes128CbcSha256) Encrypt(pkt *recordlayer.RecordLayer, raw []byte) ([]byte, error) { cipherSuite, ok := c.cbc.Load().(*ciphersuite.CBC) if !ok { // !c.isInitialized() @@ -107,12 +109,12 @@ func (c *TLSEcdhePskWithAes128CbcSha256) Encrypt(pkt *recordlayer.RecordLayer, r return cipherSuite.Encrypt(pkt, raw) } -// Decrypt decrypts a single TLS RecordLayer -func (c *TLSEcdhePskWithAes128CbcSha256) Decrypt(raw []byte) ([]byte, error) { +// Decrypt decrypts a single TLS RecordLayer. +func (c *TLSEcdhePskWithAes128CbcSha256) Decrypt(h recordlayer.Header, raw []byte) ([]byte, error) { cipherSuite, ok := c.cbc.Load().(*ciphersuite.CBC) if !ok { // !c.isInitialized() return nil, fmt.Errorf("%w, unable to decrypt", errCipherSuiteNotInit) } - return cipherSuite.Decrypt(raw) + return cipherSuite.Decrypt(h, raw) } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/internal/ciphersuite/tls_ecdhe_rsa_with_aes_128_gcm_sha256.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/internal/ciphersuite/tls_ecdhe_rsa_with_aes_128_gcm_sha256.go similarity index 81% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/internal/ciphersuite/tls_ecdhe_rsa_with_aes_128_gcm_sha256.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/internal/ciphersuite/tls_ecdhe_rsa_with_aes_128_gcm_sha256.go index 478a2e0dc..b78969111 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/internal/ciphersuite/tls_ecdhe_rsa_with_aes_128_gcm_sha256.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/internal/ciphersuite/tls_ecdhe_rsa_with_aes_128_gcm_sha256.go @@ -3,19 +3,19 @@ package ciphersuite -import "github.com/pion/dtls/v2/pkg/crypto/clientcertificate" +import "github.com/pion/dtls/v3/pkg/crypto/clientcertificate" -// TLSEcdheRsaWithAes128GcmSha256 implements the TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 CipherSuite +// TLSEcdheRsaWithAes128GcmSha256 implements the TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 CipherSuite. type TLSEcdheRsaWithAes128GcmSha256 struct { TLSEcdheEcdsaWithAes128GcmSha256 } -// CertificateType returns what type of certificate this CipherSuite exchanges +// CertificateType returns what type of certificate this CipherSuite exchanges. func (c *TLSEcdheRsaWithAes128GcmSha256) CertificateType() clientcertificate.Type { return clientcertificate.RSASign } -// ID returns the ID of the CipherSuite +// ID returns the ID of the CipherSuite. func (c *TLSEcdheRsaWithAes128GcmSha256) ID() ID { return TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/internal/ciphersuite/tls_ecdhe_rsa_with_aes_256_cbc_sha.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/internal/ciphersuite/tls_ecdhe_rsa_with_aes_256_cbc_sha.go similarity index 81% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/internal/ciphersuite/tls_ecdhe_rsa_with_aes_256_cbc_sha.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/internal/ciphersuite/tls_ecdhe_rsa_with_aes_256_cbc_sha.go index 8e88ee639..deb20dd94 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/internal/ciphersuite/tls_ecdhe_rsa_with_aes_256_cbc_sha.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/internal/ciphersuite/tls_ecdhe_rsa_with_aes_256_cbc_sha.go @@ -3,19 +3,19 @@ package ciphersuite -import "github.com/pion/dtls/v2/pkg/crypto/clientcertificate" +import "github.com/pion/dtls/v3/pkg/crypto/clientcertificate" -// TLSEcdheRsaWithAes256CbcSha implements the TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA CipherSuite +// TLSEcdheRsaWithAes256CbcSha implements the TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA CipherSuite. type TLSEcdheRsaWithAes256CbcSha struct { TLSEcdheEcdsaWithAes256CbcSha } -// CertificateType returns what type of certificate this CipherSuite exchanges +// CertificateType returns what type of certificate this CipherSuite exchanges. func (c *TLSEcdheRsaWithAes256CbcSha) CertificateType() clientcertificate.Type { return clientcertificate.RSASign } -// ID returns the ID of the CipherSuite +// ID returns the ID of the CipherSuite. func (c *TLSEcdheRsaWithAes256CbcSha) ID() ID { return TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/internal/ciphersuite/tls_ecdhe_rsa_with_aes_256_gcm_sha384.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/internal/ciphersuite/tls_ecdhe_rsa_with_aes_256_gcm_sha384.go similarity index 81% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/internal/ciphersuite/tls_ecdhe_rsa_with_aes_256_gcm_sha384.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/internal/ciphersuite/tls_ecdhe_rsa_with_aes_256_gcm_sha384.go index 752fb529c..f7d7049a8 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/internal/ciphersuite/tls_ecdhe_rsa_with_aes_256_gcm_sha384.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/internal/ciphersuite/tls_ecdhe_rsa_with_aes_256_gcm_sha384.go @@ -3,19 +3,19 @@ package ciphersuite -import "github.com/pion/dtls/v2/pkg/crypto/clientcertificate" +import "github.com/pion/dtls/v3/pkg/crypto/clientcertificate" -// TLSEcdheRsaWithAes256GcmSha384 implements the TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 CipherSuite +// TLSEcdheRsaWithAes256GcmSha384 implements the TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 CipherSuite. type TLSEcdheRsaWithAes256GcmSha384 struct { TLSEcdheEcdsaWithAes256GcmSha384 } -// CertificateType returns what type of certificate this CipherSuite exchanges +// CertificateType returns what type of certificate this CipherSuite exchanges. func (c *TLSEcdheRsaWithAes256GcmSha384) CertificateType() clientcertificate.Type { return clientcertificate.RSASign } -// ID returns the ID of the CipherSuite +// ID returns the ID of the CipherSuite. func (c *TLSEcdheRsaWithAes256GcmSha384) ID() ID { return TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/internal/ciphersuite/tls_psk_with_aes_128_cbc_sha256.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/internal/ciphersuite/tls_psk_with_aes_128_cbc_sha256.go similarity index 73% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/internal/ciphersuite/tls_psk_with_aes_128_cbc_sha256.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/internal/ciphersuite/tls_psk_with_aes_128_cbc_sha256.go index 7336ad946..32507cdc3 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/internal/ciphersuite/tls_psk_with_aes_128_cbc_sha256.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/internal/ciphersuite/tls_psk_with_aes_128_cbc_sha256.go @@ -9,33 +9,33 @@ import ( "hash" "sync/atomic" - "github.com/pion/dtls/v2/pkg/crypto/ciphersuite" - "github.com/pion/dtls/v2/pkg/crypto/clientcertificate" - "github.com/pion/dtls/v2/pkg/crypto/prf" - "github.com/pion/dtls/v2/pkg/protocol/recordlayer" + "github.com/pion/dtls/v3/pkg/crypto/ciphersuite" + "github.com/pion/dtls/v3/pkg/crypto/clientcertificate" + "github.com/pion/dtls/v3/pkg/crypto/prf" + "github.com/pion/dtls/v3/pkg/protocol/recordlayer" ) -// TLSPskWithAes128CbcSha256 implements the TLS_PSK_WITH_AES_128_CBC_SHA256 CipherSuite +// TLSPskWithAes128CbcSha256 implements the TLS_PSK_WITH_AES_128_CBC_SHA256 CipherSuite. type TLSPskWithAes128CbcSha256 struct { cbc atomic.Value // *cryptoCBC } -// CertificateType returns what type of certificate this CipherSuite exchanges +// CertificateType returns what type of certificate this CipherSuite exchanges. func (c *TLSPskWithAes128CbcSha256) CertificateType() clientcertificate.Type { return clientcertificate.Type(0) } -// KeyExchangeAlgorithm controls what key exchange algorithm is using during the handshake +// KeyExchangeAlgorithm controls what key exchange algorithm is using during the handshake. func (c *TLSPskWithAes128CbcSha256) KeyExchangeAlgorithm() KeyExchangeAlgorithm { return KeyExchangeAlgorithmPsk } -// ECC uses Elliptic Curve Cryptography +// ECC uses Elliptic Curve Cryptography. func (c *TLSPskWithAes128CbcSha256) ECC() bool { return false } -// ID returns the ID of the CipherSuite +// ID returns the ID of the CipherSuite. func (c *TLSPskWithAes128CbcSha256) ID() ID { return TLS_PSK_WITH_AES_128_CBC_SHA256 } @@ -44,23 +44,23 @@ func (c *TLSPskWithAes128CbcSha256) String() string { return "TLS_PSK_WITH_AES_128_CBC_SHA256" } -// HashFunc returns the hashing func for this CipherSuite +// HashFunc returns the hashing func for this CipherSuite. func (c *TLSPskWithAes128CbcSha256) HashFunc() func() hash.Hash { return sha256.New } -// AuthenticationType controls what authentication method is using during the handshake +// AuthenticationType controls what authentication method is using during the handshake. func (c *TLSPskWithAes128CbcSha256) AuthenticationType() AuthenticationType { return AuthenticationTypePreSharedKey } // IsInitialized returns if the CipherSuite has keying material and can -// encrypt/decrypt packets +// encrypt/decrypt packets. func (c *TLSPskWithAes128CbcSha256) IsInitialized() bool { return c.cbc.Load() != nil } -// Init initializes the internal Cipher with keying material +// Init initializes the internal Cipher with keying material. func (c *TLSPskWithAes128CbcSha256) Init(masterSecret, clientRandom, serverRandom []byte, isClient bool) error { const ( prfMacLen = 32 @@ -68,7 +68,9 @@ func (c *TLSPskWithAes128CbcSha256) Init(masterSecret, clientRandom, serverRando prfIvLen = 16 ) - keys, err := prf.GenerateEncryptionKeys(masterSecret, clientRandom, serverRandom, prfMacLen, prfKeyLen, prfIvLen, c.HashFunc()) + keys, err := prf.GenerateEncryptionKeys( + masterSecret, clientRandom, serverRandom, prfMacLen, prfKeyLen, prfIvLen, c.HashFunc(), + ) if err != nil { return err } @@ -92,7 +94,7 @@ func (c *TLSPskWithAes128CbcSha256) Init(masterSecret, clientRandom, serverRando return err } -// Encrypt encrypts a single TLS RecordLayer +// Encrypt encrypts a single TLS RecordLayer. func (c *TLSPskWithAes128CbcSha256) Encrypt(pkt *recordlayer.RecordLayer, raw []byte) ([]byte, error) { cipherSuite, ok := c.cbc.Load().(*ciphersuite.CBC) if !ok { @@ -102,12 +104,12 @@ func (c *TLSPskWithAes128CbcSha256) Encrypt(pkt *recordlayer.RecordLayer, raw [] return cipherSuite.Encrypt(pkt, raw) } -// Decrypt decrypts a single TLS RecordLayer -func (c *TLSPskWithAes128CbcSha256) Decrypt(raw []byte) ([]byte, error) { +// Decrypt decrypts a single TLS RecordLayer. +func (c *TLSPskWithAes128CbcSha256) Decrypt(h recordlayer.Header, raw []byte) ([]byte, error) { cipherSuite, ok := c.cbc.Load().(*ciphersuite.CBC) if !ok { return nil, fmt.Errorf("%w, unable to decrypt", errCipherSuiteNotInit) } - return cipherSuite.Decrypt(raw) + return cipherSuite.Decrypt(h, raw) } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/internal/ciphersuite/tls_psk_with_aes_128_ccm.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/internal/ciphersuite/tls_psk_with_aes_128_ccm.go new file mode 100644 index 000000000..0b802fc8c --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/internal/ciphersuite/tls_psk_with_aes_128_ccm.go @@ -0,0 +1,21 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + +package ciphersuite + +import ( + "github.com/pion/dtls/v3/pkg/crypto/ciphersuite" + "github.com/pion/dtls/v3/pkg/crypto/clientcertificate" +) + +// NewTLSPskWithAes128Ccm returns the TLS_PSK_WITH_AES_128_CCM CipherSuite. +func NewTLSPskWithAes128Ccm() *Aes128Ccm { + return newAes128Ccm( + clientcertificate.Type(0), + TLS_PSK_WITH_AES_128_CCM, + true, + ciphersuite.CCMTagLength, + KeyExchangeAlgorithmPsk, + false, + ) +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/internal/ciphersuite/tls_psk_with_aes_128_ccm8.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/internal/ciphersuite/tls_psk_with_aes_128_ccm8.go new file mode 100644 index 000000000..c6bf6dc59 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/internal/ciphersuite/tls_psk_with_aes_128_ccm8.go @@ -0,0 +1,21 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + +package ciphersuite + +import ( + "github.com/pion/dtls/v3/pkg/crypto/ciphersuite" + "github.com/pion/dtls/v3/pkg/crypto/clientcertificate" +) + +// NewTLSPskWithAes128Ccm8 returns the TLS_PSK_WITH_AES_128_CCM_8 CipherSuite. +func NewTLSPskWithAes128Ccm8() *Aes128Ccm { + return newAes128Ccm( + clientcertificate.Type(0), + TLS_PSK_WITH_AES_128_CCM_8, + true, + ciphersuite.CCMTagLength8, + KeyExchangeAlgorithmPsk, + false, + ) +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/internal/ciphersuite/tls_psk_with_aes_128_gcm_sha256.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/internal/ciphersuite/tls_psk_with_aes_128_gcm_sha256.go similarity index 83% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/internal/ciphersuite/tls_psk_with_aes_128_gcm_sha256.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/internal/ciphersuite/tls_psk_with_aes_128_gcm_sha256.go index 8ab5b89a8..bc50d562b 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/internal/ciphersuite/tls_psk_with_aes_128_gcm_sha256.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/internal/ciphersuite/tls_psk_with_aes_128_gcm_sha256.go @@ -3,24 +3,24 @@ package ciphersuite -import "github.com/pion/dtls/v2/pkg/crypto/clientcertificate" +import "github.com/pion/dtls/v3/pkg/crypto/clientcertificate" -// TLSPskWithAes128GcmSha256 implements the TLS_PSK_WITH_AES_128_GCM_SHA256 CipherSuite +// TLSPskWithAes128GcmSha256 implements the TLS_PSK_WITH_AES_128_GCM_SHA256 CipherSuite. type TLSPskWithAes128GcmSha256 struct { TLSEcdheEcdsaWithAes128GcmSha256 } -// CertificateType returns what type of certificate this CipherSuite exchanges +// CertificateType returns what type of certificate this CipherSuite exchanges. func (c *TLSPskWithAes128GcmSha256) CertificateType() clientcertificate.Type { return clientcertificate.Type(0) } -// KeyExchangeAlgorithm controls what key exchange algorithm is using during the handshake +// KeyExchangeAlgorithm controls what key exchange algorithm is using during the handshake. func (c *TLSPskWithAes128GcmSha256) KeyExchangeAlgorithm() KeyExchangeAlgorithm { return KeyExchangeAlgorithmPsk } -// ID returns the ID of the CipherSuite +// ID returns the ID of the CipherSuite. func (c *TLSPskWithAes128GcmSha256) ID() ID { return TLS_PSK_WITH_AES_128_GCM_SHA256 } @@ -29,7 +29,7 @@ func (c *TLSPskWithAes128GcmSha256) String() string { return "TLS_PSK_WITH_AES_128_GCM_SHA256" } -// AuthenticationType controls what authentication method is using during the handshake +// AuthenticationType controls what authentication method is using during the handshake. func (c *TLSPskWithAes128GcmSha256) AuthenticationType() AuthenticationType { return AuthenticationTypePreSharedKey } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/internal/ciphersuite/tls_psk_with_aes_256_ccm8.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/internal/ciphersuite/tls_psk_with_aes_256_ccm8.go new file mode 100644 index 000000000..771a1d42e --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/internal/ciphersuite/tls_psk_with_aes_256_ccm8.go @@ -0,0 +1,21 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + +package ciphersuite + +import ( + "github.com/pion/dtls/v3/pkg/crypto/ciphersuite" + "github.com/pion/dtls/v3/pkg/crypto/clientcertificate" +) + +// NewTLSPskWithAes256Ccm8 returns the TLS_PSK_WITH_AES_256_CCM_8 CipherSuite. +func NewTLSPskWithAes256Ccm8() *Aes256Ccm { + return newAes256Ccm( + clientcertificate.Type(0), + TLS_PSK_WITH_AES_256_CCM_8, + true, + ciphersuite.CCMTagLength8, + KeyExchangeAlgorithmPsk, + false, + ) +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/internal/ciphersuite/types/authentication_type.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/internal/ciphersuite/types/authentication_type.go similarity index 86% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/internal/ciphersuite/types/authentication_type.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/internal/ciphersuite/types/authentication_type.go index 2da21e642..09681cec5 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/internal/ciphersuite/types/authentication_type.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/internal/ciphersuite/types/authentication_type.go @@ -3,10 +3,10 @@ package types -// AuthenticationType controls what authentication method is using during the handshake +// AuthenticationType controls what authentication method is using during the handshake. type AuthenticationType int -// AuthenticationType Enums +// AuthenticationType Enums. const ( AuthenticationTypeCertificate AuthenticationType = iota + 1 AuthenticationTypePreSharedKey diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/internal/ciphersuite/types/key_exchange_algorithm.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/internal/ciphersuite/types/key_exchange_algorithm.go similarity index 94% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/internal/ciphersuite/types/key_exchange_algorithm.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/internal/ciphersuite/types/key_exchange_algorithm.go index c2c39113a..5b59f2410 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/internal/ciphersuite/types/key_exchange_algorithm.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/internal/ciphersuite/types/key_exchange_algorithm.go @@ -7,7 +7,7 @@ package types // KeyExchangeAlgorithm controls what exchange algorithm was chosen. type KeyExchangeAlgorithm int -// KeyExchangeAlgorithm Bitmask +// KeyExchangeAlgorithm Bitmask. const ( KeyExchangeAlgorithmNone KeyExchangeAlgorithm = 0 KeyExchangeAlgorithmPsk KeyExchangeAlgorithm = iota << 1 diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/internal/closer/closer.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/internal/closer/closer.go similarity index 70% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/internal/closer/closer.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/internal/closer/closer.go index bfa171cda..a1c25f379 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/internal/closer/closer.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/internal/closer/closer.go @@ -8,41 +8,43 @@ import ( "context" ) -// Closer allows for each signaling a channel for shutdown +// Closer allows for each signaling a channel for shutdown. type Closer struct { - ctx context.Context + ctx context.Context //nolint:containedctx closeFunc func() } -// NewCloser creates a new instance of Closer +// NewCloser creates a new instance of Closer. func NewCloser() *Closer { ctx, closeFunc := context.WithCancel(context.Background()) + return &Closer{ ctx: ctx, closeFunc: closeFunc, } } -// NewCloserWithParent creates a new instance of Closer with a parent context +// NewCloserWithParent creates a new instance of Closer with a parent context. func NewCloserWithParent(ctx context.Context) *Closer { ctx, closeFunc := context.WithCancel(ctx) + return &Closer{ ctx: ctx, closeFunc: closeFunc, } } -// Done returns a channel signaling when it is done +// Done returns a channel signaling when it is done. func (c *Closer) Done() <-chan struct{} { return c.ctx.Done() } -// Err returns an error of the context +// Err returns an error of the context. func (c *Closer) Err() error { return c.ctx.Err() } -// Close sends a signal to trigger the ctx done channel +// Close sends a signal to trigger the ctx done channel. func (c *Closer) Close() { c.closeFunc() } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/internal/net/buffer.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/internal/net/buffer.go new file mode 100644 index 000000000..c763f15e4 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/internal/net/buffer.go @@ -0,0 +1,242 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + +// Package net implements DTLS specific networking primitives. +// NOTE: this package is an adaption of pion/transport/packetio that allows for +// storing a remote address alongside each packet in the buffer and implements +// relevant methods of net.PacketConn. If possible, the updates made in this +// repository will be reflected back upstream. If not, it is likely that this +// will be moved to a public package in this repository. +// +// This package was migrated from pion/transport/packetio at +// https://github.com/pion/transport/commit/6890c795c807a617c054149eee40a69d7fdfbfdb +package net + +import ( + "bytes" + "errors" + "io" + "net" + "sync" + "time" + + "github.com/pion/transport/v3/deadline" +) + +// ErrTimeout indicates that deadline was reached before operation could be +// completed. +var ErrTimeout = errors.New("buffer: i/o timeout") + +// AddrPacket is a packet payload and the associated remote address from which +// it was received. +type AddrPacket struct { + addr net.Addr + data bytes.Buffer +} + +// PacketBuffer is a circular buffer for network packets. Each slot in the +// buffer contains the remote address from which the packet was received, as +// well as the packet data. +type PacketBuffer struct { + mutex sync.Mutex + + packets []AddrPacket + write, read int + + // full indicates whether the buffer is full, which is needed to distinguish + // when the write pointer and read pointer are at the same index. + full bool + + notify chan struct{} + closed bool + + readDeadline *deadline.Deadline +} + +// NewPacketBuffer creates a new PacketBuffer. +func NewPacketBuffer() *PacketBuffer { + return &PacketBuffer{ + readDeadline: deadline.New(), + // In the narrow context in which this package is currently used, there + // will always be at least one packet written to the buffer. Therefore, + // we opt to allocate with size of 1 during construction, rather than + // waiting until that first packet is written. + packets: make([]AddrPacket, 1), + full: false, + } +} + +// WriteTo writes a single packet to the buffer. The supplied address will +// remain associated with the packet. +func (b *PacketBuffer) WriteTo(pkt []byte, addr net.Addr) (int, error) { + b.mutex.Lock() + + if b.closed { + b.mutex.Unlock() + + return 0, io.ErrClosedPipe + } + + var notify chan struct{} + if b.notify != nil { + notify = b.notify + b.notify = nil + } + + // Check to see if we are full. + if b.full { + // If so, grow AddrPacket buffer. + var newSize int + if len(b.packets) < 128 { + // Double the number of packets. + newSize = len(b.packets) * 2 + } else { + // Increase the number of packets by 25%. + newSize = 5 * len(b.packets) / 4 + } + newBuf := make([]AddrPacket, newSize) + var n int + if b.read < b.write { + n = copy(newBuf, b.packets[b.read:b.write]) + } else { + n = copy(newBuf, b.packets[b.read:]) + n += copy(newBuf[n:], b.packets[:b.write]) + } + + b.packets = newBuf + + // Update write pointer to point to new location and mark buffer as not + // full. + b.write = n + b.full = false + } + + // Store the packet at the write pointer. + packet := &b.packets[b.write] + packet.data.Reset() + n, err := packet.data.Write(pkt) + if err != nil { + b.mutex.Unlock() + + return n, err + } + packet.addr = addr + + // Increment write pointer. + b.write++ + + // If the write pointer is equal to the length of the buffer, wrap around. + if len(b.packets) == b.write { + b.write = 0 + } + + // If a write resulted in making write and read pointers equivalent, then we + // are full. + if b.write == b.read { + b.full = true + } + + b.mutex.Unlock() + + if notify != nil { + close(notify) + } + + return n, nil +} + +// ReadFrom reads a single packet from the buffer, or blocks until one is +// available. +func (b *PacketBuffer) ReadFrom(packet []byte) (n int, addr net.Addr, err error) { //nolint:cyclop + select { + case <-b.readDeadline.Done(): + return 0, nil, ErrTimeout + default: + } + + for { + b.mutex.Lock() + + if b.read != b.write || b.full { + ap := b.packets[b.read] + if len(packet) < ap.data.Len() { + b.mutex.Unlock() + + return 0, nil, io.ErrShortBuffer + } + + // Copy packet data from buffer. + n, err := ap.data.Read(packet) + if err != nil { + b.mutex.Unlock() + + return n, nil, err + } + + // Advance read pointer. + b.read++ + if len(b.packets) == b.read { + b.read = 0 + } + + // If we were full before reading and have successfully read, we are + // no longer full. + if b.full { + b.full = false + } + + b.mutex.Unlock() + + return n, ap.addr, nil + } + + if b.closed { + b.mutex.Unlock() + + return 0, nil, io.EOF + } + + if b.notify == nil { + b.notify = make(chan struct{}) + } + notify := b.notify + b.mutex.Unlock() + + select { + case <-b.readDeadline.Done(): + return 0, nil, ErrTimeout + case <-notify: + } + } +} + +// Close closes the buffer, allowing unread packets to be read, but erroring on +// any new writes. +func (b *PacketBuffer) Close() (err error) { + b.mutex.Lock() + + if b.closed { + b.mutex.Unlock() + + return nil + } + + notify := b.notify + b.notify = nil + b.closed = true + + b.mutex.Unlock() + + if notify != nil { + close(notify) + } + + return nil +} + +// SetReadDeadline sets the read deadline for the buffer. +func (b *PacketBuffer) SetReadDeadline(t time.Time) error { + b.readDeadline.Set(t) + + return nil +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/internal/net/udp/packet_conn.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/internal/net/udp/packet_conn.go new file mode 100644 index 000000000..e3e214ce9 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/internal/net/udp/packet_conn.go @@ -0,0 +1,413 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + +// Package udp implements DTLS specific UDP networking primitives. +// NOTE: this package is an adaption of pion/transport/udp that allows for +// routing datagrams based on identifiers other than the remote address. The +// primary use case for this functionality is routing based on DTLS connection +// IDs. In order to allow for consumers of this package to treat connections as +// generic net.PackageConn, routing and identitier establishment is based on +// custom introspecion of datagrams, rather than direct intervention by +// consumers. If possible, the updates made in this repository will be reflected +// back upstream. If not, it is likely that this will be moved to a public +// package in this repository. +// +// This package was migrated from pion/transport/udp at +// https://github.com/pion/transport/commit/6890c795c807a617c054149eee40a69d7fdfbfdb +package udp + +import ( + "context" + "errors" + "net" + "sync" + "sync/atomic" + "time" + + idtlsnet "github.com/pion/dtls/v3/internal/net" + dtlsnet "github.com/pion/dtls/v3/pkg/net" + "github.com/pion/transport/v3/deadline" +) + +const ( + receiveMTU = 8192 + defaultListenBacklog = 128 // same as Linux default +) + +// Typed errors. +var ( + ErrClosedListener = errors.New("udp: listener closed") + ErrListenQueueExceeded = errors.New("udp: listen queue exceeded") +) + +// listener augments a connection-oriented Listener over a UDP PacketConn. +type listener struct { + pConn *net.UDPConn + + accepting atomic.Value // bool + acceptCh chan *PacketConn + doneCh chan struct{} + doneOnce sync.Once + acceptFilter func([]byte) bool + datagramRouter func([]byte) (string, bool) + connIdentifier func([]byte) (string, bool) + + connLock sync.Mutex + conns map[string]*PacketConn + connWG sync.WaitGroup + + readWG sync.WaitGroup + errClose atomic.Value // error + + readDoneCh chan struct{} + errRead atomic.Value // error +} + +// Accept waits for and returns the next connection to the listener. +func (l *listener) Accept() (net.PacketConn, net.Addr, error) { + select { + case c := <-l.acceptCh: + l.connWG.Add(1) + + return c, c.raddr, nil + + case <-l.readDoneCh: + err, _ := l.errRead.Load().(error) + + return nil, nil, err + + case <-l.doneCh: + return nil, nil, ErrClosedListener + } +} + +// Close closes the listener. +// Any blocked Accept operations will be unblocked and return errors. +func (l *listener) Close() error { + var err error + l.doneOnce.Do(func() { + l.accepting.Store(false) + close(l.doneCh) + + l.connLock.Lock() + // Close unaccepted connections + lclose: + for { + select { + case c := <-l.acceptCh: + close(c.doneCh) + // If we have an alternate identifier, remove it from the connection + // map. + if id := c.id.Load(); id != nil { + delete(l.conns, id.(string)) //nolint:forcetypeassert + } + // If we haven't already removed the remote address, remove it + // from the connection map. + if c.rmraddr.Load() == nil { + delete(l.conns, c.raddr.String()) + c.rmraddr.Store(true) + } + default: + break lclose + } + } + nConns := len(l.conns) + l.connLock.Unlock() + + l.connWG.Done() + + if nConns == 0 { + // Wait if this is the final connection. + l.readWG.Wait() + if errClose, ok := l.errClose.Load().(error); ok { + err = errClose + } + } else { + err = nil + } + }) + + return err +} + +// Addr returns the listener's network address. +func (l *listener) Addr() net.Addr { + return l.pConn.LocalAddr() +} + +// ListenConfig stores options for listening to an address. +type ListenConfig struct { + // Backlog defines the maximum length of the queue of pending + // connections. It is equivalent of the backlog argument of + // POSIX listen function. + // If a connection request arrives when the queue is full, + // the request will be silently discarded, unlike TCP. + // Set zero to use default value 128 which is same as Linux default. + Backlog int + + // AcceptFilter determines whether the new conn should be made for + // the incoming packet. If not set, any packet creates new conn. + AcceptFilter func([]byte) bool + + // DatagramRouter routes an incoming datagram to a connection by extracting + // an identifier from the its paylod + DatagramRouter func([]byte) (string, bool) + + // ConnectionIdentifier extracts an identifier from an outgoing packet. If + // the identifier is not already associated with the connection, it will be + // added. + ConnectionIdentifier func([]byte) (string, bool) +} + +// Listen creates a new listener based on the ListenConfig. +func (lc *ListenConfig) Listen(network string, laddr *net.UDPAddr) (dtlsnet.PacketListener, error) { + if lc.Backlog == 0 { + lc.Backlog = defaultListenBacklog + } + + conn, err := net.ListenUDP(network, laddr) + if err != nil { + return nil, err + } + + packetListener := &listener{ + pConn: conn, + acceptCh: make(chan *PacketConn, lc.Backlog), + conns: make(map[string]*PacketConn), + doneCh: make(chan struct{}), + acceptFilter: lc.AcceptFilter, + datagramRouter: lc.DatagramRouter, + connIdentifier: lc.ConnectionIdentifier, + readDoneCh: make(chan struct{}), + } + + packetListener.accepting.Store(true) + packetListener.connWG.Add(1) + packetListener.readWG.Add(2) // wait readLoop and Close execution routine + + go packetListener.readLoop() + go func() { + packetListener.connWG.Wait() + if err := packetListener.pConn.Close(); err != nil { + packetListener.errClose.Store(err) + } + packetListener.readWG.Done() + }() + + return packetListener, nil +} + +// Listen creates a new listener using default ListenConfig. +func Listen(network string, laddr *net.UDPAddr) (dtlsnet.PacketListener, error) { + return (&ListenConfig{}).Listen(network, laddr) +} + +// readLoop dispatches packets to the proper connection, creating a new one if +// necessary, until all connections are closed. +func (l *listener) readLoop() { + defer l.readWG.Done() + defer close(l.readDoneCh) + + buf := make([]byte, receiveMTU) + + for { + n, raddr, err := l.pConn.ReadFrom(buf) + if err != nil { + l.errRead.Store(err) + + return + } + conn, ok, err := l.getConn(raddr, buf[:n]) + if err != nil { + continue + } + if ok { + _, _ = conn.buffer.WriteTo(buf[:n], raddr) + } + } +} + +// getConn gets an existing connection or creates a new one. +func (l *listener) getConn(raddr net.Addr, buf []byte) (*PacketConn, bool, error) { //nolint:cyclop + l.connLock.Lock() + defer l.connLock.Unlock() + // If we have a custom resolver, use it. + if l.datagramRouter != nil { + if id, ok := l.datagramRouter(buf); ok { + if conn, ok := l.conns[id]; ok { + return conn, true, nil + } + } + } + + // If we don't have a custom resolver, or we were unable to find an + // associated connection, fall back to remote address. + conn, ok := l.conns[raddr.String()] + if !ok { + if isAccepting, ok := l.accepting.Load().(bool); !isAccepting || !ok { + return nil, false, ErrClosedListener + } + if l.acceptFilter != nil { + if !l.acceptFilter(buf) { + return nil, false, nil + } + } + conn = l.newPacketConn(raddr) + select { + case l.acceptCh <- conn: + l.conns[raddr.String()] = conn + default: + return nil, false, ErrListenQueueExceeded + } + } + + return conn, true, nil +} + +// PacketConn is a net.PacketConn implementation that is able to dictate its +// routing ID via an alternate identifier from its remote address. Internal +// buffering is performed for reads, and writes are passed through to the +// underlying net.PacketConn. +type PacketConn struct { + listener *listener + + raddr net.Addr + rmraddr atomic.Value // bool + id atomic.Value // string + + buffer *idtlsnet.PacketBuffer + + doneCh chan struct{} + doneOnce sync.Once + + writeDeadline *deadline.Deadline +} + +// newPacketConn constructs a new PacketConn. +func (l *listener) newPacketConn(raddr net.Addr) *PacketConn { + return &PacketConn{ + listener: l, + raddr: raddr, + buffer: idtlsnet.NewPacketBuffer(), + doneCh: make(chan struct{}), + writeDeadline: deadline.New(), + } +} + +// ReadFrom reads a single packet payload and its associated remote address from +// the underlying buffer. +func (c *PacketConn) ReadFrom(buff []byte) (int, net.Addr, error) { + return c.buffer.ReadFrom(buff) +} + +// WriteTo writes len(payload) bytes from payload to the specified address. +func (c *PacketConn) WriteTo(payload []byte, addr net.Addr) (n int, err error) { + // If we have a connection identifier, check to see if the outgoing packet + // sets it. + if c.listener.connIdentifier != nil { + id := c.id.Load() + // Only update establish identifier if we haven't already done so. + if id == nil { + candidate, ok := c.listener.connIdentifier(payload) + // If we have an identifier, add entry to connection map. + if ok { + c.listener.connLock.Lock() + c.listener.conns[candidate] = c + c.listener.connLock.Unlock() + c.id.Store(candidate) + } + } + // If we are writing to a remote address that differs from the initial, + // we have an alternate identifier established, and we haven't already + // freed the remote address, free the remote address to be used by + // another connection. + // Note: this strategy results in holding onto a remote address after it + // is potentially no longer in use by the client. However, releasing + // earlier means that we could miss some packets that should have been + // routed to this connection. Ideally, we would drop the connection + // entry for the remote address as soon as the client starts sending + // using an alternate identifier, but in practice this proves + // challenging because any client could spoof a connection identifier, + // resulting in the remote address entry being dropped prior to the + // "real" client transitioning to sending using the alternate + // identifier. + if id != nil && c.rmraddr.Load() == nil && addr.String() != c.raddr.String() { + c.listener.connLock.Lock() + delete(c.listener.conns, c.raddr.String()) + c.rmraddr.Store(true) + c.listener.connLock.Unlock() + } + } + + select { + case <-c.writeDeadline.Done(): + return 0, context.DeadlineExceeded + default: + } + + return c.listener.pConn.WriteTo(payload, addr) +} + +// Close closes the conn and releases any Read calls. +func (c *PacketConn) Close() error { + var err error + c.doneOnce.Do(func() { + c.listener.connWG.Done() + close(c.doneCh) + c.listener.connLock.Lock() + // If we have an alternate identifier, remove it from the connection + // map. + if id := c.id.Load(); id != nil { + delete(c.listener.conns, id.(string)) //nolint:forcetypeassert + } + // If we haven't already removed the remote address, remove it from the + // connection map. + if c.rmraddr.Load() == nil { + delete(c.listener.conns, c.raddr.String()) + c.rmraddr.Store(true) + } + nConns := len(c.listener.conns) + c.listener.connLock.Unlock() + + if isAccepting, ok := c.listener.accepting.Load().(bool); nConns == 0 && !isAccepting && ok { + // Wait if this is the final connection + c.listener.readWG.Wait() + if errClose, ok := c.listener.errClose.Load().(error); ok { + err = errClose + } + } else { + err = nil + } + + if errBuf := c.buffer.Close(); errBuf != nil && err == nil { + err = errBuf + } + }) + + return err +} + +// LocalAddr implements net.PacketConn.LocalAddr. +func (c *PacketConn) LocalAddr() net.Addr { + return c.listener.pConn.LocalAddr() +} + +// SetDeadline implements net.PacketConn.SetDeadline. +func (c *PacketConn) SetDeadline(t time.Time) error { + c.writeDeadline.Set(t) + + return c.SetReadDeadline(t) +} + +// SetReadDeadline implements net.PacketConn.SetReadDeadline. +func (c *PacketConn) SetReadDeadline(t time.Time) error { + return c.buffer.SetReadDeadline(t) +} + +// SetWriteDeadline implements net.PacketConn.SetWriteDeadline. +func (c *PacketConn) SetWriteDeadline(t time.Time) error { + c.writeDeadline.Set(t) + // Write deadline of underlying connection should not be changed + // since the connection can be shared. + return nil +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/internal/util/util.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/internal/util/util.go similarity index 55% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/internal/util/util.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/internal/util/util.go index 685910fc2..8ebbcd44f 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/internal/util/util.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/internal/util/util.go @@ -6,9 +6,11 @@ package util import ( "encoding/binary" + + "golang.org/x/crypto/cryptobyte" ) -// BigEndianUint24 returns the value of a big endian uint24 +// BigEndianUint24 returns the value of a big endian uint24. func BigEndianUint24(raw []byte) uint32 { if len(raw) < 3 { return 0 @@ -16,27 +18,36 @@ func BigEndianUint24(raw []byte) uint32 { rawCopy := make([]byte, 4) copy(rawCopy[1:], raw) + return binary.BigEndian.Uint32(rawCopy) } -// PutBigEndianUint24 encodes a uint24 and places into out +// PutBigEndianUint24 encodes a uint24 and places into out. func PutBigEndianUint24(out []byte, in uint32) { tmp := make([]byte, 4) binary.BigEndian.PutUint32(tmp, in) copy(out, tmp[1:]) } -// PutBigEndianUint48 encodes a uint64 and places into out +// PutBigEndianUint48 encodes a uint64 and places into out. func PutBigEndianUint48(out []byte, in uint64) { tmp := make([]byte, 8) binary.BigEndian.PutUint64(tmp, in) copy(out, tmp[2:]) } -// Max returns the larger value +// Max returns the larger value. func Max(a, b int) int { if a > b { return a } + return b } + +// AddUint48 appends a big-endian, 48-bit value to the byte string. +// Remove if / when https://github.com/golang/crypto/pull/265 is merged +// upstream. +func AddUint48(b *cryptobyte.Builder, v uint64) { + b.AddBytes([]byte{byte(v >> 40), byte(v >> 32), byte(v >> 24), byte(v >> 16), byte(v >> 8), byte(v)}) +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/listener.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/listener.go similarity index 69% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/listener.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/listener.go index 190d236c7..3583d0308 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/listener.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/listener.go @@ -6,12 +6,13 @@ package dtls import ( "net" - "github.com/pion/dtls/v2/pkg/protocol" - "github.com/pion/dtls/v2/pkg/protocol/recordlayer" - "github.com/pion/transport/v2/udp" + "github.com/pion/dtls/v3/internal/net/udp" + dtlsnet "github.com/pion/dtls/v3/pkg/net" + "github.com/pion/dtls/v3/pkg/protocol" + "github.com/pion/dtls/v3/pkg/protocol/recordlayer" ) -// Listen creates a DTLS listener +// Listen creates a DTLS listener. func Listen(network string, laddr *net.UDPAddr, config *Config) (net.Listener, error) { if err := validateConfig(config); err != nil { return nil, err @@ -27,13 +28,21 @@ func Listen(network string, laddr *net.UDPAddr, config *Config) (net.Listener, e if err := h.Unmarshal(pkts[0]); err != nil { return false } + return h.ContentType == protocol.ContentTypeHandshake }, } + // If connection ID support is enabled, then they must be supported in + // routing. + if config.ConnectionIDGenerator != nil { + lc.DatagramRouter = cidDatagramRouter(len(config.ConnectionIDGenerator())) + lc.ConnectionIdentifier = cidConnIdentifier() + } parent, err := lc.Listen(network, laddr) if err != nil { return nil, err } + return &listener{ config: config, parent: parent, @@ -41,7 +50,7 @@ func Listen(network string, laddr *net.UDPAddr, config *Config) (net.Listener, e } // NewListener creates a DTLS listener which accepts connections from an inner Listener. -func NewListener(inner net.Listener, config *Config) (net.Listener, error) { +func NewListener(inner dtlsnet.PacketListener, config *Config) (net.Listener, error) { if err := validateConfig(config); err != nil { return nil, err } @@ -52,22 +61,21 @@ func NewListener(inner net.Listener, config *Config) (net.Listener, error) { }, nil } -// listener represents a DTLS listener +// listener represents a DTLS listener. type listener struct { config *Config - parent net.Listener + parent dtlsnet.PacketListener } // Accept waits for and returns the next connection to the listener. // You have to either close or read on all connection that are created. -// Connection handshake will timeout using ConnectContextMaker in the Config. -// If you want to specify the timeout duration, set ConnectContextMaker. func (l *listener) Accept() (net.Conn, error) { - c, err := l.parent.Accept() + c, raddr, err := l.parent.Accept() if err != nil { return nil, err } - return Server(c, l.config) + + return Server(c, raddr, l.config) } // Close closes the listener. diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/packet.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/packet.go similarity index 72% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/packet.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/packet.go index 55d6272ee..c224eff1b 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/packet.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/packet.go @@ -3,10 +3,13 @@ package dtls -import "github.com/pion/dtls/v2/pkg/protocol/recordlayer" +import ( + "github.com/pion/dtls/v3/pkg/protocol/recordlayer" +) type packet struct { record *recordlayer.RecordLayer shouldEncrypt bool + shouldWrapCID bool resetLocalSequenceNumber bool } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/crypto/ccm/ccm.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/crypto/ccm/ccm.go similarity index 89% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/crypto/ccm/ccm.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/crypto/ccm/ccm.go index d6e6fc479..bc268deeb 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/crypto/ccm/ccm.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/crypto/ccm/ccm.go @@ -65,7 +65,8 @@ func NewCCM(b cipher.Block, tagsize, noncesize int) (CCM, error) { if lensize < 2 || lensize > 8 { return nil, errInvalidNonceSize } - c := &ccm{b: b, M: uint8(tagsize), L: uint8(lensize)} + c := &ccm{b: b, M: uint8(tagsize), L: uint8(lensize)} //nolint:gosec // G114 + return c, nil } @@ -74,14 +75,15 @@ func (c *ccm) Overhead() int { return int(c.M) } func (c *ccm) MaxLength() int { return maxlen(c.L, c.Overhead()) } func maxlen(l uint8, tagsize int) int { - max := (uint64(1) << (8 * l)) - 1 - if m64 := uint64(math.MaxInt64) - uint64(tagsize); l > 8 || max > m64 { - max = m64 // The maximum lentgh on a 64bit arch + mLen := (uint64(1) << (8 * l)) - 1 + if m64 := uint64(math.MaxInt64) - uint64(tagsize); l > 8 || mLen > m64 { //nolint:gosec // G114 + mLen = m64 // The maximum lentgh on a 64bit arch } - if max != uint64(int(max)) { + if mLen != uint64(int(mLen)) { //nolint:gosec // G114 return math.MaxInt32 - tagsize // We have only 32bit int's } - return int(max) + + return int(mLen) //nolint:gosec // G114 } // MaxNonceLength returns the maximum nonce length for a given plaintext length. @@ -90,10 +92,11 @@ func maxlen(l uint8, tagsize int) int { func MaxNonceLength(pdatalen int) int { const tagsize = 16 for L := 2; L <= 8; L++ { - if maxlen(uint8(L), tagsize) >= pdatalen { + if maxlen(uint8(L), tagsize) >= pdatalen { //nolint:gosec // G115 return 15 - L } } + return 0 } @@ -137,20 +140,20 @@ func (c *ccm) tag(nonce, plaintext, adata []byte) ([]byte, error) { c.b.Encrypt(mac[:], mac[:]) var block [ccmBlockSize]byte - if n := uint64(len(adata)); n > 0 { + if adataLength := uint64(len(adata)); adataLength > 0 { //nolint:nestif // First adata block includes adata length i := 2 - if n <= 0xfeff { - binary.BigEndian.PutUint16(block[:i], uint16(n)) + if adataLength <= 0xfeff { + binary.BigEndian.PutUint16(block[:i], uint16(adataLength)) } else { block[0] = 0xfe block[1] = 0xff - if n < uint64(1<<32) { + if adataLength < uint64(1<<32) { i = 2 + 4 - binary.BigEndian.PutUint32(block[2:i], uint32(n)) + binary.BigEndian.PutUint32(block[2:i], uint32(adataLength)) //nolint:gosec // G115 } else { i = 2 + 8 - binary.BigEndian.PutUint64(block[2:i], n) + binary.BigEndian.PutUint64(block[2:i], adataLength) } } i = copy(block[i:], adata) @@ -170,6 +173,7 @@ func (c *ccm) tag(nonce, plaintext, adata []byte) ([]byte, error) { // second slice that aliases into it and contains only the extra bytes. If the // original slice has sufficient capacity then no allocation is performed. // From crypto/cipher/gcm.go +// . func sliceForAppend(in []byte, n int) (head, tail []byte) { if total := len(in) + n; cap(in) >= total { head = in[:total] @@ -178,6 +182,7 @@ func sliceForAppend(in []byte, n int) (head, tail []byte) { copy(head, in) } tail = head[len(in):] + return } @@ -207,6 +212,7 @@ func (c *ccm) Seal(dst, nonce, plaintext, adata []byte) []byte { ret, out := sliceForAppend(dst, len(plaintext)+int(c.M)) stream.XORKeyStream(out, plaintext) copy(out[len(plaintext):], tag) + return ret } @@ -250,5 +256,6 @@ func (c *ccm) Open(dst, nonce, ciphertext, adata []byte) ([]byte, error) { if subtle.ConstantTimeCompare(tag, expectedTag) != 1 { return nil, errOpen } + return append(dst, plaintext...), nil } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/crypto/ciphersuite/cbc.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/crypto/ciphersuite/cbc.go new file mode 100644 index 000000000..ab2588f9f --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/crypto/ciphersuite/cbc.go @@ -0,0 +1,250 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + +package ciphersuite + +import ( //nolint:gci + "crypto/aes" + "crypto/cipher" + "crypto/hmac" + "crypto/rand" + "encoding/binary" + "hash" + + "github.com/pion/dtls/v3/internal/util" + "github.com/pion/dtls/v3/pkg/crypto/prf" + "github.com/pion/dtls/v3/pkg/protocol" + "github.com/pion/dtls/v3/pkg/protocol/recordlayer" + "golang.org/x/crypto/cryptobyte" +) + +// block ciphers using cipher block chaining. +type cbcMode interface { + cipher.BlockMode + SetIV([]byte) +} + +// CBC Provides an API to Encrypt/Decrypt DTLS 1.2 Packets. +type CBC struct { + writeCBC, readCBC cbcMode + writeMac, readMac []byte + h prf.HashFunc +} + +// NewCBC creates a DTLS CBC Cipher. +func NewCBC( + localKey, localWriteIV, localMac, remoteKey, remoteWriteIV, remoteMac []byte, + hashFunc prf.HashFunc, +) (*CBC, error) { + writeBlock, err := aes.NewCipher(localKey) + if err != nil { + return nil, err + } + + readBlock, err := aes.NewCipher(remoteKey) + if err != nil { + return nil, err + } + + writeCBC, ok := cipher.NewCBCEncrypter(writeBlock, localWriteIV).(cbcMode) + if !ok { + return nil, errFailedToCast + } + + readCBC, ok := cipher.NewCBCDecrypter(readBlock, remoteWriteIV).(cbcMode) + if !ok { + return nil, errFailedToCast + } + + return &CBC{ + writeCBC: writeCBC, + writeMac: localMac, + + readCBC: readCBC, + readMac: remoteMac, + h: hashFunc, + }, nil +} + +// Encrypt encrypt a DTLS RecordLayer message. +func (c *CBC) Encrypt(pkt *recordlayer.RecordLayer, raw []byte) ([]byte, error) { + payload := raw[pkt.Header.Size():] + raw = raw[:pkt.Header.Size()] + blockSize := c.writeCBC.BlockSize() + + // Generate + Append MAC + h := pkt.Header + + var err error + var mac []byte + if h.ContentType == protocol.ContentTypeConnectionID { + mac, err = c.hmacCID(h.Epoch, h.SequenceNumber, h.Version, payload, c.writeMac, c.h, h.ConnectionID) + } else { + mac, err = c.hmac(h.Epoch, h.SequenceNumber, h.ContentType, h.Version, payload, c.writeMac, c.h) + } + if err != nil { + return nil, err + } + payload = append(payload, mac...) + + // Generate + Append padding + padding := make([]byte, blockSize-len(payload)%blockSize) + paddingLen := len(padding) + for i := 0; i < paddingLen; i++ { + padding[i] = byte(paddingLen - 1) + } + payload = append(payload, padding...) + + // Generate IV + iv := make([]byte, blockSize) + if _, err := rand.Read(iv); err != nil { + return nil, err + } + + // Set IV + Encrypt + Prepend IV + c.writeCBC.SetIV(iv) + c.writeCBC.CryptBlocks(payload, payload) + payload = append(iv, payload...) //nolint:makezero // todo: FIX + + // Prepend unencrypted header with encrypted payload + raw = append(raw, payload...) + + // Update recordLayer size to include IV+MAC+Padding + binary.BigEndian.PutUint16(raw[pkt.Header.Size()-2:], uint16(len(raw)-pkt.Header.Size())) //nolint:gosec //G115 + + return raw, nil +} + +// Decrypt decrypts a DTLS RecordLayer message. +func (c *CBC) Decrypt(header recordlayer.Header, in []byte) ([]byte, error) { + blockSize := c.readCBC.BlockSize() + mac := c.h() + + if err := header.Unmarshal(in); err != nil { + return nil, err + } + body := in[header.Size():] + + switch { + case header.ContentType == protocol.ContentTypeChangeCipherSpec: + // Nothing to encrypt with ChangeCipherSpec + return in, nil + case len(body)%blockSize != 0 || len(body) < blockSize+util.Max(mac.Size()+1, blockSize): + return nil, errNotEnoughRoomForNonce + } + + // Set + remove per record IV + c.readCBC.SetIV(body[:blockSize]) + body = body[blockSize:] + + // Decrypt + c.readCBC.CryptBlocks(body, body) + + // Padding+MAC needs to be checked in constant time + // Otherwise we reveal information about the level of correctness + paddingLen, paddingGood := examinePadding(body) + if paddingGood != 255 { + return nil, errInvalidMAC + } + + macSize := mac.Size() + if len(body) < macSize { + return nil, errInvalidMAC + } + + dataEnd := len(body) - macSize - paddingLen + + expectedMAC := body[dataEnd : dataEnd+macSize] + var err error + var actualMAC []byte + if header.ContentType == protocol.ContentTypeConnectionID { + actualMAC, err = c.hmacCID( + header.Epoch, header.SequenceNumber, header.Version, body[:dataEnd], c.readMac, c.h, header.ConnectionID, + ) + } else { + actualMAC, err = c.hmac( + header.Epoch, header.SequenceNumber, header.ContentType, header.Version, body[:dataEnd], c.readMac, c.h, + ) + } + // Compute Local MAC and compare + if err != nil || !hmac.Equal(actualMAC, expectedMAC) { + return nil, errInvalidMAC + } + + return append(in[:header.Size()], body[:dataEnd]...), nil +} + +func (c *CBC) hmac( + epoch uint16, + sequenceNumber uint64, + contentType protocol.ContentType, + protocolVersion protocol.Version, + payload []byte, + key []byte, + hf func() hash.Hash, +) ([]byte, error) { + hmacHash := hmac.New(hf, key) + + msg := make([]byte, 13) + + binary.BigEndian.PutUint16(msg, epoch) + util.PutBigEndianUint48(msg[2:], sequenceNumber) + msg[8] = byte(contentType) + msg[9] = protocolVersion.Major + msg[10] = protocolVersion.Minor + binary.BigEndian.PutUint16(msg[11:], uint16(len(payload))) //nolint:gosec //G115 + + if _, err := hmacHash.Write(msg); err != nil { + return nil, err + } + if _, err := hmacHash.Write(payload); err != nil { + return nil, err + } + + return hmacHash.Sum(nil), nil +} + +// hmacCID calculates a MAC according to +// https://datatracker.ietf.org/doc/html/rfc9146#section-5.1 +func (c *CBC) hmacCID( + epoch uint16, + sequenceNumber uint64, + protocolVersion protocol.Version, + payload []byte, + key []byte, + hf func() hash.Hash, + cid []byte, +) ([]byte, error) { + // Must unmarshal inner plaintext in orde to perform MAC. + ip := &recordlayer.InnerPlaintext{} + if err := ip.Unmarshal(payload); err != nil { + return nil, err + } + + hmacHash := hmac.New(hf, key) + + var msg cryptobyte.Builder + + msg.AddUint64(seqNumPlaceholder) + msg.AddUint8(uint8(protocol.ContentTypeConnectionID)) + msg.AddUint8(uint8(len(cid))) //nolint:gosec //G115 + msg.AddUint8(uint8(protocol.ContentTypeConnectionID)) + msg.AddUint8(protocolVersion.Major) + msg.AddUint8(protocolVersion.Minor) + msg.AddUint16(epoch) + util.AddUint48(&msg, sequenceNumber) + msg.AddBytes(cid) + msg.AddUint16(uint16(len(payload))) //nolint:gosec //G115 + msg.AddBytes(ip.Content) + msg.AddUint8(uint8(ip.RealType)) + msg.AddBytes(make([]byte, ip.Zeros)) + + if _, err := hmacHash.Write(msg.BytesOrPanic()); err != nil { + return nil, err + } + if _, err := hmacHash.Write(payload); err != nil { + return nil, err + } + + return hmacHash.Sum(nil), nil +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/crypto/ciphersuite/ccm.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/crypto/ciphersuite/ccm.go similarity index 55% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/crypto/ciphersuite/ccm.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/crypto/ciphersuite/ccm.go index 24050dc92..9a40cae8f 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/crypto/ciphersuite/ccm.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/crypto/ciphersuite/ccm.go @@ -9,29 +9,29 @@ import ( "encoding/binary" "fmt" - "github.com/pion/dtls/v2/pkg/crypto/ccm" - "github.com/pion/dtls/v2/pkg/protocol" - "github.com/pion/dtls/v2/pkg/protocol/recordlayer" + "github.com/pion/dtls/v3/pkg/crypto/ccm" + "github.com/pion/dtls/v3/pkg/protocol" + "github.com/pion/dtls/v3/pkg/protocol/recordlayer" ) -// CCMTagLen is the length of Authentication Tag +// CCMTagLen is the length of Authentication Tag. type CCMTagLen int -// CCM Enums +// CCM Enums. const ( CCMTagLength8 CCMTagLen = 8 CCMTagLength CCMTagLen = 16 ccmNonceLength = 12 ) -// CCM Provides an API to Encrypt/Decrypt DTLS 1.2 Packets +// CCM Provides an API to Encrypt/Decrypt DTLS 1.2 Packets. type CCM struct { localCCM, remoteCCM ccm.CCM localWriteIV, remoteWriteIV []byte tagLen CCMTagLen } -// NewCCM creates a DTLS GCM Cipher +// NewCCM creates a DTLS GCM Cipher. func NewCCM(tagLen CCMTagLen, localKey, localWriteIV, remoteKey, remoteWriteIV []byte) (*CCM, error) { localBlock, err := aes.NewCipher(localKey) if err != nil { @@ -60,48 +60,60 @@ func NewCCM(tagLen CCMTagLen, localKey, localWriteIV, remoteKey, remoteWriteIV [ }, nil } -// Encrypt encrypt a DTLS RecordLayer message +// Encrypt encrypt a DTLS RecordLayer message. func (c *CCM) Encrypt(pkt *recordlayer.RecordLayer, raw []byte) ([]byte, error) { - payload := raw[recordlayer.HeaderSize:] - raw = raw[:recordlayer.HeaderSize] + payload := raw[pkt.Header.Size():] + raw = raw[:pkt.Header.Size()] nonce := append(append([]byte{}, c.localWriteIV[:4]...), make([]byte, 8)...) if _, err := rand.Read(nonce[4:]); err != nil { return nil, err } - additionalData := generateAEADAdditionalData(&pkt.Header, len(payload)) + var additionalData []byte + if pkt.Header.ContentType == protocol.ContentTypeConnectionID { + additionalData = generateAEADAdditionalDataCID(&pkt.Header, len(payload)) + } else { + additionalData = generateAEADAdditionalData(&pkt.Header, len(payload)) + } encryptedPayload := c.localCCM.Seal(nil, nonce, payload, additionalData) encryptedPayload = append(nonce[4:], encryptedPayload...) raw = append(raw, encryptedPayload...) // Update recordLayer size to include explicit nonce - binary.BigEndian.PutUint16(raw[recordlayer.HeaderSize-2:], uint16(len(raw)-recordlayer.HeaderSize)) + binary.BigEndian.PutUint16(raw[pkt.Header.Size()-2:], uint16(len(raw)-pkt.Header.Size())) //nolint:gosec //G115 + return raw, nil } -// Decrypt decrypts a DTLS RecordLayer message -func (c *CCM) Decrypt(in []byte) ([]byte, error) { - var h recordlayer.Header - err := h.Unmarshal(in) - switch { - case err != nil: +// Decrypt decrypts a DTLS RecordLayer message. +func (c *CCM) Decrypt(header recordlayer.Header, in []byte) ([]byte, error) { + if err := header.Unmarshal(in); err != nil { return nil, err - case h.ContentType == protocol.ContentTypeChangeCipherSpec: + } + switch { + case header.ContentType == protocol.ContentTypeChangeCipherSpec: // Nothing to encrypt with ChangeCipherSpec return in, nil - case len(in) <= (8 + recordlayer.HeaderSize): + case len(in) <= (8 + header.Size()): return nil, errNotEnoughRoomForNonce } - nonce := append(append([]byte{}, c.remoteWriteIV[:4]...), in[recordlayer.HeaderSize:recordlayer.HeaderSize+8]...) - out := in[recordlayer.HeaderSize+8:] + nonce := append(append([]byte{}, c.remoteWriteIV[:4]...), in[header.Size():header.Size()+8]...) + out := in[header.Size()+8:] - additionalData := generateAEADAdditionalData(&h, len(out)-int(c.tagLen)) + var additionalData []byte + if header.ContentType == protocol.ContentTypeConnectionID { + additionalData = generateAEADAdditionalDataCID(&header, len(out)-int(c.tagLen)) + } else { + additionalData = generateAEADAdditionalData(&header, len(out)-int(c.tagLen)) + } + var err error out, err = c.remoteCCM.Open(out[:0], nonce, out, additionalData) if err != nil { return nil, fmt.Errorf("%w: %v", errDecryptPacket, err) //nolint:errorlint } - return append(in[:recordlayer.HeaderSize], out...), nil + + return append(in[:header.Size()], out...), nil } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/crypto/ciphersuite/ciphersuite.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/crypto/ciphersuite/ciphersuite.go similarity index 53% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/crypto/ciphersuite/ciphersuite.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/crypto/ciphersuite/ciphersuite.go index 9d9fb7418..5c01de580 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/crypto/ciphersuite/ciphersuite.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/crypto/ciphersuite/ciphersuite.go @@ -8,19 +8,32 @@ import ( "encoding/binary" "errors" - "github.com/pion/dtls/v2/pkg/protocol" - "github.com/pion/dtls/v2/pkg/protocol/recordlayer" + "github.com/pion/dtls/v3/internal/util" + "github.com/pion/dtls/v3/pkg/protocol" + "github.com/pion/dtls/v3/pkg/protocol/recordlayer" + "golang.org/x/crypto/cryptobyte" +) + +const ( + // 8 bytes of 0xff. + // https://datatracker.ietf.org/doc/html/rfc9146#name-record-payload-protection + seqNumPlaceholder = 0xffffffffffffffff ) var ( - errNotEnoughRoomForNonce = &protocol.InternalError{Err: errors.New("buffer not long enough to contain nonce")} //nolint:goerr113 - errDecryptPacket = &protocol.TemporaryError{Err: errors.New("failed to decrypt packet")} //nolint:goerr113 - errInvalidMAC = &protocol.TemporaryError{Err: errors.New("invalid mac")} //nolint:goerr113 - errFailedToCast = &protocol.FatalError{Err: errors.New("failed to cast")} //nolint:goerr113 + //nolint:goerr113 + errNotEnoughRoomForNonce = &protocol.InternalError{Err: errors.New("buffer not long enough to contain nonce")} + //nolint:goerr113 + errDecryptPacket = &protocol.TemporaryError{Err: errors.New("failed to decrypt packet")} + //nolint:goerr113 + errInvalidMAC = &protocol.TemporaryError{Err: errors.New("invalid mac")} + //nolint:goerr113 + errFailedToCast = &protocol.FatalError{Err: errors.New("failed to cast")} ) func generateAEADAdditionalData(h *recordlayer.Header, payloadLen int) []byte { var additionalData [13]byte + // SequenceNumber MUST be set first // we only want uint48, clobbering an extra 2 (using uint64, Golang doesn't have uint48) binary.BigEndian.PutUint64(additionalData[:], h.SequenceNumber) @@ -28,11 +41,31 @@ func generateAEADAdditionalData(h *recordlayer.Header, payloadLen int) []byte { additionalData[8] = byte(h.ContentType) additionalData[9] = h.Version.Major additionalData[10] = h.Version.Minor + //nolint:gosec //G115 binary.BigEndian.PutUint16(additionalData[len(additionalData)-2:], uint16(payloadLen)) return additionalData[:] } +// generateAEADAdditionalDataCID generates additional data for AEAD ciphers +// according to https://datatracker.ietf.org/doc/html/rfc9146#name-aead-ciphers +func generateAEADAdditionalDataCID(h *recordlayer.Header, payloadLen int) []byte { + var builder cryptobyte.Builder + + builder.AddUint64(seqNumPlaceholder) + builder.AddUint8(uint8(protocol.ContentTypeConnectionID)) + builder.AddUint8(uint8(len(h.ConnectionID))) //nolint:gosec //G115 + builder.AddUint8(uint8(protocol.ContentTypeConnectionID)) + builder.AddUint8(h.Version.Major) + builder.AddUint8(h.Version.Minor) + builder.AddUint16(h.Epoch) + util.AddUint48(&builder, h.SequenceNumber) + builder.AddBytes(h.ConnectionID) + builder.AddUint16(uint16(payloadLen)) //nolint:gosec //G115 + + return builder.BytesOrPanic() +} + // examinePadding returns, in constant time, the length of the padding to remove // from the end of payload. It also returns a byte which is equal to 255 if the // padding was valid and 0 otherwise. See RFC 2246, Section 6.2.3.2. @@ -44,9 +77,9 @@ func examinePadding(payload []byte) (toRemove int, good byte) { } paddingLen := payload[len(payload)-1] - t := uint(len(payload)-1) - uint(paddingLen) + t := uint(len(payload)-1) - uint(paddingLen) //nolint:gosec //G115 // if len(payload) >= (paddingLen - 1) then the MSB of t is zero - good = byte(int32(^t) >> 31) + good = byte(int32(^t) >> 31) //nolint:gosec //G115 // The maximum possible padding length plus the actual length field toCheck := 256 @@ -56,9 +89,9 @@ func examinePadding(payload []byte) (toRemove int, good byte) { } for i := 0; i < toCheck; i++ { - t := uint(paddingLen) - uint(i) + t := uint(paddingLen) - uint(i) //nolint:gosec //G115 // if i <= paddingLen then the MSB of t is zero - mask := byte(int32(^t) >> 31) + mask := byte(int32(^t) >> 31) //nolint:gosec //G115 b := payload[len(payload)-1-i] good &^= mask&paddingLen ^ mask&b } @@ -68,7 +101,7 @@ func examinePadding(payload []byte) (toRemove int, good byte) { good &= good << 4 good &= good << 2 good &= good << 1 - good = uint8(int8(good) >> 7) + good = uint8(int8(good) >> 7) //nolint:gosec //G115 toRemove = int(paddingLen) + 1 diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/crypto/ciphersuite/gcm.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/crypto/ciphersuite/gcm.go similarity index 57% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/crypto/ciphersuite/gcm.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/crypto/ciphersuite/gcm.go index c0fd1f76f..1c50dd967 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/crypto/ciphersuite/gcm.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/crypto/ciphersuite/gcm.go @@ -10,8 +10,8 @@ import ( "encoding/binary" "fmt" - "github.com/pion/dtls/v2/pkg/protocol" - "github.com/pion/dtls/v2/pkg/protocol/recordlayer" + "github.com/pion/dtls/v3/pkg/protocol" + "github.com/pion/dtls/v3/pkg/protocol/recordlayer" ) const ( @@ -19,13 +19,13 @@ const ( gcmNonceLength = 12 ) -// GCM Provides an API to Encrypt/Decrypt DTLS 1.2 Packets +// GCM Provides an API to Encrypt/Decrypt DTLS 1.2 Packets. type GCM struct { localGCM, remoteGCM cipher.AEAD localWriteIV, remoteWriteIV []byte } -// NewGCM creates a DTLS GCM Cipher +// NewGCM creates a DTLS GCM Cipher. func NewGCM(localKey, localWriteIV, remoteKey, remoteWriteIV []byte) (*GCM, error) { localBlock, err := aes.NewCipher(localKey) if err != nil { @@ -53,10 +53,10 @@ func NewGCM(localKey, localWriteIV, remoteKey, remoteWriteIV []byte) (*GCM, erro }, nil } -// Encrypt encrypt a DTLS RecordLayer message +// Encrypt encrypt a DTLS RecordLayer message. func (g *GCM) Encrypt(pkt *recordlayer.RecordLayer, raw []byte) ([]byte, error) { - payload := raw[recordlayer.HeaderSize:] - raw = raw[:recordlayer.HeaderSize] + payload := raw[pkt.Header.Size():] + raw = raw[:pkt.Header.Size()] nonce := make([]byte, gcmNonceLength) copy(nonce, g.localWriteIV[:4]) @@ -64,7 +64,12 @@ func (g *GCM) Encrypt(pkt *recordlayer.RecordLayer, raw []byte) ([]byte, error) return nil, err } - additionalData := generateAEADAdditionalData(&pkt.Header, len(payload)) + var additionalData []byte + if pkt.Header.ContentType == protocol.ContentTypeConnectionID { + additionalData = generateAEADAdditionalDataCID(&pkt.Header, len(payload)) + } else { + additionalData = generateAEADAdditionalData(&pkt.Header, len(payload)) + } encryptedPayload := g.localGCM.Seal(nil, nonce, payload, additionalData) r := make([]byte, len(raw)+len(nonce[4:])+len(encryptedPayload)) copy(r, raw) @@ -72,32 +77,38 @@ func (g *GCM) Encrypt(pkt *recordlayer.RecordLayer, raw []byte) ([]byte, error) copy(r[len(raw)+len(nonce[4:]):], encryptedPayload) // Update recordLayer size to include explicit nonce - binary.BigEndian.PutUint16(r[recordlayer.HeaderSize-2:], uint16(len(r)-recordlayer.HeaderSize)) + binary.BigEndian.PutUint16(r[pkt.Header.Size()-2:], uint16(len(r)-pkt.Header.Size())) //nolint:gosec //G115 + return r, nil } -// Decrypt decrypts a DTLS RecordLayer message -func (g *GCM) Decrypt(in []byte) ([]byte, error) { - var h recordlayer.Header - err := h.Unmarshal(in) +// Decrypt decrypts a DTLS RecordLayer message. +func (g *GCM) Decrypt(header recordlayer.Header, in []byte) ([]byte, error) { + err := header.Unmarshal(in) switch { case err != nil: return nil, err - case h.ContentType == protocol.ContentTypeChangeCipherSpec: + case header.ContentType == protocol.ContentTypeChangeCipherSpec: // Nothing to encrypt with ChangeCipherSpec return in, nil - case len(in) <= (8 + recordlayer.HeaderSize): + case len(in) <= (8 + header.Size()): return nil, errNotEnoughRoomForNonce } nonce := make([]byte, 0, gcmNonceLength) - nonce = append(append(nonce, g.remoteWriteIV[:4]...), in[recordlayer.HeaderSize:recordlayer.HeaderSize+8]...) - out := in[recordlayer.HeaderSize+8:] + nonce = append(append(nonce, g.remoteWriteIV[:4]...), in[header.Size():header.Size()+8]...) + out := in[header.Size()+8:] - additionalData := generateAEADAdditionalData(&h, len(out)-gcmTagLength) + var additionalData []byte + if header.ContentType == protocol.ContentTypeConnectionID { + additionalData = generateAEADAdditionalDataCID(&header, len(out)-gcmTagLength) + } else { + additionalData = generateAEADAdditionalData(&header, len(out)-gcmTagLength) + } out, err = g.remoteGCM.Open(out[:0], nonce, out, additionalData) if err != nil { return nil, fmt.Errorf("%w: %v", errDecryptPacket, err) //nolint:errorlint } - return append(in[:recordlayer.HeaderSize], out...), nil + + return append(in[:header.Size()], out...), nil } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/crypto/clientcertificate/client_certificate.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/crypto/clientcertificate/client_certificate.go similarity index 86% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/crypto/clientcertificate/client_certificate.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/crypto/clientcertificate/client_certificate.go index ddfa39ebe..0a510d4d4 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/crypto/clientcertificate/client_certificate.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/crypto/clientcertificate/client_certificate.go @@ -10,13 +10,13 @@ package clientcertificate // https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-2 type Type byte -// ClientCertificateType enums +// ClientCertificateType enums. const ( RSASign Type = 1 ECDSASign Type = 64 ) -// Types returns all valid ClientCertificate Types +// Types returns all valid ClientCertificate Types. func Types() map[Type]bool { return map[Type]bool{ RSASign: true, diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/crypto/elliptic/elliptic.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/crypto/elliptic/elliptic.go similarity index 90% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/crypto/elliptic/elliptic.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/crypto/elliptic/elliptic.go index 126523872..b98fb4f9c 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/crypto/elliptic/elliptic.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/crypto/elliptic/elliptic.go @@ -20,12 +20,12 @@ var errInvalidNamedCurve = errors.New("invalid named curve") // https://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-9 type CurvePointFormat byte -// CurvePointFormat enums +// CurvePointFormat enums. const ( CurvePointFormatUncompressed CurvePointFormat = 0 ) -// Keypair is a Curve with a Private/Public Keypair +// Keypair is a Curve with a Private/Public Keypair. type Keypair struct { Curve Curve PublicKey []byte @@ -37,12 +37,12 @@ type Keypair struct { // https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-10 type CurveType byte -// CurveType enums +// CurveType enums. const ( CurveTypeNamedCurve CurveType = 0x03 ) -// CurveTypes returns all known curves +// CurveTypes returns all known curves. func CurveTypes() map[CurveType]struct{} { return map[CurveType]struct{}{ CurveTypeNamedCurve: {}, @@ -54,7 +54,7 @@ func CurveTypes() map[CurveType]struct{} { // https://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-8 type Curve uint16 -// Curve enums +// Curve enums. const ( P256 Curve = 0x0017 P384 Curve = 0x0018 @@ -70,10 +70,11 @@ func (c Curve) String() string { case X25519: return "X25519" } + return fmt.Sprintf("%#x", uint16(c)) } -// Curves returns all curves we implement +// Curves returns all curves we implement. func Curves() map[Curve]bool { return map[Curve]bool{ X25519: true, @@ -82,7 +83,7 @@ func Curves() map[Curve]bool { } } -// GenerateKeypair generates a keypair for the given Curve +// GenerateKeypair generates a keypair for the given Curve. func GenerateKeypair(c Curve) (*Keypair, error) { switch c { //nolint:revive case X25519: @@ -95,6 +96,7 @@ func GenerateKeypair(c Curve) (*Keypair, error) { copy(private[:], tmp) curve25519.ScalarBaseMult(&public, &private) + return &Keypair{X25519, public[:], private[:]}, nil case P256: return ellipticCurveKeypair(P256, elliptic.P256(), elliptic.P256()) diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/crypto/fingerprint/fingerprint.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/crypto/fingerprint/fingerprint.go similarity index 97% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/crypto/fingerprint/fingerprint.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/crypto/fingerprint/fingerprint.go index 7c66265c7..43d4a4000 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/crypto/fingerprint/fingerprint.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/crypto/fingerprint/fingerprint.go @@ -16,7 +16,7 @@ var ( errInvalidFingerprintLength = errors.New("fingerprint: invalid fingerprint length") ) -// Fingerprint creates a fingerprint for a certificate using the specified hash algorithm +// Fingerprint creates a fingerprint for a certificate using the specified hash algorithm. func Fingerprint(cert *x509.Certificate, algo crypto.Hash) (string, error) { if !algo.Available() { return "", errHashUnavailable diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/crypto/fingerprint/hash.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/crypto/fingerprint/hash.go similarity index 97% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/crypto/fingerprint/hash.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/crypto/fingerprint/hash.go index 3f988ffb7..8aacd673d 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/crypto/fingerprint/hash.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/crypto/fingerprint/hash.go @@ -22,11 +22,12 @@ func nameToHash() map[string]crypto.Hash { } } -// HashFromString allows looking up a hash algorithm by it's string representation +// HashFromString allows looking up a hash algorithm by it's string representation. func HashFromString(s string) (crypto.Hash, error) { if h, ok := nameToHash()[strings.ToLower(s)]; ok { return h, nil } + return 0, errInvalidHashAlgorithm } @@ -37,5 +38,6 @@ func StringFromHash(hash crypto.Hash) (string, error) { return s, nil } } + return "", errInvalidHashAlgorithm } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/crypto/hash/hash.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/crypto/hash/hash.go similarity index 92% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/crypto/hash/hash.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/crypto/hash/hash.go index 9966626e3..a390170fe 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/crypto/hash/hash.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/crypto/hash/hash.go @@ -16,7 +16,7 @@ import ( //nolint:gci // https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-18 type Algorithm uint16 -// Supported hash algorithms +// Supported hash algorithms. const ( None Algorithm = 0 // Blacklisted MD5 Algorithm = 1 // Blacklisted @@ -28,7 +28,7 @@ const ( Ed25519 Algorithm = 8 ) -// String makes hashAlgorithm printable +// String makes hashAlgorithm printable. func (a Algorithm) String() string { switch a { case None: @@ -52,28 +52,34 @@ func (a Algorithm) String() string { } } -// Digest performs a digest on the passed value +// Digest performs a digest on the passed value. func (a Algorithm) Digest(b []byte) []byte { switch a { case None: return nil case MD5: hash := md5.Sum(b) // #nosec + return hash[:] case SHA1: hash := sha1.Sum(b) // #nosec + return hash[:] case SHA224: hash := sha256.Sum224(b) + return hash[:] case SHA256: hash := sha256.Sum256(b) + return hash[:] case SHA384: hash := sha512.Sum384(b) + return hash[:] case SHA512: hash := sha512.Sum512(b) + return hash[:] default: return nil @@ -81,6 +87,7 @@ func (a Algorithm) Digest(b []byte) []byte { } // Insecure returns if the given HashAlgorithm is considered secure in DTLS 1.2 +// . func (a Algorithm) Insecure() bool { switch a { case None, MD5, SHA1: @@ -90,7 +97,7 @@ func (a Algorithm) Insecure() bool { } } -// CryptoHash returns the crypto.Hash implementation for the given HashAlgorithm +// CryptoHash returns the crypto.Hash implementation for the given HashAlgorithm. func (a Algorithm) CryptoHash() crypto.Hash { switch a { case None: @@ -114,7 +121,7 @@ func (a Algorithm) CryptoHash() crypto.Hash { } } -// Algorithms returns all the supported Hash Algorithms +// Algorithms returns all the supported Hash Algorithms. func Algorithms() map[Algorithm]struct{} { return map[Algorithm]struct{}{ None: {}, diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/crypto/prf/prf.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/crypto/prf/prf.go similarity index 89% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/crypto/prf/prf.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/crypto/prf/prf.go index 6e7b3ecba..9eace83b7 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/crypto/prf/prf.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/crypto/prf/prf.go @@ -13,8 +13,8 @@ import ( //nolint:gci "hash" "math" - "github.com/pion/dtls/v2/pkg/crypto/elliptic" - "github.com/pion/dtls/v2/pkg/protocol" + "github.com/pion/dtls/v3/pkg/crypto/elliptic" + "github.com/pion/dtls/v3/pkg/protocol" "golang.org/x/crypto/curve25519" ) @@ -26,10 +26,10 @@ const ( verifyDataServerLabel = "server finished" ) -// HashFunc allows callers to decide what hash is used in PRF +// HashFunc allows callers to decide what hash is used in PRF. type HashFunc func() hash.Hash -// EncryptionKeys is all the state needed for a TLS CipherSuite +// EncryptionKeys is all the state needed for a TLS CipherSuite. type EncryptionKeys struct { MasterSecret []byte ClientMACKey []byte @@ -68,7 +68,7 @@ func (e *EncryptionKeys) String() string { // // https://tools.ietf.org/html/rfc4279#section-2 func PSKPreMasterSecret(psk []byte) []byte { - pskLen := uint16(len(psk)) + pskLen := uint16(len(psk)) //nolint:gosec // G115 out := append(make([]byte, 2+pskLen+2), psk...) binary.BigEndian.PutUint16(out, pskLen) @@ -89,7 +89,7 @@ func EcdhePSKPreMasterSecret(psk, publicKey, privateKey []byte, curve elliptic.C // write preMasterSecret length offset := 0 - binary.BigEndian.PutUint16(out[offset:], uint16(len(preMasterSecret))) + binary.BigEndian.PutUint16(out[offset:], uint16(len(preMasterSecret))) //nolint:gosec // G115 offset += 2 // write preMasterSecret @@ -97,15 +97,16 @@ func EcdhePSKPreMasterSecret(psk, publicKey, privateKey []byte, curve elliptic.C offset += len(preMasterSecret) // write psk length - binary.BigEndian.PutUint16(out[offset:], uint16(len(psk))) + binary.BigEndian.PutUint16(out[offset:], uint16(len(psk))) //nolint:gosec // G115 offset += 2 // write psk copy(out[offset:], psk) + return out, nil } -// PreMasterSecret implements TLS 1.2 Premaster Secret generation given a keypair and a curve +// PreMasterSecret implements TLS 1.2 Premaster Secret generation given a keypair and a curve. func PreMasterSecret(publicKey, privateKey []byte, curve elliptic.Curve) ([]byte, error) { switch curve { case elliptic.X25519: @@ -129,6 +130,7 @@ func ellipticCurvePreMasterSecret(publicKey, privateKey []byte, c1, c2 ellipticS preMasterSecret := make([]byte, (c2.Params().BitSize+7)>>3) resultBytes := result.Bytes() copy(preMasterSecret[len(preMasterSecret)-len(resultBytes):], resultBytes) + return preMasterSecret, nil } @@ -155,12 +157,13 @@ func ellipticCurvePreMasterSecret(publicKey, privateKey []byte, c1, c2 ellipticS // output data. // // https://tools.ietf.org/html/rfc4346w -func PHash(secret, seed []byte, requestedLength int, h HashFunc) ([]byte, error) { +func PHash(secret, seed []byte, requestedLength int, hashFunc HashFunc) ([]byte, error) { hmacSHA256 := func(key, data []byte) ([]byte, error) { - mac := hmac.New(h, key) + mac := hmac.New(hashFunc, key) if _, err := mac.Write(data); err != nil { return nil, err } + return mac.Sum(nil), nil } @@ -168,7 +171,7 @@ func PHash(secret, seed []byte, requestedLength int, h HashFunc) ([]byte, error) lastRound := seed out := []byte{} - iterations := int(math.Ceil(float64(requestedLength) / float64(h().Size()))) + iterations := int(math.Ceil(float64(requestedLength) / float64(hashFunc().Size()))) for i := 0; i < iterations; i++ { lastRound, err = hmacSHA256(secret, lastRound) if err != nil { @@ -188,18 +191,24 @@ func PHash(secret, seed []byte, requestedLength int, h HashFunc) ([]byte, error) // https://tools.ietf.org/html/rfc7627 func ExtendedMasterSecret(preMasterSecret, sessionHash []byte, h HashFunc) ([]byte, error) { seed := append([]byte(extendedMasterSecretLabel), sessionHash...) + return PHash(preMasterSecret, seed, 48, h) } -// MasterSecret generates a TLS 1.2 MasterSecret +// MasterSecret generates a TLS 1.2 MasterSecret. func MasterSecret(preMasterSecret, clientRandom, serverRandom []byte, h HashFunc) ([]byte, error) { seed := append(append([]byte(masterSecretLabel), clientRandom...), serverRandom...) + return PHash(preMasterSecret, seed, 48, h) } // GenerateEncryptionKeys is the final step TLS 1.2 PRF. Given all state generated so far generates -// the final keys need for encryption -func GenerateEncryptionKeys(masterSecret, clientRandom, serverRandom []byte, macLen, keyLen, ivLen int, h HashFunc) (*EncryptionKeys, error) { +// the final keys need for encryption. +func GenerateEncryptionKeys( + masterSecret, clientRandom, serverRandom []byte, + macLen, keyLen, ivLen int, + h HashFunc, +) (*EncryptionKeys, error) { seed := append(append([]byte(keyExpansionLabel), serverRandom...), clientRandom...) keyMaterial, err := PHash(masterSecret, seed, (2*macLen)+(2*keyLen)+(2*ivLen), h) if err != nil { @@ -241,15 +250,16 @@ func prfVerifyData(masterSecret, handshakeBodies []byte, label string, hashFunc } seed := append([]byte(label), h.Sum(nil)...) + return PHash(masterSecret, seed, 12, hashFunc) } -// VerifyDataClient is caled on the Client Side to either verify or generate the VerifyData message +// VerifyDataClient is caled on the Client Side to either verify or generate the VerifyData message. func VerifyDataClient(masterSecret, handshakeBodies []byte, h HashFunc) ([]byte, error) { return prfVerifyData(masterSecret, handshakeBodies, verifyDataClientLabel, h) } -// VerifyDataServer is caled on the Server Side to either verify or generate the VerifyData message +// VerifyDataServer is caled on the Server Side to either verify or generate the VerifyData message. func VerifyDataServer(masterSecret, handshakeBodies []byte, h HashFunc) ([]byte, error) { return prfVerifyData(masterSecret, handshakeBodies, verifyDataServerLabel, h) } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/crypto/signature/signature.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/crypto/signature/signature.go similarity index 86% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/crypto/signature/signature.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/crypto/signature/signature.go index fec7fba3b..53fb7c952 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/crypto/signature/signature.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/crypto/signature/signature.go @@ -8,7 +8,7 @@ package signature // https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-16 type Algorithm uint16 -// SignatureAlgorithm enums +// SignatureAlgorithm enums. const ( Anonymous Algorithm = 0 RSA Algorithm = 1 @@ -16,7 +16,7 @@ const ( Ed25519 Algorithm = 7 ) -// Algorithms returns all implemented Signature Algorithms +// Algorithms returns all implemented Signature Algorithms. func Algorithms() map[Algorithm]struct{} { return map[Algorithm]struct{}{ Anonymous: {}, diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/crypto/signaturehash/errors.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/crypto/signaturehash/errors.go similarity index 85% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/crypto/signaturehash/errors.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/crypto/signaturehash/errors.go index 4aeb3e40a..2e2b72bb8 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/crypto/signaturehash/errors.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/crypto/signaturehash/errors.go @@ -9,4 +9,5 @@ var ( errNoAvailableSignatureSchemes = errors.New("connection can not be created, no SignatureScheme satisfy this Config") errInvalidSignatureAlgorithm = errors.New("invalid signature algorithm") errInvalidHashAlgorithm = errors.New("invalid hash algorithm") + errInvalidPrivateKey = errors.New("invalid private key type") ) diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/crypto/signaturehash/signaturehash.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/crypto/signaturehash/signaturehash.go similarity index 83% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/crypto/signaturehash/signaturehash.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/crypto/signaturehash/signaturehash.go index 2561accd1..2c72f8ca8 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/crypto/signaturehash/signaturehash.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/crypto/signaturehash/signaturehash.go @@ -12,8 +12,8 @@ import ( "crypto/tls" "fmt" - "github.com/pion/dtls/v2/pkg/crypto/hash" - "github.com/pion/dtls/v2/pkg/crypto/signature" + "github.com/pion/dtls/v3/pkg/crypto/hash" + "github.com/pion/dtls/v3/pkg/crypto/signature" ) // Algorithm is a signature/hash algorithm pairs which may be used in @@ -25,7 +25,7 @@ type Algorithm struct { Signature signature.Algorithm } -// Algorithms are all the know SignatureHash Algorithms +// Algorithms are all the know SignatureHash Algorithms. func Algorithms() []Algorithm { return []Algorithm{ {hash.SHA256, signature.ECDSA}, @@ -40,22 +40,27 @@ func Algorithms() []Algorithm { // SelectSignatureScheme returns most preferred and compatible scheme. func SelectSignatureScheme(sigs []Algorithm, privateKey crypto.PrivateKey) (Algorithm, error) { + signer, ok := privateKey.(crypto.Signer) + if !ok { + return Algorithm{}, errInvalidPrivateKey + } for _, ss := range sigs { - if ss.isCompatible(privateKey) { + if ss.isCompatible(signer) { return ss, nil } } + return Algorithm{}, errNoAvailableSignatureSchemes } // isCompatible checks that given private key is compatible with the signature scheme. -func (a *Algorithm) isCompatible(privateKey crypto.PrivateKey) bool { - switch privateKey.(type) { - case ed25519.PrivateKey: +func (a *Algorithm) isCompatible(signer crypto.Signer) bool { + switch signer.Public().(type) { + case ed25519.PublicKey: return a.Signature == signature.Ed25519 - case *ecdsa.PrivateKey: + case *ecdsa.PublicKey: return a.Signature == signature.ECDSA - case *rsa.PrivateKey: + case *rsa.PublicKey: return a.Signature == signature.RSA default: return false diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/net/net.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/net/net.go new file mode 100644 index 000000000..3db604777 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/net/net.go @@ -0,0 +1,111 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + +// Package net defines packet-oriented primitives that are compatible with net +// in the standard library. +package net + +import ( + "net" + "time" +) + +// A PacketListener is the same as net.Listener but returns a net.PacketConn on +// Accept() rather than a net.Conn. +// +// Multiple goroutines may invoke methods on a PacketListener simultaneously. +type PacketListener interface { + // Accept waits for and returns the next connection to the listener. + Accept() (net.PacketConn, net.Addr, error) + + // Close closes the listener. + // Any blocked Accept operations will be unblocked and return errors. + Close() error + + // Addr returns the listener's network address. + Addr() net.Addr +} + +// PacketListenerFromListener converts a net.Listener into a +// dtlsnet.PacketListener. +func PacketListenerFromListener(l net.Listener) PacketListener { + return &packetListenerWrapper{ + l: l, + } +} + +// packetListenerWrapper wraps a net.Listener and implements +// dtlsnet.PacketListener. +type packetListenerWrapper struct { + l net.Listener +} + +// Accept calls Accept on the underlying net.Listener and converts the returned +// net.Conn into a net.PacketConn. +func (p *packetListenerWrapper) Accept() (net.PacketConn, net.Addr, error) { + c, err := p.l.Accept() + if err != nil { + return PacketConnFromConn(c), nil, err + } + + return PacketConnFromConn(c), c.RemoteAddr(), nil +} + +// Close closes the underlying net.Listener. +func (p *packetListenerWrapper) Close() error { + return p.l.Close() +} + +// Addr returns the address of the underlying net.Listener. +func (p *packetListenerWrapper) Addr() net.Addr { + return p.l.Addr() +} + +// PacketConnFromConn converts a net.Conn into a net.PacketConn. +func PacketConnFromConn(conn net.Conn) net.PacketConn { + return &packetConnWrapper{conn} +} + +// packetConnWrapper wraps a net.Conn and implements net.PacketConn. +type packetConnWrapper struct { + conn net.Conn +} + +// ReadFrom reads from the underlying net.Conn and returns its remote address. +func (p *packetConnWrapper) ReadFrom(b []byte) (int, net.Addr, error) { + n, err := p.conn.Read(b) + + return n, p.conn.RemoteAddr(), err +} + +// WriteTo writes to the underlying net.Conn. +func (p *packetConnWrapper) WriteTo(b []byte, _ net.Addr) (int, error) { + n, err := p.conn.Write(b) + + return n, err +} + +// Close closes the underlying net.Conn. +func (p *packetConnWrapper) Close() error { + return p.conn.Close() +} + +// LocalAddr returns the local address of the underlying net.Conn. +func (p *packetConnWrapper) LocalAddr() net.Addr { + return p.conn.LocalAddr() +} + +// SetDeadline sets the deadline on the underlying net.Conn. +func (p *packetConnWrapper) SetDeadline(t time.Time) error { + return p.conn.SetDeadline(t) +} + +// SetReadDeadline sets the read deadline on the underlying net.Conn. +func (p *packetConnWrapper) SetReadDeadline(t time.Time) error { + return p.conn.SetReadDeadline(t) +} + +// SetWriteDeadline sets the write deadline on the underlying net.Conn. +func (p *packetConnWrapper) SetWriteDeadline(t time.Time) error { + return p.conn.SetWriteDeadline(t) +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/alert/alert.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/alert/alert.go similarity index 91% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/alert/alert.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/alert/alert.go index 91e9f4d60..8fac65962 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/alert/alert.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/alert/alert.go @@ -8,15 +8,15 @@ import ( "errors" "fmt" - "github.com/pion/dtls/v2/pkg/protocol" + "github.com/pion/dtls/v3/pkg/protocol" ) var errBufferTooSmall = &protocol.TemporaryError{Err: errors.New("buffer is too small")} //nolint:goerr113 -// Level is the level of the TLS Alert +// Level is the level of the TLS Alert. type Level byte -// Level enums +// Level enums. const ( Warning Level = 1 Fatal Level = 2 @@ -33,10 +33,10 @@ func (l Level) String() string { } } -// Description is the extended info of the TLS Alert +// Description is the extended info of the TLS Alert. type Description byte -// Description enums +// Description enums. const ( CloseNotify Description = 0 UnexpectedMessage Description = 10 @@ -66,7 +66,7 @@ const ( NoApplicationProtocol Description = 120 ) -func (d Description) String() string { +func (d Description) String() string { //nolint:cyclop switch d { case CloseNotify: return "CloseNotify" @@ -140,17 +140,17 @@ type Alert struct { Description Description } -// ContentType returns the ContentType of this Content +// ContentType returns the ContentType of this Content. func (a Alert) ContentType() protocol.ContentType { return protocol.ContentTypeAlert } -// Marshal returns the encoded alert +// Marshal returns the encoded alert. func (a *Alert) Marshal() ([]byte, error) { return []byte{byte(a.Level), byte(a.Description)}, nil } -// Unmarshal populates the alert from binary data +// Unmarshal populates the alert from binary data. func (a *Alert) Unmarshal(data []byte) error { if len(data) != 2 { return errBufferTooSmall @@ -158,6 +158,7 @@ func (a *Alert) Unmarshal(data []byte) error { a.Level = Level(data[0]) a.Description = Description(data[1]) + return nil } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/application_data.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/application_data.go similarity index 81% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/application_data.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/application_data.go index f42211511..f478c4231 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/application_data.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/application_data.go @@ -12,18 +12,19 @@ type ApplicationData struct { Data []byte } -// ContentType returns the ContentType of this content +// ContentType returns the ContentType of this content. func (a ApplicationData) ContentType() ContentType { return ContentTypeApplicationData } -// Marshal encodes the ApplicationData to binary +// Marshal encodes the ApplicationData to binary. func (a *ApplicationData) Marshal() ([]byte, error) { return append([]byte{}, a.Data...), nil } -// Unmarshal populates the ApplicationData from binary +// Unmarshal populates the ApplicationData from binary. func (a *ApplicationData) Unmarshal(data []byte) error { a.Data = append([]byte{}, data...) + return nil } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/change_cipher_spec.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/change_cipher_spec.go similarity index 83% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/change_cipher_spec.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/change_cipher_spec.go index 87f28bc37..4813cd564 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/change_cipher_spec.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/change_cipher_spec.go @@ -10,17 +10,17 @@ package protocol // https://tools.ietf.org/html/rfc5246#section-7.1 type ChangeCipherSpec struct{} -// ContentType returns the ContentType of this content +// ContentType returns the ContentType of this content. func (c ChangeCipherSpec) ContentType() ContentType { return ContentTypeChangeCipherSpec } -// Marshal encodes the ChangeCipherSpec to binary +// Marshal encodes the ChangeCipherSpec to binary. func (c *ChangeCipherSpec) Marshal() ([]byte, error) { return []byte{0x01}, nil } -// Unmarshal populates the ChangeCipherSpec from binary +// Unmarshal populates the ChangeCipherSpec from binary. func (c *ChangeCipherSpec) Unmarshal(data []byte) error { if len(data) == 1 && data[0] == 0x01 { return nil diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/compression_method.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/compression_method.go similarity index 78% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/compression_method.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/compression_method.go index 3478ee38c..0fb99a51b 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/compression_method.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/compression_method.go @@ -3,26 +3,26 @@ package protocol -// CompressionMethodID is the ID for a CompressionMethod +// CompressionMethodID is the ID for a CompressionMethod. type CompressionMethodID byte const ( compressionMethodNull CompressionMethodID = 0 ) -// CompressionMethod represents a TLS Compression Method +// CompressionMethod represents a TLS Compression Method. type CompressionMethod struct { ID CompressionMethodID } -// CompressionMethods returns all supported CompressionMethods +// CompressionMethods returns all supported CompressionMethods. func CompressionMethods() map[CompressionMethodID]*CompressionMethod { return map[CompressionMethodID]*CompressionMethod{ compressionMethodNull: {ID: compressionMethodNull}, } } -// DecodeCompressionMethods the given compression methods +// DecodeCompressionMethods the given compression methods. func DecodeCompressionMethods(buf []byte) ([]*CompressionMethod, error) { if len(buf) < 1 { return nil, errBufferTooSmall @@ -38,14 +38,16 @@ func DecodeCompressionMethods(buf []byte) ([]*CompressionMethod, error) { c = append(c, compressionMethod) } } + return c, nil } -// EncodeCompressionMethods the given compression methods +// EncodeCompressionMethods the given compression methods. func EncodeCompressionMethods(c []*CompressionMethod) []byte { out := []byte{byte(len(c))} for i := len(c); i > 0; i-- { out = append(out, byte(c[i-1].ID)) } + return out } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/content.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/content.go similarity index 81% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/content.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/content.go index 92c9db2bf..9b6daa51f 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/content.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/content.go @@ -8,15 +8,16 @@ package protocol // https://tools.ietf.org/html/rfc4346#section-6.2.1 type ContentType uint8 -// ContentType enums +// ContentType enums. const ( ContentTypeChangeCipherSpec ContentType = 20 ContentTypeAlert ContentType = 21 ContentTypeHandshake ContentType = 22 ContentTypeApplicationData ContentType = 23 + ContentTypeConnectionID ContentType = 25 ) -// Content is the top level distinguisher for a DTLS Datagram +// Content is the top level distinguisher for a DTLS Datagram. type Content interface { ContentType() ContentType Marshal() ([]byte, error) diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/errors.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/errors.go similarity index 84% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/errors.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/errors.go index d87aff7fb..dc091bff3 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/errors.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/errors.go @@ -20,7 +20,8 @@ type FatalError struct { Err error } -// InternalError indicates and internal error caused by the implementation, and the DTLS connection is no longer available. +// InternalError indicates and internal error caused by the implementation, +// and the DTLS connection is no longer available. // It is mainly caused by bugs or tried to use unimplemented features. type InternalError struct { Err error @@ -41,10 +42,10 @@ type HandshakeError struct { Err error } -// Timeout implements net.Error.Timeout() +// Timeout implements net.Error.Timeout(). func (*FatalError) Timeout() bool { return false } -// Temporary implements net.Error.Temporary() +// Temporary implements net.Error.Temporary(). func (*FatalError) Temporary() bool { return false } // Unwrap implements Go1.13 error unwrapper. @@ -52,10 +53,10 @@ func (e *FatalError) Unwrap() error { return e.Err } func (e *FatalError) Error() string { return fmt.Sprintf("dtls fatal: %v", e.Err) } -// Timeout implements net.Error.Timeout() +// Timeout implements net.Error.Timeout(). func (*InternalError) Timeout() bool { return false } -// Temporary implements net.Error.Temporary() +// Temporary implements net.Error.Temporary(). func (*InternalError) Temporary() bool { return false } // Unwrap implements Go1.13 error unwrapper. @@ -63,10 +64,10 @@ func (e *InternalError) Unwrap() error { return e.Err } func (e *InternalError) Error() string { return fmt.Sprintf("dtls internal: %v", e.Err) } -// Timeout implements net.Error.Timeout() +// Timeout implements net.Error.Timeout(). func (*TemporaryError) Timeout() bool { return false } -// Temporary implements net.Error.Temporary() +// Temporary implements net.Error.Temporary(). func (*TemporaryError) Temporary() bool { return true } // Unwrap implements Go1.13 error unwrapper. @@ -74,10 +75,10 @@ func (e *TemporaryError) Unwrap() error { return e.Err } func (e *TemporaryError) Error() string { return fmt.Sprintf("dtls temporary: %v", e.Err) } -// Timeout implements net.Error.Timeout() +// Timeout implements net.Error.Timeout(). func (*TimeoutError) Timeout() bool { return true } -// Temporary implements net.Error.Temporary() +// Temporary implements net.Error.Temporary(). func (*TimeoutError) Temporary() bool { return true } // Unwrap implements Go1.13 error unwrapper. @@ -85,21 +86,23 @@ func (e *TimeoutError) Unwrap() error { return e.Err } func (e *TimeoutError) Error() string { return fmt.Sprintf("dtls timeout: %v", e.Err) } -// Timeout implements net.Error.Timeout() +// Timeout implements net.Error.Timeout(). func (e *HandshakeError) Timeout() bool { var netErr net.Error if errors.As(e.Err, &netErr) { return netErr.Timeout() } + return false } -// Temporary implements net.Error.Temporary() +// Temporary implements net.Error.Temporary(). func (e *HandshakeError) Temporary() bool { var netErr net.Error if errors.As(e.Err, &netErr) { return netErr.Temporary() //nolint } + return false } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/extension/alpn.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/extension/alpn.go similarity index 84% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/extension/alpn.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/extension/alpn.go index e780dc9e1..719428601 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/extension/alpn.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/extension/alpn.go @@ -15,16 +15,16 @@ type ALPN struct { ProtocolNameList []string } -// TypeValue returns the extension TypeValue +// TypeValue returns the extension TypeValue. func (a ALPN) TypeValue() TypeValue { return ALPNTypeValue } -// Marshal encodes the extension +// Marshal encodes the extension. func (a *ALPN) Marshal() ([]byte, error) { - var b cryptobyte.Builder - b.AddUint16(uint16(a.TypeValue())) - b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + var builder cryptobyte.Builder + builder.AddUint16(uint16(a.TypeValue())) + builder.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { for _, proto := range a.ProtocolNameList { p := proto // Satisfy range scope lint @@ -34,10 +34,11 @@ func (a *ALPN) Marshal() ([]byte, error) { } }) }) - return b.Bytes() + + return builder.Bytes() } -// Unmarshal populates the extension from encoded data +// Unmarshal populates the extension from encoded data. func (a *ALPN) Unmarshal(data []byte) error { val := cryptobyte.String(data) @@ -61,10 +62,11 @@ func (a *ALPN) Unmarshal(data []byte) error { } a.ProtocolNameList = append(a.ProtocolNameList, string(proto)) } + return nil } -// ALPNProtocolSelection negotiates a shared protocol according to #3.2 of rfc7301 +// ALPNProtocolSelection negotiates a shared protocol according to #3.2 of rfc7301. func ALPNProtocolSelection(supportedProtocols, peerSupportedProtocols []string) (string, error) { if len(supportedProtocols) == 0 || len(peerSupportedProtocols) == 0 { return "", nil @@ -76,5 +78,6 @@ func ALPNProtocolSelection(supportedProtocols, peerSupportedProtocols []string) } } } + return "", errALPNNoAppProto } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/extension/connection_id.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/extension/connection_id.go new file mode 100644 index 000000000..6c8a7f566 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/extension/connection_id.go @@ -0,0 +1,61 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + +package extension + +import ( + "golang.org/x/crypto/cryptobyte" +) + +// ConnectionID is a DTLS extension that provides an alternative to IP address +// and port for session association. +// +// https://tools.ietf.org/html/rfc9146 +type ConnectionID struct { + // A zero-length connection ID indicates for a client or server that + // negotiated connection IDs from the peer will be sent but there is no need + // to respond with one + CID []byte // variable length +} + +// TypeValue returns the extension TypeValue. +func (c ConnectionID) TypeValue() TypeValue { + return ConnectionIDTypeValue +} + +// Marshal encodes the extension. +func (c *ConnectionID) Marshal() ([]byte, error) { + var b cryptobyte.Builder + b.AddUint16(uint16(c.TypeValue())) + b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) { + b.AddBytes(c.CID) + }) + }) + + return b.Bytes() +} + +// Unmarshal populates the extension from encoded data. +func (c *ConnectionID) Unmarshal(data []byte) error { + val := cryptobyte.String(data) + var extension uint16 + val.ReadUint16(&extension) + if TypeValue(extension) != c.TypeValue() { + return errInvalidExtensionType + } + + var extData cryptobyte.String + val.ReadUint16LengthPrefixed(&extData) + + var cid cryptobyte.String + if !extData.ReadUint8LengthPrefixed(&cid) { + return errInvalidCIDFormat + } + c.CID = make([]byte, len(cid)) + if !cid.CopyBytes(c.CID) { + return errInvalidCIDFormat + } + + return nil +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/extension/errors.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/extension/errors.go new file mode 100644 index 000000000..424ae5b1a --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/extension/errors.go @@ -0,0 +1,38 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + +package extension + +import ( + "errors" + + "github.com/pion/dtls/v3/pkg/protocol" +) + +var ( + // ErrALPNInvalidFormat is raised when the ALPN format is invalid. + ErrALPNInvalidFormat = &protocol.FatalError{ + Err: errors.New("invalid alpn format"), //nolint:goerr113 + } + errALPNNoAppProto = &protocol.FatalError{ + Err: errors.New("no application protocol"), //nolint:goerr113 + } + errBufferTooSmall = &protocol.TemporaryError{ + Err: errors.New("buffer is too small"), //nolint:goerr113 + } + errInvalidExtensionType = &protocol.FatalError{ + Err: errors.New("invalid extension type"), //nolint:goerr113 + } + errInvalidSNIFormat = &protocol.FatalError{ + Err: errors.New("invalid server name format"), //nolint:goerr113 + } + errInvalidCIDFormat = &protocol.FatalError{ + Err: errors.New("invalid connection ID format"), //nolint:goerr113 + } + errLengthMismatch = &protocol.InternalError{ + Err: errors.New("data length and declared length do not match"), //nolint:goerr113 + } + errMasterKeyIdentifierTooLarge = &protocol.FatalError{ + Err: errors.New("master key identifier is over 255 bytes"), //nolint:goerr113 + } +) diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/extension/extension.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/extension/extension.go similarity index 80% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/extension/extension.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/extension/extension.go index 5173a5863..ba82beea3 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/extension/extension.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/extension/extension.go @@ -11,7 +11,7 @@ import "encoding/binary" // https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml type TypeValue uint16 -// TypeValue constants +// TypeValue constants. const ( ServerNameTypeValue TypeValue = 0 SupportedEllipticCurvesTypeValue TypeValue = 10 @@ -20,18 +20,19 @@ const ( UseSRTPTypeValue TypeValue = 14 ALPNTypeValue TypeValue = 16 UseExtendedMasterSecretTypeValue TypeValue = 23 + ConnectionIDTypeValue TypeValue = 54 RenegotiationInfoTypeValue TypeValue = 65281 ) -// Extension represents a single TLS extension +// Extension represents a single TLS extension. type Extension interface { Marshal() ([]byte, error) Unmarshal(data []byte) error TypeValue() TypeValue } -// Unmarshal many extensions at once -func Unmarshal(buf []byte) ([]Extension, error) { +// Unmarshal many extensions at once. +func Unmarshal(buf []byte) ([]Extension, error) { //nolint:cyclop switch { case len(buf) == 0: return []Extension{}, nil @@ -51,6 +52,7 @@ func Unmarshal(buf []byte) ([]Extension, error) { return err } extensions = append(extensions, e) + return nil } @@ -64,6 +66,10 @@ func Unmarshal(buf []byte) ([]Extension, error) { err = unmarshalAndAppend(buf[offset:], &ServerName{}) case SupportedEllipticCurvesTypeValue: err = unmarshalAndAppend(buf[offset:], &SupportedEllipticCurves{}) + case SupportedPointFormatsTypeValue: + err = unmarshalAndAppend(buf[offset:], &SupportedPointFormats{}) + case SupportedSignatureAlgorithmsTypeValue: + err = unmarshalAndAppend(buf[offset:], &SupportedSignatureAlgorithms{}) case UseSRTPTypeValue: err = unmarshalAndAppend(buf[offset:], &UseSRTP{}) case ALPNTypeValue: @@ -72,6 +78,8 @@ func Unmarshal(buf []byte) ([]Extension, error) { err = unmarshalAndAppend(buf[offset:], &UseExtendedMasterSecret{}) case RenegotiationInfoTypeValue: err = unmarshalAndAppend(buf[offset:], &RenegotiationInfo{}) + case ConnectionIDTypeValue: + err = unmarshalAndAppend(buf[offset:], &ConnectionID{}) default: } if err != nil { @@ -83,10 +91,11 @@ func Unmarshal(buf []byte) ([]Extension, error) { extensionLength := binary.BigEndian.Uint16(buf[offset+2:]) offset += (4 + int(extensionLength)) } + return extensions, nil } -// Marshal many extensions at once +// Marshal many extensions at once. func Marshal(e []Extension) ([]byte, error) { extensions := []byte{} for _, e := range e { @@ -97,6 +106,7 @@ func Marshal(e []Extension) ([]byte, error) { extensions = append(extensions, raw...) } out := []byte{0x00, 0x00} - binary.BigEndian.PutUint16(out, uint16(len(extensions))) + binary.BigEndian.PutUint16(out, uint16(len(extensions))) //nolint:gosec // G115 + return append(out, extensions...), nil } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/extension/renegotiation_info.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/extension/renegotiation_info.go similarity index 88% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/extension/renegotiation_info.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/extension/renegotiation_info.go index c5092a7db..57432fd0b 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/extension/renegotiation_info.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/extension/renegotiation_info.go @@ -17,22 +17,23 @@ type RenegotiationInfo struct { RenegotiatedConnection uint8 } -// TypeValue returns the extension TypeValue +// TypeValue returns the extension TypeValue. func (r RenegotiationInfo) TypeValue() TypeValue { return RenegotiationInfoTypeValue } -// Marshal encodes the extension +// Marshal encodes the extension. func (r *RenegotiationInfo) Marshal() ([]byte, error) { out := make([]byte, renegotiationInfoHeaderSize) binary.BigEndian.PutUint16(out, uint16(r.TypeValue())) binary.BigEndian.PutUint16(out[2:], uint16(1)) // length out[4] = r.RenegotiatedConnection + return out, nil } -// Unmarshal populates the extension from encoded data +// Unmarshal populates the extension from encoded data. func (r *RenegotiationInfo) Unmarshal(data []byte) error { if len(data) < renegotiationInfoHeaderSize { return errBufferTooSmall diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/extension/server_name.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/extension/server_name.go similarity index 90% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/extension/server_name.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/extension/server_name.go index 183e08e6e..31e6327d3 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/extension/server_name.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/extension/server_name.go @@ -20,12 +20,12 @@ type ServerName struct { ServerName string } -// TypeValue returns the extension TypeValue +// TypeValue returns the extension TypeValue. func (s ServerName) TypeValue() TypeValue { return ServerNameTypeValue } -// Marshal encodes the extension +// Marshal encodes the extension. func (s *ServerName) Marshal() ([]byte, error) { var b cryptobyte.Builder b.AddUint16(uint16(s.TypeValue())) @@ -37,11 +37,12 @@ func (s *ServerName) Marshal() ([]byte, error) { }) }) }) + return b.Bytes() } -// Unmarshal populates the extension from encoded data -func (s *ServerName) Unmarshal(data []byte) error { +// Unmarshal populates the extension from encoded data. +func (s *ServerName) Unmarshal(data []byte) error { //nolint:cyclop val := cryptobyte.String(data) var extension uint16 val.ReadUint16(&extension) @@ -77,5 +78,6 @@ func (s *ServerName) Unmarshal(data []byte) error { return errInvalidSNIFormat } } + return nil } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/extension/srtp_protection_profile.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/extension/srtp_protection_profile.go similarity index 66% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/extension/srtp_protection_profile.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/extension/srtp_protection_profile.go index 2966966dd..75a8c2ee3 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/extension/srtp_protection_profile.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/extension/srtp_protection_profile.go @@ -10,6 +10,10 @@ type SRTPProtectionProfile uint16 const ( SRTP_AES128_CM_HMAC_SHA1_80 SRTPProtectionProfile = 0x0001 // nolint SRTP_AES128_CM_HMAC_SHA1_32 SRTPProtectionProfile = 0x0002 // nolint + SRTP_AES256_CM_SHA1_80 SRTPProtectionProfile = 0x0003 // nolint + SRTP_AES256_CM_SHA1_32 SRTPProtectionProfile = 0x0004 // nolint + SRTP_NULL_HMAC_SHA1_80 SRTPProtectionProfile = 0x0005 // nolint + SRTP_NULL_HMAC_SHA1_32 SRTPProtectionProfile = 0x0006 // nolint SRTP_AEAD_AES_128_GCM SRTPProtectionProfile = 0x0007 // nolint SRTP_AEAD_AES_256_GCM SRTPProtectionProfile = 0x0008 // nolint ) @@ -18,6 +22,10 @@ func srtpProtectionProfiles() map[SRTPProtectionProfile]bool { return map[SRTPProtectionProfile]bool{ SRTP_AES128_CM_HMAC_SHA1_80: true, SRTP_AES128_CM_HMAC_SHA1_32: true, + SRTP_AES256_CM_SHA1_80: true, + SRTP_AES256_CM_SHA1_32: true, + SRTP_NULL_HMAC_SHA1_80: true, + SRTP_NULL_HMAC_SHA1_32: true, SRTP_AEAD_AES_128_GCM: true, SRTP_AEAD_AES_256_GCM: true, } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/extension/supported_elliptic_curves.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/extension/supported_elliptic_curves.go similarity index 83% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/extension/supported_elliptic_curves.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/extension/supported_elliptic_curves.go index dd9b54f0d..e3e87634b 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/extension/supported_elliptic_curves.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/extension/supported_elliptic_curves.go @@ -6,7 +6,7 @@ package extension import ( "encoding/binary" - "github.com/pion/dtls/v2/pkg/crypto/elliptic" + "github.com/pion/dtls/v3/pkg/crypto/elliptic" ) const ( @@ -21,28 +21,28 @@ type SupportedEllipticCurves struct { EllipticCurves []elliptic.Curve } -// TypeValue returns the extension TypeValue +// TypeValue returns the extension TypeValue. func (s SupportedEllipticCurves) TypeValue() TypeValue { return SupportedEllipticCurvesTypeValue } -// Marshal encodes the extension +// Marshal encodes the extension. func (s *SupportedEllipticCurves) Marshal() ([]byte, error) { out := make([]byte, supportedGroupsHeaderSize) binary.BigEndian.PutUint16(out, uint16(s.TypeValue())) - binary.BigEndian.PutUint16(out[2:], uint16(2+(len(s.EllipticCurves)*2))) - binary.BigEndian.PutUint16(out[4:], uint16(len(s.EllipticCurves)*2)) + binary.BigEndian.PutUint16(out[2:], uint16(2+(len(s.EllipticCurves)*2))) //nolint:gosec // G115 + binary.BigEndian.PutUint16(out[4:], uint16(len(s.EllipticCurves)*2)) //nolint:gosec // G115 for _, v := range s.EllipticCurves { - out = append(out, []byte{0x00, 0x00}...) + out = append(out, []byte{0x00, 0x00}...) //nolint:makezero // todo: fix binary.BigEndian.PutUint16(out[len(out)-2:], uint16(v)) } return out, nil } -// Unmarshal populates the extension from encoded data +// Unmarshal populates the extension from encoded data. func (s *SupportedEllipticCurves) Unmarshal(data []byte) error { if len(data) <= supportedGroupsHeaderSize { return errBufferTooSmall @@ -61,5 +61,6 @@ func (s *SupportedEllipticCurves) Unmarshal(data []byte) error { s.EllipticCurves = append(s.EllipticCurves, supportedGroupID) } } + return nil } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/extension/supported_point_formats.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/extension/supported_point_formats.go similarity index 74% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/extension/supported_point_formats.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/extension/supported_point_formats.go index 9c2543e6e..77dc4fd50 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/extension/supported_point_formats.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/extension/supported_point_formats.go @@ -6,7 +6,7 @@ package extension import ( "encoding/binary" - "github.com/pion/dtls/v2/pkg/crypto/elliptic" + "github.com/pion/dtls/v3/pkg/crypto/elliptic" ) const ( @@ -21,35 +21,38 @@ type SupportedPointFormats struct { PointFormats []elliptic.CurvePointFormat } -// TypeValue returns the extension TypeValue +// TypeValue returns the extension TypeValue. func (s SupportedPointFormats) TypeValue() TypeValue { return SupportedPointFormatsTypeValue } -// Marshal encodes the extension +// Marshal encodes the extension. func (s *SupportedPointFormats) Marshal() ([]byte, error) { out := make([]byte, supportedPointFormatsSize) binary.BigEndian.PutUint16(out, uint16(s.TypeValue())) - binary.BigEndian.PutUint16(out[2:], uint16(1+(len(s.PointFormats)))) + binary.BigEndian.PutUint16(out[2:], uint16(1+(len(s.PointFormats)))) //nolint:gosec // G115 out[4] = byte(len(s.PointFormats)) for _, v := range s.PointFormats { - out = append(out, byte(v)) + out = append(out, byte(v)) //nolint:makezero // todo: fix } + return out, nil } -// Unmarshal populates the extension from encoded data +// Unmarshal populates the extension from encoded data. func (s *SupportedPointFormats) Unmarshal(data []byte) error { if len(data) <= supportedPointFormatsSize { return errBufferTooSmall - } else if TypeValue(binary.BigEndian.Uint16(data)) != s.TypeValue() { + } + + if TypeValue(binary.BigEndian.Uint16(data)) != s.TypeValue() { return errInvalidExtensionType } - pointFormatCount := int(binary.BigEndian.Uint16(data[4:])) - if supportedGroupsHeaderSize+(pointFormatCount) > len(data) { + pointFormatCount := int(data[4]) + if supportedPointFormatsSize+pointFormatCount > len(data) { return errLengthMismatch } @@ -61,5 +64,6 @@ func (s *SupportedPointFormats) Unmarshal(data []byte) error { default: } } + return nil } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/extension/supported_signature_algorithms.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/extension/supported_signature_algorithms.go similarity index 82% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/extension/supported_signature_algorithms.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/extension/supported_signature_algorithms.go index 2ff4b90b6..e7ad0d422 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/extension/supported_signature_algorithms.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/extension/supported_signature_algorithms.go @@ -6,9 +6,9 @@ package extension import ( "encoding/binary" - "github.com/pion/dtls/v2/pkg/crypto/hash" - "github.com/pion/dtls/v2/pkg/crypto/signature" - "github.com/pion/dtls/v2/pkg/crypto/signaturehash" + "github.com/pion/dtls/v3/pkg/crypto/hash" + "github.com/pion/dtls/v3/pkg/crypto/signature" + "github.com/pion/dtls/v3/pkg/crypto/signaturehash" ) const ( @@ -23,20 +23,20 @@ type SupportedSignatureAlgorithms struct { SignatureHashAlgorithms []signaturehash.Algorithm } -// TypeValue returns the extension TypeValue +// TypeValue returns the extension TypeValue. func (s SupportedSignatureAlgorithms) TypeValue() TypeValue { return SupportedSignatureAlgorithmsTypeValue } -// Marshal encodes the extension +// Marshal encodes the extension. func (s *SupportedSignatureAlgorithms) Marshal() ([]byte, error) { out := make([]byte, supportedSignatureAlgorithmsHeaderSize) binary.BigEndian.PutUint16(out, uint16(s.TypeValue())) - binary.BigEndian.PutUint16(out[2:], uint16(2+(len(s.SignatureHashAlgorithms)*2))) - binary.BigEndian.PutUint16(out[4:], uint16(len(s.SignatureHashAlgorithms)*2)) + binary.BigEndian.PutUint16(out[2:], uint16(2+(len(s.SignatureHashAlgorithms)*2))) //nolint:gosec // G115 + binary.BigEndian.PutUint16(out[4:], uint16(len(s.SignatureHashAlgorithms)*2)) //nolint:gosec // G115 for _, v := range s.SignatureHashAlgorithms { - out = append(out, []byte{0x00, 0x00}...) + out = append(out, []byte{0x00, 0x00}...) //nolint:makezero // todo: fix out[len(out)-2] = byte(v.Hash) out[len(out)-1] = byte(v.Signature) } @@ -44,7 +44,7 @@ func (s *SupportedSignatureAlgorithms) Marshal() ([]byte, error) { return out, nil } -// Unmarshal populates the extension from encoded data +// Unmarshal populates the extension from encoded data. func (s *SupportedSignatureAlgorithms) Unmarshal(data []byte) error { if len(data) <= supportedSignatureAlgorithmsHeaderSize { return errBufferTooSmall diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/extension/use_master_secret.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/extension/use_master_secret.go similarity index 89% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/extension/use_master_secret.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/extension/use_master_secret.go index d0b70cafb..fcf5dd289 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/extension/use_master_secret.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/extension/use_master_secret.go @@ -16,12 +16,12 @@ type UseExtendedMasterSecret struct { Supported bool } -// TypeValue returns the extension TypeValue +// TypeValue returns the extension TypeValue. func (u UseExtendedMasterSecret) TypeValue() TypeValue { return UseExtendedMasterSecretTypeValue } -// Marshal encodes the extension +// Marshal encodes the extension. func (u *UseExtendedMasterSecret) Marshal() ([]byte, error) { if !u.Supported { return []byte{}, nil @@ -31,10 +31,11 @@ func (u *UseExtendedMasterSecret) Marshal() ([]byte, error) { binary.BigEndian.PutUint16(out, uint16(u.TypeValue())) binary.BigEndian.PutUint16(out[2:], uint16(0)) // length + return out, nil } -// Unmarshal populates the extension from encoded data +// Unmarshal populates the extension from encoded data. func (u *UseExtendedMasterSecret) Unmarshal(data []byte) error { if len(data) < useExtendedMasterSecretHeaderSize { return errBufferTooSmall diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/extension/use_srtp.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/extension/use_srtp.go similarity index 53% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/extension/use_srtp.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/extension/use_srtp.go index ea9f10872..4e0410cae 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/extension/use_srtp.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/extension/use_srtp.go @@ -3,7 +3,9 @@ package extension -import "encoding/binary" +import ( + "encoding/binary" +) const ( useSRTPHeaderSize = 6 @@ -14,32 +16,42 @@ const ( // // https://tools.ietf.org/html/rfc8422 type UseSRTP struct { - ProtectionProfiles []SRTPProtectionProfile + ProtectionProfiles []SRTPProtectionProfile + MasterKeyIdentifier []byte } -// TypeValue returns the extension TypeValue +// TypeValue returns the extension TypeValue. func (u UseSRTP) TypeValue() TypeValue { return UseSRTPTypeValue } -// Marshal encodes the extension +// Marshal encodes the extension. func (u *UseSRTP) Marshal() ([]byte, error) { out := make([]byte, useSRTPHeaderSize) binary.BigEndian.PutUint16(out, uint16(u.TypeValue())) - binary.BigEndian.PutUint16(out[2:], uint16(2+(len(u.ProtectionProfiles)*2)+ /* MKI Length */ 1)) - binary.BigEndian.PutUint16(out[4:], uint16(len(u.ProtectionProfiles)*2)) + //nolint:gosec // G115 + binary.BigEndian.PutUint16( + out[2:], + uint16(2+(len(u.ProtectionProfiles)*2)+ /* MKI Length */ 1+len(u.MasterKeyIdentifier)), + ) + binary.BigEndian.PutUint16(out[4:], uint16(len(u.ProtectionProfiles)*2)) //nolint:gosec // G115 for _, v := range u.ProtectionProfiles { - out = append(out, []byte{0x00, 0x00}...) + out = append(out, []byte{0x00, 0x00}...) //nolint:makezero // todo: fix binary.BigEndian.PutUint16(out[len(out)-2:], uint16(v)) } + if len(u.MasterKeyIdentifier) > 255 { + return nil, errMasterKeyIdentifierTooLarge + } + + out = append(out, byte(len(u.MasterKeyIdentifier))) //nolint:makezero // todo: fix + out = append(out, u.MasterKeyIdentifier...) //nolint:makezero // todo: fix - out = append(out, 0x00) /* MKI Length */ return out, nil } -// Unmarshal populates the extension from encoded data +// Unmarshal populates the extension from encoded data. func (u *UseSRTP) Unmarshal(data []byte) error { if len(data) <= useSRTPHeaderSize { return errBufferTooSmall @@ -48,7 +60,8 @@ func (u *UseSRTP) Unmarshal(data []byte) error { } profileCount := int(binary.BigEndian.Uint16(data[4:]) / 2) - if supportedGroupsHeaderSize+(profileCount*2) > len(data) { + masterKeyIdentifierIndex := supportedGroupsHeaderSize + (profileCount * 2) + if masterKeyIdentifierIndex+1 > len(data) { return errLengthMismatch } @@ -58,5 +71,16 @@ func (u *UseSRTP) Unmarshal(data []byte) error { u.ProtectionProfiles = append(u.ProtectionProfiles, supportedProfile) } } + + masterKeyIdentifierLen := int(data[masterKeyIdentifierIndex]) + if masterKeyIdentifierIndex+masterKeyIdentifierLen >= len(data) { + return errLengthMismatch + } + + u.MasterKeyIdentifier = append( + []byte{}, + data[masterKeyIdentifierIndex+1:masterKeyIdentifierIndex+1+masterKeyIdentifierLen]..., + ) + return nil } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/handshake/cipher_suite.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/handshake/cipher_suite.go similarity index 95% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/handshake/cipher_suite.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/handshake/cipher_suite.go index b29629717..49d2b7407 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/handshake/cipher_suite.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/handshake/cipher_suite.go @@ -18,15 +18,17 @@ func decodeCipherSuiteIDs(buf []byte) ([]uint16, error) { rtrn[i] = binary.BigEndian.Uint16(buf[(i*2)+2:]) } + return rtrn, nil } func encodeCipherSuiteIDs(cipherSuiteIDs []uint16) []byte { out := []byte{0x00, 0x00} - binary.BigEndian.PutUint16(out[len(out)-2:], uint16(len(cipherSuiteIDs)*2)) + binary.BigEndian.PutUint16(out[len(out)-2:], uint16(len(cipherSuiteIDs)*2)) //nolint:gosec // G115 for _, id := range cipherSuiteIDs { out = append(out, []byte{0x00, 0x00}...) binary.BigEndian.PutUint16(out[len(out)-2:], id) } + return out } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/handshake/errors.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/handshake/errors.go new file mode 100644 index 000000000..20794f78c --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/handshake/errors.go @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + +package handshake + +import ( + "errors" + + "github.com/pion/dtls/v3/pkg/protocol" +) + +// Typed errors. +var ( + errUnableToMarshalFragmented = &protocol.InternalError{ + Err: errors.New("unable to marshal fragmented handshakes"), //nolint:err113 + } + errHandshakeMessageUnset = &protocol.InternalError{ + Err: errors.New("handshake message unset, unable to marshal"), //nolint:err113 + } + errBufferTooSmall = &protocol.TemporaryError{ + Err: errors.New("buffer is too small"), //nolint:err113 + } + errLengthMismatch = &protocol.InternalError{ + Err: errors.New("data length and declared length do not match"), //nolint:err113 + } + errInvalidClientKeyExchange = &protocol.FatalError{ + Err: errors.New("unable to determine if ClientKeyExchange is a public key or PSK Identity"), //nolint:err113 + } + errInvalidHashAlgorithm = &protocol.FatalError{ + Err: errors.New("invalid hash algorithm"), //nolint:err113 + } + errInvalidSignatureAlgorithm = &protocol.FatalError{ + Err: errors.New("invalid signature algorithm"), //nolint:err113 + } + errCookieTooLong = &protocol.FatalError{ + Err: errors.New("cookie must not be longer then 255 bytes"), //nolint:err113 + } + errInvalidEllipticCurveType = &protocol.FatalError{ + Err: errors.New("invalid or unknown elliptic curve type"), //nolint:err113 + } + errInvalidNamedCurve = &protocol.FatalError{ + Err: errors.New("invalid named curve"), //nolint:err113 + } + errCipherSuiteUnset = &protocol.FatalError{ + Err: errors.New("server hello can not be created without a cipher suite"), //nolint:err113 + } + errCompressionMethodUnset = &protocol.FatalError{ + Err: errors.New("server hello can not be created without a compression method"), //nolint:err113 + } + errInvalidCompressionMethod = &protocol.FatalError{ + Err: errors.New("invalid or unknown compression method"), //nolint:err113 + } + errNotImplemented = &protocol.InternalError{ + Err: errors.New("feature has not been implemented yet"), //nolint:err113 + } +) diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/handshake/handshake.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/handshake/handshake.go similarity index 84% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/handshake/handshake.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/handshake/handshake.go index b1f682bf5..9c6187711 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/handshake/handshake.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/handshake/handshake.go @@ -5,16 +5,16 @@ package handshake import ( - "github.com/pion/dtls/v2/internal/ciphersuite/types" - "github.com/pion/dtls/v2/internal/util" - "github.com/pion/dtls/v2/pkg/protocol" + "github.com/pion/dtls/v3/internal/ciphersuite/types" + "github.com/pion/dtls/v3/internal/util" + "github.com/pion/dtls/v3/pkg/protocol" ) // Type is the unique identifier for each handshake message // https://tools.ietf.org/html/rfc5246#section-7.4 type Type uint8 -// Types of DTLS Handshake messages we know about +// Types of DTLS Handshake messages we know about. const ( TypeHelloRequest Type = 0 TypeClientHello Type = 1 @@ -29,8 +29,8 @@ const ( TypeFinished Type = 20 ) -// String returns the string representation of this type -func (t Type) String() string { +// String returns the string representation of this type. +func (t Type) String() string { //nolint:cyclop switch t { case TypeHelloRequest: return "HelloRequest" @@ -55,10 +55,11 @@ func (t Type) String() string { case TypeFinished: return "Finished" } + return "" } -// Message is the body of a Handshake datagram +// Message is the body of a Handshake datagram. type Message interface { Marshal() ([]byte, error) Unmarshal(data []byte) error @@ -78,12 +79,12 @@ type Handshake struct { KeyExchangeAlgorithm types.KeyExchangeAlgorithm } -// ContentType returns what kind of content this message is carying +// ContentType returns what kind of content this message is carying. func (h Handshake) ContentType() protocol.ContentType { return protocol.ContentTypeHandshake } -// Marshal encodes a handshake into a binary message +// Marshal encodes a handshake into a binary message. func (h *Handshake) Marshal() ([]byte, error) { if h.Message == nil { return nil, errHandshakeMessageUnset @@ -96,7 +97,7 @@ func (h *Handshake) Marshal() ([]byte, error) { return nil, err } - h.Header.Length = uint32(len(msg)) + h.Header.Length = uint32(len(msg)) //nolint:gosec // G115 h.Header.FragmentLength = h.Header.Length h.Header.Type = h.Message.Type() header, err := h.Header.Marshal() @@ -107,14 +108,14 @@ func (h *Handshake) Marshal() ([]byte, error) { return append(header, msg...), nil } -// Unmarshal decodes a handshake from a binary message -func (h *Handshake) Unmarshal(data []byte) error { +// Unmarshal decodes a handshake from a binary message. +func (h *Handshake) Unmarshal(data []byte) error { //nolint:cyclop if err := h.Header.Unmarshal(data); err != nil { return err } reportedLen := util.BigEndianUint24(data[1:]) - if uint32(len(data)-HeaderLength) != reportedLen { + if uint32(len(data)-HeaderLength) != reportedLen { //nolint:gosec // G115 return errLengthMismatch } else if reportedLen != h.Header.FragmentLength { return errLengthMismatch @@ -146,5 +147,6 @@ func (h *Handshake) Unmarshal(data []byte) error { default: return errNotImplemented } + return h.Message.Unmarshal(data[HeaderLength:]) } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/handshake/header.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/handshake/header.go similarity index 91% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/handshake/header.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/handshake/header.go index 4f9a96287..4e909de54 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/handshake/header.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/handshake/header.go @@ -6,11 +6,11 @@ package handshake import ( "encoding/binary" - "github.com/pion/dtls/v2/internal/util" + "github.com/pion/dtls/v3/internal/util" ) // HeaderLength msg_len for Handshake messages assumes an extra -// 12 bytes for sequence, fragment and version information vs TLS +// 12 bytes for sequence, fragment and version information vs TLS. const HeaderLength = 12 // Header is the static first 12 bytes of each RecordLayer @@ -26,7 +26,7 @@ type Header struct { FragmentLength uint32 // uint24 in spec } -// Marshal encodes the Header +// Marshal encodes the Header. func (h *Header) Marshal() ([]byte, error) { out := make([]byte, HeaderLength) @@ -35,10 +35,11 @@ func (h *Header) Marshal() ([]byte, error) { binary.BigEndian.PutUint16(out[4:], h.MessageSequence) util.PutBigEndianUint24(out[6:], h.FragmentOffset) util.PutBigEndianUint24(out[9:], h.FragmentLength) + return out, nil } -// Unmarshal populates the header from encoded data +// Unmarshal populates the header from encoded data. func (h *Header) Unmarshal(data []byte) error { if len(data) < HeaderLength { return errBufferTooSmall @@ -49,5 +50,6 @@ func (h *Header) Unmarshal(data []byte) error { h.MessageSequence = binary.BigEndian.Uint16(data[4:]) h.FragmentOffset = util.BigEndianUint24(data[6:]) h.FragmentLength = util.BigEndianUint24(data[9:]) + return nil } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/handshake/message_certificate.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/handshake/message_certificate.go similarity index 75% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/handshake/message_certificate.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/handshake/message_certificate.go index d5c861d90..27d2ea99a 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/handshake/message_certificate.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/handshake/message_certificate.go @@ -4,7 +4,7 @@ package handshake import ( - "github.com/pion/dtls/v2/internal/util" + "github.com/pion/dtls/v3/internal/util" ) // MessageCertificate is a DTLS Handshake Message @@ -15,7 +15,7 @@ type MessageCertificate struct { Certificate [][]byte } -// Type returns the Handshake Type +// Type returns the Handshake Type. func (m MessageCertificate) Type() Type { return TypeCertificate } @@ -24,31 +24,36 @@ const ( handshakeMessageCertificateLengthFieldSize = 3 ) -// Marshal encodes the Handshake +// Marshal encodes the Handshake. func (m *MessageCertificate) Marshal() ([]byte, error) { out := make([]byte, handshakeMessageCertificateLengthFieldSize) for _, r := range m.Certificate { // Certificate Length + //nolint:makezero // todo: fix out = append(out, make([]byte, handshakeMessageCertificateLengthFieldSize)...) + //nolint:gosec // G115 util.PutBigEndianUint24(out[len(out)-handshakeMessageCertificateLengthFieldSize:], uint32(len(r))) // Certificate body - out = append(out, append([]byte{}, r...)...) + out = append(out, append([]byte{}, r...)...) //nolint:makezero // todo: fix } // Total Payload Size - util.PutBigEndianUint24(out[0:], uint32(len(out[handshakeMessageCertificateLengthFieldSize:]))) + util.PutBigEndianUint24(out[0:], uint32(len(out[handshakeMessageCertificateLengthFieldSize:]))) //nolint:gosec //G115 + return out, nil } -// Unmarshal populates the message from encoded data +// Unmarshal populates the message from encoded data. func (m *MessageCertificate) Unmarshal(data []byte) error { if len(data) < handshakeMessageCertificateLengthFieldSize { return errBufferTooSmall } - if certificateBodyLen := int(util.BigEndianUint24(data)); certificateBodyLen+handshakeMessageCertificateLengthFieldSize != len(data) { + if certificateBodyLen := int(util.BigEndianUint24( + data, + )); certificateBodyLen+handshakeMessageCertificateLengthFieldSize != len(data) { return errLengthMismatch } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/handshake/message_certificate_request.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/handshake/message_certificate_request.go similarity index 89% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/handshake/message_certificate_request.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/handshake/message_certificate_request.go index 11a44d440..28dabf35a 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/handshake/message_certificate_request.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/handshake/message_certificate_request.go @@ -6,10 +6,10 @@ package handshake import ( "encoding/binary" - "github.com/pion/dtls/v2/pkg/crypto/clientcertificate" - "github.com/pion/dtls/v2/pkg/crypto/hash" - "github.com/pion/dtls/v2/pkg/crypto/signature" - "github.com/pion/dtls/v2/pkg/crypto/signaturehash" + "github.com/pion/dtls/v3/pkg/crypto/clientcertificate" + "github.com/pion/dtls/v3/pkg/crypto/hash" + "github.com/pion/dtls/v3/pkg/crypto/signature" + "github.com/pion/dtls/v3/pkg/crypto/signaturehash" ) /* @@ -31,12 +31,12 @@ const ( messageCertificateRequestMinLength = 5 ) -// Type returns the Handshake Type +// Type returns the Handshake Type. func (m MessageCertificateRequest) Type() Type { return TypeCertificateRequest } -// Marshal encodes the Handshake +// Marshal encodes the Handshake. func (m *MessageCertificateRequest) Marshal() ([]byte, error) { out := []byte{byte(len(m.CertificateTypes))} for _, v := range m.CertificateTypes { @@ -44,7 +44,7 @@ func (m *MessageCertificateRequest) Marshal() ([]byte, error) { } out = append(out, []byte{0x00, 0x00}...) - binary.BigEndian.PutUint16(out[len(out)-2:], uint16(len(m.SignatureHashAlgorithms)*2)) + binary.BigEndian.PutUint16(out[len(out)-2:], uint16(len(m.SignatureHashAlgorithms)*2)) //nolint:gosec //G115 for _, v := range m.SignatureHashAlgorithms { out = append(out, byte(v.Hash)) out = append(out, byte(v.Signature)) @@ -56,19 +56,20 @@ func (m *MessageCertificateRequest) Marshal() ([]byte, error) { casLength += len(ca) + 2 } out = append(out, []byte{0x00, 0x00}...) - binary.BigEndian.PutUint16(out[len(out)-2:], uint16(casLength)) + binary.BigEndian.PutUint16(out[len(out)-2:], uint16(casLength)) //nolint:gosec //G115 if casLength > 0 { for _, ca := range m.CertificateAuthoritiesNames { out = append(out, []byte{0x00, 0x00}...) - binary.BigEndian.PutUint16(out[len(out)-2:], uint16(len(ca))) + binary.BigEndian.PutUint16(out[len(out)-2:], uint16(len(ca))) //nolint:gosec //G115 out = append(out, ca...) } } + return out, nil } -// Unmarshal populates the message from encoded data -func (m *MessageCertificateRequest) Unmarshal(data []byte) error { +// Unmarshal populates the message from encoded data. +func (m *MessageCertificateRequest) Unmarshal(data []byte) error { //nolint:cyclop if len(data) < messageCertificateRequestMinLength { return errBufferTooSmall } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/handshake/message_certificate_verify.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/handshake/message_certificate_verify.go similarity index 82% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/handshake/message_certificate_verify.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/handshake/message_certificate_verify.go index 9e02a9c11..d10ffa035 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/handshake/message_certificate_verify.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/handshake/message_certificate_verify.go @@ -6,8 +6,8 @@ package handshake import ( "encoding/binary" - "github.com/pion/dtls/v2/pkg/crypto/hash" - "github.com/pion/dtls/v2/pkg/crypto/signature" + "github.com/pion/dtls/v3/pkg/crypto/hash" + "github.com/pion/dtls/v3/pkg/crypto/signature" ) // MessageCertificateVerify provide explicit verification of a @@ -22,23 +22,24 @@ type MessageCertificateVerify struct { const handshakeMessageCertificateVerifyMinLength = 4 -// Type returns the Handshake Type +// Type returns the Handshake Type. func (m MessageCertificateVerify) Type() Type { return TypeCertificateVerify } -// Marshal encodes the Handshake +// Marshal encodes the Handshake. func (m *MessageCertificateVerify) Marshal() ([]byte, error) { out := make([]byte, 1+1+2+len(m.Signature)) out[0] = byte(m.HashAlgorithm) out[1] = byte(m.SignatureAlgorithm) - binary.BigEndian.PutUint16(out[2:], uint16(len(m.Signature))) + binary.BigEndian.PutUint16(out[2:], uint16(len(m.Signature))) //nolint:gosec // G115 copy(out[4:], m.Signature) + return out, nil } -// Unmarshal populates the message from encoded data +// Unmarshal populates the message from encoded data. func (m *MessageCertificateVerify) Unmarshal(data []byte) error { if len(data) < handshakeMessageCertificateVerifyMinLength { return errBufferTooSmall @@ -60,5 +61,6 @@ func (m *MessageCertificateVerify) Unmarshal(data []byte) error { } m.Signature = append([]byte{}, data[4:]...) + return nil } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/handshake/message_client_hello.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/handshake/message_client_hello.go similarity index 76% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/handshake/message_client_hello.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/handshake/message_client_hello.go index bea6dd969..e7aa5e397 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/handshake/message_client_hello.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/handshake/message_client_hello.go @@ -6,8 +6,8 @@ package handshake import ( "encoding/binary" - "github.com/pion/dtls/v2/pkg/protocol" - "github.com/pion/dtls/v2/pkg/protocol/extension" + "github.com/pion/dtls/v3/pkg/protocol" + "github.com/pion/dtls/v3/pkg/protocol/extension" ) /* @@ -31,12 +31,12 @@ type MessageClientHello struct { const handshakeMessageClientHelloVariableWidthStart = 34 -// Type returns the Handshake Type +// Type returns the Handshake Type. func (m MessageClientHello) Type() Type { return TypeClientHello } -// Marshal encodes the Handshake +// Marshal encodes the Handshake. func (m *MessageClientHello) Marshal() ([]byte, error) { if len(m.Cookie) > 255 { return nil, errCookieTooLong @@ -49,24 +49,24 @@ func (m *MessageClientHello) Marshal() ([]byte, error) { rand := m.Random.MarshalFixed() copy(out[2:], rand[:]) - out = append(out, byte(len(m.SessionID))) - out = append(out, m.SessionID...) + out = append(out, byte(len(m.SessionID))) //nolint:makezero // todo: fix + out = append(out, m.SessionID...) //nolint:makezero // todo: fix - out = append(out, byte(len(m.Cookie))) - out = append(out, m.Cookie...) - out = append(out, encodeCipherSuiteIDs(m.CipherSuiteIDs)...) - out = append(out, protocol.EncodeCompressionMethods(m.CompressionMethods)...) + out = append(out, byte(len(m.Cookie))) //nolint:makezero // todo: fix + out = append(out, m.Cookie...) //nolint:makezero // todo: fix + out = append(out, encodeCipherSuiteIDs(m.CipherSuiteIDs)...) //nolint:makezero // todo: fix + out = append(out, protocol.EncodeCompressionMethods(m.CompressionMethods)...) //nolint:makezero // todo: fix extensions, err := extension.Marshal(m.Extensions) if err != nil { return nil, err } - return append(out, extensions...), nil + return append(out, extensions...), nil //nolint:makezero // todo: fix } -// Unmarshal populates the message from encoded data -func (m *MessageClientHello) Unmarshal(data []byte) error { +// Unmarshal populates the message from encoded data. +func (m *MessageClientHello) Unmarshal(data []byte) error { //nolint:cyclop if len(data) < 2+RandomLength { return errBufferTooSmall } @@ -137,5 +137,6 @@ func (m *MessageClientHello) Unmarshal(data []byte) error { return err } m.Extensions = extensions + return nil } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/handshake/message_client_key_exchange.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/handshake/message_client_key_exchange.go similarity index 88% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/handshake/message_client_key_exchange.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/handshake/message_client_key_exchange.go index 2abcd5bf7..60361a94a 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/handshake/message_client_key_exchange.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/handshake/message_client_key_exchange.go @@ -6,7 +6,7 @@ package handshake import ( "encoding/binary" - "github.com/pion/dtls/v2/internal/ciphersuite/types" + "github.com/pion/dtls/v3/internal/ciphersuite/types" ) // MessageClientKeyExchange is a DTLS Handshake Message @@ -24,12 +24,12 @@ type MessageClientKeyExchange struct { KeyExchangeAlgorithm types.KeyExchangeAlgorithm } -// Type returns the Handshake Type +// Type returns the Handshake Type. func (m MessageClientKeyExchange) Type() Type { return TypeClientKeyExchange } -// Marshal encodes the Handshake +// Marshal encodes the Handshake. func (m *MessageClientKeyExchange) Marshal() (out []byte, err error) { if m.IdentityHint == nil && m.PublicKey == nil { return nil, errInvalidClientKeyExchange @@ -37,7 +37,7 @@ func (m *MessageClientKeyExchange) Marshal() (out []byte, err error) { if m.IdentityHint != nil { out = append([]byte{0x00, 0x00}, m.IdentityHint...) - binary.BigEndian.PutUint16(out, uint16(len(out)-2)) + binary.BigEndian.PutUint16(out, uint16(len(out)-2)) //nolint:gosec // G115 } if m.PublicKey != nil { @@ -48,7 +48,7 @@ func (m *MessageClientKeyExchange) Marshal() (out []byte, err error) { return out, nil } -// Unmarshal populates the message from encoded data +// Unmarshal populates the message from encoded data. func (m *MessageClientKeyExchange) Unmarshal(data []byte) error { switch { case len(data) < 2: diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/handshake/message_finished.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/handshake/message_finished.go similarity index 85% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/handshake/message_finished.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/handshake/message_finished.go index 255aedd7e..f7187d88a 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/handshake/message_finished.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/handshake/message_finished.go @@ -13,18 +13,19 @@ type MessageFinished struct { VerifyData []byte } -// Type returns the Handshake Type +// Type returns the Handshake Type. func (m MessageFinished) Type() Type { return TypeFinished } -// Marshal encodes the Handshake +// Marshal encodes the Handshake. func (m *MessageFinished) Marshal() ([]byte, error) { return append([]byte{}, m.VerifyData...), nil } -// Unmarshal populates the message from encoded data +// Unmarshal populates the message from encoded data. func (m *MessageFinished) Unmarshal(data []byte) error { m.VerifyData = append([]byte{}, data...) + return nil } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/handshake/message_hello_verify_request.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/handshake/message_hello_verify_request.go similarity index 90% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/handshake/message_hello_verify_request.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/handshake/message_hello_verify_request.go index 398e59cc3..7f5bc95aa 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/handshake/message_hello_verify_request.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/handshake/message_hello_verify_request.go @@ -4,7 +4,7 @@ package handshake import ( - "github.com/pion/dtls/v2/pkg/protocol" + "github.com/pion/dtls/v3/pkg/protocol" ) // MessageHelloVerifyRequest is as follows: @@ -27,12 +27,12 @@ type MessageHelloVerifyRequest struct { Cookie []byte } -// Type returns the Handshake Type +// Type returns the Handshake Type. func (m MessageHelloVerifyRequest) Type() Type { return TypeHelloVerifyRequest } -// Marshal encodes the Handshake +// Marshal encodes the Handshake. func (m *MessageHelloVerifyRequest) Marshal() ([]byte, error) { if len(m.Cookie) > 255 { return nil, errCookieTooLong @@ -47,7 +47,7 @@ func (m *MessageHelloVerifyRequest) Marshal() ([]byte, error) { return out, nil } -// Unmarshal populates the message from encoded data +// Unmarshal populates the message from encoded data. func (m *MessageHelloVerifyRequest) Unmarshal(data []byte) error { if len(data) < 3 { return errBufferTooSmall @@ -61,5 +61,6 @@ func (m *MessageHelloVerifyRequest) Unmarshal(data []byte) error { m.Cookie = make([]byte, cookieLength) copy(m.Cookie, data[3:3+cookieLength]) + return nil } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/handshake/message_server_hello.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/handshake/message_server_hello.go similarity index 81% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/handshake/message_server_hello.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/handshake/message_server_hello.go index caf186da8..e2f19c1d9 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/handshake/message_server_hello.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/handshake/message_server_hello.go @@ -6,8 +6,8 @@ package handshake import ( "encoding/binary" - "github.com/pion/dtls/v2/pkg/protocol" - "github.com/pion/dtls/v2/pkg/protocol/extension" + "github.com/pion/dtls/v3/pkg/protocol" + "github.com/pion/dtls/v3/pkg/protocol/extension" ) // MessageServerHello is sent in response to a ClientHello @@ -29,12 +29,12 @@ type MessageServerHello struct { const messageServerHelloVariableWidthStart = 2 + RandomLength -// Type returns the Handshake Type +// Type returns the Handshake Type. func (m MessageServerHello) Type() Type { return TypeServerHello } -// Marshal encodes the Handshake +// Marshal encodes the Handshake. func (m *MessageServerHello) Marshal() ([]byte, error) { if m.CipherSuiteID == nil { return nil, errCipherSuiteUnset @@ -49,23 +49,23 @@ func (m *MessageServerHello) Marshal() ([]byte, error) { rand := m.Random.MarshalFixed() copy(out[2:], rand[:]) - out = append(out, byte(len(m.SessionID))) - out = append(out, m.SessionID...) + out = append(out, byte(len(m.SessionID))) //nolint:makezero // todo: fix + out = append(out, m.SessionID...) //nolint:makezero // todo: fix - out = append(out, []byte{0x00, 0x00}...) + out = append(out, []byte{0x00, 0x00}...) //nolint:makezero // todo: fix binary.BigEndian.PutUint16(out[len(out)-2:], *m.CipherSuiteID) - out = append(out, byte(m.CompressionMethod.ID)) + out = append(out, byte(m.CompressionMethod.ID)) //nolint:makezero // todo: fix extensions, err := extension.Marshal(m.Extensions) if err != nil { return nil, err } - return append(out, extensions...), nil + return append(out, extensions...), nil //nolint:makezero // todo: fix } -// Unmarshal populates the message from encoded data +// Unmarshal populates the message from encoded data. func (m *MessageServerHello) Unmarshal(data []byte) error { if len(data) < 2+RandomLength { return errBufferTooSmall @@ -110,6 +110,7 @@ func (m *MessageServerHello) Unmarshal(data []byte) error { if len(data) <= currOffset { m.Extensions = []extension.Extension{} + return nil } @@ -118,5 +119,6 @@ func (m *MessageServerHello) Unmarshal(data []byte) error { return err } m.Extensions = extensions + return nil } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/handshake/message_server_hello_done.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/handshake/message_server_hello_done.go similarity index 77% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/handshake/message_server_hello_done.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/handshake/message_server_hello_done.go index b187dd417..49a830c2a 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/handshake/message_server_hello_done.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/handshake/message_server_hello_done.go @@ -5,20 +5,20 @@ package handshake // MessageServerHelloDone is final non-encrypted message from server // this communicates server has sent all its handshake messages and next -// should be MessageFinished +// should be MessageFinished. type MessageServerHelloDone struct{} -// Type returns the Handshake Type +// Type returns the Handshake Type. func (m MessageServerHelloDone) Type() Type { return TypeServerHelloDone } -// Marshal encodes the Handshake +// Marshal encodes the Handshake. func (m *MessageServerHelloDone) Marshal() ([]byte, error) { return []byte{}, nil } -// Unmarshal populates the message from encoded data +// Unmarshal populates the message from encoded data. func (m *MessageServerHelloDone) Unmarshal([]byte) error { return nil } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/handshake/message_server_key_exchange.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/handshake/message_server_key_exchange.go similarity index 86% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/handshake/message_server_key_exchange.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/handshake/message_server_key_exchange.go index 82abbe0d4..59a5392f3 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/handshake/message_server_key_exchange.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/handshake/message_server_key_exchange.go @@ -6,13 +6,13 @@ package handshake import ( "encoding/binary" - "github.com/pion/dtls/v2/internal/ciphersuite/types" - "github.com/pion/dtls/v2/pkg/crypto/elliptic" - "github.com/pion/dtls/v2/pkg/crypto/hash" - "github.com/pion/dtls/v2/pkg/crypto/signature" + "github.com/pion/dtls/v3/internal/ciphersuite/types" + "github.com/pion/dtls/v3/pkg/crypto/elliptic" + "github.com/pion/dtls/v3/pkg/crypto/hash" + "github.com/pion/dtls/v3/pkg/crypto/signature" ) -// MessageServerKeyExchange supports ECDH and PSK +// MessageServerKeyExchange supports ECDH and PSK. type MessageServerKeyExchange struct { IdentityHint []byte @@ -27,17 +27,17 @@ type MessageServerKeyExchange struct { KeyExchangeAlgorithm types.KeyExchangeAlgorithm } -// Type returns the Handshake Type +// Type returns the Handshake Type. func (m MessageServerKeyExchange) Type() Type { return TypeServerKeyExchange } -// Marshal encodes the Handshake -func (m *MessageServerKeyExchange) Marshal() ([]byte, error) { +// Marshal encodes the Handshake. +func (m *MessageServerKeyExchange) Marshal() ([]byte, error) { //nolint:cyclop var out []byte if m.IdentityHint != nil { out = append([]byte{0x00, 0x00}, m.IdentityHint...) - binary.BigEndian.PutUint16(out, uint16(len(out)-2)) + binary.BigEndian.PutUint16(out, uint16(len(out)-2)) //nolint:gosec //G115 } if m.EllipticCurveType == 0 || len(m.PublicKey) == 0 { @@ -60,14 +60,14 @@ func (m *MessageServerKeyExchange) Marshal() ([]byte, error) { } out = append(out, []byte{byte(m.HashAlgorithm), byte(m.SignatureAlgorithm), 0x00, 0x00}...) - binary.BigEndian.PutUint16(out[len(out)-2:], uint16(len(m.Signature))) + binary.BigEndian.PutUint16(out[len(out)-2:], uint16(len(m.Signature))) //nolint:gosec // G115 out = append(out, m.Signature...) return out, nil } -// Unmarshal populates the message from encoded data -func (m *MessageServerKeyExchange) Unmarshal(data []byte) error { +// Unmarshal populates the message from encoded data. +func (m *MessageServerKeyExchange) Unmarshal(data []byte) error { //nolint:cyclop switch { case len(data) < 2: return errBufferTooSmall @@ -84,6 +84,7 @@ func (m *MessageServerKeyExchange) Unmarshal(data []byte) error { if len(data) == 0 { return nil } + return errLengthMismatch } @@ -144,5 +145,6 @@ func (m *MessageServerKeyExchange) Unmarshal(data []byte) error { return errBufferTooSmall } m.Signature = append([]byte{}, data[offset:offset+signatureLength]...) + return nil } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/handshake/random.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/handshake/random.go similarity index 84% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/handshake/random.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/handshake/random.go index 56f37569b..6eb2815f4 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/handshake/random.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/handshake/random.go @@ -9,7 +9,7 @@ import ( "time" ) -// Consts for Random in Handshake +// Consts for Random in Handshake. const ( RandomBytesLength = 28 RandomLength = RandomBytesLength + 4 @@ -23,24 +23,24 @@ type Random struct { RandomBytes [RandomBytesLength]byte } -// MarshalFixed encodes the Handshake +// MarshalFixed encodes the Handshake. func (r *Random) MarshalFixed() [RandomLength]byte { var out [RandomLength]byte - binary.BigEndian.PutUint32(out[0:], uint32(r.GMTUnixTime.Unix())) + binary.BigEndian.PutUint32(out[0:], uint32(r.GMTUnixTime.Unix())) //nolint:gosec // G115 copy(out[4:], r.RandomBytes[:]) return out } -// UnmarshalFixed populates the message from encoded data +// UnmarshalFixed populates the message from encoded data. func (r *Random) UnmarshalFixed(data [RandomLength]byte) { r.GMTUnixTime = time.Unix(int64(binary.BigEndian.Uint32(data[0:])), 0) copy(r.RandomBytes[:], data[4:]) } // Populate fills the handshakeRandom with random values -// may be called multiple times +// may be called multiple times. func (r *Random) Populate() error { r.GMTUnixTime = time.Now() diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/recordlayer/errors.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/recordlayer/errors.go new file mode 100644 index 000000000..09599249b --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/recordlayer/errors.go @@ -0,0 +1,24 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + +// Package recordlayer implements the TLS Record Layer https://tools.ietf.org/html/rfc5246#section-6 +package recordlayer + +import ( + "errors" + + "github.com/pion/dtls/v3/pkg/protocol" +) + +var ( + // ErrInvalidPacketLength is returned when the packet length too small + // or declared length do not match. + ErrInvalidPacketLength = &protocol.TemporaryError{ + Err: errors.New("packet length and declared length do not match"), //nolint:goerr113 + } + + errBufferTooSmall = &protocol.TemporaryError{Err: errors.New("buffer is too small")} //nolint:goerr113 + errSequenceNumberOverflow = &protocol.InternalError{Err: errors.New("sequence number overflow")} //nolint:goerr113 + errUnsupportedProtocolVersion = &protocol.FatalError{Err: errors.New("unsupported protocol version")} //nolint:goerr113 + errInvalidContentType = &protocol.TemporaryError{Err: errors.New("invalid content type")} //nolint:goerr113 +) diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/recordlayer/header.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/recordlayer/header.go similarity index 54% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/recordlayer/header.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/recordlayer/header.go index 92252502b..47af855df 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/recordlayer/header.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/recordlayer/header.go @@ -6,47 +6,64 @@ package recordlayer import ( "encoding/binary" - "github.com/pion/dtls/v2/internal/util" - "github.com/pion/dtls/v2/pkg/protocol" + "github.com/pion/dtls/v3/internal/util" + "github.com/pion/dtls/v3/pkg/protocol" ) -// Header implements a TLS RecordLayer header +// Header implements a TLS RecordLayer header. type Header struct { ContentType protocol.ContentType ContentLen uint16 Version protocol.Version Epoch uint16 SequenceNumber uint64 // uint48 in spec + + // Optional Fields + ConnectionID []byte } -// RecordLayer enums +// RecordLayer enums. const ( - HeaderSize = 13 + // FixedHeaderSize is the size of a DTLS record header when connection IDs + // are not in use. + FixedHeaderSize = 13 MaxSequenceNumber = 0x0000FFFFFFFFFFFF ) -// Marshal encodes a TLS RecordLayer Header to binary +// Marshal encodes a TLS RecordLayer Header to binary. func (h *Header) Marshal() ([]byte, error) { if h.SequenceNumber > MaxSequenceNumber { return nil, errSequenceNumberOverflow } - out := make([]byte, HeaderSize) + hs := FixedHeaderSize + len(h.ConnectionID) + + out := make([]byte, hs) out[0] = byte(h.ContentType) out[1] = h.Version.Major out[2] = h.Version.Minor binary.BigEndian.PutUint16(out[3:], h.Epoch) util.PutBigEndianUint48(out[5:], h.SequenceNumber) - binary.BigEndian.PutUint16(out[HeaderSize-2:], h.ContentLen) + copy(out[11:11+len(h.ConnectionID)], h.ConnectionID) + binary.BigEndian.PutUint16(out[hs-2:], h.ContentLen) + return out, nil } -// Unmarshal populates a TLS RecordLayer Header from binary +// Unmarshal populates a TLS RecordLayer Header from binary. func (h *Header) Unmarshal(data []byte) error { - if len(data) < HeaderSize { + if len(data) < FixedHeaderSize { return errBufferTooSmall } h.ContentType = protocol.ContentType(data[0]) + if h.ContentType == protocol.ContentTypeConnectionID { + // If a CID was expected the ConnectionID should have been initialized. + if len(data) < FixedHeaderSize+len(h.ConnectionID) { + return errBufferTooSmall + } + h.ConnectionID = data[11 : 11+len(h.ConnectionID)] + } + h.Version.Major = data[1] h.Version.Minor = data[2] h.Epoch = binary.BigEndian.Uint16(data[3:]) @@ -62,3 +79,8 @@ func (h *Header) Unmarshal(data []byte) error { return nil } + +// Size returns the total size of the header. +func (h *Header) Size() int { + return FixedHeaderSize + len(h.ConnectionID) +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/recordlayer/inner_plaintext.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/recordlayer/inner_plaintext.go new file mode 100644 index 000000000..2c67c86f2 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/recordlayer/inner_plaintext.go @@ -0,0 +1,49 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + +package recordlayer + +import ( + "github.com/pion/dtls/v3/pkg/protocol" + "golang.org/x/crypto/cryptobyte" +) + +// InnerPlaintext implements DTLSInnerPlaintext +// +// https://datatracker.ietf.org/doc/html/rfc9146#name-record-layer-extensions +type InnerPlaintext struct { + Content []byte + RealType protocol.ContentType + Zeros uint +} + +// Marshal encodes a DTLS InnerPlaintext to binary. +func (p *InnerPlaintext) Marshal() ([]byte, error) { + var out cryptobyte.Builder + out.AddBytes(p.Content) + out.AddUint8(uint8(p.RealType)) + out.AddBytes(make([]byte, p.Zeros)) + + return out.Bytes() +} + +// Unmarshal populates a DTLS InnerPlaintext from binary. +func (p *InnerPlaintext) Unmarshal(data []byte) error { + // Process in reverse + i := len(data) - 1 + for i >= 0 { + if data[i] != 0 { + p.Zeros = uint(len(data) - 1 - i) //nolint:gosec // G115 + + break + } + i-- + } + if i == 0 { + return errBufferTooSmall + } + p.RealType = protocol.ContentType(data[i]) + p.Content = append([]byte{}, data[:i]...) + + return nil +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/recordlayer/recordlayer.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/recordlayer/recordlayer.go similarity index 54% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/recordlayer/recordlayer.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/recordlayer/recordlayer.go index 02325fd2d..95113da4f 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/recordlayer/recordlayer.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/recordlayer/recordlayer.go @@ -6,11 +6,28 @@ package recordlayer import ( "encoding/binary" - "github.com/pion/dtls/v2/pkg/protocol" - "github.com/pion/dtls/v2/pkg/protocol/alert" - "github.com/pion/dtls/v2/pkg/protocol/handshake" + "github.com/pion/dtls/v3/pkg/protocol" + "github.com/pion/dtls/v3/pkg/protocol/alert" + "github.com/pion/dtls/v3/pkg/protocol/handshake" ) +// DTLS fixed size record layer header when Connection IDs are not in-use. + +// --------------------------------- +// | Type | Version | Epoch | +// --------------------------------- +// | Epoch | Sequence Number | +// --------------------------------- +// | Sequence Number | Length | +// --------------------------------- +// | Length | Fragment... | +// --------------------------------- + +// fixedHeaderLenIdx is the index at which the record layer content length is +// specified in a fixed length header (i.e. one that does not include a +// Connection ID). +const fixedHeaderLenIdx = 11 + // RecordLayer which handles all data transport. // The record layer is assumed to sit directly on top of some // reliable transport such as TCP. The record layer can carry four types of content: @@ -31,14 +48,14 @@ type RecordLayer struct { Content protocol.Content } -// Marshal encodes the RecordLayer to binary +// Marshal encodes the RecordLayer to binary. func (r *RecordLayer) Marshal() ([]byte, error) { contentRaw, err := r.Content.Marshal() if err != nil { return nil, err } - r.Header.ContentLen = uint16(len(contentRaw)) + r.Header.ContentLen = uint16(len(contentRaw)) //nolint:gosec // G115 r.Header.ContentType = r.Content.ContentType() headerRaw, err := r.Header.Marshal() @@ -49,16 +66,13 @@ func (r *RecordLayer) Marshal() ([]byte, error) { return append(headerRaw, contentRaw...), nil } -// Unmarshal populates the RecordLayer from binary +// Unmarshal populates the RecordLayer from binary. func (r *RecordLayer) Unmarshal(data []byte) error { - if len(data) < HeaderSize { - return errBufferTooSmall - } if err := r.Header.Unmarshal(data); err != nil { return err } - switch protocol.ContentType(data[0]) { + switch r.Header.ContentType { case protocol.ContentTypeChangeCipherSpec: r.Content = &protocol.ChangeCipherSpec{} case protocol.ContentTypeAlert: @@ -71,7 +85,7 @@ func (r *RecordLayer) Unmarshal(data []byte) error { return errInvalidContentType } - return r.Content.Unmarshal(data[HeaderSize:]) + return r.Content.Unmarshal(data[r.Header.Size()+len(r.Header.ConnectionID):]) } // UnpackDatagram extracts all RecordLayer messages from a single datagram. @@ -85,13 +99,42 @@ func UnpackDatagram(buf []byte) ([][]byte, error) { out := [][]byte{} for offset := 0; len(buf) != offset; { - if len(buf)-offset <= HeaderSize { - return nil, errInvalidPacketLength + if len(buf)-offset <= FixedHeaderSize { + return nil, ErrInvalidPacketLength } - pktLen := (HeaderSize + int(binary.BigEndian.Uint16(buf[offset+11:]))) + pktLen := (FixedHeaderSize + int(binary.BigEndian.Uint16(buf[offset+11:]))) if offset+pktLen > len(buf) { - return nil, errInvalidPacketLength + return nil, ErrInvalidPacketLength + } + + out = append(out, buf[offset:offset+pktLen]) + offset += pktLen + } + + return out, nil +} + +// ContentAwareUnpackDatagram is the same as UnpackDatagram but considers the +// presence of a connection identifier if the record is of content type +// tls12_cid. +func ContentAwareUnpackDatagram(buf []byte, cidLength int) ([][]byte, error) { + out := [][]byte{} + + for offset := 0; len(buf) != offset; { + headerSize := FixedHeaderSize + lenIdx := fixedHeaderLenIdx + if protocol.ContentType(buf[offset]) == protocol.ContentTypeConnectionID { + headerSize += cidLength + lenIdx += cidLength + } + if len(buf)-offset <= headerSize { + return nil, ErrInvalidPacketLength + } + + pktLen := (headerSize + int(binary.BigEndian.Uint16(buf[offset+lenIdx:]))) + if offset+pktLen > len(buf) { + return nil, ErrInvalidPacketLength } out = append(out, buf[offset:offset+pktLen]) diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/version.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/version.go similarity index 89% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/version.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/version.go index c4d94ac3a..3943c1504 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/pkg/protocol/version.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/pkg/protocol/version.go @@ -4,7 +4,7 @@ // Package protocol provides the DTLS wire format package protocol -// Version enums +// Version enums. var ( Version1_0 = Version{Major: 0xfe, Minor: 0xff} //nolint:gochecknoglobals Version1_2 = Version{Major: 0xfe, Minor: 0xfd} //nolint:gochecknoglobals @@ -18,7 +18,7 @@ type Version struct { Major, Minor uint8 } -// Equal determines if two protocol versions are equal +// Equal determines if two protocol versions are equal. func (v Version) Equal(x Version) bool { return v.Major == x.Major && v.Minor == x.Minor } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/renovate.json b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/renovate.json similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/renovate.json rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/renovate.json diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/resume.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/resume.go similarity index 53% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/resume.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/resume.go index c470d856b..954907dd0 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/resume.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/resume.go @@ -4,19 +4,14 @@ package dtls import ( - "context" "net" ) -// Resume imports an already established dtls connection using a specific dtls state -func Resume(state *State, conn net.Conn, config *Config) (*Conn, error) { +// Resume imports an already established dtls connection using a specific dtls state. +func Resume(state *State, conn net.PacketConn, rAddr net.Addr, config *Config) (*Conn, error) { if err := state.initCipherSuite(); err != nil { return nil, err } - c, err := createConn(context.Background(), conn, config, state.isClient, state) - if err != nil { - return nil, err - } - return c, nil + return createConn(conn, rAddr, config, state.isClient, state) } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/session.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/session.go similarity index 92% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/session.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/session.go index 99bf5a499..912a5997a 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/session.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/session.go @@ -3,7 +3,7 @@ package dtls -// Session store data needed in resumption +// Session store data needed in resumption. type Session struct { // ID store session id ID []byte diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/srtp_protection_profile.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/srtp_protection_profile.go similarity index 60% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/srtp_protection_profile.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/srtp_protection_profile.go index e306e9e6a..bc242095b 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/srtp_protection_profile.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/srtp_protection_profile.go @@ -3,7 +3,7 @@ package dtls -import "github.com/pion/dtls/v2/pkg/protocol/extension" +import "github.com/pion/dtls/v3/pkg/protocol/extension" // SRTPProtectionProfile defines the parameters and options that are in effect for the SRTP processing // https://tools.ietf.org/html/rfc5764#section-4.1.2 @@ -12,6 +12,10 @@ type SRTPProtectionProfile = extension.SRTPProtectionProfile const ( SRTP_AES128_CM_HMAC_SHA1_80 SRTPProtectionProfile = extension.SRTP_AES128_CM_HMAC_SHA1_80 // nolint:revive,stylecheck SRTP_AES128_CM_HMAC_SHA1_32 SRTPProtectionProfile = extension.SRTP_AES128_CM_HMAC_SHA1_32 // nolint:revive,stylecheck + SRTP_AES256_CM_SHA1_80 SRTPProtectionProfile = extension.SRTP_AES256_CM_SHA1_80 // nolint:revive,stylecheck + SRTP_AES256_CM_SHA1_32 SRTPProtectionProfile = extension.SRTP_AES256_CM_SHA1_32 // nolint:revive,stylecheck + SRTP_NULL_HMAC_SHA1_80 SRTPProtectionProfile = extension.SRTP_NULL_HMAC_SHA1_80 // nolint:revive,stylecheck + SRTP_NULL_HMAC_SHA1_32 SRTPProtectionProfile = extension.SRTP_NULL_HMAC_SHA1_32 // nolint:revive,stylecheck SRTP_AEAD_AES_128_GCM SRTPProtectionProfile = extension.SRTP_AEAD_AES_128_GCM // nolint:revive,stylecheck SRTP_AEAD_AES_256_GCM SRTPProtectionProfile = extension.SRTP_AEAD_AES_256_GCM // nolint:revive,stylecheck ) diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/state.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/state.go similarity index 61% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/state.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/state.go index e9f86a80b..364f7dcc1 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/state.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/state.go @@ -6,26 +6,46 @@ package dtls import ( "bytes" "encoding/gob" + "errors" "sync/atomic" - "github.com/pion/dtls/v2/pkg/crypto/elliptic" - "github.com/pion/dtls/v2/pkg/crypto/prf" - "github.com/pion/dtls/v2/pkg/protocol/handshake" - "github.com/pion/transport/v2/replaydetector" + "github.com/pion/dtls/v3/pkg/crypto/elliptic" + "github.com/pion/dtls/v3/pkg/crypto/prf" + "github.com/pion/dtls/v3/pkg/crypto/signaturehash" + "github.com/pion/dtls/v3/pkg/protocol/handshake" + "github.com/pion/transport/v3/replaydetector" ) -// State holds the dtls connection state and implements both encoding.BinaryMarshaler and encoding.BinaryUnmarshaler +// State holds the dtls connection state and implements both encoding.BinaryMarshaler and +// encoding.BinaryUnmarshaler. type State struct { localEpoch, remoteEpoch atomic.Value localSequenceNumber []uint64 // uint48 localRandom, remoteRandom handshake.Random masterSecret []byte cipherSuite CipherSuite // nil if a cipherSuite hasn't been chosen + CipherSuiteID CipherSuiteID - srtpProtectionProfile SRTPProtectionProfile // Negotiated SRTPProtectionProfile - PeerCertificates [][]byte - IdentityHint []byte - SessionID []byte + srtpProtectionProfile atomic.Value // Negotiated SRTPProtectionProfile + remoteSRTPMasterKeyIdentifier []byte + + PeerCertificates [][]byte + IdentityHint []byte + SessionID []byte + + // Connection Identifiers must be negotiated afresh on session resumption. + // https://datatracker.ietf.org/doc/html/rfc9146#name-the-connection_id-extension + + // localConnectionID is the locally generated connection ID that is expected + // to be received from the remote endpoint. + // For a server, this is the connection ID sent in ServerHello. + // For a client, this is the connection ID sent in the ClientHello. + localConnectionID atomic.Value + // remoteConnectionID is the connection ID that the remote endpoint + // specifies should be sent. + // For a server, this is the connection ID received in the ClientHello. + // For a client, this is the connection ID received in the ServerHello. + remoteConnectionID []byte isClient bool @@ -38,6 +58,7 @@ type State struct { handshakeSendSequence int handshakeRecvSequence int serverName string + remoteCertRequestAlgs []signaturehash.Algorithm remoteRequestedCertificate bool // Did we get a CertificateRequest localCertificatesVerify []byte // cache CertificateVerify localVerifyData []byte // cached VerifyData @@ -62,37 +83,54 @@ type serializedState struct { PeerCertificates [][]byte IdentityHint []byte SessionID []byte + LocalConnectionID []byte + RemoteConnectionID []byte IsClient bool + NegotiatedProtocol string } -func (s *State) clone() *State { - serialized := s.serialize() +var errCipherSuiteNotSet = &InternalError{Err: errors.New("cipher suite not set")} //nolint:goerr113 + +func (s *State) clone() (*State, error) { + serialized, err := s.serialize() + if err != nil { + return nil, err + } state := &State{} state.deserialize(*serialized) - return state + return state, err } -func (s *State) serialize() *serializedState { +func (s *State) serialize() (*serializedState, error) { + if s.cipherSuite == nil { + return nil, errCipherSuiteNotSet + } + cipherSuiteID := uint16(s.cipherSuite.ID()) + // Marshal random values localRnd := s.localRandom.MarshalFixed() remoteRnd := s.remoteRandom.MarshalFixed() epoch := s.getLocalEpoch() + return &serializedState{ LocalEpoch: s.getLocalEpoch(), RemoteEpoch: s.getRemoteEpoch(), - CipherSuiteID: uint16(s.cipherSuite.ID()), + CipherSuiteID: cipherSuiteID, MasterSecret: s.masterSecret, SequenceNumber: atomic.LoadUint64(&s.localSequenceNumber[epoch]), LocalRandom: localRnd, RemoteRandom: remoteRnd, - SRTPProtectionProfile: uint16(s.srtpProtectionProfile), + SRTPProtectionProfile: uint16(s.getSRTPProtectionProfile()), PeerCertificates: s.PeerCertificates, IdentityHint: s.IdentityHint, SessionID: s.SessionID, + LocalConnectionID: s.getLocalConnectionID(), + RemoteConnectionID: s.remoteConnectionID, IsClient: s.isClient, - } + NegotiatedProtocol: s.NegotiatedProtocol, + }, nil } func (s *State) deserialize(serialized serializedState) { @@ -120,15 +158,24 @@ func (s *State) deserialize(serialized serializedState) { s.masterSecret = serialized.MasterSecret // Set cipher suite - s.cipherSuite = cipherSuiteForID(CipherSuiteID(serialized.CipherSuiteID), nil) + s.CipherSuiteID = CipherSuiteID(serialized.CipherSuiteID) + s.cipherSuite = cipherSuiteForID(s.CipherSuiteID, nil) atomic.StoreUint64(&s.localSequenceNumber[epoch], serialized.SequenceNumber) - s.srtpProtectionProfile = SRTPProtectionProfile(serialized.SRTPProtectionProfile) + s.setSRTPProtectionProfile(SRTPProtectionProfile(serialized.SRTPProtectionProfile)) // Set remote certificate s.PeerCertificates = serialized.PeerCertificates + s.IdentityHint = serialized.IdentityHint + + // Set local and remote connection IDs + s.setLocalConnectionID(serialized.LocalConnectionID) + s.remoteConnectionID = serialized.RemoteConnectionID + s.SessionID = serialized.SessionID + + s.NegotiatedProtocol = serialized.NegotiatedProtocol } func (s *State) initCipherSuite() error { @@ -148,22 +195,27 @@ func (s *State) initCipherSuite() error { if err != nil { return err } + return nil } -// MarshalBinary is a binary.BinaryMarshaler.MarshalBinary implementation +// MarshalBinary is a binary.BinaryMarshaler.MarshalBinary implementation. func (s *State) MarshalBinary() ([]byte, error) { - serialized := s.serialize() + serialized, err := s.serialize() + if err != nil { + return nil, err + } var buf bytes.Buffer enc := gob.NewEncoder(&buf) if err := enc.Encode(*serialized); err != nil { return nil, err } + return buf.Bytes(), nil } -// UnmarshalBinary is a binary.BinaryUnmarshaler.UnmarshalBinary implementation +// UnmarshalBinary is a binary.BinaryUnmarshaler.UnmarshalBinary implementation. func (s *State) UnmarshalBinary(data []byte) error { enc := gob.NewDecoder(bytes.NewBuffer(data)) var serialized serializedState @@ -179,7 +231,7 @@ func (s *State) UnmarshalBinary(data []byte) error { // ExportKeyingMaterial returns length bytes of exported key material in a new // slice as defined in RFC 5705. // This allows protocols to use DTLS for key establishment, but -// then use some of the keying material for their own purposes +// then use some of the keying material for their own purposes. func (s *State) ExportKeyingMaterial(label string, context []byte, length int) ([]byte, error) { if s.getLocalEpoch() == 0 { return nil, errHandshakeInProgress @@ -198,6 +250,7 @@ func (s *State) ExportKeyingMaterial(label string, context []byte, length int) ( } else { seed = append(append(seed, remoteRandom[:]...), localRandom[:]...) } + return prf.PHash(s.masterSecret, seed, length, s.cipherSuite.HashFunc()) } @@ -205,6 +258,7 @@ func (s *State) getRemoteEpoch() uint16 { if remoteEpoch, ok := s.remoteEpoch.Load().(uint16); ok { return remoteEpoch } + return 0 } @@ -212,5 +266,35 @@ func (s *State) getLocalEpoch() uint16 { if localEpoch, ok := s.localEpoch.Load().(uint16); ok { return localEpoch } + return 0 } + +func (s *State) setSRTPProtectionProfile(profile SRTPProtectionProfile) { + s.srtpProtectionProfile.Store(profile) +} + +func (s *State) getSRTPProtectionProfile() SRTPProtectionProfile { + if val, ok := s.srtpProtectionProfile.Load().(SRTPProtectionProfile); ok { + return val + } + + return 0 +} + +func (s *State) getLocalConnectionID() []byte { + if val, ok := s.localConnectionID.Load().([]byte); ok { + return val + } + + return nil +} + +func (s *State) setLocalConnectionID(v []byte) { + s.localConnectionID.Store(v) +} + +// RemoteRandomBytes returns the remote client hello random bytes. +func (s *State) RemoteRandomBytes() [handshake.RandomBytesLength]byte { + return s.remoteRandom.RandomBytes +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/util.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/util.go similarity index 99% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/util.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/util.go index 663c4437c..3d9b0bc85 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/util.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v3/util.go @@ -11,6 +11,7 @@ func findMatchingSRTPProfile(a, b []SRTPProtectionProfile) (SRTPProtectionProfil } } } + return 0, false } @@ -22,6 +23,7 @@ func findMatchingCipherSuite(a, b []CipherSuite) (CipherSuite, bool) { } } } + return nil, false } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/AUTHORS.txt b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/AUTHORS.txt deleted file mode 100644 index 57eb69378..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/AUTHORS.txt +++ /dev/null @@ -1,65 +0,0 @@ -# Thank you to everyone that made Pion possible. If you are interested in contributing -# we would love to have you https://github.com/pion/webrtc/wiki/Contributing -# -# This file is auto generated, using git to list all individuals contributors. -# see https://github.com/pion/.goassets/blob/master/scripts/generate-authors.sh for the scripting -Aaron France -Adam Kiss -adwpc -Aleksandr Razumov -aler9 <46489434+aler9@users.noreply.github.com> -Antoine Baché -Artur Shellunts -Assad Obaid -Atsushi Watanabe -backkem -buptczq -cgojin -Chao Yuan -cnderrauber -David Hamilton -David Zhao -David Zhao -Eric Daniels -Genteure -Henry -hexiang -hn8 <10730886+hn8@users.noreply.github.com> -Hugo Arregui -Hugo Arregui -Jason Maldonis -Jerko Steiner -JooYoung -Juliusz Chroboczek -Kacper Bąk <56700396+53jk1@users.noreply.github.com> -Kevin Caffrey -Konstantin Itskov -korymiller1489 -Kyle Carberry -Lander Noterman -Luke Curley -Meelap Shah -Michael MacDonald -Michael MacDonald -Mikhail Bragin -Miroslav Šedivý -Nevio Vesic -Ori Bernstein -Rasmus Hanning -Robert Eperjesi -Sam Lancia -Sam Lancia -San9H0 -Sean DuBois -Sean DuBois -Sebastian Waisbrot -Sidney San Martín -Steffen Vogel -Will Forcey -Woodrow Douglass -Yutaka Takeda -ZHENK -Zizheng Tai - -# List of contributors not appearing in Git history - diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/addr.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/addr.go deleted file mode 100644 index 1d70025be..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/addr.go +++ /dev/null @@ -1,71 +0,0 @@ -// SPDX-FileCopyrightText: 2023 The Pion community -// SPDX-License-Identifier: MIT - -package ice - -import ( - "net" -) - -func parseMulticastAnswerAddr(in net.Addr) (net.IP, bool) { - switch addr := in.(type) { - case *net.IPAddr: - return addr.IP, true - case *net.UDPAddr: - return addr.IP, true - case *net.TCPAddr: - return addr.IP, true - } - return nil, false -} - -func parseAddr(in net.Addr) (net.IP, int, NetworkType, bool) { - switch addr := in.(type) { - case *net.UDPAddr: - return addr.IP, addr.Port, NetworkTypeUDP4, true - case *net.TCPAddr: - return addr.IP, addr.Port, NetworkTypeTCP4, true - } - return nil, 0, 0, false -} - -func createAddr(network NetworkType, ip net.IP, port int) net.Addr { - switch { - case network.IsTCP(): - return &net.TCPAddr{IP: ip, Port: port} - default: - return &net.UDPAddr{IP: ip, Port: port} - } -} - -func addrEqual(a, b net.Addr) bool { - aIP, aPort, aType, aOk := parseAddr(a) - if !aOk { - return false - } - - bIP, bPort, bType, bOk := parseAddr(b) - if !bOk { - return false - } - - return aType == bType && aIP.Equal(bIP) && aPort == bPort -} - -// AddrPort is an IP and a port number. -type AddrPort [18]byte - -func toAddrPort(addr net.Addr) AddrPort { - var ap AddrPort - switch addr := addr.(type) { - case *net.UDPAddr: - copy(ap[:16], addr.IP.To16()) - ap[16] = uint8(addr.Port >> 8) - ap[17] = uint8(addr.Port) - case *net.TCPAddr: - copy(ap[:16], addr.IP.To16()) - ap[16] = uint8(addr.Port >> 8) - ap[17] = uint8(addr.Port) - } - return ap -} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/agent_handlers.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/agent_handlers.go deleted file mode 100644 index c5a5ec03b..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/agent_handlers.go +++ /dev/null @@ -1,60 +0,0 @@ -// SPDX-FileCopyrightText: 2023 The Pion community -// SPDX-License-Identifier: MIT - -package ice - -// OnConnectionStateChange sets a handler that is fired when the connection state changes -func (a *Agent) OnConnectionStateChange(f func(ConnectionState)) error { - a.onConnectionStateChangeHdlr.Store(f) - return nil -} - -// OnSelectedCandidatePairChange sets a handler that is fired when the final candidate -// pair is selected -func (a *Agent) OnSelectedCandidatePairChange(f func(Candidate, Candidate)) error { - a.onSelectedCandidatePairChangeHdlr.Store(f) - return nil -} - -// OnCandidate sets a handler that is fired when new candidates gathered. When -// the gathering process complete the last candidate is nil. -func (a *Agent) OnCandidate(f func(Candidate)) error { - a.onCandidateHdlr.Store(f) - return nil -} - -func (a *Agent) onSelectedCandidatePairChange(p *CandidatePair) { - if h, ok := a.onSelectedCandidatePairChangeHdlr.Load().(func(Candidate, Candidate)); ok { - h(p.Local, p.Remote) - } -} - -func (a *Agent) onCandidate(c Candidate) { - if onCandidateHdlr, ok := a.onCandidateHdlr.Load().(func(Candidate)); ok { - onCandidateHdlr(c) - } -} - -func (a *Agent) onConnectionStateChange(s ConnectionState) { - if hdlr, ok := a.onConnectionStateChangeHdlr.Load().(func(ConnectionState)); ok { - hdlr(s) - } -} - -func (a *Agent) candidatePairRoutine() { - for p := range a.chanCandidatePair { - a.onSelectedCandidatePairChange(p) - } -} - -func (a *Agent) connectionStateRoutine() { - for s := range a.chanState { - go a.onConnectionStateChange(s) - } -} - -func (a *Agent) candidateRoutine() { - for c := range a.chanCandidate { - a.onCandidate(c) - } -} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/agent_stats.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/agent_stats.go deleted file mode 100644 index b9ad7187e..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/agent_stats.go +++ /dev/null @@ -1,122 +0,0 @@ -// SPDX-FileCopyrightText: 2023 The Pion community -// SPDX-License-Identifier: MIT - -package ice - -import ( - "context" - "time" -) - -// GetCandidatePairsStats returns a list of candidate pair stats -func (a *Agent) GetCandidatePairsStats() []CandidatePairStats { - var res []CandidatePairStats - err := a.run(a.context(), func(ctx context.Context, agent *Agent) { - result := make([]CandidatePairStats, 0, len(agent.checklist)) - for _, cp := range agent.checklist { - stat := CandidatePairStats{ - Timestamp: time.Now(), - LocalCandidateID: cp.Local.ID(), - RemoteCandidateID: cp.Remote.ID(), - State: cp.state, - Nominated: cp.nominated, - // PacketsSent uint32 - // PacketsReceived uint32 - // BytesSent uint64 - // BytesReceived uint64 - // LastPacketSentTimestamp time.Time - // LastPacketReceivedTimestamp time.Time - // FirstRequestTimestamp time.Time - // LastRequestTimestamp time.Time - // LastResponseTimestamp time.Time - // TotalRoundTripTime float64 - // CurrentRoundTripTime float64 - // AvailableOutgoingBitrate float64 - // AvailableIncomingBitrate float64 - // CircuitBreakerTriggerCount uint32 - // RequestsReceived uint64 - // RequestsSent uint64 - // ResponsesReceived uint64 - // ResponsesSent uint64 - // RetransmissionsReceived uint64 - // RetransmissionsSent uint64 - // ConsentRequestsSent uint64 - // ConsentExpiredTimestamp time.Time - } - result = append(result, stat) - } - res = result - }) - if err != nil { - a.log.Errorf("Failed to get candidate pairs stats: %v", err) - return []CandidatePairStats{} - } - return res -} - -// GetLocalCandidatesStats returns a list of local candidates stats -func (a *Agent) GetLocalCandidatesStats() []CandidateStats { - var res []CandidateStats - err := a.run(a.context(), func(ctx context.Context, agent *Agent) { - result := make([]CandidateStats, 0, len(agent.localCandidates)) - for networkType, localCandidates := range agent.localCandidates { - for _, c := range localCandidates { - relayProtocol := "" - if c.Type() == CandidateTypeRelay { - if cRelay, ok := c.(*CandidateRelay); ok { - relayProtocol = cRelay.RelayProtocol() - } - } - stat := CandidateStats{ - Timestamp: time.Now(), - ID: c.ID(), - NetworkType: networkType, - IP: c.Address(), - Port: c.Port(), - CandidateType: c.Type(), - Priority: c.Priority(), - // URL string - RelayProtocol: relayProtocol, - // Deleted bool - } - result = append(result, stat) - } - } - res = result - }) - if err != nil { - a.log.Errorf("Failed to get candidate pair stats: %v", err) - return []CandidateStats{} - } - return res -} - -// GetRemoteCandidatesStats returns a list of remote candidates stats -func (a *Agent) GetRemoteCandidatesStats() []CandidateStats { - var res []CandidateStats - err := a.run(a.context(), func(ctx context.Context, agent *Agent) { - result := make([]CandidateStats, 0, len(agent.remoteCandidates)) - for networkType, remoteCandidates := range agent.remoteCandidates { - for _, c := range remoteCandidates { - stat := CandidateStats{ - Timestamp: time.Now(), - ID: c.ID(), - NetworkType: networkType, - IP: c.Address(), - Port: c.Port(), - CandidateType: c.Type(), - Priority: c.Priority(), - // URL string - RelayProtocol: "", - } - result = append(result, stat) - } - } - res = result - }) - if err != nil { - a.log.Errorf("Failed to get candidate pair stats: %v", err) - return []CandidateStats{} - } - return res -} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/candidate_base.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/candidate_base.go deleted file mode 100644 index 8e551d8f2..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/candidate_base.go +++ /dev/null @@ -1,543 +0,0 @@ -// SPDX-FileCopyrightText: 2023 The Pion community -// SPDX-License-Identifier: MIT - -package ice - -import ( - "context" - "errors" - "fmt" - "hash/crc32" - "io" - "net" - "strconv" - "strings" - "sync/atomic" - "time" - - "github.com/pion/stun" -) - -type candidateBase struct { - id string - networkType NetworkType - candidateType CandidateType - - component uint16 - address string - port int - relatedAddress *CandidateRelatedAddress - tcpType TCPType - - resolvedAddr net.Addr - - lastSent atomic.Value - lastReceived atomic.Value - conn net.PacketConn - - currAgent *Agent - closeCh chan struct{} - closedCh chan struct{} - - foundationOverride string - priorityOverride uint32 - - remoteCandidateCaches map[AddrPort]Candidate -} - -// Done implements context.Context -func (c *candidateBase) Done() <-chan struct{} { - return c.closeCh -} - -// Err implements context.Context -func (c *candidateBase) Err() error { - select { - case <-c.closedCh: - return ErrRunCanceled - default: - return nil - } -} - -// Deadline implements context.Context -func (c *candidateBase) Deadline() (deadline time.Time, ok bool) { - return time.Time{}, false -} - -// Value implements context.Context -func (c *candidateBase) Value(interface{}) interface{} { - return nil -} - -// ID returns Candidate ID -func (c *candidateBase) ID() string { - return c.id -} - -func (c *candidateBase) Foundation() string { - if c.foundationOverride != "" { - return c.foundationOverride - } - - return fmt.Sprintf("%d", crc32.ChecksumIEEE([]byte(c.Type().String()+c.address+c.networkType.String()))) -} - -// Address returns Candidate Address -func (c *candidateBase) Address() string { - return c.address -} - -// Port returns Candidate Port -func (c *candidateBase) Port() int { - return c.port -} - -// Type returns candidate type -func (c *candidateBase) Type() CandidateType { - return c.candidateType -} - -// NetworkType returns candidate NetworkType -func (c *candidateBase) NetworkType() NetworkType { - return c.networkType -} - -// Component returns candidate component -func (c *candidateBase) Component() uint16 { - return c.component -} - -func (c *candidateBase) SetComponent(component uint16) { - c.component = component -} - -// LocalPreference returns the local preference for this candidate -func (c *candidateBase) LocalPreference() uint16 { - if c.NetworkType().IsTCP() { - // RFC 6544, section 4.2 - // - // In Section 4.1.2.1 of [RFC5245], a recommended formula for UDP ICE - // candidate prioritization is defined. For TCP candidates, the same - // formula and candidate type preferences SHOULD be used, and the - // RECOMMENDED type preferences for the new candidate types defined in - // this document (see Section 5) are 105 for NAT-assisted candidates and - // 75 for UDP-tunneled candidates. - // - // (...) - // - // With TCP candidates, the local preference part of the recommended - // priority formula is updated to also include the directionality - // (active, passive, or simultaneous-open) of the TCP connection. The - // RECOMMENDED local preference is then defined as: - // - // local preference = (2^13) * direction-pref + other-pref - // - // The direction-pref MUST be between 0 and 7 (both inclusive), with 7 - // being the most preferred. The other-pref MUST be between 0 and 8191 - // (both inclusive), with 8191 being the most preferred. It is - // RECOMMENDED that the host, UDP-tunneled, and relayed TCP candidates - // have the direction-pref assigned as follows: 6 for active, 4 for - // passive, and 2 for S-O. For the NAT-assisted and server reflexive - // candidates, the RECOMMENDED values are: 6 for S-O, 4 for active, and - // 2 for passive. - // - // (...) - // - // If any two candidates have the same type-preference and direction- - // pref, they MUST have a unique other-pref. With this specification, - // this usually only happens with multi-homed hosts, in which case - // other-pref is the preference for the particular IP address from which - // the candidate was obtained. When there is only a single IP address, - // this value SHOULD be set to the maximum allowed value (8191). - var otherPref uint16 = 8191 - - directionPref := func() uint16 { - switch c.Type() { - case CandidateTypeHost, CandidateTypeRelay: - switch c.tcpType { - case TCPTypeActive: - return 6 - case TCPTypePassive: - return 4 - case TCPTypeSimultaneousOpen: - return 2 - case TCPTypeUnspecified: - return 0 - } - case CandidateTypePeerReflexive, CandidateTypeServerReflexive: - switch c.tcpType { - case TCPTypeSimultaneousOpen: - return 6 - case TCPTypeActive: - return 4 - case TCPTypePassive: - return 2 - case TCPTypeUnspecified: - return 0 - } - case CandidateTypeUnspecified: - return 0 - } - return 0 - }() - - return (1<<13)*directionPref + otherPref - } - - return defaultLocalPreference -} - -// RelatedAddress returns *CandidateRelatedAddress -func (c *candidateBase) RelatedAddress() *CandidateRelatedAddress { - return c.relatedAddress -} - -func (c *candidateBase) TCPType() TCPType { - return c.tcpType -} - -// start runs the candidate using the provided connection -func (c *candidateBase) start(a *Agent, conn net.PacketConn, initializedCh <-chan struct{}) { - if c.conn != nil { - c.agent().log.Warn("Can't start already started candidateBase") - return - } - c.currAgent = a - c.conn = conn - c.closeCh = make(chan struct{}) - c.closedCh = make(chan struct{}) - - go c.recvLoop(initializedCh) -} - -func (c *candidateBase) recvLoop(initializedCh <-chan struct{}) { - a := c.agent() - - defer close(c.closedCh) - - select { - case <-initializedCh: - case <-c.closeCh: - return - } - - buf := make([]byte, receiveMTU) - for { - n, srcAddr, err := c.conn.ReadFrom(buf) - if err != nil { - if !(errors.Is(err, io.EOF) || errors.Is(err, net.ErrClosed)) { - a.log.Warnf("Failed to read from candidate %s: %v", c, err) - } - return - } - - c.handleInboundPacket(buf[:n], srcAddr) - } -} - -func (c *candidateBase) validateSTUNTrafficCache(addr net.Addr) bool { - if candidate, ok := c.remoteCandidateCaches[toAddrPort(addr)]; ok { - candidate.seen(false) - return true - } - return false -} - -func (c *candidateBase) addRemoteCandidateCache(candidate Candidate, srcAddr net.Addr) { - if c.validateSTUNTrafficCache(srcAddr) { - return - } - c.remoteCandidateCaches[toAddrPort(srcAddr)] = candidate -} - -func (c *candidateBase) handleInboundPacket(buf []byte, srcAddr net.Addr) { - a := c.agent() - - if stun.IsMessage(buf) { - m := &stun.Message{ - Raw: make([]byte, len(buf)), - } - - // Explicitly copy raw buffer so Message can own the memory. - copy(m.Raw, buf) - - if err := m.Decode(); err != nil { - a.log.Warnf("Failed to handle decode ICE from %s to %s: %v", c.addr(), srcAddr, err) - return - } - - if err := a.run(c, func(ctx context.Context, a *Agent) { - a.handleInbound(m, c, srcAddr) - }); err != nil { - a.log.Warnf("Failed to handle message: %v", err) - } - - return - } - - if !c.validateSTUNTrafficCache(srcAddr) { - remoteCandidate, valid := a.validateNonSTUNTraffic(c, srcAddr) //nolint:contextcheck - if !valid { - a.log.Warnf("Discarded message from %s, not a valid remote candidate", c.addr()) - return - } - c.addRemoteCandidateCache(remoteCandidate, srcAddr) - } - - // Note: This will return packetio.ErrFull if the buffer ever manages to fill up. - if _, err := a.buf.Write(buf); err != nil { - a.log.Warnf("Failed to write packet: %s", err) - return - } -} - -// close stops the recvLoop -func (c *candidateBase) close() error { - // If conn has never been started will be nil - if c.Done() == nil { - return nil - } - - // Assert that conn has not already been closed - select { - case <-c.Done(): - return nil - default: - } - - var firstErr error - - // Unblock recvLoop - close(c.closeCh) - if err := c.conn.SetDeadline(time.Now()); err != nil { - firstErr = err - } - - // Close the conn - if err := c.conn.Close(); err != nil && firstErr == nil { - firstErr = err - } - - if firstErr != nil { - return firstErr - } - - // Wait until the recvLoop is closed - <-c.closedCh - - return nil -} - -func (c *candidateBase) writeTo(raw []byte, dst Candidate) (int, error) { - n, err := c.conn.WriteTo(raw, dst.addr()) - if err != nil { - // If the connection is closed, we should return the error - if errors.Is(err, io.ErrClosedPipe) { - return n, err - } - c.agent().log.Infof("%s: %v", errSendPacket, err) - return n, nil - } - c.seen(true) - return n, nil -} - -// Priority computes the priority for this ICE Candidate -func (c *candidateBase) Priority() uint32 { - if c.priorityOverride != 0 { - return c.priorityOverride - } - - // The local preference MUST be an integer from 0 (lowest preference) to - // 65535 (highest preference) inclusive. When there is only a single IP - // address, this value SHOULD be set to 65535. If there are multiple - // candidates for a particular component for a particular data stream - // that have the same type, the local preference MUST be unique for each - // one. - return (1<<24)*uint32(c.Type().Preference()) + - (1<<8)*uint32(c.LocalPreference()) + - uint32(256-c.Component()) -} - -// Equal is used to compare two candidateBases -func (c *candidateBase) Equal(other Candidate) bool { - return c.NetworkType() == other.NetworkType() && - c.Type() == other.Type() && - c.Address() == other.Address() && - c.Port() == other.Port() && - c.TCPType() == other.TCPType() && - c.RelatedAddress().Equal(other.RelatedAddress()) -} - -// String makes the candidateBase printable -func (c *candidateBase) String() string { - return fmt.Sprintf("%s %s %s%s", c.NetworkType(), c.Type(), net.JoinHostPort(c.Address(), strconv.Itoa(c.Port())), c.relatedAddress) -} - -// LastReceived returns a time.Time indicating the last time -// this candidate was received -func (c *candidateBase) LastReceived() time.Time { - if lastReceived, ok := c.lastReceived.Load().(time.Time); ok { - return lastReceived - } - return time.Time{} -} - -func (c *candidateBase) setLastReceived(t time.Time) { - c.lastReceived.Store(t) -} - -// LastSent returns a time.Time indicating the last time -// this candidate was sent -func (c *candidateBase) LastSent() time.Time { - if lastSent, ok := c.lastSent.Load().(time.Time); ok { - return lastSent - } - return time.Time{} -} - -func (c *candidateBase) setLastSent(t time.Time) { - c.lastSent.Store(t) -} - -func (c *candidateBase) seen(outbound bool) { - if outbound { - c.setLastSent(time.Now()) - } else { - c.setLastReceived(time.Now()) - } -} - -func (c *candidateBase) addr() net.Addr { - return c.resolvedAddr -} - -func (c *candidateBase) agent() *Agent { - return c.currAgent -} - -func (c *candidateBase) context() context.Context { - return c -} - -func (c *candidateBase) copy() (Candidate, error) { - return UnmarshalCandidate(c.Marshal()) -} - -// Marshal returns the string representation of the ICECandidate -func (c *candidateBase) Marshal() string { - val := c.Foundation() - if val == " " { - val = "" - } - - val = fmt.Sprintf("%s %d %s %d %s %d typ %s", - val, - c.Component(), - c.NetworkType().NetworkShort(), - c.Priority(), - c.Address(), - c.Port(), - c.Type()) - - if c.tcpType != TCPTypeUnspecified { - val += fmt.Sprintf(" tcptype %s", c.tcpType.String()) - } - - if r := c.RelatedAddress(); r != nil && r.Address != "" && r.Port != 0 { - val = fmt.Sprintf("%s raddr %s rport %d", - val, - r.Address, - r.Port) - } - - return val -} - -// UnmarshalCandidate creates a Candidate from its string representation -func UnmarshalCandidate(raw string) (Candidate, error) { - split := strings.Fields(raw) - // Foundation not specified: not RFC 8445 compliant but seen in the wild - if len(raw) != 0 && raw[0] == ' ' { - split = append([]string{" "}, split...) - } - if len(split) < 8 { - return nil, fmt.Errorf("%w (%d)", errAttributeTooShortICECandidate, len(split)) - } - - // Foundation - foundation := split[0] - - // Component - rawComponent, err := strconv.ParseUint(split[1], 10, 16) - if err != nil { - return nil, fmt.Errorf("%w: %v", errParseComponent, err) //nolint:errorlint - } - component := uint16(rawComponent) - - // Protocol - protocol := split[2] - - // Priority - priorityRaw, err := strconv.ParseUint(split[3], 10, 32) - if err != nil { - return nil, fmt.Errorf("%w: %v", errParsePriority, err) //nolint:errorlint - } - priority := uint32(priorityRaw) - - // Address - address := split[4] - - // Port - rawPort, err := strconv.ParseUint(split[5], 10, 16) - if err != nil { - return nil, fmt.Errorf("%w: %v", errParsePort, err) //nolint:errorlint - } - port := int(rawPort) - typ := split[7] - - relatedAddress := "" - relatedPort := 0 - tcpType := TCPTypeUnspecified - - if len(split) > 8 { - split = split[8:] - - if split[0] == "raddr" { - if len(split) < 4 { - return nil, fmt.Errorf("%w: incorrect length", errParseRelatedAddr) - } - - // RelatedAddress - relatedAddress = split[1] - - // RelatedPort - rawRelatedPort, parseErr := strconv.ParseUint(split[3], 10, 16) - if parseErr != nil { - return nil, fmt.Errorf("%w: %v", errParsePort, parseErr) //nolint:errorlint - } - relatedPort = int(rawRelatedPort) - } else if split[0] == "tcptype" { - if len(split) < 2 { - return nil, fmt.Errorf("%w: incorrect length", errParseTCPType) - } - - tcpType = NewTCPType(split[1]) - } - } - - switch typ { - case "host": - return NewCandidateHost(&CandidateHostConfig{"", protocol, address, port, component, priority, foundation, tcpType}) - case "srflx": - return NewCandidateServerReflexive(&CandidateServerReflexiveConfig{"", protocol, address, port, component, priority, foundation, relatedAddress, relatedPort}) - case "prflx": - return NewCandidatePeerReflexive(&CandidatePeerReflexiveConfig{"", protocol, address, port, component, priority, foundation, relatedAddress, relatedPort}) - case "relay": - return NewCandidateRelay(&CandidateRelayConfig{"", protocol, address, port, component, priority, foundation, relatedAddress, relatedPort, "", nil}) - default: - } - - return nil, fmt.Errorf("%w (%s)", ErrUnknownCandidateTyp, typ) -} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/candidatepair.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/candidatepair.go deleted file mode 100644 index f33be539c..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/candidatepair.go +++ /dev/null @@ -1,102 +0,0 @@ -// SPDX-FileCopyrightText: 2023 The Pion community -// SPDX-License-Identifier: MIT - -package ice - -import ( - "fmt" - - "github.com/pion/stun" -) - -func newCandidatePair(local, remote Candidate, controlling bool) *CandidatePair { - return &CandidatePair{ - iceRoleControlling: controlling, - Remote: remote, - Local: local, - state: CandidatePairStateWaiting, - } -} - -// CandidatePair is a combination of a -// local and remote candidate -type CandidatePair struct { - iceRoleControlling bool - Remote Candidate - Local Candidate - bindingRequestCount uint16 - state CandidatePairState - nominated bool - nominateOnBindingSuccess bool -} - -func (p *CandidatePair) String() string { - if p == nil { - return "" - } - - return fmt.Sprintf("prio %d (local, prio %d) %s <-> %s (remote, prio %d)", - p.priority(), p.Local.Priority(), p.Local, p.Remote, p.Remote.Priority()) -} - -func (p *CandidatePair) equal(other *CandidatePair) bool { - if p == nil && other == nil { - return true - } - if p == nil || other == nil { - return false - } - return p.Local.Equal(other.Local) && p.Remote.Equal(other.Remote) -} - -// RFC 5245 - 5.7.2. Computing Pair Priority and Ordering Pairs -// Let G be the priority for the candidate provided by the controlling -// agent. Let D be the priority for the candidate provided by the -// controlled agent. -// pair priority = 2^32*MIN(G,D) + 2*MAX(G,D) + (G>D?1:0) -func (p *CandidatePair) priority() uint64 { - var g, d uint32 - if p.iceRoleControlling { - g = p.Local.Priority() - d = p.Remote.Priority() - } else { - g = p.Remote.Priority() - d = p.Local.Priority() - } - - // Just implement these here rather - // than fooling around with the math package - min := func(x, y uint32) uint64 { - if x < y { - return uint64(x) - } - return uint64(y) - } - max := func(x, y uint32) uint64 { - if x > y { - return uint64(x) - } - return uint64(y) - } - cmp := func(x, y uint32) uint64 { - if x > y { - return uint64(1) - } - return uint64(0) - } - - // 1<<32 overflows uint32; and if both g && d are - // maxUint32, this result would overflow uint64 - return (1<<32-1)*min(g, d) + 2*max(g, d) + cmp(g, d) -} - -func (p *CandidatePair) Write(b []byte) (int, error) { - return p.Local.writeTo(b, p.Remote) -} - -func (a *Agent) sendSTUN(msg *stun.Message, local, remote Candidate) { - _, err := local.writeTo(msg.Raw, remote) - if err != nil { - a.log.Tracef("failed to send STUN message: %s", err) - } -} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/context.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/context.go deleted file mode 100644 index 36454450c..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/context.go +++ /dev/null @@ -1,40 +0,0 @@ -// SPDX-FileCopyrightText: 2023 The Pion community -// SPDX-License-Identifier: MIT - -package ice - -import ( - "context" - "time" -) - -func (a *Agent) context() context.Context { - return agentContext(a.done) -} - -type agentContext chan struct{} - -// Done implements context.Context -func (a agentContext) Done() <-chan struct{} { - return (chan struct{})(a) -} - -// Err implements context.Context -func (a agentContext) Err() error { - select { - case <-(chan struct{})(a): - return ErrRunCanceled - default: - return nil - } -} - -// Deadline implements context.Context -func (a agentContext) Deadline() (deadline time.Time, ok bool) { - return time.Time{}, false -} - -// Value implements context.Context -func (a agentContext) Value(interface{}) interface{} { - return nil -} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/mdns.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/mdns.go deleted file mode 100644 index aa8231648..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/mdns.go +++ /dev/null @@ -1,65 +0,0 @@ -// SPDX-FileCopyrightText: 2023 The Pion community -// SPDX-License-Identifier: MIT - -package ice - -import ( - "github.com/google/uuid" - "github.com/pion/logging" - "github.com/pion/mdns" - "github.com/pion/transport/v2" - "golang.org/x/net/ipv4" -) - -// MulticastDNSMode represents the different Multicast modes ICE can run in -type MulticastDNSMode byte - -// MulticastDNSMode enum -const ( - // MulticastDNSModeDisabled means remote mDNS candidates will be discarded, and local host candidates will use IPs - MulticastDNSModeDisabled MulticastDNSMode = iota + 1 - - // MulticastDNSModeQueryOnly means remote mDNS candidates will be accepted, and local host candidates will use IPs - MulticastDNSModeQueryOnly - - // MulticastDNSModeQueryAndGather means remote mDNS candidates will be accepted, and local host candidates will use mDNS - MulticastDNSModeQueryAndGather -) - -func generateMulticastDNSName() (string, error) { - // https://tools.ietf.org/id/draft-ietf-rtcweb-mdns-ice-candidates-02.html#gathering - // The unique name MUST consist of a version 4 UUID as defined in [RFC4122], followed by “.local”. - u, err := uuid.NewRandom() - return u.String() + ".local", err -} - -func createMulticastDNS(n transport.Net, mDNSMode MulticastDNSMode, mDNSName string, log logging.LeveledLogger) (*mdns.Conn, MulticastDNSMode, error) { - if mDNSMode == MulticastDNSModeDisabled { - return nil, mDNSMode, nil - } - - addr, mdnsErr := n.ResolveUDPAddr("udp4", mdns.DefaultAddress) - if mdnsErr != nil { - return nil, mDNSMode, mdnsErr - } - - l, mdnsErr := n.ListenUDP("udp4", addr) - if mdnsErr != nil { - // If ICE fails to start MulticastDNS server just warn the user and continue - log.Errorf("Failed to enable mDNS, continuing in mDNS disabled mode: (%s)", mdnsErr) - return nil, MulticastDNSModeDisabled, nil - } - - switch mDNSMode { - case MulticastDNSModeQueryOnly: - conn, err := mdns.Server(ipv4.NewPacketConn(l), &mdns.Config{}) - return conn, mDNSMode, err - case MulticastDNSModeQueryAndGather: - conn, err := mdns.Server(ipv4.NewPacketConn(l), &mdns.Config{ - LocalNames: []string{mDNSName}, - }) - return conn, mDNSMode, err - default: - return nil, mDNSMode, nil - } -} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/net.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/net.go deleted file mode 100644 index d716bc19c..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/net.go +++ /dev/null @@ -1,137 +0,0 @@ -// SPDX-FileCopyrightText: 2023 The Pion community -// SPDX-License-Identifier: MIT - -package ice - -import ( - "net" - - "github.com/pion/logging" - "github.com/pion/transport/v2" -) - -// The conditions of invalidation written below are defined in -// https://tools.ietf.org/html/rfc8445#section-5.1.1.1 -func isSupportedIPv6(ip net.IP) bool { - if len(ip) != net.IPv6len || - isZeros(ip[0:12]) || // !(IPv4-compatible IPv6) - ip[0] == 0xfe && ip[1]&0xc0 == 0xc0 || // !(IPv6 site-local unicast) - ip.IsLinkLocalUnicast() || - ip.IsLinkLocalMulticast() { - return false - } - return true -} - -func isZeros(ip net.IP) bool { - for i := 0; i < len(ip); i++ { - if ip[i] != 0 { - return false - } - } - return true -} - -func localInterfaces(n transport.Net, interfaceFilter func(string) bool, ipFilter func(net.IP) bool, networkTypes []NetworkType, includeLoopback bool) ([]net.IP, error) { //nolint:gocognit - ips := []net.IP{} - ifaces, err := n.Interfaces() - if err != nil { - return ips, err - } - - var IPv4Requested, IPv6Requested bool - for _, typ := range networkTypes { - if typ.IsIPv4() { - IPv4Requested = true - } - - if typ.IsIPv6() { - IPv6Requested = true - } - } - - for _, iface := range ifaces { - if iface.Flags&net.FlagUp == 0 { - continue // Interface down - } - if (iface.Flags&net.FlagLoopback != 0) && !includeLoopback { - continue // Loopback interface - } - - if interfaceFilter != nil && !interfaceFilter(iface.Name) { - continue - } - - addrs, err := iface.Addrs() - if err != nil { - continue - } - - for _, addr := range addrs { - var ip net.IP - switch addr := addr.(type) { - case *net.IPNet: - ip = addr.IP - case *net.IPAddr: - ip = addr.IP - } - if ip == nil || (ip.IsLoopback() && !includeLoopback) { - continue - } - - if ipv4 := ip.To4(); ipv4 == nil { - if !IPv6Requested { - continue - } else if !isSupportedIPv6(ip) { - continue - } - } else if !IPv4Requested { - continue - } - - if ipFilter != nil && !ipFilter(ip) { - continue - } - - ips = append(ips, ip) - } - } - return ips, nil -} - -func listenUDPInPortRange(n transport.Net, log logging.LeveledLogger, portMax, portMin int, network string, lAddr *net.UDPAddr) (transport.UDPConn, error) { - if (lAddr.Port != 0) || ((portMin == 0) && (portMax == 0)) { - return n.ListenUDP(network, lAddr) - } - var i, j int - i = portMin - if i == 0 { - i = 1 - } - j = portMax - if j == 0 { - j = 0xFFFF - } - if i > j { - return nil, ErrPort - } - - portStart := globalMathRandomGenerator.Intn(j-i+1) + i - portCurrent := portStart - for { - lAddr = &net.UDPAddr{IP: lAddr.IP, Port: portCurrent} - c, e := n.ListenUDP(network, lAddr) - if e == nil { - return c, e //nolint:nilerr - } - log.Debugf("Failed to listen %s: %v", lAddr.String(), e) - portCurrent++ - if portCurrent > j { - portCurrent = i - } - if portCurrent == portStart { - break - } - } - return nil, ErrPort -} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/test_utils.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/test_utils.go deleted file mode 100644 index 235fda315..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/test_utils.go +++ /dev/null @@ -1,79 +0,0 @@ -// SPDX-FileCopyrightText: 2023 The Pion community -// SPDX-License-Identifier: MIT - -//go:build !js -// +build !js - -package ice - -import ( - "testing" - - "github.com/stretchr/testify/require" -) - -func newHostRemote(t *testing.T) *CandidateHost { - remoteHostConfig := &CandidateHostConfig{ - Network: "udp", - Address: "1.2.3.5", - Port: 12350, - Component: 1, - } - hostRemote, err := NewCandidateHost(remoteHostConfig) - require.NoError(t, err) - return hostRemote -} - -func newPrflxRemote(t *testing.T) *CandidatePeerReflexive { - prflxConfig := &CandidatePeerReflexiveConfig{ - Network: "udp", - Address: "10.10.10.2", - Port: 19217, - Component: 1, - RelAddr: "4.3.2.1", - RelPort: 43211, - } - prflxRemote, err := NewCandidatePeerReflexive(prflxConfig) - require.NoError(t, err) - return prflxRemote -} - -func newSrflxRemote(t *testing.T) *CandidateServerReflexive { - srflxConfig := &CandidateServerReflexiveConfig{ - Network: "udp", - Address: "10.10.10.2", - Port: 19218, - Component: 1, - RelAddr: "4.3.2.1", - RelPort: 43212, - } - srflxRemote, err := NewCandidateServerReflexive(srflxConfig) - require.NoError(t, err) - return srflxRemote -} - -func newRelayRemote(t *testing.T) *CandidateRelay { - relayConfig := &CandidateRelayConfig{ - Network: "udp", - Address: "1.2.3.4", - Port: 12340, - Component: 1, - RelAddr: "4.3.2.1", - RelPort: 43210, - } - relayRemote, err := NewCandidateRelay(relayConfig) - require.NoError(t, err) - return relayRemote -} - -func newHostLocal(t *testing.T) *CandidateHost { - localHostConfig := &CandidateHostConfig{ - Network: "udp", - Address: "192.168.1.1", - Port: 19216, - Component: 1, - } - hostLocal, err := NewCandidateHost(localHostConfig) - require.NoError(t, err) - return hostLocal -} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/udp_muxed_conn.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/udp_muxed_conn.go deleted file mode 100644 index 09e4b3a8e..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/udp_muxed_conn.go +++ /dev/null @@ -1,246 +0,0 @@ -// SPDX-FileCopyrightText: 2023 The Pion community -// SPDX-License-Identifier: MIT - -package ice - -import ( - "encoding/binary" - "io" - "net" - "sync" - "time" - - "github.com/pion/logging" - "github.com/pion/transport/v2/packetio" -) - -type udpMuxedConnParams struct { - Mux *UDPMuxDefault - AddrPool *sync.Pool - Key string - LocalAddr net.Addr - Logger logging.LeveledLogger -} - -// udpMuxedConn represents a logical packet conn for a single remote as identified by ufrag -type udpMuxedConn struct { - params *udpMuxedConnParams - // Remote addresses that we have sent to on this conn - addresses []string - - // Channel holding incoming packets - buf *packetio.Buffer - closedChan chan struct{} - closeOnce sync.Once - mu sync.Mutex -} - -func newUDPMuxedConn(params *udpMuxedConnParams) *udpMuxedConn { - p := &udpMuxedConn{ - params: params, - buf: packetio.NewBuffer(), - closedChan: make(chan struct{}), - } - - return p -} - -func (c *udpMuxedConn) ReadFrom(b []byte) (n int, rAddr net.Addr, err error) { - buf := c.params.AddrPool.Get().(*bufferHolder) //nolint:forcetypeassert - defer c.params.AddrPool.Put(buf) - - // Read address - total, err := c.buf.Read(buf.buf) - if err != nil { - return 0, nil, err - } - - dataLen := int(binary.LittleEndian.Uint16(buf.buf[:2])) - if dataLen > total || dataLen > len(b) { - return 0, nil, io.ErrShortBuffer - } - - // Read data and then address - offset := 2 - copy(b, buf.buf[offset:offset+dataLen]) - offset += dataLen - - // Read address len & decode address - addrLen := int(binary.LittleEndian.Uint16(buf.buf[offset : offset+2])) - offset += 2 - - if rAddr, err = decodeUDPAddr(buf.buf[offset : offset+addrLen]); err != nil { - return 0, nil, err - } - - return dataLen, rAddr, nil -} - -func (c *udpMuxedConn) WriteTo(buf []byte, rAddr net.Addr) (n int, err error) { - if c.isClosed() { - return 0, io.ErrClosedPipe - } - // Each time we write to a new address, we'll register it with the mux - addr := rAddr.String() - if !c.containsAddress(addr) { - c.addAddress(addr) - } - - return c.params.Mux.writeTo(buf, rAddr) -} - -func (c *udpMuxedConn) LocalAddr() net.Addr { - return c.params.LocalAddr -} - -func (c *udpMuxedConn) SetDeadline(time.Time) error { - return nil -} - -func (c *udpMuxedConn) SetReadDeadline(time.Time) error { - return nil -} - -func (c *udpMuxedConn) SetWriteDeadline(time.Time) error { - return nil -} - -func (c *udpMuxedConn) CloseChannel() <-chan struct{} { - return c.closedChan -} - -func (c *udpMuxedConn) Close() error { - var err error - c.closeOnce.Do(func() { - err = c.buf.Close() - close(c.closedChan) - }) - return err -} - -func (c *udpMuxedConn) isClosed() bool { - select { - case <-c.closedChan: - return true - default: - return false - } -} - -func (c *udpMuxedConn) getAddresses() []string { - c.mu.Lock() - defer c.mu.Unlock() - addresses := make([]string, len(c.addresses)) - copy(addresses, c.addresses) - return addresses -} - -func (c *udpMuxedConn) addAddress(addr string) { - c.mu.Lock() - c.addresses = append(c.addresses, addr) - c.mu.Unlock() - - // Map it on mux - c.params.Mux.registerConnForAddress(c, addr) -} - -func (c *udpMuxedConn) removeAddress(addr string) { - c.mu.Lock() - defer c.mu.Unlock() - - newAddresses := make([]string, 0, len(c.addresses)) - for _, a := range c.addresses { - if a != addr { - newAddresses = append(newAddresses, a) - } - } - - c.addresses = newAddresses -} - -func (c *udpMuxedConn) containsAddress(addr string) bool { - c.mu.Lock() - defer c.mu.Unlock() - for _, a := range c.addresses { - if addr == a { - return true - } - } - return false -} - -func (c *udpMuxedConn) writePacket(data []byte, addr *net.UDPAddr) error { - // Write two packets, address and data - buf := c.params.AddrPool.Get().(*bufferHolder) //nolint:forcetypeassert - defer c.params.AddrPool.Put(buf) - - // Format of buffer | data len | data bytes | addr len | addr bytes | - if len(buf.buf) < len(data)+maxAddrSize { - return io.ErrShortBuffer - } - // Data length - binary.LittleEndian.PutUint16(buf.buf, uint16(len(data))) - offset := 2 - - // Data - copy(buf.buf[offset:], data) - offset += len(data) - - // Write address first, leaving room for its length - n, err := encodeUDPAddr(addr, buf.buf[offset+2:]) - if err != nil { - return err - } - total := offset + n + 2 - - // Address len - binary.LittleEndian.PutUint16(buf.buf[offset:], uint16(n)) - - if _, err := c.buf.Write(buf.buf[:total]); err != nil { - return err - } - return nil -} - -func encodeUDPAddr(addr *net.UDPAddr, buf []byte) (int, error) { - ipData, err := addr.IP.MarshalText() - if err != nil { - return 0, err - } - total := 2 + len(ipData) + 2 + len(addr.Zone) - if total > len(buf) { - return 0, io.ErrShortBuffer - } - - binary.LittleEndian.PutUint16(buf, uint16(len(ipData))) - offset := 2 - n := copy(buf[offset:], ipData) - offset += n - binary.LittleEndian.PutUint16(buf[offset:], uint16(addr.Port)) - offset += 2 - copy(buf[offset:], addr.Zone) - return total, nil -} - -func decodeUDPAddr(buf []byte) (*net.UDPAddr, error) { - addr := net.UDPAddr{} - - offset := 0 - ipLen := int(binary.LittleEndian.Uint16(buf[:2])) - offset += 2 - // Basic bounds checking - if ipLen+offset > len(buf) { - return nil, io.ErrShortBuffer - } - if err := addr.IP.UnmarshalText(buf[offset : offset+ipLen]); err != nil { - return nil, err - } - offset += ipLen - addr.Port = int(binary.LittleEndian.Uint16(buf[offset : offset+2])) - offset += 2 - zone := make([]byte, len(buf[offset:])) - copy(zone, buf[offset:]) - addr.Zone = string(zone) - - return &addr, nil -} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/.gitignore b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/.gitignore similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/.gitignore rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/.gitignore diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/.golangci.yml b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/.golangci.yml new file mode 100644 index 000000000..88cb4fbf9 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/.golangci.yml @@ -0,0 +1,138 @@ +# SPDX-FileCopyrightText: 2023 The Pion community +# SPDX-License-Identifier: MIT + +run: + timeout: 5m + +linters-settings: + govet: + enable: + - shadow + misspell: + locale: US + exhaustive: + default-signifies-exhaustive: true + gomodguard: + blocked: + modules: + - github.com/pkg/errors: + recommendations: + - errors + forbidigo: + forbid: + - ^fmt.Print(f|ln)?$ + - ^log.(Panic|Fatal|Print)(f|ln)?$ + - ^os.Exit$ + - ^panic$ + - ^print(ln)?$ + varnamelen: + max-distance: 12 + min-name-length: 2 + ignore-type-assert-ok: true + ignore-map-index-ok: true + ignore-chan-recv-ok: true + ignore-decls: + - i int + - n int + - w io.Writer + - r io.Reader + - b []byte + +linters: + enable: + - asciicheck # Simple linter to check that your code does not contain non-ASCII identifiers + - bidichk # Checks for dangerous unicode character sequences + - bodyclose # checks whether HTTP response body is closed successfully + - containedctx # containedctx is a linter that detects struct contained context.Context field + - contextcheck # check the function whether use a non-inherited context + - cyclop # checks function and package cyclomatic complexity + - decorder # check declaration order and count of types, constants, variables and functions + - dogsled # Checks assignments with too many blank identifiers (e.g. x, _, _, _, := f()) + - dupl # Tool for code clone detection + - durationcheck # check for two durations multiplied together + - err113 # Golang linter to check the errors handling expressions + - errcheck # Errcheck is a program for checking for unchecked errors in go programs. These unchecked errors can be critical bugs in some cases + - errchkjson # Checks types passed to the json encoding functions. Reports unsupported types and optionally reports occations, where the check for the returned error can be omitted. + - errname # Checks that sentinel errors are prefixed with the `Err` and error types are suffixed with the `Error`. + - errorlint # errorlint is a linter for that can be used to find code that will cause problems with the error wrapping scheme introduced in Go 1.13. + - exhaustive # check exhaustiveness of enum switch statements + - exportloopref # checks for pointers to enclosing loop variables + - forbidigo # Forbids identifiers + - forcetypeassert # finds forced type assertions + - gci # Gci control golang package import order and make it always deterministic. + - gochecknoglobals # Checks that no globals are present in Go code + - gocognit # Computes and checks the cognitive complexity of functions + - goconst # Finds repeated strings that could be replaced by a constant + - gocritic # The most opinionated Go source code linter + - gocyclo # Computes and checks the cyclomatic complexity of functions + - godot # Check if comments end in a period + - godox # Tool for detection of FIXME, TODO and other comment keywords + - gofmt # Gofmt checks whether code was gofmt-ed. By default this tool runs with -s option to check for code simplification + - gofumpt # Gofumpt checks whether code was gofumpt-ed. + - goheader # Checks is file header matches to pattern + - goimports # Goimports does everything that gofmt does. Additionally it checks unused imports + - gomoddirectives # Manage the use of 'replace', 'retract', and 'excludes' directives in go.mod. + - goprintffuncname # Checks that printf-like functions are named with `f` at the end + - gosec # Inspects source code for security problems + - gosimple # Linter for Go source code that specializes in simplifying a code + - govet # Vet examines Go source code and reports suspicious constructs, such as Printf calls whose arguments do not align with the format string + - grouper # An analyzer to analyze expression groups. + - importas # Enforces consistent import aliases + - ineffassign # Detects when assignments to existing variables are not used + - lll # Reports long lines + - maintidx # maintidx measures the maintainability index of each function. + - makezero # Finds slice declarations with non-zero initial length + - misspell # Finds commonly misspelled English words in comments + - nakedret # Finds naked returns in functions greater than a specified function length + - nestif # Reports deeply nested if statements + - nilerr # Finds the code that returns nil even if it checks that the error is not nil. + - nilnil # Checks that there is no simultaneous return of `nil` error and an invalid value. + - nlreturn # nlreturn checks for a new line before return and branch statements to increase code clarity + - noctx # noctx finds sending http request without context.Context + - predeclared # find code that shadows one of Go's predeclared identifiers + - revive # golint replacement, finds style mistakes + - staticcheck # Staticcheck is a go vet on steroids, applying a ton of static analysis checks + - stylecheck # Stylecheck is a replacement for golint + - tagliatelle # Checks the struct tags. + - tenv # tenv is analyzer that detects using os.Setenv instead of t.Setenv since Go1.17 + - thelper # thelper detects golang test helpers without t.Helper() call and checks the consistency of test helpers + - typecheck # Like the front-end of a Go compiler, parses and type-checks Go code + - unconvert # Remove unnecessary type conversions + - unparam # Reports unused function parameters + - unused # Checks Go code for unused constants, variables, functions and types + - varnamelen # checks that the length of a variable's name matches its scope + - wastedassign # wastedassign finds wasted assignment statements + - whitespace # Tool for detection of leading and trailing whitespace + disable: + - depguard # Go linter that checks if package imports are in a list of acceptable packages + - funlen # Tool for detection of long functions + - gochecknoinits # Checks that no init functions are present in Go code + - gomodguard # Allow and block list linter for direct Go module dependencies. This is different from depguard where there are different block types for example version constraints and module recommendations. + - interfacebloat # A linter that checks length of interface. + - ireturn # Accept Interfaces, Return Concrete Types + - mnd # An analyzer to detect magic numbers + - nolintlint # Reports ill-formed or insufficient nolint directives + - paralleltest # paralleltest detects missing usage of t.Parallel() method in your Go test + - prealloc # Finds slice declarations that could potentially be preallocated + - promlinter # Check Prometheus metrics naming via promlint + - rowserrcheck # checks whether Err of rows is checked successfully + - sqlclosecheck # Checks that sql.Rows and sql.Stmt are closed. + - testpackage # linter that makes you use a separate _test package + - tparallel # tparallel detects inappropriate usage of t.Parallel() method in your Go test codes + - wrapcheck # Checks that errors returned from external packages are wrapped + - wsl # Whitespace Linter - Forces you to use empty lines! + +issues: + exclude-use-default: false + exclude-dirs-use-default: false + exclude-rules: + # Allow complex tests and examples, better to be self contained + - path: (examples|main\.go|_test\.go) + linters: + - forbidigo + - gocognit + + # Allow forbidden identifiers in CLI commands + - path: cmd + linters: + - forbidigo diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/.goreleaser.yml b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/.goreleaser.yml similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/.goreleaser.yml rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/.goreleaser.yml diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/LICENSE b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/LICENSE similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/LICENSE rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/LICENSE diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/README.md b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/README.md similarity index 65% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/README.md rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/README.md index 111ca7057..5171a41ff 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/README.md +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/README.md @@ -6,10 +6,10 @@

A Go implementation of ICE

Pion ICE - Slack Widget + join us on Discord Follow us on Bluesky
GitHub Workflow Status - Go Reference + Go Reference Coverage Status Go Report Card License: MIT @@ -20,15 +20,15 @@ The library is used as a part of our WebRTC implementation. Please refer to that [roadmap](https://github.com/pion/webrtc/issues/9) to track our major milestones. ### Community -Pion has an active community on the [Slack](https://pion.ly/slack). +Pion has an active community on the [Discord](https://discord.gg/PngbdqpFbt). -Follow the [Pion Twitter](https://twitter.com/_pion) for project updates and important WebRTC news. +Follow the [Pion Bluesky](https://bsky.app/profile/pion.ly) or [Pion Twitter](https://twitter.com/_pion) for project updates and important WebRTC news. We are always looking to support **your projects**. Please reach out if you have something to build! If you need commercial support or don't want to use public methods you can contact us at [team@pion.ly](mailto:team@pion.ly) ### Contributing -Check out the [contributing wiki](https://github.com/pion/webrtc/wiki/Contributing) to join the group of amazing people making this project possible: [AUTHORS.txt](./AUTHORS.txt) +Check out the [contributing wiki](https://github.com/pion/webrtc/wiki/Contributing) to join the group of amazing people making this project possible ### License MIT License - see [LICENSE](LICENSE) for full text diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/active_tcp.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/active_tcp.go new file mode 100644 index 000000000..b55e65041 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/active_tcp.go @@ -0,0 +1,177 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + +package ice + +import ( + "context" + "io" + "net" + "net/netip" + "sync/atomic" + "time" + + "github.com/pion/logging" + "github.com/pion/transport/v3/packetio" +) + +type activeTCPConn struct { + readBuffer, writeBuffer *packetio.Buffer + localAddr, remoteAddr atomic.Value + closed int32 +} + +func newActiveTCPConn( + ctx context.Context, + localAddress string, + remoteAddress netip.AddrPort, + log logging.LeveledLogger, +) (a *activeTCPConn) { + a = &activeTCPConn{ + readBuffer: packetio.NewBuffer(), + writeBuffer: packetio.NewBuffer(), + } + + laddr, err := getTCPAddrOnInterface(localAddress) + if err != nil { + atomic.StoreInt32(&a.closed, 1) + log.Infof("Failed to dial TCP address %s: %v", remoteAddress, err) + + return a + } + a.localAddr.Store(laddr) + + go func() { + defer func() { + atomic.StoreInt32(&a.closed, 1) + }() + + dialer := &net.Dialer{ + LocalAddr: laddr, + } + conn, err := dialer.DialContext(ctx, "tcp", remoteAddress.String()) + if err != nil { + log.Infof("Failed to dial TCP address %s: %v", remoteAddress, err) + + return + } + a.remoteAddr.Store(conn.RemoteAddr()) + + go func() { + buff := make([]byte, receiveMTU) + + for atomic.LoadInt32(&a.closed) == 0 { + n, err := readStreamingPacket(conn, buff) + if err != nil { + log.Infof("Failed to read streaming packet: %s", err) + + break + } + + if _, err := a.readBuffer.Write(buff[:n]); err != nil { + log.Infof("Failed to write to buffer: %s", err) + + break + } + } + }() + + buff := make([]byte, receiveMTU) + + for atomic.LoadInt32(&a.closed) == 0 { + n, err := a.writeBuffer.Read(buff) + if err != nil { + log.Infof("Failed to read from buffer: %s", err) + + break + } + + if _, err = writeStreamingPacket(conn, buff[:n]); err != nil { + log.Infof("Failed to write streaming packet: %s", err) + + break + } + } + + if err := conn.Close(); err != nil { + log.Infof("Failed to close connection: %s", err) + } + }() + + return a +} + +func (a *activeTCPConn) ReadFrom(buff []byte) (n int, srcAddr net.Addr, err error) { + if atomic.LoadInt32(&a.closed) == 1 { + return 0, nil, io.ErrClosedPipe + } + + n, err = a.readBuffer.Read(buff) + // RemoteAddr is assuredly set *after* we can read from the buffer + srcAddr = a.RemoteAddr() + + return +} + +func (a *activeTCPConn) WriteTo(buff []byte, _ net.Addr) (n int, err error) { + if atomic.LoadInt32(&a.closed) == 1 { + return 0, io.ErrClosedPipe + } + + return a.writeBuffer.Write(buff) +} + +func (a *activeTCPConn) Close() error { + atomic.StoreInt32(&a.closed, 1) + _ = a.readBuffer.Close() + _ = a.writeBuffer.Close() + + return nil +} + +func (a *activeTCPConn) LocalAddr() net.Addr { + if v, ok := a.localAddr.Load().(*net.TCPAddr); ok { + return v + } + + return &net.TCPAddr{} +} + +// RemoteAddr returns the remote address of the connection which is only +// set once a background goroutine has successfully dialed. That means +// this may return ":0" for the address prior to that happening. If this +// becomes an issue, we can introduce a synchronization point between Dial +// and these methods. +func (a *activeTCPConn) RemoteAddr() net.Addr { + if v, ok := a.remoteAddr.Load().(*net.TCPAddr); ok { + return v + } + + return &net.TCPAddr{} +} + +func (a *activeTCPConn) SetDeadline(time.Time) error { return io.EOF } +func (a *activeTCPConn) SetReadDeadline(time.Time) error { return io.EOF } +func (a *activeTCPConn) SetWriteDeadline(time.Time) error { return io.EOF } + +func getTCPAddrOnInterface(address string) (*net.TCPAddr, error) { + addr, err := net.ResolveTCPAddr("tcp", address) + if err != nil { + return nil, err + } + + l, err := net.ListenTCP("tcp", addr) + if err != nil { + return nil, err + } + defer func() { + _ = l.Close() + }() + + tcpAddr, ok := l.Addr().(*net.TCPAddr) + if !ok { + return nil, errInvalidAddress + } + + return tcpAddr, nil +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/addr.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/addr.go new file mode 100644 index 000000000..fad58b93a --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/addr.go @@ -0,0 +1,153 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + +package ice + +import ( + "fmt" + "net" + "net/netip" +) + +func addrWithOptionalZone(addr netip.Addr, zone string) netip.Addr { + if zone == "" { + return addr + } + if addr.Is6() && (addr.IsLinkLocalUnicast() || addr.IsLinkLocalMulticast()) { + return addr.WithZone(zone) + } + + return addr +} + +// parseAddrFromIface should only be used when it's known the address belongs to that interface. +// e.g. it's LocalAddress on a listener. +func parseAddrFromIface(in net.Addr, ifcName string) (netip.Addr, int, NetworkType, error) { + addr, port, nt, err := parseAddr(in) + if err != nil { + return netip.Addr{}, 0, 0, err + } + if _, ok := in.(*net.IPNet); ok { + // net.IPNet does not have a Zone but we provide it from the interface + addr = addrWithOptionalZone(addr, ifcName) + } + + return addr, port, nt, nil +} + +func parseAddr(in net.Addr) (netip.Addr, int, NetworkType, error) { //nolint:cyclop + switch addr := in.(type) { + case *net.IPNet: + ipAddr, err := ipAddrToNetIP(addr.IP, "") + if err != nil { + return netip.Addr{}, 0, 0, err + } + + return ipAddr, 0, 0, nil + case *net.IPAddr: + ipAddr, err := ipAddrToNetIP(addr.IP, addr.Zone) + if err != nil { + return netip.Addr{}, 0, 0, err + } + + return ipAddr, 0, 0, nil + case *net.UDPAddr: + ipAddr, err := ipAddrToNetIP(addr.IP, addr.Zone) + if err != nil { + return netip.Addr{}, 0, 0, err + } + var nt NetworkType + if ipAddr.Is4() { + nt = NetworkTypeUDP4 + } else { + nt = NetworkTypeUDP6 + } + + return ipAddr, addr.Port, nt, nil + case *net.TCPAddr: + ipAddr, err := ipAddrToNetIP(addr.IP, addr.Zone) + if err != nil { + return netip.Addr{}, 0, 0, err + } + var nt NetworkType + if ipAddr.Is4() { + nt = NetworkTypeTCP4 + } else { + nt = NetworkTypeTCP6 + } + + return ipAddr, addr.Port, nt, nil + default: + return netip.Addr{}, 0, 0, addrParseError{in} + } +} + +type addrParseError struct { + addr net.Addr +} + +func (e addrParseError) Error() string { + return fmt.Sprintf("do not know how to parse address type %T", e.addr) +} + +type ipConvertError struct { + ip []byte +} + +func (e ipConvertError) Error() string { + return fmt.Sprintf("failed to convert IP '%s' to netip.Addr", e.ip) +} + +func ipAddrToNetIP(ip []byte, zone string) (netip.Addr, error) { + netIPAddr, ok := netip.AddrFromSlice(ip) + if !ok { + return netip.Addr{}, ipConvertError{ip} + } + // we'd rather have an IPv4-mapped IPv6 become IPv4 so that it is usable. + netIPAddr = netIPAddr.Unmap() + netIPAddr = addrWithOptionalZone(netIPAddr, zone) + + return netIPAddr, nil +} + +func createAddr(network NetworkType, ip netip.Addr, port int) net.Addr { + switch { + case network.IsTCP(): + return &net.TCPAddr{IP: ip.AsSlice(), Port: port, Zone: ip.Zone()} + default: + return &net.UDPAddr{IP: ip.AsSlice(), Port: port, Zone: ip.Zone()} + } +} + +func addrEqual(a, b net.Addr) bool { + aIP, aPort, aType, aErr := parseAddr(a) + if aErr != nil { + return false + } + + bIP, bPort, bType, bErr := parseAddr(b) + if bErr != nil { + return false + } + + return aType == bType && aIP.Compare(bIP) == 0 && aPort == bPort +} + +// AddrPort is an IP and a port number. +type AddrPort [18]byte + +func toAddrPort(addr net.Addr) AddrPort { + var ap AddrPort + switch addr := addr.(type) { + case *net.UDPAddr: + copy(ap[:16], addr.IP.To16()) + ap[16] = uint8(addr.Port >> 8) //nolint:gosec // G115 false positive + ap[17] = uint8(addr.Port) //nolint:gosec // G115 false positive + case *net.TCPAddr: + copy(ap[:16], addr.IP.To16()) + ap[16] = uint8(addr.Port >> 8) //nolint:gosec // G115 false positive + ap[17] = uint8(addr.Port) //nolint:gosec // G115 false positive + } + + return ap +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/agent.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/agent.go similarity index 58% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/agent.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/agent.go index 5350330f6..80c89d05b 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/agent.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/agent.go @@ -8,21 +8,23 @@ package ice import ( "context" "fmt" + "math" "net" + "net/netip" "strings" "sync" "sync/atomic" "time" - atomicx "github.com/pion/ice/v2/internal/atomic" - stunx "github.com/pion/ice/v2/internal/stun" + stunx "github.com/pion/ice/v4/internal/stun" + "github.com/pion/ice/v4/internal/taskloop" "github.com/pion/logging" - "github.com/pion/mdns" - "github.com/pion/stun" - "github.com/pion/transport/v2" - "github.com/pion/transport/v2/packetio" - "github.com/pion/transport/v2/stdnet" - "github.com/pion/transport/v2/vnet" + "github.com/pion/mdns/v2" + "github.com/pion/stun/v3" + "github.com/pion/transport/v3" + "github.com/pion/transport/v3/packetio" + "github.com/pion/transport/v3/stdnet" + "github.com/pion/transport/v3/vnet" "golang.org/x/net/proxy" ) @@ -33,17 +35,14 @@ type bindingRequest struct { isUseCandidate bool } -// Agent represents the ICE agent +// Agent represents the ICE agent. type Agent struct { - chanTask chan task - afterRunFn []func(ctx context.Context) - muAfterRun sync.Mutex + loop *taskloop.Loop onConnectionStateChangeHdlr atomic.Value // func(ConnectionState) onSelectedCandidatePairChangeHdlr atomic.Value // func(Candidate, Candidate) onCandidateHdlr atomic.Value // func(Candidate) - // State owned by the taskLoop onConnected chan struct{} onConnectedOnce sync.Once @@ -71,6 +70,10 @@ type Agent struct { srflxAcceptanceMinWait time.Duration prflxAcceptanceMinWait time.Duration relayAcceptanceMinWait time.Duration + stunGatherTimeout time.Duration + + tcpPriorityOffset uint16 + disableActiveTCP bool portMin uint16 portMax uint16 @@ -116,17 +119,16 @@ type Agent struct { // 1:1 D-NAT IP address mapping extIPMapper *externalIPMapper - // State for closing - done chan struct{} - taskLoopDone chan struct{} - err atomicx.Error + // Callback that allows user to implement custom behavior + // for STUN Binding Requests + userBindingRequestHandler func(m *stun.Message, local, remote Candidate, pair *CandidatePair) bool gatherCandidateCancel func() gatherCandidateDone chan struct{} - chanCandidate chan Candidate - chanCandidatePair chan *CandidatePair - chanState chan ConnectionState + connectionStateNotifier *handlerNotifier + candidateNotifier *handlerNotifier + selectedCandidatePairNotifier *handlerNotifier loggerFactory logging.LoggerFactory log logging.LeveledLogger @@ -136,113 +138,19 @@ type Agent struct { udpMux UDPMux udpMuxSrflx UniversalUDPMux - interfaceFilter func(string) bool - ipFilter func(net.IP) bool + interfaceFilter func(string) (keep bool) + ipFilter func(net.IP) (keep bool) includeLoopback bool insecureSkipVerify bool proxyDialer proxy.Dialer + + enableUseCandidateCheckPriority bool } -type task struct { - fn func(context.Context, *Agent) - done chan struct{} -} - -// afterRun registers function to be run after the task. -func (a *Agent) afterRun(f func(context.Context)) { - a.muAfterRun.Lock() - a.afterRunFn = append(a.afterRunFn, f) - a.muAfterRun.Unlock() -} - -func (a *Agent) getAfterRunFn() []func(context.Context) { - a.muAfterRun.Lock() - defer a.muAfterRun.Unlock() - fns := a.afterRunFn - a.afterRunFn = nil - return fns -} - -func (a *Agent) ok() error { - select { - case <-a.done: - return a.getErr() - default: - } - return nil -} - -func (a *Agent) getErr() error { - if err := a.err.Load(); err != nil { - return err - } - return ErrClosed -} - -// Run task in serial. Blocking tasks must be cancelable by context. -func (a *Agent) run(ctx context.Context, t func(context.Context, *Agent)) error { - if err := a.ok(); err != nil { - return err - } - done := make(chan struct{}) - select { - case <-ctx.Done(): - return ctx.Err() - case a.chanTask <- task{t, done}: - <-done - return nil - } -} - -// taskLoop handles registered tasks and agent close. -func (a *Agent) taskLoop() { - after := func() { - for { - // Get and run func registered by afterRun(). - fns := a.getAfterRunFn() - if len(fns) == 0 { - break - } - for _, fn := range fns { - fn(a.context()) - } - } - } - defer func() { - a.deleteAllCandidates() - a.startedFn() - - if err := a.buf.Close(); err != nil { - a.log.Warnf("Failed to close buffer: %v", err) - } - - a.closeMulticastConn() - a.updateConnectionState(ConnectionStateClosed) - - after() - - close(a.chanState) - close(a.chanCandidate) - close(a.chanCandidatePair) - close(a.taskLoopDone) - }() - - for { - select { - case <-a.done: - return - case t := <-a.chanTask: - t.fn(a.context(), a) - close(t.done) - after() - } - } -} - -// NewAgent creates a new Agent -func NewAgent(config *AgentConfig) (*Agent, error) { //nolint:gocognit +// NewAgent creates a new Agent. +func NewAgent(config *AgentConfig) (*Agent, error) { //nolint:gocognit,cyclop var err error if config.PortMax < config.PortMin { return nil, ErrPort @@ -272,34 +180,28 @@ func NewAgent(config *AgentConfig) (*Agent, error) { //nolint:gocognit startedCtx, startedFn := context.WithCancel(context.Background()) - a := &Agent{ - chanTask: make(chan task), - chanState: make(chan ConnectionState), - chanCandidate: make(chan Candidate), - chanCandidatePair: make(chan *CandidatePair), - tieBreaker: globalMathRandomGenerator.Uint64(), - lite: config.Lite, - gatheringState: GatheringStateNew, - connectionState: ConnectionStateNew, - localCandidates: make(map[NetworkType][]Candidate), - remoteCandidates: make(map[NetworkType][]Candidate), - urls: config.Urls, - networkTypes: config.NetworkTypes, - onConnected: make(chan struct{}), - buf: packetio.NewBuffer(), - done: make(chan struct{}), - taskLoopDone: make(chan struct{}), - startedCh: startedCtx.Done(), - startedFn: startedFn, - portMin: config.PortMin, - portMax: config.PortMax, - loggerFactory: loggerFactory, - log: log, - net: config.Net, - proxyDialer: config.ProxyDialer, - tcpMux: config.TCPMux, - udpMux: config.UDPMux, - udpMuxSrflx: config.UDPMuxSrflx, + agent := &Agent{ + tieBreaker: globalMathRandomGenerator.Uint64(), + lite: config.Lite, + gatheringState: GatheringStateNew, + connectionState: ConnectionStateNew, + localCandidates: make(map[NetworkType][]Candidate), + remoteCandidates: make(map[NetworkType][]Candidate), + urls: config.Urls, + networkTypes: config.NetworkTypes, + onConnected: make(chan struct{}), + buf: packetio.NewBuffer(), + startedCh: startedCtx.Done(), + startedFn: startedFn, + portMin: config.PortMin, + portMax: config.PortMax, + loggerFactory: loggerFactory, + log: log, + net: config.Net, + proxyDialer: config.ProxyDialer, + tcpMux: config.TCPMux, + udpMux: config.UDPMux, + udpMuxSrflx: config.UDPMuxSrflx, mDNSMode: mDNSMode, mDNSName: mDNSName, @@ -315,65 +217,115 @@ func NewAgent(config *AgentConfig) (*Agent, error) { //nolint:gocognit insecureSkipVerify: config.InsecureSkipVerify, includeLoopback: config.IncludeLoopback, + + disableActiveTCP: config.DisableActiveTCP, + + userBindingRequestHandler: config.BindingRequestHandler, + + enableUseCandidateCheckPriority: config.EnableUseCandidateCheckPriority, + } + agent.connectionStateNotifier = &handlerNotifier{ + connectionStateFunc: agent.onConnectionStateChange, + done: make(chan struct{}), + } + agent.candidateNotifier = &handlerNotifier{candidateFunc: agent.onCandidate, done: make(chan struct{})} + agent.selectedCandidatePairNotifier = &handlerNotifier{ + candidatePairFunc: agent.onSelectedCandidatePairChange, + done: make(chan struct{}), } - if a.net == nil { - a.net, err = stdnet.NewNet() + if agent.net == nil { + agent.net, err = stdnet.NewNet() if err != nil { return nil, fmt.Errorf("failed to create network: %w", err) } - } else if _, isVirtual := a.net.(*vnet.Net); isVirtual { - a.log.Warn("Virtual network is enabled") - if a.mDNSMode != MulticastDNSModeDisabled { - a.log.Warn("Virtual network does not support mDNS yet") + } else if _, isVirtual := agent.net.(*vnet.Net); isVirtual { + agent.log.Warn("Virtual network is enabled") + if agent.mDNSMode != MulticastDNSModeDisabled { + agent.log.Warn("Virtual network does not support mDNS yet") } } + localIfcs, _, err := localInterfaces( + agent.net, + agent.interfaceFilter, + agent.ipFilter, + agent.networkTypes, + agent.includeLoopback, + ) + if err != nil { + return nil, fmt.Errorf("error getting local interfaces: %w", err) + } + // Opportunistic mDNS: If we can't open the connection, that's ok: we // can continue without it. - if a.mDNSConn, a.mDNSMode, err = createMulticastDNS(a.net, mDNSMode, mDNSName, log); err != nil { + if agent.mDNSConn, agent.mDNSMode, err = createMulticastDNS( + agent.net, + agent.networkTypes, + localIfcs, + agent.includeLoopback, + mDNSMode, + mDNSName, + log, + loggerFactory, + ); err != nil { log.Warnf("Failed to initialize mDNS %s: %v", mDNSName, err) } - config.initWithDefaults(a) + config.initWithDefaults(agent) // Make sure the buffer doesn't grow indefinitely. // NOTE: We actually won't get anywhere close to this limit. // SRTP will constantly read from the endpoint and drop packets if it's full. - a.buf.SetLimitSize(maxBufferSize) + agent.buf.SetLimitSize(maxBufferSize) + + if agent.lite && (len(agent.candidateTypes) != 1 || agent.candidateTypes[0] != CandidateTypeHost) { + agent.closeMulticastConn() - if a.lite && (len(a.candidateTypes) != 1 || a.candidateTypes[0] != CandidateTypeHost) { - a.closeMulticastConn() return nil, ErrLiteUsingNonHostCandidates } - if config.Urls != nil && len(config.Urls) > 0 && !containsCandidateType(CandidateTypeServerReflexive, a.candidateTypes) && !containsCandidateType(CandidateTypeRelay, a.candidateTypes) { - a.closeMulticastConn() + if len(config.Urls) > 0 && + !containsCandidateType(CandidateTypeServerReflexive, agent.candidateTypes) && + !containsCandidateType(CandidateTypeRelay, agent.candidateTypes) { + agent.closeMulticastConn() + return nil, ErrUselessUrlsProvided } - if err = config.initExtIPMapping(a); err != nil { - a.closeMulticastConn() + if err = config.initExtIPMapping(agent); err != nil { + agent.closeMulticastConn() + return nil, err } - go a.taskLoop() + agent.loop = taskloop.New(func() { + agent.removeUfragFromMux() + agent.deleteAllCandidates() + agent.startedFn() - // CandidatePair and ConnectionState are usually changed at once. - // Blocking one by the other one causes deadlock. - // Hence, we call handlers from independent Goroutines. - go a.candidatePairRoutine() - go a.connectionStateRoutine() - go a.candidateRoutine() + if err := agent.buf.Close(); err != nil { + agent.log.Warnf("Failed to close buffer: %v", err) + } + + agent.closeMulticastConn() + agent.updateConnectionState(ConnectionStateClosed) + + agent.gatherCandidateCancel() + if agent.gatherCandidateDone != nil { + <-agent.gatherCandidateDone + } + }) // Restart is also used to initialize the agent for the first time - if err := a.Restart(config.LocalUfrag, config.LocalPwd); err != nil { - a.closeMulticastConn() - _ = a.Close() + if err := agent.Restart(config.LocalUfrag, config.LocalPwd); err != nil { + agent.closeMulticastConn() + _ = agent.Close() + return nil, err } - return a, nil + return agent, nil } func (a *Agent) startConnectivityChecks(isControlling bool, remoteUfrag, remotePwd string) error { @@ -390,10 +342,10 @@ func (a *Agent) startConnectivityChecks(isControlling bool, remoteUfrag, remoteP a.log.Debugf("Started agent: isControlling? %t, remoteUfrag: %q, remotePwd: %q", isControlling, remoteUfrag, remotePwd) - return a.run(a.context(), func(ctx context.Context, agent *Agent) { - agent.isControlling = isControlling - agent.remoteUfrag = remoteUfrag - agent.remotePwd = remotePwd + return a.loop.Run(a.loop, func(_ context.Context) { + a.isControlling = isControlling + a.remoteUfrag = remoteUfrag + a.remotePwd = remotePwd if isControlling { a.selector = &controllingSelector{agent: a, log: a.log} @@ -408,19 +360,19 @@ func (a *Agent) startConnectivityChecks(isControlling bool, remoteUfrag, remoteP a.selector.Start() a.startedFn() - agent.updateConnectionState(ConnectionStateChecking) + a.updateConnectionState(ConnectionStateChecking) a.requestConnectivityCheck() go a.connectivityChecks() //nolint:contextcheck }) } -func (a *Agent) connectivityChecks() { +func (a *Agent) connectivityChecks() { //nolint:cyclop lastConnectionState := ConnectionState(0) checkingDuration := time.Time{} contact := func() { - if err := a.run(a.context(), func(ctx context.Context, a *Agent) { + if err := a.loop.Run(a.loop, func(_ context.Context) { defer func() { lastConnectionState = a.connectionState }() @@ -439,6 +391,7 @@ func (a *Agent) connectivityChecks() { // We have been in checking longer then Disconnect+Failed timeout, set the connection to Failed if time.Since(checkingDuration) > a.disconnectedTimeout+a.failedTimeout { a.updateConnectionState(ConnectionStateFailed) + return } default: @@ -450,6 +403,9 @@ func (a *Agent) connectivityChecks() { } } + timer := time.NewTimer(math.MaxInt64) + timer.Stop() + for { interval := defaultKeepaliveInterval @@ -470,15 +426,19 @@ func (a *Agent) connectivityChecks() { updateInterval(a.disconnectedTimeout) updateInterval(a.failedTimeout) - t := time.NewTimer(interval) + timer.Reset(interval) + select { case <-a.forceCandidateContact: - t.Stop() + if !timer.Stop() { + <-timer.C + } contact() - case <-t.C: + case <-timer.C: contact() - case <-a.done: - t.Stop() + case <-a.loop.Done(): + timer.Stop() + return } } @@ -488,48 +448,43 @@ func (a *Agent) updateConnectionState(newState ConnectionState) { if a.connectionState != newState { // Connection has gone to failed, release all gathered candidates if newState == ConnectionStateFailed { + a.removeUfragFromMux() + a.checklist = make([]*CandidatePair, 0) + a.pendingBindingRequests = make([]bindingRequest, 0) + a.setSelectedPair(nil) a.deleteAllCandidates() } a.log.Infof("Setting new connection state: %s", newState) a.connectionState = newState - - // Call handler after finishing current task since we may be holding the agent lock - // and the handler may also require it - a.afterRun(func(ctx context.Context) { - a.chanState <- newState - }) + a.connectionStateNotifier.EnqueueConnectionState(newState) } } -func (a *Agent) setSelectedPair(p *CandidatePair) { - if p == nil { +func (a *Agent) setSelectedPair(pair *CandidatePair) { + if pair == nil { var nilPair *CandidatePair a.selectedPair.Store(nilPair) a.log.Tracef("Unset selected candidate pair") + return } - p.nominated = true - a.selectedPair.Store(p) - a.log.Tracef("Set selected candidate pair: %s", p) + pair.nominated = true + a.selectedPair.Store(pair) + a.log.Tracef("Set selected candidate pair: %s", pair) a.updateConnectionState(ConnectionStateConnected) // Notify when the selected pair changes - a.afterRun(func(ctx context.Context) { - select { - case a.chanCandidatePair <- p: - case <-ctx.Done(): - } - }) + a.selectedCandidatePairNotifier.EnqueueSelectedCandidatePair(pair) // Signal connected a.onConnectedOnce.Do(func() { close(a.onConnected) }) } func (a *Agent) pingAllCandidates() { - a.log.Trace("pinging all candidates") + a.log.Trace("Pinging all candidates") if len(a.checklist) == 0 { a.log.Warn("Failed to ping without candidate pairs. Connection is not possible yet.") @@ -543,7 +498,7 @@ func (a *Agent) pingAllCandidates() { } if p.bindingRequestCount > a.maxBindingRequests { - a.log.Tracef("max requests reached for pair %s, marking it as failed", p) + a.log.Tracef("Maximum requests reached for pair %s, marking it as failed", p) p.state = CandidatePairStateFailed } else { a.selector.PingCandidate(p.Local, p.Remote) @@ -565,6 +520,7 @@ func (a *Agent) getBestAvailableCandidatePair() *CandidatePair { best = p } } + return best } @@ -581,12 +537,14 @@ func (a *Agent) getBestValidCandidatePair() *CandidatePair { best = p } } + return best } func (a *Agent) addPair(local, remote Candidate) *CandidatePair { p := newCandidatePair(local, remote, a.isControlling) a.checklist = append(a.checklist, p) + return p } @@ -596,6 +554,7 @@ func (a *Agent) findPair(local, remote Candidate) *CandidatePair { return p } } + return nil } @@ -636,82 +595,83 @@ func (a *Agent) checkKeepalive() { return } - if (a.keepaliveInterval != 0) && - ((time.Since(selectedPair.Local.LastSent()) > a.keepaliveInterval) || - (time.Since(selectedPair.Remote.LastReceived()) > a.keepaliveInterval)) { + if a.keepaliveInterval != 0 { // We use binding request instead of indication to support refresh consent schemas // see https://tools.ietf.org/html/rfc7675 a.selector.PingCandidate(selectedPair.Local, selectedPair.Remote) } } -// AddRemoteCandidate adds a new remote candidate -func (a *Agent) AddRemoteCandidate(c Candidate) error { - if c == nil { +// AddRemoteCandidate adds a new remote candidate. +func (a *Agent) AddRemoteCandidate(cand Candidate) error { + if cand == nil { return nil } - // Cannot check for network yet because it might not be applied - // when mDNS hostname is used. - if c.TCPType() == TCPTypeActive { - // TCP Candidates with TCP type active will probe server passive ones, so - // no need to do anything with them. - a.log.Infof("Ignoring remote candidate with tcpType active: %s", c) + // TCP Candidates with TCP type active will probe server passive ones, so + // no need to do anything with them. + if cand.TCPType() == TCPTypeActive { + a.log.Infof("Ignoring remote candidate with tcpType active: %s", cand) + return nil } // If we have a mDNS Candidate lets fully resolve it before adding it locally - if c.Type() == CandidateTypeHost && strings.HasSuffix(c.Address(), ".local") { + if cand.Type() == CandidateTypeHost && strings.HasSuffix(cand.Address(), ".local") { if a.mDNSMode == MulticastDNSModeDisabled { - a.log.Warnf("Remote mDNS candidate added, but mDNS is disabled: (%s)", c.Address()) + a.log.Warnf("Remote mDNS candidate added, but mDNS is disabled: (%s)", cand.Address()) + return nil } - hostCandidate, ok := c.(*CandidateHost) + hostCandidate, ok := cand.(*CandidateHost) if !ok { return ErrAddressParseFailed } go a.resolveAndAddMulticastCandidate(hostCandidate) + return nil } go func() { - if err := a.run(a.context(), func(ctx context.Context, agent *Agent) { - agent.addRemoteCandidate(c) + if err := a.loop.Run(a.loop, func(_ context.Context) { + // nolint: contextcheck + a.addRemoteCandidate(cand) }); err != nil { - a.log.Warnf("Failed to add remote candidate %s: %v", c.Address(), err) + a.log.Warnf("Failed to add remote candidate %s: %v", cand.Address(), err) + return } }() + return nil } -func (a *Agent) resolveAndAddMulticastCandidate(c *CandidateHost) { +func (a *Agent) resolveAndAddMulticastCandidate(cand *CandidateHost) { if a.mDNSConn == nil { return } - _, src, err := a.mDNSConn.Query(c.context(), c.Address()) + + _, src, err := a.mDNSConn.QueryAddr(cand.context(), cand.Address()) if err != nil { - a.log.Warnf("Failed to discover mDNS candidate %s: %v", c.Address(), err) + a.log.Warnf("Failed to discover mDNS candidate %s: %v", cand.Address(), err) + return } - ip, ipOk := parseMulticastAnswerAddr(src) - if !ipOk { - a.log.Warnf("Failed to discover mDNS candidate %s: failed to parse IP", c.Address()) + if err = cand.setIPAddr(src); err != nil { + a.log.Warnf("Failed to discover mDNS candidate %s: %v", cand.Address(), err) + return } - if err = c.setIP(ip); err != nil { - a.log.Warnf("Failed to discover mDNS candidate %s: %v", c.Address(), err) - return - } - - if err = a.run(a.context(), func(ctx context.Context, agent *Agent) { - agent.addRemoteCandidate(c) + if err = a.loop.Run(a.loop, func(_ context.Context) { + // nolint: contextcheck + a.addRemoteCandidate(cand) }); err != nil { - a.log.Warnf("Failed to add mDNS candidate %s: %v", c.Address(), err) + a.log.Warnf("Failed to add mDNS candidate %s: %v", cand.Address(), err) + return } } @@ -723,68 +683,158 @@ func (a *Agent) requestConnectivityCheck() { } } -// addRemoteCandidate assumes you are holding the lock (must be execute using a.run) -func (a *Agent) addRemoteCandidate(c Candidate) { - set := a.remoteCandidates[c.NetworkType()] +func (a *Agent) addRemotePassiveTCPCandidate(remoteCandidate Candidate) { + _, localIPs, err := localInterfaces( + a.net, + a.interfaceFilter, + a.ipFilter, + []NetworkType{remoteCandidate.NetworkType()}, + a.includeLoopback, + ) + if err != nil { + a.log.Warnf("Failed to iterate local interfaces, host candidates will not be gathered %s", err) + + return + } + + for i := range localIPs { + ip, _, _, err := parseAddr(remoteCandidate.addr()) + if err != nil { + a.log.Warnf("Failed to parse address: %s; error: %s", remoteCandidate.addr(), err) + + continue + } + + conn := newActiveTCPConn( + a.loop, + net.JoinHostPort(localIPs[i].String(), "0"), + netip.AddrPortFrom(ip, uint16(remoteCandidate.Port())), //nolint:gosec // G115, no overflow, a port + a.log, + ) + + tcpAddr, ok := conn.LocalAddr().(*net.TCPAddr) + if !ok { + closeConnAndLog(conn, a.log, "Failed to create Active ICE-TCP Candidate: %v", errInvalidAddress) + + continue + } + + localCandidate, err := NewCandidateHost(&CandidateHostConfig{ + Network: remoteCandidate.NetworkType().String(), + Address: localIPs[i].String(), + Port: tcpAddr.Port, + Component: ComponentRTP, + TCPType: TCPTypeActive, + }) + if err != nil { + closeConnAndLog(conn, a.log, "Failed to create Active ICE-TCP Candidate: %v", err) + + continue + } + + localCandidate.start(a, conn, a.startedCh) + a.localCandidates[localCandidate.NetworkType()] = append( + a.localCandidates[localCandidate.NetworkType()], + localCandidate, + ) + a.candidateNotifier.EnqueueCandidate(localCandidate) + + a.addPair(localCandidate, remoteCandidate) + } +} + +// addRemoteCandidate assumes you are holding the lock (must be execute using a.run). +func (a *Agent) addRemoteCandidate(cand Candidate) { //nolint:cyclop + set := a.remoteCandidates[cand.NetworkType()] for _, candidate := range set { - if candidate.Equal(c) { + if candidate.Equal(cand) { return } } - set = append(set, c) - a.remoteCandidates[c.NetworkType()] = set + acceptRemotePassiveTCPCandidate := false + // Assert that TCP4 or TCP6 is a enabled NetworkType locally + if !a.disableActiveTCP && cand.TCPType() == TCPTypePassive { + for _, networkType := range a.networkTypes { + if cand.NetworkType() == networkType { + acceptRemotePassiveTCPCandidate = true + } + } + } - if localCandidates, ok := a.localCandidates[c.NetworkType()]; ok { - for _, localCandidate := range localCandidates { - a.addPair(localCandidate, c) + if acceptRemotePassiveTCPCandidate { + a.addRemotePassiveTCPCandidate(cand) + } + + set = append(set, cand) + a.remoteCandidates[cand.NetworkType()] = set + + if cand.TCPType() != TCPTypePassive { + if localCandidates, ok := a.localCandidates[cand.NetworkType()]; ok { + for _, localCandidate := range localCandidates { + a.addPair(localCandidate, cand) + } } } a.requestConnectivityCheck() } -func (a *Agent) addCandidate(ctx context.Context, c Candidate, candidateConn net.PacketConn) error { - return a.run(ctx, func(ctx context.Context, agent *Agent) { - set := a.localCandidates[c.NetworkType()] +func (a *Agent) addCandidate(ctx context.Context, cand Candidate, candidateConn net.PacketConn) error { + return a.loop.Run(ctx, func(context.Context) { + set := a.localCandidates[cand.NetworkType()] for _, candidate := range set { - if candidate.Equal(c) { - a.log.Debugf("Ignore duplicate candidate: %s", c.String()) - if err := c.close(); err != nil { + if candidate.Equal(cand) { + a.log.Debugf("Ignore duplicate candidate: %s", cand) + if err := cand.close(); err != nil { a.log.Warnf("Failed to close duplicate candidate: %v", err) } if err := candidateConn.Close(); err != nil { a.log.Warnf("Failed to close duplicate candidate connection: %v", err) } + return } } - c.start(a, candidateConn, a.startedCh) + a.setCandidateExtensions(cand) + cand.start(a, candidateConn, a.startedCh) - set = append(set, c) - a.localCandidates[c.NetworkType()] = set + set = append(set, cand) + a.localCandidates[cand.NetworkType()] = set - if remoteCandidates, ok := a.remoteCandidates[c.NetworkType()]; ok { + if remoteCandidates, ok := a.remoteCandidates[cand.NetworkType()]; ok { for _, remoteCandidate := range remoteCandidates { - a.addPair(c, remoteCandidate) + a.addPair(cand, remoteCandidate) } } a.requestConnectivityCheck() - a.chanCandidate <- c + if !cand.filterForLocationTracking() { + a.candidateNotifier.EnqueueCandidate(cand) + } }) } -// GetLocalCandidates returns the local candidates -func (a *Agent) GetLocalCandidates() ([]Candidate, error) { +func (a *Agent) setCandidateExtensions(cand Candidate) { + err := cand.AddExtension(CandidateExtension{ + Key: "ufrag", + Value: a.localUfrag, + }) + if err != nil { + a.log.Errorf("Failed to add ufrag extension to candidate: %v", err) + } +} + +// GetRemoteCandidates returns the remote candidates. +func (a *Agent) GetRemoteCandidates() ([]Candidate, error) { var res []Candidate - err := a.run(a.context(), func(ctx context.Context, agent *Agent) { + err := a.loop.Run(a.loop, func(_ context.Context) { var candidates []Candidate - for _, set := range agent.localCandidates { + for _, set := range a.remoteCandidates { candidates = append(candidates, set...) } res = candidates @@ -796,33 +846,58 @@ func (a *Agent) GetLocalCandidates() ([]Candidate, error) { return res, nil } -// GetLocalUserCredentials returns the local user credentials +// GetLocalCandidates returns the local candidates. +func (a *Agent) GetLocalCandidates() ([]Candidate, error) { + var res []Candidate + + err := a.loop.Run(a.loop, func(_ context.Context) { + var candidates []Candidate + for _, set := range a.localCandidates { + for _, c := range set { + if c.filterForLocationTracking() { + continue + } + candidates = append(candidates, c) + } + } + res = candidates + }) + if err != nil { + return nil, err + } + + return res, nil +} + +// GetLocalUserCredentials returns the local user credentials. func (a *Agent) GetLocalUserCredentials() (frag string, pwd string, err error) { valSet := make(chan struct{}) - err = a.run(a.context(), func(ctx context.Context, agent *Agent) { - frag = agent.localUfrag - pwd = agent.localPwd + err = a.loop.Run(a.loop, func(_ context.Context) { + frag = a.localUfrag + pwd = a.localPwd close(valSet) }) if err == nil { <-valSet } + return } -// GetRemoteUserCredentials returns the remote user credentials +// GetRemoteUserCredentials returns the remote user credentials. func (a *Agent) GetRemoteUserCredentials() (frag string, pwd string, err error) { valSet := make(chan struct{}) - err = a.run(a.context(), func(ctx context.Context, agent *Agent) { - frag = agent.remoteUfrag - pwd = agent.remotePwd + err = a.loop.Run(a.loop, func(_ context.Context) { + frag = a.remoteUfrag + pwd = a.remotePwd close(valSet) }) if err == nil { <-valSet } + return } @@ -838,31 +913,35 @@ func (a *Agent) removeUfragFromMux() { } } -// Close cleans up the Agent +// Close cleans up the Agent. func (a *Agent) Close() error { - if err := a.ok(); err != nil { - return err - } + return a.close(false) +} - a.afterRun(func(context.Context) { - a.gatherCandidateCancel() - if a.gatherCandidateDone != nil { - <-a.gatherCandidateDone - } - }) - a.err.Store(ErrClosed) +// GracefulClose cleans up the Agent and waits for any goroutines it started +// to complete. This is only safe to call outside of Agent callbacks or if in a callback, +// in its own goroutine. +func (a *Agent) GracefulClose() error { + return a.close(true) +} - a.removeUfragFromMux() +func (a *Agent) close(graceful bool) error { + // the loop is safe to wait on no matter what + a.loop.Close() + + // but we are in less control of the notifiers, so we will + // pass through `graceful`. + a.connectionStateNotifier.Close(graceful) + a.candidateNotifier.Close(graceful) + a.selectedCandidatePairNotifier.Close(graceful) - close(a.done) - <-a.taskLoopDone return nil } // Remove all candidates. This closes any listening sockets // and removes both the local and remote candidate lists. // -// This is used for restarts, failures and on close +// This is used for restarts, failures and on close. func (a *Agent) deleteAllCandidates() { for net, cs := range a.localCandidates { for _, c := range cs { @@ -883,9 +962,10 @@ func (a *Agent) deleteAllCandidates() { } func (a *Agent) findRemoteCandidate(networkType NetworkType, addr net.Addr) Candidate { - ip, port, _, ok := parseAddr(addr) - if !ok { - a.log.Warnf("Failed to parse address: %s", addr) + ip, port, _, err := parseAddr(addr) + if err != nil { + a.log.Warnf("Failed to parse address: %s; error: %s", addr, err) + return nil } @@ -895,35 +975,42 @@ func (a *Agent) findRemoteCandidate(networkType NetworkType, addr net.Addr) Cand return c } } + return nil } -func (a *Agent) sendBindingRequest(m *stun.Message, local, remote Candidate) { - a.log.Tracef("ping STUN from %s to %s", local.String(), remote.String()) +func (a *Agent) sendBindingRequest(msg *stun.Message, local, remote Candidate) { + a.log.Tracef("Ping STUN from %s to %s", local, remote) a.invalidatePendingBindingRequests(time.Now()) a.pendingBindingRequests = append(a.pendingBindingRequests, bindingRequest{ timestamp: time.Now(), - transactionID: m.TransactionID, + transactionID: msg.TransactionID, destination: remote.addr(), - isUseCandidate: m.Contains(stun.AttrUseCandidate), + isUseCandidate: msg.Contains(stun.AttrUseCandidate), }) - a.sendSTUN(m, local, remote) + if pair := a.findPair(local, remote); pair != nil { + pair.UpdateRequestSent() + } else { + a.log.Warnf("Failed to find pair for add binding request from %s to %s", local, remote) + } + a.sendSTUN(msg, local, remote) } func (a *Agent) sendBindingSuccess(m *stun.Message, local, remote Candidate) { base := remote - ip, port, _, ok := parseAddr(base.addr()) - if !ok { - a.log.Warnf("Failed to parse address: %s", base.addr()) + ip, port, _, err := parseAddr(base.addr()) + if err != nil { + a.log.Warnf("Failed to parse address: %s; error: %s", base.addr(), err) + return } if out, err := stun.Build(m, stun.BindingSuccess, &stun.XORMappedAddress{ - IP: ip, + IP: ip.AsSlice(), Port: port, }, stun.NewShortTermIntegrity(a.localPwd), @@ -931,6 +1018,11 @@ func (a *Agent) sendBindingSuccess(m *stun.Message, local, remote Candidate) { ); err != nil { a.log.Warnf("Failed to handle inbound ICE from: %s to: %s error: %s", local, remote, err) } else { + if pair := a.findPair(local, remote); pair != nil { + pair.UpdateResponseSent() + } else { + a.log.Warnf("Failed to find pair for add binding response from %s to %s", local, remote) + } a.sendSTUN(out, local, remote) } } @@ -957,75 +1049,93 @@ func (a *Agent) invalidatePendingBindingRequests(filterTime time.Time) { } // Assert that the passed TransactionID is in our pendingBindingRequests and returns the destination -// If the bindingRequest was valid remove it from our pending cache -func (a *Agent) handleInboundBindingSuccess(id [stun.TransactionIDSize]byte) (bool, *bindingRequest) { +// If the bindingRequest was valid remove it from our pending cache. +func (a *Agent) handleInboundBindingSuccess(id [stun.TransactionIDSize]byte) (bool, *bindingRequest, time.Duration) { a.invalidatePendingBindingRequests(time.Now()) for i := range a.pendingBindingRequests { if a.pendingBindingRequests[i].transactionID == id { validBindingRequest := a.pendingBindingRequests[i] a.pendingBindingRequests = append(a.pendingBindingRequests[:i], a.pendingBindingRequests[i+1:]...) - return true, &validBindingRequest + + return true, &validBindingRequest, time.Since(validBindingRequest.timestamp) } } - return false, nil + + return false, nil, 0 } -// handleInbound processes STUN traffic from a remote candidate -func (a *Agent) handleInbound(m *stun.Message, local Candidate, remote net.Addr) { //nolint:gocognit +// handleInbound processes STUN traffic from a remote candidate. +func (a *Agent) handleInbound(msg *stun.Message, local Candidate, remote net.Addr) { //nolint:gocognit,cyclop var err error - if m == nil || local == nil { + if msg == nil || local == nil { return } - if m.Type.Method != stun.MethodBinding || - !(m.Type.Class == stun.ClassSuccessResponse || - m.Type.Class == stun.ClassRequest || - m.Type.Class == stun.ClassIndication) { - a.log.Tracef("unhandled STUN from %s to %s class(%s) method(%s)", remote, local, m.Type.Class, m.Type.Method) + if msg.Type.Method != stun.MethodBinding || + !(msg.Type.Class == stun.ClassSuccessResponse || + msg.Type.Class == stun.ClassRequest || + msg.Type.Class == stun.ClassIndication) { + a.log.Tracef("Unhandled STUN from %s to %s class(%s) method(%s)", remote, local, msg.Type.Class, msg.Type.Method) + return } if a.isControlling { - if m.Contains(stun.AttrICEControlling) { + if msg.Contains(stun.AttrICEControlling) { a.log.Debug("Inbound STUN message: isControlling && a.isControlling == true") + return - } else if m.Contains(stun.AttrUseCandidate) { + } else if msg.Contains(stun.AttrUseCandidate) { a.log.Debug("Inbound STUN message: useCandidate && a.isControlling == true") + return } } else { - if m.Contains(stun.AttrICEControlled) { + if msg.Contains(stun.AttrICEControlled) { a.log.Debug("Inbound STUN message: isControlled && a.isControlling == false") + return } } remoteCandidate := a.findRemoteCandidate(local.NetworkType(), remote) - if m.Type.Class == stun.ClassSuccessResponse { - if err = stun.MessageIntegrity([]byte(a.remotePwd)).Check(m); err != nil { + if msg.Type.Class == stun.ClassSuccessResponse { //nolint:nestif + if err = stun.MessageIntegrity([]byte(a.remotePwd)).Check(msg); err != nil { a.log.Warnf("Discard message from (%s), %v", remote, err) + return } if remoteCandidate == nil { a.log.Warnf("Discard success message from (%s), no such remote", remote) + return } - a.selector.HandleSuccessResponse(m, local, remoteCandidate, remote) - } else if m.Type.Class == stun.ClassRequest { - if err = stunx.AssertUsername(m, a.localUfrag+":"+a.remoteUfrag); err != nil { + a.selector.HandleSuccessResponse(msg, local, remoteCandidate, remote) + } else if msg.Type.Class == stun.ClassRequest { + a.log.Tracef( + "Inbound STUN (Request) from %s to %s, useCandidate: %v", + remote, + local, + msg.Contains(stun.AttrUseCandidate), + ) + + if err = stunx.AssertUsername(msg, a.localUfrag+":"+a.remoteUfrag); err != nil { a.log.Warnf("Discard message from (%s), %v", remote, err) + return - } else if err = stun.MessageIntegrity([]byte(a.localPwd)).Check(m); err != nil { + } else if err = stun.MessageIntegrity([]byte(a.localPwd)).Check(msg); err != nil { a.log.Warnf("Discard message from (%s), %v", remote, err) + return } if remoteCandidate == nil { - ip, port, networkType, ok := parseAddr(remote) - if !ok { - a.log.Errorf("Failed to create parse remote net.Addr when creating remote prflx candidate") + ip, port, networkType, err := parseAddr(remote) + if err != nil { + a.log.Errorf("Failed to create parse remote net.Addr when creating remote prflx candidate: %s", err) + return } @@ -1041,6 +1151,7 @@ func (a *Agent) handleInbound(m *stun.Message, local Candidate, remote net.Addr) prflxCandidate, err := NewCandidatePeerReflexive(&prflxCandidateConfig) if err != nil { a.log.Errorf("Failed to create new remote prflx candidate (%s)", err) + return } remoteCandidate = prflxCandidate @@ -1049,9 +1160,7 @@ func (a *Agent) handleInbound(m *stun.Message, local Candidate, remote net.Addr) a.addRemoteCandidate(remoteCandidate) } - a.log.Tracef("inbound STUN (Request) from %s to %s", remote.String(), local.String()) - - a.selector.HandleBindingRequest(m, local, remoteCandidate) + a.selector.HandleBindingRequest(msg, local, remoteCandidate) } if remoteCandidate != nil { @@ -1060,10 +1169,10 @@ func (a *Agent) handleInbound(m *stun.Message, local Candidate, remote net.Addr) } // validateNonSTUNTraffic processes non STUN traffic from a remote candidate, -// and returns true if it is an actual remote candidate +// and returns true if it is an actual remote candidate. func (a *Agent) validateNonSTUNTraffic(local Candidate, remote net.Addr) (Candidate, bool) { var remoteCandidate Candidate - if err := a.run(local.context(), func(ctx context.Context, agent *Agent) { + if err := a.loop.Run(local.context(), func(context.Context) { remoteCandidate = a.findRemoteCandidate(local.NetworkType(), remote) if remoteCandidate != nil { remoteCandidate.seen(false) @@ -1075,7 +1184,7 @@ func (a *Agent) validateNonSTUNTraffic(local Candidate, remote net.Addr) (Candid return remoteCandidate, remoteCandidate != nil } -// GetSelectedCandidatePair returns the selected pair or nil if there is none +// GetSelectedCandidatePair returns the selected pair or nil if there is none. func (a *Agent) GetSelectedCandidatePair() (*CandidatePair, error) { selectedPair := a.getSelectedPair() if selectedPair == nil { @@ -1111,7 +1220,7 @@ func (a *Agent) closeMulticastConn() { } } -// SetRemoteCredentials sets the credentials of the remote agent +// SetRemoteCredentials sets the credentials of the remote agent. func (a *Agent) SetRemoteCredentials(remoteUfrag, remotePwd string) error { switch { case remoteUfrag == "": @@ -1120,9 +1229,9 @@ func (a *Agent) SetRemoteCredentials(remoteUfrag, remotePwd string) error { return ErrRemotePwdEmpty } - return a.run(a.context(), func(ctx context.Context, agent *Agent) { - agent.remoteUfrag = remoteUfrag - agent.remotePwd = remotePwd + return a.loop.Run(a.loop, func(_ context.Context) { + a.remoteUfrag = remoteUfrag + a.remotePwd = remotePwd }) } @@ -1133,7 +1242,7 @@ func (a *Agent) SetRemoteCredentials(remoteUfrag, remotePwd string) error { // cancel it. // After a Restart, the user must then call GatherCandidates explicitly // to start generating new ones. -func (a *Agent) Restart(ufrag, pwd string) error { +func (a *Agent) Restart(ufrag, pwd string) error { //nolint:cyclop if ufrag == "" { var err error ufrag, err = generateUFrag() @@ -1157,17 +1266,17 @@ func (a *Agent) Restart(ufrag, pwd string) error { } var err error - if runErr := a.run(a.context(), func(ctx context.Context, agent *Agent) { - if agent.gatheringState == GatheringStateGathering { - agent.gatherCandidateCancel() + if runErr := a.loop.Run(a.loop, func(_ context.Context) { + if a.gatheringState == GatheringStateGathering { + a.gatherCandidateCancel() } // Clear all agent needed to take back to fresh state a.removeUfragFromMux() - agent.localUfrag = ufrag - agent.localPwd = pwd - agent.remoteUfrag = "" - agent.remotePwd = "" + a.localUfrag = ufrag + a.localPwd = pwd + a.remoteUfrag = "" + a.remotePwd = "" a.gatheringState = GatheringStateNew a.checklist = make([]*CandidatePair, 0) a.pendingBindingRequests = make([]bindingRequest, 0) @@ -1185,14 +1294,15 @@ func (a *Agent) Restart(ufrag, pwd string) error { }); runErr != nil { return runErr } + return err } func (a *Agent) setGatheringState(newState GatheringState) error { done := make(chan struct{}) - if err := a.run(a.context(), func(ctx context.Context, agent *Agent) { + if err := a.loop.Run(a.loop, func(context.Context) { if a.gatheringState != newState && newState == GatheringStateComplete { - a.chanCandidate <- nil + a.candidateNotifier.EnqueueCandidate(nil) } a.gatheringState = newState @@ -1202,5 +1312,10 @@ func (a *Agent) setGatheringState(newState GatheringState) error { } <-done + return nil } + +func (a *Agent) needsToCheckPriorityOnNominated() bool { + return !a.lite || a.enableUseCandidateCheckPriority +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/agent_config.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/agent_config.go similarity index 61% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/agent_config.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/agent_config.go index f5897cd4a..708aab569 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/agent_config.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/agent_config.go @@ -8,43 +8,50 @@ import ( "time" "github.com/pion/logging" - "github.com/pion/stun" - "github.com/pion/transport/v2" + "github.com/pion/stun/v3" + "github.com/pion/transport/v3" "golang.org/x/net/proxy" ) const ( - // defaultCheckInterval is the interval at which the agent performs candidate checks in the connecting phase + // defaultCheckInterval is the interval at which the agent performs candidate checks in the connecting phase. defaultCheckInterval = 200 * time.Millisecond - // keepaliveInterval used to keep candidates alive + // keepaliveInterval used to keep candidates alive. defaultKeepaliveInterval = 2 * time.Second - // defaultDisconnectedTimeout is the default time till an Agent transitions disconnected + // defaultDisconnectedTimeout is the default time till an Agent transitions disconnected. defaultDisconnectedTimeout = 5 * time.Second - // defaultFailedTimeout is the default time till an Agent transitions to failed after disconnected + // defaultFailedTimeout is the default time till an Agent transitions to failed after disconnected. defaultFailedTimeout = 25 * time.Second - // defaultHostAcceptanceMinWait is the wait time before nominating a host candidate + // defaultHostAcceptanceMinWait is the wait time before nominating a host candidate. defaultHostAcceptanceMinWait = 0 - // defaultSrflxAcceptanceMinWait is the wait time before nominating a srflx candidate + // defaultSrflxAcceptanceMinWait is the wait time before nominating a srflx candidate. defaultSrflxAcceptanceMinWait = 500 * time.Millisecond - // defaultPrflxAcceptanceMinWait is the wait time before nominating a prflx candidate + // defaultPrflxAcceptanceMinWait is the wait time before nominating a prflx candidate. defaultPrflxAcceptanceMinWait = 1000 * time.Millisecond - // defaultRelayAcceptanceMinWait is the wait time before nominating a relay candidate + // defaultRelayAcceptanceMinWait is the wait time before nominating a relay candidate. defaultRelayAcceptanceMinWait = 2000 * time.Millisecond - // defaultMaxBindingRequests is the maximum number of binding requests before considering a pair failed + // defaultSTUNGatherTimeout is the wait time for STUN responses. + defaultSTUNGatherTimeout = 5 * time.Second + + // defaultMaxBindingRequests is the maximum number of binding requests before considering a pair failed. defaultMaxBindingRequests = 7 - // maxBufferSize is the number of bytes that can be buffered before we start to error + // TCPPriorityOffset is a number which is subtracted from the default (UDP) candidate type preference + // for host, srflx and prfx candidate types. + defaultTCPPriorityOffset = 27 + + // maxBufferSize is the number of bytes that can be buffered before we start to error. maxBufferSize = 1000 * 1000 // 1MB - // maxBindingRequestTimeout is the wait time before binding requests can be deleted + // maxBindingRequestTimeout is the wait time before binding requests can be deleted. maxBindingRequestTimeout = 4000 * time.Millisecond ) @@ -53,7 +60,7 @@ func defaultCandidateTypes() []CandidateType { } // AgentConfig collects the arguments to ice.Agent construction into -// a single structure, for future-proofness of the interface +// a single structure, for future-proofness of the interface. type AgentConfig struct { Urls []*stun.URI @@ -84,7 +91,7 @@ type AgentConfig struct { // KeepaliveInterval determines how often should we send ICE // keepalives (should be less then connectiontimeout above) - // when this is nil, it defaults to 10 seconds. + // when this is nil, it defaults to 2 seconds. // A keepalive interval of 0 means we never send keepalive packets KeepaliveInterval *time.Duration @@ -126,12 +133,14 @@ type AgentConfig struct { // HostAcceptanceMinWait specify a minimum wait time before selecting host candidates HostAcceptanceMinWait *time.Duration - // HostAcceptanceMinWait specify a minimum wait time before selecting srflx candidates + // SrflxAcceptanceMinWait specify a minimum wait time before selecting srflx candidates SrflxAcceptanceMinWait *time.Duration - // HostAcceptanceMinWait specify a minimum wait time before selecting prflx candidates + // PrflxAcceptanceMinWait specify a minimum wait time before selecting prflx candidates PrflxAcceptanceMinWait *time.Duration - // HostAcceptanceMinWait specify a minimum wait time before selecting relay candidates + // RelayAcceptanceMinWait specify a minimum wait time before selecting relay candidates RelayAcceptanceMinWait *time.Duration + // STUNGatherTimeout specify a minimum wait time for STUN responses + STUNGatherTimeout *time.Duration // Net is the our abstracted network interface for internal development purpose only // (see https://github.com/pion/transport) @@ -139,11 +148,11 @@ type AgentConfig struct { // InterfaceFilter is a function that you can use in order to whitelist or blacklist // the interfaces which are used to gather ICE candidates. - InterfaceFilter func(string) bool + InterfaceFilter func(string) (keep bool) // IPFilter is a function that you can use in order to whitelist or blacklist // the ips which are used to gather ICE candidates. - IPFilter func(net.IP) bool + IPFilter func(net.IP) (keep bool) // InsecureSkipVerify controls if self-signed certificates are accepted when connecting // to TURN servers via TLS or DTLS @@ -174,99 +183,137 @@ type AgentConfig struct { // Include loopback addresses in the candidate list. IncludeLoopback bool + + // TCPPriorityOffset is a number which is subtracted from the default (UDP) candidate type preference + // for host, srflx and prfx candidate types. It helps to configure relative preference of UDP candidates + // against TCP ones. Relay candidates for TCP and UDP are always 0 and not affected by this setting. + // When this is nil, defaultTCPPriorityOffset is used. + TCPPriorityOffset *uint16 + + // DisableActiveTCP can be used to disable Active TCP candidates. Otherwise when TCP is enabled + // Active TCP candidates will be created when a new passive TCP remote candidate is added. + DisableActiveTCP bool + + // BindingRequestHandler allows applications to perform logic on incoming STUN Binding Requests + // This was implemented to allow users to + // * Log incoming Binding Requests for debugging + // * Implement draft-thatcher-ice-renomination + // * Implement custom CandidatePair switching logic + BindingRequestHandler func(m *stun.Message, local, remote Candidate, pair *CandidatePair) bool + + // EnableUseCandidateCheckPriority can be used to enable checking for equal or higher priority to + // switch selected candidate pair if the peer requests USE-CANDIDATE and agent is a lite agent. + // This is disabled by default, i. e. when peer requests USE-CANDIDATE, the selected pair will be + // switched to that irrespective of relative priority between current selected pair + // and priority of the pair being switched to. + EnableUseCandidateCheckPriority bool } -// initWithDefaults populates an agent and falls back to defaults if fields are unset -func (config *AgentConfig) initWithDefaults(a *Agent) { +// initWithDefaults populates an agent and falls back to defaults if fields are unset. +func (config *AgentConfig) initWithDefaults(agent *Agent) { //nolint:cyclop if config.MaxBindingRequests == nil { - a.maxBindingRequests = defaultMaxBindingRequests + agent.maxBindingRequests = defaultMaxBindingRequests } else { - a.maxBindingRequests = *config.MaxBindingRequests + agent.maxBindingRequests = *config.MaxBindingRequests } if config.HostAcceptanceMinWait == nil { - a.hostAcceptanceMinWait = defaultHostAcceptanceMinWait + agent.hostAcceptanceMinWait = defaultHostAcceptanceMinWait } else { - a.hostAcceptanceMinWait = *config.HostAcceptanceMinWait + agent.hostAcceptanceMinWait = *config.HostAcceptanceMinWait } if config.SrflxAcceptanceMinWait == nil { - a.srflxAcceptanceMinWait = defaultSrflxAcceptanceMinWait + agent.srflxAcceptanceMinWait = defaultSrflxAcceptanceMinWait } else { - a.srflxAcceptanceMinWait = *config.SrflxAcceptanceMinWait + agent.srflxAcceptanceMinWait = *config.SrflxAcceptanceMinWait } if config.PrflxAcceptanceMinWait == nil { - a.prflxAcceptanceMinWait = defaultPrflxAcceptanceMinWait + agent.prflxAcceptanceMinWait = defaultPrflxAcceptanceMinWait } else { - a.prflxAcceptanceMinWait = *config.PrflxAcceptanceMinWait + agent.prflxAcceptanceMinWait = *config.PrflxAcceptanceMinWait } if config.RelayAcceptanceMinWait == nil { - a.relayAcceptanceMinWait = defaultRelayAcceptanceMinWait + agent.relayAcceptanceMinWait = defaultRelayAcceptanceMinWait } else { - a.relayAcceptanceMinWait = *config.RelayAcceptanceMinWait + agent.relayAcceptanceMinWait = *config.RelayAcceptanceMinWait + } + + if config.STUNGatherTimeout == nil { + agent.stunGatherTimeout = defaultSTUNGatherTimeout + } else { + agent.stunGatherTimeout = *config.STUNGatherTimeout + } + + if config.TCPPriorityOffset == nil { + agent.tcpPriorityOffset = defaultTCPPriorityOffset + } else { + agent.tcpPriorityOffset = *config.TCPPriorityOffset } if config.DisconnectedTimeout == nil { - a.disconnectedTimeout = defaultDisconnectedTimeout + agent.disconnectedTimeout = defaultDisconnectedTimeout } else { - a.disconnectedTimeout = *config.DisconnectedTimeout + agent.disconnectedTimeout = *config.DisconnectedTimeout } if config.FailedTimeout == nil { - a.failedTimeout = defaultFailedTimeout + agent.failedTimeout = defaultFailedTimeout } else { - a.failedTimeout = *config.FailedTimeout + agent.failedTimeout = *config.FailedTimeout } if config.KeepaliveInterval == nil { - a.keepaliveInterval = defaultKeepaliveInterval + agent.keepaliveInterval = defaultKeepaliveInterval } else { - a.keepaliveInterval = *config.KeepaliveInterval + agent.keepaliveInterval = *config.KeepaliveInterval } if config.CheckInterval == nil { - a.checkInterval = defaultCheckInterval + agent.checkInterval = defaultCheckInterval } else { - a.checkInterval = *config.CheckInterval + agent.checkInterval = *config.CheckInterval } - if config.CandidateTypes == nil || len(config.CandidateTypes) == 0 { - a.candidateTypes = defaultCandidateTypes() + if len(config.CandidateTypes) == 0 { + agent.candidateTypes = defaultCandidateTypes() } else { - a.candidateTypes = config.CandidateTypes + agent.candidateTypes = config.CandidateTypes } } -func (config *AgentConfig) initExtIPMapping(a *Agent) error { +func (config *AgentConfig) initExtIPMapping(agent *Agent) error { //nolint:cyclop var err error - a.extIPMapper, err = newExternalIPMapper(config.NAT1To1IPCandidateType, config.NAT1To1IPs) + agent.extIPMapper, err = newExternalIPMapper(config.NAT1To1IPCandidateType, config.NAT1To1IPs) if err != nil { return err } - if a.extIPMapper == nil { + if agent.extIPMapper == nil { return nil // This may happen when config.NAT1To1IPs is an empty array } - if a.extIPMapper.candidateType == CandidateTypeHost { - if a.mDNSMode == MulticastDNSModeQueryAndGather { + if agent.extIPMapper.candidateType == CandidateTypeHost { //nolint:nestif + if agent.mDNSMode == MulticastDNSModeQueryAndGather { return ErrMulticastDNSWithNAT1To1IPMapping } candiHostEnabled := false - for _, candiType := range a.candidateTypes { + for _, candiType := range agent.candidateTypes { if candiType == CandidateTypeHost { candiHostEnabled = true + break } } if !candiHostEnabled { return ErrIneffectiveNAT1To1IPMappingHost } - } else if a.extIPMapper.candidateType == CandidateTypeServerReflexive { + } else if agent.extIPMapper.candidateType == CandidateTypeServerReflexive { candiSrflxEnabled := false - for _, candiType := range a.candidateTypes { + for _, candiType := range agent.candidateTypes { if candiType == CandidateTypeServerReflexive { candiSrflxEnabled = true + break } } @@ -274,5 +321,6 @@ func (config *AgentConfig) initExtIPMapping(a *Agent) error { return ErrIneffectiveNAT1To1IPMappingSrflx } } + return nil } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/agent_handlers.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/agent_handlers.go new file mode 100644 index 000000000..823514e44 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/agent_handlers.go @@ -0,0 +1,190 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + +package ice + +import "sync" + +// OnConnectionStateChange sets a handler that is fired when the connection state changes. +func (a *Agent) OnConnectionStateChange(f func(ConnectionState)) error { + a.onConnectionStateChangeHdlr.Store(f) + + return nil +} + +// OnSelectedCandidatePairChange sets a handler that is fired when the final candidate. +// pair is selected. +func (a *Agent) OnSelectedCandidatePairChange(f func(Candidate, Candidate)) error { + a.onSelectedCandidatePairChangeHdlr.Store(f) + + return nil +} + +// OnCandidate sets a handler that is fired when new candidates gathered. When +// the gathering process complete the last candidate is nil. +func (a *Agent) OnCandidate(f func(Candidate)) error { + a.onCandidateHdlr.Store(f) + + return nil +} + +func (a *Agent) onSelectedCandidatePairChange(p *CandidatePair) { + if h, ok := a.onSelectedCandidatePairChangeHdlr.Load().(func(Candidate, Candidate)); ok && h != nil { + h(p.Local, p.Remote) + } +} + +func (a *Agent) onCandidate(c Candidate) { + if onCandidateHdlr, ok := a.onCandidateHdlr.Load().(func(Candidate)); ok && onCandidateHdlr != nil { + onCandidateHdlr(c) + } +} + +func (a *Agent) onConnectionStateChange(s ConnectionState) { + if hdlr, ok := a.onConnectionStateChangeHdlr.Load().(func(ConnectionState)); ok && hdlr != nil { + hdlr(s) + } +} + +type handlerNotifier struct { + sync.Mutex + running bool + notifiers sync.WaitGroup + + connectionStates []ConnectionState + connectionStateFunc func(ConnectionState) + + candidates []Candidate + candidateFunc func(Candidate) + + selectedCandidatePairs []*CandidatePair + candidatePairFunc func(*CandidatePair) + + // State for closing + done chan struct{} +} + +func (h *handlerNotifier) Close(graceful bool) { + if graceful { + // if we were closed ungracefully before, we now + // want ot wait. + defer h.notifiers.Wait() + } + + h.Lock() + + select { + case <-h.done: + h.Unlock() + + return + default: + } + close(h.done) + h.Unlock() +} + +func (h *handlerNotifier) EnqueueConnectionState(state ConnectionState) { + h.Lock() + defer h.Unlock() + + select { + case <-h.done: + return + default: + } + + notify := func() { + defer h.notifiers.Done() + for { + h.Lock() + if len(h.connectionStates) == 0 { + h.running = false + h.Unlock() + + return + } + notification := h.connectionStates[0] + h.connectionStates = h.connectionStates[1:] + h.Unlock() + h.connectionStateFunc(notification) + } + } + + h.connectionStates = append(h.connectionStates, state) + if !h.running { + h.running = true + h.notifiers.Add(1) + go notify() + } +} + +func (h *handlerNotifier) EnqueueCandidate(cand Candidate) { + h.Lock() + defer h.Unlock() + + select { + case <-h.done: + return + default: + } + + notify := func() { + defer h.notifiers.Done() + for { + h.Lock() + if len(h.candidates) == 0 { + h.running = false + h.Unlock() + + return + } + notification := h.candidates[0] + h.candidates = h.candidates[1:] + h.Unlock() + h.candidateFunc(notification) + } + } + + h.candidates = append(h.candidates, cand) + if !h.running { + h.running = true + h.notifiers.Add(1) + go notify() + } +} + +func (h *handlerNotifier) EnqueueSelectedCandidatePair(pair *CandidatePair) { + h.Lock() + defer h.Unlock() + + select { + case <-h.done: + return + default: + } + + notify := func() { + defer h.notifiers.Done() + for { + h.Lock() + if len(h.selectedCandidatePairs) == 0 { + h.running = false + h.Unlock() + + return + } + notification := h.selectedCandidatePairs[0] + h.selectedCandidatePairs = h.selectedCandidatePairs[1:] + h.Unlock() + h.candidatePairFunc(notification) + } + } + + h.selectedCandidatePairs = append(h.selectedCandidatePairs, pair) + if !h.running { + h.running = true + h.notifiers.Add(1) + go notify() + } +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/agent_stats.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/agent_stats.go new file mode 100644 index 000000000..c6b21f57e --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/agent_stats.go @@ -0,0 +1,183 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + +package ice + +import ( + "context" + "time" +) + +// GetCandidatePairsStats returns a list of candidate pair stats. +func (a *Agent) GetCandidatePairsStats() []CandidatePairStats { + var res []CandidatePairStats + err := a.loop.Run(a.loop, func(_ context.Context) { + result := make([]CandidatePairStats, 0, len(a.checklist)) + for _, cp := range a.checklist { + stat := CandidatePairStats{ + Timestamp: time.Now(), + LocalCandidateID: cp.Local.ID(), + RemoteCandidateID: cp.Remote.ID(), + State: cp.state, + Nominated: cp.nominated, + // PacketsSent uint32 + // PacketsReceived uint32 + // BytesSent uint64 + // BytesReceived uint64 + // LastPacketSentTimestamp time.Time + // LastPacketReceivedTimestamp time.Time + FirstRequestTimestamp: cp.FirstRequestSentAt(), + LastRequestTimestamp: cp.LastRequestSentAt(), + FirstResponseTimestamp: cp.FirstReponseReceivedAt(), + LastResponseTimestamp: cp.LastResponseReceivedAt(), + FirstRequestReceivedTimestamp: cp.FirstRequestReceivedAt(), + LastRequestReceivedTimestamp: cp.LastRequestReceivedAt(), + + TotalRoundTripTime: cp.TotalRoundTripTime(), + CurrentRoundTripTime: cp.CurrentRoundTripTime(), + // AvailableOutgoingBitrate float64 + // AvailableIncomingBitrate float64 + // CircuitBreakerTriggerCount uint32 + RequestsReceived: cp.RequestsReceived(), + RequestsSent: cp.RequestsSent(), + ResponsesReceived: cp.ResponsesReceived(), + ResponsesSent: cp.ResponsesSent(), + // RetransmissionsReceived uint64 + // RetransmissionsSent uint64 + // ConsentRequestsSent uint64 + // ConsentExpiredTimestamp time.Time + } + result = append(result, stat) + } + res = result + }) + if err != nil { + a.log.Errorf("Failed to get candidate pairs stats: %v", err) + + return []CandidatePairStats{} + } + + return res +} + +// GetSelectedCandidatePairStats returns a candidate pair stats for selected candidate pair. +// Returns false if there is no selected pair. +func (a *Agent) GetSelectedCandidatePairStats() (CandidatePairStats, bool) { + isAvailable := false + var res CandidatePairStats + err := a.loop.Run(a.loop, func(_ context.Context) { + sp := a.getSelectedPair() + if sp == nil { + return + } + + isAvailable = true + res = CandidatePairStats{ + Timestamp: time.Now(), + LocalCandidateID: sp.Local.ID(), + RemoteCandidateID: sp.Remote.ID(), + State: sp.state, + Nominated: sp.nominated, + // PacketsSent uint32 + // PacketsReceived uint32 + // BytesSent uint64 + // BytesReceived uint64 + // LastPacketSentTimestamp time.Time + // LastPacketReceivedTimestamp time.Time + // FirstRequestTimestamp time.Time + // LastRequestTimestamp time.Time + // LastResponseTimestamp time.Time + TotalRoundTripTime: sp.TotalRoundTripTime(), + CurrentRoundTripTime: sp.CurrentRoundTripTime(), + // AvailableOutgoingBitrate float64 + // AvailableIncomingBitrate float64 + // CircuitBreakerTriggerCount uint32 + // RequestsReceived uint64 + // RequestsSent uint64 + ResponsesReceived: sp.ResponsesReceived(), + // ResponsesSent uint64 + // RetransmissionsReceived uint64 + // RetransmissionsSent uint64 + // ConsentRequestsSent uint64 + // ConsentExpiredTimestamp time.Time + } + }) + if err != nil { + a.log.Errorf("Failed to get selected candidate pair stats: %v", err) + + return CandidatePairStats{}, false + } + + return res, isAvailable +} + +// GetLocalCandidatesStats returns a list of local candidates stats. +func (a *Agent) GetLocalCandidatesStats() []CandidateStats { + var res []CandidateStats + err := a.loop.Run(a.loop, func(_ context.Context) { + result := make([]CandidateStats, 0, len(a.localCandidates)) + for networkType, localCandidates := range a.localCandidates { + for _, cand := range localCandidates { + relayProtocol := "" + if cand.Type() == CandidateTypeRelay { + if cRelay, ok := cand.(*CandidateRelay); ok { + relayProtocol = cRelay.RelayProtocol() + } + } + stat := CandidateStats{ + Timestamp: time.Now(), + ID: cand.ID(), + NetworkType: networkType, + IP: cand.Address(), + Port: cand.Port(), + CandidateType: cand.Type(), + Priority: cand.Priority(), + // URL string + RelayProtocol: relayProtocol, + // Deleted bool + } + result = append(result, stat) + } + } + res = result + }) + if err != nil { + a.log.Errorf("Failed to get candidate pair stats: %v", err) + + return []CandidateStats{} + } + + return res +} + +// GetRemoteCandidatesStats returns a list of remote candidates stats. +func (a *Agent) GetRemoteCandidatesStats() []CandidateStats { + var res []CandidateStats + err := a.loop.Run(a.loop, func(_ context.Context) { + result := make([]CandidateStats, 0, len(a.remoteCandidates)) + for networkType, remoteCandidates := range a.remoteCandidates { + for _, c := range remoteCandidates { + stat := CandidateStats{ + Timestamp: time.Now(), + ID: c.ID(), + NetworkType: networkType, + IP: c.Address(), + Port: c.Port(), + CandidateType: c.Type(), + Priority: c.Priority(), + // URL string + RelayProtocol: "", + } + result = append(result, stat) + } + } + res = result + }) + if err != nil { + a.log.Errorf("Failed to get candidate pair stats: %v", err) + + return []CandidateStats{} + } + + return res +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/candidate.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/candidate.go similarity index 53% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/candidate.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/candidate.go index 92a007688..89082f986 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/candidate.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/candidate.go @@ -13,13 +13,13 @@ const ( receiveMTU = 8192 defaultLocalPreference = 65535 - // ComponentRTP indicates that the candidate is used for RTP + // ComponentRTP indicates that the candidate is used for RTP. ComponentRTP uint16 = 1 - // ComponentRTCP indicates that the candidate is used for RTCP + // ComponentRTCP indicates that the candidate is used for RTCP. ComponentRTCP ) -// Candidate represents an ICE candidate +// Candidate represents an ICE candidate. type Candidate interface { // An arbitrary string used in the freezing algorithm to // group similar candidates. It is the same for two candidates that @@ -52,15 +52,38 @@ type Candidate interface { // candidate, which is useful for diagnostics and other purposes RelatedAddress() *CandidateRelatedAddress + // Extensions returns a copy of all extension attributes associated with the ICECandidate. + // In the order of insertion, *(key value). + // Extension attributes are defined in RFC 5245, Section 15.1: + // https://datatracker.ietf.org/doc/html/rfc5245#section-15.1 + //. + Extensions() []CandidateExtension + // GetExtension returns the value of the extension attribute associated with the ICECandidate. + // Extension attributes are defined in RFC 5245, Section 15.1: + // https://datatracker.ietf.org/doc/html/rfc5245#section-15.1 + //. + GetExtension(key string) (value CandidateExtension, ok bool) + // AddExtension adds an extension attribute to the ICECandidate. + // If an extension with the same key already exists, it will be overwritten. + // Extension attributes are defined in RFC 5245, Section 15.1: + AddExtension(extension CandidateExtension) error + // RemoveExtension removes an extension attribute from the ICECandidate. + // Extension attributes are defined in RFC 5245, Section 15.1: + RemoveExtension(key string) (ok bool) + String() string Type() CandidateType TCPType() TCPType Equal(other Candidate) bool + // DeepEqual same as Equal, But it also compares the candidate extensions. + DeepEqual(other Candidate) bool + Marshal() string addr() net.Addr + filterForLocationTracking() bool agent() *Agent context() context.Context diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/candidate_base.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/candidate_base.go new file mode 100644 index 000000000..66fb776ee --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/candidate_base.go @@ -0,0 +1,1059 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + +package ice + +import ( + "context" + "errors" + "fmt" + "hash/crc32" + "io" + "net" + "strconv" + "strings" + "sync" + "sync/atomic" + "time" + + "github.com/pion/stun/v3" +) + +type candidateBase struct { + id string + networkType NetworkType + candidateType CandidateType + + component uint16 + address string + port int + relatedAddress *CandidateRelatedAddress + tcpType TCPType + + resolvedAddr net.Addr + + lastSent atomic.Value + lastReceived atomic.Value + conn net.PacketConn + + currAgent *Agent + closeCh chan struct{} + closedCh chan struct{} + + foundationOverride string + priorityOverride uint32 + + remoteCandidateCaches map[AddrPort]Candidate + isLocationTracked bool + extensions []CandidateExtension +} + +// Done implements context.Context. +func (c *candidateBase) Done() <-chan struct{} { + return c.closeCh +} + +// Err implements context.Context. +func (c *candidateBase) Err() error { + select { + case <-c.closedCh: + return ErrRunCanceled + default: + return nil + } +} + +// Deadline implements context.Context. +func (c *candidateBase) Deadline() (deadline time.Time, ok bool) { + return time.Time{}, false +} + +// Value implements context.Context. +func (c *candidateBase) Value(interface{}) interface{} { + return nil +} + +// ID returns Candidate ID. +func (c *candidateBase) ID() string { + return c.id +} + +func (c *candidateBase) Foundation() string { + if c.foundationOverride != "" { + return c.foundationOverride + } + + return fmt.Sprintf("%d", crc32.ChecksumIEEE([]byte(c.Type().String()+c.address+c.networkType.String()))) +} + +// Address returns Candidate Address. +func (c *candidateBase) Address() string { + return c.address +} + +// Port returns Candidate Port. +func (c *candidateBase) Port() int { + return c.port +} + +// Type returns candidate type. +func (c *candidateBase) Type() CandidateType { + return c.candidateType +} + +// NetworkType returns candidate NetworkType. +func (c *candidateBase) NetworkType() NetworkType { + return c.networkType +} + +// Component returns candidate component. +func (c *candidateBase) Component() uint16 { + return c.component +} + +func (c *candidateBase) SetComponent(component uint16) { + c.component = component +} + +// LocalPreference returns the local preference for this candidate. +func (c *candidateBase) LocalPreference() uint16 { //nolint:cyclop + if c.NetworkType().IsTCP() { + // RFC 6544, section 4.2 + // + // In Section 4.1.2.1 of [RFC5245], a recommended formula for UDP ICE + // candidate prioritization is defined. For TCP candidates, the same + // formula and candidate type preferences SHOULD be used, and the + // RECOMMENDED type preferences for the new candidate types defined in + // this document (see Section 5) are 105 for NAT-assisted candidates and + // 75 for UDP-tunneled candidates. + // + // (...) + // + // With TCP candidates, the local preference part of the recommended + // priority formula is updated to also include the directionality + // (active, passive, or simultaneous-open) of the TCP connection. The + // RECOMMENDED local preference is then defined as: + // + // local preference = (2^13) * direction-pref + other-pref + // + // The direction-pref MUST be between 0 and 7 (both inclusive), with 7 + // being the most preferred. The other-pref MUST be between 0 and 8191 + // (both inclusive), with 8191 being the most preferred. It is + // RECOMMENDED that the host, UDP-tunneled, and relayed TCP candidates + // have the direction-pref assigned as follows: 6 for active, 4 for + // passive, and 2 for S-O. For the NAT-assisted and server reflexive + // candidates, the RECOMMENDED values are: 6 for S-O, 4 for active, and + // 2 for passive. + // + // (...) + // + // If any two candidates have the same type-preference and direction- + // pref, they MUST have a unique other-pref. With this specification, + // this usually only happens with multi-homed hosts, in which case + // other-pref is the preference for the particular IP address from which + // the candidate was obtained. When there is only a single IP address, + // this value SHOULD be set to the maximum allowed value (8191). + var otherPref uint16 = 8191 + + directionPref := func() uint16 { + switch c.Type() { + case CandidateTypeHost, CandidateTypeRelay: + switch c.tcpType { + case TCPTypeActive: + return 6 + case TCPTypePassive: + return 4 + case TCPTypeSimultaneousOpen: + return 2 + case TCPTypeUnspecified: + return 0 + } + case CandidateTypePeerReflexive, CandidateTypeServerReflexive: + switch c.tcpType { + case TCPTypeSimultaneousOpen: + return 6 + case TCPTypeActive: + return 4 + case TCPTypePassive: + return 2 + case TCPTypeUnspecified: + return 0 + } + case CandidateTypeUnspecified: + return 0 + } + + return 0 + }() + + return (1<<13)*directionPref + otherPref + } + + return defaultLocalPreference +} + +// RelatedAddress returns *CandidateRelatedAddress. +func (c *candidateBase) RelatedAddress() *CandidateRelatedAddress { + return c.relatedAddress +} + +func (c *candidateBase) TCPType() TCPType { + return c.tcpType +} + +// start runs the candidate using the provided connection. +func (c *candidateBase) start(a *Agent, conn net.PacketConn, initializedCh <-chan struct{}) { + if c.conn != nil { + c.agent().log.Warn("Can't start already started candidateBase") + + return + } + c.currAgent = a + c.conn = conn + c.closeCh = make(chan struct{}) + c.closedCh = make(chan struct{}) + + go c.recvLoop(initializedCh) +} + +var bufferPool = sync.Pool{ // nolint:gochecknoglobals + New: func() interface{} { + return make([]byte, receiveMTU) + }, +} + +func (c *candidateBase) recvLoop(initializedCh <-chan struct{}) { + agent := c.agent() + + defer close(c.closedCh) + + select { + case <-initializedCh: + case <-c.closeCh: + return + } + + bufferPoolBuffer := bufferPool.Get() + defer bufferPool.Put(bufferPoolBuffer) + buf, ok := bufferPoolBuffer.([]byte) + if !ok { + return + } + + for { + n, srcAddr, err := c.conn.ReadFrom(buf) + if err != nil { + if !(errors.Is(err, io.EOF) || errors.Is(err, net.ErrClosed)) { + agent.log.Warnf("Failed to read from candidate %s: %v", c, err) + } + + return + } + + c.handleInboundPacket(buf[:n], srcAddr) + } +} + +func (c *candidateBase) validateSTUNTrafficCache(addr net.Addr) bool { + if candidate, ok := c.remoteCandidateCaches[toAddrPort(addr)]; ok { + candidate.seen(false) + + return true + } + + return false +} + +func (c *candidateBase) addRemoteCandidateCache(candidate Candidate, srcAddr net.Addr) { + if c.validateSTUNTrafficCache(srcAddr) { + return + } + c.remoteCandidateCaches[toAddrPort(srcAddr)] = candidate +} + +func (c *candidateBase) handleInboundPacket(buf []byte, srcAddr net.Addr) { + agent := c.agent() + + if stun.IsMessage(buf) { + msg := &stun.Message{ + Raw: make([]byte, len(buf)), + } + + // Explicitly copy raw buffer so Message can own the memory. + copy(msg.Raw, buf) + + if err := msg.Decode(); err != nil { + agent.log.Warnf("Failed to handle decode ICE from %s to %s: %v", c.addr(), srcAddr, err) + + return + } + + if err := agent.loop.Run(c, func(_ context.Context) { + // nolint: contextcheck + agent.handleInbound(msg, c, srcAddr) + }); err != nil { + agent.log.Warnf("Failed to handle message: %v", err) + } + + return + } + + if !c.validateSTUNTrafficCache(srcAddr) { + remoteCandidate, valid := agent.validateNonSTUNTraffic(c, srcAddr) //nolint:contextcheck + if !valid { + agent.log.Warnf("Discarded message from %s, not a valid remote candidate", c.addr()) + + return + } + c.addRemoteCandidateCache(remoteCandidate, srcAddr) + } + + // Note: This will return packetio.ErrFull if the buffer ever manages to fill up. + if _, err := agent.buf.Write(buf); err != nil { + agent.log.Warnf("Failed to write packet: %s", err) + + return + } +} + +// close stops the recvLoop. +func (c *candidateBase) close() error { + // If conn has never been started will be nil + if c.Done() == nil { + return nil + } + + // Assert that conn has not already been closed + select { + case <-c.Done(): + return nil + default: + } + + var firstErr error + + // Unblock recvLoop + close(c.closeCh) + if err := c.conn.SetDeadline(time.Now()); err != nil { + firstErr = err + } + + // Close the conn + if err := c.conn.Close(); err != nil && firstErr == nil { + firstErr = err + } + + if firstErr != nil { + return firstErr + } + + // Wait until the recvLoop is closed + <-c.closedCh + + return nil +} + +func (c *candidateBase) writeTo(raw []byte, dst Candidate) (int, error) { + n, err := c.conn.WriteTo(raw, dst.addr()) + if err != nil { + // If the connection is closed, we should return the error + if errors.Is(err, io.ErrClosedPipe) { + return n, err + } + c.agent().log.Infof("Failed to send packet: %v", err) + + return n, nil + } + c.seen(true) + + return n, nil +} + +// TypePreference returns the type preference for this candidate. +func (c *candidateBase) TypePreference() uint16 { + pref := c.Type().Preference() + if pref == 0 { + return 0 + } + + if c.NetworkType().IsTCP() { + var tcpPriorityOffset uint16 = defaultTCPPriorityOffset + if c.agent() != nil { + tcpPriorityOffset = c.agent().tcpPriorityOffset + } + + pref -= tcpPriorityOffset + } + + return pref +} + +// Priority computes the priority for this ICE Candidate +// See: https://www.rfc-editor.org/rfc/rfc8445#section-5.1.2.1 +func (c *candidateBase) Priority() uint32 { + if c.priorityOverride != 0 { + return c.priorityOverride + } + + // The local preference MUST be an integer from 0 (lowest preference) to + // 65535 (highest preference) inclusive. When there is only a single IP + // address, this value SHOULD be set to 65535. If there are multiple + // candidates for a particular component for a particular data stream + // that have the same type, the local preference MUST be unique for each + // one. + + return (1<<24)*uint32(c.TypePreference()) + + (1<<8)*uint32(c.LocalPreference()) + + (1<<0)*uint32(256-c.Component()) +} + +// Equal is used to compare two candidateBases. +func (c *candidateBase) Equal(other Candidate) bool { + if c.addr() != other.addr() { + if c.addr() == nil || other.addr() == nil { + return false + } + if !addrEqual(c.addr(), other.addr()) { + return false + } + } + + return c.NetworkType() == other.NetworkType() && + c.Type() == other.Type() && + c.Address() == other.Address() && + c.Port() == other.Port() && + c.TCPType() == other.TCPType() && + c.RelatedAddress().Equal(other.RelatedAddress()) +} + +// DeepEqual is same as Equal but also compares the extensions. +func (c *candidateBase) DeepEqual(other Candidate) bool { + return c.Equal(other) && c.extensionsEqual(other.Extensions()) +} + +// String makes the candidateBase printable. +func (c *candidateBase) String() string { + return fmt.Sprintf( + "%s %s %s%s (resolved: %v)", + c.NetworkType(), + c.Type(), + net.JoinHostPort(c.Address(), strconv.Itoa(c.Port())), + c.relatedAddress, + c.resolvedAddr, + ) +} + +// LastReceived returns a time.Time indicating the last time +// this candidate was received. +func (c *candidateBase) LastReceived() time.Time { + if lastReceived, ok := c.lastReceived.Load().(time.Time); ok { + return lastReceived + } + + return time.Time{} +} + +func (c *candidateBase) setLastReceived(t time.Time) { + c.lastReceived.Store(t) +} + +// LastSent returns a time.Time indicating the last time +// this candidate was sent. +func (c *candidateBase) LastSent() time.Time { + if lastSent, ok := c.lastSent.Load().(time.Time); ok { + return lastSent + } + + return time.Time{} +} + +func (c *candidateBase) setLastSent(t time.Time) { + c.lastSent.Store(t) +} + +func (c *candidateBase) seen(outbound bool) { + if outbound { + c.setLastSent(time.Now()) + } else { + c.setLastReceived(time.Now()) + } +} + +func (c *candidateBase) addr() net.Addr { + return c.resolvedAddr +} + +func (c *candidateBase) filterForLocationTracking() bool { + return c.isLocationTracked +} + +func (c *candidateBase) agent() *Agent { + return c.currAgent +} + +func (c *candidateBase) context() context.Context { + return c +} + +func (c *candidateBase) copy() (Candidate, error) { + return UnmarshalCandidate(c.Marshal()) +} + +func removeZoneIDFromAddress(addr string) string { + if i := strings.Index(addr, "%"); i != -1 { + return addr[:i] + } + + return addr +} + +// Marshal returns the string representation of the ICECandidate. +func (c *candidateBase) Marshal() string { + val := c.Foundation() + if val == " " { + val = "" + } + + val = fmt.Sprintf("%s %d %s %d %s %d typ %s", + val, + c.Component(), + c.NetworkType().NetworkShort(), + c.Priority(), + removeZoneIDFromAddress(c.Address()), + c.Port(), + c.Type()) + + if r := c.RelatedAddress(); r != nil && r.Address != "" && r.Port != 0 { + val = fmt.Sprintf("%s raddr %s rport %d", + val, + r.Address, + r.Port) + } + + extensions := c.marshalExtensions() + + if extensions != "" { + val = fmt.Sprintf("%s %s", val, extensions) + } + + return val +} + +// CandidateExtension represents a single candidate extension +// as defined in https://tools.ietf.org/html/rfc5245#section-15.1 +// . +type CandidateExtension struct { + Key string + Value string +} + +func (c *candidateBase) Extensions() []CandidateExtension { + tcpType := c.TCPType() + hasTCPType := 0 + if tcpType != TCPTypeUnspecified { + hasTCPType = 1 + } + + extensions := make([]CandidateExtension, len(c.extensions)+hasTCPType) + // We store the TCPType in c.tcpType, but we need to return it as an extension. + if hasTCPType == 1 { + extensions[0] = CandidateExtension{ + Key: "tcptype", + Value: tcpType.String(), + } + } + + copy(extensions[hasTCPType:], c.extensions) + + return extensions +} + +// Get returns the value of the given key if it exists. +func (c *candidateBase) GetExtension(key string) (CandidateExtension, bool) { + extension := CandidateExtension{Key: key} + + for i := range c.extensions { + if c.extensions[i].Key == key { + extension.Value = c.extensions[i].Value + + return extension, true + } + } + + // TCPType was manually set. + if key == "tcptype" && c.TCPType() != TCPTypeUnspecified { //nolint:goconst + extension.Value = c.TCPType().String() + + return extension, true + } + + return extension, false +} + +func (c *candidateBase) AddExtension(ext CandidateExtension) error { + if ext.Key == "tcptype" { + tcpType := NewTCPType(ext.Value) + if tcpType == TCPTypeUnspecified { + return fmt.Errorf("%w: invalid or unsupported TCPtype %s", errParseTCPType, ext.Value) + } + + c.tcpType = tcpType + + return nil + } + + if ext.Key == "" { + return fmt.Errorf("%w: key is empty", errParseExtension) + } + + // per spec, Extensions aren't explicitly unique, we only set the first one. + // If the exteion is set multiple times. + for i := range c.extensions { + if c.extensions[i].Key == ext.Key { + c.extensions[i] = ext + + return nil + } + } + + c.extensions = append(c.extensions, ext) + + return nil +} + +func (c *candidateBase) RemoveExtension(key string) (ok bool) { + if key == "tcptype" { + c.tcpType = TCPTypeUnspecified + ok = true + } + + for i := range c.extensions { + if c.extensions[i].Key == key { + c.extensions = append(c.extensions[:i], c.extensions[i+1:]...) + ok = true + + break + } + } + + return ok +} + +// marshalExtensions returns the string representation of the candidate extensions. +func (c *candidateBase) marshalExtensions() string { + value := "" + exts := c.Extensions() + + for i := range exts { + if value != "" { + value += " " + } + + value += exts[i].Key + " " + exts[i].Value + } + + return value +} + +// Equal returns true if the candidate extensions are equal. +func (c *candidateBase) extensionsEqual(other []CandidateExtension) bool { + freq1 := make(map[CandidateExtension]int) + freq2 := make(map[CandidateExtension]int) + + if len(c.extensions) != len(other) { + return false + } + + if len(c.extensions) == 0 { + return true + } + + if len(c.extensions) == 1 { + return c.extensions[0] == other[0] + } + + for i := range c.extensions { + freq1[c.extensions[i]]++ + freq2[other[i]]++ + } + + for k, v := range freq1 { + if freq2[k] != v { + return false + } + } + + return true +} + +func (c *candidateBase) setExtensions(extensions []CandidateExtension) { + c.extensions = extensions +} + +// UnmarshalCandidate Parses a candidate from a string +// https://datatracker.ietf.org/doc/html/rfc5245#section-15.1 +func UnmarshalCandidate(raw string) (Candidate, error) { //nolint:cyclop + // Handle candidates with the "candidate:" prefix as defined in RFC 5245 section 15.1. + raw = strings.TrimPrefix(raw, "candidate:") + + pos := 0 + // foundation ( 1*32ice-char ) But we allow for empty foundation, + foundation, pos, err := readCandidateCharToken(raw, pos, 32) + if err != nil { + return nil, fmt.Errorf("%w: %v in %s", errParseFoundation, err, raw) //nolint:errorlint // we wrap the error + } + + // Empty foundation, not RFC 8445 compliant but seen in the wild + if foundation == "" { + foundation = " " + } + + if pos >= len(raw) { + return nil, fmt.Errorf("%w: expected component in %s", errAttributeTooShortICECandidate, raw) + } + + // component-id ( 1*5DIGIT ) + component, pos, err := readCandidateDigitToken(raw, pos, 5) + if err != nil { + return nil, fmt.Errorf("%w: %v in %s", errParseComponent, err, raw) //nolint:errorlint // we wrap the error + } + + if pos >= len(raw) { + return nil, fmt.Errorf("%w: expected transport in %s", errAttributeTooShortICECandidate, raw) + } + + // transport ( "UDP" / transport-extension ; from RFC 3261 ) SP + protocol, pos := readCandidateStringToken(raw, pos) + + if pos >= len(raw) { + return nil, fmt.Errorf("%w: expected priority in %s", errAttributeTooShortICECandidate, raw) + } + + // priority ( 1*10DIGIT ) SP + priority, pos, err := readCandidateDigitToken(raw, pos, 10) + if err != nil { + return nil, fmt.Errorf("%w: %v in %s", errParsePriority, err, raw) //nolint:errorlint // we wrap the error + } + + if pos >= len(raw) { + return nil, fmt.Errorf("%w: expected address in %s", errAttributeTooShortICECandidate, raw) + } + + // connection-address SP ;from RFC 4566 + address, pos := readCandidateStringToken(raw, pos) + + // Remove IPv6 ZoneID: https://github.com/pion/ice/pull/704 + address = removeZoneIDFromAddress(address) + + if pos >= len(raw) { + return nil, fmt.Errorf("%w: expected port in %s", errAttributeTooShortICECandidate, raw) + } + + // port from RFC 4566 + port, pos, err := readCandidatePort(raw, pos) + if err != nil { + return nil, fmt.Errorf("%w: %v in %s", errParsePort, err, raw) //nolint:errorlint // we wrap the error + } + + // "typ" SP + typeKey, pos := readCandidateStringToken(raw, pos) + if typeKey != "typ" { + return nil, fmt.Errorf("%w (%s)", ErrUnknownCandidateTyp, typeKey) + } + + if pos >= len(raw) { + return nil, fmt.Errorf("%w: expected candidate type in %s", errAttributeTooShortICECandidate, raw) + } + + // SP cand-type ("host" / "srflx" / "prflx" / "relay") + typ, pos := readCandidateStringToken(raw, pos) + + raddr, rport, pos, err := tryReadRelativeAddrs(raw, pos) + if err != nil { + return nil, err + } + + tcpType := TCPTypeUnspecified + var extensions []CandidateExtension + var tcpTypeRaw string + + if pos < len(raw) { + extensions, tcpTypeRaw, err = unmarshalCandidateExtensions(raw[pos:]) + if err != nil { + return nil, fmt.Errorf("%w: %v", errParseExtension, err) //nolint:errorlint // we wrap the error + } + + if tcpTypeRaw != "" { + tcpType = NewTCPType(tcpTypeRaw) + if tcpType == TCPTypeUnspecified { + return nil, fmt.Errorf("%w: invalid or unsupported TCPtype %s", errParseTCPType, tcpTypeRaw) + } + } + } + + // this code is ugly because we can't break backwards compatibility + // with the old way of parsing candidates + switch typ { + case "host": + candidate, err := NewCandidateHost(&CandidateHostConfig{ + "", + protocol, + address, + port, + uint16(component), //nolint:gosec // G115 no overflow we read 5 digits + uint32(priority), //nolint:gosec // G115 no overflow we read 5 digits + foundation, + tcpType, + false, + }) + if err != nil { + return nil, err + } + + candidate.setExtensions(extensions) + + return candidate, nil + case "srflx": + candidate, err := NewCandidateServerReflexive(&CandidateServerReflexiveConfig{ + "", + protocol, + address, + port, + uint16(component), //nolint:gosec // G115 no overflow we read 5 digits + uint32(priority), //nolint:gosec // G115 no overflow we read 5 digits + foundation, + raddr, + rport, + }) + if err != nil { + return nil, err + } + + candidate.setExtensions(extensions) + + return candidate, nil + case "prflx": + candidate, err := NewCandidatePeerReflexive(&CandidatePeerReflexiveConfig{ + "", + protocol, + address, + port, + uint16(component), //nolint:gosec // G115 no overflow we read 5 digits + uint32(priority), //nolint:gosec // G115 no overflow we read 5 digits + foundation, + raddr, + rport, + }) + if err != nil { + return nil, err + } + + candidate.setExtensions(extensions) + + return candidate, nil + case "relay": + candidate, err := NewCandidateRelay(&CandidateRelayConfig{ + "", + protocol, + address, + port, + uint16(component), //nolint:gosec // G115 no overflow we read 5 digits + uint32(priority), //nolint:gosec // G115 no overflow we read 5 digits + foundation, + raddr, + rport, + "", + nil, + }) + if err != nil { + return nil, err + } + + candidate.setExtensions(extensions) + + return candidate, nil + default: + return nil, fmt.Errorf("%w (%s)", ErrUnknownCandidateTyp, typ) + } +} + +// Read an ice-char token from the raw string +// ice-char = ALPHA / DIGIT / "+" / "/" +// stop reading when a space is encountered or the end of the string. +func readCandidateCharToken(raw string, start int, limit int) (string, int, error) { //nolint:cyclop + for i, char := range raw[start:] { + if char == 0x20 { // SP + return raw[start : start+i], start + i + 1, nil + } + + if i == limit { + //nolint: err113 // handled by caller + return "", 0, fmt.Errorf("token too long: %s expected 1x%d", raw[start:start+i], limit) + } + + if !(char >= 'A' && char <= 'Z' || + char >= 'a' && char <= 'z' || + char >= '0' && char <= '9' || + char == '+' || char == '/') { + return "", 0, fmt.Errorf("invalid ice-char token: %c", char) //nolint: err113 // handled by caller + } + } + + return raw[start:], len(raw), nil +} + +// Read an ice string token from the raw string until a space is encountered +// Or the end of the string, we imply that ice string are UTF-8 encoded. +func readCandidateStringToken(raw string, start int) (string, int) { + for i, char := range raw[start:] { + if char == 0x20 { // SP + return raw[start : start+i], start + i + 1 + } + } + + return raw[start:], len(raw) +} + +// Read a digit token from the raw string +// stop reading when a space is encountered or the end of the string. +func readCandidateDigitToken(raw string, start, limit int) (int, int, error) { + var val int + for i, char := range raw[start:] { + if char == 0x20 { // SP + return val, start + i + 1, nil + } + + if i == limit { + //nolint: err113 // handled by caller + return 0, 0, fmt.Errorf("token too long: %s expected 1x%d", raw[start:start+i], limit) + } + + if !(char >= '0' && char <= '9') { + return 0, 0, fmt.Errorf("invalid digit token: %c", char) //nolint: err113 // handled by caller + } + + val = val*10 + int(char-'0') + } + + return val, len(raw), nil +} + +// Read and validate RFC 4566 port from the raw string. +func readCandidatePort(raw string, start int) (int, int, error) { + port, pos, err := readCandidateDigitToken(raw, start, 5) + if err != nil { + return 0, 0, err + } + + if port > 65535 { + return 0, 0, fmt.Errorf("invalid RFC 4566 port %d", port) //nolint: err113 // handled by caller + } + + return port, pos, nil +} + +// Read a byte-string token from the raw string +// As defined in RFC 4566 1*(%x01-09/%x0B-0C/%x0E-FF) ;any byte except NUL, CR, or LF +// we imply that extensions byte-string are UTF-8 encoded. +func readCandidateByteString(raw string, start int) (string, int, error) { + for i, char := range raw[start:] { + if char == 0x20 { // SP + return raw[start : start+i], start + i + 1, nil + } + + // 1*(%x01-09/%x0B-0C/%x0E-FF) + if !(char >= 0x01 && char <= 0x09 || + char >= 0x0B && char <= 0x0C || + char >= 0x0E && char <= 0xFF) { + return "", 0, fmt.Errorf("invalid byte-string character: %c", char) //nolint: err113 // handled by caller + } + } + + return raw[start:], len(raw), nil +} + +// Read and validate raddr and rport from the raw string +// [SP rel-addr] [SP rel-port] +// defined in https://datatracker.ietf.org/doc/html/rfc5245#section-15.1 +// . +func tryReadRelativeAddrs(raw string, start int) (raddr string, rport, pos int, err error) { + key, pos := readCandidateStringToken(raw, start) + + if key != "raddr" { + return "", 0, start, nil + } + + if pos >= len(raw) { + return "", 0, 0, fmt.Errorf("%w: expected raddr value in %s", errParseRelatedAddr, raw) + } + + raddr, pos = readCandidateStringToken(raw, pos) + + if pos >= len(raw) { + return "", 0, 0, fmt.Errorf("%w: expected rport in %s", errParseRelatedAddr, raw) + } + + key, pos = readCandidateStringToken(raw, pos) + if key != "rport" { + return "", 0, 0, fmt.Errorf("%w: expected rport in %s", errParseRelatedAddr, raw) + } + + if pos >= len(raw) { + return "", 0, 0, fmt.Errorf("%w: expected rport value in %s", errParseRelatedAddr, raw) + } + + rport, pos, err = readCandidatePort(raw, pos) + if err != nil { + return "", 0, 0, fmt.Errorf("%w: %v", errParseRelatedAddr, err) //nolint:errorlint // we wrap the error + } + + return raddr, rport, pos, nil +} + +// UnmarshalCandidateExtensions parses the candidate extensions from the raw string. +// *(SP extension-att-name SP extension-att-value) +// Where extension-att-name, and extension-att-value are byte-strings +// as defined in https://tools.ietf.org/html/rfc5245#section-15.1 +func unmarshalCandidateExtensions(raw string) (extensions []CandidateExtension, rawTCPTypeRaw string, err error) { + extensions = make([]CandidateExtension, 0) + + if raw == "" { + return extensions, "", nil + } + + if raw[0] == 0x20 { // SP + return extensions, "", fmt.Errorf("%w: unexpected space %s", errParseExtension, raw) + } + + for i := 0; i < len(raw); { + key, next, err := readCandidateByteString(raw, i) + if err != nil { + return extensions, "", fmt.Errorf( + "%w: failed to read key %v", errParseExtension, err, //nolint: errorlint // we wrap the error + ) + } + i = next + + // while not spec-compliant, we allow for empty values, as seen in the wild + var value string + if i < len(raw) { + value, next, err = readCandidateByteString(raw, i) + if err != nil { + return extensions, "", fmt.Errorf( + "%w: failed to read value %v", errParseExtension, err, //nolint: errorlint // we are wrapping the error + ) + } + i = next + } + + if key == "tcptype" { + rawTCPTypeRaw = value + + continue + } + + extensions = append(extensions, CandidateExtension{key, value}) + } + + return extensions, rawTCPTypeRaw, nil +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/candidate_host.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/candidate_host.go similarity index 58% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/candidate_host.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/candidate_host.go index 5d207dd91..ac33ca3f3 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/candidate_host.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/candidate_host.go @@ -4,30 +4,31 @@ package ice import ( - "net" + "net/netip" "strings" ) -// CandidateHost is a candidate of type host +// CandidateHost is a candidate of type host. type CandidateHost struct { candidateBase network string } -// CandidateHostConfig is the config required to create a new CandidateHost +// CandidateHostConfig is the config required to create a new CandidateHost. type CandidateHostConfig struct { - CandidateID string - Network string - Address string - Port int - Component uint16 - Priority uint32 - Foundation string - TCPType TCPType + CandidateID string + Network string + Address string + Port int + Component uint16 + Priority uint32 + Foundation string + TCPType TCPType + IsLocationTracked bool } -// NewCandidateHost creates a new host candidate +// NewCandidateHost creates a new host candidate. func NewCandidateHost(config *CandidateHostConfig) (*CandidateHost, error) { candidateID := config.CandidateID @@ -35,7 +36,7 @@ func NewCandidateHost(config *CandidateHostConfig) (*CandidateHost, error) { candidateID = globalCandidateIDGenerator.Generate() } - c := &CandidateHost{ + candidateHost := &CandidateHost{ candidateBase: candidateBase{ id: candidateID, address: config.Address, @@ -46,35 +47,36 @@ func NewCandidateHost(config *CandidateHostConfig) (*CandidateHost, error) { foundationOverride: config.Foundation, priorityOverride: config.Priority, remoteCandidateCaches: map[AddrPort]Candidate{}, + isLocationTracked: config.IsLocationTracked, }, network: config.Network, } if !strings.HasSuffix(config.Address, ".local") { - ip := net.ParseIP(config.Address) - if ip == nil { - return nil, ErrAddressParseFailed + ipAddr, err := netip.ParseAddr(config.Address) + if err != nil { + return nil, err } - if err := c.setIP(ip); err != nil { + if err := candidateHost.setIPAddr(ipAddr); err != nil { return nil, err } } else { // Until mDNS candidate is resolved assume it is UDPv4 - c.candidateBase.networkType = NetworkTypeUDP4 + candidateHost.candidateBase.networkType = NetworkTypeUDP4 } - return c, nil + return candidateHost, nil } -func (c *CandidateHost) setIP(ip net.IP) error { - networkType, err := determineNetworkType(c.network, ip) +func (c *CandidateHost) setIPAddr(addr netip.Addr) error { + networkType, err := determineNetworkType(c.network, addr) if err != nil { return err } c.candidateBase.networkType = networkType - c.candidateBase.resolvedAddr = createAddr(networkType, ip, c.port) + c.candidateBase.resolvedAddr = createAddr(networkType, addr, c.port) return nil } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/candidate_peer_reflexive.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/candidate_peer_reflexive.go similarity index 78% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/candidate_peer_reflexive.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/candidate_peer_reflexive.go index f019ec698..9bf435cd7 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/candidate_peer_reflexive.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/candidate_peer_reflexive.go @@ -6,14 +6,16 @@ //nolint:dupl package ice -import "net" +import ( + "net/netip" +) // CandidatePeerReflexive ... type CandidatePeerReflexive struct { candidateBase } -// CandidatePeerReflexiveConfig is the config required to create a new CandidatePeerReflexive +// CandidatePeerReflexiveConfig is the config required to create a new CandidatePeerReflexive. type CandidatePeerReflexiveConfig struct { CandidateID string Network string @@ -26,22 +28,21 @@ type CandidatePeerReflexiveConfig struct { RelPort int } -// NewCandidatePeerReflexive creates a new peer reflective candidate +// NewCandidatePeerReflexive creates a new peer reflective candidate. func NewCandidatePeerReflexive(config *CandidatePeerReflexiveConfig) (*CandidatePeerReflexive, error) { - ip := net.ParseIP(config.Address) - if ip == nil { - return nil, ErrAddressParseFailed + ipAddr, err := netip.ParseAddr(config.Address) + if err != nil { + return nil, err } - networkType, err := determineNetworkType(config.Network, ip) + networkType, err := determineNetworkType(config.Network, ipAddr) if err != nil { return nil, err } candidateID := config.CandidateID - candidateIDGenerator := newCandidateIDGenerator() if candidateID == "" { - candidateID = candidateIDGenerator.Generate() + candidateID = globalCandidateIDGenerator.Generate() } return &CandidatePeerReflexive{ @@ -51,7 +52,7 @@ func NewCandidatePeerReflexive(config *CandidatePeerReflexiveConfig) (*Candidate candidateType: CandidateTypePeerReflexive, address: config.Address, port: config.Port, - resolvedAddr: createAddr(networkType, ip, config.Port), + resolvedAddr: createAddr(networkType, ipAddr, config.Port), component: config.Component, foundationOverride: config.Foundation, priorityOverride: config.Priority, diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/candidate_relay.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/candidate_relay.go similarity index 63% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/candidate_relay.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/candidate_relay.go index 449d077a6..9e88b1a63 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/candidate_relay.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/candidate_relay.go @@ -5,6 +5,7 @@ package ice import ( "net" + "net/netip" ) // CandidateRelay ... @@ -15,7 +16,7 @@ type CandidateRelay struct { onClose func() error } -// CandidateRelayConfig is the config required to create a new CandidateRelay +// CandidateRelayConfig is the config required to create a new CandidateRelay. type CandidateRelayConfig struct { CandidateID string Network string @@ -30,7 +31,7 @@ type CandidateRelayConfig struct { OnClose func() error } -// NewCandidateRelay creates a new relay candidate +// NewCandidateRelay creates a new relay candidate. func NewCandidateRelay(config *CandidateRelayConfig) (*CandidateRelay, error) { candidateID := config.CandidateID @@ -38,24 +39,28 @@ func NewCandidateRelay(config *CandidateRelayConfig) (*CandidateRelay, error) { candidateID = globalCandidateIDGenerator.Generate() } - ip := net.ParseIP(config.Address) - if ip == nil { - return nil, ErrAddressParseFailed + ipAddr, err := netip.ParseAddr(config.Address) + if err != nil { + return nil, err } - networkType, err := determineNetworkType(config.Network, ip) + networkType, err := determineNetworkType(config.Network, ipAddr) if err != nil { return nil, err } return &CandidateRelay{ candidateBase: candidateBase{ - id: candidateID, - networkType: networkType, - candidateType: CandidateTypeRelay, - address: config.Address, - port: config.Port, - resolvedAddr: &net.UDPAddr{IP: ip, Port: config.Port}, + id: candidateID, + networkType: networkType, + candidateType: CandidateTypeRelay, + address: config.Address, + port: config.Port, + resolvedAddr: &net.UDPAddr{ + IP: ipAddr.AsSlice(), + Port: config.Port, + Zone: ipAddr.Zone(), + }, component: config.Component, foundationOverride: config.Foundation, priorityOverride: config.Priority, @@ -70,6 +75,23 @@ func NewCandidateRelay(config *CandidateRelayConfig) (*CandidateRelay, error) { }, nil } +// LocalPreference returns the local preference for this candidate. +func (c *CandidateRelay) LocalPreference() uint16 { + // These preference values come from libwebrtc + // https://github.com/mozilla/libwebrtc/blob/1389c76d9c79839a2ca069df1db48aa3f2e6a1ac/p2p/base/turn_port.cc#L61 + var relayPreference uint16 + switch c.relayProtocol { + case relayProtocolTLS, relayProtocolDTLS: + relayPreference = 2 + case tcp: + relayPreference = 1 + default: + relayPreference = 0 + } + + return c.candidateBase.LocalPreference() + relayPreference +} + // RelayProtocol returns the protocol used between the endpoint and the relay server. func (c *CandidateRelay) RelayProtocol() string { return c.relayProtocol @@ -81,6 +103,7 @@ func (c *CandidateRelay) close() error { err = c.onClose() c.onClose = nil } + return err } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/candidate_server_reflexive.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/candidate_server_reflexive.go similarity index 69% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/candidate_server_reflexive.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/candidate_server_reflexive.go index 3a8ac0ff7..3612edbce 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/candidate_server_reflexive.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/candidate_server_reflexive.go @@ -3,14 +3,17 @@ package ice -import "net" +import ( + "net" + "net/netip" +) // CandidateServerReflexive ... type CandidateServerReflexive struct { candidateBase } -// CandidateServerReflexiveConfig is the config required to create a new CandidateServerReflexive +// CandidateServerReflexiveConfig is the config required to create a new CandidateServerReflexive. type CandidateServerReflexiveConfig struct { CandidateID string Network string @@ -23,14 +26,14 @@ type CandidateServerReflexiveConfig struct { RelPort int } -// NewCandidateServerReflexive creates a new server reflective candidate +// NewCandidateServerReflexive creates a new server reflective candidate. func NewCandidateServerReflexive(config *CandidateServerReflexiveConfig) (*CandidateServerReflexive, error) { - ip := net.ParseIP(config.Address) - if ip == nil { - return nil, ErrAddressParseFailed + ipAddr, err := netip.ParseAddr(config.Address) + if err != nil { + return nil, err } - networkType, err := determineNetworkType(config.Network, ip) + networkType, err := determineNetworkType(config.Network, ipAddr) if err != nil { return nil, err } @@ -42,12 +45,16 @@ func NewCandidateServerReflexive(config *CandidateServerReflexiveConfig) (*Candi return &CandidateServerReflexive{ candidateBase: candidateBase{ - id: candidateID, - networkType: networkType, - candidateType: CandidateTypeServerReflexive, - address: config.Address, - port: config.Port, - resolvedAddr: &net.UDPAddr{IP: ip, Port: config.Port}, + id: candidateID, + networkType: networkType, + candidateType: CandidateTypeServerReflexive, + address: config.Address, + port: config.Port, + resolvedAddr: &net.UDPAddr{ + IP: ipAddr.AsSlice(), + Port: config.Port, + Zone: ipAddr.Zone(), + }, component: config.Component, foundationOverride: config.Foundation, priorityOverride: config.Priority, diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/candidatepair.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/candidatepair.go new file mode 100644 index 000000000..82655aa5f --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/candidatepair.go @@ -0,0 +1,256 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + +package ice + +import ( + "fmt" + "sync/atomic" + "time" + + "github.com/pion/stun/v3" +) + +func newCandidatePair(local, remote Candidate, controlling bool) *CandidatePair { + return &CandidatePair{ + iceRoleControlling: controlling, + Remote: remote, + Local: local, + state: CandidatePairStateWaiting, + } +} + +// CandidatePair is a combination of a local and remote candidate. +type CandidatePair struct { + iceRoleControlling bool + Remote Candidate + Local Candidate + bindingRequestCount uint16 + state CandidatePairState + nominated bool + nominateOnBindingSuccess bool + + // stats + currentRoundTripTime int64 // in ns + totalRoundTripTime int64 // in ns + + requestsReceived uint64 + requestsSent uint64 + responsesReceived uint64 + responsesSent uint64 + + firstRequestSentAt atomic.Value // time.Time + lastRequestSentAt atomic.Value // time.Time + firstReponseReceivedAt atomic.Value // time.Time + lastResponseReceivedAt atomic.Value // time.Time + firstRequestReceivedAt atomic.Value // time.Time + lastRequestReceivedAt atomic.Value // time.Time +} + +func (p *CandidatePair) String() string { + if p == nil { + return "" + } + + return fmt.Sprintf( + "prio %d (local, prio %d) %s <-> %s (remote, prio %d), state: %s, nominated: %v, nominateOnBindingSuccess: %v", + p.priority(), + p.Local.Priority(), + p.Local, + p.Remote, + p.Remote.Priority(), + p.state, + p.nominated, + p.nominateOnBindingSuccess, + ) +} + +func (p *CandidatePair) equal(other *CandidatePair) bool { + if p == nil && other == nil { + return true + } + if p == nil || other == nil { + return false + } + + return p.Local.Equal(other.Local) && p.Remote.Equal(other.Remote) +} + +// RFC 5245 - 5.7.2. Computing Pair Priority and Ordering Pairs +// Let G be the priority for the candidate provided by the controlling +// agent. Let D be the priority for the candidate provided by the +// controlled agent. +// pair priority = 2^32*MIN(G,D) + 2*MAX(G,D) + (G>D?1:0). +func (p *CandidatePair) priority() uint64 { + var g, d uint32 //nolint:varnamelen // clearer to use g and d here + if p.iceRoleControlling { + g = p.Local.Priority() + d = p.Remote.Priority() + } else { + g = p.Remote.Priority() + d = p.Local.Priority() + } + + // Just implement these here rather + // than fooling around with the math package + localMin := func(x, y uint32) uint64 { + if x < y { + return uint64(x) + } + + return uint64(y) + } + localMax := func(x, y uint32) uint64 { + if x > y { + return uint64(x) + } + + return uint64(y) + } + cmp := func(x, y uint32) uint64 { + if x > y { + return uint64(1) + } + + return uint64(0) + } + + // 1<<32 overflows uint32; and if both g && d are + // maxUint32, this result would overflow uint64 + return (1<<32-1)*localMin(g, d) + 2*localMax(g, d) + cmp(g, d) +} + +func (p *CandidatePair) Write(b []byte) (int, error) { + return p.Local.writeTo(b, p.Remote) +} + +func (a *Agent) sendSTUN(msg *stun.Message, local, remote Candidate) { + _, err := local.writeTo(msg.Raw, remote) + if err != nil { + a.log.Tracef("Failed to send STUN message: %s", err) + } +} + +// UpdateRoundTripTime sets the current round time of this pair and +// accumulates total round trip time and responses received. +func (p *CandidatePair) UpdateRoundTripTime(rtt time.Duration) { + rttNs := rtt.Nanoseconds() + atomic.StoreInt64(&p.currentRoundTripTime, rttNs) + atomic.AddInt64(&p.totalRoundTripTime, rttNs) + atomic.AddUint64(&p.responsesReceived, 1) + + now := time.Now() + p.firstReponseReceivedAt.CompareAndSwap(nil, now) + p.lastResponseReceivedAt.Store(now) +} + +// CurrentRoundTripTime returns the current round trip time in seconds +// https://www.w3.org/TR/webrtc-stats/#dom-rtcicecandidatepairstats-currentroundtriptime +func (p *CandidatePair) CurrentRoundTripTime() float64 { + return time.Duration(atomic.LoadInt64(&p.currentRoundTripTime)).Seconds() +} + +// TotalRoundTripTime returns the current round trip time in seconds +// https://www.w3.org/TR/webrtc-stats/#dom-rtcicecandidatepairstats-totalroundtriptime +func (p *CandidatePair) TotalRoundTripTime() float64 { + return time.Duration(atomic.LoadInt64(&p.totalRoundTripTime)).Seconds() +} + +// RequestsReceived returns the total number of connectivity checks received +// https://www.w3.org/TR/webrtc-stats/#dom-rtcicecandidatepairstats-requestsreceived +func (p *CandidatePair) RequestsReceived() uint64 { + return atomic.LoadUint64(&p.requestsReceived) +} + +// RequestsSent returns the total number of connectivity checks sent +// https://www.w3.org/TR/webrtc-stats/#dom-rtcicecandidatepairstats-requestssent +func (p *CandidatePair) RequestsSent() uint64 { + return atomic.LoadUint64(&p.requestsSent) +} + +// ResponsesReceived returns the total number of connectivity responses received +// https://www.w3.org/TR/webrtc-stats/#dom-rtcicecandidatepairstats-responsesreceived +func (p *CandidatePair) ResponsesReceived() uint64 { + return atomic.LoadUint64(&p.responsesReceived) +} + +// ResponsesSent returns the total number of connectivity responses sent +// https://www.w3.org/TR/webrtc-stats/#dom-rtcicecandidatepairstats-responsessent +func (p *CandidatePair) ResponsesSent() uint64 { + return atomic.LoadUint64(&p.responsesSent) +} + +// FirstRequestSentAt returns the timestamp of the first connectivity check sent. +func (p *CandidatePair) FirstRequestSentAt() time.Time { + if v, ok := p.firstRequestSentAt.Load().(time.Time); ok { + return v + } + + return time.Time{} +} + +// LastRequestSentAt returns the timestamp of the last connectivity check sent. +func (p *CandidatePair) LastRequestSentAt() time.Time { + if v, ok := p.lastRequestSentAt.Load().(time.Time); ok { + return v + } + + return time.Time{} +} + +// FirstReponseReceivedAt returns the timestamp of the first connectivity response received. +func (p *CandidatePair) FirstReponseReceivedAt() time.Time { + if v, ok := p.firstReponseReceivedAt.Load().(time.Time); ok { + return v + } + + return time.Time{} +} + +// LastResponseReceivedAt returns the timestamp of the last connectivity response received. +func (p *CandidatePair) LastResponseReceivedAt() time.Time { + if v, ok := p.lastResponseReceivedAt.Load().(time.Time); ok { + return v + } + + return time.Time{} +} + +// FirstRequestReceivedAt returns the timestamp of the first connectivity check received. +func (p *CandidatePair) FirstRequestReceivedAt() time.Time { + if v, ok := p.firstRequestReceivedAt.Load().(time.Time); ok { + return v + } + + return time.Time{} +} + +// LastRequestReceivedAt returns the timestamp of the last connectivity check received. +func (p *CandidatePair) LastRequestReceivedAt() time.Time { + if v, ok := p.lastRequestReceivedAt.Load().(time.Time); ok { + return v + } + + return time.Time{} +} + +// UpdateRequestSent increments the number of requests sent and updates the timestamp. +func (p *CandidatePair) UpdateRequestSent() { + atomic.AddUint64(&p.requestsSent, 1) + now := time.Now() + p.firstRequestSentAt.CompareAndSwap(nil, now) + p.lastRequestSentAt.Store(now) +} + +// UpdateResponseSent increments the number of responses sent. +func (p *CandidatePair) UpdateResponseSent() { + atomic.AddUint64(&p.responsesSent, 1) +} + +// UpdateRequestReceived increments the number of requests received and updates the timestamp. +func (p *CandidatePair) UpdateRequestReceived() { + atomic.AddUint64(&p.requestsReceived, 1) + now := time.Now() + p.firstRequestReceivedAt.CompareAndSwap(nil, now) + p.lastRequestReceivedAt.Store(now) +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/candidatepair_state.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/candidatepair_state.go similarity index 88% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/candidatepair_state.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/candidatepair_state.go index 1a1e827b0..e1efd39a1 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/candidatepair_state.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/candidatepair_state.go @@ -3,13 +3,13 @@ package ice -// CandidatePairState represent the ICE candidate pair state +// CandidatePairState represent the ICE candidate pair state. type CandidatePairState int const ( // CandidatePairStateWaiting means a check has not been performed for - // this pair - CandidatePairStateWaiting = iota + 1 + // this pair. + CandidatePairStateWaiting CandidatePairState = iota + 1 // CandidatePairStateInProgress means a check has been sent for this pair, // but the transaction is in progress. @@ -36,5 +36,6 @@ func (c CandidatePairState) String() string { case CandidatePairStateSucceeded: return "succeeded" } + return "Unknown candidate pair state" } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/candidaterelatedaddress.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/candidaterelatedaddress.go similarity index 93% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/candidaterelatedaddress.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/candidaterelatedaddress.go index e87c70514..161adf83e 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/candidaterelatedaddress.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/candidaterelatedaddress.go @@ -12,7 +12,7 @@ type CandidateRelatedAddress struct { Port int } -// String makes CandidateRelatedAddress printable +// String makes CandidateRelatedAddress printable. func (c *CandidateRelatedAddress) String() string { if c == nil { return "" @@ -27,6 +27,7 @@ func (c *CandidateRelatedAddress) Equal(other *CandidateRelatedAddress) bool { if c == nil && other == nil { return true } + return c != nil && other != nil && c.Address == other.Address && c.Port == other.Port diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/candidatetype.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/candidatetype.go similarity index 92% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/candidatetype.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/candidatetype.go index 3972934cb..fef798b6b 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/candidatetype.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/candidatetype.go @@ -3,10 +3,10 @@ package ice -// CandidateType represents the type of candidate +// CandidateType represents the type of candidate. type CandidateType byte -// CandidateType enum +// CandidateType enum. const ( CandidateTypeUnspecified CandidateType = iota CandidateTypeHost @@ -15,7 +15,7 @@ const ( CandidateTypeRelay ) -// String makes CandidateType printable +// String makes CandidateType printable. func (c CandidateType) String() string { switch c { case CandidateTypeHost: @@ -29,6 +29,7 @@ func (c CandidateType) String() string { case CandidateTypeUnspecified: return "Unknown candidate type" } + return "Unknown candidate type" } @@ -49,6 +50,7 @@ func (c CandidateType) Preference() uint16 { case CandidateTypeRelay, CandidateTypeUnspecified: return 0 } + return 0 } @@ -61,5 +63,6 @@ func containsCandidateType(candidateType CandidateType, candidateTypeList []Cand return true } } + return false } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/codecov.yml b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/codecov.yml similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/codecov.yml rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/codecov.yml diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/errors.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/errors.go similarity index 74% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/errors.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/errors.go index e05cce898..39b22e5bd 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/errors.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/errors.go @@ -3,7 +3,11 @@ package ice -import "errors" +import ( + "errors" + + "github.com/pion/ice/v4/internal/taskloop" +) var ( // ErrUnknownType indicates an error with Unknown info. @@ -25,69 +29,71 @@ var ( ErrPort = errors.New("invalid port") // ErrLocalUfragInsufficientBits indicates local username fragment insufficient bits are provided. - // Have to be at least 24 bits long + // Have to be at least 24 bits long. ErrLocalUfragInsufficientBits = errors.New("local username fragment is less than 24 bits long") // ErrLocalPwdInsufficientBits indicates local password insufficient bits are provided. - // Have to be at least 128 bits long + // Have to be at least 128 bits long. ErrLocalPwdInsufficientBits = errors.New("local password is less than 128 bits long") // ErrProtoType indicates an unsupported transport type was provided. ErrProtoType = errors.New("invalid transport protocol type") - // ErrClosed indicates the agent is closed - ErrClosed = errors.New("the agent is closed") + // ErrClosed indicates the agent is closed. + ErrClosed = taskloop.ErrClosed - // ErrNoCandidatePairs indicates agent does not have a valid candidate pair + // ErrNoCandidatePairs indicates agent does not have a valid candidate pair. ErrNoCandidatePairs = errors.New("no candidate pairs available") - // ErrCanceledByCaller indicates agent connection was canceled by the caller + // ErrCanceledByCaller indicates agent connection was canceled by the caller. ErrCanceledByCaller = errors.New("connecting canceled by caller") - // ErrMultipleStart indicates agent was started twice + // ErrMultipleStart indicates agent was started twice. ErrMultipleStart = errors.New("attempted to start agent twice") - // ErrRemoteUfragEmpty indicates agent was started with an empty remote ufrag + // ErrRemoteUfragEmpty indicates agent was started with an empty remote ufrag. ErrRemoteUfragEmpty = errors.New("remote ufrag is empty") - // ErrRemotePwdEmpty indicates agent was started with an empty remote pwd + // ErrRemotePwdEmpty indicates agent was started with an empty remote pwd. ErrRemotePwdEmpty = errors.New("remote pwd is empty") - // ErrNoOnCandidateHandler indicates agent was started without OnCandidate + // ErrNoOnCandidateHandler indicates agent was started without OnCandidate. ErrNoOnCandidateHandler = errors.New("no OnCandidate provided") - // ErrMultipleGatherAttempted indicates GatherCandidates has been called multiple times + // ErrMultipleGatherAttempted indicates GatherCandidates has been called multiple times. ErrMultipleGatherAttempted = errors.New("attempting to gather candidates during gathering state") - // ErrUsernameEmpty indicates agent was give TURN URL with an empty Username + // ErrUsernameEmpty indicates agent was give TURN URL with an empty Username. ErrUsernameEmpty = errors.New("username is empty") - // ErrPasswordEmpty indicates agent was give TURN URL with an empty Password + // ErrPasswordEmpty indicates agent was give TURN URL with an empty Password. ErrPasswordEmpty = errors.New("password is empty") - // ErrAddressParseFailed indicates we were unable to parse a candidate address + // ErrAddressParseFailed indicates we were unable to parse a candidate address. ErrAddressParseFailed = errors.New("failed to parse address") - // ErrLiteUsingNonHostCandidates indicates non host candidates were selected for a lite agent + // ErrLiteUsingNonHostCandidates indicates non host candidates were selected for a lite agent. ErrLiteUsingNonHostCandidates = errors.New("lite agents must only use host candidates") // ErrUselessUrlsProvided indicates that one or more URL was provided to the agent but no host - // candidate required them + // candidate required them. ErrUselessUrlsProvided = errors.New("agent does not need URL with selected candidate types") // ErrUnsupportedNAT1To1IPCandidateType indicates that the specified NAT1To1IPCandidateType is - // unsupported + // unsupported. ErrUnsupportedNAT1To1IPCandidateType = errors.New("unsupported 1:1 NAT IP candidate type") - // ErrInvalidNAT1To1IPMapping indicates that the given 1:1 NAT IP mapping is invalid + // ErrInvalidNAT1To1IPMapping indicates that the given 1:1 NAT IP mapping is invalid. ErrInvalidNAT1To1IPMapping = errors.New("invalid 1:1 NAT IP mapping") - // ErrExternalMappedIPNotFound in NAT1To1IPMapping + // ErrExternalMappedIPNotFound in NAT1To1IPMapping. ErrExternalMappedIPNotFound = errors.New("external mapped IP not found") // ErrMulticastDNSWithNAT1To1IPMapping indicates that the mDNS gathering cannot be used along // with 1:1 NAT IP mapping for host candidate. - ErrMulticastDNSWithNAT1To1IPMapping = errors.New("mDNS gathering cannot be used with 1:1 NAT IP mapping for host candidate") + ErrMulticastDNSWithNAT1To1IPMapping = errors.New( + "mDNS gathering cannot be used with 1:1 NAT IP mapping for host candidate", + ) // ErrIneffectiveNAT1To1IPMappingHost indicates that 1:1 NAT IP mapping for host candidate is // requested, but the host candidate type is disabled. @@ -97,10 +103,12 @@ var ( // requested, but the srflx candidate type is disabled. ErrIneffectiveNAT1To1IPMappingSrflx = errors.New("1:1 NAT IP mapping for srflx candidate ineffective") - // ErrInvalidMulticastDNSHostName indicates an invalid MulticastDNSHostName - ErrInvalidMulticastDNSHostName = errors.New("invalid mDNS HostName, must end with .local and can only contain a single '.'") + // ErrInvalidMulticastDNSHostName indicates an invalid MulticastDNSHostName. + ErrInvalidMulticastDNSHostName = errors.New( + "invalid mDNS HostName, must end with .local and can only contain a single '.'", + ) - // ErrRunCanceled indicates a run operation was canceled by its individual done + // ErrRunCanceled indicates a run operation was canceled by its individual done. ErrRunCanceled = errors.New("run was canceled by done") // ErrTCPRemoteAddrAlreadyExists indicates we already have the connection with same remote addr. @@ -109,34 +117,36 @@ var ( // ErrUnknownCandidateTyp indicates that a candidate had a unknown type value. ErrUnknownCandidateTyp = errors.New("unknown candidate typ") - // ErrDetermineNetworkType indicates that the NetworkType was not able to be parsed + // ErrDetermineNetworkType indicates that the NetworkType was not able to be parsed. ErrDetermineNetworkType = errors.New("unable to determine networkType") - errSendPacket = errors.New("failed to send packet") errAttributeTooShortICECandidate = errors.New("attribute not long enough to be ICE candidate") - errParseComponent = errors.New("could not parse component") - errParsePriority = errors.New("could not parse priority") - errParsePort = errors.New("could not parse port") - errParseRelatedAddr = errors.New("could not parse related addresses") - errParseTCPType = errors.New("could not parse TCP type") - errGetXorMappedAddrResponse = errors.New("failed to get XOR-MAPPED-ADDRESS response") + errClosingConnection = errors.New("failed to close connection") errConnectionAddrAlreadyExist = errors.New("connection with same remote address already exists") - errReadingStreamingPacket = errors.New("error reading streaming packet") - errWriting = errors.New("error writing to") - errClosingConnection = errors.New("error closing connection") - errRead = errors.New("unexpected error trying to read") - errUnknownRole = errors.New("unknown role") - errICEWriteSTUNMessage = errors.New("the ICE conn can't write STUN messages") - errUDPMuxDisabled = errors.New("UDPMux is not enabled") - errNoXorAddrMapping = errors.New("no address mapping") - errSendSTUNPacket = errors.New("failed to send STUN packet") - errXORMappedAddrTimeout = errors.New("timeout while waiting for XORMappedAddr") + errGetXorMappedAddrResponse = errors.New("failed to get XOR-MAPPED-ADDRESS response") + errInvalidAddress = errors.New("invalid address") + errNoTCPMuxAvailable = errors.New("no TCP mux is available") errNotImplemented = errors.New("not implemented yet") errNoUDPMuxAvailable = errors.New("no UDP mux is available") - errNoTCPMuxAvailable = errors.New("no TCP mux is available") - errInvalidAddress = errors.New("invalid address") + errNoXorAddrMapping = errors.New("no address mapping") + errParseFoundation = errors.New("failed to parse foundation") + errParseComponent = errors.New("failed to parse component") + errParsePort = errors.New("failed to parse port") + errParsePriority = errors.New("failed to parse priority") + errParseRelatedAddr = errors.New("failed to parse related addresses") + errParseExtension = errors.New("failed to parse extension") + errParseTCPType = errors.New("failed to parse TCP type") + errRead = errors.New("failed to read") + errUDPMuxDisabled = errors.New("UDPMux is not enabled") + errUnknownRole = errors.New("unknown role") + errWrite = errors.New("failed to write") + errWriteSTUNMessage = errors.New("failed to send STUN message") + errWriteSTUNMessageToIceConn = errors.New("failed to write STUN message to ICE connection") + errXORMappedAddrTimeout = errors.New("timeout while waiting for XORMappedAddr") + errFailedToCastUDPAddr = errors.New("failed to cast net.Addr to net.UDPAddr") + errInvalidIPAddress = errors.New("invalid ip address") // UDPMuxDefault should not listen on unspecified address, but to keep backward compatibility, don't return error now. // will be used in the future. - // errListenUnspecified = errors.New("can't listen on unspecified address") + // errListenUnspecified = errors.New("can't listen on unspecified address"). ) diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/external_ip_mapper.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/external_ip_mapper.go similarity index 83% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/external_ip_mapper.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/external_ip_mapper.go index 3d542fb1a..2d483ff96 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/external_ip_mapper.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/external_ip_mapper.go @@ -13,10 +13,13 @@ func validateIPString(ipStr string) (net.IP, bool, error) { if ip == nil { return nil, false, ErrInvalidNAT1To1IPMapping } + return ip, (ip.To4() != nil), nil } -// ipMapping holds the mapping of local and external IP address for a particular IP family +// ipMapping holds the mapping of local and external IP address +// +// for a particular IP family. type ipMapping struct { ipSole net.IP // When non-nil, this is the sole external IP for one local IP assumed ipMap map[string]net.IP // Local-to-external IP mapping (k: local, v: external) @@ -75,7 +78,11 @@ type externalIPMapper struct { candidateType CandidateType } -func newExternalIPMapper(candidateType CandidateType, ips []string) (*externalIPMapper, error) { //nolint:gocognit +//nolint:gocognit,cyclop +func newExternalIPMapper( + candidateType CandidateType, + ips []string, +) (*externalIPMapper, error) { if len(ips) == 0 { return nil, nil //nolint:nilnil } @@ -85,7 +92,7 @@ func newExternalIPMapper(candidateType CandidateType, ips []string) (*externalIP return nil, ErrUnsupportedNAT1To1IPCandidateType } - m := &externalIPMapper{ + mapper := &externalIPMapper{ ipv4Mapping: ipMapping{ipMap: map[string]net.IP{}}, ipv6Mapping: ipMapping{ipMap: map[string]net.IP{}}, candidateType: candidateType, @@ -101,13 +108,13 @@ func newExternalIPMapper(candidateType CandidateType, ips []string) (*externalIP if err != nil { return nil, err } - if len(ipPair) == 1 { + if len(ipPair) == 1 { //nolint:nestif if isExtIPv4 { - if err := m.ipv4Mapping.setSoleIP(extIP); err != nil { + if err := mapper.ipv4Mapping.setSoleIP(extIP); err != nil { return nil, err } } else { - if err := m.ipv6Mapping.setSoleIP(extIP); err != nil { + if err := mapper.ipv6Mapping.setSoleIP(extIP); err != nil { return nil, err } } @@ -121,7 +128,7 @@ func newExternalIPMapper(candidateType CandidateType, ips []string) (*externalIP return nil, ErrInvalidNAT1To1IPMapping } - if err := m.ipv4Mapping.addIPMapping(locIP, extIP); err != nil { + if err := mapper.ipv4Mapping.addIPMapping(locIP, extIP); err != nil { return nil, err } } else { @@ -129,14 +136,14 @@ func newExternalIPMapper(candidateType CandidateType, ips []string) (*externalIP return nil, ErrInvalidNAT1To1IPMapping } - if err := m.ipv6Mapping.addIPMapping(locIP, extIP); err != nil { + if err := mapper.ipv6Mapping.addIPMapping(locIP, extIP); err != nil { return nil, err } } } } - return m, nil + return mapper, nil } func (m *externalIPMapper) findExternalIP(localIPStr string) (net.IP, error) { diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/gather.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/gather.go similarity index 74% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/gather.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/gather.go index 15e2da146..a1e024716 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/gather.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/gather.go @@ -9,30 +9,27 @@ import ( "fmt" "io" "net" + "net/netip" "reflect" "sync" - "time" - "github.com/pion/dtls/v2" - "github.com/pion/ice/v2/internal/fakenet" - stunx "github.com/pion/ice/v2/internal/stun" + "github.com/pion/dtls/v3" + "github.com/pion/ice/v4/internal/fakenet" + stunx "github.com/pion/ice/v4/internal/stun" "github.com/pion/logging" - "github.com/pion/stun" - "github.com/pion/turn/v2" + "github.com/pion/stun/v3" + "github.com/pion/turn/v4" ) -const ( - stunGatherTimeout = time.Second * 5 -) - -// Close a net.Conn and log if we have a failure +// Close a net.Conn and log if we have a failure. func closeConnAndLog(c io.Closer, log logging.LeveledLogger, msg string, args ...interface{}) { if c == nil || (reflect.ValueOf(c).Kind() == reflect.Ptr && reflect.ValueOf(c).IsNil()) { log.Warnf("Connection is not allocated: "+msg, args...) + return } - log.Warnf(msg) + log.Warnf(msg, args...) if err := c.Close(); err != nil { log.Warnf("Failed to close connection: %v", err) } @@ -42,12 +39,14 @@ func closeConnAndLog(c io.Closer, log logging.LeveledLogger, msg string, args .. func (a *Agent) GatherCandidates() error { var gatherErr error - if runErr := a.run(a.context(), func(ctx context.Context, agent *Agent) { + if runErr := a.loop.Run(a.loop, func(ctx context.Context) { if a.gatheringState != GatheringStateNew { gatherErr = ErrMultipleGatherAttempted + return } else if a.onCandidateHdlr.Load() == nil { gatherErr = ErrNoOnCandidateHandler + return } @@ -61,13 +60,15 @@ func (a *Agent) GatherCandidates() error { }); runErr != nil { return runErr } + return gatherErr } -func (a *Agent) gatherCandidates(ctx context.Context, done chan struct{}) { +func (a *Agent) gatherCandidates(ctx context.Context, done chan struct{}) { //nolint:cyclop defer close(done) if err := a.setGatheringState(GatheringStateGathering); err != nil { //nolint:contextcheck a.log.Warnf("Failed to set gatheringState to GatheringStateGathering: %v", err) + return } @@ -115,7 +116,8 @@ func (a *Agent) gatherCandidates(ctx context.Context, done chan struct{}) { } } -func (a *Agent) gatherCandidatesLocal(ctx context.Context, networkTypes []NetworkType) { //nolint:gocognit +//nolint:gocognit,gocyclo,cyclop +func (a *Agent) gatherCandidatesLocal(ctx context.Context, networkTypes []NetworkType) { networks := map[string]struct{}{} for _, networkType := range networkTypes { if networkType.IsTCP() { @@ -133,25 +135,40 @@ func (a *Agent) gatherCandidatesLocal(ctx context.Context, networkTypes []Networ delete(networks, udp) } - localIPs, err := localInterfaces(a.net, a.interfaceFilter, a.ipFilter, networkTypes, a.includeLoopback) + _, localAddrs, err := localInterfaces(a.net, a.interfaceFilter, a.ipFilter, networkTypes, a.includeLoopback) if err != nil { a.log.Warnf("Failed to iterate local interfaces, host candidates will not be gathered %s", err) + return } - for _, ip := range localIPs { - mappedIP := ip - if a.mDNSMode != MulticastDNSModeQueryAndGather && a.extIPMapper != nil && a.extIPMapper.candidateType == CandidateTypeHost { - if _mappedIP, innerErr := a.extIPMapper.findExternalIP(ip.String()); innerErr == nil { - mappedIP = _mappedIP + for _, addr := range localAddrs { + mappedIP := addr + if a.mDNSMode != MulticastDNSModeQueryAndGather && + a.extIPMapper != nil && a.extIPMapper.candidateType == CandidateTypeHost { + if _mappedIP, innerErr := a.extIPMapper.findExternalIP(addr.String()); innerErr == nil { + conv, ok := netip.AddrFromSlice(_mappedIP) + if !ok { + a.log.Warnf("failed to convert mapped external IP to netip.Addr'%s'", addr.String()) + + continue + } + // we'd rather have an IPv4-mapped IPv6 become IPv4 so that it is usable + mappedIP = conv.Unmap() } else { - a.log.Warnf("1:1 NAT mapping is enabled but no external IP is found for %s", ip.String()) + a.log.Warnf("1:1 NAT mapping is enabled but no external IP is found for %s", addr.String()) } } address := mappedIP.String() + var isLocationTracked bool if a.mDNSMode == MulticastDNSModeQueryAndGather { address = a.mDNSName + } else { + // Here, we are not doing multicast gathering, so we will need to skip this address so + // that we don't accidentally reveal location tracking information. Otherwise, the + // case above hides the IP behind an mDNS address. + isLocationTracked = shouldFilterLocationTrackedIP(mappedIP) } for network := range networks { @@ -174,16 +191,20 @@ func (a *Agent) gatherCandidatesLocal(ctx context.Context, networkTypes []Networ var muxConns []net.PacketConn if multi, ok := a.tcpMux.(AllConnsGetter); ok { a.log.Debugf("GetAllConns by ufrag: %s", a.localUfrag) - muxConns, err = multi.GetAllConns(a.localUfrag, mappedIP.To4() == nil, ip) + // Note: this is missing zone for IPv6 by just grabbing the IP slice + muxConns, err = multi.GetAllConns(a.localUfrag, mappedIP.Is6(), addr.AsSlice()) if err != nil { - a.log.Warnf("Failed to get all TCP connections by ufrag: %s %s %s", network, ip, a.localUfrag) + a.log.Warnf("Failed to get all TCP connections by ufrag: %s %s %s", network, addr, a.localUfrag) + continue } } else { a.log.Debugf("GetConn by ufrag: %s", a.localUfrag) - conn, err := a.tcpMux.GetConnByUfrag(a.localUfrag, mappedIP.To4() == nil, ip) + // Note: this is missing zone for IPv6 by just grabbing the IP slice + conn, err := a.tcpMux.GetConnByUfrag(a.localUfrag, mappedIP.Is6(), addr.AsSlice()) if err != nil { - a.log.Warnf("Failed to get TCP connections by ufrag: %s %s %s", network, ip, a.localUfrag) + a.log.Warnf("Failed to get TCP connections by ufrag: %s %s %s", network, addr, a.localUfrag) + continue } muxConns = []net.PacketConn{conn} @@ -194,7 +215,7 @@ func (a *Agent) gatherCandidatesLocal(ctx context.Context, networkTypes []Networ if tcpConn, ok := conn.LocalAddr().(*net.TCPAddr); ok { conns = append(conns, connAndPort{conn, tcpConn.Port}) } else { - a.log.Warnf("Failed to get port of connection from TCPMux: %s %s %s", network, ip, a.localUfrag) + a.log.Warnf("Failed to get port of connection from TCPMux: %s %s %s", network, addr, a.localUfrag) } } if len(conns) == 0 { @@ -205,16 +226,22 @@ func (a *Agent) gatherCandidatesLocal(ctx context.Context, networkTypes []Networ // Is there a way to verify that the listen address is even // accessible from the current interface. case udp: - conn, err := listenUDPInPortRange(a.net, a.log, int(a.portMax), int(a.portMin), network, &net.UDPAddr{IP: ip, Port: 0}) + conn, err := listenUDPInPortRange(a.net, a.log, int(a.portMax), int(a.portMin), network, &net.UDPAddr{ + IP: addr.AsSlice(), + Port: 0, + Zone: addr.Zone(), + }) if err != nil { - a.log.Warnf("Failed to listen %s %s", network, ip) + a.log.Warnf("Failed to listen %s %s", network, addr) + continue } if udpConn, ok := conn.LocalAddr().(*net.UDPAddr); ok { conns = append(conns, connAndPort{conn, udpConn.Port}) } else { - a.log.Warnf("Failed to get port of UDPAddr from ListenUDPInPortRange: %s %s %s", network, ip, a.localUfrag) + a.log.Warnf("Failed to get port of UDPAddr from ListenUDPInPortRange: %s %s %s", network, addr, a.localUfrag) + continue } } @@ -226,23 +253,43 @@ func (a *Agent) gatherCandidatesLocal(ctx context.Context, networkTypes []Networ Port: connAndPort.port, Component: ComponentRTP, TCPType: tcpType, + // we will still process this candidate so that we start up the right + // listeners. + IsLocationTracked: isLocationTracked, } - c, err := NewCandidateHost(&hostConfig) + candidateHost, err := NewCandidateHost(&hostConfig) if err != nil { - closeConnAndLog(connAndPort.conn, a.log, "failed to create host candidate: %s %s %d: %v", network, mappedIP, connAndPort.port, err) + closeConnAndLog( + connAndPort.conn, + a.log, + "failed to create host candidate: %s %s %d: %v", + network, mappedIP, + connAndPort.port, + err, + ) + continue } if a.mDNSMode == MulticastDNSModeQueryAndGather { - if err = c.setIP(ip); err != nil { - closeConnAndLog(connAndPort.conn, a.log, "failed to create host candidate: %s %s %d: %v", network, mappedIP, connAndPort.port, err) + if err = candidateHost.setIPAddr(addr); err != nil { + closeConnAndLog( + connAndPort.conn, + a.log, + "failed to create host candidate: %s %s %d: %v", + network, + mappedIP, + connAndPort.port, + err, + ) + continue } } - if err := a.addCandidate(ctx, c, connAndPort.conn); err != nil { - if closeErr := c.close(); closeErr != nil { + if err := a.addCandidate(ctx, candidateHost, connAndPort.conn); err != nil { + if closeErr := candidateHost.close(); closeErr != nil { a.log.Warnf("Failed to close candidate: %v", closeErr) } a.log.Warnf("Failed to append to localCandidates and run onCandidateHdlr: %v", err) @@ -252,7 +299,29 @@ func (a *Agent) gatherCandidatesLocal(ctx context.Context, networkTypes []Networ } } -func (a *Agent) gatherCandidatesLocalUDPMux(ctx context.Context) error { //nolint:gocognit +// shouldFilterLocationTrackedIP returns if this candidate IP should be filtered out from +// any candidate publishing/notification for location tracking reasons. +func shouldFilterLocationTrackedIP(candidateIP netip.Addr) bool { + // https://tools.ietf.org/html/rfc8445#section-5.1.1.1 + // Similarly, when host candidates corresponding to + // an IPv6 address generated using a mechanism that prevents location + // tracking are gathered, then host candidates corresponding to IPv6 + // link-local addresses [RFC4291] MUST NOT be gathered. + return candidateIP.Is6() && (candidateIP.IsLinkLocalUnicast() || candidateIP.IsLinkLocalMulticast()) +} + +// shouldFilterLocationTracked returns if this candidate IP should be filtered out from +// any candidate publishing/notification for location tracking reasons. +func shouldFilterLocationTracked(candidateIP net.IP) bool { + addr, ok := netip.AddrFromSlice(candidateIP) + if !ok { + return false + } + + return shouldFilterLocationTrackedIP(addr) +} + +func (a *Agent) gatherCandidatesLocalUDPMux(ctx context.Context) error { //nolint:gocognit,cyclop if a.udpMux == nil { return errUDPMuxDisabled } @@ -266,21 +335,44 @@ func (a *Agent) gatherCandidatesLocalUDPMux(ctx context.Context) error { //nolin return errInvalidAddress } candidateIP := udpAddr.IP - if a.extIPMapper != nil && a.extIPMapper.candidateType == CandidateTypeHost { + + if _, ok := a.udpMux.(*UDPMuxDefault); ok && !a.includeLoopback && candidateIP.IsLoopback() { + // Unlike MultiUDPMux Default, UDPMuxDefault doesn't have + // a separate param to include loopback, so we respect agent config + continue + } + + if a.mDNSMode != MulticastDNSModeQueryAndGather && + a.extIPMapper != nil && + a.extIPMapper.candidateType == CandidateTypeHost { mappedIP, err := a.extIPMapper.findExternalIP(candidateIP.String()) if err != nil { a.log.Warnf("1:1 NAT mapping is enabled but no external IP is found for %s", candidateIP.String()) + continue } candidateIP = mappedIP } + var address string + var isLocationTracked bool + if a.mDNSMode == MulticastDNSModeQueryAndGather { + address = a.mDNSName + } else { + address = candidateIP.String() + // Here, we are not doing multicast gathering, so we will need to skip this address so + // that we don't accidentally reveal location tracking information. Otherwise, the + // case above hides the IP behind an mDNS address. + isLocationTracked = shouldFilterLocationTracked(candidateIP) + } + hostConfig := CandidateHostConfig{ - Network: udp, - Address: candidateIP.String(), - Port: udpAddr.Port, - Component: ComponentRTP, + Network: udp, + Address: address, + Port: udpAddr.Port, + Component: ComponentRTP, + IsLocationTracked: isLocationTracked, } // Detect a duplicate candidate before calling addCandidate(). @@ -299,6 +391,7 @@ func (a *Agent) gatherCandidatesLocalUDPMux(ctx context.Context) error { //nolin c, err := NewCandidateHost(&hostConfig) if err != nil { closeConnAndLog(conn, a.log, "failed to create host mux candidate: %s %d: %v", candidateIP, udpAddr.Port, err) + continue } @@ -308,6 +401,7 @@ func (a *Agent) gatherCandidatesLocalUDPMux(ctx context.Context) error { //nolin } closeConnAndLog(conn, a.log, "failed to add candidate: %s %d: %v", candidateIP, udpAddr.Port, err) + continue } @@ -331,21 +425,37 @@ func (a *Agent) gatherCandidatesSrflxMapped(ctx context.Context, networkTypes [] go func() { defer wg.Done() - conn, err := listenUDPInPortRange(a.net, a.log, int(a.portMax), int(a.portMin), network, &net.UDPAddr{IP: nil, Port: 0}) + conn, err := listenUDPInPortRange( + a.net, + a.log, + int(a.portMax), + int(a.portMin), + network, + &net.UDPAddr{IP: nil, Port: 0}, + ) if err != nil { a.log.Warnf("Failed to listen %s: %v", network, err) + return } lAddr, ok := conn.LocalAddr().(*net.UDPAddr) if !ok { closeConnAndLog(conn, a.log, "1:1 NAT mapping is enabled but LocalAddr is not a UDPAddr") + return } mappedIP, err := a.extIPMapper.findExternalIP(lAddr.IP.String()) if err != nil { closeConnAndLog(conn, a.log, "1:1 NAT mapping is enabled but no external IP is found for %s", lAddr.IP.String()) + + return + } + + if shouldFilterLocationTracked(mappedIP) { + closeConnAndLog(conn, a.log, "external IP is somehow filtered for location tracking reasons %s", mappedIP) + return } @@ -364,6 +474,7 @@ func (a *Agent) gatherCandidatesSrflxMapped(ctx context.Context, networkTypes [] mappedIP.String(), lAddr.Port, err) + return } @@ -377,7 +488,8 @@ func (a *Agent) gatherCandidatesSrflxMapped(ctx context.Context, networkTypes [] } } -func (a *Agent) gatherCandidatesSrflxUDPMux(ctx context.Context, urls []*stun.URI, networkTypes []NetworkType) { //nolint:gocognit +//nolint:gocognit,cyclop +func (a *Agent) gatherCandidatesSrflxUDPMux(ctx context.Context, urls []*stun.URI, networkTypes []NetworkType) { var wg sync.WaitGroup defer wg.Wait() @@ -391,6 +503,7 @@ func (a *Agent) gatherCandidatesSrflxUDPMux(ctx context.Context, urls []*stun.UR udpAddr, ok := listenAddr.(*net.UDPAddr) if !ok { a.log.Warn("Failed to cast udpMuxSrflx listen address to UDPAddr") + continue } wg.Add(1) @@ -400,19 +513,28 @@ func (a *Agent) gatherCandidatesSrflxUDPMux(ctx context.Context, urls []*stun.UR hostPort := fmt.Sprintf("%s:%d", url.Host, url.Port) serverAddr, err := a.net.ResolveUDPAddr(network, hostPort) if err != nil { - a.log.Warnf("Failed to resolve STUN host: %s: %v", hostPort, err) + a.log.Debugf("Failed to resolve STUN host: %s %s: %v", network, hostPort, err) + return } - xorAddr, err := a.udpMuxSrflx.GetXORMappedAddr(serverAddr, stunGatherTimeout) + if shouldFilterLocationTracked(serverAddr.IP) { + a.log.Warnf("STUN host %s is somehow filtered for location tracking reasons", hostPort) + + return + } + + xorAddr, err := a.udpMuxSrflx.GetXORMappedAddr(serverAddr, a.stunGatherTimeout) if err != nil { a.log.Warnf("Failed get server reflexive address %s %s: %v", network, url, err) + return } conn, err := a.udpMuxSrflx.GetConnForURL(a.localUfrag, url.String(), localAddr) if err != nil { a.log.Warnf("Failed to find connection in UDPMuxSrflx %s %s: %v", network, url, err) + return } @@ -430,6 +552,7 @@ func (a *Agent) gatherCandidatesSrflxUDPMux(ctx context.Context, urls []*stun.UR c, err := NewCandidateServerReflexive(&srflxConfig) if err != nil { closeConnAndLog(conn, a.log, "failed to create server reflexive candidate: %s %s %d: %v", network, ip, port, err) + return } @@ -445,7 +568,8 @@ func (a *Agent) gatherCandidatesSrflxUDPMux(ctx context.Context, urls []*stun.UR } } -func (a *Agent) gatherCandidatesSrflx(ctx context.Context, urls []*stun.URI, networkTypes []NetworkType) { //nolint:gocognit +//nolint:cyclop,gocognit +func (a *Agent) gatherCandidatesSrflx(ctx context.Context, urls []*stun.URI, networkTypes []NetworkType) { var wg sync.WaitGroup defer wg.Wait() @@ -462,13 +586,28 @@ func (a *Agent) gatherCandidatesSrflx(ctx context.Context, urls []*stun.URI, net hostPort := fmt.Sprintf("%s:%d", url.Host, url.Port) serverAddr, err := a.net.ResolveUDPAddr(network, hostPort) if err != nil { - a.log.Warnf("Failed to resolve STUN host: %s: %v", hostPort, err) + a.log.Debugf("Failed to resolve STUN host: %s %s: %v", network, hostPort, err) + return } - conn, err := listenUDPInPortRange(a.net, a.log, int(a.portMax), int(a.portMin), network, &net.UDPAddr{IP: nil, Port: 0}) + if shouldFilterLocationTracked(serverAddr.IP) { + a.log.Warnf("STUN host %s is somehow filtered for location tracking reasons", hostPort) + + return + } + + conn, err := listenUDPInPortRange( + a.net, + a.log, + int(a.portMax), + int(a.portMin), + network, + &net.UDPAddr{IP: nil, Port: 0}, + ) if err != nil { closeConnAndLog(conn, a.log, "failed to listen for %s: %v", serverAddr.String(), err) + return } // If the agent closes midway through the connection @@ -479,14 +618,15 @@ func (a *Agent) gatherCandidatesSrflx(ctx context.Context, urls []*stun.URI, net select { case <-cancelCtx.Done(): return - case <-a.done: + case <-a.loop.Done(): _ = conn.Close() } }() - xorAddr, err := stunx.GetXORMappedAddr(conn, serverAddr, stunGatherTimeout) + xorAddr, err := stunx.GetXORMappedAddr(conn, serverAddr, a.stunGatherTimeout) if err != nil { closeConnAndLog(conn, a.log, "failed to get server reflexive address %s %s: %v", network, url, err) + return } @@ -505,6 +645,7 @@ func (a *Agent) gatherCandidatesSrflx(ctx context.Context, urls []*stun.URI, net c, err := NewCandidateServerReflexive(&srflxConfig) if err != nil { closeConnAndLog(conn, a.log, "failed to create server reflexive candidate: %s %s %d: %v", network, ip, port, err) + return } @@ -519,7 +660,8 @@ func (a *Agent) gatherCandidatesSrflx(ctx context.Context, urls []*stun.URI, net } } -func (a *Agent) gatherCandidatesRelay(ctx context.Context, urls []*stun.URI) { //nolint:gocognit +//nolint:maintidx,gocognit,gocyclo,cyclop +func (a *Agent) gatherCandidatesRelay(ctx context.Context, urls []*stun.URI) { var wg sync.WaitGroup defer wg.Wait() @@ -530,9 +672,11 @@ func (a *Agent) gatherCandidatesRelay(ctx context.Context, urls []*stun.URI) { / continue case urls[i].Username == "": a.log.Errorf("Failed to gather relay candidates: %v", ErrUsernameEmpty) + return case urls[i].Password == "": a.log.Errorf("Failed to gather relay candidates: %v", ErrPasswordEmpty) + return } @@ -552,6 +696,7 @@ func (a *Agent) gatherCandidatesRelay(ctx context.Context, urls []*stun.URI) { / case url.Proto == stun.ProtoTypeUDP && url.Scheme == stun.SchemeTypeTURN: if locConn, err = a.net.ListenPacket(network, "0.0.0.0:0"); err != nil { a.log.Warnf("Failed to listen %s: %v", network, err) + return } @@ -563,6 +708,7 @@ func (a *Agent) gatherCandidatesRelay(ctx context.Context, urls []*stun.URI) { / conn, connectErr := a.proxyDialer.Dial(NetworkTypeTCP4.String(), turnServerAddr) if connectErr != nil { a.log.Warnf("Failed to dial TCP address %s via proxy dialer: %v", turnServerAddr, connectErr) + return } @@ -579,12 +725,14 @@ func (a *Agent) gatherCandidatesRelay(ctx context.Context, urls []*stun.URI) { / tcpAddr, connectErr := a.net.ResolveTCPAddr(NetworkTypeTCP4.String(), turnServerAddr) if connectErr != nil { a.log.Warnf("Failed to resolve TCP address %s: %v", turnServerAddr, connectErr) + return } conn, connectErr := a.net.DialTCP(NetworkTypeTCP4.String(), nil, tcpAddr) if connectErr != nil { a.log.Warnf("Failed to dial TCP address %s: %v", turnServerAddr, connectErr) + return } @@ -596,38 +744,50 @@ func (a *Agent) gatherCandidatesRelay(ctx context.Context, urls []*stun.URI) { / udpAddr, connectErr := a.net.ResolveUDPAddr(network, turnServerAddr) if connectErr != nil { a.log.Warnf("Failed to resolve UDP address %s: %v", turnServerAddr, connectErr) + return } udpConn, dialErr := a.net.DialUDP("udp", nil, udpAddr) if dialErr != nil { a.log.Warnf("Failed to dial DTLS address %s: %v", turnServerAddr, dialErr) + return } - conn, connectErr := dtls.ClientWithContext(ctx, udpConn, &dtls.Config{ + conn, connectErr := dtls.Client(&fakenet.PacketConn{Conn: udpConn}, udpConn.RemoteAddr(), &dtls.Config{ ServerName: url.Host, InsecureSkipVerify: a.insecureSkipVerify, //nolint:gosec + LoggerFactory: a.loggerFactory, }) if connectErr != nil { a.log.Warnf("Failed to create DTLS client: %v", turnServerAddr, connectErr) + + return + } + + if connectErr = conn.HandshakeContext(ctx); connectErr != nil { + a.log.Warnf("Failed to create DTLS client: %v", turnServerAddr, connectErr) + return } relAddr = conn.LocalAddr().(*net.UDPAddr).IP.String() //nolint:forcetypeassert relPort = conn.LocalAddr().(*net.UDPAddr).Port //nolint:forcetypeassert - relayProtocol = "dtls" + relayProtocol = relayProtocolDTLS locConn = &fakenet.PacketConn{Conn: conn} case url.Proto == stun.ProtoTypeTCP && url.Scheme == stun.SchemeTypeTURNS: tcpAddr, resolvErr := a.net.ResolveTCPAddr(NetworkTypeTCP4.String(), turnServerAddr) if resolvErr != nil { a.log.Warnf("Failed to resolve relay address %s: %v", turnServerAddr, resolvErr) + return } tcpConn, dialErr := a.net.DialTCP(NetworkTypeTCP4.String(), nil, tcpAddr) if dialErr != nil { a.log.Warnf("Failed to connect to relay: %v", dialErr) + return } @@ -641,15 +801,17 @@ func (a *Agent) gatherCandidatesRelay(ctx context.Context, urls []*stun.URI) { / a.log.Errorf("Failed to close relay connection: %v", closeErr) } a.log.Warnf("Failed to connect to relay: %v", hsErr) + return } relAddr = conn.LocalAddr().(*net.TCPAddr).IP.String() //nolint:forcetypeassert relPort = conn.LocalAddr().(*net.TCPAddr).Port //nolint:forcetypeassert - relayProtocol = "tls" + relayProtocol = relayProtocolTLS locConn = turn.NewSTUNConn(conn) default: a.log.Warnf("Unable to handle URL in gatherCandidatesRelay %v", url) + return } @@ -663,12 +825,14 @@ func (a *Agent) gatherCandidatesRelay(ctx context.Context, urls []*stun.URI) { / }) if err != nil { closeConnAndLog(locConn, a.log, "failed to create new TURN client %s %s", turnServerAddr, err) + return } if err = client.Listen(); err != nil { client.Close() closeConnAndLog(locConn, a.log, "failed to listen on TURN client %s %s", turnServerAddr, err) + return } @@ -676,10 +840,18 @@ func (a *Agent) gatherCandidatesRelay(ctx context.Context, urls []*stun.URI) { / if err != nil { client.Close() closeConnAndLog(locConn, a.log, "failed to allocate on TURN client %s %s", turnServerAddr, err) + return } rAddr := relayConn.LocalAddr().(*net.UDPAddr) //nolint:forcetypeassert + + if shouldFilterLocationTracked(rAddr.IP) { + a.log.Warnf("TURN address %s is somehow filtered for location tracking reasons", rAddr.IP) + + return + } + relayConfig := CandidateRelayConfig{ Network: network, Component: ComponentRTP, @@ -690,6 +862,7 @@ func (a *Agent) gatherCandidatesRelay(ctx context.Context, urls []*stun.URI) { / RelayProtocol: relayProtocol, OnClose: func() error { client.Close() + return locConn.Close() }, } @@ -704,6 +877,7 @@ func (a *Agent) gatherCandidatesRelay(ctx context.Context, urls []*stun.URI) { / client.Close() closeConnAndLog(locConn, a.log, "failed to create relay candidate: %s %s: %v", network, rAddr.String(), err) + return } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/ice.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/ice.go similarity index 78% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/ice.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/ice.go index bd551206e..bd53702f5 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/ice.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/ice.go @@ -3,33 +3,33 @@ package ice -// ConnectionState is an enum showing the state of a ICE Connection +// ConnectionState is an enum showing the state of a ICE Connection. type ConnectionState int -// List of supported States +// List of supported States. const ( - // ConnectionStateUnknown represents an unknown state + // ConnectionStateUnknown represents an unknown state. ConnectionStateUnknown ConnectionState = iota - // ConnectionStateNew ICE agent is gathering addresses + // ConnectionStateNew ICE agent is gathering addresses. ConnectionStateNew - // ConnectionStateChecking ICE agent has been given local and remote candidates, and is attempting to find a match + // ConnectionStateChecking ICE agent has been given local and remote candidates, and is attempting to find a match. ConnectionStateChecking - // ConnectionStateConnected ICE agent has a pairing, but is still checking other pairs + // ConnectionStateConnected ICE agent has a pairing, but is still checking other pairs. ConnectionStateConnected - // ConnectionStateCompleted ICE agent has finished + // ConnectionStateCompleted ICE agent has finished. ConnectionStateCompleted - // ConnectionStateFailed ICE agent never could successfully connect + // ConnectionStateFailed ICE agent never could successfully connect. ConnectionStateFailed - // ConnectionStateDisconnected ICE agent connected successfully, but has entered a failed state + // ConnectionStateDisconnected ICE agent connected successfully, but has entered a failed state. ConnectionStateDisconnected - // ConnectionStateClosed ICE agent has finished and is no longer handling requests + // ConnectionStateClosed ICE agent has finished and is no longer handling requests. ConnectionStateClosed ) @@ -54,20 +54,20 @@ func (c ConnectionState) String() string { } } -// GatheringState describes the state of the candidate gathering process +// GatheringState describes the state of the candidate gathering process. type GatheringState int const ( - // GatheringStateUnknown represents an unknown state + // GatheringStateUnknown represents an unknown state. GatheringStateUnknown GatheringState = iota - // GatheringStateNew indicates candidate gathering is not yet started + // GatheringStateNew indicates candidate gathering is not yet started. GatheringStateNew - // GatheringStateGathering indicates candidate gathering is ongoing + // GatheringStateGathering indicates candidate gathering is ongoing. GatheringStateGathering - // GatheringStateComplete indicates candidate gathering has been completed + // GatheringStateComplete indicates candidate gathering has been completed. GatheringStateComplete ) @@ -83,3 +83,8 @@ func (t GatheringState) String() string { return ErrUnknownType.Error() } } + +const ( + relayProtocolDTLS = "dtls" + relayProtocolTLS = "tls" +) diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/icecontrol.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/icecontrol.go similarity index 98% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/icecontrol.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/icecontrol.go index b086bd892..fcf08a0ed 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/icecontrol.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/icecontrol.go @@ -6,7 +6,7 @@ package ice import ( "encoding/binary" - "github.com/pion/stun" + "github.com/pion/stun/v3" ) // tiebreaker is common helper for ICE-{CONTROLLED,CONTROLLING} @@ -20,6 +20,7 @@ func (a tiebreaker) AddToAs(m *stun.Message, t stun.AttrType) error { v := make([]byte, tiebreakerSize) binary.BigEndian.PutUint64(v, uint64(a)) m.Add(t, v) + return nil } @@ -33,6 +34,7 @@ func (a *tiebreaker) GetFromAs(m *stun.Message, t stun.AttrType) error { return err } *a = tiebreaker(binary.BigEndian.Uint64(v)) + return nil } @@ -73,6 +75,7 @@ func (c AttrControl) AddTo(m *stun.Message) error { if c.Role == Controlling { return tiebreaker(c.Tiebreaker).AddToAs(m, stun.AttrICEControlling) } + return tiebreaker(c.Tiebreaker).AddToAs(m, stun.AttrICEControlled) } @@ -80,11 +83,14 @@ func (c AttrControl) AddTo(m *stun.Message) error { func (c *AttrControl) GetFrom(m *stun.Message) error { if m.Contains(stun.AttrICEControlling) { c.Role = Controlling + return (*tiebreaker)(&c.Tiebreaker).GetFromAs(m, stun.AttrICEControlling) } if m.Contains(stun.AttrICEControlled) { c.Role = Controlled + return (*tiebreaker)(&c.Tiebreaker).GetFromAs(m, stun.AttrICEControlled) } + return stun.ErrAttributeNotFound } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/internal/atomic/atomic.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/internal/atomic/atomic.go similarity index 73% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/internal/atomic/atomic.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/internal/atomic/atomic.go index f8caf5a2e..f170133b0 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/internal/atomic/atomic.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/internal/atomic/atomic.go @@ -6,18 +6,19 @@ package atomic import "sync/atomic" -// Error is an atomic error +// Error is an atomic error. type Error struct { v atomic.Value } -// Store updates the value of the atomic variable +// Store updates the value of the atomic variable. func (a *Error) Store(err error) { a.v.Store(struct{ error }{err}) } -// Load retrieves the current value of the atomic variable +// Load retrieves the current value of the atomic variable. func (a *Error) Load() error { err, _ := a.v.Load().(struct{ error }) + return err.error } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/internal/fakenet/mock_conn.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/internal/fakenet/mock_conn.go similarity index 97% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/internal/fakenet/mock_conn.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/internal/fakenet/mock_conn.go index cc98849d5..baf012ab5 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/internal/fakenet/mock_conn.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/internal/fakenet/mock_conn.go @@ -11,7 +11,7 @@ import ( "time" ) -// MockPacketConn for tests +// MockPacketConn for tests. type MockPacketConn struct{} func (m *MockPacketConn) ReadFrom([]byte) (n int, addr net.Addr, err error) { return 0, nil, nil } //nolint:revive diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/internal/fakenet/packet_conn.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/internal/fakenet/packet_conn.go similarity index 80% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/internal/fakenet/packet_conn.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/internal/fakenet/packet_conn.go index 0b9faaa84..f9cb66fdd 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/internal/fakenet/packet_conn.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/internal/fakenet/packet_conn.go @@ -8,18 +8,19 @@ import ( "net" ) -// Compile-time assertion +// Compile-time assertion. var _ net.PacketConn = (*PacketConn)(nil) -// PacketConn wraps a net.Conn and emulates net.PacketConn +// PacketConn wraps a net.Conn and emulates net.PacketConn. type PacketConn struct { net.Conn } -// ReadFrom reads a packet from the connection, +// ReadFrom reads a packet from the connection. func (f *PacketConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) { n, err = f.Conn.Read(p) addr = f.Conn.RemoteAddr() + return } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/internal/stun/stun.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/internal/stun/stun.go similarity index 96% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/internal/stun/stun.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/internal/stun/stun.go index 230cf850a..55ccb9b4a 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/internal/stun/stun.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/internal/stun/stun.go @@ -10,7 +10,7 @@ import ( "net" "time" - "github.com/pion/stun" + "github.com/pion/stun/v3" ) var ( @@ -59,7 +59,7 @@ func GetXORMappedAddr(conn net.PacketConn, serverAddr net.Addr, timeout time.Dur return &addr, nil } -// AssertUsername checks that the given STUN message m has a USERNAME attribute with a given value +// AssertUsername checks that the given STUN message m has a USERNAME attribute with a given value. func AssertUsername(m *stun.Message, expectedUsername string) error { var username stun.Username if err := username.GetFrom(m); err != nil { diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/internal/taskloop/taskloop.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/internal/taskloop/taskloop.go new file mode 100644 index 000000000..15a266654 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/internal/taskloop/taskloop.go @@ -0,0 +1,121 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + +// Package taskloop implements a task loop to run +// tasks sequentially in a separate Goroutine. +package taskloop + +import ( + "context" + "errors" + "time" + + atomicx "github.com/pion/ice/v4/internal/atomic" +) + +// ErrClosed indicates that the loop has been stopped. +var ErrClosed = errors.New("the agent is closed") + +type task struct { + fn func(context.Context) + done chan struct{} +} + +// Loop runs submitted task serially in a dedicated Goroutine. +type Loop struct { + tasks chan task + + // State for closing + done chan struct{} + taskLoopDone chan struct{} + err atomicx.Error +} + +// New creates and starts a new task loop. +func New(onClose func()) *Loop { + l := &Loop{ + tasks: make(chan task), + done: make(chan struct{}), + taskLoopDone: make(chan struct{}), + } + + go l.runLoop(onClose) + + return l +} + +// runLoop handles registered tasks and agent close. +func (l *Loop) runLoop(onClose func()) { + defer func() { + onClose() + close(l.taskLoopDone) + }() + + for { + select { + case <-l.done: + return + case t := <-l.tasks: + t.fn(l) + close(t.done) + } + } +} + +// Close stops the loop after finishing the execution of the current task. +// Other pending tasks will not be executed. +func (l *Loop) Close() { + if err := l.Err(); err != nil { + return + } + + l.err.Store(ErrClosed) + + close(l.done) + <-l.taskLoopDone +} + +// Run serially executes the submitted callback. +// Blocking tasks must be cancelable by context. +func (l *Loop) Run(ctx context.Context, t func(context.Context)) error { + if err := l.Err(); err != nil { + return err + } + done := make(chan struct{}) + select { + case <-ctx.Done(): + return ctx.Err() + case l.tasks <- task{t, done}: + <-done + + return nil + } +} + +// The following methods implement context.Context for TaskLoop + +// Done returns a channel that's closed when the task loop has been stopped. +func (l *Loop) Done() <-chan struct{} { + return l.done +} + +// Err returns nil if the task loop is still running. +// Otherwise it return errClosed if the loop has been closed/stopped. +func (l *Loop) Err() error { + select { + case <-l.done: + return ErrClosed + default: + return nil + } +} + +// Deadline returns the no valid time as task loops have no deadline. +func (l *Loop) Deadline() (deadline time.Time, ok bool) { + return time.Time{}, false +} + +// Value is not supported for task loops. +func (l *Loop) Value(interface{}) interface{} { + return nil +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/mdns.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/mdns.go new file mode 100644 index 000000000..b88909d29 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/mdns.go @@ -0,0 +1,144 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + +package ice + +import ( + "net" + + "github.com/google/uuid" + "github.com/pion/logging" + "github.com/pion/mdns/v2" + "github.com/pion/transport/v3" + "golang.org/x/net/ipv4" + "golang.org/x/net/ipv6" +) + +// MulticastDNSMode represents the different Multicast modes ICE can run in. +type MulticastDNSMode byte + +// MulticastDNSMode enum. +const ( + // MulticastDNSModeDisabled means remote mDNS candidates will be discarded, and local host candidates will use IPs. + MulticastDNSModeDisabled MulticastDNSMode = iota + 1 + + // MulticastDNSModeQueryOnly means remote mDNS candidates will be accepted, and local host candidates will use IPs. + MulticastDNSModeQueryOnly + + // MulticastDNSModeQueryAndGather means remote mDNS candidates will be accepted, + // and local host candidates will use mDNS. + MulticastDNSModeQueryAndGather +) + +func generateMulticastDNSName() (string, error) { + // https://tools.ietf.org/id/draft-ietf-rtcweb-mdns-ice-candidates-02.html#gathering + // The unique name MUST consist of a version 4 UUID as defined in [RFC4122], followed by “.local”. + u, err := uuid.NewRandom() + + return u.String() + ".local", err +} + +//nolint:cyclop +func createMulticastDNS( + netTransport transport.Net, + networkTypes []NetworkType, + interfaces []*transport.Interface, + includeLoopback bool, + mDNSMode MulticastDNSMode, + mDNSName string, + log logging.LeveledLogger, + loggerFactory logging.LoggerFactory, +) (*mdns.Conn, MulticastDNSMode, error) { + if mDNSMode == MulticastDNSModeDisabled { + return nil, mDNSMode, nil + } + + var useV4, useV6 bool + if len(networkTypes) == 0 { + useV4 = true + useV6 = true + } else { + for _, nt := range networkTypes { + if nt.IsIPv4() { + useV4 = true + + continue + } + if nt.IsIPv6() { + useV6 = true + } + } + } + + addr4, mdnsErr := netTransport.ResolveUDPAddr("udp4", mdns.DefaultAddressIPv4) + if mdnsErr != nil { + return nil, mDNSMode, mdnsErr + } + addr6, mdnsErr := netTransport.ResolveUDPAddr("udp6", mdns.DefaultAddressIPv6) + if mdnsErr != nil { + return nil, mDNSMode, mdnsErr + } + + var pktConnV4 *ipv4.PacketConn + var mdns4Err error + if useV4 { + var l transport.UDPConn + l, mdns4Err = netTransport.ListenUDP("udp4", addr4) + if mdns4Err != nil { + // If ICE fails to start MulticastDNS server just warn the user and continue + log.Errorf("Failed to enable mDNS over IPv4: (%s)", mdns4Err) + + return nil, MulticastDNSModeDisabled, nil + } + pktConnV4 = ipv4.NewPacketConn(l) + } + + var pktConnV6 *ipv6.PacketConn + var mdns6Err error + if useV6 { + var l transport.UDPConn + l, mdns6Err = netTransport.ListenUDP("udp6", addr6) + if mdns6Err != nil { + log.Errorf("Failed to enable mDNS over IPv6: (%s)", mdns6Err) + + return nil, MulticastDNSModeDisabled, nil + } + pktConnV6 = ipv6.NewPacketConn(l) + } + + if mdns4Err != nil && mdns6Err != nil { + // If ICE fails to start MulticastDNS server just warn the user and continue + log.Errorf("Failed to enable mDNS, continuing in mDNS disabled mode") + //nolint:nilerr + return nil, MulticastDNSModeDisabled, nil + } + var ifcs []net.Interface + if interfaces != nil { + ifcs = make([]net.Interface, 0, len(ifcs)) + for _, ifc := range interfaces { + ifcs = append(ifcs, ifc.Interface) + } + } + + switch mDNSMode { + case MulticastDNSModeQueryOnly: + conn, err := mdns.Server(pktConnV4, pktConnV6, &mdns.Config{ + Interfaces: ifcs, + IncludeLoopback: includeLoopback, + LoggerFactory: loggerFactory, + }) + + return conn, mDNSMode, err + case MulticastDNSModeQueryAndGather: + conn, err := mdns.Server(pktConnV4, pktConnV6, &mdns.Config{ + Interfaces: ifcs, + IncludeLoopback: includeLoopback, + LocalNames: []string{mDNSName}, + LoggerFactory: loggerFactory, + }) + + return conn, mDNSMode, err + default: + return nil, mDNSMode, nil + } +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/net.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/net.go new file mode 100644 index 000000000..54ec4ca26 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/net.go @@ -0,0 +1,171 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + +package ice + +import ( + "net" + "net/netip" + + "github.com/pion/logging" + "github.com/pion/transport/v3" +) + +// The conditions of invalidation written below are defined in +// https://tools.ietf.org/html/rfc8445#section-5.1.1.1 +// It is partial because the link-local check is done later in various gather local +// candidate methods which conditionally accept IPv6 based on usage of mDNS or not. +func isSupportedIPv6Partial(ip net.IP) bool { + if len(ip) != net.IPv6len || + // Deprecated IPv4-compatible IPv6 addresses [RFC4291] and IPv6 site- + // local unicast addresses [RFC3879] MUST NOT be included in the + // address candidates. + isZeros(ip[0:12]) || // !(IPv4-compatible IPv6) + ip[0] == 0xfe && ip[1]&0xc0 == 0xc0 { // !(IPv6 site-local unicast) + return false + } + + return true +} + +func isZeros(ip net.IP) bool { + for i := 0; i < len(ip); i++ { + if ip[i] != 0 { + return false + } + } + + return true +} + +//nolint:gocognit,cyclop +func localInterfaces( + n transport.Net, + interfaceFilter func(string) (keep bool), + ipFilter func(net.IP) (keep bool), + networkTypes []NetworkType, + includeLoopback bool, +) ([]*transport.Interface, []netip.Addr, error) { + ipAddrs := []netip.Addr{} + ifaces, err := n.Interfaces() + if err != nil { + return nil, ipAddrs, err + } + + filteredIfaces := make([]*transport.Interface, 0, len(ifaces)) + + var ipV4Requested, ipv6Requested bool + if len(networkTypes) == 0 { + ipV4Requested = true + ipv6Requested = true + } else { + for _, typ := range networkTypes { + if typ.IsIPv4() { + ipV4Requested = true + } + + if typ.IsIPv6() { + ipv6Requested = true + } + } + } + + for _, iface := range ifaces { + if iface.Flags&net.FlagUp == 0 { + continue // Interface down + } + if (iface.Flags&net.FlagLoopback != 0) && !includeLoopback { + continue // Loopback interface + } + + if interfaceFilter != nil && !interfaceFilter(iface.Name) { + continue + } + + ifaceAddrs, err := iface.Addrs() + if err != nil { + continue + } + + atLeastOneAddr := false + for _, addr := range ifaceAddrs { + ipAddr, _, _, err := parseAddrFromIface(addr, iface.Name) + if err != nil || (ipAddr.IsLoopback() && !includeLoopback) { + continue + } + if ipAddr.Is6() { + if !ipv6Requested { + continue + } else if !isSupportedIPv6Partial(ipAddr.AsSlice()) { + continue + } + } else if !ipV4Requested { + continue + } + + if ipFilter != nil && !ipFilter(ipAddr.AsSlice()) { + continue + } + + atLeastOneAddr = true + ipAddrs = append(ipAddrs, ipAddr) + } + + if atLeastOneAddr { + ifaceCopy := iface + filteredIfaces = append(filteredIfaces, ifaceCopy) + } + } + + return filteredIfaces, ipAddrs, nil +} + +//nolint:cyclop +func listenUDPInPortRange( + netTransport transport.Net, + log logging.LeveledLogger, + portMax, portMin int, + network string, + lAddr *net.UDPAddr, +) (transport.UDPConn, error) { + if (lAddr.Port != 0) || ((portMin == 0) && (portMax == 0)) { + return netTransport.ListenUDP(network, lAddr) + } + + if portMin == 0 { + portMin = 1024 // Start at 1024 which is non-privileged + } + + if portMax == 0 { + portMax = 0xFFFF + } + + if portMin > portMax { + return nil, ErrPort + } + + portStart := globalMathRandomGenerator.Intn(portMax-portMin+1) + portMin + portCurrent := portStart + for { + addr := &net.UDPAddr{ + IP: lAddr.IP, + Zone: lAddr.Zone, + Port: portCurrent, + } + + c, e := netTransport.ListenUDP(network, addr) + if e == nil { + return c, e //nolint:nilerr + } + log.Debugf("Failed to listen %s: %v", lAddr.String(), e) + portCurrent++ + if portCurrent > portMax { + portCurrent = portMin + } + if portCurrent == portStart { + break + } + } + + return nil, ErrPort +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/networktype.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/networktype.go similarity index 87% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/networktype.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/networktype.go index 57df18631..af055c593 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/networktype.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/networktype.go @@ -5,7 +5,7 @@ package ice import ( "fmt" - "net" + "net/netip" "strings" ) @@ -27,7 +27,7 @@ func supportedNetworkTypes() []NetworkType { } } -// NetworkType represents the type of network +// NetworkType represents the type of network. type NetworkType int const ( @@ -69,7 +69,7 @@ func (t NetworkType) IsTCP() bool { return t == NetworkTypeTCP4 || t == NetworkTypeTCP6 } -// NetworkShort returns the short network description +// NetworkShort returns the short network description. func (t NetworkType) NetworkShort() string { switch t { case NetworkTypeUDP4, NetworkTypeUDP6: @@ -81,7 +81,7 @@ func (t NetworkType) NetworkShort() string { } } -// IsReliable returns true if the network is reliable +// IsReliable returns true if the network is reliable. func (t NetworkType) IsReliable() bool { switch t { case NetworkTypeUDP4, NetworkTypeUDP6: @@ -89,6 +89,7 @@ func (t NetworkType) IsReliable() bool { case NetworkTypeTCP4, NetworkTypeTCP6: return true } + return false } @@ -100,6 +101,7 @@ func (t NetworkType) IsIPv4() bool { case NetworkTypeUDP6, NetworkTypeTCP6: return false } + return false } @@ -111,25 +113,28 @@ func (t NetworkType) IsIPv6() bool { case NetworkTypeUDP6, NetworkTypeTCP6: return true } + return false } // determineNetworkType determines the type of network based on // the short network string and an IP address. -func determineNetworkType(network string, ip net.IP) (NetworkType, error) { - ipv4 := ip.To4() != nil - +func determineNetworkType(network string, ip netip.Addr) (NetworkType, error) { + // we'd rather have an IPv4-mapped IPv6 become IPv4 so that it is usable. + ip = ip.Unmap() switch { case strings.HasPrefix(strings.ToLower(network), udp): - if ipv4 { + if ip.Is4() { return NetworkTypeUDP4, nil } + return NetworkTypeUDP6, nil case strings.HasPrefix(strings.ToLower(network), tcp): - if ipv4 { + if ip.Is4() { return NetworkTypeTCP4, nil } + return NetworkTypeTCP6, nil } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/priority.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/priority.go similarity index 96% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/priority.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/priority.go index 16ac5cc73..f8c8740fa 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/priority.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/priority.go @@ -6,7 +6,7 @@ package ice import ( "encoding/binary" - "github.com/pion/stun" + "github.com/pion/stun/v3" ) // PriorityAttr represents PRIORITY attribute. @@ -19,6 +19,7 @@ func (p PriorityAttr) AddTo(m *stun.Message) error { v := make([]byte, prioritySize) binary.BigEndian.PutUint32(v, uint32(p)) m.Add(stun.AttrPriority, v) + return nil } @@ -32,5 +33,6 @@ func (p *PriorityAttr) GetFrom(m *stun.Message) error { return err } *p = PriorityAttr(binary.BigEndian.Uint32(v)) + return nil } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/rand.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/rand.go similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/rand.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/rand.go diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/renovate.json b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/renovate.json similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/renovate.json rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/renovate.json diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/role.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/role.go similarity index 99% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/role.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/role.go index e9a7bda94..49f68963b 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/role.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/role.go @@ -26,6 +26,7 @@ func (r *Role) UnmarshalText(text []byte) error { default: return fmt.Errorf("%w %q", errUnknownRole, text) } + return nil } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/selection.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/selection.go similarity index 66% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/selection.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/selection.go index 9f312637f..b67898dd7 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/selection.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/selection.go @@ -8,7 +8,7 @@ import ( "time" "github.com/pion/logging" - "github.com/pion/stun" + "github.com/pion/stun/v3" ) type pairCandidateSelector interface { @@ -44,6 +44,7 @@ func (s *controllingSelector) isNominatable(c Candidate) bool { } s.log.Errorf("Invalid candidate type: %s", c.Type()) + return false } @@ -51,7 +52,7 @@ func (s *controllingSelector) ContactCandidates() { switch { case s.agent.getSelectedPair() != nil: if s.agent.validateSelectedPair() { - s.log.Trace("checking keepalive") + s.log.Trace("Checking keepalive") s.agent.checkKeepalive() } case s.nominatedPair != nil: @@ -59,10 +60,11 @@ func (s *controllingSelector) ContactCandidates() { default: p := s.agent.getBestValidCandidatePair() if p != nil && s.isNominatable(p.Local) && s.isNominatable(p.Remote) { - s.log.Tracef("Nominatable pair found, nominating (%s, %s)", p.Local.String(), p.Remote.String()) + s.log.Tracef("Nominatable pair found, nominating (%s, %s)", p.Local, p.Remote) p.nominated = true s.nominatedPair = p s.nominatePair(p) + return } s.agent.pingAllCandidates() @@ -84,40 +86,54 @@ func (s *controllingSelector) nominatePair(pair *CandidatePair) { ) if err != nil { s.log.Error(err.Error()) + return } - s.log.Tracef("ping STUN (nominate candidate pair) from %s to %s", pair.Local.String(), pair.Remote.String()) + s.log.Tracef("Ping STUN (nominate candidate pair) from %s to %s", pair.Local, pair.Remote) s.agent.sendBindingRequest(msg, pair.Local, pair.Remote) } -func (s *controllingSelector) HandleBindingRequest(m *stun.Message, local, remote Candidate) { - s.agent.sendBindingSuccess(m, local, remote) +func (s *controllingSelector) HandleBindingRequest(message *stun.Message, local, remote Candidate) { //nolint:cyclop + s.agent.sendBindingSuccess(message, local, remote) - p := s.agent.findPair(local, remote) + pair := s.agent.findPair(local, remote) + + if pair == nil { + pair = s.agent.addPair(local, remote) + pair.UpdateRequestReceived() - if p == nil { - s.agent.addPair(local, remote) return } + pair.UpdateRequestReceived() - if p.state == CandidatePairStateSucceeded && s.nominatedPair == nil && s.agent.getSelectedPair() == nil { + if pair.state == CandidatePairStateSucceeded && s.nominatedPair == nil && s.agent.getSelectedPair() == nil { bestPair := s.agent.getBestAvailableCandidatePair() if bestPair == nil { s.log.Tracef("No best pair available") - } else if bestPair.equal(p) && s.isNominatable(p.Local) && s.isNominatable(p.Remote) { - s.log.Tracef("The candidate (%s, %s) is the best candidate available, marking it as nominated", - p.Local.String(), p.Remote.String()) - s.nominatedPair = p - s.nominatePair(p) + } else if bestPair.equal(pair) && s.isNominatable(pair.Local) && s.isNominatable(pair.Remote) { + s.log.Tracef( + "The candidate (%s, %s) is the best candidate available, marking it as nominated", + pair.Local, + pair.Remote, + ) + s.nominatedPair = pair + s.nominatePair(pair) + } + } + + if s.agent.userBindingRequestHandler != nil { + if shouldSwitch := s.agent.userBindingRequestHandler(message, local, remote, pair); shouldSwitch { + s.agent.setSelectedPair(pair) } } } func (s *controllingSelector) HandleSuccessResponse(m *stun.Message, local, remote Candidate, remoteAddr net.Addr) { - ok, pendingRequest := s.agent.handleInboundBindingSuccess(m.TransactionID) + ok, pendingRequest, rtt := s.agent.handleInboundBindingSuccess(m.TransactionID) if !ok { s.log.Warnf("Discard message from (%s), unknown TransactionID 0x%x", remote, m.TransactionID) + return } @@ -126,24 +142,32 @@ func (s *controllingSelector) HandleSuccessResponse(m *stun.Message, local, remo // Assert that NAT is not symmetric // https://tools.ietf.org/html/rfc8445#section-7.2.5.2.1 if !addrEqual(transactionAddr, remoteAddr) { - s.log.Debugf("Discard message: transaction source and destination does not match expected(%s), actual(%s)", transactionAddr, remote) + s.log.Debugf( + "Discard message: transaction source and destination does not match expected(%s), actual(%s)", + transactionAddr, + remote, + ) + return } - s.log.Tracef("inbound STUN (SuccessResponse) from %s to %s", remote.String(), local.String()) - p := s.agent.findPair(local, remote) + s.log.Tracef("Inbound STUN (SuccessResponse) from %s to %s", remote, local) + pair := s.agent.findPair(local, remote) - if p == nil { + if pair == nil { // This shouldn't happen s.log.Error("Success response from invalid candidate pair") + return } - p.state = CandidatePairStateSucceeded - s.log.Tracef("Found valid candidate pair: %s", p) + pair.state = CandidatePairStateSucceeded + s.log.Tracef("Found valid candidate pair: %s", pair) if pendingRequest.isUseCandidate && s.agent.getSelectedPair() == nil { - s.agent.setSelectedPair(p) + s.agent.setSelectedPair(pair) } + + pair.UpdateRoundTripTime(rtt) } func (s *controllingSelector) PingCandidate(local, remote Candidate) { @@ -156,6 +180,7 @@ func (s *controllingSelector) PingCandidate(local, remote Candidate) { ) if err != nil { s.log.Error(err.Error()) + return } @@ -173,7 +198,7 @@ func (s *controlledSelector) Start() { func (s *controlledSelector) ContactCandidates() { if s.agent.getSelectedPair() != nil { if s.agent.validateSelectedPair() { - s.log.Trace("checking keepalive") + s.log.Trace("Checking keepalive") s.agent.checkKeepalive() } } else { @@ -191,6 +216,7 @@ func (s *controlledSelector) PingCandidate(local, remote Candidate) { ) if err != nil { s.log.Error(err.Error()) + return } @@ -206,9 +232,10 @@ func (s *controlledSelector) HandleSuccessResponse(m *stun.Message, local, remot // request with an appropriate error code response (e.g., 400) // [RFC5389]. - ok, pendingRequest := s.agent.handleInboundBindingSuccess(m.TransactionID) + ok, pendingRequest, rtt := s.agent.handleInboundBindingSuccess(m.TransactionID) if !ok { s.log.Warnf("Discard message from (%s), unknown TransactionID 0x%x", remote, m.TransactionID) + return } @@ -217,52 +244,63 @@ func (s *controlledSelector) HandleSuccessResponse(m *stun.Message, local, remot // Assert that NAT is not symmetric // https://tools.ietf.org/html/rfc8445#section-7.2.5.2.1 if !addrEqual(transactionAddr, remoteAddr) { - s.log.Debugf("Discard message: transaction source and destination does not match expected(%s), actual(%s)", transactionAddr, remote) + s.log.Debugf( + "Discard message: transaction source and destination does not match expected(%s), actual(%s)", + transactionAddr, + remote, + ) + return } - s.log.Tracef("inbound STUN (SuccessResponse) from %s to %s", remote.String(), local.String()) + s.log.Tracef("Inbound STUN (SuccessResponse) from %s to %s", remote, local) - p := s.agent.findPair(local, remote) - if p == nil { + pair := s.agent.findPair(local, remote) + if pair == nil { // This shouldn't happen s.log.Error("Success response from invalid candidate pair") + return } - p.state = CandidatePairStateSucceeded - s.log.Tracef("Found valid candidate pair: %s", p) - if p.nominateOnBindingSuccess { + pair.state = CandidatePairStateSucceeded + s.log.Tracef("Found valid candidate pair: %s", pair) + if pair.nominateOnBindingSuccess { if selectedPair := s.agent.getSelectedPair(); selectedPair == nil || - (selectedPair != p && selectedPair.priority() <= p.priority()) { - s.agent.setSelectedPair(p) - } else if selectedPair != p { - s.log.Tracef("ignore nominate new pair %s, already nominated pair %s", p, selectedPair) + (selectedPair != pair && + (!s.agent.needsToCheckPriorityOnNominated() || selectedPair.priority() <= pair.priority())) { + s.agent.setSelectedPair(pair) + } else if selectedPair != pair { + s.log.Tracef("Ignore nominate new pair %s, already nominated pair %s", pair, selectedPair) } } + + pair.UpdateRoundTripTime(rtt) } -func (s *controlledSelector) HandleBindingRequest(m *stun.Message, local, remote Candidate) { - useCandidate := m.Contains(stun.AttrUseCandidate) - - p := s.agent.findPair(local, remote) - if p == nil { - p = s.agent.addPair(local, remote) +func (s *controlledSelector) HandleBindingRequest(message *stun.Message, local, remote Candidate) { //nolint:cyclop + pair := s.agent.findPair(local, remote) + if pair == nil { + pair = s.agent.addPair(local, remote) } + pair.UpdateRequestReceived() - if useCandidate { + if message.Contains(stun.AttrUseCandidate) { //nolint:nestif // https://tools.ietf.org/html/rfc8445#section-7.3.1.5 - if p.state == CandidatePairStateSucceeded { + if pair.state == CandidatePairStateSucceeded { // If the state of this pair is Succeeded, it means that the check // previously sent by this pair produced a successful response and // generated a valid pair (Section 7.2.5.3.2). The agent sets the // nominated flag value of the valid pair to true. - if selectedPair := s.agent.getSelectedPair(); selectedPair == nil || - (selectedPair != p && selectedPair.priority() <= p.priority()) { - s.agent.setSelectedPair(p) - } else if selectedPair != p { - s.log.Tracef("ignore nominate new pair %s, already nominated pair %s", p, selectedPair) + selectedPair := s.agent.getSelectedPair() + if selectedPair == nil || + (selectedPair != pair && + (!s.agent.needsToCheckPriorityOnNominated() || + selectedPair.priority() <= pair.priority())) { + s.agent.setSelectedPair(pair) + } else if selectedPair != pair { + s.log.Tracef("Ignore nominate new pair %s, already nominated pair %s", pair, selectedPair) } } else { // If the received Binding request triggered a new check to be @@ -273,19 +311,25 @@ func (s *controlledSelector) HandleBindingRequest(m *stun.Message, local, remote // MUST remove the candidate pair from the valid list, set the // candidate pair state to Failed, and set the checklist state to // Failed. - p.nominateOnBindingSuccess = true + pair.nominateOnBindingSuccess = true } } - s.agent.sendBindingSuccess(m, local, remote) + s.agent.sendBindingSuccess(message, local, remote) s.PingCandidate(local, remote) + + if s.agent.userBindingRequestHandler != nil { + if shouldSwitch := s.agent.userBindingRequestHandler(message, local, remote, pair); shouldSwitch { + s.agent.setSelectedPair(pair) + } + } } type liteSelector struct { pairCandidateSelector } -// A lite selector should not contact candidates +// A lite selector should not contact candidates. func (s *liteSelector) ContactCandidates() { if _, ok := s.pairCandidateSelector.(*controllingSelector); ok { //nolint:godox diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/stats.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/stats.go similarity index 93% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/stats.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/stats.go index 9b83bea85..30a0c02b8 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/stats.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/stats.go @@ -7,7 +7,7 @@ import ( "time" ) -// CandidatePairStats contains ICE candidate pair statistics +// CandidatePairStats contains ICE candidate pair statistics. type CandidatePairStats struct { // Timestamp is the timestamp associated with this object. Timestamp time.Time @@ -58,10 +58,22 @@ type CandidatePairStats struct { // (LastRequestTimestamp - FirstRequestTimestamp) / RequestsSent. LastRequestTimestamp time.Time + // FirstResponseTimestamp represents the timestamp at which the first STUN response + // was received on this particular candidate pair. + FirstResponseTimestamp time.Time + // LastResponseTimestamp represents the timestamp at which the last STUN response // was received on this particular candidate pair. LastResponseTimestamp time.Time + // FirstRequestReceivedTimestamp represents the timestamp at which the first + // connectivity check request was received. + FirstRequestReceivedTimestamp time.Time + + // LastRequestReceivedTimestamp represents the timestamp at which the last + // connectivity check request was received. + LastRequestReceivedTimestamp time.Time + // TotalRoundTripTime represents the sum of all round trip time measurements // in seconds since the beginning of the session, based on STUN connectivity // check responses (ResponsesReceived), including those that reply to requests diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/tcp_mux.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/tcp_mux.go similarity index 71% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/tcp_mux.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/tcp_mux.go index fb4e5243e..829eac195 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/tcp_mux.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/tcp_mux.go @@ -10,9 +10,10 @@ import ( "net" "strings" "sync" + "time" "github.com/pion/logging" - "github.com/pion/stun" + "github.com/pion/stun/v3" ) // ErrGetTransportAddress can't convert net.Addr to underlying type (UDPAddr or TCPAddr). @@ -52,6 +53,16 @@ type TCPMuxParams struct { // if the write buffer is full, the subsequent write packet will be dropped until it has enough space. // a default 4MB is recommended. WriteBufferSize int + + // A new established connection will be removed if the first STUN binding request is not received within this timeout, + // avoiding the client with bad network or attacker to create a lot of empty connections. + // Default 30s timeout will be used if not set. + FirstStunBindTimeout time.Duration + + // TCPMux will create connection from STUN binding request with an unknown username, if + // the connection is not used in the timeout, it will be removed to avoid resource leak / attack. + // Default 30s timeout will be used if not set. + AliveDurationForConnFromStun time.Duration } // NewTCPMuxDefault creates a new instance of TCPMuxDefault. @@ -60,20 +71,28 @@ func NewTCPMuxDefault(params TCPMuxParams) *TCPMuxDefault { params.Logger = logging.NewDefaultLoggerFactory().NewLogger("ice") } - m := &TCPMuxDefault{ + if params.FirstStunBindTimeout == 0 { + params.FirstStunBindTimeout = 30 * time.Second + } + + if params.AliveDurationForConnFromStun == 0 { + params.AliveDurationForConnFromStun = 30 * time.Second + } + + mux := &TCPMuxDefault{ params: ¶ms, connsIPv4: map[string]map[ipAddr]*tcpPacketConn{}, connsIPv6: map[string]map[ipAddr]*tcpPacketConn{}, } - m.wg.Add(1) + mux.wg.Add(1) go func() { - defer m.wg.Done() - m.start() + defer mux.wg.Done() + mux.start() }() - return m + return mux } func (m *TCPMuxDefault) start() { @@ -82,6 +101,7 @@ func (m *TCPMuxDefault) start() { conn, err := m.params.Listener.Accept() if err != nil { m.params.Logger.Infof("Error accepting connection: %s", err) + return } @@ -110,25 +130,34 @@ func (m *TCPMuxDefault) GetConnByUfrag(ufrag string, isIPv6 bool, local net.IP) } if conn, ok := m.getConn(ufrag, isIPv6, local); ok { + conn.ClearAliveTimer() + return conn, nil } - return m.createConn(ufrag, isIPv6, local) + return m.createConn(ufrag, isIPv6, local, false) } -func (m *TCPMuxDefault) createConn(ufrag string, isIPv6 bool, local net.IP) (*tcpPacketConn, error) { +func (m *TCPMuxDefault) createConn(ufrag string, isIPv6 bool, local net.IP, fromStun bool) (*tcpPacketConn, error) { addr, ok := m.LocalAddr().(*net.TCPAddr) if !ok { return nil, ErrGetTransportAddress } localAddr := *addr + // Note: this is missing zone for IPv6 localAddr.IP = local + var alive time.Duration + if fromStun { + alive = m.params.AliveDurationForConnFromStun + } + conn := newTCPPacketConn(tcpPacketParams{ - ReadBuffer: m.params.ReadBufferSize, - WriteBuffer: m.params.WriteBufferSize, - LocalAddr: &localAddr, - Logger: m.params.Logger, + ReadBuffer: m.params.ReadBufferSize, + WriteBuffer: m.params.WriteBufferSize, + LocalAddr: &localAddr, + Logger: m.params.Logger, + AliveDuration: alive, }) var conns map[ipAddr]*tcpPacketConn @@ -143,13 +172,15 @@ func (m *TCPMuxDefault) createConn(ufrag string, isIPv6 bool, local net.IP) (*tc m.connsIPv4[ufrag] = conns } } - conns[ipAddr(local.String())] = conn + // Note: this is missing zone for IPv6 + connKey := ipAddr(local.String()) + conns[connKey] = conn m.wg.Add(1) go func() { defer m.wg.Done() <-conn.CloseChannel() - m.removeConnByUfragAndLocalHost(ufrag, local) + m.removeConnByUfragAndLocalHost(ufrag, connKey) }() return conn, nil @@ -162,14 +193,33 @@ func (m *TCPMuxDefault) closeAndLogError(closer io.Closer) { } } -func (m *TCPMuxDefault) handleConn(conn net.Conn) { - buf := make([]byte, receiveMTU) +func (m *TCPMuxDefault) handleConn(conn net.Conn) { //nolint:cyclop + buf := make([]byte, 512) + if m.params.FirstStunBindTimeout > 0 { + if err := conn.SetReadDeadline(time.Now().Add(m.params.FirstStunBindTimeout)); err != nil { + m.params.Logger.Warnf( + "Failed to set read deadline for first STUN message: %s to %s , err: %s", + conn.RemoteAddr(), + conn.LocalAddr(), + err, + ) + } + } n, err := readStreamingPacket(conn, buf) if err != nil { - m.params.Logger.Warnf("Error reading first packet from %s: %s", conn.RemoteAddr().String(), err) + if errors.Is(err, io.ErrShortBuffer) { + m.params.Logger.Warnf("Buffer too small for first packet from %s: %s", conn.RemoteAddr(), err) + } else { + m.params.Logger.Warnf("Error reading first packet from %s: %s", conn.RemoteAddr(), err) + } + m.closeAndLogError(conn) + return } + if err = conn.SetReadDeadline(time.Time{}); err != nil { + m.params.Logger.Warnf("Failed to reset read deadline from %s: %s", conn.RemoteAddr(), err) + } buf = buf[:n] @@ -181,36 +231,45 @@ func (m *TCPMuxDefault) handleConn(conn net.Conn) { if err = msg.Decode(); err != nil { m.closeAndLogError(conn) m.params.Logger.Warnf("Failed to handle decode ICE from %s to %s: %v", conn.RemoteAddr(), conn.LocalAddr(), err) + return } if m == nil || msg.Type.Method != stun.MethodBinding { // Not a STUN m.closeAndLogError(conn) m.params.Logger.Warnf("Not a STUN message from %s to %s", conn.RemoteAddr(), conn.LocalAddr()) + return } for _, attr := range msg.Attributes { - m.params.Logger.Debugf("msg attr: %s", attr.String()) + m.params.Logger.Debugf("Message attribute: %s", attr.String()) } attr, err := msg.Get(stun.AttrUsername) if err != nil { m.closeAndLogError(conn) - m.params.Logger.Warnf("No Username attribute in STUN message from %s to %s", conn.RemoteAddr(), conn.LocalAddr()) + m.params.Logger.Warnf( + "No Username attribute in STUN message from %s to %s", + conn.RemoteAddr(), + conn.LocalAddr(), + ) + return } ufrag := strings.Split(string(attr), ":")[0] m.params.Logger.Debugf("Ufrag: %s", ufrag) - m.mu.Lock() - defer m.mu.Unlock() - host, _, err := net.SplitHostPort(conn.RemoteAddr().String()) if err != nil { m.closeAndLogError(conn) - m.params.Logger.Warnf("Failed to get host in STUN message from %s to %s", conn.RemoteAddr(), conn.LocalAddr()) + m.params.Logger.Warnf( + "Failed to get host in STUN message from %s to %s", + conn.RemoteAddr(), + conn.LocalAddr(), + ) + return } @@ -219,22 +278,42 @@ func (m *TCPMuxDefault) handleConn(conn net.Conn) { localAddr, ok := conn.LocalAddr().(*net.TCPAddr) if !ok { m.closeAndLogError(conn) - m.params.Logger.Warnf("Failed to get local tcp address in STUN message from %s to %s", conn.RemoteAddr(), conn.LocalAddr()) + m.params.Logger.Warnf( + "Failed to get local tcp address in STUN message from %s to %s", + conn.RemoteAddr(), + conn.LocalAddr(), + ) + return } + m.mu.Lock() + packetConn, ok := m.getConn(ufrag, isIPv6, localAddr.IP) if !ok { - packetConn, err = m.createConn(ufrag, isIPv6, localAddr.IP) + packetConn, err = m.createConn(ufrag, isIPv6, localAddr.IP, true) if err != nil { + m.mu.Unlock() m.closeAndLogError(conn) - m.params.Logger.Warnf("Failed to create packetConn for STUN message from %s to %s", conn.RemoteAddr(), conn.LocalAddr()) + m.params.Logger.Warnf( + "Failed to create packetConn for STUN message from %s to %s", + conn.RemoteAddr(), + conn.LocalAddr(), + ) + return } } + m.mu.Unlock() if err := packetConn.AddConn(conn, buf); err != nil { m.closeAndLogError(conn) - m.params.Logger.Warnf("Error adding conn to tcpPacketConn from %s to %s: %s", conn.RemoteAddr(), conn.LocalAddr(), err) + m.params.Logger.Warnf( + "Error adding conn to tcpPacketConn from %s to %s: %s", + conn.RemoteAddr(), + conn.LocalAddr(), + err, + ) + return } } @@ -295,15 +374,14 @@ func (m *TCPMuxDefault) RemoveConnByUfrag(ufrag string) { } } -func (m *TCPMuxDefault) removeConnByUfragAndLocalHost(ufrag string, local net.IP) { +func (m *TCPMuxDefault) removeConnByUfragAndLocalHost(ufrag string, localIPAddr ipAddr) { removedConns := make([]*tcpPacketConn, 0, 4) - localIP := ipAddr(local.String()) // Keep lock section small to avoid deadlock with conn lock m.mu.Lock() if conns, ok := m.connsIPv4[ufrag]; ok { - if conn, ok := conns[localIP]; ok { - delete(conns, localIP) + if conn, ok := conns[localIPAddr]; ok { + delete(conns, localIPAddr) if len(conns) == 0 { delete(m.connsIPv4, ufrag) } @@ -311,8 +389,8 @@ func (m *TCPMuxDefault) removeConnByUfragAndLocalHost(ufrag string, local net.IP } } if conns, ok := m.connsIPv6[ufrag]; ok { - if conn, ok := conns[localIP]; ok { - delete(conns, localIP) + if conn, ok := conns[localIPAddr]; ok { + delete(conns, localIPAddr) if len(conns) == 0 { delete(m.connsIPv6, ufrag) } @@ -336,7 +414,9 @@ func (m *TCPMuxDefault) getConn(ufrag string, isIPv6 bool, local net.IP) (val *t conns, ok = m.connsIPv4[ufrag] } if conns != nil { - val, ok = conns[ipAddr(local.String())] + // Note: this is missing zone for IPv6 + connKey := ipAddr(local.String()) + val, ok = conns[connKey] } return @@ -384,7 +464,7 @@ func readStreamingPacket(conn net.Conn, buf []byte) (int, error) { func writeStreamingPacket(conn net.Conn, buf []byte) (int, error) { bufCopy := make([]byte, streamingPacketHeaderLen+len(buf)) - binary.BigEndian.PutUint16(bufCopy, uint16(len(buf))) + binary.BigEndian.PutUint16(bufCopy, uint16(len(buf))) //nolint:gosec // G115 copy(bufCopy[2:], buf) n, err := conn.Write(bufCopy) diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/tcp_mux_multi.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/tcp_mux_multi.go similarity index 94% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/tcp_mux_multi.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/tcp_mux_multi.go index e32acbf3e..225cefe2b 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/tcp_mux_multi.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/tcp_mux_multi.go @@ -3,7 +3,9 @@ package ice -import "net" +import ( + "net" +) // AllConnsGetter allows multiple fixed TCP ports to be used, // each of which is multiplexed like TCPMux. AllConnsGetter also acts as @@ -38,6 +40,7 @@ func (m *MultiTCPMuxDefault) GetConnByUfrag(ufrag string, isIPv6 bool, local net if len(m.muxes) == 0 { return nil, errNoTCPMuxAvailable } + return m.muxes[0].GetConnByUfrag(ufrag, isIPv6, local) } @@ -49,7 +52,7 @@ func (m *MultiTCPMuxDefault) RemoveConnByUfrag(ufrag string) { } } -// GetAllConns returns a PacketConn for each underlying TCPMux +// GetAllConns returns a PacketConn for each underlying TCPMux. func (m *MultiTCPMuxDefault) GetAllConns(ufrag string, isIPv6 bool, local net.IP) ([]net.PacketConn, error) { if len(m.muxes) == 0 { // Make sure that we either return at least one connection or an error. @@ -66,10 +69,11 @@ func (m *MultiTCPMuxDefault) GetAllConns(ufrag string, isIPv6 bool, local net.IP conns = append(conns, conn) } } + return conns, nil } -// Close the multi mux, no further connections could be created +// Close the multi mux, no further connections could be created. func (m *MultiTCPMuxDefault) Close() error { var err error for _, mux := range m.muxes { @@ -77,5 +81,6 @@ func (m *MultiTCPMuxDefault) Close() error { err = e } } + return err } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/tcp_packet_conn.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/tcp_packet_conn.go similarity index 79% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/tcp_packet_conn.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/tcp_packet_conn.go index 8c51fd1cc..1d1dffcb8 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/tcp_packet_conn.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/tcp_packet_conn.go @@ -13,7 +13,7 @@ import ( "time" "github.com/pion/logging" - "github.com/pion/transport/v2/packetio" + "github.com/pion/transport/v3/packetio" ) type bufferedConn struct { @@ -36,6 +36,7 @@ func newBufferedConn(conn net.Conn, bufSize int, logger logging.LeveledLogger) n } go bc.writeProcess() + return bc } @@ -44,6 +45,7 @@ func (bc *bufferedConn) Write(b []byte) (int, error) { if err != nil { return n, err } + return n, nil } @@ -56,12 +58,14 @@ func (bc *bufferedConn) writeProcess() { } if err != nil { - bc.logger.Warnf("read buffer error: %s", err) + bc.logger.Warnf("Failed to read from buffer: %s", err) + continue } if _, err := bc.Conn.Write(pktBuf[:n]); err != nil { - bc.logger.Warnf("write error: %s", err) + bc.logger.Warnf("Failed to write: %s", err) + continue } } @@ -70,6 +74,7 @@ func (bc *bufferedConn) writeProcess() { func (bc *bufferedConn) Close() error { atomic.StoreInt32(&bc.closed, 1) _ = bc.buf.Close() + return bc.Conn.Close() } @@ -85,6 +90,7 @@ type tcpPacketConn struct { wg sync.WaitGroup closedChan chan struct{} closeOnce sync.Once + aliveTimer *time.Timer } type streamingPacket struct { @@ -94,14 +100,15 @@ type streamingPacket struct { } type tcpPacketParams struct { - ReadBuffer int - LocalAddr net.Addr - Logger logging.LeveledLogger - WriteBuffer int + ReadBuffer int + LocalAddr net.Addr + Logger logging.LeveledLogger + WriteBuffer int + AliveDuration time.Duration } func newTCPPacketConn(params tcpPacketParams) *tcpPacketConn { - p := &tcpPacketConn{ + packet := &tcpPacketConn{ params: ¶ms, conns: map[string]net.Conn{}, @@ -110,11 +117,31 @@ func newTCPPacketConn(params tcpPacketParams) *tcpPacketConn { closedChan: make(chan struct{}), } - return p + if params.AliveDuration > 0 { + packet.aliveTimer = time.AfterFunc(params.AliveDuration, func() { + packet.params.Logger.Warn("close tcp packet conn by alive timeout") + _ = packet.Close() + }) + } + + return packet +} + +func (t *tcpPacketConn) ClearAliveTimer() { + t.mu.Lock() + if t.aliveTimer != nil { + t.aliveTimer.Stop() + } + t.mu.Unlock() } func (t *tcpPacketConn) AddConn(conn net.Conn, firstPacketData []byte) error { - t.params.Logger.Infof("AddConn: %s remote %s to local %s", conn.RemoteAddr().Network(), conn.RemoteAddr(), conn.LocalAddr()) + t.params.Logger.Infof( + "Added connection: %s remote %s to local %s", + conn.RemoteAddr().Network(), + conn.RemoteAddr(), + conn.LocalAddr(), + ) t.mu.Lock() defer t.mu.Unlock() @@ -160,9 +187,13 @@ func (t *tcpPacketConn) startReading(conn net.Conn) { for { n, err := readStreamingPacket(conn, buf) if err != nil { - t.params.Logger.Infof("%v: %s", errReadingStreamingPacket, err) - t.handleRecv(streamingPacket{nil, conn.RemoteAddr(), err}) - t.removeConn(conn) + t.params.Logger.Warnf("Failed to read streaming packet: %s", err) + last := t.removeConn(conn) + // Only propagate connection closure errors if no other open connection exists. + if last || !(errors.Is(err, io.EOF) || errors.Is(err, net.ErrClosed)) { + t.handleRecv(streamingPacket{nil, conn.RemoteAddr(), err}) + } + return } @@ -216,6 +247,7 @@ func (t *tcpPacketConn) ReadFrom(b []byte) (n int, rAddr net.Addr, err error) { n = len(pkt.Data) copy(b, pkt.Data[:n]) + return n, pkt.RAddr, err } @@ -231,7 +263,8 @@ func (t *tcpPacketConn) WriteTo(buf []byte, rAddr net.Addr) (n int, err error) { n, err = writeStreamingPacket(conn, buf) if err != nil { - t.params.Logger.Tracef("%w %s", errWriting, rAddr) + t.params.Logger.Tracef("%w %s", errWrite, rAddr) + return n, err } @@ -245,13 +278,15 @@ func (t *tcpPacketConn) closeAndLogError(closer io.Closer) { } } -func (t *tcpPacketConn) removeConn(conn net.Conn) { +func (t *tcpPacketConn) removeConn(conn net.Conn) bool { t.mu.Lock() defer t.mu.Unlock() t.closeAndLogError(conn) delete(t.conns, conn.RemoteAddr().String()) + + return len(t.conns) == 0 } func (t *tcpPacketConn) Close() error { @@ -261,6 +296,9 @@ func (t *tcpPacketConn) Close() error { t.closeOnce.Do(func() { close(t.closedChan) shouldCloseRecvChan = true + if t.aliveTimer != nil { + t.aliveTimer.Stop() + } }) for _, conn := range t.conns { diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/tcptype.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/tcptype.go similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/tcptype.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/tcptype.go diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/transport.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/transport.go similarity index 79% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/transport.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/transport.go index cd37a9b26..a28605dfe 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/transport.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/transport.go @@ -9,7 +9,7 @@ import ( "sync/atomic" "time" - "github.com/pion/stun" + "github.com/pion/stun/v3" ) // Dial connects to the remote agent, acting as the controlling ice agent. @@ -32,18 +32,18 @@ type Conn struct { agent *Agent } -// BytesSent returns the number of bytes sent +// BytesSent returns the number of bytes sent. func (c *Conn) BytesSent() uint64 { return atomic.LoadUint64(&c.bytesSent) } -// BytesReceived returns the number of bytes received +// BytesReceived returns the number of bytes received. func (c *Conn) BytesReceived() uint64 { return atomic.LoadUint64(&c.bytesReceived) } func (a *Agent) connect(ctx context.Context, isControlling bool, remoteUfrag, remotePwd string) (*Conn, error) { - err := a.ok() + err := a.loop.Err() if err != nil { return nil, err } @@ -54,8 +54,8 @@ func (a *Agent) connect(ctx context.Context, isControlling bool, remoteUfrag, re // Block until pair selected select { - case <-a.done: - return nil, a.getErr() + case <-a.loop.Done(): + return nil, a.loop.Err() case <-ctx.Done(): return nil, ErrCanceledByCaller case <-a.onConnected: @@ -68,31 +68,32 @@ func (a *Agent) connect(ctx context.Context, isControlling bool, remoteUfrag, re // Read implements the Conn Read method. func (c *Conn) Read(p []byte) (int, error) { - err := c.agent.ok() + err := c.agent.loop.Err() if err != nil { return 0, err } n, err := c.agent.buf.Read(p) - atomic.AddUint64(&c.bytesReceived, uint64(n)) + atomic.AddUint64(&c.bytesReceived, uint64(n)) //nolint:gosec // G115 + return n, err } // Write implements the Conn Write method. -func (c *Conn) Write(p []byte) (int, error) { - err := c.agent.ok() +func (c *Conn) Write(packet []byte) (int, error) { + err := c.agent.loop.Err() if err != nil { return 0, err } - if stun.IsMessage(p) { - return 0, errICEWriteSTUNMessage + if stun.IsMessage(packet) { + return 0, errWriteSTUNMessageToIceConn } pair := c.agent.getSelectedPair() if pair == nil { - if err = c.agent.run(c.agent.context(), func(ctx context.Context, a *Agent) { - pair = a.getBestValidCandidatePair() + if err = c.agent.loop.Run(c.agent.loop, func(_ context.Context) { + pair = c.agent.getBestValidCandidatePair() }); err != nil { return 0, err } @@ -102,8 +103,9 @@ func (c *Conn) Write(p []byte) (int, error) { } } - atomic.AddUint64(&c.bytesSent, uint64(len(p))) - return pair.Write(p) + atomic.AddUint64(&c.bytesSent, uint64(len(packet))) + + return pair.Write(packet) } // Close implements the Conn Close method. It is used to close @@ -132,17 +134,17 @@ func (c *Conn) RemoteAddr() net.Addr { return pair.Remote.addr() } -// SetDeadline is a stub +// SetDeadline is a stub. func (c *Conn) SetDeadline(time.Time) error { return nil } -// SetReadDeadline is a stub +// SetReadDeadline is a stub. func (c *Conn) SetReadDeadline(time.Time) error { return nil } -// SetWriteDeadline is a stub +// SetWriteDeadline is a stub. func (c *Conn) SetWriteDeadline(time.Time) error { return nil } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/udp_mux.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/udp_mux.go similarity index 70% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/udp_mux.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/udp_mux.go index 405bb7b1a..3732b2685 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/udp_mux.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/udp_mux.go @@ -7,17 +7,18 @@ import ( "errors" "io" "net" + "net/netip" "os" "strings" "sync" "github.com/pion/logging" - "github.com/pion/stun" - "github.com/pion/transport/v2" - "github.com/pion/transport/v2/stdnet" + "github.com/pion/stun/v3" + "github.com/pion/transport/v3" + "github.com/pion/transport/v3/stdnet" ) -// UDPMux allows multiple connections to go over a single UDP port +// UDPMux allows multiple connections to go over a single UDP port. type UDPMux interface { io.Closer GetConn(ufrag string, addr net.Addr) (net.PacketConn, error) @@ -25,7 +26,7 @@ type UDPMux interface { GetListenAddresses() []net.Addr } -// UDPMuxDefault is an implementation of the interface +// UDPMuxDefault is an implementation of the interface. type UDPMuxDefault struct { params UDPMuxParams @@ -36,7 +37,7 @@ type UDPMuxDefault struct { connsIPv4, connsIPv6 map[string]*udpMuxedConn addressMapMu sync.RWMutex - addressMap map[string]*udpMuxedConn + addressMap map[ipPort]*udpMuxedConn // Buffer pool to recycle buffers for net.UDPAddr encodes/decodes pool *sync.Pool @@ -47,12 +48,11 @@ type UDPMuxDefault struct { localAddrsForUnspecified []net.Addr } -const maxAddrSize = 512 - // UDPMuxParams are parameters for UDPMux. type UDPMuxParams struct { - Logger logging.LeveledLogger - UDPConn net.PacketConn + Logger logging.LeveledLogger + UDPConn net.PacketConn + UDPConnString string // Required for gathering local addresses // in case a un UDPConn is passed which does not @@ -60,26 +60,26 @@ type UDPMuxParams struct { Net transport.Net } -// NewUDPMuxDefault creates an implementation of UDPMux -func NewUDPMuxDefault(params UDPMuxParams) *UDPMuxDefault { +// NewUDPMuxDefault creates an implementation of UDPMux. +func NewUDPMuxDefault(params UDPMuxParams) *UDPMuxDefault { //nolint:cyclop if params.Logger == nil { params.Logger = logging.NewDefaultLoggerFactory().NewLogger("ice") } var localAddrsForUnspecified []net.Addr - if addr, ok := params.UDPConn.LocalAddr().(*net.UDPAddr); !ok { + if udpAddr, ok := params.UDPConn.LocalAddr().(*net.UDPAddr); !ok { //nolint:nestif params.Logger.Errorf("LocalAddr is not a net.UDPAddr, got %T", params.UDPConn.LocalAddr()) - } else if ok && addr.IP.IsUnspecified() { + } else if ok && udpAddr.IP.IsUnspecified() { // For unspecified addresses, the correct behavior is to return errListenUnspecified, but // it will break the applications that are already using unspecified UDP connection // with UDPMuxDefault, so print a warn log and create a local address list for mux. params.Logger.Warn("UDPMuxDefault should not listening on unspecified address, use NewMultiUDPMuxFromPort instead") var networks []NetworkType switch { - case addr.IP.To4() != nil: + case udpAddr.IP.To4() != nil: networks = []NetworkType{NetworkTypeUDP4} - case addr.IP.To16() != nil: + case udpAddr.IP.To16() != nil: networks = []NetworkType{NetworkTypeUDP4, NetworkTypeUDP6} default: @@ -89,23 +89,28 @@ func NewUDPMuxDefault(params UDPMuxParams) *UDPMuxDefault { if params.Net == nil { var err error if params.Net, err = stdnet.NewNet(); err != nil { - params.Logger.Errorf("failed to get create network: %v", err) + params.Logger.Errorf("Failed to get create network: %v", err) } } - ips, err := localInterfaces(params.Net, nil, nil, networks, true) + _, addrs, err := localInterfaces(params.Net, nil, nil, networks, true) if err == nil { - for _, ip := range ips { - localAddrsForUnspecified = append(localAddrsForUnspecified, &net.UDPAddr{IP: ip, Port: addr.Port}) + for _, addr := range addrs { + localAddrsForUnspecified = append(localAddrsForUnspecified, &net.UDPAddr{ + IP: addr.AsSlice(), + Port: udpAddr.Port, + Zone: addr.Zone(), + }) } } else { - params.Logger.Errorf("failed to get local interfaces for unspecified addr: %v", err) + params.Logger.Errorf("Failed to get local interfaces for unspecified addr: %v", err) } } } + params.UDPConnString = params.UDPConn.LocalAddr().String() - m := &UDPMuxDefault{ - addressMap: map[string]*udpMuxedConn{}, + mux := &UDPMuxDefault{ + addressMap: map[ipPort]*udpMuxedConn{}, params: params, connsIPv4: make(map[string]*udpMuxedConn), connsIPv6: make(map[string]*udpMuxedConn), @@ -113,23 +118,23 @@ func NewUDPMuxDefault(params UDPMuxParams) *UDPMuxDefault { pool: &sync.Pool{ New: func() interface{} { // Big enough buffer to fit both packet and address - return newBufferHolder(receiveMTU + maxAddrSize) + return newBufferHolder(receiveMTU) }, }, localAddrsForUnspecified: localAddrsForUnspecified, } - go m.connWorker() + go mux.connWorker() - return m + return mux } -// LocalAddr returns the listening address of this UDPMuxDefault +// LocalAddr returns the listening address of this UDPMuxDefault. func (m *UDPMuxDefault) LocalAddr() net.Addr { return m.params.UDPConn.LocalAddr() } -// GetListenAddresses returns the list of addresses that this mux is listening on +// GetListenAddresses returns the list of addresses that this mux is listening on. func (m *UDPMuxDefault) GetListenAddresses() []net.Addr { if len(m.localAddrsForUnspecified) > 0 { return m.localAddrsForUnspecified @@ -138,11 +143,11 @@ func (m *UDPMuxDefault) GetListenAddresses() []net.Addr { return []net.Addr{m.LocalAddr()} } -// GetConn returns a PacketConn given the connection's ufrag and network address -// creates the connection if an existing one can't be found +// GetConn returns a PacketConn given the connection's ufrag and network address. +// creates the connection if an existing one can't be found. func (m *UDPMuxDefault) GetConn(ufrag string, addr net.Addr) (net.PacketConn, error) { // don't check addr for mux using unspecified address - if len(m.localAddrsForUnspecified) == 0 && m.params.UDPConn.LocalAddr().String() != addr.String() { + if len(m.localAddrsForUnspecified) == 0 && m.params.UDPConnString != addr.String() { return nil, errInvalidAddress } @@ -176,11 +181,11 @@ func (m *UDPMuxDefault) GetConn(ufrag string, addr net.Addr) (net.PacketConn, er return c, nil } -// RemoveConnByUfrag stops and removes the muxed packet connection +// RemoveConnByUfrag stops and removes the muxed packet connection. func (m *UDPMuxDefault) RemoveConnByUfrag(ufrag string) { removedConns := make([]*udpMuxedConn, 0, 2) - // Keep lock section small to avoid deadlock with conn lock + // Keep lock section small to avoid deadlock with conn lock. m.mu.Lock() if c, ok := m.connsIPv4[ufrag]; ok { delete(m.connsIPv4, ufrag) @@ -193,7 +198,7 @@ func (m *UDPMuxDefault) RemoveConnByUfrag(ufrag string) { m.mu.Unlock() if len(removedConns) == 0 { - // No need to lock if no connection was found + // No need to lock if no connection was found. return } @@ -208,7 +213,7 @@ func (m *UDPMuxDefault) RemoveConnByUfrag(ufrag string) { } } -// IsClosed returns true if the mux had been closed +// IsClosed returns true if the mux had been closed. func (m *UDPMuxDefault) IsClosed() bool { select { case <-m.closedChan: @@ -218,7 +223,7 @@ func (m *UDPMuxDefault) IsClosed() bool { } } -// Close the mux, no further connections could be created +// Close the mux, no further connections could be created. func (m *UDPMuxDefault) Close() error { var err error m.closeOnce.Do(func() { @@ -239,6 +244,7 @@ func (m *UDPMuxDefault) Close() error { _ = m.params.UDPConn.Close() }) + return err } @@ -246,7 +252,7 @@ func (m *UDPMuxDefault) writeTo(buf []byte, rAddr net.Addr) (n int, err error) { return m.params.UDPConn.WriteTo(buf, rAddr) } -func (m *UDPMuxDefault) registerConnForAddress(conn *udpMuxedConn, addr string) { +func (m *UDPMuxDefault) registerConnForAddress(conn *udpMuxedConn, addr ipPort) { if m.IsClosed() { return } @@ -260,7 +266,7 @@ func (m *UDPMuxDefault) registerConnForAddress(conn *udpMuxedConn, addr string) } m.addressMap[addr] = conn - m.params.Logger.Debugf("Registered %s for %s", addr, conn.params.Key) + m.params.Logger.Debugf("Registered %s for %s", addr.addr.String(), conn.params.Key) } func (m *UDPMuxDefault) createMuxedConn(key string) *udpMuxedConn { @@ -271,10 +277,11 @@ func (m *UDPMuxDefault) createMuxedConn(key string) *udpMuxedConn { LocalAddr: m.LocalAddr(), Logger: m.params.Logger, }) + return c } -func (m *UDPMuxDefault) connWorker() { +func (m *UDPMuxDefault) connWorker() { //nolint:cyclop logger := m.params.Logger defer func() { @@ -290,21 +297,28 @@ func (m *UDPMuxDefault) connWorker() { if os.IsTimeout(err) { continue } else if !errors.Is(err, io.EOF) { - logger.Errorf("could not read udp packet: %v", err) + logger.Errorf("Failed to read UDP packet: %v", err) } return } - udpAddr, ok := addr.(*net.UDPAddr) + netUDPAddr, ok := addr.(*net.UDPAddr) if !ok { - logger.Errorf("underlying PacketConn did not return a UDPAddr") + logger.Errorf("Underlying PacketConn did not return a UDPAddr") + + return + } + udpAddr, err := newIPPort(netUDPAddr.IP, netUDPAddr.Zone, uint16(netUDPAddr.Port)) //nolint:gosec + if err != nil { + logger.Errorf("Failed to create a new IP/Port host pair") + return } // If we have already seen this address dispatch to the appropriate destination m.addressMapMu.Lock() - destinationConn := m.addressMap[addr.String()] + destinationConn := m.addressMap[udpAddr] m.addressMapMu.Unlock() // If we haven't seen this address before but is a STUN packet lookup by ufrag @@ -315,17 +329,19 @@ func (m *UDPMuxDefault) connWorker() { if err = msg.Decode(); err != nil { m.params.Logger.Warnf("Failed to handle decode ICE from %s: %v", addr.String(), err) + continue } attr, stunAttrErr := msg.Get(stun.AttrUsername) if stunAttrErr != nil { m.params.Logger.Warnf("No Username attribute in STUN message from %s", addr.String()) + continue } ufrag := strings.Split(string(attr), ":")[0] - isIPv6 := udpAddr.IP.To4() == nil + isIPv6 := netUDPAddr.IP.To4() == nil m.mu.Lock() destinationConn, _ = m.getConn(ufrag, isIPv6) @@ -333,12 +349,13 @@ func (m *UDPMuxDefault) connWorker() { } if destinationConn == nil { - m.params.Logger.Tracef("dropping packet from %s, addr: %s", udpAddr.String(), addr.String()) + m.params.Logger.Tracef("Dropping packet from %s, addr: %s", udpAddr.addr, addr) + continue } - if err = destinationConn.writePacket(buf[:n], udpAddr); err != nil { - m.params.Logger.Errorf("could not write packet: %v", err) + if err = destinationConn.writePacket(buf[:n], netUDPAddr); err != nil { + m.params.Logger.Errorf("Failed to write packet: %v", err) } } } @@ -349,11 +366,14 @@ func (m *UDPMuxDefault) getConn(ufrag string, isIPv6 bool) (val *udpMuxedConn, o } else { val, ok = m.connsIPv4[ufrag] } + return } type bufferHolder struct { - buf []byte + next *bufferHolder + buf []byte + addr *net.UDPAddr } func newBufferHolder(size int) *bufferHolder { @@ -361,3 +381,28 @@ func newBufferHolder(size int) *bufferHolder { buf: make([]byte, size), } } + +func (b *bufferHolder) reset() { + b.next = nil + b.addr = nil +} + +type ipPort struct { + addr netip.Addr + port uint16 +} + +// newIPPort create a custom type of address based on netip.Addr and +// port. The underlying ip address passed is converted to IPv6 format +// to simplify ip address handling. +func newIPPort(ip net.IP, zone string, port uint16) (ipPort, error) { + n, ok := netip.AddrFromSlice(ip.To16()) + if !ok { + return ipPort{}, errInvalidIPAddress + } + + return ipPort{ + addr: n.WithZone(zone), + port: port, + }, nil +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/udp_mux_multi.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/udp_mux_multi.go similarity index 84% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/udp_mux_multi.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/udp_mux_multi.go index 158cbc37f..46c88bb93 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/udp_mux_multi.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/udp_mux_multi.go @@ -8,8 +8,8 @@ import ( "net" "github.com/pion/logging" - "github.com/pion/transport/v2" - "github.com/pion/transport/v2/stdnet" + "github.com/pion/transport/v3" + "github.com/pion/transport/v3/stdnet" ) // MultiUDPMuxDefault implements both UDPMux and AllConnsGetter, @@ -29,6 +29,7 @@ func NewMultiUDPMuxDefault(muxes ...UDPMux) *MultiUDPMuxDefault { addrToMux[addr.String()] = mux } } + return &MultiUDPMuxDefault{ muxes: muxes, localAddrToMux: addrToMux, @@ -42,6 +43,7 @@ func (m *MultiUDPMuxDefault) GetConn(ufrag string, addr net.Addr) (net.PacketCon if !ok { return nil, errNoUDPMuxAvailable } + return mux.GetConn(ufrag, addr) } @@ -53,7 +55,7 @@ func (m *MultiUDPMuxDefault) RemoveConnByUfrag(ufrag string) { } } -// Close the multi mux, no further connections could be created +// Close the multi mux, no further connections could be created. func (m *MultiUDPMuxDefault) Close() error { var err error for _, mux := range m.muxes { @@ -61,21 +63,23 @@ func (m *MultiUDPMuxDefault) Close() error { err = e } } + return err } -// GetListenAddresses returns the list of addresses that this mux is listening on +// GetListenAddresses returns the list of addresses that this mux is listening on. func (m *MultiUDPMuxDefault) GetListenAddresses() []net.Addr { addrs := make([]net.Addr, 0, len(m.localAddrToMux)) for _, mux := range m.muxes { addrs = append(addrs, mux.GetListenAddresses()...) } + return addrs } // NewMultiUDPMuxFromPort creates an instance of MultiUDPMuxDefault that // listen all interfaces on the provided port. -func NewMultiUDPMuxFromPort(port int, opts ...UDPMuxFromPortOption) (*MultiUDPMuxDefault, error) { +func NewMultiUDPMuxFromPort(port int, opts ...UDPMuxFromPortOption) (*MultiUDPMuxDefault, error) { //nolint:cyclop params := multiUDPMuxFromPortParam{ networks: []NetworkType{NetworkTypeUDP4, NetworkTypeUDP6}, } @@ -90,16 +94,21 @@ func NewMultiUDPMuxFromPort(port int, opts ...UDPMuxFromPortOption) (*MultiUDPMu } } - ips, err := localInterfaces(params.net, params.ifFilter, params.ipFilter, params.networks, params.includeLoopback) + _, addrs, err := localInterfaces(params.net, params.ifFilter, params.ipFilter, params.networks, params.includeLoopback) if err != nil { return nil, err } - conns := make([]net.PacketConn, 0, len(ips)) - for _, ip := range ips { - conn, listenErr := params.net.ListenUDP("udp", &net.UDPAddr{IP: ip, Port: port}) + conns := make([]net.PacketConn, 0, len(addrs)) + for _, addr := range addrs { + conn, listenErr := params.net.ListenUDP("udp", &net.UDPAddr{ + IP: addr.AsSlice(), + Port: port, + Zone: addr.Zone(), + }) if listenErr != nil { err = listenErr + break } if params.readBufferSize > 0 { @@ -115,6 +124,7 @@ func NewMultiUDPMuxFromPort(port int, opts ...UDPMuxFromPortOption) (*MultiUDPMu for _, conn := range conns { _ = conn.Close() } + return nil, err } @@ -131,14 +141,14 @@ func NewMultiUDPMuxFromPort(port int, opts ...UDPMuxFromPortOption) (*MultiUDPMu return NewMultiUDPMuxDefault(muxes...), nil } -// UDPMuxFromPortOption provide options for NewMultiUDPMuxFromPort +// UDPMuxFromPortOption provide options for NewMultiUDPMuxFromPort. type UDPMuxFromPortOption interface { apply(*multiUDPMuxFromPortParam) } type multiUDPMuxFromPortParam struct { - ifFilter func(string) bool - ipFilter func(ip net.IP) bool + ifFilter func(string) (keep bool) + ipFilter func(ip net.IP) (keep bool) networks []NetworkType readBufferSize int writeBufferSize int @@ -155,8 +165,8 @@ func (o *udpMuxFromPortOption) apply(p *multiUDPMuxFromPortParam) { o.f(p) } -// UDPMuxFromPortWithInterfaceFilter set the filter to filter out interfaces that should not be used -func UDPMuxFromPortWithInterfaceFilter(f func(string) bool) UDPMuxFromPortOption { +// UDPMuxFromPortWithInterfaceFilter set the filter to filter out interfaces that should not be used. +func UDPMuxFromPortWithInterfaceFilter(f func(string) (keep bool)) UDPMuxFromPortOption { return &udpMuxFromPortOption{ f: func(p *multiUDPMuxFromPortParam) { p.ifFilter = f @@ -164,8 +174,8 @@ func UDPMuxFromPortWithInterfaceFilter(f func(string) bool) UDPMuxFromPortOption } } -// UDPMuxFromPortWithIPFilter set the filter to filter out IP addresses that should not be used -func UDPMuxFromPortWithIPFilter(f func(ip net.IP) bool) UDPMuxFromPortOption { +// UDPMuxFromPortWithIPFilter set the filter to filter out IP addresses that should not be used. +func UDPMuxFromPortWithIPFilter(f func(ip net.IP) (keep bool)) UDPMuxFromPortOption { return &udpMuxFromPortOption{ f: func(p *multiUDPMuxFromPortParam) { p.ipFilter = f @@ -173,7 +183,7 @@ func UDPMuxFromPortWithIPFilter(f func(ip net.IP) bool) UDPMuxFromPortOption { } } -// UDPMuxFromPortWithNetworks set the networks that should be used. default is both IPv4 and IPv6 +// UDPMuxFromPortWithNetworks set the networks that should be used. default is both IPv4 and IPv6. func UDPMuxFromPortWithNetworks(networks ...NetworkType) UDPMuxFromPortOption { return &udpMuxFromPortOption{ f: func(p *multiUDPMuxFromPortParam) { @@ -182,7 +192,7 @@ func UDPMuxFromPortWithNetworks(networks ...NetworkType) UDPMuxFromPortOption { } } -// UDPMuxFromPortWithReadBufferSize set the UDP connection read buffer size +// UDPMuxFromPortWithReadBufferSize set the UDP connection read buffer size. func UDPMuxFromPortWithReadBufferSize(size int) UDPMuxFromPortOption { return &udpMuxFromPortOption{ f: func(p *multiUDPMuxFromPortParam) { @@ -191,7 +201,7 @@ func UDPMuxFromPortWithReadBufferSize(size int) UDPMuxFromPortOption { } } -// UDPMuxFromPortWithWriteBufferSize set the UDP connection write buffer size +// UDPMuxFromPortWithWriteBufferSize set the UDP connection write buffer size. func UDPMuxFromPortWithWriteBufferSize(size int) UDPMuxFromPortOption { return &udpMuxFromPortOption{ f: func(p *multiUDPMuxFromPortParam) { @@ -200,7 +210,7 @@ func UDPMuxFromPortWithWriteBufferSize(size int) UDPMuxFromPortOption { } } -// UDPMuxFromPortWithLogger set the logger for the created UDPMux +// UDPMuxFromPortWithLogger set the logger for the created UDPMux. func UDPMuxFromPortWithLogger(logger logging.LeveledLogger) UDPMuxFromPortOption { return &udpMuxFromPortOption{ f: func(p *multiUDPMuxFromPortParam) { @@ -209,7 +219,7 @@ func UDPMuxFromPortWithLogger(logger logging.LeveledLogger) UDPMuxFromPortOption } } -// UDPMuxFromPortWithLoopback set loopback interface should be included +// UDPMuxFromPortWithLoopback set loopback interface should be included. func UDPMuxFromPortWithLoopback() UDPMuxFromPortOption { return &udpMuxFromPortOption{ f: func(p *multiUDPMuxFromPortParam) { diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/udp_mux_universal.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/udp_mux_universal.go similarity index 85% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/udp_mux_universal.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/udp_mux_universal.go index 07b6a70ea..50c80af5d 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/udp_mux_universal.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/udp_mux_universal.go @@ -9,8 +9,8 @@ import ( "time" "github.com/pion/logging" - "github.com/pion/stun" - "github.com/pion/transport/v2" + "github.com/pion/stun/v3" + "github.com/pion/transport/v3" ) // UniversalUDPMux allows multiple connections to go over a single UDP port for @@ -29,7 +29,8 @@ type UniversalUDPMuxDefault struct { *UDPMuxDefault params UniversalUDPMuxParams - // Since we have a shared socket, for srflx candidates it makes sense to have a shared mapped address across all the agents + // Since we have a shared socket, for srflx candidates it makes sense + // to have a shared mapped address across all the agents // stun.XORMappedAddress indexed by the STUN server addr xorMappedMap map[string]*xorMapped } @@ -42,7 +43,7 @@ type UniversalUDPMuxParams struct { Net transport.Net } -// NewUniversalUDPMuxDefault creates an implementation of UniversalUDPMux embedding UDPMux +// NewUniversalUDPMuxDefault creates an implementation of UniversalUDPMux embedding UDPMux. func NewUniversalUDPMuxDefault(params UniversalUDPMuxParams) *UniversalUDPMuxDefault { if params.Logger == nil { params.Logger = logging.NewDefaultLoggerFactory().NewLogger("ice") @@ -51,31 +52,31 @@ func NewUniversalUDPMuxDefault(params UniversalUDPMuxParams) *UniversalUDPMuxDef params.XORMappedAddrCacheTTL = time.Second * 25 } - m := &UniversalUDPMuxDefault{ + mux := &UniversalUDPMuxDefault{ params: params, xorMappedMap: make(map[string]*xorMapped), } // Wrap UDP connection, process server reflexive messages // before they are passed to the UDPMux connection handler (connWorker) - m.params.UDPConn = &udpConn{ + mux.params.UDPConn = &udpConn{ PacketConn: params.UDPConn, - mux: m, + mux: mux, logger: params.Logger, } // Embed UDPMux udpMuxParams := UDPMuxParams{ Logger: params.Logger, - UDPConn: m.params.UDPConn, - Net: m.params.Net, + UDPConn: mux.params.UDPConn, + Net: mux.params.Net, } - m.UDPMuxDefault = NewUDPMuxDefault(udpMuxParams) + mux.UDPMuxDefault = NewUDPMuxDefault(udpMuxParams) - return m + return mux } -// udpConn is a wrapper around UDPMux conn that overrides ReadFrom and handles STUN/TURN packets +// udpConn is a wrapper around UDPMux conn that overrides ReadFrom and handles STUN/TURN packets. type udpConn struct { net.PacketConn mux *UniversalUDPMuxDefault @@ -88,7 +89,8 @@ func (m *UniversalUDPMuxDefault) GetRelayedAddr(net.Addr, time.Duration) (*net.A return nil, errNotImplemented } -// GetConnForURL add uniques to the muxed connection by concatenating ufrag and URL (e.g. STUN URL) to be able to support multiple STUN/TURN servers +// GetConnForURL add uniques to the muxed connection by concatenating ufrag and URL +// (e.g. STUN URL) to be able to support multiple STUN/TURN servers // and return a unique connection per server. func (m *UniversalUDPMuxDefault) GetConnForURL(ufrag string, url string, addr net.Addr) (net.PacketConn, error) { return m.UDPMuxDefault.GetConn(fmt.Sprintf("%s%s", ufrag, url), addr) @@ -99,24 +101,24 @@ func (m *UniversalUDPMuxDefault) GetConnForURL(ufrag string, url string, addr ne func (c *udpConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) { n, addr, err = c.PacketConn.ReadFrom(p) if err != nil { - return + return n, addr, err } - if stun.IsMessage(p[:n]) { + if stun.IsMessage(p[:n]) { //nolint:nestif msg := &stun.Message{ Raw: append([]byte{}, p[:n]...), } if err = msg.Decode(); err != nil { c.logger.Warnf("Failed to handle decode ICE from %s: %v", addr.String(), err) - err = nil - return + + return n, addr, nil } udpAddr, ok := addr.(*net.UDPAddr) if !ok { // Message about this err will be logged in the UDPMux - return + return n, addr, err } if c.mux.isXORMappedResponse(msg, udpAddr.String()) { @@ -125,9 +127,11 @@ func (c *udpConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) { c.logger.Debugf("%w: %v", errGetXorMappedAddrResponse, err) err = nil } - return + + return n, addr, err } } + return n, addr, err } @@ -135,14 +139,16 @@ func (c *udpConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) { func (m *UniversalUDPMuxDefault) isXORMappedResponse(msg *stun.Message, stunAddr string) bool { m.mu.Lock() defer m.mu.Unlock() - // Check first if it is a STUN server address because remote peer can also send similar messages but as a BindingSuccess + // Check first if it is a STUN server address, + // because remote peer can also send similar messages but as a BindingSuccess. _, ok := m.xorMappedMap[stunAddr] _, err := msg.Get(stun.AttrXORMappedAddress) + return err == nil && ok } -// handleXORMappedResponse parses response from the STUN server, extracts XORMappedAddress attribute -// and set the mapped address for the server +// handleXORMappedResponse parses response from the STUN server, extracts XORMappedAddress attribute. +// and set the mapped address for the server. func (m *UniversalUDPMuxDefault) handleXORMappedResponse(stunAddr *net.UDPAddr, msg *stun.Message) error { m.mu.Lock() defer m.mu.Unlock() @@ -167,7 +173,10 @@ func (m *UniversalUDPMuxDefault) handleXORMappedResponse(stunAddr *net.UDPAddr, // Makes a STUN binding request to discover mapped address otherwise. // Blocks until the stun.XORMappedAddress has been discovered or deadline. // Method is safe for concurrent use. -func (m *UniversalUDPMuxDefault) GetXORMappedAddr(serverAddr net.Addr, deadline time.Duration) (*stun.XORMappedAddress, error) { +func (m *UniversalUDPMuxDefault) GetXORMappedAddr( + serverAddr net.Addr, + deadline time.Duration, +) (*stun.XORMappedAddress, error) { m.mu.Lock() mappedAddr, ok := m.xorMappedMap[serverAddr.String()] // If we already have a mapping for this STUN server (address already received) @@ -188,9 +197,9 @@ func (m *UniversalUDPMuxDefault) GetXORMappedAddr(serverAddr net.Addr, deadline // Otherwise, make a STUN request to discover the address // or wait for already sent request to complete - waitAddrReceived, err := m.sendSTUN(serverAddr) + waitAddrReceived, err := m.writeSTUN(serverAddr) if err != nil { - return nil, fmt.Errorf("%w: %s", errSendSTUNPacket, err) //nolint:errorlint + return nil, fmt.Errorf("%w: %s", errWriteSTUNMessage, err) //nolint:errorlint } // Block until response was handled by the connWorker routine and XORMappedAddress was updated @@ -203,17 +212,18 @@ func (m *UniversalUDPMuxDefault) GetXORMappedAddr(serverAddr net.Addr, deadline if mappedAddr.addr == nil { return nil, errNoXorAddrMapping } + return mappedAddr.addr, nil case <-time.After(deadline): return nil, errXORMappedAddrTimeout } } -// sendSTUN sends a STUN request via UDP conn. +// writeSTUN sends a STUN request via UDP conn. // // The returned channel is closed when the STUN response has been received. // Method is safe for concurrent use. -func (m *UniversalUDPMuxDefault) sendSTUN(serverAddr net.Addr) (chan struct{}, error) { +func (m *UniversalUDPMuxDefault) writeSTUN(serverAddr net.Addr) (chan struct{}, error) { m.mu.Lock() defer m.mu.Unlock() diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/udp_muxed_conn.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/udp_muxed_conn.go new file mode 100644 index 000000000..e32cb3059 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/udp_muxed_conn.go @@ -0,0 +1,252 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + +package ice + +import ( + "io" + "net" + "sync" + "time" + + "github.com/pion/logging" +) + +type udpMuxedConnState int + +const ( + udpMuxedConnOpen udpMuxedConnState = iota + udpMuxedConnWaiting + udpMuxedConnClosed +) + +type udpMuxedConnParams struct { + Mux *UDPMuxDefault + AddrPool *sync.Pool + Key string + LocalAddr net.Addr + Logger logging.LeveledLogger +} + +// udpMuxedConn represents a logical packet conn for a single remote as identified by ufrag. +type udpMuxedConn struct { + params *udpMuxedConnParams + // Remote addresses that we have sent to on this conn + addresses []ipPort + + // FIFO queue holding incoming packets + bufHead, bufTail *bufferHolder + notify chan struct{} + closedChan chan struct{} + state udpMuxedConnState + mu sync.Mutex +} + +func newUDPMuxedConn(params *udpMuxedConnParams) *udpMuxedConn { + return &udpMuxedConn{ + params: params, + notify: make(chan struct{}, 1), + closedChan: make(chan struct{}), + } +} + +func (c *udpMuxedConn) ReadFrom(b []byte) (n int, rAddr net.Addr, err error) { + for { + c.mu.Lock() + if c.bufTail != nil { + pkt := c.bufTail + c.bufTail = pkt.next + + if pkt == c.bufHead { + c.bufHead = nil + } + c.mu.Unlock() + + if len(b) < len(pkt.buf) { + err = io.ErrShortBuffer + } else { + n = copy(b, pkt.buf) + rAddr = pkt.addr + } + + pkt.reset() + c.params.AddrPool.Put(pkt) + + return n, rAddr, err + } + + if c.state == udpMuxedConnClosed { + c.mu.Unlock() + + return 0, nil, io.EOF + } + + c.state = udpMuxedConnWaiting + c.mu.Unlock() + + select { + case <-c.notify: + case <-c.closedChan: + return 0, nil, io.EOF + } + } +} + +func (c *udpMuxedConn) WriteTo(buf []byte, rAddr net.Addr) (n int, err error) { + if c.isClosed() { + return 0, io.ErrClosedPipe + } + // Each time we write to a new address, we'll register it with the mux + netUDPAddr, ok := rAddr.(*net.UDPAddr) + if !ok { + return 0, errFailedToCastUDPAddr + } + + //nolint:gosec // TODO add port validation G115 + ipAndPort, err := newIPPort(netUDPAddr.IP, netUDPAddr.Zone, uint16(netUDPAddr.Port)) + if err != nil { + return 0, err + } + if !c.containsAddress(ipAndPort) { + c.addAddress(ipAndPort) + } + + return c.params.Mux.writeTo(buf, rAddr) +} + +func (c *udpMuxedConn) LocalAddr() net.Addr { + return c.params.LocalAddr +} + +func (c *udpMuxedConn) SetDeadline(time.Time) error { + return nil +} + +func (c *udpMuxedConn) SetReadDeadline(time.Time) error { + return nil +} + +func (c *udpMuxedConn) SetWriteDeadline(time.Time) error { + return nil +} + +func (c *udpMuxedConn) CloseChannel() <-chan struct{} { + return c.closedChan +} + +func (c *udpMuxedConn) Close() error { + c.mu.Lock() + defer c.mu.Unlock() + if c.state != udpMuxedConnClosed { + for pkt := c.bufTail; pkt != nil; { + next := pkt.next + + pkt.reset() + c.params.AddrPool.Put(pkt) + + pkt = next + } + c.bufHead = nil + c.bufTail = nil + + c.state = udpMuxedConnClosed + close(c.closedChan) + } + + return nil +} + +func (c *udpMuxedConn) isClosed() bool { + c.mu.Lock() + defer c.mu.Unlock() + + return c.state == udpMuxedConnClosed +} + +func (c *udpMuxedConn) getAddresses() []ipPort { + c.mu.Lock() + defer c.mu.Unlock() + addresses := make([]ipPort, len(c.addresses)) + copy(addresses, c.addresses) + + return addresses +} + +func (c *udpMuxedConn) addAddress(addr ipPort) { + c.mu.Lock() + c.addresses = append(c.addresses, addr) + c.mu.Unlock() + + // Map it on mux + c.params.Mux.registerConnForAddress(c, addr) +} + +func (c *udpMuxedConn) removeAddress(addr ipPort) { + c.mu.Lock() + defer c.mu.Unlock() + + newAddresses := make([]ipPort, 0, len(c.addresses)) + for _, a := range c.addresses { + if a != addr { + newAddresses = append(newAddresses, a) + } + } + + c.addresses = newAddresses +} + +func (c *udpMuxedConn) containsAddress(addr ipPort) bool { + c.mu.Lock() + defer c.mu.Unlock() + for _, a := range c.addresses { + if addr == a { + return true + } + } + + return false +} + +func (c *udpMuxedConn) writePacket(data []byte, addr *net.UDPAddr) error { + pkt := c.params.AddrPool.Get().(*bufferHolder) //nolint:forcetypeassert + if cap(pkt.buf) < len(data) { + c.params.AddrPool.Put(pkt) + + return io.ErrShortBuffer + } + + pkt.buf = append(pkt.buf[:0], data...) + pkt.addr = addr + + c.mu.Lock() + if c.state == udpMuxedConnClosed { + c.mu.Unlock() + + pkt.reset() + c.params.AddrPool.Put(pkt) + + return io.ErrClosedPipe + } + + if c.bufHead != nil { + c.bufHead.next = pkt + } + c.bufHead = pkt + + if c.bufTail == nil { + c.bufTail = pkt + } + + state := c.state + c.state = udpMuxedConnOpen + c.mu.Unlock() + + if state == udpMuxedConnWaiting { + select { + case c.notify <- struct{}{}: + default: + } + } + + return nil +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/url.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/url.go similarity index 67% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/url.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/url.go index b2b9f8bd3..f18d78772 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/url.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/url.go @@ -3,80 +3,80 @@ package ice -import "github.com/pion/stun" +import "github.com/pion/stun/v3" type ( - // URL represents a STUN (rfc7064) or TURN (rfc7065) URI + // URL represents a STUN (rfc7064) or TURN (rfc7065) URI. // - // Deprecated: Please use pion/stun.URI + // Deprecated: Please use pion/stun.URI. URL = stun.URI // ProtoType indicates the transport protocol type that is used in the ice.URL // structure. // - // Deprecated: TPlease use pion/stun.ProtoType + // Deprecated: TPlease use pion/stun.ProtoType. ProtoType = stun.ProtoType // SchemeType indicates the type of server used in the ice.URL structure. // - // Deprecated: Please use pion/stun.SchemeType + // Deprecated: Please use pion/stun.SchemeType. SchemeType = stun.SchemeType ) const ( // SchemeTypeSTUN indicates the URL represents a STUN server. // - // Deprecated: Please use pion/stun.SchemeTypeSTUN + // Deprecated: Please use pion/stun.SchemeTypeSTUN. SchemeTypeSTUN = stun.SchemeTypeSTUN // SchemeTypeSTUNS indicates the URL represents a STUNS (secure) server. // - // Deprecated: Please use pion/stun.SchemeTypeSTUNS + // Deprecated: Please use pion/stun.SchemeTypeSTUNS. SchemeTypeSTUNS = stun.SchemeTypeSTUNS // SchemeTypeTURN indicates the URL represents a TURN server. // - // Deprecated: Please use pion/stun.SchemeTypeTURN + // Deprecated: Please use pion/stun.SchemeTypeTURN. SchemeTypeTURN = stun.SchemeTypeTURN // SchemeTypeTURNS indicates the URL represents a TURNS (secure) server. // - // Deprecated: Please use pion/stun.SchemeTypeTURNS + // Deprecated: Please use pion/stun.SchemeTypeTURNS. SchemeTypeTURNS = stun.SchemeTypeTURNS ) const ( // ProtoTypeUDP indicates the URL uses a UDP transport. // - // Deprecated: Please use pion/stun.ProtoTypeUDP + // Deprecated: Please use pion/stun.ProtoTypeUDP. ProtoTypeUDP = stun.ProtoTypeUDP // ProtoTypeTCP indicates the URL uses a TCP transport. // - // Deprecated: Please use pion/stun.ProtoTypeTCP + // Deprecated: Please use pion/stun.ProtoTypeTCP. ProtoTypeTCP = stun.ProtoTypeTCP ) -// Unknown represents and unknown ProtoType or SchemeType +// Unknown represents and unknown ProtoType or SchemeType. // -// Deprecated: Please use pion/stun.SchemeTypeUnknown or pion/stun.ProtoTypeUnknown +// Deprecated: Please use pion/stun.SchemeTypeUnknown or pion/stun.ProtoTypeUnknown. const Unknown = 0 -// ParseURL parses a STUN or TURN urls following the ABNF syntax described in +// ParseURL parses a STUN or TURN urls following the ABNF syntax described in. // https://tools.ietf.org/html/rfc7064 and https://tools.ietf.org/html/rfc7065 // respectively. // -// Deprecated: Please use pion/stun.ParseURI +// Deprecated: Please use pion/stun.ParseURI. var ParseURL = stun.ParseURI //nolint:gochecknoglobals -// NewSchemeType defines a procedure for creating a new SchemeType from a raw +// NewSchemeType defines a procedure for creating a new SchemeType from a raw. // string naming the scheme type. // -// Deprecated: Please use pion/stun.NewSchemeType +// Deprecated: Please use pion/stun.NewSchemeType. var NewSchemeType = stun.NewSchemeType //nolint:gochecknoglobals -// NewProtoType defines a procedure for creating a new ProtoType from a raw +// NewProtoType defines a procedure for creating a new ProtoType from a raw. // string naming the transport protocol type. // -// Deprecated: Please use pion/stun.NewProtoType +// Deprecated: Please use pion/stun.NewProtoType. var NewProtoType = stun.NewProtoType //nolint:gochecknoglobals diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/usecandidate.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/usecandidate.go similarity index 94% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/usecandidate.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/usecandidate.go index 6fc7ed50c..512f50438 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/usecandidate.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v4/usecandidate.go @@ -3,7 +3,7 @@ package ice -import "github.com/pion/stun" +import "github.com/pion/stun/v3" // UseCandidateAttr represents USE-CANDIDATE attribute. type UseCandidateAttr struct{} @@ -11,12 +11,14 @@ type UseCandidateAttr struct{} // AddTo adds USE-CANDIDATE attribute to message. func (UseCandidateAttr) AddTo(m *stun.Message) error { m.Add(stun.AttrUseCandidate, nil) + return nil } // IsSet returns true if USE-CANDIDATE attribute is set. func (UseCandidateAttr) IsSet(m *stun.Message) bool { _, err := m.Get(stun.AttrUseCandidate) + return err == nil } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/.golangci.yml b/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/.golangci.yml index 4e3eddf42..a3235bec2 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/.golangci.yml +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/.golangci.yml @@ -1,9 +1,13 @@ # SPDX-FileCopyrightText: 2023 The Pion community # SPDX-License-Identifier: MIT +run: + timeout: 5m + linters-settings: govet: - check-shadowing: true + enable: + - shadow misspell: locale: US exhaustive: @@ -29,7 +33,6 @@ linters: - bodyclose # checks whether HTTP response body is closed successfully - contextcheck # check the function whether use a non-inherited context - decorder # check declaration order and count of types, constants, variables and functions - - depguard # Go linter that checks if package imports are in a list of acceptable packages - dogsled # Checks assignments with too many blank identifiers (e.g. x, _, _, _, := f()) - dupl # Tool for code clone detection - durationcheck # check for two durations multiplied together @@ -48,7 +51,7 @@ linters: - goconst # Finds repeated strings that could be replaced by a constant - gocritic # The most opinionated Go source code linter - godox # Tool for detection of FIXME, TODO and other comment keywords - - goerr113 # Golang linter to check the errors handling expressions + - err113 # Golang linter to check the errors handling expressions - gofmt # Gofmt checks whether code was gofmt-ed. By default this tool runs with -s option to check for code simplification - gofumpt # Gofumpt checks whether code was gofumpt-ed. - goheader # Checks is file header matches to pattern @@ -63,7 +66,6 @@ linters: - importas # Enforces consistent import aliases - ineffassign # Detects when assignments to existing variables are not used - misspell # Finds commonly misspelled English words in comments - - nakedret # Finds naked returns in functions greater than a specified function length - nilerr # Finds the code that returns nil even if it checks that the error is not nil. - nilnil # Checks that there is no simultaneous return of `nil` error and an invalid value. - noctx # noctx finds sending http request without context.Context @@ -81,19 +83,18 @@ linters: - wastedassign # wastedassign finds wasted assignment statements - whitespace # Tool for detection of leading and trailing whitespace disable: + - depguard # Go linter that checks if package imports are in a list of acceptable packages - containedctx # containedctx is a linter that detects struct contained context.Context field - cyclop # checks function and package cyclomatic complexity - - exhaustivestruct # Checks if all struct's fields are initialized - funlen # Tool for detection of long functions - gocyclo # Computes and checks the cyclomatic complexity of functions - godot # Check if comments end in a period - gomnd # An analyzer to detect magic numbers. - - ifshort # Checks that your code uses short syntax for if-statements whenever possible - ireturn # Accept Interfaces, Return Concrete Types - lll # Reports long lines - maintidx # maintidx measures the maintainability index of each function. - makezero # Finds slice declarations with non-zero initial length - - maligned # Tool to detect Go structs that would take less memory if their fields were sorted + - nakedret # Finds naked returns in functions greater than a specified function length - nestif # Reports deeply nested if statements - nlreturn # nlreturn checks for a new line before return and branch statements to increase code clarity - nolintlint # Reports ill-formed or insufficient nolint directives @@ -110,28 +111,15 @@ linters: issues: exclude-use-default: false + exclude-dirs-use-default: false exclude-rules: - # Allow complex tests, better to be self contained - - path: _test\.go - linters: - - gocognit - - forbidigo - - # Allow complex main function in examples - - path: examples - text: "of func `main` is high" - linters: - - gocognit - - # Allow forbidden identifiers in examples - - path: examples + # Allow complex tests and examples, better to be self contained + - path: (examples|main\.go|_test\.go) linters: - forbidigo + - gocognit # Allow forbidden identifiers in CLI commands - path: cmd linters: - forbidigo - -run: - skip-dirs-use-default: false diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/AUTHORS.txt b/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/AUTHORS.txt deleted file mode 100644 index 44a421ef8..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/AUTHORS.txt +++ /dev/null @@ -1,30 +0,0 @@ -# Thank you to everyone that made Pion possible. If you are interested in contributing -# we would love to have you https://github.com/pion/webrtc/wiki/Contributing -# -# This file is auto generated, using git to list all individuals contributors. -# see https://github.com/pion/.goassets/blob/master/scripts/generate-authors.sh for the scripting -Aaron Boushley -Adam Kiss -adamroach -Aditya Kumar -aler9 <46489434+aler9@users.noreply.github.com> -Antoine Baché -Atsushi Watanabe -Bobby Peck -boks1971 -David Zhao -Jonathan Müller -Kevin Caffrey -Maksim Nesterov -Mathis Engelbart -Miroslav -Miroslav Šedivý -Quentin Renard -Rayleigh Li -Sean DuBois -Steffen Vogel -XLPolar -ziminghua <565209960@qq.com> - -# List of contributors not appearing in Git history - diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/README.md b/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/README.md index dcc856f1e..5db5d4414 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/README.md +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/README.md @@ -78,7 +78,7 @@ We are always looking to support **your projects**. Please reach out if you have If you need commercial support or don't want to use public methods you can contact us at [team@pion.ly](mailto:team@pion.ly) ### Contributing -Check out the [contributing wiki](https://github.com/pion/webrtc/wiki/Contributing) to join the group of amazing people making this project possible: [AUTHORS.txt](./AUTHORS.txt) +Check out the [contributing wiki](https://github.com/pion/webrtc/wiki/Contributing) to join the group of amazing people making this project possible ### License MIT License - see [LICENSE](LICENSE) for full text diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/attributes.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/attributes.go index d7936d526..8b6d0f5cf 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/attributes.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/attributes.go @@ -33,7 +33,7 @@ func (a Attributes) Set(key interface{}, val interface{}) { } // GetRTPHeader gets the RTP header if present. If it is not present, it will be -// unmarshalled from the raw byte slice and stored in the attribtues. +// unmarshalled from the raw byte slice and stored in the attributes. func (a Attributes) GetRTPHeader(raw []byte) (*rtp.Header, error) { if val, ok := a[rtpHeaderKey]; ok { if header, ok := val.(*rtp.Header); ok { @@ -50,7 +50,7 @@ func (a Attributes) GetRTPHeader(raw []byte) (*rtp.Header, error) { } // GetRTCPPackets gets the RTCP packets if present. If the packet slice is not -// present, it will be unmarshaled from the raw byte slice and stored in the +// present, it will be unmarshalled from the raw byte slice and stored in the // attributes. func (a Attributes) GetRTCPPackets(raw []byte) ([]rtcp.Packet, error) { if val, ok := a[rtcpPacketsKey]; ok { diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/internal/sequencenumber/unwrapper.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/internal/sequencenumber/unwrapper.go new file mode 100644 index 000000000..311ff09df --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/internal/sequencenumber/unwrapper.go @@ -0,0 +1,45 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + +// Package sequencenumber provides a sequence number unwrapper +package sequencenumber + +const ( + maxSequenceNumberPlusOne = int64(65536) + breakpoint = 32768 // half of max uint16 +) + +// Unwrapper stores an unwrapped sequence number +type Unwrapper struct { + init bool + lastUnwrapped int64 +} + +func isNewer(value, previous uint16) bool { + if value-previous == breakpoint { + return value > previous + } + return value != previous && (value-previous) < breakpoint +} + +// Unwrap unwraps the next sequencenumber +func (u *Unwrapper) Unwrap(i uint16) int64 { + if !u.init { + u.init = true + u.lastUnwrapped = int64(i) + return u.lastUnwrapped + } + + lastWrapped := uint16(u.lastUnwrapped) + delta := int64(i - lastWrapped) + if isNewer(i, lastWrapped) { + if delta < 0 { + delta += maxSequenceNumberPlusOne + } + } else if delta > 0 && u.lastUnwrapped+delta-maxSequenceNumberPlusOne >= 0 { + delta -= maxSequenceNumberPlusOne + } + + u.lastUnwrapped += delta + return u.lastUnwrapped +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/pkg/nack/generator_interceptor.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/pkg/nack/generator_interceptor.go index faf533ba4..ab2bb2c52 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/pkg/nack/generator_interceptor.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/pkg/nack/generator_interceptor.go @@ -21,12 +21,15 @@ type GeneratorInterceptorFactory struct { // NewInterceptor constructs a new ReceiverInterceptor func (g *GeneratorInterceptorFactory) NewInterceptor(_ string) (interceptor.Interceptor, error) { i := &GeneratorInterceptor{ - size: 512, - skipLastN: 0, - interval: time.Millisecond * 100, - receiveLogs: map[uint32]*receiveLog{}, - close: make(chan struct{}), - log: logging.NewDefaultLoggerFactory().NewLogger("nack_generator"), + streamsFilter: streamSupportNack, + size: 512, + skipLastN: 0, + maxNacksPerPacket: 0, + interval: time.Millisecond * 100, + receiveLogs: map[uint32]*receiveLog{}, + nackCountLogs: map[uint32]map[uint16]uint16{}, + close: make(chan struct{}), + log: logging.NewDefaultLoggerFactory().NewLogger("nack_generator"), } for _, opt := range g.opts { @@ -45,13 +48,16 @@ func (g *GeneratorInterceptorFactory) NewInterceptor(_ string) (interceptor.Inte // GeneratorInterceptor interceptor generates nack feedback messages. type GeneratorInterceptor struct { interceptor.NoOp - size uint16 - skipLastN uint16 - interval time.Duration - m sync.Mutex - wg sync.WaitGroup - close chan struct{} - log logging.LeveledLogger + streamsFilter func(info *interceptor.StreamInfo) bool + size uint16 + skipLastN uint16 + maxNacksPerPacket uint16 + interval time.Duration + m sync.Mutex + wg sync.WaitGroup + close chan struct{} + log logging.LeveledLogger + nackCountLogs map[uint32]map[uint16]uint16 receiveLogs map[uint32]*receiveLog receiveLogsMu sync.Mutex @@ -82,7 +88,7 @@ func (n *GeneratorInterceptor) BindRTCPWriter(writer interceptor.RTCPWriter) int // BindRemoteStream lets you modify any incoming RTP packets. It is called once for per RemoteStream. The returned method // will be called once per rtp packet. func (n *GeneratorInterceptor) BindRemoteStream(info *interceptor.StreamInfo, reader interceptor.RTPReader) interceptor.RTPReader { - if !streamSupportNack(info) { + if !n.streamsFilter(info) { return reader } @@ -131,6 +137,7 @@ func (n *GeneratorInterceptor) Close() error { return nil } +// nolint:gocognit func (n *GeneratorInterceptor) loop(rtcpWriter interceptor.RTCPWriter) { defer n.wg.Done() @@ -147,14 +154,47 @@ func (n *GeneratorInterceptor) loop(rtcpWriter interceptor.RTCPWriter) { for ssrc, receiveLog := range n.receiveLogs { missing := receiveLog.missingSeqNumbers(n.skipLastN) + + if len(missing) == 0 || n.nackCountLogs[ssrc] == nil { + n.nackCountLogs[ssrc] = map[uint16]uint16{} + } if len(missing) == 0 { continue } + filteredMissing := []uint16{} + if n.maxNacksPerPacket > 0 { + for _, missingSeq := range missing { + if n.nackCountLogs[ssrc][missingSeq] < n.maxNacksPerPacket { + filteredMissing = append(filteredMissing, missingSeq) + } + n.nackCountLogs[ssrc][missingSeq]++ + } + } else { + filteredMissing = missing + } + nack := &rtcp.TransportLayerNack{ SenderSSRC: senderSSRC, MediaSSRC: ssrc, - Nacks: rtcp.NackPairsFromSequenceNumbers(missing), + Nacks: rtcp.NackPairsFromSequenceNumbers(filteredMissing), + } + + for nackSeq := range n.nackCountLogs[ssrc] { + isMissing := false + for _, missingSeq := range missing { + if missingSeq == nackSeq { + isMissing = true + break + } + } + if !isMissing { + delete(n.nackCountLogs[ssrc], nackSeq) + } + } + + if len(filteredMissing) == 0 { + continue } if _, err := rtcpWriter.Write([]rtcp.Packet{nack}, interceptor.Attributes{}); err != nil { diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/pkg/nack/generator_option.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/pkg/nack/generator_option.go index e4f46f7c9..5403e3eee 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/pkg/nack/generator_option.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/pkg/nack/generator_option.go @@ -6,6 +6,7 @@ package nack import ( "time" + "github.com/pion/interceptor" "github.com/pion/logging" ) @@ -30,6 +31,15 @@ func GeneratorSkipLastN(skipLastN uint16) GeneratorOption { } } +// GeneratorMaxNacksPerPacket sets the maximum number of NACKs sent per missing packet, e.g. if set to 2, a missing +// packet will only be NACKed at most twice. If set to 0 (default), max number of NACKs is unlimited +func GeneratorMaxNacksPerPacket(maxNacks uint16) GeneratorOption { + return func(r *GeneratorInterceptor) error { + r.maxNacksPerPacket = maxNacks + return nil + } +} + // GeneratorLog sets a logger for the interceptor func GeneratorLog(log logging.LeveledLogger) GeneratorOption { return func(r *GeneratorInterceptor) error { @@ -45,3 +55,11 @@ func GeneratorInterval(interval time.Duration) GeneratorOption { return nil } } + +// GeneratorStreamsFilter sets filter for generator streams +func GeneratorStreamsFilter(filter func(info *interceptor.StreamInfo) bool) GeneratorOption { + return func(r *GeneratorInterceptor) error { + r.streamsFilter = filter + return nil + } +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/pkg/nack/responder_interceptor.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/pkg/nack/responder_interceptor.go index 8f74952dd..22d038ba4 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/pkg/nack/responder_interceptor.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/pkg/nack/responder_interceptor.go @@ -18,15 +18,16 @@ type ResponderInterceptorFactory struct { } type packetFactory interface { - NewPacket(header *rtp.Header, payload []byte) (*retainablePacket, error) + NewPacket(header *rtp.Header, payload []byte, rtxSsrc uint32, rtxPayloadType uint8) (*retainablePacket, error) } // NewInterceptor constructs a new ResponderInterceptor func (r *ResponderInterceptorFactory) NewInterceptor(_ string) (interceptor.Interceptor, error) { i := &ResponderInterceptor{ - size: 1024, - log: logging.NewDefaultLoggerFactory().NewLogger("nack_responder"), - streams: map[uint32]*localStream{}, + streamsFilter: streamSupportNack, + size: 1024, + log: logging.NewDefaultLoggerFactory().NewLogger("nack_responder"), + streams: map[uint32]*localStream{}, } for _, opt := range r.opts { @@ -49,6 +50,7 @@ func (r *ResponderInterceptorFactory) NewInterceptor(_ string) (interceptor.Inte // ResponderInterceptor responds to nack feedback messages type ResponderInterceptor struct { interceptor.NoOp + streamsFilter func(info *interceptor.StreamInfo) bool size uint16 log logging.LeveledLogger packetFactory packetFactory @@ -99,18 +101,21 @@ func (n *ResponderInterceptor) BindRTCPReader(reader interceptor.RTCPReader) int // BindLocalStream lets you modify any outgoing RTP packets. It is called once for per LocalStream. The returned method // will be called once per rtp packet. func (n *ResponderInterceptor) BindLocalStream(info *interceptor.StreamInfo, writer interceptor.RTPWriter) interceptor.RTPWriter { - if !streamSupportNack(info) { + if !n.streamsFilter(info) { return writer } // error is already checked in NewGeneratorInterceptor sendBuffer, _ := newSendBuffer(n.size) n.streamsMu.Lock() - n.streams[info.SSRC] = &localStream{sendBuffer: sendBuffer, rtpWriter: writer} + n.streams[info.SSRC] = &localStream{ + sendBuffer: sendBuffer, + rtpWriter: writer, + } n.streamsMu.Unlock() return interceptor.RTPWriterFunc(func(header *rtp.Header, payload []byte, attributes interceptor.Attributes) (int, error) { - pkt, err := n.packetFactory.NewPacket(header, payload) + pkt, err := n.packetFactory.NewPacket(header, payload, info.SSRCRetransmission, info.PayloadTypeRetransmission) if err != nil { return 0, err } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/pkg/nack/responder_option.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/pkg/nack/responder_option.go index 0aaa7577f..24c7c4693 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/pkg/nack/responder_option.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/pkg/nack/responder_option.go @@ -3,7 +3,10 @@ package nack -import "github.com/pion/logging" +import ( + "github.com/pion/interceptor" + "github.com/pion/logging" +) // ResponderOption can be used to configure ResponderInterceptor type ResponderOption func(s *ResponderInterceptor) error @@ -33,3 +36,11 @@ func DisableCopy() ResponderOption { return nil } } + +// ResponderStreamsFilter sets filter for local streams +func ResponderStreamsFilter(filter func(info *interceptor.StreamInfo) bool) ResponderOption { + return func(r *ResponderInterceptor) error { + r.streamsFilter = filter + return nil + } +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/pkg/nack/retainable_packet.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/pkg/nack/retainable_packet.go index 31e9d832f..18c533a8a 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/pkg/nack/retainable_packet.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/pkg/nack/retainable_packet.go @@ -4,6 +4,7 @@ package nack import ( + "encoding/binary" "io" "sync" @@ -13,8 +14,9 @@ import ( const maxPayloadLen = 1460 type packetManager struct { - headerPool *sync.Pool - payloadPool *sync.Pool + headerPool *sync.Pool + payloadPool *sync.Pool + rtxSequencer rtp.Sequencer } func newPacketManager() *packetManager { @@ -30,16 +32,18 @@ func newPacketManager() *packetManager { return &buf }, }, + rtxSequencer: rtp.NewRandomSequencer(), } } -func (m *packetManager) NewPacket(header *rtp.Header, payload []byte) (*retainablePacket, error) { +func (m *packetManager) NewPacket(header *rtp.Header, payload []byte, rtxSsrc uint32, rtxPayloadType uint8) (*retainablePacket, error) { if len(payload) > maxPayloadLen { return nil, io.ErrShortBuffer } p := &retainablePacket{ - onRelease: m.releasePacket, + onRelease: m.releasePacket, + sequenceNumber: header.SequenceNumber, // new packets have retain count of 1 count: 1, } @@ -62,6 +66,29 @@ func (m *packetManager) NewPacket(header *rtp.Header, payload []byte) (*retainab p.payload = (*p.buffer)[:size] } + if rtxSsrc != 0 && rtxPayloadType != 0 { + // Store the original sequence number and rewrite the sequence number. + originalSequenceNumber := p.header.SequenceNumber + p.header.SequenceNumber = m.rtxSequencer.NextSequenceNumber() + + // Rewrite the SSRC. + p.header.SSRC = rtxSsrc + // Rewrite the payload type. + p.header.PayloadType = rtxPayloadType + + // Remove padding if present. + paddingLength := 0 + if p.header.Padding && p.payload != nil && len(p.payload) > 0 { + paddingLength = int(p.payload[len(p.payload)-1]) + p.header.Padding = false + } + + // Write the original sequence number at the beginning of the payload. + payload := make([]byte, 2) + binary.BigEndian.PutUint16(payload, originalSequenceNumber) + p.payload = append(payload, p.payload[:len(p.payload)-paddingLength]...) + } + return p, nil } @@ -74,12 +101,13 @@ func (m *packetManager) releasePacket(header *rtp.Header, payload *[]byte) { type noOpPacketFactory struct{} -func (f *noOpPacketFactory) NewPacket(header *rtp.Header, payload []byte) (*retainablePacket, error) { +func (f *noOpPacketFactory) NewPacket(header *rtp.Header, payload []byte, _ uint32, _ uint8) (*retainablePacket, error) { return &retainablePacket{ - onRelease: f.releasePacket, - count: 1, - header: header, - payload: payload, + onRelease: f.releasePacket, + count: 1, + header: header, + payload: payload, + sequenceNumber: header.SequenceNumber, }, nil } @@ -96,6 +124,8 @@ type retainablePacket struct { header *rtp.Header buffer *[]byte payload []byte + + sequenceNumber uint16 } func (p *retainablePacket) Header() *rtp.Header { diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/pkg/nack/send_buffer.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/pkg/nack/send_buffer.go index e8e816f61..2b3b076f5 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/pkg/nack/send_buffer.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/pkg/nack/send_buffer.go @@ -46,7 +46,7 @@ func (s *sendBuffer) add(packet *retainablePacket) { s.m.Lock() defer s.m.Unlock() - seq := packet.Header().SequenceNumber + seq := packet.sequenceNumber if !s.started { s.packets[seq%s.size] = packet s.lastAdded = seq @@ -92,7 +92,7 @@ func (s *sendBuffer) get(seq uint16) *retainablePacket { pkt := s.packets[seq%s.size] if pkt != nil { - if pkt.Header().SequenceNumber != seq { + if pkt.sequenceNumber != seq { return nil } // already released diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/pkg/report/receiver_interceptor.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/pkg/report/receiver_interceptor.go index c126f9abc..0afbd08f5 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/pkg/report/receiver_interceptor.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/pkg/report/receiver_interceptor.go @@ -100,7 +100,7 @@ func (r *ReceiverInterceptor) loop(rtcpWriter interceptor.RTCPWriter) { select { case <-ticker.C: now := r.now() - r.streams.Range(func(key, value interface{}) bool { + r.streams.Range(func(_, value interface{}) bool { if stream, ok := value.(*receiverStream); !ok { r.log.Warnf("failed to cast ReceiverInterceptor stream") } else if _, err := rtcpWriter.Write([]rtcp.Packet{stream.generateReport(now)}, interceptor.Attributes{}); err != nil { @@ -142,8 +142,8 @@ func (r *ReceiverInterceptor) BindRemoteStream(info *interceptor.StreamInfo, rea }) } -// UnbindLocalStream is called when the Stream is removed. It can be used to clean up any data related to that track. -func (r *ReceiverInterceptor) UnbindLocalStream(info *interceptor.StreamInfo) { +// UnbindRemoteStream is called when the Stream is removed. It can be used to clean up any data related to that track. +func (r *ReceiverInterceptor) UnbindRemoteStream(info *interceptor.StreamInfo) { r.streams.Delete(info.SSRC) } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/pkg/report/receiver_stream.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/pkg/report/receiver_stream.go index b899bb1b2..ebe08473d 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/pkg/report/receiver_stream.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/pkg/report/receiver_stream.go @@ -12,6 +12,13 @@ import ( "github.com/pion/rtp" ) +const ( + // packetsPerHistoryEntry represents how many packets are in the bitmask for + // each entry in the `packets` slice in the receiver stream. Because we use + // a uint64, we can keep track of 64 packets per entry. + packetsPerHistoryEntry = 64 +) + type receiverStream struct { ssrc uint32 receiverSSRC uint32 @@ -57,10 +64,10 @@ func (stream *receiverStream) processRTP(now time.Time, pktHeader *rtp.Header) { } else { // following frames stream.setReceived(pktHeader.SequenceNumber) - diff := int32(pktHeader.SequenceNumber) - int32(stream.lastSeqnum) - if diff > 0 || diff < -0x0FFF { - // overflow - if diff < -0x0FFF { + diff := pktHeader.SequenceNumber - stream.lastSeqnum + if diff > 0 && diff < (1<<15) { + // wrap around + if pktHeader.SequenceNumber < stream.lastSeqnum { stream.seqnumCycles++ } @@ -86,18 +93,18 @@ func (stream *receiverStream) processRTP(now time.Time, pktHeader *rtp.Header) { } func (stream *receiverStream) setReceived(seq uint16) { - pos := seq % stream.size - stream.packets[pos/64] |= 1 << (pos % 64) + pos := seq % (stream.size * packetsPerHistoryEntry) + stream.packets[pos/packetsPerHistoryEntry] |= 1 << (pos % packetsPerHistoryEntry) } func (stream *receiverStream) delReceived(seq uint16) { - pos := seq % stream.size - stream.packets[pos/64] &^= 1 << (pos % 64) + pos := seq % (stream.size * packetsPerHistoryEntry) + stream.packets[pos/packetsPerHistoryEntry] &^= 1 << (pos % packetsPerHistoryEntry) } func (stream *receiverStream) getReceived(seq uint16) bool { - pos := seq % stream.size - return (stream.packets[pos/64] & (1 << (pos % 64))) != 0 + pos := seq % (stream.size * packetsPerHistoryEntry) + return (stream.packets[pos/packetsPerHistoryEntry] & (1 << (pos % packetsPerHistoryEntry))) != 0 } func (stream *receiverStream) processSenderReport(now time.Time, sr *rtcp.SenderReport) { diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/pkg/report/sender_interceptor.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/pkg/report/sender_interceptor.go index 02d1c0001..1b6f4b252 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/pkg/report/sender_interceptor.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/pkg/report/sender_interceptor.go @@ -13,6 +13,9 @@ import ( "github.com/pion/rtp" ) +// TickerFactory is a factory to create new tickers +type TickerFactory func(d time.Duration) Ticker + // SenderInterceptorFactory is a interceptor.Factory for a SenderInterceptor type SenderInterceptorFactory struct { opts []SenderOption @@ -23,8 +26,11 @@ func (s *SenderInterceptorFactory) NewInterceptor(_ string) (interceptor.Interce i := &SenderInterceptor{ interval: 1 * time.Second, now: time.Now, - log: logging.NewDefaultLoggerFactory().NewLogger("sender_interceptor"), - close: make(chan struct{}), + newTicker: func(d time.Duration) Ticker { + return &timeTicker{time.NewTicker(d)} + }, + log: logging.NewDefaultLoggerFactory().NewLogger("sender_interceptor"), + close: make(chan struct{}), } for _, opt := range s.opts { @@ -44,13 +50,17 @@ func NewSenderInterceptor(opts ...SenderOption) (*SenderInterceptorFactory, erro // SenderInterceptor interceptor generates sender reports. type SenderInterceptor struct { interceptor.NoOp - interval time.Duration - now func() time.Time - streams sync.Map - log logging.LeveledLogger - m sync.Mutex - wg sync.WaitGroup - close chan struct{} + interval time.Duration + now func() time.Time + newTicker TickerFactory + streams sync.Map + log logging.LeveledLogger + m sync.Mutex + wg sync.WaitGroup + close chan struct{} + started chan struct{} + + useLatestPacket bool } func (s *SenderInterceptor) isClosed() bool { @@ -95,13 +105,18 @@ func (s *SenderInterceptor) BindRTCPWriter(writer interceptor.RTCPWriter) interc func (s *SenderInterceptor) loop(rtcpWriter interceptor.RTCPWriter) { defer s.wg.Done() - ticker := time.NewTicker(s.interval) + ticker := s.newTicker(s.interval) defer ticker.Stop() + if s.started != nil { + // This lets us synchronize in tests to know whether the loop has begun or not. + // It only happens if started was initialized, which should not occur in non-tests. + close(s.started) + } for { select { - case <-ticker.C: + case <-ticker.Ch(): now := s.now() - s.streams.Range(func(key, value interface{}) bool { + s.streams.Range(func(_, value interface{}) bool { if stream, ok := value.(*senderStream); !ok { s.log.Warnf("failed to cast SenderInterceptor stream") } else if _, err := rtcpWriter.Write([]rtcp.Packet{stream.generateReport(now)}, interceptor.Attributes{}); err != nil { @@ -120,7 +135,7 @@ func (s *SenderInterceptor) loop(rtcpWriter interceptor.RTCPWriter) { // BindLocalStream lets you modify any outgoing RTP packets. It is called once for per LocalStream. The returned method // will be called once per rtp packet. func (s *SenderInterceptor) BindLocalStream(info *interceptor.StreamInfo, writer interceptor.RTPWriter) interceptor.RTPWriter { - stream := newSenderStream(info.SSRC, info.ClockRate) + stream := newSenderStream(info.SSRC, info.ClockRate, s.useLatestPacket) s.streams.Store(info.SSRC, stream) return interceptor.RTPWriterFunc(func(header *rtp.Header, payload []byte, a interceptor.Attributes) (int, error) { @@ -129,3 +144,8 @@ func (s *SenderInterceptor) BindLocalStream(info *interceptor.StreamInfo, writer return writer.Write(header, payload, a) }) } + +// UnbindLocalStream is called when the Stream is removed. It can be used to clean up any data related to that track. +func (s *SenderInterceptor) UnbindLocalStream(info *interceptor.StreamInfo) { + s.streams.Delete(info.SSRC) +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/pkg/report/sender_option.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/pkg/report/sender_option.go index 6932e1c0a..1e489b0b3 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/pkg/report/sender_option.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/pkg/report/sender_option.go @@ -35,3 +35,29 @@ func SenderNow(f func() time.Time) SenderOption { return nil } } + +// SenderTicker sets an alternative for the time.NewTicker function. +func SenderTicker(f TickerFactory) SenderOption { + return func(r *SenderInterceptor) error { + r.newTicker = f + return nil + } +} + +// SenderUseLatestPacket sets the interceptor to always use the latest packet, even +// if it appears to be out-of-order. +func SenderUseLatestPacket() SenderOption { + return func(r *SenderInterceptor) error { + r.useLatestPacket = true + return nil + } +} + +// enableStartTracking is used by tests to synchronize whether the loop() has begun +// and it's safe to start sending ticks to the ticker. +func enableStartTracking(startedCh chan struct{}) SenderOption { + return func(r *SenderInterceptor) error { + r.started = startedCh + return nil + } +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/pkg/report/sender_stream.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/pkg/report/sender_stream.go index 29d14da41..44658e246 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/pkg/report/sender_stream.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/pkg/report/sender_stream.go @@ -17,17 +17,21 @@ type senderStream struct { clockRate float64 m sync.Mutex + useLatestPacket bool + // data from rtp packets lastRTPTimeRTP uint32 lastRTPTimeTime time.Time + lastRTPSN uint16 packetCount uint32 octetCount uint32 } -func newSenderStream(ssrc uint32, clockRate uint32) *senderStream { +func newSenderStream(ssrc uint32, clockRate uint32, useLatestPacket bool) *senderStream { return &senderStream{ - ssrc: ssrc, - clockRate: float64(clockRate), + ssrc: ssrc, + clockRate: float64(clockRate), + useLatestPacket: useLatestPacket, } } @@ -35,9 +39,13 @@ func (stream *senderStream) processRTP(now time.Time, header *rtp.Header, payloa stream.m.Lock() defer stream.m.Unlock() - // always update time to minimize errors - stream.lastRTPTimeRTP = header.Timestamp - stream.lastRTPTimeTime = now + diff := header.SequenceNumber - stream.lastRTPSN + if stream.useLatestPacket || stream.packetCount == 0 || (diff > 0 && diff < (1<<15)) { + // Told to consider every packet, or this was the first packet, or it's in-order + stream.lastRTPSN = header.SequenceNumber + stream.lastRTPTimeRTP = header.Timestamp + stream.lastRTPTimeTime = now + } stream.packetCount++ stream.octetCount += uint32(len(payload)) diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/pkg/report/ticker.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/pkg/report/ticker.go new file mode 100644 index 000000000..59a8c6c50 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/pkg/report/ticker.go @@ -0,0 +1,20 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + +package report + +import "time" + +// Ticker is an interface for *time.Ticker for use with the SenderTicker option. +type Ticker interface { + Ch() <-chan time.Time + Stop() +} + +type timeTicker struct { + *time.Ticker +} + +func (t *timeTicker) Ch() <-chan time.Time { + return t.C +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/pkg/rfc8888/interceptor.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/pkg/rfc8888/interceptor.go new file mode 100644 index 000000000..efe2df29c --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/pkg/rfc8888/interceptor.go @@ -0,0 +1,182 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + +// Package rfc8888 provides an interceptor that generates congestion control +// feedback reports as defined by RFC 8888. +package rfc8888 + +import ( + "sync" + "time" + + "github.com/pion/interceptor" + "github.com/pion/logging" + "github.com/pion/rtcp" +) + +// TickerFactory is a factory to create new tickers +type TickerFactory func(d time.Duration) ticker + +// SenderInterceptorFactory is a interceptor.Factory for a SenderInterceptor +type SenderInterceptorFactory struct { + opts []Option +} + +// NewInterceptor constructs a new SenderInterceptor +func (s *SenderInterceptorFactory) NewInterceptor(_ string) (interceptor.Interceptor, error) { + i := &SenderInterceptor{ + NoOp: interceptor.NoOp{}, + log: logging.NewDefaultLoggerFactory().NewLogger("rfc8888_interceptor"), + lock: sync.Mutex{}, + wg: sync.WaitGroup{}, + recorder: NewRecorder(), + interval: 100 * time.Millisecond, + maxReportSize: 1200, + packetChan: make(chan packet), + newTicker: func(d time.Duration) ticker { + return &timeTicker{time.NewTicker(d)} + }, + now: time.Now, + close: make(chan struct{}), + } + for _, opt := range s.opts { + err := opt(i) + if err != nil { + return nil, err + } + } + return i, nil +} + +// NewSenderInterceptor returns a new SenderInterceptorFactory configured with the given options. +func NewSenderInterceptor(opts ...Option) (*SenderInterceptorFactory, error) { + return &SenderInterceptorFactory{opts: opts}, nil +} + +// SenderInterceptor sends congestion control feedback as specified in RFC 8888. +type SenderInterceptor struct { + interceptor.NoOp + log logging.LeveledLogger + lock sync.Mutex + wg sync.WaitGroup + recorder *Recorder + interval time.Duration + maxReportSize int64 + packetChan chan packet + newTicker TickerFactory + now func() time.Time + close chan struct{} +} + +type packet struct { + arrival time.Time + ssrc uint32 + sequenceNumber uint16 + ecn uint8 +} + +// BindRTCPWriter lets you modify any outgoing RTCP packets. It is called once per PeerConnection. The returned method +// will be called once per packet batch. +func (s *SenderInterceptor) BindRTCPWriter(writer interceptor.RTCPWriter) interceptor.RTCPWriter { + s.lock.Lock() + defer s.lock.Unlock() + + if s.isClosed() { + return writer + } + + s.wg.Add(1) + go s.loop(writer) + + return writer +} + +// BindRemoteStream lets you modify any incoming RTP packets. It is called once for per RemoteStream. The returned method +// will be called once per rtp packet. +func (s *SenderInterceptor) BindRemoteStream(_ *interceptor.StreamInfo, reader interceptor.RTPReader) interceptor.RTPReader { + return interceptor.RTPReaderFunc(func(b []byte, a interceptor.Attributes) (int, interceptor.Attributes, error) { + i, attr, err := reader.Read(b, a) + if err != nil { + return 0, nil, err + } + + if attr == nil { + attr = make(interceptor.Attributes) + } + header, err := attr.GetRTPHeader(b[:i]) + if err != nil { + return 0, nil, err + } + + p := packet{ + arrival: s.now(), + ssrc: header.SSRC, + sequenceNumber: header.SequenceNumber, + ecn: 0, // ECN is not supported (yet). + } + s.packetChan <- p + return i, attr, nil + }) +} + +// Close closes the interceptor. +func (s *SenderInterceptor) Close() error { + s.log.Trace("close") + defer s.wg.Wait() + + if !s.isClosed() { + close(s.close) + } + + return nil +} + +func (s *SenderInterceptor) isClosed() bool { + select { + case <-s.close: + return true + default: + return false + } +} + +func (s *SenderInterceptor) loop(writer interceptor.RTCPWriter) { + defer s.wg.Done() + + select { + case <-s.close: + return + case pkt := <-s.packetChan: + s.log.Tracef("got first packet: %v", pkt) + s.recorder.AddPacket(pkt.arrival, pkt.ssrc, pkt.sequenceNumber, pkt.ecn) + } + + s.log.Trace("start loop") + t := s.newTicker(s.interval) + for { + select { + case <-s.close: + t.Stop() + return + + case pkt := <-s.packetChan: + s.log.Tracef("got packet: %v", pkt) + s.recorder.AddPacket(pkt.arrival, pkt.ssrc, pkt.sequenceNumber, pkt.ecn) + + case now := <-t.Ch(): + s.log.Tracef("report triggered at %v", now) + if writer == nil { + s.log.Trace("no writer added, continue") + continue + } + pkts := s.recorder.BuildReport(now, int(s.maxReportSize)) + if pkts == nil { + continue + } + s.log.Tracef("got report: %v", pkts) + if _, err := writer.Write([]rtcp.Packet{pkts}, nil); err != nil { + s.log.Error(err.Error()) + } + } + } +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/pkg/rfc8888/option.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/pkg/rfc8888/option.go new file mode 100644 index 000000000..1214868bf --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/pkg/rfc8888/option.go @@ -0,0 +1,33 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + +package rfc8888 + +import "time" + +// An Option is a function that can be used to configure a SenderInterceptor +type Option func(*SenderInterceptor) error + +// SenderTicker sets an alternative for time.Ticker. +func SenderTicker(f TickerFactory) Option { + return func(i *SenderInterceptor) error { + i.newTicker = f + return nil + } +} + +// SenderNow sets an alternative for the time.Now function. +func SenderNow(f func() time.Time) Option { + return func(i *SenderInterceptor) error { + i.now = f + return nil + } +} + +// SendInterval sets the feedback send interval for the interceptor +func SendInterval(interval time.Duration) Option { + return func(s *SenderInterceptor) error { + s.interval = interval + return nil + } +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/pkg/rfc8888/recorder.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/pkg/rfc8888/recorder.go new file mode 100644 index 000000000..4423df1e3 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/pkg/rfc8888/recorder.go @@ -0,0 +1,78 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + +package rfc8888 + +import ( + "time" + + "github.com/pion/rtcp" +) + +type packetReport struct { + arrivalTime time.Time + ecn uint8 +} + +// Recorder records incoming RTP packets and their arrival times. Recorder can +// be used to create feedback reports as defined by RFC 8888. +type Recorder struct { + ssrc uint32 + streams map[uint32]*streamLog +} + +// NewRecorder creates a new Recorder +func NewRecorder() *Recorder { + return &Recorder{ + streams: map[uint32]*streamLog{}, + } +} + +// AddPacket writes a packet to the underlying stream. +func (r *Recorder) AddPacket(ts time.Time, ssrc uint32, seq uint16, ecn uint8) { + stream, ok := r.streams[ssrc] + if !ok { + stream = newStreamLog(ssrc) + r.streams[ssrc] = stream + } + stream.add(ts, seq, ecn) +} + +// BuildReport creates a new rtcp.CCFeedbackReport containing all packets that +// were added by AddPacket and missing packets. +func (r *Recorder) BuildReport(now time.Time, maxSize int) *rtcp.CCFeedbackReport { + report := &rtcp.CCFeedbackReport{ + SenderSSRC: r.ssrc, + ReportBlocks: []rtcp.CCFeedbackReportBlock{}, + ReportTimestamp: ntpTime32(now), + } + + maxReportBlocks := (maxSize - 12 - (8 * len(r.streams))) / 2 + var maxReportBlocksPerStream int + if len(r.streams) > 1 { + maxReportBlocksPerStream = maxReportBlocks / (len(r.streams) - 1) + } else { + maxReportBlocksPerStream = maxReportBlocks + } + + for i, log := range r.streams { + if len(r.streams) > 1 && int(i) == len(r.streams)-1 { + maxReportBlocksPerStream = maxReportBlocks % len(r.streams) + } + block := log.metricsAfter(now, int64(maxReportBlocksPerStream)) + report.ReportBlocks = append(report.ReportBlocks, block) + } + + return report +} + +func ntpTime32(t time.Time) uint32 { + // seconds since 1st January 1900 + s := (float64(t.UnixNano()) / 1000000000.0) + 2208988800 + + integerPart := uint32(s) + fractionalPart := uint32((s - float64(integerPart)) * 0xFFFFFFFF) + + // higher 32 bits are the integer part, lower 32 bits are the fractional part + return uint32(((uint64(integerPart)<<32 | uint64(fractionalPart)) >> 16) & 0xFFFFFFFF) +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/pkg/rfc8888/stream_log.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/pkg/rfc8888/stream_log.go new file mode 100644 index 000000000..8dfb14fc9 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/pkg/rfc8888/stream_log.go @@ -0,0 +1,110 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + +package rfc8888 + +import ( + "time" + + "github.com/pion/rtcp" +) + +const maxReportsPerReportBlock = 16384 + +type streamLog struct { + ssrc uint32 + sequence unwrapper + init bool + nextSequenceNumberToReport int64 // next to report + lastSequenceNumberReceived int64 // highest received + log map[int64]*packetReport +} + +func newStreamLog(ssrc uint32) *streamLog { + return &streamLog{ + ssrc: ssrc, + sequence: unwrapper{}, + init: false, + nextSequenceNumberToReport: 0, + lastSequenceNumberReceived: 0, + log: map[int64]*packetReport{}, + } +} + +func (l *streamLog) add(ts time.Time, sequenceNumber uint16, ecn uint8) { + unwrappedSequenceNumber := l.sequence.unwrap(sequenceNumber) + if !l.init { + l.init = true + l.nextSequenceNumberToReport = unwrappedSequenceNumber + } + l.log[unwrappedSequenceNumber] = &packetReport{ + arrivalTime: ts, + ecn: ecn, + } + if l.lastSequenceNumberReceived < unwrappedSequenceNumber { + l.lastSequenceNumberReceived = unwrappedSequenceNumber + } +} + +// metricsAfter iterates over all packets order of their sequence number. +// Packets are removed until the first loss is detected. +func (l *streamLog) metricsAfter(reference time.Time, maxReportBlocks int64) rtcp.CCFeedbackReportBlock { + if len(l.log) == 0 { + return rtcp.CCFeedbackReportBlock{ + MediaSSRC: l.ssrc, + BeginSequence: uint16(l.nextSequenceNumberToReport), + MetricBlocks: []rtcp.CCFeedbackMetricBlock{}, + } + } + numReports := l.lastSequenceNumberReceived - l.nextSequenceNumberToReport + 1 + if numReports > maxReportBlocks { + numReports = maxReportBlocks + l.nextSequenceNumberToReport = l.lastSequenceNumberReceived - maxReportBlocks + 1 + } + metricBlocks := make([]rtcp.CCFeedbackMetricBlock, numReports) + offset := l.nextSequenceNumberToReport + lastReceived := l.nextSequenceNumberToReport + gapDetected := false + for i := offset; i <= l.lastSequenceNumberReceived; i++ { + received := false + ecn := uint8(0) + ato := uint16(0) + if report, ok := l.log[i]; ok { + received = true + ecn = report.ecn + ato = getArrivalTimeOffset(reference, report.arrivalTime) + } + metricBlocks[i-offset] = rtcp.CCFeedbackMetricBlock{ + Received: received, + ECN: rtcp.ECN(ecn), + ArrivalTimeOffset: ato, + } + + if !gapDetected { + if received && i == l.nextSequenceNumberToReport { + delete(l.log, i) + l.nextSequenceNumberToReport++ + lastReceived = i + } + if i > lastReceived+1 { + gapDetected = true + } + } + } + return rtcp.CCFeedbackReportBlock{ + MediaSSRC: l.ssrc, + BeginSequence: uint16(offset), + MetricBlocks: metricBlocks, + } +} + +func getArrivalTimeOffset(base time.Time, arrival time.Time) uint16 { + if base.Before(arrival) { + return 0x1FFF + } + ato := uint16(base.Sub(arrival).Seconds() * 1024.0) + if ato > 0x1FFD { + return 0x1FFE + } + return ato +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/pkg/rfc8888/ticker.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/pkg/rfc8888/ticker.go new file mode 100644 index 000000000..571b28e0b --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/pkg/rfc8888/ticker.go @@ -0,0 +1,19 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + +package rfc8888 + +import "time" + +type ticker interface { + Ch() <-chan time.Time + Stop() +} + +type timeTicker struct { + *time.Ticker +} + +func (t *timeTicker) Ch() <-chan time.Time { + return t.C +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/pkg/rfc8888/unwrapper.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/pkg/rfc8888/unwrapper.go new file mode 100644 index 000000000..f15f33e6e --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/pkg/rfc8888/unwrapper.go @@ -0,0 +1,42 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + +package rfc8888 + +const ( + maxSequenceNumberPlusOne = int64(65536) + breakpoint = 32768 // half of max uint16 +) + +type unwrapper struct { + init bool + lastUnwrapped int64 +} + +func isNewer(value, previous uint16) bool { + if value-previous == breakpoint { + return value > previous + } + return value != previous && (value-previous) < breakpoint +} + +func (u *unwrapper) unwrap(i uint16) int64 { + if !u.init { + u.init = true + u.lastUnwrapped = int64(i) + return u.lastUnwrapped + } + + lastWrapped := uint16(u.lastUnwrapped) + delta := int64(i - lastWrapped) + if isNewer(i, lastWrapped) { + if delta < 0 { + delta += maxSequenceNumberPlusOne + } + } else if delta > 0 && u.lastUnwrapped+delta-maxSequenceNumberPlusOne >= 0 { + delta -= maxSequenceNumberPlusOne + } + + u.lastUnwrapped += delta + return u.lastUnwrapped +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/pkg/twcc/arrival_time_map.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/pkg/twcc/arrival_time_map.go new file mode 100644 index 000000000..d3e2a8af3 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/pkg/twcc/arrival_time_map.go @@ -0,0 +1,192 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + +package twcc + +const ( + minCapacity = 128 + maxNumberOfPackets = 1 << 15 +) + +// packetArrivalTimeMap is adapted from Chrome's implementation of TWCC, and keeps track +// of the arrival times of packets. It is used by the TWCC interceptor to build feedback +// packets. +// See https://source.chromium.org/chromium/chromium/src/+/refs/heads/main:third_party/webrtc/modules/remote_bitrate_estimator/packet_arrival_map.h;drc=b5cd13bb6d5d157a5fbe3628b2dd1c1e106203c6 +type packetArrivalTimeMap struct { + // arrivalTimes is a circular buffer, where the packet with sequence number sn is stored + // in slot sn % len(arrivalTimes) + arrivalTimes []int64 + + // The unwrapped sequence numbers for the range of valid sequence numbers in arrivalTimes. + // beginSequenceNumber is inclusive, and endSequenceNumber is exclusive. + beginSequenceNumber, endSequenceNumber int64 +} + +// AddPacket records the fact that the packet with sequence number sequenceNumber arrived +// at arrivalTime. +func (m *packetArrivalTimeMap) AddPacket(sequenceNumber int64, arrivalTime int64) { + if m.arrivalTimes == nil { + // First packet + m.reallocate(minCapacity) + m.beginSequenceNumber = sequenceNumber + m.endSequenceNumber = sequenceNumber + 1 + m.arrivalTimes[m.index(sequenceNumber)] = arrivalTime + return + } + + if sequenceNumber >= m.beginSequenceNumber && sequenceNumber < m.endSequenceNumber { + // The packet is within the buffer, no need to resize. + m.arrivalTimes[m.index(sequenceNumber)] = arrivalTime + return + } + + if sequenceNumber < m.beginSequenceNumber { + // The packet goes before the current buffer. Expand to add packet, + // but only if it fits within the maximum number of packets. + newSize := int(m.endSequenceNumber - sequenceNumber) + if newSize > maxNumberOfPackets { + // Don't expand the buffer back for this packet, as it would remove newer received + // packets. + return + } + m.adjustToSize(newSize) + m.arrivalTimes[m.index(sequenceNumber)] = arrivalTime + m.setNotReceived(sequenceNumber+1, m.beginSequenceNumber) + m.beginSequenceNumber = sequenceNumber + return + } + + // The packet goes after the buffer. + newEndSequenceNumber := sequenceNumber + 1 + + if newEndSequenceNumber >= m.endSequenceNumber+maxNumberOfPackets { + // All old packets have to be removed. + m.beginSequenceNumber = sequenceNumber + m.endSequenceNumber = newEndSequenceNumber + m.arrivalTimes[m.index(sequenceNumber)] = arrivalTime + return + } + + if m.beginSequenceNumber < newEndSequenceNumber-maxNumberOfPackets { + // Remove oldest entries. + m.beginSequenceNumber = newEndSequenceNumber - maxNumberOfPackets + } + + m.adjustToSize(int(newEndSequenceNumber - m.beginSequenceNumber)) + + // Packets can be received out of order. If this isn't the next expected packet, + // add enough placeholders to fill the gap. + m.setNotReceived(m.endSequenceNumber, sequenceNumber) + m.endSequenceNumber = newEndSequenceNumber + m.arrivalTimes[m.index(sequenceNumber)] = arrivalTime +} + +func (m *packetArrivalTimeMap) setNotReceived(startInclusive, endExclusive int64) { + for sn := startInclusive; sn < endExclusive; sn++ { + m.arrivalTimes[m.index(sn)] = -1 + } +} + +// BeginSequenceNumber returns the first valid sequence number in the map. +func (m *packetArrivalTimeMap) BeginSequenceNumber() int64 { + return m.beginSequenceNumber +} + +// EndSequenceNumber returns the first sequence number after the last valid sequence number in the map. +func (m *packetArrivalTimeMap) EndSequenceNumber() int64 { + return m.endSequenceNumber +} + +// FindNextAtOrAfter returns the sequence number and timestamp of the first received packet that has a sequence number +// greator or equal to sequenceNumber. +func (m *packetArrivalTimeMap) FindNextAtOrAfter(sequenceNumber int64) (foundSequenceNumber int64, arrivalTime int64, ok bool) { + for sequenceNumber = m.Clamp(sequenceNumber); sequenceNumber < m.endSequenceNumber; sequenceNumber++ { + if t := m.get(sequenceNumber); t >= 0 { + return sequenceNumber, t, true + } + } + return -1, -1, false +} + +// EraseTo erases all elements from the beginning of the map until sequenceNumber. +func (m *packetArrivalTimeMap) EraseTo(sequenceNumber int64) { + if sequenceNumber < m.beginSequenceNumber { + return + } + if sequenceNumber >= m.endSequenceNumber { + // Erase all. + m.beginSequenceNumber = m.endSequenceNumber + return + } + // Remove some + m.beginSequenceNumber = sequenceNumber + m.adjustToSize(int(m.endSequenceNumber - m.beginSequenceNumber)) +} + +// RemoveOldPackets removes packets from the beginning of the map as long as they are before +// sequenceNumber and with an age older than arrivalTimeLimit. +func (m *packetArrivalTimeMap) RemoveOldPackets(sequenceNumber int64, arrivalTimeLimit int64) { + checkTo := min64(sequenceNumber, m.endSequenceNumber) + for m.beginSequenceNumber < checkTo && m.get(m.beginSequenceNumber) <= arrivalTimeLimit { + m.beginSequenceNumber++ + } + m.adjustToSize(int(m.endSequenceNumber - m.beginSequenceNumber)) +} + +// HasReceived returns whether a packet with the sequence number has been received. +func (m *packetArrivalTimeMap) HasReceived(sequenceNumber int64) bool { + return m.get(sequenceNumber) >= 0 +} + +// Clamp returns sequenceNumber clamped to [beginSequenceNumber, endSequenceNumber] +func (m *packetArrivalTimeMap) Clamp(sequenceNumber int64) int64 { + if sequenceNumber < m.beginSequenceNumber { + return m.beginSequenceNumber + } + if m.endSequenceNumber < sequenceNumber { + return m.endSequenceNumber + } + return sequenceNumber +} + +func (m *packetArrivalTimeMap) get(sequenceNumber int64) int64 { + if sequenceNumber < m.beginSequenceNumber || sequenceNumber >= m.endSequenceNumber { + return -1 + } + return m.arrivalTimes[m.index(sequenceNumber)] +} + +func (m *packetArrivalTimeMap) index(sequenceNumber int64) int { + // Sequence number might be negative, and we always guarantee that arrivalTimes + // length is a power of 2, so it's easier to use "&" instead of "%" + return int(sequenceNumber & int64(m.capacity()-1)) +} + +func (m *packetArrivalTimeMap) adjustToSize(newSize int) { + if newSize > m.capacity() { + newCapacity := m.capacity() + for newCapacity < newSize { + newCapacity *= 2 + } + m.reallocate(newCapacity) + } + if m.capacity() > maxInt(minCapacity, newSize*4) { + newCapacity := m.capacity() + for newCapacity >= 2*maxInt(newSize, minCapacity) { + newCapacity /= 2 + } + m.reallocate(newCapacity) + } +} + +func (m *packetArrivalTimeMap) capacity() int { + return len(m.arrivalTimes) +} + +func (m *packetArrivalTimeMap) reallocate(newCapacity int) { + newBuffer := make([]int64, newCapacity) + for sn := m.beginSequenceNumber; sn < m.endSequenceNumber; sn++ { + newBuffer[int(sn&(int64(newCapacity-1)))] = m.get(sn) + } + m.arrivalTimes = newBuffer +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/pkg/twcc/sender_interceptor.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/pkg/twcc/sender_interceptor.go index 8706e4518..d7906fc68 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/pkg/twcc/sender_interceptor.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/pkg/twcc/sender_interceptor.go @@ -196,7 +196,7 @@ func (s *SenderInterceptor) loop(w interceptor.RTCPWriter) { case <-ticker.C: // build and send twcc pkts := s.recorder.BuildFeedbackPacket() - if pkts == nil { + if len(pkts) == 0 { continue } if _, err := w.Write(pkts, nil); err != nil { diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/pkg/twcc/twcc.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/pkg/twcc/twcc.go index 235f1f11c..6464c77bc 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/pkg/twcc/twcc.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/pkg/twcc/twcc.go @@ -7,94 +7,157 @@ package twcc import ( "math" + "github.com/pion/interceptor/internal/sequencenumber" "github.com/pion/rtcp" ) -type pktInfo struct { - sequenceNumber uint32 - arrivalTime int64 -} +const ( + packetWindowMicroseconds = 500_000 + maxMissingSequenceNumbers = 0x7FFE +) // Recorder records incoming RTP packets and their delays and creates // transport wide congestion control feedback reports as specified in // https://datatracker.ietf.org/doc/html/draft-holmer-rmcat-transport-wide-cc-extensions-01 type Recorder struct { - receivedPackets []pktInfo + arrivalTimeMap packetArrivalTimeMap - cycles uint32 - lastSequenceNumber uint16 + sequenceUnwrapper sequencenumber.Unwrapper + + // startSequenceNumber is the first sequence number that will be included in the the + // next feedback packet. + startSequenceNumber *int64 senderSSRC uint32 mediaSSRC uint32 fbPktCnt uint8 + + packetsHeld int } // NewRecorder creates a new Recorder which uses the given senderSSRC in the created // feedback packets. func NewRecorder(senderSSRC uint32) *Recorder { return &Recorder{ - receivedPackets: []pktInfo{}, - senderSSRC: senderSSRC, + senderSSRC: senderSSRC, } } // Record marks a packet with mediaSSRC and a transport wide sequence number sequenceNumber as received at arrivalTime. func (r *Recorder) Record(mediaSSRC uint32, sequenceNumber uint16, arrivalTime int64) { r.mediaSSRC = mediaSSRC - if sequenceNumber < 0x0fff && (r.lastSequenceNumber&0xffff) > 0xf000 { - r.cycles += 1 << 16 + + // "Unwrap" the sequence number to get a monotonically increasing sequence number that + // won't wrap around after math.MaxUint16. + unwrappedSN := r.sequenceUnwrapper.Unwrap(sequenceNumber) + r.maybeCullOldPackets(unwrappedSN, arrivalTime) + if r.startSequenceNumber == nil || unwrappedSN < *r.startSequenceNumber { + r.startSequenceNumber = &unwrappedSN + } + + // We are only interested in the first time a packet is received. + if r.arrivalTimeMap.HasReceived(unwrappedSN) { + return + } + + r.arrivalTimeMap.AddPacket(unwrappedSN, arrivalTime) + r.packetsHeld++ + + // Limit the range of sequence numbers to send feedback for. + if *r.startSequenceNumber < r.arrivalTimeMap.BeginSequenceNumber() { + sn := r.arrivalTimeMap.BeginSequenceNumber() + r.startSequenceNumber = &sn } - r.receivedPackets = insertSorted(r.receivedPackets, pktInfo{ - sequenceNumber: r.cycles | uint32(sequenceNumber), - arrivalTime: arrivalTime, - }) - r.lastSequenceNumber = sequenceNumber } -func insertSorted(list []pktInfo, element pktInfo) []pktInfo { - if len(list) == 0 { - return append(list, element) +func (r *Recorder) maybeCullOldPackets(sequenceNumber int64, arrivalTime int64) { + if r.startSequenceNumber != nil && *r.startSequenceNumber >= r.arrivalTimeMap.EndSequenceNumber() && arrivalTime >= packetWindowMicroseconds { + r.arrivalTimeMap.RemoveOldPackets(sequenceNumber, arrivalTime-packetWindowMicroseconds) } - for i := len(list) - 1; i >= 0; i-- { - if list[i].sequenceNumber < element.sequenceNumber { - list = append(list, pktInfo{}) - copy(list[i+2:], list[i+1:]) - list[i+1] = element - return list - } - if list[i].sequenceNumber == element.sequenceNumber { - list[i] = element - return list - } - } - // element.sequenceNumber is between 0 and first ever received sequenceNumber - return append([]pktInfo{element}, list...) +} + +// PacketsHeld returns the number of received packets currently held by the recorder +func (r *Recorder) PacketsHeld() int { + return r.packetsHeld } // BuildFeedbackPacket creates a new RTCP packet containing a TWCC feedback report. func (r *Recorder) BuildFeedbackPacket() []rtcp.Packet { - if len(r.receivedPackets) < 2 { + if r.startSequenceNumber == nil { return nil } - feedback := newFeedback(r.senderSSRC, r.mediaSSRC, r.fbPktCnt) - r.fbPktCnt++ - feedback.setBase(uint16(r.receivedPackets[0].sequenceNumber&0xffff), r.receivedPackets[0].arrivalTime) - - var pkts []rtcp.Packet - for _, pkt := range r.receivedPackets { - ok := feedback.addReceived(uint16(pkt.sequenceNumber&0xffff), pkt.arrivalTime) - if !ok { - pkts = append(pkts, feedback.getRTCP()) - feedback = newFeedback(r.senderSSRC, r.mediaSSRC, r.fbPktCnt) - r.fbPktCnt++ - feedback.addReceived(uint16(pkt.sequenceNumber&0xffff), pkt.arrivalTime) + endSN := r.arrivalTimeMap.EndSequenceNumber() + var feedbacks []rtcp.Packet + for *r.startSequenceNumber < endSN { + feedback := r.maybeBuildFeedbackPacket(*r.startSequenceNumber, endSN) + if feedback == nil { + break } - } - r.receivedPackets = []pktInfo{} - pkts = append(pkts, feedback.getRTCP()) + feedbacks = append(feedbacks, feedback.getRTCP()) - return pkts + // NOTE: we don't erase packets from the history in case they need to be resent + // after a reordering. They will be removed instead in Record when they get too + // old. + } + r.packetsHeld = 0 + return feedbacks +} + +// maybeBuildFeedbackPacket builds a feedback packet starting from startSN (inclusive) until +// endSN (exclusive). +func (r *Recorder) maybeBuildFeedbackPacket(beginSeqNumInclusive, endSeqNumExclusive int64) *feedback { + // NOTE: The logic of this method is inspired by the implementation in Chrome. + // See https://source.chromium.org/chromium/chromium/src/+/refs/heads/main:third_party/webrtc/modules/remote_bitrate_estimator/remote_estimator_proxy.cc;l=276;drc=b5cd13bb6d5d157a5fbe3628b2dd1c1e106203c6 + startSNInclusive, endSNExclusive := r.arrivalTimeMap.Clamp(beginSeqNumInclusive), r.arrivalTimeMap.Clamp(endSeqNumExclusive) + + // Create feedback on demand, as we don't yet know if there are packets in the range that have been + // received. + var fb *feedback + + nextSequenceNumber := beginSeqNumInclusive + + for seq := startSNInclusive; seq < endSNExclusive; seq++ { + foundSeq, arrivalTime, ok := r.arrivalTimeMap.FindNextAtOrAfter(seq) + seq = foundSeq + if !ok || seq >= endSNExclusive { + break + } + + if fb == nil { + fb = newFeedback(r.senderSSRC, r.mediaSSRC, r.fbPktCnt) + r.fbPktCnt++ + + // It should be possible to add seq to this new packet. + // If the difference between seq and beginSeqNumInclusive is too large, discard + // reporting too old missing packets. + baseSequenceNumber := max64(beginSeqNumInclusive, seq-maxMissingSequenceNumbers) + + // baseSequenceNumber is the expected first sequence number. This is known, + // but we may not have actually received it, so the base time should be the time + // of the first received packet in the feedback. + fb.setBase(uint16(baseSequenceNumber), arrivalTime) + + if !fb.addReceived(uint16(seq), arrivalTime) { + // Could not add a single received packet to the feedback. + // This is unexpected to actually occur, but if it does, we'll + // try again after skipping any missing packets. + // NOTE: It's fine that we already incremented fbPktCnt, as in essence + // we did actually "skip" a feedback (and this matches Chrome's behavior). + r.startSequenceNumber = &seq + return nil + } + } else if !fb.addReceived(uint16(seq), arrivalTime) { + // Could not add timestamp. Packet may be full. Return + // and try again with a fresh packet. + break + } + + nextSequenceNumber = seq + 1 + } + + r.startSequenceNumber = &nextSequenceNumber + return fb } type feedback struct { @@ -154,10 +217,16 @@ func (f *feedback) getRTCP() *rtcp.TransportLayerCC { func (f *feedback) addReceived(sequenceNumber uint16, timestampUS int64) bool { deltaUS := timestampUS - f.lastTimestampUS - delta250US := deltaUS / 250 + var delta250US int64 + if deltaUS >= 0 { + delta250US = (deltaUS + rtcp.TypeTCCDeltaScaleFactor/2) / rtcp.TypeTCCDeltaScaleFactor + } else { + delta250US = (deltaUS - rtcp.TypeTCCDeltaScaleFactor/2) / rtcp.TypeTCCDeltaScaleFactor + } if delta250US < math.MinInt16 || delta250US > math.MaxInt16 { // delta doesn't fit into 16 bit, need to create new packet return false } + deltaUSRounded := delta250US * rtcp.TypeTCCDeltaScaleFactor for ; f.nextSequenceNumber != sequenceNumber; f.nextSequenceNumber++ { if !f.lastChunk.canAdd(rtcp.TypeTCCPacketNotReceived) { @@ -183,9 +252,9 @@ func (f *feedback) addReceived(sequenceNumber uint16, timestampUS int64) bool { f.lastChunk.add(recvDelta) f.deltas = append(f.deltas, &rtcp.RecvDelta{ Type: recvDelta, - Delta: deltaUS, + Delta: deltaUSRounded, }) - f.lastTimestampUS = timestampUS + f.lastTimestampUS += deltaUSRounded f.sequenceNumberCount++ f.nextSequenceNumber++ return true @@ -238,7 +307,7 @@ func (c *chunk) encode() rtcp.PacketStatusChunk { } } - minCap := min(maxTwoBitCap, len(c.deltas)) + minCap := minInt(maxTwoBitCap, len(c.deltas)) svc := &rtcp.StatusVectorChunk{ SymbolSize: rtcp.TypeTCCSymbolSizeTwoBit, SymbolList: c.deltas[:minCap], @@ -268,7 +337,28 @@ func (c *chunk) reset() { c.hasDifferentTypes = false } -func min(a, b int) int { +func maxInt(a, b int) int { + if a > b { + return a + } + return b +} + +func minInt(a, b int) int { + if a < b { + return a + } + return b +} + +func max64(a, b int64) int64 { + if a > b { + return a + } + return b +} + +func min64(a, b int64) int64 { if a < b { return a } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/streaminfo.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/streaminfo.go index 4108159c5..cb261304f 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/streaminfo.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/interceptor/streaminfo.go @@ -11,16 +11,20 @@ type RTPHeaderExtension struct { // StreamInfo is the Context passed when a StreamLocal or StreamRemote has been Binded or Unbinded type StreamInfo struct { - ID string - Attributes Attributes - SSRC uint32 - PayloadType uint8 - RTPHeaderExtensions []RTPHeaderExtension - MimeType string - ClockRate uint32 - Channels uint16 - SDPFmtpLine string - RTCPFeedback []RTCPFeedback + ID string + Attributes Attributes + SSRC uint32 + SSRCRetransmission uint32 + SSRCForwardErrorCorrection uint32 + PayloadType uint8 + PayloadTypeRetransmission uint8 + PayloadTypeForwardErrorCorrection uint8 + RTPHeaderExtensions []RTPHeaderExtension + MimeType string + ClockRate uint32 + Channels uint16 + SDPFmtpLine string + RTCPFeedback []RTCPFeedback } // RTCPFeedback signals the connection to use additional RTCP packet types. diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/.gitignore b/trunk/3rdparty/srs-bench/vendor/github.com/pion/logging/.gitignore similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/.gitignore rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/logging/.gitignore diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/logging/.golangci.yml b/trunk/3rdparty/srs-bench/vendor/github.com/pion/logging/.golangci.yml index ffb0058e6..50211be0c 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/logging/.golangci.yml +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/logging/.golangci.yml @@ -1,13 +1,138 @@ +# SPDX-FileCopyrightText: 2023 The Pion community +# SPDX-License-Identifier: MIT + +run: + timeout: 5m + linters-settings: govet: - check-shadowing: true + enable: + - shadow misspell: locale: US + exhaustive: + default-signifies-exhaustive: true + gomodguard: + blocked: + modules: + - github.com/pkg/errors: + recommendations: + - errors + forbidigo: + forbid: + - ^fmt.Print(f|ln)?$ + - ^log.(Panic|Fatal|Print)(f|ln)?$ + - ^os.Exit$ + - ^panic$ + - ^print(ln)?$ + varnamelen: + max-distance: 12 + min-name-length: 2 + ignore-type-assert-ok: true + ignore-map-index-ok: true + ignore-chan-recv-ok: true + ignore-decls: + - i int + - n int + - w io.Writer + - r io.Reader + - b []byte linters: - enable-all: true + enable: + - asciicheck # Simple linter to check that your code does not contain non-ASCII identifiers + - bidichk # Checks for dangerous unicode character sequences + - bodyclose # checks whether HTTP response body is closed successfully + - containedctx # containedctx is a linter that detects struct contained context.Context field + - contextcheck # check the function whether use a non-inherited context + - cyclop # checks function and package cyclomatic complexity + - decorder # check declaration order and count of types, constants, variables and functions + - dogsled # Checks assignments with too many blank identifiers (e.g. x, _, _, _, := f()) + - dupl # Tool for code clone detection + - durationcheck # check for two durations multiplied together + - err113 # Golang linter to check the errors handling expressions + - errcheck # Errcheck is a program for checking for unchecked errors in go programs. These unchecked errors can be critical bugs in some cases + - errchkjson # Checks types passed to the json encoding functions. Reports unsupported types and optionally reports occations, where the check for the returned error can be omitted. + - errname # Checks that sentinel errors are prefixed with the `Err` and error types are suffixed with the `Error`. + - errorlint # errorlint is a linter for that can be used to find code that will cause problems with the error wrapping scheme introduced in Go 1.13. + - exhaustive # check exhaustiveness of enum switch statements + - exportloopref # checks for pointers to enclosing loop variables + - forbidigo # Forbids identifiers + - forcetypeassert # finds forced type assertions + - funlen # Tool for detection of long functions + - gci # Gci control golang package import order and make it always deterministic. + - gochecknoglobals # Checks that no globals are present in Go code + - gocognit # Computes and checks the cognitive complexity of functions + - goconst # Finds repeated strings that could be replaced by a constant + - gocritic # The most opinionated Go source code linter + - gocyclo # Computes and checks the cyclomatic complexity of functions + - godot # Check if comments end in a period + - godox # Tool for detection of FIXME, TODO and other comment keywords + - gofmt # Gofmt checks whether code was gofmt-ed. By default this tool runs with -s option to check for code simplification + - gofumpt # Gofumpt checks whether code was gofumpt-ed. + - goheader # Checks is file header matches to pattern + - goimports # Goimports does everything that gofmt does. Additionally it checks unused imports + - gomoddirectives # Manage the use of 'replace', 'retract', and 'excludes' directives in go.mod. + - goprintffuncname # Checks that printf-like functions are named with `f` at the end + - gosec # Inspects source code for security problems + - gosimple # Linter for Go source code that specializes in simplifying a code + - govet # Vet examines Go source code and reports suspicious constructs, such as Printf calls whose arguments do not align with the format string + - grouper # An analyzer to analyze expression groups. + - importas # Enforces consistent import aliases + - ineffassign # Detects when assignments to existing variables are not used + - lll # Reports long lines + - maintidx # maintidx measures the maintainability index of each function. + - makezero # Finds slice declarations with non-zero initial length + - misspell # Finds commonly misspelled English words in comments + - nakedret # Finds naked returns in functions greater than a specified function length + - nestif # Reports deeply nested if statements + - nilerr # Finds the code that returns nil even if it checks that the error is not nil. + - nilnil # Checks that there is no simultaneous return of `nil` error and an invalid value. + - nlreturn # nlreturn checks for a new line before return and branch statements to increase code clarity + - noctx # noctx finds sending http request without context.Context + - predeclared # find code that shadows one of Go's predeclared identifiers + - revive # golint replacement, finds style mistakes + - staticcheck # Staticcheck is a go vet on steroids, applying a ton of static analysis checks + - stylecheck # Stylecheck is a replacement for golint + - tagliatelle # Checks the struct tags. + - tenv # tenv is analyzer that detects using os.Setenv instead of t.Setenv since Go1.17 + - thelper # thelper detects golang test helpers without t.Helper() call and checks the consistency of test helpers + - typecheck # Like the front-end of a Go compiler, parses and type-checks Go code + - unconvert # Remove unnecessary type conversions + - unparam # Reports unused function parameters + - unused # Checks Go code for unused constants, variables, functions and types + - varnamelen # checks that the length of a variable's name matches its scope + - wastedassign # wastedassign finds wasted assignment statements + - whitespace # Tool for detection of leading and trailing whitespace + disable: + - depguard # Go linter that checks if package imports are in a list of acceptable packages + - gochecknoinits # Checks that no init functions are present in Go code + - gomodguard # Allow and block list linter for direct Go module dependencies. This is different from depguard where there are different block types for example version constraints and module recommendations. + - interfacebloat # A linter that checks length of interface. + - ireturn # Accept Interfaces, Return Concrete Types + - mnd # An analyzer to detect magic numbers + - nolintlint # Reports ill-formed or insufficient nolint directives + - paralleltest # paralleltest detects missing usage of t.Parallel() method in your Go test + - prealloc # Finds slice declarations that could potentially be preallocated + - promlinter # Check Prometheus metrics naming via promlint + - rowserrcheck # checks whether Err of rows is checked successfully + - sqlclosecheck # Checks that sql.Rows and sql.Stmt are closed. + - testpackage # linter that makes you use a separate _test package + - tparallel # tparallel detects inappropriate usage of t.Parallel() method in your Go test codes + - wrapcheck # Checks that errors returned from external packages are wrapped + - wsl # Whitespace Linter - Forces you to use empty lines! issues: exclude-use-default: false - max-per-linter: 0 - max-same-issues: 50 + exclude-dirs-use-default: false + exclude-rules: + # Allow complex tests and examples, better to be self contained + - path: (examples|main\.go|_test\.go) + linters: + - forbidigo + - gocognit + + # Allow forbidden identifiers in CLI commands + - path: cmd + linters: + - forbidigo diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/.goreleaser.yml b/trunk/3rdparty/srs-bench/vendor/github.com/pion/logging/.goreleaser.yml similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/.goreleaser.yml rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/logging/.goreleaser.yml diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/logging/.travis.yml b/trunk/3rdparty/srs-bench/vendor/github.com/pion/logging/.travis.yml deleted file mode 100644 index b96a1edb9..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/logging/.travis.yml +++ /dev/null @@ -1,19 +0,0 @@ -language: go - -go: - - "1.x" # use the latest Go release - -env: - - GO111MODULE=on - -before_script: - - curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | bash -s -- -b $GOPATH/bin v1.15.0 - -script: - - golangci-lint run ./... -# - rm -rf examples # Remove examples, no test coverage for them - - go test -coverpkg=$(go list ./... | tr '\n' ',') -coverprofile=cover.out -v -race -covermode=atomic ./... - - bash <(curl -s https://codecov.io/bash) - - bash .github/assert-contributors.sh - - bash .github/lint-disallowed-functions-in-library.sh - - bash .github/lint-commit-message.sh diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/logging/LICENSE b/trunk/3rdparty/srs-bench/vendor/github.com/pion/logging/LICENSE index ab602974d..491caf6b0 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/logging/LICENSE +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/logging/LICENSE @@ -1,21 +1,9 @@ MIT License -Copyright (c) 2018 +Copyright (c) 2023 The Pion community -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/logging/README.md b/trunk/3rdparty/srs-bench/vendor/github.com/pion/logging/README.md index c15471d61..b9824abb6 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/logging/README.md +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/logging/README.md @@ -8,8 +8,8 @@ Pion transport Slack Widget
- Build Status - GoDoc + GitHub Workflow Status + Go Reference Coverage Status Go Report Card License: MIT @@ -20,22 +20,15 @@ The library is used as a part of our WebRTC implementation. Please refer to that [roadmap](https://github.com/pion/webrtc/issues/9) to track our major milestones. ### Community -Pion has an active community on the [Golang Slack](https://invite.slack.golangbridge.org/). Sign up and join the **#pion** channel for discussions and support. You can also use [Pion mailing list](https://groups.google.com/forum/#!forum/pion). +Pion has an active community on the [Slack](https://pion.ly/slack). + +Follow the [Pion Twitter](https://twitter.com/_pion) for project updates and important WebRTC news. We are always looking to support **your projects**. Please reach out if you have something to build! - If you need commercial support or don't want to use public methods you can contact us at [team@pion.ly](mailto:team@pion.ly) ### Contributing -Check out the **[contributing wiki](https://github.com/pion/webrtc/wiki/Contributing)** to join the group of amazing people making this project possible: - -* [John Bradley](https://github.com/kc5nra) - *Original Author* -* [Sean DuBois](https://github.com/Sean-Der) - *Original Author* -* [Michael MacDonald](https://github.com/mjmac) - *Original Author* -* [Woodrow Douglass](https://github.com/wdouglass) - *Test coverage* -* [Michiel De Backker](https://github.com/backkem) - *Docs* -* [Hugo Arregui](https://github.com/hugoArregui) - *Custom Logs* -* [Justin Okamoto](https://github.com/justinokamoto) - *Disabled Logs Update* +Check out the [contributing wiki](https://github.com/pion/webrtc/wiki/Contributing) to join the group of amazing people making this project possible ### License MIT License - see [LICENSE](LICENSE) for full text diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/codecov.yml b/trunk/3rdparty/srs-bench/vendor/github.com/pion/logging/codecov.yml similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/codecov.yml rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/logging/codecov.yml diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/logging/logger.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/logging/logger.go index 35f650581..eb1e56af6 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/logging/logger.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/logging/logger.go @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + +// Package logging provides the logging library used by Pion package logging import ( @@ -9,8 +13,8 @@ import ( "sync" ) -// Use this abstraction to ensure thread-safe access to the logger's io.Writer -// (which could change at runtime) +// Use this abstraction to ensure thread-safe access to the logger's io.Writer. +// (which could change at runtime). type loggerWriter struct { sync.RWMutex output io.Writer @@ -25,11 +29,12 @@ func (lw *loggerWriter) SetOutput(output io.Writer) { func (lw *loggerWriter) Write(data []byte) (int, error) { lw.RLock() defer lw.RUnlock() + return lw.output.Write(data) } -// DefaultLeveledLogger encapsulates functionality for providing logging at -// user-defined levels +// DefaultLeveledLogger encapsulates functionality for providing logging at. +// user-defined levels. type DefaultLeveledLogger struct { level LogLevel writer *loggerWriter @@ -41,44 +46,50 @@ type DefaultLeveledLogger struct { } // WithTraceLogger is a chainable configuration function which sets the -// Trace-level logger +// Trace-level logger. func (ll *DefaultLeveledLogger) WithTraceLogger(log *log.Logger) *DefaultLeveledLogger { ll.trace = log + return ll } // WithDebugLogger is a chainable configuration function which sets the -// Debug-level logger +// Debug-level logger. func (ll *DefaultLeveledLogger) WithDebugLogger(log *log.Logger) *DefaultLeveledLogger { ll.debug = log + return ll } // WithInfoLogger is a chainable configuration function which sets the -// Info-level logger +// Info-level logger. func (ll *DefaultLeveledLogger) WithInfoLogger(log *log.Logger) *DefaultLeveledLogger { ll.info = log + return ll } // WithWarnLogger is a chainable configuration function which sets the -// Warn-level logger +// Warn-level logger. func (ll *DefaultLeveledLogger) WithWarnLogger(log *log.Logger) *DefaultLeveledLogger { ll.warn = log + return ll } // WithErrorLogger is a chainable configuration function which sets the -// Error-level logger +// Error-level logger. func (ll *DefaultLeveledLogger) WithErrorLogger(log *log.Logger) *DefaultLeveledLogger { ll.err = log + return ll } // WithOutput is a chainable configuration function which sets the logger's -// logging output to the supplied io.Writer +// logging output to the supplied io.Writer. func (ll *DefaultLeveledLogger) WithOutput(output io.Writer) *DefaultLeveledLogger { ll.writer.SetOutput(output) + return ll } @@ -94,70 +105,71 @@ func (ll *DefaultLeveledLogger) logf(logger *log.Logger, level LogLevel, format } } -// SetLevel sets the logger's logging level +// SetLevel sets the logger's logging level. func (ll *DefaultLeveledLogger) SetLevel(newLevel LogLevel) { ll.level.Set(newLevel) } -// Trace emits the preformatted message if the logger is at or below LogLevelTrace +// Trace emits the preformatted message if the logger is at or below LogLevelTrace. func (ll *DefaultLeveledLogger) Trace(msg string) { - ll.logf(ll.trace, LogLevelTrace, msg) + ll.logf(ll.trace, LogLevelTrace, msg) // nolint: govet } -// Tracef formats and emits a message if the logger is at or below LogLevelTrace +// Tracef formats and emits a message if the logger is at or below LogLevelTrace. func (ll *DefaultLeveledLogger) Tracef(format string, args ...interface{}) { ll.logf(ll.trace, LogLevelTrace, format, args...) } -// Debug emits the preformatted message if the logger is at or below LogLevelDebug +// Debug emits the preformatted message if the logger is at or below LogLevelDebug. func (ll *DefaultLeveledLogger) Debug(msg string) { - ll.logf(ll.debug, LogLevelDebug, msg) + ll.logf(ll.debug, LogLevelDebug, msg) // nolint: govet } -// Debugf formats and emits a message if the logger is at or below LogLevelDebug +// Debugf formats and emits a message if the logger is at or below LogLevelDebug. func (ll *DefaultLeveledLogger) Debugf(format string, args ...interface{}) { ll.logf(ll.debug, LogLevelDebug, format, args...) } -// Info emits the preformatted message if the logger is at or below LogLevelInfo +// Info emits the preformatted message if the logger is at or below LogLevelInfo. func (ll *DefaultLeveledLogger) Info(msg string) { - ll.logf(ll.info, LogLevelInfo, msg) + ll.logf(ll.info, LogLevelInfo, msg) // nolint: govet } -// Infof formats and emits a message if the logger is at or below LogLevelInfo +// Infof formats and emits a message if the logger is at or below LogLevelInfo. func (ll *DefaultLeveledLogger) Infof(format string, args ...interface{}) { ll.logf(ll.info, LogLevelInfo, format, args...) } -// Warn emits the preformatted message if the logger is at or below LogLevelWarn +// Warn emits the preformatted message if the logger is at or below LogLevelWarn. func (ll *DefaultLeveledLogger) Warn(msg string) { - ll.logf(ll.warn, LogLevelWarn, msg) + ll.logf(ll.warn, LogLevelWarn, msg) // nolint: govet } -// Warnf formats and emits a message if the logger is at or below LogLevelWarn +// Warnf formats and emits a message if the logger is at or below LogLevelWarn. func (ll *DefaultLeveledLogger) Warnf(format string, args ...interface{}) { ll.logf(ll.warn, LogLevelWarn, format, args...) } -// Error emits the preformatted message if the logger is at or below LogLevelError +// Error emits the preformatted message if the logger is at or below LogLevelError. func (ll *DefaultLeveledLogger) Error(msg string) { - ll.logf(ll.err, LogLevelError, msg) + ll.logf(ll.err, LogLevelError, msg) // nolint: govet } -// Errorf formats and emits a message if the logger is at or below LogLevelError +// Errorf formats and emits a message if the logger is at or below LogLevelError. func (ll *DefaultLeveledLogger) Errorf(format string, args ...interface{}) { ll.logf(ll.err, LogLevelError, format, args...) } -// NewDefaultLeveledLoggerForScope returns a configured LeveledLogger +// NewDefaultLeveledLoggerForScope returns a configured LeveledLogger. func NewDefaultLeveledLoggerForScope(scope string, level LogLevel, writer io.Writer) *DefaultLeveledLogger { if writer == nil { - writer = os.Stdout + writer = os.Stderr } logger := &DefaultLeveledLogger{ writer: &loggerWriter{output: writer}, level: level, } + return logger. WithTraceLogger(log.New(logger.writer, fmt.Sprintf("%s TRACE: ", scope), log.Lmicroseconds|log.Lshortfile)). WithDebugLogger(log.New(logger.writer, fmt.Sprintf("%s DEBUG: ", scope), log.Lmicroseconds|log.Lshortfile)). @@ -166,19 +178,19 @@ func NewDefaultLeveledLoggerForScope(scope string, level LogLevel, writer io.Wri WithErrorLogger(log.New(logger.writer, fmt.Sprintf("%s ERROR: ", scope), log.LstdFlags)) } -// DefaultLoggerFactory define levels by scopes and creates new DefaultLeveledLogger +// DefaultLoggerFactory define levels by scopes and creates new DefaultLeveledLogger. type DefaultLoggerFactory struct { Writer io.Writer DefaultLogLevel LogLevel ScopeLevels map[string]LogLevel } -// NewDefaultLoggerFactory creates a new DefaultLoggerFactory +// NewDefaultLoggerFactory creates a new DefaultLoggerFactory. func NewDefaultLoggerFactory() *DefaultLoggerFactory { factory := DefaultLoggerFactory{} factory.DefaultLogLevel = LogLevelError factory.ScopeLevels = make(map[string]LogLevel) - factory.Writer = os.Stdout + factory.Writer = os.Stderr logLevels := map[string]LogLevel{ "DISABLE": LogLevelDisabled, @@ -201,7 +213,10 @@ func NewDefaultLoggerFactory() *DefaultLoggerFactory { } if strings.ToLower(env) == "all" { - factory.DefaultLogLevel = level + if factory.DefaultLogLevel < level { + factory.DefaultLogLevel = level + } + continue } @@ -214,7 +229,7 @@ func NewDefaultLoggerFactory() *DefaultLoggerFactory { return &factory } -// NewLogger returns a configured LeveledLogger for the given , argsscope +// NewLogger returns a configured LeveledLogger for the given, argsscope. func (f *DefaultLoggerFactory) NewLogger(scope string) LeveledLogger { logLevel := f.DefaultLogLevel if f.ScopeLevels != nil { @@ -224,5 +239,6 @@ func (f *DefaultLoggerFactory) NewLogger(scope string) LeveledLogger { logLevel = scopeLevel } } + return NewDefaultLeveledLoggerForScope(scope, logLevel, f.Writer) } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/mdns/renovate.json b/trunk/3rdparty/srs-bench/vendor/github.com/pion/logging/renovate.json similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/mdns/renovate.json rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/logging/renovate.json diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/logging/scoped.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/logging/scoped.go index 678bab426..7b3a550ee 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/logging/scoped.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/logging/scoped.go @@ -1,18 +1,21 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package logging import ( "sync/atomic" ) -// LogLevel represents the level at which the logger will emit log messages +// LogLevel represents the level at which the logger will emit log messages. type LogLevel int32 -// Set updates the LogLevel to the supplied value +// Set updates the LogLevel to the supplied value. func (ll *LogLevel) Set(newLevel LogLevel) { atomic.StoreInt32((*int32)(ll), int32(newLevel)) } -// Get retrieves the current LogLevel value +// Get retrieves the current LogLevel value. func (ll *LogLevel) Get() LogLevel { return LogLevel(atomic.LoadInt32((*int32)(ll))) } @@ -37,22 +40,22 @@ func (ll LogLevel) String() string { } const ( - // LogLevelDisabled completely disables logging of any events + // LogLevelDisabled completely disables logging of any events. LogLevelDisabled LogLevel = iota // LogLevelError is for fatal errors which should be handled by user code, - // but are logged to ensure that they are seen + // but are logged to ensure that they are seen. LogLevelError - // LogLevelWarn is for logging abnormal, but non-fatal library operation + // LogLevelWarn is for logging abnormal, but non-fatal library operation. LogLevelWarn - // LogLevelInfo is for logging normal library operation (e.g. state transitions, etc.) + // LogLevelInfo is for logging normal library operation (e.g. state transitions, etc.). LogLevelInfo - // LogLevelDebug is for logging low-level library information (e.g. internal operations) + // LogLevelDebug is for logging low-level library information (e.g. internal operations). LogLevelDebug - // LogLevelTrace is for logging very low-level library information (e.g. network traces) + // LogLevelTrace is for logging very low-level library information (e.g. network traces). LogLevelTrace ) -// LeveledLogger is the basic pion Logger interface +// LeveledLogger is the basic pion Logger interface. type LeveledLogger interface { Trace(msg string) Tracef(format string, args ...interface{}) @@ -66,7 +69,7 @@ type LeveledLogger interface { Errorf(format string, args ...interface{}) } -// LoggerFactory is the basic pion LoggerFactory interface +// LoggerFactory is the basic pion LoggerFactory interface. type LoggerFactory interface { NewLogger(scope string) LeveledLogger } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/mdns/.golangci.yml b/trunk/3rdparty/srs-bench/vendor/github.com/pion/mdns/.golangci.yml deleted file mode 100644 index 48696f16b..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/mdns/.golangci.yml +++ /dev/null @@ -1,116 +0,0 @@ -linters-settings: - govet: - check-shadowing: true - misspell: - locale: US - exhaustive: - default-signifies-exhaustive: true - gomodguard: - blocked: - modules: - - github.com/pkg/errors: - recommendations: - - errors - -linters: - enable: - - asciicheck # Simple linter to check that your code does not contain non-ASCII identifiers - - bidichk # Checks for dangerous unicode character sequences - - bodyclose # checks whether HTTP response body is closed successfully - - contextcheck # check the function whether use a non-inherited context - - decorder # check declaration order and count of types, constants, variables and functions - - depguard # Go linter that checks if package imports are in a list of acceptable packages - - dogsled # Checks assignments with too many blank identifiers (e.g. x, _, _, _, := f()) - - dupl # Tool for code clone detection - - durationcheck # check for two durations multiplied together - - errcheck # Errcheck is a program for checking for unchecked errors in go programs. These unchecked errors can be critical bugs in some cases - - errchkjson # Checks types passed to the json encoding functions. Reports unsupported types and optionally reports occations, where the check for the returned error can be omitted. - - errname # Checks that sentinel errors are prefixed with the `Err` and error types are suffixed with the `Error`. - - errorlint # errorlint is a linter for that can be used to find code that will cause problems with the error wrapping scheme introduced in Go 1.13. - - exhaustive # check exhaustiveness of enum switch statements - - exportloopref # checks for pointers to enclosing loop variables - - forcetypeassert # finds forced type assertions - - gci # Gci control golang package import order and make it always deterministic. - - gochecknoglobals # Checks that no globals are present in Go code - - gochecknoinits # Checks that no init functions are present in Go code - - gocognit # Computes and checks the cognitive complexity of functions - - goconst # Finds repeated strings that could be replaced by a constant - - gocritic # The most opinionated Go source code linter - - godox # Tool for detection of FIXME, TODO and other comment keywords - - goerr113 # Golang linter to check the errors handling expressions - - gofmt # Gofmt checks whether code was gofmt-ed. By default this tool runs with -s option to check for code simplification - - gofumpt # Gofumpt checks whether code was gofumpt-ed. - - goheader # Checks is file header matches to pattern - - goimports # Goimports does everything that gofmt does. Additionally it checks unused imports - - gomoddirectives # Manage the use of 'replace', 'retract', and 'excludes' directives in go.mod. - - gomodguard # Allow and block list linter for direct Go module dependencies. This is different from depguard where there are different block types for example version constraints and module recommendations. - - goprintffuncname # Checks that printf-like functions are named with `f` at the end - - gosec # Inspects source code for security problems - - gosimple # Linter for Go source code that specializes in simplifying a code - - govet # Vet examines Go source code and reports suspicious constructs, such as Printf calls whose arguments do not align with the format string - - grouper # An analyzer to analyze expression groups. - - importas # Enforces consistent import aliases - - ineffassign # Detects when assignments to existing variables are not used - - misspell # Finds commonly misspelled English words in comments - - nakedret # Finds naked returns in functions greater than a specified function length - - nilerr # Finds the code that returns nil even if it checks that the error is not nil. - - nilnil # Checks that there is no simultaneous return of `nil` error and an invalid value. - - noctx # noctx finds sending http request without context.Context - - predeclared # find code that shadows one of Go's predeclared identifiers - - revive # golint replacement, finds style mistakes - - staticcheck # Staticcheck is a go vet on steroids, applying a ton of static analysis checks - - stylecheck # Stylecheck is a replacement for golint - - tagliatelle # Checks the struct tags. - - tenv # tenv is analyzer that detects using os.Setenv instead of t.Setenv since Go1.17 - - tparallel # tparallel detects inappropriate usage of t.Parallel() method in your Go test codes - - typecheck # Like the front-end of a Go compiler, parses and type-checks Go code - - unconvert # Remove unnecessary type conversions - - unparam # Reports unused function parameters - - unused # Checks Go code for unused constants, variables, functions and types - - wastedassign # wastedassign finds wasted assignment statements - - whitespace # Tool for detection of leading and trailing whitespace - disable: - - containedctx # containedctx is a linter that detects struct contained context.Context field - - cyclop # checks function and package cyclomatic complexity - - exhaustivestruct # Checks if all struct's fields are initialized - - forbidigo # Forbids identifiers - - funlen # Tool for detection of long functions - - gocyclo # Computes and checks the cyclomatic complexity of functions - - godot # Check if comments end in a period - - gomnd # An analyzer to detect magic numbers. - - ifshort # Checks that your code uses short syntax for if-statements whenever possible - - ireturn # Accept Interfaces, Return Concrete Types - - lll # Reports long lines - - maintidx # maintidx measures the maintainability index of each function. - - makezero # Finds slice declarations with non-zero initial length - - maligned # Tool to detect Go structs that would take less memory if their fields were sorted - - nestif # Reports deeply nested if statements - - nlreturn # nlreturn checks for a new line before return and branch statements to increase code clarity - - nolintlint # Reports ill-formed or insufficient nolint directives - - paralleltest # paralleltest detects missing usage of t.Parallel() method in your Go test - - prealloc # Finds slice declarations that could potentially be preallocated - - promlinter # Check Prometheus metrics naming via promlint - - rowserrcheck # checks whether Err of rows is checked successfully - - sqlclosecheck # Checks that sql.Rows and sql.Stmt are closed. - - testpackage # linter that makes you use a separate _test package - - thelper # thelper detects golang test helpers without t.Helper() call and checks the consistency of test helpers - - varnamelen # checks that the length of a variable's name matches its scope - - wrapcheck # Checks that errors returned from external packages are wrapped - - wsl # Whitespace Linter - Forces you to use empty lines! - -issues: - exclude-use-default: false - exclude-rules: - # Allow complex tests, better to be self contained - - path: _test\.go - linters: - - gocognit - - # Allow complex main function in examples - - path: examples - text: "of func `main` is high" - linters: - - gocognit - -run: - skip-dirs-use-default: false diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/mdns/.goreleaser.yml b/trunk/3rdparty/srs-bench/vendor/github.com/pion/mdns/.goreleaser.yml deleted file mode 100644 index 2caa5fbd3..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/mdns/.goreleaser.yml +++ /dev/null @@ -1,2 +0,0 @@ -builds: -- skip: true diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/mdns/AUTHORS.txt b/trunk/3rdparty/srs-bench/vendor/github.com/pion/mdns/AUTHORS.txt deleted file mode 100644 index 48ceb8211..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/mdns/AUTHORS.txt +++ /dev/null @@ -1,17 +0,0 @@ -# Thank you to everyone that made Pion possible. If you are interested in contributing -# we would love to have you https://github.com/pion/webrtc/wiki/Contributing -# -# This file is auto generated, using git to list all individuals contributors. -# see https://github.com/pion/.goassets/blob/master/scripts/generate-authors.sh for the scripting -Atsushi Watanabe -Bjørn Remseth -Doug Cone -Hugo Arregui -Javier Peletier -Jonas van den Berg <24623262+vonas@users.noreply.github.com> -Konstantin Itskov -Sean DuBois -Sean DuBois - -# List of contributors not appearing in Git history - diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/mdns/config.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/mdns/config.go deleted file mode 100644 index e028046e7..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/mdns/config.go +++ /dev/null @@ -1,27 +0,0 @@ -package mdns - -import ( - "time" - - "github.com/pion/logging" -) - -const ( - // DefaultAddress is the default used by mDNS - // and in most cases should be the address that the - // net.Conn passed to Server is bound to - DefaultAddress = "224.0.0.0:5353" -) - -// Config is used to configure a mDNS client or server. -type Config struct { - // QueryInterval controls how often we sends Queries until we - // get a response for the requested name - QueryInterval time.Duration - - // LocalNames are the names that we will generate answers for - // when we get questions - LocalNames []string - - LoggerFactory logging.LoggerFactory -} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/mdns/conn.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/mdns/conn.go deleted file mode 100644 index 31037e252..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/mdns/conn.go +++ /dev/null @@ -1,384 +0,0 @@ -package mdns - -import ( - "context" - "errors" - "math/big" - "net" - "runtime" - "sync" - "time" - - "github.com/pion/logging" - "golang.org/x/net/dns/dnsmessage" - "golang.org/x/net/ipv4" -) - -// Conn represents a mDNS Server -type Conn struct { - mu sync.RWMutex - log logging.LeveledLogger - - socket *ipv4.PacketConn - dstAddr *net.UDPAddr - - queryInterval time.Duration - localNames []string - queries []query - ifaces []net.Interface - - closed chan interface{} -} - -type query struct { - nameWithSuffix string - queryResultChan chan queryResult -} - -type queryResult struct { - answer dnsmessage.ResourceHeader - addr net.Addr -} - -const ( - defaultQueryInterval = time.Second - destinationAddress = "224.0.0.251:5353" - maxMessageRecords = 3 - responseTTL = 120 -) - -var errNoPositiveMTUFound = errors.New("no positive MTU found") - -// Server establishes a mDNS connection over an existing conn -func Server(conn *ipv4.PacketConn, config *Config) (*Conn, error) { - if config == nil { - return nil, errNilConfig - } - - ifaces, err := net.Interfaces() - if err != nil { - return nil, err - } - - inboundBufferSize := 0 - joinErrCount := 0 - ifacesToUse := make([]net.Interface, 0, len(ifaces)) - for i, ifc := range ifaces { - if err = conn.JoinGroup(&ifaces[i], &net.UDPAddr{IP: net.IPv4(224, 0, 0, 251)}); err != nil { - joinErrCount++ - continue - } - - ifcCopy := ifc - ifacesToUse = append(ifacesToUse, ifcCopy) - if ifaces[i].MTU > inboundBufferSize { - inboundBufferSize = ifaces[i].MTU - } - } - - if inboundBufferSize == 0 { - return nil, errNoPositiveMTUFound - } - if joinErrCount >= len(ifaces) { - return nil, errJoiningMulticastGroup - } - - dstAddr, err := net.ResolveUDPAddr("udp", destinationAddress) - if err != nil { - return nil, err - } - - loggerFactory := config.LoggerFactory - if loggerFactory == nil { - loggerFactory = logging.NewDefaultLoggerFactory() - } - - localNames := []string{} - for _, l := range config.LocalNames { - localNames = append(localNames, l+".") - } - - c := &Conn{ - queryInterval: defaultQueryInterval, - queries: []query{}, - socket: conn, - dstAddr: dstAddr, - localNames: localNames, - ifaces: ifacesToUse, - log: loggerFactory.NewLogger("mdns"), - closed: make(chan interface{}), - } - if config.QueryInterval != 0 { - c.queryInterval = config.QueryInterval - } - - // https://www.rfc-editor.org/rfc/rfc6762.html#section-17 - // Multicast DNS messages carried by UDP may be up to the IP MTU of the - // physical interface, less the space required for the IP header (20 - // bytes for IPv4; 40 bytes for IPv6) and the UDP header (8 bytes). - go c.start(inboundBufferSize - 20 - 8) - return c, nil -} - -// Close closes the mDNS Conn -func (c *Conn) Close() error { - select { - case <-c.closed: - return nil - default: - } - - if err := c.socket.Close(); err != nil { - return err - } - - <-c.closed - return nil -} - -// Query sends mDNS Queries for the following name until -// either the Context is canceled/expires or we get a result -func (c *Conn) Query(ctx context.Context, name string) (dnsmessage.ResourceHeader, net.Addr, error) { - select { - case <-c.closed: - return dnsmessage.ResourceHeader{}, nil, errConnectionClosed - default: - } - - nameWithSuffix := name + "." - - queryChan := make(chan queryResult, 1) - c.mu.Lock() - c.queries = append(c.queries, query{nameWithSuffix, queryChan}) - ticker := time.NewTicker(c.queryInterval) - c.mu.Unlock() - - defer ticker.Stop() - - c.sendQuestion(nameWithSuffix) - for { - select { - case <-ticker.C: - c.sendQuestion(nameWithSuffix) - case <-c.closed: - return dnsmessage.ResourceHeader{}, nil, errConnectionClosed - case res := <-queryChan: - return res.answer, res.addr, nil - case <-ctx.Done(): - return dnsmessage.ResourceHeader{}, nil, errContextElapsed - } - } -} - -func ipToBytes(ip net.IP) (out [4]byte) { - rawIP := ip.To4() - if rawIP == nil { - return - } - - ipInt := big.NewInt(0) - ipInt.SetBytes(rawIP) - copy(out[:], ipInt.Bytes()) - return -} - -func interfaceForRemote(remote string) (net.IP, error) { - conn, err := net.Dial("udp", remote) - if err != nil { - return nil, err - } - - localAddr, ok := conn.LocalAddr().(*net.UDPAddr) - if !ok { - return nil, errFailedCast - } - - if err := conn.Close(); err != nil { - return nil, err - } - - return localAddr.IP, nil -} - -func (c *Conn) sendQuestion(name string) { - packedName, err := dnsmessage.NewName(name) - if err != nil { - c.log.Warnf("Failed to construct mDNS packet %v", err) - return - } - - msg := dnsmessage.Message{ - Header: dnsmessage.Header{}, - Questions: []dnsmessage.Question{ - { - Type: dnsmessage.TypeA, - Class: dnsmessage.ClassINET, - Name: packedName, - }, - }, - } - - rawQuery, err := msg.Pack() - if err != nil { - c.log.Warnf("Failed to construct mDNS packet %v", err) - return - } - - c.writeToSocket(rawQuery) -} - -const isWindows = runtime.GOOS == "windows" - -func (c *Conn) writeToSocket(b []byte) { - var wcm ipv4.ControlMessage - for i := range c.ifaces { - if isWindows { - if err := c.socket.SetMulticastInterface(&c.ifaces[i]); err != nil { - c.log.Warnf("Failed to set multicast interface for %d: %v", i, err) - } - } else { - wcm.IfIndex = c.ifaces[i].Index - } - if _, err := c.socket.WriteTo(b, &wcm, c.dstAddr); err != nil { - c.log.Warnf("Failed to send mDNS packet on interface %d: %v", i, err) - } - } -} - -func (c *Conn) sendAnswer(name string, dst net.IP) { - packedName, err := dnsmessage.NewName(name) - if err != nil { - c.log.Warnf("Failed to construct mDNS packet %v", err) - return - } - - msg := dnsmessage.Message{ - Header: dnsmessage.Header{ - Response: true, - Authoritative: true, - }, - Answers: []dnsmessage.Resource{ - { - Header: dnsmessage.ResourceHeader{ - Type: dnsmessage.TypeA, - Class: dnsmessage.ClassINET, - Name: packedName, - TTL: responseTTL, - }, - Body: &dnsmessage.AResource{ - A: ipToBytes(dst), - }, - }, - }, - } - - rawAnswer, err := msg.Pack() - if err != nil { - c.log.Warnf("Failed to construct mDNS packet %v", err) - return - } - - c.writeToSocket(rawAnswer) -} - -func (c *Conn) start(inboundBufferSize int) { //nolint gocognit - defer func() { - c.mu.Lock() - defer c.mu.Unlock() - close(c.closed) - }() - - b := make([]byte, inboundBufferSize) - p := dnsmessage.Parser{} - - for { - n, _, src, err := c.socket.ReadFrom(b) - if err != nil { - if errors.Is(err, net.ErrClosed) { - return - } - c.log.Warnf("Failed to ReadFrom %q %v", src, err) - continue - } - - func() { - c.mu.RLock() - defer c.mu.RUnlock() - - if _, err := p.Start(b[:n]); err != nil { - c.log.Warnf("Failed to parse mDNS packet %v", err) - return - } - - for i := 0; i <= maxMessageRecords; i++ { - q, err := p.Question() - if errors.Is(err, dnsmessage.ErrSectionDone) { - break - } else if err != nil { - c.log.Warnf("Failed to parse mDNS packet %v", err) - return - } - - for _, localName := range c.localNames { - if localName == q.Name.String() { - localAddress, err := interfaceForRemote(src.String()) - if err != nil { - c.log.Warnf("Failed to get local interface to communicate with %s: %v", src.String(), err) - continue - } - - c.sendAnswer(q.Name.String(), localAddress) - } - } - } - - for i := 0; i <= maxMessageRecords; i++ { - a, err := p.AnswerHeader() - if errors.Is(err, dnsmessage.ErrSectionDone) { - return - } - if err != nil { - c.log.Warnf("Failed to parse mDNS packet %v", err) - return - } - - if a.Type != dnsmessage.TypeA && a.Type != dnsmessage.TypeAAAA { - continue - } - - for i := len(c.queries) - 1; i >= 0; i-- { - if c.queries[i].nameWithSuffix == a.Name.String() { - ip, err := ipFromAnswerHeader(a, p) - if err != nil { - c.log.Warnf("Failed to parse mDNS answer %v", err) - return - } - - c.queries[i].queryResultChan <- queryResult{a, &net.IPAddr{ - IP: ip, - }} - c.queries = append(c.queries[:i], c.queries[i+1:]...) - } - } - } - }() - } -} - -func ipFromAnswerHeader(a dnsmessage.ResourceHeader, p dnsmessage.Parser) (ip []byte, err error) { - if a.Type == dnsmessage.TypeA { - resource, err := p.AResource() - if err != nil { - return nil, err - } - ip = net.IP(resource.A[:]) - } else { - resource, err := p.AAAAResource() - if err != nil { - return nil, err - } - ip = resource.AAAA[:] - } - - return -} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/mdns/mdns.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/mdns/mdns.go deleted file mode 100644 index 853ae833e..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/mdns/mdns.go +++ /dev/null @@ -1,2 +0,0 @@ -// Package mdns implements mDNS (multicast DNS) -package mdns diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/.gitignore b/trunk/3rdparty/srs-bench/vendor/github.com/pion/mdns/v2/.gitignore similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/.gitignore rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/mdns/v2/.gitignore diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/.golangci.yml b/trunk/3rdparty/srs-bench/vendor/github.com/pion/mdns/v2/.golangci.yml similarity index 96% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/.golangci.yml rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/mdns/v2/.golangci.yml index 4e3eddf42..6dd80c805 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/ice/v2/.golangci.yml +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/mdns/v2/.golangci.yml @@ -29,7 +29,6 @@ linters: - bodyclose # checks whether HTTP response body is closed successfully - contextcheck # check the function whether use a non-inherited context - decorder # check declaration order and count of types, constants, variables and functions - - depguard # Go linter that checks if package imports are in a list of acceptable packages - dogsled # Checks assignments with too many blank identifiers (e.g. x, _, _, _, := f()) - dupl # Tool for code clone detection - durationcheck # check for two durations multiplied together @@ -63,7 +62,6 @@ linters: - importas # Enforces consistent import aliases - ineffassign # Detects when assignments to existing variables are not used - misspell # Finds commonly misspelled English words in comments - - nakedret # Finds naked returns in functions greater than a specified function length - nilerr # Finds the code that returns nil even if it checks that the error is not nil. - nilnil # Checks that there is no simultaneous return of `nil` error and an invalid value. - noctx # noctx finds sending http request without context.Context @@ -81,6 +79,7 @@ linters: - wastedassign # wastedassign finds wasted assignment statements - whitespace # Tool for detection of leading and trailing whitespace disable: + - depguard # Go linter that checks if package imports are in a list of acceptable packages - containedctx # containedctx is a linter that detects struct contained context.Context field - cyclop # checks function and package cyclomatic complexity - exhaustivestruct # Checks if all struct's fields are initialized @@ -94,6 +93,7 @@ linters: - maintidx # maintidx measures the maintainability index of each function. - makezero # Finds slice declarations with non-zero initial length - maligned # Tool to detect Go structs that would take less memory if their fields were sorted + - nakedret # Finds naked returns in functions greater than a specified function length - nestif # Reports deeply nested if statements - nlreturn # nlreturn checks for a new line before return and branch statements to increase code clarity - nolintlint # Reports ill-formed or insufficient nolint directives @@ -111,22 +111,11 @@ linters: issues: exclude-use-default: false exclude-rules: - # Allow complex tests, better to be self contained - - path: _test\.go - linters: - - gocognit - - forbidigo - - # Allow complex main function in examples - - path: examples - text: "of func `main` is high" - linters: - - gocognit - - # Allow forbidden identifiers in examples - - path: examples + # Allow complex tests and examples, better to be self contained + - path: (examples|main\.go|_test\.go) linters: - forbidigo + - gocognit # Allow forbidden identifiers in CLI commands - path: cmd diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/.goreleaser.yml b/trunk/3rdparty/srs-bench/vendor/github.com/pion/mdns/v2/.goreleaser.yml similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/.goreleaser.yml rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/mdns/v2/.goreleaser.yml diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/mdns/LICENSE b/trunk/3rdparty/srs-bench/vendor/github.com/pion/mdns/v2/LICENSE similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/mdns/LICENSE rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/mdns/v2/LICENSE diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/mdns/README.md b/trunk/3rdparty/srs-bench/vendor/github.com/pion/mdns/v2/README.md similarity index 56% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/mdns/README.md rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/mdns/v2/README.md index b2d7d9c73..70b488188 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/mdns/README.md +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/mdns/v2/README.md @@ -8,8 +8,8 @@ Pion mDNS Slack Widget
- Build Status - GoDoc + GitHub Workflow Status + Go Reference Coverage Status Go Report Card License: MIT @@ -24,6 +24,12 @@ For a mDNS server that responds to queries for `pion-test.local` go run examples/server/main.go ``` +For a mDNS server that responds to queries for `pion-test.local` with a given address +```sh +go run examples/server/publish_ip/main.go -ip=[IP] +``` +If you don't set the `ip` parameter, "1.2.3.4" will be used instead. + ### Running Client To query using Pion you can run the `query` example @@ -41,19 +47,26 @@ Or the avahi client avahi-resolve -a pion-test.local ``` -### References -https://tools.ietf.org/html/rfc6762 -https://tools.ietf.org/id/draft-ietf-rtcweb-mdns-ice-candidates-02.html +### RFCs +#### Implemented +- **RFC 6762** [Multicast DNS][rfc6762] +- **draft-ietf-rtcweb-mdns-ice-candidates-02** [Using Multicast DNS to protect privacy when exposing ICE candidates](https://datatracker.ietf.org/doc/html/draft-ietf-rtcweb-mdns-ice-candidates-02.html) + +[rfc6762]: https://tools.ietf.org/html/rfc6762 + +### Roadmap +The library is used as a part of our WebRTC implementation. Please refer to that [roadmap](https://github.com/pion/webrtc/issues/9) to track our major milestones. ### Community -Pion has an active community on the [Golang Slack](https://invite.slack.golangbridge.org/). Sign up and join the **#pion** channel for discussions and support. You can also use [Pion mailing list](https://groups.google.com/forum/#!forum/pion). +Pion has an active community on the [Slack](https://pion.ly/slack). + +Follow the [Pion Twitter](https://twitter.com/_pion) for project updates and important WebRTC news. We are always looking to support **your projects**. Please reach out if you have something to build! - If you need commercial support or don't want to use public methods you can contact us at [team@pion.ly](mailto:team@pion.ly) ### Contributing -Check out the **[contributing wiki](https://github.com/pion/webrtc/wiki/Contributing)** to join the group of amazing people making this project possible: +Check out the [contributing wiki](https://github.com/pion/webrtc/wiki/Contributing) to join the group of amazing people making this project possible ### License -MIT License - see [LICENSE](LICENSE) for full text +MIT License - see [LICENSE](LICENSE) for full text \ No newline at end of file diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/codecov.yml b/trunk/3rdparty/srs-bench/vendor/github.com/pion/mdns/v2/codecov.yml similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/codecov.yml rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/mdns/v2/codecov.yml diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/mdns/v2/config.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/mdns/v2/config.go new file mode 100644 index 000000000..4659e0664 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/mdns/v2/config.go @@ -0,0 +1,49 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + +package mdns + +import ( + "net" + "time" + + "github.com/pion/logging" +) + +const ( + // DefaultAddressIPv4 is the default used by mDNS + // and in most cases should be the address that the + // ipv4.PacketConn passed to Server is bound to + DefaultAddressIPv4 = "224.0.0.0:5353" + + // DefaultAddressIPv6 is the default IPv6 address used + // by mDNS and in most cases should be the address that + // the ipv6.PacketConn passed to Server is bound to + DefaultAddressIPv6 = "[FF02::]:5353" +) + +// Config is used to configure a mDNS client or server. +type Config struct { + // Name is the name of the client/server used for logging purposes. + Name string + + // QueryInterval controls how often we sends Queries until we + // get a response for the requested name + QueryInterval time.Duration + + // LocalNames are the names that we will generate answers for + // when we get questions + LocalNames []string + + // LocalAddress will override the published address with the given IP + // when set. Otherwise, the automatically determined address will be used. + LocalAddress net.IP + + LoggerFactory logging.LoggerFactory + + // IncludeLoopback will include loopback interfaces to be eligble for queries and answers. + IncludeLoopback bool + + // Interfaces will override the interfaces used for queries and answers. + Interfaces []net.Interface +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/mdns/v2/conn.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/mdns/v2/conn.go new file mode 100644 index 000000000..d300163ad --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/mdns/v2/conn.go @@ -0,0 +1,1220 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + +package mdns + +import ( + "context" + "errors" + "fmt" + "net" + "net/netip" + "sync" + "time" + + "github.com/pion/logging" + "golang.org/x/net/dns/dnsmessage" + "golang.org/x/net/ipv4" + "golang.org/x/net/ipv6" +) + +// Conn represents a mDNS Server +type Conn struct { + mu sync.RWMutex + name string + log logging.LeveledLogger + + multicastPktConnV4 ipPacketConn + multicastPktConnV6 ipPacketConn + dstAddr4 *net.UDPAddr + dstAddr6 *net.UDPAddr + + unicastPktConnV4 ipPacketConn + unicastPktConnV6 ipPacketConn + + queryInterval time.Duration + localNames []string + queries []*query + ifaces map[int]netInterface + + closed chan interface{} +} + +type query struct { + nameWithSuffix string + queryResultChan chan queryResult +} + +type queryResult struct { + answer dnsmessage.ResourceHeader + addr netip.Addr +} + +const ( + defaultQueryInterval = time.Second + destinationAddress4 = "224.0.0.251:5353" + destinationAddress6 = "[FF02::FB]:5353" + maxMessageRecords = 3 + responseTTL = 120 + // maxPacketSize is the maximum size of a mdns packet. + // From RFC 6762: + // Even when fragmentation is used, a Multicast DNS packet, including IP + // and UDP headers, MUST NOT exceed 9000 bytes. + // https://datatracker.ietf.org/doc/html/rfc6762#section-17 + maxPacketSize = 9000 +) + +var ( + errNoPositiveMTUFound = errors.New("no positive MTU found") + errNoPacketConn = errors.New("must supply at least a multicast IPv4 or IPv6 PacketConn") + errNoUsableInterfaces = errors.New("no usable interfaces found for mDNS") + errFailedToClose = errors.New("failed to close mDNS Conn") +) + +type netInterface struct { + net.Interface + ipAddrs []netip.Addr + supportsV4 bool + supportsV6 bool +} + +// Server establishes a mDNS connection over an existing conn. +// Either one or both of the multicast packet conns should be provided. +// The presence of each IP type of PacketConn will dictate what kinds +// of questions are sent for queries. That is, if an ipv6.PacketConn is +// provided, then AAAA questions will be sent. A questions will only be +// sent if an ipv4.PacketConn is also provided. In the future, we may +// add a QueryAddr method that allows specifying this more clearly. +// +//nolint:gocognit +func Server( + multicastPktConnV4 *ipv4.PacketConn, + multicastPktConnV6 *ipv6.PacketConn, + config *Config, +) (*Conn, error) { + if config == nil { + return nil, errNilConfig + } + loggerFactory := config.LoggerFactory + if loggerFactory == nil { + loggerFactory = logging.NewDefaultLoggerFactory() + } + log := loggerFactory.NewLogger("mdns") + + c := &Conn{ + queryInterval: defaultQueryInterval, + log: log, + closed: make(chan interface{}), + } + c.name = config.Name + if c.name == "" { + c.name = fmt.Sprintf("%p", &c) + } + + if multicastPktConnV4 == nil && multicastPktConnV6 == nil { + return nil, errNoPacketConn + } + + ifaces := config.Interfaces + if ifaces == nil { + var err error + ifaces, err = net.Interfaces() + if err != nil { + return nil, err + } + } + + var unicastPktConnV4 *ipv4.PacketConn + { + addr4, err := net.ResolveUDPAddr("udp4", "0.0.0.0:0") + if err != nil { + return nil, err + } + + unicastConnV4, err := net.ListenUDP("udp4", addr4) + if err != nil { + log.Warnf("[%s] failed to listen on unicast IPv4 %s: %s; will not be able to receive unicast responses on IPv4", c.name, addr4, err) + } else { + unicastPktConnV4 = ipv4.NewPacketConn(unicastConnV4) + } + } + + var unicastPktConnV6 *ipv6.PacketConn + { + addr6, err := net.ResolveUDPAddr("udp6", "[::]:") + if err != nil { + return nil, err + } + + unicastConnV6, err := net.ListenUDP("udp6", addr6) + if err != nil { + log.Warnf("[%s] failed to listen on unicast IPv6 %s: %s; will not be able to receive unicast responses on IPv6", c.name, addr6, err) + } else { + unicastPktConnV6 = ipv6.NewPacketConn(unicastConnV6) + } + } + + mutlicastGroup4 := net.IPv4(224, 0, 0, 251) + multicastGroupAddr4 := &net.UDPAddr{IP: mutlicastGroup4} + + // FF02::FB + mutlicastGroup6 := net.IP{0xff, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfb} + multicastGroupAddr6 := &net.UDPAddr{IP: mutlicastGroup6} + + inboundBufferSize := 0 + joinErrCount := 0 + ifacesToUse := make(map[int]netInterface, len(ifaces)) + for i := range ifaces { + ifc := ifaces[i] + if !config.IncludeLoopback && ifc.Flags&net.FlagLoopback == net.FlagLoopback { + continue + } + if ifc.Flags&net.FlagUp == 0 { + continue + } + + addrs, err := ifc.Addrs() + if err != nil { + continue + } + var supportsV4, supportsV6 bool + ifcIPAddrs := make([]netip.Addr, 0, len(addrs)) + for _, addr := range addrs { + var ipToConv net.IP + switch addr := addr.(type) { + case *net.IPNet: + ipToConv = addr.IP + case *net.IPAddr: + ipToConv = addr.IP + default: + continue + } + + ipAddr, ok := netip.AddrFromSlice(ipToConv) + if !ok { + continue + } + if multicastPktConnV4 != nil { + // don't want mapping since we also support IPv4/A + ipAddr = ipAddr.Unmap() + } + ipAddr = addrWithOptionalZone(ipAddr, ifc.Name) + + if ipAddr.Is6() && !ipAddr.Is4In6() { + supportsV6 = true + } else { + // we'll claim we support v4 but defer if we send it or not + // based on IPv4-to-IPv6 mapping rules later (search for Is4In6 below) + supportsV4 = true + } + ifcIPAddrs = append(ifcIPAddrs, ipAddr) + } + if !(supportsV4 || supportsV6) { + continue + } + + var atLeastOneJoin bool + if supportsV4 && multicastPktConnV4 != nil { + if err := multicastPktConnV4.JoinGroup(&ifc, multicastGroupAddr4); err == nil { + atLeastOneJoin = true + } + } + if supportsV6 && multicastPktConnV6 != nil { + if err := multicastPktConnV6.JoinGroup(&ifc, multicastGroupAddr6); err == nil { + atLeastOneJoin = true + } + } + if !atLeastOneJoin { + joinErrCount++ + continue + } + + ifacesToUse[ifc.Index] = netInterface{ + Interface: ifc, + ipAddrs: ifcIPAddrs, + supportsV4: supportsV4, + supportsV6: supportsV6, + } + if ifc.MTU > inboundBufferSize { + inboundBufferSize = ifc.MTU + } + } + + if len(ifacesToUse) == 0 { + return nil, errNoUsableInterfaces + } + if inboundBufferSize == 0 { + return nil, errNoPositiveMTUFound + } + if inboundBufferSize > maxPacketSize { + inboundBufferSize = maxPacketSize + } + if joinErrCount >= len(ifaces) { + return nil, errJoiningMulticastGroup + } + + dstAddr4, err := net.ResolveUDPAddr("udp4", destinationAddress4) + if err != nil { + return nil, err + } + + dstAddr6, err := net.ResolveUDPAddr("udp6", destinationAddress6) + if err != nil { + return nil, err + } + + var localNames []string + for _, l := range config.LocalNames { + localNames = append(localNames, l+".") + } + + c.dstAddr4 = dstAddr4 + c.dstAddr6 = dstAddr6 + c.localNames = localNames + c.ifaces = ifacesToUse + + if config.QueryInterval != 0 { + c.queryInterval = config.QueryInterval + } + + if multicastPktConnV4 != nil { + if err := multicastPktConnV4.SetControlMessage(ipv4.FlagInterface, true); err != nil { + c.log.Warnf("[%s] failed to SetControlMessage(ipv4.FlagInterface) on multicast IPv4 PacketConn %v", c.name, err) + } + if err := multicastPktConnV4.SetControlMessage(ipv4.FlagDst, true); err != nil { + c.log.Warnf("[%s] failed to SetControlMessage(ipv4.FlagDst) on multicast IPv4 PacketConn %v", c.name, err) + } + c.multicastPktConnV4 = ipPacketConn4{c.name, multicastPktConnV4, log} + } + if multicastPktConnV6 != nil { + if err := multicastPktConnV6.SetControlMessage(ipv6.FlagInterface, true); err != nil { + c.log.Warnf("[%s] failed to SetControlMessage(ipv6.FlagInterface) on multicast IPv6 PacketConn %v", c.name, err) + } + if err := multicastPktConnV6.SetControlMessage(ipv6.FlagDst, true); err != nil { + c.log.Warnf("[%s] failed to SetControlMessage(ipv6.FlagInterface) on multicast IPv6 PacketConn %v", c.name, err) + } + c.multicastPktConnV6 = ipPacketConn6{c.name, multicastPktConnV6, log} + } + if unicastPktConnV4 != nil { + if err := unicastPktConnV4.SetControlMessage(ipv4.FlagInterface, true); err != nil { + c.log.Warnf("[%s] failed to SetControlMessage(ipv4.FlagInterface) on unicast IPv4 PacketConn %v", c.name, err) + } + if err := unicastPktConnV4.SetControlMessage(ipv4.FlagDst, true); err != nil { + c.log.Warnf("[%s] failed to SetControlMessage(ipv4.FlagInterface) on unicast IPv4 PacketConn %v", c.name, err) + } + c.unicastPktConnV4 = ipPacketConn4{c.name, unicastPktConnV4, log} + } + if unicastPktConnV6 != nil { + if err := unicastPktConnV6.SetControlMessage(ipv6.FlagInterface, true); err != nil { + c.log.Warnf("[%s] failed to SetControlMessage(ipv6.FlagInterface) on unicast IPv6 PacketConn %v", c.name, err) + } + if err := unicastPktConnV6.SetControlMessage(ipv6.FlagDst, true); err != nil { + c.log.Warnf("[%s] failed to SetControlMessage(ipv6.FlagInterface) on unicast IPv6 PacketConn %v", c.name, err) + } + c.unicastPktConnV6 = ipPacketConn6{c.name, unicastPktConnV6, log} + } + + if config.IncludeLoopback { + // this is an efficient way for us to send ourselves a message faster instead of it going + // further out into the network stack. + if multicastPktConnV4 != nil { + if err := multicastPktConnV4.SetMulticastLoopback(true); err != nil { + c.log.Warnf("[%s] failed to SetMulticastLoopback(true) on multicast IPv4 PacketConn %v; this may cause inefficient network path c.name,communications", c.name, err) + } + } + if multicastPktConnV6 != nil { + if err := multicastPktConnV6.SetMulticastLoopback(true); err != nil { + c.log.Warnf("[%s] failed to SetMulticastLoopback(true) on multicast IPv6 PacketConn %v; this may cause inefficient network path c.name,communications", c.name, err) + } + } + if unicastPktConnV4 != nil { + if err := unicastPktConnV4.SetMulticastLoopback(true); err != nil { + c.log.Warnf("[%s] failed to SetMulticastLoopback(true) on unicast IPv4 PacketConn %v; this may cause inefficient network path c.name,communications", c.name, err) + } + } + if unicastPktConnV6 != nil { + if err := unicastPktConnV6.SetMulticastLoopback(true); err != nil { + c.log.Warnf("[%s] failed to SetMulticastLoopback(true) on unicast IPv6 PacketConn %v; this may cause inefficient network path c.name,communications", c.name, err) + } + } + } + + // https://www.rfc-editor.org/rfc/rfc6762.html#section-17 + // Multicast DNS messages carried by UDP may be up to the IP MTU of the + // physical interface, less the space required for the IP header (20 + // bytes for IPv4; 40 bytes for IPv6) and the UDP header (8 bytes). + started := make(chan struct{}) + go c.start(started, inboundBufferSize-20-8, config) + <-started + return c, nil +} + +// Close closes the mDNS Conn +func (c *Conn) Close() error { + select { + case <-c.closed: + return nil + default: + } + + // Once on go1.20, can use errors.Join + var errs []error + if c.multicastPktConnV4 != nil { + if err := c.multicastPktConnV4.Close(); err != nil { + errs = append(errs, err) + } + } + + if c.multicastPktConnV6 != nil { + if err := c.multicastPktConnV6.Close(); err != nil { + errs = append(errs, err) + } + } + + if c.unicastPktConnV4 != nil { + if err := c.unicastPktConnV4.Close(); err != nil { + errs = append(errs, err) + } + } + + if c.unicastPktConnV6 != nil { + if err := c.unicastPktConnV6.Close(); err != nil { + errs = append(errs, err) + } + } + + if len(errs) == 0 { + <-c.closed + return nil + } + + rtrn := errFailedToClose + for _, err := range errs { + rtrn = fmt.Errorf("%w\n%w", err, rtrn) + } + return rtrn +} + +// Query sends mDNS Queries for the following name until +// either the Context is canceled/expires or we get a result +// +// Deprecated: Use QueryAddr instead as it supports the easier to use netip.Addr. +func (c *Conn) Query(ctx context.Context, name string) (dnsmessage.ResourceHeader, net.Addr, error) { + header, addr, err := c.QueryAddr(ctx, name) + if err != nil { + return header, nil, err + } + return header, &net.IPAddr{ + IP: addr.AsSlice(), + Zone: addr.Zone(), + }, nil +} + +// QueryAddr sends mDNS Queries for the following name until +// either the Context is canceled/expires or we get a result +func (c *Conn) QueryAddr(ctx context.Context, name string) (dnsmessage.ResourceHeader, netip.Addr, error) { + select { + case <-c.closed: + return dnsmessage.ResourceHeader{}, netip.Addr{}, errConnectionClosed + default: + } + + nameWithSuffix := name + "." + + queryChan := make(chan queryResult, 1) + query := &query{nameWithSuffix, queryChan} + c.mu.Lock() + c.queries = append(c.queries, query) + c.mu.Unlock() + + defer func() { + c.mu.Lock() + defer c.mu.Unlock() + for i := len(c.queries) - 1; i >= 0; i-- { + if c.queries[i] == query { + c.queries = append(c.queries[:i], c.queries[i+1:]...) + } + } + }() + + ticker := time.NewTicker(c.queryInterval) + defer ticker.Stop() + + c.sendQuestion(nameWithSuffix) + for { + select { + case <-ticker.C: + c.sendQuestion(nameWithSuffix) + case <-c.closed: + return dnsmessage.ResourceHeader{}, netip.Addr{}, errConnectionClosed + case res := <-queryChan: + // Given https://datatracker.ietf.org/doc/html/draft-ietf-mmusic-mdns-ice-candidates#section-3.2.2-2 + // An ICE agent SHOULD ignore candidates where the hostname resolution returns more than one IP address. + // + // We will take the first we receive which could result in a race between two suitable addresses where + // one is better than the other (e.g. localhost vs LAN). + return res.answer, res.addr, nil + case <-ctx.Done(): + return dnsmessage.ResourceHeader{}, netip.Addr{}, errContextElapsed + } + } +} + +type ipToBytesError struct { + addr netip.Addr + expectedType string +} + +func (err ipToBytesError) Error() string { + return fmt.Sprintf("ip (%s) is not %s", err.addr, err.expectedType) +} + +// assumes ipv4-to-ipv6 mapping has been checked +func ipv4ToBytes(ipAddr netip.Addr) ([4]byte, error) { + if !ipAddr.Is4() { + return [4]byte{}, ipToBytesError{ipAddr, "IPv4"} + } + + md, err := ipAddr.MarshalBinary() + if err != nil { + return [4]byte{}, err + } + + // net.IPs are stored in big endian / network byte order + var out [4]byte + copy(out[:], md) + return out, nil +} + +// assumes ipv4-to-ipv6 mapping has been checked +func ipv6ToBytes(ipAddr netip.Addr) ([16]byte, error) { + if !ipAddr.Is6() { + return [16]byte{}, ipToBytesError{ipAddr, "IPv6"} + } + md, err := ipAddr.MarshalBinary() + if err != nil { + return [16]byte{}, err + } + + // net.IPs are stored in big endian / network byte order + var out [16]byte + copy(out[:], md) + return out, nil +} + +type ipToAddrError struct { + ip []byte +} + +func (err ipToAddrError) Error() string { + return fmt.Sprintf("failed to convert ip address '%s' to netip.Addr", err.ip) +} + +func interfaceForRemote(remote string) (*netip.Addr, error) { + conn, err := net.Dial("udp", remote) + if err != nil { + return nil, err + } + + localAddr, ok := conn.LocalAddr().(*net.UDPAddr) + if !ok { + return nil, errFailedCast + } + + if err := conn.Close(); err != nil { + return nil, err + } + + ipAddr, ok := netip.AddrFromSlice(localAddr.IP) + if !ok { + return nil, ipToAddrError{localAddr.IP} + } + ipAddr = addrWithOptionalZone(ipAddr, localAddr.Zone) + return &ipAddr, nil +} + +type writeType byte + +const ( + writeTypeQuestion writeType = iota + writeTypeAnswer +) + +func (c *Conn) sendQuestion(name string) { + packedName, err := dnsmessage.NewName(name) + if err != nil { + c.log.Warnf("[%s] failed to construct mDNS packet %v", c.name, err) + return + } + + // https://datatracker.ietf.org/doc/html/draft-ietf-rtcweb-mdns-ice-candidates-04#section-3.2.1 + // + // 2. Otherwise, resolve the candidate using mDNS. The ICE agent + // SHOULD set the unicast-response bit of the corresponding mDNS + // query message; this minimizes multicast traffic, as the response + // is probably only useful to the querying node. + // + // 18.12. Repurposing of Top Bit of qclass in Question Section + // + // In the Question Section of a Multicast DNS query, the top bit of the + // qclass field is used to indicate that unicast responses are preferred + // for this particular question. (See Section 5.4.) + // + // We'll follow this up sending on our unicast based packet connections so that we can + // get a unicast response back. + msg := dnsmessage.Message{ + Header: dnsmessage.Header{}, + } + + // limit what we ask for based on what IPv is available. In the future, + // this could be an option since there's no reason you cannot get an + // A record on an IPv6 sourced question and vice versa. + if c.multicastPktConnV4 != nil { + msg.Questions = append(msg.Questions, dnsmessage.Question{ + Type: dnsmessage.TypeA, + Class: dnsmessage.ClassINET | (1 << 15), + Name: packedName, + }) + } + if c.multicastPktConnV6 != nil { + msg.Questions = append(msg.Questions, dnsmessage.Question{ + Type: dnsmessage.TypeAAAA, + Class: dnsmessage.ClassINET | (1 << 15), + Name: packedName, + }) + } + + rawQuery, err := msg.Pack() + if err != nil { + c.log.Warnf("[%s] failed to construct mDNS packet %v", c.name, err) + return + } + + c.writeToSocket(-1, rawQuery, false, false, writeTypeQuestion, nil) +} + +//nolint:gocognit +func (c *Conn) writeToSocket( + ifIndex int, + b []byte, + hasLoopbackData bool, + hasIPv6Zone bool, + wType writeType, + unicastDst *net.UDPAddr, +) { + var dst4, dst6 net.Addr + if wType == writeTypeAnswer { + if unicastDst == nil { + dst4 = c.dstAddr4 + dst6 = c.dstAddr6 + } else { + if unicastDst.IP.To4() == nil { + dst6 = unicastDst + } else { + dst4 = unicastDst + } + } + } + + if ifIndex != -1 { + if wType == writeTypeQuestion { + c.log.Errorf("[%s] Unexpected question using specific interface index %d; dropping question", c.name, ifIndex) + return + } + + ifc, ok := c.ifaces[ifIndex] + if !ok { + c.log.Warnf("[%s] no interface for %d", c.name, ifIndex) + return + } + if hasLoopbackData && ifc.Flags&net.FlagLoopback == 0 { + // avoid accidentally tricking the destination that itself is the same as us + c.log.Debugf("[%s] interface is not loopback %d", c.name, ifIndex) + return + } + + c.log.Debugf("[%s] writing answer to IPv4: %v, IPv6: %v", c.name, dst4, dst6) + + if ifc.supportsV4 && c.multicastPktConnV4 != nil && dst4 != nil { + if !hasIPv6Zone { + if _, err := c.multicastPktConnV4.WriteTo(b, &ifc.Interface, nil, dst4); err != nil { + c.log.Warnf("[%s] failed to send mDNS packet on IPv4 interface %d: %v", c.name, ifIndex, err) + } + } else { + c.log.Debugf("[%s] refusing to send mDNS packet with IPv6 zone over IPv4", c.name) + } + } + if ifc.supportsV6 && c.multicastPktConnV6 != nil && dst6 != nil { + if _, err := c.multicastPktConnV6.WriteTo(b, &ifc.Interface, nil, dst6); err != nil { + c.log.Warnf("[%s] failed to send mDNS packet on IPv6 interface %d: %v", c.name, ifIndex, err) + } + } + + return + } + for ifcIdx := range c.ifaces { + ifc := c.ifaces[ifcIdx] + if hasLoopbackData { + c.log.Debugf("[%s] Refusing to send loopback data with non-specific interface", c.name) + continue + } + + if wType == writeTypeQuestion { + // we'll write via unicast if we can in case the responder chooses to respond to the address the request + // came from (i.e. not respecting unicast-response bit). If we were to use the multicast packet + // conn here, we'd be writing from a specific multicast address which won't be able to receive unicast + // traffic (it only works when listening on 0.0.0.0/[::]). + if c.unicastPktConnV4 == nil && c.unicastPktConnV6 == nil { + c.log.Debugf("[%s] writing question to multicast IPv4/6 %s", c.name, c.dstAddr4) + if ifc.supportsV4 && c.multicastPktConnV4 != nil { + if _, err := c.multicastPktConnV4.WriteTo(b, &ifc.Interface, nil, c.dstAddr4); err != nil { + c.log.Warnf("[%s] failed to send mDNS packet (multicast) on IPv4 interface %d: %v", c.name, ifc.Index, err) + } + } + if ifc.supportsV6 && c.multicastPktConnV6 != nil { + if _, err := c.multicastPktConnV6.WriteTo(b, &ifc.Interface, nil, c.dstAddr6); err != nil { + c.log.Warnf("[%s] failed to send mDNS packet (multicast) on IPv6 interface %d: %v", c.name, ifc.Index, err) + } + } + } + if ifc.supportsV4 && c.unicastPktConnV4 != nil { + c.log.Debugf("[%s] writing question to unicast IPv4 %s", c.name, c.dstAddr4) + if _, err := c.unicastPktConnV4.WriteTo(b, &ifc.Interface, nil, c.dstAddr4); err != nil { + c.log.Warnf("[%s] failed to send mDNS packet (unicast) on interface %d: %v", c.name, ifc.Index, err) + } + } + if ifc.supportsV6 && c.unicastPktConnV6 != nil { + c.log.Debugf("[%s] writing question to unicast IPv6 %s", c.name, c.dstAddr6) + if _, err := c.unicastPktConnV6.WriteTo(b, &ifc.Interface, nil, c.dstAddr6); err != nil { + c.log.Warnf("[%s] failed to send mDNS packet (unicast) on interface %d: %v", c.name, ifc.Index, err) + } + } + } else { + c.log.Debugf("[%s] writing answer to IPv4: %v, IPv6: %v", c.name, dst4, dst6) + + if ifc.supportsV4 && c.multicastPktConnV4 != nil && dst4 != nil { + if !hasIPv6Zone { + if _, err := c.multicastPktConnV4.WriteTo(b, &ifc.Interface, nil, dst4); err != nil { + c.log.Warnf("[%s] failed to send mDNS packet (multicast) on IPv4 interface %d: %v", c.name, ifIndex, err) + } + } else { + c.log.Debugf("[%s] refusing to send mDNS packet with IPv6 zone over IPv4", c.name) + } + } + if ifc.supportsV6 && c.multicastPktConnV6 != nil && dst6 != nil { + if _, err := c.multicastPktConnV6.WriteTo(b, &ifc.Interface, nil, dst6); err != nil { + c.log.Warnf("[%s] failed to send mDNS packet (multicast) on IPv6 interface %d: %v", c.name, ifIndex, err) + } + } + } + } +} + +func createAnswer(id uint16, name string, addr netip.Addr) (dnsmessage.Message, error) { + packedName, err := dnsmessage.NewName(name) + if err != nil { + return dnsmessage.Message{}, err + } + + msg := dnsmessage.Message{ + Header: dnsmessage.Header{ + ID: id, + Response: true, + Authoritative: true, + }, + Answers: []dnsmessage.Resource{ + { + Header: dnsmessage.ResourceHeader{ + Class: dnsmessage.ClassINET, + Name: packedName, + TTL: responseTTL, + }, + }, + }, + } + + if addr.Is4() { + ipBuf, err := ipv4ToBytes(addr) + if err != nil { + return dnsmessage.Message{}, err + } + msg.Answers[0].Header.Type = dnsmessage.TypeA + msg.Answers[0].Body = &dnsmessage.AResource{ + A: ipBuf, + } + } else if addr.Is6() { + // we will lose the zone here, but the receiver can reconstruct it + ipBuf, err := ipv6ToBytes(addr) + if err != nil { + return dnsmessage.Message{}, err + } + msg.Answers[0].Header.Type = dnsmessage.TypeAAAA + msg.Answers[0].Body = &dnsmessage.AAAAResource{ + AAAA: ipBuf, + } + } + + return msg, nil +} + +func (c *Conn) sendAnswer(queryID uint16, name string, ifIndex int, result netip.Addr, dst *net.UDPAddr) { + answer, err := createAnswer(queryID, name, result) + if err != nil { + c.log.Warnf("[%s] failed to create mDNS answer %v", c.name, err) + return + } + + rawAnswer, err := answer.Pack() + if err != nil { + c.log.Warnf("[%s] failed to construct mDNS packet %v", c.name, err) + return + } + + c.writeToSocket( + ifIndex, + rawAnswer, + result.IsLoopback(), + result.Is6() && result.Zone() != "", + writeTypeAnswer, + dst, + ) +} + +type ipControlMessage struct { + IfIndex int + Dst net.IP +} + +type ipPacketConn interface { + ReadFrom(b []byte) (n int, cm *ipControlMessage, src net.Addr, err error) + WriteTo(b []byte, via *net.Interface, cm *ipControlMessage, dst net.Addr) (n int, err error) + Close() error +} + +type ipPacketConn4 struct { + name string + conn *ipv4.PacketConn + log logging.LeveledLogger +} + +func (c ipPacketConn4) ReadFrom(b []byte) (n int, cm *ipControlMessage, src net.Addr, err error) { + n, cm4, src, err := c.conn.ReadFrom(b) + if err != nil || cm4 == nil { + return n, nil, src, err + } + return n, &ipControlMessage{IfIndex: cm4.IfIndex, Dst: cm4.Dst}, src, err +} + +func (c ipPacketConn4) WriteTo(b []byte, via *net.Interface, cm *ipControlMessage, dst net.Addr) (n int, err error) { + var cm4 *ipv4.ControlMessage + if cm != nil { + cm4 = &ipv4.ControlMessage{ + IfIndex: cm.IfIndex, + } + } + if err := c.conn.SetMulticastInterface(via); err != nil { + c.log.Warnf("[%s] failed to set multicast interface for %d: %v", c.name, via.Index, err) + return 0, err + } + return c.conn.WriteTo(b, cm4, dst) +} + +func (c ipPacketConn4) Close() error { + return c.conn.Close() +} + +type ipPacketConn6 struct { + name string + conn *ipv6.PacketConn + log logging.LeveledLogger +} + +func (c ipPacketConn6) ReadFrom(b []byte) (n int, cm *ipControlMessage, src net.Addr, err error) { + n, cm6, src, err := c.conn.ReadFrom(b) + if err != nil || cm6 == nil { + return n, nil, src, err + } + return n, &ipControlMessage{IfIndex: cm6.IfIndex, Dst: cm6.Dst}, src, err +} + +func (c ipPacketConn6) WriteTo(b []byte, via *net.Interface, cm *ipControlMessage, dst net.Addr) (n int, err error) { + var cm6 *ipv6.ControlMessage + if cm != nil { + cm6 = &ipv6.ControlMessage{ + IfIndex: cm.IfIndex, + } + } + if err := c.conn.SetMulticastInterface(via); err != nil { + c.log.Warnf("[%s] failed to set multicast interface for %d: %v", c.name, via.Index, err) + return 0, err + } + return c.conn.WriteTo(b, cm6, dst) +} + +func (c ipPacketConn6) Close() error { + return c.conn.Close() +} + +func (c *Conn) readLoop(name string, pktConn ipPacketConn, inboundBufferSize int, config *Config) { //nolint:gocognit + b := make([]byte, inboundBufferSize) + p := dnsmessage.Parser{} + + for { + n, cm, src, err := pktConn.ReadFrom(b) + if err != nil { + if errors.Is(err, net.ErrClosed) { + return + } + c.log.Warnf("[%s] failed to ReadFrom %q %v", c.name, src, err) + continue + } + c.log.Debugf("[%s] got read on %s from %s", c.name, name, src) + + var ifIndex int + var pktDst net.IP + if cm != nil { + ifIndex = cm.IfIndex + pktDst = cm.Dst + } else { + ifIndex = -1 + } + srcAddr, ok := src.(*net.UDPAddr) + if !ok { + c.log.Warnf("[%s] expected source address %s to be UDP but got %", c.name, src, src) + continue + } + + func() { + header, err := p.Start(b[:n]) + if err != nil { + c.log.Warnf("[%s] failed to parse mDNS packet %v", c.name, err) + return + } + + for i := 0; i <= maxMessageRecords; i++ { + q, err := p.Question() + if errors.Is(err, dnsmessage.ErrSectionDone) { + break + } else if err != nil { + c.log.Warnf("[%s] failed to parse mDNS packet %v", c.name, err) + return + } + + if q.Type != dnsmessage.TypeA && q.Type != dnsmessage.TypeAAAA { + continue + } + + // https://datatracker.ietf.org/doc/html/rfc6762#section-6 + // The destination UDP port in all Multicast DNS responses MUST be 5353, + // and the destination address MUST be the mDNS IPv4 link-local + // multicast address 224.0.0.251 or its IPv6 equivalent FF02::FB, except + // when generating a reply to a query that explicitly requested a + // unicast response + shouldUnicastResponse := (q.Class&(1<<15)) != 0 || // via the unicast-response bit + srcAddr.Port != 5353 || // by virtue of being a legacy query (Section 6.7), or + (len(pktDst) != 0 && !(pktDst.Equal(c.dstAddr4.IP) || // by virtue of being a direct unicast query + pktDst.Equal(c.dstAddr6.IP))) + var dst *net.UDPAddr + if shouldUnicastResponse { + dst = srcAddr + } + + queryWantsV4 := q.Type == dnsmessage.TypeA + + for _, localName := range c.localNames { + if localName == q.Name.String() { + var localAddress *netip.Addr + if config.LocalAddress != nil { + // this means the LocalAddress does not support link-local since + // we have no zone to set here. + ipAddr, ok := netip.AddrFromSlice(config.LocalAddress) + if !ok { + c.log.Warnf("[%s] failed to convert config.LocalAddress '%s' to netip.Addr", c.name, config.LocalAddress) + continue + } + if c.multicastPktConnV4 != nil { + // don't want mapping since we also support IPv4/A + ipAddr = ipAddr.Unmap() + } + localAddress = &ipAddr + } else { + // prefer the address of the interface if we know its index, but otherwise + // derive it from the address we read from. We do this because even if + // multicast loopback is in use or we send from a loopback interface, + // there are still cases where the IP packet will contain the wrong + // source IP (e.g. a LAN interface). + // For example, we can have a packet that has: + // Source: 192.168.65.3 + // Destination: 224.0.0.251 + // Interface Index: 1 + // Interface Addresses @ 1: [127.0.0.1/8 ::1/128] + if ifIndex != -1 { + ifc, ok := c.ifaces[ifIndex] + if !ok { + c.log.Warnf("[%s] no interface for %d", c.name, ifIndex) + return + } + var selectedAddrs []netip.Addr + for _, addr := range ifc.ipAddrs { + addrCopy := addr + + // match up respective IP types based on question + if queryWantsV4 { + if addrCopy.Is4In6() { + // we may allow 4-in-6, but the question wants an A record + addrCopy = addrCopy.Unmap() + } + if !addrCopy.Is4() { + continue + } + } else { // queryWantsV6 + if !addrCopy.Is6() { + continue + } + if !isSupportedIPv6(addrCopy, c.multicastPktConnV4 == nil) { + c.log.Debugf("[%s] interface %d address not a supported IPv6 address %s", c.name, ifIndex, &addrCopy) + continue + } + } + + selectedAddrs = append(selectedAddrs, addrCopy) + } + if len(selectedAddrs) == 0 { + c.log.Debugf("[%s] failed to find suitable IP for interface %d; deriving address from source address c.name,instead", c.name, ifIndex) + } else { + // choose the best match + var choice *netip.Addr + for _, option := range selectedAddrs { + optCopy := option + if option.Is4() { + // select first + choice = &optCopy + break + } + // we're okay with 4In6 for now but ideally we get a an actual IPv6. + // Maybe in the future we never want this but it does look like Docker + // can route IPv4 over IPv6. + if choice == nil { + choice = &optCopy + } else if !optCopy.Is4In6() { + choice = &optCopy + } + if !optCopy.Is4In6() { + break + } + // otherwise keep searching for an actual IPv6 + } + localAddress = choice + } + } + if ifIndex == -1 || localAddress == nil { + localAddress, err = interfaceForRemote(src.String()) + if err != nil { + c.log.Warnf("[%s] failed to get local interface to communicate with %s: %v", c.name, src.String(), err) + continue + } + } + } + if queryWantsV4 { + if !localAddress.Is4() { + c.log.Debugf("[%s] have IPv6 address %s to respond with but question is for A not c.name,AAAA", c.name, localAddress) + continue + } + } else { + if !localAddress.Is6() { + c.log.Debugf("[%s] have IPv4 address %s to respond with but question is for AAAA not c.name,A", c.name, localAddress) + continue + } + if !isSupportedIPv6(*localAddress, c.multicastPktConnV4 == nil) { + c.log.Debugf("[%s] got local interface address but not a supported IPv6 address %v", c.name, localAddress) + continue + } + } + + if dst != nil && len(dst.IP) == net.IPv4len && + localAddress.Is6() && + localAddress.Zone() != "" && + (localAddress.IsLinkLocalUnicast() || localAddress.IsLinkLocalMulticast()) { + // This case happens when multicast v4 picks up an AAAA question that has a zone + // in the address. Since we cannot send this zone over DNS (it's meaningless), + // the other side can only infer this via the response interface on the other + // side (some IPv6 interface). + c.log.Debugf("[%s] refusing to send link-local address %s to an IPv4 destination %s", c.name, localAddress, dst) + continue + } + c.log.Debugf("[%s] sending response for %s on ifc %d of %s to %s", c.name, q.Name, ifIndex, *localAddress, dst) + c.sendAnswer(header.ID, q.Name.String(), ifIndex, *localAddress, dst) + } + } + } + + for i := 0; i <= maxMessageRecords; i++ { + a, err := p.AnswerHeader() + if errors.Is(err, dnsmessage.ErrSectionDone) { + return + } + if err != nil { + c.log.Warnf("[%s] failed to parse mDNS packet %v", c.name, err) + return + } + + if a.Type != dnsmessage.TypeA && a.Type != dnsmessage.TypeAAAA { + continue + } + + c.mu.Lock() + queries := make([]*query, len(c.queries)) + copy(queries, c.queries) + c.mu.Unlock() + + var answered []*query + for _, query := range queries { + queryCopy := query + if queryCopy.nameWithSuffix == a.Name.String() { + addr, err := addrFromAnswerHeader(a, p) + if err != nil { + c.log.Warnf("[%s] failed to parse mDNS answer %v", c.name, err) + return + } + + resultAddr := *addr + // DNS records don't contain IPv6 zones. + // We're trusting that since we're on the same link, that we will only + // be sent link-local addresses from that source's interface's address. + // If it's not present, we're out of luck since we cannot rely on the + // interface zone to be the same as the source's. + resultAddr = addrWithOptionalZone(resultAddr, srcAddr.Zone) + + select { + case queryCopy.queryResultChan <- queryResult{a, resultAddr}: + answered = append(answered, queryCopy) + default: + } + } + } + + c.mu.Lock() + for queryIdx := len(c.queries) - 1; queryIdx >= 0; queryIdx-- { + for answerIdx := len(answered) - 1; answerIdx >= 0; answerIdx-- { + if c.queries[queryIdx] == answered[answerIdx] { + c.queries = append(c.queries[:queryIdx], c.queries[queryIdx+1:]...) + answered = append(answered[:answerIdx], answered[answerIdx+1:]...) + queryIdx-- + break + } + } + } + c.mu.Unlock() + } + }() + } +} + +func (c *Conn) start(started chan<- struct{}, inboundBufferSize int, config *Config) { + defer func() { + c.mu.Lock() + defer c.mu.Unlock() + close(c.closed) + }() + + var numReaders int + readerStarted := make(chan struct{}) + readerEnded := make(chan struct{}) + + if c.multicastPktConnV4 != nil { + numReaders++ + go func() { + defer func() { + readerEnded <- struct{}{} + }() + readerStarted <- struct{}{} + c.readLoop("multi4", c.multicastPktConnV4, inboundBufferSize, config) + }() + } + if c.multicastPktConnV6 != nil { + numReaders++ + go func() { + defer func() { + readerEnded <- struct{}{} + }() + readerStarted <- struct{}{} + c.readLoop("multi6", c.multicastPktConnV6, inboundBufferSize, config) + }() + } + if c.unicastPktConnV4 != nil { + numReaders++ + go func() { + defer func() { + readerEnded <- struct{}{} + }() + readerStarted <- struct{}{} + c.readLoop("uni4", c.unicastPktConnV4, inboundBufferSize, config) + }() + } + if c.unicastPktConnV6 != nil { + numReaders++ + go func() { + defer func() { + readerEnded <- struct{}{} + }() + readerStarted <- struct{}{} + c.readLoop("uni6", c.unicastPktConnV6, inboundBufferSize, config) + }() + } + for i := 0; i < numReaders; i++ { + <-readerStarted + } + close(started) + for i := 0; i < numReaders; i++ { + <-readerEnded + } +} + +func addrFromAnswerHeader(a dnsmessage.ResourceHeader, p dnsmessage.Parser) (addr *netip.Addr, err error) { + if a.Type == dnsmessage.TypeA { + resource, err := p.AResource() + if err != nil { + return nil, err + } + ipAddr, ok := netip.AddrFromSlice(resource.A[:]) + if !ok { + return nil, fmt.Errorf("failed to convert A record: %w", ipToAddrError{resource.A[:]}) + } + ipAddr = ipAddr.Unmap() // do not want 4-in-6 + addr = &ipAddr + } else { + resource, err := p.AAAAResource() + if err != nil { + return nil, err + } + ipAddr, ok := netip.AddrFromSlice(resource.AAAA[:]) + if !ok { + return nil, fmt.Errorf("failed to convert AAAA record: %w", ipToAddrError{resource.AAAA[:]}) + } + addr = &ipAddr + } + + return +} + +func isSupportedIPv6(addr netip.Addr, ipv6Only bool) bool { + if !addr.Is6() { + return false + } + // IPv4-mapped-IPv6 addresses cannot be connected to unless + // unmapped. + if !ipv6Only && addr.Is4In6() { + return false + } + return true +} + +func addrWithOptionalZone(addr netip.Addr, zone string) netip.Addr { + if zone == "" { + return addr + } + if addr.Is6() && (addr.IsLinkLocalUnicast() || addr.IsLinkLocalMulticast()) { + return addr.WithZone(zone) + } + return addr +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/mdns/errors.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/mdns/v2/errors.go similarity index 80% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/mdns/errors.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/mdns/v2/errors.go index 0a1b61240..f065e165f 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/mdns/errors.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/mdns/v2/errors.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package mdns import "errors" diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/mdns/v2/mdns.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/mdns/v2/mdns.go new file mode 100644 index 000000000..a76b16b65 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/mdns/v2/mdns.go @@ -0,0 +1,5 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + +// Package mdns implements mDNS (multicast DNS) +package mdns diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/renovate.json b/trunk/3rdparty/srs-bench/vendor/github.com/pion/mdns/v2/renovate.json similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/renovate.json rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/mdns/v2/renovate.json diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/.gitignore b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/.gitignore index f977e7485..6e2f206a9 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/.gitignore +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/.gitignore @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2023 The Pion community +# SPDX-License-Identifier: MIT + ### JetBrains IDE ### ##################### .idea/ diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/.golangci.yml b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/.golangci.yml index d7a88eca3..a3235bec2 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/.golangci.yml +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/.golangci.yml @@ -1,6 +1,13 @@ +# SPDX-FileCopyrightText: 2023 The Pion community +# SPDX-License-Identifier: MIT + +run: + timeout: 5m + linters-settings: govet: - check-shadowing: true + enable: + - shadow misspell: locale: US exhaustive: @@ -10,7 +17,14 @@ linters-settings: modules: - github.com/pkg/errors: recommendations: - - errors + - errors + forbidigo: + forbid: + - ^fmt.Print(f|ln)?$ + - ^log.(Panic|Fatal|Print)(f|ln)?$ + - ^os.Exit$ + - ^panic$ + - ^print(ln)?$ linters: enable: @@ -18,9 +32,7 @@ linters: - bidichk # Checks for dangerous unicode character sequences - bodyclose # checks whether HTTP response body is closed successfully - contextcheck # check the function whether use a non-inherited context - - deadcode # Finds unused code - decorder # check declaration order and count of types, constants, variables and functions - - depguard # Go linter that checks if package imports are in a list of acceptable packages - dogsled # Checks assignments with too many blank identifiers (e.g. x, _, _, _, := f()) - dupl # Tool for code clone detection - durationcheck # check for two durations multiplied together @@ -30,6 +42,7 @@ linters: - errorlint # errorlint is a linter for that can be used to find code that will cause problems with the error wrapping scheme introduced in Go 1.13. - exhaustive # check exhaustiveness of enum switch statements - exportloopref # checks for pointers to enclosing loop variables + - forbidigo # Forbids identifiers - forcetypeassert # finds forced type assertions - gci # Gci control golang package import order and make it always deterministic. - gochecknoglobals # Checks that no globals are present in Go code @@ -38,7 +51,7 @@ linters: - goconst # Finds repeated strings that could be replaced by a constant - gocritic # The most opinionated Go source code linter - godox # Tool for detection of FIXME, TODO and other comment keywords - - goerr113 # Golang linter to check the errors handling expressions + - err113 # Golang linter to check the errors handling expressions - gofmt # Gofmt checks whether code was gofmt-ed. By default this tool runs with -s option to check for code simplification - gofumpt # Gofumpt checks whether code was gofumpt-ed. - goheader # Checks is file header matches to pattern @@ -53,14 +66,12 @@ linters: - importas # Enforces consistent import aliases - ineffassign # Detects when assignments to existing variables are not used - misspell # Finds commonly misspelled English words in comments - - nakedret # Finds naked returns in functions greater than a specified function length - nilerr # Finds the code that returns nil even if it checks that the error is not nil. - nilnil # Checks that there is no simultaneous return of `nil` error and an invalid value. - noctx # noctx finds sending http request without context.Context - predeclared # find code that shadows one of Go's predeclared identifiers - revive # golint replacement, finds style mistakes - staticcheck # Staticcheck is a go vet on steroids, applying a ton of static analysis checks - - structcheck # Finds unused struct fields - stylecheck # Stylecheck is a replacement for golint - tagliatelle # Checks the struct tags. - tenv # tenv is analyzer that detects using os.Setenv instead of t.Setenv since Go1.17 @@ -69,24 +80,21 @@ linters: - unconvert # Remove unnecessary type conversions - unparam # Reports unused function parameters - unused # Checks Go code for unused constants, variables, functions and types - - varcheck # Finds unused global variables and constants - wastedassign # wastedassign finds wasted assignment statements - whitespace # Tool for detection of leading and trailing whitespace disable: + - depguard # Go linter that checks if package imports are in a list of acceptable packages - containedctx # containedctx is a linter that detects struct contained context.Context field - cyclop # checks function and package cyclomatic complexity - - exhaustivestruct # Checks if all struct's fields are initialized - - forbidigo # Forbids identifiers - funlen # Tool for detection of long functions - gocyclo # Computes and checks the cyclomatic complexity of functions - godot # Check if comments end in a period - gomnd # An analyzer to detect magic numbers. - - ifshort # Checks that your code uses short syntax for if-statements whenever possible - ireturn # Accept Interfaces, Return Concrete Types - lll # Reports long lines - maintidx # maintidx measures the maintainability index of each function. - makezero # Finds slice declarations with non-zero initial length - - maligned # Tool to detect Go structs that would take less memory if their fields were sorted + - nakedret # Finds naked returns in functions greater than a specified function length - nestif # Reports deeply nested if statements - nlreturn # nlreturn checks for a new line before return and branch statements to increase code clarity - nolintlint # Reports ill-formed or insufficient nolint directives @@ -103,17 +111,15 @@ linters: issues: exclude-use-default: false + exclude-dirs-use-default: false exclude-rules: - # Allow complex tests, better to be self contained - - path: _test\.go + # Allow complex tests and examples, better to be self contained + - path: (examples|main\.go|_test\.go) linters: + - forbidigo - gocognit - # Allow complex main function in examples - - path: examples - text: "of func `main` is high" + # Allow forbidden identifiers in CLI commands + - path: cmd linters: - - gocognit - -run: - skip-dirs-use-default: false + - forbidigo diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/.goreleaser.yml b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/.goreleaser.yml similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/.goreleaser.yml rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/.goreleaser.yml diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/AUTHORS.txt b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/AUTHORS.txt deleted file mode 100644 index 5d5a53cc2..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/AUTHORS.txt +++ /dev/null @@ -1,23 +0,0 @@ -# Thank you to everyone that made Pion possible. If you are interested in contributing -# we would love to have you https://github.com/pion/webrtc/wiki/Contributing -# -# This file is auto generated, using git to list all individuals contributors. -# see `.github/generate-authors.sh` for the scripting -Adam Roach -adwpc -aggresss -Atsushi Watanabe -cnderrauber -Gabor Pongracz -Hugo Arregui -Hugo Arregui -Juliusz Chroboczek -Kevin Wang -lllf -Luke Curley -Mathis Engelbart -Max Hawkins -Sean DuBois -Sean DuBois -Simone Gotti -Woodrow Douglass diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/LICENSE b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/LICENSE index ab602974d..491caf6b0 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/LICENSE +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/LICENSE @@ -1,21 +1,9 @@ MIT License -Copyright (c) 2018 +Copyright (c) 2023 The Pion community -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/README.md b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/README.md index ec82c3fa6..063574aa9 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/README.md +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/README.md @@ -9,8 +9,8 @@ Sourcegraph Widget Slack Widget
- Build Status - GoDoc + GitHub Workflow Status + Go Reference Coverage Status Go Report Card License: MIT @@ -23,14 +23,15 @@ See [DESIGN.md](DESIGN.md) for an overview of features and future goals. The library is used as a part of our WebRTC implementation. Please refer to that [roadmap](https://github.com/pion/webrtc/issues/9) to track our major milestones. ### Community -Pion has an active community on the [Golang Slack](https://invite.slack.golangbridge.org/). Sign up and join the **#pion** channel for discussions and support. You can also use [Pion mailing list](https://groups.google.com/forum/#!forum/pion). +Pion has an active community on the [Slack](https://pion.ly/slack). + +Follow the [Pion Twitter](https://twitter.com/_pion) for project updates and important WebRTC news. We are always looking to support **your projects**. Please reach out if you have something to build! - If you need commercial support or don't want to use public methods you can contact us at [team@pion.ly](mailto:team@pion.ly) ### Contributing -Check out the **[contributing wiki](https://github.com/pion/webrtc/wiki/Contributing)** to join the group of amazing people making this project possible: +Check out the [contributing wiki](https://github.com/pion/webrtc/wiki/Contributing) to join the group of amazing people making this project possible ### License MIT License - see [LICENSE](LICENSE) for full text diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/application_defined.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/application_defined.go new file mode 100644 index 000000000..77a119395 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/application_defined.go @@ -0,0 +1,122 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + +package rtcp + +import ( + "encoding/binary" +) + +// ApplicationDefined represents an RTCP application-defined packet. +type ApplicationDefined struct { + SubType uint8 + SSRC uint32 + Name string + Data []byte +} + +// DestinationSSRC returns the SSRC value for this packet. +func (a ApplicationDefined) DestinationSSRC() []uint32 { + return []uint32{a.SSRC} +} + +// Marshal serializes the application-defined struct into a byte slice with padding. +func (a ApplicationDefined) Marshal() ([]byte, error) { + dataLength := len(a.Data) + if dataLength > 0xFFFF-12 { + return nil, errAppDefinedDataTooLarge + } + if len(a.Name) != 4 { + return nil, errAppDefinedInvalidName + } + // Calculate the padding size to be added to make the packet length a multiple of 4 bytes. + paddingSize := 4 - (dataLength % 4) + if paddingSize == 4 { + paddingSize = 0 + } + + packetSize := a.MarshalSize() + header := Header{ + Type: TypeApplicationDefined, + Length: uint16((packetSize / 4) - 1), + Padding: paddingSize != 0, + Count: a.SubType, + } + + headerBytes, err := header.Marshal() + if err != nil { + return nil, err + } + + rawPacket := make([]byte, packetSize) + copy(rawPacket, headerBytes) + binary.BigEndian.PutUint32(rawPacket[4:8], a.SSRC) + copy(rawPacket[8:12], a.Name) + copy(rawPacket[12:], a.Data) + + // Add padding if necessary. + if paddingSize > 0 { + for i := 0; i < paddingSize; i++ { + rawPacket[12+dataLength+i] = byte(paddingSize) + } + } + + return rawPacket, nil +} + +// Unmarshal parses the given raw packet into an application-defined struct, handling padding. +func (a *ApplicationDefined) Unmarshal(rawPacket []byte) error { + /* + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + |V=2|P| subtype | PT=APP=204 | length | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | SSRC/CSRC | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | name (ASCII) | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | application-dependent data ... + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + header := Header{} + err := header.Unmarshal(rawPacket) + if err != nil { + return err + } + if len(rawPacket) < 12 { + return errPacketTooShort + } + + if int(header.Length+1)*4 != len(rawPacket) { + return errAppDefinedInvalidLength + } + + a.SubType = header.Count + a.SSRC = binary.BigEndian.Uint32(rawPacket[4:8]) + a.Name = string(rawPacket[8:12]) + + // Check for padding. + paddingSize := 0 + if header.Padding { + paddingSize = int(rawPacket[len(rawPacket)-1]) + if paddingSize > len(rawPacket)-12 { + return errWrongPadding + } + } + + a.Data = rawPacket[12 : len(rawPacket)-paddingSize] + + return nil +} + +// MarshalSize returns the size of the packet once marshaled +func (a *ApplicationDefined) MarshalSize() int { + dataLength := len(a.Data) + // Calculate the padding size to be added to make the packet length a multiple of 4 bytes. + paddingSize := 4 - (dataLength % 4) + if paddingSize == 4 { + paddingSize = 0 + } + return 12 + dataLength + paddingSize +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/codecov.yml b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/codecov.yml index 085200a48..263e4d45c 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/codecov.yml +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/codecov.yml @@ -3,6 +3,8 @@ # # It is automatically copied from https://github.com/pion/.goassets repository. # +# SPDX-FileCopyrightText: 2023 The Pion community +# SPDX-License-Identifier: MIT coverage: status: diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/compound_packet.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/compound_packet.go index 33448248d..a621c6117 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/compound_packet.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/compound_packet.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package rtcp import ( @@ -107,6 +110,15 @@ func (c CompoundPacket) Marshal() ([]byte, error) { return Marshal(p) } +// MarshalSize returns the size of the packet once marshaled +func (c CompoundPacket) MarshalSize() int { + l := 0 + for _, p := range c { + l += p.MarshalSize() + } + return l +} + // Unmarshal decodes a CompoundPacket from binary. func (c *CompoundPacket) Unmarshal(rawData []byte) error { out := make(CompoundPacket, 0) @@ -121,11 +133,7 @@ func (c *CompoundPacket) Unmarshal(rawData []byte) error { } *c = out - if err := c.Validate(); err != nil { - return err - } - - return nil + return c.Validate() } // DestinationSSRC returns the synchronization sources associated with this diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/doc.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/doc.go index a983c2e45..22f06cc85 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/doc.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/doc.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + /* Package rtcp implements encoding and decoding of RTCP packets according to RFCs 3550 and 5506. @@ -35,6 +38,5 @@ Encoding RTCP packets: } pliData, err := pkt.Marshal() // ... - */ package rtcp diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/errors.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/errors.go index ed5bd0029..05e6847f1 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/errors.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/errors.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package rtcp import "errors" @@ -19,6 +22,7 @@ var ( errSDESMissingType = errors.New("rtcp: sdes item missing type") errReasonTooLong = errors.New("rtcp: reason must be < 255 octets long") errBadVersion = errors.New("rtcp: invalid packet version") + errBadLength = errors.New("rtcp: invalid packet length") errWrongPadding = errors.New("rtcp: invalid padding value") errWrongFeedbackType = errors.New("rtcp: wrong feedback message type") errWrongPayloadType = errors.New("rtcp: wrong payload type") @@ -31,4 +35,7 @@ var ( errWrongChunkType = errors.New("rtcp: wrong chunk type") errBadStructMemberType = errors.New("rtcp: struct contains unexpected member type") errBadReadParameter = errors.New("rtcp: cannot read into non-pointer") + errAppDefinedInvalidLength = errors.New("rtcp: application defined type invalid length") + errAppDefinedDataTooLarge = errors.New("rtcp: application defined data is too large") + errAppDefinedInvalidName = errors.New("rtcp: application defined name must be 4 ASCII chars") ) diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/extended_report.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/extended_report.go index 62e576bb4..0f9ee2ccf 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/extended_report.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/extended_report.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package rtcp import ( @@ -10,8 +13,9 @@ import ( // more report blocks, each of which conveys a different kind of // information. // -// 0 1 2 3 -// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +// 0 1 2 3 +// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +// // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // |V=2|P|reserved | PT=XR=207 | length | // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ @@ -88,8 +92,9 @@ func (t BlockTypeType) String() string { // Loss RLE report blocks (RFC 3611 §4.1) and Duplicate RLE // report blocks (RFC 3611 §4.2). // -// 0 1 2 3 -// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +// 0 1 2 3 +// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +// // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // | BT = 1 or 2 | rsvd. | T | block length | // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ @@ -117,27 +122,27 @@ type rleReportBlock struct { // // Run Length Chunk: // -// 0 1 -// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// |C|R| run length | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// 0 1 +// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// |C|R| run length | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // // Bit Vector Chunk: // -// 0 1 -// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// |C| bit vector | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// 0 1 +// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// |C| bit vector | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // // Terminating Null Chunk: // -// 0 1 -// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// |0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0| -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// 0 1 +// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// |0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0| +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ type Chunk uint16 // LossRLEReportBlock is used to report information about packet @@ -234,8 +239,9 @@ func (c Chunk) Value() uint { // PacketReceiptTimesReportBlock represents a Packet Receipt Times // report block, as described in RFC 3611 section 4.3. // -// 0 1 2 3 -// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +// 0 1 2 3 +// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +// // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // | BT=3 | rsvd. | T | block length | // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ @@ -278,8 +284,9 @@ func (b *PacketReceiptTimesReportBlock) unpackBlockHeader() { // ReceiverReferenceTimeReportBlock encodes a Receiver Reference Time // report block as described in RFC 3611 section 4.4. // -// 0 1 2 3 -// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +// 0 1 2 3 +// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +// // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // | BT=4 | reserved | block length = 2 | // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ @@ -309,8 +316,9 @@ func (b *ReceiverReferenceTimeReportBlock) unpackBlockHeader() { // DLRRReportBlock encodes a DLRR Report Block as described in // RFC 3611 section 4.5. // -// 0 1 2 3 -// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +// 0 1 2 3 +// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +// // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // | BT=5 | reserved | block length | // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ @@ -357,8 +365,9 @@ func (b *DLRRReportBlock) unpackBlockHeader() { // StatisticsSummaryReportBlock encodes a Statistics Summary Report // Block as described in RFC 3611, section 4.6. // -// 0 1 2 3 -// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +// 0 1 2 3 +// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +// // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // | BT=6 |L|D|J|ToH|rsvd.| block length = 9 | // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ @@ -455,8 +464,9 @@ func (b *StatisticsSummaryReportBlock) unpackBlockHeader() { // VoIPMetricsReportBlock encodes a VoIP Metrics Report Block as described // in RFC 3611, section 4.7. // -// 0 1 2 3 -// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +// 0 1 2 3 +// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +// // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // | BT=7 | reserved | block length = 8 | // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ @@ -535,6 +545,11 @@ func (b *UnknownReportBlock) setupBlockHeader() { func (b *UnknownReportBlock) unpackBlockHeader() { } +// MarshalSize returns the size of the packet once marshaled +func (x ExtendedReport) MarshalSize() int { + return wireSize(x) +} + // Marshal encodes the ExtendedReport in binary func (x ExtendedReport) Marshal() ([]byte, error) { for _, p := range x.Reports { @@ -631,7 +646,8 @@ func (x *ExtendedReport) Unmarshal(b []byte) error { // DestinationSSRC returns an array of SSRC values that this packet refers to. func (x *ExtendedReport) DestinationSSRC() []uint32 { - ssrc := make([]uint32, 0) + ssrc := make([]uint32, 0, len(x.Reports)+1) + ssrc = append(ssrc, x.SenderSSRC) for _, p := range x.Reports { ssrc = append(ssrc, p.DestinationSSRC()...) } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/full_intra_request.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/full_intra_request.go index 74ca928d6..7c67c5043 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/full_intra_request.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/full_intra_request.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package rtcp import ( @@ -64,6 +67,11 @@ func (p *FullIntraRequest) Unmarshal(rawPacket []byte) error { return errWrongType } + // The FCI field MUST contain one or more FIR entries + if 4*h.Length-firOffset <= 0 || (4*h.Length)%8 != 0 { + return errBadLength + } + p.SenderSSRC = binary.BigEndian.Uint32(rawPacket[headerLength:]) p.MediaSSRC = binary.BigEndian.Uint32(rawPacket[headerLength+ssrcLength:]) for i := headerLength + firOffset; i < (headerLength + int(h.Length*4)); i += 8 { @@ -80,11 +88,12 @@ func (p *FullIntraRequest) Header() Header { return Header{ Count: FormatFIR, Type: TypePayloadSpecificFeedback, - Length: uint16((p.len() / 4) - 1), + Length: uint16((p.MarshalSize() / 4) - 1), } } -func (p *FullIntraRequest) len() int { +// MarshalSize returns the size of the packet once marshaled +func (p *FullIntraRequest) MarshalSize() int { return headerLength + firOffset + len(p.FIR)*8 } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/fuzz.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/fuzz.go deleted file mode 100644 index b8118224a..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/fuzz.go +++ /dev/null @@ -1,52 +0,0 @@ -//go:build gofuzz -// +build gofuzz - -package rtcp - -import ( - "bytes" - "io" -) - -// Fuzz implements a randomized fuzz test of the rtcp -// parser using go-fuzz. -// -// To run the fuzzer, first download go-fuzz: -// `go get github.com/dvyukov/go-fuzz/...` -// -// Then build the testing package: -// `go-fuzz-build github.com/pion/webrtc` -// -// And run the fuzzer on the corpus: -// ``` -// mkdir workdir -// -// # optionally add a starter corpus of valid rtcp packets. -// # the corpus should be as compact and diverse as possible. -// cp -r ~/my-rtcp-packets workdir/corpus -// -// go-fuzz -bin=ase-fuzz.zip -workdir=workdir -// ```` -func Fuzz(data []byte) int { - r := NewReader(bytes.NewReader(data)) - for { - _, data, err := r.ReadPacket() - if err == io.EOF { - break - } - if err != nil { - return 0 - } - - packet, err := Unmarshal(data) - if err != nil { - return 0 - } - - if _, err := packet.Marshal(); err != nil { - return 0 - } - } - - return 1 -} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/goodbye.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/goodbye.go index 0d09199b1..f87731c07 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/goodbye.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/goodbye.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package rtcp import ( @@ -29,7 +32,7 @@ func (g Goodbye) Marshal() ([]byte, error) { * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ - rawPacket := make([]byte, g.len()) + rawPacket := make([]byte, g.MarshalSize()) packetBody := rawPacket[headerLength:] if len(g.Sources) > countMax { @@ -123,13 +126,18 @@ func (g *Goodbye) Header() Header { Padding: false, Count: uint8(len(g.Sources)), Type: TypeGoodbye, - Length: uint16((g.len() / 4) - 1), + Length: uint16((g.MarshalSize() / 4) - 1), } } -func (g *Goodbye) len() int { +// MarshalSize returns the size of the packet once marshaled +func (g *Goodbye) MarshalSize() int { srcsLength := len(g.Sources) * ssrcLength - reasonLength := len(g.Reason) + 1 + // reason is optional + reasonLength := len(g.Reason) + if reasonLength > 0 { + reasonLength++ + } l := headerLength + srcsLength + reasonLength diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/header.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/header.go index 43f6abc06..534c82f2e 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/header.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/header.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package rtcp import ( diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/packet.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/packet.go index 885d52cde..fc3c9a3cf 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/packet.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/packet.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package rtcp // Packet represents an RTCP packet, a protocol used for out-of-band statistics and control information for an RTP session @@ -7,6 +10,7 @@ type Packet interface { Marshal() ([]byte, error) Unmarshal(rawPacket []byte) error + MarshalSize() int } // Unmarshal takes an entire udp datagram (which may consist of multiple RTCP packets) and @@ -110,6 +114,9 @@ func unmarshal(rawData []byte) (packet Packet, bytesprocessed int, err error) { case TypeExtendedReport: packet = new(ExtendedReport) + case TypeApplicationDefined: + packet = new(ApplicationDefined) + default: packet = new(RawPacket) } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/packet_buffer.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/packet_buffer.go index 9febe9d43..f6c7eaa96 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/packet_buffer.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/packet_buffer.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package rtcp import ( @@ -43,7 +46,6 @@ const omit = "omit" // PacketBuffer is initialized with. This function will // modify the PacketBuffer.bytes slice to exclude those // bytes that have been written into. -// func (b *packetBuffer) write(v interface{}) error { //nolint:gocognit value := reflect.ValueOf(v) diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/packet_stringifier.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/packet_stringifier.go index 888372e15..dd7c01f51 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/packet_stringifier.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/packet_stringifier.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package rtcp import ( @@ -6,26 +9,26 @@ import ( ) /* - Converts an RTCP Packet into a human-readable format. The Packets - themselves can control the presentation as follows: +Converts an RTCP Packet into a human-readable format. The Packets +themselves can control the presentation as follows: - - Fields of a type that have a String() method will be formatted - with that String method (which should not emit '\n' characters) + - Fields of a type that have a String() method will be formatted + with that String method (which should not emit '\n' characters) - - Otherwise, fields with a tag containing a "fmt" string will use that - format when serializing the value. For example, to format an SSRC - value as base 16 insted of base 10: + - Otherwise, fields with a tag containing a "fmt" string will use that + format when serializing the value. For example, to format an SSRC + value as base 16 insted of base 10: - type ExamplePacket struct { - LocalSSRC uint32 `fmt:"0x%X"` - RemotsSSRCs []uint32 `fmt:"%X"` - } + type ExamplePacket struct { + LocalSSRC uint32 `fmt:"0x%X"` + RemotsSSRCs []uint32 `fmt:"%X"` + } - - If no fmt string is present, "%+v" is used by default +- If no fmt string is present, "%+v" is used by default - The intention of this stringify() function is to simplify creation - of String() methods on new packet types, as it provides a simple - baseline implementation that works well in the majority of cases. +The intention of this stringify() function is to simplify creation +of String() methods on new packet types, as it provides a simple +baseline implementation that works well in the majority of cases. */ func stringify(p Packet) string { value := reflect.Indirect(reflect.ValueOf(p)) diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/picture_loss_indication.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/picture_loss_indication.go index 86d4cf1b9..56a7de256 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/picture_loss_indication.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/picture_loss_indication.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package rtcp import ( @@ -26,7 +29,7 @@ func (p PictureLossIndication) Marshal() ([]byte, error) { * * The semantics of this FB message is independent of the payload type. */ - rawPacket := make([]byte, p.len()) + rawPacket := make([]byte, p.MarshalSize()) packetBody := rawPacket[headerLength:] binary.BigEndian.PutUint32(packetBody, p.SenderSSRC) @@ -75,7 +78,8 @@ func (p *PictureLossIndication) Header() Header { } } -func (p *PictureLossIndication) len() int { +// MarshalSize returns the size of the packet once marshaled +func (p *PictureLossIndication) MarshalSize() int { return headerLength + ssrcLength*2 } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/rapid_resynchronization_request.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/rapid_resynchronization_request.go index 00c7e8626..dc67d4928 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/rapid_resynchronization_request.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/rapid_resynchronization_request.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package rtcp import ( @@ -32,7 +35,7 @@ func (p RapidResynchronizationRequest) Marshal() ([]byte, error) { * * The semantics of this FB message is independent of the payload type. */ - rawPacket := make([]byte, p.len()) + rawPacket := make([]byte, p.MarshalSize()) packetBody := rawPacket[headerLength:] binary.BigEndian.PutUint32(packetBody, p.SenderSSRC) @@ -67,7 +70,8 @@ func (p *RapidResynchronizationRequest) Unmarshal(rawPacket []byte) error { return nil } -func (p *RapidResynchronizationRequest) len() int { +// MarshalSize returns the size of the packet once marshaled +func (p *RapidResynchronizationRequest) MarshalSize() int { return headerLength + rrrHeaderLength } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/raw_packet.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/raw_packet.go index d0f949030..eafb034fe 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/raw_packet.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/raw_packet.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package rtcp import "fmt" @@ -40,3 +43,8 @@ func (r RawPacket) String() string { out := fmt.Sprintf("RawPacket: %v", ([]byte)(r)) return out } + +// MarshalSize returns the size of the packet once marshaled +func (r RawPacket) MarshalSize() int { + return len(r) +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/receiver_estimated_maximum_bitrate.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/receiver_estimated_maximum_bitrate.go index 69d1194b4..7be57e6ab 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/receiver_estimated_maximum_bitrate.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/receiver_estimated_maximum_bitrate.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package rtcp import ( @@ -39,9 +42,8 @@ func (p ReceiverEstimatedMaximumBitrate) Marshal() (buf []byte, err error) { return buf, nil } -// MarshalSize returns the size of the packet when marshaled. -// This can be used in conjunction with `MarshalTo` to avoid allocations. -func (p ReceiverEstimatedMaximumBitrate) MarshalSize() (n int) { +// MarshalSize returns the size of the packet once marshaled +func (p ReceiverEstimatedMaximumBitrate) MarshalSize() int { return 20 + 4*len(p.SSRCs) } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/receiver_report.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/receiver_report.go index 22ff233be..e91770206 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/receiver_report.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/receiver_report.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package rtcp import ( @@ -55,7 +58,7 @@ func (r ReceiverReport) Marshal() ([]byte, error) { * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ - rawPacket := make([]byte, r.len()) + rawPacket := make([]byte, r.MarshalSize()) packetBody := rawPacket[headerLength:] binary.BigEndian.PutUint32(packetBody, r.SSRC) @@ -154,7 +157,8 @@ func (r *ReceiverReport) Unmarshal(rawPacket []byte) error { return nil } -func (r *ReceiverReport) len() int { +// MarshalSize returns the size of the packet once marshaled +func (r *ReceiverReport) MarshalSize() int { repsLength := 0 for _, rep := range r.Reports { repsLength += rep.len() @@ -167,7 +171,7 @@ func (r *ReceiverReport) Header() Header { return Header{ Count: uint8(len(r.Reports)), Type: TypeReceiverReport, - Length: uint16((r.len()/4)-1) + uint16(getPadding(len(r.ProfileExtensions))), + Length: uint16((r.MarshalSize()/4)-1) + uint16(getPadding(len(r.ProfileExtensions))), } } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/reception_report.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/reception_report.go index 5bff8f2b5..c0b06059c 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/reception_report.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/reception_report.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package rtcp import "encoding/binary" diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/renovate.json b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/renovate.json index f1614058a..f1bb98c6a 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/renovate.json +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/renovate.json @@ -1,27 +1,6 @@ { + "$schema": "https://docs.renovatebot.com/renovate-schema.json", "extends": [ - "config:base", - ":disableDependencyDashboard" - ], - "postUpdateOptions": [ - "gomodTidy" - ], - "commitBody": "Generated by renovateBot", - "packageRules": [ - { - "matchUpdateTypes": ["minor", "patch", "pin", "digest"], - "automerge": true - }, - { - "packagePatterns": ["^golang.org/x/"], - "schedule": ["on the first day of the month"] - } - ], - "ignorePaths": [ - ".github/workflows/generate-authors.yml", - ".github/workflows/lint.yaml", - ".github/workflows/renovate-go-mod-fix.yaml", - ".github/workflows/test.yaml", - ".github/workflows/tidy-check.yaml" + "github>pion/renovate-config" ] } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/rfc8888.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/rfc8888.go index 8527fc8e7..544c6e380 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/rfc8888.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/rfc8888.go @@ -1,9 +1,13 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package rtcp import ( "encoding/binary" "errors" "fmt" + "math" ) // https://www.rfc-editor.org/rfc/rfc8888.html#name-rtcp-congestion-control-fee @@ -89,8 +93,13 @@ func (b CCFeedbackReport) DestinationSSRC() []uint32 { } // Len returns the length of the report in bytes -func (b *CCFeedbackReport) Len() uint16 { - n := uint16(0) +func (b *CCFeedbackReport) Len() int { + return b.MarshalSize() +} + +// MarshalSize returns the size of the packet once marshaled +func (b *CCFeedbackReport) MarshalSize() int { + n := 0 for _, block := range b.ReportBlocks { n += block.len() } @@ -103,7 +112,7 @@ func (b *CCFeedbackReport) Header() Header { Padding: false, Count: FormatCCFB, Type: TypeTransportSpecificFeedback, - Length: b.Len()/4 - 1, + Length: uint16(b.MarshalSize()/4 - 1), } } @@ -118,7 +127,7 @@ func (b CCFeedbackReport) Marshal() ([]byte, error) { buf := make([]byte, length) copy(buf[:headerLength], headerBuf) binary.BigEndian.PutUint32(buf[headerLength:], b.SenderSSRC) - offset := uint16(reportBlockOffset) + offset := reportBlockOffset for _, block := range b.ReportBlocks { b, err := block.marshal() if err != nil { @@ -160,10 +169,10 @@ func (b *CCFeedbackReport) Unmarshal(rawPacket []byte) error { b.SenderSSRC = binary.BigEndian.Uint32(rawPacket[headerLength:]) - reportTimestampOffset := uint16(len(rawPacket) - reportTimestampLength) + reportTimestampOffset := len(rawPacket) - reportTimestampLength b.ReportTimestamp = binary.BigEndian.Uint32(rawPacket[reportTimestampOffset:]) - offset := uint16(reportBlockOffset) + offset := reportBlockOffset b.ReportBlocks = []CCFeedbackReportBlock{} for offset < reportTimestampOffset { var block CCFeedbackReportBlock @@ -195,12 +204,12 @@ type CCFeedbackReportBlock struct { } // len returns the length of the report block in bytes -func (b *CCFeedbackReportBlock) len() uint16 { +func (b *CCFeedbackReportBlock) len() int { n := len(b.MetricBlocks) if n%2 != 0 { n++ } - return reportsOffset + 2*uint16(n) + return reportsOffset + 2*n } func (b CCFeedbackReportBlock) String() string { @@ -253,14 +262,20 @@ func (b *CCFeedbackReportBlock) unmarshal(rawPacket []byte) error { if numReportsField == 0 { return nil } - endSequence := b.BeginSequence + numReportsField - numReports := endSequence - b.BeginSequence + 1 - if len(rawPacket) < int(reportsOffset+numReports*2) { + if int(b.BeginSequence)+int(numReportsField) > math.MaxUint16 { return errIncorrectNumReports } + + endSequence := b.BeginSequence + numReportsField + numReports := int(endSequence - b.BeginSequence + 1) + + if len(rawPacket) < reportsOffset+numReports*2 { + return errIncorrectNumReports + } + b.MetricBlocks = make([]CCFeedbackMetricBlock, numReports) - for i := uint16(0); i < numReports; i++ { + for i := int(0); i < numReports; i++ { var mb CCFeedbackMetricBlock offset := reportsOffset + 2*i if err := mb.unmarshal(rawPacket[offset : offset+2]); err != nil { diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/sender_report.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/sender_report.go index 8e0beeccd..aaee0ee9d 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/sender_report.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/sender_report.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package rtcp import ( @@ -93,7 +96,7 @@ func (r SenderReport) Marshal() ([]byte, error) { * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ - rawPacket := make([]byte, r.len()) + rawPacket := make([]byte, r.MarshalSize()) packetBody := rawPacket[headerLength:] binary.BigEndian.PutUint32(packetBody[srSSRCOffset:], r.SSRC) @@ -225,7 +228,8 @@ func (r *SenderReport) DestinationSSRC() []uint32 { return out } -func (r *SenderReport) len() int { +// MarshalSize returns the size of the packet once marshaled +func (r *SenderReport) MarshalSize() int { repsLength := 0 for _, rep := range r.Reports { repsLength += rep.len() @@ -238,7 +242,7 @@ func (r *SenderReport) Header() Header { return Header{ Count: uint8(len(r.Reports)), Type: TypeSenderReport, - Length: uint16((r.len() / 4) - 1), + Length: uint16((r.MarshalSize() / 4) - 1), } } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/slice_loss_indication.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/slice_loss_indication.go index ccd93c998..014fcb7cd 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/slice_loss_indication.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/slice_loss_indication.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package rtcp import ( @@ -90,7 +93,8 @@ func (p *SliceLossIndication) Unmarshal(rawPacket []byte) error { return nil } -func (p *SliceLossIndication) len() int { +// MarshalSize returns the size of the packet once marshaled +func (p *SliceLossIndication) MarshalSize() int { return headerLength + sliOffset + (len(p.SLI) * 4) } @@ -99,7 +103,7 @@ func (p *SliceLossIndication) Header() Header { return Header{ Count: FormatSLI, Type: TypeTransportSpecificFeedback, - Length: uint16((p.len() / 4) - 1), + Length: uint16((p.MarshalSize() / 4) - 1), } } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/source_description.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/source_description.go index c4483c301..fc29d8e1a 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/source_description.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/source_description.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package rtcp import ( @@ -94,7 +97,7 @@ func (s SourceDescription) Marshal() ([]byte, error) { * +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ */ - rawPacket := make([]byte, s.len()) + rawPacket := make([]byte, s.MarshalSize()) packetBody := rawPacket[headerLength:] chunkOffset := 0 @@ -166,7 +169,8 @@ func (s *SourceDescription) Unmarshal(rawPacket []byte) error { return nil } -func (s *SourceDescription) len() int { +// MarshalSize returns the size of the packet once marshaled +func (s *SourceDescription) MarshalSize() int { chunksLength := 0 for _, c := range s.Chunks { chunksLength += c.len() @@ -179,7 +183,7 @@ func (s *SourceDescription) Header() Header { return Header{ Count: uint8(len(s.Chunks)), Type: TypeSourceDescription, - Length: uint16((s.len() / 4) - 1), + Length: uint16((s.MarshalSize() / 4) - 1), } } @@ -248,7 +252,7 @@ func (s *SourceDescriptionChunk) Unmarshal(rawPacket []byte) error { return err } s.Items = append(s.Items, it) - i += it.len() + i += it.Len() } return errPacketTooShort @@ -257,7 +261,7 @@ func (s *SourceDescriptionChunk) Unmarshal(rawPacket []byte) error { func (s SourceDescriptionChunk) len() int { chunkLen := sdesSourceLen for _, it := range s.Items { - chunkLen += it.len() + chunkLen += it.Len() } chunkLen += sdesTypeLen // for terminating null octet @@ -277,7 +281,8 @@ type SourceDescriptionItem struct { Text string } -func (s SourceDescriptionItem) len() int { +// Len returns the length of the SourceDescriptionItem when encoded as binary. +func (s SourceDescriptionItem) Len() int { /* * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/transport_layer_cc.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/transport_layer_cc.go index 013902163..84ead7dd3 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/transport_layer_cc.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/transport_layer_cc.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package rtcp // Author: adwpc @@ -360,13 +363,18 @@ func (t *TransportLayerCC) packetLen() uint16 { // Len return total bytes with padding func (t *TransportLayerCC) Len() uint16 { + return uint16(t.MarshalSize()) +} + +// MarshalSize returns the size of the packet once marshaled +func (t *TransportLayerCC) MarshalSize() int { n := t.packetLen() // has padding if n%4 != 0 { n = (n/4 + 1) * 4 } - return n + return int(n) } func (t TransportLayerCC) String() string { @@ -396,7 +404,7 @@ func (t TransportLayerCC) Marshal() ([]byte, error) { return nil, err } - payload := make([]byte, t.Len()-headerLength) + payload := make([]byte, t.MarshalSize()-headerLength) binary.BigEndian.PutUint32(payload, t.SenderSSRC) binary.BigEndian.PutUint32(payload[4:], t.MediaSSRC) binary.BigEndian.PutUint16(payload[baseSequenceNumberOffset:], t.BaseSequenceNumber) @@ -427,7 +435,7 @@ func (t TransportLayerCC) Marshal() ([]byte, error) { } if t.Header.Padding { - payload[len(payload)-1] = uint8(t.Len() - t.packetLen()) + payload[len(payload)-1] = uint8(t.MarshalSize() - int(t.packetLen())) } return append(header, payload...), nil @@ -483,7 +491,7 @@ func (t *TransportLayerCC) Unmarshal(rawPacket []byte) error { //nolint:gocognit return err } - packetNumberToProcess := min(t.PacketStatusCount-processedPacketNum, packetStatus.RunLength) + packetNumberToProcess := localMin(t.PacketStatusCount-processedPacketNum, packetStatus.RunLength) if packetStatus.PacketStatusSymbol == TypeTCCPacketReceivedSmallDelta || packetStatus.PacketStatusSymbol == TypeTCCPacketReceivedLargeDelta { for j := uint16(0); j < packetNumberToProcess; j++ { @@ -520,10 +528,10 @@ func (t *TransportLayerCC) Unmarshal(rawPacket []byte) error { //nolint:gocognit recvDeltasPos := packetStatusPos for _, delta := range t.RecvDeltas { - if recvDeltasPos >= totalLength { - return errPacketTooShort - } if delta.Type == TypeTCCPacketReceivedSmallDelta { + if recvDeltasPos+1 > totalLength { + return errPacketTooShort + } err := delta.Unmarshal(rawPacket[recvDeltasPos : recvDeltasPos+1]) if err != nil { return err @@ -531,6 +539,9 @@ func (t *TransportLayerCC) Unmarshal(rawPacket []byte) error { //nolint:gocognit recvDeltasPos++ } if delta.Type == TypeTCCPacketReceivedLargeDelta { + if recvDeltasPos+2 > totalLength { + return errPacketTooShort + } err := delta.Unmarshal(rawPacket[recvDeltasPos : recvDeltasPos+2]) if err != nil { return err @@ -547,7 +558,7 @@ func (t TransportLayerCC) DestinationSSRC() []uint32 { return []uint32{t.MediaSSRC} } -func min(x, y uint16) uint16 { +func localMin(x, y uint16) uint16 { if x < y { return x } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/transport_layer_nack.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/transport_layer_nack.go index ab0c03d9d..802b915ec 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/transport_layer_nack.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/transport_layer_nack.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package rtcp import ( @@ -132,6 +135,11 @@ func (p *TransportLayerNack) Unmarshal(rawPacket []byte) error { return errWrongType } + // The FCI field MUST contain at least one and MAY contain more than one Generic NACK + if 4*h.Length <= nackOffset { + return errBadLength + } + p.SenderSSRC = binary.BigEndian.Uint32(rawPacket[headerLength:]) p.MediaSSRC = binary.BigEndian.Uint32(rawPacket[headerLength+ssrcLength:]) for i := headerLength + nackOffset; i < (headerLength + int(h.Length*4)); i += 4 { @@ -143,7 +151,8 @@ func (p *TransportLayerNack) Unmarshal(rawPacket []byte) error { return nil } -func (p *TransportLayerNack) len() int { +// MarshalSize returns the size of the packet once marshaled +func (p *TransportLayerNack) MarshalSize() int { return headerLength + nackOffset + (len(p.Nacks) * 4) } @@ -152,7 +161,7 @@ func (p *TransportLayerNack) Header() Header { return Header{ Count: FormatTLN, Type: TypeTransportSpecificFeedback, - Length: uint16((p.len() / 4) - 1), + Length: uint16((p.MarshalSize() / 4) - 1), } } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/util.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/util.go index 95e8f1a83..c68cebef5 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/util.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtcp/util.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package rtcp // getPadding Returns the padding required to make the length a multiple of 4 diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/.gitignore b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/.gitignore index f977e7485..6e2f206a9 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/.gitignore +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/.gitignore @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2023 The Pion community +# SPDX-License-Identifier: MIT + ### JetBrains IDE ### ##################### .idea/ diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/.golangci.yml b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/.golangci.yml index d6162c970..120faf29b 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/.golangci.yml +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/.golangci.yml @@ -1,6 +1,13 @@ +# SPDX-FileCopyrightText: 2023 The Pion community +# SPDX-License-Identifier: MIT + +run: + timeout: 5m + linters-settings: govet: - check-shadowing: true + enable: + - shadow misspell: locale: US exhaustive: @@ -10,80 +17,129 @@ linters-settings: modules: - github.com/pkg/errors: recommendations: - - errors + - errors + forbidigo: + analyze-types: true + forbid: + - ^fmt.Print(f|ln)?$ + - ^log.(Panic|Fatal|Print)(f|ln)?$ + - ^os.Exit$ + - ^panic$ + - ^print(ln)?$ + - p: ^testing.T.(Error|Errorf|Fatal|Fatalf|Fail|FailNow)$ + pkg: ^testing$ + msg: "use testify/assert instead" + varnamelen: + max-distance: 12 + min-name-length: 2 + ignore-type-assert-ok: true + ignore-map-index-ok: true + ignore-chan-recv-ok: true + ignore-decls: + - i int + - n int + - w io.Writer + - r io.Reader + - b []byte linters: enable: - asciicheck # Simple linter to check that your code does not contain non-ASCII identifiers + - bidichk # Checks for dangerous unicode character sequences - bodyclose # checks whether HTTP response body is closed successfully - - deadcode # Finds unused code - - depguard # Go linter that checks if package imports are in a list of acceptable packages + - containedctx # containedctx is a linter that detects struct contained context.Context field + - contextcheck # check the function whether use a non-inherited context + - cyclop # checks function and package cyclomatic complexity + - decorder # check declaration order and count of types, constants, variables and functions - dogsled # Checks assignments with too many blank identifiers (e.g. x, _, _, _, := f()) - dupl # Tool for code clone detection + - durationcheck # check for two durations multiplied together + - err113 # Golang linter to check the errors handling expressions - errcheck # Errcheck is a program for checking for unchecked errors in go programs. These unchecked errors can be critical bugs in some cases + - errchkjson # Checks types passed to the json encoding functions. Reports unsupported types and optionally reports occations, where the check for the returned error can be omitted. + - errname # Checks that sentinel errors are prefixed with the `Err` and error types are suffixed with the `Error`. + - errorlint # errorlint is a linter for that can be used to find code that will cause problems with the error wrapping scheme introduced in Go 1.13. - exhaustive # check exhaustiveness of enum switch statements - exportloopref # checks for pointers to enclosing loop variables + - forbidigo # Forbids identifiers + - forcetypeassert # finds forced type assertions - gci # Gci control golang package import order and make it always deterministic. - gochecknoglobals # Checks that no globals are present in Go code - - gochecknoinits # Checks that no init functions are present in Go code - gocognit # Computes and checks the cognitive complexity of functions - goconst # Finds repeated strings that could be replaced by a constant - gocritic # The most opinionated Go source code linter + - gocyclo # Computes and checks the cyclomatic complexity of functions + - godot # Check if comments end in a period - godox # Tool for detection of FIXME, TODO and other comment keywords - - goerr113 # Golang linter to check the errors handling expressions - gofmt # Gofmt checks whether code was gofmt-ed. By default this tool runs with -s option to check for code simplification - gofumpt # Gofumpt checks whether code was gofumpt-ed. - goheader # Checks is file header matches to pattern - goimports # Goimports does everything that gofmt does. Additionally it checks unused imports - - golint # Golint differs from gofmt. Gofmt reformats Go source code, whereas golint prints out style mistakes - - gomodguard # Allow and block list linter for direct Go module dependencies. This is different from depguard where there are different block types for example version constraints and module recommendations. + - gomoddirectives # Manage the use of 'replace', 'retract', and 'excludes' directives in go.mod. - goprintffuncname # Checks that printf-like functions are named with `f` at the end - gosec # Inspects source code for security problems - gosimple # Linter for Go source code that specializes in simplifying a code - govet # Vet examines Go source code and reports suspicious constructs, such as Printf calls whose arguments do not align with the format string + - grouper # An analyzer to analyze expression groups. + - importas # Enforces consistent import aliases - ineffassign # Detects when assignments to existing variables are not used + - lll # Reports long lines + - maintidx # maintidx measures the maintainability index of each function. + - makezero # Finds slice declarations with non-zero initial length - misspell # Finds commonly misspelled English words in comments - nakedret # Finds naked returns in functions greater than a specified function length + - nestif # Reports deeply nested if statements + - nilerr # Finds the code that returns nil even if it checks that the error is not nil. + - nilnil # Checks that there is no simultaneous return of `nil` error and an invalid value. + - nlreturn # nlreturn checks for a new line before return and branch statements to increase code clarity - noctx # noctx finds sending http request without context.Context - - scopelint # Scopelint checks for unpinned variables in go programs + - predeclared # find code that shadows one of Go's predeclared identifiers + - revive # golint replacement, finds style mistakes - staticcheck # Staticcheck is a go vet on steroids, applying a ton of static analysis checks - - structcheck # Finds unused struct fields - stylecheck # Stylecheck is a replacement for golint + - tagliatelle # Checks the struct tags. + - tenv # tenv is analyzer that detects using os.Setenv instead of t.Setenv since Go1.17 + - thelper # thelper detects golang test helpers without t.Helper() call and checks the consistency of test helpers - typecheck # Like the front-end of a Go compiler, parses and type-checks Go code - unconvert # Remove unnecessary type conversions - unparam # Reports unused function parameters - unused # Checks Go code for unused constants, variables, functions and types - - varcheck # Finds unused global variables and constants + - varnamelen # checks that the length of a variable's name matches its scope + - wastedassign # wastedassign finds wasted assignment statements - whitespace # Tool for detection of leading and trailing whitespace disable: + - depguard # Go linter that checks if package imports are in a list of acceptable packages - funlen # Tool for detection of long functions - - gocyclo # Computes and checks the cyclomatic complexity of functions - - godot # Check if comments end in a period - - gomnd # An analyzer to detect magic numbers. - - lll # Reports long lines - - maligned # Tool to detect Go structs that would take less memory if their fields were sorted - - nestif # Reports deeply nested if statements - - nlreturn # nlreturn checks for a new line before return and branch statements to increase code clarity + - gochecknoinits # Checks that no init functions are present in Go code + - gomodguard # Allow and block list linter for direct Go module dependencies. This is different from depguard where there are different block types for example version constraints and module recommendations. + - interfacebloat # A linter that checks length of interface. + - ireturn # Accept Interfaces, Return Concrete Types + - mnd # An analyzer to detect magic numbers - nolintlint # Reports ill-formed or insufficient nolint directives + - paralleltest # paralleltest detects missing usage of t.Parallel() method in your Go test - prealloc # Finds slice declarations that could potentially be preallocated + - promlinter # Check Prometheus metrics naming via promlint - rowserrcheck # checks whether Err of rows is checked successfully - sqlclosecheck # Checks that sql.Rows and sql.Stmt are closed. - testpackage # linter that makes you use a separate _test package + - tparallel # tparallel detects inappropriate usage of t.Parallel() method in your Go test codes + - wrapcheck # Checks that errors returned from external packages are wrapped - wsl # Whitespace Linter - Forces you to use empty lines! issues: exclude-use-default: false + exclude-dirs-use-default: false exclude-rules: - # Allow complex tests, better to be self contained + # Allow complex tests and examples, better to be self contained + - path: (examples|main\.go) + linters: + - gocognit + - forbidigo - path: _test\.go linters: - gocognit - # Allow complex main function in examples - - path: examples - text: "of func `main` is high" + # Allow forbidden identifiers in CLI commands + - path: cmd linters: - - gocognit - -run: - skip-dirs-use-default: false + - forbidigo diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/.goreleaser.yml b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/.goreleaser.yml new file mode 100644 index 000000000..30093e9d6 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/.goreleaser.yml @@ -0,0 +1,5 @@ +# SPDX-FileCopyrightText: 2023 The Pion community +# SPDX-License-Identifier: MIT + +builds: +- skip: true diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/AUTHORS.txt b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/AUTHORS.txt deleted file mode 100644 index a7bc7a02b..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/AUTHORS.txt +++ /dev/null @@ -1,36 +0,0 @@ -# Thank you to everyone that made Pion possible. If you are interested in contributing -# we would love to have you https://github.com/pion/webrtc/wiki/Contributing -# -# This file is auto generated, using git to list all individuals contributors. -# see `.github/generate-authors.sh` for the scripting -adwpc -aler9 <46489434+aler9@users.noreply.github.com> -Antoine Baché -Antoine Baché -Atsushi Watanabe -baiyufei -Bao Nguyen -boks1971 -debiandebiandebian -ffmiyo -Guilherme -Haiyang Wang -Hugo Arregui -John Bradley -Juliusz Chroboczek -Kazuyuki Honda -Luke Curley -lxb -Michael MacDonald -Michael MacDonald -Michael Uti -Raphael Derosso Pereira -Rob Lofthouse -Robin Raymond -Sean DuBois -Sean DuBois -Sean DuBois -Simone Gotti -Tarrence van As -wangzixiang -Woodrow Douglass diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/LICENSE b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/LICENSE index ab602974d..2071b23b0 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/LICENSE +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/LICENSE @@ -1,21 +1,9 @@ MIT License -Copyright (c) 2018 +Copyright (c) -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/README.md b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/README.md index ce04599a8..11b720a67 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/README.md +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/README.md @@ -7,10 +7,10 @@

Pion RTP Sourcegraph Widget - Slack Widget + join us on Discord Follow us on Bluesky
- Build Status - GoDoc + GitHub Workflow Status + Go Reference Coverage Status Go Report Card License: MIT @@ -21,14 +21,15 @@ The library is used as a part of our WebRTC implementation. Please refer to that [roadmap](https://github.com/pion/webrtc/issues/9) to track our major milestones. ### Community -Pion has an active community on the [Golang Slack](https://invite.slack.golangbridge.org/). Sign up and join the **#pion** channel for discussions and support. You can also use [Pion mailing list](https://groups.google.com/forum/#!forum/pion). +Pion has an active community on the [Discord](https://discord.gg/PngbdqpFbt). + +Follow the [Pion Bluesky](https://bsky.app/profile/pion.ly) or [Pion Twitter](https://twitter.com/_pion) for project updates and important WebRTC news. We are always looking to support **your projects**. Please reach out if you have something to build! - If you need commercial support or don't want to use public methods you can contact us at [team@pion.ly](mailto:team@pion.ly) ### Contributing -Check out the **[contributing wiki](https://github.com/pion/webrtc/wiki/Contributing)** to join the group of amazing people making this project possible: +Check out the [contributing wiki](https://github.com/pion/webrtc/wiki/Contributing) to join the group of amazing people making this project possible ### License MIT License - see [LICENSE](LICENSE) for full text diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/abscapturetimeextension.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/abscapturetimeextension.go new file mode 100644 index 000000000..68b43ca22 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/abscapturetimeextension.go @@ -0,0 +1,115 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + +package rtp + +import ( + "encoding/binary" + "time" +) + +const ( + absCaptureTimeExtensionSize = 8 + absCaptureTimeExtendedExtensionSize = 16 +) + +// AbsCaptureTimeExtension is a extension payload format in. +// http://www.webrtc.org/experiments/rtp-hdrext/abs-capture-time +// 0 1 2 3 +// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | ID | len=7 | absolute capture timestamp (bit 0-23) | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | absolute capture timestamp (bit 24-55) | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | ... (56-63) | +// +-+-+-+-+-+-+-+-+ +// . +type AbsCaptureTimeExtension struct { + Timestamp uint64 + EstimatedCaptureClockOffset *int64 +} + +// Marshal serializes the members to buffer. +func (t AbsCaptureTimeExtension) Marshal() ([]byte, error) { + if t.EstimatedCaptureClockOffset != nil { + buf := make([]byte, 16) + binary.BigEndian.PutUint64(buf[0:8], t.Timestamp) + binary.BigEndian.PutUint64(buf[8:16], uint64(*t.EstimatedCaptureClockOffset)) // nolint: gosec // G115 + + return buf, nil + } + buf := make([]byte, 8) + binary.BigEndian.PutUint64(buf[0:8], t.Timestamp) + + return buf, nil +} + +// Unmarshal parses the passed byte slice and stores the result in the members. +func (t *AbsCaptureTimeExtension) Unmarshal(rawData []byte) error { + if len(rawData) < absCaptureTimeExtensionSize { + return errTooSmall + } + t.Timestamp = binary.BigEndian.Uint64(rawData[0:8]) + if len(rawData) >= absCaptureTimeExtendedExtensionSize { + offset := int64(binary.BigEndian.Uint64(rawData[8:16])) // nolint: gosec // G115 false positive + t.EstimatedCaptureClockOffset = &offset + } + + return nil +} + +// CaptureTime produces the estimated time.Time represented by this extension. +func (t AbsCaptureTimeExtension) CaptureTime() time.Time { + return toTime(t.Timestamp) +} + +// EstimatedCaptureClockOffsetDuration produces the estimated time.Duration represented by this extension. +func (t AbsCaptureTimeExtension) EstimatedCaptureClockOffsetDuration() *time.Duration { + if t.EstimatedCaptureClockOffset == nil { + return nil + } + offset := *t.EstimatedCaptureClockOffset + negative := false + if offset < 0 { + offset = -offset + negative = true + } + duration := time.Duration(offset/(1<<32))*time.Second + time.Duration((offset&0xFFFFFFFF)*1e9/(1<<32))*time.Nanosecond + if negative { + duration = -duration + } + + return &duration +} + +// NewAbsCaptureTimeExtension makes new AbsCaptureTimeExtension from time.Time. +func NewAbsCaptureTimeExtension(captureTime time.Time) *AbsCaptureTimeExtension { + return &AbsCaptureTimeExtension{ + Timestamp: toNtpTime(captureTime), + } +} + +// NewAbsCaptureTimeExtensionWithCaptureClockOffset makes new AbsCaptureTimeExtension from time.Time and a clock offset. +func NewAbsCaptureTimeExtensionWithCaptureClockOffset( + captureTime time.Time, + captureClockOffset time.Duration, +) *AbsCaptureTimeExtension { + ns := captureClockOffset.Nanoseconds() + negative := false + if ns < 0 { + ns = -ns + negative = true + } + lsb := (ns / 1e9) & 0xFFFFFFFF + msb := (((ns % 1e9) * (1 << 32)) / 1e9) & 0xFFFFFFFF + offset := (lsb << 32) | msb + if negative { + offset = -offset + } + + return &AbsCaptureTimeExtension{ + Timestamp: toNtpTime(captureTime), + EstimatedCaptureClockOffset: &offset, + } +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/abssendtimeextension.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/abssendtimeextension.go index f0c6de375..d66e47c96 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/abssendtimeextension.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/abssendtimeextension.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package rtp import ( @@ -29,6 +32,7 @@ func (t *AbsSendTimeExtension) Unmarshal(rawData []byte) error { return errTooSmall } t.Timestamp = uint64(rawData[0])<<16 | uint64(rawData[1])<<8 | uint64(rawData[2]) + return nil } @@ -55,7 +59,7 @@ func NewAbsSendTimeExtension(sendTime time.Time) *AbsSendTimeExtension { func toNtpTime(t time.Time) uint64 { var s uint64 var f uint64 - u := uint64(t.UnixNano()) + u := uint64(t.UnixNano()) // nolint: gosec // G115 false positive s = u / 1e9 s += 0x83AA7E80 // offset in seconds between unix epoch and ntp epoch f = u % 1e9 @@ -74,5 +78,5 @@ func toTime(t uint64) time.Time { s -= 0x83AA7E80 u := s*1e9 + f - return time.Unix(0, int64(u)) + return time.Unix(0, int64(u)) // nolint: gosec // G115 false positive } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/audiolevelextension.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/audiolevelextension.go index ca44f2870..cc2e65291 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/audiolevelextension.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/audiolevelextension.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package rtp import ( @@ -5,7 +8,7 @@ import ( ) const ( - // audioLevelExtensionSize One byte header size + // audioLevelExtensionSize One byte header size. audioLevelExtensionSize = 1 ) @@ -30,12 +33,14 @@ var errAudioLevelOverflow = errors.New("audio level overflow") // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // | ID | len=1 |V| level | 0 (pad) | // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// +//nolint:lll type AudioLevelExtension struct { Level uint8 Voice bool } -// Marshal serializes the members to buffer +// Marshal serializes the members to buffer. func (a AudioLevelExtension) Marshal() ([]byte, error) { if a.Level > 127 { return nil, errAudioLevelOverflow @@ -46,15 +51,17 @@ func (a AudioLevelExtension) Marshal() ([]byte, error) { } buf := make([]byte, audioLevelExtensionSize) buf[0] = voice | a.Level + return buf, nil } -// Unmarshal parses the passed byte slice and stores the result in the members +// Unmarshal parses the passed byte slice and stores the result in the members. func (a *AudioLevelExtension) Unmarshal(rawData []byte) error { if len(rawData) < audioLevelExtensionSize { return errTooSmall } a.Level = rawData[0] & 0x7F a.Voice = rawData[0]&0x80 != 0 + return nil } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecov.yml b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecov.yml index 085200a48..263e4d45c 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecov.yml +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecov.yml @@ -3,6 +3,8 @@ # # It is automatically copied from https://github.com/pion/.goassets repository. # +# SPDX-FileCopyrightText: 2023 The Pion community +# SPDX-License-Identifier: MIT coverage: status: diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/av1/obu/errors.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/av1/obu/errors.go new file mode 100644 index 000000000..eeba3a4fe --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/av1/obu/errors.go @@ -0,0 +1,14 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + +package obu + +import "errors" + +var ( + // ErrInvalidOBUHeader is returned when an OBU header has forbidden bits set. + ErrInvalidOBUHeader = errors.New("invalid OBU header") + // ErrShortHeader is returned when an OBU header is not large enough. + // This can happen when an extension header is expected but not present. + ErrShortHeader = errors.New("OBU header is not large enough") +) diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/pkg/obu/leb128.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/av1/obu/leb128.go similarity index 64% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/pkg/obu/leb128.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/av1/obu/leb128.go index 988a8f442..56b9ff0fd 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/pkg/obu/leb128.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/av1/obu/leb128.go @@ -1,4 +1,7 @@ -// Package obu implements tools for working with the "Open Bitstream Unit" +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + +// Package obu implements tools for working with the Open Bitstream Unit. package obu import "errors" @@ -8,10 +11,10 @@ const ( msbBitmask = uint(0b10000000) ) -// ErrFailedToReadLEB128 indicates that a buffer ended before a LEB128 value could be successfully read +// ErrFailedToReadLEB128 indicates that a buffer ended before a LEB128 value could be successfully read. var ErrFailedToReadLEB128 = errors.New("payload ended before LEB128 was finished") -// EncodeLEB128 encodes a uint as LEB128 +// EncodeLEB128 encodes a uint as LEB128. func EncodeLEB128(in uint) (out uint) { for { // Copy seven bits from in and discard @@ -47,7 +50,7 @@ func decodeLEB128(in uint) (out uint) { // ReadLeb128 scans an buffer and decodes a Leb128 value. // If the end of the buffer is reached and all MSB are set -// an error is returned +// an error is returned. func ReadLeb128(in []byte) (uint, uint, error) { var encodedLength uint @@ -55,7 +58,7 @@ func ReadLeb128(in []byte) (uint, uint, error) { encodedLength |= uint(in[i]) if in[i]&byte(msbBitmask) == 0 { - return decodeLEB128(encodedLength), uint(i + 1), nil + return decodeLEB128(encodedLength), uint(i + 1), nil // nolint: gosec // G115 } // Make more room for next read @@ -64,3 +67,19 @@ func ReadLeb128(in []byte) (uint, uint, error) { return 0, 0, ErrFailedToReadLEB128 } + +// WriteToLeb128 writes a uint to a LEB128 encoded byte slice. +func WriteToLeb128(in uint) []byte { + b := make([]byte, 10) + + for i := 0; i < len(b); i++ { + b[i] = byte(in & 0x7f) + in >>= 7 + if in == 0 { + return b[:i+1] + } + b[i] |= 0x80 + } + + return b // unreachable +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/av1/obu/obu.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/av1/obu/obu.go new file mode 100644 index 000000000..6bc91f177 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/av1/obu/obu.go @@ -0,0 +1,219 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + +package obu + +import ( + "fmt" +) + +// Type represents the type of an AV1 OBU. +type Type uint8 + +// OBU types as defined in the AV1 specification. +// 5.3.1: https://aomediacodec.github.io/av1-spec/av1-spec.pdf#page=39 +const ( + // OBUSequenceHeader av1 sequence_header_obu. + OBUSequenceHeader = Type(1) + // OBUTemporalDelimiter av1 temporal_delimiter_obu. + OBUTemporalDelimiter = Type(2) + // OBUFrameHeader av1 frame_header_obu. + OBUFrameHeader = Type(3) + // OBUTileGroup av1 tile_group_obu. + OBUTileGroup = Type(4) + // OBUMetadata av1 metadata_obu. + OBUMetadata = Type(5) + // OBUFrame av1 frame_obu. + OBUFrame = Type(6) + // OBURedundantFrameHeader av1 redundant_frame_header_obu. + OBURedundantFrameHeader = Type(7) + // OBUTileList av1 tile_list_obu. + OBUTileList = Type(8) + // OBUPadding av1 padding_obu. + OBUPadding = Type(15) +) + +//nolint:cyclop +func (o Type) String() string { + switch o { + case OBUSequenceHeader: + return "OBU_SEQUENCE_HEADER" + case OBUTemporalDelimiter: + return "OBU_TEMPORAL_DELIMITER" + case OBUFrameHeader: + return "OBU_FRAME_HEADER" + case OBUTileGroup: + return "OBU_TILE_GROUP" + case OBUMetadata: + return "OBU_METADATA" + case OBUFrame: + return "OBU_FRAME" + case OBURedundantFrameHeader: + return "OBU_REDUNDANT_FRAME_HEADER" + case OBUTileList: + return "OBU_TILE_LIST" + case OBUPadding: + return "OBU_PADDING" + default: + return "OBU_RESERVED" + } +} + +// Header represents the header of an OBU obu_header(). +// 5.3.2: https://aomediacodec.github.io/av1-spec/av1-spec.pdf#page=40 +type Header struct { + Type Type + ExtensionHeader *ExtensionHeader + HasSizeField bool + Reserved1Bit bool +} + +// ParseOBUHeader parses an OBU header from the given data. +// 5.3.2: https://aomediacodec.github.io/av1-spec/av1-spec.pdf#page=40 +/* + obu_header() { Type + obu_forbidden_bit f(1) + obu_type f(4) + obu_extension_flag f(1) + obu_has_size_field f(1) + obu_reserved_1bit f(1) + if ( obu_extension_flag == 1 ) + obu_extension_header() + } + } +*/ +func ParseOBUHeader(data []byte) (*Header, error) { + if len(data) < 1 { + return nil, fmt.Errorf("%w: data is too short", ErrShortHeader) + } + + forbiddenBit := data[0] & 0x80 + if forbiddenBit != 0 { + return nil, fmt.Errorf("%w: forbidden bit is set", ErrInvalidOBUHeader) + } + + obuType := Type((data[0] & 0x78) >> 3) + obuExtensionFlag := (data[0] & 0x04) != 0 + obuHasSizeField := (data[0] & 0x02) != 0 + obuReserved1Bit := (data[0] & 0x01) != 0 + + header := &Header{ + Type: obuType, + HasSizeField: obuHasSizeField, + Reserved1Bit: obuReserved1Bit, + } + + if obuExtensionFlag { + if len(data) < 2 { + return nil, fmt.Errorf("%w: Unexpected end of data, expected extension header", ErrShortHeader) + } + + extensionHeader := ParseOBUExtensionHeader(data[1]) + header.ExtensionHeader = &extensionHeader + } + + return header, nil +} + +// Marshal serializes the OBU header to a byte slice. +// If the OBU has an extension header, the extension header is serialized as well. +// 5.3.2: https://aomediacodec.github.io/av1-spec/av1-spec.pdf#page=40 +/* + obu_header() { Type + obu_forbidden_bit f(1) + obu_type f(4) + obu_extension_flag f(1) + obu_has_size_field f(1) + obu_reserved_1bit f(1) + if ( obu_extension_flag == 1 ) + obu_extension_header() + } + } +*/ +func (o *Header) Marshal() []byte { + header := make([]byte, o.Size()) + + header[0] = (byte(o.Type) & 0x0f) << 3 + + if o.ExtensionHeader != nil { + header[0] |= 0x04 + header[1] = o.ExtensionHeader.Marshal() + } + + if o.HasSizeField { + header[0] |= 0x02 + } + + if o.Reserved1Bit { + header[0] |= 0x01 + } + + return header +} + +// Size returns the size of the OBU header in bytes. +func (o *Header) Size() int { + size := 1 + if o.ExtensionHeader != nil { + size++ + } + + return size +} + +// ExtensionHeader represents an OBU extension header obu_extension_header(). +// 5.3.3 https://aomediacodec.github.io/av1-spec/av1-spec.pdf#page=40 +type ExtensionHeader struct { + TemporalID uint8 + SpatialID uint8 + Reserved3Bits uint8 +} + +// ParseOBUExtensionHeader parses an OBU extension header from the given data. +// 5.3.3 https://aomediacodec.github.io/av1-spec/av1-spec.pdf#page=40 +/* + obu_extension_header() { Type + temporal_id f(3) + spatial_id f(2) + extension_header_reserved_3bits f(3) + } +*/ +func ParseOBUExtensionHeader(headerData byte) ExtensionHeader { + return ExtensionHeader{ + TemporalID: headerData >> 5, + SpatialID: (headerData >> 3) & 0x03, + Reserved3Bits: headerData & 0x07, + } +} + +// Marshal serializes the OBU extension header to a byte slice. +// 5.3.3 https://aomediacodec.github.io/av1-spec/av1-spec.pdf#page=40 +/* + obu_extension_header() { Type + temporal_id f(3) + spatial_id f(2) + extension_header_reserved_3bits f(3) + } +*/ +func (o *ExtensionHeader) Marshal() byte { + return (o.TemporalID << 5) | ((o.SpatialID & 0x3) << 3) | (o.Reserved3Bits & 0x07) +} + +// OBU represents an AV1 OBU. +// 5.1 https://aomediacodec.github.io/av1-spec/av1-spec.pdf#page=39 +type OBU struct { + Header Header + Payload []byte +} + +// Marshal serializes the OBU to low-overhead bitstream format. +// 5.2 https://aomediacodec.github.io/av1-spec/av1-spec.pdf#page=40 +func (o *OBU) Marshal() []byte { + buffer := o.Header.Marshal() + + if o.Header.HasSizeField { + buffer = append(buffer, WriteToLeb128(uint(len(o.Payload)))...) + } + + return append(buffer, o.Payload...) +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/av1_depacketizer.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/av1_depacketizer.go new file mode 100644 index 000000000..bc83231d3 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/av1_depacketizer.go @@ -0,0 +1,188 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + +package codecs + +import ( + "fmt" + + "github.com/pion/rtp/codecs/av1/obu" +) + +// AV1Depacketizer is a AV1 RTP Packet depacketizer. +// Reads AV1 packets from a RTP stream and outputs AV1 low overhead bitstream. +type AV1Depacketizer struct { + // holds the fragmented OBU from the previous packet. + buffer []byte + + // Z, Y, N are flags from the AV1 Aggregation Header. + Z, Y, N bool + + videoDepacketizer +} + +// Unmarshal parses an AV1 RTP payload into its constituent OBUs stream with obu_size_field, +// It assumes that the payload is in order (e.g. the caller is responsible for reordering RTP packets). +// If the last OBU in the payload is fragmented, it will be stored in the buffer until the +// it is completed. +// +//nolint:gocognit,cyclop +func (d *AV1Depacketizer) Unmarshal(payload []byte) (buff []byte, err error) { + buff = make([]byte, 0) + + if len(payload) <= 1 { + return nil, errShortPacket + } + + // |Z|Y| W |N|-|-|-| + obuZ := (av1ZMask & payload[0]) != 0 // Z + obuY := (av1YMask & payload[0]) != 0 // Y + obuCount := (av1WMask & payload[0]) >> 4 // W + obuN := (av1NMask & payload[0]) != 0 // N + d.Z = obuZ + d.Y = obuY + d.N = obuN + if obuN { + d.buffer = nil + } + + // Make sure we clear the buffer if Z is not 0. + if !obuZ && len(d.buffer) > 0 { + d.buffer = nil + } + + obuOffset := 0 + for offset := 1; offset < len(payload); obuOffset++ { + isFirst := obuOffset == 0 + isLast := obuCount != 0 && obuOffset == int(obuCount)-1 + + // https://aomediacodec.github.io/av1-rtp-spec/#44-av1-aggregation-header + // W: two bit field that describes the number of OBU elements in the packet. + // This field MUST be set equal to 0 or equal to the number of OBU elements contained in the packet. + // If set to 0, each OBU element MUST be preceded by a length field. If not set to 0 + // (i.e., W = 1, 2 or 3) the last OBU element MUST NOT be preceded by a length field. + var lengthField, n int + if obuCount == 0 || !isLast { + obuSizeVal, nVal, err := obu.ReadLeb128(payload[offset:]) + lengthField = int(obuSizeVal) //nolint:gosec // G115 false positive + n = int(nVal) //nolint:gosec // G115 false positive + if err != nil { + return nil, err + } + + offset += n + if obuCount == 0 && offset+lengthField == len(payload) { + isLast = true + } + } else { + // https://aomediacodec.github.io/av1-rtp-spec/#44-av1-aggregation-header + // Length of the last OBU element = + // length of the RTP payload + // - length of aggregation header + // - length of previous OBU elements including length fields + lengthField = len(payload) - offset + } + + if offset+lengthField > len(payload) { + return nil, fmt.Errorf( + "%w: OBU size %d + %d offset exceeds payload length %d", + errShortPacket, lengthField, offset, len(payload), + ) + } + + var obuBuffer []byte + if isFirst && obuZ { + // We lost the first fragment of the OBU + // We drop the buffer and continue + if len(d.buffer) == 0 { + if isLast { + break + } + offset += lengthField + + continue + } + + obuBuffer = make([]byte, len(d.buffer)+lengthField) + + copy(obuBuffer, d.buffer) + copy(obuBuffer[len(d.buffer):], payload[offset:offset+lengthField]) + d.buffer = nil + } else { + obuBuffer = payload[offset : offset+lengthField] + } + offset += lengthField + + if isLast && obuY { + d.buffer = obuBuffer + + break + } + + if len(obuBuffer) == 0 { + continue + } + + obuHeader, err := obu.ParseOBUHeader(obuBuffer) + if err != nil { + return nil, err + } + + // The temporal delimiter OBU, if present, SHOULD be removed when transmitting, + // and MUST be ignored by receivers. Tile list OBUs are not supported. + // They SHOULD be removed when transmitted, and MUST be ignored by receivers. + // https://aomediacodec.github.io/av1-rtp-spec/#5-packetization-rules + if obuHeader.Type == obu.OBUTemporalDelimiter || obuHeader.Type == obu.OBUTileList { + continue + } + + // obu_has_size_field should be set to 0 for AV1 RTP packets. + // But we still check it to be sure, if we get obu size we just use it, instead of calculating it. + if obuHeader.HasSizeField { + obuSize, n, err := obu.ReadLeb128(obuBuffer[obuHeader.Size():]) + if err != nil { + return nil, err + } + + // We validate the obu_size_field if it is present. + sizeFromOBUSize := obuHeader.Size() + int(obuSize) + int(n) //nolint:gosec + if lengthField != sizeFromOBUSize { + return nil, fmt.Errorf( + "%w: OBU size %d does not match calculated size %d", + errShortPacket, obuSize, sizeFromOBUSize, + ) + } + + buff = append(buff, obuBuffer...) + } else { + obuHeader.HasSizeField = true + buff = append(buff, obuHeader.Marshal()...) + size := len(obuBuffer) - obuHeader.Size() + buff = append(buff, obu.WriteToLeb128(uint(size))...) // nolint: gosec // G104 + buff = append(buff, obuBuffer[obuHeader.Size():]...) + } + + if isLast { + break + } + } + + if obuCount != 0 && obuOffset != int(obuCount-1) { + return nil, fmt.Errorf( + "%w: OBU count %d does not match number of OBUs %d", + errShortPacket, obuCount, obuOffset, + ) + } + + return buff, nil +} + +// IsPartitionHead returns true if Z in the AV1 Aggregation Header +// is set to 0. +func (d *AV1Depacketizer) IsPartitionHead(payload []byte) bool { + if len(payload) == 0 { + return false + } + + return (payload[0] & av1ZMask) == 0 +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/av1_packet.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/av1_packet.go index 120a904c1..7eeceae91 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/av1_packet.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/av1_packet.go @@ -1,81 +1,295 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package codecs import ( - "github.com/pion/rtp/pkg/obu" + "github.com/pion/rtp/codecs/av1/obu" ) const ( - zMask = byte(0b10000000) - zBitshift = 7 + av1ZMask = byte(0b10000000) + av1ZBitshift = 7 - yMask = byte(0b01000000) - yBitshift = 6 + av1YMask = byte(0b01000000) + av1YBitshift = 6 - wMask = byte(0b00110000) - wBitshift = 4 + av1WMask = byte(0b00110000) + av1WBitshift = 4 - nMask = byte(0b00001000) - nBitshift = 3 - - av1PayloaderHeadersize = 1 + av1NMask = byte(0b00001000) + av1NBitshift = 3 ) -// AV1Payloader payloads AV1 packets +// AV1Payloader payloads AV1 packets. type AV1Payloader struct{} -// Payload fragments a AV1 packet across one or more byte arrays -// See AV1Packet for description of AV1 Payload Header +// Payload implements AV1 RTP payloader. +// Reads from a open_bitstream_unit (OBU) framing stream as defined in +// 5.3. https://aomediacodec.github.io/av1-spec/av1-spec.pdf#page=39 +// Returns AV1 RTP packets https://aomediacodec.github.io/av1-rtp-spec/ +// The payload is fragmented into multiple packets, each packet is a valid AV1 RTP payload. +// nolint:cyclop func (p *AV1Payloader) Payload(mtu uint16, payload []byte) (payloads [][]byte) { - maxFragmentSize := int(mtu) - av1PayloaderHeadersize - 2 - payloadDataRemaining := len(payload) - payloadDataIndex := 0 - - // Make sure the fragment/payload size is correct - if min(maxFragmentSize, payloadDataRemaining) <= 0 { + // 2 is the minimum MTU for AV1 (aggregate header + 1 byte) + if mtu <= 1 || len(payload) == 0 { return payloads } - for payloadDataRemaining > 0 { - currentFragmentSize := min(maxFragmentSize, payloadDataRemaining) - leb128Size := 1 - if currentFragmentSize >= 127 { - leb128Size = 2 + // We maximize the use of the W field in the AV1 aggregation header + // to minimize the need for explicit length fields for each OBU. + // To achieve this, we temporarily hold the OBU payload before adding it to a packet. + // Since we can't determine in advance whether the next OBU should be included in the same packet + // or start a new one, we also can't know ahead of time if an OBU is the last in the current packet. + var currentOBUPayload []byte + var currentPacketOBUHeader *obu.ExtensionHeader + obusInPacket := 0 + newSequence := false + startWithNewPacket := false + + for offset := 0; offset < len(payload); { + obuHeader, err := obu.ParseOBUHeader(payload[offset:]) + if err != nil { + break } - out := make([]byte, av1PayloaderHeadersize+leb128Size+currentFragmentSize) - leb128Value := obu.EncodeLEB128(uint(currentFragmentSize)) - if leb128Size == 1 { - out[1] = byte(leb128Value) + offset += obuHeader.Size() + // if ( obu_has_size_field ) { + // obu_size leb128() + // } else { + // obu_size = sz - 1 - obu_extension_flag + // } + var obuSize int + if obuHeader.HasSizeField { + obuSizeValue, n, err := obu.ReadLeb128(payload[offset:]) + if err != nil { + break + } + + offset += int(n) //nolint:gosec // G115, leb128 size is a signle digit + obuSize = int(obuSizeValue) //nolint:gosec // G115, Leb128 is capped at 4 bytes } else { - out[1] = byte(leb128Value >> 8) - out[2] = byte(leb128Value) + obuSize = len(payload) - offset } - copy(out[av1PayloaderHeadersize+leb128Size:], payload[payloadDataIndex:payloadDataIndex+currentFragmentSize]) - payloads = append(payloads, out) - - payloadDataRemaining -= currentFragmentSize - payloadDataIndex += currentFragmentSize - - if len(payloads) > 1 { - out[0] ^= zMask + // Each RTP packet MUST NOT contain OBUs that belong to different temporal units. + // If a sequence header OBU is present in an RTP packet, then it SHOULD be the first OBU in the packet. + // https://aomediacodec.github.io/av1-rtp-spec/#5-packetization-rules + needNewPacket := obuHeader.Type == obu.OBUTemporalDelimiter || obuHeader.Type == obu.OBUSequenceHeader + // If more than one OBU contained in an RTP packet has an OBU extension header, + // then the values of the temporal_id and spatial_id MUST be the same in all such OBUs in the RTP packet. + if !needNewPacket && obuHeader.ExtensionHeader != nil && currentPacketOBUHeader != nil { + needNewPacket = obuHeader.ExtensionHeader.SpatialID != currentPacketOBUHeader.SpatialID || + obuHeader.ExtensionHeader.TemporalID != currentPacketOBUHeader.TemporalID } - if payloadDataRemaining != 0 { - out[0] ^= yMask + + if obuHeader.ExtensionHeader != nil { + currentPacketOBUHeader = obuHeader.ExtensionHeader } + + if obuSize > len(payload)-offset { + break + } + + if len(currentOBUPayload) > 0 { + payloads, obusInPacket = p.appendOBUPayload( + payloads, + currentOBUPayload, + newSequence, + needNewPacket, + startWithNewPacket, + int(mtu), + obusInPacket, + ) + currentOBUPayload = nil + startWithNewPacket = needNewPacket + + if needNewPacket { + newSequence = false + currentPacketOBUHeader = nil + } + } + + // The temporal delimiter OBU, if present, SHOULD be removed when transmitting, + // and MUST be ignored by receivers. Tile list OBUs are not supported. + // They SHOULD be removed when transmitted, and MUST be ignored by receivers. + // https://aomediacodec.github.io/av1-rtp-spec/#5-packetization-rules + if obuHeader.Type == obu.OBUTileList || obuHeader.Type == obu.OBUTemporalDelimiter { + offset += obuSize + + continue + } + + currentOBUPayload = make([]byte, obuSize+obuHeader.Size()) + // The AV1 specification allows OBUs to have an optional size field called obu_size + // (also leb128 encoded), signaled by the obu_has_size_field flag in the OBU header. + // To minimize overhead, the obu_has_size_field flag SHOULD be set to zero in all OBUs. + // https://aomediacodec.github.io/av1-rtp-spec/#45-payload-structure + obuHeader.HasSizeField = false + copy(currentOBUPayload, obuHeader.Marshal()) + //nolint:gosec // G115 we validate the size of the payload + copy(currentOBUPayload[obuHeader.Size():], payload[offset:offset+obuSize]) + offset += obuSize + newSequence = obuHeader.Type == obu.OBUSequenceHeader + } + + if len(currentOBUPayload) > 0 { + payloads, _ = p.appendOBUPayload( + payloads, + currentOBUPayload, + newSequence, + true, + startWithNewPacket, + int(mtu), + obusInPacket, + ) } return payloads } +//nolint:cyclop +func (p *AV1Payloader) appendOBUPayload( + payloads [][]byte, + obuPayload []byte, + isNewVideoSequence, isLast, startWithNewPacket bool, + mtu, currentOBUCount int, +) ([][]byte, int) { + currentPayload := len(payloads) - 1 + freeSpace := 0 + if currentPayload >= 0 { + freeSpace = mtu - len(payloads[currentPayload]) + } + + if currentPayload < 0 || freeSpace <= 0 || startWithNewPacket { + payload := make([]byte, 1, mtu) + if isNewVideoSequence { + payload[0] |= 1 << av1NBitshift + } + + payloads = append(payloads, payload) + currentPayload = len(payloads) - 1 + // MTU - aggregation header + freeSpace = mtu - 1 + currentOBUCount = 0 + } + + remaining := len(obuPayload) + // How much to write to the current packet. + toWrite := remaining + if toWrite >= freeSpace { + toWrite = freeSpace + } + + // W: two bit field that describes the number of OBU elements in the packet. + // This field MUST be set equal to 0 or equal to the number of OBU elements contained in the packet. + // If set to 0, each OBU element MUST be preceded by a length field. If not set to 0 (i.e., W = 1, 2 or 3) + // the last OBU element MUST NOT be preceded by a length field. + // https://aomediacodec.github.io/av1-rtp-spec/#44-av1-aggregation-header + shouldUseWField := (isLast || toWrite >= freeSpace) && currentOBUCount < 3 + switch { + case shouldUseWField: + payloads[currentPayload][0] |= byte((currentOBUCount+1)<= 2: + // 2 bytes is the minimum size for OBUs with length field. + // [1 byte for the length field] [1 byte for the OBU] + //nolint:gosec // G115 false positive + toWrite = p.computeWriteSize(toWrite, freeSpace) + lengthField := obu.WriteToLeb128(uint(toWrite)) //nolint:gosec // G115 false positive + payloads[currentPayload] = append(payloads[currentPayload], lengthField...) + payloads[currentPayload] = append(payloads[currentPayload], obuPayload[:toWrite]...) + currentOBUCount++ + default: + // If we can't fit any more OBUs in the current packet (only 1 byte left and W=0) + toWrite = 0 + } + + obuPayload = obuPayload[toWrite:] + remaining -= toWrite + + // Handle fragments. + for remaining > 0 { + // New packet with empty aggregation header. + payload := make([]byte, 1, mtu) + payloads = append(payloads, payload) + currentPayload++ + + // Append the Y bit to the previous packet. And Z bit to the current packet. + // If we wrote some bytes to the previous packet. + // Handles an edge case where the previous packet has only one byte remaining, + // while the W field is not used. This results in insufficient space + // for a one-byte length field and a one-byte OBU. + // So we don't write anything to the initial packet. + if toWrite != 0 { + payloads[currentPayload-1][0] |= av1YMask + payloads[currentPayload][0] |= av1ZMask + } + + toWrite = remaining + if toWrite >= mtu-1 { // MTU - aggregation header + toWrite = mtu - 1 + } + + // Last OBU in the current packet, Or this whole packet is a fragment. + if isLast || remaining >= mtu-1 { + payloads[currentPayload][0] |= 1 << av1WBitshift + } else { + toWrite = p.computeWriteSize(toWrite, mtu-1) + lengthField := obu.WriteToLeb128(uint(toWrite)) //nolint:gosec // G115 false positive + payloads[currentPayload] = append(payloads[currentPayload], lengthField...) + } + + payloads[currentPayload] = append(payloads[currentPayload], obuPayload[:toWrite]...) + obuPayload = obuPayload[toWrite:] + remaining -= toWrite + currentOBUCount = 1 + } + + return payloads, currentOBUCount +} + +// Measure the maximum write size for a payload with leb128 encoding added. +func (p *AV1Payloader) computeWriteSize(wantToWrite, canWrite int) int { + leb128Size, isAtEge := p.leb128Size(wantToWrite) + if canWrite >= wantToWrite+leb128Size { + return wantToWrite + } + + // Handle edge case where subtracting one from the leb128 size + // results in a smaller leb128 size that can fit in the remaining space. + if isAtEge && canWrite >= wantToWrite+leb128Size-1 { + return wantToWrite - 1 + } + + return wantToWrite - leb128Size +} + +func (p *AV1Payloader) leb128Size(leb128 int) (size int, isAtEge bool) { + switch { + case leb128 >= 268435456: // 2^28 + return 5, leb128 == 268435456 + case leb128 >= 2097152: // 2^21 + return 4, leb128 == 2097152 + case leb128 >= 16384: // 2^14 + return 3, leb128 == 16384 + case leb128 >= 128: // 2^7 + return 2, leb128 == 128 + default: + return 1, false + } +} + // AV1Packet represents a depacketized AV1 RTP Packet -// -// 0 1 2 3 4 5 6 7 -// +-+-+-+-+-+-+-+-+ -// |Z|Y| W |N|-|-|-| -// +-+-+-+-+-+-+-+-+ -// +/* +* 0 1 2 3 4 5 6 7 +* +-+-+-+-+-+-+-+-+ +* |Z|Y| W |N|-|-|-| +* +-+-+-+-+-+-+-+-+ +**/ // https://aomediacodec.github.io/av1-rtp-spec/#44-av1-aggregation-header +// Deprecated: Use AV1Depacketizer instead. type AV1Packet struct { // Z: MUST be set to 1 if the first OBU element is an // OBU fragment that is a continuation of an OBU fragment @@ -104,9 +318,12 @@ type AV1Packet struct { // Each AV1 RTP Packet is a collection of OBU Elements. Each OBU Element may be a full OBU, or just a fragment of one. // AV1Frame provides the tools to construct a collection of OBUs from a collection of OBU Elements OBUElements [][]byte + + // zeroAllocation prevents populating the OBUElements field + zeroAllocation bool } -// Unmarshal parses the passed byte slice and stores the result in the AV1Packet this method is called upon +// Unmarshal parses the passed byte slice and stores the result in the AV1Packet this method is called upon. func (p *AV1Packet) Unmarshal(payload []byte) ([]byte, error) { if payload == nil { return nil, errNilPacket @@ -114,22 +331,35 @@ func (p *AV1Packet) Unmarshal(payload []byte) ([]byte, error) { return nil, errShortPacket } - p.Z = ((payload[0] & zMask) >> zBitshift) != 0 - p.Y = ((payload[0] & yMask) >> yBitshift) != 0 - p.N = ((payload[0] & nMask) >> nBitshift) != 0 - p.W = (payload[0] & wMask) >> wBitshift + p.Z = ((payload[0] & av1ZMask) >> av1ZBitshift) != 0 + p.Y = ((payload[0] & av1YMask) >> av1YBitshift) != 0 + p.N = ((payload[0] & av1NMask) >> av1NBitshift) != 0 + p.W = (payload[0] & av1WMask) >> av1WBitshift if p.Z && p.N { return nil, errIsKeyframeAndFragment } - currentIndex := uint(1) - p.OBUElements = [][]byte{} + if !p.zeroAllocation { + obuElements, err := p.parseBody(payload[1:]) + if err != nil { + return nil, err + } + p.OBUElements = obuElements + } - var ( - obuElementLength, bytesRead uint - err error - ) + return payload[1:], nil +} + +func (p *AV1Packet) parseBody(payload []byte) ([][]byte, error) { + if p.OBUElements != nil { + return p.OBUElements, nil + } + + obuElements := [][]byte{} + + var obuElementLength, bytesRead uint + currentIndex := uint(0) for i := 1; ; i++ { if currentIndex == uint(len(payload)) { break @@ -140,6 +370,7 @@ func (p *AV1Packet) Unmarshal(payload []byte) ([]byte, error) { bytesRead = 0 obuElementLength = uint(len(payload)) - currentIndex } else { + var err error obuElementLength, bytesRead, err = obu.ReadLeb128(payload[currentIndex:]) if err != nil { return nil, err @@ -150,9 +381,9 @@ func (p *AV1Packet) Unmarshal(payload []byte) ([]byte, error) { if uint(len(payload)) < currentIndex+obuElementLength { return nil, errShortPacket } - p.OBUElements = append(p.OBUElements, payload[currentIndex:currentIndex+obuElementLength]) + obuElements = append(obuElements, payload[currentIndex:currentIndex+obuElementLength]) currentIndex += obuElementLength } - return payload[1:], nil + return obuElements, nil } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/codecs.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/codecs.go index 0e078974e..cd1c89150 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/codecs.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/codecs.go @@ -1,2 +1,5 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + // Package codecs implements codec specific RTP payloader/depayloaders package codecs diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/common.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/common.go index af5632ac7..8d7531a35 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/common.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/common.go @@ -1,26 +1,40 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package codecs -func min(a, b int) int { +func minInt(a, b int) int { if a < b { return a } + return b } -// audioDepacketizer is a mixin for audio codec depacketizers +// audioDepacketizer is a mixin for audio codec depacketizers. type audioDepacketizer struct{} -func (d *audioDepacketizer) IsPartitionTail(marker bool, payload []byte) bool { +func (d *audioDepacketizer) IsPartitionTail(_ bool, _ []byte) bool { return true } -func (d *audioDepacketizer) IsPartitionHead(payload []byte) bool { +func (d *audioDepacketizer) IsPartitionHead(_ []byte) bool { return true } -// videoDepacketizer is a mixin for video codec depacketizers -type videoDepacketizer struct{} +// videoDepacketizer is a mixin for video codec depacketizers. +type videoDepacketizer struct { + zeroAllocation bool +} -func (d *videoDepacketizer) IsPartitionTail(marker bool, payload []byte) bool { +func (d *videoDepacketizer) IsPartitionTail(marker bool, _ []byte) bool { return marker } + +// SetZeroAllocation enables Zero Allocation mode for the depacketizer +// By default the Depacketizers will allocate as they parse. These allocations +// are needed for Metadata and other optional values. If you don't need this information +// enabling SetZeroAllocation gives you higher performance at a reduced feature set. +func (d *videoDepacketizer) SetZeroAllocation(zeroAllocation bool) { + d.zeroAllocation = zeroAllocation +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/error.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/error.go index 7f72e7b8e..60530e97c 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/error.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/error.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package codecs import "errors" @@ -9,6 +12,8 @@ var ( errTooManySpatialLayers = errors.New("too many spatial layers") errUnhandledNALUType = errors.New("NALU Type is unhandled") - // AV1 Errors - errIsKeyframeAndFragment = errors.New("bits Z and N are set. Not possible to have OBU be tail fragment and be keyframe") + // AV1 Errors. + errIsKeyframeAndFragment = errors.New( + "bits Z and N are set. Not possible to have OBU be tail fragment and be keyframe", + ) ) diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/g711_packet.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/g711_packet.go index 7ab68b2c3..7ac268a10 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/g711_packet.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/g711_packet.go @@ -1,9 +1,12 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package codecs -// G711Payloader payloads G711 packets +// G711Payloader payloads G711 packets. type G711Payloader struct{} -// Payload fragments an G711 packet across one or more byte arrays +// Payload fragments an G711 packet across one or more byte arrays. func (p *G711Payloader) Payload(mtu uint16, payload []byte) [][]byte { var out [][]byte if payload == nil || mtu == 0 { @@ -18,5 +21,6 @@ func (p *G711Payloader) Payload(mtu uint16, payload []byte) [][]byte { } o := make([]byte, len(payload)) copy(o, payload) + return append(out, o) } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/g722_packet.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/g722_packet.go index 13e17b674..7d586ab9f 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/g722_packet.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/g722_packet.go @@ -1,9 +1,12 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package codecs -// G722Payloader payloads G722 packets +// G722Payloader payloads G722 packets. type G722Payloader struct{} -// Payload fragments an G722 packet across one or more byte arrays +// Payload fragments an G722 packet across one or more byte arrays. func (p *G722Payloader) Payload(mtu uint16, payload []byte) [][]byte { var out [][]byte if payload == nil || mtu == 0 { @@ -18,5 +21,6 @@ func (p *G722Payloader) Payload(mtu uint16, payload []byte) [][]byte { } o := make([]byte, len(payload)) copy(o, payload) + return append(out, o) } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/h264_packet.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/h264_packet.go index 11a82fe40..fdc00edc6 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/h264_packet.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/h264_packet.go @@ -1,13 +1,18 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package codecs import ( + "bytes" "encoding/binary" "fmt" ) -// H264Payloader payloads H264 packets +// H264Payloader payloads H264 packets. type H264Payloader struct { spsNalu, ppsNalu []byte + DisableStapA bool } const ( @@ -31,45 +36,59 @@ const ( outputStapAHeader = 0x78 ) -func annexbNALUStartCode() []byte { return []byte{0x00, 0x00, 0x00, 0x01} } +// nolint:gochecknoglobals +var ( + naluStartCode = []byte{0x00, 0x00, 0x01} + annexbNALUStartCode = []byte{0x00, 0x00, 0x00, 0x01} +) func emitNalus(nals []byte, emit func([]byte)) { - nextInd := func(nalu []byte, start int) (indStart int, indLen int) { - zeroCount := 0 + // look for 3-byte NALU start code + start := bytes.Index(nals, naluStartCode) + offset := 3 - for i, b := range nalu[start:] { - if b == 0 { - zeroCount++ - continue - } else if b == 1 { - if zeroCount >= 2 { - return start + i - zeroCount, zeroCount + 1 - } - } - zeroCount = 0 - } - return -1, -1 + if start == -1 { + // no start code, emit the whole buffer + emit(nals) + + return } - nextIndStart, nextIndLen := nextInd(nals, 0) - if nextIndStart == -1 { - emit(nals) - } else { - for nextIndStart != -1 { - prevStart := nextIndStart + nextIndLen - nextIndStart, nextIndLen = nextInd(nals, prevStart) - if nextIndStart != -1 { - emit(nals[prevStart:nextIndStart]) - } else { - // Emit until end of stream, no end indicator found - emit(nals[prevStart:]) - } + length := len(nals) + + for start < length { + // look for the next NALU start (end of this NALU) + end := bytes.Index(nals[start+offset:], naluStartCode) + if end == -1 { + // no more NALUs, emit the rest of the buffer + emit(nals[start+offset:]) + + break + } + + // next NALU start + nextStart := start + offset + end + + // check if the next NALU is actually a 4-byte start code + endIs4Byte := nals[nextStart-1] == 0 + if endIs4Byte { + nextStart-- + } + + emit(nals[start+offset : nextStart]) + + start = nextStart + + if endIs4Byte { + offset = 4 + } else { + offset = 3 } } } -// Payload fragments a H264 packet across one or more byte arrays -func (p *H264Payloader) Payload(mtu uint16, payload []byte) [][]byte { +// Payload fragments a H264 packet across one or more byte arrays. +func (p *H264Payloader) Payload(mtu uint16, payload []byte) [][]byte { //nolint:cyclop var payloads [][]byte if len(payload) == 0 { return payloads @@ -87,18 +106,24 @@ func (p *H264Payloader) Payload(mtu uint16, payload []byte) [][]byte { case naluType == audNALUType || naluType == fillerNALUType: return case naluType == spsNALUType: - p.spsNalu = nalu - return + if !p.DisableStapA { + p.spsNalu = nalu + + return + } case naluType == ppsNALUType: - p.ppsNalu = nalu - return - case p.spsNalu != nil && p.ppsNalu != nil: + if !p.DisableStapA { + p.ppsNalu = nalu + + return + } + case !p.DisableStapA && p.spsNalu != nil && p.ppsNalu != nil: // Pack current NALU with SPS and PPS as STAP-A spsLen := make([]byte, 2) - binary.BigEndian.PutUint16(spsLen, uint16(len(p.spsNalu))) + binary.BigEndian.PutUint16(spsLen, uint16(len(p.spsNalu))) // nolint: gosec // G115 ppsLen := make([]byte, 2) - binary.BigEndian.PutUint16(ppsLen, uint16(len(p.ppsNalu))) + binary.BigEndian.PutUint16(ppsLen, uint16(len(p.ppsNalu))) // nolint: gosec // G115 stapANalu := []byte{outputStapAHeader} stapANalu = append(stapANalu, spsLen...) @@ -120,6 +145,7 @@ func (p *H264Payloader) Payload(mtu uint16, payload []byte) [][]byte { out := make([]byte, len(nalu)) copy(out, nalu) payloads = append(payloads, out) + return } @@ -137,18 +163,17 @@ func (p *H264Payloader) Payload(mtu uint16, payload []byte) [][]byte { // the FU header. An FU payload MAY have any number of octets and MAY // be empty. - naluData := nalu // According to the RFC, the first octet is skipped due to redundant information - naluDataIndex := 1 - naluDataLength := len(nalu) - naluDataIndex - naluDataRemaining := naluDataLength + naluIndex := 1 + naluLength := len(nalu) - naluIndex + naluRemaining := naluLength - if min(maxFragmentSize, naluDataRemaining) <= 0 { + if minInt(maxFragmentSize, naluRemaining) <= 0 { return } - for naluDataRemaining > 0 { - currentFragmentSize := min(maxFragmentSize, naluDataRemaining) + for naluRemaining > 0 { + currentFragmentSize := minInt(maxFragmentSize, naluRemaining) out := make([]byte, fuaHeaderSize+currentFragmentSize) // +---------------+ @@ -166,26 +191,26 @@ func (p *H264Payloader) Payload(mtu uint16, payload []byte) [][]byte { // +---------------+ out[1] = naluType - if naluDataRemaining == naluDataLength { + if naluRemaining == naluLength { // Set start bit out[1] |= 1 << 7 - } else if naluDataRemaining-currentFragmentSize == 0 { + } else if naluRemaining-currentFragmentSize == 0 { // Set end bit out[1] |= 1 << 6 } - copy(out[fuaHeaderSize:], naluData[naluDataIndex:naluDataIndex+currentFragmentSize]) + copy(out[fuaHeaderSize:], nalu[naluIndex:naluIndex+currentFragmentSize]) payloads = append(payloads, out) - naluDataRemaining -= currentFragmentSize - naluDataIndex += currentFragmentSize + naluRemaining -= currentFragmentSize + naluIndex += currentFragmentSize } }) return payloads } -// H264Packet represents the H264 header that is stored in the payload of an RTP Packet +// H264Packet represents the H264 header that is stored in the payload of an RTP Packet. type H264Packet struct { IsAVC bool fuaBuffer []byte @@ -193,28 +218,38 @@ type H264Packet struct { videoDepacketizer } -func (p *H264Packet) doPackaging(nalu []byte) []byte { +func (p *H264Packet) doPackaging(buf, nalu []byte) []byte { if p.IsAVC { - naluLength := make([]byte, 4) - binary.BigEndian.PutUint32(naluLength, uint32(len(nalu))) - return append(naluLength, nalu...) + buf = binary.BigEndian.AppendUint32(buf, uint32(len(nalu))) // nolint: gosec // G115 false positive + buf = append(buf, nalu...) + + return buf } - return append(annexbNALUStartCode(), nalu...) + buf = append(buf, annexbNALUStartCode...) + buf = append(buf, nalu...) + + return buf } // IsDetectedFinalPacketInSequence returns true of the packet passed in has the -// marker bit set indicated the end of a packet sequence +// marker bit set indicated the end of a packet sequence. func (p *H264Packet) IsDetectedFinalPacketInSequence(rtpPacketMarketBit bool) bool { return rtpPacketMarketBit } -// Unmarshal parses the passed byte slice and stores the result in the H264Packet this method is called upon +// Unmarshal parses the passed byte slice and stores the result in the H264Packet this method is called upon. func (p *H264Packet) Unmarshal(payload []byte) ([]byte, error) { - if payload == nil { - return nil, errNilPacket - } else if len(payload) <= 2 { - return nil, fmt.Errorf("%w: %d <= 2", errShortPacket, len(payload)) + if p.zeroAllocation { + return payload, nil + } + + return p.parseBody(payload) +} + +func (p *H264Packet) parseBody(payload []byte) ([]byte, error) { //nolint:cyclop + if len(payload) == 0 { + return nil, fmt.Errorf("%w: %d <=0", errShortPacket, len(payload)) } // NALU Types @@ -222,22 +257,32 @@ func (p *H264Packet) Unmarshal(payload []byte) ([]byte, error) { naluType := payload[0] & naluTypeBitmask switch { case naluType > 0 && naluType < 24: - return p.doPackaging(payload), nil + return p.doPackaging(nil, payload), nil case naluType == stapaNALUType: currOffset := int(stapaHeaderSize) result := []byte{} for currOffset < len(payload) { - naluSize := int(binary.BigEndian.Uint16(payload[currOffset:])) + naluSizeBytes := payload[currOffset:] + if len(naluSizeBytes) < stapaNALULengthSize { + break + } + naluSize := int(binary.BigEndian.Uint16(naluSizeBytes)) currOffset += stapaNALULengthSize if len(payload) < currOffset+naluSize { - return nil, fmt.Errorf("%w STAP-A declared size(%d) is larger than buffer(%d)", errShortPacket, naluSize, len(payload)-currOffset) + return nil, fmt.Errorf( + "%w STAP-A declared size(%d) is larger than buffer(%d)", + errShortPacket, + naluSize, + len(payload)-currOffset, + ) } - result = append(result, p.doPackaging(payload[currOffset:currOffset+naluSize])...) + result = p.doPackaging(result, payload[currOffset:currOffset+naluSize]) currOffset += naluSize } + return result, nil case naluType == fuaNALUType: @@ -258,7 +303,8 @@ func (p *H264Packet) Unmarshal(payload []byte) ([]byte, error) { nalu := append([]byte{}, naluRefIdc|fragmentedNaluType) nalu = append(nalu, p.fuaBuffer...) p.fuaBuffer = nil - return p.doPackaging(nalu), nil + + return p.doPackaging(nil, nalu), nil } return []byte{}, nil @@ -267,9 +313,18 @@ func (p *H264Packet) Unmarshal(payload []byte) ([]byte, error) { return nil, fmt.Errorf("%w: %d", errUnhandledNALUType, naluType) } -// H264PartitionHeadChecker is obsolete +// H264PartitionHeadChecker checks H264 partition head. +// +// Deprecated: replaced by H264Packet.IsPartitionHead(). type H264PartitionHeadChecker struct{} +// IsPartitionHead checks if this is the head of a packetized nalu stream. +// +// Deprecated: replaced by H264Packet.IsPartitionHead(). +func (*H264PartitionHeadChecker) IsPartitionHead(packet []byte) bool { + return (&H264Packet{}).IsPartitionHead(packet) +} + // IsPartitionHead checks if this is the head of a packetized nalu stream. func (*H264Packet) IsPartitionHead(payload []byte) bool { if len(payload) < 2 { diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/h265_packet.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/h265_packet.go index 6f0490dc6..ff24f080f 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/h265_packet.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/h265_packet.go @@ -1,9 +1,13 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package codecs import ( "encoding/binary" "errors" "fmt" + "math" ) // @@ -20,7 +24,7 @@ var ( // const ( - // sizeof(uint16) + // sizeof(uint16). h265NaluHeaderSize = 2 // https://datatracker.ietf.org/doc/html/rfc7798#section-4.4.2 h265NaluAggregationPacketType = 48 @@ -30,13 +34,16 @@ const ( h265NaluPACIPacketType = 50 ) -// H265NALUHeader is a H265 NAL Unit Header +// H265NALUHeader is a H265 NAL Unit Header. // https://datatracker.ietf.org/doc/html/rfc7798#section-1.1.4 -// +---------------+---------------+ -// |0|1|2|3|4|5|6|7|0|1|2|3|4|5|6|7| -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// |F| Type | LayerID | TID | -// +-------------+-----------------+ +/* +* +---------------+---------------+ +* |0|1|2|3|4|5|6|7|0|1|2|3|4|5|6|7| +* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +* |F| Type | LayerID | TID | +* +-------------+-----------------+ +**/ +// . type H265NALUHeader uint16 func newH265NALUHeader(highByte, lowByte uint8) H265NALUHeader { @@ -52,13 +59,15 @@ func (h H265NALUHeader) F() bool { func (h H265NALUHeader) Type() uint8 { // 01111110 00000000 const mask = 0b01111110 << 8 - return uint8((uint16(h) & mask) >> (8 + 1)) + + return uint8((uint16(h) & mask) >> (8 + 1)) // nolint: gosec // G115 false positive } // IsTypeVCLUnit returns whether or not the NAL Unit type is a VCL NAL unit. func (h H265NALUHeader) IsTypeVCLUnit() bool { // Type is coded on 6 bits const msbMask = 0b00100000 + return (h.Type() & msbMask) == 0 } @@ -66,13 +75,15 @@ func (h H265NALUHeader) IsTypeVCLUnit() bool { func (h H265NALUHeader) LayerID() uint8 { // 00000001 11111000 const mask = (0b00000001 << 8) | 0b11111000 - return uint8((uint16(h) & mask) >> 3) + + return uint8((uint16(h) & mask) >> 3) // nolint: gosec // G115 false positive } // TID is the temporal identifier of the NAL unit +1. func (h H265NALUHeader) TID() uint8 { const mask = 0b00000111 - return uint8(uint16(h) & mask) + + return uint8(uint16(h) & mask) // nolint: gosec // G115 false positive } // IsAggregationPacket returns whether or not the packet is an Aggregation packet. @@ -95,18 +106,19 @@ func (h H265NALUHeader) IsPACIPacket() bool { // // H265SingleNALUnitPacket represents a NALU packet, containing exactly one NAL unit. -// 0 1 2 3 -// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | PayloadHdr | DONL (conditional) | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | | -// | NAL unit payload data | -// | | -// | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | :...OPTIONAL RTP padding | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// +/* +* 0 1 2 3 +* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +* | PayloadHdr | DONL (conditional) | +* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +* | | +* | NAL unit payload data | +* | | +* | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +* | :...OPTIONAL RTP padding | +* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +**/ // Reference: https://datatracker.ietf.org/doc/html/rfc7798#section-4.4.1 type H265SingleNALUnitPacket struct { // payloadHeader is the header of the H265 packet. @@ -125,7 +137,8 @@ func (p *H265SingleNALUnitPacket) WithDONL(value bool) { p.mightNeedDONL = value } -// Unmarshal parses the passed byte slice and stores the result in the H265SingleNALUnitPacket this method is called upon. +// Unmarshal parses the passed byte slice and stores the result in the H265SingleNALUnitPacket +// this method is called upon. func (p *H265SingleNALUnitPacket) Unmarshal(payload []byte) ([]byte, error) { // sizeof(headers) const totalHeaderSize = h265NaluHeaderSize @@ -184,19 +197,19 @@ func (p *H265SingleNALUnitPacket) isH265Packet() {} // // H265AggregationUnitFirst represent the First Aggregation Unit in an AP. -// -// 0 1 2 3 -// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// : DONL (conditional) | NALU size | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | NALU size | | -// +-+-+-+-+-+-+-+-+ NAL unit | -// | | -// | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | : -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// +/* +* 0 1 2 3 +* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +* : DONL (conditional) | NALU size | +* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +* | NALU size | | +* +-+-+-+-+-+-+-+-+ NAL unit | +* | | +* | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +* | : +* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +**/ // Reference: https://datatracker.ietf.org/doc/html/rfc7798#section-4.4.2 type H265AggregationUnitFirst struct { donl *uint16 @@ -222,18 +235,18 @@ func (u H265AggregationUnitFirst) NalUnit() []byte { } // H265AggregationUnit represent the an Aggregation Unit in an AP, which is not the first one. -// -// 0 1 2 3 -// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// : DOND (cond) | NALU size | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | | -// | NAL unit | -// | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | : -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// +/* +* 0 1 2 3 +* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +* : DOND (cond) | NALU size | +* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +* | | +* | NAL unit | +* | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +* | : +* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +**/ // Reference: https://datatracker.ietf.org/doc/html/rfc7798#section-4.4.2 type H265AggregationUnit struct { dond *uint8 @@ -259,18 +272,19 @@ func (u H265AggregationUnit) NalUnit() []byte { } // H265AggregationPacket represents an Aggregation packet. -// 0 1 2 3 -// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | PayloadHdr (Type=48) | | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | -// | | -// | two or more aggregation units | -// | | -// | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | :...OPTIONAL RTP padding | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// +/* +* 0 1 2 3 +* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +* | PayloadHdr (Type=48) | | +* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | +* | | +* | two or more aggregation units | +* | | +* | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +* | :...OPTIONAL RTP padding | +* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +**/ // Reference: https://datatracker.ietf.org/doc/html/rfc7798#section-4.4.2 type H265AggregationPacket struct { firstUnit *H265AggregationUnitFirst @@ -286,7 +300,7 @@ func (p *H265AggregationPacket) WithDONL(value bool) { } // Unmarshal parses the passed byte slice and stores the result in the H265AggregationPacket this method is called upon. -func (p *H265AggregationPacket) Unmarshal(payload []byte) ([]byte, error) { +func (p *H265AggregationPacket) Unmarshal(payload []byte) ([]byte, error) { //nolint:cyclop // sizeof(headers) const totalHeaderSize = h265NaluHeaderSize if payload == nil { @@ -390,51 +404,56 @@ func (p *H265AggregationPacket) isH265Packet() {} // const ( - // sizeof(uint8) + // sizeof(uint8). h265FragmentationUnitHeaderSize = 1 ) -// H265FragmentationUnitHeader is a H265 FU Header +// H265FragmentationUnitHeader is a H265 FU Header. +// // +---------------+ // |0|1|2|3|4|5|6|7| // +-+-+-+-+-+-+-+-+ // |S|E| FuType | // +---------------+ +// . type H265FragmentationUnitHeader uint8 // S represents the start of a fragmented NAL unit. func (h H265FragmentationUnitHeader) S() bool { const mask = 0b10000000 + return ((h & mask) >> 7) != 0 } // E represents the end of a fragmented NAL unit. func (h H265FragmentationUnitHeader) E() bool { const mask = 0b01000000 + return ((h & mask) >> 6) != 0 } // FuType MUST be equal to the field Type of the fragmented NAL unit. func (h H265FragmentationUnitHeader) FuType() uint8 { const mask = 0b00111111 + return uint8(h) & mask } // H265FragmentationUnitPacket represents a single Fragmentation Unit packet. -// -// 0 1 2 3 -// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | PayloadHdr (Type=49) | FU header | DONL (cond) | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-| -// | DONL (cond) | | -// |-+-+-+-+-+-+-+-+ | -// | FU payload | -// | | -// | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | :...OPTIONAL RTP padding | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// +/* +* 0 1 2 3 +* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +* | PayloadHdr (Type=49) | FU header | DONL (cond) | +* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-| +* | DONL (cond) | | +* |-+-+-+-+-+-+-+-+ | +* | FU payload | +* | | +* | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +* | :...OPTIONAL RTP padding | +* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +**/ // Reference: https://datatracker.ietf.org/doc/html/rfc7798#section-4.4.3 type H265FragmentationUnitPacket struct { // payloadHeader is the header of the H265 packet. @@ -455,7 +474,8 @@ func (p *H265FragmentationUnitPacket) WithDONL(value bool) { p.mightNeedDONL = value } -// Unmarshal parses the passed byte slice and stores the result in the H265FragmentationUnitPacket this method is called upon. +// Unmarshal parses the passed byte slice and stores the result in the H265FragmentationUnitPacket +// this method is called upon. func (p *H265FragmentationUnitPacket) Unmarshal(payload []byte) ([]byte, error) { // sizeof(headers) const totalHeaderSize = h265NaluHeaderSize + h265FragmentationUnitHeaderSize @@ -521,22 +541,22 @@ func (p *H265FragmentationUnitPacket) isH265Packet() {} // // H265PACIPacket represents a single H265 PACI packet. -// -// 0 1 2 3 -// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | PayloadHdr (Type=50) |A| cType | PHSsize |F0..2|Y| -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | Payload Header Extension Structure (PHES) | -// |=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=| -// | | -// | PACI payload: NAL unit | -// | . . . | -// | | -// | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | :...OPTIONAL RTP padding | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// +/* +* 0 1 2 3 +* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +* | PayloadHdr (Type=50) |A| cType | PHSsize |F0..2|Y| +* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +* | Payload Header Extension Structure (PHES) | +* |=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=| +* | | +* | PACI payload: NAL unit | +* | . . . | +* | | +* | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +* | :...OPTIONAL RTP padding | +* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +**/ // Reference: https://datatracker.ietf.org/doc/html/rfc7798#section-4.4.4 type H265PACIPacket struct { // payloadHeader is the header of the H265 packet. @@ -560,42 +580,49 @@ func (p *H265PACIPacket) PayloadHeader() H265NALUHeader { // A copies the F bit of the PACI payload NALU. func (p *H265PACIPacket) A() bool { const mask = 0b10000000 << 8 + return (p.paciHeaderFields & mask) != 0 } // CType copies the Type field of the PACI payload NALU. func (p *H265PACIPacket) CType() uint8 { const mask = 0b01111110 << 8 - return uint8((p.paciHeaderFields & mask) >> (8 + 1)) + + return uint8((p.paciHeaderFields & mask) >> (8 + 1)) // nolint: gosec // G115 false positive } // PHSsize indicates the size of the PHES field. func (p *H265PACIPacket) PHSsize() uint8 { const mask = (0b00000001 << 8) | 0b11110000 - return uint8((p.paciHeaderFields & mask) >> 4) + + return uint8((p.paciHeaderFields & mask) >> 4) // nolint: gosec // G115 false positive } // F0 indicates the presence of a Temporal Scalability support extension in the PHES. func (p *H265PACIPacket) F0() bool { const mask = 0b00001000 + return (p.paciHeaderFields & mask) != 0 } // F1 must be zero, reserved for future extensions. func (p *H265PACIPacket) F1() bool { const mask = 0b00000100 + return (p.paciHeaderFields & mask) != 0 } // F2 must be zero, reserved for future extensions. func (p *H265PACIPacket) F2() bool { const mask = 0b00000010 + return (p.paciHeaderFields & mask) != 0 } // Y must be zero, reserved for future extensions. func (p *H265PACIPacket) Y() bool { const mask = 0b00000001 + return (p.paciHeaderFields & mask) != 0 } @@ -616,6 +643,7 @@ func (p *H265PACIPacket) TSCI() *H265TSCI { } tsci := H265TSCI((uint32(p.phes[0]) << 16) | (uint32(p.phes[1]) << 8) | uint32(p.phes[0])) + return &tsci } @@ -645,6 +673,7 @@ func (p *H265PACIPacket) Unmarshal(payload []byte) ([]byte, error) { if len(payload) < int(headerExtensionSize)+1 { p.paciHeaderFields = 0 + return nil, errShortPacket } @@ -674,35 +703,40 @@ type H265TSCI uint32 func (h H265TSCI) TL0PICIDX() uint8 { const m1 = 0xFFFF0000 const m2 = 0xFF00 - return uint8((((h & m1) >> 16) & m2) >> 8) + + return uint8((((h & m1) >> 16) & m2) >> 8) // nolint: gosec // G115 false positive } // IrapPicID see RFC7798 for more details. func (h H265TSCI) IrapPicID() uint8 { const m1 = 0xFFFF0000 const m2 = 0x00FF - return uint8(((h & m1) >> 16) & m2) + + return uint8(((h & m1) >> 16) & m2) // nolint: gosec // G115 false positive } // S see RFC7798 for more details. func (h H265TSCI) S() bool { const m1 = 0xFF00 const m2 = 0b10000000 - return (uint8((h&m1)>>8) & m2) != 0 + + return (uint8((h&m1)>>8) & m2) != 0 // nolint: gosec // G115 false positive } // E see RFC7798 for more details. func (h H265TSCI) E() bool { const m1 = 0xFF00 const m2 = 0b01000000 - return (uint8((h&m1)>>8) & m2) != 0 + + return (uint8((h&m1)>>8) & m2) != 0 // nolint: gosec // G115 false positive } // RES see RFC7798 for more details. func (h H265TSCI) RES() uint8 { const m1 = 0xFF00 const m2 = 0b00111111 - return uint8((h&m1)>>8) & m2 + + return uint8((h&m1)>>8) & m2 // nolint: gosec // G115 false positive } // @@ -738,8 +772,8 @@ func (p *H265Packet) WithDONL(value bool) { p.mightNeedDONL = value } -// Unmarshal parses the passed byte slice and stores the result in the H265Packet this method is called upon -func (p *H265Packet) Unmarshal(payload []byte) ([]byte, error) { +// Unmarshal parses the passed byte slice and stores the result in the H265Packet this method is called upon. +func (p *H265Packet) Unmarshal(payload []byte) ([]byte, error) { // nolint:cyclop if payload == nil { return nil, errNilPacket } else if len(payload) <= h265NaluHeaderSize { @@ -817,3 +851,206 @@ func (*H265Packet) IsPartitionHead(payload []byte) bool { return true } + +// H265Payloader payloads H265 packets. +type H265Payloader struct { + AddDONL bool + SkipAggregation bool + donl uint16 +} + +// Payload fragments a H265 packet across one or more byte arrays. +func (p *H265Payloader) Payload(mtu uint16, payload []byte) [][]byte { //nolint:gocognit,cyclop + var payloads [][]byte + if len(payload) == 0 || mtu == 0 { + return payloads + } + + bufferedNALUs := make([][]byte, 0) + aggregationBufferSize := 0 + + flushBufferedNals := func() { + if len(bufferedNALUs) == 0 { + return + } + if len(bufferedNALUs) == 1 { //nolint:nestif + // emit this as a single NALU packet + nalu := bufferedNALUs[0] + + if p.AddDONL { + buf := make([]byte, len(nalu)+2) + + // copy the NALU header to the payload header + copy(buf[0:h265NaluHeaderSize], nalu[0:h265NaluHeaderSize]) + + // copy the DONL into the header + binary.BigEndian.PutUint16(buf[h265NaluHeaderSize:h265NaluHeaderSize+2], p.donl) + + // write the payload + copy(buf[h265NaluHeaderSize+2:], nalu[h265NaluHeaderSize:]) + + p.donl++ + + payloads = append(payloads, buf) + } else { + // write the nalu directly to the payload + payloads = append(payloads, nalu) + } + } else { + // construct an aggregation packet + aggregationPacketSize := aggregationBufferSize + buf := make([]byte, aggregationPacketSize) + + layerID := uint8(math.MaxUint8) + tid := uint8(math.MaxUint8) + for _, nalu := range bufferedNALUs { + header := newH265NALUHeader(nalu[0], nalu[1]) + headerLayerID := header.LayerID() + headerTID := header.TID() + if headerLayerID < layerID { + layerID = headerLayerID + } + if headerTID < tid { + tid = headerTID + } + } + + binary.BigEndian.PutUint16(buf[0:2], (uint16(h265NaluAggregationPacketType)<<9)|(uint16(layerID)<<3)|uint16(tid)) + + index := 2 + for i, nalu := range bufferedNALUs { + if p.AddDONL { + if i == 0 { + binary.BigEndian.PutUint16(buf[index:index+2], p.donl) + index += 2 + } else { + buf[index] = byte(i - 1) + index++ + } + } + + // Since the type of mtu is uint16, len(nalu) fits in as well, so it is safe. + // #nosec + binary.BigEndian.PutUint16(buf[index:index+2], uint16(len(nalu))) + index += 2 + index += copy(buf[index:], nalu) + } + payloads = append(payloads, buf) + } + // clear the buffered NALUs + bufferedNALUs = make([][]byte, 0) + aggregationBufferSize = 0 + } + + calcMarginalAggregationSize := func(nalu []byte) int { + marginalAggregationSize := len(nalu) + 2 // +2 is NALU size Field size + if len(bufferedNALUs) == 1 { + marginalAggregationSize = len(nalu) + 4 // +4 are Aggregation header + NALU size Field size + } + if p.AddDONL { + if len(bufferedNALUs) == 0 { + marginalAggregationSize += 2 + } else { + marginalAggregationSize++ + } + } + + return marginalAggregationSize + } + + emitNalus(payload, func(nalu []byte) { + if len(nalu) < 2 { + // NALU header is 2 bytes + return + } + + naluLen := len(nalu) + 2 + if p.AddDONL { + naluLen += 2 + } + if naluLen <= int(mtu) { //nolint:nestif + // this nalu fits into a single packet, either it can be emitted as + // a single nalu or appended to the previous aggregation packet + marginalAggregationSize := calcMarginalAggregationSize(nalu) + + if aggregationBufferSize+marginalAggregationSize > int(mtu) { + flushBufferedNals() + marginalAggregationSize = calcMarginalAggregationSize(nalu) + } + bufferedNALUs = append(bufferedNALUs, nalu) + aggregationBufferSize += marginalAggregationSize + if p.SkipAggregation { + // emit this immediately. + flushBufferedNals() + } + } else { + // if this nalu doesn't fit in the current mtu, it needs to be fragmented + fuPacketHeaderSize := h265FragmentationUnitHeaderSize + 2 /* payload header size */ + if p.AddDONL { + fuPacketHeaderSize += 2 + } + + // then, fragment the nalu + maxFUPayloadSize := int(mtu) - fuPacketHeaderSize + + naluHeader := newH265NALUHeader(nalu[0], nalu[1]) + + // the nalu header is omitted from the fragmentation packet payload + nalu = nalu[h265NaluHeaderSize:] + + if maxFUPayloadSize <= 0 || len(nalu) == 0 { + return + } + + // flush any buffered aggregation packets. + flushBufferedNals() + + fullNALUSize := len(nalu) + for len(nalu) > 0 { + curentFUPayloadSize := len(nalu) + if curentFUPayloadSize > maxFUPayloadSize { + curentFUPayloadSize = maxFUPayloadSize + } + + out := make([]byte, fuPacketHeaderSize+curentFUPayloadSize) + + // write the payload header + binary.BigEndian.PutUint16(out[0:2], uint16(naluHeader)) + out[0] = (out[0] & 0b10000001) | h265NaluFragmentationUnitType<<1 + + // write the fragment header + out[2] = byte(H265FragmentationUnitHeader(naluHeader.Type())) + if len(nalu) == fullNALUSize { + // Set start bit + out[2] |= 1 << 7 + } else if len(nalu)-curentFUPayloadSize == 0 { + // Set end bit + out[2] |= 1 << 6 + } + + if p.AddDONL { + // write the DONL header + binary.BigEndian.PutUint16(out[3:5], p.donl) + + p.donl++ + + // copy the fragment payload + copy(out[5:], nalu[0:curentFUPayloadSize]) + } else { + // copy the fragment payload + copy(out[3:], nalu[0:curentFUPayloadSize]) + } + + // append the fragment to the payload + payloads = append(payloads, out) + + // advance the nalu data pointer + nalu = nalu[curentFUPayloadSize:] + } + } + }) + + flushBufferedNals() + + return payloads +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/opus_packet.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/opus_packet.go index cd5ea332d..89aaae35a 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/opus_packet.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/opus_packet.go @@ -1,27 +1,31 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package codecs -// OpusPayloader payloads Opus packets +// OpusPayloader payloads Opus packets. type OpusPayloader struct{} -// Payload fragments an Opus packet across one or more byte arrays -func (p *OpusPayloader) Payload(mtu uint16, payload []byte) [][]byte { +// Payload fragments an Opus packet across one or more byte arrays. +func (p *OpusPayloader) Payload(_ uint16, payload []byte) [][]byte { if payload == nil { return [][]byte{} } out := make([]byte, len(payload)) copy(out, payload) + return [][]byte{out} } -// OpusPacket represents the Opus header that is stored in the payload of an RTP Packet +// OpusPacket represents the Opus header that is stored in the payload of an RTP Packet. type OpusPacket struct { Payload []byte audioDepacketizer } -// Unmarshal parses the passed byte slice and stores the result in the OpusPacket this method is called upon +// Unmarshal parses the passed byte slice and stores the result in the OpusPacket this method is called upon. func (p *OpusPacket) Unmarshal(packet []byte) ([]byte, error) { if packet == nil { return nil, errNilPacket @@ -30,8 +34,18 @@ func (p *OpusPacket) Unmarshal(packet []byte) ([]byte, error) { } p.Payload = packet + return packet, nil } -// OpusPartitionHeadChecker is obsolete +// OpusPartitionHeadChecker checks Opus partition head. +// +// Deprecated: replaced by OpusPacket.IsPartitionHead(). type OpusPartitionHeadChecker struct{} + +// IsPartitionHead checks whether if this is a head of the Opus partition. +// +// Deprecated: replaced by OpusPacket.IsPartitionHead(). +func (*OpusPartitionHeadChecker) IsPartitionHead(packet []byte) bool { + return (&OpusPacket{}).IsPartitionHead(packet) +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/vp8_packet.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/vp8_packet.go index cd8692904..64471f8af 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/vp8_packet.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/vp8_packet.go @@ -1,6 +1,9 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package codecs -// VP8Payloader payloads VP8 packets +// VP8Payloader payloads VP8 packets. type VP8Payloader struct { EnablePictureID bool pictureID uint16 @@ -10,8 +13,8 @@ const ( vp8HeaderSize = 1 ) -// Payload fragments a VP8 packet across one or more byte arrays -func (p *VP8Payloader) Payload(mtu uint16, payload []byte) [][]byte { +// Payload fragments a VP8 packet across one or more byte arrays. +func (p *VP8Payloader) Payload(mtu uint16, payload []byte) [][]byte { //nolint:cyclop /* * https://tools.ietf.org/html/rfc7741#section-4.2 * @@ -53,12 +56,12 @@ func (p *VP8Payloader) Payload(mtu uint16, payload []byte) [][]byte { var payloads [][]byte // Make sure the fragment/payload size is correct - if min(maxFragmentSize, payloadDataRemaining) <= 0 { + if minInt(maxFragmentSize, payloadDataRemaining) <= 0 { return payloads } first := true for payloadDataRemaining > 0 { - currentFragmentSize := min(maxFragmentSize, payloadDataRemaining) + currentFragmentSize := minInt(maxFragmentSize, payloadDataRemaining) out := make([]byte, usingHeaderSize+currentFragmentSize) if first { @@ -71,12 +74,12 @@ func (p *VP8Payloader) Payload(mtu uint16, payload []byte) [][]byte { case vp8HeaderSize + 2: out[0] |= 0x80 out[1] |= 0x80 - out[2] |= uint8(p.pictureID & 0x7F) + out[2] |= uint8(p.pictureID & 0x7F) // nolint: gosec // G115 false positive case vp8HeaderSize + 3: out[0] |= 0x80 out[1] |= 0x80 - out[2] |= 0x80 | uint8((p.pictureID>>8)&0x7F) - out[3] |= uint8(p.pictureID & 0xFF) + out[2] |= 0x80 | uint8((p.pictureID>>8)&0x7F) // nolint: gosec // G115 false positive + out[3] |= uint8(p.pictureID & 0xFF) // nolint: gosec // G115 false positive } } @@ -93,7 +96,7 @@ func (p *VP8Payloader) Payload(mtu uint16, payload []byte) [][]byte { return payloads } -// VP8Packet represents the VP8 header that is stored in the payload of an RTP Packet +// VP8Packet represents the VP8 header that is stored in the payload of an RTP Packet. type VP8Packet struct { // Required Header X uint8 /* extended control bits present */ @@ -119,20 +122,19 @@ type VP8Packet struct { videoDepacketizer } -// Unmarshal parses the passed byte slice and stores the result in the VP8Packet this method is called upon -func (p *VP8Packet) Unmarshal(payload []byte) ([]byte, error) { +// Unmarshal parses the passed byte slice and stores the result in the VP8Packet this method is called upon. +func (p *VP8Packet) Unmarshal(payload []byte) ([]byte, error) { //nolint:gocognit,cyclop if payload == nil { return nil, errNilPacket } payloadLen := len(payload) - if payloadLen < 4 { - return nil, errShortPacket - } - payloadIndex := 0 + if payloadIndex >= payloadLen { + return nil, errShortPacket + } p.X = (payload[payloadIndex] & 0x80) >> 7 p.N = (payload[payloadIndex] & 0x20) >> 5 p.S = (payload[payloadIndex] & 0x10) >> 4 @@ -141,61 +143,95 @@ func (p *VP8Packet) Unmarshal(payload []byte) ([]byte, error) { payloadIndex++ if p.X == 1 { + if payloadIndex >= payloadLen { + return nil, errShortPacket + } p.I = (payload[payloadIndex] & 0x80) >> 7 p.L = (payload[payloadIndex] & 0x40) >> 6 p.T = (payload[payloadIndex] & 0x20) >> 5 p.K = (payload[payloadIndex] & 0x10) >> 4 payloadIndex++ + } else { + p.I = 0 + p.L = 0 + p.T = 0 + p.K = 0 } + // nolint: nestif if p.I == 1 { // PID present? + if payloadIndex >= payloadLen { + return nil, errShortPacket + } if payload[payloadIndex]&0x80 > 0 { // M == 1, PID is 16bit + if payloadIndex+1 >= payloadLen { + return nil, errShortPacket + } p.PictureID = (uint16(payload[payloadIndex]&0x7F) << 8) | uint16(payload[payloadIndex+1]) payloadIndex += 2 } else { p.PictureID = uint16(payload[payloadIndex]) payloadIndex++ } - } - - if payloadIndex >= payloadLen { - return nil, errShortPacket + } else { + p.PictureID = 0 } if p.L == 1 { + if payloadIndex >= payloadLen { + return nil, errShortPacket + } p.TL0PICIDX = payload[payloadIndex] payloadIndex++ + } else { + p.TL0PICIDX = 0 } - if payloadIndex >= payloadLen { - return nil, errShortPacket - } - - if p.T == 1 || p.K == 1 { + if p.T == 1 || p.K == 1 { // nolint: nestif + if payloadIndex >= payloadLen { + return nil, errShortPacket + } if p.T == 1 { p.TID = payload[payloadIndex] >> 6 p.Y = (payload[payloadIndex] >> 5) & 0x1 + } else { + p.TID = 0 + p.Y = 0 } if p.K == 1 { p.KEYIDX = payload[payloadIndex] & 0x1F + } else { + p.KEYIDX = 0 } payloadIndex++ + } else { + p.TID = 0 + p.Y = 0 + p.KEYIDX = 0 } - if payloadIndex >= payloadLen { - return nil, errShortPacket - } p.Payload = payload[payloadIndex:] + return p.Payload, nil } -// VP8PartitionHeadChecker is obsolete +// VP8PartitionHeadChecker checks VP8 partition head +// +// Deprecated: replaced by VP8Packet.IsPartitionHead(). type VP8PartitionHeadChecker struct{} -// IsPartitionHead checks whether if this is a head of the VP8 partition +// IsPartitionHead checks whether if this is a head of the VP8 partition. +// +// Deprecated: replaced by VP8Packet.IsPartitionHead(). +func (*VP8PartitionHeadChecker) IsPartitionHead(packet []byte) bool { + return (&VP8Packet{}).IsPartitionHead(packet) +} + +// IsPartitionHead checks whether if this is a head of the VP8 partition. func (*VP8Packet) IsPartitionHead(payload []byte) bool { if len(payload) < 1 { return false } + return (payload[0] & 0x10) != 0 } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/vp9/bits.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/vp9/bits.go new file mode 100644 index 000000000..97f7022d2 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/vp9/bits.go @@ -0,0 +1,68 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + +package vp9 + +import "errors" + +var errNotEnoughBits = errors.New("not enough bits") + +func hasSpace(buf []byte, pos int, n int) error { + if n > ((len(buf) * 8) - pos) { + return errNotEnoughBits + } + + return nil +} + +func readFlag(buf []byte, pos *int) (bool, error) { + err := hasSpace(buf, *pos, 1) + if err != nil { + return false, err + } + + return readFlagUnsafe(buf, pos), nil +} + +func readFlagUnsafe(buf []byte, pos *int) bool { + b := (buf[*pos>>0x03] >> (7 - (*pos & 0x07))) & 0x01 + *pos++ + + return b == 1 +} + +func readBits(buf []byte, pos *int, n int) (uint64, error) { + err := hasSpace(buf, *pos, n) + if err != nil { + return 0, err + } + + return readBitsUnsafe(buf, pos, n), nil +} + +func readBitsUnsafe(buf []byte, pos *int, n int) uint64 { + res := 8 - (*pos & 0x07) + if n < res { + bits := uint64((buf[*pos>>0x03] >> (res - n)) & (1<>0x03] & (1<= 8 { + bits = (bits << 8) | uint64(buf[*pos>>0x03]) + *pos += 8 + n -= 8 + } + + if n > 0 { + bits = (bits << n) | uint64(buf[*pos>>0x03]>>(8-n)) + *pos += n + } + + return bits +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/vp9/header.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/vp9/header.go new file mode 100644 index 000000000..263147471 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/vp9/header.go @@ -0,0 +1,225 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + +// Package vp9 contains a VP9 header parser. +package vp9 + +import ( + "errors" +) + +var ( + errInvalidFrameMarker = errors.New("invalid frame marker") + errWrongFrameSyncByte0 = errors.New("wrong frame_sync_byte_0") + errWrongFrameSyncByte1 = errors.New("wrong frame_sync_byte_1") + errWrongFrameSyncByte2 = errors.New("wrong frame_sync_byte_2") +) + +// HeaderColorConfig is the color_config member of an header. +type HeaderColorConfig struct { + TenOrTwelveBit bool + BitDepth uint8 + ColorSpace uint8 + ColorRange bool + SubsamplingX bool + SubsamplingY bool +} + +func (c *HeaderColorConfig) unmarshal(profile uint8, buf []byte, pos *int) error { // nolint:cyclop + if profile >= 2 { + var err error + c.TenOrTwelveBit, err = readFlag(buf, pos) + if err != nil { + return err + } + + if c.TenOrTwelveBit { + c.BitDepth = 12 + } else { + c.BitDepth = 10 + } + } else { + c.BitDepth = 8 + } + + tmp, err := readBits(buf, pos, 3) + if err != nil { + return err + } + c.ColorSpace = uint8(tmp) // nolint: gosec // G115, no overflow we read 3 bits + + if c.ColorSpace != 7 { // nolint: nestif + var err error + c.ColorRange, err = readFlag(buf, pos) + if err != nil { + return err + } + + if profile == 1 || profile == 3 { + err := hasSpace(buf, *pos, 3) + if err != nil { + return err + } + + c.SubsamplingX = readFlagUnsafe(buf, pos) + c.SubsamplingY = readFlagUnsafe(buf, pos) + *pos++ + } else { + c.SubsamplingX = true + c.SubsamplingY = true + } + } else { + c.ColorRange = true + + if profile == 1 || profile == 3 { + c.SubsamplingX = false + c.SubsamplingY = false + + err := hasSpace(buf, *pos, 1) + if err != nil { + return err + } + *pos++ + } + } + + return nil +} + +// HeaderFrameSize is the frame_size member of an header. +type HeaderFrameSize struct { + FrameWidthMinus1 uint16 + FrameHeightMinus1 uint16 +} + +func (s *HeaderFrameSize) unmarshal(buf []byte, pos *int) error { + err := hasSpace(buf, *pos, 32) + if err != nil { + return err + } + + s.FrameWidthMinus1 = uint16(readBitsUnsafe(buf, pos, 16)) // nolint: gosec // G115 no overflow, we read 16 bits + s.FrameHeightMinus1 = uint16(readBitsUnsafe(buf, pos, 16)) // nolint: gosec // G115 + + return nil +} + +// Header is a VP9 Frame header. +// Specification: +// https://storage.googleapis.com/downloads.webmproject.org/docs/vp9/vp9-bitstream-specification-v0.6-20160331-draft.pdf +type Header struct { + Profile uint8 + ShowExistingFrame bool + FrameToShowMapIdx uint8 + NonKeyFrame bool + ShowFrame bool + ErrorResilientMode bool + ColorConfig *HeaderColorConfig + FrameSize *HeaderFrameSize +} + +// Unmarshal decodes a Header. +func (h *Header) Unmarshal(buf []byte) error { //nolint:cyclop + pos := 0 + + err := hasSpace(buf, pos, 4) + if err != nil { + return err + } + + frameMarker := readBitsUnsafe(buf, &pos, 2) + if frameMarker != 2 { + return errInvalidFrameMarker + } + + profileLowBit := uint8(readBitsUnsafe(buf, &pos, 1)) // nolint: gosec // no overflow, we read 1 bit + profileHighBit := uint8(readBitsUnsafe(buf, &pos, 1)) // nolint: gosec // G115 + h.Profile = profileHighBit<<1 + profileLowBit + + if h.Profile == 3 { + err = hasSpace(buf, pos, 1) + if err != nil { + return err + } + pos++ + } + + h.ShowExistingFrame, err = readFlag(buf, &pos) + if err != nil { + return err + } + + if h.ShowExistingFrame { + var tmp uint64 + tmp, err = readBits(buf, &pos, 3) + if err != nil { + return err + } + h.FrameToShowMapIdx = uint8(tmp) // nolint: gosec // no overflow, we read 3 bits + + return nil + } + + err = hasSpace(buf, pos, 3) + if err != nil { + return err + } + + h.NonKeyFrame = readFlagUnsafe(buf, &pos) + h.ShowFrame = readFlagUnsafe(buf, &pos) + h.ErrorResilientMode = readFlagUnsafe(buf, &pos) + + if !h.NonKeyFrame { // nolint: nestif + err := hasSpace(buf, pos, 24) + if err != nil { + return err + } + + frameSyncByte0 := uint8(readBitsUnsafe(buf, &pos, 8)) // nolint: gosec // no overflow, we read 8 bits + if frameSyncByte0 != 0x49 { + return errWrongFrameSyncByte0 + } + + frameSyncByte1 := uint8(readBitsUnsafe(buf, &pos, 8)) // nolint: gosec // no overflow, we read 8 bits + if frameSyncByte1 != 0x83 { + return errWrongFrameSyncByte1 + } + + frameSyncByte2 := uint8(readBitsUnsafe(buf, &pos, 8)) // nolint: gosec // no overflow, we read 8 bits + if frameSyncByte2 != 0x42 { + return errWrongFrameSyncByte2 + } + + h.ColorConfig = &HeaderColorConfig{} + err = h.ColorConfig.unmarshal(h.Profile, buf, &pos) + if err != nil { + return err + } + + h.FrameSize = &HeaderFrameSize{} + err = h.FrameSize.unmarshal(buf, &pos) + if err != nil { + return err + } + } + + return nil +} + +// Width returns the video width. +func (h Header) Width() uint16 { + if h.FrameSize == nil { + return 0 + } + + return h.FrameSize.FrameWidthMinus1 + 1 +} + +// Height returns the video height. +func (h Header) Height() uint16 { + if h.FrameSize == nil { + return 0 + } + + return h.FrameSize.FrameHeightMinus1 + 1 +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/vp9_packet.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/vp9_packet.go index 917e630bb..bbae1ce7b 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/vp9_packet.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/codecs/vp9_packet.go @@ -1,32 +1,62 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package codecs import ( "github.com/pion/randutil" + "github.com/pion/rtp/codecs/vp9" ) // Use global random generator to properly seed by crypto grade random. var globalMathRandomGenerator = randutil.NewMathRandomGenerator() // nolint:gochecknoglobals -// VP9Payloader payloads VP9 packets +// VP9Payloader payloads VP9 packets. type VP9Payloader struct { - pictureID uint16 - initialized bool + // whether to use flexible mode or non-flexible mode. + FlexibleMode bool // InitialPictureIDFn is a function that returns random initial picture ID. InitialPictureIDFn func() uint16 + + pictureID uint16 + initialized bool } const ( - vp9HeaderSize = 3 // Flexible mode 15 bit picture ID maxSpatialLayers = 5 maxVP9RefPics = 3 ) -// Payload fragments an VP9 packet across one or more byte arrays +// Payload fragments an VP9 packet across one or more byte arrays. func (p *VP9Payloader) Payload(mtu uint16, payload []byte) [][]byte { + if !p.initialized { + if p.InitialPictureIDFn == nil { + p.InitialPictureIDFn = func() uint16 { + return uint16(globalMathRandomGenerator.Intn(0x7FFF)) // nolint: gosec + } + } + p.pictureID = p.InitialPictureIDFn() & 0x7FFF + p.initialized = true + } + + var payloads [][]byte + if p.FlexibleMode { + payloads = p.payloadFlexible(mtu, payload) + } else { + payloads = p.payloadNonFlexible(mtu, payload) + } + + p.pictureID++ + if p.pictureID >= 0x8000 { + p.pictureID = 0 + } + + return payloads +} + +func (p *VP9Payloader) payloadFlexible(mtu uint16, payload []byte) [][]byte { /* - * https://www.ietf.org/id/draft-ietf-payload-vp9-13.txt - * * Flexible mode (F=1) * 0 1 2 3 4 5 6 7 * +-+-+-+-+-+-+-+-+ @@ -43,7 +73,45 @@ func (p *VP9Payloader) Payload(mtu uint16, payload []byte) [][]byte { * V: | SS | * | .. | * +-+-+-+-+-+-+-+-+ - * + */ + + headerSize := 3 + maxFragmentSize := int(mtu) - headerSize + payloadDataRemaining := len(payload) + payloadDataIndex := 0 + var payloads [][]byte + + if minInt(maxFragmentSize, payloadDataRemaining) <= 0 { + return [][]byte{} + } + + for payloadDataRemaining > 0 { + currentFragmentSize := minInt(maxFragmentSize, payloadDataRemaining) + out := make([]byte, headerSize+currentFragmentSize) + + out[0] = 0x90 // F=1, I=1 + if payloadDataIndex == 0 { + out[0] |= 0x08 // B=1 + } + if payloadDataRemaining == currentFragmentSize { + out[0] |= 0x04 // E=1 + } + + out[1] = byte(p.pictureID>>8) | 0x80 + out[2] = byte(p.pictureID) + + copy(out[headerSize:], payload[payloadDataIndex:payloadDataIndex+currentFragmentSize]) + payloads = append(payloads, out) + + payloadDataRemaining -= currentFragmentSize + payloadDataIndex += currentFragmentSize + } + + return payloads +} + +func (p *VP9Payloader) payloadNonFlexible(mtu uint16, payload []byte) [][]byte { //nolint:cyclop + /* * Non-flexible mode (F=0) * 0 1 2 3 4 5 6 7 * +-+-+-+-+-+-+-+-+ @@ -62,56 +130,85 @@ func (p *VP9Payloader) Payload(mtu uint16, payload []byte) [][]byte { * +-+-+-+-+-+-+-+-+ */ - if !p.initialized { - if p.InitialPictureIDFn == nil { - p.InitialPictureIDFn = func() uint16 { - return uint16(globalMathRandomGenerator.Intn(0x7FFF)) - } - } - p.pictureID = p.InitialPictureIDFn() & 0x7FFF - p.initialized = true - } - if payload == nil { + var header vp9.Header + err := header.Unmarshal(payload) + if err != nil { return [][]byte{} } - maxFragmentSize := int(mtu) - vp9HeaderSize payloadDataRemaining := len(payload) payloadDataIndex := 0 - - if min(maxFragmentSize, payloadDataRemaining) <= 0 { - return [][]byte{} - } - var payloads [][]byte - for payloadDataRemaining > 0 { - currentFragmentSize := min(maxFragmentSize, payloadDataRemaining) - out := make([]byte, vp9HeaderSize+currentFragmentSize) - out[0] = 0x90 // F=1 I=1 + for payloadDataRemaining > 0 { + var headerSize int + if !header.NonKeyFrame && payloadDataIndex == 0 { + headerSize = 3 + 8 + } else { + headerSize = 3 + } + + maxFragmentSize := int(mtu) - headerSize + currentFragmentSize := minInt(maxFragmentSize, payloadDataRemaining) + if currentFragmentSize <= 0 { + return [][]byte{} + } + + out := make([]byte, headerSize+currentFragmentSize) + + out[0] = 0x80 | 0x01 // I=1, Z=1 + + if header.NonKeyFrame { + out[0] |= 0x40 // P=1 + } if payloadDataIndex == 0 { out[0] |= 0x08 // B=1 } if payloadDataRemaining == currentFragmentSize { out[0] |= 0x04 // E=1 } + out[1] = byte(p.pictureID>>8) | 0x80 out[2] = byte(p.pictureID) - copy(out[vp9HeaderSize:], payload[payloadDataIndex:payloadDataIndex+currentFragmentSize]) + off := 3 + + if !header.NonKeyFrame && payloadDataIndex == 0 { + out[0] |= 0x02 // V=1 + out[off] = 0x10 | 0x08 // N_S=0, Y=1, G=1 + off++ + + width := header.Width() + out[off] = byte(width >> 8) + off++ + out[off] = byte(width & 0xFF) + off++ + + height := header.Height() + out[off] = byte(height >> 8) + off++ + out[off] = byte(height & 0xFF) + off++ + + out[off] = 0x01 // N_G=1 + off++ + + out[off] = 1<<4 | 1<<2 // TID=0, U=1, R=1 + off++ + + out[off] = 0x01 // P_DIFF=1 + } + + copy(out[headerSize:], payload[payloadDataIndex:payloadDataIndex+currentFragmentSize]) payloads = append(payloads, out) payloadDataRemaining -= currentFragmentSize payloadDataIndex += currentFragmentSize } - p.pictureID++ - if p.pictureID >= 0x8000 { - p.pictureID = 0 - } return payloads } -// VP9Packet represents the VP9 header that is stored in the payload of an RTP Packet +// VP9Packet represents the VP9 header that is stored in the payload of an RTP Packet. type VP9Packet struct { // Required header I bool // PictureID is present @@ -152,8 +249,8 @@ type VP9Packet struct { videoDepacketizer } -// Unmarshal parses the passed byte slice and stores the result in the VP9Packet this method is called upon -func (p *VP9Packet) Unmarshal(packet []byte) ([]byte, error) { +// Unmarshal parses the passed byte slice and stores the result in the VP9Packet this method is called upon. +func (p *VP9Packet) Unmarshal(packet []byte) ([]byte, error) { // nolint:cyclop if packet == nil { return nil, errNilPacket } @@ -202,17 +299,19 @@ func (p *VP9Packet) Unmarshal(packet []byte) ([]byte, error) { } p.Payload = packet[pos:] + return p.Payload, nil } // Picture ID: -// -// +-+-+-+-+-+-+-+-+ -// I: |M| PICTURE ID | M:0 => picture id is 7 bits. -// +-+-+-+-+-+-+-+-+ M:1 => picture id is 15 bits. -// M: | EXTENDED PID | -// +-+-+-+-+-+-+-+-+ -// +/* +* +-+-+-+-+-+-+-+-+ +* I: |M| PICTURE ID | M:0 => picture id is 7 bits. +* +-+-+-+-+-+-+-+-+ M:1 => picture id is 15 bits. +* M: | EXTENDED PID | +* +-+-+-+-+-+-+-+-+ +**/ +// . func (p *VP9Packet) parsePictureID(packet []byte, pos int) (int, error) { if len(packet) <= pos { return pos, errShortPacket @@ -227,6 +326,7 @@ func (p *VP9Packet) parsePictureID(packet []byte, pos int) (int, error) { p.PictureID = p.PictureID<<8 | uint16(packet[pos]) } pos++ + return pos, nil } @@ -244,11 +344,12 @@ func (p *VP9Packet) parseLayerInfo(packet []byte, pos int) (int, error) { } // Layer indices (flexible mode): -// -// +-+-+-+-+-+-+-+-+ -// L: | T |U| S |D| -// +-+-+-+-+-+-+-+-+ -// +/* +* +-+-+-+-+-+-+-+-+ +* L: | T |U| S |D| +* +-+-+-+-+-+-+-+-+ +**/ +// . func (p *VP9Packet) parseLayerInfoCommon(packet []byte, pos int) (int, error) { if len(packet) <= pos { return pos, errShortPacket @@ -264,17 +365,19 @@ func (p *VP9Packet) parseLayerInfoCommon(packet []byte, pos int) (int, error) { } pos++ + return pos, nil } // Layer indices (non-flexible mode): -// -// +-+-+-+-+-+-+-+-+ -// L: | T |U| S |D| -// +-+-+-+-+-+-+-+-+ -// | TL0PICIDX | -// +-+-+-+-+-+-+-+-+ -// +/* +* +-+-+-+-+-+-+-+-+ +* L: | T |U| S |D| +* +-+-+-+-+-+-+-+-+ +* | TL0PICIDX | +* +-+-+-+-+-+-+-+-+ +**/ +// . func (p *VP9Packet) parseLayerInfoNonFlexibleMode(packet []byte, pos int) (int, error) { if len(packet) <= pos { return pos, errShortPacket @@ -282,16 +385,19 @@ func (p *VP9Packet) parseLayerInfoNonFlexibleMode(packet []byte, pos int) (int, p.TL0PICIDX = packet[pos] pos++ + return pos, nil } -// Reference indices: -// -// +-+-+-+-+-+-+-+-+ P=1,F=1: At least one reference index -// P,F: | P_DIFF |N| up to 3 times has to be specified. -// +-+-+-+-+-+-+-+-+ N=1: An additional P_DIFF follows -// current P_DIFF. -// +// Reference indices: . +/* +* +-+-+-+-+-+-+-+-+ P=1,F=1: At least one reference index +* P,F: | P_DIFF |N| up to 3 times has to be specified. +* +-+-+-+-+-+-+-+-+ N=1: An additional P_DIFF follows +* current P_DIFF. +* +**/ +// . func (p *VP9Packet) parseRefIndices(packet []byte, pos int) (int, error) { for { if len(packet) <= pos { @@ -312,33 +418,34 @@ func (p *VP9Packet) parseRefIndices(packet []byte, pos int) (int, error) { } // Scalability structure (SS): -// -// +-+-+-+-+-+-+-+-+ -// V: | N_S |Y|G|-|-|-| -// +-+-+-+-+-+-+-+-+ -| -// Y: | WIDTH | (OPTIONAL) . -// + + . -// | | (OPTIONAL) . -// +-+-+-+-+-+-+-+-+ . N_S + 1 times -// | HEIGHT | (OPTIONAL) . -// + + . -// | | (OPTIONAL) . -// +-+-+-+-+-+-+-+-+ -| -// G: | N_G | (OPTIONAL) -// +-+-+-+-+-+-+-+-+ -| -// N_G: | T |U| R |-|-| (OPTIONAL) . -// +-+-+-+-+-+-+-+-+ -| . N_G times -// | P_DIFF | (OPTIONAL) . R times . -// +-+-+-+-+-+-+-+-+ -| -| -// -func (p *VP9Packet) parseSSData(packet []byte, pos int) (int, error) { +/* +* +-+-+-+-+-+-+-+-+ +* V: | N_S |Y|G|-|-|-| +* +-+-+-+-+-+-+-+-+ -| +* Y: | WIDTH | (OPTIONAL) . +* + . +* | | (OPTIONAL) . +* +-+-+-+-+-+-+-+-+ . N_S + 1 times +* | HEIGHT | (OPTIONAL) . +* + . +* | | (OPTIONAL) . +* +-+-+-+-+-+-+-+-+ -| +* G: | N_G | (OPTIONAL) +* +-+-+-+-+-+-+-+-+ -| +* N_G: | T |U| R |-|-| (OPTIONAL) . +* +-+-+-+-+-+-+-+-+ -| . N_G times +* | P_DIFF | (OPTIONAL) . R times . +* +-+-+-+-+-+-+-+-+ -| -| +**/ +// . +func (p *VP9Packet) parseSSData(packet []byte, pos int) (int, error) { // nolint: cyclop if len(packet) <= pos { return pos, errShortPacket } p.NS = packet[pos] >> 5 p.Y = packet[pos]&0x10 != 0 - p.G = (packet[pos]>>1)&0x7 != 0 + p.G = packet[pos]&0x8 != 0 pos++ NS := p.NS + 1 @@ -348,6 +455,10 @@ func (p *VP9Packet) parseSSData(packet []byte, pos int) (int, error) { p.Width = make([]uint16, NS) p.Height = make([]uint16, NS) for i := 0; i < int(NS); i++ { + if len(packet) <= (pos + 3) { + return pos, errShortPacket + } + p.Width[i] = uint16(packet[pos])<<8 | uint16(packet[pos+1]) pos += 2 p.Height[i] = uint16(packet[pos])<<8 | uint16(packet[pos+1]) @@ -356,17 +467,30 @@ func (p *VP9Packet) parseSSData(packet []byte, pos int) (int, error) { } if p.G { + if len(packet) <= pos { + return pos, errShortPacket + } + p.NG = packet[pos] pos++ } for i := 0; i < int(p.NG); i++ { + if len(packet) <= pos { + return pos, errShortPacket + } + p.PGTID = append(p.PGTID, packet[pos]>>5) p.PGU = append(p.PGU, packet[pos]&0x10 != 0) R := (packet[pos] >> 2) & 0x3 pos++ p.PGPDiff = append(p.PGPDiff, []uint8{}) + + if len(packet) <= (pos + int(R) - 1) { + return pos, errShortPacket + } + for j := 0; j < int(R); j++ { p.PGPDiff[i] = append(p.PGPDiff[i], packet[pos]) pos++ @@ -376,13 +500,23 @@ func (p *VP9Packet) parseSSData(packet []byte, pos int) (int, error) { return pos, nil } -// VP9PartitionHeadChecker is obsolete +// VP9PartitionHeadChecker checks VP9 partition head. +// +// Deprecated: replaced by VP9Packet.IsPartitionHead(). type VP9PartitionHeadChecker struct{} -// IsPartitionHead checks whether if this is a head of the VP9 partition +// IsPartitionHead checks whether if this is a head of the VP9 partition. +// +// Deprecated: replaced by VP9Packet.IsPartitionHead(). +func (*VP9PartitionHeadChecker) IsPartitionHead(packet []byte) bool { + return (&VP9Packet{}).IsPartitionHead(packet) +} + +// IsPartitionHead checks whether if this is a head of the VP9 partition. func (*VP9Packet) IsPartitionHead(payload []byte) bool { if len(payload) < 1 { return false } + return (payload[0] & 0x08) != 0 } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/depacketizer.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/depacketizer.go index c66d2e30c..3027ae677 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/depacketizer.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/depacketizer.go @@ -1,12 +1,19 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package rtp -// Depacketizer depacketizes a RTP payload, removing any RTP specific data from the payload +// Depacketizer depacketizes a RTP payload, removing any RTP specific data from the payload. type Depacketizer interface { + // Unmarshal parses the RTP payload and returns media. + // Metadata may be stored on the Depacketizer itself Unmarshal(packet []byte) ([]byte, error) + // Checks if the packet is at the beginning of a partition. This // should return false if the result could not be determined, in // which case the caller will detect timestamp discontinuities. IsPartitionHead(payload []byte) bool + // Checks if the packet is at the end of a partition. This should // return false if the result could not be determined. IsPartitionTail(marker bool, payload []byte) bool diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/error.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/error.go index 5458c6fa5..eb78874ad 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/error.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/error.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package rtp import ( @@ -11,11 +14,21 @@ var ( errHeaderExtensionsNotEnabled = errors.New("h.Extension not enabled") errHeaderExtensionNotFound = errors.New("extension not found") - errRFC8285OneByteHeaderIDRange = errors.New("header extension id must be between 1 and 14 for RFC 5285 one byte extensions") - errRFC8285OneByteHeaderSize = errors.New("header extension payload must be 16bytes or less for RFC 5285 one byte extensions") + errRFC8285OneByteHeaderIDRange = errors.New( + "header extension id must be between 1 and 14 for RFC 5285 one byte extensions", + ) + errRFC8285OneByteHeaderSize = errors.New( + "header extension payload must be 16bytes or less for RFC 5285 one byte extensions", + ) - errRFC8285TwoByteHeaderIDRange = errors.New("header extension id must be between 1 and 255 for RFC 5285 two byte extensions") - errRFC8285TwoByteHeaderSize = errors.New("header extension payload must be 255bytes or less for RFC 5285 two byte extensions") + errRFC8285TwoByteHeaderIDRange = errors.New( + "header extension id must be between 1 and 255 for RFC 5285 two byte extensions", + ) + errRFC8285TwoByteHeaderSize = errors.New( + "header extension payload must be 255bytes or less for RFC 5285 two byte extensions", + ) errRFC3550HeaderIDRange = errors.New("header extension id must be 0 for non-RFC 5285 extensions") + + errInvalidRTPPadding = errors.New("invalid RTP padding") ) diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/header_extension.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/header_extension.go index c143ac119..b36d09af8 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/header_extension.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/header_extension.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package rtp import ( @@ -42,22 +45,25 @@ func (e *OneByteHeaderExtension) Set(id uint8, buf []byte) error { for n := 4; n < len(e.payload); { if e.payload[n] == 0x00 { // padding n++ + continue } extid := e.payload[n] >> 4 - len := int(e.payload[n]&^0xF0 + 1) + payloadLen := int(e.payload[n]&^0xF0 + 1) n++ if extid == id { - e.payload = append(e.payload[:n+1], append(buf, e.payload[n+1+len:]...)...) + e.payload = append(e.payload[:n+1], append(buf, e.payload[n+1+payloadLen:]...)...) + return nil } - n += len + n += payloadLen } - e.payload = append(e.payload, (id<<4 | uint8(len(buf)-1))) + e.payload = append(e.payload, (id<<4 | uint8(len(buf)-1))) // nolint: gosec // G115 e.payload = append(e.payload, buf...) binary.BigEndian.PutUint16(e.payload[2:4], binary.BigEndian.Uint16(e.payload[2:4])+1) + return nil } @@ -67,11 +73,12 @@ func (e *OneByteHeaderExtension) GetIDs() []uint8 { for n := 4; n < len(e.payload); { if e.payload[n] == 0x00 { // padding n++ + continue } extid := e.payload[n] >> 4 - len := int(e.payload[n]&^0xF0 + 1) + payloadLen := int(e.payload[n]&^0xF0 + 1) n++ if extid == headerExtensionIDReserved { @@ -79,8 +86,9 @@ func (e *OneByteHeaderExtension) GetIDs() []uint8 { } ids = append(ids, extid) - n += len + n += payloadLen } + return ids } @@ -89,18 +97,20 @@ func (e *OneByteHeaderExtension) Get(id uint8) []byte { for n := 4; n < len(e.payload); { if e.payload[n] == 0x00 { // padding n++ + continue } extid := e.payload[n] >> 4 - len := int(e.payload[n]&^0xF0 + 1) + payloadLen := int(e.payload[n]&^0xF0 + 1) n++ if extid == id { - return e.payload[n : n+len] + return e.payload[n : n+payloadLen] } - n += len + n += payloadLen } + return nil } @@ -109,18 +119,21 @@ func (e *OneByteHeaderExtension) Del(id uint8) error { for n := 4; n < len(e.payload); { if e.payload[n] == 0x00 { // padding n++ + continue } extid := e.payload[n] >> 4 - len := int(e.payload[n]&^0xF0 + 1) + payloadLen := int(e.payload[n]&^0xF0 + 1) if extid == id { - e.payload = append(e.payload[:n], e.payload[n+1+len:]...) + e.payload = append(e.payload[:n], e.payload[n+1+payloadLen:]...) + return nil } - n += len + 1 + n += payloadLen + 1 } + return errHeaderExtensionNotFound } @@ -131,6 +144,7 @@ func (e *OneByteHeaderExtension) Unmarshal(buf []byte) (int, error) { return 0, fmt.Errorf("%w actual(%x)", errHeaderExtensionNotFound, buf[0:2]) } e.payload = buf + return len(buf), nil } @@ -145,6 +159,7 @@ func (e OneByteHeaderExtension) MarshalTo(buf []byte) (int, error) { if size > len(buf) { return 0, io.ErrShortBuffer } + return copy(buf, e.payload), nil } @@ -160,7 +175,7 @@ type TwoByteHeaderExtension struct { // Set sets the extension payload for the specified ID. func (e *TwoByteHeaderExtension) Set(id uint8, buf []byte) error { - if id < 1 || id > 255 { + if id < 1 { return fmt.Errorf("%w actual(%d)", errRFC8285TwoByteHeaderIDRange, id) } if len(buf) > 255 { @@ -170,24 +185,27 @@ func (e *TwoByteHeaderExtension) Set(id uint8, buf []byte) error { for n := 4; n < len(e.payload); { if e.payload[n] == 0x00 { // padding n++ + continue } extid := e.payload[n] n++ - len := int(e.payload[n]) + payloadLen := int(e.payload[n]) n++ if extid == id { - e.payload = append(e.payload[:n+2], append(buf, e.payload[n+2+len:]...)...) + e.payload = append(e.payload[:n+2], append(buf, e.payload[n+2+payloadLen:]...)...) + return nil } - n += len + n += payloadLen } - e.payload = append(e.payload, id, uint8(len(buf))) + e.payload = append(e.payload, id, uint8(len(buf))) // nolint: gosec // G115 e.payload = append(e.payload, buf...) binary.BigEndian.PutUint16(e.payload[2:4], binary.BigEndian.Uint16(e.payload[2:4])+1) + return nil } @@ -197,18 +215,20 @@ func (e *TwoByteHeaderExtension) GetIDs() []uint8 { for n := 4; n < len(e.payload); { if e.payload[n] == 0x00 { // padding n++ + continue } extid := e.payload[n] n++ - len := int(e.payload[n]) + payloadLen := int(e.payload[n]) n++ ids = append(ids, extid) - n += len + n += payloadLen } + return ids } @@ -217,20 +237,22 @@ func (e *TwoByteHeaderExtension) Get(id uint8) []byte { for n := 4; n < len(e.payload); { if e.payload[n] == 0x00 { // padding n++ + continue } extid := e.payload[n] n++ - len := int(e.payload[n]) + payloadLen := int(e.payload[n]) n++ if extid == id { - return e.payload[n : n+len] + return e.payload[n : n+payloadLen] } - n += len + n += payloadLen } + return nil } @@ -239,19 +261,22 @@ func (e *TwoByteHeaderExtension) Del(id uint8) error { for n := 4; n < len(e.payload); { if e.payload[n] == 0x00 { // padding n++ + continue } extid := e.payload[n] - len := int(e.payload[n+1]) + payloadLen := int(e.payload[n+1]) if extid == id { - e.payload = append(e.payload[:n], e.payload[n+2+len:]...) + e.payload = append(e.payload[:n], e.payload[n+2+payloadLen:]...) + return nil } - n += len + 2 + n += payloadLen + 2 } + return errHeaderExtensionNotFound } @@ -262,6 +287,7 @@ func (e *TwoByteHeaderExtension) Unmarshal(buf []byte) (int, error) { return 0, fmt.Errorf("%w actual(%x)", errHeaderExtensionNotFound, buf[0:2]) } e.payload = buf + return len(buf), nil } @@ -276,6 +302,7 @@ func (e TwoByteHeaderExtension) MarshalTo(buf []byte) (int, error) { if size > len(buf) { return 0, io.ErrShortBuffer } + return copy(buf, e.payload), nil } @@ -295,6 +322,7 @@ func (e *RawExtension) Set(id uint8, payload []byte) error { return fmt.Errorf("%w actual(%d)", errRFC3550HeaderIDRange, id) } e.payload = payload + return nil } @@ -308,6 +336,7 @@ func (e *RawExtension) Get(id uint8) []byte { if id == 0 { return e.payload } + return nil } @@ -315,8 +344,10 @@ func (e *RawExtension) Get(id uint8) []byte { func (e *RawExtension) Del(id uint8) error { if id == 0 { e.payload = nil + return nil } + return fmt.Errorf("%w actual(%d)", errRFC3550HeaderIDRange, id) } @@ -327,6 +358,7 @@ func (e *RawExtension) Unmarshal(buf []byte) (int, error) { return 0, fmt.Errorf("%w actual(%x)", errHeaderExtensionNotFound, buf[0:2]) } e.payload = buf + return len(buf), nil } @@ -341,6 +373,7 @@ func (e RawExtension) MarshalTo(buf []byte) (int, error) { if size > len(buf) { return 0, io.ErrShortBuffer } + return copy(buf, e.payload), nil } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/packet.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/packet.go index b3ae12400..c51d8c7d8 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/packet.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/packet.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package rtp import ( @@ -6,13 +9,13 @@ import ( "io" ) -// Extension RTP Header extension +// Extension RTP Header extension. type Extension struct { id uint8 payload []byte } -// Header represents an RTP packet header +// Header represents an RTP packet header. type Header struct { Version uint8 Padding bool @@ -25,13 +28,19 @@ type Header struct { CSRC []uint32 ExtensionProfile uint16 Extensions []Extension + + // Deprecated: will be removed in a future version. + PayloadOffset int } -// Packet represents an RTP Packet +// Packet represents an RTP Packet. type Packet struct { Header Payload []byte PaddingSize byte + + // Deprecated: will be removed in a future version. + Raw []byte } const ( @@ -59,7 +68,7 @@ const ( csrcLength = 4 ) -// String helps with debugging by printing packet information in a readable way +// String helps with debugging by printing packet information in a readable way. func (p Packet) String() string { out := "RTP PACKET:\n" @@ -76,7 +85,7 @@ func (p Packet) String() string { // Unmarshal parses the passed byte slice and stores the result in the Header. // It returns the number of bytes read n and any error. -func (h *Header) Unmarshal(buf []byte) (n int, err error) { //nolint:gocognit +func (h *Header) Unmarshal(buf []byte) (n int, err error) { //nolint:gocognit,cyclop if len(buf) < headerLength { return 0, fmt.Errorf("%w: %d < %d", errHeaderSizeInsufficient, len(buf), headerLength) } @@ -128,7 +137,7 @@ func (h *Header) Unmarshal(buf []byte) (n int, err error) { //nolint:gocognit h.Extensions = h.Extensions[:0] } - if h.Extension { + if h.Extension { // nolint: nestif if expected := n + 4; len(buf) < expected { return n, fmt.Errorf("size %d < %d: %w", len(buf), expected, @@ -140,68 +149,61 @@ func (h *Header) Unmarshal(buf []byte) (n int, err error) { //nolint:gocognit n += 2 extensionLength := int(binary.BigEndian.Uint16(buf[n:])) * 4 n += 2 + extensionEnd := n + extensionLength - if expected := n + extensionLength; len(buf) < expected { - return n, fmt.Errorf("size %d < %d: %w", - len(buf), expected, - errHeaderSizeInsufficientForExtension, - ) + if len(buf) < extensionEnd { + return n, fmt.Errorf("size %d < %d: %w", len(buf), extensionEnd, errHeaderSizeInsufficientForExtension) } - switch h.ExtensionProfile { - // RFC 8285 RTP One Byte Header Extension - case extensionProfileOneByte: - end := n + extensionLength - for n < end { + if h.ExtensionProfile == extensionProfileOneByte || h.ExtensionProfile == extensionProfileTwoByte { + var ( + extid uint8 + payloadLen int + ) + + for n < extensionEnd { if buf[n] == 0x00 { // padding n++ + continue } - extid := buf[n] >> 4 - len := int(buf[n]&^0xF0 + 1) - n++ - - if extid == extensionIDReserved { - break - } - - extension := Extension{id: extid, payload: buf[n : n+len]} - h.Extensions = append(h.Extensions, extension) - n += len - } - - // RFC 8285 RTP Two Byte Header Extension - case extensionProfileTwoByte: - end := n + extensionLength - for n < end { - if buf[n] == 0x00 { // padding + if h.ExtensionProfile == extensionProfileOneByte { + extid = buf[n] >> 4 + payloadLen = int(buf[n]&^0xF0 + 1) + n++ + + if extid == extensionIDReserved { + break + } + } else { + extid = buf[n] + n++ + + if len(buf) <= n { + return n, fmt.Errorf("size %d < %d: %w", len(buf), n, errHeaderSizeInsufficientForExtension) + } + + payloadLen = int(buf[n]) n++ - continue } - extid := buf[n] - n++ + if extensionPayloadEnd := n + payloadLen; len(buf) <= extensionPayloadEnd { + return n, fmt.Errorf("size %d < %d: %w", len(buf), extensionPayloadEnd, errHeaderSizeInsufficientForExtension) + } - len := int(buf[n]) - n++ - - extension := Extension{id: extid, payload: buf[n : n+len]} + extension := Extension{id: extid, payload: buf[n : n+payloadLen]} h.Extensions = append(h.Extensions, extension) - n += len + n += payloadLen } - - default: // RFC3550 Extension - if len(buf) < n+extensionLength { - return n, fmt.Errorf("%w: %d < %d", - errHeaderSizeInsufficientForExtension, len(buf), n+extensionLength) - } - - extension := Extension{id: 0, payload: buf[n : n+extensionLength]} + } else { + // RFC3550 Extension + extension := Extension{id: 0, payload: buf[n:extensionEnd]} h.Extensions = append(h.Extensions, extension) n += len(h.Extensions[0].payload) } } + return n, nil } @@ -211,15 +213,23 @@ func (p *Packet) Unmarshal(buf []byte) error { if err != nil { return err } + end := len(buf) if p.Header.Padding { + if end <= n { + return errTooSmall + } p.PaddingSize = buf[end-1] end -= int(p.PaddingSize) + } else { + p.PaddingSize = 0 } if end < n { return errTooSmall } + p.Payload = buf[n:end] + return nil } @@ -231,11 +241,12 @@ func (h Header) Marshal() (buf []byte, err error) { if err != nil { return nil, err } + return buf[:n], nil } // MarshalTo serializes the header and writes to the buffer. -func (h Header) MarshalTo(buf []byte) (n int, err error) { +func (h Header) MarshalTo(buf []byte) (n int, err error) { //nolint:cyclop /* * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 @@ -258,7 +269,7 @@ func (h Header) MarshalTo(buf []byte) (n int, err error) { // The first byte contains the version, padding bit, extension bit, // and csrc size. - buf[0] = (h.Version << versionShift) | uint8(len(h.CSRC)) + buf[0] = (h.Version << versionShift) | uint8(len(h.CSRC)) // nolint: gosec // G115 if h.Padding { buf[0] |= 1 << paddingShift } @@ -293,7 +304,7 @@ func (h Header) MarshalTo(buf []byte) (n int, err error) { // RFC 8285 RTP One Byte Header Extension case extensionProfileOneByte: for _, extension := range h.Extensions { - buf[n] = extension.id<<4 | (uint8(len(extension.payload)) - 1) + buf[n] = extension.id<<4 | (uint8(len(extension.payload)) - 1) // nolint: gosec // G115 n++ n += copy(buf[n:], extension.payload) } @@ -302,7 +313,7 @@ func (h Header) MarshalTo(buf []byte) (n int, err error) { for _, extension := range h.Extensions { buf[n] = extension.id n++ - buf[n] = uint8(len(extension.payload)) + buf[n] = uint8(len(extension.payload)) // nolint: gosec // G115 n++ n += copy(buf[n:], extension.payload) } @@ -319,6 +330,7 @@ func (h Header) MarshalTo(buf []byte) (n int, err error) { extSize := n - startExtensionsPos roundedExtSize := ((extSize + 3) / 4) * 4 + // nolint: gosec // G115 false positive binary.BigEndian.PutUint16(buf[extHeaderPos+2:extHeaderPos+4], uint16(roundedExtSize/4)) // add padding to reach 4 bytes boundaries @@ -361,9 +373,9 @@ func (h Header) MarshalSize() int { return size } -// SetExtension sets an RTP header extension -func (h *Header) SetExtension(id uint8, payload []byte) error { //nolint:gocognit - if h.Extension { +// SetExtension sets an RTP header extension. +func (h *Header) SetExtension(id uint8, payload []byte) error { //nolint:gocognit, cyclop + if h.Extension { // nolint: nestif switch h.ExtensionProfile { // RFC 8285 RTP One Byte Header Extension case extensionProfileOneByte: @@ -375,7 +387,7 @@ func (h *Header) SetExtension(id uint8, payload []byte) error { //nolint:gocogni } // RFC 8285 RTP Two Byte Header Extension case extensionProfileTwoByte: - if id < 1 || id > 255 { + if id < 1 { return fmt.Errorf("%w actual(%d)", errRFC8285TwoByteHeaderIDRange, id) } if len(payload) > 255 { @@ -391,28 +403,32 @@ func (h *Header) SetExtension(id uint8, payload []byte) error { //nolint:gocogni for i, extension := range h.Extensions { if extension.id == id { h.Extensions[i].payload = payload + return nil } } + h.Extensions = append(h.Extensions, Extension{id: id, payload: payload}) + return nil } // No existing header extensions h.Extension = true - switch len := len(payload); { - case len <= 16: + switch payloadLen := len(payload); { + case payloadLen <= 16: h.ExtensionProfile = extensionProfileOneByte - case len > 16 && len < 256: + case payloadLen > 16 && payloadLen < 256: h.ExtensionProfile = extensionProfileTwoByte } h.Extensions = append(h.Extensions, Extension{id: id, payload: payload}) + return nil } -// GetExtensionIDs returns an extension id array +// GetExtensionIDs returns an extension id array. func (h *Header) GetExtensionIDs() []uint8 { if !h.Extension { return nil @@ -426,10 +442,11 @@ func (h *Header) GetExtensionIDs() []uint8 { for _, extension := range h.Extensions { ids = append(ids, extension.id) } + return ids } -// GetExtension returns an RTP header extension +// GetExtension returns an RTP header extension. func (h *Header) GetExtension(id uint8) []byte { if !h.Extension { return nil @@ -439,10 +456,11 @@ func (h *Header) GetExtension(id uint8) []byte { return extension.payload } } + return nil } -// DelExtension Removes an RTP Header extension +// DelExtension Removes an RTP Header extension. func (h *Header) DelExtension(id uint8) error { if !h.Extension { return errHeaderExtensionsNotEnabled @@ -450,9 +468,11 @@ func (h *Header) DelExtension(id uint8) error { for i, extension := range h.Extensions { if extension.id == id { h.Extensions = append(h.Extensions[:i], h.Extensions[i+1:]...) + return nil } } + return errHeaderExtensionNotFound } @@ -469,8 +489,11 @@ func (p Packet) Marshal() (buf []byte, err error) { } // MarshalTo serializes the packet and writes to the buffer. -func (p Packet) MarshalTo(buf []byte) (n int, err error) { - p.Header.Padding = p.PaddingSize != 0 +func (p *Packet) MarshalTo(buf []byte) (n int, err error) { + if p.Header.Padding && p.PaddingSize == 0 { + return 0, errInvalidRTPPadding + } + n, err = p.Header.MarshalTo(buf) if err != nil { return 0, err @@ -482,6 +505,7 @@ func (p Packet) MarshalTo(buf []byte) (n int, err error) { } m := copy(buf[n:], p.Payload) + if p.Header.Padding { buf[n+m+int(p.PaddingSize-1)] = p.PaddingSize } @@ -503,6 +527,7 @@ func (p Packet) Clone() *Packet { copy(clone.Payload, p.Payload) } clone.PaddingSize = p.PaddingSize + return clone } @@ -524,5 +549,6 @@ func (h Header) Clone() Header { } clone.Extensions = ext } + return clone } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/packetizer.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/packetizer.go index 19f6c756d..c0dbea49f 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/packetizer.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/packetizer.go @@ -1,37 +1,52 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package rtp import ( "time" ) -// Payloader payloads a byte array for use as rtp.Packet payloads +// Payloader payloads a byte array for use as rtp.Packet payloads. type Payloader interface { Payload(mtu uint16, payload []byte) [][]byte } -// Packetizer packetizes a payload +// Packetizer packetizes a payload. type Packetizer interface { Packetize(payload []byte, samples uint32) []*Packet + GeneratePadding(samples uint32) []*Packet EnableAbsSendTime(value int) SkipSamples(skippedSamples uint32) } type packetizer struct { - MTU uint16 - PayloadType uint8 - SSRC uint32 - Payloader Payloader - Sequencer Sequencer - Timestamp uint32 - ClockRate uint32 - extensionNumbers struct { // put extension numbers in here. If they're 0, the extension is disabled (0 is not a legal extension number) + MTU uint16 + PayloadType uint8 + SSRC uint32 + Payloader Payloader + Sequencer Sequencer + Timestamp uint32 + + // Deprecated: will be removed in a future version. + ClockRate uint32 + + // put extension numbers in here. If they're 0, the extension is disabled (0 is not a legal extension number) + extensionNumbers struct { AbsSendTime int // http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time } timegen func() time.Time } -// NewPacketizer returns a new instance of a Packetizer for a specific payloader -func NewPacketizer(mtu uint16, pt uint8, ssrc uint32, payloader Payloader, sequencer Sequencer, clockRate uint32) Packetizer { +// NewPacketizer returns a new instance of a Packetizer for a specific payloader. +func NewPacketizer( + mtu uint16, + pt uint8, + ssrc uint32, + payloader Payloader, + sequencer Sequencer, + clockRate uint32, +) Packetizer { return &packetizer{ MTU: mtu, PayloadType: pt, @@ -44,11 +59,59 @@ func NewPacketizer(mtu uint16, pt uint8, ssrc uint32, payloader Payloader, seque } } +// WithSSRC sets the SSRC for the Packetizer. +func WithSSRC(ssrc uint32) func(*packetizer) { + return func(p *packetizer) { + p.SSRC = ssrc + } +} + +// WithPayloadType sets the PayloadType for the Packetizer. +func WithPayloadType(pt uint8) func(*packetizer) { + return func(p *packetizer) { + p.PayloadType = pt + } +} + +// WithTimestamp sets the initial Timestamp for the Packetizer. +func WithTimestamp(timestamp uint32) func(*packetizer) { + return func(p *packetizer) { + p.Timestamp = timestamp + } +} + +// PacketizerOption is a function that configures a RTP Packetizer. +type PacketizerOption func(*packetizer) + +// NewPacketizerWithOptions returns a new instance of a Packetizer with the given options. +func NewPacketizerWithOptions( + mtu uint16, + payloader Payloader, + sequencer Sequencer, + clockRate uint32, + options ...PacketizerOption, +) Packetizer { + packetizerInstance := &packetizer{ + MTU: mtu, + Payloader: payloader, + Sequencer: sequencer, + Timestamp: globalMathRandomGenerator.Uint32(), + ClockRate: clockRate, + timegen: time.Now, + } + + for _, option := range options { + option(packetizerInstance) + } + + return packetizerInstance +} + func (p *packetizer) EnableAbsSendTime(value int) { p.extensionNumbers.AbsSendTime = value } -// Packetize packetizes the payload of an RTP packet and returns one or more RTP packets +// Packetize packetizes the payload of an RTP packet and returns one or more RTP packets. func (p *packetizer) Packetize(payload []byte, samples uint32) []*Packet { // Guard against an empty payload if len(payload) == 0 { @@ -69,6 +132,7 @@ func (p *packetizer) Packetize(payload []byte, samples uint32) []*Packet { SequenceNumber: p.Sequencer.NextSequenceNumber(), Timestamp: p.Timestamp, // Figure out how to do timestamps SSRC: p.SSRC, + CSRC: []uint32{}, }, Payload: pp, } @@ -82,7 +146,7 @@ func (p *packetizer) Packetize(payload []byte, samples uint32) []*Packet { if err != nil { return nil // never happens } - err = packets[len(packets)-1].SetExtension(uint8(p.extensionNumbers.AbsSendTime), b) + err = packets[len(packets)-1].SetExtension(uint8(p.extensionNumbers.AbsSendTime), b) // nolint: gosec // G115 if err != nil { return nil // never happens } @@ -91,8 +155,40 @@ func (p *packetizer) Packetize(payload []byte, samples uint32) []*Packet { return packets } +// GeneratePadding returns required padding-only packages. +func (p *packetizer) GeneratePadding(samples uint32) []*Packet { + // Guard against an empty payload + if samples == 0 { + return nil + } + + packets := make([]*Packet, samples) + + for i := 0; i < int(samples); i++ { + pp := make([]byte, 255) + pp[254] = 255 + + packets[i] = &Packet{ + Header: Header{ + Version: 2, + Padding: true, + Extension: false, + Marker: false, + PayloadType: p.PayloadType, + SequenceNumber: p.Sequencer.NextSequenceNumber(), + Timestamp: p.Timestamp, // Use latest timestamp + SSRC: p.SSRC, + CSRC: []uint32{}, + }, + Payload: pp, + } + } + + return packets +} + // SkipSamples causes a gap in sample count between Packetize requests so the -// RTP payloads produced have a gap in timestamps +// RTP payloads produced have a gap in timestamps. func (p *packetizer) SkipSamples(skippedSamples uint32) { p.Timestamp += skippedSamples } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/partitionheadchecker.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/partitionheadchecker.go index 6ec2a7631..51f16a961 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/partitionheadchecker.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/partitionheadchecker.go @@ -1,6 +1,9 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package rtp -// PartitionHeadChecker is the interface that checks whether the packet is keyframe or not +// PartitionHeadChecker is the interface that checks whether the packet is keyframe or not. type PartitionHeadChecker interface { IsPartitionHead([]byte) bool } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/payload_types.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/payload_types.go new file mode 100644 index 000000000..a9bf2272a --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/payload_types.go @@ -0,0 +1,68 @@ +// SPDX-FileCopyrightText: 2024 The Pion community +// SPDX-License-Identifier: MIT + +package rtp + +// https://www.iana.org/assignments/rtp-parameters/rtp-parameters.xhtml +// https://en.wikipedia.org/wiki/RTP_payload_formats + +// Audio Payload Types as defined in https://www.iana.org/assignments/rtp-parameters/rtp-parameters.xhtml +const ( + // PayloadTypePCMU is a payload type for ITU-T G.711 PCM μ-Law audio 64 kbit/s (RFC 3551). + PayloadTypePCMU = 0 + // PayloadTypeGSM is a payload type for European GSM Full Rate audio 13 kbit/s (GSM 06.10). + PayloadTypeGSM = 3 + // PayloadTypeG723 is a payload type for ITU-T G.723.1 audio (RFC 3551). + PayloadTypeG723 = 4 + // PayloadTypeDVI4_8000 is a payload type for IMA ADPCM audio 32 kbit/s (RFC 3551). + PayloadTypeDVI4_8000 = 5 + // PayloadTypeDVI4_16000 is a payload type for IMA ADPCM audio 64 kbit/s (RFC 3551). + PayloadTypeDVI4_16000 = 6 + // PayloadTypeLPC is a payload type for Experimental Linear Predictive Coding audio 5.6 kbit/s (RFC 3551). + PayloadTypeLPC = 7 + // PayloadTypePCMA is a payload type for ITU-T G.711 PCM A-Law audio 64 kbit/s (RFC 3551). + PayloadTypePCMA = 8 + // PayloadTypeG722 is a payload type for ITU-T G.722 audio 64 kbit/s (RFC 3551). + PayloadTypeG722 = 9 + // PayloadTypeL16Stereo is a payload type for Linear PCM 16-bit Stereo audio 1411.2 kbit/s, uncompressed (RFC 3551). + PayloadTypeL16Stereo = 10 + // PayloadTypeL16Mono is a payload type for Linear PCM 16-bit audio 705.6 kbit/s, uncompressed (RFC 3551). + PayloadTypeL16Mono = 11 + // PayloadTypeQCELP is a payload type for Qualcomm Code Excited Linear Prediction (RFC 2658, RFC 3551). + PayloadTypeQCELP = 12 + // PayloadTypeCN is a payload type for Comfort noise (RFC 3389). + PayloadTypeCN = 13 + // PayloadTypeMPA is a payload type for MPEG-1 or MPEG-2 audio only (RFC 3551, RFC 2250). + PayloadTypeMPA = 14 + // PayloadTypeG728 is a payload type for ITU-T G.728 audio 16 kbit/s (RFC 3551). + PayloadTypeG728 = 15 + // PayloadTypeDVI4_11025 is a payload type for IMA ADPCM audio 44.1 kbit/s (RFC 3551). + PayloadTypeDVI4_11025 = 16 + // PayloadTypeDVI4_22050 is a payload type for IMA ADPCM audio 88.2 kbit/s (RFC 3551). + PayloadTypeDVI4_22050 = 17 + // PayloadTypeG729 is a payload type for ITU-T G.729 and G.729a audio 8 kbit/s (RFC 3551, RFC 3555). + PayloadTypeG729 = 18 +) + +// Video Payload Types as defined in https://www.iana.org/assignments/rtp-parameters/rtp-parameters.xhtml +const ( + // PayloadTypeCELLB is a payload type for Sun CellB video (RFC 2029). + PayloadTypeCELLB = 25 + // PayloadTypeJPEG is a payload type for JPEG video (RFC 2435). + PayloadTypeJPEG = 26 + // PayloadTypeNV is a payload type for Xerox PARC's Network Video (nv, RFC 3551). + PayloadTypeNV = 28 + // PayloadTypeH261 is a payload type for ITU-T H.261 video (RFC 4587). + PayloadTypeH261 = 31 + // PayloadTypeMPV is a payload type for MPEG-1 and MPEG-2 video (RFC 2250). + PayloadTypeMPV = 32 + // PayloadTypeMP2T is a payload type for MPEG-2 transport stream (RFC 2250). + PayloadTypeMP2T = 33 + // PayloadTypeH263 is a payload type for H.263 video, first version (1996, RFC 3551, RFC 2190). + PayloadTypeH263 = 34 +) + +const ( + // PayloadTypeFirstDynamic is a first non-static payload type. + PayloadTypeFirstDynamic = 35 +) diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/pkg/frame/av1.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/pkg/frame/av1.go deleted file mode 100644 index 30525abc0..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/pkg/frame/av1.go +++ /dev/null @@ -1,44 +0,0 @@ -// Package frame provides code to construct complete media frames from packetized media -package frame - -import "github.com/pion/rtp/codecs" - -// AV1 represents a collection of OBUs given a stream of AV1 Packets. -// Each AV1 RTP Packet is a collection of OBU Elements. Each OBU Element may be a full OBU, or just a fragment of one. -// AV1 provides the tools to construct a collection of OBUs from a collection of OBU Elements. This structure -// contains an internal cache and should be used for the entire RTP Stream. -type AV1 struct { - // Buffer for fragmented OBU. If ReadFrames is called on a RTP Packet - // that doesn't contain a fully formed OBU - obuBuffer []byte -} - -func (f *AV1) pushOBUElement(isFirstOBUFragment *bool, obuElement []byte, obuList [][]byte) [][]byte { - if *isFirstOBUFragment { - *isFirstOBUFragment = false - // Discard pushed because we don't have a fragment to combine it with - if f.obuBuffer == nil { - return obuList - } - obuElement = append(f.obuBuffer, obuElement...) - f.obuBuffer = nil - } - return append(obuList, obuElement) -} - -// ReadFrames processes the codecs.AV1Packet and returns fully constructed frames -func (f *AV1) ReadFrames(pkt *codecs.AV1Packet) ([][]byte, error) { - OBUs := [][]byte{} - isFirstOBUFragment := pkt.Z - - for i := range pkt.OBUElements { - OBUs = f.pushOBUElement(&isFirstOBUFragment, pkt.OBUElements[i], OBUs) - } - - if pkt.Y && len(OBUs) > 0 { - // Take copy of OBUElement that is being cached - f.obuBuffer = append(f.obuBuffer, append([]byte{}, OBUs[len(OBUs)-1]...)...) - OBUs = OBUs[:len(OBUs)-1] - } - return OBUs, nil -} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/playoutdelayextension.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/playoutdelayextension.go new file mode 100644 index 000000000..81d2d5bf0 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/playoutdelayextension.go @@ -0,0 +1,52 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + +package rtp + +import ( + "encoding/binary" + "errors" +) + +const ( + playoutDelayExtensionSize = 3 + playoutDelayMaxValue = (1 << 12) - 1 +) + +var errPlayoutDelayInvalidValue = errors.New("invalid playout delay value") + +// PlayoutDelayExtension is a extension payload format in +// http://www.webrtc.org/experiments/rtp-hdrext/playout-delay +// 0 1 2 3 +// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | ID | len=2 | MIN delay | MAX delay | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// . +type PlayoutDelayExtension struct { + MinDelay, MaxDelay uint16 +} + +// Marshal serializes the members to buffer. +func (p PlayoutDelayExtension) Marshal() ([]byte, error) { + if p.MinDelay > playoutDelayMaxValue || p.MaxDelay > playoutDelayMaxValue { + return nil, errPlayoutDelayInvalidValue + } + + return []byte{ + byte(p.MinDelay >> 4), + byte(p.MinDelay<<4) | byte(p.MaxDelay>>8), + byte(p.MaxDelay), + }, nil +} + +// Unmarshal parses the passed byte slice and stores the result in the members. +func (p *PlayoutDelayExtension) Unmarshal(rawData []byte) error { + if len(rawData) < playoutDelayExtensionSize { + return errTooSmall + } + p.MinDelay = binary.BigEndian.Uint16(rawData[0:2]) >> 4 + p.MaxDelay = binary.BigEndian.Uint16(rawData[1:3]) & 0x0FFF + + return nil +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/rand.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/rand.go index ee8552356..3ddddd1bf 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/rand.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/rand.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package rtp import ( diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/renovate.json b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/renovate.json index f1614058a..f1bb98c6a 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/renovate.json +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/renovate.json @@ -1,27 +1,6 @@ { + "$schema": "https://docs.renovatebot.com/renovate-schema.json", "extends": [ - "config:base", - ":disableDependencyDashboard" - ], - "postUpdateOptions": [ - "gomodTidy" - ], - "commitBody": "Generated by renovateBot", - "packageRules": [ - { - "matchUpdateTypes": ["minor", "patch", "pin", "digest"], - "automerge": true - }, - { - "packagePatterns": ["^golang.org/x/"], - "schedule": ["on the first day of the month"] - } - ], - "ignorePaths": [ - ".github/workflows/generate-authors.yml", - ".github/workflows/lint.yaml", - ".github/workflows/renovate-go-mod-fix.yaml", - ".github/workflows/test.yaml", - ".github/workflows/tidy-check.yaml" + "github>pion/renovate-config" ] } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/rtp.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/rtp.go index b66b2e4b8..5487232e5 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/rtp.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/rtp.go @@ -1,2 +1,5 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + // Package rtp provides RTP packetizer and depacketizer package rtp diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/sequencer.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/sequencer.go index 2b4a5072e..aad500272 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/sequencer.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/sequencer.go @@ -1,26 +1,35 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package rtp import ( - "math" "sync" ) -// Sequencer generates sequential sequence numbers for building RTP packets +// Sequencer generates sequential sequence numbers for building RTP packets. type Sequencer interface { NextSequenceNumber() uint16 RollOverCount() uint64 } +// maxInitialRandomSequenceNumber is the maximum value used for the initial sequence +// number when using NewRandomSequencer(). +// This uses only half the potential sequence number space to avoid issues decrypting +// SRTP when the sequence number starts near the rollover and there is packet loss. +// See https://webrtc-review.googlesource.com/c/src/+/358360 +const maxInitialRandomSequenceNumber = 1<<15 - 1 + // NewRandomSequencer returns a new sequencer starting from a random sequence -// number +// number. func NewRandomSequencer() Sequencer { return &sequencer{ - sequenceNumber: uint16(globalMathRandomGenerator.Intn(math.MaxUint16)), + sequenceNumber: uint16(globalMathRandomGenerator.Intn(maxInitialRandomSequenceNumber)), // nolint: gosec // G115 } } // NewFixedSequencer returns a new sequencer starting from a specific -// sequence number +// sequence number. func NewFixedSequencer(s uint16) Sequencer { return &sequencer{ sequenceNumber: s - 1, // -1 because the first sequence number prepends 1 @@ -34,7 +43,7 @@ type sequencer struct { } // NextSequenceNumber increment and returns a new sequence number for -// building RTP packets +// building RTP packets. func (s *sequencer) NextSequenceNumber() uint16 { s.mutex.Lock() defer s.mutex.Unlock() @@ -48,7 +57,7 @@ func (s *sequencer) NextSequenceNumber() uint16 { } // RollOverCount returns the amount of times the 16bit sequence number -// has wrapped +// has wrapped. func (s *sequencer) RollOverCount() uint64 { s.mutex.Lock() defer s.mutex.Unlock() diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/transportccextension.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/transportccextension.go index 236af056a..add44ea4c 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/transportccextension.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/transportccextension.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package rtp import ( @@ -5,7 +8,7 @@ import ( ) const ( - // transport-wide sequence + // transport-wide sequence. transportCCExtensionSize = 2 ) @@ -18,22 +21,25 @@ const ( // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // | ID | L=1 |transport-wide sequence number | zero padding | // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// . type TransportCCExtension struct { TransportSequence uint16 } -// Marshal serializes the members to buffer +// Marshal serializes the members to buffer. func (t TransportCCExtension) Marshal() ([]byte, error) { buf := make([]byte, transportCCExtensionSize) binary.BigEndian.PutUint16(buf[0:2], t.TransportSequence) + return buf, nil } -// Unmarshal parses the passed byte slice and stores the result in the members +// Unmarshal parses the passed byte slice and stores the result in the members. func (t *TransportCCExtension) Unmarshal(rawData []byte) error { if len(rawData) < transportCCExtensionSize { return errTooSmall } t.TransportSequence = binary.BigEndian.Uint16(rawData[0:2]) + return nil } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/vlaextension.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/vlaextension.go new file mode 100644 index 000000000..8863029e0 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/rtp/vlaextension.go @@ -0,0 +1,373 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + +package rtp + +import ( + "encoding/binary" + "errors" + "fmt" + "strings" + + "github.com/pion/rtp/codecs/av1/obu" +) + +var ( + // ErrVLATooShort is returned when payload is too short. + ErrVLATooShort = errors.New("VLA payload too short") + // ErrVLAInvalidStreamCount is returned when RTP stream count is invalid. + ErrVLAInvalidStreamCount = errors.New("invalid RTP stream count in VLA") + // ErrVLAInvalidStreamID is returned when RTP stream ID is invalid. + ErrVLAInvalidStreamID = errors.New("invalid RTP stream ID in VLA") + // ErrVLAInvalidSpatialID is returned when spatial ID is invalid. + ErrVLAInvalidSpatialID = errors.New("invalid spatial ID in VLA") + // ErrVLADuplicateSpatialID is returned when spatial ID is invalid. + ErrVLADuplicateSpatialID = errors.New("duplicate spatial ID in VLA") + // ErrVLAInvalidTemporalLayer is returned when temporal layer is invalid. + ErrVLAInvalidTemporalLayer = errors.New("invalid temporal layer in VLA") +) + +// SpatialLayer is a spatial layer in VLA. +type SpatialLayer struct { + RTPStreamID int + SpatialID int + TargetBitrates []int // target bitrates per temporal layer + + // Following members are valid only when HasResolutionAndFramerate is true + Width int + Height int + Framerate int +} + +// VLA is a Video Layer Allocation (VLA) extension. +// See https://webrtc.googlesource.com/src/+/refs/heads/main/docs/native-code/rtp-hdrext/video-layers-allocation00 +type VLA struct { + RTPStreamID int // 0-origin RTP stream ID (RID) this allocation is sent on (0..3) + RTPStreamCount int // Number of RTP streams (1..4) + ActiveSpatialLayer []SpatialLayer + HasResolutionAndFramerate bool +} + +type vlaMarshalingContext struct { + slMBs [4]uint8 + sls [4][4]*SpatialLayer + commonSLBM uint8 + encodedTargetBitrates [][]byte + requiredLen int +} + +func (v VLA) preprocessForMashaling(ctx *vlaMarshalingContext) error { + for i := 0; i < len(v.ActiveSpatialLayer); i++ { + sl := v.ActiveSpatialLayer[i] + if sl.RTPStreamID < 0 || sl.RTPStreamID >= v.RTPStreamCount { + return fmt.Errorf("invalid RTP streamID %d:%w", sl.RTPStreamID, ErrVLAInvalidStreamID) + } + if sl.SpatialID < 0 || sl.SpatialID >= 4 { + return fmt.Errorf("invalid spatial ID %d: %w", sl.SpatialID, ErrVLAInvalidSpatialID) + } + if len(sl.TargetBitrates) == 0 || len(sl.TargetBitrates) > 4 { + return fmt.Errorf("invalid temporal layer count %d: %w", len(sl.TargetBitrates), ErrVLAInvalidTemporalLayer) + } + ctx.slMBs[sl.RTPStreamID] |= 1 << sl.SpatialID + if ctx.sls[sl.RTPStreamID][sl.SpatialID] != nil { + return fmt.Errorf("duplicate spatial layer: %w", ErrVLADuplicateSpatialID) + } + ctx.sls[sl.RTPStreamID][sl.SpatialID] = &sl + } + + return nil +} + +func (v VLA) encodeTargetBitrates(ctx *vlaMarshalingContext) { + for rtpStreamID := 0; rtpStreamID < v.RTPStreamCount; rtpStreamID++ { + for spatialID := 0; spatialID < 4; spatialID++ { + if sl := ctx.sls[rtpStreamID][spatialID]; sl != nil { + for _, kbps := range sl.TargetBitrates { + leb128 := obu.WriteToLeb128(uint(kbps)) // nolint: gosec + ctx.encodedTargetBitrates = append(ctx.encodedTargetBitrates, leb128) + ctx.requiredLen += len(leb128) + } + } + } + } +} + +func (v VLA) analyzeVLAForMarshaling() (*vlaMarshalingContext, error) { + // Validate RTPStreamCount + if v.RTPStreamCount <= 0 || v.RTPStreamCount > 4 { + return nil, ErrVLAInvalidStreamCount + } + // Validate RTPStreamID + if v.RTPStreamID < 0 || v.RTPStreamID >= v.RTPStreamCount { + return nil, ErrVLAInvalidStreamID + } + + ctx := &vlaMarshalingContext{} + err := v.preprocessForMashaling(ctx) + if err != nil { + return nil, err + } + + ctx.commonSLBM = commonSLBMValues(ctx.slMBs[:]) + + // RID, NS, sl_bm fields + if ctx.commonSLBM != 0 { + ctx.requiredLen = 1 + } else { + ctx.requiredLen = 3 + } + + // #tl fields + ctx.requiredLen += (len(v.ActiveSpatialLayer)-1)/4 + 1 + + v.encodeTargetBitrates(ctx) + + if v.HasResolutionAndFramerate { + ctx.requiredLen += len(v.ActiveSpatialLayer) * 5 + } + + return ctx, nil +} + +// Marshal encodes VLA into a byte slice. +func (v VLA) Marshal() ([]byte, error) { // nolint: cyclop + ctx, err := v.analyzeVLAForMarshaling() + if err != nil { + return nil, err + } + + payload := make([]byte, ctx.requiredLen) + offset := 0 + + // RID, NS, sl_bm fields + payload[offset] = byte(v.RTPStreamID<<6) | byte(v.RTPStreamCount-1)<<4 | ctx.commonSLBM + + if ctx.commonSLBM == 0 { + offset++ + for streamID := 0; streamID < v.RTPStreamCount; streamID++ { + if streamID%2 == 0 { + payload[offset+streamID/2] |= ctx.slMBs[streamID] << 4 + } else { + payload[offset+streamID/2] |= ctx.slMBs[streamID] + } + } + offset += (v.RTPStreamCount - 1) / 2 + } + + // #tl fields + offset++ + var temporalLayerIndex int + for rtpStreamID := 0; rtpStreamID < v.RTPStreamCount; rtpStreamID++ { + for spatialID := 0; spatialID < 4; spatialID++ { + if sl := ctx.sls[rtpStreamID][spatialID]; sl != nil { + if temporalLayerIndex >= 4 { + temporalLayerIndex = 0 + offset++ + } + payload[offset] |= byte(len(sl.TargetBitrates)-1) << (2 * (3 - temporalLayerIndex)) + temporalLayerIndex++ + } + } + } + + // Target bitrate fields + offset++ + for _, encodedKbps := range ctx.encodedTargetBitrates { + encodedSize := len(encodedKbps) + copy(payload[offset:], encodedKbps) + offset += encodedSize + } + + // Resolution & framerate fields + if v.HasResolutionAndFramerate { + for _, sl := range v.ActiveSpatialLayer { + binary.BigEndian.PutUint16(payload[offset+0:], uint16(sl.Width-1)) // nolint: gosec + binary.BigEndian.PutUint16(payload[offset+2:], uint16(sl.Height-1)) // nolint: gosec + payload[offset+4] = byte(sl.Framerate) + offset += 5 + } + } + + return payload, nil +} + +func commonSLBMValues(slMBs []uint8) uint8 { + var common uint8 + for i := 0; i < len(slMBs); i++ { + if slMBs[i] == 0 { + continue + } + if common == 0 { + common = slMBs[i] + + continue + } + if slMBs[i] != common { + return 0 + } + } + + return common +} + +type vlaUnmarshalingContext struct { + payload []byte + offset int + slBMField uint8 + slBMs [4]uint8 +} + +func (ctx *vlaUnmarshalingContext) checkRemainingLen(requiredLen int) bool { + return len(ctx.payload)-ctx.offset >= requiredLen +} + +func (v *VLA) unmarshalSpatialLayers(ctx *vlaUnmarshalingContext) error { + if !ctx.checkRemainingLen(1) { + return fmt.Errorf("failed to unmarshal VLA (offset=%d): %w", ctx.offset, ErrVLATooShort) + } + v.RTPStreamID = int(ctx.payload[ctx.offset] >> 6 & 0b11) + v.RTPStreamCount = int(ctx.payload[ctx.offset]>>4&0b11) + 1 + + // sl_bm fields + ctx.slBMField = ctx.payload[ctx.offset] & 0b1111 + ctx.offset++ + + if ctx.slBMField != 0 { + for streamID := 0; streamID < v.RTPStreamCount; streamID++ { + ctx.slBMs[streamID] = ctx.slBMField + } + } else { + if !ctx.checkRemainingLen((v.RTPStreamCount-1)/2 + 1) { + return fmt.Errorf("failed to unmarshal VLA (offset=%d): %w", ctx.offset, ErrVLATooShort) + } + // slX_bm fields + for streamID := 0; streamID < v.RTPStreamCount; streamID++ { + var bm uint8 + if streamID%2 == 0 { + bm = ctx.payload[ctx.offset+streamID/2] >> 4 & 0b1111 + } else { + bm = ctx.payload[ctx.offset+streamID/2] & 0b1111 + } + ctx.slBMs[streamID] = bm + } + ctx.offset += 1 + (v.RTPStreamCount-1)/2 + } + + return nil +} + +func (v *VLA) unmarshalTemporalLayers(ctx *vlaUnmarshalingContext) error { // nolint: cyclop + if !ctx.checkRemainingLen(1) { + return fmt.Errorf("failed to unmarshal VLA (offset=%d): %w", ctx.offset, ErrVLATooShort) + } + + var temporalLayerIndex int + for streamID := 0; streamID < v.RTPStreamCount; streamID++ { + for spatialID := 0; spatialID < 4; spatialID++ { + if ctx.slBMs[streamID]&(1<= 4 { + temporalLayerIndex = 0 + ctx.offset++ + if !ctx.checkRemainingLen(1) { + return fmt.Errorf("failed to unmarshal VLA (offset=%d): %w", ctx.offset, ErrVLATooShort) + } + } + tlCount := int(ctx.payload[ctx.offset]>>(2*(3-temporalLayerIndex))&0b11) + 1 + temporalLayerIndex++ + sl := SpatialLayer{ + RTPStreamID: streamID, + SpatialID: spatialID, + TargetBitrates: make([]int, tlCount), + } + v.ActiveSpatialLayer = append(v.ActiveSpatialLayer, sl) + } + } + ctx.offset++ + + // target bitrates + for i, sl := range v.ActiveSpatialLayer { + for j := range sl.TargetBitrates { + kbps, n, err := obu.ReadLeb128(ctx.payload[ctx.offset:]) + if err != nil { + return err + } + + in := int(n) // nolint: gosec + + if !ctx.checkRemainingLen(in) { + return fmt.Errorf("failed to unmarshal VLA (offset=%d): %w", ctx.offset, ErrVLATooShort) + } + v.ActiveSpatialLayer[i].TargetBitrates[j] = int(kbps) // nolint: gosec + ctx.offset += in + } + } + + return nil +} + +func (v *VLA) unmarshalResolutionAndFramerate(ctx *vlaUnmarshalingContext) error { + if !ctx.checkRemainingLen(len(v.ActiveSpatialLayer) * 5) { + return fmt.Errorf("failed to unmarshal VLA (offset=%d): %w", ctx.offset, ErrVLATooShort) + } + + v.HasResolutionAndFramerate = true + + for i := range v.ActiveSpatialLayer { + v.ActiveSpatialLayer[i].Width = int(binary.BigEndian.Uint16(ctx.payload[ctx.offset+0:])) + 1 + v.ActiveSpatialLayer[i].Height = int(binary.BigEndian.Uint16(ctx.payload[ctx.offset+2:])) + 1 + v.ActiveSpatialLayer[i].Framerate = int(ctx.payload[ctx.offset+4]) + ctx.offset += 5 + } + + return nil +} + +// Unmarshal decodes VLA from a byte slice. +func (v *VLA) Unmarshal(payload []byte) (int, error) { + ctx := &vlaUnmarshalingContext{ + payload: payload, + } + + err := v.unmarshalSpatialLayers(ctx) + if err != nil { + return ctx.offset, err + } + + // #tl fields (build the list ActiveSpatialLayer at the same time) + err = v.unmarshalTemporalLayers(ctx) + if err != nil { + return ctx.offset, err + } + + if len(ctx.payload) == ctx.offset { + return ctx.offset, nil + } + + // resolution & framerate (optional) + err = v.unmarshalResolutionAndFramerate(ctx) + if err != nil { + return ctx.offset, err + } + + return ctx.offset, nil +} + +// String makes VLA printable. +func (v VLA) String() string { + out := fmt.Sprintf("RID:%d,RTPStreamCount:%d", v.RTPStreamID, v.RTPStreamCount) + var slOut []string + for _, sl := range v.ActiveSpatialLayer { + out2 := fmt.Sprintf("RTPStreamID:%d", sl.RTPStreamID) + out2 += fmt.Sprintf(",TargetBitrates:%v", sl.TargetBitrates) + if v.HasResolutionAndFramerate { + out2 += fmt.Sprintf(",Resolution:(%d,%d)", sl.Width, sl.Height) + out2 += fmt.Sprintf(",Framerate:%d", sl.Framerate) + } + slOut = append(slOut, out2) + } + out += fmt.Sprintf(",ActiveSpatialLayers:{%s}", strings.Join(slOut, ",")) + + return out +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/.gitignore b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/.gitignore index f977e7485..6e2f206a9 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/.gitignore +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/.gitignore @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2023 The Pion community +# SPDX-License-Identifier: MIT + ### JetBrains IDE ### ##################### .idea/ diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/.golangci.yml b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/.golangci.yml index 48696f16b..120faf29b 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/.golangci.yml +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/.golangci.yml @@ -1,6 +1,13 @@ +# SPDX-FileCopyrightText: 2023 The Pion community +# SPDX-License-Identifier: MIT + +run: + timeout: 5m + linters-settings: govet: - check-shadowing: true + enable: + - shadow misspell: locale: US exhaustive: @@ -10,40 +17,65 @@ linters-settings: modules: - github.com/pkg/errors: recommendations: - - errors + - errors + forbidigo: + analyze-types: true + forbid: + - ^fmt.Print(f|ln)?$ + - ^log.(Panic|Fatal|Print)(f|ln)?$ + - ^os.Exit$ + - ^panic$ + - ^print(ln)?$ + - p: ^testing.T.(Error|Errorf|Fatal|Fatalf|Fail|FailNow)$ + pkg: ^testing$ + msg: "use testify/assert instead" + varnamelen: + max-distance: 12 + min-name-length: 2 + ignore-type-assert-ok: true + ignore-map-index-ok: true + ignore-chan-recv-ok: true + ignore-decls: + - i int + - n int + - w io.Writer + - r io.Reader + - b []byte linters: enable: - asciicheck # Simple linter to check that your code does not contain non-ASCII identifiers - bidichk # Checks for dangerous unicode character sequences - bodyclose # checks whether HTTP response body is closed successfully + - containedctx # containedctx is a linter that detects struct contained context.Context field - contextcheck # check the function whether use a non-inherited context + - cyclop # checks function and package cyclomatic complexity - decorder # check declaration order and count of types, constants, variables and functions - - depguard # Go linter that checks if package imports are in a list of acceptable packages - dogsled # Checks assignments with too many blank identifiers (e.g. x, _, _, _, := f()) - dupl # Tool for code clone detection - durationcheck # check for two durations multiplied together + - err113 # Golang linter to check the errors handling expressions - errcheck # Errcheck is a program for checking for unchecked errors in go programs. These unchecked errors can be critical bugs in some cases - errchkjson # Checks types passed to the json encoding functions. Reports unsupported types and optionally reports occations, where the check for the returned error can be omitted. - errname # Checks that sentinel errors are prefixed with the `Err` and error types are suffixed with the `Error`. - errorlint # errorlint is a linter for that can be used to find code that will cause problems with the error wrapping scheme introduced in Go 1.13. - exhaustive # check exhaustiveness of enum switch statements - exportloopref # checks for pointers to enclosing loop variables + - forbidigo # Forbids identifiers - forcetypeassert # finds forced type assertions - gci # Gci control golang package import order and make it always deterministic. - gochecknoglobals # Checks that no globals are present in Go code - - gochecknoinits # Checks that no init functions are present in Go code - gocognit # Computes and checks the cognitive complexity of functions - goconst # Finds repeated strings that could be replaced by a constant - gocritic # The most opinionated Go source code linter + - gocyclo # Computes and checks the cyclomatic complexity of functions + - godot # Check if comments end in a period - godox # Tool for detection of FIXME, TODO and other comment keywords - - goerr113 # Golang linter to check the errors handling expressions - gofmt # Gofmt checks whether code was gofmt-ed. By default this tool runs with -s option to check for code simplification - gofumpt # Gofumpt checks whether code was gofumpt-ed. - goheader # Checks is file header matches to pattern - goimports # Goimports does everything that gofmt does. Additionally it checks unused imports - gomoddirectives # Manage the use of 'replace', 'retract', and 'excludes' directives in go.mod. - - gomodguard # Allow and block list linter for direct Go module dependencies. This is different from depguard where there are different block types for example version constraints and module recommendations. - goprintffuncname # Checks that printf-like functions are named with `f` at the end - gosec # Inspects source code for security problems - gosimple # Linter for Go source code that specializes in simplifying a code @@ -51,10 +83,15 @@ linters: - grouper # An analyzer to analyze expression groups. - importas # Enforces consistent import aliases - ineffassign # Detects when assignments to existing variables are not used + - lll # Reports long lines + - maintidx # maintidx measures the maintainability index of each function. + - makezero # Finds slice declarations with non-zero initial length - misspell # Finds commonly misspelled English words in comments - nakedret # Finds naked returns in functions greater than a specified function length + - nestif # Reports deeply nested if statements - nilerr # Finds the code that returns nil even if it checks that the error is not nil. - nilnil # Checks that there is no simultaneous return of `nil` error and an invalid value. + - nlreturn # nlreturn checks for a new line before return and branch statements to increase code clarity - noctx # noctx finds sending http request without context.Context - predeclared # find code that shadows one of Go's predeclared identifiers - revive # golint replacement, finds style mistakes @@ -62,30 +99,22 @@ linters: - stylecheck # Stylecheck is a replacement for golint - tagliatelle # Checks the struct tags. - tenv # tenv is analyzer that detects using os.Setenv instead of t.Setenv since Go1.17 - - tparallel # tparallel detects inappropriate usage of t.Parallel() method in your Go test codes + - thelper # thelper detects golang test helpers without t.Helper() call and checks the consistency of test helpers - typecheck # Like the front-end of a Go compiler, parses and type-checks Go code - unconvert # Remove unnecessary type conversions - unparam # Reports unused function parameters - unused # Checks Go code for unused constants, variables, functions and types + - varnamelen # checks that the length of a variable's name matches its scope - wastedassign # wastedassign finds wasted assignment statements - whitespace # Tool for detection of leading and trailing whitespace disable: - - containedctx # containedctx is a linter that detects struct contained context.Context field - - cyclop # checks function and package cyclomatic complexity - - exhaustivestruct # Checks if all struct's fields are initialized - - forbidigo # Forbids identifiers + - depguard # Go linter that checks if package imports are in a list of acceptable packages - funlen # Tool for detection of long functions - - gocyclo # Computes and checks the cyclomatic complexity of functions - - godot # Check if comments end in a period - - gomnd # An analyzer to detect magic numbers. - - ifshort # Checks that your code uses short syntax for if-statements whenever possible + - gochecknoinits # Checks that no init functions are present in Go code + - gomodguard # Allow and block list linter for direct Go module dependencies. This is different from depguard where there are different block types for example version constraints and module recommendations. + - interfacebloat # A linter that checks length of interface. - ireturn # Accept Interfaces, Return Concrete Types - - lll # Reports long lines - - maintidx # maintidx measures the maintainability index of each function. - - makezero # Finds slice declarations with non-zero initial length - - maligned # Tool to detect Go structs that would take less memory if their fields were sorted - - nestif # Reports deeply nested if statements - - nlreturn # nlreturn checks for a new line before return and branch statements to increase code clarity + - mnd # An analyzer to detect magic numbers - nolintlint # Reports ill-formed or insufficient nolint directives - paralleltest # paralleltest detects missing usage of t.Parallel() method in your Go test - prealloc # Finds slice declarations that could potentially be preallocated @@ -93,24 +122,24 @@ linters: - rowserrcheck # checks whether Err of rows is checked successfully - sqlclosecheck # Checks that sql.Rows and sql.Stmt are closed. - testpackage # linter that makes you use a separate _test package - - thelper # thelper detects golang test helpers without t.Helper() call and checks the consistency of test helpers - - varnamelen # checks that the length of a variable's name matches its scope + - tparallel # tparallel detects inappropriate usage of t.Parallel() method in your Go test codes - wrapcheck # Checks that errors returned from external packages are wrapped - wsl # Whitespace Linter - Forces you to use empty lines! issues: exclude-use-default: false + exclude-dirs-use-default: false exclude-rules: - # Allow complex tests, better to be self contained + # Allow complex tests and examples, better to be self contained + - path: (examples|main\.go) + linters: + - gocognit + - forbidigo - path: _test\.go linters: - gocognit - # Allow complex main function in examples - - path: examples - text: "of func `main` is high" + # Allow forbidden identifiers in CLI commands + - path: cmd linters: - - gocognit - -run: - skip-dirs-use-default: false + - forbidigo diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/.goreleaser.yml b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/.goreleaser.yml index 2caa5fbd3..30093e9d6 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/.goreleaser.yml +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/.goreleaser.yml @@ -1,2 +1,5 @@ +# SPDX-FileCopyrightText: 2023 The Pion community +# SPDX-License-Identifier: MIT + builds: - skip: true diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/AUTHORS.txt b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/AUTHORS.txt deleted file mode 100644 index ed95135c8..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/AUTHORS.txt +++ /dev/null @@ -1,33 +0,0 @@ -# Thank you to everyone that made Pion possible. If you are interested in contributing -# we would love to have you https://github.com/pion/webrtc/wiki/Contributing -# -# This file is auto generated, using git to list all individuals contributors. -# see https://github.com/pion/.goassets/blob/master/scripts/generate-authors.sh for the scripting -Aaron France -Adrian Cable -Atsushi Watanabe -backkem -Cecylia Bocovich -chenkaiC4 -Eric Daniels -Hugo Arregui -Hugo Arregui -Jerko Steiner -Jerry Tao -John Bradley -Konstantin Itskov -Lukas Herman -Luke Curley -Michael MacDonald -ronan -Sam Lancia -Sean DuBois -Sean DuBois -Steffen Vogel -Teddy -Will Forcey -Yutaka Takeda -ZHENK - -# List of contributors not appearing in Git history - diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/LICENSE b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/LICENSE index ab602974d..491caf6b0 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/LICENSE +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/LICENSE @@ -1,21 +1,9 @@ MIT License -Copyright (c) 2018 +Copyright (c) 2023 The Pion community -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/README.md b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/README.md index 3ca234452..18fa3f164 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/README.md +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/README.md @@ -6,7 +6,7 @@

A Go implementation of SCTP

Pion SCTP - Slack Widget + join us on Discord Follow us on Bluesky
GitHub Workflow Status Go Reference @@ -20,15 +20,15 @@ The library is used as a part of our WebRTC implementation. Please refer to that [roadmap](https://github.com/pion/webrtc/issues/9) to track our major milestones. ### Community -Pion has an active community on the [Slack](https://pion.ly/slack). +Pion has an active community on the [Discord](https://discord.gg/PngbdqpFbt). -Follow the [Pion Twitter](https://twitter.com/_pion) for project updates and important WebRTC news. +Follow the [Pion Bluesky](https://bsky.app/profile/pion.ly) or [Pion Twitter](https://twitter.com/_pion) for project updates and important WebRTC news. We are always looking to support **your projects**. Please reach out if you have something to build! If you need commercial support or don't want to use public methods you can contact us at [team@pion.ly](mailto:team@pion.ly) ### Contributing -Check out the [contributing wiki](https://github.com/pion/webrtc/wiki/Contributing) to join the group of amazing people making this project possible: [AUTHORS.txt](./AUTHORS.txt) +Check out the [contributing wiki](https://github.com/pion/webrtc/wiki/Contributing) to join the group of amazing people making this project possible ### License MIT License - see [LICENSE](LICENSE) for full text diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/ack_timer.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/ack_timer.go index ba23d54d2..80e96885e 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/ack_timer.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/ack_timer.go @@ -1,6 +1,10 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package sctp import ( + "math" "sync" "time" ) @@ -14,23 +18,39 @@ type ackTimerObserver interface { onAckTimeout() } -// ackTimer provides the retnransmission timer conforms with RFC 4960 Sec 6.3.1 -type ackTimer struct { - observer ackTimerObserver - interval time.Duration - stopFunc stopAckTimerLoop - closed bool - mutex sync.RWMutex -} +type ackTimerState uint8 -type stopAckTimerLoop func() +const ( + ackTimerStopped ackTimerState = iota + ackTimerStarted + ackTimerClosed +) + +// ackTimer provides the retnransmission timer conforms with RFC 4960 Sec 6.3.1. +type ackTimer struct { + timer *time.Timer + observer ackTimerObserver + mutex sync.Mutex + state ackTimerState + pending uint8 +} // newAckTimer creates a new acknowledgement timer used to enable delayed ack. func newAckTimer(observer ackTimerObserver) *ackTimer { - return &ackTimer{ - observer: observer, - interval: ackInterval, + t := &ackTimer{observer: observer} + t.timer = time.AfterFunc(math.MaxInt64, t.timeout) + t.timer.Stop() + + return t +} + +func (t *ackTimer) timeout() { + t.mutex.Lock() + if t.pending--; t.pending == 0 && t.state == ackTimerStarted { + t.state = ackTimerStopped + defer t.observer.onAckTimeout() } + t.mutex.Unlock() } // start starts the timer. @@ -38,68 +58,49 @@ func (t *ackTimer) start() bool { t.mutex.Lock() defer t.mutex.Unlock() - // this timer is already closed - if t.closed { + // this timer is already closed or already running + if t.state != ackTimerStopped { return false } - // this is a noop if the timer is already running - if t.stopFunc != nil { - return false - } - - cancelCh := make(chan struct{}) - - go func() { - timer := time.NewTimer(t.interval) - - select { - case <-timer.C: - t.stop() - t.observer.onAckTimeout() - case <-cancelCh: - timer.Stop() - } - }() - - t.stopFunc = func() { - close(cancelCh) - } + t.state = ackTimerStarted + t.pending++ + t.timer.Reset(ackInterval) return true } // stops the timer. this is similar to stop() but subsequent start() call -// will fail (the timer is no longer usable) +// will fail (the timer is no longer usable). func (t *ackTimer) stop() { t.mutex.Lock() defer t.mutex.Unlock() - if t.stopFunc != nil { - t.stopFunc() - t.stopFunc = nil + if t.state == ackTimerStarted { + if t.timer.Stop() { + t.pending-- + } + t.state = ackTimerStopped } } // closes the timer. this is similar to stop() but subsequent start() call -// will fail (the timer is no longer usable) +// will fail (the timer is no longer usable). func (t *ackTimer) close() { t.mutex.Lock() defer t.mutex.Unlock() - if t.stopFunc != nil { - t.stopFunc() - t.stopFunc = nil + if t.state == ackTimerStarted && t.timer.Stop() { + t.pending-- } - - t.closed = true + t.state = ackTimerClosed } // isRunning tests if the timer is running. -// Debug purpose only +// Debug purpose only. func (t *ackTimer) isRunning() bool { - t.mutex.RLock() - defer t.mutex.RUnlock() + t.mutex.Lock() + defer t.mutex.Unlock() - return (t.stopFunc != nil) + return t.state == ackTimerStarted } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/association.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/association.go index fb7fd38db..81044503f 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/association.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/association.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package sctp import ( @@ -14,33 +17,44 @@ import ( "github.com/pion/logging" "github.com/pion/randutil" + "github.com/pion/transport/v3/deadline" ) +// Port 5000 shows up in examples for SDPs used by WebRTC. Since this implementation +// assumes it will be used by DTLS over UDP, the port is only meaningful for de-multiplexing +// but more-so verification. +// Example usage: https://www.rfc-editor.org/rfc/rfc8841.html#section-13.1-2 +const defaultSCTPSrcDstPort = 5000 + // Use global random generator to properly seed by crypto grade random. var globalMathRandomGenerator = randutil.NewMathRandomGenerator() // nolint:gochecknoglobals -// Association errors +// Association errors. var ( ErrChunk = errors.New("abort chunk, with following errors") ErrShutdownNonEstablished = errors.New("shutdown called in non-established state") ErrAssociationClosedBeforeConn = errors.New("association closed before connecting") + ErrAssociationClosed = errors.New("association closed") ErrSilentlyDiscard = errors.New("silently discard") ErrInitNotStoredToSend = errors.New("the init not stored to send") ErrCookieEchoNotStoredToSend = errors.New("cookieEcho not stored to send") ErrSCTPPacketSourcePortZero = errors.New("sctp packet must not have a source port of 0") ErrSCTPPacketDestinationPortZero = errors.New("sctp packet must not have a destination port of 0") ErrInitChunkBundled = errors.New("init chunk must not be bundled with any other chunk") - ErrInitChunkVerifyTagNotZero = errors.New("init chunk expects a verification tag of 0 on the packet when out-of-the-blue") - ErrHandleInitState = errors.New("todo: handle Init when in state") - ErrInitAckNoCookie = errors.New("no cookie in InitAck") - ErrInflightQueueTSNPop = errors.New("unable to be popped from inflight queue TSN") - ErrTSNRequestNotExist = errors.New("requested non-existent TSN") - ErrResetPacketInStateNotExist = errors.New("sending reset packet in non-established state") - ErrParamterType = errors.New("unexpected parameter type") - ErrPayloadDataStateNotExist = errors.New("sending payload data in non-established state") - ErrChunkTypeUnhandled = errors.New("unhandled chunk type") - ErrHandshakeInitAck = errors.New("handshake failed (INIT ACK)") - ErrHandshakeCookieEcho = errors.New("handshake failed (COOKIE ECHO)") + ErrInitChunkVerifyTagNotZero = errors.New( + "init chunk expects a verification tag of 0 on the packet when out-of-the-blue", + ) + ErrHandleInitState = errors.New("todo: handle Init when in state") + ErrInitAckNoCookie = errors.New("no cookie in InitAck") + ErrInflightQueueTSNPop = errors.New("unable to be popped from inflight queue TSN") + ErrTSNRequestNotExist = errors.New("requested non-existent TSN") + ErrResetPacketInStateNotExist = errors.New("sending reset packet in non-established state") + ErrParamterType = errors.New("unexpected parameter type") + ErrPayloadDataStateNotExist = errors.New("sending payload data in non-established state") + ErrChunkTypeUnhandled = errors.New("unhandled chunk type") + ErrHandshakeInitAck = errors.New("handshake failed (INIT ACK)") + ErrHandshakeCookieEcho = errors.New("handshake failed (COOKIE ECHO)") + ErrTooManyReconfigRequests = errors.New("too many outstanding reconfig requests") ) const ( @@ -52,7 +66,7 @@ const ( defaultMaxMessageSize uint32 = 65536 ) -// association state enums +// association state enums. const ( closed uint32 = iota cookieWait @@ -64,7 +78,7 @@ const ( shutdownSent ) -// retransmission timer IDs +// retransmission timer IDs. const ( timerT1Init int = iota timerT1Cookie @@ -73,27 +87,40 @@ const ( timerReconfig ) -// ack mode (for testing) +// ack mode (for testing). const ( ackModeNormal int = iota ackModeNoDelay ackModeAlwaysDelay ) -// ack transmission state +// ack transmission state. const ( ackStateIdle int = iota // ack timer is off ackStateImmediate // will send ack immediately ackStateDelay // ack timer is on (ack is being delayed) ) -// other constants +// other constants. const ( acceptChSize = 16 + // avgChunkSize is an estimate of the average chunk size. There is no theory behind + // this estimate. + avgChunkSize = 500 + // minTSNOffset is the minimum offset over the cummulative TSN that we will enqueue + // irrespective of the receive buffer size + // see getMaxTSNOffset. + minTSNOffset = 2000 + // maxTSNOffset is the maximum offset over the cummulative TSN that we will enqueue + // irrespective of the receive buffer size + // see getMaxTSNOffset. + maxTSNOffset = 40000 + // maxReconfigRequests is the maximum number of reconfig requests we will keep outstanding. + maxReconfigRequests = 1000 ) -func getAssociationStateString(a uint32) string { - switch a { +func getAssociationStateString(assoc uint32) string { + switch assoc { case closed: return "Closed" case cookieWait: @@ -111,7 +138,7 @@ func getAssociationStateString(a uint32) string { case shutdownAckSent: return "ShutdownAckSent" default: - return fmt.Sprintf("Invalid association state %d", a) + return fmt.Sprintf("Invalid association state %d", assoc) } } @@ -128,6 +155,8 @@ func getAssociationStateString(a uint32) string { // // Note: No "CLOSED" state is illustrated since if a // association is "CLOSED" its TCB SHOULD be removed. +// Note: By nature of an Association being constructed with one net.Conn, +// it is not a multi-home supporting implementation of SCTP. type Association struct { bytesReceived uint64 bytesSent uint64 @@ -139,8 +168,8 @@ type Association struct { peerVerificationTag uint32 myVerificationTag uint32 state uint32 + initialTSN uint32 myNextTSN uint32 // nextTSN - peerLastTSN uint32 // lastRcvdTSN minTSN2MeasureRTT uint32 // for RTT measurement willSendForwardTSN bool willRetransmitFast bool @@ -164,7 +193,7 @@ type Association struct { myMaxNumInboundStreams uint16 myMaxNumOutboundStreams uint16 myCookie *paramStateCookie - payloadQueue *payloadQueue + payloadQueue *receivePayloadQueue inflightQueue *payloadQueue pendingQueue *pendingQueue controlQueue *controlQueue @@ -174,6 +203,8 @@ type Association struct { cumulativeTSNAckPoint uint32 advancedPeerTSNAckPoint uint32 useForwardTSN bool + sendZeroChecksum bool + recvZeroChecksum bool // Congestion control parameters maxReceiveBufferSize uint32 @@ -184,6 +215,9 @@ type Association struct { partialBytesAcked uint32 inFastRecovery bool fastRecoverExitPoint uint32 + minCwnd uint32 // Minimum congestion window + fastRtxWnd uint32 // Send window for fast retransmit + cwndCAStep uint32 // Step of congestion window increase at Congestion Avoidance // RTX & Ack timer rtoMgr *rtoManager @@ -220,20 +254,38 @@ type Association struct { delayedAckTriggered bool immediateAckTriggered bool + blockWrite bool + writePending bool + writeNotify chan struct{} + name string log logging.LeveledLogger } // Config collects the arguments to createAssociation construction into -// a single structure +// a single structure. type Config struct { + Name string NetConn net.Conn MaxReceiveBufferSize uint32 MaxMessageSize uint32 + EnableZeroChecksum bool LoggerFactory logging.LoggerFactory + BlockWrite bool + MTU uint32 + + // congestion control configuration + // RTOMax is the maximum retransmission timeout in milliseconds + RTOMax float64 + // Minimum congestion window + MinCwnd uint32 + // Send window for fast retransmit + FastRtxWnd uint32 + // Step of congestion window increase at Congestion Avoidance + CwndCAStep uint32 } -// Server accepts a SCTP stream over a conn +// Server accepts a SCTP stream over a conn. func Server(config Config) (*Association, error) { a := createAssociation(config) a.init(false) @@ -243,62 +295,84 @@ func Server(config Config) (*Association, error) { if err != nil { return nil, err } + return a, nil case <-a.readLoopCloseCh: return nil, ErrAssociationClosedBeforeConn } } -// Client opens a SCTP stream over a conn +// Client opens a SCTP stream over a conn. func Client(config Config) (*Association, error) { - a := createAssociation(config) - a.init(true) + return createClientWithContext(context.Background(), config) +} + +func createClientWithContext(ctx context.Context, config Config) (*Association, error) { + assoc := createAssociation(config) + assoc.init(true) select { - case err := <-a.handshakeCompletedCh: + case <-ctx.Done(): + assoc.log.Errorf("[%s] client handshake canceled: state=%s", assoc.name, getAssociationStateString(assoc.getState())) + assoc.Close() // nolint:errcheck,gosec + + return nil, ctx.Err() + case err := <-assoc.handshakeCompletedCh: if err != nil { return nil, err } - return a, nil - case <-a.readLoopCloseCh: + + return assoc, nil + case <-assoc.readLoopCloseCh: return nil, ErrAssociationClosedBeforeConn } } func createAssociation(config Config) *Association { - var maxReceiveBufferSize uint32 - if config.MaxReceiveBufferSize == 0 { + maxReceiveBufferSize := config.MaxReceiveBufferSize + if maxReceiveBufferSize == 0 { maxReceiveBufferSize = initialRecvBufSize - } else { - maxReceiveBufferSize = config.MaxReceiveBufferSize } - var maxMessageSize uint32 - if config.MaxMessageSize == 0 { + maxMessageSize := config.MaxMessageSize + if maxMessageSize == 0 { maxMessageSize = defaultMaxMessageSize - } else { - maxMessageSize = config.MaxMessageSize + } + + mtu := config.MTU + if mtu == 0 { + mtu = initialMTU } tsn := globalMathRandomGenerator.Uint32() - a := &Association{ - netConn: config.NetConn, - maxReceiveBufferSize: maxReceiveBufferSize, - maxMessageSize: maxMessageSize, + assoc := &Association{ + netConn: config.NetConn, + maxReceiveBufferSize: maxReceiveBufferSize, + maxMessageSize: maxMessageSize, + minCwnd: config.MinCwnd, + fastRtxWnd: config.FastRtxWnd, + cwndCAStep: config.CwndCAStep, + + // These two max values have us not need to follow + // 5.1.1 where this peer may be incapable of supporting + // the requested amount of outbound streams from the other + // peer. myMaxNumOutboundStreams: math.MaxUint16, myMaxNumInboundStreams: math.MaxUint16, - payloadQueue: newPayloadQueue(), + + payloadQueue: newReceivePayloadQueue(getMaxTSNOffset(maxReceiveBufferSize)), inflightQueue: newPayloadQueue(), pendingQueue: newPendingQueue(), controlQueue: newControlQueue(), - mtu: initialMTU, - maxPayloadSize: initialMTU - (commonHeaderSize + dataChunkHeaderSize), + mtu: mtu, + maxPayloadSize: mtu - (commonHeaderSize + dataChunkHeaderSize), myVerificationTag: globalMathRandomGenerator.Uint32(), + initialTSN: tsn, myNextTSN: tsn, myNextRSN: tsn, minTSN2MeasureRTT: tsn, state: closed, - rtoMgr: newRTOManager(), + rtoMgr: newRTOManager(config.RTOMax), streams: map[uint16]*Stream{}, reconfigs: map[uint32]*chunkReconfig{}, reconfigRequests: map[uint32]*paramOutgoingResetRequest{}, @@ -309,30 +383,36 @@ func createAssociation(config Config) *Association { handshakeCompletedCh: make(chan error), cumulativeTSNAckPoint: tsn - 1, advancedPeerTSNAckPoint: tsn - 1, + recvZeroChecksum: config.EnableZeroChecksum, silentError: ErrSilentlyDiscard, stats: &associationStats{}, log: config.LoggerFactory.NewLogger("sctp"), + name: config.Name, + blockWrite: config.BlockWrite, + writeNotify: make(chan struct{}, 1), } - a.name = fmt.Sprintf("%p", a) + if assoc.name == "" { + assoc.name = fmt.Sprintf("%p", assoc) + } // RFC 4690 Sec 7.2.1 // o The initial cwnd before DATA transmission or after a sufficiently // long idle period MUST be set to min(4*MTU, max (2*MTU, 4380 // bytes)). - a.cwnd = min32(4*a.mtu, max32(2*a.mtu, 4380)) - a.log.Tracef("[%s] updated cwnd=%d ssthresh=%d inflight=%d (INI)", - a.name, a.cwnd, a.ssthresh, a.inflightQueue.getNumBytes()) + assoc.setCWND(min32(4*assoc.MTU(), max32(2*assoc.MTU(), 4380))) + assoc.log.Tracef("[%s] updated cwnd=%d ssthresh=%d inflight=%d (INI)", + assoc.name, assoc.CWND(), assoc.ssthresh, assoc.inflightQueue.getNumBytes()) - a.srtt.Store(float64(0)) - a.t1Init = newRTXTimer(timerT1Init, a, maxInitRetrans) - a.t1Cookie = newRTXTimer(timerT1Cookie, a, maxInitRetrans) - a.t2Shutdown = newRTXTimer(timerT2Shutdown, a, noMaxRetrans) // retransmit forever - a.t3RTX = newRTXTimer(timerT3RTX, a, noMaxRetrans) // retransmit forever - a.tReconfig = newRTXTimer(timerReconfig, a, noMaxRetrans) // retransmit forever - a.ackTimer = newAckTimer(a) + assoc.srtt.Store(float64(0)) + assoc.t1Init = newRTXTimer(timerT1Init, assoc, maxInitRetrans, config.RTOMax) + assoc.t1Cookie = newRTXTimer(timerT1Cookie, assoc, maxInitRetrans, config.RTOMax) + assoc.t2Shutdown = newRTXTimer(timerT2Shutdown, assoc, noMaxRetrans, config.RTOMax) + assoc.t3RTX = newRTXTimer(timerT3RTX, assoc, noMaxRetrans, config.RTOMax) + assoc.tReconfig = newRTXTimer(timerReconfig, assoc, noMaxRetrans, config.RTOMax) + assoc.ackTimer = newAckTimer(assoc) - return a + return assoc } func (a *Association) init(isClient bool) { @@ -343,7 +423,6 @@ func (a *Association) init(isClient bool) { go a.writeLoop() if isClient { - a.setState(cookieWait) init := &chunkInit{} init.initialTSN = a.myNextTSN init.numOutboundStreams = a.myMaxNumOutboundStreams @@ -351,6 +430,11 @@ func (a *Association) init(isClient bool) { init.initiateTag = a.myVerificationTag init.advertisedReceiverWindowCredit = a.maxReceiveBufferSize setSupportedExtensions(&init.chunkInitCommon) + + if a.recvZeroChecksum { + init.params = append(init.params, ¶mZeroChecksumAcceptable{edmid: dtlsErrorDetectionMethod}) + } + a.storedInit = init err := a.sendInit() @@ -358,11 +442,16 @@ func (a *Association) init(isClient bool) { a.log.Errorf("[%s] failed to send init: %s", a.name, err.Error()) } + // After sending the INIT chunk, "A" starts the T1-init timer and enters the COOKIE-WAIT state. + // Note: ideally we would set state after the timer starts but since we don't do this in an atomic + // set + timer-start, it's safer to just set the state first so that we don't have a timer expiration + // race. + a.setState(cookieWait) a.t1Init.start(a.rtoMgr.getRTO()) } } -// caller must hold a.lock +// caller must hold a.lock. func (a *Association) sendInit() error { a.log.Debugf("[%s] sending INIT", a.name) if a.storedInit == nil { @@ -370,9 +459,9 @@ func (a *Association) sendInit() error { } outbound := &packet{} - outbound.verificationTag = a.peerVerificationTag - a.sourcePort = 5000 // Spec?? - a.destinationPort = 5000 // Spec?? + outbound.verificationTag = 0 + a.sourcePort = defaultSCTPSrcDstPort + a.destinationPort = defaultSCTPSrcDstPort outbound.sourcePort = a.sourcePort outbound.destinationPort = a.destinationPort @@ -384,7 +473,7 @@ func (a *Association) sendInit() error { return nil } -// caller must hold a.lock +// caller must hold a.lock. func (a *Association) sendCookieEcho() error { if a.storedCookieEcho == nil { return ErrCookieEchoNotStoredToSend @@ -438,7 +527,7 @@ func (a *Association) Shutdown(ctx context.Context) error { } } -// Close ends the SCTP Association and cleans up any state +// Close ends the SCTP Association and cleans up any state. func (a *Association) Close() error { a.log.Debugf("[%s] closing association..", a.name) @@ -448,8 +537,11 @@ func (a *Association) Close() error { <-a.readLoopCloseCh a.log.Debugf("[%s] association closed", a.name) + a.log.Debugf("[%s] stats nPackets (in) : %d", a.name, a.stats.getNumPacketsReceived()) + a.log.Debugf("[%s] stats nPackets (out) : %d", a.name, a.stats.getNumPacketsSent()) a.log.Debugf("[%s] stats nDATAs (in) : %d", a.name, a.stats.getNumDATAs()) - a.log.Debugf("[%s] stats nSACKs (in) : %d", a.name, a.stats.getNumSACKs()) + a.log.Debugf("[%s] stats nSACKs (in) : %d", a.name, a.stats.getNumSACKsReceived()) + a.log.Debugf("[%s] stats nSACKs (out) : %d", a.name, a.stats.getNumSACKsSent()) a.log.Debugf("[%s] stats nT3Timeouts : %d", a.name, a.stats.getNumT3Timeouts()) a.log.Debugf("[%s] stats nAckTimeouts: %d", a.name, a.stats.getNumAckTimeouts()) a.log.Debugf("[%s] stats nFastRetrans: %d", a.name, a.stats.getNumFastRetrans()) @@ -510,6 +602,7 @@ func (a *Association) readLoop() { a.closeWriteLoopOnce.Do(func() { close(a.closeWriteLoopCh) }) a.lock.Lock() + a.setState(closed) for _, s := range a.streams { a.unregisterStream(s, closeErr) } @@ -519,7 +612,7 @@ func (a *Association) readLoop() { a.log.Debugf("[%s] association closed", a.name) a.log.Debugf("[%s] stats nDATAs (in) : %d", a.name, a.stats.getNumDATAs()) - a.log.Debugf("[%s] stats nSACKs (in) : %d", a.name, a.stats.getNumSACKs()) + a.log.Debugf("[%s] stats nSACKs (in) : %d", a.name, a.stats.getNumSACKsReceived()) a.log.Debugf("[%s] stats nT3Timeouts : %d", a.name, a.stats.getNumT3Timeouts()) a.log.Debugf("[%s] stats nAckTimeouts: %d", a.name, a.stats.getNumAckTimeouts()) a.log.Debugf("[%s] stats nFastRetrans: %d", a.name, a.stats.getNumFastRetrans()) @@ -532,6 +625,7 @@ func (a *Association) readLoop() { n, err := a.netConn.Read(buffer) if err != nil { closeErr = err + break } // Make a buffer sized to what we read, then copy the data we @@ -540,9 +634,10 @@ func (a *Association) readLoop() { // copying. inbound := make([]byte, n) copy(inbound, buffer[:n]) - atomic.AddUint64(&a.bytesReceived, uint64(n)) + atomic.AddUint64(&a.bytesReceived, uint64(n)) //nolint:gosec // G115 if err = a.handleInbound(inbound); err != nil { closeErr = err + break } } @@ -565,9 +660,11 @@ loop: a.log.Warnf("[%s] failed to write packets on netConn: %v", a.name, err) } a.log.Debugf("[%s] writeLoop ended", a.name) + break loop } atomic.AddUint64(&a.bytesSent, uint64(len(raw))) + a.stats.incPacketsSent() } if !ok { @@ -596,6 +693,20 @@ func (a *Association) awakeWriteLoop() { } } +func (a *Association) isBlockWrite() bool { + return a.blockWrite +} + +// Mark the association is writable and unblock the waiting write, +// the caller should hold the association write lock. +func (a *Association) notifyBlockWritable() { + a.writePending = false + select { + case a.writeNotify <- struct{}{}: + default: + } +} + // unregisterStream un-registers a stream from the association // The caller should hold the association write lock. func (a *Association) unregisterStream(s *Stream, err error) { @@ -607,38 +718,65 @@ func (a *Association) unregisterStream(s *Stream, err error) { s.readNotifier.Broadcast() } -// handleInbound parses incoming raw packets -func (a *Association) handleInbound(raw []byte) error { +func chunkMandatoryChecksum(cc []chunk) bool { + for _, c := range cc { + switch c.(type) { + case *chunkInit, *chunkCookieEcho: + return true + } + } + + return false +} + +func (a *Association) marshalPacket(p *packet) ([]byte, error) { + return p.marshal(!a.sendZeroChecksum || chunkMandatoryChecksum(p.chunks)) +} + +func (a *Association) unmarshalPacket(raw []byte) (*packet, error) { p := &packet{} - if err := p.unmarshal(raw); err != nil { + if err := p.unmarshal(!a.recvZeroChecksum, raw); err != nil { + return nil, err + } + + return p, nil +} + +// handleInbound parses incoming raw packets. +func (a *Association) handleInbound(raw []byte) error { + pkt, err := a.unmarshalPacket(raw) + if err != nil { a.log.Warnf("[%s] unable to parse SCTP packet %s", a.name, err) + return nil } - if err := checkPacket(p); err != nil { + if err := checkPacket(pkt); err != nil { a.log.Warnf("[%s] failed validating packet %s", a.name, err) + return nil } - a.handleChunkStart() + a.handleChunksStart() - for _, c := range p.chunks { - if err := a.handleChunk(p, c); err != nil { + for _, c := range pkt.chunks { + if err := a.handleChunk(pkt, c); err != nil { return err } } - a.handleChunkEnd() + a.handleChunksEnd() return nil } -// The caller should hold the lock +// The caller should hold the lock. func (a *Association) gatherDataPacketsToRetransmit(rawPackets [][]byte) [][]byte { for _, p := range a.getDataPacketsToRetransmit() { - raw, err := p.marshal() + raw, err := a.marshalPacket(p) if err != nil { a.log.Warnf("[%s] failed to serialize a DATA packet to be retransmitted", a.name) + continue } rawPackets = append(rawPackets, raw) @@ -647,7 +785,9 @@ func (a *Association) gatherDataPacketsToRetransmit(rawPackets [][]byte) [][]byt return rawPackets } -// The caller should hold the lock +// The caller should hold the lock. +// +//nolint:cyclop func (a *Association) gatherOutboundDataAndReconfigPackets(rawPackets [][]byte) [][]byte { // Pop unsent data chunks from the pending queue to send as much as // cwnd and rwnd allow. @@ -657,22 +797,23 @@ func (a *Association) gatherOutboundDataAndReconfigPackets(rawPackets [][]byte) a.log.Tracef("[%s] T3-rtx timer start (pt1)", a.name) a.t3RTX.start(a.rtoMgr.getRTO()) for _, p := range a.bundleDataChunksIntoPackets(chunks) { - raw, err := p.marshal() + raw, err := a.marshalPacket(p) if err != nil { a.log.Warnf("[%s] failed to serialize a DATA packet", a.name) + continue } rawPackets = append(rawPackets, raw) } } - if len(sisToReset) > 0 || a.willRetransmitReconfig { + if len(sisToReset) > 0 || a.willRetransmitReconfig { //nolint:nestif if a.willRetransmitReconfig { a.willRetransmitReconfig = false a.log.Debugf("[%s] retransmit %d RECONFIG chunk(s)", a.name, len(a.reconfigs)) for _, c := range a.reconfigs { p := a.createPacket([]chunk{c}) - raw, err := p.marshal() + raw, err := a.marshalPacket(p) if err != nil { a.log.Warnf("[%s] failed to serialize a RECONFIG packet to be retransmitted", a.name) } else { @@ -695,7 +836,7 @@ func (a *Association) gatherOutboundDataAndReconfigPackets(rawPackets [][]byte) a.log.Debugf("[%s] sending RECONFIG: rsn=%d tsn=%d streams=%v", a.name, rsn, a.myNextTSN-1, sisToReset) p := a.createPacket([]chunk{c}) - raw, err := p.marshal() + raw, err := a.marshalPacket(p) if err != nil { a.log.Warnf("[%s] failed to serialize a RECONFIG packet to be transmitted", a.name) } else { @@ -711,25 +852,31 @@ func (a *Association) gatherOutboundDataAndReconfigPackets(rawPackets [][]byte) return rawPackets } -// The caller should hold the lock +// The caller should hold the lock. +// +//nolint:cyclop func (a *Association) gatherOutboundFastRetransmissionPackets(rawPackets [][]byte) [][]byte { - if a.willRetransmitFast { + if a.willRetransmitFast { //nolint:nestif a.willRetransmitFast = false - toFastRetrans := []chunk{} + toFastRetrans := []*chunkPayloadData{} fastRetransSize := commonHeaderSize + fastRetransWnd := a.MTU() + if fastRetransWnd < a.fastRtxWnd { + fastRetransWnd = a.fastRtxWnd + } for i := 0; ; i++ { - c, ok := a.inflightQueue.get(a.cumulativeTSNAckPoint + uint32(i) + 1) + chunkPayload, ok := a.inflightQueue.get(a.cumulativeTSNAckPoint + uint32(i) + 1) //nolint:gosec // G115 if !ok { break // end of pending data } - if c.acked || c.abandoned() { + if chunkPayload.acked || chunkPayload.abandoned() { continue } - if c.nSent > 1 || c.missIndicator < 3 { + if chunkPayload.nSent > 1 || chunkPayload.missIndicator < 3 { continue } @@ -743,25 +890,28 @@ func (a *Association) gatherOutboundFastRetransmissionPackets(rawPackets [][]byt // of cwnd and SHOULD NOT delay retransmission for this single // packet. - dataChunkSize := dataChunkHeaderSize + uint32(len(c.userData)) - if a.mtu < fastRetransSize+dataChunkSize { + dataChunkSize := dataChunkHeaderSize + uint32(len(chunkPayload.userData)) //nolint:gosec // G115 + if fastRetransWnd < fastRetransSize+dataChunkSize { break } fastRetransSize += dataChunkSize a.stats.incFastRetrans() - c.nSent++ - a.checkPartialReliabilityStatus(c) - toFastRetrans = append(toFastRetrans, c) + chunkPayload.nSent++ + a.checkPartialReliabilityStatus(chunkPayload) + toFastRetrans = append(toFastRetrans, chunkPayload) a.log.Tracef("[%s] fast-retransmit: tsn=%d sent=%d htna=%d", - a.name, c.tsn, c.nSent, a.fastRecoverExitPoint) + a.name, chunkPayload.tsn, chunkPayload.nSent, a.fastRecoverExitPoint) } if len(toFastRetrans) > 0 { - raw, err := a.createPacket(toFastRetrans).marshal() - if err != nil { - a.log.Warnf("[%s] failed to serialize a DATA packet to be fast-retransmitted", a.name) - } else { + for _, p := range a.bundleDataChunksIntoPackets(toFastRetrans) { + raw, err := a.marshalPacket(p) + if err != nil { + a.log.Warnf("[%s] failed to serialize a DATA packet to be fast-retransmitted", a.name) + + continue + } rawPackets = append(rawPackets, raw) } } @@ -770,13 +920,14 @@ func (a *Association) gatherOutboundFastRetransmissionPackets(rawPackets [][]byt return rawPackets } -// The caller should hold the lock +// The caller should hold the lock. func (a *Association) gatherOutboundSackPackets(rawPackets [][]byte) [][]byte { if a.ackState == ackStateImmediate { a.ackState = ackStateIdle sack := a.createSelectiveAckChunk() + a.stats.incSACKsSent() a.log.Debugf("[%s] sending SACK: %s", a.name, sack) - raw, err := a.createPacket([]chunk{sack}).marshal() + raw, err := a.marshalPacket(a.createPacket([]chunk{sack})) if err != nil { a.log.Warnf("[%s] failed to serialize a SACK packet", a.name) } else { @@ -787,13 +938,13 @@ func (a *Association) gatherOutboundSackPackets(rawPackets [][]byte) [][]byte { return rawPackets } -// The caller should hold the lock +// The caller should hold the lock. func (a *Association) gatherOutboundForwardTSNPackets(rawPackets [][]byte) [][]byte { if a.willSendForwardTSN { a.willSendForwardTSN = false if sna32GT(a.advancedPeerTSNAckPoint, a.cumulativeTSNAckPoint) { fwdtsn := a.createForwardTSN() - raw, err := a.createPacket([]chunk{fwdtsn}).marshal() + raw, err := a.marshalPacket(a.createPacket([]chunk{fwdtsn})) if err != nil { a.log.Warnf("[%s] failed to serialize a Forward TSN packet", a.name) } else { @@ -816,7 +967,7 @@ func (a *Association) gatherOutboundShutdownPackets(rawPackets [][]byte) ([][]by cumulativeTSNAck: a.cumulativeTSNAckPoint, } - raw, err := a.createPacket([]chunk{shutdown}).marshal() + raw, err := a.marshalPacket(a.createPacket([]chunk{shutdown})) if err != nil { a.log.Warnf("[%s] failed to serialize a Shutdown packet", a.name) } else { @@ -828,7 +979,7 @@ func (a *Association) gatherOutboundShutdownPackets(rawPackets [][]byte) ([][]by shutdownAck := &chunkShutdownAck{} - raw, err := a.createPacket([]chunk{shutdownAck}).marshal() + raw, err := a.marshalPacket(a.createPacket([]chunk{shutdownAck})) if err != nil { a.log.Warnf("[%s] failed to serialize a ShutdownAck packet", a.name) } else { @@ -840,7 +991,7 @@ func (a *Association) gatherOutboundShutdownPackets(rawPackets [][]byte) ([][]by shutdownComplete := &chunkShutdownComplete{} - raw, err := a.createPacket([]chunk{shutdownComplete}).marshal() + raw, err := a.marshalPacket(a.createPacket([]chunk{shutdownComplete})) if err != nil { a.log.Warnf("[%s] failed to serialize a ShutdownComplete packet", a.name) } else { @@ -864,7 +1015,7 @@ func (a *Association) gatherAbortPacket() ([]byte, error) { abort.errorCauses = []errorCause{cause} } - raw, err := a.createPacket([]chunk{abort}).marshal() + raw, err := a.marshalPacket(a.createPacket([]chunk{abort})) return raw, err } @@ -879,6 +1030,7 @@ func (a *Association) gatherOutbound() ([][]byte, bool) { pkt, err := a.gatherAbortPacket() if err != nil { a.log.Warnf("[%s] failed to serialize an abort packet", a.name) + return nil, false } @@ -889,9 +1041,10 @@ func (a *Association) gatherOutbound() ([][]byte, bool) { if a.controlQueue.size() > 0 { for _, p := range a.controlQueue.popAll() { - raw, err := p.marshal() + raw, err := a.marshalPacket(p) if err != nil { a.log.Warnf("[%s] failed to serialize a control packet", a.name) + continue } rawPackets = append(rawPackets, raw) @@ -921,7 +1074,7 @@ func (a *Association) gatherOutbound() ([][]byte, bool) { return rawPackets, ok } -func checkPacket(p *packet) error { +func checkPacket(pkt *packet) error { // All packets must adhere to these rules // This is the SCTP sender's port number. It can be used by the @@ -929,7 +1082,7 @@ func checkPacket(p *packet) error { // destination port, and possibly the destination IP address to // identify the association to which this packet belongs. The port // number 0 MUST NOT be used. - if p.sourcePort == 0 { + if pkt.sourcePort == 0 { return ErrSCTPPacketSourcePortZero } @@ -937,24 +1090,24 @@ func checkPacket(p *packet) error { // The receiving host will use this port number to de-multiplex the // SCTP packet to the correct receiving endpoint/application. The // port number 0 MUST NOT be used. - if p.destinationPort == 0 { + if pkt.destinationPort == 0 { return ErrSCTPPacketDestinationPortZero } // Check values on the packet that are specific to a particular chunk type - for _, c := range p.chunks { + for _, c := range pkt.chunks { switch c.(type) { // nolint:gocritic case *chunkInit: // An INIT or INIT ACK chunk MUST NOT be bundled with any other chunk. // They MUST be the only chunks present in the SCTP packets that carry // them. - if len(p.chunks) != 1 { + if len(pkt.chunks) != 1 { return ErrInitChunkBundled } // A packet containing an INIT chunk MUST have a zero Verification // Tag. - if p.verificationTag != 0 { + if pkt.verificationTag != 0 { return ErrInitChunkVerifyTagNotZero } } @@ -967,6 +1120,7 @@ func min16(a, b uint16) uint16 { if a < b { return a } + return b } @@ -974,6 +1128,7 @@ func max32(a, b uint32) uint32 { if a > b { return a } + return b } @@ -981,9 +1136,15 @@ func min32(a, b uint32) uint32 { if a < b { return a } + return b } +// peerLastTSN return last received cumulative TSN. +func (a *Association) peerLastTSN() uint32 { + return a.payloadQueue.getcumulativeTSN() +} + // setState atomically sets the state of the Association. // The caller should hold the lock. func (a *Association) setState(newState uint32) { @@ -1001,36 +1162,63 @@ func (a *Association) getState() uint32 { return atomic.LoadUint32(&a.state) } -// BytesSent returns the number of bytes sent +// BytesSent returns the number of bytes sent. func (a *Association) BytesSent() uint64 { return atomic.LoadUint64(&a.bytesSent) } -// BytesReceived returns the number of bytes received +// BytesReceived returns the number of bytes received. func (a *Association) BytesReceived() uint64 { return atomic.LoadUint64(&a.bytesReceived) } -// MTU returns the association's current MTU +// MTU returns the association's current MTU. func (a *Association) MTU() uint32 { return atomic.LoadUint32(&a.mtu) } -// CWND returns the association's current congestion window (cwnd) +// CWND returns the association's current congestion window (cwnd). func (a *Association) CWND() uint32 { return atomic.LoadUint32(&a.cwnd) } -// RWND returns the association's current receiver window (rwnd) +func (a *Association) setCWND(cwnd uint32) { + if cwnd < a.minCwnd { + cwnd = a.minCwnd + } + atomic.StoreUint32(&a.cwnd, cwnd) +} + +// RWND returns the association's current receiver window (rwnd). func (a *Association) RWND() uint32 { return atomic.LoadUint32(&a.rwnd) } -// SRTT returns the latest smoothed round-trip time (srrt) +func (a *Association) setRWND(rwnd uint32) { + atomic.StoreUint32(&a.rwnd, rwnd) +} + +// SRTT returns the latest smoothed round-trip time (srrt). func (a *Association) SRTT() float64 { return a.srtt.Load().(float64) //nolint:forcetypeassert } +// getMaxTSNOffset returns the maximum offset over the current cummulative TSN that +// we are willing to enqueue. This ensures that we keep the bytes utilized in the receive +// buffer within a small multiple of the user provided max receive buffer size. +func getMaxTSNOffset(maxReceiveBufferSize uint32) uint32 { + // 4 is a magic number here. There is no theory behind this. + offset := (maxReceiveBufferSize * 4) / avgChunkSize + if offset < minTSNOffset { + offset = minTSNOffset + } + if offset > maxTSNOffset { + offset = maxTSNOffset + } + + return offset +} + func setSupportedExtensions(init *chunkInitCommon) { // nolint:godox // TODO RFC5061 https://tools.ietf.org/html/rfc6525#section-5.2 @@ -1043,7 +1231,9 @@ func setSupportedExtensions(init *chunkInitCommon) { } // The caller should hold the lock. -func (a *Association) handleInit(p *packet, i *chunkInit) ([]*packet, error) { +// +//nolint:cyclop +func (a *Association) handleInit(pkt *packet, initChunk *chunkInit) ([]*packet, error) { state := a.getState() a.log.Debugf("[%s] chunkInit received in state '%s'", a.name, getAssociationStateString(state)) @@ -1060,20 +1250,26 @@ func (a *Association) handleInit(p *packet, i *chunkInit) ([]*packet, error) { return nil, fmt.Errorf("%w: %s", ErrHandleInitState, getAssociationStateString(state)) } - // Should we be setting any of these permanently until we've ACKed further? - a.myMaxNumInboundStreams = min16(i.numInboundStreams, a.myMaxNumInboundStreams) - a.myMaxNumOutboundStreams = min16(i.numOutboundStreams, a.myMaxNumOutboundStreams) - a.peerVerificationTag = i.initiateTag - a.sourcePort = p.destinationPort - a.destinationPort = p.sourcePort + // NOTE: Setting these prior to a reception of a COOKIE ECHO chunk containing + // our cookie is not compliant with https://www.rfc-editor.org/rfc/rfc9260#section-5.1-2.2.3. + // It makes us more vulnerable to resource attacks, albeit minimally so. + // https://www.rfc-editor.org/rfc/rfc9260#sec_handle_stream_parameters + a.myMaxNumInboundStreams = min16(initChunk.numInboundStreams, a.myMaxNumInboundStreams) + a.myMaxNumOutboundStreams = min16(initChunk.numOutboundStreams, a.myMaxNumOutboundStreams) + a.peerVerificationTag = initChunk.initiateTag + a.sourcePort = pkt.destinationPort + a.destinationPort = pkt.sourcePort // 13.2 This is the last TSN received in sequence. This value // is set initially by taking the peer's initial TSN, // received in the INIT or INIT ACK chunk, and // subtracting one from it. - a.peerLastTSN = i.initialTSN - 1 + a.payloadQueue.init(initChunk.initialTSN - 1) - for _, param := range i.params { + a.setRWND(initChunk.advertisedReceiverWindowCredit) + a.log.Debugf("[%s] initial rwnd=%d", a.name, a.RWND()) + + for _, param := range initChunk.params { switch v := param.(type) { // nolint:gocritic case *paramSupportedExtensions: for _, t := range v.ChunkTypes { @@ -1082,8 +1278,11 @@ func (a *Association) handleInit(p *packet, i *chunkInit) ([]*packet, error) { a.useForwardTSN = true } } + case *paramZeroChecksumAcceptable: + a.sendZeroChecksum = v.edmid == dtlsErrorDetectionMethod } } + if !a.useForwardTSN { a.log.Warnf("[%s] not using ForwardTSN (on init)", a.name) } @@ -1094,6 +1293,7 @@ func (a *Association) handleInit(p *packet, i *chunkInit) ([]*packet, error) { outbound.destinationPort = a.destinationPort initAck := &chunkInitAck{} + a.log.Debug("sending INIT ACK") initAck.initialTSN = a.myNextTSN initAck.numOutboundStreams = a.myMaxNumOutboundStreams @@ -1103,6 +1303,8 @@ func (a *Association) handleInit(p *packet, i *chunkInit) ([]*packet, error) { if a.myCookie == nil { var err error + // NOTE: This generation process is not compliant with + // 5.1.3. Generating State Cookie (https://www.rfc-editor.org/rfc/rfc4960#section-5.1.3) if a.myCookie, err = newRandomStateCookie(); err != nil { return nil, err } @@ -1110,6 +1312,11 @@ func (a *Association) handleInit(p *packet, i *chunkInit) ([]*packet, error) { initAck.params = []param{a.myCookie} + if a.recvZeroChecksum { + initAck.params = append(initAck.params, ¶mZeroChecksumAcceptable{edmid: dtlsErrorDetectionMethod}) + } + a.log.Debugf("[%s] sendZeroChecksum=%t (on init)", a.name, a.sendZeroChecksum) + setSupportedExtensions(&initAck.chunkInitCommon) outbound.chunks = []chunk{initAck} @@ -1118,7 +1325,7 @@ func (a *Association) handleInit(p *packet, i *chunkInit) ([]*packet, error) { } // The caller should hold the lock. -func (a *Association) handleInitAck(p *packet, i *chunkInitAck) error { +func (a *Association) handleInitAck(pkt *packet, initChunkAck *chunkInitAck) error { //nolint:cyclop state := a.getState() a.log.Debugf("[%s] chunkInitAck received in state '%s'", a.name, getAssociationStateString(state)) if state != cookieWait { @@ -1131,32 +1338,33 @@ func (a *Association) handleInitAck(p *packet, i *chunkInitAck) error { return nil } - a.myMaxNumInboundStreams = min16(i.numInboundStreams, a.myMaxNumInboundStreams) - a.myMaxNumOutboundStreams = min16(i.numOutboundStreams, a.myMaxNumOutboundStreams) - a.peerVerificationTag = i.initiateTag - a.peerLastTSN = i.initialTSN - 1 - if a.sourcePort != p.destinationPort || - a.destinationPort != p.sourcePort { + a.myMaxNumInboundStreams = min16(initChunkAck.numInboundStreams, a.myMaxNumInboundStreams) + a.myMaxNumOutboundStreams = min16(initChunkAck.numOutboundStreams, a.myMaxNumOutboundStreams) + a.peerVerificationTag = initChunkAck.initiateTag + a.payloadQueue.init(initChunkAck.initialTSN - 1) + if a.sourcePort != pkt.destinationPort || + a.destinationPort != pkt.sourcePort { a.log.Warnf("[%s] handleInitAck: port mismatch", a.name) + return nil } - a.rwnd = i.advertisedReceiverWindowCredit - a.log.Debugf("[%s] initial rwnd=%d", a.name, a.rwnd) + a.setRWND(initChunkAck.advertisedReceiverWindowCredit) + a.log.Debugf("[%s] initial rwnd=%d", a.name, a.RWND()) // RFC 4690 Sec 7.2.1 // o The initial value of ssthresh MAY be arbitrarily high (for // example, implementations MAY use the size of the receiver // advertised window). - a.ssthresh = a.rwnd + a.ssthresh = a.RWND() a.log.Tracef("[%s] updated cwnd=%d ssthresh=%d inflight=%d (INI)", - a.name, a.cwnd, a.ssthresh, a.inflightQueue.getNumBytes()) + a.name, a.CWND(), a.ssthresh, a.inflightQueue.getNumBytes()) a.t1Init.stop() a.storedInit = nil var cookieParam *paramStateCookie - for _, param := range i.params { + for _, param := range initChunkAck.params { switch v := param.(type) { case *paramStateCookie: cookieParam = v @@ -1167,8 +1375,13 @@ func (a *Association) handleInitAck(p *packet, i *chunkInitAck) error { a.useForwardTSN = true } } + case *paramZeroChecksumAcceptable: + a.sendZeroChecksum = v.edmid == dtlsErrorDetectionMethod } } + + a.log.Debugf("[%s] sendZeroChecksum=%t (on initAck)", a.name, a.sendZeroChecksum) + if !a.useForwardTSN { a.log.Warnf("[%s] not using ForwardTSN (on initAck)", a.name) } @@ -1186,6 +1399,7 @@ func (a *Association) handleInitAck(p *packet, i *chunkInitAck) error { a.t1Cookie.start(a.rtoMgr.getRTO()) a.setState(cookieEchoed) + return nil } @@ -1212,26 +1426,29 @@ func (a *Association) handleHeartbeat(c *chunkHeartbeat) []*packet { } // The caller should hold the lock. -func (a *Association) handleCookieEcho(c *chunkCookieEcho) []*packet { +func (a *Association) handleCookieEcho(cookieEcho *chunkCookieEcho) []*packet { state := a.getState() a.log.Debugf("[%s] COOKIE-ECHO received in state '%s'", a.name, getAssociationStateString(state)) if a.myCookie == nil { a.log.Debugf("[%s] COOKIE-ECHO received before initialization", a.name) + return nil } switch state { default: return nil case established: - if !bytes.Equal(a.myCookie.cookie, c.cookie) { + if !bytes.Equal(a.myCookie.cookie, cookieEcho.cookie) { return nil } case closed, cookieWait, cookieEchoed: - if !bytes.Equal(a.myCookie.cookie, c.cookie) { + if !bytes.Equal(a.myCookie.cookie, cookieEcho.cookie) { return nil } + // RFC wise, these do not seem to belong here, but removing them + // causes TestCookieEchoRetransmission to break a.t1Init.stop() a.storedInit = nil @@ -1239,7 +1456,9 @@ func (a *Association) handleCookieEcho(c *chunkCookieEcho) []*packet { a.storedCookieEcho = nil a.setState(established) - a.handshakeCompletedCh <- nil + if !a.completeHandshake(nil) { + return nil + } } p := &packet{ @@ -1248,6 +1467,7 @@ func (a *Association) handleCookieEcho(c *chunkCookieEcho) []*packet { destinationPort: a.destinationPort, chunks: []chunk{&chunkCookieAck{}}, } + return pack(p) } @@ -1267,48 +1487,55 @@ func (a *Association) handleCookieAck() { a.storedCookieEcho = nil a.setState(established) - a.handshakeCompletedCh <- nil + a.completeHandshake(nil) } // The caller should hold the lock. -func (a *Association) handleData(d *chunkPayloadData) []*packet { +func (a *Association) handleData(chunkPayload *chunkPayloadData) []*packet { a.log.Tracef("[%s] DATA: tsn=%d immediateSack=%v len=%d", - a.name, d.tsn, d.immediateSack, len(d.userData)) + a.name, chunkPayload.tsn, chunkPayload.immediateSack, len(chunkPayload.userData)) a.stats.incDATAs() - canPush := a.payloadQueue.canPush(d, a.peerLastTSN) - if canPush { - s := a.getOrCreateStream(d.streamIdentifier, true, PayloadTypeUnknown) - if s == nil { - // silentely discard the data. (sender will retry on T3-rtx timeout) + canPush := a.payloadQueue.canPush(chunkPayload.tsn) + if canPush { //nolint:nestif + stream := a.getOrCreateStream(chunkPayload.streamIdentifier, true, PayloadTypeUnknown) + if stream == nil { + // silently discard the data. (sender will retry on T3-rtx timeout) // see pion/sctp#30 - a.log.Debugf("discard %d", d.streamSequenceNumber) + a.log.Debugf("[%s] discard %d", a.name, chunkPayload.streamSequenceNumber) + return nil } if a.getMyReceiverWindowCredit() > 0 { // Pass the new chunk to stream level as soon as it arrives - a.payloadQueue.push(d, a.peerLastTSN) - s.handleData(d) + a.payloadQueue.push(chunkPayload.tsn) + stream.handleData(chunkPayload) } else { // Receive buffer is full lastTSN, ok := a.payloadQueue.getLastTSNReceived() - if ok && sna32LT(d.tsn, lastTSN) { - a.log.Debugf("[%s] receive buffer full, but accepted as this is a missing chunk with tsn=%d ssn=%d", a.name, d.tsn, d.streamSequenceNumber) - a.payloadQueue.push(d, a.peerLastTSN) - s.handleData(d) + if ok && sna32LT(chunkPayload.tsn, lastTSN) { + a.log.Debugf( + "[%s] receive buffer full, but accepted as this is a missing chunk with tsn=%d ssn=%d", + a.name, chunkPayload.tsn, chunkPayload.streamSequenceNumber, + ) + a.payloadQueue.push(chunkPayload.tsn) + stream.handleData(chunkPayload) } else { - a.log.Debugf("[%s] receive buffer full. dropping DATA with tsn=%d ssn=%d", a.name, d.tsn, d.streamSequenceNumber) + a.log.Debugf( + "[%s] receive buffer full. dropping DATA with tsn=%d ssn=%d", + a.name, chunkPayload.tsn, chunkPayload.streamSequenceNumber, + ) } } } - return a.handlePeerLastTSNAndAcknowledgement(d.immediateSack) + return a.handlePeerLastTSNAndAcknowledgement(chunkPayload.immediateSack) } // A common routine for handleData and handleForwardTSN routines // The caller should hold the lock. -func (a *Association) handlePeerLastTSNAndAcknowledgement(sackImmediately bool) []*packet { +func (a *Association) handlePeerLastTSNAndAcknowledgement(sackImmediately bool) []*packet { //nolint:cyclop var reply []*packet // Try to advance peerLastTSN @@ -1319,10 +1546,9 @@ func (a *Association) handlePeerLastTSNAndAcknowledgement(sackImmediately bool) // Meaning, if peerLastTSN+1 points to a chunk that is received, // advance peerLastTSN until peerLastTSN+1 points to unreceived chunk. for { - if _, popOk := a.payloadQueue.pop(a.peerLastTSN + 1); !popOk { + if popOk := a.payloadQueue.pop(false); !popOk { break } - a.peerLastTSN++ for _, rstReq := range a.reconfigRequests { resp := a.resetStreamsIfAny(rstReq) @@ -1335,10 +1561,11 @@ func (a *Association) handlePeerLastTSNAndAcknowledgement(sackImmediately bool) hasPacketLoss := (a.payloadQueue.size() > 0) if hasPacketLoss { - a.log.Tracef("[%s] packetloss: %s", a.name, a.payloadQueue.getGapAckBlocksString(a.peerLastTSN)) + a.log.Tracef("[%s] packetloss: %s", a.name, a.payloadQueue.getGapAckBlocksString()) } - if (a.ackState != ackStateImmediate && !sackImmediately && !hasPacketLoss && a.ackMode == ackModeNormal) || a.ackMode == ackModeAlwaysDelay { + if (a.ackState != ackStateImmediate && !sackImmediately && !hasPacketLoss && a.ackMode == ackModeNormal) || + a.ackMode == ackModeAlwaysDelay { if a.ackState == ackStateIdle { a.delayedAckTriggered = true } else { @@ -1355,66 +1582,83 @@ func (a *Association) handlePeerLastTSNAndAcknowledgement(sackImmediately bool) func (a *Association) getMyReceiverWindowCredit() uint32 { var bytesQueued uint32 for _, s := range a.streams { - bytesQueued += uint32(s.getNumBytesInReassemblyQueue()) + bytesQueued += uint32(s.getNumBytesInReassemblyQueue()) //nolint:gosec // G115 } if bytesQueued >= a.maxReceiveBufferSize { return 0 } + return a.maxReceiveBufferSize - bytesQueued } -// OpenStream opens a stream -func (a *Association) OpenStream(streamIdentifier uint16, defaultPayloadType PayloadProtocolIdentifier) (*Stream, error) { +// OpenStream opens a stream. +func (a *Association) OpenStream( + streamIdentifier uint16, + defaultPayloadType PayloadProtocolIdentifier, +) (*Stream, error) { a.lock.Lock() defer a.lock.Unlock() + switch a.getState() { + case shutdownAckSent, shutdownPending, shutdownReceived, shutdownSent, closed: + return nil, ErrAssociationClosed + } + return a.getOrCreateStream(streamIdentifier, false, defaultPayloadType), nil } -// AcceptStream accepts a stream +// AcceptStream accepts a stream. func (a *Association) AcceptStream() (*Stream, error) { s, ok := <-a.acceptCh if !ok { return nil, io.EOF // no more incoming streams } + return s, nil } // createStream creates a stream. The caller should hold the lock and check no stream exists for this id. func (a *Association) createStream(streamIdentifier uint16, accept bool) *Stream { - s := &Stream{ + stream := &Stream{ association: a, streamIdentifier: streamIdentifier, reassemblyQueue: newReassemblyQueue(streamIdentifier), log: a.log, name: fmt.Sprintf("%d:%s", streamIdentifier, a.name), + writeDeadline: deadline.New(), } - s.readNotifier = sync.NewCond(&s.lock) + stream.readNotifier = sync.NewCond(&stream.lock) if accept { select { - case a.acceptCh <- s: - a.streams[streamIdentifier] = s + case a.acceptCh <- stream: + a.streams[streamIdentifier] = stream a.log.Debugf("[%s] accepted a new stream (streamIdentifier: %d)", a.name, streamIdentifier) default: a.log.Debugf("[%s] dropped a new stream (acceptCh size: %d)", a.name, len(a.acceptCh)) + return nil } } else { - a.streams[streamIdentifier] = s + a.streams[streamIdentifier] = stream } - return s + return stream } // getOrCreateStream gets or creates a stream. The caller should hold the lock. -func (a *Association) getOrCreateStream(streamIdentifier uint16, accept bool, defaultPayloadType PayloadProtocolIdentifier) *Stream { +func (a *Association) getOrCreateStream( + streamIdentifier uint16, + accept bool, + defaultPayloadType PayloadProtocolIdentifier, +) *Stream { if s, ok := a.streams[streamIdentifier]; ok { s.SetDefaultPayloadType(defaultPayloadType) + return s } @@ -1422,23 +1666,26 @@ func (a *Association) getOrCreateStream(streamIdentifier uint16, accept bool, de if s != nil { s.SetDefaultPayloadType(defaultPayloadType) } + return s } // The caller should hold the lock. -func (a *Association) processSelectiveAck(d *chunkSelectiveAck) (map[uint16]int, uint32, error) { // nolint:gocognit +// +//nolint:gocognit,cyclop +func (a *Association) processSelectiveAck(selectiveAckChunk *chunkSelectiveAck) (map[uint16]int, uint32, error) { bytesAckedPerStream := map[uint16]int{} // New ack point, so pop all ACKed packets from inflightQueue // We add 1 because the "currentAckPoint" has already been popped from the inflight queue // For the first SACK we take care of this by setting the ackpoint to cumAck - 1 - for i := a.cumulativeTSNAckPoint + 1; sna32LTE(i, d.cumulativeTSNAck); i++ { - c, ok := a.inflightQueue.pop(i) + for i := a.cumulativeTSNAckPoint + 1; sna32LTE(i, selectiveAckChunk.cumulativeTSNAck); i++ { + chunkPayload, ok := a.inflightQueue.pop(i) if !ok { return nil, 0, fmt.Errorf("%w: %v", ErrInflightQueueTSNPop, i) } - if !c.acked { + if !chunkPayload.acked { // RFC 4096 sec 6.3.2. Retransmission Timer Rules // R3) Whenever a SACK is received that acknowledges the DATA chunk // with the earliest outstanding TSN for that address, restart the @@ -1449,13 +1696,13 @@ func (a *Association) processSelectiveAck(d *chunkSelectiveAck) (map[uint16]int, a.t3RTX.stop() } - nBytesAcked := len(c.userData) + nBytesAcked := len(chunkPayload.userData) // Sum the number of bytes acknowledged per stream - if amount, ok := bytesAckedPerStream[c.streamIdentifier]; ok { - bytesAckedPerStream[c.streamIdentifier] = amount + nBytesAcked + if amount, ok := bytesAckedPerStream[chunkPayload.streamIdentifier]; ok { + bytesAckedPerStream[chunkPayload.streamIdentifier] = amount + nBytesAcked } else { - bytesAckedPerStream[c.streamIdentifier] = nBytesAcked + bytesAckedPerStream[chunkPayload.streamIdentifier] = nBytesAcked } // RFC 4960 sec 6.3.1. RTO Calculation @@ -1467,9 +1714,9 @@ func (a *Association) processSelectiveAck(d *chunkSelectiveAck) (map[uint16]int, // packets that were retransmitted (and thus for which it is // ambiguous whether the reply was for the first instance of the // chunk or for a later instance) - if c.nSent == 1 && sna32GTE(c.tsn, a.minTSN2MeasureRTT) { + if chunkPayload.nSent == 1 && sna32GTE(chunkPayload.tsn, a.minTSN2MeasureRTT) { a.minTSN2MeasureRTT = a.myNextTSN - rtt := time.Since(c.since).Seconds() * 1000.0 + rtt := time.Since(chunkPayload.since).Seconds() * 1000.0 srtt := a.rtoMgr.setNewRTT(rtt) a.srtt.Store(srtt) a.log.Tracef("[%s] SACK: measured-rtt=%f srtt=%f new-rto=%f", @@ -1477,38 +1724,38 @@ func (a *Association) processSelectiveAck(d *chunkSelectiveAck) (map[uint16]int, } } - if a.inFastRecovery && c.tsn == a.fastRecoverExitPoint { + if a.inFastRecovery && chunkPayload.tsn == a.fastRecoverExitPoint { a.log.Debugf("[%s] exit fast-recovery", a.name) a.inFastRecovery = false } } - htna := d.cumulativeTSNAck + htna := selectiveAckChunk.cumulativeTSNAck // Mark selectively acknowledged chunks as "acked" - for _, g := range d.gapAckBlocks { + for _, g := range selectiveAckChunk.gapAckBlocks { for i := g.start; i <= g.end; i++ { - tsn := d.cumulativeTSNAck + uint32(i) - c, ok := a.inflightQueue.get(tsn) + tsn := selectiveAckChunk.cumulativeTSNAck + uint32(i) + chunkPayload, ok := a.inflightQueue.get(tsn) if !ok { return nil, 0, fmt.Errorf("%w: %v", ErrTSNRequestNotExist, tsn) } - if !c.acked { + if !chunkPayload.acked { nBytesAcked := a.inflightQueue.markAsAcked(tsn) // Sum the number of bytes acknowledged per stream - if amount, ok := bytesAckedPerStream[c.streamIdentifier]; ok { - bytesAckedPerStream[c.streamIdentifier] = amount + nBytesAcked + if amount, ok := bytesAckedPerStream[chunkPayload.streamIdentifier]; ok { + bytesAckedPerStream[chunkPayload.streamIdentifier] = amount + nBytesAcked } else { - bytesAckedPerStream[c.streamIdentifier] = nBytesAcked + bytesAckedPerStream[chunkPayload.streamIdentifier] = nBytesAcked } - a.log.Tracef("[%s] tsn=%d has been sacked", a.name, c.tsn) + a.log.Tracef("[%s] tsn=%d has been sacked", a.name, chunkPayload.tsn) - if c.nSent == 1 { + if chunkPayload.nSent == 1 { a.minTSN2MeasureRTT = a.myNextTSN - rtt := time.Since(c.since).Seconds() * 1000.0 + rtt := time.Since(chunkPayload.since).Seconds() * 1000.0 srtt := a.rtoMgr.setNewRTT(rtt) a.srtt.Store(srtt) a.log.Tracef("[%s] SACK: measured-rtt=%f srtt=%f new-rto=%f", @@ -1539,7 +1786,7 @@ func (a *Association) onCumulativeTSNAckPointAdvanced(totalBytesAcked int) { } // Update congestion control parameters - if a.cwnd <= a.ssthresh { + if a.CWND() <= a.ssthresh { //nolint:nestif // RFC 4096, sec 7.2.1. Slow-Start // o When cwnd is less than or equal to ssthresh, an SCTP endpoint MUST // use the slow-start algorithm to increase cwnd only if the current @@ -1553,13 +1800,13 @@ func (a *Association) onCumulativeTSNAckPointAdvanced(totalBytesAcked int) { // path MTU. if !a.inFastRecovery && a.pendingQueue.size() > 0 { - a.cwnd += min32(uint32(totalBytesAcked), a.cwnd) // TCP way - // a.cwnd += min32(uint32(totalBytesAcked), a.mtu) // SCTP way (slow) + a.setCWND(a.CWND() + min32(uint32(totalBytesAcked), a.CWND())) //nolint:gosec // G115 + // a.cwnd += min32(uint32(totalBytesAcked), a.MTU()) // SCTP way (slow) a.log.Tracef("[%s] updated cwnd=%d ssthresh=%d acked=%d (SS)", - a.name, a.cwnd, a.ssthresh, totalBytesAcked) + a.name, a.CWND(), a.ssthresh, totalBytesAcked) } else { a.log.Tracef("[%s] cwnd did not grow: cwnd=%d ssthresh=%d acked=%d FR=%v pending=%d", - a.name, a.cwnd, a.ssthresh, totalBytesAcked, a.inFastRecovery, a.pendingQueue.size()) + a.name, a.CWND(), a.ssthresh, totalBytesAcked, a.inFastRecovery, a.pendingQueue.size()) } } else { // RFC 4096, sec 7.2.2. Congestion Avoidance @@ -1568,24 +1815,35 @@ func (a *Association) onCumulativeTSNAckPointAdvanced(totalBytesAcked int) { // partial_bytes_acked by the total number of bytes of all new chunks // acknowledged in that SACK including chunks acknowledged by the new // Cumulative TSN Ack and by Gap Ack Blocks. - a.partialBytesAcked += uint32(totalBytesAcked) + a.partialBytesAcked += uint32(totalBytesAcked) //nolint:gosec // G115 // o When partial_bytes_acked is equal to or greater than cwnd and // before the arrival of the SACK the sender had cwnd or more bytes // of data outstanding (i.e., before arrival of the SACK, flight size // was greater than or equal to cwnd), increase cwnd by MTU, and // reset partial_bytes_acked to (partial_bytes_acked - cwnd). - if a.partialBytesAcked >= a.cwnd && a.pendingQueue.size() > 0 { - a.partialBytesAcked -= a.cwnd - a.cwnd += a.mtu + if a.partialBytesAcked >= a.CWND() && a.pendingQueue.size() > 0 { + a.partialBytesAcked -= a.CWND() + step := a.MTU() + if step < a.cwndCAStep { + step = a.cwndCAStep + } + a.setCWND(a.CWND() + step) a.log.Tracef("[%s] updated cwnd=%d ssthresh=%d acked=%d (CA)", - a.name, a.cwnd, a.ssthresh, totalBytesAcked) + a.name, a.CWND(), a.ssthresh, totalBytesAcked) } } } // The caller should hold the lock. -func (a *Association) processFastRetransmission(cumTSNAckPoint, htna uint32, cumTSNAckPointAdvanced bool) error { +// +//nolint:cyclop +func (a *Association) processFastRetransmission( + cumTSNAckPoint uint32, + gapAckBlocks []gapAckBlock, + htna uint32, + cumTSNAckPointAdvanced bool, +) error { // HTNA algorithm - RFC 4960 Sec 7.2.4 // Increment missIndicator of each chunks that the SACK reported missing // when either of the following is met: @@ -1595,14 +1853,19 @@ func (a *Association) processFastRetransmission(cumTSNAckPoint, htna uint32, cum // b) In fast-recovery AND the Cumulative TSN Ack Point advanced // the miss indications are incremented for all TSNs reported missing // in the SACK. - if !a.inFastRecovery || (a.inFastRecovery && cumTSNAckPointAdvanced) { + //nolint:nestif + if !a.inFastRecovery || + (a.inFastRecovery && cumTSNAckPointAdvanced) { var maxTSN uint32 if !a.inFastRecovery { // a) increment only for missing TSNs prior to the HTNA maxTSN = htna } else { // b) increment for all TSNs reported missing - maxTSN = cumTSNAckPoint + uint32(a.inflightQueue.size()) + 1 + maxTSN = cumTSNAckPoint + if len(gapAckBlocks) > 0 { + maxTSN += uint32(gapAckBlocks[len(gapAckBlocks)-1].end) + } } for tsn := cumTSNAckPoint + 1; sna32LT(tsn, maxTSN); tsn++ { @@ -1619,13 +1882,13 @@ func (a *Association) processFastRetransmission(cumTSNAckPoint, htna uint32, cum // last sent, according to the formula described in Section 7.2.3. a.inFastRecovery = true a.fastRecoverExitPoint = htna - a.ssthresh = max32(a.cwnd/2, 4*a.mtu) - a.cwnd = a.ssthresh + a.ssthresh = max32(a.CWND()/2, 4*a.MTU()) + a.setCWND(a.ssthresh) a.partialBytesAcked = 0 a.willRetransmitFast = true a.log.Tracef("[%s] updated cwnd=%d ssthresh=%d inflight=%d (FR)", - a.name, a.cwnd, a.ssthresh, a.inflightQueue.getNumBytes()) + a.name, a.CWND(), a.ssthresh, a.inflightQueue.getNumBytes()) } } } @@ -1640,16 +1903,21 @@ func (a *Association) processFastRetransmission(cumTSNAckPoint, htna uint32, cum } // The caller should hold the lock. -func (a *Association) handleSack(d *chunkSelectiveAck) error { - a.log.Tracef("[%s] SACK: cumTSN=%d a_rwnd=%d", a.name, d.cumulativeTSNAck, d.advertisedReceiverWindowCredit) +// +//nolint:cyclop +func (a *Association) handleSack(selectiveAckChunk *chunkSelectiveAck) error { + a.log.Tracef( + "[%s] SACK: cumTSN=%d a_rwnd=%d", + a.name, selectiveAckChunk.cumulativeTSNAck, selectiveAckChunk.advertisedReceiverWindowCredit, + ) state := a.getState() if state != established && state != shutdownPending && state != shutdownReceived { return nil } - a.stats.incSACKs() + a.stats.incSACKsReceived() - if sna32GT(a.cumulativeTSNAckPoint, d.cumulativeTSNAck) { + if sna32GT(a.cumulativeTSNAckPoint, selectiveAckChunk.cumulativeTSNAck) { // RFC 4960 sec 6.2.1. Processing a Received SACK // D) // i) If Cumulative TSN Ack is less than the Cumulative TSN Ack @@ -1660,14 +1928,14 @@ func (a *Association) handleSack(d *chunkSelectiveAck) error { a.log.Debugf("[%s] SACK Cumulative ACK %v is older than ACK point %v", a.name, - d.cumulativeTSNAck, + selectiveAckChunk.cumulativeTSNAck, a.cumulativeTSNAckPoint) return nil } // Process selective ack - bytesAckedPerStream, htna, err := a.processSelectiveAck(d) + bytesAckedPerStream, htna, err := a.processSelectiveAck(selectiveAckChunk) if err != nil { return err } @@ -1678,13 +1946,13 @@ func (a *Association) handleSack(d *chunkSelectiveAck) error { } cumTSNAckPointAdvanced := false - if sna32LT(a.cumulativeTSNAckPoint, d.cumulativeTSNAck) { + if sna32LT(a.cumulativeTSNAckPoint, selectiveAckChunk.cumulativeTSNAck) { a.log.Tracef("[%s] SACK: cumTSN advanced: %d -> %d", a.name, a.cumulativeTSNAckPoint, - d.cumulativeTSNAck) + selectiveAckChunk.cumulativeTSNAck) - a.cumulativeTSNAckPoint = d.cumulativeTSNAck + a.cumulativeTSNAckPoint = selectiveAckChunk.cumulativeTSNAck cumTSNAckPointAdvanced = true a.onCumulativeTSNAckPointAdvanced(totalBytesAcked) } @@ -1705,14 +1973,16 @@ func (a *Association) handleSack(d *chunkSelectiveAck) error { // TSN Ack and the Gap Ack Blocks. // bytes acked were already subtracted by markAsAcked() method - bytesOutstanding := uint32(a.inflightQueue.getNumBytes()) - if bytesOutstanding >= d.advertisedReceiverWindowCredit { - a.rwnd = 0 + bytesOutstanding := uint32(a.inflightQueue.getNumBytes()) //nolint:gosec // G115 + if bytesOutstanding >= selectiveAckChunk.advertisedReceiverWindowCredit { + a.setRWND(0) } else { - a.rwnd = d.advertisedReceiverWindowCredit - bytesOutstanding + a.setRWND(selectiveAckChunk.advertisedReceiverWindowCredit - bytesOutstanding) } - err = a.processFastRetransmission(d.cumulativeTSNAck, htna, cumTSNAckPointAdvanced) + err = a.processFastRetransmission( + selectiveAckChunk.cumulativeTSNAck, selectiveAckChunk.gapAckBlocks, htna, cumTSNAckPointAdvanced, + ) if err != nil { return err } @@ -1864,7 +2134,10 @@ func (a *Association) createForwardTSN() *chunkForwardTSN { sequence: ssn, }) } - a.log.Tracef("[%s] building fwdtsn: newCumulativeTSN=%d cumTSN=%d - %s", a.name, fwdtsn.newCumulativeTSN, a.cumulativeTSNAckPoint, streamStr) + a.log.Tracef( + "[%s] building fwdtsn: newCumulativeTSN=%d cumTSN=%d - %s", + a.name, fwdtsn.newCumulativeTSN, a.cumulativeTSNAckPoint, streamStr, + ) return fwdtsn } @@ -1881,34 +2154,35 @@ func (a *Association) createPacket(cs []chunk) *packet { } // The caller should hold the lock. -func (a *Association) handleReconfig(c *chunkReconfig) ([]*packet, error) { +func (a *Association) handleReconfig(reconfigChunk *chunkReconfig) ([]*packet, error) { a.log.Tracef("[%s] handleReconfig", a.name) pp := make([]*packet, 0) - p, err := a.handleReconfigParam(c.paramA) + pkt, err := a.handleReconfigParam(reconfigChunk.paramA) if err != nil { return nil, err } - if p != nil { - pp = append(pp, p) + if pkt != nil { + pp = append(pp, pkt) } - if c.paramB != nil { - p, err = a.handleReconfigParam(c.paramB) + if reconfigChunk.paramB != nil { + pkt, err = a.handleReconfigParam(reconfigChunk.paramB) if err != nil { return nil, err } - if p != nil { - pp = append(pp, p) + if pkt != nil { + pp = append(pp, pkt) } } + return pp, nil } // The caller should hold the lock. -func (a *Association) handleForwardTSN(c *chunkForwardTSN) []*packet { - a.log.Tracef("[%s] FwdTSN: %s", a.name, c.String()) +func (a *Association) handleForwardTSN(chunkTSN *chunkForwardTSN) []*packet { + a.log.Tracef("[%s] FwdTSN: %s", a.name, chunkTSN.String()) if !a.useForwardTSN { a.log.Warn("[%s] received FwdTSN but not enabled") @@ -1921,6 +2195,7 @@ func (a *Association) handleForwardTSN(c *chunkForwardTSN) []*packet { outbound.sourcePort = a.sourcePort outbound.destinationPort = a.destinationPort outbound.chunks = []chunk{cerr} + return []*packet{outbound} } @@ -1933,12 +2208,13 @@ func (a *Association) handleForwardTSN(c *chunkForwardTSN) []*packet { // duplicate may indicate the previous SACK was lost in the network. a.log.Tracef("[%s] should send ack? newCumTSN=%d peerLastTSN=%d", - a.name, c.newCumulativeTSN, a.peerLastTSN) - if sna32LTE(c.newCumulativeTSN, a.peerLastTSN) { + a.name, chunkTSN.newCumulativeTSN, a.peerLastTSN()) + if sna32LTE(chunkTSN.newCumulativeTSN, a.peerLastTSN()) { a.log.Tracef("[%s] sending ack on Forward TSN", a.name) a.ackState = ackStateImmediate a.ackTimer.stop() a.awakeWriteLoop() + return nil } @@ -1953,15 +2229,14 @@ func (a *Association) handleForwardTSN(c *chunkForwardTSN) []*packet { // chunk, // Advance peerLastTSN - for sna32LT(a.peerLastTSN, c.newCumulativeTSN) { - a.payloadQueue.pop(a.peerLastTSN + 1) // may not exist - a.peerLastTSN++ + for sna32LT(a.peerLastTSN(), chunkTSN.newCumulativeTSN) { + a.payloadQueue.pop(true) // may not exist } // Report new peerLastTSN value and abandoned largest SSN value to // corresponding streams so that the abandoned chunks can be removed // from the reassemblyQueue. - for _, forwarded := range c.streams { + for _, forwarded := range chunkTSN.streams { if s, ok := a.streams[forwarded.identifier]; ok { s.handleForwardTSNForOrdered(forwarded.sequence) } @@ -1973,7 +2248,7 @@ func (a *Association) handleForwardTSN(c *chunkForwardTSN) []*packet { // unordered chunks. // See https://github.com/pion/sctp/issues/106 for _, s := range a.streams { - s.handleForwardTSNForUnordered(c.newCumulativeTSN) + s.handleForwardTSNForUnordered(chunkTSN.newCumulativeTSN) } return a.handlePeerLastTSNAndAcknowledgement(false) @@ -2000,40 +2275,69 @@ func (a *Association) sendResetRequest(streamIdentifier uint16) error { a.pendingQueue.push(c) a.awakeWriteLoop() + return nil } // The caller should hold the lock. func (a *Association) handleReconfigParam(raw param) (*packet, error) { - switch p := raw.(type) { + switch par := raw.(type) { case *paramOutgoingResetRequest: a.log.Tracef("[%s] handleReconfigParam (OutgoingResetRequest)", a.name) - a.reconfigRequests[p.reconfigRequestSequenceNumber] = p - resp := a.resetStreamsIfAny(p) + if a.peerLastTSN() < par.senderLastTSN && len(a.reconfigRequests) >= maxReconfigRequests { + // We have too many reconfig requests outstanding. Drop the request and let + // the peer retransmit. A well behaved peer should only have 1 outstanding + // reconfig request. + // + // RFC 6525: https://www.rfc-editor.org/rfc/rfc6525.html#section-5.1.1 + // At any given time, there MUST NOT be more than one request in flight. + // So, if the Re-configuration Timer is running and the RE-CONFIG chunk + // contains at least one request parameter, the chunk MUST be buffered. + // chrome: + // https://chromium.googlesource.com/external/webrtc/+/refs/heads/main/net/dcsctp/socket/stream_reset_handler.cc#271 + return nil, fmt.Errorf("%w: %d", ErrTooManyReconfigRequests, len(a.reconfigRequests)) + } + a.reconfigRequests[par.reconfigRequestSequenceNumber] = par + resp := a.resetStreamsIfAny(par) if resp != nil { return resp, nil } - return nil, nil //nolint:nilnil + return nil, nil //nolint:nilnil case *paramReconfigResponse: a.log.Tracef("[%s] handleReconfigParam (ReconfigResponse)", a.name) - delete(a.reconfigs, p.reconfigResponseSequenceNumber) + if par.result == reconfigResultInProgress { + // RFC 6525: https://www.rfc-editor.org/rfc/rfc6525.html#section-5.2.7 + // + // If the Result field indicates "In progress", the timer for the + // Re-configuration Request Sequence Number is started again. If + // the timer runs out, the RE-CONFIG chunk MUST be retransmitted + // but the corresponding error counters MUST NOT be incremented. + if _, ok := a.reconfigs[par.reconfigResponseSequenceNumber]; ok { + a.tReconfig.stop() + a.tReconfig.start(a.rtoMgr.getRTO()) + } + + return nil, nil //nolint:nilnil + } + delete(a.reconfigs, par.reconfigResponseSequenceNumber) if len(a.reconfigs) == 0 { a.tReconfig.stop() } + return nil, nil //nolint:nilnil default: - return nil, fmt.Errorf("%w: %t", ErrParamterType, p) + return nil, fmt.Errorf("%w: %t", ErrParamterType, par) } } // The caller should hold the lock. -func (a *Association) resetStreamsIfAny(p *paramOutgoingResetRequest) *packet { +func (a *Association) resetStreamsIfAny(resetRequest *paramOutgoingResetRequest) *packet { result := reconfigResultSuccessPerformed - if sna32LTE(p.senderLastTSN, a.peerLastTSN) { + if sna32LTE(resetRequest.senderLastTSN, a.peerLastTSN()) { a.log.Debugf("[%s] resetStream(): senderLastTSN=%d <= peerLastTSN=%d", - a.name, p.senderLastTSN, a.peerLastTSN) - for _, id := range p.streamIdentifiers { + a.name, resetRequest.senderLastTSN, a.peerLastTSN()) + for _, id := range resetRequest.streamIdentifiers { s, ok := a.streams[id] if !ok { continue @@ -2044,16 +2348,16 @@ func (a *Association) resetStreamsIfAny(p *paramOutgoingResetRequest) *packet { a.log.Debugf("[%s] deleting stream %d", a.name, id) delete(a.streams, s.streamIdentifier) } - delete(a.reconfigRequests, p.reconfigRequestSequenceNumber) + delete(a.reconfigRequests, resetRequest.reconfigRequestSequenceNumber) } else { a.log.Debugf("[%s] resetStream(): senderLastTSN=%d > peerLastTSN=%d", - a.name, p.senderLastTSN, a.peerLastTSN) + a.name, resetRequest.senderLastTSN, a.peerLastTSN()) result = reconfigResultInProgress } return a.createPacket([]chunk{&chunkReconfig{ paramA: ¶mReconfigResponse{ - reconfigResponseSequenceNumber: p.reconfigRequestSequenceNumber, + reconfigResponseSequenceNumber: resetRequest.reconfigRequestSequenceNumber, result: result, }, }}) @@ -2061,38 +2365,49 @@ func (a *Association) resetStreamsIfAny(p *paramOutgoingResetRequest) *packet { // Move the chunk peeked with a.pendingQueue.peek() to the inflightQueue. // The caller should hold the lock. -func (a *Association) movePendingDataChunkToInflightQueue(c *chunkPayloadData) { - if err := a.pendingQueue.pop(c); err != nil { +func (a *Association) movePendingDataChunkToInflightQueue(chunkPayload *chunkPayloadData) { + if err := a.pendingQueue.pop(chunkPayload); err != nil { a.log.Errorf("[%s] failed to pop from pending queue: %s", a.name, err.Error()) } // Mark all fragements are in-flight now - if c.endingFragment { - c.setAllInflight() + if chunkPayload.endingFragment { + chunkPayload.setAllInflight() } // Assign TSN - c.tsn = a.generateNextTSN() + chunkPayload.tsn = a.generateNextTSN() - c.since = time.Now() // use to calculate RTT and also for maxPacketLifeTime - c.nSent = 1 // being sent for the first time + chunkPayload.since = time.Now() // use to calculate RTT and also for maxPacketLifeTime + chunkPayload.nSent = 1 // being sent for the first time - a.checkPartialReliabilityStatus(c) + a.checkPartialReliabilityStatus(chunkPayload) - a.log.Tracef("[%s] sending ppi=%d tsn=%d ssn=%d sent=%d len=%d (%v,%v)", - a.name, c.payloadType, c.tsn, c.streamSequenceNumber, c.nSent, len(c.userData), c.beginningFragment, c.endingFragment) + a.log.Tracef( + "[%s] sending ppi=%d tsn=%d ssn=%d sent=%d len=%d (%v,%v)", + a.name, + chunkPayload.payloadType, + chunkPayload.tsn, + chunkPayload.streamSequenceNumber, + chunkPayload.nSent, + len(chunkPayload.userData), + chunkPayload.beginningFragment, + chunkPayload.endingFragment, + ) - a.inflightQueue.pushNoCheck(c) + a.inflightQueue.pushNoCheck(chunkPayload) } // popPendingDataChunksToSend pops chunks from the pending queues as many as // the cwnd and rwnd allows to send. // The caller should hold the lock. +// +//nolint:cyclop func (a *Association) popPendingDataChunksToSend() ([]*chunkPayloadData, []uint16) { chunks := []*chunkPayloadData{} var sisToReset []uint16 // stream identifieres to reset - if a.pendingQueue.size() > 0 { + if a.pendingQueue.size() > 0 { //nolint:nestif // RFC 4960 sec 6.1. Transmission of DATA Chunks // A) At any given time, the data sender MUST NOT transmit new data to // any destination transport address if its peer's rwnd indicates @@ -2102,33 +2417,34 @@ func (a *Association) popPendingDataChunksToSend() ([]*chunkPayloadData, []uint1 // the receiver if allowed by cwnd (see rule B, below). for { - c := a.pendingQueue.peek() - if c == nil { + chunkPayload := a.pendingQueue.peek() + if chunkPayload == nil { break // no more pending data } - dataLen := uint32(len(c.userData)) + dataLen := uint32(len(chunkPayload.userData)) //nolint:gosec // G115 if dataLen == 0 { - sisToReset = append(sisToReset, c.streamIdentifier) - err := a.pendingQueue.pop(c) + sisToReset = append(sisToReset, chunkPayload.streamIdentifier) + err := a.pendingQueue.pop(chunkPayload) if err != nil { a.log.Errorf("failed to pop from pending queue: %s", err.Error()) } + continue } - if uint32(a.inflightQueue.getNumBytes())+dataLen > a.cwnd { + if uint32(a.inflightQueue.getNumBytes())+dataLen > a.CWND() { //nolint:gosec // G115 break // would exceeds cwnd } - if dataLen > a.rwnd { + if dataLen > a.RWND() { break // no more rwnd } - a.rwnd -= dataLen + a.setRWND(a.RWND() - dataLen) - a.movePendingDataChunkToInflightQueue(c) - chunks = append(chunks, c) + a.movePendingDataChunkToInflightQueue(chunkPayload) + chunks = append(chunks, chunkPayload) } // the data sender can always have one DATA chunk in flight to the receiver @@ -2142,6 +2458,11 @@ func (a *Association) popPendingDataChunksToSend() ([]*chunkPayloadData, []uint1 } } + if a.blockWrite && len(chunks) > 0 && a.pendingQueue.size() == 0 { + a.log.Tracef("[%s] all pending data have been sent, notify writable", a.name) + a.notifyBlockWritable() + } + return chunks, sisToReset } @@ -2154,20 +2475,21 @@ func (a *Association) bundleDataChunksIntoPackets(chunks []*chunkPayloadData) [] chunksToSend := []chunk{} bytesInPacket := int(commonHeaderSize) - for _, c := range chunks { + for _, chunkPayload := range chunks { // RFC 4960 sec 6.1. Transmission of DATA Chunks // Multiple DATA chunks committed for transmission MAY be bundled in a // single packet. Furthermore, DATA chunks being retransmitted MAY be // bundled with new DATA chunks, as long as the resulting packet size // does not exceed the path MTU. - if bytesInPacket+len(c.userData) > int(a.mtu) { + chunkSizeInPacket := int(dataChunkHeaderSize) + len(chunkPayload.userData) + chunkSizeInPacket += getPadding(chunkSizeInPacket) + if bytesInPacket+chunkSizeInPacket > int(a.MTU()) { packets = append(packets, a.createPacket(chunksToSend)) chunksToSend = []chunk{} bytesInPacket = int(commonHeaderSize) } - - chunksToSend = append(chunksToSend, c) - bytesInPacket += int(dataChunkHeaderSize) + len(c.userData) + chunksToSend = append(chunksToSend, chunkPayload) + bytesInPacket += chunkSizeInPacket } if len(chunksToSend) > 0 { @@ -2178,27 +2500,43 @@ func (a *Association) bundleDataChunksIntoPackets(chunks []*chunkPayloadData) [] } // sendPayloadData sends the data chunks. -func (a *Association) sendPayloadData(chunks []*chunkPayloadData) error { +func (a *Association) sendPayloadData(ctx context.Context, chunks []*chunkPayloadData) error { a.lock.Lock() - defer a.lock.Unlock() state := a.getState() if state != established { + a.lock.Unlock() + return fmt.Errorf("%w: state=%s", ErrPayloadDataStateNotExist, getAssociationStateString(state)) } + if a.blockWrite { + for a.writePending { + a.lock.Unlock() + select { + case <-ctx.Done(): + return ctx.Err() + case <-a.writeNotify: + a.lock.Lock() + } + } + a.writePending = true + } + // Push the chunks into the pending queue first. for _, c := range chunks { a.pendingQueue.push(c) } + a.lock.Unlock() a.awakeWriteLoop() + return nil } // The caller should hold the lock. -func (a *Association) checkPartialReliabilityStatus(c *chunkPayloadData) { +func (a *Association) checkPartialReliabilityStatus(chunkPayload *chunkPayloadData) { if !a.useForwardTSN { return } @@ -2208,28 +2546,35 @@ func (a *Association) checkPartialReliabilityStatus(c *chunkPayloadData) { // All Data Channel Establishment Protocol messages MUST be sent using // ordered delivery and reliable transmission. // - if c.payloadType == PayloadTypeWebRTCDCEP { + if chunkPayload.payloadType == PayloadTypeWebRTCDCEP { return } // PR-SCTP - if s, ok := a.streams[c.streamIdentifier]; ok { - s.lock.RLock() - if s.reliabilityType == ReliabilityTypeRexmit { - if c.nSent >= s.reliabilityValue { - c.setAbandoned(true) - a.log.Tracef("[%s] marked as abandoned: tsn=%d ppi=%d (remix: %d)", a.name, c.tsn, c.payloadType, c.nSent) + if stream, ok := a.streams[chunkPayload.streamIdentifier]; ok { //nolint:nestif + stream.lock.RLock() + if stream.reliabilityType == ReliabilityTypeRexmit { + if chunkPayload.nSent >= stream.reliabilityValue { + chunkPayload.setAbandoned(true) + a.log.Tracef( + "[%s] marked as abandoned: tsn=%d ppi=%d (remix: %d)", + a.name, chunkPayload.tsn, chunkPayload.payloadType, chunkPayload.nSent, + ) } - } else if s.reliabilityType == ReliabilityTypeTimed { - elapsed := int64(time.Since(c.since).Seconds() * 1000) - if elapsed >= int64(s.reliabilityValue) { - c.setAbandoned(true) - a.log.Tracef("[%s] marked as abandoned: tsn=%d ppi=%d (timed: %d)", a.name, c.tsn, c.payloadType, elapsed) + } else if stream.reliabilityType == ReliabilityTypeTimed { + elapsed := int64(time.Since(chunkPayload.since).Seconds() * 1000) + if elapsed >= int64(stream.reliabilityValue) { + chunkPayload.setAbandoned(true) + a.log.Tracef( + "[%s] marked as abandoned: tsn=%d ppi=%d (timed: %d)", + a.name, chunkPayload.tsn, chunkPayload.payloadType, elapsed, + ) } } - s.lock.RUnlock() + stream.lock.RUnlock() } else { - a.log.Errorf("[%s] stream %d not found)", a.name, c.streamIdentifier) + // Remote has reset its send side of the stream, we can still send data. + a.log.Tracef("[%s] stream %d not found, remote reset", a.name, chunkPayload.streamIdentifier) } } @@ -2237,40 +2582,43 @@ func (a *Association) checkPartialReliabilityStatus(c *chunkPayloadData) { // that are not acked or abandoned yet. // The caller should hold the lock. func (a *Association) getDataPacketsToRetransmit() []*packet { - awnd := min32(a.cwnd, a.rwnd) + awnd := min32(a.CWND(), a.RWND()) chunks := []*chunkPayloadData{} var bytesToSend int var done bool for i := 0; !done; i++ { - c, ok := a.inflightQueue.get(a.cumulativeTSNAckPoint + uint32(i) + 1) + chunkPayload, ok := a.inflightQueue.get(a.cumulativeTSNAckPoint + uint32(i) + 1) //nolint:gosec // G115 if !ok { break // end of pending data } - if !c.retransmit { + if !chunkPayload.retransmit { continue } - if i == 0 && int(a.rwnd) < len(c.userData) { + if i == 0 && int(a.RWND()) < len(chunkPayload.userData) { // Send it as a zero window probe done = true - } else if bytesToSend+len(c.userData) > int(awnd) { + } else if bytesToSend+len(chunkPayload.userData) > int(awnd) { break } // reset the retransmit flag not to retransmit again before the next // t3-rtx timer fires - c.retransmit = false - bytesToSend += len(c.userData) + chunkPayload.retransmit = false + bytesToSend += len(chunkPayload.userData) - c.nSent++ + chunkPayload.nSent++ - a.checkPartialReliabilityStatus(c) + a.checkPartialReliabilityStatus(chunkPayload) - a.log.Tracef("[%s] retransmitting tsn=%d ssn=%d sent=%d", a.name, c.tsn, c.streamSequenceNumber, c.nSent) + a.log.Tracef( + "[%s] retransmitting tsn=%d ssn=%d sent=%d", + a.name, chunkPayload.tsn, chunkPayload.streamSequenceNumber, chunkPayload.nSent, + ) - chunks = append(chunks, c) + chunks = append(chunks, chunkPayload) } return a.bundleDataChunksIntoPackets(chunks) @@ -2281,6 +2629,7 @@ func (a *Association) getDataPacketsToRetransmit() []*packet { func (a *Association) generateNextTSN() uint32 { tsn := a.myNextTSN a.myNextTSN++ + return tsn } @@ -2289,15 +2638,17 @@ func (a *Association) generateNextTSN() uint32 { func (a *Association) generateNextRSN() uint32 { rsn := a.myNextRSN a.myNextRSN++ + return rsn } func (a *Association) createSelectiveAckChunk() *chunkSelectiveAck { sack := &chunkSelectiveAck{} - sack.cumulativeTSNAck = a.peerLastTSN + sack.cumulativeTSNAck = a.peerLastTSN() sack.advertisedReceiverWindowCredit = a.getMyReceiverWindowCredit() sack.duplicateTSN = a.payloadQueue.popDuplicates() - sack.gapAckBlocks = a.payloadQueue.getGapAckBlocks(a.peerLastTSN) + sack.gapAckBlocks = a.payloadQueue.getGapAckBlocks() + return sack } @@ -2305,15 +2656,17 @@ func pack(p *packet) []*packet { return []*packet{p} } -func (a *Association) handleChunkStart() { +func (a *Association) handleChunksStart() { a.lock.Lock() defer a.lock.Unlock() + a.stats.incPacketsReceived() + a.delayedAckTriggered = false a.immediateAckTriggered = false } -func (a *Association) handleChunkEnd() { +func (a *Association) handleChunksEnd() { a.lock.Lock() defer a.lock.Unlock() @@ -2328,65 +2681,72 @@ func (a *Association) handleChunkEnd() { } } -func (a *Association) handleChunk(p *packet, c chunk) error { +func (a *Association) handleChunk(receivedPacket *packet, receivedChunk chunk) error { //nolint:cyclop a.lock.Lock() defer a.lock.Unlock() var packets []*packet var err error - if _, err = c.check(); err != nil { - a.log.Errorf("[ %s ] failed validating chunk: %s ", a.name, err) + if _, err = receivedChunk.check(); err != nil { + a.log.Errorf("[%s] failed validating chunk: %s ", a.name, err) + return nil } isAbort := false - switch c := c.(type) { + switch receivedChunk := receivedChunk.(type) { + // Note: We do not do the following for chunkInit, chunkInitAck, and chunkCookieEcho: + // If an endpoint receives an INIT, INIT ACK, or COOKIE ECHO chunk but decides not to establish the + // new association due to missing mandatory parameters in the received INIT or INIT ACK chunk, invalid + // parameter values, or lack of local resources, it SHOULD respond with an ABORT chunk. + case *chunkInit: - packets, err = a.handleInit(p, c) + packets, err = a.handleInit(receivedPacket, receivedChunk) case *chunkInitAck: - err = a.handleInitAck(p, c) + err = a.handleInitAck(receivedPacket, receivedChunk) case *chunkAbort: isAbort = true - err = a.handleAbort(c) + err = a.handleAbort(receivedChunk) case *chunkError: var errStr string - for _, e := range c.errorCauses { + for _, e := range receivedChunk.errorCauses { errStr += fmt.Sprintf("(%s)", e) } a.log.Debugf("[%s] Error chunk, with following errors: %s", a.name, errStr) + // Note: chunkHeartbeatAck not handled? case *chunkHeartbeat: - packets = a.handleHeartbeat(c) + packets = a.handleHeartbeat(receivedChunk) case *chunkCookieEcho: - packets = a.handleCookieEcho(c) + packets = a.handleCookieEcho(receivedChunk) case *chunkCookieAck: a.handleCookieAck() case *chunkPayloadData: - packets = a.handleData(c) + packets = a.handleData(receivedChunk) case *chunkSelectiveAck: - err = a.handleSack(c) + err = a.handleSack(receivedChunk) case *chunkReconfig: - packets, err = a.handleReconfig(c) + packets, err = a.handleReconfig(receivedChunk) case *chunkForwardTSN: - packets = a.handleForwardTSN(c) + packets = a.handleForwardTSN(receivedChunk) case *chunkShutdown: - a.handleShutdown(c) + a.handleShutdown(receivedChunk) case *chunkShutdownAck: - a.handleShutdownAck(c) + a.handleShutdownAck(receivedChunk) case *chunkShutdownComplete: - err = a.handleShutdownComplete(c) + err = a.handleShutdownComplete(receivedChunk) default: err = ErrChunkTypeUnhandled @@ -2399,6 +2759,7 @@ func (a *Association) handleChunk(p *packet, c chunk) error { } a.log.Errorf("Failed to handle chunk: %v", err) + return nil } @@ -2410,15 +2771,22 @@ func (a *Association) handleChunk(p *packet, c chunk) error { return nil } -func (a *Association) onRetransmissionTimeout(id int, nRtos uint) { +func (a *Association) onRetransmissionTimeout(id int, nRtos uint) { //nolint:cyclop a.lock.Lock() defer a.lock.Unlock() + // TSN hasn't been incremented in 3 attempts. Speculatively + // toggle ZeroChecksum because old Pion versions had a broken implementation + if a.cumulativeTSNAckPoint+1 == a.initialTSN && nRtos%3 == 0 { + a.sendZeroChecksum = !a.sendZeroChecksum + } + if id == timerT1Init { err := a.sendInit() if err != nil { a.log.Debugf("[%s] failed to retransmit init (nRtos=%d): %v", a.name, nRtos, err) } + return } @@ -2427,6 +2795,7 @@ func (a *Association) onRetransmissionTimeout(id int, nRtos uint) { if err != nil { a.log.Debugf("[%s] failed to retransmit cookie-echo (nRtos=%d): %v", a.name, nRtos, err) } + return } @@ -2444,7 +2813,7 @@ func (a *Association) onRetransmissionTimeout(id int, nRtos uint) { } } - if id == timerT3RTX { + if id == timerT3RTX { //nolint:nestif a.stats.incT3Timeouts() // RFC 4960 sec 6.3.3 @@ -2457,10 +2826,10 @@ func (a *Association) onRetransmissionTimeout(id int, nRtos uint) { // ssthresh = max(cwnd/2, 4*MTU) // cwnd = 1*MTU - a.ssthresh = max32(a.cwnd/2, 4*a.mtu) - a.cwnd = a.mtu + a.ssthresh = max32(a.CWND()/2, 4*a.MTU()) + a.setCWND(a.MTU()) a.log.Tracef("[%s] updated cwnd=%d ssthresh=%d inflight=%d (RTO)", - a.name, a.cwnd, a.ssthresh, a.inflightQueue.getNumBytes()) + a.name, a.CWND(), a.ssthresh, a.inflightQueue.getNumBytes()) // RFC 3758 sec 3.5 // A5) Any time the T3-rtx timer expires, on any destination, the sender @@ -2485,7 +2854,7 @@ func (a *Association) onRetransmissionTimeout(id int, nRtos uint) { } } - a.log.Debugf("[%s] T3-rtx timed out: nRtos=%d cwnd=%d ssthresh=%d", a.name, nRtos, a.cwnd, a.ssthresh) + a.log.Debugf("[%s] T3-rtx timed out: nRtos=%d cwnd=%d ssthresh=%d", a.name, nRtos, a.CWND(), a.ssthresh) /* a.log.Debugf(" - advancedPeerTSNAckPoint=%d", a.advancedPeerTSNAckPoint) @@ -2517,18 +2886,21 @@ func (a *Association) onRetransmissionFailure(id int) { if id == timerT1Init { a.log.Errorf("[%s] retransmission failure: T1-init", a.name) - a.handshakeCompletedCh <- ErrHandshakeInitAck + a.completeHandshake(ErrHandshakeInitAck) + return } if id == timerT1Cookie { a.log.Errorf("[%s] retransmission failure: T1-cookie", a.name) - a.handshakeCompletedCh <- ErrHandshakeCookieEcho + a.completeHandshake(ErrHandshakeCookieEcho) + return } if id == timerT2Shutdown { a.log.Errorf("[%s] retransmission failure: T2-shutdown", a.name) + return } @@ -2538,6 +2910,7 @@ func (a *Association) onRetransmissionFailure(id int) { // * ICE would fail if the connectivity is lost // * WebRTC spec is not clear how this incident should be reported to ULP a.log.Errorf("[%s] retransmission failure: T3-rtx (DATA)", a.name) + return } } @@ -2553,9 +2926,8 @@ func (a *Association) onAckTimeout() { a.awakeWriteLoop() } -// bufferedAmount returns total amount (in bytes) of currently buffered user data. -// This is used only by testing. -func (a *Association) bufferedAmount() int { +// BufferedAmount returns total amount (in bytes) of currently buffered user data. +func (a *Association) BufferedAmount() int { a.lock.RLock() defer a.lock.RUnlock() @@ -2571,3 +2943,18 @@ func (a *Association) MaxMessageSize() uint32 { func (a *Association) SetMaxMessageSize(maxMsgSize uint32) { atomic.StoreUint32(&a.maxMessageSize, maxMsgSize) } + +// completeHandshake sends the given error to handshakeCompletedCh unless the read/write +// side of the association closes before that can happen. It returns whether it was able +// to send on the channel or not. +func (a *Association) completeHandshake(handshakeErr error) bool { + select { + // Note: This is a future place where the user could be notified (COMMUNICATION UP) + case a.handshakeCompletedCh <- handshakeErr: + return true + case <-a.closeWriteLoopCh: // check the read/write sides for closure + case <-a.readLoopCloseCh: + } + + return false +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/association_stats.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/association_stats.go index 4ccb7be99..0e4e581ba 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/association_stats.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/association_stats.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package sctp import ( @@ -5,11 +8,30 @@ import ( ) type associationStats struct { - nDATAs uint64 - nSACKs uint64 - nT3Timeouts uint64 - nAckTimeouts uint64 - nFastRetrans uint64 + nPacketsReceived uint64 + nPacketsSent uint64 + nDATAs uint64 + nSACKsReceived uint64 + nSACKsSent uint64 + nT3Timeouts uint64 + nAckTimeouts uint64 + nFastRetrans uint64 +} + +func (s *associationStats) incPacketsReceived() { + atomic.AddUint64(&s.nPacketsReceived, 1) +} + +func (s *associationStats) getNumPacketsReceived() uint64 { + return atomic.LoadUint64(&s.nPacketsReceived) +} + +func (s *associationStats) incPacketsSent() { + atomic.AddUint64(&s.nPacketsSent, 1) +} + +func (s *associationStats) getNumPacketsSent() uint64 { + return atomic.LoadUint64(&s.nPacketsSent) } func (s *associationStats) incDATAs() { @@ -20,12 +42,20 @@ func (s *associationStats) getNumDATAs() uint64 { return atomic.LoadUint64(&s.nDATAs) } -func (s *associationStats) incSACKs() { - atomic.AddUint64(&s.nSACKs, 1) +func (s *associationStats) incSACKsReceived() { + atomic.AddUint64(&s.nSACKsReceived, 1) } -func (s *associationStats) getNumSACKs() uint64 { - return atomic.LoadUint64(&s.nSACKs) +func (s *associationStats) getNumSACKsReceived() uint64 { + return atomic.LoadUint64(&s.nSACKsReceived) +} + +func (s *associationStats) incSACKsSent() { + atomic.AddUint64(&s.nSACKsSent, 1) +} + +func (s *associationStats) getNumSACKsSent() uint64 { + return atomic.LoadUint64(&s.nSACKsSent) } func (s *associationStats) incT3Timeouts() { @@ -53,8 +83,11 @@ func (s *associationStats) getNumFastRetrans() uint64 { } func (s *associationStats) reset() { + atomic.StoreUint64(&s.nPacketsReceived, 0) + atomic.StoreUint64(&s.nPacketsSent, 0) atomic.StoreUint64(&s.nDATAs, 0) - atomic.StoreUint64(&s.nSACKs, 0) + atomic.StoreUint64(&s.nSACKsReceived, 0) + atomic.StoreUint64(&s.nSACKsSent, 0) atomic.StoreUint64(&s.nT3Timeouts, 0) atomic.StoreUint64(&s.nAckTimeouts, 0) atomic.StoreUint64(&s.nFastRetrans, 0) diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk.go index ec47da17a..50b8a2e4d 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package sctp type chunk interface { diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_abort.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_abort.go index eab64a4f4..2bf15dc02 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_abort.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_abort.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package sctp // nolint:dupl import ( @@ -31,7 +34,7 @@ type chunkAbort struct { errorCauses []errorCause } -// Abort chunk errors +// Abort chunk errors. var ( ErrChunkTypeNotAbort = errors.New("ChunkType is not of type ABORT") ErrBuildAbortChunkFailed = errors.New("failed build Abort Chunk") @@ -60,6 +63,7 @@ func (a *chunkAbort) unmarshal(raw []byte) error { offset += int(e.length()) a.errorCauses = append(a.errorCauses, e) } + return nil } @@ -74,6 +78,7 @@ func (a *chunkAbort) marshal() ([]byte, error) { } a.raw = append(a.raw, raw...) } + return a.chunkHeader.marshal() } @@ -81,7 +86,7 @@ func (a *chunkAbort) check() (abort bool, err error) { return false, nil } -// String makes chunkAbort printable +// String makes chunkAbort printable. func (a *chunkAbort) String() string { res := a.chunkHeader.String() diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_cookie_ack.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_cookie_ack.go index 5d63b1c48..845674966 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_cookie_ack.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_cookie_ack.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package sctp import ( @@ -18,7 +21,7 @@ type chunkCookieAck struct { chunkHeader } -// Cookie ack chunk errors +// Cookie ack chunk errors. var ( ErrChunkTypeNotCookieAck = errors.New("ChunkType is not of type COOKIEACK") ) @@ -37,6 +40,7 @@ func (c *chunkCookieAck) unmarshal(raw []byte) error { func (c *chunkCookieAck) marshal() ([]byte, error) { c.chunkHeader.typ = ctCookieAck + return c.chunkHeader.marshal() } @@ -44,7 +48,7 @@ func (c *chunkCookieAck) check() (abort bool, err error) { return false, nil } -// String makes chunkCookieAck printable +// String makes chunkCookieAck printable. func (c *chunkCookieAck) String() string { return c.chunkHeader.String() } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_cookie_echo.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_cookie_echo.go index 8eb956647..bf7d361b6 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_cookie_echo.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_cookie_echo.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package sctp import ( @@ -22,7 +25,7 @@ type chunkCookieEcho struct { cookie []byte } -// Cookie echo chunk errors +// Cookie echo chunk errors. var ( ErrChunkTypeNotCookieEcho = errors.New("ChunkType is not of type COOKIEECHO") ) @@ -43,6 +46,7 @@ func (c *chunkCookieEcho) unmarshal(raw []byte) error { func (c *chunkCookieEcho) marshal() ([]byte, error) { c.chunkHeader.typ = ctCookieEcho c.chunkHeader.raw = c.cookie + return c.chunkHeader.marshal() } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_error.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_error.go index d2a2b2971..89328460a 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_error.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_error.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package sctp // nolint:dupl import ( @@ -38,7 +41,7 @@ type chunkError struct { errorCauses []errorCause } -// Error chunk errors +// Error chunk errors. var ( ErrChunkTypeNotCtError = errors.New("ChunkType is not of type ctError") ErrBuildErrorChunkFailed = errors.New("failed build Error Chunk") @@ -67,6 +70,7 @@ func (a *chunkError) unmarshal(raw []byte) error { offset += int(e.length()) a.errorCauses = append(a.errorCauses, e) } + return nil } @@ -81,6 +85,7 @@ func (a *chunkError) marshal() ([]byte, error) { } a.raw = append(a.raw, raw...) } + return a.chunkHeader.marshal() } @@ -88,7 +93,7 @@ func (a *chunkError) check() (abort bool, err error) { return false, nil } -// String makes chunkError printable +// String makes chunkError printable. func (a *chunkError) String() string { res := a.chunkHeader.String() diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_forward_tsn.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_forward_tsn.go index 70b5079f0..e342e6581 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_forward_tsn.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_forward_tsn.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package sctp import ( @@ -43,7 +46,7 @@ const ( forwardTSNStreamLength = 4 ) -// Forward TSN chunk errors +// Forward TSN chunk errors. var ( ErrMarshalStreamFailed = errors.New("failed to marshal stream") ErrChunkTooShort = errors.New("chunk too short") @@ -87,11 +90,12 @@ func (c *chunkForwardTSN) marshal() ([]byte, error) { if err != nil { return nil, fmt.Errorf("%w: %v", ErrMarshalStreamFailed, err) //nolint:errorlint } - out = append(out, b...) + out = append(out, b...) //nolint:makezero // TODO: fix } c.typ = ctForwardTSN c.raw = out + return c.chunkHeader.marshal() } @@ -99,12 +103,13 @@ func (c *chunkForwardTSN) check() (abort bool, err error) { return true, nil } -// String makes chunkForwardTSN printable +// String makes chunkForwardTSN printable. func (c *chunkForwardTSN) String() string { res := fmt.Sprintf("New Cumulative TSN: %d\n", c.newCumulativeTSN) for _, s := range c.streams { res += fmt.Sprintf(" - si=%d, ssn=%d\n", s.identifier, s.sequence) } + return res } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_heartbeat.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_heartbeat.go index 3cfcd5ada..341e5442c 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_heartbeat.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_heartbeat.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package sctp import ( @@ -31,13 +34,14 @@ in Section 3.2.1, i.e.: Variable Parameters Status Type Value ------------------------------------------------------------- heartbeat Info Mandatory 1 +. */ type chunkHeartbeat struct { chunkHeader params []param } -// Heartbeat chunk errors +// Heartbeat chunk errors. var ( ErrChunkTypeNotHeartbeat = errors.New("ChunkType is not of type HEARTBEAT") ErrHeartbeatNotLongEnoughInfo = errors.New("heartbeat is not long enough to contain Heartbeat Info") diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_heartbeat_ack.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_heartbeat_ack.go index 3d21b593d..8ccc15312 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_heartbeat_ack.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_heartbeat_ack.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package sctp import ( @@ -31,13 +34,14 @@ in Section 3.2.1, i.e.: Variable Parameters Status Type Value ------------------------------------------------------------- Heartbeat Info Mandatory 1 +. */ type chunkHeartbeatAck struct { chunkHeader params []param } -// Heartbeat ack chunk errors +// Heartbeat ack chunk errors. var ( ErrUnimplemented = errors.New("unimplemented") ErrHeartbeatAckParams = errors.New("heartbeat Ack must have one param") diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_init.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_init.go index 8eab506b9..b31aa9738 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_init.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_init.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package sctp // nolint:dupl import ( @@ -24,7 +27,7 @@ type chunkInit struct { chunkInitCommon } -// Init chunk errors +// Init chunk errors. var ( ErrChunkTypeNotTypeInit = errors.New("ChunkType is not of type INIT") ErrChunkValueNotLongEnough = errors.New("chunk Value isn't long enough for mandatory parameters exp") @@ -35,6 +38,7 @@ var ( ErrInitInboundStreamRequestZero = errors.New("INIT ACK inbound stream request must be > 0") ErrInitOutboundStreamRequestZero = errors.New("INIT ACK outbound stream request must be > 0") ErrInitAdvertisedReceiver1500 = errors.New("INIT ACK Advertised Receiver Window Credit (a_rwnd) must be >= 1500") + ErrInitUnknownParam = errors.New("INIT with unknown param") ) func (i *chunkInit) unmarshal(raw []byte) error { @@ -70,6 +74,7 @@ func (i *chunkInit) marshal() ([]byte, error) { i.chunkHeader.typ = ctInit i.chunkHeader.raw = initShared + return i.chunkHeader.marshal() } @@ -86,8 +91,7 @@ func (i *chunkInit) check() (abort bool, err error) { // to be 0, the receiver MUST treat it as an error and close the // association by transmitting an ABORT. if i.initiateTag == 0 { - abort = true - return abort, ErrChunkTypeInitInitateTagZero + return true, ErrChunkTypeInitInitateTagZero } // Defines the maximum number of streams the sender of this INIT @@ -101,8 +105,7 @@ func (i *chunkInit) check() (abort bool, err error) { // Note: A receiver of an INIT with the MIS value of 0 SHOULD abort // the association. if i.numInboundStreams == 0 { - abort = true - return abort, ErrInitInboundStreamRequestZero + return true, ErrInitInboundStreamRequestZero } // Defines the number of outbound streams the sender of this INIT @@ -113,8 +116,7 @@ func (i *chunkInit) check() (abort bool, err error) { // abort the association. if i.numOutboundStreams == 0 { - abort = true - return abort, ErrInitOutboundStreamRequestZero + return true, ErrInitOutboundStreamRequestZero } // An SCTP receiver MUST be able to receive a minimum of 1500 bytes in @@ -122,14 +124,20 @@ func (i *chunkInit) check() (abort bool, err error) { // less than 1500 bytes in its initial a_rwnd sent in the INIT or INIT // ACK. if i.advertisedReceiverWindowCredit < 1500 { - abort = true - return abort, ErrInitAdvertisedReceiver1500 + return true, ErrInitAdvertisedReceiver1500 + } + + for _, p := range i.unrecognizedParams { + if p.unrecognizedAction == paramHeaderUnrecognizedActionStop || + p.unrecognizedAction == paramHeaderUnrecognizedActionStopAndReport { + return true, ErrInitUnknownParam + } } return false, nil } -// String makes chunkInit printable +// String makes chunkInit printable. func (i *chunkInit) String() string { return fmt.Sprintf("%s\n%s", i.chunkHeader, i.chunkInitCommon) } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_init_ack.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_init_ack.go index c34f1d6b6..abd65c8cf 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_init_ack.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_init_ack.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package sctp // nolint:dupl import ( @@ -24,7 +27,7 @@ type chunkInitAck struct { chunkInitCommon } -// Init ack chunk errors +// Init ack chunk errors. var ( ErrChunkTypeNotInitAck = errors.New("ChunkType is not of type INIT ACK") ErrChunkNotLongEnoughForParams = errors.New("chunk Value isn't long enough for mandatory parameters exp") @@ -70,6 +73,7 @@ func (i *chunkInitAck) marshal() ([]byte, error) { i.chunkHeader.typ = ctInitAck i.chunkHeader.raw = initShared + return i.chunkHeader.marshal() } @@ -88,6 +92,7 @@ func (i *chunkInitAck) check() (abort bool, err error) { // purpose. if i.initiateTag == 0 { abort = true + return abort, ErrChunkTypeInitAckInitateTagZero } @@ -103,6 +108,7 @@ func (i *chunkInitAck) check() (abort bool, err error) { // destroy the association discarding its TCB. if i.numInboundStreams == 0 { abort = true + return abort, ErrInitAckInboundStreamRequestZero } @@ -116,6 +122,7 @@ func (i *chunkInitAck) check() (abort bool, err error) { if i.numOutboundStreams == 0 { abort = true + return abort, ErrInitAckOutboundStreamRequestZero } @@ -125,13 +132,14 @@ func (i *chunkInitAck) check() (abort bool, err error) { // ACK. if i.advertisedReceiverWindowCredit < 1500 { abort = true + return abort, ErrInitAckAdvertisedReceiver1500 } return false, nil } -// String makes chunkInitAck printable +// String makes chunkInitAck printable. func (i *chunkInitAck) String() string { return fmt.Sprintf("%s\n%s", i.chunkHeader, i.chunkInitCommon) } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_init_common.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_init_common.go index c2ccfadc0..5c893a7d7 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_init_common.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_init_common.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package sctp import ( @@ -46,6 +49,7 @@ type chunkInitCommon struct { numInboundStreams uint16 initialTSN uint32 params []param + unrecognizedParams []paramHeader } const ( @@ -53,10 +57,9 @@ const ( initOptionalVarHeaderLength = 4 ) -// Init chunk errors +// Init chunk errors. var ( ErrInitChunkParseParamTypeFailed = errors.New("failed to parse param type") - ErrInitChunkUnmarshalParam = errors.New("failed unmarshalling param in Init Chunk") ErrInitAckMarshalParam = errors.New("unable to marshal parameter for INIT/INITACK") ) @@ -88,18 +91,21 @@ func (i *chunkInitCommon) unmarshal(raw []byte) error { remaining := len(raw) - offset for remaining > 0 { if remaining > initOptionalVarHeaderLength { - pType, err := parseParamType(raw[offset:]) - if err != nil { + var pHeader paramHeader + if err := pHeader.unmarshal(raw[offset:]); err != nil { return fmt.Errorf("%w: %v", ErrInitChunkParseParamTypeFailed, err) //nolint:errorlint } - p, err := buildParam(pType, raw[offset:]) + + p, err := buildParam(pHeader.typ, raw[offset:]) if err != nil { - return fmt.Errorf("%w: %v", ErrInitChunkUnmarshalParam, err) //nolint:errorlint + i.unrecognizedParams = append(i.unrecognizedParams, pHeader) + } else { + i.params = append(i.params, p) } - i.params = append(i.params, p) - padding := getPadding(p.length()) - offset += p.length() + padding - remaining -= p.length() + padding + + padding := getPadding(pHeader.length()) + offset += pHeader.length() + padding + remaining -= pHeader.length() + padding } else { break } @@ -121,7 +127,7 @@ func (i *chunkInitCommon) marshal() ([]byte, error) { return nil, fmt.Errorf("%w: %v", ErrInitAckMarshalParam, err) //nolint:errorlint } - out = append(out, pp...) + out = append(out, pp...) //nolint:makezero // TODO: fix // Chunks (including Type, Length, and Value fields) are padded out // by the sender with all zero bytes to be a multiple of 4 bytes @@ -138,7 +144,7 @@ func (i *chunkInitCommon) marshal() ([]byte, error) { return out, nil } -// String makes chunkInitCommon printable +// String makes chunkInitCommon printable. func (i chunkInitCommon) String() string { format := `initiateTag: %d advertisedReceiverWindowCredit: %d @@ -157,5 +163,6 @@ func (i chunkInitCommon) String() string { for i, param := range i.params { res += fmt.Sprintf("Param %d:\n %s", i, param) } + return res } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_payload_data.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_payload_data.go index 50554ac45..1ff9b5916 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_payload_data.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_payload_data.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package sctp import ( @@ -83,7 +86,7 @@ const ( payloadDataHeaderSize = 12 ) -// PayloadProtocolIdentifier is an enum for DataChannel payload types +// PayloadProtocolIdentifier is an enum for DataChannel payload types. type PayloadProtocolIdentifier uint32 // PayloadProtocolIdentifier enums @@ -97,7 +100,7 @@ const ( PayloadTypeWebRTCBinaryEmpty PayloadProtocolIdentifier = 57 ) -// Data chunk errors +// Data chunk errors. var ( ErrChunkPayloadSmall = errors.New("packet is smaller than the header size") ) @@ -129,7 +132,7 @@ func (p *chunkPayloadData) unmarshal(raw []byte) error { p.beginningFragment = p.flags&payloadDataBeginingFragmentBitmask != 0 p.endingFragment = p.flags&payloadDataEndingFragmentBitmask != 0 - if len(raw) < payloadDataHeaderSize { + if len(p.raw) < payloadDataHeaderSize { return ErrChunkPayloadSmall } p.tsn = binary.BigEndian.Uint32(p.raw[0:]) @@ -167,6 +170,7 @@ func (p *chunkPayloadData) marshal() ([]byte, error) { p.chunkHeader.flags = flags p.chunkHeader.typ = ctPayloadData p.chunkHeader.raw = payRaw + return p.chunkHeader.marshal() } @@ -174,7 +178,7 @@ func (p *chunkPayloadData) check() (abort bool, err error) { return false, nil } -// String makes chunkPayloadData printable +// String makes chunkPayloadData printable. func (p *chunkPayloadData) String() string { return fmt.Sprintf("%s\n%d", p.chunkHeader, p.tsn) } @@ -183,12 +187,14 @@ func (p *chunkPayloadData) abandoned() bool { if p.head != nil { return p.head._abandoned && p.head._allInflight } + return p._abandoned && p._allInflight } func (p *chunkPayloadData) setAbandoned(abandoned bool) { if p.head != nil { p.head._abandoned = abandoned + return } p._abandoned = abandoned @@ -203,3 +209,7 @@ func (p *chunkPayloadData) setAllInflight() { } } } + +func (p *chunkPayloadData) isFragmented() bool { + return !(p.head == nil && p.beginningFragment && p.endingFragment) +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_reconfig.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_reconfig.go index 9b018b213..8e47c2bb5 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_reconfig.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_reconfig.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package sctp import ( @@ -28,7 +31,7 @@ type chunkReconfig struct { paramB param } -// Reconfigure chunk errors +// Reconfigure chunk errors. var ( ErrChunkParseParamTypeFailed = errors.New("failed to parse param type") ErrChunkMarshalParamAReconfigFailed = errors.New("unable to marshal parameter A for reconfig") @@ -85,6 +88,7 @@ func (c *chunkReconfig) marshal() ([]byte, error) { c.typ = ctReconfig c.raw = out + return c.chunkHeader.marshal() } @@ -95,11 +99,12 @@ func (c *chunkReconfig) check() (abort bool, err error) { return true, nil } -// String makes chunkReconfig printable +// String makes chunkReconfig printable. func (c *chunkReconfig) String() string { res := fmt.Sprintf("Param A:\n %s", c.paramA) if c.paramB != nil { res += fmt.Sprintf("Param B:\n %s", c.paramB) } + return res } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_selective_ack.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_selective_ack.go index 28223a920..0fed910f6 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_selective_ack.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_selective_ack.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package sctp import ( @@ -46,14 +49,14 @@ type gapAckBlock struct { end uint16 } -// Selective ack chunk errors +// Selective ack chunk errors. var ( ErrChunkTypeNotSack = errors.New("ChunkType is not of type SACK") ErrSackSizeNotLargeEnoughInfo = errors.New("SACK Chunk size is not large enough to contain header") ErrSackSizeNotMatchPredicted = errors.New("SACK Chunk size does not match predicted amount from header values") ) -// String makes gapAckBlock printable +// String makes gapAckBlock printable. func (g gapAckBlock) String() string { return fmt.Sprintf("%d - %d", g.start, g.end) } @@ -111,8 +114,8 @@ func (s *chunkSelectiveAck) marshal() ([]byte, error) { sackRaw := make([]byte, selectiveAckHeaderSize+(4*len(s.gapAckBlocks)+(4*len(s.duplicateTSN)))) binary.BigEndian.PutUint32(sackRaw[0:], s.cumulativeTSNAck) binary.BigEndian.PutUint32(sackRaw[4:], s.advertisedReceiverWindowCredit) - binary.BigEndian.PutUint16(sackRaw[8:], uint16(len(s.gapAckBlocks))) - binary.BigEndian.PutUint16(sackRaw[10:], uint16(len(s.duplicateTSN))) + binary.BigEndian.PutUint16(sackRaw[8:], uint16(len(s.gapAckBlocks))) //nolint:gosec // G115 + binary.BigEndian.PutUint16(sackRaw[10:], uint16(len(s.duplicateTSN))) //nolint:gosec // G115 offset := selectiveAckHeaderSize for _, g := range s.gapAckBlocks { binary.BigEndian.PutUint16(sackRaw[offset:], g.start) @@ -126,6 +129,7 @@ func (s *chunkSelectiveAck) marshal() ([]byte, error) { s.chunkHeader.typ = ctSack s.chunkHeader.raw = sackRaw + return s.chunkHeader.marshal() } @@ -133,7 +137,7 @@ func (s *chunkSelectiveAck) check() (abort bool, err error) { return false, nil } -// String makes chunkSelectiveAck printable +// String makes chunkSelectiveAck printable. func (s *chunkSelectiveAck) String() string { res := fmt.Sprintf("SACK cumTsnAck=%d arwnd=%d dupTsn=%d", s.cumulativeTSNAck, diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_shutdown.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_shutdown.go index bcd9fc155..7259977a7 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_shutdown.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_shutdown.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package sctp import ( @@ -15,7 +18,7 @@ chunkShutdown represents an SCTP Chunk of type chunkShutdown | Type = 7 | Chunk Flags | Length = 8 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Cumulative TSN Ack | -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+. */ type chunkShutdown struct { chunkHeader @@ -26,7 +29,7 @@ const ( cumulativeTSNAckLength = 4 ) -// Shutdown chunk errors +// Shutdown chunk errors. var ( ErrInvalidChunkSize = errors.New("invalid chunk size") ErrChunkTypeNotShutdown = errors.New("ChunkType is not of type SHUTDOWN") @@ -56,6 +59,7 @@ func (c *chunkShutdown) marshal() ([]byte, error) { c.typ = ctShutdown c.raw = out + return c.chunkHeader.marshal() } @@ -63,7 +67,7 @@ func (c *chunkShutdown) check() (abort bool, err error) { return false, nil } -// String makes chunkShutdown printable +// String makes chunkShutdown printable. func (c *chunkShutdown) String() string { return c.chunkHeader.String() } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_shutdown_ack.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_shutdown_ack.go index a8bb8d0c2..338810038 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_shutdown_ack.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_shutdown_ack.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package sctp import ( @@ -12,13 +15,13 @@ chunkShutdownAck represents an SCTP Chunk of type chunkShutdownAck 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Type = 8 | Chunk Flags | Length = 4 | -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+. */ type chunkShutdownAck struct { chunkHeader } -// Shutdown ack chunk errors +// Shutdown ack chunk errors. var ( ErrChunkTypeNotShutdownAck = errors.New("ChunkType is not of type SHUTDOWN-ACK") ) @@ -37,6 +40,7 @@ func (c *chunkShutdownAck) unmarshal(raw []byte) error { func (c *chunkShutdownAck) marshal() ([]byte, error) { c.typ = ctShutdownAck + return c.chunkHeader.marshal() } @@ -44,7 +48,7 @@ func (c *chunkShutdownAck) check() (abort bool, err error) { return false, nil } -// String makes chunkShutdownAck printable +// String makes chunkShutdownAck printable. func (c *chunkShutdownAck) String() string { return c.chunkHeader.String() } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_shutdown_complete.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_shutdown_complete.go index 4de045d62..dfd7dd6b9 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_shutdown_complete.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunk_shutdown_complete.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package sctp import ( @@ -12,13 +15,13 @@ chunkShutdownComplete represents an SCTP Chunk of type chunkShutdownComplete 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Type = 14 |Reserved |T| Length = 4 | -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+. */ type chunkShutdownComplete struct { chunkHeader } -// Shutdown complete chunk errors +// Shutdown complete chunk errors. var ( ErrChunkTypeNotShutdownComplete = errors.New("ChunkType is not of type SHUTDOWN-COMPLETE") ) @@ -37,6 +40,7 @@ func (c *chunkShutdownComplete) unmarshal(raw []byte) error { func (c *chunkShutdownComplete) marshal() ([]byte, error) { c.typ = ctShutdownComplete + return c.chunkHeader.marshal() } @@ -44,7 +48,7 @@ func (c *chunkShutdownComplete) check() (abort bool, err error) { return false, nil } -// String makes chunkShutdownComplete printable +// String makes chunkShutdownComplete printable. func (c *chunkShutdownComplete) String() string { return c.chunkHeader.String() } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunkheader.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunkheader.go index 6e9a5e9d6..8c5c31295 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunkheader.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunkheader.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package sctp import ( @@ -33,7 +36,7 @@ const ( chunkHeaderSize = 4 ) -// SCTP chunk header errors +// SCTP chunk header errors. var ( ErrChunkHeaderTooSmall = errors.New("raw is too small for a SCTP chunk") ErrChunkHeaderNotEnoughSpace = errors.New("not enough data left in SCTP packet to satisfy requested length") @@ -42,7 +45,10 @@ var ( func (c *chunkHeader) unmarshal(raw []byte) error { if len(raw) < chunkHeaderSize { - return fmt.Errorf("%w: raw only %d bytes, %d is the minimum length", ErrChunkHeaderTooSmall, len(raw), chunkHeaderSize) + return fmt.Errorf( + "%w: raw only %d bytes, %d is the minimum length", + ErrChunkHeaderTooSmall, len(raw), chunkHeaderSize, + ) } c.typ = chunkType(raw[0]) @@ -74,6 +80,7 @@ func (c *chunkHeader) unmarshal(raw []byte) error { } c.raw = raw[chunkHeaderSize : chunkHeaderSize+valueLength] + return nil } @@ -82,8 +89,9 @@ func (c *chunkHeader) marshal() ([]byte, error) { raw[0] = uint8(c.typ) raw[1] = c.flags - binary.BigEndian.PutUint16(raw[2:], uint16(len(c.raw)+chunkHeaderSize)) + binary.BigEndian.PutUint16(raw[2:], uint16(len(c.raw)+chunkHeaderSize)) //nolint:gosec // G115 copy(raw[4:], c.raw) + return raw, nil } @@ -91,7 +99,7 @@ func (c *chunkHeader) valueLength() int { return len(c.raw) } -// String makes chunkHeader printable +// String makes chunkHeader printable. func (c chunkHeader) String() string { return c.typ.String() } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunktype.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunktype.go index 65b57a463..92133f29e 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunktype.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/chunktype.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package sctp import "fmt" @@ -7,7 +10,7 @@ import "fmt" // Chunk Value field. type chunkType uint8 -// List of known chunkType enums +// List of known chunkType enums. const ( ctPayloadData chunkType = 0 ctInit chunkType = 1 @@ -27,7 +30,7 @@ const ( ctForwardTSN chunkType = 192 ) -func (c chunkType) String() string { +func (c chunkType) String() string { //nolint:cyclop switch c { case ctPayloadData: return "DATA" diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/codecov.yml b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/codecov.yml index 085200a48..263e4d45c 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/codecov.yml +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/codecov.yml @@ -3,6 +3,8 @@ # # It is automatically copied from https://github.com/pion/.goassets repository. # +# SPDX-FileCopyrightText: 2023 The Pion community +# SPDX-License-Identifier: MIT coverage: status: diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/control_queue.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/control_queue.go index 7e1346935..20ae995d5 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/control_queue.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/control_queue.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package sctp // control queue @@ -21,6 +24,7 @@ func (q *controlQueue) pushAll(packets []*packet) { func (q *controlQueue) popAll() []*packet { packets := q.queue q.queue = []*packet{} + return packets } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/error_cause.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/error_cause.go index 9e5e68d85..f3cf72f54 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/error_cause.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/error_cause.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package sctp import ( @@ -6,7 +9,7 @@ import ( "fmt" ) -// errorCauseCode is a cause code that appears in either a ERROR or ABORT chunk +// errorCauseCode is a cause code that appears in either a ERROR or ABORT chunk. type errorCauseCode uint16 type errorCause interface { @@ -18,34 +21,34 @@ type errorCause interface { errorCauseCode() errorCauseCode } -// Error and abort chunk errors +// Error and abort chunk errors. var ( ErrBuildErrorCaseHandle = errors.New("BuildErrorCause does not handle") ) -// buildErrorCause delegates the building of a error cause from raw bytes to the correct structure +// buildErrorCause delegates the building of a error cause from raw bytes to the correct structure. func buildErrorCause(raw []byte) (errorCause, error) { - var e errorCause + var errCause errorCause c := errorCauseCode(binary.BigEndian.Uint16(raw[0:])) switch c { case invalidMandatoryParameter: - e = &errorCauseInvalidMandatoryParameter{} + errCause = &errorCauseInvalidMandatoryParameter{} case unrecognizedChunkType: - e = &errorCauseUnrecognizedChunkType{} + errCause = &errorCauseUnrecognizedChunkType{} case protocolViolation: - e = &errorCauseProtocolViolation{} + errCause = &errorCauseProtocolViolation{} case userInitiatedAbort: - e = &errorCauseUserInitiatedAbort{} + errCause = &errorCauseUserInitiatedAbort{} default: return nil, fmt.Errorf("%w: %s", ErrBuildErrorCaseHandle, c.String()) } - if err := e.unmarshal(raw); err != nil { + if err := errCause.unmarshal(raw); err != nil { return nil, err } - return e, nil + return errCause, nil } const ( @@ -64,7 +67,7 @@ const ( protocolViolation errorCauseCode = 13 ) -func (e errorCauseCode) String() string { +func (e errorCauseCode) String() string { //nolint:cyclop switch e { case invalidStreamIdentifier: return "Invalid Stream Identifier" diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/error_cause_header.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/error_cause_header.go index 1ad6e1da4..fd1cd261c 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/error_cause_header.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/error_cause_header.go @@ -1,10 +1,14 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package sctp import ( "encoding/binary" + "errors" ) -// errorCauseHeader represents the shared header that is shared by all error causes +// errorCauseHeader represents the shared header that is shared by all error causes. type errorCauseHeader struct { code errorCauseCode len uint16 @@ -15,8 +19,11 @@ const ( errorCauseHeaderLength = 4 ) +// ErrInvalidSCTPChunk is returned when an SCTP chunk is invalid. +var ErrInvalidSCTPChunk = errors.New("invalid SCTP chunk") + func (e *errorCauseHeader) marshal() ([]byte, error) { - e.len = uint16(len(e.raw)) + uint16(errorCauseHeaderLength) + e.len = uint16(len(e.raw)) + uint16(errorCauseHeaderLength) //nolint:gosec // G115 raw := make([]byte, e.len) binary.BigEndian.PutUint16(raw[0:], uint16(e.code)) binary.BigEndian.PutUint16(raw[2:], e.len) @@ -28,8 +35,12 @@ func (e *errorCauseHeader) marshal() ([]byte, error) { func (e *errorCauseHeader) unmarshal(raw []byte) error { e.code = errorCauseCode(binary.BigEndian.Uint16(raw[0:])) e.len = binary.BigEndian.Uint16(raw[2:]) + if e.len < errorCauseHeaderLength || int(e.len) > len(raw) { + return ErrInvalidSCTPChunk + } valueLength := e.len - errorCauseHeaderLength e.raw = raw[errorCauseHeaderLength : errorCauseHeaderLength+valueLength] + return nil } @@ -41,7 +52,7 @@ func (e *errorCauseHeader) errorCauseCode() errorCauseCode { return e.code } -// String makes errorCauseHeader printable +// String makes errorCauseHeader printable. func (e errorCauseHeader) String() string { return e.code.String() } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/error_cause_invalid_mandatory_parameter.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/error_cause_invalid_mandatory_parameter.go index 3da8b4783..e8615a4ed 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/error_cause_invalid_mandatory_parameter.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/error_cause_invalid_mandatory_parameter.go @@ -1,6 +1,9 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package sctp -// errorCauseInvalidMandatoryParameter represents an SCTP error cause +// errorCauseInvalidMandatoryParameter represents an SCTP error cause. type errorCauseInvalidMandatoryParameter struct { errorCauseHeader } @@ -13,7 +16,7 @@ func (e *errorCauseInvalidMandatoryParameter) unmarshal(raw []byte) error { return e.errorCauseHeader.unmarshal(raw) } -// String makes errorCauseInvalidMandatoryParameter printable +// String makes errorCauseInvalidMandatoryParameter printable. func (e *errorCauseInvalidMandatoryParameter) String() string { return e.errorCauseHeader.String() } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/error_cause_protocol_violation.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/error_cause_protocol_violation.go index 5434e0e3e..4228ac36d 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/error_cause_protocol_violation.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/error_cause_protocol_violation.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package sctp import ( @@ -27,13 +30,14 @@ type errorCauseProtocolViolation struct { additionalInformation []byte } -// Abort chunk errors +// Abort chunk errors. var ( ErrProtocolViolationUnmarshal = errors.New("unable to unmarshal Protocol Violation error") ) func (e *errorCauseProtocolViolation) marshal() ([]byte, error) { e.raw = e.additionalInformation + return e.errorCauseHeader.marshal() } @@ -48,7 +52,7 @@ func (e *errorCauseProtocolViolation) unmarshal(raw []byte) error { return nil } -// String makes errorCauseProtocolViolation printable +// String makes errorCauseProtocolViolation printable. func (e *errorCauseProtocolViolation) String() string { return fmt.Sprintf("%s: %s", e.errorCauseHeader, e.additionalInformation) } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/error_cause_unrecognized_chunk_type.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/error_cause_unrecognized_chunk_type.go index fee9a3603..3a616ae8c 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/error_cause_unrecognized_chunk_type.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/error_cause_unrecognized_chunk_type.go @@ -1,6 +1,9 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package sctp -// errorCauseUnrecognizedChunkType represents an SCTP error cause +// errorCauseUnrecognizedChunkType represents an SCTP error cause. type errorCauseUnrecognizedChunkType struct { errorCauseHeader unrecognizedChunk []byte @@ -9,6 +12,7 @@ type errorCauseUnrecognizedChunkType struct { func (e *errorCauseUnrecognizedChunkType) marshal() ([]byte, error) { e.code = unrecognizedChunkType e.errorCauseHeader.raw = e.unrecognizedChunk + return e.errorCauseHeader.marshal() } @@ -19,10 +23,11 @@ func (e *errorCauseUnrecognizedChunkType) unmarshal(raw []byte) error { } e.unrecognizedChunk = e.errorCauseHeader.raw + return nil } -// String makes errorCauseUnrecognizedChunkType printable +// String makes errorCauseUnrecognizedChunkType printable. func (e *errorCauseUnrecognizedChunkType) String() string { return e.errorCauseHeader.String() } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/error_cause_user_initiated_abort.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/error_cause_user_initiated_abort.go index 1dee93733..57ffd14d4 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/error_cause_user_initiated_abort.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/error_cause_user_initiated_abort.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package sctp import ( @@ -27,6 +30,7 @@ type errorCauseUserInitiatedAbort struct { func (e *errorCauseUserInitiatedAbort) marshal() ([]byte, error) { e.code = userInitiatedAbort e.errorCauseHeader.raw = e.upperLayerAbortReason + return e.errorCauseHeader.marshal() } @@ -37,10 +41,11 @@ func (e *errorCauseUserInitiatedAbort) unmarshal(raw []byte) error { } e.upperLayerAbortReason = e.errorCauseHeader.raw + return nil } -// String makes errorCauseUserInitiatedAbort printable +// String makes errorCauseUserInitiatedAbort printable. func (e *errorCauseUserInitiatedAbort) String() string { return fmt.Sprintf("%s: %s", e.errorCauseHeader.String(), e.upperLayerAbortReason) } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/packet.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/packet.go index 7bc22c82f..1e4ce529c 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/packet.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/packet.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package sctp import ( @@ -7,7 +10,7 @@ import ( "hash/crc32" ) -// Create the crc32 table we'll use for the checksum +// Create the crc32 table we'll use for the checksum. var castagnoliTable = crc32.MakeTable(crc32.Castagnoli) // nolint:gochecknoglobals // Allocate and zero this data once. @@ -54,7 +57,7 @@ const ( packetHeaderSize = 12 ) -// SCTP packet errors +// SCTP packet errors. var ( ErrPacketRawTooSmall = errors.New("raw is smaller than the minimum length for a SCTP packet") ErrParseSCTPChunkNotEnoughData = errors.New("unable to parse SCTP chunk, not enough data for complete header") @@ -62,16 +65,35 @@ var ( ErrChecksumMismatch = errors.New("checksum mismatch theirs") ) -func (p *packet) unmarshal(raw []byte) error { +func (p *packet) unmarshal(doChecksum bool, raw []byte) error { //nolint:cyclop if len(raw) < packetHeaderSize { return fmt.Errorf("%w: raw only %d bytes, %d is the minimum length", ErrPacketRawTooSmall, len(raw), packetHeaderSize) } + offset := packetHeaderSize + + // Check if doing CRC32c is required. + // Without having SCTP AUTH implemented, this depends only on the type + // og the first chunk. + if offset+chunkHeaderSize <= len(raw) { + switch chunkType(raw[offset]) { + case ctInit, ctCookieEcho: + doChecksum = true + default: + } + } + theirChecksum := binary.LittleEndian.Uint32(raw[8:]) + if theirChecksum != 0 || doChecksum { + ourChecksum := generatePacketChecksum(raw) + if theirChecksum != ourChecksum { + return fmt.Errorf("%w: %d ours: %d", ErrChecksumMismatch, theirChecksum, ourChecksum) + } + } + p.sourcePort = binary.BigEndian.Uint16(raw[0:]) p.destinationPort = binary.BigEndian.Uint16(raw[2:]) p.verificationTag = binary.BigEndian.Uint32(raw[4:]) - offset := packetHeaderSize for { // Exact match, no more chunks if offset == len(raw) { @@ -80,57 +102,53 @@ func (p *packet) unmarshal(raw []byte) error { return fmt.Errorf("%w: offset %d remaining %d", ErrParseSCTPChunkNotEnoughData, offset, len(raw)) } - var c chunk + var dataChunk chunk switch chunkType(raw[offset]) { case ctInit: - c = &chunkInit{} + dataChunk = &chunkInit{} case ctInitAck: - c = &chunkInitAck{} + dataChunk = &chunkInitAck{} case ctAbort: - c = &chunkAbort{} + dataChunk = &chunkAbort{} case ctCookieEcho: - c = &chunkCookieEcho{} + dataChunk = &chunkCookieEcho{} case ctCookieAck: - c = &chunkCookieAck{} + dataChunk = &chunkCookieAck{} case ctHeartbeat: - c = &chunkHeartbeat{} + dataChunk = &chunkHeartbeat{} case ctPayloadData: - c = &chunkPayloadData{} + dataChunk = &chunkPayloadData{} case ctSack: - c = &chunkSelectiveAck{} + dataChunk = &chunkSelectiveAck{} case ctReconfig: - c = &chunkReconfig{} + dataChunk = &chunkReconfig{} case ctForwardTSN: - c = &chunkForwardTSN{} + dataChunk = &chunkForwardTSN{} case ctError: - c = &chunkError{} + dataChunk = &chunkError{} case ctShutdown: - c = &chunkShutdown{} + dataChunk = &chunkShutdown{} case ctShutdownAck: - c = &chunkShutdownAck{} + dataChunk = &chunkShutdownAck{} case ctShutdownComplete: - c = &chunkShutdownComplete{} + dataChunk = &chunkShutdownComplete{} default: return fmt.Errorf("%w: %s", ErrUnmarshalUnknownChunkType, chunkType(raw[offset]).String()) } - if err := c.unmarshal(raw[offset:]); err != nil { + if err := dataChunk.unmarshal(raw[offset:]); err != nil { return err } - p.chunks = append(p.chunks, c) - chunkValuePadding := getPadding(c.valueLength()) - offset += chunkHeaderSize + c.valueLength() + chunkValuePadding - } - theirChecksum := binary.LittleEndian.Uint32(raw[8:]) - ourChecksum := generatePacketChecksum(raw) - if theirChecksum != ourChecksum { - return fmt.Errorf("%w: %d ours: %d", ErrChecksumMismatch, theirChecksum, ourChecksum) + p.chunks = append(p.chunks, dataChunk) + chunkValuePadding := getPadding(dataChunk.valueLength()) + offset += chunkHeaderSize + dataChunk.valueLength() + chunkValuePadding } + return nil } -func (p *packet) marshal() ([]byte, error) { +func (p *packet) marshal(doChecksum bool) ([]byte, error) { raw := make([]byte, packetHeaderSize) // Populate static headers @@ -145,17 +163,24 @@ func (p *packet) marshal() ([]byte, error) { if err != nil { return nil, err } - raw = append(raw, chunkRaw...) + raw = append(raw, chunkRaw...) //nolint:makezero // todo:fix paddingNeeded := getPadding(len(raw)) if paddingNeeded != 0 { - raw = append(raw, make([]byte, paddingNeeded)...) + raw = append(raw, make([]byte, paddingNeeded)...) //nolint:makezero // todo:fix } } - // Checksum is already in BigEndian - // Using LittleEndian.PutUint32 stops it from being flipped - binary.LittleEndian.PutUint32(raw[8:], generatePacketChecksum(raw)) + if doChecksum { + // golang CRC32C uses reflected input and reflected output, the + // net result of this is to have the bytes flipped compared to + // the non reflected variant that the spec expects. + // + // Use LittleEndian.PutUint32 to avoid flipping the bytes in to + // the spec compliant checksum order + binary.LittleEndian.PutUint32(raw[8:], generatePacketChecksum(raw)) + } + return raw, nil } @@ -164,10 +189,11 @@ func generatePacketChecksum(raw []byte) (sum uint32) { sum = crc32.Update(sum, castagnoliTable, raw[0:8]) sum = crc32.Update(sum, castagnoliTable, fourZeroes[:]) sum = crc32.Update(sum, castagnoliTable, raw[12:]) + return sum } -// String makes packet printable +// String makes packet printable. func (p *packet) String() string { format := `Packet: sourcePort: %d @@ -182,5 +208,22 @@ func (p *packet) String() string { for i, chunk := range p.chunks { res += fmt.Sprintf("Chunk %d:\n %s", i, chunk) } + return res } + +// TryMarshalUnmarshal attempts to marshal and unmarshal a message. Added for fuzzing. +func TryMarshalUnmarshal(msg []byte) int { + p := &packet{} + err := p.unmarshal(false, msg) + if err != nil { + return 0 + } + + _, err = p.marshal(false) + if err != nil { + return 0 + } + + return 1 +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/param.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/param.go index a23935341..8ac3e484e 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/param.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/param.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package sctp import ( @@ -13,8 +16,8 @@ type param interface { // ErrParamTypeUnhandled is returned if unknown parameter type is specified. var ErrParamTypeUnhandled = errors.New("unhandled ParamType") -func buildParam(t paramType, rawParam []byte) (param, error) { - switch t { +func buildParam(typeParam paramType, rawParam []byte) (param, error) { //nolint:cyclop + switch typeParam { case forwardTSNSupp: return (¶mForwardTSNSupported{}).unmarshal(rawParam) case supportedExt: @@ -35,7 +38,9 @@ func buildParam(t paramType, rawParam []byte) (param, error) { return (¶mOutgoingResetRequest{}).unmarshal(rawParam) case reconfigResp: return (¶mReconfigResponse{}).unmarshal(rawParam) + case zeroChecksumAcceptable: + return (¶mZeroChecksumAcceptable{}).unmarshal(rawParam) default: - return nil, fmt.Errorf("%w: %v", ErrParamTypeUnhandled, t) + return nil, fmt.Errorf("%w: %v", ErrParamTypeUnhandled, typeParam) } } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/param_chunk_list.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/param_chunk_list.go index 4ea484c9f..fe8905208 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/param_chunk_list.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/param_chunk_list.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package sctp type paramChunkList struct { diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/param_ecn_capable.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/param_ecn_capable.go index 7845743fb..65f269a87 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/param_ecn_capable.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/param_ecn_capable.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package sctp type paramECNCapable struct { @@ -7,6 +10,7 @@ type paramECNCapable struct { func (r *paramECNCapable) marshal() ([]byte, error) { r.typ = ecnCapable r.raw = []byte{} + return r.paramHeader.marshal() } @@ -15,5 +19,6 @@ func (r *paramECNCapable) unmarshal(raw []byte) (param, error) { if err != nil { return nil, err } + return r, nil } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/param_forward_tsn_supported.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/param_forward_tsn_supported.go index 62de15570..89ef51aad 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/param_forward_tsn_supported.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/param_forward_tsn_supported.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package sctp // At the initialization of the association, the sender of the INIT or @@ -16,6 +19,7 @@ type paramForwardTSNSupported struct { func (f *paramForwardTSNSupported) marshal() ([]byte, error) { f.typ = forwardTSNSupp f.raw = []byte{} + return f.paramHeader.marshal() } @@ -24,5 +28,6 @@ func (f *paramForwardTSNSupported) unmarshal(raw []byte) (param, error) { if err != nil { return nil, err } + return f, nil } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/param_heartbeat_info.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/param_heartbeat_info.go index 47f64eb87..f7ab5128e 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/param_heartbeat_info.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/param_heartbeat_info.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package sctp type paramHeartbeatInfo struct { @@ -8,6 +11,7 @@ type paramHeartbeatInfo struct { func (h *paramHeartbeatInfo) marshal() ([]byte, error) { h.typ = heartbeatInfo h.raw = h.heartbeatInformation + return h.paramHeader.marshal() } @@ -17,5 +21,6 @@ func (h *paramHeartbeatInfo) unmarshal(raw []byte) (param, error) { return nil, err } h.heartbeatInformation = h.raw + return h, nil } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/param_outgoing_reset_request.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/param_outgoing_reset_request.go index 8ec0bf6cc..7a39b94d0 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/param_outgoing_reset_request.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/param_outgoing_reset_request.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package sctp import ( @@ -52,7 +55,7 @@ type paramOutgoingResetRequest struct { streamIdentifiers []uint16 } -// Outgoing reset request parameter errors +// Outgoing reset request parameter errors. var ( ErrSSNResetRequestParamTooShort = errors.New("outgoing SSN reset request parameter too short") ) @@ -66,6 +69,7 @@ func (r *paramOutgoingResetRequest) marshal() ([]byte, error) { for i, sID := range r.streamIdentifiers { binary.BigEndian.PutUint16(r.raw[paramOutgoingResetRequestStreamIdentifiersOffset+2*i:], sID) } + return r.paramHeader.marshal() } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/param_random.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/param_random.go index dc454b358..a4b68450c 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/param_random.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/param_random.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package sctp type paramRandom struct { @@ -8,6 +11,7 @@ type paramRandom struct { func (r *paramRandom) marshal() ([]byte, error) { r.typ = random r.raw = r.randomData + return r.paramHeader.marshal() } @@ -17,5 +21,6 @@ func (r *paramRandom) unmarshal(raw []byte) (param, error) { return nil, err } r.randomData = r.raw + return r, nil } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/param_reconfig_response.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/param_reconfig_response.go index e3bfab5a4..54e141792 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/param_reconfig_response.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/param_reconfig_response.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package sctp import ( @@ -45,7 +48,7 @@ const ( reconfigResultInProgress reconfigResult = 6 ) -// Reconfiguration response errors +// Reconfiguration response errors. var ( ErrReconfigRespParamTooShort = errors.New("reconfig response parameter too short") ) diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/param_requested_hmac_algorithm.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/param_requested_hmac_algorithm.go index d546af88a..3e98ea714 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/param_requested_hmac_algorithm.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/param_requested_hmac_algorithm.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package sctp import ( @@ -10,7 +13,7 @@ type hmacAlgorithm uint16 const ( hmacResv1 hmacAlgorithm = 0 - hmacSHA128 = 1 + hmacSHA128 hmacAlgorithm = 1 hmacResv2 hmacAlgorithm = 2 hmacSHA256 hmacAlgorithm = 3 ) @@ -18,6 +21,9 @@ const ( // ErrInvalidAlgorithmType is returned if unknown auth algorithm is specified. var ErrInvalidAlgorithmType = errors.New("invalid algorithm type") +// ErrInvalidChunkLength is returned if the chunk length is invalid. +var ErrInvalidChunkLength = errors.New("invalid chunk length") + func (c hmacAlgorithm) String() string { switch c { case hmacResv1: @@ -55,6 +61,9 @@ func (r *paramRequestedHMACAlgorithm) unmarshal(raw []byte) (param, error) { if err != nil { return nil, err } + if len(r.raw)%2 == 1 { + return nil, ErrInvalidChunkLength + } i := 0 for i < len(r.raw) { diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/param_state_cookie.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/param_state_cookie.go index 9681267d5..e7dfb9151 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/param_state_cookie.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/param_state_cookie.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package sctp import ( @@ -28,6 +31,7 @@ func newRandomStateCookie() (*paramStateCookie, error) { func (s *paramStateCookie) marshal() ([]byte, error) { s.typ = stateCookie s.raw = s.cookie + return s.paramHeader.marshal() } @@ -37,10 +41,11 @@ func (s *paramStateCookie) unmarshal(raw []byte) (param, error) { return nil, err } s.cookie = s.raw + return s, nil } -// String makes paramStateCookie printable +// String makes paramStateCookie printable. func (s *paramStateCookie) String() string { return fmt.Sprintf("%s: %s", s.paramHeader, s.cookie) } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/param_supported_extensions.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/param_supported_extensions.go index 2935524ca..0441053a1 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/param_supported_extensions.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/param_supported_extensions.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package sctp type paramSupportedExtensions struct { diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/param_zero_checksum.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/param_zero_checksum.go new file mode 100644 index 000000000..29028926f --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/param_zero_checksum.go @@ -0,0 +1,58 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + +package sctp + +import ( + "encoding/binary" + "errors" +) + +// This parameter is used to inform the receiver that a sender is willing to +// accept zero as checksum if some other error detection method is used +// instead. +// +// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | Type = 0x8001 (suggested) | Length = 8 | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | Error Detection Method Identifier (EDMID) | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +type paramZeroChecksumAcceptable struct { + paramHeader + // The Error Detection Method Identifier (EDMID) specifies an alternate + // error detection method the sender of this parameter is willing to use for + // received packets. + edmid uint32 +} + +// Zero Checksum parameter error. +var ( + ErrZeroChecksumParamTooShort = errors.New("zero checksum parameter too short") +) + +const ( + dtlsErrorDetectionMethod uint32 = 1 +) + +func (r *paramZeroChecksumAcceptable) marshal() ([]byte, error) { + r.typ = zeroChecksumAcceptable + r.raw = make([]byte, 4) + binary.BigEndian.PutUint32(r.raw, r.edmid) + + return r.paramHeader.marshal() +} + +func (r *paramZeroChecksumAcceptable) unmarshal(raw []byte) (param, error) { + err := r.paramHeader.unmarshal(raw) + if err != nil { + return nil, err + } + if len(r.raw) < 4 { + return nil, ErrZeroChecksumParamTooShort + } + r.edmid = binary.BigEndian.Uint32(r.raw) + + return r, nil +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/paramheader.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/paramheader.go index f3cbf74ca..8b1986afd 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/paramheader.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/paramheader.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package sctp import ( @@ -7,17 +10,44 @@ import ( "fmt" ) +type paramHeaderUnrecognizedAction byte + type paramHeader struct { - typ paramType - len int - raw []byte + typ paramType + unrecognizedAction paramHeaderUnrecognizedAction + len int + raw []byte } +/* + The Parameter Types are encoded such that the highest-order 2 bits specify + the action that is taken if the processing endpoint does not recognize the + Parameter Type. + + 00 - Stop processing this parameter and do not process any further parameters within this chunk. + + 01 - Stop processing this parameter, do not process any further parameters within this chunk, and + report the unrecognized parameter, as described in Section 3.2.2. + + 10 - Skip this parameter and continue processing. + + 11 - Skip this parameter and continue processing, but report the unrecognized + parameter, as described in Section 3.2.2. + + https://www.rfc-editor.org/rfc/rfc9260.html#section-3.2.1 +*/ + const ( + paramHeaderUnrecognizedActionMask = 0b11000000 + paramHeaderUnrecognizedActionStop paramHeaderUnrecognizedAction = 0b00000000 + paramHeaderUnrecognizedActionStopAndReport paramHeaderUnrecognizedAction = 0b01000000 + paramHeaderUnrecognizedActionSkip paramHeaderUnrecognizedAction = 0b10000000 + paramHeaderUnrecognizedActionSkipAndReport paramHeaderUnrecognizedAction = 0b11000000 + paramHeaderLength = 4 ) -// Parameter header parse errors +// Parameter header parse errors. var ( ErrParamHeaderTooShort = errors.New("param header too short") ErrParamHeaderSelfReportedLengthShorter = errors.New("param self reported length is shorter than header length") @@ -30,7 +60,7 @@ func (p *paramHeader) marshal() ([]byte, error) { rawParam := make([]byte, paramLengthPlusHeader) binary.BigEndian.PutUint16(rawParam[0:], uint16(p.typ)) - binary.BigEndian.PutUint16(rawParam[2:], uint16(paramLengthPlusHeader)) + binary.BigEndian.PutUint16(rawParam[2:], uint16(paramLengthPlusHeader)) //nolint:gosec // G115 copy(rawParam[paramHeaderLength:], p.raw) return rawParam, nil @@ -43,10 +73,16 @@ func (p *paramHeader) unmarshal(raw []byte) error { paramLengthPlusHeader := binary.BigEndian.Uint16(raw[2:]) if int(paramLengthPlusHeader) < paramHeaderLength { - return fmt.Errorf("%w: param self reported length (%d) shorter than header length (%d)", ErrParamHeaderSelfReportedLengthShorter, int(paramLengthPlusHeader), paramHeaderLength) + return fmt.Errorf( + "%w: param self reported length (%d) shorter than header length (%d)", + ErrParamHeaderSelfReportedLengthShorter, int(paramLengthPlusHeader), paramHeaderLength, + ) } if len(raw) < int(paramLengthPlusHeader) { - return fmt.Errorf("%w: param length (%d) shorter than its self reported length (%d)", ErrParamHeaderSelfReportedLengthLonger, len(raw), int(paramLengthPlusHeader)) + return fmt.Errorf( + "%w: param length (%d) shorter than its self reported length (%d)", + ErrParamHeaderSelfReportedLengthLonger, len(raw), int(paramLengthPlusHeader), + ) } typ, err := parseParamType(raw[0:]) @@ -54,6 +90,7 @@ func (p *paramHeader) unmarshal(raw []byte) error { return fmt.Errorf("%w: %v", ErrParamHeaderParseFailed, err) //nolint:errorlint } p.typ = typ + p.unrecognizedAction = paramHeaderUnrecognizedAction(raw[0] & paramHeaderUnrecognizedActionMask) p.raw = raw[paramHeaderLength:paramLengthPlusHeader] p.len = int(paramLengthPlusHeader) @@ -64,7 +101,7 @@ func (p *paramHeader) length() int { return p.len } -// String makes paramHeader printable +// String makes paramHeader printable. func (p paramHeader) String() string { return fmt.Sprintf("%s (%d): %s", p.typ, p.len, hex.Dump(p.raw)) } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/paramtype.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/paramtype.go index 2db73ddec..c82d2bf71 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/paramtype.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/paramtype.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package sctp import ( @@ -6,40 +9,41 @@ import ( "fmt" ) -// paramType represents a SCTP INIT/INITACK parameter +// paramType represents a SCTP INIT/INITACK parameter. type paramType uint16 const ( - heartbeatInfo paramType = 1 // Heartbeat Info [RFC4960] - ipV4Addr paramType = 5 // IPv4 IP [RFC4960] - ipV6Addr paramType = 6 // IPv6 IP [RFC4960] - stateCookie paramType = 7 // State Cookie [RFC4960] - unrecognizedParam paramType = 8 // Unrecognized Parameters [RFC4960] - cookiePreservative paramType = 9 // Cookie Preservative [RFC4960] - hostNameAddr paramType = 11 // Host Name IP [RFC4960] - supportedAddrTypes paramType = 12 // Supported IP Types [RFC4960] - outSSNResetReq paramType = 13 // Outgoing SSN Reset Request Parameter [RFC6525] - incSSNResetReq paramType = 14 // Incoming SSN Reset Request Parameter [RFC6525] - ssnTSNResetReq paramType = 15 // SSN/TSN Reset Request Parameter [RFC6525] - reconfigResp paramType = 16 // Re-configuration Response Parameter [RFC6525] - addOutStreamsReq paramType = 17 // Add Outgoing Streams Request Parameter [RFC6525] - addIncStreamsReq paramType = 18 // Add Incoming Streams Request Parameter [RFC6525] - ecnCapable paramType = 32768 // ECN Capable (0x8000) [RFC2960] - random paramType = 32770 // Random (0x8002) [RFC4805] - chunkList paramType = 32771 // Chunk List (0x8003) [RFC4895] - reqHMACAlgo paramType = 32772 // Requested HMAC Algorithm Parameter (0x8004) [RFC4895] - padding paramType = 32773 // Padding (0x8005) - supportedExt paramType = 32776 // Supported Extensions (0x8008) [RFC5061] - forwardTSNSupp paramType = 49152 // Forward TSN supported (0xC000) [RFC3758] - addIPAddr paramType = 49153 // Add IP IP (0xC001) [RFC5061] - delIPAddr paramType = 49154 // Delete IP IP (0xC002) [RFC5061] - errClauseInd paramType = 49155 // Error Cause Indication (0xC003) [RFC5061] - setPriAddr paramType = 49156 // Set Primary IP (0xC004) [RFC5061] - successInd paramType = 49157 // Success Indication (0xC005) [RFC5061] - adaptLayerInd paramType = 49158 // Adaptation Layer Indication (0xC006) [RFC5061] + heartbeatInfo paramType = 1 // Heartbeat Info [RFC4960] + ipV4Addr paramType = 5 // IPv4 IP [RFC4960] + ipV6Addr paramType = 6 // IPv6 IP [RFC4960] + stateCookie paramType = 7 // State Cookie [RFC4960] + unrecognizedParam paramType = 8 // Unrecognized Parameters [RFC4960] + cookiePreservative paramType = 9 // Cookie Preservative [RFC4960] + hostNameAddr paramType = 11 // Host Name IP [RFC4960] + supportedAddrTypes paramType = 12 // Supported IP Types [RFC4960] + outSSNResetReq paramType = 13 // Outgoing SSN Reset Request Parameter [RFC6525] + incSSNResetReq paramType = 14 // Incoming SSN Reset Request Parameter [RFC6525] + ssnTSNResetReq paramType = 15 // SSN/TSN Reset Request Parameter [RFC6525] + reconfigResp paramType = 16 // Re-configuration Response Parameter [RFC6525] + addOutStreamsReq paramType = 17 // Add Outgoing Streams Request Parameter [RFC6525] + addIncStreamsReq paramType = 18 // Add Incoming Streams Request Parameter [RFC6525] + ecnCapable paramType = 32768 // ECN Capable (0x8000) [RFC2960] + zeroChecksumAcceptable paramType = 32769 // Zero Checksum Acceptable [draft-ietf-tsvwg-sctp-zero-checksum-00] + random paramType = 32770 // Random (0x8002) [RFC4805] + chunkList paramType = 32771 // Chunk List (0x8003) [RFC4895] + reqHMACAlgo paramType = 32772 // Requested HMAC Algorithm Parameter (0x8004) [RFC4895] + padding paramType = 32773 // Padding (0x8005) + supportedExt paramType = 32776 // Supported Extensions (0x8008) [RFC5061] + forwardTSNSupp paramType = 49152 // Forward TSN supported (0xC000) [RFC3758] + addIPAddr paramType = 49153 // Add IP IP (0xC001) [RFC5061] + delIPAddr paramType = 49154 // Delete IP IP (0xC002) [RFC5061] + errClauseInd paramType = 49155 // Error Cause Indication (0xC003) [RFC5061] + setPriAddr paramType = 49156 // Set Primary IP (0xC004) [RFC5061] + successInd paramType = 49157 // Success Indication (0xC005) [RFC5061] + adaptLayerInd paramType = 49158 // Adaptation Layer Indication (0xC006) [RFC5061] ) -// Parameter packet errors +// Parameter packet errors. var ( ErrParamPacketTooShort = errors.New("packet to short") ) @@ -48,10 +52,11 @@ func parseParamType(raw []byte) (paramType, error) { if len(raw) < 2 { return paramType(0), ErrParamPacketTooShort } + return paramType(binary.BigEndian.Uint16(raw)), nil } -func (p paramType) String() string { +func (p paramType) String() string { //nolint:cyclop switch p { case heartbeatInfo: return "Heartbeat Info" @@ -83,6 +88,8 @@ func (p paramType) String() string { return "Add Incoming Streams Request Parameter" case ecnCapable: return "ECN Capable" + case zeroChecksumAcceptable: + return "Zero Checksum Acceptable" case random: return "Random" case chunkList: diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/payload_queue.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/payload_queue.go index 2d1a35a81..34efdde68 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/payload_queue.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/payload_queue.go @@ -1,80 +1,29 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package sctp -import ( - "fmt" - "sort" -) - type payloadQueue struct { - chunkMap map[uint32]*chunkPayloadData - sorted []uint32 - dupTSN []uint32 - nBytes int + chunks *queue[*chunkPayloadData] + nBytes int } func newPayloadQueue() *payloadQueue { - return &payloadQueue{chunkMap: map[uint32]*chunkPayloadData{}} -} - -func (q *payloadQueue) updateSortedKeys() { - if q.sorted != nil { - return - } - - q.sorted = make([]uint32, len(q.chunkMap)) - i := 0 - for k := range q.chunkMap { - q.sorted[i] = k - i++ - } - - sort.Slice(q.sorted, func(i, j int) bool { - return sna32LT(q.sorted[i], q.sorted[j]) - }) -} - -func (q *payloadQueue) canPush(p *chunkPayloadData, cumulativeTSN uint32) bool { - _, ok := q.chunkMap[p.tsn] - if ok || sna32LTE(p.tsn, cumulativeTSN) { - return false - } - return true + return &payloadQueue{chunks: newQueue[*chunkPayloadData](128)} } func (q *payloadQueue) pushNoCheck(p *chunkPayloadData) { - q.chunkMap[p.tsn] = p + q.chunks.PushBack(p) q.nBytes += len(p.userData) - q.sorted = nil -} - -// push pushes a payload data. If the payload data is already in our queue or -// older than our cumulativeTSN marker, it will be recored as duplications, -// which can later be retrieved using popDuplicates. -func (q *payloadQueue) push(p *chunkPayloadData, cumulativeTSN uint32) bool { - _, ok := q.chunkMap[p.tsn] - if ok || sna32LTE(p.tsn, cumulativeTSN) { - // Found the packet, log in dups - q.dupTSN = append(q.dupTSN, p.tsn) - return false - } - - q.chunkMap[p.tsn] = p - q.nBytes += len(p.userData) - q.sorted = nil - return true } // pop pops only if the oldest chunk's TSN matches the given TSN. func (q *payloadQueue) pop(tsn uint32) (*chunkPayloadData, bool) { - q.updateSortedKeys() + if q.chunks.Len() > 0 && tsn == q.chunks.Front().tsn { + c := q.chunks.PopFront() + q.nBytes -= len(c.userData) - if len(q.chunkMap) > 0 && tsn == q.sorted[0] { - q.sorted = q.sorted[1:] - if c, ok := q.chunkMap[tsn]; ok { - delete(q.chunkMap, tsn) - q.nBytes -= len(c.userData) - return c, true - } + return c, true } return nil, false @@ -82,65 +31,21 @@ func (q *payloadQueue) pop(tsn uint32) (*chunkPayloadData, bool) { // get returns reference to chunkPayloadData with the given TSN value. func (q *payloadQueue) get(tsn uint32) (*chunkPayloadData, bool) { - c, ok := q.chunkMap[tsn] - return c, ok -} - -// popDuplicates returns an array of TSN values that were found duplicate. -func (q *payloadQueue) popDuplicates() []uint32 { - dups := q.dupTSN - q.dupTSN = []uint32{} - return dups -} - -func (q *payloadQueue) getGapAckBlocks(cumulativeTSN uint32) (gapAckBlocks []gapAckBlock) { - var b gapAckBlock - - if len(q.chunkMap) == 0 { - return []gapAckBlock{} + length := q.chunks.Len() + if length == 0 { + return nil, false + } + head := q.chunks.Front().tsn + if tsn < head || int(tsn-head) >= length { + return nil, false } - q.updateSortedKeys() - - for i, tsn := range q.sorted { - if i == 0 { - b.start = uint16(tsn - cumulativeTSN) - b.end = b.start - continue - } - diff := uint16(tsn - cumulativeTSN) - if b.end+1 == diff { - b.end++ - } else { - gapAckBlocks = append(gapAckBlocks, gapAckBlock{ - start: b.start, - end: b.end, - }) - b.start = diff - b.end = diff - } - } - - gapAckBlocks = append(gapAckBlocks, gapAckBlock{ - start: b.start, - end: b.end, - }) - - return gapAckBlocks -} - -func (q *payloadQueue) getGapAckBlocksString(cumulativeTSN uint32) string { - gapAckBlocks := q.getGapAckBlocks(cumulativeTSN) - str := fmt.Sprintf("cumTSN=%d", cumulativeTSN) - for _, b := range gapAckBlocks { - str += fmt.Sprintf(",%d-%d", b.start, b.end) - } - return str + return q.chunks.At(int(tsn - head)), true } func (q *payloadQueue) markAsAcked(tsn uint32) int { var nBytesAcked int - if c, ok := q.chunkMap[tsn]; ok { + if c, ok := q.get(tsn); ok { c.acked = true c.retransmit = false nBytesAcked = len(c.userData) @@ -151,18 +56,9 @@ func (q *payloadQueue) markAsAcked(tsn uint32) int { return nBytesAcked } -func (q *payloadQueue) getLastTSNReceived() (uint32, bool) { - q.updateSortedKeys() - - qlen := len(q.sorted) - if qlen == 0 { - return 0, false - } - return q.sorted[qlen-1], true -} - func (q *payloadQueue) markAllToRetrasmit() { - for _, c := range q.chunkMap { + for i := 0; i < q.chunks.Len(); i++ { + c := q.chunks.At(i) if c.acked || c.abandoned() { continue } @@ -175,5 +71,5 @@ func (q *payloadQueue) getNumBytes() int { } func (q *payloadQueue) size() int { - return len(q.chunkMap) + return q.chunks.Len() } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/pending_queue.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/pending_queue.go index 8082cf52f..a9a1552b4 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/pending_queue.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/pending_queue.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package sctp import ( @@ -24,6 +27,7 @@ func (q *pendingBaseQueue) pop() *chunkPayloadData { } c := q.queue[0] q.queue = q.queue[1:] + return c } @@ -31,6 +35,7 @@ func (q *pendingBaseQueue) get(i int) *chunkPayloadData { if len(q.queue) == 0 || i < 0 || i >= len(q.queue) { return nil } + return q.queue[i] } @@ -48,7 +53,7 @@ type pendingQueue struct { unorderedIsSelected bool } -// Pending queue errors +// Pending queue errors. var ( ErrUnexpectedChuckPoppedUnordered = errors.New("unexpected chunk popped (unordered)") ErrUnexpectedChuckPoppedOrdered = errors.New("unexpected chunk popped (ordered)") @@ -76,26 +81,28 @@ func (q *pendingQueue) peek() *chunkPayloadData { if q.unorderedIsSelected { return q.unorderedQueue.get(0) } + return q.orderedQueue.get(0) } if c := q.unorderedQueue.get(0); c != nil { return c } + return q.orderedQueue.get(0) } -func (q *pendingQueue) pop(c *chunkPayloadData) error { - if q.selected { +func (q *pendingQueue) pop(chunkPayload *chunkPayloadData) error { //nolint:cyclop + if q.selected { //nolint:nestif var popped *chunkPayloadData if q.unorderedIsSelected { popped = q.unorderedQueue.pop() - if popped != c { + if popped != chunkPayload { return ErrUnexpectedChuckPoppedUnordered } } else { popped = q.orderedQueue.pop() - if popped != c { + if popped != chunkPayload { return ErrUnexpectedChuckPoppedOrdered } } @@ -103,12 +110,12 @@ func (q *pendingQueue) pop(c *chunkPayloadData) error { q.selected = false } } else { - if !c.beginningFragment { + if !chunkPayload.beginningFragment { return ErrUnexpectedQState } - if c.unordered { + if chunkPayload.unordered { popped := q.unorderedQueue.pop() - if popped != c { + if popped != chunkPayload { return ErrUnexpectedChuckPoppedUnordered } if !popped.endingFragment { @@ -117,7 +124,7 @@ func (q *pendingQueue) pop(c *chunkPayloadData) error { } } else { popped := q.orderedQueue.pop() - if popped != c { + if popped != chunkPayload { return ErrUnexpectedChuckPoppedOrdered } if !popped.endingFragment { @@ -126,7 +133,8 @@ func (q *pendingQueue) pop(c *chunkPayloadData) error { } } } - q.nBytes -= len(c.userData) + q.nBytes -= len(chunkPayload.userData) + return nil } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/queue.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/queue.go new file mode 100644 index 000000000..1b82edc92 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/queue.go @@ -0,0 +1,75 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + +package sctp + +type queue[T any] struct { + buf []T + head int + tail int + count int +} + +const minCap = 16 + +func newQueue[T any](capacity int) *queue[T] { + queueCap := minCap + for queueCap < capacity { + queueCap <<= 1 + } + + return &queue[T]{ + buf: make([]T, queueCap), + } +} + +func (q *queue[T]) Len() int { + return q.count +} + +func (q *queue[T]) PushBack(ele T) { + q.growIfFull() + q.buf[q.tail] = ele + q.tail = (q.tail + 1) % len(q.buf) + q.count++ +} + +func (q *queue[T]) PopFront() T { + ele := q.buf[q.head] + var zeroVal T + q.buf[q.head] = zeroVal + q.head = (q.head + 1) % len(q.buf) + q.count-- + + return ele +} + +func (q *queue[T]) Front() T { + return q.buf[q.head] +} + +func (q *queue[T]) Back() T { + return q.buf[(q.tail-1+len(q.buf))%len(q.buf)] +} + +func (q *queue[T]) At(i int) T { + return q.buf[(q.head+i)%(len(q.buf))] +} + +func (q *queue[T]) growIfFull() { + if q.count < len(q.buf) { + return + } + + newBuf := make([]T, q.count<<1) + if q.tail > q.head { + copy(newBuf, q.buf[q.head:q.tail]) + } else { + n := copy(newBuf, q.buf[q.head:]) + copy(newBuf[n:], q.buf[:q.tail]) + } + + q.head = 0 + q.tail = q.count + q.buf = newBuf +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/reassembly_queue.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/reassembly_queue.go index d00c046a9..bef4ca5bb 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/reassembly_queue.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/reassembly_queue.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package sctp import ( @@ -19,7 +22,7 @@ func sortChunksBySSN(a []*chunkSet) { }) } -// chunkSet is a set of chunks that share the same SSN +// chunkSet is a set of chunks that share the same SSN. type chunkSet struct { ssn uint16 // used only with the ordered chunks ppi PayloadProtocolIdentifier @@ -48,6 +51,7 @@ func (set *chunkSet) push(chunk *chunkPayloadData) bool { // Check if we now have a complete set complete := set.isComplete() + return complete } @@ -76,7 +80,7 @@ func (set *chunkSet) isComplete() bool { // 3. var lastTSN uint32 - for i, c := range set.chunks { + for i, chunk := range set.chunks { if i > 0 { // Fragments must have contiguous TSN // From RFC 4960 Section 3.3.1: @@ -84,13 +88,13 @@ func (set *chunkSet) isComplete() bool { // used by the receiver to reassemble the message. This means that the // TSNs for each fragment of a fragmented user message MUST be strictly // sequential. - if c.tsn != lastTSN+1 { + if chunk.tsn != lastTSN+1 { // mid or end fragment is missing return false } } - lastTSN = c.tsn + lastTSN = chunk.tsn } return true @@ -121,7 +125,7 @@ func newReassemblyQueue(si uint16) *reassemblyQueue { } } -func (r *reassemblyQueue) push(chunk *chunkPayloadData) bool { +func (r *reassemblyQueue) push(chunk *chunkPayloadData) bool { //nolint:cyclop var cset *chunkSet if chunk.streamIdentifier != r.si { @@ -140,6 +144,7 @@ func (r *reassemblyQueue) push(chunk *chunkPayloadData) bool { // If found, append the complete set to the unordered array if cset != nil { r.unordered = append(r.unordered, cset) + return true } @@ -152,11 +157,23 @@ func (r *reassemblyQueue) push(chunk *chunkPayloadData) bool { return false } - // Check if a chunkSet with the SSN already exists - for _, set := range r.ordered { - if set.ssn == chunk.streamSequenceNumber { - cset = set - break + // Check if a fragmented chunkSet with the fragmented SSN already exists + if chunk.isFragmented() { + for _, set := range r.ordered { + // nolint:godox + // TODO: add caution around SSN wrapping here... this helps only a little bit + // by ensuring we don't add to an unfragmented cset (1 chunk). There's + // a case where if the SSN does wrap around, we may see the same SSN + // for a different chunk. + + // nolint:godox + // TODO: this slice can get pretty big; it may be worth maintaining a map + // for O(1) lookups at the cost of 2x memory. + if set.ssn == chunk.streamSequenceNumber && set.chunks[0].isFragmented() { + cset = set + + break + } } } @@ -180,17 +197,19 @@ func (r *reassemblyQueue) findCompleteUnorderedChunkSet() *chunkSet { var lastTSN uint32 var found bool - for i, c := range r.unorderedChunks { + for i, chunk := range r.unorderedChunks { // seek beigining - if c.beginningFragment { + if chunk.beginningFragment { startIdx = i nChunks = 1 - lastTSN = c.tsn + lastTSN = chunk.tsn - if c.endingFragment { + if chunk.endingFragment { found = true + break } + continue } @@ -199,16 +218,18 @@ func (r *reassemblyQueue) findCompleteUnorderedChunkSet() *chunkSet { } // Check if contiguous in TSN - if c.tsn != lastTSN+1 { + if chunk.tsn != lastTSN+1 { startIdx = -1 + continue } - lastTSN = c.tsn + lastTSN = chunk.tsn nChunks++ - if c.endingFragment { + if chunk.endingFragment { found = true + break } } @@ -247,18 +268,23 @@ func (r *reassemblyQueue) isReadable() bool { } } } + return false } -func (r *reassemblyQueue) read(buf []byte) (int, PayloadProtocolIdentifier, error) { - var cset *chunkSet - // Check unordered first +func (r *reassemblyQueue) read(buf []byte) (int, PayloadProtocolIdentifier, error) { // nolint: cyclop + var ( + cset *chunkSet + isUnordered bool + nTotal int + err error + ) + switch { case len(r.unordered) > 0: cset = r.unordered[0] - r.unordered = r.unordered[1:] + isUnordered = true case len(r.ordered) > 0: - // Now, check ordered cset = r.ordered[0] if !cset.isComplete() { return 0, 0, errTryAgain @@ -266,31 +292,35 @@ func (r *reassemblyQueue) read(buf []byte) (int, PayloadProtocolIdentifier, erro if sna16GT(cset.ssn, r.nextSSN) { return 0, 0, errTryAgain } - r.ordered = r.ordered[1:] - if cset.ssn == r.nextSSN { - r.nextSSN++ - } default: return 0, 0, errTryAgain } - // Concat all fragments into the buffer - nWritten := 0 - ppi := cset.ppi - var err error for _, c := range cset.chunks { - toCopy := len(c.userData) - r.subtractNumBytes(toCopy) - if err == nil { - n := copy(buf[nWritten:], c.userData) - nWritten += n - if n < toCopy { - err = io.ErrShortBuffer - } + if len(buf)-nTotal < len(c.userData) { + err = io.ErrShortBuffer + } else { + copy(buf[nTotal:], c.userData) + } + + nTotal += len(c.userData) + } + + switch { + case err != nil: + return nTotal, 0, err + case isUnordered: + r.unordered = r.unordered[1:] + default: + r.ordered = r.ordered[1:] + if cset.ssn == r.nextSSN { + r.nextSSN++ } } - return nWritten, ppi, err + r.subtractNumBytes(nTotal) + + return nTotal, cset.ppi, err } func (r *reassemblyQueue) forwardTSNForOrdered(lastSSN uint16) { @@ -304,6 +334,7 @@ func (r *reassemblyQueue) forwardTSNForOrdered(lastSSN uint16) { for _, c := range set.chunks { r.subtractNumBytes(len(c.userData)) } + continue } } @@ -340,13 +371,13 @@ func (r *reassemblyQueue) forwardTSNForUnordered(newCumulativeTSN uint32) { func (r *reassemblyQueue) subtractNumBytes(nBytes int) { cur := atomic.LoadUint64(&r.nBytes) - if int(cur) >= nBytes { - atomic.AddUint64(&r.nBytes, -uint64(nBytes)) + if int(cur) >= nBytes { //nolint:gosec // G115 + atomic.AddUint64(&r.nBytes, -uint64(nBytes)) //nolint:gosec // G115 } else { atomic.StoreUint64(&r.nBytes, 0) } } func (r *reassemblyQueue) getNumBytes() int { - return int(atomic.LoadUint64(&r.nBytes)) + return int(atomic.LoadUint64(&r.nBytes)) //nolint:gosec // G115 } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/receive_payload_queue.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/receive_payload_queue.go new file mode 100644 index 000000000..30c9109dc --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/receive_payload_queue.go @@ -0,0 +1,201 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + +package sctp + +import ( + "fmt" + "math/bits" +) + +type receivePayloadQueue struct { + tailTSN uint32 + chunkSize int + tsnBitmask []uint64 + dupTSN []uint32 + maxTSNOffset uint32 + + cumulativeTSN uint32 +} + +func newReceivePayloadQueue(maxTSNOffset uint32) *receivePayloadQueue { + maxTSNOffset = ((maxTSNOffset + 63) / 64) * 64 + + return &receivePayloadQueue{ + tsnBitmask: make([]uint64, maxTSNOffset/64), + maxTSNOffset: maxTSNOffset, + } +} + +func (q *receivePayloadQueue) init(cumulativeTSN uint32) { + q.cumulativeTSN = cumulativeTSN + q.tailTSN = cumulativeTSN + q.chunkSize = 0 + for i := range q.tsnBitmask { + q.tsnBitmask[i] = 0 + } + q.dupTSN = q.dupTSN[:0] +} + +func (q *receivePayloadQueue) hasChunk(tsn uint32) bool { + if q.chunkSize == 0 || sna32LTE(tsn, q.cumulativeTSN) || sna32GT(tsn, q.tailTSN) { + return false + } + + index, offset := int(tsn/64)%len(q.tsnBitmask), tsn%64 + + return q.tsnBitmask[index]&(1<> uint64(start)) //nolint:gosec // G115 + + return i + start, i+start < end +} + +func getFirstZeroBit(val uint64, start, end int) (int, bool) { + return getFirstNonZeroBit(^val, start, end) +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/rtx_timer.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/rtx_timer.go index 14bc39d77..658382492 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/rtx_timer.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/rtx_timer.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package sctp import ( @@ -7,14 +10,28 @@ import ( ) const ( - rtoInitial float64 = 3.0 * 1000 // msec - rtoMin float64 = 1.0 * 1000 // msec - rtoMax float64 = 60.0 * 1000 // msec - rtoAlpha float64 = 0.125 - rtoBeta float64 = 0.25 - maxInitRetrans uint = 8 - pathMaxRetrans uint = 5 - noMaxRetrans uint = 0 + // RTO.Initial in msec. + rtoInitial float64 = 1.0 * 1000 + + // RTO.Min in msec. + rtoMin float64 = 1.0 * 1000 + + // RTO.Max in msec. + defaultRTOMax float64 = 60.0 * 1000 + + // RTO.Alpha. + rtoAlpha float64 = 0.125 + + // RTO.Beta. + rtoBeta float64 = 0.25 + + // Max.Init.Retransmits. + maxInitRetrans uint = 8 + + // Path.Max.Retrans. + pathMaxRetrans uint = 5 + + noMaxRetrans uint = 0 ) // rtoManager manages Rtx timeout values. @@ -25,13 +42,20 @@ type rtoManager struct { rto float64 noUpdate bool mutex sync.RWMutex + rtoMax float64 } // newRTOManager creates a new rtoManager. -func newRTOManager() *rtoManager { - return &rtoManager{ - rto: rtoInitial, +func newRTOManager(rtoMax float64) *rtoManager { + mgr := rtoManager{ + rto: rtoInitial, + rtoMax: rtoMax, } + if mgr.rtoMax == 0 { + mgr.rtoMax = defaultRTOMax + } + + return &mgr } // setNewRTT takes a newly measured RTT then adjust the RTO in msec. @@ -52,7 +76,8 @@ func (m *rtoManager) setNewRTT(rtt float64) float64 { m.rttvar = (1-rtoBeta)*m.rttvar + rtoBeta*(math.Abs(m.srtt-rtt)) m.srtt = (1-rtoAlpha)*m.srtt + rtoAlpha*rtt } - m.rto = math.Min(math.Max(m.srtt+4*m.rttvar, rtoMin), rtoMax) + m.rto = math.Min(math.Max(m.srtt+4*m.rttvar, rtoMin), m.rtoMax) + return m.srtt } @@ -78,7 +103,7 @@ func (m *rtoManager) reset() { m.rto = rtoInitial } -// set RTO value for testing +// set RTO value for testing. func (m *rtoManager) setRTO(rto float64, noUpdate bool) { m.mutex.Lock() defer m.mutex.Unlock() @@ -95,27 +120,68 @@ type rtxTimerObserver interface { onRetransmissionFailure(timerID int) } -// rtxTimer provides the retnransmission timer conforms with RFC 4960 Sec 6.3.1 -type rtxTimer struct { - id int - observer rtxTimerObserver - maxRetrans uint - stopFunc stopTimerLoop - closed bool - mutex sync.RWMutex -} +type rtxTimerState uint8 -type stopTimerLoop func() +const ( + rtxTimerStopped rtxTimerState = iota + rtxTimerStarted + rtxTimerClosed +) + +// rtxTimer provides the retnransmission timer conforms with RFC 4960 Sec 6.3.1. +type rtxTimer struct { + timer *time.Timer + observer rtxTimerObserver + id int + maxRetrans uint + rtoMax float64 + mutex sync.Mutex + rto float64 + nRtos uint + state rtxTimerState + pending uint8 +} // newRTXTimer creates a new retransmission timer. // if maxRetrans is set to 0, it will keep retransmitting until stop() is called. // (it will never make onRetransmissionFailure() callback. -func newRTXTimer(id int, observer rtxTimerObserver, maxRetrans uint) *rtxTimer { - return &rtxTimer{ +func newRTXTimer(id int, observer rtxTimerObserver, maxRetrans uint, + rtoMax float64, +) *rtxTimer { + timer := rtxTimer{ id: id, observer: observer, maxRetrans: maxRetrans, + rtoMax: rtoMax, } + if timer.rtoMax == 0 { + timer.rtoMax = defaultRTOMax + } + timer.timer = time.AfterFunc(math.MaxInt64, timer.timeout) + timer.timer.Stop() + + return &timer +} + +func (t *rtxTimer) calculateNextTimeout() time.Duration { + timeout := calculateNextTimeout(t.rto, t.nRtos, t.rtoMax) + + return time.Duration(timeout) * time.Millisecond +} + +func (t *rtxTimer) timeout() { + t.mutex.Lock() + if t.pending--; t.pending == 0 && t.state == rtxTimerStarted { + if t.nRtos++; t.maxRetrans == 0 || t.nRtos <= t.maxRetrans { + t.timer.Reset(t.calculateNextTimeout()) + t.pending++ + defer t.observer.onRetransmissionTimeout(t.id, t.nRtos) + } else { + t.state = rtxTimerStopped + defer t.observer.onRetransmissionFailure(t.id) + } + } + t.mutex.Unlock() } // start starts the timer. @@ -123,13 +189,8 @@ func (t *rtxTimer) start(rto float64) bool { t.mutex.Lock() defer t.mutex.Unlock() - // this timer is already closed - if t.closed { - return false - } - - // this is a noop if the timer is always running - if t.stopFunc != nil { + // this timer is already closed or aleady running + if t.state != rtxTimerStopped { return false } @@ -137,36 +198,11 @@ func (t *rtxTimer) start(rto float64) bool { // fast timeout for the tests. Non-test code should pass in the // rto generated by rtoManager getRTO() method which caps the // value at RTO.Min or at RTO.Max. - var nRtos uint - - cancelCh := make(chan struct{}) - - go func() { - canceling := false - - for !canceling { - timeout := calculateNextTimeout(rto, nRtos) - timer := time.NewTimer(time.Duration(timeout) * time.Millisecond) - - select { - case <-timer.C: - nRtos++ - if t.maxRetrans == 0 || nRtos <= t.maxRetrans { - t.observer.onRetransmissionTimeout(t.id, nRtos) - } else { - t.stop() - t.observer.onRetransmissionFailure(t.id) - } - case <-cancelCh: - canceling = true - timer.Stop() - } - } - }() - - t.stopFunc = func() { - close(cancelCh) - } + t.rto = rto + t.nRtos = 0 + t.state = rtxTimerStarted + t.pending++ + t.timer.Reset(t.calculateNextTimeout()) return true } @@ -176,36 +212,36 @@ func (t *rtxTimer) stop() { t.mutex.Lock() defer t.mutex.Unlock() - if t.stopFunc != nil { - t.stopFunc() - t.stopFunc = nil + if t.state == rtxTimerStarted { + if t.timer.Stop() { + t.pending-- + } + t.state = rtxTimerStopped } } // closes the timer. this is similar to stop() but subsequent start() call -// will fail (the timer is no longer usable) +// will fail (the timer is no longer usable). func (t *rtxTimer) close() { t.mutex.Lock() defer t.mutex.Unlock() - if t.stopFunc != nil { - t.stopFunc() - t.stopFunc = nil + if t.state == rtxTimerStarted && t.timer.Stop() { + t.pending-- } - - t.closed = true + t.state = rtxTimerClosed } // isRunning tests if the timer is running. -// Debug purpose only +// Debug purpose only. func (t *rtxTimer) isRunning() bool { - t.mutex.RLock() - defer t.mutex.RUnlock() + t.mutex.Lock() + defer t.mutex.Unlock() - return (t.stopFunc != nil) + return t.state == rtxTimerStarted } -func calculateNextTimeout(rto float64, nRtos uint) float64 { +func calculateNextTimeout(rto float64, nRtos uint, rtoMax float64) float64 { // RFC 4096 sec 6.3.3. Handle T3-rtx Expiration // E2) For the destination address for which the timer expires, set RTO // <- RTO * 2 ("back off the timer"). The maximum value discussed @@ -213,7 +249,9 @@ func calculateNextTimeout(rto float64, nRtos uint) float64 { // to this doubling operation. if nRtos < 31 { m := 1 << nRtos + return math.Min(rto*float64(m), rtoMax) } + return rtoMax } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/sctp.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/sctp.go index e60134293..2bf74fb38 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/sctp.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/sctp.go @@ -1,2 +1,5 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + // Package sctp implements the SCTP spec package sctp diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/stream.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/stream.go index 43038ee1e..3a05f6379 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/stream.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/stream.go @@ -1,24 +1,27 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package sctp import ( "errors" "fmt" "io" - "math" "os" "sync" "sync/atomic" "time" "github.com/pion/logging" + "github.com/pion/transport/v3/deadline" ) const ( - // ReliabilityTypeReliable is used for reliable transmission + // ReliabilityTypeReliable is used for reliable transmission. ReliabilityTypeReliable byte = 0 - // ReliabilityTypeRexmit is used for partial reliability by retransmission count + // ReliabilityTypeRexmit is used for partial reliability by retransmission count. ReliabilityTypeRexmit byte = 1 - // ReliabilityTypeTimed is used for partial reliability by retransmission duration + // ReliabilityTypeTimed is used for partial reliability by retransmission duration. ReliabilityTypeTimed byte = 2 ) @@ -26,7 +29,7 @@ const ( // This field identifies the state of stream. type StreamState int -// StreamState enums +// StreamState enums. const ( StreamStateOpen StreamState = iota // Stream object starts with StreamStateOpen StreamStateClosing // Outgoing stream is being reset @@ -42,17 +45,18 @@ func (ss StreamState) String() string { case StreamStateClosed: return "closed" } + return "unknown" } -// SCTP stream errors +// SCTP stream errors. var ( ErrOutboundPacketTooLarge = errors.New("outbound packet larger than maximum message size") ErrStreamClosed = errors.New("stream closed") ErrReadDeadlineExceeded = fmt.Errorf("read deadline exceeded: %w", os.ErrDeadlineExceeded) ) -// Stream represents an SCTP stream +// Stream represents an SCTP stream. type Stream struct { association *Association lock sync.RWMutex @@ -63,6 +67,8 @@ type Stream struct { readNotifier *sync.Cond readErr error readTimeoutCancel chan struct{} + writeDeadline *deadline.Deadline + writeLock sync.Mutex unordered bool reliabilityType byte reliabilityValue uint32 @@ -78,6 +84,7 @@ type Stream struct { func (s *Stream) StreamIdentifier() uint16 { s.lock.RLock() defer s.lock.RUnlock() + return s.streamIdentifier } @@ -109,14 +116,15 @@ func (s *Stream) setReliabilityParams(unordered bool, relType byte, relVal uint3 // otherwise. func (s *Stream) Read(p []byte) (int, error) { n, _, err := s.ReadSCTP(p) + return n, err } -// ReadSCTP reads a packet of len(p) bytes and returns the associated Payload +// ReadSCTP reads a packet of len(payload) bytes and returns the associated Payload // Protocol Identifier. // Returns EOF when the stream is reset or an error if the stream is closed // otherwise. -func (s *Stream) ReadSCTP(p []byte) (int, PayloadProtocolIdentifier, error) { +func (s *Stream) ReadSCTP(payload []byte) (int, PayloadProtocolIdentifier, error) { s.lock.Lock() defer s.lock.Unlock() @@ -129,23 +137,20 @@ func (s *Stream) ReadSCTP(p []byte) (int, PayloadProtocolIdentifier, error) { }() for { - n, ppi, err := s.reassemblyQueue.read(p) - if err == nil { - return n, ppi, nil - } else if errors.Is(err, io.ErrShortBuffer) { - return 0, PayloadProtocolIdentifier(0), err + n, ppi, err := s.reassemblyQueue.read(payload) + if err == nil || errors.Is(err, io.ErrShortBuffer) { + return n, ppi, err } - err = s.readErr - if err != nil { - return 0, PayloadProtocolIdentifier(0), err + if s.readErr != nil { + return 0, PayloadProtocolIdentifier(0), s.readErr } s.readNotifier.Wait() } } -// SetReadDeadline sets the read deadline in an identical way to net.Conn +// SetReadDeadline sets the read deadline in an identical way to net.Conn. func (s *Stream) SetReadDeadline(deadline time.Time) error { s.lock.Lock() defer s.lock.Unlock() @@ -170,8 +175,14 @@ func (s *Stream) SetReadDeadline(deadline time.Time) error { select { case <-readTimeoutCancel: t.Stop() + return case <-t.C: + select { + case <-readTimeoutCancel: + return + default: + } s.lock.Lock() if s.readErr == nil { s.readErr = ErrReadDeadlineExceeded @@ -183,6 +194,7 @@ func (s *Stream) SetReadDeadline(deadline time.Time) error { } }(s.readTimeoutCancel) } + return nil } @@ -248,38 +260,72 @@ func (s *Stream) handleForwardTSNForUnordered(newCumulativeTSN uint32) { } } -// Write writes len(p) bytes from p with the default Payload Protocol Identifier -func (s *Stream) Write(p []byte) (n int, err error) { +// Write writes len(payload) bytes from payload with the default Payload Protocol Identifier. +func (s *Stream) Write(payload []byte) (n int, err error) { ppi := PayloadProtocolIdentifier(atomic.LoadUint32((*uint32)(&s.defaultPayloadType))) - return s.WriteSCTP(p, ppi) + + return s.WriteSCTP(payload, ppi) } -// WriteSCTP writes len(p) bytes from p to the DTLS connection -func (s *Stream) WriteSCTP(p []byte, ppi PayloadProtocolIdentifier) (int, error) { +// WriteSCTP writes len(payload) bytes from payload to the DTLS connection. +func (s *Stream) WriteSCTP(payload []byte, ppi PayloadProtocolIdentifier) (int, error) { maxMessageSize := s.association.MaxMessageSize() - if len(p) > int(maxMessageSize) { - return 0, fmt.Errorf("%w: %v", ErrOutboundPacketTooLarge, math.MaxUint16) + if len(payload) > int(maxMessageSize) { + return 0, fmt.Errorf("%w: %v", ErrOutboundPacketTooLarge, maxMessageSize) } if s.State() != StreamStateOpen { return 0, ErrStreamClosed } - chunks := s.packetize(p, ppi) - n := len(p) - err := s.association.sendPayloadData(chunks) - if err != nil { - return n, ErrStreamClosed + // the send could fail if the association is blocked for writing (timeout), it will left a hole + // in the stream sequence number space, so we need to lock the write to avoid concurrent send and decrement + // the sequence number in case of failure + if s.association.isBlockWrite() { + s.writeLock.Lock() } - return n, nil + chunks, unordered := s.packetize(payload, ppi) + n := len(payload) + err := s.association.sendPayloadData(s.writeDeadline, chunks) + if err != nil { + s.lock.Lock() + s.bufferedAmount -= uint64(n) + if !unordered { + s.sequenceNumber-- + } + s.lock.Unlock() + n = 0 + } + if s.association.isBlockWrite() { + s.writeLock.Unlock() + } + + return n, err } -func (s *Stream) packetize(raw []byte, ppi PayloadProtocolIdentifier) []*chunkPayloadData { +// SetWriteDeadline sets the write deadline in an identical way to net.Conn, +// it will only work for blocking writes. +func (s *Stream) SetWriteDeadline(deadline time.Time) error { + s.writeDeadline.Set(deadline) + + return nil +} + +// SetDeadline sets the read and write deadlines in an identical way to net.Conn. +func (s *Stream) SetDeadline(t time.Time) error { + if err := s.SetReadDeadline(t); err != nil { + return err + } + + return s.SetWriteDeadline(t) +} + +func (s *Stream) packetize(raw []byte, ppi PayloadProtocolIdentifier) ([]*chunkPayloadData, bool) { s.lock.Lock() defer s.lock.Unlock() - i := uint32(0) - remaining := uint32(len(raw)) + offset := uint32(0) + remaining := uint32(len(raw)) //nolint:gosec // G115 // From draft-ietf-rtcweb-data-protocol-09, section 6: // All Data Channel Establishment Protocol messages MUST be sent using @@ -294,13 +340,13 @@ func (s *Stream) packetize(raw []byte, ppi PayloadProtocolIdentifier) []*chunkPa // Copy the userdata since we'll have to store it until acked // and the caller may re-use the buffer in the mean time userData := make([]byte, fragmentSize) - copy(userData, raw[i:i+fragmentSize]) + copy(userData, raw[offset:offset+fragmentSize]) chunk := &chunkPayloadData{ streamIdentifier: s.streamIdentifier, userData: userData, unordered: unordered, - beginningFragment: i == 0, + beginningFragment: offset == 0, endingFragment: remaining-fragmentSize == 0, immediateSack: false, payloadType: ppi, @@ -315,7 +361,7 @@ func (s *Stream) packetize(raw []byte, ppi PayloadProtocolIdentifier) []*chunkPa chunks = append(chunks, chunk) remaining -= fragmentSize - i += fragmentSize + offset += fragmentSize } // RFC 4960 Sec 6.6 @@ -329,7 +375,7 @@ func (s *Stream) packetize(raw []byte, ppi PayloadProtocolIdentifier) []*chunkPa s.bufferedAmount += uint64(len(raw)) s.log.Tracef("[%s] bufferedAmount = %d", s.name, s.bufferedAmount) - return chunks + return chunks, unordered } // Close closes the write-direction of the stream. @@ -348,8 +394,10 @@ func (s *Stream) Close() error { s.state = StreamStateClosed } s.log.Debugf("[%s] state change: open => %s", s.name, s.state.String()) + return s.streamIdentifier, true } + return s.streamIdentifier, false }(); resetOutbound { // Reset the outgoing stream @@ -420,6 +468,7 @@ func (s *Stream) onBufferReleased(nBytesReleased int) { f := s.onBufferedAmountLow s.lock.Unlock() f() + return } @@ -460,5 +509,6 @@ func (s *Stream) onInboundStreamReset() { func (s *Stream) State() StreamState { s.lock.RLock() defer s.lock.RUnlock() + return s.state } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/util.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/util.go index 9302e7126..257e289aa 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/util.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sctp/util.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package sctp const ( @@ -13,10 +16,11 @@ func padByte(in []byte, cnt int) []byte { cnt = 0 } padding := make([]byte, cnt) + return append(in, padding...) } -// Serial Number Arithmetic (RFC 1982) +// Serial Number Arithmetic (RFC 1982). func sna32LT(i1, i2 uint32) bool { return (i1 < i2 && i2-i1 < 1<<31) || (i1 > i2 && i1-i2 > 1<<31) } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/.gitignore b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/.gitignore index f977e7485..6e2f206a9 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/.gitignore +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/.gitignore @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2023 The Pion community +# SPDX-License-Identifier: MIT + ### JetBrains IDE ### ##################### .idea/ diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/.golangci.yml b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/.golangci.yml index d7a88eca3..88cb4fbf9 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/.golangci.yml +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/.golangci.yml @@ -1,6 +1,13 @@ +# SPDX-FileCopyrightText: 2023 The Pion community +# SPDX-License-Identifier: MIT + +run: + timeout: 5m + linters-settings: govet: - check-shadowing: true + enable: + - shadow misspell: locale: US exhaustive: @@ -10,41 +17,61 @@ linters-settings: modules: - github.com/pkg/errors: recommendations: - - errors + - errors + forbidigo: + forbid: + - ^fmt.Print(f|ln)?$ + - ^log.(Panic|Fatal|Print)(f|ln)?$ + - ^os.Exit$ + - ^panic$ + - ^print(ln)?$ + varnamelen: + max-distance: 12 + min-name-length: 2 + ignore-type-assert-ok: true + ignore-map-index-ok: true + ignore-chan-recv-ok: true + ignore-decls: + - i int + - n int + - w io.Writer + - r io.Reader + - b []byte linters: enable: - asciicheck # Simple linter to check that your code does not contain non-ASCII identifiers - bidichk # Checks for dangerous unicode character sequences - bodyclose # checks whether HTTP response body is closed successfully + - containedctx # containedctx is a linter that detects struct contained context.Context field - contextcheck # check the function whether use a non-inherited context - - deadcode # Finds unused code + - cyclop # checks function and package cyclomatic complexity - decorder # check declaration order and count of types, constants, variables and functions - - depguard # Go linter that checks if package imports are in a list of acceptable packages - dogsled # Checks assignments with too many blank identifiers (e.g. x, _, _, _, := f()) - dupl # Tool for code clone detection - durationcheck # check for two durations multiplied together + - err113 # Golang linter to check the errors handling expressions - errcheck # Errcheck is a program for checking for unchecked errors in go programs. These unchecked errors can be critical bugs in some cases - errchkjson # Checks types passed to the json encoding functions. Reports unsupported types and optionally reports occations, where the check for the returned error can be omitted. - errname # Checks that sentinel errors are prefixed with the `Err` and error types are suffixed with the `Error`. - errorlint # errorlint is a linter for that can be used to find code that will cause problems with the error wrapping scheme introduced in Go 1.13. - exhaustive # check exhaustiveness of enum switch statements - exportloopref # checks for pointers to enclosing loop variables + - forbidigo # Forbids identifiers - forcetypeassert # finds forced type assertions - gci # Gci control golang package import order and make it always deterministic. - gochecknoglobals # Checks that no globals are present in Go code - - gochecknoinits # Checks that no init functions are present in Go code - gocognit # Computes and checks the cognitive complexity of functions - goconst # Finds repeated strings that could be replaced by a constant - gocritic # The most opinionated Go source code linter + - gocyclo # Computes and checks the cyclomatic complexity of functions + - godot # Check if comments end in a period - godox # Tool for detection of FIXME, TODO and other comment keywords - - goerr113 # Golang linter to check the errors handling expressions - gofmt # Gofmt checks whether code was gofmt-ed. By default this tool runs with -s option to check for code simplification - gofumpt # Gofumpt checks whether code was gofumpt-ed. - goheader # Checks is file header matches to pattern - goimports # Goimports does everything that gofmt does. Additionally it checks unused imports - gomoddirectives # Manage the use of 'replace', 'retract', and 'excludes' directives in go.mod. - - gomodguard # Allow and block list linter for direct Go module dependencies. This is different from depguard where there are different block types for example version constraints and module recommendations. - goprintffuncname # Checks that printf-like functions are named with `f` at the end - gosec # Inspects source code for security problems - gosimple # Linter for Go source code that specializes in simplifying a code @@ -52,43 +79,38 @@ linters: - grouper # An analyzer to analyze expression groups. - importas # Enforces consistent import aliases - ineffassign # Detects when assignments to existing variables are not used + - lll # Reports long lines + - maintidx # maintidx measures the maintainability index of each function. + - makezero # Finds slice declarations with non-zero initial length - misspell # Finds commonly misspelled English words in comments - nakedret # Finds naked returns in functions greater than a specified function length + - nestif # Reports deeply nested if statements - nilerr # Finds the code that returns nil even if it checks that the error is not nil. - nilnil # Checks that there is no simultaneous return of `nil` error and an invalid value. + - nlreturn # nlreturn checks for a new line before return and branch statements to increase code clarity - noctx # noctx finds sending http request without context.Context - predeclared # find code that shadows one of Go's predeclared identifiers - revive # golint replacement, finds style mistakes - staticcheck # Staticcheck is a go vet on steroids, applying a ton of static analysis checks - - structcheck # Finds unused struct fields - stylecheck # Stylecheck is a replacement for golint - tagliatelle # Checks the struct tags. - tenv # tenv is analyzer that detects using os.Setenv instead of t.Setenv since Go1.17 - - tparallel # tparallel detects inappropriate usage of t.Parallel() method in your Go test codes + - thelper # thelper detects golang test helpers without t.Helper() call and checks the consistency of test helpers - typecheck # Like the front-end of a Go compiler, parses and type-checks Go code - unconvert # Remove unnecessary type conversions - unparam # Reports unused function parameters - unused # Checks Go code for unused constants, variables, functions and types - - varcheck # Finds unused global variables and constants + - varnamelen # checks that the length of a variable's name matches its scope - wastedassign # wastedassign finds wasted assignment statements - whitespace # Tool for detection of leading and trailing whitespace disable: - - containedctx # containedctx is a linter that detects struct contained context.Context field - - cyclop # checks function and package cyclomatic complexity - - exhaustivestruct # Checks if all struct's fields are initialized - - forbidigo # Forbids identifiers + - depguard # Go linter that checks if package imports are in a list of acceptable packages - funlen # Tool for detection of long functions - - gocyclo # Computes and checks the cyclomatic complexity of functions - - godot # Check if comments end in a period - - gomnd # An analyzer to detect magic numbers. - - ifshort # Checks that your code uses short syntax for if-statements whenever possible + - gochecknoinits # Checks that no init functions are present in Go code + - gomodguard # Allow and block list linter for direct Go module dependencies. This is different from depguard where there are different block types for example version constraints and module recommendations. + - interfacebloat # A linter that checks length of interface. - ireturn # Accept Interfaces, Return Concrete Types - - lll # Reports long lines - - maintidx # maintidx measures the maintainability index of each function. - - makezero # Finds slice declarations with non-zero initial length - - maligned # Tool to detect Go structs that would take less memory if their fields were sorted - - nestif # Reports deeply nested if statements - - nlreturn # nlreturn checks for a new line before return and branch statements to increase code clarity + - mnd # An analyzer to detect magic numbers - nolintlint # Reports ill-formed or insufficient nolint directives - paralleltest # paralleltest detects missing usage of t.Parallel() method in your Go test - prealloc # Finds slice declarations that could potentially be preallocated @@ -96,24 +118,21 @@ linters: - rowserrcheck # checks whether Err of rows is checked successfully - sqlclosecheck # Checks that sql.Rows and sql.Stmt are closed. - testpackage # linter that makes you use a separate _test package - - thelper # thelper detects golang test helpers without t.Helper() call and checks the consistency of test helpers - - varnamelen # checks that the length of a variable's name matches its scope + - tparallel # tparallel detects inappropriate usage of t.Parallel() method in your Go test codes - wrapcheck # Checks that errors returned from external packages are wrapped - wsl # Whitespace Linter - Forces you to use empty lines! issues: exclude-use-default: false + exclude-dirs-use-default: false exclude-rules: - # Allow complex tests, better to be self contained - - path: _test\.go + # Allow complex tests and examples, better to be self contained + - path: (examples|main\.go|_test\.go) linters: + - forbidigo - gocognit - # Allow complex main function in examples - - path: examples - text: "of func `main` is high" + # Allow forbidden identifiers in CLI commands + - path: cmd linters: - - gocognit - -run: - skip-dirs-use-default: false + - forbidigo diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/.goreleaser.yml b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/.goreleaser.yml new file mode 100644 index 000000000..30093e9d6 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/.goreleaser.yml @@ -0,0 +1,5 @@ +# SPDX-FileCopyrightText: 2023 The Pion community +# SPDX-License-Identifier: MIT + +builds: +- skip: true diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/AUTHORS.txt b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/AUTHORS.txt deleted file mode 100644 index 038e59911..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/AUTHORS.txt +++ /dev/null @@ -1,32 +0,0 @@ -# Thank you to everyone that made Pion possible. If you are interested in contributing -# we would love to have you https://github.com/pion/webrtc/wiki/Contributing -# -# This file is auto generated, using git to list all individuals contributors. -# see `.github/generate-authors.sh` for the scripting -adwpc -Atsushi Watanabe -backkem -Brendan Abolivier -chenkaiC4 -cnderrauber -Daniele Sluijters -Graham King -Guilherme -Hugo Arregui -Jason -Jerko Steiner -John Bradley -Konstantin Itskov -korymiller1489 -Luke S -Max Hawkins -Maxim Oransky -mchlrhw <4028654+mchlrhw@users.noreply.github.com> -Michael MacDonald -Mustafa Navruz -Roman Romanenko -Sean DuBois -Sean DuBois -tarrencev -Woodrow Douglass -ZHENK diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/LICENSE b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/LICENSE index ab602974d..491caf6b0 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/LICENSE +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/LICENSE @@ -1,21 +1,9 @@ MIT License -Copyright (c) 2018 +Copyright (c) 2023 The Pion community -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/README.md b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/README.md index c29c97f78..1cb8dbd21 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/README.md +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/README.md @@ -9,27 +9,27 @@ Sourcegraph Widget Slack Widget
- Build Status - GoDoc + GitHub Workflow Status + Go Reference Coverage Status Go Report Card License: MIT


- ### Roadmap The library is used as a part of our WebRTC implementation. Please refer to that [roadmap](https://github.com/pion/webrtc/issues/9) to track our major milestones. ### Community -Pion has an active community on the [Golang Slack](https://invite.slack.golangbridge.org/). Sign up and join the **#pion** channel for discussions and support. You can also use [Pion mailing list](https://groups.google.com/forum/#!forum/pion). +Pion has an active community on the [Slack](https://pion.ly/slack). + +Follow the [Pion Twitter](https://twitter.com/_pion) for project updates and important WebRTC news. We are always looking to support **your projects**. Please reach out if you have something to build! - If you need commercial support or don't want to use public methods you can contact us at [team@pion.ly](mailto:team@pion.ly) ### Contributing -Check out the **[contributing wiki](https://github.com/pion/webrtc/wiki/Contributing)** to join the group of amazing people making this project possible: +Check out the [contributing wiki](https://github.com/pion/webrtc/wiki/Contributing) to join the group of amazing people making this project possible ### License -MIT License - see [LICENSE](LICENSE) for full text +MIT License - see [LICENSE](LICENSE) for full text \ No newline at end of file diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/base_lexer.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/base_lexer.go index f1f2ccd1a..4cd9dc5ba 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/base_lexer.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/base_lexer.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package sdp import ( @@ -18,16 +21,17 @@ func (e syntaxError) Error() string { if e.i < 0 { e.i = 0 } + return fmt.Sprintf("sdp: syntax error at pos %d: %s", e.i, strconv.QuoteToASCII(e.s[e.i:e.i+1])) } type baseLexer struct { - value []byte + value string pos int } func (l baseLexer) syntaxError() error { - return syntaxError{s: string(l.value), i: l.pos - 1} + return syntaxError{s: l.value, i: l.pos - 1} } func (l *baseLexer) unreadByte() error { @@ -35,6 +39,7 @@ func (l *baseLexer) unreadByte() error { return errDocumentStart } l.pos-- + return nil } @@ -44,6 +49,7 @@ func (l *baseLexer) readByte() (byte, error) { } ch := l.value[l.pos] l.pos++ + return ch, nil } @@ -61,7 +67,7 @@ func (l *baseLexer) nextLine() error { } } -func (l *baseLexer) readWhitespace() error { +func (l *baseLexer) readWhitespace() error { //notlint:cyclop for { ch, err := l.readByte() if errors.Is(err, io.EOF) { @@ -75,7 +81,7 @@ func (l *baseLexer) readWhitespace() error { } } -func (l *baseLexer) readUint64Field() (i uint64, err error) { +func (l *baseLexer) readUint64Field() (i uint64, err error) { //nolint:cyclop for { ch, err := l.readByte() if errors.Is(err, io.EOF) && i > 0 { @@ -88,6 +94,7 @@ func (l *baseLexer) readUint64Field() (i uint64, err error) { if err := l.unreadByte(); err != nil { return i, err } + break } @@ -95,6 +102,7 @@ func (l *baseLexer) readUint64Field() (i uint64, err error) { if err := l.readWhitespace(); err != nil { return i, err } + break } @@ -127,7 +135,7 @@ func (l *baseLexer) readUint64Field() (i uint64, err error) { return i, nil } -// Returns next field on this line or empty string if no more fields on line +// Returns next field on this line or empty string if no more fields on line. func (l *baseLexer) readField() (string, error) { start := l.pos var stop int @@ -144,6 +152,7 @@ func (l *baseLexer) readField() (string, error) { if err := l.unreadByte(); err != nil { return "", err } + break } @@ -151,13 +160,15 @@ func (l *baseLexer) readField() (string, error) { if err := l.readWhitespace(); err != nil { return "", err } + break } } - return string(l.value[start:stop]), nil + + return l.value[start:stop], nil } -// Returns symbols until line end +// Returns symbols until line end. func (l *baseLexer) readLine() (string, error) { start := l.pos trim := 1 @@ -170,50 +181,32 @@ func (l *baseLexer) readLine() (string, error) { trim++ } if ch == '\n' { - return string(l.value[start : l.pos-trim]), nil + return l.value[start : l.pos-trim], nil } } } -func (l *baseLexer) readString(until byte) (string, error) { - start := l.pos +func (l *baseLexer) readType() (byte, error) { for { - ch, err := l.readByte() + firstByte, err := l.readByte() if err != nil { - return "", err - } - if ch == until { - return string(l.value[start:l.pos]), nil - } - } -} - -func (l *baseLexer) readType() (string, error) { - for { - b, err := l.readByte() - if err != nil { - return "", err + return 0, err } - if isNewline(b) { + if isNewline(firstByte) { continue } - err = l.unreadByte() + secondByte, err := l.readByte() if err != nil { - return "", err + return 0, err } - key, err := l.readString('=') - if err != nil { - return key, err + if secondByte != '=' { + return firstByte, l.syntaxError() } - if len(key) == 2 { - return key, nil - } - - return key, l.syntaxError() + return firstByte, nil } } @@ -227,5 +220,6 @@ func anyOf(element string, data ...string) bool { return true } } + return false } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/codecov.yml b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/codecov.yml index 085200a48..263e4d45c 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/codecov.yml +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/codecov.yml @@ -3,6 +3,8 @@ # # It is automatically copied from https://github.com/pion/.goassets repository. # +# SPDX-FileCopyrightText: 2023 The Pion community +# SPDX-License-Identifier: MIT coverage: status: diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/common_description.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/common_description.go index 1174be416..6d678cebe 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/common_description.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/common_description.go @@ -1,8 +1,10 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package sdp import ( "strconv" - "strings" ) // Information describes the "i=" field which provides textual information @@ -10,7 +12,15 @@ import ( type Information string func (i Information) String() string { - return string(i) + return stringFromMarshal(i.marshalInto, i.marshalSize) +} + +func (i Information) marshalInto(b []byte) []byte { + return append(b, i...) +} + +func (i Information) marshalSize() (size int) { + return len(i) } // ConnectionInformation defines the representation for the "c=" field @@ -22,11 +32,29 @@ type ConnectionInformation struct { } func (c ConnectionInformation) String() string { - parts := []string{c.NetworkType, c.AddressType} - if c.Address != nil && c.Address.String() != "" { - parts = append(parts, c.Address.String()) + return stringFromMarshal(c.marshalInto, c.marshalSize) +} + +func (c ConnectionInformation) marshalInto(b []byte) []byte { + b = append(append(b, c.NetworkType...), ' ') + b = append(b, c.AddressType...) + + if c.Address != nil { + b = append(b, ' ') + b = c.Address.marshalInto(b) } - return strings.Join(parts, " ") + + return b +} + +func (c ConnectionInformation) marshalSize() (size int) { + size = len(c.NetworkType) + size += 1 + len(c.AddressType) + if c.Address != nil { + size += 1 + c.Address.marshalSize() + } + + return } // Address desribes a structured address token from within the "c=" field. @@ -37,17 +65,33 @@ type Address struct { } func (c *Address) String() string { - var parts []string - parts = append(parts, c.Address) + return stringFromMarshal(c.marshalInto, c.marshalSize) +} + +func (c *Address) marshalInto(b []byte) []byte { + b = append(b, c.Address...) if c.TTL != nil { - parts = append(parts, strconv.Itoa(*c.TTL)) + b = append(b, '/') + b = strconv.AppendInt(b, int64(*c.TTL), 10) } - if c.Range != nil { - parts = append(parts, strconv.Itoa(*c.Range)) + b = append(b, '/') + b = strconv.AppendInt(b, int64(*c.Range), 10) } - return strings.Join(parts, "/") + return b +} + +func (c Address) marshalSize() (size int) { + size = len(c.Address) + if c.TTL != nil { + size += 1 + lenUint(uint64(*c.TTL)) //nolint:gosec // G115 + } + if c.Range != nil { + size += 1 + lenUint(uint64(*c.Range)) //nolint:gosec // G115 + } + + return } // Bandwidth describes an optional field which denotes the proposed bandwidth @@ -59,19 +103,41 @@ type Bandwidth struct { } func (b Bandwidth) String() string { - var output string + return stringFromMarshal(b.marshalInto, b.marshalSize) +} + +func (b Bandwidth) marshalInto(d []byte) []byte { if b.Experimental { - output += "X-" + d = append(d, "X-"...) } - output += b.Type + ":" + strconv.FormatUint(b.Bandwidth, 10) - return output + d = append(append(d, b.Type...), ':') + + return strconv.AppendUint(d, b.Bandwidth, 10) +} + +func (b Bandwidth) marshalSize() (size int) { + if b.Experimental { + size += 2 + } + + size += len(b.Type) + 1 + lenUint(b.Bandwidth) + + return } // EncryptionKey describes the "k=" which conveys encryption key information. type EncryptionKey string -func (s EncryptionKey) String() string { - return string(s) +func (e EncryptionKey) String() string { + return stringFromMarshal(e.marshalInto, e.marshalSize) +} + +func (e EncryptionKey) marshalInto(b []byte) []byte { + return append(b, e...) +} + +func (e EncryptionKey) marshalSize() (size int) { + return len(e) } // Attribute describes the "a=" field which represents the primary means for @@ -81,14 +147,14 @@ type Attribute struct { Value string } -// NewPropertyAttribute constructs a new attribute +// NewPropertyAttribute constructs a new attribute. func NewPropertyAttribute(key string) Attribute { return Attribute{ Key: key, } } -// NewAttribute constructs a new attribute +// NewAttribute constructs a new attribute. func NewAttribute(key, value string) Attribute { return Attribute{ Key: key, @@ -97,11 +163,25 @@ func NewAttribute(key, value string) Attribute { } func (a Attribute) String() string { - output := a.Key + return stringFromMarshal(a.marshalInto, a.marshalSize) +} + +func (a Attribute) marshalInto(b []byte) []byte { + b = append(b, a.Key...) if len(a.Value) > 0 { - output += ":" + a.Value + b = append(append(b, ':'), a.Value...) } - return output + + return b +} + +func (a Attribute) marshalSize() (size int) { + size = len(a.Key) + if len(a.Value) > 0 { + size += 1 + len(a.Value) + } + + return size } // IsICECandidate returns true if the attribute key equals "candidate". diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/direction.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/direction.go index 19ea92db7..8cc97bf81 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/direction.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/direction.go @@ -1,18 +1,21 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package sdp import "errors" -// Direction is a marker for transmission directon of an endpoint +// Direction is a marker for transmission directon of an endpoint. type Direction int const ( - // DirectionSendRecv is for bidirectional communication + // DirectionSendRecv is for bidirectional communication. DirectionSendRecv Direction = iota + 1 - // DirectionSendOnly is for outgoing communication + // DirectionSendOnly is for outgoing communication. DirectionSendOnly - // DirectionRecvOnly is for incoming communication + // DirectionRecvOnly is for incoming communication. DirectionRecvOnly - // DirectionInactive is for no communication + // DirectionInactive is for no communication. DirectionInactive ) diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/extmap.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/extmap.go index 1242a8cf0..0114b569b 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/extmap.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/extmap.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package sdp import ( @@ -7,21 +10,22 @@ import ( "strings" ) -// Default ext values +// Default ext values. const ( DefExtMapValueABSSendTime = 1 DefExtMapValueTransportCC = 2 DefExtMapValueSDESMid = 3 DefExtMapValueSDESRTPStreamID = 4 - ABSSendTimeURI = "http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time" - TransportCCURI = "http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01" - SDESMidURI = "urn:ietf:params:rtp-hdrext:sdes:mid" - SDESRTPStreamIDURI = "urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id" - AudioLevelURI = "urn:ietf:params:rtp-hdrext:ssrc-audio-level" + ABSSendTimeURI = "http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time" + TransportCCURI = "http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01" + SDESMidURI = "urn:ietf:params:rtp-hdrext:sdes:mid" + SDESRTPStreamIDURI = "urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id" + SDESRepairRTPStreamIDURI = "urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id" + AudioLevelURI = "urn:ietf:params:rtp-hdrext:ssrc-audio-level" ) -// ExtMap represents the activation of a single RTP header extension +// ExtMap represents the activation of a single RTP header extension. type ExtMap struct { Value int Direction Direction @@ -29,12 +33,12 @@ type ExtMap struct { ExtAttr *string } -// Clone converts this object to an Attribute +// Clone converts this object to an Attribute. func (e *ExtMap) Clone() Attribute { return Attribute{Key: "extmap", Value: e.string()} } -// Unmarshal creates an Extmap from a string +// Unmarshal creates an Extmap from a string. func (e *ExtMap) Unmarshal(raw string) error { parts := strings.SplitN(raw, ":", 2) if len(parts) != 2 { @@ -76,10 +80,11 @@ func (e *ExtMap) Unmarshal(raw string) error { e.Value = int(value) e.Direction = direction e.URI = uri + return nil } -// Marshal creates a string from an ExtMap +// Marshal creates a string from an ExtMap. func (e *ExtMap) Marshal() string { return e.Name() + ":" + e.string() } @@ -102,7 +107,7 @@ func (e *ExtMap) string() string { return output } -// Name returns the constant name of this object +// Name returns the constant name of this object. func (e *ExtMap) Name() string { return "extmap" } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/fuzz.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/fuzz.go deleted file mode 100644 index f41ef78c6..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/fuzz.go +++ /dev/null @@ -1,31 +0,0 @@ -// +build gofuzz - -package sdp - -// Fuzz implements a randomized fuzz test of the sdp -// parser using go-fuzz. -// -// To run the fuzzer, first download go-fuzz: -// `go get github.com/dvyukov/go-fuzz/...` -// -// Then build the testing package: -// `go-fuzz-build` -// -// And run the fuzzer on the corpus: -// `go-fuzz` -func Fuzz(data []byte) int { - // Check that unmarshalling any byte slice does not panic. - var sd SessionDescription - if err := sd.Unmarshal(data); err != nil { - return 0 - } - // Check that we can marshal anything we unmarshalled. - _, err := sd.Marshal() - if err != nil { - panic("failed to marshal") // nolint - } - // It'd be nice to check that if we round trip Marshal then Unmarshal, - // we get the original back. Right now, though, we frequently don't, - // and we'd need to fix that first. - return 1 -} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/jsep.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/jsep.go index de07d8f30..388a13e9e 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/jsep.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/jsep.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package sdp import ( @@ -7,7 +10,7 @@ import ( "time" ) -// Constants for SDP attributes used in JSEP +// Constants for SDP attributes used in JSEP. const ( AttrKeyCandidate = "candidate" AttrKeyEndOfCandidates = "end-of-candidates" @@ -30,7 +33,7 @@ const ( AttrKeyExtMapAllowMixed = "extmap-allow-mixed" ) -// Constants for semantic tokens used in JSEP +// Constants for semantic tokens used in JSEP. const ( SemanticTokenLipSynchronization = "LS" SemanticTokenFlowIdentification = "FID" @@ -38,7 +41,7 @@ const ( SemanticTokenWebRTCMediaStreams = "WMS" ) -// Constants for extmap key +// Constants for extmap key. const ( ExtMapValueTransportCC = 3 ) @@ -56,19 +59,20 @@ func extMapURI() map[int]string { // some settings that are required by the JSEP spec. // // Note: Since v2.4.0, session ID has been fixed to use crypto random according to -// JSEP spec, so that NewJSEPSessionDescription now returns error as a second -// return value. +// +// JSEP spec, so that NewJSEPSessionDescription now returns error as a second +// return value. func NewJSEPSessionDescription(identity bool) (*SessionDescription, error) { sid, err := newSessionID() if err != nil { return nil, err } - d := &SessionDescription{ + descr := &SessionDescription{ Version: 0, Origin: Origin{ Username: "-", SessionID: sid, - SessionVersion: uint64(time.Now().Unix()), + SessionVersion: uint64(time.Now().Unix()), //nolint:gosec // G115 NetworkType: "IN", AddressType: "IP4", UnicastAddress: "0.0.0.0", @@ -89,38 +93,41 @@ func NewJSEPSessionDescription(identity bool) (*SessionDescription, error) { } if identity { - d.WithPropertyAttribute(AttrKeyIdentity) + descr.WithPropertyAttribute(AttrKeyIdentity) } - return d, nil + return descr, nil } -// WithPropertyAttribute adds a property attribute 'a=key' to the session description +// WithPropertyAttribute adds a property attribute 'a=key' to the session description. func (s *SessionDescription) WithPropertyAttribute(key string) *SessionDescription { s.Attributes = append(s.Attributes, NewPropertyAttribute(key)) + return s } -// WithValueAttribute adds a value attribute 'a=key:value' to the session description +// WithValueAttribute adds a value attribute 'a=key:value' to the session description. func (s *SessionDescription) WithValueAttribute(key, value string) *SessionDescription { s.Attributes = append(s.Attributes, NewAttribute(key, value)) + return s } -// WithFingerprint adds a fingerprint to the session description +// WithFingerprint adds a fingerprint to the session description. func (s *SessionDescription) WithFingerprint(algorithm, value string) *SessionDescription { return s.WithValueAttribute("fingerprint", algorithm+" "+value) } -// WithMedia adds a media description to the session description +// WithMedia adds a media description to the session description. func (s *SessionDescription) WithMedia(md *MediaDescription) *SessionDescription { s.MediaDescriptions = append(s.MediaDescriptions, md) + return s } // NewJSEPMediaDescription creates a new MediaName with // some settings that are required by the JSEP spec. -func NewJSEPMediaDescription(codecType string, codecPrefs []string) *MediaDescription { +func NewJSEPMediaDescription(codecType string, _ []string) *MediaDescription { return &MediaDescription{ MediaName: MediaName{ Media: codecType, @@ -137,32 +144,40 @@ func NewJSEPMediaDescription(codecType string, codecPrefs []string) *MediaDescri } } -// WithPropertyAttribute adds a property attribute 'a=key' to the media description +// WithPropertyAttribute adds a property attribute 'a=key' to the media description. func (d *MediaDescription) WithPropertyAttribute(key string) *MediaDescription { d.Attributes = append(d.Attributes, NewPropertyAttribute(key)) + return d } -// WithValueAttribute adds a value attribute 'a=key:value' to the media description +// WithValueAttribute adds a value attribute 'a=key:value' to the media description. func (d *MediaDescription) WithValueAttribute(key, value string) *MediaDescription { d.Attributes = append(d.Attributes, NewAttribute(key, value)) + return d } -// WithFingerprint adds a fingerprint to the media description +// WithFingerprint adds a fingerprint to the media description. func (d *MediaDescription) WithFingerprint(algorithm, value string) *MediaDescription { return d.WithValueAttribute("fingerprint", algorithm+" "+value) } -// WithICECredentials adds ICE credentials to the media description +// WithICECredentials adds ICE credentials to the media description. func (d *MediaDescription) WithICECredentials(username, password string) *MediaDescription { return d. WithValueAttribute("ice-ufrag", username). WithValueAttribute("ice-pwd", password) } -// WithCodec adds codec information to the media description -func (d *MediaDescription) WithCodec(payloadType uint8, name string, clockrate uint32, channels uint16, fmtp string) *MediaDescription { +// WithCodec adds codec information to the media description. +func (d *MediaDescription) WithCodec( + payloadType uint8, + name string, + clockrate uint32, + channels uint16, + fmtp string, +) *MediaDescription { d.MediaName.Formats = append(d.MediaName.Formats, strconv.Itoa(int(payloadType))) rtpmap := fmt.Sprintf("%d %s/%d", payloadType, name, clockrate) if channels > 0 { @@ -172,10 +187,11 @@ func (d *MediaDescription) WithCodec(payloadType uint8, name string, clockrate u if fmtp != "" { d.WithValueAttribute("fmtp", fmt.Sprintf("%d %s", payloadType, fmtp)) } + return d } -// WithMediaSource adds media source information to the media description +// WithMediaSource adds media source information to the media description. func (d *MediaDescription) WithMediaSource(ssrc uint32, cname, streamLabel, label string) *MediaDescription { return d. WithValueAttribute("ssrc", fmt.Sprintf("%d cname:%s", ssrc, cname)). // Deprecated but not phased out? @@ -184,23 +200,24 @@ func (d *MediaDescription) WithMediaSource(ssrc uint32, cname, streamLabel, labe WithValueAttribute("ssrc", fmt.Sprintf("%d label:%s", ssrc, label)) // Deprecated but not phased out? } -// WithCandidate adds an ICE candidate to the media description -// Deprecated: use WithICECandidate instead +// WithCandidate adds an ICE candidate to the media description. +// Deprecated: use WithICECandidate instead. func (d *MediaDescription) WithCandidate(value string) *MediaDescription { return d.WithValueAttribute("candidate", value) } -// WithExtMap adds an extmap to the media description +// WithExtMap adds an extmap to the media description. func (d *MediaDescription) WithExtMap(e ExtMap) *MediaDescription { return d.WithPropertyAttribute(e.Marshal()) } -// WithTransportCCExtMap adds an extmap to the media description +// WithTransportCCExtMap adds an extmap to the media description. func (d *MediaDescription) WithTransportCCExtMap() *MediaDescription { uri, _ := url.Parse(extMapURI()[ExtMapValueTransportCC]) e := ExtMap{ Value: ExtMapValueTransportCC, URI: uri, } + return d.WithExtMap(e) } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/marshal.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/marshal.go index f029c4e99..81b6aa122 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/marshal.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/marshal.go @@ -1,136 +1,242 @@ -package sdp +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT -import ( - "strings" -) +package sdp // Marshal takes a SDP struct to text // https://tools.ietf.org/html/rfc4566#section-5 // Session description -// v= (protocol version) -// o= (originator and session identifier) -// s= (session name) -// i=* (session information) -// u=* (URI of description) -// e=* (email address) -// p=* (phone number) -// c=* (connection information -- not required if included in -// all media) -// b=* (zero or more bandwidth information lines) -// One or more time descriptions ("t=" and "r=" lines; see below) -// z=* (time zone adjustments) -// k=* (encryption key) -// a=* (zero or more session attribute lines) -// Zero or more media descriptions +// +// v= (protocol version) +// o= (originator and session identifier) +// s= (session name) +// i=* (session information) +// u=* (URI of description) +// e=* (email address) +// p=* (phone number) +// c=* (connection information -- not required if included in +// all media) +// b=* (zero or more bandwidth information lines) +// One or more time descriptions ("t=" and "r=" lines; see below) +// z=* (time zone adjustments) +// k=* (encryption key) +// a=* (zero or more session attribute lines) +// Zero or more media descriptions // // Time description -// t= (time the session is active) -// r=* (zero or more repeat times) +// +// t= (time the session is active) +// r=* (zero or more repeat times) // // Media description, if present -// m= (media name and transport address) -// i=* (media title) -// c=* (connection information -- optional if included at -// session level) -// b=* (zero or more bandwidth information lines) -// k=* (encryption key) -// a=* (zero or more media attribute lines) -func (s *SessionDescription) Marshal() ([]byte, error) { - m := make(marshaller, 0, 1024) +// +// m= (media name and transport address) +// i=* (media title) +// c=* (connection information -- optional if included at +// session level) +// b=* (zero or more bandwidth information lines) +// k=* (encryption key) +// a=* (zero or more media attribute lines) +func (s *SessionDescription) Marshal() ([]byte, error) { //nolint:cyclop + marsh := make(marshaller, 0, s.MarshalSize()) - m.addKeyValue("v=", s.Version.String()) - m.addKeyValue("o=", s.Origin.String()) - m.addKeyValue("s=", s.SessionName.String()) + marsh.addKeyValue("v=", s.Version.marshalInto) + marsh.addKeyValue("o=", s.Origin.marshalInto) + marsh.addKeyValue("s=", s.SessionName.marshalInto) if s.SessionInformation != nil { - m.addKeyValue("i=", s.SessionInformation.String()) + marsh.addKeyValue("i=", s.SessionInformation.marshalInto) } if s.URI != nil { - m.addKeyValue("u=", s.URI.String()) + marsh = append(marsh, "u="...) + marsh = append(marsh, s.URI.String()...) + marsh = append(marsh, "\r\n"...) } if s.EmailAddress != nil { - m.addKeyValue("e=", s.EmailAddress.String()) + marsh.addKeyValue("e=", s.EmailAddress.marshalInto) } if s.PhoneNumber != nil { - m.addKeyValue("p=", s.PhoneNumber.String()) + marsh.addKeyValue("p=", s.PhoneNumber.marshalInto) } if s.ConnectionInformation != nil { - m.addKeyValue("c=", s.ConnectionInformation.String()) + marsh.addKeyValue("c=", s.ConnectionInformation.marshalInto) } for _, b := range s.Bandwidth { - m.addKeyValue("b=", b.String()) + marsh.addKeyValue("b=", b.marshalInto) } for _, td := range s.TimeDescriptions { - m.addKeyValue("t=", td.Timing.String()) + marsh.addKeyValue("t=", td.Timing.marshalInto) for _, r := range td.RepeatTimes { - m.addKeyValue("r=", r.String()) + marsh.addKeyValue("r=", r.marshalInto) } } if len(s.TimeZones) > 0 { - var b strings.Builder + marsh = append(marsh, "z="...) for i, z := range s.TimeZones { if i > 0 { - b.WriteString(" ") + marsh = append(marsh, ' ') } - b.WriteString(z.String()) + marsh = z.marshalInto(marsh) } - m.addKeyValue("z=", b.String()) + marsh = append(marsh, "\r\n"...) } if s.EncryptionKey != nil { - m.addKeyValue("k=", s.EncryptionKey.String()) + marsh.addKeyValue("k=", s.EncryptionKey.marshalInto) } for _, a := range s.Attributes { - m.addKeyValue("a=", a.String()) + marsh.addKeyValue("a=", a.marshalInto) } for _, md := range s.MediaDescriptions { - m.addKeyValue("m=", md.MediaName.String()) + marsh.addKeyValue("m=", md.MediaName.marshalInto) if md.MediaTitle != nil { - m.addKeyValue("i=", md.MediaTitle.String()) + marsh.addKeyValue("i=", md.MediaTitle.marshalInto) } if md.ConnectionInformation != nil { - m.addKeyValue("c=", md.ConnectionInformation.String()) + marsh.addKeyValue("c=", md.ConnectionInformation.marshalInto) } for _, b := range md.Bandwidth { - m.addKeyValue("b=", b.String()) + marsh.addKeyValue("b=", b.marshalInto) } if md.EncryptionKey != nil { - m.addKeyValue("k=", md.EncryptionKey.String()) + marsh.addKeyValue("k=", md.EncryptionKey.marshalInto) } for _, a := range md.Attributes { - m.addKeyValue("a=", a.String()) + marsh.addKeyValue("a=", a.marshalInto) } } - return m.bytes(), nil + return marsh, nil +} + +// `$type=` and CRLF size. +const lineBaseSize = 4 + +// MarshalSize returns the size of the SessionDescription once marshaled. +func (s *SessionDescription) MarshalSize() (marshalSize int) { //nolint:cyclop + marshalSize += lineBaseSize + s.Version.marshalSize() + marshalSize += lineBaseSize + s.Origin.marshalSize() + marshalSize += lineBaseSize + s.SessionName.marshalSize() + + if s.SessionInformation != nil { + marshalSize += lineBaseSize + s.SessionInformation.marshalSize() + } + + if s.URI != nil { + marshalSize += lineBaseSize + len(s.URI.String()) + } + + if s.EmailAddress != nil { + marshalSize += lineBaseSize + s.EmailAddress.marshalSize() + } + + if s.PhoneNumber != nil { + marshalSize += lineBaseSize + s.PhoneNumber.marshalSize() + } + + if s.ConnectionInformation != nil { + marshalSize += lineBaseSize + s.ConnectionInformation.marshalSize() + } + + for _, b := range s.Bandwidth { + marshalSize += lineBaseSize + b.marshalSize() + } + + for _, td := range s.TimeDescriptions { + marshalSize += lineBaseSize + td.Timing.marshalSize() + for _, r := range td.RepeatTimes { + marshalSize += lineBaseSize + r.marshalSize() + } + } + + if len(s.TimeZones) > 0 { + marshalSize += lineBaseSize + + for i, z := range s.TimeZones { + if i > 0 { + marshalSize++ + } + marshalSize += z.marshalSize() + } + } + + if s.EncryptionKey != nil { + marshalSize += lineBaseSize + s.EncryptionKey.marshalSize() + } + + for _, a := range s.Attributes { + marshalSize += lineBaseSize + a.marshalSize() + } + + for _, md := range s.MediaDescriptions { + marshalSize += lineBaseSize + md.MediaName.marshalSize() + if md.MediaTitle != nil { + marshalSize += lineBaseSize + md.MediaTitle.marshalSize() + } + if md.ConnectionInformation != nil { + marshalSize += lineBaseSize + md.ConnectionInformation.marshalSize() + } + + for _, b := range md.Bandwidth { + marshalSize += lineBaseSize + b.marshalSize() + } + + if md.EncryptionKey != nil { + marshalSize += lineBaseSize + md.EncryptionKey.marshalSize() + } + + for _, a := range md.Attributes { + marshalSize += lineBaseSize + a.marshalSize() + } + } + + return marshalSize } // marshaller contains state during marshaling. type marshaller []byte -func (m *marshaller) addKeyValue(key, value string) { - if value == "" { - return - } +func (m *marshaller) addKeyValue(key string, value func([]byte) []byte) { *m = append(*m, key...) - *m = append(*m, value...) + *m = value(*m) *m = append(*m, "\r\n"...) } -func (m *marshaller) bytes() []byte { - return *m +func lenUint(i uint64) (count int) { + if i == 0 { + return 1 + } + + for i != 0 { + i /= 10 + count++ + } + + return +} + +func lenInt(i int64) (count int) { + if i < 0 { + return lenUint(uint64(-i)) + 1 + } + + return lenUint(uint64(i)) +} + +func stringFromMarshal(marshalFunc func([]byte) []byte, sizeFunc func() int) string { + return string(marshalFunc(make([]byte, 0, sizeFunc()))) } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/media_description.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/media_description.go index c08850704..e3071151b 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/media_description.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/media_description.go @@ -1,8 +1,10 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package sdp import ( "strconv" - "strings" ) // MediaDescription represents a media type. @@ -35,13 +37,14 @@ type MediaDescription struct { Attributes []Attribute } -// Attribute returns the value of an attribute and if it exists +// Attribute returns the value of an attribute and if it exists. func (d *MediaDescription) Attribute(key string) (string, bool) { for _, a := range d.Attributes { if a.Key == key { return a.Value, true } } + return "", false } @@ -59,9 +62,29 @@ func (p *RangedPort) String() string { if p.Range != nil { output += "/" + strconv.Itoa(*p.Range) } + return output } +func (p RangedPort) marshalInto(b []byte) []byte { + b = strconv.AppendInt(b, int64(p.Value), 10) + if p.Range != nil { + b = append(b, '/') + b = strconv.AppendInt(b, int64(*p.Range), 10) + } + + return b +} + +func (p RangedPort) marshalSize() (size int) { + size = lenInt(int64(p.Value)) + if p.Range != nil { + size += 1 + lenInt(int64(*p.Range)) + } + + return +} + // MediaName describes the "m=" field storage structure. type MediaName struct { Media string @@ -71,10 +94,39 @@ type MediaName struct { } func (m MediaName) String() string { - return strings.Join([]string{ - m.Media, - m.Port.String(), - strings.Join(m.Protos, "/"), - strings.Join(m.Formats, " "), - }, " ") + return stringFromMarshal(m.marshalInto, m.marshalSize) +} + +func (m MediaName) marshalInto(b []byte) []byte { + appendList := func(list []string, sep byte) { + for i, p := range list { + if i != 0 && i != len(list) { + b = append(b, sep) + } + b = append(b, p...) + } + } + + b = append(append(b, m.Media...), ' ') + b = append(m.Port.marshalInto(b), ' ') + appendList(m.Protos, '/') + b = append(b, ' ') + appendList(m.Formats, ' ') + + return b +} + +func (m MediaName) marshalSize() (size int) { + listSize := func(list []string) { + for _, p := range list { + size += 1 + len(p) + } + } + + size = len(m.Media) + size += 1 + m.Port.marshalSize() + listSize(m.Protos) + listSize(m.Formats) + + return size } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/renovate.json b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/renovate.json index f1614058a..f1bb98c6a 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/renovate.json +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/renovate.json @@ -1,27 +1,6 @@ { + "$schema": "https://docs.renovatebot.com/renovate-schema.json", "extends": [ - "config:base", - ":disableDependencyDashboard" - ], - "postUpdateOptions": [ - "gomodTidy" - ], - "commitBody": "Generated by renovateBot", - "packageRules": [ - { - "matchUpdateTypes": ["minor", "patch", "pin", "digest"], - "automerge": true - }, - { - "packagePatterns": ["^golang.org/x/"], - "schedule": ["on the first day of the month"] - } - ], - "ignorePaths": [ - ".github/workflows/generate-authors.yml", - ".github/workflows/lint.yaml", - ".github/workflows/renovate-go-mod-fix.yaml", - ".github/workflows/test.yaml", - ".github/workflows/tidy-check.yaml" + "github>pion/renovate-config" ] } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/sdp.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/sdp.go index c92ac1a7f..a13e838f1 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/sdp.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/sdp.go @@ -1,2 +1,5 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + // Package sdp implements Session Description Protocol (SDP) package sdp diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/session_description.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/session_description.go index c4aaf5f95..dee37a452 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/session_description.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/session_description.go @@ -1,7 +1,9 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package sdp import ( - "fmt" "net/url" "strconv" ) @@ -67,13 +69,14 @@ type SessionDescription struct { MediaDescriptions []*MediaDescription } -// Attribute returns the value of an attribute and if it exists +// Attribute returns the value of an attribute and if it exists. func (s *SessionDescription) Attribute(key string) (string, bool) { for _, a := range s.Attributes { if a.Key == key { return a.Value, true } } + return "", false } @@ -82,7 +85,15 @@ func (s *SessionDescription) Attribute(key string) (string, bool) { type Version int func (v Version) String() string { - return strconv.Itoa(int(v)) + return stringFromMarshal(v.marshalInto, v.marshalSize) +} + +func (v Version) marshalInto(b []byte) []byte { + return strconv.AppendInt(b, int64(v), 10) +} + +func (v Version) marshalSize() (size int) { + return lenInt(int64(v)) } // Origin defines the structure for the "o=" field which provides the @@ -97,15 +108,27 @@ type Origin struct { } func (o Origin) String() string { - return fmt.Sprintf( - "%v %d %d %v %v %v", - o.Username, - o.SessionID, - o.SessionVersion, - o.NetworkType, - o.AddressType, - o.UnicastAddress, - ) + return stringFromMarshal(o.marshalInto, o.marshalSize) +} + +func (o Origin) marshalInto(b []byte) []byte { + b = append(append(b, o.Username...), ' ') + b = append(strconv.AppendUint(b, o.SessionID, 10), ' ') + b = append(strconv.AppendUint(b, o.SessionVersion, 10), ' ') + b = append(append(b, o.NetworkType...), ' ') + b = append(append(b, o.AddressType...), ' ') + + return append(b, o.UnicastAddress...) +} + +func (o Origin) marshalSize() (size int) { + return len(o.Username) + + lenUint(o.SessionID) + + lenUint(o.SessionVersion) + + len(o.NetworkType) + + len(o.AddressType) + + len(o.UnicastAddress) + + 5 } // SessionName describes a structured representations for the "s=" field @@ -113,7 +136,15 @@ func (o Origin) String() string { type SessionName string func (s SessionName) String() string { - return string(s) + return stringFromMarshal(s.marshalInto, s.marshalSize) +} + +func (s SessionName) marshalInto(b []byte) []byte { + return append(b, s...) +} + +func (s SessionName) marshalSize() (size int) { + return len(s) } // EmailAddress describes a structured representations for the "e=" line @@ -122,7 +153,15 @@ func (s SessionName) String() string { type EmailAddress string func (e EmailAddress) String() string { - return string(e) + return stringFromMarshal(e.marshalInto, e.marshalSize) +} + +func (e EmailAddress) marshalInto(b []byte) []byte { + return append(b, e...) +} + +func (e EmailAddress) marshalSize() (size int) { + return len(e) } // PhoneNumber describes a structured representations for the "p=" line @@ -131,7 +170,15 @@ func (e EmailAddress) String() string { type PhoneNumber string func (p PhoneNumber) String() string { - return string(p) + return stringFromMarshal(p.marshalInto, p.marshalSize) +} + +func (p PhoneNumber) marshalInto(b []byte) []byte { + return append(b, p...) +} + +func (p PhoneNumber) marshalSize() (size int) { + return len(p) } // TimeZone defines the structured object for "z=" line which describes @@ -142,5 +189,16 @@ type TimeZone struct { } func (z TimeZone) String() string { - return strconv.FormatUint(z.AdjustmentTime, 10) + " " + strconv.FormatInt(z.Offset, 10) + return stringFromMarshal(z.marshalInto, z.marshalSize) +} + +func (z TimeZone) marshalInto(b []byte) []byte { + b = strconv.AppendUint(b, z.AdjustmentTime, 10) + b = append(b, ' ') + + return strconv.AppendInt(b, z.Offset, 10) +} + +func (z TimeZone) marshalSize() (size int) { + return lenUint(z.AdjustmentTime) + 1 + lenInt(z.Offset) } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/time_description.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/time_description.go index 8b24e130d..1682ba327 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/time_description.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/time_description.go @@ -1,8 +1,10 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package sdp import ( "strconv" - "strings" ) // TimeDescription describes "t=", "r=" fields of the session description @@ -26,9 +28,17 @@ type Timing struct { } func (t Timing) String() string { - output := strconv.FormatUint(t.StartTime, 10) - output += " " + strconv.FormatUint(t.StopTime, 10) - return output + return stringFromMarshal(t.marshalInto, t.marshalSize) +} + +func (t Timing) marshalInto(b []byte) []byte { + b = append(strconv.AppendUint(b, t.StartTime, 10), ' ') + + return strconv.AppendUint(b, t.StopTime, 10) +} + +func (t Timing) marshalSize() (size int) { + return lenUint(t.StartTime) + 1 + lenUint(t.StopTime) } // RepeatTime describes the "r=" fields of the session description which @@ -40,12 +50,27 @@ type RepeatTime struct { } func (r RepeatTime) String() string { - fields := make([]string, 0) - fields = append(fields, strconv.FormatInt(r.Interval, 10)) - fields = append(fields, strconv.FormatInt(r.Duration, 10)) + return stringFromMarshal(r.marshalInto, r.marshalSize) +} + +func (r RepeatTime) marshalInto(b []byte) []byte { + b = strconv.AppendInt(b, r.Interval, 10) + b = append(b, ' ') + b = strconv.AppendInt(b, r.Duration, 10) for _, value := range r.Offsets { - fields = append(fields, strconv.FormatInt(value, 10)) + b = append(b, ' ') + b = strconv.AppendInt(b, value, 10) } - return strings.Join(fields, " ") + return b +} + +func (r RepeatTime) marshalSize() (size int) { + size = lenInt(r.Interval) + size += 1 + lenInt(r.Duration) + for _, o := range r.Offsets { + size += 1 + lenInt(o) + } + + return } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/unmarshal.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/unmarshal.go index 59fcbe74c..e884b0f9f 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/unmarshal.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/unmarshal.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package sdp import ( @@ -6,6 +9,7 @@ import ( "net/url" "strconv" "strings" + "sync" ) var ( @@ -13,57 +17,72 @@ var ( errSDPInvalidNumericValue = errors.New("sdp: invalid numeric value") errSDPInvalidValue = errors.New("sdp: invalid value") errSDPInvalidPortValue = errors.New("sdp: invalid port value") + errSDPCacheInvalid = errors.New("sdp: invalid cache") + + //nolint: gochecknoglobals + unmarshalCachePool = sync.Pool{ + New: func() interface{} { + return &unmarshalCache{} + }, + } ) -// Unmarshal is the primary function that deserializes the session description +// UnmarshalString is the primary function that deserializes the session description // message and stores it inside of a structured SessionDescription object. // // The States Transition Table describes the computation flow between functions // (namely s1, s2, s3, ...) for a parsing procedure that complies with the // specifications laid out by the rfc4566#section-5 as well as by JavaScript // Session Establishment Protocol draft. Links: -// https://tools.ietf.org/html/rfc4566#section-5 -// https://tools.ietf.org/html/draft-ietf-rtcweb-jsep-24 +// +// https://tools.ietf.org/html/rfc4566#section-5 +// https://tools.ietf.org/html/draft-ietf-rtcweb-jsep-24 // // https://tools.ietf.org/html/rfc4566#section-5 // Session description -// v= (protocol version) -// o= (originator and session identifier) -// s= (session name) -// i=* (session information) -// u=* (URI of description) -// e=* (email address) -// p=* (phone number) -// c=* (connection information -- not required if included in -// all media) -// b=* (zero or more bandwidth information lines) -// One or more time descriptions ("t=" and "r=" lines; see below) -// z=* (time zone adjustments) -// k=* (encryption key) -// a=* (zero or more session attribute lines) -// Zero or more media descriptions +// +// v= (protocol version) +// o= (originator and session identifier) +// s= (session name) +// i=* (session information) +// u=* (URI of description) +// e=* (email address) +// p=* (phone number) +// c=* (connection information -- not required if included in +// all media) +// b=* (zero or more bandwidth information lines) +// One or more time descriptions ("t=" and "r=" lines; see below) +// z=* (time zone adjustments) +// k=* (encryption key) +// a=* (zero or more session attribute lines) +// Zero or more media descriptions // // Time description -// t= (time the session is active) -// r=* (zero or more repeat times) +// +// t= (time the session is active) +// r=* (zero or more repeat times) // // Media description, if present -// m= (media name and transport address) -// i=* (media title) -// c=* (connection information -- optional if included at -// session level) -// b=* (zero or more bandwidth information lines) -// k=* (encryption key) -// a=* (zero or more media attribute lines) +// +// m= (media name and transport address) +// i=* (media title) +// c=* (connection information -- optional if included at +// session level) +// b=* (zero or more bandwidth information lines) +// k=* (encryption key) +// a=* (zero or more media attribute lines) // // In order to generate the following state table and draw subsequent // deterministic finite-state automota ("DFA") the following regex was used to // derive the DFA: -// vosi?u?e?p?c?b*(tr*)+z?k?a*(mi?c?b*k?a*)* +// +// vosi?u?e?p?c?b*(tr*)+z?k?a*(mi?c?b*k?a*)* +// // possible place and state to exit: -// ** * * * ** * * * * -// 99 1 1 1 11 1 1 1 1 -// 3 1 1 26 5 5 4 4 +// +// ** * * * ** * * * * +// 99 1 1 1 11 1 1 1 1 +// 3 1 1 26 5 5 4 4 // // Please pay close attention to the `k`, and `a` parsing states. In the table // below in order to distinguish between the states belonging to the media @@ -88,278 +107,312 @@ var ( // | s14 | 14 | | | | | | | | 12 | | | | | | | | | // | s15 | | 14 | | | 15 | | | | 12 | | | | | | | | | // | s16 | | 14 | | | | 15 | | | 12 | | | | | | | | | -// +--------+----+-------+----+-----+----+-----+---+----+----+---+---+-----+---+---+----+---+----+ -func (s *SessionDescription) Unmarshal(value []byte) error { - l := new(lexer) - l.desc = s - l.value = value +// +--------+----+-------+----+-----+----+-----+---+----+----+---+---+-----+---+---+----+---+----+ . +func (s *SessionDescription) UnmarshalString(value string) error { + var ok bool + lex := new(lexer) + if lex.cache, ok = unmarshalCachePool.Get().(*unmarshalCache); !ok { + return errSDPCacheInvalid + } + defer unmarshalCachePool.Put(lex.cache) + + lex.cache.reset() + lex.desc = s + lex.value = value + for state := s1; state != nil; { var err error - state, err = state(l) + state, err = state(lex) if err != nil { return err } } + + s.Attributes = lex.cache.cloneSessionAttributes() + populateMediaAttributes(lex.cache, lex.desc) + return nil } +// Unmarshal converts the value into a []byte and then calls UnmarshalString. +// Callers should use the more performant UnmarshalString. +func (s *SessionDescription) Unmarshal(value []byte) error { + return s.UnmarshalString(string(value)) +} + func s1(l *lexer) (stateFn, error) { - return l.handleType(func(key string) stateFn { - if key == "v=" { + return l.handleType(func(key byte) stateFn { + if key == 'v' { return unmarshalProtocolVersion } + return nil }) } func s2(l *lexer) (stateFn, error) { - return l.handleType(func(key string) stateFn { - if key == "o=" { + return l.handleType(func(key byte) stateFn { + if key == 'o' { return unmarshalOrigin } + return nil }) } func s3(l *lexer) (stateFn, error) { - return l.handleType(func(key string) stateFn { - if key == "s=" { + return l.handleType(func(key byte) stateFn { + if key == 's' { return unmarshalSessionName } + return nil }) } func s4(l *lexer) (stateFn, error) { - return l.handleType(func(key string) stateFn { + return l.handleType(func(key byte) stateFn { switch key { - case "i=": + case 'i': return unmarshalSessionInformation - case "u=": + case 'u': return unmarshalURI - case "e=": + case 'e': return unmarshalEmail - case "p=": + case 'p': return unmarshalPhone - case "c=": + case 'c': return unmarshalSessionConnectionInformation - case "b=": + case 'b': return unmarshalSessionBandwidth - case "t=": + case 't': return unmarshalTiming } + return nil }) } func s5(l *lexer) (stateFn, error) { - return l.handleType(func(key string) stateFn { + return l.handleType(func(key byte) stateFn { switch key { - case "b=": + case 'b': return unmarshalSessionBandwidth - case "t=": + case 't': return unmarshalTiming } + return nil }) } func s6(l *lexer) (stateFn, error) { - return l.handleType(func(key string) stateFn { + return l.handleType(func(key byte) stateFn { switch key { - case "p=": + case 'p': return unmarshalPhone - case "c=": + case 'c': return unmarshalSessionConnectionInformation - case "b=": + case 'b': return unmarshalSessionBandwidth - case "t=": + case 't': return unmarshalTiming } + return nil }) } func s7(l *lexer) (stateFn, error) { - return l.handleType(func(key string) stateFn { + return l.handleType(func(key byte) stateFn { switch key { - case "u=": + case 'u': return unmarshalURI - case "e=": + case 'e': return unmarshalEmail - case "p=": + case 'p': return unmarshalPhone - case "c=": + case 'c': return unmarshalSessionConnectionInformation - case "b=": + case 'b': return unmarshalSessionBandwidth - case "t=": + case 't': return unmarshalTiming } + return nil }) } func s8(l *lexer) (stateFn, error) { - return l.handleType(func(key string) stateFn { + return l.handleType(func(key byte) stateFn { switch key { - case "c=": + case 'c': return unmarshalSessionConnectionInformation - case "b=": + case 'b': return unmarshalSessionBandwidth - case "t=": + case 't': return unmarshalTiming } + return nil }) } func s9(l *lexer) (stateFn, error) { - return l.handleType(func(key string) stateFn { + return l.handleType(func(key byte) stateFn { switch key { - case "z=": + case 'z': return unmarshalTimeZones - case "k=": + case 'k': return unmarshalSessionEncryptionKey - case "a=": + case 'a': return unmarshalSessionAttribute - case "r=": + case 'r': return unmarshalRepeatTimes - case "t=": + case 't': return unmarshalTiming - case "m=": + case 'm': return unmarshalMediaDescription } + return nil }) } func s10(l *lexer) (stateFn, error) { - return l.handleType(func(key string) stateFn { + return l.handleType(func(key byte) stateFn { switch key { - case "e=": + case 'e': return unmarshalEmail - case "p=": + case 'p': return unmarshalPhone - case "c=": + case 'c': return unmarshalSessionConnectionInformation - case "b=": + case 'b': return unmarshalSessionBandwidth - case "t=": + case 't': return unmarshalTiming } + return nil }) } func s11(l *lexer) (stateFn, error) { - return l.handleType(func(key string) stateFn { + return l.handleType(func(key byte) stateFn { switch key { - case "a=": + case 'a': return unmarshalSessionAttribute - case "m=": + case 'm': return unmarshalMediaDescription } + return nil }) } func s12(l *lexer) (stateFn, error) { - return l.handleType(func(key string) stateFn { + return l.handleType(func(key byte) stateFn { switch key { - case "a=": + case 'a': return unmarshalMediaAttribute - case "k=": + case 'k': return unmarshalMediaEncryptionKey - case "b=": + case 'b': return unmarshalMediaBandwidth - case "c=": + case 'c': return unmarshalMediaConnectionInformation - case "i=": + case 'i': return unmarshalMediaTitle - case "m=": + case 'm': return unmarshalMediaDescription } + return nil }) } func s13(l *lexer) (stateFn, error) { - return l.handleType(func(key string) stateFn { + return l.handleType(func(key byte) stateFn { switch key { - case "a=": + case 'a': return unmarshalSessionAttribute - case "k=": + case 'k': return unmarshalSessionEncryptionKey - case "m=": + case 'm': return unmarshalMediaDescription } + return nil }) } func s14(l *lexer) (stateFn, error) { - return l.handleType(func(key string) stateFn { + return l.handleType(func(key byte) stateFn { switch key { - case "a=": + case 'a': return unmarshalMediaAttribute - case "k=": + case 'k': // Non-spec ordering return unmarshalMediaEncryptionKey - case "b=": + case 'b': // Non-spec ordering return unmarshalMediaBandwidth - case "c=": + case 'c': // Non-spec ordering return unmarshalMediaConnectionInformation - case "i=": + case 'i': // Non-spec ordering return unmarshalMediaTitle - case "m=": + case 'm': return unmarshalMediaDescription } + return nil }) } func s15(l *lexer) (stateFn, error) { - return l.handleType(func(key string) stateFn { + return l.handleType(func(key byte) stateFn { switch key { - case "a=": + case 'a': return unmarshalMediaAttribute - case "k=": + case 'k': return unmarshalMediaEncryptionKey - case "b=": + case 'b': return unmarshalMediaBandwidth - case "c=": + case 'c': return unmarshalMediaConnectionInformation - case "i=": + case 'i': // Non-spec ordering return unmarshalMediaTitle - case "m=": + case 'm': return unmarshalMediaDescription } + return nil }) } func s16(l *lexer) (stateFn, error) { - return l.handleType(func(key string) stateFn { + return l.handleType(func(key byte) stateFn { switch key { - case "a=": + case 'a': return unmarshalMediaAttribute - case "k=": + case 'k': return unmarshalMediaEncryptionKey - case "c=": + case 'c': return unmarshalMediaConnectionInformation - case "b=": + case 'b': return unmarshalMediaBandwidth - case "i=": + case 'i': // Non-spec ordering return unmarshalMediaTitle - case "m=": + case 'm': return unmarshalMediaDescription } + return nil }) } @@ -383,52 +436,52 @@ func unmarshalProtocolVersion(l *lexer) (stateFn, error) { return s2, nil } -func unmarshalOrigin(l *lexer) (stateFn, error) { +func unmarshalOrigin(lex *lexer) (stateFn, error) { var err error - l.desc.Origin.Username, err = l.readField() + lex.desc.Origin.Username, err = lex.readField() if err != nil { return nil, err } - l.desc.Origin.SessionID, err = l.readUint64Field() + lex.desc.Origin.SessionID, err = lex.readUint64Field() if err != nil { return nil, err } - l.desc.Origin.SessionVersion, err = l.readUint64Field() + lex.desc.Origin.SessionVersion, err = lex.readUint64Field() if err != nil { return nil, err } - l.desc.Origin.NetworkType, err = l.readField() + lex.desc.Origin.NetworkType, err = lex.readField() if err != nil { return nil, err } // Set according to currently registered with IANA // https://tools.ietf.org/html/rfc4566#section-8.2.6 - if !anyOf(l.desc.Origin.NetworkType, "IN") { - return nil, fmt.Errorf("%w `%v`", errSDPInvalidValue, l.desc.Origin.NetworkType) + if !anyOf(lex.desc.Origin.NetworkType, "IN") { + return nil, fmt.Errorf("%w `%v`", errSDPInvalidValue, lex.desc.Origin.NetworkType) } - l.desc.Origin.AddressType, err = l.readField() + lex.desc.Origin.AddressType, err = lex.readField() if err != nil { return nil, err } // Set according to currently registered with IANA // https://tools.ietf.org/html/rfc4566#section-8.2.7 - if !anyOf(l.desc.Origin.AddressType, "IP4", "IP6") { - return nil, fmt.Errorf("%w `%v`", errSDPInvalidValue, l.desc.Origin.AddressType) + if !anyOf(lex.desc.Origin.AddressType, "IP4", "IP6") { + return nil, fmt.Errorf("%w `%v`", errSDPInvalidValue, lex.desc.Origin.AddressType) } - l.desc.Origin.UnicastAddress, err = l.readField() + lex.desc.Origin.UnicastAddress, err = lex.readField() if err != nil { return nil, err } - if err := l.nextLine(); err != nil { + if err := lex.nextLine(); err != nil { return nil, err } @@ -442,6 +495,7 @@ func unmarshalSessionName(l *lexer) (stateFn, error) { } l.desc.SessionName = SessionName(value) + return s4, nil } @@ -453,6 +507,7 @@ func unmarshalSessionInformation(l *lexer) (stateFn, error) { sessionInformation := Information(value) l.desc.SessionInformation = &sessionInformation + return s7, nil } @@ -478,6 +533,7 @@ func unmarshalEmail(l *lexer) (stateFn, error) { emailAddress := EmailAddress(value) l.desc.EmailAddress = &emailAddress + return s6, nil } @@ -489,6 +545,7 @@ func unmarshalPhone(l *lexer) (stateFn, error) { phoneNumber := PhoneNumber(value) l.desc.PhoneNumber = &phoneNumber + return s8, nil } @@ -498,33 +555,34 @@ func unmarshalSessionConnectionInformation(l *lexer) (stateFn, error) { if err != nil { return nil, err } + return s5, nil } func (l *lexer) unmarshalConnectionInformation() (*ConnectionInformation, error) { var err error - var c ConnectionInformation + var connInfo ConnectionInformation - c.NetworkType, err = l.readField() + connInfo.NetworkType, err = l.readField() if err != nil { return nil, err } // Set according to currently registered with IANA // https://tools.ietf.org/html/rfc4566#section-8.2.6 - if !anyOf(c.NetworkType, "IN") { - return nil, fmt.Errorf("%w `%v`", errSDPInvalidValue, c.NetworkType) + if !anyOf(connInfo.NetworkType, "IN") { + return nil, fmt.Errorf("%w `%v`", errSDPInvalidValue, connInfo.NetworkType) } - c.AddressType, err = l.readField() + connInfo.AddressType, err = l.readField() if err != nil { return nil, err } // Set according to currently registered with IANA // https://tools.ietf.org/html/rfc4566#section-8.2.7 - if !anyOf(c.AddressType, "IP4", "IP6") { - return nil, fmt.Errorf("%w `%v`", errSDPInvalidValue, c.AddressType) + if !anyOf(connInfo.AddressType, "IP4", "IP6") { + return nil, fmt.Errorf("%w `%v`", errSDPInvalidValue, connInfo.AddressType) } address, err := l.readField() @@ -533,15 +591,15 @@ func (l *lexer) unmarshalConnectionInformation() (*ConnectionInformation, error) } if address != "" { - c.Address = new(Address) - c.Address.Address = address + connInfo.Address = new(Address) + connInfo.Address.Address = address } if err := l.nextLine(); err != nil { return nil, err } - return &c, nil + return &connInfo, nil } func unmarshalSessionBandwidth(l *lexer) (stateFn, error) { @@ -588,35 +646,36 @@ func unmarshalBandwidth(value string) (*Bandwidth, error) { }, nil } -func unmarshalTiming(l *lexer) (stateFn, error) { +func unmarshalTiming(lex *lexer) (stateFn, error) { var err error var td TimeDescription - td.Timing.StartTime, err = l.readUint64Field() + td.Timing.StartTime, err = lex.readUint64Field() if err != nil { return nil, err } - td.Timing.StopTime, err = l.readUint64Field() + td.Timing.StopTime, err = lex.readUint64Field() if err != nil { return nil, err } - if err := l.nextLine(); err != nil { + if err := lex.nextLine(); err != nil { return nil, err } - l.desc.TimeDescriptions = append(l.desc.TimeDescriptions, td) + lex.desc.TimeDescriptions = append(lex.desc.TimeDescriptions, td) + return s9, nil } -func unmarshalRepeatTimes(l *lexer) (stateFn, error) { +func unmarshalRepeatTimes(lex *lexer) (stateFn, error) { var err error var newRepeatTime RepeatTime - latestTimeDesc := &l.desc.TimeDescriptions[len(l.desc.TimeDescriptions)-1] + latestTimeDesc := &lex.desc.TimeDescriptions[len(lex.desc.TimeDescriptions)-1] - field, err := l.readField() + field, err := lex.readField() if err != nil { return nil, err } @@ -626,7 +685,7 @@ func unmarshalRepeatTimes(l *lexer) (stateFn, error) { return nil, fmt.Errorf("%w `%v`", errSDPInvalidValue, field) } - field, err = l.readField() + field, err = lex.readField() if err != nil { return nil, err } @@ -637,7 +696,7 @@ func unmarshalRepeatTimes(l *lexer) (stateFn, error) { } for { - field, err := l.readField() + field, err := lex.readField() if err != nil { return nil, err } @@ -651,15 +710,16 @@ func unmarshalRepeatTimes(l *lexer) (stateFn, error) { newRepeatTime.Offsets = append(newRepeatTime.Offsets, offset) } - if err := l.nextLine(); err != nil { + if err := lex.nextLine(); err != nil { return nil, err } latestTimeDesc.RepeatTimes = append(latestTimeDesc.RepeatTimes, newRepeatTime) + return s9, nil } -func unmarshalTimeZones(l *lexer) (stateFn, error) { +func unmarshalTimeZones(lex *lexer) (stateFn, error) { // These fields are transimitted in pairs // z= .... // so we are making sure that there are actually multiple of 2 total. @@ -667,12 +727,12 @@ func unmarshalTimeZones(l *lexer) (stateFn, error) { var err error var timeZone TimeZone - timeZone.AdjustmentTime, err = l.readUint64Field() + timeZone.AdjustmentTime, err = lex.readUint64Field() if err != nil { return nil, err } - offset, err := l.readField() + offset, err := lex.readField() if err != nil { return nil, err } @@ -686,10 +746,10 @@ func unmarshalTimeZones(l *lexer) (stateFn, error) { return nil, err } - l.desc.TimeZones = append(l.desc.TimeZones, timeZone) + lex.desc.TimeZones = append(lex.desc.TimeZones, timeZone) } - if err := l.nextLine(); err != nil { + if err := lex.nextLine(); err != nil { return nil, err } @@ -704,6 +764,7 @@ func unmarshalSessionEncryptionKey(l *lexer) (stateFn, error) { encryptionKey := EncryptionKey(value) l.desc.EncryptionKey = &encryptionKey + return s11, nil } @@ -714,22 +775,23 @@ func unmarshalSessionAttribute(l *lexer) (stateFn, error) { } i := strings.IndexRune(value, ':') - var a Attribute + a := l.cache.getSessionAttribute() if i > 0 { - a = NewAttribute(value[:i], value[i+1:]) + a.Key = value[:i] + a.Value = value[i+1:] } else { - a = NewPropertyAttribute(value) + a.Key = value } - l.desc.Attributes = append(l.desc.Attributes, a) return s11, nil } -func unmarshalMediaDescription(l *lexer) (stateFn, error) { +func unmarshalMediaDescription(lex *lexer) (stateFn, error) { //nolint:cyclop + populateMediaAttributes(lex.cache, lex.desc) var newMediaDesc MediaDescription // - field, err := l.readField() + field, err := lex.readField() if err != nil { return nil, err } @@ -742,7 +804,7 @@ func unmarshalMediaDescription(l *lexer) (stateFn, error) { newMediaDesc.MediaName.Media = field // - field, err = l.readField() + field, err = lex.readField() if err != nil { return nil, err } @@ -762,7 +824,7 @@ func unmarshalMediaDescription(l *lexer) (stateFn, error) { } // - field, err = l.readField() + field, err = lex.readField() if err != nil { return nil, err } @@ -771,7 +833,24 @@ func unmarshalMediaDescription(l *lexer) (stateFn, error) { // https://tools.ietf.org/html/rfc4566#section-5.14 // https://tools.ietf.org/html/rfc4975#section-8.1 for _, proto := range strings.Split(field, "/") { - if !anyOf(proto, "UDP", "RTP", "AVP", "SAVP", "SAVPF", "TLS", "DTLS", "SCTP", "AVPF", "TCP", "MSRP") { + if !anyOf( + proto, + "UDP", + "RTP", + "AVP", + "SAVP", + "SAVPF", + "TLS", + "DTLS", + "SCTP", + "AVPF", + "TCP", + "MSRP", + "BFCP", + "UDT", + "IX", + "MRCPv2", + ) { return nil, fmt.Errorf("%w `%v`", errSDPInvalidNumericValue, field) } newMediaDesc.MediaName.Protos = append(newMediaDesc.MediaName.Protos, proto) @@ -779,7 +858,7 @@ func unmarshalMediaDescription(l *lexer) (stateFn, error) { // ... for { - field, err = l.readField() + field, err = lex.readField() if err != nil { return nil, err } @@ -789,11 +868,12 @@ func unmarshalMediaDescription(l *lexer) (stateFn, error) { newMediaDesc.MediaName.Formats = append(newMediaDesc.MediaName.Formats, field) } - if err := l.nextLine(); err != nil { + if err := lex.nextLine(); err != nil { return nil, err } - l.desc.MediaDescriptions = append(l.desc.MediaDescriptions, &newMediaDesc) + lex.desc.MediaDescriptions = append(lex.desc.MediaDescriptions, &newMediaDesc) + return s12, nil } @@ -806,6 +886,7 @@ func unmarshalMediaTitle(l *lexer) (stateFn, error) { latestMediaDesc := l.desc.MediaDescriptions[len(l.desc.MediaDescriptions)-1] mediaTitle := Information(value) latestMediaDesc.MediaTitle = &mediaTitle + return s16, nil } @@ -816,6 +897,7 @@ func unmarshalMediaConnectionInformation(l *lexer) (stateFn, error) { if err != nil { return nil, err } + return s15, nil } @@ -831,6 +913,7 @@ func unmarshalMediaBandwidth(l *lexer) (stateFn, error) { return nil, fmt.Errorf("%w `b=%v`", errSDPInvalidSyntax, value) } latestMediaDesc.Bandwidth = append(latestMediaDesc.Bandwidth, *bandwidth) + return s15, nil } @@ -843,6 +926,7 @@ func unmarshalMediaEncryptionKey(l *lexer) (stateFn, error) { latestMediaDesc := l.desc.MediaDescriptions[len(l.desc.MediaDescriptions)-1] encryptionKey := EncryptionKey(value) latestMediaDesc.EncryptionKey = &encryptionKey + return s14, nil } @@ -853,19 +937,21 @@ func unmarshalMediaAttribute(l *lexer) (stateFn, error) { } i := strings.IndexRune(value, ':') - var a Attribute + a := l.cache.getMediaAttribute() if i > 0 { - a = NewAttribute(value[:i], value[i+1:]) + a.Key = value[:i] + a.Value = value[i+1:] } else { - a = NewPropertyAttribute(value) + a.Key = value } - latestMediaDesc := l.desc.MediaDescriptions[len(l.desc.MediaDescriptions)-1] - latestMediaDesc.Attributes = append(latestMediaDesc.Attributes, a) return s14, nil } func parseTimeUnits(value string) (num int64, err error) { + if len(value) == 0 { + return 0, fmt.Errorf("%w `%v`", errSDPInvalidValue, value) + } k := timeShorthand(value[len(value)-1]) if k > 0 { num, err = strconv.ParseInt(value[:len(value)-1], 10, 64) @@ -876,6 +962,7 @@ func parseTimeUnits(value string) (num int64, err error) { if err != nil { return 0, fmt.Errorf("%w `%v`", errSDPInvalidValue, value) } + return num * k, nil } @@ -908,3 +995,10 @@ func parsePort(value string) (int, error) { return port, nil } + +func populateMediaAttributes(c *unmarshalCache, s *SessionDescription) { + if len(s.MediaDescriptions) != 0 { + lastMediaDesc := s.MediaDescriptions[len(s.MediaDescriptions)-1] + lastMediaDesc.Attributes = c.cloneMediaAttributes() + } +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/unmarshal_cache.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/unmarshal_cache.go new file mode 100644 index 000000000..478d0f75c --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/unmarshal_cache.go @@ -0,0 +1,48 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + +package sdp + +type unmarshalCache struct { + sessionAttributes []Attribute + mediaAttributes []Attribute +} + +func (c *unmarshalCache) reset() { + c.sessionAttributes = c.sessionAttributes[:0] + c.mediaAttributes = c.mediaAttributes[:0] +} + +func (c *unmarshalCache) getSessionAttribute() *Attribute { + c.sessionAttributes = append(c.sessionAttributes, Attribute{}) + + return &c.sessionAttributes[len(c.sessionAttributes)-1] +} + +func (c *unmarshalCache) cloneSessionAttributes() []Attribute { + if len(c.sessionAttributes) == 0 { + return nil + } + s := make([]Attribute, len(c.sessionAttributes)) + copy(s, c.sessionAttributes) + c.sessionAttributes = c.sessionAttributes[:0] + + return s +} + +func (c *unmarshalCache) getMediaAttribute() *Attribute { + c.mediaAttributes = append(c.mediaAttributes, Attribute{}) + + return &c.mediaAttributes[len(c.mediaAttributes)-1] +} + +func (c *unmarshalCache) cloneMediaAttributes() []Attribute { + if len(c.mediaAttributes) == 0 { + return nil + } + s := make([]Attribute, len(c.mediaAttributes)) + copy(s, c.mediaAttributes) + c.mediaAttributes = c.mediaAttributes[:0] + + return s +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/util.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/util.go index 84cba7f7d..4550feece 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/util.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/sdp/v3/util.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package sdp import ( @@ -16,15 +19,19 @@ const ( ) var ( - errExtractCodecRtpmap = errors.New("could not extract codec from rtpmap") - errExtractCodecFmtp = errors.New("could not extract codec from fmtp") - errExtractCodecRtcpFb = errors.New("could not extract codec from rtcp-fb") - errPayloadTypeNotFound = errors.New("payload type not found") - errCodecNotFound = errors.New("codec not found") - errSyntaxError = errors.New("SyntaxError") + errExtractCodecRtpmap = errors.New("could not extract codec from rtpmap") + errExtractCodecFmtp = errors.New("could not extract codec from fmtp") + errExtractCodecRtcpFb = errors.New("could not extract codec from rtcp-fb") + errMultipleName = errors.New("codec has multiple names defined") + errMultipleClockRate = errors.New("codec has multiple clock rates") + errMultipleEncodingParameters = errors.New("codec has multiple encoding parameters") + errMultipleFmtp = errors.New("codec has multiple fmtp values") + errPayloadTypeNotFound = errors.New("payload type not found") + errCodecNotFound = errors.New("codec not found") + errSyntaxError = errors.New("SyntaxError") ) -// ConnectionRole indicates which of the end points should initiate the connection establishment +// ConnectionRole indicates which of the end points should initiate the connection establishment. type ConnectionRole int const ( @@ -34,7 +41,8 @@ const ( // ConnectionRolePassive indicates the endpoint will accept an incoming connection. ConnectionRolePassive - // ConnectionRoleActpass indicates the endpoint is willing to accept an incoming connection or to initiate an outgoing connection. + // ConnectionRoleActpass indicates the endpoint is willing to accept an incoming connection or + // to initiate an outgoing connection. ConnectionRoleActpass // ConnectionRoleHoldconn indicates the endpoint does not want the connection to be established for the time being. @@ -62,10 +70,11 @@ func newSessionID() (uint64, error) { // quantity with the highest bit set to zero and the remaining 63-bits // being cryptographically random. id, err := randutil.CryptoUint64() + return id & (^(uint64(1) << 63)), err } -// Codec represents a codec +// Codec represents a codec. type Codec struct { PayloadType uint8 Name string @@ -80,7 +89,25 @@ const ( ) func (c Codec) String() string { - return fmt.Sprintf("%d %s/%d/%s (%s) [%s]", c.PayloadType, c.Name, c.ClockRate, c.EncodingParameters, c.Fmtp, strings.Join(c.RTCPFeedback, ", ")) + return fmt.Sprintf( + "%d %s/%d/%s (%s) [%s]", + c.PayloadType, + c.Name, + c.ClockRate, + c.EncodingParameters, + c.Fmtp, + strings.Join(c.RTCPFeedback, ", "), + ) +} + +func (c *Codec) appendRTCPFeedback(rtcpFeedback string) { + for _, existingRTCPFeedback := range c.RTCPFeedback { + if existingRTCPFeedback == rtcpFeedback { + return + } + } + + c.RTCPFeedback = append(c.RTCPFeedback, rtcpFeedback) } func parseRtpmap(rtpmap string) (Codec, error) { @@ -127,7 +154,7 @@ func parseFmtp(fmtp string) (Codec, error) { parsingFailed := errExtractCodecFmtp // a=fmtp: - split := strings.Split(fmtp, " ") + split := strings.SplitN(fmtp, " ", 2) if len(split) != 2 { return codec, parsingFailed } @@ -150,58 +177,94 @@ func parseFmtp(fmtp string) (Codec, error) { return codec, nil } -func parseRtcpFb(rtcpFb string) (Codec, error) { - var codec Codec - parsingFailed := errExtractCodecRtcpFb +func parseRtcpFb(rtcpFb string) (codec Codec, isWildcard bool, err error) { + var ptInt uint64 + err = errExtractCodecRtcpFb // a=ftcp-fb: [] split := strings.SplitN(rtcpFb, " ", 2) if len(split) != 2 { - return codec, parsingFailed + return } ptSplit := strings.Split(split[0], ":") if len(ptSplit) != 2 { - return codec, parsingFailed + return } - ptInt, err := strconv.ParseUint(ptSplit[1], 10, 8) - if err != nil { - return codec, parsingFailed + isWildcard = ptSplit[1] == "*" + if !isWildcard { + ptInt, err = strconv.ParseUint(ptSplit[1], 10, 8) + if err != nil { + return + } + + codec.PayloadType = uint8(ptInt) } - codec.PayloadType = uint8(ptInt) codec.RTCPFeedback = append(codec.RTCPFeedback, split[1]) - return codec, nil + return codec, isWildcard, nil } -func mergeCodecs(codec Codec, codecs map[uint8]Codec) { +func mergeCodecs(codec Codec, codecs map[uint8]Codec) error { // nolint: cyclop savedCodec := codecs[codec.PayloadType] + savedCodec.PayloadType = codec.PayloadType + + if codec.Name != "" { + if savedCodec.Name != "" && savedCodec.Name != codec.Name { + return errMultipleName + } - if savedCodec.PayloadType == 0 { - savedCodec.PayloadType = codec.PayloadType - } - if savedCodec.Name == "" { savedCodec.Name = codec.Name } - if savedCodec.ClockRate == 0 { + + if codec.ClockRate != 0 { + if savedCodec.ClockRate != 0 && savedCodec.ClockRate != codec.ClockRate { + return errMultipleClockRate + } + savedCodec.ClockRate = codec.ClockRate } - if savedCodec.EncodingParameters == "" { + + if codec.EncodingParameters != "" { + if savedCodec.EncodingParameters != "" && savedCodec.EncodingParameters != codec.EncodingParameters { + return errMultipleEncodingParameters + } + savedCodec.EncodingParameters = codec.EncodingParameters } - if savedCodec.Fmtp == "" { + + if codec.Fmtp != "" { + if savedCodec.Fmtp != "" && savedCodec.Fmtp != codec.Fmtp { + return errMultipleFmtp + } + savedCodec.Fmtp = codec.Fmtp } - savedCodec.RTCPFeedback = append(savedCodec.RTCPFeedback, codec.RTCPFeedback...) + savedCodec.RTCPFeedback = append(savedCodec.RTCPFeedback, codec.RTCPFeedback...) codecs[savedCodec.PayloadType] = savedCodec + + return nil } -func (s *SessionDescription) buildCodecMap() map[uint8]Codec { - codecs := make(map[uint8]Codec) +func (s *SessionDescription) buildCodecMap() (map[uint8]Codec, error) { //nolint:cyclop, gocognit + codecs := map[uint8]Codec{ + // static codecs that do not require a rtpmap + 0: { + PayloadType: 0, + Name: "PCMU", + ClockRate: 8000, + }, + 8: { + PayloadType: 8, + Name: "PCMA", + ClockRate: 8000, + }, + } + wildcardRTCPFeedback := []string{} for _, m := range s.MediaDescriptions { for _, a := range m.Attributes { attr := a.String() @@ -209,23 +272,41 @@ func (s *SessionDescription) buildCodecMap() map[uint8]Codec { case strings.HasPrefix(attr, "rtpmap:"): codec, err := parseRtpmap(attr) if err == nil { - mergeCodecs(codec, codecs) + if err = mergeCodecs(codec, codecs); err != nil { + return nil, err + } } case strings.HasPrefix(attr, "fmtp:"): codec, err := parseFmtp(attr) if err == nil { - mergeCodecs(codec, codecs) + if err = mergeCodecs(codec, codecs); err != nil { + return nil, err + } } case strings.HasPrefix(attr, "rtcp-fb:"): - codec, err := parseRtcpFb(attr) - if err == nil { - mergeCodecs(codec, codecs) + codec, isWildcard, err := parseRtcpFb(attr) + switch { + case err != nil: + case isWildcard: + wildcardRTCPFeedback = append(wildcardRTCPFeedback, codec.RTCPFeedback...) + default: + if err = mergeCodecs(codec, codecs); err != nil { + return nil, err + } } } } } - return codecs + for i, codec := range codecs { + for _, newRTCPFeedback := range wildcardRTCPFeedback { + codec.appendRTCPFeedback(newRTCPFeedback) + } + + codecs[i] = codec + } + + return codecs, nil } func equivalentFmtp(want, got string) bool { @@ -267,9 +348,12 @@ func codecsMatch(wanted, got Codec) bool { return true } -// GetCodecForPayloadType scans the SessionDescription for the given payload type and returns the codec +// GetCodecForPayloadType scans the SessionDescription for the given payload type and returns the codec. func (s *SessionDescription) GetCodecForPayloadType(payloadType uint8) (Codec, error) { - codecs := s.buildCodecMap() + codecs, err := s.buildCodecMap() + if err != nil { + return Codec{}, err + } codec, ok := codecs[payloadType] if ok { @@ -280,9 +364,12 @@ func (s *SessionDescription) GetCodecForPayloadType(payloadType uint8) (Codec, e } // GetPayloadTypeForCodec scans the SessionDescription for a codec that matches the provided codec -// as closely as possible and returns its payload type +// as closely as possible and returns its payload type. func (s *SessionDescription) GetPayloadTypeForCodec(wanted Codec) (uint8, error) { - codecs := s.buildCodecMap() + codecs, err := s.buildCodecMap() + if err != nil { + return 0, err + } for payloadType, codec := range codecs { if codecsMatch(wanted, codec) { @@ -296,15 +383,16 @@ func (s *SessionDescription) GetPayloadTypeForCodec(wanted Codec) (uint8, error) type stateFn func(*lexer) (stateFn, error) type lexer struct { - desc *SessionDescription + desc *SessionDescription + cache *unmarshalCache baseLexer } -type keyToState func(key string) stateFn +type keyToState func(key byte) stateFn func (l *lexer) handleType(fn keyToState) (stateFn, error) { key, err := l.readType() - if errors.Is(err, io.EOF) && key == "" { + if errors.Is(err, io.EOF) && key == 0 { return nil, nil //nolint:nilnil } else if err != nil { return nil, err diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/AUTHORS.txt b/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/AUTHORS.txt deleted file mode 100644 index daca101e1..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/AUTHORS.txt +++ /dev/null @@ -1,36 +0,0 @@ -# Thank you to everyone that made Pion possible. If you are interested in contributing -# we would love to have you https://github.com/pion/webrtc/wiki/Contributing -# -# This file is auto generated, using git to list all individuals contributors. -# see https://github.com/pion/.goassets/blob/master/scripts/generate-authors.sh for the scripting -adamroach -Adrian Cable -Agniva De Sarker -Antoine Baché -Atsushi Watanabe -backkem -chenkaiC4 -Chris Hiszpanski -cszdlt -Hugo Arregui -Jerko Steiner -Juliusz Chroboczek -Luke Curley -Luke Curley -Max Hawkins -mission-liao -Novel Corpse -OrlandoCo -Patryk -Patryk Rogalski -Sean DuBois -Sean DuBois -SeongGyu Park -Steffen -Steffen Vogel -Tobias Fridén -Woodrow Douglass -Yutaka Takeda - -# List of contributors not appearing in Git history - diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/option.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/option.go deleted file mode 100644 index 7e2618e38..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/option.go +++ /dev/null @@ -1,57 +0,0 @@ -// SPDX-FileCopyrightText: 2023 The Pion community -// SPDX-License-Identifier: MIT - -package srtp - -import ( - "github.com/pion/transport/v2/replaydetector" -) - -// ContextOption represents option of Context using the functional options pattern. -type ContextOption func(*Context) error - -// SRTPReplayProtection sets SRTP replay protection window size. -func SRTPReplayProtection(windowSize uint) ContextOption { // nolint:revive - return func(c *Context) error { - c.newSRTPReplayDetector = func() replaydetector.ReplayDetector { - return replaydetector.New(windowSize, maxROC<<16|maxSequenceNumber) - } - return nil - } -} - -// SRTCPReplayProtection sets SRTCP replay protection window size. -func SRTCPReplayProtection(windowSize uint) ContextOption { - return func(c *Context) error { - c.newSRTCPReplayDetector = func() replaydetector.ReplayDetector { - return replaydetector.New(windowSize, maxSRTCPIndex) - } - return nil - } -} - -// SRTPNoReplayProtection disables SRTP replay protection. -func SRTPNoReplayProtection() ContextOption { // nolint:revive - return func(c *Context) error { - c.newSRTPReplayDetector = func() replaydetector.ReplayDetector { - return &nopReplayDetector{} - } - return nil - } -} - -// SRTCPNoReplayProtection disables SRTCP replay protection. -func SRTCPNoReplayProtection() ContextOption { - return func(c *Context) error { - c.newSRTCPReplayDetector = func() replaydetector.ReplayDetector { - return &nopReplayDetector{} - } - return nil - } -} - -type nopReplayDetector struct{} - -func (s *nopReplayDetector) Check(uint64) (func(), bool) { - return func() {}, true -} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/protection_profile.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/protection_profile.go deleted file mode 100644 index c9b0fce3a..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/protection_profile.go +++ /dev/null @@ -1,86 +0,0 @@ -// SPDX-FileCopyrightText: 2023 The Pion community -// SPDX-License-Identifier: MIT - -package srtp - -import "fmt" - -// ProtectionProfile specifies Cipher and AuthTag details, similar to TLS cipher suite -type ProtectionProfile uint16 - -// Supported protection profiles -// See https://www.iana.org/assignments/srtp-protection/srtp-protection.xhtml -const ( - ProtectionProfileAes128CmHmacSha1_80 ProtectionProfile = 0x0001 - ProtectionProfileAes128CmHmacSha1_32 ProtectionProfile = 0x0002 - ProtectionProfileAeadAes128Gcm ProtectionProfile = 0x0007 - ProtectionProfileAeadAes256Gcm ProtectionProfile = 0x0008 -) - -func (p ProtectionProfile) keyLen() (int, error) { - switch p { - case ProtectionProfileAes128CmHmacSha1_32, ProtectionProfileAes128CmHmacSha1_80, ProtectionProfileAeadAes128Gcm: - return 16, nil - case ProtectionProfileAeadAes256Gcm: - return 32, nil - default: - return 0, fmt.Errorf("%w: %#v", errNoSuchSRTPProfile, p) - } -} - -func (p ProtectionProfile) saltLen() (int, error) { - switch p { - case ProtectionProfileAes128CmHmacSha1_32, ProtectionProfileAes128CmHmacSha1_80: - return 14, nil - case ProtectionProfileAeadAes128Gcm, ProtectionProfileAeadAes256Gcm: - return 12, nil - default: - return 0, fmt.Errorf("%w: %#v", errNoSuchSRTPProfile, p) - } -} - -func (p ProtectionProfile) rtpAuthTagLen() (int, error) { - switch p { - case ProtectionProfileAes128CmHmacSha1_80: - return 10, nil - case ProtectionProfileAes128CmHmacSha1_32: - return 4, nil - case ProtectionProfileAeadAes128Gcm, ProtectionProfileAeadAes256Gcm: - return 0, nil - default: - return 0, fmt.Errorf("%w: %#v", errNoSuchSRTPProfile, p) - } -} - -func (p ProtectionProfile) rtcpAuthTagLen() (int, error) { - switch p { - case ProtectionProfileAes128CmHmacSha1_32, ProtectionProfileAes128CmHmacSha1_80: - return 10, nil - case ProtectionProfileAeadAes128Gcm, ProtectionProfileAeadAes256Gcm: - return 0, nil - default: - return 0, fmt.Errorf("%w: %#v", errNoSuchSRTPProfile, p) - } -} - -func (p ProtectionProfile) aeadAuthTagLen() (int, error) { - switch p { - case ProtectionProfileAes128CmHmacSha1_32, ProtectionProfileAes128CmHmacSha1_80: - return 0, nil - case ProtectionProfileAeadAes128Gcm, ProtectionProfileAeadAes256Gcm: - return 16, nil - default: - return 0, fmt.Errorf("%w: %#v", errNoSuchSRTPProfile, p) - } -} - -func (p ProtectionProfile) authKeyLen() (int, error) { - switch p { - case ProtectionProfileAes128CmHmacSha1_32, ProtectionProfileAes128CmHmacSha1_80: - return 20, nil - case ProtectionProfileAeadAes128Gcm, ProtectionProfileAeadAes256Gcm: - return 0, nil - default: - return 0, fmt.Errorf("%w: %#v", errNoSuchSRTPProfile, p) - } -} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/.gitignore b/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v3/.gitignore similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/.gitignore rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v3/.gitignore diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/.golangci.yml b/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v3/.golangci.yml similarity index 92% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/.golangci.yml rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v3/.golangci.yml index 48696f16b..a3235bec2 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/.golangci.yml +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v3/.golangci.yml @@ -1,6 +1,13 @@ +# SPDX-FileCopyrightText: 2023 The Pion community +# SPDX-License-Identifier: MIT + +run: + timeout: 5m + linters-settings: govet: - check-shadowing: true + enable: + - shadow misspell: locale: US exhaustive: @@ -10,7 +17,14 @@ linters-settings: modules: - github.com/pkg/errors: recommendations: - - errors + - errors + forbidigo: + forbid: + - ^fmt.Print(f|ln)?$ + - ^log.(Panic|Fatal|Print)(f|ln)?$ + - ^os.Exit$ + - ^panic$ + - ^print(ln)?$ linters: enable: @@ -19,7 +33,6 @@ linters: - bodyclose # checks whether HTTP response body is closed successfully - contextcheck # check the function whether use a non-inherited context - decorder # check declaration order and count of types, constants, variables and functions - - depguard # Go linter that checks if package imports are in a list of acceptable packages - dogsled # Checks assignments with too many blank identifiers (e.g. x, _, _, _, := f()) - dupl # Tool for code clone detection - durationcheck # check for two durations multiplied together @@ -29,6 +42,7 @@ linters: - errorlint # errorlint is a linter for that can be used to find code that will cause problems with the error wrapping scheme introduced in Go 1.13. - exhaustive # check exhaustiveness of enum switch statements - exportloopref # checks for pointers to enclosing loop variables + - forbidigo # Forbids identifiers - forcetypeassert # finds forced type assertions - gci # Gci control golang package import order and make it always deterministic. - gochecknoglobals # Checks that no globals are present in Go code @@ -37,7 +51,7 @@ linters: - goconst # Finds repeated strings that could be replaced by a constant - gocritic # The most opinionated Go source code linter - godox # Tool for detection of FIXME, TODO and other comment keywords - - goerr113 # Golang linter to check the errors handling expressions + - err113 # Golang linter to check the errors handling expressions - gofmt # Gofmt checks whether code was gofmt-ed. By default this tool runs with -s option to check for code simplification - gofumpt # Gofumpt checks whether code was gofumpt-ed. - goheader # Checks is file header matches to pattern @@ -52,7 +66,6 @@ linters: - importas # Enforces consistent import aliases - ineffassign # Detects when assignments to existing variables are not used - misspell # Finds commonly misspelled English words in comments - - nakedret # Finds naked returns in functions greater than a specified function length - nilerr # Finds the code that returns nil even if it checks that the error is not nil. - nilnil # Checks that there is no simultaneous return of `nil` error and an invalid value. - noctx # noctx finds sending http request without context.Context @@ -70,20 +83,18 @@ linters: - wastedassign # wastedassign finds wasted assignment statements - whitespace # Tool for detection of leading and trailing whitespace disable: + - depguard # Go linter that checks if package imports are in a list of acceptable packages - containedctx # containedctx is a linter that detects struct contained context.Context field - cyclop # checks function and package cyclomatic complexity - - exhaustivestruct # Checks if all struct's fields are initialized - - forbidigo # Forbids identifiers - funlen # Tool for detection of long functions - gocyclo # Computes and checks the cyclomatic complexity of functions - godot # Check if comments end in a period - gomnd # An analyzer to detect magic numbers. - - ifshort # Checks that your code uses short syntax for if-statements whenever possible - ireturn # Accept Interfaces, Return Concrete Types - lll # Reports long lines - maintidx # maintidx measures the maintainability index of each function. - makezero # Finds slice declarations with non-zero initial length - - maligned # Tool to detect Go structs that would take less memory if their fields were sorted + - nakedret # Finds naked returns in functions greater than a specified function length - nestif # Reports deeply nested if statements - nlreturn # nlreturn checks for a new line before return and branch statements to increase code clarity - nolintlint # Reports ill-formed or insufficient nolint directives @@ -100,17 +111,15 @@ linters: issues: exclude-use-default: false + exclude-dirs-use-default: false exclude-rules: - # Allow complex tests, better to be self contained - - path: _test\.go + # Allow complex tests and examples, better to be self contained + - path: (examples|main\.go|_test\.go) linters: + - forbidigo - gocognit - # Allow complex main function in examples - - path: examples - text: "of func `main` is high" + # Allow forbidden identifiers in CLI commands + - path: cmd linters: - - gocognit - -run: - skip-dirs-use-default: false + - forbidigo diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v3/.goreleaser.yml b/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v3/.goreleaser.yml new file mode 100644 index 000000000..30093e9d6 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v3/.goreleaser.yml @@ -0,0 +1,5 @@ +# SPDX-FileCopyrightText: 2023 The Pion community +# SPDX-License-Identifier: MIT + +builds: +- skip: true diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/LICENSE b/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v3/LICENSE similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/LICENSE rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v3/LICENSE diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/README.md b/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v3/README.md similarity index 97% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/README.md rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v3/README.md index d0e94e7a9..d6fdbd0d3 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/README.md +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v3/README.md @@ -29,7 +29,7 @@ We are always looking to support **your projects**. Please reach out if you have If you need commercial support or don't want to use public methods you can contact us at [team@pion.ly](mailto:team@pion.ly) ### Contributing -Check out the [contributing wiki](https://github.com/pion/webrtc/wiki/Contributing) to join the group of amazing people making this project possible: [AUTHORS.txt](./AUTHORS.txt) +Check out the [contributing wiki](https://github.com/pion/webrtc/wiki/Contributing) to join the group of amazing people making this project possible ### License MIT License - see [LICENSE](LICENSE) for full text diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/codecov.yml b/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v3/codecov.yml similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/codecov.yml rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v3/codecov.yml diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/context.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v3/context.go similarity index 63% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/context.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v3/context.go index 27da02cfd..cb2ed56a7 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/context.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v3/context.go @@ -4,9 +4,10 @@ package srtp import ( + "bytes" "fmt" - "github.com/pion/transport/v2/replaydetector" + "github.com/pion/transport/v3/replaydetector" ) const ( @@ -56,6 +57,14 @@ type Context struct { newSRTCPReplayDetector func() replaydetector.ReplayDetector newSRTPReplayDetector func() replaydetector.ReplayDetector + + profile ProtectionProfile + + sendMKI []byte // Master Key Identifier used for encrypting RTP/RTCP packets. Set to nil if MKI is not enabled. + mkis map[string]srtpCipher // Master Key Identifier to cipher mapping. Used for decrypting packets. Empty if MKI is not enabled. + + encryptSRTP bool + encryptSRTCP bool } // CreateContext creates a new SRTP Context. @@ -66,43 +75,19 @@ type Context struct { // // decCtx, err := srtp.CreateContext(key, salt, profile, srtp.SRTPReplayProtection(256)) func CreateContext(masterKey, masterSalt []byte, profile ProtectionProfile, opts ...ContextOption) (c *Context, err error) { - keyLen, err := profile.keyLen() - if err != nil { - return nil, err - } - - saltLen, err := profile.saltLen() - if err != nil { - return nil, err - } - - if masterKeyLen := len(masterKey); masterKeyLen != keyLen { - return c, fmt.Errorf("%w expected(%d) actual(%d)", errShortSrtpMasterKey, masterKey, keyLen) - } else if masterSaltLen := len(masterSalt); masterSaltLen != saltLen { - return c, fmt.Errorf("%w expected(%d) actual(%d)", errShortSrtpMasterSalt, saltLen, masterSaltLen) - } - c = &Context{ srtpSSRCStates: map[uint32]*srtpSSRCState{}, srtcpSSRCStates: map[uint32]*srtcpSSRCState{}, - } - - switch profile { - case ProtectionProfileAeadAes128Gcm, ProtectionProfileAeadAes256Gcm: - c.cipher, err = newSrtpCipherAeadAesGcm(profile, masterKey, masterSalt) - case ProtectionProfileAes128CmHmacSha1_32, ProtectionProfileAes128CmHmacSha1_80: - c.cipher, err = newSrtpCipherAesCmHmacSha1(profile, masterKey, masterSalt) - default: - return nil, fmt.Errorf("%w: %#v", errNoSuchSRTPProfile, profile) - } - if err != nil { - return nil, err + profile: profile, + mkis: map[string]srtpCipher{}, } for _, o := range append( []ContextOption{ // Default options SRTPNoReplayProtection(), SRTCPNoReplayProtection(), + SRTPEncryption(), + SRTCPEncryption(), }, opts..., // User specified options ) { @@ -111,9 +96,93 @@ func CreateContext(masterKey, masterSalt []byte, profile ProtectionProfile, opts } } + c.cipher, err = c.createCipher(c.sendMKI, masterKey, masterSalt, c.encryptSRTP, c.encryptSRTCP) + if err != nil { + return nil, err + } + if len(c.sendMKI) != 0 { + c.mkis[string(c.sendMKI)] = c.cipher + } + return c, nil } +// AddCipherForMKI adds new MKI with associated masker key and salt. Context must be created with MasterKeyIndicator option +// to enable MKI support. MKI must be unique and have the same length as the one used for creating Context. +// Operation is not thread-safe, you need to provide synchronization with decrypting packets. +func (c *Context) AddCipherForMKI(mki, masterKey, masterSalt []byte) error { + if len(c.mkis) == 0 { + return errMKIIsNotEnabled + } + if len(mki) == 0 || len(mki) != len(c.sendMKI) { + return errInvalidMKILength + } + if _, ok := c.mkis[string(mki)]; ok { + return errMKIAlreadyInUse + } + + cipher, err := c.createCipher(mki, masterKey, masterSalt, c.encryptSRTP, c.encryptSRTCP) + if err != nil { + return err + } + c.mkis[string(mki)] = cipher + return nil +} + +func (c *Context) createCipher(mki, masterKey, masterSalt []byte, encryptSRTP, encryptSRTCP bool) (srtpCipher, error) { + keyLen, err := c.profile.KeyLen() + if err != nil { + return nil, err + } + + saltLen, err := c.profile.SaltLen() + if err != nil { + return nil, err + } + + if masterKeyLen := len(masterKey); masterKeyLen != keyLen { + return nil, fmt.Errorf("%w expected(%d) actual(%d)", errShortSrtpMasterKey, masterKey, keyLen) + } else if masterSaltLen := len(masterSalt); masterSaltLen != saltLen { + return nil, fmt.Errorf("%w expected(%d) actual(%d)", errShortSrtpMasterSalt, saltLen, masterSaltLen) + } + + switch c.profile { + case ProtectionProfileAeadAes128Gcm, ProtectionProfileAeadAes256Gcm: + return newSrtpCipherAeadAesGcm(c.profile, masterKey, masterSalt, mki, encryptSRTP, encryptSRTCP) + case ProtectionProfileAes128CmHmacSha1_32, ProtectionProfileAes128CmHmacSha1_80, ProtectionProfileAes256CmHmacSha1_32, ProtectionProfileAes256CmHmacSha1_80: + return newSrtpCipherAesCmHmacSha1(c.profile, masterKey, masterSalt, mki, encryptSRTP, encryptSRTCP) + case ProtectionProfileNullHmacSha1_32, ProtectionProfileNullHmacSha1_80: + return newSrtpCipherAesCmHmacSha1(c.profile, masterKey, masterSalt, mki, false, false) + default: + return nil, fmt.Errorf("%w: %#v", errNoSuchSRTPProfile, c.profile) + } +} + +// RemoveMKI removes one of MKIs. You cannot remove last MKI and one used for encrypting RTP/RTCP packets. +// Operation is not thread-safe, you need to provide synchronization with decrypting packets. +func (c *Context) RemoveMKI(mki []byte) error { + if _, ok := c.mkis[string(mki)]; !ok { + return ErrMKINotFound + } + if bytes.Equal(mki, c.sendMKI) { + return errMKIAlreadyInUse + } + delete(c.mkis, string(mki)) + return nil +} + +// SetSendMKI switches MKI and cipher used for encrypting RTP/RTCP packets. +// Operation is not thread-safe, you need to provide synchronization with encrypting packets. +func (c *Context) SetSendMKI(mki []byte) error { + cipher, ok := c.mkis[string(mki)] + if !ok { + return ErrMKINotFound + } + c.sendMKI = mki + c.cipher = cipher + return nil +} + // https://tools.ietf.org/html/rfc3550#appendix-A.1 func (s *srtpSSRCState) nextRolloverCount(sequenceNumber uint16) (roc uint32, diff int32, overflow bool) { seq := int32(sequenceNumber) diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/crypto.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v3/crypto.go similarity index 68% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/crypto.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v3/crypto.go index 9696e8f2c..3f1913017 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/crypto.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v3/crypto.go @@ -5,8 +5,9 @@ package srtp import ( "crypto/cipher" + "sync" - "github.com/pion/transport/v2/utils/xor" + "github.com/pion/transport/v3/utils/xor" ) // incrementCTR increments a big-endian integer of arbitrary size. @@ -19,6 +20,12 @@ func incrementCTR(ctr []byte) { } } +var xorBufferPool = sync.Pool{ // nolint:gochecknoglobals + New: func() interface{} { + return make([]byte, 1500) + }, +} + // xorBytesCTR performs CTR encryption and decryption. // It is equivalent to cipher.NewCTR followed by XORKeyStream. func xorBytesCTR(block cipher.Block, iv []byte, dst, src []byte) error { @@ -26,10 +33,17 @@ func xorBytesCTR(block cipher.Block, iv []byte, dst, src []byte) error { return errBadIVLength } - ctr := make([]byte, len(iv)) + xorBuf := xorBufferPool.Get() + defer xorBufferPool.Put(xorBuf) + buffer, ok := xorBuf.([]byte) + if !ok { + return errFailedTypeAssertion + } + + ctr := buffer[:len(iv)] copy(ctr, iv) bs := block.BlockSize() - stream := make([]byte, bs) + stream := buffer[len(iv) : len(iv)+bs] i := 0 for i < len(src) { diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/errors.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v3/errors.go similarity index 74% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/errors.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v3/errors.go index 5b1751d30..c22653f0b 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/errors.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v3/errors.go @@ -9,6 +9,11 @@ import ( ) var ( + // ErrFailedToVerifyAuthTag is returned when decryption fails due to invalid authentication tag + ErrFailedToVerifyAuthTag = errors.New("failed to verify auth tag") + // ErrMKINotFound is returned when decryption fails due to unknown MKI value in packet + ErrMKINotFound = errors.New("MKI not found") + errDuplicated = errors.New("duplicated packet") errShortSrtpMasterKey = errors.New("SRTP master key is not long enough") errShortSrtpMasterSalt = errors.New("SRTP master salt is not long enough") @@ -17,12 +22,15 @@ var ( errExporterWrongLabel = errors.New("exporter called with wrong label") errNoConfig = errors.New("no config provided") errNoConn = errors.New("no conn provided") - errFailedToVerifyAuthTag = errors.New("failed to verify auth tag") - errTooShortRTCP = errors.New("packet is too short to be rtcp packet") + errTooShortRTP = errors.New("packet is too short to be RTP packet") + errTooShortRTCP = errors.New("packet is too short to be RTCP packet") errPayloadDiffers = errors.New("payload differs") errStartedChannelUsedIncorrectly = errors.New("started channel used incorrectly, should only be closed") errBadIVLength = errors.New("bad iv length in xorBytesCTR") errExceededMaxPackets = errors.New("exceeded the maximum number of packets") + errMKIAlreadyInUse = errors.New("MKI already in use") + errMKIIsNotEnabled = errors.New("MKI is not enabled") + errInvalidMKILength = errors.New("invalid MKI length") errStreamNotInited = errors.New("stream has not been inited, unable to close") errStreamAlreadyClosed = errors.New("stream is already closed") diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/key_derivation.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v3/key_derivation.go similarity index 91% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/key_derivation.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v3/key_derivation.go index 05f0f29fa..f192fafcc 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/key_derivation.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v3/key_derivation.go @@ -19,7 +19,6 @@ func aesCmKeyDerivation(label byte, masterKey, masterSalt []byte, indexOverKdr i // concatenation of the encryption key label 0x00 with (index DIV kdr), // - index is 'rollover count' and DIV is 'divided by' - nMasterKey := len(masterKey) nMasterSalt := len(masterSalt) prfIn := make([]byte, 16) @@ -33,11 +32,12 @@ func aesCmKeyDerivation(label byte, masterKey, masterSalt []byte, indexOverKdr i return nil, err } - out := make([]byte, ((outLen+nMasterKey)/nMasterKey)*nMasterKey) + nBlockSize := block.BlockSize() + out := make([]byte, ((outLen+nBlockSize-1)/nBlockSize)*nBlockSize) var i uint16 - for n := 0; n < outLen; n += block.BlockSize() { + for n := 0; n < outLen; n += nBlockSize { binary.BigEndian.PutUint16(prfIn[len(prfIn)-2:], i) - block.Encrypt(out[n:n+nMasterKey], prfIn) + block.Encrypt(out[n:n+nBlockSize], prfIn) i++ } return out[:outLen], nil diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/keying.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v3/keying.go similarity index 95% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/keying.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v3/keying.go index c5977c398..617f4d71c 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/keying.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v3/keying.go @@ -14,12 +14,12 @@ type KeyingMaterialExporter interface { // extracting them from DTLS. This behavior is defined in RFC5764: // https://tools.ietf.org/html/rfc5764 func (c *Config) ExtractSessionKeysFromDTLS(exporter KeyingMaterialExporter, isClient bool) error { - keyLen, err := c.Profile.keyLen() + keyLen, err := c.Profile.KeyLen() if err != nil { return err } - saltLen, err := c.Profile.saltLen() + saltLen, err := c.Profile.SaltLen() if err != nil { return err } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v3/option.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v3/option.go new file mode 100644 index 000000000..dac0bcf1d --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v3/option.go @@ -0,0 +1,120 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + +package srtp + +import ( + "github.com/pion/transport/v3/replaydetector" +) + +// ContextOption represents option of Context using the functional options pattern. +type ContextOption func(*Context) error + +// SRTPReplayProtection sets SRTP replay protection window size. +func SRTPReplayProtection(windowSize uint) ContextOption { // nolint:revive + return func(c *Context) error { + c.newSRTPReplayDetector = func() replaydetector.ReplayDetector { + return replaydetector.New(windowSize, maxROC<<16|maxSequenceNumber) + } + return nil + } +} + +// SRTCPReplayProtection sets SRTCP replay protection window size. +func SRTCPReplayProtection(windowSize uint) ContextOption { + return func(c *Context) error { + c.newSRTCPReplayDetector = func() replaydetector.ReplayDetector { + return replaydetector.New(windowSize, maxSRTCPIndex) + } + return nil + } +} + +// SRTPNoReplayProtection disables SRTP replay protection. +func SRTPNoReplayProtection() ContextOption { // nolint:revive + return func(c *Context) error { + c.newSRTPReplayDetector = func() replaydetector.ReplayDetector { + return &nopReplayDetector{} + } + return nil + } +} + +// SRTCPNoReplayProtection disables SRTCP replay protection. +func SRTCPNoReplayProtection() ContextOption { + return func(c *Context) error { + c.newSRTCPReplayDetector = func() replaydetector.ReplayDetector { + return &nopReplayDetector{} + } + return nil + } +} + +// SRTPReplayDetectorFactory sets custom SRTP replay detector. +func SRTPReplayDetectorFactory(fn func() replaydetector.ReplayDetector) ContextOption { // nolint:revive + return func(c *Context) error { + c.newSRTPReplayDetector = fn + return nil + } +} + +// SRTCPReplayDetectorFactory sets custom SRTCP replay detector. +func SRTCPReplayDetectorFactory(fn func() replaydetector.ReplayDetector) ContextOption { + return func(c *Context) error { + c.newSRTCPReplayDetector = fn + return nil + } +} + +type nopReplayDetector struct{} + +func (s *nopReplayDetector) Check(uint64) (func() bool, bool) { + return func() bool { return true }, true +} + +// MasterKeyIndicator sets RTP/RTCP MKI for the initial master key. Array passed as an argument will be +// copied as-is to encrypted SRTP/SRTCP packets, so it must be of proper length and in Big Endian format. +// All MKIs added later using Context.AddCipherForMKI must have the same length as the one used here. +func MasterKeyIndicator(mki []byte) ContextOption { + return func(c *Context) error { + if len(mki) > 0 { + c.sendMKI = make([]byte, len(mki)) + copy(c.sendMKI, mki) + } + return nil + } +} + +// SRTPEncryption enables SRTP encryption. +func SRTPEncryption() ContextOption { // nolint:revive + return func(c *Context) error { + c.encryptSRTP = true + return nil + } +} + +// SRTPNoEncryption disables SRTP encryption. This option is useful when you want to use NullCipher for SRTP and keep authentication only. +// It simplifies debugging and testing, but it is not recommended for production use. +func SRTPNoEncryption() ContextOption { // nolint:revive + return func(c *Context) error { + c.encryptSRTP = false + return nil + } +} + +// SRTCPEncryption enables SRTCP encryption. +func SRTCPEncryption() ContextOption { + return func(c *Context) error { + c.encryptSRTCP = true + return nil + } +} + +// SRTCPNoEncryption disables SRTCP encryption. This option is useful when you want to use NullCipher for SRTCP and keep authentication only. +// It simplifies debugging and testing, but it is not recommended for production use. +func SRTCPNoEncryption() ContextOption { + return func(c *Context) error { + c.encryptSRTCP = false + return nil + } +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v3/protection_profile.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v3/protection_profile.go new file mode 100644 index 000000000..9384bf8f9 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v3/protection_profile.go @@ -0,0 +1,128 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + +package srtp + +import "fmt" + +// ProtectionProfile specifies Cipher and AuthTag details, similar to TLS cipher suite +type ProtectionProfile uint16 + +// Supported protection profiles +// See https://www.iana.org/assignments/srtp-protection/srtp-protection.xhtml +// +// AES128_CM_HMAC_SHA1_80 and AES128_CM_HMAC_SHA1_32 are valid SRTP profiles, but they do not have an DTLS-SRTP Protection Profiles ID assigned +// in RFC 5764. They were in earlier draft of this RFC: https://datatracker.ietf.org/doc/html/draft-ietf-avt-dtls-srtp-03#section-4.1.2 +// Their IDs are now marked as reserved in the IANA registry. Despite this Chrome supports them: +// https://chromium.googlesource.com/chromium/deps/libsrtp/+/84122798bb16927b1e676bd4f938a6e48e5bf2fe/srtp/include/srtp.h#694 +// +// Null profiles disable encryption, they are used for debugging and testing. They are not recommended for production use. +// Use of them is equivalent to using ProtectionProfileAes128CmHmacSha1_NN profile with SRTPNoEncryption and SRTCPNoEncryption options. +const ( + ProtectionProfileAes128CmHmacSha1_80 ProtectionProfile = 0x0001 + ProtectionProfileAes128CmHmacSha1_32 ProtectionProfile = 0x0002 + ProtectionProfileAes256CmHmacSha1_80 ProtectionProfile = 0x0003 + ProtectionProfileAes256CmHmacSha1_32 ProtectionProfile = 0x0004 + ProtectionProfileNullHmacSha1_80 ProtectionProfile = 0x0005 + ProtectionProfileNullHmacSha1_32 ProtectionProfile = 0x0006 + ProtectionProfileAeadAes128Gcm ProtectionProfile = 0x0007 + ProtectionProfileAeadAes256Gcm ProtectionProfile = 0x0008 +) + +// KeyLen returns length of encryption key in bytes. For all profiles except NullHmacSha1_32 and NullHmacSha1_80 is is also the length of the session key. +func (p ProtectionProfile) KeyLen() (int, error) { + switch p { + case ProtectionProfileAes128CmHmacSha1_32, ProtectionProfileAes128CmHmacSha1_80, ProtectionProfileAeadAes128Gcm, ProtectionProfileNullHmacSha1_32, ProtectionProfileNullHmacSha1_80: + return 16, nil + case ProtectionProfileAeadAes256Gcm, ProtectionProfileAes256CmHmacSha1_32, ProtectionProfileAes256CmHmacSha1_80: + return 32, nil + default: + return 0, fmt.Errorf("%w: %#v", errNoSuchSRTPProfile, p) + } +} + +// SaltLen returns length of salt key in bytes. For all profiles except NullHmacSha1_32 and NullHmacSha1_80 is is also the length of the session salt. +func (p ProtectionProfile) SaltLen() (int, error) { + switch p { + case ProtectionProfileAes128CmHmacSha1_32, ProtectionProfileAes128CmHmacSha1_80, ProtectionProfileAes256CmHmacSha1_32, ProtectionProfileAes256CmHmacSha1_80, ProtectionProfileNullHmacSha1_32, ProtectionProfileNullHmacSha1_80: + return 14, nil + case ProtectionProfileAeadAes128Gcm, ProtectionProfileAeadAes256Gcm: + return 12, nil + default: + return 0, fmt.Errorf("%w: %#v", errNoSuchSRTPProfile, p) + } +} + +// AuthTagRTPLen returns length of RTP authentication tag in bytes for AES protection profiles. For AEAD ones it returns zero. +func (p ProtectionProfile) AuthTagRTPLen() (int, error) { + switch p { + case ProtectionProfileAes128CmHmacSha1_80, ProtectionProfileAes256CmHmacSha1_80, ProtectionProfileNullHmacSha1_80: + return 10, nil + case ProtectionProfileAes128CmHmacSha1_32, ProtectionProfileAes256CmHmacSha1_32, ProtectionProfileNullHmacSha1_32: + return 4, nil + case ProtectionProfileAeadAes128Gcm, ProtectionProfileAeadAes256Gcm: + return 0, nil + default: + return 0, fmt.Errorf("%w: %#v", errNoSuchSRTPProfile, p) + } +} + +// AuthTagRTCPLen returns length of RTCP authentication tag in bytes for AES protection profiles. For AEAD ones it returns zero. +func (p ProtectionProfile) AuthTagRTCPLen() (int, error) { + switch p { + case ProtectionProfileAes128CmHmacSha1_32, ProtectionProfileAes128CmHmacSha1_80, ProtectionProfileAes256CmHmacSha1_32, ProtectionProfileAes256CmHmacSha1_80, ProtectionProfileNullHmacSha1_32, ProtectionProfileNullHmacSha1_80: + return 10, nil + case ProtectionProfileAeadAes128Gcm, ProtectionProfileAeadAes256Gcm: + return 0, nil + default: + return 0, fmt.Errorf("%w: %#v", errNoSuchSRTPProfile, p) + } +} + +// AEADAuthTagLen returns length of authentication tag in bytes for AEAD protection profiles. For AES ones it returns zero. +func (p ProtectionProfile) AEADAuthTagLen() (int, error) { + switch p { + case ProtectionProfileAes128CmHmacSha1_32, ProtectionProfileAes128CmHmacSha1_80, ProtectionProfileAes256CmHmacSha1_32, ProtectionProfileAes256CmHmacSha1_80, ProtectionProfileNullHmacSha1_32, ProtectionProfileNullHmacSha1_80: + return 0, nil + case ProtectionProfileAeadAes128Gcm, ProtectionProfileAeadAes256Gcm: + return 16, nil + default: + return 0, fmt.Errorf("%w: %#v", errNoSuchSRTPProfile, p) + } +} + +// AuthKeyLen returns length of authentication key in bytes for AES protection profiles. For AEAD ones it returns zero. +func (p ProtectionProfile) AuthKeyLen() (int, error) { + switch p { + case ProtectionProfileAes128CmHmacSha1_32, ProtectionProfileAes128CmHmacSha1_80, ProtectionProfileAes256CmHmacSha1_32, ProtectionProfileAes256CmHmacSha1_80, ProtectionProfileNullHmacSha1_32, ProtectionProfileNullHmacSha1_80: + return 20, nil + case ProtectionProfileAeadAes128Gcm, ProtectionProfileAeadAes256Gcm: + return 0, nil + default: + return 0, fmt.Errorf("%w: %#v", errNoSuchSRTPProfile, p) + } +} + +// String returns the name of the protection profile. +func (p ProtectionProfile) String() string { + switch p { + case ProtectionProfileAes128CmHmacSha1_80: + return "SRTP_AES128_CM_HMAC_SHA1_80" + case ProtectionProfileAes128CmHmacSha1_32: + return "SRTP_AES128_CM_HMAC_SHA1_32" + case ProtectionProfileAes256CmHmacSha1_80: + return "SRTP_AES256_CM_HMAC_SHA1_80" + case ProtectionProfileAes256CmHmacSha1_32: + return "SRTP_AES256_CM_HMAC_SHA1_32" + case ProtectionProfileAeadAes128Gcm: + return "SRTP_AEAD_AES_128_GCM" + case ProtectionProfileAeadAes256Gcm: + return "SRTP_AEAD_AES_256_GCM" + case ProtectionProfileNullHmacSha1_80: + return "SRTP_NULL_HMAC_SHA1_80" + case ProtectionProfileNullHmacSha1_32: + return "SRTP_NULL_HMAC_SHA1_32" + default: + return fmt.Sprintf("Unknown SRTP profile: %#v", p) + } +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/renovate.json b/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v3/renovate.json similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/renovate.json rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v3/renovate.json diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/session.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v3/session.go similarity index 98% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/session.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v3/session.go index 2e1f4fe3f..cc4f60095 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/session.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v3/session.go @@ -11,7 +11,7 @@ import ( "time" "github.com/pion/logging" - "github.com/pion/transport/v2/packetio" + "github.com/pion/transport/v3/packetio" ) type streamSession interface { diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/session_srtcp.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v3/session_srtcp.go similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/session_srtcp.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v3/session_srtcp.go diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/session_srtp.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v3/session_srtp.go similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/session_srtp.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v3/session_srtp.go diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/srtcp.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v3/srtcp.go similarity index 76% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/srtcp.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v3/srtcp.go index 7fd0746bd..6d1a1c1d9 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/srtcp.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v3/srtcp.go @@ -12,23 +12,22 @@ import ( const maxSRTCPIndex = 0x7FFFFFFF +const srtcpHeaderSize = 8 + func (c *Context) decryptRTCP(dst, encrypted []byte) ([]byte, error) { - out := allocateIfMismatch(dst, encrypted) - - authTagLen, err := c.cipher.rtcpAuthTagLen() + authTagLen, err := c.cipher.AuthTagRTCPLen() if err != nil { return nil, err } - aeadAuthTagLen, err := c.cipher.aeadAuthTagLen() + aeadAuthTagLen, err := c.cipher.AEADAuthTagLen() if err != nil { return nil, err } - tailOffset := len(encrypted) - (authTagLen + srtcpIndexSize) + mkiLen := len(c.sendMKI) - if tailOffset < aeadAuthTagLen { + // Verify that encrypted packet is long enough + if len(encrypted) < (srtcpHeaderSize + aeadAuthTagLen + srtcpIndexSize + mkiLen + authTagLen) { return nil, fmt.Errorf("%w: %d", errTooShortRTCP, len(encrypted)) - } else if isEncrypted := encrypted[tailOffset] >> 7; isEncrypted == 0 { - return out, nil } index := c.cipher.getRTCPIndex(encrypted) @@ -40,7 +39,19 @@ func (c *Context) decryptRTCP(dst, encrypted []byte) ([]byte, error) { return nil, &duplicatedError{Proto: "srtcp", SSRC: ssrc, Index: index} } - out, err = c.cipher.decryptRTCP(out, encrypted, index, ssrc) + cipher := c.cipher + if len(c.mkis) > 0 { + // Find cipher for MKI + actualMKI := c.cipher.getMKI(encrypted, false) + cipher, ok = c.mkis[string(actualMKI)] + if !ok { + return nil, ErrMKINotFound + } + } + + out := allocateIfMismatch(dst, encrypted) + + out, err = cipher.decryptRTCP(out, encrypted, index, ssrc) if err != nil { return nil, err } @@ -63,6 +74,10 @@ func (c *Context) DecryptRTCP(dst, encrypted []byte, header *rtcp.Header) ([]byt } func (c *Context) encryptRTCP(dst, decrypted []byte) ([]byte, error) { + if len(decrypted) < srtcpHeaderSize { + return nil, fmt.Errorf("%w: %d", errTooShortRTCP, len(decrypted)) + } + ssrc := binary.BigEndian.Uint32(decrypted[4:]) s := c.getSRTCPSSRCState(ssrc) diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/srtp.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v3/srtp.go similarity index 79% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/srtp.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v3/srtp.go index 42c71be01..56828bcf4 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/srtp.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v3/srtp.go @@ -5,10 +5,27 @@ package srtp import ( + "fmt" + "github.com/pion/rtp" ) func (c *Context) decryptRTP(dst, ciphertext []byte, header *rtp.Header, headerLen int) ([]byte, error) { + authTagLen, err := c.cipher.AuthTagRTPLen() + if err != nil { + return nil, err + } + aeadAuthTagLen, err := c.cipher.AEADAuthTagLen() + if err != nil { + return nil, err + } + mkiLen := len(c.sendMKI) + + // Verify that encrypted packet is long enough + if len(ciphertext) < (headerLen + aeadAuthTagLen + mkiLen + authTagLen) { + return nil, fmt.Errorf("%w: %d", errTooShortRTP, len(ciphertext)) + } + s := c.getSRTPSSRCState(header.SSRC) roc, diff, _ := s.nextRolloverCount(header.SequenceNumber) @@ -21,13 +38,19 @@ func (c *Context) decryptRTP(dst, ciphertext []byte, header *rtp.Header, headerL } } - authTagLen, err := c.cipher.rtpAuthTagLen() - if err != nil { - return nil, err + cipher := c.cipher + if len(c.mkis) > 0 { + // Find cipher for MKI + actualMKI := c.cipher.getMKI(ciphertext, true) + cipher, ok = c.mkis[string(actualMKI)] + if !ok { + return nil, ErrMKINotFound + } } - dst = growBufferSize(dst, len(ciphertext)-authTagLen) - dst, err = c.cipher.decryptRTP(dst, ciphertext, header, headerLen, roc) + dst = growBufferSize(dst, len(ciphertext)-authTagLen-len(c.sendMKI)) + + dst, err = cipher.decryptRTP(dst, ciphertext, header, headerLen, roc) if err != nil { return nil, err } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/srtp_cipher.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v3/srtp_cipher.go similarity index 86% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/srtp_cipher.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v3/srtp_cipher.go index db501472f..da745e7cd 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/srtp_cipher.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v3/srtp_cipher.go @@ -8,14 +8,15 @@ import "github.com/pion/rtp" // cipher represents a implementation of one // of the SRTP Specific ciphers type srtpCipher interface { - // authTagLen returns auth key length of the cipher. + // AuthTagRTPLen/AuthTagRTCPLen return auth key length of the cipher. // See the note below. - rtpAuthTagLen() (int, error) - rtcpAuthTagLen() (int, error) - // aeadAuthTagLen returns AEAD auth key length of the cipher. + AuthTagRTPLen() (int, error) + AuthTagRTCPLen() (int, error) + // AEADAuthTagLen returns AEAD auth key length of the cipher. // See the note below. - aeadAuthTagLen() (int, error) + AEADAuthTagLen() (int, error) getRTCPIndex([]byte) uint32 + getMKI([]byte, bool) []byte encryptRTP([]byte, *rtp.Header, []byte, uint32) ([]byte, error) encryptRTCP([]byte, []byte, uint32, uint32) ([]byte, error) diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/srtp_cipher_aead_aes_gcm.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v3/srtp_cipher_aead_aes_gcm.go similarity index 57% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/srtp_cipher_aead_aes_gcm.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v3/srtp_cipher_aead_aes_gcm.go index 90643d92d..64f890fa9 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/srtp_cipher_aead_aes_gcm.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v3/srtp_cipher_aead_aes_gcm.go @@ -7,6 +7,7 @@ import ( "crypto/aes" "crypto/cipher" "encoding/binary" + "fmt" "github.com/pion/rtp" ) @@ -21,10 +22,18 @@ type srtpCipherAeadAesGcm struct { srtpCipher, srtcpCipher cipher.AEAD srtpSessionSalt, srtcpSessionSalt []byte + + mki []byte + + srtpEncrypted, srtcpEncrypted bool } -func newSrtpCipherAeadAesGcm(profile ProtectionProfile, masterKey, masterSalt []byte) (*srtpCipherAeadAesGcm, error) { - s := &srtpCipherAeadAesGcm{ProtectionProfile: profile} +func newSrtpCipherAeadAesGcm(profile ProtectionProfile, masterKey, masterSalt, mki []byte, encryptSRTP, encryptSRTCP bool) (*srtpCipherAeadAesGcm, error) { + s := &srtpCipherAeadAesGcm{ + ProtectionProfile: profile, + srtpEncrypted: encryptSRTP, + srtcpEncrypted: encryptSRTCP, + } srtpSessionKey, err := aesCmKeyDerivation(labelSRTPEncryption, masterKey, masterSalt, 0, len(masterKey)) if err != nil { @@ -62,16 +71,22 @@ func newSrtpCipherAeadAesGcm(profile ProtectionProfile, masterKey, masterSalt [] return nil, err } + mkiLen := len(mki) + if mkiLen > 0 { + s.mki = make([]byte, mkiLen) + copy(s.mki, mki) + } + return s, nil } func (s *srtpCipherAeadAesGcm) encryptRTP(dst []byte, header *rtp.Header, payload []byte, roc uint32) (ciphertext []byte, err error) { // Grow the given buffer to fit the output. - authTagLen, err := s.aeadAuthTagLen() + authTagLen, err := s.AEADAuthTagLen() if err != nil { return nil, err } - dst = growBufferSize(dst, header.MarshalSize()+len(payload)+authTagLen) + dst = growBufferSize(dst, header.MarshalSize()+len(payload)+authTagLen+len(s.mki)) n, err := header.MarshalTo(dst) if err != nil { @@ -79,29 +94,52 @@ func (s *srtpCipherAeadAesGcm) encryptRTP(dst []byte, header *rtp.Header, payloa } iv := s.rtpInitializationVector(header, roc) - s.srtpCipher.Seal(dst[n:n], iv[:], payload, dst[:n]) + if s.srtpEncrypted { + s.srtpCipher.Seal(dst[n:n], iv[:], payload, dst[:n]) + } else { + clearLen := n + len(payload) + copy(dst[n:], payload) + s.srtpCipher.Seal(dst[clearLen:clearLen], iv[:], nil, dst[:clearLen]) + } + + // Add MKI after the encrypted payload + if len(s.mki) > 0 { + copy(dst[len(dst)-len(s.mki):], s.mki) + } + return dst, nil } func (s *srtpCipherAeadAesGcm) decryptRTP(dst, ciphertext []byte, header *rtp.Header, headerLen int, roc uint32) ([]byte, error) { // Grow the given buffer to fit the output. - authTagLen, err := s.aeadAuthTagLen() + authTagLen, err := s.AEADAuthTagLen() if err != nil { return nil, err } - nDst := len(ciphertext) - authTagLen - if nDst < 0 { + nDst := len(ciphertext) - authTagLen - len(s.mki) + if nDst < headerLen { // Size of ciphertext is shorter than AEAD auth tag len. - return nil, errFailedToVerifyAuthTag + return nil, ErrFailedToVerifyAuthTag } dst = growBufferSize(dst, nDst) iv := s.rtpInitializationVector(header, roc) - if _, err := s.srtpCipher.Open( - dst[headerLen:headerLen], iv[:], ciphertext[headerLen:], ciphertext[:headerLen], - ); err != nil { - return nil, err + nEnd := len(ciphertext) - len(s.mki) + if s.srtpEncrypted { + if _, err := s.srtpCipher.Open( + dst[headerLen:headerLen], iv[:], ciphertext[headerLen:nEnd], ciphertext[:headerLen], + ); err != nil { + return nil, fmt.Errorf("%w: %w", ErrFailedToVerifyAuthTag, err) + } + } else { + nDataEnd := nEnd - authTagLen + if _, err := s.srtpCipher.Open( + nil, iv[:], ciphertext[nDataEnd:nEnd], ciphertext[:nDataEnd], + ); err != nil { + return nil, fmt.Errorf("%w: %w", ErrFailedToVerifyAuthTag, err) + } + copy(dst[headerLen:], ciphertext[headerLen:nDataEnd]) } copy(dst[:headerLen], ciphertext[:headerLen]) @@ -109,43 +147,71 @@ func (s *srtpCipherAeadAesGcm) decryptRTP(dst, ciphertext []byte, header *rtp.He } func (s *srtpCipherAeadAesGcm) encryptRTCP(dst, decrypted []byte, srtcpIndex uint32, ssrc uint32) ([]byte, error) { - authTagLen, err := s.aeadAuthTagLen() + authTagLen, err := s.AEADAuthTagLen() if err != nil { return nil, err } aadPos := len(decrypted) + authTagLen // Grow the given buffer to fit the output. - dst = growBufferSize(dst, aadPos+srtcpIndexSize) + dst = growBufferSize(dst, aadPos+srtcpIndexSize+len(s.mki)) iv := s.rtcpInitializationVector(srtcpIndex, ssrc) - aad := s.rtcpAdditionalAuthenticatedData(decrypted, srtcpIndex) + if s.srtcpEncrypted { + aad := s.rtcpAdditionalAuthenticatedData(decrypted, srtcpIndex) + copy(dst[:8], decrypted[:8]) + copy(dst[aadPos:aadPos+4], aad[8:12]) + s.srtcpCipher.Seal(dst[8:8], iv[:], decrypted[8:], aad[:]) + } else { + // Copy the packet unencrypted. + copy(dst, decrypted) + // Append the SRTCP index to the end of the packet - this will form the AAD. + binary.BigEndian.PutUint32(dst[len(decrypted):], srtcpIndex) + // Generate the authentication tag. + tag := make([]byte, authTagLen) + s.srtcpCipher.Seal(tag[0:0], iv[:], nil, dst[:len(decrypted)+4]) + // Copy index to the proper place. + copy(dst[aadPos:], dst[len(decrypted):len(decrypted)+4]) + // Copy the auth tag after RTCP payload. + copy(dst[len(decrypted):], tag) + } - s.srtcpCipher.Seal(dst[8:8], iv[:], decrypted[8:], aad[:]) - - copy(dst[:8], decrypted[:8]) - copy(dst[aadPos:aadPos+4], aad[8:12]) + copy(dst[aadPos+4:], s.mki) return dst, nil } func (s *srtpCipherAeadAesGcm) decryptRTCP(dst, encrypted []byte, srtcpIndex, ssrc uint32) ([]byte, error) { - aadPos := len(encrypted) - srtcpIndexSize + aadPos := len(encrypted) - srtcpIndexSize - len(s.mki) // Grow the given buffer to fit the output. - authTagLen, err := s.aeadAuthTagLen() + authTagLen, err := s.AEADAuthTagLen() if err != nil { return nil, err } nDst := aadPos - authTagLen if nDst < 0 { // Size of ciphertext is shorter than AEAD auth tag len. - return nil, errFailedToVerifyAuthTag + return nil, ErrFailedToVerifyAuthTag } dst = growBufferSize(dst, nDst) + isEncrypted := encrypted[aadPos]>>7 != 0 iv := s.rtcpInitializationVector(srtcpIndex, ssrc) - aad := s.rtcpAdditionalAuthenticatedData(encrypted, srtcpIndex) - - if _, err := s.srtcpCipher.Open(dst[8:8], iv[:], encrypted[8:aadPos], aad[:]); err != nil { - return nil, err + if isEncrypted { + aad := s.rtcpAdditionalAuthenticatedData(encrypted, srtcpIndex) + if _, err := s.srtcpCipher.Open(dst[8:8], iv[:], encrypted[8:aadPos], aad[:]); err != nil { + return nil, fmt.Errorf("%w: %w", ErrFailedToVerifyAuthTag, err) + } + } else { + // Prepare AAD for received packet. + dataEnd := aadPos - authTagLen + aad := make([]byte, dataEnd+4) + copy(aad, encrypted[:dataEnd]) + copy(aad[dataEnd:], encrypted[aadPos:aadPos+4]) + // Verify the auth tag. + if _, err := s.srtcpCipher.Open(nil, iv[:], encrypted[dataEnd:aadPos], aad); err != nil { + return nil, fmt.Errorf("%w: %w", ErrFailedToVerifyAuthTag, err) + } + // Copy the unencrypted payload. + copy(dst[8:], encrypted[8:dataEnd]) } copy(dst[:8], encrypted[:8]) @@ -205,5 +271,15 @@ func (s *srtpCipherAeadAesGcm) rtcpAdditionalAuthenticatedData(rtcpPacket []byte } func (s *srtpCipherAeadAesGcm) getRTCPIndex(in []byte) uint32 { - return binary.BigEndian.Uint32(in[len(in)-4:]) &^ (rtcpEncryptionFlag << 24) + return binary.BigEndian.Uint32(in[len(in)-len(s.mki)-4:]) &^ (rtcpEncryptionFlag << 24) +} + +func (s *srtpCipherAeadAesGcm) getMKI(in []byte, _ bool) []byte { + mkiLen := len(s.mki) + if mkiLen == 0 { + return nil + } + + tailOffset := len(in) - mkiLen + return in[tailOffset:] } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/srtp_cipher_aes_cm_hmac_sha1.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v3/srtp_cipher_aes_cm_hmac_sha1.go similarity index 65% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/srtp_cipher_aes_cm_hmac_sha1.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v3/srtp_cipher_aes_cm_hmac_sha1.go index d56e6afb1..aa673fa94 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/srtp_cipher_aes_cm_hmac_sha1.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v3/srtp_cipher_aes_cm_hmac_sha1.go @@ -21,14 +21,28 @@ type srtpCipherAesCmHmacSha1 struct { srtpSessionSalt []byte srtpSessionAuth hash.Hash srtpBlock cipher.Block + srtpEncrypted bool srtcpSessionSalt []byte srtcpSessionAuth hash.Hash srtcpBlock cipher.Block + srtcpEncrypted bool + + mki []byte } -func newSrtpCipherAesCmHmacSha1(profile ProtectionProfile, masterKey, masterSalt []byte) (*srtpCipherAesCmHmacSha1, error) { - s := &srtpCipherAesCmHmacSha1{ProtectionProfile: profile} +func newSrtpCipherAesCmHmacSha1(profile ProtectionProfile, masterKey, masterSalt, mki []byte, encryptSRTP, encryptSRTCP bool) (*srtpCipherAesCmHmacSha1, error) { + if profile == ProtectionProfileNullHmacSha1_80 || profile == ProtectionProfileNullHmacSha1_32 { + encryptSRTP = false + encryptSRTCP = false + } + + s := &srtpCipherAesCmHmacSha1{ + ProtectionProfile: profile, + srtpEncrypted: encryptSRTP, + srtcpEncrypted: encryptSRTCP, + } + srtpSessionKey, err := aesCmKeyDerivation(labelSRTPEncryption, masterKey, masterSalt, 0, len(masterKey)) if err != nil { return nil, err @@ -49,7 +63,7 @@ func newSrtpCipherAesCmHmacSha1(profile ProtectionProfile, masterKey, masterSalt return nil, err } - authKeyLen, err := profile.authKeyLen() + authKeyLen, err := profile.AuthKeyLen() if err != nil { return nil, err } @@ -66,16 +80,23 @@ func newSrtpCipherAesCmHmacSha1(profile ProtectionProfile, masterKey, masterSalt s.srtcpSessionAuth = hmac.New(sha1.New, srtcpSessionAuthTag) s.srtpSessionAuth = hmac.New(sha1.New, srtpSessionAuthTag) + + mkiLen := len(mki) + if mkiLen > 0 { + s.mki = make([]byte, mkiLen) + copy(s.mki, mki) + } + return s, nil } func (s *srtpCipherAesCmHmacSha1) encryptRTP(dst []byte, header *rtp.Header, payload []byte, roc uint32) (ciphertext []byte, err error) { // Grow the given buffer to fit the output. - authTagLen, err := s.rtpAuthTagLen() + authTagLen, err := s.AuthTagRTPLen() if err != nil { return nil, err } - dst = growBufferSize(dst, header.MarshalSize()+len(payload)+authTagLen) + dst = growBufferSize(dst, header.MarshalSize()+len(payload)+len(s.mki)+authTagLen) // Copy the header unencrypted. n, err := header.MarshalTo(dst) @@ -84,9 +105,13 @@ func (s *srtpCipherAesCmHmacSha1) encryptRTP(dst []byte, header *rtp.Header, pay } // Encrypt the payload - counter := generateCounter(header.SequenceNumber, roc, header.SSRC, s.srtpSessionSalt) - if err = xorBytesCTR(s.srtpBlock, counter[:], dst[n:], payload); err != nil { - return nil, err + if s.srtpEncrypted { + counter := generateCounter(header.SequenceNumber, roc, header.SSRC, s.srtpSessionSalt) + if err = xorBytesCTR(s.srtpBlock, counter[:], dst[n:], payload); err != nil { + return nil, err + } + } else { + copy(dst[n:], payload) } n += len(payload) @@ -96,6 +121,12 @@ func (s *srtpCipherAesCmHmacSha1) encryptRTP(dst []byte, header *rtp.Header, pay return nil, err } + // Append the MKI (if used) + if len(s.mki) > 0 { + copy(dst[n:], s.mki) + n += len(s.mki) + } + // Write the auth tag to the dest. copy(dst[n:], authTag) @@ -104,12 +135,14 @@ func (s *srtpCipherAesCmHmacSha1) encryptRTP(dst []byte, header *rtp.Header, pay func (s *srtpCipherAesCmHmacSha1) decryptRTP(dst, ciphertext []byte, header *rtp.Header, headerLen int, roc uint32) ([]byte, error) { // Split the auth tag and the cipher text into two parts. - authTagLen, err := s.rtpAuthTagLen() + authTagLen, err := s.AuthTagRTPLen() if err != nil { return nil, err } + + // Split the auth tag and the cipher text into two parts. actualTag := ciphertext[len(ciphertext)-authTagLen:] - ciphertext = ciphertext[:len(ciphertext)-authTagLen] + ciphertext = ciphertext[:len(ciphertext)-len(s.mki)-authTagLen] // Generate the auth tag we expect to see from the ciphertext. expectedTag, err := s.generateSrtpAuthTag(ciphertext, roc) @@ -120,61 +153,93 @@ func (s *srtpCipherAesCmHmacSha1) decryptRTP(dst, ciphertext []byte, header *rtp // See if the auth tag actually matches. // We use a constant time comparison to prevent timing attacks. if subtle.ConstantTimeCompare(actualTag, expectedTag) != 1 { - return nil, errFailedToVerifyAuthTag + return nil, ErrFailedToVerifyAuthTag } // Write the plaintext header to the destination buffer. copy(dst, ciphertext[:headerLen]) // Decrypt the ciphertext for the payload. - counter := generateCounter(header.SequenceNumber, roc, header.SSRC, s.srtpSessionSalt) - err = xorBytesCTR( - s.srtpBlock, counter[:], dst[headerLen:], ciphertext[headerLen:], - ) - return dst, err + if s.srtpEncrypted { + counter := generateCounter(header.SequenceNumber, roc, header.SSRC, s.srtpSessionSalt) + err = xorBytesCTR( + s.srtpBlock, counter[:], dst[headerLen:], ciphertext[headerLen:], + ) + if err != nil { + return nil, err + } + } else { + copy(dst[headerLen:], ciphertext[headerLen:]) + } + return dst, nil } func (s *srtpCipherAesCmHmacSha1) encryptRTCP(dst, decrypted []byte, srtcpIndex uint32, ssrc uint32) ([]byte, error) { dst = allocateIfMismatch(dst, decrypted) // Encrypt everything after header - counter := generateCounter(uint16(srtcpIndex&0xffff), srtcpIndex>>16, ssrc, s.srtcpSessionSalt) - if err := xorBytesCTR(s.srtcpBlock, counter[:], dst[8:], dst[8:]); err != nil { - return nil, err + if s.srtcpEncrypted { + counter := generateCounter(uint16(srtcpIndex&0xffff), srtcpIndex>>16, ssrc, s.srtcpSessionSalt) + if err := xorBytesCTR(s.srtcpBlock, counter[:], dst[8:], dst[8:]); err != nil { + return nil, err + } + + // Add SRTCP Index and set Encryption bit + dst = append(dst, make([]byte, 4)...) + binary.BigEndian.PutUint32(dst[len(dst)-4:], srtcpIndex) + dst[len(dst)-4] |= 0x80 + } else { + // Copy the decrypted payload as is + copy(dst[8:], decrypted[8:]) + + // Add SRTCP Index with Encryption bit cleared + dst = append(dst, make([]byte, 4)...) + binary.BigEndian.PutUint32(dst[len(dst)-4:], srtcpIndex) } - // Add SRTCP Index and set Encryption bit - dst = append(dst, make([]byte, 4)...) - binary.BigEndian.PutUint32(dst[len(dst)-4:], srtcpIndex) - dst[len(dst)-4] |= 0x80 - + // Generate the authentication tag authTag, err := s.generateSrtcpAuthTag(dst) if err != nil { return nil, err } + + // Include the MKI if provided + if len(s.mki) > 0 { + dst = append(dst, s.mki...) + } + + // Append the auth tag at the end of the buffer return append(dst, authTag...), nil } func (s *srtpCipherAesCmHmacSha1) decryptRTCP(out, encrypted []byte, index, ssrc uint32) ([]byte, error) { - authTagLen, err := s.rtcpAuthTagLen() + authTagLen, err := s.AuthTagRTCPLen() if err != nil { return nil, err } - tailOffset := len(encrypted) - (authTagLen + srtcpIndexSize) + tailOffset := len(encrypted) - (authTagLen + len(s.mki) + srtcpIndexSize) + if tailOffset < 8 { + return nil, errTooShortRTCP + } out = out[0:tailOffset] - expectedTag, err := s.generateSrtcpAuthTag(encrypted[:len(encrypted)-authTagLen]) + expectedTag, err := s.generateSrtcpAuthTag(encrypted[:len(encrypted)-len(s.mki)-authTagLen]) if err != nil { return nil, err } actualTag := encrypted[len(encrypted)-authTagLen:] if subtle.ConstantTimeCompare(actualTag, expectedTag) != 1 { - return nil, errFailedToVerifyAuthTag + return nil, ErrFailedToVerifyAuthTag } - counter := generateCounter(uint16(index&0xffff), index>>16, ssrc, s.srtcpSessionSalt) - err = xorBytesCTR(s.srtcpBlock, counter[:], out[8:], out[8:]) + isEncrypted := encrypted[tailOffset]>>7 != 0 + if isEncrypted { + counter := generateCounter(uint16(index&0xffff), index>>16, ssrc, s.srtcpSessionSalt) + err = xorBytesCTR(s.srtcpBlock, counter[:], out[8:], out[8:]) + } else { + copy(out[8:], encrypted[8:]) + } return out, err } @@ -210,7 +275,7 @@ func (s *srtpCipherAesCmHmacSha1) generateSrtpAuthTag(buf []byte, roc uint32) ([ } // Truncate the hash to the size indicated by the profile - authTagLen, err := s.rtpAuthTagLen() + authTagLen, err := s.AuthTagRTPLen() if err != nil { return nil, err } @@ -234,7 +299,7 @@ func (s *srtpCipherAesCmHmacSha1) generateSrtcpAuthTag(buf []byte) ([]byte, erro if _, err := s.srtcpSessionAuth.Write(buf); err != nil { return nil, err } - authTagLen, err := s.rtcpAuthTagLen() + authTagLen, err := s.AuthTagRTCPLen() if err != nil { return nil, err } @@ -243,8 +308,24 @@ func (s *srtpCipherAesCmHmacSha1) generateSrtcpAuthTag(buf []byte) ([]byte, erro } func (s *srtpCipherAesCmHmacSha1) getRTCPIndex(in []byte) uint32 { - authTagLen, _ := s.rtcpAuthTagLen() - tailOffset := len(in) - (authTagLen + srtcpIndexSize) + authTagLen, _ := s.AuthTagRTCPLen() + tailOffset := len(in) - (authTagLen + srtcpIndexSize + len(s.mki)) srtcpIndexBuffer := in[tailOffset : tailOffset+srtcpIndexSize] return binary.BigEndian.Uint32(srtcpIndexBuffer) &^ (1 << 31) } + +func (s *srtpCipherAesCmHmacSha1) getMKI(in []byte, rtp bool) []byte { + mkiLen := len(s.mki) + if mkiLen == 0 { + return nil + } + + var authTagLen int + if rtp { + authTagLen, _ = s.AuthTagRTPLen() + } else { + authTagLen, _ = s.AuthTagRTCPLen() + } + tailOffset := len(in) - (authTagLen + mkiLen) + return in[tailOffset : tailOffset+mkiLen] +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/stream.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v3/stream.go similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/stream.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v3/stream.go diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/stream_srtcp.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v3/stream_srtcp.go similarity index 98% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/stream_srtcp.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v3/stream_srtcp.go index 08d36dca5..dc71c40f3 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/stream_srtcp.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v3/stream_srtcp.go @@ -10,7 +10,7 @@ import ( "time" "github.com/pion/rtcp" - "github.com/pion/transport/v2/packetio" + "github.com/pion/transport/v3/packetio" ) // Limit the buffer size to 100KB diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/stream_srtp.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v3/stream_srtp.go similarity index 98% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/stream_srtp.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v3/stream_srtp.go index 858970082..cad0a38c1 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/stream_srtp.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v3/stream_srtp.go @@ -10,7 +10,7 @@ import ( "time" "github.com/pion/rtp" - "github.com/pion/transport/v2/packetio" + "github.com/pion/transport/v3/packetio" ) // Limit the buffer size to 1MB diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/util.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v3/util.go similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/util.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v3/util.go diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/AUTHORS.txt b/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/AUTHORS.txt deleted file mode 100644 index 3c3d9e00f..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/AUTHORS.txt +++ /dev/null @@ -1,40 +0,0 @@ -# Thank you to everyone that made Pion possible. If you are interested in contributing -# we would love to have you https://github.com/pion/webrtc/wiki/Contributing -# -# This file is auto generated, using git to list all individuals contributors. -# see https://github.com/pion/.goassets/blob/master/scripts/generate-authors.sh for the scripting -Adam Kiss -Aleksandr Razumov -Aleksandr Razumov -Atsushi Watanabe -backkem -Cecylia Bocovich -Christian Muehlhaeuser -David-dp- -ernado -ernado -fossabot -Frank Dietrich -Hugo Arregui -Jerry Tao -jinleileiking -John Bradley -Juliusz Chroboczek -Maanas Royy -Moises Marangoni -Raphael Randschau -Sean DuBois -Sean DuBois -Sean DuBois -songjiayang -Steffen Vogel -Vladislav Yarmak -Will LE -Y.Horie -Yutaka Takeda -ZHENK - -# List of contributors not appearing in Git history -Aliaksandr Valialkin -The IETF Trust -The gortc project diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/.gitignore b/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/v3/.gitignore similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/.gitignore rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/v3/.gitignore diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/.golangci.yml b/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/v3/.golangci.yml similarity index 95% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/.golangci.yml rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/v3/.golangci.yml index 4e3eddf42..e06de4d3c 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/dtls/v2/.golangci.yml +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/v3/.golangci.yml @@ -3,7 +3,8 @@ linters-settings: govet: - check-shadowing: true + enable: + - shadow misspell: locale: US exhaustive: @@ -29,7 +30,6 @@ linters: - bodyclose # checks whether HTTP response body is closed successfully - contextcheck # check the function whether use a non-inherited context - decorder # check declaration order and count of types, constants, variables and functions - - depguard # Go linter that checks if package imports are in a list of acceptable packages - dogsled # Checks assignments with too many blank identifiers (e.g. x, _, _, _, := f()) - dupl # Tool for code clone detection - durationcheck # check for two durations multiplied together @@ -63,7 +63,6 @@ linters: - importas # Enforces consistent import aliases - ineffassign # Detects when assignments to existing variables are not used - misspell # Finds commonly misspelled English words in comments - - nakedret # Finds naked returns in functions greater than a specified function length - nilerr # Finds the code that returns nil even if it checks that the error is not nil. - nilnil # Checks that there is no simultaneous return of `nil` error and an invalid value. - noctx # noctx finds sending http request without context.Context @@ -81,6 +80,7 @@ linters: - wastedassign # wastedassign finds wasted assignment statements - whitespace # Tool for detection of leading and trailing whitespace disable: + - depguard # Go linter that checks if package imports are in a list of acceptable packages - containedctx # containedctx is a linter that detects struct contained context.Context field - cyclop # checks function and package cyclomatic complexity - exhaustivestruct # Checks if all struct's fields are initialized @@ -94,6 +94,7 @@ linters: - maintidx # maintidx measures the maintainability index of each function. - makezero # Finds slice declarations with non-zero initial length - maligned # Tool to detect Go structs that would take less memory if their fields were sorted + - nakedret # Finds naked returns in functions greater than a specified function length - nestif # Reports deeply nested if statements - nlreturn # nlreturn checks for a new line before return and branch statements to increase code clarity - nolintlint # Reports ill-formed or insufficient nolint directives @@ -110,28 +111,15 @@ linters: issues: exclude-use-default: false + exclude-dirs-use-default: false exclude-rules: - # Allow complex tests, better to be self contained - - path: _test\.go - linters: - - gocognit - - forbidigo - - # Allow complex main function in examples - - path: examples - text: "of func `main` is high" - linters: - - gocognit - - # Allow forbidden identifiers in examples - - path: examples + # Allow complex tests and examples, better to be self contained + - path: (examples|main\.go|_test\.go) linters: - forbidigo + - gocognit # Allow forbidden identifiers in CLI commands - path: cmd linters: - forbidigo - -run: - skip-dirs-use-default: false diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/v3/.goreleaser.yml b/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/v3/.goreleaser.yml new file mode 100644 index 000000000..30093e9d6 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/v3/.goreleaser.yml @@ -0,0 +1,5 @@ +# SPDX-FileCopyrightText: 2023 The Pion community +# SPDX-License-Identifier: MIT + +builds: +- skip: true diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/LICENSE b/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/v3/LICENSE similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/LICENSE rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/v3/LICENSE diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/Makefile b/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/v3/Makefile similarity index 96% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/Makefile rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/v3/Makefile index ebfcd3394..eaaefa5c6 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/Makefile +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/v3/Makefile @@ -32,8 +32,6 @@ install: test-integration: @cd e2e && bash ./test.sh prepush: test lint test-integration -check-api: - @cd api && bash ./check.sh test: @./go.test.sh clean: diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/README.md b/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/v3/README.md similarity index 99% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/README.md rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/v3/README.md index fe1b28ffb..f0661e58b 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/README.md +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/v3/README.md @@ -180,7 +180,7 @@ We are always looking to support **your projects**. Please reach out if you have If you need commercial support or don't want to use public methods you can contact us at [team@pion.ly](mailto:team@pion.ly) ### Contributing -Check out the [contributing wiki](https://github.com/pion/webrtc/wiki/Contributing) to join the group of amazing people making this project possible: [AUTHORS.txt](./AUTHORS.txt) +Check out the [contributing wiki](https://github.com/pion/webrtc/wiki/Contributing) to join the group of amazing people making this project possible ### License MIT License - see [LICENSE](LICENSE) for full text diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/addr.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/v3/addr.go similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/addr.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/v3/addr.go diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/agent.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/v3/agent.go similarity index 99% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/agent.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/v3/agent.go index f03efa3c0..bc160c864 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/agent.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/v3/agent.go @@ -11,7 +11,7 @@ import ( // NoopHandler just discards any event. func NoopHandler() Handler { - return func(e Event) {} + return func(Event) {} } // NewAgent initializes and returns new Agent with provided handler. diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/attributes.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/v3/attributes.go similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/attributes.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/v3/attributes.go diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/attributes_debug.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/v3/attributes_debug.go similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/attributes_debug.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/v3/attributes_debug.go diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/checks.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/v3/checks.go similarity index 96% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/checks.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/v3/checks.go index 6b678a06b..db90a5a73 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/checks.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/v3/checks.go @@ -9,7 +9,7 @@ package stun import ( "errors" - "github.com/pion/stun/internal/hmac" + "github.com/pion/stun/v3/internal/hmac" ) // CheckSize returns ErrAttrSizeInvalid if got is not equal to expected. diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/checks_debug.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/v3/checks_debug.go similarity index 96% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/checks_debug.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/v3/checks_debug.go index 0b5c67c83..fe236c7f8 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/checks_debug.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/v3/checks_debug.go @@ -6,7 +6,7 @@ package stun -import "github.com/pion/stun/internal/hmac" +import "github.com/pion/stun/v3/internal/hmac" // CheckSize returns *AttrLengthError if got is not equal to expected. func CheckSize(a AttrType, got, expected int) error { diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/client.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/v3/client.go similarity index 97% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/client.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/v3/client.go index 5d02e51dc..24d3fafeb 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/client.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/v3/client.go @@ -16,9 +16,9 @@ import ( "sync/atomic" "time" - "github.com/pion/dtls/v2" - "github.com/pion/transport/v2" - "github.com/pion/transport/v2/stdnet" + "github.com/pion/dtls/v3" + "github.com/pion/transport/v3" + "github.com/pion/transport/v3/stdnet" ) // ErrUnsupportedURI is an error thrown if the user passes an unsupported STUN or TURN URI @@ -78,12 +78,17 @@ func DialURI(uri *URI, cfg *DialConfig) (*Client, error) { dtlsCfg := cfg.DTLSConfig // Copy dtlsCfg.ServerName = uri.Host - udpConn, err := nw.Dial("udp", addr) + udpAddr, err := net.ResolveUDPAddr("udp", addr) + if err != nil { + return nil, fmt.Errorf("failed to resolve UDPAddr: %w", err) + } + + udpConn, err := nw.DialUDP("udp", nil, udpAddr) if err != nil { return nil, fmt.Errorf("failed to dial: %w", err) } - if conn, err = dtls.Client(udpConn, &dtlsCfg); err != nil { + if conn, err = dtls.Client(udpConn, udpConn.RemoteAddr(), &dtlsCfg); err != nil { return nil, fmt.Errorf("failed to connect to '%s': %w", addr, err) } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/codecov.yml b/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/v3/codecov.yml similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/codecov.yml rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/v3/codecov.yml diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/errorcode.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/v3/errorcode.go similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/errorcode.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/v3/errorcode.go diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/errors.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/v3/errors.go similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/errors.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/v3/errors.go diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/fingerprint.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/v3/fingerprint.go similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/fingerprint.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/v3/fingerprint.go diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/fingerprint_debug.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/v3/fingerprint_debug.go similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/fingerprint_debug.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/v3/fingerprint_debug.go diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/helpers.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/v3/helpers.go similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/helpers.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/v3/helpers.go diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/integrity.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/v3/integrity.go similarity index 98% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/integrity.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/v3/integrity.go index 0fee0b075..29f688934 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/integrity.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/v3/integrity.go @@ -10,7 +10,7 @@ import ( //nolint:gci "fmt" "strings" - "github.com/pion/stun/internal/hmac" + "github.com/pion/stun/v3/internal/hmac" ) // separator for credentials. diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/integrity_debug.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/v3/integrity_debug.go similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/integrity_debug.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/v3/integrity_debug.go diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/internal/hmac/hmac.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/v3/internal/hmac/hmac.go similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/internal/hmac/hmac.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/v3/internal/hmac/hmac.go diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/internal/hmac/pool.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/v3/internal/hmac/pool.go similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/internal/hmac/pool.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/v3/internal/hmac/pool.go diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/internal/hmac/vendor.sh b/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/v3/internal/hmac/vendor.sh similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/internal/hmac/vendor.sh rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/v3/internal/hmac/vendor.sh diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/message.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/v3/message.go similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/message.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/v3/message.go diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/renovate.json b/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/v3/renovate.json similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/renovate.json rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/v3/renovate.json diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/stun.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/v3/stun.go similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/stun.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/v3/stun.go diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/textattrs.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/v3/textattrs.go similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/textattrs.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/v3/textattrs.go diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/uattrs.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/v3/uattrs.go similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/uattrs.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/v3/uattrs.go diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/uri.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/v3/uri.go similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/uri.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/v3/uri.go diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/xoraddr.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/v3/xoraddr.go similarity index 98% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/xoraddr.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/v3/xoraddr.go index fc423be86..2c5a9548f 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/xoraddr.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/v3/xoraddr.go @@ -10,7 +10,7 @@ import ( "net" "strconv" - "github.com/pion/transport/v2/utils/xor" + "github.com/pion/transport/v3/utils/xor" ) const ( diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/.golangci.yml b/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/.golangci.yml deleted file mode 100644 index 4e3eddf42..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/.golangci.yml +++ /dev/null @@ -1,137 +0,0 @@ -# SPDX-FileCopyrightText: 2023 The Pion community -# SPDX-License-Identifier: MIT - -linters-settings: - govet: - check-shadowing: true - misspell: - locale: US - exhaustive: - default-signifies-exhaustive: true - gomodguard: - blocked: - modules: - - github.com/pkg/errors: - recommendations: - - errors - forbidigo: - forbid: - - ^fmt.Print(f|ln)?$ - - ^log.(Panic|Fatal|Print)(f|ln)?$ - - ^os.Exit$ - - ^panic$ - - ^print(ln)?$ - -linters: - enable: - - asciicheck # Simple linter to check that your code does not contain non-ASCII identifiers - - bidichk # Checks for dangerous unicode character sequences - - bodyclose # checks whether HTTP response body is closed successfully - - contextcheck # check the function whether use a non-inherited context - - decorder # check declaration order and count of types, constants, variables and functions - - depguard # Go linter that checks if package imports are in a list of acceptable packages - - dogsled # Checks assignments with too many blank identifiers (e.g. x, _, _, _, := f()) - - dupl # Tool for code clone detection - - durationcheck # check for two durations multiplied together - - errcheck # Errcheck is a program for checking for unchecked errors in go programs. These unchecked errors can be critical bugs in some cases - - errchkjson # Checks types passed to the json encoding functions. Reports unsupported types and optionally reports occations, where the check for the returned error can be omitted. - - errname # Checks that sentinel errors are prefixed with the `Err` and error types are suffixed with the `Error`. - - errorlint # errorlint is a linter for that can be used to find code that will cause problems with the error wrapping scheme introduced in Go 1.13. - - exhaustive # check exhaustiveness of enum switch statements - - exportloopref # checks for pointers to enclosing loop variables - - forbidigo # Forbids identifiers - - forcetypeassert # finds forced type assertions - - gci # Gci control golang package import order and make it always deterministic. - - gochecknoglobals # Checks that no globals are present in Go code - - gochecknoinits # Checks that no init functions are present in Go code - - gocognit # Computes and checks the cognitive complexity of functions - - goconst # Finds repeated strings that could be replaced by a constant - - gocritic # The most opinionated Go source code linter - - godox # Tool for detection of FIXME, TODO and other comment keywords - - goerr113 # Golang linter to check the errors handling expressions - - gofmt # Gofmt checks whether code was gofmt-ed. By default this tool runs with -s option to check for code simplification - - gofumpt # Gofumpt checks whether code was gofumpt-ed. - - goheader # Checks is file header matches to pattern - - goimports # Goimports does everything that gofmt does. Additionally it checks unused imports - - gomoddirectives # Manage the use of 'replace', 'retract', and 'excludes' directives in go.mod. - - gomodguard # Allow and block list linter for direct Go module dependencies. This is different from depguard where there are different block types for example version constraints and module recommendations. - - goprintffuncname # Checks that printf-like functions are named with `f` at the end - - gosec # Inspects source code for security problems - - gosimple # Linter for Go source code that specializes in simplifying a code - - govet # Vet examines Go source code and reports suspicious constructs, such as Printf calls whose arguments do not align with the format string - - grouper # An analyzer to analyze expression groups. - - importas # Enforces consistent import aliases - - ineffassign # Detects when assignments to existing variables are not used - - misspell # Finds commonly misspelled English words in comments - - nakedret # Finds naked returns in functions greater than a specified function length - - nilerr # Finds the code that returns nil even if it checks that the error is not nil. - - nilnil # Checks that there is no simultaneous return of `nil` error and an invalid value. - - noctx # noctx finds sending http request without context.Context - - predeclared # find code that shadows one of Go's predeclared identifiers - - revive # golint replacement, finds style mistakes - - staticcheck # Staticcheck is a go vet on steroids, applying a ton of static analysis checks - - stylecheck # Stylecheck is a replacement for golint - - tagliatelle # Checks the struct tags. - - tenv # tenv is analyzer that detects using os.Setenv instead of t.Setenv since Go1.17 - - tparallel # tparallel detects inappropriate usage of t.Parallel() method in your Go test codes - - typecheck # Like the front-end of a Go compiler, parses and type-checks Go code - - unconvert # Remove unnecessary type conversions - - unparam # Reports unused function parameters - - unused # Checks Go code for unused constants, variables, functions and types - - wastedassign # wastedassign finds wasted assignment statements - - whitespace # Tool for detection of leading and trailing whitespace - disable: - - containedctx # containedctx is a linter that detects struct contained context.Context field - - cyclop # checks function and package cyclomatic complexity - - exhaustivestruct # Checks if all struct's fields are initialized - - funlen # Tool for detection of long functions - - gocyclo # Computes and checks the cyclomatic complexity of functions - - godot # Check if comments end in a period - - gomnd # An analyzer to detect magic numbers. - - ifshort # Checks that your code uses short syntax for if-statements whenever possible - - ireturn # Accept Interfaces, Return Concrete Types - - lll # Reports long lines - - maintidx # maintidx measures the maintainability index of each function. - - makezero # Finds slice declarations with non-zero initial length - - maligned # Tool to detect Go structs that would take less memory if their fields were sorted - - nestif # Reports deeply nested if statements - - nlreturn # nlreturn checks for a new line before return and branch statements to increase code clarity - - nolintlint # Reports ill-formed or insufficient nolint directives - - paralleltest # paralleltest detects missing usage of t.Parallel() method in your Go test - - prealloc # Finds slice declarations that could potentially be preallocated - - promlinter # Check Prometheus metrics naming via promlint - - rowserrcheck # checks whether Err of rows is checked successfully - - sqlclosecheck # Checks that sql.Rows and sql.Stmt are closed. - - testpackage # linter that makes you use a separate _test package - - thelper # thelper detects golang test helpers without t.Helper() call and checks the consistency of test helpers - - varnamelen # checks that the length of a variable's name matches its scope - - wrapcheck # Checks that errors returned from external packages are wrapped - - wsl # Whitespace Linter - Forces you to use empty lines! - -issues: - exclude-use-default: false - exclude-rules: - # Allow complex tests, better to be self contained - - path: _test\.go - linters: - - gocognit - - forbidigo - - # Allow complex main function in examples - - path: examples - text: "of func `main` is high" - linters: - - gocognit - - # Allow forbidden identifiers in examples - - path: examples - linters: - - forbidigo - - # Allow forbidden identifiers in CLI commands - - path: cmd - linters: - - forbidigo - -run: - skip-dirs-use-default: false diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/AUTHORS.txt b/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/AUTHORS.txt deleted file mode 100644 index 35bbec396..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/AUTHORS.txt +++ /dev/null @@ -1,28 +0,0 @@ -# Thank you to everyone that made Pion possible. If you are interested in contributing -# we would love to have you https://github.com/pion/webrtc/wiki/Contributing -# -# This file is auto generated, using git to list all individuals contributors. -# see https://github.com/pion/.goassets/blob/master/scripts/generate-authors.sh for the scripting -Adrian Cable -Atsushi Watanabe -backkem -cnderrauber -Hugo Arregui -Jeremiah Millay -Jozef Kralik -Juliusz Chroboczek -Luke Curley -Mathis Engelbart -OrlandoCo -Sean DuBois -Sean DuBois -Sean DuBois -Sean DuBois -Steffen Vogel -Winlin -Woodrow Douglass -Yutaka Takeda -ZHENK - -# List of contributors not appearing in Git history - diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/udp/conn.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/udp/conn.go deleted file mode 100644 index 2b57174a3..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/udp/conn.go +++ /dev/null @@ -1,327 +0,0 @@ -// SPDX-FileCopyrightText: 2023 The Pion community -// SPDX-License-Identifier: MIT - -// Package udp provides a connection-oriented listener over a UDP PacketConn -package udp - -import ( - "context" - "errors" - "net" - "sync" - "sync/atomic" - "time" - - "github.com/pion/transport/v2/deadline" - "github.com/pion/transport/v2/packetio" -) - -const ( - receiveMTU = 8192 - defaultListenBacklog = 128 // same as Linux default -) - -// Typed errors -var ( - ErrClosedListener = errors.New("udp: listener closed") - ErrListenQueueExceeded = errors.New("udp: listen queue exceeded") - ErrReadBufferFailed = errors.New("udp: failed to get read buffer from pool") -) - -// listener augments a connection-oriented Listener over a UDP PacketConn -type listener struct { - pConn *net.UDPConn - - accepting atomic.Value // bool - acceptCh chan *Conn - doneCh chan struct{} - doneOnce sync.Once - acceptFilter func([]byte) bool - readBufferPool *sync.Pool - - connLock sync.Mutex - conns map[string]*Conn - connWG *sync.WaitGroup - - readWG sync.WaitGroup - errClose atomic.Value // error - - readDoneCh chan struct{} - errRead atomic.Value // error -} - -// Accept waits for and returns the next connection to the listener. -func (l *listener) Accept() (net.Conn, error) { - select { - case c := <-l.acceptCh: - l.connWG.Add(1) - return c, nil - - case <-l.readDoneCh: - err, _ := l.errRead.Load().(error) - return nil, err - - case <-l.doneCh: - return nil, ErrClosedListener - } -} - -// Close closes the listener. -// Any blocked Accept operations will be unblocked and return errors. -func (l *listener) Close() error { - var err error - l.doneOnce.Do(func() { - l.accepting.Store(false) - close(l.doneCh) - - l.connLock.Lock() - // Close unaccepted connections - lclose: - for { - select { - case c := <-l.acceptCh: - close(c.doneCh) - delete(l.conns, c.rAddr.String()) - - default: - break lclose - } - } - nConns := len(l.conns) - l.connLock.Unlock() - - l.connWG.Done() - - if nConns == 0 { - // Wait if this is the final connection - l.readWG.Wait() - if errClose, ok := l.errClose.Load().(error); ok { - err = errClose - } - } else { - err = nil - } - }) - - return err -} - -// Addr returns the listener's network address. -func (l *listener) Addr() net.Addr { - return l.pConn.LocalAddr() -} - -// ListenConfig stores options for listening to an address. -type ListenConfig struct { - // Backlog defines the maximum length of the queue of pending - // connections. It is equivalent of the backlog argument of - // POSIX listen function. - // If a connection request arrives when the queue is full, - // the request will be silently discarded, unlike TCP. - // Set zero to use default value 128 which is same as Linux default. - Backlog int - - // AcceptFilter determines whether the new conn should be made for - // the incoming packet. If not set, any packet creates new conn. - AcceptFilter func([]byte) bool -} - -// Listen creates a new listener based on the ListenConfig. -func (lc *ListenConfig) Listen(network string, laddr *net.UDPAddr) (net.Listener, error) { - if lc.Backlog == 0 { - lc.Backlog = defaultListenBacklog - } - - conn, err := net.ListenUDP(network, laddr) - if err != nil { - return nil, err - } - - l := &listener{ - pConn: conn, - acceptCh: make(chan *Conn, lc.Backlog), - conns: make(map[string]*Conn), - doneCh: make(chan struct{}), - acceptFilter: lc.AcceptFilter, - readBufferPool: &sync.Pool{ - New: func() interface{} { - buf := make([]byte, receiveMTU) - return &buf - }, - }, - connWG: &sync.WaitGroup{}, - readDoneCh: make(chan struct{}), - } - - l.accepting.Store(true) - l.connWG.Add(1) - l.readWG.Add(2) // wait readLoop and Close execution routine - - go l.readLoop() - go func() { - l.connWG.Wait() - if err := l.pConn.Close(); err != nil { - l.errClose.Store(err) - } - l.readWG.Done() - }() - - return l, nil -} - -// Listen creates a new listener using default ListenConfig. -func Listen(network string, laddr *net.UDPAddr) (net.Listener, error) { - return (&ListenConfig{}).Listen(network, laddr) -} - -// readLoop has to tasks: -// 1. Dispatching incoming packets to the correct Conn. -// It can therefore not be ended until all Conns are closed. -// 2. Creating a new Conn when receiving from a new remote. -func (l *listener) readLoop() { - defer l.readWG.Done() - defer close(l.readDoneCh) - - buf, ok := l.readBufferPool.Get().(*[]byte) - if !ok { - l.errRead.Store(ErrReadBufferFailed) - return - } - defer l.readBufferPool.Put(buf) - - for { - n, raddr, err := l.pConn.ReadFrom(*buf) - if err != nil { - l.errRead.Store(err) - return - } - conn, ok, err := l.getConn(raddr, (*buf)[:n]) - if err != nil { - continue - } - if ok { - _, _ = conn.buffer.Write((*buf)[:n]) - } - } -} - -func (l *listener) getConn(raddr net.Addr, buf []byte) (*Conn, bool, error) { - l.connLock.Lock() - defer l.connLock.Unlock() - conn, ok := l.conns[raddr.String()] - if !ok { - if isAccepting, ok := l.accepting.Load().(bool); !isAccepting || !ok { - return nil, false, ErrClosedListener - } - if l.acceptFilter != nil { - if !l.acceptFilter(buf) { - return nil, false, nil - } - } - conn = l.newConn(raddr) - select { - case l.acceptCh <- conn: - l.conns[raddr.String()] = conn - default: - return nil, false, ErrListenQueueExceeded - } - } - return conn, true, nil -} - -// Conn augments a connection-oriented connection over a UDP PacketConn -type Conn struct { - listener *listener - - rAddr net.Addr - - buffer *packetio.Buffer - - doneCh chan struct{} - doneOnce sync.Once - - writeDeadline *deadline.Deadline -} - -func (l *listener) newConn(rAddr net.Addr) *Conn { - return &Conn{ - listener: l, - rAddr: rAddr, - buffer: packetio.NewBuffer(), - doneCh: make(chan struct{}), - writeDeadline: deadline.New(), - } -} - -// Read reads from c into p -func (c *Conn) Read(p []byte) (int, error) { - return c.buffer.Read(p) -} - -// Write writes len(p) bytes from p to the DTLS connection -func (c *Conn) Write(p []byte) (n int, err error) { - select { - case <-c.writeDeadline.Done(): - return 0, context.DeadlineExceeded - default: - } - return c.listener.pConn.WriteTo(p, c.rAddr) -} - -// Close closes the conn and releases any Read calls -func (c *Conn) Close() error { - var err error - c.doneOnce.Do(func() { - c.listener.connWG.Done() - close(c.doneCh) - c.listener.connLock.Lock() - delete(c.listener.conns, c.rAddr.String()) - nConns := len(c.listener.conns) - c.listener.connLock.Unlock() - - if isAccepting, ok := c.listener.accepting.Load().(bool); nConns == 0 && !isAccepting && ok { - // Wait if this is the final connection - c.listener.readWG.Wait() - if errClose, ok := c.listener.errClose.Load().(error); ok { - err = errClose - } - } else { - err = nil - } - - if errBuf := c.buffer.Close(); errBuf != nil && err == nil { - err = errBuf - } - }) - - return err -} - -// LocalAddr implements net.Conn.LocalAddr -func (c *Conn) LocalAddr() net.Addr { - return c.listener.pConn.LocalAddr() -} - -// RemoteAddr implements net.Conn.RemoteAddr -func (c *Conn) RemoteAddr() net.Addr { - return c.rAddr -} - -// SetDeadline implements net.Conn.SetDeadline -func (c *Conn) SetDeadline(t time.Time) error { - c.writeDeadline.Set(t) - return c.SetReadDeadline(t) -} - -// SetReadDeadline implements net.Conn.SetDeadline -func (c *Conn) SetReadDeadline(t time.Time) error { - return c.buffer.SetReadDeadline(t) -} - -// SetWriteDeadline implements net.Conn.SetDeadline -func (c *Conn) SetWriteDeadline(t time.Time) error { - c.writeDeadline.Set(t) - // Write deadline of underlying connection should not be changed - // since the connection can be shared. - return nil -} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/utils/xor/xor_amd64.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/utils/xor/xor_amd64.go deleted file mode 100644 index ded8e0d35..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/utils/xor/xor_amd64.go +++ /dev/null @@ -1,29 +0,0 @@ -// SPDX-FileCopyrightText: 2018 The Go Authors. All rights reserved. -// SPDX-License-Identifier: BSD-3-Clause - -//go:build !gccgo -// +build !gccgo - -// Package xor provides utility functions used by other Pion -// packages. AMD64 arch. -package xor - -// XorBytes xors the bytes in a and b. The destination should have enough -// space, otherwise xorBytes will panic. Returns the number of bytes xor'd. -// -//revive:disable-next-line -func XorBytes(dst, a, b []byte) int { - n := len(a) - if len(b) < n { - n = len(b) - } - if n == 0 { - return 0 - } - _ = dst[n-1] - xorBytesSSE2(&dst[0], &a[0], &b[0], n) // amd64 must have SSE2 - return n -} - -//go:noescape -func xorBytesSSE2(dst, a, b *byte, n int) diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/utils/xor/xor_amd64.s b/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/utils/xor/xor_amd64.s deleted file mode 100644 index f66ac95a2..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/utils/xor/xor_amd64.s +++ /dev/null @@ -1,56 +0,0 @@ -// SPDX-FileCopyrightText: 2018 The Go Authors. All rights reserved. -// SPDX-License-Identifier: BSD-3-Clause - -// go:build !gccgo -// +build !gccgo - -#include "textflag.h" - -// func xorBytesSSE2(dst, a, b *byte, n int) -TEXT ·xorBytesSSE2(SB), NOSPLIT, $0 - MOVQ dst+0(FP), BX - MOVQ a+8(FP), SI - MOVQ b+16(FP), CX - MOVQ n+24(FP), DX - TESTQ $15, DX // AND 15 & len, if not zero jump to not_aligned. - JNZ not_aligned - -aligned: - MOVQ $0, AX // position in slices - -loop16b: - MOVOU (SI)(AX*1), X0 // XOR 16byte forwards. - MOVOU (CX)(AX*1), X1 - PXOR X1, X0 - MOVOU X0, (BX)(AX*1) - ADDQ $16, AX - CMPQ DX, AX - JNE loop16b - RET - -loop_1b: - SUBQ $1, DX // XOR 1byte backwards. - MOVB (SI)(DX*1), DI - MOVB (CX)(DX*1), AX - XORB AX, DI - MOVB DI, (BX)(DX*1) - TESTQ $7, DX // AND 7 & len, if not zero jump to loop_1b. - JNZ loop_1b - CMPQ DX, $0 // if len is 0, ret. - JE ret - TESTQ $15, DX // AND 15 & len, if zero jump to aligned. - JZ aligned - -not_aligned: - TESTQ $7, DX // AND $7 & len, if not zero jump to loop_1b. - JNE loop_1b - SUBQ $8, DX // XOR 8bytes backwards. - MOVQ (SI)(DX*1), DI - MOVQ (CX)(DX*1), AX - XORQ AX, DI - MOVQ DI, (BX)(DX*1) - CMPQ DX, $16 // if len is greater or equal 16 here, it must be aligned. - JGE aligned - -ret: - RET diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/utils/xor/xor_arm64.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/utils/xor/xor_arm64.go deleted file mode 100644 index 7002ab7c9..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/utils/xor/xor_arm64.go +++ /dev/null @@ -1,31 +0,0 @@ -// SPDX-FileCopyrightText: 2020 The Go Authors. All rights reserved. -// SPDX-License-Identifier: BSD-3-Clause - -//go:build !gccgo -// +build !gccgo - -// Package xor provides utility functions used by other Pion -// packages. ARM64 arch. -package xor - -// XorBytes xors the bytes in a and b. The destination should have enough -// space, otherwise xorBytes will panic. Returns the number of bytes xor'd. -// -//revive:disable-next-line -func XorBytes(dst, a, b []byte) int { - n := len(a) - if len(b) < n { - n = len(b) - } - if n == 0 { - return 0 - } - // make sure dst has enough space - _ = dst[n-1] - - xorBytesARM64(&dst[0], &a[0], &b[0], n) - return n -} - -//go:noescape -func xorBytesARM64(dst, a, b *byte, n int) diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/utils/xor/xor_arm64.s b/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/utils/xor/xor_arm64.s deleted file mode 100644 index 0b82d0992..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/utils/xor/xor_arm64.s +++ /dev/null @@ -1,69 +0,0 @@ -// SPDX-FileCopyrightText: 2020 The Go Authors. All rights reserved. -// SPDX-License-Identifier: BSD-3-Clause - -//go:build !gccgo -// +build !gccgo - -#include "textflag.h" - -// func xorBytesARM64(dst, a, b *byte, n int) -TEXT ·xorBytesARM64(SB), NOSPLIT|NOFRAME, $0 - MOVD dst+0(FP), R0 - MOVD a+8(FP), R1 - MOVD b+16(FP), R2 - MOVD n+24(FP), R3 - CMP $64, R3 - BLT tail -loop_64: - VLD1.P 64(R1), [V0.B16, V1.B16, V2.B16, V3.B16] - VLD1.P 64(R2), [V4.B16, V5.B16, V6.B16, V7.B16] - VEOR V0.B16, V4.B16, V4.B16 - VEOR V1.B16, V5.B16, V5.B16 - VEOR V2.B16, V6.B16, V6.B16 - VEOR V3.B16, V7.B16, V7.B16 - VST1.P [V4.B16, V5.B16, V6.B16, V7.B16], 64(R0) - SUBS $64, R3 - CMP $64, R3 - BGE loop_64 -tail: - // quick end - CBZ R3, end - TBZ $5, R3, less_than32 - VLD1.P 32(R1), [V0.B16, V1.B16] - VLD1.P 32(R2), [V2.B16, V3.B16] - VEOR V0.B16, V2.B16, V2.B16 - VEOR V1.B16, V3.B16, V3.B16 - VST1.P [V2.B16, V3.B16], 32(R0) -less_than32: - TBZ $4, R3, less_than16 - LDP.P 16(R1), (R11, R12) - LDP.P 16(R2), (R13, R14) - EOR R11, R13, R13 - EOR R12, R14, R14 - STP.P (R13, R14), 16(R0) -less_than16: - TBZ $3, R3, less_than8 - MOVD.P 8(R1), R11 - MOVD.P 8(R2), R12 - EOR R11, R12, R12 - MOVD.P R12, 8(R0) -less_than8: - TBZ $2, R3, less_than4 - MOVWU.P 4(R1), R13 - MOVWU.P 4(R2), R14 - EORW R13, R14, R14 - MOVWU.P R14, 4(R0) -less_than4: - TBZ $1, R3, less_than2 - MOVHU.P 2(R1), R15 - MOVHU.P 2(R2), R16 - EORW R15, R16, R16 - MOVHU.P R16, 2(R0) -less_than2: - TBZ $0, R3, end - MOVBU (R1), R17 - MOVBU (R2), R19 - EORW R17, R19, R19 - MOVBU R19, (R0) -end: - RET diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/utils/xor/xor_ppc64x.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/utils/xor/xor_ppc64x.go deleted file mode 100644 index bcc5926c4..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/utils/xor/xor_ppc64x.go +++ /dev/null @@ -1,29 +0,0 @@ -// SPDX-FileCopyrightText: 2018 The Go Authors. All rights reserved. -// SPDX-License-Identifier: BSD-3-Clause - -//go:build (ppc64 && !gccgo) || (ppc64le && !gccgo) -// +build ppc64,!gccgo ppc64le,!gccgo - -// Package xor provides utility functions used by other Pion -// packages. PPC64 arch. -package xor - -// XorBytes xors the bytes in a and b. The destination should have enough -// space, otherwise xorBytes will panic. Returns the number of bytes xor'd. -// -//revive:disable-next-line -func XorBytes(dst, a, b []byte) int { - n := len(a) - if len(b) < n { - n = len(b) - } - if n == 0 { - return 0 - } - _ = dst[n-1] - xorBytesVSX(&dst[0], &a[0], &b[0], n) - return n -} - -//go:noescape -func xorBytesVSX(dst, a, b *byte, n int) diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/utils/xor/xor_ppc64x.s b/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/utils/xor/xor_ppc64x.s deleted file mode 100644 index 22763535f..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/utils/xor/xor_ppc64x.s +++ /dev/null @@ -1,87 +0,0 @@ -// SPDX-FileCopyrightText: 2018 The Go Authors. All rights reserved. -// SPDX-License-Identifier: BSD-3-Clause - -//go:build (ppc64 && !gccgo) || (ppc64le && !gccgo) -//+build ppc64,!gccgo ppc64le,!gccgo - -#include "textflag.h" - -// func xorBytesVSX(dst, a, b *byte, n int) -TEXT ·xorBytesVSX(SB), NOSPLIT, $0 - MOVD dst+0(FP), R3 // R3 = dst - MOVD a+8(FP), R4 // R4 = a - MOVD b+16(FP), R5 // R5 = b - MOVD n+24(FP), R6 // R6 = n - - CMPU R6, $32, CR7 // Check if n ≥ 32 bytes - MOVD R0, R8 // R8 = index - CMPU R6, $8, CR6 // Check if 8 ≤ n < 32 bytes - BLT CR6, small // Smaller than 8 - BLT CR7, xor16 // Case for 16 ≤ n < 32 bytes - - // Case for n ≥ 32 bytes -preloop32: - SRD $5, R6, R7 // Setup loop counter - MOVD R7, CTR - MOVD $16, R10 - ANDCC $31, R6, R9 // Check for tailing bytes for later -loop32: - LXVD2X (R4)(R8), VS32 // VS32 = a[i,...,i+15] - LXVD2X (R4)(R10), VS34 - LXVD2X (R5)(R8), VS33 // VS33 = b[i,...,i+15] - LXVD2X (R5)(R10), VS35 - XXLXOR VS32, VS33, VS32 // VS34 = a[] ^ b[] - XXLXOR VS34, VS35, VS34 - STXVD2X VS32, (R3)(R8) // Store to dst - STXVD2X VS34, (R3)(R10) - ADD $32, R8 // Update index - ADD $32, R10 - BC 16, 0, loop32 // bdnz loop16 - - BEQ CR0, done - - MOVD R9, R6 - CMP R6, $8 - BLT small -xor16: - CMP R6, $16 - BLT xor8 - LXVD2X (R4)(R8), VS32 - LXVD2X (R5)(R8), VS33 - XXLXOR VS32, VS33, VS32 - STXVD2X VS32, (R3)(R8) - ADD $16, R8 - ADD $-16, R6 - CMP R6, $8 - BLT small -xor8: - // Case for 8 ≤ n < 16 bytes - MOVD (R4)(R8), R14 // R14 = a[i,...,i+7] - MOVD (R5)(R8), R15 // R15 = b[i,...,i+7] - XOR R14, R15, R16 // R16 = a[] ^ b[] - SUB $8, R6 // n = n - 8 - MOVD R16, (R3)(R8) // Store to dst - ADD $8, R8 - - // Check if we're finished - CMP R6, R0 - BGT small - RET - - // Case for n < 8 bytes and tailing bytes from the - // previous cases. -small: - CMP R6, R0 - BEQ done - MOVD R6, CTR // Setup loop counter - -loop: - MOVBZ (R4)(R8), R14 // R14 = a[i] - MOVBZ (R5)(R8), R15 // R15 = b[i] - XOR R14, R15, R16 // R16 = a[i] ^ b[i] - MOVB R16, (R3)(R8) // Store to dst - ADD $1, R8 - BC 16, 0, loop // bdnz loop - -done: - RET diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/mdns/.gitignore b/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/.gitignore similarity index 75% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/mdns/.gitignore rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/.gitignore index f977e7485..6e2f206a9 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/mdns/.gitignore +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/.gitignore @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2023 The Pion community +# SPDX-License-Identifier: MIT + ### JetBrains IDE ### ##################### .idea/ diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/.golangci.yml b/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/.golangci.yml similarity index 95% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/.golangci.yml rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/.golangci.yml index 4e3eddf42..e06de4d3c 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/srtp/v2/.golangci.yml +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/.golangci.yml @@ -3,7 +3,8 @@ linters-settings: govet: - check-shadowing: true + enable: + - shadow misspell: locale: US exhaustive: @@ -29,7 +30,6 @@ linters: - bodyclose # checks whether HTTP response body is closed successfully - contextcheck # check the function whether use a non-inherited context - decorder # check declaration order and count of types, constants, variables and functions - - depguard # Go linter that checks if package imports are in a list of acceptable packages - dogsled # Checks assignments with too many blank identifiers (e.g. x, _, _, _, := f()) - dupl # Tool for code clone detection - durationcheck # check for two durations multiplied together @@ -63,7 +63,6 @@ linters: - importas # Enforces consistent import aliases - ineffassign # Detects when assignments to existing variables are not used - misspell # Finds commonly misspelled English words in comments - - nakedret # Finds naked returns in functions greater than a specified function length - nilerr # Finds the code that returns nil even if it checks that the error is not nil. - nilnil # Checks that there is no simultaneous return of `nil` error and an invalid value. - noctx # noctx finds sending http request without context.Context @@ -81,6 +80,7 @@ linters: - wastedassign # wastedassign finds wasted assignment statements - whitespace # Tool for detection of leading and trailing whitespace disable: + - depguard # Go linter that checks if package imports are in a list of acceptable packages - containedctx # containedctx is a linter that detects struct contained context.Context field - cyclop # checks function and package cyclomatic complexity - exhaustivestruct # Checks if all struct's fields are initialized @@ -94,6 +94,7 @@ linters: - maintidx # maintidx measures the maintainability index of each function. - makezero # Finds slice declarations with non-zero initial length - maligned # Tool to detect Go structs that would take less memory if their fields were sorted + - nakedret # Finds naked returns in functions greater than a specified function length - nestif # Reports deeply nested if statements - nlreturn # nlreturn checks for a new line before return and branch statements to increase code clarity - nolintlint # Reports ill-formed or insufficient nolint directives @@ -110,28 +111,15 @@ linters: issues: exclude-use-default: false + exclude-dirs-use-default: false exclude-rules: - # Allow complex tests, better to be self contained - - path: _test\.go - linters: - - gocognit - - forbidigo - - # Allow complex main function in examples - - path: examples - text: "of func `main` is high" - linters: - - gocognit - - # Allow forbidden identifiers in examples - - path: examples + # Allow complex tests and examples, better to be self contained + - path: (examples|main\.go|_test\.go) linters: - forbidigo + - gocognit # Allow forbidden identifiers in CLI commands - path: cmd linters: - forbidigo - -run: - skip-dirs-use-default: false diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/.goreleaser.yml b/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/.goreleaser.yml new file mode 100644 index 000000000..30093e9d6 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/.goreleaser.yml @@ -0,0 +1,5 @@ +# SPDX-FileCopyrightText: 2023 The Pion community +# SPDX-License-Identifier: MIT + +builds: +- skip: true diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/LICENSE b/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/LICENSE similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/LICENSE rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/LICENSE diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/README.md b/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/README.md similarity index 97% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/README.md rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/README.md index b604b104d..c1045f39d 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/README.md +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/README.md @@ -28,7 +28,7 @@ We are always looking to support **your projects**. Please reach out if you have If you need commercial support or don't want to use public methods you can contact us at [team@pion.ly](mailto:team@pion.ly) ### Contributing -Check out the [contributing wiki](https://github.com/pion/webrtc/wiki/Contributing) to join the group of amazing people making this project possible: [AUTHORS.txt](./AUTHORS.txt) +Check out the [contributing wiki](https://github.com/pion/webrtc/wiki/Contributing) to join the group of amazing people making this project possible ### License MIT License - see [LICENSE](LICENSE) for full text diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/mdns/codecov.yml b/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/codecov.yml similarity index 78% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/mdns/codecov.yml rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/codecov.yml index 085200a48..263e4d45c 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/mdns/codecov.yml +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/codecov.yml @@ -3,6 +3,8 @@ # # It is automatically copied from https://github.com/pion/.goassets repository. # +# SPDX-FileCopyrightText: 2023 The Pion community +# SPDX-License-Identifier: MIT coverage: status: diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/deadline/deadline.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/deadline/deadline.go similarity index 59% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/deadline/deadline.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/deadline/deadline.go index abd39f06d..f49b908db 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/deadline/deadline.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/deadline/deadline.go @@ -11,25 +11,46 @@ import ( "time" ) +type deadlineState uint8 + +const ( + deadlineStopped deadlineState = iota + deadlineStarted + deadlineExceeded +) + +var _ context.Context = (*Deadline)(nil) + // Deadline signals updatable deadline timer. // Also, it implements context.Context. type Deadline struct { - exceeded chan struct{} - stop chan struct{} - stopped chan bool - deadline time.Time mu sync.RWMutex + timer timer + done chan struct{} + deadline time.Time + state deadlineState + pending uint8 } // New creates new deadline timer. func New() *Deadline { - d := &Deadline{ - exceeded: make(chan struct{}), - stop: make(chan struct{}), - stopped: make(chan bool, 1), + return &Deadline{ + done: make(chan struct{}), } - d.stopped <- true - return d +} + +func (d *Deadline) timeout() { + d.mu.Lock() + if d.pending--; d.pending != 0 || d.state != deadlineStarted { + d.mu.Unlock() + return + } + + d.state = deadlineExceeded + done := d.done + d.mu.Unlock() + + close(done) } // Set new deadline. Zero value means no deadline. @@ -37,55 +58,43 @@ func (d *Deadline) Set(t time.Time) { d.mu.Lock() defer d.mu.Unlock() - d.deadline = t - - close(d.stop) - - select { - case <-d.exceeded: - d.exceeded = make(chan struct{}) - default: - stopped := <-d.stopped - if !stopped { - d.exceeded = make(chan struct{}) - } + if d.state == deadlineStarted && d.timer.Stop() { + d.pending-- + } + + d.deadline = t + d.pending++ + + if d.state == deadlineExceeded { + d.done = make(chan struct{}) } - d.stop = make(chan struct{}) - d.stopped = make(chan bool, 1) if t.IsZero() { - d.stopped <- true + d.pending-- + d.state = deadlineStopped return } if dur := time.Until(t); dur > 0 { - exceeded := d.exceeded - stopped := d.stopped - go func() { - timer := time.NewTimer(dur) - select { - case <-timer.C: - close(exceeded) - stopped <- false - case <-d.stop: - if !timer.Stop() { - <-timer.C - } - stopped <- true - } - }() + d.state = deadlineStarted + if d.timer == nil { + d.timer = afterFunc(dur, d.timeout) + } else { + d.timer.Reset(dur) + } return } - close(d.exceeded) - d.stopped <- false + d.pending-- + d.state = deadlineExceeded + close(d.done) } // Done receives deadline signal. func (d *Deadline) Done() <-chan struct{} { d.mu.RLock() defer d.mu.RUnlock() - return d.exceeded + return d.done } // Err returns context.DeadlineExceeded if the deadline is exceeded. @@ -93,12 +102,10 @@ func (d *Deadline) Done() <-chan struct{} { func (d *Deadline) Err() error { d.mu.RLock() defer d.mu.RUnlock() - select { - case <-d.exceeded: + if d.state == deadlineExceeded { return context.DeadlineExceeded - default: - return nil } + return nil } // Deadline returns current deadline. diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/deadline/timer.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/deadline/timer.go new file mode 100644 index 000000000..5a3972478 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/deadline/timer.go @@ -0,0 +1,13 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + +package deadline + +import ( + "time" +) + +type timer interface { + Stop() bool + Reset(time.Duration) bool +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/deadline/timer_generic.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/deadline/timer_generic.go new file mode 100644 index 000000000..0c8f87ca0 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/deadline/timer_generic.go @@ -0,0 +1,15 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + +//go:build !js +// +build !js + +package deadline + +import ( + "time" +) + +func afterFunc(d time.Duration, f func()) timer { + return time.AfterFunc(d, f) +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/deadline/timer_js.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/deadline/timer_js.go new file mode 100644 index 000000000..b77e31e09 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/deadline/timer_js.go @@ -0,0 +1,67 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + +//go:build js +// +build js + +package deadline + +import ( + "sync" + "time" +) + +// jsTimer is a timer utility for wasm with a working Reset function. +type jsTimer struct { + f func() + mu sync.Mutex + timer *time.Timer + version uint64 + started bool +} + +func afterFunc(d time.Duration, f func()) timer { + t := &jsTimer{f: f} + t.Reset(d) + return t +} + +func (t *jsTimer) Stop() bool { + t.mu.Lock() + defer t.mu.Unlock() + + t.version++ + t.timer.Stop() + + started := t.started + t.started = false + return started +} + +func (t *jsTimer) Reset(d time.Duration) bool { + t.mu.Lock() + defer t.mu.Unlock() + + if t.timer != nil { + t.timer.Stop() + } + + t.version++ + version := t.version + t.timer = time.AfterFunc(d, func() { + t.mu.Lock() + if version != t.version { + t.mu.Unlock() + return + } + + t.started = false + t.mu.Unlock() + + t.f() + }) + + started := t.started + t.started = true + return started +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/net.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/net.go similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/net.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/net.go diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/connctx/connctx.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/netctx/conn.go similarity index 70% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/connctx/connctx.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/netctx/conn.go index 0bdd59509..823107c7e 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/connctx/connctx.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/netctx/conn.go @@ -1,8 +1,8 @@ // SPDX-FileCopyrightText: 2023 The Pion community // SPDX-License-Identifier: MIT -// Package connctx wraps net.Conn using context.Context. -package connctx +// Package netctx wraps common net interfaces using context.Context. +package netctx import ( "context" @@ -33,8 +33,8 @@ type ReadWriter interface { Writer } -// ConnCtx is a wrapper of net.Conn using context.Context. -type ConnCtx interface { +// Conn is a wrapper of net.Conn using context.Context. +type Conn interface { Reader Writer io.Closer @@ -43,7 +43,7 @@ type ConnCtx interface { Conn() net.Conn } -type connCtx struct { +type conn struct { nextConn net.Conn closed chan struct{} closeOnce sync.Once @@ -53,22 +53,24 @@ type connCtx struct { var veryOld = time.Unix(0, 1) //nolint:gochecknoglobals -// New creates a new ConnCtx wrapping given net.Conn. -func New(conn net.Conn) ConnCtx { - c := &connCtx{ - nextConn: conn, +// NewConn creates a new Conn wrapping given net.Conn. +func NewConn(netConn net.Conn) Conn { + c := &conn{ + nextConn: netConn, closed: make(chan struct{}), } return c } -func (c *connCtx) ReadContext(ctx context.Context, b []byte) (int, error) { +// ReadContext reads data from the connection. +// Unlike net.Conn.Read(), the provided context is used to control timeout. +func (c *conn) ReadContext(ctx context.Context, b []byte) (int, error) { c.readMu.Lock() defer c.readMu.Unlock() select { case <-c.closed: - return 0, io.EOF + return 0, net.ErrClosed default: } @@ -106,7 +108,9 @@ func (c *connCtx) ReadContext(ctx context.Context, b []byte) (int, error) { return n, err } -func (c *connCtx) WriteContext(ctx context.Context, b []byte) (int, error) { +// WriteContext writes data to the connection. +// Unlike net.Conn.Write(), the provided context is used to control timeout. +func (c *conn) WriteContext(ctx context.Context, b []byte) (int, error) { c.writeMu.Lock() defer c.writeMu.Unlock() @@ -150,7 +154,10 @@ func (c *connCtx) WriteContext(ctx context.Context, b []byte) (int, error) { return n, err } -func (c *connCtx) Close() error { +// Close closes the connection. +// Any blocked ReadContext or WriteContext operations will be unblocked and +// return errors. +func (c *conn) Close() error { err := c.nextConn.Close() c.closeOnce.Do(func() { c.writeMu.Lock() @@ -162,14 +169,17 @@ func (c *connCtx) Close() error { return err } -func (c *connCtx) LocalAddr() net.Addr { +// LocalAddr returns the local network address, if known. +func (c *conn) LocalAddr() net.Addr { return c.nextConn.LocalAddr() } -func (c *connCtx) RemoteAddr() net.Addr { +// LocalAddr returns the local network address, if known. +func (c *conn) RemoteAddr() net.Addr { return c.nextConn.RemoteAddr() } -func (c *connCtx) Conn() net.Conn { +// Conn returns the underlying net.Conn. +func (c *conn) Conn() net.Conn { return c.nextConn } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/netctx/packetconn.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/netctx/packetconn.go new file mode 100644 index 000000000..a4ce22d95 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/netctx/packetconn.go @@ -0,0 +1,175 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + +package netctx + +import ( + "context" + "io" + "net" + "sync" + "sync/atomic" + "time" +) + +// ReaderFrom is an interface for context controlled packet reader. +type ReaderFrom interface { + ReadFromContext(context.Context, []byte) (int, net.Addr, error) +} + +// WriterTo is an interface for context controlled packet writer. +type WriterTo interface { + WriteToContext(context.Context, []byte, net.Addr) (int, error) +} + +// PacketConn is a wrapper of net.PacketConn using context.Context. +type PacketConn interface { + ReaderFrom + WriterTo + io.Closer + LocalAddr() net.Addr + Conn() net.PacketConn +} + +type packetConn struct { + nextConn net.PacketConn + closed chan struct{} + closeOnce sync.Once + readMu sync.Mutex + writeMu sync.Mutex +} + +// NewPacketConn creates a new PacketConn wrapping the given net.PacketConn. +func NewPacketConn(pconn net.PacketConn) PacketConn { + p := &packetConn{ + nextConn: pconn, + closed: make(chan struct{}), + } + return p +} + +// ReadFromContext reads a packet from the connection, +// copying the payload into p. It returns the number of +// bytes copied into p and the return address that +// was on the packet. +// It returns the number of bytes read (0 <= n <= len(p)) +// and any error encountered. Callers should always process +// the n > 0 bytes returned before considering the error err. +// Unlike net.PacketConn.ReadFrom(), the provided context is +// used to control timeout. +func (p *packetConn) ReadFromContext(ctx context.Context, b []byte) (int, net.Addr, error) { + p.readMu.Lock() + defer p.readMu.Unlock() + + select { + case <-p.closed: + return 0, nil, net.ErrClosed + default: + } + + done := make(chan struct{}) + var wg sync.WaitGroup + var errSetDeadline atomic.Value + wg.Add(1) + go func() { + defer wg.Done() + select { + case <-ctx.Done(): + // context canceled + if err := p.nextConn.SetReadDeadline(veryOld); err != nil { + errSetDeadline.Store(err) + return + } + <-done + if err := p.nextConn.SetReadDeadline(time.Time{}); err != nil { + errSetDeadline.Store(err) + } + case <-done: + } + }() + + n, raddr, err := p.nextConn.ReadFrom(b) + + close(done) + wg.Wait() + if e := ctx.Err(); e != nil && n == 0 { + err = e + } + if err2, ok := errSetDeadline.Load().(error); ok && err == nil && err2 != nil { + err = err2 + } + return n, raddr, err +} + +// WriteToContext writes a packet with payload p to addr. +// Unlike net.PacketConn.WriteTo(), the provided context +// is used to control timeout. +// On packet-oriented connections, write timeouts are rare. +func (p *packetConn) WriteToContext(ctx context.Context, b []byte, raddr net.Addr) (int, error) { + p.writeMu.Lock() + defer p.writeMu.Unlock() + + select { + case <-p.closed: + return 0, ErrClosing + default: + } + + done := make(chan struct{}) + var wg sync.WaitGroup + var errSetDeadline atomic.Value + wg.Add(1) + go func() { + defer wg.Done() + select { + case <-ctx.Done(): + // context canceled + if err := p.nextConn.SetWriteDeadline(veryOld); err != nil { + errSetDeadline.Store(err) + return + } + <-done + if err := p.nextConn.SetWriteDeadline(time.Time{}); err != nil { + errSetDeadline.Store(err) + } + case <-done: + } + }() + + n, err := p.nextConn.WriteTo(b, raddr) + + close(done) + wg.Wait() + if e := ctx.Err(); e != nil && n == 0 { + err = e + } + if err2, ok := errSetDeadline.Load().(error); ok && err == nil && err2 != nil { + err = err2 + } + return n, err +} + +// Close closes the connection. +// Any blocked ReadFromContext or WriteToContext operations will be unblocked +// and return errors. +func (p *packetConn) Close() error { + err := p.nextConn.Close() + p.closeOnce.Do(func() { + p.writeMu.Lock() + p.readMu.Lock() + close(p.closed) + p.readMu.Unlock() + p.writeMu.Unlock() + }) + return err +} + +// LocalAddr returns the local network address, if known. +func (p *packetConn) LocalAddr() net.Addr { + return p.nextConn.LocalAddr() +} + +// Conn returns the underlying net.PacketConn. +func (p *packetConn) Conn() net.PacketConn { + return p.nextConn +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/connctx/pipe.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/netctx/pipe.go similarity index 56% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/connctx/pipe.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/netctx/pipe.go index 96b802e43..7deae668a 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/connctx/pipe.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/netctx/pipe.go @@ -1,14 +1,14 @@ // SPDX-FileCopyrightText: 2023 The Pion community // SPDX-License-Identifier: MIT -package connctx +package netctx import ( "net" ) -// Pipe creates piped pair of ConnCtx. -func Pipe() (ConnCtx, ConnCtx) { +// Pipe creates piped pair of Conn. +func Pipe() (Conn, Conn) { ca, cb := net.Pipe() - return New(ca), New(cb) + return NewConn(ca), NewConn(cb) } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/packetio/buffer.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/packetio/buffer.go similarity index 93% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/packetio/buffer.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/packetio/buffer.go index 2d46d796a..cdd39d77c 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/packetio/buffer.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/packetio/buffer.go @@ -10,7 +10,7 @@ import ( "sync" "time" - "github.com/pion/transport/v2/deadline" + "github.com/pion/transport/v3/deadline" ) var errPacketTooBig = errors.New("packet too big") @@ -38,7 +38,7 @@ type Buffer struct { data []byte head, tail int - notify chan struct{} // non-nil when we have blocked readers + notify chan struct{} closed bool count int @@ -56,6 +56,7 @@ const ( // NewBuffer creates a new Buffer. func NewBuffer() *Buffer { return &Buffer{ + notify: make(chan struct{}, 1), readDeadline: deadline.New(), } } @@ -149,14 +150,6 @@ func (b *Buffer) Write(packet []byte) (int, error) { } } - var notify chan struct{} - if b.notify != nil { - // Prepare to notify readers, but only - // actually do it after we release the lock. - notify = b.notify - b.notify = nil - } - // store the length of the packet b.data[b.tail] = uint8(len(packet) >> 8) b.tail++ @@ -178,11 +171,12 @@ func (b *Buffer) Write(packet []byte) (int, error) { b.tail = m } b.count++ - b.mutex.Unlock() - if notify != nil { - close(notify) + select { + case b.notify <- struct{}{}: + default: } + b.mutex.Unlock() return len(packet), nil } @@ -244,7 +238,6 @@ func (b *Buffer) Read(packet []byte) (n int, err error) { //nolint:gocognit } b.count-- - b.mutex.Unlock() if copied < count { @@ -257,17 +250,12 @@ func (b *Buffer) Read(packet []byte) (n int, err error) { //nolint:gocognit b.mutex.Unlock() return 0, io.EOF } - - if b.notify == nil { - b.notify = make(chan struct{}) - } - notify := b.notify b.mutex.Unlock() select { case <-b.readDeadline.Done(): return 0, &netError{ErrTimeout, true, true} - case <-notify: + case <-b.notify: } } } @@ -282,16 +270,10 @@ func (b *Buffer) Close() (err error) { return nil } - notify := b.notify - b.notify = nil b.closed = true - + close(b.notify) b.mutex.Unlock() - if notify != nil { - close(notify) - } - return nil } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/packetio/errors.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/packetio/errors.go similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/packetio/errors.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/packetio/errors.go diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/packetio/hardlimit.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/packetio/hardlimit.go similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/packetio/hardlimit.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/packetio/hardlimit.go diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/packetio/no_hardlimit.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/packetio/no_hardlimit.go similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/packetio/no_hardlimit.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/packetio/no_hardlimit.go diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/renovate.json b/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/renovate.json similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/renovate.json rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/renovate.json diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/replaydetector/fixedbig.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/replaydetector/fixedbig.go similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/replaydetector/fixedbig.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/replaydetector/fixedbig.go diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/replaydetector/replaydetector.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/replaydetector/replaydetector.go similarity index 78% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/replaydetector/replaydetector.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/replaydetector/replaydetector.go index 4358d8f3b..d40799568 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/replaydetector/replaydetector.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/replaydetector/replaydetector.go @@ -8,7 +8,14 @@ package replaydetector type ReplayDetector interface { // Check returns true if given sequence number is not replayed. // Call accept() to mark the packet is received properly. - Check(seq uint64) (accept func(), ok bool) + // The return value of accept() indicates whether the accepted packet is + // has the latest observed sequence number. + Check(seq uint64) (accept func() bool, ok bool) +} + +// nop is a no-op func that is returned in the case that Check() fails. +func nop() bool { + return false } type slidingWindowDetector struct { @@ -30,30 +37,33 @@ func New(windowSize uint, maxSeq uint64) ReplayDetector { } } -func (d *slidingWindowDetector) Check(seq uint64) (accept func(), ok bool) { +func (d *slidingWindowDetector) Check(seq uint64) (func() bool, bool) { if seq > d.maxSeq { // Exceeded upper limit. - return func() {}, false + return nop, false } if seq <= d.latestSeq { if d.latestSeq >= uint64(d.windowSize)+seq { - return func() {}, false + return nop, false } if d.mask.Bit(uint(d.latestSeq-seq)) != 0 { // The sequence number is duplicated. - return func() {}, false + return nop, false } } - return func() { + return func() bool { + latest := seq == 0 if seq > d.latestSeq { // Update the head of the window. d.mask.Lsh(uint(seq - d.latestSeq)) d.latestSeq = seq + latest = true } diff := (d.latestSeq - seq) % d.maxSeq d.mask.SetBit(uint(diff)) + return latest }, true } @@ -75,10 +85,10 @@ type wrappedSlidingWindowDetector struct { init bool } -func (d *wrappedSlidingWindowDetector) Check(seq uint64) (accept func(), ok bool) { +func (d *wrappedSlidingWindowDetector) Check(seq uint64) (func() bool, bool) { if seq > d.maxSeq { // Exceeded upper limit. - return func() {}, false + return nop, false } if !d.init { if seq != 0 { @@ -99,21 +109,24 @@ func (d *wrappedSlidingWindowDetector) Check(seq uint64) (accept func(), ok bool if diff >= int64(d.windowSize) { // Too old. - return func() {}, false + return nop, false } if diff >= 0 { if d.mask.Bit(uint(diff)) != 0 { // The sequence number is duplicated. - return func() {}, false + return nop, false } } - return func() { + return func() bool { + latest := false if diff < 0 { // Update the head of the window. d.mask.Lsh(uint(-diff)) d.latestSeq = seq + latest = true } d.mask.SetBit(uint(d.latestSeq - seq)) + return latest }, true } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/stdnet/net.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/stdnet/net.go similarity index 95% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/stdnet/net.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/stdnet/net.go index fa4753b51..3d2a6e866 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/stdnet/net.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/stdnet/net.go @@ -9,7 +9,8 @@ import ( "fmt" "net" - "github.com/pion/transport/v2" + "github.com/pion/transport/v3" + "github.com/wlynxg/anet" ) const ( @@ -38,15 +39,15 @@ var _ transport.Net = &Net{} func (n *Net) UpdateInterfaces() error { ifs := []*transport.Interface{} - oifs, err := net.Interfaces() + oifs, err := anet.Interfaces() if err != nil { return err } - for _, oif := range oifs { - ifc := transport.NewInterface(oif) + for i := range oifs { + ifc := transport.NewInterface(oifs[i]) - addrs, err := oif.Addrs() + addrs, err := anet.InterfaceAddrsByInterface(&oifs[i]) if err != nil { return err } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/utils/xor/xor_arm.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/utils/xor/xor_arm.go similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/utils/xor/xor_arm.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/utils/xor/xor_arm.go diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/utils/xor/xor_arm.s b/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/utils/xor/xor_arm.s similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/utils/xor/xor_arm.s rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/utils/xor/xor_arm.s diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/utils/xor/xor_generic.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/utils/xor/xor_generic.go new file mode 100644 index 000000000..690549aad --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/utils/xor/xor_generic.go @@ -0,0 +1,20 @@ +// SPDX-FileCopyrightText: 2013 The Go Authors. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// SPDX-FileCopyrightText: 2024 The Pion community +// SPDX-License-Identifier: MIT + +//go:build go1.20 && !arm && !gccgo + +// Package xor provides the XorBytes function. +package xor + +import ( + "crypto/subtle" +) + +// XorBytes calls [crypto/suble.XORBytes]. +// +//revive:disable-next-line +func XorBytes(dst, a, b []byte) int { + return subtle.XORBytes(dst, a, b) +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/utils/xor/xor_generic.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/utils/xor/xor_old.go similarity index 82% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/utils/xor/xor_generic.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/utils/xor/xor_old.go index 967fed33a..f46f4d987 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/utils/xor/xor_generic.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/utils/xor/xor_old.go @@ -3,11 +3,10 @@ // SPDX-FileCopyrightText: 2022 The Pion community // SPDX-License-Identifier: MIT -//go:build (!amd64 && !ppc64 && !ppc64le && !arm64 && !arm) || gccgo -// +build !amd64,!ppc64,!ppc64le,!arm64,!arm gccgo +//go:build (!go1.20 && !arm) || gccgo -// Package xor provides utility functions used by other Pion -// packages. Generic arch. +// Package xor provides the XorBytes function. +// This version is only used on Go up to version 1.19. package xor import ( @@ -16,8 +15,8 @@ import ( ) const ( - wordSize = int(unsafe.Sizeof(uintptr(0))) // nolint:gosec - supportsUnaligned = runtime.GOARCH == "386" || runtime.GOARCH == "ppc64" || runtime.GOARCH == "ppc64le" || runtime.GOARCH == "s390x" // nolint:gochecknoglobals + wordSize = int(unsafe.Sizeof(uintptr(0))) // nolint:gosec + supportsUnaligned = runtime.GOARCH == "386" || runtime.GOARCH == "amd64" || runtime.GOARCH == "arm64" || runtime.GOARCH == "ppc64" || runtime.GOARCH == "ppc64le" || runtime.GOARCH == "s390x" // nolint:gochecknoglobals ) func isAligned(a *byte) bool { diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/vnet/.gitignore b/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/vnet/.gitignore similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/vnet/.gitignore rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/vnet/.gitignore diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/vnet/README.md b/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/vnet/README.md similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/vnet/README.md rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/vnet/README.md diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/vnet/chunk.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/vnet/chunk.go similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/vnet/chunk.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/vnet/chunk.go diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/vnet/chunk_queue.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/vnet/chunk_queue.go similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/vnet/chunk_queue.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/vnet/chunk_queue.go diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/vnet/conn.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/vnet/conn.go similarity index 99% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/vnet/conn.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/vnet/conn.go index 8f6f34269..a407f72dc 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/vnet/conn.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/vnet/conn.go @@ -12,7 +12,7 @@ import ( "sync" "time" - "github.com/pion/transport/v2" + "github.com/pion/transport/v3" ) const ( diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/vnet/conn_map.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/vnet/conn_map.go similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/vnet/conn_map.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/vnet/conn_map.go diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/vnet/delay_filter.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/vnet/delay_filter.go similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/vnet/delay_filter.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/vnet/delay_filter.go diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/vnet/errors.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/vnet/errors.go similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/vnet/errors.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/vnet/errors.go diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/vnet/loss_filter.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/vnet/loss_filter.go similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/vnet/loss_filter.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/vnet/loss_filter.go diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/vnet/nat.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/vnet/nat.go similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/vnet/nat.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/vnet/nat.go diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/vnet/net.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/vnet/net.go similarity index 99% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/vnet/net.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/vnet/net.go index 5d0938e64..08fd1f5b3 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/vnet/net.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/vnet/net.go @@ -13,7 +13,7 @@ import ( "strings" "sync" - "github.com/pion/transport/v2" + "github.com/pion/transport/v3" ) const ( diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/vnet/resolver.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/vnet/resolver.go similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/vnet/resolver.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/vnet/resolver.go diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/vnet/router.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/vnet/router.go similarity index 99% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/vnet/router.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/vnet/router.go index cd4b88dc4..cfa42116f 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/vnet/router.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/vnet/router.go @@ -14,7 +14,7 @@ import ( "time" "github.com/pion/logging" - "github.com/pion/transport/v2" + "github.com/pion/transport/v3" ) const ( diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/vnet/tbf.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/vnet/tbf.go similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/vnet/tbf.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/vnet/tbf.go diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/vnet/udpproxy.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/vnet/udpproxy.go similarity index 99% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/vnet/udpproxy.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/vnet/udpproxy.go index c5b4f9965..6de9cebb5 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/vnet/udpproxy.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/vnet/udpproxy.go @@ -55,7 +55,7 @@ func NewProxy(router *Router) (*UDPProxy, error) { // Close the proxy, stop all workers. func (v *UDPProxy) Close() error { - v.workers.Range(func(key, value interface{}) bool { + v.workers.Range(func(_, value interface{}) bool { _ = value.(*aUDPProxyWorker).Close() //nolint:forcetypeassert return true }) diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/vnet/udpproxy_direct.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/vnet/udpproxy_direct.go similarity index 95% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/vnet/udpproxy_direct.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/vnet/udpproxy_direct.go index bb2aedfd0..35d815df5 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/vnet/udpproxy_direct.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/vnet/udpproxy_direct.go @@ -11,7 +11,7 @@ import ( // Deliver directly send packet to vnet or real-server. // For example, we can use this API to simulate the REPLAY ATTACK. func (v *UDPProxy) Deliver(sourceAddr, destAddr net.Addr, b []byte) (nn int, err error) { - v.workers.Range(func(key, value interface{}) bool { + v.workers.Range(func(_, value interface{}) bool { if nn, err = value.(*aUDPProxyWorker).Deliver(sourceAddr, destAddr, b); err != nil { return false // Fail, abort. } else if nn == len(b) { diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/vnet/vnet.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/vnet/vnet.go similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v2/vnet/vnet.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/transport/v3/vnet/vnet.go diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/.goreleaser.yml b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/.goreleaser.yml deleted file mode 100644 index 2caa5fbd3..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/.goreleaser.yml +++ /dev/null @@ -1,2 +0,0 @@ -builds: -- skip: true diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/AUTHORS.txt b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/AUTHORS.txt deleted file mode 100644 index 3b38a5c1f..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/AUTHORS.txt +++ /dev/null @@ -1,43 +0,0 @@ -# Thank you to everyone that made Pion possible. If you are interested in contributing -# we would love to have you https://github.com/pion/webrtc/wiki/Contributing -# -# This file is auto generated, using git to list all individuals contributors. -# see https://github.com/pion/.goassets/blob/master/scripts/generate-authors.sh for the scripting -Aaron France -Aleksandr Razumov -andrefsp -Antonio Sorrentino -Atsushi Watanabe -backkem -Caleb Phillips -cnderrauber -David Colburn -Gabor Retvari -Herman Banken -Hugo Arregui -Igor German -Ingmar Wittkau -Jannis Mattheis -John Bradley -jose nazario -Juliusz Chroboczek -lllf -Lukas Rezek -Marouane <6729798+nindolabs@users.noreply.github.com> -Mészáros Mihály -nindolabs <6729798+nindolabs@users.noreply.github.com> -Onwuka Gideon -Robert Eperjesi -Sean DuBois -Sean DuBois -Sean DuBois -Sean DuBois -songjiayang -Steffen Vogel -ted -Tom Clift -Yusuke Nakamura -Yutaka Takeda - -# List of contributors not appearing in Git history - diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/DESIGN.md b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/DESIGN.md deleted file mode 100644 index 2c5246693..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/DESIGN.md +++ /dev/null @@ -1,31 +0,0 @@ -# Why Pion TURN -TURN servers aren't exactly a hot technology, they are usually an after thought when building something. Most of the time -beginners build an interesting WebRTC application, but at the very end realize they need a TURN server. It is really frustrating when you -want to share your cool new project, only to realize you have to run another service. - -Then you find yourself building from source, fighting with config files and making changes you don't fully understand. Pion TURN was born -hoping to solve these frustrations. These are the guiding principals/features that define pion-turn. - -## Easy setup -simple-turn is a statically built TURN server, configured by environment variables. The entire install setup is 5 commands, on any platform! -The goal is that anyone should be able to run a TURN server on any platform. - -## Integration first -pion-turn makes no assumptions about how you authenticate users, how you log, or even your topology! Instead of running a dedicated TURN server you -can inherit from github.com/pion/turn and set whatever logger you want. - -## Embeddable -You can add this to an existing service. This means all your config files stay homogeneous instead of having the mismatch that makes it harder to manage your services. -For small setups it is usually an overkill to deploy dedicated TURN servers, this makes it easier to solve the problems you care about. - -## Safe -Golang provides a great foundation to build safe network services. Especially when running a networked service that is highly concurrent bugs can be devastating. - -## Readable -All network interaction is commented with a link to the spec. This makes learning and debugging easier, the TURN server was written to also serve as a guide for others. - -## Tested -Every commit is tested via travis-ci Go provides fantastic facilities for testing, and more will be added as time goes on. - -## Shared libraries -Every pion product is built using shared libraries, allowing others to build things using existing tested STUN and TURN tools. diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/FAQ.md b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/FAQ.md deleted file mode 100644 index a8ffd6491..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/FAQ.md +++ /dev/null @@ -1,17 +0,0 @@ - - -## FAQ - -Q: Will pion/turn also act as a STUN server? - -A: Yes. - -Q: How do I implement token-based authentication? - -A: Replace the username with a token in the [AuthHandler](https://github.com/pion/turn/blob/6d0ff435910870eb9024b18321b93b61844fcfec/examples/turn-server/simple/main.go#L49). -The password sent by the client can be any non-empty string, as long as it matches that used by the [GenerateAuthKey](https://github.com/pion/turn/blob/6d0ff435910870eb9024b18321b93b61844fcfec/examples/turn-server/simple/main.go#L41) -function. - -Q: Will WebRTC prioritize using STUN over TURN? - -A: Yes. \ No newline at end of file diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/allocation/five_tuple.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/allocation/five_tuple.go deleted file mode 100644 index 1f2b3b5b6..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/allocation/five_tuple.go +++ /dev/null @@ -1,36 +0,0 @@ -package allocation - -import ( - "fmt" - "net" -) - -// Protocol is an enum for relay protocol -type Protocol uint8 - -// Network protocols for relay -const ( - UDP Protocol = iota - TCP -) - -// FiveTuple is the combination (client IP address and port, server IP -// address and port, and transport protocol (currently one of UDP, -// TCP, or TLS)) used to communicate between the client and the -// server. The 5-tuple uniquely identifies this communication -// stream. The 5-tuple also uniquely identifies the Allocation on -// the server. -type FiveTuple struct { - Protocol - SrcAddr, DstAddr net.Addr -} - -// Equal asserts if two FiveTuples are equal -func (f *FiveTuple) Equal(b *FiveTuple) bool { - return f.Fingerprint() == b.Fingerprint() -} - -// Fingerprint is the identity of a FiveTuple -func (f *FiveTuple) Fingerprint() string { - return fmt.Sprintf("%d_%s_%s", f.Protocol, f.SrcAddr.String(), f.DstAddr.String()) -} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/lt_cred.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/lt_cred.go deleted file mode 100644 index d4e9ab565..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/lt_cred.go +++ /dev/null @@ -1,56 +0,0 @@ -package turn - -import ( //nolint:gci - "crypto/hmac" - "crypto/sha1" //nolint:gosec,gci - "encoding/base64" - "net" - "strconv" - "time" - - "github.com/pion/logging" -) - -// GenerateLongTermCredentials can be used to create credentials valid for [duration] time -func GenerateLongTermCredentials(sharedSecret string, duration time.Duration) (string, string, error) { - t := time.Now().Add(duration).Unix() - username := strconv.FormatInt(t, 10) - password, err := longTermCredentials(username, sharedSecret) - return username, password, err -} - -func longTermCredentials(username string, sharedSecret string) (string, error) { - mac := hmac.New(sha1.New, []byte(sharedSecret)) - _, err := mac.Write([]byte(username)) - if err != nil { - return "", err // Not sure if this will ever happen - } - password := mac.Sum(nil) - return base64.StdEncoding.EncodeToString(password), nil -} - -// NewLongTermAuthHandler returns a turn.AuthAuthHandler used with Long Term (or Time Windowed) Credentials. -// https://tools.ietf.org/search/rfc5389#section-10.2 -func NewLongTermAuthHandler(sharedSecret string, l logging.LeveledLogger) AuthHandler { - if l == nil { - l = logging.NewDefaultLoggerFactory().NewLogger("turn") - } - return func(username, realm string, srcAddr net.Addr) (key []byte, ok bool) { - l.Tracef("Authentication username=%q realm=%q srcAddr=%v", username, realm, srcAddr) - t, err := strconv.Atoi(username) - if err != nil { - l.Errorf("Invalid time-windowed username %q", username) - return nil, false - } - if int64(t) < time.Now().Unix() { - l.Errorf("Expired time-windowed username %q", username) - return nil, false - } - password, err := longTermCredentials(username, sharedSecret) - if err != nil { - l.Error(err.Error()) - return nil, false - } - return GenerateAuthKey(username, realm, password), true - } -} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/.gitignore b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/.gitignore similarity index 75% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/.gitignore rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/.gitignore index f977e7485..6e2f206a9 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/.gitignore +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/.gitignore @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2023 The Pion community +# SPDX-License-Identifier: MIT + ### JetBrains IDE ### ##################### .idea/ diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/.golangci.yml b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/.golangci.yml similarity index 95% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/.golangci.yml rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/.golangci.yml index 4e3eddf42..e06de4d3c 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/stun/.golangci.yml +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/.golangci.yml @@ -3,7 +3,8 @@ linters-settings: govet: - check-shadowing: true + enable: + - shadow misspell: locale: US exhaustive: @@ -29,7 +30,6 @@ linters: - bodyclose # checks whether HTTP response body is closed successfully - contextcheck # check the function whether use a non-inherited context - decorder # check declaration order and count of types, constants, variables and functions - - depguard # Go linter that checks if package imports are in a list of acceptable packages - dogsled # Checks assignments with too many blank identifiers (e.g. x, _, _, _, := f()) - dupl # Tool for code clone detection - durationcheck # check for two durations multiplied together @@ -63,7 +63,6 @@ linters: - importas # Enforces consistent import aliases - ineffassign # Detects when assignments to existing variables are not used - misspell # Finds commonly misspelled English words in comments - - nakedret # Finds naked returns in functions greater than a specified function length - nilerr # Finds the code that returns nil even if it checks that the error is not nil. - nilnil # Checks that there is no simultaneous return of `nil` error and an invalid value. - noctx # noctx finds sending http request without context.Context @@ -81,6 +80,7 @@ linters: - wastedassign # wastedassign finds wasted assignment statements - whitespace # Tool for detection of leading and trailing whitespace disable: + - depguard # Go linter that checks if package imports are in a list of acceptable packages - containedctx # containedctx is a linter that detects struct contained context.Context field - cyclop # checks function and package cyclomatic complexity - exhaustivestruct # Checks if all struct's fields are initialized @@ -94,6 +94,7 @@ linters: - maintidx # maintidx measures the maintainability index of each function. - makezero # Finds slice declarations with non-zero initial length - maligned # Tool to detect Go structs that would take less memory if their fields were sorted + - nakedret # Finds naked returns in functions greater than a specified function length - nestif # Reports deeply nested if statements - nlreturn # nlreturn checks for a new line before return and branch statements to increase code clarity - nolintlint # Reports ill-formed or insufficient nolint directives @@ -110,28 +111,15 @@ linters: issues: exclude-use-default: false + exclude-dirs-use-default: false exclude-rules: - # Allow complex tests, better to be self contained - - path: _test\.go - linters: - - gocognit - - forbidigo - - # Allow complex main function in examples - - path: examples - text: "of func `main` is high" - linters: - - gocognit - - # Allow forbidden identifiers in examples - - path: examples + # Allow complex tests and examples, better to be self contained + - path: (examples|main\.go|_test\.go) linters: - forbidigo + - gocognit # Allow forbidden identifiers in CLI commands - path: cmd linters: - forbidigo - -run: - skip-dirs-use-default: false diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/.goreleaser.yml b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/.goreleaser.yml new file mode 100644 index 000000000..30093e9d6 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/.goreleaser.yml @@ -0,0 +1,5 @@ +# SPDX-FileCopyrightText: 2023 The Pion community +# SPDX-License-Identifier: MIT + +builds: +- skip: true diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/LICENSE b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/LICENSE similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/LICENSE rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/LICENSE diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/README.md b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/README.md similarity index 59% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/README.md rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/README.md index b8901fd30..a571c0ba9 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/README.md +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/README.md @@ -10,10 +10,10 @@ Slack Widget
- Build Status - GoDoc + GitHub Workflow Status + Go Reference Coverage Status - Go Report Card + Go Report Card License: MIT


@@ -28,7 +28,7 @@ Pion TURN is a Go toolkit for building TURN servers and clients. We wrote it to * **Safe** - Stability and safety is important for network services. Go provides everything we need. * **Scalable** - Create allocations and mutate state at runtime. Designed to make scaling easy. -# Using +### Using `pion/turn` is an API for building STUN/TURN clients and servers, not a binary you deploy then configure. It may require copying our examples and making minor modifications to fit your need, no knowledge of Go is required however. You may be able to download the pre-made binaries of our examples if you wish to get started quickly. @@ -37,7 +37,7 @@ The advantage of this is that you don't need to deal with complicated config fil After you instantiate an instance of a Pion TURN server or client you interact with it like any library. The quickest way to get started is to look at the [examples](examples) or [GoDoc](https://godoc.org/github.com/pion/turn) -# Examples +### Examples We try to cover most common use cases in [examples](examples). If more examples could be helpful please file an issue, we are always looking to expand and improve `pion/turn` to make it easier for developers. @@ -46,24 +46,48 @@ It is also very easy to [cross compile](https://dave.cheney.net/2015/08/22/cross You can also see `pion/turn` usage in [pion/ice](https://github.com/pion/ice) -# [FAQ](https://github.com/pion/webrtc/wiki/FAQ) +### FAQ + +Also take a look at the [Pion WebRTC FAQ](https://github.com/pion/webrtc/wiki/FAQ) + +#### Will pion/turn also act as a STUN server? +Yes. + +#### How do I implement token-based authentication? +Replace the username with a token in the [AuthHandler](https://github.com/pion/turn/blob/6d0ff435910870eb9024b18321b93b61844fcfec/examples/turn-server/simple/main.go#L49). +The password sent by the client can be any non-empty string, as long as it matches that used by the [GenerateAuthKey](https://github.com/pion/turn/blob/6d0ff435910870eb9024b18321b93b61844fcfec/examples/turn-server/simple/main.go#L41) +function. + +#### Will WebRTC prioritize using STUN over TURN? +Yes. ### RFCs #### Implemented -* [RFC 5389: Session Traversal Utilities for NAT (STUN)](https://tools.ietf.org/html/rfc5389) -* [RFC 5766: Traversal Using Relays around NAT (TURN)](https://tools.ietf.org/html/rfc5766) +* **RFC 5389**: [Session Traversal Utilities for NAT (STUN)][rfc5389] +* **RFC 5766**: [Traversal Using Relays around NAT (TURN): Relay Extensions to Session Traversal Utilities for NAT (STUN)][rfc5766] #### Planned -* [RFC 6062: Traversal Using Relays around NAT (TURN) Extensions for TCP Allocations](https://tools.ietf.org/html/rfc6062) -* [RFC 6156: Traversal Using Relays around NAT (TURN) Extension for IPv6](https://tools.ietf.org/html/rfc6156) +* **RFC 6062**: [Traversal Using Relays around NAT (TURN) Extensions for TCP Allocations][rfc6062] +* **RFC 6156**: [Traversal Using Relays around NAT (TURN) Extension for IPv6][rfc6156] + +[rfc5389]: https://tools.ietf.org/html/rfc5389 +[rfc5766]: https://tools.ietf.org/html/rfc5766 +[rfc6062]: https://tools.ietf.org/html/rfc6062 +[rfc6156]: https://tools.ietf.org/html/rfc6156 + +### Roadmap +The library is used as a part of our WebRTC implementation. Please refer to that [roadmap](https://github.com/pion/webrtc/issues/9) to track our major milestones. ### Community -Pion has an active community on the [Golang Slack](https://pion.ly/slack). Sign up and join the **#pion** channel for discussions and support. +Pion has an active community on the [Slack](https://pion.ly/slack). + +Follow the [Pion Twitter](https://twitter.com/_pion) for project updates and important WebRTC news. We are always looking to support **your projects**. Please reach out if you have something to build! +If you need commercial support or don't want to use public methods you can contact us at [team@pion.ly](mailto:team@pion.ly) ### Contributing -Check out the **[contributing wiki](https://github.com/pion/webrtc/wiki/Contributing)** to join the group of amazing people making this project possible. +Check out the [contributing wiki](https://github.com/pion/webrtc/wiki/Contributing) to join the group of amazing people making this project possible ### License -MIT License - see [LICENSE.md](LICENSE.md) for full text +MIT License - see [LICENSE](LICENSE) for full text diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/client.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/client.go similarity index 63% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/client.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/client.go index 5e675fd36..6e38ae109 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/client.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/client.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package turn import ( @@ -9,18 +12,17 @@ import ( "time" "github.com/pion/logging" - "github.com/pion/stun" - "github.com/pion/transport/v2" - "github.com/pion/transport/v2/stdnet" - "github.com/pion/transport/v2/vnet" - "github.com/pion/turn/v2/internal/client" - "github.com/pion/turn/v2/internal/proto" + "github.com/pion/stun/v3" + "github.com/pion/transport/v3" + "github.com/pion/transport/v3/stdnet" + "github.com/pion/turn/v4/internal/client" + "github.com/pion/turn/v4/internal/proto" ) const ( defaultRTO = 200 * time.Millisecond - maxRtxCount = 7 // total 7 requests (Rc) - maxDataBufferSize = math.MaxUint16 // message size limit for Chromium + maxRtxCount = 7 // Total 7 requests (Rc) + maxDataBufferSize = math.MaxUint16 // Message size limit for Chromium ) // interval [msec] @@ -43,31 +45,31 @@ type ClientConfig struct { Software string RTO time.Duration Conn net.PacketConn // Listening socket (net.PacketConn) - LoggerFactory logging.LoggerFactory Net transport.Net + LoggerFactory logging.LoggerFactory } // Client is a STUN server client type Client struct { - conn net.PacketConn // read-only - stunServ net.Addr // read-only - turnServ net.Addr // read-only - stunServStr string // read-only, used for de-multiplexing - turnServStr string // read-only, used for de-multiplexing - username stun.Username // read-only - password string // read-only - realm stun.Realm // read-only - integrity stun.MessageIntegrity // read-only - software stun.Software // read-only - trMap *client.TransactionMap // thread-safe - rto time.Duration // read-only - relayedConn *client.UDPConn // protected by mutex *** - allocTryLock client.TryLock // thread-safe - listenTryLock client.TryLock // thread-safe - net transport.Net // read-only - mutex sync.RWMutex // thread-safe - mutexTrMap sync.Mutex // thread-safe - log logging.LeveledLogger // read-only + conn net.PacketConn // Read-only + net transport.Net // Read-only + stunServerAddr net.Addr // Read-only + turnServerAddr net.Addr // Read-only + + username stun.Username // Read-only + password string // Read-only + realm stun.Realm // Read-only + integrity stun.MessageIntegrity // Read-only + software stun.Software // Read-only + trMap *client.TransactionMap // Thread-safe + rto time.Duration // Read-only + relayedConn *client.UDPConn // Protected by mutex *** + tcpAllocation *client.TCPAllocation // Protected by mutex *** + allocTryLock client.TryLock // Thread-safe + listenTryLock client.TryLock // Thread-safe + mutex sync.RWMutex // Thread-safe + mutexTrMap sync.Mutex // Thread-safe + log logging.LeveledLogger // Read-only } // NewClient returns a new Client instance. listeningAddress is the address and port to listen on, default "0.0.0.0:0" @@ -83,56 +85,52 @@ func NewClient(config *ClientConfig) (*Client, error) { return nil, errNilConn } - var err error - if config.Net == nil { - config.Net, err = stdnet.NewNet() // defaults to native operation - if err != nil { - return nil, err - } - } else if _, ok := config.Net.(*vnet.Net); ok { - log.Warn("Virtual network is enabled") - } - - var stunServ, turnServ net.Addr - var stunServStr, turnServStr string - if len(config.STUNServerAddr) > 0 { - log.Debugf("resolving %s", config.STUNServerAddr) - stunServ, err = config.Net.ResolveUDPAddr("udp4", config.STUNServerAddr) - if err != nil { - return nil, err - } - stunServStr = stunServ.String() - log.Debugf("stunServ: %s", stunServStr) - } - if len(config.TURNServerAddr) > 0 { - log.Debugf("resolving %s", config.TURNServerAddr) - turnServ, err = config.Net.ResolveUDPAddr("udp4", config.TURNServerAddr) - if err != nil { - return nil, err - } - turnServStr = turnServ.String() - log.Debugf("turnServ: %s", turnServStr) - } - rto := defaultRTO if config.RTO > 0 { rto = config.RTO } + if config.Net == nil { + n, err := stdnet.NewNet() + if err != nil { + return nil, err + } + config.Net = n + } + + var stunServ, turnServ net.Addr + var err error + + if len(config.STUNServerAddr) > 0 { + stunServ, err = config.Net.ResolveUDPAddr("udp4", config.STUNServerAddr) + if err != nil { + return nil, err + } + + log.Debugf("Resolved STUN server %s to %s", config.STUNServerAddr, stunServ) + } + + if len(config.TURNServerAddr) > 0 { + turnServ, err = config.Net.ResolveUDPAddr("udp4", config.TURNServerAddr) + if err != nil { + return nil, err + } + + log.Debugf("Resolved TURN server %s to %s", config.TURNServerAddr, turnServ) + } + c := &Client{ - conn: config.Conn, - stunServ: stunServ, - turnServ: turnServ, - stunServStr: stunServStr, - turnServStr: turnServStr, - username: stun.NewUsername(config.Username), - password: config.Password, - realm: stun.NewRealm(config.Realm), - software: stun.NewSoftware(config.Software), - net: config.Net, - trMap: client.NewTransactionMap(), - rto: rto, - log: log, + conn: config.Conn, + stunServerAddr: stunServ, + turnServerAddr: turnServ, + username: stun.NewUsername(config.Username), + password: config.Password, + realm: stun.NewRealm(config.Realm), + software: stun.NewSoftware(config.Software), + trMap: client.NewTransactionMap(), + net: config.Net, + rto: rto, + log: log, } return c, nil @@ -140,12 +138,12 @@ func NewClient(config *ClientConfig) (*Client, error) { // TURNServerAddr return the TURN server address func (c *Client) TURNServerAddr() net.Addr { - return c.turnServ + return c.turnServerAddr } // STUNServerAddr return the STUN server address func (c *Client) STUNServerAddr() net.Addr { - return c.stunServ + return c.stunServerAddr } // Username returns username @@ -176,13 +174,13 @@ func (c *Client) Listen() error { for { n, from, err := c.conn.ReadFrom(buf) if err != nil { - c.log.Debugf("exiting read loop: %s", err.Error()) + c.log.Debugf("Failed to read: %s. Exiting loop", err) break } _, err = c.HandleInbound(buf[:n], from) if err != nil { - c.log.Debugf("exiting read loop: %s", err.Error()) + c.log.Debugf("Failed to handle inbound message: %s. Exiting loop", err) break } } @@ -232,10 +230,84 @@ func (c *Client) SendBindingRequestTo(to net.Addr) (net.Addr, error) { // SendBindingRequest sends a new STUN request to the STUN server func (c *Client) SendBindingRequest() (net.Addr, error) { - if c.stunServ == nil { + if c.stunServerAddr == nil { return nil, errSTUNServerAddressNotSet } - return c.SendBindingRequestTo(c.stunServ) + return c.SendBindingRequestTo(c.stunServerAddr) +} + +func (c *Client) sendAllocateRequest(protocol proto.Protocol) (proto.RelayedAddress, proto.Lifetime, stun.Nonce, error) { + var relayed proto.RelayedAddress + var lifetime proto.Lifetime + var nonce stun.Nonce + + msg, err := stun.Build( + stun.TransactionID, + stun.NewType(stun.MethodAllocate, stun.ClassRequest), + proto.RequestedTransport{Protocol: protocol}, + stun.Fingerprint, + ) + if err != nil { + return relayed, lifetime, nonce, err + } + + trRes, err := c.PerformTransaction(msg, c.turnServerAddr, false) + if err != nil { + return relayed, lifetime, nonce, err + } + + res := trRes.Msg + + // Anonymous allocate failed, trying to authenticate. + if err = nonce.GetFrom(res); err != nil { + return relayed, lifetime, nonce, err + } + if err = c.realm.GetFrom(res); err != nil { + return relayed, lifetime, nonce, err + } + c.realm = append([]byte(nil), c.realm...) + c.integrity = stun.NewLongTermIntegrity( + c.username.String(), c.realm.String(), c.password, + ) + // Trying to authorize. + msg, err = stun.Build( + stun.TransactionID, + stun.NewType(stun.MethodAllocate, stun.ClassRequest), + proto.RequestedTransport{Protocol: protocol}, + &c.username, + &c.realm, + &nonce, + &c.integrity, + stun.Fingerprint, + ) + if err != nil { + return relayed, lifetime, nonce, err + } + + trRes, err = c.PerformTransaction(msg, c.turnServerAddr, false) + if err != nil { + return relayed, lifetime, nonce, err + } + res = trRes.Msg + + if res.Type.Class == stun.ClassErrorResponse { + var code stun.ErrorCodeAttribute + if err = code.GetFrom(res); err == nil { + return relayed, lifetime, nonce, fmt.Errorf("%s (error %s)", res.Type, code) //nolint:goerr113 + } + return relayed, lifetime, nonce, fmt.Errorf("%s", res.Type) //nolint:goerr113 + } + + // Getting relayed addresses from response. + if err := relayed.GetFrom(res); err != nil { + return relayed, lifetime, nonce, err + } + + // Getting lifetime from response + if err := lifetime.GetFrom(res); err != nil { + return relayed, lifetime, nonce, err + } + return relayed, lifetime, nonce, nil } // Allocate sends a TURN allocation request to the given transport address @@ -250,98 +322,88 @@ func (c *Client) Allocate() (net.PacketConn, error) { return nil, fmt.Errorf("%w: %s", errAlreadyAllocated, relayedConn.LocalAddr().String()) } - msg, err := stun.Build( - stun.TransactionID, - stun.NewType(stun.MethodAllocate, stun.ClassRequest), - proto.RequestedTransport{Protocol: proto.ProtoUDP}, - stun.Fingerprint, - ) + relayed, lifetime, nonce, err := c.sendAllocateRequest(proto.ProtoUDP) if err != nil { return nil, err } - trRes, err := c.PerformTransaction(msg, c.turnServ, false) - if err != nil { - return nil, err - } - - res := trRes.Msg - - // Anonymous allocate failed, trying to authenticate. - var nonce stun.Nonce - if err = nonce.GetFrom(res); err != nil { - return nil, err - } - if err = c.realm.GetFrom(res); err != nil { - return nil, err - } - c.realm = append([]byte(nil), c.realm...) - c.integrity = stun.NewLongTermIntegrity( - c.username.String(), c.realm.String(), c.password, - ) - // Trying to authorize. - msg, err = stun.Build( - stun.TransactionID, - stun.NewType(stun.MethodAllocate, stun.ClassRequest), - proto.RequestedTransport{Protocol: proto.ProtoUDP}, - &c.username, - &c.realm, - &nonce, - &c.integrity, - stun.Fingerprint, - ) - if err != nil { - return nil, err - } - - trRes, err = c.PerformTransaction(msg, c.turnServ, false) - if err != nil { - return nil, err - } - res = trRes.Msg - - if res.Type.Class == stun.ClassErrorResponse { - var code stun.ErrorCodeAttribute - if err = code.GetFrom(res); err == nil { - return nil, fmt.Errorf("%s (error %s)", res.Type, code) //nolint:goerr113 - } - return nil, fmt.Errorf("%s", res.Type) //nolint:goerr113 - } - - // Getting relayed addresses from response. - var relayed proto.RelayedAddress - if err := relayed.GetFrom(res); err != nil { - return nil, err - } relayedAddr := &net.UDPAddr{ IP: relayed.IP, Port: relayed.Port, } - // Getting lifetime from response - var lifetime proto.Lifetime - if err := lifetime.GetFrom(res); err != nil { - return nil, err - } - - relayedConn = client.NewUDPConn(&client.UDPConnConfig{ - Observer: c, + relayedConn = client.NewUDPConn(&client.AllocationConfig{ + Client: c, RelayedAddr: relayedAddr, + ServerAddr: c.turnServerAddr, + Realm: c.realm, + Username: c.username, Integrity: c.integrity, Nonce: nonce, Lifetime: lifetime.Duration, + Net: c.net, Log: c.log, }) - c.setRelayedUDPConn(relayedConn) return relayedConn, nil } +// AllocateTCP creates a new TCP allocation at the TURN server. +func (c *Client) AllocateTCP() (*client.TCPAllocation, error) { + if err := c.allocTryLock.Lock(); err != nil { + return nil, fmt.Errorf("%w: %s", errOneAllocateOnly, err.Error()) + } + defer c.allocTryLock.Unlock() + + allocation := c.getTCPAllocation() + if allocation != nil { + return nil, fmt.Errorf("%w: %s", errAlreadyAllocated, allocation.Addr()) + } + + relayed, lifetime, nonce, err := c.sendAllocateRequest(proto.ProtoTCP) + if err != nil { + return nil, err + } + + relayedAddr := &net.TCPAddr{ + IP: relayed.IP, + Port: relayed.Port, + } + + allocation = client.NewTCPAllocation(&client.AllocationConfig{ + Client: c, + RelayedAddr: relayedAddr, + ServerAddr: c.turnServerAddr, + Realm: c.realm, + Username: c.username, + Integrity: c.integrity, + Nonce: nonce, + Lifetime: lifetime.Duration, + Net: c.net, + Log: c.log, + }) + + c.setTCPAllocation(allocation) + + return allocation, nil +} + // CreatePermission Issues a CreatePermission request for the supplied addresses // as described in https://datatracker.ietf.org/doc/html/rfc5766#section-9 func (c *Client) CreatePermission(addrs ...net.Addr) error { - return c.relayedUDPConn().CreatePermissions(addrs...) + if conn := c.relayedUDPConn(); conn != nil { + if err := conn.CreatePermissions(addrs...); err != nil { + return err + } + } + + if allocation := c.getTCPAllocation(); allocation != nil { + if err := allocation.CreatePermissions(addrs...); err != nil { + return err + } + } + return nil } // PerformTransaction performs STUN transaction @@ -363,7 +425,7 @@ func (c *Client) PerformTransaction(msg *stun.Message, to net.Addr, ignoreResult c.trMap.Insert(trKey, tr) - c.log.Tracef("start %s transaction %s to %s", msg.Type, trKey, tr.To.String()) + c.log.Tracef("Start %s transaction %s to %s", msg.Type, trKey, tr.To) _, err := c.conn.WriteTo(tr.Raw, to) if err != nil { return client.TransactionResult{}, err @@ -371,7 +433,7 @@ func (c *Client) PerformTransaction(msg *stun.Message, to net.Addr, ignoreResult tr.StartRtxTimer(c.onRtxTimeout) - // If dontWait is true, get the transaction going and return immediately + // If ignoreResult is true, get the transaction going and return immediately if ignoreResult { return client.TransactionResult{}, nil } @@ -385,8 +447,9 @@ func (c *Client) PerformTransaction(msg *stun.Message, to net.Addr, ignoreResult // OnDeallocated is called when de-allocation of relay address has been complete. // (Called by UDPConn) -func (c *Client) OnDeallocated(relayedAddr net.Addr) { +func (c *Client) OnDeallocated(net.Addr) { c.setRelayedUDPConn(nil) + c.setTCPAllocation(nil) } // HandleInbound handles data received. @@ -420,12 +483,12 @@ func (c *Client) HandleInbound(data []byte, from net.Addr) (bool, error) { return true, c.handleSTUNMessage(data, from) case proto.IsChannelData(data): return true, c.handleChannelData(data) - case len(c.stunServStr) != 0 && from.String() == c.stunServStr: - // received from STUN server but it is not a STUN message + case c.stunServerAddr != nil && from.String() == c.stunServerAddr.String(): + // Received from STUN server but it is not a STUN message return true, errNonSTUNMessage default: - // assume, this is an application data - c.log.Tracef("non-STUN/TURN packet, unhandled") + // Assume, this is an application data + c.log.Tracef("Ignoring non-STUN/TURN packet") } return false, nil @@ -445,7 +508,8 @@ func (c *Client) handleSTUNMessage(data []byte, from net.Addr) error { } if msg.Type.Class == stun.ClassIndication { - if msg.Type.Method == stun.MethodData { + switch msg.Type.Method { + case stun.MethodData: var peerAddr proto.PeerAddress if err := peerAddr.GetFrom(msg); err != nil { return err @@ -460,15 +524,41 @@ func (c *Client) handleSTUNMessage(data []byte, from net.Addr) error { return err } - c.log.Debugf("data indication received from %s", from.String()) + c.log.Tracef("Data indication received from %s", from) relayedConn := c.relayedUDPConn() if relayedConn == nil { - c.log.Debug("no relayed conn allocated") - return nil // silently discard + c.log.Debug("No relayed conn allocated") + return nil // Silently discard + } + relayedConn.HandleInbound(data, from) + case stun.MethodConnectionAttempt: + var peerAddr proto.PeerAddress + if err := peerAddr.GetFrom(msg); err != nil { + return err } - relayedConn.HandleInbound(data, from) + addr := &net.TCPAddr{ + IP: peerAddr.IP, + Port: peerAddr.Port, + } + + var cid proto.ConnectionID + if err := cid.GetFrom(msg); err != nil { + return err + } + + c.log.Debugf("Connection attempt from %s", addr) + + allocation := c.getTCPAllocation() + if allocation == nil { + c.log.Debug("No TCP allocation exists") + return nil // Silently discard + } + + allocation.HandleConnectionAttempt(addr, cid) + default: + c.log.Debug("Received unsupported STUN method") } return nil } @@ -484,8 +574,8 @@ func (c *Client) handleSTUNMessage(data []byte, from net.Addr) error { tr, ok := c.trMap.Find(trKey) if !ok { c.mutexTrMap.Unlock() - // silently discard - c.log.Debugf("no transaction for %s", msg.String()) + // Silently discard + c.log.Debugf("No transaction for %s", msg) return nil } @@ -499,7 +589,7 @@ func (c *Client) handleSTUNMessage(data []byte, from net.Addr) error { From: from, Retries: tr.Retries(), }) { - c.log.Debugf("no listener for %s", msg.String()) + c.log.Debugf("No listener for %s", msg) } return nil @@ -516,8 +606,8 @@ func (c *Client) handleChannelData(data []byte) error { relayedConn := c.relayedUDPConn() if relayedConn == nil { - c.log.Debug("no relayed conn allocated") - return nil // silently discard + c.log.Debug("No relayed conn allocated") + return nil // Silently discard } addr, ok := relayedConn.FindAddrByChannelNumber(uint16(chData.Number)) @@ -525,7 +615,7 @@ func (c *Client) handleChannelData(data []byte) error { return fmt.Errorf("%w: %d", errChannelBindNotFound, int(chData.Number)) } - c.log.Tracef("channel data received from %s (ch=%d)", addr.String(), int(chData.Number)) + c.log.Tracef("Channel data received from %s (ch=%d)", addr.String(), int(chData.Number)) relayedConn.HandleInbound(chData.Data, addr) return nil @@ -537,21 +627,21 @@ func (c *Client) onRtxTimeout(trKey string, nRtx int) { tr, ok := c.trMap.Find(trKey) if !ok { - return // already gone + return // Already gone } if nRtx == maxRtxCount { - // all retransmissions failed + // All retransmissions failed c.trMap.Delete(trKey) if !tr.WriteResult(client.TransactionResult{ Err: fmt.Errorf("%w %s", errAllRetransmissionsFailed, trKey), }) { - c.log.Debug("no listener for transaction") + c.log.Debug("No listener for transaction") } return } - c.log.Tracef("retransmitting transaction %s to %s (nRtx=%d)", + c.log.Tracef("Retransmitting transaction %s to %s (nRtx=%d)", trKey, tr.To.String(), nRtx) _, err := c.conn.WriteTo(tr.Raw, tr.To) if err != nil { @@ -559,7 +649,7 @@ func (c *Client) onRtxTimeout(trKey string, nRtx int) { if !tr.WriteResult(client.TransactionResult{ Err: fmt.Errorf("%w %s", errFailedToRetransmitTransaction, trKey), }) { - c.log.Debug("no listener for transaction") + c.log.Debug("No listener for transaction") } return } @@ -579,3 +669,17 @@ func (c *Client) relayedUDPConn() *client.UDPConn { return c.relayedConn } + +func (c *Client) setTCPAllocation(alloc *client.TCPAllocation) { + c.mutex.Lock() + defer c.mutex.Unlock() + + c.tcpAllocation = alloc +} + +func (c *Client) getTCPAllocation() *client.TCPAllocation { + c.mutex.RLock() + defer c.mutex.RUnlock() + + return c.tcpAllocation +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/codecov.yml b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/codecov.yml similarity index 78% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/codecov.yml rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/codecov.yml index 085200a48..263e4d45c 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/codecov.yml +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/codecov.yml @@ -3,6 +3,8 @@ # # It is automatically copied from https://github.com/pion/.goassets repository. # +# SPDX-FileCopyrightText: 2023 The Pion community +# SPDX-License-Identifier: MIT coverage: status: diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/errors.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/errors.go similarity index 91% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/errors.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/errors.go index 12d5e0e86..3ebd26ae8 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/errors.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/errors.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package turn import "errors" @@ -25,4 +28,5 @@ var ( errNonSTUNMessage = errors.New("non-STUN message from STUN server") errFailedToDecodeSTUN = errors.New("failed to decode STUN message") errUnexpectedSTUNRequestMessage = errors.New("unexpected STUN request message") + errRelayAddressGeneratorNil = errors.New("RelayAddressGenerator is nil") ) diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/allocation/allocation.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/allocation/allocation.go similarity index 90% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/allocation/allocation.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/allocation/allocation.go index 7a3ce1ddf..5b5ff369b 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/allocation/allocation.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/allocation/allocation.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + // Package allocation contains all CRUD operations for allocations package allocation @@ -8,9 +11,9 @@ import ( "time" "github.com/pion/logging" - "github.com/pion/stun" - "github.com/pion/turn/v2/internal/ipnet" - "github.com/pion/turn/v2/internal/proto" + "github.com/pion/stun/v3" + "github.com/pion/turn/v4/internal/ipnet" + "github.com/pion/turn/v4/internal/proto" ) type allocationResponse struct { @@ -34,23 +37,13 @@ type Allocation struct { closed chan interface{} log logging.LeveledLogger - // some clients (Firefox or others using resiprocate's nICE lib) may retry allocation + // Some clients (Firefox or others using resiprocate's nICE lib) may retry allocation // with same 5 tuple when received 413, for compatible with these clients, // cache for response lost and client retry to implement 'stateless stack approach' - // https://datatracker.ietf.org/doc/html/rfc5766#section-6.2 + // See: https://datatracker.ietf.org/doc/html/rfc5766#section-6.2 responseCache atomic.Value // *allocationResponse } -func addr2IPFingerprint(addr net.Addr) string { - switch a := addr.(type) { - case *net.UDPAddr: - return a.IP.String() - case *net.TCPAddr: // Do we really need this case? - return a.IP.String() - } - return "" // should never happen -} - // NewAllocation creates a new instance of NewAllocation. func NewAllocation(turnSocket net.PacketConn, fiveTuple *FiveTuple, log logging.LeveledLogger) *Allocation { return &Allocation{ @@ -67,12 +60,12 @@ func (a *Allocation) GetPermission(addr net.Addr) *Permission { a.permissionsLock.RLock() defer a.permissionsLock.RUnlock() - return a.permissions[addr2IPFingerprint(addr)] + return a.permissions[ipnet.FingerprintAddr(addr)] } // AddPermission adds a new permission to the allocation func (a *Allocation) AddPermission(p *Permission) { - fingerprint := addr2IPFingerprint(p.Addr) + fingerprint := ipnet.FingerprintAddr(p.Addr) a.permissionsLock.RLock() existedPermission, ok := a.permissions[fingerprint] @@ -95,7 +88,7 @@ func (a *Allocation) AddPermission(p *Permission) { func (a *Allocation) RemovePermission(addr net.Addr) { a.permissionsLock.Lock() defer a.permissionsLock.Unlock() - delete(a.permissions, addr2IPFingerprint(addr)) + delete(a.permissions, ipnet.FingerprintAddr(addr)) } // AddChannelBind adds a new ChannelBind to the allocation, it also updates the @@ -250,10 +243,10 @@ func (a *Allocation) packetHandler(m *Manager) { return } - a.log.Debugf("relay socket %s received %d bytes from %s", - a.RelaySocket.LocalAddr().String(), + a.log.Debugf("Relay socket %s received %d bytes from %s", + a.RelaySocket.LocalAddr(), n, - srcAddr.String()) + srcAddr) if channel := a.GetChannelByAddr(srcAddr); channel != nil { channelData := &proto.ChannelData{ @@ -280,14 +273,14 @@ func (a *Allocation) packetHandler(m *Manager) { a.log.Errorf("Failed to send DataIndication from allocation %v %v", srcAddr, err) return } - a.log.Debugf("relaying message from %s to client at %s", - srcAddr.String(), - a.fiveTuple.SrcAddr.String()) + a.log.Debugf("Relaying message from %s to client at %s", + srcAddr, + a.fiveTuple.SrcAddr) if _, err = a.TurnSocket.WriteTo(msg.Raw, a.fiveTuple.SrcAddr); err != nil { a.log.Errorf("Failed to send DataIndication from allocation %v %v", srcAddr, err) } } else { - a.log.Infof("No Permission or Channel exists for %v on allocation %v", srcAddr, a.RelayAddr.String()) + a.log.Infof("No Permission or Channel exists for %v on allocation %v", srcAddr, a.RelayAddr) } } } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/allocation/allocation_manager.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/allocation/allocation_manager.go similarity index 94% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/allocation/allocation_manager.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/allocation/allocation_manager.go index 5e924ac64..2b7659212 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/allocation/allocation_manager.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/allocation/allocation_manager.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package allocation import ( @@ -27,7 +30,7 @@ type Manager struct { lock sync.RWMutex log logging.LeveledLogger - allocations map[string]*Allocation + allocations map[FiveTupleFingerprint]*Allocation reservations []*reservation allocatePacketConn func(network string, requestedPort int) (net.PacketConn, net.Addr, error) @@ -48,7 +51,7 @@ func NewManager(config ManagerConfig) (*Manager, error) { return &Manager{ log: config.LeveledLogger, - allocations: make(map[string]*Allocation, 64), + allocations: make(map[FiveTupleFingerprint]*Allocation, 64), allocatePacketConn: config.AllocatePacketConn, allocateConn: config.AllocateConn, permissionHandler: config.PermissionHandler, @@ -110,7 +113,7 @@ func (m *Manager) CreateAllocation(fiveTuple *FiveTuple, turnSocket net.PacketCo a.RelaySocket = conn a.RelayAddr = relayAddr - m.log.Debugf("listening on relay addr: %s", a.RelayAddr.String()) + m.log.Debugf("Listening on relay address: %s", a.RelayAddr) a.lifetimeTimer = time.AfterFunc(lifetime, func() { m.DeleteAllocation(a.fiveTuple) @@ -202,7 +205,7 @@ func (m *Manager) GetRandomEvenPort() (int, error) { // GrantPermission handles permission requests by calling the permission handler callback // associated with the TURN server listener socket func (m *Manager) GrantPermission(sourceAddr net.Addr, peerIP net.IP) error { - // no permission handler: open + // No permission handler: open if m.permissionHandler == nil { return nil } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/allocation/channel_bind.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/allocation/channel_bind.go similarity index 83% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/allocation/channel_bind.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/allocation/channel_bind.go index 6216369d7..19b184317 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/allocation/channel_bind.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/allocation/channel_bind.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package allocation import ( @@ -5,11 +8,11 @@ import ( "time" "github.com/pion/logging" - "github.com/pion/turn/v2/internal/proto" + "github.com/pion/turn/v4/internal/proto" ) // ChannelBind represents a TURN Channel -// https://tools.ietf.org/html/rfc5766#section-2.5 +// See: https://tools.ietf.org/html/rfc5766#section-2.5 type ChannelBind struct { Peer net.Addr Number proto.ChannelNumber diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/allocation/errors.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/allocation/errors.go similarity index 92% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/allocation/errors.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/allocation/errors.go index b9677e11a..584073c93 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/allocation/errors.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/allocation/errors.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package allocation import "errors" diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/allocation/five_tuple.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/allocation/five_tuple.go new file mode 100644 index 000000000..6d812caf7 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/allocation/five_tuple.go @@ -0,0 +1,63 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + +package allocation + +import ( + "net" +) + +// Protocol is an enum for relay protocol +type Protocol uint8 + +// Network protocols for relay +const ( + UDP Protocol = iota + TCP +) + +// FiveTuple is the combination (client IP address and port, server IP +// address and port, and transport protocol (currently one of UDP, +// TCP, or TLS)) used to communicate between the client and the +// server. The 5-tuple uniquely identifies this communication +// stream. The 5-tuple also uniquely identifies the Allocation on +// the server. +type FiveTuple struct { + Protocol + SrcAddr, DstAddr net.Addr +} + +// Equal asserts if two FiveTuples are equal +func (f *FiveTuple) Equal(b *FiveTuple) bool { + return f.Fingerprint() == b.Fingerprint() +} + +// FiveTupleFingerprint is a comparable representation of a FiveTuple +type FiveTupleFingerprint struct { + srcIP, dstIP [16]byte + srcPort, dstPort uint16 + protocol Protocol +} + +// Fingerprint is the identity of a FiveTuple +func (f *FiveTuple) Fingerprint() (fp FiveTupleFingerprint) { + srcIP, srcPort := netAddrIPAndPort(f.SrcAddr) + copy(fp.srcIP[:], srcIP) + fp.srcPort = srcPort + dstIP, dstPort := netAddrIPAndPort(f.DstAddr) + copy(fp.dstIP[:], dstIP) + fp.dstPort = dstPort + fp.protocol = f.Protocol + return +} + +func netAddrIPAndPort(addr net.Addr) (net.IP, uint16) { + switch a := addr.(type) { + case *net.UDPAddr: + return a.IP.To16(), uint16(a.Port) + case *net.TCPAddr: + return a.IP.To16(), uint16(a.Port) + default: + return nil, 0 + } +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/allocation/permission.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/allocation/permission.go similarity index 85% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/allocation/permission.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/allocation/permission.go index 03538eb5b..a774f2ceb 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/allocation/permission.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/allocation/permission.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package allocation import ( @@ -11,7 +14,7 @@ const permissionTimeout = time.Duration(5) * time.Minute // Permission represents a TURN permission. TURN permissions mimic the address-restricted // filtering mechanism of NATs that comply with [RFC4787]. -// https://tools.ietf.org/html/rfc5766#section-2.3 +// See: https://tools.ietf.org/html/rfc5766#section-2.3 type Permission struct { Addr net.Addr allocation *Allocation diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/client/allocation.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/client/allocation.go new file mode 100644 index 000000000..a7f746360 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/client/allocation.go @@ -0,0 +1,189 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + +package client + +import ( + "errors" + "fmt" + "net" + "sync" + "time" + + "github.com/pion/logging" + "github.com/pion/stun/v3" + "github.com/pion/transport/v3" + "github.com/pion/turn/v4/internal/proto" +) + +// AllocationConfig is a set of configuration params use by NewUDPConn and NewTCPAllocation +type AllocationConfig struct { + Client Client + RelayedAddr net.Addr + ServerAddr net.Addr + Integrity stun.MessageIntegrity + Nonce stun.Nonce + Username stun.Username + Realm stun.Realm + Lifetime time.Duration + Net transport.Net + Log logging.LeveledLogger +} + +type allocation struct { + client Client // Read-only + relayedAddr net.Addr // Read-only + serverAddr net.Addr // Read-only + permMap *permissionMap // Thread-safe + integrity stun.MessageIntegrity // Read-only + username stun.Username // Read-only + realm stun.Realm // Read-only + _nonce stun.Nonce // Needs mutex x + _lifetime time.Duration // Needs mutex x + net transport.Net // Thread-safe + refreshAllocTimer *PeriodicTimer // Thread-safe + refreshPermsTimer *PeriodicTimer // Thread-safe + readTimer *time.Timer // Thread-safe + mutex sync.RWMutex // Thread-safe + log logging.LeveledLogger // Read-only +} + +func (a *allocation) setNonceFromMsg(msg *stun.Message) { + // Update nonce + var nonce stun.Nonce + if err := nonce.GetFrom(msg); err == nil { + a.setNonce(nonce) + a.log.Debug("Refresh allocation: 438, got new nonce.") + } else { + a.log.Warn("Refresh allocation: 438 but no nonce.") + } +} + +func (a *allocation) refreshAllocation(lifetime time.Duration, dontWait bool) error { + msg, err := stun.Build( + stun.TransactionID, + stun.NewType(stun.MethodRefresh, stun.ClassRequest), + proto.Lifetime{Duration: lifetime}, + a.username, + a.realm, + a.nonce(), + a.integrity, + stun.Fingerprint, + ) + if err != nil { + return fmt.Errorf("%w: %s", errFailedToBuildRefreshRequest, err.Error()) + } + + a.log.Debugf("Send refresh request (dontWait=%v)", dontWait) + trRes, err := a.client.PerformTransaction(msg, a.serverAddr, dontWait) + if err != nil { + return fmt.Errorf("%w: %s", errFailedToRefreshAllocation, err.Error()) + } + + if dontWait { + a.log.Debug("Refresh request sent") + return nil + } + + a.log.Debug("Refresh request sent, and waiting response") + + res := trRes.Msg + if res.Type.Class == stun.ClassErrorResponse { + var code stun.ErrorCodeAttribute + if err = code.GetFrom(res); err == nil { + if code.Code == stun.CodeStaleNonce { + a.setNonceFromMsg(res) + return errTryAgain + } + return err + } + return fmt.Errorf("%s", res.Type) //nolint:goerr113 + } + + // Getting lifetime from response + var updatedLifetime proto.Lifetime + if err := updatedLifetime.GetFrom(res); err != nil { + return fmt.Errorf("%w: %s", errFailedToGetLifetime, err.Error()) + } + + a.setLifetime(updatedLifetime.Duration) + a.log.Debugf("Updated lifetime: %d seconds", int(a.lifetime().Seconds())) + return nil +} + +func (a *allocation) refreshPermissions() error { + addrs := a.permMap.addrs() + if len(addrs) == 0 { + a.log.Debug("No permission to refresh") + return nil + } + if err := a.CreatePermissions(addrs...); err != nil { + if errors.Is(err, errTryAgain) { + return errTryAgain + } + a.log.Errorf("Fail to refresh permissions: %s", err) + return err + } + a.log.Debug("Refresh permissions successful") + return nil +} + +func (a *allocation) onRefreshTimers(id int) { + a.log.Debugf("Refresh timer %d expired", id) + switch id { + case timerIDRefreshAlloc: + var err error + lifetime := a.lifetime() + // Limit the max retries on errTryAgain to 3 + // when stale nonce returns, sencond retry should succeed + for i := 0; i < maxRetryAttempts; i++ { + err = a.refreshAllocation(lifetime, false) + if !errors.Is(err, errTryAgain) { + break + } + } + if err != nil { + a.log.Warnf("Failed to refresh allocation: %s", err) + } + case timerIDRefreshPerms: + var err error + for i := 0; i < maxRetryAttempts; i++ { + err = a.refreshPermissions() + if !errors.Is(err, errTryAgain) { + break + } + } + if err != nil { + a.log.Warnf("Failed to refresh permissions: %s", err) + } + } +} + +func (a *allocation) nonce() stun.Nonce { + a.mutex.RLock() + defer a.mutex.RUnlock() + + return a._nonce +} + +func (a *allocation) setNonce(nonce stun.Nonce) { + a.mutex.Lock() + defer a.mutex.Unlock() + + a.log.Debugf("Set new nonce with %d bytes", len(nonce)) + a._nonce = nonce +} + +func (a *allocation) lifetime() time.Duration { + a.mutex.RLock() + defer a.mutex.RUnlock() + + return a._lifetime +} + +func (a *allocation) setLifetime(lifetime time.Duration) { + a.mutex.Lock() + defer a.mutex.Unlock() + + a._lifetime = lifetime +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/client/binding.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/client/binding.go similarity index 85% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/client/binding.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/client/binding.go index f4d6fa2b4..a0217476e 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/client/binding.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/client/binding.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package client import ( @@ -27,13 +30,13 @@ const ( ) type binding struct { - number uint16 // read-only - st bindingState // thread-safe (atomic op) - addr net.Addr // read-only - mgr *bindingManager // read-only - muBind sync.Mutex // thread-safe, for ChannelBind ops - _refreshedAt time.Time // protected by mutex - mutex sync.RWMutex // thread-safe + number uint16 // Read-only + st bindingState // Thread-safe (atomic op) + addr net.Addr // Read-only + mgr *bindingManager // Read-only + muBind sync.Mutex // Thread-safe, for ChannelBind ops + _refreshedAt time.Time // Protected by mutex + mutex sync.RWMutex // Thread-safe } func (b *binding) setState(state bindingState) { diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/client/client.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/client/client.go new file mode 100644 index 000000000..10b49a284 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/client/client.go @@ -0,0 +1,18 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + +// Package client implements the API for a TURN client +package client + +import ( + "net" + + "github.com/pion/stun/v3" +) + +// Client is an interface for the public turn.Client in order to break cyclic dependencies +type Client interface { + WriteTo(data []byte, to net.Addr) (int, error) + PerformTransaction(msg *stun.Message, to net.Addr, dontWait bool) (TransactionResult, error) + OnDeallocated(relayedAddr net.Addr) +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/client/errors.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/client/errors.go similarity index 75% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/client/errors.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/client/errors.go index 7fc816fd0..ff40d2e8a 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/client/errors.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/client/errors.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package client import ( @@ -8,7 +11,8 @@ var ( errFake = errors.New("fake error") errTryAgain = errors.New("try again") errClosed = errors.New("use of closed network connection") - errUDPAddrCast = errors.New("addr is not a net.UDPAddr") + errTCPAddrCast = errors.New("addr is not a TCP address") + errUDPAddrCast = errors.New("addr is not a UDP address") errAlreadyClosed = errors.New("already closed") errDoubleLock = errors.New("try-lock is already locked") errTransactionClosed = errors.New("transaction closed") @@ -16,6 +20,8 @@ var ( errFailedToBuildRefreshRequest = errors.New("failed to build refresh request") errFailedToRefreshAllocation = errors.New("failed to refresh allocation") errFailedToGetLifetime = errors.New("failed to get lifetime from refresh response") + errInvalidTURNAddress = errors.New("invalid TURN server address") + errUnexpectedSTUNRequestMessage = errors.New("unexpected STUN request message") ) type timeoutError struct { diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/client/periodic_timer.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/client/periodic_timer.go similarity index 90% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/client/periodic_timer.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/client/periodic_timer.go index fcd567870..5660bc45e 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/client/periodic_timer.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/client/periodic_timer.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package client import ( @@ -31,7 +34,7 @@ func (t *PeriodicTimer) Start() bool { t.mutex.Lock() defer t.mutex.Unlock() - // this is a noop if the timer is always running + // This is a noop if the timer is always running if t.stopFunc != nil { return false } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/client/permission.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/client/permission.go similarity index 68% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/client/permission.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/client/permission.go index 5546a22e2..0436e4ea6 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/client/permission.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/client/permission.go @@ -1,9 +1,14 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package client import ( "net" "sync" "sync/atomic" + + "github.com/pion/turn/v4/internal/ipnet" ) type permState int32 @@ -14,8 +19,9 @@ const ( ) type permission struct { - st permState // thread-safe (atomic op) - mutex sync.RWMutex // thread-safe + addr net.Addr + st permState // Thread-safe (atomic op) + mutex sync.RWMutex // Thread-safe } func (p *permission) setState(state permState) { @@ -35,39 +41,22 @@ type permissionMap struct { func (m *permissionMap) insert(addr net.Addr, p *permission) bool { m.mutex.Lock() defer m.mutex.Unlock() - - udpAddr, ok := addr.(*net.UDPAddr) - if !ok { - return false - } - - m.permMap[udpAddr.IP.String()] = p + p.addr = addr + m.permMap[ipnet.FingerprintAddr(addr)] = p return true } func (m *permissionMap) find(addr net.Addr) (*permission, bool) { m.mutex.RLock() defer m.mutex.RUnlock() - - udpAddr, ok := addr.(*net.UDPAddr) - if !ok { - return nil, false - } - - p, ok := m.permMap[udpAddr.IP.String()] + p, ok := m.permMap[ipnet.FingerprintAddr(addr)] return p, ok } func (m *permissionMap) delete(addr net.Addr) { m.mutex.Lock() defer m.mutex.Unlock() - - udpAddr, ok := addr.(*net.UDPAddr) - if !ok { - return - } - - delete(m.permMap, udpAddr.IP.String()) + delete(m.permMap, ipnet.FingerprintAddr(addr)) } func (m *permissionMap) addrs() []net.Addr { @@ -75,10 +64,8 @@ func (m *permissionMap) addrs() []net.Addr { defer m.mutex.RUnlock() addrs := []net.Addr{} - for k := range m.permMap { - addrs = append(addrs, &net.UDPAddr{ - IP: net.ParseIP(k), - }) + for _, p := range m.permMap { + addrs = append(addrs, p.addr) } return addrs } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/client/tcp_alloc.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/client/tcp_alloc.go new file mode 100644 index 000000000..82948387c --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/client/tcp_alloc.go @@ -0,0 +1,376 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + +package client + +import ( + "encoding/binary" + "errors" + "fmt" + "math" + "net" + "time" + + "github.com/pion/stun/v3" + "github.com/pion/transport/v3" + "github.com/pion/turn/v4/internal/proto" +) + +var ( + _ transport.TCPListener = (*TCPAllocation)(nil) // Includes type check for net.Listener + _ transport.Dialer = (*TCPAllocation)(nil) +) + +func noDeadline() time.Time { + return time.Time{} +} + +// TCPAllocation is an active TCP allocation on the TURN server +// as specified by RFC 6062. +// The allocation can be used to Dial/Accept relayed outgoing/incoming TCP connections. +type TCPAllocation struct { + connAttemptCh chan *connectionAttempt + acceptTimer *time.Timer + allocation +} + +// NewTCPAllocation creates a new instance of TCPConn +func NewTCPAllocation(config *AllocationConfig) *TCPAllocation { + a := &TCPAllocation{ + connAttemptCh: make(chan *connectionAttempt, 10), + acceptTimer: time.NewTimer(time.Duration(math.MaxInt64)), + allocation: allocation{ + client: config.Client, + relayedAddr: config.RelayedAddr, + serverAddr: config.ServerAddr, + username: config.Username, + realm: config.Realm, + permMap: newPermissionMap(), + integrity: config.Integrity, + _nonce: config.Nonce, + _lifetime: config.Lifetime, + net: config.Net, + log: config.Log, + }, + } + + a.log.Debugf("Initial lifetime: %d seconds", int(a.lifetime().Seconds())) + + a.refreshAllocTimer = NewPeriodicTimer( + timerIDRefreshAlloc, + a.onRefreshTimers, + a.lifetime()/2, + ) + + a.refreshPermsTimer = NewPeriodicTimer( + timerIDRefreshPerms, + a.onRefreshTimers, + permRefreshInterval, + ) + + if a.refreshAllocTimer.Start() { + a.log.Debug("Started refreshAllocTimer") + } + if a.refreshPermsTimer.Start() { + a.log.Debug("Started refreshPermsTimer") + } + + return a +} + +// Connect sends a Connect request to the turn server and returns a chosen connection ID +func (a *TCPAllocation) Connect(peer net.Addr) (proto.ConnectionID, error) { + setters := []stun.Setter{ + stun.TransactionID, + stun.NewType(stun.MethodConnect, stun.ClassRequest), + addr2PeerAddress(peer), + a.username, + a.realm, + a.nonce(), + a.integrity, + stun.Fingerprint, + } + + msg, err := stun.Build(setters...) + if err != nil { + return 0, err + } + + a.log.Debugf("Send connect request (peer=%v)", peer) + trRes, err := a.client.PerformTransaction(msg, a.serverAddr, false) + if err != nil { + return 0, err + } + + res := trRes.Msg + + if res.Type.Class == stun.ClassErrorResponse { + var code stun.ErrorCodeAttribute + if err = code.GetFrom(res); err == nil { + return 0, fmt.Errorf("%s (error %s)", res.Type, code) //nolint:goerr113 + } + + return 0, fmt.Errorf("%s", res.Type) //nolint:goerr113 + } + + var cid proto.ConnectionID + if err := cid.GetFrom(res); err != nil { + return 0, err + } + + a.log.Debugf("Connect request successful (cid=%v)", cid) + return cid, nil +} + +// Dial connects to the address on the named network. +func (a *TCPAllocation) Dial(network, rAddrStr string) (net.Conn, error) { + rAddr, err := net.ResolveTCPAddr(network, rAddrStr) + if err != nil { + return nil, err + } + + return a.DialTCP(network, nil, rAddr) +} + +// DialWithConn connects to the address on the named network with an already existing connection. +// The provided connection must be an already connected TCP connection to the TURN server. +func (a *TCPAllocation) DialWithConn(conn net.Conn, network, rAddrStr string) (*TCPConn, error) { + rAddr, err := net.ResolveTCPAddr(network, rAddrStr) + if err != nil { + return nil, err + } + + return a.DialTCPWithConn(conn, network, rAddr) +} + +// DialTCP acts like Dial for TCP networks. +func (a *TCPAllocation) DialTCP(network string, lAddr, rAddr *net.TCPAddr) (*TCPConn, error) { + var rAddrServer *net.TCPAddr + if addr, ok := a.serverAddr.(*net.TCPAddr); ok { + rAddrServer = &net.TCPAddr{ + IP: addr.IP, + Port: addr.Port, + } + } else if addr, ok := a.serverAddr.(*net.UDPAddr); ok { + rAddrServer = &net.TCPAddr{ + IP: addr.IP, + Port: addr.Port, + } + } else { + return nil, errInvalidTURNAddress + } + + conn, err := a.net.DialTCP(network, lAddr, rAddrServer) + if err != nil { + return nil, err + } + + dataConn, err := a.DialTCPWithConn(conn, network, rAddr) + if err != nil { + conn.Close() //nolint:errcheck,gosec + } + + return dataConn, err +} + +// DialTCPWithConn acts like DialWithConn for TCP networks. +func (a *TCPAllocation) DialTCPWithConn(conn net.Conn, _ string, rAddr *net.TCPAddr) (*TCPConn, error) { + var err error + + // Check if we have a permission for the destination IP addr + perm, ok := a.permMap.find(rAddr) + if !ok { + perm = &permission{} + a.permMap.insert(rAddr, perm) + } + + for i := 0; i < maxRetryAttempts; i++ { + if err = a.createPermission(perm, rAddr); !errors.Is(err, errTryAgain) { + break + } + } + if err != nil { + return nil, err + } + + // Send connect request if haven't done so. + cid, err := a.Connect(rAddr) + if err != nil { + return nil, err + } + + tcpConn, ok := conn.(transport.TCPConn) + if !ok { + return nil, errTCPAddrCast + } + + dataConn := &TCPConn{ + TCPConn: tcpConn, + ConnectionID: cid, + remoteAddress: rAddr, + allocation: a, + } + + if err := a.BindConnection(dataConn, cid); err != nil { + return nil, fmt.Errorf("failed to bind connection: %w", err) + } + + return dataConn, nil +} + +// BindConnection associates the provided connection +func (a *TCPAllocation) BindConnection(dataConn *TCPConn, cid proto.ConnectionID) error { + msg, err := stun.Build( + stun.TransactionID, + stun.NewType(stun.MethodConnectionBind, stun.ClassRequest), + cid, + a.username, + a.realm, + a.nonce(), + a.integrity, + stun.Fingerprint, + ) + if err != nil { + return err + } + + a.log.Debugf("Send connectionBind request (cid=%v)", cid) + + _, err = dataConn.Write(msg.Raw) + if err != nil { + return err + } + + // Read exactly one STUN message, any data after belongs to the user + b := make([]byte, stunHeaderSize) + n, err := dataConn.Read(b) + if n != stunHeaderSize { + return errIncompleteTURNFrame + } else if err != nil { + return err + } + + if !stun.IsMessage(b) { + return errInvalidTURNFrame + } + + datagramSize := binary.BigEndian.Uint16(b[2:4]) + stunHeaderSize + raw := make([]byte, datagramSize) + copy(raw, b) + _, err = dataConn.Read(raw[stunHeaderSize:]) + if err != nil { + return err + } + res := &stun.Message{Raw: raw} + if err = res.Decode(); err != nil { + return fmt.Errorf("failed to decode STUN message: %w", err) + } + + switch res.Type.Class { + case stun.ClassErrorResponse: + var code stun.ErrorCodeAttribute + if err = code.GetFrom(res); err == nil { + return fmt.Errorf("%s (error %s)", res.Type, code) //nolint:goerr113 + } + return fmt.Errorf("%s", res.Type) //nolint:goerr113 + case stun.ClassSuccessResponse: + a.log.Debug("Successful connectionBind request") + return nil + default: + return fmt.Errorf("%w: %s", errUnexpectedSTUNRequestMessage, res.String()) + } +} + +// Accept waits for and returns the next connection to the listener. +func (a *TCPAllocation) Accept() (net.Conn, error) { + return a.AcceptTCP() +} + +// AcceptTCP accepts the next incoming call and returns the new connection. +func (a *TCPAllocation) AcceptTCP() (transport.TCPConn, error) { + addr, err := net.ResolveTCPAddr("tcp4", a.serverAddr.String()) + if err != nil { + return nil, err + } + + tcpConn, err := a.net.DialTCP("tcp", nil, addr) + if err != nil { + return nil, err + } + + dataConn, err := a.AcceptTCPWithConn(tcpConn) + if err != nil { + tcpConn.Close() //nolint:errcheck,gosec + } + + return dataConn, err +} + +// AcceptTCPWithConn accepts the next incoming call and returns the new connection. +func (a *TCPAllocation) AcceptTCPWithConn(conn net.Conn) (*TCPConn, error) { + select { + case attempt := <-a.connAttemptCh: + + tcpConn, ok := conn.(transport.TCPConn) + if !ok { + return nil, errTCPAddrCast + } + + dataConn := &TCPConn{ + TCPConn: tcpConn, + ConnectionID: attempt.cid, + remoteAddress: attempt.from, + allocation: a, + } + + if err := a.BindConnection(dataConn, attempt.cid); err != nil { + return nil, fmt.Errorf("failed to bind connection: %w", err) + } + + return dataConn, nil + case <-a.acceptTimer.C: + return nil, &net.OpError{ + Op: "accept", + Net: a.Addr().Network(), + Addr: a.Addr(), + Err: newTimeoutError("i/o timeout"), + } + } +} + +// SetDeadline sets the deadline associated with the listener. A zero time value disables the deadline. +func (a *TCPAllocation) SetDeadline(t time.Time) error { + var d time.Duration + if t == noDeadline() { + d = time.Duration(math.MaxInt64) + } else { + d = time.Until(t) + } + a.acceptTimer.Reset(d) + return nil +} + +// Close releases the allocation +// Any blocked Accept operations will be unblocked and return errors. +// Any opened connection via Dial/Accept will be closed. +func (a *TCPAllocation) Close() error { + a.refreshAllocTimer.Stop() + a.refreshPermsTimer.Stop() + + a.client.OnDeallocated(a.relayedAddr) + return a.refreshAllocation(0, true /* dontWait=true */) +} + +// Addr returns the relayed address of the allocation +func (a *TCPAllocation) Addr() net.Addr { + return a.relayedAddr +} + +// HandleConnectionAttempt is called by the TURN client +// when it receives a ConnectionAttempt indication. +func (a *TCPAllocation) HandleConnectionAttempt(from *net.TCPAddr, cid proto.ConnectionID) { + a.connAttemptCh <- &connectionAttempt{ + from: from, + cid: cid, + } +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/client/tcp_conn.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/client/tcp_conn.go new file mode 100644 index 000000000..990b6d424 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/client/tcp_conn.go @@ -0,0 +1,49 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + +package client + +import ( + "errors" + "net" + + "github.com/pion/transport/v3" + "github.com/pion/turn/v4/internal/proto" +) + +var ( + errInvalidTURNFrame = errors.New("data is not a valid TURN frame, no STUN or ChannelData found") + errIncompleteTURNFrame = errors.New("data contains incomplete STUN or TURN frame") +) + +const ( + stunHeaderSize = 20 +) + +var _ transport.TCPConn = (*TCPConn)(nil) // Includes type check for net.Conn + +// TCPConn wraps a transport.TCPConn and returns the allocations relayed +// transport address in response to TCPConn.LocalAddress() +type TCPConn struct { + transport.TCPConn + remoteAddress *net.TCPAddr + allocation *TCPAllocation + ConnectionID proto.ConnectionID +} + +type connectionAttempt struct { + from *net.TCPAddr + cid proto.ConnectionID +} + +// LocalAddr returns the local network address. +// The Addr returned is shared by all invocations of LocalAddr, so do not modify it. +func (c *TCPConn) LocalAddr() net.Addr { + return c.allocation.Addr() +} + +// RemoteAddr returns the remote network address. +// The Addr returned is shared by all invocations of RemoteAddr, so do not modify it. +func (c *TCPConn) RemoteAddr() net.Addr { + return c.remoteAddress +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/client/transaction.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/client/transaction.go similarity index 81% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/client/transaction.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/client/transaction.go index 54024b447..b1c9105e6 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/client/transaction.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/client/transaction.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package client import ( @@ -5,7 +8,7 @@ import ( "sync" "time" - "github.com/pion/stun" + "github.com/pion/stun/v3" ) const ( @@ -26,18 +29,18 @@ type TransactionConfig struct { Raw []byte To net.Addr Interval time.Duration - IgnoreResult bool // true to throw away the result of this transaction (it will not be readable using WaitForResult) + IgnoreResult bool // True to throw away the result of this transaction (it will not be readable using WaitForResult) } // Transaction represents a transaction type Transaction struct { - Key string // read-only - Raw []byte // read-only - To net.Addr // read-only - nRtx int // modified only by the timer thread - interval time.Duration // modified only by the timer thread - timer *time.Timer // thread-safe, set only by the creator, and stopper - resultCh chan TransactionResult // thread-safe + Key string // Read-only + Raw []byte // Read-only + To net.Addr // Read-only + nRtx int // Modified only by the timer thread + interval time.Duration // Modified only by the timer thread + timer *time.Timer // Thread-safe, set only by the creator, and stopper + resultCh chan TransactionResult // Thread-safe mutex sync.RWMutex } @@ -49,11 +52,11 @@ func NewTransaction(config *TransactionConfig) *Transaction { } return &Transaction{ - Key: config.Key, // read-only - Raw: config.Raw, // read-only - To: config.To, // read-only - interval: config.Interval, // modified only by the timer thread - resultCh: resultCh, // thread-safe + Key: config.Key, // Read-only + Raw: config.Raw, // Read-only + To: config.To, // Read-only + interval: config.Interval, // Modified only by the timer thread + resultCh: resultCh, // Thread-safe } } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/client/trylock.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/client/trylock.go similarity index 81% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/client/trylock.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/client/trylock.go index 2d11a2d3c..6bfe6ff31 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/client/trylock.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/client/trylock.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package client import ( diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/client/conn.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/client/udp_conn.go similarity index 56% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/client/conn.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/client/udp_conn.go index 8aeb742c3..7bb187659 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/client/conn.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/client/udp_conn.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + // Package client implements the API for a TURN client package client @@ -7,12 +10,10 @@ import ( "io" "math" "net" - "sync" "time" - "github.com/pion/logging" - "github.com/pion/stun" - "github.com/pion/turn/v2/internal/proto" + "github.com/pion/stun/v3" + "github.com/pion/turn/v4/internal/proto" ) const ( @@ -26,71 +27,43 @@ const ( timerIDRefreshPerms ) -func noDeadline() time.Time { - return time.Time{} -} - type inboundData struct { data []byte from net.Addr } -// UDPConnObserver is an interface to UDPConn observer -type UDPConnObserver interface { - TURNServerAddr() net.Addr - Username() stun.Username - Realm() stun.Realm - WriteTo(data []byte, to net.Addr) (int, error) - PerformTransaction(msg *stun.Message, to net.Addr, dontWait bool) (TransactionResult, error) - OnDeallocated(relayedAddr net.Addr) -} - -// UDPConnConfig is a set of configuration params use by NewUDPConn -type UDPConnConfig struct { - Observer UDPConnObserver - RelayedAddr net.Addr - Integrity stun.MessageIntegrity - Nonce stun.Nonce - Lifetime time.Duration - Log logging.LeveledLogger -} - // UDPConn is the implementation of the Conn and PacketConn interfaces for UDP network connections. -// comatible with net.PacketConn and net.Conn +// compatible with net.PacketConn and net.Conn type UDPConn struct { - obs UDPConnObserver // read-only - relayedAddr net.Addr // read-only - permMap *permissionMap // thread-safe - bindingMgr *bindingManager // thread-safe - integrity stun.MessageIntegrity // read-only - _nonce stun.Nonce // needs mutex x - _lifetime time.Duration // needs mutex x - readCh chan *inboundData // thread-safe - closeCh chan struct{} // thread-safe - readTimer *time.Timer // thread-safe - refreshAllocTimer *PeriodicTimer // thread-safe - refreshPermsTimer *PeriodicTimer // thread-safe - mutex sync.RWMutex // thread-safe - log logging.LeveledLogger // read-only + bindingMgr *bindingManager // Thread-safe + readCh chan *inboundData // Thread-safe + closeCh chan struct{} // Thread-safe + allocation } // NewUDPConn creates a new instance of UDPConn -func NewUDPConn(config *UDPConnConfig) *UDPConn { +func NewUDPConn(config *AllocationConfig) *UDPConn { c := &UDPConn{ - obs: config.Observer, - relayedAddr: config.RelayedAddr, - permMap: newPermissionMap(), - bindingMgr: newBindingManager(), - integrity: config.Integrity, - _nonce: config.Nonce, - _lifetime: config.Lifetime, - readCh: make(chan *inboundData, maxReadQueueSize), - closeCh: make(chan struct{}), - readTimer: time.NewTimer(time.Duration(math.MaxInt64)), - log: config.Log, + bindingMgr: newBindingManager(), + readCh: make(chan *inboundData, maxReadQueueSize), + closeCh: make(chan struct{}), + allocation: allocation{ + client: config.Client, + relayedAddr: config.RelayedAddr, + serverAddr: config.ServerAddr, + readTimer: time.NewTimer(time.Duration(math.MaxInt64)), + permMap: newPermissionMap(), + username: config.Username, + realm: config.Realm, + integrity: config.Integrity, + _nonce: config.Nonce, + _lifetime: config.Lifetime, + net: config.Net, + log: config.Log, + }, } - c.log.Debugf("initial lifetime: %d seconds", int(c.lifetime().Seconds())) + c.log.Debugf("Initial lifetime: %d seconds", int(c.lifetime().Seconds())) c.refreshAllocTimer = NewPeriodicTimer( timerIDRefreshAlloc, @@ -105,10 +78,10 @@ func NewUDPConn(config *UDPConnConfig) *UDPConn { ) if c.refreshAllocTimer.Start() { - c.log.Debugf("refreshAllocTimer started") + c.log.Debugf("Started refresh allocation timer") } if c.refreshPermsTimer.Start() { - c.log.Debugf("refreshPermsTimer started") + c.log.Debugf("Started refresh permission timer") } return c @@ -153,14 +126,14 @@ func (c *UDPConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) { } } -func (c *UDPConn) createPermission(perm *permission, addr net.Addr) error { +func (a *allocation) createPermission(perm *permission, addr net.Addr) error { perm.mutex.Lock() defer perm.mutex.Unlock() if perm.state() == permStateIdle { - // punch a hole! (this would block a bit..) - if err := c.CreatePermissions(addr); err != nil { - c.permMap.delete(addr) + // Punch a hole! (this would block a bit..) + if err := a.CreatePermissions(addr); err != nil { + a.permMap.delete(addr) return err } perm.setState(permStatePermitted) @@ -180,7 +153,7 @@ func (c *UDPConn) WriteTo(p []byte, addr net.Addr) (int, error) { //nolint: goco return 0, errUDPAddrCast } - // check if we have a permission for the destination IP addr + // Check if we have a permission for the destination IP addr perm, ok := c.permMap.find(addr) if !ok { perm = &permission{} @@ -203,7 +176,7 @@ func (c *UDPConn) WriteTo(p []byte, addr net.Addr) (int, error) { //nolint: goco return 0, err } - // bind channel + // Bind channel b, ok := c.bindingMgr.findByAddr(addr) if !ok { b = c.bindingMgr.create(addr) @@ -213,20 +186,20 @@ func (c *UDPConn) WriteTo(p []byte, addr net.Addr) (int, error) { //nolint: goco if bindSt == bindingStateIdle || bindSt == bindingStateRequest || bindSt == bindingStateFailed { func() { - // block only callers with the same binding until + // Block only callers with the same binding until // the binding transaction has been complete b.muBind.Lock() defer b.muBind.Unlock() - // binding state may have been changed while waiting. check again. + // Binding state may have been changed while waiting. check again. if b.state() == bindingStateIdle { b.setState(bindingStateRequest) go func() { err2 := c.bind(b) if err2 != nil { - c.log.Warnf("bind() failed: %s", err2.Error()) + c.log.Warnf("Failed to bind bind(): %s", err2) b.setState(bindingStateFailed) - // keep going... + // Keep going... } else { b.setState(bindingStateReady) } @@ -234,7 +207,7 @@ func (c *UDPConn) WriteTo(p []byte, addr net.Addr) (int, error) { //nolint: goco } }() - // send data using SendIndication + // Send data using SendIndication peerAddr := addr2PeerAddress(addr) var msg *stun.Message msg, err = stun.Build( @@ -248,14 +221,14 @@ func (c *UDPConn) WriteTo(p []byte, addr net.Addr) (int, error) { //nolint: goco return 0, err } - // indication has no transaction (fire-and-forget) + // Indication has no transaction (fire-and-forget) - return c.obs.WriteTo(msg.Raw, c.obs.TURNServerAddr()) + return c.client.WriteTo(msg.Raw, c.serverAddr) } - // binding is either ready + // Binding is either ready - // check if the binding needs a refresh + // Check if the binding needs a refresh func() { b.muBind.Lock() defer b.muBind.Unlock() @@ -265,9 +238,9 @@ func (c *UDPConn) WriteTo(p []byte, addr net.Addr) (int, error) { //nolint: goco go func() { err = c.bind(b) if err != nil { - c.log.Warnf("bind() for refresh failed: %s", err.Error()) + c.log.Warnf("Failed to bind() for refresh: %s", err) b.setState(bindingStateFailed) - // keep going... + // Keep going... } else { b.setRefreshedAt(time.Now()) b.setState(bindingStateReady) @@ -276,7 +249,7 @@ func (c *UDPConn) WriteTo(p []byte, addr net.Addr) (int, error) { //nolint: goco } }() - // send via ChannelData + // Send via ChannelData _, err = c.sendChannelData(p, b.number) if err != nil { return 0, err @@ -297,7 +270,7 @@ func (c *UDPConn) Close() error { close(c.closeCh) } - c.obs.OnDeallocated(c.relayedAddr) + c.client.OnDeallocated(c.relayedAddr) return c.refreshAllocation(0, true /* dontWait=true */) } @@ -344,7 +317,7 @@ func (c *UDPConn) SetReadDeadline(t time.Time) error { // Even if write times out, it may return n > 0, indicating that // some of the data was successfully written. // A zero value for t means WriteTo will not time out. -func (c *UDPConn) SetWriteDeadline(t time.Time) error { +func (c *UDPConn) SetWriteDeadline(time.Time) error { // Write never blocks. return nil } @@ -365,7 +338,7 @@ func addr2PeerAddress(addr net.Addr) proto.PeerAddress { // CreatePermissions Issues a CreatePermission request for the supplied addresses // as described in https://datatracker.ietf.org/doc/html/rfc5766#section-9 -func (c *UDPConn) CreatePermissions(addrs ...net.Addr) error { +func (a *allocation) CreatePermissions(addrs ...net.Addr) error { setters := []stun.Setter{ stun.TransactionID, stun.NewType(stun.MethodCreatePermission, stun.ClassRequest), @@ -376,10 +349,10 @@ func (c *UDPConn) CreatePermissions(addrs ...net.Addr) error { } setters = append(setters, - c.obs.Username(), - c.obs.Realm(), - c.nonce(), - c.integrity, + a.username, + a.realm, + a.nonce(), + a.integrity, stun.Fingerprint) msg, err := stun.Build(setters...) @@ -387,7 +360,7 @@ func (c *UDPConn) CreatePermissions(addrs ...net.Addr) error { return err } - trRes, err := c.obs.PerformTransaction(msg, c.obs.TURNServerAddr(), false) + trRes, err := a.client.PerformTransaction(msg, a.serverAddr, false) if err != nil { return err } @@ -398,12 +371,11 @@ func (c *UDPConn) CreatePermissions(addrs ...net.Addr) error { var code stun.ErrorCodeAttribute if err = code.GetFrom(res); err == nil { if code.Code == stun.CodeStaleNonce { - c.setNonceFromMsg(res) + a.setNonceFromMsg(res) return errTryAgain } return fmt.Errorf("%s (error %s)", res.Type, code) //nolint:goerr113 } - return fmt.Errorf("%s", res.Type) //nolint:goerr113 } @@ -412,14 +384,14 @@ func (c *UDPConn) CreatePermissions(addrs ...net.Addr) error { // HandleInbound passes inbound data in UDPConn func (c *UDPConn) HandleInbound(data []byte, from net.Addr) { - // copy data + // Copy data copied := make([]byte, len(data)) copy(copied, data) select { case c.readCh <- &inboundData{data: copied, from: from}: default: - c.log.Warnf("receive buffer full") + c.log.Warnf("Receive buffer full") } } @@ -433,94 +405,14 @@ func (c *UDPConn) FindAddrByChannelNumber(chNum uint16) (net.Addr, bool) { return b.addr, true } -func (c *UDPConn) setNonceFromMsg(msg *stun.Message) { - // Update nonce - var nonce stun.Nonce - if err := nonce.GetFrom(msg); err == nil { - c.setNonce(nonce) - c.log.Debug("refresh allocation: 438, got new nonce.") - } else { - c.log.Warn("refresh allocation: 438 but no nonce.") - } -} - -func (c *UDPConn) refreshAllocation(lifetime time.Duration, dontWait bool) error { - msg, err := stun.Build( - stun.TransactionID, - stun.NewType(stun.MethodRefresh, stun.ClassRequest), - proto.Lifetime{Duration: lifetime}, - c.obs.Username(), - c.obs.Realm(), - c.nonce(), - c.integrity, - stun.Fingerprint, - ) - if err != nil { - return fmt.Errorf("%w: %s", errFailedToBuildRefreshRequest, err.Error()) - } - - c.log.Debugf("send refresh request (dontWait=%v)", dontWait) - trRes, err := c.obs.PerformTransaction(msg, c.obs.TURNServerAddr(), dontWait) - if err != nil { - return fmt.Errorf("%w: %s", errFailedToRefreshAllocation, err.Error()) - } - - if dontWait { - c.log.Debug("refresh request sent") - return nil - } - - c.log.Debug("refresh request sent, and waiting response") - - res := trRes.Msg - if res.Type.Class == stun.ClassErrorResponse { - var code stun.ErrorCodeAttribute - if err = code.GetFrom(res); err == nil { - if code.Code == stun.CodeStaleNonce { - c.setNonceFromMsg(res) - return errTryAgain - } - return err - } - return fmt.Errorf("%s", res.Type) //nolint:goerr113 - } - - // Getting lifetime from response - var updatedLifetime proto.Lifetime - if err := updatedLifetime.GetFrom(res); err != nil { - return fmt.Errorf("%w: %s", errFailedToGetLifetime, err.Error()) - } - - c.setLifetime(updatedLifetime.Duration) - c.log.Debugf("updated lifetime: %d seconds", int(c.lifetime().Seconds())) - return nil -} - -func (c *UDPConn) refreshPermissions() error { - addrs := c.permMap.addrs() - if len(addrs) == 0 { - c.log.Debug("no permission to refresh") - return nil - } - if err := c.CreatePermissions(addrs...); err != nil { - if errors.Is(err, errTryAgain) { - return errTryAgain - } - c.log.Errorf("fail to refresh permissions: %s", err.Error()) - return err - } - c.log.Debug("refresh permissions successful") - return nil -} - func (c *UDPConn) bind(b *binding) error { setters := []stun.Setter{ stun.TransactionID, stun.NewType(stun.MethodChannelBind, stun.ClassRequest), addr2PeerAddress(b.addr), proto.ChannelNumber(b.number), - c.obs.Username(), - c.obs.Realm(), + c.username, + c.realm, c.nonce(), c.integrity, stun.Fingerprint, @@ -531,7 +423,7 @@ func (c *UDPConn) bind(b *binding) error { return err } - trRes, err := c.obs.PerformTransaction(msg, c.obs.TURNServerAddr(), false) + trRes, err := c.client.PerformTransaction(msg, c.serverAddr, false) if err != nil { c.bindingMgr.deleteByAddr(b.addr) return err @@ -543,7 +435,7 @@ func (c *UDPConn) bind(b *binding) error { return fmt.Errorf("unexpected response type %s", res.Type) //nolint:goerr113 } - c.log.Debugf("channel binding successful: %s %d", b.addr.String(), b.number) + c.log.Debugf("Channel binding successful: %s %d", b.addr, b.number) // Success. return nil @@ -555,69 +447,9 @@ func (c *UDPConn) sendChannelData(data []byte, chNum uint16) (int, error) { Number: proto.ChannelNumber(chNum), } chData.Encode() - _, err := c.obs.WriteTo(chData.Raw, c.obs.TURNServerAddr()) + _, err := c.client.WriteTo(chData.Raw, c.serverAddr) if err != nil { return 0, err } return len(data), nil } - -func (c *UDPConn) onRefreshTimers(id int) { - c.log.Debugf("refresh timer %d expired", id) - switch id { - case timerIDRefreshAlloc: - var err error - lifetime := c.lifetime() - // limit the max retries on errTryAgain to 3 - // when stale nonce returns, sencond retry should succeed - for i := 0; i < maxRetryAttempts; i++ { - err = c.refreshAllocation(lifetime, false) - if !errors.Is(err, errTryAgain) { - break - } - } - if err != nil { - c.log.Warnf("refresh allocation failed") - } - case timerIDRefreshPerms: - var err error - for i := 0; i < maxRetryAttempts; i++ { - err = c.refreshPermissions() - if !errors.Is(err, errTryAgain) { - break - } - } - if err != nil { - c.log.Warnf("refresh permissions failed") - } - } -} - -func (c *UDPConn) nonce() stun.Nonce { - c.mutex.RLock() - defer c.mutex.RUnlock() - - return c._nonce -} - -func (c *UDPConn) setNonce(nonce stun.Nonce) { - c.mutex.Lock() - defer c.mutex.Unlock() - - c.log.Debugf("set new nonce with %d bytes", len(nonce)) - c._nonce = nonce -} - -func (c *UDPConn) lifetime() time.Duration { - c.mutex.RLock() - defer c.mutex.RUnlock() - - return c._lifetime -} - -func (c *UDPConn) setLifetime(lifetime time.Duration) { - c.mutex.Lock() - defer c.mutex.Unlock() - - c._lifetime = lifetime -} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/ipnet/util.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/ipnet/util.go similarity index 65% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/ipnet/util.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/ipnet/util.go index 24256b0a0..c3a5b32f3 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/ipnet/util.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/ipnet/util.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + // Package ipnet contains helper functions around net and IP package ipnet @@ -38,3 +41,15 @@ func AddrEqual(a, b net.Addr) bool { return aUDP.IP.Equal(bUDP.IP) && aUDP.Port == bUDP.Port } + +// FingerprintAddr generates a fingerprint from net.UDPAddr or net.TCPAddr's +// which can be used for indexing maps. +func FingerprintAddr(addr net.Addr) string { + switch a := addr.(type) { + case *net.UDPAddr: + return a.IP.String() + case *net.TCPAddr: // Do we really need this case? + return a.IP.String() + } + return "" // Should never happen +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/proto/addr.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/proto/addr.go similarity index 91% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/proto/addr.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/proto/addr.go index b1d654d9e..7d4db8bf7 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/proto/addr.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/proto/addr.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package proto import ( diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/proto/chandata.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/proto/chandata.go similarity index 92% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/proto/chandata.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/proto/chandata.go index 6f023e088..df9371193 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/proto/chandata.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/proto/chandata.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package proto import ( @@ -11,8 +14,8 @@ import ( // // See RFC 5766 Section 11.4 type ChannelData struct { - Data []byte // can be sub slice of Raw - Length int // ignored while encoding, len(Data) is used + Data []byte // Can be sub slice of Raw + Length int // Ignored while encoding, len(Data) is used Number ChannelNumber Raw []byte } @@ -34,7 +37,7 @@ func (c *ChannelData) Equal(b *ChannelData) bool { return bytes.Equal(c.Data, b.Data) } -// grow ensures that internal buffer will fit v more bytes and +// Grow ensures that internal buffer will fit v more bytes and // increases it capacity if necessary. // // Similar to stun.Message.grow method. diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/proto/chann.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/proto/chann.go similarity index 88% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/proto/chann.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/proto/chann.go index d64ef73f4..3aeb59f38 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/proto/chann.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/proto/chann.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package proto import ( @@ -5,7 +8,7 @@ import ( "errors" "strconv" - "github.com/pion/stun" + "github.com/pion/stun/v3" ) // ChannelNumber represents CHANNEL-NUMBER attribute. @@ -13,7 +16,7 @@ import ( // The CHANNEL-NUMBER attribute contains the number of the channel. // // RFC 5766 Section 14.1 -type ChannelNumber uint16 // encoded as uint16 +type ChannelNumber uint16 // Encoded as uint16 func (n ChannelNumber) String() string { return strconv.Itoa(int(n)) } @@ -38,7 +41,7 @@ func (n *ChannelNumber) GetFrom(m *stun.Message) error { if err = stun.CheckSize(stun.AttrChannelNumber, len(v), channelNumberSize); err != nil { return err } - _ = v[channelNumberSize-1] // asserting length + _ = v[channelNumberSize-1] // Asserting length *n = ChannelNumber(binary.BigEndian.Uint16(v[:2])) // v[2:4] is RFFU and equals to 0. return nil diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/proto/connection_id.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/proto/connection_id.go similarity index 83% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/proto/connection_id.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/proto/connection_id.go index 4984b474b..568deff15 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/proto/connection_id.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/proto/connection_id.go @@ -1,9 +1,12 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package proto import ( "encoding/binary" - "github.com/pion/stun" + "github.com/pion/stun/v3" ) // ConnectionID represents CONNECTION-ID attribute. @@ -33,7 +36,7 @@ func (c *ConnectionID) GetFrom(m *stun.Message) error { if err = stun.CheckSize(stun.AttrConnectionID, len(v), connectionIDSize); err != nil { return err } - _ = v[connectionIDSize-1] // asserting length + _ = v[connectionIDSize-1] // Asserting length *(*uint32)(c) = binary.BigEndian.Uint32(v) return nil } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/proto/data.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/proto/data.go similarity index 83% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/proto/data.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/proto/data.go index 64243e0c5..dcba23b44 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/proto/data.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/proto/data.go @@ -1,6 +1,9 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package proto -import "github.com/pion/stun" +import "github.com/pion/stun/v3" // Data represents DATA attribute. // diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/proto/dontfrag.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/proto/dontfrag.go similarity index 84% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/proto/dontfrag.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/proto/dontfrag.go index ac52b2b51..e4be0af67 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/proto/dontfrag.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/proto/dontfrag.go @@ -1,7 +1,10 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package proto import ( - "github.com/pion/stun" + "github.com/pion/stun/v3" ) // DontFragmentAttr is a deprecated alias for DontFragment @@ -32,10 +35,7 @@ func (d *DontFragment) GetFrom(m *stun.Message) error { if err != nil { return err } - if err = stun.CheckSize(stun.AttrDontFragment, len(v), dontFragmentSize); err != nil { - return err - } - return nil + return stun.CheckSize(stun.AttrDontFragment, len(v), dontFragmentSize) } // IsSet returns true if DONT-FRAGMENT attribute is set. diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/proto/evenport.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/proto/evenport.go similarity index 89% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/proto/evenport.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/proto/evenport.go index a5a388258..31468c757 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/proto/evenport.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/proto/evenport.go @@ -1,6 +1,9 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package proto -import "github.com/pion/stun" +import "github.com/pion/stun/v3" // EvenPort represents EVEN-PORT attribute. // diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/proto/lifetime.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/proto/lifetime.go similarity index 86% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/proto/lifetime.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/proto/lifetime.go index b78169660..6f55c7a97 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/proto/lifetime.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/proto/lifetime.go @@ -1,10 +1,13 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package proto import ( "encoding/binary" "time" - "github.com/pion/stun" + "github.com/pion/stun/v3" ) // DefaultLifetime in RFC 5766 is 10 minutes. @@ -25,7 +28,7 @@ type Lifetime struct { time.Duration } -// uint32 seconds +// Seconds in uint32 const lifetimeSize = 4 // 4 bytes, 32 bits // AddTo adds LIFETIME to message. @@ -45,7 +48,7 @@ func (l *Lifetime) GetFrom(m *stun.Message) error { if err = stun.CheckSize(stun.AttrLifetime, len(v), lifetimeSize); err != nil { return err } - _ = v[lifetimeSize-1] // asserting length + _ = v[lifetimeSize-1] // Asserting length seconds := binary.BigEndian.Uint32(v) l.Duration = time.Second * time.Duration(seconds) return nil diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/proto/peeraddr.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/proto/peeraddr.go similarity index 89% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/proto/peeraddr.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/proto/peeraddr.go index b357b823e..f4d9de7b6 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/proto/peeraddr.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/proto/peeraddr.go @@ -1,9 +1,12 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package proto import ( "net" - "github.com/pion/stun" + "github.com/pion/stun/v3" ) // PeerAddress implements XOR-PEER-ADDRESS attribute. diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/proto/proto.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/proto/proto.go similarity index 88% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/proto/proto.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/proto/proto.go index 4b08c7620..170cf7f18 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/proto/proto.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/proto/proto.go @@ -1,10 +1,11 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + // Package proto implements RFC 5766 Traversal Using Relays around NAT. -// -// Merged from gortc/turn v0.80. package proto import ( - "github.com/pion/stun" + "github.com/pion/stun/v3" ) // Default ports for TURN from RFC 5766 Section 4. diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/proto/relayedaddr.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/proto/relayedaddr.go similarity index 88% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/proto/relayedaddr.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/proto/relayedaddr.go index 2169cb756..c5fb2686c 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/proto/relayedaddr.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/proto/relayedaddr.go @@ -1,9 +1,12 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package proto import ( "net" - "github.com/pion/stun" + "github.com/pion/stun/v3" ) // RelayedAddress implements XOR-RELAYED-ADDRESS attribute. diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/proto/reqfamily.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/proto/reqfamily.go similarity index 92% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/proto/reqfamily.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/proto/reqfamily.go index e83d6bba4..01016a987 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/proto/reqfamily.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/proto/reqfamily.go @@ -1,9 +1,12 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package proto import ( "errors" - "github.com/pion/stun" + "github.com/pion/stun/v3" ) // RequestedAddressFamily represents the REQUESTED-ADDRESS-FAMILY Attribute as diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/proto/reqtrans.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/proto/reqtrans.go similarity index 86% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/proto/reqtrans.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/proto/reqtrans.go index cc73a4713..111dcd69b 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/proto/reqtrans.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/proto/reqtrans.go @@ -1,21 +1,28 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package proto import ( "strconv" - "github.com/pion/stun" + "github.com/pion/stun/v3" ) // Protocol is IANA assigned protocol number. type Protocol byte const ( + // ProtoTCP is IANA assigned protocol number for TCP. + ProtoTCP Protocol = 6 // ProtoUDP is IANA assigned protocol number for UDP. ProtoUDP Protocol = 17 ) func (p Protocol) String() string { switch p { + case ProtoTCP: + return "TCP" case ProtoUDP: return "UDP" default: diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/proto/rsrvtoken.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/proto/rsrvtoken.go similarity index 89% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/proto/rsrvtoken.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/proto/rsrvtoken.go index 6e2ed4d80..9c816485d 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/proto/rsrvtoken.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/proto/rsrvtoken.go @@ -1,6 +1,9 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package proto -import "github.com/pion/stun" +import "github.com/pion/stun/v3" // ReservationToken represents RESERVATION-TOKEN attribute. // diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/server/errors.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/server/errors.go similarity index 85% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/server/errors.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/server/errors.go index 13f8ee1a3..ea6da834c 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/server/errors.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/server/errors.go @@ -1,11 +1,14 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package server import "errors" var ( errFailedToGenerateNonce = errors.New("failed to generate nonce") + errInvalidNonce = errors.New("invalid nonce") errFailedToSendError = errors.New("failed to send error message") - errDuplicatedNonce = errors.New("duplicated Nonce generated, discarding request") errNoSuchUser = errors.New("no such user exists") errUnexpectedClass = errors.New("unexpected class") errUnexpectedMethod = errors.New("unexpected method") @@ -15,7 +18,7 @@ var ( errFailedToCreateSTUNPacket = errors.New("failed to create stun message from packet") errFailedToCreateChannelData = errors.New("failed to create channel data from packet") errRelayAlreadyAllocatedForFiveTuple = errors.New("relay already allocated for 5-TUPLE") - errRequestedTransportMustBeUDP = errors.New("RequestedTransport must be UDP") + errUnsupportedTransportProtocol = errors.New("RequestedTransport must be UDP or TCP") errNoDontFragmentSupport = errors.New("no support for DONT-FRAGMENT") errRequestWithReservationTokenAndEvenPort = errors.New("Request must not contain RESERVATION-TOKEN and EVEN-PORT") errNoAllocationFound = errors.New("no allocation found") diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/server/nonce.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/server/nonce.go new file mode 100644 index 000000000..b3f3131e8 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/server/nonce.go @@ -0,0 +1,71 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + +package server + +import ( + "crypto/hmac" + "crypto/rand" + "crypto/sha256" + "encoding/binary" + "encoding/hex" + "fmt" + "time" +) + +const ( + nonceLifetime = time.Hour // See: https://tools.ietf.org/html/rfc5766#section-4 + nonceLength = 40 + nonceKeyLength = 64 +) + +// NewNonceHash creates a NonceHash +func NewNonceHash() (*NonceHash, error) { + key := make([]byte, nonceKeyLength) + if _, err := rand.Read(key); err != nil { + return nil, err + } + + return &NonceHash{key}, nil +} + +// NonceHash is used to create and verify nonces +type NonceHash struct { + key []byte +} + +// Generate a nonce +func (n *NonceHash) Generate() (string, error) { + nonce := make([]byte, 8, nonceLength) + binary.BigEndian.PutUint64(nonce, uint64(time.Now().UnixMilli())) + + hash := hmac.New(sha256.New, n.key) + if _, err := hash.Write(nonce[:8]); err != nil { + return "", fmt.Errorf("%w: %v", errFailedToGenerateNonce, err) //nolint:errorlint + } + nonce = hash.Sum(nonce) + + return hex.EncodeToString(nonce), nil +} + +// Validate checks that nonce is signed and is not expired +func (n *NonceHash) Validate(nonce string) error { + b, err := hex.DecodeString(nonce) + if err != nil || len(b) != nonceLength { + return fmt.Errorf("%w: %v", errInvalidNonce, err) //nolint:errorlint + } + + if ts := time.UnixMilli(int64(binary.BigEndian.Uint64(b))); time.Since(ts) > nonceLifetime { + return errInvalidNonce + } + + hash := hmac.New(sha256.New, n.key) + if _, err = hash.Write(b[:8]); err != nil { + return fmt.Errorf("%w: %v", errInvalidNonce, err) //nolint:errorlint + } + if !hmac.Equal(b[8:], hash.Sum(nil)) { + return errInvalidNonce + } + + return nil +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/server/server.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/server/server.go similarity index 76% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/server/server.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/server/server.go index 27f375839..253492e92 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/server/server.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/server/server.go @@ -1,16 +1,18 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + // Package server implements the private API to implement a TURN server package server import ( "fmt" "net" - "sync" "time" "github.com/pion/logging" - "github.com/pion/stun" - "github.com/pion/turn/v2/internal/allocation" - "github.com/pion/turn/v2/internal/proto" + "github.com/pion/stun/v3" + "github.com/pion/turn/v4/internal/allocation" + "github.com/pion/turn/v4/internal/proto" ) // Request contains all the state needed to process a single incoming datagram @@ -22,7 +24,7 @@ type Request struct { // Server State AllocationManager *allocation.Manager - Nonces *sync.Map + NonceHash *NonceHash // User Configuration AuthHandler func(username string, realm string, srcAddr net.Addr) (key []byte, ok bool) @@ -33,7 +35,7 @@ type Request struct { // HandleRequest processes the give Request func HandleRequest(r Request) error { - r.Log.Debugf("received %d bytes of udp from %s on %s", len(r.Buff), r.SrcAddr.String(), r.Conn.LocalAddr().String()) + r.Log.Debugf("Received %d bytes of udp from %s on %s", len(r.Buff), r.SrcAddr, r.Conn.LocalAddr()) if proto.IsChannelData(r.Buff) { return handleDataPacket(r) @@ -43,35 +45,35 @@ func HandleRequest(r Request) error { } func handleDataPacket(r Request) error { - r.Log.Debugf("received DataPacket from %s", r.SrcAddr.String()) + r.Log.Debugf("Received DataPacket from %s", r.SrcAddr.String()) c := proto.ChannelData{Raw: r.Buff} if err := c.Decode(); err != nil { - return fmt.Errorf("%w: %v", errFailedToCreateChannelData, err) + return fmt.Errorf("%w: %v", errFailedToCreateChannelData, err) //nolint:errorlint } err := handleChannelData(r, &c) if err != nil { - err = fmt.Errorf("%w from %v: %v", errUnableToHandleChannelData, r.SrcAddr, err) + err = fmt.Errorf("%w from %v: %v", errUnableToHandleChannelData, r.SrcAddr, err) //nolint:errorlint } return err } func handleTURNPacket(r Request) error { - r.Log.Debug("handleTURNPacket") + r.Log.Debug("Handling TURN packet") m := &stun.Message{Raw: append([]byte{}, r.Buff...)} if err := m.Decode(); err != nil { - return fmt.Errorf("%w: %v", errFailedToCreateSTUNPacket, err) + return fmt.Errorf("%w: %v", errFailedToCreateSTUNPacket, err) //nolint:errorlint } h, err := getMessageHandler(m.Type.Class, m.Type.Method) if err != nil { - return fmt.Errorf("%w %v-%v from %v: %v", errUnhandledSTUNPacket, m.Type.Method, m.Type.Class, r.SrcAddr, err) + return fmt.Errorf("%w %v-%v from %v: %v", errUnhandledSTUNPacket, m.Type.Method, m.Type.Class, r.SrcAddr, err) //nolint:errorlint } err = h(r, m) if err != nil { - return fmt.Errorf("%w %v-%v from %v: %v", errFailedToHandle, m.Type.Method, m.Type.Class, r.SrcAddr, err) + return fmt.Errorf("%w %v-%v from %v: %v", errFailedToHandle, m.Type.Method, m.Type.Class, r.SrcAddr, err) //nolint:errorlint } return nil diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/server/stun.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/server/stun.go similarity index 60% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/server/stun.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/server/stun.go index 673e99f62..393bb99d8 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/server/stun.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/server/stun.go @@ -1,12 +1,15 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package server import ( - "github.com/pion/stun" - "github.com/pion/turn/v2/internal/ipnet" + "github.com/pion/stun/v3" + "github.com/pion/turn/v4/internal/ipnet" ) func handleBindingRequest(r Request, m *stun.Message) error { - r.Log.Debugf("received BindingRequest from %s", r.SrcAddr.String()) + r.Log.Debugf("Received BindingRequest from %s", r.SrcAddr) ip, port, err := ipnet.AddrIPPort(r.SrcAddr) if err != nil { diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/server/turn.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/server/turn.go similarity index 89% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/server/turn.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/server/turn.go index 4e7d25db0..46e45ecbe 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/server/turn.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/server/turn.go @@ -1,18 +1,24 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package server import ( "fmt" "net" - "github.com/pion/stun" - "github.com/pion/turn/v2/internal/allocation" - "github.com/pion/turn/v2/internal/ipnet" - "github.com/pion/turn/v2/internal/proto" + "github.com/pion/randutil" + "github.com/pion/stun/v3" + "github.com/pion/turn/v4/internal/allocation" + "github.com/pion/turn/v4/internal/ipnet" + "github.com/pion/turn/v4/internal/proto" ) -// // https://tools.ietf.org/html/rfc5766#section-6.2 +const runesAlpha = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" + +// See: https://tools.ietf.org/html/rfc5766#section-6.2 func handleAllocateRequest(r Request, m *stun.Message) error { - r.Log.Debugf("received AllocateRequest from %s", r.SrcAddr.String()) + r.Log.Debugf("Received AllocateRequest from %s", r.SrcAddr) // 1. The server MUST require that the request be authenticated. This // authentication MUST be done using the long-term credential @@ -44,7 +50,7 @@ func handleAllocateRequest(r Request, m *stun.Message) error { msg := buildMsg(m.TransactionID, stun.NewType(stun.MethodAllocate, stun.ClassErrorResponse), &stun.ErrorCodeAttribute{Code: stun.CodeAllocMismatch}) return buildAndSendErr(r.Conn, r.SrcAddr, errRelayAlreadyAllocatedForFiveTuple, msg...) } - // a retry allocation + // A retry allocation msg := buildMsg(m.TransactionID, stun.NewType(stun.MethodAllocate, stun.ClassSuccessResponse), append(attrs, messageIntegrity)...) return buildAndSend(r.Conn, r.SrcAddr, msg...) } @@ -53,14 +59,14 @@ func handleAllocateRequest(r Request, m *stun.Message) error { // attribute. If the REQUESTED-TRANSPORT attribute is not included // or is malformed, the server rejects the request with a 400 (Bad // Request) error. Otherwise, if the attribute is included but - // specifies a protocol other that UDP, the server rejects the + // specifies a protocol other that UDP/TCP, the server rejects the // request with a 442 (Unsupported Transport Protocol) error. var requestedTransport proto.RequestedTransport if err = requestedTransport.GetFrom(m); err != nil { return buildAndSendErr(r.Conn, r.SrcAddr, err, badRequestMsg...) - } else if requestedTransport.Protocol != proto.ProtoUDP { + } else if requestedTransport.Protocol != proto.ProtoUDP && requestedTransport.Protocol != proto.ProtoTCP { msg := buildMsg(m.TransactionID, stun.NewType(stun.MethodAllocate, stun.ClassErrorResponse), &stun.ErrorCodeAttribute{Code: stun.CodeUnsupportedTransProto}) - return buildAndSendErr(r.Conn, r.SrcAddr, errRequestedTransportMustBeUDP, msg...) + return buildAndSendErr(r.Conn, r.SrcAddr, errUnsupportedTransportProtocol, msg...) } // 4. The request may contain a DONT-FRAGMENT attribute. If it does, @@ -103,7 +109,10 @@ func handleAllocateRequest(r Request, m *stun.Message) error { return buildAndSendErr(r.Conn, r.SrcAddr, err, insufficientCapacityMsg...) } requestedPort = randomPort - reservationToken = randSeq(8) + reservationToken, err = randutil.GenerateCryptoRandomString(8, runesAlpha) + if err != nil { + return err + } } // 7. At any point, the server MAY choose to reject the request with a @@ -128,7 +137,8 @@ func handleAllocateRequest(r Request, m *stun.Message) error { } // Once the allocation is created, the server replies with a success - // response. The success response contains: + // response. + // The success response contains: // * An XOR-RELAYED-ADDRESS attribute containing the relayed transport // address. // * A LIFETIME attribute containing the current value of the time-to- @@ -173,7 +183,7 @@ func handleAllocateRequest(r Request, m *stun.Message) error { } func handleRefreshRequest(r Request, m *stun.Message) error { - r.Log.Debugf("received RefreshRequest from %s", r.SrcAddr.String()) + r.Log.Debugf("Received RefreshRequest from %s", r.SrcAddr) messageIntegrity, hasAuth, err := authenticateRequest(r, m, stun.MethodRefresh) if !hasAuth { @@ -207,7 +217,7 @@ func handleRefreshRequest(r Request, m *stun.Message) error { } func handleCreatePermissionRequest(r Request, m *stun.Message) error { - r.Log.Debugf("received CreatePermission from %s", r.SrcAddr.String()) + r.Log.Debugf("Received CreatePermission from %s", r.SrcAddr) a := r.AllocationManager.GetAllocation(&allocation.FiveTuple{ SrcAddr: r.SrcAddr, @@ -232,13 +242,12 @@ func handleCreatePermissionRequest(r Request, m *stun.Message) error { } if err := r.AllocationManager.GrantPermission(r.SrcAddr, peerAddress.IP); err != nil { - r.Log.Infof("permission denied for client %s to peer %s", r.SrcAddr.String(), - peerAddress.IP.String()) + r.Log.Infof("permission denied for client %s to peer %s", r.SrcAddr, peerAddress.IP) return err } - r.Log.Debugf("adding permission for %s", fmt.Sprintf("%s:%d", - peerAddress.IP.String(), peerAddress.Port)) + r.Log.Debugf("Adding permission for %s", fmt.Sprintf("%s:%d", + peerAddress.IP, peerAddress.Port)) a.AddPermission(allocation.NewPermission( &net.UDPAddr{ @@ -262,7 +271,7 @@ func handleCreatePermissionRequest(r Request, m *stun.Message) error { } func handleSendIndication(r Request, m *stun.Message) error { - r.Log.Debugf("received SendIndication from %s", r.SrcAddr.String()) + r.Log.Debugf("Received SendIndication from %s", r.SrcAddr) a := r.AllocationManager.GetAllocation(&allocation.FiveTuple{ SrcAddr: r.SrcAddr, DstAddr: r.Conn.LocalAddr(), @@ -289,13 +298,13 @@ func handleSendIndication(r Request, m *stun.Message) error { l, err := a.RelaySocket.WriteTo(dataAttr, msgDst) if l != len(dataAttr) { - return fmt.Errorf("%w %d != %d (expected) err: %v", errShortWrite, l, len(dataAttr), err) + return fmt.Errorf("%w %d != %d (expected) err: %v", errShortWrite, l, len(dataAttr), err) //nolint:errorlint } return err } func handleChannelBindRequest(r Request, m *stun.Message) error { - r.Log.Debugf("received ChannelBindRequest from %s", r.SrcAddr.String()) + r.Log.Debugf("Received ChannelBindRequest from %s", r.SrcAddr) a := r.AllocationManager.GetAllocation(&allocation.FiveTuple{ SrcAddr: r.SrcAddr, @@ -324,8 +333,7 @@ func handleChannelBindRequest(r Request, m *stun.Message) error { } if err = r.AllocationManager.GrantPermission(r.SrcAddr, peerAddr.IP); err != nil { - r.Log.Infof("permission denied for client %s to peer %s", r.SrcAddr.String(), - peerAddr.IP.String()) + r.Log.Infof("permission denied for client %s to peer %s", r.SrcAddr, peerAddr.IP) unauthorizedRequestMsg := buildMsg(m.TransactionID, stun.NewType(stun.MethodChannelBind, stun.ClassErrorResponse), @@ -333,9 +341,7 @@ func handleChannelBindRequest(r Request, m *stun.Message) error { return buildAndSendErr(r.Conn, r.SrcAddr, err, unauthorizedRequestMsg...) } - r.Log.Debugf("binding channel %d to %s", - channel, - fmt.Sprintf("%s:%d", peerAddr.IP.String(), peerAddr.Port)) + r.Log.Debugf("Binding channel %d to %s", channel, peerAddr) err = a.AddChannelBind(allocation.NewChannelBind( channel, &net.UDPAddr{IP: peerAddr.IP, Port: peerAddr.Port}, @@ -349,7 +355,7 @@ func handleChannelBindRequest(r Request, m *stun.Message) error { } func handleChannelData(r Request, c *proto.ChannelData) error { - r.Log.Debugf("received ChannelData from %s", r.SrcAddr.String()) + r.Log.Debugf("Received ChannelData from %s", r.SrcAddr) a := r.AllocationManager.GetAllocation(&allocation.FiveTuple{ SrcAddr: r.SrcAddr, diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/server/util.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/server/util.go similarity index 65% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/server/util.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/server/util.go index c9a339213..7c01d3297 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/internal/server/util.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/internal/server/util.go @@ -1,58 +1,39 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package server import ( - "crypto/md5" //nolint:gosec,gci + "errors" "fmt" - "io" - "math/rand" "net" - "strconv" "time" - "github.com/pion/stun" - "github.com/pion/turn/v2/internal/proto" + "github.com/pion/stun/v3" + "github.com/pion/turn/v4/internal/proto" ) const ( - maximumAllocationLifetime = time.Hour // https://tools.ietf.org/html/rfc5766#section-6.2 defines 3600 seconds recommendation - nonceLifetime = time.Hour // https://tools.ietf.org/html/rfc5766#section-4 - + maximumAllocationLifetime = time.Hour // See: https://tools.ietf.org/html/rfc5766#section-6.2 defines 3600 seconds recommendation ) -func randSeq(n int) string { - letters := []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") - b := make([]rune, n) - for i := range b { - b[i] = letters[rand.Intn(len(letters))] //nolint:gosec - } - return string(b) -} - -func buildNonce() (string, error) { - /* #nosec */ - h := md5.New() - if _, err := io.WriteString(h, strconv.FormatInt(time.Now().Unix(), 10)); err != nil { - return "", fmt.Errorf("%w: %v", errFailedToGenerateNonce, err) - } - if _, err := io.WriteString(h, strconv.FormatInt(rand.Int63(), 10)); err != nil { //nolint:gosec - return "", fmt.Errorf("%w: %v", errFailedToGenerateNonce, err) - } - return fmt.Sprintf("%x", h.Sum(nil)), nil -} - func buildAndSend(conn net.PacketConn, dst net.Addr, attrs ...stun.Setter) error { msg, err := stun.Build(attrs...) if err != nil { return err } _, err = conn.WriteTo(msg.Raw, dst) + if errors.Is(err, net.ErrClosed) { + return nil + } + return err } // Send a STUN packet and return the original error to the caller func buildAndSendErr(conn net.PacketConn, dst net.Addr, err error, attrs ...stun.Setter) error { if sendErr := buildAndSend(conn, dst, attrs...); sendErr != nil { - err = fmt.Errorf("%w %v %v", errFailedToSendError, sendErr, err) + err = fmt.Errorf("%w %v %v", errFailedToSendError, sendErr, err) //nolint:errorlint } return err } @@ -63,16 +44,11 @@ func buildMsg(transactionID [stun.TransactionIDSize]byte, msgType stun.MessageTy func authenticateRequest(r Request, m *stun.Message, callingMethod stun.Method) (stun.MessageIntegrity, bool, error) { respondWithNonce := func(responseCode stun.ErrorCode) (stun.MessageIntegrity, bool, error) { - nonce, err := buildNonce() + nonce, err := r.NonceHash.Generate() if err != nil { return nil, false, err } - // Nonce has already been taken - if _, keyCollision := r.Nonces.LoadOrStore(nonce, time.Now()); keyCollision { - return nil, false, errDuplicatedNonce - } - return nil, false, buildAndSend(r.Conn, r.SrcAddr, buildMsg(m.TransactionID, stun.NewType(callingMethod, stun.ClassErrorResponse), &stun.ErrorCodeAttribute{Code: responseCode}, @@ -90,19 +66,19 @@ func authenticateRequest(r Request, m *stun.Message, callingMethod stun.Method) realmAttr := &stun.Realm{} badRequestMsg := buildMsg(m.TransactionID, stun.NewType(callingMethod, stun.ClassErrorResponse), &stun.ErrorCodeAttribute{Code: stun.CodeBadRequest}) + // No Auth handler is set, server is running in STUN only mode + // Respond with 400 so clients don't retry + if r.AuthHandler == nil { + sendErr := buildAndSend(r.Conn, r.SrcAddr, badRequestMsg...) + return nil, false, sendErr + } + if err := nonceAttr.GetFrom(m); err != nil { return nil, false, buildAndSendErr(r.Conn, r.SrcAddr, err, badRequestMsg...) } - // Assert Nonce exists and is not expired - nonceCreationTime, nonceFound := r.Nonces.Load(string(*nonceAttr)) - if !nonceFound { - r.Nonces.Delete(nonceAttr) - return respondWithNonce(stun.CodeStaleNonce) - } - - if timeValue, ok := nonceCreationTime.(time.Time); !ok || time.Since(timeValue) >= nonceLifetime { - r.Nonces.Delete(nonceAttr) + // Assert Nonce is signed and is not expired + if err := r.NonceHash.Validate(nonceAttr.String()); err != nil { return respondWithNonce(stun.CodeStaleNonce) } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/lt_cred.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/lt_cred.go new file mode 100644 index 000000000..42466c381 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/lt_cred.go @@ -0,0 +1,100 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + +package turn + +import ( //nolint:gci + "crypto/hmac" + "crypto/sha1" //nolint:gosec,gci + "encoding/base64" + "net" + "strconv" + "strings" + "time" + + "github.com/pion/logging" +) + +// GenerateLongTermCredentials can be used to create credentials valid for [duration] time +func GenerateLongTermCredentials(sharedSecret string, duration time.Duration) (string, string, error) { + t := time.Now().Add(duration).Unix() + username := strconv.FormatInt(t, 10) + password, err := longTermCredentials(username, sharedSecret) + return username, password, err +} + +// GenerateLongTermTURNRESTCredentials can be used to create credentials valid for [duration] time +func GenerateLongTermTURNRESTCredentials(sharedSecret string, user string, duration time.Duration) (string, string, error) { + t := time.Now().Add(duration).Unix() + timestamp := strconv.FormatInt(t, 10) + username := timestamp + ":" + user + password, err := longTermCredentials(username, sharedSecret) + return username, password, err +} + +func longTermCredentials(username string, sharedSecret string) (string, error) { + mac := hmac.New(sha1.New, []byte(sharedSecret)) + _, err := mac.Write([]byte(username)) + if err != nil { + return "", err // Not sure if this will ever happen + } + password := mac.Sum(nil) + return base64.StdEncoding.EncodeToString(password), nil +} + +// NewLongTermAuthHandler returns a turn.AuthAuthHandler used with Long Term (or Time Windowed) Credentials. +// See: https://datatracker.ietf.org/doc/html/rfc8489#section-9.2 +func NewLongTermAuthHandler(sharedSecret string, l logging.LeveledLogger) AuthHandler { + if l == nil { + l = logging.NewDefaultLoggerFactory().NewLogger("turn") + } + return func(username, realm string, srcAddr net.Addr) (key []byte, ok bool) { + l.Tracef("Authentication username=%q realm=%q srcAddr=%v", username, realm, srcAddr) + t, err := strconv.Atoi(username) + if err != nil { + l.Errorf("Invalid time-windowed username %q", username) + return nil, false + } + if int64(t) < time.Now().Unix() { + l.Errorf("Expired time-windowed username %q", username) + return nil, false + } + password, err := longTermCredentials(username, sharedSecret) + if err != nil { + l.Error(err.Error()) + return nil, false + } + return GenerateAuthKey(username, realm, password), true + } +} + +// LongTermTURNRESTAuthHandler returns a turn.AuthAuthHandler that can be used to authenticate +// time-windowed ephemeral credentials generated by the TURN REST API as described in +// https://datatracker.ietf.org/doc/html/draft-uberti-behave-turn-rest-00 +// +// The supported format of is timestamp:username, where username is an arbitrary user id and the +// timestamp specifies the expiry of the credential. +func LongTermTURNRESTAuthHandler(sharedSecret string, l logging.LeveledLogger) AuthHandler { + if l == nil { + l = logging.NewDefaultLoggerFactory().NewLogger("turn") + } + return func(username, realm string, srcAddr net.Addr) (key []byte, ok bool) { + l.Tracef("Authentication username=%q realm=%q srcAddr=%v\n", username, realm, srcAddr) + timestamp := strings.Split(username, ":")[0] + t, err := strconv.Atoi(timestamp) + if err != nil { + l.Errorf("Invalid time-windowed username %q", username) + return nil, false + } + if int64(t) < time.Now().Unix() { + l.Errorf("Expired time-windowed username %q", username) + return nil, false + } + password, err := longTermCredentials(username, sharedSecret) + if err != nil { + l.Error(err.Error()) + return nil, false + } + return GenerateAuthKey(username, realm, password), true + } +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/relay_address_generator_none.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/relay_address_generator_none.go similarity index 82% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/relay_address_generator_none.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/relay_address_generator_none.go index f453d0994..b0974010c 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/relay_address_generator_none.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/relay_address_generator_none.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package turn import ( @@ -5,8 +8,8 @@ import ( "net" "strconv" - "github.com/pion/transport/v2" - "github.com/pion/transport/v2/stdnet" + "github.com/pion/transport/v3" + "github.com/pion/transport/v3/stdnet" ) // RelayAddressGeneratorNone returns the listener with no modifications @@ -46,6 +49,6 @@ func (r *RelayAddressGeneratorNone) AllocatePacketConn(network string, requested } // AllocateConn generates a new Conn to receive traffic on and the IP/Port to populate the allocation response with -func (r *RelayAddressGeneratorNone) AllocateConn(network string, requestedPort int) (net.Conn, net.Addr, error) { +func (r *RelayAddressGeneratorNone) AllocateConn(string, int) (net.Conn, net.Addr, error) { return nil, nil, errTODO } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/relay_address_generator_range.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/relay_address_generator_range.go similarity index 90% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/relay_address_generator_range.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/relay_address_generator_range.go index 48a0f2bbc..d87a57f9f 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/relay_address_generator_range.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/relay_address_generator_range.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package turn import ( @@ -5,8 +8,8 @@ import ( "net" "github.com/pion/randutil" - "github.com/pion/transport/v2" - "github.com/pion/transport/v2/stdnet" + "github.com/pion/transport/v3" + "github.com/pion/transport/v3/stdnet" ) // RelayAddressGeneratorPortRange can be used to only allocate connections inside a defined port range. @@ -100,6 +103,6 @@ func (r *RelayAddressGeneratorPortRange) AllocatePacketConn(network string, requ } // AllocateConn generates a new Conn to receive traffic on and the IP/Port to populate the allocation response with -func (r *RelayAddressGeneratorPortRange) AllocateConn(network string, requestedPort int) (net.Conn, net.Addr, error) { +func (r *RelayAddressGeneratorPortRange) AllocateConn(string, int) (net.Conn, net.Addr, error) { return nil, nil, errTODO } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/relay_address_generator_static.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/relay_address_generator_static.go similarity index 86% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/relay_address_generator_static.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/relay_address_generator_static.go index ba2be9fd3..39c687779 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/relay_address_generator_static.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/relay_address_generator_static.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package turn import ( @@ -5,8 +8,8 @@ import ( "net" "strconv" - "github.com/pion/transport/v2" - "github.com/pion/transport/v2/stdnet" + "github.com/pion/transport/v3" + "github.com/pion/transport/v3/stdnet" ) // RelayAddressGeneratorStatic can be used to return static IP address each time a relay is created. @@ -60,6 +63,6 @@ func (r *RelayAddressGeneratorStatic) AllocatePacketConn(network string, request } // AllocateConn generates a new Conn to receive traffic on and the IP/Port to populate the allocation response with -func (r *RelayAddressGeneratorStatic) AllocateConn(network string, requestedPort int) (net.Conn, net.Addr, error) { +func (r *RelayAddressGeneratorStatic) AllocateConn(string, int) (net.Conn, net.Addr, error) { return nil, nil, errTODO } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/renovate.json b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/renovate.json similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/renovate.json rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/renovate.json diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/server.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/server.go similarity index 66% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/server.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/server.go index 3f57f9db0..3b58938ff 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/server.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/server.go @@ -1,16 +1,19 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + // Package turn contains the public API for pion/turn, a toolkit for building TURN clients and servers package turn import ( + "errors" "fmt" "net" - "sync" "time" "github.com/pion/logging" - "github.com/pion/turn/v2/internal/allocation" - "github.com/pion/turn/v2/internal/proto" - "github.com/pion/turn/v2/internal/server" + "github.com/pion/turn/v4/internal/allocation" + "github.com/pion/turn/v4/internal/proto" + "github.com/pion/turn/v4/internal/server" ) const ( @@ -23,7 +26,7 @@ type Server struct { authHandler AuthHandler realm string channelBindTimeout time.Duration - nonces *sync.Map + nonceHash *server.NonceHash packetConnConfigs []PacketConnConfig listenerConfigs []ListenerConfig @@ -49,6 +52,11 @@ func NewServer(config ServerConfig) (*Server, error) { mtu = config.InboundMTU } + nonceHash, err := server.NewNonceHash() + if err != nil { + return nil, err + } + s := &Server{ log: loggerFactory.NewLogger("turn"), authHandler: config.AuthHandler, @@ -56,7 +64,7 @@ func NewServer(config ServerConfig) (*Server, error) { channelBindTimeout: config.ChannelBindTimeout, packetConnConfigs: config.PacketConnConfigs, listenerConfigs: config.ListenerConfigs, - nonces: &sync.Map{}, + nonceHash: nonceHash, inboundMTU: mtu, } @@ -70,7 +78,13 @@ func NewServer(config ServerConfig) (*Server, error) { return nil, fmt.Errorf("failed to create AllocationManager: %w", err) } - go s.readPacketConn(cfg, am) + go func(cfg PacketConnConfig, am *allocation.Manager) { + s.readLoop(cfg.PacketConn, am) + + if err := am.Close(); err != nil { + s.log.Errorf("Failed to close AllocationManager: %s", err) + } + }(cfg, am) } for _, cfg := range s.listenerConfigs { @@ -79,7 +93,13 @@ func NewServer(config ServerConfig) (*Server, error) { return nil, fmt.Errorf("failed to create AllocationManager: %w", err) } - go s.readListener(cfg, am) + go func(cfg ListenerConfig, am *allocation.Manager) { + s.readListener(cfg.Listener, am) + + if err := am.Close(); err != nil { + s.log.Errorf("Failed to close AllocationManager: %s", err) + } + }(cfg, am) } return s, nil @@ -116,42 +136,56 @@ func (s *Server) Close() error { err := errFailedToClose for _, e := range errors { - err = fmt.Errorf("%s; close error (%w) ", err, e) + err = fmt.Errorf("%s; close error (%w) ", err, e) //nolint:errorlint } return err } -func (s *Server) readPacketConn(p PacketConnConfig, am *allocation.Manager) { - s.readLoop(p.PacketConn, am) - - if err := am.Close(); err != nil { - s.log.Errorf("Failed to close AllocationManager: %s", err) - } -} - -func (s *Server) readListener(l ListenerConfig, am *allocation.Manager) { - defer func() { - if err := am.Close(); err != nil { - s.log.Errorf("Failed to close AllocationManager: %s", err) - } - }() - +func (s *Server) readListener(l net.Listener, am *allocation.Manager) { for { - conn, err := l.Listener.Accept() + conn, err := l.Accept() if err != nil { s.log.Debugf("Failed to accept: %s", err) return } - go s.readLoop(NewSTUNConn(conn), am) + go func() { + s.readLoop(NewSTUNConn(conn), am) + + // Delete allocation + am.DeleteAllocation(&allocation.FiveTuple{ + Protocol: allocation.UDP, // fixed UDP + SrcAddr: conn.RemoteAddr(), + DstAddr: conn.LocalAddr(), + }) + + if err := conn.Close(); err != nil && !errors.Is(err, net.ErrClosed) { + s.log.Errorf("Failed to close conn: %s", err) + } + }() } } +type nilAddressGenerator struct{} + +func (n *nilAddressGenerator) Validate() error { return errRelayAddressGeneratorNil } + +func (n *nilAddressGenerator) AllocatePacketConn(string, int) (net.PacketConn, net.Addr, error) { + return nil, nil, errRelayAddressGeneratorNil +} + +func (n *nilAddressGenerator) AllocateConn(string, int) (net.Conn, net.Addr, error) { + return nil, nil, errRelayAddressGeneratorNil +} + func (s *Server) createAllocationManager(addrGenerator RelayAddressGenerator, handler PermissionHandler) (*allocation.Manager, error) { if handler == nil { handler = DefaultPermissionHandler } + if addrGenerator == nil { + addrGenerator = &nilAddressGenerator{} + } am, err := allocation.NewManager(allocation.ManagerConfig{ AllocatePacketConn: addrGenerator.AllocatePacketConn, @@ -174,10 +208,11 @@ func (s *Server) readLoop(p net.PacketConn, allocationManager *allocation.Manage n, addr, err := p.ReadFrom(buf) switch { case err != nil: - s.log.Debugf("exit read loop on error: %s", err.Error()) + s.log.Debugf("Exit read loop on error: %s", err) return case n >= s.inboundMTU: s.log.Debugf("Read bytes exceeded MTU, packet is possibly truncated") + continue } if err := server.HandleRequest(server.Request{ @@ -189,9 +224,9 @@ func (s *Server) readLoop(p net.PacketConn, allocationManager *allocation.Manage Realm: s.realm, AllocationManager: allocationManager, ChannelBindTimeout: s.channelBindTimeout, - Nonces: s.nonces, + NonceHash: s.nonceHash, }); err != nil { - s.log.Errorf("error when handling datagram: %v", err) + s.log.Errorf("Failed to handle datagram: %v", err) } } } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/server_config.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/server_config.go similarity index 94% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/server_config.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/server_config.go index 5487900db..eaa7a2581 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/server_config.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/server_config.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package turn import ( @@ -32,7 +35,7 @@ type RelayAddressGenerator interface { type PermissionHandler func(clientAddr net.Addr, peerIP net.IP) (ok bool) // DefaultPermissionHandler is convince function that grants permission to all peers -func DefaultPermissionHandler(clientAddr net.Addr, peerIP net.IP) (ok bool) { +func DefaultPermissionHandler(net.Addr, net.IP) (ok bool) { return true } @@ -54,11 +57,14 @@ func (c *PacketConnConfig) validate() error { if c.PacketConn == nil { return errConnUnset } - if c.RelayAddressGenerator == nil { - return errRelayAddressGeneratorUnset + + if c.RelayAddressGenerator != nil { + if err := c.RelayAddressGenerator.Validate(); err != nil { + return err + } } - return c.RelayAddressGenerator.Validate() + return nil } // ListenerConfig is a single net.Listener to accept connections on. This will be used for TCP, TLS and DTLS listeners diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/stun_conn.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/stun_conn.go similarity index 93% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/stun_conn.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/stun_conn.go index ca911ee4c..57543544a 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/stun_conn.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v4/stun_conn.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + package turn import ( @@ -6,8 +9,8 @@ import ( "net" "time" - "github.com/pion/stun" - "github.com/pion/turn/v2/internal/proto" + "github.com/pion/stun/v3" + "github.com/pion/turn/v4/internal/proto" ) var ( @@ -89,7 +92,7 @@ func (s *STUNConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) { } // WriteTo implements WriteTo from net.PacketConn -func (s *STUNConn) WriteTo(p []byte, addr net.Addr) (n int, err error) { +func (s *STUNConn) WriteTo(p []byte, _ net.Addr) (n int, err error) { return s.nextConn.Write(p) } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/.golangci.yml b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/.golangci.yml deleted file mode 100644 index 4e3eddf42..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/.golangci.yml +++ /dev/null @@ -1,137 +0,0 @@ -# SPDX-FileCopyrightText: 2023 The Pion community -# SPDX-License-Identifier: MIT - -linters-settings: - govet: - check-shadowing: true - misspell: - locale: US - exhaustive: - default-signifies-exhaustive: true - gomodguard: - blocked: - modules: - - github.com/pkg/errors: - recommendations: - - errors - forbidigo: - forbid: - - ^fmt.Print(f|ln)?$ - - ^log.(Panic|Fatal|Print)(f|ln)?$ - - ^os.Exit$ - - ^panic$ - - ^print(ln)?$ - -linters: - enable: - - asciicheck # Simple linter to check that your code does not contain non-ASCII identifiers - - bidichk # Checks for dangerous unicode character sequences - - bodyclose # checks whether HTTP response body is closed successfully - - contextcheck # check the function whether use a non-inherited context - - decorder # check declaration order and count of types, constants, variables and functions - - depguard # Go linter that checks if package imports are in a list of acceptable packages - - dogsled # Checks assignments with too many blank identifiers (e.g. x, _, _, _, := f()) - - dupl # Tool for code clone detection - - durationcheck # check for two durations multiplied together - - errcheck # Errcheck is a program for checking for unchecked errors in go programs. These unchecked errors can be critical bugs in some cases - - errchkjson # Checks types passed to the json encoding functions. Reports unsupported types and optionally reports occations, where the check for the returned error can be omitted. - - errname # Checks that sentinel errors are prefixed with the `Err` and error types are suffixed with the `Error`. - - errorlint # errorlint is a linter for that can be used to find code that will cause problems with the error wrapping scheme introduced in Go 1.13. - - exhaustive # check exhaustiveness of enum switch statements - - exportloopref # checks for pointers to enclosing loop variables - - forbidigo # Forbids identifiers - - forcetypeassert # finds forced type assertions - - gci # Gci control golang package import order and make it always deterministic. - - gochecknoglobals # Checks that no globals are present in Go code - - gochecknoinits # Checks that no init functions are present in Go code - - gocognit # Computes and checks the cognitive complexity of functions - - goconst # Finds repeated strings that could be replaced by a constant - - gocritic # The most opinionated Go source code linter - - godox # Tool for detection of FIXME, TODO and other comment keywords - - goerr113 # Golang linter to check the errors handling expressions - - gofmt # Gofmt checks whether code was gofmt-ed. By default this tool runs with -s option to check for code simplification - - gofumpt # Gofumpt checks whether code was gofumpt-ed. - - goheader # Checks is file header matches to pattern - - goimports # Goimports does everything that gofmt does. Additionally it checks unused imports - - gomoddirectives # Manage the use of 'replace', 'retract', and 'excludes' directives in go.mod. - - gomodguard # Allow and block list linter for direct Go module dependencies. This is different from depguard where there are different block types for example version constraints and module recommendations. - - goprintffuncname # Checks that printf-like functions are named with `f` at the end - - gosec # Inspects source code for security problems - - gosimple # Linter for Go source code that specializes in simplifying a code - - govet # Vet examines Go source code and reports suspicious constructs, such as Printf calls whose arguments do not align with the format string - - grouper # An analyzer to analyze expression groups. - - importas # Enforces consistent import aliases - - ineffassign # Detects when assignments to existing variables are not used - - misspell # Finds commonly misspelled English words in comments - - nakedret # Finds naked returns in functions greater than a specified function length - - nilerr # Finds the code that returns nil even if it checks that the error is not nil. - - nilnil # Checks that there is no simultaneous return of `nil` error and an invalid value. - - noctx # noctx finds sending http request without context.Context - - predeclared # find code that shadows one of Go's predeclared identifiers - - revive # golint replacement, finds style mistakes - - staticcheck # Staticcheck is a go vet on steroids, applying a ton of static analysis checks - - stylecheck # Stylecheck is a replacement for golint - - tagliatelle # Checks the struct tags. - - tenv # tenv is analyzer that detects using os.Setenv instead of t.Setenv since Go1.17 - - tparallel # tparallel detects inappropriate usage of t.Parallel() method in your Go test codes - - typecheck # Like the front-end of a Go compiler, parses and type-checks Go code - - unconvert # Remove unnecessary type conversions - - unparam # Reports unused function parameters - - unused # Checks Go code for unused constants, variables, functions and types - - wastedassign # wastedassign finds wasted assignment statements - - whitespace # Tool for detection of leading and trailing whitespace - disable: - - containedctx # containedctx is a linter that detects struct contained context.Context field - - cyclop # checks function and package cyclomatic complexity - - exhaustivestruct # Checks if all struct's fields are initialized - - funlen # Tool for detection of long functions - - gocyclo # Computes and checks the cyclomatic complexity of functions - - godot # Check if comments end in a period - - gomnd # An analyzer to detect magic numbers. - - ifshort # Checks that your code uses short syntax for if-statements whenever possible - - ireturn # Accept Interfaces, Return Concrete Types - - lll # Reports long lines - - maintidx # maintidx measures the maintainability index of each function. - - makezero # Finds slice declarations with non-zero initial length - - maligned # Tool to detect Go structs that would take less memory if their fields were sorted - - nestif # Reports deeply nested if statements - - nlreturn # nlreturn checks for a new line before return and branch statements to increase code clarity - - nolintlint # Reports ill-formed or insufficient nolint directives - - paralleltest # paralleltest detects missing usage of t.Parallel() method in your Go test - - prealloc # Finds slice declarations that could potentially be preallocated - - promlinter # Check Prometheus metrics naming via promlint - - rowserrcheck # checks whether Err of rows is checked successfully - - sqlclosecheck # Checks that sql.Rows and sql.Stmt are closed. - - testpackage # linter that makes you use a separate _test package - - thelper # thelper detects golang test helpers without t.Helper() call and checks the consistency of test helpers - - varnamelen # checks that the length of a variable's name matches its scope - - wrapcheck # Checks that errors returned from external packages are wrapped - - wsl # Whitespace Linter - Forces you to use empty lines! - -issues: - exclude-use-default: false - exclude-rules: - # Allow complex tests, better to be self contained - - path: _test\.go - linters: - - gocognit - - forbidigo - - # Allow complex main function in examples - - path: examples - text: "of func `main` is high" - linters: - - gocognit - - # Allow forbidden identifiers in examples - - path: examples - linters: - - forbidigo - - # Allow forbidden identifiers in CLI commands - - path: cmd - linters: - - forbidigo - -run: - skip-dirs-use-default: false diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/AUTHORS.txt b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/AUTHORS.txt deleted file mode 100644 index 4ebd9a22f..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/AUTHORS.txt +++ /dev/null @@ -1,214 +0,0 @@ -# Thank you to everyone that made Pion possible. If you are interested in contributing -# we would love to have you https://github.com/pion/webrtc/wiki/Contributing -# -# This file is auto generated, using git to list all individuals contributors. -# see https://github.com/pion/.goassets/blob/master/scripts/generate-authors.sh for the scripting -a-wing <1@233.email> -Aaron Boushley -Aaron France -Adam Kiss -Aditya Kumar -Adrian Cable -adwpc -aggresss -akil -Aleksandr Razumov -aler9 <46489434+aler9@users.noreply.github.com> -Alex Browne -Alex Harford -Alexey Khit -AlexWoo(武杰) -Ali Error -Andrew N. Shalaev -Antoine Baché -Antoine Baché -Anton -Artur Shellunts -Assad Obaid -Ato Araki -Atsushi Watanabe -backkem -baiyufei -Bao Nguyen -Ben Weitzman -Benny Daon -bkim -Bo Shi -boks1971 -Brendan Rius -brian -Bryan Phelps -Cameron Elliott -Cecylia Bocovich -Cedric Fung -cgojin -Chad Retz -chenkaiC4 -Chinmay Kousik -Chris Hiszpanski -Christopher Fry -Clayton McCray -cnderrauber -cyannuk -Daniele Sluijters -David Hamilton -David Zhao -David Zhao -david.s -Dean Sheather -decanus <7621705+decanus@users.noreply.github.com> -Denis -digitalix -donotanswer -earle -Egon Elbre -Eric Daniels -Eric Fontaine -feixiao -Forest Johnson -frank -funvit -Gabor Pongracz -Gareth Hayes -Guilherme -Hanjun Kim -Hendrik Hofstadt -Henry -Hongchao Ma -Hugo Arregui -Hugo Arregui -Ilya Mayorov -imalic3 -Ivan Egorov -JacobZwang <59858341+JacobZwang@users.noreply.github.com> -Jake B -Jamie Good -Jason -Jeff Tchang -jeremija -Jerko Steiner -Jerry Tao -jinleileiking -John Berthels -John Bradley -John Selbie -JooYoung -Jorropo -Josh Bleecher Snyder -juberti -Juliusz Chroboczek -Justin Okamoto -Justin Okamoto -Kevin Staunton-Lambert -Kevin Wang -Konstantin Chugalinskiy -Konstantin Itskov -krishna chiatanya -Kuzmin Vladimir -lawl -Len -Leslie Wang -lisa yan -Lukas Herman -Luke -Luke Curley -Luke S -Magnus Wahlstrand -Manish -Markus Tzoe -Marouane <6729798+nindolabs@users.noreply.github.com> -Marouane -Masahiro Nakamura <13937915+tsuu32@users.noreply.github.com> -Mathis Engelbart -Max Hawkins -mchlrhw <4028654+mchlrhw@users.noreply.github.com> -Michael MacDonald -Michael MacDonald -Michiel De Backker <38858977+backkem@users.noreply.github.com> -Mike Coleman -Mindgamesnl -mission-liao -mohammadne -mr-shitij <21.shitijagrawal@gmail.com> -mxmCherry -Nam V. Do -Nick Mykins -nindolabs <6729798+nindolabs@users.noreply.github.com> -Norman Rasmussen -notedit -o0olele -obasajujoshua31 -Oleg Kovalov -opennota -OrlandoCo -Pascal Benoit -pascal-ace <47424881+pascal-ace@users.noreply.github.com> -Patrice Ferlet -Patrick Lange -Patryk Rogalski -Pieere Pi -Pouget-Abadie -q191201771 <191201771@qq.com> -Quentin Renard -Rafael Viscarra -rahulnakre -Raphael Randschau -Raphael Randschau -Reese <3253971+figadore@users.noreply.github.com> -rob -rob-deutsch -Robert Eperjesi -Robin Raymond -Roman Romanenko -Roman Romanenko -ronan -Ryan Shumate -salmān aljammāz -Sam Lancia -Sean DuBois -Sean DuBois -Sean DuBois -Sean DuBois -Sean DuBois -Sean Knight -Sebastian Waisbrot -Sidney San Martín -Simon Eisenmann -simonacca-fotokite <47634061+simonacca-fotokite@users.noreply.github.com> -Simone Gotti -Slugalisk -Somers Matthews -soolaugust -spaceCh1mp -Steffen Vogel -stephanrotolante -streamer45 -Suhas Gaddam -Suzuki Takeo -sylba2050 -Tarrence van As -tarrencev -Thomas Miller -Tobias Fridén -Tomek -treyhakanson -Tristan Matthews -Twometer -Vicken Simonian -wattanakorn495 -Will Forcey -Will Watson -WofWca -Woodrow Douglass -xsbchen -Yoon SeungYong -Yuki Igarashi -yusuke -Yutaka Takeda -ZHENK -zigazeljko -Štefan Uram -박종훈 - -# List of contributors not appearing in Git history - diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/constants.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/constants.go deleted file mode 100644 index 94ba78494..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/constants.go +++ /dev/null @@ -1,43 +0,0 @@ -// SPDX-FileCopyrightText: 2023 The Pion community -// SPDX-License-Identifier: MIT - -package webrtc - -import "github.com/pion/dtls/v2" - -const ( - // Unknown defines default public constant to use for "enum" like struct - // comparisons when no value was defined. - Unknown = iota - unknownStr = "unknown" - - // Equal to UDP MTU - receiveMTU = 1460 - - // simulcastProbeCount is the amount of RTP Packets - // that handleUndeclaredSSRC will read and try to dispatch from - // mid and rid values - simulcastProbeCount = 10 - - // simulcastMaxProbeRoutines is how many active routines can be used to probe - // If the total amount of incoming SSRCes exceeds this new requests will be ignored - simulcastMaxProbeRoutines = 25 - - mediaSectionApplication = "application" - - sdpAttributeRid = "rid" - - rtpOutboundMTU = 1200 - - rtpPayloadTypeBitmask = 0x7F - - incomingUnhandledRTPSsrc = "Incoming unhandled RTP ssrc(%d), OnTrack will not be fired. %v" - - generatedCertificateOrigin = "WebRTC" - - sdesRepairRTPStreamIDURI = "urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id" -) - -func defaultSrtpProtectionProfiles() []dtls.SRTPProtectionProfile { - return []dtls.SRTPProtectionProfile{dtls.SRTP_AEAD_AES_256_GCM, dtls.SRTP_AEAD_AES_128_GCM, dtls.SRTP_AES128_CM_HMAC_SHA1_80} -} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/internal/fmtp/fmtp.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/internal/fmtp/fmtp.go deleted file mode 100644 index 5461c019b..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/internal/fmtp/fmtp.go +++ /dev/null @@ -1,95 +0,0 @@ -// SPDX-FileCopyrightText: 2023 The Pion community -// SPDX-License-Identifier: MIT - -// Package fmtp implements per codec parsing of fmtp lines -package fmtp - -import ( - "strings" -) - -// FMTP interface for implementing custom -// FMTP parsers based on MimeType -type FMTP interface { - // MimeType returns the MimeType associated with - // the fmtp - MimeType() string - // Match compares two fmtp descriptions for - // compatibility based on the MimeType - Match(f FMTP) bool - // Parameter returns a value for the associated key - // if contained in the parsed fmtp string - Parameter(key string) (string, bool) -} - -// Parse parses an fmtp string based on the MimeType -func Parse(mimetype, line string) FMTP { - var f FMTP - - parameters := make(map[string]string) - - for _, p := range strings.Split(line, ";") { - pp := strings.SplitN(strings.TrimSpace(p), "=", 2) - key := strings.ToLower(pp[0]) - var value string - if len(pp) > 1 { - value = pp[1] - } - parameters[key] = value - } - - switch { - case strings.EqualFold(mimetype, "video/h264"): - f = &h264FMTP{ - parameters: parameters, - } - default: - f = &genericFMTP{ - mimeType: mimetype, - parameters: parameters, - } - } - - return f -} - -type genericFMTP struct { - mimeType string - parameters map[string]string -} - -func (g *genericFMTP) MimeType() string { - return g.mimeType -} - -// Match returns true if g and b are compatible fmtp descriptions -// The generic implementation is used for MimeTypes that are not defined -func (g *genericFMTP) Match(b FMTP) bool { - c, ok := b.(*genericFMTP) - if !ok { - return false - } - - if !strings.EqualFold(g.mimeType, c.MimeType()) { - return false - } - - for k, v := range g.parameters { - if vb, ok := c.parameters[k]; ok && !strings.EqualFold(vb, v) { - return false - } - } - - for k, v := range c.parameters { - if va, ok := g.parameters[k]; ok && !strings.EqualFold(va, v) { - return false - } - } - - return true -} - -func (g *genericFMTP) Parameter(key string) (string, bool) { - v, ok := g.parameters[key] - return v, ok -} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/operations.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/operations.go deleted file mode 100644 index d9dca4a8e..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/operations.go +++ /dev/null @@ -1,96 +0,0 @@ -// SPDX-FileCopyrightText: 2023 The Pion community -// SPDX-License-Identifier: MIT - -package webrtc - -import ( - "container/list" - "sync" -) - -// Operation is a function -type operation func() - -// Operations is a task executor. -type operations struct { - mu sync.Mutex - busy bool - ops *list.List -} - -func newOperations() *operations { - return &operations{ - ops: list.New(), - } -} - -// Enqueue adds a new action to be executed. If there are no actions scheduled, -// the execution will start immediately in a new goroutine. -func (o *operations) Enqueue(op operation) { - if op == nil { - return - } - - o.mu.Lock() - running := o.busy - o.ops.PushBack(op) - o.busy = true - o.mu.Unlock() - - if !running { - go o.start() - } -} - -// IsEmpty checks if there are tasks in the queue -func (o *operations) IsEmpty() bool { - o.mu.Lock() - defer o.mu.Unlock() - return o.ops.Len() == 0 -} - -// Done blocks until all currently enqueued operations are finished executing. -// For more complex synchronization, use Enqueue directly. -func (o *operations) Done() { - var wg sync.WaitGroup - wg.Add(1) - o.Enqueue(func() { - wg.Done() - }) - wg.Wait() -} - -func (o *operations) pop() func() { - o.mu.Lock() - defer o.mu.Unlock() - if o.ops.Len() == 0 { - return nil - } - - e := o.ops.Front() - o.ops.Remove(e) - if op, ok := e.Value.(operation); ok { - return op - } - return nil -} - -func (o *operations) start() { - defer func() { - o.mu.Lock() - defer o.mu.Unlock() - if o.ops.Len() == 0 { - o.busy = false - return - } - // either a new operation was enqueued while we - // were busy, or an operation panicked - go o.start() - }() - - fn := o.pop() - for fn != nil { - fn() - fn = o.pop() - } -} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/package.json b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/package.json deleted file mode 100644 index 429f3efb3..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/package.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "name": "webrtc", - "repository": "git@github.com:pion/webrtc.git", - "private": true, - "devDependencies": { - "wrtc": "0.4.7" - }, - "dependencies": { - "request": "2.88.2" - } -} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/pkg/media/ivfwriter/ivfwriter.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/pkg/media/ivfwriter/ivfwriter.go deleted file mode 100644 index 6d7b506e8..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/pkg/media/ivfwriter/ivfwriter.go +++ /dev/null @@ -1,233 +0,0 @@ -// SPDX-FileCopyrightText: 2023 The Pion community -// SPDX-License-Identifier: MIT - -// Package ivfwriter implements IVF media container writer -package ivfwriter - -import ( - "encoding/binary" - "errors" - "io" - "os" - - "github.com/pion/rtp" - "github.com/pion/rtp/codecs" - "github.com/pion/rtp/pkg/frame" -) - -var ( - errFileNotOpened = errors.New("file not opened") - errInvalidNilPacket = errors.New("invalid nil packet") - errCodecAlreadySet = errors.New("codec is already set") - errNoSuchCodec = errors.New("no codec for this MimeType") -) - -const ( - mimeTypeVP8 = "video/VP8" - mimeTypeAV1 = "video/AV1" - - ivfFileHeaderSignature = "DKIF" -) - -// IVFWriter is used to take RTP packets and write them to an IVF on disk -type IVFWriter struct { - ioWriter io.Writer - count uint64 - seenKeyFrame bool - - isVP8, isAV1 bool - - // VP8 - currentFrame []byte - - // AV1 - av1Frame frame.AV1 -} - -// New builds a new IVF writer -func New(fileName string, opts ...Option) (*IVFWriter, error) { - f, err := os.Create(fileName) //nolint:gosec - if err != nil { - return nil, err - } - writer, err := NewWith(f, opts...) - if err != nil { - return nil, err - } - writer.ioWriter = f - return writer, nil -} - -// NewWith initialize a new IVF writer with an io.Writer output -func NewWith(out io.Writer, opts ...Option) (*IVFWriter, error) { - if out == nil { - return nil, errFileNotOpened - } - - writer := &IVFWriter{ - ioWriter: out, - seenKeyFrame: false, - } - - for _, o := range opts { - if err := o(writer); err != nil { - return nil, err - } - } - - if !writer.isAV1 && !writer.isVP8 { - writer.isVP8 = true - } - - if err := writer.writeHeader(); err != nil { - return nil, err - } - return writer, nil -} - -func (i *IVFWriter) writeHeader() error { - header := make([]byte, 32) - copy(header[0:], ivfFileHeaderSignature) // DKIF - binary.LittleEndian.PutUint16(header[4:], 0) // Version - binary.LittleEndian.PutUint16(header[6:], 32) // Header size - - // FOURCC - if i.isVP8 { - copy(header[8:], "VP80") - } else if i.isAV1 { - copy(header[8:], "AV01") - } - - binary.LittleEndian.PutUint16(header[12:], 640) // Width in pixels - binary.LittleEndian.PutUint16(header[14:], 480) // Height in pixels - binary.LittleEndian.PutUint32(header[16:], 30) // Framerate denominator - binary.LittleEndian.PutUint32(header[20:], 1) // Framerate numerator - binary.LittleEndian.PutUint32(header[24:], 900) // Frame count, will be updated on first Close() call - binary.LittleEndian.PutUint32(header[28:], 0) // Unused - - _, err := i.ioWriter.Write(header) - return err -} - -func (i *IVFWriter) writeFrame(frame []byte) error { - frameHeader := make([]byte, 12) - binary.LittleEndian.PutUint32(frameHeader[0:], uint32(len(frame))) // Frame length - binary.LittleEndian.PutUint64(frameHeader[4:], i.count) // PTS - i.count++ - - if _, err := i.ioWriter.Write(frameHeader); err != nil { - return err - } - _, err := i.ioWriter.Write(frame) - return err -} - -// WriteRTP adds a new packet and writes the appropriate headers for it -func (i *IVFWriter) WriteRTP(packet *rtp.Packet) error { - if i.ioWriter == nil { - return errFileNotOpened - } else if len(packet.Payload) == 0 { - return nil - } - - if i.isVP8 { - vp8Packet := codecs.VP8Packet{} - if _, err := vp8Packet.Unmarshal(packet.Payload); err != nil { - return err - } - - isKeyFrame := vp8Packet.Payload[0] & 0x01 - switch { - case !i.seenKeyFrame && isKeyFrame == 1: - return nil - case i.currentFrame == nil && vp8Packet.S != 1: - return nil - } - - i.seenKeyFrame = true - i.currentFrame = append(i.currentFrame, vp8Packet.Payload[0:]...) - - if !packet.Marker { - return nil - } else if len(i.currentFrame) == 0 { - return nil - } - - if err := i.writeFrame(i.currentFrame); err != nil { - return err - } - i.currentFrame = nil - } else if i.isAV1 { - av1Packet := &codecs.AV1Packet{} - if _, err := av1Packet.Unmarshal(packet.Payload); err != nil { - return err - } - - obus, err := i.av1Frame.ReadFrames(av1Packet) - if err != nil { - return err - } - - for j := range obus { - if err := i.writeFrame(obus[j]); err != nil { - return err - } - } - } - - return nil -} - -// Close stops the recording -func (i *IVFWriter) Close() error { - if i.ioWriter == nil { - // Returns no error as it may be convenient to call - // Close() multiple times - return nil - } - - defer func() { - i.ioWriter = nil - }() - - if ws, ok := i.ioWriter.(io.WriteSeeker); ok { - // Update the framecount - if _, err := ws.Seek(24, 0); err != nil { - return err - } - buff := make([]byte, 4) - binary.LittleEndian.PutUint32(buff, uint32(i.count)) - if _, err := ws.Write(buff); err != nil { - return err - } - } - - if closer, ok := i.ioWriter.(io.Closer); ok { - return closer.Close() - } - - return nil -} - -// An Option configures a SampleBuilder. -type Option func(i *IVFWriter) error - -// WithCodec configures if IVFWriter is writing AV1 or VP8 packets to disk -func WithCodec(mimeType string) Option { - return func(i *IVFWriter) error { - if i.isVP8 || i.isAV1 { - return errCodecAlreadySet - } - - switch mimeType { - case mimeTypeVP8: - i.isVP8 = true - case mimeTypeAV1: - i.isAV1 = true - default: - return errNoSuchCodec - } - - return nil - } -} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/track_local.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/track_local.go deleted file mode 100644 index a2e6599a5..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/track_local.go +++ /dev/null @@ -1,90 +0,0 @@ -// SPDX-FileCopyrightText: 2023 The Pion community -// SPDX-License-Identifier: MIT - -package webrtc - -import ( - "github.com/pion/interceptor" - "github.com/pion/rtp" -) - -// TrackLocalWriter is the Writer for outbound RTP Packets -type TrackLocalWriter interface { - // WriteRTP encrypts a RTP packet and writes to the connection - WriteRTP(header *rtp.Header, payload []byte) (int, error) - - // Write encrypts and writes a full RTP packet - Write(b []byte) (int, error) -} - -// TrackLocalContext is the Context passed when a TrackLocal has been Binded/Unbinded from a PeerConnection, and used -// in Interceptors. -type TrackLocalContext struct { - id string - params RTPParameters - ssrc SSRC - writeStream TrackLocalWriter - rtcpInterceptor interceptor.RTCPReader -} - -// CodecParameters returns the negotiated RTPCodecParameters. These are the codecs supported by both -// PeerConnections and the SSRC/PayloadTypes -func (t *TrackLocalContext) CodecParameters() []RTPCodecParameters { - return t.params.Codecs -} - -// HeaderExtensions returns the negotiated RTPHeaderExtensionParameters. These are the header extensions supported by -// both PeerConnections and the SSRC/PayloadTypes -func (t *TrackLocalContext) HeaderExtensions() []RTPHeaderExtensionParameter { - return t.params.HeaderExtensions -} - -// SSRC requires the negotiated SSRC of this track -// This track may have multiple if RTX is enabled -func (t *TrackLocalContext) SSRC() SSRC { - return t.ssrc -} - -// WriteStream returns the WriteStream for this TrackLocal. The implementer writes the outbound -// media packets to it -func (t *TrackLocalContext) WriteStream() TrackLocalWriter { - return t.writeStream -} - -// ID is a unique identifier that is used for both Bind/Unbind -func (t *TrackLocalContext) ID() string { - return t.id -} - -// RTCPReader returns the RTCP interceptor for this TrackLocal. Used to read RTCP of this TrackLocal. -func (t *TrackLocalContext) RTCPReader() interceptor.RTCPReader { - return t.rtcpInterceptor -} - -// TrackLocal is an interface that controls how the user can send media -// The user can provide their own TrackLocal implementations, or use -// the implementations in pkg/media -type TrackLocal interface { - // Bind should implement the way how the media data flows from the Track to the PeerConnection - // This will be called internally after signaling is complete and the list of available - // codecs has been determined - Bind(TrackLocalContext) (RTPCodecParameters, error) - - // Unbind should implement the teardown logic when the track is no longer needed. This happens - // because a track has been stopped. - Unbind(TrackLocalContext) error - - // ID is the unique identifier for this Track. This should be unique for the - // stream, but doesn't have to globally unique. A common example would be 'audio' or 'video' - // and StreamID would be 'desktop' or 'webcam' - ID() string - - // RID is the RTP Stream ID for this track. - RID() string - - // StreamID is the group this track belongs too. This must be unique - StreamID() string - - // Kind controls if this TrackLocal is audio or video - Kind() RTPCodecType -} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/yarn.lock b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/yarn.lock deleted file mode 100644 index 01bf7823d..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/yarn.lock +++ /dev/null @@ -1,797 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - -# SPDX-FileCopyrightText: 2023 The Pion community -# SPDX-License-Identifier: MIT - -abbrev@1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" - integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== - -ajv@^6.5.5: - version "6.12.2" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.2.tgz#c629c5eced17baf314437918d2da88c99d5958cd" - integrity sha512-k+V+hzjm5q/Mr8ef/1Y9goCmlsK4I6Sm74teeyGvFk1XrOsbsKLjEdrvny42CZ+a8sXbk8KWpY/bDwS+FLL2UQ== - dependencies: - fast-deep-equal "^3.1.1" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.4.1" - uri-js "^4.2.2" - -ansi-regex@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" - integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= - -ansi-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" - integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= - -aproba@^1.0.3: - version "1.2.0" - resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" - integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== - -are-we-there-yet@~1.1.2: - version "1.1.5" - resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21" - integrity sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w== - dependencies: - delegates "^1.0.0" - readable-stream "^2.0.6" - -asn1@~0.2.3: - version "0.2.4" - resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" - integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg== - dependencies: - safer-buffer "~2.1.0" - -assert-plus@1.0.0, assert-plus@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" - integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= - -asynckit@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" - integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= - -aws-sign2@~0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" - integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= - -aws4@^1.8.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.10.0.tgz#a17b3a8ea811060e74d47d306122400ad4497ae2" - integrity sha512-3YDiu347mtVtjpyV3u5kVqQLP242c06zwDOgpeRnybmXlYYsLbtTrUBUm8i8srONt+FWobl5aibnU1030PeeuA== - -balanced-match@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" - integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= - -bcrypt-pbkdf@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" - integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4= - dependencies: - tweetnacl "^0.14.3" - -brace-expansion@^1.1.7: - version "1.1.11" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" - integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== - dependencies: - balanced-match "^1.0.0" - concat-map "0.0.1" - -caseless@~0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" - integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= - -chownr@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.1.tgz#54726b8b8fff4df053c42187e801fb4412df1494" - integrity sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g== - -code-point-at@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" - integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= - -combined-stream@^1.0.6, combined-stream@~1.0.6: - version "1.0.8" - resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" - integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== - dependencies: - delayed-stream "~1.0.0" - -concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= - -console-control-strings@^1.0.0, console-control-strings@~1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" - integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= - -core-util-is@1.0.2, core-util-is@~1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" - integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= - -dashdash@^1.12.0: - version "1.14.1" - resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" - integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA= - dependencies: - assert-plus "^1.0.0" - -debug@^2.1.2: - version "2.6.9" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" - integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== - dependencies: - ms "2.0.0" - -deep-extend@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" - integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== - -delayed-stream@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" - integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= - -delegates@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" - integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= - -detect-libc@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" - integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= - -domexception@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/domexception/-/domexception-1.0.1.tgz#937442644ca6a31261ef36e3ec677fe805582c90" - integrity sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug== - dependencies: - webidl-conversions "^4.0.2" - -ecc-jsbn@~0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" - integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk= - dependencies: - jsbn "~0.1.0" - safer-buffer "^2.1.0" - -extend@~3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" - integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== - -extsprintf@1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" - integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU= - -extsprintf@^1.2.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" - integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8= - -fast-deep-equal@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz#545145077c501491e33b15ec408c294376e94ae4" - integrity sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA== - -fast-json-stable-stringify@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" - integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== - -forever-agent@~0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" - integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= - -form-data@~2.3.2: - version "2.3.3" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" - integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.6" - mime-types "^2.1.12" - -fs-minipass@^1.2.5: - version "1.2.5" - resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.5.tgz#06c277218454ec288df77ada54a03b8702aacb9d" - integrity sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ== - dependencies: - minipass "^2.2.1" - -fs.realpath@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= - -gauge@~2.7.3: - version "2.7.4" - resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" - integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c= - dependencies: - aproba "^1.0.3" - console-control-strings "^1.0.0" - has-unicode "^2.0.0" - object-assign "^4.1.0" - signal-exit "^3.0.0" - string-width "^1.0.1" - strip-ansi "^3.0.1" - wide-align "^1.1.0" - -getpass@^0.1.1: - version "0.1.7" - resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" - integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo= - dependencies: - assert-plus "^1.0.0" - -glob@^7.1.3: - version "7.1.3" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" - integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -har-schema@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" - integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= - -har-validator@~5.1.3: - version "5.1.3" - resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.3.tgz#1ef89ebd3e4996557675eed9893110dc350fa080" - integrity sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g== - dependencies: - ajv "^6.5.5" - har-schema "^2.0.0" - -has-unicode@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" - integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= - -http-signature@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" - integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE= - dependencies: - assert-plus "^1.0.0" - jsprim "^1.2.2" - sshpk "^1.7.0" - -iconv-lite@^0.4.4: - version "0.4.24" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" - integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== - dependencies: - safer-buffer ">= 2.1.2 < 3" - -ignore-walk@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.1.tgz#a83e62e7d272ac0e3b551aaa82831a19b69f82f8" - integrity sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ== - dependencies: - minimatch "^3.0.4" - -inflight@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= - dependencies: - once "^1.3.0" - wrappy "1" - -inherits@2, inherits@~2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" - integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= - -ini@~1.3.0: - version "1.3.5" - resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" - integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== - -is-fullwidth-code-point@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" - integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs= - dependencies: - number-is-nan "^1.0.0" - -is-fullwidth-code-point@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" - integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= - -is-typedarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" - integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= - -isarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= - -isstream@~0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" - integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= - -jsbn@~0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" - integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= - -json-schema-traverse@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" - integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== - -json-schema@0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" - integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM= - -json-stringify-safe@~5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" - integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= - -jsprim@^1.2.2: - version "1.4.1" - resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" - integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI= - dependencies: - assert-plus "1.0.0" - extsprintf "1.3.0" - json-schema "0.2.3" - verror "1.10.0" - -mime-db@1.44.0: - version "1.44.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.44.0.tgz#fa11c5eb0aca1334b4233cb4d52f10c5a6272f92" - integrity sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg== - -mime-types@^2.1.12, mime-types@~2.1.19: - version "2.1.27" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.27.tgz#47949f98e279ea53119f5722e0f34e529bec009f" - integrity sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w== - dependencies: - mime-db "1.44.0" - -minimatch@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" - integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== - dependencies: - brace-expansion "^1.1.7" - -minimist@0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" - integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= - -minimist@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" - integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= - -minipass@^2.2.1, minipass@^2.3.4: - version "2.3.5" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.3.5.tgz#cacebe492022497f656b0f0f51e2682a9ed2d848" - integrity sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA== - dependencies: - safe-buffer "^5.1.2" - yallist "^3.0.0" - -minizlib@^1.1.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.2.1.tgz#dd27ea6136243c7c880684e8672bb3a45fd9b614" - integrity sha512-7+4oTUOWKg7AuL3vloEWekXY2/D20cevzsrNT2kGWm+39J9hGTCBv8VI5Pm5lXZ/o3/mdR4f8rflAPhnQb8mPA== - dependencies: - minipass "^2.2.1" - -mkdirp@^0.5.0, mkdirp@^0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" - integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= - dependencies: - minimist "0.0.8" - -ms@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= - -needle@^2.2.1: - version "2.2.4" - resolved "https://registry.yarnpkg.com/needle/-/needle-2.2.4.tgz#51931bff82533b1928b7d1d69e01f1b00ffd2a4e" - integrity sha512-HyoqEb4wr/rsoaIDfTH2aVL9nWtQqba2/HvMv+++m8u0dz808MaagKILxtfeSN7QU7nvbQ79zk3vYOJp9zsNEA== - dependencies: - debug "^2.1.2" - iconv-lite "^0.4.4" - sax "^1.2.4" - -node-pre-gyp@^0.13.0: - version "0.13.0" - resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.13.0.tgz#df9ab7b68dd6498137717838e4f92a33fc9daa42" - integrity sha512-Md1D3xnEne8b/HGVQkZZwV27WUi1ZRuZBij24TNaZwUPU3ZAFtvT6xxJGaUVillfmMKnn5oD1HoGsp2Ftik7SQ== - dependencies: - detect-libc "^1.0.2" - mkdirp "^0.5.1" - needle "^2.2.1" - nopt "^4.0.1" - npm-packlist "^1.1.6" - npmlog "^4.0.2" - rc "^1.2.7" - rimraf "^2.6.1" - semver "^5.3.0" - tar "^4" - -nopt@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d" - integrity sha1-0NRoWv1UFRk8jHUFYC0NF81kR00= - dependencies: - abbrev "1" - osenv "^0.1.4" - -npm-bundled@^1.0.1: - version "1.0.6" - resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.0.6.tgz#e7ba9aadcef962bb61248f91721cd932b3fe6bdd" - integrity sha512-8/JCaftHwbd//k6y2rEWp6k1wxVfpFzB6t1p825+cUb7Ym2XQfhwIC5KwhrvzZRJu+LtDE585zVaS32+CGtf0g== - -npm-packlist@^1.1.6: - version "1.4.1" - resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.4.1.tgz#19064cdf988da80ea3cee45533879d90192bbfbc" - integrity sha512-+TcdO7HJJ8peiiYhvPxsEDhF3PJFGUGRcFsGve3vxvxdcpO2Z4Z7rkosRM0kWj6LfbK/P0gu3dzk5RU1ffvFcw== - dependencies: - ignore-walk "^3.0.1" - npm-bundled "^1.0.1" - -npmlog@^4.0.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" - integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== - dependencies: - are-we-there-yet "~1.1.2" - console-control-strings "~1.1.0" - gauge "~2.7.3" - set-blocking "~2.0.0" - -number-is-nan@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" - integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= - -oauth-sign@~0.9.0: - version "0.9.0" - resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" - integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== - -object-assign@^4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" - integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= - -once@^1.3.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= - dependencies: - wrappy "1" - -os-homedir@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" - integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= - -os-tmpdir@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" - integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= - -osenv@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410" - integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g== - dependencies: - os-homedir "^1.0.0" - os-tmpdir "^1.0.0" - -path-is-absolute@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= - -performance-now@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" - integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= - -process-nextick-args@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa" - integrity sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw== - -psl@^1.1.28: - version "1.8.0" - resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24" - integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ== - -punycode@^2.1.0, punycode@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" - integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== - -qs@~6.5.2: - version "6.5.2" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" - integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== - -rc@^1.2.7: - version "1.2.8" - resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" - integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== - dependencies: - deep-extend "^0.6.0" - ini "~1.3.0" - minimist "^1.2.0" - strip-json-comments "~2.0.1" - -readable-stream@^2.0.6: - version "2.3.6" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" - integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw== - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.3" - isarray "~1.0.0" - process-nextick-args "~2.0.0" - safe-buffer "~5.1.1" - string_decoder "~1.1.1" - util-deprecate "~1.0.1" - -request@2.88.2: - version "2.88.2" - resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" - integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== - dependencies: - aws-sign2 "~0.7.0" - aws4 "^1.8.0" - caseless "~0.12.0" - combined-stream "~1.0.6" - extend "~3.0.2" - forever-agent "~0.6.1" - form-data "~2.3.2" - har-validator "~5.1.3" - http-signature "~1.2.0" - is-typedarray "~1.0.0" - isstream "~0.1.2" - json-stringify-safe "~5.0.1" - mime-types "~2.1.19" - oauth-sign "~0.9.0" - performance-now "^2.1.0" - qs "~6.5.2" - safe-buffer "^5.1.2" - tough-cookie "~2.5.0" - tunnel-agent "^0.6.0" - uuid "^3.3.2" - -rimraf@^2.6.1: - version "2.6.3" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" - integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== - dependencies: - glob "^7.1.3" - -safe-buffer@^5.0.1: - version "5.2.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" - integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== - -safe-buffer@^5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: - version "5.1.2" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" - integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== - -"safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: - version "2.1.2" - resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" - integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== - -sax@^1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" - integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== - -semver@^5.3.0: - version "5.6.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004" - integrity sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg== - -set-blocking@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" - integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= - -signal-exit@^3.0.0: - version "3.0.2" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" - integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0= - -sshpk@^1.7.0: - version "1.16.1" - resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877" - integrity sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg== - dependencies: - asn1 "~0.2.3" - assert-plus "^1.0.0" - bcrypt-pbkdf "^1.0.0" - dashdash "^1.12.0" - ecc-jsbn "~0.1.1" - getpass "^0.1.1" - jsbn "~0.1.0" - safer-buffer "^2.0.2" - tweetnacl "~0.14.0" - -string-width@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" - integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= - dependencies: - code-point-at "^1.0.0" - is-fullwidth-code-point "^1.0.0" - strip-ansi "^3.0.0" - -"string-width@^1.0.2 || 2": - version "2.1.1" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" - integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== - dependencies: - is-fullwidth-code-point "^2.0.0" - strip-ansi "^4.0.0" - -string_decoder@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" - integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== - dependencies: - safe-buffer "~5.1.0" - -strip-ansi@^3.0.0, strip-ansi@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" - integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= - dependencies: - ansi-regex "^2.0.0" - -strip-ansi@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" - integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= - dependencies: - ansi-regex "^3.0.0" - -strip-json-comments@~2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" - integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= - -tar@^4: - version "4.4.8" - resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.8.tgz#b19eec3fde2a96e64666df9fdb40c5ca1bc3747d" - integrity sha512-LzHF64s5chPQQS0IYBn9IN5h3i98c12bo4NCO7e0sGM2llXQ3p2FGC5sdENN4cTW48O915Sh+x+EXx7XW96xYQ== - dependencies: - chownr "^1.1.1" - fs-minipass "^1.2.5" - minipass "^2.3.4" - minizlib "^1.1.1" - mkdirp "^0.5.0" - safe-buffer "^5.1.2" - yallist "^3.0.2" - -tough-cookie@~2.5.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" - integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== - dependencies: - psl "^1.1.28" - punycode "^2.1.1" - -tunnel-agent@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" - integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= - dependencies: - safe-buffer "^5.0.1" - -tweetnacl@^0.14.3, tweetnacl@~0.14.0: - version "0.14.5" - resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" - integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= - -uri-js@^4.2.2: - version "4.2.2" - resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" - integrity sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ== - dependencies: - punycode "^2.1.0" - -util-deprecate@~1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= - -uuid@^3.3.2: - version "3.4.0" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" - integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== - -verror@1.10.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" - integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA= - dependencies: - assert-plus "^1.0.0" - core-util-is "1.0.2" - extsprintf "^1.2.0" - -webidl-conversions@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad" - integrity sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg== - -wide-align@^1.1.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" - integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== - dependencies: - string-width "^1.0.2 || 2" - -wrappy@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= - -wrtc@0.4.7: - version "0.4.7" - resolved "https://registry.yarnpkg.com/wrtc/-/wrtc-0.4.7.tgz#c61530cd662713e50bffe64b7a78673ce070426c" - integrity sha512-P6Hn7VT4lfSH49HxLHcHhDq+aFf/jd9dPY7lDHeFhZ22N3858EKuwm2jmnlPzpsRGEPaoF6XwkcxY5SYnt4f/g== - dependencies: - node-pre-gyp "^0.13.0" - optionalDependencies: - domexception "^1.0.1" - -yallist@^3.0.0, yallist@^3.0.2: - version "3.0.3" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.3.tgz#b4b049e314be545e3ce802236d6cd22cd91c3de9" - integrity sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A== diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/.codacy.yaml b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/.codacy.yaml similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/.codacy.yaml rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/.codacy.yaml diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/.eslintrc.json b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/.eslintrc.json similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/.eslintrc.json rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/.eslintrc.json diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/.gitignore b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/.gitignore new file mode 100644 index 000000000..6e2f206a9 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/.gitignore @@ -0,0 +1,28 @@ +# SPDX-FileCopyrightText: 2023 The Pion community +# SPDX-License-Identifier: MIT + +### JetBrains IDE ### +##################### +.idea/ + +### Emacs Temporary Files ### +############################# +*~ + +### Folders ### +############### +bin/ +vendor/ +node_modules/ + +### Files ### +############# +*.ivf +*.ogg +tags +cover.out +*.sw[poe] +*.wasm +examples/sfu-ws/cert.pem +examples/sfu-ws/key.pem +wasm_exec.js diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/.golangci.yml b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/.golangci.yml new file mode 100644 index 000000000..120faf29b --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/.golangci.yml @@ -0,0 +1,145 @@ +# SPDX-FileCopyrightText: 2023 The Pion community +# SPDX-License-Identifier: MIT + +run: + timeout: 5m + +linters-settings: + govet: + enable: + - shadow + misspell: + locale: US + exhaustive: + default-signifies-exhaustive: true + gomodguard: + blocked: + modules: + - github.com/pkg/errors: + recommendations: + - errors + forbidigo: + analyze-types: true + forbid: + - ^fmt.Print(f|ln)?$ + - ^log.(Panic|Fatal|Print)(f|ln)?$ + - ^os.Exit$ + - ^panic$ + - ^print(ln)?$ + - p: ^testing.T.(Error|Errorf|Fatal|Fatalf|Fail|FailNow)$ + pkg: ^testing$ + msg: "use testify/assert instead" + varnamelen: + max-distance: 12 + min-name-length: 2 + ignore-type-assert-ok: true + ignore-map-index-ok: true + ignore-chan-recv-ok: true + ignore-decls: + - i int + - n int + - w io.Writer + - r io.Reader + - b []byte + +linters: + enable: + - asciicheck # Simple linter to check that your code does not contain non-ASCII identifiers + - bidichk # Checks for dangerous unicode character sequences + - bodyclose # checks whether HTTP response body is closed successfully + - containedctx # containedctx is a linter that detects struct contained context.Context field + - contextcheck # check the function whether use a non-inherited context + - cyclop # checks function and package cyclomatic complexity + - decorder # check declaration order and count of types, constants, variables and functions + - dogsled # Checks assignments with too many blank identifiers (e.g. x, _, _, _, := f()) + - dupl # Tool for code clone detection + - durationcheck # check for two durations multiplied together + - err113 # Golang linter to check the errors handling expressions + - errcheck # Errcheck is a program for checking for unchecked errors in go programs. These unchecked errors can be critical bugs in some cases + - errchkjson # Checks types passed to the json encoding functions. Reports unsupported types and optionally reports occations, where the check for the returned error can be omitted. + - errname # Checks that sentinel errors are prefixed with the `Err` and error types are suffixed with the `Error`. + - errorlint # errorlint is a linter for that can be used to find code that will cause problems with the error wrapping scheme introduced in Go 1.13. + - exhaustive # check exhaustiveness of enum switch statements + - exportloopref # checks for pointers to enclosing loop variables + - forbidigo # Forbids identifiers + - forcetypeassert # finds forced type assertions + - gci # Gci control golang package import order and make it always deterministic. + - gochecknoglobals # Checks that no globals are present in Go code + - gocognit # Computes and checks the cognitive complexity of functions + - goconst # Finds repeated strings that could be replaced by a constant + - gocritic # The most opinionated Go source code linter + - gocyclo # Computes and checks the cyclomatic complexity of functions + - godot # Check if comments end in a period + - godox # Tool for detection of FIXME, TODO and other comment keywords + - gofmt # Gofmt checks whether code was gofmt-ed. By default this tool runs with -s option to check for code simplification + - gofumpt # Gofumpt checks whether code was gofumpt-ed. + - goheader # Checks is file header matches to pattern + - goimports # Goimports does everything that gofmt does. Additionally it checks unused imports + - gomoddirectives # Manage the use of 'replace', 'retract', and 'excludes' directives in go.mod. + - goprintffuncname # Checks that printf-like functions are named with `f` at the end + - gosec # Inspects source code for security problems + - gosimple # Linter for Go source code that specializes in simplifying a code + - govet # Vet examines Go source code and reports suspicious constructs, such as Printf calls whose arguments do not align with the format string + - grouper # An analyzer to analyze expression groups. + - importas # Enforces consistent import aliases + - ineffassign # Detects when assignments to existing variables are not used + - lll # Reports long lines + - maintidx # maintidx measures the maintainability index of each function. + - makezero # Finds slice declarations with non-zero initial length + - misspell # Finds commonly misspelled English words in comments + - nakedret # Finds naked returns in functions greater than a specified function length + - nestif # Reports deeply nested if statements + - nilerr # Finds the code that returns nil even if it checks that the error is not nil. + - nilnil # Checks that there is no simultaneous return of `nil` error and an invalid value. + - nlreturn # nlreturn checks for a new line before return and branch statements to increase code clarity + - noctx # noctx finds sending http request without context.Context + - predeclared # find code that shadows one of Go's predeclared identifiers + - revive # golint replacement, finds style mistakes + - staticcheck # Staticcheck is a go vet on steroids, applying a ton of static analysis checks + - stylecheck # Stylecheck is a replacement for golint + - tagliatelle # Checks the struct tags. + - tenv # tenv is analyzer that detects using os.Setenv instead of t.Setenv since Go1.17 + - thelper # thelper detects golang test helpers without t.Helper() call and checks the consistency of test helpers + - typecheck # Like the front-end of a Go compiler, parses and type-checks Go code + - unconvert # Remove unnecessary type conversions + - unparam # Reports unused function parameters + - unused # Checks Go code for unused constants, variables, functions and types + - varnamelen # checks that the length of a variable's name matches its scope + - wastedassign # wastedassign finds wasted assignment statements + - whitespace # Tool for detection of leading and trailing whitespace + disable: + - depguard # Go linter that checks if package imports are in a list of acceptable packages + - funlen # Tool for detection of long functions + - gochecknoinits # Checks that no init functions are present in Go code + - gomodguard # Allow and block list linter for direct Go module dependencies. This is different from depguard where there are different block types for example version constraints and module recommendations. + - interfacebloat # A linter that checks length of interface. + - ireturn # Accept Interfaces, Return Concrete Types + - mnd # An analyzer to detect magic numbers + - nolintlint # Reports ill-formed or insufficient nolint directives + - paralleltest # paralleltest detects missing usage of t.Parallel() method in your Go test + - prealloc # Finds slice declarations that could potentially be preallocated + - promlinter # Check Prometheus metrics naming via promlint + - rowserrcheck # checks whether Err of rows is checked successfully + - sqlclosecheck # Checks that sql.Rows and sql.Stmt are closed. + - testpackage # linter that makes you use a separate _test package + - tparallel # tparallel detects inappropriate usage of t.Parallel() method in your Go test codes + - wrapcheck # Checks that errors returned from external packages are wrapped + - wsl # Whitespace Linter - Forces you to use empty lines! + +issues: + exclude-use-default: false + exclude-dirs-use-default: false + exclude-rules: + # Allow complex tests and examples, better to be self contained + - path: (examples|main\.go) + linters: + - gocognit + - forbidigo + - path: _test\.go + linters: + - gocognit + + # Allow forbidden identifiers in CLI commands + - path: cmd + linters: + - forbidigo diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/.goreleaser.yml b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/.goreleaser.yml new file mode 100644 index 000000000..30093e9d6 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/.goreleaser.yml @@ -0,0 +1,5 @@ +# SPDX-FileCopyrightText: 2023 The Pion community +# SPDX-License-Identifier: MIT + +builds: +- skip: true diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/DESIGN.md b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/DESIGN.md similarity index 97% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/DESIGN.md rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/DESIGN.md index e22b08e30..45ca1ac0e 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/DESIGN.md +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/DESIGN.md @@ -19,7 +19,7 @@ When possible we leave all decisions to the user. When choice is possible (like If you know how to use WebRTC in your browser, you know how to use Pion WebRTC. We try our best just to duplicate the Javascript API, so your code can look the same everywhere. -If this is your first time using WebRTC, don't worry! We have multiple [examples](https://github.com/pion/webrtc/tree/master/examples) and [GoDoc](https://pkg.go.dev/github.com/pion/webrtc/v3) +If this is your first time using WebRTC, don't worry! We have multiple [examples](https://github.com/pion/webrtc/tree/master/examples) and [GoDoc](https://pkg.go.dev/github.com/pion/webrtc/v4) ### Bring your own media Pion WebRTC doesn't make any assumptions about where your audio, video or text come from. You can use FFmpeg, GStreamer, MLT or just serve a video file. diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/LICENSE.md b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/LICENSE similarity index 93% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/LICENSE.md rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/LICENSE index 5cc9cbdc5..491caf6b0 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/turn/v2/LICENSE.md +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/LICENSE @@ -1,4 +1,6 @@ -Copyright 2018 Pion LLC +MIT License + +Copyright (c) 2023 The Pion community Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/README.md b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/README.md similarity index 70% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/README.md rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/README.md index 80dd8c123..97bbe70f0 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/README.md +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/README.md @@ -8,20 +8,29 @@

Pion WebRTC Sourcegraph Widget - Slack Widget - Twitter Widget + join us on Discord Follow us on Bluesky Twitter Widget
GitHub Workflow Status - Go Reference + Go Reference Coverage Status - Go Report Card + Go Report Card License: MIT


+### New Release + +Pion WebRTC v4.0.0 has been released! See the [release notes](https://github.com/pion/webrtc/wiki/Release-WebRTC@v4.0.0) to learn about new features and breaking changes. + +If you aren't able to upgrade yet check the [tags](https://github.com/pion/webrtc/tags) for the latest `v3` release. + +We would love your feedback! Please create GitHub issues or Join the [Discord](https://discord.gg/PngbdqpFbt) to follow development and speak with the maintainers. + +----- + ### Usage -[Go Modules](https://blog.golang.org/using-go-modules) are mandatory for using Pion WebRTC. So make sure you set `export GO111MODULE=on`, and explicitly specify `/v2` or `/v3` when importing. +[Go Modules](https://blog.golang.org/using-go-modules) are mandatory for using Pion WebRTC. So make sure you set `export GO111MODULE=on`, and explicitly specify `/v4` (or an earlier version) when importing. **[example applications](examples/README.md)** contains code samples of common things people build with Pion WebRTC. @@ -30,9 +39,9 @@ **[awesome-pion](https://github.com/pion/awesome-pion)** contains projects that have used Pion, and serve as real world examples of usage. -**[GoDoc](https://pkg.go.dev/github.com/pion/webrtc/v3)** is an auto generated API reference. All our Public APIs are commented. +**[GoDoc](https://pkg.go.dev/github.com/pion/webrtc/v4)** is an auto generated API reference. All our Public APIs are commented. -**[FAQ](https://github.com/pion/webrtc/wiki/FAQ)** has answers to common questions. If you have a question not covered please ask in [Slack](https://pion.ly/slack) we are always looking to expand it. +**[FAQ](https://github.com/pion/webrtc/wiki/FAQ)** has answers to common questions. If you have a question not covered please ask in [Discord](https://discord.gg/PngbdqpFbt) we are always looking to expand it. Now go build something awesome! Here are some **ideas** to get your creative juices flowing: * Send a video file to multiple browser in real time for perfectly synchronized movie watching. @@ -42,16 +51,17 @@ Now go build something awesome! Here are some **ideas** to get your creative jui * Build a conferencing application that processes audio/video and make decisions off of it. * Remotely control a robots and stream its cameras in realtime. -### Want to learn more about WebRTC? -Join our [Office Hours](https://github.com/pion/webrtc/wiki/OfficeHours). Come hang out, ask questions, get help debugging and -hear about the cool things being built with WebRTC. We also start every meeting with basic project planning. - +### Need Help? Check out [WebRTC for the Curious](https://webrtcforthecurious.com). A book about WebRTC in depth, not just about the APIs. -Learn the full details of ICE, SCTP, DTLS, SRTP, and how they work together to make up the WebRTC stack. +Learn the full details of ICE, SCTP, DTLS, SRTP, and how they work together to make up the WebRTC stack. This is also a great +resource if you are trying to debug. Learn the tools of the trade and how to approach WebRTC issues. This book is vendor +agnostic and will not have any Pion specific information. -This is also a great resource if you are trying to debug. Learn the tools of the trade and how to approach WebRTC issues. +Pion has an active community on [Discord](https://discord.gg/PngbdqpFbt). Please ask for help about anything, questions don't have to be Pion specific! +Come share your interesting project you are working on. We are here to support you. -This book is vendor agnostic and will not have any Pion specific information. +One of the maintainers of Pion [Sean-Der](https://github.com/sean-der) is available to help. Schedule at [siobud.com/meeting](https://siobud.com/meeting) +He is available to talk about Pion or general WebRTC questions, feel free to reach out about anything! ### Features #### PeerConnection API @@ -60,7 +70,7 @@ This book is vendor agnostic and will not have any Pion specific information. * Send/Receive audio and video * Renegotiation * Plan-B and Unified Plan -* [SettingEngine](https://pkg.go.dev/github.com/pion/webrtc/v3#SettingEngine) for Pion specific extensions +* [SettingEngine](https://pkg.go.dev/github.com/pion/webrtc/v4#SettingEngine) for Pion specific extensions #### Connectivity @@ -115,15 +125,15 @@ If you are looking to get involved this is a great place to get started! We woul Work on Pion's congestion control and bandwidth estimation was funded through the [User-Operated Internet](https://nlnet.nl/useroperated/) fund, a fund established by [NLnet](https://nlnet.nl/) made possible by financial support from the [PKT Community](https://pkt.cash/)/[The Network Steward](https://pkt.cash/network-steward) and stichting [Technology Commons Trust](https://technologycommons.org/). ### Community -Pion has an active community on the [Slack](https://pion.ly/slack). +Pion has an active community on the [Discord](https://discord.gg/PngbdqpFbt). -Follow the [Pion Twitter](https://twitter.com/_pion) for project updates and important WebRTC news. +Follow the [Pion Bluesky](https://bsky.app/profile/pion.ly) or [Pion Twitter](https://twitter.com/_pion) for project updates and important WebRTC news. We are always looking to support **your projects**. Please reach out if you have something to build! If you need commercial support or don't want to use public methods you can contact us at [team@pion.ly](mailto:team@pion.ly) ### Contributing -Check out the [contributing wiki](https://github.com/pion/webrtc/wiki/Contributing) to join the group of amazing people making this project possible: [AUTHORS.txt](./AUTHORS.txt) +Check out the [contributing wiki](https://github.com/pion/webrtc/wiki/Contributing) to join the group of amazing people making this project possible ### License MIT License - see [LICENSE](LICENSE) for full text diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/api.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/api.go similarity index 67% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/api.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/api.go index 716be1f38..a96ebad40 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/api.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/api.go @@ -25,23 +25,42 @@ type API struct { } // NewAPI Creates a new API object for keeping semi-global settings to WebRTC objects +// +// It uses the default Codecs and Interceptors unless you customize them +// using WithMediaEngine and WithInterceptorRegistry respectively. func NewAPI(options ...func(*API)) *API { - a := &API{ - interceptor: &interceptor.NoOp{}, - settingEngine: &SettingEngine{}, - mediaEngine: &MediaEngine{}, - interceptorRegistry: &interceptor.Registry{}, + api := &API{ + interceptor: &interceptor.NoOp{}, + settingEngine: &SettingEngine{}, } for _, o := range options { - o(a) + o(api) } - if a.settingEngine.LoggerFactory == nil { - a.settingEngine.LoggerFactory = logging.NewDefaultLoggerFactory() + if api.settingEngine.LoggerFactory == nil { + api.settingEngine.LoggerFactory = logging.NewDefaultLoggerFactory() } - return a + logger := api.settingEngine.LoggerFactory.NewLogger("api") + + if api.mediaEngine == nil { + api.mediaEngine = &MediaEngine{} + err := api.mediaEngine.RegisterDefaultCodecs() + if err != nil { + logger.Errorf("Failed to register default codecs %s", err) + } + } + + if api.interceptorRegistry == nil { + api.interceptorRegistry = &interceptor.Registry{} + err := RegisterDefaultInterceptors(api.mediaEngine, api.interceptorRegistry) + if err != nil { + logger.Errorf("Failed to register default interceptors %s", err) + } + } + + return api } // WithMediaEngine allows providing a MediaEngine to the API. diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/api_js.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/api_js.go similarity index 91% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/api_js.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/api_js.go index fe94bff1f..1f0fcb74c 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/api_js.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/api_js.go @@ -6,7 +6,7 @@ package webrtc -// API bundles the global funcions of the WebRTC and ORTC API. +// API bundles the global functions of the WebRTC and ORTC API. type API struct { settingEngine *SettingEngine } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/atomicbool.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/atomicbool.go similarity index 99% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/atomicbool.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/atomicbool.go index cc6cdc1e8..846289eca 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/atomicbool.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/atomicbool.go @@ -27,5 +27,6 @@ func (b *atomicBool) swap(value bool) bool { if value { i = 1 } + return atomic.SwapInt32(&(b.val), i) != 0 } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/bundlepolicy.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/bundlepolicy.go similarity index 91% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/bundlepolicy.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/bundlepolicy.go index ea6dad5ae..1750ade38 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/bundlepolicy.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/bundlepolicy.go @@ -14,11 +14,14 @@ import ( type BundlePolicy int const ( + // BundlePolicyUnknown is the enum's zero-value. + BundlePolicyUnknown BundlePolicy = iota + // BundlePolicyBalanced indicates to gather ICE candidates for each // media type in use (audio, video, and data). If the remote endpoint is // not bundle-aware, negotiate only one audio and video track on separate // transports. - BundlePolicyBalanced BundlePolicy = iota + 1 + BundlePolicyBalanced // BundlePolicyMaxCompat indicates to gather ICE candidates for each // track. If the remote endpoint is not bundle-aware, negotiate all media @@ -47,7 +50,7 @@ func newBundlePolicy(raw string) BundlePolicy { case bundlePolicyMaxBundleStr: return BundlePolicyMaxBundle default: - return BundlePolicy(Unknown) + return BundlePolicyUnknown } } @@ -64,7 +67,7 @@ func (t BundlePolicy) String() string { } } -// UnmarshalJSON parses the JSON-encoded data and stores the result +// UnmarshalJSON parses the JSON-encoded data and stores the result. func (t *BundlePolicy) UnmarshalJSON(b []byte) error { var val string if err := json.Unmarshal(b, &val); err != nil { @@ -72,10 +75,11 @@ func (t *BundlePolicy) UnmarshalJSON(b []byte) error { } *t = newBundlePolicy(val) + return nil } -// MarshalJSON returns the JSON encoding +// MarshalJSON returns the JSON encoding. func (t BundlePolicy) MarshalJSON() ([]byte, error) { return json.Marshal(t.String()) } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/certificate.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/certificate.go similarity index 72% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/certificate.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/certificate.go index 1d5631bc4..c63d1d851 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/certificate.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/certificate.go @@ -1,9 +1,6 @@ // SPDX-FileCopyrightText: 2023 The Pion community // SPDX-License-Identifier: MIT -//go:build !js -// +build !js - package webrtc import ( @@ -20,8 +17,8 @@ import ( "strings" "time" - "github.com/pion/dtls/v2/pkg/crypto/fingerprint" - "github.com/pion/webrtc/v3/pkg/rtcerr" + "github.com/pion/dtls/v3/pkg/crypto/fingerprint" + "github.com/pion/webrtc/v4/pkg/rtcerr" ) // Certificate represents a x509Cert used to authenticate WebRTC communications. @@ -62,28 +59,36 @@ func NewCertificate(key crypto.PrivateKey, tpl x509.Certificate) (*Certificate, return nil, &rtcerr.UnknownError{Err: err} } - return &Certificate{privateKey: key, x509Cert: cert, statsID: fmt.Sprintf("certificate-%d", time.Now().UnixNano())}, nil + return &Certificate{ + privateKey: key, + x509Cert: cert, + statsID: fmt.Sprintf("certificate-%d", time.Now().UnixNano()), + }, nil } // Equals determines if two certificates are identical by comparing both the // secretKeys and x509Certificates. -func (c Certificate) Equals(o Certificate) bool { +func (c Certificate) Equals(cert Certificate) bool { switch cSK := c.privateKey.(type) { case *rsa.PrivateKey: - if oSK, ok := o.privateKey.(*rsa.PrivateKey); ok { + if oSK, ok := cert.privateKey.(*rsa.PrivateKey); ok { if cSK.N.Cmp(oSK.N) != 0 { return false } - return c.x509Cert.Equal(o.x509Cert) + + return c.x509Cert.Equal(cert.x509Cert) } + return false case *ecdsa.PrivateKey: - if oSK, ok := o.privateKey.(*ecdsa.PrivateKey); ok { + if oSK, ok := cert.privateKey.(*ecdsa.PrivateKey); ok { if cSK.X.Cmp(oSK.X) != 0 || cSK.Y.Cmp(oSK.Y) != 0 { return false } - return c.x509Cert.Equal(o.x509Cert) + + return c.x509Cert.Equal(cert.x509Cert) } + return false default: return false @@ -95,6 +100,7 @@ func (c Certificate) Expires() time.Time { if c.x509Cert == nil { return time.Time{} } + return c.x509Cert.NotAfter } @@ -150,7 +156,7 @@ func GenerateCertificate(secretKey crypto.PrivateKey) (*Certificate, error) { // CertificateFromX509 creates a new WebRTC Certificate from a given PrivateKey and Certificate // -// This can be used if you want to share a certificate across multiple PeerConnections +// This can be used if you want to share a certificate across multiple PeerConnections. func CertificateFromX509(privateKey crypto.PrivateKey, certificate *x509.Certificate) Certificate { return Certificate{privateKey, certificate, fmt.Sprintf("certificate-%d", time.Now().UnixNano())} } @@ -176,48 +182,72 @@ func (c Certificate) collectStats(report *statsReportCollector) error { } report.Collect(stats.ID, stats) + return nil } // CertificateFromPEM creates a fresh certificate based on a string containing -// pem blocks fort the private key and x509 certificate -func CertificateFromPEM(pems string) (*Certificate, error) { - // decode & parse the certificate - block, more := pem.Decode([]byte(pems)) - if block == nil || block.Type != "CERTIFICATE" { - return nil, errCertificatePEMFormatError +// pem blocks fort the private key and x509 certificate. +func CertificateFromPEM(pems string) (*Certificate, error) { //nolint: cyclop + var cert *x509.Certificate + var privateKey crypto.PrivateKey + + var block *pem.Block + more := []byte(pems) + for { + var err error + block, more = pem.Decode(more) + if block == nil { + break + } + + // decode & parse the certificate + switch block.Type { + case "CERTIFICATE": + if cert != nil { + return nil, errCertificatePEMMultipleCert + } + cert, err = x509.ParseCertificate(block.Bytes) + // If parsing failed using block.Bytes, then parse the bytes as base64 and try again + if err != nil { + var n int + certBytes := make([]byte, base64.StdEncoding.DecodedLen(len(block.Bytes))) + n, err = base64.StdEncoding.Decode(certBytes, block.Bytes) + if err == nil { + cert, err = x509.ParseCertificate(certBytes[:n]) + } + } + case "PRIVATE KEY": + if privateKey != nil { + return nil, errCertificatePEMMultiplePriv + } + privateKey, err = x509.ParsePKCS8PrivateKey(block.Bytes) + } + + // Report errors from parsing either the private key or the certificate + if err != nil { + return nil, fmt.Errorf("failed to decode %s: %w", block.Type, err) + } } - certBytes := make([]byte, base64.StdEncoding.DecodedLen(len(block.Bytes))) - n, err := base64.StdEncoding.Decode(certBytes, block.Bytes) - if err != nil { - return nil, fmt.Errorf("failed to decode ceritifcate: %w", err) + + if cert == nil || privateKey == nil { + return nil, errCertificatePEMMissing } - cert, err := x509.ParseCertificate(certBytes[:n]) - if err != nil { - return nil, fmt.Errorf("failed parsing ceritifcate: %w", err) - } - // decode & parse the private key - block, _ = pem.Decode(more) - if block == nil || block.Type != "PRIVATE KEY" { - return nil, errCertificatePEMFormatError - } - privateKey, err := x509.ParsePKCS8PrivateKey(block.Bytes) - if err != nil { - return nil, fmt.Errorf("unable to parse private key: %w", err) - } - x := CertificateFromX509(privateKey, cert) - return &x, nil + + ret := CertificateFromX509(privateKey, cert) + + return &ret, nil } // PEM returns the certificate encoded as two pem block: once for the X509 -// certificate and the other for the private key +// certificate and the other for the private key. func (c Certificate) PEM() (string, error) { // First write the X509 certificate - var o strings.Builder + var builder strings.Builder xcertBytes := make( []byte, base64.StdEncoding.EncodedLen(len(c.x509Cert.Raw))) base64.StdEncoding.Encode(xcertBytes, c.x509Cert.Raw) - err := pem.Encode(&o, &pem.Block{Type: "CERTIFICATE", Bytes: xcertBytes}) + err := pem.Encode(&builder, &pem.Block{Type: "CERTIFICATE", Bytes: xcertBytes}) if err != nil { return "", fmt.Errorf("failed to pem encode the X certificate: %w", err) } @@ -226,9 +256,10 @@ func (c Certificate) PEM() (string, error) { if err != nil { return "", fmt.Errorf("failed to marshal private key: %w", err) } - err = pem.Encode(&o, &pem.Block{Type: "PRIVATE KEY", Bytes: privBytes}) + err = pem.Encode(&builder, &pem.Block{Type: "PRIVATE KEY", Bytes: privBytes}) if err != nil { return "", fmt.Errorf("failed to encode private key: %w", err) } - return o.String(), nil + + return builder.String(), nil } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/codecov.yml b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/codecov.yml new file mode 100644 index 000000000..263e4d45c --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/codecov.yml @@ -0,0 +1,22 @@ +# +# DO NOT EDIT THIS FILE +# +# It is automatically copied from https://github.com/pion/.goassets repository. +# +# SPDX-FileCopyrightText: 2023 The Pion community +# SPDX-License-Identifier: MIT + +coverage: + status: + project: + default: + # Allow decreasing 2% of total coverage to avoid noise. + threshold: 2% + patch: + default: + target: 70% + only_pulls: true + +ignore: + - "examples/*" + - "examples/**/*" diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/configuration.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/configuration.go similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/configuration.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/configuration.go diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/configuration_common.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/configuration_common.go similarity index 99% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/configuration_common.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/configuration_common.go index a3acdf5b8..4fb22fb85 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/configuration_common.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/configuration_common.go @@ -23,5 +23,6 @@ func (c Configuration) getICEServers() []ICEServer { iceServers[iceServersIndex].URLs[urlsIndex] = rawURL } } + return iceServers } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/configuration_js.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/configuration_js.go similarity index 95% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/configuration_js.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/configuration_js.go index 097085f9b..2af5afccd 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/configuration_js.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/configuration_js.go @@ -36,4 +36,6 @@ type Configuration struct { // ICECandidatePoolSize describes the size of the prefetched ICE pool. ICECandidatePoolSize uint8 + + Certificates []Certificate `json:"certificates,omitempty"` } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/constants.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/constants.go new file mode 100644 index 000000000..e1a74ef9d --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/constants.go @@ -0,0 +1,66 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + +package webrtc + +import ( + "math" + + "github.com/pion/dtls/v3" +) + +const ( + // default as the standard ethernet MTU + // can be overwritten with SettingEngine.SetReceiveMTU(). + receiveMTU = 1500 + + // simulcastProbeCount is the amount of RTP Packets + // that handleUndeclaredSSRC will read and try to dispatch from + // mid and rid values. + simulcastProbeCount = 10 + + // simulcastMaxProbeRoutines is how many active routines can be used to probe + // If the total amount of incoming SSRCes exceeds this new requests will be ignored. + simulcastMaxProbeRoutines = 25 + + // Default Max SCTP Message Size is the largest single DataChannel + // message we can send or accept. This default was chosen to match FireFox. + defaultMaxSCTPMessageSize = 1073741823 + + // If a DataChannel Max Message Size isn't declared by the Remote(max-message-size) + // this is the value we default to. This value was chosen because it was the behavior + // of Pion before max-message-size was implemented. + sctpMaxMessageSizeUnsetValue = math.MaxUint16 + + mediaSectionApplication = "application" + + sdpAttributeRid = "rid" + + sdpAttributeSimulcast = "simulcast" + + outboundMTU = 1200 + + rtpPayloadTypeBitmask = 0x7F + + incomingUnhandledRTPSsrc = "Incoming unhandled RTP ssrc(%d), OnTrack will not be fired. %v" + + generatedCertificateOrigin = "WebRTC" + + // AttributeRtxPayloadType is the interceptor attribute added when Read() + // returns an RTX packet containing the RTX stream payload type. + AttributeRtxPayloadType = "rtx_payload_type" + // AttributeRtxSsrc is the interceptor attribute added when Read() + // returns an RTX packet containing the RTX stream SSRC. + AttributeRtxSsrc = "rtx_ssrc" + // AttributeRtxSequenceNumber is the interceptor attribute added when + // Read() returns an RTX packet containing the RTX stream sequence number. + AttributeRtxSequenceNumber = "rtx_sequence_number" +) + +func defaultSrtpProtectionProfiles() []dtls.SRTPProtectionProfile { + return []dtls.SRTPProtectionProfile{ + dtls.SRTP_AEAD_AES_256_GCM, + dtls.SRTP_AEAD_AES_128_GCM, + dtls.SRTP_AES128_CM_HMAC_SHA1_80, + } +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/datachannel.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/datachannel.go similarity index 77% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/datachannel.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/datachannel.go index 9c9154c8c..c8cf50da5 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/datachannel.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/datachannel.go @@ -10,22 +10,20 @@ import ( "errors" "fmt" "io" - "math" "sync" "sync/atomic" "time" "github.com/pion/datachannel" "github.com/pion/logging" - "github.com/pion/webrtc/v3/pkg/rtcerr" + "github.com/pion/webrtc/v4/pkg/rtcerr" ) -const dataChannelBufferSize = math.MaxUint16 // message size limit for Chromium var errSCTPNotEstablished = errors.New("SCTP not established") // DataChannel represents a WebRTC DataChannel // The DataChannel interface represents a network channel -// which can be used for bidirectional peer-to-peer transfers of arbitrary data +// which can be used for bidirectional peer-to-peer transfers of arbitrary data. type DataChannel struct { mu sync.RWMutex @@ -40,6 +38,8 @@ type DataChannel struct { readyState atomic.Value // DataChannelState bufferedAmountLowThreshold uint64 detachCalled bool + readLoopActive chan struct{} + isGracefulClosed bool // The binaryType represents attribute MUST, on getting, return the value to // which it was last set. On setting, if the new value is either the string @@ -85,13 +85,17 @@ func (api *API) NewDataChannel(transport *SCTPTransport, params *DataChannelPara // newDataChannel is an internal constructor for the data channel used to // create the DataChannel object before the networking is set up. -func (api *API) newDataChannel(params *DataChannelParameters, sctpTransport *SCTPTransport, log logging.LeveledLogger) (*DataChannel, error) { +func (api *API) newDataChannel( + params *DataChannelParameters, + sctpTransport *SCTPTransport, + log logging.LeveledLogger, +) (*DataChannel, error) { // https://w3c.github.io/webrtc-pc/#peer-to-peer-data-api (Step #5) if len(params.Label) > 65535 { return nil, &rtcerr.TypeError{Err: ErrStringSizeLimit} } - d := &DataChannel{ + dataChannel := &DataChannel{ sctpTransport: sctpTransport, statsID: fmt.Sprintf("DataChannel-%d", time.Now().UnixNano()), label: params.Label, @@ -105,12 +109,13 @@ func (api *API) newDataChannel(params *DataChannelParameters, sctpTransport *SCT log: log, } - d.setReadyState(DataChannelStateConnecting) - return d, nil + dataChannel.setReadyState(DataChannelStateConnecting) + + return dataChannel, nil } -// open opens the datachannel over the sctp transport -func (d *DataChannel) open(sctpTransport *SCTPTransport) error { +// open opens the datachannel over the sctp transport. +func (d *DataChannel) open(sctpTransport *SCTPTransport) error { //nolint:cyclop association := sctpTransport.association() if association == nil { return errSCTPNotEstablished @@ -119,6 +124,7 @@ func (d *DataChannel) open(sctpTransport *SCTPTransport) error { d.mu.Lock() if d.sctpTransport != nil { // already open d.mu.Unlock() + return nil } d.sctpTransport = sctpTransport @@ -173,6 +179,7 @@ func (d *DataChannel) open(sctpTransport *SCTPTransport) error { dc, err := datachannel.Dial(association, *d.id, cfg) if err != nil { d.mu.Unlock() + return err } @@ -183,6 +190,7 @@ func (d *DataChannel) open(sctpTransport *SCTPTransport) error { d.onDial() d.handleOpen(dc, false, d.negotiated) + return nil } @@ -195,7 +203,7 @@ func (d *DataChannel) Transport() *SCTPTransport { } // After onOpen is complete check that the user called detach -// and provide an error message if the call was missed +// and provide an error message if the call was missed. func (d *DataChannel) checkDetachAfterOpen() { d.mu.RLock() defer d.mu.RUnlock() @@ -225,6 +233,11 @@ func (d *DataChannel) OnOpen(f func()) { func (d *DataChannel) onOpen() { d.mu.RLock() handler := d.onOpenHandler + if d.isGracefulClosed { + d.mu.RUnlock() + + return + } d.mu.RUnlock() if handler != nil { @@ -236,7 +249,7 @@ func (d *DataChannel) onOpen() { } // OnDial sets an event handler which is invoked when the -// peer has been dialed, but before said peer has responsed +// peer has been dialed, but before said peer has responded. func (d *DataChannel) OnDial(f func()) { d.mu.Lock() d.dialHandlerOnce = sync.Once{} @@ -252,6 +265,11 @@ func (d *DataChannel) OnDial(f func()) { func (d *DataChannel) onDial() { d.mu.RLock() handler := d.onDialHandler + if d.isGracefulClosed { + d.mu.RUnlock() + + return + } d.mu.RUnlock() if handler != nil { @@ -261,6 +279,10 @@ func (d *DataChannel) onDial() { // OnClose sets an event handler which is invoked when // the underlying data transport has been closed. +// Note: Due to backwards compatibility, there is a chance that +// OnClose can be called, even if the GracefulClose is used. +// If this is the case for you, you can deregister OnClose +// prior to GracefulClose. func (d *DataChannel) OnClose(f func()) { d.mu.Lock() defer d.mu.Unlock() @@ -292,6 +314,11 @@ func (d *DataChannel) OnMessage(f func(msg DataChannelMessage)) { func (d *DataChannel) onMessage(msg DataChannelMessage) { d.mu.RLock() handler := d.onMessageHandler + if d.isGracefulClosed { + d.mu.RUnlock() + + return + } d.mu.RUnlock() if handler == nil { @@ -302,7 +329,18 @@ func (d *DataChannel) onMessage(msg DataChannelMessage) { func (d *DataChannel) handleOpen(dc *datachannel.DataChannel, isRemote, isAlreadyNegotiated bool) { d.mu.Lock() + if d.isGracefulClosed { // The channel was closed during the connecting state + d.mu.Unlock() + if err := dc.Close(); err != nil { + d.log.Errorf("Failed to close DataChannel that was closed during connecting state %v", err.Error()) + } + d.onClose() + + return + } d.dataChannel = dc + bufferedAmountLowThreshold := d.bufferedAmountLowThreshold + onBufferedAmountLow := d.onBufferedAmountLow d.mu.Unlock() d.setReadyState(DataChannelStateOpen) @@ -312,8 +350,8 @@ func (d *DataChannel) handleOpen(dc *datachannel.DataChannel, isRemote, isAlread // * already negotiated datachannels should fire OnOpened if d.api.settingEngine.detach.DataChannels || isRemote || isAlreadyNegotiated { // bufferedAmountLowThreshold and onBufferedAmountLow might be set earlier - d.dataChannel.SetBufferedAmountLowThreshold(d.bufferedAmountLowThreshold) - d.dataChannel.OnBufferedAmountLow(d.onBufferedAmountLow) + d.dataChannel.SetBufferedAmountLowThreshold(bufferedAmountLowThreshold) + d.dataChannel.OnBufferedAmountLow(onBufferedAmountLow) d.onOpen() } else { dc.OnOpen(func() { @@ -324,7 +362,12 @@ func (d *DataChannel) handleOpen(dc *datachannel.DataChannel, isRemote, isAlread d.mu.Lock() defer d.mu.Unlock() + if d.isGracefulClosed { + return + } + if !d.api.settingEngine.detach.DataChannels { + d.readLoopActive = make(chan struct{}) go d.readLoop() } } @@ -340,6 +383,11 @@ func (d *DataChannel) OnError(f func(err error)) { func (d *DataChannel) onError(err error) { d.mu.RLock() handler := d.onErrorHandler + if d.isGracefulClosed { + d.mu.RUnlock() + + return + } d.mu.RUnlock() if handler != nil { @@ -347,37 +395,48 @@ func (d *DataChannel) onError(err error) { } } -// See https://github.com/pion/webrtc/issues/1516 -// nolint:gochecknoglobals -var rlBufPool = sync.Pool{New: func() interface{} { - return make([]byte, dataChannelBufferSize) -}} - func (d *DataChannel) readLoop() { + defer func() { + d.mu.Lock() + readLoopActive := d.readLoopActive + d.mu.Unlock() + defer close(readLoopActive) + }() + + buffer := make([]byte, sctpMaxMessageSizeUnsetValue) for { - buffer := rlBufPool.Get().([]byte) //nolint:forcetypeassert n, isString, err := d.dataChannel.ReadDataChannel(buffer) if err != nil { - rlBufPool.Put(buffer) // nolint:staticcheck + if errors.Is(err, io.ErrShortBuffer) { + if int64(n) < int64(d.api.settingEngine.getSCTPMaxMessageSize()) { + buffer = append(buffer, make([]byte, len(buffer))...) // nolint + + continue + } + + d.log.Errorf( + "Incoming DataChannel message larger then Max Message size %v", + d.api.settingEngine.getSCTPMaxMessageSize(), + ) + } + d.setReadyState(DataChannelStateClosed) if !errors.Is(err, io.EOF) { d.onError(err) } d.onClose() + return } - m := DataChannelMessage{Data: make([]byte, n), IsString: isString} - copy(m.Data, buffer[:n]) - // The 'staticcheck' pragma is a false positive on the part of the CI linter. - rlBufPool.Put(buffer) // nolint:staticcheck - - // NB: Why was DataChannelMessage not passed as a pointer value? - d.onMessage(m) // nolint:staticcheck + d.onMessage(DataChannelMessage{ + Data: append([]byte{}, buffer[:n]...), + IsString: isString, + }) } } -// Send sends the binary message to the DataChannel peer +// Send sends the binary message to the DataChannel peer. func (d *DataChannel) Send(data []byte) error { err := d.ensureOpen() if err != nil { @@ -385,10 +444,11 @@ func (d *DataChannel) Send(data []byte) error { } _, err = d.dataChannel.WriteDataChannel(data, false) + return err } -// SendText sends the text message to the DataChannel peer +// SendText sends the text message to the DataChannel peer. func (d *DataChannel) SendText(s string) error { err := d.ensureOpen() if err != nil { @@ -396,6 +456,7 @@ func (d *DataChannel) SendText(s string) error { } _, err = d.dataChannel.WriteDataChannel([]byte(s), true) + return err } @@ -405,11 +466,15 @@ func (d *DataChannel) ensureOpen() error { if d.ReadyState() != DataChannelStateOpen { return io.ErrClosedPipe } + return nil } -// Detach allows you to detach the underlying datachannel. This provides -// an idiomatic API to work with, however it disables the OnMessage callback. +// Detach allows you to detach the underlying datachannel. +// This provides an idiomatic API to work with +// (`io.ReadWriteCloser` with its `.Read()` and `.Write()` methods, +// as opposed to `.Send()` and `.OnMessage`), +// however it disables the OnMessage callback. // Before calling Detach you have to enable this behavior by calling // webrtc.DetachDataChannels(). Combining detached and normal data channels // is not supported. @@ -417,26 +482,81 @@ func (d *DataChannel) ensureOpen() error { // pion/datachannel documentation for the correct way to handle the // resulting DataChannel object. func (d *DataChannel) Detach() (datachannel.ReadWriteCloser, error) { + return d.DetachWithDeadline() +} + +// DetachWithDeadline allows you to detach the underlying datachannel. +// It is the same as Detach but returns a ReadWriteCloserDeadliner. +func (d *DataChannel) DetachWithDeadline() (datachannel.ReadWriteCloserDeadliner, error) { d.mu.Lock() - defer d.mu.Unlock() if !d.api.settingEngine.detach.DataChannels { + d.mu.Unlock() + return nil, errDetachNotEnabled } if d.dataChannel == nil { + d.mu.Unlock() + return nil, errDetachBeforeOpened } d.detachCalled = true - return d.dataChannel, nil + dataChannel := d.dataChannel + d.mu.Unlock() + + // Remove the reference from SCTPTransport so that the datachannel + // can be garbage collected on close + d.sctpTransport.lock.Lock() + n := len(d.sctpTransport.dataChannels) + j := 0 + for i := 0; i < n; i++ { + if d == d.sctpTransport.dataChannels[i] { + continue + } + d.sctpTransport.dataChannels[j] = d.sctpTransport.dataChannels[i] + j++ + } + for i := j; i < n; i++ { + d.sctpTransport.dataChannels[i] = nil + } + d.sctpTransport.dataChannels = d.sctpTransport.dataChannels[:j] + d.sctpTransport.lock.Unlock() + + return dataChannel, nil } // Close Closes the DataChannel. It may be called regardless of whether // the DataChannel object was created by this peer or the remote peer. func (d *DataChannel) Close() error { + return d.close(false) +} + +// GracefulClose Closes the DataChannel. It may be called regardless of whether +// the DataChannel object was created by this peer or the remote peer. It also waits +// for any goroutines it started to complete. This is only safe to call outside of +// DataChannel callbacks or if in a callback, in its own goroutine. +func (d *DataChannel) GracefulClose() error { + return d.close(true) +} + +// Normally, close only stops writes from happening, so graceful=true +// will wait for reads to be finished based on underlying SCTP association +// closure or a SCTP reset stream from the other side. This is safe to call +// with graceful=true after tearing down a PeerConnection but not +// necessarily before. For example, if you used a vnet and dropped all packets +// right before closing the DataChannel, you'd need never see a reset stream. +func (d *DataChannel) close(shouldGracefullyClose bool) error { d.mu.Lock() + d.isGracefulClosed = true + readLoopActive := d.readLoopActive + if shouldGracefullyClose && readLoopActive != nil { + defer func() { + <-readLoopActive + }() + } haveSctpTransport := d.dataChannel != nil d.mu.Unlock() @@ -525,6 +645,7 @@ func (d *DataChannel) ReadyState() DataChannelState { if v, ok := d.readyState.Load().(DataChannelState); ok { return v } + return DataChannelState(0) } @@ -545,6 +666,7 @@ func (d *DataChannel) BufferedAmount() uint64 { if d.dataChannel == nil { return 0 } + return d.dataChannel.BufferedAmount() } @@ -561,6 +683,7 @@ func (d *DataChannel) BufferedAmountLowThreshold() uint64 { if d.dataChannel == nil { return d.bufferedAmountLowThreshold } + return d.dataChannel.BufferedAmountLowThreshold() } @@ -578,7 +701,7 @@ func (d *DataChannel) SetBufferedAmountLowThreshold(th uint64) { } // OnBufferedAmountLow sets an event handler which is invoked when -// the number of bytes of outgoing data becomes lower than the +// the number of bytes of outgoing data becomes lower than or equal to the // BufferedAmountLowThreshold. func (d *DataChannel) OnBufferedAmountLow(f func()) { d.mu.Lock() @@ -593,6 +716,7 @@ func (d *DataChannel) OnBufferedAmountLow(f func()) { func (d *DataChannel) getStatsID() string { d.mu.Lock() defer d.mu.Unlock() + return d.statsID } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/datachannel_js.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/datachannel_js.go similarity index 87% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/datachannel_js.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/datachannel_js.go index a34ab6efd..add07b697 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/datachannel_js.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/datachannel_js.go @@ -7,6 +7,7 @@ package webrtc import ( + "errors" "fmt" "syscall/js" @@ -26,13 +27,20 @@ type DataChannel struct { // syscall/js API. Initially nil. onOpenHandler *js.Func onCloseHandler *js.Func + onClosingHandler *js.Func onMessageHandler *js.Func onBufferedAmountLow *js.Func + onErrorHandler *js.Func // A reference to the associated api object used by this datachannel api *API } +// JSValue returns the underlying RTCDataChannel +func (d *DataChannel) JSValue() js.Value { + return d.underlying +} + // OnOpen sets an event handler which is invoked when // the underlying data transport has been established (or re-established). func (d *DataChannel) OnOpen(f func()) { @@ -63,6 +71,39 @@ func (d *DataChannel) OnClose(f func()) { d.underlying.Set("onclose", onCloseHandler) } +// FYI `OnClosing` is not implemented in the non-JS version of Pion. + +func (d *DataChannel) OnClosing(f func()) { + if d.onClosingHandler != nil { + oldHandler := d.onClosingHandler + defer oldHandler.Release() + } + onClosingHandler := js.FuncOf(func(this js.Value, args []js.Value) interface{} { + go f() + return js.Undefined() + }) + d.onClosingHandler = &onClosingHandler + d.underlying.Set("onclosing", onClosingHandler) +} + +func (d *DataChannel) OnError(f func(err error)) { + if d.onErrorHandler != nil { + oldHandler := d.onErrorHandler + defer oldHandler.Release() + } + onErrorHandler := js.FuncOf(func(this js.Value, args []js.Value) interface{} { + event := args[0] + errorObj := event.Get("error") + // FYI RTCError has some extra properties, e.g. `errorDetail`: + // https://developer.mozilla.org/en-US/docs/Web/API/RTCDataChannel/error_event + errorMessage := errorObj.Get("message").String() + go f(errors.New(errorMessage)) + return js.Undefined() + }) + d.onErrorHandler = &onErrorHandler + d.underlying.Set("onerror", onErrorHandler) +} + // OnMessage sets an event handler which is invoked on a binary message arrival // from a remote peer. Note that browsers may place limitations on message size. func (d *DataChannel) OnMessage(f func(msg DataChannelMessage)) { @@ -115,7 +156,7 @@ func (d *DataChannel) SendText(s string) (err error) { // Before calling Detach you have to enable this behavior by calling // webrtc.DetachDataChannels(). Combining detached and normal data channels // is not supported. -// Please reffer to the data-channels-detach example and the +// Please refer to the data-channels-detach example and the // pion/datachannel documentation for the correct way to handle the // resulting DataChannel object. func (d *DataChannel) Detach() (datachannel.ReadWriteCloser, error) { @@ -145,12 +186,18 @@ func (d *DataChannel) Close() (err error) { if d.onCloseHandler != nil { d.onCloseHandler.Release() } + if d.onClosingHandler != nil { + d.onClosingHandler.Release() + } if d.onMessageHandler != nil { d.onMessageHandler.Release() } if d.onBufferedAmountLow != nil { d.onBufferedAmountLow.Release() } + if d.onErrorHandler != nil { + d.onErrorHandler.Release() + } return nil } @@ -246,7 +293,7 @@ func (d *DataChannel) SetBufferedAmountLowThreshold(th uint64) { } // OnBufferedAmountLow sets an event handler which is invoked when -// the number of bytes of outgoing data becomes lower than the +// the number of bytes of outgoing data becomes lower than or equal to the // BufferedAmountLowThreshold. func (d *DataChannel) OnBufferedAmountLow(f func()) { if d.onBufferedAmountLow != nil { diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/datachannel_js_detach.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/datachannel_js_detach.go similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/datachannel_js_detach.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/datachannel_js_detach.go diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/datachannelinit.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/datachannelinit.go similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/datachannelinit.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/datachannelinit.go diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/datachannelmessage.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/datachannelmessage.go similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/datachannelmessage.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/datachannelmessage.go diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/datachannelparameters.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/datachannelparameters.go similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/datachannelparameters.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/datachannelparameters.go diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/datachannelstate.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/datachannelstate.go similarity index 79% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/datachannelstate.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/datachannelstate.go index b2a85aaeb..ad275c5db 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/datachannelstate.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/datachannelstate.go @@ -7,10 +7,13 @@ package webrtc type DataChannelState int const ( + // DataChannelStateUnknown is the enum's zero-value. + DataChannelStateUnknown DataChannelState = iota + // DataChannelStateConnecting indicates that the data channel is being // established. This is the initial state of DataChannel, whether created // with CreateDataChannel, or dispatched as a part of an DataChannelEvent. - DataChannelStateConnecting DataChannelState = iota + 1 + DataChannelStateConnecting // DataChannelStateOpen indicates that the underlying data transport is // established and communication is possible. @@ -44,7 +47,7 @@ func newDataChannelState(raw string) DataChannelState { case dataChannelStateClosedStr: return DataChannelStateClosed default: - return DataChannelState(Unknown) + return DataChannelStateUnknown } } @@ -62,3 +65,15 @@ func (t DataChannelState) String() string { return ErrUnknownType.Error() } } + +// MarshalText implements encoding.TextMarshaler. +func (t DataChannelState) MarshalText() ([]byte, error) { + return []byte(t.String()), nil +} + +// UnmarshalText implements encoding.TextUnmarshaler. +func (t *DataChannelState) UnmarshalText(b []byte) error { + *t = newDataChannelState(string(b)) + + return nil +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/dtlsfingerprint.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/dtlsfingerprint.go similarity index 88% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/dtlsfingerprint.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/dtlsfingerprint.go index b0d061481..b1bf773bc 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/dtlsfingerprint.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/dtlsfingerprint.go @@ -6,7 +6,7 @@ package webrtc // DTLSFingerprint specifies the hash function algorithm and certificate // fingerprint as described in https://tools.ietf.org/html/rfc4572. type DTLSFingerprint struct { - // Algorithm specifies one of the the hash function algorithms defined in + // Algorithm specifies one of the hash function algorithms defined in // the 'Hash function Textual Names' registry. Algorithm string `json:"algorithm"` diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/dtlsparameters.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/dtlsparameters.go similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/dtlsparameters.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/dtlsparameters.go diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/dtlsrole.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/dtlsrole.go similarity index 93% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/dtlsrole.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/dtlsrole.go index 9cee581d9..94cbac961 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/dtlsrole.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/dtlsrole.go @@ -11,10 +11,13 @@ import ( type DTLSRole byte const ( + // DTLSRoleUnknown is the enum's zero-value. + DTLSRoleUnknown DTLSRole = iota + // DTLSRoleAuto defines the DTLS role is determined based on // the resolved ICE role: the ICE controlled role acts as the DTLS // client and the ICE controlling role acts as the DTLS server. - DTLSRoleAuto DTLSRole = iota + 1 + DTLSRoleAuto // DTLSRoleClient defines the DTLS client role. DTLSRoleClient @@ -51,13 +54,13 @@ func (r DTLSRole) String() string { case DTLSRoleServer: return "server" default: - return unknownStr + return ErrUnknownType.Error() } } // Iterate a SessionDescription from a remote to determine if an explicit // role can been determined from it. The decision is made from the first role we we parse. -// If no role can be found we return DTLSRoleAuto +// If no role can be found we return DTLSRoleAuto. func dtlsRoleFromRemoteSDP(sessionDescription *sdp.SessionDescription) DTLSRole { if sessionDescription == nil { return DTLSRoleAuto diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/dtlstransport.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/dtlstransport.go similarity index 79% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/dtlstransport.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/dtlstransport.go index df3472cf2..e0b575a11 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/dtlstransport.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/dtlstransport.go @@ -19,15 +19,15 @@ import ( "sync/atomic" "time" - "github.com/pion/dtls/v2" - "github.com/pion/dtls/v2/pkg/crypto/fingerprint" + "github.com/pion/dtls/v3" + "github.com/pion/dtls/v3/pkg/crypto/fingerprint" "github.com/pion/interceptor" "github.com/pion/logging" "github.com/pion/rtcp" - "github.com/pion/srtp/v2" - "github.com/pion/webrtc/v3/internal/mux" - "github.com/pion/webrtc/v3/internal/util" - "github.com/pion/webrtc/v3/pkg/rtcerr" + "github.com/pion/srtp/v3" + "github.com/pion/webrtc/v4/internal/mux" + "github.com/pion/webrtc/v4/internal/util" + "github.com/pion/webrtc/v4/pkg/rtcerr" ) // DTLSTransport allows an application access to information about the DTLS @@ -44,13 +44,14 @@ type DTLSTransport struct { state DTLSTransportState srtpProtectionProfile srtp.ProtectionProfile - onStateChangeHandler func(DTLSTransportState) + onStateChangeHandler func(DTLSTransportState) + internalOnCloseHandler func() conn *dtls.Conn srtpSession, srtcpSession atomic.Value srtpEndpoint, srtcpEndpoint *mux.Endpoint - simulcastStreams []*srtp.ReadStreamSRTP + simulcastStreams []simulcastStreamPair srtpReady chan struct{} dtlsMatcher mux.MatchFunc @@ -59,11 +60,16 @@ type DTLSTransport struct { log logging.LeveledLogger } +type simulcastStreamPair struct { + srtp *srtp.ReadStreamSRTP + srtcp *srtp.ReadStreamSRTCP +} + // NewDTLSTransport creates a new DTLSTransport. // This constructor is part of the ORTC API. It is not // meant to be used together with the basic WebRTC API. func (api *API) NewDTLSTransport(transport *ICETransport, certificates []Certificate) (*DTLSTransport, error) { - t := &DTLSTransport{ + trans := &DTLSTransport{ iceTransport: transport, api: api, state: DTLSTransportStateNew, @@ -78,7 +84,7 @@ func (api *API) NewDTLSTransport(transport *ICETransport, certificates []Certifi if !x509Cert.Expires().IsZero() && now.After(x509Cert.Expires()) { return nil, &rtcerr.InvalidAccessError{Err: ErrCertificateExpired} } - t.certificates = append(t.certificates, x509Cert) + trans.certificates = append(trans.certificates, x509Cert) } } else { sk, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) @@ -89,21 +95,22 @@ func (api *API) NewDTLSTransport(transport *ICETransport, certificates []Certifi if err != nil { return nil, err } - t.certificates = []Certificate{*certificate} + trans.certificates = []Certificate{*certificate} } - return t, nil + return trans, nil } // ICETransport returns the currently-configured *ICETransport or nil -// if one has not been configured +// if one has not been configured. func (t *DTLSTransport) ICETransport() *ICETransport { t.lock.RLock() defer t.lock.RUnlock() + return t.iceTransport } -// onStateChange requires the caller holds the lock +// onStateChange requires the caller holds the lock. func (t *DTLSTransport) onStateChange(state DTLSTransportState) { t.state = state handler := t.onStateChangeHandler @@ -124,6 +131,7 @@ func (t *DTLSTransport) OnStateChange(f func(DTLSTransportState)) { func (t *DTLSTransport) State() DTLSTransportState { t.lock.RLock() defer t.lock.RUnlock() + return t.state } @@ -169,10 +177,11 @@ func (t *DTLSTransport) GetLocalParameters() (DTLSParameters, error) { } // GetRemoteCertificate returns the certificate chain in use by the remote side -// returns an empty list prior to selection of the remote certificate +// returns an empty list prior to selection of the remote certificate. func (t *DTLSTransport) GetRemoteCertificate() []byte { t.lock.RLock() defer t.lock.RUnlock() + return t.remoteCertificate } @@ -210,7 +219,12 @@ func (t *DTLSTransport) startSRTP() error { ) } - connState := t.conn.ConnectionState() + connState, ok := t.conn.ConnectionState() + if !ok { + // nolint + return fmt.Errorf("%w: Failed to get DTLS ConnectionState", errDtlsKeyExtractionFailed) + } + err := srtpConfig.ExtractSessionKeysFromDTLS(&connState, t.role() == DTLSRoleClient) if err != nil { // nolint @@ -232,6 +246,7 @@ func (t *DTLSTransport) startSRTP() error { t.srtpSession.Store(srtpSession) t.srtcpSession.Store(srtcpSession) close(t.srtpReady) + return nil } @@ -274,11 +289,12 @@ func (t *DTLSTransport) role() DTLSRole { if t.iceTransport.Role() == ICERoleControlling { return DTLSRoleServer } + return defaultDtlsRoleAnswer } -// Start DTLS transport negotiation with the parameters of the remote DTLS transport -func (t *DTLSTransport) Start(remoteParameters DTLSParameters) error { +// Start DTLS transport negotiation with the parameters of the remote DTLS transport. +func (t *DTLSTransport) Start(remoteParameters DTLSParameters) error { //nolint:gocognit,cyclop // Take lock and prepare connection, we must not hold the lock // when connecting prepareTransport := func() (DTLSRole, *dtls.Config, error) { @@ -317,18 +333,20 @@ func (t *DTLSTransport) Start(remoteParameters DTLSParameters) error { ClientAuth: dtls.RequireAnyClientCert, LoggerFactory: t.api.settingEngine.LoggerFactory, InsecureSkipVerify: !t.api.settingEngine.dtls.disableInsecureSkipVerify, + CustomCipherSuites: t.api.settingEngine.dtls.customCipherSuites, }, nil } var dtlsConn *dtls.Conn dtlsEndpoint := t.iceTransport.newEndpoint(mux.MatchDTLS) + dtlsEndpoint.SetOnClose(t.internalOnCloseHandler) role, dtlsConfig, err := prepareTransport() if err != nil { return err } if t.api.settingEngine.replayProtection.DTLS != nil { - dtlsConfig.ReplayProtectionWindow = int(*t.api.settingEngine.replayProtection.DTLS) + dtlsConfig.ReplayProtectionWindow = int(*t.api.settingEngine.replayProtection.DTLS) //nolint:gosec // G115 } if t.api.settingEngine.dtls.clientAuth != nil { @@ -338,17 +356,29 @@ func (t *DTLSTransport) Start(remoteParameters DTLSParameters) error { dtlsConfig.FlightInterval = t.api.settingEngine.dtls.retransmissionInterval dtlsConfig.InsecureSkipVerifyHello = t.api.settingEngine.dtls.insecureSkipHelloVerify dtlsConfig.EllipticCurves = t.api.settingEngine.dtls.ellipticCurves - dtlsConfig.ConnectContextMaker = t.api.settingEngine.dtls.connectContextMaker dtlsConfig.ExtendedMasterSecret = t.api.settingEngine.dtls.extendedMasterSecret dtlsConfig.ClientCAs = t.api.settingEngine.dtls.clientCAs dtlsConfig.RootCAs = t.api.settingEngine.dtls.rootCAs + dtlsConfig.KeyLogWriter = t.api.settingEngine.dtls.keyLogWriter + dtlsConfig.ClientHelloMessageHook = t.api.settingEngine.dtls.clientHelloMessageHook + dtlsConfig.ServerHelloMessageHook = t.api.settingEngine.dtls.serverHelloMessageHook + dtlsConfig.CertificateRequestMessageHook = t.api.settingEngine.dtls.certificateRequestMessageHook // Connect as DTLS Client/Server, function is blocking and we // must not hold the DTLSTransport lock if role == DTLSRoleClient { - dtlsConn, err = dtls.Client(dtlsEndpoint, dtlsConfig) + dtlsConn, err = dtls.Client(dtlsEndpoint, dtlsEndpoint.RemoteAddr(), dtlsConfig) } else { - dtlsConn, err = dtls.Server(dtlsEndpoint, dtlsConfig) + dtlsConn, err = dtls.Server(dtlsEndpoint, dtlsEndpoint.RemoteAddr(), dtlsConfig) + } + + if err == nil { + if t.api.settingEngine.dtls.connectContextMaker != nil { + handshakeCtx, _ := t.api.settingEngine.dtls.connectContextMaker() + err = dtlsConn.HandshakeContext(handshakeCtx) + } else { + err = dtlsConn.Handshake() + } } // Re-take the lock, nothing beyond here is blocking @@ -357,12 +387,14 @@ func (t *DTLSTransport) Start(remoteParameters DTLSParameters) error { if err != nil { t.onStateChange(DTLSTransportStateFailed) + return err } srtpProfile, ok := dtlsConn.SelectedSRTPProtectionProfile() if !ok { t.onStateChange(DTLSTransportStateFailed) + return ErrNoSRTPProtectionProfile } @@ -373,20 +405,30 @@ func (t *DTLSTransport) Start(remoteParameters DTLSParameters) error { t.srtpProtectionProfile = srtp.ProtectionProfileAeadAes256Gcm case dtls.SRTP_AES128_CM_HMAC_SHA1_80: t.srtpProtectionProfile = srtp.ProtectionProfileAes128CmHmacSha1_80 + case dtls.SRTP_NULL_HMAC_SHA1_80: + t.srtpProtectionProfile = srtp.ProtectionProfileNullHmacSha1_80 default: t.onStateChange(DTLSTransportStateFailed) + return ErrNoSRTPProtectionProfile } // Check the fingerprint if a certificate was exchanged - remoteCerts := dtlsConn.ConnectionState().PeerCertificates - if len(remoteCerts) == 0 { + connectionState, ok := dtlsConn.ConnectionState() + if !ok { t.onStateChange(DTLSTransportStateFailed) + return errNoRemoteCertificate } - t.remoteCertificate = remoteCerts[0] - if !t.api.settingEngine.disableCertificateFingerprintVerification { + if len(connectionState.PeerCertificates) == 0 { + t.onStateChange(DTLSTransportStateFailed) + + return errNoRemoteCertificate + } + t.remoteCertificate = connectionState.PeerCertificates[0] + + if !t.api.settingEngine.disableCertificateFingerprintVerification { //nolint:nestif parsedRemoteCert, err := x509.ParseCertificate(t.remoteCertificate) if err != nil { if closeErr := dtlsConn.Close(); closeErr != nil { @@ -394,6 +436,7 @@ func (t *DTLSTransport) Start(remoteParameters DTLSParameters) error { } t.onStateChange(DTLSTransportStateFailed) + return err } @@ -403,6 +446,7 @@ func (t *DTLSTransport) Start(remoteParameters DTLSParameters) error { } t.onStateChange(DTLSTransportStateFailed) + return err } } @@ -430,7 +474,8 @@ func (t *DTLSTransport) Stop() error { } for i := range t.simulcastStreams { - closeErrs = append(closeErrs, t.simulcastStreams[i].Close()) + closeErrs = append(closeErrs, t.simulcastStreams[i].srtp.Close()) + closeErrs = append(closeErrs, t.simulcastStreams[i].srtcp.Close()) } if t.conn != nil { @@ -440,6 +485,7 @@ func (t *DTLSTransport) Stop() error { } } t.onStateChange(DTLSTransportStateClosed) + return util.FlattenErrs(closeErrs) } @@ -471,14 +517,20 @@ func (t *DTLSTransport) ensureICEConn() error { return nil } -func (t *DTLSTransport) storeSimulcastStream(s *srtp.ReadStreamSRTP) { +func (t *DTLSTransport) storeSimulcastStream( + srtpReadStream *srtp.ReadStreamSRTP, + srtcpReadStream *srtp.ReadStreamSRTCP, +) { t.lock.Lock() defer t.lock.Unlock() - t.simulcastStreams = append(t.simulcastStreams, s) + t.simulcastStreams = append(t.simulcastStreams, simulcastStreamPair{srtpReadStream, srtcpReadStream}) } -func (t *DTLSTransport) streamsForSSRC(ssrc SSRC, streamInfo interceptor.StreamInfo) (*srtp.ReadStreamSRTP, interceptor.RTPReader, *srtp.ReadStreamSRTCP, interceptor.RTCPReader, error) { +func (t *DTLSTransport) streamsForSSRC( + ssrc SSRC, + streamInfo interceptor.StreamInfo, +) (*srtp.ReadStreamSRTP, interceptor.RTPReader, *srtp.ReadStreamSRTCP, interceptor.RTCPReader, error) { srtpSession, err := t.getSRTPSession() if err != nil { return nil, nil, nil, nil, err @@ -489,10 +541,16 @@ func (t *DTLSTransport) streamsForSSRC(ssrc SSRC, streamInfo interceptor.StreamI return nil, nil, nil, nil, err } - rtpInterceptor := t.api.interceptor.BindRemoteStream(&streamInfo, interceptor.RTPReaderFunc(func(in []byte, a interceptor.Attributes) (n int, attributes interceptor.Attributes, err error) { - n, err = rtpReadStream.Read(in) - return n, a, err - })) + rtpInterceptor := t.api.interceptor.BindRemoteStream( + &streamInfo, + interceptor.RTPReaderFunc( + func(in []byte, a interceptor.Attributes) (n int, attributes interceptor.Attributes, err error) { + n, err = rtpReadStream.Read(in) + + return n, a, err + }, + ), + ) srtcpSession, err := t.getSRTCPSession() if err != nil { @@ -504,10 +562,13 @@ func (t *DTLSTransport) streamsForSSRC(ssrc SSRC, streamInfo interceptor.StreamI return nil, nil, nil, nil, err } - rtcpInterceptor := t.api.interceptor.BindRTCPReader(interceptor.RTPReaderFunc(func(in []byte, a interceptor.Attributes) (n int, attributes interceptor.Attributes, err error) { - n, err = rtcpReadStream.Read(in) - return n, a, err - })) + rtcpInterceptor := t.api.interceptor.BindRTCPReader(interceptor.RTCPReaderFunc( + func(in []byte, a interceptor.Attributes) (n int, attributes interceptor.Attributes, err error) { + n, err = rtcpReadStream.Read(in) + + return n, a, err + }), + ) return rtpReadStream, rtpInterceptor, rtcpReadStream, rtcpInterceptor, nil } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/dtlstransport_js.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/dtlstransport_js.go similarity index 88% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/dtlstransport_js.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/dtlstransport_js.go index bc3444e56..846cfb712 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/dtlstransport_js.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/dtlstransport_js.go @@ -17,6 +17,11 @@ type DTLSTransport struct { underlying js.Value } +// JSValue returns the underlying RTCDtlsTransport +func (r *DTLSTransport) JSValue() js.Value { + return r.underlying +} + // ICETransport returns the currently-configured *ICETransport or nil // if one has not been configured func (r *DTLSTransport) ICETransport() *ICETransport { diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/dtlstransportstate.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/dtlstransportstate.go similarity index 82% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/dtlstransportstate.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/dtlstransportstate.go index f986e22cb..933e38dca 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/dtlstransportstate.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/dtlstransportstate.go @@ -7,9 +7,12 @@ package webrtc type DTLSTransportState int const ( + // DTLSTransportStateUnknown is the enum's zero-value. + DTLSTransportStateUnknown DTLSTransportState = iota + // DTLSTransportStateNew indicates that DTLS has not started negotiating // yet. - DTLSTransportStateNew DTLSTransportState = iota + 1 + DTLSTransportStateNew // DTLSTransportStateConnecting indicates that DTLS is in the process of // negotiating a secure connection and verifying the remote fingerprint. @@ -52,7 +55,7 @@ func newDTLSTransportState(raw string) DTLSTransportState { case dtlsTransportStateFailedStr: return DTLSTransportStateFailed default: - return DTLSTransportState(Unknown) + return DTLSTransportStateUnknown } } @@ -72,3 +75,15 @@ func (t DTLSTransportState) String() string { return ErrUnknownType.Error() } } + +// MarshalText implements encoding.TextMarshaler. +func (t DTLSTransportState) MarshalText() ([]byte, error) { + return []byte(t.String()), nil +} + +// UnmarshalText implements encoding.TextUnmarshaler. +func (t *DTLSTransportState) UnmarshalText(b []byte) error { + *t = newDTLSTransportState(string(b)) + + return nil +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/errors.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/errors.go similarity index 69% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/errors.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/errors.go index 009e91dd6..539422913 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/errors.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/errors.go @@ -76,88 +76,103 @@ var ( // and is mutually exclusive. ErrRetransmitsOrPacketLifeTime = errors.New("both MaxPacketLifeTime and MaxRetransmits was set") - // ErrCodecNotFound is returned when a codec search to the Media Engine fails + // ErrCodecNotFound is returned when a codec search to the Media Engine fails. ErrCodecNotFound = errors.New("codec not found") // ErrNoRemoteDescription indicates that an operation was rejected because - // the remote description is not set + // the remote description is not set. ErrNoRemoteDescription = errors.New("remote description is not set") // ErrIncorrectSDPSemantics indicates that the PeerConnection was configured to - // generate SDP Answers with different SDP Semantics than the received Offer + // generate SDP Answers with different SDP Semantics than the received Offer. ErrIncorrectSDPSemantics = errors.New("remote SessionDescription semantics does not match configuration") - // ErrIncorrectSignalingState indicates that the signaling state of PeerConnection is not correct + // ErrIncorrectSignalingState indicates that the signaling state of PeerConnection is not correct. ErrIncorrectSignalingState = errors.New("operation can not be run in current signaling state") // ErrProtocolTooLarge indicates that value given for a DataChannelInit protocol is - // longer then 65535 bytes + // longer then 65535 bytes. ErrProtocolTooLarge = errors.New("protocol is larger then 65535 bytes") // ErrSenderNotCreatedByConnection indicates RemoveTrack was called with a RtpSender not created - // by this PeerConnection + // by this PeerConnection. ErrSenderNotCreatedByConnection = errors.New("RtpSender not created by this PeerConnection") // ErrSessionDescriptionNoFingerprint indicates SetRemoteDescription was called with a SessionDescription that has no - // fingerprint + // fingerprint. ErrSessionDescriptionNoFingerprint = errors.New("SetRemoteDescription called with no fingerprint") // ErrSessionDescriptionInvalidFingerprint indicates SetRemoteDescription was called with a SessionDescription that - // has an invalid fingerprint + // has an invalid fingerprint. ErrSessionDescriptionInvalidFingerprint = errors.New("SetRemoteDescription called with an invalid fingerprint") - // ErrSessionDescriptionConflictingFingerprints indicates SetRemoteDescription was called with a SessionDescription that - // has an conflicting fingerprints - ErrSessionDescriptionConflictingFingerprints = errors.New("SetRemoteDescription called with multiple conflicting fingerprint") + // ErrSessionDescriptionConflictingFingerprints indicates SetRemoteDescription was called with a SessionDescription + // that has an conflicting fingerprints. + ErrSessionDescriptionConflictingFingerprints = errors.New( + "SetRemoteDescription called with multiple conflicting fingerprint", + ) // ErrSessionDescriptionMissingIceUfrag indicates SetRemoteDescription was called with a SessionDescription that - // is missing an ice-ufrag value + // is missing an ice-ufrag value. ErrSessionDescriptionMissingIceUfrag = errors.New("SetRemoteDescription called with no ice-ufrag") // ErrSessionDescriptionMissingIcePwd indicates SetRemoteDescription was called with a SessionDescription that - // is missing an ice-pwd value + // is missing an ice-pwd value. ErrSessionDescriptionMissingIcePwd = errors.New("SetRemoteDescription called with no ice-pwd") - // ErrSessionDescriptionConflictingIceUfrag indicates SetRemoteDescription was called with a SessionDescription that - // contains multiple conflicting ice-ufrag values - ErrSessionDescriptionConflictingIceUfrag = errors.New("SetRemoteDescription called with multiple conflicting ice-ufrag values") + // ErrSessionDescriptionConflictingIceUfrag indicates SetRemoteDescription was called with a SessionDescription + // that contains multiple conflicting ice-ufrag values. + ErrSessionDescriptionConflictingIceUfrag = errors.New( + "SetRemoteDescription called with multiple conflicting ice-ufrag values", + ) - // ErrSessionDescriptionConflictingIcePwd indicates SetRemoteDescription was called with a SessionDescription that - // contains multiple conflicting ice-pwd values - ErrSessionDescriptionConflictingIcePwd = errors.New("SetRemoteDescription called with multiple conflicting ice-pwd values") + // ErrSessionDescriptionConflictingIcePwd indicates SetRemoteDescription was called with a SessionDescription + // that contains multiple conflicting ice-pwd values. + ErrSessionDescriptionConflictingIcePwd = errors.New( + "SetRemoteDescription called with multiple conflicting ice-pwd values", + ) - // ErrNoSRTPProtectionProfile indicates that the DTLS handshake completed and no SRTP Protection Profile was chosen + // ErrNoSRTPProtectionProfile indicates that the DTLS handshake completed and no SRTP Protection Profile was chosen. ErrNoSRTPProtectionProfile = errors.New("DTLS Handshake completed and no SRTP Protection Profile was chosen") - // ErrFailedToGenerateCertificateFingerprint indicates that we failed to generate the fingerprint used for comparing certificates + // ErrFailedToGenerateCertificateFingerprint indicates that we failed to generate the fingerprint + // used for comparing certificates. ErrFailedToGenerateCertificateFingerprint = errors.New("failed to generate certificate fingerprint") - // ErrNoCodecsAvailable indicates that operation isn't possible because the MediaEngine has no codecs available + // ErrNoCodecsAvailable indicates that operation isn't possible because the MediaEngine has no codecs available. ErrNoCodecsAvailable = errors.New("operation failed no codecs are available") - // ErrUnsupportedCodec indicates the remote peer doesn't support the requested codec + // ErrUnsupportedCodec indicates the remote peer doesn't support the requested codec. ErrUnsupportedCodec = errors.New("unable to start track, codec is not supported by remote") - // ErrSenderWithNoCodecs indicates that a RTPSender was created without any codecs. To send media the MediaEngine needs at - // least one configured codec. + // ErrSenderWithNoCodecs indicates that a RTPSender was created without any codecs. To send media the MediaEngine + // needs at least one configured codec. ErrSenderWithNoCodecs = errors.New("unable to populate media section, RTPSender created with no codecs") - // ErrRTPSenderNewTrackHasIncorrectKind indicates that the new track is of a different kind than the previous/original + // ErrCodecAlreadyRegistered indicates that a codec has already been registered for the same payload type. + ErrCodecAlreadyRegistered = errors.New("codec already registered for same payload type") + + // ErrRTPSenderNewTrackHasIncorrectKind indicates that the new track is of a different kind than the previous/original. ErrRTPSenderNewTrackHasIncorrectKind = errors.New("new track must be of the same kind as previous") - // ErrRTPSenderNewTrackHasIncorrectEnvelope indicates that the new track has a different envelope than the previous/original + // ErrRTPSenderNewTrackHasIncorrectEnvelope indicates that the new track has a different envelope + // than the previous/original. ErrRTPSenderNewTrackHasIncorrectEnvelope = errors.New("new track must have the same envelope as previous") - // ErrUnbindFailed indicates that a TrackLocal was not able to be unbind + // ErrUnbindFailed indicates that a TrackLocal was not able to be unbind. ErrUnbindFailed = errors.New("failed to unbind TrackLocal from PeerConnection") - // ErrNoPayloaderForCodec indicates that the requested codec does not have a payloader + // ErrNoPayloaderForCodec indicates that the requested codec does not have a payloader. ErrNoPayloaderForCodec = errors.New("the requested codec does not have a payloader") - // ErrRegisterHeaderExtensionInvalidDirection indicates that a extension was registered with a direction besides `sendonly` or `recvonly` - ErrRegisterHeaderExtensionInvalidDirection = errors.New("a header extension must be registered as 'recvonly', 'sendonly' or both") + // ErrRegisterHeaderExtensionInvalidDirection indicates that a extension was + // registered with a direction besides `sendonly` or `recvonly`. + ErrRegisterHeaderExtensionInvalidDirection = errors.New( + "a header extension must be registered as 'recvonly', 'sendonly' or both", + ) - // ErrSimulcastProbeOverflow indicates that too many Simulcast probe streams are in flight and the requested SSRC was ignored + // ErrSimulcastProbeOverflow indicates that too many Simulcast probe streams are in flight + // and the requested SSRC was ignored. ErrSimulcastProbeOverflow = errors.New("simulcast probe limit has been reached, new SSRC has been discarded") errDetachNotEnabled = errors.New("enable detaching by calling webrtc.DetachDataChannels()") @@ -173,35 +188,49 @@ var ( errICEConnectionNotStarted = errors.New("ICE connection not started") errICECandidateTypeUnknown = errors.New("unknown candidate type") - errICEInvalidConvertCandidateType = errors.New("cannot convert ice.CandidateType into webrtc.ICECandidateType, invalid type") - errICEAgentNotExist = errors.New("ICEAgent does not exist") - errICECandiatesCoversionFailed = errors.New("unable to convert ICE candidates to ICECandidates") - errICERoleUnknown = errors.New("unknown ICE Role") - errICEProtocolUnknown = errors.New("unknown protocol") - errICEGathererNotStarted = errors.New("gatherer not started") + errICEInvalidConvertCandidateType = errors.New( + "cannot convert ice.CandidateType into webrtc.ICECandidateType, invalid type", + ) + errICEAgentNotExist = errors.New("ICEAgent does not exist") + errICECandiatesCoversionFailed = errors.New("unable to convert ICE candidates to ICECandidates") + errICERoleUnknown = errors.New("unknown ICE Role") + errICEProtocolUnknown = errors.New("unknown protocol") + errICEGathererNotStarted = errors.New("gatherer not started") errNetworkTypeUnknown = errors.New("unknown network type") - errSDPDoesNotMatchOffer = errors.New("new sdp does not match previous offer") - errSDPDoesNotMatchAnswer = errors.New("new sdp does not match previous answer") - errPeerConnSDPTypeInvalidValue = errors.New("provided value is not a valid enum value of type SDPType") + errSDPDoesNotMatchOffer = errors.New("new sdp does not match previous offer") + errSDPDoesNotMatchAnswer = errors.New("new sdp does not match previous answer") + errPeerConnSDPTypeInvalidValue = errors.New( + "provided value is not a valid enum value of type SDPType", + ) errPeerConnStateChangeInvalid = errors.New("invalid state change op") errPeerConnStateChangeUnhandled = errors.New("unhandled state change op") errPeerConnSDPTypeInvalidValueSetLocalDescription = errors.New("invalid SDP type supplied to SetLocalDescription()") - errPeerConnRemoteDescriptionWithoutMidValue = errors.New("remoteDescription contained media section without mid value") - errPeerConnRemoteDescriptionNil = errors.New("remoteDescription has not been set yet") - errPeerConnSingleMediaSectionHasExplicitSSRC = errors.New("single media section has an explicit SSRC") - errPeerConnRemoteSSRCAddTransceiver = errors.New("could not add transceiver for remote SSRC") - errPeerConnSimulcastMidRTPExtensionRequired = errors.New("mid RTP Extensions required for Simulcast") - errPeerConnSimulcastStreamIDRTPExtensionRequired = errors.New("stream id RTP Extensions required for Simulcast") - errPeerConnSimulcastIncomingSSRCFailed = errors.New("incoming SSRC failed Simulcast probing") - errPeerConnAddTransceiverFromKindOnlyAcceptsOne = errors.New("AddTransceiverFromKind only accepts one RTPTransceiverInit") - errPeerConnAddTransceiverFromTrackOnlyAcceptsOne = errors.New("AddTransceiverFromTrack only accepts one RTPTransceiverInit") - errPeerConnAddTransceiverFromKindSupport = errors.New("AddTransceiverFromKind currently only supports recvonly") - errPeerConnAddTransceiverFromTrackSupport = errors.New("AddTransceiverFromTrack currently only supports sendonly and sendrecv") - errPeerConnSetIdentityProviderNotImplemented = errors.New("TODO SetIdentityProvider") - errPeerConnWriteRTCPOpenWriteStream = errors.New("WriteRTCP failed to open WriteStream") - errPeerConnTranscieverMidNil = errors.New("cannot find transceiver with mid") + errPeerConnRemoteDescriptionWithoutMidValue = errors.New( + "remoteDescription contained media section without mid value", + ) + errPeerConnRemoteDescriptionNil = errors.New("remoteDescription has not been set yet") + errMediaSectionHasExplictSSRCAttribute = errors.New("media section has an explicit SSRC") + errPeerConnRemoteSSRCAddTransceiver = errors.New("could not add transceiver for remote SSRC") + errPeerConnSimulcastMidRTPExtensionRequired = errors.New("mid RTP Extensions required for Simulcast") + errPeerConnSimulcastStreamIDRTPExtensionRequired = errors.New("stream id RTP Extensions required for Simulcast") + errPeerConnSimulcastIncomingSSRCFailed = errors.New("incoming SSRC failed Simulcast probing") + errPeerConnAddTransceiverFromKindOnlyAcceptsOne = errors.New( + "AddTransceiverFromKind only accepts one RTPTransceiverInit", + ) + errPeerConnAddTransceiverFromTrackOnlyAcceptsOne = errors.New( + "AddTransceiverFromTrack only accepts one RTPTransceiverInit", + ) + errPeerConnAddTransceiverFromKindSupport = errors.New( + "AddTransceiverFromKind currently only supports recvonly", + ) + errPeerConnAddTransceiverFromTrackSupport = errors.New( + "AddTransceiverFromTrack currently only supports sendonly and sendrecv", + ) + errPeerConnSetIdentityProviderNotImplemented = errors.New("TODO SetIdentityProvider") + errPeerConnWriteRTCPOpenWriteStream = errors.New("WriteRTCP failed to open WriteStream") + errPeerConnTranscieverMidNil = errors.New("cannot find transceiver with mid") errRTPReceiverDTLSTransportNil = errors.New("DTLSTransport must not be nil") errRTPReceiverReceiveAlreadyCalled = errors.New("Receive has already been called") @@ -227,21 +256,28 @@ var ( errSDPZeroTransceivers = errors.New("addTransceiverSDP() called with 0 transceivers") errSDPMediaSectionMediaDataChanInvalid = errors.New("invalid Media Section. Media + DataChannel both enabled") - errSDPMediaSectionMultipleTrackInvalid = errors.New("invalid Media Section. Can not have multiple tracks in one MediaSection in UnifiedPlan") + errSDPMediaSectionMultipleTrackInvalid = errors.New( + "invalid Media Section. Can not have multiple tracks in one MediaSection in UnifiedPlan", + ) errSettingEngineSetAnsweringDTLSRole = errors.New("SetAnsweringDTLSRole must DTLSRoleClient or DTLSRoleServer") errSignalingStateCannotRollback = errors.New("can't rollback from stable state") errSignalingStateProposedTransitionInvalid = errors.New("invalid proposed signaling state transition") - errStatsICECandidateStateInvalid = errors.New("cannot convert to StatsICECandidatePairStateSucceeded invalid ice candidate state") + errStatsICECandidateStateInvalid = errors.New( + "cannot convert to StatsICECandidatePairStateSucceeded invalid ice candidate state", + ) errInvalidICECredentialTypeString = errors.New("invalid ICECredentialType") errInvalidICEServer = errors.New("invalid ICEServer") errICETransportNotInNew = errors.New("ICETransport can only be called in ICETransportStateNew") + errICETransportClosed = errors.New("ICETransport closed") - errCertificatePEMFormatError = errors.New("bad Certificate PEM format") + errCertificatePEMMultipleCert = errors.New("failed parsing certificate, more than 1 CERTIFICATE block in pems") + errCertificatePEMMultiplePriv = errors.New("failed parsing certificate, more than 1 PRIVATE KEY block in pems") + errCertificatePEMMissing = errors.New("failed parsing certificate, pems must contain both a CERTIFICATE block and a PRIVATE KEY block") // nolint: lll errRTPTooShort = errors.New("not long enough to be a RTP Packet") diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/gathering_complete_promise.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/gathering_complete_promise.go similarity index 87% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/gathering_complete_promise.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/gathering_complete_promise.go index 12d3170d6..d51a99363 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/gathering_complete_promise.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/gathering_complete_promise.go @@ -7,10 +7,12 @@ import ( "context" ) -// GatheringCompletePromise is a Pion specific helper function that returns a channel that is closed when gathering is complete. +// GatheringCompletePromise is a Pion specific helper function that returns a channel that is closed +// when gathering is complete. // This function may be helpful in cases where you are unable to trickle your ICE Candidates. // -// It is better to not use this function, and instead trickle candidates. If you use this function you will see longer connection startup times. +// It is better to not use this function, and instead trickle candidates. +// If you use this function you will see longer connection startup times. // When the call is connected you will see no impact however. func GatheringCompletePromise(pc *PeerConnection) (gatherComplete <-chan struct{}) { gatheringComplete, done := context.WithCancel(context.Background()) diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/ice_go.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/ice_go.go similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/ice_go.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/ice_go.go diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/icecandidate.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/icecandidate.go similarity index 55% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/icecandidate.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/icecandidate.go index fa0b68093..db7af8409 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/icecandidate.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/icecandidate.go @@ -6,10 +6,10 @@ package webrtc import ( "fmt" - "github.com/pion/ice/v2" + "github.com/pion/ice/v4" ) -// ICECandidate represents a ice candidate +// ICECandidate represents a ice candidate. type ICECandidate struct { statsID string Foundation string `json:"foundation"` @@ -22,15 +22,21 @@ type ICECandidate struct { RelatedAddress string `json:"relatedAddress"` RelatedPort uint16 `json:"relatedPort"` TCPType string `json:"tcpType"` + SDPMid string `json:"sdpMid"` + SDPMLineIndex uint16 `json:"sdpMLineIndex"` + extensions string } -// Conversion for package ice - -func newICECandidatesFromICE(iceCandidates []ice.Candidate) ([]ICECandidate, error) { +// Conversion for package ice. +func newICECandidatesFromICE( + iceCandidates []ice.Candidate, + sdpMid string, + sdpMLineIndex uint16, +) ([]ICECandidate, error) { candidates := []ICECandidate{} for _, i := range iceCandidates { - c, err := newICECandidateFromICE(i) + c, err := newICECandidateFromICE(i, sdpMid, sdpMLineIndex) if err != nil { return nil, err } @@ -40,37 +46,42 @@ func newICECandidatesFromICE(iceCandidates []ice.Candidate) ([]ICECandidate, err return candidates, nil } -func newICECandidateFromICE(i ice.Candidate) (ICECandidate, error) { - typ, err := convertTypeFromICE(i.Type()) +func newICECandidateFromICE(candidate ice.Candidate, sdpMid string, sdpMLineIndex uint16) (ICECandidate, error) { + typ, err := convertTypeFromICE(candidate.Type()) if err != nil { return ICECandidate{}, err } - protocol, err := NewICEProtocol(i.NetworkType().NetworkShort()) + protocol, err := NewICEProtocol(candidate.NetworkType().NetworkShort()) if err != nil { return ICECandidate{}, err } - c := ICECandidate{ - statsID: i.ID(), - Foundation: i.Foundation(), - Priority: i.Priority(), - Address: i.Address(), - Protocol: protocol, - Port: uint16(i.Port()), - Component: i.Component(), - Typ: typ, - TCPType: i.TCPType().String(), + newCandidate := ICECandidate{ + statsID: candidate.ID(), + Foundation: candidate.Foundation(), + Priority: candidate.Priority(), + Address: candidate.Address(), + Protocol: protocol, + Port: uint16(candidate.Port()), //nolint:gosec // G115 + Component: candidate.Component(), + Typ: typ, + TCPType: candidate.TCPType().String(), + SDPMid: sdpMid, + SDPMLineIndex: sdpMLineIndex, } - if i.RelatedAddress() != nil { - c.RelatedAddress = i.RelatedAddress().Address - c.RelatedPort = uint16(i.RelatedAddress().Port) + newCandidate.setExtensions(candidate.Extensions()) + + if candidate.RelatedAddress() != nil { + newCandidate.RelatedAddress = candidate.RelatedAddress().Address + newCandidate.RelatedPort = uint16(candidate.RelatedAddress().Port) //nolint:gosec // G115 } - return c, nil + return newCandidate, nil } -func (c ICECandidate) toICE() (ice.Candidate, error) { +// ToICE converts ICECandidate to ice.Candidate. +func (c ICECandidate) ToICE() (cand ice.Candidate, err error) { candidateID := c.statsID switch c.Typ { case ICECandidateTypeHost: @@ -84,7 +95,8 @@ func (c ICECandidate) toICE() (ice.Candidate, error) { Foundation: c.Foundation, Priority: c.Priority, } - return ice.NewCandidateHost(&config) + + cand, err = ice.NewCandidateHost(&config) case ICECandidateTypeSrflx: config := ice.CandidateServerReflexiveConfig{ CandidateID: candidateID, @@ -97,7 +109,8 @@ func (c ICECandidate) toICE() (ice.Candidate, error) { RelAddr: c.RelatedAddress, RelPort: int(c.RelatedPort), } - return ice.NewCandidateServerReflexive(&config) + + cand, err = ice.NewCandidateServerReflexive(&config) case ICECandidateTypePrflx: config := ice.CandidatePeerReflexiveConfig{ CandidateID: candidateID, @@ -110,7 +123,8 @@ func (c ICECandidate) toICE() (ice.Candidate, error) { RelAddr: c.RelatedAddress, RelPort: int(c.RelatedPort), } - return ice.NewCandidatePeerReflexive(&config) + + cand, err = ice.NewCandidatePeerReflexive(&config) case ICECandidateTypeRelay: config := ice.CandidateRelayConfig{ CandidateID: candidateID, @@ -123,10 +137,68 @@ func (c ICECandidate) toICE() (ice.Candidate, error) { RelAddr: c.RelatedAddress, RelPort: int(c.RelatedPort), } - return ice.NewCandidateRelay(&config) + + cand, err = ice.NewCandidateRelay(&config) default: return nil, fmt.Errorf("%w: %s", errICECandidateTypeUnknown, c.Typ) } + + if cand != nil && err == nil { + err = c.exportExtensions(cand) + } + + return cand, err +} + +func (c *ICECandidate) setExtensions(ext []ice.CandidateExtension) { + var extensions string + + for i := range ext { + if i > 0 { + extensions += " " + } + + extensions += ext[i].Key + " " + ext[i].Value + } + + c.extensions = extensions +} + +func (c *ICECandidate) exportExtensions(cand ice.Candidate) error { + extensions := c.extensions + var ext ice.CandidateExtension + var field string + + for i, start := 0, 0; i < len(extensions); i++ { + switch { + case extensions[i] == ' ': + field = extensions[start:i] + start = i + 1 + case i == len(extensions)-1: + field = extensions[start:] + default: + continue + } + + // Extension keys can't be empty + hasKey := ext.Key != "" + if !hasKey { + ext.Key = field + } else { + ext.Value = field + } + + // Extension value can be empty + if hasKey || i == len(extensions)-1 { + if err := cand.AddExtension(ext); err != nil { + return err + } + + ext = ice.CandidateExtension{} + } + } + + return nil } func convertTypeFromICE(t ice.CandidateType) (ICECandidateType, error) { @@ -145,28 +217,27 @@ func convertTypeFromICE(t ice.CandidateType) (ICECandidateType, error) { } func (c ICECandidate) String() string { - ic, err := c.toICE() + ic, err := c.ToICE() if err != nil { return fmt.Sprintf("%#v failed to convert to ICE: %s", c, err) } + return ic.String() } // ToJSON returns an ICECandidateInit // as indicated by the spec https://w3c.github.io/webrtc-pc/#dom-rtcicecandidate-tojson func (c ICECandidate) ToJSON() ICECandidateInit { - zeroVal := uint16(0) - emptyStr := "" candidateStr := "" - candidate, err := c.toICE() + candidate, err := c.ToICE() if err == nil { candidateStr = candidate.Marshal() } return ICECandidateInit{ Candidate: fmt.Sprintf("candidate:%s", candidateStr), - SDPMid: &emptyStr, - SDPMLineIndex: &zeroVal, + SDPMid: &c.SDPMid, + SDPMLineIndex: &c.SDPMLineIndex, } } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/icecandidateinit.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/icecandidateinit.go similarity index 85% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/icecandidateinit.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/icecandidateinit.go index 30ad93c0b..bd9df800d 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/icecandidateinit.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/icecandidateinit.go @@ -3,7 +3,7 @@ package webrtc -// ICECandidateInit is used to serialize ice candidates +// ICECandidateInit is used to serialize ice candidates. type ICECandidateInit struct { Candidate string `json:"candidate"` SDPMid *string `json:"sdpMid"` diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/icecandidatepair.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/icecandidatepair.go similarity index 87% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/icecandidatepair.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/icecandidatepair.go index b87884bce..2ae2efe54 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/icecandidatepair.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/icecandidatepair.go @@ -5,7 +5,7 @@ package webrtc import "fmt" -// ICECandidatePair represents an ICE Candidate pair +// ICECandidatePair represents an ICE Candidate pair. type ICECandidatePair struct { statsID string Local *ICECandidate @@ -21,9 +21,10 @@ func (p *ICECandidatePair) String() string { } // NewICECandidatePair returns an initialized *ICECandidatePair -// for the given pair of ICECandidate instances +// for the given pair of ICECandidate instances. func NewICECandidatePair(local, remote *ICECandidate) *ICECandidatePair { statsID := newICECandidatePairStatsID(local.statsID, remote.statsID) + return &ICECandidatePair{ statsID: statsID, Local: local, diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/icecandidatetype.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/icecandidatetype.go similarity index 78% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/icecandidatetype.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/icecandidatetype.go index a274c45db..7ac62db11 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/icecandidatetype.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/icecandidatetype.go @@ -6,21 +6,24 @@ package webrtc import ( "fmt" - "github.com/pion/ice/v2" + "github.com/pion/ice/v4" ) // ICECandidateType represents the type of the ICE candidate used. type ICECandidateType int const ( + // ICECandidateTypeUnknown is the enum's zero-value. + ICECandidateTypeUnknown ICECandidateType = iota + // ICECandidateTypeHost indicates that the candidate is of Host type as // described in https://tools.ietf.org/html/rfc8445#section-5.1.1.1. A // candidate obtained by binding to a specific port from an IP address on // the host. This includes IP addresses on physical interfaces and logical // ones, such as ones obtained through VPNs. - ICECandidateTypeHost ICECandidateType = iota + 1 + ICECandidateTypeHost - // ICECandidateTypeSrflx indicates the the candidate is of Server + // ICECandidateTypeSrflx indicates the candidate is of Server // Reflexive type as described // https://tools.ietf.org/html/rfc8445#section-5.1.1.2. A candidate type // whose IP address and port are a binding allocated by a NAT for an ICE @@ -34,7 +37,7 @@ const ( // NAT to its peer. ICECandidateTypePrflx - // ICECandidateTypeRelay indicates the the candidate is of Relay type as + // ICECandidateTypeRelay indicates the candidate is of Relay type as // described in https://tools.ietf.org/html/rfc8445#section-5.1.1.2. A // candidate type obtained from a relay server, such as a TURN server. ICECandidateTypeRelay @@ -48,7 +51,7 @@ const ( iceCandidateTypeRelayStr = "relay" ) -// NewICECandidateType takes a string and converts it into ICECandidateType +// NewICECandidateType takes a string and converts it into ICECandidateType. func NewICECandidateType(raw string) (ICECandidateType, error) { switch raw { case iceCandidateTypeHostStr: @@ -60,7 +63,7 @@ func NewICECandidateType(raw string) (ICECandidateType, error) { case iceCandidateTypeRelayStr: return ICECandidateTypeRelay, nil default: - return ICECandidateType(Unknown), fmt.Errorf("%w: %s", errICECandidateTypeUnknown, raw) + return ICECandidateTypeUnknown, fmt.Errorf("%w: %s", errICECandidateTypeUnknown, raw) } } @@ -92,6 +95,20 @@ func getCandidateType(candidateType ice.CandidateType) (ICECandidateType, error) default: // NOTE: this should never happen[tm] err := fmt.Errorf("%w: %s", errICEInvalidConvertCandidateType, candidateType.String()) - return ICECandidateType(Unknown), err + + return ICECandidateTypeUnknown, err } } + +// MarshalText implements the encoding.TextMarshaler interface. +func (t ICECandidateType) MarshalText() ([]byte, error) { + return []byte(t.String()), nil +} + +// UnmarshalText implements the encoding.TextUnmarshaler interface. +func (t *ICECandidateType) UnmarshalText(b []byte) error { + var err error + *t, err = NewICECandidateType(string(b)) + + return err +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/icecomponent.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/icecomponent.go similarity index 90% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/icecomponent.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/icecomponent.go index c65a893dc..ea13f9859 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/icecomponent.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/icecomponent.go @@ -8,12 +8,15 @@ package webrtc type ICEComponent int const ( + // ICEComponentUnknown is the enum's zero-value. + ICEComponentUnknown ICEComponent = iota + // ICEComponentRTP indicates that the ICE Transport is used for RTP (or // RTCP multiplexing), as defined in // https://tools.ietf.org/html/rfc5245#section-4.1.1.1. Protocols // multiplexed with RTP (e.g. data channel) share its component ID. This // represents the component-id value 1 when encoded in candidate-attribute. - ICEComponentRTP ICEComponent = iota + 1 + ICEComponentRTP // ICEComponentRTCP indicates that the ICE Transport is used for RTCP as // defined by https://tools.ietf.org/html/rfc5245#section-4.1.1.1. This @@ -34,7 +37,7 @@ func newICEComponent(raw string) ICEComponent { case iceComponentRTCPStr: return ICEComponentRTCP default: - return ICEComponent(Unknown) + return ICEComponentUnknown } } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/iceconnectionstate.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/iceconnectionstate.go similarity index 94% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/iceconnectionstate.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/iceconnectionstate.go index e52e1328a..488b882ab 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/iceconnectionstate.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/iceconnectionstate.go @@ -7,11 +7,14 @@ package webrtc type ICEConnectionState int const ( + // ICEConnectionStateUnknown is the enum's zero-value. + ICEConnectionStateUnknown ICEConnectionState = iota + // ICEConnectionStateNew indicates that any of the ICETransports are // in the "new" state and none of them are in the "checking", "disconnected" // or "failed" state, or all ICETransports are in the "closed" state, or // there are no transports. - ICEConnectionStateNew ICEConnectionState = iota + 1 + ICEConnectionStateNew // ICEConnectionStateChecking indicates that any of the ICETransports // are in the "checking" state and none of them are in the "disconnected" @@ -53,7 +56,7 @@ const ( iceConnectionStateClosedStr = "closed" ) -// NewICEConnectionState takes a string and converts it to ICEConnectionState +// NewICEConnectionState takes a string and converts it to ICEConnectionState. func NewICEConnectionState(raw string) ICEConnectionState { switch raw { case iceConnectionStateNewStr: @@ -71,7 +74,7 @@ func NewICEConnectionState(raw string) ICEConnectionState { case iceConnectionStateClosedStr: return ICEConnectionStateClosed default: - return ICEConnectionState(Unknown) + return ICEConnectionStateUnknown } } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/icecredentialtype.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/icecredentialtype.go similarity index 97% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/icecredentialtype.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/icecredentialtype.go index 5d704a9bd..ae30d1d66 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/icecredentialtype.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/icecredentialtype.go @@ -50,7 +50,7 @@ func (t ICECredentialType) String() string { } } -// UnmarshalJSON parses the JSON-encoded data and stores the result +// UnmarshalJSON parses the JSON-encoded data and stores the result. func (t *ICECredentialType) UnmarshalJSON(b []byte) error { var val string if err := json.Unmarshal(b, &val); err != nil { @@ -63,10 +63,11 @@ func (t *ICECredentialType) UnmarshalJSON(b []byte) error { } *t = tmp + return nil } -// MarshalJSON returns the JSON encoding +// MarshalJSON returns the JSON encoding. func (t ICECredentialType) MarshalJSON() ([]byte, error) { return json.Marshal(t.String()) } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/icegatherer.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/icegatherer.go similarity index 76% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/icegatherer.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/icegatherer.go index cf12b4206..2a1bc6b4e 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/icegatherer.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/icegatherer.go @@ -11,9 +11,9 @@ import ( "sync" "sync/atomic" - "github.com/pion/ice/v2" + "github.com/pion/ice/v4" "github.com/pion/logging" - "github.com/pion/stun" + "github.com/pion/stun/v3" ) // ICEGatherer gathers local host, server reflexive and relay @@ -37,6 +37,11 @@ type ICEGatherer struct { onGatheringCompleteHandler atomic.Value // func() api *API + + // Used to set the corresponding media stream identification tag and media description index + // for ICE candidates generated by this gatherer. + sdpMid atomic.Value // string + sdpMLineIndex atomic.Uint32 // uint16 } // NewICEGatherer creates a new NewICEGatherer. @@ -60,10 +65,12 @@ func (api *API) NewICEGatherer(opts ICEGatherOptions) (*ICEGatherer, error) { validatedServers: validatedServers, api: api, log: api.settingEngine.LoggerFactory.NewLogger("ice"), + sdpMid: atomic.Value{}, + sdpMLineIndex: atomic.Uint32{}, }, nil } -func (g *ICEGatherer) createAgent() error { +func (g *ICEGatherer) createAgent() error { //nolint:cyclop g.lock.Lock() defer g.lock.Unlock() @@ -108,6 +115,7 @@ func (g *ICEGatherer) createAgent() error { SrflxAcceptanceMinWait: g.api.settingEngine.timeout.ICESrflxAcceptanceMinWait, PrflxAcceptanceMinWait: g.api.settingEngine.timeout.ICEPrflxAcceptanceMinWait, RelayAcceptanceMinWait: g.api.settingEngine.timeout.ICERelayAcceptanceMinWait, + STUNGatherTimeout: g.api.settingEngine.timeout.ICESTUNGatherTimeout, InterfaceFilter: g.api.settingEngine.candidates.InterfaceFilter, IPFilter: g.api.settingEngine.candidates.IPFilter, NAT1To1IPs: g.api.settingEngine.candidates.NAT1To1IPs, @@ -121,6 +129,9 @@ func (g *ICEGatherer) createAgent() error { TCPMux: g.api.settingEngine.iceTCPMux, UDPMux: g.api.settingEngine.iceUDPMux, ProxyDialer: g.api.settingEngine.iceProxyDialer, + DisableActiveTCP: g.api.settingEngine.iceDisableActiveTCP, + MaxBindingRequests: g.api.settingEngine.iceMaxBindingRequests, + BindingRequestHandler: g.api.settingEngine.iceBindingRequestHandler, } requestedNetworkTypes := g.api.settingEngine.candidates.ICENetworkTypes @@ -138,11 +149,12 @@ func (g *ICEGatherer) createAgent() error { } g.agent = agent + return nil } // Gather ICE candidates. -func (g *ICEGatherer) Gather() error { +func (g *ICEGatherer) Gather() error { //nolint:cyclop if err := g.createAgent(); err != nil { return err } @@ -165,10 +177,19 @@ func (g *ICEGatherer) Gather() error { onGatheringCompleteHandler = handler } + sdpMid := "" + + if mid, ok := g.sdpMid.Load().(string); ok { + sdpMid = mid + } + + sdpMLineIndex := uint16(g.sdpMLineIndex.Load()) //nolint:gosec // G115 + if candidate != nil { - c, err := newICECandidateFromICE(candidate) + c, err := newICECandidateFromICE(candidate, sdpMid, sdpMLineIndex) if err != nil { g.log.Warnf("Failed to convert ice.Candidate: %s", err) + return } onLocalCandidateHandler(&c) @@ -181,18 +202,43 @@ func (g *ICEGatherer) Gather() error { }); err != nil { return err } + return agent.GatherCandidates() } +// set media stream identification tag and media description index for this gatherer. +func (g *ICEGatherer) setMediaStreamIdentification(mid string, mLineIndex uint16) { + g.sdpMid.Store(mid) + g.sdpMLineIndex.Store(uint32(mLineIndex)) +} + // Close prunes all local candidates, and closes the ports. func (g *ICEGatherer) Close() error { + return g.close(false /* shouldGracefullyClose */) +} + +// GracefulClose prunes all local candidates, and closes the ports. It also waits +// for any goroutines it started to complete. This is only safe to call outside of +// ICEGatherer callbacks or if in a callback, in its own goroutine. +func (g *ICEGatherer) GracefulClose() error { + return g.close(true /* shouldGracefullyClose */) +} + +func (g *ICEGatherer) close(shouldGracefullyClose bool) error { g.lock.Lock() defer g.lock.Unlock() if g.agent == nil { return nil - } else if err := g.agent.Close(); err != nil { - return err + } + if shouldGracefullyClose { + if err := g.agent.GracefulClose(); err != nil { + return err + } + } else { + if err := g.agent.Close(); err != nil { + return err + } } g.agent = nil @@ -242,7 +288,14 @@ func (g *ICEGatherer) GetLocalCandidates() ([]ICECandidate, error) { return nil, err } - return newICECandidatesFromICE(iceCandidates) + sdpMid := "" + if mid, ok := g.sdpMid.Load().(string); ok { + sdpMid = mid + } + + sdpMLineIndex := uint16(g.sdpMLineIndex.Load()) //nolint:gosec // G115 + + return newICECandidatesFromICE(iceCandidates, sdpMid, sdpMLineIndex) } // OnLocalCandidate sets an event handler which fires when a new local ICE candidate is available @@ -251,7 +304,7 @@ func (g *ICEGatherer) OnLocalCandidate(f func(*ICECandidate)) { g.onLocalCandidateHandler.Store(f) } -// OnStateChange fires any time the ICEGatherer changes +// OnStateChange fires any time the ICEGatherer changes. func (g *ICEGatherer) OnStateChange(f func(ICEGathererState)) { g.onStateChangeHandler.Store(f) } @@ -272,6 +325,7 @@ func (g *ICEGatherer) setState(s ICEGathererState) { func (g *ICEGatherer) getAgent() *ice.Agent { g.lock.RLock() defer g.lock.RUnlock() + return g.agent } @@ -286,46 +340,14 @@ func (g *ICEGatherer) collectStats(collector *statsReportCollector) { for _, candidatePairStats := range agent.GetCandidatePairsStats() { collector.Collecting() - state, err := toStatsICECandidatePairState(candidatePairStats.State) + stats, err := toICECandidatePairStats(candidatePairStats) if err != nil { g.log.Error(err.Error()) + collector.Done() + + continue } - pairID := newICECandidatePairStatsID(candidatePairStats.LocalCandidateID, - candidatePairStats.RemoteCandidateID) - - stats := ICECandidatePairStats{ - Timestamp: statsTimestampFrom(candidatePairStats.Timestamp), - Type: StatsTypeCandidatePair, - ID: pairID, - // TransportID: - LocalCandidateID: candidatePairStats.LocalCandidateID, - RemoteCandidateID: candidatePairStats.RemoteCandidateID, - State: state, - Nominated: candidatePairStats.Nominated, - PacketsSent: candidatePairStats.PacketsSent, - PacketsReceived: candidatePairStats.PacketsReceived, - BytesSent: candidatePairStats.BytesSent, - BytesReceived: candidatePairStats.BytesReceived, - LastPacketSentTimestamp: statsTimestampFrom(candidatePairStats.LastPacketSentTimestamp), - LastPacketReceivedTimestamp: statsTimestampFrom(candidatePairStats.LastPacketReceivedTimestamp), - FirstRequestTimestamp: statsTimestampFrom(candidatePairStats.FirstRequestTimestamp), - LastRequestTimestamp: statsTimestampFrom(candidatePairStats.LastRequestTimestamp), - LastResponseTimestamp: statsTimestampFrom(candidatePairStats.LastResponseTimestamp), - TotalRoundTripTime: candidatePairStats.TotalRoundTripTime, - CurrentRoundTripTime: candidatePairStats.CurrentRoundTripTime, - AvailableOutgoingBitrate: candidatePairStats.AvailableOutgoingBitrate, - AvailableIncomingBitrate: candidatePairStats.AvailableIncomingBitrate, - CircuitBreakerTriggerCount: candidatePairStats.CircuitBreakerTriggerCount, - RequestsReceived: candidatePairStats.RequestsReceived, - RequestsSent: candidatePairStats.RequestsSent, - ResponsesReceived: candidatePairStats.ResponsesReceived, - ResponsesSent: candidatePairStats.ResponsesSent, - RetransmissionsReceived: candidatePairStats.RetransmissionsReceived, - RetransmissionsSent: candidatePairStats.RetransmissionsSent, - ConsentRequestsSent: candidatePairStats.ConsentRequestsSent, - ConsentExpiredTimestamp: statsTimestampFrom(candidatePairStats.ConsentExpiredTimestamp), - } collector.Collect(stats.ID, stats) } @@ -346,12 +368,11 @@ func (g *ICEGatherer) collectStats(collector *statsReportCollector) { Timestamp: statsTimestampFrom(candidateStats.Timestamp), ID: candidateStats.ID, Type: StatsTypeLocalCandidate, - NetworkType: networkType, IP: candidateStats.IP, - Port: int32(candidateStats.Port), + Port: int32(candidateStats.Port), //nolint:gosec // G115, no overflow, port Protocol: networkType.Protocol(), CandidateType: candidateType, - Priority: int32(candidateStats.Priority), + Priority: int32(candidateStats.Priority), //nolint:gosec URL: candidateStats.URL, RelayProtocol: candidateStats.RelayProtocol, Deleted: candidateStats.Deleted, @@ -375,12 +396,11 @@ func (g *ICEGatherer) collectStats(collector *statsReportCollector) { Timestamp: statsTimestampFrom(candidateStats.Timestamp), ID: candidateStats.ID, Type: StatsTypeRemoteCandidate, - NetworkType: networkType, IP: candidateStats.IP, - Port: int32(candidateStats.Port), + Port: int32(candidateStats.Port), //nolint:gosec // G115, no overflow, port Protocol: networkType.Protocol(), CandidateType: candidateType, - Priority: int32(candidateStats.Priority), + Priority: int32(candidateStats.Priority), //nolint:gosec // G115 URL: candidateStats.URL, RelayProtocol: candidateStats.RelayProtocol, } @@ -389,3 +409,24 @@ func (g *ICEGatherer) collectStats(collector *statsReportCollector) { collector.Done() }(collector, agent) } + +func (g *ICEGatherer) getSelectedCandidatePairStats() (ICECandidatePairStats, bool) { + agent := g.getAgent() + if agent == nil { + return ICECandidatePairStats{}, false + } + + selectedCandidatePairStats, isAvailable := agent.GetSelectedCandidatePairStats() + if !isAvailable { + return ICECandidatePairStats{}, false + } + + stats, err := toICECandidatePairStats(selectedCandidatePairStats) + if err != nil { + g.log.Error(err.Error()) + + return ICECandidatePairStats{}, false + } + + return stats, true +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/icegathererstate.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/icegathererstate.go similarity index 89% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/icegathererstate.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/icegathererstate.go index b90acd33e..26966dd8a 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/icegathererstate.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/icegathererstate.go @@ -11,9 +11,12 @@ import ( type ICEGathererState uint32 const ( + // ICEGathererStateUnknown is the enum's zero-value. + ICEGathererStateUnknown ICEGathererState = iota + // ICEGathererStateNew indicates object has been created but // gather() has not been called. - ICEGathererStateNew ICEGathererState = iota + 1 + ICEGathererStateNew // ICEGathererStateGathering indicates gather() has been called, // and the ICEGatherer is in the process of gathering candidates. @@ -38,7 +41,7 @@ func (s ICEGathererState) String() string { case ICEGathererStateClosed: return "closed" default: - return unknownStr + return ErrUnknownType.Error() } } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/icegatheringstate.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/icegatheringstate.go similarity index 89% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/icegatheringstate.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/icegatheringstate.go index 1925dddbf..2878277b1 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/icegatheringstate.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/icegatheringstate.go @@ -7,10 +7,13 @@ package webrtc type ICEGatheringState int const ( + // ICEGatheringStateUnknown is the enum's zero-value. + ICEGatheringStateUnknown ICEGatheringState = iota + // ICEGatheringStateNew indicates that any of the ICETransports are // in the "new" gathering state and none of the transports are in the // "gathering" state, or there are no transports. - ICEGatheringStateNew ICEGatheringState = iota + 1 + ICEGatheringStateNew // ICEGatheringStateGathering indicates that any of the ICETransports // are in the "gathering" state. @@ -28,7 +31,7 @@ const ( iceGatheringStateCompleteStr = "complete" ) -// NewICEGatheringState takes a string and converts it to ICEGatheringState +// NewICEGatheringState takes a string and converts it to ICEGatheringState. func NewICEGatheringState(raw string) ICEGatheringState { switch raw { case iceGatheringStateNewStr: @@ -38,7 +41,7 @@ func NewICEGatheringState(raw string) ICEGatheringState { case iceGatheringStateCompleteStr: return ICEGatheringStateComplete default: - return ICEGatheringState(Unknown) + return ICEGatheringStateUnknown } } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/icegatheroptions.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/icegatheroptions.go similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/icegatheroptions.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/icegatheroptions.go diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/icemux.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/icemux.go similarity index 96% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/icemux.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/icemux.go index 1bae31310..4f7ecb3f3 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/icemux.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/icemux.go @@ -6,7 +6,7 @@ package webrtc import ( "net" - "github.com/pion/ice/v2" + "github.com/pion/ice/v4" "github.com/pion/logging" ) diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/iceparameters.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/iceparameters.go similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/iceparameters.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/iceparameters.go diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/iceprotocol.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/iceprotocol.go similarity index 79% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/iceprotocol.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/iceprotocol.go index 3582b6830..8362e93d4 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/iceprotocol.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/iceprotocol.go @@ -13,8 +13,11 @@ import ( type ICEProtocol int const ( + // ICEProtocolUnknown is the enum's zero-value. + ICEProtocolUnknown ICEProtocol = iota + // ICEProtocolUDP indicates the URL uses a UDP transport. - ICEProtocolUDP ICEProtocol = iota + 1 + ICEProtocolUDP // ICEProtocolTCP indicates the URL uses a TCP transport. ICEProtocolTCP @@ -26,7 +29,7 @@ const ( iceProtocolTCPStr = "tcp" ) -// NewICEProtocol takes a string and converts it to ICEProtocol +// NewICEProtocol takes a string and converts it to ICEProtocol. func NewICEProtocol(raw string) (ICEProtocol, error) { switch { case strings.EqualFold(iceProtocolUDPStr, raw): @@ -34,7 +37,7 @@ func NewICEProtocol(raw string) (ICEProtocol, error) { case strings.EqualFold(iceProtocolTCPStr, raw): return ICEProtocolTCP, nil default: - return ICEProtocol(Unknown), fmt.Errorf("%w: %s", errICEProtocolUnknown, raw) + return ICEProtocolUnknown, fmt.Errorf("%w: %s", errICEProtocolUnknown, raw) } } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/icerole.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/icerole.go similarity index 75% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/icerole.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/icerole.go index 99268bace..59ac9af54 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/icerole.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/icerole.go @@ -8,11 +8,14 @@ package webrtc type ICERole int const ( + // ICERoleUnknown is the enum's zero-value. + ICERoleUnknown ICERole = iota + // ICERoleControlling indicates that the ICE agent that is responsible // for selecting the final choice of candidate pairs and signaling them // through STUN and an updated offer, if needed. In any session, one agent // is always controlling. The other is the controlled agent. - ICERoleControlling ICERole = iota + 1 + ICERoleControlling // ICERoleControlled indicates that an ICE agent that waits for the // controlling agent to select the final choice of candidate pairs. @@ -32,7 +35,7 @@ func newICERole(raw string) ICERole { case iceRoleControlledStr: return ICERoleControlled default: - return ICERole(Unknown) + return ICERoleUnknown } } @@ -46,3 +49,15 @@ func (t ICERole) String() string { return ErrUnknownType.Error() } } + +// MarshalText implements encoding.TextMarshaler. +func (t ICERole) MarshalText() ([]byte, error) { + return []byte(t.String()), nil +} + +// UnmarshalText implements encoding.TextUnmarshaler. +func (t *ICERole) UnmarshalText(b []byte) error { + *t = newICERole(string(b)) + + return nil +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/iceserver.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/iceserver.go similarity index 89% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/iceserver.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/iceserver.go index 35d231fd5..32a368541 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/iceserver.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/iceserver.go @@ -9,8 +9,8 @@ package webrtc import ( "encoding/json" - "github.com/pion/stun" - "github.com/pion/webrtc/v3/pkg/rtcerr" + "github.com/pion/stun/v3" + "github.com/pion/webrtc/v4/pkg/rtcerr" ) // ICEServer describes a single STUN and TURN server that can be used by @@ -28,10 +28,11 @@ func (s ICEServer) parseURL(i int) (*stun.URI, error) { func (s ICEServer) validate() error { _, err := s.urls() + return err } -func (s ICEServer) urls() ([]*stun.URI, error) { +func (s ICEServer) urls() ([]*stun.URI, error) { //nolint:cyclop urls := []*stun.URI{} for i := range s.URLs { @@ -85,6 +86,7 @@ func iceserverUnmarshalUrls(val interface{}) (*[]string, error) { return nil, errInvalidICEServer } } + return &out, nil } @@ -101,14 +103,15 @@ func iceserverUnmarshalOauth(val interface{}) (*OAuthCredential, error) { if !ok { return nil, errInvalidICEServer } + return &OAuthCredential{ MACKey: MACKey, AccessToken: AccessToken, }, nil } -func (s *ICEServer) iceserverUnmarshalFields(m map[string]interface{}) error { - if val, ok := m["urls"]; ok { +func (s *ICEServer) iceserverUnmarshalFields(fields map[string]interface{}) error { //nolint:cyclop + if val, ok := fields["urls"]; ok { u, err := iceserverUnmarshalUrls(val) if err != nil { return err @@ -118,13 +121,13 @@ func (s *ICEServer) iceserverUnmarshalFields(m map[string]interface{}) error { s.URLs = []string{} } - if val, ok := m["username"]; ok { + if val, ok := fields["username"]; ok { s.Username, ok = val.(string) if !ok { return errInvalidICEServer } } - if val, ok := m["credentialType"]; ok { + if val, ok := fields["credentialType"]; ok { ct, ok := val.(string) if !ok { return errInvalidICEServer @@ -137,7 +140,7 @@ func (s *ICEServer) iceserverUnmarshalFields(m map[string]interface{}) error { } else { s.CredentialType = ICECredentialTypePassword } - if val, ok := m["credential"]; ok { + if val, ok := fields["credential"]; ok { switch s.CredentialType { case ICECredentialTypePassword: s.Credential = val @@ -151,10 +154,11 @@ func (s *ICEServer) iceserverUnmarshalFields(m map[string]interface{}) error { return errInvalidICECredentialTypeString } } + return nil } -// UnmarshalJSON parses the JSON-encoded data and stores the result +// UnmarshalJSON parses the JSON-encoded data and stores the result. func (s *ICEServer) UnmarshalJSON(b []byte) error { var tmp interface{} err := json.Unmarshal(b, &tmp) @@ -164,10 +168,11 @@ func (s *ICEServer) UnmarshalJSON(b []byte) error { if m, ok := tmp.(map[string]interface{}); ok { return s.iceserverUnmarshalFields(m) } + return errInvalidICEServer } -// MarshalJSON returns the JSON encoding +// MarshalJSON returns the JSON encoding. func (s ICEServer) MarshalJSON() ([]byte, error) { m := make(map[string]interface{}) m["urls"] = s.URLs @@ -178,5 +183,6 @@ func (s ICEServer) MarshalJSON() ([]byte, error) { m["credential"] = s.Credential } m["credentialType"] = s.CredentialType + return json.Marshal(m) } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/iceserver_js.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/iceserver_js.go similarity index 97% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/iceserver_js.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/iceserver_js.go index e4061fa5f..2f293dde0 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/iceserver_js.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/iceserver_js.go @@ -9,7 +9,7 @@ package webrtc import ( "errors" - "github.com/pion/ice/v2" + "github.com/pion/ice/v4" ) // ICEServer describes a single STUN and TURN server that can be used by diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/icetransport.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/icetransport.go similarity index 70% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/icetransport.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/icetransport.go index f3b6925c8..f8130e100 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/icetransport.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/icetransport.go @@ -13,9 +13,10 @@ import ( "sync/atomic" "time" - "github.com/pion/ice/v2" + "github.com/pion/ice/v4" "github.com/pion/logging" - "github.com/pion/webrtc/v3/internal/mux" + "github.com/pion/webrtc/v4/internal/mux" + "github.com/pion/webrtc/v4/internal/util" ) // ICETransport allows an application access to information about the ICE @@ -35,7 +36,6 @@ type ICETransport struct { conn *ice.Conn mux *mux.Mux - ctx context.Context ctxCancel func() loggerFactory logging.LoggerFactory @@ -44,7 +44,7 @@ type ICETransport struct { } // GetSelectedCandidatePair returns the selected candidate pair on which packets are sent -// if there is no selected pair nil is returned +// if there is no selected pair nil is returned. func (t *ICETransport) GetSelectedCandidatePair() (*ICECandidatePair, error) { agent := t.gatherer.getAgent() if agent == nil { @@ -56,17 +56,23 @@ func (t *ICETransport) GetSelectedCandidatePair() (*ICECandidatePair, error) { return nil, err } - local, err := newICECandidateFromICE(icePair.Local) + local, err := newICECandidateFromICE(icePair.Local, "", 0) if err != nil { return nil, err } - remote, err := newICECandidateFromICE(icePair.Remote) + remote, err := newICECandidateFromICE(icePair.Remote, "", 0) if err != nil { return nil, err } - return &ICECandidatePair{Local: &local, Remote: &remote}, nil + return NewICECandidatePair(&local, &remote), nil +} + +// GetSelectedCandidatePairStats returns the selected candidate pair stats on which packets are sent +// if there is no selected pair empty stats, false is returned to indicate stats not available. +func (t *ICETransport) GetSelectedCandidatePairStats() (ICECandidatePairStats, bool) { + return t.gatherer.getSelectedCandidatePairStats() } // NewICETransport creates a new NewICETransport. @@ -77,11 +83,12 @@ func NewICETransport(gatherer *ICEGatherer, loggerFactory logging.LoggerFactory) log: loggerFactory.NewLogger("ortc"), } iceTransport.setState(ICETransportStateNew) + return iceTransport } // Start incoming connectivity checks based on its configured role. -func (t *ICETransport) Start(gatherer *ICEGatherer, params ICEParameters, role *ICERole) error { +func (t *ICETransport) Start(gatherer *ICEGatherer, params ICEParameters, role *ICERole) error { //nolint:cyclop t.lock.Lock() defer t.lock.Unlock() @@ -111,9 +118,10 @@ func (t *ICETransport) Start(gatherer *ICEGatherer, params ICEParameters, role * return err } if err := agent.OnSelectedCandidatePairChange(func(local, remote ice.Candidate) { - candidates, err := newICECandidatesFromICE([]ice.Candidate{local, remote}) + candidates, err := newICECandidatesFromICE([]ice.Candidate{local, remote}, "", 0) if err != nil { t.log.Warnf("%w: %s", errICECandiatesCoversionFailed, err) + return } t.onSelectedCandidatePairChange(NewICECandidatePair(&candidates[0], &candidates[1])) @@ -127,7 +135,8 @@ func (t *ICETransport) Start(gatherer *ICEGatherer, params ICEParameters, role * } t.role = *role - t.ctx, t.ctxCancel = context.WithCancel(context.Background()) + ctx, ctxCancel := context.WithCancel(context.Background()) + t.ctxCancel = ctxCancel // Drop the lock here to allow ICE candidates to be // added so that the agent can complete a connection @@ -137,12 +146,12 @@ func (t *ICETransport) Start(gatherer *ICEGatherer, params ICEParameters, role * var err error switch *role { case ICERoleControlling: - iceConn, err = agent.Dial(t.ctx, + iceConn, err = agent.Dial(ctx, params.UsernameFragment, params.Password) case ICERoleControlled: - iceConn, err = agent.Accept(t.ctx, + iceConn, err = agent.Accept(ctx, params.UsernameFragment, params.Password) @@ -156,11 +165,15 @@ func (t *ICETransport) Start(gatherer *ICEGatherer, params ICEParameters, role * return err } + if t.State() == ICETransportStateClosed { + return errICETransportClosed + } + t.conn = iceConn config := mux.Config{ Conn: t.conn, - BufferSize: int(t.gatherer.api.settingEngine.getReceiveMTU()), + BufferSize: int(t.gatherer.api.settingEngine.getReceiveMTU()), //nolint:gosec // G115 LoggerFactory: t.loggerFactory, } t.mux = mux.NewMux(config) @@ -169,7 +182,7 @@ func (t *ICETransport) Start(gatherer *ICEGatherer, params ICEParameters, role * } // restart is not exposed currently because ORTC has users create a whole new ICETransport -// so for now lets keep it private so we don't cause ORTC users to depend on non-standard APIs +// so for now lets keep it private so we don't cause ORTC users to depend on non-standard APIs. func (t *ICETransport) restart() error { t.lock.Lock() defer t.lock.Unlock() @@ -179,33 +192,64 @@ func (t *ICETransport) restart() error { return fmt.Errorf("%w: unable to restart ICETransport", errICEAgentNotExist) } - if err := agent.Restart(t.gatherer.api.settingEngine.candidates.UsernameFragment, t.gatherer.api.settingEngine.candidates.Password); err != nil { + if err := agent.Restart( + t.gatherer.api.settingEngine.candidates.UsernameFragment, + t.gatherer.api.settingEngine.candidates.Password, + ); err != nil { return err } + return t.gatherer.Gather() } // Stop irreversibly stops the ICETransport. func (t *ICETransport) Stop() error { - t.lock.Lock() - defer t.lock.Unlock() + return t.stop(false /* shouldGracefullyClose */) +} +// GracefulStop irreversibly stops the ICETransport. It also waits +// for any goroutines it started to complete. This is only safe to call outside of +// ICETransport callbacks or if in a callback, in its own goroutine. +func (t *ICETransport) GracefulStop() error { + return t.stop(true /* shouldGracefullyClose */) +} + +func (t *ICETransport) stop(shouldGracefullyClose bool) error { + t.lock.Lock() t.setState(ICETransportStateClosed) if t.ctxCancel != nil { t.ctxCancel() } - if t.mux != nil { - return t.mux.Close() - } else if t.gatherer != nil { - return t.gatherer.Close() + // mux and gatherer can only be set when ICETransport.State != Closed. + mux := t.mux + gatherer := t.gatherer + t.lock.Unlock() + + if mux != nil { + var closeErrs []error + if shouldGracefullyClose && gatherer != nil { + // we can't access icegatherer/icetransport.Close via + // mux's net.Conn Close so we call it earlier here. + closeErrs = append(closeErrs, gatherer.GracefulClose()) + } + closeErrs = append(closeErrs, mux.Close()) + + return util.FlattenErrs(closeErrs) + } else if gatherer != nil { + if shouldGracefullyClose { + return gatherer.GracefulClose() + } + + return gatherer.Close() } + return nil } // OnSelectedCandidatePairChange sets a handler that is invoked when a new -// ICE candidate pair is selected +// ICE candidate pair is selected. func (t *ICETransport) OnSelectedCandidatePairChange(f func(*ICECandidatePair)) { t.onSelectedCandidatePairChangeHandler.Store(f) } @@ -254,7 +298,7 @@ func (t *ICETransport) SetRemoteCandidates(remoteCandidates []ICECandidate) erro } for _, c := range remoteCandidates { - i, err := c.toICE() + i, err := c.ToICE() if err != nil { return err } @@ -273,8 +317,8 @@ func (t *ICETransport) AddRemoteCandidate(remoteCandidate *ICECandidate) error { defer t.lock.RUnlock() var ( - c ice.Candidate - err error + candidate ice.Candidate + err error ) if err = t.ensureGatherer(); err != nil { @@ -282,7 +326,7 @@ func (t *ICETransport) AddRemoteCandidate(remoteCandidate *ICECandidate) error { } if remoteCandidate != nil { - if c, err = remoteCandidate.toICE(); err != nil { + if candidate, err = remoteCandidate.ToICE(); err != nil { return err } } @@ -292,7 +336,7 @@ func (t *ICETransport) AddRemoteCandidate(remoteCandidate *ICECandidate) error { return fmt.Errorf("%w: unable to add remote candidates", errICEAgentNotExist) } - return agent.AddRemoteCandidate(c) + return agent.AddRemoteCandidate(candidate) } // State returns the current ice transport state. @@ -300,9 +344,42 @@ func (t *ICETransport) State() ICETransportState { if v, ok := t.state.Load().(ICETransportState); ok { return v } + return ICETransportState(0) } +// GetLocalParameters returns an IceParameters object which provides information +// uniquely identifying the local peer for the duration of the ICE session. +func (t *ICETransport) GetLocalParameters() (ICEParameters, error) { + if err := t.ensureGatherer(); err != nil { + return ICEParameters{}, err + } + + return t.gatherer.GetLocalParameters() +} + +// GetRemoteParameters returns an IceParameters object which provides information +// uniquely identifying the remote peer for the duration of the ICE session. +func (t *ICETransport) GetRemoteParameters() (ICEParameters, error) { + t.lock.Lock() + defer t.lock.Unlock() + + agent := t.gatherer.getAgent() + if agent == nil { + return ICEParameters{}, fmt.Errorf("%w: unable to get remote parameters", errICEAgentNotExist) + } + + uFrag, uPwd, err := agent.GetRemoteUserCredentials() + if err != nil { + return ICEParameters{}, fmt.Errorf("%w: unable to get remote parameters", err) + } + + return ICEParameters{ + UsernameFragment: uFrag, + Password: uPwd, + }, nil +} + func (t *ICETransport) setState(i ICETransportState) { t.state.Store(i) } @@ -310,6 +387,7 @@ func (t *ICETransport) setState(i ICETransportState) { func (t *ICETransport) newEndpoint(f mux.MatchFunc) *mux.Endpoint { t.lock.Lock() defer t.lock.Unlock() + return t.mux.NewEndpoint(f) } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/icetransport_js.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/icetransport_js.go similarity index 88% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/icetransport_js.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/icetransport_js.go index 3ca577b10..29c69ad7a 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/icetransport_js.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/icetransport_js.go @@ -15,6 +15,11 @@ type ICETransport struct { underlying js.Value } +// JSValue returns the underlying RTCIceTransport +func (t *ICETransport) JSValue() js.Value { + return t.underlying +} + // GetSelectedCandidatePair returns the selected candidate pair on which packets are sent // if there is no selected pair nil is returned func (t *ICETransport) GetSelectedCandidatePair() (*ICECandidatePair, error) { diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/icetransportpolicy.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/icetransportpolicy.go similarity index 89% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/icetransportpolicy.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/icetransportpolicy.go index a2629fdab..39a1fa364 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/icetransportpolicy.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/icetransportpolicy.go @@ -11,7 +11,7 @@ import ( // permitted candidates. Only these candidates are used for connectivity checks. type ICETransportPolicy int -// ICEGatherPolicy is the ORTC equivalent of ICETransportPolicy +// ICEGatherPolicy is the ORTC equivalent of ICETransportPolicy. type ICEGatherPolicy = ICETransportPolicy const ( @@ -29,15 +29,13 @@ const ( iceTransportPolicyAllStr = "all" ) -// NewICETransportPolicy takes a string and converts it to ICETransportPolicy +// NewICETransportPolicy takes a string and converts it to ICETransportPolicy. func NewICETransportPolicy(raw string) ICETransportPolicy { switch raw { case iceTransportPolicyRelayStr: return ICETransportPolicyRelay - case iceTransportPolicyAllStr: - return ICETransportPolicyAll default: - return ICETransportPolicy(Unknown) + return ICETransportPolicyAll } } @@ -52,17 +50,18 @@ func (t ICETransportPolicy) String() string { } } -// UnmarshalJSON parses the JSON-encoded data and stores the result +// UnmarshalJSON parses the JSON-encoded data and stores the result. func (t *ICETransportPolicy) UnmarshalJSON(b []byte) error { var val string if err := json.Unmarshal(b, &val); err != nil { return err } *t = NewICETransportPolicy(val) + return nil } -// MarshalJSON returns the JSON encoding +// MarshalJSON returns the JSON encoding. func (t ICETransportPolicy) MarshalJSON() ([]byte, error) { return json.Marshal(t.String()) } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/icetransportstate.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/icetransportstate.go similarity index 64% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/icetransportstate.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/icetransportstate.go index 4edbf0f47..714d5fe61 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/icetransportstate.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/icetransportstate.go @@ -3,15 +3,18 @@ package webrtc -import "github.com/pion/ice/v2" +import "github.com/pion/ice/v4" // ICETransportState represents the current state of the ICE transport. type ICETransportState int const ( + // ICETransportStateUnknown is the enum's zero-value. + ICETransportStateUnknown ICETransportState = iota + // ICETransportStateNew indicates the ICETransport is waiting // for remote candidates to be supplied. - ICETransportStateNew = iota + 1 + ICETransportStateNew // ICETransportStateChecking indicates the ICETransport has // received at least one remote candidate, and a local and remote @@ -46,24 +49,55 @@ const ( ICETransportStateClosed ) +const ( + iceTransportStateNewStr = "new" + iceTransportStateCheckingStr = "checking" + iceTransportStateConnectedStr = "connected" + iceTransportStateCompletedStr = "completed" + iceTransportStateFailedStr = "failed" + iceTransportStateDisconnectedStr = "disconnected" + iceTransportStateClosedStr = "closed" +) + +func newICETransportState(raw string) ICETransportState { + switch raw { + case iceTransportStateNewStr: + return ICETransportStateNew + case iceTransportStateCheckingStr: + return ICETransportStateChecking + case iceTransportStateConnectedStr: + return ICETransportStateConnected + case iceTransportStateCompletedStr: + return ICETransportStateCompleted + case iceTransportStateFailedStr: + return ICETransportStateFailed + case iceTransportStateDisconnectedStr: + return ICETransportStateDisconnected + case iceTransportStateClosedStr: + return ICETransportStateClosed + default: + return ICETransportStateUnknown + } +} + func (c ICETransportState) String() string { switch c { case ICETransportStateNew: - return "new" + return iceTransportStateNewStr case ICETransportStateChecking: - return "checking" + return iceTransportStateCheckingStr case ICETransportStateConnected: - return "connected" + return iceTransportStateConnectedStr case ICETransportStateCompleted: - return "completed" + return iceTransportStateCompletedStr case ICETransportStateFailed: - return "failed" + return iceTransportStateFailedStr case ICETransportStateDisconnected: - return "disconnected" + return iceTransportStateDisconnectedStr case ICETransportStateClosed: - return "closed" + return iceTransportStateClosedStr default: - return unknownStr + return ErrUnknownType.Error() } } @@ -84,7 +118,7 @@ func newICETransportStateFromICE(i ice.ConnectionState) ICETransportState { case ice.ConnectionStateClosed: return ICETransportStateClosed default: - return ICETransportState(Unknown) + return ICETransportStateUnknown } } @@ -105,6 +139,18 @@ func (c ICETransportState) toICE() ice.ConnectionState { case ICETransportStateClosed: return ice.ConnectionStateClosed default: - return ice.ConnectionState(Unknown) + return ice.ConnectionStateUnknown } } + +// MarshalText implements encoding.TextMarshaler. +func (c ICETransportState) MarshalText() ([]byte, error) { + return []byte(c.String()), nil +} + +// UnmarshalText implements encoding.TextUnmarshaler. +func (c *ICETransportState) UnmarshalText(b []byte) error { + *c = newICETransportState(string(b)) + + return nil +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/interceptor.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/interceptor.go similarity index 56% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/interceptor.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/interceptor.go index 85232f35d..d2df622f9 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/interceptor.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/interceptor.go @@ -12,6 +12,7 @@ import ( "github.com/pion/interceptor" "github.com/pion/interceptor/pkg/nack" "github.com/pion/interceptor/pkg/report" + "github.com/pion/interceptor/pkg/rfc8888" "github.com/pion/interceptor/pkg/twcc" "github.com/pion/rtp" "github.com/pion/sdp/v3" @@ -29,10 +30,14 @@ func RegisterDefaultInterceptors(mediaEngine *MediaEngine, interceptorRegistry * return err } + if err := ConfigureSimulcastExtensionHeaders(mediaEngine); err != nil { + return err + } + return ConfigureTWCCSender(mediaEngine, interceptorRegistry) } -// ConfigureRTCPReports will setup everything necessary for generating Sender and Receiver Reports +// ConfigureRTCPReports will setup everything necessary for generating Sender and Receiver Reports. func ConfigureRTCPReports(interceptorRegistry *interceptor.Registry) error { reciver, err := report.NewReceiverInterceptor() if err != nil { @@ -46,6 +51,7 @@ func ConfigureRTCPReports(interceptorRegistry *interceptor.Registry) error { interceptorRegistry.Add(reciver) interceptorRegistry.Add(sender) + return nil } @@ -65,17 +71,22 @@ func ConfigureNack(mediaEngine *MediaEngine, interceptorRegistry *interceptor.Re mediaEngine.RegisterFeedback(RTCPFeedback{Type: "nack", Parameter: "pli"}, RTPCodecTypeVideo) interceptorRegistry.Add(responder) interceptorRegistry.Add(generator) + return nil } // ConfigureTWCCHeaderExtensionSender will setup everything necessary for adding // a TWCC header extension to outgoing RTP packets. This will allow the remote peer to generate TWCC reports. func ConfigureTWCCHeaderExtensionSender(mediaEngine *MediaEngine, interceptorRegistry *interceptor.Registry) error { - if err := mediaEngine.RegisterHeaderExtension(RTPHeaderExtensionCapability{URI: sdp.TransportCCURI}, RTPCodecTypeVideo); err != nil { + if err := mediaEngine.RegisterHeaderExtension( + RTPHeaderExtensionCapability{URI: sdp.TransportCCURI}, RTPCodecTypeVideo, + ); err != nil { return err } - if err := mediaEngine.RegisterHeaderExtension(RTPHeaderExtensionCapability{URI: sdp.TransportCCURI}, RTPCodecTypeAudio); err != nil { + if err := mediaEngine.RegisterHeaderExtension( + RTPHeaderExtensionCapability{URI: sdp.TransportCCURI}, RTPCodecTypeAudio, + ); err != nil { return err } @@ -85,18 +96,24 @@ func ConfigureTWCCHeaderExtensionSender(mediaEngine *MediaEngine, interceptorReg } interceptorRegistry.Add(i) + return nil } // ConfigureTWCCSender will setup everything necessary for generating TWCC reports. +// This must be called after registering codecs with the MediaEngine. func ConfigureTWCCSender(mediaEngine *MediaEngine, interceptorRegistry *interceptor.Registry) error { mediaEngine.RegisterFeedback(RTCPFeedback{Type: TypeRTCPFBTransportCC}, RTPCodecTypeVideo) - if err := mediaEngine.RegisterHeaderExtension(RTPHeaderExtensionCapability{URI: sdp.TransportCCURI}, RTPCodecTypeVideo); err != nil { + if err := mediaEngine.RegisterHeaderExtension( + RTPHeaderExtensionCapability{URI: sdp.TransportCCURI}, RTPCodecTypeVideo, + ); err != nil { return err } mediaEngine.RegisterFeedback(RTCPFeedback{Type: TypeRTCPFBTransportCC}, RTPCodecTypeAudio) - if err := mediaEngine.RegisterHeaderExtension(RTPHeaderExtensionCapability{URI: sdp.TransportCCURI}, RTPCodecTypeAudio); err != nil { + if err := mediaEngine.RegisterHeaderExtension( + RTPHeaderExtensionCapability{URI: sdp.TransportCCURI}, RTPCodecTypeAudio, + ); err != nil { return err } @@ -106,9 +123,43 @@ func ConfigureTWCCSender(mediaEngine *MediaEngine, interceptorRegistry *intercep } interceptorRegistry.Add(generator) + return nil } +// ConfigureCongestionControlFeedback registers congestion control feedback as +// defined in RFC 8888 (https://datatracker.ietf.org/doc/rfc8888/) +func ConfigureCongestionControlFeedback(mediaEngine *MediaEngine, interceptorRegistry *interceptor.Registry) error { + mediaEngine.RegisterFeedback(RTCPFeedback{Type: TypeRTCPFBACK, Parameter: "ccfb"}, RTPCodecTypeVideo) + mediaEngine.RegisterFeedback(RTCPFeedback{Type: TypeRTCPFBACK, Parameter: "ccfb"}, RTPCodecTypeAudio) + generator, err := rfc8888.NewSenderInterceptor() + if err != nil { + return err + } + interceptorRegistry.Add(generator) + + return nil +} + +// ConfigureSimulcastExtensionHeaders enables the RTP Extension Headers needed for Simulcast. +func ConfigureSimulcastExtensionHeaders(mediaEngine *MediaEngine) error { + if err := mediaEngine.RegisterHeaderExtension( + RTPHeaderExtensionCapability{URI: sdp.SDESMidURI}, RTPCodecTypeVideo, + ); err != nil { + return err + } + + if err := mediaEngine.RegisterHeaderExtension( + RTPHeaderExtensionCapability{URI: sdp.SDESRTPStreamIDURI}, RTPCodecTypeVideo, + ); err != nil { + return err + } + + return mediaEngine.RegisterHeaderExtension( + RTPHeaderExtensionCapability{URI: sdp.SDESRepairRTPStreamIDURI}, RTPCodecTypeVideo, + ) +} + type interceptorToTrackLocalWriter struct{ interceptor atomic.Value } // interceptor.RTPWriter } func (i *interceptorToTrackLocalWriter) WriteRTP(header *rtp.Header, payload []byte) (int, error) { @@ -128,7 +179,14 @@ func (i *interceptorToTrackLocalWriter) Write(b []byte) (int, error) { return i.WriteRTP(&packet.Header, packet.Payload) } -func createStreamInfo(id string, ssrc SSRC, payloadType PayloadType, codec RTPCodecCapability, webrtcHeaderExtensions []RTPHeaderExtensionParameter) *interceptor.StreamInfo { +//nolint:unparam +func createStreamInfo( + id string, + ssrc, ssrcRTX, ssrcFEC SSRC, + payloadType, payloadTypeRTX, payloadTypeFEC PayloadType, + codec RTPCodecCapability, + webrtcHeaderExtensions []RTPHeaderExtensionParameter, +) *interceptor.StreamInfo { headerExtensions := make([]interceptor.RTPHeaderExtension, 0, len(webrtcHeaderExtensions)) for _, h := range webrtcHeaderExtensions { headerExtensions = append(headerExtensions, interceptor.RTPHeaderExtension{ID: h.ID, URI: h.URI}) @@ -140,15 +198,19 @@ func createStreamInfo(id string, ssrc SSRC, payloadType PayloadType, codec RTPCo } return &interceptor.StreamInfo{ - ID: id, - Attributes: interceptor.Attributes{}, - SSRC: uint32(ssrc), - PayloadType: uint8(payloadType), - RTPHeaderExtensions: headerExtensions, - MimeType: codec.MimeType, - ClockRate: codec.ClockRate, - Channels: codec.Channels, - SDPFmtpLine: codec.SDPFmtpLine, - RTCPFeedback: feedbacks, + ID: id, + Attributes: interceptor.Attributes{}, + SSRC: uint32(ssrc), + SSRCRetransmission: uint32(ssrcRTX), + SSRCForwardErrorCorrection: uint32(ssrcFEC), + PayloadType: uint8(payloadType), + PayloadTypeRetransmission: uint8(payloadTypeRTX), + PayloadTypeForwardErrorCorrection: uint8(payloadTypeFEC), + RTPHeaderExtensions: headerExtensions, + MimeType: codec.MimeType, + ClockRate: codec.ClockRate, + Channels: codec.Channels, + SDPFmtpLine: codec.SDPFmtpLine, + RTCPFeedback: feedbacks, } } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/internal/fmtp/av1.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/internal/fmtp/av1.go new file mode 100644 index 000000000..d7eab4d29 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/internal/fmtp/av1.go @@ -0,0 +1,42 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + +package fmtp + +type av1FMTP struct { + parameters map[string]string +} + +func (h *av1FMTP) MimeType() string { + return "video/av1" +} + +func (h *av1FMTP) Match(b FMTP) bool { + c, ok := b.(*av1FMTP) + if !ok { + return false + } + + // RTP Payload Format For AV1 (v1.0) + // https://aomediacodec.github.io/av1-rtp-spec/ + // If the profile parameter is not present, it MUST be inferred to be 0 (“Main” profile). + hProfile, ok := h.parameters["profile"] + if !ok { + hProfile = "0" + } + cProfile, ok := c.parameters["profile"] + if !ok { + cProfile = "0" + } + if hProfile != cProfile { + return false + } + + return true +} + +func (h *av1FMTP) Parameter(key string) (string, bool) { + v, ok := h.parameters[key] + + return v, ok +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/internal/fmtp/fmtp.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/internal/fmtp/fmtp.go new file mode 100644 index 000000000..71ceb48df --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/internal/fmtp/fmtp.go @@ -0,0 +1,185 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + +// Package fmtp implements per codec parsing of fmtp lines +package fmtp + +import ( + "strings" +) + +func defaultClockRate(mimeType string) uint32 { + defaults := map[string]uint32{ + "audio/opus": 48000, + "audio/pcmu": 8000, + "audio/pcma": 8000, + } + + if def, ok := defaults[strings.ToLower(mimeType)]; ok { + return def + } + + return 90000 +} + +func defaultChannels(mimeType string) uint16 { + defaults := map[string]uint16{ + "audio/opus": 2, + } + + if def, ok := defaults[strings.ToLower(mimeType)]; ok { + return def + } + + return 0 +} + +func parseParameters(line string) map[string]string { + parameters := make(map[string]string) + + for _, p := range strings.Split(line, ";") { + pp := strings.SplitN(strings.TrimSpace(p), "=", 2) + key := strings.ToLower(pp[0]) + var value string + if len(pp) > 1 { + value = pp[1] + } + parameters[key] = value + } + + return parameters +} + +// ClockRateEqual checks whether two clock rates are equal. +func ClockRateEqual(mimeType string, valA, valB uint32) bool { + // Lots of users use formats without setting clock rate or channels. + // In this case, use default values. + // It would be better to remove this exception in a future major release. + if valA == 0 { + valA = defaultClockRate(mimeType) + } + if valB == 0 { + valB = defaultClockRate(mimeType) + } + + return valA == valB +} + +// ChannelsEqual checks whether two channels are equal. +func ChannelsEqual(mimeType string, valA, valB uint16) bool { + // Lots of users use formats without setting clock rate or channels. + // In this case, use default values. + // It would be better to remove this exception in a future major release. + if valA == 0 { + valA = defaultChannels(mimeType) + } + if valB == 0 { + valB = defaultChannels(mimeType) + } + + // RFC8866: channel count "is OPTIONAL and may be omitted + // if the number of channels is one". + if valA == 0 { + valA = 1 + } + if valB == 0 { + valB = 1 + } + + return valA == valB +} + +func paramsEqual(valA, valB map[string]string) bool { + for k, v := range valA { + if vb, ok := valB[k]; ok && !strings.EqualFold(vb, v) { + return false + } + } + + for k, v := range valB { + if va, ok := valA[k]; ok && !strings.EqualFold(va, v) { + return false + } + } + + return true +} + +// FMTP interface for implementing custom +// FMTP parsers based on MimeType. +type FMTP interface { + // MimeType returns the MimeType associated with + // the fmtp + MimeType() string + // Match compares two fmtp descriptions for + // compatibility based on the MimeType + Match(f FMTP) bool + // Parameter returns a value for the associated key + // if contained in the parsed fmtp string + Parameter(key string) (string, bool) +} + +// Parse parses an fmtp string based on the MimeType. +func Parse(mimeType string, clockRate uint32, channels uint16, line string) FMTP { + var fmtp FMTP + + parameters := parseParameters(line) + + switch { + case strings.EqualFold(mimeType, "video/h264"): + fmtp = &h264FMTP{ + parameters: parameters, + } + + case strings.EqualFold(mimeType, "video/vp9"): + fmtp = &vp9FMTP{ + parameters: parameters, + } + + case strings.EqualFold(mimeType, "video/av1"): + fmtp = &av1FMTP{ + parameters: parameters, + } + + default: + fmtp = &genericFMTP{ + mimeType: mimeType, + clockRate: clockRate, + channels: channels, + parameters: parameters, + } + } + + return fmtp +} + +type genericFMTP struct { + mimeType string + clockRate uint32 + channels uint16 + parameters map[string]string +} + +func (g *genericFMTP) MimeType() string { + return g.mimeType +} + +// Match returns true if g and b are compatible fmtp descriptions +// The generic implementation is used for MimeTypes that are not defined. +func (g *genericFMTP) Match(b FMTP) bool { + fmtp, ok := b.(*genericFMTP) + if !ok { + return false + } + + return strings.EqualFold(g.mimeType, fmtp.MimeType()) && + ClockRateEqual(g.mimeType, g.clockRate, fmtp.clockRate) && + ChannelsEqual(g.mimeType, g.channels, fmtp.channels) && + paramsEqual(g.parameters, fmtp.parameters) +} + +func (g *genericFMTP) Parameter(key string) (string, bool) { + v, ok := g.parameters[key] + + return v, ok +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/internal/fmtp/h264.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/internal/fmtp/h264.go similarity index 93% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/internal/fmtp/h264.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/internal/fmtp/h264.go index b89b97aa2..0fdaea559 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/internal/fmtp/h264.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/internal/fmtp/h264.go @@ -16,6 +16,7 @@ func profileLevelIDMatches(a, b string) bool { if err != nil || len(bb) < 2 { return false } + return aa[0] == bb[0] && aa[1] == bb[1] } @@ -41,7 +42,7 @@ func (h *h264FMTP) MimeType() string { // apply for the level part of profile-level-id and does not apply // for the other stream properties and capability parameters. func (h *h264FMTP) Match(b FMTP) bool { - c, ok := b.(*h264FMTP) + fmtp, ok := b.(*h264FMTP) if !ok { return false } @@ -51,7 +52,7 @@ func (h *h264FMTP) Match(b FMTP) bool { if !hok { return false } - cpmode, cok := c.parameters["packetization-mode"] + cpmode, cok := fmtp.parameters["packetization-mode"] if !cok { return false } @@ -66,7 +67,7 @@ func (h *h264FMTP) Match(b FMTP) bool { return false } - cplid, cok := c.parameters["profile-level-id"] + cplid, cok := fmtp.parameters["profile-level-id"] if !cok { return false } @@ -80,5 +81,6 @@ func (h *h264FMTP) Match(b FMTP) bool { func (h *h264FMTP) Parameter(key string) (string, bool) { v, ok := h.parameters[key] + return v, ok } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/internal/fmtp/vp9.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/internal/fmtp/vp9.go new file mode 100644 index 000000000..bbbd7f29a --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/internal/fmtp/vp9.go @@ -0,0 +1,42 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + +package fmtp + +type vp9FMTP struct { + parameters map[string]string +} + +func (h *vp9FMTP) MimeType() string { + return "video/vp9" +} + +func (h *vp9FMTP) Match(b FMTP) bool { + c, ok := b.(*vp9FMTP) + if !ok { + return false + } + + // RTP Payload Format for VP9 Video - draft-ietf-payload-vp9-16 + // https://datatracker.ietf.org/doc/html/draft-ietf-payload-vp9-16 + // If no profile-id is present, Profile 0 MUST be inferred + hProfileID, ok := h.parameters["profile-id"] + if !ok { + hProfileID = "0" + } + cProfileID, ok := c.parameters["profile-id"] + if !ok { + cProfileID = "0" + } + if hProfileID != cProfileID { + return false + } + + return true +} + +func (h *vp9FMTP) Parameter(key string) (string, bool) { + v, ok := h.parameters[key] + + return v, ok +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/internal/mux/endpoint.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/internal/mux/endpoint.go similarity index 53% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/internal/mux/endpoint.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/internal/mux/endpoint.go index 3f53d16c5..d1a24c0b6 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/internal/mux/endpoint.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/internal/mux/endpoint.go @@ -9,24 +9,29 @@ import ( "net" "time" - "github.com/pion/ice/v2" - "github.com/pion/transport/v2/packetio" + "github.com/pion/ice/v4" + "github.com/pion/transport/v3/packetio" ) // Endpoint implements net.Conn. It is used to read muxed packets. type Endpoint struct { - mux *Mux - buffer *packetio.Buffer + mux *Mux + buffer *packetio.Buffer + onClose func() } -// Close unregisters the endpoint from the Mux +// Close unregisters the endpoint from the Mux. func (e *Endpoint) Close() (err error) { - err = e.close() - if err != nil { + if e.onClose != nil { + e.onClose() + } + + if err = e.close(); err != nil { return err } e.mux.RemoveEndpoint(e) + return nil } @@ -35,12 +40,20 @@ func (e *Endpoint) close() error { } // Read reads a packet of len(p) bytes from the underlying conn -// that are matched by the associated MuxFunc +// that are matched by the associated MuxFunc. func (e *Endpoint) Read(p []byte) (int, error) { return e.buffer.Read(p) } -// Write writes len(p) bytes to the underlying conn +// ReadFrom reads a packet of len(p) bytes from the underlying conn +// that are matched by the associated MuxFunc. +func (e *Endpoint) ReadFrom(p []byte) (int, net.Addr, error) { + i, err := e.Read(p) + + return i, nil, err +} + +// Write writes len(p) bytes to the underlying conn. func (e *Endpoint) Write(p []byte) (int, error) { n, err := e.mux.nextConn.Write(p) if errors.Is(err, ice.ErrNoCandidatePairs) { @@ -52,27 +65,38 @@ func (e *Endpoint) Write(p []byte) (int, error) { return n, err } -// LocalAddr is a stub +// WriteTo writes len(p) bytes to the underlying conn. +func (e *Endpoint) WriteTo(p []byte, _ net.Addr) (int, error) { + return e.Write(p) +} + +// LocalAddr is a stub. func (e *Endpoint) LocalAddr() net.Addr { return e.mux.nextConn.LocalAddr() } -// RemoteAddr is a stub +// RemoteAddr is a stub. func (e *Endpoint) RemoteAddr() net.Addr { return e.mux.nextConn.RemoteAddr() } -// SetDeadline is a stub +// SetDeadline is a stub. func (e *Endpoint) SetDeadline(time.Time) error { return nil } -// SetReadDeadline is a stub +// SetReadDeadline is a stub. func (e *Endpoint) SetReadDeadline(time.Time) error { return nil } -// SetWriteDeadline is a stub +// SetWriteDeadline is a stub. func (e *Endpoint) SetWriteDeadline(time.Time) error { return nil } + +// SetOnClose is a user set callback that +// will be executed when `Close` is called. +func (e *Endpoint) SetOnClose(onClose func()) { + e.onClose = onClose +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/internal/mux/mux.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/internal/mux/mux.go similarity index 53% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/internal/mux/mux.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/internal/mux/mux.go index 1e167b897..942476897 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/internal/mux/mux.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/internal/mux/mux.go @@ -10,36 +10,44 @@ import ( "net" "sync" - "github.com/pion/ice/v2" + "github.com/pion/ice/v4" "github.com/pion/logging" - "github.com/pion/transport/v2/packetio" + "github.com/pion/transport/v3/packetio" ) -// The maximum amount of data that can be buffered before returning errors. -const maxBufferSize = 1000 * 1000 // 1MB +const ( + // The maximum amount of data that can be buffered before returning errors. + maxBufferSize = 1000 * 1000 // 1MB + + // How many total pending packets can be cached. + maxPendingPackets = 15 +) // Config collects the arguments to mux.Mux construction into -// a single structure +// a single structure. type Config struct { Conn net.Conn BufferSize int LoggerFactory logging.LoggerFactory } -// Mux allows multiplexing +// Mux allows multiplexing. type Mux struct { - lock sync.RWMutex nextConn net.Conn - endpoints map[*Endpoint]MatchFunc bufferSize int - closedCh chan struct{} + lock sync.Mutex + endpoints map[*Endpoint]MatchFunc + isClosed bool - log logging.LeveledLogger + pendingPackets [][]byte + + closedCh chan struct{} + log logging.LeveledLogger } -// NewMux creates a new Mux +// NewMux creates a new Mux. func NewMux(config Config) *Mux { - m := &Mux{ + mux := &Mux{ nextConn: config.Conn, endpoints: make(map[*Endpoint]MatchFunc), bufferSize: config.BufferSize, @@ -47,29 +55,31 @@ func NewMux(config Config) *Mux { log: config.LoggerFactory.NewLogger("mux"), } - go m.readLoop() + go mux.readLoop() - return m + return mux } -// NewEndpoint creates a new Endpoint -func (m *Mux) NewEndpoint(f MatchFunc) *Endpoint { - e := &Endpoint{ +// NewEndpoint creates a new Endpoint. +func (m *Mux) NewEndpoint(matchFunc MatchFunc) *Endpoint { + endpoint := &Endpoint{ mux: m, buffer: packetio.NewBuffer(), } // Set a maximum size of the buffer in bytes. - e.buffer.SetLimitSize(maxBufferSize) + endpoint.buffer.SetLimitSize(maxBufferSize) m.lock.Lock() - m.endpoints[e] = f + m.endpoints[endpoint] = matchFunc m.lock.Unlock() - return e + go m.handlePendingPackets(endpoint, matchFunc) + + return endpoint } -// RemoveEndpoint removes an endpoint from the Mux +// RemoveEndpoint removes an endpoint from the Mux. func (m *Mux) RemoveEndpoint(e *Endpoint) { m.lock.Lock() defer m.lock.Unlock() @@ -82,11 +92,13 @@ func (m *Mux) Close() error { for e := range m.endpoints { if err := e.close(); err != nil { m.lock.Unlock() + return err } delete(m.endpoints, e) } + m.isClosed = true m.lock.Unlock() err := m.nextConn.Close() @@ -113,47 +125,92 @@ func (m *Mux) readLoop() { return case errors.Is(err, io.ErrShortBuffer), errors.Is(err, packetio.ErrTimeout): m.log.Errorf("mux: failed to read from packetio.Buffer %s", err.Error()) + continue case err != nil: m.log.Errorf("mux: ending readLoop packetio.Buffer error %s", err.Error()) + return } if err = m.dispatch(buf[:n]); err != nil { + if errors.Is(err, io.ErrClosedPipe) { + // if the buffer was closed, that's not an error we care to report + return + } m.log.Errorf("mux: ending readLoop dispatch error %s", err.Error()) + return } } } func (m *Mux) dispatch(buf []byte) error { + if len(buf) == 0 { + m.log.Warnf("Warning: mux: unable to dispatch zero length packet") + + return nil + } + var endpoint *Endpoint m.lock.Lock() for e, f := range m.endpoints { if f(buf) { endpoint = e + break } } - m.lock.Unlock() - if endpoint == nil { - if len(buf) > 0 { - m.log.Warnf("Warning: mux: no endpoint for packet starting with %d", buf[0]) - } else { - m.log.Warnf("Warning: mux: no endpoint for zero length packet") + defer m.lock.Unlock() + + if !m.isClosed { + if len(m.pendingPackets) >= maxPendingPackets { + m.log.Warnf( + "Warning: mux: no endpoint for packet starting with %d, not adding to queue size(%d)", + buf[0], //nolint:gosec // G602, false positive? + len(m.pendingPackets), + ) + } else { + m.log.Warnf( + "Warning: mux: no endpoint for packet starting with %d, adding to queue size(%d)", + buf[0], //nolint:gosec // G602, false positive? + len(m.pendingPackets), + ) + m.pendingPackets = append(m.pendingPackets, append([]byte{}, buf...)) + } } + return nil } + m.lock.Unlock() _, err := endpoint.buffer.Write(buf) // Expected when bytes are received faster than the endpoint can process them (#2152, #2180) if errors.Is(err, packetio.ErrFull) { m.log.Infof("mux: endpoint buffer is full, dropping packet") + return nil } return err } + +func (m *Mux) handlePendingPackets(endpoint *Endpoint, matchFunc MatchFunc) { + m.lock.Lock() + defer m.lock.Unlock() + + pendingPackets := make([][]byte, len(m.pendingPackets)) + for _, buf := range m.pendingPackets { + if matchFunc(buf) { + if _, err := endpoint.buffer.Write(buf); err != nil { + m.log.Warnf("Warning: mux: error writing packet to endpoint from pending queue: %s", err) + } + } else { + pendingPackets = append(pendingPackets, buf) //nolint:makezero // todo fix + } + } + m.pendingPackets = pendingPackets +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/internal/mux/muxfunc.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/internal/mux/muxfunc.go similarity index 94% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/internal/mux/muxfunc.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/internal/mux/muxfunc.go index 69c3d14cd..3f3e42928 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/internal/mux/muxfunc.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/internal/mux/muxfunc.go @@ -3,20 +3,21 @@ package mux -// MatchFunc allows custom logic for mapping packets to an Endpoint +// MatchFunc allows custom logic for mapping packets to an Endpoint. type MatchFunc func([]byte) bool -// MatchAll always returns true +// MatchAll always returns true. func MatchAll([]byte) bool { return true } -// MatchRange returns true if the first byte of buf is in [lower..upper] +// MatchRange returns true if the first byte of buf is in [lower..upper]. func MatchRange(lower, upper byte, buf []byte) bool { if len(buf) < 1 { return false } b := buf[0] + return b >= lower && b <= upper } @@ -35,13 +36,13 @@ func MatchRange(lower, upper byte, buf []byte) bool { // +----------------+ // MatchDTLS is a MatchFunc that accepts packets with the first byte in [20..63] -// as defied in RFC7983 +// as defied in RFC7983. func MatchDTLS(b []byte) bool { return MatchRange(20, 63, b) } // MatchSRTPOrSRTCP is a MatchFunc that accepts packets with the first byte in [128..191] -// as defied in RFC7983 +// as defied in RFC7983. func MatchSRTPOrSRTCP(b []byte) bool { return MatchRange(128, 191, b) } @@ -51,15 +52,16 @@ func isRTCP(buf []byte) bool { if len(buf) < 4 { return false } + return buf[1] >= 192 && buf[1] <= 223 } -// MatchSRTP is a MatchFunc that only matches SRTP and not SRTCP +// MatchSRTP is a MatchFunc that only matches SRTP and not SRTCP. func MatchSRTP(buf []byte) bool { return MatchSRTPOrSRTCP(buf) && !isRTCP(buf) } -// MatchSRTCP is a MatchFunc that only matches SRTCP and not SRTP +// MatchSRTCP is a MatchFunc that only matches SRTCP and not SRTP. func MatchSRTCP(buf []byte) bool { return MatchSRTPOrSRTCP(buf) && isRTCP(buf) } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/internal/util/util.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/internal/util/util.go similarity index 88% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/internal/util/util.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/internal/util/util.go index 3f43c123e..46703ef4d 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/internal/util/util.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/internal/util/util.go @@ -18,17 +18,17 @@ const ( // Use global random generator to properly seed by crypto grade random. var globalMathRandomGenerator = randutil.NewMathRandomGenerator() // nolint:gochecknoglobals -// MathRandAlpha generates a mathmatical random alphabet sequence of the requested length. +// MathRandAlpha generates a mathematical random alphabet sequence of the requested length. func MathRandAlpha(n int) string { return globalMathRandomGenerator.GenerateString(n, runesAlpha) } -// RandUint32 generates a mathmatical random uint32. +// RandUint32 generates a mathematical random uint32. func RandUint32() uint32 { return globalMathRandomGenerator.Uint32() } -// FlattenErrs flattens multiple errors into one +// FlattenErrs flattens multiple errors into one. func FlattenErrs(errs []error) error { errs2 := []error{} for _, e := range errs { @@ -39,6 +39,7 @@ func FlattenErrs(errs []error) error { if len(errs2) == 0 { return nil } + return multiError(errs2) } @@ -71,5 +72,6 @@ func (me multiError) Is(err error) bool { } } } + return false } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/js_utils.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/js_utils.go similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/js_utils.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/js_utils.go diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/mediaengine.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/mediaengine.go similarity index 58% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/mediaengine.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/mediaengine.go index c824d1ed4..ab735e9f0 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/mediaengine.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/mediaengine.go @@ -7,6 +7,7 @@ package webrtc import ( + "errors" "fmt" "strconv" "strings" @@ -16,37 +17,7 @@ import ( "github.com/pion/rtp" "github.com/pion/rtp/codecs" "github.com/pion/sdp/v3" - "github.com/pion/webrtc/v3/internal/fmtp" -) - -const ( - // MimeTypeH264 H264 MIME type. - // Note: Matching should be case insensitive. - MimeTypeH264 = "video/H264" - // MimeTypeH265 H265 MIME type - // Note: Matching should be case insensitive. - MimeTypeH265 = "video/H265" - // MimeTypeOpus Opus MIME type - // Note: Matching should be case insensitive. - MimeTypeOpus = "audio/opus" - // MimeTypeVP8 VP8 MIME type - // Note: Matching should be case insensitive. - MimeTypeVP8 = "video/VP8" - // MimeTypeVP9 VP9 MIME type - // Note: Matching should be case insensitive. - MimeTypeVP9 = "video/VP9" - // MimeTypeAV1 AV1 MIME type - // Note: Matching should be case insensitive. - MimeTypeAV1 = "video/AV1" - // MimeTypeG722 G722 MIME type - // Note: Matching should be case insensitive. - MimeTypeG722 = "audio/G722" - // MimeTypePCMU PCMU MIME type - // Note: Matching should be case insensitive. - MimeTypePCMU = "audio/PCMU" - // MimeTypePCMA PCMA MIME type - // Note: Matching should be case insensitive. - MimeTypePCMA = "audio/PCMA" + "github.com/pion/webrtc/v4/internal/fmtp" ) type mediaEngineHeaderExtension struct { @@ -62,6 +33,7 @@ type mediaEngineHeaderExtension struct { type MediaEngine struct { // If we have attempted to negotiate a codec type yet. negotiatedVideo, negotiatedAudio bool + negotiateMultiCodecs bool videoCodecs, audioCodecs []RTPCodecParameters negotiatedVideoCodecs, negotiatedAudioCodecs []RTPCodecParameters @@ -72,6 +44,22 @@ type MediaEngine struct { mu sync.RWMutex } +// setMultiCodecNegotiation enables or disables the negotiation of multiple codecs. +func (m *MediaEngine) setMultiCodecNegotiation(negotiateMultiCodecs bool) { + m.mu.Lock() + defer m.mu.Unlock() + + m.negotiateMultiCodecs = negotiateMultiCodecs +} + +// multiCodecNegotiation returns the current state of the negotiation of multiple codecs. +func (m *MediaEngine) multiCodecNegotiation() bool { + m.mu.RLock() + defer m.mu.RUnlock() + + return m.negotiateMultiCodecs +} + // RegisterDefaultCodecs registers the default codecs supported by Pion WebRTC. // RegisterDefaultCodecs is not safe for concurrent use. func (m *MediaEngine) RegisterDefaultCodecs() error { @@ -83,15 +71,15 @@ func (m *MediaEngine) RegisterDefaultCodecs() error { }, { RTPCodecCapability: RTPCodecCapability{MimeTypeG722, 8000, 0, "", nil}, - PayloadType: 9, + PayloadType: rtp.PayloadTypeG722, }, { RTPCodecCapability: RTPCodecCapability{MimeTypePCMU, 8000, 0, "", nil}, - PayloadType: 0, + PayloadType: rtp.PayloadTypePCMU, }, { RTPCodecCapability: RTPCodecCapability{MimeTypePCMA, 8000, 0, "", nil}, - PayloadType: 8, + PayloadType: rtp.PayloadTypePCMA, }, } { if err := m.RegisterCodec(codec, RTPCodecTypeAudio); err != nil { @@ -106,85 +94,138 @@ func (m *MediaEngine) RegisterDefaultCodecs() error { PayloadType: 96, }, { - RTPCodecCapability: RTPCodecCapability{"video/rtx", 90000, 0, "apt=96", nil}, + RTPCodecCapability: RTPCodecCapability{MimeTypeRTX, 90000, 0, "apt=96", nil}, PayloadType: 97, }, + { + RTPCodecCapability: RTPCodecCapability{ + MimeTypeH264, 90000, 0, + "level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f", + videoRTCPFeedback, + }, + PayloadType: 102, + }, + { + RTPCodecCapability: RTPCodecCapability{MimeTypeRTX, 90000, 0, "apt=102", nil}, + PayloadType: 103, + }, + + { + RTPCodecCapability: RTPCodecCapability{ + MimeTypeH264, 90000, 0, + "level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=42001f", + videoRTCPFeedback, + }, + PayloadType: 104, + }, + { + RTPCodecCapability: RTPCodecCapability{MimeTypeRTX, 90000, 0, "apt=104", nil}, + PayloadType: 105, + }, + + { + RTPCodecCapability: RTPCodecCapability{ + MimeTypeH264, 90000, 0, + "level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f", + videoRTCPFeedback, + }, + PayloadType: 106, + }, + { + RTPCodecCapability: RTPCodecCapability{MimeTypeRTX, 90000, 0, "apt=106", nil}, + PayloadType: 107, + }, + + { + RTPCodecCapability: RTPCodecCapability{ + MimeTypeH264, 90000, 0, + "level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=42e01f", + videoRTCPFeedback, + }, + PayloadType: 108, + }, + { + RTPCodecCapability: RTPCodecCapability{MimeTypeRTX, 90000, 0, "apt=108", nil}, + PayloadType: 109, + }, + + { + RTPCodecCapability: RTPCodecCapability{ + MimeTypeH264, 90000, 0, + "level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=4d001f", + videoRTCPFeedback, + }, + PayloadType: 127, + }, + { + RTPCodecCapability: RTPCodecCapability{MimeTypeRTX, 90000, 0, "apt=127", nil}, + PayloadType: 125, + }, + + { + RTPCodecCapability: RTPCodecCapability{ + MimeTypeH264, + 90000, 0, + "level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=4d001f", + videoRTCPFeedback, + }, + PayloadType: 39, + }, + { + RTPCodecCapability: RTPCodecCapability{MimeTypeRTX, 90000, 0, "apt=39", nil}, + PayloadType: 40, + }, + { + RTPCodecCapability: RTPCodecCapability{ + MimeType: MimeTypeH265, + ClockRate: 90000, + RTCPFeedback: videoRTCPFeedback, + }, + PayloadType: 116, + }, + { + RTPCodecCapability: RTPCodecCapability{MimeTypeRTX, 90000, 0, "apt=116", nil}, + PayloadType: 117, + }, + { + RTPCodecCapability: RTPCodecCapability{MimeTypeAV1, 90000, 0, "", videoRTCPFeedback}, + PayloadType: 45, + }, + { + RTPCodecCapability: RTPCodecCapability{MimeTypeRTX, 90000, 0, "apt=45", nil}, + PayloadType: 46, + }, + { RTPCodecCapability: RTPCodecCapability{MimeTypeVP9, 90000, 0, "profile-id=0", videoRTCPFeedback}, PayloadType: 98, }, { - RTPCodecCapability: RTPCodecCapability{"video/rtx", 90000, 0, "apt=98", nil}, + RTPCodecCapability: RTPCodecCapability{MimeTypeRTX, 90000, 0, "apt=98", nil}, PayloadType: 99, }, { - RTPCodecCapability: RTPCodecCapability{MimeTypeVP9, 90000, 0, "profile-id=1", videoRTCPFeedback}, + RTPCodecCapability: RTPCodecCapability{MimeTypeVP9, 90000, 0, "profile-id=2", videoRTCPFeedback}, PayloadType: 100, }, { - RTPCodecCapability: RTPCodecCapability{"video/rtx", 90000, 0, "apt=100", nil}, + RTPCodecCapability: RTPCodecCapability{MimeTypeRTX, 90000, 0, "apt=100", nil}, PayloadType: 101, }, { - RTPCodecCapability: RTPCodecCapability{MimeTypeH264, 90000, 0, "level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f", videoRTCPFeedback}, - PayloadType: 102, + RTPCodecCapability: RTPCodecCapability{ + MimeTypeH264, 90000, 0, + "level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=64001f", + videoRTCPFeedback, + }, + PayloadType: 112, }, { - RTPCodecCapability: RTPCodecCapability{"video/rtx", 90000, 0, "apt=102", nil}, - PayloadType: 121, - }, - - { - RTPCodecCapability: RTPCodecCapability{MimeTypeH264, 90000, 0, "level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=42001f", videoRTCPFeedback}, - PayloadType: 127, - }, - { - RTPCodecCapability: RTPCodecCapability{"video/rtx", 90000, 0, "apt=127", nil}, - PayloadType: 120, - }, - - { - RTPCodecCapability: RTPCodecCapability{MimeTypeH264, 90000, 0, "level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f", videoRTCPFeedback}, - PayloadType: 125, - }, - { - RTPCodecCapability: RTPCodecCapability{"video/rtx", 90000, 0, "apt=125", nil}, - PayloadType: 107, - }, - - { - RTPCodecCapability: RTPCodecCapability{MimeTypeH264, 90000, 0, "level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=42e01f", videoRTCPFeedback}, - PayloadType: 108, - }, - { - RTPCodecCapability: RTPCodecCapability{"video/rtx", 90000, 0, "apt=108", nil}, - PayloadType: 109, - }, - - { - RTPCodecCapability: RTPCodecCapability{MimeTypeH264, 90000, 0, "level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=42001f", videoRTCPFeedback}, - PayloadType: 127, - }, - { - RTPCodecCapability: RTPCodecCapability{"video/rtx", 90000, 0, "apt=127", nil}, - PayloadType: 120, - }, - - { - RTPCodecCapability: RTPCodecCapability{MimeTypeH264, 90000, 0, "level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=640032", videoRTCPFeedback}, - PayloadType: 123, - }, - { - RTPCodecCapability: RTPCodecCapability{"video/rtx", 90000, 0, "apt=123", nil}, - PayloadType: 118, - }, - - { - RTPCodecCapability: RTPCodecCapability{"video/ulpfec", 90000, 0, "", nil}, - PayloadType: 116, + RTPCodecCapability: RTPCodecCapability{MimeTypeRTX, 90000, 0, "apt=112", nil}, + PayloadType: 113, }, } { if err := m.RegisterCodec(codec, RTPCodecTypeVideo); err != nil { @@ -195,38 +236,52 @@ func (m *MediaEngine) RegisterDefaultCodecs() error { return nil } -// addCodec will append codec if it not exists -func (m *MediaEngine) addCodec(codecs []RTPCodecParameters, codec RTPCodecParameters) []RTPCodecParameters { +// addCodec will append codec if it not exists. +func (m *MediaEngine) addCodec(codecs []RTPCodecParameters, codec RTPCodecParameters) ([]RTPCodecParameters, error) { for _, c := range codecs { - if c.MimeType == codec.MimeType && c.PayloadType == codec.PayloadType { - return codecs + if c.PayloadType == codec.PayloadType { + if strings.EqualFold(c.MimeType, codec.MimeType) && + fmtp.ClockRateEqual(c.MimeType, c.ClockRate, codec.ClockRate) && + fmtp.ChannelsEqual(c.MimeType, c.Channels, codec.Channels) { + return codecs, nil + } + + return codecs, ErrCodecAlreadyRegistered } } - return append(codecs, codec) + + return append(codecs, codec), nil } // RegisterCodec adds codec to the MediaEngine // These are the list of codecs supported by this PeerConnection. -// RegisterCodec is not safe for concurrent use. func (m *MediaEngine) RegisterCodec(codec RTPCodecParameters, typ RTPCodecType) error { m.mu.Lock() defer m.mu.Unlock() + var err error codec.statsID = fmt.Sprintf("RTPCodec-%d", time.Now().UnixNano()) switch typ { case RTPCodecTypeAudio: - m.audioCodecs = m.addCodec(m.audioCodecs, codec) + m.audioCodecs, err = m.addCodec(m.audioCodecs, codec) case RTPCodecTypeVideo: - m.videoCodecs = m.addCodec(m.videoCodecs, codec) + m.videoCodecs, err = m.addCodec(m.videoCodecs, codec) default: return ErrUnknownType } - return nil + + return err } // RegisterHeaderExtension adds a header extension to the MediaEngine -// To determine the negotiated value use `GetHeaderExtensionID` after signaling is complete -func (m *MediaEngine) RegisterHeaderExtension(extension RTPHeaderExtensionCapability, typ RTPCodecType, allowedDirections ...RTPTransceiverDirection) error { +// To determine the negotiated value use `GetHeaderExtensionID` after signaling is complete. +// +//nolint:cyclop +func (m *MediaEngine) RegisterHeaderExtension( + extension RTPHeaderExtensionCapability, + typ RTPCodecType, + allowedDirections ...RTPTransceiverDirection, +) error { m.mu.Lock() defer m.mu.Unlock() @@ -273,13 +328,12 @@ func (m *MediaEngine) RegisterFeedback(feedback RTCPFeedback, typ RTPCodecType) m.mu.Lock() defer m.mu.Unlock() - switch typ { - case RTPCodecTypeVideo: + if typ == RTPCodecTypeVideo { for i, v := range m.videoCodecs { v.RTCPFeedback = append(v.RTCPFeedback, feedback) m.videoCodecs[i] = v } - case RTPCodecTypeAudio: + } else if typ == RTPCodecTypeAudio { for i, v := range m.audioCodecs { v.RTCPFeedback = append(v.RTCPFeedback, feedback) m.audioCodecs[i] = v @@ -288,8 +342,11 @@ func (m *MediaEngine) RegisterFeedback(feedback RTCPFeedback, typ RTPCodecType) } // getHeaderExtensionID returns the negotiated ID for a header extension. -// If the Header Extension isn't enabled ok will be false -func (m *MediaEngine) getHeaderExtensionID(extension RTPHeaderExtensionCapability) (val int, audioNegotiated, videoNegotiated bool) { +// If the Header Extension isn't enabled ok will be false. +func (m *MediaEngine) getHeaderExtensionID(extension RTPHeaderExtensionCapability) ( + val int, + audioNegotiated, videoNegotiated bool, +) { m.mu.RLock() defer m.mu.RUnlock() @@ -307,7 +364,7 @@ func (m *MediaEngine) getHeaderExtensionID(extension RTPHeaderExtensionCapabilit } // copy copies any user modifiable state of the MediaEngine -// all internal state is reset +// all internal state is reset. func (m *MediaEngine) copy() *MediaEngine { m.mu.Lock() defer m.mu.Unlock() @@ -319,6 +376,7 @@ func (m *MediaEngine) copy() *MediaEngine { if len(m.headerExtensions) > 0 { cloned.negotiatedHeaderExtensions = map[int]mediaEngineHeaderExtension{} } + return cloned } @@ -328,6 +386,7 @@ func findCodecByPayload(codecs []RTPCodecParameters, payloadType PayloadType) *R return &codec } } + return nil } @@ -375,7 +434,7 @@ func (m *MediaEngine) collectStats(collector *statsReportCollector) { PayloadType: codec.PayloadType, MimeType: codec.MimeType, ClockRate: codec.ClockRate, - Channels: uint8(codec.Channels), + Channels: uint8(codec.Channels), //nolint:gosec // G115 SDPFmtpLine: codec.SDPFmtpLine, } @@ -387,24 +446,38 @@ func (m *MediaEngine) collectStats(collector *statsReportCollector) { statsLoop(m.audioCodecs) } -// Look up a codec and enable if it exists -func (m *MediaEngine) matchRemoteCodec(remoteCodec RTPCodecParameters, typ RTPCodecType, exactMatches, partialMatches []RTPCodecParameters) (codecMatchType, error) { +// Look up a codec and enable if it exists. +// +//nolint:cyclop +func (m *MediaEngine) matchRemoteCodec( + remoteCodec RTPCodecParameters, + typ RTPCodecType, + exactMatches, partialMatches []RTPCodecParameters, +) (RTPCodecParameters, codecMatchType, error) { codecs := m.videoCodecs if typ == RTPCodecTypeAudio { codecs = m.audioCodecs } - remoteFmtp := fmtp.Parse(remoteCodec.RTPCodecCapability.MimeType, remoteCodec.RTPCodecCapability.SDPFmtpLine) - if apt, hasApt := remoteFmtp.Parameter("apt"); hasApt { + remoteFmtp := fmtp.Parse( + remoteCodec.RTPCodecCapability.MimeType, + remoteCodec.RTPCodecCapability.ClockRate, + remoteCodec.RTPCodecCapability.Channels, + remoteCodec.RTPCodecCapability.SDPFmtpLine) + + if apt, hasApt := remoteFmtp.Parameter("apt"); hasApt { //nolint:nestif payloadType, err := strconv.ParseUint(apt, 10, 8) if err != nil { - return codecMatchNone, err + return RTPCodecParameters{}, codecMatchNone, err } aptMatch := codecMatchNone + var aptCodec RTPCodecParameters for _, codec := range exactMatches { if codec.PayloadType == PayloadType(payloadType) { aptMatch = codecMatchExact + aptCodec = codec + break } } @@ -413,28 +486,68 @@ func (m *MediaEngine) matchRemoteCodec(remoteCodec RTPCodecParameters, typ RTPCo for _, codec := range partialMatches { if codec.PayloadType == PayloadType(payloadType) { aptMatch = codecMatchPartial + aptCodec = codec + break } } } if aptMatch == codecMatchNone { - return codecMatchNone, nil // not an error, we just ignore this codec we don't support + return RTPCodecParameters{}, codecMatchNone, nil // not an error, we just ignore this codec we don't support } - // if apt's media codec is partial match, then apt codec must be partial match too - _, matchType := codecParametersFuzzySearch(remoteCodec, codecs) + // replace the apt value with the original codec's payload type + toMatchCodec := remoteCodec + if aptMatched, mt := codecParametersFuzzySearch(aptCodec, codecs); mt == aptMatch { + toMatchCodec.SDPFmtpLine = strings.Replace( + toMatchCodec.SDPFmtpLine, + fmt.Sprintf("apt=%d", payloadType), + fmt.Sprintf("apt=%d", aptMatched.PayloadType), + 1, + ) + } + + // if apt's media codec is partial match, then apt codec must be partial match too. + localCodec, matchType := codecParametersFuzzySearch(toMatchCodec, codecs) if matchType == codecMatchExact && aptMatch == codecMatchPartial { matchType = codecMatchPartial } - return matchType, nil + + return localCodec, matchType, nil } - _, matchType := codecParametersFuzzySearch(remoteCodec, codecs) - return matchType, nil + localCodec, matchType := codecParametersFuzzySearch(remoteCodec, codecs) + + return localCodec, matchType, nil } -// Look up a header extension and enable if it exists +// Update header extensions from a remote media section. +func (m *MediaEngine) updateHeaderExtensionFromMediaSection(media *sdp.MediaDescription) error { + var typ RTPCodecType + switch { + case strings.EqualFold(media.MediaName.Media, "audio"): + typ = RTPCodecTypeAudio + case strings.EqualFold(media.MediaName.Media, "video"): + typ = RTPCodecTypeVideo + default: + return nil + } + extensions, err := rtpExtensionsFromMediaDescription(media) + if err != nil { + return err + } + + for extension, id := range extensions { + if err = m.updateHeaderExtension(id, extension, typ); err != nil { + return err + } + } + + return nil +} + +// Look up a header extension and enable if it exists. func (m *MediaEngine) updateHeaderExtension(id int, extension string, typ RTPCodecType) error { if m.negotiatedHeaderExtensions == nil { return nil @@ -457,35 +570,59 @@ func (m *MediaEngine) updateHeaderExtension(id int, extension string, typ RTPCod m.negotiatedHeaderExtensions[id] = h } } + return nil } -func (m *MediaEngine) pushCodecs(codecs []RTPCodecParameters, typ RTPCodecType) { +func (m *MediaEngine) pushCodecs(codecs []RTPCodecParameters, typ RTPCodecType) error { + var joinedErr error for _, codec := range codecs { + var err error if typ == RTPCodecTypeAudio { - m.negotiatedAudioCodecs = m.addCodec(m.negotiatedAudioCodecs, codec) + m.negotiatedAudioCodecs, err = m.addCodec(m.negotiatedAudioCodecs, codec) } else if typ == RTPCodecTypeVideo { - m.negotiatedVideoCodecs = m.addCodec(m.negotiatedVideoCodecs, codec) + m.negotiatedVideoCodecs, err = m.addCodec(m.negotiatedVideoCodecs, codec) + } + if err != nil { + joinedErr = errors.Join(joinedErr, err) } } + + return joinedErr } -// Update the MediaEngine from a remote description -func (m *MediaEngine) updateFromRemoteDescription(desc sdp.SessionDescription) error { +// Update the MediaEngine from a remote description. +func (m *MediaEngine) updateFromRemoteDescription(desc sdp.SessionDescription) error { //nolint:cyclop,gocognit m.mu.Lock() defer m.mu.Unlock() for _, media := range desc.MediaDescriptions { var typ RTPCodecType + switch { - case !m.negotiatedAudio && strings.EqualFold(media.MediaName.Media, "audio"): - m.negotiatedAudio = true + case strings.EqualFold(media.MediaName.Media, "audio"): typ = RTPCodecTypeAudio - case !m.negotiatedVideo && strings.EqualFold(media.MediaName.Media, "video"): - m.negotiatedVideo = true + case strings.EqualFold(media.MediaName.Media, "video"): typ = RTPCodecTypeVideo + } + + switch { + case !m.negotiatedAudio && typ == RTPCodecTypeAudio: + m.negotiatedAudio = true + case !m.negotiatedVideo && typ == RTPCodecTypeVideo: + m.negotiatedVideo = true default: - continue + // update header extesions from remote sdp if codec is negotiated, Firefox + // would send updated header extension in renegotiation. + // e.g. publish first track without simucalst ->negotiated-> publish second track with simucalst + // then the two media secontions have different rtp header extensions in offer + if err := m.updateHeaderExtensionFromMediaSection(media); err != nil { + return err + } + + if !m.negotiateMultiCodecs || (typ != RTPCodecTypeAudio && typ != RTPCodecTypeVideo) { + continue + } } codecs, err := codecsFromMediaDescription(media) @@ -496,41 +633,40 @@ func (m *MediaEngine) updateFromRemoteDescription(desc sdp.SessionDescription) e exactMatches := make([]RTPCodecParameters, 0, len(codecs)) partialMatches := make([]RTPCodecParameters, 0, len(codecs)) - for _, codec := range codecs { - matchType, mErr := m.matchRemoteCodec(codec, typ, exactMatches, partialMatches) + for _, remoteCodec := range codecs { + localCodec, matchType, mErr := m.matchRemoteCodec(remoteCodec, typ, exactMatches, partialMatches) if mErr != nil { return mErr } + remoteCodec.RTCPFeedback = rtcpFeedbackIntersection(localCodec.RTCPFeedback, remoteCodec.RTCPFeedback) + if matchType == codecMatchExact { - exactMatches = append(exactMatches, codec) + exactMatches = append(exactMatches, remoteCodec) } else if matchType == codecMatchPartial { - partialMatches = append(partialMatches, codec) + partialMatches = append(partialMatches, remoteCodec) } } // use exact matches when they exist, otherwise fall back to partial switch { case len(exactMatches) > 0: - m.pushCodecs(exactMatches, typ) + err = m.pushCodecs(exactMatches, typ) case len(partialMatches) > 0: - m.pushCodecs(partialMatches, typ) + err = m.pushCodecs(partialMatches, typ) default: // no match, not negotiated continue } - - extensions, err := rtpExtensionsFromMediaDescription(media) if err != nil { return err } - for extension, id := range extensions { - if err = m.updateHeaderExtension(id, extension, typ); err != nil { - return err - } + if err := m.updateHeaderExtensionFromMediaSection(media); err != nil { + return err } } + return nil } @@ -555,7 +691,8 @@ func (m *MediaEngine) getCodecsByKind(typ RTPCodecType) []RTPCodecParameters { return nil } -func (m *MediaEngine) getRTPParametersByKind(typ RTPCodecType, directions []RTPTransceiverDirection) RTPParameters { //nolint:gocognit +//nolint:gocognit,cyclop +func (m *MediaEngine) getRTPParametersByKind(typ RTPCodecType, directions []RTPTransceiverDirection) RTPParameters { headerExtensions := make([]RTPHeaderExtensionParameter, 0) // perform before locking to prevent recursive RLocks @@ -563,21 +700,24 @@ func (m *MediaEngine) getRTPParametersByKind(typ RTPCodecType, directions []RTPT m.mu.RLock() defer m.mu.RUnlock() - if m.negotiatedVideo && typ == RTPCodecTypeVideo || - m.negotiatedAudio && typ == RTPCodecTypeAudio { + + //nolint:nestif + if (m.negotiatedVideo && typ == RTPCodecTypeVideo) || (m.negotiatedAudio && typ == RTPCodecTypeAudio) { for id, e := range m.negotiatedHeaderExtensions { - if haveRTPTransceiverDirectionIntersection(e.allowedDirections, directions) && (e.isAudio && typ == RTPCodecTypeAudio || e.isVideo && typ == RTPCodecTypeVideo) { + if haveRTPTransceiverDirectionIntersection(e.allowedDirections, directions) && + (e.isAudio && typ == RTPCodecTypeAudio || e.isVideo && typ == RTPCodecTypeVideo) { headerExtensions = append(headerExtensions, RTPHeaderExtensionParameter{ID: id, URI: e.uri}) } } } else { mediaHeaderExtensions := make(map[int]mediaEngineHeaderExtension) - for _, e := range m.headerExtensions { + for _, ext := range m.headerExtensions { usingNegotiatedID := false for id := range m.negotiatedHeaderExtensions { - if m.negotiatedHeaderExtensions[id].uri == e.uri { + if m.negotiatedHeaderExtensions[id].uri == ext.uri { usingNegotiatedID = true - mediaHeaderExtensions[id] = e + mediaHeaderExtensions[id] = ext + break } } @@ -588,7 +728,8 @@ func (m *MediaEngine) getRTPParametersByKind(typ RTPCodecType, directions []RTPT idAvailable = false } if _, taken := m.negotiatedHeaderExtensions[id]; idAvailable && !taken { - mediaHeaderExtensions[id] = e + mediaHeaderExtensions[id] = ext + break } } @@ -596,7 +737,8 @@ func (m *MediaEngine) getRTPParametersByKind(typ RTPCodecType, directions []RTPT } for id, e := range mediaHeaderExtensions { - if haveRTPTransceiverDirectionIntersection(e.allowedDirections, directions) && (e.isAudio && typ == RTPCodecTypeAudio || e.isVideo && typ == RTPCodecTypeVideo) { + if haveRTPTransceiverDirectionIntersection(e.allowedDirections, directions) && + (e.isAudio && typ == RTPCodecTypeAudio || e.isVideo && typ == RTPCodecTypeVideo) { headerExtensions = append(headerExtensions, RTPHeaderExtensionParameter{ID: id, URI: e.uri}) } } @@ -633,6 +775,8 @@ func payloaderForCodec(codec RTPCodecCapability) (rtp.Payloader, error) { switch strings.ToLower(codec.MimeType) { case strings.ToLower(MimeTypeH264): return &codecs.H264Payloader{}, nil + case strings.ToLower(MimeTypeH265): + return &codecs.H265Payloader{}, nil case strings.ToLower(MimeTypeOpus): return &codecs.OpusPayloader{}, nil case strings.ToLower(MimeTypeVP8): @@ -651,3 +795,23 @@ func payloaderForCodec(codec RTPCodecCapability) (rtp.Payloader, error) { return nil, ErrNoPayloaderForCodec } } + +func (m *MediaEngine) isRTXEnabled(typ RTPCodecType, directions []RTPTransceiverDirection) bool { + for _, p := range m.getRTPParametersByKind(typ, directions).Codecs { + if strings.EqualFold(p.MimeType, MimeTypeRTX) { + return true + } + } + + return false +} + +func (m *MediaEngine) isFECEnabled(typ RTPCodecType, directions []RTPTransceiverDirection) bool { + for _, p := range m.getRTPParametersByKind(typ, directions).Codecs { + if strings.Contains(strings.ToLower(p.MimeType), MimeTypeFlexFEC) { + return true + } + } + + return false +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/mimetype.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/mimetype.go new file mode 100644 index 000000000..9575f9eb1 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/mimetype.go @@ -0,0 +1,46 @@ +// SPDX-FileCopyrightText: 2025 The Pion community +// SPDX-License-Identifier: MIT + +package webrtc + +const ( + // MimeTypeH264 H264 MIME type. + // Note: Matching should be case insensitive. + MimeTypeH264 = "video/H264" + // MimeTypeH265 H265 MIME type + // Note: Matching should be case insensitive. + MimeTypeH265 = "video/H265" + // MimeTypeOpus Opus MIME type + // Note: Matching should be case insensitive. + MimeTypeOpus = "audio/opus" + // MimeTypeVP8 VP8 MIME type + // Note: Matching should be case insensitive. + MimeTypeVP8 = "video/VP8" + // MimeTypeVP9 VP9 MIME type + // Note: Matching should be case insensitive. + MimeTypeVP9 = "video/VP9" + // MimeTypeAV1 AV1 MIME type + // Note: Matching should be case insensitive. + MimeTypeAV1 = "video/AV1" + // MimeTypeG722 G722 MIME type + // Note: Matching should be case insensitive. + MimeTypeG722 = "audio/G722" + // MimeTypePCMU PCMU MIME type + // Note: Matching should be case insensitive. + MimeTypePCMU = "audio/PCMU" + // MimeTypePCMA PCMA MIME type + // Note: Matching should be case insensitive. + MimeTypePCMA = "audio/PCMA" + // MimeTypeRTX RTX MIME type + // Note: Matching should be case insensitive. + MimeTypeRTX = "video/rtx" + // MimeTypeFlexFEC FEC MIME Type + // Note: Matching should be case insensitive. + MimeTypeFlexFEC = "video/flexfec" + // MimeTypeFlexFEC03 FlexFEC03 MIME Type + // Note: Matching should be case insensitive. + MimeTypeFlexFEC03 = "video/flexfec-03" + // MimeTypeUlpFEC UlpFEC MIME Type + // Note: Matching should be case insensitive. + MimeTypeUlpFEC = "video/ulpfec" +) diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/networktype.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/networktype.go similarity index 84% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/networktype.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/networktype.go index 601e73ff8..a7ee773c1 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/networktype.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/networktype.go @@ -6,7 +6,7 @@ package webrtc import ( "fmt" - "github.com/pion/ice/v2" + "github.com/pion/ice/v4" ) func supportedNetworkTypes() []NetworkType { @@ -18,12 +18,15 @@ func supportedNetworkTypes() []NetworkType { } } -// NetworkType represents the type of network +// NetworkType represents the type of network. type NetworkType int const ( + // NetworkTypeUnknown is the enum's zero-value. + NetworkTypeUnknown NetworkType = iota + // NetworkTypeUDP4 indicates UDP over IPv4. - NetworkTypeUDP4 NetworkType = iota + 1 + NetworkTypeUDP4 // NetworkTypeUDP6 indicates UDP over IPv6. NetworkTypeUDP6 @@ -58,7 +61,7 @@ func (t NetworkType) String() string { } } -// Protocol returns udp or tcp +// Protocol returns udp or tcp. func (t NetworkType) Protocol() string { switch t { case NetworkTypeUDP4: @@ -87,7 +90,7 @@ func NewNetworkType(raw string) (NetworkType, error) { case networkTypeTCP6Str: return NetworkTypeTCP6, nil default: - return NetworkType(Unknown), fmt.Errorf("%w: %s", errNetworkTypeUnknown, raw) + return NetworkTypeUnknown, fmt.Errorf("%w: %s", errNetworkTypeUnknown, raw) } } @@ -102,6 +105,6 @@ func getNetworkType(iceNetworkType ice.NetworkType) (NetworkType, error) { case ice.NetworkTypeTCP6: return NetworkTypeTCP6, nil default: - return NetworkType(Unknown), fmt.Errorf("%w: %s", errNetworkTypeUnknown, iceNetworkType.String()) + return NetworkTypeUnknown, fmt.Errorf("%w: %s", errNetworkTypeUnknown, iceNetworkType.String()) } } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/oauthcredential.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/oauthcredential.go similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/oauthcredential.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/oauthcredential.go diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/offeransweroptions.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/offeransweroptions.go similarity index 97% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/offeransweroptions.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/offeransweroptions.go index 528688975..17435566a 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/offeransweroptions.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/offeransweroptions.go @@ -18,7 +18,7 @@ type AnswerOptions struct { } // OfferOptions structure describes the options used to control the offer -// creation process +// creation process. type OfferOptions struct { OfferAnswerOptions diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/operations.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/operations.go new file mode 100644 index 000000000..3e65f1357 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/operations.go @@ -0,0 +1,158 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + +package webrtc + +import ( + "container/list" + "sync" +) + +// Operation is a function. +type operation func() + +// Operations is a task executor. +type operations struct { + mu sync.Mutex + busyCh chan struct{} + ops *list.List + + updateNegotiationNeededFlagOnEmptyChain *atomicBool + onNegotiationNeeded func() + isClosed bool +} + +func newOperations( + updateNegotiationNeededFlagOnEmptyChain *atomicBool, + onNegotiationNeeded func(), +) *operations { + return &operations{ + ops: list.New(), + updateNegotiationNeededFlagOnEmptyChain: updateNegotiationNeededFlagOnEmptyChain, + onNegotiationNeeded: onNegotiationNeeded, + } +} + +// Enqueue adds a new action to be executed. If there are no actions scheduled, +// the execution will start immediately in a new goroutine. If the queue has been +// closed, the operation will be dropped. The queue is only deliberately closed +// by a user. +func (o *operations) Enqueue(op operation) { + o.mu.Lock() + defer o.mu.Unlock() + _ = o.tryEnqueue(op) +} + +// tryEnqueue attempts to enqueue the given operation. It returns false +// if the op is invalid or the queue is closed. mu must be locked by +// tryEnqueue's caller. +func (o *operations) tryEnqueue(op operation) bool { + if op == nil { + return false + } + + if o.isClosed { + return false + } + o.ops.PushBack(op) + + if o.busyCh == nil { + o.busyCh = make(chan struct{}) + go o.start() + } + + return true +} + +// IsEmpty checks if there are tasks in the queue. +func (o *operations) IsEmpty() bool { + o.mu.Lock() + defer o.mu.Unlock() + + return o.ops.Len() == 0 +} + +// Done blocks until all currently enqueued operations are finished executing. +// For more complex synchronization, use Enqueue directly. +func (o *operations) Done() { + var wg sync.WaitGroup + wg.Add(1) + o.mu.Lock() + enqueued := o.tryEnqueue(func() { + wg.Done() + }) + o.mu.Unlock() + if !enqueued { + return + } + wg.Wait() +} + +// GracefulClose waits for the operations queue to be cleared and forbids +// new operations from being enqueued. +func (o *operations) GracefulClose() { + o.mu.Lock() + if o.isClosed { + o.mu.Unlock() + + return + } + // do not enqueue anymore ops from here on + // o.isClosed=true will also not allow a new busyCh + // to be created. + o.isClosed = true + + busyCh := o.busyCh + o.mu.Unlock() + if busyCh == nil { + return + } + <-busyCh +} + +func (o *operations) pop() func() { + o.mu.Lock() + defer o.mu.Unlock() + if o.ops.Len() == 0 { + return nil + } + + e := o.ops.Front() + o.ops.Remove(e) + if op, ok := e.Value.(operation); ok { + return op + } + + return nil +} + +func (o *operations) start() { + defer func() { + o.mu.Lock() + defer o.mu.Unlock() + // this wil lbe the most recent busy chan + close(o.busyCh) + + if o.ops.Len() == 0 || o.isClosed { + o.busyCh = nil + + return + } + + // either a new operation was enqueued while we + // were busy, or an operation panicked + o.busyCh = make(chan struct{}) + go o.start() + }() + + fn := o.pop() + for fn != nil { + fn() + fn = o.pop() + } + if !o.updateNegotiationNeededFlagOnEmptyChain.get() { + return + } + o.updateNegotiationNeededFlagOnEmptyChain.set(false) + o.onNegotiationNeeded() +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/package.json b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/package.json new file mode 100644 index 000000000..f58d23972 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/package.json @@ -0,0 +1,12 @@ +{ + "name": "webrtc", + "repository": "git@github.com:pion/webrtc.git", + "private": true, + "devDependencies": { + "@roamhq/wrtc": "^0.8.0" + }, + "dependencies": { + "request": "2.88.2" + }, + "packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e" +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/peerconnection.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/peerconnection.go similarity index 69% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/peerconnection.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/peerconnection.go index b3c0ef427..a2d1a7afb 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/peerconnection.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/peerconnection.go @@ -19,14 +19,14 @@ import ( "sync/atomic" "time" - "github.com/pion/ice/v2" + "github.com/pion/ice/v4" "github.com/pion/interceptor" "github.com/pion/logging" "github.com/pion/rtcp" "github.com/pion/sdp/v3" - "github.com/pion/srtp/v2" - "github.com/pion/webrtc/v3/internal/util" - "github.com/pion/webrtc/v3/pkg/rtcerr" + "github.com/pion/srtp/v3" + "github.com/pion/webrtc/v4/internal/util" + "github.com/pion/webrtc/v4/pkg/rtcerr" ) // PeerConnection represents a WebRTC connection that establishes a @@ -55,9 +55,12 @@ type PeerConnection struct { idpLoginURL *string - isClosed *atomicBool - isNegotiationNeeded *atomicBool - negotiationNeededState negotiationNeededState + isClosed *atomicBool + isGracefullyClosingOrClosed bool + isCloseDone chan struct{} + isGracefulCloseDone chan struct{} + isNegotiationNeeded *atomicBool + updateNegotiationNeededFlagOnEmptyChain *atomicBool lastOffer string lastAnswer string @@ -68,7 +71,8 @@ type PeerConnection struct { // should be defined (see JSEP 3.4.1). greaterMid int - rtpTransceivers []*RTPTransceiver + rtpTransceivers []*RTPTransceiver + nonMediaBandwidthProbe atomic.Value // RTPReceiver onSignalingStateChangeHandler func(SignalingState) onICEConnectionStateChangeHandler atomic.Value // func(ICEConnectionState) @@ -89,32 +93,27 @@ type PeerConnection struct { interceptorRTCPWriter interceptor.RTCPWriter } -// NewPeerConnection creates a PeerConnection with the default codecs and -// interceptors. See RegisterDefaultCodecs and RegisterDefaultInterceptors. +// NewPeerConnection creates a PeerConnection with the default codecs and interceptors. // -// If you wish to customize the set of available codecs or the set of -// active interceptors, create a MediaEngine and call api.NewPeerConnection -// instead of this function. +// If you wish to customize the set of available codecs and/or the set of active interceptors, +// create an API with a custom MediaEngine and/or interceptor.Registry, +// then call [(*API).NewPeerConnection] instead of this function. func NewPeerConnection(configuration Configuration) (*PeerConnection, error) { - m := &MediaEngine{} - if err := m.RegisterDefaultCodecs(); err != nil { - return nil, err - } + api := NewAPI() - i := &interceptor.Registry{} - if err := RegisterDefaultInterceptors(m, i); err != nil { - return nil, err - } - - api := NewAPI(WithMediaEngine(m), WithInterceptorRegistry(i)) return api.NewPeerConnection(configuration) } -// NewPeerConnection creates a new PeerConnection with the provided configuration against the received API object +// NewPeerConnection creates a new PeerConnection with the provided configuration against the received API object. +// This method will attach a default set of codecs and interceptors to +// the resulting PeerConnection. If this behavior is not desired, +// set the set of codecs and interceptors explicitly by using +// [WithMediaEngine] and [WithInterceptorRegistry] when calling [NewAPI]. func (api *API) NewPeerConnection(configuration Configuration) (*PeerConnection, error) { // https://w3c.github.io/webrtc-pc/#constructor (Step #2) // Some variables defined explicitly despite their implicit zero values to // allow better readability to understand what is happening. + pc := &PeerConnection{ statsID: fmt.Sprintf("PeerConnection-%d", time.Now().UnixNano()), configuration: Configuration{ @@ -125,18 +124,21 @@ func (api *API) NewPeerConnection(configuration Configuration) (*PeerConnection, Certificates: []Certificate{}, ICECandidatePoolSize: 0, }, - ops: newOperations(), - isClosed: &atomicBool{}, - isNegotiationNeeded: &atomicBool{}, - negotiationNeededState: negotiationNeededStateEmpty, - lastOffer: "", - lastAnswer: "", - greaterMid: -1, - signalingState: SignalingStateStable, + isClosed: &atomicBool{}, + isCloseDone: make(chan struct{}), + isGracefulCloseDone: make(chan struct{}), + isNegotiationNeeded: &atomicBool{}, + updateNegotiationNeededFlagOnEmptyChain: &atomicBool{}, + lastOffer: "", + lastAnswer: "", + greaterMid: -1, + signalingState: SignalingStateStable, api: api, log: api.settingEngine.LoggerFactory.NewLogger("pc"), } + pc.ops = newOperations(pc.updateNegotiationNeededFlagOnEmptyChain, pc.onNegotiationNeeded) + pc.iceConnectionState.Store(ICEConnectionStateNew) pc.connectionState.Store(PeerConnectionStateNew) @@ -154,6 +156,7 @@ func (api *API) NewPeerConnection(configuration Configuration) (*PeerConnection, pc.api.mediaEngine = api.mediaEngine } else { pc.api.mediaEngine = api.mediaEngine.copy() + pc.api.mediaEngine.setMultiCodecNegotiation(!api.settingEngine.disableMediaEngineMultipleCodecs) } if err = pc.initConfiguration(configuration); err != nil { @@ -199,7 +202,7 @@ func (api *API) NewPeerConnection(configuration Configuration) (*PeerConnection, // from its SetConfiguration counterpart because most of the checks do not // include verification statements related to the existing state. Thus the // function describes only minor verification of some the struct variables. -func (pc *PeerConnection) initConfiguration(configuration Configuration) error { +func (pc *PeerConnection) initConfiguration(configuration Configuration) error { //nolint:cyclop if configuration.PeerIdentity != "" { pc.configuration.PeerIdentity = configuration.PeerIdentity } @@ -225,11 +228,11 @@ func (pc *PeerConnection) initConfiguration(configuration Configuration) error { pc.configuration.Certificates = []Certificate{*certificate} } - if configuration.BundlePolicy != BundlePolicy(Unknown) { + if configuration.BundlePolicy != BundlePolicyUnknown { pc.configuration.BundlePolicy = configuration.BundlePolicy } - if configuration.RTCPMuxPolicy != RTCPMuxPolicy(Unknown) { + if configuration.RTCPMuxPolicy != RTCPMuxPolicyUnknown { pc.configuration.RTCPMuxPolicy = configuration.RTCPMuxPolicy } @@ -237,13 +240,8 @@ func (pc *PeerConnection) initConfiguration(configuration Configuration) error { pc.configuration.ICECandidatePoolSize = configuration.ICECandidatePoolSize } - if configuration.ICETransportPolicy != ICETransportPolicy(Unknown) { - pc.configuration.ICETransportPolicy = configuration.ICETransportPolicy - } - - if configuration.SDPSemantics != SDPSemantics(Unknown) { - pc.configuration.SDPSemantics = configuration.SDPSemantics - } + pc.configuration.ICETransportPolicy = configuration.ICETransportPolicy + pc.configuration.SDPSemantics = configuration.SDPSemantics sanitizedICEServers := configuration.getICEServers() if len(sanitizedICEServers) > 0 { @@ -259,7 +257,7 @@ func (pc *PeerConnection) initConfiguration(configuration Configuration) error { } // OnSignalingStateChange sets an event handler which is invoked when the -// peer connection's signaling state changes +// peer connection's signaling state changes. func (pc *PeerConnection) OnSignalingStateChange(f func(SignalingState)) { pc.mu.Lock() defer pc.mu.Unlock() @@ -286,79 +284,70 @@ func (pc *PeerConnection) OnDataChannel(f func(*DataChannel)) { } // OnNegotiationNeeded sets an event handler which is invoked when -// a change has occurred which requires session negotiation +// a change has occurred which requires session negotiation. func (pc *PeerConnection) OnNegotiationNeeded(f func()) { pc.onNegotiationNeededHandler.Store(f) } // onNegotiationNeeded enqueues negotiationNeededOp if necessary // caller of this method should hold `pc.mu` lock +// https://www.w3.org/TR/webrtc/#dfn-update-the-negotiation-needed-flag func (pc *PeerConnection) onNegotiationNeeded() { - // https://w3c.github.io/webrtc-pc/#updating-the-negotiation-needed-flag - // non-canon step 1 - if pc.negotiationNeededState == negotiationNeededStateRun { - pc.negotiationNeededState = negotiationNeededStateQueue - return - } else if pc.negotiationNeededState == negotiationNeededStateQueue { + // 4.7.3.1 If the length of connection.[[Operations]] is not 0, then set + // connection.[[UpdateNegotiationNeededFlagOnEmptyChain]] to true, and abort these steps. + if !pc.ops.IsEmpty() { + pc.updateNegotiationNeededFlagOnEmptyChain.set(true) + return } - pc.negotiationNeededState = negotiationNeededStateRun pc.ops.Enqueue(pc.negotiationNeededOp) } +// https://www.w3.org/TR/webrtc/#dfn-update-the-negotiation-needed-flag func (pc *PeerConnection) negotiationNeededOp() { - // Don't run NegotiatedNeeded checks if OnNegotiationNeeded is not set - if handler, ok := pc.onNegotiationNeededHandler.Load().(func()); !ok || handler == nil { - return - } - - // https://www.w3.org/TR/webrtc/#updating-the-negotiation-needed-flag - // Step 2.1 + // 4.7.3.2.1 If connection.[[IsClosed]] is true, abort these steps. if pc.isClosed.get() { return } - // non-canon step 2.2 + + // 4.7.3.2.2 If the length of connection.[[Operations]] is not 0, + // then set connection.[[UpdateNegotiationNeededFlagOnEmptyChain]] to + // true, and abort these steps. if !pc.ops.IsEmpty() { - pc.ops.Enqueue(pc.negotiationNeededOp) + pc.updateNegotiationNeededFlagOnEmptyChain.set(true) + return } - // non-canon, run again if there was a request - defer func() { - pc.mu.Lock() - defer pc.mu.Unlock() - if pc.negotiationNeededState == negotiationNeededStateQueue { - defer pc.onNegotiationNeeded() - } - pc.negotiationNeededState = negotiationNeededStateEmpty - }() - - // Step 2.3 + // 4.7.3.2.3 If connection's signaling state is not "stable", abort these steps. if pc.SignalingState() != SignalingStateStable { return } - // Step 2.4 + // 4.7.3.2.4 If the result of checking if negotiation is needed is false, + // clear the negotiation-needed flag by setting connection.[[NegotiationNeeded]] + // to false, and abort these steps. if !pc.checkNegotiationNeeded() { pc.isNegotiationNeeded.set(false) + return } - // Step 2.5 + // 4.7.3.2.5 If connection.[[NegotiationNeeded]] is already true, abort these steps. if pc.isNegotiationNeeded.get() { return } - // Step 2.6 + // 4.7.3.2.6 Set connection.[[NegotiationNeeded]] to true. pc.isNegotiationNeeded.set(true) - // Step 2.7 + // 4.7.3.2.7 Fire an event named negotiationneeded at connection. if handler, ok := pc.onNegotiationNeededHandler.Load().(func()); ok && handler != nil { handler() } } -func (pc *PeerConnection) checkNegotiationNeeded() bool { //nolint:gocognit +func (pc *PeerConnection) checkNegotiationNeeded() bool { //nolint:gocognit,cyclop // To check if negotiation is needed for connection, perform the following checks: // Skip 1, 2 steps // Step 3 @@ -380,55 +369,65 @@ func (pc *PeerConnection) checkNegotiationNeeded() bool { //nolint:gocognit return true } - for _, t := range pc.rtpTransceivers { + for _, transceiver := range pc.rtpTransceivers { // https://www.w3.org/TR/webrtc/#dfn-update-the-negotiation-needed-flag // Step 5.1 // if t.stopping && !t.stopped { // return true // } - m := getByMid(t.Mid(), localDesc) + mid := getByMid(transceiver.Mid(), localDesc) + // Step 5.2 - if !t.stopped && m == nil { + if mid == nil { return true } - if !t.stopped && m != nil { - // Step 5.3.1 - if t.Direction() == RTPTransceiverDirectionSendrecv || t.Direction() == RTPTransceiverDirectionSendonly { - descMsid, okMsid := m.Attribute(sdp.AttrKeyMsid) - sender := t.Sender() - if sender == nil { - return true - } - track := sender.Track() - if !okMsid || descMsid != track.StreamID()+" "+track.ID() { - return true - } - } - switch localDesc.Type { - case SDPTypeOffer: - // Step 5.3.2 - rm := getByMid(t.Mid(), remoteDesc) - if rm == nil { - return true - } - if getPeerDirection(m) != t.Direction() && getPeerDirection(rm) != t.Direction().Revers() { - return true - } - case SDPTypeAnswer: - // Step 5.3.3 - if _, ok := m.Attribute(t.Direction().String()); !ok { - return true - } - default: + // Step 5.3.1 + if transceiver.Direction() == RTPTransceiverDirectionSendrecv || + transceiver.Direction() == RTPTransceiverDirectionSendonly { + descMsid, okMsid := mid.Attribute(sdp.AttrKeyMsid) + sender := transceiver.Sender() + if sender == nil { + return true } - } - // Step 5.4 - if t.stopped && t.Mid() != "" { - if getByMid(t.Mid(), localDesc) != nil || getByMid(t.Mid(), remoteDesc) != nil { + track := sender.Track() + if track == nil { + // Situation when sender's track is nil could happen when + // a) replaceTrack(nil) is called + // b) removeTrack() is called, changing the transceiver's direction to inactive + // As t.Direction() in this branch is either sendrecv or sendonly, we believe (a) option is the case + // As calling replaceTrack does not require renegotiation, we skip check for this transceiver + continue + } + if !okMsid || descMsid != track.StreamID()+" "+track.ID() { return true } } + switch localDesc.Type { + case SDPTypeOffer: + // Step 5.3.2 + rm := getByMid(transceiver.Mid(), remoteDesc) + if rm == nil { + return true + } + + if getPeerDirection(mid) != transceiver.Direction() && getPeerDirection(rm) != transceiver.Direction().Revers() { + return true + } + case SDPTypeAnswer: + // Step 5.3.3 + if _, ok := mid.Attribute(transceiver.Direction().String()); !ok { + return true + } + default: + } + + // Step 5.4 + // if t.stopped && t.Mid() != "" { + // if getByMid(t.Mid(), localDesc) != nil || getByMid(t.Mid(), remoteDesc) != nil { + // return true + // } + // } } // Step 6 return false @@ -446,8 +445,18 @@ func (pc *PeerConnection) OnICECandidate(f func(*ICECandidate)) { // OnICEGatheringStateChange sets an event handler which is invoked when the // ICE candidate gathering state has changed. -func (pc *PeerConnection) OnICEGatheringStateChange(f func(ICEGathererState)) { - pc.iceGatherer.OnStateChange(f) +func (pc *PeerConnection) OnICEGatheringStateChange(f func(ICEGatheringState)) { + pc.iceGatherer.OnStateChange( + func(gathererState ICEGathererState) { + switch gathererState { + case ICEGathererStateGathering: + f(ICEGatheringStateGathering) + case ICEGathererStateComplete: + f(ICEGatheringStateComplete) + default: + // Other states ignored + } + }) } // OnTrack sets an event handler which is called when remote track @@ -488,7 +497,7 @@ func (pc *PeerConnection) onICEConnectionStateChange(cs ICEConnectionState) { } // OnConnectionStateChange sets an event handler which is called -// when the PeerConnectionState has changed +// when the PeerConnectionState has changed. func (pc *PeerConnection) OnConnectionStateChange(f func(PeerConnectionState)) { pc.onConnectionStateChangeHandler.Store(f) } @@ -502,7 +511,7 @@ func (pc *PeerConnection) onConnectionStateChange(cs PeerConnectionState) { } // SetConfiguration updates the configuration of this PeerConnection object. -func (pc *PeerConnection) SetConfiguration(configuration Configuration) error { //nolint:gocognit +func (pc *PeerConnection) SetConfiguration(configuration Configuration) error { //nolint:gocognit,cyclop // https://www.w3.org/TR/webrtc/#dom-rtcpeerconnection-setconfiguration (step #2) if pc.isClosed.get() { return &rtcerr.InvalidStateError{Err: ErrConnectionClosed} @@ -531,7 +540,7 @@ func (pc *PeerConnection) SetConfiguration(configuration Configuration) error { } // https://www.w3.org/TR/webrtc/#set-the-configuration (step #5) - if configuration.BundlePolicy != BundlePolicy(Unknown) { + if configuration.BundlePolicy != BundlePolicyUnknown { if configuration.BundlePolicy != pc.configuration.BundlePolicy { return &rtcerr.InvalidModificationError{Err: ErrModifyingBundlePolicy} } @@ -539,7 +548,7 @@ func (pc *PeerConnection) SetConfiguration(configuration Configuration) error { } // https://www.w3.org/TR/webrtc/#set-the-configuration (step #6) - if configuration.RTCPMuxPolicy != RTCPMuxPolicy(Unknown) { + if configuration.RTCPMuxPolicy != RTCPMuxPolicyUnknown { if configuration.RTCPMuxPolicy != pc.configuration.RTCPMuxPolicy { return &rtcerr.InvalidModificationError{Err: ErrModifyingRTCPMuxPolicy} } @@ -556,9 +565,7 @@ func (pc *PeerConnection) SetConfiguration(configuration Configuration) error { } // https://www.w3.org/TR/webrtc/#set-the-configuration (step #8) - if configuration.ICETransportPolicy != ICETransportPolicy(Unknown) { - pc.configuration.ICETransportPolicy = configuration.ICETransportPolicy - } + pc.configuration.ICETransportPolicy = configuration.ICETransportPolicy // https://www.w3.org/TR/webrtc/#set-the-configuration (step #11) if len(configuration.ICEServers) > 0 { @@ -570,6 +577,7 @@ func (pc *PeerConnection) SetConfiguration(configuration Configuration) error { } pc.configuration.ICEServers = configuration.ICEServers } + return nil } @@ -585,11 +593,12 @@ func (pc *PeerConnection) GetConfiguration() Configuration { func (pc *PeerConnection) getStatsID() string { pc.mu.RLock() defer pc.mu.RUnlock() + return pc.statsID } // hasLocalDescriptionChanged returns whether local media (rtpTransceivers) has changed -// caller of this method should hold `pc.mu` lock +// caller of this method should hold `pc.mu` lock. func (pc *PeerConnection) hasLocalDescriptionChanged(desc *SessionDescription) bool { for _, t := range pc.rtpTransceivers { m := getByMid(t.Mid(), desc) @@ -601,12 +610,15 @@ func (pc *PeerConnection) hasLocalDescriptionChanged(desc *SessionDescription) b return true } } + return false } // CreateOffer starts the PeerConnection and generates the localDescription // https://w3c.github.io/webrtc-pc/#dom-rtcpeerconnection-createoffer -func (pc *PeerConnection) CreateOffer(options *OfferOptions) (SessionDescription, error) { //nolint:gocognit +// +//nolint:gocognit,cyclop +func (pc *PeerConnection) CreateOffer(options *OfferOptions) (SessionDescription, error) { useIdentity := pc.idpLoginURL != nil switch { case useIdentity: @@ -622,7 +634,7 @@ func (pc *PeerConnection) CreateOffer(options *OfferOptions) (SessionDescription } var ( - d *sdp.SessionDescription + descr *sdp.SessionDescription offer SessionDescription err error ) @@ -648,7 +660,7 @@ func (pc *PeerConnection) CreateOffer(options *OfferOptions) (SessionDescription } // include unmatched local transceivers - if !isPlanB { + if !isPlanB { //nolint:nestif // update the greater mid if the remote description provides a greater one if pc.currentRemoteDescription != nil { var numericMid int @@ -674,6 +686,7 @@ func (pc *PeerConnection) CreateOffer(options *OfferOptions) (SessionDescription pc.greaterMid = numericMid } } + continue } pc.greaterMid++ @@ -685,17 +698,22 @@ func (pc *PeerConnection) CreateOffer(options *OfferOptions) (SessionDescription } if pc.currentRemoteDescription == nil { - d, err = pc.generateUnmatchedSDP(currentTransceivers, useIdentity) + descr, err = pc.generateUnmatchedSDP(currentTransceivers, useIdentity) } else { - d, err = pc.generateMatchedSDP(currentTransceivers, useIdentity, true /*includeUnmatched */, connectionRoleFromDtlsRole(defaultDtlsRoleOffer)) + descr, err = pc.generateMatchedSDP( + currentTransceivers, + useIdentity, + true, /*includeUnmatched */ + connectionRoleFromDtlsRole(defaultDtlsRoleOffer), + ) } if err != nil { return SessionDescription{}, err } - updateSDPOrigin(&pc.sdpOrigin, d) - sdpBytes, err := d.Marshal() + updateSDPOrigin(&pc.sdpOrigin, descr) + sdpBytes, err := descr.Marshal() if err != nil { return SessionDescription{}, err } @@ -703,7 +721,7 @@ func (pc *PeerConnection) CreateOffer(options *OfferOptions) (SessionDescription offer = SessionDescription{ Type: SDPTypeOffer, SDP: string(sdpBytes), - parsed: d, + parsed: descr, } // Verify local media hasn't changed during offer @@ -718,6 +736,7 @@ func (pc *PeerConnection) CreateOffer(options *OfferOptions) (SessionDescription } pc.lastOffer = offer.SDP + return offer, nil } @@ -735,7 +754,12 @@ func (pc *PeerConnection) createICEGatherer() (*ICEGatherer, error) { // Update the PeerConnectionState given the state of relevant transports // https://www.w3.org/TR/webrtc/#rtcpeerconnectionstate-enum -func (pc *PeerConnection) updateConnectionState(iceConnectionState ICEConnectionState, dtlsTransportState DTLSTransportState) { +// +//nolint:cyclop +func (pc *PeerConnection) updateConnectionState( + iceConnectionState ICEConnectionState, + dtlsTransportState DTLSTransportState, +) { connectionState := PeerConnectionStateNew switch { // The RTCPeerConnection object's [[IsClosed]] slot is true. @@ -765,7 +789,8 @@ func (pc *PeerConnection) updateConnectionState(iceConnectionState ICEConnection // All RTCIceTransports and RTCDtlsTransports are in the "connected", "completed" or "closed" // state and all RTCDtlsTransports are in the "connected" or "closed" state. - case (iceConnectionState == ICEConnectionStateConnected || iceConnectionState == ICEConnectionStateCompleted || iceConnectionState == ICEConnectionStateClosed) && + case (iceConnectionState == ICEConnectionStateConnected || + iceConnectionState == ICEConnectionStateCompleted || iceConnectionState == ICEConnectionStateClosed) && (dtlsTransportState == DTLSTransportStateConnected || dtlsTransportState == DTLSTransportStateClosed): connectionState = PeerConnectionStateConnected } @@ -778,8 +803,8 @@ func (pc *PeerConnection) updateConnectionState(iceConnectionState ICEConnection } func (pc *PeerConnection) createICETransport() *ICETransport { - t := pc.api.NewICETransport(pc.iceGatherer) - t.internalOnConnectionStateChangeHandler.Store(func(state ICETransportState) { + transport := pc.api.NewICETransport(pc.iceGatherer) + transport.internalOnConnectionStateChangeHandler.Store(func(state ICETransportState) { var cs ICEConnectionState switch state { case ICETransportStateNew: @@ -798,16 +823,19 @@ func (pc *PeerConnection) createICETransport() *ICETransport { cs = ICEConnectionStateClosed default: pc.log.Warnf("OnConnectionStateChange: unhandled ICE state: %s", state) + return } pc.onICEConnectionStateChange(cs) pc.updateConnectionState(cs, pc.dtlsTransport.State()) }) - return t + return transport } -// CreateAnswer starts the PeerConnection and generates the localDescription +// CreateAnswer starts the PeerConnection and generates the localDescription. +// +//nolint:cyclop func (pc *PeerConnection) CreateAnswer(*AnswerOptions) (SessionDescription, error) { useIdentity := pc.idpLoginURL != nil remoteDesc := pc.RemoteDescription() @@ -818,7 +846,8 @@ func (pc *PeerConnection) CreateAnswer(*AnswerOptions) (SessionDescription, erro return SessionDescription{}, errIdentityProviderNotImplemented case pc.isClosed.get(): return SessionDescription{}, &rtcerr.InvalidStateError{Err: ErrConnectionClosed} - case pc.signalingState.Get() != SignalingStateHaveRemoteOffer && pc.signalingState.Get() != SignalingStateHaveLocalPranswer: + case pc.signalingState.Get() != SignalingStateHaveRemoteOffer && + pc.signalingState.Get() != SignalingStateHaveLocalPranswer: return SessionDescription{}, &rtcerr.InvalidStateError{Err: ErrIncorrectSignalingState} } @@ -826,7 +855,7 @@ func (pc *PeerConnection) CreateAnswer(*AnswerOptions) (SessionDescription, erro if connectionRole == sdp.ConnectionRole(0) { connectionRole = connectionRoleFromDtlsRole(defaultDtlsRoleAnswer) - // If one of the agents is lite and the other one is not, the lite agent must be the controlling agent. + // If one of the agents is lite and the other one is not, the lite agent must be the controlled agent. // If both or neither agents are lite the offering agent is controlling. // RFC 8445 S6.1.1 if isIceLiteSet(remoteDesc.parsed) && !pc.api.settingEngine.candidates.ICELite { @@ -836,13 +865,13 @@ func (pc *PeerConnection) CreateAnswer(*AnswerOptions) (SessionDescription, erro pc.mu.Lock() defer pc.mu.Unlock() - d, err := pc.generateMatchedSDP(pc.rtpTransceivers, useIdentity, false /*includeUnmatched */, connectionRole) + descr, err := pc.generateMatchedSDP(pc.rtpTransceivers, useIdentity, false /*includeUnmatched */, connectionRole) if err != nil { return SessionDescription{}, err } - updateSDPOrigin(&pc.sdpOrigin, d) - sdpBytes, err := d.Marshal() + updateSDPOrigin(&pc.sdpOrigin, descr) + sdpBytes, err := descr.Marshal() if err != nil { return SessionDescription{}, err } @@ -850,19 +879,24 @@ func (pc *PeerConnection) CreateAnswer(*AnswerOptions) (SessionDescription, erro desc := SessionDescription{ Type: SDPTypeAnswer, SDP: string(sdpBytes), - parsed: d, + parsed: descr, } pc.lastAnswer = desc.SDP + return desc, nil } // 4.4.1.6 Set the SessionDescription -func (pc *PeerConnection) setDescription(sd *SessionDescription, op stateChangeOp) error { //nolint:gocognit +// +//nolint:gocognit,cyclop +func (pc *PeerConnection) setDescription(sd *SessionDescription, op stateChangeOp) error { switch { case pc.isClosed.get(): return &rtcerr.InvalidStateError{Err: ErrConnectionClosed} - case NewSDPType(sd.Type.String()) == SDPType(Unknown): - return &rtcerr.TypeError{Err: fmt.Errorf("%w: '%d' is not a valid enum value of type SDPType", errPeerConnSDPTypeInvalidValue, sd.Type)} + case NewSDPType(sd.Type.String()) == SDPTypeUnknown: + return &rtcerr.TypeError{ + Err: fmt.Errorf("%w: '%d' is not a valid enum value of type SDPType", errPeerConnSDPTypeInvalidValue, sd.Type), + } } nextState, err := func() (SignalingState, error) { @@ -968,10 +1002,13 @@ func (pc *PeerConnection) setDescription(sd *SessionDescription, op stateChangeO } pc.onSignalingStateChange(nextState) } + return err } // SetLocalDescription sets the SessionDescription of the local peer +// +//nolint:cyclop func (pc *PeerConnection) SetLocalDescription(desc SessionDescription) error { if pc.isClosed.get() { return &rtcerr.InvalidStateError{Err: ErrConnectionClosed} @@ -994,7 +1031,7 @@ func (pc *PeerConnection) SetLocalDescription(desc SessionDescription) error { } desc.parsed = &sdp.SessionDescription{} - if err := desc.parsed.Unmarshal([]byte(desc.SDP)); err != nil { + if err := desc.parsed.UnmarshalString(desc.SDP); err != nil { return err } if err := pc.setDescription(&desc, stateChangeOpSetLocal); err != nil { @@ -1016,9 +1053,15 @@ func (pc *PeerConnection) SetLocalDescription(desc SessionDescription) error { }) } + mediaSection, ok := selectCandidateMediaSection(desc.parsed) + if ok { + pc.iceGatherer.setMediaStreamIdentification(mediaSection.SDPMid, mediaSection.SDPMLineIndex) + } + if pc.iceGatherer.State() == ICEGathererStateNew { return pc.iceGatherer.Gather() } + return nil } @@ -1030,16 +1073,19 @@ func (pc *PeerConnection) LocalDescription() *SessionDescription { if pendingLocalDescription := pc.PendingLocalDescription(); pendingLocalDescription != nil { return pendingLocalDescription } + return pc.CurrentLocalDescription() } // SetRemoteDescription sets the SessionDescription of the remote peer -func (pc *PeerConnection) SetRemoteDescription(desc SessionDescription) error { //nolint:gocognit,gocyclo +// +//nolint:gocognit,gocyclo,cyclop,maintidx +func (pc *PeerConnection) SetRemoteDescription(desc SessionDescription) error { if pc.isClosed.get() { return &rtcerr.InvalidStateError{Err: ErrConnectionClosed} } - isRenegotation := pc.currentRemoteDescription != nil + isRenegotiation := pc.currentRemoteDescription != nil if _, err := desc.Unmarshal(); err != nil { return err @@ -1052,7 +1098,12 @@ func (pc *PeerConnection) SetRemoteDescription(desc SessionDescription) error { return err } - var t *RTPTransceiver + // Disable RTX/FEC on RTPSenders if the remote didn't support it + for _, sender := range pc.GetSenders() { + sender.configureRTXAndFEC() + } + + var transceiver *RTPTransceiver localTransceivers := append([]*RTPTransceiver{}, pc.GetTransceivers()...) detectedPlanB := descriptionIsPlanB(pc.RemoteDescription(), pc.log) if pc.configuration.SDPSemantics != SDPSemanticsUnifiedPlan { @@ -1061,7 +1112,7 @@ func (pc *PeerConnection) SetRemoteDescription(desc SessionDescription) error { weOffer := desc.Type == SDPTypeAnswer - if !weOffer && !detectedPlanB { + if !weOffer && !detectedPlanB { //nolint:nestif for _, media := range pc.RemoteDescription().parsed.MediaDescriptions { midValue := getMidValue(media) if midValue == "" { @@ -1074,21 +1125,21 @@ func (pc *PeerConnection) SetRemoteDescription(desc SessionDescription) error { kind := NewRTPCodecType(media.MediaName.Media) direction := getPeerDirection(media) - if kind == 0 || direction == RTPTransceiverDirection(Unknown) { + if kind == 0 || direction == RTPTransceiverDirectionUnknown { continue } - t, localTransceivers = findByMid(midValue, localTransceivers) - if t == nil { - t, localTransceivers = satisfyTypeAndDirection(kind, direction, localTransceivers) + transceiver, localTransceivers = findByMid(midValue, localTransceivers) + if transceiver == nil { + transceiver, localTransceivers = satisfyTypeAndDirection(kind, direction, localTransceivers) } else if direction == RTPTransceiverDirectionInactive { - if err := t.Stop(); err != nil { + if err := transceiver.Stop(); err != nil { return err } } switch { - case t == nil: + case transceiver == nil: receiver, err := pc.api.NewRTPReceiver(kind, pc.dtlsTransport) if err != nil { return err @@ -1101,48 +1152,59 @@ func (pc *PeerConnection) SetRemoteDescription(desc SessionDescription) error { localDirection = RTPTransceiverDirectionInactive } - t = newRTPTransceiver(receiver, nil, localDirection, kind, pc.api) + transceiver = newRTPTransceiver(receiver, nil, localDirection, kind, pc.api) pc.mu.Lock() - pc.addRTPTransceiver(t) + pc.addRTPTransceiver(transceiver) pc.mu.Unlock() // if transceiver is create by remote sdp, set prefer codec same as remote peer if codecs, err := codecsFromMediaDescription(media); err == nil { filteredCodecs := []RTPCodecParameters{} for _, codec := range codecs { - if c, matchType := codecParametersFuzzySearch(codec, pc.api.mediaEngine.getCodecsByKind(kind)); matchType == codecMatchExact { + if c, matchType := codecParametersFuzzySearch( + codec, + pc.api.mediaEngine.getCodecsByKind(kind), + ); matchType == codecMatchExact { // if codec match exact, use payloadtype register to mediaengine codec.PayloadType = c.PayloadType filteredCodecs = append(filteredCodecs, codec) } } - _ = t.SetCodecPreferences(filteredCodecs) + _ = transceiver.SetCodecPreferences(filteredCodecs) } case direction == RTPTransceiverDirectionRecvonly: - if t.Direction() == RTPTransceiverDirectionSendrecv { - t.setDirection(RTPTransceiverDirectionSendonly) + if transceiver.Direction() == RTPTransceiverDirectionSendrecv { + transceiver.setDirection(RTPTransceiverDirectionSendonly) + } else if transceiver.Direction() == RTPTransceiverDirectionRecvonly { + transceiver.setDirection(RTPTransceiverDirectionInactive) } case direction == RTPTransceiverDirectionSendrecv: - if t.Direction() == RTPTransceiverDirectionSendonly { - t.setDirection(RTPTransceiverDirectionSendrecv) + if transceiver.Direction() == RTPTransceiverDirectionSendonly { + transceiver.setDirection(RTPTransceiverDirectionSendrecv) + } else if transceiver.Direction() == RTPTransceiverDirectionInactive { + transceiver.setDirection(RTPTransceiverDirectionRecvonly) + } + case direction == RTPTransceiverDirectionSendonly: + if transceiver.Direction() == RTPTransceiverDirectionInactive { + transceiver.setDirection(RTPTransceiverDirectionRecvonly) } } - if t.Mid() == "" { - if err := t.SetMid(midValue); err != nil { + if transceiver.Mid() == "" { + if err := transceiver.SetMid(midValue); err != nil { return err } } } } - remoteUfrag, remotePwd, candidates, err := extractICEDetails(desc.parsed, pc.log) + iceDetails, err := extractICEDetails(desc.parsed, pc.log) if err != nil { return err } - if isRenegotation && pc.iceTransport.haveRemoteCredentialsChange(remoteUfrag, remotePwd) { + if isRenegotiation && pc.iceTransport.haveRemoteCredentialsChange(iceDetails.Ufrag, iceDetails.Password) { // An ICE Restart only happens implicitly for a SetRemoteDescription of type offer if !weOffer { if err = pc.iceTransport.restart(); err != nil { @@ -1150,20 +1212,20 @@ func (pc *PeerConnection) SetRemoteDescription(desc SessionDescription) error { } } - if err = pc.iceTransport.setRemoteCredentials(remoteUfrag, remotePwd); err != nil { + if err = pc.iceTransport.setRemoteCredentials(iceDetails.Ufrag, iceDetails.Password); err != nil { return err } } - for i := range candidates { - if err = pc.iceTransport.AddRemoteCandidate(&candidates[i]); err != nil { + for i := range iceDetails.Candidates { + if err = pc.iceTransport.AddRemoteCandidate(&iceDetails.Candidates[i]); err != nil { return err } } currentTransceivers := append([]*RTPTransceiver{}, pc.GetTransceivers()...) - if isRenegotation { + if isRenegotiation { if weOffer { _ = setRTPTransceiverCurrentDirection(&desc, currentTransceivers, true) if err = pc.startRTPSenders(currentTransceivers); err != nil { @@ -1174,6 +1236,7 @@ func (pc *PeerConnection) SetRemoteDescription(desc SessionDescription) error { pc.startRTP(true, &desc, currentTransceivers) }) } + return nil } @@ -1185,10 +1248,11 @@ func (pc *PeerConnection) SetRemoteDescription(desc SessionDescription) error { } iceRole := ICERoleControlled - // If one of the agents is lite and the other one is not, the lite agent must be the controlling agent. + // If one of the agents is lite and the other one is not, the lite agent must be the controlled agent. // If both or neither agents are lite the offering agent is controlling. // RFC 8445 S6.1.1 - if (weOffer && remoteIsLite == pc.api.settingEngine.candidates.ICELite) || (remoteIsLite && !pc.api.settingEngine.candidates.ICELite) { + if (weOffer && remoteIsLite == pc.api.settingEngine.candidates.ICELite) || + (remoteIsLite && !pc.api.settingEngine.candidates.ICELite) { iceRole = ICERoleControlling } @@ -1204,11 +1268,19 @@ func (pc *PeerConnection) SetRemoteDescription(desc SessionDescription) error { } pc.ops.Enqueue(func() { - pc.startTransports(iceRole, dtlsRoleFromRemoteSDP(desc.parsed), remoteUfrag, remotePwd, fingerprint, fingerprintHash) + pc.startTransports( + iceRole, + dtlsRoleFromRemoteSDP(desc.parsed), + iceDetails.Ufrag, + iceDetails.Password, + fingerprint, + fingerprintHash, + ) if weOffer { pc.startRTP(false, &desc, currentTransceivers) } }) + return nil } @@ -1228,33 +1300,46 @@ func (pc *PeerConnection) configureReceiver(incoming trackDetails, receiver *RTP func (pc *PeerConnection) startReceiver(incoming trackDetails, receiver *RTPReceiver) { if err := receiver.startReceive(trackDetailsToRTPReceiveParameters(&incoming)); err != nil { pc.log.Warnf("RTPReceiver Receive failed %s", err) + return } - for _, t := range receiver.Tracks() { - if t.SSRC() == 0 || t.RID() != "" { + for _, track := range receiver.Tracks() { + if track.SSRC() == 0 || track.RID() != "" { return } + if pc.api.settingEngine.fireOnTrackBeforeFirstRTP { + pc.onTrack(track, receiver) + + return + } go func(track *TrackRemote) { b := make([]byte, pc.api.settingEngine.getReceiveMTU()) n, _, err := track.peek(b) if err != nil { pc.log.Warnf("Could not determine PayloadType for SSRC %d (%s)", track.SSRC(), err) + return } if err = track.checkAndUpdateTrack(b[:n]); err != nil { pc.log.Warnf("Failed to set codec settings for track SSRC %d (%s)", track.SSRC(), err) + return } pc.onTrack(track, receiver) - }(t) + }(track) } } -func setRTPTransceiverCurrentDirection(answer *SessionDescription, currentTransceivers []*RTPTransceiver, weOffer bool) error { +//nolint:cyclop +func setRTPTransceiverCurrentDirection( + answer *SessionDescription, + currentTransceivers []*RTPTransceiver, + weOffer bool, +) error { currentTransceivers = append([]*RTPTransceiver{}, currentTransceivers...) for _, media := range answer.parsed.MediaDescriptions { midValue := getMidValue(media) @@ -1266,15 +1351,15 @@ func setRTPTransceiverCurrentDirection(answer *SessionDescription, currentTransc continue } - var t *RTPTransceiver - t, currentTransceivers = findByMid(midValue, currentTransceivers) + var transceiver *RTPTransceiver + transceiver, currentTransceivers = findByMid(midValue, currentTransceivers) - if t == nil { + if transceiver == nil { return fmt.Errorf("%w: %q", errPeerConnTranscieverMidNil, midValue) } direction := getPeerDirection(media) - if direction == RTPTransceiverDirection(Unknown) { + if direction == RTPTransceiverDirectionUnknown { continue } @@ -1292,19 +1377,20 @@ func setRTPTransceiverCurrentDirection(answer *SessionDescription, currentTransc // If a transceiver is created by applying a remote description that has recvonly transceiver, // it will have no sender. In this case, the transceiver's current direction is set to inactive so // that the transceiver can be reused by next AddTrack. - if direction == RTPTransceiverDirectionSendonly && t.Sender() == nil { + if !weOffer && direction == RTPTransceiverDirectionSendonly && transceiver.Sender() == nil { direction = RTPTransceiverDirectionInactive } - t.setCurrentDirection(direction) + transceiver.setCurrentDirection(direction) } + return nil } func runIfNewReceiver( incomingTrack trackDetails, transceivers []*RTPTransceiver, - f func(incomingTrack trackDetails, receiver *RTPReceiver), + callbackFunc func(incomingTrack trackDetails, receiver *RTPReceiver), ) bool { for _, t := range transceivers { if t.Mid() != incomingTrack.mid { @@ -1319,53 +1405,62 @@ func runIfNewReceiver( continue } - f(incomingTrack, receiver) + callbackFunc(incomingTrack, receiver) + return true } return false } -// configurepRTPReceivers opens knows inbound SRTP streams from the RemoteDescription -func (pc *PeerConnection) configureRTPReceivers(isRenegotiation bool, remoteDesc *SessionDescription, currentTransceivers []*RTPTransceiver) { //nolint:gocognit +// configureRTPReceivers opens knows inbound SRTP streams from the RemoteDescription. +// +//nolint:gocognit,cyclop +func (pc *PeerConnection) configureRTPReceivers( + isRenegotiation bool, + remoteDesc *SessionDescription, + currentTransceivers []*RTPTransceiver, +) { incomingTracks := trackDetailsFromSDP(pc.log, remoteDesc.parsed) - if isRenegotiation { - for _, t := range currentTransceivers { - receiver := t.Receiver() + if isRenegotiation { //nolint:nestif + for _, transceiver := range currentTransceivers { + receiver := transceiver.Receiver() if receiver == nil { continue } - tracks := t.Receiver().Tracks() + tracks := transceiver.Receiver().Tracks() if len(tracks) == 0 { continue } - mid := t.Mid() + mid := transceiver.Mid() receiverNeedsStopped := false - func() { - for _, t := range tracks { - t.mu.Lock() - defer t.mu.Unlock() + for _, trackRemote := range tracks { + func(track *TrackRemote) { + track.mu.Lock() + defer track.mu.Unlock() - if t.rid != "" { - if details := trackDetailsForRID(incomingTracks, mid, t.rid); details != nil { - t.id = details.id - t.streamID = details.streamID - continue + if track.rid != "" { + if details := trackDetailsForRID(incomingTracks, mid, track.rid); details != nil { + track.id = details.id + track.streamID = details.streamID + + return } - } else if t.ssrc != 0 { - if details := trackDetailsForSSRC(incomingTracks, t.ssrc); details != nil { - t.id = details.id - t.streamID = details.streamID - continue + } else if track.ssrc != 0 { + if details := trackDetailsForSSRC(incomingTracks, track.ssrc); details != nil { + track.id = details.id + track.streamID = details.streamID + + return } } receiverNeedsStopped = true - } - }() + }(trackRemote) + } if !receiverNeedsStopped { continue @@ -1373,15 +1468,17 @@ func (pc *PeerConnection) configureRTPReceivers(isRenegotiation bool, remoteDesc if err := receiver.Stop(); err != nil { pc.log.Warnf("Failed to stop RtpReceiver: %s", err) + continue } receiver, err := pc.api.NewRTPReceiver(receiver.kind, pc.dtlsTransport) if err != nil { pc.log.Warnf("Failed to create new RtpReceiver: %s", err) + continue } - t.setReceiver(receiver) + transceiver.setReceiver(receiver) } } @@ -1409,7 +1506,7 @@ func (pc *PeerConnection) configureRTPReceivers(isRenegotiation bool, remoteDesc } } -// startRTPReceivers opens knows inbound SRTP streams from the RemoteDescription +// startRTPReceivers opens knows inbound SRTP streams from the RemoteDescription. func (pc *PeerConnection) startRTPReceivers(remoteDesc *SessionDescription, currentTransceivers []*RTPTransceiver) { incomingTracks := trackDetailsFromSDP(pc.log, remoteDesc.parsed) if len(incomingTracks) == 0 { @@ -1443,6 +1540,7 @@ func (pc *PeerConnection) startRTPReceivers(remoteDesc *SessionDescription, curr }) if err != nil { pc.log.Warnf("Could not add transceiver for remote SSRC %d: %s", incomingTrack.ssrcs[0], err) + continue } pc.configureReceiver(incomingTrack, t.Receiver()) @@ -1451,7 +1549,7 @@ func (pc *PeerConnection) startRTPReceivers(remoteDesc *SessionDescription, curr } } -// startRTPSenders starts all outbound RTP streams +// startRTPSenders starts all outbound RTP streams. func (pc *PeerConnection) startRTPSenders(currentTransceivers []*RTPTransceiver) error { for _, transceiver := range currentTransceivers { if sender := transceiver.Sender(); sender != nil && sender.isNegotiated() && !sender.hasSent() { @@ -1465,11 +1563,11 @@ func (pc *PeerConnection) startRTPSenders(currentTransceivers []*RTPTransceiver) return nil } -// Start SCTP subsystem -func (pc *PeerConnection) startSCTP() { +// Start SCTP subsystem. +func (pc *PeerConnection) startSCTP(maxMessageSize uint32) { // Start sctp if err := pc.sctpTransport.Start(SCTPCapabilities{ - MaxMessageSize: 0, + MaxMessageSize: maxMessageSize, }); err != nil { pc.log.Warnf("Failed to start SCTP: %s", err) if err = pc.sctpTransport.Stop(); err != nil { @@ -1480,18 +1578,16 @@ func (pc *PeerConnection) startSCTP() { } } -func (pc *PeerConnection) handleUndeclaredSSRC(ssrc SSRC, remoteDescription *SessionDescription) (handled bool, err error) { - if len(remoteDescription.parsed.MediaDescriptions) != 1 { - return false, nil - } - - onlyMediaSection := remoteDescription.parsed.MediaDescriptions[0] +func (pc *PeerConnection) handleUndeclaredSSRC( + ssrc SSRC, + mediaSection *sdp.MediaDescription, +) (handled bool, err error) { streamID := "" id := "" hasRidAttribute := false hasSSRCAttribute := false - for _, a := range onlyMediaSection.Attributes { + for _, a := range mediaSection.Attributes { switch a.Key { case sdp.AttrKeyMsid: if split := strings.Split(a.Value, " "); len(split) == 2 { @@ -1508,7 +1604,7 @@ func (pc *PeerConnection) handleUndeclaredSSRC(ssrc SSRC, remoteDescription *Ses if hasRidAttribute { return false, nil } else if hasSSRCAttribute { - return false, errPeerConnSingleMediaSectionHasExplicitSSRC + return false, errMediaSectionHasExplictSSRCAttribute } incoming := trackDetails{ @@ -1517,7 +1613,7 @@ func (pc *PeerConnection) handleUndeclaredSSRC(ssrc SSRC, remoteDescription *Ses streamID: streamID, id: id, } - if onlyMediaSection.MediaName.Media == RTPCodecTypeAudio.String() { + if mediaSection.MediaName.Media == RTPCodecTypeAudio.String() { incoming.kind = RTPCodecTypeAudio } @@ -1531,10 +1627,72 @@ func (pc *PeerConnection) handleUndeclaredSSRC(ssrc SSRC, remoteDescription *Ses pc.configureReceiver(incoming, t.Receiver()) pc.startReceiver(incoming, t.Receiver()) + return true, nil } -func (pc *PeerConnection) handleIncomingSSRC(rtpStream io.Reader, ssrc SSRC) error { //nolint:gocognit +// For legacy clients that didn't support urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id +// or urn:ietf:params:rtp-hdrext:sdes:mid extension, and didn't declare a=ssrc lines. +// Assumes that the payload type is unique across the media section. +func (pc *PeerConnection) findMediaSectionByPayloadType( + payloadType PayloadType, + remoteDescription *SessionDescription, +) (selectedMediaSection *sdp.MediaDescription, ok bool) { + for i := range remoteDescription.parsed.MediaDescriptions { + descr := remoteDescription.parsed.MediaDescriptions[i] + media := descr.MediaName.Media + if !strings.EqualFold(media, "video") && !strings.EqualFold(media, "audio") { + continue + } + + formats := descr.MediaName.Formats + for _, payloadStr := range formats { + payload, err := strconv.ParseUint(payloadStr, 10, 8) + if err != nil { + continue + } + + // Return the first media section that has the payload type. + // Assuming that the payload type is unique across the media section. + if PayloadType(payload) == payloadType { + return remoteDescription.parsed.MediaDescriptions[i], true + } + } + } + + return nil, false +} + +// Chrome sends probing traffic on SSRC 0. This reads the packets to ensure that we properly +// generate TWCC reports for it. Since this isn't actually media we don't pass this to the user. +func (pc *PeerConnection) handleNonMediaBandwidthProbe() { + nonMediaBandwidthProbe, err := pc.api.NewRTPReceiver(RTPCodecTypeVideo, pc.dtlsTransport) + if err != nil { + pc.log.Errorf("handleNonMediaBandwidthProbe failed to create RTPReceiver: %v", err) + + return + } + + if err = nonMediaBandwidthProbe.Receive(RTPReceiveParameters{ + Encodings: []RTPDecodingParameters{{RTPCodingParameters: RTPCodingParameters{}}}, + }); err != nil { + pc.log.Errorf("handleNonMediaBandwidthProbe failed to start RTPReceiver: %v", err) + + return + } + + pc.nonMediaBandwidthProbe.Store(nonMediaBandwidthProbe) + b := make([]byte, pc.api.settingEngine.getReceiveMTU()) + for { + if _, _, err = nonMediaBandwidthProbe.readRTP(b, nonMediaBandwidthProbe.Track()); err != nil { + pc.log.Tracef("handleNonMediaBandwidthProbe read exiting: %v", err) + + return + } + } +} + +func (pc *PeerConnection) handleIncomingSSRC(rtpStream io.Reader, ssrc SSRC) error { //nolint:gocyclo,gocognit,cyclop remoteDescription := pc.RemoteDescription() if remoteDescription == nil { return errPeerConnRemoteDescriptionNil @@ -1552,23 +1710,20 @@ func (pc *PeerConnection) handleIncomingSSRC(rtpStream io.Reader, ssrc SSRC) err } } - // If the remote SDP was only one media section the ssrc doesn't have to be explicitly declared - if handled, err := pc.handleUndeclaredSSRC(ssrc, remoteDescription); handled || err != nil { - return err + // if the SSRC is not declared in the SDP and there is only one media section, + // we attempt to resolve it using this single section + // This applies even if the client supports RTP extensions: + // (urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id and urn:ietf:params:rtp-hdrext:sdes:mid) + // and even if the RTP stream contains an incorrect MID or RID. + // while this can be incorrect, this is done to maintain compatibility with older behavior. + if len(remoteDescription.parsed.MediaDescriptions) == 1 { + mediaSection := remoteDescription.parsed.MediaDescriptions[0] + if handled, err := pc.handleUndeclaredSSRC(ssrc, mediaSection); handled || err != nil { + return err + } } - midExtensionID, audioSupported, videoSupported := pc.api.mediaEngine.getHeaderExtensionID(RTPHeaderExtensionCapability{sdp.SDESMidURI}) - if !audioSupported && !videoSupported { - return errPeerConnSimulcastMidRTPExtensionRequired - } - - streamIDExtensionID, audioSupported, videoSupported := pc.api.mediaEngine.getHeaderExtensionID(RTPHeaderExtensionCapability{sdp.SDESRTPStreamIDURI}) - if !audioSupported && !videoSupported { - return errPeerConnSimulcastStreamIDRTPExtensionRequired - } - - repairStreamIDExtensionID, _, _ := pc.api.mediaEngine.getHeaderExtensionID(RTPHeaderExtensionCapability{sdesRepairRTPStreamIDURI}) - + // We read the RTP packet to determine the payload type b := make([]byte, pc.api.settingEngine.getReceiveMTU()) i, err := rtpStream.Read(b) @@ -1576,31 +1731,78 @@ func (pc *PeerConnection) handleIncomingSSRC(rtpStream io.Reader, ssrc SSRC) err return err } - var mid, rid, rsid string - payloadType, err := handleUnknownRTPPacket(b[:i], uint8(midExtensionID), uint8(streamIDExtensionID), uint8(repairStreamIDExtensionID), &mid, &rid, &rsid) - if err != nil { - return err + if i < 4 { + return errRTPTooShort } + payloadType := PayloadType(b[1] & 0x7f) params, err := pc.api.mediaEngine.getRTPParametersByPayloadType(payloadType) if err != nil { return err } - streamInfo := createStreamInfo("", ssrc, params.Codecs[0].PayloadType, params.Codecs[0].RTPCodecCapability, params.HeaderExtensions) + midExtensionID, audioSupported, videoSupported := pc.api.mediaEngine.getHeaderExtensionID( + RTPHeaderExtensionCapability{sdp.SDESMidURI}, + ) + if !audioSupported && !videoSupported { + // try to find media section by payload type as a last resort for legacy clients. + mediaSection, ok := pc.findMediaSectionByPayloadType(payloadType, remoteDescription) + if ok { + if ok, err = pc.handleUndeclaredSSRC(ssrc, mediaSection); ok || err != nil { + return err + } + } + + return errPeerConnSimulcastMidRTPExtensionRequired + } + + streamIDExtensionID, audioSupported, videoSupported := pc.api.mediaEngine.getHeaderExtensionID( + RTPHeaderExtensionCapability{sdp.SDESRTPStreamIDURI}, + ) + if !audioSupported && !videoSupported { + return errPeerConnSimulcastStreamIDRTPExtensionRequired + } + + repairStreamIDExtensionID, _, _ := pc.api.mediaEngine.getHeaderExtensionID( + RTPHeaderExtensionCapability{sdp.SDESRepairRTPStreamIDURI}, + ) + + streamInfo := createStreamInfo( + "", + ssrc, + 0, 0, + params.Codecs[0].PayloadType, + 0, 0, + params.Codecs[0].RTPCodecCapability, + params.HeaderExtensions, + ) readStream, interceptor, rtcpReadStream, rtcpInterceptor, err := pc.dtlsTransport.streamsForSSRC(ssrc, *streamInfo) if err != nil { return err } + var mid, rid, rsid string + var paddingOnly bool for readCount := 0; readCount <= simulcastProbeCount; readCount++ { if mid == "" || (rid == "" && rsid == "") { + // skip padding only packets for probing + if paddingOnly { + readCount-- + } + i, _, err := interceptor.Read(b, nil) if err != nil { return err } - if _, err = handleUnknownRTPPacket(b[:i], uint8(midExtensionID), uint8(streamIDExtensionID), uint8(repairStreamIDExtensionID), &mid, &rid, &rsid); err != nil { + if _, paddingOnly, err = handleUnknownRTPPacket( + b[:i], uint8(midExtensionID), //nolint:gosec // G115 + uint8(streamIDExtensionID), //nolint:gosec // G115 + uint8(repairStreamIDExtensionID), //nolint:gosec // G115 + &mid, + &rid, + &rsid, + ); err != nil { return err } @@ -1616,64 +1818,103 @@ func (pc *PeerConnection) handleIncomingSSRC(rtpStream io.Reader, ssrc SSRC) err if rsid != "" { receiver.mu.Lock() defer receiver.mu.Unlock() + return receiver.receiveForRtx(SSRC(0), rsid, streamInfo, readStream, interceptor, rtcpReadStream, rtcpInterceptor) } - track, err := receiver.receiveForRid(rid, params, streamInfo, readStream, interceptor, rtcpReadStream, rtcpInterceptor) + track, err := receiver.receiveForRid( + rid, + params, + streamInfo, + readStream, + interceptor, + rtcpReadStream, + rtcpInterceptor, + ) if err != nil { return err } pc.onTrack(track, receiver) + return nil } } pc.api.interceptor.UnbindRemoteStream(streamInfo) + return errPeerConnSimulcastIncomingSSRCFailed } -// undeclaredMediaProcessor handles RTP/RTCP packets that don't match any a:ssrc lines +// undeclaredMediaProcessor handles RTP/RTCP packets that don't match any a:ssrc lines. func (pc *PeerConnection) undeclaredMediaProcessor() { go pc.undeclaredRTPMediaProcessor() go pc.undeclaredRTCPMediaProcessor() } -func (pc *PeerConnection) undeclaredRTPMediaProcessor() { +func (pc *PeerConnection) undeclaredRTPMediaProcessor() { //nolint:cyclop var simulcastRoutineCount uint64 for { srtpSession, err := pc.dtlsTransport.getSRTPSession() if err != nil { pc.log.Warnf("undeclaredMediaProcessor failed to open SrtpSession: %v", err) + return } - stream, ssrc, err := srtpSession.AcceptStream() + srtcpSession, err := pc.dtlsTransport.getSRTCPSession() + if err != nil { + pc.log.Warnf("undeclaredMediaProcessor failed to open SrtcpSession: %v", err) + + return + } + + srtpReadStream, ssrc, err := srtpSession.AcceptStream() if err != nil { pc.log.Warnf("Failed to accept RTP %v", err) + + return + } + + // open accompanying srtcp stream + srtcpReadStream, err := srtcpSession.OpenReadStream(ssrc) + if err != nil { + pc.log.Warnf("Failed to open RTCP stream for %d: %v", ssrc, err) + return } if pc.isClosed.get() { - if err = stream.Close(); err != nil { + if err = srtpReadStream.Close(); err != nil { pc.log.Warnf("Failed to close RTP stream %v", err) } + if err = srtcpReadStream.Close(); err != nil { + pc.log.Warnf("Failed to close RTCP stream %v", err) + } + + continue + } + + pc.dtlsTransport.storeSimulcastStream(srtpReadStream, srtcpReadStream) + + if ssrc == 0 { + go pc.handleNonMediaBandwidthProbe() + continue } if atomic.AddUint64(&simulcastRoutineCount, 1) >= simulcastMaxProbeRoutines { atomic.AddUint64(&simulcastRoutineCount, ^uint64(0)) pc.log.Warn(ErrSimulcastProbeOverflow.Error()) - pc.dtlsTransport.storeSimulcastStream(stream) + continue } go func(rtpStream io.Reader, ssrc SSRC) { if err := pc.handleIncomingSSRC(rtpStream, ssrc); err != nil { pc.log.Errorf(incomingUnhandledRTPSsrc, ssrc, err) - pc.dtlsTransport.storeSimulcastStream(stream) } atomic.AddUint64(&simulcastRoutineCount, ^uint64(0)) - }(stream, SSRC(ssrc)) + }(srtpReadStream, SSRC(ssrc)) } } @@ -1688,12 +1929,14 @@ func (pc *PeerConnection) undeclaredRTCPMediaProcessor() { srtcpSession, err := pc.dtlsTransport.getSRTCPSession() if err != nil { pc.log.Warnf("undeclaredMediaProcessor failed to open SrtcpSession: %v", err) + return } stream, ssrc, err := srtcpSession.AcceptStream() if err != nil { pc.log.Warnf("Failed to accept RTCP %v", err) + return } pc.log.Warnf("Incoming unhandled RTCP ssrc(%d), OnTrack will not be fired", ssrc) @@ -1712,37 +1955,72 @@ func (pc *PeerConnection) RemoteDescription() *SessionDescription { if pc.pendingRemoteDescription != nil { return pc.pendingRemoteDescription } + return pc.currentRemoteDescription } // AddICECandidate accepts an ICE candidate string and adds it // to the existing set of candidates. func (pc *PeerConnection) AddICECandidate(candidate ICECandidateInit) error { - if pc.RemoteDescription() == nil { + remoteDesc := pc.RemoteDescription() + if remoteDesc == nil { return &rtcerr.InvalidStateError{Err: ErrNoRemoteDescription} } candidateValue := strings.TrimPrefix(candidate.Candidate, "candidate:") - var iceCandidate *ICECandidate - if candidateValue != "" { - candidate, err := ice.UnmarshalCandidate(candidateValue) - if err != nil { - if errors.Is(err, ice.ErrUnknownCandidateTyp) || errors.Is(err, ice.ErrDetermineNetworkType) { - pc.log.Warnf("Discarding remote candidate: %s", err) - return nil - } - return err - } - - c, err := newICECandidateFromICE(candidate) - if err != nil { - return err - } - iceCandidate = &c + if candidateValue == "" { + return pc.iceTransport.AddRemoteCandidate(nil) } - return pc.iceTransport.AddRemoteCandidate(iceCandidate) + cand, err := ice.UnmarshalCandidate(candidateValue) + if err != nil { + if errors.Is(err, ice.ErrUnknownCandidateTyp) || errors.Is(err, ice.ErrDetermineNetworkType) { + pc.log.Warnf("Discarding remote candidate: %s", err) + + return nil + } + + return err + } + + // Reject candidates from old generations. + // If candidate.usernameFragment is not null, + // and is not equal to any username fragment present in the corresponding media + // description of an applied remote description, + // return a promise rejected with a newly created OperationError. + // https://w3c.github.io/webrtc-pc/#dom-peerconnection-addicecandidate + if ufrag, ok := cand.GetExtension("ufrag"); ok { + if !pc.descriptionContainsUfrag(remoteDesc.parsed, ufrag.Value) { + pc.log.Errorf("dropping candidate with ufrag %s because it doesn't match the current ufrags", ufrag.Value) + + return nil + } + } + + c, err := newICECandidateFromICE(cand, "", 0) + if err != nil { + return err + } + + return pc.iceTransport.AddRemoteCandidate(&c) +} + +// Return true if the sdp contains a specific ufrag. +func (pc *PeerConnection) descriptionContainsUfrag(sdp *sdp.SessionDescription, matchUfrag string) bool { + ufrag, ok := sdp.Attribute("ice-ufrag") + if ok && ufrag == matchUfrag { + return true + } + + for _, media := range sdp.MediaDescriptions { + ufrag, ok := media.Attribute("ice-ufrag") + if ok && ufrag == matchUfrag { + return true + } + } + + return false } // ICEConnectionState returns the ICE connection state of the @@ -1751,10 +2029,11 @@ func (pc *PeerConnection) ICEConnectionState() ICEConnectionState { if state, ok := pc.iceConnectionState.Load().(ICEConnectionState); ok { return state } + return ICEConnectionState(0) } -// GetSenders returns the RTPSender that are currently attached to this PeerConnection +// GetSenders returns the RTPSender that are currently attached to this PeerConnection. func (pc *PeerConnection) GetSenders() (result []*RTPSender) { pc.mu.Lock() defer pc.mu.Unlock() @@ -1764,10 +2043,11 @@ func (pc *PeerConnection) GetSenders() (result []*RTPSender) { result = append(result, sender) } } + return result } -// GetReceivers returns the RTPReceivers that are currently attached to this PeerConnection +// GetReceivers returns the RTPReceivers that are currently attached to this PeerConnection. func (pc *PeerConnection) GetReceivers() (receivers []*RTPReceiver) { pc.mu.Lock() defer pc.mu.Unlock() @@ -1777,10 +2057,11 @@ func (pc *PeerConnection) GetReceivers() (receivers []*RTPReceiver) { receivers = append(receivers, receiver) } } + return } -// GetTransceivers returns the RtpTransceiver that are currently attached to this PeerConnection +// GetTransceivers returns the RtpTransceiver that are currently attached to this PeerConnection. func (pc *PeerConnection) GetTransceivers() []*RTPTransceiver { pc.mu.Lock() defer pc.mu.Unlock() @@ -1788,7 +2069,9 @@ func (pc *PeerConnection) GetTransceivers() []*RTPTransceiver { return pc.rtpTransceivers } -// AddTrack adds a Track to the PeerConnection +// AddTrack adds a Track to the PeerConnection. +// +//nolint:cyclop func (pc *PeerConnection) AddTrack(track TrackLocal) (*RTPSender, error) { if pc.isClosed.get() { return nil, &rtcerr.InvalidStateError{Err: ErrConnectionClosed} @@ -1796,26 +2079,27 @@ func (pc *PeerConnection) AddTrack(track TrackLocal) (*RTPSender, error) { pc.mu.Lock() defer pc.mu.Unlock() - for _, t := range pc.rtpTransceivers { - currentDirection := t.getCurrentDirection() + for _, transceiver := range pc.rtpTransceivers { + currentDirection := transceiver.getCurrentDirection() // According to https://www.w3.org/TR/webrtc/#dom-rtcpeerconnection-addtrack, if the // transceiver can be reused only if it's currentDirection never be sendrecv or sendonly. // But that will cause sdp inflate. So we only check currentDirection's current value, // that's worked for all browsers. - if !t.stopped && t.kind == track.Kind() && t.Sender() == nil && + if transceiver.kind == track.Kind() && transceiver.Sender() == nil && !(currentDirection == RTPTransceiverDirectionSendrecv || currentDirection == RTPTransceiverDirectionSendonly) { sender, err := pc.api.NewRTPSender(track, pc.dtlsTransport) if err == nil { - err = t.SetSender(sender, track) + err = transceiver.SetSender(sender, track) if err != nil { _ = sender.Stop() - t.setSender(nil) + transceiver.setSender(nil) } } if err != nil { return nil, err } pc.onNegotiationNeeded() + return sender, nil } } @@ -1825,10 +2109,11 @@ func (pc *PeerConnection) AddTrack(track TrackLocal) (*RTPSender, error) { return nil, err } pc.addRTPTransceiver(transceiver) + return transceiver.Sender(), nil } -// RemoveTrack removes a Track from the PeerConnection +// RemoveTrack removes a Track from the PeerConnection. func (pc *PeerConnection) RemoveTrack(sender *RTPSender) (err error) { if pc.isClosed.get() { return &rtcerr.InvalidStateError{Err: ErrConnectionClosed} @@ -1840,6 +2125,7 @@ func (pc *PeerConnection) RemoveTrack(sender *RTPSender) (err error) { for _, t := range pc.rtpTransceivers { if t.Sender() == sender { transceiver = t + break } } @@ -1851,34 +2137,52 @@ func (pc *PeerConnection) RemoveTrack(sender *RTPSender) (err error) { pc.onNegotiationNeeded() } } + return } -func (pc *PeerConnection) newTransceiverFromTrack(direction RTPTransceiverDirection, track TrackLocal) (t *RTPTransceiver, err error) { +//nolint:cyclop +func (pc *PeerConnection) newTransceiverFromTrack( + direction RTPTransceiverDirection, + track TrackLocal, + init ...RTPTransceiverInit, +) (t *RTPTransceiver, err error) { var ( - r *RTPReceiver - s *RTPSender + receiver *RTPReceiver + sender *RTPSender ) switch direction { case RTPTransceiverDirectionSendrecv: - r, err = pc.api.NewRTPReceiver(track.Kind(), pc.dtlsTransport) + receiver, err = pc.api.NewRTPReceiver(track.Kind(), pc.dtlsTransport) if err != nil { - return + return t, err } - s, err = pc.api.NewRTPSender(track, pc.dtlsTransport) + sender, err = pc.api.NewRTPSender(track, pc.dtlsTransport) case RTPTransceiverDirectionSendonly: - s, err = pc.api.NewRTPSender(track, pc.dtlsTransport) + sender, err = pc.api.NewRTPSender(track, pc.dtlsTransport) default: err = errPeerConnAddTransceiverFromTrackSupport } if err != nil { - return + return t, err } - return newRTPTransceiver(r, s, direction, track.Kind(), pc.api), nil + + // Allow RTPTransceiverInit to override SSRC + if sender != nil && len(sender.trackEncodings) == 1 && + len(init) == 1 && len(init[0].SendEncodings) == 1 && init[0].SendEncodings[0].SSRC != 0 { + sender.trackEncodings[0].ssrc = init[0].SendEncodings[0].SSRC + } + + return newRTPTransceiver(receiver, sender, direction, track.Kind(), pc.api), nil } // AddTransceiverFromKind Create a new RtpTransceiver and adds it to the set of transceivers. -func (pc *PeerConnection) AddTransceiverFromKind(kind RTPCodecType, init ...RTPTransceiverInit) (t *RTPTransceiver, err error) { +// +//nolint:cyclop +func (pc *PeerConnection) AddTransceiverFromKind( + kind RTPCodecType, + init ...RTPTransceiverInit, +) (t *RTPTransceiver, err error) { if pc.isClosed.get() { return nil, &rtcerr.InvalidStateError{Err: ErrConnectionClosed} } @@ -1899,7 +2203,7 @@ func (pc *PeerConnection) AddTransceiverFromKind(kind RTPCodecType, init ...RTPT if err != nil { return nil, err } - t, err = pc.newTransceiverFromTrack(direction, track) + t, err = pc.newTransceiverFromTrack(direction, track, init...) if err != nil { return nil, err } @@ -1915,11 +2219,15 @@ func (pc *PeerConnection) AddTransceiverFromKind(kind RTPCodecType, init ...RTPT pc.mu.Lock() pc.addRTPTransceiver(t) pc.mu.Unlock() + return t, nil } // AddTransceiverFromTrack Create a new RtpTransceiver(SendRecv or SendOnly) and add it to the set of transceivers. -func (pc *PeerConnection) AddTransceiverFromTrack(track TrackLocal, init ...RTPTransceiverInit) (t *RTPTransceiver, err error) { +func (pc *PeerConnection) AddTransceiverFromTrack( + track TrackLocal, + init ...RTPTransceiverInit, +) (t *RTPTransceiver, err error) { if pc.isClosed.get() { return nil, &rtcerr.InvalidStateError{Err: ErrConnectionClosed} } @@ -1931,18 +2239,21 @@ func (pc *PeerConnection) AddTransceiverFromTrack(track TrackLocal, init ...RTPT direction = init[0].Direction } - t, err = pc.newTransceiverFromTrack(direction, track) + t, err = pc.newTransceiverFromTrack(direction, track, init...) if err == nil { pc.mu.Lock() pc.addRTPTransceiver(t) pc.mu.Unlock() } + return } // CreateDataChannel creates a new DataChannel object with the given label // and optional DataChannelInit used to configure properties of the // underlying channel such as data reliability. +// +//nolint:cyclop func (pc *PeerConnection) CreateDataChannel(label string, options *DataChannelInit) (*DataChannel, error) { // https://w3c.github.io/webrtc-pc/#peer-to-peer-data-api (Step #2) if pc.isClosed.get() { @@ -1959,7 +2270,7 @@ func (pc *PeerConnection) CreateDataChannel(label string, options *DataChannelIn params.ID = options.ID } - if options != nil { + if options != nil { //nolint:nestif // Ordered indicates if data is allowed to be delivered out of order. The // default value of true, guarantees that data will be delivered in order. // https://w3c.github.io/webrtc-pc/#peer-to-peer-data-api (Step #9) @@ -1993,24 +2304,27 @@ func (pc *PeerConnection) CreateDataChannel(label string, options *DataChannelIn } } - d, err := pc.api.newDataChannel(params, nil, pc.log) + dataChannel, err := pc.api.newDataChannel(params, nil, pc.log) if err != nil { return nil, err } // https://w3c.github.io/webrtc-pc/#peer-to-peer-data-api (Step #16) - if d.maxPacketLifeTime != nil && d.maxRetransmits != nil { + if dataChannel.maxPacketLifeTime != nil && dataChannel.maxRetransmits != nil { return nil, &rtcerr.TypeError{Err: ErrRetransmitsOrPacketLifeTime} } pc.sctpTransport.lock.Lock() - pc.sctpTransport.dataChannels = append(pc.sctpTransport.dataChannels, d) + pc.sctpTransport.dataChannels = append(pc.sctpTransport.dataChannels, dataChannel) + if dataChannel.ID() != nil { + pc.sctpTransport.dataChannelIDsUsed[*dataChannel.ID()] = struct{}{} + } pc.sctpTransport.dataChannelsRequested++ pc.sctpTransport.lock.Unlock() // If SCTP already connected open all the channels if pc.sctpTransport.State() == SCTPTransportStateConnected { - if err = d.open(pc.sctpTransport); err != nil { + if err = dataChannel.open(pc.sctpTransport); err != nil { return nil, err } } @@ -2019,10 +2333,10 @@ func (pc *PeerConnection) CreateDataChannel(label string, options *DataChannelIn pc.onNegotiationNeeded() pc.mu.Unlock() - return d, nil + return dataChannel, nil } -// SetIdentityProvider is used to configure an identity provider to generate identity assertions +// SetIdentityProvider is used to configure an identity provider to generate identity assertions. func (pc *PeerConnection) SetIdentityProvider(string) error { return errPeerConnSetIdentityProviderNotImplemented } @@ -2031,6 +2345,7 @@ func (pc *PeerConnection) SetIdentityProvider(string) error { // packet is discarded. It also runs any configured interceptors. func (pc *PeerConnection) WriteRTCP(pkts []rtcp.Packet) error { _, err := pc.interceptorRTCPWriter.Write(pkts, make(interceptor.Attributes)) + return err } @@ -2038,16 +2353,60 @@ func (pc *PeerConnection) writeRTCP(pkts []rtcp.Packet, _ interceptor.Attributes return pc.dtlsTransport.WriteRTCP(pkts) } -// Close ends the PeerConnection +// Close ends the PeerConnection. func (pc *PeerConnection) Close() error { + return pc.close(false /* shouldGracefullyClose */) +} + +// GracefulClose ends the PeerConnection. It also waits +// for any goroutines it started to complete. This is only safe to call outside of +// PeerConnection callbacks or if in a callback, in its own goroutine. +func (pc *PeerConnection) GracefulClose() error { + return pc.close(true /* shouldGracefullyClose */) +} + +func (pc *PeerConnection) close(shouldGracefullyClose bool) error { //nolint:cyclop // https://www.w3.org/TR/webrtc/#dom-rtcpeerconnection-close (step #1) // https://www.w3.org/TR/webrtc/#dom-rtcpeerconnection-close (step #2) - if pc.isClosed.swap(true) { - return nil + + pc.mu.Lock() + // A lock in this critical section is needed because pc.isClosed and + // pc.isGracefullyClosingOrClosed are related to each other in that we + // want to make graceful and normal closure one time operations in order + // to avoid any double closure errors from cropping up. However, there are + // some overlapping close cases when both normal and graceful close are used + // that should be idempotent, but be cautioned when writing new close behavior + // to preserve this property. + isAlreadyClosingOrClosed := pc.isClosed.swap(true) + isAlreadyGracefullyClosingOrClosed := pc.isGracefullyClosingOrClosed + if shouldGracefullyClose && !isAlreadyGracefullyClosingOrClosed { + pc.isGracefullyClosingOrClosed = true + } + pc.mu.Unlock() + + if isAlreadyClosingOrClosed { + if !shouldGracefullyClose { + return nil + } + // Even if we're already closing, it may not be graceful: + // If we are not the ones doing the closing, we just wait for the graceful close + // to happen and then return. + if isAlreadyGracefullyClosingOrClosed { + <-pc.isGracefulCloseDone + + return nil + } + // Otherwise we need to go through the graceful closure flow once the + // normal closure is done since there are extra steps to take with a + // graceful close. + <-pc.isCloseDone + } else { + defer close(pc.isCloseDone) } - // https://www.w3.org/TR/webrtc/#dom-rtcpeerconnection-close (step #3) - pc.signalingState.Set(SignalingStateClosed) + if shouldGracefullyClose { + defer close(pc.isGracefulCloseDone) + } // Try closing everything and collect the errors // Shutdown strategy: @@ -2057,14 +2416,42 @@ func (pc *PeerConnection) Close() error { // continue the chain the Mux has to be closed. closeErrs := make([]error, 4) - closeErrs = append(closeErrs, pc.api.interceptor.Close()) + doGracefulCloseOps := func() []error { + if !shouldGracefullyClose { + return nil + } + + // these are all non-canon steps + var gracefulCloseErrors []error + if pc.iceTransport != nil { + gracefulCloseErrors = append(gracefulCloseErrors, pc.iceTransport.GracefulStop()) + } + + pc.ops.GracefulClose() + + pc.sctpTransport.lock.Lock() + for _, d := range pc.sctpTransport.dataChannels { + gracefulCloseErrors = append(gracefulCloseErrors, d.GracefulClose()) + } + pc.sctpTransport.lock.Unlock() + + return gracefulCloseErrors + } + + if isAlreadyClosingOrClosed { + return util.FlattenErrs(doGracefulCloseOps()) + } + + // https://www.w3.org/TR/webrtc/#dom-rtcpeerconnection-close (step #3) + pc.signalingState.Set(SignalingStateClosed) // https://www.w3.org/TR/webrtc/#dom-rtcpeerconnection-close (step #4) pc.mu.Lock() for _, t := range pc.rtpTransceivers { - if !t.stopped { - closeErrs = append(closeErrs, t.Stop()) - } + closeErrs = append(closeErrs, t.Stop()) //nolint:makezero // todo fix + } + if nonMediaBandwidthProbe, ok := pc.nonMediaBandwidthProbe.Load().(*RTPReceiver); ok { + closeErrs = append(closeErrs, nonMediaBandwidthProbe.Stop()) //nolint:makezero // todo fix } pc.mu.Unlock() @@ -2077,26 +2464,32 @@ func (pc *PeerConnection) Close() error { // https://www.w3.org/TR/webrtc/#dom-rtcpeerconnection-close (step #6) if pc.sctpTransport != nil { - closeErrs = append(closeErrs, pc.sctpTransport.Stop()) + closeErrs = append(closeErrs, pc.sctpTransport.Stop()) //nolint:makezero // todo fix } // https://www.w3.org/TR/webrtc/#dom-rtcpeerconnection-close (step #7) - closeErrs = append(closeErrs, pc.dtlsTransport.Stop()) + closeErrs = append(closeErrs, pc.dtlsTransport.Stop()) //nolint:makezero // todo fix // https://www.w3.org/TR/webrtc/#dom-rtcpeerconnection-close (step #8, #9, #10) - if pc.iceTransport != nil { - closeErrs = append(closeErrs, pc.iceTransport.Stop()) + if pc.iceTransport != nil && !shouldGracefullyClose { + // we will stop gracefully in doGracefulCloseOps + closeErrs = append(closeErrs, pc.iceTransport.Stop()) //nolint:makezero // todo fix } // https://www.w3.org/TR/webrtc/#dom-rtcpeerconnection-close (step #11) pc.updateConnectionState(pc.ICEConnectionState(), pc.dtlsTransport.State()) + closeErrs = append(closeErrs, doGracefulCloseOps()...) //nolint:makezero // todo fix + + // Interceptor closes at the end to prevent Bind from being called after interceptor is closed + closeErrs = append(closeErrs, pc.api.interceptor.Close()) //nolint:makezero // todo fix + return util.FlattenErrs(closeErrs) } // addRTPTransceiver appends t into rtpTransceivers // and fires onNegotiationNeeded; -// caller of this method should hold `pc.mu` lock +// caller of this method should hold `pc.mu` lock. func (pc *PeerConnection) addRTPTransceiver(t *RTPTransceiver) { pc.rtpTransceivers = append(pc.rtpTransceivers, t) pc.onNegotiationNeeded() @@ -2108,10 +2501,12 @@ func (pc *PeerConnection) addRTPTransceiver(t *RTPTransceiver) { // by the ICEAgent since the offer or answer was created. func (pc *PeerConnection) CurrentLocalDescription() *SessionDescription { pc.mu.Lock() + defer pc.mu.Unlock() + localDescription := pc.currentLocalDescription iceGather := pc.iceGatherer iceGatheringState := pc.ICEGatheringState() - pc.mu.Unlock() + return populateLocalCandidates(localDescription, iceGather, iceGatheringState) } @@ -2121,10 +2516,12 @@ func (pc *PeerConnection) CurrentLocalDescription() *SessionDescription { // PeerConnection is in the stable state, the value is null. func (pc *PeerConnection) PendingLocalDescription() *SessionDescription { pc.mu.Lock() + defer pc.mu.Unlock() + localDescription := pc.pendingLocalDescription iceGather := pc.iceGatherer iceGatheringState := pc.ICEGatheringState() - pc.mu.Unlock() + return populateLocalCandidates(localDescription, iceGather, iceGatheringState) } @@ -2180,10 +2577,11 @@ func (pc *PeerConnection) ConnectionState() PeerConnectionState { if state, ok := pc.connectionState.Load().(PeerConnectionState); ok { return state } + return PeerConnectionState(0) } -// GetStats return data providing statistics about the overall connection +// GetStats return data providing statistics about the overall connection. func (pc *PeerConnection) GetStats() StatsReport { var ( dataChannelsAccepted uint32 @@ -2244,8 +2642,12 @@ func (pc *PeerConnection) GetStats() StatsReport { return statsCollector.Ready() } -// Start all transports. PeerConnection now has enough state -func (pc *PeerConnection) startTransports(iceRole ICERole, dtlsRole DTLSRole, remoteUfrag, remotePwd, fingerprint, fingerprintHash string) { +// Start all transports. PeerConnection now has enough state. +func (pc *PeerConnection) startTransports( + iceRole ICERole, + dtlsRole DTLSRole, + remoteUfrag, remotePwd, fingerprint, fingerprintHash string, +) { // Start the ice transport err := pc.iceTransport.Start( pc.iceGatherer, @@ -2258,9 +2660,23 @@ func (pc *PeerConnection) startTransports(iceRole ICERole, dtlsRole DTLSRole, re ) if err != nil { pc.log.Warnf("Failed to start manager: %s", err) + return } + pc.dtlsTransport.internalOnCloseHandler = func() { + if pc.isClosed.get() || pc.api.settingEngine.disableCloseByDTLS { + return + } + + pc.log.Info("Closing PeerConnection from DTLS CloseNotify") + go func() { + if pcClosErr := pc.Close(); pcClosErr != nil { + pc.log.Warnf("Failed to close PeerConnection from DTLS CloseNotify: %s", pcClosErr) + } + }() + } + // Start the dtls transport err = pc.dtlsTransport.Start(DTLSParameters{ Role: dtlsRole, @@ -2269,29 +2685,40 @@ func (pc *PeerConnection) startTransports(iceRole ICERole, dtlsRole DTLSRole, re pc.updateConnectionState(pc.ICEConnectionState(), pc.dtlsTransport.State()) if err != nil { pc.log.Warnf("Failed to start manager: %s", err) + return } } // nolint: gocognit -func (pc *PeerConnection) startRTP(isRenegotiation bool, remoteDesc *SessionDescription, currentTransceivers []*RTPTransceiver) { +func (pc *PeerConnection) startRTP( + isRenegotiation bool, + remoteDesc *SessionDescription, + currentTransceivers []*RTPTransceiver, +) { if !isRenegotiation { pc.undeclaredMediaProcessor() } pc.startRTPReceivers(remoteDesc, currentTransceivers) - if haveApplicationMediaSection(remoteDesc.parsed) { - pc.startSCTP() + if d := haveDataChannel(remoteDesc); d != nil { + pc.startSCTP(getMaxMessageSize(d)) } } // generateUnmatchedSDP generates an SDP that doesn't take remote state into account -// This is used for the initial call for CreateOffer -func (pc *PeerConnection) generateUnmatchedSDP(transceivers []*RTPTransceiver, useIdentity bool) (*sdp.SessionDescription, error) { - d, err := sdp.NewJSEPSessionDescription(useIdentity) +// This is used for the initial call for CreateOffer. +// +//nolint:cyclop +func (pc *PeerConnection) generateUnmatchedSDP( + transceivers []*RTPTransceiver, + useIdentity bool, +) (*sdp.SessionDescription, error) { + desc, err := sdp.NewJSEPSessionDescription(useIdentity) if err != nil { return nil, err } + desc.Attributes = append(desc.Attributes, sdp.Attribute{Key: sdp.AttrKeyMsidSemantic, Value: "WMS*"}) iceParams, err := pc.iceGatherer.GetLocalParameters() if err != nil { @@ -2310,7 +2737,7 @@ func (pc *PeerConnection) generateUnmatchedSDP(transceivers []*RTPTransceiver, u pc.sctpTransport.lock.Lock() defer pc.sctpTransport.lock.Unlock() - if isPlanB { + if isPlanB { //nolint:nestif video := make([]*RTPTransceiver, 0) audio := make([]*RTPTransceiver, 0) @@ -2353,17 +2780,38 @@ func (pc *PeerConnection) generateUnmatchedSDP(transceivers []*RTPTransceiver, u return nil, err } - return populateSDP(d, isPlanB, dtlsFingerprints, pc.api.settingEngine.sdpMediaLevelFingerprints, pc.api.settingEngine.candidates.ICELite, true, pc.api.mediaEngine, connectionRoleFromDtlsRole(defaultDtlsRoleOffer), candidates, iceParams, mediaSections, pc.ICEGatheringState()) + return populateSDP( + desc, + isPlanB, + dtlsFingerprints, + pc.api.settingEngine.sdpMediaLevelFingerprints, + pc.api.settingEngine.candidates.ICELite, + true, + pc.api.mediaEngine, + connectionRoleFromDtlsRole(defaultDtlsRoleOffer), + candidates, + iceParams, + mediaSections, + pc.ICEGatheringState(), + nil, + pc.api.settingEngine.getSCTPMaxMessageSize(), + ) } // generateMatchedSDP generates a SDP and takes the remote state into account // this is used everytime we have a RemoteDescription -// nolint: gocyclo -func (pc *PeerConnection) generateMatchedSDP(transceivers []*RTPTransceiver, useIdentity bool, includeUnmatched bool, connectionRole sdp.ConnectionRole) (*sdp.SessionDescription, error) { //nolint:gocognit - d, err := sdp.NewJSEPSessionDescription(useIdentity) +// +//nolint:gocognit,gocyclo,cyclop +func (pc *PeerConnection) generateMatchedSDP( + transceivers []*RTPTransceiver, + useIdentity, includeUnmatched bool, + connectionRole sdp.ConnectionRole, +) (*sdp.SessionDescription, error) { + desc, err := sdp.NewJSEPSessionDescription(useIdentity) if err != nil { return nil, err } + desc.Attributes = append(desc.Attributes, sdp.Attribute{Key: sdp.AttrKeyMsidSemantic, Value: "WMS*"}) iceParams, err := pc.iceGatherer.GetLocalParameters() if err != nil { @@ -2375,7 +2823,7 @@ func (pc *PeerConnection) generateMatchedSDP(transceivers []*RTPTransceiver, use return nil, err } - var t *RTPTransceiver + var transceiver *RTPTransceiver remoteDescription := pc.currentRemoteDescription if pc.pendingRemoteDescription != nil { remoteDescription = pc.pendingRemoteDescription @@ -2399,12 +2847,13 @@ func (pc *PeerConnection) generateMatchedSDP(transceivers []*RTPTransceiver, use if media.MediaName.Media == mediaSectionApplication { mediaSections = append(mediaSections, mediaSection{id: midValue, data: true}) alreadyHaveApplicationMediaSection = true + continue } kind := NewRTPCodecType(media.MediaName.Media) direction := getPeerDirection(media) - if kind == 0 || direction == RTPTransceiverDirection(Unknown) { + if kind == 0 || direction == RTPTransceiverDirectionUnknown { continue } @@ -2413,46 +2862,63 @@ func (pc *PeerConnection) generateMatchedSDP(transceivers []*RTPTransceiver, use switch { case sdpSemantics == SDPSemanticsPlanB || sdpSemantics == SDPSemanticsUnifiedPlanWithFallback && detectedPlanB: if !detectedPlanB { - return nil, &rtcerr.TypeError{Err: fmt.Errorf("%w: Expected PlanB, but RemoteDescription is UnifiedPlan", ErrIncorrectSDPSemantics)} + return nil, &rtcerr.TypeError{ + Err: fmt.Errorf("%w: Expected PlanB, but RemoteDescription is UnifiedPlan", ErrIncorrectSDPSemantics), + } } // If we're responding to a plan-b offer, then we should try to fill up this // media entry with all matching local transceivers mediaTransceivers := []*RTPTransceiver{} for { // keep going until we can't get any more - t, localTransceivers = satisfyTypeAndDirection(kind, direction, localTransceivers) - if t == nil { + transceiver, localTransceivers = satisfyTypeAndDirection(kind, direction, localTransceivers) + if transceiver == nil { if len(mediaTransceivers) == 0 { - t = &RTPTransceiver{kind: kind, api: pc.api, codecs: pc.api.mediaEngine.getCodecsByKind(kind)} - t.setDirection(RTPTransceiverDirectionInactive) - mediaTransceivers = append(mediaTransceivers, t) + transceiver = &RTPTransceiver{kind: kind, api: pc.api, codecs: pc.api.mediaEngine.getCodecsByKind(kind)} + transceiver.setDirection(RTPTransceiverDirectionInactive) + mediaTransceivers = append(mediaTransceivers, transceiver) } + break } - if sender := t.Sender(); sender != nil { + if sender := transceiver.Sender(); sender != nil { sender.setNegotiated() } - mediaTransceivers = append(mediaTransceivers, t) + mediaTransceivers = append(mediaTransceivers, transceiver) } mediaSections = append(mediaSections, mediaSection{id: midValue, transceivers: mediaTransceivers}) case sdpSemantics == SDPSemanticsUnifiedPlan || sdpSemantics == SDPSemanticsUnifiedPlanWithFallback: if detectedPlanB { - return nil, &rtcerr.TypeError{Err: fmt.Errorf("%w: Expected UnifiedPlan, but RemoteDescription is PlanB", ErrIncorrectSDPSemantics)} + return nil, &rtcerr.TypeError{ + Err: fmt.Errorf( + "%w: Expected UnifiedPlan, but RemoteDescription is PlanB", + ErrIncorrectSDPSemantics, + ), + } } - t, localTransceivers = findByMid(midValue, localTransceivers) - if t == nil { + transceiver, localTransceivers = findByMid(midValue, localTransceivers) + if transceiver == nil { return nil, fmt.Errorf("%w: %q", errPeerConnTranscieverMidNil, midValue) } - if sender := t.Sender(); sender != nil { + if sender := transceiver.Sender(); sender != nil { sender.setNegotiated() } - mediaTransceivers := []*RTPTransceiver{t} - mediaSections = append(mediaSections, mediaSection{id: midValue, transceivers: mediaTransceivers, ridMap: getRids(media)}) + mediaTransceivers := []*RTPTransceiver{transceiver} + + extensions, _ := rtpExtensionsFromMediaDescription(media) + mediaSections = append( + mediaSections, + mediaSection{id: midValue, transceivers: mediaTransceivers, matchExtensions: extensions, rids: getRids(media)}, + ) } } + pc.sctpTransport.lock.Lock() + defer pc.sctpTransport.lock.Unlock() + + var bundleGroup *string // If we are offering also include unmatched local transceivers - if includeUnmatched { + if includeUnmatched { //nolint:nestif if !detectedPlanB { for _, t := range localTransceivers { if sender := t.Sender(); sender != nil { @@ -2469,6 +2935,10 @@ func (pc *PeerConnection) generateMatchedSDP(transceivers []*RTPTransceiver, use mediaSections = append(mediaSections, mediaSection{id: strconv.Itoa(len(mediaSections)), data: true}) } } + } else if remoteDescription != nil { + groupValue, _ := remoteDescription.parsed.Attribute(sdp.AttrKeyGroup) + groupValue = strings.TrimLeft(groupValue, "BUNDLE") + bundleGroup = &groupValue } if pc.configuration.SDPSemantics == SDPSemanticsUnifiedPlanWithFallback && detectedPlanB { @@ -2480,7 +2950,22 @@ func (pc *PeerConnection) generateMatchedSDP(transceivers []*RTPTransceiver, use return nil, err } - return populateSDP(d, detectedPlanB, dtlsFingerprints, pc.api.settingEngine.sdpMediaLevelFingerprints, pc.api.settingEngine.candidates.ICELite, isExtmapAllowMixed, pc.api.mediaEngine, connectionRole, candidates, iceParams, mediaSections, pc.ICEGatheringState()) + return populateSDP( + desc, + detectedPlanB, + dtlsFingerprints, + pc.api.settingEngine.sdpMediaLevelFingerprints, + pc.api.settingEngine.candidates.ICELite, + isExtmapAllowMixed, + pc.api.mediaEngine, + connectionRole, + candidates, + iceParams, + mediaSections, + pc.ICEGatheringState(), + bundleGroup, + pc.api.settingEngine.getSCTPMaxMessageSize(), + ) } func (pc *PeerConnection) setGatherCompleteHandler(handler func()) { diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/peerconnection_js.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/peerconnection_js.go similarity index 99% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/peerconnection_js.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/peerconnection_js.go index 8322e1be9..c7e968ca2 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/peerconnection_js.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/peerconnection_js.go @@ -10,8 +10,8 @@ package webrtc import ( "syscall/js" - "github.com/pion/ice/v2" - "github.com/pion/webrtc/v3/pkg/rtcerr" + "github.com/pion/ice/v4" + "github.com/pion/webrtc/v4/pkg/rtcerr" ) // PeerConnection represents a WebRTC connection that establishes a @@ -182,14 +182,14 @@ func (pc *PeerConnection) checkConfiguration(configuration Configuration) error // } // https://www.w3.org/TR/webrtc/#set-the-configuration (step #5) - if configuration.BundlePolicy != BundlePolicy(Unknown) { + if configuration.BundlePolicy != BundlePolicyUnknown { if configuration.BundlePolicy != existingConfig.BundlePolicy { return &rtcerr.InvalidModificationError{Err: ErrModifyingBundlePolicy} } } // https://www.w3.org/TR/webrtc/#set-the-configuration (step #6) - if configuration.RTCPMuxPolicy != RTCPMuxPolicy(Unknown) { + if configuration.RTCPMuxPolicy != RTCPMuxPolicyUnknown { if configuration.RTCPMuxPolicy != existingConfig.RTCPMuxPolicy { return &rtcerr.InvalidModificationError{Err: ErrModifyingRTCPMuxPolicy} } @@ -667,7 +667,7 @@ func valueToICECandidate(val js.Value) *ICECandidate { return nil } - iceCandidate, err := newICECandidateFromICE(c) + iceCandidate, err := newICECandidateFromICE(c, "", 0) if err != nil { return nil } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/peerconnectionstate.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/peerconnectionstate.go similarity index 88% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/peerconnectionstate.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/peerconnectionstate.go index 1f1456882..677cfa95c 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/peerconnectionstate.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/peerconnectionstate.go @@ -7,11 +7,14 @@ package webrtc type PeerConnectionState int const ( + // PeerConnectionStateUnknown is the enum's zero-value. + PeerConnectionStateUnknown PeerConnectionState = iota + // PeerConnectionStateNew indicates that any of the ICETransports or // DTLSTransports are in the "new" state and none of the transports are // in the "connecting", "checking", "failed" or "disconnected" state, or // all transports are in the "closed" state, or there are no transports. - PeerConnectionStateNew PeerConnectionState = iota + 1 + PeerConnectionStateNew // PeerConnectionStateConnecting indicates that any of the // ICETransports or DTLSTransports are in the "connecting" or @@ -62,7 +65,7 @@ func newPeerConnectionState(raw string) PeerConnectionState { case peerConnectionStateClosedStr: return PeerConnectionStateClosed default: - return PeerConnectionState(Unknown) + return PeerConnectionStateUnknown } } @@ -84,14 +87,3 @@ func (t PeerConnectionState) String() string { return ErrUnknownType.Error() } } - -type negotiationNeededState int - -const ( - // NegotiationNeededStateEmpty not running and queue is empty - negotiationNeededStateEmpty = iota - // NegotiationNeededStateEmpty running and queue is empty - negotiationNeededStateRun - // NegotiationNeededStateEmpty running and queue - negotiationNeededStateQueue -) diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/pkg/media/h264reader/h264reader.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/pkg/media/h264reader/h264reader.go similarity index 97% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/pkg/media/h264reader/h264reader.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/pkg/media/h264reader/h264reader.go index c99759104..21400237b 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/pkg/media/h264reader/h264reader.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/pkg/media/h264reader/h264reader.go @@ -10,7 +10,7 @@ import ( "io" ) -// H264Reader reads data from stream and constructs h264 nal units +// H264Reader reads data from stream and constructs h264 nal units. type H264Reader struct { stream io.Reader nalBuffer []byte @@ -25,7 +25,7 @@ var ( errDataIsNotH264Stream = errors.New("data is not a H264 bitstream") ) -// NewReader creates new H264Reader +// NewReader creates new H264Reader. func NewReader(in io.Reader) (*H264Reader, error) { if in == nil { return nil, errNilReader @@ -42,7 +42,7 @@ func NewReader(in io.Reader) (*H264Reader, error) { return reader, nil } -// NAL H.264 Network Abstraction Layer +// NAL H.264 Network Abstraction Layer. type NAL struct { PictureOrderCount uint32 @@ -73,6 +73,7 @@ func (reader *H264Reader) read(numToRead int) (data []byte, e error) { } data = reader.readBuffer[0:numShouldRead] reader.readBuffer = reader.readBuffer[numShouldRead:] + return data, nil } @@ -82,7 +83,7 @@ func (reader *H264Reader) bitStreamStartsWithH264Prefix() (prefixLength int, e e prefixBuffer, e := reader.read(4) if e != nil { - return + return prefixLength, e } n := len(prefixBuffer) @@ -100,12 +101,14 @@ func (reader *H264Reader) bitStreamStartsWithH264Prefix() (prefixLength int, e e if nalPrefix3BytesFound { return 0, io.EOF } + return 0, errDataIsNotH264Stream } // n == 4 if nalPrefix3BytesFound { reader.nalBuffer = append(reader.nalBuffer, prefixBuffer[3]) + return 3, nil } @@ -113,6 +116,7 @@ func (reader *H264Reader) bitStreamStartsWithH264Prefix() (prefixLength int, e e if nalPrefix4BytesFound { return 4, nil } + return 0, errDataIsNotH264Stream } @@ -147,8 +151,10 @@ func (reader *H264Reader) NextNAL() (*NAL, error) { nal.parseHeader() if nal.UnitType == NalUnitTypeSEI { reader.nalBuffer = nil + continue } + break } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/pkg/media/h264reader/nalunittype.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/pkg/media/h264reader/nalunittype.go similarity index 95% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/pkg/media/h264reader/nalunittype.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/pkg/media/h264reader/nalunittype.go index 7d87342bb..ff94236fe 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/pkg/media/h264reader/nalunittype.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/pkg/media/h264reader/nalunittype.go @@ -5,10 +5,10 @@ package h264reader import "strconv" -// NalUnitType is the type of a NAL +// NalUnitType is the type of a NAL. type NalUnitType uint8 -// Enums for NalUnitTypes +// Enums for NalUnitTypes. const ( NalUnitTypeUnspecified NalUnitType = 0 // Unspecified NalUnitTypeCodedSliceNonIdr NalUnitType = 1 // Coded slice of a non-IDR picture @@ -25,12 +25,12 @@ const ( NalUnitTypeFiller NalUnitType = 12 // Filler data NalUnitTypeSpsExt NalUnitType = 13 // Sequence parameter set extension NalUnitTypeCodedSliceAux NalUnitType = 19 // Coded slice of an auxiliary coded picture without partitioning - // 14..18 // Reserved - // 20..23 // Reserved - // 24..31 // Unspecified + // 14..18 // Reserved. + // 20..23 // Reserved. + // 24..31 // Unspecified. ) -func (n *NalUnitType) String() string { +func (n *NalUnitType) String() string { //nolint:cyclop var str string switch *n { case NalUnitTypeUnspecified: @@ -67,5 +67,6 @@ func (n *NalUnitType) String() string { str = "Unknown" } str = str + "(" + strconv.FormatInt(int64(*n), 10) + ")" + return str } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/pkg/media/h264writer/h264writer.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/pkg/media/h264writer/h264writer.go similarity index 94% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/pkg/media/h264writer/h264writer.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/pkg/media/h264writer/h264writer.go index cc8f64bac..6dbb2baae 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/pkg/media/h264writer/h264writer.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/pkg/media/h264writer/h264writer.go @@ -27,7 +27,7 @@ type ( } ) -// New builds a new H264 writer +// New builds a new H264 writer. func New(filename string) (*H264Writer, error) { f, err := os.Create(filename) //nolint:gosec if err != nil { @@ -37,14 +37,14 @@ func New(filename string) (*H264Writer, error) { return NewWith(f), nil } -// NewWith initializes a new H264 writer with an io.Writer output +// NewWith initializes a new H264 writer with an io.Writer output. func NewWith(w io.Writer) *H264Writer { return &H264Writer{ writer: w, } } -// WriteRTP adds a new packet and writes the appropriate headers for it +// WriteRTP adds a new packet and writes the appropriate headers for it. func (h *H264Writer) WriteRTP(packet *rtp.Packet) error { if len(packet.Payload) == 0 { return nil @@ -62,7 +62,7 @@ func (h *H264Writer) WriteRTP(packet *rtp.Packet) error { } data, err := h.cachedPacket.Unmarshal(packet.Payload) - if err != nil { + if err != nil || len(data) == 0 { return err } @@ -71,7 +71,7 @@ func (h *H264Writer) WriteRTP(packet *rtp.Packet) error { return err } -// Close closes the underlying writer +// Close closes the underlying writer. func (h *H264Writer) Close() error { h.cachedPacket = nil if h.writer != nil { diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/pkg/media/ivfwriter/ivfwriter.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/pkg/media/ivfwriter/ivfwriter.go new file mode 100644 index 000000000..00903e99e --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/pkg/media/ivfwriter/ivfwriter.go @@ -0,0 +1,341 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + +// Package ivfwriter implements IVF media container writer +package ivfwriter + +import ( + "encoding/binary" + "errors" + "io" + "os" + + "github.com/pion/rtp" + "github.com/pion/rtp/codecs" + "github.com/pion/rtp/codecs/av1/obu" +) + +var ( + errFileNotOpened = errors.New("file not opened") + errInvalidNilPacket = errors.New("invalid nil packet") + errCodecUnset = errors.New("codec is unset") + errCodecAlreadySet = errors.New("codec is already set") + errNoSuchCodec = errors.New("no codec for this MimeType") + errInvalidMediaTimebase = errors.New("invalid media timebase") +) + +type ( + codec int + + // IVFWriter is used to take RTP packets and write them to an IVF on disk. + IVFWriter struct { + ioWriter io.Writer + count uint64 + seenKeyFrame bool + + codec codec + + timebaseDenominator uint32 + timebaseNumerator uint32 + firstFrameTimestamp uint32 + clockRate uint64 + + // VP8, VP9 + currentFrame []byte + + // AV1 + av1Depacketizer *codecs.AV1Depacketizer + } +) + +const ( + codecUnset codec = iota + codecVP8 + codecVP9 + codecAV1 + + mimeTypeVP8 = "video/VP8" + mimeTypeVP9 = "video/VP9" + mimeTypeAV1 = "video/AV1" +) + +// New builds a new IVF writer. +func New(fileName string, opts ...Option) (*IVFWriter, error) { + file, err := os.Create(fileName) //nolint:gosec + if err != nil { + return nil, err + } + writer, err := NewWith(file, opts...) + if err != nil { + return nil, err + } + writer.ioWriter = file + + return writer, nil +} + +// NewWith initialize a new IVF writer with an io.Writer output. +func NewWith(out io.Writer, opts ...Option) (*IVFWriter, error) { + if out == nil { + return nil, errFileNotOpened + } + + writer := &IVFWriter{ + ioWriter: out, + seenKeyFrame: false, + timebaseDenominator: 30, + timebaseNumerator: 1, + clockRate: 90000, + } + + for _, o := range opts { + if err := o(writer); err != nil { + return nil, err + } + } + + if writer.codec == codecUnset { + writer.codec = codecVP8 + } + if err := writer.writeHeader(); err != nil { + return nil, err + } + + if writer.timebaseDenominator == 0 { + return nil, errInvalidMediaTimebase + } + + return writer, nil +} + +func (i *IVFWriter) writeHeader() error { + header := make([]byte, 32) + copy(header[0:], "DKIF") // DKIF + binary.LittleEndian.PutUint16(header[4:], 0) // Version + binary.LittleEndian.PutUint16(header[6:], 32) // Header size + + // FOURCC + switch i.codec { + case codecVP8: + copy(header[8:], "VP80") + case codecVP9: + copy(header[8:], "VP90") + case codecAV1: + copy(header[8:], "AV01") + default: + return errCodecUnset + } + + binary.LittleEndian.PutUint16(header[12:], 640) // Width in pixels + binary.LittleEndian.PutUint16(header[14:], 480) // Height in pixels + binary.LittleEndian.PutUint32(header[16:], i.timebaseDenominator) // Framerate denominator + binary.LittleEndian.PutUint32(header[20:], i.timebaseNumerator) // Framerate numerator + binary.LittleEndian.PutUint32(header[24:], 900) // Frame count, will be updated on first Close() call + binary.LittleEndian.PutUint32(header[28:], 0) // Unused + + _, err := i.ioWriter.Write(header) + + return err +} + +func (i *IVFWriter) timestampToPts(timestamp uint64) uint64 { + return timestamp * uint64(i.timebaseNumerator) / uint64(i.timebaseDenominator) +} + +func (i *IVFWriter) writeFrame(frame []byte, timestamp uint64) error { + frameHeader := make([]byte, 12) + //nolint:gosec // G115 + binary.LittleEndian.PutUint32(frameHeader[0:], uint32(len(frame))) // Frame length + binary.LittleEndian.PutUint64(frameHeader[4:], i.timestampToPts(timestamp)) // PTS + i.count++ + + if _, err := i.ioWriter.Write(frameHeader); err != nil { + return err + } + _, err := i.ioWriter.Write(frame) + + return err +} + +// WriteRTP adds a new packet and writes the appropriate headers for it. +func (i *IVFWriter) WriteRTP(packet *rtp.Packet) error { + if i.ioWriter == nil { + return errFileNotOpened + } else if len(packet.Payload) == 0 { + return nil + } + + if i.count == 0 { + i.firstFrameTimestamp = packet.Timestamp + } + relativeTstampMs := 1000 * uint64(packet.Timestamp-i.firstFrameTimestamp) / i.clockRate + + switch i.codec { + case codecVP8: + return i.writeVP8(packet, relativeTstampMs) + case codecVP9: + return i.writeVP9(packet, relativeTstampMs) + case codecAV1: + return i.writeAV1(packet, relativeTstampMs) + default: + return errCodecUnset + } +} + +func (i *IVFWriter) writeVP8(packet *rtp.Packet, timestamp uint64) error { + vp8Packet := codecs.VP8Packet{} + if _, err := vp8Packet.Unmarshal(packet.Payload); err != nil { + return err + } + + isKeyFrame := (vp8Packet.Payload[0] & 0x01) == 0 + switch { + case !i.seenKeyFrame && !isKeyFrame: + return nil + case i.currentFrame == nil && vp8Packet.S != 1: + return nil + } + + i.seenKeyFrame = true + i.currentFrame = append(i.currentFrame, vp8Packet.Payload[0:]...) + + if !packet.Marker { + return nil + } else if len(i.currentFrame) == 0 { + return nil + } + + if err := i.writeFrame(i.currentFrame, timestamp); err != nil { + return err + } + i.currentFrame = nil + + return nil +} + +func (i *IVFWriter) writeVP9(packet *rtp.Packet, timestamp uint64) error { + vp9Packet := codecs.VP9Packet{} + if _, err := vp9Packet.Unmarshal(packet.Payload); err != nil { + return err + } + + switch { + case !i.seenKeyFrame && vp9Packet.P: + return nil + case i.currentFrame == nil && !vp9Packet.B: + return nil + } + + i.seenKeyFrame = true + i.currentFrame = append(i.currentFrame, vp9Packet.Payload[0:]...) + + if !packet.Marker { + return nil + } else if len(i.currentFrame) == 0 { + return nil + } + + // the timestamp must be sequential. webrtc mandates a clock rate of 90000 + // and we've assumed 30fps in the header. + if err := i.writeFrame(i.currentFrame, timestamp); err != nil { + return err + } + i.currentFrame = nil + + return nil +} + +func (i *IVFWriter) writeAV1(packet *rtp.Packet, timestamp uint64) error { + if i.av1Depacketizer == nil { + i.av1Depacketizer = &codecs.AV1Depacketizer{} + } + + payload, err := i.av1Depacketizer.Unmarshal(packet.Payload) + if err != nil { + return err + } + + if !i.seenKeyFrame { + isKeyFrame := i.av1Depacketizer.N || (len(payload) > 0 && obu.Type((payload[0]&0x78)>>3) == obu.OBUSequenceHeader) + if !isKeyFrame { + return nil + } + + i.seenKeyFrame = true + } + + i.currentFrame = append(i.currentFrame, payload...) + if !packet.Marker { + return nil + } + + delimiter := obu.Header{ + Type: obu.OBUTemporalDelimiter, + HasSizeField: true, + } + frame := append(delimiter.Marshal(), 0) + frame = append(frame, i.currentFrame...) + + if err := i.writeFrame(frame, timestamp); err != nil { + return err + } + i.currentFrame = nil + + return nil +} + +// Close stops the recording. +func (i *IVFWriter) Close() error { + if i.ioWriter == nil { + // Returns no error as it may be convenient to call + // Close() multiple times + return nil + } + + defer func() { + i.ioWriter = nil + }() + + if ws, ok := i.ioWriter.(io.WriteSeeker); ok { + // Update the framecount + if _, err := ws.Seek(24, 0); err != nil { + return err + } + buff := make([]byte, 4) + binary.LittleEndian.PutUint32(buff, uint32(i.count)) //nolint:gosec // G115 + if _, err := ws.Write(buff); err != nil { + return err + } + } + + if closer, ok := i.ioWriter.(io.Closer); ok { + return closer.Close() + } + + return nil +} + +// An Option configures a SampleBuilder. +type Option func(i *IVFWriter) error + +// WithCodec configures if IVFWriter is writing AV1 or VP8 packets to disk. +func WithCodec(mimeType string) Option { + return func(i *IVFWriter) error { + if i.codec != codecUnset { + return errCodecAlreadySet + } + + switch mimeType { + case mimeTypeVP8: + i.codec = codecVP8 + case mimeTypeVP9: + i.codec = codecVP9 + case mimeTypeAV1: + i.codec = codecAV1 + default: + return errNoSuchCodec + } + + return nil + } +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/pkg/media/media.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/pkg/media/media.go similarity index 68% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/pkg/media/media.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/pkg/media/media.go index 2ed5573f8..f8ee5e382 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/pkg/media/media.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/pkg/media/media.go @@ -10,17 +10,22 @@ import ( "github.com/pion/rtp" ) -// A Sample contains encoded media and timing information +// A Sample contains encoded media and timing information. type Sample struct { Data []byte Timestamp time.Time Duration time.Duration PacketTimestamp uint32 PrevDroppedPackets uint16 + Metadata interface{} + + // RTP headers of RTP packets forming this Sample. (Optional) + // Useful for accessing RTP extensions associated to the Sample. + RTPHeaders []*rtp.Header } // Writer defines an interface to handle -// the creation of media files +// the creation of media files. type Writer interface { // Add the content of an RTP packet to the media WriteRTP(packet *rtp.Packet) error diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/pkg/media/oggreader/oggreader.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/pkg/media/oggreader/oggreader.go similarity index 84% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/pkg/media/oggreader/oggreader.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/pkg/media/oggreader/oggreader.go index 50d1a7cd8..905a3da6c 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/pkg/media/oggreader/oggreader.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/pkg/media/oggreader/oggreader.go @@ -30,7 +30,7 @@ var ( errChecksumMismatch = errors.New("expected and actual checksum do not match") ) -// OggReader is used to read Ogg files and return page payloads +// OggReader is used to read Ogg files and return page payloads. type OggReader struct { stream io.Reader bytesReadSuccesfully int64 @@ -67,7 +67,7 @@ type OggPageHeader struct { } // NewWith returns a new Ogg reader and Ogg header -// with an io.Reader input +// with an io.Reader input. func NewWith(in io.Reader) (*OggReader, *OggHeader, error) { return newWith(in /* doChecksum */, true) } @@ -126,26 +126,26 @@ func (o *OggReader) readHeaders() (*OggHeader, error) { // ParseNextPage reads from stream and returns Ogg page payload, header, // and an error if there is incomplete page data. -func (o *OggReader) ParseNextPage() ([]byte, *OggPageHeader, error) { - h := make([]byte, pageHeaderLen) +func (o *OggReader) ParseNextPage() ([]byte, *OggPageHeader, error) { //nolint:cyclop + header := make([]byte, pageHeaderLen) - n, err := io.ReadFull(o.stream, h) + n, err := io.ReadFull(o.stream, header) if err != nil { return nil, nil, err - } else if n < len(h) { + } else if n < len(header) { return nil, nil, errShortPageHeader } pageHeader := &OggPageHeader{ - sig: [4]byte{h[0], h[1], h[2], h[3]}, + sig: [4]byte{header[0], header[1], header[2], header[3]}, } - pageHeader.version = h[4] - pageHeader.headerType = h[5] - pageHeader.GranulePosition = binary.LittleEndian.Uint64(h[6 : 6+8]) - pageHeader.serial = binary.LittleEndian.Uint32(h[14 : 14+4]) - pageHeader.index = binary.LittleEndian.Uint32(h[18 : 18+4]) - pageHeader.segmentsCount = h[26] + pageHeader.version = header[4] + pageHeader.headerType = header[5] + pageHeader.GranulePosition = binary.LittleEndian.Uint64(header[6 : 6+8]) + pageHeader.serial = binary.LittleEndian.Uint32(header[14 : 14+4]) + pageHeader.index = binary.LittleEndian.Uint32(header[18 : 18+4]) + pageHeader.segmentsCount = header[26] sizeBuffer := make([]byte, pageHeader.segmentsCount) if _, err = io.ReadFull(o.stream, sizeBuffer); err != nil { @@ -168,14 +168,15 @@ func (o *OggReader) ParseNextPage() ([]byte, *OggPageHeader, error) { checksum = (checksum << 8) ^ o.checksumTable[byte(checksum>>24)^v] } - for index := range h { + for index := range header { // Don't include expected checksum in our generation if index > 21 && index < 26 { updateChecksum(0) + continue } - updateChecksum(h[index]) + updateChecksum(header[index]) } for _, s := range sizeBuffer { updateChecksum(s) @@ -184,11 +185,13 @@ func (o *OggReader) ParseNextPage() ([]byte, *OggPageHeader, error) { updateChecksum(payload[index]) } - if binary.LittleEndian.Uint32(h[22:22+4]) != checksum { + if binary.LittleEndian.Uint32(header[22:22+4]) != checksum { return nil, nil, errChecksumMismatch } } + o.bytesReadSuccesfully += int64(len(header) + len(sizeBuffer) + len(payload)) + return payload, pageHeader, nil } @@ -204,7 +207,7 @@ func generateChecksumTable() *[256]uint32 { const poly = 0x04c11db7 for i := range table { - r := uint32(i) << 24 + r := uint32(i) << 24 //nolint:gosec // G115 for j := 0; j < 8; j++ { if (r & 0x80000000) != 0 { r = (r << 1) ^ poly @@ -214,5 +217,6 @@ func generateChecksumTable() *[256]uint32 { table[i] = (r & 0xffffffff) } } + return &table } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/pkg/media/oggwriter/oggwriter.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/pkg/media/oggwriter/oggwriter.go similarity index 83% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/pkg/media/oggwriter/oggwriter.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/pkg/media/oggwriter/oggwriter.go index 16952f157..8015f71f1 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/pkg/media/oggwriter/oggwriter.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/pkg/media/oggwriter/oggwriter.go @@ -10,9 +10,9 @@ import ( "io" "os" - "github.com/pion/randutil" "github.com/pion/rtp" "github.com/pion/rtp/codecs" + "github.com/pion/webrtc/v4/internal/util" ) const ( @@ -30,7 +30,7 @@ var ( errInvalidNilPacket = errors.New("invalid nil packet") ) -// OggWriter is used to take RTP packets and write them to an OGG on disk +// OggWriter is used to take RTP packets and write them to an OGG on disk. type OggWriter struct { stream io.Writer fd *os.File @@ -44,21 +44,22 @@ type OggWriter struct { lastPayloadSize int } -// New builds a new OGG Opus writer +// New builds a new OGG Opus writer. func New(fileName string, sampleRate uint32, channelCount uint16) (*OggWriter, error) { - f, err := os.Create(fileName) //nolint:gosec + file, err := os.Create(fileName) //nolint:gosec if err != nil { return nil, err } - writer, err := NewWith(f, sampleRate, channelCount) + writer, err := NewWith(file, sampleRate, channelCount) if err != nil { - return nil, f.Close() + return nil, file.Close() } - writer.fd = f + writer.fd = file + return writer, nil } -// NewWith initialize a new OGG Opus writer with an io.Writer output +// NewWith initialize a new OGG Opus writer with an io.Writer output. func NewWith(out io.Writer, sampleRate uint32, channelCount uint16) (*OggWriter, error) { if out == nil { return nil, errFileNotOpened @@ -68,7 +69,7 @@ func NewWith(out io.Writer, sampleRate uint32, channelCount uint16) (*OggWriter, stream: out, sampleRate: sampleRate, channelCount: channelCount, - serial: randutil.NewMathRandomGenerator().Uint32(), + serial: util.RandUint32(), checksumTable: generateChecksumTable(), // Timestamp and Granule MUST start from 1 @@ -110,8 +111,9 @@ func (i *OggWriter) writeHeaders() error { // ID Header oggIDHeader := make([]byte, 19) - copy(oggIDHeader[0:], idPageSignature) // Magic Signature 'OpusHead' - oggIDHeader[8] = 1 // Version + copy(oggIDHeader[0:], idPageSignature) // Magic Signature 'OpusHead' + oggIDHeader[8] = 1 // Version + //nolint:gosec // G115 oggIDHeader[9] = uint8(i.channelCount) // Channel count binary.LittleEndian.PutUint16(oggIDHeader[10:], defaultPreSkip) // pre-skip binary.LittleEndian.PutUint32(oggIDHeader[12:], i.sampleRate) // original sample rate, any valid sample e.g 48000 @@ -149,7 +151,9 @@ const ( func (i *OggWriter) createPage(payload []uint8, headerType uint8, granulePos uint64, pageIndex uint32) []byte { i.lastPayloadSize = len(payload) - page := make([]byte, pageHeaderSize+1+i.lastPayloadSize) + nSegments := (len(payload) / 255) + 1 // A segment can be at most 255 bytes long. + + page := make([]byte, pageHeaderSize+i.lastPayloadSize+nSegments) copy(page[0:], pageHeaderSignature) // page headers starts with 'OggS' page[4] = 0 // Version @@ -157,20 +161,31 @@ func (i *OggWriter) createPage(payload []uint8, headerType uint8, granulePos uin binary.LittleEndian.PutUint64(page[6:], granulePos) // granule position binary.LittleEndian.PutUint32(page[14:], i.serial) // Bitstream serial number binary.LittleEndian.PutUint32(page[18:], pageIndex) // Page sequence number - page[26] = 1 // Number of segments in page, giving always 1 segment - page[27] = uint8(i.lastPayloadSize) // Segment Table inserting at 27th position since page header length is 27 - copy(page[28:], payload) // inserting at 28th since Segment Table(1) + header length(27) + //nolint:gosec // G115 + page[26] = uint8(nSegments) // Number of segments in page. + + // Filling segment table with the lacing values. + // First (nSegments - 1) values will always be 255. + for i := 0; i < nSegments-1; i++ { + page[pageHeaderSize+i] = 255 + } + // The last value will be the remainder. + page[pageHeaderSize+nSegments-1] = uint8(len(payload) % 255) //nolint:gosec // G115 + + copy(page[pageHeaderSize+nSegments:], payload) // Payload goes after the segment table, so at pageHeaderSize+nSegments. var checksum uint32 for index := range page { checksum = (checksum << 8) ^ i.checksumTable[byte(checksum>>24)^page[index]] } - binary.LittleEndian.PutUint32(page[22:], checksum) // Checksum - generating for page data and inserting at 22th position into 32 bits + + // Checksum - generating for page data and inserting at 22th position into 32 bits + binary.LittleEndian.PutUint32(page[22:], checksum) return page } -// WriteRTP adds a new packet and writes the appropriate headers for it +// WriteRTP adds a new packet and writes the appropriate headers for it. func (i *OggWriter) WriteRTP(packet *rtp.Packet) error { if packet == nil { return errInvalidNilPacket @@ -196,10 +211,11 @@ func (i *OggWriter) WriteRTP(packet *rtp.Packet) error { data := i.createPage(payload, pageHeaderTypeContinuationOfStream, i.previousGranulePosition, i.pageIndex) i.pageIndex++ + return i.writeToStream(data) } -// Close stops the recording +// Close stops the recording. func (i *OggWriter) Close() error { defer func() { i.fd = nil @@ -213,6 +229,7 @@ func (i *OggWriter) Close() error { if closer, ok := i.stream.(io.Closer); ok { return closer.Close() } + return nil } @@ -238,13 +255,14 @@ func (i *OggWriter) Close() error { } // Wraps writing to the stream and maintains state -// so we can set values for EOS +// so we can set values for EOS. func (i *OggWriter) writeToStream(p []byte) error { if i.stream == nil { return errFileNotOpened } _, err := i.stream.Write(p) + return err } @@ -253,15 +271,16 @@ func generateChecksumTable() *[256]uint32 { const poly = 0x04c11db7 for i := range table { - r := uint32(i) << 24 + remainder := uint32(i) << 24 //nolint:gosec // G115 for j := 0; j < 8; j++ { - if (r & 0x80000000) != 0 { - r = (r << 1) ^ poly + if (remainder & 0x80000000) != 0 { + remainder = (remainder << 1) ^ poly } else { - r <<= 1 + remainder <<= 1 } - table[i] = (r & 0xffffffff) + table[i] = (remainder & 0xffffffff) } } + return &table } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/pkg/rtcerr/errors.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/pkg/rtcerr/errors.go similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/pkg/rtcerr/errors.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/pkg/rtcerr/errors.go diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/renovate.json b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/renovate.json new file mode 100644 index 000000000..f1bb98c6a --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/renovate.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "extends": [ + "github>pion/renovate-config" + ] +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/rtcpfeedback.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/rtcpfeedback.go similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/rtcpfeedback.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/rtcpfeedback.go diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/rtcpmuxpolicy.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/rtcpmuxpolicy.go similarity index 89% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/rtcpmuxpolicy.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/rtcpmuxpolicy.go index bd68ab562..d4f7f476d 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/rtcpmuxpolicy.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/rtcpmuxpolicy.go @@ -12,11 +12,14 @@ import ( type RTCPMuxPolicy int const ( + // RTCPMuxPolicyUnknown is the enum's zero-value. + RTCPMuxPolicyUnknown RTCPMuxPolicy = iota + // RTCPMuxPolicyNegotiate indicates to gather ICE candidates for both // RTP and RTCP candidates. If the remote-endpoint is capable of // multiplexing RTCP, multiplex RTCP on the RTP candidates. If it is not, // use both the RTP and RTCP candidates separately. - RTCPMuxPolicyNegotiate RTCPMuxPolicy = iota + 1 + RTCPMuxPolicyNegotiate // RTCPMuxPolicyRequire indicates to gather ICE candidates only for // RTP and multiplex RTCP on the RTP candidates. If the remote endpoint is @@ -37,7 +40,7 @@ func newRTCPMuxPolicy(raw string) RTCPMuxPolicy { case rtcpMuxPolicyRequireStr: return RTCPMuxPolicyRequire default: - return RTCPMuxPolicy(Unknown) + return RTCPMuxPolicyUnknown } } @@ -52,7 +55,7 @@ func (t RTCPMuxPolicy) String() string { } } -// UnmarshalJSON parses the JSON-encoded data and stores the result +// UnmarshalJSON parses the JSON-encoded data and stores the result. func (t *RTCPMuxPolicy) UnmarshalJSON(b []byte) error { var val string if err := json.Unmarshal(b, &val); err != nil { @@ -60,10 +63,11 @@ func (t *RTCPMuxPolicy) UnmarshalJSON(b []byte) error { } *t = newRTCPMuxPolicy(val) + return nil } -// MarshalJSON returns the JSON encoding +// MarshalJSON returns the JSON encoding. func (t RTCPMuxPolicy) MarshalJSON() ([]byte, error) { return json.Marshal(t.String()) } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/rtpcapabilities.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/rtpcapabilities.go similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/rtpcapabilities.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/rtpcapabilities.go diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/rtpcodec.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/rtpcodec.go similarity index 55% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/rtpcodec.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/rtpcodec.go index 5692d5f56..d4733dbd0 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/rtpcodec.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/rtpcodec.go @@ -4,27 +4,30 @@ package webrtc import ( + "fmt" "strings" - "github.com/pion/webrtc/v3/internal/fmtp" + "github.com/pion/webrtc/v4/internal/fmtp" ) -// RTPCodecType determines the type of a codec +// RTPCodecType determines the type of a codec. type RTPCodecType int const ( + // RTPCodecTypeUnknown is the enum's zero-value. + RTPCodecTypeUnknown RTPCodecType = iota - // RTPCodecTypeAudio indicates this is an audio codec - RTPCodecTypeAudio RTPCodecType = iota + 1 + // RTPCodecTypeAudio indicates this is an audio codec. + RTPCodecTypeAudio - // RTPCodecTypeVideo indicates this is a video codec + // RTPCodecTypeVideo indicates this is a video codec. RTPCodecTypeVideo ) func (t RTPCodecType) String() string { switch t { case RTPCodecTypeAudio: - return "audio" + return "audio" //nolint: goconst case RTPCodecTypeVideo: return "video" //nolint: goconst default: @@ -32,7 +35,7 @@ func (t RTPCodecType) String() string { } } -// NewRTPCodecType creates a RTPCodecType from a string +// NewRTPCodecType creates a RTPCodecType from a string. func NewRTPCodecType(r string) RTPCodecType { switch { case strings.EqualFold(r, RTPCodecTypeAudio.String()): @@ -100,24 +103,79 @@ const ( // Do a fuzzy find for a codec in the list of codecs // Used for lookup up a codec in an existing list to find a match -// Returns codecMatchExact, codecMatchPartial, or codecMatchNone -func codecParametersFuzzySearch(needle RTPCodecParameters, haystack []RTPCodecParameters) (RTPCodecParameters, codecMatchType) { - needleFmtp := fmtp.Parse(needle.RTPCodecCapability.MimeType, needle.RTPCodecCapability.SDPFmtpLine) +// Returns codecMatchExact, codecMatchPartial, or codecMatchNone. +func codecParametersFuzzySearch( + needle RTPCodecParameters, + haystack []RTPCodecParameters, +) (RTPCodecParameters, codecMatchType) { + needleFmtp := fmtp.Parse( + needle.RTPCodecCapability.MimeType, + needle.RTPCodecCapability.ClockRate, + needle.RTPCodecCapability.Channels, + needle.RTPCodecCapability.SDPFmtpLine) - // First attempt to match on MimeType + SDPFmtpLine + // First attempt to match on MimeType + ClockRate + Channels + SDPFmtpLine for _, c := range haystack { - cfmtp := fmtp.Parse(c.RTPCodecCapability.MimeType, c.RTPCodecCapability.SDPFmtpLine) + cfmtp := fmtp.Parse( + c.RTPCodecCapability.MimeType, + c.RTPCodecCapability.ClockRate, + c.RTPCodecCapability.Channels, + c.RTPCodecCapability.SDPFmtpLine) + if needleFmtp.Match(cfmtp) { return c, codecMatchExact } } - // Fallback to just MimeType + // Fallback to just MimeType + ClockRate + Channels for _, c := range haystack { - if strings.EqualFold(c.RTPCodecCapability.MimeType, needle.RTPCodecCapability.MimeType) { + if strings.EqualFold(c.RTPCodecCapability.MimeType, needle.RTPCodecCapability.MimeType) && + fmtp.ClockRateEqual(c.RTPCodecCapability.MimeType, + c.RTPCodecCapability.ClockRate, + needle.RTPCodecCapability.ClockRate) && + fmtp.ChannelsEqual(c.RTPCodecCapability.MimeType, + c.RTPCodecCapability.Channels, + needle.RTPCodecCapability.Channels) { return c, codecMatchPartial } } return RTPCodecParameters{}, codecMatchNone } + +// Given a CodecParameters find the RTX CodecParameters if one exists. +func findRTXPayloadType(needle PayloadType, haystack []RTPCodecParameters) PayloadType { + aptStr := fmt.Sprintf("apt=%d", needle) + for _, c := range haystack { + if aptStr == c.SDPFmtpLine { + return c.PayloadType + } + } + + return PayloadType(0) +} + +// For now, only FlexFEC is supported. +func findFECPayloadType(haystack []RTPCodecParameters) PayloadType { + for _, c := range haystack { + if strings.Contains(c.RTPCodecCapability.MimeType, MimeTypeFlexFEC) { + return c.PayloadType + } + } + + return PayloadType(0) +} + +func rtcpFeedbackIntersection(a, b []RTCPFeedback) (out []RTCPFeedback) { + for _, aFeedback := range a { + for _, bFeeback := range b { + if aFeedback.Type == bFeeback.Type && aFeedback.Parameter == bFeeback.Parameter { + out = append(out, aFeedback) + + break + } + } + } + + return +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/rtpcodingparameters.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/rtpcodingparameters.go similarity index 74% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/rtpcodingparameters.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/rtpcodingparameters.go index f03d8c35f..fa39a631d 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/rtpcodingparameters.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/rtpcodingparameters.go @@ -9,6 +9,12 @@ type RTPRtxParameters struct { SSRC SSRC `json:"ssrc"` } +// RTPFecParameters dictionary contains information relating to forward error correction (FEC) settings. +// https://draft.ortc.org/#dom-rtcrtpfecparameters +type RTPFecParameters struct { + SSRC SSRC `json:"ssrc"` +} + // RTPCodingParameters provides information relating to both encoding and decoding. // This is a subset of the RFC since Pion WebRTC doesn't implement encoding/decoding itself // http://draft.ortc.org/#dom-rtcrtpcodingparameters @@ -17,4 +23,5 @@ type RTPCodingParameters struct { SSRC SSRC `json:"ssrc"` PayloadType PayloadType `json:"payloadType"` RTX RTPRtxParameters `json:"rtx"` + FEC RTPFecParameters `json:"fec"` } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/rtpdecodingparameters.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/rtpdecodingparameters.go similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/rtpdecodingparameters.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/rtpdecodingparameters.go diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/rtpencodingparameters.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/rtpencodingparameters.go similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/rtpencodingparameters.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/rtpencodingparameters.go diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/rtpreceiveparameters.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/rtpreceiveparameters.go similarity index 95% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/rtpreceiveparameters.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/rtpreceiveparameters.go index 26a667616..a07bbc6c9 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/rtpreceiveparameters.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/rtpreceiveparameters.go @@ -3,7 +3,7 @@ package webrtc -// RTPReceiveParameters contains the RTP stack settings used by receivers +// RTPReceiveParameters contains the RTP stack settings used by receivers. type RTPReceiveParameters struct { Encodings []RTPDecodingParameters } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/rtpreceiver.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/rtpreceiver.go similarity index 61% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/rtpreceiver.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/rtpreceiver.go index dac154be6..109f88a4a 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/rtpreceiver.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/rtpreceiver.go @@ -7,6 +7,7 @@ package webrtc import ( + "encoding/binary" "fmt" "io" "sync" @@ -14,12 +15,12 @@ import ( "github.com/pion/interceptor" "github.com/pion/rtcp" - "github.com/pion/srtp/v2" - "github.com/pion/webrtc/v3/internal/util" + "github.com/pion/srtp/v3" + "github.com/pion/webrtc/v4/internal/util" ) // trackStreams maintains a mapping of RTP/RTCP streams to a specific track -// a RTPReceiver may contain multiple streams if we are dealing with Simulcast +// a RTPReceiver may contain multiple streams if we are dealing with Simulcast. type trackStreams struct { track *TrackRemote @@ -31,14 +32,29 @@ type trackStreams struct { rtcpReadStream *srtp.ReadStreamSRTCP rtcpInterceptor interceptor.RTCPReader - repairReadStream *srtp.ReadStreamSRTP - repairInterceptor interceptor.RTPReader + repairReadStream *srtp.ReadStreamSRTP + repairInterceptor interceptor.RTPReader + repairStreamChannel chan rtxPacketWithAttributes repairRtcpReadStream *srtp.ReadStreamSRTCP repairRtcpInterceptor interceptor.RTCPReader } -// RTPReceiver allows an application to inspect the receipt of a TrackRemote +type rtxPacketWithAttributes struct { + pkt []byte + attributes interceptor.Attributes + pool *sync.Pool +} + +func (p *rtxPacketWithAttributes) release() { + if p.pkt != nil { + b := p.pkt[:cap(p.pkt)] + p.pool.Put(b) // nolint:staticcheck + p.pkt = nil + } +} + +// RTPReceiver allows an application to inspect the receipt of a TrackRemote. type RTPReceiver struct { kind RTPCodecType transport *DTLSTransport @@ -52,9 +68,11 @@ type RTPReceiver struct { // A reference to the associated api object api *API + + rtxPool sync.Pool } -// NewRTPReceiver constructs a new RTPReceiver +// NewRTPReceiver constructs a new RTPReceiver. func (api *API) NewRTPReceiver(kind RTPCodecType, transport *DTLSTransport) (*RTPReceiver, error) { if transport == nil { return nil, errRTPReceiverDTLSTransportNil @@ -67,6 +85,9 @@ func (api *API) NewRTPReceiver(kind RTPCodecType, transport *DTLSTransport) (*RT closed: make(chan interface{}), received: make(chan interface{}), tracks: []trackStreams{}, + rtxPool: sync.Pool{New: func() interface{} { + return make([]byte, api.settingEngine.getReceiveMTU()) + }}, } return r, nil @@ -79,18 +100,23 @@ func (r *RTPReceiver) setRTPTransceiver(tr *RTPTransceiver) { } // Transport returns the currently-configured *DTLSTransport or nil -// if one has not yet been configured +// if one has not yet been configured. func (r *RTPReceiver) Transport() *DTLSTransport { r.mu.RLock() defer r.mu.RUnlock() + return r.transport } func (r *RTPReceiver) getParameters() RTPParameters { - parameters := r.api.mediaEngine.getRTPParametersByKind(r.kind, []RTPTransceiverDirection{RTPTransceiverDirectionRecvonly}) + parameters := r.api.mediaEngine.getRTPParametersByKind( + r.kind, + []RTPTransceiverDirection{RTPTransceiverDirectionRecvonly}, + ) if r.tr != nil { parameters.Codecs = r.tr.getCodecs() } + return parameters } @@ -99,10 +125,11 @@ func (r *RTPReceiver) getParameters() RTPParameters { func (r *RTPReceiver) GetParameters() RTPParameters { r.mu.RLock() defer r.mu.RUnlock() + return r.getParameters() } -// Track returns the RtpTransceiver TrackRemote +// Track returns the RtpTransceiver TrackRemote. func (r *RTPReceiver) Track() *TrackRemote { r.mu.RLock() defer r.mu.RUnlock() @@ -110,11 +137,12 @@ func (r *RTPReceiver) Track() *TrackRemote { if len(r.tracks) != 1 { return nil } + return r.tracks[0].track } // Tracks returns the RtpTransceiver tracks -// A RTPReceiver to support Simulcast may now have multiple tracks +// A RTPReceiver to support Simulcast may now have multiple tracks. func (r *RTPReceiver) Tracks() []*TrackRemote { r.mu.RLock() defer r.mu.RUnlock() @@ -123,10 +151,20 @@ func (r *RTPReceiver) Tracks() []*TrackRemote { for i := range r.tracks { tracks = append(tracks, r.tracks[i].track) } + return tracks } -// configureReceive initialize the track +// RTPTransceiver returns the RTPTransceiver this +// RTPReceiver belongs too, or nil if none. +func (r *RTPReceiver) RTPTransceiver() *RTPTransceiver { + r.mu.Lock() + defer r.mu.Unlock() + + return r.tr +} + +// configureReceive initialize the track. func (r *RTPReceiver) configureReceive(parameters RTPReceiveParameters) { r.mu.Lock() defer r.mu.Unlock() @@ -136,6 +174,7 @@ func (r *RTPReceiver) configureReceive(parameters RTPReceiveParameters) { track: newTrackRemote( r.kind, parameters.Encodings[i].SSRC, + parameters.Encodings[i].RTX.SSRC, parameters.Encodings[i].RID, r, ), @@ -145,8 +184,8 @@ func (r *RTPReceiver) configureReceive(parameters RTPReceiveParameters) { } } -// startReceive starts all the transports -func (r *RTPReceiver) startReceive(parameters RTPReceiveParameters) error { +// startReceive starts all the transports. +func (r *RTPReceiver) startReceive(parameters RTPReceiveParameters) error { //nolint:cyclop r.mu.Lock() defer r.mu.Unlock() select { @@ -154,7 +193,6 @@ func (r *RTPReceiver) startReceive(parameters RTPReceiveParameters) error { return errRTPReceiverReceiveAlreadyCalled default: } - defer close(r.received) globalParams := r.getParameters() codec := RTPCodecCapability{} @@ -168,48 +206,69 @@ func (r *RTPReceiver) startReceive(parameters RTPReceiveParameters) error { continue } - var t *trackStreams + var streams *trackStreams for idx, ts := range r.tracks { - if ts.track != nil && parameters.Encodings[i].SSRC != 0 && ts.track.SSRC() == parameters.Encodings[i].SSRC { - t = &r.tracks[idx] + if ts.track != nil && ts.track.SSRC() == parameters.Encodings[i].SSRC { + streams = &r.tracks[idx] + break } } - if t == nil { + if streams == nil { return fmt.Errorf("%w: %d", errRTPReceiverWithSSRCTrackStreamNotFound, parameters.Encodings[i].SSRC) } - if parameters.Encodings[i].SSRC != 0 { - t.streamInfo = createStreamInfo("", parameters.Encodings[i].SSRC, 0, codec, globalParams.HeaderExtensions) - var err error - if t.rtpReadStream, t.rtpInterceptor, t.rtcpReadStream, t.rtcpInterceptor, err = r.transport.streamsForSSRC(parameters.Encodings[i].SSRC, *t.streamInfo); err != nil { - return err - } + streams.streamInfo = createStreamInfo( + "", + parameters.Encodings[i].SSRC, + 0, 0, 0, 0, 0, + codec, + globalParams.HeaderExtensions, + ) + var err error + + //nolint:lll // # TODO refactor + if streams.rtpReadStream, streams.rtpInterceptor, streams.rtcpReadStream, streams.rtcpInterceptor, err = r.transport.streamsForSSRC(parameters.Encodings[i].SSRC, *streams.streamInfo); err != nil { + return err } if rtxSsrc := parameters.Encodings[i].RTX.SSRC; rtxSsrc != 0 { - streamInfo := createStreamInfo("", rtxSsrc, 0, codec, globalParams.HeaderExtensions) - rtpReadStream, rtpInterceptor, rtcpReadStream, rtcpInterceptor, err := r.transport.streamsForSSRC(rtxSsrc, *streamInfo) + streamInfo := createStreamInfo("", rtxSsrc, 0, 0, 0, 0, 0, codec, globalParams.HeaderExtensions) + rtpReadStream, rtpInterceptor, rtcpReadStream, rtcpInterceptor, err := r.transport.streamsForSSRC( + rtxSsrc, + *streamInfo, + ) if err != nil { return err } - if err = r.receiveForRtx(rtxSsrc, "", streamInfo, rtpReadStream, rtpInterceptor, rtcpReadStream, rtcpInterceptor); err != nil { + if err = r.receiveForRtx( + rtxSsrc, + "", + streamInfo, + rtpReadStream, + rtpInterceptor, + rtcpReadStream, + rtcpInterceptor, + ); err != nil { return err } } } + close(r.received) + return nil } -// Receive initialize the track and starts all the transports +// Receive initialize the track and starts all the transports. func (r *RTPReceiver) Receive(parameters RTPReceiveParameters) error { r.configureReceive(parameters) + return r.startReceive(parameters) } -// Read reads incoming RTCP for this RTPReceiver +// Read reads incoming RTCP for this RTPReceiver. func (r *RTPReceiver) Read(b []byte) (n int, a interceptor.Attributes, err error) { select { case <-r.received: @@ -219,16 +278,26 @@ func (r *RTPReceiver) Read(b []byte) (n int, a interceptor.Attributes, err error } } -// ReadSimulcast reads incoming RTCP for this RTPReceiver for given rid +// ReadSimulcast reads incoming RTCP for this RTPReceiver for given rid. func (r *RTPReceiver) ReadSimulcast(b []byte, rid string) (n int, a interceptor.Attributes, err error) { select { case <-r.received: + var rtcpInterceptor interceptor.RTCPReader + + r.mu.Lock() for _, t := range r.tracks { if t.track != nil && t.track.rid == rid { - return t.rtcpInterceptor.Read(b, a) + rtcpInterceptor = t.rtcpInterceptor } } - return 0, nil, fmt.Errorf("%w: %s", errRTPReceiverForRIDTrackStreamNotFound, rid) + r.mu.Unlock() + + if rtcpInterceptor == nil { + return 0, nil, fmt.Errorf("%w: %s", errRTPReceiverForRIDTrackStreamNotFound, rid) + } + + return rtcpInterceptor.Read(b, a) + case <-r.closed: return 0, nil, io.ErrClosedPipe } @@ -251,7 +320,7 @@ func (r *RTPReceiver) ReadRTCP() ([]rtcp.Packet, interceptor.Attributes, error) return pkts, attributes, nil } -// ReadSimulcastRTCP is a convenience method that wraps ReadSimulcast and unmarshal for you +// ReadSimulcastRTCP is a convenience method that wraps ReadSimulcast and unmarshal for you. func (r *RTPReceiver) ReadSimulcastRTCP(rid string) ([]rtcp.Packet, interceptor.Attributes, error) { b := make([]byte, r.api.settingEngine.getReceiveMTU()) i, attributes, err := r.ReadSimulcast(b, rid) @@ -260,6 +329,7 @@ func (r *RTPReceiver) ReadSimulcastRTCP(rid string) ([]rtcp.Packet, interceptor. } pkts, err := rtcp.Unmarshal(b[:i]) + return pkts, attributes, err } @@ -272,8 +342,8 @@ func (r *RTPReceiver) haveReceived() bool { } } -// Stop irreversibly stops the RTPReceiver -func (r *RTPReceiver) Stop() error { +// Stop irreversibly stops the RTPReceiver. +func (r *RTPReceiver) Stop() error { //nolint:cyclop r.mu.Lock() defer r.mu.Unlock() var err error @@ -319,6 +389,7 @@ func (r *RTPReceiver) Stop() error { } close(r.closed) + return err } @@ -328,12 +399,18 @@ func (r *RTPReceiver) streamsForTrack(t *TrackRemote) *trackStreams { return &r.tracks[i] } } + return nil } -// readRTP should only be called by a track, this only exists so we can keep state in one place +// readRTP should only be called by a track, this only exists so we can keep state in one place. func (r *RTPReceiver) readRTP(b []byte, reader *TrackRemote) (n int, a interceptor.Attributes, err error) { - <-r.received + select { + case <-r.received: + case <-r.closed: + return 0, nil, io.EOF + } + if t := r.streamsForTrack(reader); t != nil { return t.rtpInterceptor.Read(b, a) } @@ -342,8 +419,16 @@ func (r *RTPReceiver) readRTP(b []byte, reader *TrackRemote) (n int, a intercept } // receiveForRid is the sibling of Receive expect for RIDs instead of SSRCs -// It populates all the internal state for the given RID -func (r *RTPReceiver) receiveForRid(rid string, params RTPParameters, streamInfo *interceptor.StreamInfo, rtpReadStream *srtp.ReadStreamSRTP, rtpInterceptor interceptor.RTPReader, rtcpReadStream *srtp.ReadStreamSRTCP, rtcpInterceptor interceptor.RTCPReader) (*TrackRemote, error) { +// It populates all the internal state for the given RID. +func (r *RTPReceiver) receiveForRid( + rid string, + params RTPParameters, + streamInfo *interceptor.StreamInfo, + rtpReadStream *srtp.ReadStreamSRTP, + rtpInterceptor interceptor.RTPReader, + rtcpReadStream *srtp.ReadStreamSRTCP, + rtcpInterceptor interceptor.RTCPReader, +) (*TrackRemote, error) { r.mu.Lock() defer r.mu.Unlock() @@ -369,10 +454,18 @@ func (r *RTPReceiver) receiveForRid(rid string, params RTPParameters, streamInfo return nil, fmt.Errorf("%w: %s", errRTPReceiverForRIDTrackStreamNotFound, rid) } -// receiveForRtx starts a routine that processes the repair stream -// These packets aren't exposed to the user yet, but we need to process them for -// TWCC -func (r *RTPReceiver) receiveForRtx(ssrc SSRC, rsid string, streamInfo *interceptor.StreamInfo, rtpReadStream *srtp.ReadStreamSRTP, rtpInterceptor interceptor.RTPReader, rtcpReadStream *srtp.ReadStreamSRTCP, rtcpInterceptor interceptor.RTCPReader) error { +// receiveForRtx starts a routine that processes the repair stream. +// +//nolint:cyclop +func (r *RTPReceiver) receiveForRtx( + ssrc SSRC, + rsid string, + streamInfo *interceptor.StreamInfo, + rtpReadStream *srtp.ReadStreamSRTP, + rtpInterceptor interceptor.RTPReader, + rtcpReadStream *srtp.ReadStreamSRTCP, + rtcpInterceptor interceptor.RTCPReader, +) error { var track *trackStreams if ssrc != 0 && len(r.tracks) == 1 { track = &r.tracks[0] @@ -380,6 +473,11 @@ func (r *RTPReceiver) receiveForRtx(ssrc SSRC, rsid string, streamInfo *intercep for i := range r.tracks { if r.tracks[i].track.RID() == rsid { track = &r.tracks[i] + if track.track.RtxSSRC() == 0 { + track.track.setRtxSSRC(SSRC(streamInfo.SSRC)) + } + + break } } } @@ -393,15 +491,65 @@ func (r *RTPReceiver) receiveForRtx(ssrc SSRC, rsid string, streamInfo *intercep track.repairInterceptor = rtpInterceptor track.repairRtcpReadStream = rtcpReadStream track.repairRtcpInterceptor = rtcpInterceptor + track.repairStreamChannel = make(chan rtxPacketWithAttributes, 50) go func() { - b := make([]byte, r.api.settingEngine.getReceiveMTU()) for { - if _, _, readErr := track.repairInterceptor.Read(b, nil); readErr != nil { + b := r.rtxPool.Get().([]byte) // nolint:forcetypeassert + i, attributes, err := track.repairInterceptor.Read(b, nil) + if err != nil { + r.rtxPool.Put(b) // nolint:staticcheck + return } + + // RTX packets have a different payload format. Move the OSN in the payload to the RTP header and rewrite the + // payload type and SSRC, so that we can return RTX packets to the caller 'transparently' i.e. in the same format + // as non-RTX RTP packets + hasExtension := b[0]&0b10000 > 0 + hasPadding := b[0]&0b100000 > 0 + csrcCount := b[0] & 0b1111 + headerLength := uint16(12 + (4 * csrcCount)) + paddingLength := 0 + if hasExtension { + headerLength += 4 * (1 + binary.BigEndian.Uint16(b[headerLength+2:headerLength+4])) + } + if hasPadding { + paddingLength = int(b[i-1]) + } + + if i-int(headerLength)-paddingLength < 2 { + // BWE probe packet, ignore + r.rtxPool.Put(b) // nolint:staticcheck + + continue + } + + if attributes == nil { + attributes = make(interceptor.Attributes) + } + attributes.Set(AttributeRtxPayloadType, b[1]&0x7F) + attributes.Set(AttributeRtxSequenceNumber, binary.BigEndian.Uint16(b[2:4])) + attributes.Set(AttributeRtxSsrc, binary.BigEndian.Uint32(b[8:12])) + + b[1] = (b[1] & 0x80) | uint8(track.track.PayloadType()) + b[2] = b[headerLength] + b[3] = b[headerLength+1] + binary.BigEndian.PutUint32(b[8:12], uint32(track.track.SSRC())) + copy(b[headerLength:i-2], b[headerLength+2:i]) + + select { + case <-r.closed: + r.rtxPool.Put(b) // nolint:staticcheck + + return + case track.repairStreamChannel <- rtxPacketWithAttributes{pkt: b[:i-2], attributes: attributes, pool: &r.rtxPool}: + default: + // skip the RTX packet if the repair stream channel is full, could be blocked in the application's read loop + } } }() + return nil } @@ -413,7 +561,8 @@ func (r *RTPReceiver) SetReadDeadline(t time.Time) error { return r.tracks[0].rtcpReadStream.SetReadDeadline(t) } -// SetReadDeadlineSimulcast sets the max amount of time the RTCP stream for a given rid will block before returning. 0 is forever. +// SetReadDeadlineSimulcast sets the max amount of time the RTCP stream for a given rid will block before returning. +// 0 is forever. func (r *RTPReceiver) SetReadDeadlineSimulcast(deadline time.Time, rid string) error { r.mu.RLock() defer r.mu.RUnlock() @@ -423,11 +572,12 @@ func (r *RTPReceiver) SetReadDeadlineSimulcast(deadline time.Time, rid string) e return t.rtcpReadStream.SetReadDeadline(deadline) } } + return fmt.Errorf("%w: %s", errRTPReceiverForRIDTrackStreamNotFound, rid) } // setRTPReadDeadline sets the max amount of time the RTP stream will block before returning. 0 is forever. -// This should be fired by calling SetReadDeadline on the TrackRemote +// This should be fired by calling SetReadDeadline on the TrackRemote. func (r *RTPReceiver) setRTPReadDeadline(deadline time.Time, reader *TrackRemote) error { r.mu.RLock() defer r.mu.RUnlock() @@ -435,5 +585,29 @@ func (r *RTPReceiver) setRTPReadDeadline(deadline time.Time, reader *TrackRemote if t := r.streamsForTrack(reader); t != nil { return t.rtpReadStream.SetReadDeadline(deadline) } + return fmt.Errorf("%w: %d", errRTPReceiverWithSSRCTrackStreamNotFound, reader.SSRC()) } + +// readRTX returns an RTX packet if one is available on the RTX track, otherwise returns nil. +func (r *RTPReceiver) readRTX(reader *TrackRemote) *rtxPacketWithAttributes { + if !reader.HasRTX() { + return nil + } + + select { + case <-r.received: + default: + return nil + } + + if t := r.streamsForTrack(reader); t != nil { + select { + case rtxPacketReceived := <-t.repairStreamChannel: + return &rtxPacketReceived + default: + } + } + + return nil +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/rtpreceiver_go.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/rtpreceiver_go.go similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/rtpreceiver_go.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/rtpreceiver_go.go diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/rtpreceiver_js.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/rtpreceiver_js.go similarity index 76% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/rtpreceiver_js.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/rtpreceiver_js.go index 44cef72d1..af82a6cb3 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/rtpreceiver_js.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/rtpreceiver_js.go @@ -13,3 +13,8 @@ type RTPReceiver struct { // Pointer to the underlying JavaScript RTCRTPReceiver object. underlying js.Value } + +// JSValue returns the underlying RTCRtpReceiver +func (r *RTPReceiver) JSValue() js.Value { + return r.underlying +} \ No newline at end of file diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/rtpsender.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/rtpsender.go similarity index 68% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/rtpsender.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/rtpsender.go index 49ae4e82e..dd4107ecb 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/rtpsender.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/rtpsender.go @@ -16,7 +16,7 @@ import ( "github.com/pion/randutil" "github.com/pion/rtcp" "github.com/pion/rtp" - "github.com/pion/webrtc/v3/internal/util" + "github.com/pion/webrtc/v4/internal/util" ) type trackEncoding struct { @@ -27,12 +27,12 @@ type trackEncoding struct { rtcpInterceptor interceptor.RTCPReader streamInfo interceptor.StreamInfo - context TrackLocalContext + context *baseTrackLocalContext - ssrc SSRC + ssrc, ssrcRTX, ssrcFEC SSRC } -// RTPSender allows an application to control how a given Track is encoded and transmitted to a remote peer +// RTPSender allows an application to control how a given Track is encoded and transmitted to a remote peer. type RTPSender struct { trackEncodings []*trackEncoding @@ -57,7 +57,7 @@ type RTPSender struct { sendCalled, stopCalled chan struct{} } -// NewRTPSender constructs a new RTPSender +// NewRTPSender constructs a new RTPSender. func (api *API) NewRTPSender(track TrackLocal, transport *DTLSTransport) (*RTPSender, error) { if track == nil { return nil, errRTPSenderTrackNil @@ -87,6 +87,7 @@ func (api *API) NewRTPSender(track TrackLocal, transport *DTLSTransport) (*RTPSe func (r *RTPSender) isNegotiated() bool { r.mu.RLock() defer r.mu.RUnlock() + return r.negotiated } @@ -103,14 +104,20 @@ func (r *RTPSender) setRTPTransceiver(rtpTransceiver *RTPTransceiver) { } // Transport returns the currently-configured *DTLSTransport or nil -// if one has not yet been configured +// if one has not yet been configured. func (r *RTPSender) Transport() *DTLSTransport { r.mu.RLock() defer r.mu.RUnlock() + return r.transport } -func (r *RTPSender) getParameters() RTPSendParameters { +// GetParameters describes the current configuration for the encoding and +// transmission of media on the sender's track. +func (r *RTPSender) GetParameters() RTPSendParameters { + r.mu.RLock() + defer r.mu.RUnlock() + var encodings []RTPEncodingParameters for _, trackEncoding := range r.trackEncodings { var rid string @@ -121,6 +128,8 @@ func (r *RTPSender) getParameters() RTPSendParameters { RTPCodingParameters: RTPCodingParameters{ RID: rid, SSRC: trackEncoding.ssrc, + RTX: RTPRtxParameters{SSRC: trackEncoding.ssrcRTX}, + FEC: RTPFecParameters{SSRC: trackEncoding.ssrcFEC}, PayloadType: r.payloadType, }, }) @@ -137,19 +146,12 @@ func (r *RTPSender) getParameters() RTPSendParameters { } else { sendParameters.Codecs = r.api.mediaEngine.getCodecsByKind(r.kind) } + return sendParameters } -// GetParameters describes the current configuration for the encoding and -// transmission of media on the sender's track. -func (r *RTPSender) GetParameters() RTPSendParameters { - r.mu.RLock() - defer r.mu.RUnlock() - return r.getParameters() -} - // AddEncoding adds an encoding to RTPSender. Used by simulcast senders. -func (r *RTPSender) AddEncoding(track TrackLocal) error { +func (r *RTPSender) AddEncoding(track TrackLocal) error { //nolint:cyclop r.mu.Lock() defer r.mu.Unlock() @@ -192,28 +194,28 @@ func (r *RTPSender) AddEncoding(track TrackLocal) error { } r.addEncoding(track) + return nil } func (r *RTPSender) addEncoding(track TrackLocal) { - ssrc := SSRC(randutil.NewMathRandomGenerator().Uint32()) trackEncoding := &trackEncoding{ - track: track, - srtpStream: &srtpWriterFuture{ssrc: ssrc}, - ssrc: ssrc, + track: track, + ssrc: SSRC(util.RandUint32()), + } + + if r.api.mediaEngine.isRTXEnabled(r.kind, []RTPTransceiverDirection{RTPTransceiverDirectionSendonly}) { + trackEncoding.ssrcRTX = SSRC(util.RandUint32()) + } + + if r.api.mediaEngine.isFECEnabled(r.kind, []RTPTransceiverDirection{RTPTransceiverDirectionSendonly}) { + trackEncoding.ssrcFEC = SSRC(util.RandUint32()) } - trackEncoding.srtpStream.rtpSender = r - trackEncoding.rtcpInterceptor = r.api.interceptor.BindRTCPReader( - interceptor.RTPReaderFunc(func(in []byte, a interceptor.Attributes) (n int, attributes interceptor.Attributes, err error) { - n, err = trackEncoding.srtpStream.Read(in) - return n, a, err - }), - ) r.trackEncodings = append(r.trackEncodings, trackEncoding) } -// Track returns the RTCRtpTransceiver track, or nil +// Track returns the RTCRtpTransceiver track, or nil. func (r *RTPSender) Track() TrackLocal { r.mu.RLock() defer r.mu.RUnlock() @@ -228,7 +230,7 @@ func (r *RTPSender) Track() TrackLocal { // ReplaceTrack replaces the track currently being used as the sender's source with a new TrackLocal. // The new track must be of the same media kind (audio, video, etc) and switching the track should not // require negotiation. -func (r *RTPSender) ReplaceTrack(track TrackLocal) error { +func (r *RTPSender) ReplaceTrack(track TrackLocal) error { //nolint:cyclop r.mu.Lock() defer r.mu.Unlock() @@ -242,32 +244,44 @@ func (r *RTPSender) ReplaceTrack(track TrackLocal) error { } var replacedTrack TrackLocal - var context *TrackLocalContext - if len(r.trackEncodings) != 0 { - replacedTrack = r.trackEncodings[0].track - context = &r.trackEncodings[0].context - } - if r.hasSent() && replacedTrack != nil { - if err := replacedTrack.Unbind(*context); err != nil { - return err + var context *baseTrackLocalContext + for _, e := range r.trackEncodings { + replacedTrack = e.track + context = e.context + + if r.hasSent() && replacedTrack != nil { + if err := replacedTrack.Unbind(context); err != nil { + return err + } + } + + if !r.hasSent() || track == nil { + e.track = track } } if !r.hasSent() || track == nil { - r.trackEncodings[0].track = track return nil } - codec, err := track.Bind(TrackLocalContext{ - id: context.id, - params: r.api.mediaEngine.getRTPParametersByKind(track.Kind(), []RTPTransceiverDirection{RTPTransceiverDirectionSendonly}), - ssrc: context.ssrc, - writeStream: context.writeStream, - rtcpInterceptor: context.rtcpInterceptor, + params := r.api.mediaEngine.getRTPParametersByKind( + track.Kind(), + []RTPTransceiverDirection{RTPTransceiverDirectionSendonly}, + ) + + // If we reach this point in the routine, there is only 1 track encoding + codec, err := track.Bind(&baseTrackLocalContext{ + id: context.ID(), + params: params, + ssrc: context.SSRC(), + ssrcRTX: context.SSRCRetransmission(), + ssrcFEC: context.SSRCForwardErrorCorrection(), + writeStream: context.WriteStream(), + rtcpInterceptor: context.RTCPReader(), }) if err != nil { // Re-bind the original track - if _, reBindErr := replacedTrack.Bind(*context); reBindErr != nil { + if _, reBindErr := replacedTrack.Bind(context); reBindErr != nil { return reBindErr } @@ -280,6 +294,7 @@ func (r *RTPSender) ReplaceTrack(track TrackLocal) error { } r.trackEncodings[0].track = track + return nil } @@ -295,12 +310,34 @@ func (r *RTPSender) Send(parameters RTPSendParameters) error { return errRTPSenderTrackRemoved } - for idx, trackEncoding := range r.trackEncodings { + for idx := range r.trackEncodings { + trackEncoding := r.trackEncodings[idx] + srtpStream := &srtpWriterFuture{ssrc: parameters.Encodings[idx].SSRC, rtpSender: r} writeStream := &interceptorToTrackLocalWriter{} - trackEncoding.context = TrackLocalContext{ + rtpParameters := r.api.mediaEngine.getRTPParametersByKind( + trackEncoding.track.Kind(), + []RTPTransceiverDirection{RTPTransceiverDirectionSendonly}, + ) + + trackEncoding.srtpStream = srtpStream + trackEncoding.ssrc = parameters.Encodings[idx].SSRC + trackEncoding.ssrcRTX = parameters.Encodings[idx].RTX.SSRC + trackEncoding.ssrcFEC = parameters.Encodings[idx].FEC.SSRC + trackEncoding.rtcpInterceptor = r.api.interceptor.BindRTCPReader( + interceptor.RTCPReaderFunc( + func(in []byte, a interceptor.Attributes) (n int, attributes interceptor.Attributes, err error) { + n, err = trackEncoding.srtpStream.Read(in) + + return n, a, err + }, + ), + ) + trackEncoding.context = &baseTrackLocalContext{ id: r.id, - params: r.api.mediaEngine.getRTPParametersByKind(trackEncoding.track.Kind(), []RTPTransceiverDirection{RTPTransceiverDirectionSendonly}), + params: rtpParameters, ssrc: parameters.Encodings[idx].SSRC, + ssrcFEC: parameters.Encodings[idx].FEC.SSRC, + ssrcRTX: parameters.Encodings[idx].RTX.SSRC, writeStream: writeStream, rtcpInterceptor: trackEncoding.rtcpInterceptor, } @@ -314,30 +351,37 @@ func (r *RTPSender) Send(parameters RTPSendParameters) error { trackEncoding.streamInfo = *createStreamInfo( r.id, parameters.Encodings[idx].SSRC, + parameters.Encodings[idx].RTX.SSRC, + parameters.Encodings[idx].FEC.SSRC, codec.PayloadType, + findRTXPayloadType(codec.PayloadType, rtpParameters.Codecs), + findFECPayloadType(rtpParameters.Codecs), codec.RTPCodecCapability, parameters.HeaderExtensions, ) - srtpStream := trackEncoding.srtpStream + rtpInterceptor := r.api.interceptor.BindLocalStream( &trackEncoding.streamInfo, - interceptor.RTPWriterFunc(func(header *rtp.Header, payload []byte, attributes interceptor.Attributes) (int, error) { + interceptor.RTPWriterFunc(func(header *rtp.Header, payload []byte, _ interceptor.Attributes) (int, error) { return srtpStream.WriteRTP(header, payload) }), ) + writeStream.interceptor.Store(rtpInterceptor) } close(r.sendCalled) + return nil } -// Stop irreversibly stops the RTPSender +// Stop irreversibly stops the RTPSender. func (r *RTPSender) Stop() error { r.mu.Lock() if stopped := r.hasStopped(); stopped { r.mu.Unlock() + return nil } @@ -355,13 +399,15 @@ func (r *RTPSender) Stop() error { errs := []error{} for _, trackEncoding := range r.trackEncodings { r.api.interceptor.UnbindLocalStream(&trackEncoding.streamInfo) - errs = append(errs, trackEncoding.srtpStream.Close()) + if trackEncoding.srtpStream != nil { + errs = append(errs, trackEncoding.srtpStream.Close()) + } } return util.FlattenErrs(errs) } -// Read reads incoming RTCP for this RTPSender +// Read reads incoming RTCP for this RTPSender. func (r *RTPSender) Read(b []byte) (n int, a interceptor.Attributes, err error) { select { case <-r.sendCalled: @@ -387,22 +433,28 @@ func (r *RTPSender) ReadRTCP() ([]rtcp.Packet, interceptor.Attributes, error) { return pkts, attributes, nil } -// ReadSimulcast reads incoming RTCP for this RTPSender for given rid +// ReadSimulcast reads incoming RTCP for this RTPSender for given rid. func (r *RTPSender) ReadSimulcast(b []byte, rid string) (n int, a interceptor.Attributes, err error) { select { case <-r.sendCalled: + r.mu.Lock() for _, t := range r.trackEncodings { if t.track != nil && t.track.RID() == rid { - return t.rtcpInterceptor.Read(b, a) + reader := t.rtcpInterceptor + r.mu.Unlock() + + return reader.Read(b, a) } } + r.mu.Unlock() + return 0, nil, fmt.Errorf("%w: %s", errRTPSenderNoTrackForRID, rid) case <-r.stopCalled: return 0, nil, io.ErrClosedPipe } } -// ReadSimulcastRTCP is a convenience method that wraps ReadSimulcast and unmarshal for you +// ReadSimulcastRTCP is a convenience method that wraps ReadSimulcast and unmarshal for you. func (r *RTPSender) ReadSimulcastRTCP(rid string) ([]rtcp.Packet, interceptor.Attributes, error) { b := make([]byte, r.api.settingEngine.getReceiveMTU()) i, attributes, err := r.ReadSimulcast(b, rid) @@ -411,6 +463,7 @@ func (r *RTPSender) ReadSimulcastRTCP(rid string) ([]rtcp.Packet, interceptor.At } pkts, err := rtcp.Unmarshal(b[:i]) + return pkts, attributes, err } @@ -420,7 +473,8 @@ func (r *RTPSender) SetReadDeadline(t time.Time) error { return r.trackEncodings[0].srtpStream.SetReadDeadline(t) } -// SetReadDeadlineSimulcast sets the max amount of time the RTCP stream for a given rid will block before returning. 0 is forever. +// SetReadDeadlineSimulcast sets the max amount of time the RTCP stream for a given rid +// will block before returning. 0 is forever. func (r *RTPSender) SetReadDeadlineSimulcast(deadline time.Time, rid string) error { r.mu.RLock() defer r.mu.RUnlock() @@ -430,10 +484,11 @@ func (r *RTPSender) SetReadDeadlineSimulcast(deadline time.Time, rid string) err return t.srtpStream.SetReadDeadline(deadline) } } + return fmt.Errorf("%w: %s", errRTPSenderNoTrackForRID, rid) } -// hasSent tells if data has been ever sent for this instance +// hasSent tells if data has been ever sent for this instance. func (r *RTPSender) hasSent() bool { select { case <-r.sendCalled: @@ -443,7 +498,7 @@ func (r *RTPSender) hasSent() bool { } } -// hasStopped tells if stop has been called +// hasStopped tells if stop has been called. func (r *RTPSender) hasStopped() bool { select { case <-r.stopCalled: @@ -452,3 +507,20 @@ func (r *RTPSender) hasStopped() bool { return false } } + +// Set a SSRC for FEC and RTX if MediaEngine has them enabled +// If the remote doesn't support FEC or RTX we disable locally. +func (r *RTPSender) configureRTXAndFEC() { + r.mu.RLock() + defer r.mu.RUnlock() + + for _, trackEncoding := range r.trackEncodings { + if !r.api.mediaEngine.isRTXEnabled(r.kind, []RTPTransceiverDirection{RTPTransceiverDirectionSendonly}) { + trackEncoding.ssrcRTX = SSRC(0) + } + + if !r.api.mediaEngine.isFECEnabled(r.kind, []RTPTransceiverDirection{RTPTransceiverDirectionSendonly}) { + trackEncoding.ssrcFEC = SSRC(0) + } + } +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/rtpsender_js.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/rtpsender_js.go similarity index 77% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/rtpsender_js.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/rtpsender_js.go index 46ea599f7..42a574320 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/rtpsender_js.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/rtpsender_js.go @@ -13,3 +13,8 @@ type RTPSender struct { // Pointer to the underlying JavaScript RTCRTPSender object. underlying js.Value } + +// JSValue returns the underlying RTCRtpSender +func (s *RTPSender) JSValue() js.Value { + return s.underlying +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/rtpsendparameters.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/rtpsendparameters.go similarity index 97% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/rtpsendparameters.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/rtpsendparameters.go index b955c61ce..685729193 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/rtpsendparameters.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/rtpsendparameters.go @@ -3,7 +3,7 @@ package webrtc -// RTPSendParameters contains the RTP stack settings used by receivers +// RTPSendParameters contains the RTP stack settings used by receivers. type RTPSendParameters struct { RTPParameters Encodings []RTPEncodingParameters diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/rtptransceiver.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/rtptransceiver.go similarity index 85% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/rtptransceiver.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/rtptransceiver.go index 02ddf7924..5ce0f2d48 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/rtptransceiver.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/rtptransceiver.go @@ -24,8 +24,7 @@ type RTPTransceiver struct { codecs []RTPCodecParameters // User provided codecs via SetCodecPreferences - stopped bool - kind RTPCodecType + kind RTPCodecType api *API mu sync.RWMutex @@ -42,27 +41,31 @@ func newRTPTransceiver( t.setReceiver(receiver) t.setSender(sender) t.setDirection(direction) - t.setCurrentDirection(RTPTransceiverDirection(Unknown)) + t.setCurrentDirection(RTPTransceiverDirectionUnknown) + return t } // SetCodecPreferences sets preferred list of supported codecs -// if codecs is empty or nil we reset to default from MediaEngine +// if codecs is empty or nil we reset to default from MediaEngine. func (t *RTPTransceiver) SetCodecPreferences(codecs []RTPCodecParameters) error { t.mu.Lock() defer t.mu.Unlock() for _, codec := range codecs { - if _, matchType := codecParametersFuzzySearch(codec, t.api.mediaEngine.getCodecsByKind(t.kind)); matchType == codecMatchNone { + if _, matchType := codecParametersFuzzySearch( + codec, t.api.mediaEngine.getCodecsByKind(t.kind), + ); matchType == codecMatchNone { return fmt.Errorf("%w %s", errRTPTransceiverCodecUnsupported, codec.MimeType) } } t.codecs = codecs + return nil } -// Codecs returns list of supported codecs +// Codecs returns list of supported codecs. func (t *RTPTransceiver) getCodecs() []RTPCodecParameters { t.mu.RLock() defer t.mu.RUnlock() @@ -78,6 +81,7 @@ func (t *RTPTransceiver) getCodecs() []RTPCodecParameters { if codec.PayloadType == 0 { codec.PayloadType = c.PayloadType } + codec.RTCPFeedback = rtcpFeedbackIntersection(codec.RTCPFeedback, c.RTCPFeedback) filteredCodecs = append(filteredCodecs, codec) } } @@ -85,7 +89,7 @@ func (t *RTPTransceiver) getCodecs() []RTPCodecParameters { return filteredCodecs } -// Sender returns the RTPTransceiver's RTPSender if it has one +// Sender returns the RTPTransceiver's RTPSender if it has one. func (t *RTPTransceiver) Sender() *RTPSender { if v, ok := t.sender.Load().(*RTPSender); ok { return v @@ -94,9 +98,10 @@ func (t *RTPTransceiver) Sender() *RTPSender { return nil } -// SetSender sets the RTPSender and Track to current transceiver +// SetSender sets the RTPSender and Track to current transceiver. func (t *RTPTransceiver) SetSender(s *RTPSender, track TrackLocal) error { t.setSender(s) + return t.setSendingTrack(track) } @@ -112,7 +117,7 @@ func (t *RTPTransceiver) setSender(s *RTPSender) { t.sender.Store(s) } -// Receiver returns the RTPTransceiver's RTPReceiver if it has one +// Receiver returns the RTPTransceiver's RTPReceiver if it has one. func (t *RTPTransceiver) Receiver() *RTPReceiver { if v, ok := t.receiver.Load().(*RTPReceiver); ok { return v @@ -127,6 +132,7 @@ func (t *RTPTransceiver) SetMid(mid string) error { return fmt.Errorf("%w: %s to %s", errRTPTransceiverCannotChangeMid, currentMid, mid) } t.mid.Store(mid) + return nil } @@ -135,6 +141,7 @@ func (t *RTPTransceiver) Mid() string { if v, ok := t.mid.Load().(string); ok { return v } + return "" } @@ -143,15 +150,16 @@ func (t *RTPTransceiver) Kind() RTPCodecType { return t.kind } -// Direction returns the RTPTransceiver's current direction +// Direction returns the RTPTransceiver's current direction. func (t *RTPTransceiver) Direction() RTPTransceiverDirection { if direction, ok := t.direction.Load().(RTPTransceiverDirection); ok { return direction } + return RTPTransceiverDirection(0) } -// Stop irreversibly stops the RTPTransceiver +// Stop irreversibly stops the RTPTransceiver. func (t *RTPTransceiver) Stop() error { if sender := t.Sender(); sender != nil { if err := sender.Stop(); err != nil { @@ -166,6 +174,7 @@ func (t *RTPTransceiver) Stop() error { t.setDirection(RTPTransceiverDirectionInactive) t.setCurrentDirection(RTPTransceiverDirectionInactive) + return nil } @@ -193,10 +202,11 @@ func (t *RTPTransceiver) getCurrentDirection() RTPTransceiverDirection { if v, ok := t.currentDirection.Load().(RTPTransceiverDirection); ok { return v } - return RTPTransceiverDirection(Unknown) + + return RTPTransceiverDirectionUnknown } -func (t *RTPTransceiver) setSendingTrack(track TrackLocal) error { +func (t *RTPTransceiver) setSendingTrack(track TrackLocal) error { //nolint:cyclop if err := t.Sender().ReplaceTrack(track); err != nil { return err } @@ -222,6 +232,7 @@ func (t *RTPTransceiver) setSendingTrack(track TrackLocal) error { default: return errRTPTransceiverSetSendingInvalidState } + return nil } @@ -236,13 +247,21 @@ func findByMid(mid string, localTransceivers []*RTPTransceiver) (*RTPTransceiver } // Given a direction+type pluck a transceiver from the passed list -// if no entry satisfies the requested type+direction return a inactive Transceiver -func satisfyTypeAndDirection(remoteKind RTPCodecType, remoteDirection RTPTransceiverDirection, localTransceivers []*RTPTransceiver) (*RTPTransceiver, []*RTPTransceiver) { +// if no entry satisfies the requested type+direction return a inactive Transceiver. +func satisfyTypeAndDirection( + remoteKind RTPCodecType, + remoteDirection RTPTransceiverDirection, + localTransceivers []*RTPTransceiver, +) (*RTPTransceiver, []*RTPTransceiver) { // Get direction order from most preferred to least getPreferredDirections := func() []RTPTransceiverDirection { switch remoteDirection { case RTPTransceiverDirectionSendrecv: - return []RTPTransceiverDirection{RTPTransceiverDirectionRecvonly, RTPTransceiverDirectionSendrecv, RTPTransceiverDirectionSendonly} + return []RTPTransceiverDirection{ + RTPTransceiverDirectionRecvonly, + RTPTransceiverDirectionSendrecv, + RTPTransceiverDirectionSendonly, + } case RTPTransceiverDirectionSendonly: return []RTPTransceiverDirection{RTPTransceiverDirectionRecvonly, RTPTransceiverDirectionSendrecv} case RTPTransceiverDirectionRecvonly: @@ -265,15 +284,25 @@ func satisfyTypeAndDirection(remoteKind RTPCodecType, remoteDirection RTPTransce } // handleUnknownRTPPacket consumes a single RTP Packet and returns information that is helpful -// for demuxing and handling an unknown SSRC (usually for Simulcast) -func handleUnknownRTPPacket(buf []byte, midExtensionID, streamIDExtensionID, repairStreamIDExtensionID uint8, mid, rid, rsid *string) (payloadType PayloadType, err error) { +// for demuxing and handling an unknown SSRC (usually for Simulcast). +func handleUnknownRTPPacket( + buf []byte, + midExtensionID, + streamIDExtensionID, + repairStreamIDExtensionID uint8, + mid, rid, rsid *string, +) (payloadType PayloadType, paddingOnly bool, err error) { rp := &rtp.Packet{} if err = rp.Unmarshal(buf); err != nil { - return + return 0, false, err + } + + if rp.Padding && len(rp.Payload) == 0 { + paddingOnly = true } if !rp.Header.Extension { - return + return payloadType, paddingOnly, nil } payloadType = PayloadType(rp.PayloadType) @@ -289,5 +318,5 @@ func handleUnknownRTPPacket(buf []byte, midExtensionID, streamIDExtensionID, rep *rsid = string(payload) } - return + return payloadType, paddingOnly, nil } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/rtptransceiver_js.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/rtptransceiver_js.go similarity index 90% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/rtptransceiver_js.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/rtptransceiver_js.go index 43e129af3..14ff92a71 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/rtptransceiver_js.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/rtptransceiver_js.go @@ -16,6 +16,11 @@ type RTPTransceiver struct { underlying js.Value } +// JSValue returns the underlying RTCRtpTransceiver +func (r *RTPTransceiver) JSValue() js.Value { + return r.underlying +} + // Direction returns the RTPTransceiver's current direction func (r *RTPTransceiver) Direction() RTPTransceiverDirection { return NewRTPTransceiverDirection(r.underlying.Get("direction").String()) diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/rtptransceiverdirection.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/rtptransceiverdirection.go similarity index 86% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/rtptransceiverdirection.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/rtptransceiverdirection.go index 752cd5b9c..b360ce4d5 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/rtptransceiverdirection.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/rtptransceiverdirection.go @@ -7,9 +7,12 @@ package webrtc type RTPTransceiverDirection int const ( + // RTPTransceiverDirectionUnknown is the enum's zero-value. + RTPTransceiverDirectionUnknown RTPTransceiverDirection = iota + // RTPTransceiverDirectionSendrecv indicates the RTPSender will offer // to send RTP and the RTPReceiver will offer to receive RTP. - RTPTransceiverDirectionSendrecv RTPTransceiverDirection = iota + 1 + RTPTransceiverDirectionSendrecv // RTPTransceiverDirectionSendonly indicates the RTPSender will offer // to send RTP. @@ -45,7 +48,7 @@ func NewRTPTransceiverDirection(raw string) RTPTransceiverDirection { case rtpTransceiverDirectionInactiveStr: return RTPTransceiverDirectionInactive default: - return RTPTransceiverDirection(Unknown) + return RTPTransceiverDirectionUnknown } } @@ -64,7 +67,7 @@ func (t RTPTransceiverDirection) String() string { } } -// Revers indicate the opposite direction +// Revers indicate the opposite direction. func (t RTPTransceiverDirection) Revers() RTPTransceiverDirection { switch t { case RTPTransceiverDirectionSendonly: @@ -76,7 +79,10 @@ func (t RTPTransceiverDirection) Revers() RTPTransceiverDirection { } } -func haveRTPTransceiverDirectionIntersection(haystack []RTPTransceiverDirection, needle []RTPTransceiverDirection) bool { +func haveRTPTransceiverDirectionIntersection( + haystack []RTPTransceiverDirection, + needle []RTPTransceiverDirection, +) bool { for _, n := range needle { for _, h := range haystack { if n == h { @@ -84,5 +90,6 @@ func haveRTPTransceiverDirectionIntersection(haystack []RTPTransceiverDirection, } } } + return false } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/rtptransceiverinit.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/rtptransceiverinit.go similarity index 53% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/rtptransceiverinit.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/rtptransceiverinit.go index 3aac1dc14..e4dd8fe24 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/rtptransceiverinit.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/rtptransceiverinit.go @@ -3,13 +3,10 @@ package webrtc -// RTPTransceiverInit dictionary is used when calling the WebRTC function addTransceiver() to provide configuration options for the new transceiver. +// RTPTransceiverInit dictionary is used when calling the WebRTC function addTransceiver() +// to provide configuration options for the new transceiver. type RTPTransceiverInit struct { Direction RTPTransceiverDirection SendEncodings []RTPEncodingParameters // Streams []*Track } - -// RtpTransceiverInit is a temporary mapping while we fix case sensitivity -// Deprecated: Use RTPTransceiverInit instead -type RtpTransceiverInit = RTPTransceiverInit //nolint: stylecheck,golint diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/sctpcapabilities.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/sctpcapabilities.go similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/sctpcapabilities.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/sctpcapabilities.go diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/sctptransport.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/sctptransport.go similarity index 69% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/sctptransport.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/sctptransport.go index c96fd173f..33eb6e9b1 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/sctptransport.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/sctptransport.go @@ -9,14 +9,13 @@ package webrtc import ( "errors" "io" - "math" "sync" "time" "github.com/pion/datachannel" "github.com/pion/logging" "github.com/pion/sctp" - "github.com/pion/webrtc/v3/pkg/rtcerr" + "github.com/pion/webrtc/v4/pkg/rtcerr" ) const sctpMaxChannels = uint16(65535) @@ -34,10 +33,6 @@ type SCTPTransport struct { // so we need a dedicated field isStarted bool - // MaxMessageSize represents the maximum size of data that can be passed to - // DataChannel's send() method. - maxMessageSize float64 - // MaxChannels represents the maximum amount of DataChannel's that can // be used simultaneously. maxChannels *uint16 @@ -45,6 +40,7 @@ type SCTPTransport struct { // OnStateChange func() onErrorHandler func(error) + onCloseHandler func(error) sctpAssociation *sctp.Association onDataChannelHandler func(*DataChannel) @@ -52,6 +48,7 @@ type SCTPTransport struct { // DataChannels dataChannels []*DataChannel + dataChannelIDsUsed map[uint16]struct{} dataChannelsOpened uint32 dataChannelsRequested uint32 dataChannelsAccepted uint32 @@ -65,13 +62,13 @@ type SCTPTransport struct { // meant to be used together with the basic WebRTC API. func (api *API) NewSCTPTransport(dtls *DTLSTransport) *SCTPTransport { res := &SCTPTransport{ - dtlsTransport: dtls, - state: SCTPTransportStateConnecting, - api: api, - log: api.settingEngine.LoggerFactory.NewLogger("ortc"), + dtlsTransport: dtls, + state: SCTPTransportStateConnecting, + api: api, + log: api.settingEngine.LoggerFactory.NewLogger("ortc"), + dataChannelIDsUsed: make(map[uint16]struct{}), } - res.updateMessageSize() res.updateMaxChannels() return res @@ -87,29 +84,46 @@ func (r *SCTPTransport) Transport() *DTLSTransport { // GetCapabilities returns the SCTPCapabilities of the SCTPTransport. func (r *SCTPTransport) GetCapabilities() SCTPCapabilities { + var maxMessageSize uint32 + if a := r.association(); a != nil { + maxMessageSize = a.MaxMessageSize() + } + return SCTPCapabilities{ - MaxMessageSize: 0, + MaxMessageSize: maxMessageSize, } } // Start the SCTPTransport. Since both local and remote parties must mutually // create an SCTPTransport, SCTP SO (Simultaneous Open) is used to establish // a connection over SCTP. -func (r *SCTPTransport) Start(SCTPCapabilities) error { +func (r *SCTPTransport) Start(capabilities SCTPCapabilities) error { if r.isStarted { return nil } r.isStarted = true + maxMessageSize := capabilities.MaxMessageSize + if maxMessageSize == 0 { + maxMessageSize = sctpMaxMessageSizeUnsetValue + } + dtlsTransport := r.Transport() if dtlsTransport == nil || dtlsTransport.conn == nil { return errSCTPTransportDTLS } - sctpAssociation, err := sctp.Client(sctp.Config{ NetConn: dtlsTransport.conn, MaxReceiveBufferSize: r.api.settingEngine.sctp.maxReceiveBufferSize, + EnableZeroChecksum: r.api.settingEngine.sctp.enableZeroChecksum, LoggerFactory: r.api.settingEngine.LoggerFactory, + RTOMax: float64(r.api.settingEngine.sctp.rtoMax) / float64(time.Millisecond), + BlockWrite: r.api.settingEngine.detach.DataChannels && r.api.settingEngine.dataChannelBlockWrite, + MaxMessageSize: maxMessageSize, + MTU: outboundMTU, + MinCwnd: r.api.settingEngine.sctp.minCwnd, + FastRtxWnd: r.api.settingEngine.sctp.fastRtxWnd, + CwndCAStep: r.api.settingEngine.sctp.cwndCAStep, }) if err != nil { return err @@ -127,6 +141,7 @@ func (r *SCTPTransport) Start(SCTPCapabilities) error { err := d.open(r) if err != nil { r.log.Warnf("failed to open data channel: %s", err) + continue } openedDCCount++ @@ -137,22 +152,20 @@ func (r *SCTPTransport) Start(SCTPCapabilities) error { r.dataChannelsOpened += openedDCCount r.lock.Unlock() - go r.acceptDataChannels(sctpAssociation) + go r.acceptDataChannels(sctpAssociation, dataChannels) return nil } -// Stop stops the SCTPTransport +// Stop stops the SCTPTransport. func (r *SCTPTransport) Stop() error { r.lock.Lock() defer r.lock.Unlock() if r.sctpAssociation == nil { return nil } - err := r.sctpAssociation.Close() - if err != nil { - return err - } + + r.sctpAssociation.Abort("") r.sctpAssociation = nil r.state = SCTPTransportStateClosed @@ -160,10 +173,13 @@ func (r *SCTPTransport) Stop() error { return nil } -func (r *SCTPTransport) acceptDataChannels(a *sctp.Association) { - r.lock.RLock() - dataChannels := make([]*datachannel.DataChannel, 0, len(r.dataChannels)) - for _, dc := range r.dataChannels { +//nolint:cyclop +func (r *SCTPTransport) acceptDataChannels( + assoc *sctp.Association, + existingDataChannels []*DataChannel, +) { + dataChannels := make([]*datachannel.DataChannel, 0, len(existingDataChannels)) + for _, dc := range existingDataChannels { dc.mu.Lock() isNil := dc.dataChannel == nil dc.mu.Unlock() @@ -172,17 +188,20 @@ func (r *SCTPTransport) acceptDataChannels(a *sctp.Association) { } dataChannels = append(dataChannels, dc.dataChannel) } - r.lock.RUnlock() ACCEPT: for { - dc, err := datachannel.Accept(a, &datachannel.Config{ + dc, err := datachannel.Accept(assoc, &datachannel.Config{ LoggerFactory: r.api.settingEngine.LoggerFactory, }, dataChannels...) if err != nil { if !errors.Is(err, io.EOF) { r.log.Errorf("Failed to accept data channel: %v", err) r.onError(err) + r.onClose(err) + } else { + r.onClose(nil) } + return } for _, ch := range dataChannels { @@ -195,7 +214,7 @@ ACCEPT: maxRetransmits *uint16 maxPacketLifeTime *uint16 ) - val := uint16(dc.Config.ReliabilityParameter) + val := uint16(dc.Config.ReliabilityParameter) //nolint:gosec //G115 ordered := true switch dc.Config.ChannelType { @@ -229,9 +248,14 @@ ACCEPT: MaxRetransmits: maxRetransmits, }, r, r.api.settingEngine.LoggerFactory.NewLogger("ortc")) if err != nil { + // This data channel is invalid. Close it and log an error. + if err1 := dc.Close(); err1 != nil { + r.log.Errorf("Failed to close invalid data channel: %v", err1) + } r.log.Errorf("Failed to accept data channel: %v", err) r.onError(err) - return + // We've received a datachannel with invalid configuration. We can still receive other datachannels. + continue ACCEPT } <-r.onDataChannel(rtcDC) @@ -248,8 +272,7 @@ ACCEPT: } } -// OnError sets an event handler which is invoked when -// the SCTP connection error occurs. +// OnError sets an event handler which is invoked when the SCTP Association errors. func (r *SCTPTransport) OnError(f func(err error)) { r.lock.Lock() defer r.lock.Unlock() @@ -266,6 +289,23 @@ func (r *SCTPTransport) onError(err error) { } } +// OnClose sets an event handler which is invoked when the SCTP Association closes. +func (r *SCTPTransport) OnClose(f func(err error)) { + r.lock.Lock() + defer r.lock.Unlock() + r.onCloseHandler = f +} + +func (r *SCTPTransport) onClose(err error) { + r.lock.RLock() + handler := r.onCloseHandler + r.lock.RUnlock() + + if handler != nil { + go handler(err) + } +} + // OnDataChannel sets an event handler which is invoked when a data // channel message arrives from a remote peer. func (r *SCTPTransport) OnDataChannel(f func(*DataChannel)) { @@ -275,7 +315,7 @@ func (r *SCTPTransport) OnDataChannel(f func(*DataChannel)) { } // OnDataChannelOpened sets an event handler which is invoked when a data -// channel is opened +// channel is opened. func (r *SCTPTransport) OnDataChannelOpened(f func(*DataChannel)) { r.lock.Lock() defer r.lock.Unlock() @@ -286,12 +326,20 @@ func (r *SCTPTransport) onDataChannel(dc *DataChannel) (done chan struct{}) { r.lock.Lock() r.dataChannels = append(r.dataChannels, dc) r.dataChannelsAccepted++ + if dc.ID() != nil { + r.dataChannelIDsUsed[*dc.ID()] = struct{}{} + } else { + // This cannot happen, the constructor for this datachannel in the caller + // takes a pointer to the id. + r.log.Errorf("accepted data channel with no ID") + } handler := r.onDataChannelHandler r.lock.Unlock() done = make(chan struct{}) if handler == nil || dc == nil { close(done) + return } @@ -305,36 +353,6 @@ func (r *SCTPTransport) onDataChannel(dc *DataChannel) (done chan struct{}) { return } -func (r *SCTPTransport) updateMessageSize() { - r.lock.Lock() - defer r.lock.Unlock() - - var remoteMaxMessageSize float64 = 65536 // pion/webrtc#758 - var canSendSize float64 = 65536 // pion/webrtc#758 - - r.maxMessageSize = r.calcMessageSize(remoteMaxMessageSize, canSendSize) -} - -func (r *SCTPTransport) calcMessageSize(remoteMaxMessageSize, canSendSize float64) float64 { - switch { - case remoteMaxMessageSize == 0 && - canSendSize == 0: - return math.Inf(1) - - case remoteMaxMessageSize == 0: - return canSendSize - - case canSendSize == 0: - return remoteMaxMessageSize - - case canSendSize > remoteMaxMessageSize: - return remoteMaxMessageSize - - default: - return canSendSize - } -} - func (r *SCTPTransport) updateMaxChannels() { val := sctpMaxChannels r.maxChannels = &val @@ -352,19 +370,20 @@ func (r *SCTPTransport) MaxChannels() uint16 { return *r.maxChannels } -// State returns the current state of the SCTPTransport +// State returns the current state of the SCTPTransport. func (r *SCTPTransport) State() SCTPTransportState { r.lock.RLock() defer r.lock.RUnlock() + return r.state } func (r *SCTPTransport) collectStats(collector *statsReportCollector) { collector.Collecting() - stats := TransportStats{ + stats := SCTPTransportStats{ Timestamp: statsTimestampFrom(time.Now()), - Type: StatsTypeTransport, + Type: StatsTypeSCTPTransport, ID: "sctpTransport", } @@ -372,6 +391,10 @@ func (r *SCTPTransport) collectStats(collector *statsReportCollector) { if association != nil { stats.BytesSent = association.BytesSent() stats.BytesReceived = association.BytesReceived() + stats.SmoothedRoundTripTime = association.SRTT() * 0.001 // convert milliseconds to seconds + stats.CongestionWindow = association.CWND() + stats.ReceiverWindow = association.RWND() + stats.MTU = association.MTU() } collector.Collect(stats.ID, stats) @@ -383,26 +406,18 @@ func (r *SCTPTransport) generateAndSetDataChannelID(dtlsRole DTLSRole, idOut **u id++ } - max := r.MaxChannels() + maxVal := r.MaxChannels() r.lock.Lock() defer r.lock.Unlock() - // Create map of ids so we can compare without double-looping each time. - idsMap := make(map[uint16]struct{}, len(r.dataChannels)) - for _, dc := range r.dataChannels { - if dc.ID() == nil { - continue - } - - idsMap[*dc.ID()] = struct{}{} - } - - for ; id < max-1; id += 2 { - if _, ok := idsMap[id]; ok { + for ; id < maxVal-1; id += 2 { + if _, ok := r.dataChannelIDsUsed[id]; ok { continue } *idOut = &id + r.dataChannelIDsUsed[id] = struct{}{} + return nil } @@ -416,5 +431,17 @@ func (r *SCTPTransport) association() *sctp.Association { r.lock.RLock() association := r.sctpAssociation r.lock.RUnlock() + return association } + +// BufferedAmount returns total amount (in bytes) of currently buffered user data. +func (r *SCTPTransport) BufferedAmount() int { + r.lock.Lock() + defer r.lock.Unlock() + if r.sctpAssociation == nil { + return 0 + } + + return r.sctpAssociation.BufferedAmount() +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/sctptransport_js.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/sctptransport_js.go similarity index 84% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/sctptransport_js.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/sctptransport_js.go index 7ab6c3900..701b7f736 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/sctptransport_js.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/sctptransport_js.go @@ -14,6 +14,11 @@ type SCTPTransport struct { underlying js.Value } +// JSValue returns the underlying RTCSctpTransport +func (r *SCTPTransport) JSValue() js.Value { + return r.underlying +} + // Transport returns the DTLSTransport instance the SCTPTransport is sending over. func (r *SCTPTransport) Transport() *DTLSTransport { underlying := r.underlying.Get("transport") diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/sctptransportstate.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/sctptransportstate.go similarity index 90% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/sctptransportstate.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/sctptransportstate.go index 5dd51d6f5..1103305fc 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/sctptransportstate.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/sctptransportstate.go @@ -7,10 +7,13 @@ package webrtc type SCTPTransportState int const ( + // SCTPTransportStateUnknown is the enum's zero-value. + SCTPTransportStateUnknown SCTPTransportState = iota + // SCTPTransportStateConnecting indicates the SCTPTransport is in the // process of negotiating an association. This is the initial state of the // SCTPTransportState when an SCTPTransport is created. - SCTPTransportStateConnecting SCTPTransportState = iota + 1 + SCTPTransportStateConnecting // SCTPTransportStateConnected indicates the negotiation of an // association is completed. @@ -39,7 +42,7 @@ func newSCTPTransportState(raw string) SCTPTransportState { case sctpTransportStateClosedStr: return SCTPTransportStateClosed default: - return SCTPTransportState(Unknown) + return SCTPTransportStateUnknown } } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/sdp.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/sdp.go similarity index 53% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/sdp.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/sdp.go index a1c8daaba..fa10b6951 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/sdp.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/sdp.go @@ -15,13 +15,13 @@ import ( "strings" "sync/atomic" - "github.com/pion/ice/v2" + "github.com/pion/ice/v4" "github.com/pion/logging" "github.com/pion/sdp/v3" ) // trackDetails represents any media source that can be represented in a SDP -// This isn't keyed by SSRC because it also needs to support rid based sources +// This isn't keyed by SSRC because it also needs to support rid based sources. type trackDetails struct { mid string kind RTPCodecType @@ -40,6 +40,7 @@ func trackDetailsForSSRC(trackDetails []trackDetails, ssrc SSRC) *trackDetails { } } } + return nil } @@ -55,6 +56,7 @@ func trackDetailsForRID(trackDetails []trackDetails, mid, rid string) *trackDeta } } } + return nil } @@ -80,12 +82,17 @@ func filterTrackWithSSRC(incomingTracks []trackDetails, ssrc SSRC) []trackDetail } // extract all trackDetails from an SDP. -func trackDetailsFromSDP(log logging.LeveledLogger, s *sdp.SessionDescription) (incomingTracks []trackDetails) { // nolint:gocognit +// +//nolint:gocognit,gocyclo,cyclop +func trackDetailsFromSDP( + log logging.LeveledLogger, + s *sdp.SessionDescription, +) (incomingTracks []trackDetails) { for _, media := range s.MediaDescriptions { tracksInMediaSection := []trackDetails{} rtxRepairFlows := map[uint64]uint64{} - // Plan B can have multiple tracks in a signle media section + // Plan B can have multiple tracks in a single media section streamID := "" trackID := "" @@ -110,7 +117,7 @@ func trackDetailsFromSDP(log logging.LeveledLogger, s *sdp.SessionDescription) ( switch attr.Key { case sdp.AttrKeySSRCGroup: split := strings.Split(attr.Value, " ") - if split[0] == sdp.SemanticTokenFlowIdentification { + if split[0] == sdp.SemanticTokenFlowIdentification { //nolint:nestif // Add rtx ssrcs to blacklist, to avoid adding them as tracks // Essentially lines like `a=ssrc-group:FID 2231627014 632943048` are processed by this section // as this declares that the second SSRC (632943048) is a rtx repair flow (RFC4588) for the first @@ -119,15 +126,26 @@ func trackDetailsFromSDP(log logging.LeveledLogger, s *sdp.SessionDescription) ( baseSsrc, err := strconv.ParseUint(split[1], 10, 32) if err != nil { log.Warnf("Failed to parse SSRC: %v", err) + continue } rtxRepairFlow, err := strconv.ParseUint(split[2], 10, 32) if err != nil { log.Warnf("Failed to parse SSRC: %v", err) + continue } rtxRepairFlows[rtxRepairFlow] = baseSsrc - tracksInMediaSection = filterTrackWithSSRC(tracksInMediaSection, SSRC(rtxRepairFlow)) // Remove if rtx was added as track before + tracksInMediaSection = filterTrackWithSSRC( + tracksInMediaSection, + SSRC(rtxRepairFlow), + ) // Remove if rtx was added as track before + for i := range tracksInMediaSection { + if tracksInMediaSection[i].ssrcs[0] == SSRC(baseSsrc) { + repairSsrc := SSRC(rtxRepairFlow) + tracksInMediaSection[i].repairSsrc = &repairSsrc + } + } } } @@ -146,6 +164,7 @@ func trackDetailsFromSDP(log logging.LeveledLogger, s *sdp.SessionDescription) ( ssrc, err := strconv.ParseUint(split[0], 10, 32) if err != nil { log.Warnf("Failed to parse SSRC: %v", err) + continue } @@ -177,7 +196,7 @@ func trackDetailsFromSDP(log logging.LeveledLogger, s *sdp.SessionDescription) ( for r, baseSsrc := range rtxRepairFlows { if baseSsrc == ssrc { - repairSsrc := SSRC(r) + repairSsrc := SSRC(r) //nolint:gosec // G115 trackDetails.repairSsrc = &repairSsrc } } @@ -196,8 +215,8 @@ func trackDetailsFromSDP(log logging.LeveledLogger, s *sdp.SessionDescription) ( id: trackID, rids: []string{}, } - for rid := range rids { - simulcastTrack.rids = append(simulcastTrack.rids, rid) + for _, rid := range rids { + simulcastTrack.rids = append(simulcastTrack.rids, rid.id) } tracksInMediaSection = []trackDetails{simulcastTrack} @@ -209,41 +228,68 @@ func trackDetailsFromSDP(log logging.LeveledLogger, s *sdp.SessionDescription) ( return incomingTracks } -func trackDetailsToRTPReceiveParameters(t *trackDetails) RTPReceiveParameters { - encodingSize := len(t.ssrcs) - if len(t.rids) >= encodingSize { - encodingSize = len(t.rids) +func trackDetailsToRTPReceiveParameters(trackDetails *trackDetails) RTPReceiveParameters { + encodingSize := len(trackDetails.ssrcs) + if len(trackDetails.rids) >= encodingSize { + encodingSize = len(trackDetails.rids) } encodings := make([]RTPDecodingParameters, encodingSize) for i := range encodings { - if len(t.rids) > i { - encodings[i].RID = t.rids[i] + if len(trackDetails.rids) > i { + encodings[i].RID = trackDetails.rids[i] } - if len(t.ssrcs) > i { - encodings[i].SSRC = t.ssrcs[i] + if len(trackDetails.ssrcs) > i { + encodings[i].SSRC = trackDetails.ssrcs[i] } - if t.repairSsrc != nil { - encodings[i].RTX.SSRC = *t.repairSsrc + if trackDetails.repairSsrc != nil { + encodings[i].RTX.SSRC = *trackDetails.repairSsrc } } return RTPReceiveParameters{Encodings: encodings} } -func getRids(media *sdp.MediaDescription) map[string]string { - rids := map[string]string{} +func getRids(media *sdp.MediaDescription) []*simulcastRid { + rids := []*simulcastRid{} + var simulcastAttr string for _, attr := range media.Attributes { if attr.Key == sdpAttributeRid { split := strings.Split(attr.Value, " ") - rids[split[0]] = attr.Value + rids = append(rids, &simulcastRid{id: split[0], attrValue: attr.Value}) + } else if attr.Key == sdpAttributeSimulcast { + simulcastAttr = attr.Value } } + // process paused stream like "a=simulcast:send 1;~2;~3" + if simulcastAttr != "" { + if space := strings.Index(simulcastAttr, " "); space > 0 { + simulcastAttr = simulcastAttr[space+1:] + } + ridStates := strings.Split(simulcastAttr, ";") + for _, ridState := range ridStates { + if ridState[:1] == "~" { + ridID := ridState[1:] + for _, rid := range rids { + if rid.id == ridID { + rid.paused = true + + break + } + } + } + } + } + return rids } -func addCandidatesToMediaDescriptions(candidates []ICECandidate, m *sdp.MediaDescription, iceGatheringState ICEGatheringState) error { +func addCandidatesToMediaDescriptions( + candidates []ICECandidate, + mediaDescr *sdp.MediaDescription, + iceGatheringState ICEGatheringState, +) error { appendCandidateIfNew := func(c ice.Candidate, attributes []sdp.Attribute) { marshaled := c.Marshal() for _, a := range attributes { @@ -252,36 +298,47 @@ func addCandidatesToMediaDescriptions(candidates []ICECandidate, m *sdp.MediaDes } } - m.WithValueAttribute("candidate", marshaled) + mediaDescr.WithValueAttribute("candidate", marshaled) } for _, c := range candidates { - candidate, err := c.toICE() + candidate, err := c.ToICE() if err != nil { return err } candidate.SetComponent(1) - appendCandidateIfNew(candidate, m.Attributes) + appendCandidateIfNew(candidate, mediaDescr.Attributes) candidate.SetComponent(2) - appendCandidateIfNew(candidate, m.Attributes) + appendCandidateIfNew(candidate, mediaDescr.Attributes) } if iceGatheringState != ICEGatheringStateComplete { return nil } - for _, a := range m.Attributes { + for _, a := range mediaDescr.Attributes { if a.Key == "end-of-candidates" { return nil } } - m.WithPropertyAttribute("end-of-candidates") + mediaDescr.WithPropertyAttribute("end-of-candidates") + return nil } -func addDataMediaSection(d *sdp.SessionDescription, shouldAddCandidates bool, dtlsFingerprints []DTLSFingerprint, midValue string, iceParams ICEParameters, candidates []ICECandidate, dtlsRole sdp.ConnectionRole, iceGatheringState ICEGatheringState) error { +func addDataMediaSection( + descr *sdp.SessionDescription, + shouldAddCandidates bool, + dtlsFingerprints []DTLSFingerprint, + midValue string, + iceParams ICEParameters, + candidates []ICECandidate, + dtlsRole sdp.ConnectionRole, + iceGatheringState ICEGatheringState, + sctpMaxMessageSize uint32, +) error { media := (&sdp.MediaDescription{ MediaName: sdp.MediaName{ Media: mediaSectionApplication, @@ -301,6 +358,7 @@ func addDataMediaSection(d *sdp.SessionDescription, shouldAddCandidates bool, dt WithValueAttribute(sdp.AttrKeyMID, midValue). WithPropertyAttribute(RTPTransceiverDirectionSendrecv.String()). WithPropertyAttribute("sctp-port:5000"). + WithValueAttribute("max-message-size", fmt.Sprintf("%d", sctpMaxMessageSize)). WithICECredentials(iceParams.UsernameFragment, iceParams.Password) for _, f := range dtlsFingerprints { @@ -313,11 +371,16 @@ func addDataMediaSection(d *sdp.SessionDescription, shouldAddCandidates bool, dt } } - d.WithMedia(media) + descr.WithMedia(media) + return nil } -func populateLocalCandidates(sessionDescription *SessionDescription, i *ICEGatherer, iceGatheringState ICEGatheringState) *SessionDescription { +func populateLocalCandidates( + sessionDescription *SessionDescription, + i *ICEGatherer, + iceGatheringState ICEGatheringState, +) *SessionDescription { if sessionDescription == nil || i == nil { return sessionDescription } @@ -329,8 +392,8 @@ func populateLocalCandidates(sessionDescription *SessionDescription, i *ICEGathe parsed := sessionDescription.parsed if len(parsed.MediaDescriptions) > 0 { - m := parsed.MediaDescriptions[0] - if err = addCandidatesToMediaDescriptions(candidates, m, iceGatheringState); err != nil { + mediaDescr := parsed.MediaDescriptions[0] + if err = addCandidatesToMediaDescriptions(candidates, mediaDescr, iceGatheringState); err != nil { return sessionDescription } } @@ -347,6 +410,7 @@ func populateLocalCandidates(sessionDescription *SessionDescription, i *ICEGathe } } +//nolint:gocognit,cyclop func addSenderSDP( mediaSection mediaSection, isPlanB bool, @@ -365,8 +429,38 @@ func addSenderSDP( sendParameters := sender.GetParameters() for _, encoding := range sendParameters.Encodings { - media = media.WithMediaSource(uint32(encoding.SSRC), track.StreamID() /* cname */, track.StreamID() /* streamLabel */, track.ID()) + if encoding.RTX.SSRC != 0 { + media = media.WithValueAttribute("ssrc-group", fmt.Sprintf("FID %d %d", encoding.SSRC, encoding.RTX.SSRC)) + } + if encoding.FEC.SSRC != 0 { + media = media.WithValueAttribute("ssrc-group", fmt.Sprintf("FEC-FR %d %d", encoding.SSRC, encoding.FEC.SSRC)) + } + + media = media.WithMediaSource( + uint32(encoding.SSRC), + track.StreamID(), /* cname */ + track.StreamID(), /* streamLabel */ + track.ID(), + ) + if !isPlanB { + if encoding.RTX.SSRC != 0 { + media = media.WithMediaSource( + uint32(encoding.RTX.SSRC), + track.StreamID(), /* cname */ + track.StreamID(), /* streamLabel */ + track.ID(), + ) + } + if encoding.FEC.SSRC != 0 { + media = media.WithMediaSource( + uint32(encoding.FEC.SSRC), + track.StreamID(), /* cname */ + track.StreamID(), /* streamLabel */ + track.ID(), + ) + } + media = media.WithPropertyAttribute("msid:" + track.StreamID() + " " + track.ID()) } } @@ -379,7 +473,7 @@ func addSenderSDP( sendRids = append(sendRids, encoding.RID) } // Simulcast - media.WithValueAttribute("simulcast", "send "+strings.Join(sendRids, ";")) + media.WithValueAttribute(sdpAttributeSimulcast, "send "+strings.Join(sendRids, ";")) } if !isPlanB { @@ -388,8 +482,9 @@ func addSenderSDP( } } +//nolint:cyclop func addTransceiverSDP( - d *sdp.SessionDescription, + descr *sdp.SessionDescription, isPlanB bool, shouldAddCandidates bool, dtlsFingerprints []DTLSFingerprint, @@ -406,15 +501,15 @@ func addTransceiverSDP( return false, errSDPZeroTransceivers } // Use the first transceiver to generate the section attributes - t := transceivers[0] - media := sdp.NewJSEPMediaDescription(t.kind.String(), []string{}). + transceiver := transceivers[0] + media := sdp.NewJSEPMediaDescription(transceiver.kind.String(), []string{}). WithValueAttribute(sdp.AttrKeyConnectionSetup, dtlsRole.String()). WithValueAttribute(sdp.AttrKeyMID, midValue). WithICECredentials(iceParams.UsernameFragment, iceParams.Password). WithPropertyAttribute(sdp.AttrKeyRTCPMux). WithPropertyAttribute(sdp.AttrKeyRTCPRsize) - codecs := t.getCodecs() + codecs := transceiver.getCodecs() for _, codec := range codecs { name := strings.TrimPrefix(codec.MimeType, "audio/") name = strings.TrimPrefix(name, "video/") @@ -426,18 +521,20 @@ func addTransceiverSDP( } if len(codecs) == 0 { // If we are sender and we have no codecs throw an error early - if t.Sender() != nil { + if transceiver.Sender() != nil { return false, ErrSenderWithNoCodecs } // Explicitly reject track if we don't have the codec // We need to include connection information even if we're rejecting a track, otherwise Firefox will fail to // parse the SDP with an error like: - // SIPCC Failed to parse SDP: SDP Parse Error on line 50: c= connection line not specified for every media level, validation failed. - // In addition this makes our SDP compliant with RFC 4566 Section 5.7: https://datatracker.ietf.org/doc/html/rfc4566#section-5.7 - d.WithMedia(&sdp.MediaDescription{ + // SIPCC Failed to parse SDP: SDP Parse Error on line 50: c= connection line not specified for every media level, + // validation failed. + // In addition this makes our SDP compliant with RFC 4566 Section 5.7: + // https://datatracker.ietf.org/doc/html/rfc4566#section-5.7 + descr.WithMedia(&sdp.MediaDescription{ MediaName: sdp.MediaName{ - Media: t.kind.String(), + Media: transceiver.kind.String(), Port: sdp.RangedPort{Value: 0}, Protos: []string{"UDP", "TLS", "RTP", "SAVPF"}, Formats: []string{"0"}, @@ -450,19 +547,25 @@ func addTransceiverSDP( }, }, }) + return false, nil } directions := []RTPTransceiverDirection{} - if t.Sender() != nil { + if transceiver.Sender() != nil { directions = append(directions, RTPTransceiverDirectionSendonly) } - if t.Receiver() != nil { + if transceiver.Receiver() != nil { directions = append(directions, RTPTransceiverDirectionRecvonly) } - parameters := mediaEngine.getRTPParametersByKind(t.kind, directions) + parameters := mediaEngine.getRTPParametersByKind(transceiver.kind, directions) for _, rtpExtension := range parameters.HeaderExtensions { + if mediaSection.matchExtensions != nil { + if _, enabled := mediaSection.matchExtensions[rtpExtension.URI]; !enabled { + continue + } + } extURL, err := url.Parse(rtpExtension.URI) if err != nil { return false, err @@ -470,20 +573,24 @@ func addTransceiverSDP( media.WithExtMap(sdp.ExtMap{Value: rtpExtension.ID, URI: extURL}) } - if len(mediaSection.ridMap) > 0 { - recvRids := make([]string, 0, len(mediaSection.ridMap)) + if len(mediaSection.rids) > 0 { + recvRids := make([]string, 0, len(mediaSection.rids)) - for rid := range mediaSection.ridMap { - media.WithValueAttribute(sdpAttributeRid, rid+" recv") - recvRids = append(recvRids, rid) + for _, rid := range mediaSection.rids { + ridID := rid.id + media.WithValueAttribute(sdpAttributeRid, ridID+" recv") + if rid.paused { + ridID = "~" + ridID + } + recvRids = append(recvRids, ridID) } // Simulcast - media.WithValueAttribute("simulcast", "recv "+strings.Join(recvRids, ";")) + media.WithValueAttribute(sdpAttributeSimulcast, "recv "+strings.Join(recvRids, ";")) } addSenderSDP(mediaSection, isPlanB, media) - media = media.WithPropertyAttribute(t.Direction().String()) + media = media.WithPropertyAttribute(transceiver.Direction().String()) for _, fingerprint := range dtlsFingerprints { media = media.WithFingerprint(fingerprint.Algorithm, strings.ToUpper(fingerprint.Value)) @@ -495,20 +602,63 @@ func addTransceiverSDP( } } - d.WithMedia(media) + descr.WithMedia(media) return true, nil } -type mediaSection struct { - id string - transceivers []*RTPTransceiver - data bool - ridMap map[string]string +type simulcastRid struct { + id string + attrValue string + paused bool } -// populateSDP serializes a PeerConnections state into an SDP -func populateSDP(d *sdp.SessionDescription, isPlanB bool, dtlsFingerprints []DTLSFingerprint, mediaDescriptionFingerprint bool, isICELite bool, isExtmapAllowMixed bool, mediaEngine *MediaEngine, connectionRole sdp.ConnectionRole, candidates []ICECandidate, iceParams ICEParameters, mediaSections []mediaSection, iceGatheringState ICEGatheringState) (*sdp.SessionDescription, error) { +type mediaSection struct { + id string + transceivers []*RTPTransceiver + data bool + matchExtensions map[string]int + rids []*simulcastRid +} + +func bundleMatchFromRemote(matchBundleGroup *string) func(mid string) bool { + if matchBundleGroup == nil { + return func(string) bool { + return true + } + } + bundleTags := strings.Split(*matchBundleGroup, " ") + + return func(midValue string) bool { + for _, tag := range bundleTags { + if tag == midValue { + return true + } + } + + return false + } +} + +// populateSDP serializes a PeerConnections state into an SDP. +// +//nolint:cyclop +func populateSDP( + descr *sdp.SessionDescription, + isPlanB bool, + dtlsFingerprints []DTLSFingerprint, + mediaDescriptionFingerprint bool, + isICELite bool, + isExtmapAllowMixed bool, + mediaEngine *MediaEngine, + connectionRole sdp.ConnectionRole, + candidates []ICECandidate, + iceParams ICEParameters, + mediaSections []mediaSection, + iceGatheringState ICEGatheringState, + matchBundleGroup *string, + sctpMaxMessageSize uint32, +) (*sdp.SessionDescription, error) { var err error mediaDtlsFingerprints := []DTLSFingerprint{} @@ -518,52 +668,84 @@ func populateSDP(d *sdp.SessionDescription, isPlanB bool, dtlsFingerprints []DTL bundleValue := "BUNDLE" bundleCount := 0 + + bundleMatch := bundleMatchFromRemote(matchBundleGroup) appendBundle := func(midValue string) { bundleValue += " " + midValue bundleCount++ } - for i, m := range mediaSections { - if m.data && len(m.transceivers) != 0 { + for i, section := range mediaSections { + if section.data && len(section.transceivers) != 0 { return nil, errSDPMediaSectionMediaDataChanInvalid - } else if !isPlanB && len(m.transceivers) > 1 { + } else if !isPlanB && len(section.transceivers) > 1 { return nil, errSDPMediaSectionMultipleTrackInvalid } shouldAddID := true shouldAddCandidates := i == 0 - if m.data { - if err = addDataMediaSection(d, shouldAddCandidates, mediaDtlsFingerprints, m.id, iceParams, candidates, connectionRole, iceGatheringState); err != nil { + if section.data { + if err = addDataMediaSection( + descr, + shouldAddCandidates, + mediaDtlsFingerprints, + section.id, + iceParams, + candidates, + connectionRole, + iceGatheringState, + sctpMaxMessageSize, + ); err != nil { return nil, err } } else { - shouldAddID, err = addTransceiverSDP(d, isPlanB, shouldAddCandidates, mediaDtlsFingerprints, mediaEngine, m.id, iceParams, candidates, connectionRole, iceGatheringState, m) + shouldAddID, err = addTransceiverSDP( + descr, + isPlanB, + shouldAddCandidates, + mediaDtlsFingerprints, + mediaEngine, + section.id, + iceParams, + candidates, + connectionRole, + iceGatheringState, + section, + ) if err != nil { return nil, err } } if shouldAddID { - appendBundle(m.id) + if bundleMatch(section.id) { + appendBundle(section.id) + } else { + descr.MediaDescriptions[len(descr.MediaDescriptions)-1].MediaName.Port = sdp.RangedPort{Value: 0} + } } } if !mediaDescriptionFingerprint { for _, fingerprint := range dtlsFingerprints { - d.WithFingerprint(fingerprint.Algorithm, strings.ToUpper(fingerprint.Value)) + descr.WithFingerprint(fingerprint.Algorithm, strings.ToUpper(fingerprint.Value)) } } if isICELite { // RFC 5245 S15.3 - d = d.WithValueAttribute(sdp.AttrKeyICELite, "") + descr = descr.WithValueAttribute(sdp.AttrKeyICELite, "") } if isExtmapAllowMixed { - d = d.WithPropertyAttribute(sdp.AttrKeyExtMapAllowMixed) + descr = descr.WithPropertyAttribute(sdp.AttrKeyExtMapAllowMixed) } - return d.WithValueAttribute(sdp.AttrKeyGroup, bundleValue), nil + if bundleCount > 0 { + descr = descr.WithValueAttribute(sdp.AttrKeyGroup, bundleValue) + } + + return descr, nil } func getMidValue(media *sdp.MediaDescription) string { @@ -572,10 +754,11 @@ func getMidValue(media *sdp.MediaDescription) string { return attr.Value } } + return "" } -// SessionDescription contains a MediaSection with Multiple SSRCs, it is Plan-B +// SessionDescription contains a MediaSection with Multiple SSRCs, it is Plan-B. func descriptionIsPlanB(desc *SessionDescription, log logging.LeveledLogger) bool { if desc == nil || desc.parsed == nil { return false @@ -596,7 +779,7 @@ func descriptionIsPlanB(desc *SessionDescription, log logging.LeveledLogger) boo // SessionDescription contains a MediaSection with name `audio`, `video` or `data` // If only one SSRC is set we can't know if it is Plan-B or Unified. If users have -// set fallback mode assume it is Plan-B +// set fallback mode assume it is Plan-B. func descriptionPossiblyPlanB(desc *SessionDescription) bool { if desc == nil || desc.parsed == nil { return false @@ -608,118 +791,208 @@ func descriptionPossiblyPlanB(desc *SessionDescription) bool { return true } } + return false } func getPeerDirection(media *sdp.MediaDescription) RTPTransceiverDirection { for _, a := range media.Attributes { - if direction := NewRTPTransceiverDirection(a.Key); direction != RTPTransceiverDirection(Unknown) { + if direction := NewRTPTransceiverDirection(a.Key); direction != RTPTransceiverDirectionUnknown { return direction } } - return RTPTransceiverDirection(Unknown) + + return RTPTransceiverDirectionUnknown } -func extractFingerprint(desc *sdp.SessionDescription) (string, string, error) { - fingerprints := []string{} +func extractBundleID(desc *sdp.SessionDescription) string { + groupAttribute, _ := desc.Attribute(sdp.AttrKeyGroup) - if fingerprint, haveFingerprint := desc.Attribute("fingerprint"); haveFingerprint { - fingerprints = append(fingerprints, fingerprint) + isBundled := strings.Contains(groupAttribute, "BUNDLE") + + if !isBundled { + return "" } - for _, m := range desc.MediaDescriptions { - if fingerprint, haveFingerprint := m.Attribute("fingerprint"); haveFingerprint { - fingerprints = append(fingerprints, fingerprint) - } + bundleIDs := strings.Split(groupAttribute, " ") + + if len(bundleIDs) < 2 { + return "" } - if len(fingerprints) < 1 { - return "", "", ErrSessionDescriptionNoFingerprint - } - - for _, m := range fingerprints { - if m != fingerprints[0] { - return "", "", ErrSessionDescriptionConflictingFingerprints - } - } - - parts := strings.Split(fingerprints[0], " ") - if len(parts) != 2 { - return "", "", ErrSessionDescriptionInvalidFingerprint - } - return parts[1], parts[0], nil + return bundleIDs[1] } -func extractICEDetails(desc *sdp.SessionDescription, log logging.LeveledLogger) (string, string, []ICECandidate, error) { // nolint:gocognit - candidates := []ICECandidate{} - remotePwds := []string{} - remoteUfrags := []string{} +func extractFingerprint(desc *sdp.SessionDescription) (string, string, error) { //nolint:gocognit,cyclop + fingerprint := "" - if ufrag, haveUfrag := desc.Attribute("ice-ufrag"); haveUfrag { - remoteUfrags = append(remoteUfrags, ufrag) - } - if pwd, havePwd := desc.Attribute("ice-pwd"); havePwd { - remotePwds = append(remotePwds, pwd) + // Fingerprint on session level has highest priority + if sessionFingerprint, haveFingerprint := desc.Attribute("fingerprint"); haveFingerprint { + fingerprint = sessionFingerprint } - for _, m := range desc.MediaDescriptions { - if ufrag, haveUfrag := m.Attribute("ice-ufrag"); haveUfrag { - remoteUfrags = append(remoteUfrags, ufrag) - } - if pwd, havePwd := m.Attribute("ice-pwd"); havePwd { - remotePwds = append(remotePwds, pwd) - } - - for _, a := range m.Attributes { - if a.IsICECandidate() { - c, err := ice.UnmarshalCandidate(a.Value) - if err != nil { - if errors.Is(err, ice.ErrUnknownCandidateTyp) || errors.Is(err, ice.ErrDetermineNetworkType) { - log.Warnf("Discarding remote candidate: %s", err) - continue + if fingerprint == "" { //nolint:nestif + bundleID := extractBundleID(desc) + if bundleID != "" { + // Locate the fingerprint of the bundled media section + for _, mediaDescr := range desc.MediaDescriptions { + if mid, haveMid := mediaDescr.Attribute("mid"); haveMid { + if mid == bundleID && fingerprint == "" { + if mediaFingerprint, haveFingerprint := mediaDescr.Attribute("fingerprint"); haveFingerprint { + fingerprint = mediaFingerprint + } } - return "", "", nil, err } - - candidate, err := newICECandidateFromICE(c) - if err != nil { - return "", "", nil, err + } + } else { + // Take the fingerprint from the first media section which has one. + // Note: According to Bundle spec each media section would have it's own transport + // with it's own cert and fingerprint each, so we would need to return a list. + for _, mediaDescr := range desc.MediaDescriptions { + mediaFingerprint, haveFingerprint := mediaDescr.Attribute("fingerprint") + if haveFingerprint && fingerprint == "" { + fingerprint = mediaFingerprint } - - candidates = append(candidates, candidate) } } } - if len(remoteUfrags) == 0 { - return "", "", nil, ErrSessionDescriptionMissingIceUfrag - } else if len(remotePwds) == 0 { - return "", "", nil, ErrSessionDescriptionMissingIcePwd + if fingerprint == "" { + return "", "", ErrSessionDescriptionNoFingerprint } - for _, m := range remoteUfrags { - if m != remoteUfrags[0] { - return "", "", nil, ErrSessionDescriptionConflictingIceUfrag - } + parts := strings.Split(fingerprint, " ") + if len(parts) != 2 { + return "", "", ErrSessionDescriptionInvalidFingerprint } - for _, m := range remotePwds { - if m != remotePwds[0] { - return "", "", nil, ErrSessionDescriptionConflictingIcePwd - } - } - - return remoteUfrags[0], remotePwds[0], candidates, nil + return parts[1], parts[0], nil } -func haveApplicationMediaSection(desc *sdp.SessionDescription) bool { - for _, m := range desc.MediaDescriptions { - if m.MediaName.Media == mediaSectionApplication { - return true +// identifiedMediaDescription contains a MediaDescription with sdpMid and sdpMLineIndex. +type identifiedMediaDescription struct { + MediaDescription *sdp.MediaDescription + SDPMid string + SDPMLineIndex uint16 +} + +func extractICEDetailsFromMedia( + media *identifiedMediaDescription, + log logging.LeveledLogger, +) (string, string, []ICECandidate, error) { + remoteUfrag := "" + remotePwd := "" + candidates := []ICECandidate{} + descr := media.MediaDescription + + if ufrag, haveUfrag := descr.Attribute("ice-ufrag"); haveUfrag { + remoteUfrag = ufrag + } + if pwd, havePwd := descr.Attribute("ice-pwd"); havePwd { + remotePwd = pwd + } + for _, a := range descr.Attributes { + if a.IsICECandidate() { + c, err := ice.UnmarshalCandidate(a.Value) + if err != nil { + if errors.Is(err, ice.ErrUnknownCandidateTyp) || errors.Is(err, ice.ErrDetermineNetworkType) { + log.Warnf("Discarding remote candidate: %s", err) + + continue + } + + return "", "", nil, err + } + + candidate, err := newICECandidateFromICE(c, media.SDPMid, media.SDPMLineIndex) + if err != nil { + return "", "", nil, err + } + + candidates = append(candidates, candidate) } } - return false + return remoteUfrag, remotePwd, candidates, nil +} + +type sdpICEDetails struct { + Ufrag string + Password string + Candidates []ICECandidate +} + +func extractICEDetails( + desc *sdp.SessionDescription, + log logging.LeveledLogger, +) (*sdpICEDetails, error) { // nolint:gocognit + details := &sdpICEDetails{ + Candidates: []ICECandidate{}, + } + + // Ufrag and Pw are allow at session level and thus have highest prio + if ufrag, haveUfrag := desc.Attribute("ice-ufrag"); haveUfrag { + details.Ufrag = ufrag + } + if pwd, havePwd := desc.Attribute("ice-pwd"); havePwd { + details.Password = pwd + } + + mediaDescr, ok := selectCandidateMediaSection(desc) + if ok { + ufrag, pwd, candidates, err := extractICEDetailsFromMedia(mediaDescr, log) + if err != nil { + return nil, err + } + + if details.Ufrag == "" && ufrag != "" { + details.Ufrag = ufrag + details.Password = pwd + } + + details.Candidates = candidates + } + + if details.Ufrag == "" { + return nil, ErrSessionDescriptionMissingIceUfrag + } else if details.Password == "" { + return nil, ErrSessionDescriptionMissingIcePwd + } + + return details, nil +} + +// Select the first media section or the first bundle section +// Currently Pion uses the first media section to gather candidates. +// https://github.com/pion/webrtc/pull/2950 +func selectCandidateMediaSection(sessionDescription *sdp.SessionDescription) ( + descr *identifiedMediaDescription, + ok bool, +) { + bundleID := extractBundleID(sessionDescription) + + for mLineIndex, mediaDescr := range sessionDescription.MediaDescriptions { + mid := getMidValue(mediaDescr) + // If bundled, only take ICE detail from bundle master section + if bundleID != "" { + if mid == bundleID { + return &identifiedMediaDescription{ + MediaDescription: mediaDescr, + SDPMid: mid, + SDPMLineIndex: uint16(mLineIndex), //nolint:gosec // G115 + }, true + } + } else { + // For not-bundled, take ICE details from the first media section + return &identifiedMediaDescription{ + MediaDescription: mediaDescr, + SDPMid: mid, + SDPMLineIndex: uint16(mLineIndex), //nolint:gosec // G115 + }, true + } + } + + return nil, false } func getByMid(searchMid string, desc *SessionDescription) *sdp.MediaDescription { @@ -728,25 +1001,27 @@ func getByMid(searchMid string, desc *SessionDescription) *sdp.MediaDescription return m } } + return nil } -// haveDataChannel return MediaDescription with MediaName equal application +// haveDataChannel return MediaDescription with MediaName equal application. func haveDataChannel(desc *SessionDescription) *sdp.MediaDescription { for _, d := range desc.parsed.MediaDescriptions { if d.MediaName.Media == mediaSectionApplication { return d } } + return nil } -func codecsFromMediaDescription(m *sdp.MediaDescription) (out []RTPCodecParameters, err error) { +func codecsFromMediaDescription(mediaDescr *sdp.MediaDescription) (out []RTPCodecParameters, err error) { s := &sdp.SessionDescription{ - MediaDescriptions: []*sdp.MediaDescription{m}, + MediaDescriptions: []*sdp.MediaDescription{mediaDescr}, } - for _, payloadStr := range m.MediaName.Formats { + for _, payloadStr := range mediaDescr.MediaName.Formats { payloadType, err := strconv.ParseUint(payloadStr, 10, 8) if err != nil { return nil, err @@ -757,6 +1032,7 @@ func codecsFromMediaDescription(m *sdp.MediaDescription) (out []RTPCodecParamete if payloadType == 0 { continue } + return nil, err } @@ -778,8 +1054,14 @@ func codecsFromMediaDescription(m *sdp.MediaDescription) (out []RTPCodecParamete } out = append(out, RTPCodecParameters{ - RTPCodecCapability: RTPCodecCapability{m.MediaName.Media + "/" + codec.Name, codec.ClockRate, channels, codec.Fmtp, feedback}, - PayloadType: PayloadType(payloadType), + RTPCodecCapability: RTPCodecCapability{ + mediaDescr.MediaName.Media + "/" + codec.Name, + codec.ClockRate, + channels, + codec.Fmtp, + feedback, + }, + PayloadType: PayloadType(payloadType), }) } @@ -807,17 +1089,17 @@ func rtpExtensionsFromMediaDescription(m *sdp.MediaDescription) (map[string]int, // for subsequent calling, it updates Origin for SessionDescription from saved one // and increments session version by one. // https://tools.ietf.org/html/draft-ietf-rtcweb-jsep-25#section-5.2.2 -func updateSDPOrigin(origin *sdp.Origin, d *sdp.SessionDescription) { - if atomic.CompareAndSwapUint64(&origin.SessionVersion, 0, d.Origin.SessionVersion) { // store - atomic.StoreUint64(&origin.SessionID, d.Origin.SessionID) +func updateSDPOrigin(origin *sdp.Origin, descr *sdp.SessionDescription) { + if atomic.CompareAndSwapUint64(&origin.SessionVersion, 0, descr.Origin.SessionVersion) { // store + atomic.StoreUint64(&origin.SessionID, descr.Origin.SessionID) } else { // load for { // awaiting for saving session id - d.Origin.SessionID = atomic.LoadUint64(&origin.SessionID) - if d.Origin.SessionID != 0 { + descr.Origin.SessionID = atomic.LoadUint64(&origin.SessionID) + if descr.Origin.SessionID != 0 { break } } - d.Origin.SessionVersion = atomic.AddUint64(&origin.SessionVersion, 1) + descr.Origin.SessionVersion = atomic.AddUint64(&origin.SessionVersion, 1) } } @@ -840,3 +1122,15 @@ func isExtMapAllowMixedSet(desc *sdp.SessionDescription) bool { return false } + +func getMaxMessageSize(desc *sdp.MediaDescription) uint32 { + for _, a := range desc.Attributes { + if strings.TrimSpace(a.Key) == "max-message-size" { + if v, err := strconv.ParseUint(a.Value, 10, 32); err == nil { + return uint32(v) + } + } + } + + return 0 +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/sdpsemantics.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/sdpsemantics.go similarity index 92% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/sdpsemantics.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/sdpsemantics.go index 6d6335047..c834167a4 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/sdpsemantics.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/sdpsemantics.go @@ -8,7 +8,7 @@ import ( ) // SDPSemantics determines which style of SDP offers and answers -// can be used +// can be used. type SDPSemantics int const ( @@ -24,7 +24,7 @@ const ( // SDPSemanticsUnifiedPlanWithFallback prefers unified-plan // offers and answers, but will respond to a plan-b offer - // with a plan-b answer + // with a plan-b answer. SDPSemanticsUnifiedPlanWithFallback ) @@ -36,14 +36,12 @@ const ( func newSDPSemantics(raw string) SDPSemantics { switch raw { - case sdpSemanticsUnifiedPlan: - return SDPSemanticsUnifiedPlan case sdpSemanticsPlanB: return SDPSemanticsPlanB case sdpSemanticsUnifiedPlanWithFallback: return SDPSemanticsUnifiedPlanWithFallback default: - return SDPSemantics(Unknown) + return SDPSemanticsUnifiedPlan } } @@ -60,7 +58,7 @@ func (s SDPSemantics) String() string { } } -// UnmarshalJSON parses the JSON-encoded data and stores the result +// UnmarshalJSON parses the JSON-encoded data and stores the result. func (s *SDPSemantics) UnmarshalJSON(b []byte) error { var val string if err := json.Unmarshal(b, &val); err != nil { @@ -68,10 +66,11 @@ func (s *SDPSemantics) UnmarshalJSON(b []byte) error { } *s = newSDPSemantics(val) + return nil } -// MarshalJSON returns the JSON encoding +// MarshalJSON returns the JSON encoding. func (s SDPSemantics) MarshalJSON() ([]byte, error) { return json.Marshal(s.String()) } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/sdptype.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/sdptype.go similarity index 89% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/sdptype.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/sdptype.go index 0c6d1d464..f265d9d64 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/sdptype.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/sdptype.go @@ -12,9 +12,11 @@ import ( type SDPType int const ( - // SDPTypeOffer indicates that a description MUST be treated as an SDP - // offer. - SDPTypeOffer SDPType = iota + 1 + // SDPTypeUnknown is the enum's zero-value. + SDPTypeUnknown SDPType = iota + + // SDPTypeOffer indicates that a description MUST be treated as an SDP offer. + SDPTypeOffer // SDPTypePranswer indicates that a description MUST be treated as an // SDP answer, but not a final answer. A description used as an SDP @@ -44,7 +46,7 @@ const ( sdpTypeRollbackStr = "rollback" ) -// NewSDPType creates an SDPType from a string +// NewSDPType creates an SDPType from a string. func NewSDPType(raw string) SDPType { switch raw { case sdpTypeOfferStr: @@ -56,7 +58,7 @@ func NewSDPType(raw string) SDPType { case sdpTypeRollbackStr: return SDPTypeRollback default: - return SDPType(Unknown) + return SDPTypeUnknown } } @@ -75,12 +77,12 @@ func (t SDPType) String() string { } } -// MarshalJSON enables JSON marshaling of a SDPType +// MarshalJSON enables JSON marshaling of a SDPType. func (t SDPType) MarshalJSON() ([]byte, error) { return json.Marshal(t.String()) } -// UnmarshalJSON enables JSON unmarshaling of a SDPType +// UnmarshalJSON enables JSON unmarshaling of a SDPType. func (t *SDPType) UnmarshalJSON(b []byte) error { var s string if err := json.Unmarshal(b, &s); err != nil { diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/sessiondescription.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/sessiondescription.go similarity index 85% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/sessiondescription.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/sessiondescription.go index 12cdf0dd6..186f85837 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/sessiondescription.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/sessiondescription.go @@ -16,9 +16,10 @@ type SessionDescription struct { parsed *sdp.SessionDescription } -// Unmarshal is a helper to deserialize the sdp +// Unmarshal is a helper to deserialize the sdp. func (sd *SessionDescription) Unmarshal() (*sdp.SessionDescription, error) { sd.parsed = &sdp.SessionDescription{} - err := sd.parsed.Unmarshal([]byte(sd.SDP)) + err := sd.parsed.UnmarshalString(sd.SDP) + return sd.parsed, err } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/settingengine.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/settingengine.go similarity index 62% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/settingengine.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/settingengine.go index b11c625e4..0291073f5 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/settingengine.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/settingengine.go @@ -13,13 +13,14 @@ import ( "net" "time" - "github.com/pion/dtls/v2" - dtlsElliptic "github.com/pion/dtls/v2/pkg/crypto/elliptic" - "github.com/pion/ice/v2" + "github.com/pion/dtls/v3" + dtlsElliptic "github.com/pion/dtls/v3/pkg/crypto/elliptic" + "github.com/pion/dtls/v3/pkg/protocol/handshake" + "github.com/pion/ice/v4" "github.com/pion/logging" - "github.com/pion/transport/v2" - "github.com/pion/transport/v2/packetio" - "github.com/pion/transport/v2/vnet" + "github.com/pion/stun/v3" + "github.com/pion/transport/v3" + "github.com/pion/transport/v3/packetio" "golang.org/x/net/proxy" ) @@ -42,12 +43,13 @@ type SettingEngine struct { ICESrflxAcceptanceMinWait *time.Duration ICEPrflxAcceptanceMinWait *time.Duration ICERelayAcceptanceMinWait *time.Duration + ICESTUNGatherTimeout *time.Duration } candidates struct { ICELite bool ICENetworkTypes []NetworkType - InterfaceFilter func(string) bool - IPFilter func(net.IP) bool + InterfaceFilter func(string) (keep bool) + IPFilter func(net.IP) (keep bool) NAT1To1IPs []string NAT1To1IPCandidateType ICECandidateType MulticastDNSMode ice.MulticastDNSMode @@ -62,18 +64,29 @@ type SettingEngine struct { SRTCP *uint } dtls struct { - insecureSkipHelloVerify bool - disableInsecureSkipVerify bool - retransmissionInterval time.Duration - ellipticCurves []dtlsElliptic.Curve - connectContextMaker func() (context.Context, func()) - extendedMasterSecret dtls.ExtendedMasterSecretType - clientAuth *dtls.ClientAuthType - clientCAs *x509.CertPool - rootCAs *x509.CertPool + insecureSkipHelloVerify bool + disableInsecureSkipVerify bool + retransmissionInterval time.Duration + ellipticCurves []dtlsElliptic.Curve + connectContextMaker func() (context.Context, func()) + extendedMasterSecret dtls.ExtendedMasterSecretType + clientAuth *dtls.ClientAuthType + clientCAs *x509.CertPool + rootCAs *x509.CertPool + keyLogWriter io.Writer + customCipherSuites func() []dtls.CipherSuite + clientHelloMessageHook func(handshake.MessageClientHello) handshake.Message + serverHelloMessageHook func(handshake.MessageServerHello) handshake.Message + certificateRequestMessageHook func(handshake.MessageCertificateRequest) handshake.Message } sctp struct { maxReceiveBufferSize uint32 + enableZeroChecksum bool + rtoMax time.Duration + maxMessageSize uint32 + minCwnd uint32 + fastRtxWnd uint32 + cwndCAStep uint32 } sdpMediaLevelFingerprints bool answeringDTLSRole DTLSRole @@ -86,12 +99,27 @@ type SettingEngine struct { iceTCPMux ice.TCPMux iceUDPMux ice.UDPMux iceProxyDialer proxy.Dialer + iceDisableActiveTCP bool + iceBindingRequestHandler func(m *stun.Message, local, remote ice.Candidate, pair *ice.CandidatePair) bool //nolint:lll disableMediaEngineCopy bool + disableMediaEngineMultipleCodecs bool srtpProtectionProfiles []dtls.SRTPProtectionProfile receiveMTU uint + iceMaxBindingRequests *uint16 + fireOnTrackBeforeFirstRTP bool + disableCloseByDTLS bool + dataChannelBlockWrite bool } -// getReceiveMTU returns the configured MTU. If SettingEngine's MTU is configured to 0 it returns the default +func (e *SettingEngine) getSCTPMaxMessageSize() uint32 { + if e.sctp.maxMessageSize != 0 { + return e.sctp.maxMessageSize + } + + return defaultMaxSCTPMessageSize +} + +// getReceiveMTU returns the configured MTU. If SettingEngine's MTU is configured to 0 it returns the default. func (e *SettingEngine) getReceiveMTU() uint { if e.receiveMTU != 0 { return e.receiveMTU @@ -107,8 +135,14 @@ func (e *SettingEngine) DetachDataChannels() { e.detach.DataChannels = true } +// EnableDataChannelBlockWrite allows data channels to block on write, +// it only works if DetachDataChannels is enabled. +func (e *SettingEngine) EnableDataChannelBlockWrite(nonblockWrite bool) { + e.dataChannelBlockWrite = nonblockWrite +} + // SetSRTPProtectionProfiles allows the user to override the default SRTP Protection Profiles -// The default srtp protection profiles are provided by the function `defaultSrtpProtectionProfiles` +// The default srtp protection profiles are provided by the function `defaultSrtpProtectionProfiles`. func (e *SettingEngine) SetSRTPProtectionProfiles(profiles ...dtls.SRTPProtectionProfile) { e.srtpProtectionProfiles = profiles } @@ -125,33 +159,40 @@ func (e *SettingEngine) SetSRTPProtectionProfiles(profiles ...dtls.SRTPProtectio // // keepAliveInterval: // -// How often the ICE Agent sends extra traffic if there is no activity, if media is flowing no traffic will be sent. Default is 2 seconds +// How often the ICE Agent sends extra traffic if there is no activity, if media is flowing no traffic will be sent. +// +// Default is 2 seconds. func (e *SettingEngine) SetICETimeouts(disconnectedTimeout, failedTimeout, keepAliveInterval time.Duration) { e.timeout.ICEDisconnectedTimeout = &disconnectedTimeout e.timeout.ICEFailedTimeout = &failedTimeout e.timeout.ICEKeepaliveInterval = &keepAliveInterval } -// SetHostAcceptanceMinWait sets the ICEHostAcceptanceMinWait +// SetHostAcceptanceMinWait sets the ICEHostAcceptanceMinWait. func (e *SettingEngine) SetHostAcceptanceMinWait(t time.Duration) { e.timeout.ICEHostAcceptanceMinWait = &t } -// SetSrflxAcceptanceMinWait sets the ICESrflxAcceptanceMinWait +// SetSrflxAcceptanceMinWait sets the ICESrflxAcceptanceMinWait. func (e *SettingEngine) SetSrflxAcceptanceMinWait(t time.Duration) { e.timeout.ICESrflxAcceptanceMinWait = &t } -// SetPrflxAcceptanceMinWait sets the ICEPrflxAcceptanceMinWait +// SetPrflxAcceptanceMinWait sets the ICEPrflxAcceptanceMinWait. func (e *SettingEngine) SetPrflxAcceptanceMinWait(t time.Duration) { e.timeout.ICEPrflxAcceptanceMinWait = &t } -// SetRelayAcceptanceMinWait sets the ICERelayAcceptanceMinWait +// SetRelayAcceptanceMinWait sets the ICERelayAcceptanceMinWait. func (e *SettingEngine) SetRelayAcceptanceMinWait(t time.Duration) { e.timeout.ICERelayAcceptanceMinWait = &t } +// SetSTUNGatherTimeout sets the ICESTUNGatherTimeout. +func (e *SettingEngine) SetSTUNGatherTimeout(t time.Duration) { + e.timeout.ICESTUNGatherTimeout = &t +} + // SetEphemeralUDPPortRange limits the pool of ephemeral ports that // ICE UDP connections can allocate from. This affects both host candidates, // and the local address of server reflexive candidates. @@ -165,10 +206,11 @@ func (e *SettingEngine) SetEphemeralUDPPortRange(portMin, portMax uint16) error e.ephemeralUDP.PortMin = portMin e.ephemeralUDP.PortMax = portMax + return nil } -// SetLite configures whether or not the ice agent should be a lite agent +// SetLite configures whether or not the ice agent should be a lite agent. func (e *SettingEngine) SetLite(lite bool) { e.candidates.ICELite = lite } @@ -182,16 +224,16 @@ func (e *SettingEngine) SetNetworkTypes(candidateTypes []NetworkType) { // SetInterfaceFilter sets the filtering functions when gathering ICE candidates // This can be used to exclude certain network interfaces from ICE. Which may be // useful if you know a certain interface will never succeed, or if you wish to reduce -// the amount of information you wish to expose to the remote peer -func (e *SettingEngine) SetInterfaceFilter(filter func(string) bool) { +// the amount of information you wish to expose to the remote peer. +func (e *SettingEngine) SetInterfaceFilter(filter func(string) (keep bool)) { e.candidates.InterfaceFilter = filter } // SetIPFilter sets the filtering functions when gathering ICE candidates // This can be used to exclude certain ip from ICE. Which may be // useful if you know a certain ip will never succeed, or if you wish to reduce -// the amount of information you wish to expose to the remote peer -func (e *SettingEngine) SetIPFilter(filter func(net.IP) bool) { +// the amount of information you wish to expose to the remote peer. +func (e *SettingEngine) SetIPFilter(filter func(net.IP) (keep bool)) { e.candidates.IPFilter = filter } @@ -226,7 +268,7 @@ func (e *SettingEngine) SetNAT1To1IPs(ips []string, candidateType ICECandidateTy } // SetIncludeLoopbackCandidate enable pion to gather loopback candidates, it is useful -// for some VM have public IP mapped to loopback interface +// for some VM have public IP mapped to loopback interface. func (e *SettingEngine) SetIncludeLoopbackCandidate(include bool) { e.candidates.IncludeLoopbackCandidate = include } @@ -248,17 +290,8 @@ func (e *SettingEngine) SetAnsweringDTLSRole(role DTLSRole) error { } e.answeringDTLSRole = role - return nil -} -// SetVNet sets the VNet instance that is passed to pion/ice -// -// VNet is a virtual network layer for Pion, allowing users to simulate -// different topologies, latency, loss and jitter. This can be useful for -// learning WebRTC concepts or testing your application in a lab environment -// Deprecated: Please use SetNet() -func (e *SettingEngine) SetVNet(vnet *vnet.Net) { - e.SetNet(vnet) + return nil } // SetNet sets the Net instance that is passed to pion/ice @@ -269,28 +302,29 @@ func (e *SettingEngine) SetNet(net transport.Net) { e.net = net } -// SetICEMulticastDNSMode controls if pion/ice queries and generates mDNS ICE Candidates +// SetICEMulticastDNSMode controls if pion/ice queries and generates mDNS ICE Candidates. func (e *SettingEngine) SetICEMulticastDNSMode(multicastDNSMode ice.MulticastDNSMode) { e.candidates.MulticastDNSMode = multicastDNSMode } // SetMulticastDNSHostName sets a static HostName to be used by pion/ice instead of generating one on startup // -// This should only be used for a single PeerConnection. Having multiple PeerConnections with the same HostName will cause -// undefined behavior +// This should only be used for a single PeerConnection. +// Having multiple PeerConnections with the same HostName will cause undefined behavior. func (e *SettingEngine) SetMulticastDNSHostName(hostName string) { e.candidates.MulticastDNSHostName = hostName } // SetICECredentials sets a staic uFrag/uPwd to be used by pion/ice // -// This is useful if you want to do signalless WebRTC session, or having a reproducible environment with static credentials +// This is useful if you want to do signalless WebRTC session, +// or having a reproducible environment with static credentials. func (e *SettingEngine) SetICECredentials(usernameFragment, password string) { e.candidates.UsernameFragment = usernameFragment e.candidates.Password = password } -// DisableCertificateFingerprintVerification disables fingerprint verification after DTLS Handshake has finished +// DisableCertificateFingerprintVerification disables fingerprint verification after DTLS Handshake has finished. func (e *SettingEngine) DisableCertificateFingerprintVerification(isDisabled bool) { e.disableCertificateFingerprintVerification = isDisabled } @@ -348,6 +382,17 @@ func (e *SettingEngine) SetICEProxyDialer(d proxy.Dialer) { e.iceProxyDialer = d } +// SetICEMaxBindingRequests sets the maximum amount of binding requests +// that can be sent on a candidate before it is considered invalid. +func (e *SettingEngine) SetICEMaxBindingRequests(d uint16) { + e.iceMaxBindingRequests = &d +} + +// DisableActiveTCP disables using active TCP for ICE. Active TCP is enabled by default. +func (e *SettingEngine) DisableActiveTCP(isDisabled bool) { + e.iceDisableActiveTCP = isDisabled +} + // DisableMediaEngineCopy stops the MediaEngine from being copied. This allows a user to modify // the MediaEngine after the PeerConnection has been constructed. This is useful if you wish to // modify codecs after signaling. Make sure not to share MediaEngines between PeerConnections. @@ -355,8 +400,18 @@ func (e *SettingEngine) DisableMediaEngineCopy(isDisabled bool) { e.disableMediaEngineCopy = isDisabled } +// DisableMediaEngineMultipleCodecs disables the MediaEngine negotiating different codecs. +// With the default value multiple media sections in the SDP can each negotiate different +// codecs. This is the new default behvior, because it makes Pion more spec compliant. +// The value of this setting will get copied to every copy of the MediaEngine generated +// for new PeerConnections (assuming DisableMediaEngineCopy is set to false). +// Note: this setting is targeted to be removed in release 4.2.0 (or later). +func (e *SettingEngine) DisableMediaEngineMultipleCodecs(isDisabled bool) { + e.disableMediaEngineMultipleCodecs = isDisabled +} + // SetReceiveMTU sets the size of read buffer that copies incoming packets. This is optional. -// Leave this 0 for the default receiveMTU +// Leave this 0 for the default receiveMTU. func (e *SettingEngine) SetReceiveMTU(receiveMTU uint) { e.receiveMTU = receiveMTU } @@ -416,8 +471,102 @@ func (e *SettingEngine) SetDTLSRootCAs(rootCAs *x509.CertPool) { e.dtls.rootCAs = rootCAs } +// SetDTLSKeyLogWriter sets the destination of the TLS key material for debugging. +// Logging key material compromises security and should only be use for debugging. +func (e *SettingEngine) SetDTLSKeyLogWriter(writer io.Writer) { + e.dtls.keyLogWriter = writer +} + // SetSCTPMaxReceiveBufferSize sets the maximum receive buffer size. // Leave this 0 for the default maxReceiveBufferSize. func (e *SettingEngine) SetSCTPMaxReceiveBufferSize(maxReceiveBufferSize uint32) { e.sctp.maxReceiveBufferSize = maxReceiveBufferSize } + +// EnableSCTPZeroChecksum controls the zero checksum feature in SCTP. +// This removes the need to checksum every incoming/outgoing packet and will reduce +// latency and CPU usage. This feature is not backwards compatible so is disabled by default. +func (e *SettingEngine) EnableSCTPZeroChecksum(isEnabled bool) { + e.sctp.enableZeroChecksum = isEnabled +} + +// SetSCTPMaxMessageSize sets the largest message we are willing to accept. +// Leave this 0 for the default max message size. +func (e *SettingEngine) SetSCTPMaxMessageSize(maxMessageSize uint32) { + e.sctp.maxMessageSize = maxMessageSize +} + +// SetDTLSCustomerCipherSuites allows the user to specify a list of DTLS CipherSuites. +// This allow usage of Ciphers that are reserved for private usage. +func (e *SettingEngine) SetDTLSCustomerCipherSuites(customCipherSuites func() []dtls.CipherSuite) { + e.dtls.customCipherSuites = customCipherSuites +} + +// SetDTLSClientHelloMessageHook if not nil, is called when a DTLS Client Hello message is sent +// from a client. The returned handshake message replaces the original message. +func (e *SettingEngine) SetDTLSClientHelloMessageHook(hook func(handshake.MessageClientHello) handshake.Message) { + e.dtls.clientHelloMessageHook = hook +} + +// SetDTLSServerHelloMessageHook if not nil, is called when a DTLS Server Hello message is sent +// from a client. The returned handshake message replaces the original message. +func (e *SettingEngine) SetDTLSServerHelloMessageHook(hook func(handshake.MessageServerHello) handshake.Message) { + e.dtls.serverHelloMessageHook = hook +} + +// SetDTLSCertificateRequestMessageHook if not nil, is called when a DTLS Certificate Request message is sent +// from a client. The returned handshake message replaces the original message. +func (e *SettingEngine) SetDTLSCertificateRequestMessageHook( + hook func(handshake.MessageCertificateRequest) handshake.Message, +) { + e.dtls.certificateRequestMessageHook = hook +} + +// SetSCTPRTOMax sets the maximum retransmission timeout. +// Leave this 0 for the default timeout. +func (e *SettingEngine) SetSCTPRTOMax(rtoMax time.Duration) { + e.sctp.rtoMax = rtoMax +} + +// SetSCTPMinCwnd sets the minimum congestion window size. The congestion window +// will not be smaller than this value during congestion control. +func (e *SettingEngine) SetSCTPMinCwnd(minCwnd uint32) { + e.sctp.minCwnd = minCwnd +} + +// SetSCTPFastRtxWnd sets the fast retransmission window size. +func (e *SettingEngine) SetSCTPFastRtxWnd(fastRtxWnd uint32) { + e.sctp.fastRtxWnd = fastRtxWnd +} + +// SetSCTPCwndCAStep sets congestion window adjustment step size during congestion avoidance. +func (e *SettingEngine) SetSCTPCwndCAStep(cwndCAStep uint32) { + e.sctp.cwndCAStep = cwndCAStep +} + +// SetICEBindingRequestHandler sets a callback that is fired on a STUN BindingRequest +// This allows users to do things like +// - Log incoming Binding Requests for debugging +// - Implement draft-thatcher-ice-renomination +// - Implement custom CandidatePair switching logic. +func (e *SettingEngine) SetICEBindingRequestHandler( + bindingRequestHandler func(m *stun.Message, local, remote ice.Candidate, pair *ice.CandidatePair) bool, +) { + e.iceBindingRequestHandler = bindingRequestHandler +} + +// SetFireOnTrackBeforeFirstRTP sets if firing the OnTrack event should happen +// before any RTP packets are received. Setting this to true will +// have the Track's Codec and PayloadTypes be initially set to their +// zero values in the OnTrack handler. +// Note: This does not yet affect simulcast tracks. +func (e *SettingEngine) SetFireOnTrackBeforeFirstRTP(fireOnTrackBeforeFirstRTP bool) { + e.fireOnTrackBeforeFirstRTP = fireOnTrackBeforeFirstRTP +} + +// DisableCloseByDTLS sets if the connection should be closed when dtls transport is closed. +// Setting this to true will keep the connection open when dtls transport is closed +// and relies on the ice failed state to detect the connection is interrupted. +func (e *SettingEngine) DisableCloseByDTLS(isEnabled bool) { + e.disableCloseByDTLS = isEnabled +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/settingengine_js.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/settingengine_js.go similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/settingengine_js.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/settingengine_js.go diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/signalingstate.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/signalingstate.go similarity index 94% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/signalingstate.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/signalingstate.go index 42911c9af..03b8fb239 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/signalingstate.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/signalingstate.go @@ -7,7 +7,7 @@ import ( "fmt" "sync/atomic" - "github.com/pion/webrtc/v3/pkg/rtcerr" + "github.com/pion/webrtc/v4/pkg/rtcerr" ) type stateChangeOp int @@ -32,10 +32,13 @@ func (op stateChangeOp) String() string { type SignalingState int32 const ( + // SignalingStateUnknown is the enum's zero-value. + SignalingStateUnknown SignalingState = iota + // SignalingStateStable indicates there is no offer/answer exchange in // progress. This is also the initial state, in which case the local and // remote descriptions are nil. - SignalingStateStable SignalingState = iota + 1 + SignalingStateStable // SignalingStateHaveLocalOffer indicates that a local description, of // type "offer", has been successfully applied. @@ -84,7 +87,7 @@ func newSignalingState(raw string) SignalingState { case signalingStateClosedStr: return SignalingStateClosed default: - return SignalingState(Unknown) + return SignalingStateUnknown } } @@ -107,17 +110,18 @@ func (t SignalingState) String() string { } } -// Get thread safe read value +// Get thread safe read value. func (t *SignalingState) Get() SignalingState { return SignalingState(atomic.LoadInt32((*int32)(t))) } -// Set thread safe write value +// Set thread safe write value. func (t *SignalingState) Set(state SignalingState) { atomic.StoreInt32((*int32)(t), int32(state)) } -func checkNextSignalingState(cur, next SignalingState, op stateChangeOp, sdpType SDPType) (SignalingState, error) { // nolint:gocognit +//nolint:gocognit,cyclop +func checkNextSignalingState(cur, next SignalingState, op stateChangeOp, sdpType SDPType) (SignalingState, error) { // Special case for rollbacks if sdpType == SDPTypeRollback && cur == SignalingStateStable { return cur, &rtcerr.InvalidModificationError{ @@ -185,6 +189,7 @@ func checkNextSignalingState(cur, next SignalingState, op stateChangeOp, sdpType } } } + return cur, &rtcerr.InvalidModificationError{ Err: fmt.Errorf("%w: %s->%s(%s)->%s", errSignalingStateProposedTransitionInvalid, cur, op, sdpType, next), } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/srtp_writer_future.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/srtp_writer_future.go similarity index 95% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/srtp_writer_future.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/srtp_writer_future.go index 6855e8d30..31afb2d13 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/srtp_writer_future.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/srtp_writer_future.go @@ -13,11 +13,11 @@ import ( "time" "github.com/pion/rtp" - "github.com/pion/srtp/v2" + "github.com/pion/srtp/v3" ) // srtpWriterFuture blocks Read/Write calls until -// the SRTP Session is available +// the SRTP Session is available. type srtpWriterFuture struct { ssrc SSRC rtpSender *RTPSender @@ -27,7 +27,7 @@ type srtpWriterFuture struct { closed bool } -func (s *srtpWriterFuture) init(returnWhenNoSRTP bool) error { +func (s *srtpWriterFuture) init(returnWhenNoSRTP bool) error { //nolint:cyclop if returnWhenNoSRTP { select { case <-s.rtpSender.stopCalled: @@ -73,6 +73,7 @@ func (s *srtpWriterFuture) init(returnWhenNoSRTP bool) error { s.rtcpReadStream.Store(rtcpReadStream) s.rtpWriteStream.Store(rtpWriteStream) + return nil } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/stats.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/stats.go similarity index 59% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/stats.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/stats.go index 5a43cb722..6302f1a18 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/stats.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/stats.go @@ -4,16 +4,75 @@ package webrtc import ( + "encoding/json" "fmt" "sync" "time" - "github.com/pion/ice/v2" + "github.com/pion/ice/v4" ) // A Stats object contains a set of statistics copies out of a monitored component // of the WebRTC stack at a specific time. -type Stats interface{} +type Stats interface { + statsMarker() +} + +// UnmarshalStatsJSON unmarshals a Stats object from JSON. +func UnmarshalStatsJSON(b []byte) (Stats, error) { //nolint:cyclop + type typeJSON struct { + Type StatsType `json:"type"` + } + typeHolder := typeJSON{} + + err := json.Unmarshal(b, &typeHolder) + if err != nil { + return nil, fmt.Errorf("unmarshal json type: %w", err) + } + + switch typeHolder.Type { + case StatsTypeCodec: + return unmarshalCodecStats(b) + case StatsTypeInboundRTP: + return unmarshalInboundRTPStreamStats(b) + case StatsTypeOutboundRTP: + return unmarshalOutboundRTPStreamStats(b) + case StatsTypeRemoteInboundRTP: + return unmarshalRemoteInboundRTPStreamStats(b) + case StatsTypeRemoteOutboundRTP: + return unmarshalRemoteOutboundRTPStreamStats(b) + case StatsTypeCSRC: + return unmarshalCSRCStats(b) + case StatsTypeMediaSource: + return unmarshalMediaSourceStats(b) + case StatsTypeMediaPlayout: + return unmarshalMediaPlayoutStats(b) + case StatsTypePeerConnection: + return unmarshalPeerConnectionStats(b) + case StatsTypeDataChannel: + return unmarshalDataChannelStats(b) + case StatsTypeStream: + return unmarshalStreamStats(b) + case StatsTypeTrack: + return unmarshalTrackStats(b) + case StatsTypeSender: + return unmarshalSenderStats(b) + case StatsTypeReceiver: + return unmarshalReceiverStats(b) + case StatsTypeTransport: + return unmarshalTransportStats(b) + case StatsTypeCandidatePair: + return unmarshalICECandidatePairStats(b) + case StatsTypeLocalCandidate, StatsTypeRemoteCandidate: + return unmarshalICECandidateStats(b) + case StatsTypeCertificate: + return unmarshalCertificateStats(b) + case StatsTypeSCTPTransport: + return unmarshalSCTPTransportStats(b) + default: + return nil, fmt.Errorf("type: %w", ErrUnknownType) + } +} // StatsType indicates the type of the object that a Stats object represents. type StatsType string @@ -37,6 +96,12 @@ const ( // StatsTypeCSRC is used by RTPContributingSourceStats. StatsTypeCSRC StatsType = "csrc" + // StatsTypeMediaSource is used by AudioSourceStats or VideoSourceStats depending on kind. + StatsTypeMediaSource = "media-source" + + // StatsTypeMediaPlayout is used by AudioPlayoutStats. + StatsTypeMediaPlayout StatsType = "media-playout" + // StatsTypePeerConnection used by PeerConnectionStats. StatsTypePeerConnection StatsType = "peer-connection" @@ -46,10 +111,10 @@ const ( // StatsTypeStream is used by MediaStreamStats. StatsTypeStream StatsType = "stream" - // StatsTypeTrack is used by SenderVideoTrackAttachmentStats and SenderAudioTrackAttachmentStats. + // StatsTypeTrack is used by SenderVideoTrackAttachmentStats and SenderAudioTrackAttachmentStats depending on kind. StatsTypeTrack StatsType = "track" - // StatsTypeSender is used by by the AudioSenderStats or VideoSenderStats depending on kind. + // StatsTypeSender is used by the AudioSenderStats or VideoSenderStats depending on kind. StatsTypeSender StatsType = "sender" // StatsTypeReceiver is used by the AudioReceiverStats or VideoReceiverStats depending on kind. @@ -69,6 +134,19 @@ const ( // StatsTypeCertificate is used by CertificateStats. StatsTypeCertificate StatsType = "certificate" + + // StatsTypeSCTPTransport is used by SCTPTransportStats. + StatsTypeSCTPTransport StatsType = "sctp-transport" +) + +// MediaKind indicates the kind of media (audio or video). +type MediaKind string + +const ( + // MediaKindAudio indicates this is audio stats. + MediaKindAudio MediaKind = "audio" + // MediaKindVideo indicates this is video stats. + MediaKindVideo MediaKind = "video" ) // StatsTimestamp is a timestamp represented by the floating point number of @@ -124,11 +202,12 @@ func (src *statsReportCollector) Ready() StatsReport { src.collectingGroup.Wait() src.mux.Lock() defer src.mux.Unlock() + return src.report } // CodecType specifies whether a CodecStats objects represents a media format -// that is being encoded or decoded +// that is being encoded or decoded. type CodecType string const ( @@ -183,9 +262,25 @@ type CodecStats struct { Implementation string `json:"implementation"` } +func (s CodecStats) statsMarker() {} + +func unmarshalCodecStats(b []byte) (CodecStats, error) { + var codecStats CodecStats + err := json.Unmarshal(b, &codecStats) + if err != nil { + return CodecStats{}, fmt.Errorf("unmarshal codec stats: %w", err) + } + + return codecStats, nil +} + // InboundRTPStreamStats contains statistics for an inbound RTP stream that is // currently received with this PeerConnection object. type InboundRTPStreamStats struct { + // Mid represents a mid value of RTPTransceiver owning this stream, if that value is not + // null. Otherwise, this member is not present. + Mid string `json:"mid"` + // Timestamp is the timestamp associated with this object. Timestamp StatsTimestamp `json:"timestamp"` @@ -220,10 +315,92 @@ type InboundRTPStreamStats struct { // received by the sender. This metric is only valid for video and is sent by receiver. PLICount uint32 `json:"pliCount"` + // TotalProcessingDelay is the sum of the time, in seconds, each audio sample or video frame + // takes from the time the first RTP packet is received (reception timestamp) and to the time + // the corresponding sample or frame is decoded (decoded timestamp). At this point the audio + // sample or video frame is ready for playout by the MediaStreamTrack. Typically ready for + // playout here means after the audio sample or video frame is fully decoded by the decoder. + TotalProcessingDelay float64 `json:"totalProcessingDelay"` + // NACKCount counts the total number of Negative ACKnowledgement (NACK) packets // received by the sender and is sent by receiver. NACKCount uint32 `json:"nackCount"` + // JitterBufferDelay is the sum of the time, in seconds, each audio sample or a video frame + // takes from the time the first packet is received by the jitter buffer (ingest timestamp) + // to the time it exits the jitter buffer (emit timestamp). The average jitter buffer delay + // can be calculated by dividing the JitterBufferDelay with the JitterBufferEmittedCount. + JitterBufferDelay float64 `json:"jitterBufferDelay"` + + // JitterBufferTargetDelay is increased by the target jitter buffer delay every time a sample is emitted + // by the jitter buffer. The added target is the target delay, in seconds, at the time that + // the sample was emitted from the jitter buffer. To get the average target delay, + // divide by JitterBufferEmittedCount + JitterBufferTargetDelay float64 `json:"jitterBufferTargetDelay"` + + // JitterBufferEmittedCount is the total number of audio samples or video frames that + // have come out of the jitter buffer (increasing jitterBufferDelay). + JitterBufferEmittedCount uint64 `json:"jitterBufferEmittedCount"` + + // JitterBufferMinimumDelay works the same way as jitterBufferTargetDelay, except that + // it is not affected by external mechanisms that increase the jitter buffer target delay, + // such as jitterBufferTarget, AV sync, or any other mechanisms. This metric is purely + // based on the network characteristics such as jitter and packet loss, and can be seen + // as the minimum obtainable jitter buffer delay if no external factors would affect it. + // The metric is updated every time JitterBufferEmittedCount is updated. + JitterBufferMinimumDelay float64 `json:"jitterBufferMinimumDelay"` + + // TotalSamplesReceived is the total number of samples that have been received on + // this RTP stream. This includes concealedSamples. Does not exist for video. + TotalSamplesReceived uint64 `json:"totalSamplesReceived"` + + // ConcealedSamples is the total number of samples that are concealed samples. + // A concealed sample is a sample that was replaced with synthesized samples generated + // locally before being played out. Examples of samples that have to be concealed are + // samples from lost packets (reported in packetsLost) or samples from packets that + // arrive too late to be played out (reported in packetsDiscarded). Does not exist for video. + ConcealedSamples uint64 `json:"concealedSamples"` + + // SilentConcealedSamples is the total number of concealed samples inserted that + // are "silent". Playing out silent samples results in silence or comfort noise. + // This is a subset of concealedSamples. Does not exist for video. + SilentConcealedSamples uint64 `json:"silentConcealedSamples"` + + // ConcealmentEvents increases every time a concealed sample is synthesized after + // a non-concealed sample. That is, multiple consecutive concealed samples will increase + // the concealedSamples count multiple times but is a single concealment event. + // Does not exist for video. + ConcealmentEvents uint64 `json:"concealmentEvents"` + + // InsertedSamplesForDeceleration is increased by the difference between the number of + // samples received and the number of samples played out when playout is slowed down. + // If playout is slowed down by inserting samples, this will be the number of inserted samples. + // Does not exist for video. + InsertedSamplesForDeceleration uint64 `json:"insertedSamplesForDeceleration"` + + // RemovedSamplesForAcceleration is increased by the difference between the number of + // samples received and the number of samples played out when playout is sped up. If speedup + // is achieved by removing samples, this will be the count of samples removed. + // Does not exist for video. + RemovedSamplesForAcceleration uint64 `json:"removedSamplesForAcceleration"` + + // AudioLevel represents the audio level of the receiving track.. + // + // The value is a value between 0..1 (linear), where 1.0 represents 0 dBov, + // 0 represents silence, and 0.5 represents approximately 6 dBSPL change in + // the sound pressure level from 0 dBov. Does not exist for video. + AudioLevel float64 `json:"audioLevel"` + + // TotalAudioEnergy represents the audio energy of the receiving track. It is calculated + // by duration * Math.pow(energy/maxEnergy, 2) for each audio sample received (and thus + // counted by TotalSamplesReceived). Does not exist for video. + TotalAudioEnergy float64 `json:"totalAudioEnergy"` + + // TotalSamplesDuration represents the total duration in seconds of all samples that have been + // received (and thus counted by TotalSamplesReceived). Can be used with totalAudioEnergy to + // compute an average audio level over different intervals. Does not exist for video. + TotalSamplesDuration float64 `json:"totalSamplesDuration"` + // SLICount counts the total number of Slice Loss Indication (SLI) packets received // by the sender. This metric is only valid for video and is sent by receiver. SLICount uint32 `json:"sliCount"` @@ -232,6 +409,25 @@ type InboundRTPStreamStats struct { // in FramesDecoded for inbound stream stats, and in FramesEncoded for outbound stream stats. QPSum uint64 `json:"qpSum"` + // TotalDecodeTime is the total number of seconds that have been spent decoding the FramesDecoded + // frames of this stream. The average decode time can be calculated by dividing this value + // with FramesDecoded. The time it takes to decode one frame is the time passed between + // feeding the decoder a frame and the decoder returning decoded data for that frame. + TotalDecodeTime float64 `json:"totalDecodeTime"` + + // TotalInterFrameDelay is the sum of the interframe delays in seconds between consecutively + // rendered frames, recorded just after a frame has been rendered. The interframe delay variance + // be calculated from TotalInterFrameDelay, TotalSquaredInterFrameDelay, and FramesRendered according + // to the formula: (TotalSquaredInterFrameDelay - TotalInterFrameDelay^2 / FramesRendered) / FramesRendered. + // Does not exist for audio. + TotalInterFrameDelay float64 `json:"totalInterFrameDelay"` + + // TotalSquaredInterFrameDelay is the sum of the squared interframe delays in seconds + // between consecutively rendered frames, recorded just after a frame has been rendered. + // See TotalInterFrameDelay for details on how to calculate the interframe delay variance. + // Does not exist for audio. + TotalSquaredInterFrameDelay float64 `json:"totalSquaredInterFrameDelay"` + // PacketsReceived is the total number of RTP packets received for this SSRC. PacketsReceived uint32 `json:"packetsReceived"` @@ -294,11 +490,41 @@ type InboundRTPStreamStats struct { // i.e., frames that would be displayed if no frames are dropped. Only valid for video. FramesDecoded uint32 `json:"framesDecoded"` + // KeyFramesDecoded represents the total number of key frames, such as key frames in + // VP8 [RFC6386] or IDR-frames in H.264 [RFC6184], successfully decoded for this RTP + // media stream. This is a subset of FramesDecoded. FramesDecoded - KeyFramesDecoded + // gives you the number of delta frames decoded. Does not exist for audio. + KeyFramesDecoded uint32 `json:"keyFramesDecoded"` + + // FramesRendered represents the total number of frames that have been rendered. + // It is incremented just after a frame has been rendered. Does not exist for audio. + FramesRendered uint32 `json:"framesRendered"` + + // FramesDropped is the total number of frames dropped prior to decode or dropped + // because the frame missed its display deadline for this receiver's track. + // The measurement begins when the receiver is created and is a cumulative metric + // as defined in Appendix A (g) of [RFC7004]. Does not exist for audio. + FramesDropped uint32 `json:"framesDropped"` + + // FrameWidth represents the width of the last decoded frame. Before the first + // frame is decoded this member does not exist. Does not exist for audio. + FrameWidth uint32 `json:"frameWidth"` + + // FrameHeight represents the height of the last decoded frame. Before the first + // frame is decoded this member does not exist. Does not exist for audio. + FrameHeight uint32 `json:"frameHeight"` + // LastPacketReceivedTimestamp represents the timestamp at which the last packet was // received for this SSRC. This differs from Timestamp, which represents the time // at which the statistics were generated by the local endpoint. LastPacketReceivedTimestamp StatsTimestamp `json:"lastPacketReceivedTimestamp"` + // HeaderBytesReceived is the total number of RTP header and padding bytes received for this SSRC. + // This includes retransmissions. This does not include the size of transport layer headers such + // as IP or UDP. headerBytesReceived + bytesReceived equals the number of bytes received as + // payload over the transport. + HeaderBytesReceived uint64 `json:"headerBytesReceived"` + // AverageRTCPInterval is the average RTCP interval between two consecutive compound RTCP packets. // This is calculated by the sending endpoint when sending compound RTCP reports. // Compound packets must contain at least a RTCP RR or SR packet and an SDES packet @@ -309,9 +535,22 @@ type InboundRTPStreamStats struct { // This counter can also be incremented when receiving FEC packets in-band with media packets (e.g., with Opus). FECPacketsReceived uint32 `json:"fecPacketsReceived"` + // FECPacketsDiscarded is the total number of RTP FEC packets received for this SSRC where the + // error correction payload was discarded by the application. This may happen + // 1. if all the source packets protected by the FEC packet were received or already + // recovered by a separate FEC packet, or + // 2. if the FEC packet arrived late, i.e., outside the recovery window, and the + // lost RTP packets have already been skipped during playout. + // This is a subset of FECPacketsReceived. + FECPacketsDiscarded uint64 `json:"fecPacketsDiscarded"` + // BytesReceived is the total number of bytes received for this SSRC. BytesReceived uint64 `json:"bytesReceived"` + // FramesReceived represents the total number of complete frames received on this RTP stream. + // This metric is incremented when the complete frame is received. Does not exist for audio. + FramesReceived uint32 `json:"framesReceived"` + // PacketsFailedDecryption is the cumulative number of RTP packets that failed // to be decrypted. These packets are not counted by PacketsDiscarded. PacketsFailedDecryption uint32 `json:"packetsFailedDecryption"` @@ -330,6 +569,46 @@ type InboundRTPStreamStats struct { // these numbers are not expected to match the numbers seen on sending. Not all // OSes make this information available. PerDSCPPacketsReceived map[string]uint32 `json:"perDscpPacketsReceived"` + + // Identifies the decoder implementation used. This is useful for diagnosing interoperability issues. + // Does not exist for audio. + DecoderImplementation string `json:"decoderImplementation"` + + // PauseCount is the total number of video pauses experienced by this receiver. + // Video is considered to be paused if time passed since last rendered frame exceeds 5 seconds. + // PauseCount is incremented when a frame is rendered after such a pause. Does not exist for audio. + PauseCount uint32 `json:"pauseCount"` + + // TotalPausesDuration is the total duration of pauses (for definition of pause see PauseCount), in seconds. + // Does not exist for audio. + TotalPausesDuration float64 `json:"totalPausesDuration"` + + // FreezeCount is the total number of video freezes experienced by this receiver. + // It is a freeze if frame duration, which is time interval between two consecutively rendered frames, + // is equal or exceeds Max(3 * avg_frame_duration_ms, avg_frame_duration_ms + 150), + // where avg_frame_duration_ms is linear average of durations of last 30 rendered frames. + // Does not exist for audio. + FreezeCount uint32 `json:"freezeCount"` + + // TotalFreezesDuration is the total duration of rendered frames which are considered as frozen + // (for definition of freeze see freezeCount), in seconds. Does not exist for audio. + TotalFreezesDuration float64 `json:"totalFreezesDuration"` + + // PowerEfficientDecoder indicates whether the decoder currently used is considered power efficient + // by the user agent. Does not exist for audio. + PowerEfficientDecoder bool `json:"powerEfficientDecoder"` +} + +func (s InboundRTPStreamStats) statsMarker() {} + +func unmarshalInboundRTPStreamStats(b []byte) (InboundRTPStreamStats, error) { + var inboundRTPStreamStats InboundRTPStreamStats + err := json.Unmarshal(b, &inboundRTPStreamStats) + if err != nil { + return InboundRTPStreamStats{}, fmt.Errorf("unmarshal inbound rtp stream stats: %w", err) + } + + return inboundRTPStreamStats, nil } // QualityLimitationReason lists the reason for limiting the resolution and/or framerate. @@ -343,16 +622,32 @@ const ( // QualityLimitationReasonCPU means the resolution and/or framerate is primarily limited due to CPU load. QualityLimitationReasonCPU QualityLimitationReason = "cpu" - // QualityLimitationReasonBandwidth means the resolution and/or framerate is primarily limited due to congestion cues during bandwidth estimation. Typical, congestion control algorithms use inter-arrival time, round-trip time, packet or other congestion cues to perform bandwidth estimation. + // QualityLimitationReasonBandwidth means the resolution and/or framerate is primarily limited + // due to congestion cues during bandwidth estimation. + // Typical, congestion control algorithms use inter-arrival time, round-trip time, + // packet or other congestion cues to perform bandwidth estimation. QualityLimitationReasonBandwidth QualityLimitationReason = "bandwidth" - // QualityLimitationReasonOther means the resolution and/or framerate is primarily limited for a reason other than the above. + // QualityLimitationReasonOther means the resolution and/or framerate is primarily limited + // for a reason other than the above. QualityLimitationReasonOther QualityLimitationReason = "other" ) // OutboundRTPStreamStats contains statistics for an outbound RTP stream that is // currently sent with this PeerConnection object. type OutboundRTPStreamStats struct { + // Mid represents a mid value of RTPTransceiver owning this stream, if that value is not + // null. Otherwise, this member is not present. + Mid string `json:"mid"` + + // Rid only exists if a rid has been set for this RTP stream. + // Must not exist for audio. + Rid string `json:"rid"` + + // MediaSourceID is the identifier of the stats object representing the track currently + // attached to the sender of this stream, an RTCMediaSourceStats. + MediaSourceID string `json:"mediaSourceId"` + // Timestamp is the timestamp associated with this object. Timestamp StatsTimestamp `json:"timestamp"` @@ -379,6 +674,23 @@ type OutboundRTPStreamStats struct { // to produce the CodecStats associated with this RTP stream. CodecID string `json:"codecId"` + // HeaderBytesSent is the total number of RTP header and padding bytes sent for this SSRC. This does not + // include the size of transport layer headers such as IP or UDP. + // HeaderBytesSent + BytesSent equals the number of bytes sent as payload over the transport. + HeaderBytesSent uint64 `json:"headerBytesSent"` + + // RetransmittedPacketsSent is the total number of packets that were retransmitted for this SSRC. + // This is a subset of packetsSent. If RTX is not negotiated, retransmitted packets are sent + // over this ssrc. If RTX was negotiated, retransmitted packets are sent over a separate SSRC + // but is still accounted for here. + RetransmittedPacketsSent uint64 `json:"retransmittedPacketsSent"` + + // RetransmittedBytesSent is the total number of bytes that were retransmitted for this SSRC, + // only including payload bytes. This is a subset of bytesSent. If RTX is not negotiated, + // retransmitted bytes are sent over this ssrc. If RTX was negotiated, retransmitted bytes + // are sent over a separate SSRC but is still accounted for here. + RetransmittedBytesSent uint64 `json:"retransmittedBytesSent"` + // FIRCount counts the total number of Full Intra Request (FIR) packets received // by the sender. This metric is only valid for video and is sent by receiver. FIRCount uint32 `json:"firCount"` @@ -447,10 +759,47 @@ type OutboundRTPStreamStats struct { // It is measured in bits per second and the bitrate is calculated over a 1 second window. TargetBitrate float64 `json:"targetBitrate"` + // TotalEncodedBytesTarget is increased by the target frame size in bytes every time + // a frame has been encoded. The actual frame size may be bigger or smaller than this number. + // This value goes up every time framesEncoded goes up. + TotalEncodedBytesTarget uint64 `json:"totalEncodedBytesTarget"` + + // FrameWidth represents the width of the last encoded frame. The resolution of the + // encoded frame may be lower than the media source. Before the first frame is encoded + // this member does not exist. Does not exist for audio. + FrameWidth uint32 `json:"frameWidth"` + + // FrameHeight represents the height of the last encoded frame. The resolution of the + // encoded frame may be lower than the media source. Before the first frame is encoded + // this member does not exist. Does not exist for audio. + FrameHeight uint32 `json:"frameHeight"` + + // FramesPerSecond is the number of encoded frames during the last second. This may be + // lower than the media source frame rate. Does not exist for audio. + FramesPerSecond float64 `json:"framesPerSecond"` + + // FramesSent represents the total number of frames sent on this RTP stream. Does not exist for audio. + FramesSent uint32 `json:"framesSent"` + + // HugeFramesSent represents the total number of huge frames sent by this RTP stream. + // Huge frames, by definition, are frames that have an encoded size at least 2.5 times + // the average size of the frames. The average size of the frames is defined as the + // target bitrate per second divided by the target FPS at the time the frame was encoded. + // These are usually complex to encode frames with a lot of changes in the picture. + // This can be used to estimate, e.g slide changes in the streamed presentation. + // Does not exist for audio. + HugeFramesSent uint32 `json:"hugeFramesSent"` + // FramesEncoded represents the total number of frames successfully encoded for this RTP media stream. // Only valid for video. FramesEncoded uint32 `json:"framesEncoded"` + // KeyFramesEncoded represents the total number of key frames, such as key frames in VP8 [RFC6386] or + // IDR-frames in H.264 [RFC6184], successfully encoded for this RTP media stream. This is a subset of + // FramesEncoded. FramesEncoded - KeyFramesEncoded gives you the number of delta frames encoded. + // Does not exist for audio. + KeyFramesEncoded uint32 `json:"keyFramesEncoded"` + // TotalEncodeTime is the total number of seconds that has been spent encoding the // framesEncoded frames of this stream. The average encode time can be calculated by // dividing this value with FramesEncoded. The time it takes to encode one frame is the @@ -458,6 +807,12 @@ type OutboundRTPStreamStats struct { // for that frame. This does not include any additional time it may take to packetize the resulting data. TotalEncodeTime float64 `json:"totalEncodeTime"` + // TotalPacketSendDelay is the total number of seconds that packets have spent buffered + // locally before being transmitted onto the network. The time is measured from when + // a packet is emitted from the RTP packetizer until it is handed over to the OS network socket. + // This measurement is added to totalPacketSendDelay when packetsSent is incremented. + TotalPacketSendDelay float64 `json:"totalPacketSendDelay"` + // AverageRTCPInterval is the average RTCP interval between two consecutive compound RTCP // packets. This is calculated by the sending endpoint when sending compound RTCP reports. // Compound packets must contain at least a RTCP RR or SR packet and an SDES packet with the CNAME item. @@ -472,9 +827,43 @@ type OutboundRTPStreamStats struct { // for all QualityLimitationReason types, including "none". Only valid for video. QualityLimitationDurations map[string]float64 `json:"qualityLimitationDurations"` + // QualityLimitationResolutionChanges is the number of times that the resolution has changed + // because we are quality limited (qualityLimitationReason has a value other than "none"). + // The counter is initially zero and increases when the resolution goes up or down. + // For example, if a 720p track is sent as 480p for some time and then recovers to 720p, + // qualityLimitationResolutionChanges will have the value 2. Does not exist for audio. + QualityLimitationResolutionChanges uint32 `json:"qualityLimitationResolutionChanges"` + // PerDSCPPacketsSent is the total number of packets sent for this SSRC, per DSCP. // DSCPs are identified as decimal integers in string form. PerDSCPPacketsSent map[string]uint32 `json:"perDscpPacketsSent"` + + // Active indicates whether this RTP stream is configured to be sent or disabled. Note that an + // active stream can still not be sending, e.g. when being limited by network conditions. + Active bool `json:"active"` + + // Identifies the encoder implementation used. This is useful for diagnosing interoperability issues. + // Does not exist for audio. + EncoderImplementation string `json:"encoderImplementation"` + + // PowerEfficientEncoder indicates whether the encoder currently used is considered power efficient. + // by the user agent. Does not exist for audio. + PowerEfficientEncoder bool `json:"powerEfficientEncoder"` + + // ScalabilityMode identifies the layering mode used for video encoding. Does not exist for audio. + ScalabilityMode string `json:"scalabilityMode"` +} + +func (s OutboundRTPStreamStats) statsMarker() {} + +func unmarshalOutboundRTPStreamStats(b []byte) (OutboundRTPStreamStats, error) { + var outboundRTPStreamStats OutboundRTPStreamStats + err := json.Unmarshal(b, &outboundRTPStreamStats) + if err != nil { + return OutboundRTPStreamStats{}, fmt.Errorf("unmarshal outbound rtp stream stats: %w", err) + } + + return outboundRTPStreamStats, nil } // RemoteInboundRTPStreamStats contains statistics for the remote endpoint's inbound @@ -581,8 +970,32 @@ type RemoteInboundRTPStreamStats struct { // RTCP timestamps in the RTCP Receiver Report (RR) and measured in seconds. RoundTripTime float64 `json:"roundTripTime"` - // FractionLost is the the fraction packet loss reported for this SSRC. + // TotalRoundTripTime represents the cumulative sum of all round trip time measurements + // in seconds since the beginning of the session. The individual round trip time is calculated + // based on the RTCP timestamps in the RTCP Receiver Report (RR) [RFC3550], hence requires + // a DLSR value other than 0. The average round trip time can be computed from + // TotalRoundTripTime by dividing it by RoundTripTimeMeasurements. + TotalRoundTripTime float64 `json:"totalRoundTripTime"` + + // FractionLost is the fraction packet loss reported for this SSRC. FractionLost float64 `json:"fractionLost"` + + // RoundTripTimeMeasurements represents the total number of RTCP RR blocks received for this SSRC + // that contain a valid round trip time. This counter will not increment if the RoundTripTime can + // not be calculated because no RTCP Receiver Report with a DLSR value other than 0 has been received. + RoundTripTimeMeasurements uint64 `json:"roundTripTimeMeasurements"` +} + +func (s RemoteInboundRTPStreamStats) statsMarker() {} + +func unmarshalRemoteInboundRTPStreamStats(b []byte) (RemoteInboundRTPStreamStats, error) { + var remoteInboundRTPStreamStats RemoteInboundRTPStreamStats + err := json.Unmarshal(b, &remoteInboundRTPStreamStats) + if err != nil { + return RemoteInboundRTPStreamStats{}, fmt.Errorf("unmarshal remote inbound rtp stream stats: %w", err) + } + + return remoteInboundRTPStreamStats, nil } // RemoteOutboundRTPStreamStats contains statistics for the remote endpoint's outbound @@ -669,6 +1082,40 @@ type RemoteOutboundRTPStreamStats struct { // Sender Report (SR) packet, which reflects the remote endpoint's clock. // That clock may not be synchronized with the local clock. RemoteTimestamp StatsTimestamp `json:"remoteTimestamp"` + + // ReportsSent represents the total number of RTCP Sender Report (SR) blocks sent for this SSRC. + ReportsSent uint64 `json:"reportsSent"` + + // RoundTripTime is estimated round trip time for this SSRC based on the latest + // RTCP Sender Report (SR) that contains a DLRR report block as defined in [RFC3611]. + // The Calculation of the round trip time is defined in section 4.5. of [RFC3611]. + // Does not exist if the latest SR does not contain the DLRR report block, or if the last RR timestamp + // in the DLRR report block is zero, or if the delay since last RR value in the DLRR report block is zero. + RoundTripTime float64 `json:"roundTripTime"` + + // TotalRoundTripTime represents the cumulative sum of all round trip time measurements in seconds + // since the beginning of the session. The individual round trip time is calculated based on the DLRR + // report block in the RTCP Sender Report (SR) [RFC3611]. This counter will not increment if the + // RoundTripTime can not be calculated. The average round trip time can be computed from + // TotalRoundTripTime by dividing it by RoundTripTimeMeasurements. + TotalRoundTripTime float64 `json:"totalRoundTripTime"` + + // RoundTripTimeMeasurements represents the total number of RTCP Sender Report (SR) blocks + // received for this SSRC that contain a DLRR report block that can derive a valid round trip time + // according to [RFC3611]. This counter will not increment if the RoundTripTime can not be calculated. + RoundTripTimeMeasurements uint64 `json:"roundTripTimeMeasurements"` +} + +func (s RemoteOutboundRTPStreamStats) statsMarker() {} + +func unmarshalRemoteOutboundRTPStreamStats(b []byte) (RemoteOutboundRTPStreamStats, error) { + var remoteOutboundRTPStreamStats RemoteOutboundRTPStreamStats + err := json.Unmarshal(b, &remoteOutboundRTPStreamStats) + if err != nil { + return RemoteOutboundRTPStreamStats{}, fmt.Errorf("unmarshal remote outbound rtp stream stats: %w", err) + } + + return remoteOutboundRTPStreamStats, nil } // RTPContributingSourceStats contains statistics for a contributing source (CSRC) that contributed @@ -707,6 +1154,216 @@ type RTPContributingSourceStats struct { AudioLevel float64 `json:"audioLevel"` } +func (s RTPContributingSourceStats) statsMarker() {} + +func unmarshalCSRCStats(b []byte) (RTPContributingSourceStats, error) { + var csrcStats RTPContributingSourceStats + err := json.Unmarshal(b, &csrcStats) + if err != nil { + return RTPContributingSourceStats{}, fmt.Errorf("unmarshal csrc stats: %w", err) + } + + return csrcStats, nil +} + +// AudioSourceStats represents an audio track that is attached to one or more senders. +type AudioSourceStats struct { + // Timestamp is the timestamp associated with this object. + Timestamp StatsTimestamp `json:"timestamp"` + + // Type is the object's StatsType + Type StatsType `json:"type"` + + // ID is a unique id that is associated with the component inspected to produce + // this Stats object. Two Stats objects will have the same ID if they were produced + // by inspecting the same underlying object. + ID string `json:"id"` + + // TrackIdentifier represents the id property of the track. + TrackIdentifier string `json:"trackIdentifier"` + + // Kind is "audio" + Kind string `json:"kind"` + + // AudioLevel represents the output audio level of the track. + // + // The value is a value between 0..1 (linear), where 1.0 represents 0 dBov, + // 0 represents silence, and 0.5 represents approximately 6 dBSPL change in + // the sound pressure level from 0 dBov. + // + // If the track is sourced from an Receiver, does no audio processing, has a + // constant level, and has a volume setting of 1.0, the audio level is expected + // to be the same as the audio level of the source SSRC, while if the volume setting + // is 0.5, the AudioLevel is expected to be half that value. + AudioLevel float64 `json:"audioLevel"` + + // TotalAudioEnergy is the total energy of all the audio samples sent/received + // for this object, calculated by duration * Math.pow(energy/maxEnergy, 2) for + // each audio sample seen. + TotalAudioEnergy float64 `json:"totalAudioEnergy"` + + // TotalSamplesDuration represents the total duration in seconds of all samples + // that have sent or received (and thus counted by TotalSamplesSent or TotalSamplesReceived). + // Can be used with TotalAudioEnergy to compute an average audio level over different intervals. + TotalSamplesDuration float64 `json:"totalSamplesDuration"` + + // EchoReturnLoss is only present while the sender is sending a track sourced from + // a microphone where echo cancellation is applied. Calculated in decibels. + EchoReturnLoss float64 `json:"echoReturnLoss"` + + // EchoReturnLossEnhancement is only present while the sender is sending a track + // sourced from a microphone where echo cancellation is applied. Calculated in decibels. + EchoReturnLossEnhancement float64 `json:"echoReturnLossEnhancement"` + + // DroppedSamplesDuration represents the total duration, in seconds, of samples produced by the device that got + // dropped before reaching the media source. Only applicable if this media source is backed by an audio capture device. + DroppedSamplesDuration float64 `json:"droppedSamplesDuration"` + + // DroppedSamplesEvents is the number of dropped samples events. This counter increases every time a sample is + // dropped after a non-dropped sample. That is, multiple consecutive dropped samples will increase + // droppedSamplesDuration multiple times but is a single dropped samples event. + DroppedSamplesEvents uint64 `json:"droppedSamplesEvents"` + + // TotalCaptureDelay is the total delay, in seconds, for each audio sample between the time the sample was emitted + // by the capture device and the sample reaching the source. This can be used together with totalSamplesCaptured to + // calculate the average capture delay per sample. + // Only applicable if the audio source represents an audio capture device. + TotalCaptureDelay float64 `json:"totalCaptureDelay"` + + // TotalSamplesCaptured is the total number of captured samples reaching the audio source, i.e. that were not dropped + // by the capture pipeline. The frequency of the media source is not necessarily the same as the frequency of encoders + // later in the pipeline. Only applicable if the audio source represents an audio capture device. + TotalSamplesCaptured uint64 `json:"totalSamplesCaptured"` +} + +func (s AudioSourceStats) statsMarker() {} + +// VideoSourceStats represents a video track that is attached to one or more senders. +type VideoSourceStats struct { + // Timestamp is the timestamp associated with this object. + Timestamp StatsTimestamp `json:"timestamp"` + + // Type is the object's StatsType + Type StatsType `json:"type"` + + // ID is a unique id that is associated with the component inspected to produce + // this Stats object. Two Stats objects will have the same ID if they were produced + // by inspecting the same underlying object. + ID string `json:"id"` + + // TrackIdentifier represents the id property of the track. + TrackIdentifier string `json:"trackIdentifier"` + + // Kind is "video" + Kind string `json:"kind"` + + // Width is width of the last frame originating from this source in pixels. + Width uint32 `json:"width"` + + // Height is height of the last frame originating from this source in pixels. + Height uint32 `json:"height"` + + // Frames is the total number of frames originating from this source. + Frames uint32 `json:"frames"` + + // FramesPerSecond is the number of frames originating from this source, measured during the last second. + FramesPerSecond float64 `json:"framesPerSecond"` +} + +func (s VideoSourceStats) statsMarker() {} + +func unmarshalMediaSourceStats(b []byte) (Stats, error) { + type kindJSON struct { + Kind string `json:"kind"` + } + kindHolder := kindJSON{} + + err := json.Unmarshal(b, &kindHolder) + if err != nil { + return nil, fmt.Errorf("unmarshal json kind: %w", err) + } + + switch MediaKind(kindHolder.Kind) { + case MediaKindAudio: + var mediaSourceStats AudioSourceStats + err := json.Unmarshal(b, &mediaSourceStats) + if err != nil { + return nil, fmt.Errorf("unmarshal audio source stats: %w", err) + } + + return mediaSourceStats, nil + case MediaKindVideo: + var mediaSourceStats VideoSourceStats + err := json.Unmarshal(b, &mediaSourceStats) + if err != nil { + return nil, fmt.Errorf("unmarshal video source stats: %w", err) + } + + return mediaSourceStats, nil + default: + return nil, fmt.Errorf("kind: %w", ErrUnknownType) + } +} + +// AudioPlayoutStats represents one playout path - if the same playout stats object is referenced by multiple +// RTCInboundRtpStreamStats this is an indication that audio mixing is happening in which case sample counters in this +// stats object refer to the samples after mixing. Only applicable if the playout path represents an audio device. +type AudioPlayoutStats struct { + // Timestamp is the timestamp associated with this object. + Timestamp StatsTimestamp `json:"timestamp"` + + // Type is the object's StatsType + Type StatsType `json:"type"` + + // ID is a unique id that is associated with the component inspected to produce + // this Stats object. Two Stats objects will have the same ID if they were produced + // by inspecting the same underlying object. + ID string `json:"id"` + + // Kind is "audio" + Kind string `json:"kind"` + + // SynthesizedSamplesDuration is measured in seconds and is incremented each time an audio sample is synthesized by + // this playout path. This metric can be used together with totalSamplesDuration to calculate the percentage of played + // out media being synthesized. If the playout path is unable to produce audio samples on time for device playout, + // samples are synthesized to be playout out instead. Synthesization typically only happens if the pipeline is + // underperforming. Samples synthesized by the RTCInboundRtpStreamStats are not counted for here, but in + // InboundRtpStreamStats.concealedSamples. + SynthesizedSamplesDuration float64 `json:"synthesizedSamplesDuration"` + + // SynthesizedSamplesEvents is the number of synthesized samples events. This counter increases every time a sample + // is synthesized after a non-synthesized sample. That is, multiple consecutive synthesized samples will increase + // synthesizedSamplesDuration multiple times but is a single synthesization samples event. + SynthesizedSamplesEvents uint64 `json:"synthesizedSamplesEvents"` + + // TotalSamplesDuration represents the total duration in seconds of all samples + // that have sent or received (and thus counted by TotalSamplesSent or TotalSamplesReceived). + // Can be used with TotalAudioEnergy to compute an average audio level over different intervals. + TotalSamplesDuration float64 `json:"totalSamplesDuration"` + + // When audio samples are pulled by the playout device, this counter is incremented with the estimated delay of the + // playout path for that audio sample. The playout delay includes the delay from being emitted to the actual time of + // playout on the device. This metric can be used together with totalSamplesCount to calculate the average + // playout delay per sample. + TotalPlayoutDelay float64 `json:"totalPlayoutDelay"` + + // When audio samples are pulled by the playout device, this counter is incremented with the number of samples + // emitted for playout. + TotalSamplesCount uint64 `json:"totalSamplesCount"` +} + +func (s AudioPlayoutStats) statsMarker() {} + +func unmarshalMediaPlayoutStats(b []byte) (Stats, error) { + var audioPlayoutStats AudioPlayoutStats + err := json.Unmarshal(b, &audioPlayoutStats) + if err != nil { + return nil, fmt.Errorf("unmarshal audio playout stats: %w", err) + } + + return audioPlayoutStats, nil +} + // PeerConnectionStats contains statistics related to the PeerConnection object. type PeerConnectionStats struct { // Timestamp is the timestamp associated with this object. @@ -741,6 +1398,18 @@ type PeerConnectionStats struct { DataChannelsAccepted uint32 `json:"dataChannelsAccepted"` } +func (s PeerConnectionStats) statsMarker() {} + +func unmarshalPeerConnectionStats(b []byte) (PeerConnectionStats, error) { + var pcStats PeerConnectionStats + err := json.Unmarshal(b, &pcStats) + if err != nil { + return PeerConnectionStats{}, fmt.Errorf("unmarshal pc stats: %w", err) + } + + return pcStats, nil +} + // DataChannelStats contains statistics related to each DataChannel ID. type DataChannelStats struct { // Timestamp is the timestamp associated with this object. @@ -784,6 +1453,18 @@ type DataChannelStats struct { BytesReceived uint64 `json:"bytesReceived"` } +func (s DataChannelStats) statsMarker() {} + +func unmarshalDataChannelStats(b []byte) (DataChannelStats, error) { + var dataChannelStats DataChannelStats + err := json.Unmarshal(b, &dataChannelStats) + if err != nil { + return DataChannelStats{}, fmt.Errorf("unmarshal data channel stats: %w", err) + } + + return dataChannelStats, nil +} + // MediaStreamStats contains statistics related to a specific MediaStream. type MediaStreamStats struct { // Timestamp is the timestamp associated with this object. @@ -805,6 +1486,18 @@ type MediaStreamStats struct { TrackIDs []string `json:"trackIds"` } +func (s MediaStreamStats) statsMarker() {} + +func unmarshalStreamStats(b []byte) (MediaStreamStats, error) { + var streamStats MediaStreamStats + err := json.Unmarshal(b, &streamStats) + if err != nil { + return MediaStreamStats{}, fmt.Errorf("unmarshal stream stats: %w", err) + } + + return streamStats, nil +} + // AudioSenderStats represents the stats about one audio sender of a PeerConnection // object for which one calls GetStats. // @@ -832,7 +1525,7 @@ type AudioSenderStats struct { // Ended reflects the "ended" state of the track. Ended bool `json:"ended"` - // Kind is either "audio" or "video". This reflects the "kind" attribute of the MediaStreamTrack. + // Kind is "audio" Kind string `json:"kind"` // AudioLevel represents the output audio level of the track. @@ -879,6 +1572,8 @@ type AudioSenderStats struct { TotalSamplesSent uint64 `json:"totalSamplesSent"` } +func (s AudioSenderStats) statsMarker() {} + // SenderAudioTrackAttachmentStats object represents the stats about one attachment // of an audio MediaStreamTrack to the PeerConnection object for which one calls GetStats. // @@ -893,6 +1588,8 @@ type AudioSenderStats struct { // it continues to appear, but with the "ObjectDeleted" member set to true. type SenderAudioTrackAttachmentStats AudioSenderStats +func (s SenderAudioTrackAttachmentStats) statsMarker() {} + // VideoSenderStats represents the stats about one video sender of a PeerConnection // object for which one calls GetStats. // @@ -910,6 +1607,9 @@ type VideoSenderStats struct { // by inspecting the same underlying object. ID string `json:"id"` + // Kind is "video" + Kind string `json:"kind"` + // FramesCaptured represents the total number of frames captured, before encoding, // for this RTPSender (or for this MediaStreamTrack, if type is "track"). For example, // if type is "sender" and this sender's track represents a camera, then this is the @@ -940,6 +1640,8 @@ type VideoSenderStats struct { KeyFramesSent uint32 `json:"keyFramesSent"` } +func (s VideoSenderStats) statsMarker() {} + // SenderVideoTrackAttachmentStats represents the stats about one attachment of a // video MediaStreamTrack to the PeerConnection object for which one calls GetStats. // @@ -954,6 +1656,74 @@ type VideoSenderStats struct { // it continues to appear, but with the "ObjectDeleted" member set to true. type SenderVideoTrackAttachmentStats VideoSenderStats +func (s SenderVideoTrackAttachmentStats) statsMarker() {} + +func unmarshalSenderStats(b []byte) (Stats, error) { + type kindJSON struct { + Kind string `json:"kind"` + } + kindHolder := kindJSON{} + + err := json.Unmarshal(b, &kindHolder) + if err != nil { + return nil, fmt.Errorf("unmarshal json kind: %w", err) + } + + switch MediaKind(kindHolder.Kind) { + case MediaKindAudio: + var senderStats AudioSenderStats + err := json.Unmarshal(b, &senderStats) + if err != nil { + return nil, fmt.Errorf("unmarshal audio sender stats: %w", err) + } + + return senderStats, nil + case MediaKindVideo: + var senderStats VideoSenderStats + err := json.Unmarshal(b, &senderStats) + if err != nil { + return nil, fmt.Errorf("unmarshal video sender stats: %w", err) + } + + return senderStats, nil + default: + return nil, fmt.Errorf("kind: %w", ErrUnknownType) + } +} + +func unmarshalTrackStats(b []byte) (Stats, error) { + type kindJSON struct { + Kind string `json:"kind"` + } + kindHolder := kindJSON{} + + err := json.Unmarshal(b, &kindHolder) + if err != nil { + return nil, fmt.Errorf("unmarshal json kind: %w", err) + } + + switch MediaKind(kindHolder.Kind) { + case MediaKindAudio: + var trackStats SenderAudioTrackAttachmentStats + err := json.Unmarshal(b, &trackStats) + if err != nil { + return nil, fmt.Errorf("unmarshal audio track stats: %w", err) + } + + return trackStats, nil + case MediaKindVideo: + var trackStats SenderVideoTrackAttachmentStats + err := json.Unmarshal(b, &trackStats) + if err != nil { + return nil, fmt.Errorf("unmarshal video track stats: %w", err) + } + + return trackStats, nil + default: + return nil, fmt.Errorf("kind: %w", ErrUnknownType) + } +} + // AudioReceiverStats contains audio metrics related to a specific receiver. type AudioReceiverStats struct { // Timestamp is the timestamp associated with this object. @@ -967,6 +1737,9 @@ type AudioReceiverStats struct { // by inspecting the same underlying object. ID string `json:"id"` + // Kind is "audio" + Kind string `json:"kind"` + // AudioLevel represents the output audio level of the track. // // The value is a value between 0..1 (linear), where 1.0 represents 0 dBov, @@ -1038,6 +1811,8 @@ type AudioReceiverStats struct { ConcealmentEvents uint64 `json:"concealmentEvents"` } +func (s AudioReceiverStats) statsMarker() {} + // VideoReceiverStats contains video metrics related to a specific receiver. type VideoReceiverStats struct { // Timestamp is the timestamp associated with this object. @@ -1051,6 +1826,9 @@ type VideoReceiverStats struct { // by inspecting the same underlying object. ID string `json:"id"` + // Kind is "video" + Kind string `json:"kind"` + // FrameWidth represents the width of the last processed frame for this track. // Before the first frame is processed this attribute is missing. FrameWidth uint32 `json:"frameWidth"` @@ -1118,6 +1896,41 @@ type VideoReceiverStats struct { FullFramesLost uint32 `json:"fullFramesLost"` } +func (s VideoReceiverStats) statsMarker() {} + +func unmarshalReceiverStats(b []byte) (Stats, error) { + type kindJSON struct { + Kind string `json:"kind"` + } + kindHolder := kindJSON{} + + err := json.Unmarshal(b, &kindHolder) + if err != nil { + return nil, fmt.Errorf("unmarshal json kind: %w", err) + } + + switch MediaKind(kindHolder.Kind) { + case MediaKindAudio: + var receiverStats AudioReceiverStats + err := json.Unmarshal(b, &receiverStats) + if err != nil { + return nil, fmt.Errorf("unmarshal audio receiver stats: %w", err) + } + + return receiverStats, nil + case MediaKindVideo: + var receiverStats VideoReceiverStats + err := json.Unmarshal(b, &receiverStats) + if err != nil { + return nil, fmt.Errorf("unmarshal video receiver stats: %w", err) + } + + return receiverStats, nil + default: + return nil, fmt.Errorf("kind: %w", ErrUnknownType) + } +} + // TransportStats contains transport statistics related to the PeerConnection object. type TransportStats struct { // Timestamp is the timestamp associated with this object. @@ -1151,12 +1964,16 @@ type TransportStats struct { RTCPTransportStatsID string `json:"rtcpTransportStatsId"` // ICERole is set to the current value of the "role" attribute of the underlying - // DTLSTransport's "transport". + // DTLSTransport's "iceTransport". ICERole ICERole `json:"iceRole"` // DTLSState is set to the current value of the "state" attribute of the underlying DTLSTransport. DTLSState DTLSTransportState `json:"dtlsState"` + // ICEState is set to the current value of the "state" attribute of the underlying + // RTCIceTransport's "state". + ICEState ICETransportState `json:"iceState"` + // SelectedCandidatePairID is a unique identifier that is associated to the object // that was inspected to produce the ICECandidatePairStats associated with this transport. SelectedCandidatePairID string `json:"selectedCandidatePairId"` @@ -1179,6 +1996,18 @@ type TransportStats struct { SRTPCipher string `json:"srtpCipher"` } +func (s TransportStats) statsMarker() {} + +func unmarshalTransportStats(b []byte) (TransportStats, error) { + var transportStats TransportStats + err := json.Unmarshal(b, &transportStats) + if err != nil { + return TransportStats{}, fmt.Errorf("unmarshal transport stats: %w", err) + } + + return transportStats, nil +} + // StatsICECandidatePairState is the state of an ICE candidate pair used in the // ICECandidatePairStats object. type StatsICECandidatePairState string @@ -1196,10 +2025,54 @@ func toStatsICECandidatePairState(state ice.CandidatePairState) (StatsICECandida default: // NOTE: this should never happen[tm] err := fmt.Errorf("%w: %s", errStatsICECandidateStateInvalid, state.String()) + return StatsICECandidatePairState("Unknown"), err } } +func toICECandidatePairStats(candidatePairStats ice.CandidatePairStats) (ICECandidatePairStats, error) { + state, err := toStatsICECandidatePairState(candidatePairStats.State) + if err != nil { + return ICECandidatePairStats{}, err + } + + return ICECandidatePairStats{ + Timestamp: statsTimestampFrom(candidatePairStats.Timestamp), + Type: StatsTypeCandidatePair, + ID: newICECandidatePairStatsID(candidatePairStats.LocalCandidateID, candidatePairStats.RemoteCandidateID), + // TransportID: + LocalCandidateID: candidatePairStats.LocalCandidateID, + RemoteCandidateID: candidatePairStats.RemoteCandidateID, + State: state, + Nominated: candidatePairStats.Nominated, + PacketsSent: candidatePairStats.PacketsSent, + PacketsReceived: candidatePairStats.PacketsReceived, + BytesSent: candidatePairStats.BytesSent, + BytesReceived: candidatePairStats.BytesReceived, + LastPacketSentTimestamp: statsTimestampFrom(candidatePairStats.LastPacketSentTimestamp), + LastPacketReceivedTimestamp: statsTimestampFrom(candidatePairStats.LastPacketReceivedTimestamp), + FirstRequestTimestamp: statsTimestampFrom(candidatePairStats.FirstRequestTimestamp), + LastRequestTimestamp: statsTimestampFrom(candidatePairStats.LastRequestTimestamp), + FirstResponseTimestamp: statsTimestampFrom(candidatePairStats.FirstResponseTimestamp), + LastResponseTimestamp: statsTimestampFrom(candidatePairStats.LastResponseTimestamp), + FirstRequestReceivedTimestamp: statsTimestampFrom(candidatePairStats.FirstRequestReceivedTimestamp), + LastRequestReceivedTimestamp: statsTimestampFrom(candidatePairStats.LastRequestReceivedTimestamp), + TotalRoundTripTime: candidatePairStats.TotalRoundTripTime, + CurrentRoundTripTime: candidatePairStats.CurrentRoundTripTime, + AvailableOutgoingBitrate: candidatePairStats.AvailableOutgoingBitrate, + AvailableIncomingBitrate: candidatePairStats.AvailableIncomingBitrate, + CircuitBreakerTriggerCount: candidatePairStats.CircuitBreakerTriggerCount, + RequestsReceived: candidatePairStats.RequestsReceived, + RequestsSent: candidatePairStats.RequestsSent, + ResponsesReceived: candidatePairStats.ResponsesReceived, + ResponsesSent: candidatePairStats.ResponsesSent, + RetransmissionsReceived: candidatePairStats.RetransmissionsReceived, + RetransmissionsSent: candidatePairStats.RetransmissionsSent, + ConsentRequestsSent: candidatePairStats.ConsentRequestsSent, + ConsentExpiredTimestamp: statsTimestampFrom(candidatePairStats.ConsentExpiredTimestamp), + }, nil +} + const ( // StatsICECandidatePairStateFrozen means a check for this pair hasn't been // performed, and it can't yet be performed until some other check succeeds, @@ -1293,10 +2166,22 @@ type ICECandidatePairStats struct { // (LastRequestTimestamp - FirstRequestTimestamp) / RequestsSent. LastRequestTimestamp StatsTimestamp `json:"lastRequestTimestamp"` + // FirstResponseTimestamp represents the timestamp at which the first STUN response + // was received on this particular candidate pair. + FirstResponseTimestamp StatsTimestamp `json:"firstResponseTimestamp"` + // LastResponseTimestamp represents the timestamp at which the last STUN response // was received on this particular candidate pair. LastResponseTimestamp StatsTimestamp `json:"lastResponseTimestamp"` + // FirstRequestReceivedTimestamp represents the timestamp at which the first + // connectivity check request was received. + FirstRequestReceivedTimestamp StatsTimestamp `json:"firstRequestReceivedTimestamp"` + + // LastRequestReceivedTimestamp represents the timestamp at which the last + // connectivity check request was received. + LastRequestReceivedTimestamp StatsTimestamp `json:"lastRequestReceivedTimestamp"` + // TotalRoundTripTime represents the sum of all round trip time measurements // in seconds since the beginning of the session, based on STUN connectivity // check responses (ResponsesReceived), including those that reply to requests @@ -1361,6 +2246,31 @@ type ICECandidatePairStats struct { // ConsentExpiredTimestamp represents the timestamp at which the latest valid // STUN binding response expired. ConsentExpiredTimestamp StatsTimestamp `json:"consentExpiredTimestamp"` + + // PacketsDiscardedOnSend retpresents the total number of packets for this candidate pair + // that have been discarded due to socket errors, i.e. a socket error occurred + // when handing the packets to the socket. This might happen due to various reasons, + // including full buffer or no available memory. + PacketsDiscardedOnSend uint32 `json:"packetsDiscardedOnSend"` + + // BytesDiscardedOnSend represents the total number of bytes for this candidate pair + // that have been discarded due to socket errors, i.e. a socket error occurred + // when handing the packets containing the bytes to the socket. This might happen due + // to various reasons, including full buffer or no available memory. + // Calculated as defined in [RFC3550] section 6.4.1. + BytesDiscardedOnSend uint32 `json:"bytesDiscardedOnSend"` +} + +func (s ICECandidatePairStats) statsMarker() {} + +func unmarshalICECandidatePairStats(b []byte) (ICECandidatePairStats, error) { + var iceCandidatePairStats ICECandidatePairStats + err := json.Unmarshal(b, &iceCandidatePairStats) + if err != nil { + return ICECandidatePairStats{}, fmt.Errorf("unmarshal ice candidate pair stats: %w", err) + } + + return iceCandidatePairStats, nil } // ICECandidateStats contains ICE candidate statistics related to the ICETransport objects. @@ -1390,7 +2300,10 @@ type ICECandidateStats struct { // it's possible that a connection will be bottlenecked by another type of network. // For example, when using Wi-Fi tethering, the networkType of the relevant candidate // would be "wifi", even when the next hop is over a cellular connection. - NetworkType NetworkType `json:"networkType"` + // + // DEPRECATED. Although it may still work in some browsers, the networkType property was deprecated for + // preserving privacy. + NetworkType string `json:"networkType,omitempty"` // IP is the IP address of the candidate, allowing for IPv4 addresses and // IPv6 addresses, but fully qualified domain names (FQDNs) are not allowed. @@ -1426,6 +2339,18 @@ type ICECandidateStats struct { Deleted bool `json:"deleted"` } +func (s ICECandidateStats) statsMarker() {} + +func unmarshalICECandidateStats(b []byte) (ICECandidateStats, error) { + var iceCandidateStats ICECandidateStats + err := json.Unmarshal(b, &iceCandidateStats) + if err != nil { + return ICECandidateStats{}, fmt.Errorf("unmarshal ice candidate stats: %w", err) + } + + return iceCandidateStats, nil +} + // CertificateStats contains information about a certificate used by an ICETransport. type CertificateStats struct { // Timestamp is the timestamp associated with this object. @@ -1453,3 +2378,67 @@ type CertificateStats struct { // (i.e. a self-signed certificate), this will not be set. IssuerCertificateID string `json:"issuerCertificateId"` } + +func (s CertificateStats) statsMarker() {} + +func unmarshalCertificateStats(b []byte) (CertificateStats, error) { + var certificateStats CertificateStats + err := json.Unmarshal(b, &certificateStats) + if err != nil { + return CertificateStats{}, fmt.Errorf("unmarshal certificate stats: %w", err) + } + + return certificateStats, nil +} + +// SCTPTransportStats contains information about a certificate used by an SCTPTransport. +type SCTPTransportStats struct { + // Timestamp is the timestamp associated with this object. + Timestamp StatsTimestamp `json:"timestamp"` + + // Type is the object's StatsType + Type StatsType `json:"type"` + + // ID is a unique id that is associated with the component inspected to produce + // this Stats object. Two Stats objects will have the same ID if they were produced + // by inspecting the same underlying object. + ID string `json:"id"` + + // TransportID is the identifier of the object that was inspected to produce the + // RTCTransportStats for the DTLSTransport and ICETransport supporting the SCTP transport. + TransportID string `json:"transportId"` + + // SmoothedRoundTripTime is the latest smoothed round-trip time value, + // corresponding to spinfo_srtt defined in [RFC6458] but converted to seconds. + // If there has been no round-trip time measurements yet, this value is undefined. + SmoothedRoundTripTime float64 `json:"smoothedRoundTripTime"` + + // CongestionWindow is the latest congestion window, corresponding to spinfo_cwnd defined in [RFC6458]. + CongestionWindow uint32 `json:"congestionWindow"` + + // ReceiverWindow is the latest receiver window, corresponding to sstat_rwnd defined in [RFC6458]. + ReceiverWindow uint32 `json:"receiverWindow"` + + // MTU is the latest maximum transmission unit, corresponding to spinfo_mtu defined in [RFC6458]. + MTU uint32 `json:"mtu"` + + // UNACKData is the number of unacknowledged DATA chunks, corresponding to sstat_unackdata defined in [RFC6458]. + UNACKData uint32 `json:"unackData"` + + // BytesSent represents the total number of bytes sent on this SCTPTransport + BytesSent uint64 `json:"bytesSent"` + + // BytesReceived represents the total number of bytes received on this SCTPTransport + BytesReceived uint64 `json:"bytesReceived"` +} + +func (s SCTPTransportStats) statsMarker() {} + +func unmarshalSCTPTransportStats(b []byte) (SCTPTransportStats, error) { + var sctpTransportStats SCTPTransportStats + if err := json.Unmarshal(b, &sctpTransportStats); err != nil { + return SCTPTransportStats{}, fmt.Errorf("unmarshal sctp transport stats: %w", err) + } + + return sctpTransportStats, nil +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/stats_go.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/stats_go.go similarity index 91% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/stats_go.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/stats_go.go index a9a8e2156..58722c181 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/stats_go.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/stats_go.go @@ -6,7 +6,7 @@ package webrtc -// GetConnectionStats is a helper method to return the associated stats for a given PeerConnection +// GetConnectionStats is a helper method to return the associated stats for a given PeerConnection. func (r StatsReport) GetConnectionStats(conn *PeerConnection) (PeerConnectionStats, bool) { statsID := conn.getStatsID() stats, ok := r[statsID] @@ -18,10 +18,11 @@ func (r StatsReport) GetConnectionStats(conn *PeerConnection) (PeerConnectionSta if !ok { return PeerConnectionStats{}, false } + return pcStats, true } -// GetDataChannelStats is a helper method to return the associated stats for a given DataChannel +// GetDataChannelStats is a helper method to return the associated stats for a given DataChannel. func (r StatsReport) GetDataChannelStats(dc *DataChannel) (DataChannelStats, bool) { statsID := dc.getStatsID() stats, ok := r[statsID] @@ -33,10 +34,11 @@ func (r StatsReport) GetDataChannelStats(dc *DataChannel) (DataChannelStats, boo if !ok { return DataChannelStats{}, false } + return dcStats, true } -// GetICECandidateStats is a helper method to return the associated stats for a given ICECandidate +// GetICECandidateStats is a helper method to return the associated stats for a given ICECandidate. func (r StatsReport) GetICECandidateStats(c *ICECandidate) (ICECandidateStats, bool) { statsID := c.statsID stats, ok := r[statsID] @@ -48,10 +50,11 @@ func (r StatsReport) GetICECandidateStats(c *ICECandidate) (ICECandidateStats, b if !ok { return ICECandidateStats{}, false } + return candidateStats, true } -// GetICECandidatePairStats is a helper method to return the associated stats for a given ICECandidatePair +// GetICECandidatePairStats is a helper method to return the associated stats for a given ICECandidatePair. func (r StatsReport) GetICECandidatePairStats(c *ICECandidatePair) (ICECandidatePairStats, bool) { statsID := c.statsID stats, ok := r[statsID] @@ -63,10 +66,11 @@ func (r StatsReport) GetICECandidatePairStats(c *ICECandidatePair) (ICECandidate if !ok { return ICECandidatePairStats{}, false } + return candidateStats, true } -// GetCertificateStats is a helper method to return the associated stats for a given Certificate +// GetCertificateStats is a helper method to return the associated stats for a given Certificate. func (r StatsReport) GetCertificateStats(c *Certificate) (CertificateStats, bool) { statsID := c.statsID stats, ok := r[statsID] @@ -78,10 +82,11 @@ func (r StatsReport) GetCertificateStats(c *Certificate) (CertificateStats, bool if !ok { return CertificateStats{}, false } + return certificateStats, true } -// GetCodecStats is a helper method to return the associated stats for a given Codec +// GetCodecStats is a helper method to return the associated stats for a given Codec. func (r StatsReport) GetCodecStats(c *RTPCodecParameters) (CodecStats, bool) { statsID := c.statsID stats, ok := r[statsID] @@ -93,5 +98,6 @@ func (r StatsReport) GetCodecStats(c *RTPCodecParameters) (CodecStats, bool) { if !ok { return CodecStats{}, false } + return codecStats, true } diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/track_local.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/track_local.go new file mode 100644 index 000000000..448b98af2 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/track_local.go @@ -0,0 +1,128 @@ +// SPDX-FileCopyrightText: 2023 The Pion community +// SPDX-License-Identifier: MIT + +package webrtc + +import ( + "github.com/pion/interceptor" + "github.com/pion/rtp" +) + +// TrackLocalWriter is the Writer for outbound RTP Packets. +type TrackLocalWriter interface { + // WriteRTP encrypts a RTP packet and writes to the connection + WriteRTP(header *rtp.Header, payload []byte) (int, error) + + // Write encrypts and writes a full RTP packet + Write(b []byte) (int, error) +} + +// TrackLocalContext is the Context passed when a TrackLocal has been Binded/Unbinded from a PeerConnection, and used +// in Interceptors. +type TrackLocalContext interface { + // CodecParameters returns the negotiated RTPCodecParameters. These are the codecs supported by both + // PeerConnections and the PayloadTypes + CodecParameters() []RTPCodecParameters + + // HeaderExtensions returns the negotiated RTPHeaderExtensionParameters. These are the header extensions supported by + // both PeerConnections and the URI/IDs + HeaderExtensions() []RTPHeaderExtensionParameter + + // SSRC returns the negotiated SSRC of this track + SSRC() SSRC + + // SSRCRetransmission returns the negotiated SSRC used to send retransmissions for this track + SSRCRetransmission() SSRC + + // SSRCForwardErrorCorrection returns the negotiated SSRC to send forward error correction for this track + SSRCForwardErrorCorrection() SSRC + + // WriteStream returns the WriteStream for this TrackLocal. The implementer writes the outbound + // media packets to it + WriteStream() TrackLocalWriter + + // ID is a unique identifier that is used for both Bind/Unbind + ID() string + + // RTCPReader returns the RTCP interceptor for this TrackLocal. Used to read RTCP of this TrackLocal. + RTCPReader() interceptor.RTCPReader +} + +type baseTrackLocalContext struct { + id string + params RTPParameters + ssrc, ssrcRTX, ssrcFEC SSRC + writeStream TrackLocalWriter + rtcpInterceptor interceptor.RTCPReader +} + +// CodecParameters returns the negotiated RTPCodecParameters. These are the codecs supported by both +// PeerConnections and the SSRC/PayloadTypes. +func (t *baseTrackLocalContext) CodecParameters() []RTPCodecParameters { + return t.params.Codecs +} + +// HeaderExtensions returns the negotiated RTPHeaderExtensionParameters. These are the header extensions supported by +// both PeerConnections and the SSRC/PayloadTypes. +func (t *baseTrackLocalContext) HeaderExtensions() []RTPHeaderExtensionParameter { + return t.params.HeaderExtensions +} + +// SSRC requires the negotiated SSRC of this track. +func (t *baseTrackLocalContext) SSRC() SSRC { + return t.ssrc +} + +// SSRCRetransmission returns the negotiated SSRC used to send retransmissions for this track. +func (t *baseTrackLocalContext) SSRCRetransmission() SSRC { + return t.ssrcRTX +} + +// SSRCForwardErrorCorrection returns the negotiated SSRC to send forward error correction for this track. +func (t *baseTrackLocalContext) SSRCForwardErrorCorrection() SSRC { + return t.ssrcFEC +} + +// WriteStream returns the WriteStream for this TrackLocal. The implementer writes the outbound +// media packets to it. +func (t *baseTrackLocalContext) WriteStream() TrackLocalWriter { + return t.writeStream +} + +// ID is a unique identifier that is used for both Bind/Unbind. +func (t *baseTrackLocalContext) ID() string { + return t.id +} + +// RTCPReader returns the RTCP interceptor for this TrackLocal. Used to read RTCP of this TrackLocal. +func (t *baseTrackLocalContext) RTCPReader() interceptor.RTCPReader { + return t.rtcpInterceptor +} + +// TrackLocal is an interface that controls how the user can send media +// The user can provide their own TrackLocal implementations, or use +// the implementations in pkg/media. +type TrackLocal interface { + // Bind should implement the way how the media data flows from the Track to the PeerConnection + // This will be called internally after signaling is complete and the list of available + // codecs has been determined + Bind(TrackLocalContext) (RTPCodecParameters, error) + + // Unbind should implement the teardown logic when the track is no longer needed. This happens + // because a track has been stopped. + Unbind(TrackLocalContext) error + + // ID is the unique identifier for this Track. This should be unique for the + // stream, but doesn't have to globally unique. A common example would be 'audio' or 'video' + // and StreamID would be 'desktop' or 'webcam' + ID() string + + // RID is the RTP Stream ID for this track. + RID() string + + // StreamID is the group this track belongs too. This must be unique + StreamID() string + + // Kind controls if this TrackLocal is audio or video + Kind() RTPCodecType +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/track_local_static.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/track_local_static.go similarity index 65% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/track_local_static.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/track_local_static.go index 17ce0587a..6bac1e1b3 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/track_local_static.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/track_local_static.go @@ -11,31 +11,37 @@ import ( "sync" "github.com/pion/rtp" - "github.com/pion/webrtc/v3/internal/util" - "github.com/pion/webrtc/v3/pkg/media" + "github.com/pion/webrtc/v4/internal/util" + "github.com/pion/webrtc/v4/pkg/media" ) // trackBinding is a single bind for a Track // Bind can be called multiple times, this stores the -// result for a single bind call so that it can be used when writing +// result for a single bind call so that it can be used when writing. type trackBinding struct { - id string - ssrc SSRC - payloadType PayloadType - writeStream TrackLocalWriter + id string + ssrc, ssrcRTX, ssrcFEC SSRC + payloadType, payloadTypeRTX PayloadType + writeStream TrackLocalWriter } // TrackLocalStaticRTP is a TrackLocal that has a pre-set codec and accepts RTP Packets. -// If you wish to send a media.Sample use TrackLocalStaticSample +// If you wish to send a media.Sample use TrackLocalStaticSample. type TrackLocalStaticRTP struct { mu sync.RWMutex bindings []trackBinding codec RTPCodecCapability + payloader func(RTPCodecCapability) (rtp.Payloader, error) id, rid, streamID string + rtpTimestamp *uint32 } // NewTrackLocalStaticRTP returns a TrackLocalStaticRTP. -func NewTrackLocalStaticRTP(c RTPCodecCapability, id, streamID string, options ...func(*TrackLocalStaticRTP)) (*TrackLocalStaticRTP, error) { +func NewTrackLocalStaticRTP( + c RTPCodecCapability, + id, streamID string, + options ...func(*TrackLocalStaticRTP), +) (*TrackLocalStaticRTP, error) { t := &TrackLocalStaticRTP{ codec: c, bindings: []trackBinding{}, @@ -57,21 +63,42 @@ func WithRTPStreamID(rid string) func(*TrackLocalStaticRTP) { } } +// WithPayloader allows the user to override the Payloader. +func WithPayloader(h func(RTPCodecCapability) (rtp.Payloader, error)) func(*TrackLocalStaticRTP) { + return func(s *TrackLocalStaticRTP) { + s.payloader = h + } +} + +// WithRTPTimestamp set the initial RTP timestamp for the track. +func WithRTPTimestamp(timestamp uint32) func(*TrackLocalStaticRTP) { + return func(s *TrackLocalStaticRTP) { + s.rtpTimestamp = ×tamp + } +} + // Bind is called by the PeerConnection after negotiation is complete // This asserts that the code requested is supported by the remote peer. -// If so it setups all the state (SSRC and PayloadType) to have a call -func (s *TrackLocalStaticRTP) Bind(t TrackLocalContext) (RTPCodecParameters, error) { +// If so it sets up all the state (SSRC and PayloadType) to have a call. +func (s *TrackLocalStaticRTP) Bind(trackContext TrackLocalContext) (RTPCodecParameters, error) { s.mu.Lock() defer s.mu.Unlock() parameters := RTPCodecParameters{RTPCodecCapability: s.codec} - if codec, matchType := codecParametersFuzzySearch(parameters, t.CodecParameters()); matchType != codecMatchNone { + if codec, matchType := codecParametersFuzzySearch( + parameters, + trackContext.CodecParameters(), + ); matchType != codecMatchNone { s.bindings = append(s.bindings, trackBinding{ - ssrc: t.SSRC(), - payloadType: codec.PayloadType, - writeStream: t.WriteStream(), - id: t.ID(), + ssrc: trackContext.SSRC(), + ssrcRTX: trackContext.SSRCRetransmission(), + ssrcFEC: trackContext.SSRCForwardErrorCorrection(), + payloadType: codec.PayloadType, + payloadTypeRTX: findRTXPayloadType(codec.PayloadType, trackContext.CodecParameters()), + writeStream: trackContext.WriteStream(), + id: trackContext.ID(), }) + return codec, nil } @@ -88,6 +115,7 @@ func (s *TrackLocalStaticRTP) Unbind(t TrackLocalContext) error { if s.bindings[i].id == t.ID() { s.bindings[i] = s.bindings[len(s.bindings)-1] s.bindings = s.bindings[:len(s.bindings)-1] + return nil } } @@ -97,16 +125,16 @@ func (s *TrackLocalStaticRTP) Unbind(t TrackLocalContext) error { // ID is the unique identifier for this Track. This should be unique for the // stream, but doesn't have to globally unique. A common example would be 'audio' or 'video' -// and StreamID would be 'desktop' or 'webcam' +// and StreamID would be 'desktop' or 'webcam'. func (s *TrackLocalStaticRTP) ID() string { return s.id } -// StreamID is the group this track belongs too. This must be unique +// StreamID is the group this track belongs too. This must be unique. func (s *TrackLocalStaticRTP) StreamID() string { return s.streamID } // RID is the RTP stream identifier. func (s *TrackLocalStaticRTP) RID() string { return s.rid } -// Kind controls if this TrackLocal is audio or video +// Kind controls if this TrackLocal is audio or video. func (s *TrackLocalStaticRTP) Kind() RTPCodecType { switch { case strings.HasPrefix(s.codec.MimeType, "audio/"): @@ -118,7 +146,7 @@ func (s *TrackLocalStaticRTP) Kind() RTPCodecType { } } -// Codec gets the Codec of the track +// Codec gets the Codec of the track. func (s *TrackLocalStaticRTP) Codec() RTPCodecCapability { return s.codec } @@ -138,13 +166,14 @@ func resetPacketPoolAllocation(localPacket *rtp.Packet) { func getPacketAllocationFromPool() *rtp.Packet { ipacket := rtpPacketPool.Get() + return ipacket.(*rtp.Packet) //nolint:forcetypeassert } // WriteRTP writes a RTP Packet to the TrackLocalStaticRTP // If one PeerConnection fails the packets will still be sent to // all PeerConnections. The error message will contain the ID of the failed -// PeerConnections so you can remove them +// PeerConnections so you can remove them. func (s *TrackLocalStaticRTP) WriteRTP(p *rtp.Packet) error { packet := getPacketAllocationFromPool() @@ -155,17 +184,17 @@ func (s *TrackLocalStaticRTP) WriteRTP(p *rtp.Packet) error { return s.writeRTP(packet) } -// writeRTP is like WriteRTP, except that it may modify the packet p -func (s *TrackLocalStaticRTP) writeRTP(p *rtp.Packet) error { +// writeRTP is like WriteRTP, except that it may modify the packet p. +func (s *TrackLocalStaticRTP) writeRTP(packet *rtp.Packet) error { s.mu.RLock() defer s.mu.RUnlock() writeErrs := []error{} for _, b := range s.bindings { - p.Header.SSRC = uint32(b.ssrc) - p.Header.PayloadType = uint8(b.payloadType) - if _, err := b.writeStream.WriteRTP(&p.Header, p.Payload); err != nil { + packet.Header.SSRC = uint32(b.ssrc) + packet.Header.PayloadType = uint8(b.payloadType) + if _, err := b.writeStream.WriteRTP(&packet.Header, packet.Payload); err != nil { writeErrs = append(writeErrs, err) } } @@ -176,7 +205,7 @@ func (s *TrackLocalStaticRTP) writeRTP(p *rtp.Packet) error { // Write writes a RTP Packet as a buffer to the TrackLocalStaticRTP // If one PeerConnection fails the packets will still be sent to // all PeerConnections. The error message will contain the ID of the failed -// PeerConnections so you can remove them +// PeerConnections so you can remove them. func (s *TrackLocalStaticRTP) Write(b []byte) (n int, err error) { packet := getPacketAllocationFromPool() @@ -190,7 +219,7 @@ func (s *TrackLocalStaticRTP) Write(b []byte) (n int, err error) { } // TrackLocalStaticSample is a TrackLocal that has a pre-set codec and accepts Samples. -// If you wish to send a RTP Packet use TrackLocalStaticRTP +// If you wish to send a RTP Packet use TrackLocalStaticRTP. type TrackLocalStaticSample struct { packetizer rtp.Packetizer sequencer rtp.Sequencer @@ -198,8 +227,12 @@ type TrackLocalStaticSample struct { clockRate float64 } -// NewTrackLocalStaticSample returns a TrackLocalStaticSample -func NewTrackLocalStaticSample(c RTPCodecCapability, id, streamID string, options ...func(*TrackLocalStaticRTP)) (*TrackLocalStaticSample, error) { +// NewTrackLocalStaticSample returns a TrackLocalStaticSample. +func NewTrackLocalStaticSample( + c RTPCodecCapability, + id, streamID string, + options ...func(*TrackLocalStaticRTP), +) (*TrackLocalStaticSample, error) { rtpTrack, err := NewTrackLocalStaticRTP(c, id, streamID, options...) if err != nil { return nil, err @@ -212,26 +245,26 @@ func NewTrackLocalStaticSample(c RTPCodecCapability, id, streamID string, option // ID is the unique identifier for this Track. This should be unique for the // stream, but doesn't have to globally unique. A common example would be 'audio' or 'video' -// and StreamID would be 'desktop' or 'webcam' +// and StreamID would be 'desktop' or 'webcam'. func (s *TrackLocalStaticSample) ID() string { return s.rtpTrack.ID() } -// StreamID is the group this track belongs too. This must be unique +// StreamID is the group this track belongs too. This must be unique. func (s *TrackLocalStaticSample) StreamID() string { return s.rtpTrack.StreamID() } // RID is the RTP stream identifier. func (s *TrackLocalStaticSample) RID() string { return s.rtpTrack.RID() } -// Kind controls if this TrackLocal is audio or video +// Kind controls if this TrackLocal is audio or video. func (s *TrackLocalStaticSample) Kind() RTPCodecType { return s.rtpTrack.Kind() } -// Codec gets the Codec of the track +// Codec gets the Codec of the track. func (s *TrackLocalStaticSample) Codec() RTPCodecCapability { return s.rtpTrack.Codec() } // Bind is called by the PeerConnection after negotiation is complete // This asserts that the code requested is supported by the remote peer. -// If so it setups all the state (SSRC and PayloadType) to have a call +// If so it setups all the state (SSRC and PayloadType) to have a call. func (s *TrackLocalStaticSample) Bind(t TrackLocalContext) (RTPCodecParameters, error) { codec, err := s.rtpTrack.Bind(t) if err != nil { @@ -246,21 +279,34 @@ func (s *TrackLocalStaticSample) Bind(t TrackLocalContext) (RTPCodecParameters, return codec, nil } - payloader, err := payloaderForCodec(codec.RTPCodecCapability) + payloadHandler := s.rtpTrack.payloader + if payloadHandler == nil { + payloadHandler = payloaderForCodec + } + + payloader, err := payloadHandler(codec.RTPCodecCapability) if err != nil { return codec, err } s.sequencer = rtp.NewRandomSequencer() - s.packetizer = rtp.NewPacketizer( - rtpOutboundMTU, - 0, // Value is handled when writing - 0, // Value is handled when writing + + options := []rtp.PacketizerOption{} + + if s.rtpTrack.rtpTimestamp != nil { + options = append(options, rtp.WithTimestamp(*s.rtpTrack.rtpTimestamp)) + } + + s.packetizer = rtp.NewPacketizerWithOptions( + outboundMTU, payloader, s.sequencer, codec.ClockRate, + options..., ) + s.clockRate = float64(codec.RTPCodecCapability.ClockRate) + return codec, nil } @@ -273,14 +319,14 @@ func (s *TrackLocalStaticSample) Unbind(t TrackLocalContext) error { // WriteSample writes a Sample to the TrackLocalStaticSample // If one PeerConnection fails the packets will still be sent to // all PeerConnections. The error message will contain the ID of the failed -// PeerConnections so you can remove them +// PeerConnections so you can remove them. func (s *TrackLocalStaticSample) WriteSample(sample media.Sample) error { s.rtpTrack.mu.RLock() - p := s.packetizer + packetizer := s.packetizer clockRate := s.clockRate s.rtpTrack.mu.RUnlock() - if p == nil { + if packetizer == nil { return nil } @@ -291,9 +337,34 @@ func (s *TrackLocalStaticSample) WriteSample(sample media.Sample) error { samples := uint32(sample.Duration.Seconds() * clockRate) if sample.PrevDroppedPackets > 0 { - p.SkipSamples(samples * uint32(sample.PrevDroppedPackets)) + packetizer.SkipSamples(samples * uint32(sample.PrevDroppedPackets)) } - packets := p.Packetize(sample.Data, samples) + packets := packetizer.Packetize(sample.Data, samples) + + writeErrs := []error{} + for _, p := range packets { + if err := s.rtpTrack.WriteRTP(p); err != nil { + writeErrs = append(writeErrs, err) + } + } + + return util.FlattenErrs(writeErrs) +} + +// GeneratePadding writes padding-only samples to the TrackLocalStaticSample +// If one PeerConnection fails the packets will still be sent to +// all PeerConnections. The error message will contain the ID of the failed +// PeerConnections so you can remove them. +func (s *TrackLocalStaticSample) GeneratePadding(samples uint32) error { + s.rtpTrack.mu.RLock() + p := s.packetizer + s.rtpTrack.mu.RUnlock() + + if p == nil { + return nil + } + + packets := p.GeneratePadding(samples) writeErrs := []error{} for _, p := range packets { diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/track_remote.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/track_remote.go similarity index 68% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/track_remote.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/track_remote.go index 150b91bc9..1b037e716 100644 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/track_remote.go +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/track_remote.go @@ -14,7 +14,7 @@ import ( "github.com/pion/rtp" ) -// TrackRemote represents a single inbound source of media +// TrackRemote represents a single inbound source of media. type TrackRemote struct { mu sync.RWMutex @@ -24,6 +24,7 @@ type TrackRemote struct { payloadType PayloadType kind RTPCodecType ssrc SSRC + rtxSsrc SSRC codec RTPCodecParameters params RTPParameters rid string @@ -33,10 +34,11 @@ type TrackRemote struct { peekedAttributes interceptor.Attributes } -func newTrackRemote(kind RTPCodecType, ssrc SSRC, rid string, receiver *RTPReceiver) *TrackRemote { +func newTrackRemote(kind RTPCodecType, ssrc, rtxSsrc SSRC, rid string, receiver *RTPReceiver) *TrackRemote { return &TrackRemote{ kind: kind, ssrc: ssrc, + rtxSsrc: rtxSsrc, rid: rid, receiver: receiver, } @@ -44,16 +46,17 @@ func newTrackRemote(kind RTPCodecType, ssrc SSRC, rid string, receiver *RTPRecei // ID is the unique identifier for this Track. This should be unique for the // stream, but doesn't have to globally unique. A common example would be 'audio' or 'video' -// and StreamID would be 'desktop' or 'webcam' +// and StreamID would be 'desktop' or 'webcam'. func (t *TrackRemote) ID() string { t.mu.RLock() defer t.mu.RUnlock() + return t.id } // RID gets the RTP Stream ID of this Track // With Simulcast you will have multiple tracks with the same ID, but different RID values. -// In many cases a TrackRemote will not have an RID, so it is important to assert it is non-zero +// In many cases a TrackRemote will not have an RID, so it is important to assert it is non-zero. func (t *TrackRemote) RID() string { t.mu.RLock() defer t.mu.RUnlock() @@ -61,50 +64,55 @@ func (t *TrackRemote) RID() string { return t.rid } -// PayloadType gets the PayloadType of the track +// PayloadType gets the PayloadType of the track. func (t *TrackRemote) PayloadType() PayloadType { t.mu.RLock() defer t.mu.RUnlock() + return t.payloadType } -// Kind gets the Kind of the track +// Kind gets the Kind of the track. func (t *TrackRemote) Kind() RTPCodecType { t.mu.RLock() defer t.mu.RUnlock() + return t.kind } -// StreamID is the group this track belongs too. This must be unique +// StreamID is the group this track belongs too. This must be unique. func (t *TrackRemote) StreamID() string { t.mu.RLock() defer t.mu.RUnlock() + return t.streamID } -// SSRC gets the SSRC of the track +// SSRC gets the SSRC of the track. func (t *TrackRemote) SSRC() SSRC { t.mu.RLock() defer t.mu.RUnlock() + return t.ssrc } -// Msid gets the Msid of the track +// Msid gets the Msid of the track. func (t *TrackRemote) Msid() string { return t.StreamID() + " " + t.ID() } -// Codec gets the Codec of the track +// Codec gets the Codec of the track. func (t *TrackRemote) Codec() RTPCodecParameters { t.mu.RLock() defer t.mu.RUnlock() + return t.codec } // Read reads data from the track. func (t *TrackRemote) Read(b []byte) (n int, attributes interceptor.Attributes, err error) { t.mu.RLock() - r := t.receiver + receiver := t.receiver peeked := t.peeked != nil t.mu.RUnlock() @@ -121,27 +129,40 @@ func (t *TrackRemote) Read(b []byte) (n int, attributes interceptor.Attributes, if data != nil { n = copy(b, data) err = t.checkAndUpdateTrack(b) - return + + return n, attributes, err } } - n, attributes, err = r.readRTP(b, t) - if err != nil { - return + // If there's a separate RTX track and an RTX packet is available, return that + if rtxPacketReceived := receiver.readRTX(t); rtxPacketReceived != nil { + n = copy(b, rtxPacketReceived.pkt) + attributes = rtxPacketReceived.attributes + rtxPacketReceived.release() + err = nil + } else { + // If there's no separate RTX track (or there's a separate RTX track but no RTX packet waiting), wait for and return + // a packet from the main track + n, attributes, err = receiver.readRTP(b, t) + if err != nil { + return n, attributes, err + } + + err = t.checkAndUpdateTrack(b) } - err = t.checkAndUpdateTrack(b) - return + return n, attributes, err } // checkAndUpdateTrack checks payloadType for every incoming packet -// once a different payloadType is detected the track will be updated +// once a different payloadType is detected the track will be updated. func (t *TrackRemote) checkAndUpdateTrack(b []byte) error { if len(b) < 2 { return errRTPTooShort } - if payloadType := PayloadType(b[1] & rtpPayloadTypeBitmask); payloadType != t.PayloadType() { + payloadType := PayloadType(b[1] & rtpPayloadTypeBitmask) + if payloadType != t.PayloadType() || len(t.params.Codecs) == 0 { t.mu.Lock() defer t.mu.Unlock() @@ -171,10 +192,11 @@ func (t *TrackRemote) ReadRTP() (*rtp.Packet, interceptor.Attributes, error) { if err := r.Unmarshal(b[:i]); err != nil { return nil, nil, err } + return r, attributes, nil } -// peek is like Read, but it doesn't discard the packet read +// peek is like Read, but it doesn't discard the packet read. func (t *TrackRemote) peek(b []byte) (n int, a interceptor.Attributes, err error) { n, a, err = t.Read(b) if err != nil { @@ -190,6 +212,7 @@ func (t *TrackRemote) peek(b []byte) (n int, a interceptor.Attributes, err error t.peeked = data t.peekedAttributes = a t.mu.Unlock() + return } @@ -197,3 +220,25 @@ func (t *TrackRemote) peek(b []byte) (n int, a interceptor.Attributes, err error func (t *TrackRemote) SetReadDeadline(deadline time.Time) error { return t.receiver.setRTPReadDeadline(deadline, t) } + +// RtxSSRC returns the RTX SSRC for a track, or 0 if track does not have a separate RTX stream. +func (t *TrackRemote) RtxSSRC() SSRC { + t.mu.RLock() + defer t.mu.RUnlock() + + return t.rtxSsrc +} + +// HasRTX returns true if the track has a separate RTX stream. +func (t *TrackRemote) HasRTX() bool { + t.mu.RLock() + defer t.mu.RUnlock() + + return t.rtxSsrc != 0 +} + +func (t *TrackRemote) setRtxSSRC(ssrc SSRC) { + t.mu.Lock() + defer t.mu.Unlock() + t.rtxSsrc = ssrc +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/webrtc.go b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/webrtc.go similarity index 100% rename from trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v3/webrtc.go rename to trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/webrtc.go diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/yarn.lock b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/yarn.lock new file mode 100644 index 000000000..809d55604 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/pion/webrtc/v4/yarn.lock @@ -0,0 +1,377 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + +# SPDX-FileCopyrightText: 2023 The Pion community +# SPDX-License-Identifier: MIT + +"@roamhq/wrtc-darwin-arm64@0.8.0": + version "0.8.0" + resolved "https://registry.yarnpkg.com/@roamhq/wrtc-darwin-arm64/-/wrtc-darwin-arm64-0.8.0.tgz#15057e6b8f57e4d1b7008a9d848b6f2036adbb24" + integrity sha512-OtV2KWO7zOG3L8TF3KCt9aucynVCD/ww2xeXXgg+FLkya3ca0uzehN8EQJ3BL4tkInksbFJ2ssyu9cehfJ3ZuA== + +"@roamhq/wrtc-darwin-x64@0.8.0": + version "0.8.0" + resolved "https://registry.yarnpkg.com/@roamhq/wrtc-darwin-x64/-/wrtc-darwin-x64-0.8.0.tgz#e09137b5a7edf2c2412bc63f1da1893dcaa211fd" + integrity sha512-VY7Vzt/SDDDCpW//h8GW9bOZrOr8gWXPZVD9473ypl4jyBIoO57yyLbHzd1G0vBUkS6szsHlQCz1WwpI30YL+g== + +"@roamhq/wrtc-linux-arm64@0.8.1": + version "0.8.1" + resolved "https://registry.yarnpkg.com/@roamhq/wrtc-linux-arm64/-/wrtc-linux-arm64-0.8.1.tgz#9a5f3297de44fcec86713d0baefa0594658ab71e" + integrity sha512-FBJLLazlWkGQUXaokC/rTbrUQbb0CNFYry52fZGstufrGLTWu+g4HcwXdVvxh1tnVtVMvkQGk+mlOL52sCxw0A== + +"@roamhq/wrtc-linux-x64@0.8.1": + version "0.8.1" + resolved "https://registry.yarnpkg.com/@roamhq/wrtc-linux-x64/-/wrtc-linux-x64-0.8.1.tgz#3c5b60ca6cc6ebf5c2389d852f4a101135031da2" + integrity sha512-I9oWG7b4uvWO1IOR/aF34n+ID6TKVuSs0jd19h5KdhfRtw7FFh9xxuwN9rONPxLVa6fS0q+MCZgAf8Scz89L8Q== + +"@roamhq/wrtc-win32-x64@0.8.0": + version "0.8.0" + resolved "https://registry.yarnpkg.com/@roamhq/wrtc-win32-x64/-/wrtc-win32-x64-0.8.0.tgz#582e2478df48201d5757b60dcd4b4dcc40a054b7" + integrity sha512-R2fxl41BLWPiP4eaTHGLzbbVvRjx1mV/OsgINCvawO7Hwz5Zx9I45+Fhrw3hd4n5amIeSG9VIF7Kz8eeTFXTGQ== + +"@roamhq/wrtc@^0.8.0": + version "0.8.0" + resolved "https://registry.yarnpkg.com/@roamhq/wrtc/-/wrtc-0.8.0.tgz#03c8c64c3b6a1e6e8965ec6496fa7e97571ae04b" + integrity sha512-C0V/nqc4/2xzORI5qa4mIeN/8UO3ywN1kInrJ9u6GljFx0D18JMUJEqe8yYHa61RrEeoWN3PKdW++k8TocSx/A== + optionalDependencies: + "@roamhq/wrtc-darwin-arm64" "0.8.0" + "@roamhq/wrtc-darwin-x64" "0.8.0" + "@roamhq/wrtc-linux-arm64" "0.8.1" + "@roamhq/wrtc-linux-x64" "0.8.1" + "@roamhq/wrtc-win32-x64" "0.8.0" + domexception "^4.0.0" + +ajv@^6.5.5: + version "6.12.2" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.2.tgz#c629c5eced17baf314437918d2da88c99d5958cd" + integrity sha512-k+V+hzjm5q/Mr8ef/1Y9goCmlsK4I6Sm74teeyGvFk1XrOsbsKLjEdrvny42CZ+a8sXbk8KWpY/bDwS+FLL2UQ== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +asn1@~0.2.3: + version "0.2.4" + resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" + integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg== + dependencies: + safer-buffer "~2.1.0" + +assert-plus@1.0.0, assert-plus@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" + integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= + +aws-sign2@~0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" + integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= + +aws4@^1.8.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.10.0.tgz#a17b3a8ea811060e74d47d306122400ad4497ae2" + integrity sha512-3YDiu347mtVtjpyV3u5kVqQLP242c06zwDOgpeRnybmXlYYsLbtTrUBUm8i8srONt+FWobl5aibnU1030PeeuA== + +bcrypt-pbkdf@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" + integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4= + dependencies: + tweetnacl "^0.14.3" + +caseless@~0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" + integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= + +combined-stream@^1.0.6, combined-stream@~1.0.6: + version "1.0.8" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + +core-util-is@1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= + +dashdash@^1.12.0: + version "1.14.1" + resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" + integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA= + dependencies: + assert-plus "^1.0.0" + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= + +domexception@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/domexception/-/domexception-4.0.0.tgz#4ad1be56ccadc86fc76d033353999a8037d03673" + integrity sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw== + dependencies: + webidl-conversions "^7.0.0" + +ecc-jsbn@~0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" + integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk= + dependencies: + jsbn "~0.1.0" + safer-buffer "^2.1.0" + +extend@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" + integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== + +extsprintf@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" + integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU= + +extsprintf@^1.2.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" + integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8= + +fast-deep-equal@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz#545145077c501491e33b15ec408c294376e94ae4" + integrity sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA== + +fast-json-stable-stringify@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + +forever-agent@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" + integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= + +form-data@~2.3.2: + version "2.3.3" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" + integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.6" + mime-types "^2.1.12" + +getpass@^0.1.1: + version "0.1.7" + resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" + integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo= + dependencies: + assert-plus "^1.0.0" + +har-schema@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" + integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= + +har-validator@~5.1.3: + version "5.1.3" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.3.tgz#1ef89ebd3e4996557675eed9893110dc350fa080" + integrity sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g== + dependencies: + ajv "^6.5.5" + har-schema "^2.0.0" + +http-signature@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" + integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE= + dependencies: + assert-plus "^1.0.0" + jsprim "^1.2.2" + sshpk "^1.7.0" + +is-typedarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= + +isstream@~0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" + integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= + +jsbn@~0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" + integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json-schema@0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" + integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM= + +json-stringify-safe@~5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= + +jsprim@^1.2.2: + version "1.4.1" + resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" + integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI= + dependencies: + assert-plus "1.0.0" + extsprintf "1.3.0" + json-schema "0.2.3" + verror "1.10.0" + +mime-db@1.44.0: + version "1.44.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.44.0.tgz#fa11c5eb0aca1334b4233cb4d52f10c5a6272f92" + integrity sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg== + +mime-types@^2.1.12, mime-types@~2.1.19: + version "2.1.27" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.27.tgz#47949f98e279ea53119f5722e0f34e529bec009f" + integrity sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w== + dependencies: + mime-db "1.44.0" + +oauth-sign@~0.9.0: + version "0.9.0" + resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" + integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== + +performance-now@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" + integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= + +psl@^1.1.28: + version "1.8.0" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24" + integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ== + +punycode@^2.1.0, punycode@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" + integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== + +qs@~6.5.2: + version "6.5.2" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" + integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== + +request@2.88.2: + version "2.88.2" + resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" + integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== + dependencies: + aws-sign2 "~0.7.0" + aws4 "^1.8.0" + caseless "~0.12.0" + combined-stream "~1.0.6" + extend "~3.0.2" + forever-agent "~0.6.1" + form-data "~2.3.2" + har-validator "~5.1.3" + http-signature "~1.2.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.19" + oauth-sign "~0.9.0" + performance-now "^2.1.0" + qs "~6.5.2" + safe-buffer "^5.1.2" + tough-cookie "~2.5.0" + tunnel-agent "^0.6.0" + uuid "^3.3.2" + +safe-buffer@^5.0.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +safe-buffer@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + +safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +sshpk@^1.7.0: + version "1.16.1" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877" + integrity sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg== + dependencies: + asn1 "~0.2.3" + assert-plus "^1.0.0" + bcrypt-pbkdf "^1.0.0" + dashdash "^1.12.0" + ecc-jsbn "~0.1.1" + getpass "^0.1.1" + jsbn "~0.1.0" + safer-buffer "^2.0.2" + tweetnacl "~0.14.0" + +tough-cookie@~2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" + integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== + dependencies: + psl "^1.1.28" + punycode "^2.1.1" + +tunnel-agent@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" + integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= + dependencies: + safe-buffer "^5.0.1" + +tweetnacl@^0.14.3, tweetnacl@~0.14.0: + version "0.14.5" + resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" + integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= + +uri-js@^4.2.2: + version "4.2.2" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" + integrity sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ== + dependencies: + punycode "^2.1.0" + +uuid@^3.3.2: + version "3.4.0" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" + integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== + +verror@1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" + integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA= + dependencies: + assert-plus "^1.0.0" + core-util-is "1.0.2" + extsprintf "^1.2.0" + +webidl-conversions@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-7.0.0.tgz#256b4e1882be7debbf01d05f0aa2039778ea080a" + integrity sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g== diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pmezard/go-difflib/LICENSE b/trunk/3rdparty/srs-bench/vendor/github.com/pmezard/go-difflib/LICENSE deleted file mode 100644 index c67dad612..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pmezard/go-difflib/LICENSE +++ /dev/null @@ -1,27 +0,0 @@ -Copyright (c) 2013, Patrick Mezard -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright -notice, this list of conditions and the following disclaimer in the -documentation and/or other materials provided with the distribution. - The names of its contributors may not be used to endorse or promote -products derived from this software without specific prior written -permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/pmezard/go-difflib/difflib/difflib.go b/trunk/3rdparty/srs-bench/vendor/github.com/pmezard/go-difflib/difflib/difflib.go deleted file mode 100644 index 003e99fad..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/pmezard/go-difflib/difflib/difflib.go +++ /dev/null @@ -1,772 +0,0 @@ -// Package difflib is a partial port of Python difflib module. -// -// It provides tools to compare sequences of strings and generate textual diffs. -// -// The following class and functions have been ported: -// -// - SequenceMatcher -// -// - unified_diff -// -// - context_diff -// -// Getting unified diffs was the main goal of the port. Keep in mind this code -// is mostly suitable to output text differences in a human friendly way, there -// are no guarantees generated diffs are consumable by patch(1). -package difflib - -import ( - "bufio" - "bytes" - "fmt" - "io" - "strings" -) - -func min(a, b int) int { - if a < b { - return a - } - return b -} - -func max(a, b int) int { - if a > b { - return a - } - return b -} - -func calculateRatio(matches, length int) float64 { - if length > 0 { - return 2.0 * float64(matches) / float64(length) - } - return 1.0 -} - -type Match struct { - A int - B int - Size int -} - -type OpCode struct { - Tag byte - I1 int - I2 int - J1 int - J2 int -} - -// SequenceMatcher compares sequence of strings. The basic -// algorithm predates, and is a little fancier than, an algorithm -// published in the late 1980's by Ratcliff and Obershelp under the -// hyperbolic name "gestalt pattern matching". The basic idea is to find -// the longest contiguous matching subsequence that contains no "junk" -// elements (R-O doesn't address junk). The same idea is then applied -// recursively to the pieces of the sequences to the left and to the right -// of the matching subsequence. This does not yield minimal edit -// sequences, but does tend to yield matches that "look right" to people. -// -// SequenceMatcher tries to compute a "human-friendly diff" between two -// sequences. Unlike e.g. UNIX(tm) diff, the fundamental notion is the -// longest *contiguous* & junk-free matching subsequence. That's what -// catches peoples' eyes. The Windows(tm) windiff has another interesting -// notion, pairing up elements that appear uniquely in each sequence. -// That, and the method here, appear to yield more intuitive difference -// reports than does diff. This method appears to be the least vulnerable -// to synching up on blocks of "junk lines", though (like blank lines in -// ordinary text files, or maybe "

" lines in HTML files). That may be -// because this is the only method of the 3 that has a *concept* of -// "junk" . -// -// Timing: Basic R-O is cubic time worst case and quadratic time expected -// case. SequenceMatcher is quadratic time for the worst case and has -// expected-case behavior dependent in a complicated way on how many -// elements the sequences have in common; best case time is linear. -type SequenceMatcher struct { - a []string - b []string - b2j map[string][]int - IsJunk func(string) bool - autoJunk bool - bJunk map[string]struct{} - matchingBlocks []Match - fullBCount map[string]int - bPopular map[string]struct{} - opCodes []OpCode -} - -func NewMatcher(a, b []string) *SequenceMatcher { - m := SequenceMatcher{autoJunk: true} - m.SetSeqs(a, b) - return &m -} - -func NewMatcherWithJunk(a, b []string, autoJunk bool, - isJunk func(string) bool) *SequenceMatcher { - - m := SequenceMatcher{IsJunk: isJunk, autoJunk: autoJunk} - m.SetSeqs(a, b) - return &m -} - -// Set two sequences to be compared. -func (m *SequenceMatcher) SetSeqs(a, b []string) { - m.SetSeq1(a) - m.SetSeq2(b) -} - -// Set the first sequence to be compared. The second sequence to be compared is -// not changed. -// -// SequenceMatcher computes and caches detailed information about the second -// sequence, so if you want to compare one sequence S against many sequences, -// use .SetSeq2(s) once and call .SetSeq1(x) repeatedly for each of the other -// sequences. -// -// See also SetSeqs() and SetSeq2(). -func (m *SequenceMatcher) SetSeq1(a []string) { - if &a == &m.a { - return - } - m.a = a - m.matchingBlocks = nil - m.opCodes = nil -} - -// Set the second sequence to be compared. The first sequence to be compared is -// not changed. -func (m *SequenceMatcher) SetSeq2(b []string) { - if &b == &m.b { - return - } - m.b = b - m.matchingBlocks = nil - m.opCodes = nil - m.fullBCount = nil - m.chainB() -} - -func (m *SequenceMatcher) chainB() { - // Populate line -> index mapping - b2j := map[string][]int{} - for i, s := range m.b { - indices := b2j[s] - indices = append(indices, i) - b2j[s] = indices - } - - // Purge junk elements - m.bJunk = map[string]struct{}{} - if m.IsJunk != nil { - junk := m.bJunk - for s, _ := range b2j { - if m.IsJunk(s) { - junk[s] = struct{}{} - } - } - for s, _ := range junk { - delete(b2j, s) - } - } - - // Purge remaining popular elements - popular := map[string]struct{}{} - n := len(m.b) - if m.autoJunk && n >= 200 { - ntest := n/100 + 1 - for s, indices := range b2j { - if len(indices) > ntest { - popular[s] = struct{}{} - } - } - for s, _ := range popular { - delete(b2j, s) - } - } - m.bPopular = popular - m.b2j = b2j -} - -func (m *SequenceMatcher) isBJunk(s string) bool { - _, ok := m.bJunk[s] - return ok -} - -// Find longest matching block in a[alo:ahi] and b[blo:bhi]. -// -// If IsJunk is not defined: -// -// Return (i,j,k) such that a[i:i+k] is equal to b[j:j+k], where -// alo <= i <= i+k <= ahi -// blo <= j <= j+k <= bhi -// and for all (i',j',k') meeting those conditions, -// k >= k' -// i <= i' -// and if i == i', j <= j' -// -// In other words, of all maximal matching blocks, return one that -// starts earliest in a, and of all those maximal matching blocks that -// start earliest in a, return the one that starts earliest in b. -// -// If IsJunk is defined, first the longest matching block is -// determined as above, but with the additional restriction that no -// junk element appears in the block. Then that block is extended as -// far as possible by matching (only) junk elements on both sides. So -// the resulting block never matches on junk except as identical junk -// happens to be adjacent to an "interesting" match. -// -// If no blocks match, return (alo, blo, 0). -func (m *SequenceMatcher) findLongestMatch(alo, ahi, blo, bhi int) Match { - // CAUTION: stripping common prefix or suffix would be incorrect. - // E.g., - // ab - // acab - // Longest matching block is "ab", but if common prefix is - // stripped, it's "a" (tied with "b"). UNIX(tm) diff does so - // strip, so ends up claiming that ab is changed to acab by - // inserting "ca" in the middle. That's minimal but unintuitive: - // "it's obvious" that someone inserted "ac" at the front. - // Windiff ends up at the same place as diff, but by pairing up - // the unique 'b's and then matching the first two 'a's. - besti, bestj, bestsize := alo, blo, 0 - - // find longest junk-free match - // during an iteration of the loop, j2len[j] = length of longest - // junk-free match ending with a[i-1] and b[j] - j2len := map[int]int{} - for i := alo; i != ahi; i++ { - // look at all instances of a[i] in b; note that because - // b2j has no junk keys, the loop is skipped if a[i] is junk - newj2len := map[int]int{} - for _, j := range m.b2j[m.a[i]] { - // a[i] matches b[j] - if j < blo { - continue - } - if j >= bhi { - break - } - k := j2len[j-1] + 1 - newj2len[j] = k - if k > bestsize { - besti, bestj, bestsize = i-k+1, j-k+1, k - } - } - j2len = newj2len - } - - // Extend the best by non-junk elements on each end. In particular, - // "popular" non-junk elements aren't in b2j, which greatly speeds - // the inner loop above, but also means "the best" match so far - // doesn't contain any junk *or* popular non-junk elements. - for besti > alo && bestj > blo && !m.isBJunk(m.b[bestj-1]) && - m.a[besti-1] == m.b[bestj-1] { - besti, bestj, bestsize = besti-1, bestj-1, bestsize+1 - } - for besti+bestsize < ahi && bestj+bestsize < bhi && - !m.isBJunk(m.b[bestj+bestsize]) && - m.a[besti+bestsize] == m.b[bestj+bestsize] { - bestsize += 1 - } - - // Now that we have a wholly interesting match (albeit possibly - // empty!), we may as well suck up the matching junk on each - // side of it too. Can't think of a good reason not to, and it - // saves post-processing the (possibly considerable) expense of - // figuring out what to do with it. In the case of an empty - // interesting match, this is clearly the right thing to do, - // because no other kind of match is possible in the regions. - for besti > alo && bestj > blo && m.isBJunk(m.b[bestj-1]) && - m.a[besti-1] == m.b[bestj-1] { - besti, bestj, bestsize = besti-1, bestj-1, bestsize+1 - } - for besti+bestsize < ahi && bestj+bestsize < bhi && - m.isBJunk(m.b[bestj+bestsize]) && - m.a[besti+bestsize] == m.b[bestj+bestsize] { - bestsize += 1 - } - - return Match{A: besti, B: bestj, Size: bestsize} -} - -// Return list of triples describing matching subsequences. -// -// Each triple is of the form (i, j, n), and means that -// a[i:i+n] == b[j:j+n]. The triples are monotonically increasing in -// i and in j. It's also guaranteed that if (i, j, n) and (i', j', n') are -// adjacent triples in the list, and the second is not the last triple in the -// list, then i+n != i' or j+n != j'. IOW, adjacent triples never describe -// adjacent equal blocks. -// -// The last triple is a dummy, (len(a), len(b), 0), and is the only -// triple with n==0. -func (m *SequenceMatcher) GetMatchingBlocks() []Match { - if m.matchingBlocks != nil { - return m.matchingBlocks - } - - var matchBlocks func(alo, ahi, blo, bhi int, matched []Match) []Match - matchBlocks = func(alo, ahi, blo, bhi int, matched []Match) []Match { - match := m.findLongestMatch(alo, ahi, blo, bhi) - i, j, k := match.A, match.B, match.Size - if match.Size > 0 { - if alo < i && blo < j { - matched = matchBlocks(alo, i, blo, j, matched) - } - matched = append(matched, match) - if i+k < ahi && j+k < bhi { - matched = matchBlocks(i+k, ahi, j+k, bhi, matched) - } - } - return matched - } - matched := matchBlocks(0, len(m.a), 0, len(m.b), nil) - - // It's possible that we have adjacent equal blocks in the - // matching_blocks list now. - nonAdjacent := []Match{} - i1, j1, k1 := 0, 0, 0 - for _, b := range matched { - // Is this block adjacent to i1, j1, k1? - i2, j2, k2 := b.A, b.B, b.Size - if i1+k1 == i2 && j1+k1 == j2 { - // Yes, so collapse them -- this just increases the length of - // the first block by the length of the second, and the first - // block so lengthened remains the block to compare against. - k1 += k2 - } else { - // Not adjacent. Remember the first block (k1==0 means it's - // the dummy we started with), and make the second block the - // new block to compare against. - if k1 > 0 { - nonAdjacent = append(nonAdjacent, Match{i1, j1, k1}) - } - i1, j1, k1 = i2, j2, k2 - } - } - if k1 > 0 { - nonAdjacent = append(nonAdjacent, Match{i1, j1, k1}) - } - - nonAdjacent = append(nonAdjacent, Match{len(m.a), len(m.b), 0}) - m.matchingBlocks = nonAdjacent - return m.matchingBlocks -} - -// Return list of 5-tuples describing how to turn a into b. -// -// Each tuple is of the form (tag, i1, i2, j1, j2). The first tuple -// has i1 == j1 == 0, and remaining tuples have i1 == the i2 from the -// tuple preceding it, and likewise for j1 == the previous j2. -// -// The tags are characters, with these meanings: -// -// 'r' (replace): a[i1:i2] should be replaced by b[j1:j2] -// -// 'd' (delete): a[i1:i2] should be deleted, j1==j2 in this case. -// -// 'i' (insert): b[j1:j2] should be inserted at a[i1:i1], i1==i2 in this case. -// -// 'e' (equal): a[i1:i2] == b[j1:j2] -func (m *SequenceMatcher) GetOpCodes() []OpCode { - if m.opCodes != nil { - return m.opCodes - } - i, j := 0, 0 - matching := m.GetMatchingBlocks() - opCodes := make([]OpCode, 0, len(matching)) - for _, m := range matching { - // invariant: we've pumped out correct diffs to change - // a[:i] into b[:j], and the next matching block is - // a[ai:ai+size] == b[bj:bj+size]. So we need to pump - // out a diff to change a[i:ai] into b[j:bj], pump out - // the matching block, and move (i,j) beyond the match - ai, bj, size := m.A, m.B, m.Size - tag := byte(0) - if i < ai && j < bj { - tag = 'r' - } else if i < ai { - tag = 'd' - } else if j < bj { - tag = 'i' - } - if tag > 0 { - opCodes = append(opCodes, OpCode{tag, i, ai, j, bj}) - } - i, j = ai+size, bj+size - // the list of matching blocks is terminated by a - // sentinel with size 0 - if size > 0 { - opCodes = append(opCodes, OpCode{'e', ai, i, bj, j}) - } - } - m.opCodes = opCodes - return m.opCodes -} - -// Isolate change clusters by eliminating ranges with no changes. -// -// Return a generator of groups with up to n lines of context. -// Each group is in the same format as returned by GetOpCodes(). -func (m *SequenceMatcher) GetGroupedOpCodes(n int) [][]OpCode { - if n < 0 { - n = 3 - } - codes := m.GetOpCodes() - if len(codes) == 0 { - codes = []OpCode{OpCode{'e', 0, 1, 0, 1}} - } - // Fixup leading and trailing groups if they show no changes. - if codes[0].Tag == 'e' { - c := codes[0] - i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2 - codes[0] = OpCode{c.Tag, max(i1, i2-n), i2, max(j1, j2-n), j2} - } - if codes[len(codes)-1].Tag == 'e' { - c := codes[len(codes)-1] - i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2 - codes[len(codes)-1] = OpCode{c.Tag, i1, min(i2, i1+n), j1, min(j2, j1+n)} - } - nn := n + n - groups := [][]OpCode{} - group := []OpCode{} - for _, c := range codes { - i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2 - // End the current group and start a new one whenever - // there is a large range with no changes. - if c.Tag == 'e' && i2-i1 > nn { - group = append(group, OpCode{c.Tag, i1, min(i2, i1+n), - j1, min(j2, j1+n)}) - groups = append(groups, group) - group = []OpCode{} - i1, j1 = max(i1, i2-n), max(j1, j2-n) - } - group = append(group, OpCode{c.Tag, i1, i2, j1, j2}) - } - if len(group) > 0 && !(len(group) == 1 && group[0].Tag == 'e') { - groups = append(groups, group) - } - return groups -} - -// Return a measure of the sequences' similarity (float in [0,1]). -// -// Where T is the total number of elements in both sequences, and -// M is the number of matches, this is 2.0*M / T. -// Note that this is 1 if the sequences are identical, and 0 if -// they have nothing in common. -// -// .Ratio() is expensive to compute if you haven't already computed -// .GetMatchingBlocks() or .GetOpCodes(), in which case you may -// want to try .QuickRatio() or .RealQuickRation() first to get an -// upper bound. -func (m *SequenceMatcher) Ratio() float64 { - matches := 0 - for _, m := range m.GetMatchingBlocks() { - matches += m.Size - } - return calculateRatio(matches, len(m.a)+len(m.b)) -} - -// Return an upper bound on ratio() relatively quickly. -// -// This isn't defined beyond that it is an upper bound on .Ratio(), and -// is faster to compute. -func (m *SequenceMatcher) QuickRatio() float64 { - // viewing a and b as multisets, set matches to the cardinality - // of their intersection; this counts the number of matches - // without regard to order, so is clearly an upper bound - if m.fullBCount == nil { - m.fullBCount = map[string]int{} - for _, s := range m.b { - m.fullBCount[s] = m.fullBCount[s] + 1 - } - } - - // avail[x] is the number of times x appears in 'b' less the - // number of times we've seen it in 'a' so far ... kinda - avail := map[string]int{} - matches := 0 - for _, s := range m.a { - n, ok := avail[s] - if !ok { - n = m.fullBCount[s] - } - avail[s] = n - 1 - if n > 0 { - matches += 1 - } - } - return calculateRatio(matches, len(m.a)+len(m.b)) -} - -// Return an upper bound on ratio() very quickly. -// -// This isn't defined beyond that it is an upper bound on .Ratio(), and -// is faster to compute than either .Ratio() or .QuickRatio(). -func (m *SequenceMatcher) RealQuickRatio() float64 { - la, lb := len(m.a), len(m.b) - return calculateRatio(min(la, lb), la+lb) -} - -// Convert range to the "ed" format -func formatRangeUnified(start, stop int) string { - // Per the diff spec at http://www.unix.org/single_unix_specification/ - beginning := start + 1 // lines start numbering with one - length := stop - start - if length == 1 { - return fmt.Sprintf("%d", beginning) - } - if length == 0 { - beginning -= 1 // empty ranges begin at line just before the range - } - return fmt.Sprintf("%d,%d", beginning, length) -} - -// Unified diff parameters -type UnifiedDiff struct { - A []string // First sequence lines - FromFile string // First file name - FromDate string // First file time - B []string // Second sequence lines - ToFile string // Second file name - ToDate string // Second file time - Eol string // Headers end of line, defaults to LF - Context int // Number of context lines -} - -// Compare two sequences of lines; generate the delta as a unified diff. -// -// Unified diffs are a compact way of showing line changes and a few -// lines of context. The number of context lines is set by 'n' which -// defaults to three. -// -// By default, the diff control lines (those with ---, +++, or @@) are -// created with a trailing newline. This is helpful so that inputs -// created from file.readlines() result in diffs that are suitable for -// file.writelines() since both the inputs and outputs have trailing -// newlines. -// -// For inputs that do not have trailing newlines, set the lineterm -// argument to "" so that the output will be uniformly newline free. -// -// The unidiff format normally has a header for filenames and modification -// times. Any or all of these may be specified using strings for -// 'fromfile', 'tofile', 'fromfiledate', and 'tofiledate'. -// The modification times are normally expressed in the ISO 8601 format. -func WriteUnifiedDiff(writer io.Writer, diff UnifiedDiff) error { - buf := bufio.NewWriter(writer) - defer buf.Flush() - wf := func(format string, args ...interface{}) error { - _, err := buf.WriteString(fmt.Sprintf(format, args...)) - return err - } - ws := func(s string) error { - _, err := buf.WriteString(s) - return err - } - - if len(diff.Eol) == 0 { - diff.Eol = "\n" - } - - started := false - m := NewMatcher(diff.A, diff.B) - for _, g := range m.GetGroupedOpCodes(diff.Context) { - if !started { - started = true - fromDate := "" - if len(diff.FromDate) > 0 { - fromDate = "\t" + diff.FromDate - } - toDate := "" - if len(diff.ToDate) > 0 { - toDate = "\t" + diff.ToDate - } - if diff.FromFile != "" || diff.ToFile != "" { - err := wf("--- %s%s%s", diff.FromFile, fromDate, diff.Eol) - if err != nil { - return err - } - err = wf("+++ %s%s%s", diff.ToFile, toDate, diff.Eol) - if err != nil { - return err - } - } - } - first, last := g[0], g[len(g)-1] - range1 := formatRangeUnified(first.I1, last.I2) - range2 := formatRangeUnified(first.J1, last.J2) - if err := wf("@@ -%s +%s @@%s", range1, range2, diff.Eol); err != nil { - return err - } - for _, c := range g { - i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2 - if c.Tag == 'e' { - for _, line := range diff.A[i1:i2] { - if err := ws(" " + line); err != nil { - return err - } - } - continue - } - if c.Tag == 'r' || c.Tag == 'd' { - for _, line := range diff.A[i1:i2] { - if err := ws("-" + line); err != nil { - return err - } - } - } - if c.Tag == 'r' || c.Tag == 'i' { - for _, line := range diff.B[j1:j2] { - if err := ws("+" + line); err != nil { - return err - } - } - } - } - } - return nil -} - -// Like WriteUnifiedDiff but returns the diff a string. -func GetUnifiedDiffString(diff UnifiedDiff) (string, error) { - w := &bytes.Buffer{} - err := WriteUnifiedDiff(w, diff) - return string(w.Bytes()), err -} - -// Convert range to the "ed" format. -func formatRangeContext(start, stop int) string { - // Per the diff spec at http://www.unix.org/single_unix_specification/ - beginning := start + 1 // lines start numbering with one - length := stop - start - if length == 0 { - beginning -= 1 // empty ranges begin at line just before the range - } - if length <= 1 { - return fmt.Sprintf("%d", beginning) - } - return fmt.Sprintf("%d,%d", beginning, beginning+length-1) -} - -type ContextDiff UnifiedDiff - -// Compare two sequences of lines; generate the delta as a context diff. -// -// Context diffs are a compact way of showing line changes and a few -// lines of context. The number of context lines is set by diff.Context -// which defaults to three. -// -// By default, the diff control lines (those with *** or ---) are -// created with a trailing newline. -// -// For inputs that do not have trailing newlines, set the diff.Eol -// argument to "" so that the output will be uniformly newline free. -// -// The context diff format normally has a header for filenames and -// modification times. Any or all of these may be specified using -// strings for diff.FromFile, diff.ToFile, diff.FromDate, diff.ToDate. -// The modification times are normally expressed in the ISO 8601 format. -// If not specified, the strings default to blanks. -func WriteContextDiff(writer io.Writer, diff ContextDiff) error { - buf := bufio.NewWriter(writer) - defer buf.Flush() - var diffErr error - wf := func(format string, args ...interface{}) { - _, err := buf.WriteString(fmt.Sprintf(format, args...)) - if diffErr == nil && err != nil { - diffErr = err - } - } - ws := func(s string) { - _, err := buf.WriteString(s) - if diffErr == nil && err != nil { - diffErr = err - } - } - - if len(diff.Eol) == 0 { - diff.Eol = "\n" - } - - prefix := map[byte]string{ - 'i': "+ ", - 'd': "- ", - 'r': "! ", - 'e': " ", - } - - started := false - m := NewMatcher(diff.A, diff.B) - for _, g := range m.GetGroupedOpCodes(diff.Context) { - if !started { - started = true - fromDate := "" - if len(diff.FromDate) > 0 { - fromDate = "\t" + diff.FromDate - } - toDate := "" - if len(diff.ToDate) > 0 { - toDate = "\t" + diff.ToDate - } - if diff.FromFile != "" || diff.ToFile != "" { - wf("*** %s%s%s", diff.FromFile, fromDate, diff.Eol) - wf("--- %s%s%s", diff.ToFile, toDate, diff.Eol) - } - } - - first, last := g[0], g[len(g)-1] - ws("***************" + diff.Eol) - - range1 := formatRangeContext(first.I1, last.I2) - wf("*** %s ****%s", range1, diff.Eol) - for _, c := range g { - if c.Tag == 'r' || c.Tag == 'd' { - for _, cc := range g { - if cc.Tag == 'i' { - continue - } - for _, line := range diff.A[cc.I1:cc.I2] { - ws(prefix[cc.Tag] + line) - } - } - break - } - } - - range2 := formatRangeContext(first.J1, last.J2) - wf("--- %s ----%s", range2, diff.Eol) - for _, c := range g { - if c.Tag == 'r' || c.Tag == 'i' { - for _, cc := range g { - if cc.Tag == 'd' { - continue - } - for _, line := range diff.B[cc.J1:cc.J2] { - ws(prefix[cc.Tag] + line) - } - } - break - } - } - } - return diffErr -} - -// Like WriteContextDiff but returns the diff a string. -func GetContextDiffString(diff ContextDiff) (string, error) { - w := &bytes.Buffer{} - err := WriteContextDiff(w, diff) - return string(w.Bytes()), err -} - -// Split a string on "\n" while preserving them. The output can be used -// as input for UnifiedDiff and ContextDiff structures. -func SplitLines(s string) []string { - lines := strings.SplitAfter(s, "\n") - lines[len(lines)-1] += "\n" - return lines -} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/LICENSE b/trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/LICENSE deleted file mode 100644 index 4b0421cf9..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2012-2020 Mat Ryer, Tyler Bunnell and contributors. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/assert/assertion_compare.go b/trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/assert/assertion_compare.go deleted file mode 100644 index 4d4b4aad6..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/assert/assertion_compare.go +++ /dev/null @@ -1,480 +0,0 @@ -package assert - -import ( - "bytes" - "fmt" - "reflect" - "time" -) - -type CompareType int - -const ( - compareLess CompareType = iota - 1 - compareEqual - compareGreater -) - -var ( - intType = reflect.TypeOf(int(1)) - int8Type = reflect.TypeOf(int8(1)) - int16Type = reflect.TypeOf(int16(1)) - int32Type = reflect.TypeOf(int32(1)) - int64Type = reflect.TypeOf(int64(1)) - - uintType = reflect.TypeOf(uint(1)) - uint8Type = reflect.TypeOf(uint8(1)) - uint16Type = reflect.TypeOf(uint16(1)) - uint32Type = reflect.TypeOf(uint32(1)) - uint64Type = reflect.TypeOf(uint64(1)) - - uintptrType = reflect.TypeOf(uintptr(1)) - - float32Type = reflect.TypeOf(float32(1)) - float64Type = reflect.TypeOf(float64(1)) - - stringType = reflect.TypeOf("") - - timeType = reflect.TypeOf(time.Time{}) - bytesType = reflect.TypeOf([]byte{}) -) - -func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) { - obj1Value := reflect.ValueOf(obj1) - obj2Value := reflect.ValueOf(obj2) - - // throughout this switch we try and avoid calling .Convert() if possible, - // as this has a pretty big performance impact - switch kind { - case reflect.Int: - { - intobj1, ok := obj1.(int) - if !ok { - intobj1 = obj1Value.Convert(intType).Interface().(int) - } - intobj2, ok := obj2.(int) - if !ok { - intobj2 = obj2Value.Convert(intType).Interface().(int) - } - if intobj1 > intobj2 { - return compareGreater, true - } - if intobj1 == intobj2 { - return compareEqual, true - } - if intobj1 < intobj2 { - return compareLess, true - } - } - case reflect.Int8: - { - int8obj1, ok := obj1.(int8) - if !ok { - int8obj1 = obj1Value.Convert(int8Type).Interface().(int8) - } - int8obj2, ok := obj2.(int8) - if !ok { - int8obj2 = obj2Value.Convert(int8Type).Interface().(int8) - } - if int8obj1 > int8obj2 { - return compareGreater, true - } - if int8obj1 == int8obj2 { - return compareEqual, true - } - if int8obj1 < int8obj2 { - return compareLess, true - } - } - case reflect.Int16: - { - int16obj1, ok := obj1.(int16) - if !ok { - int16obj1 = obj1Value.Convert(int16Type).Interface().(int16) - } - int16obj2, ok := obj2.(int16) - if !ok { - int16obj2 = obj2Value.Convert(int16Type).Interface().(int16) - } - if int16obj1 > int16obj2 { - return compareGreater, true - } - if int16obj1 == int16obj2 { - return compareEqual, true - } - if int16obj1 < int16obj2 { - return compareLess, true - } - } - case reflect.Int32: - { - int32obj1, ok := obj1.(int32) - if !ok { - int32obj1 = obj1Value.Convert(int32Type).Interface().(int32) - } - int32obj2, ok := obj2.(int32) - if !ok { - int32obj2 = obj2Value.Convert(int32Type).Interface().(int32) - } - if int32obj1 > int32obj2 { - return compareGreater, true - } - if int32obj1 == int32obj2 { - return compareEqual, true - } - if int32obj1 < int32obj2 { - return compareLess, true - } - } - case reflect.Int64: - { - int64obj1, ok := obj1.(int64) - if !ok { - int64obj1 = obj1Value.Convert(int64Type).Interface().(int64) - } - int64obj2, ok := obj2.(int64) - if !ok { - int64obj2 = obj2Value.Convert(int64Type).Interface().(int64) - } - if int64obj1 > int64obj2 { - return compareGreater, true - } - if int64obj1 == int64obj2 { - return compareEqual, true - } - if int64obj1 < int64obj2 { - return compareLess, true - } - } - case reflect.Uint: - { - uintobj1, ok := obj1.(uint) - if !ok { - uintobj1 = obj1Value.Convert(uintType).Interface().(uint) - } - uintobj2, ok := obj2.(uint) - if !ok { - uintobj2 = obj2Value.Convert(uintType).Interface().(uint) - } - if uintobj1 > uintobj2 { - return compareGreater, true - } - if uintobj1 == uintobj2 { - return compareEqual, true - } - if uintobj1 < uintobj2 { - return compareLess, true - } - } - case reflect.Uint8: - { - uint8obj1, ok := obj1.(uint8) - if !ok { - uint8obj1 = obj1Value.Convert(uint8Type).Interface().(uint8) - } - uint8obj2, ok := obj2.(uint8) - if !ok { - uint8obj2 = obj2Value.Convert(uint8Type).Interface().(uint8) - } - if uint8obj1 > uint8obj2 { - return compareGreater, true - } - if uint8obj1 == uint8obj2 { - return compareEqual, true - } - if uint8obj1 < uint8obj2 { - return compareLess, true - } - } - case reflect.Uint16: - { - uint16obj1, ok := obj1.(uint16) - if !ok { - uint16obj1 = obj1Value.Convert(uint16Type).Interface().(uint16) - } - uint16obj2, ok := obj2.(uint16) - if !ok { - uint16obj2 = obj2Value.Convert(uint16Type).Interface().(uint16) - } - if uint16obj1 > uint16obj2 { - return compareGreater, true - } - if uint16obj1 == uint16obj2 { - return compareEqual, true - } - if uint16obj1 < uint16obj2 { - return compareLess, true - } - } - case reflect.Uint32: - { - uint32obj1, ok := obj1.(uint32) - if !ok { - uint32obj1 = obj1Value.Convert(uint32Type).Interface().(uint32) - } - uint32obj2, ok := obj2.(uint32) - if !ok { - uint32obj2 = obj2Value.Convert(uint32Type).Interface().(uint32) - } - if uint32obj1 > uint32obj2 { - return compareGreater, true - } - if uint32obj1 == uint32obj2 { - return compareEqual, true - } - if uint32obj1 < uint32obj2 { - return compareLess, true - } - } - case reflect.Uint64: - { - uint64obj1, ok := obj1.(uint64) - if !ok { - uint64obj1 = obj1Value.Convert(uint64Type).Interface().(uint64) - } - uint64obj2, ok := obj2.(uint64) - if !ok { - uint64obj2 = obj2Value.Convert(uint64Type).Interface().(uint64) - } - if uint64obj1 > uint64obj2 { - return compareGreater, true - } - if uint64obj1 == uint64obj2 { - return compareEqual, true - } - if uint64obj1 < uint64obj2 { - return compareLess, true - } - } - case reflect.Float32: - { - float32obj1, ok := obj1.(float32) - if !ok { - float32obj1 = obj1Value.Convert(float32Type).Interface().(float32) - } - float32obj2, ok := obj2.(float32) - if !ok { - float32obj2 = obj2Value.Convert(float32Type).Interface().(float32) - } - if float32obj1 > float32obj2 { - return compareGreater, true - } - if float32obj1 == float32obj2 { - return compareEqual, true - } - if float32obj1 < float32obj2 { - return compareLess, true - } - } - case reflect.Float64: - { - float64obj1, ok := obj1.(float64) - if !ok { - float64obj1 = obj1Value.Convert(float64Type).Interface().(float64) - } - float64obj2, ok := obj2.(float64) - if !ok { - float64obj2 = obj2Value.Convert(float64Type).Interface().(float64) - } - if float64obj1 > float64obj2 { - return compareGreater, true - } - if float64obj1 == float64obj2 { - return compareEqual, true - } - if float64obj1 < float64obj2 { - return compareLess, true - } - } - case reflect.String: - { - stringobj1, ok := obj1.(string) - if !ok { - stringobj1 = obj1Value.Convert(stringType).Interface().(string) - } - stringobj2, ok := obj2.(string) - if !ok { - stringobj2 = obj2Value.Convert(stringType).Interface().(string) - } - if stringobj1 > stringobj2 { - return compareGreater, true - } - if stringobj1 == stringobj2 { - return compareEqual, true - } - if stringobj1 < stringobj2 { - return compareLess, true - } - } - // Check for known struct types we can check for compare results. - case reflect.Struct: - { - // All structs enter here. We're not interested in most types. - if !obj1Value.CanConvert(timeType) { - break - } - - // time.Time can be compared! - timeObj1, ok := obj1.(time.Time) - if !ok { - timeObj1 = obj1Value.Convert(timeType).Interface().(time.Time) - } - - timeObj2, ok := obj2.(time.Time) - if !ok { - timeObj2 = obj2Value.Convert(timeType).Interface().(time.Time) - } - - return compare(timeObj1.UnixNano(), timeObj2.UnixNano(), reflect.Int64) - } - case reflect.Slice: - { - // We only care about the []byte type. - if !obj1Value.CanConvert(bytesType) { - break - } - - // []byte can be compared! - bytesObj1, ok := obj1.([]byte) - if !ok { - bytesObj1 = obj1Value.Convert(bytesType).Interface().([]byte) - - } - bytesObj2, ok := obj2.([]byte) - if !ok { - bytesObj2 = obj2Value.Convert(bytesType).Interface().([]byte) - } - - return CompareType(bytes.Compare(bytesObj1, bytesObj2)), true - } - case reflect.Uintptr: - { - uintptrObj1, ok := obj1.(uintptr) - if !ok { - uintptrObj1 = obj1Value.Convert(uintptrType).Interface().(uintptr) - } - uintptrObj2, ok := obj2.(uintptr) - if !ok { - uintptrObj2 = obj2Value.Convert(uintptrType).Interface().(uintptr) - } - if uintptrObj1 > uintptrObj2 { - return compareGreater, true - } - if uintptrObj1 == uintptrObj2 { - return compareEqual, true - } - if uintptrObj1 < uintptrObj2 { - return compareLess, true - } - } - } - - return compareEqual, false -} - -// Greater asserts that the first element is greater than the second -// -// assert.Greater(t, 2, 1) -// assert.Greater(t, float64(2), float64(1)) -// assert.Greater(t, "b", "a") -func Greater(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return compareTwoValues(t, e1, e2, []CompareType{compareGreater}, "\"%v\" is not greater than \"%v\"", msgAndArgs...) -} - -// GreaterOrEqual asserts that the first element is greater than or equal to the second -// -// assert.GreaterOrEqual(t, 2, 1) -// assert.GreaterOrEqual(t, 2, 2) -// assert.GreaterOrEqual(t, "b", "a") -// assert.GreaterOrEqual(t, "b", "b") -func GreaterOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return compareTwoValues(t, e1, e2, []CompareType{compareGreater, compareEqual}, "\"%v\" is not greater than or equal to \"%v\"", msgAndArgs...) -} - -// Less asserts that the first element is less than the second -// -// assert.Less(t, 1, 2) -// assert.Less(t, float64(1), float64(2)) -// assert.Less(t, "a", "b") -func Less(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return compareTwoValues(t, e1, e2, []CompareType{compareLess}, "\"%v\" is not less than \"%v\"", msgAndArgs...) -} - -// LessOrEqual asserts that the first element is less than or equal to the second -// -// assert.LessOrEqual(t, 1, 2) -// assert.LessOrEqual(t, 2, 2) -// assert.LessOrEqual(t, "a", "b") -// assert.LessOrEqual(t, "b", "b") -func LessOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return compareTwoValues(t, e1, e2, []CompareType{compareLess, compareEqual}, "\"%v\" is not less than or equal to \"%v\"", msgAndArgs...) -} - -// Positive asserts that the specified element is positive -// -// assert.Positive(t, 1) -// assert.Positive(t, 1.23) -func Positive(t TestingT, e interface{}, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - zero := reflect.Zero(reflect.TypeOf(e)) - return compareTwoValues(t, e, zero.Interface(), []CompareType{compareGreater}, "\"%v\" is not positive", msgAndArgs...) -} - -// Negative asserts that the specified element is negative -// -// assert.Negative(t, -1) -// assert.Negative(t, -1.23) -func Negative(t TestingT, e interface{}, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - zero := reflect.Zero(reflect.TypeOf(e)) - return compareTwoValues(t, e, zero.Interface(), []CompareType{compareLess}, "\"%v\" is not negative", msgAndArgs...) -} - -func compareTwoValues(t TestingT, e1 interface{}, e2 interface{}, allowedComparesResults []CompareType, failMessage string, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - - e1Kind := reflect.ValueOf(e1).Kind() - e2Kind := reflect.ValueOf(e2).Kind() - if e1Kind != e2Kind { - return Fail(t, "Elements should be the same type", msgAndArgs...) - } - - compareResult, isComparable := compare(e1, e2, e1Kind) - if !isComparable { - return Fail(t, fmt.Sprintf("Can not compare type \"%s\"", reflect.TypeOf(e1)), msgAndArgs...) - } - - if !containsValue(allowedComparesResults, compareResult) { - return Fail(t, fmt.Sprintf(failMessage, e1, e2), msgAndArgs...) - } - - return true -} - -func containsValue(values []CompareType, value CompareType) bool { - for _, v := range values { - if v == value { - return true - } - } - - return false -} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/assert/assertion_format.go b/trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/assert/assertion_format.go deleted file mode 100644 index 3ddab109a..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/assert/assertion_format.go +++ /dev/null @@ -1,815 +0,0 @@ -// Code generated with github.com/stretchr/testify/_codegen; DO NOT EDIT. - -package assert - -import ( - http "net/http" - url "net/url" - time "time" -) - -// Conditionf uses a Comparison to assert a complex condition. -func Conditionf(t TestingT, comp Comparison, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return Condition(t, comp, append([]interface{}{msg}, args...)...) -} - -// Containsf asserts that the specified string, list(array, slice...) or map contains the -// specified substring or element. -// -// assert.Containsf(t, "Hello World", "World", "error message %s", "formatted") -// assert.Containsf(t, ["Hello", "World"], "World", "error message %s", "formatted") -// assert.Containsf(t, {"Hello": "World"}, "Hello", "error message %s", "formatted") -func Containsf(t TestingT, s interface{}, contains interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return Contains(t, s, contains, append([]interface{}{msg}, args...)...) -} - -// DirExistsf checks whether a directory exists in the given path. It also fails -// if the path is a file rather a directory or there is an error checking whether it exists. -func DirExistsf(t TestingT, path string, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return DirExists(t, path, append([]interface{}{msg}, args...)...) -} - -// ElementsMatchf asserts that the specified listA(array, slice...) is equal to specified -// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, -// the number of appearances of each of them in both lists should match. -// -// assert.ElementsMatchf(t, [1, 3, 2, 3], [1, 3, 3, 2], "error message %s", "formatted") -func ElementsMatchf(t TestingT, listA interface{}, listB interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return ElementsMatch(t, listA, listB, append([]interface{}{msg}, args...)...) -} - -// Emptyf asserts that the specified object is empty. I.e. nil, "", false, 0 or either -// a slice or a channel with len == 0. -// -// assert.Emptyf(t, obj, "error message %s", "formatted") -func Emptyf(t TestingT, object interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return Empty(t, object, append([]interface{}{msg}, args...)...) -} - -// Equalf asserts that two objects are equal. -// -// assert.Equalf(t, 123, 123, "error message %s", "formatted") -// -// Pointer variable equality is determined based on the equality of the -// referenced values (as opposed to the memory addresses). Function equality -// cannot be determined and will always fail. -func Equalf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return Equal(t, expected, actual, append([]interface{}{msg}, args...)...) -} - -// EqualErrorf asserts that a function returned an error (i.e. not `nil`) -// and that it is equal to the provided error. -// -// actualObj, err := SomeFunction() -// assert.EqualErrorf(t, err, expectedErrorString, "error message %s", "formatted") -func EqualErrorf(t TestingT, theError error, errString string, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return EqualError(t, theError, errString, append([]interface{}{msg}, args...)...) -} - -// EqualExportedValuesf asserts that the types of two objects are equal and their public -// fields are also equal. This is useful for comparing structs that have private fields -// that could potentially differ. -// -// type S struct { -// Exported int -// notExported int -// } -// assert.EqualExportedValuesf(t, S{1, 2}, S{1, 3}, "error message %s", "formatted") => true -// assert.EqualExportedValuesf(t, S{1, 2}, S{2, 3}, "error message %s", "formatted") => false -func EqualExportedValuesf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return EqualExportedValues(t, expected, actual, append([]interface{}{msg}, args...)...) -} - -// EqualValuesf asserts that two objects are equal or convertible to the same types -// and equal. -// -// assert.EqualValuesf(t, uint32(123), int32(123), "error message %s", "formatted") -func EqualValuesf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return EqualValues(t, expected, actual, append([]interface{}{msg}, args...)...) -} - -// Errorf asserts that a function returned an error (i.e. not `nil`). -// -// actualObj, err := SomeFunction() -// if assert.Errorf(t, err, "error message %s", "formatted") { -// assert.Equal(t, expectedErrorf, err) -// } -func Errorf(t TestingT, err error, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return Error(t, err, append([]interface{}{msg}, args...)...) -} - -// ErrorAsf asserts that at least one of the errors in err's chain matches target, and if so, sets target to that error value. -// This is a wrapper for errors.As. -func ErrorAsf(t TestingT, err error, target interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return ErrorAs(t, err, target, append([]interface{}{msg}, args...)...) -} - -// ErrorContainsf asserts that a function returned an error (i.e. not `nil`) -// and that the error contains the specified substring. -// -// actualObj, err := SomeFunction() -// assert.ErrorContainsf(t, err, expectedErrorSubString, "error message %s", "formatted") -func ErrorContainsf(t TestingT, theError error, contains string, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return ErrorContains(t, theError, contains, append([]interface{}{msg}, args...)...) -} - -// ErrorIsf asserts that at least one of the errors in err's chain matches target. -// This is a wrapper for errors.Is. -func ErrorIsf(t TestingT, err error, target error, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return ErrorIs(t, err, target, append([]interface{}{msg}, args...)...) -} - -// Eventuallyf asserts that given condition will be met in waitFor time, -// periodically checking target function each tick. -// -// assert.Eventuallyf(t, func() bool { return true; }, time.Second, 10*time.Millisecond, "error message %s", "formatted") -func Eventuallyf(t TestingT, condition func() bool, waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return Eventually(t, condition, waitFor, tick, append([]interface{}{msg}, args...)...) -} - -// EventuallyWithTf asserts that given condition will be met in waitFor time, -// periodically checking target function each tick. In contrast to Eventually, -// it supplies a CollectT to the condition function, so that the condition -// function can use the CollectT to call other assertions. -// The condition is considered "met" if no errors are raised in a tick. -// The supplied CollectT collects all errors from one tick (if there are any). -// If the condition is not met before waitFor, the collected errors of -// the last tick are copied to t. -// -// externalValue := false -// go func() { -// time.Sleep(8*time.Second) -// externalValue = true -// }() -// assert.EventuallyWithTf(t, func(c *assert.CollectT, "error message %s", "formatted") { -// // add assertions as needed; any assertion failure will fail the current tick -// assert.True(c, externalValue, "expected 'externalValue' to be true") -// }, 1*time.Second, 10*time.Second, "external state has not changed to 'true'; still false") -func EventuallyWithTf(t TestingT, condition func(collect *CollectT), waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return EventuallyWithT(t, condition, waitFor, tick, append([]interface{}{msg}, args...)...) -} - -// Exactlyf asserts that two objects are equal in value and type. -// -// assert.Exactlyf(t, int32(123), int64(123), "error message %s", "formatted") -func Exactlyf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return Exactly(t, expected, actual, append([]interface{}{msg}, args...)...) -} - -// Failf reports a failure through -func Failf(t TestingT, failureMessage string, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return Fail(t, failureMessage, append([]interface{}{msg}, args...)...) -} - -// FailNowf fails test -func FailNowf(t TestingT, failureMessage string, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return FailNow(t, failureMessage, append([]interface{}{msg}, args...)...) -} - -// Falsef asserts that the specified value is false. -// -// assert.Falsef(t, myBool, "error message %s", "formatted") -func Falsef(t TestingT, value bool, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return False(t, value, append([]interface{}{msg}, args...)...) -} - -// FileExistsf checks whether a file exists in the given path. It also fails if -// the path points to a directory or there is an error when trying to check the file. -func FileExistsf(t TestingT, path string, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return FileExists(t, path, append([]interface{}{msg}, args...)...) -} - -// Greaterf asserts that the first element is greater than the second -// -// assert.Greaterf(t, 2, 1, "error message %s", "formatted") -// assert.Greaterf(t, float64(2), float64(1), "error message %s", "formatted") -// assert.Greaterf(t, "b", "a", "error message %s", "formatted") -func Greaterf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return Greater(t, e1, e2, append([]interface{}{msg}, args...)...) -} - -// GreaterOrEqualf asserts that the first element is greater than or equal to the second -// -// assert.GreaterOrEqualf(t, 2, 1, "error message %s", "formatted") -// assert.GreaterOrEqualf(t, 2, 2, "error message %s", "formatted") -// assert.GreaterOrEqualf(t, "b", "a", "error message %s", "formatted") -// assert.GreaterOrEqualf(t, "b", "b", "error message %s", "formatted") -func GreaterOrEqualf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return GreaterOrEqual(t, e1, e2, append([]interface{}{msg}, args...)...) -} - -// HTTPBodyContainsf asserts that a specified handler returns a -// body that contains a string. -// -// assert.HTTPBodyContainsf(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). -func HTTPBodyContainsf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return HTTPBodyContains(t, handler, method, url, values, str, append([]interface{}{msg}, args...)...) -} - -// HTTPBodyNotContainsf asserts that a specified handler returns a -// body that does not contain a string. -// -// assert.HTTPBodyNotContainsf(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). -func HTTPBodyNotContainsf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return HTTPBodyNotContains(t, handler, method, url, values, str, append([]interface{}{msg}, args...)...) -} - -// HTTPErrorf asserts that a specified handler returns an error status code. -// -// assert.HTTPErrorf(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} -// -// Returns whether the assertion was successful (true) or not (false). -func HTTPErrorf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return HTTPError(t, handler, method, url, values, append([]interface{}{msg}, args...)...) -} - -// HTTPRedirectf asserts that a specified handler returns a redirect status code. -// -// assert.HTTPRedirectf(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} -// -// Returns whether the assertion was successful (true) or not (false). -func HTTPRedirectf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return HTTPRedirect(t, handler, method, url, values, append([]interface{}{msg}, args...)...) -} - -// HTTPStatusCodef asserts that a specified handler returns a specified status code. -// -// assert.HTTPStatusCodef(t, myHandler, "GET", "/notImplemented", nil, 501, "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). -func HTTPStatusCodef(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, statuscode int, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return HTTPStatusCode(t, handler, method, url, values, statuscode, append([]interface{}{msg}, args...)...) -} - -// HTTPSuccessf asserts that a specified handler returns a success status code. -// -// assert.HTTPSuccessf(t, myHandler, "POST", "http://www.google.com", nil, "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). -func HTTPSuccessf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return HTTPSuccess(t, handler, method, url, values, append([]interface{}{msg}, args...)...) -} - -// Implementsf asserts that an object is implemented by the specified interface. -// -// assert.Implementsf(t, (*MyInterface)(nil), new(MyObject), "error message %s", "formatted") -func Implementsf(t TestingT, interfaceObject interface{}, object interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return Implements(t, interfaceObject, object, append([]interface{}{msg}, args...)...) -} - -// InDeltaf asserts that the two numerals are within delta of each other. -// -// assert.InDeltaf(t, math.Pi, 22/7.0, 0.01, "error message %s", "formatted") -func InDeltaf(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return InDelta(t, expected, actual, delta, append([]interface{}{msg}, args...)...) -} - -// InDeltaMapValuesf is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys. -func InDeltaMapValuesf(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return InDeltaMapValues(t, expected, actual, delta, append([]interface{}{msg}, args...)...) -} - -// InDeltaSlicef is the same as InDelta, except it compares two slices. -func InDeltaSlicef(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return InDeltaSlice(t, expected, actual, delta, append([]interface{}{msg}, args...)...) -} - -// InEpsilonf asserts that expected and actual have a relative error less than epsilon -func InEpsilonf(t TestingT, expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return InEpsilon(t, expected, actual, epsilon, append([]interface{}{msg}, args...)...) -} - -// InEpsilonSlicef is the same as InEpsilon, except it compares each value from two slices. -func InEpsilonSlicef(t TestingT, expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return InEpsilonSlice(t, expected, actual, epsilon, append([]interface{}{msg}, args...)...) -} - -// IsDecreasingf asserts that the collection is decreasing -// -// assert.IsDecreasingf(t, []int{2, 1, 0}, "error message %s", "formatted") -// assert.IsDecreasingf(t, []float{2, 1}, "error message %s", "formatted") -// assert.IsDecreasingf(t, []string{"b", "a"}, "error message %s", "formatted") -func IsDecreasingf(t TestingT, object interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return IsDecreasing(t, object, append([]interface{}{msg}, args...)...) -} - -// IsIncreasingf asserts that the collection is increasing -// -// assert.IsIncreasingf(t, []int{1, 2, 3}, "error message %s", "formatted") -// assert.IsIncreasingf(t, []float{1, 2}, "error message %s", "formatted") -// assert.IsIncreasingf(t, []string{"a", "b"}, "error message %s", "formatted") -func IsIncreasingf(t TestingT, object interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return IsIncreasing(t, object, append([]interface{}{msg}, args...)...) -} - -// IsNonDecreasingf asserts that the collection is not decreasing -// -// assert.IsNonDecreasingf(t, []int{1, 1, 2}, "error message %s", "formatted") -// assert.IsNonDecreasingf(t, []float{1, 2}, "error message %s", "formatted") -// assert.IsNonDecreasingf(t, []string{"a", "b"}, "error message %s", "formatted") -func IsNonDecreasingf(t TestingT, object interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return IsNonDecreasing(t, object, append([]interface{}{msg}, args...)...) -} - -// IsNonIncreasingf asserts that the collection is not increasing -// -// assert.IsNonIncreasingf(t, []int{2, 1, 1}, "error message %s", "formatted") -// assert.IsNonIncreasingf(t, []float{2, 1}, "error message %s", "formatted") -// assert.IsNonIncreasingf(t, []string{"b", "a"}, "error message %s", "formatted") -func IsNonIncreasingf(t TestingT, object interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return IsNonIncreasing(t, object, append([]interface{}{msg}, args...)...) -} - -// IsTypef asserts that the specified objects are of the same type. -func IsTypef(t TestingT, expectedType interface{}, object interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return IsType(t, expectedType, object, append([]interface{}{msg}, args...)...) -} - -// JSONEqf asserts that two JSON strings are equivalent. -// -// assert.JSONEqf(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`, "error message %s", "formatted") -func JSONEqf(t TestingT, expected string, actual string, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return JSONEq(t, expected, actual, append([]interface{}{msg}, args...)...) -} - -// Lenf asserts that the specified object has specific length. -// Lenf also fails if the object has a type that len() not accept. -// -// assert.Lenf(t, mySlice, 3, "error message %s", "formatted") -func Lenf(t TestingT, object interface{}, length int, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return Len(t, object, length, append([]interface{}{msg}, args...)...) -} - -// Lessf asserts that the first element is less than the second -// -// assert.Lessf(t, 1, 2, "error message %s", "formatted") -// assert.Lessf(t, float64(1), float64(2), "error message %s", "formatted") -// assert.Lessf(t, "a", "b", "error message %s", "formatted") -func Lessf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return Less(t, e1, e2, append([]interface{}{msg}, args...)...) -} - -// LessOrEqualf asserts that the first element is less than or equal to the second -// -// assert.LessOrEqualf(t, 1, 2, "error message %s", "formatted") -// assert.LessOrEqualf(t, 2, 2, "error message %s", "formatted") -// assert.LessOrEqualf(t, "a", "b", "error message %s", "formatted") -// assert.LessOrEqualf(t, "b", "b", "error message %s", "formatted") -func LessOrEqualf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return LessOrEqual(t, e1, e2, append([]interface{}{msg}, args...)...) -} - -// Negativef asserts that the specified element is negative -// -// assert.Negativef(t, -1, "error message %s", "formatted") -// assert.Negativef(t, -1.23, "error message %s", "formatted") -func Negativef(t TestingT, e interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return Negative(t, e, append([]interface{}{msg}, args...)...) -} - -// Neverf asserts that the given condition doesn't satisfy in waitFor time, -// periodically checking the target function each tick. -// -// assert.Neverf(t, func() bool { return false; }, time.Second, 10*time.Millisecond, "error message %s", "formatted") -func Neverf(t TestingT, condition func() bool, waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return Never(t, condition, waitFor, tick, append([]interface{}{msg}, args...)...) -} - -// Nilf asserts that the specified object is nil. -// -// assert.Nilf(t, err, "error message %s", "formatted") -func Nilf(t TestingT, object interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return Nil(t, object, append([]interface{}{msg}, args...)...) -} - -// NoDirExistsf checks whether a directory does not exist in the given path. -// It fails if the path points to an existing _directory_ only. -func NoDirExistsf(t TestingT, path string, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return NoDirExists(t, path, append([]interface{}{msg}, args...)...) -} - -// NoErrorf asserts that a function returned no error (i.e. `nil`). -// -// actualObj, err := SomeFunction() -// if assert.NoErrorf(t, err, "error message %s", "formatted") { -// assert.Equal(t, expectedObj, actualObj) -// } -func NoErrorf(t TestingT, err error, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return NoError(t, err, append([]interface{}{msg}, args...)...) -} - -// NoFileExistsf checks whether a file does not exist in a given path. It fails -// if the path points to an existing _file_ only. -func NoFileExistsf(t TestingT, path string, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return NoFileExists(t, path, append([]interface{}{msg}, args...)...) -} - -// NotContainsf asserts that the specified string, list(array, slice...) or map does NOT contain the -// specified substring or element. -// -// assert.NotContainsf(t, "Hello World", "Earth", "error message %s", "formatted") -// assert.NotContainsf(t, ["Hello", "World"], "Earth", "error message %s", "formatted") -// assert.NotContainsf(t, {"Hello": "World"}, "Earth", "error message %s", "formatted") -func NotContainsf(t TestingT, s interface{}, contains interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return NotContains(t, s, contains, append([]interface{}{msg}, args...)...) -} - -// NotEmptyf asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either -// a slice or a channel with len == 0. -// -// if assert.NotEmptyf(t, obj, "error message %s", "formatted") { -// assert.Equal(t, "two", obj[1]) -// } -func NotEmptyf(t TestingT, object interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return NotEmpty(t, object, append([]interface{}{msg}, args...)...) -} - -// NotEqualf asserts that the specified values are NOT equal. -// -// assert.NotEqualf(t, obj1, obj2, "error message %s", "formatted") -// -// Pointer variable equality is determined based on the equality of the -// referenced values (as opposed to the memory addresses). -func NotEqualf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return NotEqual(t, expected, actual, append([]interface{}{msg}, args...)...) -} - -// NotEqualValuesf asserts that two objects are not equal even when converted to the same type -// -// assert.NotEqualValuesf(t, obj1, obj2, "error message %s", "formatted") -func NotEqualValuesf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return NotEqualValues(t, expected, actual, append([]interface{}{msg}, args...)...) -} - -// NotErrorIsf asserts that at none of the errors in err's chain matches target. -// This is a wrapper for errors.Is. -func NotErrorIsf(t TestingT, err error, target error, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return NotErrorIs(t, err, target, append([]interface{}{msg}, args...)...) -} - -// NotImplementsf asserts that an object does not implement the specified interface. -// -// assert.NotImplementsf(t, (*MyInterface)(nil), new(MyObject), "error message %s", "formatted") -func NotImplementsf(t TestingT, interfaceObject interface{}, object interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return NotImplements(t, interfaceObject, object, append([]interface{}{msg}, args...)...) -} - -// NotNilf asserts that the specified object is not nil. -// -// assert.NotNilf(t, err, "error message %s", "formatted") -func NotNilf(t TestingT, object interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return NotNil(t, object, append([]interface{}{msg}, args...)...) -} - -// NotPanicsf asserts that the code inside the specified PanicTestFunc does NOT panic. -// -// assert.NotPanicsf(t, func(){ RemainCalm() }, "error message %s", "formatted") -func NotPanicsf(t TestingT, f PanicTestFunc, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return NotPanics(t, f, append([]interface{}{msg}, args...)...) -} - -// NotRegexpf asserts that a specified regexp does not match a string. -// -// assert.NotRegexpf(t, regexp.MustCompile("starts"), "it's starting", "error message %s", "formatted") -// assert.NotRegexpf(t, "^start", "it's not starting", "error message %s", "formatted") -func NotRegexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return NotRegexp(t, rx, str, append([]interface{}{msg}, args...)...) -} - -// NotSamef asserts that two pointers do not reference the same object. -// -// assert.NotSamef(t, ptr1, ptr2, "error message %s", "formatted") -// -// Both arguments must be pointer variables. Pointer variable sameness is -// determined based on the equality of both type and value. -func NotSamef(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return NotSame(t, expected, actual, append([]interface{}{msg}, args...)...) -} - -// NotSubsetf asserts that the specified list(array, slice...) or map does NOT -// contain all elements given in the specified subset list(array, slice...) or -// map. -// -// assert.NotSubsetf(t, [1, 3, 4], [1, 2], "error message %s", "formatted") -// assert.NotSubsetf(t, {"x": 1, "y": 2}, {"z": 3}, "error message %s", "formatted") -func NotSubsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return NotSubset(t, list, subset, append([]interface{}{msg}, args...)...) -} - -// NotZerof asserts that i is not the zero value for its type. -func NotZerof(t TestingT, i interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return NotZero(t, i, append([]interface{}{msg}, args...)...) -} - -// Panicsf asserts that the code inside the specified PanicTestFunc panics. -// -// assert.Panicsf(t, func(){ GoCrazy() }, "error message %s", "formatted") -func Panicsf(t TestingT, f PanicTestFunc, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return Panics(t, f, append([]interface{}{msg}, args...)...) -} - -// PanicsWithErrorf asserts that the code inside the specified PanicTestFunc -// panics, and that the recovered panic value is an error that satisfies the -// EqualError comparison. -// -// assert.PanicsWithErrorf(t, "crazy error", func(){ GoCrazy() }, "error message %s", "formatted") -func PanicsWithErrorf(t TestingT, errString string, f PanicTestFunc, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return PanicsWithError(t, errString, f, append([]interface{}{msg}, args...)...) -} - -// PanicsWithValuef asserts that the code inside the specified PanicTestFunc panics, and that -// the recovered panic value equals the expected panic value. -// -// assert.PanicsWithValuef(t, "crazy error", func(){ GoCrazy() }, "error message %s", "formatted") -func PanicsWithValuef(t TestingT, expected interface{}, f PanicTestFunc, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return PanicsWithValue(t, expected, f, append([]interface{}{msg}, args...)...) -} - -// Positivef asserts that the specified element is positive -// -// assert.Positivef(t, 1, "error message %s", "formatted") -// assert.Positivef(t, 1.23, "error message %s", "formatted") -func Positivef(t TestingT, e interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return Positive(t, e, append([]interface{}{msg}, args...)...) -} - -// Regexpf asserts that a specified regexp matches a string. -// -// assert.Regexpf(t, regexp.MustCompile("start"), "it's starting", "error message %s", "formatted") -// assert.Regexpf(t, "start...$", "it's not starting", "error message %s", "formatted") -func Regexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return Regexp(t, rx, str, append([]interface{}{msg}, args...)...) -} - -// Samef asserts that two pointers reference the same object. -// -// assert.Samef(t, ptr1, ptr2, "error message %s", "formatted") -// -// Both arguments must be pointer variables. Pointer variable sameness is -// determined based on the equality of both type and value. -func Samef(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return Same(t, expected, actual, append([]interface{}{msg}, args...)...) -} - -// Subsetf asserts that the specified list(array, slice...) or map contains all -// elements given in the specified subset list(array, slice...) or map. -// -// assert.Subsetf(t, [1, 2, 3], [1, 2], "error message %s", "formatted") -// assert.Subsetf(t, {"x": 1, "y": 2}, {"x": 1}, "error message %s", "formatted") -func Subsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return Subset(t, list, subset, append([]interface{}{msg}, args...)...) -} - -// Truef asserts that the specified value is true. -// -// assert.Truef(t, myBool, "error message %s", "formatted") -func Truef(t TestingT, value bool, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return True(t, value, append([]interface{}{msg}, args...)...) -} - -// WithinDurationf asserts that the two times are within duration delta of each other. -// -// assert.WithinDurationf(t, time.Now(), time.Now(), 10*time.Second, "error message %s", "formatted") -func WithinDurationf(t TestingT, expected time.Time, actual time.Time, delta time.Duration, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return WithinDuration(t, expected, actual, delta, append([]interface{}{msg}, args...)...) -} - -// WithinRangef asserts that a time is within a time range (inclusive). -// -// assert.WithinRangef(t, time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second), "error message %s", "formatted") -func WithinRangef(t TestingT, actual time.Time, start time.Time, end time.Time, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return WithinRange(t, actual, start, end, append([]interface{}{msg}, args...)...) -} - -// YAMLEqf asserts that two YAML strings are equivalent. -func YAMLEqf(t TestingT, expected string, actual string, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return YAMLEq(t, expected, actual, append([]interface{}{msg}, args...)...) -} - -// Zerof asserts that i is the zero value for its type. -func Zerof(t TestingT, i interface{}, msg string, args ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return Zero(t, i, append([]interface{}{msg}, args...)...) -} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/assert/assertion_format.go.tmpl b/trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/assert/assertion_format.go.tmpl deleted file mode 100644 index d2bb0b817..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/assert/assertion_format.go.tmpl +++ /dev/null @@ -1,5 +0,0 @@ -{{.CommentFormat}} -func {{.DocInfo.Name}}f(t TestingT, {{.ParamsFormat}}) bool { - if h, ok := t.(tHelper); ok { h.Helper() } - return {{.DocInfo.Name}}(t, {{.ForwardedParamsFormat}}) -} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/assert/assertion_forward.go b/trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/assert/assertion_forward.go deleted file mode 100644 index a84e09bd4..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/assert/assertion_forward.go +++ /dev/null @@ -1,1621 +0,0 @@ -// Code generated with github.com/stretchr/testify/_codegen; DO NOT EDIT. - -package assert - -import ( - http "net/http" - url "net/url" - time "time" -) - -// Condition uses a Comparison to assert a complex condition. -func (a *Assertions) Condition(comp Comparison, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Condition(a.t, comp, msgAndArgs...) -} - -// Conditionf uses a Comparison to assert a complex condition. -func (a *Assertions) Conditionf(comp Comparison, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Conditionf(a.t, comp, msg, args...) -} - -// Contains asserts that the specified string, list(array, slice...) or map contains the -// specified substring or element. -// -// a.Contains("Hello World", "World") -// a.Contains(["Hello", "World"], "World") -// a.Contains({"Hello": "World"}, "Hello") -func (a *Assertions) Contains(s interface{}, contains interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Contains(a.t, s, contains, msgAndArgs...) -} - -// Containsf asserts that the specified string, list(array, slice...) or map contains the -// specified substring or element. -// -// a.Containsf("Hello World", "World", "error message %s", "formatted") -// a.Containsf(["Hello", "World"], "World", "error message %s", "formatted") -// a.Containsf({"Hello": "World"}, "Hello", "error message %s", "formatted") -func (a *Assertions) Containsf(s interface{}, contains interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Containsf(a.t, s, contains, msg, args...) -} - -// DirExists checks whether a directory exists in the given path. It also fails -// if the path is a file rather a directory or there is an error checking whether it exists. -func (a *Assertions) DirExists(path string, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return DirExists(a.t, path, msgAndArgs...) -} - -// DirExistsf checks whether a directory exists in the given path. It also fails -// if the path is a file rather a directory or there is an error checking whether it exists. -func (a *Assertions) DirExistsf(path string, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return DirExistsf(a.t, path, msg, args...) -} - -// ElementsMatch asserts that the specified listA(array, slice...) is equal to specified -// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, -// the number of appearances of each of them in both lists should match. -// -// a.ElementsMatch([1, 3, 2, 3], [1, 3, 3, 2]) -func (a *Assertions) ElementsMatch(listA interface{}, listB interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return ElementsMatch(a.t, listA, listB, msgAndArgs...) -} - -// ElementsMatchf asserts that the specified listA(array, slice...) is equal to specified -// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, -// the number of appearances of each of them in both lists should match. -// -// a.ElementsMatchf([1, 3, 2, 3], [1, 3, 3, 2], "error message %s", "formatted") -func (a *Assertions) ElementsMatchf(listA interface{}, listB interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return ElementsMatchf(a.t, listA, listB, msg, args...) -} - -// Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or either -// a slice or a channel with len == 0. -// -// a.Empty(obj) -func (a *Assertions) Empty(object interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Empty(a.t, object, msgAndArgs...) -} - -// Emptyf asserts that the specified object is empty. I.e. nil, "", false, 0 or either -// a slice or a channel with len == 0. -// -// a.Emptyf(obj, "error message %s", "formatted") -func (a *Assertions) Emptyf(object interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Emptyf(a.t, object, msg, args...) -} - -// Equal asserts that two objects are equal. -// -// a.Equal(123, 123) -// -// Pointer variable equality is determined based on the equality of the -// referenced values (as opposed to the memory addresses). Function equality -// cannot be determined and will always fail. -func (a *Assertions) Equal(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Equal(a.t, expected, actual, msgAndArgs...) -} - -// EqualError asserts that a function returned an error (i.e. not `nil`) -// and that it is equal to the provided error. -// -// actualObj, err := SomeFunction() -// a.EqualError(err, expectedErrorString) -func (a *Assertions) EqualError(theError error, errString string, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return EqualError(a.t, theError, errString, msgAndArgs...) -} - -// EqualErrorf asserts that a function returned an error (i.e. not `nil`) -// and that it is equal to the provided error. -// -// actualObj, err := SomeFunction() -// a.EqualErrorf(err, expectedErrorString, "error message %s", "formatted") -func (a *Assertions) EqualErrorf(theError error, errString string, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return EqualErrorf(a.t, theError, errString, msg, args...) -} - -// EqualExportedValues asserts that the types of two objects are equal and their public -// fields are also equal. This is useful for comparing structs that have private fields -// that could potentially differ. -// -// type S struct { -// Exported int -// notExported int -// } -// a.EqualExportedValues(S{1, 2}, S{1, 3}) => true -// a.EqualExportedValues(S{1, 2}, S{2, 3}) => false -func (a *Assertions) EqualExportedValues(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return EqualExportedValues(a.t, expected, actual, msgAndArgs...) -} - -// EqualExportedValuesf asserts that the types of two objects are equal and their public -// fields are also equal. This is useful for comparing structs that have private fields -// that could potentially differ. -// -// type S struct { -// Exported int -// notExported int -// } -// a.EqualExportedValuesf(S{1, 2}, S{1, 3}, "error message %s", "formatted") => true -// a.EqualExportedValuesf(S{1, 2}, S{2, 3}, "error message %s", "formatted") => false -func (a *Assertions) EqualExportedValuesf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return EqualExportedValuesf(a.t, expected, actual, msg, args...) -} - -// EqualValues asserts that two objects are equal or convertible to the same types -// and equal. -// -// a.EqualValues(uint32(123), int32(123)) -func (a *Assertions) EqualValues(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return EqualValues(a.t, expected, actual, msgAndArgs...) -} - -// EqualValuesf asserts that two objects are equal or convertible to the same types -// and equal. -// -// a.EqualValuesf(uint32(123), int32(123), "error message %s", "formatted") -func (a *Assertions) EqualValuesf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return EqualValuesf(a.t, expected, actual, msg, args...) -} - -// Equalf asserts that two objects are equal. -// -// a.Equalf(123, 123, "error message %s", "formatted") -// -// Pointer variable equality is determined based on the equality of the -// referenced values (as opposed to the memory addresses). Function equality -// cannot be determined and will always fail. -func (a *Assertions) Equalf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Equalf(a.t, expected, actual, msg, args...) -} - -// Error asserts that a function returned an error (i.e. not `nil`). -// -// actualObj, err := SomeFunction() -// if a.Error(err) { -// assert.Equal(t, expectedError, err) -// } -func (a *Assertions) Error(err error, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Error(a.t, err, msgAndArgs...) -} - -// ErrorAs asserts that at least one of the errors in err's chain matches target, and if so, sets target to that error value. -// This is a wrapper for errors.As. -func (a *Assertions) ErrorAs(err error, target interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return ErrorAs(a.t, err, target, msgAndArgs...) -} - -// ErrorAsf asserts that at least one of the errors in err's chain matches target, and if so, sets target to that error value. -// This is a wrapper for errors.As. -func (a *Assertions) ErrorAsf(err error, target interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return ErrorAsf(a.t, err, target, msg, args...) -} - -// ErrorContains asserts that a function returned an error (i.e. not `nil`) -// and that the error contains the specified substring. -// -// actualObj, err := SomeFunction() -// a.ErrorContains(err, expectedErrorSubString) -func (a *Assertions) ErrorContains(theError error, contains string, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return ErrorContains(a.t, theError, contains, msgAndArgs...) -} - -// ErrorContainsf asserts that a function returned an error (i.e. not `nil`) -// and that the error contains the specified substring. -// -// actualObj, err := SomeFunction() -// a.ErrorContainsf(err, expectedErrorSubString, "error message %s", "formatted") -func (a *Assertions) ErrorContainsf(theError error, contains string, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return ErrorContainsf(a.t, theError, contains, msg, args...) -} - -// ErrorIs asserts that at least one of the errors in err's chain matches target. -// This is a wrapper for errors.Is. -func (a *Assertions) ErrorIs(err error, target error, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return ErrorIs(a.t, err, target, msgAndArgs...) -} - -// ErrorIsf asserts that at least one of the errors in err's chain matches target. -// This is a wrapper for errors.Is. -func (a *Assertions) ErrorIsf(err error, target error, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return ErrorIsf(a.t, err, target, msg, args...) -} - -// Errorf asserts that a function returned an error (i.e. not `nil`). -// -// actualObj, err := SomeFunction() -// if a.Errorf(err, "error message %s", "formatted") { -// assert.Equal(t, expectedErrorf, err) -// } -func (a *Assertions) Errorf(err error, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Errorf(a.t, err, msg, args...) -} - -// Eventually asserts that given condition will be met in waitFor time, -// periodically checking target function each tick. -// -// a.Eventually(func() bool { return true; }, time.Second, 10*time.Millisecond) -func (a *Assertions) Eventually(condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Eventually(a.t, condition, waitFor, tick, msgAndArgs...) -} - -// EventuallyWithT asserts that given condition will be met in waitFor time, -// periodically checking target function each tick. In contrast to Eventually, -// it supplies a CollectT to the condition function, so that the condition -// function can use the CollectT to call other assertions. -// The condition is considered "met" if no errors are raised in a tick. -// The supplied CollectT collects all errors from one tick (if there are any). -// If the condition is not met before waitFor, the collected errors of -// the last tick are copied to t. -// -// externalValue := false -// go func() { -// time.Sleep(8*time.Second) -// externalValue = true -// }() -// a.EventuallyWithT(func(c *assert.CollectT) { -// // add assertions as needed; any assertion failure will fail the current tick -// assert.True(c, externalValue, "expected 'externalValue' to be true") -// }, 1*time.Second, 10*time.Second, "external state has not changed to 'true'; still false") -func (a *Assertions) EventuallyWithT(condition func(collect *CollectT), waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return EventuallyWithT(a.t, condition, waitFor, tick, msgAndArgs...) -} - -// EventuallyWithTf asserts that given condition will be met in waitFor time, -// periodically checking target function each tick. In contrast to Eventually, -// it supplies a CollectT to the condition function, so that the condition -// function can use the CollectT to call other assertions. -// The condition is considered "met" if no errors are raised in a tick. -// The supplied CollectT collects all errors from one tick (if there are any). -// If the condition is not met before waitFor, the collected errors of -// the last tick are copied to t. -// -// externalValue := false -// go func() { -// time.Sleep(8*time.Second) -// externalValue = true -// }() -// a.EventuallyWithTf(func(c *assert.CollectT, "error message %s", "formatted") { -// // add assertions as needed; any assertion failure will fail the current tick -// assert.True(c, externalValue, "expected 'externalValue' to be true") -// }, 1*time.Second, 10*time.Second, "external state has not changed to 'true'; still false") -func (a *Assertions) EventuallyWithTf(condition func(collect *CollectT), waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return EventuallyWithTf(a.t, condition, waitFor, tick, msg, args...) -} - -// Eventuallyf asserts that given condition will be met in waitFor time, -// periodically checking target function each tick. -// -// a.Eventuallyf(func() bool { return true; }, time.Second, 10*time.Millisecond, "error message %s", "formatted") -func (a *Assertions) Eventuallyf(condition func() bool, waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Eventuallyf(a.t, condition, waitFor, tick, msg, args...) -} - -// Exactly asserts that two objects are equal in value and type. -// -// a.Exactly(int32(123), int64(123)) -func (a *Assertions) Exactly(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Exactly(a.t, expected, actual, msgAndArgs...) -} - -// Exactlyf asserts that two objects are equal in value and type. -// -// a.Exactlyf(int32(123), int64(123), "error message %s", "formatted") -func (a *Assertions) Exactlyf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Exactlyf(a.t, expected, actual, msg, args...) -} - -// Fail reports a failure through -func (a *Assertions) Fail(failureMessage string, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Fail(a.t, failureMessage, msgAndArgs...) -} - -// FailNow fails test -func (a *Assertions) FailNow(failureMessage string, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return FailNow(a.t, failureMessage, msgAndArgs...) -} - -// FailNowf fails test -func (a *Assertions) FailNowf(failureMessage string, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return FailNowf(a.t, failureMessage, msg, args...) -} - -// Failf reports a failure through -func (a *Assertions) Failf(failureMessage string, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Failf(a.t, failureMessage, msg, args...) -} - -// False asserts that the specified value is false. -// -// a.False(myBool) -func (a *Assertions) False(value bool, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return False(a.t, value, msgAndArgs...) -} - -// Falsef asserts that the specified value is false. -// -// a.Falsef(myBool, "error message %s", "formatted") -func (a *Assertions) Falsef(value bool, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Falsef(a.t, value, msg, args...) -} - -// FileExists checks whether a file exists in the given path. It also fails if -// the path points to a directory or there is an error when trying to check the file. -func (a *Assertions) FileExists(path string, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return FileExists(a.t, path, msgAndArgs...) -} - -// FileExistsf checks whether a file exists in the given path. It also fails if -// the path points to a directory or there is an error when trying to check the file. -func (a *Assertions) FileExistsf(path string, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return FileExistsf(a.t, path, msg, args...) -} - -// Greater asserts that the first element is greater than the second -// -// a.Greater(2, 1) -// a.Greater(float64(2), float64(1)) -// a.Greater("b", "a") -func (a *Assertions) Greater(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Greater(a.t, e1, e2, msgAndArgs...) -} - -// GreaterOrEqual asserts that the first element is greater than or equal to the second -// -// a.GreaterOrEqual(2, 1) -// a.GreaterOrEqual(2, 2) -// a.GreaterOrEqual("b", "a") -// a.GreaterOrEqual("b", "b") -func (a *Assertions) GreaterOrEqual(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return GreaterOrEqual(a.t, e1, e2, msgAndArgs...) -} - -// GreaterOrEqualf asserts that the first element is greater than or equal to the second -// -// a.GreaterOrEqualf(2, 1, "error message %s", "formatted") -// a.GreaterOrEqualf(2, 2, "error message %s", "formatted") -// a.GreaterOrEqualf("b", "a", "error message %s", "formatted") -// a.GreaterOrEqualf("b", "b", "error message %s", "formatted") -func (a *Assertions) GreaterOrEqualf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return GreaterOrEqualf(a.t, e1, e2, msg, args...) -} - -// Greaterf asserts that the first element is greater than the second -// -// a.Greaterf(2, 1, "error message %s", "formatted") -// a.Greaterf(float64(2), float64(1), "error message %s", "formatted") -// a.Greaterf("b", "a", "error message %s", "formatted") -func (a *Assertions) Greaterf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Greaterf(a.t, e1, e2, msg, args...) -} - -// HTTPBodyContains asserts that a specified handler returns a -// body that contains a string. -// -// a.HTTPBodyContains(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky") -// -// Returns whether the assertion was successful (true) or not (false). -func (a *Assertions) HTTPBodyContains(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return HTTPBodyContains(a.t, handler, method, url, values, str, msgAndArgs...) -} - -// HTTPBodyContainsf asserts that a specified handler returns a -// body that contains a string. -// -// a.HTTPBodyContainsf(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). -func (a *Assertions) HTTPBodyContainsf(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return HTTPBodyContainsf(a.t, handler, method, url, values, str, msg, args...) -} - -// HTTPBodyNotContains asserts that a specified handler returns a -// body that does not contain a string. -// -// a.HTTPBodyNotContains(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky") -// -// Returns whether the assertion was successful (true) or not (false). -func (a *Assertions) HTTPBodyNotContains(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return HTTPBodyNotContains(a.t, handler, method, url, values, str, msgAndArgs...) -} - -// HTTPBodyNotContainsf asserts that a specified handler returns a -// body that does not contain a string. -// -// a.HTTPBodyNotContainsf(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). -func (a *Assertions) HTTPBodyNotContainsf(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return HTTPBodyNotContainsf(a.t, handler, method, url, values, str, msg, args...) -} - -// HTTPError asserts that a specified handler returns an error status code. -// -// a.HTTPError(myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} -// -// Returns whether the assertion was successful (true) or not (false). -func (a *Assertions) HTTPError(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return HTTPError(a.t, handler, method, url, values, msgAndArgs...) -} - -// HTTPErrorf asserts that a specified handler returns an error status code. -// -// a.HTTPErrorf(myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} -// -// Returns whether the assertion was successful (true) or not (false). -func (a *Assertions) HTTPErrorf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return HTTPErrorf(a.t, handler, method, url, values, msg, args...) -} - -// HTTPRedirect asserts that a specified handler returns a redirect status code. -// -// a.HTTPRedirect(myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} -// -// Returns whether the assertion was successful (true) or not (false). -func (a *Assertions) HTTPRedirect(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return HTTPRedirect(a.t, handler, method, url, values, msgAndArgs...) -} - -// HTTPRedirectf asserts that a specified handler returns a redirect status code. -// -// a.HTTPRedirectf(myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} -// -// Returns whether the assertion was successful (true) or not (false). -func (a *Assertions) HTTPRedirectf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return HTTPRedirectf(a.t, handler, method, url, values, msg, args...) -} - -// HTTPStatusCode asserts that a specified handler returns a specified status code. -// -// a.HTTPStatusCode(myHandler, "GET", "/notImplemented", nil, 501) -// -// Returns whether the assertion was successful (true) or not (false). -func (a *Assertions) HTTPStatusCode(handler http.HandlerFunc, method string, url string, values url.Values, statuscode int, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return HTTPStatusCode(a.t, handler, method, url, values, statuscode, msgAndArgs...) -} - -// HTTPStatusCodef asserts that a specified handler returns a specified status code. -// -// a.HTTPStatusCodef(myHandler, "GET", "/notImplemented", nil, 501, "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). -func (a *Assertions) HTTPStatusCodef(handler http.HandlerFunc, method string, url string, values url.Values, statuscode int, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return HTTPStatusCodef(a.t, handler, method, url, values, statuscode, msg, args...) -} - -// HTTPSuccess asserts that a specified handler returns a success status code. -// -// a.HTTPSuccess(myHandler, "POST", "http://www.google.com", nil) -// -// Returns whether the assertion was successful (true) or not (false). -func (a *Assertions) HTTPSuccess(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return HTTPSuccess(a.t, handler, method, url, values, msgAndArgs...) -} - -// HTTPSuccessf asserts that a specified handler returns a success status code. -// -// a.HTTPSuccessf(myHandler, "POST", "http://www.google.com", nil, "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). -func (a *Assertions) HTTPSuccessf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return HTTPSuccessf(a.t, handler, method, url, values, msg, args...) -} - -// Implements asserts that an object is implemented by the specified interface. -// -// a.Implements((*MyInterface)(nil), new(MyObject)) -func (a *Assertions) Implements(interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Implements(a.t, interfaceObject, object, msgAndArgs...) -} - -// Implementsf asserts that an object is implemented by the specified interface. -// -// a.Implementsf((*MyInterface)(nil), new(MyObject), "error message %s", "formatted") -func (a *Assertions) Implementsf(interfaceObject interface{}, object interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Implementsf(a.t, interfaceObject, object, msg, args...) -} - -// InDelta asserts that the two numerals are within delta of each other. -// -// a.InDelta(math.Pi, 22/7.0, 0.01) -func (a *Assertions) InDelta(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return InDelta(a.t, expected, actual, delta, msgAndArgs...) -} - -// InDeltaMapValues is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys. -func (a *Assertions) InDeltaMapValues(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return InDeltaMapValues(a.t, expected, actual, delta, msgAndArgs...) -} - -// InDeltaMapValuesf is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys. -func (a *Assertions) InDeltaMapValuesf(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return InDeltaMapValuesf(a.t, expected, actual, delta, msg, args...) -} - -// InDeltaSlice is the same as InDelta, except it compares two slices. -func (a *Assertions) InDeltaSlice(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return InDeltaSlice(a.t, expected, actual, delta, msgAndArgs...) -} - -// InDeltaSlicef is the same as InDelta, except it compares two slices. -func (a *Assertions) InDeltaSlicef(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return InDeltaSlicef(a.t, expected, actual, delta, msg, args...) -} - -// InDeltaf asserts that the two numerals are within delta of each other. -// -// a.InDeltaf(math.Pi, 22/7.0, 0.01, "error message %s", "formatted") -func (a *Assertions) InDeltaf(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return InDeltaf(a.t, expected, actual, delta, msg, args...) -} - -// InEpsilon asserts that expected and actual have a relative error less than epsilon -func (a *Assertions) InEpsilon(expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return InEpsilon(a.t, expected, actual, epsilon, msgAndArgs...) -} - -// InEpsilonSlice is the same as InEpsilon, except it compares each value from two slices. -func (a *Assertions) InEpsilonSlice(expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return InEpsilonSlice(a.t, expected, actual, epsilon, msgAndArgs...) -} - -// InEpsilonSlicef is the same as InEpsilon, except it compares each value from two slices. -func (a *Assertions) InEpsilonSlicef(expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return InEpsilonSlicef(a.t, expected, actual, epsilon, msg, args...) -} - -// InEpsilonf asserts that expected and actual have a relative error less than epsilon -func (a *Assertions) InEpsilonf(expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return InEpsilonf(a.t, expected, actual, epsilon, msg, args...) -} - -// IsDecreasing asserts that the collection is decreasing -// -// a.IsDecreasing([]int{2, 1, 0}) -// a.IsDecreasing([]float{2, 1}) -// a.IsDecreasing([]string{"b", "a"}) -func (a *Assertions) IsDecreasing(object interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return IsDecreasing(a.t, object, msgAndArgs...) -} - -// IsDecreasingf asserts that the collection is decreasing -// -// a.IsDecreasingf([]int{2, 1, 0}, "error message %s", "formatted") -// a.IsDecreasingf([]float{2, 1}, "error message %s", "formatted") -// a.IsDecreasingf([]string{"b", "a"}, "error message %s", "formatted") -func (a *Assertions) IsDecreasingf(object interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return IsDecreasingf(a.t, object, msg, args...) -} - -// IsIncreasing asserts that the collection is increasing -// -// a.IsIncreasing([]int{1, 2, 3}) -// a.IsIncreasing([]float{1, 2}) -// a.IsIncreasing([]string{"a", "b"}) -func (a *Assertions) IsIncreasing(object interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return IsIncreasing(a.t, object, msgAndArgs...) -} - -// IsIncreasingf asserts that the collection is increasing -// -// a.IsIncreasingf([]int{1, 2, 3}, "error message %s", "formatted") -// a.IsIncreasingf([]float{1, 2}, "error message %s", "formatted") -// a.IsIncreasingf([]string{"a", "b"}, "error message %s", "formatted") -func (a *Assertions) IsIncreasingf(object interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return IsIncreasingf(a.t, object, msg, args...) -} - -// IsNonDecreasing asserts that the collection is not decreasing -// -// a.IsNonDecreasing([]int{1, 1, 2}) -// a.IsNonDecreasing([]float{1, 2}) -// a.IsNonDecreasing([]string{"a", "b"}) -func (a *Assertions) IsNonDecreasing(object interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return IsNonDecreasing(a.t, object, msgAndArgs...) -} - -// IsNonDecreasingf asserts that the collection is not decreasing -// -// a.IsNonDecreasingf([]int{1, 1, 2}, "error message %s", "formatted") -// a.IsNonDecreasingf([]float{1, 2}, "error message %s", "formatted") -// a.IsNonDecreasingf([]string{"a", "b"}, "error message %s", "formatted") -func (a *Assertions) IsNonDecreasingf(object interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return IsNonDecreasingf(a.t, object, msg, args...) -} - -// IsNonIncreasing asserts that the collection is not increasing -// -// a.IsNonIncreasing([]int{2, 1, 1}) -// a.IsNonIncreasing([]float{2, 1}) -// a.IsNonIncreasing([]string{"b", "a"}) -func (a *Assertions) IsNonIncreasing(object interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return IsNonIncreasing(a.t, object, msgAndArgs...) -} - -// IsNonIncreasingf asserts that the collection is not increasing -// -// a.IsNonIncreasingf([]int{2, 1, 1}, "error message %s", "formatted") -// a.IsNonIncreasingf([]float{2, 1}, "error message %s", "formatted") -// a.IsNonIncreasingf([]string{"b", "a"}, "error message %s", "formatted") -func (a *Assertions) IsNonIncreasingf(object interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return IsNonIncreasingf(a.t, object, msg, args...) -} - -// IsType asserts that the specified objects are of the same type. -func (a *Assertions) IsType(expectedType interface{}, object interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return IsType(a.t, expectedType, object, msgAndArgs...) -} - -// IsTypef asserts that the specified objects are of the same type. -func (a *Assertions) IsTypef(expectedType interface{}, object interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return IsTypef(a.t, expectedType, object, msg, args...) -} - -// JSONEq asserts that two JSON strings are equivalent. -// -// a.JSONEq(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) -func (a *Assertions) JSONEq(expected string, actual string, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return JSONEq(a.t, expected, actual, msgAndArgs...) -} - -// JSONEqf asserts that two JSON strings are equivalent. -// -// a.JSONEqf(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`, "error message %s", "formatted") -func (a *Assertions) JSONEqf(expected string, actual string, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return JSONEqf(a.t, expected, actual, msg, args...) -} - -// Len asserts that the specified object has specific length. -// Len also fails if the object has a type that len() not accept. -// -// a.Len(mySlice, 3) -func (a *Assertions) Len(object interface{}, length int, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Len(a.t, object, length, msgAndArgs...) -} - -// Lenf asserts that the specified object has specific length. -// Lenf also fails if the object has a type that len() not accept. -// -// a.Lenf(mySlice, 3, "error message %s", "formatted") -func (a *Assertions) Lenf(object interface{}, length int, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Lenf(a.t, object, length, msg, args...) -} - -// Less asserts that the first element is less than the second -// -// a.Less(1, 2) -// a.Less(float64(1), float64(2)) -// a.Less("a", "b") -func (a *Assertions) Less(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Less(a.t, e1, e2, msgAndArgs...) -} - -// LessOrEqual asserts that the first element is less than or equal to the second -// -// a.LessOrEqual(1, 2) -// a.LessOrEqual(2, 2) -// a.LessOrEqual("a", "b") -// a.LessOrEqual("b", "b") -func (a *Assertions) LessOrEqual(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return LessOrEqual(a.t, e1, e2, msgAndArgs...) -} - -// LessOrEqualf asserts that the first element is less than or equal to the second -// -// a.LessOrEqualf(1, 2, "error message %s", "formatted") -// a.LessOrEqualf(2, 2, "error message %s", "formatted") -// a.LessOrEqualf("a", "b", "error message %s", "formatted") -// a.LessOrEqualf("b", "b", "error message %s", "formatted") -func (a *Assertions) LessOrEqualf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return LessOrEqualf(a.t, e1, e2, msg, args...) -} - -// Lessf asserts that the first element is less than the second -// -// a.Lessf(1, 2, "error message %s", "formatted") -// a.Lessf(float64(1), float64(2), "error message %s", "formatted") -// a.Lessf("a", "b", "error message %s", "formatted") -func (a *Assertions) Lessf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Lessf(a.t, e1, e2, msg, args...) -} - -// Negative asserts that the specified element is negative -// -// a.Negative(-1) -// a.Negative(-1.23) -func (a *Assertions) Negative(e interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Negative(a.t, e, msgAndArgs...) -} - -// Negativef asserts that the specified element is negative -// -// a.Negativef(-1, "error message %s", "formatted") -// a.Negativef(-1.23, "error message %s", "formatted") -func (a *Assertions) Negativef(e interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Negativef(a.t, e, msg, args...) -} - -// Never asserts that the given condition doesn't satisfy in waitFor time, -// periodically checking the target function each tick. -// -// a.Never(func() bool { return false; }, time.Second, 10*time.Millisecond) -func (a *Assertions) Never(condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Never(a.t, condition, waitFor, tick, msgAndArgs...) -} - -// Neverf asserts that the given condition doesn't satisfy in waitFor time, -// periodically checking the target function each tick. -// -// a.Neverf(func() bool { return false; }, time.Second, 10*time.Millisecond, "error message %s", "formatted") -func (a *Assertions) Neverf(condition func() bool, waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Neverf(a.t, condition, waitFor, tick, msg, args...) -} - -// Nil asserts that the specified object is nil. -// -// a.Nil(err) -func (a *Assertions) Nil(object interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Nil(a.t, object, msgAndArgs...) -} - -// Nilf asserts that the specified object is nil. -// -// a.Nilf(err, "error message %s", "formatted") -func (a *Assertions) Nilf(object interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Nilf(a.t, object, msg, args...) -} - -// NoDirExists checks whether a directory does not exist in the given path. -// It fails if the path points to an existing _directory_ only. -func (a *Assertions) NoDirExists(path string, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NoDirExists(a.t, path, msgAndArgs...) -} - -// NoDirExistsf checks whether a directory does not exist in the given path. -// It fails if the path points to an existing _directory_ only. -func (a *Assertions) NoDirExistsf(path string, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NoDirExistsf(a.t, path, msg, args...) -} - -// NoError asserts that a function returned no error (i.e. `nil`). -// -// actualObj, err := SomeFunction() -// if a.NoError(err) { -// assert.Equal(t, expectedObj, actualObj) -// } -func (a *Assertions) NoError(err error, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NoError(a.t, err, msgAndArgs...) -} - -// NoErrorf asserts that a function returned no error (i.e. `nil`). -// -// actualObj, err := SomeFunction() -// if a.NoErrorf(err, "error message %s", "formatted") { -// assert.Equal(t, expectedObj, actualObj) -// } -func (a *Assertions) NoErrorf(err error, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NoErrorf(a.t, err, msg, args...) -} - -// NoFileExists checks whether a file does not exist in a given path. It fails -// if the path points to an existing _file_ only. -func (a *Assertions) NoFileExists(path string, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NoFileExists(a.t, path, msgAndArgs...) -} - -// NoFileExistsf checks whether a file does not exist in a given path. It fails -// if the path points to an existing _file_ only. -func (a *Assertions) NoFileExistsf(path string, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NoFileExistsf(a.t, path, msg, args...) -} - -// NotContains asserts that the specified string, list(array, slice...) or map does NOT contain the -// specified substring or element. -// -// a.NotContains("Hello World", "Earth") -// a.NotContains(["Hello", "World"], "Earth") -// a.NotContains({"Hello": "World"}, "Earth") -func (a *Assertions) NotContains(s interface{}, contains interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NotContains(a.t, s, contains, msgAndArgs...) -} - -// NotContainsf asserts that the specified string, list(array, slice...) or map does NOT contain the -// specified substring or element. -// -// a.NotContainsf("Hello World", "Earth", "error message %s", "formatted") -// a.NotContainsf(["Hello", "World"], "Earth", "error message %s", "formatted") -// a.NotContainsf({"Hello": "World"}, "Earth", "error message %s", "formatted") -func (a *Assertions) NotContainsf(s interface{}, contains interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NotContainsf(a.t, s, contains, msg, args...) -} - -// NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either -// a slice or a channel with len == 0. -// -// if a.NotEmpty(obj) { -// assert.Equal(t, "two", obj[1]) -// } -func (a *Assertions) NotEmpty(object interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NotEmpty(a.t, object, msgAndArgs...) -} - -// NotEmptyf asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either -// a slice or a channel with len == 0. -// -// if a.NotEmptyf(obj, "error message %s", "formatted") { -// assert.Equal(t, "two", obj[1]) -// } -func (a *Assertions) NotEmptyf(object interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NotEmptyf(a.t, object, msg, args...) -} - -// NotEqual asserts that the specified values are NOT equal. -// -// a.NotEqual(obj1, obj2) -// -// Pointer variable equality is determined based on the equality of the -// referenced values (as opposed to the memory addresses). -func (a *Assertions) NotEqual(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NotEqual(a.t, expected, actual, msgAndArgs...) -} - -// NotEqualValues asserts that two objects are not equal even when converted to the same type -// -// a.NotEqualValues(obj1, obj2) -func (a *Assertions) NotEqualValues(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NotEqualValues(a.t, expected, actual, msgAndArgs...) -} - -// NotEqualValuesf asserts that two objects are not equal even when converted to the same type -// -// a.NotEqualValuesf(obj1, obj2, "error message %s", "formatted") -func (a *Assertions) NotEqualValuesf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NotEqualValuesf(a.t, expected, actual, msg, args...) -} - -// NotEqualf asserts that the specified values are NOT equal. -// -// a.NotEqualf(obj1, obj2, "error message %s", "formatted") -// -// Pointer variable equality is determined based on the equality of the -// referenced values (as opposed to the memory addresses). -func (a *Assertions) NotEqualf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NotEqualf(a.t, expected, actual, msg, args...) -} - -// NotErrorIs asserts that at none of the errors in err's chain matches target. -// This is a wrapper for errors.Is. -func (a *Assertions) NotErrorIs(err error, target error, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NotErrorIs(a.t, err, target, msgAndArgs...) -} - -// NotErrorIsf asserts that at none of the errors in err's chain matches target. -// This is a wrapper for errors.Is. -func (a *Assertions) NotErrorIsf(err error, target error, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NotErrorIsf(a.t, err, target, msg, args...) -} - -// NotImplements asserts that an object does not implement the specified interface. -// -// a.NotImplements((*MyInterface)(nil), new(MyObject)) -func (a *Assertions) NotImplements(interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NotImplements(a.t, interfaceObject, object, msgAndArgs...) -} - -// NotImplementsf asserts that an object does not implement the specified interface. -// -// a.NotImplementsf((*MyInterface)(nil), new(MyObject), "error message %s", "formatted") -func (a *Assertions) NotImplementsf(interfaceObject interface{}, object interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NotImplementsf(a.t, interfaceObject, object, msg, args...) -} - -// NotNil asserts that the specified object is not nil. -// -// a.NotNil(err) -func (a *Assertions) NotNil(object interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NotNil(a.t, object, msgAndArgs...) -} - -// NotNilf asserts that the specified object is not nil. -// -// a.NotNilf(err, "error message %s", "formatted") -func (a *Assertions) NotNilf(object interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NotNilf(a.t, object, msg, args...) -} - -// NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic. -// -// a.NotPanics(func(){ RemainCalm() }) -func (a *Assertions) NotPanics(f PanicTestFunc, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NotPanics(a.t, f, msgAndArgs...) -} - -// NotPanicsf asserts that the code inside the specified PanicTestFunc does NOT panic. -// -// a.NotPanicsf(func(){ RemainCalm() }, "error message %s", "formatted") -func (a *Assertions) NotPanicsf(f PanicTestFunc, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NotPanicsf(a.t, f, msg, args...) -} - -// NotRegexp asserts that a specified regexp does not match a string. -// -// a.NotRegexp(regexp.MustCompile("starts"), "it's starting") -// a.NotRegexp("^start", "it's not starting") -func (a *Assertions) NotRegexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NotRegexp(a.t, rx, str, msgAndArgs...) -} - -// NotRegexpf asserts that a specified regexp does not match a string. -// -// a.NotRegexpf(regexp.MustCompile("starts"), "it's starting", "error message %s", "formatted") -// a.NotRegexpf("^start", "it's not starting", "error message %s", "formatted") -func (a *Assertions) NotRegexpf(rx interface{}, str interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NotRegexpf(a.t, rx, str, msg, args...) -} - -// NotSame asserts that two pointers do not reference the same object. -// -// a.NotSame(ptr1, ptr2) -// -// Both arguments must be pointer variables. Pointer variable sameness is -// determined based on the equality of both type and value. -func (a *Assertions) NotSame(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NotSame(a.t, expected, actual, msgAndArgs...) -} - -// NotSamef asserts that two pointers do not reference the same object. -// -// a.NotSamef(ptr1, ptr2, "error message %s", "formatted") -// -// Both arguments must be pointer variables. Pointer variable sameness is -// determined based on the equality of both type and value. -func (a *Assertions) NotSamef(expected interface{}, actual interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NotSamef(a.t, expected, actual, msg, args...) -} - -// NotSubset asserts that the specified list(array, slice...) or map does NOT -// contain all elements given in the specified subset list(array, slice...) or -// map. -// -// a.NotSubset([1, 3, 4], [1, 2]) -// a.NotSubset({"x": 1, "y": 2}, {"z": 3}) -func (a *Assertions) NotSubset(list interface{}, subset interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NotSubset(a.t, list, subset, msgAndArgs...) -} - -// NotSubsetf asserts that the specified list(array, slice...) or map does NOT -// contain all elements given in the specified subset list(array, slice...) or -// map. -// -// a.NotSubsetf([1, 3, 4], [1, 2], "error message %s", "formatted") -// a.NotSubsetf({"x": 1, "y": 2}, {"z": 3}, "error message %s", "formatted") -func (a *Assertions) NotSubsetf(list interface{}, subset interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NotSubsetf(a.t, list, subset, msg, args...) -} - -// NotZero asserts that i is not the zero value for its type. -func (a *Assertions) NotZero(i interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NotZero(a.t, i, msgAndArgs...) -} - -// NotZerof asserts that i is not the zero value for its type. -func (a *Assertions) NotZerof(i interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return NotZerof(a.t, i, msg, args...) -} - -// Panics asserts that the code inside the specified PanicTestFunc panics. -// -// a.Panics(func(){ GoCrazy() }) -func (a *Assertions) Panics(f PanicTestFunc, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Panics(a.t, f, msgAndArgs...) -} - -// PanicsWithError asserts that the code inside the specified PanicTestFunc -// panics, and that the recovered panic value is an error that satisfies the -// EqualError comparison. -// -// a.PanicsWithError("crazy error", func(){ GoCrazy() }) -func (a *Assertions) PanicsWithError(errString string, f PanicTestFunc, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return PanicsWithError(a.t, errString, f, msgAndArgs...) -} - -// PanicsWithErrorf asserts that the code inside the specified PanicTestFunc -// panics, and that the recovered panic value is an error that satisfies the -// EqualError comparison. -// -// a.PanicsWithErrorf("crazy error", func(){ GoCrazy() }, "error message %s", "formatted") -func (a *Assertions) PanicsWithErrorf(errString string, f PanicTestFunc, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return PanicsWithErrorf(a.t, errString, f, msg, args...) -} - -// PanicsWithValue asserts that the code inside the specified PanicTestFunc panics, and that -// the recovered panic value equals the expected panic value. -// -// a.PanicsWithValue("crazy error", func(){ GoCrazy() }) -func (a *Assertions) PanicsWithValue(expected interface{}, f PanicTestFunc, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return PanicsWithValue(a.t, expected, f, msgAndArgs...) -} - -// PanicsWithValuef asserts that the code inside the specified PanicTestFunc panics, and that -// the recovered panic value equals the expected panic value. -// -// a.PanicsWithValuef("crazy error", func(){ GoCrazy() }, "error message %s", "formatted") -func (a *Assertions) PanicsWithValuef(expected interface{}, f PanicTestFunc, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return PanicsWithValuef(a.t, expected, f, msg, args...) -} - -// Panicsf asserts that the code inside the specified PanicTestFunc panics. -// -// a.Panicsf(func(){ GoCrazy() }, "error message %s", "formatted") -func (a *Assertions) Panicsf(f PanicTestFunc, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Panicsf(a.t, f, msg, args...) -} - -// Positive asserts that the specified element is positive -// -// a.Positive(1) -// a.Positive(1.23) -func (a *Assertions) Positive(e interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Positive(a.t, e, msgAndArgs...) -} - -// Positivef asserts that the specified element is positive -// -// a.Positivef(1, "error message %s", "formatted") -// a.Positivef(1.23, "error message %s", "formatted") -func (a *Assertions) Positivef(e interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Positivef(a.t, e, msg, args...) -} - -// Regexp asserts that a specified regexp matches a string. -// -// a.Regexp(regexp.MustCompile("start"), "it's starting") -// a.Regexp("start...$", "it's not starting") -func (a *Assertions) Regexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Regexp(a.t, rx, str, msgAndArgs...) -} - -// Regexpf asserts that a specified regexp matches a string. -// -// a.Regexpf(regexp.MustCompile("start"), "it's starting", "error message %s", "formatted") -// a.Regexpf("start...$", "it's not starting", "error message %s", "formatted") -func (a *Assertions) Regexpf(rx interface{}, str interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Regexpf(a.t, rx, str, msg, args...) -} - -// Same asserts that two pointers reference the same object. -// -// a.Same(ptr1, ptr2) -// -// Both arguments must be pointer variables. Pointer variable sameness is -// determined based on the equality of both type and value. -func (a *Assertions) Same(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Same(a.t, expected, actual, msgAndArgs...) -} - -// Samef asserts that two pointers reference the same object. -// -// a.Samef(ptr1, ptr2, "error message %s", "formatted") -// -// Both arguments must be pointer variables. Pointer variable sameness is -// determined based on the equality of both type and value. -func (a *Assertions) Samef(expected interface{}, actual interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Samef(a.t, expected, actual, msg, args...) -} - -// Subset asserts that the specified list(array, slice...) or map contains all -// elements given in the specified subset list(array, slice...) or map. -// -// a.Subset([1, 2, 3], [1, 2]) -// a.Subset({"x": 1, "y": 2}, {"x": 1}) -func (a *Assertions) Subset(list interface{}, subset interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Subset(a.t, list, subset, msgAndArgs...) -} - -// Subsetf asserts that the specified list(array, slice...) or map contains all -// elements given in the specified subset list(array, slice...) or map. -// -// a.Subsetf([1, 2, 3], [1, 2], "error message %s", "formatted") -// a.Subsetf({"x": 1, "y": 2}, {"x": 1}, "error message %s", "formatted") -func (a *Assertions) Subsetf(list interface{}, subset interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Subsetf(a.t, list, subset, msg, args...) -} - -// True asserts that the specified value is true. -// -// a.True(myBool) -func (a *Assertions) True(value bool, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return True(a.t, value, msgAndArgs...) -} - -// Truef asserts that the specified value is true. -// -// a.Truef(myBool, "error message %s", "formatted") -func (a *Assertions) Truef(value bool, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Truef(a.t, value, msg, args...) -} - -// WithinDuration asserts that the two times are within duration delta of each other. -// -// a.WithinDuration(time.Now(), time.Now(), 10*time.Second) -func (a *Assertions) WithinDuration(expected time.Time, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return WithinDuration(a.t, expected, actual, delta, msgAndArgs...) -} - -// WithinDurationf asserts that the two times are within duration delta of each other. -// -// a.WithinDurationf(time.Now(), time.Now(), 10*time.Second, "error message %s", "formatted") -func (a *Assertions) WithinDurationf(expected time.Time, actual time.Time, delta time.Duration, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return WithinDurationf(a.t, expected, actual, delta, msg, args...) -} - -// WithinRange asserts that a time is within a time range (inclusive). -// -// a.WithinRange(time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second)) -func (a *Assertions) WithinRange(actual time.Time, start time.Time, end time.Time, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return WithinRange(a.t, actual, start, end, msgAndArgs...) -} - -// WithinRangef asserts that a time is within a time range (inclusive). -// -// a.WithinRangef(time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second), "error message %s", "formatted") -func (a *Assertions) WithinRangef(actual time.Time, start time.Time, end time.Time, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return WithinRangef(a.t, actual, start, end, msg, args...) -} - -// YAMLEq asserts that two YAML strings are equivalent. -func (a *Assertions) YAMLEq(expected string, actual string, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return YAMLEq(a.t, expected, actual, msgAndArgs...) -} - -// YAMLEqf asserts that two YAML strings are equivalent. -func (a *Assertions) YAMLEqf(expected string, actual string, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return YAMLEqf(a.t, expected, actual, msg, args...) -} - -// Zero asserts that i is the zero value for its type. -func (a *Assertions) Zero(i interface{}, msgAndArgs ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Zero(a.t, i, msgAndArgs...) -} - -// Zerof asserts that i is the zero value for its type. -func (a *Assertions) Zerof(i interface{}, msg string, args ...interface{}) bool { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - return Zerof(a.t, i, msg, args...) -} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/assert/assertion_forward.go.tmpl b/trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/assert/assertion_forward.go.tmpl deleted file mode 100644 index 188bb9e17..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/assert/assertion_forward.go.tmpl +++ /dev/null @@ -1,5 +0,0 @@ -{{.CommentWithoutT "a"}} -func (a *Assertions) {{.DocInfo.Name}}({{.Params}}) bool { - if h, ok := a.t.(tHelper); ok { h.Helper() } - return {{.DocInfo.Name}}(a.t, {{.ForwardedParams}}) -} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/assert/assertion_order.go b/trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/assert/assertion_order.go deleted file mode 100644 index 00df62a05..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/assert/assertion_order.go +++ /dev/null @@ -1,81 +0,0 @@ -package assert - -import ( - "fmt" - "reflect" -) - -// isOrdered checks that collection contains orderable elements. -func isOrdered(t TestingT, object interface{}, allowedComparesResults []CompareType, failMessage string, msgAndArgs ...interface{}) bool { - objKind := reflect.TypeOf(object).Kind() - if objKind != reflect.Slice && objKind != reflect.Array { - return false - } - - objValue := reflect.ValueOf(object) - objLen := objValue.Len() - - if objLen <= 1 { - return true - } - - value := objValue.Index(0) - valueInterface := value.Interface() - firstValueKind := value.Kind() - - for i := 1; i < objLen; i++ { - prevValue := value - prevValueInterface := valueInterface - - value = objValue.Index(i) - valueInterface = value.Interface() - - compareResult, isComparable := compare(prevValueInterface, valueInterface, firstValueKind) - - if !isComparable { - return Fail(t, fmt.Sprintf("Can not compare type \"%s\" and \"%s\"", reflect.TypeOf(value), reflect.TypeOf(prevValue)), msgAndArgs...) - } - - if !containsValue(allowedComparesResults, compareResult) { - return Fail(t, fmt.Sprintf(failMessage, prevValue, value), msgAndArgs...) - } - } - - return true -} - -// IsIncreasing asserts that the collection is increasing -// -// assert.IsIncreasing(t, []int{1, 2, 3}) -// assert.IsIncreasing(t, []float{1, 2}) -// assert.IsIncreasing(t, []string{"a", "b"}) -func IsIncreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { - return isOrdered(t, object, []CompareType{compareLess}, "\"%v\" is not less than \"%v\"", msgAndArgs...) -} - -// IsNonIncreasing asserts that the collection is not increasing -// -// assert.IsNonIncreasing(t, []int{2, 1, 1}) -// assert.IsNonIncreasing(t, []float{2, 1}) -// assert.IsNonIncreasing(t, []string{"b", "a"}) -func IsNonIncreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { - return isOrdered(t, object, []CompareType{compareEqual, compareGreater}, "\"%v\" is not greater than or equal to \"%v\"", msgAndArgs...) -} - -// IsDecreasing asserts that the collection is decreasing -// -// assert.IsDecreasing(t, []int{2, 1, 0}) -// assert.IsDecreasing(t, []float{2, 1}) -// assert.IsDecreasing(t, []string{"b", "a"}) -func IsDecreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { - return isOrdered(t, object, []CompareType{compareGreater}, "\"%v\" is not greater than \"%v\"", msgAndArgs...) -} - -// IsNonDecreasing asserts that the collection is not decreasing -// -// assert.IsNonDecreasing(t, []int{1, 1, 2}) -// assert.IsNonDecreasing(t, []float{1, 2}) -// assert.IsNonDecreasing(t, []string{"a", "b"}) -func IsNonDecreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { - return isOrdered(t, object, []CompareType{compareLess, compareEqual}, "\"%v\" is not less than or equal to \"%v\"", msgAndArgs...) -} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/assert/assertions.go b/trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/assert/assertions.go deleted file mode 100644 index 0b7570f21..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/assert/assertions.go +++ /dev/null @@ -1,2105 +0,0 @@ -package assert - -import ( - "bufio" - "bytes" - "encoding/json" - "errors" - "fmt" - "math" - "os" - "reflect" - "regexp" - "runtime" - "runtime/debug" - "strings" - "time" - "unicode" - "unicode/utf8" - - "github.com/davecgh/go-spew/spew" - "github.com/pmezard/go-difflib/difflib" - "gopkg.in/yaml.v3" -) - -//go:generate sh -c "cd ../_codegen && go build && cd - && ../_codegen/_codegen -output-package=assert -template=assertion_format.go.tmpl" - -// TestingT is an interface wrapper around *testing.T -type TestingT interface { - Errorf(format string, args ...interface{}) -} - -// ComparisonAssertionFunc is a common function prototype when comparing two values. Can be useful -// for table driven tests. -type ComparisonAssertionFunc func(TestingT, interface{}, interface{}, ...interface{}) bool - -// ValueAssertionFunc is a common function prototype when validating a single value. Can be useful -// for table driven tests. -type ValueAssertionFunc func(TestingT, interface{}, ...interface{}) bool - -// BoolAssertionFunc is a common function prototype when validating a bool value. Can be useful -// for table driven tests. -type BoolAssertionFunc func(TestingT, bool, ...interface{}) bool - -// ErrorAssertionFunc is a common function prototype when validating an error value. Can be useful -// for table driven tests. -type ErrorAssertionFunc func(TestingT, error, ...interface{}) bool - -// Comparison is a custom function that returns true on success and false on failure -type Comparison func() (success bool) - -/* - Helper functions -*/ - -// ObjectsAreEqual determines if two objects are considered equal. -// -// This function does no assertion of any kind. -func ObjectsAreEqual(expected, actual interface{}) bool { - if expected == nil || actual == nil { - return expected == actual - } - - exp, ok := expected.([]byte) - if !ok { - return reflect.DeepEqual(expected, actual) - } - - act, ok := actual.([]byte) - if !ok { - return false - } - if exp == nil || act == nil { - return exp == nil && act == nil - } - return bytes.Equal(exp, act) -} - -// copyExportedFields iterates downward through nested data structures and creates a copy -// that only contains the exported struct fields. -func copyExportedFields(expected interface{}) interface{} { - if isNil(expected) { - return expected - } - - expectedType := reflect.TypeOf(expected) - expectedKind := expectedType.Kind() - expectedValue := reflect.ValueOf(expected) - - switch expectedKind { - case reflect.Struct: - result := reflect.New(expectedType).Elem() - for i := 0; i < expectedType.NumField(); i++ { - field := expectedType.Field(i) - isExported := field.IsExported() - if isExported { - fieldValue := expectedValue.Field(i) - if isNil(fieldValue) || isNil(fieldValue.Interface()) { - continue - } - newValue := copyExportedFields(fieldValue.Interface()) - result.Field(i).Set(reflect.ValueOf(newValue)) - } - } - return result.Interface() - - case reflect.Ptr: - result := reflect.New(expectedType.Elem()) - unexportedRemoved := copyExportedFields(expectedValue.Elem().Interface()) - result.Elem().Set(reflect.ValueOf(unexportedRemoved)) - return result.Interface() - - case reflect.Array, reflect.Slice: - var result reflect.Value - if expectedKind == reflect.Array { - result = reflect.New(reflect.ArrayOf(expectedValue.Len(), expectedType.Elem())).Elem() - } else { - result = reflect.MakeSlice(expectedType, expectedValue.Len(), expectedValue.Len()) - } - for i := 0; i < expectedValue.Len(); i++ { - index := expectedValue.Index(i) - if isNil(index) { - continue - } - unexportedRemoved := copyExportedFields(index.Interface()) - result.Index(i).Set(reflect.ValueOf(unexportedRemoved)) - } - return result.Interface() - - case reflect.Map: - result := reflect.MakeMap(expectedType) - for _, k := range expectedValue.MapKeys() { - index := expectedValue.MapIndex(k) - unexportedRemoved := copyExportedFields(index.Interface()) - result.SetMapIndex(k, reflect.ValueOf(unexportedRemoved)) - } - return result.Interface() - - default: - return expected - } -} - -// ObjectsExportedFieldsAreEqual determines if the exported (public) fields of two objects are -// considered equal. This comparison of only exported fields is applied recursively to nested data -// structures. -// -// This function does no assertion of any kind. -// -// Deprecated: Use [EqualExportedValues] instead. -func ObjectsExportedFieldsAreEqual(expected, actual interface{}) bool { - expectedCleaned := copyExportedFields(expected) - actualCleaned := copyExportedFields(actual) - return ObjectsAreEqualValues(expectedCleaned, actualCleaned) -} - -// ObjectsAreEqualValues gets whether two objects are equal, or if their -// values are equal. -func ObjectsAreEqualValues(expected, actual interface{}) bool { - if ObjectsAreEqual(expected, actual) { - return true - } - - expectedValue := reflect.ValueOf(expected) - actualValue := reflect.ValueOf(actual) - if !expectedValue.IsValid() || !actualValue.IsValid() { - return false - } - - expectedType := expectedValue.Type() - actualType := actualValue.Type() - if !expectedType.ConvertibleTo(actualType) { - return false - } - - if !isNumericType(expectedType) || !isNumericType(actualType) { - // Attempt comparison after type conversion - return reflect.DeepEqual( - expectedValue.Convert(actualType).Interface(), actual, - ) - } - - // If BOTH values are numeric, there are chances of false positives due - // to overflow or underflow. So, we need to make sure to always convert - // the smaller type to a larger type before comparing. - if expectedType.Size() >= actualType.Size() { - return actualValue.Convert(expectedType).Interface() == expected - } - - return expectedValue.Convert(actualType).Interface() == actual -} - -// isNumericType returns true if the type is one of: -// int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, -// float32, float64, complex64, complex128 -func isNumericType(t reflect.Type) bool { - return t.Kind() >= reflect.Int && t.Kind() <= reflect.Complex128 -} - -/* CallerInfo is necessary because the assert functions use the testing object -internally, causing it to print the file:line of the assert method, rather than where -the problem actually occurred in calling code.*/ - -// CallerInfo returns an array of strings containing the file and line number -// of each stack frame leading from the current test to the assert call that -// failed. -func CallerInfo() []string { - - var pc uintptr - var ok bool - var file string - var line int - var name string - - callers := []string{} - for i := 0; ; i++ { - pc, file, line, ok = runtime.Caller(i) - if !ok { - // The breaks below failed to terminate the loop, and we ran off the - // end of the call stack. - break - } - - // This is a huge edge case, but it will panic if this is the case, see #180 - if file == "" { - break - } - - f := runtime.FuncForPC(pc) - if f == nil { - break - } - name = f.Name() - - // testing.tRunner is the standard library function that calls - // tests. Subtests are called directly by tRunner, without going through - // the Test/Benchmark/Example function that contains the t.Run calls, so - // with subtests we should break when we hit tRunner, without adding it - // to the list of callers. - if name == "testing.tRunner" { - break - } - - parts := strings.Split(file, "/") - if len(parts) > 1 { - filename := parts[len(parts)-1] - dir := parts[len(parts)-2] - if (dir != "assert" && dir != "mock" && dir != "require") || filename == "mock_test.go" { - callers = append(callers, fmt.Sprintf("%s:%d", file, line)) - } - } - - // Drop the package - segments := strings.Split(name, ".") - name = segments[len(segments)-1] - if isTest(name, "Test") || - isTest(name, "Benchmark") || - isTest(name, "Example") { - break - } - } - - return callers -} - -// Stolen from the `go test` tool. -// isTest tells whether name looks like a test (or benchmark, according to prefix). -// It is a Test (say) if there is a character after Test that is not a lower-case letter. -// We don't want TesticularCancer. -func isTest(name, prefix string) bool { - if !strings.HasPrefix(name, prefix) { - return false - } - if len(name) == len(prefix) { // "Test" is ok - return true - } - r, _ := utf8.DecodeRuneInString(name[len(prefix):]) - return !unicode.IsLower(r) -} - -func messageFromMsgAndArgs(msgAndArgs ...interface{}) string { - if len(msgAndArgs) == 0 || msgAndArgs == nil { - return "" - } - if len(msgAndArgs) == 1 { - msg := msgAndArgs[0] - if msgAsStr, ok := msg.(string); ok { - return msgAsStr - } - return fmt.Sprintf("%+v", msg) - } - if len(msgAndArgs) > 1 { - return fmt.Sprintf(msgAndArgs[0].(string), msgAndArgs[1:]...) - } - return "" -} - -// Aligns the provided message so that all lines after the first line start at the same location as the first line. -// Assumes that the first line starts at the correct location (after carriage return, tab, label, spacer and tab). -// The longestLabelLen parameter specifies the length of the longest label in the output (required because this is the -// basis on which the alignment occurs). -func indentMessageLines(message string, longestLabelLen int) string { - outBuf := new(bytes.Buffer) - - for i, scanner := 0, bufio.NewScanner(strings.NewReader(message)); scanner.Scan(); i++ { - // no need to align first line because it starts at the correct location (after the label) - if i != 0 { - // append alignLen+1 spaces to align with "{{longestLabel}}:" before adding tab - outBuf.WriteString("\n\t" + strings.Repeat(" ", longestLabelLen+1) + "\t") - } - outBuf.WriteString(scanner.Text()) - } - - return outBuf.String() -} - -type failNower interface { - FailNow() -} - -// FailNow fails test -func FailNow(t TestingT, failureMessage string, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - Fail(t, failureMessage, msgAndArgs...) - - // We cannot extend TestingT with FailNow() and - // maintain backwards compatibility, so we fallback - // to panicking when FailNow is not available in - // TestingT. - // See issue #263 - - if t, ok := t.(failNower); ok { - t.FailNow() - } else { - panic("test failed and t is missing `FailNow()`") - } - return false -} - -// Fail reports a failure through -func Fail(t TestingT, failureMessage string, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - content := []labeledContent{ - {"Error Trace", strings.Join(CallerInfo(), "\n\t\t\t")}, - {"Error", failureMessage}, - } - - // Add test name if the Go version supports it - if n, ok := t.(interface { - Name() string - }); ok { - content = append(content, labeledContent{"Test", n.Name()}) - } - - message := messageFromMsgAndArgs(msgAndArgs...) - if len(message) > 0 { - content = append(content, labeledContent{"Messages", message}) - } - - t.Errorf("\n%s", ""+labeledOutput(content...)) - - return false -} - -type labeledContent struct { - label string - content string -} - -// labeledOutput returns a string consisting of the provided labeledContent. Each labeled output is appended in the following manner: -// -// \t{{label}}:{{align_spaces}}\t{{content}}\n -// -// The initial carriage return is required to undo/erase any padding added by testing.T.Errorf. The "\t{{label}}:" is for the label. -// If a label is shorter than the longest label provided, padding spaces are added to make all the labels match in length. Once this -// alignment is achieved, "\t{{content}}\n" is added for the output. -// -// If the content of the labeledOutput contains line breaks, the subsequent lines are aligned so that they start at the same location as the first line. -func labeledOutput(content ...labeledContent) string { - longestLabel := 0 - for _, v := range content { - if len(v.label) > longestLabel { - longestLabel = len(v.label) - } - } - var output string - for _, v := range content { - output += "\t" + v.label + ":" + strings.Repeat(" ", longestLabel-len(v.label)) + "\t" + indentMessageLines(v.content, longestLabel) + "\n" - } - return output -} - -// Implements asserts that an object is implemented by the specified interface. -// -// assert.Implements(t, (*MyInterface)(nil), new(MyObject)) -func Implements(t TestingT, interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - interfaceType := reflect.TypeOf(interfaceObject).Elem() - - if object == nil { - return Fail(t, fmt.Sprintf("Cannot check if nil implements %v", interfaceType), msgAndArgs...) - } - if !reflect.TypeOf(object).Implements(interfaceType) { - return Fail(t, fmt.Sprintf("%T must implement %v", object, interfaceType), msgAndArgs...) - } - - return true -} - -// NotImplements asserts that an object does not implement the specified interface. -// -// assert.NotImplements(t, (*MyInterface)(nil), new(MyObject)) -func NotImplements(t TestingT, interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - interfaceType := reflect.TypeOf(interfaceObject).Elem() - - if object == nil { - return Fail(t, fmt.Sprintf("Cannot check if nil does not implement %v", interfaceType), msgAndArgs...) - } - if reflect.TypeOf(object).Implements(interfaceType) { - return Fail(t, fmt.Sprintf("%T implements %v", object, interfaceType), msgAndArgs...) - } - - return true -} - -// IsType asserts that the specified objects are of the same type. -func IsType(t TestingT, expectedType interface{}, object interface{}, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - - if !ObjectsAreEqual(reflect.TypeOf(object), reflect.TypeOf(expectedType)) { - return Fail(t, fmt.Sprintf("Object expected to be of type %v, but was %v", reflect.TypeOf(expectedType), reflect.TypeOf(object)), msgAndArgs...) - } - - return true -} - -// Equal asserts that two objects are equal. -// -// assert.Equal(t, 123, 123) -// -// Pointer variable equality is determined based on the equality of the -// referenced values (as opposed to the memory addresses). Function equality -// cannot be determined and will always fail. -func Equal(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if err := validateEqualArgs(expected, actual); err != nil { - return Fail(t, fmt.Sprintf("Invalid operation: %#v == %#v (%s)", - expected, actual, err), msgAndArgs...) - } - - if !ObjectsAreEqual(expected, actual) { - diff := diff(expected, actual) - expected, actual = formatUnequalValues(expected, actual) - return Fail(t, fmt.Sprintf("Not equal: \n"+ - "expected: %s\n"+ - "actual : %s%s", expected, actual, diff), msgAndArgs...) - } - - return true - -} - -// validateEqualArgs checks whether provided arguments can be safely used in the -// Equal/NotEqual functions. -func validateEqualArgs(expected, actual interface{}) error { - if expected == nil && actual == nil { - return nil - } - - if isFunction(expected) || isFunction(actual) { - return errors.New("cannot take func type as argument") - } - return nil -} - -// Same asserts that two pointers reference the same object. -// -// assert.Same(t, ptr1, ptr2) -// -// Both arguments must be pointer variables. Pointer variable sameness is -// determined based on the equality of both type and value. -func Same(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - - if !samePointers(expected, actual) { - return Fail(t, fmt.Sprintf("Not same: \n"+ - "expected: %p %#v\n"+ - "actual : %p %#v", expected, expected, actual, actual), msgAndArgs...) - } - - return true -} - -// NotSame asserts that two pointers do not reference the same object. -// -// assert.NotSame(t, ptr1, ptr2) -// -// Both arguments must be pointer variables. Pointer variable sameness is -// determined based on the equality of both type and value. -func NotSame(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - - if samePointers(expected, actual) { - return Fail(t, fmt.Sprintf( - "Expected and actual point to the same object: %p %#v", - expected, expected), msgAndArgs...) - } - return true -} - -// samePointers compares two generic interface objects and returns whether -// they point to the same object -func samePointers(first, second interface{}) bool { - firstPtr, secondPtr := reflect.ValueOf(first), reflect.ValueOf(second) - if firstPtr.Kind() != reflect.Ptr || secondPtr.Kind() != reflect.Ptr { - return false - } - - firstType, secondType := reflect.TypeOf(first), reflect.TypeOf(second) - if firstType != secondType { - return false - } - - // compare pointer addresses - return first == second -} - -// formatUnequalValues takes two values of arbitrary types and returns string -// representations appropriate to be presented to the user. -// -// If the values are not of like type, the returned strings will be prefixed -// with the type name, and the value will be enclosed in parentheses similar -// to a type conversion in the Go grammar. -func formatUnequalValues(expected, actual interface{}) (e string, a string) { - if reflect.TypeOf(expected) != reflect.TypeOf(actual) { - return fmt.Sprintf("%T(%s)", expected, truncatingFormat(expected)), - fmt.Sprintf("%T(%s)", actual, truncatingFormat(actual)) - } - switch expected.(type) { - case time.Duration: - return fmt.Sprintf("%v", expected), fmt.Sprintf("%v", actual) - } - return truncatingFormat(expected), truncatingFormat(actual) -} - -// truncatingFormat formats the data and truncates it if it's too long. -// -// This helps keep formatted error messages lines from exceeding the -// bufio.MaxScanTokenSize max line length that the go testing framework imposes. -func truncatingFormat(data interface{}) string { - value := fmt.Sprintf("%#v", data) - max := bufio.MaxScanTokenSize - 100 // Give us some space the type info too if needed. - if len(value) > max { - value = value[0:max] + "<... truncated>" - } - return value -} - -// EqualValues asserts that two objects are equal or convertible to the same types -// and equal. -// -// assert.EqualValues(t, uint32(123), int32(123)) -func EqualValues(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - - if !ObjectsAreEqualValues(expected, actual) { - diff := diff(expected, actual) - expected, actual = formatUnequalValues(expected, actual) - return Fail(t, fmt.Sprintf("Not equal: \n"+ - "expected: %s\n"+ - "actual : %s%s", expected, actual, diff), msgAndArgs...) - } - - return true - -} - -// EqualExportedValues asserts that the types of two objects are equal and their public -// fields are also equal. This is useful for comparing structs that have private fields -// that could potentially differ. -// -// type S struct { -// Exported int -// notExported int -// } -// assert.EqualExportedValues(t, S{1, 2}, S{1, 3}) => true -// assert.EqualExportedValues(t, S{1, 2}, S{2, 3}) => false -func EqualExportedValues(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - - aType := reflect.TypeOf(expected) - bType := reflect.TypeOf(actual) - - if aType != bType { - return Fail(t, fmt.Sprintf("Types expected to match exactly\n\t%v != %v", aType, bType), msgAndArgs...) - } - - if aType.Kind() == reflect.Ptr { - aType = aType.Elem() - } - if bType.Kind() == reflect.Ptr { - bType = bType.Elem() - } - - if aType.Kind() != reflect.Struct { - return Fail(t, fmt.Sprintf("Types expected to both be struct or pointer to struct \n\t%v != %v", aType.Kind(), reflect.Struct), msgAndArgs...) - } - - if bType.Kind() != reflect.Struct { - return Fail(t, fmt.Sprintf("Types expected to both be struct or pointer to struct \n\t%v != %v", bType.Kind(), reflect.Struct), msgAndArgs...) - } - - expected = copyExportedFields(expected) - actual = copyExportedFields(actual) - - if !ObjectsAreEqualValues(expected, actual) { - diff := diff(expected, actual) - expected, actual = formatUnequalValues(expected, actual) - return Fail(t, fmt.Sprintf("Not equal (comparing only exported fields): \n"+ - "expected: %s\n"+ - "actual : %s%s", expected, actual, diff), msgAndArgs...) - } - - return true -} - -// Exactly asserts that two objects are equal in value and type. -// -// assert.Exactly(t, int32(123), int64(123)) -func Exactly(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - - aType := reflect.TypeOf(expected) - bType := reflect.TypeOf(actual) - - if aType != bType { - return Fail(t, fmt.Sprintf("Types expected to match exactly\n\t%v != %v", aType, bType), msgAndArgs...) - } - - return Equal(t, expected, actual, msgAndArgs...) - -} - -// NotNil asserts that the specified object is not nil. -// -// assert.NotNil(t, err) -func NotNil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { - if !isNil(object) { - return true - } - if h, ok := t.(tHelper); ok { - h.Helper() - } - return Fail(t, "Expected value not to be nil.", msgAndArgs...) -} - -// isNil checks if a specified object is nil or not, without Failing. -func isNil(object interface{}) bool { - if object == nil { - return true - } - - value := reflect.ValueOf(object) - switch value.Kind() { - case - reflect.Chan, reflect.Func, - reflect.Interface, reflect.Map, - reflect.Ptr, reflect.Slice, reflect.UnsafePointer: - - return value.IsNil() - } - - return false -} - -// Nil asserts that the specified object is nil. -// -// assert.Nil(t, err) -func Nil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { - if isNil(object) { - return true - } - if h, ok := t.(tHelper); ok { - h.Helper() - } - return Fail(t, fmt.Sprintf("Expected nil, but got: %#v", object), msgAndArgs...) -} - -// isEmpty gets whether the specified object is considered empty or not. -func isEmpty(object interface{}) bool { - - // get nil case out of the way - if object == nil { - return true - } - - objValue := reflect.ValueOf(object) - - switch objValue.Kind() { - // collection types are empty when they have no element - case reflect.Chan, reflect.Map, reflect.Slice: - return objValue.Len() == 0 - // pointers are empty if nil or if the value they point to is empty - case reflect.Ptr: - if objValue.IsNil() { - return true - } - deref := objValue.Elem().Interface() - return isEmpty(deref) - // for all other types, compare against the zero value - // array types are empty when they match their zero-initialized state - default: - zero := reflect.Zero(objValue.Type()) - return reflect.DeepEqual(object, zero.Interface()) - } -} - -// Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or either -// a slice or a channel with len == 0. -// -// assert.Empty(t, obj) -func Empty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { - pass := isEmpty(object) - if !pass { - if h, ok := t.(tHelper); ok { - h.Helper() - } - Fail(t, fmt.Sprintf("Should be empty, but was %v", object), msgAndArgs...) - } - - return pass - -} - -// NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either -// a slice or a channel with len == 0. -// -// if assert.NotEmpty(t, obj) { -// assert.Equal(t, "two", obj[1]) -// } -func NotEmpty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { - pass := !isEmpty(object) - if !pass { - if h, ok := t.(tHelper); ok { - h.Helper() - } - Fail(t, fmt.Sprintf("Should NOT be empty, but was %v", object), msgAndArgs...) - } - - return pass - -} - -// getLen tries to get the length of an object. -// It returns (0, false) if impossible. -func getLen(x interface{}) (length int, ok bool) { - v := reflect.ValueOf(x) - defer func() { - ok = recover() == nil - }() - return v.Len(), true -} - -// Len asserts that the specified object has specific length. -// Len also fails if the object has a type that len() not accept. -// -// assert.Len(t, mySlice, 3) -func Len(t TestingT, object interface{}, length int, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - l, ok := getLen(object) - if !ok { - return Fail(t, fmt.Sprintf("\"%v\" could not be applied builtin len()", object), msgAndArgs...) - } - - if l != length { - return Fail(t, fmt.Sprintf("\"%v\" should have %d item(s), but has %d", object, length, l), msgAndArgs...) - } - return true -} - -// True asserts that the specified value is true. -// -// assert.True(t, myBool) -func True(t TestingT, value bool, msgAndArgs ...interface{}) bool { - if !value { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return Fail(t, "Should be true", msgAndArgs...) - } - - return true - -} - -// False asserts that the specified value is false. -// -// assert.False(t, myBool) -func False(t TestingT, value bool, msgAndArgs ...interface{}) bool { - if value { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return Fail(t, "Should be false", msgAndArgs...) - } - - return true - -} - -// NotEqual asserts that the specified values are NOT equal. -// -// assert.NotEqual(t, obj1, obj2) -// -// Pointer variable equality is determined based on the equality of the -// referenced values (as opposed to the memory addresses). -func NotEqual(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if err := validateEqualArgs(expected, actual); err != nil { - return Fail(t, fmt.Sprintf("Invalid operation: %#v != %#v (%s)", - expected, actual, err), msgAndArgs...) - } - - if ObjectsAreEqual(expected, actual) { - return Fail(t, fmt.Sprintf("Should not be: %#v\n", actual), msgAndArgs...) - } - - return true - -} - -// NotEqualValues asserts that two objects are not equal even when converted to the same type -// -// assert.NotEqualValues(t, obj1, obj2) -func NotEqualValues(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - - if ObjectsAreEqualValues(expected, actual) { - return Fail(t, fmt.Sprintf("Should not be: %#v\n", actual), msgAndArgs...) - } - - return true -} - -// containsElement try loop over the list check if the list includes the element. -// return (false, false) if impossible. -// return (true, false) if element was not found. -// return (true, true) if element was found. -func containsElement(list interface{}, element interface{}) (ok, found bool) { - - listValue := reflect.ValueOf(list) - listType := reflect.TypeOf(list) - if listType == nil { - return false, false - } - listKind := listType.Kind() - defer func() { - if e := recover(); e != nil { - ok = false - found = false - } - }() - - if listKind == reflect.String { - elementValue := reflect.ValueOf(element) - return true, strings.Contains(listValue.String(), elementValue.String()) - } - - if listKind == reflect.Map { - mapKeys := listValue.MapKeys() - for i := 0; i < len(mapKeys); i++ { - if ObjectsAreEqual(mapKeys[i].Interface(), element) { - return true, true - } - } - return true, false - } - - for i := 0; i < listValue.Len(); i++ { - if ObjectsAreEqual(listValue.Index(i).Interface(), element) { - return true, true - } - } - return true, false - -} - -// Contains asserts that the specified string, list(array, slice...) or map contains the -// specified substring or element. -// -// assert.Contains(t, "Hello World", "World") -// assert.Contains(t, ["Hello", "World"], "World") -// assert.Contains(t, {"Hello": "World"}, "Hello") -func Contains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - - ok, found := containsElement(s, contains) - if !ok { - return Fail(t, fmt.Sprintf("%#v could not be applied builtin len()", s), msgAndArgs...) - } - if !found { - return Fail(t, fmt.Sprintf("%#v does not contain %#v", s, contains), msgAndArgs...) - } - - return true - -} - -// NotContains asserts that the specified string, list(array, slice...) or map does NOT contain the -// specified substring or element. -// -// assert.NotContains(t, "Hello World", "Earth") -// assert.NotContains(t, ["Hello", "World"], "Earth") -// assert.NotContains(t, {"Hello": "World"}, "Earth") -func NotContains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - - ok, found := containsElement(s, contains) - if !ok { - return Fail(t, fmt.Sprintf("%#v could not be applied builtin len()", s), msgAndArgs...) - } - if found { - return Fail(t, fmt.Sprintf("%#v should not contain %#v", s, contains), msgAndArgs...) - } - - return true - -} - -// Subset asserts that the specified list(array, slice...) or map contains all -// elements given in the specified subset list(array, slice...) or map. -// -// assert.Subset(t, [1, 2, 3], [1, 2]) -// assert.Subset(t, {"x": 1, "y": 2}, {"x": 1}) -func Subset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok bool) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if subset == nil { - return true // we consider nil to be equal to the nil set - } - - listKind := reflect.TypeOf(list).Kind() - if listKind != reflect.Array && listKind != reflect.Slice && listKind != reflect.Map { - return Fail(t, fmt.Sprintf("%q has an unsupported type %s", list, listKind), msgAndArgs...) - } - - subsetKind := reflect.TypeOf(subset).Kind() - if subsetKind != reflect.Array && subsetKind != reflect.Slice && listKind != reflect.Map { - return Fail(t, fmt.Sprintf("%q has an unsupported type %s", subset, subsetKind), msgAndArgs...) - } - - if subsetKind == reflect.Map && listKind == reflect.Map { - subsetMap := reflect.ValueOf(subset) - actualMap := reflect.ValueOf(list) - - for _, k := range subsetMap.MapKeys() { - ev := subsetMap.MapIndex(k) - av := actualMap.MapIndex(k) - - if !av.IsValid() { - return Fail(t, fmt.Sprintf("%#v does not contain %#v", list, subset), msgAndArgs...) - } - if !ObjectsAreEqual(ev.Interface(), av.Interface()) { - return Fail(t, fmt.Sprintf("%#v does not contain %#v", list, subset), msgAndArgs...) - } - } - - return true - } - - subsetList := reflect.ValueOf(subset) - for i := 0; i < subsetList.Len(); i++ { - element := subsetList.Index(i).Interface() - ok, found := containsElement(list, element) - if !ok { - return Fail(t, fmt.Sprintf("%#v could not be applied builtin len()", list), msgAndArgs...) - } - if !found { - return Fail(t, fmt.Sprintf("%#v does not contain %#v", list, element), msgAndArgs...) - } - } - - return true -} - -// NotSubset asserts that the specified list(array, slice...) or map does NOT -// contain all elements given in the specified subset list(array, slice...) or -// map. -// -// assert.NotSubset(t, [1, 3, 4], [1, 2]) -// assert.NotSubset(t, {"x": 1, "y": 2}, {"z": 3}) -func NotSubset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok bool) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if subset == nil { - return Fail(t, "nil is the empty set which is a subset of every set", msgAndArgs...) - } - - listKind := reflect.TypeOf(list).Kind() - if listKind != reflect.Array && listKind != reflect.Slice && listKind != reflect.Map { - return Fail(t, fmt.Sprintf("%q has an unsupported type %s", list, listKind), msgAndArgs...) - } - - subsetKind := reflect.TypeOf(subset).Kind() - if subsetKind != reflect.Array && subsetKind != reflect.Slice && listKind != reflect.Map { - return Fail(t, fmt.Sprintf("%q has an unsupported type %s", subset, subsetKind), msgAndArgs...) - } - - if subsetKind == reflect.Map && listKind == reflect.Map { - subsetMap := reflect.ValueOf(subset) - actualMap := reflect.ValueOf(list) - - for _, k := range subsetMap.MapKeys() { - ev := subsetMap.MapIndex(k) - av := actualMap.MapIndex(k) - - if !av.IsValid() { - return true - } - if !ObjectsAreEqual(ev.Interface(), av.Interface()) { - return true - } - } - - return Fail(t, fmt.Sprintf("%q is a subset of %q", subset, list), msgAndArgs...) - } - - subsetList := reflect.ValueOf(subset) - for i := 0; i < subsetList.Len(); i++ { - element := subsetList.Index(i).Interface() - ok, found := containsElement(list, element) - if !ok { - return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", list), msgAndArgs...) - } - if !found { - return true - } - } - - return Fail(t, fmt.Sprintf("%q is a subset of %q", subset, list), msgAndArgs...) -} - -// ElementsMatch asserts that the specified listA(array, slice...) is equal to specified -// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, -// the number of appearances of each of them in both lists should match. -// -// assert.ElementsMatch(t, [1, 3, 2, 3], [1, 3, 3, 2]) -func ElementsMatch(t TestingT, listA, listB interface{}, msgAndArgs ...interface{}) (ok bool) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if isEmpty(listA) && isEmpty(listB) { - return true - } - - if !isList(t, listA, msgAndArgs...) || !isList(t, listB, msgAndArgs...) { - return false - } - - extraA, extraB := diffLists(listA, listB) - - if len(extraA) == 0 && len(extraB) == 0 { - return true - } - - return Fail(t, formatListDiff(listA, listB, extraA, extraB), msgAndArgs...) -} - -// isList checks that the provided value is array or slice. -func isList(t TestingT, list interface{}, msgAndArgs ...interface{}) (ok bool) { - kind := reflect.TypeOf(list).Kind() - if kind != reflect.Array && kind != reflect.Slice { - return Fail(t, fmt.Sprintf("%q has an unsupported type %s, expecting array or slice", list, kind), - msgAndArgs...) - } - return true -} - -// diffLists diffs two arrays/slices and returns slices of elements that are only in A and only in B. -// If some element is present multiple times, each instance is counted separately (e.g. if something is 2x in A and -// 5x in B, it will be 0x in extraA and 3x in extraB). The order of items in both lists is ignored. -func diffLists(listA, listB interface{}) (extraA, extraB []interface{}) { - aValue := reflect.ValueOf(listA) - bValue := reflect.ValueOf(listB) - - aLen := aValue.Len() - bLen := bValue.Len() - - // Mark indexes in bValue that we already used - visited := make([]bool, bLen) - for i := 0; i < aLen; i++ { - element := aValue.Index(i).Interface() - found := false - for j := 0; j < bLen; j++ { - if visited[j] { - continue - } - if ObjectsAreEqual(bValue.Index(j).Interface(), element) { - visited[j] = true - found = true - break - } - } - if !found { - extraA = append(extraA, element) - } - } - - for j := 0; j < bLen; j++ { - if visited[j] { - continue - } - extraB = append(extraB, bValue.Index(j).Interface()) - } - - return -} - -func formatListDiff(listA, listB interface{}, extraA, extraB []interface{}) string { - var msg bytes.Buffer - - msg.WriteString("elements differ") - if len(extraA) > 0 { - msg.WriteString("\n\nextra elements in list A:\n") - msg.WriteString(spewConfig.Sdump(extraA)) - } - if len(extraB) > 0 { - msg.WriteString("\n\nextra elements in list B:\n") - msg.WriteString(spewConfig.Sdump(extraB)) - } - msg.WriteString("\n\nlistA:\n") - msg.WriteString(spewConfig.Sdump(listA)) - msg.WriteString("\n\nlistB:\n") - msg.WriteString(spewConfig.Sdump(listB)) - - return msg.String() -} - -// Condition uses a Comparison to assert a complex condition. -func Condition(t TestingT, comp Comparison, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - result := comp() - if !result { - Fail(t, "Condition failed!", msgAndArgs...) - } - return result -} - -// PanicTestFunc defines a func that should be passed to the assert.Panics and assert.NotPanics -// methods, and represents a simple func that takes no arguments, and returns nothing. -type PanicTestFunc func() - -// didPanic returns true if the function passed to it panics. Otherwise, it returns false. -func didPanic(f PanicTestFunc) (didPanic bool, message interface{}, stack string) { - didPanic = true - - defer func() { - message = recover() - if didPanic { - stack = string(debug.Stack()) - } - }() - - // call the target function - f() - didPanic = false - - return -} - -// Panics asserts that the code inside the specified PanicTestFunc panics. -// -// assert.Panics(t, func(){ GoCrazy() }) -func Panics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - - if funcDidPanic, panicValue, _ := didPanic(f); !funcDidPanic { - return Fail(t, fmt.Sprintf("func %#v should panic\n\tPanic value:\t%#v", f, panicValue), msgAndArgs...) - } - - return true -} - -// PanicsWithValue asserts that the code inside the specified PanicTestFunc panics, and that -// the recovered panic value equals the expected panic value. -// -// assert.PanicsWithValue(t, "crazy error", func(){ GoCrazy() }) -func PanicsWithValue(t TestingT, expected interface{}, f PanicTestFunc, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - - funcDidPanic, panicValue, panickedStack := didPanic(f) - if !funcDidPanic { - return Fail(t, fmt.Sprintf("func %#v should panic\n\tPanic value:\t%#v", f, panicValue), msgAndArgs...) - } - if panicValue != expected { - return Fail(t, fmt.Sprintf("func %#v should panic with value:\t%#v\n\tPanic value:\t%#v\n\tPanic stack:\t%s", f, expected, panicValue, panickedStack), msgAndArgs...) - } - - return true -} - -// PanicsWithError asserts that the code inside the specified PanicTestFunc -// panics, and that the recovered panic value is an error that satisfies the -// EqualError comparison. -// -// assert.PanicsWithError(t, "crazy error", func(){ GoCrazy() }) -func PanicsWithError(t TestingT, errString string, f PanicTestFunc, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - - funcDidPanic, panicValue, panickedStack := didPanic(f) - if !funcDidPanic { - return Fail(t, fmt.Sprintf("func %#v should panic\n\tPanic value:\t%#v", f, panicValue), msgAndArgs...) - } - panicErr, ok := panicValue.(error) - if !ok || panicErr.Error() != errString { - return Fail(t, fmt.Sprintf("func %#v should panic with error message:\t%#v\n\tPanic value:\t%#v\n\tPanic stack:\t%s", f, errString, panicValue, panickedStack), msgAndArgs...) - } - - return true -} - -// NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic. -// -// assert.NotPanics(t, func(){ RemainCalm() }) -func NotPanics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - - if funcDidPanic, panicValue, panickedStack := didPanic(f); funcDidPanic { - return Fail(t, fmt.Sprintf("func %#v should not panic\n\tPanic value:\t%v\n\tPanic stack:\t%s", f, panicValue, panickedStack), msgAndArgs...) - } - - return true -} - -// WithinDuration asserts that the two times are within duration delta of each other. -// -// assert.WithinDuration(t, time.Now(), time.Now(), 10*time.Second) -func WithinDuration(t TestingT, expected, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - - dt := expected.Sub(actual) - if dt < -delta || dt > delta { - return Fail(t, fmt.Sprintf("Max difference between %v and %v allowed is %v, but difference was %v", expected, actual, delta, dt), msgAndArgs...) - } - - return true -} - -// WithinRange asserts that a time is within a time range (inclusive). -// -// assert.WithinRange(t, time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second)) -func WithinRange(t TestingT, actual, start, end time.Time, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - - if end.Before(start) { - return Fail(t, "Start should be before end", msgAndArgs...) - } - - if actual.Before(start) { - return Fail(t, fmt.Sprintf("Time %v expected to be in time range %v to %v, but is before the range", actual, start, end), msgAndArgs...) - } else if actual.After(end) { - return Fail(t, fmt.Sprintf("Time %v expected to be in time range %v to %v, but is after the range", actual, start, end), msgAndArgs...) - } - - return true -} - -func toFloat(x interface{}) (float64, bool) { - var xf float64 - xok := true - - switch xn := x.(type) { - case uint: - xf = float64(xn) - case uint8: - xf = float64(xn) - case uint16: - xf = float64(xn) - case uint32: - xf = float64(xn) - case uint64: - xf = float64(xn) - case int: - xf = float64(xn) - case int8: - xf = float64(xn) - case int16: - xf = float64(xn) - case int32: - xf = float64(xn) - case int64: - xf = float64(xn) - case float32: - xf = float64(xn) - case float64: - xf = xn - case time.Duration: - xf = float64(xn) - default: - xok = false - } - - return xf, xok -} - -// InDelta asserts that the two numerals are within delta of each other. -// -// assert.InDelta(t, math.Pi, 22/7.0, 0.01) -func InDelta(t TestingT, expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - - af, aok := toFloat(expected) - bf, bok := toFloat(actual) - - if !aok || !bok { - return Fail(t, "Parameters must be numerical", msgAndArgs...) - } - - if math.IsNaN(af) && math.IsNaN(bf) { - return true - } - - if math.IsNaN(af) { - return Fail(t, "Expected must not be NaN", msgAndArgs...) - } - - if math.IsNaN(bf) { - return Fail(t, fmt.Sprintf("Expected %v with delta %v, but was NaN", expected, delta), msgAndArgs...) - } - - dt := af - bf - if dt < -delta || dt > delta { - return Fail(t, fmt.Sprintf("Max difference between %v and %v allowed is %v, but difference was %v", expected, actual, delta, dt), msgAndArgs...) - } - - return true -} - -// InDeltaSlice is the same as InDelta, except it compares two slices. -func InDeltaSlice(t TestingT, expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if expected == nil || actual == nil || - reflect.TypeOf(actual).Kind() != reflect.Slice || - reflect.TypeOf(expected).Kind() != reflect.Slice { - return Fail(t, "Parameters must be slice", msgAndArgs...) - } - - actualSlice := reflect.ValueOf(actual) - expectedSlice := reflect.ValueOf(expected) - - for i := 0; i < actualSlice.Len(); i++ { - result := InDelta(t, actualSlice.Index(i).Interface(), expectedSlice.Index(i).Interface(), delta, msgAndArgs...) - if !result { - return result - } - } - - return true -} - -// InDeltaMapValues is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys. -func InDeltaMapValues(t TestingT, expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if expected == nil || actual == nil || - reflect.TypeOf(actual).Kind() != reflect.Map || - reflect.TypeOf(expected).Kind() != reflect.Map { - return Fail(t, "Arguments must be maps", msgAndArgs...) - } - - expectedMap := reflect.ValueOf(expected) - actualMap := reflect.ValueOf(actual) - - if expectedMap.Len() != actualMap.Len() { - return Fail(t, "Arguments must have the same number of keys", msgAndArgs...) - } - - for _, k := range expectedMap.MapKeys() { - ev := expectedMap.MapIndex(k) - av := actualMap.MapIndex(k) - - if !ev.IsValid() { - return Fail(t, fmt.Sprintf("missing key %q in expected map", k), msgAndArgs...) - } - - if !av.IsValid() { - return Fail(t, fmt.Sprintf("missing key %q in actual map", k), msgAndArgs...) - } - - if !InDelta( - t, - ev.Interface(), - av.Interface(), - delta, - msgAndArgs..., - ) { - return false - } - } - - return true -} - -func calcRelativeError(expected, actual interface{}) (float64, error) { - af, aok := toFloat(expected) - bf, bok := toFloat(actual) - if !aok || !bok { - return 0, fmt.Errorf("Parameters must be numerical") - } - if math.IsNaN(af) && math.IsNaN(bf) { - return 0, nil - } - if math.IsNaN(af) { - return 0, errors.New("expected value must not be NaN") - } - if af == 0 { - return 0, fmt.Errorf("expected value must have a value other than zero to calculate the relative error") - } - if math.IsNaN(bf) { - return 0, errors.New("actual value must not be NaN") - } - - return math.Abs(af-bf) / math.Abs(af), nil -} - -// InEpsilon asserts that expected and actual have a relative error less than epsilon -func InEpsilon(t TestingT, expected, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if math.IsNaN(epsilon) { - return Fail(t, "epsilon must not be NaN", msgAndArgs...) - } - actualEpsilon, err := calcRelativeError(expected, actual) - if err != nil { - return Fail(t, err.Error(), msgAndArgs...) - } - if actualEpsilon > epsilon { - return Fail(t, fmt.Sprintf("Relative error is too high: %#v (expected)\n"+ - " < %#v (actual)", epsilon, actualEpsilon), msgAndArgs...) - } - - return true -} - -// InEpsilonSlice is the same as InEpsilon, except it compares each value from two slices. -func InEpsilonSlice(t TestingT, expected, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - - if expected == nil || actual == nil { - return Fail(t, "Parameters must be slice", msgAndArgs...) - } - - expectedSlice := reflect.ValueOf(expected) - actualSlice := reflect.ValueOf(actual) - - if expectedSlice.Type().Kind() != reflect.Slice { - return Fail(t, "Expected value must be slice", msgAndArgs...) - } - - expectedLen := expectedSlice.Len() - if !IsType(t, expected, actual) || !Len(t, actual, expectedLen) { - return false - } - - for i := 0; i < expectedLen; i++ { - if !InEpsilon(t, expectedSlice.Index(i).Interface(), actualSlice.Index(i).Interface(), epsilon, "at index %d", i) { - return false - } - } - - return true -} - -/* - Errors -*/ - -// NoError asserts that a function returned no error (i.e. `nil`). -// -// actualObj, err := SomeFunction() -// if assert.NoError(t, err) { -// assert.Equal(t, expectedObj, actualObj) -// } -func NoError(t TestingT, err error, msgAndArgs ...interface{}) bool { - if err != nil { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return Fail(t, fmt.Sprintf("Received unexpected error:\n%+v", err), msgAndArgs...) - } - - return true -} - -// Error asserts that a function returned an error (i.e. not `nil`). -// -// actualObj, err := SomeFunction() -// if assert.Error(t, err) { -// assert.Equal(t, expectedError, err) -// } -func Error(t TestingT, err error, msgAndArgs ...interface{}) bool { - if err == nil { - if h, ok := t.(tHelper); ok { - h.Helper() - } - return Fail(t, "An error is expected but got nil.", msgAndArgs...) - } - - return true -} - -// EqualError asserts that a function returned an error (i.e. not `nil`) -// and that it is equal to the provided error. -// -// actualObj, err := SomeFunction() -// assert.EqualError(t, err, expectedErrorString) -func EqualError(t TestingT, theError error, errString string, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if !Error(t, theError, msgAndArgs...) { - return false - } - expected := errString - actual := theError.Error() - // don't need to use deep equals here, we know they are both strings - if expected != actual { - return Fail(t, fmt.Sprintf("Error message not equal:\n"+ - "expected: %q\n"+ - "actual : %q", expected, actual), msgAndArgs...) - } - return true -} - -// ErrorContains asserts that a function returned an error (i.e. not `nil`) -// and that the error contains the specified substring. -// -// actualObj, err := SomeFunction() -// assert.ErrorContains(t, err, expectedErrorSubString) -func ErrorContains(t TestingT, theError error, contains string, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if !Error(t, theError, msgAndArgs...) { - return false - } - - actual := theError.Error() - if !strings.Contains(actual, contains) { - return Fail(t, fmt.Sprintf("Error %#v does not contain %#v", actual, contains), msgAndArgs...) - } - - return true -} - -// matchRegexp return true if a specified regexp matches a string. -func matchRegexp(rx interface{}, str interface{}) bool { - - var r *regexp.Regexp - if rr, ok := rx.(*regexp.Regexp); ok { - r = rr - } else { - r = regexp.MustCompile(fmt.Sprint(rx)) - } - - return (r.FindStringIndex(fmt.Sprint(str)) != nil) - -} - -// Regexp asserts that a specified regexp matches a string. -// -// assert.Regexp(t, regexp.MustCompile("start"), "it's starting") -// assert.Regexp(t, "start...$", "it's not starting") -func Regexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - - match := matchRegexp(rx, str) - - if !match { - Fail(t, fmt.Sprintf("Expect \"%v\" to match \"%v\"", str, rx), msgAndArgs...) - } - - return match -} - -// NotRegexp asserts that a specified regexp does not match a string. -// -// assert.NotRegexp(t, regexp.MustCompile("starts"), "it's starting") -// assert.NotRegexp(t, "^start", "it's not starting") -func NotRegexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - match := matchRegexp(rx, str) - - if match { - Fail(t, fmt.Sprintf("Expect \"%v\" to NOT match \"%v\"", str, rx), msgAndArgs...) - } - - return !match - -} - -// Zero asserts that i is the zero value for its type. -func Zero(t TestingT, i interface{}, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if i != nil && !reflect.DeepEqual(i, reflect.Zero(reflect.TypeOf(i)).Interface()) { - return Fail(t, fmt.Sprintf("Should be zero, but was %v", i), msgAndArgs...) - } - return true -} - -// NotZero asserts that i is not the zero value for its type. -func NotZero(t TestingT, i interface{}, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if i == nil || reflect.DeepEqual(i, reflect.Zero(reflect.TypeOf(i)).Interface()) { - return Fail(t, fmt.Sprintf("Should not be zero, but was %v", i), msgAndArgs...) - } - return true -} - -// FileExists checks whether a file exists in the given path. It also fails if -// the path points to a directory or there is an error when trying to check the file. -func FileExists(t TestingT, path string, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - info, err := os.Lstat(path) - if err != nil { - if os.IsNotExist(err) { - return Fail(t, fmt.Sprintf("unable to find file %q", path), msgAndArgs...) - } - return Fail(t, fmt.Sprintf("error when running os.Lstat(%q): %s", path, err), msgAndArgs...) - } - if info.IsDir() { - return Fail(t, fmt.Sprintf("%q is a directory", path), msgAndArgs...) - } - return true -} - -// NoFileExists checks whether a file does not exist in a given path. It fails -// if the path points to an existing _file_ only. -func NoFileExists(t TestingT, path string, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - info, err := os.Lstat(path) - if err != nil { - return true - } - if info.IsDir() { - return true - } - return Fail(t, fmt.Sprintf("file %q exists", path), msgAndArgs...) -} - -// DirExists checks whether a directory exists in the given path. It also fails -// if the path is a file rather a directory or there is an error checking whether it exists. -func DirExists(t TestingT, path string, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - info, err := os.Lstat(path) - if err != nil { - if os.IsNotExist(err) { - return Fail(t, fmt.Sprintf("unable to find file %q", path), msgAndArgs...) - } - return Fail(t, fmt.Sprintf("error when running os.Lstat(%q): %s", path, err), msgAndArgs...) - } - if !info.IsDir() { - return Fail(t, fmt.Sprintf("%q is a file", path), msgAndArgs...) - } - return true -} - -// NoDirExists checks whether a directory does not exist in the given path. -// It fails if the path points to an existing _directory_ only. -func NoDirExists(t TestingT, path string, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - info, err := os.Lstat(path) - if err != nil { - if os.IsNotExist(err) { - return true - } - return true - } - if !info.IsDir() { - return true - } - return Fail(t, fmt.Sprintf("directory %q exists", path), msgAndArgs...) -} - -// JSONEq asserts that two JSON strings are equivalent. -// -// assert.JSONEq(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) -func JSONEq(t TestingT, expected string, actual string, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - var expectedJSONAsInterface, actualJSONAsInterface interface{} - - if err := json.Unmarshal([]byte(expected), &expectedJSONAsInterface); err != nil { - return Fail(t, fmt.Sprintf("Expected value ('%s') is not valid json.\nJSON parsing error: '%s'", expected, err.Error()), msgAndArgs...) - } - - if err := json.Unmarshal([]byte(actual), &actualJSONAsInterface); err != nil { - return Fail(t, fmt.Sprintf("Input ('%s') needs to be valid json.\nJSON parsing error: '%s'", actual, err.Error()), msgAndArgs...) - } - - return Equal(t, expectedJSONAsInterface, actualJSONAsInterface, msgAndArgs...) -} - -// YAMLEq asserts that two YAML strings are equivalent. -func YAMLEq(t TestingT, expected string, actual string, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - var expectedYAMLAsInterface, actualYAMLAsInterface interface{} - - if err := yaml.Unmarshal([]byte(expected), &expectedYAMLAsInterface); err != nil { - return Fail(t, fmt.Sprintf("Expected value ('%s') is not valid yaml.\nYAML parsing error: '%s'", expected, err.Error()), msgAndArgs...) - } - - if err := yaml.Unmarshal([]byte(actual), &actualYAMLAsInterface); err != nil { - return Fail(t, fmt.Sprintf("Input ('%s') needs to be valid yaml.\nYAML error: '%s'", actual, err.Error()), msgAndArgs...) - } - - return Equal(t, expectedYAMLAsInterface, actualYAMLAsInterface, msgAndArgs...) -} - -func typeAndKind(v interface{}) (reflect.Type, reflect.Kind) { - t := reflect.TypeOf(v) - k := t.Kind() - - if k == reflect.Ptr { - t = t.Elem() - k = t.Kind() - } - return t, k -} - -// diff returns a diff of both values as long as both are of the same type and -// are a struct, map, slice, array or string. Otherwise it returns an empty string. -func diff(expected interface{}, actual interface{}) string { - if expected == nil || actual == nil { - return "" - } - - et, ek := typeAndKind(expected) - at, _ := typeAndKind(actual) - - if et != at { - return "" - } - - if ek != reflect.Struct && ek != reflect.Map && ek != reflect.Slice && ek != reflect.Array && ek != reflect.String { - return "" - } - - var e, a string - - switch et { - case reflect.TypeOf(""): - e = reflect.ValueOf(expected).String() - a = reflect.ValueOf(actual).String() - case reflect.TypeOf(time.Time{}): - e = spewConfigStringerEnabled.Sdump(expected) - a = spewConfigStringerEnabled.Sdump(actual) - default: - e = spewConfig.Sdump(expected) - a = spewConfig.Sdump(actual) - } - - diff, _ := difflib.GetUnifiedDiffString(difflib.UnifiedDiff{ - A: difflib.SplitLines(e), - B: difflib.SplitLines(a), - FromFile: "Expected", - FromDate: "", - ToFile: "Actual", - ToDate: "", - Context: 1, - }) - - return "\n\nDiff:\n" + diff -} - -func isFunction(arg interface{}) bool { - if arg == nil { - return false - } - return reflect.TypeOf(arg).Kind() == reflect.Func -} - -var spewConfig = spew.ConfigState{ - Indent: " ", - DisablePointerAddresses: true, - DisableCapacities: true, - SortKeys: true, - DisableMethods: true, - MaxDepth: 10, -} - -var spewConfigStringerEnabled = spew.ConfigState{ - Indent: " ", - DisablePointerAddresses: true, - DisableCapacities: true, - SortKeys: true, - MaxDepth: 10, -} - -type tHelper interface { - Helper() -} - -// Eventually asserts that given condition will be met in waitFor time, -// periodically checking target function each tick. -// -// assert.Eventually(t, func() bool { return true; }, time.Second, 10*time.Millisecond) -func Eventually(t TestingT, condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - - ch := make(chan bool, 1) - - timer := time.NewTimer(waitFor) - defer timer.Stop() - - ticker := time.NewTicker(tick) - defer ticker.Stop() - - for tick := ticker.C; ; { - select { - case <-timer.C: - return Fail(t, "Condition never satisfied", msgAndArgs...) - case <-tick: - tick = nil - go func() { ch <- condition() }() - case v := <-ch: - if v { - return true - } - tick = ticker.C - } - } -} - -// CollectT implements the TestingT interface and collects all errors. -type CollectT struct { - errors []error -} - -// Errorf collects the error. -func (c *CollectT) Errorf(format string, args ...interface{}) { - c.errors = append(c.errors, fmt.Errorf(format, args...)) -} - -// FailNow panics. -func (*CollectT) FailNow() { - panic("Assertion failed") -} - -// Deprecated: That was a method for internal usage that should not have been published. Now just panics. -func (*CollectT) Reset() { - panic("Reset() is deprecated") -} - -// Deprecated: That was a method for internal usage that should not have been published. Now just panics. -func (*CollectT) Copy(TestingT) { - panic("Copy() is deprecated") -} - -// EventuallyWithT asserts that given condition will be met in waitFor time, -// periodically checking target function each tick. In contrast to Eventually, -// it supplies a CollectT to the condition function, so that the condition -// function can use the CollectT to call other assertions. -// The condition is considered "met" if no errors are raised in a tick. -// The supplied CollectT collects all errors from one tick (if there are any). -// If the condition is not met before waitFor, the collected errors of -// the last tick are copied to t. -// -// externalValue := false -// go func() { -// time.Sleep(8*time.Second) -// externalValue = true -// }() -// assert.EventuallyWithT(t, func(c *assert.CollectT) { -// // add assertions as needed; any assertion failure will fail the current tick -// assert.True(c, externalValue, "expected 'externalValue' to be true") -// }, 1*time.Second, 10*time.Second, "external state has not changed to 'true'; still false") -func EventuallyWithT(t TestingT, condition func(collect *CollectT), waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - - var lastFinishedTickErrs []error - ch := make(chan []error, 1) - - timer := time.NewTimer(waitFor) - defer timer.Stop() - - ticker := time.NewTicker(tick) - defer ticker.Stop() - - for tick := ticker.C; ; { - select { - case <-timer.C: - for _, err := range lastFinishedTickErrs { - t.Errorf("%v", err) - } - return Fail(t, "Condition never satisfied", msgAndArgs...) - case <-tick: - tick = nil - go func() { - collect := new(CollectT) - defer func() { - ch <- collect.errors - }() - condition(collect) - }() - case errs := <-ch: - if len(errs) == 0 { - return true - } - // Keep the errors from the last ended condition, so that they can be copied to t if timeout is reached. - lastFinishedTickErrs = errs - tick = ticker.C - } - } -} - -// Never asserts that the given condition doesn't satisfy in waitFor time, -// periodically checking the target function each tick. -// -// assert.Never(t, func() bool { return false; }, time.Second, 10*time.Millisecond) -func Never(t TestingT, condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - - ch := make(chan bool, 1) - - timer := time.NewTimer(waitFor) - defer timer.Stop() - - ticker := time.NewTicker(tick) - defer ticker.Stop() - - for tick := ticker.C; ; { - select { - case <-timer.C: - return true - case <-tick: - tick = nil - go func() { ch <- condition() }() - case v := <-ch: - if v { - return Fail(t, "Condition satisfied", msgAndArgs...) - } - tick = ticker.C - } - } -} - -// ErrorIs asserts that at least one of the errors in err's chain matches target. -// This is a wrapper for errors.Is. -func ErrorIs(t TestingT, err, target error, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if errors.Is(err, target) { - return true - } - - var expectedText string - if target != nil { - expectedText = target.Error() - } - - chain := buildErrorChainString(err) - - return Fail(t, fmt.Sprintf("Target error should be in err chain:\n"+ - "expected: %q\n"+ - "in chain: %s", expectedText, chain, - ), msgAndArgs...) -} - -// NotErrorIs asserts that at none of the errors in err's chain matches target. -// This is a wrapper for errors.Is. -func NotErrorIs(t TestingT, err, target error, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if !errors.Is(err, target) { - return true - } - - var expectedText string - if target != nil { - expectedText = target.Error() - } - - chain := buildErrorChainString(err) - - return Fail(t, fmt.Sprintf("Target error should not be in err chain:\n"+ - "found: %q\n"+ - "in chain: %s", expectedText, chain, - ), msgAndArgs...) -} - -// ErrorAs asserts that at least one of the errors in err's chain matches target, and if so, sets target to that error value. -// This is a wrapper for errors.As. -func ErrorAs(t TestingT, err error, target interface{}, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if errors.As(err, target) { - return true - } - - chain := buildErrorChainString(err) - - return Fail(t, fmt.Sprintf("Should be in error chain:\n"+ - "expected: %q\n"+ - "in chain: %s", target, chain, - ), msgAndArgs...) -} - -func buildErrorChainString(err error) string { - if err == nil { - return "" - } - - e := errors.Unwrap(err) - chain := fmt.Sprintf("%q", err.Error()) - for e != nil { - chain += fmt.Sprintf("\n\t%q", e.Error()) - e = errors.Unwrap(e) - } - return chain -} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/assert/doc.go b/trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/assert/doc.go deleted file mode 100644 index 4953981d3..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/assert/doc.go +++ /dev/null @@ -1,46 +0,0 @@ -// Package assert provides a set of comprehensive testing tools for use with the normal Go testing system. -// -// # Example Usage -// -// The following is a complete example using assert in a standard test function: -// -// import ( -// "testing" -// "github.com/stretchr/testify/assert" -// ) -// -// func TestSomething(t *testing.T) { -// -// var a string = "Hello" -// var b string = "Hello" -// -// assert.Equal(t, a, b, "The two words should be the same.") -// -// } -// -// if you assert many times, use the format below: -// -// import ( -// "testing" -// "github.com/stretchr/testify/assert" -// ) -// -// func TestSomething(t *testing.T) { -// assert := assert.New(t) -// -// var a string = "Hello" -// var b string = "Hello" -// -// assert.Equal(a, b, "The two words should be the same.") -// } -// -// # Assertions -// -// Assertions allow you to easily write test code, and are global funcs in the `assert` package. -// All assertion functions take, as the first argument, the `*testing.T` object provided by the -// testing framework. This allows the assertion funcs to write the failings and other details to -// the correct place. -// -// Every assertion function also takes an optional string message as the final argument, -// allowing custom error messages to be appended to the message the assertion method outputs. -package assert diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/assert/errors.go b/trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/assert/errors.go deleted file mode 100644 index ac9dc9d1d..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/assert/errors.go +++ /dev/null @@ -1,10 +0,0 @@ -package assert - -import ( - "errors" -) - -// AnError is an error instance useful for testing. If the code does not care -// about error specifics, and only needs to return the error for example, this -// error should be used to make the test code more readable. -var AnError = errors.New("assert.AnError general error for testing") diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/assert/forward_assertions.go b/trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/assert/forward_assertions.go deleted file mode 100644 index df189d234..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/assert/forward_assertions.go +++ /dev/null @@ -1,16 +0,0 @@ -package assert - -// Assertions provides assertion methods around the -// TestingT interface. -type Assertions struct { - t TestingT -} - -// New makes a new Assertions object for the specified TestingT. -func New(t TestingT) *Assertions { - return &Assertions{ - t: t, - } -} - -//go:generate sh -c "cd ../_codegen && go build && cd - && ../_codegen/_codegen -output-package=assert -template=assertion_forward.go.tmpl -include-format-funcs" diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/assert/http_assertions.go b/trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/assert/http_assertions.go deleted file mode 100644 index 861ed4b7c..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/assert/http_assertions.go +++ /dev/null @@ -1,165 +0,0 @@ -package assert - -import ( - "fmt" - "net/http" - "net/http/httptest" - "net/url" - "strings" -) - -// httpCode is a helper that returns HTTP code of the response. It returns -1 and -// an error if building a new request fails. -func httpCode(handler http.HandlerFunc, method, url string, values url.Values) (int, error) { - w := httptest.NewRecorder() - req, err := http.NewRequest(method, url, http.NoBody) - if err != nil { - return -1, err - } - req.URL.RawQuery = values.Encode() - handler(w, req) - return w.Code, nil -} - -// HTTPSuccess asserts that a specified handler returns a success status code. -// -// assert.HTTPSuccess(t, myHandler, "POST", "http://www.google.com", nil) -// -// Returns whether the assertion was successful (true) or not (false). -func HTTPSuccess(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - code, err := httpCode(handler, method, url, values) - if err != nil { - Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err), msgAndArgs...) - } - - isSuccessCode := code >= http.StatusOK && code <= http.StatusPartialContent - if !isSuccessCode { - Fail(t, fmt.Sprintf("Expected HTTP success status code for %q but received %d", url+"?"+values.Encode(), code), msgAndArgs...) - } - - return isSuccessCode -} - -// HTTPRedirect asserts that a specified handler returns a redirect status code. -// -// assert.HTTPRedirect(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} -// -// Returns whether the assertion was successful (true) or not (false). -func HTTPRedirect(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - code, err := httpCode(handler, method, url, values) - if err != nil { - Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err), msgAndArgs...) - } - - isRedirectCode := code >= http.StatusMultipleChoices && code <= http.StatusTemporaryRedirect - if !isRedirectCode { - Fail(t, fmt.Sprintf("Expected HTTP redirect status code for %q but received %d", url+"?"+values.Encode(), code), msgAndArgs...) - } - - return isRedirectCode -} - -// HTTPError asserts that a specified handler returns an error status code. -// -// assert.HTTPError(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} -// -// Returns whether the assertion was successful (true) or not (false). -func HTTPError(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - code, err := httpCode(handler, method, url, values) - if err != nil { - Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err), msgAndArgs...) - } - - isErrorCode := code >= http.StatusBadRequest - if !isErrorCode { - Fail(t, fmt.Sprintf("Expected HTTP error status code for %q but received %d", url+"?"+values.Encode(), code), msgAndArgs...) - } - - return isErrorCode -} - -// HTTPStatusCode asserts that a specified handler returns a specified status code. -// -// assert.HTTPStatusCode(t, myHandler, "GET", "/notImplemented", nil, 501) -// -// Returns whether the assertion was successful (true) or not (false). -func HTTPStatusCode(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, statuscode int, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - code, err := httpCode(handler, method, url, values) - if err != nil { - Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err), msgAndArgs...) - } - - successful := code == statuscode - if !successful { - Fail(t, fmt.Sprintf("Expected HTTP status code %d for %q but received %d", statuscode, url+"?"+values.Encode(), code), msgAndArgs...) - } - - return successful -} - -// HTTPBody is a helper that returns HTTP body of the response. It returns -// empty string if building a new request fails. -func HTTPBody(handler http.HandlerFunc, method, url string, values url.Values) string { - w := httptest.NewRecorder() - if len(values) > 0 { - url += "?" + values.Encode() - } - req, err := http.NewRequest(method, url, http.NoBody) - if err != nil { - return "" - } - handler(w, req) - return w.Body.String() -} - -// HTTPBodyContains asserts that a specified handler returns a -// body that contains a string. -// -// assert.HTTPBodyContains(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky") -// -// Returns whether the assertion was successful (true) or not (false). -func HTTPBodyContains(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - body := HTTPBody(handler, method, url, values) - - contains := strings.Contains(body, fmt.Sprint(str)) - if !contains { - Fail(t, fmt.Sprintf("Expected response body for \"%s\" to contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body), msgAndArgs...) - } - - return contains -} - -// HTTPBodyNotContains asserts that a specified handler returns a -// body that does not contain a string. -// -// assert.HTTPBodyNotContains(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky") -// -// Returns whether the assertion was successful (true) or not (false). -func HTTPBodyNotContains(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool { - if h, ok := t.(tHelper); ok { - h.Helper() - } - body := HTTPBody(handler, method, url, values) - - contains := strings.Contains(body, fmt.Sprint(str)) - if contains { - Fail(t, fmt.Sprintf("Expected response body for \"%s\" to NOT contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body), msgAndArgs...) - } - - return !contains -} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/require/doc.go b/trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/require/doc.go deleted file mode 100644 index 968434724..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/require/doc.go +++ /dev/null @@ -1,29 +0,0 @@ -// Package require implements the same assertions as the `assert` package but -// stops test execution when a test fails. -// -// # Example Usage -// -// The following is a complete example using require in a standard test function: -// -// import ( -// "testing" -// "github.com/stretchr/testify/require" -// ) -// -// func TestSomething(t *testing.T) { -// -// var a string = "Hello" -// var b string = "Hello" -// -// require.Equal(t, a, b, "The two words should be the same.") -// -// } -// -// # Assertions -// -// The `require` package have same global functions as in the `assert` package, -// but instead of returning a boolean result they call `t.FailNow()`. -// -// Every assertion function also takes an optional string message as the final argument, -// allowing custom error messages to be appended to the message the assertion method outputs. -package require diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/require/forward_requirements.go b/trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/require/forward_requirements.go deleted file mode 100644 index 1dcb2338c..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/require/forward_requirements.go +++ /dev/null @@ -1,16 +0,0 @@ -package require - -// Assertions provides assertion methods around the -// TestingT interface. -type Assertions struct { - t TestingT -} - -// New makes a new Assertions object for the specified TestingT. -func New(t TestingT) *Assertions { - return &Assertions{ - t: t, - } -} - -//go:generate sh -c "cd ../_codegen && go build && cd - && ../_codegen/_codegen -output-package=require -template=require_forward.go.tmpl -include-format-funcs" diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/require/require.go b/trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/require/require.go deleted file mode 100644 index 506a82f80..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/require/require.go +++ /dev/null @@ -1,2060 +0,0 @@ -// Code generated with github.com/stretchr/testify/_codegen; DO NOT EDIT. - -package require - -import ( - assert "github.com/stretchr/testify/assert" - http "net/http" - url "net/url" - time "time" -) - -// Condition uses a Comparison to assert a complex condition. -func Condition(t TestingT, comp assert.Comparison, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Condition(t, comp, msgAndArgs...) { - return - } - t.FailNow() -} - -// Conditionf uses a Comparison to assert a complex condition. -func Conditionf(t TestingT, comp assert.Comparison, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Conditionf(t, comp, msg, args...) { - return - } - t.FailNow() -} - -// Contains asserts that the specified string, list(array, slice...) or map contains the -// specified substring or element. -// -// assert.Contains(t, "Hello World", "World") -// assert.Contains(t, ["Hello", "World"], "World") -// assert.Contains(t, {"Hello": "World"}, "Hello") -func Contains(t TestingT, s interface{}, contains interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Contains(t, s, contains, msgAndArgs...) { - return - } - t.FailNow() -} - -// Containsf asserts that the specified string, list(array, slice...) or map contains the -// specified substring or element. -// -// assert.Containsf(t, "Hello World", "World", "error message %s", "formatted") -// assert.Containsf(t, ["Hello", "World"], "World", "error message %s", "formatted") -// assert.Containsf(t, {"Hello": "World"}, "Hello", "error message %s", "formatted") -func Containsf(t TestingT, s interface{}, contains interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Containsf(t, s, contains, msg, args...) { - return - } - t.FailNow() -} - -// DirExists checks whether a directory exists in the given path. It also fails -// if the path is a file rather a directory or there is an error checking whether it exists. -func DirExists(t TestingT, path string, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.DirExists(t, path, msgAndArgs...) { - return - } - t.FailNow() -} - -// DirExistsf checks whether a directory exists in the given path. It also fails -// if the path is a file rather a directory or there is an error checking whether it exists. -func DirExistsf(t TestingT, path string, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.DirExistsf(t, path, msg, args...) { - return - } - t.FailNow() -} - -// ElementsMatch asserts that the specified listA(array, slice...) is equal to specified -// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, -// the number of appearances of each of them in both lists should match. -// -// assert.ElementsMatch(t, [1, 3, 2, 3], [1, 3, 3, 2]) -func ElementsMatch(t TestingT, listA interface{}, listB interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.ElementsMatch(t, listA, listB, msgAndArgs...) { - return - } - t.FailNow() -} - -// ElementsMatchf asserts that the specified listA(array, slice...) is equal to specified -// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, -// the number of appearances of each of them in both lists should match. -// -// assert.ElementsMatchf(t, [1, 3, 2, 3], [1, 3, 3, 2], "error message %s", "formatted") -func ElementsMatchf(t TestingT, listA interface{}, listB interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.ElementsMatchf(t, listA, listB, msg, args...) { - return - } - t.FailNow() -} - -// Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or either -// a slice or a channel with len == 0. -// -// assert.Empty(t, obj) -func Empty(t TestingT, object interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Empty(t, object, msgAndArgs...) { - return - } - t.FailNow() -} - -// Emptyf asserts that the specified object is empty. I.e. nil, "", false, 0 or either -// a slice or a channel with len == 0. -// -// assert.Emptyf(t, obj, "error message %s", "formatted") -func Emptyf(t TestingT, object interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Emptyf(t, object, msg, args...) { - return - } - t.FailNow() -} - -// Equal asserts that two objects are equal. -// -// assert.Equal(t, 123, 123) -// -// Pointer variable equality is determined based on the equality of the -// referenced values (as opposed to the memory addresses). Function equality -// cannot be determined and will always fail. -func Equal(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Equal(t, expected, actual, msgAndArgs...) { - return - } - t.FailNow() -} - -// EqualError asserts that a function returned an error (i.e. not `nil`) -// and that it is equal to the provided error. -// -// actualObj, err := SomeFunction() -// assert.EqualError(t, err, expectedErrorString) -func EqualError(t TestingT, theError error, errString string, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.EqualError(t, theError, errString, msgAndArgs...) { - return - } - t.FailNow() -} - -// EqualErrorf asserts that a function returned an error (i.e. not `nil`) -// and that it is equal to the provided error. -// -// actualObj, err := SomeFunction() -// assert.EqualErrorf(t, err, expectedErrorString, "error message %s", "formatted") -func EqualErrorf(t TestingT, theError error, errString string, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.EqualErrorf(t, theError, errString, msg, args...) { - return - } - t.FailNow() -} - -// EqualExportedValues asserts that the types of two objects are equal and their public -// fields are also equal. This is useful for comparing structs that have private fields -// that could potentially differ. -// -// type S struct { -// Exported int -// notExported int -// } -// assert.EqualExportedValues(t, S{1, 2}, S{1, 3}) => true -// assert.EqualExportedValues(t, S{1, 2}, S{2, 3}) => false -func EqualExportedValues(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.EqualExportedValues(t, expected, actual, msgAndArgs...) { - return - } - t.FailNow() -} - -// EqualExportedValuesf asserts that the types of two objects are equal and their public -// fields are also equal. This is useful for comparing structs that have private fields -// that could potentially differ. -// -// type S struct { -// Exported int -// notExported int -// } -// assert.EqualExportedValuesf(t, S{1, 2}, S{1, 3}, "error message %s", "formatted") => true -// assert.EqualExportedValuesf(t, S{1, 2}, S{2, 3}, "error message %s", "formatted") => false -func EqualExportedValuesf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.EqualExportedValuesf(t, expected, actual, msg, args...) { - return - } - t.FailNow() -} - -// EqualValues asserts that two objects are equal or convertible to the same types -// and equal. -// -// assert.EqualValues(t, uint32(123), int32(123)) -func EqualValues(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.EqualValues(t, expected, actual, msgAndArgs...) { - return - } - t.FailNow() -} - -// EqualValuesf asserts that two objects are equal or convertible to the same types -// and equal. -// -// assert.EqualValuesf(t, uint32(123), int32(123), "error message %s", "formatted") -func EqualValuesf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.EqualValuesf(t, expected, actual, msg, args...) { - return - } - t.FailNow() -} - -// Equalf asserts that two objects are equal. -// -// assert.Equalf(t, 123, 123, "error message %s", "formatted") -// -// Pointer variable equality is determined based on the equality of the -// referenced values (as opposed to the memory addresses). Function equality -// cannot be determined and will always fail. -func Equalf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Equalf(t, expected, actual, msg, args...) { - return - } - t.FailNow() -} - -// Error asserts that a function returned an error (i.e. not `nil`). -// -// actualObj, err := SomeFunction() -// if assert.Error(t, err) { -// assert.Equal(t, expectedError, err) -// } -func Error(t TestingT, err error, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Error(t, err, msgAndArgs...) { - return - } - t.FailNow() -} - -// ErrorAs asserts that at least one of the errors in err's chain matches target, and if so, sets target to that error value. -// This is a wrapper for errors.As. -func ErrorAs(t TestingT, err error, target interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.ErrorAs(t, err, target, msgAndArgs...) { - return - } - t.FailNow() -} - -// ErrorAsf asserts that at least one of the errors in err's chain matches target, and if so, sets target to that error value. -// This is a wrapper for errors.As. -func ErrorAsf(t TestingT, err error, target interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.ErrorAsf(t, err, target, msg, args...) { - return - } - t.FailNow() -} - -// ErrorContains asserts that a function returned an error (i.e. not `nil`) -// and that the error contains the specified substring. -// -// actualObj, err := SomeFunction() -// assert.ErrorContains(t, err, expectedErrorSubString) -func ErrorContains(t TestingT, theError error, contains string, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.ErrorContains(t, theError, contains, msgAndArgs...) { - return - } - t.FailNow() -} - -// ErrorContainsf asserts that a function returned an error (i.e. not `nil`) -// and that the error contains the specified substring. -// -// actualObj, err := SomeFunction() -// assert.ErrorContainsf(t, err, expectedErrorSubString, "error message %s", "formatted") -func ErrorContainsf(t TestingT, theError error, contains string, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.ErrorContainsf(t, theError, contains, msg, args...) { - return - } - t.FailNow() -} - -// ErrorIs asserts that at least one of the errors in err's chain matches target. -// This is a wrapper for errors.Is. -func ErrorIs(t TestingT, err error, target error, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.ErrorIs(t, err, target, msgAndArgs...) { - return - } - t.FailNow() -} - -// ErrorIsf asserts that at least one of the errors in err's chain matches target. -// This is a wrapper for errors.Is. -func ErrorIsf(t TestingT, err error, target error, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.ErrorIsf(t, err, target, msg, args...) { - return - } - t.FailNow() -} - -// Errorf asserts that a function returned an error (i.e. not `nil`). -// -// actualObj, err := SomeFunction() -// if assert.Errorf(t, err, "error message %s", "formatted") { -// assert.Equal(t, expectedErrorf, err) -// } -func Errorf(t TestingT, err error, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Errorf(t, err, msg, args...) { - return - } - t.FailNow() -} - -// Eventually asserts that given condition will be met in waitFor time, -// periodically checking target function each tick. -// -// assert.Eventually(t, func() bool { return true; }, time.Second, 10*time.Millisecond) -func Eventually(t TestingT, condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Eventually(t, condition, waitFor, tick, msgAndArgs...) { - return - } - t.FailNow() -} - -// EventuallyWithT asserts that given condition will be met in waitFor time, -// periodically checking target function each tick. In contrast to Eventually, -// it supplies a CollectT to the condition function, so that the condition -// function can use the CollectT to call other assertions. -// The condition is considered "met" if no errors are raised in a tick. -// The supplied CollectT collects all errors from one tick (if there are any). -// If the condition is not met before waitFor, the collected errors of -// the last tick are copied to t. -// -// externalValue := false -// go func() { -// time.Sleep(8*time.Second) -// externalValue = true -// }() -// assert.EventuallyWithT(t, func(c *assert.CollectT) { -// // add assertions as needed; any assertion failure will fail the current tick -// assert.True(c, externalValue, "expected 'externalValue' to be true") -// }, 1*time.Second, 10*time.Second, "external state has not changed to 'true'; still false") -func EventuallyWithT(t TestingT, condition func(collect *assert.CollectT), waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.EventuallyWithT(t, condition, waitFor, tick, msgAndArgs...) { - return - } - t.FailNow() -} - -// EventuallyWithTf asserts that given condition will be met in waitFor time, -// periodically checking target function each tick. In contrast to Eventually, -// it supplies a CollectT to the condition function, so that the condition -// function can use the CollectT to call other assertions. -// The condition is considered "met" if no errors are raised in a tick. -// The supplied CollectT collects all errors from one tick (if there are any). -// If the condition is not met before waitFor, the collected errors of -// the last tick are copied to t. -// -// externalValue := false -// go func() { -// time.Sleep(8*time.Second) -// externalValue = true -// }() -// assert.EventuallyWithTf(t, func(c *assert.CollectT, "error message %s", "formatted") { -// // add assertions as needed; any assertion failure will fail the current tick -// assert.True(c, externalValue, "expected 'externalValue' to be true") -// }, 1*time.Second, 10*time.Second, "external state has not changed to 'true'; still false") -func EventuallyWithTf(t TestingT, condition func(collect *assert.CollectT), waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.EventuallyWithTf(t, condition, waitFor, tick, msg, args...) { - return - } - t.FailNow() -} - -// Eventuallyf asserts that given condition will be met in waitFor time, -// periodically checking target function each tick. -// -// assert.Eventuallyf(t, func() bool { return true; }, time.Second, 10*time.Millisecond, "error message %s", "formatted") -func Eventuallyf(t TestingT, condition func() bool, waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Eventuallyf(t, condition, waitFor, tick, msg, args...) { - return - } - t.FailNow() -} - -// Exactly asserts that two objects are equal in value and type. -// -// assert.Exactly(t, int32(123), int64(123)) -func Exactly(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Exactly(t, expected, actual, msgAndArgs...) { - return - } - t.FailNow() -} - -// Exactlyf asserts that two objects are equal in value and type. -// -// assert.Exactlyf(t, int32(123), int64(123), "error message %s", "formatted") -func Exactlyf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Exactlyf(t, expected, actual, msg, args...) { - return - } - t.FailNow() -} - -// Fail reports a failure through -func Fail(t TestingT, failureMessage string, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Fail(t, failureMessage, msgAndArgs...) { - return - } - t.FailNow() -} - -// FailNow fails test -func FailNow(t TestingT, failureMessage string, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.FailNow(t, failureMessage, msgAndArgs...) { - return - } - t.FailNow() -} - -// FailNowf fails test -func FailNowf(t TestingT, failureMessage string, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.FailNowf(t, failureMessage, msg, args...) { - return - } - t.FailNow() -} - -// Failf reports a failure through -func Failf(t TestingT, failureMessage string, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Failf(t, failureMessage, msg, args...) { - return - } - t.FailNow() -} - -// False asserts that the specified value is false. -// -// assert.False(t, myBool) -func False(t TestingT, value bool, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.False(t, value, msgAndArgs...) { - return - } - t.FailNow() -} - -// Falsef asserts that the specified value is false. -// -// assert.Falsef(t, myBool, "error message %s", "formatted") -func Falsef(t TestingT, value bool, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Falsef(t, value, msg, args...) { - return - } - t.FailNow() -} - -// FileExists checks whether a file exists in the given path. It also fails if -// the path points to a directory or there is an error when trying to check the file. -func FileExists(t TestingT, path string, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.FileExists(t, path, msgAndArgs...) { - return - } - t.FailNow() -} - -// FileExistsf checks whether a file exists in the given path. It also fails if -// the path points to a directory or there is an error when trying to check the file. -func FileExistsf(t TestingT, path string, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.FileExistsf(t, path, msg, args...) { - return - } - t.FailNow() -} - -// Greater asserts that the first element is greater than the second -// -// assert.Greater(t, 2, 1) -// assert.Greater(t, float64(2), float64(1)) -// assert.Greater(t, "b", "a") -func Greater(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Greater(t, e1, e2, msgAndArgs...) { - return - } - t.FailNow() -} - -// GreaterOrEqual asserts that the first element is greater than or equal to the second -// -// assert.GreaterOrEqual(t, 2, 1) -// assert.GreaterOrEqual(t, 2, 2) -// assert.GreaterOrEqual(t, "b", "a") -// assert.GreaterOrEqual(t, "b", "b") -func GreaterOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.GreaterOrEqual(t, e1, e2, msgAndArgs...) { - return - } - t.FailNow() -} - -// GreaterOrEqualf asserts that the first element is greater than or equal to the second -// -// assert.GreaterOrEqualf(t, 2, 1, "error message %s", "formatted") -// assert.GreaterOrEqualf(t, 2, 2, "error message %s", "formatted") -// assert.GreaterOrEqualf(t, "b", "a", "error message %s", "formatted") -// assert.GreaterOrEqualf(t, "b", "b", "error message %s", "formatted") -func GreaterOrEqualf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.GreaterOrEqualf(t, e1, e2, msg, args...) { - return - } - t.FailNow() -} - -// Greaterf asserts that the first element is greater than the second -// -// assert.Greaterf(t, 2, 1, "error message %s", "formatted") -// assert.Greaterf(t, float64(2), float64(1), "error message %s", "formatted") -// assert.Greaterf(t, "b", "a", "error message %s", "formatted") -func Greaterf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Greaterf(t, e1, e2, msg, args...) { - return - } - t.FailNow() -} - -// HTTPBodyContains asserts that a specified handler returns a -// body that contains a string. -// -// assert.HTTPBodyContains(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky") -// -// Returns whether the assertion was successful (true) or not (false). -func HTTPBodyContains(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.HTTPBodyContains(t, handler, method, url, values, str, msgAndArgs...) { - return - } - t.FailNow() -} - -// HTTPBodyContainsf asserts that a specified handler returns a -// body that contains a string. -// -// assert.HTTPBodyContainsf(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). -func HTTPBodyContainsf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.HTTPBodyContainsf(t, handler, method, url, values, str, msg, args...) { - return - } - t.FailNow() -} - -// HTTPBodyNotContains asserts that a specified handler returns a -// body that does not contain a string. -// -// assert.HTTPBodyNotContains(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky") -// -// Returns whether the assertion was successful (true) or not (false). -func HTTPBodyNotContains(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.HTTPBodyNotContains(t, handler, method, url, values, str, msgAndArgs...) { - return - } - t.FailNow() -} - -// HTTPBodyNotContainsf asserts that a specified handler returns a -// body that does not contain a string. -// -// assert.HTTPBodyNotContainsf(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). -func HTTPBodyNotContainsf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.HTTPBodyNotContainsf(t, handler, method, url, values, str, msg, args...) { - return - } - t.FailNow() -} - -// HTTPError asserts that a specified handler returns an error status code. -// -// assert.HTTPError(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} -// -// Returns whether the assertion was successful (true) or not (false). -func HTTPError(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.HTTPError(t, handler, method, url, values, msgAndArgs...) { - return - } - t.FailNow() -} - -// HTTPErrorf asserts that a specified handler returns an error status code. -// -// assert.HTTPErrorf(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} -// -// Returns whether the assertion was successful (true) or not (false). -func HTTPErrorf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.HTTPErrorf(t, handler, method, url, values, msg, args...) { - return - } - t.FailNow() -} - -// HTTPRedirect asserts that a specified handler returns a redirect status code. -// -// assert.HTTPRedirect(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} -// -// Returns whether the assertion was successful (true) or not (false). -func HTTPRedirect(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.HTTPRedirect(t, handler, method, url, values, msgAndArgs...) { - return - } - t.FailNow() -} - -// HTTPRedirectf asserts that a specified handler returns a redirect status code. -// -// assert.HTTPRedirectf(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} -// -// Returns whether the assertion was successful (true) or not (false). -func HTTPRedirectf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.HTTPRedirectf(t, handler, method, url, values, msg, args...) { - return - } - t.FailNow() -} - -// HTTPStatusCode asserts that a specified handler returns a specified status code. -// -// assert.HTTPStatusCode(t, myHandler, "GET", "/notImplemented", nil, 501) -// -// Returns whether the assertion was successful (true) or not (false). -func HTTPStatusCode(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, statuscode int, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.HTTPStatusCode(t, handler, method, url, values, statuscode, msgAndArgs...) { - return - } - t.FailNow() -} - -// HTTPStatusCodef asserts that a specified handler returns a specified status code. -// -// assert.HTTPStatusCodef(t, myHandler, "GET", "/notImplemented", nil, 501, "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). -func HTTPStatusCodef(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, statuscode int, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.HTTPStatusCodef(t, handler, method, url, values, statuscode, msg, args...) { - return - } - t.FailNow() -} - -// HTTPSuccess asserts that a specified handler returns a success status code. -// -// assert.HTTPSuccess(t, myHandler, "POST", "http://www.google.com", nil) -// -// Returns whether the assertion was successful (true) or not (false). -func HTTPSuccess(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.HTTPSuccess(t, handler, method, url, values, msgAndArgs...) { - return - } - t.FailNow() -} - -// HTTPSuccessf asserts that a specified handler returns a success status code. -// -// assert.HTTPSuccessf(t, myHandler, "POST", "http://www.google.com", nil, "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). -func HTTPSuccessf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.HTTPSuccessf(t, handler, method, url, values, msg, args...) { - return - } - t.FailNow() -} - -// Implements asserts that an object is implemented by the specified interface. -// -// assert.Implements(t, (*MyInterface)(nil), new(MyObject)) -func Implements(t TestingT, interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Implements(t, interfaceObject, object, msgAndArgs...) { - return - } - t.FailNow() -} - -// Implementsf asserts that an object is implemented by the specified interface. -// -// assert.Implementsf(t, (*MyInterface)(nil), new(MyObject), "error message %s", "formatted") -func Implementsf(t TestingT, interfaceObject interface{}, object interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Implementsf(t, interfaceObject, object, msg, args...) { - return - } - t.FailNow() -} - -// InDelta asserts that the two numerals are within delta of each other. -// -// assert.InDelta(t, math.Pi, 22/7.0, 0.01) -func InDelta(t TestingT, expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.InDelta(t, expected, actual, delta, msgAndArgs...) { - return - } - t.FailNow() -} - -// InDeltaMapValues is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys. -func InDeltaMapValues(t TestingT, expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.InDeltaMapValues(t, expected, actual, delta, msgAndArgs...) { - return - } - t.FailNow() -} - -// InDeltaMapValuesf is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys. -func InDeltaMapValuesf(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.InDeltaMapValuesf(t, expected, actual, delta, msg, args...) { - return - } - t.FailNow() -} - -// InDeltaSlice is the same as InDelta, except it compares two slices. -func InDeltaSlice(t TestingT, expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.InDeltaSlice(t, expected, actual, delta, msgAndArgs...) { - return - } - t.FailNow() -} - -// InDeltaSlicef is the same as InDelta, except it compares two slices. -func InDeltaSlicef(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.InDeltaSlicef(t, expected, actual, delta, msg, args...) { - return - } - t.FailNow() -} - -// InDeltaf asserts that the two numerals are within delta of each other. -// -// assert.InDeltaf(t, math.Pi, 22/7.0, 0.01, "error message %s", "formatted") -func InDeltaf(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.InDeltaf(t, expected, actual, delta, msg, args...) { - return - } - t.FailNow() -} - -// InEpsilon asserts that expected and actual have a relative error less than epsilon -func InEpsilon(t TestingT, expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.InEpsilon(t, expected, actual, epsilon, msgAndArgs...) { - return - } - t.FailNow() -} - -// InEpsilonSlice is the same as InEpsilon, except it compares each value from two slices. -func InEpsilonSlice(t TestingT, expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.InEpsilonSlice(t, expected, actual, epsilon, msgAndArgs...) { - return - } - t.FailNow() -} - -// InEpsilonSlicef is the same as InEpsilon, except it compares each value from two slices. -func InEpsilonSlicef(t TestingT, expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.InEpsilonSlicef(t, expected, actual, epsilon, msg, args...) { - return - } - t.FailNow() -} - -// InEpsilonf asserts that expected and actual have a relative error less than epsilon -func InEpsilonf(t TestingT, expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.InEpsilonf(t, expected, actual, epsilon, msg, args...) { - return - } - t.FailNow() -} - -// IsDecreasing asserts that the collection is decreasing -// -// assert.IsDecreasing(t, []int{2, 1, 0}) -// assert.IsDecreasing(t, []float{2, 1}) -// assert.IsDecreasing(t, []string{"b", "a"}) -func IsDecreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.IsDecreasing(t, object, msgAndArgs...) { - return - } - t.FailNow() -} - -// IsDecreasingf asserts that the collection is decreasing -// -// assert.IsDecreasingf(t, []int{2, 1, 0}, "error message %s", "formatted") -// assert.IsDecreasingf(t, []float{2, 1}, "error message %s", "formatted") -// assert.IsDecreasingf(t, []string{"b", "a"}, "error message %s", "formatted") -func IsDecreasingf(t TestingT, object interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.IsDecreasingf(t, object, msg, args...) { - return - } - t.FailNow() -} - -// IsIncreasing asserts that the collection is increasing -// -// assert.IsIncreasing(t, []int{1, 2, 3}) -// assert.IsIncreasing(t, []float{1, 2}) -// assert.IsIncreasing(t, []string{"a", "b"}) -func IsIncreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.IsIncreasing(t, object, msgAndArgs...) { - return - } - t.FailNow() -} - -// IsIncreasingf asserts that the collection is increasing -// -// assert.IsIncreasingf(t, []int{1, 2, 3}, "error message %s", "formatted") -// assert.IsIncreasingf(t, []float{1, 2}, "error message %s", "formatted") -// assert.IsIncreasingf(t, []string{"a", "b"}, "error message %s", "formatted") -func IsIncreasingf(t TestingT, object interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.IsIncreasingf(t, object, msg, args...) { - return - } - t.FailNow() -} - -// IsNonDecreasing asserts that the collection is not decreasing -// -// assert.IsNonDecreasing(t, []int{1, 1, 2}) -// assert.IsNonDecreasing(t, []float{1, 2}) -// assert.IsNonDecreasing(t, []string{"a", "b"}) -func IsNonDecreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.IsNonDecreasing(t, object, msgAndArgs...) { - return - } - t.FailNow() -} - -// IsNonDecreasingf asserts that the collection is not decreasing -// -// assert.IsNonDecreasingf(t, []int{1, 1, 2}, "error message %s", "formatted") -// assert.IsNonDecreasingf(t, []float{1, 2}, "error message %s", "formatted") -// assert.IsNonDecreasingf(t, []string{"a", "b"}, "error message %s", "formatted") -func IsNonDecreasingf(t TestingT, object interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.IsNonDecreasingf(t, object, msg, args...) { - return - } - t.FailNow() -} - -// IsNonIncreasing asserts that the collection is not increasing -// -// assert.IsNonIncreasing(t, []int{2, 1, 1}) -// assert.IsNonIncreasing(t, []float{2, 1}) -// assert.IsNonIncreasing(t, []string{"b", "a"}) -func IsNonIncreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.IsNonIncreasing(t, object, msgAndArgs...) { - return - } - t.FailNow() -} - -// IsNonIncreasingf asserts that the collection is not increasing -// -// assert.IsNonIncreasingf(t, []int{2, 1, 1}, "error message %s", "formatted") -// assert.IsNonIncreasingf(t, []float{2, 1}, "error message %s", "formatted") -// assert.IsNonIncreasingf(t, []string{"b", "a"}, "error message %s", "formatted") -func IsNonIncreasingf(t TestingT, object interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.IsNonIncreasingf(t, object, msg, args...) { - return - } - t.FailNow() -} - -// IsType asserts that the specified objects are of the same type. -func IsType(t TestingT, expectedType interface{}, object interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.IsType(t, expectedType, object, msgAndArgs...) { - return - } - t.FailNow() -} - -// IsTypef asserts that the specified objects are of the same type. -func IsTypef(t TestingT, expectedType interface{}, object interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.IsTypef(t, expectedType, object, msg, args...) { - return - } - t.FailNow() -} - -// JSONEq asserts that two JSON strings are equivalent. -// -// assert.JSONEq(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) -func JSONEq(t TestingT, expected string, actual string, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.JSONEq(t, expected, actual, msgAndArgs...) { - return - } - t.FailNow() -} - -// JSONEqf asserts that two JSON strings are equivalent. -// -// assert.JSONEqf(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`, "error message %s", "formatted") -func JSONEqf(t TestingT, expected string, actual string, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.JSONEqf(t, expected, actual, msg, args...) { - return - } - t.FailNow() -} - -// Len asserts that the specified object has specific length. -// Len also fails if the object has a type that len() not accept. -// -// assert.Len(t, mySlice, 3) -func Len(t TestingT, object interface{}, length int, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Len(t, object, length, msgAndArgs...) { - return - } - t.FailNow() -} - -// Lenf asserts that the specified object has specific length. -// Lenf also fails if the object has a type that len() not accept. -// -// assert.Lenf(t, mySlice, 3, "error message %s", "formatted") -func Lenf(t TestingT, object interface{}, length int, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Lenf(t, object, length, msg, args...) { - return - } - t.FailNow() -} - -// Less asserts that the first element is less than the second -// -// assert.Less(t, 1, 2) -// assert.Less(t, float64(1), float64(2)) -// assert.Less(t, "a", "b") -func Less(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Less(t, e1, e2, msgAndArgs...) { - return - } - t.FailNow() -} - -// LessOrEqual asserts that the first element is less than or equal to the second -// -// assert.LessOrEqual(t, 1, 2) -// assert.LessOrEqual(t, 2, 2) -// assert.LessOrEqual(t, "a", "b") -// assert.LessOrEqual(t, "b", "b") -func LessOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.LessOrEqual(t, e1, e2, msgAndArgs...) { - return - } - t.FailNow() -} - -// LessOrEqualf asserts that the first element is less than or equal to the second -// -// assert.LessOrEqualf(t, 1, 2, "error message %s", "formatted") -// assert.LessOrEqualf(t, 2, 2, "error message %s", "formatted") -// assert.LessOrEqualf(t, "a", "b", "error message %s", "formatted") -// assert.LessOrEqualf(t, "b", "b", "error message %s", "formatted") -func LessOrEqualf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.LessOrEqualf(t, e1, e2, msg, args...) { - return - } - t.FailNow() -} - -// Lessf asserts that the first element is less than the second -// -// assert.Lessf(t, 1, 2, "error message %s", "formatted") -// assert.Lessf(t, float64(1), float64(2), "error message %s", "formatted") -// assert.Lessf(t, "a", "b", "error message %s", "formatted") -func Lessf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Lessf(t, e1, e2, msg, args...) { - return - } - t.FailNow() -} - -// Negative asserts that the specified element is negative -// -// assert.Negative(t, -1) -// assert.Negative(t, -1.23) -func Negative(t TestingT, e interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Negative(t, e, msgAndArgs...) { - return - } - t.FailNow() -} - -// Negativef asserts that the specified element is negative -// -// assert.Negativef(t, -1, "error message %s", "formatted") -// assert.Negativef(t, -1.23, "error message %s", "formatted") -func Negativef(t TestingT, e interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Negativef(t, e, msg, args...) { - return - } - t.FailNow() -} - -// Never asserts that the given condition doesn't satisfy in waitFor time, -// periodically checking the target function each tick. -// -// assert.Never(t, func() bool { return false; }, time.Second, 10*time.Millisecond) -func Never(t TestingT, condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Never(t, condition, waitFor, tick, msgAndArgs...) { - return - } - t.FailNow() -} - -// Neverf asserts that the given condition doesn't satisfy in waitFor time, -// periodically checking the target function each tick. -// -// assert.Neverf(t, func() bool { return false; }, time.Second, 10*time.Millisecond, "error message %s", "formatted") -func Neverf(t TestingT, condition func() bool, waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Neverf(t, condition, waitFor, tick, msg, args...) { - return - } - t.FailNow() -} - -// Nil asserts that the specified object is nil. -// -// assert.Nil(t, err) -func Nil(t TestingT, object interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Nil(t, object, msgAndArgs...) { - return - } - t.FailNow() -} - -// Nilf asserts that the specified object is nil. -// -// assert.Nilf(t, err, "error message %s", "formatted") -func Nilf(t TestingT, object interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Nilf(t, object, msg, args...) { - return - } - t.FailNow() -} - -// NoDirExists checks whether a directory does not exist in the given path. -// It fails if the path points to an existing _directory_ only. -func NoDirExists(t TestingT, path string, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NoDirExists(t, path, msgAndArgs...) { - return - } - t.FailNow() -} - -// NoDirExistsf checks whether a directory does not exist in the given path. -// It fails if the path points to an existing _directory_ only. -func NoDirExistsf(t TestingT, path string, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NoDirExistsf(t, path, msg, args...) { - return - } - t.FailNow() -} - -// NoError asserts that a function returned no error (i.e. `nil`). -// -// actualObj, err := SomeFunction() -// if assert.NoError(t, err) { -// assert.Equal(t, expectedObj, actualObj) -// } -func NoError(t TestingT, err error, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NoError(t, err, msgAndArgs...) { - return - } - t.FailNow() -} - -// NoErrorf asserts that a function returned no error (i.e. `nil`). -// -// actualObj, err := SomeFunction() -// if assert.NoErrorf(t, err, "error message %s", "formatted") { -// assert.Equal(t, expectedObj, actualObj) -// } -func NoErrorf(t TestingT, err error, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NoErrorf(t, err, msg, args...) { - return - } - t.FailNow() -} - -// NoFileExists checks whether a file does not exist in a given path. It fails -// if the path points to an existing _file_ only. -func NoFileExists(t TestingT, path string, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NoFileExists(t, path, msgAndArgs...) { - return - } - t.FailNow() -} - -// NoFileExistsf checks whether a file does not exist in a given path. It fails -// if the path points to an existing _file_ only. -func NoFileExistsf(t TestingT, path string, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NoFileExistsf(t, path, msg, args...) { - return - } - t.FailNow() -} - -// NotContains asserts that the specified string, list(array, slice...) or map does NOT contain the -// specified substring or element. -// -// assert.NotContains(t, "Hello World", "Earth") -// assert.NotContains(t, ["Hello", "World"], "Earth") -// assert.NotContains(t, {"Hello": "World"}, "Earth") -func NotContains(t TestingT, s interface{}, contains interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NotContains(t, s, contains, msgAndArgs...) { - return - } - t.FailNow() -} - -// NotContainsf asserts that the specified string, list(array, slice...) or map does NOT contain the -// specified substring or element. -// -// assert.NotContainsf(t, "Hello World", "Earth", "error message %s", "formatted") -// assert.NotContainsf(t, ["Hello", "World"], "Earth", "error message %s", "formatted") -// assert.NotContainsf(t, {"Hello": "World"}, "Earth", "error message %s", "formatted") -func NotContainsf(t TestingT, s interface{}, contains interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NotContainsf(t, s, contains, msg, args...) { - return - } - t.FailNow() -} - -// NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either -// a slice or a channel with len == 0. -// -// if assert.NotEmpty(t, obj) { -// assert.Equal(t, "two", obj[1]) -// } -func NotEmpty(t TestingT, object interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NotEmpty(t, object, msgAndArgs...) { - return - } - t.FailNow() -} - -// NotEmptyf asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either -// a slice or a channel with len == 0. -// -// if assert.NotEmptyf(t, obj, "error message %s", "formatted") { -// assert.Equal(t, "two", obj[1]) -// } -func NotEmptyf(t TestingT, object interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NotEmptyf(t, object, msg, args...) { - return - } - t.FailNow() -} - -// NotEqual asserts that the specified values are NOT equal. -// -// assert.NotEqual(t, obj1, obj2) -// -// Pointer variable equality is determined based on the equality of the -// referenced values (as opposed to the memory addresses). -func NotEqual(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NotEqual(t, expected, actual, msgAndArgs...) { - return - } - t.FailNow() -} - -// NotEqualValues asserts that two objects are not equal even when converted to the same type -// -// assert.NotEqualValues(t, obj1, obj2) -func NotEqualValues(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NotEqualValues(t, expected, actual, msgAndArgs...) { - return - } - t.FailNow() -} - -// NotEqualValuesf asserts that two objects are not equal even when converted to the same type -// -// assert.NotEqualValuesf(t, obj1, obj2, "error message %s", "formatted") -func NotEqualValuesf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NotEqualValuesf(t, expected, actual, msg, args...) { - return - } - t.FailNow() -} - -// NotEqualf asserts that the specified values are NOT equal. -// -// assert.NotEqualf(t, obj1, obj2, "error message %s", "formatted") -// -// Pointer variable equality is determined based on the equality of the -// referenced values (as opposed to the memory addresses). -func NotEqualf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NotEqualf(t, expected, actual, msg, args...) { - return - } - t.FailNow() -} - -// NotErrorIs asserts that at none of the errors in err's chain matches target. -// This is a wrapper for errors.Is. -func NotErrorIs(t TestingT, err error, target error, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NotErrorIs(t, err, target, msgAndArgs...) { - return - } - t.FailNow() -} - -// NotErrorIsf asserts that at none of the errors in err's chain matches target. -// This is a wrapper for errors.Is. -func NotErrorIsf(t TestingT, err error, target error, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NotErrorIsf(t, err, target, msg, args...) { - return - } - t.FailNow() -} - -// NotImplements asserts that an object does not implement the specified interface. -// -// assert.NotImplements(t, (*MyInterface)(nil), new(MyObject)) -func NotImplements(t TestingT, interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NotImplements(t, interfaceObject, object, msgAndArgs...) { - return - } - t.FailNow() -} - -// NotImplementsf asserts that an object does not implement the specified interface. -// -// assert.NotImplementsf(t, (*MyInterface)(nil), new(MyObject), "error message %s", "formatted") -func NotImplementsf(t TestingT, interfaceObject interface{}, object interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NotImplementsf(t, interfaceObject, object, msg, args...) { - return - } - t.FailNow() -} - -// NotNil asserts that the specified object is not nil. -// -// assert.NotNil(t, err) -func NotNil(t TestingT, object interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NotNil(t, object, msgAndArgs...) { - return - } - t.FailNow() -} - -// NotNilf asserts that the specified object is not nil. -// -// assert.NotNilf(t, err, "error message %s", "formatted") -func NotNilf(t TestingT, object interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NotNilf(t, object, msg, args...) { - return - } - t.FailNow() -} - -// NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic. -// -// assert.NotPanics(t, func(){ RemainCalm() }) -func NotPanics(t TestingT, f assert.PanicTestFunc, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NotPanics(t, f, msgAndArgs...) { - return - } - t.FailNow() -} - -// NotPanicsf asserts that the code inside the specified PanicTestFunc does NOT panic. -// -// assert.NotPanicsf(t, func(){ RemainCalm() }, "error message %s", "formatted") -func NotPanicsf(t TestingT, f assert.PanicTestFunc, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NotPanicsf(t, f, msg, args...) { - return - } - t.FailNow() -} - -// NotRegexp asserts that a specified regexp does not match a string. -// -// assert.NotRegexp(t, regexp.MustCompile("starts"), "it's starting") -// assert.NotRegexp(t, "^start", "it's not starting") -func NotRegexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NotRegexp(t, rx, str, msgAndArgs...) { - return - } - t.FailNow() -} - -// NotRegexpf asserts that a specified regexp does not match a string. -// -// assert.NotRegexpf(t, regexp.MustCompile("starts"), "it's starting", "error message %s", "formatted") -// assert.NotRegexpf(t, "^start", "it's not starting", "error message %s", "formatted") -func NotRegexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NotRegexpf(t, rx, str, msg, args...) { - return - } - t.FailNow() -} - -// NotSame asserts that two pointers do not reference the same object. -// -// assert.NotSame(t, ptr1, ptr2) -// -// Both arguments must be pointer variables. Pointer variable sameness is -// determined based on the equality of both type and value. -func NotSame(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NotSame(t, expected, actual, msgAndArgs...) { - return - } - t.FailNow() -} - -// NotSamef asserts that two pointers do not reference the same object. -// -// assert.NotSamef(t, ptr1, ptr2, "error message %s", "formatted") -// -// Both arguments must be pointer variables. Pointer variable sameness is -// determined based on the equality of both type and value. -func NotSamef(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NotSamef(t, expected, actual, msg, args...) { - return - } - t.FailNow() -} - -// NotSubset asserts that the specified list(array, slice...) or map does NOT -// contain all elements given in the specified subset list(array, slice...) or -// map. -// -// assert.NotSubset(t, [1, 3, 4], [1, 2]) -// assert.NotSubset(t, {"x": 1, "y": 2}, {"z": 3}) -func NotSubset(t TestingT, list interface{}, subset interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NotSubset(t, list, subset, msgAndArgs...) { - return - } - t.FailNow() -} - -// NotSubsetf asserts that the specified list(array, slice...) or map does NOT -// contain all elements given in the specified subset list(array, slice...) or -// map. -// -// assert.NotSubsetf(t, [1, 3, 4], [1, 2], "error message %s", "formatted") -// assert.NotSubsetf(t, {"x": 1, "y": 2}, {"z": 3}, "error message %s", "formatted") -func NotSubsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NotSubsetf(t, list, subset, msg, args...) { - return - } - t.FailNow() -} - -// NotZero asserts that i is not the zero value for its type. -func NotZero(t TestingT, i interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NotZero(t, i, msgAndArgs...) { - return - } - t.FailNow() -} - -// NotZerof asserts that i is not the zero value for its type. -func NotZerof(t TestingT, i interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.NotZerof(t, i, msg, args...) { - return - } - t.FailNow() -} - -// Panics asserts that the code inside the specified PanicTestFunc panics. -// -// assert.Panics(t, func(){ GoCrazy() }) -func Panics(t TestingT, f assert.PanicTestFunc, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Panics(t, f, msgAndArgs...) { - return - } - t.FailNow() -} - -// PanicsWithError asserts that the code inside the specified PanicTestFunc -// panics, and that the recovered panic value is an error that satisfies the -// EqualError comparison. -// -// assert.PanicsWithError(t, "crazy error", func(){ GoCrazy() }) -func PanicsWithError(t TestingT, errString string, f assert.PanicTestFunc, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.PanicsWithError(t, errString, f, msgAndArgs...) { - return - } - t.FailNow() -} - -// PanicsWithErrorf asserts that the code inside the specified PanicTestFunc -// panics, and that the recovered panic value is an error that satisfies the -// EqualError comparison. -// -// assert.PanicsWithErrorf(t, "crazy error", func(){ GoCrazy() }, "error message %s", "formatted") -func PanicsWithErrorf(t TestingT, errString string, f assert.PanicTestFunc, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.PanicsWithErrorf(t, errString, f, msg, args...) { - return - } - t.FailNow() -} - -// PanicsWithValue asserts that the code inside the specified PanicTestFunc panics, and that -// the recovered panic value equals the expected panic value. -// -// assert.PanicsWithValue(t, "crazy error", func(){ GoCrazy() }) -func PanicsWithValue(t TestingT, expected interface{}, f assert.PanicTestFunc, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.PanicsWithValue(t, expected, f, msgAndArgs...) { - return - } - t.FailNow() -} - -// PanicsWithValuef asserts that the code inside the specified PanicTestFunc panics, and that -// the recovered panic value equals the expected panic value. -// -// assert.PanicsWithValuef(t, "crazy error", func(){ GoCrazy() }, "error message %s", "formatted") -func PanicsWithValuef(t TestingT, expected interface{}, f assert.PanicTestFunc, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.PanicsWithValuef(t, expected, f, msg, args...) { - return - } - t.FailNow() -} - -// Panicsf asserts that the code inside the specified PanicTestFunc panics. -// -// assert.Panicsf(t, func(){ GoCrazy() }, "error message %s", "formatted") -func Panicsf(t TestingT, f assert.PanicTestFunc, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Panicsf(t, f, msg, args...) { - return - } - t.FailNow() -} - -// Positive asserts that the specified element is positive -// -// assert.Positive(t, 1) -// assert.Positive(t, 1.23) -func Positive(t TestingT, e interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Positive(t, e, msgAndArgs...) { - return - } - t.FailNow() -} - -// Positivef asserts that the specified element is positive -// -// assert.Positivef(t, 1, "error message %s", "formatted") -// assert.Positivef(t, 1.23, "error message %s", "formatted") -func Positivef(t TestingT, e interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Positivef(t, e, msg, args...) { - return - } - t.FailNow() -} - -// Regexp asserts that a specified regexp matches a string. -// -// assert.Regexp(t, regexp.MustCompile("start"), "it's starting") -// assert.Regexp(t, "start...$", "it's not starting") -func Regexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Regexp(t, rx, str, msgAndArgs...) { - return - } - t.FailNow() -} - -// Regexpf asserts that a specified regexp matches a string. -// -// assert.Regexpf(t, regexp.MustCompile("start"), "it's starting", "error message %s", "formatted") -// assert.Regexpf(t, "start...$", "it's not starting", "error message %s", "formatted") -func Regexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Regexpf(t, rx, str, msg, args...) { - return - } - t.FailNow() -} - -// Same asserts that two pointers reference the same object. -// -// assert.Same(t, ptr1, ptr2) -// -// Both arguments must be pointer variables. Pointer variable sameness is -// determined based on the equality of both type and value. -func Same(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Same(t, expected, actual, msgAndArgs...) { - return - } - t.FailNow() -} - -// Samef asserts that two pointers reference the same object. -// -// assert.Samef(t, ptr1, ptr2, "error message %s", "formatted") -// -// Both arguments must be pointer variables. Pointer variable sameness is -// determined based on the equality of both type and value. -func Samef(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Samef(t, expected, actual, msg, args...) { - return - } - t.FailNow() -} - -// Subset asserts that the specified list(array, slice...) or map contains all -// elements given in the specified subset list(array, slice...) or map. -// -// assert.Subset(t, [1, 2, 3], [1, 2]) -// assert.Subset(t, {"x": 1, "y": 2}, {"x": 1}) -func Subset(t TestingT, list interface{}, subset interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Subset(t, list, subset, msgAndArgs...) { - return - } - t.FailNow() -} - -// Subsetf asserts that the specified list(array, slice...) or map contains all -// elements given in the specified subset list(array, slice...) or map. -// -// assert.Subsetf(t, [1, 2, 3], [1, 2], "error message %s", "formatted") -// assert.Subsetf(t, {"x": 1, "y": 2}, {"x": 1}, "error message %s", "formatted") -func Subsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Subsetf(t, list, subset, msg, args...) { - return - } - t.FailNow() -} - -// True asserts that the specified value is true. -// -// assert.True(t, myBool) -func True(t TestingT, value bool, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.True(t, value, msgAndArgs...) { - return - } - t.FailNow() -} - -// Truef asserts that the specified value is true. -// -// assert.Truef(t, myBool, "error message %s", "formatted") -func Truef(t TestingT, value bool, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Truef(t, value, msg, args...) { - return - } - t.FailNow() -} - -// WithinDuration asserts that the two times are within duration delta of each other. -// -// assert.WithinDuration(t, time.Now(), time.Now(), 10*time.Second) -func WithinDuration(t TestingT, expected time.Time, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.WithinDuration(t, expected, actual, delta, msgAndArgs...) { - return - } - t.FailNow() -} - -// WithinDurationf asserts that the two times are within duration delta of each other. -// -// assert.WithinDurationf(t, time.Now(), time.Now(), 10*time.Second, "error message %s", "formatted") -func WithinDurationf(t TestingT, expected time.Time, actual time.Time, delta time.Duration, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.WithinDurationf(t, expected, actual, delta, msg, args...) { - return - } - t.FailNow() -} - -// WithinRange asserts that a time is within a time range (inclusive). -// -// assert.WithinRange(t, time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second)) -func WithinRange(t TestingT, actual time.Time, start time.Time, end time.Time, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.WithinRange(t, actual, start, end, msgAndArgs...) { - return - } - t.FailNow() -} - -// WithinRangef asserts that a time is within a time range (inclusive). -// -// assert.WithinRangef(t, time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second), "error message %s", "formatted") -func WithinRangef(t TestingT, actual time.Time, start time.Time, end time.Time, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.WithinRangef(t, actual, start, end, msg, args...) { - return - } - t.FailNow() -} - -// YAMLEq asserts that two YAML strings are equivalent. -func YAMLEq(t TestingT, expected string, actual string, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.YAMLEq(t, expected, actual, msgAndArgs...) { - return - } - t.FailNow() -} - -// YAMLEqf asserts that two YAML strings are equivalent. -func YAMLEqf(t TestingT, expected string, actual string, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.YAMLEqf(t, expected, actual, msg, args...) { - return - } - t.FailNow() -} - -// Zero asserts that i is the zero value for its type. -func Zero(t TestingT, i interface{}, msgAndArgs ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Zero(t, i, msgAndArgs...) { - return - } - t.FailNow() -} - -// Zerof asserts that i is the zero value for its type. -func Zerof(t TestingT, i interface{}, msg string, args ...interface{}) { - if h, ok := t.(tHelper); ok { - h.Helper() - } - if assert.Zerof(t, i, msg, args...) { - return - } - t.FailNow() -} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/require/require.go.tmpl b/trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/require/require.go.tmpl deleted file mode 100644 index 55e42ddeb..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/require/require.go.tmpl +++ /dev/null @@ -1,6 +0,0 @@ -{{.Comment}} -func {{.DocInfo.Name}}(t TestingT, {{.Params}}) { - if h, ok := t.(tHelper); ok { h.Helper() } - if assert.{{.DocInfo.Name}}(t, {{.ForwardedParams}}) { return } - t.FailNow() -} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/require/require_forward.go b/trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/require/require_forward.go deleted file mode 100644 index eee8310a5..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/require/require_forward.go +++ /dev/null @@ -1,1622 +0,0 @@ -// Code generated with github.com/stretchr/testify/_codegen; DO NOT EDIT. - -package require - -import ( - assert "github.com/stretchr/testify/assert" - http "net/http" - url "net/url" - time "time" -) - -// Condition uses a Comparison to assert a complex condition. -func (a *Assertions) Condition(comp assert.Comparison, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Condition(a.t, comp, msgAndArgs...) -} - -// Conditionf uses a Comparison to assert a complex condition. -func (a *Assertions) Conditionf(comp assert.Comparison, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Conditionf(a.t, comp, msg, args...) -} - -// Contains asserts that the specified string, list(array, slice...) or map contains the -// specified substring or element. -// -// a.Contains("Hello World", "World") -// a.Contains(["Hello", "World"], "World") -// a.Contains({"Hello": "World"}, "Hello") -func (a *Assertions) Contains(s interface{}, contains interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Contains(a.t, s, contains, msgAndArgs...) -} - -// Containsf asserts that the specified string, list(array, slice...) or map contains the -// specified substring or element. -// -// a.Containsf("Hello World", "World", "error message %s", "formatted") -// a.Containsf(["Hello", "World"], "World", "error message %s", "formatted") -// a.Containsf({"Hello": "World"}, "Hello", "error message %s", "formatted") -func (a *Assertions) Containsf(s interface{}, contains interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Containsf(a.t, s, contains, msg, args...) -} - -// DirExists checks whether a directory exists in the given path. It also fails -// if the path is a file rather a directory or there is an error checking whether it exists. -func (a *Assertions) DirExists(path string, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - DirExists(a.t, path, msgAndArgs...) -} - -// DirExistsf checks whether a directory exists in the given path. It also fails -// if the path is a file rather a directory or there is an error checking whether it exists. -func (a *Assertions) DirExistsf(path string, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - DirExistsf(a.t, path, msg, args...) -} - -// ElementsMatch asserts that the specified listA(array, slice...) is equal to specified -// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, -// the number of appearances of each of them in both lists should match. -// -// a.ElementsMatch([1, 3, 2, 3], [1, 3, 3, 2]) -func (a *Assertions) ElementsMatch(listA interface{}, listB interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - ElementsMatch(a.t, listA, listB, msgAndArgs...) -} - -// ElementsMatchf asserts that the specified listA(array, slice...) is equal to specified -// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, -// the number of appearances of each of them in both lists should match. -// -// a.ElementsMatchf([1, 3, 2, 3], [1, 3, 3, 2], "error message %s", "formatted") -func (a *Assertions) ElementsMatchf(listA interface{}, listB interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - ElementsMatchf(a.t, listA, listB, msg, args...) -} - -// Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or either -// a slice or a channel with len == 0. -// -// a.Empty(obj) -func (a *Assertions) Empty(object interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Empty(a.t, object, msgAndArgs...) -} - -// Emptyf asserts that the specified object is empty. I.e. nil, "", false, 0 or either -// a slice or a channel with len == 0. -// -// a.Emptyf(obj, "error message %s", "formatted") -func (a *Assertions) Emptyf(object interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Emptyf(a.t, object, msg, args...) -} - -// Equal asserts that two objects are equal. -// -// a.Equal(123, 123) -// -// Pointer variable equality is determined based on the equality of the -// referenced values (as opposed to the memory addresses). Function equality -// cannot be determined and will always fail. -func (a *Assertions) Equal(expected interface{}, actual interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Equal(a.t, expected, actual, msgAndArgs...) -} - -// EqualError asserts that a function returned an error (i.e. not `nil`) -// and that it is equal to the provided error. -// -// actualObj, err := SomeFunction() -// a.EqualError(err, expectedErrorString) -func (a *Assertions) EqualError(theError error, errString string, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - EqualError(a.t, theError, errString, msgAndArgs...) -} - -// EqualErrorf asserts that a function returned an error (i.e. not `nil`) -// and that it is equal to the provided error. -// -// actualObj, err := SomeFunction() -// a.EqualErrorf(err, expectedErrorString, "error message %s", "formatted") -func (a *Assertions) EqualErrorf(theError error, errString string, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - EqualErrorf(a.t, theError, errString, msg, args...) -} - -// EqualExportedValues asserts that the types of two objects are equal and their public -// fields are also equal. This is useful for comparing structs that have private fields -// that could potentially differ. -// -// type S struct { -// Exported int -// notExported int -// } -// a.EqualExportedValues(S{1, 2}, S{1, 3}) => true -// a.EqualExportedValues(S{1, 2}, S{2, 3}) => false -func (a *Assertions) EqualExportedValues(expected interface{}, actual interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - EqualExportedValues(a.t, expected, actual, msgAndArgs...) -} - -// EqualExportedValuesf asserts that the types of two objects are equal and their public -// fields are also equal. This is useful for comparing structs that have private fields -// that could potentially differ. -// -// type S struct { -// Exported int -// notExported int -// } -// a.EqualExportedValuesf(S{1, 2}, S{1, 3}, "error message %s", "formatted") => true -// a.EqualExportedValuesf(S{1, 2}, S{2, 3}, "error message %s", "formatted") => false -func (a *Assertions) EqualExportedValuesf(expected interface{}, actual interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - EqualExportedValuesf(a.t, expected, actual, msg, args...) -} - -// EqualValues asserts that two objects are equal or convertible to the same types -// and equal. -// -// a.EqualValues(uint32(123), int32(123)) -func (a *Assertions) EqualValues(expected interface{}, actual interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - EqualValues(a.t, expected, actual, msgAndArgs...) -} - -// EqualValuesf asserts that two objects are equal or convertible to the same types -// and equal. -// -// a.EqualValuesf(uint32(123), int32(123), "error message %s", "formatted") -func (a *Assertions) EqualValuesf(expected interface{}, actual interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - EqualValuesf(a.t, expected, actual, msg, args...) -} - -// Equalf asserts that two objects are equal. -// -// a.Equalf(123, 123, "error message %s", "formatted") -// -// Pointer variable equality is determined based on the equality of the -// referenced values (as opposed to the memory addresses). Function equality -// cannot be determined and will always fail. -func (a *Assertions) Equalf(expected interface{}, actual interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Equalf(a.t, expected, actual, msg, args...) -} - -// Error asserts that a function returned an error (i.e. not `nil`). -// -// actualObj, err := SomeFunction() -// if a.Error(err) { -// assert.Equal(t, expectedError, err) -// } -func (a *Assertions) Error(err error, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Error(a.t, err, msgAndArgs...) -} - -// ErrorAs asserts that at least one of the errors in err's chain matches target, and if so, sets target to that error value. -// This is a wrapper for errors.As. -func (a *Assertions) ErrorAs(err error, target interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - ErrorAs(a.t, err, target, msgAndArgs...) -} - -// ErrorAsf asserts that at least one of the errors in err's chain matches target, and if so, sets target to that error value. -// This is a wrapper for errors.As. -func (a *Assertions) ErrorAsf(err error, target interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - ErrorAsf(a.t, err, target, msg, args...) -} - -// ErrorContains asserts that a function returned an error (i.e. not `nil`) -// and that the error contains the specified substring. -// -// actualObj, err := SomeFunction() -// a.ErrorContains(err, expectedErrorSubString) -func (a *Assertions) ErrorContains(theError error, contains string, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - ErrorContains(a.t, theError, contains, msgAndArgs...) -} - -// ErrorContainsf asserts that a function returned an error (i.e. not `nil`) -// and that the error contains the specified substring. -// -// actualObj, err := SomeFunction() -// a.ErrorContainsf(err, expectedErrorSubString, "error message %s", "formatted") -func (a *Assertions) ErrorContainsf(theError error, contains string, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - ErrorContainsf(a.t, theError, contains, msg, args...) -} - -// ErrorIs asserts that at least one of the errors in err's chain matches target. -// This is a wrapper for errors.Is. -func (a *Assertions) ErrorIs(err error, target error, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - ErrorIs(a.t, err, target, msgAndArgs...) -} - -// ErrorIsf asserts that at least one of the errors in err's chain matches target. -// This is a wrapper for errors.Is. -func (a *Assertions) ErrorIsf(err error, target error, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - ErrorIsf(a.t, err, target, msg, args...) -} - -// Errorf asserts that a function returned an error (i.e. not `nil`). -// -// actualObj, err := SomeFunction() -// if a.Errorf(err, "error message %s", "formatted") { -// assert.Equal(t, expectedErrorf, err) -// } -func (a *Assertions) Errorf(err error, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Errorf(a.t, err, msg, args...) -} - -// Eventually asserts that given condition will be met in waitFor time, -// periodically checking target function each tick. -// -// a.Eventually(func() bool { return true; }, time.Second, 10*time.Millisecond) -func (a *Assertions) Eventually(condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Eventually(a.t, condition, waitFor, tick, msgAndArgs...) -} - -// EventuallyWithT asserts that given condition will be met in waitFor time, -// periodically checking target function each tick. In contrast to Eventually, -// it supplies a CollectT to the condition function, so that the condition -// function can use the CollectT to call other assertions. -// The condition is considered "met" if no errors are raised in a tick. -// The supplied CollectT collects all errors from one tick (if there are any). -// If the condition is not met before waitFor, the collected errors of -// the last tick are copied to t. -// -// externalValue := false -// go func() { -// time.Sleep(8*time.Second) -// externalValue = true -// }() -// a.EventuallyWithT(func(c *assert.CollectT) { -// // add assertions as needed; any assertion failure will fail the current tick -// assert.True(c, externalValue, "expected 'externalValue' to be true") -// }, 1*time.Second, 10*time.Second, "external state has not changed to 'true'; still false") -func (a *Assertions) EventuallyWithT(condition func(collect *assert.CollectT), waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - EventuallyWithT(a.t, condition, waitFor, tick, msgAndArgs...) -} - -// EventuallyWithTf asserts that given condition will be met in waitFor time, -// periodically checking target function each tick. In contrast to Eventually, -// it supplies a CollectT to the condition function, so that the condition -// function can use the CollectT to call other assertions. -// The condition is considered "met" if no errors are raised in a tick. -// The supplied CollectT collects all errors from one tick (if there are any). -// If the condition is not met before waitFor, the collected errors of -// the last tick are copied to t. -// -// externalValue := false -// go func() { -// time.Sleep(8*time.Second) -// externalValue = true -// }() -// a.EventuallyWithTf(func(c *assert.CollectT, "error message %s", "formatted") { -// // add assertions as needed; any assertion failure will fail the current tick -// assert.True(c, externalValue, "expected 'externalValue' to be true") -// }, 1*time.Second, 10*time.Second, "external state has not changed to 'true'; still false") -func (a *Assertions) EventuallyWithTf(condition func(collect *assert.CollectT), waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - EventuallyWithTf(a.t, condition, waitFor, tick, msg, args...) -} - -// Eventuallyf asserts that given condition will be met in waitFor time, -// periodically checking target function each tick. -// -// a.Eventuallyf(func() bool { return true; }, time.Second, 10*time.Millisecond, "error message %s", "formatted") -func (a *Assertions) Eventuallyf(condition func() bool, waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Eventuallyf(a.t, condition, waitFor, tick, msg, args...) -} - -// Exactly asserts that two objects are equal in value and type. -// -// a.Exactly(int32(123), int64(123)) -func (a *Assertions) Exactly(expected interface{}, actual interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Exactly(a.t, expected, actual, msgAndArgs...) -} - -// Exactlyf asserts that two objects are equal in value and type. -// -// a.Exactlyf(int32(123), int64(123), "error message %s", "formatted") -func (a *Assertions) Exactlyf(expected interface{}, actual interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Exactlyf(a.t, expected, actual, msg, args...) -} - -// Fail reports a failure through -func (a *Assertions) Fail(failureMessage string, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Fail(a.t, failureMessage, msgAndArgs...) -} - -// FailNow fails test -func (a *Assertions) FailNow(failureMessage string, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - FailNow(a.t, failureMessage, msgAndArgs...) -} - -// FailNowf fails test -func (a *Assertions) FailNowf(failureMessage string, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - FailNowf(a.t, failureMessage, msg, args...) -} - -// Failf reports a failure through -func (a *Assertions) Failf(failureMessage string, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Failf(a.t, failureMessage, msg, args...) -} - -// False asserts that the specified value is false. -// -// a.False(myBool) -func (a *Assertions) False(value bool, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - False(a.t, value, msgAndArgs...) -} - -// Falsef asserts that the specified value is false. -// -// a.Falsef(myBool, "error message %s", "formatted") -func (a *Assertions) Falsef(value bool, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Falsef(a.t, value, msg, args...) -} - -// FileExists checks whether a file exists in the given path. It also fails if -// the path points to a directory or there is an error when trying to check the file. -func (a *Assertions) FileExists(path string, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - FileExists(a.t, path, msgAndArgs...) -} - -// FileExistsf checks whether a file exists in the given path. It also fails if -// the path points to a directory or there is an error when trying to check the file. -func (a *Assertions) FileExistsf(path string, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - FileExistsf(a.t, path, msg, args...) -} - -// Greater asserts that the first element is greater than the second -// -// a.Greater(2, 1) -// a.Greater(float64(2), float64(1)) -// a.Greater("b", "a") -func (a *Assertions) Greater(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Greater(a.t, e1, e2, msgAndArgs...) -} - -// GreaterOrEqual asserts that the first element is greater than or equal to the second -// -// a.GreaterOrEqual(2, 1) -// a.GreaterOrEqual(2, 2) -// a.GreaterOrEqual("b", "a") -// a.GreaterOrEqual("b", "b") -func (a *Assertions) GreaterOrEqual(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - GreaterOrEqual(a.t, e1, e2, msgAndArgs...) -} - -// GreaterOrEqualf asserts that the first element is greater than or equal to the second -// -// a.GreaterOrEqualf(2, 1, "error message %s", "formatted") -// a.GreaterOrEqualf(2, 2, "error message %s", "formatted") -// a.GreaterOrEqualf("b", "a", "error message %s", "formatted") -// a.GreaterOrEqualf("b", "b", "error message %s", "formatted") -func (a *Assertions) GreaterOrEqualf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - GreaterOrEqualf(a.t, e1, e2, msg, args...) -} - -// Greaterf asserts that the first element is greater than the second -// -// a.Greaterf(2, 1, "error message %s", "formatted") -// a.Greaterf(float64(2), float64(1), "error message %s", "formatted") -// a.Greaterf("b", "a", "error message %s", "formatted") -func (a *Assertions) Greaterf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Greaterf(a.t, e1, e2, msg, args...) -} - -// HTTPBodyContains asserts that a specified handler returns a -// body that contains a string. -// -// a.HTTPBodyContains(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky") -// -// Returns whether the assertion was successful (true) or not (false). -func (a *Assertions) HTTPBodyContains(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - HTTPBodyContains(a.t, handler, method, url, values, str, msgAndArgs...) -} - -// HTTPBodyContainsf asserts that a specified handler returns a -// body that contains a string. -// -// a.HTTPBodyContainsf(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). -func (a *Assertions) HTTPBodyContainsf(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - HTTPBodyContainsf(a.t, handler, method, url, values, str, msg, args...) -} - -// HTTPBodyNotContains asserts that a specified handler returns a -// body that does not contain a string. -// -// a.HTTPBodyNotContains(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky") -// -// Returns whether the assertion was successful (true) or not (false). -func (a *Assertions) HTTPBodyNotContains(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - HTTPBodyNotContains(a.t, handler, method, url, values, str, msgAndArgs...) -} - -// HTTPBodyNotContainsf asserts that a specified handler returns a -// body that does not contain a string. -// -// a.HTTPBodyNotContainsf(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). -func (a *Assertions) HTTPBodyNotContainsf(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - HTTPBodyNotContainsf(a.t, handler, method, url, values, str, msg, args...) -} - -// HTTPError asserts that a specified handler returns an error status code. -// -// a.HTTPError(myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} -// -// Returns whether the assertion was successful (true) or not (false). -func (a *Assertions) HTTPError(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - HTTPError(a.t, handler, method, url, values, msgAndArgs...) -} - -// HTTPErrorf asserts that a specified handler returns an error status code. -// -// a.HTTPErrorf(myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} -// -// Returns whether the assertion was successful (true) or not (false). -func (a *Assertions) HTTPErrorf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - HTTPErrorf(a.t, handler, method, url, values, msg, args...) -} - -// HTTPRedirect asserts that a specified handler returns a redirect status code. -// -// a.HTTPRedirect(myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} -// -// Returns whether the assertion was successful (true) or not (false). -func (a *Assertions) HTTPRedirect(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - HTTPRedirect(a.t, handler, method, url, values, msgAndArgs...) -} - -// HTTPRedirectf asserts that a specified handler returns a redirect status code. -// -// a.HTTPRedirectf(myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} -// -// Returns whether the assertion was successful (true) or not (false). -func (a *Assertions) HTTPRedirectf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - HTTPRedirectf(a.t, handler, method, url, values, msg, args...) -} - -// HTTPStatusCode asserts that a specified handler returns a specified status code. -// -// a.HTTPStatusCode(myHandler, "GET", "/notImplemented", nil, 501) -// -// Returns whether the assertion was successful (true) or not (false). -func (a *Assertions) HTTPStatusCode(handler http.HandlerFunc, method string, url string, values url.Values, statuscode int, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - HTTPStatusCode(a.t, handler, method, url, values, statuscode, msgAndArgs...) -} - -// HTTPStatusCodef asserts that a specified handler returns a specified status code. -// -// a.HTTPStatusCodef(myHandler, "GET", "/notImplemented", nil, 501, "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). -func (a *Assertions) HTTPStatusCodef(handler http.HandlerFunc, method string, url string, values url.Values, statuscode int, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - HTTPStatusCodef(a.t, handler, method, url, values, statuscode, msg, args...) -} - -// HTTPSuccess asserts that a specified handler returns a success status code. -// -// a.HTTPSuccess(myHandler, "POST", "http://www.google.com", nil) -// -// Returns whether the assertion was successful (true) or not (false). -func (a *Assertions) HTTPSuccess(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - HTTPSuccess(a.t, handler, method, url, values, msgAndArgs...) -} - -// HTTPSuccessf asserts that a specified handler returns a success status code. -// -// a.HTTPSuccessf(myHandler, "POST", "http://www.google.com", nil, "error message %s", "formatted") -// -// Returns whether the assertion was successful (true) or not (false). -func (a *Assertions) HTTPSuccessf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - HTTPSuccessf(a.t, handler, method, url, values, msg, args...) -} - -// Implements asserts that an object is implemented by the specified interface. -// -// a.Implements((*MyInterface)(nil), new(MyObject)) -func (a *Assertions) Implements(interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Implements(a.t, interfaceObject, object, msgAndArgs...) -} - -// Implementsf asserts that an object is implemented by the specified interface. -// -// a.Implementsf((*MyInterface)(nil), new(MyObject), "error message %s", "formatted") -func (a *Assertions) Implementsf(interfaceObject interface{}, object interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Implementsf(a.t, interfaceObject, object, msg, args...) -} - -// InDelta asserts that the two numerals are within delta of each other. -// -// a.InDelta(math.Pi, 22/7.0, 0.01) -func (a *Assertions) InDelta(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - InDelta(a.t, expected, actual, delta, msgAndArgs...) -} - -// InDeltaMapValues is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys. -func (a *Assertions) InDeltaMapValues(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - InDeltaMapValues(a.t, expected, actual, delta, msgAndArgs...) -} - -// InDeltaMapValuesf is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys. -func (a *Assertions) InDeltaMapValuesf(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - InDeltaMapValuesf(a.t, expected, actual, delta, msg, args...) -} - -// InDeltaSlice is the same as InDelta, except it compares two slices. -func (a *Assertions) InDeltaSlice(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - InDeltaSlice(a.t, expected, actual, delta, msgAndArgs...) -} - -// InDeltaSlicef is the same as InDelta, except it compares two slices. -func (a *Assertions) InDeltaSlicef(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - InDeltaSlicef(a.t, expected, actual, delta, msg, args...) -} - -// InDeltaf asserts that the two numerals are within delta of each other. -// -// a.InDeltaf(math.Pi, 22/7.0, 0.01, "error message %s", "formatted") -func (a *Assertions) InDeltaf(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - InDeltaf(a.t, expected, actual, delta, msg, args...) -} - -// InEpsilon asserts that expected and actual have a relative error less than epsilon -func (a *Assertions) InEpsilon(expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - InEpsilon(a.t, expected, actual, epsilon, msgAndArgs...) -} - -// InEpsilonSlice is the same as InEpsilon, except it compares each value from two slices. -func (a *Assertions) InEpsilonSlice(expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - InEpsilonSlice(a.t, expected, actual, epsilon, msgAndArgs...) -} - -// InEpsilonSlicef is the same as InEpsilon, except it compares each value from two slices. -func (a *Assertions) InEpsilonSlicef(expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - InEpsilonSlicef(a.t, expected, actual, epsilon, msg, args...) -} - -// InEpsilonf asserts that expected and actual have a relative error less than epsilon -func (a *Assertions) InEpsilonf(expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - InEpsilonf(a.t, expected, actual, epsilon, msg, args...) -} - -// IsDecreasing asserts that the collection is decreasing -// -// a.IsDecreasing([]int{2, 1, 0}) -// a.IsDecreasing([]float{2, 1}) -// a.IsDecreasing([]string{"b", "a"}) -func (a *Assertions) IsDecreasing(object interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - IsDecreasing(a.t, object, msgAndArgs...) -} - -// IsDecreasingf asserts that the collection is decreasing -// -// a.IsDecreasingf([]int{2, 1, 0}, "error message %s", "formatted") -// a.IsDecreasingf([]float{2, 1}, "error message %s", "formatted") -// a.IsDecreasingf([]string{"b", "a"}, "error message %s", "formatted") -func (a *Assertions) IsDecreasingf(object interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - IsDecreasingf(a.t, object, msg, args...) -} - -// IsIncreasing asserts that the collection is increasing -// -// a.IsIncreasing([]int{1, 2, 3}) -// a.IsIncreasing([]float{1, 2}) -// a.IsIncreasing([]string{"a", "b"}) -func (a *Assertions) IsIncreasing(object interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - IsIncreasing(a.t, object, msgAndArgs...) -} - -// IsIncreasingf asserts that the collection is increasing -// -// a.IsIncreasingf([]int{1, 2, 3}, "error message %s", "formatted") -// a.IsIncreasingf([]float{1, 2}, "error message %s", "formatted") -// a.IsIncreasingf([]string{"a", "b"}, "error message %s", "formatted") -func (a *Assertions) IsIncreasingf(object interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - IsIncreasingf(a.t, object, msg, args...) -} - -// IsNonDecreasing asserts that the collection is not decreasing -// -// a.IsNonDecreasing([]int{1, 1, 2}) -// a.IsNonDecreasing([]float{1, 2}) -// a.IsNonDecreasing([]string{"a", "b"}) -func (a *Assertions) IsNonDecreasing(object interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - IsNonDecreasing(a.t, object, msgAndArgs...) -} - -// IsNonDecreasingf asserts that the collection is not decreasing -// -// a.IsNonDecreasingf([]int{1, 1, 2}, "error message %s", "formatted") -// a.IsNonDecreasingf([]float{1, 2}, "error message %s", "formatted") -// a.IsNonDecreasingf([]string{"a", "b"}, "error message %s", "formatted") -func (a *Assertions) IsNonDecreasingf(object interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - IsNonDecreasingf(a.t, object, msg, args...) -} - -// IsNonIncreasing asserts that the collection is not increasing -// -// a.IsNonIncreasing([]int{2, 1, 1}) -// a.IsNonIncreasing([]float{2, 1}) -// a.IsNonIncreasing([]string{"b", "a"}) -func (a *Assertions) IsNonIncreasing(object interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - IsNonIncreasing(a.t, object, msgAndArgs...) -} - -// IsNonIncreasingf asserts that the collection is not increasing -// -// a.IsNonIncreasingf([]int{2, 1, 1}, "error message %s", "formatted") -// a.IsNonIncreasingf([]float{2, 1}, "error message %s", "formatted") -// a.IsNonIncreasingf([]string{"b", "a"}, "error message %s", "formatted") -func (a *Assertions) IsNonIncreasingf(object interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - IsNonIncreasingf(a.t, object, msg, args...) -} - -// IsType asserts that the specified objects are of the same type. -func (a *Assertions) IsType(expectedType interface{}, object interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - IsType(a.t, expectedType, object, msgAndArgs...) -} - -// IsTypef asserts that the specified objects are of the same type. -func (a *Assertions) IsTypef(expectedType interface{}, object interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - IsTypef(a.t, expectedType, object, msg, args...) -} - -// JSONEq asserts that two JSON strings are equivalent. -// -// a.JSONEq(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) -func (a *Assertions) JSONEq(expected string, actual string, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - JSONEq(a.t, expected, actual, msgAndArgs...) -} - -// JSONEqf asserts that two JSON strings are equivalent. -// -// a.JSONEqf(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`, "error message %s", "formatted") -func (a *Assertions) JSONEqf(expected string, actual string, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - JSONEqf(a.t, expected, actual, msg, args...) -} - -// Len asserts that the specified object has specific length. -// Len also fails if the object has a type that len() not accept. -// -// a.Len(mySlice, 3) -func (a *Assertions) Len(object interface{}, length int, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Len(a.t, object, length, msgAndArgs...) -} - -// Lenf asserts that the specified object has specific length. -// Lenf also fails if the object has a type that len() not accept. -// -// a.Lenf(mySlice, 3, "error message %s", "formatted") -func (a *Assertions) Lenf(object interface{}, length int, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Lenf(a.t, object, length, msg, args...) -} - -// Less asserts that the first element is less than the second -// -// a.Less(1, 2) -// a.Less(float64(1), float64(2)) -// a.Less("a", "b") -func (a *Assertions) Less(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Less(a.t, e1, e2, msgAndArgs...) -} - -// LessOrEqual asserts that the first element is less than or equal to the second -// -// a.LessOrEqual(1, 2) -// a.LessOrEqual(2, 2) -// a.LessOrEqual("a", "b") -// a.LessOrEqual("b", "b") -func (a *Assertions) LessOrEqual(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - LessOrEqual(a.t, e1, e2, msgAndArgs...) -} - -// LessOrEqualf asserts that the first element is less than or equal to the second -// -// a.LessOrEqualf(1, 2, "error message %s", "formatted") -// a.LessOrEqualf(2, 2, "error message %s", "formatted") -// a.LessOrEqualf("a", "b", "error message %s", "formatted") -// a.LessOrEqualf("b", "b", "error message %s", "formatted") -func (a *Assertions) LessOrEqualf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - LessOrEqualf(a.t, e1, e2, msg, args...) -} - -// Lessf asserts that the first element is less than the second -// -// a.Lessf(1, 2, "error message %s", "formatted") -// a.Lessf(float64(1), float64(2), "error message %s", "formatted") -// a.Lessf("a", "b", "error message %s", "formatted") -func (a *Assertions) Lessf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Lessf(a.t, e1, e2, msg, args...) -} - -// Negative asserts that the specified element is negative -// -// a.Negative(-1) -// a.Negative(-1.23) -func (a *Assertions) Negative(e interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Negative(a.t, e, msgAndArgs...) -} - -// Negativef asserts that the specified element is negative -// -// a.Negativef(-1, "error message %s", "formatted") -// a.Negativef(-1.23, "error message %s", "formatted") -func (a *Assertions) Negativef(e interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Negativef(a.t, e, msg, args...) -} - -// Never asserts that the given condition doesn't satisfy in waitFor time, -// periodically checking the target function each tick. -// -// a.Never(func() bool { return false; }, time.Second, 10*time.Millisecond) -func (a *Assertions) Never(condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Never(a.t, condition, waitFor, tick, msgAndArgs...) -} - -// Neverf asserts that the given condition doesn't satisfy in waitFor time, -// periodically checking the target function each tick. -// -// a.Neverf(func() bool { return false; }, time.Second, 10*time.Millisecond, "error message %s", "formatted") -func (a *Assertions) Neverf(condition func() bool, waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Neverf(a.t, condition, waitFor, tick, msg, args...) -} - -// Nil asserts that the specified object is nil. -// -// a.Nil(err) -func (a *Assertions) Nil(object interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Nil(a.t, object, msgAndArgs...) -} - -// Nilf asserts that the specified object is nil. -// -// a.Nilf(err, "error message %s", "formatted") -func (a *Assertions) Nilf(object interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Nilf(a.t, object, msg, args...) -} - -// NoDirExists checks whether a directory does not exist in the given path. -// It fails if the path points to an existing _directory_ only. -func (a *Assertions) NoDirExists(path string, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NoDirExists(a.t, path, msgAndArgs...) -} - -// NoDirExistsf checks whether a directory does not exist in the given path. -// It fails if the path points to an existing _directory_ only. -func (a *Assertions) NoDirExistsf(path string, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NoDirExistsf(a.t, path, msg, args...) -} - -// NoError asserts that a function returned no error (i.e. `nil`). -// -// actualObj, err := SomeFunction() -// if a.NoError(err) { -// assert.Equal(t, expectedObj, actualObj) -// } -func (a *Assertions) NoError(err error, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NoError(a.t, err, msgAndArgs...) -} - -// NoErrorf asserts that a function returned no error (i.e. `nil`). -// -// actualObj, err := SomeFunction() -// if a.NoErrorf(err, "error message %s", "formatted") { -// assert.Equal(t, expectedObj, actualObj) -// } -func (a *Assertions) NoErrorf(err error, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NoErrorf(a.t, err, msg, args...) -} - -// NoFileExists checks whether a file does not exist in a given path. It fails -// if the path points to an existing _file_ only. -func (a *Assertions) NoFileExists(path string, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NoFileExists(a.t, path, msgAndArgs...) -} - -// NoFileExistsf checks whether a file does not exist in a given path. It fails -// if the path points to an existing _file_ only. -func (a *Assertions) NoFileExistsf(path string, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NoFileExistsf(a.t, path, msg, args...) -} - -// NotContains asserts that the specified string, list(array, slice...) or map does NOT contain the -// specified substring or element. -// -// a.NotContains("Hello World", "Earth") -// a.NotContains(["Hello", "World"], "Earth") -// a.NotContains({"Hello": "World"}, "Earth") -func (a *Assertions) NotContains(s interface{}, contains interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NotContains(a.t, s, contains, msgAndArgs...) -} - -// NotContainsf asserts that the specified string, list(array, slice...) or map does NOT contain the -// specified substring or element. -// -// a.NotContainsf("Hello World", "Earth", "error message %s", "formatted") -// a.NotContainsf(["Hello", "World"], "Earth", "error message %s", "formatted") -// a.NotContainsf({"Hello": "World"}, "Earth", "error message %s", "formatted") -func (a *Assertions) NotContainsf(s interface{}, contains interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NotContainsf(a.t, s, contains, msg, args...) -} - -// NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either -// a slice or a channel with len == 0. -// -// if a.NotEmpty(obj) { -// assert.Equal(t, "two", obj[1]) -// } -func (a *Assertions) NotEmpty(object interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NotEmpty(a.t, object, msgAndArgs...) -} - -// NotEmptyf asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either -// a slice or a channel with len == 0. -// -// if a.NotEmptyf(obj, "error message %s", "formatted") { -// assert.Equal(t, "two", obj[1]) -// } -func (a *Assertions) NotEmptyf(object interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NotEmptyf(a.t, object, msg, args...) -} - -// NotEqual asserts that the specified values are NOT equal. -// -// a.NotEqual(obj1, obj2) -// -// Pointer variable equality is determined based on the equality of the -// referenced values (as opposed to the memory addresses). -func (a *Assertions) NotEqual(expected interface{}, actual interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NotEqual(a.t, expected, actual, msgAndArgs...) -} - -// NotEqualValues asserts that two objects are not equal even when converted to the same type -// -// a.NotEqualValues(obj1, obj2) -func (a *Assertions) NotEqualValues(expected interface{}, actual interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NotEqualValues(a.t, expected, actual, msgAndArgs...) -} - -// NotEqualValuesf asserts that two objects are not equal even when converted to the same type -// -// a.NotEqualValuesf(obj1, obj2, "error message %s", "formatted") -func (a *Assertions) NotEqualValuesf(expected interface{}, actual interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NotEqualValuesf(a.t, expected, actual, msg, args...) -} - -// NotEqualf asserts that the specified values are NOT equal. -// -// a.NotEqualf(obj1, obj2, "error message %s", "formatted") -// -// Pointer variable equality is determined based on the equality of the -// referenced values (as opposed to the memory addresses). -func (a *Assertions) NotEqualf(expected interface{}, actual interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NotEqualf(a.t, expected, actual, msg, args...) -} - -// NotErrorIs asserts that at none of the errors in err's chain matches target. -// This is a wrapper for errors.Is. -func (a *Assertions) NotErrorIs(err error, target error, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NotErrorIs(a.t, err, target, msgAndArgs...) -} - -// NotErrorIsf asserts that at none of the errors in err's chain matches target. -// This is a wrapper for errors.Is. -func (a *Assertions) NotErrorIsf(err error, target error, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NotErrorIsf(a.t, err, target, msg, args...) -} - -// NotImplements asserts that an object does not implement the specified interface. -// -// a.NotImplements((*MyInterface)(nil), new(MyObject)) -func (a *Assertions) NotImplements(interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NotImplements(a.t, interfaceObject, object, msgAndArgs...) -} - -// NotImplementsf asserts that an object does not implement the specified interface. -// -// a.NotImplementsf((*MyInterface)(nil), new(MyObject), "error message %s", "formatted") -func (a *Assertions) NotImplementsf(interfaceObject interface{}, object interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NotImplementsf(a.t, interfaceObject, object, msg, args...) -} - -// NotNil asserts that the specified object is not nil. -// -// a.NotNil(err) -func (a *Assertions) NotNil(object interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NotNil(a.t, object, msgAndArgs...) -} - -// NotNilf asserts that the specified object is not nil. -// -// a.NotNilf(err, "error message %s", "formatted") -func (a *Assertions) NotNilf(object interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NotNilf(a.t, object, msg, args...) -} - -// NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic. -// -// a.NotPanics(func(){ RemainCalm() }) -func (a *Assertions) NotPanics(f assert.PanicTestFunc, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NotPanics(a.t, f, msgAndArgs...) -} - -// NotPanicsf asserts that the code inside the specified PanicTestFunc does NOT panic. -// -// a.NotPanicsf(func(){ RemainCalm() }, "error message %s", "formatted") -func (a *Assertions) NotPanicsf(f assert.PanicTestFunc, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NotPanicsf(a.t, f, msg, args...) -} - -// NotRegexp asserts that a specified regexp does not match a string. -// -// a.NotRegexp(regexp.MustCompile("starts"), "it's starting") -// a.NotRegexp("^start", "it's not starting") -func (a *Assertions) NotRegexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NotRegexp(a.t, rx, str, msgAndArgs...) -} - -// NotRegexpf asserts that a specified regexp does not match a string. -// -// a.NotRegexpf(regexp.MustCompile("starts"), "it's starting", "error message %s", "formatted") -// a.NotRegexpf("^start", "it's not starting", "error message %s", "formatted") -func (a *Assertions) NotRegexpf(rx interface{}, str interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NotRegexpf(a.t, rx, str, msg, args...) -} - -// NotSame asserts that two pointers do not reference the same object. -// -// a.NotSame(ptr1, ptr2) -// -// Both arguments must be pointer variables. Pointer variable sameness is -// determined based on the equality of both type and value. -func (a *Assertions) NotSame(expected interface{}, actual interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NotSame(a.t, expected, actual, msgAndArgs...) -} - -// NotSamef asserts that two pointers do not reference the same object. -// -// a.NotSamef(ptr1, ptr2, "error message %s", "formatted") -// -// Both arguments must be pointer variables. Pointer variable sameness is -// determined based on the equality of both type and value. -func (a *Assertions) NotSamef(expected interface{}, actual interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NotSamef(a.t, expected, actual, msg, args...) -} - -// NotSubset asserts that the specified list(array, slice...) or map does NOT -// contain all elements given in the specified subset list(array, slice...) or -// map. -// -// a.NotSubset([1, 3, 4], [1, 2]) -// a.NotSubset({"x": 1, "y": 2}, {"z": 3}) -func (a *Assertions) NotSubset(list interface{}, subset interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NotSubset(a.t, list, subset, msgAndArgs...) -} - -// NotSubsetf asserts that the specified list(array, slice...) or map does NOT -// contain all elements given in the specified subset list(array, slice...) or -// map. -// -// a.NotSubsetf([1, 3, 4], [1, 2], "error message %s", "formatted") -// a.NotSubsetf({"x": 1, "y": 2}, {"z": 3}, "error message %s", "formatted") -func (a *Assertions) NotSubsetf(list interface{}, subset interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NotSubsetf(a.t, list, subset, msg, args...) -} - -// NotZero asserts that i is not the zero value for its type. -func (a *Assertions) NotZero(i interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NotZero(a.t, i, msgAndArgs...) -} - -// NotZerof asserts that i is not the zero value for its type. -func (a *Assertions) NotZerof(i interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - NotZerof(a.t, i, msg, args...) -} - -// Panics asserts that the code inside the specified PanicTestFunc panics. -// -// a.Panics(func(){ GoCrazy() }) -func (a *Assertions) Panics(f assert.PanicTestFunc, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Panics(a.t, f, msgAndArgs...) -} - -// PanicsWithError asserts that the code inside the specified PanicTestFunc -// panics, and that the recovered panic value is an error that satisfies the -// EqualError comparison. -// -// a.PanicsWithError("crazy error", func(){ GoCrazy() }) -func (a *Assertions) PanicsWithError(errString string, f assert.PanicTestFunc, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - PanicsWithError(a.t, errString, f, msgAndArgs...) -} - -// PanicsWithErrorf asserts that the code inside the specified PanicTestFunc -// panics, and that the recovered panic value is an error that satisfies the -// EqualError comparison. -// -// a.PanicsWithErrorf("crazy error", func(){ GoCrazy() }, "error message %s", "formatted") -func (a *Assertions) PanicsWithErrorf(errString string, f assert.PanicTestFunc, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - PanicsWithErrorf(a.t, errString, f, msg, args...) -} - -// PanicsWithValue asserts that the code inside the specified PanicTestFunc panics, and that -// the recovered panic value equals the expected panic value. -// -// a.PanicsWithValue("crazy error", func(){ GoCrazy() }) -func (a *Assertions) PanicsWithValue(expected interface{}, f assert.PanicTestFunc, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - PanicsWithValue(a.t, expected, f, msgAndArgs...) -} - -// PanicsWithValuef asserts that the code inside the specified PanicTestFunc panics, and that -// the recovered panic value equals the expected panic value. -// -// a.PanicsWithValuef("crazy error", func(){ GoCrazy() }, "error message %s", "formatted") -func (a *Assertions) PanicsWithValuef(expected interface{}, f assert.PanicTestFunc, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - PanicsWithValuef(a.t, expected, f, msg, args...) -} - -// Panicsf asserts that the code inside the specified PanicTestFunc panics. -// -// a.Panicsf(func(){ GoCrazy() }, "error message %s", "formatted") -func (a *Assertions) Panicsf(f assert.PanicTestFunc, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Panicsf(a.t, f, msg, args...) -} - -// Positive asserts that the specified element is positive -// -// a.Positive(1) -// a.Positive(1.23) -func (a *Assertions) Positive(e interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Positive(a.t, e, msgAndArgs...) -} - -// Positivef asserts that the specified element is positive -// -// a.Positivef(1, "error message %s", "formatted") -// a.Positivef(1.23, "error message %s", "formatted") -func (a *Assertions) Positivef(e interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Positivef(a.t, e, msg, args...) -} - -// Regexp asserts that a specified regexp matches a string. -// -// a.Regexp(regexp.MustCompile("start"), "it's starting") -// a.Regexp("start...$", "it's not starting") -func (a *Assertions) Regexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Regexp(a.t, rx, str, msgAndArgs...) -} - -// Regexpf asserts that a specified regexp matches a string. -// -// a.Regexpf(regexp.MustCompile("start"), "it's starting", "error message %s", "formatted") -// a.Regexpf("start...$", "it's not starting", "error message %s", "formatted") -func (a *Assertions) Regexpf(rx interface{}, str interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Regexpf(a.t, rx, str, msg, args...) -} - -// Same asserts that two pointers reference the same object. -// -// a.Same(ptr1, ptr2) -// -// Both arguments must be pointer variables. Pointer variable sameness is -// determined based on the equality of both type and value. -func (a *Assertions) Same(expected interface{}, actual interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Same(a.t, expected, actual, msgAndArgs...) -} - -// Samef asserts that two pointers reference the same object. -// -// a.Samef(ptr1, ptr2, "error message %s", "formatted") -// -// Both arguments must be pointer variables. Pointer variable sameness is -// determined based on the equality of both type and value. -func (a *Assertions) Samef(expected interface{}, actual interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Samef(a.t, expected, actual, msg, args...) -} - -// Subset asserts that the specified list(array, slice...) or map contains all -// elements given in the specified subset list(array, slice...) or map. -// -// a.Subset([1, 2, 3], [1, 2]) -// a.Subset({"x": 1, "y": 2}, {"x": 1}) -func (a *Assertions) Subset(list interface{}, subset interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Subset(a.t, list, subset, msgAndArgs...) -} - -// Subsetf asserts that the specified list(array, slice...) or map contains all -// elements given in the specified subset list(array, slice...) or map. -// -// a.Subsetf([1, 2, 3], [1, 2], "error message %s", "formatted") -// a.Subsetf({"x": 1, "y": 2}, {"x": 1}, "error message %s", "formatted") -func (a *Assertions) Subsetf(list interface{}, subset interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Subsetf(a.t, list, subset, msg, args...) -} - -// True asserts that the specified value is true. -// -// a.True(myBool) -func (a *Assertions) True(value bool, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - True(a.t, value, msgAndArgs...) -} - -// Truef asserts that the specified value is true. -// -// a.Truef(myBool, "error message %s", "formatted") -func (a *Assertions) Truef(value bool, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Truef(a.t, value, msg, args...) -} - -// WithinDuration asserts that the two times are within duration delta of each other. -// -// a.WithinDuration(time.Now(), time.Now(), 10*time.Second) -func (a *Assertions) WithinDuration(expected time.Time, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - WithinDuration(a.t, expected, actual, delta, msgAndArgs...) -} - -// WithinDurationf asserts that the two times are within duration delta of each other. -// -// a.WithinDurationf(time.Now(), time.Now(), 10*time.Second, "error message %s", "formatted") -func (a *Assertions) WithinDurationf(expected time.Time, actual time.Time, delta time.Duration, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - WithinDurationf(a.t, expected, actual, delta, msg, args...) -} - -// WithinRange asserts that a time is within a time range (inclusive). -// -// a.WithinRange(time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second)) -func (a *Assertions) WithinRange(actual time.Time, start time.Time, end time.Time, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - WithinRange(a.t, actual, start, end, msgAndArgs...) -} - -// WithinRangef asserts that a time is within a time range (inclusive). -// -// a.WithinRangef(time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second), "error message %s", "formatted") -func (a *Assertions) WithinRangef(actual time.Time, start time.Time, end time.Time, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - WithinRangef(a.t, actual, start, end, msg, args...) -} - -// YAMLEq asserts that two YAML strings are equivalent. -func (a *Assertions) YAMLEq(expected string, actual string, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - YAMLEq(a.t, expected, actual, msgAndArgs...) -} - -// YAMLEqf asserts that two YAML strings are equivalent. -func (a *Assertions) YAMLEqf(expected string, actual string, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - YAMLEqf(a.t, expected, actual, msg, args...) -} - -// Zero asserts that i is the zero value for its type. -func (a *Assertions) Zero(i interface{}, msgAndArgs ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Zero(a.t, i, msgAndArgs...) -} - -// Zerof asserts that i is the zero value for its type. -func (a *Assertions) Zerof(i interface{}, msg string, args ...interface{}) { - if h, ok := a.t.(tHelper); ok { - h.Helper() - } - Zerof(a.t, i, msg, args...) -} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/require/require_forward.go.tmpl b/trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/require/require_forward.go.tmpl deleted file mode 100644 index 54124df1d..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/require/require_forward.go.tmpl +++ /dev/null @@ -1,5 +0,0 @@ -{{.CommentWithoutT "a"}} -func (a *Assertions) {{.DocInfo.Name}}({{.Params}}) { - if h, ok := a.t.(tHelper); ok { h.Helper() } - {{.DocInfo.Name}}(a.t, {{.ForwardedParams}}) -} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/require/requirements.go b/trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/require/requirements.go deleted file mode 100644 index 91772dfeb..000000000 --- a/trunk/3rdparty/srs-bench/vendor/github.com/stretchr/testify/require/requirements.go +++ /dev/null @@ -1,29 +0,0 @@ -package require - -// TestingT is an interface wrapper around *testing.T -type TestingT interface { - Errorf(format string, args ...interface{}) - FailNow() -} - -type tHelper interface { - Helper() -} - -// ComparisonAssertionFunc is a common function prototype when comparing two values. Can be useful -// for table driven tests. -type ComparisonAssertionFunc func(TestingT, interface{}, interface{}, ...interface{}) - -// ValueAssertionFunc is a common function prototype when validating a single value. Can be useful -// for table driven tests. -type ValueAssertionFunc func(TestingT, interface{}, ...interface{}) - -// BoolAssertionFunc is a common function prototype when validating a bool value. Can be useful -// for table driven tests. -type BoolAssertionFunc func(TestingT, bool, ...interface{}) - -// ErrorAssertionFunc is a common function prototype when validating an error value. Can be useful -// for table driven tests. -type ErrorAssertionFunc func(TestingT, error, ...interface{}) - -//go:generate sh -c "cd ../_codegen && go build && cd - && ../_codegen/_codegen -output-package=require -template=require.go.tmpl -include-format-funcs" diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/wlynxg/anet/.gitignore b/trunk/3rdparty/srs-bench/vendor/github.com/wlynxg/anet/.gitignore new file mode 100644 index 000000000..723ef36f4 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/wlynxg/anet/.gitignore @@ -0,0 +1 @@ +.idea \ No newline at end of file diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/wlynxg/anet/LICENSE b/trunk/3rdparty/srs-bench/vendor/github.com/wlynxg/anet/LICENSE new file mode 100644 index 000000000..db6fa3676 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/wlynxg/anet/LICENSE @@ -0,0 +1,28 @@ +BSD 3-Clause License + +Copyright (c) 2023, wlynxg + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/wlynxg/anet/README.md b/trunk/3rdparty/srs-bench/vendor/github.com/wlynxg/anet/README.md new file mode 100644 index 000000000..93fe68b61 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/wlynxg/anet/README.md @@ -0,0 +1,126 @@ +## Introduction +In response to the modifications made to the permissions for accessing system MAC addresses in Android 11, ordinary applications encounter several main issues when using NETLINK sockets: + +- Not allowing bind operations on `NETLINK` sockets. +- Not permitting the use of the `RTM_GETLINK` functionality. + +For detailed information, please refer to: https://developer.android.com/training/articles/user-data-ids#mac-11-plus + +As a result of the aforementioned reasons, using `net.Interfaces()` and `net.InterfaceAddrs()` from the Go net package in the Android environment leads to the `route ip+net: netlinkrib: permission denied` error. + +You can find specific issue details here: https://github.com/golang/go/issues/40569 + +To address the issue of using the Go net package in the Android environment, we have made partial modifications to its source code to ensure proper functionality on Android. + +I have fully resolved the issues with `net.InterfaceAddrs()`. + +However, for `net.Interfaces()`, we have only addressed some problems, as the following issues still remain: +- It can only return interfaces with IP addresses. +- It cannot return hardware MAC addresses. + +Nevertheless, the fixed `net.Interfaces()` function now aligns with the Android API's `NetworkInterface.getNetworkInterfaces()` and can be used normally in most scenarios. + +The specific fix logic includes: + +Removing the `Bind()` operation on `Netlink` sockets in the `NetlinkRIB()` function. +Using `ioctl` based on the Index number returned by `RTM_GETADDR` to retrieve the network card's name, MTU, and flags. + +There are two implementations of the `net` package: one from the [Go standard library](https://pkg.go.dev/net) and another from the [golang.org/x/net](https://pkg.go.dev/golang.org/x/net) module. Both of these implementations have the same issues in the Android environment. The `anet` package should be compatible with both of them. + +## Test Code +### net.Interface() +use `net.Interface()`: +```go +func RawInterface() { + interfaces, err := net.Interfaces() + if err != nil { + panic(err) + } + + for _, i := range interfaces { + log.Println(i) + } +} +``` +result: +``` +panic: route ip+net: netlinkrib: permission denied +``` + +use `anet.Interface()`: +```go +func AnetInterface() { + interfaces, err := anet.Interfaces() + if err != nil { + panic(err) + } + + for _, i := range interfaces { + log.Println(i) + } +} +``` + +result: +``` +{1 65536 lo up|loopback|running} +{15 1400 rmnet_data1 up|running} +{24 1500 wlan0 up|broadcast|multicast|running} +{3 1500 dummy0 up|broadcast|running} +{4 1500 ifb0 up|broadcast|running} +{5 1500 ifb1 up|broadcast|running} +{12 1500 ifb2 up|broadcast|running} +{14 1500 rmnet_data0 up|running} +{16 1400 rmnet_data2 up|running} +{17 1400 rmnet_data3 up|running} +``` + +### net.InterfaceAddrs() +use `net.InterfaceAddrs()`: +```go +func NetInterfaceAddrs() { + addrs, err := net.InterfaceAddrs() + if err != nil { + panic(err) + } + + for _, addr := range addrs { + log.Println(addr) + } +} +``` +result: +``` +panic: route ip+net: netlinkrib: permission denied +``` + +use `anet.InterfaceAddrs()`: +```go +func AnetInterfaceAddrs() { + addrs, err := anet.InterfaceAddrs() + if err != nil { + panic(err) + } + + for _, addr := range addrs { + log.Println(addr) + } +} +``` +result: +``` +127.0.0.1/8 +::1/128 +... +192.168.6.143/24 +fe80::7e4f:4446:eb3:1eb8/64 +``` + +## Other issues due to #40569 +- https://github.com/golang/go/issues/68082 + +## How to build with Go 1.23.0 or later +The `anet` library internally relies on `//go:linkname` directive. Since the usage of `//go:linkname` has been restricted since Go 1.23.0 ([Go 1.23 Release Notes](https://tip.golang.org/doc/go1.23#linker)), it is necessary to specify the `-checklinkname=0` linker flag when building the `anet` package with Go 1.23.0 or later. Without this flag, the following linker error will occur: +``` +link: github.com/wlynxg/anet: invalid reference to net.zoneCache +``` diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/wlynxg/anet/README_zh.md b/trunk/3rdparty/srs-bench/vendor/github.com/wlynxg/anet/README_zh.md new file mode 100644 index 000000000..07e9a3c2c --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/wlynxg/anet/README_zh.md @@ -0,0 +1,25 @@ +针对Android 11之后对访问系统MAC地址的权限进行了修改的问题,导致普通应用在调用`NETLINK`套接字时会遇到以下几个主要问题: +- 不允许对`NETLINK`套接字进行`bind`操作。 +- 不允许调用`RTM_GETLINK`功能。 + +详细说明可以在此链接找到:https://developer.android.com/training/articles/user-data-ids#mac-11-plus + +由于上述两个原因,导致在安卓环境下使用Go net包中的`net.Interfaces()`和`net.InterfaceAddrs()`时会抛出`route ip+net: netlinkrib: permission denied`错误。 +具体 issue 可见:https://github.com/golang/go/issues/40569 + +为了解决在安卓环境下使用Go net包的问题,我们对其源代码进行了部分改造,以使其能够在Android上正常工作。 + +对于`net.InterfaceAddrs()`,我已经完全解决了其中的问题; +对于`net.Interfaces()`,我只解决了部分问题,目前仍存在以下问题: +- 只能返回具有IP地址的接口。 +- 不能返回硬件的MAC地址。 + +但是修复后的`net.Interfaces()`函数现在与Android API的`NetworkInterface.getNetworkInterfaces()`保持一致,在大多数情况下可正常使用。 + +具体修复逻辑包括: + +- 取消了`NetlinkRIB()`函数中对`Netlink`套接字的`Bind()`操作。 +- 根据`RTM_GETADDR`返回的Index号,使用`ioctl`获取其网卡的名称、MTU和标志位。 + +## 由于 #40569 导致的其他问题 +- #[68082](https://github.com/golang/go/issues/68082) \ No newline at end of file diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/wlynxg/anet/android_api_level.go b/trunk/3rdparty/srs-bench/vendor/github.com/wlynxg/anet/android_api_level.go new file mode 100644 index 000000000..a0a93e8db --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/wlynxg/anet/android_api_level.go @@ -0,0 +1,7 @@ +//go:build !(android && cgo) + +package anet + +func androidDeviceApiLevel() int { + return -1 +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/wlynxg/anet/android_api_level_cgo.go b/trunk/3rdparty/srs-bench/vendor/github.com/wlynxg/anet/android_api_level_cgo.go new file mode 100644 index 000000000..992feeef3 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/wlynxg/anet/android_api_level_cgo.go @@ -0,0 +1,23 @@ +//go:build android && cgo + +package anet + +// #include +import "C" + +import "sync" + +var ( + apiLevel int + once sync.Once +) + +// Returns the API level of the device we're actually running on, or -1 on failure. +// The returned value is equivalent to the Java Build.VERSION.SDK_INT API. +func androidDeviceApiLevel() int { + once.Do(func() { + apiLevel = int(C.android_get_device_api_level()) + }) + + return apiLevel +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/wlynxg/anet/interface.go b/trunk/3rdparty/srs-bench/vendor/github.com/wlynxg/anet/interface.go new file mode 100644 index 000000000..384f29c70 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/wlynxg/anet/interface.go @@ -0,0 +1,30 @@ +//go:build !android +// +build !android + +package anet + +import ( + "net" +) + +// Interfaces returns a list of the system's network interfaces. +func Interfaces() ([]net.Interface, error) { + return net.Interfaces() +} + +// InterfaceAddrs returns a list of the system's unicast interface +// addresses. +// +// The returned list does not identify the associated interface; use +// Interfaces and Interface.Addrs for more detail. +func InterfaceAddrs() ([]net.Addr, error) { + return net.InterfaceAddrs() +} + +// InterfaceAddrsByInterface returns a list of the system's unicast +// interface addresses by specific interface. +func InterfaceAddrsByInterface(ifi *net.Interface) ([]net.Addr, error) { + return ifi.Addrs() +} + +func SetAndroidVersion(version uint) {} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/wlynxg/anet/interface_android.go b/trunk/3rdparty/srs-bench/vendor/github.com/wlynxg/anet/interface_android.go new file mode 100644 index 000000000..6b080c5d9 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/wlynxg/anet/interface_android.go @@ -0,0 +1,442 @@ +package anet + +import ( + "bytes" + "errors" + "net" + "os" + "sync" + "syscall" + "time" + "unsafe" +) + +const ( + android11ApiLevel = 30 +) + +var ( + customAndroidApiLevel = -1 + errInvalidInterface = errors.New("invalid network interface") + errInvalidInterfaceIndex = errors.New("invalid network interface index") + errInvalidInterfaceName = errors.New("invalid network interface name") + errNoSuchInterface = errors.New("no such network interface") + errNoSuchMulticastInterface = errors.New("no such multicast network interface") +) + +type ifReq [40]byte + +// Interfaces returns a list of the system's network interfaces. +func Interfaces() ([]net.Interface, error) { + if androidApiLevel() < android11ApiLevel { + return net.Interfaces() + } + + ift, err := interfaceTable(0) + if err != nil { + return nil, &net.OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: err} + } + if len(ift) != 0 { + zoneCache.update(ift, true) + zoneCacheX.update(ift, true) + } + return ift, nil +} + +// InterfaceAddrs returns a list of the system's unicast interface +// addresses. +// +// The returned list does not identify the associated interface; use +// Interfaces and Interface.Addrs for more detail. +func InterfaceAddrs() ([]net.Addr, error) { + if androidApiLevel() < android11ApiLevel { + return net.InterfaceAddrs() + } + + ifat, err := interfaceAddrTable(nil) + if err != nil { + err = &net.OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: err} + } + return ifat, err +} + +// InterfaceByIndex returns the interface specified by index. +// +// On Solaris, it returns one of the logical network interfaces +// sharing the logical data link; for more precision use +// InterfaceByName. +func InterfaceByIndex(index int) (*net.Interface, error) { + if androidApiLevel() < android11ApiLevel { + return net.InterfaceByIndex(index) + } + + if index <= 0 { + return nil, &net.OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: errInvalidInterfaceIndex} + } + ift, err := interfaceTable(index) + if err != nil { + return nil, &net.OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: err} + } + ifi, err := interfaceByIndex(ift, index) + if err != nil { + err = &net.OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: err} + } + return ifi, err +} + +// InterfaceByName returns the interface specified by name. +func InterfaceByName(name string) (*net.Interface, error) { + if name == "" { + return nil, &net.OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: errInvalidInterfaceName} + } + ift, err := interfaceTable(0) + if err != nil { + return nil, &net.OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: err} + } + if len(ift) != 0 { + zoneCache.update(ift, true) + zoneCacheX.update(ift, true) + } + for _, ifi := range ift { + if name == ifi.Name { + return &ifi, nil + } + } + return nil, &net.OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: errNoSuchInterface} +} + +// InterfaceAddrsByInterface returns a list of the system's unicast +// interface addresses by specific interface. +func InterfaceAddrsByInterface(ifi *net.Interface) ([]net.Addr, error) { + if ifi == nil { + return nil, &net.OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: errInvalidInterface} + } + + if androidApiLevel() < android11ApiLevel { + return ifi.Addrs() + } + + ifat, err := interfaceAddrTable(ifi) + if err != nil { + err = &net.OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: err} + } + return ifat, err +} + +// SetAndroidVersion set the Android environment in which the program runs. +// The Android system version number can be obtained through +// `android.os.Build.VERSION.RELEASE` of the Android framework. +// If version is 0 the actual version will be detected automatically if possible. +func SetAndroidVersion(version uint) { + switch { + case version == 0: + customAndroidApiLevel = -1 + case version >= 11: + customAndroidApiLevel = android11ApiLevel + default: + customAndroidApiLevel = 0 + } +} + +func androidApiLevel() int { + if customAndroidApiLevel != -1 { + // user-provided api level should be used + return customAndroidApiLevel + } + + // try to autodetect api level + return androidDeviceApiLevel() +} + +// An ipv6ZoneCache represents a cache holding partial network +// interface information. It is used for reducing the cost of IPv6 +// addressing scope zone resolution. +// +// Multiple names sharing the index are managed by first-come +// first-served basis for consistency. +type ipv6ZoneCache struct { + sync.RWMutex // guard the following + lastFetched time.Time // last time routing information was fetched + toIndex map[string]int // interface name to its index + toName map[int]string // interface index to its name +} + +//go:linkname zoneCache net.zoneCache +var zoneCache ipv6ZoneCache + +//go:linkname zoneCacheX golang.org/x/net/internal/socket.zoneCache +var zoneCacheX ipv6ZoneCache + +// update refreshes the network interface information if the cache was last +// updated more than 1 minute ago, or if force is set. It reports whether the +// cache was updated. +func (zc *ipv6ZoneCache) update(ift []net.Interface, force bool) (updated bool) { + zc.Lock() + defer zc.Unlock() + now := time.Now() + if !force && zc.lastFetched.After(now.Add(-60*time.Second)) { + return false + } + zc.lastFetched = now + if len(ift) == 0 { + var err error + if ift, err = interfaceTable(0); err != nil { + return false + } + } + zc.toIndex = make(map[string]int, len(ift)) + zc.toName = make(map[int]string, len(ift)) + for _, ifi := range ift { + zc.toIndex[ifi.Name] = ifi.Index + if _, ok := zc.toName[ifi.Index]; !ok { + zc.toName[ifi.Index] = ifi.Name + } + } + return true +} + +// If the ifindex is zero, interfaceTable returns mappings of all +// network interfaces. Otherwise it returns a mapping of a specific +// interface. +func interfaceTable(ifindex int) ([]net.Interface, error) { + tab, err := NetlinkRIB(syscall.RTM_GETADDR, syscall.AF_UNSPEC) + if err != nil { + return nil, os.NewSyscallError("netlinkrib", err) + } + msgs, err := syscall.ParseNetlinkMessage(tab) + if err != nil { + return nil, os.NewSyscallError("parsenetlinkmessage", err) + } + + var ift []net.Interface + im := make(map[uint32]struct{}) +loop: + for _, m := range msgs { + switch m.Header.Type { + case syscall.NLMSG_DONE: + break loop + case syscall.RTM_NEWADDR: + ifam := (*syscall.IfAddrmsg)(unsafe.Pointer(&m.Data[0])) + if _, ok := im[ifam.Index]; ok { + continue + } else { + im[ifam.Index] = struct{}{} + } + + if ifindex == 0 || ifindex == int(ifam.Index) { + ifi := newLink(ifam) + if ifi != nil { + ift = append(ift, *ifi) + } + if ifindex == int(ifam.Index) { + break loop + } + } + } + } + + return ift, nil +} + +func newLink(ifam *syscall.IfAddrmsg) *net.Interface { + ift := &net.Interface{Index: int(ifam.Index)} + + name, err := indexToName(ifam.Index) + if err != nil { + return nil + } + ift.Name = name + + mtu, err := nameToMTU(name) + if err != nil { + return nil + } + ift.MTU = mtu + + flags, err := nameToFlags(name) + if err != nil { + return nil + } + ift.Flags = flags + return ift +} + +func linkFlags(rawFlags uint32) net.Flags { + var f net.Flags + if rawFlags&syscall.IFF_UP != 0 { + f |= net.FlagUp + } + if rawFlags&syscall.IFF_RUNNING != 0 { + f |= net.FlagRunning + } + if rawFlags&syscall.IFF_BROADCAST != 0 { + f |= net.FlagBroadcast + } + if rawFlags&syscall.IFF_LOOPBACK != 0 { + f |= net.FlagLoopback + } + if rawFlags&syscall.IFF_POINTOPOINT != 0 { + f |= net.FlagPointToPoint + } + if rawFlags&syscall.IFF_MULTICAST != 0 { + f |= net.FlagMulticast + } + return f +} + +// If the ifi is nil, interfaceAddrTable returns addresses for all +// network interfaces. Otherwise it returns addresses for a specific +// interface. +func interfaceAddrTable(ifi *net.Interface) ([]net.Addr, error) { + tab, err := NetlinkRIB(syscall.RTM_GETADDR, syscall.AF_UNSPEC) + if err != nil { + return nil, os.NewSyscallError("netlinkrib", err) + } + msgs, err := syscall.ParseNetlinkMessage(tab) + if err != nil { + return nil, os.NewSyscallError("parsenetlinkmessage", err) + } + + var ift []net.Interface + if ifi == nil { + var err error + ift, err = interfaceTable(0) + if err != nil { + return nil, err + } + } + ifat, err := addrTable(ift, ifi, msgs) + if err != nil { + return nil, err + } + return ifat, nil +} + +func addrTable(ift []net.Interface, ifi *net.Interface, msgs []syscall.NetlinkMessage) ([]net.Addr, error) { + var ifat []net.Addr +loop: + for _, m := range msgs { + switch m.Header.Type { + case syscall.NLMSG_DONE: + break loop + case syscall.RTM_NEWADDR: + ifam := (*syscall.IfAddrmsg)(unsafe.Pointer(&m.Data[0])) + if len(ift) != 0 || ifi.Index == int(ifam.Index) { + attrs, err := syscall.ParseNetlinkRouteAttr(&m) + if err != nil { + return nil, os.NewSyscallError("parsenetlinkrouteattr", err) + } + ifa := newAddr(ifam, attrs) + if ifa != nil { + ifat = append(ifat, ifa) + } + } + } + } + return ifat, nil +} + +func newAddr(ifam *syscall.IfAddrmsg, attrs []syscall.NetlinkRouteAttr) net.Addr { + var ipPointToPoint bool + // Seems like we need to make sure whether the IP interface + // stack consists of IP point-to-point numbered or unnumbered + // addressing. + for _, a := range attrs { + if a.Attr.Type == syscall.IFA_LOCAL { + ipPointToPoint = true + break + } + } + for _, a := range attrs { + if ipPointToPoint && a.Attr.Type == syscall.IFA_ADDRESS { + continue + } + switch ifam.Family { + case syscall.AF_INET: + return &net.IPNet{IP: net.IPv4(a.Value[0], a.Value[1], a.Value[2], a.Value[3]), Mask: net.CIDRMask(int(ifam.Prefixlen), 8*net.IPv4len)} + case syscall.AF_INET6: + ifa := &net.IPNet{IP: make(net.IP, net.IPv6len), Mask: net.CIDRMask(int(ifam.Prefixlen), 8*net.IPv6len)} + copy(ifa.IP, a.Value[:]) + return ifa + } + } + return nil +} + +func interfaceByIndex(ift []net.Interface, index int) (*net.Interface, error) { + for _, ifi := range ift { + if index == ifi.Index { + return &ifi, nil + } + } + return nil, errNoSuchInterface +} + +func ioctl(fd int, req uint, arg unsafe.Pointer) error { + _, _, e1 := syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), uintptr(req), uintptr(arg)) + if e1 != 0 { + return e1 + } + return nil +} + +func indexToName(index uint32) (string, error) { + fd, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_DGRAM|syscall.SOCK_CLOEXEC, 0) + if err != nil { + return "", err + } + defer syscall.Close(fd) + + var ifr ifReq + *(*uint32)(unsafe.Pointer(&ifr[syscall.IFNAMSIZ])) = index + err = ioctl(fd, syscall.SIOCGIFNAME, unsafe.Pointer(&ifr[0])) + if err != nil { + return "", err + } + + return string(bytes.Trim(ifr[:syscall.IFNAMSIZ], "\x00")), nil +} + +func nameToMTU(name string) (int, error) { + // Leave room for terminating NULL byte. + if len(name) >= syscall.IFNAMSIZ { + return -1, syscall.EINVAL + } + + fd, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_DGRAM|syscall.SOCK_CLOEXEC, 0) + if err != nil { + return -1, err + } + defer syscall.Close(fd) + + var ifr ifReq + copy(ifr[:], name) + err = ioctl(fd, syscall.SIOCGIFMTU, unsafe.Pointer(&ifr[0])) + if err != nil { + return -1, err + } + + return int(*(*int32)(unsafe.Pointer(&ifr[syscall.IFNAMSIZ]))), nil +} + +func nameToFlags(name string) (net.Flags, error) { + // Leave room for terminating NULL byte. + if len(name) >= syscall.IFNAMSIZ { + return 0, syscall.EINVAL + } + + fd, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_DGRAM|syscall.SOCK_CLOEXEC, 0) + if err != nil { + return 0, err + } + defer syscall.Close(fd) + + var ifr ifReq + copy(ifr[:], name) + err = ioctl(fd, syscall.SIOCGIFFLAGS, unsafe.Pointer(&ifr[0])) + if err != nil { + return 0, err + } + + return linkFlags(*(*uint32)(unsafe.Pointer(&ifr[syscall.IFNAMSIZ]))), nil +} diff --git a/trunk/3rdparty/srs-bench/vendor/github.com/wlynxg/anet/netlink_android.go b/trunk/3rdparty/srs-bench/vendor/github.com/wlynxg/anet/netlink_android.go new file mode 100644 index 000000000..fc0d84d38 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/github.com/wlynxg/anet/netlink_android.go @@ -0,0 +1,179 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Netlink sockets and messages + +package anet + +import ( + "syscall" + "unsafe" +) + +// Round the length of a netlink message up to align it properly. +func nlmAlignOf(msglen int) int { + return (msglen + syscall.NLMSG_ALIGNTO - 1) & ^(syscall.NLMSG_ALIGNTO - 1) +} + +// Round the length of a netlink route attribute up to align it +// properly. +func rtaAlignOf(attrlen int) int { + return (attrlen + syscall.RTA_ALIGNTO - 1) & ^(syscall.RTA_ALIGNTO - 1) +} + +// NetlinkRouteRequest represents a request message to receive routing +// and link states from the kernel. +type NetlinkRouteRequest struct { + Header syscall.NlMsghdr + Data syscall.RtGenmsg +} + +func (rr *NetlinkRouteRequest) toWireFormat() []byte { + b := make([]byte, rr.Header.Len) + *(*uint32)(unsafe.Pointer(&b[0:4][0])) = rr.Header.Len + *(*uint16)(unsafe.Pointer(&b[4:6][0])) = rr.Header.Type + *(*uint16)(unsafe.Pointer(&b[6:8][0])) = rr.Header.Flags + *(*uint32)(unsafe.Pointer(&b[8:12][0])) = rr.Header.Seq + *(*uint32)(unsafe.Pointer(&b[12:16][0])) = rr.Header.Pid + b[16] = byte(rr.Data.Family) + return b +} + +func newNetlinkRouteRequest(proto, seq, family int) []byte { + rr := &NetlinkRouteRequest{} + rr.Header.Len = uint32(syscall.NLMSG_HDRLEN + syscall.SizeofRtGenmsg) + rr.Header.Type = uint16(proto) + rr.Header.Flags = syscall.NLM_F_DUMP | syscall.NLM_F_REQUEST + rr.Header.Seq = uint32(seq) + rr.Data.Family = uint8(family) + return rr.toWireFormat() +} + +// NetlinkRIB returns routing information base, as known as RIB, which +// consists of network facility information, states and parameters. +func NetlinkRIB(proto, family int) ([]byte, error) { + s, err := syscall.Socket(syscall.AF_NETLINK, syscall.SOCK_RAW|syscall.SOCK_CLOEXEC, syscall.NETLINK_ROUTE) + if err != nil { + return nil, err + } + defer syscall.Close(s) + sa := &syscall.SockaddrNetlink{Family: syscall.AF_NETLINK} + + wb := newNetlinkRouteRequest(proto, 1, family) + if err := syscall.Sendto(s, wb, 0, sa); err != nil { + return nil, err + } + lsa, err := syscall.Getsockname(s) + if err != nil { + return nil, err + } + lsanl, ok := lsa.(*syscall.SockaddrNetlink) + if !ok { + return nil, syscall.EINVAL + } + var tab []byte + rbNew := make([]byte, syscall.Getpagesize()) +done: + for { + rb := rbNew + nr, _, err := syscall.Recvfrom(s, rb, 0) + if err != nil { + return nil, err + } + if nr < syscall.NLMSG_HDRLEN { + return nil, syscall.EINVAL + } + rb = rb[:nr] + tab = append(tab, rb...) + msgs, err := ParseNetlinkMessage(rb) + if err != nil { + return nil, err + } + for _, m := range msgs { + if m.Header.Seq != 1 || m.Header.Pid != lsanl.Pid { + return nil, syscall.EINVAL + } + if m.Header.Type == syscall.NLMSG_DONE { + break done + } + if m.Header.Type == syscall.NLMSG_ERROR { + return nil, syscall.EINVAL + } + } + } + return tab, nil +} + +// NetlinkMessage represents a netlink message. +type NetlinkMessage struct { + Header syscall.NlMsghdr + Data []byte +} + +// ParseNetlinkMessage parses b as an array of netlink messages and +// returns the slice containing the NetlinkMessage structures. +func ParseNetlinkMessage(b []byte) ([]NetlinkMessage, error) { + var msgs []NetlinkMessage + for len(b) >= syscall.NLMSG_HDRLEN { + h, dbuf, dlen, err := netlinkMessageHeaderAndData(b) + if err != nil { + return nil, err + } + m := NetlinkMessage{Header: *h, Data: dbuf[:int(h.Len)-syscall.NLMSG_HDRLEN]} + msgs = append(msgs, m) + b = b[dlen:] + } + return msgs, nil +} + +func netlinkMessageHeaderAndData(b []byte) (*syscall.NlMsghdr, []byte, int, error) { + h := (*syscall.NlMsghdr)(unsafe.Pointer(&b[0])) + l := nlmAlignOf(int(h.Len)) + if int(h.Len) < syscall.NLMSG_HDRLEN || l > len(b) { + return nil, nil, 0, syscall.EINVAL + } + return h, b[syscall.NLMSG_HDRLEN:], l, nil +} + +// NetlinkRouteAttr represents a netlink route attribute. +type NetlinkRouteAttr struct { + Attr syscall.RtAttr + Value []byte +} + +// ParseNetlinkRouteAttr parses m's payload as an array of netlink +// route attributes and returns the slice containing the +// NetlinkRouteAttr structures. +func ParseNetlinkRouteAttr(m *NetlinkMessage) ([]NetlinkRouteAttr, error) { + var b []byte + switch m.Header.Type { + case syscall.RTM_NEWLINK, syscall.RTM_DELLINK: + b = m.Data[syscall.SizeofIfInfomsg:] + case syscall.RTM_NEWADDR, syscall.RTM_DELADDR: + b = m.Data[syscall.SizeofIfAddrmsg:] + case syscall.RTM_NEWROUTE, syscall.RTM_DELROUTE: + b = m.Data[syscall.SizeofRtMsg:] + default: + return nil, syscall.EINVAL + } + var attrs []NetlinkRouteAttr + for len(b) >= syscall.SizeofRtAttr { + a, vbuf, alen, err := netlinkRouteAttrAndValue(b) + if err != nil { + return nil, err + } + ra := NetlinkRouteAttr{Attr: *a, Value: vbuf[:int(a.Len)-syscall.SizeofRtAttr]} + attrs = append(attrs, ra) + b = b[alen:] + } + return attrs, nil +} + +func netlinkRouteAttrAndValue(b []byte) (*syscall.RtAttr, []byte, int, error) { + a := (*syscall.RtAttr)(unsafe.Pointer(&b[0])) + if int(a.Len) < syscall.SizeofRtAttr || int(a.Len) > len(b) { + return nil, nil, 0, syscall.EINVAL + } + return a, b[syscall.SizeofRtAttr:], rtaAlignOf(int(a.Len)), nil +} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/crypto/LICENSE b/trunk/3rdparty/srs-bench/vendor/golang.org/x/crypto/LICENSE index 6a66aea5e..2a7cf70da 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/crypto/LICENSE +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/crypto/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2009 The Go Authors. All rights reserved. +Copyright 2009 The Go Authors. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are @@ -10,7 +10,7 @@ notice, this list of conditions and the following disclaimer. copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - * Neither the name of Google Inc. nor the names of its + * Neither the name of Google LLC nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/crypto/cryptobyte/asn1/asn1.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/crypto/cryptobyte/asn1/asn1.go index cda8e3edf..90ef6a241 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/crypto/cryptobyte/asn1/asn1.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/crypto/cryptobyte/asn1/asn1.go @@ -4,7 +4,7 @@ // Package asn1 contains supporting types for parsing and building ASN.1 // messages with the cryptobyte package. -package asn1 // import "golang.org/x/crypto/cryptobyte/asn1" +package asn1 // Tag represents an ASN.1 identifier octet, consisting of a tag number // (indicating a type) and class (such as context-specific or constructed). diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/crypto/cryptobyte/string.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/crypto/cryptobyte/string.go index 10692a8a3..4b0f8097f 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/crypto/cryptobyte/string.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/crypto/cryptobyte/string.go @@ -15,7 +15,7 @@ // // See the documentation and examples for the Builder and String types to get // started. -package cryptobyte // import "golang.org/x/crypto/cryptobyte" +package cryptobyte // String represents a string of bytes. It provides methods for parsing // fixed-length and length-prefixed values from it. diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/crypto/curve25519/curve25519.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/crypto/curve25519/curve25519.go index 00f963ea2..21ca3b2ee 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/crypto/curve25519/curve25519.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/crypto/curve25519/curve25519.go @@ -6,9 +6,11 @@ // performs scalar multiplication on the elliptic curve known as Curve25519. // See RFC 7748. // -// Starting in Go 1.20, this package is a wrapper for the X25519 implementation +// This package is a wrapper for the X25519 implementation // in the crypto/ecdh package. -package curve25519 // import "golang.org/x/crypto/curve25519" +package curve25519 + +import "crypto/ecdh" // ScalarMult sets dst to the product scalar * point. // @@ -16,7 +18,13 @@ package curve25519 // import "golang.org/x/crypto/curve25519" // zeroes, irrespective of the scalar. Instead, use the X25519 function, which // will return an error. func ScalarMult(dst, scalar, point *[32]byte) { - scalarMult(dst, scalar, point) + if _, err := x25519(dst, scalar[:], point[:]); err != nil { + // The only error condition for x25519 when the inputs are 32 bytes long + // is if the output would have been the all-zero value. + for i := range dst { + dst[i] = 0 + } + } } // ScalarBaseMult sets dst to the product scalar * base where base is the @@ -25,7 +33,12 @@ func ScalarMult(dst, scalar, point *[32]byte) { // It is recommended to use the X25519 function with Basepoint instead, as // copying into fixed size arrays can lead to unexpected bugs. func ScalarBaseMult(dst, scalar *[32]byte) { - scalarBaseMult(dst, scalar) + curve := ecdh.X25519() + priv, err := curve.NewPrivateKey(scalar[:]) + if err != nil { + panic("curve25519: internal error: scalarBaseMult was not 32 bytes") + } + copy(dst[:], priv.PublicKey().Bytes()) } const ( @@ -57,3 +70,21 @@ func X25519(scalar, point []byte) ([]byte, error) { var dst [32]byte return x25519(&dst, scalar, point) } + +func x25519(dst *[32]byte, scalar, point []byte) ([]byte, error) { + curve := ecdh.X25519() + pub, err := curve.NewPublicKey(point) + if err != nil { + return nil, err + } + priv, err := curve.NewPrivateKey(scalar) + if err != nil { + return nil, err + } + out, err := priv.ECDH(pub) + if err != nil { + return nil, err + } + copy(dst[:], out) + return dst[:], nil +} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/crypto/curve25519/curve25519_compat.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/crypto/curve25519/curve25519_compat.go deleted file mode 100644 index ba647e8d7..000000000 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/crypto/curve25519/curve25519_compat.go +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !go1.20 - -package curve25519 - -import ( - "crypto/subtle" - "errors" - "strconv" - - "golang.org/x/crypto/curve25519/internal/field" -) - -func scalarMult(dst, scalar, point *[32]byte) { - var e [32]byte - - copy(e[:], scalar[:]) - e[0] &= 248 - e[31] &= 127 - e[31] |= 64 - - var x1, x2, z2, x3, z3, tmp0, tmp1 field.Element - x1.SetBytes(point[:]) - x2.One() - x3.Set(&x1) - z3.One() - - swap := 0 - for pos := 254; pos >= 0; pos-- { - b := e[pos/8] >> uint(pos&7) - b &= 1 - swap ^= int(b) - x2.Swap(&x3, swap) - z2.Swap(&z3, swap) - swap = int(b) - - tmp0.Subtract(&x3, &z3) - tmp1.Subtract(&x2, &z2) - x2.Add(&x2, &z2) - z2.Add(&x3, &z3) - z3.Multiply(&tmp0, &x2) - z2.Multiply(&z2, &tmp1) - tmp0.Square(&tmp1) - tmp1.Square(&x2) - x3.Add(&z3, &z2) - z2.Subtract(&z3, &z2) - x2.Multiply(&tmp1, &tmp0) - tmp1.Subtract(&tmp1, &tmp0) - z2.Square(&z2) - - z3.Mult32(&tmp1, 121666) - x3.Square(&x3) - tmp0.Add(&tmp0, &z3) - z3.Multiply(&x1, &z2) - z2.Multiply(&tmp1, &tmp0) - } - - x2.Swap(&x3, swap) - z2.Swap(&z3, swap) - - z2.Invert(&z2) - x2.Multiply(&x2, &z2) - copy(dst[:], x2.Bytes()) -} - -func scalarBaseMult(dst, scalar *[32]byte) { - checkBasepoint() - scalarMult(dst, scalar, &basePoint) -} - -func x25519(dst *[32]byte, scalar, point []byte) ([]byte, error) { - var in [32]byte - if l := len(scalar); l != 32 { - return nil, errors.New("bad scalar length: " + strconv.Itoa(l) + ", expected 32") - } - if l := len(point); l != 32 { - return nil, errors.New("bad point length: " + strconv.Itoa(l) + ", expected 32") - } - copy(in[:], scalar) - if &point[0] == &Basepoint[0] { - scalarBaseMult(dst, &in) - } else { - var base, zero [32]byte - copy(base[:], point) - scalarMult(dst, &in, &base) - if subtle.ConstantTimeCompare(dst[:], zero[:]) == 1 { - return nil, errors.New("bad input point: low order point") - } - } - return dst[:], nil -} - -func checkBasepoint() { - if subtle.ConstantTimeCompare(Basepoint, []byte{ - 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }) != 1 { - panic("curve25519: global Basepoint value was modified") - } -} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/crypto/curve25519/curve25519_go120.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/crypto/curve25519/curve25519_go120.go deleted file mode 100644 index 627df4972..000000000 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/crypto/curve25519/curve25519_go120.go +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build go1.20 - -package curve25519 - -import "crypto/ecdh" - -func x25519(dst *[32]byte, scalar, point []byte) ([]byte, error) { - curve := ecdh.X25519() - pub, err := curve.NewPublicKey(point) - if err != nil { - return nil, err - } - priv, err := curve.NewPrivateKey(scalar) - if err != nil { - return nil, err - } - out, err := priv.ECDH(pub) - if err != nil { - return nil, err - } - copy(dst[:], out) - return dst[:], nil -} - -func scalarMult(dst, scalar, point *[32]byte) { - if _, err := x25519(dst, scalar[:], point[:]); err != nil { - // The only error condition for x25519 when the inputs are 32 bytes long - // is if the output would have been the all-zero value. - for i := range dst { - dst[i] = 0 - } - } -} - -func scalarBaseMult(dst, scalar *[32]byte) { - curve := ecdh.X25519() - priv, err := curve.NewPrivateKey(scalar[:]) - if err != nil { - panic("curve25519: internal error: scalarBaseMult was not 32 bytes") - } - copy(dst[:], priv.PublicKey().Bytes()) -} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/crypto/curve25519/internal/field/README b/trunk/3rdparty/srs-bench/vendor/golang.org/x/crypto/curve25519/internal/field/README deleted file mode 100644 index e25bca7dc..000000000 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/crypto/curve25519/internal/field/README +++ /dev/null @@ -1,7 +0,0 @@ -This package is kept in sync with crypto/ed25519/internal/edwards25519/field in -the standard library. - -If there are any changes in the standard library that need to be synced to this -package, run sync.sh. It will not overwrite any local changes made since the -previous sync, so it's ok to land changes in this package first, and then sync -to the standard library later. diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/crypto/curve25519/internal/field/fe.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/crypto/curve25519/internal/field/fe.go deleted file mode 100644 index ca841ad99..000000000 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/crypto/curve25519/internal/field/fe.go +++ /dev/null @@ -1,416 +0,0 @@ -// Copyright (c) 2017 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package field implements fast arithmetic modulo 2^255-19. -package field - -import ( - "crypto/subtle" - "encoding/binary" - "math/bits" -) - -// Element represents an element of the field GF(2^255-19). Note that this -// is not a cryptographically secure group, and should only be used to interact -// with edwards25519.Point coordinates. -// -// This type works similarly to math/big.Int, and all arguments and receivers -// are allowed to alias. -// -// The zero value is a valid zero element. -type Element struct { - // An element t represents the integer - // t.l0 + t.l1*2^51 + t.l2*2^102 + t.l3*2^153 + t.l4*2^204 - // - // Between operations, all limbs are expected to be lower than 2^52. - l0 uint64 - l1 uint64 - l2 uint64 - l3 uint64 - l4 uint64 -} - -const maskLow51Bits uint64 = (1 << 51) - 1 - -var feZero = &Element{0, 0, 0, 0, 0} - -// Zero sets v = 0, and returns v. -func (v *Element) Zero() *Element { - *v = *feZero - return v -} - -var feOne = &Element{1, 0, 0, 0, 0} - -// One sets v = 1, and returns v. -func (v *Element) One() *Element { - *v = *feOne - return v -} - -// reduce reduces v modulo 2^255 - 19 and returns it. -func (v *Element) reduce() *Element { - v.carryPropagate() - - // After the light reduction we now have a field element representation - // v < 2^255 + 2^13 * 19, but need v < 2^255 - 19. - - // If v >= 2^255 - 19, then v + 19 >= 2^255, which would overflow 2^255 - 1, - // generating a carry. That is, c will be 0 if v < 2^255 - 19, and 1 otherwise. - c := (v.l0 + 19) >> 51 - c = (v.l1 + c) >> 51 - c = (v.l2 + c) >> 51 - c = (v.l3 + c) >> 51 - c = (v.l4 + c) >> 51 - - // If v < 2^255 - 19 and c = 0, this will be a no-op. Otherwise, it's - // effectively applying the reduction identity to the carry. - v.l0 += 19 * c - - v.l1 += v.l0 >> 51 - v.l0 = v.l0 & maskLow51Bits - v.l2 += v.l1 >> 51 - v.l1 = v.l1 & maskLow51Bits - v.l3 += v.l2 >> 51 - v.l2 = v.l2 & maskLow51Bits - v.l4 += v.l3 >> 51 - v.l3 = v.l3 & maskLow51Bits - // no additional carry - v.l4 = v.l4 & maskLow51Bits - - return v -} - -// Add sets v = a + b, and returns v. -func (v *Element) Add(a, b *Element) *Element { - v.l0 = a.l0 + b.l0 - v.l1 = a.l1 + b.l1 - v.l2 = a.l2 + b.l2 - v.l3 = a.l3 + b.l3 - v.l4 = a.l4 + b.l4 - // Using the generic implementation here is actually faster than the - // assembly. Probably because the body of this function is so simple that - // the compiler can figure out better optimizations by inlining the carry - // propagation. TODO - return v.carryPropagateGeneric() -} - -// Subtract sets v = a - b, and returns v. -func (v *Element) Subtract(a, b *Element) *Element { - // We first add 2 * p, to guarantee the subtraction won't underflow, and - // then subtract b (which can be up to 2^255 + 2^13 * 19). - v.l0 = (a.l0 + 0xFFFFFFFFFFFDA) - b.l0 - v.l1 = (a.l1 + 0xFFFFFFFFFFFFE) - b.l1 - v.l2 = (a.l2 + 0xFFFFFFFFFFFFE) - b.l2 - v.l3 = (a.l3 + 0xFFFFFFFFFFFFE) - b.l3 - v.l4 = (a.l4 + 0xFFFFFFFFFFFFE) - b.l4 - return v.carryPropagate() -} - -// Negate sets v = -a, and returns v. -func (v *Element) Negate(a *Element) *Element { - return v.Subtract(feZero, a) -} - -// Invert sets v = 1/z mod p, and returns v. -// -// If z == 0, Invert returns v = 0. -func (v *Element) Invert(z *Element) *Element { - // Inversion is implemented as exponentiation with exponent p − 2. It uses the - // same sequence of 255 squarings and 11 multiplications as [Curve25519]. - var z2, z9, z11, z2_5_0, z2_10_0, z2_20_0, z2_50_0, z2_100_0, t Element - - z2.Square(z) // 2 - t.Square(&z2) // 4 - t.Square(&t) // 8 - z9.Multiply(&t, z) // 9 - z11.Multiply(&z9, &z2) // 11 - t.Square(&z11) // 22 - z2_5_0.Multiply(&t, &z9) // 31 = 2^5 - 2^0 - - t.Square(&z2_5_0) // 2^6 - 2^1 - for i := 0; i < 4; i++ { - t.Square(&t) // 2^10 - 2^5 - } - z2_10_0.Multiply(&t, &z2_5_0) // 2^10 - 2^0 - - t.Square(&z2_10_0) // 2^11 - 2^1 - for i := 0; i < 9; i++ { - t.Square(&t) // 2^20 - 2^10 - } - z2_20_0.Multiply(&t, &z2_10_0) // 2^20 - 2^0 - - t.Square(&z2_20_0) // 2^21 - 2^1 - for i := 0; i < 19; i++ { - t.Square(&t) // 2^40 - 2^20 - } - t.Multiply(&t, &z2_20_0) // 2^40 - 2^0 - - t.Square(&t) // 2^41 - 2^1 - for i := 0; i < 9; i++ { - t.Square(&t) // 2^50 - 2^10 - } - z2_50_0.Multiply(&t, &z2_10_0) // 2^50 - 2^0 - - t.Square(&z2_50_0) // 2^51 - 2^1 - for i := 0; i < 49; i++ { - t.Square(&t) // 2^100 - 2^50 - } - z2_100_0.Multiply(&t, &z2_50_0) // 2^100 - 2^0 - - t.Square(&z2_100_0) // 2^101 - 2^1 - for i := 0; i < 99; i++ { - t.Square(&t) // 2^200 - 2^100 - } - t.Multiply(&t, &z2_100_0) // 2^200 - 2^0 - - t.Square(&t) // 2^201 - 2^1 - for i := 0; i < 49; i++ { - t.Square(&t) // 2^250 - 2^50 - } - t.Multiply(&t, &z2_50_0) // 2^250 - 2^0 - - t.Square(&t) // 2^251 - 2^1 - t.Square(&t) // 2^252 - 2^2 - t.Square(&t) // 2^253 - 2^3 - t.Square(&t) // 2^254 - 2^4 - t.Square(&t) // 2^255 - 2^5 - - return v.Multiply(&t, &z11) // 2^255 - 21 -} - -// Set sets v = a, and returns v. -func (v *Element) Set(a *Element) *Element { - *v = *a - return v -} - -// SetBytes sets v to x, which must be a 32-byte little-endian encoding. -// -// Consistent with RFC 7748, the most significant bit (the high bit of the -// last byte) is ignored, and non-canonical values (2^255-19 through 2^255-1) -// are accepted. Note that this is laxer than specified by RFC 8032. -func (v *Element) SetBytes(x []byte) *Element { - if len(x) != 32 { - panic("edwards25519: invalid field element input size") - } - - // Bits 0:51 (bytes 0:8, bits 0:64, shift 0, mask 51). - v.l0 = binary.LittleEndian.Uint64(x[0:8]) - v.l0 &= maskLow51Bits - // Bits 51:102 (bytes 6:14, bits 48:112, shift 3, mask 51). - v.l1 = binary.LittleEndian.Uint64(x[6:14]) >> 3 - v.l1 &= maskLow51Bits - // Bits 102:153 (bytes 12:20, bits 96:160, shift 6, mask 51). - v.l2 = binary.LittleEndian.Uint64(x[12:20]) >> 6 - v.l2 &= maskLow51Bits - // Bits 153:204 (bytes 19:27, bits 152:216, shift 1, mask 51). - v.l3 = binary.LittleEndian.Uint64(x[19:27]) >> 1 - v.l3 &= maskLow51Bits - // Bits 204:251 (bytes 24:32, bits 192:256, shift 12, mask 51). - // Note: not bytes 25:33, shift 4, to avoid overread. - v.l4 = binary.LittleEndian.Uint64(x[24:32]) >> 12 - v.l4 &= maskLow51Bits - - return v -} - -// Bytes returns the canonical 32-byte little-endian encoding of v. -func (v *Element) Bytes() []byte { - // This function is outlined to make the allocations inline in the caller - // rather than happen on the heap. - var out [32]byte - return v.bytes(&out) -} - -func (v *Element) bytes(out *[32]byte) []byte { - t := *v - t.reduce() - - var buf [8]byte - for i, l := range [5]uint64{t.l0, t.l1, t.l2, t.l3, t.l4} { - bitsOffset := i * 51 - binary.LittleEndian.PutUint64(buf[:], l<= len(out) { - break - } - out[off] |= bb - } - } - - return out[:] -} - -// Equal returns 1 if v and u are equal, and 0 otherwise. -func (v *Element) Equal(u *Element) int { - sa, sv := u.Bytes(), v.Bytes() - return subtle.ConstantTimeCompare(sa, sv) -} - -// mask64Bits returns 0xffffffff if cond is 1, and 0 otherwise. -func mask64Bits(cond int) uint64 { return ^(uint64(cond) - 1) } - -// Select sets v to a if cond == 1, and to b if cond == 0. -func (v *Element) Select(a, b *Element, cond int) *Element { - m := mask64Bits(cond) - v.l0 = (m & a.l0) | (^m & b.l0) - v.l1 = (m & a.l1) | (^m & b.l1) - v.l2 = (m & a.l2) | (^m & b.l2) - v.l3 = (m & a.l3) | (^m & b.l3) - v.l4 = (m & a.l4) | (^m & b.l4) - return v -} - -// Swap swaps v and u if cond == 1 or leaves them unchanged if cond == 0, and returns v. -func (v *Element) Swap(u *Element, cond int) { - m := mask64Bits(cond) - t := m & (v.l0 ^ u.l0) - v.l0 ^= t - u.l0 ^= t - t = m & (v.l1 ^ u.l1) - v.l1 ^= t - u.l1 ^= t - t = m & (v.l2 ^ u.l2) - v.l2 ^= t - u.l2 ^= t - t = m & (v.l3 ^ u.l3) - v.l3 ^= t - u.l3 ^= t - t = m & (v.l4 ^ u.l4) - v.l4 ^= t - u.l4 ^= t -} - -// IsNegative returns 1 if v is negative, and 0 otherwise. -func (v *Element) IsNegative() int { - return int(v.Bytes()[0] & 1) -} - -// Absolute sets v to |u|, and returns v. -func (v *Element) Absolute(u *Element) *Element { - return v.Select(new(Element).Negate(u), u, u.IsNegative()) -} - -// Multiply sets v = x * y, and returns v. -func (v *Element) Multiply(x, y *Element) *Element { - feMul(v, x, y) - return v -} - -// Square sets v = x * x, and returns v. -func (v *Element) Square(x *Element) *Element { - feSquare(v, x) - return v -} - -// Mult32 sets v = x * y, and returns v. -func (v *Element) Mult32(x *Element, y uint32) *Element { - x0lo, x0hi := mul51(x.l0, y) - x1lo, x1hi := mul51(x.l1, y) - x2lo, x2hi := mul51(x.l2, y) - x3lo, x3hi := mul51(x.l3, y) - x4lo, x4hi := mul51(x.l4, y) - v.l0 = x0lo + 19*x4hi // carried over per the reduction identity - v.l1 = x1lo + x0hi - v.l2 = x2lo + x1hi - v.l3 = x3lo + x2hi - v.l4 = x4lo + x3hi - // The hi portions are going to be only 32 bits, plus any previous excess, - // so we can skip the carry propagation. - return v -} - -// mul51 returns lo + hi * 2⁵¹ = a * b. -func mul51(a uint64, b uint32) (lo uint64, hi uint64) { - mh, ml := bits.Mul64(a, uint64(b)) - lo = ml & maskLow51Bits - hi = (mh << 13) | (ml >> 51) - return -} - -// Pow22523 set v = x^((p-5)/8), and returns v. (p-5)/8 is 2^252-3. -func (v *Element) Pow22523(x *Element) *Element { - var t0, t1, t2 Element - - t0.Square(x) // x^2 - t1.Square(&t0) // x^4 - t1.Square(&t1) // x^8 - t1.Multiply(x, &t1) // x^9 - t0.Multiply(&t0, &t1) // x^11 - t0.Square(&t0) // x^22 - t0.Multiply(&t1, &t0) // x^31 - t1.Square(&t0) // x^62 - for i := 1; i < 5; i++ { // x^992 - t1.Square(&t1) - } - t0.Multiply(&t1, &t0) // x^1023 -> 1023 = 2^10 - 1 - t1.Square(&t0) // 2^11 - 2 - for i := 1; i < 10; i++ { // 2^20 - 2^10 - t1.Square(&t1) - } - t1.Multiply(&t1, &t0) // 2^20 - 1 - t2.Square(&t1) // 2^21 - 2 - for i := 1; i < 20; i++ { // 2^40 - 2^20 - t2.Square(&t2) - } - t1.Multiply(&t2, &t1) // 2^40 - 1 - t1.Square(&t1) // 2^41 - 2 - for i := 1; i < 10; i++ { // 2^50 - 2^10 - t1.Square(&t1) - } - t0.Multiply(&t1, &t0) // 2^50 - 1 - t1.Square(&t0) // 2^51 - 2 - for i := 1; i < 50; i++ { // 2^100 - 2^50 - t1.Square(&t1) - } - t1.Multiply(&t1, &t0) // 2^100 - 1 - t2.Square(&t1) // 2^101 - 2 - for i := 1; i < 100; i++ { // 2^200 - 2^100 - t2.Square(&t2) - } - t1.Multiply(&t2, &t1) // 2^200 - 1 - t1.Square(&t1) // 2^201 - 2 - for i := 1; i < 50; i++ { // 2^250 - 2^50 - t1.Square(&t1) - } - t0.Multiply(&t1, &t0) // 2^250 - 1 - t0.Square(&t0) // 2^251 - 2 - t0.Square(&t0) // 2^252 - 4 - return v.Multiply(&t0, x) // 2^252 - 3 -> x^(2^252-3) -} - -// sqrtM1 is 2^((p-1)/4), which squared is equal to -1 by Euler's Criterion. -var sqrtM1 = &Element{1718705420411056, 234908883556509, - 2233514472574048, 2117202627021982, 765476049583133} - -// SqrtRatio sets r to the non-negative square root of the ratio of u and v. -// -// If u/v is square, SqrtRatio returns r and 1. If u/v is not square, SqrtRatio -// sets r according to Section 4.3 of draft-irtf-cfrg-ristretto255-decaf448-00, -// and returns r and 0. -func (r *Element) SqrtRatio(u, v *Element) (rr *Element, wasSquare int) { - var a, b Element - - // r = (u * v3) * (u * v7)^((p-5)/8) - v2 := a.Square(v) - uv3 := b.Multiply(u, b.Multiply(v2, v)) - uv7 := a.Multiply(uv3, a.Square(v2)) - r.Multiply(uv3, r.Pow22523(uv7)) - - check := a.Multiply(v, a.Square(r)) // check = v * r^2 - - uNeg := b.Negate(u) - correctSignSqrt := check.Equal(u) - flippedSignSqrt := check.Equal(uNeg) - flippedSignSqrtI := check.Equal(uNeg.Multiply(uNeg, sqrtM1)) - - rPrime := b.Multiply(r, sqrtM1) // r_prime = SQRT_M1 * r - // r = CT_SELECT(r_prime IF flipped_sign_sqrt | flipped_sign_sqrt_i ELSE r) - r.Select(rPrime, r, flippedSignSqrt|flippedSignSqrtI) - - r.Absolute(r) // Choose the nonnegative square root. - return r, correctSignSqrt | flippedSignSqrt -} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/crypto/curve25519/internal/field/fe_amd64.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/crypto/curve25519/internal/field/fe_amd64.go deleted file mode 100644 index 70c541692..000000000 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/crypto/curve25519/internal/field/fe_amd64.go +++ /dev/null @@ -1,15 +0,0 @@ -// Code generated by command: go run fe_amd64_asm.go -out ../fe_amd64.s -stubs ../fe_amd64.go -pkg field. DO NOT EDIT. - -//go:build amd64 && gc && !purego - -package field - -// feMul sets out = a * b. It works like feMulGeneric. -// -//go:noescape -func feMul(out *Element, a *Element, b *Element) - -// feSquare sets out = a * a. It works like feSquareGeneric. -// -//go:noescape -func feSquare(out *Element, a *Element) diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/crypto/curve25519/internal/field/fe_amd64.s b/trunk/3rdparty/srs-bench/vendor/golang.org/x/crypto/curve25519/internal/field/fe_amd64.s deleted file mode 100644 index 60817acc4..000000000 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/crypto/curve25519/internal/field/fe_amd64.s +++ /dev/null @@ -1,378 +0,0 @@ -// Code generated by command: go run fe_amd64_asm.go -out ../fe_amd64.s -stubs ../fe_amd64.go -pkg field. DO NOT EDIT. - -//go:build amd64 && gc && !purego - -#include "textflag.h" - -// func feMul(out *Element, a *Element, b *Element) -TEXT ·feMul(SB), NOSPLIT, $0-24 - MOVQ a+8(FP), CX - MOVQ b+16(FP), BX - - // r0 = a0×b0 - MOVQ (CX), AX - MULQ (BX) - MOVQ AX, DI - MOVQ DX, SI - - // r0 += 19×a1×b4 - MOVQ 8(CX), AX - IMUL3Q $0x13, AX, AX - MULQ 32(BX) - ADDQ AX, DI - ADCQ DX, SI - - // r0 += 19×a2×b3 - MOVQ 16(CX), AX - IMUL3Q $0x13, AX, AX - MULQ 24(BX) - ADDQ AX, DI - ADCQ DX, SI - - // r0 += 19×a3×b2 - MOVQ 24(CX), AX - IMUL3Q $0x13, AX, AX - MULQ 16(BX) - ADDQ AX, DI - ADCQ DX, SI - - // r0 += 19×a4×b1 - MOVQ 32(CX), AX - IMUL3Q $0x13, AX, AX - MULQ 8(BX) - ADDQ AX, DI - ADCQ DX, SI - - // r1 = a0×b1 - MOVQ (CX), AX - MULQ 8(BX) - MOVQ AX, R9 - MOVQ DX, R8 - - // r1 += a1×b0 - MOVQ 8(CX), AX - MULQ (BX) - ADDQ AX, R9 - ADCQ DX, R8 - - // r1 += 19×a2×b4 - MOVQ 16(CX), AX - IMUL3Q $0x13, AX, AX - MULQ 32(BX) - ADDQ AX, R9 - ADCQ DX, R8 - - // r1 += 19×a3×b3 - MOVQ 24(CX), AX - IMUL3Q $0x13, AX, AX - MULQ 24(BX) - ADDQ AX, R9 - ADCQ DX, R8 - - // r1 += 19×a4×b2 - MOVQ 32(CX), AX - IMUL3Q $0x13, AX, AX - MULQ 16(BX) - ADDQ AX, R9 - ADCQ DX, R8 - - // r2 = a0×b2 - MOVQ (CX), AX - MULQ 16(BX) - MOVQ AX, R11 - MOVQ DX, R10 - - // r2 += a1×b1 - MOVQ 8(CX), AX - MULQ 8(BX) - ADDQ AX, R11 - ADCQ DX, R10 - - // r2 += a2×b0 - MOVQ 16(CX), AX - MULQ (BX) - ADDQ AX, R11 - ADCQ DX, R10 - - // r2 += 19×a3×b4 - MOVQ 24(CX), AX - IMUL3Q $0x13, AX, AX - MULQ 32(BX) - ADDQ AX, R11 - ADCQ DX, R10 - - // r2 += 19×a4×b3 - MOVQ 32(CX), AX - IMUL3Q $0x13, AX, AX - MULQ 24(BX) - ADDQ AX, R11 - ADCQ DX, R10 - - // r3 = a0×b3 - MOVQ (CX), AX - MULQ 24(BX) - MOVQ AX, R13 - MOVQ DX, R12 - - // r3 += a1×b2 - MOVQ 8(CX), AX - MULQ 16(BX) - ADDQ AX, R13 - ADCQ DX, R12 - - // r3 += a2×b1 - MOVQ 16(CX), AX - MULQ 8(BX) - ADDQ AX, R13 - ADCQ DX, R12 - - // r3 += a3×b0 - MOVQ 24(CX), AX - MULQ (BX) - ADDQ AX, R13 - ADCQ DX, R12 - - // r3 += 19×a4×b4 - MOVQ 32(CX), AX - IMUL3Q $0x13, AX, AX - MULQ 32(BX) - ADDQ AX, R13 - ADCQ DX, R12 - - // r4 = a0×b4 - MOVQ (CX), AX - MULQ 32(BX) - MOVQ AX, R15 - MOVQ DX, R14 - - // r4 += a1×b3 - MOVQ 8(CX), AX - MULQ 24(BX) - ADDQ AX, R15 - ADCQ DX, R14 - - // r4 += a2×b2 - MOVQ 16(CX), AX - MULQ 16(BX) - ADDQ AX, R15 - ADCQ DX, R14 - - // r4 += a3×b1 - MOVQ 24(CX), AX - MULQ 8(BX) - ADDQ AX, R15 - ADCQ DX, R14 - - // r4 += a4×b0 - MOVQ 32(CX), AX - MULQ (BX) - ADDQ AX, R15 - ADCQ DX, R14 - - // First reduction chain - MOVQ $0x0007ffffffffffff, AX - SHLQ $0x0d, DI, SI - SHLQ $0x0d, R9, R8 - SHLQ $0x0d, R11, R10 - SHLQ $0x0d, R13, R12 - SHLQ $0x0d, R15, R14 - ANDQ AX, DI - IMUL3Q $0x13, R14, R14 - ADDQ R14, DI - ANDQ AX, R9 - ADDQ SI, R9 - ANDQ AX, R11 - ADDQ R8, R11 - ANDQ AX, R13 - ADDQ R10, R13 - ANDQ AX, R15 - ADDQ R12, R15 - - // Second reduction chain (carryPropagate) - MOVQ DI, SI - SHRQ $0x33, SI - MOVQ R9, R8 - SHRQ $0x33, R8 - MOVQ R11, R10 - SHRQ $0x33, R10 - MOVQ R13, R12 - SHRQ $0x33, R12 - MOVQ R15, R14 - SHRQ $0x33, R14 - ANDQ AX, DI - IMUL3Q $0x13, R14, R14 - ADDQ R14, DI - ANDQ AX, R9 - ADDQ SI, R9 - ANDQ AX, R11 - ADDQ R8, R11 - ANDQ AX, R13 - ADDQ R10, R13 - ANDQ AX, R15 - ADDQ R12, R15 - - // Store output - MOVQ out+0(FP), AX - MOVQ DI, (AX) - MOVQ R9, 8(AX) - MOVQ R11, 16(AX) - MOVQ R13, 24(AX) - MOVQ R15, 32(AX) - RET - -// func feSquare(out *Element, a *Element) -TEXT ·feSquare(SB), NOSPLIT, $0-16 - MOVQ a+8(FP), CX - - // r0 = l0×l0 - MOVQ (CX), AX - MULQ (CX) - MOVQ AX, SI - MOVQ DX, BX - - // r0 += 38×l1×l4 - MOVQ 8(CX), AX - IMUL3Q $0x26, AX, AX - MULQ 32(CX) - ADDQ AX, SI - ADCQ DX, BX - - // r0 += 38×l2×l3 - MOVQ 16(CX), AX - IMUL3Q $0x26, AX, AX - MULQ 24(CX) - ADDQ AX, SI - ADCQ DX, BX - - // r1 = 2×l0×l1 - MOVQ (CX), AX - SHLQ $0x01, AX - MULQ 8(CX) - MOVQ AX, R8 - MOVQ DX, DI - - // r1 += 38×l2×l4 - MOVQ 16(CX), AX - IMUL3Q $0x26, AX, AX - MULQ 32(CX) - ADDQ AX, R8 - ADCQ DX, DI - - // r1 += 19×l3×l3 - MOVQ 24(CX), AX - IMUL3Q $0x13, AX, AX - MULQ 24(CX) - ADDQ AX, R8 - ADCQ DX, DI - - // r2 = 2×l0×l2 - MOVQ (CX), AX - SHLQ $0x01, AX - MULQ 16(CX) - MOVQ AX, R10 - MOVQ DX, R9 - - // r2 += l1×l1 - MOVQ 8(CX), AX - MULQ 8(CX) - ADDQ AX, R10 - ADCQ DX, R9 - - // r2 += 38×l3×l4 - MOVQ 24(CX), AX - IMUL3Q $0x26, AX, AX - MULQ 32(CX) - ADDQ AX, R10 - ADCQ DX, R9 - - // r3 = 2×l0×l3 - MOVQ (CX), AX - SHLQ $0x01, AX - MULQ 24(CX) - MOVQ AX, R12 - MOVQ DX, R11 - - // r3 += 2×l1×l2 - MOVQ 8(CX), AX - IMUL3Q $0x02, AX, AX - MULQ 16(CX) - ADDQ AX, R12 - ADCQ DX, R11 - - // r3 += 19×l4×l4 - MOVQ 32(CX), AX - IMUL3Q $0x13, AX, AX - MULQ 32(CX) - ADDQ AX, R12 - ADCQ DX, R11 - - // r4 = 2×l0×l4 - MOVQ (CX), AX - SHLQ $0x01, AX - MULQ 32(CX) - MOVQ AX, R14 - MOVQ DX, R13 - - // r4 += 2×l1×l3 - MOVQ 8(CX), AX - IMUL3Q $0x02, AX, AX - MULQ 24(CX) - ADDQ AX, R14 - ADCQ DX, R13 - - // r4 += l2×l2 - MOVQ 16(CX), AX - MULQ 16(CX) - ADDQ AX, R14 - ADCQ DX, R13 - - // First reduction chain - MOVQ $0x0007ffffffffffff, AX - SHLQ $0x0d, SI, BX - SHLQ $0x0d, R8, DI - SHLQ $0x0d, R10, R9 - SHLQ $0x0d, R12, R11 - SHLQ $0x0d, R14, R13 - ANDQ AX, SI - IMUL3Q $0x13, R13, R13 - ADDQ R13, SI - ANDQ AX, R8 - ADDQ BX, R8 - ANDQ AX, R10 - ADDQ DI, R10 - ANDQ AX, R12 - ADDQ R9, R12 - ANDQ AX, R14 - ADDQ R11, R14 - - // Second reduction chain (carryPropagate) - MOVQ SI, BX - SHRQ $0x33, BX - MOVQ R8, DI - SHRQ $0x33, DI - MOVQ R10, R9 - SHRQ $0x33, R9 - MOVQ R12, R11 - SHRQ $0x33, R11 - MOVQ R14, R13 - SHRQ $0x33, R13 - ANDQ AX, SI - IMUL3Q $0x13, R13, R13 - ADDQ R13, SI - ANDQ AX, R8 - ADDQ BX, R8 - ANDQ AX, R10 - ADDQ DI, R10 - ANDQ AX, R12 - ADDQ R9, R12 - ANDQ AX, R14 - ADDQ R11, R14 - - // Store output - MOVQ out+0(FP), AX - MOVQ SI, (AX) - MOVQ R8, 8(AX) - MOVQ R10, 16(AX) - MOVQ R12, 24(AX) - MOVQ R14, 32(AX) - RET diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/crypto/curve25519/internal/field/fe_amd64_noasm.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/crypto/curve25519/internal/field/fe_amd64_noasm.go deleted file mode 100644 index 9da280d1d..000000000 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/crypto/curve25519/internal/field/fe_amd64_noasm.go +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright (c) 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !amd64 || !gc || purego - -package field - -func feMul(v, x, y *Element) { feMulGeneric(v, x, y) } - -func feSquare(v, x *Element) { feSquareGeneric(v, x) } diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/crypto/curve25519/internal/field/fe_arm64.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/crypto/curve25519/internal/field/fe_arm64.go deleted file mode 100644 index 075fe9b92..000000000 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/crypto/curve25519/internal/field/fe_arm64.go +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) 2020 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build arm64 && gc && !purego - -package field - -//go:noescape -func carryPropagate(v *Element) - -func (v *Element) carryPropagate() *Element { - carryPropagate(v) - return v -} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/crypto/curve25519/internal/field/fe_arm64.s b/trunk/3rdparty/srs-bench/vendor/golang.org/x/crypto/curve25519/internal/field/fe_arm64.s deleted file mode 100644 index 3126a4341..000000000 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/crypto/curve25519/internal/field/fe_arm64.s +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright (c) 2020 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build arm64 && gc && !purego - -#include "textflag.h" - -// carryPropagate works exactly like carryPropagateGeneric and uses the -// same AND, ADD, and LSR+MADD instructions emitted by the compiler, but -// avoids loading R0-R4 twice and uses LDP and STP. -// -// See https://golang.org/issues/43145 for the main compiler issue. -// -// func carryPropagate(v *Element) -TEXT ·carryPropagate(SB),NOFRAME|NOSPLIT,$0-8 - MOVD v+0(FP), R20 - - LDP 0(R20), (R0, R1) - LDP 16(R20), (R2, R3) - MOVD 32(R20), R4 - - AND $0x7ffffffffffff, R0, R10 - AND $0x7ffffffffffff, R1, R11 - AND $0x7ffffffffffff, R2, R12 - AND $0x7ffffffffffff, R3, R13 - AND $0x7ffffffffffff, R4, R14 - - ADD R0>>51, R11, R11 - ADD R1>>51, R12, R12 - ADD R2>>51, R13, R13 - ADD R3>>51, R14, R14 - // R4>>51 * 19 + R10 -> R10 - LSR $51, R4, R21 - MOVD $19, R22 - MADD R22, R10, R21, R10 - - STP (R10, R11), 0(R20) - STP (R12, R13), 16(R20) - MOVD R14, 32(R20) - - RET diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/crypto/curve25519/internal/field/fe_arm64_noasm.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/crypto/curve25519/internal/field/fe_arm64_noasm.go deleted file mode 100644 index fc029ac12..000000000 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/crypto/curve25519/internal/field/fe_arm64_noasm.go +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright (c) 2021 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !arm64 || !gc || purego - -package field - -func (v *Element) carryPropagate() *Element { - return v.carryPropagateGeneric() -} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/crypto/curve25519/internal/field/fe_generic.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/crypto/curve25519/internal/field/fe_generic.go deleted file mode 100644 index 2671217da..000000000 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/crypto/curve25519/internal/field/fe_generic.go +++ /dev/null @@ -1,264 +0,0 @@ -// Copyright (c) 2017 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package field - -import "math/bits" - -// uint128 holds a 128-bit number as two 64-bit limbs, for use with the -// bits.Mul64 and bits.Add64 intrinsics. -type uint128 struct { - lo, hi uint64 -} - -// mul64 returns a * b. -func mul64(a, b uint64) uint128 { - hi, lo := bits.Mul64(a, b) - return uint128{lo, hi} -} - -// addMul64 returns v + a * b. -func addMul64(v uint128, a, b uint64) uint128 { - hi, lo := bits.Mul64(a, b) - lo, c := bits.Add64(lo, v.lo, 0) - hi, _ = bits.Add64(hi, v.hi, c) - return uint128{lo, hi} -} - -// shiftRightBy51 returns a >> 51. a is assumed to be at most 115 bits. -func shiftRightBy51(a uint128) uint64 { - return (a.hi << (64 - 51)) | (a.lo >> 51) -} - -func feMulGeneric(v, a, b *Element) { - a0 := a.l0 - a1 := a.l1 - a2 := a.l2 - a3 := a.l3 - a4 := a.l4 - - b0 := b.l0 - b1 := b.l1 - b2 := b.l2 - b3 := b.l3 - b4 := b.l4 - - // Limb multiplication works like pen-and-paper columnar multiplication, but - // with 51-bit limbs instead of digits. - // - // a4 a3 a2 a1 a0 x - // b4 b3 b2 b1 b0 = - // ------------------------ - // a4b0 a3b0 a2b0 a1b0 a0b0 + - // a4b1 a3b1 a2b1 a1b1 a0b1 + - // a4b2 a3b2 a2b2 a1b2 a0b2 + - // a4b3 a3b3 a2b3 a1b3 a0b3 + - // a4b4 a3b4 a2b4 a1b4 a0b4 = - // ---------------------------------------------- - // r8 r7 r6 r5 r4 r3 r2 r1 r0 - // - // We can then use the reduction identity (a * 2²⁵⁵ + b = a * 19 + b) to - // reduce the limbs that would overflow 255 bits. r5 * 2²⁵⁵ becomes 19 * r5, - // r6 * 2³⁰⁶ becomes 19 * r6 * 2⁵¹, etc. - // - // Reduction can be carried out simultaneously to multiplication. For - // example, we do not compute r5: whenever the result of a multiplication - // belongs to r5, like a1b4, we multiply it by 19 and add the result to r0. - // - // a4b0 a3b0 a2b0 a1b0 a0b0 + - // a3b1 a2b1 a1b1 a0b1 19×a4b1 + - // a2b2 a1b2 a0b2 19×a4b2 19×a3b2 + - // a1b3 a0b3 19×a4b3 19×a3b3 19×a2b3 + - // a0b4 19×a4b4 19×a3b4 19×a2b4 19×a1b4 = - // -------------------------------------- - // r4 r3 r2 r1 r0 - // - // Finally we add up the columns into wide, overlapping limbs. - - a1_19 := a1 * 19 - a2_19 := a2 * 19 - a3_19 := a3 * 19 - a4_19 := a4 * 19 - - // r0 = a0×b0 + 19×(a1×b4 + a2×b3 + a3×b2 + a4×b1) - r0 := mul64(a0, b0) - r0 = addMul64(r0, a1_19, b4) - r0 = addMul64(r0, a2_19, b3) - r0 = addMul64(r0, a3_19, b2) - r0 = addMul64(r0, a4_19, b1) - - // r1 = a0×b1 + a1×b0 + 19×(a2×b4 + a3×b3 + a4×b2) - r1 := mul64(a0, b1) - r1 = addMul64(r1, a1, b0) - r1 = addMul64(r1, a2_19, b4) - r1 = addMul64(r1, a3_19, b3) - r1 = addMul64(r1, a4_19, b2) - - // r2 = a0×b2 + a1×b1 + a2×b0 + 19×(a3×b4 + a4×b3) - r2 := mul64(a0, b2) - r2 = addMul64(r2, a1, b1) - r2 = addMul64(r2, a2, b0) - r2 = addMul64(r2, a3_19, b4) - r2 = addMul64(r2, a4_19, b3) - - // r3 = a0×b3 + a1×b2 + a2×b1 + a3×b0 + 19×a4×b4 - r3 := mul64(a0, b3) - r3 = addMul64(r3, a1, b2) - r3 = addMul64(r3, a2, b1) - r3 = addMul64(r3, a3, b0) - r3 = addMul64(r3, a4_19, b4) - - // r4 = a0×b4 + a1×b3 + a2×b2 + a3×b1 + a4×b0 - r4 := mul64(a0, b4) - r4 = addMul64(r4, a1, b3) - r4 = addMul64(r4, a2, b2) - r4 = addMul64(r4, a3, b1) - r4 = addMul64(r4, a4, b0) - - // After the multiplication, we need to reduce (carry) the five coefficients - // to obtain a result with limbs that are at most slightly larger than 2⁵¹, - // to respect the Element invariant. - // - // Overall, the reduction works the same as carryPropagate, except with - // wider inputs: we take the carry for each coefficient by shifting it right - // by 51, and add it to the limb above it. The top carry is multiplied by 19 - // according to the reduction identity and added to the lowest limb. - // - // The largest coefficient (r0) will be at most 111 bits, which guarantees - // that all carries are at most 111 - 51 = 60 bits, which fits in a uint64. - // - // r0 = a0×b0 + 19×(a1×b4 + a2×b3 + a3×b2 + a4×b1) - // r0 < 2⁵²×2⁵² + 19×(2⁵²×2⁵² + 2⁵²×2⁵² + 2⁵²×2⁵² + 2⁵²×2⁵²) - // r0 < (1 + 19 × 4) × 2⁵² × 2⁵² - // r0 < 2⁷ × 2⁵² × 2⁵² - // r0 < 2¹¹¹ - // - // Moreover, the top coefficient (r4) is at most 107 bits, so c4 is at most - // 56 bits, and c4 * 19 is at most 61 bits, which again fits in a uint64 and - // allows us to easily apply the reduction identity. - // - // r4 = a0×b4 + a1×b3 + a2×b2 + a3×b1 + a4×b0 - // r4 < 5 × 2⁵² × 2⁵² - // r4 < 2¹⁰⁷ - // - - c0 := shiftRightBy51(r0) - c1 := shiftRightBy51(r1) - c2 := shiftRightBy51(r2) - c3 := shiftRightBy51(r3) - c4 := shiftRightBy51(r4) - - rr0 := r0.lo&maskLow51Bits + c4*19 - rr1 := r1.lo&maskLow51Bits + c0 - rr2 := r2.lo&maskLow51Bits + c1 - rr3 := r3.lo&maskLow51Bits + c2 - rr4 := r4.lo&maskLow51Bits + c3 - - // Now all coefficients fit into 64-bit registers but are still too large to - // be passed around as a Element. We therefore do one last carry chain, - // where the carries will be small enough to fit in the wiggle room above 2⁵¹. - *v = Element{rr0, rr1, rr2, rr3, rr4} - v.carryPropagate() -} - -func feSquareGeneric(v, a *Element) { - l0 := a.l0 - l1 := a.l1 - l2 := a.l2 - l3 := a.l3 - l4 := a.l4 - - // Squaring works precisely like multiplication above, but thanks to its - // symmetry we get to group a few terms together. - // - // l4 l3 l2 l1 l0 x - // l4 l3 l2 l1 l0 = - // ------------------------ - // l4l0 l3l0 l2l0 l1l0 l0l0 + - // l4l1 l3l1 l2l1 l1l1 l0l1 + - // l4l2 l3l2 l2l2 l1l2 l0l2 + - // l4l3 l3l3 l2l3 l1l3 l0l3 + - // l4l4 l3l4 l2l4 l1l4 l0l4 = - // ---------------------------------------------- - // r8 r7 r6 r5 r4 r3 r2 r1 r0 - // - // l4l0 l3l0 l2l0 l1l0 l0l0 + - // l3l1 l2l1 l1l1 l0l1 19×l4l1 + - // l2l2 l1l2 l0l2 19×l4l2 19×l3l2 + - // l1l3 l0l3 19×l4l3 19×l3l3 19×l2l3 + - // l0l4 19×l4l4 19×l3l4 19×l2l4 19×l1l4 = - // -------------------------------------- - // r4 r3 r2 r1 r0 - // - // With precomputed 2×, 19×, and 2×19× terms, we can compute each limb with - // only three Mul64 and four Add64, instead of five and eight. - - l0_2 := l0 * 2 - l1_2 := l1 * 2 - - l1_38 := l1 * 38 - l2_38 := l2 * 38 - l3_38 := l3 * 38 - - l3_19 := l3 * 19 - l4_19 := l4 * 19 - - // r0 = l0×l0 + 19×(l1×l4 + l2×l3 + l3×l2 + l4×l1) = l0×l0 + 19×2×(l1×l4 + l2×l3) - r0 := mul64(l0, l0) - r0 = addMul64(r0, l1_38, l4) - r0 = addMul64(r0, l2_38, l3) - - // r1 = l0×l1 + l1×l0 + 19×(l2×l4 + l3×l3 + l4×l2) = 2×l0×l1 + 19×2×l2×l4 + 19×l3×l3 - r1 := mul64(l0_2, l1) - r1 = addMul64(r1, l2_38, l4) - r1 = addMul64(r1, l3_19, l3) - - // r2 = l0×l2 + l1×l1 + l2×l0 + 19×(l3×l4 + l4×l3) = 2×l0×l2 + l1×l1 + 19×2×l3×l4 - r2 := mul64(l0_2, l2) - r2 = addMul64(r2, l1, l1) - r2 = addMul64(r2, l3_38, l4) - - // r3 = l0×l3 + l1×l2 + l2×l1 + l3×l0 + 19×l4×l4 = 2×l0×l3 + 2×l1×l2 + 19×l4×l4 - r3 := mul64(l0_2, l3) - r3 = addMul64(r3, l1_2, l2) - r3 = addMul64(r3, l4_19, l4) - - // r4 = l0×l4 + l1×l3 + l2×l2 + l3×l1 + l4×l0 = 2×l0×l4 + 2×l1×l3 + l2×l2 - r4 := mul64(l0_2, l4) - r4 = addMul64(r4, l1_2, l3) - r4 = addMul64(r4, l2, l2) - - c0 := shiftRightBy51(r0) - c1 := shiftRightBy51(r1) - c2 := shiftRightBy51(r2) - c3 := shiftRightBy51(r3) - c4 := shiftRightBy51(r4) - - rr0 := r0.lo&maskLow51Bits + c4*19 - rr1 := r1.lo&maskLow51Bits + c0 - rr2 := r2.lo&maskLow51Bits + c1 - rr3 := r3.lo&maskLow51Bits + c2 - rr4 := r4.lo&maskLow51Bits + c3 - - *v = Element{rr0, rr1, rr2, rr3, rr4} - v.carryPropagate() -} - -// carryPropagateGeneric brings the limbs below 52 bits by applying the reduction -// identity (a * 2²⁵⁵ + b = a * 19 + b) to the l4 carry. TODO inline -func (v *Element) carryPropagateGeneric() *Element { - c0 := v.l0 >> 51 - c1 := v.l1 >> 51 - c2 := v.l2 >> 51 - c3 := v.l3 >> 51 - c4 := v.l4 >> 51 - - v.l0 = v.l0&maskLow51Bits + c4*19 - v.l1 = v.l1&maskLow51Bits + c0 - v.l2 = v.l2&maskLow51Bits + c1 - v.l3 = v.l3&maskLow51Bits + c2 - v.l4 = v.l4&maskLow51Bits + c3 - - return v -} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/crypto/curve25519/internal/field/sync.checkpoint b/trunk/3rdparty/srs-bench/vendor/golang.org/x/crypto/curve25519/internal/field/sync.checkpoint deleted file mode 100644 index e3685f95c..000000000 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/crypto/curve25519/internal/field/sync.checkpoint +++ /dev/null @@ -1 +0,0 @@ -b0c49ae9f59d233526f8934262c5bbbe14d4358d diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/crypto/curve25519/internal/field/sync.sh b/trunk/3rdparty/srs-bench/vendor/golang.org/x/crypto/curve25519/internal/field/sync.sh deleted file mode 100644 index 1ba22a8b4..000000000 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/crypto/curve25519/internal/field/sync.sh +++ /dev/null @@ -1,19 +0,0 @@ -#! /bin/bash -set -euo pipefail - -cd "$(git rev-parse --show-toplevel)" - -STD_PATH=src/crypto/ed25519/internal/edwards25519/field -LOCAL_PATH=curve25519/internal/field -LAST_SYNC_REF=$(cat $LOCAL_PATH/sync.checkpoint) - -git fetch https://go.googlesource.com/go master - -if git diff --quiet $LAST_SYNC_REF:$STD_PATH FETCH_HEAD:$STD_PATH; then - echo "No changes." -else - NEW_REF=$(git rev-parse FETCH_HEAD | tee $LOCAL_PATH/sync.checkpoint) - echo "Applying changes from $LAST_SYNC_REF to $NEW_REF..." - git diff $LAST_SYNC_REF:$STD_PATH FETCH_HEAD:$STD_PATH | \ - git apply -3 --directory=$LOCAL_PATH -fi diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/LICENSE b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/LICENSE index 6a66aea5e..2a7cf70da 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/LICENSE +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2009 The Go Authors. All rights reserved. +Copyright 2009 The Go Authors. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are @@ -10,7 +10,7 @@ notice, this list of conditions and the following disclaimer. copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - * Neither the name of Google Inc. nor the names of its + * Neither the name of Google LLC nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/internal/socket/zsys_openbsd_ppc64.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/internal/socket/zsys_openbsd_ppc64.go index cebde7634..3c9576e2d 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/internal/socket/zsys_openbsd_ppc64.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/internal/socket/zsys_openbsd_ppc64.go @@ -4,27 +4,27 @@ package socket type iovec struct { - Base *byte - Len uint64 + Base *byte + Len uint64 } type msghdr struct { - Name *byte - Namelen uint32 - Iov *iovec - Iovlen uint32 - Control *byte - Controllen uint32 - Flags int32 + Name *byte + Namelen uint32 + Iov *iovec + Iovlen uint32 + Control *byte + Controllen uint32 + Flags int32 } type cmsghdr struct { - Len uint32 - Level int32 - Type int32 + Len uint32 + Level int32 + Type int32 } const ( - sizeofIovec = 0x10 - sizeofMsghdr = 0x30 + sizeofIovec = 0x10 + sizeofMsghdr = 0x30 ) diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/internal/socket/zsys_openbsd_riscv64.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/internal/socket/zsys_openbsd_riscv64.go index cebde7634..3c9576e2d 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/internal/socket/zsys_openbsd_riscv64.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/internal/socket/zsys_openbsd_riscv64.go @@ -4,27 +4,27 @@ package socket type iovec struct { - Base *byte - Len uint64 + Base *byte + Len uint64 } type msghdr struct { - Name *byte - Namelen uint32 - Iov *iovec - Iovlen uint32 - Control *byte - Controllen uint32 - Flags int32 + Name *byte + Namelen uint32 + Iov *iovec + Iovlen uint32 + Control *byte + Controllen uint32 + Flags int32 } type cmsghdr struct { - Len uint32 - Level int32 - Type int32 + Len uint32 + Level int32 + Type int32 } const ( - sizeofIovec = 0x10 - sizeofMsghdr = 0x30 + sizeofIovec = 0x10 + sizeofMsghdr = 0x30 ) diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/batch.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/batch.go new file mode 100644 index 000000000..2ccb9849c --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/batch.go @@ -0,0 +1,116 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ipv6 + +import ( + "net" + "runtime" + + "golang.org/x/net/internal/socket" +) + +// BUG(mikio): On Windows, the ReadBatch and WriteBatch methods of +// PacketConn are not implemented. + +// A Message represents an IO message. +// +// type Message struct { +// Buffers [][]byte +// OOB []byte +// Addr net.Addr +// N int +// NN int +// Flags int +// } +// +// The Buffers fields represents a list of contiguous buffers, which +// can be used for vectored IO, for example, putting a header and a +// payload in each slice. +// When writing, the Buffers field must contain at least one byte to +// write. +// When reading, the Buffers field will always contain a byte to read. +// +// The OOB field contains protocol-specific control or miscellaneous +// ancillary data known as out-of-band data. +// It can be nil when not required. +// +// The Addr field specifies a destination address when writing. +// It can be nil when the underlying protocol of the endpoint uses +// connection-oriented communication. +// After a successful read, it may contain the source address on the +// received packet. +// +// The N field indicates the number of bytes read or written from/to +// Buffers. +// +// The NN field indicates the number of bytes read or written from/to +// OOB. +// +// The Flags field contains protocol-specific information on the +// received message. +type Message = socket.Message + +// ReadBatch reads a batch of messages. +// +// The provided flags is a set of platform-dependent flags, such as +// syscall.MSG_PEEK. +// +// On a successful read it returns the number of messages received, up +// to len(ms). +// +// On Linux, a batch read will be optimized. +// On other platforms, this method will read only a single message. +func (c *payloadHandler) ReadBatch(ms []Message, flags int) (int, error) { + if !c.ok() { + return 0, errInvalidConn + } + switch runtime.GOOS { + case "linux": + n, err := c.RecvMsgs([]socket.Message(ms), flags) + if err != nil { + err = &net.OpError{Op: "read", Net: c.PacketConn.LocalAddr().Network(), Source: c.PacketConn.LocalAddr(), Err: err} + } + return n, err + default: + n := 1 + err := c.RecvMsg(&ms[0], flags) + if err != nil { + n = 0 + err = &net.OpError{Op: "read", Net: c.PacketConn.LocalAddr().Network(), Source: c.PacketConn.LocalAddr(), Err: err} + } + return n, err + } +} + +// WriteBatch writes a batch of messages. +// +// The provided flags is a set of platform-dependent flags, such as +// syscall.MSG_DONTROUTE. +// +// It returns the number of messages written on a successful write. +// +// On Linux, a batch write will be optimized. +// On other platforms, this method will write only a single message. +func (c *payloadHandler) WriteBatch(ms []Message, flags int) (int, error) { + if !c.ok() { + return 0, errInvalidConn + } + switch runtime.GOOS { + case "linux": + n, err := c.SendMsgs([]socket.Message(ms), flags) + if err != nil { + err = &net.OpError{Op: "write", Net: c.PacketConn.LocalAddr().Network(), Source: c.PacketConn.LocalAddr(), Err: err} + } + return n, err + default: + n := 1 + err := c.SendMsg(&ms[0], flags) + if err != nil { + n = 0 + err = &net.OpError{Op: "write", Net: c.PacketConn.LocalAddr().Network(), Source: c.PacketConn.LocalAddr(), Err: err} + } + return n, err + } +} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/control.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/control.go new file mode 100644 index 000000000..2da644413 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/control.go @@ -0,0 +1,187 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ipv6 + +import ( + "fmt" + "net" + "sync" + + "golang.org/x/net/internal/iana" + "golang.org/x/net/internal/socket" +) + +// Note that RFC 3542 obsoletes RFC 2292 but OS X Snow Leopard and the +// former still support RFC 2292 only. Please be aware that almost +// all protocol implementations prohibit using a combination of RFC +// 2292 and RFC 3542 for some practical reasons. + +type rawOpt struct { + sync.RWMutex + cflags ControlFlags +} + +func (c *rawOpt) set(f ControlFlags) { c.cflags |= f } +func (c *rawOpt) clear(f ControlFlags) { c.cflags &^= f } +func (c *rawOpt) isset(f ControlFlags) bool { return c.cflags&f != 0 } + +// A ControlFlags represents per packet basis IP-level socket option +// control flags. +type ControlFlags uint + +const ( + FlagTrafficClass ControlFlags = 1 << iota // pass the traffic class on the received packet + FlagHopLimit // pass the hop limit on the received packet + FlagSrc // pass the source address on the received packet + FlagDst // pass the destination address on the received packet + FlagInterface // pass the interface index on the received packet + FlagPathMTU // pass the path MTU on the received packet path +) + +const flagPacketInfo = FlagDst | FlagInterface + +// A ControlMessage represents per packet basis IP-level socket +// options. +type ControlMessage struct { + // Receiving socket options: SetControlMessage allows to + // receive the options from the protocol stack using ReadFrom + // method of PacketConn. + // + // Specifying socket options: ControlMessage for WriteTo + // method of PacketConn allows to send the options to the + // protocol stack. + // + TrafficClass int // traffic class, must be 1 <= value <= 255 when specifying + HopLimit int // hop limit, must be 1 <= value <= 255 when specifying + Src net.IP // source address, specifying only + Dst net.IP // destination address, receiving only + IfIndex int // interface index, must be 1 <= value when specifying + NextHop net.IP // next hop address, specifying only + MTU int // path MTU, receiving only +} + +func (cm *ControlMessage) String() string { + if cm == nil { + return "" + } + return fmt.Sprintf("tclass=%#x hoplim=%d src=%v dst=%v ifindex=%d nexthop=%v mtu=%d", cm.TrafficClass, cm.HopLimit, cm.Src, cm.Dst, cm.IfIndex, cm.NextHop, cm.MTU) +} + +// Marshal returns the binary encoding of cm. +func (cm *ControlMessage) Marshal() []byte { + if cm == nil { + return nil + } + var l int + tclass := false + if ctlOpts[ctlTrafficClass].name > 0 && cm.TrafficClass > 0 { + tclass = true + l += socket.ControlMessageSpace(ctlOpts[ctlTrafficClass].length) + } + hoplimit := false + if ctlOpts[ctlHopLimit].name > 0 && cm.HopLimit > 0 { + hoplimit = true + l += socket.ControlMessageSpace(ctlOpts[ctlHopLimit].length) + } + pktinfo := false + if ctlOpts[ctlPacketInfo].name > 0 && (cm.Src.To16() != nil && cm.Src.To4() == nil || cm.IfIndex > 0) { + pktinfo = true + l += socket.ControlMessageSpace(ctlOpts[ctlPacketInfo].length) + } + nexthop := false + if ctlOpts[ctlNextHop].name > 0 && cm.NextHop.To16() != nil && cm.NextHop.To4() == nil { + nexthop = true + l += socket.ControlMessageSpace(ctlOpts[ctlNextHop].length) + } + var b []byte + if l > 0 { + b = make([]byte, l) + bb := b + if tclass { + bb = ctlOpts[ctlTrafficClass].marshal(bb, cm) + } + if hoplimit { + bb = ctlOpts[ctlHopLimit].marshal(bb, cm) + } + if pktinfo { + bb = ctlOpts[ctlPacketInfo].marshal(bb, cm) + } + if nexthop { + bb = ctlOpts[ctlNextHop].marshal(bb, cm) + } + } + return b +} + +// Parse parses b as a control message and stores the result in cm. +func (cm *ControlMessage) Parse(b []byte) error { + ms, err := socket.ControlMessage(b).Parse() + if err != nil { + return err + } + for _, m := range ms { + lvl, typ, l, err := m.ParseHeader() + if err != nil { + return err + } + if lvl != iana.ProtocolIPv6 { + continue + } + switch { + case typ == ctlOpts[ctlTrafficClass].name && l >= ctlOpts[ctlTrafficClass].length: + ctlOpts[ctlTrafficClass].parse(cm, m.Data(l)) + case typ == ctlOpts[ctlHopLimit].name && l >= ctlOpts[ctlHopLimit].length: + ctlOpts[ctlHopLimit].parse(cm, m.Data(l)) + case typ == ctlOpts[ctlPacketInfo].name && l >= ctlOpts[ctlPacketInfo].length: + ctlOpts[ctlPacketInfo].parse(cm, m.Data(l)) + case typ == ctlOpts[ctlPathMTU].name && l >= ctlOpts[ctlPathMTU].length: + ctlOpts[ctlPathMTU].parse(cm, m.Data(l)) + } + } + return nil +} + +// NewControlMessage returns a new control message. +// +// The returned message is large enough for options specified by cf. +func NewControlMessage(cf ControlFlags) []byte { + opt := rawOpt{cflags: cf} + var l int + if opt.isset(FlagTrafficClass) && ctlOpts[ctlTrafficClass].name > 0 { + l += socket.ControlMessageSpace(ctlOpts[ctlTrafficClass].length) + } + if opt.isset(FlagHopLimit) && ctlOpts[ctlHopLimit].name > 0 { + l += socket.ControlMessageSpace(ctlOpts[ctlHopLimit].length) + } + if opt.isset(flagPacketInfo) && ctlOpts[ctlPacketInfo].name > 0 { + l += socket.ControlMessageSpace(ctlOpts[ctlPacketInfo].length) + } + if opt.isset(FlagPathMTU) && ctlOpts[ctlPathMTU].name > 0 { + l += socket.ControlMessageSpace(ctlOpts[ctlPathMTU].length) + } + var b []byte + if l > 0 { + b = make([]byte, l) + } + return b +} + +// Ancillary data socket options +const ( + ctlTrafficClass = iota // header field + ctlHopLimit // header field + ctlPacketInfo // inbound or outbound packet path + ctlNextHop // nexthop + ctlPathMTU // path mtu + ctlMax +) + +// A ctlOpt represents a binding for ancillary data socket option. +type ctlOpt struct { + name int // option name, must be equal or greater than 1 + length int // option length + marshal func([]byte, *ControlMessage) []byte + parse func(*ControlMessage, []byte) +} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/control_rfc2292_unix.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/control_rfc2292_unix.go new file mode 100644 index 000000000..a8f04e7b3 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/control_rfc2292_unix.go @@ -0,0 +1,50 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build darwin + +package ipv6 + +import ( + "unsafe" + + "golang.org/x/net/internal/iana" + "golang.org/x/net/internal/socket" + + "golang.org/x/sys/unix" +) + +func marshal2292HopLimit(b []byte, cm *ControlMessage) []byte { + m := socket.ControlMessage(b) + m.MarshalHeader(iana.ProtocolIPv6, unix.IPV6_2292HOPLIMIT, 4) + if cm != nil { + socket.NativeEndian.PutUint32(m.Data(4), uint32(cm.HopLimit)) + } + return m.Next(4) +} + +func marshal2292PacketInfo(b []byte, cm *ControlMessage) []byte { + m := socket.ControlMessage(b) + m.MarshalHeader(iana.ProtocolIPv6, unix.IPV6_2292PKTINFO, sizeofInet6Pktinfo) + if cm != nil { + pi := (*inet6Pktinfo)(unsafe.Pointer(&m.Data(sizeofInet6Pktinfo)[0])) + if ip := cm.Src.To16(); ip != nil && ip.To4() == nil { + copy(pi.Addr[:], ip) + } + if cm.IfIndex > 0 { + pi.setIfindex(cm.IfIndex) + } + } + return m.Next(sizeofInet6Pktinfo) +} + +func marshal2292NextHop(b []byte, cm *ControlMessage) []byte { + m := socket.ControlMessage(b) + m.MarshalHeader(iana.ProtocolIPv6, unix.IPV6_2292NEXTHOP, sizeofSockaddrInet6) + if cm != nil { + sa := (*sockaddrInet6)(unsafe.Pointer(&m.Data(sizeofSockaddrInet6)[0])) + sa.setSockaddr(cm.NextHop, cm.IfIndex) + } + return m.Next(sizeofSockaddrInet6) +} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/control_rfc3542_unix.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/control_rfc3542_unix.go new file mode 100644 index 000000000..51fbbb1f1 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/control_rfc3542_unix.go @@ -0,0 +1,96 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos + +package ipv6 + +import ( + "net" + "unsafe" + + "golang.org/x/net/internal/iana" + "golang.org/x/net/internal/socket" + + "golang.org/x/sys/unix" +) + +func marshalTrafficClass(b []byte, cm *ControlMessage) []byte { + m := socket.ControlMessage(b) + m.MarshalHeader(iana.ProtocolIPv6, unix.IPV6_TCLASS, 4) + if cm != nil { + socket.NativeEndian.PutUint32(m.Data(4), uint32(cm.TrafficClass)) + } + return m.Next(4) +} + +func parseTrafficClass(cm *ControlMessage, b []byte) { + cm.TrafficClass = int(socket.NativeEndian.Uint32(b[:4])) +} + +func marshalHopLimit(b []byte, cm *ControlMessage) []byte { + m := socket.ControlMessage(b) + m.MarshalHeader(iana.ProtocolIPv6, unix.IPV6_HOPLIMIT, 4) + if cm != nil { + socket.NativeEndian.PutUint32(m.Data(4), uint32(cm.HopLimit)) + } + return m.Next(4) +} + +func parseHopLimit(cm *ControlMessage, b []byte) { + cm.HopLimit = int(socket.NativeEndian.Uint32(b[:4])) +} + +func marshalPacketInfo(b []byte, cm *ControlMessage) []byte { + m := socket.ControlMessage(b) + m.MarshalHeader(iana.ProtocolIPv6, unix.IPV6_PKTINFO, sizeofInet6Pktinfo) + if cm != nil { + pi := (*inet6Pktinfo)(unsafe.Pointer(&m.Data(sizeofInet6Pktinfo)[0])) + if ip := cm.Src.To16(); ip != nil && ip.To4() == nil { + copy(pi.Addr[:], ip) + } + if cm.IfIndex > 0 { + pi.setIfindex(cm.IfIndex) + } + } + return m.Next(sizeofInet6Pktinfo) +} + +func parsePacketInfo(cm *ControlMessage, b []byte) { + pi := (*inet6Pktinfo)(unsafe.Pointer(&b[0])) + if len(cm.Dst) < net.IPv6len { + cm.Dst = make(net.IP, net.IPv6len) + } + copy(cm.Dst, pi.Addr[:]) + cm.IfIndex = int(pi.Ifindex) +} + +func marshalNextHop(b []byte, cm *ControlMessage) []byte { + m := socket.ControlMessage(b) + m.MarshalHeader(iana.ProtocolIPv6, unix.IPV6_NEXTHOP, sizeofSockaddrInet6) + if cm != nil { + sa := (*sockaddrInet6)(unsafe.Pointer(&m.Data(sizeofSockaddrInet6)[0])) + sa.setSockaddr(cm.NextHop, cm.IfIndex) + } + return m.Next(sizeofSockaddrInet6) +} + +func parseNextHop(cm *ControlMessage, b []byte) { +} + +func marshalPathMTU(b []byte, cm *ControlMessage) []byte { + m := socket.ControlMessage(b) + m.MarshalHeader(iana.ProtocolIPv6, unix.IPV6_PATHMTU, sizeofIPv6Mtuinfo) + return m.Next(sizeofIPv6Mtuinfo) +} + +func parsePathMTU(cm *ControlMessage, b []byte) { + mi := (*ipv6Mtuinfo)(unsafe.Pointer(&b[0])) + if len(cm.Dst) < net.IPv6len { + cm.Dst = make(net.IP, net.IPv6len) + } + copy(cm.Dst, mi.Addr.Addr[:]) + cm.IfIndex = int(mi.Addr.Scope_id) + cm.MTU = int(mi.Mtu) +} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/control_stub.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/control_stub.go new file mode 100644 index 000000000..eb28ce753 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/control_stub.go @@ -0,0 +1,13 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !aix && !darwin && !dragonfly && !freebsd && !linux && !netbsd && !openbsd && !solaris && !windows && !zos + +package ipv6 + +import "golang.org/x/net/internal/socket" + +func setControlMessage(c *socket.Conn, opt *rawOpt, cf ControlFlags, on bool) error { + return errNotImplemented +} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/control_unix.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/control_unix.go new file mode 100644 index 000000000..9c73b8647 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/control_unix.go @@ -0,0 +1,55 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos + +package ipv6 + +import "golang.org/x/net/internal/socket" + +func setControlMessage(c *socket.Conn, opt *rawOpt, cf ControlFlags, on bool) error { + opt.Lock() + defer opt.Unlock() + if so, ok := sockOpts[ssoReceiveTrafficClass]; ok && cf&FlagTrafficClass != 0 { + if err := so.SetInt(c, boolint(on)); err != nil { + return err + } + if on { + opt.set(FlagTrafficClass) + } else { + opt.clear(FlagTrafficClass) + } + } + if so, ok := sockOpts[ssoReceiveHopLimit]; ok && cf&FlagHopLimit != 0 { + if err := so.SetInt(c, boolint(on)); err != nil { + return err + } + if on { + opt.set(FlagHopLimit) + } else { + opt.clear(FlagHopLimit) + } + } + if so, ok := sockOpts[ssoReceivePacketInfo]; ok && cf&flagPacketInfo != 0 { + if err := so.SetInt(c, boolint(on)); err != nil { + return err + } + if on { + opt.set(cf & flagPacketInfo) + } else { + opt.clear(cf & flagPacketInfo) + } + } + if so, ok := sockOpts[ssoReceivePathMTU]; ok && cf&FlagPathMTU != 0 { + if err := so.SetInt(c, boolint(on)); err != nil { + return err + } + if on { + opt.set(FlagPathMTU) + } else { + opt.clear(FlagPathMTU) + } + } + return nil +} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/control_windows.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/control_windows.go new file mode 100644 index 000000000..8882d8193 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/control_windows.go @@ -0,0 +1,12 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ipv6 + +import "golang.org/x/net/internal/socket" + +func setControlMessage(c *socket.Conn, opt *rawOpt, cf ControlFlags, on bool) error { + // TODO(mikio): implement this + return errNotImplemented +} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/dgramopt.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/dgramopt.go new file mode 100644 index 000000000..846f0e1f9 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/dgramopt.go @@ -0,0 +1,301 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ipv6 + +import ( + "net" + + "golang.org/x/net/bpf" +) + +// MulticastHopLimit returns the hop limit field value for outgoing +// multicast packets. +func (c *dgramOpt) MulticastHopLimit() (int, error) { + if !c.ok() { + return 0, errInvalidConn + } + so, ok := sockOpts[ssoMulticastHopLimit] + if !ok { + return 0, errNotImplemented + } + return so.GetInt(c.Conn) +} + +// SetMulticastHopLimit sets the hop limit field value for future +// outgoing multicast packets. +func (c *dgramOpt) SetMulticastHopLimit(hoplim int) error { + if !c.ok() { + return errInvalidConn + } + so, ok := sockOpts[ssoMulticastHopLimit] + if !ok { + return errNotImplemented + } + return so.SetInt(c.Conn, hoplim) +} + +// MulticastInterface returns the default interface for multicast +// packet transmissions. +func (c *dgramOpt) MulticastInterface() (*net.Interface, error) { + if !c.ok() { + return nil, errInvalidConn + } + so, ok := sockOpts[ssoMulticastInterface] + if !ok { + return nil, errNotImplemented + } + return so.getMulticastInterface(c.Conn) +} + +// SetMulticastInterface sets the default interface for future +// multicast packet transmissions. +func (c *dgramOpt) SetMulticastInterface(ifi *net.Interface) error { + if !c.ok() { + return errInvalidConn + } + so, ok := sockOpts[ssoMulticastInterface] + if !ok { + return errNotImplemented + } + return so.setMulticastInterface(c.Conn, ifi) +} + +// MulticastLoopback reports whether transmitted multicast packets +// should be copied and send back to the originator. +func (c *dgramOpt) MulticastLoopback() (bool, error) { + if !c.ok() { + return false, errInvalidConn + } + so, ok := sockOpts[ssoMulticastLoopback] + if !ok { + return false, errNotImplemented + } + on, err := so.GetInt(c.Conn) + if err != nil { + return false, err + } + return on == 1, nil +} + +// SetMulticastLoopback sets whether transmitted multicast packets +// should be copied and send back to the originator. +func (c *dgramOpt) SetMulticastLoopback(on bool) error { + if !c.ok() { + return errInvalidConn + } + so, ok := sockOpts[ssoMulticastLoopback] + if !ok { + return errNotImplemented + } + return so.SetInt(c.Conn, boolint(on)) +} + +// JoinGroup joins the group address group on the interface ifi. +// By default all sources that can cast data to group are accepted. +// It's possible to mute and unmute data transmission from a specific +// source by using ExcludeSourceSpecificGroup and +// IncludeSourceSpecificGroup. +// JoinGroup uses the system assigned multicast interface when ifi is +// nil, although this is not recommended because the assignment +// depends on platforms and sometimes it might require routing +// configuration. +func (c *dgramOpt) JoinGroup(ifi *net.Interface, group net.Addr) error { + if !c.ok() { + return errInvalidConn + } + so, ok := sockOpts[ssoJoinGroup] + if !ok { + return errNotImplemented + } + grp := netAddrToIP16(group) + if grp == nil { + return errMissingAddress + } + return so.setGroup(c.Conn, ifi, grp) +} + +// LeaveGroup leaves the group address group on the interface ifi +// regardless of whether the group is any-source group or +// source-specific group. +func (c *dgramOpt) LeaveGroup(ifi *net.Interface, group net.Addr) error { + if !c.ok() { + return errInvalidConn + } + so, ok := sockOpts[ssoLeaveGroup] + if !ok { + return errNotImplemented + } + grp := netAddrToIP16(group) + if grp == nil { + return errMissingAddress + } + return so.setGroup(c.Conn, ifi, grp) +} + +// JoinSourceSpecificGroup joins the source-specific group comprising +// group and source on the interface ifi. +// JoinSourceSpecificGroup uses the system assigned multicast +// interface when ifi is nil, although this is not recommended because +// the assignment depends on platforms and sometimes it might require +// routing configuration. +func (c *dgramOpt) JoinSourceSpecificGroup(ifi *net.Interface, group, source net.Addr) error { + if !c.ok() { + return errInvalidConn + } + so, ok := sockOpts[ssoJoinSourceGroup] + if !ok { + return errNotImplemented + } + grp := netAddrToIP16(group) + if grp == nil { + return errMissingAddress + } + src := netAddrToIP16(source) + if src == nil { + return errMissingAddress + } + return so.setSourceGroup(c.Conn, ifi, grp, src) +} + +// LeaveSourceSpecificGroup leaves the source-specific group on the +// interface ifi. +func (c *dgramOpt) LeaveSourceSpecificGroup(ifi *net.Interface, group, source net.Addr) error { + if !c.ok() { + return errInvalidConn + } + so, ok := sockOpts[ssoLeaveSourceGroup] + if !ok { + return errNotImplemented + } + grp := netAddrToIP16(group) + if grp == nil { + return errMissingAddress + } + src := netAddrToIP16(source) + if src == nil { + return errMissingAddress + } + return so.setSourceGroup(c.Conn, ifi, grp, src) +} + +// ExcludeSourceSpecificGroup excludes the source-specific group from +// the already joined any-source groups by JoinGroup on the interface +// ifi. +func (c *dgramOpt) ExcludeSourceSpecificGroup(ifi *net.Interface, group, source net.Addr) error { + if !c.ok() { + return errInvalidConn + } + so, ok := sockOpts[ssoBlockSourceGroup] + if !ok { + return errNotImplemented + } + grp := netAddrToIP16(group) + if grp == nil { + return errMissingAddress + } + src := netAddrToIP16(source) + if src == nil { + return errMissingAddress + } + return so.setSourceGroup(c.Conn, ifi, grp, src) +} + +// IncludeSourceSpecificGroup includes the excluded source-specific +// group by ExcludeSourceSpecificGroup again on the interface ifi. +func (c *dgramOpt) IncludeSourceSpecificGroup(ifi *net.Interface, group, source net.Addr) error { + if !c.ok() { + return errInvalidConn + } + so, ok := sockOpts[ssoUnblockSourceGroup] + if !ok { + return errNotImplemented + } + grp := netAddrToIP16(group) + if grp == nil { + return errMissingAddress + } + src := netAddrToIP16(source) + if src == nil { + return errMissingAddress + } + return so.setSourceGroup(c.Conn, ifi, grp, src) +} + +// Checksum reports whether the kernel will compute, store or verify a +// checksum for both incoming and outgoing packets. If on is true, it +// returns an offset in bytes into the data of where the checksum +// field is located. +func (c *dgramOpt) Checksum() (on bool, offset int, err error) { + if !c.ok() { + return false, 0, errInvalidConn + } + so, ok := sockOpts[ssoChecksum] + if !ok { + return false, 0, errNotImplemented + } + offset, err = so.GetInt(c.Conn) + if err != nil { + return false, 0, err + } + if offset < 0 { + return false, 0, nil + } + return true, offset, nil +} + +// SetChecksum enables the kernel checksum processing. If on is true, +// the offset should be an offset in bytes into the data of where the +// checksum field is located. +func (c *dgramOpt) SetChecksum(on bool, offset int) error { + if !c.ok() { + return errInvalidConn + } + so, ok := sockOpts[ssoChecksum] + if !ok { + return errNotImplemented + } + if !on { + offset = -1 + } + return so.SetInt(c.Conn, offset) +} + +// ICMPFilter returns an ICMP filter. +func (c *dgramOpt) ICMPFilter() (*ICMPFilter, error) { + if !c.ok() { + return nil, errInvalidConn + } + so, ok := sockOpts[ssoICMPFilter] + if !ok { + return nil, errNotImplemented + } + return so.getICMPFilter(c.Conn) +} + +// SetICMPFilter deploys the ICMP filter. +func (c *dgramOpt) SetICMPFilter(f *ICMPFilter) error { + if !c.ok() { + return errInvalidConn + } + so, ok := sockOpts[ssoICMPFilter] + if !ok { + return errNotImplemented + } + return so.setICMPFilter(c.Conn, f) +} + +// SetBPF attaches a BPF program to the connection. +// +// Only supported on Linux. +func (c *dgramOpt) SetBPF(filter []bpf.RawInstruction) error { + if !c.ok() { + return errInvalidConn + } + so, ok := sockOpts[ssoAttachFilter] + if !ok { + return errNotImplemented + } + return so.setBPF(c.Conn, filter) +} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/doc.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/doc.go new file mode 100644 index 000000000..2148b814f --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/doc.go @@ -0,0 +1,239 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package ipv6 implements IP-level socket options for the Internet +// Protocol version 6. +// +// The package provides IP-level socket options that allow +// manipulation of IPv6 facilities. +// +// The IPv6 protocol is defined in RFC 8200. +// Socket interface extensions are defined in RFC 3493, RFC 3542 and +// RFC 3678. +// MLDv1 and MLDv2 are defined in RFC 2710 and RFC 3810. +// Source-specific multicast is defined in RFC 4607. +// +// On Darwin, this package requires OS X Mavericks version 10.9 or +// above, or equivalent. +// +// # Unicasting +// +// The options for unicasting are available for net.TCPConn, +// net.UDPConn and net.IPConn which are created as network connections +// that use the IPv6 transport. When a single TCP connection carrying +// a data flow of multiple packets needs to indicate the flow is +// important, Conn is used to set the traffic class field on the IPv6 +// header for each packet. +// +// ln, err := net.Listen("tcp6", "[::]:1024") +// if err != nil { +// // error handling +// } +// defer ln.Close() +// for { +// c, err := ln.Accept() +// if err != nil { +// // error handling +// } +// go func(c net.Conn) { +// defer c.Close() +// +// The outgoing packets will be labeled DiffServ assured forwarding +// class 1 low drop precedence, known as AF11 packets. +// +// if err := ipv6.NewConn(c).SetTrafficClass(0x28); err != nil { +// // error handling +// } +// if _, err := c.Write(data); err != nil { +// // error handling +// } +// }(c) +// } +// +// # Multicasting +// +// The options for multicasting are available for net.UDPConn and +// net.IPConn which are created as network connections that use the +// IPv6 transport. A few network facilities must be prepared before +// you begin multicasting, at a minimum joining network interfaces and +// multicast groups. +// +// en0, err := net.InterfaceByName("en0") +// if err != nil { +// // error handling +// } +// en1, err := net.InterfaceByIndex(911) +// if err != nil { +// // error handling +// } +// group := net.ParseIP("ff02::114") +// +// First, an application listens to an appropriate address with an +// appropriate service port. +// +// c, err := net.ListenPacket("udp6", "[::]:1024") +// if err != nil { +// // error handling +// } +// defer c.Close() +// +// Second, the application joins multicast groups, starts listening to +// the groups on the specified network interfaces. Note that the +// service port for transport layer protocol does not matter with this +// operation as joining groups affects only network and link layer +// protocols, such as IPv6 and Ethernet. +// +// p := ipv6.NewPacketConn(c) +// if err := p.JoinGroup(en0, &net.UDPAddr{IP: group}); err != nil { +// // error handling +// } +// if err := p.JoinGroup(en1, &net.UDPAddr{IP: group}); err != nil { +// // error handling +// } +// +// The application might set per packet control message transmissions +// between the protocol stack within the kernel. When the application +// needs a destination address on an incoming packet, +// SetControlMessage of PacketConn is used to enable control message +// transmissions. +// +// if err := p.SetControlMessage(ipv6.FlagDst, true); err != nil { +// // error handling +// } +// +// The application could identify whether the received packets are +// of interest by using the control message that contains the +// destination address of the received packet. +// +// b := make([]byte, 1500) +// for { +// n, rcm, src, err := p.ReadFrom(b) +// if err != nil { +// // error handling +// } +// if rcm.Dst.IsMulticast() { +// if rcm.Dst.Equal(group) { +// // joined group, do something +// } else { +// // unknown group, discard +// continue +// } +// } +// +// The application can also send both unicast and multicast packets. +// +// p.SetTrafficClass(0x0) +// p.SetHopLimit(16) +// if _, err := p.WriteTo(data[:n], nil, src); err != nil { +// // error handling +// } +// dst := &net.UDPAddr{IP: group, Port: 1024} +// wcm := ipv6.ControlMessage{TrafficClass: 0xe0, HopLimit: 1} +// for _, ifi := range []*net.Interface{en0, en1} { +// wcm.IfIndex = ifi.Index +// if _, err := p.WriteTo(data[:n], &wcm, dst); err != nil { +// // error handling +// } +// } +// } +// +// # More multicasting +// +// An application that uses PacketConn may join multiple multicast +// groups. For example, a UDP listener with port 1024 might join two +// different groups across over two different network interfaces by +// using: +// +// c, err := net.ListenPacket("udp6", "[::]:1024") +// if err != nil { +// // error handling +// } +// defer c.Close() +// p := ipv6.NewPacketConn(c) +// if err := p.JoinGroup(en0, &net.UDPAddr{IP: net.ParseIP("ff02::1:114")}); err != nil { +// // error handling +// } +// if err := p.JoinGroup(en0, &net.UDPAddr{IP: net.ParseIP("ff02::2:114")}); err != nil { +// // error handling +// } +// if err := p.JoinGroup(en1, &net.UDPAddr{IP: net.ParseIP("ff02::2:114")}); err != nil { +// // error handling +// } +// +// It is possible for multiple UDP listeners that listen on the same +// UDP port to join the same multicast group. The net package will +// provide a socket that listens to a wildcard address with reusable +// UDP port when an appropriate multicast address prefix is passed to +// the net.ListenPacket or net.ListenUDP. +// +// c1, err := net.ListenPacket("udp6", "[ff02::]:1024") +// if err != nil { +// // error handling +// } +// defer c1.Close() +// c2, err := net.ListenPacket("udp6", "[ff02::]:1024") +// if err != nil { +// // error handling +// } +// defer c2.Close() +// p1 := ipv6.NewPacketConn(c1) +// if err := p1.JoinGroup(en0, &net.UDPAddr{IP: net.ParseIP("ff02::114")}); err != nil { +// // error handling +// } +// p2 := ipv6.NewPacketConn(c2) +// if err := p2.JoinGroup(en0, &net.UDPAddr{IP: net.ParseIP("ff02::114")}); err != nil { +// // error handling +// } +// +// Also it is possible for the application to leave or rejoin a +// multicast group on the network interface. +// +// if err := p.LeaveGroup(en0, &net.UDPAddr{IP: net.ParseIP("ff02::114")}); err != nil { +// // error handling +// } +// if err := p.JoinGroup(en0, &net.UDPAddr{IP: net.ParseIP("ff01::114")}); err != nil { +// // error handling +// } +// +// # Source-specific multicasting +// +// An application that uses PacketConn on MLDv2 supported platform is +// able to join source-specific multicast groups. +// The application may use JoinSourceSpecificGroup and +// LeaveSourceSpecificGroup for the operation known as "include" mode, +// +// ssmgroup := net.UDPAddr{IP: net.ParseIP("ff32::8000:9")} +// ssmsource := net.UDPAddr{IP: net.ParseIP("fe80::cafe")} +// if err := p.JoinSourceSpecificGroup(en0, &ssmgroup, &ssmsource); err != nil { +// // error handling +// } +// if err := p.LeaveSourceSpecificGroup(en0, &ssmgroup, &ssmsource); err != nil { +// // error handling +// } +// +// or JoinGroup, ExcludeSourceSpecificGroup, +// IncludeSourceSpecificGroup and LeaveGroup for the operation known +// as "exclude" mode. +// +// exclsource := net.UDPAddr{IP: net.ParseIP("fe80::dead")} +// if err := p.JoinGroup(en0, &ssmgroup); err != nil { +// // error handling +// } +// if err := p.ExcludeSourceSpecificGroup(en0, &ssmgroup, &exclsource); err != nil { +// // error handling +// } +// if err := p.LeaveGroup(en0, &ssmgroup); err != nil { +// // error handling +// } +// +// Note that it depends on each platform implementation what happens +// when an application which runs on MLDv2 unsupported platform uses +// JoinSourceSpecificGroup and LeaveSourceSpecificGroup. +// In general the platform tries to fall back to conversations using +// MLDv1 and starts to listen to multicast traffic. +// In the fallback case, ExcludeSourceSpecificGroup and +// IncludeSourceSpecificGroup may return an error. +package ipv6 // import "golang.org/x/net/ipv6" + +// BUG(mikio): This package is not implemented on JS, NaCl and Plan 9. diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/endpoint.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/endpoint.go new file mode 100644 index 000000000..f534a0bf3 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/endpoint.go @@ -0,0 +1,127 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ipv6 + +import ( + "net" + "time" + + "golang.org/x/net/internal/socket" +) + +// BUG(mikio): On Windows, the JoinSourceSpecificGroup, +// LeaveSourceSpecificGroup, ExcludeSourceSpecificGroup and +// IncludeSourceSpecificGroup methods of PacketConn are not +// implemented. + +// A Conn represents a network endpoint that uses IPv6 transport. +// It allows to set basic IP-level socket options such as traffic +// class and hop limit. +type Conn struct { + genericOpt +} + +type genericOpt struct { + *socket.Conn +} + +func (c *genericOpt) ok() bool { return c != nil && c.Conn != nil } + +// PathMTU returns a path MTU value for the destination associated +// with the endpoint. +func (c *Conn) PathMTU() (int, error) { + if !c.ok() { + return 0, errInvalidConn + } + so, ok := sockOpts[ssoPathMTU] + if !ok { + return 0, errNotImplemented + } + _, mtu, err := so.getMTUInfo(c.Conn) + if err != nil { + return 0, err + } + return mtu, nil +} + +// NewConn returns a new Conn. +func NewConn(c net.Conn) *Conn { + cc, _ := socket.NewConn(c) + return &Conn{ + genericOpt: genericOpt{Conn: cc}, + } +} + +// A PacketConn represents a packet network endpoint that uses IPv6 +// transport. It is used to control several IP-level socket options +// including IPv6 header manipulation. It also provides datagram +// based network I/O methods specific to the IPv6 and higher layer +// protocols such as OSPF, GRE, and UDP. +type PacketConn struct { + genericOpt + dgramOpt + payloadHandler +} + +type dgramOpt struct { + *socket.Conn +} + +func (c *dgramOpt) ok() bool { return c != nil && c.Conn != nil } + +// SetControlMessage allows to receive the per packet basis IP-level +// socket options. +func (c *PacketConn) SetControlMessage(cf ControlFlags, on bool) error { + if !c.payloadHandler.ok() { + return errInvalidConn + } + return setControlMessage(c.dgramOpt.Conn, &c.payloadHandler.rawOpt, cf, on) +} + +// SetDeadline sets the read and write deadlines associated with the +// endpoint. +func (c *PacketConn) SetDeadline(t time.Time) error { + if !c.payloadHandler.ok() { + return errInvalidConn + } + return c.payloadHandler.SetDeadline(t) +} + +// SetReadDeadline sets the read deadline associated with the +// endpoint. +func (c *PacketConn) SetReadDeadline(t time.Time) error { + if !c.payloadHandler.ok() { + return errInvalidConn + } + return c.payloadHandler.SetReadDeadline(t) +} + +// SetWriteDeadline sets the write deadline associated with the +// endpoint. +func (c *PacketConn) SetWriteDeadline(t time.Time) error { + if !c.payloadHandler.ok() { + return errInvalidConn + } + return c.payloadHandler.SetWriteDeadline(t) +} + +// Close closes the endpoint. +func (c *PacketConn) Close() error { + if !c.payloadHandler.ok() { + return errInvalidConn + } + return c.payloadHandler.Close() +} + +// NewPacketConn returns a new PacketConn using c as its underlying +// transport. +func NewPacketConn(c net.PacketConn) *PacketConn { + cc, _ := socket.NewConn(c.(net.Conn)) + return &PacketConn{ + genericOpt: genericOpt{Conn: cc}, + dgramOpt: dgramOpt{Conn: cc}, + payloadHandler: payloadHandler{PacketConn: c, Conn: cc}, + } +} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/genericopt.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/genericopt.go new file mode 100644 index 000000000..0326aed6d --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/genericopt.go @@ -0,0 +1,56 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ipv6 + +// TrafficClass returns the traffic class field value for outgoing +// packets. +func (c *genericOpt) TrafficClass() (int, error) { + if !c.ok() { + return 0, errInvalidConn + } + so, ok := sockOpts[ssoTrafficClass] + if !ok { + return 0, errNotImplemented + } + return so.GetInt(c.Conn) +} + +// SetTrafficClass sets the traffic class field value for future +// outgoing packets. +func (c *genericOpt) SetTrafficClass(tclass int) error { + if !c.ok() { + return errInvalidConn + } + so, ok := sockOpts[ssoTrafficClass] + if !ok { + return errNotImplemented + } + return so.SetInt(c.Conn, tclass) +} + +// HopLimit returns the hop limit field value for outgoing packets. +func (c *genericOpt) HopLimit() (int, error) { + if !c.ok() { + return 0, errInvalidConn + } + so, ok := sockOpts[ssoHopLimit] + if !ok { + return 0, errNotImplemented + } + return so.GetInt(c.Conn) +} + +// SetHopLimit sets the hop limit field value for future outgoing +// packets. +func (c *genericOpt) SetHopLimit(hoplim int) error { + if !c.ok() { + return errInvalidConn + } + so, ok := sockOpts[ssoHopLimit] + if !ok { + return errNotImplemented + } + return so.SetInt(c.Conn, hoplim) +} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/header.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/header.go new file mode 100644 index 000000000..e05cb08b2 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/header.go @@ -0,0 +1,55 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ipv6 + +import ( + "encoding/binary" + "fmt" + "net" +) + +const ( + Version = 6 // protocol version + HeaderLen = 40 // header length +) + +// A Header represents an IPv6 base header. +type Header struct { + Version int // protocol version + TrafficClass int // traffic class + FlowLabel int // flow label + PayloadLen int // payload length + NextHeader int // next header + HopLimit int // hop limit + Src net.IP // source address + Dst net.IP // destination address +} + +func (h *Header) String() string { + if h == nil { + return "" + } + return fmt.Sprintf("ver=%d tclass=%#x flowlbl=%#x payloadlen=%d nxthdr=%d hoplim=%d src=%v dst=%v", h.Version, h.TrafficClass, h.FlowLabel, h.PayloadLen, h.NextHeader, h.HopLimit, h.Src, h.Dst) +} + +// ParseHeader parses b as an IPv6 base header. +func ParseHeader(b []byte) (*Header, error) { + if len(b) < HeaderLen { + return nil, errHeaderTooShort + } + h := &Header{ + Version: int(b[0]) >> 4, + TrafficClass: int(b[0]&0x0f)<<4 | int(b[1])>>4, + FlowLabel: int(b[1]&0x0f)<<16 | int(b[2])<<8 | int(b[3]), + PayloadLen: int(binary.BigEndian.Uint16(b[4:6])), + NextHeader: int(b[6]), + HopLimit: int(b[7]), + } + h.Src = make(net.IP, net.IPv6len) + copy(h.Src, b[8:24]) + h.Dst = make(net.IP, net.IPv6len) + copy(h.Dst, b[24:40]) + return h, nil +} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/helper.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/helper.go new file mode 100644 index 000000000..c2d508f9c --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/helper.go @@ -0,0 +1,58 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ipv6 + +import ( + "errors" + "net" + "runtime" +) + +var ( + errInvalidConn = errors.New("invalid connection") + errMissingAddress = errors.New("missing address") + errHeaderTooShort = errors.New("header too short") + errInvalidConnType = errors.New("invalid conn type") + errNotImplemented = errors.New("not implemented on " + runtime.GOOS + "/" + runtime.GOARCH) +) + +func boolint(b bool) int { + if b { + return 1 + } + return 0 +} + +func netAddrToIP16(a net.Addr) net.IP { + switch v := a.(type) { + case *net.UDPAddr: + if ip := v.IP.To16(); ip != nil && ip.To4() == nil { + return ip + } + case *net.IPAddr: + if ip := v.IP.To16(); ip != nil && ip.To4() == nil { + return ip + } + } + return nil +} + +func opAddr(a net.Addr) net.Addr { + switch a.(type) { + case *net.TCPAddr: + if a == nil { + return nil + } + case *net.UDPAddr: + if a == nil { + return nil + } + case *net.IPAddr: + if a == nil { + return nil + } + } + return a +} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/iana.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/iana.go new file mode 100644 index 000000000..32db1aa94 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/iana.go @@ -0,0 +1,86 @@ +// go generate gen.go +// Code generated by the command above; DO NOT EDIT. + +package ipv6 + +// Internet Control Message Protocol version 6 (ICMPv6) Parameters, Updated: 2018-03-09 +const ( + ICMPTypeDestinationUnreachable ICMPType = 1 // Destination Unreachable + ICMPTypePacketTooBig ICMPType = 2 // Packet Too Big + ICMPTypeTimeExceeded ICMPType = 3 // Time Exceeded + ICMPTypeParameterProblem ICMPType = 4 // Parameter Problem + ICMPTypeEchoRequest ICMPType = 128 // Echo Request + ICMPTypeEchoReply ICMPType = 129 // Echo Reply + ICMPTypeMulticastListenerQuery ICMPType = 130 // Multicast Listener Query + ICMPTypeMulticastListenerReport ICMPType = 131 // Multicast Listener Report + ICMPTypeMulticastListenerDone ICMPType = 132 // Multicast Listener Done + ICMPTypeRouterSolicitation ICMPType = 133 // Router Solicitation + ICMPTypeRouterAdvertisement ICMPType = 134 // Router Advertisement + ICMPTypeNeighborSolicitation ICMPType = 135 // Neighbor Solicitation + ICMPTypeNeighborAdvertisement ICMPType = 136 // Neighbor Advertisement + ICMPTypeRedirect ICMPType = 137 // Redirect Message + ICMPTypeRouterRenumbering ICMPType = 138 // Router Renumbering + ICMPTypeNodeInformationQuery ICMPType = 139 // ICMP Node Information Query + ICMPTypeNodeInformationResponse ICMPType = 140 // ICMP Node Information Response + ICMPTypeInverseNeighborDiscoverySolicitation ICMPType = 141 // Inverse Neighbor Discovery Solicitation Message + ICMPTypeInverseNeighborDiscoveryAdvertisement ICMPType = 142 // Inverse Neighbor Discovery Advertisement Message + ICMPTypeVersion2MulticastListenerReport ICMPType = 143 // Version 2 Multicast Listener Report + ICMPTypeHomeAgentAddressDiscoveryRequest ICMPType = 144 // Home Agent Address Discovery Request Message + ICMPTypeHomeAgentAddressDiscoveryReply ICMPType = 145 // Home Agent Address Discovery Reply Message + ICMPTypeMobilePrefixSolicitation ICMPType = 146 // Mobile Prefix Solicitation + ICMPTypeMobilePrefixAdvertisement ICMPType = 147 // Mobile Prefix Advertisement + ICMPTypeCertificationPathSolicitation ICMPType = 148 // Certification Path Solicitation Message + ICMPTypeCertificationPathAdvertisement ICMPType = 149 // Certification Path Advertisement Message + ICMPTypeMulticastRouterAdvertisement ICMPType = 151 // Multicast Router Advertisement + ICMPTypeMulticastRouterSolicitation ICMPType = 152 // Multicast Router Solicitation + ICMPTypeMulticastRouterTermination ICMPType = 153 // Multicast Router Termination + ICMPTypeFMIPv6 ICMPType = 154 // FMIPv6 Messages + ICMPTypeRPLControl ICMPType = 155 // RPL Control Message + ICMPTypeILNPv6LocatorUpdate ICMPType = 156 // ILNPv6 Locator Update Message + ICMPTypeDuplicateAddressRequest ICMPType = 157 // Duplicate Address Request + ICMPTypeDuplicateAddressConfirmation ICMPType = 158 // Duplicate Address Confirmation + ICMPTypeMPLControl ICMPType = 159 // MPL Control Message + ICMPTypeExtendedEchoRequest ICMPType = 160 // Extended Echo Request + ICMPTypeExtendedEchoReply ICMPType = 161 // Extended Echo Reply +) + +// Internet Control Message Protocol version 6 (ICMPv6) Parameters, Updated: 2018-03-09 +var icmpTypes = map[ICMPType]string{ + 1: "destination unreachable", + 2: "packet too big", + 3: "time exceeded", + 4: "parameter problem", + 128: "echo request", + 129: "echo reply", + 130: "multicast listener query", + 131: "multicast listener report", + 132: "multicast listener done", + 133: "router solicitation", + 134: "router advertisement", + 135: "neighbor solicitation", + 136: "neighbor advertisement", + 137: "redirect message", + 138: "router renumbering", + 139: "icmp node information query", + 140: "icmp node information response", + 141: "inverse neighbor discovery solicitation message", + 142: "inverse neighbor discovery advertisement message", + 143: "version 2 multicast listener report", + 144: "home agent address discovery request message", + 145: "home agent address discovery reply message", + 146: "mobile prefix solicitation", + 147: "mobile prefix advertisement", + 148: "certification path solicitation message", + 149: "certification path advertisement message", + 151: "multicast router advertisement", + 152: "multicast router solicitation", + 153: "multicast router termination", + 154: "fmipv6 messages", + 155: "rpl control message", + 156: "ilnpv6 locator update message", + 157: "duplicate address request", + 158: "duplicate address confirmation", + 159: "mpl control message", + 160: "extended echo request", + 161: "extended echo reply", +} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/icmp.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/icmp.go new file mode 100644 index 000000000..b7f48e27b --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/icmp.go @@ -0,0 +1,60 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ipv6 + +import "golang.org/x/net/internal/iana" + +// BUG(mikio): On Windows, methods related to ICMPFilter are not +// implemented. + +// An ICMPType represents a type of ICMP message. +type ICMPType int + +func (typ ICMPType) String() string { + s, ok := icmpTypes[typ] + if !ok { + return "" + } + return s +} + +// Protocol returns the ICMPv6 protocol number. +func (typ ICMPType) Protocol() int { + return iana.ProtocolIPv6ICMP +} + +// An ICMPFilter represents an ICMP message filter for incoming +// packets. The filter belongs to a packet delivery path on a host and +// it cannot interact with forwarding packets or tunnel-outer packets. +// +// Note: RFC 8200 defines a reasonable role model. A node means a +// device that implements IP. A router means a node that forwards IP +// packets not explicitly addressed to itself, and a host means a node +// that is not a router. +type ICMPFilter struct { + icmpv6Filter +} + +// Accept accepts incoming ICMP packets including the type field value +// typ. +func (f *ICMPFilter) Accept(typ ICMPType) { + f.accept(typ) +} + +// Block blocks incoming ICMP packets including the type field value +// typ. +func (f *ICMPFilter) Block(typ ICMPType) { + f.block(typ) +} + +// SetAll sets the filter action to the filter. +func (f *ICMPFilter) SetAll(block bool) { + f.setAll(block) +} + +// WillBlock reports whether the ICMP type will be blocked. +func (f *ICMPFilter) WillBlock(typ ICMPType) bool { + return f.willBlock(typ) +} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/icmp_bsd.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/icmp_bsd.go new file mode 100644 index 000000000..2814534a0 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/icmp_bsd.go @@ -0,0 +1,29 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build aix || darwin || dragonfly || freebsd || netbsd || openbsd + +package ipv6 + +func (f *icmpv6Filter) accept(typ ICMPType) { + f.Filt[typ>>5] |= 1 << (uint32(typ) & 31) +} + +func (f *icmpv6Filter) block(typ ICMPType) { + f.Filt[typ>>5] &^= 1 << (uint32(typ) & 31) +} + +func (f *icmpv6Filter) setAll(block bool) { + for i := range f.Filt { + if block { + f.Filt[i] = 0 + } else { + f.Filt[i] = 1<<32 - 1 + } + } +} + +func (f *icmpv6Filter) willBlock(typ ICMPType) bool { + return f.Filt[typ>>5]&(1<<(uint32(typ)&31)) == 0 +} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/icmp_linux.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/icmp_linux.go new file mode 100644 index 000000000..647f6b44f --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/icmp_linux.go @@ -0,0 +1,27 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ipv6 + +func (f *icmpv6Filter) accept(typ ICMPType) { + f.Data[typ>>5] &^= 1 << (uint32(typ) & 31) +} + +func (f *icmpv6Filter) block(typ ICMPType) { + f.Data[typ>>5] |= 1 << (uint32(typ) & 31) +} + +func (f *icmpv6Filter) setAll(block bool) { + for i := range f.Data { + if block { + f.Data[i] = 1<<32 - 1 + } else { + f.Data[i] = 0 + } + } +} + +func (f *icmpv6Filter) willBlock(typ ICMPType) bool { + return f.Data[typ>>5]&(1<<(uint32(typ)&31)) != 0 +} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/icmp_solaris.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/icmp_solaris.go new file mode 100644 index 000000000..7c23bb1cf --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/icmp_solaris.go @@ -0,0 +1,27 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ipv6 + +func (f *icmpv6Filter) accept(typ ICMPType) { + f.X__icmp6_filt[typ>>5] |= 1 << (uint32(typ) & 31) +} + +func (f *icmpv6Filter) block(typ ICMPType) { + f.X__icmp6_filt[typ>>5] &^= 1 << (uint32(typ) & 31) +} + +func (f *icmpv6Filter) setAll(block bool) { + for i := range f.X__icmp6_filt { + if block { + f.X__icmp6_filt[i] = 0 + } else { + f.X__icmp6_filt[i] = 1<<32 - 1 + } + } +} + +func (f *icmpv6Filter) willBlock(typ ICMPType) bool { + return f.X__icmp6_filt[typ>>5]&(1<<(uint32(typ)&31)) == 0 +} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/icmp_stub.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/icmp_stub.go new file mode 100644 index 000000000..c92c9b51e --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/icmp_stub.go @@ -0,0 +1,23 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !aix && !darwin && !dragonfly && !freebsd && !linux && !netbsd && !openbsd && !solaris && !windows && !zos + +package ipv6 + +type icmpv6Filter struct { +} + +func (f *icmpv6Filter) accept(typ ICMPType) { +} + +func (f *icmpv6Filter) block(typ ICMPType) { +} + +func (f *icmpv6Filter) setAll(block bool) { +} + +func (f *icmpv6Filter) willBlock(typ ICMPType) bool { + return false +} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/icmp_windows.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/icmp_windows.go new file mode 100644 index 000000000..443cd0736 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/icmp_windows.go @@ -0,0 +1,22 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ipv6 + +func (f *icmpv6Filter) accept(typ ICMPType) { + // TODO(mikio): implement this +} + +func (f *icmpv6Filter) block(typ ICMPType) { + // TODO(mikio): implement this +} + +func (f *icmpv6Filter) setAll(block bool) { + // TODO(mikio): implement this +} + +func (f *icmpv6Filter) willBlock(typ ICMPType) bool { + // TODO(mikio): implement this + return false +} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/icmp_zos.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/icmp_zos.go new file mode 100644 index 000000000..ddf8f093f --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/icmp_zos.go @@ -0,0 +1,29 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ipv6 + +func (f *icmpv6Filter) accept(typ ICMPType) { + f.Filt[typ>>5] |= 1 << (uint32(typ) & 31) + +} + +func (f *icmpv6Filter) block(typ ICMPType) { + f.Filt[typ>>5] &^= 1 << (uint32(typ) & 31) + +} + +func (f *icmpv6Filter) setAll(block bool) { + for i := range f.Filt { + if block { + f.Filt[i] = 0 + } else { + f.Filt[i] = 1<<32 - 1 + } + } +} + +func (f *icmpv6Filter) willBlock(typ ICMPType) bool { + return f.Filt[typ>>5]&(1<<(uint32(typ)&31)) == 0 +} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/payload.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/payload.go new file mode 100644 index 000000000..a8197f169 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/payload.go @@ -0,0 +1,23 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ipv6 + +import ( + "net" + + "golang.org/x/net/internal/socket" +) + +// BUG(mikio): On Windows, the ControlMessage for ReadFrom and WriteTo +// methods of PacketConn is not implemented. + +// A payloadHandler represents the IPv6 datagram payload handler. +type payloadHandler struct { + net.PacketConn + *socket.Conn + rawOpt +} + +func (c *payloadHandler) ok() bool { return c != nil && c.PacketConn != nil && c.Conn != nil } diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/payload_cmsg.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/payload_cmsg.go new file mode 100644 index 000000000..be04e4d6a --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/payload_cmsg.go @@ -0,0 +1,70 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos + +package ipv6 + +import ( + "net" + + "golang.org/x/net/internal/socket" +) + +// ReadFrom reads a payload of the received IPv6 datagram, from the +// endpoint c, copying the payload into b. It returns the number of +// bytes copied into b, the control message cm and the source address +// src of the received datagram. +func (c *payloadHandler) ReadFrom(b []byte) (n int, cm *ControlMessage, src net.Addr, err error) { + if !c.ok() { + return 0, nil, nil, errInvalidConn + } + c.rawOpt.RLock() + m := socket.Message{ + Buffers: [][]byte{b}, + OOB: NewControlMessage(c.rawOpt.cflags), + } + c.rawOpt.RUnlock() + switch c.PacketConn.(type) { + case *net.UDPConn: + if err := c.RecvMsg(&m, 0); err != nil { + return 0, nil, nil, &net.OpError{Op: "read", Net: c.PacketConn.LocalAddr().Network(), Source: c.PacketConn.LocalAddr(), Err: err} + } + case *net.IPConn: + if err := c.RecvMsg(&m, 0); err != nil { + return 0, nil, nil, &net.OpError{Op: "read", Net: c.PacketConn.LocalAddr().Network(), Source: c.PacketConn.LocalAddr(), Err: err} + } + default: + return 0, nil, nil, &net.OpError{Op: "read", Net: c.PacketConn.LocalAddr().Network(), Source: c.PacketConn.LocalAddr(), Err: errInvalidConnType} + } + if m.NN > 0 { + cm = new(ControlMessage) + if err := cm.Parse(m.OOB[:m.NN]); err != nil { + return 0, nil, nil, &net.OpError{Op: "read", Net: c.PacketConn.LocalAddr().Network(), Source: c.PacketConn.LocalAddr(), Err: err} + } + cm.Src = netAddrToIP16(m.Addr) + } + return m.N, cm, m.Addr, nil +} + +// WriteTo writes a payload of the IPv6 datagram, to the destination +// address dst through the endpoint c, copying the payload from b. It +// returns the number of bytes written. The control message cm allows +// the IPv6 header fields and the datagram path to be specified. The +// cm may be nil if control of the outgoing datagram is not required. +func (c *payloadHandler) WriteTo(b []byte, cm *ControlMessage, dst net.Addr) (n int, err error) { + if !c.ok() { + return 0, errInvalidConn + } + m := socket.Message{ + Buffers: [][]byte{b}, + OOB: cm.Marshal(), + Addr: dst, + } + err = c.SendMsg(&m, 0) + if err != nil { + err = &net.OpError{Op: "write", Net: c.PacketConn.LocalAddr().Network(), Source: c.PacketConn.LocalAddr(), Addr: opAddr(dst), Err: err} + } + return m.N, err +} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/payload_nocmsg.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/payload_nocmsg.go new file mode 100644 index 000000000..29b9ccf69 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/payload_nocmsg.go @@ -0,0 +1,38 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !aix && !darwin && !dragonfly && !freebsd && !linux && !netbsd && !openbsd && !solaris && !zos + +package ipv6 + +import "net" + +// ReadFrom reads a payload of the received IPv6 datagram, from the +// endpoint c, copying the payload into b. It returns the number of +// bytes copied into b, the control message cm and the source address +// src of the received datagram. +func (c *payloadHandler) ReadFrom(b []byte) (n int, cm *ControlMessage, src net.Addr, err error) { + if !c.ok() { + return 0, nil, nil, errInvalidConn + } + if n, src, err = c.PacketConn.ReadFrom(b); err != nil { + return 0, nil, nil, err + } + return +} + +// WriteTo writes a payload of the IPv6 datagram, to the destination +// address dst through the endpoint c, copying the payload from b. It +// returns the number of bytes written. The control message cm allows +// the IPv6 header fields and the datagram path to be specified. The +// cm may be nil if control of the outgoing datagram is not required. +func (c *payloadHandler) WriteTo(b []byte, cm *ControlMessage, dst net.Addr) (n int, err error) { + if !c.ok() { + return 0, errInvalidConn + } + if dst == nil { + return 0, errMissingAddress + } + return c.PacketConn.WriteTo(b, dst) +} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/sockopt.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/sockopt.go new file mode 100644 index 000000000..cc3907df3 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/sockopt.go @@ -0,0 +1,43 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ipv6 + +import "golang.org/x/net/internal/socket" + +// Sticky socket options +const ( + ssoTrafficClass = iota // header field for unicast packet, RFC 3542 + ssoHopLimit // header field for unicast packet, RFC 3493 + ssoMulticastInterface // outbound interface for multicast packet, RFC 3493 + ssoMulticastHopLimit // header field for multicast packet, RFC 3493 + ssoMulticastLoopback // loopback for multicast packet, RFC 3493 + ssoReceiveTrafficClass // header field on received packet, RFC 3542 + ssoReceiveHopLimit // header field on received packet, RFC 2292 or 3542 + ssoReceivePacketInfo // incbound or outbound packet path, RFC 2292 or 3542 + ssoReceivePathMTU // path mtu, RFC 3542 + ssoPathMTU // path mtu, RFC 3542 + ssoChecksum // packet checksum, RFC 2292 or 3542 + ssoICMPFilter // icmp filter, RFC 2292 or 3542 + ssoJoinGroup // any-source multicast, RFC 3493 + ssoLeaveGroup // any-source multicast, RFC 3493 + ssoJoinSourceGroup // source-specific multicast + ssoLeaveSourceGroup // source-specific multicast + ssoBlockSourceGroup // any-source or source-specific multicast + ssoUnblockSourceGroup // any-source or source-specific multicast + ssoAttachFilter // attach BPF for filtering inbound traffic +) + +// Sticky socket option value types +const ( + ssoTypeIPMreq = iota + 1 + ssoTypeGroupReq + ssoTypeGroupSourceReq +) + +// A sockOpt represents a binding for sticky socket option. +type sockOpt struct { + socket.Option + typ int // hint for option value type; optional +} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/sockopt_posix.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/sockopt_posix.go new file mode 100644 index 000000000..34dfed588 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/sockopt_posix.go @@ -0,0 +1,89 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || windows || zos + +package ipv6 + +import ( + "net" + "runtime" + "unsafe" + + "golang.org/x/net/bpf" + "golang.org/x/net/internal/socket" +) + +func (so *sockOpt) getMulticastInterface(c *socket.Conn) (*net.Interface, error) { + n, err := so.GetInt(c) + if err != nil { + return nil, err + } + return net.InterfaceByIndex(n) +} + +func (so *sockOpt) setMulticastInterface(c *socket.Conn, ifi *net.Interface) error { + var n int + if ifi != nil { + n = ifi.Index + } + return so.SetInt(c, n) +} + +func (so *sockOpt) getICMPFilter(c *socket.Conn) (*ICMPFilter, error) { + b := make([]byte, so.Len) + n, err := so.Get(c, b) + if err != nil { + return nil, err + } + if n != sizeofICMPv6Filter { + return nil, errNotImplemented + } + return (*ICMPFilter)(unsafe.Pointer(&b[0])), nil +} + +func (so *sockOpt) setICMPFilter(c *socket.Conn, f *ICMPFilter) error { + b := (*[sizeofICMPv6Filter]byte)(unsafe.Pointer(f))[:sizeofICMPv6Filter] + return so.Set(c, b) +} + +func (so *sockOpt) getMTUInfo(c *socket.Conn) (*net.Interface, int, error) { + b := make([]byte, so.Len) + n, err := so.Get(c, b) + if err != nil { + return nil, 0, err + } + if n != sizeofIPv6Mtuinfo { + return nil, 0, errNotImplemented + } + mi := (*ipv6Mtuinfo)(unsafe.Pointer(&b[0])) + if mi.Addr.Scope_id == 0 || runtime.GOOS == "aix" { + // AIX kernel might return a wrong address. + return nil, int(mi.Mtu), nil + } + ifi, err := net.InterfaceByIndex(int(mi.Addr.Scope_id)) + if err != nil { + return nil, 0, err + } + return ifi, int(mi.Mtu), nil +} + +func (so *sockOpt) setGroup(c *socket.Conn, ifi *net.Interface, grp net.IP) error { + switch so.typ { + case ssoTypeIPMreq: + return so.setIPMreq(c, ifi, grp) + case ssoTypeGroupReq: + return so.setGroupReq(c, ifi, grp) + default: + return errNotImplemented + } +} + +func (so *sockOpt) setSourceGroup(c *socket.Conn, ifi *net.Interface, grp, src net.IP) error { + return so.setGroupSourceReq(c, ifi, grp, src) +} + +func (so *sockOpt) setBPF(c *socket.Conn, f []bpf.RawInstruction) error { + return so.setAttachFilter(c, f) +} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/sockopt_stub.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/sockopt_stub.go new file mode 100644 index 000000000..a09c3aaf2 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/sockopt_stub.go @@ -0,0 +1,46 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !aix && !darwin && !dragonfly && !freebsd && !linux && !netbsd && !openbsd && !solaris && !windows && !zos + +package ipv6 + +import ( + "net" + + "golang.org/x/net/bpf" + "golang.org/x/net/internal/socket" +) + +func (so *sockOpt) getMulticastInterface(c *socket.Conn) (*net.Interface, error) { + return nil, errNotImplemented +} + +func (so *sockOpt) setMulticastInterface(c *socket.Conn, ifi *net.Interface) error { + return errNotImplemented +} + +func (so *sockOpt) getICMPFilter(c *socket.Conn) (*ICMPFilter, error) { + return nil, errNotImplemented +} + +func (so *sockOpt) setICMPFilter(c *socket.Conn, f *ICMPFilter) error { + return errNotImplemented +} + +func (so *sockOpt) getMTUInfo(c *socket.Conn) (*net.Interface, int, error) { + return nil, 0, errNotImplemented +} + +func (so *sockOpt) setGroup(c *socket.Conn, ifi *net.Interface, grp net.IP) error { + return errNotImplemented +} + +func (so *sockOpt) setSourceGroup(c *socket.Conn, ifi *net.Interface, grp, src net.IP) error { + return errNotImplemented +} + +func (so *sockOpt) setBPF(c *socket.Conn, f []bpf.RawInstruction) error { + return errNotImplemented +} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/sys_aix.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/sys_aix.go new file mode 100644 index 000000000..93c8efc46 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/sys_aix.go @@ -0,0 +1,79 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Added for go1.11 compatibility +//go:build aix + +package ipv6 + +import ( + "net" + "syscall" + "unsafe" + + "golang.org/x/net/internal/iana" + "golang.org/x/net/internal/socket" + + "golang.org/x/sys/unix" +) + +var ( + ctlOpts = [ctlMax]ctlOpt{ + ctlTrafficClass: {unix.IPV6_TCLASS, 4, marshalTrafficClass, parseTrafficClass}, + ctlHopLimit: {unix.IPV6_HOPLIMIT, 4, marshalHopLimit, parseHopLimit}, + ctlPacketInfo: {unix.IPV6_PKTINFO, sizeofInet6Pktinfo, marshalPacketInfo, parsePacketInfo}, + ctlNextHop: {unix.IPV6_NEXTHOP, sizeofSockaddrInet6, marshalNextHop, parseNextHop}, + ctlPathMTU: {unix.IPV6_PATHMTU, sizeofIPv6Mtuinfo, marshalPathMTU, parsePathMTU}, + } + + sockOpts = map[int]*sockOpt{ + ssoTrafficClass: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.IPV6_TCLASS, Len: 4}}, + ssoHopLimit: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.IPV6_UNICAST_HOPS, Len: 4}}, + ssoMulticastInterface: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.IPV6_MULTICAST_IF, Len: 4}}, + ssoMulticastHopLimit: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.IPV6_MULTICAST_HOPS, Len: 4}}, + ssoMulticastLoopback: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.IPV6_MULTICAST_LOOP, Len: 4}}, + ssoReceiveTrafficClass: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.IPV6_RECVTCLASS, Len: 4}}, + ssoReceiveHopLimit: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.IPV6_RECVHOPLIMIT, Len: 4}}, + ssoReceivePacketInfo: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.IPV6_RECVPKTINFO, Len: 4}}, + ssoReceivePathMTU: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.IPV6_RECVPATHMTU, Len: 4}}, + ssoPathMTU: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.IPV6_PATHMTU, Len: sizeofIPv6Mtuinfo}}, + ssoChecksum: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.IPV6_CHECKSUM, Len: 4}}, + ssoICMPFilter: {Option: socket.Option{Level: iana.ProtocolIPv6ICMP, Name: unix.ICMP6_FILTER, Len: sizeofICMPv6Filter}}, + ssoJoinGroup: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.IPV6_JOIN_GROUP, Len: sizeofIPv6Mreq}, typ: ssoTypeIPMreq}, + ssoLeaveGroup: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.IPV6_LEAVE_GROUP, Len: sizeofIPv6Mreq}, typ: ssoTypeIPMreq}, + } +) + +func (sa *sockaddrInet6) setSockaddr(ip net.IP, i int) { + sa.Len = sizeofSockaddrInet6 + sa.Family = syscall.AF_INET6 + copy(sa.Addr[:], ip) + sa.Scope_id = uint32(i) +} + +func (pi *inet6Pktinfo) setIfindex(i int) { + pi.Ifindex = int32(i) +} + +func (mreq *ipv6Mreq) setIfindex(i int) { + mreq.Interface = uint32(i) +} + +func (gr *groupReq) setGroup(grp net.IP) { + sa := (*sockaddrInet6)(unsafe.Pointer(uintptr(unsafe.Pointer(gr)) + 4)) + sa.Len = sizeofSockaddrInet6 + sa.Family = syscall.AF_INET6 + copy(sa.Addr[:], grp) +} + +func (gsr *groupSourceReq) setSourceGroup(grp, src net.IP) { + sa := (*sockaddrInet6)(unsafe.Pointer(uintptr(unsafe.Pointer(gsr)) + 4)) + sa.Len = sizeofSockaddrInet6 + sa.Family = syscall.AF_INET6 + copy(sa.Addr[:], grp) + sa = (*sockaddrInet6)(unsafe.Pointer(uintptr(unsafe.Pointer(gsr)) + 132)) + sa.Len = sizeofSockaddrInet6 + sa.Family = syscall.AF_INET6 + copy(sa.Addr[:], src) +} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/sys_asmreq.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/sys_asmreq.go new file mode 100644 index 000000000..5c9cb4447 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/sys_asmreq.go @@ -0,0 +1,24 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || windows + +package ipv6 + +import ( + "net" + "unsafe" + + "golang.org/x/net/internal/socket" +) + +func (so *sockOpt) setIPMreq(c *socket.Conn, ifi *net.Interface, grp net.IP) error { + var mreq ipv6Mreq + copy(mreq.Multiaddr[:], grp) + if ifi != nil { + mreq.setIfindex(ifi.Index) + } + b := (*[sizeofIPv6Mreq]byte)(unsafe.Pointer(&mreq))[:sizeofIPv6Mreq] + return so.Set(c, b) +} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/sys_asmreq_stub.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/sys_asmreq_stub.go new file mode 100644 index 000000000..dc7049468 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/sys_asmreq_stub.go @@ -0,0 +1,17 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !aix && !darwin && !dragonfly && !freebsd && !linux && !netbsd && !openbsd && !solaris && !windows + +package ipv6 + +import ( + "net" + + "golang.org/x/net/internal/socket" +) + +func (so *sockOpt) setIPMreq(c *socket.Conn, ifi *net.Interface, grp net.IP) error { + return errNotImplemented +} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/sys_bpf.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/sys_bpf.go new file mode 100644 index 000000000..e39f75f49 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/sys_bpf.go @@ -0,0 +1,24 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build linux + +package ipv6 + +import ( + "unsafe" + + "golang.org/x/net/bpf" + "golang.org/x/net/internal/socket" + "golang.org/x/sys/unix" +) + +func (so *sockOpt) setAttachFilter(c *socket.Conn, f []bpf.RawInstruction) error { + prog := unix.SockFprog{ + Len: uint16(len(f)), + Filter: (*unix.SockFilter)(unsafe.Pointer(&f[0])), + } + b := (*[unix.SizeofSockFprog]byte)(unsafe.Pointer(&prog))[:unix.SizeofSockFprog] + return so.Set(c, b) +} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/sys_bpf_stub.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/sys_bpf_stub.go new file mode 100644 index 000000000..8532a8f5d --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/sys_bpf_stub.go @@ -0,0 +1,16 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !linux + +package ipv6 + +import ( + "golang.org/x/net/bpf" + "golang.org/x/net/internal/socket" +) + +func (so *sockOpt) setAttachFilter(c *socket.Conn, f []bpf.RawInstruction) error { + return errNotImplemented +} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/sys_bsd.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/sys_bsd.go new file mode 100644 index 000000000..9f3bc2afd --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/sys_bsd.go @@ -0,0 +1,59 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build dragonfly || netbsd || openbsd + +package ipv6 + +import ( + "net" + "syscall" + + "golang.org/x/net/internal/iana" + "golang.org/x/net/internal/socket" + + "golang.org/x/sys/unix" +) + +var ( + ctlOpts = [ctlMax]ctlOpt{ + ctlTrafficClass: {unix.IPV6_TCLASS, 4, marshalTrafficClass, parseTrafficClass}, + ctlHopLimit: {unix.IPV6_HOPLIMIT, 4, marshalHopLimit, parseHopLimit}, + ctlPacketInfo: {unix.IPV6_PKTINFO, sizeofInet6Pktinfo, marshalPacketInfo, parsePacketInfo}, + ctlNextHop: {unix.IPV6_NEXTHOP, sizeofSockaddrInet6, marshalNextHop, parseNextHop}, + ctlPathMTU: {unix.IPV6_PATHMTU, sizeofIPv6Mtuinfo, marshalPathMTU, parsePathMTU}, + } + + sockOpts = map[int]*sockOpt{ + ssoTrafficClass: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.IPV6_TCLASS, Len: 4}}, + ssoHopLimit: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.IPV6_UNICAST_HOPS, Len: 4}}, + ssoMulticastInterface: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.IPV6_MULTICAST_IF, Len: 4}}, + ssoMulticastHopLimit: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.IPV6_MULTICAST_HOPS, Len: 4}}, + ssoMulticastLoopback: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.IPV6_MULTICAST_LOOP, Len: 4}}, + ssoReceiveTrafficClass: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.IPV6_RECVTCLASS, Len: 4}}, + ssoReceiveHopLimit: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.IPV6_RECVHOPLIMIT, Len: 4}}, + ssoReceivePacketInfo: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.IPV6_RECVPKTINFO, Len: 4}}, + ssoReceivePathMTU: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.IPV6_RECVPATHMTU, Len: 4}}, + ssoPathMTU: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.IPV6_PATHMTU, Len: sizeofIPv6Mtuinfo}}, + ssoChecksum: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.IPV6_CHECKSUM, Len: 4}}, + ssoICMPFilter: {Option: socket.Option{Level: iana.ProtocolIPv6ICMP, Name: unix.ICMP6_FILTER, Len: sizeofICMPv6Filter}}, + ssoJoinGroup: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.IPV6_JOIN_GROUP, Len: sizeofIPv6Mreq}, typ: ssoTypeIPMreq}, + ssoLeaveGroup: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.IPV6_LEAVE_GROUP, Len: sizeofIPv6Mreq}, typ: ssoTypeIPMreq}, + } +) + +func (sa *sockaddrInet6) setSockaddr(ip net.IP, i int) { + sa.Len = sizeofSockaddrInet6 + sa.Family = syscall.AF_INET6 + copy(sa.Addr[:], ip) + sa.Scope_id = uint32(i) +} + +func (pi *inet6Pktinfo) setIfindex(i int) { + pi.Ifindex = uint32(i) +} + +func (mreq *ipv6Mreq) setIfindex(i int) { + mreq.Interface = uint32(i) +} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/sys_darwin.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/sys_darwin.go new file mode 100644 index 000000000..b80ec8064 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/sys_darwin.go @@ -0,0 +1,80 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ipv6 + +import ( + "net" + "syscall" + "unsafe" + + "golang.org/x/net/internal/iana" + "golang.org/x/net/internal/socket" + + "golang.org/x/sys/unix" +) + +var ( + ctlOpts = [ctlMax]ctlOpt{ + ctlTrafficClass: {unix.IPV6_TCLASS, 4, marshalTrafficClass, parseTrafficClass}, + ctlHopLimit: {unix.IPV6_HOPLIMIT, 4, marshalHopLimit, parseHopLimit}, + ctlPacketInfo: {unix.IPV6_PKTINFO, sizeofInet6Pktinfo, marshalPacketInfo, parsePacketInfo}, + ctlNextHop: {unix.IPV6_NEXTHOP, sizeofSockaddrInet6, marshalNextHop, parseNextHop}, + ctlPathMTU: {unix.IPV6_PATHMTU, sizeofIPv6Mtuinfo, marshalPathMTU, parsePathMTU}, + } + + sockOpts = map[int]*sockOpt{ + ssoHopLimit: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.IPV6_UNICAST_HOPS, Len: 4}}, + ssoMulticastInterface: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.IPV6_MULTICAST_IF, Len: 4}}, + ssoMulticastHopLimit: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.IPV6_MULTICAST_HOPS, Len: 4}}, + ssoMulticastLoopback: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.IPV6_MULTICAST_LOOP, Len: 4}}, + ssoTrafficClass: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.IPV6_TCLASS, Len: 4}}, + ssoReceiveTrafficClass: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.IPV6_RECVTCLASS, Len: 4}}, + ssoReceiveHopLimit: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.IPV6_RECVHOPLIMIT, Len: 4}}, + ssoReceivePacketInfo: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.IPV6_RECVPKTINFO, Len: 4}}, + ssoReceivePathMTU: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.IPV6_RECVPATHMTU, Len: 4}}, + ssoPathMTU: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.IPV6_PATHMTU, Len: sizeofIPv6Mtuinfo}}, + ssoChecksum: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.IPV6_CHECKSUM, Len: 4}}, + ssoICMPFilter: {Option: socket.Option{Level: iana.ProtocolIPv6ICMP, Name: unix.ICMP6_FILTER, Len: sizeofICMPv6Filter}}, + ssoJoinGroup: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.MCAST_JOIN_GROUP, Len: sizeofGroupReq}, typ: ssoTypeGroupReq}, + ssoLeaveGroup: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.MCAST_LEAVE_GROUP, Len: sizeofGroupReq}, typ: ssoTypeGroupReq}, + ssoJoinSourceGroup: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.MCAST_JOIN_SOURCE_GROUP, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq}, + ssoLeaveSourceGroup: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.MCAST_LEAVE_SOURCE_GROUP, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq}, + ssoBlockSourceGroup: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.MCAST_BLOCK_SOURCE, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq}, + ssoUnblockSourceGroup: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.MCAST_UNBLOCK_SOURCE, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq}, + } +) + +func (sa *sockaddrInet6) setSockaddr(ip net.IP, i int) { + sa.Len = sizeofSockaddrInet6 + sa.Family = syscall.AF_INET6 + copy(sa.Addr[:], ip) + sa.Scope_id = uint32(i) +} + +func (pi *inet6Pktinfo) setIfindex(i int) { + pi.Ifindex = uint32(i) +} + +func (mreq *ipv6Mreq) setIfindex(i int) { + mreq.Interface = uint32(i) +} + +func (gr *groupReq) setGroup(grp net.IP) { + sa := (*sockaddrInet6)(unsafe.Pointer(uintptr(unsafe.Pointer(gr)) + 4)) + sa.Len = sizeofSockaddrInet6 + sa.Family = syscall.AF_INET6 + copy(sa.Addr[:], grp) +} + +func (gsr *groupSourceReq) setSourceGroup(grp, src net.IP) { + sa := (*sockaddrInet6)(unsafe.Pointer(uintptr(unsafe.Pointer(gsr)) + 4)) + sa.Len = sizeofSockaddrInet6 + sa.Family = syscall.AF_INET6 + copy(sa.Addr[:], grp) + sa = (*sockaddrInet6)(unsafe.Pointer(uintptr(unsafe.Pointer(gsr)) + 132)) + sa.Len = sizeofSockaddrInet6 + sa.Family = syscall.AF_INET6 + copy(sa.Addr[:], src) +} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/sys_freebsd.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/sys_freebsd.go new file mode 100644 index 000000000..6282cf977 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/sys_freebsd.go @@ -0,0 +1,94 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ipv6 + +import ( + "net" + "runtime" + "strings" + "syscall" + "unsafe" + + "golang.org/x/net/internal/iana" + "golang.org/x/net/internal/socket" + + "golang.org/x/sys/unix" +) + +var ( + ctlOpts = [ctlMax]ctlOpt{ + ctlTrafficClass: {unix.IPV6_TCLASS, 4, marshalTrafficClass, parseTrafficClass}, + ctlHopLimit: {unix.IPV6_HOPLIMIT, 4, marshalHopLimit, parseHopLimit}, + ctlPacketInfo: {unix.IPV6_PKTINFO, sizeofInet6Pktinfo, marshalPacketInfo, parsePacketInfo}, + ctlNextHop: {unix.IPV6_NEXTHOP, sizeofSockaddrInet6, marshalNextHop, parseNextHop}, + ctlPathMTU: {unix.IPV6_PATHMTU, sizeofIPv6Mtuinfo, marshalPathMTU, parsePathMTU}, + } + + sockOpts = map[int]sockOpt{ + ssoTrafficClass: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.IPV6_TCLASS, Len: 4}}, + ssoHopLimit: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.IPV6_UNICAST_HOPS, Len: 4}}, + ssoMulticastInterface: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.IPV6_MULTICAST_IF, Len: 4}}, + ssoMulticastHopLimit: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.IPV6_MULTICAST_HOPS, Len: 4}}, + ssoMulticastLoopback: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.IPV6_MULTICAST_LOOP, Len: 4}}, + ssoReceiveTrafficClass: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.IPV6_RECVTCLASS, Len: 4}}, + ssoReceiveHopLimit: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.IPV6_RECVHOPLIMIT, Len: 4}}, + ssoReceivePacketInfo: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.IPV6_RECVPKTINFO, Len: 4}}, + ssoReceivePathMTU: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.IPV6_RECVPATHMTU, Len: 4}}, + ssoPathMTU: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.IPV6_PATHMTU, Len: sizeofIPv6Mtuinfo}}, + ssoChecksum: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.IPV6_CHECKSUM, Len: 4}}, + ssoICMPFilter: {Option: socket.Option{Level: iana.ProtocolIPv6ICMP, Name: unix.ICMP6_FILTER, Len: sizeofICMPv6Filter}}, + ssoJoinGroup: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.MCAST_JOIN_GROUP, Len: sizeofGroupReq}, typ: ssoTypeGroupReq}, + ssoLeaveGroup: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.MCAST_LEAVE_GROUP, Len: sizeofGroupReq}, typ: ssoTypeGroupReq}, + ssoJoinSourceGroup: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.MCAST_JOIN_SOURCE_GROUP, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq}, + ssoLeaveSourceGroup: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.MCAST_LEAVE_SOURCE_GROUP, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq}, + ssoBlockSourceGroup: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.MCAST_BLOCK_SOURCE, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq}, + ssoUnblockSourceGroup: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.MCAST_UNBLOCK_SOURCE, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq}, + } +) + +func init() { + if runtime.GOOS == "freebsd" && runtime.GOARCH == "386" { + archs, _ := syscall.Sysctl("kern.supported_archs") + for _, s := range strings.Fields(archs) { + if s == "amd64" { + compatFreeBSD32 = true + break + } + } + } +} + +func (sa *sockaddrInet6) setSockaddr(ip net.IP, i int) { + sa.Len = sizeofSockaddrInet6 + sa.Family = syscall.AF_INET6 + copy(sa.Addr[:], ip) + sa.Scope_id = uint32(i) +} + +func (pi *inet6Pktinfo) setIfindex(i int) { + pi.Ifindex = uint32(i) +} + +func (mreq *ipv6Mreq) setIfindex(i int) { + mreq.Interface = uint32(i) +} + +func (gr *groupReq) setGroup(grp net.IP) { + sa := (*sockaddrInet6)(unsafe.Pointer(&gr.Group)) + sa.Len = sizeofSockaddrInet6 + sa.Family = syscall.AF_INET6 + copy(sa.Addr[:], grp) +} + +func (gsr *groupSourceReq) setSourceGroup(grp, src net.IP) { + sa := (*sockaddrInet6)(unsafe.Pointer(&gsr.Group)) + sa.Len = sizeofSockaddrInet6 + sa.Family = syscall.AF_INET6 + copy(sa.Addr[:], grp) + sa = (*sockaddrInet6)(unsafe.Pointer(&gsr.Source)) + sa.Len = sizeofSockaddrInet6 + sa.Family = syscall.AF_INET6 + copy(sa.Addr[:], src) +} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/sys_linux.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/sys_linux.go new file mode 100644 index 000000000..82e212100 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/sys_linux.go @@ -0,0 +1,76 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ipv6 + +import ( + "net" + "syscall" + "unsafe" + + "golang.org/x/net/internal/iana" + "golang.org/x/net/internal/socket" + + "golang.org/x/sys/unix" +) + +var ( + ctlOpts = [ctlMax]ctlOpt{ + ctlTrafficClass: {unix.IPV6_TCLASS, 4, marshalTrafficClass, parseTrafficClass}, + ctlHopLimit: {unix.IPV6_HOPLIMIT, 4, marshalHopLimit, parseHopLimit}, + ctlPacketInfo: {unix.IPV6_PKTINFO, sizeofInet6Pktinfo, marshalPacketInfo, parsePacketInfo}, + ctlPathMTU: {unix.IPV6_PATHMTU, sizeofIPv6Mtuinfo, marshalPathMTU, parsePathMTU}, + } + + sockOpts = map[int]*sockOpt{ + ssoTrafficClass: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.IPV6_TCLASS, Len: 4}}, + ssoHopLimit: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.IPV6_UNICAST_HOPS, Len: 4}}, + ssoMulticastInterface: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.IPV6_MULTICAST_IF, Len: 4}}, + ssoMulticastHopLimit: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.IPV6_MULTICAST_HOPS, Len: 4}}, + ssoMulticastLoopback: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.IPV6_MULTICAST_LOOP, Len: 4}}, + ssoReceiveTrafficClass: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.IPV6_RECVTCLASS, Len: 4}}, + ssoReceiveHopLimit: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.IPV6_RECVHOPLIMIT, Len: 4}}, + ssoReceivePacketInfo: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.IPV6_RECVPKTINFO, Len: 4}}, + ssoReceivePathMTU: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.IPV6_RECVPATHMTU, Len: 4}}, + ssoPathMTU: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.IPV6_PATHMTU, Len: sizeofIPv6Mtuinfo}}, + ssoChecksum: {Option: socket.Option{Level: iana.ProtocolReserved, Name: unix.IPV6_CHECKSUM, Len: 4}}, + ssoICMPFilter: {Option: socket.Option{Level: iana.ProtocolIPv6ICMP, Name: unix.ICMPV6_FILTER, Len: sizeofICMPv6Filter}}, + ssoJoinGroup: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.MCAST_JOIN_GROUP, Len: sizeofGroupReq}, typ: ssoTypeGroupReq}, + ssoLeaveGroup: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.MCAST_LEAVE_GROUP, Len: sizeofGroupReq}, typ: ssoTypeGroupReq}, + ssoJoinSourceGroup: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.MCAST_JOIN_SOURCE_GROUP, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq}, + ssoLeaveSourceGroup: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.MCAST_LEAVE_SOURCE_GROUP, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq}, + ssoBlockSourceGroup: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.MCAST_BLOCK_SOURCE, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq}, + ssoUnblockSourceGroup: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.MCAST_UNBLOCK_SOURCE, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq}, + ssoAttachFilter: {Option: socket.Option{Level: unix.SOL_SOCKET, Name: unix.SO_ATTACH_FILTER, Len: unix.SizeofSockFprog}}, + } +) + +func (sa *sockaddrInet6) setSockaddr(ip net.IP, i int) { + sa.Family = syscall.AF_INET6 + copy(sa.Addr[:], ip) + sa.Scope_id = uint32(i) +} + +func (pi *inet6Pktinfo) setIfindex(i int) { + pi.Ifindex = int32(i) +} + +func (mreq *ipv6Mreq) setIfindex(i int) { + mreq.Ifindex = int32(i) +} + +func (gr *groupReq) setGroup(grp net.IP) { + sa := (*sockaddrInet6)(unsafe.Pointer(&gr.Group)) + sa.Family = syscall.AF_INET6 + copy(sa.Addr[:], grp) +} + +func (gsr *groupSourceReq) setSourceGroup(grp, src net.IP) { + sa := (*sockaddrInet6)(unsafe.Pointer(&gsr.Group)) + sa.Family = syscall.AF_INET6 + copy(sa.Addr[:], grp) + sa = (*sockaddrInet6)(unsafe.Pointer(&gsr.Source)) + sa.Family = syscall.AF_INET6 + copy(sa.Addr[:], src) +} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/sys_solaris.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/sys_solaris.go new file mode 100644 index 000000000..1fc30add4 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/sys_solaris.go @@ -0,0 +1,76 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ipv6 + +import ( + "net" + "syscall" + "unsafe" + + "golang.org/x/net/internal/iana" + "golang.org/x/net/internal/socket" + + "golang.org/x/sys/unix" +) + +var ( + ctlOpts = [ctlMax]ctlOpt{ + ctlTrafficClass: {unix.IPV6_TCLASS, 4, marshalTrafficClass, parseTrafficClass}, + ctlHopLimit: {unix.IPV6_HOPLIMIT, 4, marshalHopLimit, parseHopLimit}, + ctlPacketInfo: {unix.IPV6_PKTINFO, sizeofInet6Pktinfo, marshalPacketInfo, parsePacketInfo}, + ctlNextHop: {unix.IPV6_NEXTHOP, sizeofSockaddrInet6, marshalNextHop, parseNextHop}, + ctlPathMTU: {unix.IPV6_PATHMTU, sizeofIPv6Mtuinfo, marshalPathMTU, parsePathMTU}, + } + + sockOpts = map[int]*sockOpt{ + ssoTrafficClass: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.IPV6_TCLASS, Len: 4}}, + ssoHopLimit: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.IPV6_UNICAST_HOPS, Len: 4}}, + ssoMulticastInterface: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.IPV6_MULTICAST_IF, Len: 4}}, + ssoMulticastHopLimit: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.IPV6_MULTICAST_HOPS, Len: 4}}, + ssoMulticastLoopback: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.IPV6_MULTICAST_LOOP, Len: 4}}, + ssoReceiveTrafficClass: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.IPV6_RECVTCLASS, Len: 4}}, + ssoReceiveHopLimit: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.IPV6_RECVHOPLIMIT, Len: 4}}, + ssoReceivePacketInfo: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.IPV6_RECVPKTINFO, Len: 4}}, + ssoReceivePathMTU: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.IPV6_RECVPATHMTU, Len: 4}}, + ssoPathMTU: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.IPV6_PATHMTU, Len: sizeofIPv6Mtuinfo}}, + ssoChecksum: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.IPV6_CHECKSUM, Len: 4}}, + ssoICMPFilter: {Option: socket.Option{Level: iana.ProtocolIPv6ICMP, Name: unix.ICMP6_FILTER, Len: sizeofICMPv6Filter}}, + ssoJoinGroup: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.MCAST_JOIN_GROUP, Len: sizeofGroupReq}, typ: ssoTypeGroupReq}, + ssoLeaveGroup: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.MCAST_LEAVE_GROUP, Len: sizeofGroupReq}, typ: ssoTypeGroupReq}, + ssoJoinSourceGroup: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.MCAST_JOIN_SOURCE_GROUP, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq}, + ssoLeaveSourceGroup: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.MCAST_LEAVE_SOURCE_GROUP, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq}, + ssoBlockSourceGroup: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.MCAST_BLOCK_SOURCE, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq}, + ssoUnblockSourceGroup: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.MCAST_UNBLOCK_SOURCE, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq}, + } +) + +func (sa *sockaddrInet6) setSockaddr(ip net.IP, i int) { + sa.Family = syscall.AF_INET6 + copy(sa.Addr[:], ip) + sa.Scope_id = uint32(i) +} + +func (pi *inet6Pktinfo) setIfindex(i int) { + pi.Ifindex = uint32(i) +} + +func (mreq *ipv6Mreq) setIfindex(i int) { + mreq.Interface = uint32(i) +} + +func (gr *groupReq) setGroup(grp net.IP) { + sa := (*sockaddrInet6)(unsafe.Pointer(uintptr(unsafe.Pointer(gr)) + 4)) + sa.Family = syscall.AF_INET6 + copy(sa.Addr[:], grp) +} + +func (gsr *groupSourceReq) setSourceGroup(grp, src net.IP) { + sa := (*sockaddrInet6)(unsafe.Pointer(uintptr(unsafe.Pointer(gsr)) + 4)) + sa.Family = syscall.AF_INET6 + copy(sa.Addr[:], grp) + sa = (*sockaddrInet6)(unsafe.Pointer(uintptr(unsafe.Pointer(gsr)) + 260)) + sa.Family = syscall.AF_INET6 + copy(sa.Addr[:], src) +} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/sys_ssmreq.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/sys_ssmreq.go new file mode 100644 index 000000000..b40f5c685 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/sys_ssmreq.go @@ -0,0 +1,54 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build aix || darwin || freebsd || linux || solaris || zos + +package ipv6 + +import ( + "net" + "unsafe" + + "golang.org/x/net/internal/socket" +) + +var compatFreeBSD32 bool // 386 emulation on amd64 + +func (so *sockOpt) setGroupReq(c *socket.Conn, ifi *net.Interface, grp net.IP) error { + var gr groupReq + if ifi != nil { + gr.Interface = uint32(ifi.Index) + } + gr.setGroup(grp) + var b []byte + if compatFreeBSD32 { + var d [sizeofGroupReq + 4]byte + s := (*[sizeofGroupReq]byte)(unsafe.Pointer(&gr)) + copy(d[:4], s[:4]) + copy(d[8:], s[4:]) + b = d[:] + } else { + b = (*[sizeofGroupReq]byte)(unsafe.Pointer(&gr))[:sizeofGroupReq] + } + return so.Set(c, b) +} + +func (so *sockOpt) setGroupSourceReq(c *socket.Conn, ifi *net.Interface, grp, src net.IP) error { + var gsr groupSourceReq + if ifi != nil { + gsr.Interface = uint32(ifi.Index) + } + gsr.setSourceGroup(grp, src) + var b []byte + if compatFreeBSD32 { + var d [sizeofGroupSourceReq + 4]byte + s := (*[sizeofGroupSourceReq]byte)(unsafe.Pointer(&gsr)) + copy(d[:4], s[:4]) + copy(d[8:], s[4:]) + b = d[:] + } else { + b = (*[sizeofGroupSourceReq]byte)(unsafe.Pointer(&gsr))[:sizeofGroupSourceReq] + } + return so.Set(c, b) +} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/sys_ssmreq_stub.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/sys_ssmreq_stub.go new file mode 100644 index 000000000..6526aad58 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/sys_ssmreq_stub.go @@ -0,0 +1,21 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !aix && !darwin && !freebsd && !linux && !solaris && !zos + +package ipv6 + +import ( + "net" + + "golang.org/x/net/internal/socket" +) + +func (so *sockOpt) setGroupReq(c *socket.Conn, ifi *net.Interface, grp net.IP) error { + return errNotImplemented +} + +func (so *sockOpt) setGroupSourceReq(c *socket.Conn, ifi *net.Interface, grp, src net.IP) error { + return errNotImplemented +} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/sys_stub.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/sys_stub.go new file mode 100644 index 000000000..76602c34e --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/sys_stub.go @@ -0,0 +1,13 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !aix && !darwin && !dragonfly && !freebsd && !linux && !netbsd && !openbsd && !solaris && !windows && !zos + +package ipv6 + +var ( + ctlOpts = [ctlMax]ctlOpt{} + + sockOpts = map[int]*sockOpt{} +) diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/sys_windows.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/sys_windows.go new file mode 100644 index 000000000..fda8a2994 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/sys_windows.go @@ -0,0 +1,68 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ipv6 + +import ( + "net" + "syscall" + + "golang.org/x/net/internal/iana" + "golang.org/x/net/internal/socket" + + "golang.org/x/sys/windows" +) + +const ( + sizeofSockaddrInet6 = 0x1c + + sizeofIPv6Mreq = 0x14 + sizeofIPv6Mtuinfo = 0x20 + sizeofICMPv6Filter = 0 +) + +type sockaddrInet6 struct { + Family uint16 + Port uint16 + Flowinfo uint32 + Addr [16]byte /* in6_addr */ + Scope_id uint32 +} + +type ipv6Mreq struct { + Multiaddr [16]byte /* in6_addr */ + Interface uint32 +} + +type ipv6Mtuinfo struct { + Addr sockaddrInet6 + Mtu uint32 +} + +type icmpv6Filter struct { + // TODO(mikio): implement this +} + +var ( + ctlOpts = [ctlMax]ctlOpt{} + + sockOpts = map[int]*sockOpt{ + ssoHopLimit: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: windows.IPV6_UNICAST_HOPS, Len: 4}}, + ssoMulticastInterface: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: windows.IPV6_MULTICAST_IF, Len: 4}}, + ssoMulticastHopLimit: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: windows.IPV6_MULTICAST_HOPS, Len: 4}}, + ssoMulticastLoopback: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: windows.IPV6_MULTICAST_LOOP, Len: 4}}, + ssoJoinGroup: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: windows.IPV6_JOIN_GROUP, Len: sizeofIPv6Mreq}, typ: ssoTypeIPMreq}, + ssoLeaveGroup: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: windows.IPV6_LEAVE_GROUP, Len: sizeofIPv6Mreq}, typ: ssoTypeIPMreq}, + } +) + +func (sa *sockaddrInet6) setSockaddr(ip net.IP, i int) { + sa.Family = syscall.AF_INET6 + copy(sa.Addr[:], ip) + sa.Scope_id = uint32(i) +} + +func (mreq *ipv6Mreq) setIfindex(i int) { + mreq.Interface = uint32(i) +} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/sys_zos.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/sys_zos.go new file mode 100644 index 000000000..31adc8665 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/sys_zos.go @@ -0,0 +1,72 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ipv6 + +import ( + "net" + "syscall" + "unsafe" + + "golang.org/x/net/internal/iana" + "golang.org/x/net/internal/socket" + + "golang.org/x/sys/unix" +) + +var ( + ctlOpts = [ctlMax]ctlOpt{ + ctlHopLimit: {unix.IPV6_HOPLIMIT, 4, marshalHopLimit, parseHopLimit}, + ctlPacketInfo: {unix.IPV6_PKTINFO, sizeofInet6Pktinfo, marshalPacketInfo, parsePacketInfo}, + ctlPathMTU: {unix.IPV6_PATHMTU, sizeofIPv6Mtuinfo, marshalPathMTU, parsePathMTU}, + } + + sockOpts = map[int]*sockOpt{ + ssoTrafficClass: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.IPV6_TCLASS, Len: 4}}, + ssoHopLimit: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.IPV6_UNICAST_HOPS, Len: 4}}, + ssoMulticastInterface: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.IPV6_MULTICAST_IF, Len: 4}}, + ssoMulticastHopLimit: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.IPV6_MULTICAST_HOPS, Len: 4}}, + ssoMulticastLoopback: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.IPV6_MULTICAST_LOOP, Len: 4}}, + ssoReceiveTrafficClass: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.IPV6_RECVTCLASS, Len: 4}}, + ssoReceiveHopLimit: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.IPV6_RECVHOPLIMIT, Len: 4}}, + ssoReceivePacketInfo: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.IPV6_RECVPKTINFO, Len: 4}}, + ssoReceivePathMTU: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.IPV6_RECVPATHMTU, Len: 4}}, + ssoChecksum: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.IPV6_CHECKSUM, Len: 4}}, + ssoICMPFilter: {Option: socket.Option{Level: iana.ProtocolIPv6ICMP, Name: unix.ICMP6_FILTER, Len: sizeofICMPv6Filter}}, + ssoJoinGroup: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.MCAST_JOIN_GROUP, Len: sizeofGroupReq}, typ: ssoTypeGroupReq}, + ssoLeaveGroup: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.MCAST_LEAVE_GROUP, Len: sizeofGroupReq}, typ: ssoTypeGroupReq}, + ssoJoinSourceGroup: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.MCAST_JOIN_SOURCE_GROUP, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq}, + ssoLeaveSourceGroup: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.MCAST_LEAVE_SOURCE_GROUP, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq}, + ssoBlockSourceGroup: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.MCAST_BLOCK_SOURCE, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq}, + ssoUnblockSourceGroup: {Option: socket.Option{Level: iana.ProtocolIPv6, Name: unix.MCAST_UNBLOCK_SOURCE, Len: sizeofGroupSourceReq}, typ: ssoTypeGroupSourceReq}, + } +) + +func (sa *sockaddrInet6) setSockaddr(ip net.IP, i int) { + sa.Family = syscall.AF_INET6 + copy(sa.Addr[:], ip) + sa.Scope_id = uint32(i) +} + +func (pi *inet6Pktinfo) setIfindex(i int) { + pi.Ifindex = uint32(i) +} + +func (gr *groupReq) setGroup(grp net.IP) { + sa := (*sockaddrInet6)(unsafe.Pointer(&gr.Group)) + sa.Family = syscall.AF_INET6 + sa.Len = sizeofSockaddrInet6 + copy(sa.Addr[:], grp) +} + +func (gsr *groupSourceReq) setSourceGroup(grp, src net.IP) { + sa := (*sockaddrInet6)(unsafe.Pointer(&gsr.Group)) + sa.Family = syscall.AF_INET6 + sa.Len = sizeofSockaddrInet6 + copy(sa.Addr[:], grp) + sa = (*sockaddrInet6)(unsafe.Pointer(&gsr.Source)) + sa.Family = syscall.AF_INET6 + sa.Len = sizeofSockaddrInet6 + copy(sa.Addr[:], src) +} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_aix_ppc64.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_aix_ppc64.go new file mode 100644 index 000000000..668716df4 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_aix_ppc64.go @@ -0,0 +1,68 @@ +// Code generated by cmd/cgo -godefs; DO NOT EDIT. +// cgo -godefs defs_aix.go + +// Added for go1.11 compatibility +//go:build aix + +package ipv6 + +const ( + sizeofSockaddrStorage = 0x508 + sizeofSockaddrInet6 = 0x1c + sizeofInet6Pktinfo = 0x14 + sizeofIPv6Mtuinfo = 0x20 + + sizeofIPv6Mreq = 0x14 + sizeofGroupReq = 0x510 + sizeofGroupSourceReq = 0xa18 + + sizeofICMPv6Filter = 0x20 +) + +type sockaddrStorage struct { + X__ss_len uint8 + Family uint8 + X__ss_pad1 [6]uint8 + X__ss_align int64 + X__ss_pad2 [1265]uint8 + Pad_cgo_0 [7]byte +} + +type sockaddrInet6 struct { + Len uint8 + Family uint8 + Port uint16 + Flowinfo uint32 + Addr [16]byte /* in6_addr */ + Scope_id uint32 +} + +type inet6Pktinfo struct { + Addr [16]byte /* in6_addr */ + Ifindex int32 +} + +type ipv6Mtuinfo struct { + Addr sockaddrInet6 + Mtu uint32 +} + +type ipv6Mreq struct { + Multiaddr [16]byte /* in6_addr */ + Interface uint32 +} + +type icmpv6Filter struct { + Filt [8]uint32 +} + +type groupReq struct { + Interface uint32 + Group sockaddrStorage +} + +type groupSourceReq struct { + Interface uint32 + Group sockaddrStorage + Source sockaddrStorage +} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_darwin.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_darwin.go new file mode 100644 index 000000000..dd6f7b28e --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_darwin.go @@ -0,0 +1,64 @@ +// Code generated by cmd/cgo -godefs; DO NOT EDIT. +// cgo -godefs defs_darwin.go + +package ipv6 + +const ( + sizeofSockaddrStorage = 0x80 + sizeofSockaddrInet6 = 0x1c + sizeofInet6Pktinfo = 0x14 + sizeofIPv6Mtuinfo = 0x20 + + sizeofIPv6Mreq = 0x14 + sizeofGroupReq = 0x84 + sizeofGroupSourceReq = 0x104 + + sizeofICMPv6Filter = 0x20 +) + +type sockaddrStorage struct { + Len uint8 + Family uint8 + X__ss_pad1 [6]int8 + X__ss_align int64 + X__ss_pad2 [112]int8 +} + +type sockaddrInet6 struct { + Len uint8 + Family uint8 + Port uint16 + Flowinfo uint32 + Addr [16]byte /* in6_addr */ + Scope_id uint32 +} + +type inet6Pktinfo struct { + Addr [16]byte /* in6_addr */ + Ifindex uint32 +} + +type ipv6Mtuinfo struct { + Addr sockaddrInet6 + Mtu uint32 +} + +type ipv6Mreq struct { + Multiaddr [16]byte /* in6_addr */ + Interface uint32 +} + +type icmpv6Filter struct { + Filt [8]uint32 +} + +type groupReq struct { + Interface uint32 + Pad_cgo_0 [128]byte +} + +type groupSourceReq struct { + Interface uint32 + Pad_cgo_0 [128]byte + Pad_cgo_1 [128]byte +} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_dragonfly.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_dragonfly.go new file mode 100644 index 000000000..6b45a94fe --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_dragonfly.go @@ -0,0 +1,42 @@ +// Code generated by cmd/cgo -godefs; DO NOT EDIT. +// cgo -godefs defs_dragonfly.go + +package ipv6 + +const ( + sizeofSockaddrInet6 = 0x1c + sizeofInet6Pktinfo = 0x14 + sizeofIPv6Mtuinfo = 0x20 + + sizeofIPv6Mreq = 0x14 + + sizeofICMPv6Filter = 0x20 +) + +type sockaddrInet6 struct { + Len uint8 + Family uint8 + Port uint16 + Flowinfo uint32 + Addr [16]byte /* in6_addr */ + Scope_id uint32 +} + +type inet6Pktinfo struct { + Addr [16]byte /* in6_addr */ + Ifindex uint32 +} + +type ipv6Mtuinfo struct { + Addr sockaddrInet6 + Mtu uint32 +} + +type ipv6Mreq struct { + Multiaddr [16]byte /* in6_addr */ + Interface uint32 +} + +type icmpv6Filter struct { + Filt [8]uint32 +} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_freebsd_386.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_freebsd_386.go new file mode 100644 index 000000000..8da55925f --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_freebsd_386.go @@ -0,0 +1,64 @@ +// Code generated by cmd/cgo -godefs; DO NOT EDIT. +// cgo -godefs defs_freebsd.go + +package ipv6 + +const ( + sizeofSockaddrStorage = 0x80 + sizeofSockaddrInet6 = 0x1c + sizeofInet6Pktinfo = 0x14 + sizeofIPv6Mtuinfo = 0x20 + + sizeofIPv6Mreq = 0x14 + sizeofGroupReq = 0x84 + sizeofGroupSourceReq = 0x104 + + sizeofICMPv6Filter = 0x20 +) + +type sockaddrStorage struct { + Len uint8 + Family uint8 + X__ss_pad1 [6]int8 + X__ss_align int64 + X__ss_pad2 [112]int8 +} + +type sockaddrInet6 struct { + Len uint8 + Family uint8 + Port uint16 + Flowinfo uint32 + Addr [16]byte /* in6_addr */ + Scope_id uint32 +} + +type inet6Pktinfo struct { + Addr [16]byte /* in6_addr */ + Ifindex uint32 +} + +type ipv6Mtuinfo struct { + Addr sockaddrInet6 + Mtu uint32 +} + +type ipv6Mreq struct { + Multiaddr [16]byte /* in6_addr */ + Interface uint32 +} + +type groupReq struct { + Interface uint32 + Group sockaddrStorage +} + +type groupSourceReq struct { + Interface uint32 + Group sockaddrStorage + Source sockaddrStorage +} + +type icmpv6Filter struct { + Filt [8]uint32 +} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_freebsd_amd64.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_freebsd_amd64.go new file mode 100644 index 000000000..72a1a65a2 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_freebsd_amd64.go @@ -0,0 +1,66 @@ +// Code generated by cmd/cgo -godefs; DO NOT EDIT. +// cgo -godefs defs_freebsd.go + +package ipv6 + +const ( + sizeofSockaddrStorage = 0x80 + sizeofSockaddrInet6 = 0x1c + sizeofInet6Pktinfo = 0x14 + sizeofIPv6Mtuinfo = 0x20 + + sizeofIPv6Mreq = 0x14 + sizeofGroupReq = 0x88 + sizeofGroupSourceReq = 0x108 + + sizeofICMPv6Filter = 0x20 +) + +type sockaddrStorage struct { + Len uint8 + Family uint8 + X__ss_pad1 [6]int8 + X__ss_align int64 + X__ss_pad2 [112]int8 +} + +type sockaddrInet6 struct { + Len uint8 + Family uint8 + Port uint16 + Flowinfo uint32 + Addr [16]byte /* in6_addr */ + Scope_id uint32 +} + +type inet6Pktinfo struct { + Addr [16]byte /* in6_addr */ + Ifindex uint32 +} + +type ipv6Mtuinfo struct { + Addr sockaddrInet6 + Mtu uint32 +} + +type ipv6Mreq struct { + Multiaddr [16]byte /* in6_addr */ + Interface uint32 +} + +type groupReq struct { + Interface uint32 + Pad_cgo_0 [4]byte + Group sockaddrStorage +} + +type groupSourceReq struct { + Interface uint32 + Pad_cgo_0 [4]byte + Group sockaddrStorage + Source sockaddrStorage +} + +type icmpv6Filter struct { + Filt [8]uint32 +} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_freebsd_arm.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_freebsd_arm.go new file mode 100644 index 000000000..72a1a65a2 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_freebsd_arm.go @@ -0,0 +1,66 @@ +// Code generated by cmd/cgo -godefs; DO NOT EDIT. +// cgo -godefs defs_freebsd.go + +package ipv6 + +const ( + sizeofSockaddrStorage = 0x80 + sizeofSockaddrInet6 = 0x1c + sizeofInet6Pktinfo = 0x14 + sizeofIPv6Mtuinfo = 0x20 + + sizeofIPv6Mreq = 0x14 + sizeofGroupReq = 0x88 + sizeofGroupSourceReq = 0x108 + + sizeofICMPv6Filter = 0x20 +) + +type sockaddrStorage struct { + Len uint8 + Family uint8 + X__ss_pad1 [6]int8 + X__ss_align int64 + X__ss_pad2 [112]int8 +} + +type sockaddrInet6 struct { + Len uint8 + Family uint8 + Port uint16 + Flowinfo uint32 + Addr [16]byte /* in6_addr */ + Scope_id uint32 +} + +type inet6Pktinfo struct { + Addr [16]byte /* in6_addr */ + Ifindex uint32 +} + +type ipv6Mtuinfo struct { + Addr sockaddrInet6 + Mtu uint32 +} + +type ipv6Mreq struct { + Multiaddr [16]byte /* in6_addr */ + Interface uint32 +} + +type groupReq struct { + Interface uint32 + Pad_cgo_0 [4]byte + Group sockaddrStorage +} + +type groupSourceReq struct { + Interface uint32 + Pad_cgo_0 [4]byte + Group sockaddrStorage + Source sockaddrStorage +} + +type icmpv6Filter struct { + Filt [8]uint32 +} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_freebsd_arm64.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_freebsd_arm64.go new file mode 100644 index 000000000..5b39eb8df --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_freebsd_arm64.go @@ -0,0 +1,64 @@ +// Code generated by cmd/cgo -godefs; DO NOT EDIT. +// cgo -godefs defs_freebsd.go + +package ipv6 + +const ( + sizeofSockaddrStorage = 0x80 + sizeofSockaddrInet6 = 0x1c + sizeofInet6Pktinfo = 0x14 + sizeofIPv6Mtuinfo = 0x20 + + sizeofIPv6Mreq = 0x14 + sizeofGroupReq = 0x88 + sizeofGroupSourceReq = 0x108 + + sizeofICMPv6Filter = 0x20 +) + +type sockaddrStorage struct { + Len uint8 + Family uint8 + X__ss_pad1 [6]uint8 + X__ss_align int64 + X__ss_pad2 [112]uint8 +} + +type sockaddrInet6 struct { + Len uint8 + Family uint8 + Port uint16 + Flowinfo uint32 + Addr [16]byte /* in6_addr */ + Scope_id uint32 +} + +type inet6Pktinfo struct { + Addr [16]byte /* in6_addr */ + Ifindex uint32 +} + +type ipv6Mtuinfo struct { + Addr sockaddrInet6 + Mtu uint32 +} + +type ipv6Mreq struct { + Multiaddr [16]byte /* in6_addr */ + Interface uint32 +} + +type groupReq struct { + Interface uint32 + Group sockaddrStorage +} + +type groupSourceReq struct { + Interface uint32 + Group sockaddrStorage + Source sockaddrStorage +} + +type icmpv6Filter struct { + Filt [8]uint32 +} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_freebsd_riscv64.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_freebsd_riscv64.go new file mode 100644 index 000000000..5b39eb8df --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_freebsd_riscv64.go @@ -0,0 +1,64 @@ +// Code generated by cmd/cgo -godefs; DO NOT EDIT. +// cgo -godefs defs_freebsd.go + +package ipv6 + +const ( + sizeofSockaddrStorage = 0x80 + sizeofSockaddrInet6 = 0x1c + sizeofInet6Pktinfo = 0x14 + sizeofIPv6Mtuinfo = 0x20 + + sizeofIPv6Mreq = 0x14 + sizeofGroupReq = 0x88 + sizeofGroupSourceReq = 0x108 + + sizeofICMPv6Filter = 0x20 +) + +type sockaddrStorage struct { + Len uint8 + Family uint8 + X__ss_pad1 [6]uint8 + X__ss_align int64 + X__ss_pad2 [112]uint8 +} + +type sockaddrInet6 struct { + Len uint8 + Family uint8 + Port uint16 + Flowinfo uint32 + Addr [16]byte /* in6_addr */ + Scope_id uint32 +} + +type inet6Pktinfo struct { + Addr [16]byte /* in6_addr */ + Ifindex uint32 +} + +type ipv6Mtuinfo struct { + Addr sockaddrInet6 + Mtu uint32 +} + +type ipv6Mreq struct { + Multiaddr [16]byte /* in6_addr */ + Interface uint32 +} + +type groupReq struct { + Interface uint32 + Group sockaddrStorage +} + +type groupSourceReq struct { + Interface uint32 + Group sockaddrStorage + Source sockaddrStorage +} + +type icmpv6Filter struct { + Filt [8]uint32 +} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_linux_386.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_linux_386.go new file mode 100644 index 000000000..ad71871b7 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_linux_386.go @@ -0,0 +1,72 @@ +// Code generated by cmd/cgo -godefs; DO NOT EDIT. +// cgo -godefs defs_linux.go + +package ipv6 + +const ( + sizeofKernelSockaddrStorage = 0x80 + sizeofSockaddrInet6 = 0x1c + sizeofInet6Pktinfo = 0x14 + sizeofIPv6Mtuinfo = 0x20 + sizeofIPv6FlowlabelReq = 0x20 + + sizeofIPv6Mreq = 0x14 + sizeofGroupReq = 0x84 + sizeofGroupSourceReq = 0x104 + + sizeofICMPv6Filter = 0x20 +) + +type kernelSockaddrStorage struct { + Family uint16 + X__data [126]int8 +} + +type sockaddrInet6 struct { + Family uint16 + Port uint16 + Flowinfo uint32 + Addr [16]byte /* in6_addr */ + Scope_id uint32 +} + +type inet6Pktinfo struct { + Addr [16]byte /* in6_addr */ + Ifindex int32 +} + +type ipv6Mtuinfo struct { + Addr sockaddrInet6 + Mtu uint32 +} + +type ipv6FlowlabelReq struct { + Dst [16]byte /* in6_addr */ + Label uint32 + Action uint8 + Share uint8 + Flags uint16 + Expires uint16 + Linger uint16 + X__flr_pad uint32 +} + +type ipv6Mreq struct { + Multiaddr [16]byte /* in6_addr */ + Ifindex int32 +} + +type groupReq struct { + Interface uint32 + Group kernelSockaddrStorage +} + +type groupSourceReq struct { + Interface uint32 + Group kernelSockaddrStorage + Source kernelSockaddrStorage +} + +type icmpv6Filter struct { + Data [8]uint32 +} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_linux_amd64.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_linux_amd64.go new file mode 100644 index 000000000..2514ab9a4 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_linux_amd64.go @@ -0,0 +1,74 @@ +// Code generated by cmd/cgo -godefs; DO NOT EDIT. +// cgo -godefs defs_linux.go + +package ipv6 + +const ( + sizeofKernelSockaddrStorage = 0x80 + sizeofSockaddrInet6 = 0x1c + sizeofInet6Pktinfo = 0x14 + sizeofIPv6Mtuinfo = 0x20 + sizeofIPv6FlowlabelReq = 0x20 + + sizeofIPv6Mreq = 0x14 + sizeofGroupReq = 0x88 + sizeofGroupSourceReq = 0x108 + + sizeofICMPv6Filter = 0x20 +) + +type kernelSockaddrStorage struct { + Family uint16 + X__data [126]int8 +} + +type sockaddrInet6 struct { + Family uint16 + Port uint16 + Flowinfo uint32 + Addr [16]byte /* in6_addr */ + Scope_id uint32 +} + +type inet6Pktinfo struct { + Addr [16]byte /* in6_addr */ + Ifindex int32 +} + +type ipv6Mtuinfo struct { + Addr sockaddrInet6 + Mtu uint32 +} + +type ipv6FlowlabelReq struct { + Dst [16]byte /* in6_addr */ + Label uint32 + Action uint8 + Share uint8 + Flags uint16 + Expires uint16 + Linger uint16 + X__flr_pad uint32 +} + +type ipv6Mreq struct { + Multiaddr [16]byte /* in6_addr */ + Ifindex int32 +} + +type groupReq struct { + Interface uint32 + Pad_cgo_0 [4]byte + Group kernelSockaddrStorage +} + +type groupSourceReq struct { + Interface uint32 + Pad_cgo_0 [4]byte + Group kernelSockaddrStorage + Source kernelSockaddrStorage +} + +type icmpv6Filter struct { + Data [8]uint32 +} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_linux_arm.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_linux_arm.go new file mode 100644 index 000000000..ad71871b7 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_linux_arm.go @@ -0,0 +1,72 @@ +// Code generated by cmd/cgo -godefs; DO NOT EDIT. +// cgo -godefs defs_linux.go + +package ipv6 + +const ( + sizeofKernelSockaddrStorage = 0x80 + sizeofSockaddrInet6 = 0x1c + sizeofInet6Pktinfo = 0x14 + sizeofIPv6Mtuinfo = 0x20 + sizeofIPv6FlowlabelReq = 0x20 + + sizeofIPv6Mreq = 0x14 + sizeofGroupReq = 0x84 + sizeofGroupSourceReq = 0x104 + + sizeofICMPv6Filter = 0x20 +) + +type kernelSockaddrStorage struct { + Family uint16 + X__data [126]int8 +} + +type sockaddrInet6 struct { + Family uint16 + Port uint16 + Flowinfo uint32 + Addr [16]byte /* in6_addr */ + Scope_id uint32 +} + +type inet6Pktinfo struct { + Addr [16]byte /* in6_addr */ + Ifindex int32 +} + +type ipv6Mtuinfo struct { + Addr sockaddrInet6 + Mtu uint32 +} + +type ipv6FlowlabelReq struct { + Dst [16]byte /* in6_addr */ + Label uint32 + Action uint8 + Share uint8 + Flags uint16 + Expires uint16 + Linger uint16 + X__flr_pad uint32 +} + +type ipv6Mreq struct { + Multiaddr [16]byte /* in6_addr */ + Ifindex int32 +} + +type groupReq struct { + Interface uint32 + Group kernelSockaddrStorage +} + +type groupSourceReq struct { + Interface uint32 + Group kernelSockaddrStorage + Source kernelSockaddrStorage +} + +type icmpv6Filter struct { + Data [8]uint32 +} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_linux_arm64.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_linux_arm64.go new file mode 100644 index 000000000..2514ab9a4 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_linux_arm64.go @@ -0,0 +1,74 @@ +// Code generated by cmd/cgo -godefs; DO NOT EDIT. +// cgo -godefs defs_linux.go + +package ipv6 + +const ( + sizeofKernelSockaddrStorage = 0x80 + sizeofSockaddrInet6 = 0x1c + sizeofInet6Pktinfo = 0x14 + sizeofIPv6Mtuinfo = 0x20 + sizeofIPv6FlowlabelReq = 0x20 + + sizeofIPv6Mreq = 0x14 + sizeofGroupReq = 0x88 + sizeofGroupSourceReq = 0x108 + + sizeofICMPv6Filter = 0x20 +) + +type kernelSockaddrStorage struct { + Family uint16 + X__data [126]int8 +} + +type sockaddrInet6 struct { + Family uint16 + Port uint16 + Flowinfo uint32 + Addr [16]byte /* in6_addr */ + Scope_id uint32 +} + +type inet6Pktinfo struct { + Addr [16]byte /* in6_addr */ + Ifindex int32 +} + +type ipv6Mtuinfo struct { + Addr sockaddrInet6 + Mtu uint32 +} + +type ipv6FlowlabelReq struct { + Dst [16]byte /* in6_addr */ + Label uint32 + Action uint8 + Share uint8 + Flags uint16 + Expires uint16 + Linger uint16 + X__flr_pad uint32 +} + +type ipv6Mreq struct { + Multiaddr [16]byte /* in6_addr */ + Ifindex int32 +} + +type groupReq struct { + Interface uint32 + Pad_cgo_0 [4]byte + Group kernelSockaddrStorage +} + +type groupSourceReq struct { + Interface uint32 + Pad_cgo_0 [4]byte + Group kernelSockaddrStorage + Source kernelSockaddrStorage +} + +type icmpv6Filter struct { + Data [8]uint32 +} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_linux_loong64.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_linux_loong64.go new file mode 100644 index 000000000..6a53284db --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_linux_loong64.go @@ -0,0 +1,76 @@ +// Code generated by cmd/cgo -godefs; DO NOT EDIT. +// cgo -godefs defs_linux.go + +//go:build loong64 + +package ipv6 + +const ( + sizeofKernelSockaddrStorage = 0x80 + sizeofSockaddrInet6 = 0x1c + sizeofInet6Pktinfo = 0x14 + sizeofIPv6Mtuinfo = 0x20 + sizeofIPv6FlowlabelReq = 0x20 + + sizeofIPv6Mreq = 0x14 + sizeofGroupReq = 0x88 + sizeofGroupSourceReq = 0x108 + + sizeofICMPv6Filter = 0x20 +) + +type kernelSockaddrStorage struct { + Family uint16 + X__data [126]int8 +} + +type sockaddrInet6 struct { + Family uint16 + Port uint16 + Flowinfo uint32 + Addr [16]byte /* in6_addr */ + Scope_id uint32 +} + +type inet6Pktinfo struct { + Addr [16]byte /* in6_addr */ + Ifindex int32 +} + +type ipv6Mtuinfo struct { + Addr sockaddrInet6 + Mtu uint32 +} + +type ipv6FlowlabelReq struct { + Dst [16]byte /* in6_addr */ + Label uint32 + Action uint8 + Share uint8 + Flags uint16 + Expires uint16 + Linger uint16 + X__flr_pad uint32 +} + +type ipv6Mreq struct { + Multiaddr [16]byte /* in6_addr */ + Ifindex int32 +} + +type groupReq struct { + Interface uint32 + Pad_cgo_0 [4]byte + Group kernelSockaddrStorage +} + +type groupSourceReq struct { + Interface uint32 + Pad_cgo_0 [4]byte + Group kernelSockaddrStorage + Source kernelSockaddrStorage +} + +type icmpv6Filter struct { + Data [8]uint32 +} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_linux_mips.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_linux_mips.go new file mode 100644 index 000000000..ad71871b7 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_linux_mips.go @@ -0,0 +1,72 @@ +// Code generated by cmd/cgo -godefs; DO NOT EDIT. +// cgo -godefs defs_linux.go + +package ipv6 + +const ( + sizeofKernelSockaddrStorage = 0x80 + sizeofSockaddrInet6 = 0x1c + sizeofInet6Pktinfo = 0x14 + sizeofIPv6Mtuinfo = 0x20 + sizeofIPv6FlowlabelReq = 0x20 + + sizeofIPv6Mreq = 0x14 + sizeofGroupReq = 0x84 + sizeofGroupSourceReq = 0x104 + + sizeofICMPv6Filter = 0x20 +) + +type kernelSockaddrStorage struct { + Family uint16 + X__data [126]int8 +} + +type sockaddrInet6 struct { + Family uint16 + Port uint16 + Flowinfo uint32 + Addr [16]byte /* in6_addr */ + Scope_id uint32 +} + +type inet6Pktinfo struct { + Addr [16]byte /* in6_addr */ + Ifindex int32 +} + +type ipv6Mtuinfo struct { + Addr sockaddrInet6 + Mtu uint32 +} + +type ipv6FlowlabelReq struct { + Dst [16]byte /* in6_addr */ + Label uint32 + Action uint8 + Share uint8 + Flags uint16 + Expires uint16 + Linger uint16 + X__flr_pad uint32 +} + +type ipv6Mreq struct { + Multiaddr [16]byte /* in6_addr */ + Ifindex int32 +} + +type groupReq struct { + Interface uint32 + Group kernelSockaddrStorage +} + +type groupSourceReq struct { + Interface uint32 + Group kernelSockaddrStorage + Source kernelSockaddrStorage +} + +type icmpv6Filter struct { + Data [8]uint32 +} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_linux_mips64.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_linux_mips64.go new file mode 100644 index 000000000..2514ab9a4 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_linux_mips64.go @@ -0,0 +1,74 @@ +// Code generated by cmd/cgo -godefs; DO NOT EDIT. +// cgo -godefs defs_linux.go + +package ipv6 + +const ( + sizeofKernelSockaddrStorage = 0x80 + sizeofSockaddrInet6 = 0x1c + sizeofInet6Pktinfo = 0x14 + sizeofIPv6Mtuinfo = 0x20 + sizeofIPv6FlowlabelReq = 0x20 + + sizeofIPv6Mreq = 0x14 + sizeofGroupReq = 0x88 + sizeofGroupSourceReq = 0x108 + + sizeofICMPv6Filter = 0x20 +) + +type kernelSockaddrStorage struct { + Family uint16 + X__data [126]int8 +} + +type sockaddrInet6 struct { + Family uint16 + Port uint16 + Flowinfo uint32 + Addr [16]byte /* in6_addr */ + Scope_id uint32 +} + +type inet6Pktinfo struct { + Addr [16]byte /* in6_addr */ + Ifindex int32 +} + +type ipv6Mtuinfo struct { + Addr sockaddrInet6 + Mtu uint32 +} + +type ipv6FlowlabelReq struct { + Dst [16]byte /* in6_addr */ + Label uint32 + Action uint8 + Share uint8 + Flags uint16 + Expires uint16 + Linger uint16 + X__flr_pad uint32 +} + +type ipv6Mreq struct { + Multiaddr [16]byte /* in6_addr */ + Ifindex int32 +} + +type groupReq struct { + Interface uint32 + Pad_cgo_0 [4]byte + Group kernelSockaddrStorage +} + +type groupSourceReq struct { + Interface uint32 + Pad_cgo_0 [4]byte + Group kernelSockaddrStorage + Source kernelSockaddrStorage +} + +type icmpv6Filter struct { + Data [8]uint32 +} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_linux_mips64le.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_linux_mips64le.go new file mode 100644 index 000000000..2514ab9a4 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_linux_mips64le.go @@ -0,0 +1,74 @@ +// Code generated by cmd/cgo -godefs; DO NOT EDIT. +// cgo -godefs defs_linux.go + +package ipv6 + +const ( + sizeofKernelSockaddrStorage = 0x80 + sizeofSockaddrInet6 = 0x1c + sizeofInet6Pktinfo = 0x14 + sizeofIPv6Mtuinfo = 0x20 + sizeofIPv6FlowlabelReq = 0x20 + + sizeofIPv6Mreq = 0x14 + sizeofGroupReq = 0x88 + sizeofGroupSourceReq = 0x108 + + sizeofICMPv6Filter = 0x20 +) + +type kernelSockaddrStorage struct { + Family uint16 + X__data [126]int8 +} + +type sockaddrInet6 struct { + Family uint16 + Port uint16 + Flowinfo uint32 + Addr [16]byte /* in6_addr */ + Scope_id uint32 +} + +type inet6Pktinfo struct { + Addr [16]byte /* in6_addr */ + Ifindex int32 +} + +type ipv6Mtuinfo struct { + Addr sockaddrInet6 + Mtu uint32 +} + +type ipv6FlowlabelReq struct { + Dst [16]byte /* in6_addr */ + Label uint32 + Action uint8 + Share uint8 + Flags uint16 + Expires uint16 + Linger uint16 + X__flr_pad uint32 +} + +type ipv6Mreq struct { + Multiaddr [16]byte /* in6_addr */ + Ifindex int32 +} + +type groupReq struct { + Interface uint32 + Pad_cgo_0 [4]byte + Group kernelSockaddrStorage +} + +type groupSourceReq struct { + Interface uint32 + Pad_cgo_0 [4]byte + Group kernelSockaddrStorage + Source kernelSockaddrStorage +} + +type icmpv6Filter struct { + Data [8]uint32 +} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_linux_mipsle.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_linux_mipsle.go new file mode 100644 index 000000000..ad71871b7 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_linux_mipsle.go @@ -0,0 +1,72 @@ +// Code generated by cmd/cgo -godefs; DO NOT EDIT. +// cgo -godefs defs_linux.go + +package ipv6 + +const ( + sizeofKernelSockaddrStorage = 0x80 + sizeofSockaddrInet6 = 0x1c + sizeofInet6Pktinfo = 0x14 + sizeofIPv6Mtuinfo = 0x20 + sizeofIPv6FlowlabelReq = 0x20 + + sizeofIPv6Mreq = 0x14 + sizeofGroupReq = 0x84 + sizeofGroupSourceReq = 0x104 + + sizeofICMPv6Filter = 0x20 +) + +type kernelSockaddrStorage struct { + Family uint16 + X__data [126]int8 +} + +type sockaddrInet6 struct { + Family uint16 + Port uint16 + Flowinfo uint32 + Addr [16]byte /* in6_addr */ + Scope_id uint32 +} + +type inet6Pktinfo struct { + Addr [16]byte /* in6_addr */ + Ifindex int32 +} + +type ipv6Mtuinfo struct { + Addr sockaddrInet6 + Mtu uint32 +} + +type ipv6FlowlabelReq struct { + Dst [16]byte /* in6_addr */ + Label uint32 + Action uint8 + Share uint8 + Flags uint16 + Expires uint16 + Linger uint16 + X__flr_pad uint32 +} + +type ipv6Mreq struct { + Multiaddr [16]byte /* in6_addr */ + Ifindex int32 +} + +type groupReq struct { + Interface uint32 + Group kernelSockaddrStorage +} + +type groupSourceReq struct { + Interface uint32 + Group kernelSockaddrStorage + Source kernelSockaddrStorage +} + +type icmpv6Filter struct { + Data [8]uint32 +} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_linux_ppc.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_linux_ppc.go new file mode 100644 index 000000000..d06c2adec --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_linux_ppc.go @@ -0,0 +1,72 @@ +// Code generated by cmd/cgo -godefs; DO NOT EDIT. +// cgo -godefs defs_linux.go + +package ipv6 + +const ( + sizeofKernelSockaddrStorage = 0x80 + sizeofSockaddrInet6 = 0x1c + sizeofInet6Pktinfo = 0x14 + sizeofIPv6Mtuinfo = 0x20 + sizeofIPv6FlowlabelReq = 0x20 + + sizeofIPv6Mreq = 0x14 + sizeofGroupReq = 0x84 + sizeofGroupSourceReq = 0x104 + + sizeofICMPv6Filter = 0x20 +) + +type kernelSockaddrStorage struct { + Family uint16 + X__data [126]uint8 +} + +type sockaddrInet6 struct { + Family uint16 + Port uint16 + Flowinfo uint32 + Addr [16]byte /* in6_addr */ + Scope_id uint32 +} + +type inet6Pktinfo struct { + Addr [16]byte /* in6_addr */ + Ifindex int32 +} + +type ipv6Mtuinfo struct { + Addr sockaddrInet6 + Mtu uint32 +} + +type ipv6FlowlabelReq struct { + Dst [16]byte /* in6_addr */ + Label uint32 + Action uint8 + Share uint8 + Flags uint16 + Expires uint16 + Linger uint16 + X__flr_pad uint32 +} + +type ipv6Mreq struct { + Multiaddr [16]byte /* in6_addr */ + Ifindex int32 +} + +type groupReq struct { + Interface uint32 + Group kernelSockaddrStorage +} + +type groupSourceReq struct { + Interface uint32 + Group kernelSockaddrStorage + Source kernelSockaddrStorage +} + +type icmpv6Filter struct { + Data [8]uint32 +} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_linux_ppc64.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_linux_ppc64.go new file mode 100644 index 000000000..2514ab9a4 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_linux_ppc64.go @@ -0,0 +1,74 @@ +// Code generated by cmd/cgo -godefs; DO NOT EDIT. +// cgo -godefs defs_linux.go + +package ipv6 + +const ( + sizeofKernelSockaddrStorage = 0x80 + sizeofSockaddrInet6 = 0x1c + sizeofInet6Pktinfo = 0x14 + sizeofIPv6Mtuinfo = 0x20 + sizeofIPv6FlowlabelReq = 0x20 + + sizeofIPv6Mreq = 0x14 + sizeofGroupReq = 0x88 + sizeofGroupSourceReq = 0x108 + + sizeofICMPv6Filter = 0x20 +) + +type kernelSockaddrStorage struct { + Family uint16 + X__data [126]int8 +} + +type sockaddrInet6 struct { + Family uint16 + Port uint16 + Flowinfo uint32 + Addr [16]byte /* in6_addr */ + Scope_id uint32 +} + +type inet6Pktinfo struct { + Addr [16]byte /* in6_addr */ + Ifindex int32 +} + +type ipv6Mtuinfo struct { + Addr sockaddrInet6 + Mtu uint32 +} + +type ipv6FlowlabelReq struct { + Dst [16]byte /* in6_addr */ + Label uint32 + Action uint8 + Share uint8 + Flags uint16 + Expires uint16 + Linger uint16 + X__flr_pad uint32 +} + +type ipv6Mreq struct { + Multiaddr [16]byte /* in6_addr */ + Ifindex int32 +} + +type groupReq struct { + Interface uint32 + Pad_cgo_0 [4]byte + Group kernelSockaddrStorage +} + +type groupSourceReq struct { + Interface uint32 + Pad_cgo_0 [4]byte + Group kernelSockaddrStorage + Source kernelSockaddrStorage +} + +type icmpv6Filter struct { + Data [8]uint32 +} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_linux_ppc64le.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_linux_ppc64le.go new file mode 100644 index 000000000..2514ab9a4 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_linux_ppc64le.go @@ -0,0 +1,74 @@ +// Code generated by cmd/cgo -godefs; DO NOT EDIT. +// cgo -godefs defs_linux.go + +package ipv6 + +const ( + sizeofKernelSockaddrStorage = 0x80 + sizeofSockaddrInet6 = 0x1c + sizeofInet6Pktinfo = 0x14 + sizeofIPv6Mtuinfo = 0x20 + sizeofIPv6FlowlabelReq = 0x20 + + sizeofIPv6Mreq = 0x14 + sizeofGroupReq = 0x88 + sizeofGroupSourceReq = 0x108 + + sizeofICMPv6Filter = 0x20 +) + +type kernelSockaddrStorage struct { + Family uint16 + X__data [126]int8 +} + +type sockaddrInet6 struct { + Family uint16 + Port uint16 + Flowinfo uint32 + Addr [16]byte /* in6_addr */ + Scope_id uint32 +} + +type inet6Pktinfo struct { + Addr [16]byte /* in6_addr */ + Ifindex int32 +} + +type ipv6Mtuinfo struct { + Addr sockaddrInet6 + Mtu uint32 +} + +type ipv6FlowlabelReq struct { + Dst [16]byte /* in6_addr */ + Label uint32 + Action uint8 + Share uint8 + Flags uint16 + Expires uint16 + Linger uint16 + X__flr_pad uint32 +} + +type ipv6Mreq struct { + Multiaddr [16]byte /* in6_addr */ + Ifindex int32 +} + +type groupReq struct { + Interface uint32 + Pad_cgo_0 [4]byte + Group kernelSockaddrStorage +} + +type groupSourceReq struct { + Interface uint32 + Pad_cgo_0 [4]byte + Group kernelSockaddrStorage + Source kernelSockaddrStorage +} + +type icmpv6Filter struct { + Data [8]uint32 +} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_linux_riscv64.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_linux_riscv64.go new file mode 100644 index 000000000..13b347205 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_linux_riscv64.go @@ -0,0 +1,76 @@ +// Code generated by cmd/cgo -godefs; DO NOT EDIT. +// cgo -godefs defs_linux.go + +//go:build riscv64 + +package ipv6 + +const ( + sizeofKernelSockaddrStorage = 0x80 + sizeofSockaddrInet6 = 0x1c + sizeofInet6Pktinfo = 0x14 + sizeofIPv6Mtuinfo = 0x20 + sizeofIPv6FlowlabelReq = 0x20 + + sizeofIPv6Mreq = 0x14 + sizeofGroupReq = 0x88 + sizeofGroupSourceReq = 0x108 + + sizeofICMPv6Filter = 0x20 +) + +type kernelSockaddrStorage struct { + Family uint16 + X__data [126]int8 +} + +type sockaddrInet6 struct { + Family uint16 + Port uint16 + Flowinfo uint32 + Addr [16]byte /* in6_addr */ + Scope_id uint32 +} + +type inet6Pktinfo struct { + Addr [16]byte /* in6_addr */ + Ifindex int32 +} + +type ipv6Mtuinfo struct { + Addr sockaddrInet6 + Mtu uint32 +} + +type ipv6FlowlabelReq struct { + Dst [16]byte /* in6_addr */ + Label uint32 + Action uint8 + Share uint8 + Flags uint16 + Expires uint16 + Linger uint16 + X__flr_pad uint32 +} + +type ipv6Mreq struct { + Multiaddr [16]byte /* in6_addr */ + Ifindex int32 +} + +type groupReq struct { + Interface uint32 + Pad_cgo_0 [4]byte + Group kernelSockaddrStorage +} + +type groupSourceReq struct { + Interface uint32 + Pad_cgo_0 [4]byte + Group kernelSockaddrStorage + Source kernelSockaddrStorage +} + +type icmpv6Filter struct { + Data [8]uint32 +} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_linux_s390x.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_linux_s390x.go new file mode 100644 index 000000000..2514ab9a4 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_linux_s390x.go @@ -0,0 +1,74 @@ +// Code generated by cmd/cgo -godefs; DO NOT EDIT. +// cgo -godefs defs_linux.go + +package ipv6 + +const ( + sizeofKernelSockaddrStorage = 0x80 + sizeofSockaddrInet6 = 0x1c + sizeofInet6Pktinfo = 0x14 + sizeofIPv6Mtuinfo = 0x20 + sizeofIPv6FlowlabelReq = 0x20 + + sizeofIPv6Mreq = 0x14 + sizeofGroupReq = 0x88 + sizeofGroupSourceReq = 0x108 + + sizeofICMPv6Filter = 0x20 +) + +type kernelSockaddrStorage struct { + Family uint16 + X__data [126]int8 +} + +type sockaddrInet6 struct { + Family uint16 + Port uint16 + Flowinfo uint32 + Addr [16]byte /* in6_addr */ + Scope_id uint32 +} + +type inet6Pktinfo struct { + Addr [16]byte /* in6_addr */ + Ifindex int32 +} + +type ipv6Mtuinfo struct { + Addr sockaddrInet6 + Mtu uint32 +} + +type ipv6FlowlabelReq struct { + Dst [16]byte /* in6_addr */ + Label uint32 + Action uint8 + Share uint8 + Flags uint16 + Expires uint16 + Linger uint16 + X__flr_pad uint32 +} + +type ipv6Mreq struct { + Multiaddr [16]byte /* in6_addr */ + Ifindex int32 +} + +type groupReq struct { + Interface uint32 + Pad_cgo_0 [4]byte + Group kernelSockaddrStorage +} + +type groupSourceReq struct { + Interface uint32 + Pad_cgo_0 [4]byte + Group kernelSockaddrStorage + Source kernelSockaddrStorage +} + +type icmpv6Filter struct { + Data [8]uint32 +} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_netbsd.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_netbsd.go new file mode 100644 index 000000000..f7335d5ae --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_netbsd.go @@ -0,0 +1,42 @@ +// Code generated by cmd/cgo -godefs; DO NOT EDIT. +// cgo -godefs defs_netbsd.go + +package ipv6 + +const ( + sizeofSockaddrInet6 = 0x1c + sizeofInet6Pktinfo = 0x14 + sizeofIPv6Mtuinfo = 0x20 + + sizeofIPv6Mreq = 0x14 + + sizeofICMPv6Filter = 0x20 +) + +type sockaddrInet6 struct { + Len uint8 + Family uint8 + Port uint16 + Flowinfo uint32 + Addr [16]byte /* in6_addr */ + Scope_id uint32 +} + +type inet6Pktinfo struct { + Addr [16]byte /* in6_addr */ + Ifindex uint32 +} + +type ipv6Mtuinfo struct { + Addr sockaddrInet6 + Mtu uint32 +} + +type ipv6Mreq struct { + Multiaddr [16]byte /* in6_addr */ + Interface uint32 +} + +type icmpv6Filter struct { + Filt [8]uint32 +} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_openbsd.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_openbsd.go new file mode 100644 index 000000000..6d1592812 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_openbsd.go @@ -0,0 +1,42 @@ +// Code generated by cmd/cgo -godefs; DO NOT EDIT. +// cgo -godefs defs_openbsd.go + +package ipv6 + +const ( + sizeofSockaddrInet6 = 0x1c + sizeofInet6Pktinfo = 0x14 + sizeofIPv6Mtuinfo = 0x20 + + sizeofIPv6Mreq = 0x14 + + sizeofICMPv6Filter = 0x20 +) + +type sockaddrInet6 struct { + Len uint8 + Family uint8 + Port uint16 + Flowinfo uint32 + Addr [16]byte /* in6_addr */ + Scope_id uint32 +} + +type inet6Pktinfo struct { + Addr [16]byte /* in6_addr */ + Ifindex uint32 +} + +type ipv6Mtuinfo struct { + Addr sockaddrInet6 + Mtu uint32 +} + +type ipv6Mreq struct { + Multiaddr [16]byte /* in6_addr */ + Interface uint32 +} + +type icmpv6Filter struct { + Filt [8]uint32 +} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_solaris.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_solaris.go new file mode 100644 index 000000000..171619747 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_solaris.go @@ -0,0 +1,63 @@ +// Code generated by cmd/cgo -godefs; DO NOT EDIT. +// cgo -godefs defs_solaris.go + +package ipv6 + +const ( + sizeofSockaddrStorage = 0x100 + sizeofSockaddrInet6 = 0x20 + sizeofInet6Pktinfo = 0x14 + sizeofIPv6Mtuinfo = 0x24 + + sizeofIPv6Mreq = 0x14 + sizeofGroupReq = 0x104 + sizeofGroupSourceReq = 0x204 + + sizeofICMPv6Filter = 0x20 +) + +type sockaddrStorage struct { + Family uint16 + X_ss_pad1 [6]int8 + X_ss_align float64 + X_ss_pad2 [240]int8 +} + +type sockaddrInet6 struct { + Family uint16 + Port uint16 + Flowinfo uint32 + Addr [16]byte /* in6_addr */ + Scope_id uint32 + X__sin6_src_id uint32 +} + +type inet6Pktinfo struct { + Addr [16]byte /* in6_addr */ + Ifindex uint32 +} + +type ipv6Mtuinfo struct { + Addr sockaddrInet6 + Mtu uint32 +} + +type ipv6Mreq struct { + Multiaddr [16]byte /* in6_addr */ + Interface uint32 +} + +type groupReq struct { + Interface uint32 + Pad_cgo_0 [256]byte +} + +type groupSourceReq struct { + Interface uint32 + Pad_cgo_0 [256]byte + Pad_cgo_1 [256]byte +} + +type icmpv6Filter struct { + X__icmp6_filt [8]uint32 +} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_zos_s390x.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_zos_s390x.go new file mode 100644 index 000000000..7c7564596 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/ipv6/zsys_zos_s390x.go @@ -0,0 +1,62 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Hand edited based on zerrors_zos_s390x.go +// TODO(Bill O'Farrell): auto-generate. + +package ipv6 + +const ( + sizeofSockaddrStorage = 128 + sizeofICMPv6Filter = 32 + sizeofInet6Pktinfo = 20 + sizeofIPv6Mtuinfo = 32 + sizeofSockaddrInet6 = 28 + sizeofGroupReq = 136 + sizeofGroupSourceReq = 264 +) + +type sockaddrStorage struct { + Len uint8 + Family byte + ss_pad1 [6]byte + ss_align int64 + ss_pad2 [112]byte +} + +type sockaddrInet6 struct { + Len uint8 + Family uint8 + Port uint16 + Flowinfo uint32 + Addr [16]byte + Scope_id uint32 +} + +type inet6Pktinfo struct { + Addr [16]byte + Ifindex uint32 +} + +type ipv6Mtuinfo struct { + Addr sockaddrInet6 + Mtu uint32 +} + +type groupReq struct { + Interface uint32 + reserved uint32 + Group sockaddrStorage +} + +type groupSourceReq struct { + Interface uint32 + reserved uint32 + Group sockaddrStorage + Source sockaddrStorage +} + +type icmpv6Filter struct { + Filt [8]uint32 +} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/proxy/per_host.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/proxy/per_host.go index 573fe79e8..d7d4b8b6e 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/proxy/per_host.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/net/proxy/per_host.go @@ -137,9 +137,7 @@ func (p *PerHost) AddNetwork(net *net.IPNet) { // AddZone specifies a DNS suffix that will use the bypass proxy. A zone of // "example.com" matches "example.com" and all of its subdomains. func (p *PerHost) AddZone(zone string) { - if strings.HasSuffix(zone, ".") { - zone = zone[:len(zone)-1] - } + zone = strings.TrimSuffix(zone, ".") if !strings.HasPrefix(zone, ".") { zone = "." + zone } @@ -148,8 +146,6 @@ func (p *PerHost) AddZone(zone string) { // AddHost specifies a host name that will use the bypass proxy. func (p *PerHost) AddHost(host string) { - if strings.HasSuffix(host, ".") { - host = host[:len(host)-1] - } + host = strings.TrimSuffix(host, ".") p.bypassHosts = append(p.bypassHosts, host) } diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/LICENSE b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/LICENSE index 6a66aea5e..2a7cf70da 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/LICENSE +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2009 The Go Authors. All rights reserved. +Copyright 2009 The Go Authors. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are @@ -10,7 +10,7 @@ notice, this list of conditions and the following disclaimer. copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - * Neither the name of Google Inc. nor the names of its + * Neither the name of Google LLC nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/cpu/asm_darwin_x86_gc.s b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/cpu/asm_darwin_x86_gc.s new file mode 100644 index 000000000..ec2acfe54 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/cpu/asm_darwin_x86_gc.s @@ -0,0 +1,17 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build darwin && amd64 && gc + +#include "textflag.h" + +TEXT libc_sysctl_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_sysctl(SB) +GLOBL ·libc_sysctl_trampoline_addr(SB), RODATA, $8 +DATA ·libc_sysctl_trampoline_addr(SB)/8, $libc_sysctl_trampoline<>(SB) + +TEXT libc_sysctlbyname_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_sysctlbyname(SB) +GLOBL ·libc_sysctlbyname_trampoline_addr(SB), RODATA, $8 +DATA ·libc_sysctlbyname_trampoline_addr(SB)/8, $libc_sysctlbyname_trampoline<>(SB) diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/cpu/cpu.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/cpu/cpu.go index 4756ad5f7..9c105f23a 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/cpu/cpu.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/cpu/cpu.go @@ -72,6 +72,9 @@ var X86 struct { HasSSSE3 bool // Supplemental streaming SIMD extension 3 HasSSE41 bool // Streaming SIMD extension 4 and 4.1 HasSSE42 bool // Streaming SIMD extension 4 and 4.2 + HasAVXIFMA bool // Advanced vector extension Integer Fused Multiply Add + HasAVXVNNI bool // Advanced vector extension Vector Neural Network Instructions + HasAVXVNNIInt8 bool // Advanced vector extension Vector Neural Network Int8 instructions _ CacheLinePad } @@ -103,7 +106,10 @@ var ARM64 struct { HasASIMDDP bool // Advanced SIMD double precision instruction set HasSHA512 bool // SHA512 hardware implementation HasSVE bool // Scalable Vector Extensions + HasSVE2 bool // Scalable Vector Extensions 2 HasASIMDFHM bool // Advanced SIMD multiplication FP16 to FP32 + HasDIT bool // Data Independent Timing support + HasI8MM bool // Advanced SIMD Int8 matrix multiplication instructions _ CacheLinePad } @@ -198,6 +204,25 @@ var S390X struct { _ CacheLinePad } +// RISCV64 contains the supported CPU features and performance characteristics for riscv64 +// platforms. The booleans in RISCV64, with the exception of HasFastMisaligned, indicate +// the presence of RISC-V extensions. +// +// It is safe to assume that all the RV64G extensions are supported and so they are omitted from +// this structure. As riscv64 Go programs require at least RV64G, the code that populates +// this structure cannot run successfully if some of the RV64G extensions are missing. +// The struct is padded to avoid false sharing. +var RISCV64 struct { + _ CacheLinePad + HasFastMisaligned bool // Fast misaligned accesses + HasC bool // Compressed instruction-set extension + HasV bool // Vector extension compatible with RVV 1.0 + HasZba bool // Address generation instructions extension + HasZbb bool // Basic bit-manipulation extension + HasZbs bool // Single-bit instructions extension + _ CacheLinePad +} + func init() { archInit() initOptions() diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/cpu/cpu_arm64.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/cpu/cpu_arm64.go index f3eb993bf..af2aa99f9 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/cpu/cpu_arm64.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/cpu/cpu_arm64.go @@ -28,6 +28,7 @@ func initOptions() { {Name: "sm3", Feature: &ARM64.HasSM3}, {Name: "sm4", Feature: &ARM64.HasSM4}, {Name: "sve", Feature: &ARM64.HasSVE}, + {Name: "sve2", Feature: &ARM64.HasSVE2}, {Name: "crc32", Feature: &ARM64.HasCRC32}, {Name: "atomics", Feature: &ARM64.HasATOMICS}, {Name: "asimdhp", Feature: &ARM64.HasASIMDHP}, @@ -37,6 +38,8 @@ func initOptions() { {Name: "dcpop", Feature: &ARM64.HasDCPOP}, {Name: "asimddp", Feature: &ARM64.HasASIMDDP}, {Name: "asimdfhm", Feature: &ARM64.HasASIMDFHM}, + {Name: "dit", Feature: &ARM64.HasDIT}, + {Name: "i8mm", Feature: &ARM64.HasI8MM}, } } @@ -144,6 +147,11 @@ func parseARM64SystemRegisters(isar0, isar1, pfr0 uint64) { ARM64.HasLRCPC = true } + switch extractBits(isar1, 52, 55) { + case 1: + ARM64.HasI8MM = true + } + // ID_AA64PFR0_EL1 switch extractBits(pfr0, 16, 19) { case 0: @@ -164,6 +172,20 @@ func parseARM64SystemRegisters(isar0, isar1, pfr0 uint64) { switch extractBits(pfr0, 32, 35) { case 1: ARM64.HasSVE = true + + parseARM64SVERegister(getzfr0()) + } + + switch extractBits(pfr0, 48, 51) { + case 1: + ARM64.HasDIT = true + } +} + +func parseARM64SVERegister(zfr0 uint64) { + switch extractBits(zfr0, 0, 3) { + case 1: + ARM64.HasSVE2 = true } } diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/cpu/cpu_arm64.s b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/cpu/cpu_arm64.s index fcb9a3888..22cc99844 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/cpu/cpu_arm64.s +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/cpu/cpu_arm64.s @@ -29,3 +29,11 @@ TEXT ·getpfr0(SB),NOSPLIT,$0-8 WORD $0xd5380400 MOVD R0, ret+0(FP) RET + +// func getzfr0() uint64 +TEXT ·getzfr0(SB),NOSPLIT,$0-8 + // get SVE Feature Register 0 into x0 + // mrs x0, ID_AA64ZFR0_EL1 = d5380480 + WORD $0xd5380480 + MOVD R0, ret+0(FP) + RET diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/cpu/cpu_darwin_x86.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/cpu/cpu_darwin_x86.go new file mode 100644 index 000000000..b838cb9e9 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/cpu/cpu_darwin_x86.go @@ -0,0 +1,61 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build darwin && amd64 && gc + +package cpu + +// darwinSupportsAVX512 checks Darwin kernel for AVX512 support via sysctl +// call (see issue 43089). It also restricts AVX512 support for Darwin to +// kernel version 21.3.0 (MacOS 12.2.0) or later (see issue 49233). +// +// Background: +// Darwin implements a special mechanism to economize on thread state when +// AVX512 specific registers are not in use. This scheme minimizes state when +// preempting threads that haven't yet used any AVX512 instructions, but adds +// special requirements to check for AVX512 hardware support at runtime (e.g. +// via sysctl call or commpage inspection). See issue 43089 and link below for +// full background: +// https://github.com/apple-oss-distributions/xnu/blob/xnu-11215.1.10/osfmk/i386/fpu.c#L214-L240 +// +// Additionally, all versions of the Darwin kernel from 19.6.0 through 21.2.0 +// (corresponding to MacOS 10.15.6 - 12.1) have a bug that can cause corruption +// of the AVX512 mask registers (K0-K7) upon signal return. For this reason +// AVX512 is considered unsafe to use on Darwin for kernel versions prior to +// 21.3.0, where a fix has been confirmed. See issue 49233 for full background. +func darwinSupportsAVX512() bool { + return darwinSysctlEnabled([]byte("hw.optional.avx512f\x00")) && darwinKernelVersionCheck(21, 3, 0) +} + +// Ensure Darwin kernel version is at least major.minor.patch, avoiding dependencies +func darwinKernelVersionCheck(major, minor, patch int) bool { + var release [256]byte + err := darwinOSRelease(&release) + if err != nil { + return false + } + + var mmp [3]int + c := 0 +Loop: + for _, b := range release[:] { + switch { + case b >= '0' && b <= '9': + mmp[c] = 10*mmp[c] + int(b-'0') + case b == '.': + c++ + if c > 2 { + return false + } + case b == 0: + break Loop + default: + return false + } + } + if c != 2 { + return false + } + return mmp[0] > major || mmp[0] == major && (mmp[1] > minor || mmp[1] == minor && mmp[2] >= patch) +} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/cpu/cpu_gc_arm64.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/cpu/cpu_gc_arm64.go index a8acd3e32..6ac6e1efb 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/cpu/cpu_gc_arm64.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/cpu/cpu_gc_arm64.go @@ -9,3 +9,4 @@ package cpu func getisar0() uint64 func getisar1() uint64 func getpfr0() uint64 +func getzfr0() uint64 diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/cpu/cpu_gc_x86.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/cpu/cpu_gc_x86.go index 910728fb1..32a44514e 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/cpu/cpu_gc_x86.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/cpu/cpu_gc_x86.go @@ -6,10 +6,10 @@ package cpu -// cpuid is implemented in cpu_x86.s for gc compiler +// cpuid is implemented in cpu_gc_x86.s for gc compiler // and in cpu_gccgo.c for gccgo. func cpuid(eaxArg, ecxArg uint32) (eax, ebx, ecx, edx uint32) -// xgetbv with ecx = 0 is implemented in cpu_x86.s for gc compiler +// xgetbv with ecx = 0 is implemented in cpu_gc_x86.s for gc compiler // and in cpu_gccgo.c for gccgo. func xgetbv() (eax, edx uint32) diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/cpu/cpu_x86.s b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/cpu/cpu_gc_x86.s similarity index 94% rename from trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/cpu/cpu_x86.s rename to trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/cpu/cpu_gc_x86.s index 7d7ba33ef..ce208ce6d 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/cpu/cpu_x86.s +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/cpu/cpu_gc_x86.s @@ -18,7 +18,7 @@ TEXT ·cpuid(SB), NOSPLIT, $0-24 RET // func xgetbv() (eax, edx uint32) -TEXT ·xgetbv(SB),NOSPLIT,$0-8 +TEXT ·xgetbv(SB), NOSPLIT, $0-8 MOVL $0, CX XGETBV MOVL AX, eax+0(FP) diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/cpu/cpu_gccgo_x86.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/cpu/cpu_gccgo_x86.go index 99c60fe9f..170d21ddf 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/cpu/cpu_gccgo_x86.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/cpu/cpu_gccgo_x86.go @@ -23,9 +23,3 @@ func xgetbv() (eax, edx uint32) { gccgoXgetbv(&a, &d) return a, d } - -// gccgo doesn't build on Darwin, per: -// https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/gcc.rb#L76 -func darwinSupportsAVX512() bool { - return false -} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/cpu/cpu_linux_arm64.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/cpu/cpu_linux_arm64.go index a968b80fa..f1caf0f78 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/cpu/cpu_linux_arm64.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/cpu/cpu_linux_arm64.go @@ -35,6 +35,10 @@ const ( hwcap_SHA512 = 1 << 21 hwcap_SVE = 1 << 22 hwcap_ASIMDFHM = 1 << 23 + hwcap_DIT = 1 << 24 + + hwcap2_SVE2 = 1 << 1 + hwcap2_I8MM = 1 << 13 ) // linuxKernelCanEmulateCPUID reports whether we're running @@ -104,6 +108,11 @@ func doinit() { ARM64.HasSHA512 = isSet(hwCap, hwcap_SHA512) ARM64.HasSVE = isSet(hwCap, hwcap_SVE) ARM64.HasASIMDFHM = isSet(hwCap, hwcap_ASIMDFHM) + ARM64.HasDIT = isSet(hwCap, hwcap_DIT) + + // HWCAP2 feature bits + ARM64.HasSVE2 = isSet(hwCap2, hwcap2_SVE2) + ARM64.HasI8MM = isSet(hwCap2, hwcap2_I8MM) } func isSet(hwc uint, value uint) bool { diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/cpu/cpu_linux_noinit.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/cpu/cpu_linux_noinit.go index cd63e7335..7d902b684 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/cpu/cpu_linux_noinit.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/cpu/cpu_linux_noinit.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build linux && !arm && !arm64 && !mips64 && !mips64le && !ppc64 && !ppc64le && !s390x +//go:build linux && !arm && !arm64 && !mips64 && !mips64le && !ppc64 && !ppc64le && !s390x && !riscv64 package cpu diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/cpu/cpu_linux_riscv64.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/cpu/cpu_linux_riscv64.go new file mode 100644 index 000000000..cb4a0c572 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/cpu/cpu_linux_riscv64.go @@ -0,0 +1,137 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package cpu + +import ( + "syscall" + "unsafe" +) + +// RISC-V extension discovery code for Linux. The approach here is to first try the riscv_hwprobe +// syscall falling back to HWCAP to check for the C extension if riscv_hwprobe is not available. +// +// A note on detection of the Vector extension using HWCAP. +// +// Support for the Vector extension version 1.0 was added to the Linux kernel in release 6.5. +// Support for the riscv_hwprobe syscall was added in 6.4. It follows that if the riscv_hwprobe +// syscall is not available then neither is the Vector extension (which needs kernel support). +// The riscv_hwprobe syscall should then be all we need to detect the Vector extension. +// However, some RISC-V board manufacturers ship boards with an older kernel on top of which +// they have back-ported various versions of the Vector extension patches but not the riscv_hwprobe +// patches. These kernels advertise support for the Vector extension using HWCAP. Falling +// back to HWCAP to detect the Vector extension, if riscv_hwprobe is not available, or simply not +// bothering with riscv_hwprobe at all and just using HWCAP may then seem like an attractive option. +// +// Unfortunately, simply checking the 'V' bit in AT_HWCAP will not work as this bit is used by +// RISC-V board and cloud instance providers to mean different things. The Lichee Pi 4A board +// and the Scaleway RV1 cloud instances use the 'V' bit to advertise their support for the unratified +// 0.7.1 version of the Vector Specification. The Banana Pi BPI-F3 and the CanMV-K230 board use +// it to advertise support for 1.0 of the Vector extension. Versions 0.7.1 and 1.0 of the Vector +// extension are binary incompatible. HWCAP can then not be used in isolation to populate the +// HasV field as this field indicates that the underlying CPU is compatible with RVV 1.0. +// +// There is a way at runtime to distinguish between versions 0.7.1 and 1.0 of the Vector +// specification by issuing a RVV 1.0 vsetvli instruction and checking the vill bit of the vtype +// register. This check would allow us to safely detect version 1.0 of the Vector extension +// with HWCAP, if riscv_hwprobe were not available. However, the check cannot +// be added until the assembler supports the Vector instructions. +// +// Note the riscv_hwprobe syscall does not suffer from these ambiguities by design as all of the +// extensions it advertises support for are explicitly versioned. It's also worth noting that +// the riscv_hwprobe syscall is the only way to detect multi-letter RISC-V extensions, e.g., Zba. +// These cannot be detected using HWCAP and so riscv_hwprobe must be used to detect the majority +// of RISC-V extensions. +// +// Please see https://docs.kernel.org/arch/riscv/hwprobe.html for more information. + +// golang.org/x/sys/cpu is not allowed to depend on golang.org/x/sys/unix so we must +// reproduce the constants, types and functions needed to make the riscv_hwprobe syscall +// here. + +const ( + // Copied from golang.org/x/sys/unix/ztypes_linux_riscv64.go. + riscv_HWPROBE_KEY_IMA_EXT_0 = 0x4 + riscv_HWPROBE_IMA_C = 0x2 + riscv_HWPROBE_IMA_V = 0x4 + riscv_HWPROBE_EXT_ZBA = 0x8 + riscv_HWPROBE_EXT_ZBB = 0x10 + riscv_HWPROBE_EXT_ZBS = 0x20 + riscv_HWPROBE_KEY_CPUPERF_0 = 0x5 + riscv_HWPROBE_MISALIGNED_FAST = 0x3 + riscv_HWPROBE_MISALIGNED_MASK = 0x7 +) + +const ( + // sys_RISCV_HWPROBE is copied from golang.org/x/sys/unix/zsysnum_linux_riscv64.go. + sys_RISCV_HWPROBE = 258 +) + +// riscvHWProbePairs is copied from golang.org/x/sys/unix/ztypes_linux_riscv64.go. +type riscvHWProbePairs struct { + key int64 + value uint64 +} + +const ( + // CPU features + hwcap_RISCV_ISA_C = 1 << ('C' - 'A') +) + +func doinit() { + // A slice of key/value pair structures is passed to the RISCVHWProbe syscall. The key + // field should be initialised with one of the key constants defined above, e.g., + // RISCV_HWPROBE_KEY_IMA_EXT_0. The syscall will set the value field to the appropriate value. + // If the kernel does not recognise a key it will set the key field to -1 and the value field to 0. + + pairs := []riscvHWProbePairs{ + {riscv_HWPROBE_KEY_IMA_EXT_0, 0}, + {riscv_HWPROBE_KEY_CPUPERF_0, 0}, + } + + // This call only indicates that extensions are supported if they are implemented on all cores. + if riscvHWProbe(pairs, 0) { + if pairs[0].key != -1 { + v := uint(pairs[0].value) + RISCV64.HasC = isSet(v, riscv_HWPROBE_IMA_C) + RISCV64.HasV = isSet(v, riscv_HWPROBE_IMA_V) + RISCV64.HasZba = isSet(v, riscv_HWPROBE_EXT_ZBA) + RISCV64.HasZbb = isSet(v, riscv_HWPROBE_EXT_ZBB) + RISCV64.HasZbs = isSet(v, riscv_HWPROBE_EXT_ZBS) + } + if pairs[1].key != -1 { + v := pairs[1].value & riscv_HWPROBE_MISALIGNED_MASK + RISCV64.HasFastMisaligned = v == riscv_HWPROBE_MISALIGNED_FAST + } + } + + // Let's double check with HWCAP if the C extension does not appear to be supported. + // This may happen if we're running on a kernel older than 6.4. + + if !RISCV64.HasC { + RISCV64.HasC = isSet(hwCap, hwcap_RISCV_ISA_C) + } +} + +func isSet(hwc uint, value uint) bool { + return hwc&value != 0 +} + +// riscvHWProbe is a simplified version of the generated wrapper function found in +// golang.org/x/sys/unix/zsyscall_linux_riscv64.go. We simplify it by removing the +// cpuCount and cpus parameters which we do not need. We always want to pass 0 for +// these parameters here so the kernel only reports the extensions that are present +// on all cores. +func riscvHWProbe(pairs []riscvHWProbePairs, flags uint) bool { + var _zero uintptr + var p0 unsafe.Pointer + if len(pairs) > 0 { + p0 = unsafe.Pointer(&pairs[0]) + } else { + p0 = unsafe.Pointer(&_zero) + } + + _, _, e1 := syscall.Syscall6(sys_RISCV_HWPROBE, uintptr(p0), uintptr(len(pairs)), uintptr(0), uintptr(0), uintptr(flags), 0) + return e1 == 0 +} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/cpu/cpu_other_x86.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/cpu/cpu_other_x86.go new file mode 100644 index 000000000..a0fd7e2f7 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/cpu/cpu_other_x86.go @@ -0,0 +1,11 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build 386 || amd64p32 || (amd64 && (!darwin || !gc)) + +package cpu + +func darwinSupportsAVX512() bool { + panic("only implemented for gc && amd64 && darwin") +} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/cpu/cpu_riscv64.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/cpu/cpu_riscv64.go index 7f0c79c00..aca3199c9 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/cpu/cpu_riscv64.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/cpu/cpu_riscv64.go @@ -8,4 +8,13 @@ package cpu const cacheLineSize = 64 -func initOptions() {} +func initOptions() { + options = []option{ + {Name: "fastmisaligned", Feature: &RISCV64.HasFastMisaligned}, + {Name: "c", Feature: &RISCV64.HasC}, + {Name: "v", Feature: &RISCV64.HasV}, + {Name: "zba", Feature: &RISCV64.HasZba}, + {Name: "zbb", Feature: &RISCV64.HasZbb}, + {Name: "zbs", Feature: &RISCV64.HasZbs}, + } +} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/cpu/cpu_x86.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/cpu/cpu_x86.go index c29f5e4c5..1e642f330 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/cpu/cpu_x86.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/cpu/cpu_x86.go @@ -53,6 +53,9 @@ func initOptions() { {Name: "sse41", Feature: &X86.HasSSE41}, {Name: "sse42", Feature: &X86.HasSSE42}, {Name: "ssse3", Feature: &X86.HasSSSE3}, + {Name: "avxifma", Feature: &X86.HasAVXIFMA}, + {Name: "avxvnni", Feature: &X86.HasAVXVNNI}, + {Name: "avxvnniint8", Feature: &X86.HasAVXVNNIInt8}, // These capabilities should always be enabled on amd64: {Name: "sse2", Feature: &X86.HasSSE2, Required: runtime.GOARCH == "amd64"}, @@ -92,10 +95,8 @@ func archInit() { osSupportsAVX = isSet(1, eax) && isSet(2, eax) if runtime.GOOS == "darwin" { - // Darwin doesn't save/restore AVX-512 mask registers correctly across signal handlers. - // Since users can't rely on mask register contents, let's not advertise AVX-512 support. - // See issue 49233. - osSupportsAVX512 = false + // Darwin requires special AVX512 checks, see cpu_darwin_x86.go + osSupportsAVX512 = osSupportsAVX && darwinSupportsAVX512() } else { // Check if OPMASK and ZMM registers have OS support. osSupportsAVX512 = osSupportsAVX && isSet(5, eax) && isSet(6, eax) && isSet(7, eax) @@ -108,7 +109,7 @@ func archInit() { return } - _, ebx7, ecx7, edx7 := cpuid(7, 0) + eax7, ebx7, ecx7, edx7 := cpuid(7, 0) X86.HasBMI1 = isSet(3, ebx7) X86.HasAVX2 = isSet(5, ebx7) && osSupportsAVX X86.HasBMI2 = isSet(8, ebx7) @@ -136,14 +137,24 @@ func archInit() { X86.HasAVX512VAES = isSet(9, ecx7) X86.HasAVX512VBMI2 = isSet(6, ecx7) X86.HasAVX512BITALG = isSet(12, ecx7) - - eax71, _, _, _ := cpuid(7, 1) - X86.HasAVX512BF16 = isSet(5, eax71) } X86.HasAMXTile = isSet(24, edx7) X86.HasAMXInt8 = isSet(25, edx7) X86.HasAMXBF16 = isSet(22, edx7) + + // These features depend on the second level of extended features. + if eax7 >= 1 { + eax71, _, _, edx71 := cpuid(7, 1) + if X86.HasAVX512 { + X86.HasAVX512BF16 = isSet(5, eax71) + } + if X86.HasAVX { + X86.HasAVXIFMA = isSet(23, eax71) + X86.HasAVXVNNI = isSet(4, eax71) + X86.HasAVXVNNIInt8 = isSet(4, edx71) + } + } } func isSet(bitpos uint, value uint32) bool { diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/cpu/syscall_darwin_x86_gc.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/cpu/syscall_darwin_x86_gc.go new file mode 100644 index 000000000..4d0888b0c --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/cpu/syscall_darwin_x86_gc.go @@ -0,0 +1,98 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Minimal copy of x/sys/unix so the cpu package can make a +// system call on Darwin without depending on x/sys/unix. + +//go:build darwin && amd64 && gc + +package cpu + +import ( + "syscall" + "unsafe" +) + +type _C_int int32 + +// adapted from unix.Uname() at x/sys/unix/syscall_darwin.go L419 +func darwinOSRelease(release *[256]byte) error { + // from x/sys/unix/zerrors_openbsd_amd64.go + const ( + CTL_KERN = 0x1 + KERN_OSRELEASE = 0x2 + ) + + mib := []_C_int{CTL_KERN, KERN_OSRELEASE} + n := unsafe.Sizeof(*release) + + return sysctl(mib, &release[0], &n, nil, 0) +} + +type Errno = syscall.Errno + +var _zero uintptr // Single-word zero for use when we need a valid pointer to 0 bytes. + +// from x/sys/unix/zsyscall_darwin_amd64.go L791-807 +func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) error { + var _p0 unsafe.Pointer + if len(mib) > 0 { + _p0 = unsafe.Pointer(&mib[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + if _, _, err := syscall_syscall6( + libc_sysctl_trampoline_addr, + uintptr(_p0), + uintptr(len(mib)), + uintptr(unsafe.Pointer(old)), + uintptr(unsafe.Pointer(oldlen)), + uintptr(unsafe.Pointer(new)), + uintptr(newlen), + ); err != 0 { + return err + } + + return nil +} + +var libc_sysctl_trampoline_addr uintptr + +// adapted from internal/cpu/cpu_arm64_darwin.go +func darwinSysctlEnabled(name []byte) bool { + out := int32(0) + nout := unsafe.Sizeof(out) + if ret := sysctlbyname(&name[0], (*byte)(unsafe.Pointer(&out)), &nout, nil, 0); ret != nil { + return false + } + return out > 0 +} + +//go:cgo_import_dynamic libc_sysctl sysctl "/usr/lib/libSystem.B.dylib" + +var libc_sysctlbyname_trampoline_addr uintptr + +// adapted from runtime/sys_darwin.go in the pattern of sysctl() above, as defined in x/sys/unix +func sysctlbyname(name *byte, old *byte, oldlen *uintptr, new *byte, newlen uintptr) error { + if _, _, err := syscall_syscall6( + libc_sysctlbyname_trampoline_addr, + uintptr(unsafe.Pointer(name)), + uintptr(unsafe.Pointer(old)), + uintptr(unsafe.Pointer(oldlen)), + uintptr(unsafe.Pointer(new)), + uintptr(newlen), + 0, + ); err != 0 { + return err + } + + return nil +} + +//go:cgo_import_dynamic libc_sysctlbyname sysctlbyname "/usr/lib/libSystem.B.dylib" + +// Implemented in the runtime package (runtime/sys_darwin.go) +func syscall_syscall6(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) + +//go:linkname syscall_syscall6 syscall.syscall6 diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/README.md b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/README.md index 7d3c060e1..6e08a76a7 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/README.md +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/README.md @@ -156,7 +156,7 @@ from the generated architecture-specific files listed below, and merge these into a common file for each OS. The merge is performed in the following steps: -1. Construct the set of common code that is idential in all architecture-specific files. +1. Construct the set of common code that is identical in all architecture-specific files. 2. Write this common code to the merged file. 3. Remove the common code from all architecture-specific files. diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/asm_zos_s390x.s b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/asm_zos_s390x.s index 2f67ba86d..813dfad7d 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/asm_zos_s390x.s +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/asm_zos_s390x.s @@ -9,9 +9,11 @@ #define PSALAA 1208(R0) #define GTAB64(x) 80(x) #define LCA64(x) 88(x) +#define SAVSTACK_ASYNC(x) 336(x) // in the LCA #define CAA(x) 8(x) -#define EDCHPXV(x) 1016(x) // in the CAA -#define SAVSTACK_ASYNC(x) 336(x) // in the LCA +#define CEECAATHDID(x) 976(x) // in the CAA +#define EDCHPXV(x) 1016(x) // in the CAA +#define GOCB(x) 1104(x) // in the CAA // SS_*, where x=SAVSTACK_ASYNC #define SS_LE(x) 0(x) @@ -19,394 +21,125 @@ #define SS_ERRNO(x) 16(x) #define SS_ERRNOJR(x) 20(x) -#define LE_CALL BYTE $0x0D; BYTE $0x76; // BL R7, R6 +// Function Descriptor Offsets +#define __errno 0x156*16 +#define __err2ad 0x16C*16 -TEXT ·clearErrno(SB),NOSPLIT,$0-0 - BL addrerrno<>(SB) - MOVD $0, 0(R3) +// Call Instructions +#define LE_CALL BYTE $0x0D; BYTE $0x76 // BL R7, R6 +#define SVC_LOAD BYTE $0x0A; BYTE $0x08 // SVC 08 LOAD +#define SVC_DELETE BYTE $0x0A; BYTE $0x09 // SVC 09 DELETE + +DATA zosLibVec<>(SB)/8, $0 +GLOBL zosLibVec<>(SB), NOPTR, $8 + +TEXT ·initZosLibVec(SB), NOSPLIT|NOFRAME, $0-0 + MOVW PSALAA, R8 + MOVD LCA64(R8), R8 + MOVD CAA(R8), R8 + MOVD EDCHPXV(R8), R8 + MOVD R8, zosLibVec<>(SB) + RET + +TEXT ·GetZosLibVec(SB), NOSPLIT|NOFRAME, $0-0 + MOVD zosLibVec<>(SB), R8 + MOVD R8, ret+0(FP) + RET + +TEXT ·clearErrno(SB), NOSPLIT, $0-0 + BL addrerrno<>(SB) + MOVD $0, 0(R3) RET // Returns the address of errno in R3. -TEXT addrerrno<>(SB),NOSPLIT|NOFRAME,$0-0 +TEXT addrerrno<>(SB), NOSPLIT|NOFRAME, $0-0 // Get library control area (LCA). - MOVW PSALAA, R8 - MOVD LCA64(R8), R8 + MOVW PSALAA, R8 + MOVD LCA64(R8), R8 // Get __errno FuncDesc. - MOVD CAA(R8), R9 - MOVD EDCHPXV(R9), R9 - ADD $(0x156*16), R9 - LMG 0(R9), R5, R6 + MOVD CAA(R8), R9 + MOVD EDCHPXV(R9), R9 + ADD $(__errno), R9 + LMG 0(R9), R5, R6 // Switch to saved LE stack. - MOVD SAVSTACK_ASYNC(R8), R9 - MOVD 0(R9), R4 - MOVD $0, 0(R9) + MOVD SAVSTACK_ASYNC(R8), R9 + MOVD 0(R9), R4 + MOVD $0, 0(R9) // Call __errno function. LE_CALL NOPH // Switch back to Go stack. - XOR R0, R0 // Restore R0 to $0. - MOVD R4, 0(R9) // Save stack pointer. - RET - -TEXT ·syscall_syscall(SB),NOSPLIT,$0-56 - BL runtime·entersyscall(SB) - MOVD a1+8(FP), R1 - MOVD a2+16(FP), R2 - MOVD a3+24(FP), R3 - - // Get library control area (LCA). - MOVW PSALAA, R8 - MOVD LCA64(R8), R8 - - // Get function. - MOVD CAA(R8), R9 - MOVD EDCHPXV(R9), R9 - MOVD trap+0(FP), R5 - SLD $4, R5 - ADD R5, R9 - LMG 0(R9), R5, R6 - - // Restore LE stack. - MOVD SAVSTACK_ASYNC(R8), R9 - MOVD 0(R9), R4 - MOVD $0, 0(R9) - - // Call function. - LE_CALL - NOPH - XOR R0, R0 // Restore R0 to $0. - MOVD R4, 0(R9) // Save stack pointer. - - MOVD R3, r1+32(FP) - MOVD R0, r2+40(FP) - MOVD R0, err+48(FP) - MOVW R3, R4 - CMP R4, $-1 - BNE done - BL addrerrno<>(SB) - MOVWZ 0(R3), R3 - MOVD R3, err+48(FP) -done: - BL runtime·exitsyscall(SB) - RET - -TEXT ·syscall_rawsyscall(SB),NOSPLIT,$0-56 - MOVD a1+8(FP), R1 - MOVD a2+16(FP), R2 - MOVD a3+24(FP), R3 - - // Get library control area (LCA). - MOVW PSALAA, R8 - MOVD LCA64(R8), R8 - - // Get function. - MOVD CAA(R8), R9 - MOVD EDCHPXV(R9), R9 - MOVD trap+0(FP), R5 - SLD $4, R5 - ADD R5, R9 - LMG 0(R9), R5, R6 - - // Restore LE stack. - MOVD SAVSTACK_ASYNC(R8), R9 - MOVD 0(R9), R4 - MOVD $0, 0(R9) - - // Call function. - LE_CALL - NOPH - XOR R0, R0 // Restore R0 to $0. - MOVD R4, 0(R9) // Save stack pointer. - - MOVD R3, r1+32(FP) - MOVD R0, r2+40(FP) - MOVD R0, err+48(FP) - MOVW R3, R4 - CMP R4, $-1 - BNE done - BL addrerrno<>(SB) - MOVWZ 0(R3), R3 - MOVD R3, err+48(FP) -done: - RET - -TEXT ·syscall_syscall6(SB),NOSPLIT,$0-80 - BL runtime·entersyscall(SB) - MOVD a1+8(FP), R1 - MOVD a2+16(FP), R2 - MOVD a3+24(FP), R3 - - // Get library control area (LCA). - MOVW PSALAA, R8 - MOVD LCA64(R8), R8 - - // Get function. - MOVD CAA(R8), R9 - MOVD EDCHPXV(R9), R9 - MOVD trap+0(FP), R5 - SLD $4, R5 - ADD R5, R9 - LMG 0(R9), R5, R6 - - // Restore LE stack. - MOVD SAVSTACK_ASYNC(R8), R9 - MOVD 0(R9), R4 - MOVD $0, 0(R9) - - // Fill in parameter list. - MOVD a4+32(FP), R12 - MOVD R12, (2176+24)(R4) - MOVD a5+40(FP), R12 - MOVD R12, (2176+32)(R4) - MOVD a6+48(FP), R12 - MOVD R12, (2176+40)(R4) - - // Call function. - LE_CALL - NOPH - XOR R0, R0 // Restore R0 to $0. - MOVD R4, 0(R9) // Save stack pointer. - - MOVD R3, r1+56(FP) - MOVD R0, r2+64(FP) - MOVD R0, err+72(FP) - MOVW R3, R4 - CMP R4, $-1 - BNE done - BL addrerrno<>(SB) - MOVWZ 0(R3), R3 - MOVD R3, err+72(FP) -done: - BL runtime·exitsyscall(SB) - RET - -TEXT ·syscall_rawsyscall6(SB),NOSPLIT,$0-80 - MOVD a1+8(FP), R1 - MOVD a2+16(FP), R2 - MOVD a3+24(FP), R3 - - // Get library control area (LCA). - MOVW PSALAA, R8 - MOVD LCA64(R8), R8 - - // Get function. - MOVD CAA(R8), R9 - MOVD EDCHPXV(R9), R9 - MOVD trap+0(FP), R5 - SLD $4, R5 - ADD R5, R9 - LMG 0(R9), R5, R6 - - // Restore LE stack. - MOVD SAVSTACK_ASYNC(R8), R9 - MOVD 0(R9), R4 - MOVD $0, 0(R9) - - // Fill in parameter list. - MOVD a4+32(FP), R12 - MOVD R12, (2176+24)(R4) - MOVD a5+40(FP), R12 - MOVD R12, (2176+32)(R4) - MOVD a6+48(FP), R12 - MOVD R12, (2176+40)(R4) - - // Call function. - LE_CALL - NOPH - XOR R0, R0 // Restore R0 to $0. - MOVD R4, 0(R9) // Save stack pointer. - - MOVD R3, r1+56(FP) - MOVD R0, r2+64(FP) - MOVD R0, err+72(FP) - MOVW R3, R4 - CMP R4, $-1 - BNE done - BL ·rrno<>(SB) - MOVWZ 0(R3), R3 - MOVD R3, err+72(FP) -done: - RET - -TEXT ·syscall_syscall9(SB),NOSPLIT,$0 - BL runtime·entersyscall(SB) - MOVD a1+8(FP), R1 - MOVD a2+16(FP), R2 - MOVD a3+24(FP), R3 - - // Get library control area (LCA). - MOVW PSALAA, R8 - MOVD LCA64(R8), R8 - - // Get function. - MOVD CAA(R8), R9 - MOVD EDCHPXV(R9), R9 - MOVD trap+0(FP), R5 - SLD $4, R5 - ADD R5, R9 - LMG 0(R9), R5, R6 - - // Restore LE stack. - MOVD SAVSTACK_ASYNC(R8), R9 - MOVD 0(R9), R4 - MOVD $0, 0(R9) - - // Fill in parameter list. - MOVD a4+32(FP), R12 - MOVD R12, (2176+24)(R4) - MOVD a5+40(FP), R12 - MOVD R12, (2176+32)(R4) - MOVD a6+48(FP), R12 - MOVD R12, (2176+40)(R4) - MOVD a7+56(FP), R12 - MOVD R12, (2176+48)(R4) - MOVD a8+64(FP), R12 - MOVD R12, (2176+56)(R4) - MOVD a9+72(FP), R12 - MOVD R12, (2176+64)(R4) - - // Call function. - LE_CALL - NOPH - XOR R0, R0 // Restore R0 to $0. - MOVD R4, 0(R9) // Save stack pointer. - - MOVD R3, r1+80(FP) - MOVD R0, r2+88(FP) - MOVD R0, err+96(FP) - MOVW R3, R4 - CMP R4, $-1 - BNE done - BL addrerrno<>(SB) - MOVWZ 0(R3), R3 - MOVD R3, err+96(FP) -done: - BL runtime·exitsyscall(SB) - RET - -TEXT ·syscall_rawsyscall9(SB),NOSPLIT,$0 - MOVD a1+8(FP), R1 - MOVD a2+16(FP), R2 - MOVD a3+24(FP), R3 - - // Get library control area (LCA). - MOVW PSALAA, R8 - MOVD LCA64(R8), R8 - - // Get function. - MOVD CAA(R8), R9 - MOVD EDCHPXV(R9), R9 - MOVD trap+0(FP), R5 - SLD $4, R5 - ADD R5, R9 - LMG 0(R9), R5, R6 - - // Restore LE stack. - MOVD SAVSTACK_ASYNC(R8), R9 - MOVD 0(R9), R4 - MOVD $0, 0(R9) - - // Fill in parameter list. - MOVD a4+32(FP), R12 - MOVD R12, (2176+24)(R4) - MOVD a5+40(FP), R12 - MOVD R12, (2176+32)(R4) - MOVD a6+48(FP), R12 - MOVD R12, (2176+40)(R4) - MOVD a7+56(FP), R12 - MOVD R12, (2176+48)(R4) - MOVD a8+64(FP), R12 - MOVD R12, (2176+56)(R4) - MOVD a9+72(FP), R12 - MOVD R12, (2176+64)(R4) - - // Call function. - LE_CALL - NOPH - XOR R0, R0 // Restore R0 to $0. - MOVD R4, 0(R9) // Save stack pointer. - - MOVD R3, r1+80(FP) - MOVD R0, r2+88(FP) - MOVD R0, err+96(FP) - MOVW R3, R4 - CMP R4, $-1 - BNE done - BL addrerrno<>(SB) - MOVWZ 0(R3), R3 - MOVD R3, err+96(FP) -done: + XOR R0, R0 // Restore R0 to $0. + MOVD R4, 0(R9) // Save stack pointer. RET // func svcCall(fnptr unsafe.Pointer, argv *unsafe.Pointer, dsa *uint64) -TEXT ·svcCall(SB),NOSPLIT,$0 - BL runtime·save_g(SB) // Save g and stack pointer - MOVW PSALAA, R8 - MOVD LCA64(R8), R8 - MOVD SAVSTACK_ASYNC(R8), R9 - MOVD R15, 0(R9) +TEXT ·svcCall(SB), NOSPLIT, $0 + BL runtime·save_g(SB) // Save g and stack pointer + MOVW PSALAA, R8 + MOVD LCA64(R8), R8 + MOVD SAVSTACK_ASYNC(R8), R9 + MOVD R15, 0(R9) - MOVD argv+8(FP), R1 // Move function arguments into registers - MOVD dsa+16(FP), g - MOVD fnptr+0(FP), R15 + MOVD argv+8(FP), R1 // Move function arguments into registers + MOVD dsa+16(FP), g + MOVD fnptr+0(FP), R15 - BYTE $0x0D // Branch to function - BYTE $0xEF + BYTE $0x0D // Branch to function + BYTE $0xEF - BL runtime·load_g(SB) // Restore g and stack pointer - MOVW PSALAA, R8 - MOVD LCA64(R8), R8 - MOVD SAVSTACK_ASYNC(R8), R9 - MOVD 0(R9), R15 + BL runtime·load_g(SB) // Restore g and stack pointer + MOVW PSALAA, R8 + MOVD LCA64(R8), R8 + MOVD SAVSTACK_ASYNC(R8), R9 + MOVD 0(R9), R15 RET // func svcLoad(name *byte) unsafe.Pointer -TEXT ·svcLoad(SB),NOSPLIT,$0 - MOVD R15, R2 // Save go stack pointer - MOVD name+0(FP), R0 // Move SVC args into registers - MOVD $0x80000000, R1 - MOVD $0, R15 - BYTE $0x0A // SVC 08 LOAD - BYTE $0x08 - MOVW R15, R3 // Save return code from SVC - MOVD R2, R15 // Restore go stack pointer - CMP R3, $0 // Check SVC return code - BNE error +TEXT ·svcLoad(SB), NOSPLIT, $0 + MOVD R15, R2 // Save go stack pointer + MOVD name+0(FP), R0 // Move SVC args into registers + MOVD $0x80000000, R1 + MOVD $0, R15 + SVC_LOAD + MOVW R15, R3 // Save return code from SVC + MOVD R2, R15 // Restore go stack pointer + CMP R3, $0 // Check SVC return code + BNE error - MOVD $-2, R3 // Reset last bit of entry point to zero - AND R0, R3 - MOVD R3, addr+8(FP) // Return entry point returned by SVC - CMP R0, R3 // Check if last bit of entry point was set - BNE done + MOVD $-2, R3 // Reset last bit of entry point to zero + AND R0, R3 + MOVD R3, ret+8(FP) // Return entry point returned by SVC + CMP R0, R3 // Check if last bit of entry point was set + BNE done - MOVD R15, R2 // Save go stack pointer - MOVD $0, R15 // Move SVC args into registers (entry point still in r0 from SVC 08) - BYTE $0x0A // SVC 09 DELETE - BYTE $0x09 - MOVD R2, R15 // Restore go stack pointer + MOVD R15, R2 // Save go stack pointer + MOVD $0, R15 // Move SVC args into registers (entry point still in r0 from SVC 08) + SVC_DELETE + MOVD R2, R15 // Restore go stack pointer error: - MOVD $0, addr+8(FP) // Return 0 on failure + MOVD $0, ret+8(FP) // Return 0 on failure + done: - XOR R0, R0 // Reset r0 to 0 + XOR R0, R0 // Reset r0 to 0 RET // func svcUnload(name *byte, fnptr unsafe.Pointer) int64 -TEXT ·svcUnload(SB),NOSPLIT,$0 - MOVD R15, R2 // Save go stack pointer - MOVD name+0(FP), R0 // Move SVC args into registers - MOVD addr+8(FP), R15 - BYTE $0x0A // SVC 09 - BYTE $0x09 - XOR R0, R0 // Reset r0 to 0 - MOVD R15, R1 // Save SVC return code - MOVD R2, R15 // Restore go stack pointer - MOVD R1, rc+0(FP) // Return SVC return code +TEXT ·svcUnload(SB), NOSPLIT, $0 + MOVD R15, R2 // Save go stack pointer + MOVD name+0(FP), R0 // Move SVC args into registers + MOVD fnptr+8(FP), R15 + SVC_DELETE + XOR R0, R0 // Reset r0 to 0 + MOVD R15, R1 // Save SVC return code + MOVD R2, R15 // Restore go stack pointer + MOVD R1, ret+16(FP) // Return SVC return code RET // func gettid() uint64 @@ -417,7 +150,233 @@ TEXT ·gettid(SB), NOSPLIT, $0 // Get CEECAATHDID MOVD CAA(R8), R9 - MOVD 0x3D0(R9), R9 + MOVD CEECAATHDID(R9), R9 MOVD R9, ret+0(FP) RET + +// +// Call LE function, if the return is -1 +// errno and errno2 is retrieved +// +TEXT ·CallLeFuncWithErr(SB), NOSPLIT, $0 + MOVW PSALAA, R8 + MOVD LCA64(R8), R8 + MOVD CAA(R8), R9 + MOVD g, GOCB(R9) + + // Restore LE stack. + MOVD SAVSTACK_ASYNC(R8), R9 // R9-> LE stack frame saving address + MOVD 0(R9), R4 // R4-> restore previously saved stack frame pointer + + MOVD parms_base+8(FP), R7 // R7 -> argument array + MOVD parms_len+16(FP), R8 // R8 number of arguments + + // arg 1 ---> R1 + CMP R8, $0 + BEQ docall + SUB $1, R8 + MOVD 0(R7), R1 + + // arg 2 ---> R2 + CMP R8, $0 + BEQ docall + SUB $1, R8 + ADD $8, R7 + MOVD 0(R7), R2 + + // arg 3 --> R3 + CMP R8, $0 + BEQ docall + SUB $1, R8 + ADD $8, R7 + MOVD 0(R7), R3 + + CMP R8, $0 + BEQ docall + MOVD $2176+16, R6 // starting LE stack address-8 to store 4th argument + +repeat: + ADD $8, R7 + MOVD 0(R7), R0 // advance arg pointer by 8 byte + ADD $8, R6 // advance LE argument address by 8 byte + MOVD R0, (R4)(R6*1) // copy argument from go-slice to le-frame + SUB $1, R8 + CMP R8, $0 + BNE repeat + +docall: + MOVD funcdesc+0(FP), R8 // R8-> function descriptor + LMG 0(R8), R5, R6 + MOVD $0, 0(R9) // R9 address of SAVSTACK_ASYNC + LE_CALL // balr R7, R6 (return #1) + NOPH + MOVD R3, ret+32(FP) + CMP R3, $-1 // compare result to -1 + BNE done + + // retrieve errno and errno2 + MOVD zosLibVec<>(SB), R8 + ADD $(__errno), R8 + LMG 0(R8), R5, R6 + LE_CALL // balr R7, R6 __errno (return #3) + NOPH + MOVWZ 0(R3), R3 + MOVD R3, err+48(FP) + MOVD zosLibVec<>(SB), R8 + ADD $(__err2ad), R8 + LMG 0(R8), R5, R6 + LE_CALL // balr R7, R6 __err2ad (return #2) + NOPH + MOVW (R3), R2 // retrieve errno2 + MOVD R2, errno2+40(FP) // store in return area + +done: + MOVD R4, 0(R9) // Save stack pointer. + RET + +// +// Call LE function, if the return is 0 +// errno and errno2 is retrieved +// +TEXT ·CallLeFuncWithPtrReturn(SB), NOSPLIT, $0 + MOVW PSALAA, R8 + MOVD LCA64(R8), R8 + MOVD CAA(R8), R9 + MOVD g, GOCB(R9) + + // Restore LE stack. + MOVD SAVSTACK_ASYNC(R8), R9 // R9-> LE stack frame saving address + MOVD 0(R9), R4 // R4-> restore previously saved stack frame pointer + + MOVD parms_base+8(FP), R7 // R7 -> argument array + MOVD parms_len+16(FP), R8 // R8 number of arguments + + // arg 1 ---> R1 + CMP R8, $0 + BEQ docall + SUB $1, R8 + MOVD 0(R7), R1 + + // arg 2 ---> R2 + CMP R8, $0 + BEQ docall + SUB $1, R8 + ADD $8, R7 + MOVD 0(R7), R2 + + // arg 3 --> R3 + CMP R8, $0 + BEQ docall + SUB $1, R8 + ADD $8, R7 + MOVD 0(R7), R3 + + CMP R8, $0 + BEQ docall + MOVD $2176+16, R6 // starting LE stack address-8 to store 4th argument + +repeat: + ADD $8, R7 + MOVD 0(R7), R0 // advance arg pointer by 8 byte + ADD $8, R6 // advance LE argument address by 8 byte + MOVD R0, (R4)(R6*1) // copy argument from go-slice to le-frame + SUB $1, R8 + CMP R8, $0 + BNE repeat + +docall: + MOVD funcdesc+0(FP), R8 // R8-> function descriptor + LMG 0(R8), R5, R6 + MOVD $0, 0(R9) // R9 address of SAVSTACK_ASYNC + LE_CALL // balr R7, R6 (return #1) + NOPH + MOVD R3, ret+32(FP) + CMP R3, $0 // compare result to 0 + BNE done + + // retrieve errno and errno2 + MOVD zosLibVec<>(SB), R8 + ADD $(__errno), R8 + LMG 0(R8), R5, R6 + LE_CALL // balr R7, R6 __errno (return #3) + NOPH + MOVWZ 0(R3), R3 + MOVD R3, err+48(FP) + MOVD zosLibVec<>(SB), R8 + ADD $(__err2ad), R8 + LMG 0(R8), R5, R6 + LE_CALL // balr R7, R6 __err2ad (return #2) + NOPH + MOVW (R3), R2 // retrieve errno2 + MOVD R2, errno2+40(FP) // store in return area + XOR R2, R2 + MOVWZ R2, (R3) // clear errno2 + +done: + MOVD R4, 0(R9) // Save stack pointer. + RET + +// +// function to test if a pointer can be safely dereferenced (content read) +// return 0 for succces +// +TEXT ·ptrtest(SB), NOSPLIT, $0-16 + MOVD arg+0(FP), R10 // test pointer in R10 + + // set up R2 to point to CEECAADMC + BYTE $0xE3; BYTE $0x20; BYTE $0x04; BYTE $0xB8; BYTE $0x00; BYTE $0x17 // llgt 2,1208 + BYTE $0xB9; BYTE $0x17; BYTE $0x00; BYTE $0x22 // llgtr 2,2 + BYTE $0xA5; BYTE $0x26; BYTE $0x7F; BYTE $0xFF // nilh 2,32767 + BYTE $0xE3; BYTE $0x22; BYTE $0x00; BYTE $0x58; BYTE $0x00; BYTE $0x04 // lg 2,88(2) + BYTE $0xE3; BYTE $0x22; BYTE $0x00; BYTE $0x08; BYTE $0x00; BYTE $0x04 // lg 2,8(2) + BYTE $0x41; BYTE $0x22; BYTE $0x03; BYTE $0x68 // la 2,872(2) + + // set up R5 to point to the "shunt" path which set 1 to R3 (failure) + BYTE $0xB9; BYTE $0x82; BYTE $0x00; BYTE $0x33 // xgr 3,3 + BYTE $0xA7; BYTE $0x55; BYTE $0x00; BYTE $0x04 // bras 5,lbl1 + BYTE $0xA7; BYTE $0x39; BYTE $0x00; BYTE $0x01 // lghi 3,1 + + // if r3 is not zero (failed) then branch to finish + BYTE $0xB9; BYTE $0x02; BYTE $0x00; BYTE $0x33 // lbl1 ltgr 3,3 + BYTE $0xA7; BYTE $0x74; BYTE $0x00; BYTE $0x08 // brc b'0111',lbl2 + + // stomic store shunt address in R5 into CEECAADMC + BYTE $0xE3; BYTE $0x52; BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x24 // stg 5,0(2) + + // now try reading from the test pointer in R10, if it fails it branches to the "lghi" instruction above + BYTE $0xE3; BYTE $0x9A; BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x04 // lg 9,0(10) + + // finish here, restore 0 into CEECAADMC + BYTE $0xB9; BYTE $0x82; BYTE $0x00; BYTE $0x99 // lbl2 xgr 9,9 + BYTE $0xE3; BYTE $0x92; BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x24 // stg 9,0(2) + MOVD R3, ret+8(FP) // result in R3 + RET + +// +// function to test if a untptr can be loaded from a pointer +// return 1: the 8-byte content +// 2: 0 for success, 1 for failure +// +// func safeload(ptr uintptr) ( value uintptr, error uintptr) +TEXT ·safeload(SB), NOSPLIT, $0-24 + MOVD ptr+0(FP), R10 // test pointer in R10 + MOVD $0x0, R6 + BYTE $0xE3; BYTE $0x20; BYTE $0x04; BYTE $0xB8; BYTE $0x00; BYTE $0x17 // llgt 2,1208 + BYTE $0xB9; BYTE $0x17; BYTE $0x00; BYTE $0x22 // llgtr 2,2 + BYTE $0xA5; BYTE $0x26; BYTE $0x7F; BYTE $0xFF // nilh 2,32767 + BYTE $0xE3; BYTE $0x22; BYTE $0x00; BYTE $0x58; BYTE $0x00; BYTE $0x04 // lg 2,88(2) + BYTE $0xE3; BYTE $0x22; BYTE $0x00; BYTE $0x08; BYTE $0x00; BYTE $0x04 // lg 2,8(2) + BYTE $0x41; BYTE $0x22; BYTE $0x03; BYTE $0x68 // la 2,872(2) + BYTE $0xB9; BYTE $0x82; BYTE $0x00; BYTE $0x33 // xgr 3,3 + BYTE $0xA7; BYTE $0x55; BYTE $0x00; BYTE $0x04 // bras 5,lbl1 + BYTE $0xA7; BYTE $0x39; BYTE $0x00; BYTE $0x01 // lghi 3,1 + BYTE $0xB9; BYTE $0x02; BYTE $0x00; BYTE $0x33 // lbl1 ltgr 3,3 + BYTE $0xA7; BYTE $0x74; BYTE $0x00; BYTE $0x08 // brc b'0111',lbl2 + BYTE $0xE3; BYTE $0x52; BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x24 // stg 5,0(2) + BYTE $0xE3; BYTE $0x6A; BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x04 // lg 6,0(10) + BYTE $0xB9; BYTE $0x82; BYTE $0x00; BYTE $0x99 // lbl2 xgr 9,9 + BYTE $0xE3; BYTE $0x92; BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x24 // stg 9,0(2) + MOVD R6, value+8(FP) // result in R6 + MOVD R3, error+16(FP) // error in R3 + RET diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/auxv.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/auxv.go new file mode 100644 index 000000000..37a82528f --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/auxv.go @@ -0,0 +1,36 @@ +// Copyright 2025 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build go1.21 && (aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos) + +package unix + +import ( + "syscall" + "unsafe" +) + +//go:linkname runtime_getAuxv runtime.getAuxv +func runtime_getAuxv() []uintptr + +// Auxv returns the ELF auxiliary vector as a sequence of key/value pairs. +// The returned slice is always a fresh copy, owned by the caller. +// It returns an error on non-ELF platforms, or if the auxiliary vector cannot be accessed, +// which happens in some locked-down environments and build modes. +func Auxv() ([][2]uintptr, error) { + vec := runtime_getAuxv() + vecLen := len(vec) + + if vecLen == 0 { + return nil, syscall.ENOENT + } + + if vecLen%2 != 0 { + return nil, syscall.EINVAL + } + + result := make([]uintptr, vecLen) + copy(result, vec) + return unsafe.Slice((*[2]uintptr)(unsafe.Pointer(&result[0])), vecLen/2), nil +} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/auxv_unsupported.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/auxv_unsupported.go new file mode 100644 index 000000000..1200487f2 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/auxv_unsupported.go @@ -0,0 +1,13 @@ +// Copyright 2025 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !go1.21 && (aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos) + +package unix + +import "syscall" + +func Auxv() ([][2]uintptr, error) { + return nil, syscall.ENOTSUP +} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/bpxsvc_zos.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/bpxsvc_zos.go new file mode 100644 index 000000000..39d647d86 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/bpxsvc_zos.go @@ -0,0 +1,657 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build zos + +package unix + +import ( + "bytes" + "fmt" + "unsafe" +) + +//go:noescape +func bpxcall(plist []unsafe.Pointer, bpx_offset int64) + +//go:noescape +func A2e([]byte) + +//go:noescape +func E2a([]byte) + +const ( + BPX4STA = 192 // stat + BPX4FST = 104 // fstat + BPX4LST = 132 // lstat + BPX4OPN = 156 // open + BPX4CLO = 72 // close + BPX4CHR = 500 // chattr + BPX4FCR = 504 // fchattr + BPX4LCR = 1180 // lchattr + BPX4CTW = 492 // cond_timed_wait + BPX4GTH = 1056 // __getthent + BPX4PTQ = 412 // pthread_quiesc + BPX4PTR = 320 // ptrace +) + +const ( + //options + //byte1 + BPX_OPNFHIGH = 0x80 + //byte2 + BPX_OPNFEXEC = 0x80 + //byte3 + BPX_O_NOLARGEFILE = 0x08 + BPX_O_LARGEFILE = 0x04 + BPX_O_ASYNCSIG = 0x02 + BPX_O_SYNC = 0x01 + //byte4 + BPX_O_CREXCL = 0xc0 + BPX_O_CREAT = 0x80 + BPX_O_EXCL = 0x40 + BPX_O_NOCTTY = 0x20 + BPX_O_TRUNC = 0x10 + BPX_O_APPEND = 0x08 + BPX_O_NONBLOCK = 0x04 + BPX_FNDELAY = 0x04 + BPX_O_RDWR = 0x03 + BPX_O_RDONLY = 0x02 + BPX_O_WRONLY = 0x01 + BPX_O_ACCMODE = 0x03 + BPX_O_GETFL = 0x0f + + //mode + // byte1 (file type) + BPX_FT_DIR = 1 + BPX_FT_CHARSPEC = 2 + BPX_FT_REGFILE = 3 + BPX_FT_FIFO = 4 + BPX_FT_SYMLINK = 5 + BPX_FT_SOCKET = 6 + //byte3 + BPX_S_ISUID = 0x08 + BPX_S_ISGID = 0x04 + BPX_S_ISVTX = 0x02 + BPX_S_IRWXU1 = 0x01 + BPX_S_IRUSR = 0x01 + //byte4 + BPX_S_IRWXU2 = 0xc0 + BPX_S_IWUSR = 0x80 + BPX_S_IXUSR = 0x40 + BPX_S_IRWXG = 0x38 + BPX_S_IRGRP = 0x20 + BPX_S_IWGRP = 0x10 + BPX_S_IXGRP = 0x08 + BPX_S_IRWXOX = 0x07 + BPX_S_IROTH = 0x04 + BPX_S_IWOTH = 0x02 + BPX_S_IXOTH = 0x01 + + CW_INTRPT = 1 + CW_CONDVAR = 32 + CW_TIMEOUT = 64 + + PGTHA_NEXT = 2 + PGTHA_CURRENT = 1 + PGTHA_FIRST = 0 + PGTHA_LAST = 3 + PGTHA_PROCESS = 0x80 + PGTHA_CONTTY = 0x40 + PGTHA_PATH = 0x20 + PGTHA_COMMAND = 0x10 + PGTHA_FILEDATA = 0x08 + PGTHA_THREAD = 0x04 + PGTHA_PTAG = 0x02 + PGTHA_COMMANDLONG = 0x01 + PGTHA_THREADFAST = 0x80 + PGTHA_FILEPATH = 0x40 + PGTHA_THDSIGMASK = 0x20 + // thread quiece mode + QUIESCE_TERM int32 = 1 + QUIESCE_FORCE int32 = 2 + QUIESCE_QUERY int32 = 3 + QUIESCE_FREEZE int32 = 4 + QUIESCE_UNFREEZE int32 = 5 + FREEZE_THIS_THREAD int32 = 6 + FREEZE_EXIT int32 = 8 + QUIESCE_SRB int32 = 9 +) + +type Pgtha struct { + Pid uint32 // 0 + Tid0 uint32 // 4 + Tid1 uint32 + Accesspid byte // C + Accesstid byte // D + Accessasid uint16 // E + Loginname [8]byte // 10 + Flag1 byte // 18 + Flag1b2 byte // 19 +} + +type Bpxystat_t struct { // DSECT BPXYSTAT + St_id [4]uint8 // 0 + St_length uint16 // 0x4 + St_version uint16 // 0x6 + St_mode uint32 // 0x8 + St_ino uint32 // 0xc + St_dev uint32 // 0x10 + St_nlink uint32 // 0x14 + St_uid uint32 // 0x18 + St_gid uint32 // 0x1c + St_size uint64 // 0x20 + St_atime uint32 // 0x28 + St_mtime uint32 // 0x2c + St_ctime uint32 // 0x30 + St_rdev uint32 // 0x34 + St_auditoraudit uint32 // 0x38 + St_useraudit uint32 // 0x3c + St_blksize uint32 // 0x40 + St_createtime uint32 // 0x44 + St_auditid [4]uint32 // 0x48 + St_res01 uint32 // 0x58 + Ft_ccsid uint16 // 0x5c + Ft_flags uint16 // 0x5e + St_res01a [2]uint32 // 0x60 + St_res02 uint32 // 0x68 + St_blocks uint32 // 0x6c + St_opaque [3]uint8 // 0x70 + St_visible uint8 // 0x73 + St_reftime uint32 // 0x74 + St_fid uint64 // 0x78 + St_filefmt uint8 // 0x80 + St_fspflag2 uint8 // 0x81 + St_res03 [2]uint8 // 0x82 + St_ctimemsec uint32 // 0x84 + St_seclabel [8]uint8 // 0x88 + St_res04 [4]uint8 // 0x90 + // end of version 1 + _ uint32 // 0x94 + St_atime64 uint64 // 0x98 + St_mtime64 uint64 // 0xa0 + St_ctime64 uint64 // 0xa8 + St_createtime64 uint64 // 0xb0 + St_reftime64 uint64 // 0xb8 + _ uint64 // 0xc0 + St_res05 [16]uint8 // 0xc8 + // end of version 2 +} + +type BpxFilestatus struct { + Oflag1 byte + Oflag2 byte + Oflag3 byte + Oflag4 byte +} + +type BpxMode struct { + Ftype byte + Mode1 byte + Mode2 byte + Mode3 byte +} + +// Thr attribute structure for extended attributes +type Bpxyatt_t struct { // DSECT BPXYATT + Att_id [4]uint8 + Att_version uint16 + Att_res01 [2]uint8 + Att_setflags1 uint8 + Att_setflags2 uint8 + Att_setflags3 uint8 + Att_setflags4 uint8 + Att_mode uint32 + Att_uid uint32 + Att_gid uint32 + Att_opaquemask [3]uint8 + Att_visblmaskres uint8 + Att_opaque [3]uint8 + Att_visibleres uint8 + Att_size_h uint32 + Att_size_l uint32 + Att_atime uint32 + Att_mtime uint32 + Att_auditoraudit uint32 + Att_useraudit uint32 + Att_ctime uint32 + Att_reftime uint32 + // end of version 1 + Att_filefmt uint8 + Att_res02 [3]uint8 + Att_filetag uint32 + Att_res03 [8]uint8 + // end of version 2 + Att_atime64 uint64 + Att_mtime64 uint64 + Att_ctime64 uint64 + Att_reftime64 uint64 + Att_seclabel [8]uint8 + Att_ver3res02 [8]uint8 + // end of version 3 +} + +func BpxOpen(name string, options *BpxFilestatus, mode *BpxMode) (rv int32, rc int32, rn int32) { + if len(name) < 1024 { + var namebuf [1024]byte + sz := int32(copy(namebuf[:], name)) + A2e(namebuf[:sz]) + var parms [7]unsafe.Pointer + parms[0] = unsafe.Pointer(&sz) + parms[1] = unsafe.Pointer(&namebuf[0]) + parms[2] = unsafe.Pointer(options) + parms[3] = unsafe.Pointer(mode) + parms[4] = unsafe.Pointer(&rv) + parms[5] = unsafe.Pointer(&rc) + parms[6] = unsafe.Pointer(&rn) + bpxcall(parms[:], BPX4OPN) + return rv, rc, rn + } + return -1, -1, -1 +} + +func BpxClose(fd int32) (rv int32, rc int32, rn int32) { + var parms [4]unsafe.Pointer + parms[0] = unsafe.Pointer(&fd) + parms[1] = unsafe.Pointer(&rv) + parms[2] = unsafe.Pointer(&rc) + parms[3] = unsafe.Pointer(&rn) + bpxcall(parms[:], BPX4CLO) + return rv, rc, rn +} + +func BpxFileFStat(fd int32, st *Bpxystat_t) (rv int32, rc int32, rn int32) { + st.St_id = [4]uint8{0xe2, 0xe3, 0xc1, 0xe3} + st.St_version = 2 + stat_sz := uint32(unsafe.Sizeof(*st)) + var parms [6]unsafe.Pointer + parms[0] = unsafe.Pointer(&fd) + parms[1] = unsafe.Pointer(&stat_sz) + parms[2] = unsafe.Pointer(st) + parms[3] = unsafe.Pointer(&rv) + parms[4] = unsafe.Pointer(&rc) + parms[5] = unsafe.Pointer(&rn) + bpxcall(parms[:], BPX4FST) + return rv, rc, rn +} + +func BpxFileStat(name string, st *Bpxystat_t) (rv int32, rc int32, rn int32) { + if len(name) < 1024 { + var namebuf [1024]byte + sz := int32(copy(namebuf[:], name)) + A2e(namebuf[:sz]) + st.St_id = [4]uint8{0xe2, 0xe3, 0xc1, 0xe3} + st.St_version = 2 + stat_sz := uint32(unsafe.Sizeof(*st)) + var parms [7]unsafe.Pointer + parms[0] = unsafe.Pointer(&sz) + parms[1] = unsafe.Pointer(&namebuf[0]) + parms[2] = unsafe.Pointer(&stat_sz) + parms[3] = unsafe.Pointer(st) + parms[4] = unsafe.Pointer(&rv) + parms[5] = unsafe.Pointer(&rc) + parms[6] = unsafe.Pointer(&rn) + bpxcall(parms[:], BPX4STA) + return rv, rc, rn + } + return -1, -1, -1 +} + +func BpxFileLStat(name string, st *Bpxystat_t) (rv int32, rc int32, rn int32) { + if len(name) < 1024 { + var namebuf [1024]byte + sz := int32(copy(namebuf[:], name)) + A2e(namebuf[:sz]) + st.St_id = [4]uint8{0xe2, 0xe3, 0xc1, 0xe3} + st.St_version = 2 + stat_sz := uint32(unsafe.Sizeof(*st)) + var parms [7]unsafe.Pointer + parms[0] = unsafe.Pointer(&sz) + parms[1] = unsafe.Pointer(&namebuf[0]) + parms[2] = unsafe.Pointer(&stat_sz) + parms[3] = unsafe.Pointer(st) + parms[4] = unsafe.Pointer(&rv) + parms[5] = unsafe.Pointer(&rc) + parms[6] = unsafe.Pointer(&rn) + bpxcall(parms[:], BPX4LST) + return rv, rc, rn + } + return -1, -1, -1 +} + +func BpxChattr(path string, attr *Bpxyatt_t) (rv int32, rc int32, rn int32) { + if len(path) >= 1024 { + return -1, -1, -1 + } + var namebuf [1024]byte + sz := int32(copy(namebuf[:], path)) + A2e(namebuf[:sz]) + attr_sz := uint32(unsafe.Sizeof(*attr)) + var parms [7]unsafe.Pointer + parms[0] = unsafe.Pointer(&sz) + parms[1] = unsafe.Pointer(&namebuf[0]) + parms[2] = unsafe.Pointer(&attr_sz) + parms[3] = unsafe.Pointer(attr) + parms[4] = unsafe.Pointer(&rv) + parms[5] = unsafe.Pointer(&rc) + parms[6] = unsafe.Pointer(&rn) + bpxcall(parms[:], BPX4CHR) + return rv, rc, rn +} + +func BpxLchattr(path string, attr *Bpxyatt_t) (rv int32, rc int32, rn int32) { + if len(path) >= 1024 { + return -1, -1, -1 + } + var namebuf [1024]byte + sz := int32(copy(namebuf[:], path)) + A2e(namebuf[:sz]) + attr_sz := uint32(unsafe.Sizeof(*attr)) + var parms [7]unsafe.Pointer + parms[0] = unsafe.Pointer(&sz) + parms[1] = unsafe.Pointer(&namebuf[0]) + parms[2] = unsafe.Pointer(&attr_sz) + parms[3] = unsafe.Pointer(attr) + parms[4] = unsafe.Pointer(&rv) + parms[5] = unsafe.Pointer(&rc) + parms[6] = unsafe.Pointer(&rn) + bpxcall(parms[:], BPX4LCR) + return rv, rc, rn +} + +func BpxFchattr(fd int32, attr *Bpxyatt_t) (rv int32, rc int32, rn int32) { + attr_sz := uint32(unsafe.Sizeof(*attr)) + var parms [6]unsafe.Pointer + parms[0] = unsafe.Pointer(&fd) + parms[1] = unsafe.Pointer(&attr_sz) + parms[2] = unsafe.Pointer(attr) + parms[3] = unsafe.Pointer(&rv) + parms[4] = unsafe.Pointer(&rc) + parms[5] = unsafe.Pointer(&rn) + bpxcall(parms[:], BPX4FCR) + return rv, rc, rn +} + +func BpxCondTimedWait(sec uint32, nsec uint32, events uint32, secrem *uint32, nsecrem *uint32) (rv int32, rc int32, rn int32) { + var parms [8]unsafe.Pointer + parms[0] = unsafe.Pointer(&sec) + parms[1] = unsafe.Pointer(&nsec) + parms[2] = unsafe.Pointer(&events) + parms[3] = unsafe.Pointer(secrem) + parms[4] = unsafe.Pointer(nsecrem) + parms[5] = unsafe.Pointer(&rv) + parms[6] = unsafe.Pointer(&rc) + parms[7] = unsafe.Pointer(&rn) + bpxcall(parms[:], BPX4CTW) + return rv, rc, rn +} +func BpxGetthent(in *Pgtha, outlen *uint32, out unsafe.Pointer) (rv int32, rc int32, rn int32) { + var parms [7]unsafe.Pointer + inlen := uint32(26) // nothing else will work. Go says Pgtha is 28-byte because of alignment, but Pgtha is "packed" and must be 26-byte + parms[0] = unsafe.Pointer(&inlen) + parms[1] = unsafe.Pointer(&in) + parms[2] = unsafe.Pointer(outlen) + parms[3] = unsafe.Pointer(&out) + parms[4] = unsafe.Pointer(&rv) + parms[5] = unsafe.Pointer(&rc) + parms[6] = unsafe.Pointer(&rn) + bpxcall(parms[:], BPX4GTH) + return rv, rc, rn +} +func ZosJobname() (jobname string, err error) { + var pgtha Pgtha + pgtha.Pid = uint32(Getpid()) + pgtha.Accesspid = PGTHA_CURRENT + pgtha.Flag1 = PGTHA_PROCESS + var out [256]byte + var outlen uint32 + outlen = 256 + rv, rc, rn := BpxGetthent(&pgtha, &outlen, unsafe.Pointer(&out[0])) + if rv == 0 { + gthc := []byte{0x87, 0xa3, 0x88, 0x83} // 'gthc' in ebcdic + ix := bytes.Index(out[:], gthc) + if ix == -1 { + err = fmt.Errorf("BPX4GTH: gthc return data not found") + return + } + jn := out[ix+80 : ix+88] // we didn't declare Pgthc, but jobname is 8-byte at offset 80 + E2a(jn) + jobname = string(bytes.TrimRight(jn, " ")) + + } else { + err = fmt.Errorf("BPX4GTH: rc=%d errno=%d reason=code=0x%x", rv, rc, rn) + } + return +} +func Bpx4ptq(code int32, data string) (rv int32, rc int32, rn int32) { + var userdata [8]byte + var parms [5]unsafe.Pointer + copy(userdata[:], data+" ") + A2e(userdata[:]) + parms[0] = unsafe.Pointer(&code) + parms[1] = unsafe.Pointer(&userdata[0]) + parms[2] = unsafe.Pointer(&rv) + parms[3] = unsafe.Pointer(&rc) + parms[4] = unsafe.Pointer(&rn) + bpxcall(parms[:], BPX4PTQ) + return rv, rc, rn +} + +const ( + PT_TRACE_ME = 0 // Debug this process + PT_READ_I = 1 // Read a full word + PT_READ_D = 2 // Read a full word + PT_READ_U = 3 // Read control info + PT_WRITE_I = 4 //Write a full word + PT_WRITE_D = 5 //Write a full word + PT_CONTINUE = 7 //Continue the process + PT_KILL = 8 //Terminate the process + PT_READ_GPR = 11 // Read GPR, CR, PSW + PT_READ_FPR = 12 // Read FPR + PT_READ_VR = 13 // Read VR + PT_WRITE_GPR = 14 // Write GPR, CR, PSW + PT_WRITE_FPR = 15 // Write FPR + PT_WRITE_VR = 16 // Write VR + PT_READ_BLOCK = 17 // Read storage + PT_WRITE_BLOCK = 19 // Write storage + PT_READ_GPRH = 20 // Read GPRH + PT_WRITE_GPRH = 21 // Write GPRH + PT_REGHSET = 22 // Read all GPRHs + PT_ATTACH = 30 // Attach to a process + PT_DETACH = 31 // Detach from a process + PT_REGSET = 32 // Read all GPRs + PT_REATTACH = 33 // Reattach to a process + PT_LDINFO = 34 // Read loader info + PT_MULTI = 35 // Multi process mode + PT_LD64INFO = 36 // RMODE64 Info Area + PT_BLOCKREQ = 40 // Block request + PT_THREAD_INFO = 60 // Read thread info + PT_THREAD_MODIFY = 61 + PT_THREAD_READ_FOCUS = 62 + PT_THREAD_WRITE_FOCUS = 63 + PT_THREAD_HOLD = 64 + PT_THREAD_SIGNAL = 65 + PT_EXPLAIN = 66 + PT_EVENTS = 67 + PT_THREAD_INFO_EXTENDED = 68 + PT_REATTACH2 = 71 + PT_CAPTURE = 72 + PT_UNCAPTURE = 73 + PT_GET_THREAD_TCB = 74 + PT_GET_ALET = 75 + PT_SWAPIN = 76 + PT_EXTENDED_EVENT = 98 + PT_RECOVER = 99 // Debug a program check + PT_GPR0 = 0 // General purpose register 0 + PT_GPR1 = 1 // General purpose register 1 + PT_GPR2 = 2 // General purpose register 2 + PT_GPR3 = 3 // General purpose register 3 + PT_GPR4 = 4 // General purpose register 4 + PT_GPR5 = 5 // General purpose register 5 + PT_GPR6 = 6 // General purpose register 6 + PT_GPR7 = 7 // General purpose register 7 + PT_GPR8 = 8 // General purpose register 8 + PT_GPR9 = 9 // General purpose register 9 + PT_GPR10 = 10 // General purpose register 10 + PT_GPR11 = 11 // General purpose register 11 + PT_GPR12 = 12 // General purpose register 12 + PT_GPR13 = 13 // General purpose register 13 + PT_GPR14 = 14 // General purpose register 14 + PT_GPR15 = 15 // General purpose register 15 + PT_FPR0 = 16 // Floating point register 0 + PT_FPR1 = 17 // Floating point register 1 + PT_FPR2 = 18 // Floating point register 2 + PT_FPR3 = 19 // Floating point register 3 + PT_FPR4 = 20 // Floating point register 4 + PT_FPR5 = 21 // Floating point register 5 + PT_FPR6 = 22 // Floating point register 6 + PT_FPR7 = 23 // Floating point register 7 + PT_FPR8 = 24 // Floating point register 8 + PT_FPR9 = 25 // Floating point register 9 + PT_FPR10 = 26 // Floating point register 10 + PT_FPR11 = 27 // Floating point register 11 + PT_FPR12 = 28 // Floating point register 12 + PT_FPR13 = 29 // Floating point register 13 + PT_FPR14 = 30 // Floating point register 14 + PT_FPR15 = 31 // Floating point register 15 + PT_FPC = 32 // Floating point control register + PT_PSW = 40 // PSW + PT_PSW0 = 40 // Left half of the PSW + PT_PSW1 = 41 // Right half of the PSW + PT_CR0 = 42 // Control register 0 + PT_CR1 = 43 // Control register 1 + PT_CR2 = 44 // Control register 2 + PT_CR3 = 45 // Control register 3 + PT_CR4 = 46 // Control register 4 + PT_CR5 = 47 // Control register 5 + PT_CR6 = 48 // Control register 6 + PT_CR7 = 49 // Control register 7 + PT_CR8 = 50 // Control register 8 + PT_CR9 = 51 // Control register 9 + PT_CR10 = 52 // Control register 10 + PT_CR11 = 53 // Control register 11 + PT_CR12 = 54 // Control register 12 + PT_CR13 = 55 // Control register 13 + PT_CR14 = 56 // Control register 14 + PT_CR15 = 57 // Control register 15 + PT_GPRH0 = 58 // GP High register 0 + PT_GPRH1 = 59 // GP High register 1 + PT_GPRH2 = 60 // GP High register 2 + PT_GPRH3 = 61 // GP High register 3 + PT_GPRH4 = 62 // GP High register 4 + PT_GPRH5 = 63 // GP High register 5 + PT_GPRH6 = 64 // GP High register 6 + PT_GPRH7 = 65 // GP High register 7 + PT_GPRH8 = 66 // GP High register 8 + PT_GPRH9 = 67 // GP High register 9 + PT_GPRH10 = 68 // GP High register 10 + PT_GPRH11 = 69 // GP High register 11 + PT_GPRH12 = 70 // GP High register 12 + PT_GPRH13 = 71 // GP High register 13 + PT_GPRH14 = 72 // GP High register 14 + PT_GPRH15 = 73 // GP High register 15 + PT_VR0 = 74 // Vector register 0 + PT_VR1 = 75 // Vector register 1 + PT_VR2 = 76 // Vector register 2 + PT_VR3 = 77 // Vector register 3 + PT_VR4 = 78 // Vector register 4 + PT_VR5 = 79 // Vector register 5 + PT_VR6 = 80 // Vector register 6 + PT_VR7 = 81 // Vector register 7 + PT_VR8 = 82 // Vector register 8 + PT_VR9 = 83 // Vector register 9 + PT_VR10 = 84 // Vector register 10 + PT_VR11 = 85 // Vector register 11 + PT_VR12 = 86 // Vector register 12 + PT_VR13 = 87 // Vector register 13 + PT_VR14 = 88 // Vector register 14 + PT_VR15 = 89 // Vector register 15 + PT_VR16 = 90 // Vector register 16 + PT_VR17 = 91 // Vector register 17 + PT_VR18 = 92 // Vector register 18 + PT_VR19 = 93 // Vector register 19 + PT_VR20 = 94 // Vector register 20 + PT_VR21 = 95 // Vector register 21 + PT_VR22 = 96 // Vector register 22 + PT_VR23 = 97 // Vector register 23 + PT_VR24 = 98 // Vector register 24 + PT_VR25 = 99 // Vector register 25 + PT_VR26 = 100 // Vector register 26 + PT_VR27 = 101 // Vector register 27 + PT_VR28 = 102 // Vector register 28 + PT_VR29 = 103 // Vector register 29 + PT_VR30 = 104 // Vector register 30 + PT_VR31 = 105 // Vector register 31 + PT_PSWG = 106 // PSWG + PT_PSWG0 = 106 // Bytes 0-3 + PT_PSWG1 = 107 // Bytes 4-7 + PT_PSWG2 = 108 // Bytes 8-11 (IA high word) + PT_PSWG3 = 109 // Bytes 12-15 (IA low word) +) + +func Bpx4ptr(request int32, pid int32, addr unsafe.Pointer, data unsafe.Pointer, buffer unsafe.Pointer) (rv int32, rc int32, rn int32) { + var parms [8]unsafe.Pointer + parms[0] = unsafe.Pointer(&request) + parms[1] = unsafe.Pointer(&pid) + parms[2] = unsafe.Pointer(&addr) + parms[3] = unsafe.Pointer(&data) + parms[4] = unsafe.Pointer(&buffer) + parms[5] = unsafe.Pointer(&rv) + parms[6] = unsafe.Pointer(&rc) + parms[7] = unsafe.Pointer(&rn) + bpxcall(parms[:], BPX4PTR) + return rv, rc, rn +} + +func copyU8(val uint8, dest []uint8) int { + if len(dest) < 1 { + return 0 + } + dest[0] = val + return 1 +} + +func copyU8Arr(src, dest []uint8) int { + if len(dest) < len(src) { + return 0 + } + for i, v := range src { + dest[i] = v + } + return len(src) +} + +func copyU16(val uint16, dest []uint16) int { + if len(dest) < 1 { + return 0 + } + dest[0] = val + return 1 +} + +func copyU32(val uint32, dest []uint32) int { + if len(dest) < 1 { + return 0 + } + dest[0] = val + return 1 +} + +func copyU32Arr(src, dest []uint32) int { + if len(dest) < len(src) { + return 0 + } + for i, v := range src { + dest[i] = v + } + return len(src) +} + +func copyU64(val uint64, dest []uint64) int { + if len(dest) < 1 { + return 0 + } + dest[0] = val + return 1 +} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/bpxsvc_zos.s b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/bpxsvc_zos.s new file mode 100644 index 000000000..4bd4a1798 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/bpxsvc_zos.s @@ -0,0 +1,192 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#include "go_asm.h" +#include "textflag.h" + +// function to call USS assembly language services +// +// doc: https://www.ibm.com/support/knowledgecenter/en/SSLTBW_3.1.0/com.ibm.zos.v3r1.bpxb100/bit64env.htm +// +// arg1 unsafe.Pointer array that ressembles an OS PLIST +// +// arg2 function offset as in +// doc: https://www.ibm.com/support/knowledgecenter/en/SSLTBW_3.1.0/com.ibm.zos.v3r1.bpxb100/bpx2cr_List_of_offsets.htm +// +// func bpxcall(plist []unsafe.Pointer, bpx_offset int64) + +TEXT ·bpxcall(SB), NOSPLIT|NOFRAME, $0 + MOVD plist_base+0(FP), R1 // r1 points to plist + MOVD bpx_offset+24(FP), R2 // r2 offset to BPX vector table + MOVD R14, R7 // save r14 + MOVD R15, R8 // save r15 + MOVWZ 16(R0), R9 + MOVWZ 544(R9), R9 + MOVWZ 24(R9), R9 // call vector in r9 + ADD R2, R9 // add offset to vector table + MOVWZ (R9), R9 // r9 points to entry point + BYTE $0x0D // BL R14,R9 --> basr r14,r9 + BYTE $0xE9 // clobbers 0,1,14,15 + MOVD R8, R15 // restore 15 + JMP R7 // return via saved return address + +// func A2e(arr [] byte) +// code page conversion from 819 to 1047 +TEXT ·A2e(SB), NOSPLIT|NOFRAME, $0 + MOVD arg_base+0(FP), R2 // pointer to arry of characters + MOVD arg_len+8(FP), R3 // count + XOR R0, R0 + XOR R1, R1 + BYTE $0xA7; BYTE $0x15; BYTE $0x00; BYTE $0x82 // BRAS 1,(2+(256/2)) + + // ASCII -> EBCDIC conversion table: + BYTE $0x00; BYTE $0x01; BYTE $0x02; BYTE $0x03 + BYTE $0x37; BYTE $0x2d; BYTE $0x2e; BYTE $0x2f + BYTE $0x16; BYTE $0x05; BYTE $0x15; BYTE $0x0b + BYTE $0x0c; BYTE $0x0d; BYTE $0x0e; BYTE $0x0f + BYTE $0x10; BYTE $0x11; BYTE $0x12; BYTE $0x13 + BYTE $0x3c; BYTE $0x3d; BYTE $0x32; BYTE $0x26 + BYTE $0x18; BYTE $0x19; BYTE $0x3f; BYTE $0x27 + BYTE $0x1c; BYTE $0x1d; BYTE $0x1e; BYTE $0x1f + BYTE $0x40; BYTE $0x5a; BYTE $0x7f; BYTE $0x7b + BYTE $0x5b; BYTE $0x6c; BYTE $0x50; BYTE $0x7d + BYTE $0x4d; BYTE $0x5d; BYTE $0x5c; BYTE $0x4e + BYTE $0x6b; BYTE $0x60; BYTE $0x4b; BYTE $0x61 + BYTE $0xf0; BYTE $0xf1; BYTE $0xf2; BYTE $0xf3 + BYTE $0xf4; BYTE $0xf5; BYTE $0xf6; BYTE $0xf7 + BYTE $0xf8; BYTE $0xf9; BYTE $0x7a; BYTE $0x5e + BYTE $0x4c; BYTE $0x7e; BYTE $0x6e; BYTE $0x6f + BYTE $0x7c; BYTE $0xc1; BYTE $0xc2; BYTE $0xc3 + BYTE $0xc4; BYTE $0xc5; BYTE $0xc6; BYTE $0xc7 + BYTE $0xc8; BYTE $0xc9; BYTE $0xd1; BYTE $0xd2 + BYTE $0xd3; BYTE $0xd4; BYTE $0xd5; BYTE $0xd6 + BYTE $0xd7; BYTE $0xd8; BYTE $0xd9; BYTE $0xe2 + BYTE $0xe3; BYTE $0xe4; BYTE $0xe5; BYTE $0xe6 + BYTE $0xe7; BYTE $0xe8; BYTE $0xe9; BYTE $0xad + BYTE $0xe0; BYTE $0xbd; BYTE $0x5f; BYTE $0x6d + BYTE $0x79; BYTE $0x81; BYTE $0x82; BYTE $0x83 + BYTE $0x84; BYTE $0x85; BYTE $0x86; BYTE $0x87 + BYTE $0x88; BYTE $0x89; BYTE $0x91; BYTE $0x92 + BYTE $0x93; BYTE $0x94; BYTE $0x95; BYTE $0x96 + BYTE $0x97; BYTE $0x98; BYTE $0x99; BYTE $0xa2 + BYTE $0xa3; BYTE $0xa4; BYTE $0xa5; BYTE $0xa6 + BYTE $0xa7; BYTE $0xa8; BYTE $0xa9; BYTE $0xc0 + BYTE $0x4f; BYTE $0xd0; BYTE $0xa1; BYTE $0x07 + BYTE $0x20; BYTE $0x21; BYTE $0x22; BYTE $0x23 + BYTE $0x24; BYTE $0x25; BYTE $0x06; BYTE $0x17 + BYTE $0x28; BYTE $0x29; BYTE $0x2a; BYTE $0x2b + BYTE $0x2c; BYTE $0x09; BYTE $0x0a; BYTE $0x1b + BYTE $0x30; BYTE $0x31; BYTE $0x1a; BYTE $0x33 + BYTE $0x34; BYTE $0x35; BYTE $0x36; BYTE $0x08 + BYTE $0x38; BYTE $0x39; BYTE $0x3a; BYTE $0x3b + BYTE $0x04; BYTE $0x14; BYTE $0x3e; BYTE $0xff + BYTE $0x41; BYTE $0xaa; BYTE $0x4a; BYTE $0xb1 + BYTE $0x9f; BYTE $0xb2; BYTE $0x6a; BYTE $0xb5 + BYTE $0xbb; BYTE $0xb4; BYTE $0x9a; BYTE $0x8a + BYTE $0xb0; BYTE $0xca; BYTE $0xaf; BYTE $0xbc + BYTE $0x90; BYTE $0x8f; BYTE $0xea; BYTE $0xfa + BYTE $0xbe; BYTE $0xa0; BYTE $0xb6; BYTE $0xb3 + BYTE $0x9d; BYTE $0xda; BYTE $0x9b; BYTE $0x8b + BYTE $0xb7; BYTE $0xb8; BYTE $0xb9; BYTE $0xab + BYTE $0x64; BYTE $0x65; BYTE $0x62; BYTE $0x66 + BYTE $0x63; BYTE $0x67; BYTE $0x9e; BYTE $0x68 + BYTE $0x74; BYTE $0x71; BYTE $0x72; BYTE $0x73 + BYTE $0x78; BYTE $0x75; BYTE $0x76; BYTE $0x77 + BYTE $0xac; BYTE $0x69; BYTE $0xed; BYTE $0xee + BYTE $0xeb; BYTE $0xef; BYTE $0xec; BYTE $0xbf + BYTE $0x80; BYTE $0xfd; BYTE $0xfe; BYTE $0xfb + BYTE $0xfc; BYTE $0xba; BYTE $0xae; BYTE $0x59 + BYTE $0x44; BYTE $0x45; BYTE $0x42; BYTE $0x46 + BYTE $0x43; BYTE $0x47; BYTE $0x9c; BYTE $0x48 + BYTE $0x54; BYTE $0x51; BYTE $0x52; BYTE $0x53 + BYTE $0x58; BYTE $0x55; BYTE $0x56; BYTE $0x57 + BYTE $0x8c; BYTE $0x49; BYTE $0xcd; BYTE $0xce + BYTE $0xcb; BYTE $0xcf; BYTE $0xcc; BYTE $0xe1 + BYTE $0x70; BYTE $0xdd; BYTE $0xde; BYTE $0xdb + BYTE $0xdc; BYTE $0x8d; BYTE $0x8e; BYTE $0xdf + +retry: + WORD $0xB9931022 // TROO 2,2,b'0001' + BVS retry + RET + +// func e2a(arr [] byte) +// code page conversion from 1047 to 819 +TEXT ·E2a(SB), NOSPLIT|NOFRAME, $0 + MOVD arg_base+0(FP), R2 // pointer to arry of characters + MOVD arg_len+8(FP), R3 // count + XOR R0, R0 + XOR R1, R1 + BYTE $0xA7; BYTE $0x15; BYTE $0x00; BYTE $0x82 // BRAS 1,(2+(256/2)) + + // EBCDIC -> ASCII conversion table: + BYTE $0x00; BYTE $0x01; BYTE $0x02; BYTE $0x03 + BYTE $0x9c; BYTE $0x09; BYTE $0x86; BYTE $0x7f + BYTE $0x97; BYTE $0x8d; BYTE $0x8e; BYTE $0x0b + BYTE $0x0c; BYTE $0x0d; BYTE $0x0e; BYTE $0x0f + BYTE $0x10; BYTE $0x11; BYTE $0x12; BYTE $0x13 + BYTE $0x9d; BYTE $0x0a; BYTE $0x08; BYTE $0x87 + BYTE $0x18; BYTE $0x19; BYTE $0x92; BYTE $0x8f + BYTE $0x1c; BYTE $0x1d; BYTE $0x1e; BYTE $0x1f + BYTE $0x80; BYTE $0x81; BYTE $0x82; BYTE $0x83 + BYTE $0x84; BYTE $0x85; BYTE $0x17; BYTE $0x1b + BYTE $0x88; BYTE $0x89; BYTE $0x8a; BYTE $0x8b + BYTE $0x8c; BYTE $0x05; BYTE $0x06; BYTE $0x07 + BYTE $0x90; BYTE $0x91; BYTE $0x16; BYTE $0x93 + BYTE $0x94; BYTE $0x95; BYTE $0x96; BYTE $0x04 + BYTE $0x98; BYTE $0x99; BYTE $0x9a; BYTE $0x9b + BYTE $0x14; BYTE $0x15; BYTE $0x9e; BYTE $0x1a + BYTE $0x20; BYTE $0xa0; BYTE $0xe2; BYTE $0xe4 + BYTE $0xe0; BYTE $0xe1; BYTE $0xe3; BYTE $0xe5 + BYTE $0xe7; BYTE $0xf1; BYTE $0xa2; BYTE $0x2e + BYTE $0x3c; BYTE $0x28; BYTE $0x2b; BYTE $0x7c + BYTE $0x26; BYTE $0xe9; BYTE $0xea; BYTE $0xeb + BYTE $0xe8; BYTE $0xed; BYTE $0xee; BYTE $0xef + BYTE $0xec; BYTE $0xdf; BYTE $0x21; BYTE $0x24 + BYTE $0x2a; BYTE $0x29; BYTE $0x3b; BYTE $0x5e + BYTE $0x2d; BYTE $0x2f; BYTE $0xc2; BYTE $0xc4 + BYTE $0xc0; BYTE $0xc1; BYTE $0xc3; BYTE $0xc5 + BYTE $0xc7; BYTE $0xd1; BYTE $0xa6; BYTE $0x2c + BYTE $0x25; BYTE $0x5f; BYTE $0x3e; BYTE $0x3f + BYTE $0xf8; BYTE $0xc9; BYTE $0xca; BYTE $0xcb + BYTE $0xc8; BYTE $0xcd; BYTE $0xce; BYTE $0xcf + BYTE $0xcc; BYTE $0x60; BYTE $0x3a; BYTE $0x23 + BYTE $0x40; BYTE $0x27; BYTE $0x3d; BYTE $0x22 + BYTE $0xd8; BYTE $0x61; BYTE $0x62; BYTE $0x63 + BYTE $0x64; BYTE $0x65; BYTE $0x66; BYTE $0x67 + BYTE $0x68; BYTE $0x69; BYTE $0xab; BYTE $0xbb + BYTE $0xf0; BYTE $0xfd; BYTE $0xfe; BYTE $0xb1 + BYTE $0xb0; BYTE $0x6a; BYTE $0x6b; BYTE $0x6c + BYTE $0x6d; BYTE $0x6e; BYTE $0x6f; BYTE $0x70 + BYTE $0x71; BYTE $0x72; BYTE $0xaa; BYTE $0xba + BYTE $0xe6; BYTE $0xb8; BYTE $0xc6; BYTE $0xa4 + BYTE $0xb5; BYTE $0x7e; BYTE $0x73; BYTE $0x74 + BYTE $0x75; BYTE $0x76; BYTE $0x77; BYTE $0x78 + BYTE $0x79; BYTE $0x7a; BYTE $0xa1; BYTE $0xbf + BYTE $0xd0; BYTE $0x5b; BYTE $0xde; BYTE $0xae + BYTE $0xac; BYTE $0xa3; BYTE $0xa5; BYTE $0xb7 + BYTE $0xa9; BYTE $0xa7; BYTE $0xb6; BYTE $0xbc + BYTE $0xbd; BYTE $0xbe; BYTE $0xdd; BYTE $0xa8 + BYTE $0xaf; BYTE $0x5d; BYTE $0xb4; BYTE $0xd7 + BYTE $0x7b; BYTE $0x41; BYTE $0x42; BYTE $0x43 + BYTE $0x44; BYTE $0x45; BYTE $0x46; BYTE $0x47 + BYTE $0x48; BYTE $0x49; BYTE $0xad; BYTE $0xf4 + BYTE $0xf6; BYTE $0xf2; BYTE $0xf3; BYTE $0xf5 + BYTE $0x7d; BYTE $0x4a; BYTE $0x4b; BYTE $0x4c + BYTE $0x4d; BYTE $0x4e; BYTE $0x4f; BYTE $0x50 + BYTE $0x51; BYTE $0x52; BYTE $0xb9; BYTE $0xfb + BYTE $0xfc; BYTE $0xf9; BYTE $0xfa; BYTE $0xff + BYTE $0x5c; BYTE $0xf7; BYTE $0x53; BYTE $0x54 + BYTE $0x55; BYTE $0x56; BYTE $0x57; BYTE $0x58 + BYTE $0x59; BYTE $0x5a; BYTE $0xb2; BYTE $0xd4 + BYTE $0xd6; BYTE $0xd2; BYTE $0xd3; BYTE $0xd5 + BYTE $0x30; BYTE $0x31; BYTE $0x32; BYTE $0x33 + BYTE $0x34; BYTE $0x35; BYTE $0x36; BYTE $0x37 + BYTE $0x38; BYTE $0x39; BYTE $0xb3; BYTE $0xdb + BYTE $0xdc; BYTE $0xd9; BYTE $0xda; BYTE $0x9f + +retry: + WORD $0xB9931022 // TROO 2,2,b'0001' + BVS retry + RET diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/epoll_zos.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/epoll_zos.go deleted file mode 100644 index 7753fddea..000000000 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/epoll_zos.go +++ /dev/null @@ -1,220 +0,0 @@ -// Copyright 2020 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build zos && s390x - -package unix - -import ( - "sync" -) - -// This file simulates epoll on z/OS using poll. - -// Analogous to epoll_event on Linux. -// TODO(neeilan): Pad is because the Linux kernel expects a 96-bit struct. We never pass this to the kernel; remove? -type EpollEvent struct { - Events uint32 - Fd int32 - Pad int32 -} - -const ( - EPOLLERR = 0x8 - EPOLLHUP = 0x10 - EPOLLIN = 0x1 - EPOLLMSG = 0x400 - EPOLLOUT = 0x4 - EPOLLPRI = 0x2 - EPOLLRDBAND = 0x80 - EPOLLRDNORM = 0x40 - EPOLLWRBAND = 0x200 - EPOLLWRNORM = 0x100 - EPOLL_CTL_ADD = 0x1 - EPOLL_CTL_DEL = 0x2 - EPOLL_CTL_MOD = 0x3 - // The following constants are part of the epoll API, but represent - // currently unsupported functionality on z/OS. - // EPOLL_CLOEXEC = 0x80000 - // EPOLLET = 0x80000000 - // EPOLLONESHOT = 0x40000000 - // EPOLLRDHUP = 0x2000 // Typically used with edge-triggered notis - // EPOLLEXCLUSIVE = 0x10000000 // Exclusive wake-up mode - // EPOLLWAKEUP = 0x20000000 // Relies on Linux's BLOCK_SUSPEND capability -) - -// TODO(neeilan): We can eliminate these epToPoll / pToEpoll calls by using identical mask values for POLL/EPOLL -// constants where possible The lower 16 bits of epoll events (uint32) can fit any system poll event (int16). - -// epToPollEvt converts epoll event field to poll equivalent. -// In epoll, Events is a 32-bit field, while poll uses 16 bits. -func epToPollEvt(events uint32) int16 { - var ep2p = map[uint32]int16{ - EPOLLIN: POLLIN, - EPOLLOUT: POLLOUT, - EPOLLHUP: POLLHUP, - EPOLLPRI: POLLPRI, - EPOLLERR: POLLERR, - } - - var pollEvts int16 = 0 - for epEvt, pEvt := range ep2p { - if (events & epEvt) != 0 { - pollEvts |= pEvt - } - } - - return pollEvts -} - -// pToEpollEvt converts 16 bit poll event bitfields to 32-bit epoll event fields. -func pToEpollEvt(revents int16) uint32 { - var p2ep = map[int16]uint32{ - POLLIN: EPOLLIN, - POLLOUT: EPOLLOUT, - POLLHUP: EPOLLHUP, - POLLPRI: EPOLLPRI, - POLLERR: EPOLLERR, - } - - var epollEvts uint32 = 0 - for pEvt, epEvt := range p2ep { - if (revents & pEvt) != 0 { - epollEvts |= epEvt - } - } - - return epollEvts -} - -// Per-process epoll implementation. -type epollImpl struct { - mu sync.Mutex - epfd2ep map[int]*eventPoll - nextEpfd int -} - -// eventPoll holds a set of file descriptors being watched by the process. A process can have multiple epoll instances. -// On Linux, this is an in-kernel data structure accessed through a fd. -type eventPoll struct { - mu sync.Mutex - fds map[int]*EpollEvent -} - -// epoll impl for this process. -var impl epollImpl = epollImpl{ - epfd2ep: make(map[int]*eventPoll), - nextEpfd: 0, -} - -func (e *epollImpl) epollcreate(size int) (epfd int, err error) { - e.mu.Lock() - defer e.mu.Unlock() - epfd = e.nextEpfd - e.nextEpfd++ - - e.epfd2ep[epfd] = &eventPoll{ - fds: make(map[int]*EpollEvent), - } - return epfd, nil -} - -func (e *epollImpl) epollcreate1(flag int) (fd int, err error) { - return e.epollcreate(4) -} - -func (e *epollImpl) epollctl(epfd int, op int, fd int, event *EpollEvent) (err error) { - e.mu.Lock() - defer e.mu.Unlock() - - ep, ok := e.epfd2ep[epfd] - if !ok { - - return EBADF - } - - switch op { - case EPOLL_CTL_ADD: - // TODO(neeilan): When we make epfds and fds disjoint, detect epoll - // loops here (instances watching each other) and return ELOOP. - if _, ok := ep.fds[fd]; ok { - return EEXIST - } - ep.fds[fd] = event - case EPOLL_CTL_MOD: - if _, ok := ep.fds[fd]; !ok { - return ENOENT - } - ep.fds[fd] = event - case EPOLL_CTL_DEL: - if _, ok := ep.fds[fd]; !ok { - return ENOENT - } - delete(ep.fds, fd) - - } - return nil -} - -// Must be called while holding ep.mu -func (ep *eventPoll) getFds() []int { - fds := make([]int, len(ep.fds)) - for fd := range ep.fds { - fds = append(fds, fd) - } - return fds -} - -func (e *epollImpl) epollwait(epfd int, events []EpollEvent, msec int) (n int, err error) { - e.mu.Lock() // in [rare] case of concurrent epollcreate + epollwait - ep, ok := e.epfd2ep[epfd] - - if !ok { - e.mu.Unlock() - return 0, EBADF - } - - pollfds := make([]PollFd, 4) - for fd, epollevt := range ep.fds { - pollfds = append(pollfds, PollFd{Fd: int32(fd), Events: epToPollEvt(epollevt.Events)}) - } - e.mu.Unlock() - - n, err = Poll(pollfds, msec) - if err != nil { - return n, err - } - - i := 0 - for _, pFd := range pollfds { - if pFd.Revents != 0 { - events[i] = EpollEvent{Fd: pFd.Fd, Events: pToEpollEvt(pFd.Revents)} - i++ - } - - if i == n { - break - } - } - - return n, nil -} - -func EpollCreate(size int) (fd int, err error) { - return impl.epollcreate(size) -} - -func EpollCreate1(flag int) (fd int, err error) { - return impl.epollcreate1(flag) -} - -func EpollCtl(epfd int, op int, fd int, event *EpollEvent) (err error) { - return impl.epollctl(epfd, op, fd, event) -} - -// Because EpollWait mutates events, the caller is expected to coordinate -// concurrent access if calling with the same epfd from multiple goroutines. -func EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) { - return impl.epollwait(epfd, events, msec) -} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/fstatfs_zos.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/fstatfs_zos.go deleted file mode 100644 index c8bde601e..000000000 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/fstatfs_zos.go +++ /dev/null @@ -1,163 +0,0 @@ -// Copyright 2020 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build zos && s390x - -package unix - -import ( - "unsafe" -) - -// This file simulates fstatfs on z/OS using fstatvfs and w_getmntent. - -func Fstatfs(fd int, stat *Statfs_t) (err error) { - var stat_v Statvfs_t - err = Fstatvfs(fd, &stat_v) - if err == nil { - // populate stat - stat.Type = 0 - stat.Bsize = stat_v.Bsize - stat.Blocks = stat_v.Blocks - stat.Bfree = stat_v.Bfree - stat.Bavail = stat_v.Bavail - stat.Files = stat_v.Files - stat.Ffree = stat_v.Ffree - stat.Fsid = stat_v.Fsid - stat.Namelen = stat_v.Namemax - stat.Frsize = stat_v.Frsize - stat.Flags = stat_v.Flag - for passn := 0; passn < 5; passn++ { - switch passn { - case 0: - err = tryGetmntent64(stat) - break - case 1: - err = tryGetmntent128(stat) - break - case 2: - err = tryGetmntent256(stat) - break - case 3: - err = tryGetmntent512(stat) - break - case 4: - err = tryGetmntent1024(stat) - break - default: - break - } - //proceed to return if: err is nil (found), err is nonnil but not ERANGE (another error occurred) - if err == nil || err != nil && err != ERANGE { - break - } - } - } - return err -} - -func tryGetmntent64(stat *Statfs_t) (err error) { - var mnt_ent_buffer struct { - header W_Mnth - filesys_info [64]W_Mntent - } - var buffer_size int = int(unsafe.Sizeof(mnt_ent_buffer)) - fs_count, err := W_Getmntent((*byte)(unsafe.Pointer(&mnt_ent_buffer)), buffer_size) - if err != nil { - return err - } - err = ERANGE //return ERANGE if no match is found in this batch - for i := 0; i < fs_count; i++ { - if stat.Fsid == uint64(mnt_ent_buffer.filesys_info[i].Dev) { - stat.Type = uint32(mnt_ent_buffer.filesys_info[i].Fstname[0]) - err = nil - break - } - } - return err -} - -func tryGetmntent128(stat *Statfs_t) (err error) { - var mnt_ent_buffer struct { - header W_Mnth - filesys_info [128]W_Mntent - } - var buffer_size int = int(unsafe.Sizeof(mnt_ent_buffer)) - fs_count, err := W_Getmntent((*byte)(unsafe.Pointer(&mnt_ent_buffer)), buffer_size) - if err != nil { - return err - } - err = ERANGE //return ERANGE if no match is found in this batch - for i := 0; i < fs_count; i++ { - if stat.Fsid == uint64(mnt_ent_buffer.filesys_info[i].Dev) { - stat.Type = uint32(mnt_ent_buffer.filesys_info[i].Fstname[0]) - err = nil - break - } - } - return err -} - -func tryGetmntent256(stat *Statfs_t) (err error) { - var mnt_ent_buffer struct { - header W_Mnth - filesys_info [256]W_Mntent - } - var buffer_size int = int(unsafe.Sizeof(mnt_ent_buffer)) - fs_count, err := W_Getmntent((*byte)(unsafe.Pointer(&mnt_ent_buffer)), buffer_size) - if err != nil { - return err - } - err = ERANGE //return ERANGE if no match is found in this batch - for i := 0; i < fs_count; i++ { - if stat.Fsid == uint64(mnt_ent_buffer.filesys_info[i].Dev) { - stat.Type = uint32(mnt_ent_buffer.filesys_info[i].Fstname[0]) - err = nil - break - } - } - return err -} - -func tryGetmntent512(stat *Statfs_t) (err error) { - var mnt_ent_buffer struct { - header W_Mnth - filesys_info [512]W_Mntent - } - var buffer_size int = int(unsafe.Sizeof(mnt_ent_buffer)) - fs_count, err := W_Getmntent((*byte)(unsafe.Pointer(&mnt_ent_buffer)), buffer_size) - if err != nil { - return err - } - err = ERANGE //return ERANGE if no match is found in this batch - for i := 0; i < fs_count; i++ { - if stat.Fsid == uint64(mnt_ent_buffer.filesys_info[i].Dev) { - stat.Type = uint32(mnt_ent_buffer.filesys_info[i].Fstname[0]) - err = nil - break - } - } - return err -} - -func tryGetmntent1024(stat *Statfs_t) (err error) { - var mnt_ent_buffer struct { - header W_Mnth - filesys_info [1024]W_Mntent - } - var buffer_size int = int(unsafe.Sizeof(mnt_ent_buffer)) - fs_count, err := W_Getmntent((*byte)(unsafe.Pointer(&mnt_ent_buffer)), buffer_size) - if err != nil { - return err - } - err = ERANGE //return ERANGE if no match is found in this batch - for i := 0; i < fs_count; i++ { - if stat.Fsid == uint64(mnt_ent_buffer.filesys_info[i].Dev) { - stat.Type = uint32(mnt_ent_buffer.filesys_info[i].Fstname[0]) - err = nil - break - } - } - return err -} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ioctl_linux.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ioctl_linux.go index dbe680eab..7ca4fa12a 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ioctl_linux.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ioctl_linux.go @@ -58,6 +58,102 @@ func IoctlGetEthtoolDrvinfo(fd int, ifname string) (*EthtoolDrvinfo, error) { return &value, err } +// IoctlGetEthtoolTsInfo fetches ethtool timestamping and PHC +// association for the network device specified by ifname. +func IoctlGetEthtoolTsInfo(fd int, ifname string) (*EthtoolTsInfo, error) { + ifr, err := NewIfreq(ifname) + if err != nil { + return nil, err + } + + value := EthtoolTsInfo{Cmd: ETHTOOL_GET_TS_INFO} + ifrd := ifr.withData(unsafe.Pointer(&value)) + + err = ioctlIfreqData(fd, SIOCETHTOOL, &ifrd) + return &value, err +} + +// IoctlGetHwTstamp retrieves the hardware timestamping configuration +// for the network device specified by ifname. +func IoctlGetHwTstamp(fd int, ifname string) (*HwTstampConfig, error) { + ifr, err := NewIfreq(ifname) + if err != nil { + return nil, err + } + + value := HwTstampConfig{} + ifrd := ifr.withData(unsafe.Pointer(&value)) + + err = ioctlIfreqData(fd, SIOCGHWTSTAMP, &ifrd) + return &value, err +} + +// IoctlSetHwTstamp updates the hardware timestamping configuration for +// the network device specified by ifname. +func IoctlSetHwTstamp(fd int, ifname string, cfg *HwTstampConfig) error { + ifr, err := NewIfreq(ifname) + if err != nil { + return err + } + ifrd := ifr.withData(unsafe.Pointer(cfg)) + return ioctlIfreqData(fd, SIOCSHWTSTAMP, &ifrd) +} + +// FdToClockID derives the clock ID from the file descriptor number +// - see clock_gettime(3), FD_TO_CLOCKID macros. The resulting ID is +// suitable for system calls like ClockGettime. +func FdToClockID(fd int) int32 { return int32((int(^fd) << 3) | 3) } + +// IoctlPtpClockGetcaps returns the description of a given PTP device. +func IoctlPtpClockGetcaps(fd int) (*PtpClockCaps, error) { + var value PtpClockCaps + err := ioctlPtr(fd, PTP_CLOCK_GETCAPS2, unsafe.Pointer(&value)) + return &value, err +} + +// IoctlPtpSysOffsetPrecise returns a description of the clock +// offset compared to the system clock. +func IoctlPtpSysOffsetPrecise(fd int) (*PtpSysOffsetPrecise, error) { + var value PtpSysOffsetPrecise + err := ioctlPtr(fd, PTP_SYS_OFFSET_PRECISE2, unsafe.Pointer(&value)) + return &value, err +} + +// IoctlPtpSysOffsetExtended returns an extended description of the +// clock offset compared to the system clock. The samples parameter +// specifies the desired number of measurements. +func IoctlPtpSysOffsetExtended(fd int, samples uint) (*PtpSysOffsetExtended, error) { + value := PtpSysOffsetExtended{Samples: uint32(samples)} + err := ioctlPtr(fd, PTP_SYS_OFFSET_EXTENDED2, unsafe.Pointer(&value)) + return &value, err +} + +// IoctlPtpPinGetfunc returns the configuration of the specified +// I/O pin on given PTP device. +func IoctlPtpPinGetfunc(fd int, index uint) (*PtpPinDesc, error) { + value := PtpPinDesc{Index: uint32(index)} + err := ioctlPtr(fd, PTP_PIN_GETFUNC2, unsafe.Pointer(&value)) + return &value, err +} + +// IoctlPtpPinSetfunc updates configuration of the specified PTP +// I/O pin. +func IoctlPtpPinSetfunc(fd int, pd *PtpPinDesc) error { + return ioctlPtr(fd, PTP_PIN_SETFUNC2, unsafe.Pointer(pd)) +} + +// IoctlPtpPeroutRequest configures the periodic output mode of the +// PTP I/O pins. +func IoctlPtpPeroutRequest(fd int, r *PtpPeroutRequest) error { + return ioctlPtr(fd, PTP_PEROUT_REQUEST2, unsafe.Pointer(r)) +} + +// IoctlPtpExttsRequest configures the external timestamping mode +// of the PTP I/O pins. +func IoctlPtpExttsRequest(fd int, r *PtpExttsRequest) error { + return ioctlPtr(fd, PTP_EXTTS_REQUEST2, unsafe.Pointer(r)) +} + // IoctlGetWatchdogInfo fetches information about a watchdog device from the // Linux watchdog API. For more information, see: // https://www.kernel.org/doc/html/latest/watchdog/watchdog-api.html. diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/mkerrors.sh b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/mkerrors.sh index fdcaa974d..6ab02b6c3 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/mkerrors.sh +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/mkerrors.sh @@ -58,6 +58,7 @@ includes_Darwin=' #define _DARWIN_USE_64_BIT_INODE #define __APPLE_USE_RFC_3542 #include +#include #include #include #include @@ -157,6 +158,16 @@ includes_Linux=' #endif #define _GNU_SOURCE +// See the description in unix/linux/types.go +#if defined(__ARM_EABI__) || \ + (defined(__mips__) && (_MIPS_SIM == _ABIO32)) || \ + (defined(__powerpc__) && (!defined(__powerpc64__))) +# ifdef _TIME_BITS +# undef _TIME_BITS +# endif +# define _TIME_BITS 32 +#endif + // is broken on powerpc64, as it fails to include definitions of // these structures. We just include them copied from . #if defined(__powerpc__) @@ -255,6 +266,7 @@ struct ltchars { #include #include #include +#include #include #include #include @@ -263,6 +275,7 @@ struct ltchars { #include #include #include +#include #include #include #include @@ -525,6 +538,7 @@ ccflags="$@" $2 ~ /^(AF|SOCK|SO|SOL|IPPROTO|IP|IPV6|TCP|MCAST|EVFILT|NOTE|SHUT|PROT|MAP|MREMAP|MFD|T?PACKET|MSG|SCM|MCL|DT|MADV|PR|LOCAL|TCPOPT|UDP)_/ || $2 ~ /^NFC_(GENL|PROTO|COMM|RF|SE|DIRECTION|LLCP|SOCKPROTO)_/ || $2 ~ /^NFC_.*_(MAX)?SIZE$/ || + $2 ~ /^PTP_/ || $2 ~ /^RAW_PAYLOAD_/ || $2 ~ /^[US]F_/ || $2 ~ /^TP_STATUS_/ || @@ -549,6 +563,8 @@ ccflags="$@" $2 !~ "NLA_TYPE_MASK" && $2 !~ /^RTC_VL_(ACCURACY|BACKUP|DATA)/ && $2 ~ /^(NETLINK|NLM|NLMSG|NLA|IFA|IFAN|RT|RTC|RTCF|RTN|RTPROT|RTNH|ARPHRD|ETH_P|NETNSA)_/ || + $2 ~ /^SOCK_|SK_DIAG_|SKNLGRP_$/ || + $2 ~ /^(CONNECT|SAE)_/ || $2 ~ /^FIORDCHK$/ || $2 ~ /^SIOC/ || $2 ~ /^TIOC/ || @@ -652,7 +668,7 @@ errors=$( signals=$( echo '#include ' | $CC -x c - -E -dM $ccflags | awk '$1=="#define" && $2 ~ /^SIG[A-Z0-9]+$/ { print $2 }' | - grep -v 'SIGSTKSIZE\|SIGSTKSZ\|SIGRT\|SIGMAX64' | + grep -E -v '(SIGSTKSIZE|SIGSTKSZ|SIGRT|SIGMAX64)' | sort ) @@ -662,7 +678,7 @@ echo '#include ' | $CC -x c - -E -dM $ccflags | sort >_error.grep echo '#include ' | $CC -x c - -E -dM $ccflags | awk '$1=="#define" && $2 ~ /^SIG[A-Z0-9]+$/ { print "^\t" $2 "[ \t]*=" }' | - grep -v 'SIGSTKSIZE\|SIGSTKSZ\|SIGRT\|SIGMAX64' | + grep -E -v '(SIGSTKSIZE|SIGSTKSZ|SIGRT|SIGMAX64)' | sort >_signal.grep echo '// mkerrors.sh' "$@" diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/mmap_nomremap.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/mmap_nomremap.go index 4b68e5978..7f602ffd2 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/mmap_nomremap.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/mmap_nomremap.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build aix || darwin || dragonfly || freebsd || openbsd || solaris +//go:build aix || darwin || dragonfly || freebsd || openbsd || solaris || zos package unix diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/mremap.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/mremap.go index fd45fe529..3a5e776f8 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/mremap.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/mremap.go @@ -50,3 +50,8 @@ func (m *mremapMmapper) Mremap(oldData []byte, newLength int, flags int) (data [ func Mremap(oldData []byte, newLength int, flags int) (data []byte, err error) { return mapper.Mremap(oldData, newLength, flags) } + +func MremapPtr(oldAddr unsafe.Pointer, oldSize uintptr, newAddr unsafe.Pointer, newSize uintptr, flags int) (ret unsafe.Pointer, err error) { + xaddr, err := mapper.mremap(uintptr(oldAddr), oldSize, newSize, flags, uintptr(newAddr)) + return unsafe.Pointer(xaddr), err +} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/pagesize_unix.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/pagesize_unix.go index 4d0a3430e..0482408d7 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/pagesize_unix.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/pagesize_unix.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris +//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos // For Unix, get the pagesize from the runtime. diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/readdirent_getdirentries.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/readdirent_getdirentries.go index 130398b6b..b903c0060 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/readdirent_getdirentries.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/readdirent_getdirentries.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build darwin +//go:build darwin || zos package unix diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/sockcmsg_zos.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/sockcmsg_zos.go new file mode 100644 index 000000000..3e53dbc02 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/sockcmsg_zos.go @@ -0,0 +1,58 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Socket control messages + +package unix + +import "unsafe" + +// UnixCredentials encodes credentials into a socket control message +// for sending to another process. This can be used for +// authentication. +func UnixCredentials(ucred *Ucred) []byte { + b := make([]byte, CmsgSpace(SizeofUcred)) + h := (*Cmsghdr)(unsafe.Pointer(&b[0])) + h.Level = SOL_SOCKET + h.Type = SCM_CREDENTIALS + h.SetLen(CmsgLen(SizeofUcred)) + *(*Ucred)(h.data(0)) = *ucred + return b +} + +// ParseUnixCredentials decodes a socket control message that contains +// credentials in a Ucred structure. To receive such a message, the +// SO_PASSCRED option must be enabled on the socket. +func ParseUnixCredentials(m *SocketControlMessage) (*Ucred, error) { + if m.Header.Level != SOL_SOCKET { + return nil, EINVAL + } + if m.Header.Type != SCM_CREDENTIALS { + return nil, EINVAL + } + ucred := *(*Ucred)(unsafe.Pointer(&m.Data[0])) + return &ucred, nil +} + +// PktInfo4 encodes Inet4Pktinfo into a socket control message of type IP_PKTINFO. +func PktInfo4(info *Inet4Pktinfo) []byte { + b := make([]byte, CmsgSpace(SizeofInet4Pktinfo)) + h := (*Cmsghdr)(unsafe.Pointer(&b[0])) + h.Level = SOL_IP + h.Type = IP_PKTINFO + h.SetLen(CmsgLen(SizeofInet4Pktinfo)) + *(*Inet4Pktinfo)(h.data(0)) = *info + return b +} + +// PktInfo6 encodes Inet6Pktinfo into a socket control message of type IPV6_PKTINFO. +func PktInfo6(info *Inet6Pktinfo) []byte { + b := make([]byte, CmsgSpace(SizeofInet6Pktinfo)) + h := (*Cmsghdr)(unsafe.Pointer(&b[0])) + h.Level = SOL_IPV6 + h.Type = IPV6_PKTINFO + h.SetLen(CmsgLen(SizeofInet6Pktinfo)) + *(*Inet6Pktinfo)(h.data(0)) = *info + return b +} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/symaddr_zos_s390x.s b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/symaddr_zos_s390x.s new file mode 100644 index 000000000..3c4f33cb6 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/symaddr_zos_s390x.s @@ -0,0 +1,75 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build zos && s390x && gc + +#include "textflag.h" + +// provide the address of function variable to be fixed up. + +TEXT ·getPipe2Addr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Pipe2(SB), R8 + MOVD R8, ret+0(FP) + RET + +TEXT ·get_FlockAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Flock(SB), R8 + MOVD R8, ret+0(FP) + RET + +TEXT ·get_GetxattrAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Getxattr(SB), R8 + MOVD R8, ret+0(FP) + RET + +TEXT ·get_NanosleepAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Nanosleep(SB), R8 + MOVD R8, ret+0(FP) + RET + +TEXT ·get_SetxattrAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Setxattr(SB), R8 + MOVD R8, ret+0(FP) + RET + +TEXT ·get_Wait4Addr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Wait4(SB), R8 + MOVD R8, ret+0(FP) + RET + +TEXT ·get_MountAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Mount(SB), R8 + MOVD R8, ret+0(FP) + RET + +TEXT ·get_UnmountAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Unmount(SB), R8 + MOVD R8, ret+0(FP) + RET + +TEXT ·get_UtimesNanoAtAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·UtimesNanoAt(SB), R8 + MOVD R8, ret+0(FP) + RET + +TEXT ·get_UtimesNanoAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·UtimesNano(SB), R8 + MOVD R8, ret+0(FP) + RET + +TEXT ·get_MkfifoatAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Mkfifoat(SB), R8 + MOVD R8, ret+0(FP) + RET + +TEXT ·get_ChtagAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Chtag(SB), R8 + MOVD R8, ret+0(FP) + RET + +TEXT ·get_ReadlinkatAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Readlinkat(SB), R8 + MOVD R8, ret+0(FP) + RET + diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/syscall_aix.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/syscall_aix.go index 67ce6cef2..6f15ba1ea 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/syscall_aix.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/syscall_aix.go @@ -360,7 +360,7 @@ func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, var status _C_int var r Pid_t err = ERESTART - // AIX wait4 may return with ERESTART errno, while the processus is still + // AIX wait4 may return with ERESTART errno, while the process is still // active. for err == ERESTART { r, err = wait4(Pid_t(pid), &status, options, rusage) diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/syscall_darwin.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/syscall_darwin.go index 59542a897..099867dee 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/syscall_darwin.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/syscall_darwin.go @@ -402,6 +402,18 @@ func IoctlSetIfreqMTU(fd int, ifreq *IfreqMTU) error { return ioctlPtr(fd, SIOCSIFMTU, unsafe.Pointer(ifreq)) } +//sys renamexNp(from string, to string, flag uint32) (err error) + +func RenamexNp(from string, to string, flag uint32) (err error) { + return renamexNp(from, to, flag) +} + +//sys renameatxNp(fromfd int, from string, tofd int, to string, flag uint32) (err error) + +func RenameatxNp(fromfd int, from string, tofd int, to string, flag uint32) (err error) { + return renameatxNp(fromfd, from, tofd, to, flag) +} + //sys sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) = SYS_SYSCTL func Uname(uname *Utsname) error { @@ -542,6 +554,55 @@ func SysctlKinfoProcSlice(name string, args ...int) ([]KinfoProc, error) { } } +//sys pthread_chdir_np(path string) (err error) + +func PthreadChdir(path string) (err error) { + return pthread_chdir_np(path) +} + +//sys pthread_fchdir_np(fd int) (err error) + +func PthreadFchdir(fd int) (err error) { + return pthread_fchdir_np(fd) +} + +// Connectx calls connectx(2) to initiate a connection on a socket. +// +// srcIf, srcAddr, and dstAddr are filled into a [SaEndpoints] struct and passed as the endpoints argument. +// +// - srcIf is the optional source interface index. 0 means unspecified. +// - srcAddr is the optional source address. nil means unspecified. +// - dstAddr is the destination address. +// +// On success, Connectx returns the number of bytes enqueued for transmission. +func Connectx(fd int, srcIf uint32, srcAddr, dstAddr Sockaddr, associd SaeAssocID, flags uint32, iov []Iovec, connid *SaeConnID) (n uintptr, err error) { + endpoints := SaEndpoints{ + Srcif: srcIf, + } + + if srcAddr != nil { + addrp, addrlen, err := srcAddr.sockaddr() + if err != nil { + return 0, err + } + endpoints.Srcaddr = (*RawSockaddr)(addrp) + endpoints.Srcaddrlen = uint32(addrlen) + } + + if dstAddr != nil { + addrp, addrlen, err := dstAddr.sockaddr() + if err != nil { + return 0, err + } + endpoints.Dstaddr = (*RawSockaddr)(addrp) + endpoints.Dstaddrlen = uint32(addrlen) + } + + err = connectx(fd, &endpoints, associd, flags, iov, &n, connid) + return +} + +//sys connectx(fd int, endpoints *SaEndpoints, associd SaeAssocID, flags uint32, iov []Iovec, n *uintptr, connid *SaeConnID) (err error) //sys sendfile(infd int, outfd int, offset int64, len *int64, hdtr unsafe.Pointer, flags int) (err error) //sys shmat(id int, addr uintptr, flag int) (ret uintptr, err error) diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/syscall_dragonfly.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/syscall_dragonfly.go index 97cb916f2..be8c00207 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/syscall_dragonfly.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/syscall_dragonfly.go @@ -246,6 +246,18 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e return sendfile(outfd, infd, offset, count) } +func Dup3(oldfd, newfd, flags int) error { + if oldfd == newfd || flags&^O_CLOEXEC != 0 { + return EINVAL + } + how := F_DUP2FD + if flags&O_CLOEXEC != 0 { + how = F_DUP2FD_CLOEXEC + } + _, err := fcntl(oldfd, how, newfd) + return err +} + /* * Exposed directly */ diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/syscall_hurd.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/syscall_hurd.go index ba46651f8..a6a2d2fc2 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/syscall_hurd.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/syscall_hurd.go @@ -11,6 +11,7 @@ package unix int ioctl(int, unsigned long int, uintptr_t); */ import "C" +import "unsafe" func ioctl(fd int, req uint, arg uintptr) (err error) { r0, er := C.ioctl(C.int(fd), C.ulong(req), C.uintptr_t(arg)) diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/syscall_linux.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/syscall_linux.go index 5682e2628..230a94549 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/syscall_linux.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/syscall_linux.go @@ -1295,6 +1295,48 @@ func GetsockoptTCPInfo(fd, level, opt int) (*TCPInfo, error) { return &value, err } +// GetsockoptTCPCCVegasInfo returns algorithm specific congestion control information for a socket using the "vegas" +// algorithm. +// +// The socket's congestion control algorighm can be retrieved via [GetsockoptString] with the [TCP_CONGESTION] option: +// +// algo, err := unix.GetsockoptString(fd, unix.IPPROTO_TCP, unix.TCP_CONGESTION) +func GetsockoptTCPCCVegasInfo(fd, level, opt int) (*TCPVegasInfo, error) { + var value [SizeofTCPCCInfo / 4]uint32 // ensure proper alignment + vallen := _Socklen(SizeofTCPCCInfo) + err := getsockopt(fd, level, opt, unsafe.Pointer(&value[0]), &vallen) + out := (*TCPVegasInfo)(unsafe.Pointer(&value[0])) + return out, err +} + +// GetsockoptTCPCCDCTCPInfo returns algorithm specific congestion control information for a socket using the "dctp" +// algorithm. +// +// The socket's congestion control algorighm can be retrieved via [GetsockoptString] with the [TCP_CONGESTION] option: +// +// algo, err := unix.GetsockoptString(fd, unix.IPPROTO_TCP, unix.TCP_CONGESTION) +func GetsockoptTCPCCDCTCPInfo(fd, level, opt int) (*TCPDCTCPInfo, error) { + var value [SizeofTCPCCInfo / 4]uint32 // ensure proper alignment + vallen := _Socklen(SizeofTCPCCInfo) + err := getsockopt(fd, level, opt, unsafe.Pointer(&value[0]), &vallen) + out := (*TCPDCTCPInfo)(unsafe.Pointer(&value[0])) + return out, err +} + +// GetsockoptTCPCCBBRInfo returns algorithm specific congestion control information for a socket using the "bbr" +// algorithm. +// +// The socket's congestion control algorighm can be retrieved via [GetsockoptString] with the [TCP_CONGESTION] option: +// +// algo, err := unix.GetsockoptString(fd, unix.IPPROTO_TCP, unix.TCP_CONGESTION) +func GetsockoptTCPCCBBRInfo(fd, level, opt int) (*TCPBBRInfo, error) { + var value [SizeofTCPCCInfo / 4]uint32 // ensure proper alignment + vallen := _Socklen(SizeofTCPCCInfo) + err := getsockopt(fd, level, opt, unsafe.Pointer(&value[0]), &vallen) + out := (*TCPBBRInfo)(unsafe.Pointer(&value[0])) + return out, err +} + // GetsockoptString returns the string value of the socket option opt for the // socket associated with fd at the given socket level. func GetsockoptString(fd, level, opt int) (string, error) { @@ -1818,6 +1860,7 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e //sys ClockAdjtime(clockid int32, buf *Timex) (state int, err error) //sys ClockGetres(clockid int32, res *Timespec) (err error) //sys ClockGettime(clockid int32, time *Timespec) (err error) +//sys ClockSettime(clockid int32, time *Timespec) (err error) //sys ClockNanosleep(clockid int32, flags int, request *Timespec, remain *Timespec) (err error) //sys Close(fd int) (err error) //sys CloseRange(first uint, last uint, flags uint) (err error) @@ -1959,7 +2002,26 @@ func Getpgrp() (pid int) { //sysnb Getpid() (pid int) //sysnb Getppid() (ppid int) //sys Getpriority(which int, who int) (prio int, err error) -//sys Getrandom(buf []byte, flags int) (n int, err error) + +func Getrandom(buf []byte, flags int) (n int, err error) { + vdsoRet, supported := vgetrandom(buf, uint32(flags)) + if supported { + if vdsoRet < 0 { + return 0, errnoErr(syscall.Errno(-vdsoRet)) + } + return vdsoRet, nil + } + var p *byte + if len(buf) > 0 { + p = &buf[0] + } + r, _, e := Syscall(SYS_GETRANDOM, uintptr(unsafe.Pointer(p)), uintptr(len(buf)), uintptr(flags)) + if e != 0 { + return 0, errnoErr(e) + } + return int(r), nil +} + //sysnb Getrusage(who int, rusage *Rusage) (err error) //sysnb Getsid(pid int) (sid int, err error) //sysnb Gettid() (tid int) @@ -2592,3 +2654,4 @@ func SchedGetAttr(pid int, flags uint) (*SchedAttr, error) { } //sys Cachestat(fd uint, crange *CachestatRange, cstat *Cachestat_t, flags uint) (err error) +//sys Mseal(b []byte, flags uint) (err error) diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/syscall_linux_arm64.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/syscall_linux_arm64.go index cf2ee6c75..745e5c7e6 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/syscall_linux_arm64.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/syscall_linux_arm64.go @@ -182,3 +182,5 @@ func KexecFileLoad(kernelFd int, initrdFd int, cmdline string, flags int) error } return kexecFileLoad(kernelFd, initrdFd, cmdlineLen, cmdline, flags) } + +const SYS_FSTATAT = SYS_NEWFSTATAT diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/syscall_linux_loong64.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/syscall_linux_loong64.go index 3d0e98451..dd2262a40 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/syscall_linux_loong64.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/syscall_linux_loong64.go @@ -214,3 +214,5 @@ func KexecFileLoad(kernelFd int, initrdFd int, cmdline string, flags int) error } return kexecFileLoad(kernelFd, initrdFd, cmdlineLen, cmdline, flags) } + +const SYS_FSTATAT = SYS_NEWFSTATAT diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/syscall_linux_riscv64.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/syscall_linux_riscv64.go index 6f5a28894..8cf3670bd 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/syscall_linux_riscv64.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/syscall_linux_riscv64.go @@ -187,3 +187,5 @@ func RISCVHWProbe(pairs []RISCVHWProbePairs, set *CPUSet, flags uint) (err error } return riscvHWProbe(pairs, setSize, set, flags) } + +const SYS_FSTATAT = SYS_NEWFSTATAT diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/syscall_openbsd.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/syscall_openbsd.go index b25343c71..b86ded549 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/syscall_openbsd.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/syscall_openbsd.go @@ -293,6 +293,7 @@ func Uname(uname *Utsname) error { //sys Mkfifoat(dirfd int, path string, mode uint32) (err error) //sys Mknod(path string, mode uint32, dev int) (err error) //sys Mknodat(dirfd int, path string, mode uint32, dev int) (err error) +//sys Mount(fsType string, dir string, flags int, data unsafe.Pointer) (err error) //sys Nanosleep(time *Timespec, leftover *Timespec) (err error) //sys Open(path string, mode int, perm uint32) (fd int, err error) //sys Openat(dirfd int, path string, mode int, perm uint32) (fd int, err error) diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/syscall_solaris.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/syscall_solaris.go index 21974af06..abc395547 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/syscall_solaris.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/syscall_solaris.go @@ -1102,3 +1102,90 @@ func (s *Strioctl) SetInt(i int) { func IoctlSetStrioctlRetInt(fd int, req int, s *Strioctl) (int, error) { return ioctlPtrRet(fd, req, unsafe.Pointer(s)) } + +// Ucred Helpers +// See ucred(3c) and getpeerucred(3c) + +//sys getpeerucred(fd uintptr, ucred *uintptr) (err error) +//sys ucredFree(ucred uintptr) = ucred_free +//sys ucredGet(pid int) (ucred uintptr, err error) = ucred_get +//sys ucredGeteuid(ucred uintptr) (uid int) = ucred_geteuid +//sys ucredGetegid(ucred uintptr) (gid int) = ucred_getegid +//sys ucredGetruid(ucred uintptr) (uid int) = ucred_getruid +//sys ucredGetrgid(ucred uintptr) (gid int) = ucred_getrgid +//sys ucredGetsuid(ucred uintptr) (uid int) = ucred_getsuid +//sys ucredGetsgid(ucred uintptr) (gid int) = ucred_getsgid +//sys ucredGetpid(ucred uintptr) (pid int) = ucred_getpid + +// Ucred is an opaque struct that holds user credentials. +type Ucred struct { + ucred uintptr +} + +// We need to ensure that ucredFree is called on the underlying ucred +// when the Ucred is garbage collected. +func ucredFinalizer(u *Ucred) { + ucredFree(u.ucred) +} + +func GetPeerUcred(fd uintptr) (*Ucred, error) { + var ucred uintptr + err := getpeerucred(fd, &ucred) + if err != nil { + return nil, err + } + result := &Ucred{ + ucred: ucred, + } + // set the finalizer on the result so that the ucred will be freed + runtime.SetFinalizer(result, ucredFinalizer) + return result, nil +} + +func UcredGet(pid int) (*Ucred, error) { + ucred, err := ucredGet(pid) + if err != nil { + return nil, err + } + result := &Ucred{ + ucred: ucred, + } + // set the finalizer on the result so that the ucred will be freed + runtime.SetFinalizer(result, ucredFinalizer) + return result, nil +} + +func (u *Ucred) Geteuid() int { + defer runtime.KeepAlive(u) + return ucredGeteuid(u.ucred) +} + +func (u *Ucred) Getruid() int { + defer runtime.KeepAlive(u) + return ucredGetruid(u.ucred) +} + +func (u *Ucred) Getsuid() int { + defer runtime.KeepAlive(u) + return ucredGetsuid(u.ucred) +} + +func (u *Ucred) Getegid() int { + defer runtime.KeepAlive(u) + return ucredGetegid(u.ucred) +} + +func (u *Ucred) Getrgid() int { + defer runtime.KeepAlive(u) + return ucredGetrgid(u.ucred) +} + +func (u *Ucred) Getsgid() int { + defer runtime.KeepAlive(u) + return ucredGetsgid(u.ucred) +} + +func (u *Ucred) Getpid() int { + defer runtime.KeepAlive(u) + return ucredGetpid(u.ucred) +} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/syscall_unix.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/syscall_unix.go index 77081de8c..4e92e5aa4 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/syscall_unix.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/syscall_unix.go @@ -154,6 +154,15 @@ func Munmap(b []byte) (err error) { return mapper.Munmap(b) } +func MmapPtr(fd int, offset int64, addr unsafe.Pointer, length uintptr, prot int, flags int) (ret unsafe.Pointer, err error) { + xaddr, err := mapper.mmap(uintptr(addr), length, prot, flags, fd, offset) + return unsafe.Pointer(xaddr), err +} + +func MunmapPtr(addr unsafe.Pointer, length uintptr) (err error) { + return mapper.munmap(uintptr(addr), length) +} + func Read(fd int, p []byte) (n int, err error) { n, err = read(fd, p) if raceenabled { diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/syscall_zos_s390x.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/syscall_zos_s390x.go index b473038c6..7bf5c04bb 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/syscall_zos_s390x.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/syscall_zos_s390x.go @@ -4,11 +4,21 @@ //go:build zos && s390x +// Many of the following syscalls are not available on all versions of z/OS. +// Some missing calls have legacy implementations/simulations but others +// will be missing completely. To achieve consistent failing behaviour on +// legacy systems, we first test the function pointer via a safeloading +// mechanism to see if the function exists on a given system. Then execution +// is branched to either continue the function call, or return an error. + package unix import ( "bytes" "fmt" + "os" + "reflect" + "regexp" "runtime" "sort" "strings" @@ -17,17 +27,205 @@ import ( "unsafe" ) +//go:noescape +func initZosLibVec() + +//go:noescape +func GetZosLibVec() uintptr + +func init() { + initZosLibVec() + r0, _, _ := CallLeFuncWithPtrReturn(GetZosLibVec()+SYS_____GETENV_A<<4, uintptr(unsafe.Pointer(&([]byte("__ZOS_XSYSTRACE\x00"))[0]))) + if r0 != 0 { + n, _, _ := CallLeFuncWithPtrReturn(GetZosLibVec()+SYS___ATOI_A<<4, r0) + ZosTraceLevel = int(n) + r0, _, _ := CallLeFuncWithPtrReturn(GetZosLibVec()+SYS_____GETENV_A<<4, uintptr(unsafe.Pointer(&([]byte("__ZOS_XSYSTRACEFD\x00"))[0]))) + if r0 != 0 { + fd, _, _ := CallLeFuncWithPtrReturn(GetZosLibVec()+SYS___ATOI_A<<4, r0) + f := os.NewFile(fd, "zostracefile") + if f != nil { + ZosTracefile = f + } + } + + } +} + +//go:noescape +func CallLeFuncWithErr(funcdesc uintptr, parms ...uintptr) (ret, errno2 uintptr, err Errno) + +//go:noescape +func CallLeFuncWithPtrReturn(funcdesc uintptr, parms ...uintptr) (ret, errno2 uintptr, err Errno) + +// ------------------------------- +// pointer validity test +// good pointer returns 0 +// bad pointer returns 1 +// +//go:nosplit +func ptrtest(uintptr) uint64 + +// Load memory at ptr location with error handling if the location is invalid +// +//go:noescape +func safeload(ptr uintptr) (value uintptr, error uintptr) + const ( - O_CLOEXEC = 0 // Dummy value (not supported). - AF_LOCAL = AF_UNIX // AF_LOCAL is an alias for AF_UNIX + entrypointLocationOffset = 8 // From function descriptor + + xplinkEyecatcher = 0x00c300c500c500f1 // ".C.E.E.1" + eyecatcherOffset = 16 // From function entrypoint (negative) + ppa1LocationOffset = 8 // From function entrypoint (negative) + + nameLenOffset = 0x14 // From PPA1 start + nameOffset = 0x16 // From PPA1 start ) -func syscall_syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) -func syscall_rawsyscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) -func syscall_syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) -func syscall_rawsyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) -func syscall_syscall9(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err Errno) -func syscall_rawsyscall9(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err Errno) +func getPpaOffset(funcptr uintptr) int64 { + entrypoint, err := safeload(funcptr + entrypointLocationOffset) + if err != 0 { + return -1 + } + + // XPLink functions have ".C.E.E.1" as the first 8 bytes (EBCDIC) + val, err := safeload(entrypoint - eyecatcherOffset) + if err != 0 { + return -1 + } + if val != xplinkEyecatcher { + return -1 + } + + ppaoff, err := safeload(entrypoint - ppa1LocationOffset) + if err != 0 { + return -1 + } + + ppaoff >>= 32 + return int64(ppaoff) +} + +//------------------------------- +// function descriptor pointer validity test +// good pointer returns 0 +// bad pointer returns 1 + +// TODO: currently mksyscall_zos_s390x.go generate empty string for funcName +// have correct funcName pass to the funcptrtest function +func funcptrtest(funcptr uintptr, funcName string) uint64 { + entrypoint, err := safeload(funcptr + entrypointLocationOffset) + if err != 0 { + return 1 + } + + ppaoff := getPpaOffset(funcptr) + if ppaoff == -1 { + return 1 + } + + // PPA1 offset value is from the start of the entire function block, not the entrypoint + ppa1 := (entrypoint - eyecatcherOffset) + uintptr(ppaoff) + + nameLen, err := safeload(ppa1 + nameLenOffset) + if err != 0 { + return 1 + } + + nameLen >>= 48 + if nameLen > 128 { + return 1 + } + + // no function name input to argument end here + if funcName == "" { + return 0 + } + + var funcname [128]byte + for i := 0; i < int(nameLen); i += 8 { + v, err := safeload(ppa1 + nameOffset + uintptr(i)) + if err != 0 { + return 1 + } + funcname[i] = byte(v >> 56) + funcname[i+1] = byte(v >> 48) + funcname[i+2] = byte(v >> 40) + funcname[i+3] = byte(v >> 32) + funcname[i+4] = byte(v >> 24) + funcname[i+5] = byte(v >> 16) + funcname[i+6] = byte(v >> 8) + funcname[i+7] = byte(v) + } + + runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS___E2A_L<<4, // __e2a_l + []uintptr{uintptr(unsafe.Pointer(&funcname[0])), nameLen}) + + name := string(funcname[:nameLen]) + if name != funcName { + return 1 + } + + return 0 +} + +// For detection of capabilities on a system. +// Is function descriptor f a valid function? +func isValidLeFunc(f uintptr) error { + ret := funcptrtest(f, "") + if ret != 0 { + return fmt.Errorf("Bad pointer, not an LE function ") + } + return nil +} + +// Retrieve function name from descriptor +func getLeFuncName(f uintptr) (string, error) { + // assume it has been checked, only check ppa1 validity here + entry := ((*[2]uintptr)(unsafe.Pointer(f)))[1] + preamp := ((*[4]uint32)(unsafe.Pointer(entry - eyecatcherOffset))) + + offsetPpa1 := preamp[2] + if offsetPpa1 > 0x0ffff { + return "", fmt.Errorf("PPA1 offset seems too big 0x%x\n", offsetPpa1) + } + + ppa1 := uintptr(unsafe.Pointer(preamp)) + uintptr(offsetPpa1) + res := ptrtest(ppa1) + if res != 0 { + return "", fmt.Errorf("PPA1 address not valid") + } + + size := *(*uint16)(unsafe.Pointer(ppa1 + nameLenOffset)) + if size > 128 { + return "", fmt.Errorf("Function name seems too long, length=%d\n", size) + } + + var name [128]byte + funcname := (*[128]byte)(unsafe.Pointer(ppa1 + nameOffset)) + copy(name[0:size], funcname[0:size]) + + runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS___E2A_L<<4, // __e2a_l + []uintptr{uintptr(unsafe.Pointer(&name[0])), uintptr(size)}) + + return string(name[:size]), nil +} + +// Check z/OS version +func zosLeVersion() (version, release uint32) { + p1 := (*(*uintptr)(unsafe.Pointer(uintptr(1208)))) >> 32 + p1 = *(*uintptr)(unsafe.Pointer(uintptr(p1 + 88))) + p1 = *(*uintptr)(unsafe.Pointer(uintptr(p1 + 8))) + p1 = *(*uintptr)(unsafe.Pointer(uintptr(p1 + 984))) + vrm := *(*uint32)(unsafe.Pointer(p1 + 80)) + version = (vrm & 0x00ff0000) >> 16 + release = (vrm & 0x0000ff00) >> 8 + return +} + +// returns a zos C FILE * for stdio fd 0, 1, 2 +func ZosStdioFilep(fd int32) uintptr { + return uintptr(*(*uint64)(unsafe.Pointer(uintptr(*(*uint64)(unsafe.Pointer(uintptr(*(*uint64)(unsafe.Pointer(uintptr(uint64(*(*uint32)(unsafe.Pointer(uintptr(1208)))) + 80))) + uint64((fd+2)<<3)))))))) +} func copyStat(stat *Stat_t, statLE *Stat_LE_t) { stat.Dev = uint64(statLE.Dev) @@ -65,6 +263,21 @@ func (d *Dirent) NameString() string { } } +func DecodeData(dest []byte, sz int, val uint64) { + for i := 0; i < sz; i++ { + dest[sz-1-i] = byte((val >> (uint64(i * 8))) & 0xff) + } +} + +func EncodeData(data []byte) uint64 { + var value uint64 + sz := len(data) + for i := 0; i < sz; i++ { + value |= uint64(data[i]) << uint64(((sz - i - 1) * 8)) + } + return value +} + func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, _Socklen, error) { if sa.Port < 0 || sa.Port > 0xFFFF { return nil, 0, EINVAL @@ -74,7 +287,9 @@ func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, _Socklen, error) { p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port)) p[0] = byte(sa.Port >> 8) p[1] = byte(sa.Port) - sa.raw.Addr = sa.Addr + for i := 0; i < len(sa.Addr); i++ { + sa.raw.Addr[i] = sa.Addr[i] + } return unsafe.Pointer(&sa.raw), _Socklen(sa.raw.Len), nil } @@ -88,7 +303,9 @@ func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, _Socklen, error) { p[0] = byte(sa.Port >> 8) p[1] = byte(sa.Port) sa.raw.Scope_id = sa.ZoneId - sa.raw.Addr = sa.Addr + for i := 0; i < len(sa.Addr); i++ { + sa.raw.Addr[i] = sa.Addr[i] + } return unsafe.Pointer(&sa.raw), _Socklen(sa.raw.Len), nil } @@ -146,7 +363,9 @@ func anyToSockaddr(_ int, rsa *RawSockaddrAny) (Sockaddr, error) { sa := new(SockaddrInet4) p := (*[2]byte)(unsafe.Pointer(&pp.Port)) sa.Port = int(p[0])<<8 + int(p[1]) - sa.Addr = pp.Addr + for i := 0; i < len(sa.Addr); i++ { + sa.Addr[i] = pp.Addr[i] + } return sa, nil case AF_INET6: @@ -155,7 +374,9 @@ func anyToSockaddr(_ int, rsa *RawSockaddrAny) (Sockaddr, error) { p := (*[2]byte)(unsafe.Pointer(&pp.Port)) sa.Port = int(p[0])<<8 + int(p[1]) sa.ZoneId = pp.Scope_id - sa.Addr = pp.Addr + for i := 0; i < len(sa.Addr); i++ { + sa.Addr[i] = pp.Addr[i] + } return sa, nil } return nil, EAFNOSUPPORT @@ -177,6 +398,43 @@ func Accept(fd int) (nfd int, sa Sockaddr, err error) { return } +func Accept4(fd int, flags int) (nfd int, sa Sockaddr, err error) { + var rsa RawSockaddrAny + var len _Socklen = SizeofSockaddrAny + nfd, err = accept4(fd, &rsa, &len, flags) + if err != nil { + return + } + if len > SizeofSockaddrAny { + panic("RawSockaddrAny too small") + } + // TODO(neeilan): Remove 0 in call + sa, err = anyToSockaddr(0, &rsa) + if err != nil { + Close(nfd) + nfd = 0 + } + return +} + +func Ctermid() (tty string, err error) { + var termdev [1025]byte + runtime.EnterSyscall() + r0, err2, err1 := CallLeFuncWithPtrReturn(GetZosLibVec()+SYS___CTERMID_A<<4, uintptr(unsafe.Pointer(&termdev[0]))) + runtime.ExitSyscall() + if r0 == 0 { + return "", fmt.Errorf("%s (errno2=0x%x)\n", err1.Error(), err2) + } + s := string(termdev[:]) + idx := strings.Index(s, string(rune(0))) + if idx == -1 { + tty = s + } else { + tty = s[:idx] + } + return +} + func (iov *Iovec) SetLen(length int) { iov.Len = uint64(length) } @@ -190,10 +448,16 @@ func (cmsg *Cmsghdr) SetLen(length int) { } //sys fcntl(fd int, cmd int, arg int) (val int, err error) +//sys Flistxattr(fd int, dest []byte) (sz int, err error) = SYS___FLISTXATTR_A +//sys Fremovexattr(fd int, attr string) (err error) = SYS___FREMOVEXATTR_A //sys read(fd int, p []byte) (n int, err error) //sys write(fd int, p []byte) (n int, err error) +//sys Fgetxattr(fd int, attr string, dest []byte) (sz int, err error) = SYS___FGETXATTR_A +//sys Fsetxattr(fd int, attr string, data []byte, flag int) (err error) = SYS___FSETXATTR_A + //sys accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) = SYS___ACCEPT_A +//sys accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error) = SYS___ACCEPT4_A //sys bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) = SYS___BIND_A //sys connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) = SYS___CONNECT_A //sysnb getgroups(n int, list *_Gid_t) (nn int, err error) @@ -204,6 +468,7 @@ func (cmsg *Cmsghdr) SetLen(length int) { //sysnb socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) //sysnb getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) = SYS___GETPEERNAME_A //sysnb getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) = SYS___GETSOCKNAME_A +//sys Removexattr(path string, attr string) (err error) = SYS___REMOVEXATTR_A //sys recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error) = SYS___RECVFROM_A //sys sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error) = SYS___SENDTO_A //sys recvmsg(s int, msg *Msghdr, flags int) (n int, err error) = SYS___RECVMSG_A @@ -212,6 +477,10 @@ func (cmsg *Cmsghdr) SetLen(length int) { //sys munmap(addr uintptr, length uintptr) (err error) = SYS_MUNMAP //sys ioctl(fd int, req int, arg uintptr) (err error) = SYS_IOCTL //sys ioctlPtr(fd int, req int, arg unsafe.Pointer) (err error) = SYS_IOCTL +//sys shmat(id int, addr uintptr, flag int) (ret uintptr, err error) = SYS_SHMAT +//sys shmctl(id int, cmd int, buf *SysvShmDesc) (result int, err error) = SYS_SHMCTL64 +//sys shmdt(addr uintptr) (err error) = SYS_SHMDT +//sys shmget(key int, size int, flag int) (id int, err error) = SYS_SHMGET //sys Access(path string, mode uint32) (err error) = SYS___ACCESS_A //sys Chdir(path string) (err error) = SYS___CHDIR_A @@ -220,14 +489,31 @@ func (cmsg *Cmsghdr) SetLen(length int) { //sys Creat(path string, mode uint32) (fd int, err error) = SYS___CREAT_A //sys Dup(oldfd int) (fd int, err error) //sys Dup2(oldfd int, newfd int) (err error) +//sys Dup3(oldfd int, newfd int, flags int) (err error) = SYS_DUP3 +//sys Dirfd(dirp uintptr) (fd int, err error) = SYS_DIRFD +//sys EpollCreate(size int) (fd int, err error) = SYS_EPOLL_CREATE +//sys EpollCreate1(flags int) (fd int, err error) = SYS_EPOLL_CREATE1 +//sys EpollCtl(epfd int, op int, fd int, event *EpollEvent) (err error) = SYS_EPOLL_CTL +//sys EpollPwait(epfd int, events []EpollEvent, msec int, sigmask *int) (n int, err error) = SYS_EPOLL_PWAIT +//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) = SYS_EPOLL_WAIT //sys Errno2() (er2 int) = SYS___ERRNO2 -//sys Err2ad() (eadd *int) = SYS___ERR2AD +//sys Eventfd(initval uint, flags int) (fd int, err error) = SYS_EVENTFD //sys Exit(code int) +//sys Faccessat(dirfd int, path string, mode uint32, flags int) (err error) = SYS___FACCESSAT_A + +func Faccessat2(dirfd int, path string, mode uint32, flags int) (err error) { + return Faccessat(dirfd, path, mode, flags) +} + //sys Fchdir(fd int) (err error) //sys Fchmod(fd int, mode uint32) (err error) +//sys Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) = SYS___FCHMODAT_A //sys Fchown(fd int, uid int, gid int) (err error) +//sys Fchownat(fd int, path string, uid int, gid int, flags int) (err error) = SYS___FCHOWNAT_A //sys FcntlInt(fd uintptr, cmd int, arg int) (retval int, err error) = SYS_FCNTL +//sys Fdatasync(fd int) (err error) = SYS_FDATASYNC //sys fstat(fd int, stat *Stat_LE_t) (err error) +//sys fstatat(dirfd int, path string, stat *Stat_LE_t, flags int) (err error) = SYS___FSTATAT_A func Fstat(fd int, stat *Stat_t) (err error) { var statLE Stat_LE_t @@ -236,28 +522,208 @@ func Fstat(fd int, stat *Stat_t) (err error) { return } +func Fstatat(dirfd int, path string, stat *Stat_t, flags int) (err error) { + var statLE Stat_LE_t + err = fstatat(dirfd, path, &statLE, flags) + copyStat(stat, &statLE) + return +} + +func impl_Getxattr(path string, attr string, dest []byte) (sz int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(attr) + if err != nil { + return + } + var _p2 unsafe.Pointer + if len(dest) > 0 { + _p2 = unsafe.Pointer(&dest[0]) + } else { + _p2 = unsafe.Pointer(&_zero) + } + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___GETXATTR_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(dest))) + sz = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_GetxattrAddr() *(func(path string, attr string, dest []byte) (sz int, err error)) + +var Getxattr = enter_Getxattr + +func enter_Getxattr(path string, attr string, dest []byte) (sz int, err error) { + funcref := get_GetxattrAddr() + if validGetxattr() { + *funcref = impl_Getxattr + } else { + *funcref = error_Getxattr + } + return (*funcref)(path, attr, dest) +} + +func error_Getxattr(path string, attr string, dest []byte) (sz int, err error) { + return -1, ENOSYS +} + +func validGetxattr() bool { + if funcptrtest(GetZosLibVec()+SYS___GETXATTR_A<<4, "") == 0 { + if name, err := getLeFuncName(GetZosLibVec() + SYS___GETXATTR_A<<4); err == nil { + return name == "__getxattr_a" + } + } + return false +} + +//sys Lgetxattr(link string, attr string, dest []byte) (sz int, err error) = SYS___LGETXATTR_A +//sys Lsetxattr(path string, attr string, data []byte, flags int) (err error) = SYS___LSETXATTR_A + +func impl_Setxattr(path string, attr string, data []byte, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(attr) + if err != nil { + return + } + var _p2 unsafe.Pointer + if len(data) > 0 { + _p2 = unsafe.Pointer(&data[0]) + } else { + _p2 = unsafe.Pointer(&_zero) + } + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___SETXATTR_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(data)), uintptr(flags)) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_SetxattrAddr() *(func(path string, attr string, data []byte, flags int) (err error)) + +var Setxattr = enter_Setxattr + +func enter_Setxattr(path string, attr string, data []byte, flags int) (err error) { + funcref := get_SetxattrAddr() + if validSetxattr() { + *funcref = impl_Setxattr + } else { + *funcref = error_Setxattr + } + return (*funcref)(path, attr, data, flags) +} + +func error_Setxattr(path string, attr string, data []byte, flags int) (err error) { + return ENOSYS +} + +func validSetxattr() bool { + if funcptrtest(GetZosLibVec()+SYS___SETXATTR_A<<4, "") == 0 { + if name, err := getLeFuncName(GetZosLibVec() + SYS___SETXATTR_A<<4); err == nil { + return name == "__setxattr_a" + } + } + return false +} + +//sys Fstatfs(fd int, buf *Statfs_t) (err error) = SYS_FSTATFS //sys Fstatvfs(fd int, stat *Statvfs_t) (err error) = SYS_FSTATVFS //sys Fsync(fd int) (err error) +//sys Futimes(fd int, tv []Timeval) (err error) = SYS_FUTIMES +//sys Futimesat(dirfd int, path string, tv []Timeval) (err error) = SYS___FUTIMESAT_A //sys Ftruncate(fd int, length int64) (err error) -//sys Getpagesize() (pgsize int) = SYS_GETPAGESIZE +//sys Getrandom(buf []byte, flags int) (n int, err error) = SYS_GETRANDOM +//sys InotifyInit() (fd int, err error) = SYS_INOTIFY_INIT +//sys InotifyInit1(flags int) (fd int, err error) = SYS_INOTIFY_INIT1 +//sys InotifyAddWatch(fd int, pathname string, mask uint32) (watchdesc int, err error) = SYS___INOTIFY_ADD_WATCH_A +//sys InotifyRmWatch(fd int, watchdesc uint32) (success int, err error) = SYS_INOTIFY_RM_WATCH +//sys Listxattr(path string, dest []byte) (sz int, err error) = SYS___LISTXATTR_A +//sys Llistxattr(path string, dest []byte) (sz int, err error) = SYS___LLISTXATTR_A +//sys Lremovexattr(path string, attr string) (err error) = SYS___LREMOVEXATTR_A +//sys Lutimes(path string, tv []Timeval) (err error) = SYS___LUTIMES_A //sys Mprotect(b []byte, prot int) (err error) = SYS_MPROTECT //sys Msync(b []byte, flags int) (err error) = SYS_MSYNC +//sys Console2(cmsg *ConsMsg2, modstr *byte, concmd *uint32) (err error) = SYS___CONSOLE2 + +// Pipe2 begin + +//go:nosplit +func getPipe2Addr() *(func([]int, int) error) + +var Pipe2 = pipe2Enter + +func pipe2Enter(p []int, flags int) (err error) { + if funcptrtest(GetZosLibVec()+SYS_PIPE2<<4, "") == 0 { + *getPipe2Addr() = pipe2Impl + } else { + *getPipe2Addr() = pipe2Error + } + return (*getPipe2Addr())(p, flags) +} + +func pipe2Impl(p []int, flags int) (err error) { + var pp [2]_C_int + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_PIPE2<<4, uintptr(unsafe.Pointer(&pp[0])), uintptr(flags)) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } else { + p[0] = int(pp[0]) + p[1] = int(pp[1]) + } + return +} +func pipe2Error(p []int, flags int) (err error) { + return fmt.Errorf("Pipe2 is not available on this system") +} + +// Pipe2 end + //sys Poll(fds []PollFd, timeout int) (n int, err error) = SYS_POLL + +func Readdir(dir uintptr) (dirent *Dirent, err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___READDIR_A<<4, uintptr(dir)) + runtime.ExitSyscall() + dirent = (*Dirent)(unsafe.Pointer(r0)) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//sys Readdir_r(dirp uintptr, entry *direntLE, result **direntLE) (err error) = SYS___READDIR_R_A +//sys Statfs(path string, buf *Statfs_t) (err error) = SYS___STATFS_A +//sys Syncfs(fd int) (err error) = SYS_SYNCFS //sys Times(tms *Tms) (ticks uintptr, err error) = SYS_TIMES //sys W_Getmntent(buff *byte, size int) (lastsys int, err error) = SYS_W_GETMNTENT //sys W_Getmntent_A(buff *byte, size int) (lastsys int, err error) = SYS___W_GETMNTENT_A //sys mount_LE(path string, filesystem string, fstype string, mtm uint32, parmlen int32, parm string) (err error) = SYS___MOUNT_A -//sys unmount(filesystem string, mtm int) (err error) = SYS___UMOUNT_A +//sys unmount_LE(filesystem string, mtm int) (err error) = SYS___UMOUNT_A //sys Chroot(path string) (err error) = SYS___CHROOT_A //sys Select(nmsgsfds int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (ret int, err error) = SYS_SELECT -//sysnb Uname(buf *Utsname) (err error) = SYS___UNAME_A +//sysnb Uname(buf *Utsname) (err error) = SYS_____OSNAME_A +//sys Unshare(flags int) (err error) = SYS_UNSHARE func Ptsname(fd int) (name string, err error) { - r0, _, e1 := syscall_syscall(SYS___PTSNAME_A, uintptr(fd), 0, 0) - name = u2s(unsafe.Pointer(r0)) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithPtrReturn(GetZosLibVec()+SYS___PTSNAME_A<<4, uintptr(fd)) + runtime.ExitSyscall() + if r0 == 0 { + err = errnoErr2(e1, e2) + } else { + name = u2s(unsafe.Pointer(r0)) } return } @@ -272,13 +738,19 @@ func u2s(cstr unsafe.Pointer) string { } func Close(fd int) (err error) { - _, _, e1 := syscall_syscall(SYS_CLOSE, uintptr(fd), 0, 0) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_CLOSE<<4, uintptr(fd)) + runtime.ExitSyscall() for i := 0; e1 == EAGAIN && i < 10; i++ { - _, _, _ = syscall_syscall(SYS_USLEEP, uintptr(10), 0, 0) - _, _, e1 = syscall_syscall(SYS_CLOSE, uintptr(fd), 0, 0) + runtime.EnterSyscall() + CallLeFuncWithErr(GetZosLibVec()+SYS_USLEEP<<4, uintptr(10)) + runtime.ExitSyscall() + runtime.EnterSyscall() + r0, e2, e1 = CallLeFuncWithErr(GetZosLibVec()+SYS_CLOSE<<4, uintptr(fd)) + runtime.ExitSyscall() } - if e1 != 0 { - err = errnoErr(e1) + if r0 != 0 { + err = errnoErr2(e1, e2) } return } @@ -288,9 +760,24 @@ func Madvise(b []byte, advice int) (err error) { return } +func Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) { + return mapper.Mmap(fd, offset, length, prot, flags) +} + +func Munmap(b []byte) (err error) { + return mapper.Munmap(b) +} + +func MmapPtr(fd int, offset int64, addr unsafe.Pointer, length uintptr, prot int, flags int) (ret unsafe.Pointer, err error) { + xaddr, err := mapper.mmap(uintptr(addr), length, prot, flags, fd, offset) + return unsafe.Pointer(xaddr), err +} + +func MunmapPtr(addr unsafe.Pointer, length uintptr) (err error) { + return mapper.munmap(uintptr(addr), length) +} + //sys Gethostname(buf []byte) (err error) = SYS___GETHOSTNAME_A -//sysnb Getegid() (egid int) -//sysnb Geteuid() (uid int) //sysnb Getgid() (gid int) //sysnb Getpid() (pid int) //sysnb Getpgid(pid int) (pgid int, err error) = SYS_GETPGID @@ -317,11 +804,14 @@ func Getrusage(who int, rusage *Rusage) (err error) { return } +//sys Getegid() (egid int) = SYS_GETEGID +//sys Geteuid() (euid int) = SYS_GETEUID //sysnb Getsid(pid int) (sid int, err error) = SYS_GETSID //sysnb Getuid() (uid int) //sysnb Kill(pid int, sig Signal) (err error) //sys Lchown(path string, uid int, gid int) (err error) = SYS___LCHOWN_A //sys Link(path string, link string) (err error) = SYS___LINK_A +//sys Linkat(oldDirFd int, oldPath string, newDirFd int, newPath string, flags int) (err error) = SYS___LINKAT_A //sys Listen(s int, n int) (err error) //sys lstat(path string, stat *Stat_LE_t) (err error) = SYS___LSTAT_A @@ -332,15 +822,150 @@ func Lstat(path string, stat *Stat_t) (err error) { return } +// for checking symlinks begins with $VERSION/ $SYSNAME/ $SYSSYMR/ $SYSSYMA/ +func isSpecialPath(path []byte) (v bool) { + var special = [4][8]byte{ + {'V', 'E', 'R', 'S', 'I', 'O', 'N', '/'}, + {'S', 'Y', 'S', 'N', 'A', 'M', 'E', '/'}, + {'S', 'Y', 'S', 'S', 'Y', 'M', 'R', '/'}, + {'S', 'Y', 'S', 'S', 'Y', 'M', 'A', '/'}} + + var i, j int + for i = 0; i < len(special); i++ { + for j = 0; j < len(special[i]); j++ { + if path[j] != special[i][j] { + break + } + } + if j == len(special[i]) { + return true + } + } + return false +} + +func realpath(srcpath string, abspath []byte) (pathlen int, errno int) { + var source [1024]byte + copy(source[:], srcpath) + source[len(srcpath)] = 0 + ret := runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS___REALPATH_A<<4, //__realpath_a() + []uintptr{uintptr(unsafe.Pointer(&source[0])), + uintptr(unsafe.Pointer(&abspath[0]))}) + if ret != 0 { + index := bytes.IndexByte(abspath[:], byte(0)) + if index != -1 { + return index, 0 + } + } else { + errptr := (*int)(unsafe.Pointer(runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS___ERRNO<<4, []uintptr{}))) //__errno() + return 0, *errptr + } + return 0, 245 // EBADDATA 245 +} + +func Readlink(path string, buf []byte) (n int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + var _p1 unsafe.Pointer + if len(buf) > 0 { + _p1 = unsafe.Pointer(&buf[0]) + } else { + _p1 = unsafe.Pointer(&_zero) + } + n = int(runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS___READLINK_A<<4, + []uintptr{uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf))})) + runtime.KeepAlive(unsafe.Pointer(_p0)) + if n == -1 { + value := *(*int32)(unsafe.Pointer(runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS___ERRNO<<4, []uintptr{}))) + err = errnoErr(Errno(value)) + } else { + if buf[0] == '$' { + if isSpecialPath(buf[1:9]) { + cnt, err1 := realpath(path, buf) + if err1 == 0 { + n = cnt + } + } + } + } + return +} + +func impl_Readlinkat(dirfd int, path string, buf []byte) (n int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + var _p1 unsafe.Pointer + if len(buf) > 0 { + _p1 = unsafe.Pointer(&buf[0]) + } else { + _p1 = unsafe.Pointer(&_zero) + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___READLINKAT_A<<4, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf))) + runtime.ExitSyscall() + n = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + return n, err + } else { + if buf[0] == '$' { + if isSpecialPath(buf[1:9]) { + cnt, err1 := realpath(path, buf) + if err1 == 0 { + n = cnt + } + } + } + } + return +} + +//go:nosplit +func get_ReadlinkatAddr() *(func(dirfd int, path string, buf []byte) (n int, err error)) + +var Readlinkat = enter_Readlinkat + +func enter_Readlinkat(dirfd int, path string, buf []byte) (n int, err error) { + funcref := get_ReadlinkatAddr() + if funcptrtest(GetZosLibVec()+SYS___READLINKAT_A<<4, "") == 0 { + *funcref = impl_Readlinkat + } else { + *funcref = error_Readlinkat + } + return (*funcref)(dirfd, path, buf) +} + +func error_Readlinkat(dirfd int, path string, buf []byte) (n int, err error) { + n = -1 + err = ENOSYS + return +} + //sys Mkdir(path string, mode uint32) (err error) = SYS___MKDIR_A +//sys Mkdirat(dirfd int, path string, mode uint32) (err error) = SYS___MKDIRAT_A //sys Mkfifo(path string, mode uint32) (err error) = SYS___MKFIFO_A //sys Mknod(path string, mode uint32, dev int) (err error) = SYS___MKNOD_A +//sys Mknodat(dirfd int, path string, mode uint32, dev int) (err error) = SYS___MKNODAT_A +//sys PivotRoot(newroot string, oldroot string) (err error) = SYS___PIVOT_ROOT_A //sys Pread(fd int, p []byte, offset int64) (n int, err error) //sys Pwrite(fd int, p []byte, offset int64) (n int, err error) -//sys Readlink(path string, buf []byte) (n int, err error) = SYS___READLINK_A +//sys Prctl(option int, arg2 uintptr, arg3 uintptr, arg4 uintptr, arg5 uintptr) (err error) = SYS___PRCTL_A +//sysnb Prlimit(pid int, resource int, newlimit *Rlimit, old *Rlimit) (err error) = SYS_PRLIMIT //sys Rename(from string, to string) (err error) = SYS___RENAME_A +//sys Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error) = SYS___RENAMEAT_A +//sys Renameat2(olddirfd int, oldpath string, newdirfd int, newpath string, flags uint) (err error) = SYS___RENAMEAT2_A //sys Rmdir(path string) (err error) = SYS___RMDIR_A //sys Seek(fd int, offset int64, whence int) (off int64, err error) = SYS_LSEEK +//sys Setegid(egid int) (err error) = SYS_SETEGID +//sys Seteuid(euid int) (err error) = SYS_SETEUID +//sys Sethostname(p []byte) (err error) = SYS___SETHOSTNAME_A +//sys Setns(fd int, nstype int) (err error) = SYS_SETNS //sys Setpriority(which int, who int, prio int) (err error) //sysnb Setpgid(pid int, pgid int) (err error) = SYS_SETPGID //sysnb Setrlimit(resource int, lim *Rlimit) (err error) @@ -360,32 +985,57 @@ func Stat(path string, sta *Stat_t) (err error) { } //sys Symlink(path string, link string) (err error) = SYS___SYMLINK_A +//sys Symlinkat(oldPath string, dirfd int, newPath string) (err error) = SYS___SYMLINKAT_A //sys Sync() = SYS_SYNC //sys Truncate(path string, length int64) (err error) = SYS___TRUNCATE_A //sys Tcgetattr(fildes int, termptr *Termios) (err error) = SYS_TCGETATTR //sys Tcsetattr(fildes int, when int, termptr *Termios) (err error) = SYS_TCSETATTR //sys Umask(mask int) (oldmask int) //sys Unlink(path string) (err error) = SYS___UNLINK_A +//sys Unlinkat(dirfd int, path string, flags int) (err error) = SYS___UNLINKAT_A //sys Utime(path string, utim *Utimbuf) (err error) = SYS___UTIME_A //sys open(path string, mode int, perm uint32) (fd int, err error) = SYS___OPEN_A func Open(path string, mode int, perm uint32) (fd int, err error) { + if mode&O_ACCMODE == 0 { + mode |= O_RDONLY + } return open(path, mode, perm) } -func Mkfifoat(dirfd int, path string, mode uint32) (err error) { - wd, err := Getwd() - if err != nil { - return err - } +//sys openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) = SYS___OPENAT_A - if err := Fchdir(dirfd); err != nil { - return err +func Openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) { + if flags&O_ACCMODE == 0 { + flags |= O_RDONLY } - defer Chdir(wd) + return openat(dirfd, path, flags, mode) +} - return Mkfifo(path, mode) +//sys openat2(dirfd int, path string, open_how *OpenHow, size int) (fd int, err error) = SYS___OPENAT2_A + +func Openat2(dirfd int, path string, how *OpenHow) (fd int, err error) { + if how.Flags&O_ACCMODE == 0 { + how.Flags |= O_RDONLY + } + return openat2(dirfd, path, how, SizeofOpenHow) +} + +func ZosFdToPath(dirfd int) (path string, err error) { + var buffer [1024]byte + runtime.EnterSyscall() + ret, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_W_IOCTL<<4, uintptr(dirfd), 17, 1024, uintptr(unsafe.Pointer(&buffer[0]))) + runtime.ExitSyscall() + if ret == 0 { + zb := bytes.IndexByte(buffer[:], 0) + if zb == -1 { + zb = len(buffer) + } + CallLeFuncWithErr(GetZosLibVec()+SYS___E2A_L<<4, uintptr(unsafe.Pointer(&buffer[0])), uintptr(zb)) + return string(buffer[:zb]), nil + } + return "", errnoErr2(e1, e2) } //sys remove(path string) (err error) @@ -403,10 +1053,12 @@ func Getcwd(buf []byte) (n int, err error) { } else { p = unsafe.Pointer(&_zero) } - _, _, e := syscall_syscall(SYS___GETCWD_A, uintptr(p), uintptr(len(buf)), 0) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithPtrReturn(GetZosLibVec()+SYS___GETCWD_A<<4, uintptr(p), uintptr(len(buf))) + runtime.ExitSyscall() n = clen(buf) + 1 - if e != 0 { - err = errnoErr(e) + if r0 == 0 { + err = errnoErr2(e1, e2) } return } @@ -520,9 +1172,41 @@ func (w WaitStatus) StopSignal() Signal { func (w WaitStatus) TrapCause() int { return -1 } +//sys waitid(idType int, id int, info *Siginfo, options int) (err error) + +func Waitid(idType int, id int, info *Siginfo, options int, rusage *Rusage) (err error) { + return waitid(idType, id, info, options) +} + //sys waitpid(pid int, wstatus *_C_int, options int) (wpid int, err error) -func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, err error) { +func impl_Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_WAIT4<<4, uintptr(pid), uintptr(unsafe.Pointer(wstatus)), uintptr(options), uintptr(unsafe.Pointer(rusage))) + runtime.ExitSyscall() + wpid = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_Wait4Addr() *(func(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, err error)) + +var Wait4 = enter_Wait4 + +func enter_Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, err error) { + funcref := get_Wait4Addr() + if funcptrtest(GetZosLibVec()+SYS_WAIT4<<4, "") == 0 { + *funcref = impl_Wait4 + } else { + *funcref = legacyWait4 + } + return (*funcref)(pid, wstatus, options, rusage) +} + +func legacyWait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, err error) { // TODO(mundaym): z/OS doesn't have wait4. I don't think getrusage does what we want. // At the moment rusage will not be touched. var status _C_int @@ -571,23 +1255,62 @@ func Pipe(p []int) (err error) { } var pp [2]_C_int err = pipe(&pp) - if err == nil { - p[0] = int(pp[0]) - p[1] = int(pp[1]) - } + p[0] = int(pp[0]) + p[1] = int(pp[1]) return } //sys utimes(path string, timeval *[2]Timeval) (err error) = SYS___UTIMES_A func Utimes(path string, tv []Timeval) (err error) { + if tv == nil { + return utimes(path, nil) + } if len(tv) != 2 { return EINVAL } return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0]))) } -func UtimesNano(path string, ts []Timespec) error { +//sys utimensat(dirfd int, path string, ts *[2]Timespec, flags int) (err error) = SYS___UTIMENSAT_A + +func validUtimensat() bool { + if funcptrtest(GetZosLibVec()+SYS___UTIMENSAT_A<<4, "") == 0 { + if name, err := getLeFuncName(GetZosLibVec() + SYS___UTIMENSAT_A<<4); err == nil { + return name == "__utimensat_a" + } + } + return false +} + +// Begin UtimesNano + +//go:nosplit +func get_UtimesNanoAddr() *(func(path string, ts []Timespec) (err error)) + +var UtimesNano = enter_UtimesNano + +func enter_UtimesNano(path string, ts []Timespec) (err error) { + funcref := get_UtimesNanoAddr() + if validUtimensat() { + *funcref = utimesNanoImpl + } else { + *funcref = legacyUtimesNano + } + return (*funcref)(path, ts) +} + +func utimesNanoImpl(path string, ts []Timespec) (err error) { + if ts == nil { + return utimensat(AT_FDCWD, path, nil, 0) + } + if len(ts) != 2 { + return EINVAL + } + return utimensat(AT_FDCWD, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), 0) +} + +func legacyUtimesNano(path string, ts []Timespec) (err error) { if len(ts) != 2 { return EINVAL } @@ -600,6 +1323,70 @@ func UtimesNano(path string, ts []Timespec) error { return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0]))) } +// End UtimesNano + +// Begin UtimesNanoAt + +//go:nosplit +func get_UtimesNanoAtAddr() *(func(dirfd int, path string, ts []Timespec, flags int) (err error)) + +var UtimesNanoAt = enter_UtimesNanoAt + +func enter_UtimesNanoAt(dirfd int, path string, ts []Timespec, flags int) (err error) { + funcref := get_UtimesNanoAtAddr() + if validUtimensat() { + *funcref = utimesNanoAtImpl + } else { + *funcref = legacyUtimesNanoAt + } + return (*funcref)(dirfd, path, ts, flags) +} + +func utimesNanoAtImpl(dirfd int, path string, ts []Timespec, flags int) (err error) { + if ts == nil { + return utimensat(dirfd, path, nil, flags) + } + if len(ts) != 2 { + return EINVAL + } + return utimensat(dirfd, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), flags) +} + +func legacyUtimesNanoAt(dirfd int, path string, ts []Timespec, flags int) (err error) { + if path[0] != '/' { + dirPath, err := ZosFdToPath(dirfd) + if err != nil { + return err + } + path = dirPath + "/" + path + } + if flags == AT_SYMLINK_NOFOLLOW { + if len(ts) != 2 { + return EINVAL + } + + if ts[0].Nsec >= 5e8 { + ts[0].Sec++ + } + ts[0].Nsec = 0 + if ts[1].Nsec >= 5e8 { + ts[1].Sec++ + } + ts[1].Nsec = 0 + + // Not as efficient as it could be because Timespec and + // Timeval have different types in the different OSes + tv := []Timeval{ + NsecToTimeval(TimespecToNsec(ts[0])), + NsecToTimeval(TimespecToNsec(ts[1])), + } + return Lutimes(path, tv) + } + return UtimesNano(path, ts) +} + +// End UtimesNanoAt + func Getsockname(fd int) (sa Sockaddr, err error) { var rsa RawSockaddrAny var len _Socklen = SizeofSockaddrAny @@ -1191,10 +1978,13 @@ func Opendir(name string) (uintptr, error) { if err != nil { return 0, err } - dir, _, e := syscall_syscall(SYS___OPENDIR_A, uintptr(unsafe.Pointer(p)), 0, 0) + err = nil + runtime.EnterSyscall() + dir, e2, e1 := CallLeFuncWithPtrReturn(GetZosLibVec()+SYS___OPENDIR_A<<4, uintptr(unsafe.Pointer(p))) + runtime.ExitSyscall() runtime.KeepAlive(unsafe.Pointer(p)) - if e != 0 { - err = errnoErr(e) + if dir == 0 { + err = errnoErr2(e1, e2) } return dir, err } @@ -1202,51 +1992,27 @@ func Opendir(name string) (uintptr, error) { // clearsyscall.Errno resets the errno value to 0. func clearErrno() -func Readdir(dir uintptr) (*Dirent, error) { - var ent Dirent - var res uintptr - // __readdir_r_a returns errno at the end of the directory stream, rather than 0. - // Therefore to avoid false positives we clear errno before calling it. - - // TODO(neeilan): Commented this out to get sys/unix compiling on z/OS. Uncomment and fix. Error: "undefined: clearsyscall" - //clearsyscall.Errno() // TODO(mundaym): check pre-emption rules. - - e, _, _ := syscall_syscall(SYS___READDIR_R_A, dir, uintptr(unsafe.Pointer(&ent)), uintptr(unsafe.Pointer(&res))) - var err error - if e != 0 { - err = errnoErr(Errno(e)) - } - if res == 0 { - return nil, err - } - return &ent, err -} - -func readdir_r(dirp uintptr, entry *direntLE, result **direntLE) (err error) { - r0, _, e1 := syscall_syscall(SYS___READDIR_R_A, dirp, uintptr(unsafe.Pointer(entry)), uintptr(unsafe.Pointer(result))) - if int64(r0) == -1 { - err = errnoErr(Errno(e1)) - } - return -} - func Closedir(dir uintptr) error { - _, _, e := syscall_syscall(SYS_CLOSEDIR, dir, 0, 0) - if e != 0 { - return errnoErr(e) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_CLOSEDIR<<4, dir) + runtime.ExitSyscall() + if r0 != 0 { + return errnoErr2(e1, e2) } return nil } func Seekdir(dir uintptr, pos int) { - _, _, _ = syscall_syscall(SYS_SEEKDIR, dir, uintptr(pos), 0) + runtime.EnterSyscall() + CallLeFuncWithErr(GetZosLibVec()+SYS_SEEKDIR<<4, dir, uintptr(pos)) + runtime.ExitSyscall() } func Telldir(dir uintptr) (int, error) { - p, _, e := syscall_syscall(SYS_TELLDIR, dir, 0, 0) + p, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_TELLDIR<<4, dir) pos := int(p) - if pos == -1 { - return pos, errnoErr(e) + if int64(p) == -1 { + return pos, errnoErr2(e1, e2) } return pos, nil } @@ -1261,19 +2027,55 @@ func FcntlFlock(fd uintptr, cmd int, lk *Flock_t) error { *(*int64)(unsafe.Pointer(&flock[4])) = lk.Start *(*int64)(unsafe.Pointer(&flock[12])) = lk.Len *(*int32)(unsafe.Pointer(&flock[20])) = lk.Pid - _, _, errno := syscall_syscall(SYS_FCNTL, fd, uintptr(cmd), uintptr(unsafe.Pointer(&flock))) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_FCNTL<<4, fd, uintptr(cmd), uintptr(unsafe.Pointer(&flock))) + runtime.ExitSyscall() lk.Type = *(*int16)(unsafe.Pointer(&flock[0])) lk.Whence = *(*int16)(unsafe.Pointer(&flock[2])) lk.Start = *(*int64)(unsafe.Pointer(&flock[4])) lk.Len = *(*int64)(unsafe.Pointer(&flock[12])) lk.Pid = *(*int32)(unsafe.Pointer(&flock[20])) - if errno == 0 { + if r0 == 0 { return nil } - return errno + return errnoErr2(e1, e2) } -func Flock(fd int, how int) error { +func impl_Flock(fd int, how int) (err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_FLOCK<<4, uintptr(fd), uintptr(how)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_FlockAddr() *(func(fd int, how int) (err error)) + +var Flock = enter_Flock + +func validFlock(fp uintptr) bool { + if funcptrtest(GetZosLibVec()+SYS_FLOCK<<4, "") == 0 { + if name, err := getLeFuncName(GetZosLibVec() + SYS_FLOCK<<4); err == nil { + return name == "flock" + } + } + return false +} + +func enter_Flock(fd int, how int) (err error) { + funcref := get_FlockAddr() + if validFlock(GetZosLibVec() + SYS_FLOCK<<4) { + *funcref = impl_Flock + } else { + *funcref = legacyFlock + } + return (*funcref)(fd, how) +} + +func legacyFlock(fd int, how int) error { var flock_type int16 var fcntl_cmd int @@ -1307,41 +2109,51 @@ func Flock(fd int, how int) error { } func Mlock(b []byte) (err error) { - _, _, e1 := syscall_syscall(SYS___MLOCKALL, _BPX_NONSWAP, 0, 0) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___MLOCKALL<<4, _BPX_NONSWAP) + runtime.ExitSyscall() + if r0 != 0 { + err = errnoErr2(e1, e2) } return } func Mlock2(b []byte, flags int) (err error) { - _, _, e1 := syscall_syscall(SYS___MLOCKALL, _BPX_NONSWAP, 0, 0) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___MLOCKALL<<4, _BPX_NONSWAP) + runtime.ExitSyscall() + if r0 != 0 { + err = errnoErr2(e1, e2) } return } func Mlockall(flags int) (err error) { - _, _, e1 := syscall_syscall(SYS___MLOCKALL, _BPX_NONSWAP, 0, 0) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___MLOCKALL<<4, _BPX_NONSWAP) + runtime.ExitSyscall() + if r0 != 0 { + err = errnoErr2(e1, e2) } return } func Munlock(b []byte) (err error) { - _, _, e1 := syscall_syscall(SYS___MLOCKALL, _BPX_SWAP, 0, 0) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___MLOCKALL<<4, _BPX_SWAP) + runtime.ExitSyscall() + if r0 != 0 { + err = errnoErr2(e1, e2) } return } func Munlockall() (err error) { - _, _, e1 := syscall_syscall(SYS___MLOCKALL, _BPX_SWAP, 0, 0) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___MLOCKALL<<4, _BPX_SWAP) + runtime.ExitSyscall() + if r0 != 0 { + err = errnoErr2(e1, e2) } return } @@ -1372,15 +2184,104 @@ func ClockGettime(clockid int32, ts *Timespec) error { return nil } -func Statfs(path string, stat *Statfs_t) (err error) { - fd, err := open(path, O_RDONLY, 0) - defer Close(fd) - if err != nil { - return err +// Chtag + +//go:nosplit +func get_ChtagAddr() *(func(path string, ccsid uint64, textbit uint64) error) + +var Chtag = enter_Chtag + +func enter_Chtag(path string, ccsid uint64, textbit uint64) error { + funcref := get_ChtagAddr() + if validSetxattr() { + *funcref = impl_Chtag + } else { + *funcref = legacy_Chtag } - return Fstatfs(fd, stat) + return (*funcref)(path, ccsid, textbit) } +func legacy_Chtag(path string, ccsid uint64, textbit uint64) error { + tag := ccsid<<16 | textbit<<15 + var tag_buff [8]byte + DecodeData(tag_buff[:], 8, tag) + return Setxattr(path, "filetag", tag_buff[:], XATTR_REPLACE) +} + +func impl_Chtag(path string, ccsid uint64, textbit uint64) error { + tag := ccsid<<16 | textbit<<15 + var tag_buff [4]byte + DecodeData(tag_buff[:], 4, tag) + return Setxattr(path, "system.filetag", tag_buff[:], XATTR_REPLACE) +} + +// End of Chtag + +// Nanosleep + +//go:nosplit +func get_NanosleepAddr() *(func(time *Timespec, leftover *Timespec) error) + +var Nanosleep = enter_Nanosleep + +func enter_Nanosleep(time *Timespec, leftover *Timespec) error { + funcref := get_NanosleepAddr() + if funcptrtest(GetZosLibVec()+SYS_NANOSLEEP<<4, "") == 0 { + *funcref = impl_Nanosleep + } else { + *funcref = legacyNanosleep + } + return (*funcref)(time, leftover) +} + +func impl_Nanosleep(time *Timespec, leftover *Timespec) error { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_NANOSLEEP<<4, uintptr(unsafe.Pointer(time)), uintptr(unsafe.Pointer(leftover))) + runtime.ExitSyscall() + if int64(r0) == -1 { + return errnoErr2(e1, e2) + } + return nil +} + +func legacyNanosleep(time *Timespec, leftover *Timespec) error { + t0 := runtime.Nanotime1() + var secrem uint32 + var nsecrem uint32 + total := time.Sec*1000000000 + time.Nsec + elapsed := runtime.Nanotime1() - t0 + var rv int32 + var rc int32 + var err error + // repeatedly sleep for 1 second until less than 1 second left + for total-elapsed > 1000000000 { + rv, rc, _ = BpxCondTimedWait(uint32(1), uint32(0), uint32(CW_CONDVAR), &secrem, &nsecrem) + if rv != 0 && rc != 112 { // 112 is EAGAIN + if leftover != nil && rc == 120 { // 120 is EINTR + leftover.Sec = int64(secrem) + leftover.Nsec = int64(nsecrem) + } + err = Errno(rc) + return err + } + elapsed = runtime.Nanotime1() - t0 + } + // sleep the remainder + if total > elapsed { + rv, rc, _ = BpxCondTimedWait(uint32(0), uint32(total-elapsed), uint32(CW_CONDVAR), &secrem, &nsecrem) + } + if leftover != nil && rc == 120 { + leftover.Sec = int64(secrem) + leftover.Nsec = int64(nsecrem) + } + if rv != 0 && rc != 112 { + err = Errno(rc) + } + return err +} + +// End of Nanosleep + var ( Stdin = 0 Stdout = 1 @@ -1395,6 +2296,9 @@ var ( errENOENT error = syscall.ENOENT ) +var ZosTraceLevel int +var ZosTracefile *os.File + var ( signalNameMapOnce sync.Once signalNameMap map[string]syscall.Signal @@ -1416,6 +2320,56 @@ func errnoErr(e Errno) error { return e } +var reg *regexp.Regexp + +// enhanced with zos specific errno2 +func errnoErr2(e Errno, e2 uintptr) error { + switch e { + case 0: + return nil + case EAGAIN: + return errEAGAIN + /* + Allow the retrieval of errno2 for EINVAL and ENOENT on zos + case EINVAL: + return errEINVAL + case ENOENT: + return errENOENT + */ + } + if ZosTraceLevel > 0 { + var name string + if reg == nil { + reg = regexp.MustCompile("(^unix\\.[^/]+$|.*\\/unix\\.[^/]+$)") + } + i := 1 + pc, file, line, ok := runtime.Caller(i) + if ok { + name = runtime.FuncForPC(pc).Name() + } + for ok && reg.MatchString(runtime.FuncForPC(pc).Name()) { + i += 1 + pc, file, line, ok = runtime.Caller(i) + } + if ok { + if ZosTracefile == nil { + ZosConsolePrintf("From %s:%d\n", file, line) + ZosConsolePrintf("%s: %s (errno2=0x%x)\n", name, e.Error(), e2) + } else { + fmt.Fprintf(ZosTracefile, "From %s:%d\n", file, line) + fmt.Fprintf(ZosTracefile, "%s: %s (errno2=0x%x)\n", name, e.Error(), e2) + } + } else { + if ZosTracefile == nil { + ZosConsolePrintf("%s (errno2=0x%x)\n", e.Error(), e2) + } else { + fmt.Fprintf(ZosTracefile, "%s (errno2=0x%x)\n", e.Error(), e2) + } + } + } + return e +} + // ErrnoName returns the error name for error number e. func ErrnoName(e Errno) string { i := sort.Search(len(errorList), func(i int) bool { @@ -1474,6 +2428,9 @@ func (m *mmapper) Mmap(fd int, offset int64, length int, prot int, flags int) (d return nil, EINVAL } + // Set __MAP_64 by default + flags |= __MAP_64 + // Map the requested memory. addr, errno := m.mmap(0, uintptr(length), prot, flags, fd, offset) if errno != nil { @@ -1778,83 +2735,170 @@ func Exec(argv0 string, argv []string, envv []string) error { return syscall.Exec(argv0, argv, envv) } -func Mount(source string, target string, fstype string, flags uintptr, data string) (err error) { - if needspace := 8 - len(fstype); needspace <= 0 { - fstype = fstype[:8] +func Getag(path string) (ccsid uint16, flag uint16, err error) { + var val [8]byte + sz, err := Getxattr(path, "ccsid", val[:]) + if err != nil { + return + } + ccsid = uint16(EncodeData(val[0:sz])) + sz, err = Getxattr(path, "flags", val[:]) + if err != nil { + return + } + flag = uint16(EncodeData(val[0:sz]) >> 15) + return +} + +// Mount begin +func impl_Mount(source string, target string, fstype string, flags uintptr, data string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(source) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(target) + if err != nil { + return + } + var _p2 *byte + _p2, err = BytePtrFromString(fstype) + if err != nil { + return + } + var _p3 *byte + _p3, err = BytePtrFromString(data) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___MOUNT1_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(unsafe.Pointer(_p2)), uintptr(flags), uintptr(unsafe.Pointer(_p3))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_MountAddr() *(func(source string, target string, fstype string, flags uintptr, data string) (err error)) + +var Mount = enter_Mount + +func enter_Mount(source string, target string, fstype string, flags uintptr, data string) (err error) { + funcref := get_MountAddr() + if validMount() { + *funcref = impl_Mount } else { - fstype += " "[:needspace] + *funcref = legacyMount + } + return (*funcref)(source, target, fstype, flags, data) +} + +func legacyMount(source string, target string, fstype string, flags uintptr, data string) (err error) { + if needspace := 8 - len(fstype); needspace <= 0 { + fstype = fstype[0:8] + } else { + fstype += " "[0:needspace] } return mount_LE(target, source, fstype, uint32(flags), int32(len(data)), data) } -func Unmount(name string, mtm int) (err error) { +func validMount() bool { + if funcptrtest(GetZosLibVec()+SYS___MOUNT1_A<<4, "") == 0 { + if name, err := getLeFuncName(GetZosLibVec() + SYS___MOUNT1_A<<4); err == nil { + return name == "__mount1_a" + } + } + return false +} + +// Mount end + +// Unmount begin +func impl_Unmount(target string, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(target) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___UMOUNT2_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(flags)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_UnmountAddr() *(func(target string, flags int) (err error)) + +var Unmount = enter_Unmount + +func enter_Unmount(target string, flags int) (err error) { + funcref := get_UnmountAddr() + if funcptrtest(GetZosLibVec()+SYS___UMOUNT2_A<<4, "") == 0 { + *funcref = impl_Unmount + } else { + *funcref = legacyUnmount + } + return (*funcref)(target, flags) +} + +func legacyUnmount(name string, mtm int) (err error) { // mountpoint is always a full path and starts with a '/' // check if input string is not a mountpoint but a filesystem name if name[0] != '/' { - return unmount(name, mtm) + return unmount_LE(name, mtm) } // treat name as mountpoint b2s := func(arr []byte) string { - nulli := bytes.IndexByte(arr, 0) - if nulli == -1 { - return string(arr) - } else { - return string(arr[:nulli]) + var str string + for i := 0; i < len(arr); i++ { + if arr[i] == 0 { + str = string(arr[:i]) + break + } } + return str } var buffer struct { header W_Mnth fsinfo [64]W_Mntent } - fsCount, err := W_Getmntent_A((*byte)(unsafe.Pointer(&buffer)), int(unsafe.Sizeof(buffer))) - if err != nil { - return err - } - if fsCount == 0 { - return EINVAL - } - for i := 0; i < fsCount; i++ { - if b2s(buffer.fsinfo[i].Mountpoint[:]) == name { - err = unmount(b2s(buffer.fsinfo[i].Fsname[:]), mtm) - break + fs_count, err := W_Getmntent_A((*byte)(unsafe.Pointer(&buffer)), int(unsafe.Sizeof(buffer))) + if err == nil { + err = EINVAL + for i := 0; i < fs_count; i++ { + if b2s(buffer.fsinfo[i].Mountpoint[:]) == name { + err = unmount_LE(b2s(buffer.fsinfo[i].Fsname[:]), mtm) + break + } } + } else if fs_count == 0 { + err = EINVAL } return err } -func fdToPath(dirfd int) (path string, err error) { - var buffer [1024]byte - // w_ctrl() - ret := runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS_W_IOCTL<<4, - []uintptr{uintptr(dirfd), 17, 1024, uintptr(unsafe.Pointer(&buffer[0]))}) - if ret == 0 { - zb := bytes.IndexByte(buffer[:], 0) - if zb == -1 { - zb = len(buffer) - } - // __e2a_l() - runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS___E2A_L<<4, - []uintptr{uintptr(unsafe.Pointer(&buffer[0])), uintptr(zb)}) - return string(buffer[:zb]), nil - } - // __errno() - errno := int(*(*int32)(unsafe.Pointer(runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS___ERRNO<<4, - []uintptr{})))) - // __errno2() - errno2 := int(runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS___ERRNO2<<4, - []uintptr{})) - // strerror_r() - ret = runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS_STRERROR_R<<4, - []uintptr{uintptr(errno), uintptr(unsafe.Pointer(&buffer[0])), 1024}) - if ret == 0 { - zb := bytes.IndexByte(buffer[:], 0) - if zb == -1 { - zb = len(buffer) - } - return "", fmt.Errorf("%s (errno2=0x%x)", buffer[:zb], errno2) - } else { - return "", fmt.Errorf("fdToPath errno %d (errno2=0x%x)", errno, errno2) +// Unmount end + +func direntIno(buf []byte) (uint64, bool) { + return readInt(buf, unsafe.Offsetof(Dirent{}.Ino), unsafe.Sizeof(Dirent{}.Ino)) +} + +func direntReclen(buf []byte) (uint64, bool) { + return readInt(buf, unsafe.Offsetof(Dirent{}.Reclen), unsafe.Sizeof(Dirent{}.Reclen)) +} + +func direntNamlen(buf []byte) (uint64, bool) { + reclen, ok := direntReclen(buf) + if !ok { + return 0, false } + return reclen - uint64(unsafe.Offsetof(Dirent{}.Name)), true } func direntLeToDirentUnix(dirent *direntLE, dir uintptr, path string) (Dirent, error) { @@ -1896,7 +2940,7 @@ func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) { } // Get path from fd to avoid unavailable call (fdopendir) - path, err := fdToPath(fd) + path, err := ZosFdToPath(fd) if err != nil { return 0, err } @@ -1910,7 +2954,7 @@ func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) { for { var entryLE direntLE var entrypLE *direntLE - e := readdir_r(d, &entryLE, &entrypLE) + e := Readdir_r(d, &entryLE, &entrypLE) if e != nil { return n, e } @@ -1956,23 +3000,214 @@ func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) { return n, nil } -func ReadDirent(fd int, buf []byte) (n int, err error) { - var base = (*uintptr)(unsafe.Pointer(new(uint64))) - return Getdirentries(fd, buf, base) +func Err2ad() (eadd *int) { + r0, _, _ := CallLeFuncWithErr(GetZosLibVec() + SYS___ERR2AD<<4) + eadd = (*int)(unsafe.Pointer(r0)) + return } -func direntIno(buf []byte) (uint64, bool) { - return readInt(buf, unsafe.Offsetof(Dirent{}.Ino), unsafe.Sizeof(Dirent{}.Ino)) -} - -func direntReclen(buf []byte) (uint64, bool) { - return readInt(buf, unsafe.Offsetof(Dirent{}.Reclen), unsafe.Sizeof(Dirent{}.Reclen)) -} - -func direntNamlen(buf []byte) (uint64, bool) { - reclen, ok := direntReclen(buf) - if !ok { - return 0, false +func ZosConsolePrintf(format string, v ...interface{}) (int, error) { + type __cmsg struct { + _ uint16 + _ [2]uint8 + __msg_length uint32 + __msg uintptr + _ [4]uint8 } - return reclen - uint64(unsafe.Offsetof(Dirent{}.Name)), true + msg := fmt.Sprintf(format, v...) + strptr := unsafe.Pointer((*reflect.StringHeader)(unsafe.Pointer(&msg)).Data) + len := (*reflect.StringHeader)(unsafe.Pointer(&msg)).Len + cmsg := __cmsg{__msg_length: uint32(len), __msg: uintptr(strptr)} + cmd := uint32(0) + runtime.EnterSyscall() + rc, err2, err1 := CallLeFuncWithErr(GetZosLibVec()+SYS_____CONSOLE_A<<4, uintptr(unsafe.Pointer(&cmsg)), 0, uintptr(unsafe.Pointer(&cmd))) + runtime.ExitSyscall() + if rc != 0 { + return 0, fmt.Errorf("%s (errno2=0x%x)\n", err1.Error(), err2) + } + return 0, nil +} +func ZosStringToEbcdicBytes(str string, nullterm bool) (ebcdicBytes []byte) { + if nullterm { + ebcdicBytes = []byte(str + "\x00") + } else { + ebcdicBytes = []byte(str) + } + A2e(ebcdicBytes) + return +} +func ZosEbcdicBytesToString(b []byte, trimRight bool) (str string) { + res := make([]byte, len(b)) + copy(res, b) + E2a(res) + if trimRight { + str = string(bytes.TrimRight(res, " \x00")) + } else { + str = string(res) + } + return +} + +func fdToPath(dirfd int) (path string, err error) { + var buffer [1024]byte + // w_ctrl() + ret := runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS_W_IOCTL<<4, + []uintptr{uintptr(dirfd), 17, 1024, uintptr(unsafe.Pointer(&buffer[0]))}) + if ret == 0 { + zb := bytes.IndexByte(buffer[:], 0) + if zb == -1 { + zb = len(buffer) + } + // __e2a_l() + runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS___E2A_L<<4, + []uintptr{uintptr(unsafe.Pointer(&buffer[0])), uintptr(zb)}) + return string(buffer[:zb]), nil + } + // __errno() + errno := int(*(*int32)(unsafe.Pointer(runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS___ERRNO<<4, + []uintptr{})))) + // __errno2() + errno2 := int(runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS___ERRNO2<<4, + []uintptr{})) + // strerror_r() + ret = runtime.CallLeFuncByPtr(runtime.XplinkLibvec+SYS_STRERROR_R<<4, + []uintptr{uintptr(errno), uintptr(unsafe.Pointer(&buffer[0])), 1024}) + if ret == 0 { + zb := bytes.IndexByte(buffer[:], 0) + if zb == -1 { + zb = len(buffer) + } + return "", fmt.Errorf("%s (errno2=0x%x)", buffer[:zb], errno2) + } else { + return "", fmt.Errorf("fdToPath errno %d (errno2=0x%x)", errno, errno2) + } +} + +func impl_Mkfifoat(dirfd int, path string, mode uint32) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___MKFIFOAT_A<<4, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_MkfifoatAddr() *(func(dirfd int, path string, mode uint32) (err error)) + +var Mkfifoat = enter_Mkfifoat + +func enter_Mkfifoat(dirfd int, path string, mode uint32) (err error) { + funcref := get_MkfifoatAddr() + if funcptrtest(GetZosLibVec()+SYS___MKFIFOAT_A<<4, "") == 0 { + *funcref = impl_Mkfifoat + } else { + *funcref = legacy_Mkfifoat + } + return (*funcref)(dirfd, path, mode) +} + +func legacy_Mkfifoat(dirfd int, path string, mode uint32) (err error) { + dirname, err := ZosFdToPath(dirfd) + if err != nil { + return err + } + return Mkfifo(dirname+"/"+path, mode) +} + +//sys Posix_openpt(oflag int) (fd int, err error) = SYS_POSIX_OPENPT +//sys Grantpt(fildes int) (rc int, err error) = SYS_GRANTPT +//sys Unlockpt(fildes int) (rc int, err error) = SYS_UNLOCKPT + +func fcntlAsIs(fd uintptr, cmd int, arg uintptr) (val int, err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_FCNTL<<4, uintptr(fd), uintptr(cmd), arg) + runtime.ExitSyscall() + val = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +func Fcntl(fd uintptr, cmd int, op interface{}) (ret int, err error) { + switch op.(type) { + case *Flock_t: + err = FcntlFlock(fd, cmd, op.(*Flock_t)) + if err != nil { + ret = -1 + } + return + case int: + return FcntlInt(fd, cmd, op.(int)) + case *F_cnvrt: + return fcntlAsIs(fd, cmd, uintptr(unsafe.Pointer(op.(*F_cnvrt)))) + case unsafe.Pointer: + return fcntlAsIs(fd, cmd, uintptr(op.(unsafe.Pointer))) + default: + return -1, EINVAL + } + return +} + +func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) { + if raceenabled { + raceReleaseMerge(unsafe.Pointer(&ioSync)) + } + return sendfile(outfd, infd, offset, count) +} + +func sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) { + // TODO: use LE call instead if the call is implemented + originalOffset, err := Seek(infd, 0, SEEK_CUR) + if err != nil { + return -1, err + } + //start reading data from in_fd + if offset != nil { + _, err := Seek(infd, *offset, SEEK_SET) + if err != nil { + return -1, err + } + } + + buf := make([]byte, count) + readBuf := make([]byte, 0) + var n int = 0 + for i := 0; i < count; i += n { + n, err := Read(infd, buf) + if n == 0 { + if err != nil { + return -1, err + } else { // EOF + break + } + } + readBuf = append(readBuf, buf...) + buf = buf[0:0] + } + + n2, err := Write(outfd, readBuf) + if err != nil { + return -1, err + } + + //When sendfile() returns, this variable will be set to the + // offset of the byte following the last byte that was read. + if offset != nil { + *offset = *offset + int64(n) + // If offset is not NULL, then sendfile() does not modify the file + // offset of in_fd + _, err := Seek(infd, originalOffset, SEEK_SET) + if err != nil { + return -1, err + } + } + return n2, nil } diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/sysvshm_unix.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/sysvshm_unix.go index 79a84f18b..672d6b0a8 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/sysvshm_unix.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/sysvshm_unix.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build (darwin && !ios) || linux +//go:build (darwin && !ios) || linux || zos package unix diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/sysvshm_unix_other.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/sysvshm_unix_other.go index 9eb0db664..8b7977a28 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/sysvshm_unix_other.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/sysvshm_unix_other.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build darwin && !ios +//go:build (darwin && !ios) || zos package unix diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/vgetrandom_linux.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/vgetrandom_linux.go new file mode 100644 index 000000000..07ac8e09d --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/vgetrandom_linux.go @@ -0,0 +1,13 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build linux && go1.24 + +package unix + +import _ "unsafe" + +//go:linkname vgetrandom runtime.vgetrandom +//go:noescape +func vgetrandom(p []byte, flags uint32) (ret int, supported bool) diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/vgetrandom_unsupported.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/vgetrandom_unsupported.go new file mode 100644 index 000000000..297e97bce --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/vgetrandom_unsupported.go @@ -0,0 +1,11 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !linux || !go1.24 + +package unix + +func vgetrandom(p []byte, flags uint32) (ret int, supported bool) { + return -1, false +} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zerrors_darwin_amd64.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zerrors_darwin_amd64.go index e40fa8524..d73c4652e 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zerrors_darwin_amd64.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zerrors_darwin_amd64.go @@ -237,6 +237,9 @@ const ( CLOCK_UPTIME_RAW_APPROX = 0x9 CLONE_NOFOLLOW = 0x1 CLONE_NOOWNERCOPY = 0x2 + CONNECT_DATA_AUTHENTICATED = 0x4 + CONNECT_DATA_IDEMPOTENT = 0x2 + CONNECT_RESUME_ON_READ_WRITE = 0x1 CR0 = 0x0 CR1 = 0x1000 CR2 = 0x2000 @@ -1169,6 +1172,11 @@ const ( PT_WRITE_D = 0x5 PT_WRITE_I = 0x4 PT_WRITE_U = 0x6 + RENAME_EXCL = 0x4 + RENAME_NOFOLLOW_ANY = 0x10 + RENAME_RESERVED1 = 0x8 + RENAME_SECLUDE = 0x1 + RENAME_SWAP = 0x2 RLIMIT_AS = 0x5 RLIMIT_CORE = 0x4 RLIMIT_CPU = 0x0 @@ -1260,6 +1268,10 @@ const ( RTV_SSTHRESH = 0x20 RUSAGE_CHILDREN = -0x1 RUSAGE_SELF = 0x0 + SAE_ASSOCID_ALL = 0xffffffff + SAE_ASSOCID_ANY = 0x0 + SAE_CONNID_ALL = 0xffffffff + SAE_CONNID_ANY = 0x0 SCM_CREDS = 0x3 SCM_RIGHTS = 0x1 SCM_TIMESTAMP = 0x2 diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zerrors_darwin_arm64.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zerrors_darwin_arm64.go index bb02aa6c0..4a55a4005 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zerrors_darwin_arm64.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zerrors_darwin_arm64.go @@ -237,6 +237,9 @@ const ( CLOCK_UPTIME_RAW_APPROX = 0x9 CLONE_NOFOLLOW = 0x1 CLONE_NOOWNERCOPY = 0x2 + CONNECT_DATA_AUTHENTICATED = 0x4 + CONNECT_DATA_IDEMPOTENT = 0x2 + CONNECT_RESUME_ON_READ_WRITE = 0x1 CR0 = 0x0 CR1 = 0x1000 CR2 = 0x2000 @@ -1169,6 +1172,11 @@ const ( PT_WRITE_D = 0x5 PT_WRITE_I = 0x4 PT_WRITE_U = 0x6 + RENAME_EXCL = 0x4 + RENAME_NOFOLLOW_ANY = 0x10 + RENAME_RESERVED1 = 0x8 + RENAME_SECLUDE = 0x1 + RENAME_SWAP = 0x2 RLIMIT_AS = 0x5 RLIMIT_CORE = 0x4 RLIMIT_CPU = 0x0 @@ -1260,6 +1268,10 @@ const ( RTV_SSTHRESH = 0x20 RUSAGE_CHILDREN = -0x1 RUSAGE_SELF = 0x0 + SAE_ASSOCID_ALL = 0xffffffff + SAE_ASSOCID_ANY = 0x0 + SAE_CONNID_ALL = 0xffffffff + SAE_CONNID_ANY = 0x0 SCM_CREDS = 0x3 SCM_RIGHTS = 0x1 SCM_TIMESTAMP = 0x2 diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zerrors_linux.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zerrors_linux.go index 36bf8399f..4f432bfe8 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zerrors_linux.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zerrors_linux.go @@ -321,6 +321,9 @@ const ( AUDIT_INTEGRITY_STATUS = 0x70a AUDIT_IPC = 0x517 AUDIT_IPC_SET_PERM = 0x51f + AUDIT_IPE_ACCESS = 0x58c + AUDIT_IPE_CONFIG_CHANGE = 0x58d + AUDIT_IPE_POLICY_LOAD = 0x58e AUDIT_KERNEL = 0x7d0 AUDIT_KERNEL_OTHER = 0x524 AUDIT_KERN_MODULE = 0x532 @@ -457,6 +460,7 @@ const ( B600 = 0x8 B75 = 0x2 B9600 = 0xd + BCACHEFS_SUPER_MAGIC = 0xca451a4e BDEVFS_MAGIC = 0x62646576 BINDERFS_SUPER_MAGIC = 0x6c6f6f70 BINFMTFS_MAGIC = 0x42494e4d @@ -488,11 +492,14 @@ const ( BPF_F_ID = 0x20 BPF_F_NETFILTER_IP_DEFRAG = 0x1 BPF_F_QUERY_EFFECTIVE = 0x1 + BPF_F_REDIRECT_FLAGS = 0x19 BPF_F_REPLACE = 0x4 BPF_F_SLEEPABLE = 0x10 BPF_F_STRICT_ALIGNMENT = 0x1 + BPF_F_TEST_REG_INVARIANTS = 0x80 BPF_F_TEST_RND_HI32 = 0x4 BPF_F_TEST_RUN_ON_CPU = 0x1 + BPF_F_TEST_SKB_CHECKSUM_COMPLETE = 0x4 BPF_F_TEST_STATE_FREQ = 0x8 BPF_F_TEST_XDP_LIVE_FRAMES = 0x2 BPF_F_XDP_DEV_BOUND_ONLY = 0x40 @@ -501,6 +508,7 @@ const ( BPF_IMM = 0x0 BPF_IND = 0x40 BPF_JA = 0x0 + BPF_JCOND = 0xe0 BPF_JEQ = 0x10 BPF_JGE = 0x30 BPF_JGT = 0x20 @@ -656,6 +664,9 @@ const ( CAN_NPROTO = 0x8 CAN_RAW = 0x1 CAN_RAW_FILTER_MAX = 0x200 + CAN_RAW_XL_VCID_RX_FILTER = 0x4 + CAN_RAW_XL_VCID_TX_PASS = 0x2 + CAN_RAW_XL_VCID_TX_SET = 0x1 CAN_RTR_FLAG = 0x40000000 CAN_SFF_ID_BITS = 0xb CAN_SFF_MASK = 0x7ff @@ -923,6 +934,7 @@ const ( EPOLL_CTL_ADD = 0x1 EPOLL_CTL_DEL = 0x2 EPOLL_CTL_MOD = 0x3 + EPOLL_IOC_TYPE = 0x8a EROFS_SUPER_MAGIC_V1 = 0xe0f5e1e2 ESP_V4_FLOW = 0xa ESP_V6_FLOW = 0xc @@ -936,9 +948,6 @@ const ( ETHTOOL_FEC_OFF = 0x4 ETHTOOL_FEC_RS = 0x8 ETHTOOL_FLAG_ALL = 0x7 - ETHTOOL_FLAG_COMPACT_BITSETS = 0x1 - ETHTOOL_FLAG_OMIT_REPLY = 0x2 - ETHTOOL_FLAG_STATS = 0x4 ETHTOOL_FLASHDEV = 0x33 ETHTOOL_FLASH_MAX_FILENAME = 0x80 ETHTOOL_FWVERS_LEN = 0x20 @@ -1161,6 +1170,7 @@ const ( EXTA = 0xe EXTB = 0xf F2FS_SUPER_MAGIC = 0xf2f52010 + FALLOC_FL_ALLOCATE_RANGE = 0x0 FALLOC_FL_COLLAPSE_RANGE = 0x8 FALLOC_FL_INSERT_RANGE = 0x20 FALLOC_FL_KEEP_SIZE = 0x1 @@ -1235,6 +1245,7 @@ const ( FAN_REPORT_DFID_NAME = 0xc00 FAN_REPORT_DFID_NAME_TARGET = 0x1e00 FAN_REPORT_DIR_FID = 0x400 + FAN_REPORT_FD_ERROR = 0x2000 FAN_REPORT_FID = 0x200 FAN_REPORT_NAME = 0x800 FAN_REPORT_PIDFD = 0x80 @@ -1320,8 +1331,10 @@ const ( FUSE_SUPER_MAGIC = 0x65735546 FUTEXFS_SUPER_MAGIC = 0xbad1dea F_ADD_SEALS = 0x409 + F_CREATED_QUERY = 0x404 F_DUPFD = 0x0 F_DUPFD_CLOEXEC = 0x406 + F_DUPFD_QUERY = 0x403 F_EXLCK = 0x4 F_GETFD = 0x1 F_GETFL = 0x3 @@ -1338,6 +1351,7 @@ const ( F_OFD_SETLK = 0x25 F_OFD_SETLKW = 0x26 F_OK = 0x0 + F_SEAL_EXEC = 0x20 F_SEAL_FUTURE_WRITE = 0x10 F_SEAL_GROW = 0x4 F_SEAL_SEAL = 0x1 @@ -1540,6 +1554,7 @@ const ( IPPROTO_ROUTING = 0x2b IPPROTO_RSVP = 0x2e IPPROTO_SCTP = 0x84 + IPPROTO_SMC = 0x100 IPPROTO_TCP = 0x6 IPPROTO_TP = 0x1d IPPROTO_UDP = 0x11 @@ -1612,6 +1627,8 @@ const ( IPV6_UNICAST_IF = 0x4c IPV6_USER_FLOW = 0xe IPV6_V6ONLY = 0x1a + IPV6_VERSION = 0x60 + IPV6_VERSION_MASK = 0xf0 IPV6_XFRM_POLICY = 0x23 IP_ADD_MEMBERSHIP = 0x23 IP_ADD_SOURCE_MEMBERSHIP = 0x27 @@ -1626,6 +1643,7 @@ const ( IP_FREEBIND = 0xf IP_HDRINCL = 0x3 IP_IPSEC_POLICY = 0x10 + IP_LOCAL_PORT_RANGE = 0x33 IP_MAXPACKET = 0xffff IP_MAX_MEMBERSHIPS = 0x14 IP_MF = 0x2000 @@ -1652,6 +1670,7 @@ const ( IP_PMTUDISC_OMIT = 0x5 IP_PMTUDISC_PROBE = 0x3 IP_PMTUDISC_WANT = 0x1 + IP_PROTOCOL = 0x34 IP_RECVERR = 0xb IP_RECVERR_RFC4884 = 0x1a IP_RECVFRAGSIZE = 0x19 @@ -1697,6 +1716,8 @@ const ( KEXEC_ARCH_S390 = 0x160000 KEXEC_ARCH_SH = 0x2a0000 KEXEC_ARCH_X86_64 = 0x3e0000 + KEXEC_CRASH_HOTPLUG_SUPPORT = 0x8 + KEXEC_FILE_DEBUG = 0x8 KEXEC_FILE_NO_INITRAMFS = 0x4 KEXEC_FILE_ON_CRASH = 0x2 KEXEC_FILE_UNLOAD = 0x1 @@ -1771,6 +1792,7 @@ const ( KEY_SPEC_USER_KEYRING = -0x4 KEY_SPEC_USER_SESSION_KEYRING = -0x5 LANDLOCK_ACCESS_FS_EXECUTE = 0x1 + LANDLOCK_ACCESS_FS_IOCTL_DEV = 0x8000 LANDLOCK_ACCESS_FS_MAKE_BLOCK = 0x800 LANDLOCK_ACCESS_FS_MAKE_CHAR = 0x40 LANDLOCK_ACCESS_FS_MAKE_DIR = 0x80 @@ -1788,6 +1810,8 @@ const ( LANDLOCK_ACCESS_NET_BIND_TCP = 0x1 LANDLOCK_ACCESS_NET_CONNECT_TCP = 0x2 LANDLOCK_CREATE_RULESET_VERSION = 0x1 + LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET = 0x1 + LANDLOCK_SCOPE_SIGNAL = 0x2 LINUX_REBOOT_CMD_CAD_OFF = 0x0 LINUX_REBOOT_CMD_CAD_ON = 0x89abcdef LINUX_REBOOT_CMD_HALT = 0xcdef0123 @@ -1849,9 +1873,23 @@ const ( MADV_UNMERGEABLE = 0xd MADV_WILLNEED = 0x3 MADV_WIPEONFORK = 0x12 + MAP_DROPPABLE = 0x8 MAP_FILE = 0x0 MAP_FIXED = 0x10 MAP_FIXED_NOREPLACE = 0x100000 + MAP_HUGE_16GB = 0x88000000 + MAP_HUGE_16KB = 0x38000000 + MAP_HUGE_16MB = 0x60000000 + MAP_HUGE_1GB = 0x78000000 + MAP_HUGE_1MB = 0x50000000 + MAP_HUGE_256MB = 0x70000000 + MAP_HUGE_2GB = 0x7c000000 + MAP_HUGE_2MB = 0x54000000 + MAP_HUGE_32MB = 0x64000000 + MAP_HUGE_512KB = 0x4c000000 + MAP_HUGE_512MB = 0x74000000 + MAP_HUGE_64KB = 0x40000000 + MAP_HUGE_8MB = 0x5c000000 MAP_HUGE_MASK = 0x3f MAP_HUGE_SHIFT = 0x1a MAP_PRIVATE = 0x2 @@ -1898,6 +1936,9 @@ const ( MNT_DETACH = 0x2 MNT_EXPIRE = 0x4 MNT_FORCE = 0x1 + MNT_ID_REQ_SIZE_VER0 = 0x18 + MNT_ID_REQ_SIZE_VER1 = 0x20 + MNT_NS_INFO_SIZE_VER0 = 0x10 MODULE_INIT_COMPRESSED_FILE = 0x4 MODULE_INIT_IGNORE_MODVERSIONS = 0x1 MODULE_INIT_IGNORE_VERMAGIC = 0x2 @@ -1933,6 +1974,7 @@ const ( MSG_PEEK = 0x2 MSG_PROXY = 0x10 MSG_RST = 0x1000 + MSG_SOCK_DEVMEM = 0x2000000 MSG_SYN = 0x400 MSG_TRUNC = 0x20 MSG_TRYHARD = 0x4 @@ -2049,6 +2091,7 @@ const ( NFC_ATR_REQ_MAXSIZE = 0x40 NFC_ATR_RES_GB_MAXSIZE = 0x2f NFC_ATR_RES_MAXSIZE = 0x40 + NFC_ATS_MAXSIZE = 0x14 NFC_COMM_ACTIVE = 0x0 NFC_COMM_PASSIVE = 0x1 NFC_DEVICE_NAME_MAXSIZE = 0x8 @@ -2129,6 +2172,7 @@ const ( NFNL_SUBSYS_QUEUE = 0x3 NFNL_SUBSYS_ULOG = 0x4 NFS_SUPER_MAGIC = 0x6969 + NFT_BITWISE_BOOL = 0x0 NFT_CHAIN_FLAGS = 0x7 NFT_CHAIN_MAXNAMELEN = 0x100 NFT_CT_MAX = 0x17 @@ -2163,10 +2207,10 @@ const ( NFT_REG_SIZE = 0x10 NFT_REJECT_ICMPX_MAX = 0x3 NFT_RT_MAX = 0x4 - NFT_SECMARK_CTX_MAXLEN = 0x100 + NFT_SECMARK_CTX_MAXLEN = 0x1000 NFT_SET_MAXNAMELEN = 0x100 NFT_SOCKET_MAX = 0x3 - NFT_TABLE_F_MASK = 0x3 + NFT_TABLE_F_MASK = 0x7 NFT_TABLE_MAXNAMELEN = 0x100 NFT_TRACETYPE_MAX = 0x3 NFT_TUNNEL_F_MASK = 0x7 @@ -2302,6 +2346,7 @@ const ( PERF_AUX_FLAG_PARTIAL = 0x4 PERF_AUX_FLAG_PMU_FORMAT_TYPE_MASK = 0xff00 PERF_AUX_FLAG_TRUNCATED = 0x1 + PERF_BRANCH_ENTRY_INFO_BITS_MAX = 0x21 PERF_BR_ARM64_DEBUG_DATA = 0x7 PERF_BR_ARM64_DEBUG_EXIT = 0x5 PERF_BR_ARM64_DEBUG_HALT = 0x4 @@ -2331,9 +2376,11 @@ const ( PERF_MEM_LVLNUM_IO = 0xa PERF_MEM_LVLNUM_L1 = 0x1 PERF_MEM_LVLNUM_L2 = 0x2 + PERF_MEM_LVLNUM_L2_MHB = 0x5 PERF_MEM_LVLNUM_L3 = 0x3 PERF_MEM_LVLNUM_L4 = 0x4 PERF_MEM_LVLNUM_LFB = 0xc + PERF_MEM_LVLNUM_MSC = 0x6 PERF_MEM_LVLNUM_NA = 0xf PERF_MEM_LVLNUM_PMEM = 0xe PERF_MEM_LVLNUM_RAM = 0xd @@ -2399,12 +2446,14 @@ const ( PERF_RECORD_MISC_USER = 0x2 PERF_SAMPLE_BRANCH_PLM_ALL = 0x7 PERF_SAMPLE_WEIGHT_TYPE = 0x1004000 + PID_FS_MAGIC = 0x50494446 PIPEFS_MAGIC = 0x50495045 PPPIOCGNPMODE = 0xc008744c PPPIOCNEWUNIT = 0xc004743e PRIO_PGRP = 0x1 PRIO_PROCESS = 0x0 PRIO_USER = 0x2 + PROCFS_IOCTL_MAGIC = 'f' PROC_SUPER_MAGIC = 0x9fa0 PROT_EXEC = 0x4 PROT_GROWSDOWN = 0x1000000 @@ -2452,6 +2501,7 @@ const ( PR_GET_PDEATHSIG = 0x2 PR_GET_SECCOMP = 0x15 PR_GET_SECUREBITS = 0x1b + PR_GET_SHADOW_STACK_STATUS = 0x4a PR_GET_SPECULATION_CTRL = 0x34 PR_GET_TAGGED_ADDR_CTRL = 0x38 PR_GET_THP_DISABLE = 0x2a @@ -2460,6 +2510,7 @@ const ( PR_GET_TIMING = 0xd PR_GET_TSC = 0x19 PR_GET_UNALIGN = 0x5 + PR_LOCK_SHADOW_STACK_STATUS = 0x4c PR_MCE_KILL = 0x21 PR_MCE_KILL_CLEAR = 0x0 PR_MCE_KILL_DEFAULT = 0x2 @@ -2486,6 +2537,25 @@ const ( PR_PAC_GET_ENABLED_KEYS = 0x3d PR_PAC_RESET_KEYS = 0x36 PR_PAC_SET_ENABLED_KEYS = 0x3c + PR_PMLEN_MASK = 0x7f000000 + PR_PMLEN_SHIFT = 0x18 + PR_PPC_DEXCR_CTRL_CLEAR = 0x4 + PR_PPC_DEXCR_CTRL_CLEAR_ONEXEC = 0x10 + PR_PPC_DEXCR_CTRL_EDITABLE = 0x1 + PR_PPC_DEXCR_CTRL_MASK = 0x1f + PR_PPC_DEXCR_CTRL_SET = 0x2 + PR_PPC_DEXCR_CTRL_SET_ONEXEC = 0x8 + PR_PPC_DEXCR_IBRTPD = 0x1 + PR_PPC_DEXCR_NPHIE = 0x3 + PR_PPC_DEXCR_SBHE = 0x0 + PR_PPC_DEXCR_SRAPD = 0x2 + PR_PPC_GET_DEXCR = 0x48 + PR_PPC_SET_DEXCR = 0x49 + PR_RISCV_CTX_SW_FENCEI_OFF = 0x1 + PR_RISCV_CTX_SW_FENCEI_ON = 0x0 + PR_RISCV_SCOPE_PER_PROCESS = 0x0 + PR_RISCV_SCOPE_PER_THREAD = 0x1 + PR_RISCV_SET_ICACHE_FLUSH_CTX = 0x47 PR_RISCV_V_GET_CONTROL = 0x46 PR_RISCV_V_SET_CONTROL = 0x45 PR_RISCV_V_VSTATE_CTRL_CUR_MASK = 0x3 @@ -2536,6 +2606,7 @@ const ( PR_SET_PTRACER = 0x59616d61 PR_SET_SECCOMP = 0x16 PR_SET_SECUREBITS = 0x1c + PR_SET_SHADOW_STACK_STATUS = 0x4b PR_SET_SPECULATION_CTRL = 0x35 PR_SET_SYSCALL_USER_DISPATCH = 0x3b PR_SET_TAGGED_ADDR_CTRL = 0x37 @@ -2546,6 +2617,9 @@ const ( PR_SET_UNALIGN = 0x6 PR_SET_VMA = 0x53564d41 PR_SET_VMA_ANON_NAME = 0x0 + PR_SHADOW_STACK_ENABLE = 0x1 + PR_SHADOW_STACK_PUSH = 0x4 + PR_SHADOW_STACK_WRITE = 0x2 PR_SME_GET_VL = 0x40 PR_SME_SET_VL = 0x3f PR_SME_SET_VL_ONEXEC = 0x40000 @@ -2577,6 +2651,28 @@ const ( PR_UNALIGN_NOPRINT = 0x1 PR_UNALIGN_SIGBUS = 0x2 PSTOREFS_MAGIC = 0x6165676c + PTP_CLK_MAGIC = '=' + PTP_ENABLE_FEATURE = 0x1 + PTP_EXTTS_EDGES = 0x6 + PTP_EXTTS_EVENT_VALID = 0x1 + PTP_EXTTS_V1_VALID_FLAGS = 0x7 + PTP_EXTTS_VALID_FLAGS = 0x1f + PTP_EXT_OFFSET = 0x10 + PTP_FALLING_EDGE = 0x4 + PTP_MAX_SAMPLES = 0x19 + PTP_PEROUT_DUTY_CYCLE = 0x2 + PTP_PEROUT_ONE_SHOT = 0x1 + PTP_PEROUT_PHASE = 0x4 + PTP_PEROUT_V1_VALID_FLAGS = 0x0 + PTP_PEROUT_VALID_FLAGS = 0x7 + PTP_PIN_GETFUNC = 0xc0603d06 + PTP_PIN_GETFUNC2 = 0xc0603d0f + PTP_RISING_EDGE = 0x2 + PTP_STRICT_FLAGS = 0x8 + PTP_SYS_OFFSET_EXTENDED = 0xc4c03d09 + PTP_SYS_OFFSET_EXTENDED2 = 0xc4c03d12 + PTP_SYS_OFFSET_PRECISE = 0xc0403d08 + PTP_SYS_OFFSET_PRECISE2 = 0xc0403d11 PTRACE_ATTACH = 0x10 PTRACE_CONT = 0x7 PTRACE_DETACH = 0x11 @@ -2833,7 +2929,6 @@ const ( RTM_NEWNEXTHOP = 0x68 RTM_NEWNEXTHOPBUCKET = 0x74 RTM_NEWNSID = 0x58 - RTM_NEWNVLAN = 0x70 RTM_NEWPREFIX = 0x34 RTM_NEWQDISC = 0x24 RTM_NEWROUTE = 0x18 @@ -2842,6 +2937,7 @@ const ( RTM_NEWTCLASS = 0x28 RTM_NEWTFILTER = 0x2c RTM_NEWTUNNEL = 0x78 + RTM_NEWVLAN = 0x70 RTM_NR_FAMILIES = 0x1b RTM_NR_MSGTYPES = 0x6c RTM_SETDCB = 0x4f @@ -2890,14 +2986,17 @@ const ( RUSAGE_SELF = 0x0 RUSAGE_THREAD = 0x1 RWF_APPEND = 0x10 + RWF_ATOMIC = 0x40 RWF_DSYNC = 0x2 RWF_HIPRI = 0x1 + RWF_NOAPPEND = 0x20 RWF_NOWAIT = 0x8 - RWF_SUPPORTED = 0x1f + RWF_SUPPORTED = 0x7f RWF_SYNC = 0x4 RWF_WRITE_LIFE_NOT_SET = 0x0 SCHED_BATCH = 0x3 SCHED_DEADLINE = 0x6 + SCHED_EXT = 0x7 SCHED_FIFO = 0x1 SCHED_FLAG_ALL = 0x7f SCHED_FLAG_DL_OVERRUN = 0x4 @@ -2914,7 +3013,9 @@ const ( SCHED_RESET_ON_FORK = 0x40000000 SCHED_RR = 0x2 SCM_CREDENTIALS = 0x2 + SCM_PIDFD = 0x4 SCM_RIGHTS = 0x1 + SCM_SECURITY = 0x3 SCM_TIMESTAMP = 0x1d SC_LOG_FLUSH = 0x100000 SECCOMP_ADDFD_FLAG_SEND = 0x2 @@ -3047,6 +3148,8 @@ const ( SIOCSMIIREG = 0x8949 SIOCSRARP = 0x8962 SIOCWANDEV = 0x894a + SK_DIAG_BPF_STORAGE_MAX = 0x3 + SK_DIAG_BPF_STORAGE_REQ_MAX = 0x1 SMACK_MAGIC = 0x43415d53 SMART_AUTOSAVE = 0xd2 SMART_AUTO_OFFLINE = 0xdb @@ -3067,6 +3170,8 @@ const ( SOCKFS_MAGIC = 0x534f434b SOCK_BUF_LOCK_MASK = 0x3 SOCK_DCCP = 0x6 + SOCK_DESTROY = 0x15 + SOCK_DIAG_BY_FAMILY = 0x14 SOCK_IOC_TYPE = 0x89 SOCK_PACKET = 0xa SOCK_RAW = 0x3 @@ -3160,6 +3265,7 @@ const ( STATX_ATTR_MOUNT_ROOT = 0x2000 STATX_ATTR_NODUMP = 0x40 STATX_ATTR_VERITY = 0x100000 + STATX_ATTR_WRITE_ATOMIC = 0x400000 STATX_BASIC_STATS = 0x7ff STATX_BLOCKS = 0x400 STATX_BTIME = 0x800 @@ -3168,12 +3274,15 @@ const ( STATX_GID = 0x10 STATX_INO = 0x100 STATX_MNT_ID = 0x1000 + STATX_MNT_ID_UNIQUE = 0x4000 STATX_MODE = 0x2 STATX_MTIME = 0x40 STATX_NLINK = 0x4 STATX_SIZE = 0x200 + STATX_SUBVOL = 0x8000 STATX_TYPE = 0x1 STATX_UID = 0x8 + STATX_WRITE_ATOMIC = 0x10000 STATX__RESERVED = 0x80000000 SYNC_FILE_RANGE_WAIT_AFTER = 0x4 SYNC_FILE_RANGE_WAIT_BEFORE = 0x1 @@ -3255,6 +3364,7 @@ const ( TCP_MAX_WINSHIFT = 0xe TCP_MD5SIG = 0xe TCP_MD5SIG_EXT = 0x20 + TCP_MD5SIG_FLAG_IFINDEX = 0x2 TCP_MD5SIG_FLAG_PREFIX = 0x1 TCP_MD5SIG_MAXKEYLEN = 0x50 TCP_MSS = 0x200 @@ -3562,12 +3672,17 @@ const ( XDP_RX_RING = 0x2 XDP_SHARED_UMEM = 0x1 XDP_STATISTICS = 0x7 + XDP_TXMD_FLAGS_CHECKSUM = 0x2 + XDP_TXMD_FLAGS_TIMESTAMP = 0x1 + XDP_TX_METADATA = 0x2 XDP_TX_RING = 0x3 XDP_UMEM_COMPLETION_RING = 0x6 XDP_UMEM_FILL_RING = 0x5 XDP_UMEM_PGOFF_COMPLETION_RING = 0x180000000 XDP_UMEM_PGOFF_FILL_RING = 0x100000000 XDP_UMEM_REG = 0x4 + XDP_UMEM_TX_METADATA_LEN = 0x4 + XDP_UMEM_TX_SW_CSUM = 0x2 XDP_UMEM_UNALIGNED_CHUNK_FLAG = 0x1 XDP_USE_NEED_WAKEUP = 0x8 XDP_USE_SG = 0x10 diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zerrors_linux_386.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zerrors_linux_386.go index 42ff8c3c1..75207613c 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zerrors_linux_386.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zerrors_linux_386.go @@ -78,6 +78,8 @@ const ( ECHOPRT = 0x400 EFD_CLOEXEC = 0x80000 EFD_NONBLOCK = 0x800 + EPIOCGPARAMS = 0x80088a02 + EPIOCSPARAMS = 0x40088a01 EPOLL_CLOEXEC = 0x80000 EXTPROC = 0x10000 FF1 = 0x8000 @@ -107,17 +109,21 @@ const ( HIDIOCGRAWINFO = 0x80084803 HIDIOCGRDESC = 0x90044802 HIDIOCGRDESCSIZE = 0x80044801 + HIDIOCREVOKE = 0x4004480d HUPCL = 0x400 ICANON = 0x2 IEXTEN = 0x8000 IN_CLOEXEC = 0x80000 IN_NONBLOCK = 0x800 IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x7b9 + IPV6_FLOWINFO_MASK = 0xffffff0f + IPV6_FLOWLABEL_MASK = 0xffff0f00 ISIG = 0x1 IUCLC = 0x200 IXOFF = 0x1000 IXON = 0x400 MAP_32BIT = 0x40 + MAP_ABOVE4G = 0x80 MAP_ANON = 0x20 MAP_ANONYMOUS = 0x20 MAP_DENYWRITE = 0x800 @@ -150,9 +156,14 @@ const ( NFDBITS = 0x20 NLDLY = 0x100 NOFLSH = 0x80 + NS_GET_MNTNS_ID = 0x8008b705 NS_GET_NSTYPE = 0xb703 NS_GET_OWNER_UID = 0xb704 NS_GET_PARENT = 0xb702 + NS_GET_PID_FROM_PIDNS = 0x8004b706 + NS_GET_PID_IN_PIDNS = 0x8004b708 + NS_GET_TGID_FROM_PIDNS = 0x8004b707 + NS_GET_TGID_IN_PIDNS = 0x8004b709 NS_GET_USERNS = 0xb701 OLCUC = 0x2 ONLCR = 0x4 @@ -229,6 +240,20 @@ const ( PPPIOCUNBRIDGECHAN = 0x7434 PPPIOCXFERUNIT = 0x744e PR_SET_PTRACER_ANY = 0xffffffff + PTP_CLOCK_GETCAPS = 0x80503d01 + PTP_CLOCK_GETCAPS2 = 0x80503d0a + PTP_ENABLE_PPS = 0x40043d04 + PTP_ENABLE_PPS2 = 0x40043d0d + PTP_EXTTS_REQUEST = 0x40103d02 + PTP_EXTTS_REQUEST2 = 0x40103d0b + PTP_MASK_CLEAR_ALL = 0x3d13 + PTP_MASK_EN_SINGLE = 0x40043d14 + PTP_PEROUT_REQUEST = 0x40383d03 + PTP_PEROUT_REQUEST2 = 0x40383d0c + PTP_PIN_SETFUNC = 0x40603d07 + PTP_PIN_SETFUNC2 = 0x40603d10 + PTP_SYS_OFFSET = 0x43403d05 + PTP_SYS_OFFSET2 = 0x43403d0e PTRACE_GETFPREGS = 0xe PTRACE_GETFPXREGS = 0x12 PTRACE_GET_THREAD_AREA = 0x19 @@ -275,10 +300,13 @@ const ( RTC_WIE_ON = 0x700f RTC_WKALM_RD = 0x80287010 RTC_WKALM_SET = 0x4028700f + SCM_DEVMEM_DMABUF = 0x4f + SCM_DEVMEM_LINEAR = 0x4e SCM_TIMESTAMPING = 0x25 SCM_TIMESTAMPING_OPT_STATS = 0x36 SCM_TIMESTAMPING_PKTINFO = 0x3a SCM_TIMESTAMPNS = 0x23 + SCM_TS_OPT_ID = 0x51 SCM_TXTIME = 0x3d SCM_WIFI_STATUS = 0x29 SECCOMP_IOCTL_NOTIF_ADDFD = 0x40182103 @@ -313,6 +341,9 @@ const ( SO_CNX_ADVICE = 0x35 SO_COOKIE = 0x39 SO_DETACH_REUSEPORT_BPF = 0x44 + SO_DEVMEM_DMABUF = 0x4f + SO_DEVMEM_DONTNEED = 0x50 + SO_DEVMEM_LINEAR = 0x4e SO_DOMAIN = 0x27 SO_DONTROUTE = 0x5 SO_ERROR = 0x4 diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go index dca436004..c68acda53 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go @@ -78,6 +78,8 @@ const ( ECHOPRT = 0x400 EFD_CLOEXEC = 0x80000 EFD_NONBLOCK = 0x800 + EPIOCGPARAMS = 0x80088a02 + EPIOCSPARAMS = 0x40088a01 EPOLL_CLOEXEC = 0x80000 EXTPROC = 0x10000 FF1 = 0x8000 @@ -107,17 +109,21 @@ const ( HIDIOCGRAWINFO = 0x80084803 HIDIOCGRDESC = 0x90044802 HIDIOCGRDESCSIZE = 0x80044801 + HIDIOCREVOKE = 0x4004480d HUPCL = 0x400 ICANON = 0x2 IEXTEN = 0x8000 IN_CLOEXEC = 0x80000 IN_NONBLOCK = 0x800 IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x7b9 + IPV6_FLOWINFO_MASK = 0xffffff0f + IPV6_FLOWLABEL_MASK = 0xffff0f00 ISIG = 0x1 IUCLC = 0x200 IXOFF = 0x1000 IXON = 0x400 MAP_32BIT = 0x40 + MAP_ABOVE4G = 0x80 MAP_ANON = 0x20 MAP_ANONYMOUS = 0x20 MAP_DENYWRITE = 0x800 @@ -150,9 +156,14 @@ const ( NFDBITS = 0x40 NLDLY = 0x100 NOFLSH = 0x80 + NS_GET_MNTNS_ID = 0x8008b705 NS_GET_NSTYPE = 0xb703 NS_GET_OWNER_UID = 0xb704 NS_GET_PARENT = 0xb702 + NS_GET_PID_FROM_PIDNS = 0x8004b706 + NS_GET_PID_IN_PIDNS = 0x8004b708 + NS_GET_TGID_FROM_PIDNS = 0x8004b707 + NS_GET_TGID_IN_PIDNS = 0x8004b709 NS_GET_USERNS = 0xb701 OLCUC = 0x2 ONLCR = 0x4 @@ -229,6 +240,20 @@ const ( PPPIOCUNBRIDGECHAN = 0x7434 PPPIOCXFERUNIT = 0x744e PR_SET_PTRACER_ANY = 0xffffffffffffffff + PTP_CLOCK_GETCAPS = 0x80503d01 + PTP_CLOCK_GETCAPS2 = 0x80503d0a + PTP_ENABLE_PPS = 0x40043d04 + PTP_ENABLE_PPS2 = 0x40043d0d + PTP_EXTTS_REQUEST = 0x40103d02 + PTP_EXTTS_REQUEST2 = 0x40103d0b + PTP_MASK_CLEAR_ALL = 0x3d13 + PTP_MASK_EN_SINGLE = 0x40043d14 + PTP_PEROUT_REQUEST = 0x40383d03 + PTP_PEROUT_REQUEST2 = 0x40383d0c + PTP_PIN_SETFUNC = 0x40603d07 + PTP_PIN_SETFUNC2 = 0x40603d10 + PTP_SYS_OFFSET = 0x43403d05 + PTP_SYS_OFFSET2 = 0x43403d0e PTRACE_ARCH_PRCTL = 0x1e PTRACE_GETFPREGS = 0xe PTRACE_GETFPXREGS = 0x12 @@ -276,10 +301,13 @@ const ( RTC_WIE_ON = 0x700f RTC_WKALM_RD = 0x80287010 RTC_WKALM_SET = 0x4028700f + SCM_DEVMEM_DMABUF = 0x4f + SCM_DEVMEM_LINEAR = 0x4e SCM_TIMESTAMPING = 0x25 SCM_TIMESTAMPING_OPT_STATS = 0x36 SCM_TIMESTAMPING_PKTINFO = 0x3a SCM_TIMESTAMPNS = 0x23 + SCM_TS_OPT_ID = 0x51 SCM_TXTIME = 0x3d SCM_WIFI_STATUS = 0x29 SECCOMP_IOCTL_NOTIF_ADDFD = 0x40182103 @@ -314,6 +342,9 @@ const ( SO_CNX_ADVICE = 0x35 SO_COOKIE = 0x39 SO_DETACH_REUSEPORT_BPF = 0x44 + SO_DEVMEM_DMABUF = 0x4f + SO_DEVMEM_DONTNEED = 0x50 + SO_DEVMEM_LINEAR = 0x4e SO_DOMAIN = 0x27 SO_DONTROUTE = 0x5 SO_ERROR = 0x4 diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go index 5cca668ac..a8c607ab8 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go @@ -78,6 +78,8 @@ const ( ECHOPRT = 0x400 EFD_CLOEXEC = 0x80000 EFD_NONBLOCK = 0x800 + EPIOCGPARAMS = 0x80088a02 + EPIOCSPARAMS = 0x40088a01 EPOLL_CLOEXEC = 0x80000 EXTPROC = 0x10000 FF1 = 0x8000 @@ -106,12 +108,15 @@ const ( HIDIOCGRAWINFO = 0x80084803 HIDIOCGRDESC = 0x90044802 HIDIOCGRDESCSIZE = 0x80044801 + HIDIOCREVOKE = 0x4004480d HUPCL = 0x400 ICANON = 0x2 IEXTEN = 0x8000 IN_CLOEXEC = 0x80000 IN_NONBLOCK = 0x800 IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x7b9 + IPV6_FLOWINFO_MASK = 0xffffff0f + IPV6_FLOWLABEL_MASK = 0xffff0f00 ISIG = 0x1 IUCLC = 0x200 IXOFF = 0x1000 @@ -148,9 +153,14 @@ const ( NFDBITS = 0x20 NLDLY = 0x100 NOFLSH = 0x80 + NS_GET_MNTNS_ID = 0x8008b705 NS_GET_NSTYPE = 0xb703 NS_GET_OWNER_UID = 0xb704 NS_GET_PARENT = 0xb702 + NS_GET_PID_FROM_PIDNS = 0x8004b706 + NS_GET_PID_IN_PIDNS = 0x8004b708 + NS_GET_TGID_FROM_PIDNS = 0x8004b707 + NS_GET_TGID_IN_PIDNS = 0x8004b709 NS_GET_USERNS = 0xb701 OLCUC = 0x2 ONLCR = 0x4 @@ -227,6 +237,20 @@ const ( PPPIOCUNBRIDGECHAN = 0x7434 PPPIOCXFERUNIT = 0x744e PR_SET_PTRACER_ANY = 0xffffffff + PTP_CLOCK_GETCAPS = 0x80503d01 + PTP_CLOCK_GETCAPS2 = 0x80503d0a + PTP_ENABLE_PPS = 0x40043d04 + PTP_ENABLE_PPS2 = 0x40043d0d + PTP_EXTTS_REQUEST = 0x40103d02 + PTP_EXTTS_REQUEST2 = 0x40103d0b + PTP_MASK_CLEAR_ALL = 0x3d13 + PTP_MASK_EN_SINGLE = 0x40043d14 + PTP_PEROUT_REQUEST = 0x40383d03 + PTP_PEROUT_REQUEST2 = 0x40383d0c + PTP_PIN_SETFUNC = 0x40603d07 + PTP_PIN_SETFUNC2 = 0x40603d10 + PTP_SYS_OFFSET = 0x43403d05 + PTP_SYS_OFFSET2 = 0x43403d0e PTRACE_GETCRUNCHREGS = 0x19 PTRACE_GETFDPIC = 0x1f PTRACE_GETFDPIC_EXEC = 0x0 @@ -282,10 +306,13 @@ const ( RTC_WIE_ON = 0x700f RTC_WKALM_RD = 0x80287010 RTC_WKALM_SET = 0x4028700f + SCM_DEVMEM_DMABUF = 0x4f + SCM_DEVMEM_LINEAR = 0x4e SCM_TIMESTAMPING = 0x25 SCM_TIMESTAMPING_OPT_STATS = 0x36 SCM_TIMESTAMPING_PKTINFO = 0x3a SCM_TIMESTAMPNS = 0x23 + SCM_TS_OPT_ID = 0x51 SCM_TXTIME = 0x3d SCM_WIFI_STATUS = 0x29 SECCOMP_IOCTL_NOTIF_ADDFD = 0x40182103 @@ -320,6 +347,9 @@ const ( SO_CNX_ADVICE = 0x35 SO_COOKIE = 0x39 SO_DETACH_REUSEPORT_BPF = 0x44 + SO_DEVMEM_DMABUF = 0x4f + SO_DEVMEM_DONTNEED = 0x50 + SO_DEVMEM_LINEAR = 0x4e SO_DOMAIN = 0x27 SO_DONTROUTE = 0x5 SO_ERROR = 0x4 diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go index d8cae6d15..18563dd8d 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go @@ -78,6 +78,8 @@ const ( ECHOPRT = 0x400 EFD_CLOEXEC = 0x80000 EFD_NONBLOCK = 0x800 + EPIOCGPARAMS = 0x80088a02 + EPIOCSPARAMS = 0x40088a01 EPOLL_CLOEXEC = 0x80000 ESR_MAGIC = 0x45535201 EXTPROC = 0x10000 @@ -87,6 +89,7 @@ const ( FICLONE = 0x40049409 FICLONERANGE = 0x4020940d FLUSHO = 0x1000 + FPMR_MAGIC = 0x46504d52 FPSIMD_MAGIC = 0x46508001 FS_IOC_ENABLE_VERITY = 0x40806685 FS_IOC_GETFLAGS = 0x80086601 @@ -106,15 +109,19 @@ const ( F_SETOWN = 0x8 F_UNLCK = 0x2 F_WRLCK = 0x1 + GCS_MAGIC = 0x47435300 HIDIOCGRAWINFO = 0x80084803 HIDIOCGRDESC = 0x90044802 HIDIOCGRDESCSIZE = 0x80044801 + HIDIOCREVOKE = 0x4004480d HUPCL = 0x400 ICANON = 0x2 IEXTEN = 0x8000 IN_CLOEXEC = 0x80000 IN_NONBLOCK = 0x800 IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x7b9 + IPV6_FLOWINFO_MASK = 0xffffff0f + IPV6_FLOWLABEL_MASK = 0xffff0f00 ISIG = 0x1 IUCLC = 0x200 IXOFF = 0x1000 @@ -151,9 +158,14 @@ const ( NFDBITS = 0x40 NLDLY = 0x100 NOFLSH = 0x80 + NS_GET_MNTNS_ID = 0x8008b705 NS_GET_NSTYPE = 0xb703 NS_GET_OWNER_UID = 0xb704 NS_GET_PARENT = 0xb702 + NS_GET_PID_FROM_PIDNS = 0x8004b706 + NS_GET_PID_IN_PIDNS = 0x8004b708 + NS_GET_TGID_FROM_PIDNS = 0x8004b707 + NS_GET_TGID_IN_PIDNS = 0x8004b709 NS_GET_USERNS = 0xb701 OLCUC = 0x2 ONLCR = 0x4 @@ -197,6 +209,7 @@ const ( PERF_EVENT_IOC_SET_BPF = 0x40042408 PERF_EVENT_IOC_SET_FILTER = 0x40082406 PERF_EVENT_IOC_SET_OUTPUT = 0x2405 + POE_MAGIC = 0x504f4530 PPPIOCATTACH = 0x4004743d PPPIOCATTCHAN = 0x40047438 PPPIOCBRIDGECHAN = 0x40047435 @@ -232,6 +245,20 @@ const ( PROT_BTI = 0x10 PROT_MTE = 0x20 PR_SET_PTRACER_ANY = 0xffffffffffffffff + PTP_CLOCK_GETCAPS = 0x80503d01 + PTP_CLOCK_GETCAPS2 = 0x80503d0a + PTP_ENABLE_PPS = 0x40043d04 + PTP_ENABLE_PPS2 = 0x40043d0d + PTP_EXTTS_REQUEST = 0x40103d02 + PTP_EXTTS_REQUEST2 = 0x40103d0b + PTP_MASK_CLEAR_ALL = 0x3d13 + PTP_MASK_EN_SINGLE = 0x40043d14 + PTP_PEROUT_REQUEST = 0x40383d03 + PTP_PEROUT_REQUEST2 = 0x40383d0c + PTP_PIN_SETFUNC = 0x40603d07 + PTP_PIN_SETFUNC2 = 0x40603d10 + PTP_SYS_OFFSET = 0x43403d05 + PTP_SYS_OFFSET2 = 0x43403d0e PTRACE_PEEKMTETAGS = 0x21 PTRACE_POKEMTETAGS = 0x22 PTRACE_SYSEMU = 0x1f @@ -272,10 +299,13 @@ const ( RTC_WIE_ON = 0x700f RTC_WKALM_RD = 0x80287010 RTC_WKALM_SET = 0x4028700f + SCM_DEVMEM_DMABUF = 0x4f + SCM_DEVMEM_LINEAR = 0x4e SCM_TIMESTAMPING = 0x25 SCM_TIMESTAMPING_OPT_STATS = 0x36 SCM_TIMESTAMPING_PKTINFO = 0x3a SCM_TIMESTAMPNS = 0x23 + SCM_TS_OPT_ID = 0x51 SCM_TXTIME = 0x3d SCM_WIFI_STATUS = 0x29 SECCOMP_IOCTL_NOTIF_ADDFD = 0x40182103 @@ -310,6 +340,9 @@ const ( SO_CNX_ADVICE = 0x35 SO_COOKIE = 0x39 SO_DETACH_REUSEPORT_BPF = 0x44 + SO_DEVMEM_DMABUF = 0x4f + SO_DEVMEM_DONTNEED = 0x50 + SO_DEVMEM_LINEAR = 0x4e SO_DOMAIN = 0x27 SO_DONTROUTE = 0x5 SO_ERROR = 0x4 diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zerrors_linux_loong64.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zerrors_linux_loong64.go index 28e39afdc..22912cdaa 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zerrors_linux_loong64.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zerrors_linux_loong64.go @@ -78,6 +78,8 @@ const ( ECHOPRT = 0x400 EFD_CLOEXEC = 0x80000 EFD_NONBLOCK = 0x800 + EPIOCGPARAMS = 0x80088a02 + EPIOCSPARAMS = 0x40088a01 EPOLL_CLOEXEC = 0x80000 EXTPROC = 0x10000 FF1 = 0x8000 @@ -107,12 +109,15 @@ const ( HIDIOCGRAWINFO = 0x80084803 HIDIOCGRDESC = 0x90044802 HIDIOCGRDESCSIZE = 0x80044801 + HIDIOCREVOKE = 0x4004480d HUPCL = 0x400 ICANON = 0x2 IEXTEN = 0x8000 IN_CLOEXEC = 0x80000 IN_NONBLOCK = 0x800 IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x7b9 + IPV6_FLOWINFO_MASK = 0xffffff0f + IPV6_FLOWLABEL_MASK = 0xffff0f00 ISIG = 0x1 IUCLC = 0x200 IXOFF = 0x1000 @@ -152,9 +157,14 @@ const ( NFDBITS = 0x40 NLDLY = 0x100 NOFLSH = 0x80 + NS_GET_MNTNS_ID = 0x8008b705 NS_GET_NSTYPE = 0xb703 NS_GET_OWNER_UID = 0xb704 NS_GET_PARENT = 0xb702 + NS_GET_PID_FROM_PIDNS = 0x8004b706 + NS_GET_PID_IN_PIDNS = 0x8004b708 + NS_GET_TGID_FROM_PIDNS = 0x8004b707 + NS_GET_TGID_IN_PIDNS = 0x8004b709 NS_GET_USERNS = 0xb701 OLCUC = 0x2 ONLCR = 0x4 @@ -231,6 +241,20 @@ const ( PPPIOCUNBRIDGECHAN = 0x7434 PPPIOCXFERUNIT = 0x744e PR_SET_PTRACER_ANY = 0xffffffffffffffff + PTP_CLOCK_GETCAPS = 0x80503d01 + PTP_CLOCK_GETCAPS2 = 0x80503d0a + PTP_ENABLE_PPS = 0x40043d04 + PTP_ENABLE_PPS2 = 0x40043d0d + PTP_EXTTS_REQUEST = 0x40103d02 + PTP_EXTTS_REQUEST2 = 0x40103d0b + PTP_MASK_CLEAR_ALL = 0x3d13 + PTP_MASK_EN_SINGLE = 0x40043d14 + PTP_PEROUT_REQUEST = 0x40383d03 + PTP_PEROUT_REQUEST2 = 0x40383d0c + PTP_PIN_SETFUNC = 0x40603d07 + PTP_PIN_SETFUNC2 = 0x40603d10 + PTP_SYS_OFFSET = 0x43403d05 + PTP_SYS_OFFSET2 = 0x43403d0e PTRACE_SYSEMU = 0x1f PTRACE_SYSEMU_SINGLESTEP = 0x20 RLIMIT_AS = 0x9 @@ -269,10 +293,13 @@ const ( RTC_WIE_ON = 0x700f RTC_WKALM_RD = 0x80287010 RTC_WKALM_SET = 0x4028700f + SCM_DEVMEM_DMABUF = 0x4f + SCM_DEVMEM_LINEAR = 0x4e SCM_TIMESTAMPING = 0x25 SCM_TIMESTAMPING_OPT_STATS = 0x36 SCM_TIMESTAMPING_PKTINFO = 0x3a SCM_TIMESTAMPNS = 0x23 + SCM_TS_OPT_ID = 0x51 SCM_TXTIME = 0x3d SCM_WIFI_STATUS = 0x29 SECCOMP_IOCTL_NOTIF_ADDFD = 0x40182103 @@ -307,6 +334,9 @@ const ( SO_CNX_ADVICE = 0x35 SO_COOKIE = 0x39 SO_DETACH_REUSEPORT_BPF = 0x44 + SO_DEVMEM_DMABUF = 0x4f + SO_DEVMEM_DONTNEED = 0x50 + SO_DEVMEM_LINEAR = 0x4e SO_DOMAIN = 0x27 SO_DONTROUTE = 0x5 SO_ERROR = 0x4 diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go index cd66e92cb..29344eb37 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go @@ -78,6 +78,8 @@ const ( ECHOPRT = 0x400 EFD_CLOEXEC = 0x80000 EFD_NONBLOCK = 0x80 + EPIOCGPARAMS = 0x40088a02 + EPIOCSPARAMS = 0x80088a01 EPOLL_CLOEXEC = 0x80000 EXTPROC = 0x10000 FF1 = 0x8000 @@ -106,12 +108,15 @@ const ( HIDIOCGRAWINFO = 0x40084803 HIDIOCGRDESC = 0x50044802 HIDIOCGRDESCSIZE = 0x40044801 + HIDIOCREVOKE = 0x8004480d HUPCL = 0x400 ICANON = 0x2 IEXTEN = 0x100 IN_CLOEXEC = 0x80000 IN_NONBLOCK = 0x80 IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x200007b9 + IPV6_FLOWINFO_MASK = 0xfffffff + IPV6_FLOWLABEL_MASK = 0xfffff ISIG = 0x1 IUCLC = 0x200 IXOFF = 0x1000 @@ -148,9 +153,14 @@ const ( NFDBITS = 0x20 NLDLY = 0x100 NOFLSH = 0x80 + NS_GET_MNTNS_ID = 0x4008b705 NS_GET_NSTYPE = 0x2000b703 NS_GET_OWNER_UID = 0x2000b704 NS_GET_PARENT = 0x2000b702 + NS_GET_PID_FROM_PIDNS = 0x4004b706 + NS_GET_PID_IN_PIDNS = 0x4004b708 + NS_GET_TGID_FROM_PIDNS = 0x4004b707 + NS_GET_TGID_IN_PIDNS = 0x4004b709 NS_GET_USERNS = 0x2000b701 OLCUC = 0x2 ONLCR = 0x4 @@ -227,6 +237,20 @@ const ( PPPIOCUNBRIDGECHAN = 0x20007434 PPPIOCXFERUNIT = 0x2000744e PR_SET_PTRACER_ANY = 0xffffffff + PTP_CLOCK_GETCAPS = 0x40503d01 + PTP_CLOCK_GETCAPS2 = 0x40503d0a + PTP_ENABLE_PPS = 0x80043d04 + PTP_ENABLE_PPS2 = 0x80043d0d + PTP_EXTTS_REQUEST = 0x80103d02 + PTP_EXTTS_REQUEST2 = 0x80103d0b + PTP_MASK_CLEAR_ALL = 0x20003d13 + PTP_MASK_EN_SINGLE = 0x80043d14 + PTP_PEROUT_REQUEST = 0x80383d03 + PTP_PEROUT_REQUEST2 = 0x80383d0c + PTP_PIN_SETFUNC = 0x80603d07 + PTP_PIN_SETFUNC2 = 0x80603d10 + PTP_SYS_OFFSET = 0x83403d05 + PTP_SYS_OFFSET2 = 0x83403d0e PTRACE_GETFPREGS = 0xe PTRACE_GET_THREAD_AREA = 0x19 PTRACE_GET_THREAD_AREA_3264 = 0xc4 @@ -275,10 +299,13 @@ const ( RTC_WIE_ON = 0x2000700f RTC_WKALM_RD = 0x40287010 RTC_WKALM_SET = 0x8028700f + SCM_DEVMEM_DMABUF = 0x4f + SCM_DEVMEM_LINEAR = 0x4e SCM_TIMESTAMPING = 0x25 SCM_TIMESTAMPING_OPT_STATS = 0x36 SCM_TIMESTAMPING_PKTINFO = 0x3a SCM_TIMESTAMPNS = 0x23 + SCM_TS_OPT_ID = 0x51 SCM_TXTIME = 0x3d SCM_WIFI_STATUS = 0x29 SECCOMP_IOCTL_NOTIF_ADDFD = 0x80182103 @@ -313,6 +340,9 @@ const ( SO_CNX_ADVICE = 0x35 SO_COOKIE = 0x39 SO_DETACH_REUSEPORT_BPF = 0x44 + SO_DEVMEM_DMABUF = 0x4f + SO_DEVMEM_DONTNEED = 0x50 + SO_DEVMEM_LINEAR = 0x4e SO_DOMAIN = 0x1029 SO_DONTROUTE = 0x10 SO_ERROR = 0x1007 diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go index c1595eba7..20d51fb96 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go @@ -78,6 +78,8 @@ const ( ECHOPRT = 0x400 EFD_CLOEXEC = 0x80000 EFD_NONBLOCK = 0x80 + EPIOCGPARAMS = 0x40088a02 + EPIOCSPARAMS = 0x80088a01 EPOLL_CLOEXEC = 0x80000 EXTPROC = 0x10000 FF1 = 0x8000 @@ -106,12 +108,15 @@ const ( HIDIOCGRAWINFO = 0x40084803 HIDIOCGRDESC = 0x50044802 HIDIOCGRDESCSIZE = 0x40044801 + HIDIOCREVOKE = 0x8004480d HUPCL = 0x400 ICANON = 0x2 IEXTEN = 0x100 IN_CLOEXEC = 0x80000 IN_NONBLOCK = 0x80 IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x200007b9 + IPV6_FLOWINFO_MASK = 0xfffffff + IPV6_FLOWLABEL_MASK = 0xfffff ISIG = 0x1 IUCLC = 0x200 IXOFF = 0x1000 @@ -148,9 +153,14 @@ const ( NFDBITS = 0x40 NLDLY = 0x100 NOFLSH = 0x80 + NS_GET_MNTNS_ID = 0x4008b705 NS_GET_NSTYPE = 0x2000b703 NS_GET_OWNER_UID = 0x2000b704 NS_GET_PARENT = 0x2000b702 + NS_GET_PID_FROM_PIDNS = 0x4004b706 + NS_GET_PID_IN_PIDNS = 0x4004b708 + NS_GET_TGID_FROM_PIDNS = 0x4004b707 + NS_GET_TGID_IN_PIDNS = 0x4004b709 NS_GET_USERNS = 0x2000b701 OLCUC = 0x2 ONLCR = 0x4 @@ -227,6 +237,20 @@ const ( PPPIOCUNBRIDGECHAN = 0x20007434 PPPIOCXFERUNIT = 0x2000744e PR_SET_PTRACER_ANY = 0xffffffffffffffff + PTP_CLOCK_GETCAPS = 0x40503d01 + PTP_CLOCK_GETCAPS2 = 0x40503d0a + PTP_ENABLE_PPS = 0x80043d04 + PTP_ENABLE_PPS2 = 0x80043d0d + PTP_EXTTS_REQUEST = 0x80103d02 + PTP_EXTTS_REQUEST2 = 0x80103d0b + PTP_MASK_CLEAR_ALL = 0x20003d13 + PTP_MASK_EN_SINGLE = 0x80043d14 + PTP_PEROUT_REQUEST = 0x80383d03 + PTP_PEROUT_REQUEST2 = 0x80383d0c + PTP_PIN_SETFUNC = 0x80603d07 + PTP_PIN_SETFUNC2 = 0x80603d10 + PTP_SYS_OFFSET = 0x83403d05 + PTP_SYS_OFFSET2 = 0x83403d0e PTRACE_GETFPREGS = 0xe PTRACE_GET_THREAD_AREA = 0x19 PTRACE_GET_THREAD_AREA_3264 = 0xc4 @@ -275,10 +299,13 @@ const ( RTC_WIE_ON = 0x2000700f RTC_WKALM_RD = 0x40287010 RTC_WKALM_SET = 0x8028700f + SCM_DEVMEM_DMABUF = 0x4f + SCM_DEVMEM_LINEAR = 0x4e SCM_TIMESTAMPING = 0x25 SCM_TIMESTAMPING_OPT_STATS = 0x36 SCM_TIMESTAMPING_PKTINFO = 0x3a SCM_TIMESTAMPNS = 0x23 + SCM_TS_OPT_ID = 0x51 SCM_TXTIME = 0x3d SCM_WIFI_STATUS = 0x29 SECCOMP_IOCTL_NOTIF_ADDFD = 0x80182103 @@ -313,6 +340,9 @@ const ( SO_CNX_ADVICE = 0x35 SO_COOKIE = 0x39 SO_DETACH_REUSEPORT_BPF = 0x44 + SO_DEVMEM_DMABUF = 0x4f + SO_DEVMEM_DONTNEED = 0x50 + SO_DEVMEM_LINEAR = 0x4e SO_DOMAIN = 0x1029 SO_DONTROUTE = 0x10 SO_ERROR = 0x1007 diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go index ee9456b0d..321b60902 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go @@ -78,6 +78,8 @@ const ( ECHOPRT = 0x400 EFD_CLOEXEC = 0x80000 EFD_NONBLOCK = 0x80 + EPIOCGPARAMS = 0x40088a02 + EPIOCSPARAMS = 0x80088a01 EPOLL_CLOEXEC = 0x80000 EXTPROC = 0x10000 FF1 = 0x8000 @@ -106,12 +108,15 @@ const ( HIDIOCGRAWINFO = 0x40084803 HIDIOCGRDESC = 0x50044802 HIDIOCGRDESCSIZE = 0x40044801 + HIDIOCREVOKE = 0x8004480d HUPCL = 0x400 ICANON = 0x2 IEXTEN = 0x100 IN_CLOEXEC = 0x80000 IN_NONBLOCK = 0x80 IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x200007b9 + IPV6_FLOWINFO_MASK = 0xffffff0f + IPV6_FLOWLABEL_MASK = 0xffff0f00 ISIG = 0x1 IUCLC = 0x200 IXOFF = 0x1000 @@ -148,9 +153,14 @@ const ( NFDBITS = 0x40 NLDLY = 0x100 NOFLSH = 0x80 + NS_GET_MNTNS_ID = 0x4008b705 NS_GET_NSTYPE = 0x2000b703 NS_GET_OWNER_UID = 0x2000b704 NS_GET_PARENT = 0x2000b702 + NS_GET_PID_FROM_PIDNS = 0x4004b706 + NS_GET_PID_IN_PIDNS = 0x4004b708 + NS_GET_TGID_FROM_PIDNS = 0x4004b707 + NS_GET_TGID_IN_PIDNS = 0x4004b709 NS_GET_USERNS = 0x2000b701 OLCUC = 0x2 ONLCR = 0x4 @@ -227,6 +237,20 @@ const ( PPPIOCUNBRIDGECHAN = 0x20007434 PPPIOCXFERUNIT = 0x2000744e PR_SET_PTRACER_ANY = 0xffffffffffffffff + PTP_CLOCK_GETCAPS = 0x40503d01 + PTP_CLOCK_GETCAPS2 = 0x40503d0a + PTP_ENABLE_PPS = 0x80043d04 + PTP_ENABLE_PPS2 = 0x80043d0d + PTP_EXTTS_REQUEST = 0x80103d02 + PTP_EXTTS_REQUEST2 = 0x80103d0b + PTP_MASK_CLEAR_ALL = 0x20003d13 + PTP_MASK_EN_SINGLE = 0x80043d14 + PTP_PEROUT_REQUEST = 0x80383d03 + PTP_PEROUT_REQUEST2 = 0x80383d0c + PTP_PIN_SETFUNC = 0x80603d07 + PTP_PIN_SETFUNC2 = 0x80603d10 + PTP_SYS_OFFSET = 0x83403d05 + PTP_SYS_OFFSET2 = 0x83403d0e PTRACE_GETFPREGS = 0xe PTRACE_GET_THREAD_AREA = 0x19 PTRACE_GET_THREAD_AREA_3264 = 0xc4 @@ -275,10 +299,13 @@ const ( RTC_WIE_ON = 0x2000700f RTC_WKALM_RD = 0x40287010 RTC_WKALM_SET = 0x8028700f + SCM_DEVMEM_DMABUF = 0x4f + SCM_DEVMEM_LINEAR = 0x4e SCM_TIMESTAMPING = 0x25 SCM_TIMESTAMPING_OPT_STATS = 0x36 SCM_TIMESTAMPING_PKTINFO = 0x3a SCM_TIMESTAMPNS = 0x23 + SCM_TS_OPT_ID = 0x51 SCM_TXTIME = 0x3d SCM_WIFI_STATUS = 0x29 SECCOMP_IOCTL_NOTIF_ADDFD = 0x80182103 @@ -313,6 +340,9 @@ const ( SO_CNX_ADVICE = 0x35 SO_COOKIE = 0x39 SO_DETACH_REUSEPORT_BPF = 0x44 + SO_DEVMEM_DMABUF = 0x4f + SO_DEVMEM_DONTNEED = 0x50 + SO_DEVMEM_LINEAR = 0x4e SO_DOMAIN = 0x1029 SO_DONTROUTE = 0x10 SO_ERROR = 0x1007 diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go index 8cfca81e1..9bacdf1e2 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go @@ -78,6 +78,8 @@ const ( ECHOPRT = 0x400 EFD_CLOEXEC = 0x80000 EFD_NONBLOCK = 0x80 + EPIOCGPARAMS = 0x40088a02 + EPIOCSPARAMS = 0x80088a01 EPOLL_CLOEXEC = 0x80000 EXTPROC = 0x10000 FF1 = 0x8000 @@ -106,12 +108,15 @@ const ( HIDIOCGRAWINFO = 0x40084803 HIDIOCGRDESC = 0x50044802 HIDIOCGRDESCSIZE = 0x40044801 + HIDIOCREVOKE = 0x8004480d HUPCL = 0x400 ICANON = 0x2 IEXTEN = 0x100 IN_CLOEXEC = 0x80000 IN_NONBLOCK = 0x80 IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x200007b9 + IPV6_FLOWINFO_MASK = 0xffffff0f + IPV6_FLOWLABEL_MASK = 0xffff0f00 ISIG = 0x1 IUCLC = 0x200 IXOFF = 0x1000 @@ -148,9 +153,14 @@ const ( NFDBITS = 0x20 NLDLY = 0x100 NOFLSH = 0x80 + NS_GET_MNTNS_ID = 0x4008b705 NS_GET_NSTYPE = 0x2000b703 NS_GET_OWNER_UID = 0x2000b704 NS_GET_PARENT = 0x2000b702 + NS_GET_PID_FROM_PIDNS = 0x4004b706 + NS_GET_PID_IN_PIDNS = 0x4004b708 + NS_GET_TGID_FROM_PIDNS = 0x4004b707 + NS_GET_TGID_IN_PIDNS = 0x4004b709 NS_GET_USERNS = 0x2000b701 OLCUC = 0x2 ONLCR = 0x4 @@ -227,6 +237,20 @@ const ( PPPIOCUNBRIDGECHAN = 0x20007434 PPPIOCXFERUNIT = 0x2000744e PR_SET_PTRACER_ANY = 0xffffffff + PTP_CLOCK_GETCAPS = 0x40503d01 + PTP_CLOCK_GETCAPS2 = 0x40503d0a + PTP_ENABLE_PPS = 0x80043d04 + PTP_ENABLE_PPS2 = 0x80043d0d + PTP_EXTTS_REQUEST = 0x80103d02 + PTP_EXTTS_REQUEST2 = 0x80103d0b + PTP_MASK_CLEAR_ALL = 0x20003d13 + PTP_MASK_EN_SINGLE = 0x80043d14 + PTP_PEROUT_REQUEST = 0x80383d03 + PTP_PEROUT_REQUEST2 = 0x80383d0c + PTP_PIN_SETFUNC = 0x80603d07 + PTP_PIN_SETFUNC2 = 0x80603d10 + PTP_SYS_OFFSET = 0x83403d05 + PTP_SYS_OFFSET2 = 0x83403d0e PTRACE_GETFPREGS = 0xe PTRACE_GET_THREAD_AREA = 0x19 PTRACE_GET_THREAD_AREA_3264 = 0xc4 @@ -275,10 +299,13 @@ const ( RTC_WIE_ON = 0x2000700f RTC_WKALM_RD = 0x40287010 RTC_WKALM_SET = 0x8028700f + SCM_DEVMEM_DMABUF = 0x4f + SCM_DEVMEM_LINEAR = 0x4e SCM_TIMESTAMPING = 0x25 SCM_TIMESTAMPING_OPT_STATS = 0x36 SCM_TIMESTAMPING_PKTINFO = 0x3a SCM_TIMESTAMPNS = 0x23 + SCM_TS_OPT_ID = 0x51 SCM_TXTIME = 0x3d SCM_WIFI_STATUS = 0x29 SECCOMP_IOCTL_NOTIF_ADDFD = 0x80182103 @@ -313,6 +340,9 @@ const ( SO_CNX_ADVICE = 0x35 SO_COOKIE = 0x39 SO_DETACH_REUSEPORT_BPF = 0x44 + SO_DEVMEM_DMABUF = 0x4f + SO_DEVMEM_DONTNEED = 0x50 + SO_DEVMEM_LINEAR = 0x4e SO_DOMAIN = 0x1029 SO_DONTROUTE = 0x10 SO_ERROR = 0x1007 diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go index 60b0deb3a..c22427261 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go @@ -78,6 +78,8 @@ const ( ECHOPRT = 0x20 EFD_CLOEXEC = 0x80000 EFD_NONBLOCK = 0x800 + EPIOCGPARAMS = 0x40088a02 + EPIOCSPARAMS = 0x80088a01 EPOLL_CLOEXEC = 0x80000 EXTPROC = 0x10000000 FF1 = 0x4000 @@ -106,12 +108,15 @@ const ( HIDIOCGRAWINFO = 0x40084803 HIDIOCGRDESC = 0x50044802 HIDIOCGRDESCSIZE = 0x40044801 + HIDIOCREVOKE = 0x8004480d HUPCL = 0x4000 ICANON = 0x100 IEXTEN = 0x400 IN_CLOEXEC = 0x80000 IN_NONBLOCK = 0x800 IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x200007b9 + IPV6_FLOWINFO_MASK = 0xfffffff + IPV6_FLOWLABEL_MASK = 0xfffff ISIG = 0x80 IUCLC = 0x1000 IXOFF = 0x400 @@ -150,9 +155,14 @@ const ( NL3 = 0x300 NLDLY = 0x300 NOFLSH = 0x80000000 + NS_GET_MNTNS_ID = 0x4008b705 NS_GET_NSTYPE = 0x2000b703 NS_GET_OWNER_UID = 0x2000b704 NS_GET_PARENT = 0x2000b702 + NS_GET_PID_FROM_PIDNS = 0x4004b706 + NS_GET_PID_IN_PIDNS = 0x4004b708 + NS_GET_TGID_FROM_PIDNS = 0x4004b707 + NS_GET_TGID_IN_PIDNS = 0x4004b709 NS_GET_USERNS = 0x2000b701 OLCUC = 0x4 ONLCR = 0x2 @@ -230,6 +240,20 @@ const ( PPPIOCXFERUNIT = 0x2000744e PROT_SAO = 0x10 PR_SET_PTRACER_ANY = 0xffffffff + PTP_CLOCK_GETCAPS = 0x40503d01 + PTP_CLOCK_GETCAPS2 = 0x40503d0a + PTP_ENABLE_PPS = 0x80043d04 + PTP_ENABLE_PPS2 = 0x80043d0d + PTP_EXTTS_REQUEST = 0x80103d02 + PTP_EXTTS_REQUEST2 = 0x80103d0b + PTP_MASK_CLEAR_ALL = 0x20003d13 + PTP_MASK_EN_SINGLE = 0x80043d14 + PTP_PEROUT_REQUEST = 0x80383d03 + PTP_PEROUT_REQUEST2 = 0x80383d0c + PTP_PIN_SETFUNC = 0x80603d07 + PTP_PIN_SETFUNC2 = 0x80603d10 + PTP_SYS_OFFSET = 0x83403d05 + PTP_SYS_OFFSET2 = 0x83403d0e PTRACE_GETEVRREGS = 0x14 PTRACE_GETFPREGS = 0xe PTRACE_GETREGS64 = 0x16 @@ -330,10 +354,13 @@ const ( RTC_WIE_ON = 0x2000700f RTC_WKALM_RD = 0x40287010 RTC_WKALM_SET = 0x8028700f + SCM_DEVMEM_DMABUF = 0x4f + SCM_DEVMEM_LINEAR = 0x4e SCM_TIMESTAMPING = 0x25 SCM_TIMESTAMPING_OPT_STATS = 0x36 SCM_TIMESTAMPING_PKTINFO = 0x3a SCM_TIMESTAMPNS = 0x23 + SCM_TS_OPT_ID = 0x51 SCM_TXTIME = 0x3d SCM_WIFI_STATUS = 0x29 SECCOMP_IOCTL_NOTIF_ADDFD = 0x80182103 @@ -368,6 +395,9 @@ const ( SO_CNX_ADVICE = 0x35 SO_COOKIE = 0x39 SO_DETACH_REUSEPORT_BPF = 0x44 + SO_DEVMEM_DMABUF = 0x4f + SO_DEVMEM_DONTNEED = 0x50 + SO_DEVMEM_LINEAR = 0x4e SO_DOMAIN = 0x27 SO_DONTROUTE = 0x5 SO_ERROR = 0x4 diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go index f90aa7281..6270c8ee1 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go @@ -78,6 +78,8 @@ const ( ECHOPRT = 0x20 EFD_CLOEXEC = 0x80000 EFD_NONBLOCK = 0x800 + EPIOCGPARAMS = 0x40088a02 + EPIOCSPARAMS = 0x80088a01 EPOLL_CLOEXEC = 0x80000 EXTPROC = 0x10000000 FF1 = 0x4000 @@ -106,12 +108,15 @@ const ( HIDIOCGRAWINFO = 0x40084803 HIDIOCGRDESC = 0x50044802 HIDIOCGRDESCSIZE = 0x40044801 + HIDIOCREVOKE = 0x8004480d HUPCL = 0x4000 ICANON = 0x100 IEXTEN = 0x400 IN_CLOEXEC = 0x80000 IN_NONBLOCK = 0x800 IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x200007b9 + IPV6_FLOWINFO_MASK = 0xfffffff + IPV6_FLOWLABEL_MASK = 0xfffff ISIG = 0x80 IUCLC = 0x1000 IXOFF = 0x400 @@ -150,9 +155,14 @@ const ( NL3 = 0x300 NLDLY = 0x300 NOFLSH = 0x80000000 + NS_GET_MNTNS_ID = 0x4008b705 NS_GET_NSTYPE = 0x2000b703 NS_GET_OWNER_UID = 0x2000b704 NS_GET_PARENT = 0x2000b702 + NS_GET_PID_FROM_PIDNS = 0x4004b706 + NS_GET_PID_IN_PIDNS = 0x4004b708 + NS_GET_TGID_FROM_PIDNS = 0x4004b707 + NS_GET_TGID_IN_PIDNS = 0x4004b709 NS_GET_USERNS = 0x2000b701 OLCUC = 0x4 ONLCR = 0x2 @@ -230,6 +240,20 @@ const ( PPPIOCXFERUNIT = 0x2000744e PROT_SAO = 0x10 PR_SET_PTRACER_ANY = 0xffffffffffffffff + PTP_CLOCK_GETCAPS = 0x40503d01 + PTP_CLOCK_GETCAPS2 = 0x40503d0a + PTP_ENABLE_PPS = 0x80043d04 + PTP_ENABLE_PPS2 = 0x80043d0d + PTP_EXTTS_REQUEST = 0x80103d02 + PTP_EXTTS_REQUEST2 = 0x80103d0b + PTP_MASK_CLEAR_ALL = 0x20003d13 + PTP_MASK_EN_SINGLE = 0x80043d14 + PTP_PEROUT_REQUEST = 0x80383d03 + PTP_PEROUT_REQUEST2 = 0x80383d0c + PTP_PIN_SETFUNC = 0x80603d07 + PTP_PIN_SETFUNC2 = 0x80603d10 + PTP_SYS_OFFSET = 0x83403d05 + PTP_SYS_OFFSET2 = 0x83403d0e PTRACE_GETEVRREGS = 0x14 PTRACE_GETFPREGS = 0xe PTRACE_GETREGS64 = 0x16 @@ -334,10 +358,13 @@ const ( RTC_WIE_ON = 0x2000700f RTC_WKALM_RD = 0x40287010 RTC_WKALM_SET = 0x8028700f + SCM_DEVMEM_DMABUF = 0x4f + SCM_DEVMEM_LINEAR = 0x4e SCM_TIMESTAMPING = 0x25 SCM_TIMESTAMPING_OPT_STATS = 0x36 SCM_TIMESTAMPING_PKTINFO = 0x3a SCM_TIMESTAMPNS = 0x23 + SCM_TS_OPT_ID = 0x51 SCM_TXTIME = 0x3d SCM_WIFI_STATUS = 0x29 SECCOMP_IOCTL_NOTIF_ADDFD = 0x80182103 @@ -372,6 +399,9 @@ const ( SO_CNX_ADVICE = 0x35 SO_COOKIE = 0x39 SO_DETACH_REUSEPORT_BPF = 0x44 + SO_DEVMEM_DMABUF = 0x4f + SO_DEVMEM_DONTNEED = 0x50 + SO_DEVMEM_LINEAR = 0x4e SO_DOMAIN = 0x27 SO_DONTROUTE = 0x5 SO_ERROR = 0x4 diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go index ba9e01503..9966c1941 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go @@ -78,6 +78,8 @@ const ( ECHOPRT = 0x20 EFD_CLOEXEC = 0x80000 EFD_NONBLOCK = 0x800 + EPIOCGPARAMS = 0x40088a02 + EPIOCSPARAMS = 0x80088a01 EPOLL_CLOEXEC = 0x80000 EXTPROC = 0x10000000 FF1 = 0x4000 @@ -106,12 +108,15 @@ const ( HIDIOCGRAWINFO = 0x40084803 HIDIOCGRDESC = 0x50044802 HIDIOCGRDESCSIZE = 0x40044801 + HIDIOCREVOKE = 0x8004480d HUPCL = 0x4000 ICANON = 0x100 IEXTEN = 0x400 IN_CLOEXEC = 0x80000 IN_NONBLOCK = 0x800 IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x200007b9 + IPV6_FLOWINFO_MASK = 0xffffff0f + IPV6_FLOWLABEL_MASK = 0xffff0f00 ISIG = 0x80 IUCLC = 0x1000 IXOFF = 0x400 @@ -150,9 +155,14 @@ const ( NL3 = 0x300 NLDLY = 0x300 NOFLSH = 0x80000000 + NS_GET_MNTNS_ID = 0x4008b705 NS_GET_NSTYPE = 0x2000b703 NS_GET_OWNER_UID = 0x2000b704 NS_GET_PARENT = 0x2000b702 + NS_GET_PID_FROM_PIDNS = 0x4004b706 + NS_GET_PID_IN_PIDNS = 0x4004b708 + NS_GET_TGID_FROM_PIDNS = 0x4004b707 + NS_GET_TGID_IN_PIDNS = 0x4004b709 NS_GET_USERNS = 0x2000b701 OLCUC = 0x4 ONLCR = 0x2 @@ -230,6 +240,20 @@ const ( PPPIOCXFERUNIT = 0x2000744e PROT_SAO = 0x10 PR_SET_PTRACER_ANY = 0xffffffffffffffff + PTP_CLOCK_GETCAPS = 0x40503d01 + PTP_CLOCK_GETCAPS2 = 0x40503d0a + PTP_ENABLE_PPS = 0x80043d04 + PTP_ENABLE_PPS2 = 0x80043d0d + PTP_EXTTS_REQUEST = 0x80103d02 + PTP_EXTTS_REQUEST2 = 0x80103d0b + PTP_MASK_CLEAR_ALL = 0x20003d13 + PTP_MASK_EN_SINGLE = 0x80043d14 + PTP_PEROUT_REQUEST = 0x80383d03 + PTP_PEROUT_REQUEST2 = 0x80383d0c + PTP_PIN_SETFUNC = 0x80603d07 + PTP_PIN_SETFUNC2 = 0x80603d10 + PTP_SYS_OFFSET = 0x83403d05 + PTP_SYS_OFFSET2 = 0x83403d0e PTRACE_GETEVRREGS = 0x14 PTRACE_GETFPREGS = 0xe PTRACE_GETREGS64 = 0x16 @@ -334,10 +358,13 @@ const ( RTC_WIE_ON = 0x2000700f RTC_WKALM_RD = 0x40287010 RTC_WKALM_SET = 0x8028700f + SCM_DEVMEM_DMABUF = 0x4f + SCM_DEVMEM_LINEAR = 0x4e SCM_TIMESTAMPING = 0x25 SCM_TIMESTAMPING_OPT_STATS = 0x36 SCM_TIMESTAMPING_PKTINFO = 0x3a SCM_TIMESTAMPNS = 0x23 + SCM_TS_OPT_ID = 0x51 SCM_TXTIME = 0x3d SCM_WIFI_STATUS = 0x29 SECCOMP_IOCTL_NOTIF_ADDFD = 0x80182103 @@ -372,6 +399,9 @@ const ( SO_CNX_ADVICE = 0x35 SO_COOKIE = 0x39 SO_DETACH_REUSEPORT_BPF = 0x44 + SO_DEVMEM_DMABUF = 0x4f + SO_DEVMEM_DONTNEED = 0x50 + SO_DEVMEM_LINEAR = 0x4e SO_DOMAIN = 0x27 SO_DONTROUTE = 0x5 SO_ERROR = 0x4 diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go index 07cdfd6e9..848e5fcc4 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go @@ -78,6 +78,8 @@ const ( ECHOPRT = 0x400 EFD_CLOEXEC = 0x80000 EFD_NONBLOCK = 0x800 + EPIOCGPARAMS = 0x80088a02 + EPIOCSPARAMS = 0x40088a01 EPOLL_CLOEXEC = 0x80000 EXTPROC = 0x10000 FF1 = 0x8000 @@ -106,12 +108,15 @@ const ( HIDIOCGRAWINFO = 0x80084803 HIDIOCGRDESC = 0x90044802 HIDIOCGRDESCSIZE = 0x80044801 + HIDIOCREVOKE = 0x4004480d HUPCL = 0x400 ICANON = 0x2 IEXTEN = 0x8000 IN_CLOEXEC = 0x80000 IN_NONBLOCK = 0x800 IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x7b9 + IPV6_FLOWINFO_MASK = 0xffffff0f + IPV6_FLOWLABEL_MASK = 0xffff0f00 ISIG = 0x1 IUCLC = 0x200 IXOFF = 0x1000 @@ -148,9 +153,14 @@ const ( NFDBITS = 0x40 NLDLY = 0x100 NOFLSH = 0x80 + NS_GET_MNTNS_ID = 0x8008b705 NS_GET_NSTYPE = 0xb703 NS_GET_OWNER_UID = 0xb704 NS_GET_PARENT = 0xb702 + NS_GET_PID_FROM_PIDNS = 0x8004b706 + NS_GET_PID_IN_PIDNS = 0x8004b708 + NS_GET_TGID_FROM_PIDNS = 0x8004b707 + NS_GET_TGID_IN_PIDNS = 0x8004b709 NS_GET_USERNS = 0xb701 OLCUC = 0x2 ONLCR = 0x4 @@ -227,6 +237,20 @@ const ( PPPIOCUNBRIDGECHAN = 0x7434 PPPIOCXFERUNIT = 0x744e PR_SET_PTRACER_ANY = 0xffffffffffffffff + PTP_CLOCK_GETCAPS = 0x80503d01 + PTP_CLOCK_GETCAPS2 = 0x80503d0a + PTP_ENABLE_PPS = 0x40043d04 + PTP_ENABLE_PPS2 = 0x40043d0d + PTP_EXTTS_REQUEST = 0x40103d02 + PTP_EXTTS_REQUEST2 = 0x40103d0b + PTP_MASK_CLEAR_ALL = 0x3d13 + PTP_MASK_EN_SINGLE = 0x40043d14 + PTP_PEROUT_REQUEST = 0x40383d03 + PTP_PEROUT_REQUEST2 = 0x40383d0c + PTP_PIN_SETFUNC = 0x40603d07 + PTP_PIN_SETFUNC2 = 0x40603d10 + PTP_SYS_OFFSET = 0x43403d05 + PTP_SYS_OFFSET2 = 0x43403d0e PTRACE_GETFDPIC = 0x21 PTRACE_GETFDPIC_EXEC = 0x0 PTRACE_GETFDPIC_INTERP = 0x1 @@ -266,10 +290,13 @@ const ( RTC_WIE_ON = 0x700f RTC_WKALM_RD = 0x80287010 RTC_WKALM_SET = 0x4028700f + SCM_DEVMEM_DMABUF = 0x4f + SCM_DEVMEM_LINEAR = 0x4e SCM_TIMESTAMPING = 0x25 SCM_TIMESTAMPING_OPT_STATS = 0x36 SCM_TIMESTAMPING_PKTINFO = 0x3a SCM_TIMESTAMPNS = 0x23 + SCM_TS_OPT_ID = 0x51 SCM_TXTIME = 0x3d SCM_WIFI_STATUS = 0x29 SECCOMP_IOCTL_NOTIF_ADDFD = 0x40182103 @@ -304,6 +331,9 @@ const ( SO_CNX_ADVICE = 0x35 SO_COOKIE = 0x39 SO_DETACH_REUSEPORT_BPF = 0x44 + SO_DEVMEM_DMABUF = 0x4f + SO_DEVMEM_DONTNEED = 0x50 + SO_DEVMEM_LINEAR = 0x4e SO_DOMAIN = 0x27 SO_DONTROUTE = 0x5 SO_ERROR = 0x4 diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go index 2f1dd214a..669b2adb8 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go @@ -78,6 +78,8 @@ const ( ECHOPRT = 0x400 EFD_CLOEXEC = 0x80000 EFD_NONBLOCK = 0x800 + EPIOCGPARAMS = 0x80088a02 + EPIOCSPARAMS = 0x40088a01 EPOLL_CLOEXEC = 0x80000 EXTPROC = 0x10000 FF1 = 0x8000 @@ -106,12 +108,15 @@ const ( HIDIOCGRAWINFO = 0x80084803 HIDIOCGRDESC = 0x90044802 HIDIOCGRDESCSIZE = 0x80044801 + HIDIOCREVOKE = 0x4004480d HUPCL = 0x400 ICANON = 0x2 IEXTEN = 0x8000 IN_CLOEXEC = 0x80000 IN_NONBLOCK = 0x800 IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x7b9 + IPV6_FLOWINFO_MASK = 0xfffffff + IPV6_FLOWLABEL_MASK = 0xfffff ISIG = 0x1 IUCLC = 0x200 IXOFF = 0x1000 @@ -148,9 +153,14 @@ const ( NFDBITS = 0x40 NLDLY = 0x100 NOFLSH = 0x80 + NS_GET_MNTNS_ID = 0x8008b705 NS_GET_NSTYPE = 0xb703 NS_GET_OWNER_UID = 0xb704 NS_GET_PARENT = 0xb702 + NS_GET_PID_FROM_PIDNS = 0x8004b706 + NS_GET_PID_IN_PIDNS = 0x8004b708 + NS_GET_TGID_FROM_PIDNS = 0x8004b707 + NS_GET_TGID_IN_PIDNS = 0x8004b709 NS_GET_USERNS = 0xb701 OLCUC = 0x2 ONLCR = 0x4 @@ -227,6 +237,20 @@ const ( PPPIOCUNBRIDGECHAN = 0x7434 PPPIOCXFERUNIT = 0x744e PR_SET_PTRACER_ANY = 0xffffffffffffffff + PTP_CLOCK_GETCAPS = 0x80503d01 + PTP_CLOCK_GETCAPS2 = 0x80503d0a + PTP_ENABLE_PPS = 0x40043d04 + PTP_ENABLE_PPS2 = 0x40043d0d + PTP_EXTTS_REQUEST = 0x40103d02 + PTP_EXTTS_REQUEST2 = 0x40103d0b + PTP_MASK_CLEAR_ALL = 0x3d13 + PTP_MASK_EN_SINGLE = 0x40043d14 + PTP_PEROUT_REQUEST = 0x40383d03 + PTP_PEROUT_REQUEST2 = 0x40383d0c + PTP_PIN_SETFUNC = 0x40603d07 + PTP_PIN_SETFUNC2 = 0x40603d10 + PTP_SYS_OFFSET = 0x43403d05 + PTP_SYS_OFFSET2 = 0x43403d0e PTRACE_DISABLE_TE = 0x5010 PTRACE_ENABLE_TE = 0x5009 PTRACE_GET_LAST_BREAK = 0x5006 @@ -338,10 +362,13 @@ const ( RTC_WIE_ON = 0x700f RTC_WKALM_RD = 0x80287010 RTC_WKALM_SET = 0x4028700f + SCM_DEVMEM_DMABUF = 0x4f + SCM_DEVMEM_LINEAR = 0x4e SCM_TIMESTAMPING = 0x25 SCM_TIMESTAMPING_OPT_STATS = 0x36 SCM_TIMESTAMPING_PKTINFO = 0x3a SCM_TIMESTAMPNS = 0x23 + SCM_TS_OPT_ID = 0x51 SCM_TXTIME = 0x3d SCM_WIFI_STATUS = 0x29 SECCOMP_IOCTL_NOTIF_ADDFD = 0x40182103 @@ -376,6 +403,9 @@ const ( SO_CNX_ADVICE = 0x35 SO_COOKIE = 0x39 SO_DETACH_REUSEPORT_BPF = 0x44 + SO_DEVMEM_DMABUF = 0x4f + SO_DEVMEM_DONTNEED = 0x50 + SO_DEVMEM_LINEAR = 0x4e SO_DOMAIN = 0x27 SO_DONTROUTE = 0x5 SO_ERROR = 0x4 diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go index f40519d90..4834e5751 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go @@ -82,6 +82,8 @@ const ( EFD_CLOEXEC = 0x400000 EFD_NONBLOCK = 0x4000 EMT_TAGOVF = 0x1 + EPIOCGPARAMS = 0x40088a02 + EPIOCSPARAMS = 0x80088a01 EPOLL_CLOEXEC = 0x400000 EXTPROC = 0x10000 FF1 = 0x8000 @@ -110,12 +112,15 @@ const ( HIDIOCGRAWINFO = 0x40084803 HIDIOCGRDESC = 0x50044802 HIDIOCGRDESCSIZE = 0x40044801 + HIDIOCREVOKE = 0x8004480d HUPCL = 0x400 ICANON = 0x2 IEXTEN = 0x8000 IN_CLOEXEC = 0x400000 IN_NONBLOCK = 0x4000 IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x200007b9 + IPV6_FLOWINFO_MASK = 0xfffffff + IPV6_FLOWLABEL_MASK = 0xfffff ISIG = 0x1 IUCLC = 0x200 IXOFF = 0x1000 @@ -153,9 +158,14 @@ const ( NFDBITS = 0x40 NLDLY = 0x100 NOFLSH = 0x80 + NS_GET_MNTNS_ID = 0x4008b705 NS_GET_NSTYPE = 0x2000b703 NS_GET_OWNER_UID = 0x2000b704 NS_GET_PARENT = 0x2000b702 + NS_GET_PID_FROM_PIDNS = 0x4004b706 + NS_GET_PID_IN_PIDNS = 0x4004b708 + NS_GET_TGID_FROM_PIDNS = 0x4004b707 + NS_GET_TGID_IN_PIDNS = 0x4004b709 NS_GET_USERNS = 0x2000b701 OLCUC = 0x2 ONLCR = 0x4 @@ -232,6 +242,20 @@ const ( PPPIOCUNBRIDGECHAN = 0x20007434 PPPIOCXFERUNIT = 0x2000744e PR_SET_PTRACER_ANY = 0xffffffffffffffff + PTP_CLOCK_GETCAPS = 0x40503d01 + PTP_CLOCK_GETCAPS2 = 0x40503d0a + PTP_ENABLE_PPS = 0x80043d04 + PTP_ENABLE_PPS2 = 0x80043d0d + PTP_EXTTS_REQUEST = 0x80103d02 + PTP_EXTTS_REQUEST2 = 0x80103d0b + PTP_MASK_CLEAR_ALL = 0x20003d13 + PTP_MASK_EN_SINGLE = 0x80043d14 + PTP_PEROUT_REQUEST = 0x80383d03 + PTP_PEROUT_REQUEST2 = 0x80383d0c + PTP_PIN_SETFUNC = 0x80603d07 + PTP_PIN_SETFUNC2 = 0x80603d10 + PTP_SYS_OFFSET = 0x83403d05 + PTP_SYS_OFFSET2 = 0x83403d0e PTRACE_GETFPAREGS = 0x14 PTRACE_GETFPREGS = 0xe PTRACE_GETFPREGS64 = 0x19 @@ -329,10 +353,13 @@ const ( RTC_WIE_ON = 0x2000700f RTC_WKALM_RD = 0x40287010 RTC_WKALM_SET = 0x8028700f + SCM_DEVMEM_DMABUF = 0x58 + SCM_DEVMEM_LINEAR = 0x57 SCM_TIMESTAMPING = 0x23 SCM_TIMESTAMPING_OPT_STATS = 0x38 SCM_TIMESTAMPING_PKTINFO = 0x3c SCM_TIMESTAMPNS = 0x21 + SCM_TS_OPT_ID = 0x5a SCM_TXTIME = 0x3f SCM_WIFI_STATUS = 0x25 SECCOMP_IOCTL_NOTIF_ADDFD = 0x80182103 @@ -415,6 +442,9 @@ const ( SO_CNX_ADVICE = 0x37 SO_COOKIE = 0x3b SO_DETACH_REUSEPORT_BPF = 0x47 + SO_DEVMEM_DMABUF = 0x58 + SO_DEVMEM_DONTNEED = 0x59 + SO_DEVMEM_LINEAR = 0x57 SO_DOMAIN = 0x1029 SO_DONTROUTE = 0x10 SO_ERROR = 0x1007 diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zerrors_zos_s390x.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zerrors_zos_s390x.go index 4dfd2e051..1ec2b1407 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zerrors_zos_s390x.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zerrors_zos_s390x.go @@ -10,41 +10,99 @@ package unix const ( - BRKINT = 0x0001 - CLOCK_MONOTONIC = 0x1 - CLOCK_PROCESS_CPUTIME_ID = 0x2 - CLOCK_REALTIME = 0x0 - CLOCK_THREAD_CPUTIME_ID = 0x3 - CS8 = 0x0030 - CSIZE = 0x0030 - ECHO = 0x00000008 - ECHONL = 0x00000001 - FD_CLOEXEC = 0x01 - FD_CLOFORK = 0x02 - FNDELAY = 0x04 - F_CLOSFD = 9 - F_CONTROL_CVT = 13 - F_DUPFD = 0 - F_DUPFD2 = 8 - F_GETFD = 1 - F_GETFL = 259 - F_GETLK = 5 - F_GETOWN = 10 - F_OK = 0x0 - F_RDLCK = 1 - F_SETFD = 2 - F_SETFL = 4 - F_SETLK = 6 - F_SETLKW = 7 - F_SETOWN = 11 - F_SETTAG = 12 - F_UNLCK = 3 - F_WRLCK = 2 - FSTYPE_ZFS = 0xe9 //"Z" - FSTYPE_HFS = 0xc8 //"H" - FSTYPE_NFS = 0xd5 //"N" - FSTYPE_TFS = 0xe3 //"T" - FSTYPE_AUTOMOUNT = 0xc1 //"A" + BRKINT = 0x0001 + CLOCAL = 0x1 + CLOCK_MONOTONIC = 0x1 + CLOCK_PROCESS_CPUTIME_ID = 0x2 + CLOCK_REALTIME = 0x0 + CLOCK_THREAD_CPUTIME_ID = 0x3 + CLONE_NEWIPC = 0x08000000 + CLONE_NEWNET = 0x40000000 + CLONE_NEWNS = 0x00020000 + CLONE_NEWPID = 0x20000000 + CLONE_NEWUTS = 0x04000000 + CLONE_PARENT = 0x00008000 + CS8 = 0x0030 + CSIZE = 0x0030 + ECHO = 0x00000008 + ECHONL = 0x00000001 + EFD_SEMAPHORE = 0x00002000 + EFD_CLOEXEC = 0x00001000 + EFD_NONBLOCK = 0x00000004 + EPOLL_CLOEXEC = 0x00001000 + EPOLL_CTL_ADD = 0 + EPOLL_CTL_MOD = 1 + EPOLL_CTL_DEL = 2 + EPOLLRDNORM = 0x0001 + EPOLLRDBAND = 0x0002 + EPOLLIN = 0x0003 + EPOLLOUT = 0x0004 + EPOLLWRBAND = 0x0008 + EPOLLPRI = 0x0010 + EPOLLERR = 0x0020 + EPOLLHUP = 0x0040 + EPOLLEXCLUSIVE = 0x20000000 + EPOLLONESHOT = 0x40000000 + FD_CLOEXEC = 0x01 + FD_CLOFORK = 0x02 + FD_SETSIZE = 0x800 + FNDELAY = 0x04 + F_CLOSFD = 9 + F_CONTROL_CVT = 13 + F_DUPFD = 0 + F_DUPFD2 = 8 + F_GETFD = 1 + F_GETFL = 259 + F_GETLK = 5 + F_GETOWN = 10 + F_OK = 0x0 + F_RDLCK = 1 + F_SETFD = 2 + F_SETFL = 4 + F_SETLK = 6 + F_SETLKW = 7 + F_SETOWN = 11 + F_SETTAG = 12 + F_UNLCK = 3 + F_WRLCK = 2 + FSTYPE_ZFS = 0xe9 //"Z" + FSTYPE_HFS = 0xc8 //"H" + FSTYPE_NFS = 0xd5 //"N" + FSTYPE_TFS = 0xe3 //"T" + FSTYPE_AUTOMOUNT = 0xc1 //"A" + GRND_NONBLOCK = 1 + GRND_RANDOM = 2 + HUPCL = 0x0100 // Hang up on last close + IN_CLOEXEC = 0x00001000 + IN_NONBLOCK = 0x00000004 + IN_ACCESS = 0x00000001 + IN_MODIFY = 0x00000002 + IN_ATTRIB = 0x00000004 + IN_CLOSE_WRITE = 0x00000008 + IN_CLOSE_NOWRITE = 0x00000010 + IN_OPEN = 0x00000020 + IN_MOVED_FROM = 0x00000040 + IN_MOVED_TO = 0x00000080 + IN_CREATE = 0x00000100 + IN_DELETE = 0x00000200 + IN_DELETE_SELF = 0x00000400 + IN_MOVE_SELF = 0x00000800 + IN_UNMOUNT = 0x00002000 + IN_Q_OVERFLOW = 0x00004000 + IN_IGNORED = 0x00008000 + IN_CLOSE = (IN_CLOSE_WRITE | IN_CLOSE_NOWRITE) + IN_MOVE = (IN_MOVED_FROM | IN_MOVED_TO) + IN_ALL_EVENTS = (IN_ACCESS | IN_MODIFY | IN_ATTRIB | + IN_CLOSE | IN_OPEN | IN_MOVE | + IN_CREATE | IN_DELETE | IN_DELETE_SELF | + IN_MOVE_SELF) + IN_ONLYDIR = 0x01000000 + IN_DONT_FOLLOW = 0x02000000 + IN_EXCL_UNLINK = 0x04000000 + IN_MASK_CREATE = 0x10000000 + IN_MASK_ADD = 0x20000000 + IN_ISDIR = 0x40000000 + IN_ONESHOT = 0x80000000 IP6F_MORE_FRAG = 0x0001 IP6F_OFF_MASK = 0xfff8 IP6F_RESERVED_MASK = 0x0006 @@ -152,10 +210,18 @@ const ( IP_PKTINFO = 101 IP_RECVPKTINFO = 102 IP_TOS = 2 - IP_TTL = 3 + IP_TTL = 14 IP_UNBLOCK_SOURCE = 11 + ICMP6_FILTER = 1 + MCAST_INCLUDE = 0 + MCAST_EXCLUDE = 1 + MCAST_JOIN_GROUP = 40 + MCAST_LEAVE_GROUP = 41 + MCAST_JOIN_SOURCE_GROUP = 42 + MCAST_LEAVE_SOURCE_GROUP = 43 + MCAST_BLOCK_SOURCE = 44 + MCAST_UNBLOCK_SOURCE = 46 ICANON = 0x0010 - ICMP6_FILTER = 0x26 ICRNL = 0x0002 IEXTEN = 0x0020 IGNBRK = 0x0004 @@ -165,10 +231,10 @@ const ( ISTRIP = 0x0080 IXON = 0x0200 IXOFF = 0x0100 - LOCK_SH = 0x1 // Not exist on zOS - LOCK_EX = 0x2 // Not exist on zOS - LOCK_NB = 0x4 // Not exist on zOS - LOCK_UN = 0x8 // Not exist on zOS + LOCK_SH = 0x1 + LOCK_EX = 0x2 + LOCK_NB = 0x4 + LOCK_UN = 0x8 POLLIN = 0x0003 POLLOUT = 0x0004 POLLPRI = 0x0010 @@ -182,15 +248,29 @@ const ( MAP_PRIVATE = 0x1 // changes are private MAP_SHARED = 0x2 // changes are shared MAP_FIXED = 0x4 // place exactly - MCAST_JOIN_GROUP = 40 - MCAST_LEAVE_GROUP = 41 - MCAST_JOIN_SOURCE_GROUP = 42 - MCAST_LEAVE_SOURCE_GROUP = 43 - MCAST_BLOCK_SOURCE = 44 - MCAST_UNBLOCK_SOURCE = 45 + __MAP_MEGA = 0x8 + __MAP_64 = 0x10 + MAP_ANON = 0x20 + MAP_ANONYMOUS = 0x20 MS_SYNC = 0x1 // msync - synchronous writes MS_ASYNC = 0x2 // asynchronous writes MS_INVALIDATE = 0x4 // invalidate mappings + MS_BIND = 0x00001000 + MS_MOVE = 0x00002000 + MS_NOSUID = 0x00000002 + MS_PRIVATE = 0x00040000 + MS_REC = 0x00004000 + MS_REMOUNT = 0x00008000 + MS_RDONLY = 0x00000001 + MS_UNBINDABLE = 0x00020000 + MNT_DETACH = 0x00000004 + ZOSDSFS_SUPER_MAGIC = 0x44534653 // zOS DSFS + NFS_SUPER_MAGIC = 0x6969 // NFS + NSFS_MAGIC = 0x6e736673 // PROCNS + PROC_SUPER_MAGIC = 0x9fa0 // proc FS + ZOSTFS_SUPER_MAGIC = 0x544653 // zOS TFS + ZOSUFS_SUPER_MAGIC = 0x554653 // zOS UFS + ZOSZFS_SUPER_MAGIC = 0x5A4653 // zOS ZFS MTM_RDONLY = 0x80000000 MTM_RDWR = 0x40000000 MTM_UMOUNT = 0x10000000 @@ -205,13 +285,20 @@ const ( MTM_REMOUNT = 0x00000100 MTM_NOSECURITY = 0x00000080 NFDBITS = 0x20 + ONLRET = 0x0020 // NL performs CR function O_ACCMODE = 0x03 O_APPEND = 0x08 O_ASYNCSIG = 0x0200 O_CREAT = 0x80 + O_DIRECT = 0x00002000 + O_NOFOLLOW = 0x00004000 + O_DIRECTORY = 0x00008000 + O_PATH = 0x00080000 + O_CLOEXEC = 0x00001000 O_EXCL = 0x40 O_GETFL = 0x0F O_LARGEFILE = 0x0400 + O_NDELAY = 0x4 O_NONBLOCK = 0x04 O_RDONLY = 0x02 O_RDWR = 0x03 @@ -248,6 +335,7 @@ const ( AF_IUCV = 17 AF_LAT = 14 AF_LINK = 18 + AF_LOCAL = AF_UNIX // AF_LOCAL is an alias for AF_UNIX AF_MAX = 30 AF_NBS = 7 AF_NDD = 23 @@ -285,15 +373,33 @@ const ( RLIMIT_AS = 5 RLIMIT_NOFILE = 6 RLIMIT_MEMLIMIT = 7 + RLIMIT_MEMLOCK = 0x8 RLIM_INFINITY = 2147483647 + SCHED_FIFO = 0x2 + SCM_CREDENTIALS = 0x2 SCM_RIGHTS = 0x01 SF_CLOSE = 0x00000002 SF_REUSE = 0x00000001 + SHM_RND = 0x2 + SHM_RDONLY = 0x1 + SHMLBA = 0x1000 + IPC_STAT = 0x3 + IPC_SET = 0x2 + IPC_RMID = 0x1 + IPC_PRIVATE = 0x0 + IPC_CREAT = 0x1000000 + __IPC_MEGA = 0x4000000 + __IPC_SHAREAS = 0x20000000 + __IPC_BELOWBAR = 0x10000000 + IPC_EXCL = 0x2000000 + __IPC_GIGA = 0x8000000 SHUT_RD = 0 SHUT_RDWR = 2 SHUT_WR = 1 + SOCK_CLOEXEC = 0x00001000 SOCK_CONN_DGRAM = 6 SOCK_DGRAM = 2 + SOCK_NONBLOCK = 0x800 SOCK_RAW = 3 SOCK_RDM = 4 SOCK_SEQPACKET = 5 @@ -378,8 +484,6 @@ const ( S_IFMST = 0x00FF0000 TCP_KEEPALIVE = 0x8 TCP_NODELAY = 0x1 - TCP_INFO = 0xb - TCP_USER_TIMEOUT = 0x1 TIOCGWINSZ = 0x4008a368 TIOCSWINSZ = 0x8008a367 TIOCSBRK = 0x2000a77b @@ -427,7 +531,10 @@ const ( VSUSP = 9 VTIME = 10 WCONTINUED = 0x4 + WEXITED = 0x8 WNOHANG = 0x1 + WNOWAIT = 0x20 + WSTOPPED = 0x10 WUNTRACED = 0x2 _BPX_SWAP = 1 _BPX_NONSWAP = 2 @@ -452,8 +559,30 @@ const ( MADV_FREE = 15 // for Linux compatibility -- no zos semantics MADV_WIPEONFORK = 16 // for Linux compatibility -- no zos semantics MADV_KEEPONFORK = 17 // for Linux compatibility -- no zos semantics - AT_SYMLINK_NOFOLLOW = 1 // for Unix compatibility -- no zos semantics - AT_FDCWD = 2 // for Unix compatibility -- no zos semantics + AT_SYMLINK_FOLLOW = 0x400 + AT_SYMLINK_NOFOLLOW = 0x100 + XATTR_CREATE = 0x1 + XATTR_REPLACE = 0x2 + P_PID = 0 + P_PGID = 1 + P_ALL = 2 + PR_SET_NAME = 15 + PR_GET_NAME = 16 + PR_SET_NO_NEW_PRIVS = 38 + PR_GET_NO_NEW_PRIVS = 39 + PR_SET_DUMPABLE = 4 + PR_GET_DUMPABLE = 3 + PR_SET_PDEATHSIG = 1 + PR_GET_PDEATHSIG = 2 + PR_SET_CHILD_SUBREAPER = 36 + PR_GET_CHILD_SUBREAPER = 37 + AT_FDCWD = -100 + AT_EACCESS = 0x200 + AT_EMPTY_PATH = 0x1000 + AT_REMOVEDIR = 0x200 + RENAME_NOREPLACE = 1 << 0 + ST_RDONLY = 1 + ST_NOSUID = 2 ) const ( @@ -476,6 +605,7 @@ const ( EMLINK = Errno(125) ENAMETOOLONG = Errno(126) ENFILE = Errno(127) + ENOATTR = Errno(265) ENODEV = Errno(128) ENOENT = Errno(129) ENOEXEC = Errno(130) @@ -700,7 +830,7 @@ var errorList = [...]struct { {145, "EDC5145I", "The parameter list is too long, or the message to receive was too large for the buffer."}, {146, "EDC5146I", "Too many levels of symbolic links."}, {147, "EDC5147I", "Illegal byte sequence."}, - {148, "", ""}, + {148, "EDC5148I", "The named attribute or data not available."}, {149, "EDC5149I", "Value Overflow Error."}, {150, "EDC5150I", "UNIX System Services is not active."}, {151, "EDC5151I", "Dynamic allocation error."}, @@ -743,6 +873,7 @@ var errorList = [...]struct { {259, "EDC5259I", "A CUN_RS_NO_CONVERSION error was issued by Unicode Services."}, {260, "EDC5260I", "A CUN_RS_TABLE_NOT_ALIGNED error was issued by Unicode Services."}, {262, "EDC5262I", "An iconv() function encountered an unexpected error while using Unicode Services."}, + {265, "EDC5265I", "The named attribute not available."}, {1000, "EDC8000I", "A bad socket-call constant was found in the IUCV header."}, {1001, "EDC8001I", "An error was found in the IUCV header."}, {1002, "EDC8002I", "A socket descriptor is out of range."}, diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsymaddr_zos_s390x.s b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsymaddr_zos_s390x.s new file mode 100644 index 000000000..b77ff5db9 --- /dev/null +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsymaddr_zos_s390x.s @@ -0,0 +1,364 @@ +// go run mksyscall_zos_s390x.go -o_sysnum zsysnum_zos_s390x.go -o_syscall zsyscall_zos_s390x.go -i_syscall syscall_zos_s390x.go -o_asm zsymaddr_zos_s390x.s +// Code generated by the command above; see README.md. DO NOT EDIT. + +//go:build zos && s390x +#include "textflag.h" + +// provide the address of function variable to be fixed up. + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_FlistxattrAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Flistxattr(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_FremovexattrAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Fremovexattr(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_FgetxattrAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Fgetxattr(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_FsetxattrAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Fsetxattr(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_accept4Addr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·accept4(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_RemovexattrAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Removexattr(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_Dup3Addr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Dup3(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_DirfdAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Dirfd(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_EpollCreateAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·EpollCreate(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_EpollCreate1Addr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·EpollCreate1(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_EpollCtlAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·EpollCtl(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_EpollPwaitAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·EpollPwait(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_EpollWaitAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·EpollWait(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_EventfdAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Eventfd(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_FaccessatAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Faccessat(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_FchmodatAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Fchmodat(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_FchownatAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Fchownat(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_FdatasyncAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Fdatasync(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_fstatatAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·fstatat(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_LgetxattrAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Lgetxattr(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_LsetxattrAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Lsetxattr(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_FstatfsAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Fstatfs(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_FutimesAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Futimes(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_FutimesatAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Futimesat(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_GetrandomAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Getrandom(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_InotifyInitAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·InotifyInit(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_InotifyInit1Addr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·InotifyInit1(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_InotifyAddWatchAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·InotifyAddWatch(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_InotifyRmWatchAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·InotifyRmWatch(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_ListxattrAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Listxattr(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_LlistxattrAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Llistxattr(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_LremovexattrAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Lremovexattr(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_LutimesAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Lutimes(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_StatfsAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Statfs(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_SyncfsAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Syncfs(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_UnshareAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Unshare(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_LinkatAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Linkat(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_MkdiratAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Mkdirat(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_MknodatAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Mknodat(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_PivotRootAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·PivotRoot(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_PrctlAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Prctl(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_PrlimitAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Prlimit(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_RenameatAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Renameat(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_Renameat2Addr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Renameat2(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_SethostnameAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Sethostname(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_SetnsAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Setns(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_SymlinkatAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Symlinkat(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_UnlinkatAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·Unlinkat(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_openatAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·openat(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_openat2Addr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·openat2(SB), R8 + MOVD R8, ret+0(FP) + RET + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +TEXT ·get_utimensatAddr(SB), NOSPLIT|NOFRAME, $0-8 + MOVD $·utimensat(SB), R8 + MOVD R8, ret+0(FP) + RET diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.go index ccb02f240..24b346e1a 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.go @@ -740,6 +740,54 @@ func ioctlPtr(fd int, req uint, arg unsafe.Pointer) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func renamexNp(from string, to string, flag uint32) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(from) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(to) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_renamex_np_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(flag)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_renamex_np_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_renamex_np renamex_np "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func renameatxNp(fromfd int, from string, tofd int, to string, flag uint32) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(from) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(to) + if err != nil { + return + } + _, _, e1 := syscall_syscall6(libc_renameatx_np_trampoline_addr, uintptr(fromfd), uintptr(unsafe.Pointer(_p0)), uintptr(tofd), uintptr(unsafe.Pointer(_p1)), uintptr(flag), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_renameatx_np_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_renameatx_np renameatx_np "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { var _p0 unsafe.Pointer if len(mib) > 0 { @@ -760,6 +808,59 @@ var libc_sysctl_trampoline_addr uintptr // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func pthread_chdir_np(path string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_pthread_chdir_np_trampoline_addr, uintptr(unsafe.Pointer(_p0)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_pthread_chdir_np_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_pthread_chdir_np pthread_chdir_np "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func pthread_fchdir_np(fd int) (err error) { + _, _, e1 := syscall_syscall(libc_pthread_fchdir_np_trampoline_addr, uintptr(fd), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_pthread_fchdir_np_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_pthread_fchdir_np pthread_fchdir_np "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func connectx(fd int, endpoints *SaEndpoints, associd SaeAssocID, flags uint32, iov []Iovec, n *uintptr, connid *SaeConnID) (err error) { + var _p0 unsafe.Pointer + if len(iov) > 0 { + _p0 = unsafe.Pointer(&iov[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + _, _, e1 := syscall_syscall9(libc_connectx_trampoline_addr, uintptr(fd), uintptr(unsafe.Pointer(endpoints)), uintptr(associd), uintptr(flags), uintptr(_p0), uintptr(len(iov)), uintptr(unsafe.Pointer(n)), uintptr(unsafe.Pointer(connid)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_connectx_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_connectx connectx "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func sendfile(infd int, outfd int, offset int64, len *int64, hdtr unsafe.Pointer, flags int) (err error) { _, _, e1 := syscall_syscall6(libc_sendfile_trampoline_addr, uintptr(infd), uintptr(outfd), uintptr(offset), uintptr(unsafe.Pointer(len)), uintptr(hdtr), uintptr(flags)) if e1 != 0 { diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.s b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.s index 8b8bb2840..ebd213100 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.s +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.s @@ -223,11 +223,36 @@ TEXT libc_ioctl_trampoline<>(SB),NOSPLIT,$0-0 GLOBL ·libc_ioctl_trampoline_addr(SB), RODATA, $8 DATA ·libc_ioctl_trampoline_addr(SB)/8, $libc_ioctl_trampoline<>(SB) +TEXT libc_renamex_np_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_renamex_np(SB) +GLOBL ·libc_renamex_np_trampoline_addr(SB), RODATA, $8 +DATA ·libc_renamex_np_trampoline_addr(SB)/8, $libc_renamex_np_trampoline<>(SB) + +TEXT libc_renameatx_np_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_renameatx_np(SB) +GLOBL ·libc_renameatx_np_trampoline_addr(SB), RODATA, $8 +DATA ·libc_renameatx_np_trampoline_addr(SB)/8, $libc_renameatx_np_trampoline<>(SB) + TEXT libc_sysctl_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_sysctl(SB) GLOBL ·libc_sysctl_trampoline_addr(SB), RODATA, $8 DATA ·libc_sysctl_trampoline_addr(SB)/8, $libc_sysctl_trampoline<>(SB) +TEXT libc_pthread_chdir_np_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_pthread_chdir_np(SB) +GLOBL ·libc_pthread_chdir_np_trampoline_addr(SB), RODATA, $8 +DATA ·libc_pthread_chdir_np_trampoline_addr(SB)/8, $libc_pthread_chdir_np_trampoline<>(SB) + +TEXT libc_pthread_fchdir_np_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_pthread_fchdir_np(SB) +GLOBL ·libc_pthread_fchdir_np_trampoline_addr(SB), RODATA, $8 +DATA ·libc_pthread_fchdir_np_trampoline_addr(SB)/8, $libc_pthread_fchdir_np_trampoline<>(SB) + +TEXT libc_connectx_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_connectx(SB) +GLOBL ·libc_connectx_trampoline_addr(SB), RODATA, $8 +DATA ·libc_connectx_trampoline_addr(SB)/8, $libc_connectx_trampoline<>(SB) + TEXT libc_sendfile_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_sendfile(SB) GLOBL ·libc_sendfile_trampoline_addr(SB), RODATA, $8 diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.go index 1b40b997b..824b9c2d5 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.go @@ -740,6 +740,54 @@ func ioctlPtr(fd int, req uint, arg unsafe.Pointer) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func renamexNp(from string, to string, flag uint32) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(from) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(to) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_renamex_np_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(flag)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_renamex_np_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_renamex_np renamex_np "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func renameatxNp(fromfd int, from string, tofd int, to string, flag uint32) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(from) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(to) + if err != nil { + return + } + _, _, e1 := syscall_syscall6(libc_renameatx_np_trampoline_addr, uintptr(fromfd), uintptr(unsafe.Pointer(_p0)), uintptr(tofd), uintptr(unsafe.Pointer(_p1)), uintptr(flag), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_renameatx_np_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_renameatx_np renameatx_np "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { var _p0 unsafe.Pointer if len(mib) > 0 { @@ -760,6 +808,59 @@ var libc_sysctl_trampoline_addr uintptr // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func pthread_chdir_np(path string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_pthread_chdir_np_trampoline_addr, uintptr(unsafe.Pointer(_p0)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_pthread_chdir_np_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_pthread_chdir_np pthread_chdir_np "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func pthread_fchdir_np(fd int) (err error) { + _, _, e1 := syscall_syscall(libc_pthread_fchdir_np_trampoline_addr, uintptr(fd), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_pthread_fchdir_np_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_pthread_fchdir_np pthread_fchdir_np "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func connectx(fd int, endpoints *SaEndpoints, associd SaeAssocID, flags uint32, iov []Iovec, n *uintptr, connid *SaeConnID) (err error) { + var _p0 unsafe.Pointer + if len(iov) > 0 { + _p0 = unsafe.Pointer(&iov[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + _, _, e1 := syscall_syscall9(libc_connectx_trampoline_addr, uintptr(fd), uintptr(unsafe.Pointer(endpoints)), uintptr(associd), uintptr(flags), uintptr(_p0), uintptr(len(iov)), uintptr(unsafe.Pointer(n)), uintptr(unsafe.Pointer(connid)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_connectx_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_connectx connectx "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func sendfile(infd int, outfd int, offset int64, len *int64, hdtr unsafe.Pointer, flags int) (err error) { _, _, e1 := syscall_syscall6(libc_sendfile_trampoline_addr, uintptr(infd), uintptr(outfd), uintptr(offset), uintptr(unsafe.Pointer(len)), uintptr(hdtr), uintptr(flags)) if e1 != 0 { diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.s b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.s index 08362c1ab..4f178a229 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.s +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.s @@ -223,11 +223,36 @@ TEXT libc_ioctl_trampoline<>(SB),NOSPLIT,$0-0 GLOBL ·libc_ioctl_trampoline_addr(SB), RODATA, $8 DATA ·libc_ioctl_trampoline_addr(SB)/8, $libc_ioctl_trampoline<>(SB) +TEXT libc_renamex_np_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_renamex_np(SB) +GLOBL ·libc_renamex_np_trampoline_addr(SB), RODATA, $8 +DATA ·libc_renamex_np_trampoline_addr(SB)/8, $libc_renamex_np_trampoline<>(SB) + +TEXT libc_renameatx_np_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_renameatx_np(SB) +GLOBL ·libc_renameatx_np_trampoline_addr(SB), RODATA, $8 +DATA ·libc_renameatx_np_trampoline_addr(SB)/8, $libc_renameatx_np_trampoline<>(SB) + TEXT libc_sysctl_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_sysctl(SB) GLOBL ·libc_sysctl_trampoline_addr(SB), RODATA, $8 DATA ·libc_sysctl_trampoline_addr(SB)/8, $libc_sysctl_trampoline<>(SB) +TEXT libc_pthread_chdir_np_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_pthread_chdir_np(SB) +GLOBL ·libc_pthread_chdir_np_trampoline_addr(SB), RODATA, $8 +DATA ·libc_pthread_chdir_np_trampoline_addr(SB)/8, $libc_pthread_chdir_np_trampoline<>(SB) + +TEXT libc_pthread_fchdir_np_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_pthread_fchdir_np(SB) +GLOBL ·libc_pthread_fchdir_np_trampoline_addr(SB), RODATA, $8 +DATA ·libc_pthread_fchdir_np_trampoline_addr(SB)/8, $libc_pthread_fchdir_np_trampoline<>(SB) + +TEXT libc_connectx_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_connectx(SB) +GLOBL ·libc_connectx_trampoline_addr(SB), RODATA, $8 +DATA ·libc_connectx_trampoline_addr(SB)/8, $libc_connectx_trampoline<>(SB) + TEXT libc_sendfile_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_sendfile(SB) GLOBL ·libc_sendfile_trampoline_addr(SB), RODATA, $8 diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsyscall_linux.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsyscall_linux.go index 87d8612a1..5cc1e8eb2 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsyscall_linux.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsyscall_linux.go @@ -592,6 +592,16 @@ func ClockGettime(clockid int32, time *Timespec) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func ClockSettime(clockid int32, time *Timespec) (err error) { + _, _, e1 := Syscall(SYS_CLOCK_SETTIME, uintptr(clockid), uintptr(unsafe.Pointer(time)), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func ClockNanosleep(clockid int32, flags int, request *Timespec, remain *Timespec) (err error) { _, _, e1 := Syscall6(SYS_CLOCK_NANOSLEEP, uintptr(clockid), uintptr(flags), uintptr(unsafe.Pointer(request)), uintptr(unsafe.Pointer(remain)), 0, 0) if e1 != 0 { @@ -971,23 +981,6 @@ func Getpriority(which int, who int) (prio int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Getrandom(buf []byte, flags int) (n int, err error) { - var _p0 unsafe.Pointer - if len(buf) > 0 { - _p0 = unsafe.Pointer(&buf[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - r0, _, e1 := Syscall(SYS_GETRANDOM, uintptr(_p0), uintptr(len(buf)), uintptr(flags)) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Getrusage(who int, rusage *Rusage) (err error) { _, _, e1 := RawSyscall(SYS_GETRUSAGE, uintptr(who), uintptr(unsafe.Pointer(rusage)), 0) if e1 != 0 { @@ -2229,3 +2222,19 @@ func Cachestat(fd uint, crange *CachestatRange, cstat *Cachestat_t, flags uint) } return } + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Mseal(b []byte, flags uint) (err error) { + var _p0 unsafe.Pointer + if len(b) > 0 { + _p0 = unsafe.Pointer(&b[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + _, _, e1 := Syscall(SYS_MSEAL, uintptr(_p0), uintptr(len(b)), uintptr(flags)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsyscall_openbsd_386.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsyscall_openbsd_386.go index 9dc42410b..1851df14e 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsyscall_openbsd_386.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsyscall_openbsd_386.go @@ -1493,6 +1493,30 @@ var libc_mknodat_trampoline_addr uintptr // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Mount(fsType string, dir string, flags int, data unsafe.Pointer) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(fsType) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(dir) + if err != nil { + return + } + _, _, e1 := syscall_syscall6(libc_mount_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(flags), uintptr(data), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_mount_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mount mount "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Nanosleep(time *Timespec, leftover *Timespec) (err error) { _, _, e1 := syscall_syscall(libc_nanosleep_trampoline_addr, uintptr(unsafe.Pointer(time)), uintptr(unsafe.Pointer(leftover)), 0) if e1 != 0 { diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsyscall_openbsd_386.s b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsyscall_openbsd_386.s index 41b561731..0b43c6936 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsyscall_openbsd_386.s +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsyscall_openbsd_386.s @@ -463,6 +463,11 @@ TEXT libc_mknodat_trampoline<>(SB),NOSPLIT,$0-0 GLOBL ·libc_mknodat_trampoline_addr(SB), RODATA, $4 DATA ·libc_mknodat_trampoline_addr(SB)/4, $libc_mknodat_trampoline<>(SB) +TEXT libc_mount_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_mount(SB) +GLOBL ·libc_mount_trampoline_addr(SB), RODATA, $4 +DATA ·libc_mount_trampoline_addr(SB)/4, $libc_mount_trampoline<>(SB) + TEXT libc_nanosleep_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_nanosleep(SB) GLOBL ·libc_nanosleep_trampoline_addr(SB), RODATA, $4 diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsyscall_openbsd_amd64.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsyscall_openbsd_amd64.go index 0d3a0751c..e1ec0dbe4 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsyscall_openbsd_amd64.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsyscall_openbsd_amd64.go @@ -1493,6 +1493,30 @@ var libc_mknodat_trampoline_addr uintptr // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Mount(fsType string, dir string, flags int, data unsafe.Pointer) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(fsType) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(dir) + if err != nil { + return + } + _, _, e1 := syscall_syscall6(libc_mount_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(flags), uintptr(data), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_mount_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mount mount "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Nanosleep(time *Timespec, leftover *Timespec) (err error) { _, _, e1 := syscall_syscall(libc_nanosleep_trampoline_addr, uintptr(unsafe.Pointer(time)), uintptr(unsafe.Pointer(leftover)), 0) if e1 != 0 { diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsyscall_openbsd_amd64.s b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsyscall_openbsd_amd64.s index 4019a656f..880c6d6e3 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsyscall_openbsd_amd64.s +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsyscall_openbsd_amd64.s @@ -463,6 +463,11 @@ TEXT libc_mknodat_trampoline<>(SB),NOSPLIT,$0-0 GLOBL ·libc_mknodat_trampoline_addr(SB), RODATA, $8 DATA ·libc_mknodat_trampoline_addr(SB)/8, $libc_mknodat_trampoline<>(SB) +TEXT libc_mount_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_mount(SB) +GLOBL ·libc_mount_trampoline_addr(SB), RODATA, $8 +DATA ·libc_mount_trampoline_addr(SB)/8, $libc_mount_trampoline<>(SB) + TEXT libc_nanosleep_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_nanosleep(SB) GLOBL ·libc_nanosleep_trampoline_addr(SB), RODATA, $8 diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm.go index c39f7776d..7c8452a63 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm.go @@ -1493,6 +1493,30 @@ var libc_mknodat_trampoline_addr uintptr // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Mount(fsType string, dir string, flags int, data unsafe.Pointer) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(fsType) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(dir) + if err != nil { + return + } + _, _, e1 := syscall_syscall6(libc_mount_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(flags), uintptr(data), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_mount_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mount mount "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Nanosleep(time *Timespec, leftover *Timespec) (err error) { _, _, e1 := syscall_syscall(libc_nanosleep_trampoline_addr, uintptr(unsafe.Pointer(time)), uintptr(unsafe.Pointer(leftover)), 0) if e1 != 0 { diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm.s b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm.s index ac4af24f9..b8ef95b0f 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm.s +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm.s @@ -463,6 +463,11 @@ TEXT libc_mknodat_trampoline<>(SB),NOSPLIT,$0-0 GLOBL ·libc_mknodat_trampoline_addr(SB), RODATA, $4 DATA ·libc_mknodat_trampoline_addr(SB)/4, $libc_mknodat_trampoline<>(SB) +TEXT libc_mount_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_mount(SB) +GLOBL ·libc_mount_trampoline_addr(SB), RODATA, $4 +DATA ·libc_mount_trampoline_addr(SB)/4, $libc_mount_trampoline<>(SB) + TEXT libc_nanosleep_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_nanosleep(SB) GLOBL ·libc_nanosleep_trampoline_addr(SB), RODATA, $4 diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm64.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm64.go index 57571d072..2ffdf861f 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm64.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm64.go @@ -1493,6 +1493,30 @@ var libc_mknodat_trampoline_addr uintptr // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Mount(fsType string, dir string, flags int, data unsafe.Pointer) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(fsType) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(dir) + if err != nil { + return + } + _, _, e1 := syscall_syscall6(libc_mount_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(flags), uintptr(data), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_mount_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mount mount "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Nanosleep(time *Timespec, leftover *Timespec) (err error) { _, _, e1 := syscall_syscall(libc_nanosleep_trampoline_addr, uintptr(unsafe.Pointer(time)), uintptr(unsafe.Pointer(leftover)), 0) if e1 != 0 { diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm64.s b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm64.s index f77d53212..2af3b5c76 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm64.s +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm64.s @@ -463,6 +463,11 @@ TEXT libc_mknodat_trampoline<>(SB),NOSPLIT,$0-0 GLOBL ·libc_mknodat_trampoline_addr(SB), RODATA, $8 DATA ·libc_mknodat_trampoline_addr(SB)/8, $libc_mknodat_trampoline<>(SB) +TEXT libc_mount_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_mount(SB) +GLOBL ·libc_mount_trampoline_addr(SB), RODATA, $8 +DATA ·libc_mount_trampoline_addr(SB)/8, $libc_mount_trampoline<>(SB) + TEXT libc_nanosleep_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_nanosleep(SB) GLOBL ·libc_nanosleep_trampoline_addr(SB), RODATA, $8 diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsyscall_openbsd_mips64.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsyscall_openbsd_mips64.go index e62963e67..1da08d526 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsyscall_openbsd_mips64.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsyscall_openbsd_mips64.go @@ -1493,6 +1493,30 @@ var libc_mknodat_trampoline_addr uintptr // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Mount(fsType string, dir string, flags int, data unsafe.Pointer) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(fsType) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(dir) + if err != nil { + return + } + _, _, e1 := syscall_syscall6(libc_mount_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(flags), uintptr(data), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_mount_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mount mount "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Nanosleep(time *Timespec, leftover *Timespec) (err error) { _, _, e1 := syscall_syscall(libc_nanosleep_trampoline_addr, uintptr(unsafe.Pointer(time)), uintptr(unsafe.Pointer(leftover)), 0) if e1 != 0 { diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsyscall_openbsd_mips64.s b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsyscall_openbsd_mips64.s index fae140b62..b7a251353 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsyscall_openbsd_mips64.s +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsyscall_openbsd_mips64.s @@ -463,6 +463,11 @@ TEXT libc_mknodat_trampoline<>(SB),NOSPLIT,$0-0 GLOBL ·libc_mknodat_trampoline_addr(SB), RODATA, $8 DATA ·libc_mknodat_trampoline_addr(SB)/8, $libc_mknodat_trampoline<>(SB) +TEXT libc_mount_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_mount(SB) +GLOBL ·libc_mount_trampoline_addr(SB), RODATA, $8 +DATA ·libc_mount_trampoline_addr(SB)/8, $libc_mount_trampoline<>(SB) + TEXT libc_nanosleep_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_nanosleep(SB) GLOBL ·libc_nanosleep_trampoline_addr(SB), RODATA, $8 diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsyscall_openbsd_ppc64.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsyscall_openbsd_ppc64.go index 00831354c..6e85b0aac 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsyscall_openbsd_ppc64.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsyscall_openbsd_ppc64.go @@ -1493,6 +1493,30 @@ var libc_mknodat_trampoline_addr uintptr // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Mount(fsType string, dir string, flags int, data unsafe.Pointer) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(fsType) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(dir) + if err != nil { + return + } + _, _, e1 := syscall_syscall6(libc_mount_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(flags), uintptr(data), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_mount_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mount mount "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Nanosleep(time *Timespec, leftover *Timespec) (err error) { _, _, e1 := syscall_syscall(libc_nanosleep_trampoline_addr, uintptr(unsafe.Pointer(time)), uintptr(unsafe.Pointer(leftover)), 0) if e1 != 0 { diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsyscall_openbsd_ppc64.s b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsyscall_openbsd_ppc64.s index 9d1e0ff06..f15dadf05 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsyscall_openbsd_ppc64.s +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsyscall_openbsd_ppc64.s @@ -555,6 +555,12 @@ TEXT libc_mknodat_trampoline<>(SB),NOSPLIT,$0-0 GLOBL ·libc_mknodat_trampoline_addr(SB), RODATA, $8 DATA ·libc_mknodat_trampoline_addr(SB)/8, $libc_mknodat_trampoline<>(SB) +TEXT libc_mount_trampoline<>(SB),NOSPLIT,$0-0 + CALL libc_mount(SB) + RET +GLOBL ·libc_mount_trampoline_addr(SB), RODATA, $8 +DATA ·libc_mount_trampoline_addr(SB)/8, $libc_mount_trampoline<>(SB) + TEXT libc_nanosleep_trampoline<>(SB),NOSPLIT,$0-0 CALL libc_nanosleep(SB) RET diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsyscall_openbsd_riscv64.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsyscall_openbsd_riscv64.go index 79029ed58..28b487df2 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsyscall_openbsd_riscv64.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsyscall_openbsd_riscv64.go @@ -1493,6 +1493,30 @@ var libc_mknodat_trampoline_addr uintptr // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Mount(fsType string, dir string, flags int, data unsafe.Pointer) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(fsType) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(dir) + if err != nil { + return + } + _, _, e1 := syscall_syscall6(libc_mount_trampoline_addr, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(flags), uintptr(data), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_mount_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_mount mount "libc.so" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Nanosleep(time *Timespec, leftover *Timespec) (err error) { _, _, e1 := syscall_syscall(libc_nanosleep_trampoline_addr, uintptr(unsafe.Pointer(time)), uintptr(unsafe.Pointer(leftover)), 0) if e1 != 0 { diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsyscall_openbsd_riscv64.s b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsyscall_openbsd_riscv64.s index da115f9a4..1e7f321e4 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsyscall_openbsd_riscv64.s +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsyscall_openbsd_riscv64.s @@ -463,6 +463,11 @@ TEXT libc_mknodat_trampoline<>(SB),NOSPLIT,$0-0 GLOBL ·libc_mknodat_trampoline_addr(SB), RODATA, $8 DATA ·libc_mknodat_trampoline_addr(SB)/8, $libc_mknodat_trampoline<>(SB) +TEXT libc_mount_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_mount(SB) +GLOBL ·libc_mount_trampoline_addr(SB), RODATA, $8 +DATA ·libc_mount_trampoline_addr(SB)/8, $libc_mount_trampoline<>(SB) + TEXT libc_nanosleep_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_nanosleep(SB) GLOBL ·libc_nanosleep_trampoline_addr(SB), RODATA, $8 diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsyscall_solaris_amd64.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsyscall_solaris_amd64.go index 829b87feb..c6545413c 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsyscall_solaris_amd64.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsyscall_solaris_amd64.go @@ -141,6 +141,16 @@ import ( //go:cgo_import_dynamic libc_getpeername getpeername "libsocket.so" //go:cgo_import_dynamic libc_setsockopt setsockopt "libsocket.so" //go:cgo_import_dynamic libc_recvfrom recvfrom "libsocket.so" +//go:cgo_import_dynamic libc_getpeerucred getpeerucred "libc.so" +//go:cgo_import_dynamic libc_ucred_get ucred_get "libc.so" +//go:cgo_import_dynamic libc_ucred_geteuid ucred_geteuid "libc.so" +//go:cgo_import_dynamic libc_ucred_getegid ucred_getegid "libc.so" +//go:cgo_import_dynamic libc_ucred_getruid ucred_getruid "libc.so" +//go:cgo_import_dynamic libc_ucred_getrgid ucred_getrgid "libc.so" +//go:cgo_import_dynamic libc_ucred_getsuid ucred_getsuid "libc.so" +//go:cgo_import_dynamic libc_ucred_getsgid ucred_getsgid "libc.so" +//go:cgo_import_dynamic libc_ucred_getpid ucred_getpid "libc.so" +//go:cgo_import_dynamic libc_ucred_free ucred_free "libc.so" //go:cgo_import_dynamic libc_port_create port_create "libc.so" //go:cgo_import_dynamic libc_port_associate port_associate "libc.so" //go:cgo_import_dynamic libc_port_dissociate port_dissociate "libc.so" @@ -280,6 +290,16 @@ import ( //go:linkname procgetpeername libc_getpeername //go:linkname procsetsockopt libc_setsockopt //go:linkname procrecvfrom libc_recvfrom +//go:linkname procgetpeerucred libc_getpeerucred +//go:linkname procucred_get libc_ucred_get +//go:linkname procucred_geteuid libc_ucred_geteuid +//go:linkname procucred_getegid libc_ucred_getegid +//go:linkname procucred_getruid libc_ucred_getruid +//go:linkname procucred_getrgid libc_ucred_getrgid +//go:linkname procucred_getsuid libc_ucred_getsuid +//go:linkname procucred_getsgid libc_ucred_getsgid +//go:linkname procucred_getpid libc_ucred_getpid +//go:linkname procucred_free libc_ucred_free //go:linkname procport_create libc_port_create //go:linkname procport_associate libc_port_associate //go:linkname procport_dissociate libc_port_dissociate @@ -420,6 +440,16 @@ var ( procgetpeername, procsetsockopt, procrecvfrom, + procgetpeerucred, + procucred_get, + procucred_geteuid, + procucred_getegid, + procucred_getruid, + procucred_getrgid, + procucred_getsuid, + procucred_getsgid, + procucred_getpid, + procucred_free, procport_create, procport_associate, procport_dissociate, @@ -2029,6 +2059,90 @@ func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Sockl // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func getpeerucred(fd uintptr, ucred *uintptr) (err error) { + _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procgetpeerucred)), 2, uintptr(fd), uintptr(unsafe.Pointer(ucred)), 0, 0, 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func ucredGet(pid int) (ucred uintptr, err error) { + r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procucred_get)), 1, uintptr(pid), 0, 0, 0, 0, 0) + ucred = uintptr(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func ucredGeteuid(ucred uintptr) (uid int) { + r0, _, _ := sysvicall6(uintptr(unsafe.Pointer(&procucred_geteuid)), 1, uintptr(ucred), 0, 0, 0, 0, 0) + uid = int(r0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func ucredGetegid(ucred uintptr) (gid int) { + r0, _, _ := sysvicall6(uintptr(unsafe.Pointer(&procucred_getegid)), 1, uintptr(ucred), 0, 0, 0, 0, 0) + gid = int(r0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func ucredGetruid(ucred uintptr) (uid int) { + r0, _, _ := sysvicall6(uintptr(unsafe.Pointer(&procucred_getruid)), 1, uintptr(ucred), 0, 0, 0, 0, 0) + uid = int(r0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func ucredGetrgid(ucred uintptr) (gid int) { + r0, _, _ := sysvicall6(uintptr(unsafe.Pointer(&procucred_getrgid)), 1, uintptr(ucred), 0, 0, 0, 0, 0) + gid = int(r0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func ucredGetsuid(ucred uintptr) (uid int) { + r0, _, _ := sysvicall6(uintptr(unsafe.Pointer(&procucred_getsuid)), 1, uintptr(ucred), 0, 0, 0, 0, 0) + uid = int(r0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func ucredGetsgid(ucred uintptr) (gid int) { + r0, _, _ := sysvicall6(uintptr(unsafe.Pointer(&procucred_getsgid)), 1, uintptr(ucred), 0, 0, 0, 0, 0) + gid = int(r0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func ucredGetpid(ucred uintptr) (pid int) { + r0, _, _ := sysvicall6(uintptr(unsafe.Pointer(&procucred_getpid)), 1, uintptr(ucred), 0, 0, 0, 0, 0) + pid = int(r0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func ucredFree(ucred uintptr) { + sysvicall6(uintptr(unsafe.Pointer(&procucred_free)), 1, uintptr(ucred), 0, 0, 0, 0, 0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func port_create() (n int, err error) { r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procport_create)), 0, 0, 0, 0, 0, 0, 0) n = int(r0) diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsyscall_zos_s390x.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsyscall_zos_s390x.go index 94f011238..7ccf66b7e 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsyscall_zos_s390x.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsyscall_zos_s390x.go @@ -1,4 +1,4 @@ -// go run mksyscall.go -tags zos,s390x syscall_zos_s390x.go +// go run mksyscall_zos_s390x.go -o_sysnum zsysnum_zos_s390x.go -o_syscall zsyscall_zos_s390x.go -i_syscall syscall_zos_s390x.go -o_asm zsymaddr_zos_s390x.s // Code generated by the command above; see README.md. DO NOT EDIT. //go:build zos && s390x @@ -6,22 +6,105 @@ package unix import ( + "runtime" + "syscall" "unsafe" ) +var _ syscall.Errno + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func fcntl(fd int, cmd int, arg int) (val int, err error) { - r0, _, e1 := syscall_syscall(SYS_FCNTL, uintptr(fd), uintptr(cmd), uintptr(arg)) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_FCNTL<<4, uintptr(fd), uintptr(cmd), uintptr(arg)) + runtime.ExitSyscall() val = int(r0) - if e1 != 0 { - err = errnoErr(e1) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func impl_Flistxattr(fd int, dest []byte) (sz int, err error) { + var _p0 unsafe.Pointer + if len(dest) > 0 { + _p0 = unsafe.Pointer(&dest[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___FLISTXATTR_A<<4, uintptr(fd), uintptr(_p0), uintptr(len(dest))) + runtime.ExitSyscall() + sz = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_FlistxattrAddr() *(func(fd int, dest []byte) (sz int, err error)) + +var Flistxattr = enter_Flistxattr + +func enter_Flistxattr(fd int, dest []byte) (sz int, err error) { + funcref := get_FlistxattrAddr() + if funcptrtest(GetZosLibVec()+SYS___FLISTXATTR_A<<4, "") == 0 { + *funcref = impl_Flistxattr + } else { + *funcref = error_Flistxattr + } + return (*funcref)(fd, dest) +} + +func error_Flistxattr(fd int, dest []byte) (sz int, err error) { + sz = -1 + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_Fremovexattr(fd int, attr string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(attr) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___FREMOVEXATTR_A<<4, uintptr(fd), uintptr(unsafe.Pointer(_p0))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_FremovexattrAddr() *(func(fd int, attr string) (err error)) + +var Fremovexattr = enter_Fremovexattr + +func enter_Fremovexattr(fd int, attr string) (err error) { + funcref := get_FremovexattrAddr() + if funcptrtest(GetZosLibVec()+SYS___FREMOVEXATTR_A<<4, "") == 0 { + *funcref = impl_Fremovexattr + } else { + *funcref = error_Fremovexattr + } + return (*funcref)(fd, attr) +} + +func error_Fremovexattr(fd int, attr string) (err error) { + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func read(fd int, p []byte) (n int, err error) { var _p0 unsafe.Pointer if len(p) > 0 { @@ -29,10 +112,12 @@ func read(fd int, p []byte) (n int, err error) { } else { _p0 = unsafe.Pointer(&_zero) } - r0, _, e1 := syscall_syscall(SYS_READ, uintptr(fd), uintptr(_p0), uintptr(len(p))) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_READ<<4, uintptr(fd), uintptr(_p0), uintptr(len(p))) + runtime.ExitSyscall() n = int(r0) - if e1 != 0 { - err = errnoErr(e1) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -46,31 +131,159 @@ func write(fd int, p []byte) (n int, err error) { } else { _p0 = unsafe.Pointer(&_zero) } - r0, _, e1 := syscall_syscall(SYS_WRITE, uintptr(fd), uintptr(_p0), uintptr(len(p))) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_WRITE<<4, uintptr(fd), uintptr(_p0), uintptr(len(p))) + runtime.ExitSyscall() n = int(r0) - if e1 != 0 { - err = errnoErr(e1) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func impl_Fgetxattr(fd int, attr string, dest []byte) (sz int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(attr) + if err != nil { + return + } + var _p1 unsafe.Pointer + if len(dest) > 0 { + _p1 = unsafe.Pointer(&dest[0]) + } else { + _p1 = unsafe.Pointer(&_zero) + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___FGETXATTR_A<<4, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(dest))) + runtime.ExitSyscall() + sz = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_FgetxattrAddr() *(func(fd int, attr string, dest []byte) (sz int, err error)) + +var Fgetxattr = enter_Fgetxattr + +func enter_Fgetxattr(fd int, attr string, dest []byte) (sz int, err error) { + funcref := get_FgetxattrAddr() + if funcptrtest(GetZosLibVec()+SYS___FGETXATTR_A<<4, "") == 0 { + *funcref = impl_Fgetxattr + } else { + *funcref = error_Fgetxattr + } + return (*funcref)(fd, attr, dest) +} + +func error_Fgetxattr(fd int, attr string, dest []byte) (sz int, err error) { + sz = -1 + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_Fsetxattr(fd int, attr string, data []byte, flag int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(attr) + if err != nil { + return + } + var _p1 unsafe.Pointer + if len(data) > 0 { + _p1 = unsafe.Pointer(&data[0]) + } else { + _p1 = unsafe.Pointer(&_zero) + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___FSETXATTR_A<<4, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(data)), uintptr(flag)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_FsetxattrAddr() *(func(fd int, attr string, data []byte, flag int) (err error)) + +var Fsetxattr = enter_Fsetxattr + +func enter_Fsetxattr(fd int, attr string, data []byte, flag int) (err error) { + funcref := get_FsetxattrAddr() + if funcptrtest(GetZosLibVec()+SYS___FSETXATTR_A<<4, "") == 0 { + *funcref = impl_Fsetxattr + } else { + *funcref = error_Fsetxattr + } + return (*funcref)(fd, attr, data, flag) +} + +func error_Fsetxattr(fd int, attr string, data []byte, flag int) (err error) { + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) { - r0, _, e1 := syscall_syscall(SYS___ACCEPT_A, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___ACCEPT_A<<4, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) + runtime.ExitSyscall() fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func impl_accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___ACCEPT4_A<<4, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), uintptr(flags)) + runtime.ExitSyscall() + fd = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_accept4Addr() *(func(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error)) + +var accept4 = enter_accept4 + +func enter_accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error) { + funcref := get_accept4Addr() + if funcptrtest(GetZosLibVec()+SYS___ACCEPT4_A<<4, "") == 0 { + *funcref = impl_accept4 + } else { + *funcref = error_accept4 + } + return (*funcref)(s, rsa, addrlen, flags) +} + +func error_accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error) { + fd = -1 + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) { - _, _, e1 := syscall_syscall(SYS___BIND_A, uintptr(s), uintptr(addr), uintptr(addrlen)) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___BIND_A<<4, uintptr(s), uintptr(addr), uintptr(addrlen)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -78,9 +291,11 @@ func bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) { - _, _, e1 := syscall_syscall(SYS___CONNECT_A, uintptr(s), uintptr(addr), uintptr(addrlen)) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___CONNECT_A<<4, uintptr(s), uintptr(addr), uintptr(addrlen)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -88,10 +303,10 @@ func connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func getgroups(n int, list *_Gid_t) (nn int, err error) { - r0, _, e1 := syscall_rawsyscall(SYS_GETGROUPS, uintptr(n), uintptr(unsafe.Pointer(list)), 0) + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_GETGROUPS<<4, uintptr(n), uintptr(unsafe.Pointer(list))) nn = int(r0) - if e1 != 0 { - err = errnoErr(e1) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -99,9 +314,9 @@ func getgroups(n int, list *_Gid_t) (nn int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func setgroups(n int, list *_Gid_t) (err error) { - _, _, e1 := syscall_rawsyscall(SYS_SETGROUPS, uintptr(n), uintptr(unsafe.Pointer(list)), 0) - if e1 != 0 { - err = errnoErr(e1) + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_SETGROUPS<<4, uintptr(n), uintptr(unsafe.Pointer(list))) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -109,9 +324,11 @@ func setgroups(n int, list *_Gid_t) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen) (err error) { - _, _, e1 := syscall_syscall6(SYS_GETSOCKOPT, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(unsafe.Pointer(vallen)), 0) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_GETSOCKOPT<<4, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(unsafe.Pointer(vallen))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -119,9 +336,11 @@ func getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) (err error) { - _, _, e1 := syscall_syscall6(SYS_SETSOCKOPT, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(vallen), 0) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_SETSOCKOPT<<4, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(vallen)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -129,10 +348,10 @@ func setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func socket(domain int, typ int, proto int) (fd int, err error) { - r0, _, e1 := syscall_rawsyscall(SYS_SOCKET, uintptr(domain), uintptr(typ), uintptr(proto)) + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_SOCKET<<4, uintptr(domain), uintptr(typ), uintptr(proto)) fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -140,9 +359,9 @@ func socket(domain int, typ int, proto int) (fd int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) { - _, _, e1 := syscall_rawsyscall6(SYS_SOCKETPAIR, uintptr(domain), uintptr(typ), uintptr(proto), uintptr(unsafe.Pointer(fd)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_SOCKETPAIR<<4, uintptr(domain), uintptr(typ), uintptr(proto), uintptr(unsafe.Pointer(fd))) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -150,9 +369,9 @@ func socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) { - _, _, e1 := syscall_rawsyscall(SYS___GETPEERNAME_A, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) - if e1 != 0 { - err = errnoErr(e1) + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___GETPEERNAME_A<<4, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -160,15 +379,57 @@ func getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) { - _, _, e1 := syscall_rawsyscall(SYS___GETSOCKNAME_A, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) - if e1 != 0 { - err = errnoErr(e1) + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___GETSOCKNAME_A<<4, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func impl_Removexattr(path string, attr string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(attr) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___REMOVEXATTR_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_RemovexattrAddr() *(func(path string, attr string) (err error)) + +var Removexattr = enter_Removexattr + +func enter_Removexattr(path string, attr string) (err error) { + funcref := get_RemovexattrAddr() + if funcptrtest(GetZosLibVec()+SYS___REMOVEXATTR_A<<4, "") == 0 { + *funcref = impl_Removexattr + } else { + *funcref = error_Removexattr + } + return (*funcref)(path, attr) +} + +func error_Removexattr(path string, attr string) (err error) { + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error) { var _p0 unsafe.Pointer if len(p) > 0 { @@ -176,10 +437,12 @@ func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Sockl } else { _p0 = unsafe.Pointer(&_zero) } - r0, _, e1 := syscall_syscall6(SYS___RECVFROM_A, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(flags), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen))) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___RECVFROM_A<<4, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(flags), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen))) + runtime.ExitSyscall() n = int(r0) - if e1 != 0 { - err = errnoErr(e1) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -193,9 +456,11 @@ func sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) ( } else { _p0 = unsafe.Pointer(&_zero) } - _, _, e1 := syscall_syscall6(SYS___SENDTO_A, uintptr(s), uintptr(_p0), uintptr(len(buf)), uintptr(flags), uintptr(to), uintptr(addrlen)) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___SENDTO_A<<4, uintptr(s), uintptr(_p0), uintptr(len(buf)), uintptr(flags), uintptr(to), uintptr(addrlen)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -203,10 +468,12 @@ func sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) ( // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func recvmsg(s int, msg *Msghdr, flags int) (n int, err error) { - r0, _, e1 := syscall_syscall(SYS___RECVMSG_A, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags)) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___RECVMSG_A<<4, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags)) + runtime.ExitSyscall() n = int(r0) - if e1 != 0 { - err = errnoErr(e1) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -214,10 +481,12 @@ func recvmsg(s int, msg *Msghdr, flags int) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func sendmsg(s int, msg *Msghdr, flags int) (n int, err error) { - r0, _, e1 := syscall_syscall(SYS___SENDMSG_A, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags)) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___SENDMSG_A<<4, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags)) + runtime.ExitSyscall() n = int(r0) - if e1 != 0 { - err = errnoErr(e1) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -225,10 +494,12 @@ func sendmsg(s int, msg *Msghdr, flags int) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error) { - r0, _, e1 := syscall_syscall6(SYS_MMAP, uintptr(addr), uintptr(length), uintptr(prot), uintptr(flag), uintptr(fd), uintptr(pos)) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_MMAP<<4, uintptr(addr), uintptr(length), uintptr(prot), uintptr(flag), uintptr(fd), uintptr(pos)) + runtime.ExitSyscall() ret = uintptr(r0) - if e1 != 0 { - err = errnoErr(e1) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -236,9 +507,11 @@ func mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) ( // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func munmap(addr uintptr, length uintptr) (err error) { - _, _, e1 := syscall_syscall(SYS_MUNMAP, uintptr(addr), uintptr(length), 0) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_MUNMAP<<4, uintptr(addr), uintptr(length)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -246,9 +519,11 @@ func munmap(addr uintptr, length uintptr) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func ioctl(fd int, req int, arg uintptr) (err error) { - _, _, e1 := syscall_syscall(SYS_IOCTL, uintptr(fd), uintptr(req), uintptr(arg)) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_IOCTL<<4, uintptr(fd), uintptr(req), uintptr(arg)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -256,9 +531,62 @@ func ioctl(fd int, req int, arg uintptr) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func ioctlPtr(fd int, req int, arg unsafe.Pointer) (err error) { - _, _, e1 := syscall_syscall(SYS_IOCTL, uintptr(fd), uintptr(req), uintptr(arg)) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_IOCTL<<4, uintptr(fd), uintptr(req), uintptr(arg)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func shmat(id int, addr uintptr, flag int) (ret uintptr, err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_SHMAT<<4, uintptr(id), uintptr(addr), uintptr(flag)) + runtime.ExitSyscall() + ret = uintptr(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func shmctl(id int, cmd int, buf *SysvShmDesc) (result int, err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_SHMCTL64<<4, uintptr(id), uintptr(cmd), uintptr(unsafe.Pointer(buf))) + runtime.ExitSyscall() + result = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func shmdt(addr uintptr) (err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_SHMDT<<4, uintptr(addr)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func shmget(key int, size int, flag int) (id int, err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_SHMGET<<4, uintptr(key), uintptr(size), uintptr(flag)) + runtime.ExitSyscall() + id = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -271,9 +599,11 @@ func Access(path string, mode uint32) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall(SYS___ACCESS_A, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___ACCESS_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(mode)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -286,9 +616,11 @@ func Chdir(path string) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall(SYS___CHDIR_A, uintptr(unsafe.Pointer(_p0)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___CHDIR_A<<4, uintptr(unsafe.Pointer(_p0))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -301,9 +633,11 @@ func Chown(path string, uid int, gid int) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall(SYS___CHOWN_A, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid)) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___CHOWN_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -316,9 +650,11 @@ func Chmod(path string, mode uint32) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall(SYS___CHMOD_A, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___CHMOD_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(mode)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -331,10 +667,12 @@ func Creat(path string, mode uint32) (fd int, err error) { if err != nil { return } - r0, _, e1 := syscall_syscall(SYS___CREAT_A, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___CREAT_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(mode)) + runtime.ExitSyscall() fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -342,10 +680,12 @@ func Creat(path string, mode uint32) (fd int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Dup(oldfd int) (fd int, err error) { - r0, _, e1 := syscall_syscall(SYS_DUP, uintptr(oldfd), 0, 0) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_DUP<<4, uintptr(oldfd)) + runtime.ExitSyscall() fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -353,42 +693,359 @@ func Dup(oldfd int) (fd int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Dup2(oldfd int, newfd int) (err error) { - _, _, e1 := syscall_syscall(SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_DUP2<<4, uintptr(oldfd), uintptr(newfd)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Errno2() (er2 int) { - uer2, _, _ := syscall_syscall(SYS___ERRNO2, 0, 0, 0) - er2 = int(uer2) +func impl_Dup3(oldfd int, newfd int, flags int) (err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_DUP3<<4, uintptr(oldfd), uintptr(newfd), uintptr(flags)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_Dup3Addr() *(func(oldfd int, newfd int, flags int) (err error)) + +var Dup3 = enter_Dup3 + +func enter_Dup3(oldfd int, newfd int, flags int) (err error) { + funcref := get_Dup3Addr() + if funcptrtest(GetZosLibVec()+SYS_DUP3<<4, "") == 0 { + *funcref = impl_Dup3 + } else { + *funcref = error_Dup3 + } + return (*funcref)(oldfd, newfd, flags) +} + +func error_Dup3(oldfd int, newfd int, flags int) (err error) { + err = ENOSYS return } // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Err2ad() (eadd *int) { - ueadd, _, _ := syscall_syscall(SYS___ERR2AD, 0, 0, 0) - eadd = (*int)(unsafe.Pointer(ueadd)) +func impl_Dirfd(dirp uintptr) (fd int, err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_DIRFD<<4, uintptr(dirp)) + runtime.ExitSyscall() + fd = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_DirfdAddr() *(func(dirp uintptr) (fd int, err error)) + +var Dirfd = enter_Dirfd + +func enter_Dirfd(dirp uintptr) (fd int, err error) { + funcref := get_DirfdAddr() + if funcptrtest(GetZosLibVec()+SYS_DIRFD<<4, "") == 0 { + *funcref = impl_Dirfd + } else { + *funcref = error_Dirfd + } + return (*funcref)(dirp) +} + +func error_Dirfd(dirp uintptr) (fd int, err error) { + fd = -1 + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_EpollCreate(size int) (fd int, err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_EPOLL_CREATE<<4, uintptr(size)) + runtime.ExitSyscall() + fd = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_EpollCreateAddr() *(func(size int) (fd int, err error)) + +var EpollCreate = enter_EpollCreate + +func enter_EpollCreate(size int) (fd int, err error) { + funcref := get_EpollCreateAddr() + if funcptrtest(GetZosLibVec()+SYS_EPOLL_CREATE<<4, "") == 0 { + *funcref = impl_EpollCreate + } else { + *funcref = error_EpollCreate + } + return (*funcref)(size) +} + +func error_EpollCreate(size int) (fd int, err error) { + fd = -1 + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_EpollCreate1(flags int) (fd int, err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_EPOLL_CREATE1<<4, uintptr(flags)) + runtime.ExitSyscall() + fd = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_EpollCreate1Addr() *(func(flags int) (fd int, err error)) + +var EpollCreate1 = enter_EpollCreate1 + +func enter_EpollCreate1(flags int) (fd int, err error) { + funcref := get_EpollCreate1Addr() + if funcptrtest(GetZosLibVec()+SYS_EPOLL_CREATE1<<4, "") == 0 { + *funcref = impl_EpollCreate1 + } else { + *funcref = error_EpollCreate1 + } + return (*funcref)(flags) +} + +func error_EpollCreate1(flags int) (fd int, err error) { + fd = -1 + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_EpollCtl(epfd int, op int, fd int, event *EpollEvent) (err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_EPOLL_CTL<<4, uintptr(epfd), uintptr(op), uintptr(fd), uintptr(unsafe.Pointer(event))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_EpollCtlAddr() *(func(epfd int, op int, fd int, event *EpollEvent) (err error)) + +var EpollCtl = enter_EpollCtl + +func enter_EpollCtl(epfd int, op int, fd int, event *EpollEvent) (err error) { + funcref := get_EpollCtlAddr() + if funcptrtest(GetZosLibVec()+SYS_EPOLL_CTL<<4, "") == 0 { + *funcref = impl_EpollCtl + } else { + *funcref = error_EpollCtl + } + return (*funcref)(epfd, op, fd, event) +} + +func error_EpollCtl(epfd int, op int, fd int, event *EpollEvent) (err error) { + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_EpollPwait(epfd int, events []EpollEvent, msec int, sigmask *int) (n int, err error) { + var _p0 unsafe.Pointer + if len(events) > 0 { + _p0 = unsafe.Pointer(&events[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_EPOLL_PWAIT<<4, uintptr(epfd), uintptr(_p0), uintptr(len(events)), uintptr(msec), uintptr(unsafe.Pointer(sigmask))) + runtime.ExitSyscall() + n = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_EpollPwaitAddr() *(func(epfd int, events []EpollEvent, msec int, sigmask *int) (n int, err error)) + +var EpollPwait = enter_EpollPwait + +func enter_EpollPwait(epfd int, events []EpollEvent, msec int, sigmask *int) (n int, err error) { + funcref := get_EpollPwaitAddr() + if funcptrtest(GetZosLibVec()+SYS_EPOLL_PWAIT<<4, "") == 0 { + *funcref = impl_EpollPwait + } else { + *funcref = error_EpollPwait + } + return (*funcref)(epfd, events, msec, sigmask) +} + +func error_EpollPwait(epfd int, events []EpollEvent, msec int, sigmask *int) (n int, err error) { + n = -1 + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) { + var _p0 unsafe.Pointer + if len(events) > 0 { + _p0 = unsafe.Pointer(&events[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_EPOLL_WAIT<<4, uintptr(epfd), uintptr(_p0), uintptr(len(events)), uintptr(msec)) + runtime.ExitSyscall() + n = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_EpollWaitAddr() *(func(epfd int, events []EpollEvent, msec int) (n int, err error)) + +var EpollWait = enter_EpollWait + +func enter_EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) { + funcref := get_EpollWaitAddr() + if funcptrtest(GetZosLibVec()+SYS_EPOLL_WAIT<<4, "") == 0 { + *funcref = impl_EpollWait + } else { + *funcref = error_EpollWait + } + return (*funcref)(epfd, events, msec) +} + +func error_EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) { + n = -1 + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Errno2() (er2 int) { + runtime.EnterSyscall() + r0, _, _ := CallLeFuncWithErr(GetZosLibVec() + SYS___ERRNO2<<4) + runtime.ExitSyscall() + er2 = int(r0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_Eventfd(initval uint, flags int) (fd int, err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_EVENTFD<<4, uintptr(initval), uintptr(flags)) + runtime.ExitSyscall() + fd = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_EventfdAddr() *(func(initval uint, flags int) (fd int, err error)) + +var Eventfd = enter_Eventfd + +func enter_Eventfd(initval uint, flags int) (fd int, err error) { + funcref := get_EventfdAddr() + if funcptrtest(GetZosLibVec()+SYS_EVENTFD<<4, "") == 0 { + *funcref = impl_Eventfd + } else { + *funcref = error_Eventfd + } + return (*funcref)(initval, flags) +} + +func error_Eventfd(initval uint, flags int) (fd int, err error) { + fd = -1 + err = ENOSYS return } // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Exit(code int) { - syscall_syscall(SYS_EXIT, uintptr(code), 0, 0) + runtime.EnterSyscall() + CallLeFuncWithErr(GetZosLibVec()+SYS_EXIT<<4, uintptr(code)) + runtime.ExitSyscall() + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_Faccessat(dirfd int, path string, mode uint32, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___FACCESSAT_A<<4, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_FaccessatAddr() *(func(dirfd int, path string, mode uint32, flags int) (err error)) + +var Faccessat = enter_Faccessat + +func enter_Faccessat(dirfd int, path string, mode uint32, flags int) (err error) { + funcref := get_FaccessatAddr() + if funcptrtest(GetZosLibVec()+SYS___FACCESSAT_A<<4, "") == 0 { + *funcref = impl_Faccessat + } else { + *funcref = error_Faccessat + } + return (*funcref)(dirfd, path, mode, flags) +} + +func error_Faccessat(dirfd int, path string, mode uint32, flags int) (err error) { + err = ENOSYS return } // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Fchdir(fd int) (err error) { - _, _, e1 := syscall_syscall(SYS_FCHDIR, uintptr(fd), 0, 0) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_FCHDIR<<4, uintptr(fd)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -396,50 +1053,333 @@ func Fchdir(fd int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Fchmod(fd int, mode uint32) (err error) { - _, _, e1 := syscall_syscall(SYS_FCHMOD, uintptr(fd), uintptr(mode), 0) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_FCHMOD<<4, uintptr(fd), uintptr(mode)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func impl_Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___FCHMODAT_A<<4, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_FchmodatAddr() *(func(dirfd int, path string, mode uint32, flags int) (err error)) + +var Fchmodat = enter_Fchmodat + +func enter_Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) { + funcref := get_FchmodatAddr() + if funcptrtest(GetZosLibVec()+SYS___FCHMODAT_A<<4, "") == 0 { + *funcref = impl_Fchmodat + } else { + *funcref = error_Fchmodat + } + return (*funcref)(dirfd, path, mode, flags) +} + +func error_Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) { + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Fchown(fd int, uid int, gid int) (err error) { - _, _, e1 := syscall_syscall(SYS_FCHOWN, uintptr(fd), uintptr(uid), uintptr(gid)) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_FCHOWN<<4, uintptr(fd), uintptr(uid), uintptr(gid)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func impl_Fchownat(fd int, path string, uid int, gid int, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___FCHOWNAT_A<<4, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid), uintptr(flags)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_FchownatAddr() *(func(fd int, path string, uid int, gid int, flags int) (err error)) + +var Fchownat = enter_Fchownat + +func enter_Fchownat(fd int, path string, uid int, gid int, flags int) (err error) { + funcref := get_FchownatAddr() + if funcptrtest(GetZosLibVec()+SYS___FCHOWNAT_A<<4, "") == 0 { + *funcref = impl_Fchownat + } else { + *funcref = error_Fchownat + } + return (*funcref)(fd, path, uid, gid, flags) +} + +func error_Fchownat(fd int, path string, uid int, gid int, flags int) (err error) { + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func FcntlInt(fd uintptr, cmd int, arg int) (retval int, err error) { - r0, _, e1 := syscall_syscall(SYS_FCNTL, uintptr(fd), uintptr(cmd), uintptr(arg)) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_FCNTL<<4, uintptr(fd), uintptr(cmd), uintptr(arg)) + runtime.ExitSyscall() retval = int(r0) - if e1 != 0 { - err = errnoErr(e1) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func impl_Fdatasync(fd int) (err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_FDATASYNC<<4, uintptr(fd)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_FdatasyncAddr() *(func(fd int) (err error)) + +var Fdatasync = enter_Fdatasync + +func enter_Fdatasync(fd int) (err error) { + funcref := get_FdatasyncAddr() + if funcptrtest(GetZosLibVec()+SYS_FDATASYNC<<4, "") == 0 { + *funcref = impl_Fdatasync + } else { + *funcref = error_Fdatasync + } + return (*funcref)(fd) +} + +func error_Fdatasync(fd int) (err error) { + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func fstat(fd int, stat *Stat_LE_t) (err error) { - _, _, e1 := syscall_syscall(SYS_FSTAT, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_FSTAT<<4, uintptr(fd), uintptr(unsafe.Pointer(stat))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func impl_fstatat(dirfd int, path string, stat *Stat_LE_t, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___FSTATAT_A<<4, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), uintptr(flags)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_fstatatAddr() *(func(dirfd int, path string, stat *Stat_LE_t, flags int) (err error)) + +var fstatat = enter_fstatat + +func enter_fstatat(dirfd int, path string, stat *Stat_LE_t, flags int) (err error) { + funcref := get_fstatatAddr() + if funcptrtest(GetZosLibVec()+SYS___FSTATAT_A<<4, "") == 0 { + *funcref = impl_fstatat + } else { + *funcref = error_fstatat + } + return (*funcref)(dirfd, path, stat, flags) +} + +func error_fstatat(dirfd int, path string, stat *Stat_LE_t, flags int) (err error) { + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_Lgetxattr(link string, attr string, dest []byte) (sz int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(link) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(attr) + if err != nil { + return + } + var _p2 unsafe.Pointer + if len(dest) > 0 { + _p2 = unsafe.Pointer(&dest[0]) + } else { + _p2 = unsafe.Pointer(&_zero) + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___LGETXATTR_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(dest))) + runtime.ExitSyscall() + sz = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_LgetxattrAddr() *(func(link string, attr string, dest []byte) (sz int, err error)) + +var Lgetxattr = enter_Lgetxattr + +func enter_Lgetxattr(link string, attr string, dest []byte) (sz int, err error) { + funcref := get_LgetxattrAddr() + if funcptrtest(GetZosLibVec()+SYS___LGETXATTR_A<<4, "") == 0 { + *funcref = impl_Lgetxattr + } else { + *funcref = error_Lgetxattr + } + return (*funcref)(link, attr, dest) +} + +func error_Lgetxattr(link string, attr string, dest []byte) (sz int, err error) { + sz = -1 + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_Lsetxattr(path string, attr string, data []byte, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(attr) + if err != nil { + return + } + var _p2 unsafe.Pointer + if len(data) > 0 { + _p2 = unsafe.Pointer(&data[0]) + } else { + _p2 = unsafe.Pointer(&_zero) + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___LSETXATTR_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(data)), uintptr(flags)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_LsetxattrAddr() *(func(path string, attr string, data []byte, flags int) (err error)) + +var Lsetxattr = enter_Lsetxattr + +func enter_Lsetxattr(path string, attr string, data []byte, flags int) (err error) { + funcref := get_LsetxattrAddr() + if funcptrtest(GetZosLibVec()+SYS___LSETXATTR_A<<4, "") == 0 { + *funcref = impl_Lsetxattr + } else { + *funcref = error_Lsetxattr + } + return (*funcref)(path, attr, data, flags) +} + +func error_Lsetxattr(path string, attr string, data []byte, flags int) (err error) { + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_Fstatfs(fd int, buf *Statfs_t) (err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_FSTATFS<<4, uintptr(fd), uintptr(unsafe.Pointer(buf))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_FstatfsAddr() *(func(fd int, buf *Statfs_t) (err error)) + +var Fstatfs = enter_Fstatfs + +func enter_Fstatfs(fd int, buf *Statfs_t) (err error) { + funcref := get_FstatfsAddr() + if funcptrtest(GetZosLibVec()+SYS_FSTATFS<<4, "") == 0 { + *funcref = impl_Fstatfs + } else { + *funcref = error_Fstatfs + } + return (*funcref)(fd, buf) +} + +func error_Fstatfs(fd int, buf *Statfs_t) (err error) { + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Fstatvfs(fd int, stat *Statvfs_t) (err error) { - _, _, e1 := syscall_syscall(SYS_FSTATVFS, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_FSTATVFS<<4, uintptr(fd), uintptr(unsafe.Pointer(stat))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -447,28 +1387,461 @@ func Fstatvfs(fd int, stat *Statvfs_t) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Fsync(fd int) (err error) { - _, _, e1 := syscall_syscall(SYS_FSYNC, uintptr(fd), 0, 0) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_FSYNC<<4, uintptr(fd)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func impl_Futimes(fd int, tv []Timeval) (err error) { + var _p0 unsafe.Pointer + if len(tv) > 0 { + _p0 = unsafe.Pointer(&tv[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_FUTIMES<<4, uintptr(fd), uintptr(_p0), uintptr(len(tv))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_FutimesAddr() *(func(fd int, tv []Timeval) (err error)) + +var Futimes = enter_Futimes + +func enter_Futimes(fd int, tv []Timeval) (err error) { + funcref := get_FutimesAddr() + if funcptrtest(GetZosLibVec()+SYS_FUTIMES<<4, "") == 0 { + *funcref = impl_Futimes + } else { + *funcref = error_Futimes + } + return (*funcref)(fd, tv) +} + +func error_Futimes(fd int, tv []Timeval) (err error) { + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_Futimesat(dirfd int, path string, tv []Timeval) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + var _p1 unsafe.Pointer + if len(tv) > 0 { + _p1 = unsafe.Pointer(&tv[0]) + } else { + _p1 = unsafe.Pointer(&_zero) + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___FUTIMESAT_A<<4, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(tv))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_FutimesatAddr() *(func(dirfd int, path string, tv []Timeval) (err error)) + +var Futimesat = enter_Futimesat + +func enter_Futimesat(dirfd int, path string, tv []Timeval) (err error) { + funcref := get_FutimesatAddr() + if funcptrtest(GetZosLibVec()+SYS___FUTIMESAT_A<<4, "") == 0 { + *funcref = impl_Futimesat + } else { + *funcref = error_Futimesat + } + return (*funcref)(dirfd, path, tv) +} + +func error_Futimesat(dirfd int, path string, tv []Timeval) (err error) { + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Ftruncate(fd int, length int64) (err error) { - _, _, e1 := syscall_syscall(SYS_FTRUNCATE, uintptr(fd), uintptr(length), 0) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_FTRUNCATE<<4, uintptr(fd), uintptr(length)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Getpagesize() (pgsize int) { - r0, _, _ := syscall_syscall(SYS_GETPAGESIZE, 0, 0, 0) - pgsize = int(r0) +func impl_Getrandom(buf []byte, flags int) (n int, err error) { + var _p0 unsafe.Pointer + if len(buf) > 0 { + _p0 = unsafe.Pointer(&buf[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_GETRANDOM<<4, uintptr(_p0), uintptr(len(buf)), uintptr(flags)) + runtime.ExitSyscall() + n = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_GetrandomAddr() *(func(buf []byte, flags int) (n int, err error)) + +var Getrandom = enter_Getrandom + +func enter_Getrandom(buf []byte, flags int) (n int, err error) { + funcref := get_GetrandomAddr() + if funcptrtest(GetZosLibVec()+SYS_GETRANDOM<<4, "") == 0 { + *funcref = impl_Getrandom + } else { + *funcref = error_Getrandom + } + return (*funcref)(buf, flags) +} + +func error_Getrandom(buf []byte, flags int) (n int, err error) { + n = -1 + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_InotifyInit() (fd int, err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec() + SYS_INOTIFY_INIT<<4) + runtime.ExitSyscall() + fd = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_InotifyInitAddr() *(func() (fd int, err error)) + +var InotifyInit = enter_InotifyInit + +func enter_InotifyInit() (fd int, err error) { + funcref := get_InotifyInitAddr() + if funcptrtest(GetZosLibVec()+SYS_INOTIFY_INIT<<4, "") == 0 { + *funcref = impl_InotifyInit + } else { + *funcref = error_InotifyInit + } + return (*funcref)() +} + +func error_InotifyInit() (fd int, err error) { + fd = -1 + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_InotifyInit1(flags int) (fd int, err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_INOTIFY_INIT1<<4, uintptr(flags)) + runtime.ExitSyscall() + fd = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_InotifyInit1Addr() *(func(flags int) (fd int, err error)) + +var InotifyInit1 = enter_InotifyInit1 + +func enter_InotifyInit1(flags int) (fd int, err error) { + funcref := get_InotifyInit1Addr() + if funcptrtest(GetZosLibVec()+SYS_INOTIFY_INIT1<<4, "") == 0 { + *funcref = impl_InotifyInit1 + } else { + *funcref = error_InotifyInit1 + } + return (*funcref)(flags) +} + +func error_InotifyInit1(flags int) (fd int, err error) { + fd = -1 + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_InotifyAddWatch(fd int, pathname string, mask uint32) (watchdesc int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(pathname) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___INOTIFY_ADD_WATCH_A<<4, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(mask)) + runtime.ExitSyscall() + watchdesc = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_InotifyAddWatchAddr() *(func(fd int, pathname string, mask uint32) (watchdesc int, err error)) + +var InotifyAddWatch = enter_InotifyAddWatch + +func enter_InotifyAddWatch(fd int, pathname string, mask uint32) (watchdesc int, err error) { + funcref := get_InotifyAddWatchAddr() + if funcptrtest(GetZosLibVec()+SYS___INOTIFY_ADD_WATCH_A<<4, "") == 0 { + *funcref = impl_InotifyAddWatch + } else { + *funcref = error_InotifyAddWatch + } + return (*funcref)(fd, pathname, mask) +} + +func error_InotifyAddWatch(fd int, pathname string, mask uint32) (watchdesc int, err error) { + watchdesc = -1 + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_InotifyRmWatch(fd int, watchdesc uint32) (success int, err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_INOTIFY_RM_WATCH<<4, uintptr(fd), uintptr(watchdesc)) + runtime.ExitSyscall() + success = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_InotifyRmWatchAddr() *(func(fd int, watchdesc uint32) (success int, err error)) + +var InotifyRmWatch = enter_InotifyRmWatch + +func enter_InotifyRmWatch(fd int, watchdesc uint32) (success int, err error) { + funcref := get_InotifyRmWatchAddr() + if funcptrtest(GetZosLibVec()+SYS_INOTIFY_RM_WATCH<<4, "") == 0 { + *funcref = impl_InotifyRmWatch + } else { + *funcref = error_InotifyRmWatch + } + return (*funcref)(fd, watchdesc) +} + +func error_InotifyRmWatch(fd int, watchdesc uint32) (success int, err error) { + success = -1 + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_Listxattr(path string, dest []byte) (sz int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + var _p1 unsafe.Pointer + if len(dest) > 0 { + _p1 = unsafe.Pointer(&dest[0]) + } else { + _p1 = unsafe.Pointer(&_zero) + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___LISTXATTR_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(dest))) + runtime.ExitSyscall() + sz = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_ListxattrAddr() *(func(path string, dest []byte) (sz int, err error)) + +var Listxattr = enter_Listxattr + +func enter_Listxattr(path string, dest []byte) (sz int, err error) { + funcref := get_ListxattrAddr() + if funcptrtest(GetZosLibVec()+SYS___LISTXATTR_A<<4, "") == 0 { + *funcref = impl_Listxattr + } else { + *funcref = error_Listxattr + } + return (*funcref)(path, dest) +} + +func error_Listxattr(path string, dest []byte) (sz int, err error) { + sz = -1 + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_Llistxattr(path string, dest []byte) (sz int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + var _p1 unsafe.Pointer + if len(dest) > 0 { + _p1 = unsafe.Pointer(&dest[0]) + } else { + _p1 = unsafe.Pointer(&_zero) + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___LLISTXATTR_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(dest))) + runtime.ExitSyscall() + sz = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_LlistxattrAddr() *(func(path string, dest []byte) (sz int, err error)) + +var Llistxattr = enter_Llistxattr + +func enter_Llistxattr(path string, dest []byte) (sz int, err error) { + funcref := get_LlistxattrAddr() + if funcptrtest(GetZosLibVec()+SYS___LLISTXATTR_A<<4, "") == 0 { + *funcref = impl_Llistxattr + } else { + *funcref = error_Llistxattr + } + return (*funcref)(path, dest) +} + +func error_Llistxattr(path string, dest []byte) (sz int, err error) { + sz = -1 + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_Lremovexattr(path string, attr string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(attr) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___LREMOVEXATTR_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_LremovexattrAddr() *(func(path string, attr string) (err error)) + +var Lremovexattr = enter_Lremovexattr + +func enter_Lremovexattr(path string, attr string) (err error) { + funcref := get_LremovexattrAddr() + if funcptrtest(GetZosLibVec()+SYS___LREMOVEXATTR_A<<4, "") == 0 { + *funcref = impl_Lremovexattr + } else { + *funcref = error_Lremovexattr + } + return (*funcref)(path, attr) +} + +func error_Lremovexattr(path string, attr string) (err error) { + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_Lutimes(path string, tv []Timeval) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + var _p1 unsafe.Pointer + if len(tv) > 0 { + _p1 = unsafe.Pointer(&tv[0]) + } else { + _p1 = unsafe.Pointer(&_zero) + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___LUTIMES_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(tv))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_LutimesAddr() *(func(path string, tv []Timeval) (err error)) + +var Lutimes = enter_Lutimes + +func enter_Lutimes(path string, tv []Timeval) (err error) { + funcref := get_LutimesAddr() + if funcptrtest(GetZosLibVec()+SYS___LUTIMES_A<<4, "") == 0 { + *funcref = impl_Lutimes + } else { + *funcref = error_Lutimes + } + return (*funcref)(path, tv) +} + +func error_Lutimes(path string, tv []Timeval) (err error) { + err = ENOSYS return } @@ -481,9 +1854,11 @@ func Mprotect(b []byte, prot int) (err error) { } else { _p0 = unsafe.Pointer(&_zero) } - _, _, e1 := syscall_syscall(SYS_MPROTECT, uintptr(_p0), uintptr(len(b)), uintptr(prot)) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_MPROTECT<<4, uintptr(_p0), uintptr(len(b)), uintptr(prot)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -497,9 +1872,23 @@ func Msync(b []byte, flags int) (err error) { } else { _p0 = unsafe.Pointer(&_zero) } - _, _, e1 := syscall_syscall(SYS_MSYNC, uintptr(_p0), uintptr(len(b)), uintptr(flags)) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_MSYNC<<4, uintptr(_p0), uintptr(len(b)), uintptr(flags)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Console2(cmsg *ConsMsg2, modstr *byte, concmd *uint32) (err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___CONSOLE2<<4, uintptr(unsafe.Pointer(cmsg)), uintptr(unsafe.Pointer(modstr)), uintptr(unsafe.Pointer(concmd))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -513,21 +1902,106 @@ func Poll(fds []PollFd, timeout int) (n int, err error) { } else { _p0 = unsafe.Pointer(&_zero) } - r0, _, e1 := syscall_syscall(SYS_POLL, uintptr(_p0), uintptr(len(fds)), uintptr(timeout)) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_POLL<<4, uintptr(_p0), uintptr(len(fds)), uintptr(timeout)) + runtime.ExitSyscall() n = int(r0) - if e1 != 0 { - err = errnoErr(e1) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Readdir_r(dirp uintptr, entry *direntLE, result **direntLE) (err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___READDIR_R_A<<4, uintptr(dirp), uintptr(unsafe.Pointer(entry)), uintptr(unsafe.Pointer(result))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_Statfs(path string, buf *Statfs_t) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___STATFS_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(buf))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_StatfsAddr() *(func(path string, buf *Statfs_t) (err error)) + +var Statfs = enter_Statfs + +func enter_Statfs(path string, buf *Statfs_t) (err error) { + funcref := get_StatfsAddr() + if funcptrtest(GetZosLibVec()+SYS___STATFS_A<<4, "") == 0 { + *funcref = impl_Statfs + } else { + *funcref = error_Statfs + } + return (*funcref)(path, buf) +} + +func error_Statfs(path string, buf *Statfs_t) (err error) { + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_Syncfs(fd int) (err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_SYNCFS<<4, uintptr(fd)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_SyncfsAddr() *(func(fd int) (err error)) + +var Syncfs = enter_Syncfs + +func enter_Syncfs(fd int) (err error) { + funcref := get_SyncfsAddr() + if funcptrtest(GetZosLibVec()+SYS_SYNCFS<<4, "") == 0 { + *funcref = impl_Syncfs + } else { + *funcref = error_Syncfs + } + return (*funcref)(fd) +} + +func error_Syncfs(fd int) (err error) { + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Times(tms *Tms) (ticks uintptr, err error) { - r0, _, e1 := syscall_syscall(SYS_TIMES, uintptr(unsafe.Pointer(tms)), 0, 0) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_TIMES<<4, uintptr(unsafe.Pointer(tms))) + runtime.ExitSyscall() ticks = uintptr(r0) - if e1 != 0 { - err = errnoErr(e1) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -535,10 +2009,12 @@ func Times(tms *Tms) (ticks uintptr, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func W_Getmntent(buff *byte, size int) (lastsys int, err error) { - r0, _, e1 := syscall_syscall(SYS_W_GETMNTENT, uintptr(unsafe.Pointer(buff)), uintptr(size), 0) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_W_GETMNTENT<<4, uintptr(unsafe.Pointer(buff)), uintptr(size)) + runtime.ExitSyscall() lastsys = int(r0) - if e1 != 0 { - err = errnoErr(e1) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -546,10 +2022,12 @@ func W_Getmntent(buff *byte, size int) (lastsys int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func W_Getmntent_A(buff *byte, size int) (lastsys int, err error) { - r0, _, e1 := syscall_syscall(SYS___W_GETMNTENT_A, uintptr(unsafe.Pointer(buff)), uintptr(size), 0) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___W_GETMNTENT_A<<4, uintptr(unsafe.Pointer(buff)), uintptr(size)) + runtime.ExitSyscall() lastsys = int(r0) - if e1 != 0 { - err = errnoErr(e1) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -577,24 +2055,28 @@ func mount_LE(path string, filesystem string, fstype string, mtm uint32, parmlen if err != nil { return } - _, _, e1 := syscall_syscall6(SYS___MOUNT_A, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(unsafe.Pointer(_p2)), uintptr(mtm), uintptr(parmlen), uintptr(unsafe.Pointer(_p3))) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___MOUNT_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(unsafe.Pointer(_p2)), uintptr(mtm), uintptr(parmlen), uintptr(unsafe.Pointer(_p3))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func unmount(filesystem string, mtm int) (err error) { +func unmount_LE(filesystem string, mtm int) (err error) { var _p0 *byte _p0, err = BytePtrFromString(filesystem) if err != nil { return } - _, _, e1 := syscall_syscall(SYS___UMOUNT_A, uintptr(unsafe.Pointer(_p0)), uintptr(mtm), 0) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___UMOUNT_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(mtm)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -607,9 +2089,24 @@ func Chroot(path string) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall(SYS___CHROOT_A, uintptr(unsafe.Pointer(_p0)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___CHROOT_A<<4, uintptr(unsafe.Pointer(_p0))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Select(nmsgsfds int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (ret int, err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_SELECT<<4, uintptr(nmsgsfds), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout))) + runtime.ExitSyscall() + ret = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -617,15 +2114,47 @@ func Chroot(path string) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Uname(buf *Utsname) (err error) { - _, _, e1 := syscall_rawsyscall(SYS___UNAME_A, uintptr(unsafe.Pointer(buf)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_____OSNAME_A<<4, uintptr(unsafe.Pointer(buf))) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func impl_Unshare(flags int) (err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_UNSHARE<<4, uintptr(flags)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_UnshareAddr() *(func(flags int) (err error)) + +var Unshare = enter_Unshare + +func enter_Unshare(flags int) (err error) { + funcref := get_UnshareAddr() + if funcptrtest(GetZosLibVec()+SYS_UNSHARE<<4, "") == 0 { + *funcref = impl_Unshare + } else { + *funcref = error_Unshare + } + return (*funcref)(flags) +} + +func error_Unshare(flags int) (err error) { + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Gethostname(buf []byte) (err error) { var _p0 unsafe.Pointer if len(buf) > 0 { @@ -633,33 +2162,19 @@ func Gethostname(buf []byte) (err error) { } else { _p0 = unsafe.Pointer(&_zero) } - _, _, e1 := syscall_syscall(SYS___GETHOSTNAME_A, uintptr(_p0), uintptr(len(buf)), 0) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___GETHOSTNAME_A<<4, uintptr(_p0), uintptr(len(buf))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Getegid() (egid int) { - r0, _, _ := syscall_rawsyscall(SYS_GETEGID, 0, 0, 0) - egid = int(r0) - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func Geteuid() (uid int) { - r0, _, _ := syscall_rawsyscall(SYS_GETEUID, 0, 0, 0) - uid = int(r0) - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Getgid() (gid int) { - r0, _, _ := syscall_rawsyscall(SYS_GETGID, 0, 0, 0) + r0, _, _ := CallLeFuncWithErr(GetZosLibVec() + SYS_GETGID<<4) gid = int(r0) return } @@ -667,7 +2182,7 @@ func Getgid() (gid int) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getpid() (pid int) { - r0, _, _ := syscall_rawsyscall(SYS_GETPID, 0, 0, 0) + r0, _, _ := CallLeFuncWithErr(GetZosLibVec() + SYS_GETPID<<4) pid = int(r0) return } @@ -675,10 +2190,10 @@ func Getpid() (pid int) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getpgid(pid int) (pgid int, err error) { - r0, _, e1 := syscall_rawsyscall(SYS_GETPGID, uintptr(pid), 0, 0) + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_GETPGID<<4, uintptr(pid)) pgid = int(r0) - if e1 != 0 { - err = errnoErr(e1) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -686,7 +2201,7 @@ func Getpgid(pid int) (pgid int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getppid() (pid int) { - r0, _, _ := syscall_rawsyscall(SYS_GETPPID, 0, 0, 0) + r0, _, _ := CallLeFuncWithErr(GetZosLibVec() + SYS_GETPPID<<4) pid = int(r0) return } @@ -694,10 +2209,12 @@ func Getppid() (pid int) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getpriority(which int, who int) (prio int, err error) { - r0, _, e1 := syscall_syscall(SYS_GETPRIORITY, uintptr(which), uintptr(who), 0) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_GETPRIORITY<<4, uintptr(which), uintptr(who)) + runtime.ExitSyscall() prio = int(r0) - if e1 != 0 { - err = errnoErr(e1) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -705,9 +2222,9 @@ func Getpriority(which int, who int) (prio int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getrlimit(resource int, rlim *Rlimit) (err error) { - _, _, e1 := syscall_rawsyscall(SYS_GETRLIMIT, uintptr(resource), uintptr(unsafe.Pointer(rlim)), 0) - if e1 != 0 { - err = errnoErr(e1) + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_GETRLIMIT<<4, uintptr(resource), uintptr(unsafe.Pointer(rlim))) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -715,20 +2232,40 @@ func Getrlimit(resource int, rlim *Rlimit) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func getrusage(who int, rusage *rusage_zos) (err error) { - _, _, e1 := syscall_rawsyscall(SYS_GETRUSAGE, uintptr(who), uintptr(unsafe.Pointer(rusage)), 0) - if e1 != 0 { - err = errnoErr(e1) + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_GETRUSAGE<<4, uintptr(who), uintptr(unsafe.Pointer(rusage))) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Getegid() (egid int) { + runtime.EnterSyscall() + r0, _, _ := CallLeFuncWithErr(GetZosLibVec() + SYS_GETEGID<<4) + runtime.ExitSyscall() + egid = int(r0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Geteuid() (euid int) { + runtime.EnterSyscall() + r0, _, _ := CallLeFuncWithErr(GetZosLibVec() + SYS_GETEUID<<4) + runtime.ExitSyscall() + euid = int(r0) + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Getsid(pid int) (sid int, err error) { - r0, _, e1 := syscall_rawsyscall(SYS_GETSID, uintptr(pid), 0, 0) + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_GETSID<<4, uintptr(pid)) sid = int(r0) - if e1 != 0 { - err = errnoErr(e1) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -736,7 +2273,7 @@ func Getsid(pid int) (sid int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Getuid() (uid int) { - r0, _, _ := syscall_rawsyscall(SYS_GETUID, 0, 0, 0) + r0, _, _ := CallLeFuncWithErr(GetZosLibVec() + SYS_GETUID<<4) uid = int(r0) return } @@ -744,9 +2281,9 @@ func Getuid() (uid int) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Kill(pid int, sig Signal) (err error) { - _, _, e1 := syscall_rawsyscall(SYS_KILL, uintptr(pid), uintptr(sig), 0) - if e1 != 0 { - err = errnoErr(e1) + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_KILL<<4, uintptr(pid), uintptr(sig)) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -759,9 +2296,11 @@ func Lchown(path string, uid int, gid int) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall(SYS___LCHOWN_A, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid)) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___LCHOWN_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -779,19 +2318,65 @@ func Link(path string, link string) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall(SYS___LINK_A, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___LINK_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func impl_Linkat(oldDirFd int, oldPath string, newDirFd int, newPath string, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(oldPath) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(newPath) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___LINKAT_A<<4, uintptr(oldDirFd), uintptr(unsafe.Pointer(_p0)), uintptr(newDirFd), uintptr(unsafe.Pointer(_p1)), uintptr(flags)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_LinkatAddr() *(func(oldDirFd int, oldPath string, newDirFd int, newPath string, flags int) (err error)) + +var Linkat = enter_Linkat + +func enter_Linkat(oldDirFd int, oldPath string, newDirFd int, newPath string, flags int) (err error) { + funcref := get_LinkatAddr() + if funcptrtest(GetZosLibVec()+SYS___LINKAT_A<<4, "") == 0 { + *funcref = impl_Linkat + } else { + *funcref = error_Linkat + } + return (*funcref)(oldDirFd, oldPath, newDirFd, newPath, flags) +} + +func error_Linkat(oldDirFd int, oldPath string, newDirFd int, newPath string, flags int) (err error) { + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Listen(s int, n int) (err error) { - _, _, e1 := syscall_syscall(SYS_LISTEN, uintptr(s), uintptr(n), 0) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_LISTEN<<4, uintptr(s), uintptr(n)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -804,9 +2389,11 @@ func lstat(path string, stat *Stat_LE_t) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall(SYS___LSTAT_A, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___LSTAT_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -819,24 +2406,65 @@ func Mkdir(path string, mode uint32) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall(SYS___MKDIR_A, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___MKDIR_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(mode)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func impl_Mkdirat(dirfd int, path string, mode uint32) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___MKDIRAT_A<<4, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_MkdiratAddr() *(func(dirfd int, path string, mode uint32) (err error)) + +var Mkdirat = enter_Mkdirat + +func enter_Mkdirat(dirfd int, path string, mode uint32) (err error) { + funcref := get_MkdiratAddr() + if funcptrtest(GetZosLibVec()+SYS___MKDIRAT_A<<4, "") == 0 { + *funcref = impl_Mkdirat + } else { + *funcref = error_Mkdirat + } + return (*funcref)(dirfd, path, mode) +} + +func error_Mkdirat(dirfd int, path string, mode uint32) (err error) { + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Mkfifo(path string, mode uint32) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) if err != nil { return } - _, _, e1 := syscall_syscall(SYS___MKFIFO_A, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___MKFIFO_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(mode)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -849,15 +2477,96 @@ func Mknod(path string, mode uint32, dev int) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall(SYS___MKNOD_A, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev)) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___MKNOD_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func impl_Mknodat(dirfd int, path string, mode uint32, dev int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___MKNODAT_A<<4, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_MknodatAddr() *(func(dirfd int, path string, mode uint32, dev int) (err error)) + +var Mknodat = enter_Mknodat + +func enter_Mknodat(dirfd int, path string, mode uint32, dev int) (err error) { + funcref := get_MknodatAddr() + if funcptrtest(GetZosLibVec()+SYS___MKNODAT_A<<4, "") == 0 { + *funcref = impl_Mknodat + } else { + *funcref = error_Mknodat + } + return (*funcref)(dirfd, path, mode, dev) +} + +func error_Mknodat(dirfd int, path string, mode uint32, dev int) (err error) { + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_PivotRoot(newroot string, oldroot string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(newroot) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(oldroot) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___PIVOT_ROOT_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_PivotRootAddr() *(func(newroot string, oldroot string) (err error)) + +var PivotRoot = enter_PivotRoot + +func enter_PivotRoot(newroot string, oldroot string) (err error) { + funcref := get_PivotRootAddr() + if funcptrtest(GetZosLibVec()+SYS___PIVOT_ROOT_A<<4, "") == 0 { + *funcref = impl_PivotRoot + } else { + *funcref = error_PivotRoot + } + return (*funcref)(newroot, oldroot) +} + +func error_PivotRoot(newroot string, oldroot string) (err error) { + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Pread(fd int, p []byte, offset int64) (n int, err error) { var _p0 unsafe.Pointer if len(p) > 0 { @@ -865,10 +2574,12 @@ func Pread(fd int, p []byte, offset int64) (n int, err error) { } else { _p0 = unsafe.Pointer(&_zero) } - r0, _, e1 := syscall_syscall6(SYS_PREAD, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), 0, 0) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_PREAD<<4, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset)) + runtime.ExitSyscall() n = int(r0) - if e1 != 0 { - err = errnoErr(e1) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -882,36 +2593,78 @@ func Pwrite(fd int, p []byte, offset int64) (n int, err error) { } else { _p0 = unsafe.Pointer(&_zero) } - r0, _, e1 := syscall_syscall6(SYS_PWRITE, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), 0, 0) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_PWRITE<<4, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset)) + runtime.ExitSyscall() n = int(r0) - if e1 != 0 { - err = errnoErr(e1) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Readlink(path string, buf []byte) (n int, err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return +func impl_Prctl(option int, arg2 uintptr, arg3 uintptr, arg4 uintptr, arg5 uintptr) (err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___PRCTL_A<<4, uintptr(option), uintptr(arg2), uintptr(arg3), uintptr(arg4), uintptr(arg5)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } - var _p1 unsafe.Pointer - if len(buf) > 0 { - _p1 = unsafe.Pointer(&buf[0]) + return +} + +//go:nosplit +func get_PrctlAddr() *(func(option int, arg2 uintptr, arg3 uintptr, arg4 uintptr, arg5 uintptr) (err error)) + +var Prctl = enter_Prctl + +func enter_Prctl(option int, arg2 uintptr, arg3 uintptr, arg4 uintptr, arg5 uintptr) (err error) { + funcref := get_PrctlAddr() + if funcptrtest(GetZosLibVec()+SYS___PRCTL_A<<4, "") == 0 { + *funcref = impl_Prctl } else { - _p1 = unsafe.Pointer(&_zero) + *funcref = error_Prctl } - r0, _, e1 := syscall_syscall(SYS___READLINK_A, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf))) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) + return (*funcref)(option, arg2, arg3, arg4, arg5) +} + +func error_Prctl(option int, arg2 uintptr, arg3 uintptr, arg4 uintptr, arg5 uintptr) (err error) { + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_Prlimit(pid int, resource int, newlimit *Rlimit, old *Rlimit) (err error) { + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_PRLIMIT<<4, uintptr(pid), uintptr(resource), uintptr(unsafe.Pointer(newlimit)), uintptr(unsafe.Pointer(old))) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } +//go:nosplit +func get_PrlimitAddr() *(func(pid int, resource int, newlimit *Rlimit, old *Rlimit) (err error)) + +var Prlimit = enter_Prlimit + +func enter_Prlimit(pid int, resource int, newlimit *Rlimit, old *Rlimit) (err error) { + funcref := get_PrlimitAddr() + if funcptrtest(GetZosLibVec()+SYS_PRLIMIT<<4, "") == 0 { + *funcref = impl_Prlimit + } else { + *funcref = error_Prlimit + } + return (*funcref)(pid, resource, newlimit, old) +} + +func error_Prlimit(pid int, resource int, newlimit *Rlimit, old *Rlimit) (err error) { + err = ENOSYS + return +} + // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Rename(from string, to string) (err error) { @@ -925,24 +2678,112 @@ func Rename(from string, to string) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall(SYS___RENAME_A, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___RENAME_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func impl_Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(oldpath) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(newpath) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___RENAMEAT_A<<4, uintptr(olddirfd), uintptr(unsafe.Pointer(_p0)), uintptr(newdirfd), uintptr(unsafe.Pointer(_p1))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_RenameatAddr() *(func(olddirfd int, oldpath string, newdirfd int, newpath string) (err error)) + +var Renameat = enter_Renameat + +func enter_Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error) { + funcref := get_RenameatAddr() + if funcptrtest(GetZosLibVec()+SYS___RENAMEAT_A<<4, "") == 0 { + *funcref = impl_Renameat + } else { + *funcref = error_Renameat + } + return (*funcref)(olddirfd, oldpath, newdirfd, newpath) +} + +func error_Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error) { + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_Renameat2(olddirfd int, oldpath string, newdirfd int, newpath string, flags uint) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(oldpath) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(newpath) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___RENAMEAT2_A<<4, uintptr(olddirfd), uintptr(unsafe.Pointer(_p0)), uintptr(newdirfd), uintptr(unsafe.Pointer(_p1)), uintptr(flags)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_Renameat2Addr() *(func(olddirfd int, oldpath string, newdirfd int, newpath string, flags uint) (err error)) + +var Renameat2 = enter_Renameat2 + +func enter_Renameat2(olddirfd int, oldpath string, newdirfd int, newpath string, flags uint) (err error) { + funcref := get_Renameat2Addr() + if funcptrtest(GetZosLibVec()+SYS___RENAMEAT2_A<<4, "") == 0 { + *funcref = impl_Renameat2 + } else { + *funcref = error_Renameat2 + } + return (*funcref)(olddirfd, oldpath, newdirfd, newpath, flags) +} + +func error_Renameat2(olddirfd int, oldpath string, newdirfd int, newpath string, flags uint) (err error) { + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Rmdir(path string) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) if err != nil { return } - _, _, e1 := syscall_syscall(SYS___RMDIR_A, uintptr(unsafe.Pointer(_p0)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___RMDIR_A<<4, uintptr(unsafe.Pointer(_p0))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -950,20 +2791,118 @@ func Rmdir(path string) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Seek(fd int, offset int64, whence int) (off int64, err error) { - r0, _, e1 := syscall_syscall(SYS_LSEEK, uintptr(fd), uintptr(offset), uintptr(whence)) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_LSEEK<<4, uintptr(fd), uintptr(offset), uintptr(whence)) + runtime.ExitSyscall() off = int64(r0) - if e1 != 0 { - err = errnoErr(e1) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Setegid(egid int) (err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_SETEGID<<4, uintptr(egid)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Seteuid(euid int) (err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_SETEUID<<4, uintptr(euid)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_Sethostname(p []byte) (err error) { + var _p0 unsafe.Pointer + if len(p) > 0 { + _p0 = unsafe.Pointer(&p[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___SETHOSTNAME_A<<4, uintptr(_p0), uintptr(len(p))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_SethostnameAddr() *(func(p []byte) (err error)) + +var Sethostname = enter_Sethostname + +func enter_Sethostname(p []byte) (err error) { + funcref := get_SethostnameAddr() + if funcptrtest(GetZosLibVec()+SYS___SETHOSTNAME_A<<4, "") == 0 { + *funcref = impl_Sethostname + } else { + *funcref = error_Sethostname + } + return (*funcref)(p) +} + +func error_Sethostname(p []byte) (err error) { + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_Setns(fd int, nstype int) (err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_SETNS<<4, uintptr(fd), uintptr(nstype)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_SetnsAddr() *(func(fd int, nstype int) (err error)) + +var Setns = enter_Setns + +func enter_Setns(fd int, nstype int) (err error) { + funcref := get_SetnsAddr() + if funcptrtest(GetZosLibVec()+SYS_SETNS<<4, "") == 0 { + *funcref = impl_Setns + } else { + *funcref = error_Setns + } + return (*funcref)(fd, nstype) +} + +func error_Setns(fd int, nstype int) (err error) { + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Setpriority(which int, who int, prio int) (err error) { - _, _, e1 := syscall_syscall(SYS_SETPRIORITY, uintptr(which), uintptr(who), uintptr(prio)) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_SETPRIORITY<<4, uintptr(which), uintptr(who), uintptr(prio)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -971,9 +2910,9 @@ func Setpriority(which int, who int, prio int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setpgid(pid int, pgid int) (err error) { - _, _, e1 := syscall_rawsyscall(SYS_SETPGID, uintptr(pid), uintptr(pgid), 0) - if e1 != 0 { - err = errnoErr(e1) + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_SETPGID<<4, uintptr(pid), uintptr(pgid)) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -981,9 +2920,9 @@ func Setpgid(pid int, pgid int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setrlimit(resource int, lim *Rlimit) (err error) { - _, _, e1 := syscall_rawsyscall(SYS_SETRLIMIT, uintptr(resource), uintptr(unsafe.Pointer(lim)), 0) - if e1 != 0 { - err = errnoErr(e1) + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_SETRLIMIT<<4, uintptr(resource), uintptr(unsafe.Pointer(lim))) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -991,9 +2930,9 @@ func Setrlimit(resource int, lim *Rlimit) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setregid(rgid int, egid int) (err error) { - _, _, e1 := syscall_rawsyscall(SYS_SETREGID, uintptr(rgid), uintptr(egid), 0) - if e1 != 0 { - err = errnoErr(e1) + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_SETREGID<<4, uintptr(rgid), uintptr(egid)) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -1001,9 +2940,9 @@ func Setregid(rgid int, egid int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setreuid(ruid int, euid int) (err error) { - _, _, e1 := syscall_rawsyscall(SYS_SETREUID, uintptr(ruid), uintptr(euid), 0) - if e1 != 0 { - err = errnoErr(e1) + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_SETREUID<<4, uintptr(ruid), uintptr(euid)) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -1011,10 +2950,10 @@ func Setreuid(ruid int, euid int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setsid() (pid int, err error) { - r0, _, e1 := syscall_rawsyscall(SYS_SETSID, 0, 0, 0) + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec() + SYS_SETSID<<4) pid = int(r0) - if e1 != 0 { - err = errnoErr(e1) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -1022,9 +2961,11 @@ func Setsid() (pid int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setuid(uid int) (err error) { - _, _, e1 := syscall_syscall(SYS_SETUID, uintptr(uid), 0, 0) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_SETUID<<4, uintptr(uid)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -1032,9 +2973,11 @@ func Setuid(uid int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Setgid(uid int) (err error) { - _, _, e1 := syscall_syscall(SYS_SETGID, uintptr(uid), 0, 0) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_SETGID<<4, uintptr(uid)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -1042,9 +2985,11 @@ func Setgid(uid int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Shutdown(fd int, how int) (err error) { - _, _, e1 := syscall_syscall(SYS_SHUTDOWN, uintptr(fd), uintptr(how), 0) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_SHUTDOWN<<4, uintptr(fd), uintptr(how)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -1057,9 +3002,11 @@ func stat(path string, statLE *Stat_LE_t) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall(SYS___STAT_A, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(statLE)), 0) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___STAT_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(statLE))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -1077,17 +3024,63 @@ func Symlink(path string, link string) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall(SYS___SYMLINK_A, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___SYMLINK_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func impl_Symlinkat(oldPath string, dirfd int, newPath string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(oldPath) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(newPath) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___SYMLINKAT_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(dirfd), uintptr(unsafe.Pointer(_p1))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_SymlinkatAddr() *(func(oldPath string, dirfd int, newPath string) (err error)) + +var Symlinkat = enter_Symlinkat + +func enter_Symlinkat(oldPath string, dirfd int, newPath string) (err error) { + funcref := get_SymlinkatAddr() + if funcptrtest(GetZosLibVec()+SYS___SYMLINKAT_A<<4, "") == 0 { + *funcref = impl_Symlinkat + } else { + *funcref = error_Symlinkat + } + return (*funcref)(oldPath, dirfd, newPath) +} + +func error_Symlinkat(oldPath string, dirfd int, newPath string) (err error) { + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Sync() { - syscall_syscall(SYS_SYNC, 0, 0, 0) + runtime.EnterSyscall() + CallLeFuncWithErr(GetZosLibVec() + SYS_SYNC<<4) + runtime.ExitSyscall() return } @@ -1099,9 +3092,11 @@ func Truncate(path string, length int64) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall(SYS___TRUNCATE_A, uintptr(unsafe.Pointer(_p0)), uintptr(length), 0) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___TRUNCATE_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(length)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -1109,9 +3104,11 @@ func Truncate(path string, length int64) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Tcgetattr(fildes int, termptr *Termios) (err error) { - _, _, e1 := syscall_syscall(SYS_TCGETATTR, uintptr(fildes), uintptr(unsafe.Pointer(termptr)), 0) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_TCGETATTR<<4, uintptr(fildes), uintptr(unsafe.Pointer(termptr))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -1119,9 +3116,11 @@ func Tcgetattr(fildes int, termptr *Termios) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Tcsetattr(fildes int, when int, termptr *Termios) (err error) { - _, _, e1 := syscall_syscall(SYS_TCSETATTR, uintptr(fildes), uintptr(when), uintptr(unsafe.Pointer(termptr))) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_TCSETATTR<<4, uintptr(fildes), uintptr(when), uintptr(unsafe.Pointer(termptr))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -1129,7 +3128,9 @@ func Tcsetattr(fildes int, when int, termptr *Termios) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func Umask(mask int) (oldmask int) { - r0, _, _ := syscall_syscall(SYS_UMASK, uintptr(mask), 0, 0) + runtime.EnterSyscall() + r0, _, _ := CallLeFuncWithErr(GetZosLibVec()+SYS_UMASK<<4, uintptr(mask)) + runtime.ExitSyscall() oldmask = int(r0) return } @@ -1142,24 +3143,65 @@ func Unlink(path string) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall(SYS___UNLINK_A, uintptr(unsafe.Pointer(_p0)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___UNLINK_A<<4, uintptr(unsafe.Pointer(_p0))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func impl_Unlinkat(dirfd int, path string, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___UNLINKAT_A<<4, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_UnlinkatAddr() *(func(dirfd int, path string, flags int) (err error)) + +var Unlinkat = enter_Unlinkat + +func enter_Unlinkat(dirfd int, path string, flags int) (err error) { + funcref := get_UnlinkatAddr() + if funcptrtest(GetZosLibVec()+SYS___UNLINKAT_A<<4, "") == 0 { + *funcref = impl_Unlinkat + } else { + *funcref = error_Unlinkat + } + return (*funcref)(dirfd, path, flags) +} + +func error_Unlinkat(dirfd int, path string, flags int) (err error) { + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Utime(path string, utim *Utimbuf) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) if err != nil { return } - _, _, e1 := syscall_syscall(SYS___UTIME_A, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(utim)), 0) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___UTIME_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(utim))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -1172,25 +3214,119 @@ func open(path string, mode int, perm uint32) (fd int, err error) { if err != nil { return } - r0, _, e1 := syscall_syscall(SYS___OPEN_A, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm)) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___OPEN_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm)) + runtime.ExitSyscall() fd = int(r0) - if e1 != 0 { - err = errnoErr(e1) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func impl_openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___OPENAT_A<<4, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags), uintptr(mode)) + runtime.ExitSyscall() + fd = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_openatAddr() *(func(dirfd int, path string, flags int, mode uint32) (fd int, err error)) + +var openat = enter_openat + +func enter_openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) { + funcref := get_openatAddr() + if funcptrtest(GetZosLibVec()+SYS___OPENAT_A<<4, "") == 0 { + *funcref = impl_openat + } else { + *funcref = error_openat + } + return (*funcref)(dirfd, path, flags, mode) +} + +func error_openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) { + fd = -1 + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func impl_openat2(dirfd int, path string, open_how *OpenHow, size int) (fd int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___OPENAT2_A<<4, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(open_how)), uintptr(size)) + runtime.ExitSyscall() + fd = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_openat2Addr() *(func(dirfd int, path string, open_how *OpenHow, size int) (fd int, err error)) + +var openat2 = enter_openat2 + +func enter_openat2(dirfd int, path string, open_how *OpenHow, size int) (fd int, err error) { + funcref := get_openat2Addr() + if funcptrtest(GetZosLibVec()+SYS___OPENAT2_A<<4, "") == 0 { + *funcref = impl_openat2 + } else { + *funcref = error_openat2 + } + return (*funcref)(dirfd, path, open_how, size) +} + +func error_openat2(dirfd int, path string, open_how *OpenHow, size int) (fd int, err error) { + fd = -1 + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func remove(path string) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) if err != nil { return } - _, _, e1 := syscall_syscall(SYS_REMOVE, uintptr(unsafe.Pointer(_p0)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_REMOVE<<4, uintptr(unsafe.Pointer(_p0))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func waitid(idType int, id int, info *Siginfo, options int) (err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_WAITID<<4, uintptr(idType), uintptr(id), uintptr(unsafe.Pointer(info)), uintptr(options)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -1198,10 +3334,12 @@ func remove(path string) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func waitpid(pid int, wstatus *_C_int, options int) (wpid int, err error) { - r0, _, e1 := syscall_syscall(SYS_WAITPID, uintptr(pid), uintptr(unsafe.Pointer(wstatus)), uintptr(options)) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_WAITPID<<4, uintptr(pid), uintptr(unsafe.Pointer(wstatus)), uintptr(options)) + runtime.ExitSyscall() wpid = int(r0) - if e1 != 0 { - err = errnoErr(e1) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -1209,9 +3347,9 @@ func waitpid(pid int, wstatus *_C_int, options int) (wpid int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func gettimeofday(tv *timeval_zos) (err error) { - _, _, e1 := syscall_rawsyscall(SYS_GETTIMEOFDAY, uintptr(unsafe.Pointer(tv)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_GETTIMEOFDAY<<4, uintptr(unsafe.Pointer(tv))) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -1219,9 +3357,9 @@ func gettimeofday(tv *timeval_zos) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT func pipe(p *[2]_C_int) (err error) { - _, _, e1 := syscall_rawsyscall(SYS_PIPE, uintptr(unsafe.Pointer(p)), 0, 0) - if e1 != 0 { - err = errnoErr(e1) + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_PIPE<<4, uintptr(unsafe.Pointer(p))) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } @@ -1234,20 +3372,87 @@ func utimes(path string, timeval *[2]Timeval) (err error) { if err != nil { return } - _, _, e1 := syscall_syscall(SYS___UTIMES_A, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(timeval)), 0) - if e1 != 0 { - err = errnoErr(e1) + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___UTIMES_A<<4, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(timeval))) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func Select(nmsgsfds int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (ret int, err error) { - r0, _, e1 := syscall_syscall6(SYS_SELECT, uintptr(nmsgsfds), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0) - ret = int(r0) - if e1 != 0 { - err = errnoErr(e1) +func impl_utimensat(dirfd int, path string, ts *[2]Timespec, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS___UTIMENSAT_A<<4, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(ts)), uintptr(flags)) + runtime.ExitSyscall() + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +//go:nosplit +func get_utimensatAddr() *(func(dirfd int, path string, ts *[2]Timespec, flags int) (err error)) + +var utimensat = enter_utimensat + +func enter_utimensat(dirfd int, path string, ts *[2]Timespec, flags int) (err error) { + funcref := get_utimensatAddr() + if funcptrtest(GetZosLibVec()+SYS___UTIMENSAT_A<<4, "") == 0 { + *funcref = impl_utimensat + } else { + *funcref = error_utimensat + } + return (*funcref)(dirfd, path, ts, flags) +} + +func error_utimensat(dirfd int, path string, ts *[2]Timespec, flags int) (err error) { + err = ENOSYS + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Posix_openpt(oflag int) (fd int, err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_POSIX_OPENPT<<4, uintptr(oflag)) + runtime.ExitSyscall() + fd = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Grantpt(fildes int) (rc int, err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_GRANTPT<<4, uintptr(fildes)) + runtime.ExitSyscall() + rc = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Unlockpt(fildes int) (rc int, err error) { + runtime.EnterSyscall() + r0, e2, e1 := CallLeFuncWithErr(GetZosLibVec()+SYS_UNLOCKPT<<4, uintptr(fildes)) + runtime.ExitSyscall() + rc = int(r0) + if int64(r0) == -1 { + err = errnoErr2(e1, e2) } return } diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go index 0cc3ce496..c79aaff30 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go @@ -452,4 +452,14 @@ const ( SYS_FUTEX_WAKE = 454 SYS_FUTEX_WAIT = 455 SYS_FUTEX_REQUEUE = 456 + SYS_STATMOUNT = 457 + SYS_LISTMOUNT = 458 + SYS_LSM_GET_SELF_ATTR = 459 + SYS_LSM_SET_SELF_ATTR = 460 + SYS_LSM_LIST_MODULES = 461 + SYS_MSEAL = 462 + SYS_SETXATTRAT = 463 + SYS_GETXATTRAT = 464 + SYS_LISTXATTRAT = 465 + SYS_REMOVEXATTRAT = 466 ) diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go index 856d92d69..5eb450695 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go @@ -341,6 +341,7 @@ const ( SYS_STATX = 332 SYS_IO_PGETEVENTS = 333 SYS_RSEQ = 334 + SYS_URETPROBE = 335 SYS_PIDFD_SEND_SIGNAL = 424 SYS_IO_URING_SETUP = 425 SYS_IO_URING_ENTER = 426 @@ -374,4 +375,14 @@ const ( SYS_FUTEX_WAKE = 454 SYS_FUTEX_WAIT = 455 SYS_FUTEX_REQUEUE = 456 + SYS_STATMOUNT = 457 + SYS_LISTMOUNT = 458 + SYS_LSM_GET_SELF_ATTR = 459 + SYS_LSM_SET_SELF_ATTR = 460 + SYS_LSM_LIST_MODULES = 461 + SYS_MSEAL = 462 + SYS_SETXATTRAT = 463 + SYS_GETXATTRAT = 464 + SYS_LISTXATTRAT = 465 + SYS_REMOVEXATTRAT = 466 ) diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go index 8d467094c..05e502974 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go @@ -416,4 +416,14 @@ const ( SYS_FUTEX_WAKE = 454 SYS_FUTEX_WAIT = 455 SYS_FUTEX_REQUEUE = 456 + SYS_STATMOUNT = 457 + SYS_LISTMOUNT = 458 + SYS_LSM_GET_SELF_ATTR = 459 + SYS_LSM_SET_SELF_ATTR = 460 + SYS_LSM_LIST_MODULES = 461 + SYS_MSEAL = 462 + SYS_SETXATTRAT = 463 + SYS_GETXATTRAT = 464 + SYS_LISTXATTRAT = 465 + SYS_REMOVEXATTRAT = 466 ) diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go index edc173244..38c53ec51 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go @@ -85,7 +85,7 @@ const ( SYS_SPLICE = 76 SYS_TEE = 77 SYS_READLINKAT = 78 - SYS_FSTATAT = 79 + SYS_NEWFSTATAT = 79 SYS_FSTAT = 80 SYS_SYNC = 81 SYS_FSYNC = 82 @@ -319,4 +319,14 @@ const ( SYS_FUTEX_WAKE = 454 SYS_FUTEX_WAIT = 455 SYS_FUTEX_REQUEUE = 456 + SYS_STATMOUNT = 457 + SYS_LISTMOUNT = 458 + SYS_LSM_GET_SELF_ATTR = 459 + SYS_LSM_SET_SELF_ATTR = 460 + SYS_LSM_LIST_MODULES = 461 + SYS_MSEAL = 462 + SYS_SETXATTRAT = 463 + SYS_GETXATTRAT = 464 + SYS_LISTXATTRAT = 465 + SYS_REMOVEXATTRAT = 466 ) diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsysnum_linux_loong64.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsysnum_linux_loong64.go index 445eba206..31d2e71a1 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsysnum_linux_loong64.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsysnum_linux_loong64.go @@ -84,6 +84,8 @@ const ( SYS_SPLICE = 76 SYS_TEE = 77 SYS_READLINKAT = 78 + SYS_NEWFSTATAT = 79 + SYS_FSTAT = 80 SYS_SYNC = 81 SYS_FSYNC = 82 SYS_FDATASYNC = 83 @@ -313,4 +315,14 @@ const ( SYS_FUTEX_WAKE = 454 SYS_FUTEX_WAIT = 455 SYS_FUTEX_REQUEUE = 456 + SYS_STATMOUNT = 457 + SYS_LISTMOUNT = 458 + SYS_LSM_GET_SELF_ATTR = 459 + SYS_LSM_SET_SELF_ATTR = 460 + SYS_LSM_LIST_MODULES = 461 + SYS_MSEAL = 462 + SYS_SETXATTRAT = 463 + SYS_GETXATTRAT = 464 + SYS_LISTXATTRAT = 465 + SYS_REMOVEXATTRAT = 466 ) diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go index adba01bca..f4184a336 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go @@ -436,4 +436,14 @@ const ( SYS_FUTEX_WAKE = 4454 SYS_FUTEX_WAIT = 4455 SYS_FUTEX_REQUEUE = 4456 + SYS_STATMOUNT = 4457 + SYS_LISTMOUNT = 4458 + SYS_LSM_GET_SELF_ATTR = 4459 + SYS_LSM_SET_SELF_ATTR = 4460 + SYS_LSM_LIST_MODULES = 4461 + SYS_MSEAL = 4462 + SYS_SETXATTRAT = 4463 + SYS_GETXATTRAT = 4464 + SYS_LISTXATTRAT = 4465 + SYS_REMOVEXATTRAT = 4466 ) diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go index 014c4e9c7..05b996227 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go @@ -366,4 +366,14 @@ const ( SYS_FUTEX_WAKE = 5454 SYS_FUTEX_WAIT = 5455 SYS_FUTEX_REQUEUE = 5456 + SYS_STATMOUNT = 5457 + SYS_LISTMOUNT = 5458 + SYS_LSM_GET_SELF_ATTR = 5459 + SYS_LSM_SET_SELF_ATTR = 5460 + SYS_LSM_LIST_MODULES = 5461 + SYS_MSEAL = 5462 + SYS_SETXATTRAT = 5463 + SYS_GETXATTRAT = 5464 + SYS_LISTXATTRAT = 5465 + SYS_REMOVEXATTRAT = 5466 ) diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go index ccc97d74d..43a256e9e 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go @@ -366,4 +366,14 @@ const ( SYS_FUTEX_WAKE = 5454 SYS_FUTEX_WAIT = 5455 SYS_FUTEX_REQUEUE = 5456 + SYS_STATMOUNT = 5457 + SYS_LISTMOUNT = 5458 + SYS_LSM_GET_SELF_ATTR = 5459 + SYS_LSM_SET_SELF_ATTR = 5460 + SYS_LSM_LIST_MODULES = 5461 + SYS_MSEAL = 5462 + SYS_SETXATTRAT = 5463 + SYS_GETXATTRAT = 5464 + SYS_LISTXATTRAT = 5465 + SYS_REMOVEXATTRAT = 5466 ) diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go index ec2b64a95..eea5ddfc2 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go @@ -436,4 +436,14 @@ const ( SYS_FUTEX_WAKE = 4454 SYS_FUTEX_WAIT = 4455 SYS_FUTEX_REQUEUE = 4456 + SYS_STATMOUNT = 4457 + SYS_LISTMOUNT = 4458 + SYS_LSM_GET_SELF_ATTR = 4459 + SYS_LSM_SET_SELF_ATTR = 4460 + SYS_LSM_LIST_MODULES = 4461 + SYS_MSEAL = 4462 + SYS_SETXATTRAT = 4463 + SYS_GETXATTRAT = 4464 + SYS_LISTXATTRAT = 4465 + SYS_REMOVEXATTRAT = 4466 ) diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc.go index 21a839e33..0d777bfbb 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc.go @@ -443,4 +443,14 @@ const ( SYS_FUTEX_WAKE = 454 SYS_FUTEX_WAIT = 455 SYS_FUTEX_REQUEUE = 456 + SYS_STATMOUNT = 457 + SYS_LISTMOUNT = 458 + SYS_LSM_GET_SELF_ATTR = 459 + SYS_LSM_SET_SELF_ATTR = 460 + SYS_LSM_LIST_MODULES = 461 + SYS_MSEAL = 462 + SYS_SETXATTRAT = 463 + SYS_GETXATTRAT = 464 + SYS_LISTXATTRAT = 465 + SYS_REMOVEXATTRAT = 466 ) diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go index c11121ec3..b44636502 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go @@ -415,4 +415,14 @@ const ( SYS_FUTEX_WAKE = 454 SYS_FUTEX_WAIT = 455 SYS_FUTEX_REQUEUE = 456 + SYS_STATMOUNT = 457 + SYS_LISTMOUNT = 458 + SYS_LSM_GET_SELF_ATTR = 459 + SYS_LSM_SET_SELF_ATTR = 460 + SYS_LSM_LIST_MODULES = 461 + SYS_MSEAL = 462 + SYS_SETXATTRAT = 463 + SYS_GETXATTRAT = 464 + SYS_LISTXATTRAT = 465 + SYS_REMOVEXATTRAT = 466 ) diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go index 909b631fc..0c7d21c18 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go @@ -415,4 +415,14 @@ const ( SYS_FUTEX_WAKE = 454 SYS_FUTEX_WAIT = 455 SYS_FUTEX_REQUEUE = 456 + SYS_STATMOUNT = 457 + SYS_LISTMOUNT = 458 + SYS_LSM_GET_SELF_ATTR = 459 + SYS_LSM_SET_SELF_ATTR = 460 + SYS_LSM_LIST_MODULES = 461 + SYS_MSEAL = 462 + SYS_SETXATTRAT = 463 + SYS_GETXATTRAT = 464 + SYS_LISTXATTRAT = 465 + SYS_REMOVEXATTRAT = 466 ) diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go index e49bed16e..840539169 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go @@ -84,7 +84,7 @@ const ( SYS_SPLICE = 76 SYS_TEE = 77 SYS_READLINKAT = 78 - SYS_FSTATAT = 79 + SYS_NEWFSTATAT = 79 SYS_FSTAT = 80 SYS_SYNC = 81 SYS_FSYNC = 82 @@ -320,4 +320,14 @@ const ( SYS_FUTEX_WAKE = 454 SYS_FUTEX_WAIT = 455 SYS_FUTEX_REQUEUE = 456 + SYS_STATMOUNT = 457 + SYS_LISTMOUNT = 458 + SYS_LSM_GET_SELF_ATTR = 459 + SYS_LSM_SET_SELF_ATTR = 460 + SYS_LSM_LIST_MODULES = 461 + SYS_MSEAL = 462 + SYS_SETXATTRAT = 463 + SYS_GETXATTRAT = 464 + SYS_LISTXATTRAT = 465 + SYS_REMOVEXATTRAT = 466 ) diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go index 66017d2d3..fcf1b790d 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go @@ -381,4 +381,14 @@ const ( SYS_FUTEX_WAKE = 454 SYS_FUTEX_WAIT = 455 SYS_FUTEX_REQUEUE = 456 + SYS_STATMOUNT = 457 + SYS_LISTMOUNT = 458 + SYS_LSM_GET_SELF_ATTR = 459 + SYS_LSM_SET_SELF_ATTR = 460 + SYS_LSM_LIST_MODULES = 461 + SYS_MSEAL = 462 + SYS_SETXATTRAT = 463 + SYS_GETXATTRAT = 464 + SYS_LISTXATTRAT = 465 + SYS_REMOVEXATTRAT = 466 ) diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go index 47bab18dc..52d15b5f9 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go @@ -394,4 +394,14 @@ const ( SYS_FUTEX_WAKE = 454 SYS_FUTEX_WAIT = 455 SYS_FUTEX_REQUEUE = 456 + SYS_STATMOUNT = 457 + SYS_LISTMOUNT = 458 + SYS_LSM_GET_SELF_ATTR = 459 + SYS_LSM_SET_SELF_ATTR = 460 + SYS_LSM_LIST_MODULES = 461 + SYS_MSEAL = 462 + SYS_SETXATTRAT = 463 + SYS_GETXATTRAT = 464 + SYS_LISTXATTRAT = 465 + SYS_REMOVEXATTRAT = 466 ) diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsysnum_zos_s390x.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsysnum_zos_s390x.go index b2e308581..5e8c263ca 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsysnum_zos_s390x.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/zsysnum_zos_s390x.go @@ -1,2669 +1,2852 @@ -// Copyright 2020 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. +// go run mksyscall_zos_s390x.go -o_sysnum zsysnum_zos_s390x.go -o_syscall zsyscall_zos_s390x.go -i_syscall syscall_zos_s390x.go -o_asm zsymaddr_zos_s390x.s +// Code generated by the command above; see README.md. DO NOT EDIT. //go:build zos && s390x package unix -// TODO: auto-generate. - const ( - SYS_ACOSD128 = 0xB80 - SYS_ACOSD32 = 0xB7E - SYS_ACOSD64 = 0xB7F - SYS_ACOSHD128 = 0xB83 - SYS_ACOSHD32 = 0xB81 - SYS_ACOSHD64 = 0xB82 - SYS_AIO_FSYNC = 0xC69 - SYS_ASCTIME = 0x0AE - SYS_ASCTIME64 = 0xCD7 - SYS_ASCTIME64_R = 0xCD8 - SYS_ASIND128 = 0xB86 - SYS_ASIND32 = 0xB84 - SYS_ASIND64 = 0xB85 - SYS_ASINHD128 = 0xB89 - SYS_ASINHD32 = 0xB87 - SYS_ASINHD64 = 0xB88 - SYS_ATAN2D128 = 0xB8F - SYS_ATAN2D32 = 0xB8D - SYS_ATAN2D64 = 0xB8E - SYS_ATAND128 = 0xB8C - SYS_ATAND32 = 0xB8A - SYS_ATAND64 = 0xB8B - SYS_ATANHD128 = 0xB92 - SYS_ATANHD32 = 0xB90 - SYS_ATANHD64 = 0xB91 - SYS_BIND2ADDRSEL = 0xD59 - SYS_C16RTOMB = 0xD40 - SYS_C32RTOMB = 0xD41 - SYS_CBRTD128 = 0xB95 - SYS_CBRTD32 = 0xB93 - SYS_CBRTD64 = 0xB94 - SYS_CEILD128 = 0xB98 - SYS_CEILD32 = 0xB96 - SYS_CEILD64 = 0xB97 - SYS_CLEARENV = 0x0C9 - SYS_CLEARERR_UNLOCKED = 0xCA1 - SYS_CLOCK = 0x0AA - SYS_CLOGL = 0xA00 - SYS_CLRMEMF = 0x0BD - SYS_CONJ = 0xA03 - SYS_CONJF = 0xA06 - SYS_CONJL = 0xA09 - SYS_COPYSIGND128 = 0xB9E - SYS_COPYSIGND32 = 0xB9C - SYS_COPYSIGND64 = 0xB9D - SYS_COSD128 = 0xBA1 - SYS_COSD32 = 0xB9F - SYS_COSD64 = 0xBA0 - SYS_COSHD128 = 0xBA4 - SYS_COSHD32 = 0xBA2 - SYS_COSHD64 = 0xBA3 - SYS_CPOW = 0xA0C - SYS_CPOWF = 0xA0F - SYS_CPOWL = 0xA12 - SYS_CPROJ = 0xA15 - SYS_CPROJF = 0xA18 - SYS_CPROJL = 0xA1B - SYS_CREAL = 0xA1E - SYS_CREALF = 0xA21 - SYS_CREALL = 0xA24 - SYS_CSIN = 0xA27 - SYS_CSINF = 0xA2A - SYS_CSINH = 0xA30 - SYS_CSINHF = 0xA33 - SYS_CSINHL = 0xA36 - SYS_CSINL = 0xA2D - SYS_CSNAP = 0x0C5 - SYS_CSQRT = 0xA39 - SYS_CSQRTF = 0xA3C - SYS_CSQRTL = 0xA3F - SYS_CTAN = 0xA42 - SYS_CTANF = 0xA45 - SYS_CTANH = 0xA4B - SYS_CTANHF = 0xA4E - SYS_CTANHL = 0xA51 - SYS_CTANL = 0xA48 - SYS_CTIME = 0x0AB - SYS_CTIME64 = 0xCD9 - SYS_CTIME64_R = 0xCDA - SYS_CTRACE = 0x0C6 - SYS_DIFFTIME = 0x0A7 - SYS_DIFFTIME64 = 0xCDB - SYS_DLADDR = 0xC82 - SYS_DYNALLOC = 0x0C3 - SYS_DYNFREE = 0x0C2 - SYS_ERFCD128 = 0xBAA - SYS_ERFCD32 = 0xBA8 - SYS_ERFCD64 = 0xBA9 - SYS_ERFD128 = 0xBA7 - SYS_ERFD32 = 0xBA5 - SYS_ERFD64 = 0xBA6 - SYS_EXP2D128 = 0xBB0 - SYS_EXP2D32 = 0xBAE - SYS_EXP2D64 = 0xBAF - SYS_EXPD128 = 0xBAD - SYS_EXPD32 = 0xBAB - SYS_EXPD64 = 0xBAC - SYS_EXPM1D128 = 0xBB3 - SYS_EXPM1D32 = 0xBB1 - SYS_EXPM1D64 = 0xBB2 - SYS_FABSD128 = 0xBB6 - SYS_FABSD32 = 0xBB4 - SYS_FABSD64 = 0xBB5 - SYS_FDELREC_UNLOCKED = 0xCA2 - SYS_FDIMD128 = 0xBB9 - SYS_FDIMD32 = 0xBB7 - SYS_FDIMD64 = 0xBB8 - SYS_FDOPEN_UNLOCKED = 0xCFC - SYS_FECLEAREXCEPT = 0xAEA - SYS_FEGETENV = 0xAEB - SYS_FEGETEXCEPTFLAG = 0xAEC - SYS_FEGETROUND = 0xAED - SYS_FEHOLDEXCEPT = 0xAEE - SYS_FEOF_UNLOCKED = 0xCA3 - SYS_FERAISEEXCEPT = 0xAEF - SYS_FERROR_UNLOCKED = 0xCA4 - SYS_FESETENV = 0xAF0 - SYS_FESETEXCEPTFLAG = 0xAF1 - SYS_FESETROUND = 0xAF2 - SYS_FETCHEP = 0x0BF - SYS_FETESTEXCEPT = 0xAF3 - SYS_FEUPDATEENV = 0xAF4 - SYS_FE_DEC_GETROUND = 0xBBA - SYS_FE_DEC_SETROUND = 0xBBB - SYS_FFLUSH_UNLOCKED = 0xCA5 - SYS_FGETC_UNLOCKED = 0xC80 - SYS_FGETPOS64 = 0xCEE - SYS_FGETPOS64_UNLOCKED = 0xCF4 - SYS_FGETPOS_UNLOCKED = 0xCA6 - SYS_FGETS_UNLOCKED = 0xC7C - SYS_FGETWC_UNLOCKED = 0xCA7 - SYS_FGETWS_UNLOCKED = 0xCA8 - SYS_FILENO_UNLOCKED = 0xCA9 - SYS_FLDATA = 0x0C1 - SYS_FLDATA_UNLOCKED = 0xCAA - SYS_FLOCATE_UNLOCKED = 0xCAB - SYS_FLOORD128 = 0xBBE - SYS_FLOORD32 = 0xBBC - SYS_FLOORD64 = 0xBBD - SYS_FMA = 0xA63 - SYS_FMAD128 = 0xBC1 - SYS_FMAD32 = 0xBBF - SYS_FMAD64 = 0xBC0 - SYS_FMAF = 0xA66 - SYS_FMAL = 0xA69 - SYS_FMAX = 0xA6C - SYS_FMAXD128 = 0xBC4 - SYS_FMAXD32 = 0xBC2 - SYS_FMAXD64 = 0xBC3 - SYS_FMAXF = 0xA6F - SYS_FMAXL = 0xA72 - SYS_FMIN = 0xA75 - SYS_FMIND128 = 0xBC7 - SYS_FMIND32 = 0xBC5 - SYS_FMIND64 = 0xBC6 - SYS_FMINF = 0xA78 - SYS_FMINL = 0xA7B - SYS_FMODD128 = 0xBCA - SYS_FMODD32 = 0xBC8 - SYS_FMODD64 = 0xBC9 - SYS_FOPEN64 = 0xD49 - SYS_FOPEN64_UNLOCKED = 0xD4A - SYS_FOPEN_UNLOCKED = 0xCFA - SYS_FPRINTF_UNLOCKED = 0xCAC - SYS_FPUTC_UNLOCKED = 0xC81 - SYS_FPUTS_UNLOCKED = 0xC7E - SYS_FPUTWC_UNLOCKED = 0xCAD - SYS_FPUTWS_UNLOCKED = 0xCAE - SYS_FREAD_NOUPDATE = 0xCEC - SYS_FREAD_NOUPDATE_UNLOCKED = 0xCED - SYS_FREAD_UNLOCKED = 0xC7B - SYS_FREEIFADDRS = 0xCE6 - SYS_FREOPEN64 = 0xD4B - SYS_FREOPEN64_UNLOCKED = 0xD4C - SYS_FREOPEN_UNLOCKED = 0xCFB - SYS_FREXPD128 = 0xBCE - SYS_FREXPD32 = 0xBCC - SYS_FREXPD64 = 0xBCD - SYS_FSCANF_UNLOCKED = 0xCAF - SYS_FSEEK64 = 0xCEF - SYS_FSEEK64_UNLOCKED = 0xCF5 - SYS_FSEEKO64 = 0xCF0 - SYS_FSEEKO64_UNLOCKED = 0xCF6 - SYS_FSEEKO_UNLOCKED = 0xCB1 - SYS_FSEEK_UNLOCKED = 0xCB0 - SYS_FSETPOS64 = 0xCF1 - SYS_FSETPOS64_UNLOCKED = 0xCF7 - SYS_FSETPOS_UNLOCKED = 0xCB3 - SYS_FTELL64 = 0xCF2 - SYS_FTELL64_UNLOCKED = 0xCF8 - SYS_FTELLO64 = 0xCF3 - SYS_FTELLO64_UNLOCKED = 0xCF9 - SYS_FTELLO_UNLOCKED = 0xCB5 - SYS_FTELL_UNLOCKED = 0xCB4 - SYS_FUPDATE = 0x0B5 - SYS_FUPDATE_UNLOCKED = 0xCB7 - SYS_FWIDE_UNLOCKED = 0xCB8 - SYS_FWPRINTF_UNLOCKED = 0xCB9 - SYS_FWRITE_UNLOCKED = 0xC7A - SYS_FWSCANF_UNLOCKED = 0xCBA - SYS_GETDATE64 = 0xD4F - SYS_GETIFADDRS = 0xCE7 - SYS_GETIPV4SOURCEFILTER = 0xC77 - SYS_GETSOURCEFILTER = 0xC79 - SYS_GETSYNTX = 0x0FD - SYS_GETS_UNLOCKED = 0xC7D - SYS_GETTIMEOFDAY64 = 0xD50 - SYS_GETWCHAR_UNLOCKED = 0xCBC - SYS_GETWC_UNLOCKED = 0xCBB - SYS_GMTIME = 0x0B0 - SYS_GMTIME64 = 0xCDC - SYS_GMTIME64_R = 0xCDD - SYS_HYPOTD128 = 0xBD1 - SYS_HYPOTD32 = 0xBCF - SYS_HYPOTD64 = 0xBD0 - SYS_ILOGBD128 = 0xBD4 - SYS_ILOGBD32 = 0xBD2 - SYS_ILOGBD64 = 0xBD3 - SYS_ILOGBF = 0xA7E - SYS_ILOGBL = 0xA81 - SYS_INET6_IS_SRCADDR = 0xD5A - SYS_ISBLANK = 0x0FE - SYS_ISWALNUM = 0x0FF - SYS_LDEXPD128 = 0xBD7 - SYS_LDEXPD32 = 0xBD5 - SYS_LDEXPD64 = 0xBD6 - SYS_LGAMMAD128 = 0xBDA - SYS_LGAMMAD32 = 0xBD8 - SYS_LGAMMAD64 = 0xBD9 - SYS_LIO_LISTIO = 0xC6A - SYS_LLRINT = 0xA84 - SYS_LLRINTD128 = 0xBDD - SYS_LLRINTD32 = 0xBDB - SYS_LLRINTD64 = 0xBDC - SYS_LLRINTF = 0xA87 - SYS_LLRINTL = 0xA8A - SYS_LLROUND = 0xA8D - SYS_LLROUNDD128 = 0xBE0 - SYS_LLROUNDD32 = 0xBDE - SYS_LLROUNDD64 = 0xBDF - SYS_LLROUNDF = 0xA90 - SYS_LLROUNDL = 0xA93 - SYS_LOCALTIM = 0x0B1 - SYS_LOCALTIME = 0x0B1 - SYS_LOCALTIME64 = 0xCDE - SYS_LOCALTIME64_R = 0xCDF - SYS_LOG10D128 = 0xBE6 - SYS_LOG10D32 = 0xBE4 - SYS_LOG10D64 = 0xBE5 - SYS_LOG1PD128 = 0xBE9 - SYS_LOG1PD32 = 0xBE7 - SYS_LOG1PD64 = 0xBE8 - SYS_LOG2D128 = 0xBEC - SYS_LOG2D32 = 0xBEA - SYS_LOG2D64 = 0xBEB - SYS_LOGBD128 = 0xBEF - SYS_LOGBD32 = 0xBED - SYS_LOGBD64 = 0xBEE - SYS_LOGBF = 0xA96 - SYS_LOGBL = 0xA99 - SYS_LOGD128 = 0xBE3 - SYS_LOGD32 = 0xBE1 - SYS_LOGD64 = 0xBE2 - SYS_LRINT = 0xA9C - SYS_LRINTD128 = 0xBF2 - SYS_LRINTD32 = 0xBF0 - SYS_LRINTD64 = 0xBF1 - SYS_LRINTF = 0xA9F - SYS_LRINTL = 0xAA2 - SYS_LROUNDD128 = 0xBF5 - SYS_LROUNDD32 = 0xBF3 - SYS_LROUNDD64 = 0xBF4 - SYS_LROUNDL = 0xAA5 - SYS_MBLEN = 0x0AF - SYS_MBRTOC16 = 0xD42 - SYS_MBRTOC32 = 0xD43 - SYS_MEMSET = 0x0A3 - SYS_MKTIME = 0x0AC - SYS_MKTIME64 = 0xCE0 - SYS_MODFD128 = 0xBF8 - SYS_MODFD32 = 0xBF6 - SYS_MODFD64 = 0xBF7 - SYS_NAN = 0xAA8 - SYS_NAND128 = 0xBFB - SYS_NAND32 = 0xBF9 - SYS_NAND64 = 0xBFA - SYS_NANF = 0xAAA - SYS_NANL = 0xAAC - SYS_NEARBYINT = 0xAAE - SYS_NEARBYINTD128 = 0xBFE - SYS_NEARBYINTD32 = 0xBFC - SYS_NEARBYINTD64 = 0xBFD - SYS_NEARBYINTF = 0xAB1 - SYS_NEARBYINTL = 0xAB4 - SYS_NEXTAFTERD128 = 0xC01 - SYS_NEXTAFTERD32 = 0xBFF - SYS_NEXTAFTERD64 = 0xC00 - SYS_NEXTAFTERF = 0xAB7 - SYS_NEXTAFTERL = 0xABA - SYS_NEXTTOWARD = 0xABD - SYS_NEXTTOWARDD128 = 0xC04 - SYS_NEXTTOWARDD32 = 0xC02 - SYS_NEXTTOWARDD64 = 0xC03 - SYS_NEXTTOWARDF = 0xAC0 - SYS_NEXTTOWARDL = 0xAC3 - SYS_NL_LANGINFO = 0x0FC - SYS_PERROR_UNLOCKED = 0xCBD - SYS_POSIX_FALLOCATE = 0xCE8 - SYS_POSIX_MEMALIGN = 0xCE9 - SYS_POSIX_OPENPT = 0xC66 - SYS_POWD128 = 0xC07 - SYS_POWD32 = 0xC05 - SYS_POWD64 = 0xC06 - SYS_PRINTF_UNLOCKED = 0xCBE - SYS_PSELECT = 0xC67 - SYS_PTHREAD_ATTR_GETSTACK = 0xB3E - SYS_PTHREAD_ATTR_SETSTACK = 0xB3F - SYS_PTHREAD_SECURITY_APPLID_NP = 0xCE4 - SYS_PUTS_UNLOCKED = 0xC7F - SYS_PUTWCHAR_UNLOCKED = 0xCC0 - SYS_PUTWC_UNLOCKED = 0xCBF - SYS_QUANTEXPD128 = 0xD46 - SYS_QUANTEXPD32 = 0xD44 - SYS_QUANTEXPD64 = 0xD45 - SYS_QUANTIZED128 = 0xC0A - SYS_QUANTIZED32 = 0xC08 - SYS_QUANTIZED64 = 0xC09 - SYS_REMAINDERD128 = 0xC0D - SYS_REMAINDERD32 = 0xC0B - SYS_REMAINDERD64 = 0xC0C - SYS_RESIZE_ALLOC = 0xCEB - SYS_REWIND_UNLOCKED = 0xCC1 - SYS_RINTD128 = 0xC13 - SYS_RINTD32 = 0xC11 - SYS_RINTD64 = 0xC12 - SYS_RINTF = 0xACB - SYS_RINTL = 0xACD - SYS_ROUND = 0xACF - SYS_ROUNDD128 = 0xC16 - SYS_ROUNDD32 = 0xC14 - SYS_ROUNDD64 = 0xC15 - SYS_ROUNDF = 0xAD2 - SYS_ROUNDL = 0xAD5 - SYS_SAMEQUANTUMD128 = 0xC19 - SYS_SAMEQUANTUMD32 = 0xC17 - SYS_SAMEQUANTUMD64 = 0xC18 - SYS_SCALBLN = 0xAD8 - SYS_SCALBLND128 = 0xC1C - SYS_SCALBLND32 = 0xC1A - SYS_SCALBLND64 = 0xC1B - SYS_SCALBLNF = 0xADB - SYS_SCALBLNL = 0xADE - SYS_SCALBND128 = 0xC1F - SYS_SCALBND32 = 0xC1D - SYS_SCALBND64 = 0xC1E - SYS_SCALBNF = 0xAE3 - SYS_SCALBNL = 0xAE6 - SYS_SCANF_UNLOCKED = 0xCC2 - SYS_SCHED_YIELD = 0xB32 - SYS_SETENV = 0x0C8 - SYS_SETIPV4SOURCEFILTER = 0xC76 - SYS_SETSOURCEFILTER = 0xC78 - SYS_SHM_OPEN = 0xC8C - SYS_SHM_UNLINK = 0xC8D - SYS_SIND128 = 0xC22 - SYS_SIND32 = 0xC20 - SYS_SIND64 = 0xC21 - SYS_SINHD128 = 0xC25 - SYS_SINHD32 = 0xC23 - SYS_SINHD64 = 0xC24 - SYS_SIZEOF_ALLOC = 0xCEA - SYS_SOCKATMARK = 0xC68 - SYS_SQRTD128 = 0xC28 - SYS_SQRTD32 = 0xC26 - SYS_SQRTD64 = 0xC27 - SYS_STRCHR = 0x0A0 - SYS_STRCSPN = 0x0A1 - SYS_STRERROR = 0x0A8 - SYS_STRERROR_R = 0xB33 - SYS_STRFTIME = 0x0B2 - SYS_STRLEN = 0x0A9 - SYS_STRPBRK = 0x0A2 - SYS_STRSPN = 0x0A4 - SYS_STRSTR = 0x0A5 - SYS_STRTOD128 = 0xC2B - SYS_STRTOD32 = 0xC29 - SYS_STRTOD64 = 0xC2A - SYS_STRTOK = 0x0A6 - SYS_TAND128 = 0xC2E - SYS_TAND32 = 0xC2C - SYS_TAND64 = 0xC2D - SYS_TANHD128 = 0xC31 - SYS_TANHD32 = 0xC2F - SYS_TANHD64 = 0xC30 - SYS_TGAMMAD128 = 0xC34 - SYS_TGAMMAD32 = 0xC32 - SYS_TGAMMAD64 = 0xC33 - SYS_TIME = 0x0AD - SYS_TIME64 = 0xCE1 - SYS_TMPFILE64 = 0xD4D - SYS_TMPFILE64_UNLOCKED = 0xD4E - SYS_TMPFILE_UNLOCKED = 0xCFD - SYS_TRUNCD128 = 0xC40 - SYS_TRUNCD32 = 0xC3E - SYS_TRUNCD64 = 0xC3F - SYS_UNGETC_UNLOCKED = 0xCC3 - SYS_UNGETWC_UNLOCKED = 0xCC4 - SYS_UNSETENV = 0xB34 - SYS_VFPRINTF_UNLOCKED = 0xCC5 - SYS_VFSCANF_UNLOCKED = 0xCC7 - SYS_VFWPRINTF_UNLOCKED = 0xCC9 - SYS_VFWSCANF_UNLOCKED = 0xCCB - SYS_VPRINTF_UNLOCKED = 0xCCD - SYS_VSCANF_UNLOCKED = 0xCCF - SYS_VWPRINTF_UNLOCKED = 0xCD1 - SYS_VWSCANF_UNLOCKED = 0xCD3 - SYS_WCSTOD128 = 0xC43 - SYS_WCSTOD32 = 0xC41 - SYS_WCSTOD64 = 0xC42 - SYS_WPRINTF_UNLOCKED = 0xCD5 - SYS_WSCANF_UNLOCKED = 0xCD6 - SYS__FLUSHLBF = 0xD68 - SYS__FLUSHLBF_UNLOCKED = 0xD6F - SYS___ACOSHF_H = 0xA54 - SYS___ACOSHL_H = 0xA55 - SYS___ASINHF_H = 0xA56 - SYS___ASINHL_H = 0xA57 - SYS___ATANPID128 = 0xC6D - SYS___ATANPID32 = 0xC6B - SYS___ATANPID64 = 0xC6C - SYS___CBRTF_H = 0xA58 - SYS___CBRTL_H = 0xA59 - SYS___CDUMP = 0x0C4 - SYS___CLASS = 0xAFA - SYS___CLASS2 = 0xB99 - SYS___CLASS2D128 = 0xC99 - SYS___CLASS2D32 = 0xC97 - SYS___CLASS2D64 = 0xC98 - SYS___CLASS2F = 0xC91 - SYS___CLASS2F_B = 0xC93 - SYS___CLASS2F_H = 0xC94 - SYS___CLASS2L = 0xC92 - SYS___CLASS2L_B = 0xC95 - SYS___CLASS2L_H = 0xC96 - SYS___CLASS2_B = 0xB9A - SYS___CLASS2_H = 0xB9B - SYS___CLASS_B = 0xAFB - SYS___CLASS_H = 0xAFC - SYS___CLOGL_B = 0xA01 - SYS___CLOGL_H = 0xA02 - SYS___CLRENV = 0x0C9 - SYS___CLRMF = 0x0BD - SYS___CODEPAGE_INFO = 0xC64 - SYS___CONJF_B = 0xA07 - SYS___CONJF_H = 0xA08 - SYS___CONJL_B = 0xA0A - SYS___CONJL_H = 0xA0B - SYS___CONJ_B = 0xA04 - SYS___CONJ_H = 0xA05 - SYS___COPYSIGN_B = 0xA5A - SYS___COPYSIGN_H = 0xAF5 - SYS___COSPID128 = 0xC70 - SYS___COSPID32 = 0xC6E - SYS___COSPID64 = 0xC6F - SYS___CPOWF_B = 0xA10 - SYS___CPOWF_H = 0xA11 - SYS___CPOWL_B = 0xA13 - SYS___CPOWL_H = 0xA14 - SYS___CPOW_B = 0xA0D - SYS___CPOW_H = 0xA0E - SYS___CPROJF_B = 0xA19 - SYS___CPROJF_H = 0xA1A - SYS___CPROJL_B = 0xA1C - SYS___CPROJL_H = 0xA1D - SYS___CPROJ_B = 0xA16 - SYS___CPROJ_H = 0xA17 - SYS___CREALF_B = 0xA22 - SYS___CREALF_H = 0xA23 - SYS___CREALL_B = 0xA25 - SYS___CREALL_H = 0xA26 - SYS___CREAL_B = 0xA1F - SYS___CREAL_H = 0xA20 - SYS___CSINF_B = 0xA2B - SYS___CSINF_H = 0xA2C - SYS___CSINHF_B = 0xA34 - SYS___CSINHF_H = 0xA35 - SYS___CSINHL_B = 0xA37 - SYS___CSINHL_H = 0xA38 - SYS___CSINH_B = 0xA31 - SYS___CSINH_H = 0xA32 - SYS___CSINL_B = 0xA2E - SYS___CSINL_H = 0xA2F - SYS___CSIN_B = 0xA28 - SYS___CSIN_H = 0xA29 - SYS___CSNAP = 0x0C5 - SYS___CSQRTF_B = 0xA3D - SYS___CSQRTF_H = 0xA3E - SYS___CSQRTL_B = 0xA40 - SYS___CSQRTL_H = 0xA41 - SYS___CSQRT_B = 0xA3A - SYS___CSQRT_H = 0xA3B - SYS___CTANF_B = 0xA46 - SYS___CTANF_H = 0xA47 - SYS___CTANHF_B = 0xA4F - SYS___CTANHF_H = 0xA50 - SYS___CTANHL_B = 0xA52 - SYS___CTANHL_H = 0xA53 - SYS___CTANH_B = 0xA4C - SYS___CTANH_H = 0xA4D - SYS___CTANL_B = 0xA49 - SYS___CTANL_H = 0xA4A - SYS___CTAN_B = 0xA43 - SYS___CTAN_H = 0xA44 - SYS___CTEST = 0x0C7 - SYS___CTRACE = 0x0C6 - SYS___D1TOP = 0xC9B - SYS___D2TOP = 0xC9C - SYS___D4TOP = 0xC9D - SYS___DYNALL = 0x0C3 - SYS___DYNFRE = 0x0C2 - SYS___EXP2F_H = 0xA5E - SYS___EXP2L_H = 0xA5F - SYS___EXP2_H = 0xA5D - SYS___EXPM1F_H = 0xA5B - SYS___EXPM1L_H = 0xA5C - SYS___FBUFSIZE = 0xD60 - SYS___FLBF = 0xD62 - SYS___FLDATA = 0x0C1 - SYS___FMAF_B = 0xA67 - SYS___FMAF_H = 0xA68 - SYS___FMAL_B = 0xA6A - SYS___FMAL_H = 0xA6B - SYS___FMAXF_B = 0xA70 - SYS___FMAXF_H = 0xA71 - SYS___FMAXL_B = 0xA73 - SYS___FMAXL_H = 0xA74 - SYS___FMAX_B = 0xA6D - SYS___FMAX_H = 0xA6E - SYS___FMA_B = 0xA64 - SYS___FMA_H = 0xA65 - SYS___FMINF_B = 0xA79 - SYS___FMINF_H = 0xA7A - SYS___FMINL_B = 0xA7C - SYS___FMINL_H = 0xA7D - SYS___FMIN_B = 0xA76 - SYS___FMIN_H = 0xA77 - SYS___FPENDING = 0xD61 - SYS___FPENDING_UNLOCKED = 0xD6C - SYS___FPURGE = 0xD69 - SYS___FPURGE_UNLOCKED = 0xD70 - SYS___FP_CAST_D = 0xBCB - SYS___FREADABLE = 0xD63 - SYS___FREADAHEAD = 0xD6A - SYS___FREADAHEAD_UNLOCKED = 0xD71 - SYS___FREADING = 0xD65 - SYS___FREADING_UNLOCKED = 0xD6D - SYS___FSEEK2 = 0xB3C - SYS___FSETERR = 0xD6B - SYS___FSETLOCKING = 0xD67 - SYS___FTCHEP = 0x0BF - SYS___FTELL2 = 0xB3B - SYS___FUPDT = 0x0B5 - SYS___FWRITABLE = 0xD64 - SYS___FWRITING = 0xD66 - SYS___FWRITING_UNLOCKED = 0xD6E - SYS___GETCB = 0x0B4 - SYS___GETGRGID1 = 0xD5B - SYS___GETGRNAM1 = 0xD5C - SYS___GETTHENT = 0xCE5 - SYS___GETTOD = 0xD3E - SYS___HYPOTF_H = 0xAF6 - SYS___HYPOTL_H = 0xAF7 - SYS___ILOGBF_B = 0xA7F - SYS___ILOGBF_H = 0xA80 - SYS___ILOGBL_B = 0xA82 - SYS___ILOGBL_H = 0xA83 - SYS___ISBLANK_A = 0xB2E - SYS___ISBLNK = 0x0FE - SYS___ISWBLANK_A = 0xB2F - SYS___LE_CEEGTJS = 0xD72 - SYS___LE_TRACEBACK = 0xB7A - SYS___LGAMMAL_H = 0xA62 - SYS___LGAMMA_B_C99 = 0xB39 - SYS___LGAMMA_H_C99 = 0xB38 - SYS___LGAMMA_R_C99 = 0xB3A - SYS___LLRINTF_B = 0xA88 - SYS___LLRINTF_H = 0xA89 - SYS___LLRINTL_B = 0xA8B - SYS___LLRINTL_H = 0xA8C - SYS___LLRINT_B = 0xA85 - SYS___LLRINT_H = 0xA86 - SYS___LLROUNDF_B = 0xA91 - SYS___LLROUNDF_H = 0xA92 - SYS___LLROUNDL_B = 0xA94 - SYS___LLROUNDL_H = 0xA95 - SYS___LLROUND_B = 0xA8E - SYS___LLROUND_H = 0xA8F - SYS___LOCALE_CTL = 0xD47 - SYS___LOG1PF_H = 0xA60 - SYS___LOG1PL_H = 0xA61 - SYS___LOGBF_B = 0xA97 - SYS___LOGBF_H = 0xA98 - SYS___LOGBL_B = 0xA9A - SYS___LOGBL_H = 0xA9B - SYS___LOGIN_APPLID = 0xCE2 - SYS___LRINTF_B = 0xAA0 - SYS___LRINTF_H = 0xAA1 - SYS___LRINTL_B = 0xAA3 - SYS___LRINTL_H = 0xAA4 - SYS___LRINT_B = 0xA9D - SYS___LRINT_H = 0xA9E - SYS___LROUNDF_FIXUP = 0xB31 - SYS___LROUNDL_B = 0xAA6 - SYS___LROUNDL_H = 0xAA7 - SYS___LROUND_FIXUP = 0xB30 - SYS___MOSERVICES = 0xD3D - SYS___MUST_STAY_CLEAN = 0xB7C - SYS___NANF_B = 0xAAB - SYS___NANL_B = 0xAAD - SYS___NAN_B = 0xAA9 - SYS___NEARBYINTF_B = 0xAB2 - SYS___NEARBYINTF_H = 0xAB3 - SYS___NEARBYINTL_B = 0xAB5 - SYS___NEARBYINTL_H = 0xAB6 - SYS___NEARBYINT_B = 0xAAF - SYS___NEARBYINT_H = 0xAB0 - SYS___NEXTAFTERF_B = 0xAB8 - SYS___NEXTAFTERF_H = 0xAB9 - SYS___NEXTAFTERL_B = 0xABB - SYS___NEXTAFTERL_H = 0xABC - SYS___NEXTTOWARDF_B = 0xAC1 - SYS___NEXTTOWARDF_H = 0xAC2 - SYS___NEXTTOWARDL_B = 0xAC4 - SYS___NEXTTOWARDL_H = 0xAC5 - SYS___NEXTTOWARD_B = 0xABE - SYS___NEXTTOWARD_H = 0xABF - SYS___O_ENV = 0xB7D - SYS___PASSWD_APPLID = 0xCE3 - SYS___PTOD1 = 0xC9E - SYS___PTOD2 = 0xC9F - SYS___PTOD4 = 0xCA0 - SYS___REGCOMP_STD = 0x0EA - SYS___REMAINDERF_H = 0xAC6 - SYS___REMAINDERL_H = 0xAC7 - SYS___REMQUOD128 = 0xC10 - SYS___REMQUOD32 = 0xC0E - SYS___REMQUOD64 = 0xC0F - SYS___REMQUOF_H = 0xAC9 - SYS___REMQUOL_H = 0xACA - SYS___REMQUO_H = 0xAC8 - SYS___RINTF_B = 0xACC - SYS___RINTL_B = 0xACE - SYS___ROUNDF_B = 0xAD3 - SYS___ROUNDF_H = 0xAD4 - SYS___ROUNDL_B = 0xAD6 - SYS___ROUNDL_H = 0xAD7 - SYS___ROUND_B = 0xAD0 - SYS___ROUND_H = 0xAD1 - SYS___SCALBLNF_B = 0xADC - SYS___SCALBLNF_H = 0xADD - SYS___SCALBLNL_B = 0xADF - SYS___SCALBLNL_H = 0xAE0 - SYS___SCALBLN_B = 0xAD9 - SYS___SCALBLN_H = 0xADA - SYS___SCALBNF_B = 0xAE4 - SYS___SCALBNF_H = 0xAE5 - SYS___SCALBNL_B = 0xAE7 - SYS___SCALBNL_H = 0xAE8 - SYS___SCALBN_B = 0xAE1 - SYS___SCALBN_H = 0xAE2 - SYS___SETENV = 0x0C8 - SYS___SINPID128 = 0xC73 - SYS___SINPID32 = 0xC71 - SYS___SINPID64 = 0xC72 - SYS___SMF_RECORD2 = 0xD48 - SYS___STATIC_REINIT = 0xB3D - SYS___TGAMMAF_H_C99 = 0xB79 - SYS___TGAMMAL_H = 0xAE9 - SYS___TGAMMA_H_C99 = 0xB78 - SYS___TOCSNAME2 = 0xC9A - SYS_CEIL = 0x01F - SYS_CHAUDIT = 0x1E0 - SYS_EXP = 0x01A - SYS_FCHAUDIT = 0x1E1 - SYS_FREXP = 0x01D - SYS_GETGROUPSBYNAME = 0x1E2 - SYS_GETPWUID = 0x1A0 - SYS_GETUID = 0x1A1 - SYS_ISATTY = 0x1A3 - SYS_KILL = 0x1A4 - SYS_LDEXP = 0x01E - SYS_LINK = 0x1A5 - SYS_LOG10 = 0x01C - SYS_LSEEK = 0x1A6 - SYS_LSTAT = 0x1A7 - SYS_MKDIR = 0x1A8 - SYS_MKFIFO = 0x1A9 - SYS_MKNOD = 0x1AA - SYS_MODF = 0x01B - SYS_MOUNT = 0x1AB - SYS_OPEN = 0x1AC - SYS_OPENDIR = 0x1AD - SYS_PATHCONF = 0x1AE - SYS_PAUSE = 0x1AF - SYS_PIPE = 0x1B0 - SYS_PTHREAD_ATTR_DESTROY = 0x1E7 - SYS_PTHREAD_ATTR_GETDETACHSTATE = 0x1EB - SYS_PTHREAD_ATTR_GETSTACKSIZE = 0x1E9 - SYS_PTHREAD_ATTR_GETWEIGHT_NP = 0x1ED - SYS_PTHREAD_ATTR_INIT = 0x1E6 - SYS_PTHREAD_ATTR_SETDETACHSTATE = 0x1EA - SYS_PTHREAD_ATTR_SETSTACKSIZE = 0x1E8 - SYS_PTHREAD_ATTR_SETWEIGHT_NP = 0x1EC - SYS_PTHREAD_CANCEL = 0x1EE - SYS_PTHREAD_CLEANUP_POP = 0x1F0 - SYS_PTHREAD_CLEANUP_PUSH = 0x1EF - SYS_PTHREAD_CONDATTR_DESTROY = 0x1F2 - SYS_PTHREAD_CONDATTR_INIT = 0x1F1 - SYS_PTHREAD_COND_BROADCAST = 0x1F6 - SYS_PTHREAD_COND_DESTROY = 0x1F4 - SYS_PTHREAD_COND_INIT = 0x1F3 - SYS_PTHREAD_COND_SIGNAL = 0x1F5 - SYS_PTHREAD_COND_TIMEDWAIT = 0x1F8 - SYS_PTHREAD_COND_WAIT = 0x1F7 - SYS_PTHREAD_CREATE = 0x1F9 - SYS_PTHREAD_DETACH = 0x1FA - SYS_PTHREAD_EQUAL = 0x1FB - SYS_PTHREAD_EXIT = 0x1E4 - SYS_PTHREAD_GETSPECIFIC = 0x1FC - SYS_PTHREAD_JOIN = 0x1FD - SYS_PTHREAD_KEY_CREATE = 0x1FE - SYS_PTHREAD_KILL = 0x1E5 - SYS_PTHREAD_MUTEXATTR_INIT = 0x1FF - SYS_READ = 0x1B2 - SYS_READDIR = 0x1B3 - SYS_READLINK = 0x1B4 - SYS_REWINDDIR = 0x1B5 - SYS_RMDIR = 0x1B6 - SYS_SETEGID = 0x1B7 - SYS_SETEUID = 0x1B8 - SYS_SETGID = 0x1B9 - SYS_SETPGID = 0x1BA - SYS_SETSID = 0x1BB - SYS_SETUID = 0x1BC - SYS_SIGACTION = 0x1BD - SYS_SIGADDSET = 0x1BE - SYS_SIGDELSET = 0x1BF - SYS_SIGEMPTYSET = 0x1C0 - SYS_SIGFILLSET = 0x1C1 - SYS_SIGISMEMBER = 0x1C2 - SYS_SIGLONGJMP = 0x1C3 - SYS_SIGPENDING = 0x1C4 - SYS_SIGPROCMASK = 0x1C5 - SYS_SIGSETJMP = 0x1C6 - SYS_SIGSUSPEND = 0x1C7 - SYS_SIGWAIT = 0x1E3 - SYS_SLEEP = 0x1C8 - SYS_STAT = 0x1C9 - SYS_SYMLINK = 0x1CB - SYS_SYSCONF = 0x1CC - SYS_TCDRAIN = 0x1CD - SYS_TCFLOW = 0x1CE - SYS_TCFLUSH = 0x1CF - SYS_TCGETATTR = 0x1D0 - SYS_TCGETPGRP = 0x1D1 - SYS_TCSENDBREAK = 0x1D2 - SYS_TCSETATTR = 0x1D3 - SYS_TCSETPGRP = 0x1D4 - SYS_TIMES = 0x1D5 - SYS_TTYNAME = 0x1D6 - SYS_TZSET = 0x1D7 - SYS_UMASK = 0x1D8 - SYS_UMOUNT = 0x1D9 - SYS_UNAME = 0x1DA - SYS_UNLINK = 0x1DB - SYS_UTIME = 0x1DC - SYS_WAIT = 0x1DD - SYS_WAITPID = 0x1DE - SYS_WRITE = 0x1DF - SYS_W_GETPSENT = 0x1B1 - SYS_W_IOCTL = 0x1A2 - SYS_W_STATFS = 0x1CA - SYS_A64L = 0x2EF - SYS_BCMP = 0x2B9 - SYS_BCOPY = 0x2BA - SYS_BZERO = 0x2BB - SYS_CATCLOSE = 0x2B6 - SYS_CATGETS = 0x2B7 - SYS_CATOPEN = 0x2B8 - SYS_CRYPT = 0x2AC - SYS_DBM_CLEARERR = 0x2F7 - SYS_DBM_CLOSE = 0x2F8 - SYS_DBM_DELETE = 0x2F9 - SYS_DBM_ERROR = 0x2FA - SYS_DBM_FETCH = 0x2FB - SYS_DBM_FIRSTKEY = 0x2FC - SYS_DBM_NEXTKEY = 0x2FD - SYS_DBM_OPEN = 0x2FE - SYS_DBM_STORE = 0x2FF - SYS_DRAND48 = 0x2B2 - SYS_ENCRYPT = 0x2AD - SYS_ENDUTXENT = 0x2E1 - SYS_ERAND48 = 0x2B3 - SYS_ERF = 0x02C - SYS_ERFC = 0x02D - SYS_FCHDIR = 0x2D9 - SYS_FFS = 0x2BC - SYS_FMTMSG = 0x2E5 - SYS_FSTATVFS = 0x2B4 - SYS_FTIME = 0x2F5 - SYS_GAMMA = 0x02E - SYS_GETDATE = 0x2A6 - SYS_GETPAGESIZE = 0x2D8 - SYS_GETTIMEOFDAY = 0x2F6 - SYS_GETUTXENT = 0x2E0 - SYS_GETUTXID = 0x2E2 - SYS_GETUTXLINE = 0x2E3 - SYS_HCREATE = 0x2C6 - SYS_HDESTROY = 0x2C7 - SYS_HSEARCH = 0x2C8 - SYS_HYPOT = 0x02B - SYS_INDEX = 0x2BD - SYS_INITSTATE = 0x2C2 - SYS_INSQUE = 0x2CF - SYS_ISASCII = 0x2ED - SYS_JRAND48 = 0x2E6 - SYS_L64A = 0x2F0 - SYS_LCONG48 = 0x2EA - SYS_LFIND = 0x2C9 - SYS_LRAND48 = 0x2E7 - SYS_LSEARCH = 0x2CA - SYS_MEMCCPY = 0x2D4 - SYS_MRAND48 = 0x2E8 - SYS_NRAND48 = 0x2E9 - SYS_PCLOSE = 0x2D2 - SYS_POPEN = 0x2D1 - SYS_PUTUTXLINE = 0x2E4 - SYS_RANDOM = 0x2C4 - SYS_REMQUE = 0x2D0 - SYS_RINDEX = 0x2BE - SYS_SEED48 = 0x2EC - SYS_SETKEY = 0x2AE - SYS_SETSTATE = 0x2C3 - SYS_SETUTXENT = 0x2DF - SYS_SRAND48 = 0x2EB - SYS_SRANDOM = 0x2C5 - SYS_STATVFS = 0x2B5 - SYS_STRCASECMP = 0x2BF - SYS_STRDUP = 0x2C0 - SYS_STRNCASECMP = 0x2C1 - SYS_SWAB = 0x2D3 - SYS_TDELETE = 0x2CB - SYS_TFIND = 0x2CC - SYS_TOASCII = 0x2EE - SYS_TSEARCH = 0x2CD - SYS_TWALK = 0x2CE - SYS_UALARM = 0x2F1 - SYS_USLEEP = 0x2F2 - SYS_WAIT3 = 0x2A7 - SYS_WAITID = 0x2A8 - SYS_Y1 = 0x02A - SYS___ATOE = 0x2DB - SYS___ATOE_L = 0x2DC - SYS___CATTRM = 0x2A9 - SYS___CNVBLK = 0x2AF - SYS___CRYTRM = 0x2B0 - SYS___DLGHT = 0x2A1 - SYS___ECRTRM = 0x2B1 - SYS___ETOA = 0x2DD - SYS___ETOA_L = 0x2DE - SYS___GDTRM = 0x2AA - SYS___OCLCK = 0x2DA - SYS___OPARGF = 0x2A2 - SYS___OPERRF = 0x2A5 - SYS___OPINDF = 0x2A4 - SYS___OPOPTF = 0x2A3 - SYS___RNDTRM = 0x2AB - SYS___SRCTRM = 0x2F4 - SYS___TZONE = 0x2A0 - SYS___UTXTRM = 0x2F3 - SYS_ASIN = 0x03E - SYS_ISXDIGIT = 0x03B - SYS_SETLOCAL = 0x03A - SYS_SETLOCALE = 0x03A - SYS_SIN = 0x03F - SYS_TOLOWER = 0x03C - SYS_TOUPPER = 0x03D - SYS_ACCEPT_AND_RECV = 0x4F7 - SYS_ATOL = 0x04E - SYS_CHECKSCH = 0x4BC - SYS_CHECKSCHENV = 0x4BC - SYS_CLEARERR = 0x04C - SYS_CONNECTS = 0x4B5 - SYS_CONNECTSERVER = 0x4B5 - SYS_CONNECTW = 0x4B4 - SYS_CONNECTWORKMGR = 0x4B4 - SYS_CONTINUE = 0x4B3 - SYS_CONTINUEWORKUNIT = 0x4B3 - SYS_COPYSIGN = 0x4C2 - SYS_CREATEWO = 0x4B2 - SYS_CREATEWORKUNIT = 0x4B2 - SYS_DELETEWO = 0x4B9 - SYS_DELETEWORKUNIT = 0x4B9 - SYS_DISCONNE = 0x4B6 - SYS_DISCONNECTSERVER = 0x4B6 - SYS_FEOF = 0x04D - SYS_FERROR = 0x04A - SYS_FINITE = 0x4C8 - SYS_GAMMA_R = 0x4E2 - SYS_JOINWORK = 0x4B7 - SYS_JOINWORKUNIT = 0x4B7 - SYS_LEAVEWOR = 0x4B8 - SYS_LEAVEWORKUNIT = 0x4B8 - SYS_LGAMMA_R = 0x4EB - SYS_MATHERR = 0x4D0 - SYS_PERROR = 0x04F - SYS_QUERYMET = 0x4BA - SYS_QUERYMETRICS = 0x4BA - SYS_QUERYSCH = 0x4BB - SYS_QUERYSCHENV = 0x4BB - SYS_REWIND = 0x04B - SYS_SCALBN = 0x4D4 - SYS_SIGNIFIC = 0x4D5 - SYS_SIGNIFICAND = 0x4D5 - SYS___ACOSH_B = 0x4DA - SYS___ACOS_B = 0x4D9 - SYS___ASINH_B = 0x4BE - SYS___ASIN_B = 0x4DB - SYS___ATAN2_B = 0x4DC - SYS___ATANH_B = 0x4DD - SYS___ATAN_B = 0x4BF - SYS___CBRT_B = 0x4C0 - SYS___CEIL_B = 0x4C1 - SYS___COSH_B = 0x4DE - SYS___COS_B = 0x4C3 - SYS___DGHT = 0x4A8 - SYS___ENVN = 0x4B0 - SYS___ERFC_B = 0x4C5 - SYS___ERF_B = 0x4C4 - SYS___EXPM1_B = 0x4C6 - SYS___EXP_B = 0x4DF - SYS___FABS_B = 0x4C7 - SYS___FLOOR_B = 0x4C9 - SYS___FMOD_B = 0x4E0 - SYS___FP_SETMODE = 0x4F8 - SYS___FREXP_B = 0x4CA - SYS___GAMMA_B = 0x4E1 - SYS___GDRR = 0x4A1 - SYS___HRRNO = 0x4A2 - SYS___HYPOT_B = 0x4E3 - SYS___ILOGB_B = 0x4CB - SYS___ISNAN_B = 0x4CC - SYS___J0_B = 0x4E4 - SYS___J1_B = 0x4E6 - SYS___JN_B = 0x4E8 - SYS___LDEXP_B = 0x4CD - SYS___LGAMMA_B = 0x4EA - SYS___LOG10_B = 0x4ED - SYS___LOG1P_B = 0x4CE - SYS___LOGB_B = 0x4CF - SYS___LOGIN = 0x4F5 - SYS___LOG_B = 0x4EC - SYS___MLOCKALL = 0x4B1 - SYS___MODF_B = 0x4D1 - SYS___NEXTAFTER_B = 0x4D2 - SYS___OPENDIR2 = 0x4F3 - SYS___OPEN_STAT = 0x4F6 - SYS___OPND = 0x4A5 - SYS___OPPT = 0x4A6 - SYS___OPRG = 0x4A3 - SYS___OPRR = 0x4A4 - SYS___PID_AFFINITY = 0x4BD - SYS___POW_B = 0x4EE - SYS___READDIR2 = 0x4F4 - SYS___REMAINDER_B = 0x4EF - SYS___RINT_B = 0x4D3 - SYS___SCALB_B = 0x4F0 - SYS___SIGACTIONSET = 0x4FB - SYS___SIGGM = 0x4A7 - SYS___SINH_B = 0x4F1 - SYS___SIN_B = 0x4D6 - SYS___SQRT_B = 0x4F2 - SYS___TANH_B = 0x4D8 - SYS___TAN_B = 0x4D7 - SYS___TRRNO = 0x4AF - SYS___TZNE = 0x4A9 - SYS___TZZN = 0x4AA - SYS___UCREATE = 0x4FC - SYS___UFREE = 0x4FE - SYS___UHEAPREPORT = 0x4FF - SYS___UMALLOC = 0x4FD - SYS___Y0_B = 0x4E5 - SYS___Y1_B = 0x4E7 - SYS___YN_B = 0x4E9 - SYS_ABORT = 0x05C - SYS_ASCTIME_R = 0x5E0 - SYS_ATEXIT = 0x05D - SYS_CONNECTE = 0x5AE - SYS_CONNECTEXPORTIMPORT = 0x5AE - SYS_CTIME_R = 0x5E1 - SYS_DN_COMP = 0x5DF - SYS_DN_EXPAND = 0x5DD - SYS_DN_SKIPNAME = 0x5DE - SYS_EXIT = 0x05A - SYS_EXPORTWO = 0x5A1 - SYS_EXPORTWORKUNIT = 0x5A1 - SYS_EXTRACTW = 0x5A5 - SYS_EXTRACTWORKUNIT = 0x5A5 - SYS_FSEEKO = 0x5C9 - SYS_FTELLO = 0x5C8 - SYS_GETGRGID_R = 0x5E7 - SYS_GETGRNAM_R = 0x5E8 - SYS_GETLOGIN_R = 0x5E9 - SYS_GETPWNAM_R = 0x5EA - SYS_GETPWUID_R = 0x5EB - SYS_GMTIME_R = 0x5E2 - SYS_IMPORTWO = 0x5A3 - SYS_IMPORTWORKUNIT = 0x5A3 - SYS_INET_NTOP = 0x5D3 - SYS_INET_PTON = 0x5D4 - SYS_LLABS = 0x5CE - SYS_LLDIV = 0x5CB - SYS_LOCALTIME_R = 0x5E3 - SYS_PTHREAD_ATFORK = 0x5ED - SYS_PTHREAD_ATTR_GETDETACHSTATE_U98 = 0x5FB - SYS_PTHREAD_ATTR_GETGUARDSIZE = 0x5EE - SYS_PTHREAD_ATTR_GETSCHEDPARAM = 0x5F9 - SYS_PTHREAD_ATTR_GETSTACKADDR = 0x5EF - SYS_PTHREAD_ATTR_SETDETACHSTATE_U98 = 0x5FC - SYS_PTHREAD_ATTR_SETGUARDSIZE = 0x5F0 - SYS_PTHREAD_ATTR_SETSCHEDPARAM = 0x5FA - SYS_PTHREAD_ATTR_SETSTACKADDR = 0x5F1 - SYS_PTHREAD_CONDATTR_GETPSHARED = 0x5F2 - SYS_PTHREAD_CONDATTR_SETPSHARED = 0x5F3 - SYS_PTHREAD_DETACH_U98 = 0x5FD - SYS_PTHREAD_GETCONCURRENCY = 0x5F4 - SYS_PTHREAD_GETSPECIFIC_U98 = 0x5FE - SYS_PTHREAD_KEY_DELETE = 0x5F5 - SYS_PTHREAD_SETCANCELSTATE = 0x5FF - SYS_PTHREAD_SETCONCURRENCY = 0x5F6 - SYS_PTHREAD_SIGMASK = 0x5F7 - SYS_QUERYENC = 0x5AD - SYS_QUERYWORKUNITCLASSIFICATION = 0x5AD - SYS_RAISE = 0x05E - SYS_RAND_R = 0x5E4 - SYS_READDIR_R = 0x5E6 - SYS_REALLOC = 0x05B - SYS_RES_INIT = 0x5D8 - SYS_RES_MKQUERY = 0x5D7 - SYS_RES_QUERY = 0x5D9 - SYS_RES_QUERYDOMAIN = 0x5DC - SYS_RES_SEARCH = 0x5DA - SYS_RES_SEND = 0x5DB - SYS_SETJMP = 0x05F - SYS_SIGQUEUE = 0x5A9 - SYS_STRTOK_R = 0x5E5 - SYS_STRTOLL = 0x5B0 - SYS_STRTOULL = 0x5B1 - SYS_TTYNAME_R = 0x5EC - SYS_UNDOEXPO = 0x5A2 - SYS_UNDOEXPORTWORKUNIT = 0x5A2 - SYS_UNDOIMPO = 0x5A4 - SYS_UNDOIMPORTWORKUNIT = 0x5A4 - SYS_WCSTOLL = 0x5CC - SYS_WCSTOULL = 0x5CD - SYS___ABORT = 0x05C - SYS___CONSOLE2 = 0x5D2 - SYS___CPL = 0x5A6 - SYS___DISCARDDATA = 0x5F8 - SYS___DSA_PREV = 0x5B2 - SYS___EP_FIND = 0x5B3 - SYS___FP_SWAPMODE = 0x5AF - SYS___GETUSERID = 0x5AB - SYS___GET_CPUID = 0x5B9 - SYS___GET_SYSTEM_SETTINGS = 0x5BA - SYS___IPDOMAINNAME = 0x5AC - SYS___MAP_INIT = 0x5A7 - SYS___MAP_SERVICE = 0x5A8 - SYS___MOUNT = 0x5AA - SYS___MSGRCV_TIMED = 0x5B7 - SYS___RES = 0x5D6 - SYS___SEMOP_TIMED = 0x5B8 - SYS___SERVER_THREADS_QUERY = 0x5B4 - SYS_FPRINTF = 0x06D - SYS_FSCANF = 0x06A - SYS_PRINTF = 0x06F - SYS_SETBUF = 0x06B - SYS_SETVBUF = 0x06C - SYS_SSCANF = 0x06E - SYS___CATGETS_A = 0x6C0 - SYS___CHAUDIT_A = 0x6F4 - SYS___CHMOD_A = 0x6E8 - SYS___COLLATE_INIT_A = 0x6AC - SYS___CREAT_A = 0x6F6 - SYS___CTYPE_INIT_A = 0x6AF - SYS___DLLLOAD_A = 0x6DF - SYS___DLLQUERYFN_A = 0x6E0 - SYS___DLLQUERYVAR_A = 0x6E1 - SYS___E2A_L = 0x6E3 - SYS___EXECLE_A = 0x6A0 - SYS___EXECLP_A = 0x6A4 - SYS___EXECVE_A = 0x6C1 - SYS___EXECVP_A = 0x6C2 - SYS___EXECV_A = 0x6B1 - SYS___FPRINTF_A = 0x6FA - SYS___GETADDRINFO_A = 0x6BF - SYS___GETNAMEINFO_A = 0x6C4 - SYS___GET_WCTYPE_STD_A = 0x6AE - SYS___ICONV_OPEN_A = 0x6DE - SYS___IF_INDEXTONAME_A = 0x6DC - SYS___IF_NAMETOINDEX_A = 0x6DB - SYS___ISWCTYPE_A = 0x6B0 - SYS___IS_WCTYPE_STD_A = 0x6B2 - SYS___LOCALECONV_A = 0x6B8 - SYS___LOCALECONV_STD_A = 0x6B9 - SYS___LOCALE_INIT_A = 0x6B7 - SYS___LSTAT_A = 0x6EE - SYS___LSTAT_O_A = 0x6EF - SYS___MKDIR_A = 0x6E9 - SYS___MKFIFO_A = 0x6EC - SYS___MKNOD_A = 0x6F0 - SYS___MONETARY_INIT_A = 0x6BC - SYS___MOUNT_A = 0x6F1 - SYS___NL_CSINFO_A = 0x6D6 - SYS___NL_LANGINFO_A = 0x6BA - SYS___NL_LNAGINFO_STD_A = 0x6BB - SYS___NL_MONINFO_A = 0x6D7 - SYS___NL_NUMINFO_A = 0x6D8 - SYS___NL_RESPINFO_A = 0x6D9 - SYS___NL_TIMINFO_A = 0x6DA - SYS___NUMERIC_INIT_A = 0x6C6 - SYS___OPEN_A = 0x6F7 - SYS___PRINTF_A = 0x6DD - SYS___RESP_INIT_A = 0x6C7 - SYS___RPMATCH_A = 0x6C8 - SYS___RPMATCH_C_A = 0x6C9 - SYS___RPMATCH_STD_A = 0x6CA - SYS___SETLOCALE_A = 0x6F9 - SYS___SPAWNP_A = 0x6C5 - SYS___SPAWN_A = 0x6C3 - SYS___SPRINTF_A = 0x6FB - SYS___STAT_A = 0x6EA - SYS___STAT_O_A = 0x6EB - SYS___STRCOLL_STD_A = 0x6A1 - SYS___STRFMON_A = 0x6BD - SYS___STRFMON_STD_A = 0x6BE - SYS___STRFTIME_A = 0x6CC - SYS___STRFTIME_STD_A = 0x6CD - SYS___STRPTIME_A = 0x6CE - SYS___STRPTIME_STD_A = 0x6CF - SYS___STRXFRM_A = 0x6A2 - SYS___STRXFRM_C_A = 0x6A3 - SYS___STRXFRM_STD_A = 0x6A5 - SYS___SYNTAX_INIT_A = 0x6D4 - SYS___TIME_INIT_A = 0x6CB - SYS___TOD_INIT_A = 0x6D5 - SYS___TOWLOWER_A = 0x6B3 - SYS___TOWLOWER_STD_A = 0x6B4 - SYS___TOWUPPER_A = 0x6B5 - SYS___TOWUPPER_STD_A = 0x6B6 - SYS___UMOUNT_A = 0x6F2 - SYS___VFPRINTF_A = 0x6FC - SYS___VPRINTF_A = 0x6FD - SYS___VSPRINTF_A = 0x6FE - SYS___VSWPRINTF_A = 0x6FF - SYS___WCSCOLL_A = 0x6A6 - SYS___WCSCOLL_C_A = 0x6A7 - SYS___WCSCOLL_STD_A = 0x6A8 - SYS___WCSFTIME_A = 0x6D0 - SYS___WCSFTIME_STD_A = 0x6D1 - SYS___WCSXFRM_A = 0x6A9 - SYS___WCSXFRM_C_A = 0x6AA - SYS___WCSXFRM_STD_A = 0x6AB - SYS___WCTYPE_A = 0x6AD - SYS___W_GETMNTENT_A = 0x6F5 - SYS_____CCSIDTYPE_A = 0x6E6 - SYS_____CHATTR_A = 0x6E2 - SYS_____CSNAMETYPE_A = 0x6E7 - SYS_____OPEN_STAT_A = 0x6ED - SYS_____SPAWN2_A = 0x6D2 - SYS_____SPAWNP2_A = 0x6D3 - SYS_____TOCCSID_A = 0x6E4 - SYS_____TOCSNAME_A = 0x6E5 - SYS_ACL_FREE = 0x7FF - SYS_ACL_INIT = 0x7FE - SYS_FWIDE = 0x7DF - SYS_FWPRINTF = 0x7D1 - SYS_FWRITE = 0x07E - SYS_FWSCANF = 0x7D5 - SYS_GETCHAR = 0x07B - SYS_GETS = 0x07C - SYS_M_CREATE_LAYOUT = 0x7C9 - SYS_M_DESTROY_LAYOUT = 0x7CA - SYS_M_GETVALUES_LAYOUT = 0x7CB - SYS_M_SETVALUES_LAYOUT = 0x7CC - SYS_M_TRANSFORM_LAYOUT = 0x7CD - SYS_M_WTRANSFORM_LAYOUT = 0x7CE - SYS_PREAD = 0x7C7 - SYS_PUTC = 0x07D - SYS_PUTCHAR = 0x07A - SYS_PUTS = 0x07F - SYS_PWRITE = 0x7C8 - SYS_TOWCTRAN = 0x7D8 - SYS_TOWCTRANS = 0x7D8 - SYS_UNATEXIT = 0x7B5 - SYS_VFWPRINT = 0x7D3 - SYS_VFWPRINTF = 0x7D3 - SYS_VWPRINTF = 0x7D4 - SYS_WCTRANS = 0x7D7 - SYS_WPRINTF = 0x7D2 - SYS_WSCANF = 0x7D6 - SYS___ASCTIME_R_A = 0x7A1 - SYS___BASENAME_A = 0x7DC - SYS___BTOWC_A = 0x7E4 - SYS___CDUMP_A = 0x7B7 - SYS___CEE3DMP_A = 0x7B6 - SYS___CEILF_H = 0x7F4 - SYS___CEILL_H = 0x7F5 - SYS___CEIL_H = 0x7EA - SYS___CRYPT_A = 0x7BE - SYS___CSNAP_A = 0x7B8 - SYS___CTEST_A = 0x7B9 - SYS___CTIME_R_A = 0x7A2 - SYS___CTRACE_A = 0x7BA - SYS___DBM_OPEN_A = 0x7E6 - SYS___DIRNAME_A = 0x7DD - SYS___FABSF_H = 0x7FA - SYS___FABSL_H = 0x7FB - SYS___FABS_H = 0x7ED - SYS___FGETWC_A = 0x7AA - SYS___FGETWS_A = 0x7AD - SYS___FLOORF_H = 0x7F6 - SYS___FLOORL_H = 0x7F7 - SYS___FLOOR_H = 0x7EB - SYS___FPUTWC_A = 0x7A5 - SYS___FPUTWS_A = 0x7A8 - SYS___GETTIMEOFDAY_A = 0x7AE - SYS___GETWCHAR_A = 0x7AC - SYS___GETWC_A = 0x7AB - SYS___GLOB_A = 0x7DE - SYS___GMTIME_A = 0x7AF - SYS___GMTIME_R_A = 0x7B0 - SYS___INET_PTON_A = 0x7BC - SYS___J0_H = 0x7EE - SYS___J1_H = 0x7EF - SYS___JN_H = 0x7F0 - SYS___LOCALTIME_A = 0x7B1 - SYS___LOCALTIME_R_A = 0x7B2 - SYS___MALLOC24 = 0x7FC - SYS___MALLOC31 = 0x7FD - SYS___MKTIME_A = 0x7B3 - SYS___MODFF_H = 0x7F8 - SYS___MODFL_H = 0x7F9 - SYS___MODF_H = 0x7EC - SYS___OPENDIR_A = 0x7C2 - SYS___OSNAME = 0x7E0 - SYS___PUTWCHAR_A = 0x7A7 - SYS___PUTWC_A = 0x7A6 - SYS___READDIR_A = 0x7C3 - SYS___STRTOLL_A = 0x7A3 - SYS___STRTOULL_A = 0x7A4 - SYS___SYSLOG_A = 0x7BD - SYS___TZZNA = 0x7B4 - SYS___UNGETWC_A = 0x7A9 - SYS___UTIME_A = 0x7A0 - SYS___VFPRINTF2_A = 0x7E7 - SYS___VPRINTF2_A = 0x7E8 - SYS___VSPRINTF2_A = 0x7E9 - SYS___VSWPRNTF2_A = 0x7BB - SYS___WCSTOD_A = 0x7D9 - SYS___WCSTOL_A = 0x7DA - SYS___WCSTOUL_A = 0x7DB - SYS___WCTOB_A = 0x7E5 - SYS___Y0_H = 0x7F1 - SYS___Y1_H = 0x7F2 - SYS___YN_H = 0x7F3 - SYS_____OPENDIR2_A = 0x7BF - SYS_____OSNAME_A = 0x7E1 - SYS_____READDIR2_A = 0x7C0 - SYS_DLCLOSE = 0x8DF - SYS_DLERROR = 0x8E0 - SYS_DLOPEN = 0x8DD - SYS_DLSYM = 0x8DE - SYS_FLOCKFILE = 0x8D3 - SYS_FTRYLOCKFILE = 0x8D4 - SYS_FUNLOCKFILE = 0x8D5 - SYS_GETCHAR_UNLOCKED = 0x8D7 - SYS_GETC_UNLOCKED = 0x8D6 - SYS_PUTCHAR_UNLOCKED = 0x8D9 - SYS_PUTC_UNLOCKED = 0x8D8 - SYS_SNPRINTF = 0x8DA - SYS_VSNPRINTF = 0x8DB - SYS_WCSCSPN = 0x08B - SYS_WCSLEN = 0x08C - SYS_WCSNCAT = 0x08D - SYS_WCSNCMP = 0x08A - SYS_WCSNCPY = 0x08F - SYS_WCSSPN = 0x08E - SYS___ABSF_H = 0x8E7 - SYS___ABSL_H = 0x8E8 - SYS___ABS_H = 0x8E6 - SYS___ACOSF_H = 0x8EA - SYS___ACOSH_H = 0x8EC - SYS___ACOSL_H = 0x8EB - SYS___ACOS_H = 0x8E9 - SYS___ASINF_H = 0x8EE - SYS___ASINH_H = 0x8F0 - SYS___ASINL_H = 0x8EF - SYS___ASIN_H = 0x8ED - SYS___ATAN2F_H = 0x8F8 - SYS___ATAN2L_H = 0x8F9 - SYS___ATAN2_H = 0x8F7 - SYS___ATANF_H = 0x8F2 - SYS___ATANHF_H = 0x8F5 - SYS___ATANHL_H = 0x8F6 - SYS___ATANH_H = 0x8F4 - SYS___ATANL_H = 0x8F3 - SYS___ATAN_H = 0x8F1 - SYS___CBRT_H = 0x8FA - SYS___COPYSIGNF_H = 0x8FB - SYS___COPYSIGNL_H = 0x8FC - SYS___COSF_H = 0x8FE - SYS___COSL_H = 0x8FF - SYS___COS_H = 0x8FD - SYS___DLERROR_A = 0x8D2 - SYS___DLOPEN_A = 0x8D0 - SYS___DLSYM_A = 0x8D1 - SYS___GETUTXENT_A = 0x8C6 - SYS___GETUTXID_A = 0x8C7 - SYS___GETUTXLINE_A = 0x8C8 - SYS___ITOA = 0x8AA - SYS___ITOA_A = 0x8B0 - SYS___LE_CONDITION_TOKEN_BUILD = 0x8A5 - SYS___LE_MSG_ADD_INSERT = 0x8A6 - SYS___LE_MSG_GET = 0x8A7 - SYS___LE_MSG_GET_AND_WRITE = 0x8A8 - SYS___LE_MSG_WRITE = 0x8A9 - SYS___LLTOA = 0x8AE - SYS___LLTOA_A = 0x8B4 - SYS___LTOA = 0x8AC - SYS___LTOA_A = 0x8B2 - SYS___PUTCHAR_UNLOCKED_A = 0x8CC - SYS___PUTC_UNLOCKED_A = 0x8CB - SYS___PUTUTXLINE_A = 0x8C9 - SYS___RESET_EXCEPTION_HANDLER = 0x8E3 - SYS___REXEC_A = 0x8C4 - SYS___REXEC_AF_A = 0x8C5 - SYS___SET_EXCEPTION_HANDLER = 0x8E2 - SYS___SNPRINTF_A = 0x8CD - SYS___SUPERKILL = 0x8A4 - SYS___TCGETATTR_A = 0x8A1 - SYS___TCSETATTR_A = 0x8A2 - SYS___ULLTOA = 0x8AF - SYS___ULLTOA_A = 0x8B5 - SYS___ULTOA = 0x8AD - SYS___ULTOA_A = 0x8B3 - SYS___UTOA = 0x8AB - SYS___UTOA_A = 0x8B1 - SYS___VHM_EVENT = 0x8E4 - SYS___VSNPRINTF_A = 0x8CE - SYS_____GETENV_A = 0x8C3 - SYS_____UTMPXNAME_A = 0x8CA - SYS_CACOSH = 0x9A0 - SYS_CACOSHF = 0x9A3 - SYS_CACOSHL = 0x9A6 - SYS_CARG = 0x9A9 - SYS_CARGF = 0x9AC - SYS_CARGL = 0x9AF - SYS_CASIN = 0x9B2 - SYS_CASINF = 0x9B5 - SYS_CASINH = 0x9BB - SYS_CASINHF = 0x9BE - SYS_CASINHL = 0x9C1 - SYS_CASINL = 0x9B8 - SYS_CATAN = 0x9C4 - SYS_CATANF = 0x9C7 - SYS_CATANH = 0x9CD - SYS_CATANHF = 0x9D0 - SYS_CATANHL = 0x9D3 - SYS_CATANL = 0x9CA - SYS_CCOS = 0x9D6 - SYS_CCOSF = 0x9D9 - SYS_CCOSH = 0x9DF - SYS_CCOSHF = 0x9E2 - SYS_CCOSHL = 0x9E5 - SYS_CCOSL = 0x9DC - SYS_CEXP = 0x9E8 - SYS_CEXPF = 0x9EB - SYS_CEXPL = 0x9EE - SYS_CIMAG = 0x9F1 - SYS_CIMAGF = 0x9F4 - SYS_CIMAGL = 0x9F7 - SYS_CLOGF = 0x9FD - SYS_MEMCHR = 0x09B - SYS_MEMCMP = 0x09A - SYS_STRCOLL = 0x09C - SYS_STRNCMP = 0x09D - SYS_STRRCHR = 0x09F - SYS_STRXFRM = 0x09E - SYS___CACOSHF_B = 0x9A4 - SYS___CACOSHF_H = 0x9A5 - SYS___CACOSHL_B = 0x9A7 - SYS___CACOSHL_H = 0x9A8 - SYS___CACOSH_B = 0x9A1 - SYS___CACOSH_H = 0x9A2 - SYS___CARGF_B = 0x9AD - SYS___CARGF_H = 0x9AE - SYS___CARGL_B = 0x9B0 - SYS___CARGL_H = 0x9B1 - SYS___CARG_B = 0x9AA - SYS___CARG_H = 0x9AB - SYS___CASINF_B = 0x9B6 - SYS___CASINF_H = 0x9B7 - SYS___CASINHF_B = 0x9BF - SYS___CASINHF_H = 0x9C0 - SYS___CASINHL_B = 0x9C2 - SYS___CASINHL_H = 0x9C3 - SYS___CASINH_B = 0x9BC - SYS___CASINH_H = 0x9BD - SYS___CASINL_B = 0x9B9 - SYS___CASINL_H = 0x9BA - SYS___CASIN_B = 0x9B3 - SYS___CASIN_H = 0x9B4 - SYS___CATANF_B = 0x9C8 - SYS___CATANF_H = 0x9C9 - SYS___CATANHF_B = 0x9D1 - SYS___CATANHF_H = 0x9D2 - SYS___CATANHL_B = 0x9D4 - SYS___CATANHL_H = 0x9D5 - SYS___CATANH_B = 0x9CE - SYS___CATANH_H = 0x9CF - SYS___CATANL_B = 0x9CB - SYS___CATANL_H = 0x9CC - SYS___CATAN_B = 0x9C5 - SYS___CATAN_H = 0x9C6 - SYS___CCOSF_B = 0x9DA - SYS___CCOSF_H = 0x9DB - SYS___CCOSHF_B = 0x9E3 - SYS___CCOSHF_H = 0x9E4 - SYS___CCOSHL_B = 0x9E6 - SYS___CCOSHL_H = 0x9E7 - SYS___CCOSH_B = 0x9E0 - SYS___CCOSH_H = 0x9E1 - SYS___CCOSL_B = 0x9DD - SYS___CCOSL_H = 0x9DE - SYS___CCOS_B = 0x9D7 - SYS___CCOS_H = 0x9D8 - SYS___CEXPF_B = 0x9EC - SYS___CEXPF_H = 0x9ED - SYS___CEXPL_B = 0x9EF - SYS___CEXPL_H = 0x9F0 - SYS___CEXP_B = 0x9E9 - SYS___CEXP_H = 0x9EA - SYS___CIMAGF_B = 0x9F5 - SYS___CIMAGF_H = 0x9F6 - SYS___CIMAGL_B = 0x9F8 - SYS___CIMAGL_H = 0x9F9 - SYS___CIMAG_B = 0x9F2 - SYS___CIMAG_H = 0x9F3 - SYS___CLOG = 0x9FA - SYS___CLOGF_B = 0x9FE - SYS___CLOGF_H = 0x9FF - SYS___CLOG_B = 0x9FB - SYS___CLOG_H = 0x9FC - SYS_ISWCTYPE = 0x10C - SYS_ISWXDIGI = 0x10A - SYS_ISWXDIGIT = 0x10A - SYS_MBSINIT = 0x10F - SYS_TOWLOWER = 0x10D - SYS_TOWUPPER = 0x10E - SYS_WCTYPE = 0x10B - SYS_WCSSTR = 0x11B - SYS___RPMTCH = 0x11A - SYS_WCSTOD = 0x12E - SYS_WCSTOK = 0x12C - SYS_WCSTOL = 0x12D - SYS_WCSTOUL = 0x12F - SYS_FGETWC = 0x13C - SYS_FGETWS = 0x13D - SYS_FPUTWC = 0x13E - SYS_FPUTWS = 0x13F - SYS_REGERROR = 0x13B - SYS_REGFREE = 0x13A - SYS_COLLEQUIV = 0x14F - SYS_COLLTOSTR = 0x14E - SYS_ISMCCOLLEL = 0x14C - SYS_STRTOCOLL = 0x14D - SYS_DLLFREE = 0x16F - SYS_DLLQUERYFN = 0x16D - SYS_DLLQUERYVAR = 0x16E - SYS_GETMCCOLL = 0x16A - SYS_GETWMCCOLL = 0x16B - SYS___ERR2AD = 0x16C - SYS_CFSETOSPEED = 0x17A - SYS_CHDIR = 0x17B - SYS_CHMOD = 0x17C - SYS_CHOWN = 0x17D - SYS_CLOSE = 0x17E - SYS_CLOSEDIR = 0x17F - SYS_LOG = 0x017 - SYS_COSH = 0x018 - SYS_FCHMOD = 0x18A - SYS_FCHOWN = 0x18B - SYS_FCNTL = 0x18C - SYS_FILENO = 0x18D - SYS_FORK = 0x18E - SYS_FPATHCONF = 0x18F - SYS_GETLOGIN = 0x19A - SYS_GETPGRP = 0x19C - SYS_GETPID = 0x19D - SYS_GETPPID = 0x19E - SYS_GETPWNAM = 0x19F - SYS_TANH = 0x019 - SYS_W_GETMNTENT = 0x19B - SYS_POW = 0x020 - SYS_PTHREAD_SELF = 0x20A - SYS_PTHREAD_SETINTR = 0x20B - SYS_PTHREAD_SETINTRTYPE = 0x20C - SYS_PTHREAD_SETSPECIFIC = 0x20D - SYS_PTHREAD_TESTINTR = 0x20E - SYS_PTHREAD_YIELD = 0x20F - SYS_SQRT = 0x021 - SYS_FLOOR = 0x022 - SYS_J1 = 0x023 - SYS_WCSPBRK = 0x23F - SYS_BSEARCH = 0x24C - SYS_FABS = 0x024 - SYS_GETENV = 0x24A - SYS_LDIV = 0x24D - SYS_SYSTEM = 0x24B - SYS_FMOD = 0x025 - SYS___RETHROW = 0x25F - SYS___THROW = 0x25E - SYS_J0 = 0x026 - SYS_PUTENV = 0x26A - SYS___GETENV = 0x26F - SYS_SEMCTL = 0x27A - SYS_SEMGET = 0x27B - SYS_SEMOP = 0x27C - SYS_SHMAT = 0x27D - SYS_SHMCTL = 0x27E - SYS_SHMDT = 0x27F - SYS_YN = 0x027 - SYS_JN = 0x028 - SYS_SIGALTSTACK = 0x28A - SYS_SIGHOLD = 0x28B - SYS_SIGIGNORE = 0x28C - SYS_SIGINTERRUPT = 0x28D - SYS_SIGPAUSE = 0x28E - SYS_SIGRELSE = 0x28F - SYS_GETOPT = 0x29A - SYS_GETSUBOPT = 0x29D - SYS_LCHOWN = 0x29B - SYS_SETPGRP = 0x29E - SYS_TRUNCATE = 0x29C - SYS_Y0 = 0x029 - SYS___GDERR = 0x29F - SYS_ISALPHA = 0x030 - SYS_VFORK = 0x30F - SYS__LONGJMP = 0x30D - SYS__SETJMP = 0x30E - SYS_GLOB = 0x31A - SYS_GLOBFREE = 0x31B - SYS_ISALNUM = 0x031 - SYS_PUTW = 0x31C - SYS_SEEKDIR = 0x31D - SYS_TELLDIR = 0x31E - SYS_TEMPNAM = 0x31F - SYS_GETTIMEOFDAY_R = 0x32E - SYS_ISLOWER = 0x032 - SYS_LGAMMA = 0x32C - SYS_REMAINDER = 0x32A - SYS_SCALB = 0x32B - SYS_SYNC = 0x32F - SYS_TTYSLOT = 0x32D - SYS_ENDPROTOENT = 0x33A - SYS_ENDSERVENT = 0x33B - SYS_GETHOSTBYADDR = 0x33D - SYS_GETHOSTBYADDR_R = 0x33C - SYS_GETHOSTBYNAME = 0x33F - SYS_GETHOSTBYNAME_R = 0x33E - SYS_ISCNTRL = 0x033 - SYS_GETSERVBYNAME = 0x34A - SYS_GETSERVBYPORT = 0x34B - SYS_GETSERVENT = 0x34C - SYS_GETSOCKNAME = 0x34D - SYS_GETSOCKOPT = 0x34E - SYS_INET_ADDR = 0x34F - SYS_ISDIGIT = 0x034 - SYS_ISGRAPH = 0x035 - SYS_SELECT = 0x35B - SYS_SELECTEX = 0x35C - SYS_SEND = 0x35D - SYS_SENDTO = 0x35F - SYS_CHROOT = 0x36A - SYS_ISNAN = 0x36D - SYS_ISUPPER = 0x036 - SYS_ULIMIT = 0x36C - SYS_UTIMES = 0x36E - SYS_W_STATVFS = 0x36B - SYS___H_ERRNO = 0x36F - SYS_GRANTPT = 0x37A - SYS_ISPRINT = 0x037 - SYS_TCGETSID = 0x37C - SYS_UNLOCKPT = 0x37B - SYS___TCGETCP = 0x37D - SYS___TCSETCP = 0x37E - SYS___TCSETTABLES = 0x37F - SYS_ISPUNCT = 0x038 - SYS_NLIST = 0x38C - SYS___IPDBCS = 0x38D - SYS___IPDSPX = 0x38E - SYS___IPMSGC = 0x38F - SYS___STHOSTENT = 0x38B - SYS___STSERVENT = 0x38A - SYS_ISSPACE = 0x039 - SYS_COS = 0x040 - SYS_T_ALLOC = 0x40A - SYS_T_BIND = 0x40B - SYS_T_CLOSE = 0x40C - SYS_T_CONNECT = 0x40D - SYS_T_ERROR = 0x40E - SYS_T_FREE = 0x40F - SYS_TAN = 0x041 - SYS_T_RCVREL = 0x41A - SYS_T_RCVUDATA = 0x41B - SYS_T_RCVUDERR = 0x41C - SYS_T_SND = 0x41D - SYS_T_SNDDIS = 0x41E - SYS_T_SNDREL = 0x41F - SYS_GETPMSG = 0x42A - SYS_ISASTREAM = 0x42B - SYS_PUTMSG = 0x42C - SYS_PUTPMSG = 0x42D - SYS_SINH = 0x042 - SYS___ISPOSIXON = 0x42E - SYS___OPENMVSREL = 0x42F - SYS_ACOS = 0x043 - SYS_ATAN = 0x044 - SYS_ATAN2 = 0x045 - SYS_FTELL = 0x046 - SYS_FGETPOS = 0x047 - SYS_SOCK_DEBUG = 0x47A - SYS_SOCK_DO_TESTSTOR = 0x47D - SYS_TAKESOCKET = 0x47E - SYS___SERVER_INIT = 0x47F - SYS_FSEEK = 0x048 - SYS___IPHOST = 0x48B - SYS___IPNODE = 0x48C - SYS___SERVER_CLASSIFY_CREATE = 0x48D - SYS___SERVER_CLASSIFY_DESTROY = 0x48E - SYS___SERVER_CLASSIFY_RESET = 0x48F - SYS___SMF_RECORD = 0x48A - SYS_FSETPOS = 0x049 - SYS___FNWSA = 0x49B - SYS___SPAWN2 = 0x49D - SYS___SPAWNP2 = 0x49E - SYS_ATOF = 0x050 - SYS_PTHREAD_MUTEXATTR_GETPSHARED = 0x50A - SYS_PTHREAD_MUTEXATTR_SETPSHARED = 0x50B - SYS_PTHREAD_RWLOCK_DESTROY = 0x50C - SYS_PTHREAD_RWLOCK_INIT = 0x50D - SYS_PTHREAD_RWLOCK_RDLOCK = 0x50E - SYS_PTHREAD_RWLOCK_TRYRDLOCK = 0x50F - SYS_ATOI = 0x051 - SYS___FP_CLASS = 0x51D - SYS___FP_CLR_FLAG = 0x51A - SYS___FP_FINITE = 0x51E - SYS___FP_ISNAN = 0x51F - SYS___FP_RAISE_XCP = 0x51C - SYS___FP_READ_FLAG = 0x51B - SYS_RAND = 0x052 - SYS_SIGTIMEDWAIT = 0x52D - SYS_SIGWAITINFO = 0x52E - SYS___CHKBFP = 0x52F - SYS___FPC_RS = 0x52C - SYS___FPC_RW = 0x52A - SYS___FPC_SM = 0x52B - SYS_STRTOD = 0x053 - SYS_STRTOL = 0x054 - SYS_STRTOUL = 0x055 - SYS_MALLOC = 0x056 - SYS_SRAND = 0x057 - SYS_CALLOC = 0x058 - SYS_FREE = 0x059 - SYS___OSENV = 0x59F - SYS___W_PIOCTL = 0x59E - SYS_LONGJMP = 0x060 - SYS___FLOORF_B = 0x60A - SYS___FLOORL_B = 0x60B - SYS___FREXPF_B = 0x60C - SYS___FREXPL_B = 0x60D - SYS___LDEXPF_B = 0x60E - SYS___LDEXPL_B = 0x60F - SYS_SIGNAL = 0x061 - SYS___ATAN2F_B = 0x61A - SYS___ATAN2L_B = 0x61B - SYS___COSHF_B = 0x61C - SYS___COSHL_B = 0x61D - SYS___EXPF_B = 0x61E - SYS___EXPL_B = 0x61F - SYS_TMPNAM = 0x062 - SYS___ABSF_B = 0x62A - SYS___ABSL_B = 0x62C - SYS___ABS_B = 0x62B - SYS___FMODF_B = 0x62D - SYS___FMODL_B = 0x62E - SYS___MODFF_B = 0x62F - SYS_ATANL = 0x63A - SYS_CEILF = 0x63B - SYS_CEILL = 0x63C - SYS_COSF = 0x63D - SYS_COSHF = 0x63F - SYS_COSL = 0x63E - SYS_REMOVE = 0x063 - SYS_POWL = 0x64A - SYS_RENAME = 0x064 - SYS_SINF = 0x64B - SYS_SINHF = 0x64F - SYS_SINL = 0x64C - SYS_SQRTF = 0x64D - SYS_SQRTL = 0x64E - SYS_BTOWC = 0x65F - SYS_FREXPL = 0x65A - SYS_LDEXPF = 0x65B - SYS_LDEXPL = 0x65C - SYS_MODFF = 0x65D - SYS_MODFL = 0x65E - SYS_TMPFILE = 0x065 - SYS_FREOPEN = 0x066 - SYS___CHARMAP_INIT_A = 0x66E - SYS___GETHOSTBYADDR_R_A = 0x66C - SYS___GETHOSTBYNAME_A = 0x66A - SYS___GETHOSTBYNAME_R_A = 0x66D - SYS___MBLEN_A = 0x66F - SYS___RES_INIT_A = 0x66B - SYS_FCLOSE = 0x067 - SYS___GETGRGID_R_A = 0x67D - SYS___WCSTOMBS_A = 0x67A - SYS___WCSTOMBS_STD_A = 0x67B - SYS___WCSWIDTH_A = 0x67C - SYS___WCSWIDTH_ASIA = 0x67F - SYS___WCSWIDTH_STD_A = 0x67E - SYS_FFLUSH = 0x068 - SYS___GETLOGIN_R_A = 0x68E - SYS___GETPWNAM_R_A = 0x68C - SYS___GETPWUID_R_A = 0x68D - SYS___TTYNAME_R_A = 0x68F - SYS___WCWIDTH_ASIA = 0x68B - SYS___WCWIDTH_STD_A = 0x68A - SYS_FOPEN = 0x069 - SYS___REGEXEC_A = 0x69A - SYS___REGEXEC_STD_A = 0x69B - SYS___REGFREE_A = 0x69C - SYS___REGFREE_STD_A = 0x69D - SYS___STRCOLL_A = 0x69E - SYS___STRCOLL_C_A = 0x69F - SYS_SCANF = 0x070 - SYS___A64L_A = 0x70C - SYS___ECVT_A = 0x70D - SYS___FCVT_A = 0x70E - SYS___GCVT_A = 0x70F - SYS___STRTOUL_A = 0x70A - SYS_____AE_CORRESTBL_QUERY_A = 0x70B - SYS_SPRINTF = 0x071 - SYS___ACCESS_A = 0x71F - SYS___CATOPEN_A = 0x71E - SYS___GETOPT_A = 0x71D - SYS___REALPATH_A = 0x71A - SYS___SETENV_A = 0x71B - SYS___SYSTEM_A = 0x71C - SYS_FGETC = 0x072 - SYS___GAI_STRERROR_A = 0x72F - SYS___RMDIR_A = 0x72A - SYS___STATVFS_A = 0x72B - SYS___SYMLINK_A = 0x72C - SYS___TRUNCATE_A = 0x72D - SYS___UNLINK_A = 0x72E - SYS_VFPRINTF = 0x073 - SYS___ISSPACE_A = 0x73A - SYS___ISUPPER_A = 0x73B - SYS___ISWALNUM_A = 0x73F - SYS___ISXDIGIT_A = 0x73C - SYS___TOLOWER_A = 0x73D - SYS___TOUPPER_A = 0x73E - SYS_VPRINTF = 0x074 - SYS___CONFSTR_A = 0x74B - SYS___FDOPEN_A = 0x74E - SYS___FLDATA_A = 0x74F - SYS___FTOK_A = 0x74C - SYS___ISWXDIGIT_A = 0x74A - SYS___MKTEMP_A = 0x74D - SYS_VSPRINTF = 0x075 - SYS___GETGRGID_A = 0x75A - SYS___GETGRNAM_A = 0x75B - SYS___GETGROUPSBYNAME_A = 0x75C - SYS___GETHOSTENT_A = 0x75D - SYS___GETHOSTNAME_A = 0x75E - SYS___GETLOGIN_A = 0x75F - SYS_GETC = 0x076 - SYS___CREATEWORKUNIT_A = 0x76A - SYS___CTERMID_A = 0x76B - SYS___FMTMSG_A = 0x76C - SYS___INITGROUPS_A = 0x76D - SYS___MSGRCV_A = 0x76F - SYS_____LOGIN_A = 0x76E - SYS_FGETS = 0x077 - SYS___STRCASECMP_A = 0x77B - SYS___STRNCASECMP_A = 0x77C - SYS___TTYNAME_A = 0x77D - SYS___UNAME_A = 0x77E - SYS___UTIMES_A = 0x77F - SYS_____SERVER_PWU_A = 0x77A - SYS_FPUTC = 0x078 - SYS___CREAT_O_A = 0x78E - SYS___ENVNA = 0x78F - SYS___FREAD_A = 0x78A - SYS___FWRITE_A = 0x78B - SYS___ISASCII = 0x78D - SYS___OPEN_O_A = 0x78C - SYS_FPUTS = 0x079 - SYS___ASCTIME_A = 0x79C - SYS___CTIME_A = 0x79D - SYS___GETDATE_A = 0x79E - SYS___GETSERVBYPORT_A = 0x79A - SYS___GETSERVENT_A = 0x79B - SYS___TZSET_A = 0x79F - SYS_ACL_FROM_TEXT = 0x80C - SYS_ACL_SET_FD = 0x80A - SYS_ACL_SET_FILE = 0x80B - SYS_ACL_SORT = 0x80E - SYS_ACL_TO_TEXT = 0x80D - SYS_UNGETC = 0x080 - SYS___SHUTDOWN_REGISTRATION = 0x80F - SYS_FREAD = 0x081 - SYS_FREEADDRINFO = 0x81A - SYS_GAI_STRERROR = 0x81B - SYS_REXEC_AF = 0x81C - SYS___DYNALLOC_A = 0x81F - SYS___POE = 0x81D - SYS_WCSTOMBS = 0x082 - SYS___INET_ADDR_A = 0x82F - SYS___NLIST_A = 0x82A - SYS_____TCGETCP_A = 0x82B - SYS_____TCSETCP_A = 0x82C - SYS_____W_PIOCTL_A = 0x82E - SYS_MBTOWC = 0x083 - SYS___CABEND = 0x83D - SYS___LE_CIB_GET = 0x83E - SYS___RECVMSG_A = 0x83B - SYS___SENDMSG_A = 0x83A - SYS___SET_LAA_FOR_JIT = 0x83F - SYS_____LCHATTR_A = 0x83C - SYS_WCTOMB = 0x084 - SYS___CBRTL_B = 0x84A - SYS___COPYSIGNF_B = 0x84B - SYS___COPYSIGNL_B = 0x84C - SYS___COTANF_B = 0x84D - SYS___COTANL_B = 0x84F - SYS___COTAN_B = 0x84E - SYS_MBSTOWCS = 0x085 - SYS___LOG1PL_B = 0x85A - SYS___LOG2F_B = 0x85B - SYS___LOG2L_B = 0x85D - SYS___LOG2_B = 0x85C - SYS___REMAINDERF_B = 0x85E - SYS___REMAINDERL_B = 0x85F - SYS_ACOSHF = 0x86E - SYS_ACOSHL = 0x86F - SYS_WCSCPY = 0x086 - SYS___ERFCF_B = 0x86D - SYS___ERFF_B = 0x86C - SYS___LROUNDF_B = 0x86A - SYS___LROUND_B = 0x86B - SYS_COTANL = 0x87A - SYS_EXP2F = 0x87B - SYS_EXP2L = 0x87C - SYS_EXPM1F = 0x87D - SYS_EXPM1L = 0x87E - SYS_FDIMF = 0x87F - SYS_WCSCAT = 0x087 - SYS___COTANL = 0x87A - SYS_REMAINDERF = 0x88A - SYS_REMAINDERL = 0x88B - SYS_REMAINDF = 0x88A - SYS_REMAINDL = 0x88B - SYS_REMQUO = 0x88D - SYS_REMQUOF = 0x88C - SYS_REMQUOL = 0x88E - SYS_TGAMMAF = 0x88F - SYS_WCSCHR = 0x088 - SYS_ERFCF = 0x89B - SYS_ERFCL = 0x89C - SYS_ERFL = 0x89A - SYS_EXP2 = 0x89E - SYS_WCSCMP = 0x089 - SYS___EXP2_B = 0x89D - SYS___FAR_JUMP = 0x89F - SYS_ABS = 0x090 - SYS___ERFCL_H = 0x90A - SYS___EXPF_H = 0x90C - SYS___EXPL_H = 0x90D - SYS___EXPM1_H = 0x90E - SYS___EXP_H = 0x90B - SYS___FDIM_H = 0x90F - SYS_DIV = 0x091 - SYS___LOG2F_H = 0x91F - SYS___LOG2_H = 0x91E - SYS___LOGB_H = 0x91D - SYS___LOGF_H = 0x91B - SYS___LOGL_H = 0x91C - SYS___LOG_H = 0x91A - SYS_LABS = 0x092 - SYS___POWL_H = 0x92A - SYS___REMAINDER_H = 0x92B - SYS___RINT_H = 0x92C - SYS___SCALB_H = 0x92D - SYS___SINF_H = 0x92F - SYS___SIN_H = 0x92E - SYS_STRNCPY = 0x093 - SYS___TANHF_H = 0x93B - SYS___TANHL_H = 0x93C - SYS___TANH_H = 0x93A - SYS___TGAMMAF_H = 0x93E - SYS___TGAMMA_H = 0x93D - SYS___TRUNC_H = 0x93F - SYS_MEMCPY = 0x094 - SYS_VFWSCANF = 0x94A - SYS_VSWSCANF = 0x94E - SYS_VWSCANF = 0x94C - SYS_INET6_RTH_ADD = 0x95D - SYS_INET6_RTH_INIT = 0x95C - SYS_INET6_RTH_REVERSE = 0x95E - SYS_INET6_RTH_SEGMENTS = 0x95F - SYS_INET6_RTH_SPACE = 0x95B - SYS_MEMMOVE = 0x095 - SYS_WCSTOLD = 0x95A - SYS_STRCPY = 0x096 - SYS_STRCMP = 0x097 - SYS_CABS = 0x98E - SYS_STRCAT = 0x098 - SYS___CABS_B = 0x98F - SYS___POW_II = 0x98A - SYS___POW_II_B = 0x98B - SYS___POW_II_H = 0x98C - SYS_CACOSF = 0x99A - SYS_CACOSL = 0x99D - SYS_STRNCAT = 0x099 - SYS___CACOSF_B = 0x99B - SYS___CACOSF_H = 0x99C - SYS___CACOSL_B = 0x99E - SYS___CACOSL_H = 0x99F - SYS_ISWALPHA = 0x100 - SYS_ISWBLANK = 0x101 - SYS___ISWBLK = 0x101 - SYS_ISWCNTRL = 0x102 - SYS_ISWDIGIT = 0x103 - SYS_ISWGRAPH = 0x104 - SYS_ISWLOWER = 0x105 - SYS_ISWPRINT = 0x106 - SYS_ISWPUNCT = 0x107 - SYS_ISWSPACE = 0x108 - SYS_ISWUPPER = 0x109 - SYS_WCTOB = 0x110 - SYS_MBRLEN = 0x111 - SYS_MBRTOWC = 0x112 - SYS_MBSRTOWC = 0x113 - SYS_MBSRTOWCS = 0x113 - SYS_WCRTOMB = 0x114 - SYS_WCSRTOMB = 0x115 - SYS_WCSRTOMBS = 0x115 - SYS___CSID = 0x116 - SYS___WCSID = 0x117 - SYS_STRPTIME = 0x118 - SYS___STRPTM = 0x118 - SYS_STRFMON = 0x119 - SYS_WCSCOLL = 0x130 - SYS_WCSXFRM = 0x131 - SYS_WCSWIDTH = 0x132 - SYS_WCWIDTH = 0x133 - SYS_WCSFTIME = 0x134 - SYS_SWPRINTF = 0x135 - SYS_VSWPRINT = 0x136 - SYS_VSWPRINTF = 0x136 - SYS_SWSCANF = 0x137 - SYS_REGCOMP = 0x138 - SYS_REGEXEC = 0x139 - SYS_GETWC = 0x140 - SYS_GETWCHAR = 0x141 - SYS_PUTWC = 0x142 - SYS_PUTWCHAR = 0x143 - SYS_UNGETWC = 0x144 - SYS_ICONV_OPEN = 0x145 - SYS_ICONV = 0x146 - SYS_ICONV_CLOSE = 0x147 - SYS_COLLRANGE = 0x150 - SYS_CCLASS = 0x151 - SYS_COLLORDER = 0x152 - SYS___DEMANGLE = 0x154 - SYS_FDOPEN = 0x155 - SYS___ERRNO = 0x156 - SYS___ERRNO2 = 0x157 - SYS___TERROR = 0x158 - SYS_MAXCOLL = 0x169 - SYS_DLLLOAD = 0x170 - SYS__EXIT = 0x174 - SYS_ACCESS = 0x175 - SYS_ALARM = 0x176 - SYS_CFGETISPEED = 0x177 - SYS_CFGETOSPEED = 0x178 - SYS_CFSETISPEED = 0x179 - SYS_CREAT = 0x180 - SYS_CTERMID = 0x181 - SYS_DUP = 0x182 - SYS_DUP2 = 0x183 - SYS_EXECL = 0x184 - SYS_EXECLE = 0x185 - SYS_EXECLP = 0x186 - SYS_EXECV = 0x187 - SYS_EXECVE = 0x188 - SYS_EXECVP = 0x189 - SYS_FSTAT = 0x190 - SYS_FSYNC = 0x191 - SYS_FTRUNCATE = 0x192 - SYS_GETCWD = 0x193 - SYS_GETEGID = 0x194 - SYS_GETEUID = 0x195 - SYS_GETGID = 0x196 - SYS_GETGRGID = 0x197 - SYS_GETGRNAM = 0x198 - SYS_GETGROUPS = 0x199 - SYS_PTHREAD_MUTEXATTR_DESTROY = 0x200 - SYS_PTHREAD_MUTEXATTR_SETKIND_NP = 0x201 - SYS_PTHREAD_MUTEXATTR_GETKIND_NP = 0x202 - SYS_PTHREAD_MUTEX_INIT = 0x203 - SYS_PTHREAD_MUTEX_DESTROY = 0x204 - SYS_PTHREAD_MUTEX_LOCK = 0x205 - SYS_PTHREAD_MUTEX_TRYLOCK = 0x206 - SYS_PTHREAD_MUTEX_UNLOCK = 0x207 - SYS_PTHREAD_ONCE = 0x209 - SYS_TW_OPEN = 0x210 - SYS_TW_FCNTL = 0x211 - SYS_PTHREAD_JOIN_D4_NP = 0x212 - SYS_PTHREAD_CONDATTR_SETKIND_NP = 0x213 - SYS_PTHREAD_CONDATTR_GETKIND_NP = 0x214 - SYS_EXTLINK_NP = 0x215 - SYS___PASSWD = 0x216 - SYS_SETGROUPS = 0x217 - SYS_INITGROUPS = 0x218 - SYS_WCSRCHR = 0x240 - SYS_SVC99 = 0x241 - SYS___SVC99 = 0x241 - SYS_WCSWCS = 0x242 - SYS_LOCALECO = 0x243 - SYS_LOCALECONV = 0x243 - SYS___LIBREL = 0x244 - SYS_RELEASE = 0x245 - SYS___RLSE = 0x245 - SYS_FLOCATE = 0x246 - SYS___FLOCT = 0x246 - SYS_FDELREC = 0x247 - SYS___FDLREC = 0x247 - SYS_FETCH = 0x248 - SYS___FETCH = 0x248 - SYS_QSORT = 0x249 - SYS___CLEANUPCATCH = 0x260 - SYS___CATCHMATCH = 0x261 - SYS___CLEAN2UPCATCH = 0x262 - SYS_GETPRIORITY = 0x270 - SYS_NICE = 0x271 - SYS_SETPRIORITY = 0x272 - SYS_GETITIMER = 0x273 - SYS_SETITIMER = 0x274 - SYS_MSGCTL = 0x275 - SYS_MSGGET = 0x276 - SYS_MSGRCV = 0x277 - SYS_MSGSND = 0x278 - SYS_MSGXRCV = 0x279 - SYS___MSGXR = 0x279 - SYS_SHMGET = 0x280 - SYS___GETIPC = 0x281 - SYS_SETGRENT = 0x282 - SYS_GETGRENT = 0x283 - SYS_ENDGRENT = 0x284 - SYS_SETPWENT = 0x285 - SYS_GETPWENT = 0x286 - SYS_ENDPWENT = 0x287 - SYS_BSD_SIGNAL = 0x288 - SYS_KILLPG = 0x289 - SYS_SIGSET = 0x290 - SYS_SIGSTACK = 0x291 - SYS_GETRLIMIT = 0x292 - SYS_SETRLIMIT = 0x293 - SYS_GETRUSAGE = 0x294 - SYS_MMAP = 0x295 - SYS_MPROTECT = 0x296 - SYS_MSYNC = 0x297 - SYS_MUNMAP = 0x298 - SYS_CONFSTR = 0x299 - SYS___NDMTRM = 0x300 - SYS_FTOK = 0x301 - SYS_BASENAME = 0x302 - SYS_DIRNAME = 0x303 - SYS_GETDTABLESIZE = 0x304 - SYS_MKSTEMP = 0x305 - SYS_MKTEMP = 0x306 - SYS_NFTW = 0x307 - SYS_GETWD = 0x308 - SYS_LOCKF = 0x309 - SYS_WORDEXP = 0x310 - SYS_WORDFREE = 0x311 - SYS_GETPGID = 0x312 - SYS_GETSID = 0x313 - SYS___UTMPXNAME = 0x314 - SYS_CUSERID = 0x315 - SYS_GETPASS = 0x316 - SYS_FNMATCH = 0x317 - SYS_FTW = 0x318 - SYS_GETW = 0x319 - SYS_ACOSH = 0x320 - SYS_ASINH = 0x321 - SYS_ATANH = 0x322 - SYS_CBRT = 0x323 - SYS_EXPM1 = 0x324 - SYS_ILOGB = 0x325 - SYS_LOGB = 0x326 - SYS_LOG1P = 0x327 - SYS_NEXTAFTER = 0x328 - SYS_RINT = 0x329 - SYS_SPAWN = 0x330 - SYS_SPAWNP = 0x331 - SYS_GETLOGIN_UU = 0x332 - SYS_ECVT = 0x333 - SYS_FCVT = 0x334 - SYS_GCVT = 0x335 - SYS_ACCEPT = 0x336 - SYS_BIND = 0x337 - SYS_CONNECT = 0x338 - SYS_ENDHOSTENT = 0x339 - SYS_GETHOSTENT = 0x340 - SYS_GETHOSTID = 0x341 - SYS_GETHOSTNAME = 0x342 - SYS_GETNETBYADDR = 0x343 - SYS_GETNETBYNAME = 0x344 - SYS_GETNETENT = 0x345 - SYS_GETPEERNAME = 0x346 - SYS_GETPROTOBYNAME = 0x347 - SYS_GETPROTOBYNUMBER = 0x348 - SYS_GETPROTOENT = 0x349 - SYS_INET_LNAOF = 0x350 - SYS_INET_MAKEADDR = 0x351 - SYS_INET_NETOF = 0x352 - SYS_INET_NETWORK = 0x353 - SYS_INET_NTOA = 0x354 - SYS_IOCTL = 0x355 - SYS_LISTEN = 0x356 - SYS_READV = 0x357 - SYS_RECV = 0x358 - SYS_RECVFROM = 0x359 - SYS_SETHOSTENT = 0x360 - SYS_SETNETENT = 0x361 - SYS_SETPEER = 0x362 - SYS_SETPROTOENT = 0x363 - SYS_SETSERVENT = 0x364 - SYS_SETSOCKOPT = 0x365 - SYS_SHUTDOWN = 0x366 - SYS_SOCKET = 0x367 - SYS_SOCKETPAIR = 0x368 - SYS_WRITEV = 0x369 - SYS_ENDNETENT = 0x370 - SYS_CLOSELOG = 0x371 - SYS_OPENLOG = 0x372 - SYS_SETLOGMASK = 0x373 - SYS_SYSLOG = 0x374 - SYS_PTSNAME = 0x375 - SYS_SETREUID = 0x376 - SYS_SETREGID = 0x377 - SYS_REALPATH = 0x378 - SYS___SIGNGAM = 0x379 - SYS_POLL = 0x380 - SYS_REXEC = 0x381 - SYS___ISASCII2 = 0x382 - SYS___TOASCII2 = 0x383 - SYS_CHPRIORITY = 0x384 - SYS_PTHREAD_ATTR_SETSYNCTYPE_NP = 0x385 - SYS_PTHREAD_ATTR_GETSYNCTYPE_NP = 0x386 - SYS_PTHREAD_SET_LIMIT_NP = 0x387 - SYS___STNETENT = 0x388 - SYS___STPROTOENT = 0x389 - SYS___SELECT1 = 0x390 - SYS_PTHREAD_SECURITY_NP = 0x391 - SYS___CHECK_RESOURCE_AUTH_NP = 0x392 - SYS___CONVERT_ID_NP = 0x393 - SYS___OPENVMREL = 0x394 - SYS_WMEMCHR = 0x395 - SYS_WMEMCMP = 0x396 - SYS_WMEMCPY = 0x397 - SYS_WMEMMOVE = 0x398 - SYS_WMEMSET = 0x399 - SYS___FPUTWC = 0x400 - SYS___PUTWC = 0x401 - SYS___PWCHAR = 0x402 - SYS___WCSFTM = 0x403 - SYS___WCSTOK = 0x404 - SYS___WCWDTH = 0x405 - SYS_T_ACCEPT = 0x409 - SYS_T_GETINFO = 0x410 - SYS_T_GETPROTADDR = 0x411 - SYS_T_GETSTATE = 0x412 - SYS_T_LISTEN = 0x413 - SYS_T_LOOK = 0x414 - SYS_T_OPEN = 0x415 - SYS_T_OPTMGMT = 0x416 - SYS_T_RCV = 0x417 - SYS_T_RCVCONNECT = 0x418 - SYS_T_RCVDIS = 0x419 - SYS_T_SNDUDATA = 0x420 - SYS_T_STRERROR = 0x421 - SYS_T_SYNC = 0x422 - SYS_T_UNBIND = 0x423 - SYS___T_ERRNO = 0x424 - SYS___RECVMSG2 = 0x425 - SYS___SENDMSG2 = 0x426 - SYS_FATTACH = 0x427 - SYS_FDETACH = 0x428 - SYS_GETMSG = 0x429 - SYS_GETCONTEXT = 0x430 - SYS_SETCONTEXT = 0x431 - SYS_MAKECONTEXT = 0x432 - SYS_SWAPCONTEXT = 0x433 - SYS_PTHREAD_GETSPECIFIC_D8_NP = 0x434 - SYS_GETCLIENTID = 0x470 - SYS___GETCLIENTID = 0x471 - SYS_GETSTABLESIZE = 0x472 - SYS_GETIBMOPT = 0x473 - SYS_GETIBMSOCKOPT = 0x474 - SYS_GIVESOCKET = 0x475 - SYS_IBMSFLUSH = 0x476 - SYS_MAXDESC = 0x477 - SYS_SETIBMOPT = 0x478 - SYS_SETIBMSOCKOPT = 0x479 - SYS___SERVER_PWU = 0x480 - SYS_PTHREAD_TAG_NP = 0x481 - SYS___CONSOLE = 0x482 - SYS___WSINIT = 0x483 - SYS___IPTCPN = 0x489 - SYS___SERVER_CLASSIFY = 0x490 - SYS___HEAPRPT = 0x496 - SYS___ISBFP = 0x500 - SYS___FP_CAST = 0x501 - SYS___CERTIFICATE = 0x502 - SYS_SEND_FILE = 0x503 - SYS_AIO_CANCEL = 0x504 - SYS_AIO_ERROR = 0x505 - SYS_AIO_READ = 0x506 - SYS_AIO_RETURN = 0x507 - SYS_AIO_SUSPEND = 0x508 - SYS_AIO_WRITE = 0x509 - SYS_PTHREAD_RWLOCK_TRYWRLOCK = 0x510 - SYS_PTHREAD_RWLOCK_UNLOCK = 0x511 - SYS_PTHREAD_RWLOCK_WRLOCK = 0x512 - SYS_PTHREAD_RWLOCKATTR_GETPSHARED = 0x513 - SYS_PTHREAD_RWLOCKATTR_SETPSHARED = 0x514 - SYS_PTHREAD_RWLOCKATTR_INIT = 0x515 - SYS_PTHREAD_RWLOCKATTR_DESTROY = 0x516 - SYS___CTTBL = 0x517 - SYS_PTHREAD_MUTEXATTR_SETTYPE = 0x518 - SYS_PTHREAD_MUTEXATTR_GETTYPE = 0x519 - SYS___FP_UNORDERED = 0x520 - SYS___FP_READ_RND = 0x521 - SYS___FP_READ_RND_B = 0x522 - SYS___FP_SWAP_RND = 0x523 - SYS___FP_SWAP_RND_B = 0x524 - SYS___FP_LEVEL = 0x525 - SYS___FP_BTOH = 0x526 - SYS___FP_HTOB = 0x527 - SYS___FPC_RD = 0x528 - SYS___FPC_WR = 0x529 - SYS_PTHREAD_SETCANCELTYPE = 0x600 - SYS_PTHREAD_TESTCANCEL = 0x601 - SYS___ATANF_B = 0x602 - SYS___ATANL_B = 0x603 - SYS___CEILF_B = 0x604 - SYS___CEILL_B = 0x605 - SYS___COSF_B = 0x606 - SYS___COSL_B = 0x607 - SYS___FABSF_B = 0x608 - SYS___FABSL_B = 0x609 - SYS___SINF_B = 0x610 - SYS___SINL_B = 0x611 - SYS___TANF_B = 0x612 - SYS___TANL_B = 0x613 - SYS___TANHF_B = 0x614 - SYS___TANHL_B = 0x615 - SYS___ACOSF_B = 0x616 - SYS___ACOSL_B = 0x617 - SYS___ASINF_B = 0x618 - SYS___ASINL_B = 0x619 - SYS___LOGF_B = 0x620 - SYS___LOGL_B = 0x621 - SYS___LOG10F_B = 0x622 - SYS___LOG10L_B = 0x623 - SYS___POWF_B = 0x624 - SYS___POWL_B = 0x625 - SYS___SINHF_B = 0x626 - SYS___SINHL_B = 0x627 - SYS___SQRTF_B = 0x628 - SYS___SQRTL_B = 0x629 - SYS___MODFL_B = 0x630 - SYS_ABSF = 0x631 - SYS_ABSL = 0x632 - SYS_ACOSF = 0x633 - SYS_ACOSL = 0x634 - SYS_ASINF = 0x635 - SYS_ASINL = 0x636 - SYS_ATAN2F = 0x637 - SYS_ATAN2L = 0x638 - SYS_ATANF = 0x639 - SYS_COSHL = 0x640 - SYS_EXPF = 0x641 - SYS_EXPL = 0x642 - SYS_TANHF = 0x643 - SYS_TANHL = 0x644 - SYS_LOG10F = 0x645 - SYS_LOG10L = 0x646 - SYS_LOGF = 0x647 - SYS_LOGL = 0x648 - SYS_POWF = 0x649 - SYS_SINHL = 0x650 - SYS_TANF = 0x651 - SYS_TANL = 0x652 - SYS_FABSF = 0x653 - SYS_FABSL = 0x654 - SYS_FLOORF = 0x655 - SYS_FLOORL = 0x656 - SYS_FMODF = 0x657 - SYS_FMODL = 0x658 - SYS_FREXPF = 0x659 - SYS___CHATTR = 0x660 - SYS___FCHATTR = 0x661 - SYS___TOCCSID = 0x662 - SYS___CSNAMETYPE = 0x663 - SYS___TOCSNAME = 0x664 - SYS___CCSIDTYPE = 0x665 - SYS___AE_CORRESTBL_QUERY = 0x666 - SYS___AE_AUTOCONVERT_STATE = 0x667 - SYS_DN_FIND = 0x668 - SYS___GETHOSTBYADDR_A = 0x669 - SYS___MBLEN_SB_A = 0x670 - SYS___MBLEN_STD_A = 0x671 - SYS___MBLEN_UTF = 0x672 - SYS___MBSTOWCS_A = 0x673 - SYS___MBSTOWCS_STD_A = 0x674 - SYS___MBTOWC_A = 0x675 - SYS___MBTOWC_ISO1 = 0x676 - SYS___MBTOWC_SBCS = 0x677 - SYS___MBTOWC_MBCS = 0x678 - SYS___MBTOWC_UTF = 0x679 - SYS___CSID_A = 0x680 - SYS___CSID_STD_A = 0x681 - SYS___WCSID_A = 0x682 - SYS___WCSID_STD_A = 0x683 - SYS___WCTOMB_A = 0x684 - SYS___WCTOMB_ISO1 = 0x685 - SYS___WCTOMB_STD_A = 0x686 - SYS___WCTOMB_UTF = 0x687 - SYS___WCWIDTH_A = 0x688 - SYS___GETGRNAM_R_A = 0x689 - SYS___READDIR_R_A = 0x690 - SYS___E2A_S = 0x691 - SYS___FNMATCH_A = 0x692 - SYS___FNMATCH_C_A = 0x693 - SYS___EXECL_A = 0x694 - SYS___FNMATCH_STD_A = 0x695 - SYS___REGCOMP_A = 0x696 - SYS___REGCOMP_STD_A = 0x697 - SYS___REGERROR_A = 0x698 - SYS___REGERROR_STD_A = 0x699 - SYS___SWPRINTF_A = 0x700 - SYS___FSCANF_A = 0x701 - SYS___SCANF_A = 0x702 - SYS___SSCANF_A = 0x703 - SYS___SWSCANF_A = 0x704 - SYS___ATOF_A = 0x705 - SYS___ATOI_A = 0x706 - SYS___ATOL_A = 0x707 - SYS___STRTOD_A = 0x708 - SYS___STRTOL_A = 0x709 - SYS___L64A_A = 0x710 - SYS___STRERROR_A = 0x711 - SYS___PERROR_A = 0x712 - SYS___FETCH_A = 0x713 - SYS___GETENV_A = 0x714 - SYS___MKSTEMP_A = 0x717 - SYS___PTSNAME_A = 0x718 - SYS___PUTENV_A = 0x719 - SYS___CHDIR_A = 0x720 - SYS___CHOWN_A = 0x721 - SYS___CHROOT_A = 0x722 - SYS___GETCWD_A = 0x723 - SYS___GETWD_A = 0x724 - SYS___LCHOWN_A = 0x725 - SYS___LINK_A = 0x726 - SYS___PATHCONF_A = 0x727 - SYS___IF_NAMEINDEX_A = 0x728 - SYS___READLINK_A = 0x729 - SYS___EXTLINK_NP_A = 0x730 - SYS___ISALNUM_A = 0x731 - SYS___ISALPHA_A = 0x732 - SYS___A2E_S = 0x733 - SYS___ISCNTRL_A = 0x734 - SYS___ISDIGIT_A = 0x735 - SYS___ISGRAPH_A = 0x736 - SYS___ISLOWER_A = 0x737 - SYS___ISPRINT_A = 0x738 - SYS___ISPUNCT_A = 0x739 - SYS___ISWALPHA_A = 0x740 - SYS___A2E_L = 0x741 - SYS___ISWCNTRL_A = 0x742 - SYS___ISWDIGIT_A = 0x743 - SYS___ISWGRAPH_A = 0x744 - SYS___ISWLOWER_A = 0x745 - SYS___ISWPRINT_A = 0x746 - SYS___ISWPUNCT_A = 0x747 - SYS___ISWSPACE_A = 0x748 - SYS___ISWUPPER_A = 0x749 - SYS___REMOVE_A = 0x750 - SYS___RENAME_A = 0x751 - SYS___TMPNAM_A = 0x752 - SYS___FOPEN_A = 0x753 - SYS___FREOPEN_A = 0x754 - SYS___CUSERID_A = 0x755 - SYS___POPEN_A = 0x756 - SYS___TEMPNAM_A = 0x757 - SYS___FTW_A = 0x758 - SYS___GETGRENT_A = 0x759 - SYS___INET_NTOP_A = 0x760 - SYS___GETPASS_A = 0x761 - SYS___GETPWENT_A = 0x762 - SYS___GETPWNAM_A = 0x763 - SYS___GETPWUID_A = 0x764 - SYS_____CHECK_RESOURCE_AUTH_NP_A = 0x765 - SYS___CHECKSCHENV_A = 0x766 - SYS___CONNECTSERVER_A = 0x767 - SYS___CONNECTWORKMGR_A = 0x768 - SYS_____CONSOLE_A = 0x769 - SYS___MSGSND_A = 0x770 - SYS___MSGXRCV_A = 0x771 - SYS___NFTW_A = 0x772 - SYS_____PASSWD_A = 0x773 - SYS___PTHREAD_SECURITY_NP_A = 0x774 - SYS___QUERYMETRICS_A = 0x775 - SYS___QUERYSCHENV = 0x776 - SYS___READV_A = 0x777 - SYS_____SERVER_CLASSIFY_A = 0x778 - SYS_____SERVER_INIT_A = 0x779 - SYS___W_GETPSENT_A = 0x780 - SYS___WRITEV_A = 0x781 - SYS___W_STATFS_A = 0x782 - SYS___W_STATVFS_A = 0x783 - SYS___FPUTC_A = 0x784 - SYS___PUTCHAR_A = 0x785 - SYS___PUTS_A = 0x786 - SYS___FGETS_A = 0x787 - SYS___GETS_A = 0x788 - SYS___FPUTS_A = 0x789 - SYS___PUTC_A = 0x790 - SYS___AE_THREAD_SETMODE = 0x791 - SYS___AE_THREAD_SWAPMODE = 0x792 - SYS___GETNETBYADDR_A = 0x793 - SYS___GETNETBYNAME_A = 0x794 - SYS___GETNETENT_A = 0x795 - SYS___GETPROTOBYNAME_A = 0x796 - SYS___GETPROTOBYNUMBER_A = 0x797 - SYS___GETPROTOENT_A = 0x798 - SYS___GETSERVBYNAME_A = 0x799 - SYS_ACL_FIRST_ENTRY = 0x800 - SYS_ACL_GET_ENTRY = 0x801 - SYS_ACL_VALID = 0x802 - SYS_ACL_CREATE_ENTRY = 0x803 - SYS_ACL_DELETE_ENTRY = 0x804 - SYS_ACL_UPDATE_ENTRY = 0x805 - SYS_ACL_DELETE_FD = 0x806 - SYS_ACL_DELETE_FILE = 0x807 - SYS_ACL_GET_FD = 0x808 - SYS_ACL_GET_FILE = 0x809 - SYS___ERFL_B = 0x810 - SYS___ERFCL_B = 0x811 - SYS___LGAMMAL_B = 0x812 - SYS___SETHOOKEVENTS = 0x813 - SYS_IF_NAMETOINDEX = 0x814 - SYS_IF_INDEXTONAME = 0x815 - SYS_IF_NAMEINDEX = 0x816 - SYS_IF_FREENAMEINDEX = 0x817 - SYS_GETADDRINFO = 0x818 - SYS_GETNAMEINFO = 0x819 - SYS___DYNFREE_A = 0x820 - SYS___RES_QUERY_A = 0x821 - SYS___RES_SEARCH_A = 0x822 - SYS___RES_QUERYDOMAIN_A = 0x823 - SYS___RES_MKQUERY_A = 0x824 - SYS___RES_SEND_A = 0x825 - SYS___DN_EXPAND_A = 0x826 - SYS___DN_SKIPNAME_A = 0x827 - SYS___DN_COMP_A = 0x828 - SYS___DN_FIND_A = 0x829 - SYS___INET_NTOA_A = 0x830 - SYS___INET_NETWORK_A = 0x831 - SYS___ACCEPT_A = 0x832 - SYS___ACCEPT_AND_RECV_A = 0x833 - SYS___BIND_A = 0x834 - SYS___CONNECT_A = 0x835 - SYS___GETPEERNAME_A = 0x836 - SYS___GETSOCKNAME_A = 0x837 - SYS___RECVFROM_A = 0x838 - SYS___SENDTO_A = 0x839 - SYS___LCHATTR = 0x840 - SYS___WRITEDOWN = 0x841 - SYS_PTHREAD_MUTEX_INIT2 = 0x842 - SYS___ACOSHF_B = 0x843 - SYS___ACOSHL_B = 0x844 - SYS___ASINHF_B = 0x845 - SYS___ASINHL_B = 0x846 - SYS___ATANHF_B = 0x847 - SYS___ATANHL_B = 0x848 - SYS___CBRTF_B = 0x849 - SYS___EXP2F_B = 0x850 - SYS___EXP2L_B = 0x851 - SYS___EXPM1F_B = 0x852 - SYS___EXPM1L_B = 0x853 - SYS___FDIMF_B = 0x854 - SYS___FDIM_B = 0x855 - SYS___FDIML_B = 0x856 - SYS___HYPOTF_B = 0x857 - SYS___HYPOTL_B = 0x858 - SYS___LOG1PF_B = 0x859 - SYS___REMQUOF_B = 0x860 - SYS___REMQUO_B = 0x861 - SYS___REMQUOL_B = 0x862 - SYS___TGAMMAF_B = 0x863 - SYS___TGAMMA_B = 0x864 - SYS___TGAMMAL_B = 0x865 - SYS___TRUNCF_B = 0x866 - SYS___TRUNC_B = 0x867 - SYS___TRUNCL_B = 0x868 - SYS___LGAMMAF_B = 0x869 - SYS_ASINHF = 0x870 - SYS_ASINHL = 0x871 - SYS_ATANHF = 0x872 - SYS_ATANHL = 0x873 - SYS_CBRTF = 0x874 - SYS_CBRTL = 0x875 - SYS_COPYSIGNF = 0x876 - SYS_CPYSIGNF = 0x876 - SYS_COPYSIGNL = 0x877 - SYS_CPYSIGNL = 0x877 - SYS_COTANF = 0x878 - SYS___COTANF = 0x878 - SYS_COTAN = 0x879 - SYS___COTAN = 0x879 - SYS_FDIM = 0x881 - SYS_FDIML = 0x882 - SYS_HYPOTF = 0x883 - SYS_HYPOTL = 0x884 - SYS_LOG1PF = 0x885 - SYS_LOG1PL = 0x886 - SYS_LOG2F = 0x887 - SYS_LOG2 = 0x888 - SYS_LOG2L = 0x889 - SYS_TGAMMA = 0x890 - SYS_TGAMMAL = 0x891 - SYS_TRUNCF = 0x892 - SYS_TRUNC = 0x893 - SYS_TRUNCL = 0x894 - SYS_LGAMMAF = 0x895 - SYS_LGAMMAL = 0x896 - SYS_LROUNDF = 0x897 - SYS_LROUND = 0x898 - SYS_ERFF = 0x899 - SYS___COSHF_H = 0x900 - SYS___COSHL_H = 0x901 - SYS___COTAN_H = 0x902 - SYS___COTANF_H = 0x903 - SYS___COTANL_H = 0x904 - SYS___ERF_H = 0x905 - SYS___ERFF_H = 0x906 - SYS___ERFL_H = 0x907 - SYS___ERFC_H = 0x908 - SYS___ERFCF_H = 0x909 - SYS___FDIMF_H = 0x910 - SYS___FDIML_H = 0x911 - SYS___FMOD_H = 0x912 - SYS___FMODF_H = 0x913 - SYS___FMODL_H = 0x914 - SYS___GAMMA_H = 0x915 - SYS___HYPOT_H = 0x916 - SYS___ILOGB_H = 0x917 - SYS___LGAMMA_H = 0x918 - SYS___LGAMMAF_H = 0x919 - SYS___LOG2L_H = 0x920 - SYS___LOG1P_H = 0x921 - SYS___LOG10_H = 0x922 - SYS___LOG10F_H = 0x923 - SYS___LOG10L_H = 0x924 - SYS___LROUND_H = 0x925 - SYS___LROUNDF_H = 0x926 - SYS___NEXTAFTER_H = 0x927 - SYS___POW_H = 0x928 - SYS___POWF_H = 0x929 - SYS___SINL_H = 0x930 - SYS___SINH_H = 0x931 - SYS___SINHF_H = 0x932 - SYS___SINHL_H = 0x933 - SYS___SQRT_H = 0x934 - SYS___SQRTF_H = 0x935 - SYS___SQRTL_H = 0x936 - SYS___TAN_H = 0x937 - SYS___TANF_H = 0x938 - SYS___TANL_H = 0x939 - SYS___TRUNCF_H = 0x940 - SYS___TRUNCL_H = 0x941 - SYS___COSH_H = 0x942 - SYS___LE_DEBUG_SET_RESUME_MCH = 0x943 - SYS_VFSCANF = 0x944 - SYS_VSCANF = 0x946 - SYS_VSSCANF = 0x948 - SYS_IMAXABS = 0x950 - SYS_IMAXDIV = 0x951 - SYS_STRTOIMAX = 0x952 - SYS_STRTOUMAX = 0x953 - SYS_WCSTOIMAX = 0x954 - SYS_WCSTOUMAX = 0x955 - SYS_ATOLL = 0x956 - SYS_STRTOF = 0x957 - SYS_STRTOLD = 0x958 - SYS_WCSTOF = 0x959 - SYS_INET6_RTH_GETADDR = 0x960 - SYS_INET6_OPT_INIT = 0x961 - SYS_INET6_OPT_APPEND = 0x962 - SYS_INET6_OPT_FINISH = 0x963 - SYS_INET6_OPT_SET_VAL = 0x964 - SYS_INET6_OPT_NEXT = 0x965 - SYS_INET6_OPT_FIND = 0x966 - SYS_INET6_OPT_GET_VAL = 0x967 - SYS___POW_I = 0x987 - SYS___POW_I_B = 0x988 - SYS___POW_I_H = 0x989 - SYS___CABS_H = 0x990 - SYS_CABSF = 0x991 - SYS___CABSF_B = 0x992 - SYS___CABSF_H = 0x993 - SYS_CABSL = 0x994 - SYS___CABSL_B = 0x995 - SYS___CABSL_H = 0x996 - SYS_CACOS = 0x997 - SYS___CACOS_B = 0x998 - SYS___CACOS_H = 0x999 + SYS_LOG = 0x17 // 23 + SYS_COSH = 0x18 // 24 + SYS_TANH = 0x19 // 25 + SYS_EXP = 0x1A // 26 + SYS_MODF = 0x1B // 27 + SYS_LOG10 = 0x1C // 28 + SYS_FREXP = 0x1D // 29 + SYS_LDEXP = 0x1E // 30 + SYS_CEIL = 0x1F // 31 + SYS_POW = 0x20 // 32 + SYS_SQRT = 0x21 // 33 + SYS_FLOOR = 0x22 // 34 + SYS_J1 = 0x23 // 35 + SYS_FABS = 0x24 // 36 + SYS_FMOD = 0x25 // 37 + SYS_J0 = 0x26 // 38 + SYS_YN = 0x27 // 39 + SYS_JN = 0x28 // 40 + SYS_Y0 = 0x29 // 41 + SYS_Y1 = 0x2A // 42 + SYS_HYPOT = 0x2B // 43 + SYS_ERF = 0x2C // 44 + SYS_ERFC = 0x2D // 45 + SYS_GAMMA = 0x2E // 46 + SYS_ISALPHA = 0x30 // 48 + SYS_ISALNUM = 0x31 // 49 + SYS_ISLOWER = 0x32 // 50 + SYS_ISCNTRL = 0x33 // 51 + SYS_ISDIGIT = 0x34 // 52 + SYS_ISGRAPH = 0x35 // 53 + SYS_ISUPPER = 0x36 // 54 + SYS_ISPRINT = 0x37 // 55 + SYS_ISPUNCT = 0x38 // 56 + SYS_ISSPACE = 0x39 // 57 + SYS_SETLOCAL = 0x3A // 58 + SYS_SETLOCALE = 0x3A // 58 + SYS_ISXDIGIT = 0x3B // 59 + SYS_TOLOWER = 0x3C // 60 + SYS_TOUPPER = 0x3D // 61 + SYS_ASIN = 0x3E // 62 + SYS_SIN = 0x3F // 63 + SYS_COS = 0x40 // 64 + SYS_TAN = 0x41 // 65 + SYS_SINH = 0x42 // 66 + SYS_ACOS = 0x43 // 67 + SYS_ATAN = 0x44 // 68 + SYS_ATAN2 = 0x45 // 69 + SYS_FTELL = 0x46 // 70 + SYS_FGETPOS = 0x47 // 71 + SYS_FSEEK = 0x48 // 72 + SYS_FSETPOS = 0x49 // 73 + SYS_FERROR = 0x4A // 74 + SYS_REWIND = 0x4B // 75 + SYS_CLEARERR = 0x4C // 76 + SYS_FEOF = 0x4D // 77 + SYS_ATOL = 0x4E // 78 + SYS_PERROR = 0x4F // 79 + SYS_ATOF = 0x50 // 80 + SYS_ATOI = 0x51 // 81 + SYS_RAND = 0x52 // 82 + SYS_STRTOD = 0x53 // 83 + SYS_STRTOL = 0x54 // 84 + SYS_STRTOUL = 0x55 // 85 + SYS_MALLOC = 0x56 // 86 + SYS_SRAND = 0x57 // 87 + SYS_CALLOC = 0x58 // 88 + SYS_FREE = 0x59 // 89 + SYS_EXIT = 0x5A // 90 + SYS_REALLOC = 0x5B // 91 + SYS_ABORT = 0x5C // 92 + SYS___ABORT = 0x5C // 92 + SYS_ATEXIT = 0x5D // 93 + SYS_RAISE = 0x5E // 94 + SYS_SETJMP = 0x5F // 95 + SYS_LONGJMP = 0x60 // 96 + SYS_SIGNAL = 0x61 // 97 + SYS_TMPNAM = 0x62 // 98 + SYS_REMOVE = 0x63 // 99 + SYS_RENAME = 0x64 // 100 + SYS_TMPFILE = 0x65 // 101 + SYS_FREOPEN = 0x66 // 102 + SYS_FCLOSE = 0x67 // 103 + SYS_FFLUSH = 0x68 // 104 + SYS_FOPEN = 0x69 // 105 + SYS_FSCANF = 0x6A // 106 + SYS_SETBUF = 0x6B // 107 + SYS_SETVBUF = 0x6C // 108 + SYS_FPRINTF = 0x6D // 109 + SYS_SSCANF = 0x6E // 110 + SYS_PRINTF = 0x6F // 111 + SYS_SCANF = 0x70 // 112 + SYS_SPRINTF = 0x71 // 113 + SYS_FGETC = 0x72 // 114 + SYS_VFPRINTF = 0x73 // 115 + SYS_VPRINTF = 0x74 // 116 + SYS_VSPRINTF = 0x75 // 117 + SYS_GETC = 0x76 // 118 + SYS_FGETS = 0x77 // 119 + SYS_FPUTC = 0x78 // 120 + SYS_FPUTS = 0x79 // 121 + SYS_PUTCHAR = 0x7A // 122 + SYS_GETCHAR = 0x7B // 123 + SYS_GETS = 0x7C // 124 + SYS_PUTC = 0x7D // 125 + SYS_FWRITE = 0x7E // 126 + SYS_PUTS = 0x7F // 127 + SYS_UNGETC = 0x80 // 128 + SYS_FREAD = 0x81 // 129 + SYS_WCSTOMBS = 0x82 // 130 + SYS_MBTOWC = 0x83 // 131 + SYS_WCTOMB = 0x84 // 132 + SYS_MBSTOWCS = 0x85 // 133 + SYS_WCSCPY = 0x86 // 134 + SYS_WCSCAT = 0x87 // 135 + SYS_WCSCHR = 0x88 // 136 + SYS_WCSCMP = 0x89 // 137 + SYS_WCSNCMP = 0x8A // 138 + SYS_WCSCSPN = 0x8B // 139 + SYS_WCSLEN = 0x8C // 140 + SYS_WCSNCAT = 0x8D // 141 + SYS_WCSSPN = 0x8E // 142 + SYS_WCSNCPY = 0x8F // 143 + SYS_ABS = 0x90 // 144 + SYS_DIV = 0x91 // 145 + SYS_LABS = 0x92 // 146 + SYS_STRNCPY = 0x93 // 147 + SYS_MEMCPY = 0x94 // 148 + SYS_MEMMOVE = 0x95 // 149 + SYS_STRCPY = 0x96 // 150 + SYS_STRCMP = 0x97 // 151 + SYS_STRCAT = 0x98 // 152 + SYS_STRNCAT = 0x99 // 153 + SYS_MEMCMP = 0x9A // 154 + SYS_MEMCHR = 0x9B // 155 + SYS_STRCOLL = 0x9C // 156 + SYS_STRNCMP = 0x9D // 157 + SYS_STRXFRM = 0x9E // 158 + SYS_STRRCHR = 0x9F // 159 + SYS_STRCHR = 0xA0 // 160 + SYS_STRCSPN = 0xA1 // 161 + SYS_STRPBRK = 0xA2 // 162 + SYS_MEMSET = 0xA3 // 163 + SYS_STRSPN = 0xA4 // 164 + SYS_STRSTR = 0xA5 // 165 + SYS_STRTOK = 0xA6 // 166 + SYS_DIFFTIME = 0xA7 // 167 + SYS_STRERROR = 0xA8 // 168 + SYS_STRLEN = 0xA9 // 169 + SYS_CLOCK = 0xAA // 170 + SYS_CTIME = 0xAB // 171 + SYS_MKTIME = 0xAC // 172 + SYS_TIME = 0xAD // 173 + SYS_ASCTIME = 0xAE // 174 + SYS_MBLEN = 0xAF // 175 + SYS_GMTIME = 0xB0 // 176 + SYS_LOCALTIM = 0xB1 // 177 + SYS_LOCALTIME = 0xB1 // 177 + SYS_STRFTIME = 0xB2 // 178 + SYS___GETCB = 0xB4 // 180 + SYS_FUPDATE = 0xB5 // 181 + SYS___FUPDT = 0xB5 // 181 + SYS_CLRMEMF = 0xBD // 189 + SYS___CLRMF = 0xBD // 189 + SYS_FETCHEP = 0xBF // 191 + SYS___FTCHEP = 0xBF // 191 + SYS_FLDATA = 0xC1 // 193 + SYS___FLDATA = 0xC1 // 193 + SYS_DYNFREE = 0xC2 // 194 + SYS___DYNFRE = 0xC2 // 194 + SYS_DYNALLOC = 0xC3 // 195 + SYS___DYNALL = 0xC3 // 195 + SYS___CDUMP = 0xC4 // 196 + SYS_CSNAP = 0xC5 // 197 + SYS___CSNAP = 0xC5 // 197 + SYS_CTRACE = 0xC6 // 198 + SYS___CTRACE = 0xC6 // 198 + SYS___CTEST = 0xC7 // 199 + SYS_SETENV = 0xC8 // 200 + SYS___SETENV = 0xC8 // 200 + SYS_CLEARENV = 0xC9 // 201 + SYS___CLRENV = 0xC9 // 201 + SYS___REGCOMP_STD = 0xEA // 234 + SYS_NL_LANGINFO = 0xFC // 252 + SYS_GETSYNTX = 0xFD // 253 + SYS_ISBLANK = 0xFE // 254 + SYS___ISBLNK = 0xFE // 254 + SYS_ISWALNUM = 0xFF // 255 + SYS_ISWALPHA = 0x100 // 256 + SYS_ISWBLANK = 0x101 // 257 + SYS___ISWBLK = 0x101 // 257 + SYS_ISWCNTRL = 0x102 // 258 + SYS_ISWDIGIT = 0x103 // 259 + SYS_ISWGRAPH = 0x104 // 260 + SYS_ISWLOWER = 0x105 // 261 + SYS_ISWPRINT = 0x106 // 262 + SYS_ISWPUNCT = 0x107 // 263 + SYS_ISWSPACE = 0x108 // 264 + SYS_ISWUPPER = 0x109 // 265 + SYS_ISWXDIGI = 0x10A // 266 + SYS_ISWXDIGIT = 0x10A // 266 + SYS_WCTYPE = 0x10B // 267 + SYS_ISWCTYPE = 0x10C // 268 + SYS_TOWLOWER = 0x10D // 269 + SYS_TOWUPPER = 0x10E // 270 + SYS_MBSINIT = 0x10F // 271 + SYS_WCTOB = 0x110 // 272 + SYS_MBRLEN = 0x111 // 273 + SYS_MBRTOWC = 0x112 // 274 + SYS_MBSRTOWC = 0x113 // 275 + SYS_MBSRTOWCS = 0x113 // 275 + SYS_WCRTOMB = 0x114 // 276 + SYS_WCSRTOMB = 0x115 // 277 + SYS_WCSRTOMBS = 0x115 // 277 + SYS___CSID = 0x116 // 278 + SYS___WCSID = 0x117 // 279 + SYS_STRPTIME = 0x118 // 280 + SYS___STRPTM = 0x118 // 280 + SYS_STRFMON = 0x119 // 281 + SYS___RPMTCH = 0x11A // 282 + SYS_WCSSTR = 0x11B // 283 + SYS_WCSTOK = 0x12C // 300 + SYS_WCSTOL = 0x12D // 301 + SYS_WCSTOD = 0x12E // 302 + SYS_WCSTOUL = 0x12F // 303 + SYS_WCSCOLL = 0x130 // 304 + SYS_WCSXFRM = 0x131 // 305 + SYS_WCSWIDTH = 0x132 // 306 + SYS_WCWIDTH = 0x133 // 307 + SYS_WCSFTIME = 0x134 // 308 + SYS_SWPRINTF = 0x135 // 309 + SYS_VSWPRINT = 0x136 // 310 + SYS_VSWPRINTF = 0x136 // 310 + SYS_SWSCANF = 0x137 // 311 + SYS_REGCOMP = 0x138 // 312 + SYS_REGEXEC = 0x139 // 313 + SYS_REGFREE = 0x13A // 314 + SYS_REGERROR = 0x13B // 315 + SYS_FGETWC = 0x13C // 316 + SYS_FGETWS = 0x13D // 317 + SYS_FPUTWC = 0x13E // 318 + SYS_FPUTWS = 0x13F // 319 + SYS_GETWC = 0x140 // 320 + SYS_GETWCHAR = 0x141 // 321 + SYS_PUTWC = 0x142 // 322 + SYS_PUTWCHAR = 0x143 // 323 + SYS_UNGETWC = 0x144 // 324 + SYS_ICONV_OPEN = 0x145 // 325 + SYS_ICONV = 0x146 // 326 + SYS_ICONV_CLOSE = 0x147 // 327 + SYS_ISMCCOLLEL = 0x14C // 332 + SYS_STRTOCOLL = 0x14D // 333 + SYS_COLLTOSTR = 0x14E // 334 + SYS_COLLEQUIV = 0x14F // 335 + SYS_COLLRANGE = 0x150 // 336 + SYS_CCLASS = 0x151 // 337 + SYS_COLLORDER = 0x152 // 338 + SYS___DEMANGLE = 0x154 // 340 + SYS_FDOPEN = 0x155 // 341 + SYS___ERRNO = 0x156 // 342 + SYS___ERRNO2 = 0x157 // 343 + SYS___TERROR = 0x158 // 344 + SYS_MAXCOLL = 0x169 // 361 + SYS_GETMCCOLL = 0x16A // 362 + SYS_GETWMCCOLL = 0x16B // 363 + SYS___ERR2AD = 0x16C // 364 + SYS_DLLQUERYFN = 0x16D // 365 + SYS_DLLQUERYVAR = 0x16E // 366 + SYS_DLLFREE = 0x16F // 367 + SYS_DLLLOAD = 0x170 // 368 + SYS__EXIT = 0x174 // 372 + SYS_ACCESS = 0x175 // 373 + SYS_ALARM = 0x176 // 374 + SYS_CFGETISPEED = 0x177 // 375 + SYS_CFGETOSPEED = 0x178 // 376 + SYS_CFSETISPEED = 0x179 // 377 + SYS_CFSETOSPEED = 0x17A // 378 + SYS_CHDIR = 0x17B // 379 + SYS_CHMOD = 0x17C // 380 + SYS_CHOWN = 0x17D // 381 + SYS_CLOSE = 0x17E // 382 + SYS_CLOSEDIR = 0x17F // 383 + SYS_CREAT = 0x180 // 384 + SYS_CTERMID = 0x181 // 385 + SYS_DUP = 0x182 // 386 + SYS_DUP2 = 0x183 // 387 + SYS_EXECL = 0x184 // 388 + SYS_EXECLE = 0x185 // 389 + SYS_EXECLP = 0x186 // 390 + SYS_EXECV = 0x187 // 391 + SYS_EXECVE = 0x188 // 392 + SYS_EXECVP = 0x189 // 393 + SYS_FCHMOD = 0x18A // 394 + SYS_FCHOWN = 0x18B // 395 + SYS_FCNTL = 0x18C // 396 + SYS_FILENO = 0x18D // 397 + SYS_FORK = 0x18E // 398 + SYS_FPATHCONF = 0x18F // 399 + SYS_FSTAT = 0x190 // 400 + SYS_FSYNC = 0x191 // 401 + SYS_FTRUNCATE = 0x192 // 402 + SYS_GETCWD = 0x193 // 403 + SYS_GETEGID = 0x194 // 404 + SYS_GETEUID = 0x195 // 405 + SYS_GETGID = 0x196 // 406 + SYS_GETGRGID = 0x197 // 407 + SYS_GETGRNAM = 0x198 // 408 + SYS_GETGROUPS = 0x199 // 409 + SYS_GETLOGIN = 0x19A // 410 + SYS_W_GETMNTENT = 0x19B // 411 + SYS_GETPGRP = 0x19C // 412 + SYS_GETPID = 0x19D // 413 + SYS_GETPPID = 0x19E // 414 + SYS_GETPWNAM = 0x19F // 415 + SYS_GETPWUID = 0x1A0 // 416 + SYS_GETUID = 0x1A1 // 417 + SYS_W_IOCTL = 0x1A2 // 418 + SYS_ISATTY = 0x1A3 // 419 + SYS_KILL = 0x1A4 // 420 + SYS_LINK = 0x1A5 // 421 + SYS_LSEEK = 0x1A6 // 422 + SYS_LSTAT = 0x1A7 // 423 + SYS_MKDIR = 0x1A8 // 424 + SYS_MKFIFO = 0x1A9 // 425 + SYS_MKNOD = 0x1AA // 426 + SYS_MOUNT = 0x1AB // 427 + SYS_OPEN = 0x1AC // 428 + SYS_OPENDIR = 0x1AD // 429 + SYS_PATHCONF = 0x1AE // 430 + SYS_PAUSE = 0x1AF // 431 + SYS_PIPE = 0x1B0 // 432 + SYS_W_GETPSENT = 0x1B1 // 433 + SYS_READ = 0x1B2 // 434 + SYS_READDIR = 0x1B3 // 435 + SYS_READLINK = 0x1B4 // 436 + SYS_REWINDDIR = 0x1B5 // 437 + SYS_RMDIR = 0x1B6 // 438 + SYS_SETEGID = 0x1B7 // 439 + SYS_SETEUID = 0x1B8 // 440 + SYS_SETGID = 0x1B9 // 441 + SYS_SETPGID = 0x1BA // 442 + SYS_SETSID = 0x1BB // 443 + SYS_SETUID = 0x1BC // 444 + SYS_SIGACTION = 0x1BD // 445 + SYS_SIGADDSET = 0x1BE // 446 + SYS_SIGDELSET = 0x1BF // 447 + SYS_SIGEMPTYSET = 0x1C0 // 448 + SYS_SIGFILLSET = 0x1C1 // 449 + SYS_SIGISMEMBER = 0x1C2 // 450 + SYS_SIGLONGJMP = 0x1C3 // 451 + SYS_SIGPENDING = 0x1C4 // 452 + SYS_SIGPROCMASK = 0x1C5 // 453 + SYS_SIGSETJMP = 0x1C6 // 454 + SYS_SIGSUSPEND = 0x1C7 // 455 + SYS_SLEEP = 0x1C8 // 456 + SYS_STAT = 0x1C9 // 457 + SYS_W_STATFS = 0x1CA // 458 + SYS_SYMLINK = 0x1CB // 459 + SYS_SYSCONF = 0x1CC // 460 + SYS_TCDRAIN = 0x1CD // 461 + SYS_TCFLOW = 0x1CE // 462 + SYS_TCFLUSH = 0x1CF // 463 + SYS_TCGETATTR = 0x1D0 // 464 + SYS_TCGETPGRP = 0x1D1 // 465 + SYS_TCSENDBREAK = 0x1D2 // 466 + SYS_TCSETATTR = 0x1D3 // 467 + SYS_TCSETPGRP = 0x1D4 // 468 + SYS_TIMES = 0x1D5 // 469 + SYS_TTYNAME = 0x1D6 // 470 + SYS_TZSET = 0x1D7 // 471 + SYS_UMASK = 0x1D8 // 472 + SYS_UMOUNT = 0x1D9 // 473 + SYS_UNAME = 0x1DA // 474 + SYS_UNLINK = 0x1DB // 475 + SYS_UTIME = 0x1DC // 476 + SYS_WAIT = 0x1DD // 477 + SYS_WAITPID = 0x1DE // 478 + SYS_WRITE = 0x1DF // 479 + SYS_CHAUDIT = 0x1E0 // 480 + SYS_FCHAUDIT = 0x1E1 // 481 + SYS_GETGROUPSBYNAME = 0x1E2 // 482 + SYS_SIGWAIT = 0x1E3 // 483 + SYS_PTHREAD_EXIT = 0x1E4 // 484 + SYS_PTHREAD_KILL = 0x1E5 // 485 + SYS_PTHREAD_ATTR_INIT = 0x1E6 // 486 + SYS_PTHREAD_ATTR_DESTROY = 0x1E7 // 487 + SYS_PTHREAD_ATTR_SETSTACKSIZE = 0x1E8 // 488 + SYS_PTHREAD_ATTR_GETSTACKSIZE = 0x1E9 // 489 + SYS_PTHREAD_ATTR_SETDETACHSTATE = 0x1EA // 490 + SYS_PTHREAD_ATTR_GETDETACHSTATE = 0x1EB // 491 + SYS_PTHREAD_ATTR_SETWEIGHT_NP = 0x1EC // 492 + SYS_PTHREAD_ATTR_GETWEIGHT_NP = 0x1ED // 493 + SYS_PTHREAD_CANCEL = 0x1EE // 494 + SYS_PTHREAD_CLEANUP_PUSH = 0x1EF // 495 + SYS_PTHREAD_CLEANUP_POP = 0x1F0 // 496 + SYS_PTHREAD_CONDATTR_INIT = 0x1F1 // 497 + SYS_PTHREAD_CONDATTR_DESTROY = 0x1F2 // 498 + SYS_PTHREAD_COND_INIT = 0x1F3 // 499 + SYS_PTHREAD_COND_DESTROY = 0x1F4 // 500 + SYS_PTHREAD_COND_SIGNAL = 0x1F5 // 501 + SYS_PTHREAD_COND_BROADCAST = 0x1F6 // 502 + SYS_PTHREAD_COND_WAIT = 0x1F7 // 503 + SYS_PTHREAD_COND_TIMEDWAIT = 0x1F8 // 504 + SYS_PTHREAD_CREATE = 0x1F9 // 505 + SYS_PTHREAD_DETACH = 0x1FA // 506 + SYS_PTHREAD_EQUAL = 0x1FB // 507 + SYS_PTHREAD_GETSPECIFIC = 0x1FC // 508 + SYS_PTHREAD_JOIN = 0x1FD // 509 + SYS_PTHREAD_KEY_CREATE = 0x1FE // 510 + SYS_PTHREAD_MUTEXATTR_INIT = 0x1FF // 511 + SYS_PTHREAD_MUTEXATTR_DESTROY = 0x200 // 512 + SYS_PTHREAD_MUTEXATTR_SETKIND_NP = 0x201 // 513 + SYS_PTHREAD_MUTEXATTR_GETKIND_NP = 0x202 // 514 + SYS_PTHREAD_MUTEX_INIT = 0x203 // 515 + SYS_PTHREAD_MUTEX_DESTROY = 0x204 // 516 + SYS_PTHREAD_MUTEX_LOCK = 0x205 // 517 + SYS_PTHREAD_MUTEX_TRYLOCK = 0x206 // 518 + SYS_PTHREAD_MUTEX_UNLOCK = 0x207 // 519 + SYS_PTHREAD_ONCE = 0x209 // 521 + SYS_PTHREAD_SELF = 0x20A // 522 + SYS_PTHREAD_SETINTR = 0x20B // 523 + SYS_PTHREAD_SETINTRTYPE = 0x20C // 524 + SYS_PTHREAD_SETSPECIFIC = 0x20D // 525 + SYS_PTHREAD_TESTINTR = 0x20E // 526 + SYS_PTHREAD_YIELD = 0x20F // 527 + SYS_TW_OPEN = 0x210 // 528 + SYS_TW_FCNTL = 0x211 // 529 + SYS_PTHREAD_JOIN_D4_NP = 0x212 // 530 + SYS_PTHREAD_CONDATTR_SETKIND_NP = 0x213 // 531 + SYS_PTHREAD_CONDATTR_GETKIND_NP = 0x214 // 532 + SYS_EXTLINK_NP = 0x215 // 533 + SYS___PASSWD = 0x216 // 534 + SYS_SETGROUPS = 0x217 // 535 + SYS_INITGROUPS = 0x218 // 536 + SYS_WCSPBRK = 0x23F // 575 + SYS_WCSRCHR = 0x240 // 576 + SYS_SVC99 = 0x241 // 577 + SYS___SVC99 = 0x241 // 577 + SYS_WCSWCS = 0x242 // 578 + SYS_LOCALECO = 0x243 // 579 + SYS_LOCALECONV = 0x243 // 579 + SYS___LIBREL = 0x244 // 580 + SYS_RELEASE = 0x245 // 581 + SYS___RLSE = 0x245 // 581 + SYS_FLOCATE = 0x246 // 582 + SYS___FLOCT = 0x246 // 582 + SYS_FDELREC = 0x247 // 583 + SYS___FDLREC = 0x247 // 583 + SYS_FETCH = 0x248 // 584 + SYS___FETCH = 0x248 // 584 + SYS_QSORT = 0x249 // 585 + SYS_GETENV = 0x24A // 586 + SYS_SYSTEM = 0x24B // 587 + SYS_BSEARCH = 0x24C // 588 + SYS_LDIV = 0x24D // 589 + SYS___THROW = 0x25E // 606 + SYS___RETHROW = 0x25F // 607 + SYS___CLEANUPCATCH = 0x260 // 608 + SYS___CATCHMATCH = 0x261 // 609 + SYS___CLEAN2UPCATCH = 0x262 // 610 + SYS_PUTENV = 0x26A // 618 + SYS___GETENV = 0x26F // 623 + SYS_GETPRIORITY = 0x270 // 624 + SYS_NICE = 0x271 // 625 + SYS_SETPRIORITY = 0x272 // 626 + SYS_GETITIMER = 0x273 // 627 + SYS_SETITIMER = 0x274 // 628 + SYS_MSGCTL = 0x275 // 629 + SYS_MSGGET = 0x276 // 630 + SYS_MSGRCV = 0x277 // 631 + SYS_MSGSND = 0x278 // 632 + SYS_MSGXRCV = 0x279 // 633 + SYS___MSGXR = 0x279 // 633 + SYS_SEMCTL = 0x27A // 634 + SYS_SEMGET = 0x27B // 635 + SYS_SEMOP = 0x27C // 636 + SYS_SHMAT = 0x27D // 637 + SYS_SHMCTL = 0x27E // 638 + SYS_SHMDT = 0x27F // 639 + SYS_SHMGET = 0x280 // 640 + SYS___GETIPC = 0x281 // 641 + SYS_SETGRENT = 0x282 // 642 + SYS_GETGRENT = 0x283 // 643 + SYS_ENDGRENT = 0x284 // 644 + SYS_SETPWENT = 0x285 // 645 + SYS_GETPWENT = 0x286 // 646 + SYS_ENDPWENT = 0x287 // 647 + SYS_BSD_SIGNAL = 0x288 // 648 + SYS_KILLPG = 0x289 // 649 + SYS_SIGALTSTACK = 0x28A // 650 + SYS_SIGHOLD = 0x28B // 651 + SYS_SIGIGNORE = 0x28C // 652 + SYS_SIGINTERRUPT = 0x28D // 653 + SYS_SIGPAUSE = 0x28E // 654 + SYS_SIGRELSE = 0x28F // 655 + SYS_SIGSET = 0x290 // 656 + SYS_SIGSTACK = 0x291 // 657 + SYS_GETRLIMIT = 0x292 // 658 + SYS_SETRLIMIT = 0x293 // 659 + SYS_GETRUSAGE = 0x294 // 660 + SYS_MMAP = 0x295 // 661 + SYS_MPROTECT = 0x296 // 662 + SYS_MSYNC = 0x297 // 663 + SYS_MUNMAP = 0x298 // 664 + SYS_CONFSTR = 0x299 // 665 + SYS_GETOPT = 0x29A // 666 + SYS_LCHOWN = 0x29B // 667 + SYS_TRUNCATE = 0x29C // 668 + SYS_GETSUBOPT = 0x29D // 669 + SYS_SETPGRP = 0x29E // 670 + SYS___GDERR = 0x29F // 671 + SYS___TZONE = 0x2A0 // 672 + SYS___DLGHT = 0x2A1 // 673 + SYS___OPARGF = 0x2A2 // 674 + SYS___OPOPTF = 0x2A3 // 675 + SYS___OPINDF = 0x2A4 // 676 + SYS___OPERRF = 0x2A5 // 677 + SYS_GETDATE = 0x2A6 // 678 + SYS_WAIT3 = 0x2A7 // 679 + SYS_WAITID = 0x2A8 // 680 + SYS___CATTRM = 0x2A9 // 681 + SYS___GDTRM = 0x2AA // 682 + SYS___RNDTRM = 0x2AB // 683 + SYS_CRYPT = 0x2AC // 684 + SYS_ENCRYPT = 0x2AD // 685 + SYS_SETKEY = 0x2AE // 686 + SYS___CNVBLK = 0x2AF // 687 + SYS___CRYTRM = 0x2B0 // 688 + SYS___ECRTRM = 0x2B1 // 689 + SYS_DRAND48 = 0x2B2 // 690 + SYS_ERAND48 = 0x2B3 // 691 + SYS_FSTATVFS = 0x2B4 // 692 + SYS_STATVFS = 0x2B5 // 693 + SYS_CATCLOSE = 0x2B6 // 694 + SYS_CATGETS = 0x2B7 // 695 + SYS_CATOPEN = 0x2B8 // 696 + SYS_BCMP = 0x2B9 // 697 + SYS_BCOPY = 0x2BA // 698 + SYS_BZERO = 0x2BB // 699 + SYS_FFS = 0x2BC // 700 + SYS_INDEX = 0x2BD // 701 + SYS_RINDEX = 0x2BE // 702 + SYS_STRCASECMP = 0x2BF // 703 + SYS_STRDUP = 0x2C0 // 704 + SYS_STRNCASECMP = 0x2C1 // 705 + SYS_INITSTATE = 0x2C2 // 706 + SYS_SETSTATE = 0x2C3 // 707 + SYS_RANDOM = 0x2C4 // 708 + SYS_SRANDOM = 0x2C5 // 709 + SYS_HCREATE = 0x2C6 // 710 + SYS_HDESTROY = 0x2C7 // 711 + SYS_HSEARCH = 0x2C8 // 712 + SYS_LFIND = 0x2C9 // 713 + SYS_LSEARCH = 0x2CA // 714 + SYS_TDELETE = 0x2CB // 715 + SYS_TFIND = 0x2CC // 716 + SYS_TSEARCH = 0x2CD // 717 + SYS_TWALK = 0x2CE // 718 + SYS_INSQUE = 0x2CF // 719 + SYS_REMQUE = 0x2D0 // 720 + SYS_POPEN = 0x2D1 // 721 + SYS_PCLOSE = 0x2D2 // 722 + SYS_SWAB = 0x2D3 // 723 + SYS_MEMCCPY = 0x2D4 // 724 + SYS_GETPAGESIZE = 0x2D8 // 728 + SYS_FCHDIR = 0x2D9 // 729 + SYS___OCLCK = 0x2DA // 730 + SYS___ATOE = 0x2DB // 731 + SYS___ATOE_L = 0x2DC // 732 + SYS___ETOA = 0x2DD // 733 + SYS___ETOA_L = 0x2DE // 734 + SYS_SETUTXENT = 0x2DF // 735 + SYS_GETUTXENT = 0x2E0 // 736 + SYS_ENDUTXENT = 0x2E1 // 737 + SYS_GETUTXID = 0x2E2 // 738 + SYS_GETUTXLINE = 0x2E3 // 739 + SYS_PUTUTXLINE = 0x2E4 // 740 + SYS_FMTMSG = 0x2E5 // 741 + SYS_JRAND48 = 0x2E6 // 742 + SYS_LRAND48 = 0x2E7 // 743 + SYS_MRAND48 = 0x2E8 // 744 + SYS_NRAND48 = 0x2E9 // 745 + SYS_LCONG48 = 0x2EA // 746 + SYS_SRAND48 = 0x2EB // 747 + SYS_SEED48 = 0x2EC // 748 + SYS_ISASCII = 0x2ED // 749 + SYS_TOASCII = 0x2EE // 750 + SYS_A64L = 0x2EF // 751 + SYS_L64A = 0x2F0 // 752 + SYS_UALARM = 0x2F1 // 753 + SYS_USLEEP = 0x2F2 // 754 + SYS___UTXTRM = 0x2F3 // 755 + SYS___SRCTRM = 0x2F4 // 756 + SYS_FTIME = 0x2F5 // 757 + SYS_GETTIMEOFDAY = 0x2F6 // 758 + SYS_DBM_CLEARERR = 0x2F7 // 759 + SYS_DBM_CLOSE = 0x2F8 // 760 + SYS_DBM_DELETE = 0x2F9 // 761 + SYS_DBM_ERROR = 0x2FA // 762 + SYS_DBM_FETCH = 0x2FB // 763 + SYS_DBM_FIRSTKEY = 0x2FC // 764 + SYS_DBM_NEXTKEY = 0x2FD // 765 + SYS_DBM_OPEN = 0x2FE // 766 + SYS_DBM_STORE = 0x2FF // 767 + SYS___NDMTRM = 0x300 // 768 + SYS_FTOK = 0x301 // 769 + SYS_BASENAME = 0x302 // 770 + SYS_DIRNAME = 0x303 // 771 + SYS_GETDTABLESIZE = 0x304 // 772 + SYS_MKSTEMP = 0x305 // 773 + SYS_MKTEMP = 0x306 // 774 + SYS_NFTW = 0x307 // 775 + SYS_GETWD = 0x308 // 776 + SYS_LOCKF = 0x309 // 777 + SYS__LONGJMP = 0x30D // 781 + SYS__SETJMP = 0x30E // 782 + SYS_VFORK = 0x30F // 783 + SYS_WORDEXP = 0x310 // 784 + SYS_WORDFREE = 0x311 // 785 + SYS_GETPGID = 0x312 // 786 + SYS_GETSID = 0x313 // 787 + SYS___UTMPXNAME = 0x314 // 788 + SYS_CUSERID = 0x315 // 789 + SYS_GETPASS = 0x316 // 790 + SYS_FNMATCH = 0x317 // 791 + SYS_FTW = 0x318 // 792 + SYS_GETW = 0x319 // 793 + SYS_GLOB = 0x31A // 794 + SYS_GLOBFREE = 0x31B // 795 + SYS_PUTW = 0x31C // 796 + SYS_SEEKDIR = 0x31D // 797 + SYS_TELLDIR = 0x31E // 798 + SYS_TEMPNAM = 0x31F // 799 + SYS_ACOSH = 0x320 // 800 + SYS_ASINH = 0x321 // 801 + SYS_ATANH = 0x322 // 802 + SYS_CBRT = 0x323 // 803 + SYS_EXPM1 = 0x324 // 804 + SYS_ILOGB = 0x325 // 805 + SYS_LOGB = 0x326 // 806 + SYS_LOG1P = 0x327 // 807 + SYS_NEXTAFTER = 0x328 // 808 + SYS_RINT = 0x329 // 809 + SYS_REMAINDER = 0x32A // 810 + SYS_SCALB = 0x32B // 811 + SYS_LGAMMA = 0x32C // 812 + SYS_TTYSLOT = 0x32D // 813 + SYS_GETTIMEOFDAY_R = 0x32E // 814 + SYS_SYNC = 0x32F // 815 + SYS_SPAWN = 0x330 // 816 + SYS_SPAWNP = 0x331 // 817 + SYS_GETLOGIN_UU = 0x332 // 818 + SYS_ECVT = 0x333 // 819 + SYS_FCVT = 0x334 // 820 + SYS_GCVT = 0x335 // 821 + SYS_ACCEPT = 0x336 // 822 + SYS_BIND = 0x337 // 823 + SYS_CONNECT = 0x338 // 824 + SYS_ENDHOSTENT = 0x339 // 825 + SYS_ENDPROTOENT = 0x33A // 826 + SYS_ENDSERVENT = 0x33B // 827 + SYS_GETHOSTBYADDR_R = 0x33C // 828 + SYS_GETHOSTBYADDR = 0x33D // 829 + SYS_GETHOSTBYNAME_R = 0x33E // 830 + SYS_GETHOSTBYNAME = 0x33F // 831 + SYS_GETHOSTENT = 0x340 // 832 + SYS_GETHOSTID = 0x341 // 833 + SYS_GETHOSTNAME = 0x342 // 834 + SYS_GETNETBYADDR = 0x343 // 835 + SYS_GETNETBYNAME = 0x344 // 836 + SYS_GETNETENT = 0x345 // 837 + SYS_GETPEERNAME = 0x346 // 838 + SYS_GETPROTOBYNAME = 0x347 // 839 + SYS_GETPROTOBYNUMBER = 0x348 // 840 + SYS_GETPROTOENT = 0x349 // 841 + SYS_GETSERVBYNAME = 0x34A // 842 + SYS_GETSERVBYPORT = 0x34B // 843 + SYS_GETSERVENT = 0x34C // 844 + SYS_GETSOCKNAME = 0x34D // 845 + SYS_GETSOCKOPT = 0x34E // 846 + SYS_INET_ADDR = 0x34F // 847 + SYS_INET_LNAOF = 0x350 // 848 + SYS_INET_MAKEADDR = 0x351 // 849 + SYS_INET_NETOF = 0x352 // 850 + SYS_INET_NETWORK = 0x353 // 851 + SYS_INET_NTOA = 0x354 // 852 + SYS_IOCTL = 0x355 // 853 + SYS_LISTEN = 0x356 // 854 + SYS_READV = 0x357 // 855 + SYS_RECV = 0x358 // 856 + SYS_RECVFROM = 0x359 // 857 + SYS_SELECT = 0x35B // 859 + SYS_SELECTEX = 0x35C // 860 + SYS_SEND = 0x35D // 861 + SYS_SENDTO = 0x35F // 863 + SYS_SETHOSTENT = 0x360 // 864 + SYS_SETNETENT = 0x361 // 865 + SYS_SETPEER = 0x362 // 866 + SYS_SETPROTOENT = 0x363 // 867 + SYS_SETSERVENT = 0x364 // 868 + SYS_SETSOCKOPT = 0x365 // 869 + SYS_SHUTDOWN = 0x366 // 870 + SYS_SOCKET = 0x367 // 871 + SYS_SOCKETPAIR = 0x368 // 872 + SYS_WRITEV = 0x369 // 873 + SYS_CHROOT = 0x36A // 874 + SYS_W_STATVFS = 0x36B // 875 + SYS_ULIMIT = 0x36C // 876 + SYS_ISNAN = 0x36D // 877 + SYS_UTIMES = 0x36E // 878 + SYS___H_ERRNO = 0x36F // 879 + SYS_ENDNETENT = 0x370 // 880 + SYS_CLOSELOG = 0x371 // 881 + SYS_OPENLOG = 0x372 // 882 + SYS_SETLOGMASK = 0x373 // 883 + SYS_SYSLOG = 0x374 // 884 + SYS_PTSNAME = 0x375 // 885 + SYS_SETREUID = 0x376 // 886 + SYS_SETREGID = 0x377 // 887 + SYS_REALPATH = 0x378 // 888 + SYS___SIGNGAM = 0x379 // 889 + SYS_GRANTPT = 0x37A // 890 + SYS_UNLOCKPT = 0x37B // 891 + SYS_TCGETSID = 0x37C // 892 + SYS___TCGETCP = 0x37D // 893 + SYS___TCSETCP = 0x37E // 894 + SYS___TCSETTABLES = 0x37F // 895 + SYS_POLL = 0x380 // 896 + SYS_REXEC = 0x381 // 897 + SYS___ISASCII2 = 0x382 // 898 + SYS___TOASCII2 = 0x383 // 899 + SYS_CHPRIORITY = 0x384 // 900 + SYS_PTHREAD_ATTR_SETSYNCTYPE_NP = 0x385 // 901 + SYS_PTHREAD_ATTR_GETSYNCTYPE_NP = 0x386 // 902 + SYS_PTHREAD_SET_LIMIT_NP = 0x387 // 903 + SYS___STNETENT = 0x388 // 904 + SYS___STPROTOENT = 0x389 // 905 + SYS___STSERVENT = 0x38A // 906 + SYS___STHOSTENT = 0x38B // 907 + SYS_NLIST = 0x38C // 908 + SYS___IPDBCS = 0x38D // 909 + SYS___IPDSPX = 0x38E // 910 + SYS___IPMSGC = 0x38F // 911 + SYS___SELECT1 = 0x390 // 912 + SYS_PTHREAD_SECURITY_NP = 0x391 // 913 + SYS___CHECK_RESOURCE_AUTH_NP = 0x392 // 914 + SYS___CONVERT_ID_NP = 0x393 // 915 + SYS___OPENVMREL = 0x394 // 916 + SYS_WMEMCHR = 0x395 // 917 + SYS_WMEMCMP = 0x396 // 918 + SYS_WMEMCPY = 0x397 // 919 + SYS_WMEMMOVE = 0x398 // 920 + SYS_WMEMSET = 0x399 // 921 + SYS___FPUTWC = 0x400 // 1024 + SYS___PUTWC = 0x401 // 1025 + SYS___PWCHAR = 0x402 // 1026 + SYS___WCSFTM = 0x403 // 1027 + SYS___WCSTOK = 0x404 // 1028 + SYS___WCWDTH = 0x405 // 1029 + SYS_T_ACCEPT = 0x409 // 1033 + SYS_T_ALLOC = 0x40A // 1034 + SYS_T_BIND = 0x40B // 1035 + SYS_T_CLOSE = 0x40C // 1036 + SYS_T_CONNECT = 0x40D // 1037 + SYS_T_ERROR = 0x40E // 1038 + SYS_T_FREE = 0x40F // 1039 + SYS_T_GETINFO = 0x410 // 1040 + SYS_T_GETPROTADDR = 0x411 // 1041 + SYS_T_GETSTATE = 0x412 // 1042 + SYS_T_LISTEN = 0x413 // 1043 + SYS_T_LOOK = 0x414 // 1044 + SYS_T_OPEN = 0x415 // 1045 + SYS_T_OPTMGMT = 0x416 // 1046 + SYS_T_RCV = 0x417 // 1047 + SYS_T_RCVCONNECT = 0x418 // 1048 + SYS_T_RCVDIS = 0x419 // 1049 + SYS_T_RCVREL = 0x41A // 1050 + SYS_T_RCVUDATA = 0x41B // 1051 + SYS_T_RCVUDERR = 0x41C // 1052 + SYS_T_SND = 0x41D // 1053 + SYS_T_SNDDIS = 0x41E // 1054 + SYS_T_SNDREL = 0x41F // 1055 + SYS_T_SNDUDATA = 0x420 // 1056 + SYS_T_STRERROR = 0x421 // 1057 + SYS_T_SYNC = 0x422 // 1058 + SYS_T_UNBIND = 0x423 // 1059 + SYS___T_ERRNO = 0x424 // 1060 + SYS___RECVMSG2 = 0x425 // 1061 + SYS___SENDMSG2 = 0x426 // 1062 + SYS_FATTACH = 0x427 // 1063 + SYS_FDETACH = 0x428 // 1064 + SYS_GETMSG = 0x429 // 1065 + SYS_GETPMSG = 0x42A // 1066 + SYS_ISASTREAM = 0x42B // 1067 + SYS_PUTMSG = 0x42C // 1068 + SYS_PUTPMSG = 0x42D // 1069 + SYS___ISPOSIXON = 0x42E // 1070 + SYS___OPENMVSREL = 0x42F // 1071 + SYS_GETCONTEXT = 0x430 // 1072 + SYS_SETCONTEXT = 0x431 // 1073 + SYS_MAKECONTEXT = 0x432 // 1074 + SYS_SWAPCONTEXT = 0x433 // 1075 + SYS_PTHREAD_GETSPECIFIC_D8_NP = 0x434 // 1076 + SYS_GETCLIENTID = 0x470 // 1136 + SYS___GETCLIENTID = 0x471 // 1137 + SYS_GETSTABLESIZE = 0x472 // 1138 + SYS_GETIBMOPT = 0x473 // 1139 + SYS_GETIBMSOCKOPT = 0x474 // 1140 + SYS_GIVESOCKET = 0x475 // 1141 + SYS_IBMSFLUSH = 0x476 // 1142 + SYS_MAXDESC = 0x477 // 1143 + SYS_SETIBMOPT = 0x478 // 1144 + SYS_SETIBMSOCKOPT = 0x479 // 1145 + SYS_SOCK_DEBUG = 0x47A // 1146 + SYS_SOCK_DO_TESTSTOR = 0x47D // 1149 + SYS_TAKESOCKET = 0x47E // 1150 + SYS___SERVER_INIT = 0x47F // 1151 + SYS___SERVER_PWU = 0x480 // 1152 + SYS_PTHREAD_TAG_NP = 0x481 // 1153 + SYS___CONSOLE = 0x482 // 1154 + SYS___WSINIT = 0x483 // 1155 + SYS___IPTCPN = 0x489 // 1161 + SYS___SMF_RECORD = 0x48A // 1162 + SYS___IPHOST = 0x48B // 1163 + SYS___IPNODE = 0x48C // 1164 + SYS___SERVER_CLASSIFY_CREATE = 0x48D // 1165 + SYS___SERVER_CLASSIFY_DESTROY = 0x48E // 1166 + SYS___SERVER_CLASSIFY_RESET = 0x48F // 1167 + SYS___SERVER_CLASSIFY = 0x490 // 1168 + SYS___HEAPRPT = 0x496 // 1174 + SYS___FNWSA = 0x49B // 1179 + SYS___SPAWN2 = 0x49D // 1181 + SYS___SPAWNP2 = 0x49E // 1182 + SYS___GDRR = 0x4A1 // 1185 + SYS___HRRNO = 0x4A2 // 1186 + SYS___OPRG = 0x4A3 // 1187 + SYS___OPRR = 0x4A4 // 1188 + SYS___OPND = 0x4A5 // 1189 + SYS___OPPT = 0x4A6 // 1190 + SYS___SIGGM = 0x4A7 // 1191 + SYS___DGHT = 0x4A8 // 1192 + SYS___TZNE = 0x4A9 // 1193 + SYS___TZZN = 0x4AA // 1194 + SYS___TRRNO = 0x4AF // 1199 + SYS___ENVN = 0x4B0 // 1200 + SYS___MLOCKALL = 0x4B1 // 1201 + SYS_CREATEWO = 0x4B2 // 1202 + SYS_CREATEWORKUNIT = 0x4B2 // 1202 + SYS_CONTINUE = 0x4B3 // 1203 + SYS_CONTINUEWORKUNIT = 0x4B3 // 1203 + SYS_CONNECTW = 0x4B4 // 1204 + SYS_CONNECTWORKMGR = 0x4B4 // 1204 + SYS_CONNECTS = 0x4B5 // 1205 + SYS_CONNECTSERVER = 0x4B5 // 1205 + SYS_DISCONNE = 0x4B6 // 1206 + SYS_DISCONNECTSERVER = 0x4B6 // 1206 + SYS_JOINWORK = 0x4B7 // 1207 + SYS_JOINWORKUNIT = 0x4B7 // 1207 + SYS_LEAVEWOR = 0x4B8 // 1208 + SYS_LEAVEWORKUNIT = 0x4B8 // 1208 + SYS_DELETEWO = 0x4B9 // 1209 + SYS_DELETEWORKUNIT = 0x4B9 // 1209 + SYS_QUERYMET = 0x4BA // 1210 + SYS_QUERYMETRICS = 0x4BA // 1210 + SYS_QUERYSCH = 0x4BB // 1211 + SYS_QUERYSCHENV = 0x4BB // 1211 + SYS_CHECKSCH = 0x4BC // 1212 + SYS_CHECKSCHENV = 0x4BC // 1212 + SYS___PID_AFFINITY = 0x4BD // 1213 + SYS___ASINH_B = 0x4BE // 1214 + SYS___ATAN_B = 0x4BF // 1215 + SYS___CBRT_B = 0x4C0 // 1216 + SYS___CEIL_B = 0x4C1 // 1217 + SYS_COPYSIGN = 0x4C2 // 1218 + SYS___COS_B = 0x4C3 // 1219 + SYS___ERF_B = 0x4C4 // 1220 + SYS___ERFC_B = 0x4C5 // 1221 + SYS___EXPM1_B = 0x4C6 // 1222 + SYS___FABS_B = 0x4C7 // 1223 + SYS_FINITE = 0x4C8 // 1224 + SYS___FLOOR_B = 0x4C9 // 1225 + SYS___FREXP_B = 0x4CA // 1226 + SYS___ILOGB_B = 0x4CB // 1227 + SYS___ISNAN_B = 0x4CC // 1228 + SYS___LDEXP_B = 0x4CD // 1229 + SYS___LOG1P_B = 0x4CE // 1230 + SYS___LOGB_B = 0x4CF // 1231 + SYS_MATHERR = 0x4D0 // 1232 + SYS___MODF_B = 0x4D1 // 1233 + SYS___NEXTAFTER_B = 0x4D2 // 1234 + SYS___RINT_B = 0x4D3 // 1235 + SYS_SCALBN = 0x4D4 // 1236 + SYS_SIGNIFIC = 0x4D5 // 1237 + SYS_SIGNIFICAND = 0x4D5 // 1237 + SYS___SIN_B = 0x4D6 // 1238 + SYS___TAN_B = 0x4D7 // 1239 + SYS___TANH_B = 0x4D8 // 1240 + SYS___ACOS_B = 0x4D9 // 1241 + SYS___ACOSH_B = 0x4DA // 1242 + SYS___ASIN_B = 0x4DB // 1243 + SYS___ATAN2_B = 0x4DC // 1244 + SYS___ATANH_B = 0x4DD // 1245 + SYS___COSH_B = 0x4DE // 1246 + SYS___EXP_B = 0x4DF // 1247 + SYS___FMOD_B = 0x4E0 // 1248 + SYS___GAMMA_B = 0x4E1 // 1249 + SYS_GAMMA_R = 0x4E2 // 1250 + SYS___HYPOT_B = 0x4E3 // 1251 + SYS___J0_B = 0x4E4 // 1252 + SYS___Y0_B = 0x4E5 // 1253 + SYS___J1_B = 0x4E6 // 1254 + SYS___Y1_B = 0x4E7 // 1255 + SYS___JN_B = 0x4E8 // 1256 + SYS___YN_B = 0x4E9 // 1257 + SYS___LGAMMA_B = 0x4EA // 1258 + SYS_LGAMMA_R = 0x4EB // 1259 + SYS___LOG_B = 0x4EC // 1260 + SYS___LOG10_B = 0x4ED // 1261 + SYS___POW_B = 0x4EE // 1262 + SYS___REMAINDER_B = 0x4EF // 1263 + SYS___SCALB_B = 0x4F0 // 1264 + SYS___SINH_B = 0x4F1 // 1265 + SYS___SQRT_B = 0x4F2 // 1266 + SYS___OPENDIR2 = 0x4F3 // 1267 + SYS___READDIR2 = 0x4F4 // 1268 + SYS___LOGIN = 0x4F5 // 1269 + SYS___OPEN_STAT = 0x4F6 // 1270 + SYS_ACCEPT_AND_RECV = 0x4F7 // 1271 + SYS___FP_SETMODE = 0x4F8 // 1272 + SYS___SIGACTIONSET = 0x4FB // 1275 + SYS___UCREATE = 0x4FC // 1276 + SYS___UMALLOC = 0x4FD // 1277 + SYS___UFREE = 0x4FE // 1278 + SYS___UHEAPREPORT = 0x4FF // 1279 + SYS___ISBFP = 0x500 // 1280 + SYS___FP_CAST = 0x501 // 1281 + SYS___CERTIFICATE = 0x502 // 1282 + SYS_SEND_FILE = 0x503 // 1283 + SYS_AIO_CANCEL = 0x504 // 1284 + SYS_AIO_ERROR = 0x505 // 1285 + SYS_AIO_READ = 0x506 // 1286 + SYS_AIO_RETURN = 0x507 // 1287 + SYS_AIO_SUSPEND = 0x508 // 1288 + SYS_AIO_WRITE = 0x509 // 1289 + SYS_PTHREAD_MUTEXATTR_GETPSHARED = 0x50A // 1290 + SYS_PTHREAD_MUTEXATTR_SETPSHARED = 0x50B // 1291 + SYS_PTHREAD_RWLOCK_DESTROY = 0x50C // 1292 + SYS_PTHREAD_RWLOCK_INIT = 0x50D // 1293 + SYS_PTHREAD_RWLOCK_RDLOCK = 0x50E // 1294 + SYS_PTHREAD_RWLOCK_TRYRDLOCK = 0x50F // 1295 + SYS_PTHREAD_RWLOCK_TRYWRLOCK = 0x510 // 1296 + SYS_PTHREAD_RWLOCK_UNLOCK = 0x511 // 1297 + SYS_PTHREAD_RWLOCK_WRLOCK = 0x512 // 1298 + SYS_PTHREAD_RWLOCKATTR_GETPSHARED = 0x513 // 1299 + SYS_PTHREAD_RWLOCKATTR_SETPSHARED = 0x514 // 1300 + SYS_PTHREAD_RWLOCKATTR_INIT = 0x515 // 1301 + SYS_PTHREAD_RWLOCKATTR_DESTROY = 0x516 // 1302 + SYS___CTTBL = 0x517 // 1303 + SYS_PTHREAD_MUTEXATTR_SETTYPE = 0x518 // 1304 + SYS_PTHREAD_MUTEXATTR_GETTYPE = 0x519 // 1305 + SYS___FP_CLR_FLAG = 0x51A // 1306 + SYS___FP_READ_FLAG = 0x51B // 1307 + SYS___FP_RAISE_XCP = 0x51C // 1308 + SYS___FP_CLASS = 0x51D // 1309 + SYS___FP_FINITE = 0x51E // 1310 + SYS___FP_ISNAN = 0x51F // 1311 + SYS___FP_UNORDERED = 0x520 // 1312 + SYS___FP_READ_RND = 0x521 // 1313 + SYS___FP_READ_RND_B = 0x522 // 1314 + SYS___FP_SWAP_RND = 0x523 // 1315 + SYS___FP_SWAP_RND_B = 0x524 // 1316 + SYS___FP_LEVEL = 0x525 // 1317 + SYS___FP_BTOH = 0x526 // 1318 + SYS___FP_HTOB = 0x527 // 1319 + SYS___FPC_RD = 0x528 // 1320 + SYS___FPC_WR = 0x529 // 1321 + SYS___FPC_RW = 0x52A // 1322 + SYS___FPC_SM = 0x52B // 1323 + SYS___FPC_RS = 0x52C // 1324 + SYS_SIGTIMEDWAIT = 0x52D // 1325 + SYS_SIGWAITINFO = 0x52E // 1326 + SYS___CHKBFP = 0x52F // 1327 + SYS___W_PIOCTL = 0x59E // 1438 + SYS___OSENV = 0x59F // 1439 + SYS_EXPORTWO = 0x5A1 // 1441 + SYS_EXPORTWORKUNIT = 0x5A1 // 1441 + SYS_UNDOEXPO = 0x5A2 // 1442 + SYS_UNDOEXPORTWORKUNIT = 0x5A2 // 1442 + SYS_IMPORTWO = 0x5A3 // 1443 + SYS_IMPORTWORKUNIT = 0x5A3 // 1443 + SYS_UNDOIMPO = 0x5A4 // 1444 + SYS_UNDOIMPORTWORKUNIT = 0x5A4 // 1444 + SYS_EXTRACTW = 0x5A5 // 1445 + SYS_EXTRACTWORKUNIT = 0x5A5 // 1445 + SYS___CPL = 0x5A6 // 1446 + SYS___MAP_INIT = 0x5A7 // 1447 + SYS___MAP_SERVICE = 0x5A8 // 1448 + SYS_SIGQUEUE = 0x5A9 // 1449 + SYS___MOUNT = 0x5AA // 1450 + SYS___GETUSERID = 0x5AB // 1451 + SYS___IPDOMAINNAME = 0x5AC // 1452 + SYS_QUERYENC = 0x5AD // 1453 + SYS_QUERYWORKUNITCLASSIFICATION = 0x5AD // 1453 + SYS_CONNECTE = 0x5AE // 1454 + SYS_CONNECTEXPORTIMPORT = 0x5AE // 1454 + SYS___FP_SWAPMODE = 0x5AF // 1455 + SYS_STRTOLL = 0x5B0 // 1456 + SYS_STRTOULL = 0x5B1 // 1457 + SYS___DSA_PREV = 0x5B2 // 1458 + SYS___EP_FIND = 0x5B3 // 1459 + SYS___SERVER_THREADS_QUERY = 0x5B4 // 1460 + SYS___MSGRCV_TIMED = 0x5B7 // 1463 + SYS___SEMOP_TIMED = 0x5B8 // 1464 + SYS___GET_CPUID = 0x5B9 // 1465 + SYS___GET_SYSTEM_SETTINGS = 0x5BA // 1466 + SYS_FTELLO = 0x5C8 // 1480 + SYS_FSEEKO = 0x5C9 // 1481 + SYS_LLDIV = 0x5CB // 1483 + SYS_WCSTOLL = 0x5CC // 1484 + SYS_WCSTOULL = 0x5CD // 1485 + SYS_LLABS = 0x5CE // 1486 + SYS___CONSOLE2 = 0x5D2 // 1490 + SYS_INET_NTOP = 0x5D3 // 1491 + SYS_INET_PTON = 0x5D4 // 1492 + SYS___RES = 0x5D6 // 1494 + SYS_RES_MKQUERY = 0x5D7 // 1495 + SYS_RES_INIT = 0x5D8 // 1496 + SYS_RES_QUERY = 0x5D9 // 1497 + SYS_RES_SEARCH = 0x5DA // 1498 + SYS_RES_SEND = 0x5DB // 1499 + SYS_RES_QUERYDOMAIN = 0x5DC // 1500 + SYS_DN_EXPAND = 0x5DD // 1501 + SYS_DN_SKIPNAME = 0x5DE // 1502 + SYS_DN_COMP = 0x5DF // 1503 + SYS_ASCTIME_R = 0x5E0 // 1504 + SYS_CTIME_R = 0x5E1 // 1505 + SYS_GMTIME_R = 0x5E2 // 1506 + SYS_LOCALTIME_R = 0x5E3 // 1507 + SYS_RAND_R = 0x5E4 // 1508 + SYS_STRTOK_R = 0x5E5 // 1509 + SYS_READDIR_R = 0x5E6 // 1510 + SYS_GETGRGID_R = 0x5E7 // 1511 + SYS_GETGRNAM_R = 0x5E8 // 1512 + SYS_GETLOGIN_R = 0x5E9 // 1513 + SYS_GETPWNAM_R = 0x5EA // 1514 + SYS_GETPWUID_R = 0x5EB // 1515 + SYS_TTYNAME_R = 0x5EC // 1516 + SYS_PTHREAD_ATFORK = 0x5ED // 1517 + SYS_PTHREAD_ATTR_GETGUARDSIZE = 0x5EE // 1518 + SYS_PTHREAD_ATTR_GETSTACKADDR = 0x5EF // 1519 + SYS_PTHREAD_ATTR_SETGUARDSIZE = 0x5F0 // 1520 + SYS_PTHREAD_ATTR_SETSTACKADDR = 0x5F1 // 1521 + SYS_PTHREAD_CONDATTR_GETPSHARED = 0x5F2 // 1522 + SYS_PTHREAD_CONDATTR_SETPSHARED = 0x5F3 // 1523 + SYS_PTHREAD_GETCONCURRENCY = 0x5F4 // 1524 + SYS_PTHREAD_KEY_DELETE = 0x5F5 // 1525 + SYS_PTHREAD_SETCONCURRENCY = 0x5F6 // 1526 + SYS_PTHREAD_SIGMASK = 0x5F7 // 1527 + SYS___DISCARDDATA = 0x5F8 // 1528 + SYS_PTHREAD_ATTR_GETSCHEDPARAM = 0x5F9 // 1529 + SYS_PTHREAD_ATTR_SETSCHEDPARAM = 0x5FA // 1530 + SYS_PTHREAD_ATTR_GETDETACHSTATE_U98 = 0x5FB // 1531 + SYS_PTHREAD_ATTR_SETDETACHSTATE_U98 = 0x5FC // 1532 + SYS_PTHREAD_DETACH_U98 = 0x5FD // 1533 + SYS_PTHREAD_GETSPECIFIC_U98 = 0x5FE // 1534 + SYS_PTHREAD_SETCANCELSTATE = 0x5FF // 1535 + SYS_PTHREAD_SETCANCELTYPE = 0x600 // 1536 + SYS_PTHREAD_TESTCANCEL = 0x601 // 1537 + SYS___ATANF_B = 0x602 // 1538 + SYS___ATANL_B = 0x603 // 1539 + SYS___CEILF_B = 0x604 // 1540 + SYS___CEILL_B = 0x605 // 1541 + SYS___COSF_B = 0x606 // 1542 + SYS___COSL_B = 0x607 // 1543 + SYS___FABSF_B = 0x608 // 1544 + SYS___FABSL_B = 0x609 // 1545 + SYS___FLOORF_B = 0x60A // 1546 + SYS___FLOORL_B = 0x60B // 1547 + SYS___FREXPF_B = 0x60C // 1548 + SYS___FREXPL_B = 0x60D // 1549 + SYS___LDEXPF_B = 0x60E // 1550 + SYS___LDEXPL_B = 0x60F // 1551 + SYS___SINF_B = 0x610 // 1552 + SYS___SINL_B = 0x611 // 1553 + SYS___TANF_B = 0x612 // 1554 + SYS___TANL_B = 0x613 // 1555 + SYS___TANHF_B = 0x614 // 1556 + SYS___TANHL_B = 0x615 // 1557 + SYS___ACOSF_B = 0x616 // 1558 + SYS___ACOSL_B = 0x617 // 1559 + SYS___ASINF_B = 0x618 // 1560 + SYS___ASINL_B = 0x619 // 1561 + SYS___ATAN2F_B = 0x61A // 1562 + SYS___ATAN2L_B = 0x61B // 1563 + SYS___COSHF_B = 0x61C // 1564 + SYS___COSHL_B = 0x61D // 1565 + SYS___EXPF_B = 0x61E // 1566 + SYS___EXPL_B = 0x61F // 1567 + SYS___LOGF_B = 0x620 // 1568 + SYS___LOGL_B = 0x621 // 1569 + SYS___LOG10F_B = 0x622 // 1570 + SYS___LOG10L_B = 0x623 // 1571 + SYS___POWF_B = 0x624 // 1572 + SYS___POWL_B = 0x625 // 1573 + SYS___SINHF_B = 0x626 // 1574 + SYS___SINHL_B = 0x627 // 1575 + SYS___SQRTF_B = 0x628 // 1576 + SYS___SQRTL_B = 0x629 // 1577 + SYS___ABSF_B = 0x62A // 1578 + SYS___ABS_B = 0x62B // 1579 + SYS___ABSL_B = 0x62C // 1580 + SYS___FMODF_B = 0x62D // 1581 + SYS___FMODL_B = 0x62E // 1582 + SYS___MODFF_B = 0x62F // 1583 + SYS___MODFL_B = 0x630 // 1584 + SYS_ABSF = 0x631 // 1585 + SYS_ABSL = 0x632 // 1586 + SYS_ACOSF = 0x633 // 1587 + SYS_ACOSL = 0x634 // 1588 + SYS_ASINF = 0x635 // 1589 + SYS_ASINL = 0x636 // 1590 + SYS_ATAN2F = 0x637 // 1591 + SYS_ATAN2L = 0x638 // 1592 + SYS_ATANF = 0x639 // 1593 + SYS_ATANL = 0x63A // 1594 + SYS_CEILF = 0x63B // 1595 + SYS_CEILL = 0x63C // 1596 + SYS_COSF = 0x63D // 1597 + SYS_COSL = 0x63E // 1598 + SYS_COSHF = 0x63F // 1599 + SYS_COSHL = 0x640 // 1600 + SYS_EXPF = 0x641 // 1601 + SYS_EXPL = 0x642 // 1602 + SYS_TANHF = 0x643 // 1603 + SYS_TANHL = 0x644 // 1604 + SYS_LOG10F = 0x645 // 1605 + SYS_LOG10L = 0x646 // 1606 + SYS_LOGF = 0x647 // 1607 + SYS_LOGL = 0x648 // 1608 + SYS_POWF = 0x649 // 1609 + SYS_POWL = 0x64A // 1610 + SYS_SINF = 0x64B // 1611 + SYS_SINL = 0x64C // 1612 + SYS_SQRTF = 0x64D // 1613 + SYS_SQRTL = 0x64E // 1614 + SYS_SINHF = 0x64F // 1615 + SYS_SINHL = 0x650 // 1616 + SYS_TANF = 0x651 // 1617 + SYS_TANL = 0x652 // 1618 + SYS_FABSF = 0x653 // 1619 + SYS_FABSL = 0x654 // 1620 + SYS_FLOORF = 0x655 // 1621 + SYS_FLOORL = 0x656 // 1622 + SYS_FMODF = 0x657 // 1623 + SYS_FMODL = 0x658 // 1624 + SYS_FREXPF = 0x659 // 1625 + SYS_FREXPL = 0x65A // 1626 + SYS_LDEXPF = 0x65B // 1627 + SYS_LDEXPL = 0x65C // 1628 + SYS_MODFF = 0x65D // 1629 + SYS_MODFL = 0x65E // 1630 + SYS_BTOWC = 0x65F // 1631 + SYS___CHATTR = 0x660 // 1632 + SYS___FCHATTR = 0x661 // 1633 + SYS___TOCCSID = 0x662 // 1634 + SYS___CSNAMETYPE = 0x663 // 1635 + SYS___TOCSNAME = 0x664 // 1636 + SYS___CCSIDTYPE = 0x665 // 1637 + SYS___AE_CORRESTBL_QUERY = 0x666 // 1638 + SYS___AE_AUTOCONVERT_STATE = 0x667 // 1639 + SYS_DN_FIND = 0x668 // 1640 + SYS___GETHOSTBYADDR_A = 0x669 // 1641 + SYS___GETHOSTBYNAME_A = 0x66A // 1642 + SYS___RES_INIT_A = 0x66B // 1643 + SYS___GETHOSTBYADDR_R_A = 0x66C // 1644 + SYS___GETHOSTBYNAME_R_A = 0x66D // 1645 + SYS___CHARMAP_INIT_A = 0x66E // 1646 + SYS___MBLEN_A = 0x66F // 1647 + SYS___MBLEN_SB_A = 0x670 // 1648 + SYS___MBLEN_STD_A = 0x671 // 1649 + SYS___MBLEN_UTF = 0x672 // 1650 + SYS___MBSTOWCS_A = 0x673 // 1651 + SYS___MBSTOWCS_STD_A = 0x674 // 1652 + SYS___MBTOWC_A = 0x675 // 1653 + SYS___MBTOWC_ISO1 = 0x676 // 1654 + SYS___MBTOWC_SBCS = 0x677 // 1655 + SYS___MBTOWC_MBCS = 0x678 // 1656 + SYS___MBTOWC_UTF = 0x679 // 1657 + SYS___WCSTOMBS_A = 0x67A // 1658 + SYS___WCSTOMBS_STD_A = 0x67B // 1659 + SYS___WCSWIDTH_A = 0x67C // 1660 + SYS___GETGRGID_R_A = 0x67D // 1661 + SYS___WCSWIDTH_STD_A = 0x67E // 1662 + SYS___WCSWIDTH_ASIA = 0x67F // 1663 + SYS___CSID_A = 0x680 // 1664 + SYS___CSID_STD_A = 0x681 // 1665 + SYS___WCSID_A = 0x682 // 1666 + SYS___WCSID_STD_A = 0x683 // 1667 + SYS___WCTOMB_A = 0x684 // 1668 + SYS___WCTOMB_ISO1 = 0x685 // 1669 + SYS___WCTOMB_STD_A = 0x686 // 1670 + SYS___WCTOMB_UTF = 0x687 // 1671 + SYS___WCWIDTH_A = 0x688 // 1672 + SYS___GETGRNAM_R_A = 0x689 // 1673 + SYS___WCWIDTH_STD_A = 0x68A // 1674 + SYS___WCWIDTH_ASIA = 0x68B // 1675 + SYS___GETPWNAM_R_A = 0x68C // 1676 + SYS___GETPWUID_R_A = 0x68D // 1677 + SYS___GETLOGIN_R_A = 0x68E // 1678 + SYS___TTYNAME_R_A = 0x68F // 1679 + SYS___READDIR_R_A = 0x690 // 1680 + SYS___E2A_S = 0x691 // 1681 + SYS___FNMATCH_A = 0x692 // 1682 + SYS___FNMATCH_C_A = 0x693 // 1683 + SYS___EXECL_A = 0x694 // 1684 + SYS___FNMATCH_STD_A = 0x695 // 1685 + SYS___REGCOMP_A = 0x696 // 1686 + SYS___REGCOMP_STD_A = 0x697 // 1687 + SYS___REGERROR_A = 0x698 // 1688 + SYS___REGERROR_STD_A = 0x699 // 1689 + SYS___REGEXEC_A = 0x69A // 1690 + SYS___REGEXEC_STD_A = 0x69B // 1691 + SYS___REGFREE_A = 0x69C // 1692 + SYS___REGFREE_STD_A = 0x69D // 1693 + SYS___STRCOLL_A = 0x69E // 1694 + SYS___STRCOLL_C_A = 0x69F // 1695 + SYS___EXECLE_A = 0x6A0 // 1696 + SYS___STRCOLL_STD_A = 0x6A1 // 1697 + SYS___STRXFRM_A = 0x6A2 // 1698 + SYS___STRXFRM_C_A = 0x6A3 // 1699 + SYS___EXECLP_A = 0x6A4 // 1700 + SYS___STRXFRM_STD_A = 0x6A5 // 1701 + SYS___WCSCOLL_A = 0x6A6 // 1702 + SYS___WCSCOLL_C_A = 0x6A7 // 1703 + SYS___WCSCOLL_STD_A = 0x6A8 // 1704 + SYS___WCSXFRM_A = 0x6A9 // 1705 + SYS___WCSXFRM_C_A = 0x6AA // 1706 + SYS___WCSXFRM_STD_A = 0x6AB // 1707 + SYS___COLLATE_INIT_A = 0x6AC // 1708 + SYS___WCTYPE_A = 0x6AD // 1709 + SYS___GET_WCTYPE_STD_A = 0x6AE // 1710 + SYS___CTYPE_INIT_A = 0x6AF // 1711 + SYS___ISWCTYPE_A = 0x6B0 // 1712 + SYS___EXECV_A = 0x6B1 // 1713 + SYS___IS_WCTYPE_STD_A = 0x6B2 // 1714 + SYS___TOWLOWER_A = 0x6B3 // 1715 + SYS___TOWLOWER_STD_A = 0x6B4 // 1716 + SYS___TOWUPPER_A = 0x6B5 // 1717 + SYS___TOWUPPER_STD_A = 0x6B6 // 1718 + SYS___LOCALE_INIT_A = 0x6B7 // 1719 + SYS___LOCALECONV_A = 0x6B8 // 1720 + SYS___LOCALECONV_STD_A = 0x6B9 // 1721 + SYS___NL_LANGINFO_A = 0x6BA // 1722 + SYS___NL_LNAGINFO_STD_A = 0x6BB // 1723 + SYS___MONETARY_INIT_A = 0x6BC // 1724 + SYS___STRFMON_A = 0x6BD // 1725 + SYS___STRFMON_STD_A = 0x6BE // 1726 + SYS___GETADDRINFO_A = 0x6BF // 1727 + SYS___CATGETS_A = 0x6C0 // 1728 + SYS___EXECVE_A = 0x6C1 // 1729 + SYS___EXECVP_A = 0x6C2 // 1730 + SYS___SPAWN_A = 0x6C3 // 1731 + SYS___GETNAMEINFO_A = 0x6C4 // 1732 + SYS___SPAWNP_A = 0x6C5 // 1733 + SYS___NUMERIC_INIT_A = 0x6C6 // 1734 + SYS___RESP_INIT_A = 0x6C7 // 1735 + SYS___RPMATCH_A = 0x6C8 // 1736 + SYS___RPMATCH_C_A = 0x6C9 // 1737 + SYS___RPMATCH_STD_A = 0x6CA // 1738 + SYS___TIME_INIT_A = 0x6CB // 1739 + SYS___STRFTIME_A = 0x6CC // 1740 + SYS___STRFTIME_STD_A = 0x6CD // 1741 + SYS___STRPTIME_A = 0x6CE // 1742 + SYS___STRPTIME_STD_A = 0x6CF // 1743 + SYS___WCSFTIME_A = 0x6D0 // 1744 + SYS___WCSFTIME_STD_A = 0x6D1 // 1745 + SYS_____SPAWN2_A = 0x6D2 // 1746 + SYS_____SPAWNP2_A = 0x6D3 // 1747 + SYS___SYNTAX_INIT_A = 0x6D4 // 1748 + SYS___TOD_INIT_A = 0x6D5 // 1749 + SYS___NL_CSINFO_A = 0x6D6 // 1750 + SYS___NL_MONINFO_A = 0x6D7 // 1751 + SYS___NL_NUMINFO_A = 0x6D8 // 1752 + SYS___NL_RESPINFO_A = 0x6D9 // 1753 + SYS___NL_TIMINFO_A = 0x6DA // 1754 + SYS___IF_NAMETOINDEX_A = 0x6DB // 1755 + SYS___IF_INDEXTONAME_A = 0x6DC // 1756 + SYS___PRINTF_A = 0x6DD // 1757 + SYS___ICONV_OPEN_A = 0x6DE // 1758 + SYS___DLLLOAD_A = 0x6DF // 1759 + SYS___DLLQUERYFN_A = 0x6E0 // 1760 + SYS___DLLQUERYVAR_A = 0x6E1 // 1761 + SYS_____CHATTR_A = 0x6E2 // 1762 + SYS___E2A_L = 0x6E3 // 1763 + SYS_____TOCCSID_A = 0x6E4 // 1764 + SYS_____TOCSNAME_A = 0x6E5 // 1765 + SYS_____CCSIDTYPE_A = 0x6E6 // 1766 + SYS_____CSNAMETYPE_A = 0x6E7 // 1767 + SYS___CHMOD_A = 0x6E8 // 1768 + SYS___MKDIR_A = 0x6E9 // 1769 + SYS___STAT_A = 0x6EA // 1770 + SYS___STAT_O_A = 0x6EB // 1771 + SYS___MKFIFO_A = 0x6EC // 1772 + SYS_____OPEN_STAT_A = 0x6ED // 1773 + SYS___LSTAT_A = 0x6EE // 1774 + SYS___LSTAT_O_A = 0x6EF // 1775 + SYS___MKNOD_A = 0x6F0 // 1776 + SYS___MOUNT_A = 0x6F1 // 1777 + SYS___UMOUNT_A = 0x6F2 // 1778 + SYS___CHAUDIT_A = 0x6F4 // 1780 + SYS___W_GETMNTENT_A = 0x6F5 // 1781 + SYS___CREAT_A = 0x6F6 // 1782 + SYS___OPEN_A = 0x6F7 // 1783 + SYS___SETLOCALE_A = 0x6F9 // 1785 + SYS___FPRINTF_A = 0x6FA // 1786 + SYS___SPRINTF_A = 0x6FB // 1787 + SYS___VFPRINTF_A = 0x6FC // 1788 + SYS___VPRINTF_A = 0x6FD // 1789 + SYS___VSPRINTF_A = 0x6FE // 1790 + SYS___VSWPRINTF_A = 0x6FF // 1791 + SYS___SWPRINTF_A = 0x700 // 1792 + SYS___FSCANF_A = 0x701 // 1793 + SYS___SCANF_A = 0x702 // 1794 + SYS___SSCANF_A = 0x703 // 1795 + SYS___SWSCANF_A = 0x704 // 1796 + SYS___ATOF_A = 0x705 // 1797 + SYS___ATOI_A = 0x706 // 1798 + SYS___ATOL_A = 0x707 // 1799 + SYS___STRTOD_A = 0x708 // 1800 + SYS___STRTOL_A = 0x709 // 1801 + SYS___STRTOUL_A = 0x70A // 1802 + SYS_____AE_CORRESTBL_QUERY_A = 0x70B // 1803 + SYS___A64L_A = 0x70C // 1804 + SYS___ECVT_A = 0x70D // 1805 + SYS___FCVT_A = 0x70E // 1806 + SYS___GCVT_A = 0x70F // 1807 + SYS___L64A_A = 0x710 // 1808 + SYS___STRERROR_A = 0x711 // 1809 + SYS___PERROR_A = 0x712 // 1810 + SYS___FETCH_A = 0x713 // 1811 + SYS___GETENV_A = 0x714 // 1812 + SYS___MKSTEMP_A = 0x717 // 1815 + SYS___PTSNAME_A = 0x718 // 1816 + SYS___PUTENV_A = 0x719 // 1817 + SYS___REALPATH_A = 0x71A // 1818 + SYS___SETENV_A = 0x71B // 1819 + SYS___SYSTEM_A = 0x71C // 1820 + SYS___GETOPT_A = 0x71D // 1821 + SYS___CATOPEN_A = 0x71E // 1822 + SYS___ACCESS_A = 0x71F // 1823 + SYS___CHDIR_A = 0x720 // 1824 + SYS___CHOWN_A = 0x721 // 1825 + SYS___CHROOT_A = 0x722 // 1826 + SYS___GETCWD_A = 0x723 // 1827 + SYS___GETWD_A = 0x724 // 1828 + SYS___LCHOWN_A = 0x725 // 1829 + SYS___LINK_A = 0x726 // 1830 + SYS___PATHCONF_A = 0x727 // 1831 + SYS___IF_NAMEINDEX_A = 0x728 // 1832 + SYS___READLINK_A = 0x729 // 1833 + SYS___RMDIR_A = 0x72A // 1834 + SYS___STATVFS_A = 0x72B // 1835 + SYS___SYMLINK_A = 0x72C // 1836 + SYS___TRUNCATE_A = 0x72D // 1837 + SYS___UNLINK_A = 0x72E // 1838 + SYS___GAI_STRERROR_A = 0x72F // 1839 + SYS___EXTLINK_NP_A = 0x730 // 1840 + SYS___ISALNUM_A = 0x731 // 1841 + SYS___ISALPHA_A = 0x732 // 1842 + SYS___A2E_S = 0x733 // 1843 + SYS___ISCNTRL_A = 0x734 // 1844 + SYS___ISDIGIT_A = 0x735 // 1845 + SYS___ISGRAPH_A = 0x736 // 1846 + SYS___ISLOWER_A = 0x737 // 1847 + SYS___ISPRINT_A = 0x738 // 1848 + SYS___ISPUNCT_A = 0x739 // 1849 + SYS___ISSPACE_A = 0x73A // 1850 + SYS___ISUPPER_A = 0x73B // 1851 + SYS___ISXDIGIT_A = 0x73C // 1852 + SYS___TOLOWER_A = 0x73D // 1853 + SYS___TOUPPER_A = 0x73E // 1854 + SYS___ISWALNUM_A = 0x73F // 1855 + SYS___ISWALPHA_A = 0x740 // 1856 + SYS___A2E_L = 0x741 // 1857 + SYS___ISWCNTRL_A = 0x742 // 1858 + SYS___ISWDIGIT_A = 0x743 // 1859 + SYS___ISWGRAPH_A = 0x744 // 1860 + SYS___ISWLOWER_A = 0x745 // 1861 + SYS___ISWPRINT_A = 0x746 // 1862 + SYS___ISWPUNCT_A = 0x747 // 1863 + SYS___ISWSPACE_A = 0x748 // 1864 + SYS___ISWUPPER_A = 0x749 // 1865 + SYS___ISWXDIGIT_A = 0x74A // 1866 + SYS___CONFSTR_A = 0x74B // 1867 + SYS___FTOK_A = 0x74C // 1868 + SYS___MKTEMP_A = 0x74D // 1869 + SYS___FDOPEN_A = 0x74E // 1870 + SYS___FLDATA_A = 0x74F // 1871 + SYS___REMOVE_A = 0x750 // 1872 + SYS___RENAME_A = 0x751 // 1873 + SYS___TMPNAM_A = 0x752 // 1874 + SYS___FOPEN_A = 0x753 // 1875 + SYS___FREOPEN_A = 0x754 // 1876 + SYS___CUSERID_A = 0x755 // 1877 + SYS___POPEN_A = 0x756 // 1878 + SYS___TEMPNAM_A = 0x757 // 1879 + SYS___FTW_A = 0x758 // 1880 + SYS___GETGRENT_A = 0x759 // 1881 + SYS___GETGRGID_A = 0x75A // 1882 + SYS___GETGRNAM_A = 0x75B // 1883 + SYS___GETGROUPSBYNAME_A = 0x75C // 1884 + SYS___GETHOSTENT_A = 0x75D // 1885 + SYS___GETHOSTNAME_A = 0x75E // 1886 + SYS___GETLOGIN_A = 0x75F // 1887 + SYS___INET_NTOP_A = 0x760 // 1888 + SYS___GETPASS_A = 0x761 // 1889 + SYS___GETPWENT_A = 0x762 // 1890 + SYS___GETPWNAM_A = 0x763 // 1891 + SYS___GETPWUID_A = 0x764 // 1892 + SYS_____CHECK_RESOURCE_AUTH_NP_A = 0x765 // 1893 + SYS___CHECKSCHENV_A = 0x766 // 1894 + SYS___CONNECTSERVER_A = 0x767 // 1895 + SYS___CONNECTWORKMGR_A = 0x768 // 1896 + SYS_____CONSOLE_A = 0x769 // 1897 + SYS___CREATEWORKUNIT_A = 0x76A // 1898 + SYS___CTERMID_A = 0x76B // 1899 + SYS___FMTMSG_A = 0x76C // 1900 + SYS___INITGROUPS_A = 0x76D // 1901 + SYS_____LOGIN_A = 0x76E // 1902 + SYS___MSGRCV_A = 0x76F // 1903 + SYS___MSGSND_A = 0x770 // 1904 + SYS___MSGXRCV_A = 0x771 // 1905 + SYS___NFTW_A = 0x772 // 1906 + SYS_____PASSWD_A = 0x773 // 1907 + SYS___PTHREAD_SECURITY_NP_A = 0x774 // 1908 + SYS___QUERYMETRICS_A = 0x775 // 1909 + SYS___QUERYSCHENV = 0x776 // 1910 + SYS___READV_A = 0x777 // 1911 + SYS_____SERVER_CLASSIFY_A = 0x778 // 1912 + SYS_____SERVER_INIT_A = 0x779 // 1913 + SYS_____SERVER_PWU_A = 0x77A // 1914 + SYS___STRCASECMP_A = 0x77B // 1915 + SYS___STRNCASECMP_A = 0x77C // 1916 + SYS___TTYNAME_A = 0x77D // 1917 + SYS___UNAME_A = 0x77E // 1918 + SYS___UTIMES_A = 0x77F // 1919 + SYS___W_GETPSENT_A = 0x780 // 1920 + SYS___WRITEV_A = 0x781 // 1921 + SYS___W_STATFS_A = 0x782 // 1922 + SYS___W_STATVFS_A = 0x783 // 1923 + SYS___FPUTC_A = 0x784 // 1924 + SYS___PUTCHAR_A = 0x785 // 1925 + SYS___PUTS_A = 0x786 // 1926 + SYS___FGETS_A = 0x787 // 1927 + SYS___GETS_A = 0x788 // 1928 + SYS___FPUTS_A = 0x789 // 1929 + SYS___FREAD_A = 0x78A // 1930 + SYS___FWRITE_A = 0x78B // 1931 + SYS___OPEN_O_A = 0x78C // 1932 + SYS___ISASCII = 0x78D // 1933 + SYS___CREAT_O_A = 0x78E // 1934 + SYS___ENVNA = 0x78F // 1935 + SYS___PUTC_A = 0x790 // 1936 + SYS___AE_THREAD_SETMODE = 0x791 // 1937 + SYS___AE_THREAD_SWAPMODE = 0x792 // 1938 + SYS___GETNETBYADDR_A = 0x793 // 1939 + SYS___GETNETBYNAME_A = 0x794 // 1940 + SYS___GETNETENT_A = 0x795 // 1941 + SYS___GETPROTOBYNAME_A = 0x796 // 1942 + SYS___GETPROTOBYNUMBER_A = 0x797 // 1943 + SYS___GETPROTOENT_A = 0x798 // 1944 + SYS___GETSERVBYNAME_A = 0x799 // 1945 + SYS___GETSERVBYPORT_A = 0x79A // 1946 + SYS___GETSERVENT_A = 0x79B // 1947 + SYS___ASCTIME_A = 0x79C // 1948 + SYS___CTIME_A = 0x79D // 1949 + SYS___GETDATE_A = 0x79E // 1950 + SYS___TZSET_A = 0x79F // 1951 + SYS___UTIME_A = 0x7A0 // 1952 + SYS___ASCTIME_R_A = 0x7A1 // 1953 + SYS___CTIME_R_A = 0x7A2 // 1954 + SYS___STRTOLL_A = 0x7A3 // 1955 + SYS___STRTOULL_A = 0x7A4 // 1956 + SYS___FPUTWC_A = 0x7A5 // 1957 + SYS___PUTWC_A = 0x7A6 // 1958 + SYS___PUTWCHAR_A = 0x7A7 // 1959 + SYS___FPUTWS_A = 0x7A8 // 1960 + SYS___UNGETWC_A = 0x7A9 // 1961 + SYS___FGETWC_A = 0x7AA // 1962 + SYS___GETWC_A = 0x7AB // 1963 + SYS___GETWCHAR_A = 0x7AC // 1964 + SYS___FGETWS_A = 0x7AD // 1965 + SYS___GETTIMEOFDAY_A = 0x7AE // 1966 + SYS___GMTIME_A = 0x7AF // 1967 + SYS___GMTIME_R_A = 0x7B0 // 1968 + SYS___LOCALTIME_A = 0x7B1 // 1969 + SYS___LOCALTIME_R_A = 0x7B2 // 1970 + SYS___MKTIME_A = 0x7B3 // 1971 + SYS___TZZNA = 0x7B4 // 1972 + SYS_UNATEXIT = 0x7B5 // 1973 + SYS___CEE3DMP_A = 0x7B6 // 1974 + SYS___CDUMP_A = 0x7B7 // 1975 + SYS___CSNAP_A = 0x7B8 // 1976 + SYS___CTEST_A = 0x7B9 // 1977 + SYS___CTRACE_A = 0x7BA // 1978 + SYS___VSWPRNTF2_A = 0x7BB // 1979 + SYS___INET_PTON_A = 0x7BC // 1980 + SYS___SYSLOG_A = 0x7BD // 1981 + SYS___CRYPT_A = 0x7BE // 1982 + SYS_____OPENDIR2_A = 0x7BF // 1983 + SYS_____READDIR2_A = 0x7C0 // 1984 + SYS___OPENDIR_A = 0x7C2 // 1986 + SYS___READDIR_A = 0x7C3 // 1987 + SYS_PREAD = 0x7C7 // 1991 + SYS_PWRITE = 0x7C8 // 1992 + SYS_M_CREATE_LAYOUT = 0x7C9 // 1993 + SYS_M_DESTROY_LAYOUT = 0x7CA // 1994 + SYS_M_GETVALUES_LAYOUT = 0x7CB // 1995 + SYS_M_SETVALUES_LAYOUT = 0x7CC // 1996 + SYS_M_TRANSFORM_LAYOUT = 0x7CD // 1997 + SYS_M_WTRANSFORM_LAYOUT = 0x7CE // 1998 + SYS_FWPRINTF = 0x7D1 // 2001 + SYS_WPRINTF = 0x7D2 // 2002 + SYS_VFWPRINT = 0x7D3 // 2003 + SYS_VFWPRINTF = 0x7D3 // 2003 + SYS_VWPRINTF = 0x7D4 // 2004 + SYS_FWSCANF = 0x7D5 // 2005 + SYS_WSCANF = 0x7D6 // 2006 + SYS_WCTRANS = 0x7D7 // 2007 + SYS_TOWCTRAN = 0x7D8 // 2008 + SYS_TOWCTRANS = 0x7D8 // 2008 + SYS___WCSTOD_A = 0x7D9 // 2009 + SYS___WCSTOL_A = 0x7DA // 2010 + SYS___WCSTOUL_A = 0x7DB // 2011 + SYS___BASENAME_A = 0x7DC // 2012 + SYS___DIRNAME_A = 0x7DD // 2013 + SYS___GLOB_A = 0x7DE // 2014 + SYS_FWIDE = 0x7DF // 2015 + SYS___OSNAME = 0x7E0 // 2016 + SYS_____OSNAME_A = 0x7E1 // 2017 + SYS___BTOWC_A = 0x7E4 // 2020 + SYS___WCTOB_A = 0x7E5 // 2021 + SYS___DBM_OPEN_A = 0x7E6 // 2022 + SYS___VFPRINTF2_A = 0x7E7 // 2023 + SYS___VPRINTF2_A = 0x7E8 // 2024 + SYS___VSPRINTF2_A = 0x7E9 // 2025 + SYS___CEIL_H = 0x7EA // 2026 + SYS___FLOOR_H = 0x7EB // 2027 + SYS___MODF_H = 0x7EC // 2028 + SYS___FABS_H = 0x7ED // 2029 + SYS___J0_H = 0x7EE // 2030 + SYS___J1_H = 0x7EF // 2031 + SYS___JN_H = 0x7F0 // 2032 + SYS___Y0_H = 0x7F1 // 2033 + SYS___Y1_H = 0x7F2 // 2034 + SYS___YN_H = 0x7F3 // 2035 + SYS___CEILF_H = 0x7F4 // 2036 + SYS___CEILL_H = 0x7F5 // 2037 + SYS___FLOORF_H = 0x7F6 // 2038 + SYS___FLOORL_H = 0x7F7 // 2039 + SYS___MODFF_H = 0x7F8 // 2040 + SYS___MODFL_H = 0x7F9 // 2041 + SYS___FABSF_H = 0x7FA // 2042 + SYS___FABSL_H = 0x7FB // 2043 + SYS___MALLOC24 = 0x7FC // 2044 + SYS___MALLOC31 = 0x7FD // 2045 + SYS_ACL_INIT = 0x7FE // 2046 + SYS_ACL_FREE = 0x7FF // 2047 + SYS_ACL_FIRST_ENTRY = 0x800 // 2048 + SYS_ACL_GET_ENTRY = 0x801 // 2049 + SYS_ACL_VALID = 0x802 // 2050 + SYS_ACL_CREATE_ENTRY = 0x803 // 2051 + SYS_ACL_DELETE_ENTRY = 0x804 // 2052 + SYS_ACL_UPDATE_ENTRY = 0x805 // 2053 + SYS_ACL_DELETE_FD = 0x806 // 2054 + SYS_ACL_DELETE_FILE = 0x807 // 2055 + SYS_ACL_GET_FD = 0x808 // 2056 + SYS_ACL_GET_FILE = 0x809 // 2057 + SYS_ACL_SET_FD = 0x80A // 2058 + SYS_ACL_SET_FILE = 0x80B // 2059 + SYS_ACL_FROM_TEXT = 0x80C // 2060 + SYS_ACL_TO_TEXT = 0x80D // 2061 + SYS_ACL_SORT = 0x80E // 2062 + SYS___SHUTDOWN_REGISTRATION = 0x80F // 2063 + SYS___ERFL_B = 0x810 // 2064 + SYS___ERFCL_B = 0x811 // 2065 + SYS___LGAMMAL_B = 0x812 // 2066 + SYS___SETHOOKEVENTS = 0x813 // 2067 + SYS_IF_NAMETOINDEX = 0x814 // 2068 + SYS_IF_INDEXTONAME = 0x815 // 2069 + SYS_IF_NAMEINDEX = 0x816 // 2070 + SYS_IF_FREENAMEINDEX = 0x817 // 2071 + SYS_GETADDRINFO = 0x818 // 2072 + SYS_GETNAMEINFO = 0x819 // 2073 + SYS_FREEADDRINFO = 0x81A // 2074 + SYS_GAI_STRERROR = 0x81B // 2075 + SYS_REXEC_AF = 0x81C // 2076 + SYS___POE = 0x81D // 2077 + SYS___DYNALLOC_A = 0x81F // 2079 + SYS___DYNFREE_A = 0x820 // 2080 + SYS___RES_QUERY_A = 0x821 // 2081 + SYS___RES_SEARCH_A = 0x822 // 2082 + SYS___RES_QUERYDOMAIN_A = 0x823 // 2083 + SYS___RES_MKQUERY_A = 0x824 // 2084 + SYS___RES_SEND_A = 0x825 // 2085 + SYS___DN_EXPAND_A = 0x826 // 2086 + SYS___DN_SKIPNAME_A = 0x827 // 2087 + SYS___DN_COMP_A = 0x828 // 2088 + SYS___DN_FIND_A = 0x829 // 2089 + SYS___NLIST_A = 0x82A // 2090 + SYS_____TCGETCP_A = 0x82B // 2091 + SYS_____TCSETCP_A = 0x82C // 2092 + SYS_____W_PIOCTL_A = 0x82E // 2094 + SYS___INET_ADDR_A = 0x82F // 2095 + SYS___INET_NTOA_A = 0x830 // 2096 + SYS___INET_NETWORK_A = 0x831 // 2097 + SYS___ACCEPT_A = 0x832 // 2098 + SYS___ACCEPT_AND_RECV_A = 0x833 // 2099 + SYS___BIND_A = 0x834 // 2100 + SYS___CONNECT_A = 0x835 // 2101 + SYS___GETPEERNAME_A = 0x836 // 2102 + SYS___GETSOCKNAME_A = 0x837 // 2103 + SYS___RECVFROM_A = 0x838 // 2104 + SYS___SENDTO_A = 0x839 // 2105 + SYS___SENDMSG_A = 0x83A // 2106 + SYS___RECVMSG_A = 0x83B // 2107 + SYS_____LCHATTR_A = 0x83C // 2108 + SYS___CABEND = 0x83D // 2109 + SYS___LE_CIB_GET = 0x83E // 2110 + SYS___SET_LAA_FOR_JIT = 0x83F // 2111 + SYS___LCHATTR = 0x840 // 2112 + SYS___WRITEDOWN = 0x841 // 2113 + SYS_PTHREAD_MUTEX_INIT2 = 0x842 // 2114 + SYS___ACOSHF_B = 0x843 // 2115 + SYS___ACOSHL_B = 0x844 // 2116 + SYS___ASINHF_B = 0x845 // 2117 + SYS___ASINHL_B = 0x846 // 2118 + SYS___ATANHF_B = 0x847 // 2119 + SYS___ATANHL_B = 0x848 // 2120 + SYS___CBRTF_B = 0x849 // 2121 + SYS___CBRTL_B = 0x84A // 2122 + SYS___COPYSIGNF_B = 0x84B // 2123 + SYS___COPYSIGNL_B = 0x84C // 2124 + SYS___COTANF_B = 0x84D // 2125 + SYS___COTAN_B = 0x84E // 2126 + SYS___COTANL_B = 0x84F // 2127 + SYS___EXP2F_B = 0x850 // 2128 + SYS___EXP2L_B = 0x851 // 2129 + SYS___EXPM1F_B = 0x852 // 2130 + SYS___EXPM1L_B = 0x853 // 2131 + SYS___FDIMF_B = 0x854 // 2132 + SYS___FDIM_B = 0x855 // 2133 + SYS___FDIML_B = 0x856 // 2134 + SYS___HYPOTF_B = 0x857 // 2135 + SYS___HYPOTL_B = 0x858 // 2136 + SYS___LOG1PF_B = 0x859 // 2137 + SYS___LOG1PL_B = 0x85A // 2138 + SYS___LOG2F_B = 0x85B // 2139 + SYS___LOG2_B = 0x85C // 2140 + SYS___LOG2L_B = 0x85D // 2141 + SYS___REMAINDERF_B = 0x85E // 2142 + SYS___REMAINDERL_B = 0x85F // 2143 + SYS___REMQUOF_B = 0x860 // 2144 + SYS___REMQUO_B = 0x861 // 2145 + SYS___REMQUOL_B = 0x862 // 2146 + SYS___TGAMMAF_B = 0x863 // 2147 + SYS___TGAMMA_B = 0x864 // 2148 + SYS___TGAMMAL_B = 0x865 // 2149 + SYS___TRUNCF_B = 0x866 // 2150 + SYS___TRUNC_B = 0x867 // 2151 + SYS___TRUNCL_B = 0x868 // 2152 + SYS___LGAMMAF_B = 0x869 // 2153 + SYS___LROUNDF_B = 0x86A // 2154 + SYS___LROUND_B = 0x86B // 2155 + SYS___ERFF_B = 0x86C // 2156 + SYS___ERFCF_B = 0x86D // 2157 + SYS_ACOSHF = 0x86E // 2158 + SYS_ACOSHL = 0x86F // 2159 + SYS_ASINHF = 0x870 // 2160 + SYS_ASINHL = 0x871 // 2161 + SYS_ATANHF = 0x872 // 2162 + SYS_ATANHL = 0x873 // 2163 + SYS_CBRTF = 0x874 // 2164 + SYS_CBRTL = 0x875 // 2165 + SYS_COPYSIGNF = 0x876 // 2166 + SYS_CPYSIGNF = 0x876 // 2166 + SYS_COPYSIGNL = 0x877 // 2167 + SYS_CPYSIGNL = 0x877 // 2167 + SYS_COTANF = 0x878 // 2168 + SYS___COTANF = 0x878 // 2168 + SYS_COTAN = 0x879 // 2169 + SYS___COTAN = 0x879 // 2169 + SYS_COTANL = 0x87A // 2170 + SYS___COTANL = 0x87A // 2170 + SYS_EXP2F = 0x87B // 2171 + SYS_EXP2L = 0x87C // 2172 + SYS_EXPM1F = 0x87D // 2173 + SYS_EXPM1L = 0x87E // 2174 + SYS_FDIMF = 0x87F // 2175 + SYS_FDIM = 0x881 // 2177 + SYS_FDIML = 0x882 // 2178 + SYS_HYPOTF = 0x883 // 2179 + SYS_HYPOTL = 0x884 // 2180 + SYS_LOG1PF = 0x885 // 2181 + SYS_LOG1PL = 0x886 // 2182 + SYS_LOG2F = 0x887 // 2183 + SYS_LOG2 = 0x888 // 2184 + SYS_LOG2L = 0x889 // 2185 + SYS_REMAINDERF = 0x88A // 2186 + SYS_REMAINDF = 0x88A // 2186 + SYS_REMAINDERL = 0x88B // 2187 + SYS_REMAINDL = 0x88B // 2187 + SYS_REMQUOF = 0x88C // 2188 + SYS_REMQUO = 0x88D // 2189 + SYS_REMQUOL = 0x88E // 2190 + SYS_TGAMMAF = 0x88F // 2191 + SYS_TGAMMA = 0x890 // 2192 + SYS_TGAMMAL = 0x891 // 2193 + SYS_TRUNCF = 0x892 // 2194 + SYS_TRUNC = 0x893 // 2195 + SYS_TRUNCL = 0x894 // 2196 + SYS_LGAMMAF = 0x895 // 2197 + SYS_LGAMMAL = 0x896 // 2198 + SYS_LROUNDF = 0x897 // 2199 + SYS_LROUND = 0x898 // 2200 + SYS_ERFF = 0x899 // 2201 + SYS_ERFL = 0x89A // 2202 + SYS_ERFCF = 0x89B // 2203 + SYS_ERFCL = 0x89C // 2204 + SYS___EXP2_B = 0x89D // 2205 + SYS_EXP2 = 0x89E // 2206 + SYS___FAR_JUMP = 0x89F // 2207 + SYS___TCGETATTR_A = 0x8A1 // 2209 + SYS___TCSETATTR_A = 0x8A2 // 2210 + SYS___SUPERKILL = 0x8A4 // 2212 + SYS___LE_CONDITION_TOKEN_BUILD = 0x8A5 // 2213 + SYS___LE_MSG_ADD_INSERT = 0x8A6 // 2214 + SYS___LE_MSG_GET = 0x8A7 // 2215 + SYS___LE_MSG_GET_AND_WRITE = 0x8A8 // 2216 + SYS___LE_MSG_WRITE = 0x8A9 // 2217 + SYS___ITOA = 0x8AA // 2218 + SYS___UTOA = 0x8AB // 2219 + SYS___LTOA = 0x8AC // 2220 + SYS___ULTOA = 0x8AD // 2221 + SYS___LLTOA = 0x8AE // 2222 + SYS___ULLTOA = 0x8AF // 2223 + SYS___ITOA_A = 0x8B0 // 2224 + SYS___UTOA_A = 0x8B1 // 2225 + SYS___LTOA_A = 0x8B2 // 2226 + SYS___ULTOA_A = 0x8B3 // 2227 + SYS___LLTOA_A = 0x8B4 // 2228 + SYS___ULLTOA_A = 0x8B5 // 2229 + SYS_____GETENV_A = 0x8C3 // 2243 + SYS___REXEC_A = 0x8C4 // 2244 + SYS___REXEC_AF_A = 0x8C5 // 2245 + SYS___GETUTXENT_A = 0x8C6 // 2246 + SYS___GETUTXID_A = 0x8C7 // 2247 + SYS___GETUTXLINE_A = 0x8C8 // 2248 + SYS___PUTUTXLINE_A = 0x8C9 // 2249 + SYS_____UTMPXNAME_A = 0x8CA // 2250 + SYS___PUTC_UNLOCKED_A = 0x8CB // 2251 + SYS___PUTCHAR_UNLOCKED_A = 0x8CC // 2252 + SYS___SNPRINTF_A = 0x8CD // 2253 + SYS___VSNPRINTF_A = 0x8CE // 2254 + SYS___DLOPEN_A = 0x8D0 // 2256 + SYS___DLSYM_A = 0x8D1 // 2257 + SYS___DLERROR_A = 0x8D2 // 2258 + SYS_FLOCKFILE = 0x8D3 // 2259 + SYS_FTRYLOCKFILE = 0x8D4 // 2260 + SYS_FUNLOCKFILE = 0x8D5 // 2261 + SYS_GETC_UNLOCKED = 0x8D6 // 2262 + SYS_GETCHAR_UNLOCKED = 0x8D7 // 2263 + SYS_PUTC_UNLOCKED = 0x8D8 // 2264 + SYS_PUTCHAR_UNLOCKED = 0x8D9 // 2265 + SYS_SNPRINTF = 0x8DA // 2266 + SYS_VSNPRINTF = 0x8DB // 2267 + SYS_DLOPEN = 0x8DD // 2269 + SYS_DLSYM = 0x8DE // 2270 + SYS_DLCLOSE = 0x8DF // 2271 + SYS_DLERROR = 0x8E0 // 2272 + SYS___SET_EXCEPTION_HANDLER = 0x8E2 // 2274 + SYS___RESET_EXCEPTION_HANDLER = 0x8E3 // 2275 + SYS___VHM_EVENT = 0x8E4 // 2276 + SYS___ABS_H = 0x8E6 // 2278 + SYS___ABSF_H = 0x8E7 // 2279 + SYS___ABSL_H = 0x8E8 // 2280 + SYS___ACOS_H = 0x8E9 // 2281 + SYS___ACOSF_H = 0x8EA // 2282 + SYS___ACOSL_H = 0x8EB // 2283 + SYS___ACOSH_H = 0x8EC // 2284 + SYS___ASIN_H = 0x8ED // 2285 + SYS___ASINF_H = 0x8EE // 2286 + SYS___ASINL_H = 0x8EF // 2287 + SYS___ASINH_H = 0x8F0 // 2288 + SYS___ATAN_H = 0x8F1 // 2289 + SYS___ATANF_H = 0x8F2 // 2290 + SYS___ATANL_H = 0x8F3 // 2291 + SYS___ATANH_H = 0x8F4 // 2292 + SYS___ATANHF_H = 0x8F5 // 2293 + SYS___ATANHL_H = 0x8F6 // 2294 + SYS___ATAN2_H = 0x8F7 // 2295 + SYS___ATAN2F_H = 0x8F8 // 2296 + SYS___ATAN2L_H = 0x8F9 // 2297 + SYS___CBRT_H = 0x8FA // 2298 + SYS___COPYSIGNF_H = 0x8FB // 2299 + SYS___COPYSIGNL_H = 0x8FC // 2300 + SYS___COS_H = 0x8FD // 2301 + SYS___COSF_H = 0x8FE // 2302 + SYS___COSL_H = 0x8FF // 2303 + SYS___COSHF_H = 0x900 // 2304 + SYS___COSHL_H = 0x901 // 2305 + SYS___COTAN_H = 0x902 // 2306 + SYS___COTANF_H = 0x903 // 2307 + SYS___COTANL_H = 0x904 // 2308 + SYS___ERF_H = 0x905 // 2309 + SYS___ERFF_H = 0x906 // 2310 + SYS___ERFL_H = 0x907 // 2311 + SYS___ERFC_H = 0x908 // 2312 + SYS___ERFCF_H = 0x909 // 2313 + SYS___ERFCL_H = 0x90A // 2314 + SYS___EXP_H = 0x90B // 2315 + SYS___EXPF_H = 0x90C // 2316 + SYS___EXPL_H = 0x90D // 2317 + SYS___EXPM1_H = 0x90E // 2318 + SYS___FDIM_H = 0x90F // 2319 + SYS___FDIMF_H = 0x910 // 2320 + SYS___FDIML_H = 0x911 // 2321 + SYS___FMOD_H = 0x912 // 2322 + SYS___FMODF_H = 0x913 // 2323 + SYS___FMODL_H = 0x914 // 2324 + SYS___GAMMA_H = 0x915 // 2325 + SYS___HYPOT_H = 0x916 // 2326 + SYS___ILOGB_H = 0x917 // 2327 + SYS___LGAMMA_H = 0x918 // 2328 + SYS___LGAMMAF_H = 0x919 // 2329 + SYS___LOG_H = 0x91A // 2330 + SYS___LOGF_H = 0x91B // 2331 + SYS___LOGL_H = 0x91C // 2332 + SYS___LOGB_H = 0x91D // 2333 + SYS___LOG2_H = 0x91E // 2334 + SYS___LOG2F_H = 0x91F // 2335 + SYS___LOG2L_H = 0x920 // 2336 + SYS___LOG1P_H = 0x921 // 2337 + SYS___LOG10_H = 0x922 // 2338 + SYS___LOG10F_H = 0x923 // 2339 + SYS___LOG10L_H = 0x924 // 2340 + SYS___LROUND_H = 0x925 // 2341 + SYS___LROUNDF_H = 0x926 // 2342 + SYS___NEXTAFTER_H = 0x927 // 2343 + SYS___POW_H = 0x928 // 2344 + SYS___POWF_H = 0x929 // 2345 + SYS___POWL_H = 0x92A // 2346 + SYS___REMAINDER_H = 0x92B // 2347 + SYS___RINT_H = 0x92C // 2348 + SYS___SCALB_H = 0x92D // 2349 + SYS___SIN_H = 0x92E // 2350 + SYS___SINF_H = 0x92F // 2351 + SYS___SINL_H = 0x930 // 2352 + SYS___SINH_H = 0x931 // 2353 + SYS___SINHF_H = 0x932 // 2354 + SYS___SINHL_H = 0x933 // 2355 + SYS___SQRT_H = 0x934 // 2356 + SYS___SQRTF_H = 0x935 // 2357 + SYS___SQRTL_H = 0x936 // 2358 + SYS___TAN_H = 0x937 // 2359 + SYS___TANF_H = 0x938 // 2360 + SYS___TANL_H = 0x939 // 2361 + SYS___TANH_H = 0x93A // 2362 + SYS___TANHF_H = 0x93B // 2363 + SYS___TANHL_H = 0x93C // 2364 + SYS___TGAMMA_H = 0x93D // 2365 + SYS___TGAMMAF_H = 0x93E // 2366 + SYS___TRUNC_H = 0x93F // 2367 + SYS___TRUNCF_H = 0x940 // 2368 + SYS___TRUNCL_H = 0x941 // 2369 + SYS___COSH_H = 0x942 // 2370 + SYS___LE_DEBUG_SET_RESUME_MCH = 0x943 // 2371 + SYS_VFSCANF = 0x944 // 2372 + SYS_VSCANF = 0x946 // 2374 + SYS_VSSCANF = 0x948 // 2376 + SYS_VFWSCANF = 0x94A // 2378 + SYS_VWSCANF = 0x94C // 2380 + SYS_VSWSCANF = 0x94E // 2382 + SYS_IMAXABS = 0x950 // 2384 + SYS_IMAXDIV = 0x951 // 2385 + SYS_STRTOIMAX = 0x952 // 2386 + SYS_STRTOUMAX = 0x953 // 2387 + SYS_WCSTOIMAX = 0x954 // 2388 + SYS_WCSTOUMAX = 0x955 // 2389 + SYS_ATOLL = 0x956 // 2390 + SYS_STRTOF = 0x957 // 2391 + SYS_STRTOLD = 0x958 // 2392 + SYS_WCSTOF = 0x959 // 2393 + SYS_WCSTOLD = 0x95A // 2394 + SYS_INET6_RTH_SPACE = 0x95B // 2395 + SYS_INET6_RTH_INIT = 0x95C // 2396 + SYS_INET6_RTH_ADD = 0x95D // 2397 + SYS_INET6_RTH_REVERSE = 0x95E // 2398 + SYS_INET6_RTH_SEGMENTS = 0x95F // 2399 + SYS_INET6_RTH_GETADDR = 0x960 // 2400 + SYS_INET6_OPT_INIT = 0x961 // 2401 + SYS_INET6_OPT_APPEND = 0x962 // 2402 + SYS_INET6_OPT_FINISH = 0x963 // 2403 + SYS_INET6_OPT_SET_VAL = 0x964 // 2404 + SYS_INET6_OPT_NEXT = 0x965 // 2405 + SYS_INET6_OPT_FIND = 0x966 // 2406 + SYS_INET6_OPT_GET_VAL = 0x967 // 2407 + SYS___POW_I = 0x987 // 2439 + SYS___POW_I_B = 0x988 // 2440 + SYS___POW_I_H = 0x989 // 2441 + SYS___POW_II = 0x98A // 2442 + SYS___POW_II_B = 0x98B // 2443 + SYS___POW_II_H = 0x98C // 2444 + SYS_CABS = 0x98E // 2446 + SYS___CABS_B = 0x98F // 2447 + SYS___CABS_H = 0x990 // 2448 + SYS_CABSF = 0x991 // 2449 + SYS___CABSF_B = 0x992 // 2450 + SYS___CABSF_H = 0x993 // 2451 + SYS_CABSL = 0x994 // 2452 + SYS___CABSL_B = 0x995 // 2453 + SYS___CABSL_H = 0x996 // 2454 + SYS_CACOS = 0x997 // 2455 + SYS___CACOS_B = 0x998 // 2456 + SYS___CACOS_H = 0x999 // 2457 + SYS_CACOSF = 0x99A // 2458 + SYS___CACOSF_B = 0x99B // 2459 + SYS___CACOSF_H = 0x99C // 2460 + SYS_CACOSL = 0x99D // 2461 + SYS___CACOSL_B = 0x99E // 2462 + SYS___CACOSL_H = 0x99F // 2463 + SYS_CACOSH = 0x9A0 // 2464 + SYS___CACOSH_B = 0x9A1 // 2465 + SYS___CACOSH_H = 0x9A2 // 2466 + SYS_CACOSHF = 0x9A3 // 2467 + SYS___CACOSHF_B = 0x9A4 // 2468 + SYS___CACOSHF_H = 0x9A5 // 2469 + SYS_CACOSHL = 0x9A6 // 2470 + SYS___CACOSHL_B = 0x9A7 // 2471 + SYS___CACOSHL_H = 0x9A8 // 2472 + SYS_CARG = 0x9A9 // 2473 + SYS___CARG_B = 0x9AA // 2474 + SYS___CARG_H = 0x9AB // 2475 + SYS_CARGF = 0x9AC // 2476 + SYS___CARGF_B = 0x9AD // 2477 + SYS___CARGF_H = 0x9AE // 2478 + SYS_CARGL = 0x9AF // 2479 + SYS___CARGL_B = 0x9B0 // 2480 + SYS___CARGL_H = 0x9B1 // 2481 + SYS_CASIN = 0x9B2 // 2482 + SYS___CASIN_B = 0x9B3 // 2483 + SYS___CASIN_H = 0x9B4 // 2484 + SYS_CASINF = 0x9B5 // 2485 + SYS___CASINF_B = 0x9B6 // 2486 + SYS___CASINF_H = 0x9B7 // 2487 + SYS_CASINL = 0x9B8 // 2488 + SYS___CASINL_B = 0x9B9 // 2489 + SYS___CASINL_H = 0x9BA // 2490 + SYS_CASINH = 0x9BB // 2491 + SYS___CASINH_B = 0x9BC // 2492 + SYS___CASINH_H = 0x9BD // 2493 + SYS_CASINHF = 0x9BE // 2494 + SYS___CASINHF_B = 0x9BF // 2495 + SYS___CASINHF_H = 0x9C0 // 2496 + SYS_CASINHL = 0x9C1 // 2497 + SYS___CASINHL_B = 0x9C2 // 2498 + SYS___CASINHL_H = 0x9C3 // 2499 + SYS_CATAN = 0x9C4 // 2500 + SYS___CATAN_B = 0x9C5 // 2501 + SYS___CATAN_H = 0x9C6 // 2502 + SYS_CATANF = 0x9C7 // 2503 + SYS___CATANF_B = 0x9C8 // 2504 + SYS___CATANF_H = 0x9C9 // 2505 + SYS_CATANL = 0x9CA // 2506 + SYS___CATANL_B = 0x9CB // 2507 + SYS___CATANL_H = 0x9CC // 2508 + SYS_CATANH = 0x9CD // 2509 + SYS___CATANH_B = 0x9CE // 2510 + SYS___CATANH_H = 0x9CF // 2511 + SYS_CATANHF = 0x9D0 // 2512 + SYS___CATANHF_B = 0x9D1 // 2513 + SYS___CATANHF_H = 0x9D2 // 2514 + SYS_CATANHL = 0x9D3 // 2515 + SYS___CATANHL_B = 0x9D4 // 2516 + SYS___CATANHL_H = 0x9D5 // 2517 + SYS_CCOS = 0x9D6 // 2518 + SYS___CCOS_B = 0x9D7 // 2519 + SYS___CCOS_H = 0x9D8 // 2520 + SYS_CCOSF = 0x9D9 // 2521 + SYS___CCOSF_B = 0x9DA // 2522 + SYS___CCOSF_H = 0x9DB // 2523 + SYS_CCOSL = 0x9DC // 2524 + SYS___CCOSL_B = 0x9DD // 2525 + SYS___CCOSL_H = 0x9DE // 2526 + SYS_CCOSH = 0x9DF // 2527 + SYS___CCOSH_B = 0x9E0 // 2528 + SYS___CCOSH_H = 0x9E1 // 2529 + SYS_CCOSHF = 0x9E2 // 2530 + SYS___CCOSHF_B = 0x9E3 // 2531 + SYS___CCOSHF_H = 0x9E4 // 2532 + SYS_CCOSHL = 0x9E5 // 2533 + SYS___CCOSHL_B = 0x9E6 // 2534 + SYS___CCOSHL_H = 0x9E7 // 2535 + SYS_CEXP = 0x9E8 // 2536 + SYS___CEXP_B = 0x9E9 // 2537 + SYS___CEXP_H = 0x9EA // 2538 + SYS_CEXPF = 0x9EB // 2539 + SYS___CEXPF_B = 0x9EC // 2540 + SYS___CEXPF_H = 0x9ED // 2541 + SYS_CEXPL = 0x9EE // 2542 + SYS___CEXPL_B = 0x9EF // 2543 + SYS___CEXPL_H = 0x9F0 // 2544 + SYS_CIMAG = 0x9F1 // 2545 + SYS___CIMAG_B = 0x9F2 // 2546 + SYS___CIMAG_H = 0x9F3 // 2547 + SYS_CIMAGF = 0x9F4 // 2548 + SYS___CIMAGF_B = 0x9F5 // 2549 + SYS___CIMAGF_H = 0x9F6 // 2550 + SYS_CIMAGL = 0x9F7 // 2551 + SYS___CIMAGL_B = 0x9F8 // 2552 + SYS___CIMAGL_H = 0x9F9 // 2553 + SYS___CLOG = 0x9FA // 2554 + SYS___CLOG_B = 0x9FB // 2555 + SYS___CLOG_H = 0x9FC // 2556 + SYS_CLOGF = 0x9FD // 2557 + SYS___CLOGF_B = 0x9FE // 2558 + SYS___CLOGF_H = 0x9FF // 2559 + SYS_CLOGL = 0xA00 // 2560 + SYS___CLOGL_B = 0xA01 // 2561 + SYS___CLOGL_H = 0xA02 // 2562 + SYS_CONJ = 0xA03 // 2563 + SYS___CONJ_B = 0xA04 // 2564 + SYS___CONJ_H = 0xA05 // 2565 + SYS_CONJF = 0xA06 // 2566 + SYS___CONJF_B = 0xA07 // 2567 + SYS___CONJF_H = 0xA08 // 2568 + SYS_CONJL = 0xA09 // 2569 + SYS___CONJL_B = 0xA0A // 2570 + SYS___CONJL_H = 0xA0B // 2571 + SYS_CPOW = 0xA0C // 2572 + SYS___CPOW_B = 0xA0D // 2573 + SYS___CPOW_H = 0xA0E // 2574 + SYS_CPOWF = 0xA0F // 2575 + SYS___CPOWF_B = 0xA10 // 2576 + SYS___CPOWF_H = 0xA11 // 2577 + SYS_CPOWL = 0xA12 // 2578 + SYS___CPOWL_B = 0xA13 // 2579 + SYS___CPOWL_H = 0xA14 // 2580 + SYS_CPROJ = 0xA15 // 2581 + SYS___CPROJ_B = 0xA16 // 2582 + SYS___CPROJ_H = 0xA17 // 2583 + SYS_CPROJF = 0xA18 // 2584 + SYS___CPROJF_B = 0xA19 // 2585 + SYS___CPROJF_H = 0xA1A // 2586 + SYS_CPROJL = 0xA1B // 2587 + SYS___CPROJL_B = 0xA1C // 2588 + SYS___CPROJL_H = 0xA1D // 2589 + SYS_CREAL = 0xA1E // 2590 + SYS___CREAL_B = 0xA1F // 2591 + SYS___CREAL_H = 0xA20 // 2592 + SYS_CREALF = 0xA21 // 2593 + SYS___CREALF_B = 0xA22 // 2594 + SYS___CREALF_H = 0xA23 // 2595 + SYS_CREALL = 0xA24 // 2596 + SYS___CREALL_B = 0xA25 // 2597 + SYS___CREALL_H = 0xA26 // 2598 + SYS_CSIN = 0xA27 // 2599 + SYS___CSIN_B = 0xA28 // 2600 + SYS___CSIN_H = 0xA29 // 2601 + SYS_CSINF = 0xA2A // 2602 + SYS___CSINF_B = 0xA2B // 2603 + SYS___CSINF_H = 0xA2C // 2604 + SYS_CSINL = 0xA2D // 2605 + SYS___CSINL_B = 0xA2E // 2606 + SYS___CSINL_H = 0xA2F // 2607 + SYS_CSINH = 0xA30 // 2608 + SYS___CSINH_B = 0xA31 // 2609 + SYS___CSINH_H = 0xA32 // 2610 + SYS_CSINHF = 0xA33 // 2611 + SYS___CSINHF_B = 0xA34 // 2612 + SYS___CSINHF_H = 0xA35 // 2613 + SYS_CSINHL = 0xA36 // 2614 + SYS___CSINHL_B = 0xA37 // 2615 + SYS___CSINHL_H = 0xA38 // 2616 + SYS_CSQRT = 0xA39 // 2617 + SYS___CSQRT_B = 0xA3A // 2618 + SYS___CSQRT_H = 0xA3B // 2619 + SYS_CSQRTF = 0xA3C // 2620 + SYS___CSQRTF_B = 0xA3D // 2621 + SYS___CSQRTF_H = 0xA3E // 2622 + SYS_CSQRTL = 0xA3F // 2623 + SYS___CSQRTL_B = 0xA40 // 2624 + SYS___CSQRTL_H = 0xA41 // 2625 + SYS_CTAN = 0xA42 // 2626 + SYS___CTAN_B = 0xA43 // 2627 + SYS___CTAN_H = 0xA44 // 2628 + SYS_CTANF = 0xA45 // 2629 + SYS___CTANF_B = 0xA46 // 2630 + SYS___CTANF_H = 0xA47 // 2631 + SYS_CTANL = 0xA48 // 2632 + SYS___CTANL_B = 0xA49 // 2633 + SYS___CTANL_H = 0xA4A // 2634 + SYS_CTANH = 0xA4B // 2635 + SYS___CTANH_B = 0xA4C // 2636 + SYS___CTANH_H = 0xA4D // 2637 + SYS_CTANHF = 0xA4E // 2638 + SYS___CTANHF_B = 0xA4F // 2639 + SYS___CTANHF_H = 0xA50 // 2640 + SYS_CTANHL = 0xA51 // 2641 + SYS___CTANHL_B = 0xA52 // 2642 + SYS___CTANHL_H = 0xA53 // 2643 + SYS___ACOSHF_H = 0xA54 // 2644 + SYS___ACOSHL_H = 0xA55 // 2645 + SYS___ASINHF_H = 0xA56 // 2646 + SYS___ASINHL_H = 0xA57 // 2647 + SYS___CBRTF_H = 0xA58 // 2648 + SYS___CBRTL_H = 0xA59 // 2649 + SYS___COPYSIGN_B = 0xA5A // 2650 + SYS___EXPM1F_H = 0xA5B // 2651 + SYS___EXPM1L_H = 0xA5C // 2652 + SYS___EXP2_H = 0xA5D // 2653 + SYS___EXP2F_H = 0xA5E // 2654 + SYS___EXP2L_H = 0xA5F // 2655 + SYS___LOG1PF_H = 0xA60 // 2656 + SYS___LOG1PL_H = 0xA61 // 2657 + SYS___LGAMMAL_H = 0xA62 // 2658 + SYS_FMA = 0xA63 // 2659 + SYS___FMA_B = 0xA64 // 2660 + SYS___FMA_H = 0xA65 // 2661 + SYS_FMAF = 0xA66 // 2662 + SYS___FMAF_B = 0xA67 // 2663 + SYS___FMAF_H = 0xA68 // 2664 + SYS_FMAL = 0xA69 // 2665 + SYS___FMAL_B = 0xA6A // 2666 + SYS___FMAL_H = 0xA6B // 2667 + SYS_FMAX = 0xA6C // 2668 + SYS___FMAX_B = 0xA6D // 2669 + SYS___FMAX_H = 0xA6E // 2670 + SYS_FMAXF = 0xA6F // 2671 + SYS___FMAXF_B = 0xA70 // 2672 + SYS___FMAXF_H = 0xA71 // 2673 + SYS_FMAXL = 0xA72 // 2674 + SYS___FMAXL_B = 0xA73 // 2675 + SYS___FMAXL_H = 0xA74 // 2676 + SYS_FMIN = 0xA75 // 2677 + SYS___FMIN_B = 0xA76 // 2678 + SYS___FMIN_H = 0xA77 // 2679 + SYS_FMINF = 0xA78 // 2680 + SYS___FMINF_B = 0xA79 // 2681 + SYS___FMINF_H = 0xA7A // 2682 + SYS_FMINL = 0xA7B // 2683 + SYS___FMINL_B = 0xA7C // 2684 + SYS___FMINL_H = 0xA7D // 2685 + SYS_ILOGBF = 0xA7E // 2686 + SYS___ILOGBF_B = 0xA7F // 2687 + SYS___ILOGBF_H = 0xA80 // 2688 + SYS_ILOGBL = 0xA81 // 2689 + SYS___ILOGBL_B = 0xA82 // 2690 + SYS___ILOGBL_H = 0xA83 // 2691 + SYS_LLRINT = 0xA84 // 2692 + SYS___LLRINT_B = 0xA85 // 2693 + SYS___LLRINT_H = 0xA86 // 2694 + SYS_LLRINTF = 0xA87 // 2695 + SYS___LLRINTF_B = 0xA88 // 2696 + SYS___LLRINTF_H = 0xA89 // 2697 + SYS_LLRINTL = 0xA8A // 2698 + SYS___LLRINTL_B = 0xA8B // 2699 + SYS___LLRINTL_H = 0xA8C // 2700 + SYS_LLROUND = 0xA8D // 2701 + SYS___LLROUND_B = 0xA8E // 2702 + SYS___LLROUND_H = 0xA8F // 2703 + SYS_LLROUNDF = 0xA90 // 2704 + SYS___LLROUNDF_B = 0xA91 // 2705 + SYS___LLROUNDF_H = 0xA92 // 2706 + SYS_LLROUNDL = 0xA93 // 2707 + SYS___LLROUNDL_B = 0xA94 // 2708 + SYS___LLROUNDL_H = 0xA95 // 2709 + SYS_LOGBF = 0xA96 // 2710 + SYS___LOGBF_B = 0xA97 // 2711 + SYS___LOGBF_H = 0xA98 // 2712 + SYS_LOGBL = 0xA99 // 2713 + SYS___LOGBL_B = 0xA9A // 2714 + SYS___LOGBL_H = 0xA9B // 2715 + SYS_LRINT = 0xA9C // 2716 + SYS___LRINT_B = 0xA9D // 2717 + SYS___LRINT_H = 0xA9E // 2718 + SYS_LRINTF = 0xA9F // 2719 + SYS___LRINTF_B = 0xAA0 // 2720 + SYS___LRINTF_H = 0xAA1 // 2721 + SYS_LRINTL = 0xAA2 // 2722 + SYS___LRINTL_B = 0xAA3 // 2723 + SYS___LRINTL_H = 0xAA4 // 2724 + SYS_LROUNDL = 0xAA5 // 2725 + SYS___LROUNDL_B = 0xAA6 // 2726 + SYS___LROUNDL_H = 0xAA7 // 2727 + SYS_NAN = 0xAA8 // 2728 + SYS___NAN_B = 0xAA9 // 2729 + SYS_NANF = 0xAAA // 2730 + SYS___NANF_B = 0xAAB // 2731 + SYS_NANL = 0xAAC // 2732 + SYS___NANL_B = 0xAAD // 2733 + SYS_NEARBYINT = 0xAAE // 2734 + SYS___NEARBYINT_B = 0xAAF // 2735 + SYS___NEARBYINT_H = 0xAB0 // 2736 + SYS_NEARBYINTF = 0xAB1 // 2737 + SYS___NEARBYINTF_B = 0xAB2 // 2738 + SYS___NEARBYINTF_H = 0xAB3 // 2739 + SYS_NEARBYINTL = 0xAB4 // 2740 + SYS___NEARBYINTL_B = 0xAB5 // 2741 + SYS___NEARBYINTL_H = 0xAB6 // 2742 + SYS_NEXTAFTERF = 0xAB7 // 2743 + SYS___NEXTAFTERF_B = 0xAB8 // 2744 + SYS___NEXTAFTERF_H = 0xAB9 // 2745 + SYS_NEXTAFTERL = 0xABA // 2746 + SYS___NEXTAFTERL_B = 0xABB // 2747 + SYS___NEXTAFTERL_H = 0xABC // 2748 + SYS_NEXTTOWARD = 0xABD // 2749 + SYS___NEXTTOWARD_B = 0xABE // 2750 + SYS___NEXTTOWARD_H = 0xABF // 2751 + SYS_NEXTTOWARDF = 0xAC0 // 2752 + SYS___NEXTTOWARDF_B = 0xAC1 // 2753 + SYS___NEXTTOWARDF_H = 0xAC2 // 2754 + SYS_NEXTTOWARDL = 0xAC3 // 2755 + SYS___NEXTTOWARDL_B = 0xAC4 // 2756 + SYS___NEXTTOWARDL_H = 0xAC5 // 2757 + SYS___REMAINDERF_H = 0xAC6 // 2758 + SYS___REMAINDERL_H = 0xAC7 // 2759 + SYS___REMQUO_H = 0xAC8 // 2760 + SYS___REMQUOF_H = 0xAC9 // 2761 + SYS___REMQUOL_H = 0xACA // 2762 + SYS_RINTF = 0xACB // 2763 + SYS___RINTF_B = 0xACC // 2764 + SYS_RINTL = 0xACD // 2765 + SYS___RINTL_B = 0xACE // 2766 + SYS_ROUND = 0xACF // 2767 + SYS___ROUND_B = 0xAD0 // 2768 + SYS___ROUND_H = 0xAD1 // 2769 + SYS_ROUNDF = 0xAD2 // 2770 + SYS___ROUNDF_B = 0xAD3 // 2771 + SYS___ROUNDF_H = 0xAD4 // 2772 + SYS_ROUNDL = 0xAD5 // 2773 + SYS___ROUNDL_B = 0xAD6 // 2774 + SYS___ROUNDL_H = 0xAD7 // 2775 + SYS_SCALBLN = 0xAD8 // 2776 + SYS___SCALBLN_B = 0xAD9 // 2777 + SYS___SCALBLN_H = 0xADA // 2778 + SYS_SCALBLNF = 0xADB // 2779 + SYS___SCALBLNF_B = 0xADC // 2780 + SYS___SCALBLNF_H = 0xADD // 2781 + SYS_SCALBLNL = 0xADE // 2782 + SYS___SCALBLNL_B = 0xADF // 2783 + SYS___SCALBLNL_H = 0xAE0 // 2784 + SYS___SCALBN_B = 0xAE1 // 2785 + SYS___SCALBN_H = 0xAE2 // 2786 + SYS_SCALBNF = 0xAE3 // 2787 + SYS___SCALBNF_B = 0xAE4 // 2788 + SYS___SCALBNF_H = 0xAE5 // 2789 + SYS_SCALBNL = 0xAE6 // 2790 + SYS___SCALBNL_B = 0xAE7 // 2791 + SYS___SCALBNL_H = 0xAE8 // 2792 + SYS___TGAMMAL_H = 0xAE9 // 2793 + SYS_FECLEAREXCEPT = 0xAEA // 2794 + SYS_FEGETENV = 0xAEB // 2795 + SYS_FEGETEXCEPTFLAG = 0xAEC // 2796 + SYS_FEGETROUND = 0xAED // 2797 + SYS_FEHOLDEXCEPT = 0xAEE // 2798 + SYS_FERAISEEXCEPT = 0xAEF // 2799 + SYS_FESETENV = 0xAF0 // 2800 + SYS_FESETEXCEPTFLAG = 0xAF1 // 2801 + SYS_FESETROUND = 0xAF2 // 2802 + SYS_FETESTEXCEPT = 0xAF3 // 2803 + SYS_FEUPDATEENV = 0xAF4 // 2804 + SYS___COPYSIGN_H = 0xAF5 // 2805 + SYS___HYPOTF_H = 0xAF6 // 2806 + SYS___HYPOTL_H = 0xAF7 // 2807 + SYS___CLASS = 0xAFA // 2810 + SYS___CLASS_B = 0xAFB // 2811 + SYS___CLASS_H = 0xAFC // 2812 + SYS___ISBLANK_A = 0xB2E // 2862 + SYS___ISWBLANK_A = 0xB2F // 2863 + SYS___LROUND_FIXUP = 0xB30 // 2864 + SYS___LROUNDF_FIXUP = 0xB31 // 2865 + SYS_SCHED_YIELD = 0xB32 // 2866 + SYS_STRERROR_R = 0xB33 // 2867 + SYS_UNSETENV = 0xB34 // 2868 + SYS___LGAMMA_H_C99 = 0xB38 // 2872 + SYS___LGAMMA_B_C99 = 0xB39 // 2873 + SYS___LGAMMA_R_C99 = 0xB3A // 2874 + SYS___FTELL2 = 0xB3B // 2875 + SYS___FSEEK2 = 0xB3C // 2876 + SYS___STATIC_REINIT = 0xB3D // 2877 + SYS_PTHREAD_ATTR_GETSTACK = 0xB3E // 2878 + SYS_PTHREAD_ATTR_SETSTACK = 0xB3F // 2879 + SYS___TGAMMA_H_C99 = 0xB78 // 2936 + SYS___TGAMMAF_H_C99 = 0xB79 // 2937 + SYS___LE_TRACEBACK = 0xB7A // 2938 + SYS___MUST_STAY_CLEAN = 0xB7C // 2940 + SYS___O_ENV = 0xB7D // 2941 + SYS_ACOSD32 = 0xB7E // 2942 + SYS_ACOSD64 = 0xB7F // 2943 + SYS_ACOSD128 = 0xB80 // 2944 + SYS_ACOSHD32 = 0xB81 // 2945 + SYS_ACOSHD64 = 0xB82 // 2946 + SYS_ACOSHD128 = 0xB83 // 2947 + SYS_ASIND32 = 0xB84 // 2948 + SYS_ASIND64 = 0xB85 // 2949 + SYS_ASIND128 = 0xB86 // 2950 + SYS_ASINHD32 = 0xB87 // 2951 + SYS_ASINHD64 = 0xB88 // 2952 + SYS_ASINHD128 = 0xB89 // 2953 + SYS_ATAND32 = 0xB8A // 2954 + SYS_ATAND64 = 0xB8B // 2955 + SYS_ATAND128 = 0xB8C // 2956 + SYS_ATAN2D32 = 0xB8D // 2957 + SYS_ATAN2D64 = 0xB8E // 2958 + SYS_ATAN2D128 = 0xB8F // 2959 + SYS_ATANHD32 = 0xB90 // 2960 + SYS_ATANHD64 = 0xB91 // 2961 + SYS_ATANHD128 = 0xB92 // 2962 + SYS_CBRTD32 = 0xB93 // 2963 + SYS_CBRTD64 = 0xB94 // 2964 + SYS_CBRTD128 = 0xB95 // 2965 + SYS_CEILD32 = 0xB96 // 2966 + SYS_CEILD64 = 0xB97 // 2967 + SYS_CEILD128 = 0xB98 // 2968 + SYS___CLASS2 = 0xB99 // 2969 + SYS___CLASS2_B = 0xB9A // 2970 + SYS___CLASS2_H = 0xB9B // 2971 + SYS_COPYSIGND32 = 0xB9C // 2972 + SYS_COPYSIGND64 = 0xB9D // 2973 + SYS_COPYSIGND128 = 0xB9E // 2974 + SYS_COSD32 = 0xB9F // 2975 + SYS_COSD64 = 0xBA0 // 2976 + SYS_COSD128 = 0xBA1 // 2977 + SYS_COSHD32 = 0xBA2 // 2978 + SYS_COSHD64 = 0xBA3 // 2979 + SYS_COSHD128 = 0xBA4 // 2980 + SYS_ERFD32 = 0xBA5 // 2981 + SYS_ERFD64 = 0xBA6 // 2982 + SYS_ERFD128 = 0xBA7 // 2983 + SYS_ERFCD32 = 0xBA8 // 2984 + SYS_ERFCD64 = 0xBA9 // 2985 + SYS_ERFCD128 = 0xBAA // 2986 + SYS_EXPD32 = 0xBAB // 2987 + SYS_EXPD64 = 0xBAC // 2988 + SYS_EXPD128 = 0xBAD // 2989 + SYS_EXP2D32 = 0xBAE // 2990 + SYS_EXP2D64 = 0xBAF // 2991 + SYS_EXP2D128 = 0xBB0 // 2992 + SYS_EXPM1D32 = 0xBB1 // 2993 + SYS_EXPM1D64 = 0xBB2 // 2994 + SYS_EXPM1D128 = 0xBB3 // 2995 + SYS_FABSD32 = 0xBB4 // 2996 + SYS_FABSD64 = 0xBB5 // 2997 + SYS_FABSD128 = 0xBB6 // 2998 + SYS_FDIMD32 = 0xBB7 // 2999 + SYS_FDIMD64 = 0xBB8 // 3000 + SYS_FDIMD128 = 0xBB9 // 3001 + SYS_FE_DEC_GETROUND = 0xBBA // 3002 + SYS_FE_DEC_SETROUND = 0xBBB // 3003 + SYS_FLOORD32 = 0xBBC // 3004 + SYS_FLOORD64 = 0xBBD // 3005 + SYS_FLOORD128 = 0xBBE // 3006 + SYS_FMAD32 = 0xBBF // 3007 + SYS_FMAD64 = 0xBC0 // 3008 + SYS_FMAD128 = 0xBC1 // 3009 + SYS_FMAXD32 = 0xBC2 // 3010 + SYS_FMAXD64 = 0xBC3 // 3011 + SYS_FMAXD128 = 0xBC4 // 3012 + SYS_FMIND32 = 0xBC5 // 3013 + SYS_FMIND64 = 0xBC6 // 3014 + SYS_FMIND128 = 0xBC7 // 3015 + SYS_FMODD32 = 0xBC8 // 3016 + SYS_FMODD64 = 0xBC9 // 3017 + SYS_FMODD128 = 0xBCA // 3018 + SYS___FP_CAST_D = 0xBCB // 3019 + SYS_FREXPD32 = 0xBCC // 3020 + SYS_FREXPD64 = 0xBCD // 3021 + SYS_FREXPD128 = 0xBCE // 3022 + SYS_HYPOTD32 = 0xBCF // 3023 + SYS_HYPOTD64 = 0xBD0 // 3024 + SYS_HYPOTD128 = 0xBD1 // 3025 + SYS_ILOGBD32 = 0xBD2 // 3026 + SYS_ILOGBD64 = 0xBD3 // 3027 + SYS_ILOGBD128 = 0xBD4 // 3028 + SYS_LDEXPD32 = 0xBD5 // 3029 + SYS_LDEXPD64 = 0xBD6 // 3030 + SYS_LDEXPD128 = 0xBD7 // 3031 + SYS_LGAMMAD32 = 0xBD8 // 3032 + SYS_LGAMMAD64 = 0xBD9 // 3033 + SYS_LGAMMAD128 = 0xBDA // 3034 + SYS_LLRINTD32 = 0xBDB // 3035 + SYS_LLRINTD64 = 0xBDC // 3036 + SYS_LLRINTD128 = 0xBDD // 3037 + SYS_LLROUNDD32 = 0xBDE // 3038 + SYS_LLROUNDD64 = 0xBDF // 3039 + SYS_LLROUNDD128 = 0xBE0 // 3040 + SYS_LOGD32 = 0xBE1 // 3041 + SYS_LOGD64 = 0xBE2 // 3042 + SYS_LOGD128 = 0xBE3 // 3043 + SYS_LOG10D32 = 0xBE4 // 3044 + SYS_LOG10D64 = 0xBE5 // 3045 + SYS_LOG10D128 = 0xBE6 // 3046 + SYS_LOG1PD32 = 0xBE7 // 3047 + SYS_LOG1PD64 = 0xBE8 // 3048 + SYS_LOG1PD128 = 0xBE9 // 3049 + SYS_LOG2D32 = 0xBEA // 3050 + SYS_LOG2D64 = 0xBEB // 3051 + SYS_LOG2D128 = 0xBEC // 3052 + SYS_LOGBD32 = 0xBED // 3053 + SYS_LOGBD64 = 0xBEE // 3054 + SYS_LOGBD128 = 0xBEF // 3055 + SYS_LRINTD32 = 0xBF0 // 3056 + SYS_LRINTD64 = 0xBF1 // 3057 + SYS_LRINTD128 = 0xBF2 // 3058 + SYS_LROUNDD32 = 0xBF3 // 3059 + SYS_LROUNDD64 = 0xBF4 // 3060 + SYS_LROUNDD128 = 0xBF5 // 3061 + SYS_MODFD32 = 0xBF6 // 3062 + SYS_MODFD64 = 0xBF7 // 3063 + SYS_MODFD128 = 0xBF8 // 3064 + SYS_NAND32 = 0xBF9 // 3065 + SYS_NAND64 = 0xBFA // 3066 + SYS_NAND128 = 0xBFB // 3067 + SYS_NEARBYINTD32 = 0xBFC // 3068 + SYS_NEARBYINTD64 = 0xBFD // 3069 + SYS_NEARBYINTD128 = 0xBFE // 3070 + SYS_NEXTAFTERD32 = 0xBFF // 3071 + SYS_NEXTAFTERD64 = 0xC00 // 3072 + SYS_NEXTAFTERD128 = 0xC01 // 3073 + SYS_NEXTTOWARDD32 = 0xC02 // 3074 + SYS_NEXTTOWARDD64 = 0xC03 // 3075 + SYS_NEXTTOWARDD128 = 0xC04 // 3076 + SYS_POWD32 = 0xC05 // 3077 + SYS_POWD64 = 0xC06 // 3078 + SYS_POWD128 = 0xC07 // 3079 + SYS_QUANTIZED32 = 0xC08 // 3080 + SYS_QUANTIZED64 = 0xC09 // 3081 + SYS_QUANTIZED128 = 0xC0A // 3082 + SYS_REMAINDERD32 = 0xC0B // 3083 + SYS_REMAINDERD64 = 0xC0C // 3084 + SYS_REMAINDERD128 = 0xC0D // 3085 + SYS___REMQUOD32 = 0xC0E // 3086 + SYS___REMQUOD64 = 0xC0F // 3087 + SYS___REMQUOD128 = 0xC10 // 3088 + SYS_RINTD32 = 0xC11 // 3089 + SYS_RINTD64 = 0xC12 // 3090 + SYS_RINTD128 = 0xC13 // 3091 + SYS_ROUNDD32 = 0xC14 // 3092 + SYS_ROUNDD64 = 0xC15 // 3093 + SYS_ROUNDD128 = 0xC16 // 3094 + SYS_SAMEQUANTUMD32 = 0xC17 // 3095 + SYS_SAMEQUANTUMD64 = 0xC18 // 3096 + SYS_SAMEQUANTUMD128 = 0xC19 // 3097 + SYS_SCALBLND32 = 0xC1A // 3098 + SYS_SCALBLND64 = 0xC1B // 3099 + SYS_SCALBLND128 = 0xC1C // 3100 + SYS_SCALBND32 = 0xC1D // 3101 + SYS_SCALBND64 = 0xC1E // 3102 + SYS_SCALBND128 = 0xC1F // 3103 + SYS_SIND32 = 0xC20 // 3104 + SYS_SIND64 = 0xC21 // 3105 + SYS_SIND128 = 0xC22 // 3106 + SYS_SINHD32 = 0xC23 // 3107 + SYS_SINHD64 = 0xC24 // 3108 + SYS_SINHD128 = 0xC25 // 3109 + SYS_SQRTD32 = 0xC26 // 3110 + SYS_SQRTD64 = 0xC27 // 3111 + SYS_SQRTD128 = 0xC28 // 3112 + SYS_STRTOD32 = 0xC29 // 3113 + SYS_STRTOD64 = 0xC2A // 3114 + SYS_STRTOD128 = 0xC2B // 3115 + SYS_TAND32 = 0xC2C // 3116 + SYS_TAND64 = 0xC2D // 3117 + SYS_TAND128 = 0xC2E // 3118 + SYS_TANHD32 = 0xC2F // 3119 + SYS_TANHD64 = 0xC30 // 3120 + SYS_TANHD128 = 0xC31 // 3121 + SYS_TGAMMAD32 = 0xC32 // 3122 + SYS_TGAMMAD64 = 0xC33 // 3123 + SYS_TGAMMAD128 = 0xC34 // 3124 + SYS_TRUNCD32 = 0xC3E // 3134 + SYS_TRUNCD64 = 0xC3F // 3135 + SYS_TRUNCD128 = 0xC40 // 3136 + SYS_WCSTOD32 = 0xC41 // 3137 + SYS_WCSTOD64 = 0xC42 // 3138 + SYS_WCSTOD128 = 0xC43 // 3139 + SYS___CODEPAGE_INFO = 0xC64 // 3172 + SYS_POSIX_OPENPT = 0xC66 // 3174 + SYS_PSELECT = 0xC67 // 3175 + SYS_SOCKATMARK = 0xC68 // 3176 + SYS_AIO_FSYNC = 0xC69 // 3177 + SYS_LIO_LISTIO = 0xC6A // 3178 + SYS___ATANPID32 = 0xC6B // 3179 + SYS___ATANPID64 = 0xC6C // 3180 + SYS___ATANPID128 = 0xC6D // 3181 + SYS___COSPID32 = 0xC6E // 3182 + SYS___COSPID64 = 0xC6F // 3183 + SYS___COSPID128 = 0xC70 // 3184 + SYS___SINPID32 = 0xC71 // 3185 + SYS___SINPID64 = 0xC72 // 3186 + SYS___SINPID128 = 0xC73 // 3187 + SYS_SETIPV4SOURCEFILTER = 0xC76 // 3190 + SYS_GETIPV4SOURCEFILTER = 0xC77 // 3191 + SYS_SETSOURCEFILTER = 0xC78 // 3192 + SYS_GETSOURCEFILTER = 0xC79 // 3193 + SYS_FWRITE_UNLOCKED = 0xC7A // 3194 + SYS_FREAD_UNLOCKED = 0xC7B // 3195 + SYS_FGETS_UNLOCKED = 0xC7C // 3196 + SYS_GETS_UNLOCKED = 0xC7D // 3197 + SYS_FPUTS_UNLOCKED = 0xC7E // 3198 + SYS_PUTS_UNLOCKED = 0xC7F // 3199 + SYS_FGETC_UNLOCKED = 0xC80 // 3200 + SYS_FPUTC_UNLOCKED = 0xC81 // 3201 + SYS_DLADDR = 0xC82 // 3202 + SYS_SHM_OPEN = 0xC8C // 3212 + SYS_SHM_UNLINK = 0xC8D // 3213 + SYS___CLASS2F = 0xC91 // 3217 + SYS___CLASS2L = 0xC92 // 3218 + SYS___CLASS2F_B = 0xC93 // 3219 + SYS___CLASS2F_H = 0xC94 // 3220 + SYS___CLASS2L_B = 0xC95 // 3221 + SYS___CLASS2L_H = 0xC96 // 3222 + SYS___CLASS2D32 = 0xC97 // 3223 + SYS___CLASS2D64 = 0xC98 // 3224 + SYS___CLASS2D128 = 0xC99 // 3225 + SYS___TOCSNAME2 = 0xC9A // 3226 + SYS___D1TOP = 0xC9B // 3227 + SYS___D2TOP = 0xC9C // 3228 + SYS___D4TOP = 0xC9D // 3229 + SYS___PTOD1 = 0xC9E // 3230 + SYS___PTOD2 = 0xC9F // 3231 + SYS___PTOD4 = 0xCA0 // 3232 + SYS_CLEARERR_UNLOCKED = 0xCA1 // 3233 + SYS_FDELREC_UNLOCKED = 0xCA2 // 3234 + SYS_FEOF_UNLOCKED = 0xCA3 // 3235 + SYS_FERROR_UNLOCKED = 0xCA4 // 3236 + SYS_FFLUSH_UNLOCKED = 0xCA5 // 3237 + SYS_FGETPOS_UNLOCKED = 0xCA6 // 3238 + SYS_FGETWC_UNLOCKED = 0xCA7 // 3239 + SYS_FGETWS_UNLOCKED = 0xCA8 // 3240 + SYS_FILENO_UNLOCKED = 0xCA9 // 3241 + SYS_FLDATA_UNLOCKED = 0xCAA // 3242 + SYS_FLOCATE_UNLOCKED = 0xCAB // 3243 + SYS_FPRINTF_UNLOCKED = 0xCAC // 3244 + SYS_FPUTWC_UNLOCKED = 0xCAD // 3245 + SYS_FPUTWS_UNLOCKED = 0xCAE // 3246 + SYS_FSCANF_UNLOCKED = 0xCAF // 3247 + SYS_FSEEK_UNLOCKED = 0xCB0 // 3248 + SYS_FSEEKO_UNLOCKED = 0xCB1 // 3249 + SYS_FSETPOS_UNLOCKED = 0xCB3 // 3251 + SYS_FTELL_UNLOCKED = 0xCB4 // 3252 + SYS_FTELLO_UNLOCKED = 0xCB5 // 3253 + SYS_FUPDATE_UNLOCKED = 0xCB7 // 3255 + SYS_FWIDE_UNLOCKED = 0xCB8 // 3256 + SYS_FWPRINTF_UNLOCKED = 0xCB9 // 3257 + SYS_FWSCANF_UNLOCKED = 0xCBA // 3258 + SYS_GETWC_UNLOCKED = 0xCBB // 3259 + SYS_GETWCHAR_UNLOCKED = 0xCBC // 3260 + SYS_PERROR_UNLOCKED = 0xCBD // 3261 + SYS_PRINTF_UNLOCKED = 0xCBE // 3262 + SYS_PUTWC_UNLOCKED = 0xCBF // 3263 + SYS_PUTWCHAR_UNLOCKED = 0xCC0 // 3264 + SYS_REWIND_UNLOCKED = 0xCC1 // 3265 + SYS_SCANF_UNLOCKED = 0xCC2 // 3266 + SYS_UNGETC_UNLOCKED = 0xCC3 // 3267 + SYS_UNGETWC_UNLOCKED = 0xCC4 // 3268 + SYS_VFPRINTF_UNLOCKED = 0xCC5 // 3269 + SYS_VFSCANF_UNLOCKED = 0xCC7 // 3271 + SYS_VFWPRINTF_UNLOCKED = 0xCC9 // 3273 + SYS_VFWSCANF_UNLOCKED = 0xCCB // 3275 + SYS_VPRINTF_UNLOCKED = 0xCCD // 3277 + SYS_VSCANF_UNLOCKED = 0xCCF // 3279 + SYS_VWPRINTF_UNLOCKED = 0xCD1 // 3281 + SYS_VWSCANF_UNLOCKED = 0xCD3 // 3283 + SYS_WPRINTF_UNLOCKED = 0xCD5 // 3285 + SYS_WSCANF_UNLOCKED = 0xCD6 // 3286 + SYS_ASCTIME64 = 0xCD7 // 3287 + SYS_ASCTIME64_R = 0xCD8 // 3288 + SYS_CTIME64 = 0xCD9 // 3289 + SYS_CTIME64_R = 0xCDA // 3290 + SYS_DIFFTIME64 = 0xCDB // 3291 + SYS_GMTIME64 = 0xCDC // 3292 + SYS_GMTIME64_R = 0xCDD // 3293 + SYS_LOCALTIME64 = 0xCDE // 3294 + SYS_LOCALTIME64_R = 0xCDF // 3295 + SYS_MKTIME64 = 0xCE0 // 3296 + SYS_TIME64 = 0xCE1 // 3297 + SYS___LOGIN_APPLID = 0xCE2 // 3298 + SYS___PASSWD_APPLID = 0xCE3 // 3299 + SYS_PTHREAD_SECURITY_APPLID_NP = 0xCE4 // 3300 + SYS___GETTHENT = 0xCE5 // 3301 + SYS_FREEIFADDRS = 0xCE6 // 3302 + SYS_GETIFADDRS = 0xCE7 // 3303 + SYS_POSIX_FALLOCATE = 0xCE8 // 3304 + SYS_POSIX_MEMALIGN = 0xCE9 // 3305 + SYS_SIZEOF_ALLOC = 0xCEA // 3306 + SYS_RESIZE_ALLOC = 0xCEB // 3307 + SYS_FREAD_NOUPDATE = 0xCEC // 3308 + SYS_FREAD_NOUPDATE_UNLOCKED = 0xCED // 3309 + SYS_FGETPOS64 = 0xCEE // 3310 + SYS_FSEEK64 = 0xCEF // 3311 + SYS_FSEEKO64 = 0xCF0 // 3312 + SYS_FSETPOS64 = 0xCF1 // 3313 + SYS_FTELL64 = 0xCF2 // 3314 + SYS_FTELLO64 = 0xCF3 // 3315 + SYS_FGETPOS64_UNLOCKED = 0xCF4 // 3316 + SYS_FSEEK64_UNLOCKED = 0xCF5 // 3317 + SYS_FSEEKO64_UNLOCKED = 0xCF6 // 3318 + SYS_FSETPOS64_UNLOCKED = 0xCF7 // 3319 + SYS_FTELL64_UNLOCKED = 0xCF8 // 3320 + SYS_FTELLO64_UNLOCKED = 0xCF9 // 3321 + SYS_FOPEN_UNLOCKED = 0xCFA // 3322 + SYS_FREOPEN_UNLOCKED = 0xCFB // 3323 + SYS_FDOPEN_UNLOCKED = 0xCFC // 3324 + SYS_TMPFILE_UNLOCKED = 0xCFD // 3325 + SYS___MOSERVICES = 0xD3D // 3389 + SYS___GETTOD = 0xD3E // 3390 + SYS_C16RTOMB = 0xD40 // 3392 + SYS_C32RTOMB = 0xD41 // 3393 + SYS_MBRTOC16 = 0xD42 // 3394 + SYS_MBRTOC32 = 0xD43 // 3395 + SYS_QUANTEXPD32 = 0xD44 // 3396 + SYS_QUANTEXPD64 = 0xD45 // 3397 + SYS_QUANTEXPD128 = 0xD46 // 3398 + SYS___LOCALE_CTL = 0xD47 // 3399 + SYS___SMF_RECORD2 = 0xD48 // 3400 + SYS_FOPEN64 = 0xD49 // 3401 + SYS_FOPEN64_UNLOCKED = 0xD4A // 3402 + SYS_FREOPEN64 = 0xD4B // 3403 + SYS_FREOPEN64_UNLOCKED = 0xD4C // 3404 + SYS_TMPFILE64 = 0xD4D // 3405 + SYS_TMPFILE64_UNLOCKED = 0xD4E // 3406 + SYS_GETDATE64 = 0xD4F // 3407 + SYS_GETTIMEOFDAY64 = 0xD50 // 3408 + SYS_BIND2ADDRSEL = 0xD59 // 3417 + SYS_INET6_IS_SRCADDR = 0xD5A // 3418 + SYS___GETGRGID1 = 0xD5B // 3419 + SYS___GETGRNAM1 = 0xD5C // 3420 + SYS___FBUFSIZE = 0xD60 // 3424 + SYS___FPENDING = 0xD61 // 3425 + SYS___FLBF = 0xD62 // 3426 + SYS___FREADABLE = 0xD63 // 3427 + SYS___FWRITABLE = 0xD64 // 3428 + SYS___FREADING = 0xD65 // 3429 + SYS___FWRITING = 0xD66 // 3430 + SYS___FSETLOCKING = 0xD67 // 3431 + SYS__FLUSHLBF = 0xD68 // 3432 + SYS___FPURGE = 0xD69 // 3433 + SYS___FREADAHEAD = 0xD6A // 3434 + SYS___FSETERR = 0xD6B // 3435 + SYS___FPENDING_UNLOCKED = 0xD6C // 3436 + SYS___FREADING_UNLOCKED = 0xD6D // 3437 + SYS___FWRITING_UNLOCKED = 0xD6E // 3438 + SYS__FLUSHLBF_UNLOCKED = 0xD6F // 3439 + SYS___FPURGE_UNLOCKED = 0xD70 // 3440 + SYS___FREADAHEAD_UNLOCKED = 0xD71 // 3441 + SYS___LE_CEEGTJS = 0xD72 // 3442 + SYS___LE_RECORD_DUMP = 0xD73 // 3443 + SYS_FSTAT64 = 0xD74 // 3444 + SYS_LSTAT64 = 0xD75 // 3445 + SYS_STAT64 = 0xD76 // 3446 + SYS___READDIR2_64 = 0xD77 // 3447 + SYS___OPEN_STAT64 = 0xD78 // 3448 + SYS_FTW64 = 0xD79 // 3449 + SYS_NFTW64 = 0xD7A // 3450 + SYS_UTIME64 = 0xD7B // 3451 + SYS_UTIMES64 = 0xD7C // 3452 + SYS___GETIPC64 = 0xD7D // 3453 + SYS_MSGCTL64 = 0xD7E // 3454 + SYS_SEMCTL64 = 0xD7F // 3455 + SYS_SHMCTL64 = 0xD80 // 3456 + SYS_MSGXRCV64 = 0xD81 // 3457 + SYS___MGXR64 = 0xD81 // 3457 + SYS_W_GETPSENT64 = 0xD82 // 3458 + SYS_PTHREAD_COND_TIMEDWAIT64 = 0xD83 // 3459 + SYS_FTIME64 = 0xD85 // 3461 + SYS_GETUTXENT64 = 0xD86 // 3462 + SYS_GETUTXID64 = 0xD87 // 3463 + SYS_GETUTXLINE64 = 0xD88 // 3464 + SYS_PUTUTXLINE64 = 0xD89 // 3465 + SYS_NEWLOCALE = 0xD8A // 3466 + SYS_FREELOCALE = 0xD8B // 3467 + SYS_USELOCALE = 0xD8C // 3468 + SYS_DUPLOCALE = 0xD8D // 3469 + SYS___CHATTR64 = 0xD9C // 3484 + SYS___LCHATTR64 = 0xD9D // 3485 + SYS___FCHATTR64 = 0xD9E // 3486 + SYS_____CHATTR64_A = 0xD9F // 3487 + SYS_____LCHATTR64_A = 0xDA0 // 3488 + SYS___LE_CEEUSGD = 0xDA1 // 3489 + SYS___LE_IFAM_CON = 0xDA2 // 3490 + SYS___LE_IFAM_DSC = 0xDA3 // 3491 + SYS___LE_IFAM_GET = 0xDA4 // 3492 + SYS___LE_IFAM_QRY = 0xDA5 // 3493 + SYS_ALIGNED_ALLOC = 0xDA6 // 3494 + SYS_ACCEPT4 = 0xDA7 // 3495 + SYS___ACCEPT4_A = 0xDA8 // 3496 + SYS_COPYFILERANGE = 0xDA9 // 3497 + SYS_GETLINE = 0xDAA // 3498 + SYS___GETLINE_A = 0xDAB // 3499 + SYS_DIRFD = 0xDAC // 3500 + SYS_CLOCK_GETTIME = 0xDAD // 3501 + SYS_DUP3 = 0xDAE // 3502 + SYS_EPOLL_CREATE = 0xDAF // 3503 + SYS_EPOLL_CREATE1 = 0xDB0 // 3504 + SYS_EPOLL_CTL = 0xDB1 // 3505 + SYS_EPOLL_WAIT = 0xDB2 // 3506 + SYS_EPOLL_PWAIT = 0xDB3 // 3507 + SYS_EVENTFD = 0xDB4 // 3508 + SYS_STATFS = 0xDB5 // 3509 + SYS___STATFS_A = 0xDB6 // 3510 + SYS_FSTATFS = 0xDB7 // 3511 + SYS_INOTIFY_INIT = 0xDB8 // 3512 + SYS_INOTIFY_INIT1 = 0xDB9 // 3513 + SYS_INOTIFY_ADD_WATCH = 0xDBA // 3514 + SYS___INOTIFY_ADD_WATCH_A = 0xDBB // 3515 + SYS_INOTIFY_RM_WATCH = 0xDBC // 3516 + SYS_PIPE2 = 0xDBD // 3517 + SYS_PIVOT_ROOT = 0xDBE // 3518 + SYS___PIVOT_ROOT_A = 0xDBF // 3519 + SYS_PRCTL = 0xDC0 // 3520 + SYS_PRLIMIT = 0xDC1 // 3521 + SYS_SETHOSTNAME = 0xDC2 // 3522 + SYS___SETHOSTNAME_A = 0xDC3 // 3523 + SYS_SETRESUID = 0xDC4 // 3524 + SYS_SETRESGID = 0xDC5 // 3525 + SYS_PTHREAD_CONDATTR_GETCLOCK = 0xDC6 // 3526 + SYS_FLOCK = 0xDC7 // 3527 + SYS_FGETXATTR = 0xDC8 // 3528 + SYS___FGETXATTR_A = 0xDC9 // 3529 + SYS_FLISTXATTR = 0xDCA // 3530 + SYS___FLISTXATTR_A = 0xDCB // 3531 + SYS_FREMOVEXATTR = 0xDCC // 3532 + SYS___FREMOVEXATTR_A = 0xDCD // 3533 + SYS_FSETXATTR = 0xDCE // 3534 + SYS___FSETXATTR_A = 0xDCF // 3535 + SYS_GETXATTR = 0xDD0 // 3536 + SYS___GETXATTR_A = 0xDD1 // 3537 + SYS_LGETXATTR = 0xDD2 // 3538 + SYS___LGETXATTR_A = 0xDD3 // 3539 + SYS_LISTXATTR = 0xDD4 // 3540 + SYS___LISTXATTR_A = 0xDD5 // 3541 + SYS_LLISTXATTR = 0xDD6 // 3542 + SYS___LLISTXATTR_A = 0xDD7 // 3543 + SYS_LREMOVEXATTR = 0xDD8 // 3544 + SYS___LREMOVEXATTR_A = 0xDD9 // 3545 + SYS_LSETXATTR = 0xDDA // 3546 + SYS___LSETXATTR_A = 0xDDB // 3547 + SYS_REMOVEXATTR = 0xDDC // 3548 + SYS___REMOVEXATTR_A = 0xDDD // 3549 + SYS_SETXATTR = 0xDDE // 3550 + SYS___SETXATTR_A = 0xDDF // 3551 + SYS_FDATASYNC = 0xDE0 // 3552 + SYS_SYNCFS = 0xDE1 // 3553 + SYS_FUTIMES = 0xDE2 // 3554 + SYS_FUTIMESAT = 0xDE3 // 3555 + SYS___FUTIMESAT_A = 0xDE4 // 3556 + SYS_LUTIMES = 0xDE5 // 3557 + SYS___LUTIMES_A = 0xDE6 // 3558 + SYS_INET_ATON = 0xDE7 // 3559 + SYS_GETRANDOM = 0xDE8 // 3560 + SYS_GETTID = 0xDE9 // 3561 + SYS_MEMFD_CREATE = 0xDEA // 3562 + SYS___MEMFD_CREATE_A = 0xDEB // 3563 + SYS_FACCESSAT = 0xDEC // 3564 + SYS___FACCESSAT_A = 0xDED // 3565 + SYS_FCHMODAT = 0xDEE // 3566 + SYS___FCHMODAT_A = 0xDEF // 3567 + SYS_FCHOWNAT = 0xDF0 // 3568 + SYS___FCHOWNAT_A = 0xDF1 // 3569 + SYS_FSTATAT = 0xDF2 // 3570 + SYS___FSTATAT_A = 0xDF3 // 3571 + SYS_LINKAT = 0xDF4 // 3572 + SYS___LINKAT_A = 0xDF5 // 3573 + SYS_MKDIRAT = 0xDF6 // 3574 + SYS___MKDIRAT_A = 0xDF7 // 3575 + SYS_MKFIFOAT = 0xDF8 // 3576 + SYS___MKFIFOAT_A = 0xDF9 // 3577 + SYS_MKNODAT = 0xDFA // 3578 + SYS___MKNODAT_A = 0xDFB // 3579 + SYS_OPENAT = 0xDFC // 3580 + SYS___OPENAT_A = 0xDFD // 3581 + SYS_READLINKAT = 0xDFE // 3582 + SYS___READLINKAT_A = 0xDFF // 3583 + SYS_RENAMEAT = 0xE00 // 3584 + SYS___RENAMEAT_A = 0xE01 // 3585 + SYS_RENAMEAT2 = 0xE02 // 3586 + SYS___RENAMEAT2_A = 0xE03 // 3587 + SYS_SYMLINKAT = 0xE04 // 3588 + SYS___SYMLINKAT_A = 0xE05 // 3589 + SYS_UNLINKAT = 0xE06 // 3590 + SYS___UNLINKAT_A = 0xE07 // 3591 + SYS_SYSINFO = 0xE08 // 3592 + SYS_WAIT4 = 0xE0A // 3594 + SYS_CLONE = 0xE0B // 3595 + SYS_UNSHARE = 0xE0C // 3596 + SYS_SETNS = 0xE0D // 3597 + SYS_CAPGET = 0xE0E // 3598 + SYS_CAPSET = 0xE0F // 3599 + SYS_STRCHRNUL = 0xE10 // 3600 + SYS_PTHREAD_CONDATTR_SETCLOCK = 0xE12 // 3602 + SYS_OPEN_BY_HANDLE_AT = 0xE13 // 3603 + SYS___OPEN_BY_HANDLE_AT_A = 0xE14 // 3604 + SYS___INET_ATON_A = 0xE15 // 3605 + SYS_MOUNT1 = 0xE16 // 3606 + SYS___MOUNT1_A = 0xE17 // 3607 + SYS_UMOUNT1 = 0xE18 // 3608 + SYS___UMOUNT1_A = 0xE19 // 3609 + SYS_UMOUNT2 = 0xE1A // 3610 + SYS___UMOUNT2_A = 0xE1B // 3611 + SYS___PRCTL_A = 0xE1C // 3612 + SYS_LOCALTIME_R2 = 0xE1D // 3613 + SYS___LOCALTIME_R2_A = 0xE1E // 3614 + SYS_OPENAT2 = 0xE1F // 3615 + SYS___OPENAT2_A = 0xE20 // 3616 + SYS___LE_CEEMICT = 0xE21 // 3617 + SYS_GETENTROPY = 0xE22 // 3618 + SYS_NANOSLEEP = 0xE23 // 3619 + SYS_UTIMENSAT = 0xE24 // 3620 + SYS___UTIMENSAT_A = 0xE25 // 3621 + SYS_ASPRINTF = 0xE26 // 3622 + SYS___ASPRINTF_A = 0xE27 // 3623 + SYS_VASPRINTF = 0xE28 // 3624 + SYS___VASPRINTF_A = 0xE29 // 3625 + SYS_DPRINTF = 0xE2A // 3626 + SYS___DPRINTF_A = 0xE2B // 3627 + SYS_GETOPT_LONG = 0xE2C // 3628 + SYS___GETOPT_LONG_A = 0xE2D // 3629 + SYS_PSIGNAL = 0xE2E // 3630 + SYS___PSIGNAL_A = 0xE2F // 3631 + SYS_PSIGNAL_UNLOCKED = 0xE30 // 3632 + SYS___PSIGNAL_UNLOCKED_A = 0xE31 // 3633 + SYS_FSTATAT_O = 0xE32 // 3634 + SYS___FSTATAT_O_A = 0xE33 // 3635 + SYS_FSTATAT64 = 0xE34 // 3636 + SYS___FSTATAT64_A = 0xE35 // 3637 + SYS___CHATTRAT = 0xE36 // 3638 + SYS_____CHATTRAT_A = 0xE37 // 3639 + SYS___CHATTRAT64 = 0xE38 // 3640 + SYS_____CHATTRAT64_A = 0xE39 // 3641 + SYS_MADVISE = 0xE3A // 3642 + SYS___AUTHENTICATE = 0xE3B // 3643 + ) diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_darwin_amd64.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_darwin_amd64.go index 091d107f3..17c53bd9b 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_darwin_amd64.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_darwin_amd64.go @@ -306,6 +306,19 @@ type XVSockPgen struct { type _Socklen uint32 +type SaeAssocID uint32 + +type SaeConnID uint32 + +type SaEndpoints struct { + Srcif uint32 + Srcaddr *RawSockaddr + Srcaddrlen uint32 + Dstaddr *RawSockaddr + Dstaddrlen uint32 + _ [4]byte +} + type Xucred struct { Version uint32 Uid uint32 @@ -449,11 +462,14 @@ type FdSet struct { const ( SizeofIfMsghdr = 0x70 + SizeofIfMsghdr2 = 0xa0 SizeofIfData = 0x60 + SizeofIfData64 = 0x80 SizeofIfaMsghdr = 0x14 SizeofIfmaMsghdr = 0x10 SizeofIfmaMsghdr2 = 0x14 SizeofRtMsghdr = 0x5c + SizeofRtMsghdr2 = 0x5c SizeofRtMetrics = 0x38 ) @@ -467,6 +483,20 @@ type IfMsghdr struct { Data IfData } +type IfMsghdr2 struct { + Msglen uint16 + Version uint8 + Type uint8 + Addrs int32 + Flags int32 + Index uint16 + Snd_len int32 + Snd_maxlen int32 + Snd_drops int32 + Timer int32 + Data IfData64 +} + type IfData struct { Type uint8 Typelen uint8 @@ -499,6 +529,34 @@ type IfData struct { Reserved2 uint32 } +type IfData64 struct { + Type uint8 + Typelen uint8 + Physical uint8 + Addrlen uint8 + Hdrlen uint8 + Recvquota uint8 + Xmitquota uint8 + Unused1 uint8 + Mtu uint32 + Metric uint32 + Baudrate uint64 + Ipackets uint64 + Ierrors uint64 + Opackets uint64 + Oerrors uint64 + Collisions uint64 + Ibytes uint64 + Obytes uint64 + Imcasts uint64 + Omcasts uint64 + Iqdrops uint64 + Noproto uint64 + Recvtiming uint32 + Xmittiming uint32 + Lastchange Timeval32 +} + type IfaMsghdr struct { Msglen uint16 Version uint8 @@ -544,6 +602,21 @@ type RtMsghdr struct { Rmx RtMetrics } +type RtMsghdr2 struct { + Msglen uint16 + Version uint8 + Type uint8 + Index uint16 + Flags int32 + Addrs int32 + Refcnt int32 + Parentflags int32 + Reserved int32 + Use int32 + Inits uint32 + Rmx RtMetrics +} + type RtMetrics struct { Locks uint32 Mtu uint32 diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_darwin_arm64.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_darwin_arm64.go index 28ff4ef74..2392226a7 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_darwin_arm64.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_darwin_arm64.go @@ -306,6 +306,19 @@ type XVSockPgen struct { type _Socklen uint32 +type SaeAssocID uint32 + +type SaeConnID uint32 + +type SaEndpoints struct { + Srcif uint32 + Srcaddr *RawSockaddr + Srcaddrlen uint32 + Dstaddr *RawSockaddr + Dstaddrlen uint32 + _ [4]byte +} + type Xucred struct { Version uint32 Uid uint32 @@ -449,11 +462,14 @@ type FdSet struct { const ( SizeofIfMsghdr = 0x70 + SizeofIfMsghdr2 = 0xa0 SizeofIfData = 0x60 + SizeofIfData64 = 0x80 SizeofIfaMsghdr = 0x14 SizeofIfmaMsghdr = 0x10 SizeofIfmaMsghdr2 = 0x14 SizeofRtMsghdr = 0x5c + SizeofRtMsghdr2 = 0x5c SizeofRtMetrics = 0x38 ) @@ -467,6 +483,20 @@ type IfMsghdr struct { Data IfData } +type IfMsghdr2 struct { + Msglen uint16 + Version uint8 + Type uint8 + Addrs int32 + Flags int32 + Index uint16 + Snd_len int32 + Snd_maxlen int32 + Snd_drops int32 + Timer int32 + Data IfData64 +} + type IfData struct { Type uint8 Typelen uint8 @@ -499,6 +529,34 @@ type IfData struct { Reserved2 uint32 } +type IfData64 struct { + Type uint8 + Typelen uint8 + Physical uint8 + Addrlen uint8 + Hdrlen uint8 + Recvquota uint8 + Xmitquota uint8 + Unused1 uint8 + Mtu uint32 + Metric uint32 + Baudrate uint64 + Ipackets uint64 + Ierrors uint64 + Opackets uint64 + Oerrors uint64 + Collisions uint64 + Ibytes uint64 + Obytes uint64 + Imcasts uint64 + Omcasts uint64 + Iqdrops uint64 + Noproto uint64 + Recvtiming uint32 + Xmittiming uint32 + Lastchange Timeval32 +} + type IfaMsghdr struct { Msglen uint16 Version uint8 @@ -544,6 +602,21 @@ type RtMsghdr struct { Rmx RtMetrics } +type RtMsghdr2 struct { + Msglen uint16 + Version uint8 + Type uint8 + Index uint16 + Flags int32 + Addrs int32 + Refcnt int32 + Parentflags int32 + Reserved int32 + Use int32 + Inits uint32 + Rmx RtMetrics +} + type RtMetrics struct { Locks uint32 Mtu uint32 diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_freebsd_386.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_freebsd_386.go index 6cbd094a3..51e13eb05 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_freebsd_386.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_freebsd_386.go @@ -625,6 +625,7 @@ const ( POLLRDNORM = 0x40 POLLWRBAND = 0x100 POLLWRNORM = 0x4 + POLLRDHUP = 0x4000 ) type CapRights struct { diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_freebsd_amd64.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_freebsd_amd64.go index 7c03b6ee7..d002d8ef3 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_freebsd_amd64.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_freebsd_amd64.go @@ -630,6 +630,7 @@ const ( POLLRDNORM = 0x40 POLLWRBAND = 0x100 POLLWRNORM = 0x4 + POLLRDHUP = 0x4000 ) type CapRights struct { diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_freebsd_arm.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_freebsd_arm.go index 422107ee8..3f863d898 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_freebsd_arm.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_freebsd_arm.go @@ -616,6 +616,7 @@ const ( POLLRDNORM = 0x40 POLLWRBAND = 0x100 POLLWRNORM = 0x4 + POLLRDHUP = 0x4000 ) type CapRights struct { diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_freebsd_arm64.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_freebsd_arm64.go index 505a12acf..61c729310 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_freebsd_arm64.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_freebsd_arm64.go @@ -610,6 +610,7 @@ const ( POLLRDNORM = 0x40 POLLWRBAND = 0x100 POLLWRNORM = 0x4 + POLLRDHUP = 0x4000 ) type CapRights struct { diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_freebsd_riscv64.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_freebsd_riscv64.go index cc986c790..b5d17414f 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_freebsd_riscv64.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_freebsd_riscv64.go @@ -612,6 +612,7 @@ const ( POLLRDNORM = 0x40 POLLWRBAND = 0x100 POLLWRNORM = 0x4 + POLLRDHUP = 0x4000 ) type CapRights struct { diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_linux.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_linux.go index eff6bcdef..a46abe647 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_linux.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_linux.go @@ -87,30 +87,35 @@ type StatxTimestamp struct { } type Statx_t struct { - Mask uint32 - Blksize uint32 - Attributes uint64 - Nlink uint32 - Uid uint32 - Gid uint32 - Mode uint16 - _ [1]uint16 - Ino uint64 - Size uint64 - Blocks uint64 - Attributes_mask uint64 - Atime StatxTimestamp - Btime StatxTimestamp - Ctime StatxTimestamp - Mtime StatxTimestamp - Rdev_major uint32 - Rdev_minor uint32 - Dev_major uint32 - Dev_minor uint32 - Mnt_id uint64 - Dio_mem_align uint32 - Dio_offset_align uint32 - _ [12]uint64 + Mask uint32 + Blksize uint32 + Attributes uint64 + Nlink uint32 + Uid uint32 + Gid uint32 + Mode uint16 + _ [1]uint16 + Ino uint64 + Size uint64 + Blocks uint64 + Attributes_mask uint64 + Atime StatxTimestamp + Btime StatxTimestamp + Ctime StatxTimestamp + Mtime StatxTimestamp + Rdev_major uint32 + Rdev_minor uint32 + Dev_major uint32 + Dev_minor uint32 + Mnt_id uint64 + Dio_mem_align uint32 + Dio_offset_align uint32 + Subvol uint64 + Atomic_write_unit_min uint32 + Atomic_write_unit_max uint32 + Atomic_write_segments_max uint32 + _ [1]uint32 + _ [9]uint64 } type Fsid struct { @@ -515,6 +520,29 @@ type TCPInfo struct { Total_rto_time uint32 } +type TCPVegasInfo struct { + Enabled uint32 + Rttcnt uint32 + Rtt uint32 + Minrtt uint32 +} + +type TCPDCTCPInfo struct { + Enabled uint16 + Ce_state uint16 + Alpha uint32 + Ab_ecn uint32 + Ab_tot uint32 +} + +type TCPBBRInfo struct { + Bw_lo uint32 + Bw_hi uint32 + Min_rtt uint32 + Pacing_gain uint32 + Cwnd_gain uint32 +} + type CanFilter struct { Id uint32 Mask uint32 @@ -556,6 +584,7 @@ const ( SizeofICMPv6Filter = 0x20 SizeofUcred = 0xc SizeofTCPInfo = 0xf8 + SizeofTCPCCInfo = 0x14 SizeofCanFilter = 0x8 SizeofTCPRepairOpt = 0x8 ) @@ -1178,7 +1207,8 @@ const ( PERF_SAMPLE_BRANCH_TYPE_SAVE_SHIFT = 0x10 PERF_SAMPLE_BRANCH_HW_INDEX_SHIFT = 0x11 PERF_SAMPLE_BRANCH_PRIV_SAVE_SHIFT = 0x12 - PERF_SAMPLE_BRANCH_MAX_SHIFT = 0x13 + PERF_SAMPLE_BRANCH_COUNTERS = 0x80000 + PERF_SAMPLE_BRANCH_MAX_SHIFT = 0x14 PERF_SAMPLE_BRANCH_USER = 0x1 PERF_SAMPLE_BRANCH_KERNEL = 0x2 PERF_SAMPLE_BRANCH_HV = 0x4 @@ -1198,7 +1228,7 @@ const ( PERF_SAMPLE_BRANCH_TYPE_SAVE = 0x10000 PERF_SAMPLE_BRANCH_HW_INDEX = 0x20000 PERF_SAMPLE_BRANCH_PRIV_SAVE = 0x40000 - PERF_SAMPLE_BRANCH_MAX = 0x80000 + PERF_SAMPLE_BRANCH_MAX = 0x100000 PERF_BR_UNKNOWN = 0x0 PERF_BR_COND = 0x1 PERF_BR_UNCOND = 0x2 @@ -1722,12 +1752,6 @@ const ( IFLA_IPVLAN_UNSPEC = 0x0 IFLA_IPVLAN_MODE = 0x1 IFLA_IPVLAN_FLAGS = 0x2 - NETKIT_NEXT = -0x1 - NETKIT_PASS = 0x0 - NETKIT_DROP = 0x2 - NETKIT_REDIRECT = 0x7 - NETKIT_L2 = 0x0 - NETKIT_L3 = 0x1 IFLA_NETKIT_UNSPEC = 0x0 IFLA_NETKIT_PEER_INFO = 0x1 IFLA_NETKIT_PRIMARY = 0x2 @@ -1766,6 +1790,7 @@ const ( IFLA_VXLAN_DF = 0x1d IFLA_VXLAN_VNIFILTER = 0x1e IFLA_VXLAN_LOCALBYPASS = 0x1f + IFLA_VXLAN_LABEL_POLICY = 0x20 IFLA_GENEVE_UNSPEC = 0x0 IFLA_GENEVE_ID = 0x1 IFLA_GENEVE_REMOTE = 0x2 @@ -1795,6 +1820,8 @@ const ( IFLA_GTP_ROLE = 0x4 IFLA_GTP_CREATE_SOCKETS = 0x5 IFLA_GTP_RESTART_COUNT = 0x6 + IFLA_GTP_LOCAL = 0x7 + IFLA_GTP_LOCAL6 = 0x8 IFLA_BOND_UNSPEC = 0x0 IFLA_BOND_MODE = 0x1 IFLA_BOND_ACTIVE_SLAVE = 0x2 @@ -1827,6 +1854,7 @@ const ( IFLA_BOND_AD_LACP_ACTIVE = 0x1d IFLA_BOND_MISSED_MAX = 0x1e IFLA_BOND_NS_IP6_TARGET = 0x1f + IFLA_BOND_COUPLED_CONTROL = 0x20 IFLA_BOND_AD_INFO_UNSPEC = 0x0 IFLA_BOND_AD_INFO_AGGREGATOR = 0x1 IFLA_BOND_AD_INFO_NUM_PORTS = 0x2 @@ -1895,6 +1923,7 @@ const ( IFLA_HSR_SEQ_NR = 0x5 IFLA_HSR_VERSION = 0x6 IFLA_HSR_PROTOCOL = 0x7 + IFLA_HSR_INTERLINK = 0x8 IFLA_STATS_UNSPEC = 0x0 IFLA_STATS_LINK_64 = 0x1 IFLA_STATS_LINK_XSTATS = 0x2 @@ -1947,6 +1976,15 @@ const ( IFLA_DSA_MASTER = 0x1 ) +const ( + NETKIT_NEXT = -0x1 + NETKIT_PASS = 0x0 + NETKIT_DROP = 0x2 + NETKIT_REDIRECT = 0x7 + NETKIT_L2 = 0x0 + NETKIT_L3 = 0x1 +) + const ( NF_INET_PRE_ROUTING = 0x0 NF_INET_LOCAL_IN = 0x1 @@ -2481,6 +2519,15 @@ type XDPMmapOffsets struct { Cr XDPRingOffset } +type XDPUmemReg struct { + Addr uint64 + Len uint64 + Size uint32 + Headroom uint32 + Flags uint32 + Tx_metadata_len uint32 +} + type XDPStatistics struct { Rx_dropped uint64 Rx_invalid_descs uint64 @@ -2547,8 +2594,8 @@ const ( SOF_TIMESTAMPING_BIND_PHC = 0x8000 SOF_TIMESTAMPING_OPT_ID_TCP = 0x10000 - SOF_TIMESTAMPING_LAST = 0x10000 - SOF_TIMESTAMPING_MASK = 0x1ffff + SOF_TIMESTAMPING_LAST = 0x20000 + SOF_TIMESTAMPING_MASK = 0x3ffff SCM_TSTAMP_SND = 0x0 SCM_TSTAMP_SCHED = 0x1 @@ -2935,7 +2982,7 @@ const ( BPF_TCP_LISTEN = 0xa BPF_TCP_CLOSING = 0xb BPF_TCP_NEW_SYN_RECV = 0xc - BPF_TCP_MAX_STATES = 0xd + BPF_TCP_MAX_STATES = 0xe TCP_BPF_IW = 0x3e9 TCP_BPF_SNDCWND_CLAMP = 0x3ea TCP_BPF_DELACK_MAX = 0x3eb @@ -3211,7 +3258,7 @@ const ( DEVLINK_CMD_LINECARD_NEW = 0x50 DEVLINK_CMD_LINECARD_DEL = 0x51 DEVLINK_CMD_SELFTESTS_GET = 0x52 - DEVLINK_CMD_MAX = 0x53 + DEVLINK_CMD_MAX = 0x54 DEVLINK_PORT_TYPE_NOTSET = 0x0 DEVLINK_PORT_TYPE_AUTO = 0x1 DEVLINK_PORT_TYPE_ETH = 0x2 @@ -3463,7 +3510,7 @@ const ( DEVLINK_PORT_FN_ATTR_STATE = 0x2 DEVLINK_PORT_FN_ATTR_OPSTATE = 0x3 DEVLINK_PORT_FN_ATTR_CAPS = 0x4 - DEVLINK_PORT_FUNCTION_ATTR_MAX = 0x5 + DEVLINK_PORT_FUNCTION_ATTR_MAX = 0x6 ) type FsverityDigest struct { @@ -3494,7 +3541,7 @@ type Nhmsg struct { type NexthopGrp struct { Id uint32 Weight uint8 - Resvd1 uint8 + High uint8 Resvd2 uint16 } @@ -3755,7 +3802,7 @@ const ( ETHTOOL_MSG_PSE_GET = 0x24 ETHTOOL_MSG_PSE_SET = 0x25 ETHTOOL_MSG_RSS_GET = 0x26 - ETHTOOL_MSG_USER_MAX = 0x2b + ETHTOOL_MSG_USER_MAX = 0x2d ETHTOOL_MSG_KERNEL_NONE = 0x0 ETHTOOL_MSG_STRSET_GET_REPLY = 0x1 ETHTOOL_MSG_LINKINFO_GET_REPLY = 0x2 @@ -3795,12 +3842,15 @@ const ( ETHTOOL_MSG_MODULE_NTF = 0x24 ETHTOOL_MSG_PSE_GET_REPLY = 0x25 ETHTOOL_MSG_RSS_GET_REPLY = 0x26 - ETHTOOL_MSG_KERNEL_MAX = 0x2b + ETHTOOL_MSG_KERNEL_MAX = 0x2e + ETHTOOL_FLAG_COMPACT_BITSETS = 0x1 + ETHTOOL_FLAG_OMIT_REPLY = 0x2 + ETHTOOL_FLAG_STATS = 0x4 ETHTOOL_A_HEADER_UNSPEC = 0x0 ETHTOOL_A_HEADER_DEV_INDEX = 0x1 ETHTOOL_A_HEADER_DEV_NAME = 0x2 ETHTOOL_A_HEADER_FLAGS = 0x3 - ETHTOOL_A_HEADER_MAX = 0x3 + ETHTOOL_A_HEADER_MAX = 0x4 ETHTOOL_A_BITSET_BIT_UNSPEC = 0x0 ETHTOOL_A_BITSET_BIT_INDEX = 0x1 ETHTOOL_A_BITSET_BIT_NAME = 0x2 @@ -3937,7 +3987,7 @@ const ( ETHTOOL_A_COALESCE_RATE_SAMPLE_INTERVAL = 0x17 ETHTOOL_A_COALESCE_USE_CQE_MODE_TX = 0x18 ETHTOOL_A_COALESCE_USE_CQE_MODE_RX = 0x19 - ETHTOOL_A_COALESCE_MAX = 0x1c + ETHTOOL_A_COALESCE_MAX = 0x1e ETHTOOL_A_PAUSE_UNSPEC = 0x0 ETHTOOL_A_PAUSE_HEADER = 0x1 ETHTOOL_A_PAUSE_AUTONEG = 0x2 @@ -3965,7 +4015,7 @@ const ( ETHTOOL_A_TSINFO_TX_TYPES = 0x3 ETHTOOL_A_TSINFO_RX_FILTERS = 0x4 ETHTOOL_A_TSINFO_PHC_INDEX = 0x5 - ETHTOOL_A_TSINFO_MAX = 0x5 + ETHTOOL_A_TSINFO_MAX = 0x6 ETHTOOL_A_CABLE_TEST_UNSPEC = 0x0 ETHTOOL_A_CABLE_TEST_HEADER = 0x1 ETHTOOL_A_CABLE_TEST_MAX = 0x1 @@ -3981,11 +4031,11 @@ const ( ETHTOOL_A_CABLE_RESULT_UNSPEC = 0x0 ETHTOOL_A_CABLE_RESULT_PAIR = 0x1 ETHTOOL_A_CABLE_RESULT_CODE = 0x2 - ETHTOOL_A_CABLE_RESULT_MAX = 0x2 + ETHTOOL_A_CABLE_RESULT_MAX = 0x3 ETHTOOL_A_CABLE_FAULT_LENGTH_UNSPEC = 0x0 ETHTOOL_A_CABLE_FAULT_LENGTH_PAIR = 0x1 ETHTOOL_A_CABLE_FAULT_LENGTH_CM = 0x2 - ETHTOOL_A_CABLE_FAULT_LENGTH_MAX = 0x2 + ETHTOOL_A_CABLE_FAULT_LENGTH_MAX = 0x3 ETHTOOL_A_CABLE_TEST_NTF_STATUS_UNSPEC = 0x0 ETHTOOL_A_CABLE_TEST_NTF_STATUS_STARTED = 0x1 ETHTOOL_A_CABLE_TEST_NTF_STATUS_COMPLETED = 0x2 @@ -4068,6 +4118,107 @@ type EthtoolDrvinfo struct { Regdump_len uint32 } +type EthtoolTsInfo struct { + Cmd uint32 + So_timestamping uint32 + Phc_index int32 + Tx_types uint32 + Tx_reserved [3]uint32 + Rx_filters uint32 + Rx_reserved [3]uint32 +} + +type HwTstampConfig struct { + Flags int32 + Tx_type int32 + Rx_filter int32 +} + +const ( + HWTSTAMP_FILTER_NONE = 0x0 + HWTSTAMP_FILTER_ALL = 0x1 + HWTSTAMP_FILTER_SOME = 0x2 + HWTSTAMP_FILTER_PTP_V1_L4_EVENT = 0x3 + HWTSTAMP_FILTER_PTP_V2_L4_EVENT = 0x6 + HWTSTAMP_FILTER_PTP_V2_L2_EVENT = 0x9 + HWTSTAMP_FILTER_PTP_V2_EVENT = 0xc +) + +const ( + HWTSTAMP_TX_OFF = 0x0 + HWTSTAMP_TX_ON = 0x1 + HWTSTAMP_TX_ONESTEP_SYNC = 0x2 +) + +type ( + PtpClockCaps struct { + Max_adj int32 + N_alarm int32 + N_ext_ts int32 + N_per_out int32 + Pps int32 + N_pins int32 + Cross_timestamping int32 + Adjust_phase int32 + Max_phase_adj int32 + Rsv [11]int32 + } + PtpClockTime struct { + Sec int64 + Nsec uint32 + Reserved uint32 + } + PtpExttsEvent struct { + T PtpClockTime + Index uint32 + Flags uint32 + Rsv [2]uint32 + } + PtpExttsRequest struct { + Index uint32 + Flags uint32 + Rsv [2]uint32 + } + PtpPeroutRequest struct { + StartOrPhase PtpClockTime + Period PtpClockTime + Index uint32 + Flags uint32 + On PtpClockTime + } + PtpPinDesc struct { + Name [64]byte + Index uint32 + Func uint32 + Chan uint32 + Rsv [5]uint32 + } + PtpSysOffset struct { + Samples uint32 + Rsv [3]uint32 + Ts [51]PtpClockTime + } + PtpSysOffsetExtended struct { + Samples uint32 + Clockid int32 + Rsv [2]uint32 + Ts [25][3]PtpClockTime + } + PtpSysOffsetPrecise struct { + Device PtpClockTime + Realtime PtpClockTime + Monoraw PtpClockTime + Rsv [4]uint32 + } +) + +const ( + PTP_PF_NONE = 0x0 + PTP_PF_EXTTS = 0x1 + PTP_PF_PEROUT = 0x2 + PTP_PF_PHYSYNC = 0x3 +) + type ( HIDRawReportDescriptor struct { Size uint32 @@ -4249,6 +4400,7 @@ const ( type LandlockRulesetAttr struct { Access_fs uint64 Access_net uint64 + Scoped uint64 } type LandlockPathBeneathAttr struct { @@ -4595,7 +4747,7 @@ const ( NL80211_ATTR_MAC_HINT = 0xc8 NL80211_ATTR_MAC_MASK = 0xd7 NL80211_ATTR_MAX_AP_ASSOC_STA = 0xca - NL80211_ATTR_MAX = 0x146 + NL80211_ATTR_MAX = 0x14d NL80211_ATTR_MAX_CRIT_PROT_DURATION = 0xb4 NL80211_ATTR_MAX_CSA_COUNTERS = 0xce NL80211_ATTR_MAX_MATCH_SETS = 0x85 @@ -4861,7 +5013,7 @@ const ( NL80211_BSS_FREQUENCY_OFFSET = 0x14 NL80211_BSS_INFORMATION_ELEMENTS = 0x6 NL80211_BSS_LAST_SEEN_BOOTTIME = 0xf - NL80211_BSS_MAX = 0x16 + NL80211_BSS_MAX = 0x18 NL80211_BSS_MLD_ADDR = 0x16 NL80211_BSS_MLO_LINK_ID = 0x15 NL80211_BSS_PAD = 0x10 @@ -4965,7 +5117,7 @@ const ( NL80211_CMD_LEAVE_IBSS = 0x2c NL80211_CMD_LEAVE_MESH = 0x45 NL80211_CMD_LEAVE_OCB = 0x6d - NL80211_CMD_MAX = 0x9a + NL80211_CMD_MAX = 0x9b NL80211_CMD_MICHAEL_MIC_FAILURE = 0x29 NL80211_CMD_MODIFY_LINK_STA = 0x97 NL80211_CMD_NAN_MATCH = 0x78 @@ -5199,7 +5351,7 @@ const ( NL80211_FREQUENCY_ATTR_GO_CONCURRENT = 0xf NL80211_FREQUENCY_ATTR_INDOOR_ONLY = 0xe NL80211_FREQUENCY_ATTR_IR_CONCURRENT = 0xf - NL80211_FREQUENCY_ATTR_MAX = 0x1c + NL80211_FREQUENCY_ATTR_MAX = 0x21 NL80211_FREQUENCY_ATTR_MAX_TX_POWER = 0x6 NL80211_FREQUENCY_ATTR_NO_10MHZ = 0x11 NL80211_FREQUENCY_ATTR_NO_160MHZ = 0xc @@ -5367,7 +5519,7 @@ const ( NL80211_MNTR_FLAG_CONTROL = 0x3 NL80211_MNTR_FLAG_COOK_FRAMES = 0x5 NL80211_MNTR_FLAG_FCSFAIL = 0x1 - NL80211_MNTR_FLAG_MAX = 0x6 + NL80211_MNTR_FLAG_MAX = 0x7 NL80211_MNTR_FLAG_OTHER_BSS = 0x4 NL80211_MNTR_FLAG_PLCPFAIL = 0x2 NL80211_MPATH_FLAG_ACTIVE = 0x1 @@ -5693,7 +5845,7 @@ const ( NL80211_STA_FLAG_ASSOCIATED = 0x7 NL80211_STA_FLAG_AUTHENTICATED = 0x5 NL80211_STA_FLAG_AUTHORIZED = 0x1 - NL80211_STA_FLAG_MAX = 0x7 + NL80211_STA_FLAG_MAX = 0x8 NL80211_STA_FLAG_MAX_OLD_API = 0x6 NL80211_STA_FLAG_MFP = 0x4 NL80211_STA_FLAG_SHORT_PREAMBLE = 0x2 @@ -5991,3 +6143,36 @@ type CachestatRange struct { Off uint64 Len uint64 } + +const ( + SK_MEMINFO_RMEM_ALLOC = 0x0 + SK_MEMINFO_RCVBUF = 0x1 + SK_MEMINFO_WMEM_ALLOC = 0x2 + SK_MEMINFO_SNDBUF = 0x3 + SK_MEMINFO_FWD_ALLOC = 0x4 + SK_MEMINFO_WMEM_QUEUED = 0x5 + SK_MEMINFO_OPTMEM = 0x6 + SK_MEMINFO_BACKLOG = 0x7 + SK_MEMINFO_DROPS = 0x8 + SK_MEMINFO_VARS = 0x9 + SKNLGRP_NONE = 0x0 + SKNLGRP_INET_TCP_DESTROY = 0x1 + SKNLGRP_INET_UDP_DESTROY = 0x2 + SKNLGRP_INET6_TCP_DESTROY = 0x3 + SKNLGRP_INET6_UDP_DESTROY = 0x4 + SK_DIAG_BPF_STORAGE_REQ_NONE = 0x0 + SK_DIAG_BPF_STORAGE_REQ_MAP_FD = 0x1 + SK_DIAG_BPF_STORAGE_REP_NONE = 0x0 + SK_DIAG_BPF_STORAGE = 0x1 + SK_DIAG_BPF_STORAGE_NONE = 0x0 + SK_DIAG_BPF_STORAGE_PAD = 0x1 + SK_DIAG_BPF_STORAGE_MAP_ID = 0x2 + SK_DIAG_BPF_STORAGE_MAP_VALUE = 0x3 +) + +type SockDiagReq struct { + Family uint8 + Protocol uint8 +} + +const RTM_NEWNVLAN = 0x70 diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_linux_386.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_linux_386.go index 438a30aff..fd402da43 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_linux_386.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_linux_386.go @@ -477,14 +477,6 @@ const ( BLKPG = 0x1269 ) -type XDPUmemReg struct { - Addr uint64 - Len uint64 - Size uint32 - Headroom uint32 - Flags uint32 -} - type CryptoUserAlg struct { Name [64]int8 Driver_name [64]int8 diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go index adceca355..eb7a5e186 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go @@ -492,15 +492,6 @@ const ( BLKPG = 0x1269 ) -type XDPUmemReg struct { - Addr uint64 - Len uint64 - Size uint32 - Headroom uint32 - Flags uint32 - _ [4]byte -} - type CryptoUserAlg struct { Name [64]int8 Driver_name [64]int8 diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go index eeaa00a37..d78ac108b 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go @@ -470,15 +470,6 @@ const ( BLKPG = 0x1269 ) -type XDPUmemReg struct { - Addr uint64 - Len uint64 - Size uint32 - Headroom uint32 - Flags uint32 - _ [4]byte -} - type CryptoUserAlg struct { Name [64]uint8 Driver_name [64]uint8 diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go index 6739aa91d..cd06d47f1 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go @@ -471,15 +471,6 @@ const ( BLKPG = 0x1269 ) -type XDPUmemReg struct { - Addr uint64 - Len uint64 - Size uint32 - Headroom uint32 - Flags uint32 - _ [4]byte -} - type CryptoUserAlg struct { Name [64]int8 Driver_name [64]int8 diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_linux_loong64.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_linux_loong64.go index 9920ef631..2f28fe26c 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_linux_loong64.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_linux_loong64.go @@ -472,15 +472,6 @@ const ( BLKPG = 0x1269 ) -type XDPUmemReg struct { - Addr uint64 - Len uint64 - Size uint32 - Headroom uint32 - Flags uint32 - _ [4]byte -} - type CryptoUserAlg struct { Name [64]int8 Driver_name [64]int8 diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go index 2923b799a..71d6cac2f 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go @@ -476,15 +476,6 @@ const ( BLKPG = 0x20001269 ) -type XDPUmemReg struct { - Addr uint64 - Len uint64 - Size uint32 - Headroom uint32 - Flags uint32 - _ [4]byte -} - type CryptoUserAlg struct { Name [64]int8 Driver_name [64]int8 diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go index ce2750ee4..8596d4535 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go @@ -474,15 +474,6 @@ const ( BLKPG = 0x20001269 ) -type XDPUmemReg struct { - Addr uint64 - Len uint64 - Size uint32 - Headroom uint32 - Flags uint32 - _ [4]byte -} - type CryptoUserAlg struct { Name [64]int8 Driver_name [64]int8 diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go index 3038811d7..cd60ea186 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go @@ -474,15 +474,6 @@ const ( BLKPG = 0x20001269 ) -type XDPUmemReg struct { - Addr uint64 - Len uint64 - Size uint32 - Headroom uint32 - Flags uint32 - _ [4]byte -} - type CryptoUserAlg struct { Name [64]int8 Driver_name [64]int8 diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go index efc6fed18..b0ae420c4 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go @@ -476,15 +476,6 @@ const ( BLKPG = 0x20001269 ) -type XDPUmemReg struct { - Addr uint64 - Len uint64 - Size uint32 - Headroom uint32 - Flags uint32 - _ [4]byte -} - type CryptoUserAlg struct { Name [64]int8 Driver_name [64]int8 diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go index 9a654b75a..835972875 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go @@ -482,15 +482,6 @@ const ( BLKPG = 0x20001269 ) -type XDPUmemReg struct { - Addr uint64 - Len uint64 - Size uint32 - Headroom uint32 - Flags uint32 - _ [4]byte -} - type CryptoUserAlg struct { Name [64]uint8 Driver_name [64]uint8 diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go index 40d358e33..69eb6a5c6 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go @@ -481,15 +481,6 @@ const ( BLKPG = 0x20001269 ) -type XDPUmemReg struct { - Addr uint64 - Len uint64 - Size uint32 - Headroom uint32 - Flags uint32 - _ [4]byte -} - type CryptoUserAlg struct { Name [64]uint8 Driver_name [64]uint8 diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go index 148c6ceb8..5f583cb62 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go @@ -481,15 +481,6 @@ const ( BLKPG = 0x20001269 ) -type XDPUmemReg struct { - Addr uint64 - Len uint64 - Size uint32 - Headroom uint32 - Flags uint32 - _ [4]byte -} - type CryptoUserAlg struct { Name [64]uint8 Driver_name [64]uint8 diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go index 72ba81543..ad05b51a6 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go @@ -499,15 +499,6 @@ const ( BLKPG = 0x1269 ) -type XDPUmemReg struct { - Addr uint64 - Len uint64 - Size uint32 - Headroom uint32 - Flags uint32 - _ [4]byte -} - type CryptoUserAlg struct { Name [64]uint8 Driver_name [64]uint8 @@ -736,6 +727,37 @@ const ( RISCV_HWPROBE_EXT_ZBA = 0x8 RISCV_HWPROBE_EXT_ZBB = 0x10 RISCV_HWPROBE_EXT_ZBS = 0x20 + RISCV_HWPROBE_EXT_ZICBOZ = 0x40 + RISCV_HWPROBE_EXT_ZBC = 0x80 + RISCV_HWPROBE_EXT_ZBKB = 0x100 + RISCV_HWPROBE_EXT_ZBKC = 0x200 + RISCV_HWPROBE_EXT_ZBKX = 0x400 + RISCV_HWPROBE_EXT_ZKND = 0x800 + RISCV_HWPROBE_EXT_ZKNE = 0x1000 + RISCV_HWPROBE_EXT_ZKNH = 0x2000 + RISCV_HWPROBE_EXT_ZKSED = 0x4000 + RISCV_HWPROBE_EXT_ZKSH = 0x8000 + RISCV_HWPROBE_EXT_ZKT = 0x10000 + RISCV_HWPROBE_EXT_ZVBB = 0x20000 + RISCV_HWPROBE_EXT_ZVBC = 0x40000 + RISCV_HWPROBE_EXT_ZVKB = 0x80000 + RISCV_HWPROBE_EXT_ZVKG = 0x100000 + RISCV_HWPROBE_EXT_ZVKNED = 0x200000 + RISCV_HWPROBE_EXT_ZVKNHA = 0x400000 + RISCV_HWPROBE_EXT_ZVKNHB = 0x800000 + RISCV_HWPROBE_EXT_ZVKSED = 0x1000000 + RISCV_HWPROBE_EXT_ZVKSH = 0x2000000 + RISCV_HWPROBE_EXT_ZVKT = 0x4000000 + RISCV_HWPROBE_EXT_ZFH = 0x8000000 + RISCV_HWPROBE_EXT_ZFHMIN = 0x10000000 + RISCV_HWPROBE_EXT_ZIHINTNTL = 0x20000000 + RISCV_HWPROBE_EXT_ZVFH = 0x40000000 + RISCV_HWPROBE_EXT_ZVFHMIN = 0x80000000 + RISCV_HWPROBE_EXT_ZFA = 0x100000000 + RISCV_HWPROBE_EXT_ZTSO = 0x200000000 + RISCV_HWPROBE_EXT_ZACAS = 0x400000000 + RISCV_HWPROBE_EXT_ZICOND = 0x800000000 + RISCV_HWPROBE_EXT_ZIHINTPAUSE = 0x1000000000 RISCV_HWPROBE_KEY_CPUPERF_0 = 0x5 RISCV_HWPROBE_MISALIGNED_UNKNOWN = 0x0 RISCV_HWPROBE_MISALIGNED_EMULATED = 0x1 @@ -743,4 +765,6 @@ const ( RISCV_HWPROBE_MISALIGNED_FAST = 0x3 RISCV_HWPROBE_MISALIGNED_UNSUPPORTED = 0x4 RISCV_HWPROBE_MISALIGNED_MASK = 0x7 + RISCV_HWPROBE_KEY_ZICBOZ_BLOCK_SIZE = 0x6 + RISCV_HWPROBE_WHICH_CPUS = 0x1 ) diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go index 71e765508..cf3ce9003 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go @@ -495,15 +495,6 @@ const ( BLKPG = 0x1269 ) -type XDPUmemReg struct { - Addr uint64 - Len uint64 - Size uint32 - Headroom uint32 - Flags uint32 - _ [4]byte -} - type CryptoUserAlg struct { Name [64]int8 Driver_name [64]int8 diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go index 4abbdb9de..590b56739 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go @@ -476,15 +476,6 @@ const ( BLKPG = 0x20001269 ) -type XDPUmemReg struct { - Addr uint64 - Len uint64 - Size uint32 - Headroom uint32 - Flags uint32 - _ [4]byte -} - type CryptoUserAlg struct { Name [64]int8 Driver_name [64]int8 diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_zos_s390x.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_zos_s390x.go index 54f31be63..2e5d5a443 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_zos_s390x.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/unix/ztypes_zos_s390x.go @@ -25,10 +25,13 @@ const ( SizeofIPv6Mreq = 20 SizeofICMPv6Filter = 32 SizeofIPv6MTUInfo = 32 + SizeofInet4Pktinfo = 8 + SizeofInet6Pktinfo = 20 SizeofLinger = 8 SizeofSockaddrInet4 = 16 SizeofSockaddrInet6 = 28 SizeofTCPInfo = 0x68 + SizeofUcred = 12 ) type ( @@ -69,12 +72,17 @@ type Utimbuf struct { } type Utsname struct { - Sysname [65]byte - Nodename [65]byte - Release [65]byte - Version [65]byte - Machine [65]byte - Domainname [65]byte + Sysname [16]byte + Nodename [32]byte + Release [8]byte + Version [8]byte + Machine [16]byte +} + +type Ucred struct { + Pid int32 + Uid uint32 + Gid uint32 } type RawSockaddrInet4 struct { @@ -325,7 +333,7 @@ type Statvfs_t struct { } type Statfs_t struct { - Type uint32 + Type uint64 Bsize uint64 Blocks uint64 Bfree uint64 @@ -336,6 +344,7 @@ type Statfs_t struct { Namelen uint64 Frsize uint64 Flags uint64 + _ [4]uint64 } type direntLE struct { @@ -368,6 +377,12 @@ type Flock_t struct { Pid int32 } +type F_cnvrt struct { + Cvtcmd int32 + Pccsid int16 + Fccsid int16 +} + type Termios struct { Cflag uint32 Iflag uint32 @@ -412,3 +427,126 @@ type W_Mntent struct { Quiesceowner [8]byte _ [38]byte } + +type EpollEvent struct { + Events uint32 + _ int32 + Fd int32 + Pad int32 +} + +type InotifyEvent struct { + Wd int32 + Mask uint32 + Cookie uint32 + Len uint32 + Name string +} + +const ( + SizeofInotifyEvent = 0x10 +) + +type ConsMsg2 struct { + Cm2Format uint16 + Cm2R1 uint16 + Cm2Msglength uint32 + Cm2Msg *byte + Cm2R2 [4]byte + Cm2R3 [4]byte + Cm2Routcde *uint32 + Cm2Descr *uint32 + Cm2Msgflag uint32 + Cm2Token uint32 + Cm2Msgid *uint32 + Cm2R4 [4]byte + Cm2DomToken uint32 + Cm2DomMsgid *uint32 + Cm2ModCartptr *byte + Cm2ModConsidptr *byte + Cm2MsgCart [8]byte + Cm2MsgConsid [4]byte + Cm2R5 [12]byte +} + +const ( + CC_modify = 1 + CC_stop = 2 + CONSOLE_FORMAT_2 = 2 + CONSOLE_FORMAT_3 = 3 + CONSOLE_HRDCPY = 0x80000000 +) + +type OpenHow struct { + Flags uint64 + Mode uint64 + Resolve uint64 +} + +const SizeofOpenHow = 0x18 + +const ( + RESOLVE_CACHED = 0x20 + RESOLVE_BENEATH = 0x8 + RESOLVE_IN_ROOT = 0x10 + RESOLVE_NO_MAGICLINKS = 0x2 + RESOLVE_NO_SYMLINKS = 0x4 + RESOLVE_NO_XDEV = 0x1 +) + +type Siginfo struct { + Signo int32 + Errno int32 + Code int32 + Pid int32 + Uid uint32 + _ [44]byte +} + +type SysvIpcPerm struct { + Uid uint32 + Gid uint32 + Cuid uint32 + Cgid uint32 + Mode int32 +} + +type SysvShmDesc struct { + Perm SysvIpcPerm + _ [4]byte + Lpid int32 + Cpid int32 + Nattch uint32 + _ [4]byte + _ [4]byte + _ [4]byte + _ int32 + _ uint8 + _ uint8 + _ uint16 + _ *byte + Segsz uint64 + Atime Time_t + Dtime Time_t + Ctime Time_t +} + +type SysvShmDesc64 struct { + Perm SysvIpcPerm + _ [4]byte + Lpid int32 + Cpid int32 + Nattch uint32 + _ [4]byte + _ [4]byte + _ [4]byte + _ int32 + _ byte + _ uint8 + _ uint16 + _ *byte + Segsz uint64 + Atime int64 + Dtime int64 + Ctime int64 +} diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/windows/aliases.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/windows/aliases.go index ce2d713d6..16f90560a 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/windows/aliases.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/windows/aliases.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build windows && go1.9 +//go:build windows package windows diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/windows/dll_windows.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/windows/dll_windows.go index 115341fba..3ca814f54 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/windows/dll_windows.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/windows/dll_windows.go @@ -43,8 +43,8 @@ type DLL struct { // LoadDLL loads DLL file into memory. // // Warning: using LoadDLL without an absolute path name is subject to -// DLL preloading attacks. To safely load a system DLL, use LazyDLL -// with System set to true, or use LoadLibraryEx directly. +// DLL preloading attacks. To safely load a system DLL, use [NewLazySystemDLL], +// or use [LoadLibraryEx] directly. func LoadDLL(name string) (dll *DLL, err error) { namep, err := UTF16PtrFromString(name) if err != nil { @@ -65,7 +65,7 @@ func LoadDLL(name string) (dll *DLL, err error) { return d, nil } -// MustLoadDLL is like LoadDLL but panics if load operation failes. +// MustLoadDLL is like LoadDLL but panics if load operation fails. func MustLoadDLL(name string) *DLL { d, e := LoadDLL(name) if e != nil { @@ -271,6 +271,9 @@ func (d *LazyDLL) NewProc(name string) *LazyProc { } // NewLazyDLL creates new LazyDLL associated with DLL file. +// +// Warning: using NewLazyDLL without an absolute path name is subject to +// DLL preloading attacks. To safely load a system DLL, use [NewLazySystemDLL]. func NewLazyDLL(name string) *LazyDLL { return &LazyDLL{Name: name} } @@ -410,7 +413,3 @@ func loadLibraryEx(name string, system bool) (*DLL, error) { } return &DLL{Name: name, Handle: h}, nil } - -type errString string - -func (s errString) Error() string { return string(s) } diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/windows/empty.s b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/windows/empty.s deleted file mode 100644 index ba64caca5..000000000 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/windows/empty.s +++ /dev/null @@ -1,8 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !go1.12 - -// This file is here to allow bodyless functions with go:linkname for Go 1.11 -// and earlier (see https://golang.org/issue/23311). diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/windows/security_windows.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/windows/security_windows.go index 26be94a8a..b6e1ab76f 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/windows/security_windows.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/windows/security_windows.go @@ -68,6 +68,7 @@ type UserInfo10 struct { //sys NetUserGetInfo(serverName *uint16, userName *uint16, level uint32, buf **byte) (neterr error) = netapi32.NetUserGetInfo //sys NetGetJoinInformation(server *uint16, name **uint16, bufType *uint32) (neterr error) = netapi32.NetGetJoinInformation //sys NetApiBufferFree(buf *byte) (neterr error) = netapi32.NetApiBufferFree +//sys NetUserEnum(serverName *uint16, level uint32, filter uint32, buf **byte, prefMaxLen uint32, entriesRead *uint32, totalEntries *uint32, resumeHandle *uint32) (neterr error) = netapi32.NetUserEnum const ( // do not reorder @@ -893,7 +894,7 @@ type ACL struct { aclRevision byte sbz1 byte aclSize uint16 - aceCount uint16 + AceCount uint16 sbz2 uint16 } @@ -1086,6 +1087,27 @@ type EXPLICIT_ACCESS struct { Trustee TRUSTEE } +// https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-ace_header +type ACE_HEADER struct { + AceType uint8 + AceFlags uint8 + AceSize uint16 +} + +// https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-access_allowed_ace +type ACCESS_ALLOWED_ACE struct { + Header ACE_HEADER + Mask ACCESS_MASK + SidStart uint32 +} + +const ( + // Constants for AceType + // https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-ace_header + ACCESS_ALLOWED_ACE_TYPE = 0 + ACCESS_DENIED_ACE_TYPE = 1 +) + // This type is the union inside of TRUSTEE and must be created using one of the TrusteeValueFrom* functions. type TrusteeValue uintptr @@ -1157,6 +1179,7 @@ type OBJECTS_AND_NAME struct { //sys makeSelfRelativeSD(absoluteSD *SECURITY_DESCRIPTOR, selfRelativeSD *SECURITY_DESCRIPTOR, selfRelativeSDSize *uint32) (err error) = advapi32.MakeSelfRelativeSD //sys setEntriesInAcl(countExplicitEntries uint32, explicitEntries *EXPLICIT_ACCESS, oldACL *ACL, newACL **ACL) (ret error) = advapi32.SetEntriesInAclW +//sys GetAce(acl *ACL, aceIndex uint32, pAce **ACCESS_ALLOWED_ACE) (err error) = advapi32.GetAce // Control returns the security descriptor control bits. func (sd *SECURITY_DESCRIPTOR) Control() (control SECURITY_DESCRIPTOR_CONTROL, revision uint32, err error) { diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/windows/syscall_windows.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/windows/syscall_windows.go index 6395a031d..4a3254386 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/windows/syscall_windows.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/windows/syscall_windows.go @@ -17,8 +17,10 @@ import ( "unsafe" ) -type Handle uintptr -type HWND uintptr +type ( + Handle uintptr + HWND uintptr +) const ( InvalidHandle = ^Handle(0) @@ -165,6 +167,9 @@ func NewCallbackCDecl(fn interface{}) uintptr { //sys CreateFile(name *uint16, access uint32, mode uint32, sa *SecurityAttributes, createmode uint32, attrs uint32, templatefile Handle) (handle Handle, err error) [failretval==InvalidHandle] = CreateFileW //sys CreateNamedPipe(name *uint16, flags uint32, pipeMode uint32, maxInstances uint32, outSize uint32, inSize uint32, defaultTimeout uint32, sa *SecurityAttributes) (handle Handle, err error) [failretval==InvalidHandle] = CreateNamedPipeW //sys ConnectNamedPipe(pipe Handle, overlapped *Overlapped) (err error) +//sys DisconnectNamedPipe(pipe Handle) (err error) +//sys GetNamedPipeClientProcessId(pipe Handle, clientProcessID *uint32) (err error) +//sys GetNamedPipeServerProcessId(pipe Handle, serverProcessID *uint32) (err error) //sys GetNamedPipeInfo(pipe Handle, flags *uint32, outSize *uint32, inSize *uint32, maxInstances *uint32) (err error) //sys GetNamedPipeHandleState(pipe Handle, state *uint32, curInstances *uint32, maxCollectionCount *uint32, collectDataTimeout *uint32, userName *uint16, maxUserNameSize uint32) (err error) = GetNamedPipeHandleStateW //sys SetNamedPipeHandleState(pipe Handle, state *uint32, maxCollectionCount *uint32, collectDataTimeout *uint32) (err error) = SetNamedPipeHandleState @@ -210,6 +215,10 @@ func NewCallbackCDecl(fn interface{}) uintptr { //sys OpenProcess(desiredAccess uint32, inheritHandle bool, processId uint32) (handle Handle, err error) //sys ShellExecute(hwnd Handle, verb *uint16, file *uint16, args *uint16, cwd *uint16, showCmd int32) (err error) [failretval<=32] = shell32.ShellExecuteW //sys GetWindowThreadProcessId(hwnd HWND, pid *uint32) (tid uint32, err error) = user32.GetWindowThreadProcessId +//sys LoadKeyboardLayout(name *uint16, flags uint32) (hkl Handle, err error) [failretval==0] = user32.LoadKeyboardLayoutW +//sys UnloadKeyboardLayout(hkl Handle) (err error) = user32.UnloadKeyboardLayout +//sys GetKeyboardLayout(tid uint32) (hkl Handle) = user32.GetKeyboardLayout +//sys ToUnicodeEx(vkey uint32, scancode uint32, keystate *byte, pwszBuff *uint16, cchBuff int32, flags uint32, hkl Handle) (ret int32) = user32.ToUnicodeEx //sys GetShellWindow() (shellWindow HWND) = user32.GetShellWindow //sys MessageBox(hwnd HWND, text *uint16, caption *uint16, boxtype uint32) (ret int32, err error) [failretval==0] = user32.MessageBoxW //sys ExitWindowsEx(flags uint32, reason uint32) (err error) = user32.ExitWindowsEx @@ -306,6 +315,10 @@ func NewCallbackCDecl(fn interface{}) uintptr { //sys SetConsoleMode(console Handle, mode uint32) (err error) = kernel32.SetConsoleMode //sys GetConsoleScreenBufferInfo(console Handle, info *ConsoleScreenBufferInfo) (err error) = kernel32.GetConsoleScreenBufferInfo //sys setConsoleCursorPosition(console Handle, position uint32) (err error) = kernel32.SetConsoleCursorPosition +//sys GetConsoleCP() (cp uint32, err error) = kernel32.GetConsoleCP +//sys GetConsoleOutputCP() (cp uint32, err error) = kernel32.GetConsoleOutputCP +//sys SetConsoleCP(cp uint32) (err error) = kernel32.SetConsoleCP +//sys SetConsoleOutputCP(cp uint32) (err error) = kernel32.SetConsoleOutputCP //sys WriteConsole(console Handle, buf *uint16, towrite uint32, written *uint32, reserved *byte) (err error) = kernel32.WriteConsoleW //sys ReadConsole(console Handle, buf *uint16, toread uint32, read *uint32, inputControl *byte) (err error) = kernel32.ReadConsoleW //sys resizePseudoConsole(pconsole Handle, size uint32) (hr error) = kernel32.ResizePseudoConsole @@ -348,8 +361,19 @@ func NewCallbackCDecl(fn interface{}) uintptr { //sys SetProcessPriorityBoost(process Handle, disable bool) (err error) = kernel32.SetProcessPriorityBoost //sys GetProcessWorkingSetSizeEx(hProcess Handle, lpMinimumWorkingSetSize *uintptr, lpMaximumWorkingSetSize *uintptr, flags *uint32) //sys SetProcessWorkingSetSizeEx(hProcess Handle, dwMinimumWorkingSetSize uintptr, dwMaximumWorkingSetSize uintptr, flags uint32) (err error) +//sys ClearCommBreak(handle Handle) (err error) +//sys ClearCommError(handle Handle, lpErrors *uint32, lpStat *ComStat) (err error) +//sys EscapeCommFunction(handle Handle, dwFunc uint32) (err error) +//sys GetCommState(handle Handle, lpDCB *DCB) (err error) +//sys GetCommModemStatus(handle Handle, lpModemStat *uint32) (err error) //sys GetCommTimeouts(handle Handle, timeouts *CommTimeouts) (err error) +//sys PurgeComm(handle Handle, dwFlags uint32) (err error) +//sys SetCommBreak(handle Handle) (err error) +//sys SetCommMask(handle Handle, dwEvtMask uint32) (err error) +//sys SetCommState(handle Handle, lpDCB *DCB) (err error) //sys SetCommTimeouts(handle Handle, timeouts *CommTimeouts) (err error) +//sys SetupComm(handle Handle, dwInQueue uint32, dwOutQueue uint32) (err error) +//sys WaitCommEvent(handle Handle, lpEvtMask *uint32, lpOverlapped *Overlapped) (err error) //sys GetActiveProcessorCount(groupNumber uint16) (ret uint32) //sys GetMaximumProcessorCount(groupNumber uint16) (ret uint32) //sys EnumWindows(enumFunc uintptr, param unsafe.Pointer) (err error) = user32.EnumWindows @@ -703,20 +727,12 @@ func DurationSinceBoot() time.Duration { } func Ftruncate(fd Handle, length int64) (err error) { - curoffset, e := Seek(fd, 0, 1) - if e != nil { - return e + type _FILE_END_OF_FILE_INFO struct { + EndOfFile int64 } - defer Seek(fd, curoffset, 0) - _, e = Seek(fd, length, 0) - if e != nil { - return e - } - e = SetEndOfFile(fd) - if e != nil { - return e - } - return nil + var info _FILE_END_OF_FILE_INFO + info.EndOfFile = length + return SetFileInformationByHandle(fd, FileEndOfFileInfo, (*byte)(unsafe.Pointer(&info)), uint32(unsafe.Sizeof(info))) } func Gettimeofday(tv *Timeval) (err error) { @@ -872,6 +888,11 @@ const socket_error = uintptr(^uint32(0)) //sys GetACP() (acp uint32) = kernel32.GetACP //sys MultiByteToWideChar(codePage uint32, dwFlags uint32, str *byte, nstr int32, wchar *uint16, nwchar int32) (nwrite int32, err error) = kernel32.MultiByteToWideChar //sys getBestInterfaceEx(sockaddr unsafe.Pointer, pdwBestIfIndex *uint32) (errcode error) = iphlpapi.GetBestInterfaceEx +//sys GetIfEntry2Ex(level uint32, row *MibIfRow2) (errcode error) = iphlpapi.GetIfEntry2Ex +//sys GetUnicastIpAddressEntry(row *MibUnicastIpAddressRow) (errcode error) = iphlpapi.GetUnicastIpAddressEntry +//sys NotifyIpInterfaceChange(family uint16, callback uintptr, callerContext unsafe.Pointer, initialNotification bool, notificationHandle *Handle) (errcode error) = iphlpapi.NotifyIpInterfaceChange +//sys NotifyUnicastIpAddressChange(family uint16, callback uintptr, callerContext unsafe.Pointer, initialNotification bool, notificationHandle *Handle) (errcode error) = iphlpapi.NotifyUnicastIpAddressChange +//sys CancelMibChangeNotify2(notificationHandle Handle) (errcode error) = iphlpapi.CancelMibChangeNotify2 // For testing: clients can set this flag to force // creation of IPv6 sockets to return EAFNOSUPPORT. @@ -1356,9 +1377,11 @@ func SetsockoptLinger(fd Handle, level, opt int, l *Linger) (err error) { func SetsockoptInet4Addr(fd Handle, level, opt int, value [4]byte) (err error) { return Setsockopt(fd, int32(level), int32(opt), (*byte)(unsafe.Pointer(&value[0])), 4) } + func SetsockoptIPMreq(fd Handle, level, opt int, mreq *IPMreq) (err error) { return Setsockopt(fd, int32(level), int32(opt), (*byte)(unsafe.Pointer(mreq)), int32(unsafe.Sizeof(*mreq))) } + func SetsockoptIPv6Mreq(fd Handle, level, opt int, mreq *IPv6Mreq) (err error) { return syscall.EWINDOWS } @@ -1661,13 +1684,16 @@ func (s NTStatus) Error() string { // do not use NTUnicodeString, and instead UTF16PtrFromString should be used for // the more common *uint16 string type. func NewNTUnicodeString(s string) (*NTUnicodeString, error) { - var u NTUnicodeString - s16, err := UTF16PtrFromString(s) + s16, err := UTF16FromString(s) if err != nil { return nil, err } - RtlInitUnicodeString(&u, s16) - return &u, nil + n := uint16(len(s16) * 2) + return &NTUnicodeString{ + Length: n - 2, // subtract 2 bytes for the NULL terminator + MaximumLength: n, + Buffer: &s16[0], + }, nil } // Slice returns a uint16 slice that aliases the data in the NTUnicodeString. @@ -1834,3 +1860,73 @@ func ResizePseudoConsole(pconsole Handle, size Coord) error { // accept arguments that can be casted to uintptr, and Coord can't. return resizePseudoConsole(pconsole, *((*uint32)(unsafe.Pointer(&size)))) } + +// DCB constants. See https://learn.microsoft.com/en-us/windows/win32/api/winbase/ns-winbase-dcb. +const ( + CBR_110 = 110 + CBR_300 = 300 + CBR_600 = 600 + CBR_1200 = 1200 + CBR_2400 = 2400 + CBR_4800 = 4800 + CBR_9600 = 9600 + CBR_14400 = 14400 + CBR_19200 = 19200 + CBR_38400 = 38400 + CBR_57600 = 57600 + CBR_115200 = 115200 + CBR_128000 = 128000 + CBR_256000 = 256000 + + DTR_CONTROL_DISABLE = 0x00000000 + DTR_CONTROL_ENABLE = 0x00000010 + DTR_CONTROL_HANDSHAKE = 0x00000020 + + RTS_CONTROL_DISABLE = 0x00000000 + RTS_CONTROL_ENABLE = 0x00001000 + RTS_CONTROL_HANDSHAKE = 0x00002000 + RTS_CONTROL_TOGGLE = 0x00003000 + + NOPARITY = 0 + ODDPARITY = 1 + EVENPARITY = 2 + MARKPARITY = 3 + SPACEPARITY = 4 + + ONESTOPBIT = 0 + ONE5STOPBITS = 1 + TWOSTOPBITS = 2 +) + +// EscapeCommFunction constants. See https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-escapecommfunction. +const ( + SETXOFF = 1 + SETXON = 2 + SETRTS = 3 + CLRRTS = 4 + SETDTR = 5 + CLRDTR = 6 + SETBREAK = 8 + CLRBREAK = 9 +) + +// PurgeComm constants. See https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-purgecomm. +const ( + PURGE_TXABORT = 0x0001 + PURGE_RXABORT = 0x0002 + PURGE_TXCLEAR = 0x0004 + PURGE_RXCLEAR = 0x0008 +) + +// SetCommMask constants. See https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-setcommmask. +const ( + EV_RXCHAR = 0x0001 + EV_RXFLAG = 0x0002 + EV_TXEMPTY = 0x0004 + EV_CTS = 0x0008 + EV_DSR = 0x0010 + EV_RLSD = 0x0020 + EV_BREAK = 0x0040 + EV_ERR = 0x0080 + EV_RING = 0x0100 +) diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/windows/types_windows.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/windows/types_windows.go index 359780f6a..9d138de5f 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/windows/types_windows.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/windows/types_windows.go @@ -176,6 +176,7 @@ const ( WAIT_FAILED = 0xFFFFFFFF // Access rights for process. + PROCESS_ALL_ACCESS = 0xFFFF PROCESS_CREATE_PROCESS = 0x0080 PROCESS_CREATE_THREAD = 0x0002 PROCESS_DUP_HANDLE = 0x0040 @@ -1060,6 +1061,7 @@ const ( SIO_GET_EXTENSION_FUNCTION_POINTER = IOC_INOUT | IOC_WS2 | 6 SIO_KEEPALIVE_VALS = IOC_IN | IOC_VENDOR | 4 SIO_UDP_CONNRESET = IOC_IN | IOC_VENDOR | 12 + SIO_UDP_NETRESET = IOC_IN | IOC_VENDOR | 15 // cf. http://support.microsoft.com/default.aspx?scid=kb;en-us;257460 @@ -2003,7 +2005,21 @@ const ( MOVEFILE_FAIL_IF_NOT_TRACKABLE = 0x20 ) -const GAA_FLAG_INCLUDE_PREFIX = 0x00000010 +// Flags for GetAdaptersAddresses, see +// https://learn.microsoft.com/en-us/windows/win32/api/iphlpapi/nf-iphlpapi-getadaptersaddresses. +const ( + GAA_FLAG_SKIP_UNICAST = 0x1 + GAA_FLAG_SKIP_ANYCAST = 0x2 + GAA_FLAG_SKIP_MULTICAST = 0x4 + GAA_FLAG_SKIP_DNS_SERVER = 0x8 + GAA_FLAG_INCLUDE_PREFIX = 0x10 + GAA_FLAG_SKIP_FRIENDLY_NAME = 0x20 + GAA_FLAG_INCLUDE_WINS_INFO = 0x40 + GAA_FLAG_INCLUDE_GATEWAYS = 0x80 + GAA_FLAG_INCLUDE_ALL_INTERFACES = 0x100 + GAA_FLAG_INCLUDE_ALL_COMPARTMENTS = 0x200 + GAA_FLAG_INCLUDE_TUNNEL_BINDINGORDER = 0x400 +) const ( IF_TYPE_OTHER = 1 @@ -2017,6 +2033,50 @@ const ( IF_TYPE_IEEE1394 = 144 ) +// Enum NL_PREFIX_ORIGIN for [IpAdapterUnicastAddress], see +// https://learn.microsoft.com/en-us/windows/win32/api/nldef/ne-nldef-nl_prefix_origin +const ( + IpPrefixOriginOther = 0 + IpPrefixOriginManual = 1 + IpPrefixOriginWellKnown = 2 + IpPrefixOriginDhcp = 3 + IpPrefixOriginRouterAdvertisement = 4 + IpPrefixOriginUnchanged = 1 << 4 +) + +// Enum NL_SUFFIX_ORIGIN for [IpAdapterUnicastAddress], see +// https://learn.microsoft.com/en-us/windows/win32/api/nldef/ne-nldef-nl_suffix_origin +const ( + NlsoOther = 0 + NlsoManual = 1 + NlsoWellKnown = 2 + NlsoDhcp = 3 + NlsoLinkLayerAddress = 4 + NlsoRandom = 5 + IpSuffixOriginOther = 0 + IpSuffixOriginManual = 1 + IpSuffixOriginWellKnown = 2 + IpSuffixOriginDhcp = 3 + IpSuffixOriginLinkLayerAddress = 4 + IpSuffixOriginRandom = 5 + IpSuffixOriginUnchanged = 1 << 4 +) + +// Enum NL_DAD_STATE for [IpAdapterUnicastAddress], see +// https://learn.microsoft.com/en-us/windows/win32/api/nldef/ne-nldef-nl_dad_state +const ( + NldsInvalid = 0 + NldsTentative = 1 + NldsDuplicate = 2 + NldsDeprecated = 3 + NldsPreferred = 4 + IpDadStateInvalid = 0 + IpDadStateTentative = 1 + IpDadStateDuplicate = 2 + IpDadStateDeprecated = 3 + IpDadStatePreferred = 4 +) + type SocketAddress struct { Sockaddr *syscall.RawSockaddrAny SockaddrLength int32 @@ -2144,6 +2204,132 @@ const ( IfOperStatusLowerLayerDown = 7 ) +const ( + IF_MAX_PHYS_ADDRESS_LENGTH = 32 + IF_MAX_STRING_SIZE = 256 +) + +// MIB_IF_ENTRY_LEVEL enumeration from netioapi.h or +// https://learn.microsoft.com/en-us/windows/win32/api/netioapi/nf-netioapi-getifentry2ex. +const ( + MibIfEntryNormal = 0 + MibIfEntryNormalWithoutStatistics = 2 +) + +// MIB_NOTIFICATION_TYPE enumeration from netioapi.h or +// https://learn.microsoft.com/en-us/windows/win32/api/netioapi/ne-netioapi-mib_notification_type. +const ( + MibParameterNotification = 0 + MibAddInstance = 1 + MibDeleteInstance = 2 + MibInitialNotification = 3 +) + +// MibIfRow2 stores information about a particular interface. See +// https://learn.microsoft.com/en-us/windows/win32/api/netioapi/ns-netioapi-mib_if_row2. +type MibIfRow2 struct { + InterfaceLuid uint64 + InterfaceIndex uint32 + InterfaceGuid GUID + Alias [IF_MAX_STRING_SIZE + 1]uint16 + Description [IF_MAX_STRING_SIZE + 1]uint16 + PhysicalAddressLength uint32 + PhysicalAddress [IF_MAX_PHYS_ADDRESS_LENGTH]uint8 + PermanentPhysicalAddress [IF_MAX_PHYS_ADDRESS_LENGTH]uint8 + Mtu uint32 + Type uint32 + TunnelType uint32 + MediaType uint32 + PhysicalMediumType uint32 + AccessType uint32 + DirectionType uint32 + InterfaceAndOperStatusFlags uint8 + OperStatus uint32 + AdminStatus uint32 + MediaConnectState uint32 + NetworkGuid GUID + ConnectionType uint32 + TransmitLinkSpeed uint64 + ReceiveLinkSpeed uint64 + InOctets uint64 + InUcastPkts uint64 + InNUcastPkts uint64 + InDiscards uint64 + InErrors uint64 + InUnknownProtos uint64 + InUcastOctets uint64 + InMulticastOctets uint64 + InBroadcastOctets uint64 + OutOctets uint64 + OutUcastPkts uint64 + OutNUcastPkts uint64 + OutDiscards uint64 + OutErrors uint64 + OutUcastOctets uint64 + OutMulticastOctets uint64 + OutBroadcastOctets uint64 + OutQLen uint64 +} + +// MIB_UNICASTIPADDRESS_ROW stores information about a unicast IP address. See +// https://learn.microsoft.com/en-us/windows/win32/api/netioapi/ns-netioapi-mib_unicastipaddress_row. +type MibUnicastIpAddressRow struct { + Address RawSockaddrInet6 // SOCKADDR_INET union + InterfaceLuid uint64 + InterfaceIndex uint32 + PrefixOrigin uint32 + SuffixOrigin uint32 + ValidLifetime uint32 + PreferredLifetime uint32 + OnLinkPrefixLength uint8 + SkipAsSource uint8 + DadState uint32 + ScopeId uint32 + CreationTimeStamp Filetime +} + +const ScopeLevelCount = 16 + +// MIB_IPINTERFACE_ROW stores interface management information for a particular IP address family on a network interface. +// See https://learn.microsoft.com/en-us/windows/win32/api/netioapi/ns-netioapi-mib_ipinterface_row. +type MibIpInterfaceRow struct { + Family uint16 + InterfaceLuid uint64 + InterfaceIndex uint32 + MaxReassemblySize uint32 + InterfaceIdentifier uint64 + MinRouterAdvertisementInterval uint32 + MaxRouterAdvertisementInterval uint32 + AdvertisingEnabled uint8 + ForwardingEnabled uint8 + WeakHostSend uint8 + WeakHostReceive uint8 + UseAutomaticMetric uint8 + UseNeighborUnreachabilityDetection uint8 + ManagedAddressConfigurationSupported uint8 + OtherStatefulConfigurationSupported uint8 + AdvertiseDefaultRoute uint8 + RouterDiscoveryBehavior uint32 + DadTransmits uint32 + BaseReachableTime uint32 + RetransmitTime uint32 + PathMtuDiscoveryTimeout uint32 + LinkLocalAddressBehavior uint32 + LinkLocalAddressTimeout uint32 + ZoneIndices [ScopeLevelCount]uint32 + SitePrefixLength uint32 + Metric uint32 + NlMtu uint32 + Connected uint8 + SupportsWakeUpPatterns uint8 + SupportsNeighborDiscovery uint8 + SupportsRouterDiscovery uint8 + ReachableTime uint32 + TransmitOffload uint32 + ReceiveOffload uint32 + DisableDefaultRoutes uint8 +} + // Console related constants used for the mode parameter to SetConsoleMode. See // https://docs.microsoft.com/en-us/windows/console/setconsolemode for details. @@ -3380,3 +3566,38 @@ type BLOB struct { Size uint32 BlobData *byte } + +type ComStat struct { + Flags uint32 + CBInQue uint32 + CBOutQue uint32 +} + +type DCB struct { + DCBlength uint32 + BaudRate uint32 + Flags uint32 + wReserved uint16 + XonLim uint16 + XoffLim uint16 + ByteSize uint8 + Parity uint8 + StopBits uint8 + XonChar byte + XoffChar byte + ErrorChar byte + EofChar byte + EvtChar byte + wReserved1 uint16 +} + +// Keyboard Layout Flags. +// See https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-loadkeyboardlayoutw +const ( + KLF_ACTIVATE = 0x00000001 + KLF_SUBSTITUTE_OK = 0x00000002 + KLF_REORDER = 0x00000008 + KLF_REPLACELANG = 0x00000010 + KLF_NOTELLSHELL = 0x00000080 + KLF_SETFORPROCESS = 0x00000100 +) diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/windows/zsyscall_windows.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/windows/zsyscall_windows.go index e8791c82c..01c0716c2 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/windows/zsyscall_windows.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/sys/windows/zsyscall_windows.go @@ -91,6 +91,7 @@ var ( procEnumServicesStatusExW = modadvapi32.NewProc("EnumServicesStatusExW") procEqualSid = modadvapi32.NewProc("EqualSid") procFreeSid = modadvapi32.NewProc("FreeSid") + procGetAce = modadvapi32.NewProc("GetAce") procGetLengthSid = modadvapi32.NewProc("GetLengthSid") procGetNamedSecurityInfoW = modadvapi32.NewProc("GetNamedSecurityInfoW") procGetSecurityDescriptorControl = modadvapi32.NewProc("GetSecurityDescriptorControl") @@ -180,14 +181,21 @@ var ( procDnsRecordListFree = moddnsapi.NewProc("DnsRecordListFree") procDwmGetWindowAttribute = moddwmapi.NewProc("DwmGetWindowAttribute") procDwmSetWindowAttribute = moddwmapi.NewProc("DwmSetWindowAttribute") + procCancelMibChangeNotify2 = modiphlpapi.NewProc("CancelMibChangeNotify2") procGetAdaptersAddresses = modiphlpapi.NewProc("GetAdaptersAddresses") procGetAdaptersInfo = modiphlpapi.NewProc("GetAdaptersInfo") procGetBestInterfaceEx = modiphlpapi.NewProc("GetBestInterfaceEx") procGetIfEntry = modiphlpapi.NewProc("GetIfEntry") + procGetIfEntry2Ex = modiphlpapi.NewProc("GetIfEntry2Ex") + procGetUnicastIpAddressEntry = modiphlpapi.NewProc("GetUnicastIpAddressEntry") + procNotifyIpInterfaceChange = modiphlpapi.NewProc("NotifyIpInterfaceChange") + procNotifyUnicastIpAddressChange = modiphlpapi.NewProc("NotifyUnicastIpAddressChange") procAddDllDirectory = modkernel32.NewProc("AddDllDirectory") procAssignProcessToJobObject = modkernel32.NewProc("AssignProcessToJobObject") procCancelIo = modkernel32.NewProc("CancelIo") procCancelIoEx = modkernel32.NewProc("CancelIoEx") + procClearCommBreak = modkernel32.NewProc("ClearCommBreak") + procClearCommError = modkernel32.NewProc("ClearCommError") procCloseHandle = modkernel32.NewProc("CloseHandle") procClosePseudoConsole = modkernel32.NewProc("ClosePseudoConsole") procConnectNamedPipe = modkernel32.NewProc("ConnectNamedPipe") @@ -212,7 +220,9 @@ var ( procDeleteProcThreadAttributeList = modkernel32.NewProc("DeleteProcThreadAttributeList") procDeleteVolumeMountPointW = modkernel32.NewProc("DeleteVolumeMountPointW") procDeviceIoControl = modkernel32.NewProc("DeviceIoControl") + procDisconnectNamedPipe = modkernel32.NewProc("DisconnectNamedPipe") procDuplicateHandle = modkernel32.NewProc("DuplicateHandle") + procEscapeCommFunction = modkernel32.NewProc("EscapeCommFunction") procExitProcess = modkernel32.NewProc("ExitProcess") procExpandEnvironmentStringsW = modkernel32.NewProc("ExpandEnvironmentStringsW") procFindClose = modkernel32.NewProc("FindClose") @@ -236,11 +246,15 @@ var ( procGenerateConsoleCtrlEvent = modkernel32.NewProc("GenerateConsoleCtrlEvent") procGetACP = modkernel32.NewProc("GetACP") procGetActiveProcessorCount = modkernel32.NewProc("GetActiveProcessorCount") + procGetCommModemStatus = modkernel32.NewProc("GetCommModemStatus") + procGetCommState = modkernel32.NewProc("GetCommState") procGetCommTimeouts = modkernel32.NewProc("GetCommTimeouts") procGetCommandLineW = modkernel32.NewProc("GetCommandLineW") procGetComputerNameExW = modkernel32.NewProc("GetComputerNameExW") procGetComputerNameW = modkernel32.NewProc("GetComputerNameW") + procGetConsoleCP = modkernel32.NewProc("GetConsoleCP") procGetConsoleMode = modkernel32.NewProc("GetConsoleMode") + procGetConsoleOutputCP = modkernel32.NewProc("GetConsoleOutputCP") procGetConsoleScreenBufferInfo = modkernel32.NewProc("GetConsoleScreenBufferInfo") procGetCurrentDirectoryW = modkernel32.NewProc("GetCurrentDirectoryW") procGetCurrentProcessId = modkernel32.NewProc("GetCurrentProcessId") @@ -266,8 +280,10 @@ var ( procGetMaximumProcessorCount = modkernel32.NewProc("GetMaximumProcessorCount") procGetModuleFileNameW = modkernel32.NewProc("GetModuleFileNameW") procGetModuleHandleExW = modkernel32.NewProc("GetModuleHandleExW") + procGetNamedPipeClientProcessId = modkernel32.NewProc("GetNamedPipeClientProcessId") procGetNamedPipeHandleStateW = modkernel32.NewProc("GetNamedPipeHandleStateW") procGetNamedPipeInfo = modkernel32.NewProc("GetNamedPipeInfo") + procGetNamedPipeServerProcessId = modkernel32.NewProc("GetNamedPipeServerProcessId") procGetOverlappedResult = modkernel32.NewProc("GetOverlappedResult") procGetPriorityClass = modkernel32.NewProc("GetPriorityClass") procGetProcAddress = modkernel32.NewProc("GetProcAddress") @@ -322,6 +338,7 @@ var ( procProcess32NextW = modkernel32.NewProc("Process32NextW") procProcessIdToSessionId = modkernel32.NewProc("ProcessIdToSessionId") procPulseEvent = modkernel32.NewProc("PulseEvent") + procPurgeComm = modkernel32.NewProc("PurgeComm") procQueryDosDeviceW = modkernel32.NewProc("QueryDosDeviceW") procQueryFullProcessImageNameW = modkernel32.NewProc("QueryFullProcessImageNameW") procQueryInformationJobObject = modkernel32.NewProc("QueryInformationJobObject") @@ -335,14 +352,18 @@ var ( procResetEvent = modkernel32.NewProc("ResetEvent") procResizePseudoConsole = modkernel32.NewProc("ResizePseudoConsole") procResumeThread = modkernel32.NewProc("ResumeThread") + procSetCommBreak = modkernel32.NewProc("SetCommBreak") + procSetCommMask = modkernel32.NewProc("SetCommMask") + procSetCommState = modkernel32.NewProc("SetCommState") procSetCommTimeouts = modkernel32.NewProc("SetCommTimeouts") + procSetConsoleCP = modkernel32.NewProc("SetConsoleCP") procSetConsoleCursorPosition = modkernel32.NewProc("SetConsoleCursorPosition") procSetConsoleMode = modkernel32.NewProc("SetConsoleMode") + procSetConsoleOutputCP = modkernel32.NewProc("SetConsoleOutputCP") procSetCurrentDirectoryW = modkernel32.NewProc("SetCurrentDirectoryW") procSetDefaultDllDirectories = modkernel32.NewProc("SetDefaultDllDirectories") procSetDllDirectoryW = modkernel32.NewProc("SetDllDirectoryW") procSetEndOfFile = modkernel32.NewProc("SetEndOfFile") - procSetFileValidData = modkernel32.NewProc("SetFileValidData") procSetEnvironmentVariableW = modkernel32.NewProc("SetEnvironmentVariableW") procSetErrorMode = modkernel32.NewProc("SetErrorMode") procSetEvent = modkernel32.NewProc("SetEvent") @@ -351,6 +372,7 @@ var ( procSetFileInformationByHandle = modkernel32.NewProc("SetFileInformationByHandle") procSetFilePointer = modkernel32.NewProc("SetFilePointer") procSetFileTime = modkernel32.NewProc("SetFileTime") + procSetFileValidData = modkernel32.NewProc("SetFileValidData") procSetHandleInformation = modkernel32.NewProc("SetHandleInformation") procSetInformationJobObject = modkernel32.NewProc("SetInformationJobObject") procSetNamedPipeHandleState = modkernel32.NewProc("SetNamedPipeHandleState") @@ -361,6 +383,7 @@ var ( procSetStdHandle = modkernel32.NewProc("SetStdHandle") procSetVolumeLabelW = modkernel32.NewProc("SetVolumeLabelW") procSetVolumeMountPointW = modkernel32.NewProc("SetVolumeMountPointW") + procSetupComm = modkernel32.NewProc("SetupComm") procSizeofResource = modkernel32.NewProc("SizeofResource") procSleepEx = modkernel32.NewProc("SleepEx") procTerminateJobObject = modkernel32.NewProc("TerminateJobObject") @@ -379,6 +402,7 @@ var ( procVirtualQueryEx = modkernel32.NewProc("VirtualQueryEx") procVirtualUnlock = modkernel32.NewProc("VirtualUnlock") procWTSGetActiveConsoleSessionId = modkernel32.NewProc("WTSGetActiveConsoleSessionId") + procWaitCommEvent = modkernel32.NewProc("WaitCommEvent") procWaitForMultipleObjects = modkernel32.NewProc("WaitForMultipleObjects") procWaitForSingleObject = modkernel32.NewProc("WaitForSingleObject") procWriteConsoleW = modkernel32.NewProc("WriteConsoleW") @@ -389,6 +413,7 @@ var ( procTransmitFile = modmswsock.NewProc("TransmitFile") procNetApiBufferFree = modnetapi32.NewProc("NetApiBufferFree") procNetGetJoinInformation = modnetapi32.NewProc("NetGetJoinInformation") + procNetUserEnum = modnetapi32.NewProc("NetUserEnum") procNetUserGetInfo = modnetapi32.NewProc("NetUserGetInfo") procNtCreateFile = modntdll.NewProc("NtCreateFile") procNtCreateNamedPipeFile = modntdll.NewProc("NtCreateNamedPipeFile") @@ -464,12 +489,16 @@ var ( procGetDesktopWindow = moduser32.NewProc("GetDesktopWindow") procGetForegroundWindow = moduser32.NewProc("GetForegroundWindow") procGetGUIThreadInfo = moduser32.NewProc("GetGUIThreadInfo") + procGetKeyboardLayout = moduser32.NewProc("GetKeyboardLayout") procGetShellWindow = moduser32.NewProc("GetShellWindow") procGetWindowThreadProcessId = moduser32.NewProc("GetWindowThreadProcessId") procIsWindow = moduser32.NewProc("IsWindow") procIsWindowUnicode = moduser32.NewProc("IsWindowUnicode") procIsWindowVisible = moduser32.NewProc("IsWindowVisible") + procLoadKeyboardLayoutW = moduser32.NewProc("LoadKeyboardLayoutW") procMessageBoxW = moduser32.NewProc("MessageBoxW") + procToUnicodeEx = moduser32.NewProc("ToUnicodeEx") + procUnloadKeyboardLayout = moduser32.NewProc("UnloadKeyboardLayout") procCreateEnvironmentBlock = moduserenv.NewProc("CreateEnvironmentBlock") procDestroyEnvironmentBlock = moduserenv.NewProc("DestroyEnvironmentBlock") procGetUserProfileDirectoryW = moduserenv.NewProc("GetUserProfileDirectoryW") @@ -775,6 +804,14 @@ func FreeSid(sid *SID) (err error) { return } +func GetAce(acl *ACL, aceIndex uint32, pAce **ACCESS_ALLOWED_ACE) (err error) { + r1, _, e1 := syscall.Syscall(procGetAce.Addr(), 3, uintptr(unsafe.Pointer(acl)), uintptr(aceIndex), uintptr(unsafe.Pointer(pAce))) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + func GetLengthSid(sid *SID) (len uint32) { r0, _, _ := syscall.Syscall(procGetLengthSid.Addr(), 1, uintptr(unsafe.Pointer(sid)), 0, 0) len = uint32(r0) @@ -1576,6 +1613,14 @@ func DwmSetWindowAttribute(hwnd HWND, attribute uint32, value unsafe.Pointer, si return } +func CancelMibChangeNotify2(notificationHandle Handle) (errcode error) { + r0, _, _ := syscall.Syscall(procCancelMibChangeNotify2.Addr(), 1, uintptr(notificationHandle), 0, 0) + if r0 != 0 { + errcode = syscall.Errno(r0) + } + return +} + func GetAdaptersAddresses(family uint32, flags uint32, reserved uintptr, adapterAddresses *IpAdapterAddresses, sizePointer *uint32) (errcode error) { r0, _, _ := syscall.Syscall6(procGetAdaptersAddresses.Addr(), 5, uintptr(family), uintptr(flags), uintptr(reserved), uintptr(unsafe.Pointer(adapterAddresses)), uintptr(unsafe.Pointer(sizePointer)), 0) if r0 != 0 { @@ -1608,6 +1653,46 @@ func GetIfEntry(pIfRow *MibIfRow) (errcode error) { return } +func GetIfEntry2Ex(level uint32, row *MibIfRow2) (errcode error) { + r0, _, _ := syscall.Syscall(procGetIfEntry2Ex.Addr(), 2, uintptr(level), uintptr(unsafe.Pointer(row)), 0) + if r0 != 0 { + errcode = syscall.Errno(r0) + } + return +} + +func GetUnicastIpAddressEntry(row *MibUnicastIpAddressRow) (errcode error) { + r0, _, _ := syscall.Syscall(procGetUnicastIpAddressEntry.Addr(), 1, uintptr(unsafe.Pointer(row)), 0, 0) + if r0 != 0 { + errcode = syscall.Errno(r0) + } + return +} + +func NotifyIpInterfaceChange(family uint16, callback uintptr, callerContext unsafe.Pointer, initialNotification bool, notificationHandle *Handle) (errcode error) { + var _p0 uint32 + if initialNotification { + _p0 = 1 + } + r0, _, _ := syscall.Syscall6(procNotifyIpInterfaceChange.Addr(), 5, uintptr(family), uintptr(callback), uintptr(callerContext), uintptr(_p0), uintptr(unsafe.Pointer(notificationHandle)), 0) + if r0 != 0 { + errcode = syscall.Errno(r0) + } + return +} + +func NotifyUnicastIpAddressChange(family uint16, callback uintptr, callerContext unsafe.Pointer, initialNotification bool, notificationHandle *Handle) (errcode error) { + var _p0 uint32 + if initialNotification { + _p0 = 1 + } + r0, _, _ := syscall.Syscall6(procNotifyUnicastIpAddressChange.Addr(), 5, uintptr(family), uintptr(callback), uintptr(callerContext), uintptr(_p0), uintptr(unsafe.Pointer(notificationHandle)), 0) + if r0 != 0 { + errcode = syscall.Errno(r0) + } + return +} + func AddDllDirectory(path *uint16) (cookie uintptr, err error) { r0, _, e1 := syscall.Syscall(procAddDllDirectory.Addr(), 1, uintptr(unsafe.Pointer(path)), 0, 0) cookie = uintptr(r0) @@ -1641,6 +1726,22 @@ func CancelIoEx(s Handle, o *Overlapped) (err error) { return } +func ClearCommBreak(handle Handle) (err error) { + r1, _, e1 := syscall.Syscall(procClearCommBreak.Addr(), 1, uintptr(handle), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func ClearCommError(handle Handle, lpErrors *uint32, lpStat *ComStat) (err error) { + r1, _, e1 := syscall.Syscall(procClearCommError.Addr(), 3, uintptr(handle), uintptr(unsafe.Pointer(lpErrors)), uintptr(unsafe.Pointer(lpStat))) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + func CloseHandle(handle Handle) (err error) { r1, _, e1 := syscall.Syscall(procCloseHandle.Addr(), 1, uintptr(handle), 0, 0) if r1 == 0 { @@ -1845,6 +1946,14 @@ func DeviceIoControl(handle Handle, ioControlCode uint32, inBuffer *byte, inBuff return } +func DisconnectNamedPipe(pipe Handle) (err error) { + r1, _, e1 := syscall.Syscall(procDisconnectNamedPipe.Addr(), 1, uintptr(pipe), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + func DuplicateHandle(hSourceProcessHandle Handle, hSourceHandle Handle, hTargetProcessHandle Handle, lpTargetHandle *Handle, dwDesiredAccess uint32, bInheritHandle bool, dwOptions uint32) (err error) { var _p0 uint32 if bInheritHandle { @@ -1857,6 +1966,14 @@ func DuplicateHandle(hSourceProcessHandle Handle, hSourceHandle Handle, hTargetP return } +func EscapeCommFunction(handle Handle, dwFunc uint32) (err error) { + r1, _, e1 := syscall.Syscall(procEscapeCommFunction.Addr(), 2, uintptr(handle), uintptr(dwFunc), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + func ExitProcess(exitcode uint32) { syscall.Syscall(procExitProcess.Addr(), 1, uintptr(exitcode), 0, 0) return @@ -2058,6 +2175,22 @@ func GetActiveProcessorCount(groupNumber uint16) (ret uint32) { return } +func GetCommModemStatus(handle Handle, lpModemStat *uint32) (err error) { + r1, _, e1 := syscall.Syscall(procGetCommModemStatus.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(lpModemStat)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func GetCommState(handle Handle, lpDCB *DCB) (err error) { + r1, _, e1 := syscall.Syscall(procGetCommState.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(lpDCB)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + func GetCommTimeouts(handle Handle, timeouts *CommTimeouts) (err error) { r1, _, e1 := syscall.Syscall(procGetCommTimeouts.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(timeouts)), 0) if r1 == 0 { @@ -2088,6 +2221,15 @@ func GetComputerName(buf *uint16, n *uint32) (err error) { return } +func GetConsoleCP() (cp uint32, err error) { + r0, _, e1 := syscall.Syscall(procGetConsoleCP.Addr(), 0, 0, 0, 0) + cp = uint32(r0) + if cp == 0 { + err = errnoErr(e1) + } + return +} + func GetConsoleMode(console Handle, mode *uint32) (err error) { r1, _, e1 := syscall.Syscall(procGetConsoleMode.Addr(), 2, uintptr(console), uintptr(unsafe.Pointer(mode)), 0) if r1 == 0 { @@ -2096,6 +2238,15 @@ func GetConsoleMode(console Handle, mode *uint32) (err error) { return } +func GetConsoleOutputCP() (cp uint32, err error) { + r0, _, e1 := syscall.Syscall(procGetConsoleOutputCP.Addr(), 0, 0, 0, 0) + cp = uint32(r0) + if cp == 0 { + err = errnoErr(e1) + } + return +} + func GetConsoleScreenBufferInfo(console Handle, info *ConsoleScreenBufferInfo) (err error) { r1, _, e1 := syscall.Syscall(procGetConsoleScreenBufferInfo.Addr(), 2, uintptr(console), uintptr(unsafe.Pointer(info)), 0) if r1 == 0 { @@ -2297,6 +2448,14 @@ func GetModuleHandleEx(flags uint32, moduleName *uint16, module *Handle) (err er return } +func GetNamedPipeClientProcessId(pipe Handle, clientProcessID *uint32) (err error) { + r1, _, e1 := syscall.Syscall(procGetNamedPipeClientProcessId.Addr(), 2, uintptr(pipe), uintptr(unsafe.Pointer(clientProcessID)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + func GetNamedPipeHandleState(pipe Handle, state *uint32, curInstances *uint32, maxCollectionCount *uint32, collectDataTimeout *uint32, userName *uint16, maxUserNameSize uint32) (err error) { r1, _, e1 := syscall.Syscall9(procGetNamedPipeHandleStateW.Addr(), 7, uintptr(pipe), uintptr(unsafe.Pointer(state)), uintptr(unsafe.Pointer(curInstances)), uintptr(unsafe.Pointer(maxCollectionCount)), uintptr(unsafe.Pointer(collectDataTimeout)), uintptr(unsafe.Pointer(userName)), uintptr(maxUserNameSize), 0, 0) if r1 == 0 { @@ -2313,6 +2472,14 @@ func GetNamedPipeInfo(pipe Handle, flags *uint32, outSize *uint32, inSize *uint3 return } +func GetNamedPipeServerProcessId(pipe Handle, serverProcessID *uint32) (err error) { + r1, _, e1 := syscall.Syscall(procGetNamedPipeServerProcessId.Addr(), 2, uintptr(pipe), uintptr(unsafe.Pointer(serverProcessID)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + func GetOverlappedResult(handle Handle, overlapped *Overlapped, done *uint32, wait bool) (err error) { var _p0 uint32 if wait { @@ -2810,6 +2977,14 @@ func PulseEvent(event Handle) (err error) { return } +func PurgeComm(handle Handle, dwFlags uint32) (err error) { + r1, _, e1 := syscall.Syscall(procPurgeComm.Addr(), 2, uintptr(handle), uintptr(dwFlags), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + func QueryDosDevice(deviceName *uint16, targetPath *uint16, max uint32) (n uint32, err error) { r0, _, e1 := syscall.Syscall(procQueryDosDeviceW.Addr(), 3, uintptr(unsafe.Pointer(deviceName)), uintptr(unsafe.Pointer(targetPath)), uintptr(max)) n = uint32(r0) @@ -2924,6 +3099,30 @@ func ResumeThread(thread Handle) (ret uint32, err error) { return } +func SetCommBreak(handle Handle) (err error) { + r1, _, e1 := syscall.Syscall(procSetCommBreak.Addr(), 1, uintptr(handle), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func SetCommMask(handle Handle, dwEvtMask uint32) (err error) { + r1, _, e1 := syscall.Syscall(procSetCommMask.Addr(), 2, uintptr(handle), uintptr(dwEvtMask), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func SetCommState(handle Handle, lpDCB *DCB) (err error) { + r1, _, e1 := syscall.Syscall(procSetCommState.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(lpDCB)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + func SetCommTimeouts(handle Handle, timeouts *CommTimeouts) (err error) { r1, _, e1 := syscall.Syscall(procSetCommTimeouts.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(timeouts)), 0) if r1 == 0 { @@ -2932,6 +3131,14 @@ func SetCommTimeouts(handle Handle, timeouts *CommTimeouts) (err error) { return } +func SetConsoleCP(cp uint32) (err error) { + r1, _, e1 := syscall.Syscall(procSetConsoleCP.Addr(), 1, uintptr(cp), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + func setConsoleCursorPosition(console Handle, position uint32) (err error) { r1, _, e1 := syscall.Syscall(procSetConsoleCursorPosition.Addr(), 2, uintptr(console), uintptr(position), 0) if r1 == 0 { @@ -2948,6 +3155,14 @@ func SetConsoleMode(console Handle, mode uint32) (err error) { return } +func SetConsoleOutputCP(cp uint32) (err error) { + r1, _, e1 := syscall.Syscall(procSetConsoleOutputCP.Addr(), 1, uintptr(cp), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + func SetCurrentDirectory(path *uint16) (err error) { r1, _, e1 := syscall.Syscall(procSetCurrentDirectoryW.Addr(), 1, uintptr(unsafe.Pointer(path)), 0, 0) if r1 == 0 { @@ -2989,14 +3204,6 @@ func SetEndOfFile(handle Handle) (err error) { return } -func SetFileValidData(handle Handle, validDataLength int64) (err error) { - r1, _, e1 := syscall.Syscall(procSetFileValidData.Addr(), 2, uintptr(handle), uintptr(validDataLength), 0) - if r1 == 0 { - err = errnoErr(e1) - } - return -} - func SetEnvironmentVariable(name *uint16, value *uint16) (err error) { r1, _, e1 := syscall.Syscall(procSetEnvironmentVariableW.Addr(), 2, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(value)), 0) if r1 == 0 { @@ -3060,6 +3267,14 @@ func SetFileTime(handle Handle, ctime *Filetime, atime *Filetime, wtime *Filetim return } +func SetFileValidData(handle Handle, validDataLength int64) (err error) { + r1, _, e1 := syscall.Syscall(procSetFileValidData.Addr(), 2, uintptr(handle), uintptr(validDataLength), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + func SetHandleInformation(handle Handle, mask uint32, flags uint32) (err error) { r1, _, e1 := syscall.Syscall(procSetHandleInformation.Addr(), 3, uintptr(handle), uintptr(mask), uintptr(flags)) if r1 == 0 { @@ -3145,6 +3360,14 @@ func SetVolumeMountPoint(volumeMountPoint *uint16, volumeName *uint16) (err erro return } +func SetupComm(handle Handle, dwInQueue uint32, dwOutQueue uint32) (err error) { + r1, _, e1 := syscall.Syscall(procSetupComm.Addr(), 3, uintptr(handle), uintptr(dwInQueue), uintptr(dwOutQueue)) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + func SizeofResource(module Handle, resInfo Handle) (size uint32, err error) { r0, _, e1 := syscall.Syscall(procSizeofResource.Addr(), 2, uintptr(module), uintptr(resInfo), 0) size = uint32(r0) @@ -3291,6 +3514,14 @@ func WTSGetActiveConsoleSessionId() (sessionID uint32) { return } +func WaitCommEvent(handle Handle, lpEvtMask *uint32, lpOverlapped *Overlapped) (err error) { + r1, _, e1 := syscall.Syscall(procWaitCommEvent.Addr(), 3, uintptr(handle), uintptr(unsafe.Pointer(lpEvtMask)), uintptr(unsafe.Pointer(lpOverlapped))) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + func waitForMultipleObjects(count uint32, handles uintptr, waitAll bool, waitMilliseconds uint32) (event uint32, err error) { var _p0 uint32 if waitAll { @@ -3378,6 +3609,14 @@ func NetGetJoinInformation(server *uint16, name **uint16, bufType *uint32) (nete return } +func NetUserEnum(serverName *uint16, level uint32, filter uint32, buf **byte, prefMaxLen uint32, entriesRead *uint32, totalEntries *uint32, resumeHandle *uint32) (neterr error) { + r0, _, _ := syscall.Syscall9(procNetUserEnum.Addr(), 8, uintptr(unsafe.Pointer(serverName)), uintptr(level), uintptr(filter), uintptr(unsafe.Pointer(buf)), uintptr(prefMaxLen), uintptr(unsafe.Pointer(entriesRead)), uintptr(unsafe.Pointer(totalEntries)), uintptr(unsafe.Pointer(resumeHandle)), 0) + if r0 != 0 { + neterr = syscall.Errno(r0) + } + return +} + func NetUserGetInfo(serverName *uint16, userName *uint16, level uint32, buf **byte) (neterr error) { r0, _, _ := syscall.Syscall6(procNetUserGetInfo.Addr(), 4, uintptr(unsafe.Pointer(serverName)), uintptr(unsafe.Pointer(userName)), uintptr(level), uintptr(unsafe.Pointer(buf)), 0, 0) if r0 != 0 { @@ -3956,6 +4195,12 @@ func GetGUIThreadInfo(thread uint32, info *GUIThreadInfo) (err error) { return } +func GetKeyboardLayout(tid uint32) (hkl Handle) { + r0, _, _ := syscall.Syscall(procGetKeyboardLayout.Addr(), 1, uintptr(tid), 0, 0) + hkl = Handle(r0) + return +} + func GetShellWindow() (shellWindow HWND) { r0, _, _ := syscall.Syscall(procGetShellWindow.Addr(), 0, 0, 0, 0) shellWindow = HWND(r0) @@ -3989,6 +4234,15 @@ func IsWindowVisible(hwnd HWND) (isVisible bool) { return } +func LoadKeyboardLayout(name *uint16, flags uint32) (hkl Handle, err error) { + r0, _, e1 := syscall.Syscall(procLoadKeyboardLayoutW.Addr(), 2, uintptr(unsafe.Pointer(name)), uintptr(flags), 0) + hkl = Handle(r0) + if hkl == 0 { + err = errnoErr(e1) + } + return +} + func MessageBox(hwnd HWND, text *uint16, caption *uint16, boxtype uint32) (ret int32, err error) { r0, _, e1 := syscall.Syscall6(procMessageBoxW.Addr(), 4, uintptr(hwnd), uintptr(unsafe.Pointer(text)), uintptr(unsafe.Pointer(caption)), uintptr(boxtype), 0, 0) ret = int32(r0) @@ -3998,6 +4252,20 @@ func MessageBox(hwnd HWND, text *uint16, caption *uint16, boxtype uint32) (ret i return } +func ToUnicodeEx(vkey uint32, scancode uint32, keystate *byte, pwszBuff *uint16, cchBuff int32, flags uint32, hkl Handle) (ret int32) { + r0, _, _ := syscall.Syscall9(procToUnicodeEx.Addr(), 7, uintptr(vkey), uintptr(scancode), uintptr(unsafe.Pointer(keystate)), uintptr(unsafe.Pointer(pwszBuff)), uintptr(cchBuff), uintptr(flags), uintptr(hkl), 0, 0) + ret = int32(r0) + return +} + +func UnloadKeyboardLayout(hkl Handle) (err error) { + r1, _, e1 := syscall.Syscall(procUnloadKeyboardLayout.Addr(), 1, uintptr(hkl), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + func CreateEnvironmentBlock(block **uint16, token Token, inheritExisting bool) (err error) { var _p0 uint32 if inheritExisting { diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/term/LICENSE b/trunk/3rdparty/srs-bench/vendor/golang.org/x/term/LICENSE index 6a66aea5e..2a7cf70da 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/term/LICENSE +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/term/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2009 The Go Authors. All rights reserved. +Copyright 2009 The Go Authors. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are @@ -10,7 +10,7 @@ notice, this list of conditions and the following disclaimer. copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - * Neither the name of Google Inc. nor the names of its + * Neither the name of Google LLC nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/term/README.md b/trunk/3rdparty/srs-bench/vendor/golang.org/x/term/README.md index d03d0aefe..05ff623f9 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/term/README.md +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/term/README.md @@ -4,16 +4,13 @@ This repository provides Go terminal and console support packages. -## Download/Install - -The easiest way to install is to run `go get -u golang.org/x/term`. You can -also manually git clone the repository to `$GOPATH/src/golang.org/x/term`. - ## Report Issues / Send Patches This repository uses Gerrit for code changes. To learn how to submit changes to -this repository, see https://golang.org/doc/contribute.html. +this repository, see https://go.dev/doc/contribute. + +The git repository is https://go.googlesource.com/term. The main issue tracker for the term repository is located at -https://github.com/golang/go/issues. Prefix your issue with "x/term:" in the +https://go.dev/issues. Prefix your issue with "x/term:" in the subject line, so it is easy to find. diff --git a/trunk/3rdparty/srs-bench/vendor/golang.org/x/term/term_windows.go b/trunk/3rdparty/srs-bench/vendor/golang.org/x/term/term_windows.go index 465f56060..df6bf948e 100644 --- a/trunk/3rdparty/srs-bench/vendor/golang.org/x/term/term_windows.go +++ b/trunk/3rdparty/srs-bench/vendor/golang.org/x/term/term_windows.go @@ -26,6 +26,7 @@ func makeRaw(fd int) (*State, error) { return nil, err } raw := st &^ (windows.ENABLE_ECHO_INPUT | windows.ENABLE_PROCESSED_INPUT | windows.ENABLE_LINE_INPUT | windows.ENABLE_PROCESSED_OUTPUT) + raw |= windows.ENABLE_VIRTUAL_TERMINAL_INPUT if err := windows.SetConsoleMode(windows.Handle(fd), raw); err != nil { return nil, err } diff --git a/trunk/3rdparty/srs-bench/vendor/gopkg.in/yaml.v3/LICENSE b/trunk/3rdparty/srs-bench/vendor/gopkg.in/yaml.v3/LICENSE deleted file mode 100644 index 2683e4bb1..000000000 --- a/trunk/3rdparty/srs-bench/vendor/gopkg.in/yaml.v3/LICENSE +++ /dev/null @@ -1,50 +0,0 @@ - -This project is covered by two different licenses: MIT and Apache. - -#### MIT License #### - -The following files were ported to Go from C files of libyaml, and thus -are still covered by their original MIT license, with the additional -copyright staring in 2011 when the project was ported over: - - apic.go emitterc.go parserc.go readerc.go scannerc.go - writerc.go yamlh.go yamlprivateh.go - -Copyright (c) 2006-2010 Kirill Simonov -Copyright (c) 2006-2011 Kirill Simonov - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - -### Apache License ### - -All the remaining project files are covered by the Apache license: - -Copyright (c) 2011-2019 Canonical Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. diff --git a/trunk/3rdparty/srs-bench/vendor/gopkg.in/yaml.v3/NOTICE b/trunk/3rdparty/srs-bench/vendor/gopkg.in/yaml.v3/NOTICE deleted file mode 100644 index 866d74a7a..000000000 --- a/trunk/3rdparty/srs-bench/vendor/gopkg.in/yaml.v3/NOTICE +++ /dev/null @@ -1,13 +0,0 @@ -Copyright 2011-2016 Canonical Ltd. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. diff --git a/trunk/3rdparty/srs-bench/vendor/gopkg.in/yaml.v3/README.md b/trunk/3rdparty/srs-bench/vendor/gopkg.in/yaml.v3/README.md deleted file mode 100644 index 08eb1babd..000000000 --- a/trunk/3rdparty/srs-bench/vendor/gopkg.in/yaml.v3/README.md +++ /dev/null @@ -1,150 +0,0 @@ -# YAML support for the Go language - -Introduction ------------- - -The yaml package enables Go programs to comfortably encode and decode YAML -values. It was developed within [Canonical](https://www.canonical.com) as -part of the [juju](https://juju.ubuntu.com) project, and is based on a -pure Go port of the well-known [libyaml](http://pyyaml.org/wiki/LibYAML) -C library to parse and generate YAML data quickly and reliably. - -Compatibility -------------- - -The yaml package supports most of YAML 1.2, but preserves some behavior -from 1.1 for backwards compatibility. - -Specifically, as of v3 of the yaml package: - - - YAML 1.1 bools (_yes/no, on/off_) are supported as long as they are being - decoded into a typed bool value. Otherwise they behave as a string. Booleans - in YAML 1.2 are _true/false_ only. - - Octals encode and decode as _0777_ per YAML 1.1, rather than _0o777_ - as specified in YAML 1.2, because most parsers still use the old format. - Octals in the _0o777_ format are supported though, so new files work. - - Does not support base-60 floats. These are gone from YAML 1.2, and were - actually never supported by this package as it's clearly a poor choice. - -and offers backwards -compatibility with YAML 1.1 in some cases. -1.2, including support for -anchors, tags, map merging, etc. Multi-document unmarshalling is not yet -implemented, and base-60 floats from YAML 1.1 are purposefully not -supported since they're a poor design and are gone in YAML 1.2. - -Installation and usage ----------------------- - -The import path for the package is *gopkg.in/yaml.v3*. - -To install it, run: - - go get gopkg.in/yaml.v3 - -API documentation ------------------ - -If opened in a browser, the import path itself leads to the API documentation: - - - [https://gopkg.in/yaml.v3](https://gopkg.in/yaml.v3) - -API stability -------------- - -The package API for yaml v3 will remain stable as described in [gopkg.in](https://gopkg.in). - - -License -------- - -The yaml package is licensed under the MIT and Apache License 2.0 licenses. -Please see the LICENSE file for details. - - -Example -------- - -```Go -package main - -import ( - "fmt" - "log" - - "gopkg.in/yaml.v3" -) - -var data = ` -a: Easy! -b: - c: 2 - d: [3, 4] -` - -// Note: struct fields must be public in order for unmarshal to -// correctly populate the data. -type T struct { - A string - B struct { - RenamedC int `yaml:"c"` - D []int `yaml:",flow"` - } -} - -func main() { - t := T{} - - err := yaml.Unmarshal([]byte(data), &t) - if err != nil { - log.Fatalf("error: %v", err) - } - fmt.Printf("--- t:\n%v\n\n", t) - - d, err := yaml.Marshal(&t) - if err != nil { - log.Fatalf("error: %v", err) - } - fmt.Printf("--- t dump:\n%s\n\n", string(d)) - - m := make(map[interface{}]interface{}) - - err = yaml.Unmarshal([]byte(data), &m) - if err != nil { - log.Fatalf("error: %v", err) - } - fmt.Printf("--- m:\n%v\n\n", m) - - d, err = yaml.Marshal(&m) - if err != nil { - log.Fatalf("error: %v", err) - } - fmt.Printf("--- m dump:\n%s\n\n", string(d)) -} -``` - -This example will generate the following output: - -``` ---- t: -{Easy! {2 [3 4]}} - ---- t dump: -a: Easy! -b: - c: 2 - d: [3, 4] - - ---- m: -map[a:Easy! b:map[c:2 d:[3 4]]] - ---- m dump: -a: Easy! -b: - c: 2 - d: - - 3 - - 4 -``` - diff --git a/trunk/3rdparty/srs-bench/vendor/gopkg.in/yaml.v3/apic.go b/trunk/3rdparty/srs-bench/vendor/gopkg.in/yaml.v3/apic.go deleted file mode 100644 index ae7d049f1..000000000 --- a/trunk/3rdparty/srs-bench/vendor/gopkg.in/yaml.v3/apic.go +++ /dev/null @@ -1,747 +0,0 @@ -// -// Copyright (c) 2011-2019 Canonical Ltd -// Copyright (c) 2006-2010 Kirill Simonov -// -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -// of the Software, and to permit persons to whom the Software is furnished to do -// so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -package yaml - -import ( - "io" -) - -func yaml_insert_token(parser *yaml_parser_t, pos int, token *yaml_token_t) { - //fmt.Println("yaml_insert_token", "pos:", pos, "typ:", token.typ, "head:", parser.tokens_head, "len:", len(parser.tokens)) - - // Check if we can move the queue at the beginning of the buffer. - if parser.tokens_head > 0 && len(parser.tokens) == cap(parser.tokens) { - if parser.tokens_head != len(parser.tokens) { - copy(parser.tokens, parser.tokens[parser.tokens_head:]) - } - parser.tokens = parser.tokens[:len(parser.tokens)-parser.tokens_head] - parser.tokens_head = 0 - } - parser.tokens = append(parser.tokens, *token) - if pos < 0 { - return - } - copy(parser.tokens[parser.tokens_head+pos+1:], parser.tokens[parser.tokens_head+pos:]) - parser.tokens[parser.tokens_head+pos] = *token -} - -// Create a new parser object. -func yaml_parser_initialize(parser *yaml_parser_t) bool { - *parser = yaml_parser_t{ - raw_buffer: make([]byte, 0, input_raw_buffer_size), - buffer: make([]byte, 0, input_buffer_size), - } - return true -} - -// Destroy a parser object. -func yaml_parser_delete(parser *yaml_parser_t) { - *parser = yaml_parser_t{} -} - -// String read handler. -func yaml_string_read_handler(parser *yaml_parser_t, buffer []byte) (n int, err error) { - if parser.input_pos == len(parser.input) { - return 0, io.EOF - } - n = copy(buffer, parser.input[parser.input_pos:]) - parser.input_pos += n - return n, nil -} - -// Reader read handler. -func yaml_reader_read_handler(parser *yaml_parser_t, buffer []byte) (n int, err error) { - return parser.input_reader.Read(buffer) -} - -// Set a string input. -func yaml_parser_set_input_string(parser *yaml_parser_t, input []byte) { - if parser.read_handler != nil { - panic("must set the input source only once") - } - parser.read_handler = yaml_string_read_handler - parser.input = input - parser.input_pos = 0 -} - -// Set a file input. -func yaml_parser_set_input_reader(parser *yaml_parser_t, r io.Reader) { - if parser.read_handler != nil { - panic("must set the input source only once") - } - parser.read_handler = yaml_reader_read_handler - parser.input_reader = r -} - -// Set the source encoding. -func yaml_parser_set_encoding(parser *yaml_parser_t, encoding yaml_encoding_t) { - if parser.encoding != yaml_ANY_ENCODING { - panic("must set the encoding only once") - } - parser.encoding = encoding -} - -// Create a new emitter object. -func yaml_emitter_initialize(emitter *yaml_emitter_t) { - *emitter = yaml_emitter_t{ - buffer: make([]byte, output_buffer_size), - raw_buffer: make([]byte, 0, output_raw_buffer_size), - states: make([]yaml_emitter_state_t, 0, initial_stack_size), - events: make([]yaml_event_t, 0, initial_queue_size), - best_width: -1, - } -} - -// Destroy an emitter object. -func yaml_emitter_delete(emitter *yaml_emitter_t) { - *emitter = yaml_emitter_t{} -} - -// String write handler. -func yaml_string_write_handler(emitter *yaml_emitter_t, buffer []byte) error { - *emitter.output_buffer = append(*emitter.output_buffer, buffer...) - return nil -} - -// yaml_writer_write_handler uses emitter.output_writer to write the -// emitted text. -func yaml_writer_write_handler(emitter *yaml_emitter_t, buffer []byte) error { - _, err := emitter.output_writer.Write(buffer) - return err -} - -// Set a string output. -func yaml_emitter_set_output_string(emitter *yaml_emitter_t, output_buffer *[]byte) { - if emitter.write_handler != nil { - panic("must set the output target only once") - } - emitter.write_handler = yaml_string_write_handler - emitter.output_buffer = output_buffer -} - -// Set a file output. -func yaml_emitter_set_output_writer(emitter *yaml_emitter_t, w io.Writer) { - if emitter.write_handler != nil { - panic("must set the output target only once") - } - emitter.write_handler = yaml_writer_write_handler - emitter.output_writer = w -} - -// Set the output encoding. -func yaml_emitter_set_encoding(emitter *yaml_emitter_t, encoding yaml_encoding_t) { - if emitter.encoding != yaml_ANY_ENCODING { - panic("must set the output encoding only once") - } - emitter.encoding = encoding -} - -// Set the canonical output style. -func yaml_emitter_set_canonical(emitter *yaml_emitter_t, canonical bool) { - emitter.canonical = canonical -} - -// Set the indentation increment. -func yaml_emitter_set_indent(emitter *yaml_emitter_t, indent int) { - if indent < 2 || indent > 9 { - indent = 2 - } - emitter.best_indent = indent -} - -// Set the preferred line width. -func yaml_emitter_set_width(emitter *yaml_emitter_t, width int) { - if width < 0 { - width = -1 - } - emitter.best_width = width -} - -// Set if unescaped non-ASCII characters are allowed. -func yaml_emitter_set_unicode(emitter *yaml_emitter_t, unicode bool) { - emitter.unicode = unicode -} - -// Set the preferred line break character. -func yaml_emitter_set_break(emitter *yaml_emitter_t, line_break yaml_break_t) { - emitter.line_break = line_break -} - -///* -// * Destroy a token object. -// */ -// -//YAML_DECLARE(void) -//yaml_token_delete(yaml_token_t *token) -//{ -// assert(token); // Non-NULL token object expected. -// -// switch (token.type) -// { -// case YAML_TAG_DIRECTIVE_TOKEN: -// yaml_free(token.data.tag_directive.handle); -// yaml_free(token.data.tag_directive.prefix); -// break; -// -// case YAML_ALIAS_TOKEN: -// yaml_free(token.data.alias.value); -// break; -// -// case YAML_ANCHOR_TOKEN: -// yaml_free(token.data.anchor.value); -// break; -// -// case YAML_TAG_TOKEN: -// yaml_free(token.data.tag.handle); -// yaml_free(token.data.tag.suffix); -// break; -// -// case YAML_SCALAR_TOKEN: -// yaml_free(token.data.scalar.value); -// break; -// -// default: -// break; -// } -// -// memset(token, 0, sizeof(yaml_token_t)); -//} -// -///* -// * Check if a string is a valid UTF-8 sequence. -// * -// * Check 'reader.c' for more details on UTF-8 encoding. -// */ -// -//static int -//yaml_check_utf8(yaml_char_t *start, size_t length) -//{ -// yaml_char_t *end = start+length; -// yaml_char_t *pointer = start; -// -// while (pointer < end) { -// unsigned char octet; -// unsigned int width; -// unsigned int value; -// size_t k; -// -// octet = pointer[0]; -// width = (octet & 0x80) == 0x00 ? 1 : -// (octet & 0xE0) == 0xC0 ? 2 : -// (octet & 0xF0) == 0xE0 ? 3 : -// (octet & 0xF8) == 0xF0 ? 4 : 0; -// value = (octet & 0x80) == 0x00 ? octet & 0x7F : -// (octet & 0xE0) == 0xC0 ? octet & 0x1F : -// (octet & 0xF0) == 0xE0 ? octet & 0x0F : -// (octet & 0xF8) == 0xF0 ? octet & 0x07 : 0; -// if (!width) return 0; -// if (pointer+width > end) return 0; -// for (k = 1; k < width; k ++) { -// octet = pointer[k]; -// if ((octet & 0xC0) != 0x80) return 0; -// value = (value << 6) + (octet & 0x3F); -// } -// if (!((width == 1) || -// (width == 2 && value >= 0x80) || -// (width == 3 && value >= 0x800) || -// (width == 4 && value >= 0x10000))) return 0; -// -// pointer += width; -// } -// -// return 1; -//} -// - -// Create STREAM-START. -func yaml_stream_start_event_initialize(event *yaml_event_t, encoding yaml_encoding_t) { - *event = yaml_event_t{ - typ: yaml_STREAM_START_EVENT, - encoding: encoding, - } -} - -// Create STREAM-END. -func yaml_stream_end_event_initialize(event *yaml_event_t) { - *event = yaml_event_t{ - typ: yaml_STREAM_END_EVENT, - } -} - -// Create DOCUMENT-START. -func yaml_document_start_event_initialize( - event *yaml_event_t, - version_directive *yaml_version_directive_t, - tag_directives []yaml_tag_directive_t, - implicit bool, -) { - *event = yaml_event_t{ - typ: yaml_DOCUMENT_START_EVENT, - version_directive: version_directive, - tag_directives: tag_directives, - implicit: implicit, - } -} - -// Create DOCUMENT-END. -func yaml_document_end_event_initialize(event *yaml_event_t, implicit bool) { - *event = yaml_event_t{ - typ: yaml_DOCUMENT_END_EVENT, - implicit: implicit, - } -} - -// Create ALIAS. -func yaml_alias_event_initialize(event *yaml_event_t, anchor []byte) bool { - *event = yaml_event_t{ - typ: yaml_ALIAS_EVENT, - anchor: anchor, - } - return true -} - -// Create SCALAR. -func yaml_scalar_event_initialize(event *yaml_event_t, anchor, tag, value []byte, plain_implicit, quoted_implicit bool, style yaml_scalar_style_t) bool { - *event = yaml_event_t{ - typ: yaml_SCALAR_EVENT, - anchor: anchor, - tag: tag, - value: value, - implicit: plain_implicit, - quoted_implicit: quoted_implicit, - style: yaml_style_t(style), - } - return true -} - -// Create SEQUENCE-START. -func yaml_sequence_start_event_initialize(event *yaml_event_t, anchor, tag []byte, implicit bool, style yaml_sequence_style_t) bool { - *event = yaml_event_t{ - typ: yaml_SEQUENCE_START_EVENT, - anchor: anchor, - tag: tag, - implicit: implicit, - style: yaml_style_t(style), - } - return true -} - -// Create SEQUENCE-END. -func yaml_sequence_end_event_initialize(event *yaml_event_t) bool { - *event = yaml_event_t{ - typ: yaml_SEQUENCE_END_EVENT, - } - return true -} - -// Create MAPPING-START. -func yaml_mapping_start_event_initialize(event *yaml_event_t, anchor, tag []byte, implicit bool, style yaml_mapping_style_t) { - *event = yaml_event_t{ - typ: yaml_MAPPING_START_EVENT, - anchor: anchor, - tag: tag, - implicit: implicit, - style: yaml_style_t(style), - } -} - -// Create MAPPING-END. -func yaml_mapping_end_event_initialize(event *yaml_event_t) { - *event = yaml_event_t{ - typ: yaml_MAPPING_END_EVENT, - } -} - -// Destroy an event object. -func yaml_event_delete(event *yaml_event_t) { - *event = yaml_event_t{} -} - -///* -// * Create a document object. -// */ -// -//YAML_DECLARE(int) -//yaml_document_initialize(document *yaml_document_t, -// version_directive *yaml_version_directive_t, -// tag_directives_start *yaml_tag_directive_t, -// tag_directives_end *yaml_tag_directive_t, -// start_implicit int, end_implicit int) -//{ -// struct { -// error yaml_error_type_t -// } context -// struct { -// start *yaml_node_t -// end *yaml_node_t -// top *yaml_node_t -// } nodes = { NULL, NULL, NULL } -// version_directive_copy *yaml_version_directive_t = NULL -// struct { -// start *yaml_tag_directive_t -// end *yaml_tag_directive_t -// top *yaml_tag_directive_t -// } tag_directives_copy = { NULL, NULL, NULL } -// value yaml_tag_directive_t = { NULL, NULL } -// mark yaml_mark_t = { 0, 0, 0 } -// -// assert(document) // Non-NULL document object is expected. -// assert((tag_directives_start && tag_directives_end) || -// (tag_directives_start == tag_directives_end)) -// // Valid tag directives are expected. -// -// if (!STACK_INIT(&context, nodes, INITIAL_STACK_SIZE)) goto error -// -// if (version_directive) { -// version_directive_copy = yaml_malloc(sizeof(yaml_version_directive_t)) -// if (!version_directive_copy) goto error -// version_directive_copy.major = version_directive.major -// version_directive_copy.minor = version_directive.minor -// } -// -// if (tag_directives_start != tag_directives_end) { -// tag_directive *yaml_tag_directive_t -// if (!STACK_INIT(&context, tag_directives_copy, INITIAL_STACK_SIZE)) -// goto error -// for (tag_directive = tag_directives_start -// tag_directive != tag_directives_end; tag_directive ++) { -// assert(tag_directive.handle) -// assert(tag_directive.prefix) -// if (!yaml_check_utf8(tag_directive.handle, -// strlen((char *)tag_directive.handle))) -// goto error -// if (!yaml_check_utf8(tag_directive.prefix, -// strlen((char *)tag_directive.prefix))) -// goto error -// value.handle = yaml_strdup(tag_directive.handle) -// value.prefix = yaml_strdup(tag_directive.prefix) -// if (!value.handle || !value.prefix) goto error -// if (!PUSH(&context, tag_directives_copy, value)) -// goto error -// value.handle = NULL -// value.prefix = NULL -// } -// } -// -// DOCUMENT_INIT(*document, nodes.start, nodes.end, version_directive_copy, -// tag_directives_copy.start, tag_directives_copy.top, -// start_implicit, end_implicit, mark, mark) -// -// return 1 -// -//error: -// STACK_DEL(&context, nodes) -// yaml_free(version_directive_copy) -// while (!STACK_EMPTY(&context, tag_directives_copy)) { -// value yaml_tag_directive_t = POP(&context, tag_directives_copy) -// yaml_free(value.handle) -// yaml_free(value.prefix) -// } -// STACK_DEL(&context, tag_directives_copy) -// yaml_free(value.handle) -// yaml_free(value.prefix) -// -// return 0 -//} -// -///* -// * Destroy a document object. -// */ -// -//YAML_DECLARE(void) -//yaml_document_delete(document *yaml_document_t) -//{ -// struct { -// error yaml_error_type_t -// } context -// tag_directive *yaml_tag_directive_t -// -// context.error = YAML_NO_ERROR // Eliminate a compiler warning. -// -// assert(document) // Non-NULL document object is expected. -// -// while (!STACK_EMPTY(&context, document.nodes)) { -// node yaml_node_t = POP(&context, document.nodes) -// yaml_free(node.tag) -// switch (node.type) { -// case YAML_SCALAR_NODE: -// yaml_free(node.data.scalar.value) -// break -// case YAML_SEQUENCE_NODE: -// STACK_DEL(&context, node.data.sequence.items) -// break -// case YAML_MAPPING_NODE: -// STACK_DEL(&context, node.data.mapping.pairs) -// break -// default: -// assert(0) // Should not happen. -// } -// } -// STACK_DEL(&context, document.nodes) -// -// yaml_free(document.version_directive) -// for (tag_directive = document.tag_directives.start -// tag_directive != document.tag_directives.end -// tag_directive++) { -// yaml_free(tag_directive.handle) -// yaml_free(tag_directive.prefix) -// } -// yaml_free(document.tag_directives.start) -// -// memset(document, 0, sizeof(yaml_document_t)) -//} -// -///** -// * Get a document node. -// */ -// -//YAML_DECLARE(yaml_node_t *) -//yaml_document_get_node(document *yaml_document_t, index int) -//{ -// assert(document) // Non-NULL document object is expected. -// -// if (index > 0 && document.nodes.start + index <= document.nodes.top) { -// return document.nodes.start + index - 1 -// } -// return NULL -//} -// -///** -// * Get the root object. -// */ -// -//YAML_DECLARE(yaml_node_t *) -//yaml_document_get_root_node(document *yaml_document_t) -//{ -// assert(document) // Non-NULL document object is expected. -// -// if (document.nodes.top != document.nodes.start) { -// return document.nodes.start -// } -// return NULL -//} -// -///* -// * Add a scalar node to a document. -// */ -// -//YAML_DECLARE(int) -//yaml_document_add_scalar(document *yaml_document_t, -// tag *yaml_char_t, value *yaml_char_t, length int, -// style yaml_scalar_style_t) -//{ -// struct { -// error yaml_error_type_t -// } context -// mark yaml_mark_t = { 0, 0, 0 } -// tag_copy *yaml_char_t = NULL -// value_copy *yaml_char_t = NULL -// node yaml_node_t -// -// assert(document) // Non-NULL document object is expected. -// assert(value) // Non-NULL value is expected. -// -// if (!tag) { -// tag = (yaml_char_t *)YAML_DEFAULT_SCALAR_TAG -// } -// -// if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error -// tag_copy = yaml_strdup(tag) -// if (!tag_copy) goto error -// -// if (length < 0) { -// length = strlen((char *)value) -// } -// -// if (!yaml_check_utf8(value, length)) goto error -// value_copy = yaml_malloc(length+1) -// if (!value_copy) goto error -// memcpy(value_copy, value, length) -// value_copy[length] = '\0' -// -// SCALAR_NODE_INIT(node, tag_copy, value_copy, length, style, mark, mark) -// if (!PUSH(&context, document.nodes, node)) goto error -// -// return document.nodes.top - document.nodes.start -// -//error: -// yaml_free(tag_copy) -// yaml_free(value_copy) -// -// return 0 -//} -// -///* -// * Add a sequence node to a document. -// */ -// -//YAML_DECLARE(int) -//yaml_document_add_sequence(document *yaml_document_t, -// tag *yaml_char_t, style yaml_sequence_style_t) -//{ -// struct { -// error yaml_error_type_t -// } context -// mark yaml_mark_t = { 0, 0, 0 } -// tag_copy *yaml_char_t = NULL -// struct { -// start *yaml_node_item_t -// end *yaml_node_item_t -// top *yaml_node_item_t -// } items = { NULL, NULL, NULL } -// node yaml_node_t -// -// assert(document) // Non-NULL document object is expected. -// -// if (!tag) { -// tag = (yaml_char_t *)YAML_DEFAULT_SEQUENCE_TAG -// } -// -// if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error -// tag_copy = yaml_strdup(tag) -// if (!tag_copy) goto error -// -// if (!STACK_INIT(&context, items, INITIAL_STACK_SIZE)) goto error -// -// SEQUENCE_NODE_INIT(node, tag_copy, items.start, items.end, -// style, mark, mark) -// if (!PUSH(&context, document.nodes, node)) goto error -// -// return document.nodes.top - document.nodes.start -// -//error: -// STACK_DEL(&context, items) -// yaml_free(tag_copy) -// -// return 0 -//} -// -///* -// * Add a mapping node to a document. -// */ -// -//YAML_DECLARE(int) -//yaml_document_add_mapping(document *yaml_document_t, -// tag *yaml_char_t, style yaml_mapping_style_t) -//{ -// struct { -// error yaml_error_type_t -// } context -// mark yaml_mark_t = { 0, 0, 0 } -// tag_copy *yaml_char_t = NULL -// struct { -// start *yaml_node_pair_t -// end *yaml_node_pair_t -// top *yaml_node_pair_t -// } pairs = { NULL, NULL, NULL } -// node yaml_node_t -// -// assert(document) // Non-NULL document object is expected. -// -// if (!tag) { -// tag = (yaml_char_t *)YAML_DEFAULT_MAPPING_TAG -// } -// -// if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error -// tag_copy = yaml_strdup(tag) -// if (!tag_copy) goto error -// -// if (!STACK_INIT(&context, pairs, INITIAL_STACK_SIZE)) goto error -// -// MAPPING_NODE_INIT(node, tag_copy, pairs.start, pairs.end, -// style, mark, mark) -// if (!PUSH(&context, document.nodes, node)) goto error -// -// return document.nodes.top - document.nodes.start -// -//error: -// STACK_DEL(&context, pairs) -// yaml_free(tag_copy) -// -// return 0 -//} -// -///* -// * Append an item to a sequence node. -// */ -// -//YAML_DECLARE(int) -//yaml_document_append_sequence_item(document *yaml_document_t, -// sequence int, item int) -//{ -// struct { -// error yaml_error_type_t -// } context -// -// assert(document) // Non-NULL document is required. -// assert(sequence > 0 -// && document.nodes.start + sequence <= document.nodes.top) -// // Valid sequence id is required. -// assert(document.nodes.start[sequence-1].type == YAML_SEQUENCE_NODE) -// // A sequence node is required. -// assert(item > 0 && document.nodes.start + item <= document.nodes.top) -// // Valid item id is required. -// -// if (!PUSH(&context, -// document.nodes.start[sequence-1].data.sequence.items, item)) -// return 0 -// -// return 1 -//} -// -///* -// * Append a pair of a key and a value to a mapping node. -// */ -// -//YAML_DECLARE(int) -//yaml_document_append_mapping_pair(document *yaml_document_t, -// mapping int, key int, value int) -//{ -// struct { -// error yaml_error_type_t -// } context -// -// pair yaml_node_pair_t -// -// assert(document) // Non-NULL document is required. -// assert(mapping > 0 -// && document.nodes.start + mapping <= document.nodes.top) -// // Valid mapping id is required. -// assert(document.nodes.start[mapping-1].type == YAML_MAPPING_NODE) -// // A mapping node is required. -// assert(key > 0 && document.nodes.start + key <= document.nodes.top) -// // Valid key id is required. -// assert(value > 0 && document.nodes.start + value <= document.nodes.top) -// // Valid value id is required. -// -// pair.key = key -// pair.value = value -// -// if (!PUSH(&context, -// document.nodes.start[mapping-1].data.mapping.pairs, pair)) -// return 0 -// -// return 1 -//} -// -// diff --git a/trunk/3rdparty/srs-bench/vendor/gopkg.in/yaml.v3/decode.go b/trunk/3rdparty/srs-bench/vendor/gopkg.in/yaml.v3/decode.go deleted file mode 100644 index 0173b6982..000000000 --- a/trunk/3rdparty/srs-bench/vendor/gopkg.in/yaml.v3/decode.go +++ /dev/null @@ -1,1000 +0,0 @@ -// -// Copyright (c) 2011-2019 Canonical Ltd -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package yaml - -import ( - "encoding" - "encoding/base64" - "fmt" - "io" - "math" - "reflect" - "strconv" - "time" -) - -// ---------------------------------------------------------------------------- -// Parser, produces a node tree out of a libyaml event stream. - -type parser struct { - parser yaml_parser_t - event yaml_event_t - doc *Node - anchors map[string]*Node - doneInit bool - textless bool -} - -func newParser(b []byte) *parser { - p := parser{} - if !yaml_parser_initialize(&p.parser) { - panic("failed to initialize YAML emitter") - } - if len(b) == 0 { - b = []byte{'\n'} - } - yaml_parser_set_input_string(&p.parser, b) - return &p -} - -func newParserFromReader(r io.Reader) *parser { - p := parser{} - if !yaml_parser_initialize(&p.parser) { - panic("failed to initialize YAML emitter") - } - yaml_parser_set_input_reader(&p.parser, r) - return &p -} - -func (p *parser) init() { - if p.doneInit { - return - } - p.anchors = make(map[string]*Node) - p.expect(yaml_STREAM_START_EVENT) - p.doneInit = true -} - -func (p *parser) destroy() { - if p.event.typ != yaml_NO_EVENT { - yaml_event_delete(&p.event) - } - yaml_parser_delete(&p.parser) -} - -// expect consumes an event from the event stream and -// checks that it's of the expected type. -func (p *parser) expect(e yaml_event_type_t) { - if p.event.typ == yaml_NO_EVENT { - if !yaml_parser_parse(&p.parser, &p.event) { - p.fail() - } - } - if p.event.typ == yaml_STREAM_END_EVENT { - failf("attempted to go past the end of stream; corrupted value?") - } - if p.event.typ != e { - p.parser.problem = fmt.Sprintf("expected %s event but got %s", e, p.event.typ) - p.fail() - } - yaml_event_delete(&p.event) - p.event.typ = yaml_NO_EVENT -} - -// peek peeks at the next event in the event stream, -// puts the results into p.event and returns the event type. -func (p *parser) peek() yaml_event_type_t { - if p.event.typ != yaml_NO_EVENT { - return p.event.typ - } - // It's curious choice from the underlying API to generally return a - // positive result on success, but on this case return true in an error - // scenario. This was the source of bugs in the past (issue #666). - if !yaml_parser_parse(&p.parser, &p.event) || p.parser.error != yaml_NO_ERROR { - p.fail() - } - return p.event.typ -} - -func (p *parser) fail() { - var where string - var line int - if p.parser.context_mark.line != 0 { - line = p.parser.context_mark.line - // Scanner errors don't iterate line before returning error - if p.parser.error == yaml_SCANNER_ERROR { - line++ - } - } else if p.parser.problem_mark.line != 0 { - line = p.parser.problem_mark.line - // Scanner errors don't iterate line before returning error - if p.parser.error == yaml_SCANNER_ERROR { - line++ - } - } - if line != 0 { - where = "line " + strconv.Itoa(line) + ": " - } - var msg string - if len(p.parser.problem) > 0 { - msg = p.parser.problem - } else { - msg = "unknown problem parsing YAML content" - } - failf("%s%s", where, msg) -} - -func (p *parser) anchor(n *Node, anchor []byte) { - if anchor != nil { - n.Anchor = string(anchor) - p.anchors[n.Anchor] = n - } -} - -func (p *parser) parse() *Node { - p.init() - switch p.peek() { - case yaml_SCALAR_EVENT: - return p.scalar() - case yaml_ALIAS_EVENT: - return p.alias() - case yaml_MAPPING_START_EVENT: - return p.mapping() - case yaml_SEQUENCE_START_EVENT: - return p.sequence() - case yaml_DOCUMENT_START_EVENT: - return p.document() - case yaml_STREAM_END_EVENT: - // Happens when attempting to decode an empty buffer. - return nil - case yaml_TAIL_COMMENT_EVENT: - panic("internal error: unexpected tail comment event (please report)") - default: - panic("internal error: attempted to parse unknown event (please report): " + p.event.typ.String()) - } -} - -func (p *parser) node(kind Kind, defaultTag, tag, value string) *Node { - var style Style - if tag != "" && tag != "!" { - tag = shortTag(tag) - style = TaggedStyle - } else if defaultTag != "" { - tag = defaultTag - } else if kind == ScalarNode { - tag, _ = resolve("", value) - } - n := &Node{ - Kind: kind, - Tag: tag, - Value: value, - Style: style, - } - if !p.textless { - n.Line = p.event.start_mark.line + 1 - n.Column = p.event.start_mark.column + 1 - n.HeadComment = string(p.event.head_comment) - n.LineComment = string(p.event.line_comment) - n.FootComment = string(p.event.foot_comment) - } - return n -} - -func (p *parser) parseChild(parent *Node) *Node { - child := p.parse() - parent.Content = append(parent.Content, child) - return child -} - -func (p *parser) document() *Node { - n := p.node(DocumentNode, "", "", "") - p.doc = n - p.expect(yaml_DOCUMENT_START_EVENT) - p.parseChild(n) - if p.peek() == yaml_DOCUMENT_END_EVENT { - n.FootComment = string(p.event.foot_comment) - } - p.expect(yaml_DOCUMENT_END_EVENT) - return n -} - -func (p *parser) alias() *Node { - n := p.node(AliasNode, "", "", string(p.event.anchor)) - n.Alias = p.anchors[n.Value] - if n.Alias == nil { - failf("unknown anchor '%s' referenced", n.Value) - } - p.expect(yaml_ALIAS_EVENT) - return n -} - -func (p *parser) scalar() *Node { - var parsedStyle = p.event.scalar_style() - var nodeStyle Style - switch { - case parsedStyle&yaml_DOUBLE_QUOTED_SCALAR_STYLE != 0: - nodeStyle = DoubleQuotedStyle - case parsedStyle&yaml_SINGLE_QUOTED_SCALAR_STYLE != 0: - nodeStyle = SingleQuotedStyle - case parsedStyle&yaml_LITERAL_SCALAR_STYLE != 0: - nodeStyle = LiteralStyle - case parsedStyle&yaml_FOLDED_SCALAR_STYLE != 0: - nodeStyle = FoldedStyle - } - var nodeValue = string(p.event.value) - var nodeTag = string(p.event.tag) - var defaultTag string - if nodeStyle == 0 { - if nodeValue == "<<" { - defaultTag = mergeTag - } - } else { - defaultTag = strTag - } - n := p.node(ScalarNode, defaultTag, nodeTag, nodeValue) - n.Style |= nodeStyle - p.anchor(n, p.event.anchor) - p.expect(yaml_SCALAR_EVENT) - return n -} - -func (p *parser) sequence() *Node { - n := p.node(SequenceNode, seqTag, string(p.event.tag), "") - if p.event.sequence_style()&yaml_FLOW_SEQUENCE_STYLE != 0 { - n.Style |= FlowStyle - } - p.anchor(n, p.event.anchor) - p.expect(yaml_SEQUENCE_START_EVENT) - for p.peek() != yaml_SEQUENCE_END_EVENT { - p.parseChild(n) - } - n.LineComment = string(p.event.line_comment) - n.FootComment = string(p.event.foot_comment) - p.expect(yaml_SEQUENCE_END_EVENT) - return n -} - -func (p *parser) mapping() *Node { - n := p.node(MappingNode, mapTag, string(p.event.tag), "") - block := true - if p.event.mapping_style()&yaml_FLOW_MAPPING_STYLE != 0 { - block = false - n.Style |= FlowStyle - } - p.anchor(n, p.event.anchor) - p.expect(yaml_MAPPING_START_EVENT) - for p.peek() != yaml_MAPPING_END_EVENT { - k := p.parseChild(n) - if block && k.FootComment != "" { - // Must be a foot comment for the prior value when being dedented. - if len(n.Content) > 2 { - n.Content[len(n.Content)-3].FootComment = k.FootComment - k.FootComment = "" - } - } - v := p.parseChild(n) - if k.FootComment == "" && v.FootComment != "" { - k.FootComment = v.FootComment - v.FootComment = "" - } - if p.peek() == yaml_TAIL_COMMENT_EVENT { - if k.FootComment == "" { - k.FootComment = string(p.event.foot_comment) - } - p.expect(yaml_TAIL_COMMENT_EVENT) - } - } - n.LineComment = string(p.event.line_comment) - n.FootComment = string(p.event.foot_comment) - if n.Style&FlowStyle == 0 && n.FootComment != "" && len(n.Content) > 1 { - n.Content[len(n.Content)-2].FootComment = n.FootComment - n.FootComment = "" - } - p.expect(yaml_MAPPING_END_EVENT) - return n -} - -// ---------------------------------------------------------------------------- -// Decoder, unmarshals a node into a provided value. - -type decoder struct { - doc *Node - aliases map[*Node]bool - terrors []string - - stringMapType reflect.Type - generalMapType reflect.Type - - knownFields bool - uniqueKeys bool - decodeCount int - aliasCount int - aliasDepth int - - mergedFields map[interface{}]bool -} - -var ( - nodeType = reflect.TypeOf(Node{}) - durationType = reflect.TypeOf(time.Duration(0)) - stringMapType = reflect.TypeOf(map[string]interface{}{}) - generalMapType = reflect.TypeOf(map[interface{}]interface{}{}) - ifaceType = generalMapType.Elem() - timeType = reflect.TypeOf(time.Time{}) - ptrTimeType = reflect.TypeOf(&time.Time{}) -) - -func newDecoder() *decoder { - d := &decoder{ - stringMapType: stringMapType, - generalMapType: generalMapType, - uniqueKeys: true, - } - d.aliases = make(map[*Node]bool) - return d -} - -func (d *decoder) terror(n *Node, tag string, out reflect.Value) { - if n.Tag != "" { - tag = n.Tag - } - value := n.Value - if tag != seqTag && tag != mapTag { - if len(value) > 10 { - value = " `" + value[:7] + "...`" - } else { - value = " `" + value + "`" - } - } - d.terrors = append(d.terrors, fmt.Sprintf("line %d: cannot unmarshal %s%s into %s", n.Line, shortTag(tag), value, out.Type())) -} - -func (d *decoder) callUnmarshaler(n *Node, u Unmarshaler) (good bool) { - err := u.UnmarshalYAML(n) - if e, ok := err.(*TypeError); ok { - d.terrors = append(d.terrors, e.Errors...) - return false - } - if err != nil { - fail(err) - } - return true -} - -func (d *decoder) callObsoleteUnmarshaler(n *Node, u obsoleteUnmarshaler) (good bool) { - terrlen := len(d.terrors) - err := u.UnmarshalYAML(func(v interface{}) (err error) { - defer handleErr(&err) - d.unmarshal(n, reflect.ValueOf(v)) - if len(d.terrors) > terrlen { - issues := d.terrors[terrlen:] - d.terrors = d.terrors[:terrlen] - return &TypeError{issues} - } - return nil - }) - if e, ok := err.(*TypeError); ok { - d.terrors = append(d.terrors, e.Errors...) - return false - } - if err != nil { - fail(err) - } - return true -} - -// d.prepare initializes and dereferences pointers and calls UnmarshalYAML -// if a value is found to implement it. -// It returns the initialized and dereferenced out value, whether -// unmarshalling was already done by UnmarshalYAML, and if so whether -// its types unmarshalled appropriately. -// -// If n holds a null value, prepare returns before doing anything. -func (d *decoder) prepare(n *Node, out reflect.Value) (newout reflect.Value, unmarshaled, good bool) { - if n.ShortTag() == nullTag { - return out, false, false - } - again := true - for again { - again = false - if out.Kind() == reflect.Ptr { - if out.IsNil() { - out.Set(reflect.New(out.Type().Elem())) - } - out = out.Elem() - again = true - } - if out.CanAddr() { - outi := out.Addr().Interface() - if u, ok := outi.(Unmarshaler); ok { - good = d.callUnmarshaler(n, u) - return out, true, good - } - if u, ok := outi.(obsoleteUnmarshaler); ok { - good = d.callObsoleteUnmarshaler(n, u) - return out, true, good - } - } - } - return out, false, false -} - -func (d *decoder) fieldByIndex(n *Node, v reflect.Value, index []int) (field reflect.Value) { - if n.ShortTag() == nullTag { - return reflect.Value{} - } - for _, num := range index { - for { - if v.Kind() == reflect.Ptr { - if v.IsNil() { - v.Set(reflect.New(v.Type().Elem())) - } - v = v.Elem() - continue - } - break - } - v = v.Field(num) - } - return v -} - -const ( - // 400,000 decode operations is ~500kb of dense object declarations, or - // ~5kb of dense object declarations with 10000% alias expansion - alias_ratio_range_low = 400000 - - // 4,000,000 decode operations is ~5MB of dense object declarations, or - // ~4.5MB of dense object declarations with 10% alias expansion - alias_ratio_range_high = 4000000 - - // alias_ratio_range is the range over which we scale allowed alias ratios - alias_ratio_range = float64(alias_ratio_range_high - alias_ratio_range_low) -) - -func allowedAliasRatio(decodeCount int) float64 { - switch { - case decodeCount <= alias_ratio_range_low: - // allow 99% to come from alias expansion for small-to-medium documents - return 0.99 - case decodeCount >= alias_ratio_range_high: - // allow 10% to come from alias expansion for very large documents - return 0.10 - default: - // scale smoothly from 99% down to 10% over the range. - // this maps to 396,000 - 400,000 allowed alias-driven decodes over the range. - // 400,000 decode operations is ~100MB of allocations in worst-case scenarios (single-item maps). - return 0.99 - 0.89*(float64(decodeCount-alias_ratio_range_low)/alias_ratio_range) - } -} - -func (d *decoder) unmarshal(n *Node, out reflect.Value) (good bool) { - d.decodeCount++ - if d.aliasDepth > 0 { - d.aliasCount++ - } - if d.aliasCount > 100 && d.decodeCount > 1000 && float64(d.aliasCount)/float64(d.decodeCount) > allowedAliasRatio(d.decodeCount) { - failf("document contains excessive aliasing") - } - if out.Type() == nodeType { - out.Set(reflect.ValueOf(n).Elem()) - return true - } - switch n.Kind { - case DocumentNode: - return d.document(n, out) - case AliasNode: - return d.alias(n, out) - } - out, unmarshaled, good := d.prepare(n, out) - if unmarshaled { - return good - } - switch n.Kind { - case ScalarNode: - good = d.scalar(n, out) - case MappingNode: - good = d.mapping(n, out) - case SequenceNode: - good = d.sequence(n, out) - case 0: - if n.IsZero() { - return d.null(out) - } - fallthrough - default: - failf("cannot decode node with unknown kind %d", n.Kind) - } - return good -} - -func (d *decoder) document(n *Node, out reflect.Value) (good bool) { - if len(n.Content) == 1 { - d.doc = n - d.unmarshal(n.Content[0], out) - return true - } - return false -} - -func (d *decoder) alias(n *Node, out reflect.Value) (good bool) { - if d.aliases[n] { - // TODO this could actually be allowed in some circumstances. - failf("anchor '%s' value contains itself", n.Value) - } - d.aliases[n] = true - d.aliasDepth++ - good = d.unmarshal(n.Alias, out) - d.aliasDepth-- - delete(d.aliases, n) - return good -} - -var zeroValue reflect.Value - -func resetMap(out reflect.Value) { - for _, k := range out.MapKeys() { - out.SetMapIndex(k, zeroValue) - } -} - -func (d *decoder) null(out reflect.Value) bool { - if out.CanAddr() { - switch out.Kind() { - case reflect.Interface, reflect.Ptr, reflect.Map, reflect.Slice: - out.Set(reflect.Zero(out.Type())) - return true - } - } - return false -} - -func (d *decoder) scalar(n *Node, out reflect.Value) bool { - var tag string - var resolved interface{} - if n.indicatedString() { - tag = strTag - resolved = n.Value - } else { - tag, resolved = resolve(n.Tag, n.Value) - if tag == binaryTag { - data, err := base64.StdEncoding.DecodeString(resolved.(string)) - if err != nil { - failf("!!binary value contains invalid base64 data") - } - resolved = string(data) - } - } - if resolved == nil { - return d.null(out) - } - if resolvedv := reflect.ValueOf(resolved); out.Type() == resolvedv.Type() { - // We've resolved to exactly the type we want, so use that. - out.Set(resolvedv) - return true - } - // Perhaps we can use the value as a TextUnmarshaler to - // set its value. - if out.CanAddr() { - u, ok := out.Addr().Interface().(encoding.TextUnmarshaler) - if ok { - var text []byte - if tag == binaryTag { - text = []byte(resolved.(string)) - } else { - // We let any value be unmarshaled into TextUnmarshaler. - // That might be more lax than we'd like, but the - // TextUnmarshaler itself should bowl out any dubious values. - text = []byte(n.Value) - } - err := u.UnmarshalText(text) - if err != nil { - fail(err) - } - return true - } - } - switch out.Kind() { - case reflect.String: - if tag == binaryTag { - out.SetString(resolved.(string)) - return true - } - out.SetString(n.Value) - return true - case reflect.Interface: - out.Set(reflect.ValueOf(resolved)) - return true - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - // This used to work in v2, but it's very unfriendly. - isDuration := out.Type() == durationType - - switch resolved := resolved.(type) { - case int: - if !isDuration && !out.OverflowInt(int64(resolved)) { - out.SetInt(int64(resolved)) - return true - } - case int64: - if !isDuration && !out.OverflowInt(resolved) { - out.SetInt(resolved) - return true - } - case uint64: - if !isDuration && resolved <= math.MaxInt64 && !out.OverflowInt(int64(resolved)) { - out.SetInt(int64(resolved)) - return true - } - case float64: - if !isDuration && resolved <= math.MaxInt64 && !out.OverflowInt(int64(resolved)) { - out.SetInt(int64(resolved)) - return true - } - case string: - if out.Type() == durationType { - d, err := time.ParseDuration(resolved) - if err == nil { - out.SetInt(int64(d)) - return true - } - } - } - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - switch resolved := resolved.(type) { - case int: - if resolved >= 0 && !out.OverflowUint(uint64(resolved)) { - out.SetUint(uint64(resolved)) - return true - } - case int64: - if resolved >= 0 && !out.OverflowUint(uint64(resolved)) { - out.SetUint(uint64(resolved)) - return true - } - case uint64: - if !out.OverflowUint(uint64(resolved)) { - out.SetUint(uint64(resolved)) - return true - } - case float64: - if resolved <= math.MaxUint64 && !out.OverflowUint(uint64(resolved)) { - out.SetUint(uint64(resolved)) - return true - } - } - case reflect.Bool: - switch resolved := resolved.(type) { - case bool: - out.SetBool(resolved) - return true - case string: - // This offers some compatibility with the 1.1 spec (https://yaml.org/type/bool.html). - // It only works if explicitly attempting to unmarshal into a typed bool value. - switch resolved { - case "y", "Y", "yes", "Yes", "YES", "on", "On", "ON": - out.SetBool(true) - return true - case "n", "N", "no", "No", "NO", "off", "Off", "OFF": - out.SetBool(false) - return true - } - } - case reflect.Float32, reflect.Float64: - switch resolved := resolved.(type) { - case int: - out.SetFloat(float64(resolved)) - return true - case int64: - out.SetFloat(float64(resolved)) - return true - case uint64: - out.SetFloat(float64(resolved)) - return true - case float64: - out.SetFloat(resolved) - return true - } - case reflect.Struct: - if resolvedv := reflect.ValueOf(resolved); out.Type() == resolvedv.Type() { - out.Set(resolvedv) - return true - } - case reflect.Ptr: - panic("yaml internal error: please report the issue") - } - d.terror(n, tag, out) - return false -} - -func settableValueOf(i interface{}) reflect.Value { - v := reflect.ValueOf(i) - sv := reflect.New(v.Type()).Elem() - sv.Set(v) - return sv -} - -func (d *decoder) sequence(n *Node, out reflect.Value) (good bool) { - l := len(n.Content) - - var iface reflect.Value - switch out.Kind() { - case reflect.Slice: - out.Set(reflect.MakeSlice(out.Type(), l, l)) - case reflect.Array: - if l != out.Len() { - failf("invalid array: want %d elements but got %d", out.Len(), l) - } - case reflect.Interface: - // No type hints. Will have to use a generic sequence. - iface = out - out = settableValueOf(make([]interface{}, l)) - default: - d.terror(n, seqTag, out) - return false - } - et := out.Type().Elem() - - j := 0 - for i := 0; i < l; i++ { - e := reflect.New(et).Elem() - if ok := d.unmarshal(n.Content[i], e); ok { - out.Index(j).Set(e) - j++ - } - } - if out.Kind() != reflect.Array { - out.Set(out.Slice(0, j)) - } - if iface.IsValid() { - iface.Set(out) - } - return true -} - -func (d *decoder) mapping(n *Node, out reflect.Value) (good bool) { - l := len(n.Content) - if d.uniqueKeys { - nerrs := len(d.terrors) - for i := 0; i < l; i += 2 { - ni := n.Content[i] - for j := i + 2; j < l; j += 2 { - nj := n.Content[j] - if ni.Kind == nj.Kind && ni.Value == nj.Value { - d.terrors = append(d.terrors, fmt.Sprintf("line %d: mapping key %#v already defined at line %d", nj.Line, nj.Value, ni.Line)) - } - } - } - if len(d.terrors) > nerrs { - return false - } - } - switch out.Kind() { - case reflect.Struct: - return d.mappingStruct(n, out) - case reflect.Map: - // okay - case reflect.Interface: - iface := out - if isStringMap(n) { - out = reflect.MakeMap(d.stringMapType) - } else { - out = reflect.MakeMap(d.generalMapType) - } - iface.Set(out) - default: - d.terror(n, mapTag, out) - return false - } - - outt := out.Type() - kt := outt.Key() - et := outt.Elem() - - stringMapType := d.stringMapType - generalMapType := d.generalMapType - if outt.Elem() == ifaceType { - if outt.Key().Kind() == reflect.String { - d.stringMapType = outt - } else if outt.Key() == ifaceType { - d.generalMapType = outt - } - } - - mergedFields := d.mergedFields - d.mergedFields = nil - - var mergeNode *Node - - mapIsNew := false - if out.IsNil() { - out.Set(reflect.MakeMap(outt)) - mapIsNew = true - } - for i := 0; i < l; i += 2 { - if isMerge(n.Content[i]) { - mergeNode = n.Content[i+1] - continue - } - k := reflect.New(kt).Elem() - if d.unmarshal(n.Content[i], k) { - if mergedFields != nil { - ki := k.Interface() - if mergedFields[ki] { - continue - } - mergedFields[ki] = true - } - kkind := k.Kind() - if kkind == reflect.Interface { - kkind = k.Elem().Kind() - } - if kkind == reflect.Map || kkind == reflect.Slice { - failf("invalid map key: %#v", k.Interface()) - } - e := reflect.New(et).Elem() - if d.unmarshal(n.Content[i+1], e) || n.Content[i+1].ShortTag() == nullTag && (mapIsNew || !out.MapIndex(k).IsValid()) { - out.SetMapIndex(k, e) - } - } - } - - d.mergedFields = mergedFields - if mergeNode != nil { - d.merge(n, mergeNode, out) - } - - d.stringMapType = stringMapType - d.generalMapType = generalMapType - return true -} - -func isStringMap(n *Node) bool { - if n.Kind != MappingNode { - return false - } - l := len(n.Content) - for i := 0; i < l; i += 2 { - shortTag := n.Content[i].ShortTag() - if shortTag != strTag && shortTag != mergeTag { - return false - } - } - return true -} - -func (d *decoder) mappingStruct(n *Node, out reflect.Value) (good bool) { - sinfo, err := getStructInfo(out.Type()) - if err != nil { - panic(err) - } - - var inlineMap reflect.Value - var elemType reflect.Type - if sinfo.InlineMap != -1 { - inlineMap = out.Field(sinfo.InlineMap) - elemType = inlineMap.Type().Elem() - } - - for _, index := range sinfo.InlineUnmarshalers { - field := d.fieldByIndex(n, out, index) - d.prepare(n, field) - } - - mergedFields := d.mergedFields - d.mergedFields = nil - var mergeNode *Node - var doneFields []bool - if d.uniqueKeys { - doneFields = make([]bool, len(sinfo.FieldsList)) - } - name := settableValueOf("") - l := len(n.Content) - for i := 0; i < l; i += 2 { - ni := n.Content[i] - if isMerge(ni) { - mergeNode = n.Content[i+1] - continue - } - if !d.unmarshal(ni, name) { - continue - } - sname := name.String() - if mergedFields != nil { - if mergedFields[sname] { - continue - } - mergedFields[sname] = true - } - if info, ok := sinfo.FieldsMap[sname]; ok { - if d.uniqueKeys { - if doneFields[info.Id] { - d.terrors = append(d.terrors, fmt.Sprintf("line %d: field %s already set in type %s", ni.Line, name.String(), out.Type())) - continue - } - doneFields[info.Id] = true - } - var field reflect.Value - if info.Inline == nil { - field = out.Field(info.Num) - } else { - field = d.fieldByIndex(n, out, info.Inline) - } - d.unmarshal(n.Content[i+1], field) - } else if sinfo.InlineMap != -1 { - if inlineMap.IsNil() { - inlineMap.Set(reflect.MakeMap(inlineMap.Type())) - } - value := reflect.New(elemType).Elem() - d.unmarshal(n.Content[i+1], value) - inlineMap.SetMapIndex(name, value) - } else if d.knownFields { - d.terrors = append(d.terrors, fmt.Sprintf("line %d: field %s not found in type %s", ni.Line, name.String(), out.Type())) - } - } - - d.mergedFields = mergedFields - if mergeNode != nil { - d.merge(n, mergeNode, out) - } - return true -} - -func failWantMap() { - failf("map merge requires map or sequence of maps as the value") -} - -func (d *decoder) merge(parent *Node, merge *Node, out reflect.Value) { - mergedFields := d.mergedFields - if mergedFields == nil { - d.mergedFields = make(map[interface{}]bool) - for i := 0; i < len(parent.Content); i += 2 { - k := reflect.New(ifaceType).Elem() - if d.unmarshal(parent.Content[i], k) { - d.mergedFields[k.Interface()] = true - } - } - } - - switch merge.Kind { - case MappingNode: - d.unmarshal(merge, out) - case AliasNode: - if merge.Alias != nil && merge.Alias.Kind != MappingNode { - failWantMap() - } - d.unmarshal(merge, out) - case SequenceNode: - for i := 0; i < len(merge.Content); i++ { - ni := merge.Content[i] - if ni.Kind == AliasNode { - if ni.Alias != nil && ni.Alias.Kind != MappingNode { - failWantMap() - } - } else if ni.Kind != MappingNode { - failWantMap() - } - d.unmarshal(ni, out) - } - default: - failWantMap() - } - - d.mergedFields = mergedFields -} - -func isMerge(n *Node) bool { - return n.Kind == ScalarNode && n.Value == "<<" && (n.Tag == "" || n.Tag == "!" || shortTag(n.Tag) == mergeTag) -} diff --git a/trunk/3rdparty/srs-bench/vendor/gopkg.in/yaml.v3/emitterc.go b/trunk/3rdparty/srs-bench/vendor/gopkg.in/yaml.v3/emitterc.go deleted file mode 100644 index 0f47c9ca8..000000000 --- a/trunk/3rdparty/srs-bench/vendor/gopkg.in/yaml.v3/emitterc.go +++ /dev/null @@ -1,2020 +0,0 @@ -// -// Copyright (c) 2011-2019 Canonical Ltd -// Copyright (c) 2006-2010 Kirill Simonov -// -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -// of the Software, and to permit persons to whom the Software is furnished to do -// so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -package yaml - -import ( - "bytes" - "fmt" -) - -// Flush the buffer if needed. -func flush(emitter *yaml_emitter_t) bool { - if emitter.buffer_pos+5 >= len(emitter.buffer) { - return yaml_emitter_flush(emitter) - } - return true -} - -// Put a character to the output buffer. -func put(emitter *yaml_emitter_t, value byte) bool { - if emitter.buffer_pos+5 >= len(emitter.buffer) && !yaml_emitter_flush(emitter) { - return false - } - emitter.buffer[emitter.buffer_pos] = value - emitter.buffer_pos++ - emitter.column++ - return true -} - -// Put a line break to the output buffer. -func put_break(emitter *yaml_emitter_t) bool { - if emitter.buffer_pos+5 >= len(emitter.buffer) && !yaml_emitter_flush(emitter) { - return false - } - switch emitter.line_break { - case yaml_CR_BREAK: - emitter.buffer[emitter.buffer_pos] = '\r' - emitter.buffer_pos += 1 - case yaml_LN_BREAK: - emitter.buffer[emitter.buffer_pos] = '\n' - emitter.buffer_pos += 1 - case yaml_CRLN_BREAK: - emitter.buffer[emitter.buffer_pos+0] = '\r' - emitter.buffer[emitter.buffer_pos+1] = '\n' - emitter.buffer_pos += 2 - default: - panic("unknown line break setting") - } - if emitter.column == 0 { - emitter.space_above = true - } - emitter.column = 0 - emitter.line++ - // [Go] Do this here and below and drop from everywhere else (see commented lines). - emitter.indention = true - return true -} - -// Copy a character from a string into buffer. -func write(emitter *yaml_emitter_t, s []byte, i *int) bool { - if emitter.buffer_pos+5 >= len(emitter.buffer) && !yaml_emitter_flush(emitter) { - return false - } - p := emitter.buffer_pos - w := width(s[*i]) - switch w { - case 4: - emitter.buffer[p+3] = s[*i+3] - fallthrough - case 3: - emitter.buffer[p+2] = s[*i+2] - fallthrough - case 2: - emitter.buffer[p+1] = s[*i+1] - fallthrough - case 1: - emitter.buffer[p+0] = s[*i+0] - default: - panic("unknown character width") - } - emitter.column++ - emitter.buffer_pos += w - *i += w - return true -} - -// Write a whole string into buffer. -func write_all(emitter *yaml_emitter_t, s []byte) bool { - for i := 0; i < len(s); { - if !write(emitter, s, &i) { - return false - } - } - return true -} - -// Copy a line break character from a string into buffer. -func write_break(emitter *yaml_emitter_t, s []byte, i *int) bool { - if s[*i] == '\n' { - if !put_break(emitter) { - return false - } - *i++ - } else { - if !write(emitter, s, i) { - return false - } - if emitter.column == 0 { - emitter.space_above = true - } - emitter.column = 0 - emitter.line++ - // [Go] Do this here and above and drop from everywhere else (see commented lines). - emitter.indention = true - } - return true -} - -// Set an emitter error and return false. -func yaml_emitter_set_emitter_error(emitter *yaml_emitter_t, problem string) bool { - emitter.error = yaml_EMITTER_ERROR - emitter.problem = problem - return false -} - -// Emit an event. -func yaml_emitter_emit(emitter *yaml_emitter_t, event *yaml_event_t) bool { - emitter.events = append(emitter.events, *event) - for !yaml_emitter_need_more_events(emitter) { - event := &emitter.events[emitter.events_head] - if !yaml_emitter_analyze_event(emitter, event) { - return false - } - if !yaml_emitter_state_machine(emitter, event) { - return false - } - yaml_event_delete(event) - emitter.events_head++ - } - return true -} - -// Check if we need to accumulate more events before emitting. -// -// We accumulate extra -// - 1 event for DOCUMENT-START -// - 2 events for SEQUENCE-START -// - 3 events for MAPPING-START -// -func yaml_emitter_need_more_events(emitter *yaml_emitter_t) bool { - if emitter.events_head == len(emitter.events) { - return true - } - var accumulate int - switch emitter.events[emitter.events_head].typ { - case yaml_DOCUMENT_START_EVENT: - accumulate = 1 - break - case yaml_SEQUENCE_START_EVENT: - accumulate = 2 - break - case yaml_MAPPING_START_EVENT: - accumulate = 3 - break - default: - return false - } - if len(emitter.events)-emitter.events_head > accumulate { - return false - } - var level int - for i := emitter.events_head; i < len(emitter.events); i++ { - switch emitter.events[i].typ { - case yaml_STREAM_START_EVENT, yaml_DOCUMENT_START_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT: - level++ - case yaml_STREAM_END_EVENT, yaml_DOCUMENT_END_EVENT, yaml_SEQUENCE_END_EVENT, yaml_MAPPING_END_EVENT: - level-- - } - if level == 0 { - return false - } - } - return true -} - -// Append a directive to the directives stack. -func yaml_emitter_append_tag_directive(emitter *yaml_emitter_t, value *yaml_tag_directive_t, allow_duplicates bool) bool { - for i := 0; i < len(emitter.tag_directives); i++ { - if bytes.Equal(value.handle, emitter.tag_directives[i].handle) { - if allow_duplicates { - return true - } - return yaml_emitter_set_emitter_error(emitter, "duplicate %TAG directive") - } - } - - // [Go] Do we actually need to copy this given garbage collection - // and the lack of deallocating destructors? - tag_copy := yaml_tag_directive_t{ - handle: make([]byte, len(value.handle)), - prefix: make([]byte, len(value.prefix)), - } - copy(tag_copy.handle, value.handle) - copy(tag_copy.prefix, value.prefix) - emitter.tag_directives = append(emitter.tag_directives, tag_copy) - return true -} - -// Increase the indentation level. -func yaml_emitter_increase_indent(emitter *yaml_emitter_t, flow, indentless bool) bool { - emitter.indents = append(emitter.indents, emitter.indent) - if emitter.indent < 0 { - if flow { - emitter.indent = emitter.best_indent - } else { - emitter.indent = 0 - } - } else if !indentless { - // [Go] This was changed so that indentations are more regular. - if emitter.states[len(emitter.states)-1] == yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE { - // The first indent inside a sequence will just skip the "- " indicator. - emitter.indent += 2 - } else { - // Everything else aligns to the chosen indentation. - emitter.indent = emitter.best_indent*((emitter.indent+emitter.best_indent)/emitter.best_indent) - } - } - return true -} - -// State dispatcher. -func yaml_emitter_state_machine(emitter *yaml_emitter_t, event *yaml_event_t) bool { - switch emitter.state { - default: - case yaml_EMIT_STREAM_START_STATE: - return yaml_emitter_emit_stream_start(emitter, event) - - case yaml_EMIT_FIRST_DOCUMENT_START_STATE: - return yaml_emitter_emit_document_start(emitter, event, true) - - case yaml_EMIT_DOCUMENT_START_STATE: - return yaml_emitter_emit_document_start(emitter, event, false) - - case yaml_EMIT_DOCUMENT_CONTENT_STATE: - return yaml_emitter_emit_document_content(emitter, event) - - case yaml_EMIT_DOCUMENT_END_STATE: - return yaml_emitter_emit_document_end(emitter, event) - - case yaml_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE: - return yaml_emitter_emit_flow_sequence_item(emitter, event, true, false) - - case yaml_EMIT_FLOW_SEQUENCE_TRAIL_ITEM_STATE: - return yaml_emitter_emit_flow_sequence_item(emitter, event, false, true) - - case yaml_EMIT_FLOW_SEQUENCE_ITEM_STATE: - return yaml_emitter_emit_flow_sequence_item(emitter, event, false, false) - - case yaml_EMIT_FLOW_MAPPING_FIRST_KEY_STATE: - return yaml_emitter_emit_flow_mapping_key(emitter, event, true, false) - - case yaml_EMIT_FLOW_MAPPING_TRAIL_KEY_STATE: - return yaml_emitter_emit_flow_mapping_key(emitter, event, false, true) - - case yaml_EMIT_FLOW_MAPPING_KEY_STATE: - return yaml_emitter_emit_flow_mapping_key(emitter, event, false, false) - - case yaml_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE: - return yaml_emitter_emit_flow_mapping_value(emitter, event, true) - - case yaml_EMIT_FLOW_MAPPING_VALUE_STATE: - return yaml_emitter_emit_flow_mapping_value(emitter, event, false) - - case yaml_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE: - return yaml_emitter_emit_block_sequence_item(emitter, event, true) - - case yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE: - return yaml_emitter_emit_block_sequence_item(emitter, event, false) - - case yaml_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE: - return yaml_emitter_emit_block_mapping_key(emitter, event, true) - - case yaml_EMIT_BLOCK_MAPPING_KEY_STATE: - return yaml_emitter_emit_block_mapping_key(emitter, event, false) - - case yaml_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE: - return yaml_emitter_emit_block_mapping_value(emitter, event, true) - - case yaml_EMIT_BLOCK_MAPPING_VALUE_STATE: - return yaml_emitter_emit_block_mapping_value(emitter, event, false) - - case yaml_EMIT_END_STATE: - return yaml_emitter_set_emitter_error(emitter, "expected nothing after STREAM-END") - } - panic("invalid emitter state") -} - -// Expect STREAM-START. -func yaml_emitter_emit_stream_start(emitter *yaml_emitter_t, event *yaml_event_t) bool { - if event.typ != yaml_STREAM_START_EVENT { - return yaml_emitter_set_emitter_error(emitter, "expected STREAM-START") - } - if emitter.encoding == yaml_ANY_ENCODING { - emitter.encoding = event.encoding - if emitter.encoding == yaml_ANY_ENCODING { - emitter.encoding = yaml_UTF8_ENCODING - } - } - if emitter.best_indent < 2 || emitter.best_indent > 9 { - emitter.best_indent = 2 - } - if emitter.best_width >= 0 && emitter.best_width <= emitter.best_indent*2 { - emitter.best_width = 80 - } - if emitter.best_width < 0 { - emitter.best_width = 1<<31 - 1 - } - if emitter.line_break == yaml_ANY_BREAK { - emitter.line_break = yaml_LN_BREAK - } - - emitter.indent = -1 - emitter.line = 0 - emitter.column = 0 - emitter.whitespace = true - emitter.indention = true - emitter.space_above = true - emitter.foot_indent = -1 - - if emitter.encoding != yaml_UTF8_ENCODING { - if !yaml_emitter_write_bom(emitter) { - return false - } - } - emitter.state = yaml_EMIT_FIRST_DOCUMENT_START_STATE - return true -} - -// Expect DOCUMENT-START or STREAM-END. -func yaml_emitter_emit_document_start(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool { - - if event.typ == yaml_DOCUMENT_START_EVENT { - - if event.version_directive != nil { - if !yaml_emitter_analyze_version_directive(emitter, event.version_directive) { - return false - } - } - - for i := 0; i < len(event.tag_directives); i++ { - tag_directive := &event.tag_directives[i] - if !yaml_emitter_analyze_tag_directive(emitter, tag_directive) { - return false - } - if !yaml_emitter_append_tag_directive(emitter, tag_directive, false) { - return false - } - } - - for i := 0; i < len(default_tag_directives); i++ { - tag_directive := &default_tag_directives[i] - if !yaml_emitter_append_tag_directive(emitter, tag_directive, true) { - return false - } - } - - implicit := event.implicit - if !first || emitter.canonical { - implicit = false - } - - if emitter.open_ended && (event.version_directive != nil || len(event.tag_directives) > 0) { - if !yaml_emitter_write_indicator(emitter, []byte("..."), true, false, false) { - return false - } - if !yaml_emitter_write_indent(emitter) { - return false - } - } - - if event.version_directive != nil { - implicit = false - if !yaml_emitter_write_indicator(emitter, []byte("%YAML"), true, false, false) { - return false - } - if !yaml_emitter_write_indicator(emitter, []byte("1.1"), true, false, false) { - return false - } - if !yaml_emitter_write_indent(emitter) { - return false - } - } - - if len(event.tag_directives) > 0 { - implicit = false - for i := 0; i < len(event.tag_directives); i++ { - tag_directive := &event.tag_directives[i] - if !yaml_emitter_write_indicator(emitter, []byte("%TAG"), true, false, false) { - return false - } - if !yaml_emitter_write_tag_handle(emitter, tag_directive.handle) { - return false - } - if !yaml_emitter_write_tag_content(emitter, tag_directive.prefix, true) { - return false - } - if !yaml_emitter_write_indent(emitter) { - return false - } - } - } - - if yaml_emitter_check_empty_document(emitter) { - implicit = false - } - if !implicit { - if !yaml_emitter_write_indent(emitter) { - return false - } - if !yaml_emitter_write_indicator(emitter, []byte("---"), true, false, false) { - return false - } - if emitter.canonical || true { - if !yaml_emitter_write_indent(emitter) { - return false - } - } - } - - if len(emitter.head_comment) > 0 { - if !yaml_emitter_process_head_comment(emitter) { - return false - } - if !put_break(emitter) { - return false - } - } - - emitter.state = yaml_EMIT_DOCUMENT_CONTENT_STATE - return true - } - - if event.typ == yaml_STREAM_END_EVENT { - if emitter.open_ended { - if !yaml_emitter_write_indicator(emitter, []byte("..."), true, false, false) { - return false - } - if !yaml_emitter_write_indent(emitter) { - return false - } - } - if !yaml_emitter_flush(emitter) { - return false - } - emitter.state = yaml_EMIT_END_STATE - return true - } - - return yaml_emitter_set_emitter_error(emitter, "expected DOCUMENT-START or STREAM-END") -} - -// Expect the root node. -func yaml_emitter_emit_document_content(emitter *yaml_emitter_t, event *yaml_event_t) bool { - emitter.states = append(emitter.states, yaml_EMIT_DOCUMENT_END_STATE) - - if !yaml_emitter_process_head_comment(emitter) { - return false - } - if !yaml_emitter_emit_node(emitter, event, true, false, false, false) { - return false - } - if !yaml_emitter_process_line_comment(emitter) { - return false - } - if !yaml_emitter_process_foot_comment(emitter) { - return false - } - return true -} - -// Expect DOCUMENT-END. -func yaml_emitter_emit_document_end(emitter *yaml_emitter_t, event *yaml_event_t) bool { - if event.typ != yaml_DOCUMENT_END_EVENT { - return yaml_emitter_set_emitter_error(emitter, "expected DOCUMENT-END") - } - // [Go] Force document foot separation. - emitter.foot_indent = 0 - if !yaml_emitter_process_foot_comment(emitter) { - return false - } - emitter.foot_indent = -1 - if !yaml_emitter_write_indent(emitter) { - return false - } - if !event.implicit { - // [Go] Allocate the slice elsewhere. - if !yaml_emitter_write_indicator(emitter, []byte("..."), true, false, false) { - return false - } - if !yaml_emitter_write_indent(emitter) { - return false - } - } - if !yaml_emitter_flush(emitter) { - return false - } - emitter.state = yaml_EMIT_DOCUMENT_START_STATE - emitter.tag_directives = emitter.tag_directives[:0] - return true -} - -// Expect a flow item node. -func yaml_emitter_emit_flow_sequence_item(emitter *yaml_emitter_t, event *yaml_event_t, first, trail bool) bool { - if first { - if !yaml_emitter_write_indicator(emitter, []byte{'['}, true, true, false) { - return false - } - if !yaml_emitter_increase_indent(emitter, true, false) { - return false - } - emitter.flow_level++ - } - - if event.typ == yaml_SEQUENCE_END_EVENT { - if emitter.canonical && !first && !trail { - if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) { - return false - } - } - emitter.flow_level-- - emitter.indent = emitter.indents[len(emitter.indents)-1] - emitter.indents = emitter.indents[:len(emitter.indents)-1] - if emitter.column == 0 || emitter.canonical && !first { - if !yaml_emitter_write_indent(emitter) { - return false - } - } - if !yaml_emitter_write_indicator(emitter, []byte{']'}, false, false, false) { - return false - } - if !yaml_emitter_process_line_comment(emitter) { - return false - } - if !yaml_emitter_process_foot_comment(emitter) { - return false - } - emitter.state = emitter.states[len(emitter.states)-1] - emitter.states = emitter.states[:len(emitter.states)-1] - - return true - } - - if !first && !trail { - if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) { - return false - } - } - - if !yaml_emitter_process_head_comment(emitter) { - return false - } - if emitter.column == 0 { - if !yaml_emitter_write_indent(emitter) { - return false - } - } - - if emitter.canonical || emitter.column > emitter.best_width { - if !yaml_emitter_write_indent(emitter) { - return false - } - } - if len(emitter.line_comment)+len(emitter.foot_comment)+len(emitter.tail_comment) > 0 { - emitter.states = append(emitter.states, yaml_EMIT_FLOW_SEQUENCE_TRAIL_ITEM_STATE) - } else { - emitter.states = append(emitter.states, yaml_EMIT_FLOW_SEQUENCE_ITEM_STATE) - } - if !yaml_emitter_emit_node(emitter, event, false, true, false, false) { - return false - } - if len(emitter.line_comment)+len(emitter.foot_comment)+len(emitter.tail_comment) > 0 { - if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) { - return false - } - } - if !yaml_emitter_process_line_comment(emitter) { - return false - } - if !yaml_emitter_process_foot_comment(emitter) { - return false - } - return true -} - -// Expect a flow key node. -func yaml_emitter_emit_flow_mapping_key(emitter *yaml_emitter_t, event *yaml_event_t, first, trail bool) bool { - if first { - if !yaml_emitter_write_indicator(emitter, []byte{'{'}, true, true, false) { - return false - } - if !yaml_emitter_increase_indent(emitter, true, false) { - return false - } - emitter.flow_level++ - } - - if event.typ == yaml_MAPPING_END_EVENT { - if (emitter.canonical || len(emitter.head_comment)+len(emitter.foot_comment)+len(emitter.tail_comment) > 0) && !first && !trail { - if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) { - return false - } - } - if !yaml_emitter_process_head_comment(emitter) { - return false - } - emitter.flow_level-- - emitter.indent = emitter.indents[len(emitter.indents)-1] - emitter.indents = emitter.indents[:len(emitter.indents)-1] - if emitter.canonical && !first { - if !yaml_emitter_write_indent(emitter) { - return false - } - } - if !yaml_emitter_write_indicator(emitter, []byte{'}'}, false, false, false) { - return false - } - if !yaml_emitter_process_line_comment(emitter) { - return false - } - if !yaml_emitter_process_foot_comment(emitter) { - return false - } - emitter.state = emitter.states[len(emitter.states)-1] - emitter.states = emitter.states[:len(emitter.states)-1] - return true - } - - if !first && !trail { - if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) { - return false - } - } - - if !yaml_emitter_process_head_comment(emitter) { - return false - } - - if emitter.column == 0 { - if !yaml_emitter_write_indent(emitter) { - return false - } - } - - if emitter.canonical || emitter.column > emitter.best_width { - if !yaml_emitter_write_indent(emitter) { - return false - } - } - - if !emitter.canonical && yaml_emitter_check_simple_key(emitter) { - emitter.states = append(emitter.states, yaml_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE) - return yaml_emitter_emit_node(emitter, event, false, false, true, true) - } - if !yaml_emitter_write_indicator(emitter, []byte{'?'}, true, false, false) { - return false - } - emitter.states = append(emitter.states, yaml_EMIT_FLOW_MAPPING_VALUE_STATE) - return yaml_emitter_emit_node(emitter, event, false, false, true, false) -} - -// Expect a flow value node. -func yaml_emitter_emit_flow_mapping_value(emitter *yaml_emitter_t, event *yaml_event_t, simple bool) bool { - if simple { - if !yaml_emitter_write_indicator(emitter, []byte{':'}, false, false, false) { - return false - } - } else { - if emitter.canonical || emitter.column > emitter.best_width { - if !yaml_emitter_write_indent(emitter) { - return false - } - } - if !yaml_emitter_write_indicator(emitter, []byte{':'}, true, false, false) { - return false - } - } - if len(emitter.line_comment)+len(emitter.foot_comment)+len(emitter.tail_comment) > 0 { - emitter.states = append(emitter.states, yaml_EMIT_FLOW_MAPPING_TRAIL_KEY_STATE) - } else { - emitter.states = append(emitter.states, yaml_EMIT_FLOW_MAPPING_KEY_STATE) - } - if !yaml_emitter_emit_node(emitter, event, false, false, true, false) { - return false - } - if len(emitter.line_comment)+len(emitter.foot_comment)+len(emitter.tail_comment) > 0 { - if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) { - return false - } - } - if !yaml_emitter_process_line_comment(emitter) { - return false - } - if !yaml_emitter_process_foot_comment(emitter) { - return false - } - return true -} - -// Expect a block item node. -func yaml_emitter_emit_block_sequence_item(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool { - if first { - if !yaml_emitter_increase_indent(emitter, false, false) { - return false - } - } - if event.typ == yaml_SEQUENCE_END_EVENT { - emitter.indent = emitter.indents[len(emitter.indents)-1] - emitter.indents = emitter.indents[:len(emitter.indents)-1] - emitter.state = emitter.states[len(emitter.states)-1] - emitter.states = emitter.states[:len(emitter.states)-1] - return true - } - if !yaml_emitter_process_head_comment(emitter) { - return false - } - if !yaml_emitter_write_indent(emitter) { - return false - } - if !yaml_emitter_write_indicator(emitter, []byte{'-'}, true, false, true) { - return false - } - emitter.states = append(emitter.states, yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE) - if !yaml_emitter_emit_node(emitter, event, false, true, false, false) { - return false - } - if !yaml_emitter_process_line_comment(emitter) { - return false - } - if !yaml_emitter_process_foot_comment(emitter) { - return false - } - return true -} - -// Expect a block key node. -func yaml_emitter_emit_block_mapping_key(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool { - if first { - if !yaml_emitter_increase_indent(emitter, false, false) { - return false - } - } - if !yaml_emitter_process_head_comment(emitter) { - return false - } - if event.typ == yaml_MAPPING_END_EVENT { - emitter.indent = emitter.indents[len(emitter.indents)-1] - emitter.indents = emitter.indents[:len(emitter.indents)-1] - emitter.state = emitter.states[len(emitter.states)-1] - emitter.states = emitter.states[:len(emitter.states)-1] - return true - } - if !yaml_emitter_write_indent(emitter) { - return false - } - if len(emitter.line_comment) > 0 { - // [Go] A line comment was provided for the key. That's unusual as the - // scanner associates line comments with the value. Either way, - // save the line comment and render it appropriately later. - emitter.key_line_comment = emitter.line_comment - emitter.line_comment = nil - } - if yaml_emitter_check_simple_key(emitter) { - emitter.states = append(emitter.states, yaml_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE) - return yaml_emitter_emit_node(emitter, event, false, false, true, true) - } - if !yaml_emitter_write_indicator(emitter, []byte{'?'}, true, false, true) { - return false - } - emitter.states = append(emitter.states, yaml_EMIT_BLOCK_MAPPING_VALUE_STATE) - return yaml_emitter_emit_node(emitter, event, false, false, true, false) -} - -// Expect a block value node. -func yaml_emitter_emit_block_mapping_value(emitter *yaml_emitter_t, event *yaml_event_t, simple bool) bool { - if simple { - if !yaml_emitter_write_indicator(emitter, []byte{':'}, false, false, false) { - return false - } - } else { - if !yaml_emitter_write_indent(emitter) { - return false - } - if !yaml_emitter_write_indicator(emitter, []byte{':'}, true, false, true) { - return false - } - } - if len(emitter.key_line_comment) > 0 { - // [Go] Line comments are generally associated with the value, but when there's - // no value on the same line as a mapping key they end up attached to the - // key itself. - if event.typ == yaml_SCALAR_EVENT { - if len(emitter.line_comment) == 0 { - // A scalar is coming and it has no line comments by itself yet, - // so just let it handle the line comment as usual. If it has a - // line comment, we can't have both so the one from the key is lost. - emitter.line_comment = emitter.key_line_comment - emitter.key_line_comment = nil - } - } else if event.sequence_style() != yaml_FLOW_SEQUENCE_STYLE && (event.typ == yaml_MAPPING_START_EVENT || event.typ == yaml_SEQUENCE_START_EVENT) { - // An indented block follows, so write the comment right now. - emitter.line_comment, emitter.key_line_comment = emitter.key_line_comment, emitter.line_comment - if !yaml_emitter_process_line_comment(emitter) { - return false - } - emitter.line_comment, emitter.key_line_comment = emitter.key_line_comment, emitter.line_comment - } - } - emitter.states = append(emitter.states, yaml_EMIT_BLOCK_MAPPING_KEY_STATE) - if !yaml_emitter_emit_node(emitter, event, false, false, true, false) { - return false - } - if !yaml_emitter_process_line_comment(emitter) { - return false - } - if !yaml_emitter_process_foot_comment(emitter) { - return false - } - return true -} - -func yaml_emitter_silent_nil_event(emitter *yaml_emitter_t, event *yaml_event_t) bool { - return event.typ == yaml_SCALAR_EVENT && event.implicit && !emitter.canonical && len(emitter.scalar_data.value) == 0 -} - -// Expect a node. -func yaml_emitter_emit_node(emitter *yaml_emitter_t, event *yaml_event_t, - root bool, sequence bool, mapping bool, simple_key bool) bool { - - emitter.root_context = root - emitter.sequence_context = sequence - emitter.mapping_context = mapping - emitter.simple_key_context = simple_key - - switch event.typ { - case yaml_ALIAS_EVENT: - return yaml_emitter_emit_alias(emitter, event) - case yaml_SCALAR_EVENT: - return yaml_emitter_emit_scalar(emitter, event) - case yaml_SEQUENCE_START_EVENT: - return yaml_emitter_emit_sequence_start(emitter, event) - case yaml_MAPPING_START_EVENT: - return yaml_emitter_emit_mapping_start(emitter, event) - default: - return yaml_emitter_set_emitter_error(emitter, - fmt.Sprintf("expected SCALAR, SEQUENCE-START, MAPPING-START, or ALIAS, but got %v", event.typ)) - } -} - -// Expect ALIAS. -func yaml_emitter_emit_alias(emitter *yaml_emitter_t, event *yaml_event_t) bool { - if !yaml_emitter_process_anchor(emitter) { - return false - } - emitter.state = emitter.states[len(emitter.states)-1] - emitter.states = emitter.states[:len(emitter.states)-1] - return true -} - -// Expect SCALAR. -func yaml_emitter_emit_scalar(emitter *yaml_emitter_t, event *yaml_event_t) bool { - if !yaml_emitter_select_scalar_style(emitter, event) { - return false - } - if !yaml_emitter_process_anchor(emitter) { - return false - } - if !yaml_emitter_process_tag(emitter) { - return false - } - if !yaml_emitter_increase_indent(emitter, true, false) { - return false - } - if !yaml_emitter_process_scalar(emitter) { - return false - } - emitter.indent = emitter.indents[len(emitter.indents)-1] - emitter.indents = emitter.indents[:len(emitter.indents)-1] - emitter.state = emitter.states[len(emitter.states)-1] - emitter.states = emitter.states[:len(emitter.states)-1] - return true -} - -// Expect SEQUENCE-START. -func yaml_emitter_emit_sequence_start(emitter *yaml_emitter_t, event *yaml_event_t) bool { - if !yaml_emitter_process_anchor(emitter) { - return false - } - if !yaml_emitter_process_tag(emitter) { - return false - } - if emitter.flow_level > 0 || emitter.canonical || event.sequence_style() == yaml_FLOW_SEQUENCE_STYLE || - yaml_emitter_check_empty_sequence(emitter) { - emitter.state = yaml_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE - } else { - emitter.state = yaml_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE - } - return true -} - -// Expect MAPPING-START. -func yaml_emitter_emit_mapping_start(emitter *yaml_emitter_t, event *yaml_event_t) bool { - if !yaml_emitter_process_anchor(emitter) { - return false - } - if !yaml_emitter_process_tag(emitter) { - return false - } - if emitter.flow_level > 0 || emitter.canonical || event.mapping_style() == yaml_FLOW_MAPPING_STYLE || - yaml_emitter_check_empty_mapping(emitter) { - emitter.state = yaml_EMIT_FLOW_MAPPING_FIRST_KEY_STATE - } else { - emitter.state = yaml_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE - } - return true -} - -// Check if the document content is an empty scalar. -func yaml_emitter_check_empty_document(emitter *yaml_emitter_t) bool { - return false // [Go] Huh? -} - -// Check if the next events represent an empty sequence. -func yaml_emitter_check_empty_sequence(emitter *yaml_emitter_t) bool { - if len(emitter.events)-emitter.events_head < 2 { - return false - } - return emitter.events[emitter.events_head].typ == yaml_SEQUENCE_START_EVENT && - emitter.events[emitter.events_head+1].typ == yaml_SEQUENCE_END_EVENT -} - -// Check if the next events represent an empty mapping. -func yaml_emitter_check_empty_mapping(emitter *yaml_emitter_t) bool { - if len(emitter.events)-emitter.events_head < 2 { - return false - } - return emitter.events[emitter.events_head].typ == yaml_MAPPING_START_EVENT && - emitter.events[emitter.events_head+1].typ == yaml_MAPPING_END_EVENT -} - -// Check if the next node can be expressed as a simple key. -func yaml_emitter_check_simple_key(emitter *yaml_emitter_t) bool { - length := 0 - switch emitter.events[emitter.events_head].typ { - case yaml_ALIAS_EVENT: - length += len(emitter.anchor_data.anchor) - case yaml_SCALAR_EVENT: - if emitter.scalar_data.multiline { - return false - } - length += len(emitter.anchor_data.anchor) + - len(emitter.tag_data.handle) + - len(emitter.tag_data.suffix) + - len(emitter.scalar_data.value) - case yaml_SEQUENCE_START_EVENT: - if !yaml_emitter_check_empty_sequence(emitter) { - return false - } - length += len(emitter.anchor_data.anchor) + - len(emitter.tag_data.handle) + - len(emitter.tag_data.suffix) - case yaml_MAPPING_START_EVENT: - if !yaml_emitter_check_empty_mapping(emitter) { - return false - } - length += len(emitter.anchor_data.anchor) + - len(emitter.tag_data.handle) + - len(emitter.tag_data.suffix) - default: - return false - } - return length <= 128 -} - -// Determine an acceptable scalar style. -func yaml_emitter_select_scalar_style(emitter *yaml_emitter_t, event *yaml_event_t) bool { - - no_tag := len(emitter.tag_data.handle) == 0 && len(emitter.tag_data.suffix) == 0 - if no_tag && !event.implicit && !event.quoted_implicit { - return yaml_emitter_set_emitter_error(emitter, "neither tag nor implicit flags are specified") - } - - style := event.scalar_style() - if style == yaml_ANY_SCALAR_STYLE { - style = yaml_PLAIN_SCALAR_STYLE - } - if emitter.canonical { - style = yaml_DOUBLE_QUOTED_SCALAR_STYLE - } - if emitter.simple_key_context && emitter.scalar_data.multiline { - style = yaml_DOUBLE_QUOTED_SCALAR_STYLE - } - - if style == yaml_PLAIN_SCALAR_STYLE { - if emitter.flow_level > 0 && !emitter.scalar_data.flow_plain_allowed || - emitter.flow_level == 0 && !emitter.scalar_data.block_plain_allowed { - style = yaml_SINGLE_QUOTED_SCALAR_STYLE - } - if len(emitter.scalar_data.value) == 0 && (emitter.flow_level > 0 || emitter.simple_key_context) { - style = yaml_SINGLE_QUOTED_SCALAR_STYLE - } - if no_tag && !event.implicit { - style = yaml_SINGLE_QUOTED_SCALAR_STYLE - } - } - if style == yaml_SINGLE_QUOTED_SCALAR_STYLE { - if !emitter.scalar_data.single_quoted_allowed { - style = yaml_DOUBLE_QUOTED_SCALAR_STYLE - } - } - if style == yaml_LITERAL_SCALAR_STYLE || style == yaml_FOLDED_SCALAR_STYLE { - if !emitter.scalar_data.block_allowed || emitter.flow_level > 0 || emitter.simple_key_context { - style = yaml_DOUBLE_QUOTED_SCALAR_STYLE - } - } - - if no_tag && !event.quoted_implicit && style != yaml_PLAIN_SCALAR_STYLE { - emitter.tag_data.handle = []byte{'!'} - } - emitter.scalar_data.style = style - return true -} - -// Write an anchor. -func yaml_emitter_process_anchor(emitter *yaml_emitter_t) bool { - if emitter.anchor_data.anchor == nil { - return true - } - c := []byte{'&'} - if emitter.anchor_data.alias { - c[0] = '*' - } - if !yaml_emitter_write_indicator(emitter, c, true, false, false) { - return false - } - return yaml_emitter_write_anchor(emitter, emitter.anchor_data.anchor) -} - -// Write a tag. -func yaml_emitter_process_tag(emitter *yaml_emitter_t) bool { - if len(emitter.tag_data.handle) == 0 && len(emitter.tag_data.suffix) == 0 { - return true - } - if len(emitter.tag_data.handle) > 0 { - if !yaml_emitter_write_tag_handle(emitter, emitter.tag_data.handle) { - return false - } - if len(emitter.tag_data.suffix) > 0 { - if !yaml_emitter_write_tag_content(emitter, emitter.tag_data.suffix, false) { - return false - } - } - } else { - // [Go] Allocate these slices elsewhere. - if !yaml_emitter_write_indicator(emitter, []byte("!<"), true, false, false) { - return false - } - if !yaml_emitter_write_tag_content(emitter, emitter.tag_data.suffix, false) { - return false - } - if !yaml_emitter_write_indicator(emitter, []byte{'>'}, false, false, false) { - return false - } - } - return true -} - -// Write a scalar. -func yaml_emitter_process_scalar(emitter *yaml_emitter_t) bool { - switch emitter.scalar_data.style { - case yaml_PLAIN_SCALAR_STYLE: - return yaml_emitter_write_plain_scalar(emitter, emitter.scalar_data.value, !emitter.simple_key_context) - - case yaml_SINGLE_QUOTED_SCALAR_STYLE: - return yaml_emitter_write_single_quoted_scalar(emitter, emitter.scalar_data.value, !emitter.simple_key_context) - - case yaml_DOUBLE_QUOTED_SCALAR_STYLE: - return yaml_emitter_write_double_quoted_scalar(emitter, emitter.scalar_data.value, !emitter.simple_key_context) - - case yaml_LITERAL_SCALAR_STYLE: - return yaml_emitter_write_literal_scalar(emitter, emitter.scalar_data.value) - - case yaml_FOLDED_SCALAR_STYLE: - return yaml_emitter_write_folded_scalar(emitter, emitter.scalar_data.value) - } - panic("unknown scalar style") -} - -// Write a head comment. -func yaml_emitter_process_head_comment(emitter *yaml_emitter_t) bool { - if len(emitter.tail_comment) > 0 { - if !yaml_emitter_write_indent(emitter) { - return false - } - if !yaml_emitter_write_comment(emitter, emitter.tail_comment) { - return false - } - emitter.tail_comment = emitter.tail_comment[:0] - emitter.foot_indent = emitter.indent - if emitter.foot_indent < 0 { - emitter.foot_indent = 0 - } - } - - if len(emitter.head_comment) == 0 { - return true - } - if !yaml_emitter_write_indent(emitter) { - return false - } - if !yaml_emitter_write_comment(emitter, emitter.head_comment) { - return false - } - emitter.head_comment = emitter.head_comment[:0] - return true -} - -// Write an line comment. -func yaml_emitter_process_line_comment(emitter *yaml_emitter_t) bool { - if len(emitter.line_comment) == 0 { - return true - } - if !emitter.whitespace { - if !put(emitter, ' ') { - return false - } - } - if !yaml_emitter_write_comment(emitter, emitter.line_comment) { - return false - } - emitter.line_comment = emitter.line_comment[:0] - return true -} - -// Write a foot comment. -func yaml_emitter_process_foot_comment(emitter *yaml_emitter_t) bool { - if len(emitter.foot_comment) == 0 { - return true - } - if !yaml_emitter_write_indent(emitter) { - return false - } - if !yaml_emitter_write_comment(emitter, emitter.foot_comment) { - return false - } - emitter.foot_comment = emitter.foot_comment[:0] - emitter.foot_indent = emitter.indent - if emitter.foot_indent < 0 { - emitter.foot_indent = 0 - } - return true -} - -// Check if a %YAML directive is valid. -func yaml_emitter_analyze_version_directive(emitter *yaml_emitter_t, version_directive *yaml_version_directive_t) bool { - if version_directive.major != 1 || version_directive.minor != 1 { - return yaml_emitter_set_emitter_error(emitter, "incompatible %YAML directive") - } - return true -} - -// Check if a %TAG directive is valid. -func yaml_emitter_analyze_tag_directive(emitter *yaml_emitter_t, tag_directive *yaml_tag_directive_t) bool { - handle := tag_directive.handle - prefix := tag_directive.prefix - if len(handle) == 0 { - return yaml_emitter_set_emitter_error(emitter, "tag handle must not be empty") - } - if handle[0] != '!' { - return yaml_emitter_set_emitter_error(emitter, "tag handle must start with '!'") - } - if handle[len(handle)-1] != '!' { - return yaml_emitter_set_emitter_error(emitter, "tag handle must end with '!'") - } - for i := 1; i < len(handle)-1; i += width(handle[i]) { - if !is_alpha(handle, i) { - return yaml_emitter_set_emitter_error(emitter, "tag handle must contain alphanumerical characters only") - } - } - if len(prefix) == 0 { - return yaml_emitter_set_emitter_error(emitter, "tag prefix must not be empty") - } - return true -} - -// Check if an anchor is valid. -func yaml_emitter_analyze_anchor(emitter *yaml_emitter_t, anchor []byte, alias bool) bool { - if len(anchor) == 0 { - problem := "anchor value must not be empty" - if alias { - problem = "alias value must not be empty" - } - return yaml_emitter_set_emitter_error(emitter, problem) - } - for i := 0; i < len(anchor); i += width(anchor[i]) { - if !is_alpha(anchor, i) { - problem := "anchor value must contain alphanumerical characters only" - if alias { - problem = "alias value must contain alphanumerical characters only" - } - return yaml_emitter_set_emitter_error(emitter, problem) - } - } - emitter.anchor_data.anchor = anchor - emitter.anchor_data.alias = alias - return true -} - -// Check if a tag is valid. -func yaml_emitter_analyze_tag(emitter *yaml_emitter_t, tag []byte) bool { - if len(tag) == 0 { - return yaml_emitter_set_emitter_error(emitter, "tag value must not be empty") - } - for i := 0; i < len(emitter.tag_directives); i++ { - tag_directive := &emitter.tag_directives[i] - if bytes.HasPrefix(tag, tag_directive.prefix) { - emitter.tag_data.handle = tag_directive.handle - emitter.tag_data.suffix = tag[len(tag_directive.prefix):] - return true - } - } - emitter.tag_data.suffix = tag - return true -} - -// Check if a scalar is valid. -func yaml_emitter_analyze_scalar(emitter *yaml_emitter_t, value []byte) bool { - var ( - block_indicators = false - flow_indicators = false - line_breaks = false - special_characters = false - tab_characters = false - - leading_space = false - leading_break = false - trailing_space = false - trailing_break = false - break_space = false - space_break = false - - preceded_by_whitespace = false - followed_by_whitespace = false - previous_space = false - previous_break = false - ) - - emitter.scalar_data.value = value - - if len(value) == 0 { - emitter.scalar_data.multiline = false - emitter.scalar_data.flow_plain_allowed = false - emitter.scalar_data.block_plain_allowed = true - emitter.scalar_data.single_quoted_allowed = true - emitter.scalar_data.block_allowed = false - return true - } - - if len(value) >= 3 && ((value[0] == '-' && value[1] == '-' && value[2] == '-') || (value[0] == '.' && value[1] == '.' && value[2] == '.')) { - block_indicators = true - flow_indicators = true - } - - preceded_by_whitespace = true - for i, w := 0, 0; i < len(value); i += w { - w = width(value[i]) - followed_by_whitespace = i+w >= len(value) || is_blank(value, i+w) - - if i == 0 { - switch value[i] { - case '#', ',', '[', ']', '{', '}', '&', '*', '!', '|', '>', '\'', '"', '%', '@', '`': - flow_indicators = true - block_indicators = true - case '?', ':': - flow_indicators = true - if followed_by_whitespace { - block_indicators = true - } - case '-': - if followed_by_whitespace { - flow_indicators = true - block_indicators = true - } - } - } else { - switch value[i] { - case ',', '?', '[', ']', '{', '}': - flow_indicators = true - case ':': - flow_indicators = true - if followed_by_whitespace { - block_indicators = true - } - case '#': - if preceded_by_whitespace { - flow_indicators = true - block_indicators = true - } - } - } - - if value[i] == '\t' { - tab_characters = true - } else if !is_printable(value, i) || !is_ascii(value, i) && !emitter.unicode { - special_characters = true - } - if is_space(value, i) { - if i == 0 { - leading_space = true - } - if i+width(value[i]) == len(value) { - trailing_space = true - } - if previous_break { - break_space = true - } - previous_space = true - previous_break = false - } else if is_break(value, i) { - line_breaks = true - if i == 0 { - leading_break = true - } - if i+width(value[i]) == len(value) { - trailing_break = true - } - if previous_space { - space_break = true - } - previous_space = false - previous_break = true - } else { - previous_space = false - previous_break = false - } - - // [Go]: Why 'z'? Couldn't be the end of the string as that's the loop condition. - preceded_by_whitespace = is_blankz(value, i) - } - - emitter.scalar_data.multiline = line_breaks - emitter.scalar_data.flow_plain_allowed = true - emitter.scalar_data.block_plain_allowed = true - emitter.scalar_data.single_quoted_allowed = true - emitter.scalar_data.block_allowed = true - - if leading_space || leading_break || trailing_space || trailing_break { - emitter.scalar_data.flow_plain_allowed = false - emitter.scalar_data.block_plain_allowed = false - } - if trailing_space { - emitter.scalar_data.block_allowed = false - } - if break_space { - emitter.scalar_data.flow_plain_allowed = false - emitter.scalar_data.block_plain_allowed = false - emitter.scalar_data.single_quoted_allowed = false - } - if space_break || tab_characters || special_characters { - emitter.scalar_data.flow_plain_allowed = false - emitter.scalar_data.block_plain_allowed = false - emitter.scalar_data.single_quoted_allowed = false - } - if space_break || special_characters { - emitter.scalar_data.block_allowed = false - } - if line_breaks { - emitter.scalar_data.flow_plain_allowed = false - emitter.scalar_data.block_plain_allowed = false - } - if flow_indicators { - emitter.scalar_data.flow_plain_allowed = false - } - if block_indicators { - emitter.scalar_data.block_plain_allowed = false - } - return true -} - -// Check if the event data is valid. -func yaml_emitter_analyze_event(emitter *yaml_emitter_t, event *yaml_event_t) bool { - - emitter.anchor_data.anchor = nil - emitter.tag_data.handle = nil - emitter.tag_data.suffix = nil - emitter.scalar_data.value = nil - - if len(event.head_comment) > 0 { - emitter.head_comment = event.head_comment - } - if len(event.line_comment) > 0 { - emitter.line_comment = event.line_comment - } - if len(event.foot_comment) > 0 { - emitter.foot_comment = event.foot_comment - } - if len(event.tail_comment) > 0 { - emitter.tail_comment = event.tail_comment - } - - switch event.typ { - case yaml_ALIAS_EVENT: - if !yaml_emitter_analyze_anchor(emitter, event.anchor, true) { - return false - } - - case yaml_SCALAR_EVENT: - if len(event.anchor) > 0 { - if !yaml_emitter_analyze_anchor(emitter, event.anchor, false) { - return false - } - } - if len(event.tag) > 0 && (emitter.canonical || (!event.implicit && !event.quoted_implicit)) { - if !yaml_emitter_analyze_tag(emitter, event.tag) { - return false - } - } - if !yaml_emitter_analyze_scalar(emitter, event.value) { - return false - } - - case yaml_SEQUENCE_START_EVENT: - if len(event.anchor) > 0 { - if !yaml_emitter_analyze_anchor(emitter, event.anchor, false) { - return false - } - } - if len(event.tag) > 0 && (emitter.canonical || !event.implicit) { - if !yaml_emitter_analyze_tag(emitter, event.tag) { - return false - } - } - - case yaml_MAPPING_START_EVENT: - if len(event.anchor) > 0 { - if !yaml_emitter_analyze_anchor(emitter, event.anchor, false) { - return false - } - } - if len(event.tag) > 0 && (emitter.canonical || !event.implicit) { - if !yaml_emitter_analyze_tag(emitter, event.tag) { - return false - } - } - } - return true -} - -// Write the BOM character. -func yaml_emitter_write_bom(emitter *yaml_emitter_t) bool { - if !flush(emitter) { - return false - } - pos := emitter.buffer_pos - emitter.buffer[pos+0] = '\xEF' - emitter.buffer[pos+1] = '\xBB' - emitter.buffer[pos+2] = '\xBF' - emitter.buffer_pos += 3 - return true -} - -func yaml_emitter_write_indent(emitter *yaml_emitter_t) bool { - indent := emitter.indent - if indent < 0 { - indent = 0 - } - if !emitter.indention || emitter.column > indent || (emitter.column == indent && !emitter.whitespace) { - if !put_break(emitter) { - return false - } - } - if emitter.foot_indent == indent { - if !put_break(emitter) { - return false - } - } - for emitter.column < indent { - if !put(emitter, ' ') { - return false - } - } - emitter.whitespace = true - //emitter.indention = true - emitter.space_above = false - emitter.foot_indent = -1 - return true -} - -func yaml_emitter_write_indicator(emitter *yaml_emitter_t, indicator []byte, need_whitespace, is_whitespace, is_indention bool) bool { - if need_whitespace && !emitter.whitespace { - if !put(emitter, ' ') { - return false - } - } - if !write_all(emitter, indicator) { - return false - } - emitter.whitespace = is_whitespace - emitter.indention = (emitter.indention && is_indention) - emitter.open_ended = false - return true -} - -func yaml_emitter_write_anchor(emitter *yaml_emitter_t, value []byte) bool { - if !write_all(emitter, value) { - return false - } - emitter.whitespace = false - emitter.indention = false - return true -} - -func yaml_emitter_write_tag_handle(emitter *yaml_emitter_t, value []byte) bool { - if !emitter.whitespace { - if !put(emitter, ' ') { - return false - } - } - if !write_all(emitter, value) { - return false - } - emitter.whitespace = false - emitter.indention = false - return true -} - -func yaml_emitter_write_tag_content(emitter *yaml_emitter_t, value []byte, need_whitespace bool) bool { - if need_whitespace && !emitter.whitespace { - if !put(emitter, ' ') { - return false - } - } - for i := 0; i < len(value); { - var must_write bool - switch value[i] { - case ';', '/', '?', ':', '@', '&', '=', '+', '$', ',', '_', '.', '~', '*', '\'', '(', ')', '[', ']': - must_write = true - default: - must_write = is_alpha(value, i) - } - if must_write { - if !write(emitter, value, &i) { - return false - } - } else { - w := width(value[i]) - for k := 0; k < w; k++ { - octet := value[i] - i++ - if !put(emitter, '%') { - return false - } - - c := octet >> 4 - if c < 10 { - c += '0' - } else { - c += 'A' - 10 - } - if !put(emitter, c) { - return false - } - - c = octet & 0x0f - if c < 10 { - c += '0' - } else { - c += 'A' - 10 - } - if !put(emitter, c) { - return false - } - } - } - } - emitter.whitespace = false - emitter.indention = false - return true -} - -func yaml_emitter_write_plain_scalar(emitter *yaml_emitter_t, value []byte, allow_breaks bool) bool { - if len(value) > 0 && !emitter.whitespace { - if !put(emitter, ' ') { - return false - } - } - - spaces := false - breaks := false - for i := 0; i < len(value); { - if is_space(value, i) { - if allow_breaks && !spaces && emitter.column > emitter.best_width && !is_space(value, i+1) { - if !yaml_emitter_write_indent(emitter) { - return false - } - i += width(value[i]) - } else { - if !write(emitter, value, &i) { - return false - } - } - spaces = true - } else if is_break(value, i) { - if !breaks && value[i] == '\n' { - if !put_break(emitter) { - return false - } - } - if !write_break(emitter, value, &i) { - return false - } - //emitter.indention = true - breaks = true - } else { - if breaks { - if !yaml_emitter_write_indent(emitter) { - return false - } - } - if !write(emitter, value, &i) { - return false - } - emitter.indention = false - spaces = false - breaks = false - } - } - - if len(value) > 0 { - emitter.whitespace = false - } - emitter.indention = false - if emitter.root_context { - emitter.open_ended = true - } - - return true -} - -func yaml_emitter_write_single_quoted_scalar(emitter *yaml_emitter_t, value []byte, allow_breaks bool) bool { - - if !yaml_emitter_write_indicator(emitter, []byte{'\''}, true, false, false) { - return false - } - - spaces := false - breaks := false - for i := 0; i < len(value); { - if is_space(value, i) { - if allow_breaks && !spaces && emitter.column > emitter.best_width && i > 0 && i < len(value)-1 && !is_space(value, i+1) { - if !yaml_emitter_write_indent(emitter) { - return false - } - i += width(value[i]) - } else { - if !write(emitter, value, &i) { - return false - } - } - spaces = true - } else if is_break(value, i) { - if !breaks && value[i] == '\n' { - if !put_break(emitter) { - return false - } - } - if !write_break(emitter, value, &i) { - return false - } - //emitter.indention = true - breaks = true - } else { - if breaks { - if !yaml_emitter_write_indent(emitter) { - return false - } - } - if value[i] == '\'' { - if !put(emitter, '\'') { - return false - } - } - if !write(emitter, value, &i) { - return false - } - emitter.indention = false - spaces = false - breaks = false - } - } - if !yaml_emitter_write_indicator(emitter, []byte{'\''}, false, false, false) { - return false - } - emitter.whitespace = false - emitter.indention = false - return true -} - -func yaml_emitter_write_double_quoted_scalar(emitter *yaml_emitter_t, value []byte, allow_breaks bool) bool { - spaces := false - if !yaml_emitter_write_indicator(emitter, []byte{'"'}, true, false, false) { - return false - } - - for i := 0; i < len(value); { - if !is_printable(value, i) || (!emitter.unicode && !is_ascii(value, i)) || - is_bom(value, i) || is_break(value, i) || - value[i] == '"' || value[i] == '\\' { - - octet := value[i] - - var w int - var v rune - switch { - case octet&0x80 == 0x00: - w, v = 1, rune(octet&0x7F) - case octet&0xE0 == 0xC0: - w, v = 2, rune(octet&0x1F) - case octet&0xF0 == 0xE0: - w, v = 3, rune(octet&0x0F) - case octet&0xF8 == 0xF0: - w, v = 4, rune(octet&0x07) - } - for k := 1; k < w; k++ { - octet = value[i+k] - v = (v << 6) + (rune(octet) & 0x3F) - } - i += w - - if !put(emitter, '\\') { - return false - } - - var ok bool - switch v { - case 0x00: - ok = put(emitter, '0') - case 0x07: - ok = put(emitter, 'a') - case 0x08: - ok = put(emitter, 'b') - case 0x09: - ok = put(emitter, 't') - case 0x0A: - ok = put(emitter, 'n') - case 0x0b: - ok = put(emitter, 'v') - case 0x0c: - ok = put(emitter, 'f') - case 0x0d: - ok = put(emitter, 'r') - case 0x1b: - ok = put(emitter, 'e') - case 0x22: - ok = put(emitter, '"') - case 0x5c: - ok = put(emitter, '\\') - case 0x85: - ok = put(emitter, 'N') - case 0xA0: - ok = put(emitter, '_') - case 0x2028: - ok = put(emitter, 'L') - case 0x2029: - ok = put(emitter, 'P') - default: - if v <= 0xFF { - ok = put(emitter, 'x') - w = 2 - } else if v <= 0xFFFF { - ok = put(emitter, 'u') - w = 4 - } else { - ok = put(emitter, 'U') - w = 8 - } - for k := (w - 1) * 4; ok && k >= 0; k -= 4 { - digit := byte((v >> uint(k)) & 0x0F) - if digit < 10 { - ok = put(emitter, digit+'0') - } else { - ok = put(emitter, digit+'A'-10) - } - } - } - if !ok { - return false - } - spaces = false - } else if is_space(value, i) { - if allow_breaks && !spaces && emitter.column > emitter.best_width && i > 0 && i < len(value)-1 { - if !yaml_emitter_write_indent(emitter) { - return false - } - if is_space(value, i+1) { - if !put(emitter, '\\') { - return false - } - } - i += width(value[i]) - } else if !write(emitter, value, &i) { - return false - } - spaces = true - } else { - if !write(emitter, value, &i) { - return false - } - spaces = false - } - } - if !yaml_emitter_write_indicator(emitter, []byte{'"'}, false, false, false) { - return false - } - emitter.whitespace = false - emitter.indention = false - return true -} - -func yaml_emitter_write_block_scalar_hints(emitter *yaml_emitter_t, value []byte) bool { - if is_space(value, 0) || is_break(value, 0) { - indent_hint := []byte{'0' + byte(emitter.best_indent)} - if !yaml_emitter_write_indicator(emitter, indent_hint, false, false, false) { - return false - } - } - - emitter.open_ended = false - - var chomp_hint [1]byte - if len(value) == 0 { - chomp_hint[0] = '-' - } else { - i := len(value) - 1 - for value[i]&0xC0 == 0x80 { - i-- - } - if !is_break(value, i) { - chomp_hint[0] = '-' - } else if i == 0 { - chomp_hint[0] = '+' - emitter.open_ended = true - } else { - i-- - for value[i]&0xC0 == 0x80 { - i-- - } - if is_break(value, i) { - chomp_hint[0] = '+' - emitter.open_ended = true - } - } - } - if chomp_hint[0] != 0 { - if !yaml_emitter_write_indicator(emitter, chomp_hint[:], false, false, false) { - return false - } - } - return true -} - -func yaml_emitter_write_literal_scalar(emitter *yaml_emitter_t, value []byte) bool { - if !yaml_emitter_write_indicator(emitter, []byte{'|'}, true, false, false) { - return false - } - if !yaml_emitter_write_block_scalar_hints(emitter, value) { - return false - } - if !yaml_emitter_process_line_comment(emitter) { - return false - } - //emitter.indention = true - emitter.whitespace = true - breaks := true - for i := 0; i < len(value); { - if is_break(value, i) { - if !write_break(emitter, value, &i) { - return false - } - //emitter.indention = true - breaks = true - } else { - if breaks { - if !yaml_emitter_write_indent(emitter) { - return false - } - } - if !write(emitter, value, &i) { - return false - } - emitter.indention = false - breaks = false - } - } - - return true -} - -func yaml_emitter_write_folded_scalar(emitter *yaml_emitter_t, value []byte) bool { - if !yaml_emitter_write_indicator(emitter, []byte{'>'}, true, false, false) { - return false - } - if !yaml_emitter_write_block_scalar_hints(emitter, value) { - return false - } - if !yaml_emitter_process_line_comment(emitter) { - return false - } - - //emitter.indention = true - emitter.whitespace = true - - breaks := true - leading_spaces := true - for i := 0; i < len(value); { - if is_break(value, i) { - if !breaks && !leading_spaces && value[i] == '\n' { - k := 0 - for is_break(value, k) { - k += width(value[k]) - } - if !is_blankz(value, k) { - if !put_break(emitter) { - return false - } - } - } - if !write_break(emitter, value, &i) { - return false - } - //emitter.indention = true - breaks = true - } else { - if breaks { - if !yaml_emitter_write_indent(emitter) { - return false - } - leading_spaces = is_blank(value, i) - } - if !breaks && is_space(value, i) && !is_space(value, i+1) && emitter.column > emitter.best_width { - if !yaml_emitter_write_indent(emitter) { - return false - } - i += width(value[i]) - } else { - if !write(emitter, value, &i) { - return false - } - } - emitter.indention = false - breaks = false - } - } - return true -} - -func yaml_emitter_write_comment(emitter *yaml_emitter_t, comment []byte) bool { - breaks := false - pound := false - for i := 0; i < len(comment); { - if is_break(comment, i) { - if !write_break(emitter, comment, &i) { - return false - } - //emitter.indention = true - breaks = true - pound = false - } else { - if breaks && !yaml_emitter_write_indent(emitter) { - return false - } - if !pound { - if comment[i] != '#' && (!put(emitter, '#') || !put(emitter, ' ')) { - return false - } - pound = true - } - if !write(emitter, comment, &i) { - return false - } - emitter.indention = false - breaks = false - } - } - if !breaks && !put_break(emitter) { - return false - } - - emitter.whitespace = true - //emitter.indention = true - return true -} diff --git a/trunk/3rdparty/srs-bench/vendor/gopkg.in/yaml.v3/encode.go b/trunk/3rdparty/srs-bench/vendor/gopkg.in/yaml.v3/encode.go deleted file mode 100644 index de9e72a3e..000000000 --- a/trunk/3rdparty/srs-bench/vendor/gopkg.in/yaml.v3/encode.go +++ /dev/null @@ -1,577 +0,0 @@ -// -// Copyright (c) 2011-2019 Canonical Ltd -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package yaml - -import ( - "encoding" - "fmt" - "io" - "reflect" - "regexp" - "sort" - "strconv" - "strings" - "time" - "unicode/utf8" -) - -type encoder struct { - emitter yaml_emitter_t - event yaml_event_t - out []byte - flow bool - indent int - doneInit bool -} - -func newEncoder() *encoder { - e := &encoder{} - yaml_emitter_initialize(&e.emitter) - yaml_emitter_set_output_string(&e.emitter, &e.out) - yaml_emitter_set_unicode(&e.emitter, true) - return e -} - -func newEncoderWithWriter(w io.Writer) *encoder { - e := &encoder{} - yaml_emitter_initialize(&e.emitter) - yaml_emitter_set_output_writer(&e.emitter, w) - yaml_emitter_set_unicode(&e.emitter, true) - return e -} - -func (e *encoder) init() { - if e.doneInit { - return - } - if e.indent == 0 { - e.indent = 4 - } - e.emitter.best_indent = e.indent - yaml_stream_start_event_initialize(&e.event, yaml_UTF8_ENCODING) - e.emit() - e.doneInit = true -} - -func (e *encoder) finish() { - e.emitter.open_ended = false - yaml_stream_end_event_initialize(&e.event) - e.emit() -} - -func (e *encoder) destroy() { - yaml_emitter_delete(&e.emitter) -} - -func (e *encoder) emit() { - // This will internally delete the e.event value. - e.must(yaml_emitter_emit(&e.emitter, &e.event)) -} - -func (e *encoder) must(ok bool) { - if !ok { - msg := e.emitter.problem - if msg == "" { - msg = "unknown problem generating YAML content" - } - failf("%s", msg) - } -} - -func (e *encoder) marshalDoc(tag string, in reflect.Value) { - e.init() - var node *Node - if in.IsValid() { - node, _ = in.Interface().(*Node) - } - if node != nil && node.Kind == DocumentNode { - e.nodev(in) - } else { - yaml_document_start_event_initialize(&e.event, nil, nil, true) - e.emit() - e.marshal(tag, in) - yaml_document_end_event_initialize(&e.event, true) - e.emit() - } -} - -func (e *encoder) marshal(tag string, in reflect.Value) { - tag = shortTag(tag) - if !in.IsValid() || in.Kind() == reflect.Ptr && in.IsNil() { - e.nilv() - return - } - iface := in.Interface() - switch value := iface.(type) { - case *Node: - e.nodev(in) - return - case Node: - if !in.CanAddr() { - var n = reflect.New(in.Type()).Elem() - n.Set(in) - in = n - } - e.nodev(in.Addr()) - return - case time.Time: - e.timev(tag, in) - return - case *time.Time: - e.timev(tag, in.Elem()) - return - case time.Duration: - e.stringv(tag, reflect.ValueOf(value.String())) - return - case Marshaler: - v, err := value.MarshalYAML() - if err != nil { - fail(err) - } - if v == nil { - e.nilv() - return - } - e.marshal(tag, reflect.ValueOf(v)) - return - case encoding.TextMarshaler: - text, err := value.MarshalText() - if err != nil { - fail(err) - } - in = reflect.ValueOf(string(text)) - case nil: - e.nilv() - return - } - switch in.Kind() { - case reflect.Interface: - e.marshal(tag, in.Elem()) - case reflect.Map: - e.mapv(tag, in) - case reflect.Ptr: - e.marshal(tag, in.Elem()) - case reflect.Struct: - e.structv(tag, in) - case reflect.Slice, reflect.Array: - e.slicev(tag, in) - case reflect.String: - e.stringv(tag, in) - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - e.intv(tag, in) - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - e.uintv(tag, in) - case reflect.Float32, reflect.Float64: - e.floatv(tag, in) - case reflect.Bool: - e.boolv(tag, in) - default: - panic("cannot marshal type: " + in.Type().String()) - } -} - -func (e *encoder) mapv(tag string, in reflect.Value) { - e.mappingv(tag, func() { - keys := keyList(in.MapKeys()) - sort.Sort(keys) - for _, k := range keys { - e.marshal("", k) - e.marshal("", in.MapIndex(k)) - } - }) -} - -func (e *encoder) fieldByIndex(v reflect.Value, index []int) (field reflect.Value) { - for _, num := range index { - for { - if v.Kind() == reflect.Ptr { - if v.IsNil() { - return reflect.Value{} - } - v = v.Elem() - continue - } - break - } - v = v.Field(num) - } - return v -} - -func (e *encoder) structv(tag string, in reflect.Value) { - sinfo, err := getStructInfo(in.Type()) - if err != nil { - panic(err) - } - e.mappingv(tag, func() { - for _, info := range sinfo.FieldsList { - var value reflect.Value - if info.Inline == nil { - value = in.Field(info.Num) - } else { - value = e.fieldByIndex(in, info.Inline) - if !value.IsValid() { - continue - } - } - if info.OmitEmpty && isZero(value) { - continue - } - e.marshal("", reflect.ValueOf(info.Key)) - e.flow = info.Flow - e.marshal("", value) - } - if sinfo.InlineMap >= 0 { - m := in.Field(sinfo.InlineMap) - if m.Len() > 0 { - e.flow = false - keys := keyList(m.MapKeys()) - sort.Sort(keys) - for _, k := range keys { - if _, found := sinfo.FieldsMap[k.String()]; found { - panic(fmt.Sprintf("cannot have key %q in inlined map: conflicts with struct field", k.String())) - } - e.marshal("", k) - e.flow = false - e.marshal("", m.MapIndex(k)) - } - } - } - }) -} - -func (e *encoder) mappingv(tag string, f func()) { - implicit := tag == "" - style := yaml_BLOCK_MAPPING_STYLE - if e.flow { - e.flow = false - style = yaml_FLOW_MAPPING_STYLE - } - yaml_mapping_start_event_initialize(&e.event, nil, []byte(tag), implicit, style) - e.emit() - f() - yaml_mapping_end_event_initialize(&e.event) - e.emit() -} - -func (e *encoder) slicev(tag string, in reflect.Value) { - implicit := tag == "" - style := yaml_BLOCK_SEQUENCE_STYLE - if e.flow { - e.flow = false - style = yaml_FLOW_SEQUENCE_STYLE - } - e.must(yaml_sequence_start_event_initialize(&e.event, nil, []byte(tag), implicit, style)) - e.emit() - n := in.Len() - for i := 0; i < n; i++ { - e.marshal("", in.Index(i)) - } - e.must(yaml_sequence_end_event_initialize(&e.event)) - e.emit() -} - -// isBase60 returns whether s is in base 60 notation as defined in YAML 1.1. -// -// The base 60 float notation in YAML 1.1 is a terrible idea and is unsupported -// in YAML 1.2 and by this package, but these should be marshalled quoted for -// the time being for compatibility with other parsers. -func isBase60Float(s string) (result bool) { - // Fast path. - if s == "" { - return false - } - c := s[0] - if !(c == '+' || c == '-' || c >= '0' && c <= '9') || strings.IndexByte(s, ':') < 0 { - return false - } - // Do the full match. - return base60float.MatchString(s) -} - -// From http://yaml.org/type/float.html, except the regular expression there -// is bogus. In practice parsers do not enforce the "\.[0-9_]*" suffix. -var base60float = regexp.MustCompile(`^[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+(?:\.[0-9_]*)?$`) - -// isOldBool returns whether s is bool notation as defined in YAML 1.1. -// -// We continue to force strings that YAML 1.1 would interpret as booleans to be -// rendered as quotes strings so that the marshalled output valid for YAML 1.1 -// parsing. -func isOldBool(s string) (result bool) { - switch s { - case "y", "Y", "yes", "Yes", "YES", "on", "On", "ON", - "n", "N", "no", "No", "NO", "off", "Off", "OFF": - return true - default: - return false - } -} - -func (e *encoder) stringv(tag string, in reflect.Value) { - var style yaml_scalar_style_t - s := in.String() - canUsePlain := true - switch { - case !utf8.ValidString(s): - if tag == binaryTag { - failf("explicitly tagged !!binary data must be base64-encoded") - } - if tag != "" { - failf("cannot marshal invalid UTF-8 data as %s", shortTag(tag)) - } - // It can't be encoded directly as YAML so use a binary tag - // and encode it as base64. - tag = binaryTag - s = encodeBase64(s) - case tag == "": - // Check to see if it would resolve to a specific - // tag when encoded unquoted. If it doesn't, - // there's no need to quote it. - rtag, _ := resolve("", s) - canUsePlain = rtag == strTag && !(isBase60Float(s) || isOldBool(s)) - } - // Note: it's possible for user code to emit invalid YAML - // if they explicitly specify a tag and a string containing - // text that's incompatible with that tag. - switch { - case strings.Contains(s, "\n"): - if e.flow { - style = yaml_DOUBLE_QUOTED_SCALAR_STYLE - } else { - style = yaml_LITERAL_SCALAR_STYLE - } - case canUsePlain: - style = yaml_PLAIN_SCALAR_STYLE - default: - style = yaml_DOUBLE_QUOTED_SCALAR_STYLE - } - e.emitScalar(s, "", tag, style, nil, nil, nil, nil) -} - -func (e *encoder) boolv(tag string, in reflect.Value) { - var s string - if in.Bool() { - s = "true" - } else { - s = "false" - } - e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil) -} - -func (e *encoder) intv(tag string, in reflect.Value) { - s := strconv.FormatInt(in.Int(), 10) - e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil) -} - -func (e *encoder) uintv(tag string, in reflect.Value) { - s := strconv.FormatUint(in.Uint(), 10) - e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil) -} - -func (e *encoder) timev(tag string, in reflect.Value) { - t := in.Interface().(time.Time) - s := t.Format(time.RFC3339Nano) - e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil) -} - -func (e *encoder) floatv(tag string, in reflect.Value) { - // Issue #352: When formatting, use the precision of the underlying value - precision := 64 - if in.Kind() == reflect.Float32 { - precision = 32 - } - - s := strconv.FormatFloat(in.Float(), 'g', -1, precision) - switch s { - case "+Inf": - s = ".inf" - case "-Inf": - s = "-.inf" - case "NaN": - s = ".nan" - } - e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil) -} - -func (e *encoder) nilv() { - e.emitScalar("null", "", "", yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil) -} - -func (e *encoder) emitScalar(value, anchor, tag string, style yaml_scalar_style_t, head, line, foot, tail []byte) { - // TODO Kill this function. Replace all initialize calls by their underlining Go literals. - implicit := tag == "" - if !implicit { - tag = longTag(tag) - } - e.must(yaml_scalar_event_initialize(&e.event, []byte(anchor), []byte(tag), []byte(value), implicit, implicit, style)) - e.event.head_comment = head - e.event.line_comment = line - e.event.foot_comment = foot - e.event.tail_comment = tail - e.emit() -} - -func (e *encoder) nodev(in reflect.Value) { - e.node(in.Interface().(*Node), "") -} - -func (e *encoder) node(node *Node, tail string) { - // Zero nodes behave as nil. - if node.Kind == 0 && node.IsZero() { - e.nilv() - return - } - - // If the tag was not explicitly requested, and dropping it won't change the - // implicit tag of the value, don't include it in the presentation. - var tag = node.Tag - var stag = shortTag(tag) - var forceQuoting bool - if tag != "" && node.Style&TaggedStyle == 0 { - if node.Kind == ScalarNode { - if stag == strTag && node.Style&(SingleQuotedStyle|DoubleQuotedStyle|LiteralStyle|FoldedStyle) != 0 { - tag = "" - } else { - rtag, _ := resolve("", node.Value) - if rtag == stag { - tag = "" - } else if stag == strTag { - tag = "" - forceQuoting = true - } - } - } else { - var rtag string - switch node.Kind { - case MappingNode: - rtag = mapTag - case SequenceNode: - rtag = seqTag - } - if rtag == stag { - tag = "" - } - } - } - - switch node.Kind { - case DocumentNode: - yaml_document_start_event_initialize(&e.event, nil, nil, true) - e.event.head_comment = []byte(node.HeadComment) - e.emit() - for _, node := range node.Content { - e.node(node, "") - } - yaml_document_end_event_initialize(&e.event, true) - e.event.foot_comment = []byte(node.FootComment) - e.emit() - - case SequenceNode: - style := yaml_BLOCK_SEQUENCE_STYLE - if node.Style&FlowStyle != 0 { - style = yaml_FLOW_SEQUENCE_STYLE - } - e.must(yaml_sequence_start_event_initialize(&e.event, []byte(node.Anchor), []byte(longTag(tag)), tag == "", style)) - e.event.head_comment = []byte(node.HeadComment) - e.emit() - for _, node := range node.Content { - e.node(node, "") - } - e.must(yaml_sequence_end_event_initialize(&e.event)) - e.event.line_comment = []byte(node.LineComment) - e.event.foot_comment = []byte(node.FootComment) - e.emit() - - case MappingNode: - style := yaml_BLOCK_MAPPING_STYLE - if node.Style&FlowStyle != 0 { - style = yaml_FLOW_MAPPING_STYLE - } - yaml_mapping_start_event_initialize(&e.event, []byte(node.Anchor), []byte(longTag(tag)), tag == "", style) - e.event.tail_comment = []byte(tail) - e.event.head_comment = []byte(node.HeadComment) - e.emit() - - // The tail logic below moves the foot comment of prior keys to the following key, - // since the value for each key may be a nested structure and the foot needs to be - // processed only the entirety of the value is streamed. The last tail is processed - // with the mapping end event. - var tail string - for i := 0; i+1 < len(node.Content); i += 2 { - k := node.Content[i] - foot := k.FootComment - if foot != "" { - kopy := *k - kopy.FootComment = "" - k = &kopy - } - e.node(k, tail) - tail = foot - - v := node.Content[i+1] - e.node(v, "") - } - - yaml_mapping_end_event_initialize(&e.event) - e.event.tail_comment = []byte(tail) - e.event.line_comment = []byte(node.LineComment) - e.event.foot_comment = []byte(node.FootComment) - e.emit() - - case AliasNode: - yaml_alias_event_initialize(&e.event, []byte(node.Value)) - e.event.head_comment = []byte(node.HeadComment) - e.event.line_comment = []byte(node.LineComment) - e.event.foot_comment = []byte(node.FootComment) - e.emit() - - case ScalarNode: - value := node.Value - if !utf8.ValidString(value) { - if stag == binaryTag { - failf("explicitly tagged !!binary data must be base64-encoded") - } - if stag != "" { - failf("cannot marshal invalid UTF-8 data as %s", stag) - } - // It can't be encoded directly as YAML so use a binary tag - // and encode it as base64. - tag = binaryTag - value = encodeBase64(value) - } - - style := yaml_PLAIN_SCALAR_STYLE - switch { - case node.Style&DoubleQuotedStyle != 0: - style = yaml_DOUBLE_QUOTED_SCALAR_STYLE - case node.Style&SingleQuotedStyle != 0: - style = yaml_SINGLE_QUOTED_SCALAR_STYLE - case node.Style&LiteralStyle != 0: - style = yaml_LITERAL_SCALAR_STYLE - case node.Style&FoldedStyle != 0: - style = yaml_FOLDED_SCALAR_STYLE - case strings.Contains(value, "\n"): - style = yaml_LITERAL_SCALAR_STYLE - case forceQuoting: - style = yaml_DOUBLE_QUOTED_SCALAR_STYLE - } - - e.emitScalar(value, node.Anchor, tag, style, []byte(node.HeadComment), []byte(node.LineComment), []byte(node.FootComment), []byte(tail)) - default: - failf("cannot encode node with unknown kind %d", node.Kind) - } -} diff --git a/trunk/3rdparty/srs-bench/vendor/gopkg.in/yaml.v3/parserc.go b/trunk/3rdparty/srs-bench/vendor/gopkg.in/yaml.v3/parserc.go deleted file mode 100644 index 268558a0d..000000000 --- a/trunk/3rdparty/srs-bench/vendor/gopkg.in/yaml.v3/parserc.go +++ /dev/null @@ -1,1258 +0,0 @@ -// -// Copyright (c) 2011-2019 Canonical Ltd -// Copyright (c) 2006-2010 Kirill Simonov -// -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -// of the Software, and to permit persons to whom the Software is furnished to do -// so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -package yaml - -import ( - "bytes" -) - -// The parser implements the following grammar: -// -// stream ::= STREAM-START implicit_document? explicit_document* STREAM-END -// implicit_document ::= block_node DOCUMENT-END* -// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END* -// block_node_or_indentless_sequence ::= -// ALIAS -// | properties (block_content | indentless_block_sequence)? -// | block_content -// | indentless_block_sequence -// block_node ::= ALIAS -// | properties block_content? -// | block_content -// flow_node ::= ALIAS -// | properties flow_content? -// | flow_content -// properties ::= TAG ANCHOR? | ANCHOR TAG? -// block_content ::= block_collection | flow_collection | SCALAR -// flow_content ::= flow_collection | SCALAR -// block_collection ::= block_sequence | block_mapping -// flow_collection ::= flow_sequence | flow_mapping -// block_sequence ::= BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END -// indentless_sequence ::= (BLOCK-ENTRY block_node?)+ -// block_mapping ::= BLOCK-MAPPING_START -// ((KEY block_node_or_indentless_sequence?)? -// (VALUE block_node_or_indentless_sequence?)?)* -// BLOCK-END -// flow_sequence ::= FLOW-SEQUENCE-START -// (flow_sequence_entry FLOW-ENTRY)* -// flow_sequence_entry? -// FLOW-SEQUENCE-END -// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? -// flow_mapping ::= FLOW-MAPPING-START -// (flow_mapping_entry FLOW-ENTRY)* -// flow_mapping_entry? -// FLOW-MAPPING-END -// flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? - -// Peek the next token in the token queue. -func peek_token(parser *yaml_parser_t) *yaml_token_t { - if parser.token_available || yaml_parser_fetch_more_tokens(parser) { - token := &parser.tokens[parser.tokens_head] - yaml_parser_unfold_comments(parser, token) - return token - } - return nil -} - -// yaml_parser_unfold_comments walks through the comments queue and joins all -// comments behind the position of the provided token into the respective -// top-level comment slices in the parser. -func yaml_parser_unfold_comments(parser *yaml_parser_t, token *yaml_token_t) { - for parser.comments_head < len(parser.comments) && token.start_mark.index >= parser.comments[parser.comments_head].token_mark.index { - comment := &parser.comments[parser.comments_head] - if len(comment.head) > 0 { - if token.typ == yaml_BLOCK_END_TOKEN { - // No heads on ends, so keep comment.head for a follow up token. - break - } - if len(parser.head_comment) > 0 { - parser.head_comment = append(parser.head_comment, '\n') - } - parser.head_comment = append(parser.head_comment, comment.head...) - } - if len(comment.foot) > 0 { - if len(parser.foot_comment) > 0 { - parser.foot_comment = append(parser.foot_comment, '\n') - } - parser.foot_comment = append(parser.foot_comment, comment.foot...) - } - if len(comment.line) > 0 { - if len(parser.line_comment) > 0 { - parser.line_comment = append(parser.line_comment, '\n') - } - parser.line_comment = append(parser.line_comment, comment.line...) - } - *comment = yaml_comment_t{} - parser.comments_head++ - } -} - -// Remove the next token from the queue (must be called after peek_token). -func skip_token(parser *yaml_parser_t) { - parser.token_available = false - parser.tokens_parsed++ - parser.stream_end_produced = parser.tokens[parser.tokens_head].typ == yaml_STREAM_END_TOKEN - parser.tokens_head++ -} - -// Get the next event. -func yaml_parser_parse(parser *yaml_parser_t, event *yaml_event_t) bool { - // Erase the event object. - *event = yaml_event_t{} - - // No events after the end of the stream or error. - if parser.stream_end_produced || parser.error != yaml_NO_ERROR || parser.state == yaml_PARSE_END_STATE { - return true - } - - // Generate the next event. - return yaml_parser_state_machine(parser, event) -} - -// Set parser error. -func yaml_parser_set_parser_error(parser *yaml_parser_t, problem string, problem_mark yaml_mark_t) bool { - parser.error = yaml_PARSER_ERROR - parser.problem = problem - parser.problem_mark = problem_mark - return false -} - -func yaml_parser_set_parser_error_context(parser *yaml_parser_t, context string, context_mark yaml_mark_t, problem string, problem_mark yaml_mark_t) bool { - parser.error = yaml_PARSER_ERROR - parser.context = context - parser.context_mark = context_mark - parser.problem = problem - parser.problem_mark = problem_mark - return false -} - -// State dispatcher. -func yaml_parser_state_machine(parser *yaml_parser_t, event *yaml_event_t) bool { - //trace("yaml_parser_state_machine", "state:", parser.state.String()) - - switch parser.state { - case yaml_PARSE_STREAM_START_STATE: - return yaml_parser_parse_stream_start(parser, event) - - case yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE: - return yaml_parser_parse_document_start(parser, event, true) - - case yaml_PARSE_DOCUMENT_START_STATE: - return yaml_parser_parse_document_start(parser, event, false) - - case yaml_PARSE_DOCUMENT_CONTENT_STATE: - return yaml_parser_parse_document_content(parser, event) - - case yaml_PARSE_DOCUMENT_END_STATE: - return yaml_parser_parse_document_end(parser, event) - - case yaml_PARSE_BLOCK_NODE_STATE: - return yaml_parser_parse_node(parser, event, true, false) - - case yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE: - return yaml_parser_parse_node(parser, event, true, true) - - case yaml_PARSE_FLOW_NODE_STATE: - return yaml_parser_parse_node(parser, event, false, false) - - case yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE: - return yaml_parser_parse_block_sequence_entry(parser, event, true) - - case yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE: - return yaml_parser_parse_block_sequence_entry(parser, event, false) - - case yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE: - return yaml_parser_parse_indentless_sequence_entry(parser, event) - - case yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE: - return yaml_parser_parse_block_mapping_key(parser, event, true) - - case yaml_PARSE_BLOCK_MAPPING_KEY_STATE: - return yaml_parser_parse_block_mapping_key(parser, event, false) - - case yaml_PARSE_BLOCK_MAPPING_VALUE_STATE: - return yaml_parser_parse_block_mapping_value(parser, event) - - case yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE: - return yaml_parser_parse_flow_sequence_entry(parser, event, true) - - case yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE: - return yaml_parser_parse_flow_sequence_entry(parser, event, false) - - case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE: - return yaml_parser_parse_flow_sequence_entry_mapping_key(parser, event) - - case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE: - return yaml_parser_parse_flow_sequence_entry_mapping_value(parser, event) - - case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE: - return yaml_parser_parse_flow_sequence_entry_mapping_end(parser, event) - - case yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE: - return yaml_parser_parse_flow_mapping_key(parser, event, true) - - case yaml_PARSE_FLOW_MAPPING_KEY_STATE: - return yaml_parser_parse_flow_mapping_key(parser, event, false) - - case yaml_PARSE_FLOW_MAPPING_VALUE_STATE: - return yaml_parser_parse_flow_mapping_value(parser, event, false) - - case yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE: - return yaml_parser_parse_flow_mapping_value(parser, event, true) - - default: - panic("invalid parser state") - } -} - -// Parse the production: -// stream ::= STREAM-START implicit_document? explicit_document* STREAM-END -// ************ -func yaml_parser_parse_stream_start(parser *yaml_parser_t, event *yaml_event_t) bool { - token := peek_token(parser) - if token == nil { - return false - } - if token.typ != yaml_STREAM_START_TOKEN { - return yaml_parser_set_parser_error(parser, "did not find expected ", token.start_mark) - } - parser.state = yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE - *event = yaml_event_t{ - typ: yaml_STREAM_START_EVENT, - start_mark: token.start_mark, - end_mark: token.end_mark, - encoding: token.encoding, - } - skip_token(parser) - return true -} - -// Parse the productions: -// implicit_document ::= block_node DOCUMENT-END* -// * -// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END* -// ************************* -func yaml_parser_parse_document_start(parser *yaml_parser_t, event *yaml_event_t, implicit bool) bool { - - token := peek_token(parser) - if token == nil { - return false - } - - // Parse extra document end indicators. - if !implicit { - for token.typ == yaml_DOCUMENT_END_TOKEN { - skip_token(parser) - token = peek_token(parser) - if token == nil { - return false - } - } - } - - if implicit && token.typ != yaml_VERSION_DIRECTIVE_TOKEN && - token.typ != yaml_TAG_DIRECTIVE_TOKEN && - token.typ != yaml_DOCUMENT_START_TOKEN && - token.typ != yaml_STREAM_END_TOKEN { - // Parse an implicit document. - if !yaml_parser_process_directives(parser, nil, nil) { - return false - } - parser.states = append(parser.states, yaml_PARSE_DOCUMENT_END_STATE) - parser.state = yaml_PARSE_BLOCK_NODE_STATE - - var head_comment []byte - if len(parser.head_comment) > 0 { - // [Go] Scan the header comment backwards, and if an empty line is found, break - // the header so the part before the last empty line goes into the - // document header, while the bottom of it goes into a follow up event. - for i := len(parser.head_comment) - 1; i > 0; i-- { - if parser.head_comment[i] == '\n' { - if i == len(parser.head_comment)-1 { - head_comment = parser.head_comment[:i] - parser.head_comment = parser.head_comment[i+1:] - break - } else if parser.head_comment[i-1] == '\n' { - head_comment = parser.head_comment[:i-1] - parser.head_comment = parser.head_comment[i+1:] - break - } - } - } - } - - *event = yaml_event_t{ - typ: yaml_DOCUMENT_START_EVENT, - start_mark: token.start_mark, - end_mark: token.end_mark, - - head_comment: head_comment, - } - - } else if token.typ != yaml_STREAM_END_TOKEN { - // Parse an explicit document. - var version_directive *yaml_version_directive_t - var tag_directives []yaml_tag_directive_t - start_mark := token.start_mark - if !yaml_parser_process_directives(parser, &version_directive, &tag_directives) { - return false - } - token = peek_token(parser) - if token == nil { - return false - } - if token.typ != yaml_DOCUMENT_START_TOKEN { - yaml_parser_set_parser_error(parser, - "did not find expected ", token.start_mark) - return false - } - parser.states = append(parser.states, yaml_PARSE_DOCUMENT_END_STATE) - parser.state = yaml_PARSE_DOCUMENT_CONTENT_STATE - end_mark := token.end_mark - - *event = yaml_event_t{ - typ: yaml_DOCUMENT_START_EVENT, - start_mark: start_mark, - end_mark: end_mark, - version_directive: version_directive, - tag_directives: tag_directives, - implicit: false, - } - skip_token(parser) - - } else { - // Parse the stream end. - parser.state = yaml_PARSE_END_STATE - *event = yaml_event_t{ - typ: yaml_STREAM_END_EVENT, - start_mark: token.start_mark, - end_mark: token.end_mark, - } - skip_token(parser) - } - - return true -} - -// Parse the productions: -// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END* -// *********** -// -func yaml_parser_parse_document_content(parser *yaml_parser_t, event *yaml_event_t) bool { - token := peek_token(parser) - if token == nil { - return false - } - - if token.typ == yaml_VERSION_DIRECTIVE_TOKEN || - token.typ == yaml_TAG_DIRECTIVE_TOKEN || - token.typ == yaml_DOCUMENT_START_TOKEN || - token.typ == yaml_DOCUMENT_END_TOKEN || - token.typ == yaml_STREAM_END_TOKEN { - parser.state = parser.states[len(parser.states)-1] - parser.states = parser.states[:len(parser.states)-1] - return yaml_parser_process_empty_scalar(parser, event, - token.start_mark) - } - return yaml_parser_parse_node(parser, event, true, false) -} - -// Parse the productions: -// implicit_document ::= block_node DOCUMENT-END* -// ************* -// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END* -// -func yaml_parser_parse_document_end(parser *yaml_parser_t, event *yaml_event_t) bool { - token := peek_token(parser) - if token == nil { - return false - } - - start_mark := token.start_mark - end_mark := token.start_mark - - implicit := true - if token.typ == yaml_DOCUMENT_END_TOKEN { - end_mark = token.end_mark - skip_token(parser) - implicit = false - } - - parser.tag_directives = parser.tag_directives[:0] - - parser.state = yaml_PARSE_DOCUMENT_START_STATE - *event = yaml_event_t{ - typ: yaml_DOCUMENT_END_EVENT, - start_mark: start_mark, - end_mark: end_mark, - implicit: implicit, - } - yaml_parser_set_event_comments(parser, event) - if len(event.head_comment) > 0 && len(event.foot_comment) == 0 { - event.foot_comment = event.head_comment - event.head_comment = nil - } - return true -} - -func yaml_parser_set_event_comments(parser *yaml_parser_t, event *yaml_event_t) { - event.head_comment = parser.head_comment - event.line_comment = parser.line_comment - event.foot_comment = parser.foot_comment - parser.head_comment = nil - parser.line_comment = nil - parser.foot_comment = nil - parser.tail_comment = nil - parser.stem_comment = nil -} - -// Parse the productions: -// block_node_or_indentless_sequence ::= -// ALIAS -// ***** -// | properties (block_content | indentless_block_sequence)? -// ********** * -// | block_content | indentless_block_sequence -// * -// block_node ::= ALIAS -// ***** -// | properties block_content? -// ********** * -// | block_content -// * -// flow_node ::= ALIAS -// ***** -// | properties flow_content? -// ********** * -// | flow_content -// * -// properties ::= TAG ANCHOR? | ANCHOR TAG? -// ************************* -// block_content ::= block_collection | flow_collection | SCALAR -// ****** -// flow_content ::= flow_collection | SCALAR -// ****** -func yaml_parser_parse_node(parser *yaml_parser_t, event *yaml_event_t, block, indentless_sequence bool) bool { - //defer trace("yaml_parser_parse_node", "block:", block, "indentless_sequence:", indentless_sequence)() - - token := peek_token(parser) - if token == nil { - return false - } - - if token.typ == yaml_ALIAS_TOKEN { - parser.state = parser.states[len(parser.states)-1] - parser.states = parser.states[:len(parser.states)-1] - *event = yaml_event_t{ - typ: yaml_ALIAS_EVENT, - start_mark: token.start_mark, - end_mark: token.end_mark, - anchor: token.value, - } - yaml_parser_set_event_comments(parser, event) - skip_token(parser) - return true - } - - start_mark := token.start_mark - end_mark := token.start_mark - - var tag_token bool - var tag_handle, tag_suffix, anchor []byte - var tag_mark yaml_mark_t - if token.typ == yaml_ANCHOR_TOKEN { - anchor = token.value - start_mark = token.start_mark - end_mark = token.end_mark - skip_token(parser) - token = peek_token(parser) - if token == nil { - return false - } - if token.typ == yaml_TAG_TOKEN { - tag_token = true - tag_handle = token.value - tag_suffix = token.suffix - tag_mark = token.start_mark - end_mark = token.end_mark - skip_token(parser) - token = peek_token(parser) - if token == nil { - return false - } - } - } else if token.typ == yaml_TAG_TOKEN { - tag_token = true - tag_handle = token.value - tag_suffix = token.suffix - start_mark = token.start_mark - tag_mark = token.start_mark - end_mark = token.end_mark - skip_token(parser) - token = peek_token(parser) - if token == nil { - return false - } - if token.typ == yaml_ANCHOR_TOKEN { - anchor = token.value - end_mark = token.end_mark - skip_token(parser) - token = peek_token(parser) - if token == nil { - return false - } - } - } - - var tag []byte - if tag_token { - if len(tag_handle) == 0 { - tag = tag_suffix - tag_suffix = nil - } else { - for i := range parser.tag_directives { - if bytes.Equal(parser.tag_directives[i].handle, tag_handle) { - tag = append([]byte(nil), parser.tag_directives[i].prefix...) - tag = append(tag, tag_suffix...) - break - } - } - if len(tag) == 0 { - yaml_parser_set_parser_error_context(parser, - "while parsing a node", start_mark, - "found undefined tag handle", tag_mark) - return false - } - } - } - - implicit := len(tag) == 0 - if indentless_sequence && token.typ == yaml_BLOCK_ENTRY_TOKEN { - end_mark = token.end_mark - parser.state = yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE - *event = yaml_event_t{ - typ: yaml_SEQUENCE_START_EVENT, - start_mark: start_mark, - end_mark: end_mark, - anchor: anchor, - tag: tag, - implicit: implicit, - style: yaml_style_t(yaml_BLOCK_SEQUENCE_STYLE), - } - return true - } - if token.typ == yaml_SCALAR_TOKEN { - var plain_implicit, quoted_implicit bool - end_mark = token.end_mark - if (len(tag) == 0 && token.style == yaml_PLAIN_SCALAR_STYLE) || (len(tag) == 1 && tag[0] == '!') { - plain_implicit = true - } else if len(tag) == 0 { - quoted_implicit = true - } - parser.state = parser.states[len(parser.states)-1] - parser.states = parser.states[:len(parser.states)-1] - - *event = yaml_event_t{ - typ: yaml_SCALAR_EVENT, - start_mark: start_mark, - end_mark: end_mark, - anchor: anchor, - tag: tag, - value: token.value, - implicit: plain_implicit, - quoted_implicit: quoted_implicit, - style: yaml_style_t(token.style), - } - yaml_parser_set_event_comments(parser, event) - skip_token(parser) - return true - } - if token.typ == yaml_FLOW_SEQUENCE_START_TOKEN { - // [Go] Some of the events below can be merged as they differ only on style. - end_mark = token.end_mark - parser.state = yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE - *event = yaml_event_t{ - typ: yaml_SEQUENCE_START_EVENT, - start_mark: start_mark, - end_mark: end_mark, - anchor: anchor, - tag: tag, - implicit: implicit, - style: yaml_style_t(yaml_FLOW_SEQUENCE_STYLE), - } - yaml_parser_set_event_comments(parser, event) - return true - } - if token.typ == yaml_FLOW_MAPPING_START_TOKEN { - end_mark = token.end_mark - parser.state = yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE - *event = yaml_event_t{ - typ: yaml_MAPPING_START_EVENT, - start_mark: start_mark, - end_mark: end_mark, - anchor: anchor, - tag: tag, - implicit: implicit, - style: yaml_style_t(yaml_FLOW_MAPPING_STYLE), - } - yaml_parser_set_event_comments(parser, event) - return true - } - if block && token.typ == yaml_BLOCK_SEQUENCE_START_TOKEN { - end_mark = token.end_mark - parser.state = yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE - *event = yaml_event_t{ - typ: yaml_SEQUENCE_START_EVENT, - start_mark: start_mark, - end_mark: end_mark, - anchor: anchor, - tag: tag, - implicit: implicit, - style: yaml_style_t(yaml_BLOCK_SEQUENCE_STYLE), - } - if parser.stem_comment != nil { - event.head_comment = parser.stem_comment - parser.stem_comment = nil - } - return true - } - if block && token.typ == yaml_BLOCK_MAPPING_START_TOKEN { - end_mark = token.end_mark - parser.state = yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE - *event = yaml_event_t{ - typ: yaml_MAPPING_START_EVENT, - start_mark: start_mark, - end_mark: end_mark, - anchor: anchor, - tag: tag, - implicit: implicit, - style: yaml_style_t(yaml_BLOCK_MAPPING_STYLE), - } - if parser.stem_comment != nil { - event.head_comment = parser.stem_comment - parser.stem_comment = nil - } - return true - } - if len(anchor) > 0 || len(tag) > 0 { - parser.state = parser.states[len(parser.states)-1] - parser.states = parser.states[:len(parser.states)-1] - - *event = yaml_event_t{ - typ: yaml_SCALAR_EVENT, - start_mark: start_mark, - end_mark: end_mark, - anchor: anchor, - tag: tag, - implicit: implicit, - quoted_implicit: false, - style: yaml_style_t(yaml_PLAIN_SCALAR_STYLE), - } - return true - } - - context := "while parsing a flow node" - if block { - context = "while parsing a block node" - } - yaml_parser_set_parser_error_context(parser, context, start_mark, - "did not find expected node content", token.start_mark) - return false -} - -// Parse the productions: -// block_sequence ::= BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END -// ******************** *********** * ********* -// -func yaml_parser_parse_block_sequence_entry(parser *yaml_parser_t, event *yaml_event_t, first bool) bool { - if first { - token := peek_token(parser) - if token == nil { - return false - } - parser.marks = append(parser.marks, token.start_mark) - skip_token(parser) - } - - token := peek_token(parser) - if token == nil { - return false - } - - if token.typ == yaml_BLOCK_ENTRY_TOKEN { - mark := token.end_mark - prior_head_len := len(parser.head_comment) - skip_token(parser) - yaml_parser_split_stem_comment(parser, prior_head_len) - token = peek_token(parser) - if token == nil { - return false - } - if token.typ != yaml_BLOCK_ENTRY_TOKEN && token.typ != yaml_BLOCK_END_TOKEN { - parser.states = append(parser.states, yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE) - return yaml_parser_parse_node(parser, event, true, false) - } else { - parser.state = yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE - return yaml_parser_process_empty_scalar(parser, event, mark) - } - } - if token.typ == yaml_BLOCK_END_TOKEN { - parser.state = parser.states[len(parser.states)-1] - parser.states = parser.states[:len(parser.states)-1] - parser.marks = parser.marks[:len(parser.marks)-1] - - *event = yaml_event_t{ - typ: yaml_SEQUENCE_END_EVENT, - start_mark: token.start_mark, - end_mark: token.end_mark, - } - - skip_token(parser) - return true - } - - context_mark := parser.marks[len(parser.marks)-1] - parser.marks = parser.marks[:len(parser.marks)-1] - return yaml_parser_set_parser_error_context(parser, - "while parsing a block collection", context_mark, - "did not find expected '-' indicator", token.start_mark) -} - -// Parse the productions: -// indentless_sequence ::= (BLOCK-ENTRY block_node?)+ -// *********** * -func yaml_parser_parse_indentless_sequence_entry(parser *yaml_parser_t, event *yaml_event_t) bool { - token := peek_token(parser) - if token == nil { - return false - } - - if token.typ == yaml_BLOCK_ENTRY_TOKEN { - mark := token.end_mark - prior_head_len := len(parser.head_comment) - skip_token(parser) - yaml_parser_split_stem_comment(parser, prior_head_len) - token = peek_token(parser) - if token == nil { - return false - } - if token.typ != yaml_BLOCK_ENTRY_TOKEN && - token.typ != yaml_KEY_TOKEN && - token.typ != yaml_VALUE_TOKEN && - token.typ != yaml_BLOCK_END_TOKEN { - parser.states = append(parser.states, yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE) - return yaml_parser_parse_node(parser, event, true, false) - } - parser.state = yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE - return yaml_parser_process_empty_scalar(parser, event, mark) - } - parser.state = parser.states[len(parser.states)-1] - parser.states = parser.states[:len(parser.states)-1] - - *event = yaml_event_t{ - typ: yaml_SEQUENCE_END_EVENT, - start_mark: token.start_mark, - end_mark: token.start_mark, // [Go] Shouldn't this be token.end_mark? - } - return true -} - -// Split stem comment from head comment. -// -// When a sequence or map is found under a sequence entry, the former head comment -// is assigned to the underlying sequence or map as a whole, not the individual -// sequence or map entry as would be expected otherwise. To handle this case the -// previous head comment is moved aside as the stem comment. -func yaml_parser_split_stem_comment(parser *yaml_parser_t, stem_len int) { - if stem_len == 0 { - return - } - - token := peek_token(parser) - if token == nil || token.typ != yaml_BLOCK_SEQUENCE_START_TOKEN && token.typ != yaml_BLOCK_MAPPING_START_TOKEN { - return - } - - parser.stem_comment = parser.head_comment[:stem_len] - if len(parser.head_comment) == stem_len { - parser.head_comment = nil - } else { - // Copy suffix to prevent very strange bugs if someone ever appends - // further bytes to the prefix in the stem_comment slice above. - parser.head_comment = append([]byte(nil), parser.head_comment[stem_len+1:]...) - } -} - -// Parse the productions: -// block_mapping ::= BLOCK-MAPPING_START -// ******************* -// ((KEY block_node_or_indentless_sequence?)? -// *** * -// (VALUE block_node_or_indentless_sequence?)?)* -// -// BLOCK-END -// ********* -// -func yaml_parser_parse_block_mapping_key(parser *yaml_parser_t, event *yaml_event_t, first bool) bool { - if first { - token := peek_token(parser) - if token == nil { - return false - } - parser.marks = append(parser.marks, token.start_mark) - skip_token(parser) - } - - token := peek_token(parser) - if token == nil { - return false - } - - // [Go] A tail comment was left from the prior mapping value processed. Emit an event - // as it needs to be processed with that value and not the following key. - if len(parser.tail_comment) > 0 { - *event = yaml_event_t{ - typ: yaml_TAIL_COMMENT_EVENT, - start_mark: token.start_mark, - end_mark: token.end_mark, - foot_comment: parser.tail_comment, - } - parser.tail_comment = nil - return true - } - - if token.typ == yaml_KEY_TOKEN { - mark := token.end_mark - skip_token(parser) - token = peek_token(parser) - if token == nil { - return false - } - if token.typ != yaml_KEY_TOKEN && - token.typ != yaml_VALUE_TOKEN && - token.typ != yaml_BLOCK_END_TOKEN { - parser.states = append(parser.states, yaml_PARSE_BLOCK_MAPPING_VALUE_STATE) - return yaml_parser_parse_node(parser, event, true, true) - } else { - parser.state = yaml_PARSE_BLOCK_MAPPING_VALUE_STATE - return yaml_parser_process_empty_scalar(parser, event, mark) - } - } else if token.typ == yaml_BLOCK_END_TOKEN { - parser.state = parser.states[len(parser.states)-1] - parser.states = parser.states[:len(parser.states)-1] - parser.marks = parser.marks[:len(parser.marks)-1] - *event = yaml_event_t{ - typ: yaml_MAPPING_END_EVENT, - start_mark: token.start_mark, - end_mark: token.end_mark, - } - yaml_parser_set_event_comments(parser, event) - skip_token(parser) - return true - } - - context_mark := parser.marks[len(parser.marks)-1] - parser.marks = parser.marks[:len(parser.marks)-1] - return yaml_parser_set_parser_error_context(parser, - "while parsing a block mapping", context_mark, - "did not find expected key", token.start_mark) -} - -// Parse the productions: -// block_mapping ::= BLOCK-MAPPING_START -// -// ((KEY block_node_or_indentless_sequence?)? -// -// (VALUE block_node_or_indentless_sequence?)?)* -// ***** * -// BLOCK-END -// -// -func yaml_parser_parse_block_mapping_value(parser *yaml_parser_t, event *yaml_event_t) bool { - token := peek_token(parser) - if token == nil { - return false - } - if token.typ == yaml_VALUE_TOKEN { - mark := token.end_mark - skip_token(parser) - token = peek_token(parser) - if token == nil { - return false - } - if token.typ != yaml_KEY_TOKEN && - token.typ != yaml_VALUE_TOKEN && - token.typ != yaml_BLOCK_END_TOKEN { - parser.states = append(parser.states, yaml_PARSE_BLOCK_MAPPING_KEY_STATE) - return yaml_parser_parse_node(parser, event, true, true) - } - parser.state = yaml_PARSE_BLOCK_MAPPING_KEY_STATE - return yaml_parser_process_empty_scalar(parser, event, mark) - } - parser.state = yaml_PARSE_BLOCK_MAPPING_KEY_STATE - return yaml_parser_process_empty_scalar(parser, event, token.start_mark) -} - -// Parse the productions: -// flow_sequence ::= FLOW-SEQUENCE-START -// ******************* -// (flow_sequence_entry FLOW-ENTRY)* -// * ********** -// flow_sequence_entry? -// * -// FLOW-SEQUENCE-END -// ***************** -// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? -// * -// -func yaml_parser_parse_flow_sequence_entry(parser *yaml_parser_t, event *yaml_event_t, first bool) bool { - if first { - token := peek_token(parser) - if token == nil { - return false - } - parser.marks = append(parser.marks, token.start_mark) - skip_token(parser) - } - token := peek_token(parser) - if token == nil { - return false - } - if token.typ != yaml_FLOW_SEQUENCE_END_TOKEN { - if !first { - if token.typ == yaml_FLOW_ENTRY_TOKEN { - skip_token(parser) - token = peek_token(parser) - if token == nil { - return false - } - } else { - context_mark := parser.marks[len(parser.marks)-1] - parser.marks = parser.marks[:len(parser.marks)-1] - return yaml_parser_set_parser_error_context(parser, - "while parsing a flow sequence", context_mark, - "did not find expected ',' or ']'", token.start_mark) - } - } - - if token.typ == yaml_KEY_TOKEN { - parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE - *event = yaml_event_t{ - typ: yaml_MAPPING_START_EVENT, - start_mark: token.start_mark, - end_mark: token.end_mark, - implicit: true, - style: yaml_style_t(yaml_FLOW_MAPPING_STYLE), - } - skip_token(parser) - return true - } else if token.typ != yaml_FLOW_SEQUENCE_END_TOKEN { - parser.states = append(parser.states, yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE) - return yaml_parser_parse_node(parser, event, false, false) - } - } - - parser.state = parser.states[len(parser.states)-1] - parser.states = parser.states[:len(parser.states)-1] - parser.marks = parser.marks[:len(parser.marks)-1] - - *event = yaml_event_t{ - typ: yaml_SEQUENCE_END_EVENT, - start_mark: token.start_mark, - end_mark: token.end_mark, - } - yaml_parser_set_event_comments(parser, event) - - skip_token(parser) - return true -} - -// -// Parse the productions: -// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? -// *** * -// -func yaml_parser_parse_flow_sequence_entry_mapping_key(parser *yaml_parser_t, event *yaml_event_t) bool { - token := peek_token(parser) - if token == nil { - return false - } - if token.typ != yaml_VALUE_TOKEN && - token.typ != yaml_FLOW_ENTRY_TOKEN && - token.typ != yaml_FLOW_SEQUENCE_END_TOKEN { - parser.states = append(parser.states, yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE) - return yaml_parser_parse_node(parser, event, false, false) - } - mark := token.end_mark - skip_token(parser) - parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE - return yaml_parser_process_empty_scalar(parser, event, mark) -} - -// Parse the productions: -// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? -// ***** * -// -func yaml_parser_parse_flow_sequence_entry_mapping_value(parser *yaml_parser_t, event *yaml_event_t) bool { - token := peek_token(parser) - if token == nil { - return false - } - if token.typ == yaml_VALUE_TOKEN { - skip_token(parser) - token := peek_token(parser) - if token == nil { - return false - } - if token.typ != yaml_FLOW_ENTRY_TOKEN && token.typ != yaml_FLOW_SEQUENCE_END_TOKEN { - parser.states = append(parser.states, yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE) - return yaml_parser_parse_node(parser, event, false, false) - } - } - parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE - return yaml_parser_process_empty_scalar(parser, event, token.start_mark) -} - -// Parse the productions: -// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? -// * -// -func yaml_parser_parse_flow_sequence_entry_mapping_end(parser *yaml_parser_t, event *yaml_event_t) bool { - token := peek_token(parser) - if token == nil { - return false - } - parser.state = yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE - *event = yaml_event_t{ - typ: yaml_MAPPING_END_EVENT, - start_mark: token.start_mark, - end_mark: token.start_mark, // [Go] Shouldn't this be end_mark? - } - return true -} - -// Parse the productions: -// flow_mapping ::= FLOW-MAPPING-START -// ****************** -// (flow_mapping_entry FLOW-ENTRY)* -// * ********** -// flow_mapping_entry? -// ****************** -// FLOW-MAPPING-END -// **************** -// flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? -// * *** * -// -func yaml_parser_parse_flow_mapping_key(parser *yaml_parser_t, event *yaml_event_t, first bool) bool { - if first { - token := peek_token(parser) - parser.marks = append(parser.marks, token.start_mark) - skip_token(parser) - } - - token := peek_token(parser) - if token == nil { - return false - } - - if token.typ != yaml_FLOW_MAPPING_END_TOKEN { - if !first { - if token.typ == yaml_FLOW_ENTRY_TOKEN { - skip_token(parser) - token = peek_token(parser) - if token == nil { - return false - } - } else { - context_mark := parser.marks[len(parser.marks)-1] - parser.marks = parser.marks[:len(parser.marks)-1] - return yaml_parser_set_parser_error_context(parser, - "while parsing a flow mapping", context_mark, - "did not find expected ',' or '}'", token.start_mark) - } - } - - if token.typ == yaml_KEY_TOKEN { - skip_token(parser) - token = peek_token(parser) - if token == nil { - return false - } - if token.typ != yaml_VALUE_TOKEN && - token.typ != yaml_FLOW_ENTRY_TOKEN && - token.typ != yaml_FLOW_MAPPING_END_TOKEN { - parser.states = append(parser.states, yaml_PARSE_FLOW_MAPPING_VALUE_STATE) - return yaml_parser_parse_node(parser, event, false, false) - } else { - parser.state = yaml_PARSE_FLOW_MAPPING_VALUE_STATE - return yaml_parser_process_empty_scalar(parser, event, token.start_mark) - } - } else if token.typ != yaml_FLOW_MAPPING_END_TOKEN { - parser.states = append(parser.states, yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE) - return yaml_parser_parse_node(parser, event, false, false) - } - } - - parser.state = parser.states[len(parser.states)-1] - parser.states = parser.states[:len(parser.states)-1] - parser.marks = parser.marks[:len(parser.marks)-1] - *event = yaml_event_t{ - typ: yaml_MAPPING_END_EVENT, - start_mark: token.start_mark, - end_mark: token.end_mark, - } - yaml_parser_set_event_comments(parser, event) - skip_token(parser) - return true -} - -// Parse the productions: -// flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? -// * ***** * -// -func yaml_parser_parse_flow_mapping_value(parser *yaml_parser_t, event *yaml_event_t, empty bool) bool { - token := peek_token(parser) - if token == nil { - return false - } - if empty { - parser.state = yaml_PARSE_FLOW_MAPPING_KEY_STATE - return yaml_parser_process_empty_scalar(parser, event, token.start_mark) - } - if token.typ == yaml_VALUE_TOKEN { - skip_token(parser) - token = peek_token(parser) - if token == nil { - return false - } - if token.typ != yaml_FLOW_ENTRY_TOKEN && token.typ != yaml_FLOW_MAPPING_END_TOKEN { - parser.states = append(parser.states, yaml_PARSE_FLOW_MAPPING_KEY_STATE) - return yaml_parser_parse_node(parser, event, false, false) - } - } - parser.state = yaml_PARSE_FLOW_MAPPING_KEY_STATE - return yaml_parser_process_empty_scalar(parser, event, token.start_mark) -} - -// Generate an empty scalar event. -func yaml_parser_process_empty_scalar(parser *yaml_parser_t, event *yaml_event_t, mark yaml_mark_t) bool { - *event = yaml_event_t{ - typ: yaml_SCALAR_EVENT, - start_mark: mark, - end_mark: mark, - value: nil, // Empty - implicit: true, - style: yaml_style_t(yaml_PLAIN_SCALAR_STYLE), - } - return true -} - -var default_tag_directives = []yaml_tag_directive_t{ - {[]byte("!"), []byte("!")}, - {[]byte("!!"), []byte("tag:yaml.org,2002:")}, -} - -// Parse directives. -func yaml_parser_process_directives(parser *yaml_parser_t, - version_directive_ref **yaml_version_directive_t, - tag_directives_ref *[]yaml_tag_directive_t) bool { - - var version_directive *yaml_version_directive_t - var tag_directives []yaml_tag_directive_t - - token := peek_token(parser) - if token == nil { - return false - } - - for token.typ == yaml_VERSION_DIRECTIVE_TOKEN || token.typ == yaml_TAG_DIRECTIVE_TOKEN { - if token.typ == yaml_VERSION_DIRECTIVE_TOKEN { - if version_directive != nil { - yaml_parser_set_parser_error(parser, - "found duplicate %YAML directive", token.start_mark) - return false - } - if token.major != 1 || token.minor != 1 { - yaml_parser_set_parser_error(parser, - "found incompatible YAML document", token.start_mark) - return false - } - version_directive = &yaml_version_directive_t{ - major: token.major, - minor: token.minor, - } - } else if token.typ == yaml_TAG_DIRECTIVE_TOKEN { - value := yaml_tag_directive_t{ - handle: token.value, - prefix: token.prefix, - } - if !yaml_parser_append_tag_directive(parser, value, false, token.start_mark) { - return false - } - tag_directives = append(tag_directives, value) - } - - skip_token(parser) - token = peek_token(parser) - if token == nil { - return false - } - } - - for i := range default_tag_directives { - if !yaml_parser_append_tag_directive(parser, default_tag_directives[i], true, token.start_mark) { - return false - } - } - - if version_directive_ref != nil { - *version_directive_ref = version_directive - } - if tag_directives_ref != nil { - *tag_directives_ref = tag_directives - } - return true -} - -// Append a tag directive to the directives stack. -func yaml_parser_append_tag_directive(parser *yaml_parser_t, value yaml_tag_directive_t, allow_duplicates bool, mark yaml_mark_t) bool { - for i := range parser.tag_directives { - if bytes.Equal(value.handle, parser.tag_directives[i].handle) { - if allow_duplicates { - return true - } - return yaml_parser_set_parser_error(parser, "found duplicate %TAG directive", mark) - } - } - - // [Go] I suspect the copy is unnecessary. This was likely done - // because there was no way to track ownership of the data. - value_copy := yaml_tag_directive_t{ - handle: make([]byte, len(value.handle)), - prefix: make([]byte, len(value.prefix)), - } - copy(value_copy.handle, value.handle) - copy(value_copy.prefix, value.prefix) - parser.tag_directives = append(parser.tag_directives, value_copy) - return true -} diff --git a/trunk/3rdparty/srs-bench/vendor/gopkg.in/yaml.v3/readerc.go b/trunk/3rdparty/srs-bench/vendor/gopkg.in/yaml.v3/readerc.go deleted file mode 100644 index b7de0a89c..000000000 --- a/trunk/3rdparty/srs-bench/vendor/gopkg.in/yaml.v3/readerc.go +++ /dev/null @@ -1,434 +0,0 @@ -// -// Copyright (c) 2011-2019 Canonical Ltd -// Copyright (c) 2006-2010 Kirill Simonov -// -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -// of the Software, and to permit persons to whom the Software is furnished to do -// so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -package yaml - -import ( - "io" -) - -// Set the reader error and return 0. -func yaml_parser_set_reader_error(parser *yaml_parser_t, problem string, offset int, value int) bool { - parser.error = yaml_READER_ERROR - parser.problem = problem - parser.problem_offset = offset - parser.problem_value = value - return false -} - -// Byte order marks. -const ( - bom_UTF8 = "\xef\xbb\xbf" - bom_UTF16LE = "\xff\xfe" - bom_UTF16BE = "\xfe\xff" -) - -// Determine the input stream encoding by checking the BOM symbol. If no BOM is -// found, the UTF-8 encoding is assumed. Return 1 on success, 0 on failure. -func yaml_parser_determine_encoding(parser *yaml_parser_t) bool { - // Ensure that we had enough bytes in the raw buffer. - for !parser.eof && len(parser.raw_buffer)-parser.raw_buffer_pos < 3 { - if !yaml_parser_update_raw_buffer(parser) { - return false - } - } - - // Determine the encoding. - buf := parser.raw_buffer - pos := parser.raw_buffer_pos - avail := len(buf) - pos - if avail >= 2 && buf[pos] == bom_UTF16LE[0] && buf[pos+1] == bom_UTF16LE[1] { - parser.encoding = yaml_UTF16LE_ENCODING - parser.raw_buffer_pos += 2 - parser.offset += 2 - } else if avail >= 2 && buf[pos] == bom_UTF16BE[0] && buf[pos+1] == bom_UTF16BE[1] { - parser.encoding = yaml_UTF16BE_ENCODING - parser.raw_buffer_pos += 2 - parser.offset += 2 - } else if avail >= 3 && buf[pos] == bom_UTF8[0] && buf[pos+1] == bom_UTF8[1] && buf[pos+2] == bom_UTF8[2] { - parser.encoding = yaml_UTF8_ENCODING - parser.raw_buffer_pos += 3 - parser.offset += 3 - } else { - parser.encoding = yaml_UTF8_ENCODING - } - return true -} - -// Update the raw buffer. -func yaml_parser_update_raw_buffer(parser *yaml_parser_t) bool { - size_read := 0 - - // Return if the raw buffer is full. - if parser.raw_buffer_pos == 0 && len(parser.raw_buffer) == cap(parser.raw_buffer) { - return true - } - - // Return on EOF. - if parser.eof { - return true - } - - // Move the remaining bytes in the raw buffer to the beginning. - if parser.raw_buffer_pos > 0 && parser.raw_buffer_pos < len(parser.raw_buffer) { - copy(parser.raw_buffer, parser.raw_buffer[parser.raw_buffer_pos:]) - } - parser.raw_buffer = parser.raw_buffer[:len(parser.raw_buffer)-parser.raw_buffer_pos] - parser.raw_buffer_pos = 0 - - // Call the read handler to fill the buffer. - size_read, err := parser.read_handler(parser, parser.raw_buffer[len(parser.raw_buffer):cap(parser.raw_buffer)]) - parser.raw_buffer = parser.raw_buffer[:len(parser.raw_buffer)+size_read] - if err == io.EOF { - parser.eof = true - } else if err != nil { - return yaml_parser_set_reader_error(parser, "input error: "+err.Error(), parser.offset, -1) - } - return true -} - -// Ensure that the buffer contains at least `length` characters. -// Return true on success, false on failure. -// -// The length is supposed to be significantly less that the buffer size. -func yaml_parser_update_buffer(parser *yaml_parser_t, length int) bool { - if parser.read_handler == nil { - panic("read handler must be set") - } - - // [Go] This function was changed to guarantee the requested length size at EOF. - // The fact we need to do this is pretty awful, but the description above implies - // for that to be the case, and there are tests - - // If the EOF flag is set and the raw buffer is empty, do nothing. - if parser.eof && parser.raw_buffer_pos == len(parser.raw_buffer) { - // [Go] ACTUALLY! Read the documentation of this function above. - // This is just broken. To return true, we need to have the - // given length in the buffer. Not doing that means every single - // check that calls this function to make sure the buffer has a - // given length is Go) panicking; or C) accessing invalid memory. - //return true - } - - // Return if the buffer contains enough characters. - if parser.unread >= length { - return true - } - - // Determine the input encoding if it is not known yet. - if parser.encoding == yaml_ANY_ENCODING { - if !yaml_parser_determine_encoding(parser) { - return false - } - } - - // Move the unread characters to the beginning of the buffer. - buffer_len := len(parser.buffer) - if parser.buffer_pos > 0 && parser.buffer_pos < buffer_len { - copy(parser.buffer, parser.buffer[parser.buffer_pos:]) - buffer_len -= parser.buffer_pos - parser.buffer_pos = 0 - } else if parser.buffer_pos == buffer_len { - buffer_len = 0 - parser.buffer_pos = 0 - } - - // Open the whole buffer for writing, and cut it before returning. - parser.buffer = parser.buffer[:cap(parser.buffer)] - - // Fill the buffer until it has enough characters. - first := true - for parser.unread < length { - - // Fill the raw buffer if necessary. - if !first || parser.raw_buffer_pos == len(parser.raw_buffer) { - if !yaml_parser_update_raw_buffer(parser) { - parser.buffer = parser.buffer[:buffer_len] - return false - } - } - first = false - - // Decode the raw buffer. - inner: - for parser.raw_buffer_pos != len(parser.raw_buffer) { - var value rune - var width int - - raw_unread := len(parser.raw_buffer) - parser.raw_buffer_pos - - // Decode the next character. - switch parser.encoding { - case yaml_UTF8_ENCODING: - // Decode a UTF-8 character. Check RFC 3629 - // (http://www.ietf.org/rfc/rfc3629.txt) for more details. - // - // The following table (taken from the RFC) is used for - // decoding. - // - // Char. number range | UTF-8 octet sequence - // (hexadecimal) | (binary) - // --------------------+------------------------------------ - // 0000 0000-0000 007F | 0xxxxxxx - // 0000 0080-0000 07FF | 110xxxxx 10xxxxxx - // 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx - // 0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx - // - // Additionally, the characters in the range 0xD800-0xDFFF - // are prohibited as they are reserved for use with UTF-16 - // surrogate pairs. - - // Determine the length of the UTF-8 sequence. - octet := parser.raw_buffer[parser.raw_buffer_pos] - switch { - case octet&0x80 == 0x00: - width = 1 - case octet&0xE0 == 0xC0: - width = 2 - case octet&0xF0 == 0xE0: - width = 3 - case octet&0xF8 == 0xF0: - width = 4 - default: - // The leading octet is invalid. - return yaml_parser_set_reader_error(parser, - "invalid leading UTF-8 octet", - parser.offset, int(octet)) - } - - // Check if the raw buffer contains an incomplete character. - if width > raw_unread { - if parser.eof { - return yaml_parser_set_reader_error(parser, - "incomplete UTF-8 octet sequence", - parser.offset, -1) - } - break inner - } - - // Decode the leading octet. - switch { - case octet&0x80 == 0x00: - value = rune(octet & 0x7F) - case octet&0xE0 == 0xC0: - value = rune(octet & 0x1F) - case octet&0xF0 == 0xE0: - value = rune(octet & 0x0F) - case octet&0xF8 == 0xF0: - value = rune(octet & 0x07) - default: - value = 0 - } - - // Check and decode the trailing octets. - for k := 1; k < width; k++ { - octet = parser.raw_buffer[parser.raw_buffer_pos+k] - - // Check if the octet is valid. - if (octet & 0xC0) != 0x80 { - return yaml_parser_set_reader_error(parser, - "invalid trailing UTF-8 octet", - parser.offset+k, int(octet)) - } - - // Decode the octet. - value = (value << 6) + rune(octet&0x3F) - } - - // Check the length of the sequence against the value. - switch { - case width == 1: - case width == 2 && value >= 0x80: - case width == 3 && value >= 0x800: - case width == 4 && value >= 0x10000: - default: - return yaml_parser_set_reader_error(parser, - "invalid length of a UTF-8 sequence", - parser.offset, -1) - } - - // Check the range of the value. - if value >= 0xD800 && value <= 0xDFFF || value > 0x10FFFF { - return yaml_parser_set_reader_error(parser, - "invalid Unicode character", - parser.offset, int(value)) - } - - case yaml_UTF16LE_ENCODING, yaml_UTF16BE_ENCODING: - var low, high int - if parser.encoding == yaml_UTF16LE_ENCODING { - low, high = 0, 1 - } else { - low, high = 1, 0 - } - - // The UTF-16 encoding is not as simple as one might - // naively think. Check RFC 2781 - // (http://www.ietf.org/rfc/rfc2781.txt). - // - // Normally, two subsequent bytes describe a Unicode - // character. However a special technique (called a - // surrogate pair) is used for specifying character - // values larger than 0xFFFF. - // - // A surrogate pair consists of two pseudo-characters: - // high surrogate area (0xD800-0xDBFF) - // low surrogate area (0xDC00-0xDFFF) - // - // The following formulas are used for decoding - // and encoding characters using surrogate pairs: - // - // U = U' + 0x10000 (0x01 00 00 <= U <= 0x10 FF FF) - // U' = yyyyyyyyyyxxxxxxxxxx (0 <= U' <= 0x0F FF FF) - // W1 = 110110yyyyyyyyyy - // W2 = 110111xxxxxxxxxx - // - // where U is the character value, W1 is the high surrogate - // area, W2 is the low surrogate area. - - // Check for incomplete UTF-16 character. - if raw_unread < 2 { - if parser.eof { - return yaml_parser_set_reader_error(parser, - "incomplete UTF-16 character", - parser.offset, -1) - } - break inner - } - - // Get the character. - value = rune(parser.raw_buffer[parser.raw_buffer_pos+low]) + - (rune(parser.raw_buffer[parser.raw_buffer_pos+high]) << 8) - - // Check for unexpected low surrogate area. - if value&0xFC00 == 0xDC00 { - return yaml_parser_set_reader_error(parser, - "unexpected low surrogate area", - parser.offset, int(value)) - } - - // Check for a high surrogate area. - if value&0xFC00 == 0xD800 { - width = 4 - - // Check for incomplete surrogate pair. - if raw_unread < 4 { - if parser.eof { - return yaml_parser_set_reader_error(parser, - "incomplete UTF-16 surrogate pair", - parser.offset, -1) - } - break inner - } - - // Get the next character. - value2 := rune(parser.raw_buffer[parser.raw_buffer_pos+low+2]) + - (rune(parser.raw_buffer[parser.raw_buffer_pos+high+2]) << 8) - - // Check for a low surrogate area. - if value2&0xFC00 != 0xDC00 { - return yaml_parser_set_reader_error(parser, - "expected low surrogate area", - parser.offset+2, int(value2)) - } - - // Generate the value of the surrogate pair. - value = 0x10000 + ((value & 0x3FF) << 10) + (value2 & 0x3FF) - } else { - width = 2 - } - - default: - panic("impossible") - } - - // Check if the character is in the allowed range: - // #x9 | #xA | #xD | [#x20-#x7E] (8 bit) - // | #x85 | [#xA0-#xD7FF] | [#xE000-#xFFFD] (16 bit) - // | [#x10000-#x10FFFF] (32 bit) - switch { - case value == 0x09: - case value == 0x0A: - case value == 0x0D: - case value >= 0x20 && value <= 0x7E: - case value == 0x85: - case value >= 0xA0 && value <= 0xD7FF: - case value >= 0xE000 && value <= 0xFFFD: - case value >= 0x10000 && value <= 0x10FFFF: - default: - return yaml_parser_set_reader_error(parser, - "control characters are not allowed", - parser.offset, int(value)) - } - - // Move the raw pointers. - parser.raw_buffer_pos += width - parser.offset += width - - // Finally put the character into the buffer. - if value <= 0x7F { - // 0000 0000-0000 007F . 0xxxxxxx - parser.buffer[buffer_len+0] = byte(value) - buffer_len += 1 - } else if value <= 0x7FF { - // 0000 0080-0000 07FF . 110xxxxx 10xxxxxx - parser.buffer[buffer_len+0] = byte(0xC0 + (value >> 6)) - parser.buffer[buffer_len+1] = byte(0x80 + (value & 0x3F)) - buffer_len += 2 - } else if value <= 0xFFFF { - // 0000 0800-0000 FFFF . 1110xxxx 10xxxxxx 10xxxxxx - parser.buffer[buffer_len+0] = byte(0xE0 + (value >> 12)) - parser.buffer[buffer_len+1] = byte(0x80 + ((value >> 6) & 0x3F)) - parser.buffer[buffer_len+2] = byte(0x80 + (value & 0x3F)) - buffer_len += 3 - } else { - // 0001 0000-0010 FFFF . 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx - parser.buffer[buffer_len+0] = byte(0xF0 + (value >> 18)) - parser.buffer[buffer_len+1] = byte(0x80 + ((value >> 12) & 0x3F)) - parser.buffer[buffer_len+2] = byte(0x80 + ((value >> 6) & 0x3F)) - parser.buffer[buffer_len+3] = byte(0x80 + (value & 0x3F)) - buffer_len += 4 - } - - parser.unread++ - } - - // On EOF, put NUL into the buffer and return. - if parser.eof { - parser.buffer[buffer_len] = 0 - buffer_len++ - parser.unread++ - break - } - } - // [Go] Read the documentation of this function above. To return true, - // we need to have the given length in the buffer. Not doing that means - // every single check that calls this function to make sure the buffer - // has a given length is Go) panicking; or C) accessing invalid memory. - // This happens here due to the EOF above breaking early. - for buffer_len < length { - parser.buffer[buffer_len] = 0 - buffer_len++ - } - parser.buffer = parser.buffer[:buffer_len] - return true -} diff --git a/trunk/3rdparty/srs-bench/vendor/gopkg.in/yaml.v3/resolve.go b/trunk/3rdparty/srs-bench/vendor/gopkg.in/yaml.v3/resolve.go deleted file mode 100644 index 64ae88805..000000000 --- a/trunk/3rdparty/srs-bench/vendor/gopkg.in/yaml.v3/resolve.go +++ /dev/null @@ -1,326 +0,0 @@ -// -// Copyright (c) 2011-2019 Canonical Ltd -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package yaml - -import ( - "encoding/base64" - "math" - "regexp" - "strconv" - "strings" - "time" -) - -type resolveMapItem struct { - value interface{} - tag string -} - -var resolveTable = make([]byte, 256) -var resolveMap = make(map[string]resolveMapItem) - -func init() { - t := resolveTable - t[int('+')] = 'S' // Sign - t[int('-')] = 'S' - for _, c := range "0123456789" { - t[int(c)] = 'D' // Digit - } - for _, c := range "yYnNtTfFoO~" { - t[int(c)] = 'M' // In map - } - t[int('.')] = '.' // Float (potentially in map) - - var resolveMapList = []struct { - v interface{} - tag string - l []string - }{ - {true, boolTag, []string{"true", "True", "TRUE"}}, - {false, boolTag, []string{"false", "False", "FALSE"}}, - {nil, nullTag, []string{"", "~", "null", "Null", "NULL"}}, - {math.NaN(), floatTag, []string{".nan", ".NaN", ".NAN"}}, - {math.Inf(+1), floatTag, []string{".inf", ".Inf", ".INF"}}, - {math.Inf(+1), floatTag, []string{"+.inf", "+.Inf", "+.INF"}}, - {math.Inf(-1), floatTag, []string{"-.inf", "-.Inf", "-.INF"}}, - {"<<", mergeTag, []string{"<<"}}, - } - - m := resolveMap - for _, item := range resolveMapList { - for _, s := range item.l { - m[s] = resolveMapItem{item.v, item.tag} - } - } -} - -const ( - nullTag = "!!null" - boolTag = "!!bool" - strTag = "!!str" - intTag = "!!int" - floatTag = "!!float" - timestampTag = "!!timestamp" - seqTag = "!!seq" - mapTag = "!!map" - binaryTag = "!!binary" - mergeTag = "!!merge" -) - -var longTags = make(map[string]string) -var shortTags = make(map[string]string) - -func init() { - for _, stag := range []string{nullTag, boolTag, strTag, intTag, floatTag, timestampTag, seqTag, mapTag, binaryTag, mergeTag} { - ltag := longTag(stag) - longTags[stag] = ltag - shortTags[ltag] = stag - } -} - -const longTagPrefix = "tag:yaml.org,2002:" - -func shortTag(tag string) string { - if strings.HasPrefix(tag, longTagPrefix) { - if stag, ok := shortTags[tag]; ok { - return stag - } - return "!!" + tag[len(longTagPrefix):] - } - return tag -} - -func longTag(tag string) string { - if strings.HasPrefix(tag, "!!") { - if ltag, ok := longTags[tag]; ok { - return ltag - } - return longTagPrefix + tag[2:] - } - return tag -} - -func resolvableTag(tag string) bool { - switch tag { - case "", strTag, boolTag, intTag, floatTag, nullTag, timestampTag: - return true - } - return false -} - -var yamlStyleFloat = regexp.MustCompile(`^[-+]?(\.[0-9]+|[0-9]+(\.[0-9]*)?)([eE][-+]?[0-9]+)?$`) - -func resolve(tag string, in string) (rtag string, out interface{}) { - tag = shortTag(tag) - if !resolvableTag(tag) { - return tag, in - } - - defer func() { - switch tag { - case "", rtag, strTag, binaryTag: - return - case floatTag: - if rtag == intTag { - switch v := out.(type) { - case int64: - rtag = floatTag - out = float64(v) - return - case int: - rtag = floatTag - out = float64(v) - return - } - } - } - failf("cannot decode %s `%s` as a %s", shortTag(rtag), in, shortTag(tag)) - }() - - // Any data is accepted as a !!str or !!binary. - // Otherwise, the prefix is enough of a hint about what it might be. - hint := byte('N') - if in != "" { - hint = resolveTable[in[0]] - } - if hint != 0 && tag != strTag && tag != binaryTag { - // Handle things we can lookup in a map. - if item, ok := resolveMap[in]; ok { - return item.tag, item.value - } - - // Base 60 floats are a bad idea, were dropped in YAML 1.2, and - // are purposefully unsupported here. They're still quoted on - // the way out for compatibility with other parser, though. - - switch hint { - case 'M': - // We've already checked the map above. - - case '.': - // Not in the map, so maybe a normal float. - floatv, err := strconv.ParseFloat(in, 64) - if err == nil { - return floatTag, floatv - } - - case 'D', 'S': - // Int, float, or timestamp. - // Only try values as a timestamp if the value is unquoted or there's an explicit - // !!timestamp tag. - if tag == "" || tag == timestampTag { - t, ok := parseTimestamp(in) - if ok { - return timestampTag, t - } - } - - plain := strings.Replace(in, "_", "", -1) - intv, err := strconv.ParseInt(plain, 0, 64) - if err == nil { - if intv == int64(int(intv)) { - return intTag, int(intv) - } else { - return intTag, intv - } - } - uintv, err := strconv.ParseUint(plain, 0, 64) - if err == nil { - return intTag, uintv - } - if yamlStyleFloat.MatchString(plain) { - floatv, err := strconv.ParseFloat(plain, 64) - if err == nil { - return floatTag, floatv - } - } - if strings.HasPrefix(plain, "0b") { - intv, err := strconv.ParseInt(plain[2:], 2, 64) - if err == nil { - if intv == int64(int(intv)) { - return intTag, int(intv) - } else { - return intTag, intv - } - } - uintv, err := strconv.ParseUint(plain[2:], 2, 64) - if err == nil { - return intTag, uintv - } - } else if strings.HasPrefix(plain, "-0b") { - intv, err := strconv.ParseInt("-"+plain[3:], 2, 64) - if err == nil { - if true || intv == int64(int(intv)) { - return intTag, int(intv) - } else { - return intTag, intv - } - } - } - // Octals as introduced in version 1.2 of the spec. - // Octals from the 1.1 spec, spelled as 0777, are still - // decoded by default in v3 as well for compatibility. - // May be dropped in v4 depending on how usage evolves. - if strings.HasPrefix(plain, "0o") { - intv, err := strconv.ParseInt(plain[2:], 8, 64) - if err == nil { - if intv == int64(int(intv)) { - return intTag, int(intv) - } else { - return intTag, intv - } - } - uintv, err := strconv.ParseUint(plain[2:], 8, 64) - if err == nil { - return intTag, uintv - } - } else if strings.HasPrefix(plain, "-0o") { - intv, err := strconv.ParseInt("-"+plain[3:], 8, 64) - if err == nil { - if true || intv == int64(int(intv)) { - return intTag, int(intv) - } else { - return intTag, intv - } - } - } - default: - panic("internal error: missing handler for resolver table: " + string(rune(hint)) + " (with " + in + ")") - } - } - return strTag, in -} - -// encodeBase64 encodes s as base64 that is broken up into multiple lines -// as appropriate for the resulting length. -func encodeBase64(s string) string { - const lineLen = 70 - encLen := base64.StdEncoding.EncodedLen(len(s)) - lines := encLen/lineLen + 1 - buf := make([]byte, encLen*2+lines) - in := buf[0:encLen] - out := buf[encLen:] - base64.StdEncoding.Encode(in, []byte(s)) - k := 0 - for i := 0; i < len(in); i += lineLen { - j := i + lineLen - if j > len(in) { - j = len(in) - } - k += copy(out[k:], in[i:j]) - if lines > 1 { - out[k] = '\n' - k++ - } - } - return string(out[:k]) -} - -// This is a subset of the formats allowed by the regular expression -// defined at http://yaml.org/type/timestamp.html. -var allowedTimestampFormats = []string{ - "2006-1-2T15:4:5.999999999Z07:00", // RCF3339Nano with short date fields. - "2006-1-2t15:4:5.999999999Z07:00", // RFC3339Nano with short date fields and lower-case "t". - "2006-1-2 15:4:5.999999999", // space separated with no time zone - "2006-1-2", // date only - // Notable exception: time.Parse cannot handle: "2001-12-14 21:59:43.10 -5" - // from the set of examples. -} - -// parseTimestamp parses s as a timestamp string and -// returns the timestamp and reports whether it succeeded. -// Timestamp formats are defined at http://yaml.org/type/timestamp.html -func parseTimestamp(s string) (time.Time, bool) { - // TODO write code to check all the formats supported by - // http://yaml.org/type/timestamp.html instead of using time.Parse. - - // Quick check: all date formats start with YYYY-. - i := 0 - for ; i < len(s); i++ { - if c := s[i]; c < '0' || c > '9' { - break - } - } - if i != 4 || i == len(s) || s[i] != '-' { - return time.Time{}, false - } - for _, format := range allowedTimestampFormats { - if t, err := time.Parse(format, s); err == nil { - return t, true - } - } - return time.Time{}, false -} diff --git a/trunk/3rdparty/srs-bench/vendor/gopkg.in/yaml.v3/scannerc.go b/trunk/3rdparty/srs-bench/vendor/gopkg.in/yaml.v3/scannerc.go deleted file mode 100644 index ca0070108..000000000 --- a/trunk/3rdparty/srs-bench/vendor/gopkg.in/yaml.v3/scannerc.go +++ /dev/null @@ -1,3038 +0,0 @@ -// -// Copyright (c) 2011-2019 Canonical Ltd -// Copyright (c) 2006-2010 Kirill Simonov -// -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -// of the Software, and to permit persons to whom the Software is furnished to do -// so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -package yaml - -import ( - "bytes" - "fmt" -) - -// Introduction -// ************ -// -// The following notes assume that you are familiar with the YAML specification -// (http://yaml.org/spec/1.2/spec.html). We mostly follow it, although in -// some cases we are less restrictive that it requires. -// -// The process of transforming a YAML stream into a sequence of events is -// divided on two steps: Scanning and Parsing. -// -// The Scanner transforms the input stream into a sequence of tokens, while the -// parser transform the sequence of tokens produced by the Scanner into a -// sequence of parsing events. -// -// The Scanner is rather clever and complicated. The Parser, on the contrary, -// is a straightforward implementation of a recursive-descendant parser (or, -// LL(1) parser, as it is usually called). -// -// Actually there are two issues of Scanning that might be called "clever", the -// rest is quite straightforward. The issues are "block collection start" and -// "simple keys". Both issues are explained below in details. -// -// Here the Scanning step is explained and implemented. We start with the list -// of all the tokens produced by the Scanner together with short descriptions. -// -// Now, tokens: -// -// STREAM-START(encoding) # The stream start. -// STREAM-END # The stream end. -// VERSION-DIRECTIVE(major,minor) # The '%YAML' directive. -// TAG-DIRECTIVE(handle,prefix) # The '%TAG' directive. -// DOCUMENT-START # '---' -// DOCUMENT-END # '...' -// BLOCK-SEQUENCE-START # Indentation increase denoting a block -// BLOCK-MAPPING-START # sequence or a block mapping. -// BLOCK-END # Indentation decrease. -// FLOW-SEQUENCE-START # '[' -// FLOW-SEQUENCE-END # ']' -// BLOCK-SEQUENCE-START # '{' -// BLOCK-SEQUENCE-END # '}' -// BLOCK-ENTRY # '-' -// FLOW-ENTRY # ',' -// KEY # '?' or nothing (simple keys). -// VALUE # ':' -// ALIAS(anchor) # '*anchor' -// ANCHOR(anchor) # '&anchor' -// TAG(handle,suffix) # '!handle!suffix' -// SCALAR(value,style) # A scalar. -// -// The following two tokens are "virtual" tokens denoting the beginning and the -// end of the stream: -// -// STREAM-START(encoding) -// STREAM-END -// -// We pass the information about the input stream encoding with the -// STREAM-START token. -// -// The next two tokens are responsible for tags: -// -// VERSION-DIRECTIVE(major,minor) -// TAG-DIRECTIVE(handle,prefix) -// -// Example: -// -// %YAML 1.1 -// %TAG ! !foo -// %TAG !yaml! tag:yaml.org,2002: -// --- -// -// The correspoding sequence of tokens: -// -// STREAM-START(utf-8) -// VERSION-DIRECTIVE(1,1) -// TAG-DIRECTIVE("!","!foo") -// TAG-DIRECTIVE("!yaml","tag:yaml.org,2002:") -// DOCUMENT-START -// STREAM-END -// -// Note that the VERSION-DIRECTIVE and TAG-DIRECTIVE tokens occupy a whole -// line. -// -// The document start and end indicators are represented by: -// -// DOCUMENT-START -// DOCUMENT-END -// -// Note that if a YAML stream contains an implicit document (without '---' -// and '...' indicators), no DOCUMENT-START and DOCUMENT-END tokens will be -// produced. -// -// In the following examples, we present whole documents together with the -// produced tokens. -// -// 1. An implicit document: -// -// 'a scalar' -// -// Tokens: -// -// STREAM-START(utf-8) -// SCALAR("a scalar",single-quoted) -// STREAM-END -// -// 2. An explicit document: -// -// --- -// 'a scalar' -// ... -// -// Tokens: -// -// STREAM-START(utf-8) -// DOCUMENT-START -// SCALAR("a scalar",single-quoted) -// DOCUMENT-END -// STREAM-END -// -// 3. Several documents in a stream: -// -// 'a scalar' -// --- -// 'another scalar' -// --- -// 'yet another scalar' -// -// Tokens: -// -// STREAM-START(utf-8) -// SCALAR("a scalar",single-quoted) -// DOCUMENT-START -// SCALAR("another scalar",single-quoted) -// DOCUMENT-START -// SCALAR("yet another scalar",single-quoted) -// STREAM-END -// -// We have already introduced the SCALAR token above. The following tokens are -// used to describe aliases, anchors, tag, and scalars: -// -// ALIAS(anchor) -// ANCHOR(anchor) -// TAG(handle,suffix) -// SCALAR(value,style) -// -// The following series of examples illustrate the usage of these tokens: -// -// 1. A recursive sequence: -// -// &A [ *A ] -// -// Tokens: -// -// STREAM-START(utf-8) -// ANCHOR("A") -// FLOW-SEQUENCE-START -// ALIAS("A") -// FLOW-SEQUENCE-END -// STREAM-END -// -// 2. A tagged scalar: -// -// !!float "3.14" # A good approximation. -// -// Tokens: -// -// STREAM-START(utf-8) -// TAG("!!","float") -// SCALAR("3.14",double-quoted) -// STREAM-END -// -// 3. Various scalar styles: -// -// --- # Implicit empty plain scalars do not produce tokens. -// --- a plain scalar -// --- 'a single-quoted scalar' -// --- "a double-quoted scalar" -// --- |- -// a literal scalar -// --- >- -// a folded -// scalar -// -// Tokens: -// -// STREAM-START(utf-8) -// DOCUMENT-START -// DOCUMENT-START -// SCALAR("a plain scalar",plain) -// DOCUMENT-START -// SCALAR("a single-quoted scalar",single-quoted) -// DOCUMENT-START -// SCALAR("a double-quoted scalar",double-quoted) -// DOCUMENT-START -// SCALAR("a literal scalar",literal) -// DOCUMENT-START -// SCALAR("a folded scalar",folded) -// STREAM-END -// -// Now it's time to review collection-related tokens. We will start with -// flow collections: -// -// FLOW-SEQUENCE-START -// FLOW-SEQUENCE-END -// FLOW-MAPPING-START -// FLOW-MAPPING-END -// FLOW-ENTRY -// KEY -// VALUE -// -// The tokens FLOW-SEQUENCE-START, FLOW-SEQUENCE-END, FLOW-MAPPING-START, and -// FLOW-MAPPING-END represent the indicators '[', ']', '{', and '}' -// correspondingly. FLOW-ENTRY represent the ',' indicator. Finally the -// indicators '?' and ':', which are used for denoting mapping keys and values, -// are represented by the KEY and VALUE tokens. -// -// The following examples show flow collections: -// -// 1. A flow sequence: -// -// [item 1, item 2, item 3] -// -// Tokens: -// -// STREAM-START(utf-8) -// FLOW-SEQUENCE-START -// SCALAR("item 1",plain) -// FLOW-ENTRY -// SCALAR("item 2",plain) -// FLOW-ENTRY -// SCALAR("item 3",plain) -// FLOW-SEQUENCE-END -// STREAM-END -// -// 2. A flow mapping: -// -// { -// a simple key: a value, # Note that the KEY token is produced. -// ? a complex key: another value, -// } -// -// Tokens: -// -// STREAM-START(utf-8) -// FLOW-MAPPING-START -// KEY -// SCALAR("a simple key",plain) -// VALUE -// SCALAR("a value",plain) -// FLOW-ENTRY -// KEY -// SCALAR("a complex key",plain) -// VALUE -// SCALAR("another value",plain) -// FLOW-ENTRY -// FLOW-MAPPING-END -// STREAM-END -// -// A simple key is a key which is not denoted by the '?' indicator. Note that -// the Scanner still produce the KEY token whenever it encounters a simple key. -// -// For scanning block collections, the following tokens are used (note that we -// repeat KEY and VALUE here): -// -// BLOCK-SEQUENCE-START -// BLOCK-MAPPING-START -// BLOCK-END -// BLOCK-ENTRY -// KEY -// VALUE -// -// The tokens BLOCK-SEQUENCE-START and BLOCK-MAPPING-START denote indentation -// increase that precedes a block collection (cf. the INDENT token in Python). -// The token BLOCK-END denote indentation decrease that ends a block collection -// (cf. the DEDENT token in Python). However YAML has some syntax pecularities -// that makes detections of these tokens more complex. -// -// The tokens BLOCK-ENTRY, KEY, and VALUE are used to represent the indicators -// '-', '?', and ':' correspondingly. -// -// The following examples show how the tokens BLOCK-SEQUENCE-START, -// BLOCK-MAPPING-START, and BLOCK-END are emitted by the Scanner: -// -// 1. Block sequences: -// -// - item 1 -// - item 2 -// - -// - item 3.1 -// - item 3.2 -// - -// key 1: value 1 -// key 2: value 2 -// -// Tokens: -// -// STREAM-START(utf-8) -// BLOCK-SEQUENCE-START -// BLOCK-ENTRY -// SCALAR("item 1",plain) -// BLOCK-ENTRY -// SCALAR("item 2",plain) -// BLOCK-ENTRY -// BLOCK-SEQUENCE-START -// BLOCK-ENTRY -// SCALAR("item 3.1",plain) -// BLOCK-ENTRY -// SCALAR("item 3.2",plain) -// BLOCK-END -// BLOCK-ENTRY -// BLOCK-MAPPING-START -// KEY -// SCALAR("key 1",plain) -// VALUE -// SCALAR("value 1",plain) -// KEY -// SCALAR("key 2",plain) -// VALUE -// SCALAR("value 2",plain) -// BLOCK-END -// BLOCK-END -// STREAM-END -// -// 2. Block mappings: -// -// a simple key: a value # The KEY token is produced here. -// ? a complex key -// : another value -// a mapping: -// key 1: value 1 -// key 2: value 2 -// a sequence: -// - item 1 -// - item 2 -// -// Tokens: -// -// STREAM-START(utf-8) -// BLOCK-MAPPING-START -// KEY -// SCALAR("a simple key",plain) -// VALUE -// SCALAR("a value",plain) -// KEY -// SCALAR("a complex key",plain) -// VALUE -// SCALAR("another value",plain) -// KEY -// SCALAR("a mapping",plain) -// BLOCK-MAPPING-START -// KEY -// SCALAR("key 1",plain) -// VALUE -// SCALAR("value 1",plain) -// KEY -// SCALAR("key 2",plain) -// VALUE -// SCALAR("value 2",plain) -// BLOCK-END -// KEY -// SCALAR("a sequence",plain) -// VALUE -// BLOCK-SEQUENCE-START -// BLOCK-ENTRY -// SCALAR("item 1",plain) -// BLOCK-ENTRY -// SCALAR("item 2",plain) -// BLOCK-END -// BLOCK-END -// STREAM-END -// -// YAML does not always require to start a new block collection from a new -// line. If the current line contains only '-', '?', and ':' indicators, a new -// block collection may start at the current line. The following examples -// illustrate this case: -// -// 1. Collections in a sequence: -// -// - - item 1 -// - item 2 -// - key 1: value 1 -// key 2: value 2 -// - ? complex key -// : complex value -// -// Tokens: -// -// STREAM-START(utf-8) -// BLOCK-SEQUENCE-START -// BLOCK-ENTRY -// BLOCK-SEQUENCE-START -// BLOCK-ENTRY -// SCALAR("item 1",plain) -// BLOCK-ENTRY -// SCALAR("item 2",plain) -// BLOCK-END -// BLOCK-ENTRY -// BLOCK-MAPPING-START -// KEY -// SCALAR("key 1",plain) -// VALUE -// SCALAR("value 1",plain) -// KEY -// SCALAR("key 2",plain) -// VALUE -// SCALAR("value 2",plain) -// BLOCK-END -// BLOCK-ENTRY -// BLOCK-MAPPING-START -// KEY -// SCALAR("complex key") -// VALUE -// SCALAR("complex value") -// BLOCK-END -// BLOCK-END -// STREAM-END -// -// 2. Collections in a mapping: -// -// ? a sequence -// : - item 1 -// - item 2 -// ? a mapping -// : key 1: value 1 -// key 2: value 2 -// -// Tokens: -// -// STREAM-START(utf-8) -// BLOCK-MAPPING-START -// KEY -// SCALAR("a sequence",plain) -// VALUE -// BLOCK-SEQUENCE-START -// BLOCK-ENTRY -// SCALAR("item 1",plain) -// BLOCK-ENTRY -// SCALAR("item 2",plain) -// BLOCK-END -// KEY -// SCALAR("a mapping",plain) -// VALUE -// BLOCK-MAPPING-START -// KEY -// SCALAR("key 1",plain) -// VALUE -// SCALAR("value 1",plain) -// KEY -// SCALAR("key 2",plain) -// VALUE -// SCALAR("value 2",plain) -// BLOCK-END -// BLOCK-END -// STREAM-END -// -// YAML also permits non-indented sequences if they are included into a block -// mapping. In this case, the token BLOCK-SEQUENCE-START is not produced: -// -// key: -// - item 1 # BLOCK-SEQUENCE-START is NOT produced here. -// - item 2 -// -// Tokens: -// -// STREAM-START(utf-8) -// BLOCK-MAPPING-START -// KEY -// SCALAR("key",plain) -// VALUE -// BLOCK-ENTRY -// SCALAR("item 1",plain) -// BLOCK-ENTRY -// SCALAR("item 2",plain) -// BLOCK-END -// - -// Ensure that the buffer contains the required number of characters. -// Return true on success, false on failure (reader error or memory error). -func cache(parser *yaml_parser_t, length int) bool { - // [Go] This was inlined: !cache(A, B) -> unread < B && !update(A, B) - return parser.unread >= length || yaml_parser_update_buffer(parser, length) -} - -// Advance the buffer pointer. -func skip(parser *yaml_parser_t) { - if !is_blank(parser.buffer, parser.buffer_pos) { - parser.newlines = 0 - } - parser.mark.index++ - parser.mark.column++ - parser.unread-- - parser.buffer_pos += width(parser.buffer[parser.buffer_pos]) -} - -func skip_line(parser *yaml_parser_t) { - if is_crlf(parser.buffer, parser.buffer_pos) { - parser.mark.index += 2 - parser.mark.column = 0 - parser.mark.line++ - parser.unread -= 2 - parser.buffer_pos += 2 - parser.newlines++ - } else if is_break(parser.buffer, parser.buffer_pos) { - parser.mark.index++ - parser.mark.column = 0 - parser.mark.line++ - parser.unread-- - parser.buffer_pos += width(parser.buffer[parser.buffer_pos]) - parser.newlines++ - } -} - -// Copy a character to a string buffer and advance pointers. -func read(parser *yaml_parser_t, s []byte) []byte { - if !is_blank(parser.buffer, parser.buffer_pos) { - parser.newlines = 0 - } - w := width(parser.buffer[parser.buffer_pos]) - if w == 0 { - panic("invalid character sequence") - } - if len(s) == 0 { - s = make([]byte, 0, 32) - } - if w == 1 && len(s)+w <= cap(s) { - s = s[:len(s)+1] - s[len(s)-1] = parser.buffer[parser.buffer_pos] - parser.buffer_pos++ - } else { - s = append(s, parser.buffer[parser.buffer_pos:parser.buffer_pos+w]...) - parser.buffer_pos += w - } - parser.mark.index++ - parser.mark.column++ - parser.unread-- - return s -} - -// Copy a line break character to a string buffer and advance pointers. -func read_line(parser *yaml_parser_t, s []byte) []byte { - buf := parser.buffer - pos := parser.buffer_pos - switch { - case buf[pos] == '\r' && buf[pos+1] == '\n': - // CR LF . LF - s = append(s, '\n') - parser.buffer_pos += 2 - parser.mark.index++ - parser.unread-- - case buf[pos] == '\r' || buf[pos] == '\n': - // CR|LF . LF - s = append(s, '\n') - parser.buffer_pos += 1 - case buf[pos] == '\xC2' && buf[pos+1] == '\x85': - // NEL . LF - s = append(s, '\n') - parser.buffer_pos += 2 - case buf[pos] == '\xE2' && buf[pos+1] == '\x80' && (buf[pos+2] == '\xA8' || buf[pos+2] == '\xA9'): - // LS|PS . LS|PS - s = append(s, buf[parser.buffer_pos:pos+3]...) - parser.buffer_pos += 3 - default: - return s - } - parser.mark.index++ - parser.mark.column = 0 - parser.mark.line++ - parser.unread-- - parser.newlines++ - return s -} - -// Get the next token. -func yaml_parser_scan(parser *yaml_parser_t, token *yaml_token_t) bool { - // Erase the token object. - *token = yaml_token_t{} // [Go] Is this necessary? - - // No tokens after STREAM-END or error. - if parser.stream_end_produced || parser.error != yaml_NO_ERROR { - return true - } - - // Ensure that the tokens queue contains enough tokens. - if !parser.token_available { - if !yaml_parser_fetch_more_tokens(parser) { - return false - } - } - - // Fetch the next token from the queue. - *token = parser.tokens[parser.tokens_head] - parser.tokens_head++ - parser.tokens_parsed++ - parser.token_available = false - - if token.typ == yaml_STREAM_END_TOKEN { - parser.stream_end_produced = true - } - return true -} - -// Set the scanner error and return false. -func yaml_parser_set_scanner_error(parser *yaml_parser_t, context string, context_mark yaml_mark_t, problem string) bool { - parser.error = yaml_SCANNER_ERROR - parser.context = context - parser.context_mark = context_mark - parser.problem = problem - parser.problem_mark = parser.mark - return false -} - -func yaml_parser_set_scanner_tag_error(parser *yaml_parser_t, directive bool, context_mark yaml_mark_t, problem string) bool { - context := "while parsing a tag" - if directive { - context = "while parsing a %TAG directive" - } - return yaml_parser_set_scanner_error(parser, context, context_mark, problem) -} - -func trace(args ...interface{}) func() { - pargs := append([]interface{}{"+++"}, args...) - fmt.Println(pargs...) - pargs = append([]interface{}{"---"}, args...) - return func() { fmt.Println(pargs...) } -} - -// Ensure that the tokens queue contains at least one token which can be -// returned to the Parser. -func yaml_parser_fetch_more_tokens(parser *yaml_parser_t) bool { - // While we need more tokens to fetch, do it. - for { - // [Go] The comment parsing logic requires a lookahead of two tokens - // so that foot comments may be parsed in time of associating them - // with the tokens that are parsed before them, and also for line - // comments to be transformed into head comments in some edge cases. - if parser.tokens_head < len(parser.tokens)-2 { - // If a potential simple key is at the head position, we need to fetch - // the next token to disambiguate it. - head_tok_idx, ok := parser.simple_keys_by_tok[parser.tokens_parsed] - if !ok { - break - } else if valid, ok := yaml_simple_key_is_valid(parser, &parser.simple_keys[head_tok_idx]); !ok { - return false - } else if !valid { - break - } - } - // Fetch the next token. - if !yaml_parser_fetch_next_token(parser) { - return false - } - } - - parser.token_available = true - return true -} - -// The dispatcher for token fetchers. -func yaml_parser_fetch_next_token(parser *yaml_parser_t) (ok bool) { - // Ensure that the buffer is initialized. - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - - // Check if we just started scanning. Fetch STREAM-START then. - if !parser.stream_start_produced { - return yaml_parser_fetch_stream_start(parser) - } - - scan_mark := parser.mark - - // Eat whitespaces and comments until we reach the next token. - if !yaml_parser_scan_to_next_token(parser) { - return false - } - - // [Go] While unrolling indents, transform the head comments of prior - // indentation levels observed after scan_start into foot comments at - // the respective indexes. - - // Check the indentation level against the current column. - if !yaml_parser_unroll_indent(parser, parser.mark.column, scan_mark) { - return false - } - - // Ensure that the buffer contains at least 4 characters. 4 is the length - // of the longest indicators ('--- ' and '... '). - if parser.unread < 4 && !yaml_parser_update_buffer(parser, 4) { - return false - } - - // Is it the end of the stream? - if is_z(parser.buffer, parser.buffer_pos) { - return yaml_parser_fetch_stream_end(parser) - } - - // Is it a directive? - if parser.mark.column == 0 && parser.buffer[parser.buffer_pos] == '%' { - return yaml_parser_fetch_directive(parser) - } - - buf := parser.buffer - pos := parser.buffer_pos - - // Is it the document start indicator? - if parser.mark.column == 0 && buf[pos] == '-' && buf[pos+1] == '-' && buf[pos+2] == '-' && is_blankz(buf, pos+3) { - return yaml_parser_fetch_document_indicator(parser, yaml_DOCUMENT_START_TOKEN) - } - - // Is it the document end indicator? - if parser.mark.column == 0 && buf[pos] == '.' && buf[pos+1] == '.' && buf[pos+2] == '.' && is_blankz(buf, pos+3) { - return yaml_parser_fetch_document_indicator(parser, yaml_DOCUMENT_END_TOKEN) - } - - comment_mark := parser.mark - if len(parser.tokens) > 0 && (parser.flow_level == 0 && buf[pos] == ':' || parser.flow_level > 0 && buf[pos] == ',') { - // Associate any following comments with the prior token. - comment_mark = parser.tokens[len(parser.tokens)-1].start_mark - } - defer func() { - if !ok { - return - } - if len(parser.tokens) > 0 && parser.tokens[len(parser.tokens)-1].typ == yaml_BLOCK_ENTRY_TOKEN { - // Sequence indicators alone have no line comments. It becomes - // a head comment for whatever follows. - return - } - if !yaml_parser_scan_line_comment(parser, comment_mark) { - ok = false - return - } - }() - - // Is it the flow sequence start indicator? - if buf[pos] == '[' { - return yaml_parser_fetch_flow_collection_start(parser, yaml_FLOW_SEQUENCE_START_TOKEN) - } - - // Is it the flow mapping start indicator? - if parser.buffer[parser.buffer_pos] == '{' { - return yaml_parser_fetch_flow_collection_start(parser, yaml_FLOW_MAPPING_START_TOKEN) - } - - // Is it the flow sequence end indicator? - if parser.buffer[parser.buffer_pos] == ']' { - return yaml_parser_fetch_flow_collection_end(parser, - yaml_FLOW_SEQUENCE_END_TOKEN) - } - - // Is it the flow mapping end indicator? - if parser.buffer[parser.buffer_pos] == '}' { - return yaml_parser_fetch_flow_collection_end(parser, - yaml_FLOW_MAPPING_END_TOKEN) - } - - // Is it the flow entry indicator? - if parser.buffer[parser.buffer_pos] == ',' { - return yaml_parser_fetch_flow_entry(parser) - } - - // Is it the block entry indicator? - if parser.buffer[parser.buffer_pos] == '-' && is_blankz(parser.buffer, parser.buffer_pos+1) { - return yaml_parser_fetch_block_entry(parser) - } - - // Is it the key indicator? - if parser.buffer[parser.buffer_pos] == '?' && (parser.flow_level > 0 || is_blankz(parser.buffer, parser.buffer_pos+1)) { - return yaml_parser_fetch_key(parser) - } - - // Is it the value indicator? - if parser.buffer[parser.buffer_pos] == ':' && (parser.flow_level > 0 || is_blankz(parser.buffer, parser.buffer_pos+1)) { - return yaml_parser_fetch_value(parser) - } - - // Is it an alias? - if parser.buffer[parser.buffer_pos] == '*' { - return yaml_parser_fetch_anchor(parser, yaml_ALIAS_TOKEN) - } - - // Is it an anchor? - if parser.buffer[parser.buffer_pos] == '&' { - return yaml_parser_fetch_anchor(parser, yaml_ANCHOR_TOKEN) - } - - // Is it a tag? - if parser.buffer[parser.buffer_pos] == '!' { - return yaml_parser_fetch_tag(parser) - } - - // Is it a literal scalar? - if parser.buffer[parser.buffer_pos] == '|' && parser.flow_level == 0 { - return yaml_parser_fetch_block_scalar(parser, true) - } - - // Is it a folded scalar? - if parser.buffer[parser.buffer_pos] == '>' && parser.flow_level == 0 { - return yaml_parser_fetch_block_scalar(parser, false) - } - - // Is it a single-quoted scalar? - if parser.buffer[parser.buffer_pos] == '\'' { - return yaml_parser_fetch_flow_scalar(parser, true) - } - - // Is it a double-quoted scalar? - if parser.buffer[parser.buffer_pos] == '"' { - return yaml_parser_fetch_flow_scalar(parser, false) - } - - // Is it a plain scalar? - // - // A plain scalar may start with any non-blank characters except - // - // '-', '?', ':', ',', '[', ']', '{', '}', - // '#', '&', '*', '!', '|', '>', '\'', '\"', - // '%', '@', '`'. - // - // In the block context (and, for the '-' indicator, in the flow context - // too), it may also start with the characters - // - // '-', '?', ':' - // - // if it is followed by a non-space character. - // - // The last rule is more restrictive than the specification requires. - // [Go] TODO Make this logic more reasonable. - //switch parser.buffer[parser.buffer_pos] { - //case '-', '?', ':', ',', '?', '-', ',', ':', ']', '[', '}', '{', '&', '#', '!', '*', '>', '|', '"', '\'', '@', '%', '-', '`': - //} - if !(is_blankz(parser.buffer, parser.buffer_pos) || parser.buffer[parser.buffer_pos] == '-' || - parser.buffer[parser.buffer_pos] == '?' || parser.buffer[parser.buffer_pos] == ':' || - parser.buffer[parser.buffer_pos] == ',' || parser.buffer[parser.buffer_pos] == '[' || - parser.buffer[parser.buffer_pos] == ']' || parser.buffer[parser.buffer_pos] == '{' || - parser.buffer[parser.buffer_pos] == '}' || parser.buffer[parser.buffer_pos] == '#' || - parser.buffer[parser.buffer_pos] == '&' || parser.buffer[parser.buffer_pos] == '*' || - parser.buffer[parser.buffer_pos] == '!' || parser.buffer[parser.buffer_pos] == '|' || - parser.buffer[parser.buffer_pos] == '>' || parser.buffer[parser.buffer_pos] == '\'' || - parser.buffer[parser.buffer_pos] == '"' || parser.buffer[parser.buffer_pos] == '%' || - parser.buffer[parser.buffer_pos] == '@' || parser.buffer[parser.buffer_pos] == '`') || - (parser.buffer[parser.buffer_pos] == '-' && !is_blank(parser.buffer, parser.buffer_pos+1)) || - (parser.flow_level == 0 && - (parser.buffer[parser.buffer_pos] == '?' || parser.buffer[parser.buffer_pos] == ':') && - !is_blankz(parser.buffer, parser.buffer_pos+1)) { - return yaml_parser_fetch_plain_scalar(parser) - } - - // If we don't determine the token type so far, it is an error. - return yaml_parser_set_scanner_error(parser, - "while scanning for the next token", parser.mark, - "found character that cannot start any token") -} - -func yaml_simple_key_is_valid(parser *yaml_parser_t, simple_key *yaml_simple_key_t) (valid, ok bool) { - if !simple_key.possible { - return false, true - } - - // The 1.2 specification says: - // - // "If the ? indicator is omitted, parsing needs to see past the - // implicit key to recognize it as such. To limit the amount of - // lookahead required, the “:” indicator must appear at most 1024 - // Unicode characters beyond the start of the key. In addition, the key - // is restricted to a single line." - // - if simple_key.mark.line < parser.mark.line || simple_key.mark.index+1024 < parser.mark.index { - // Check if the potential simple key to be removed is required. - if simple_key.required { - return false, yaml_parser_set_scanner_error(parser, - "while scanning a simple key", simple_key.mark, - "could not find expected ':'") - } - simple_key.possible = false - return false, true - } - return true, true -} - -// Check if a simple key may start at the current position and add it if -// needed. -func yaml_parser_save_simple_key(parser *yaml_parser_t) bool { - // A simple key is required at the current position if the scanner is in - // the block context and the current column coincides with the indentation - // level. - - required := parser.flow_level == 0 && parser.indent == parser.mark.column - - // - // If the current position may start a simple key, save it. - // - if parser.simple_key_allowed { - simple_key := yaml_simple_key_t{ - possible: true, - required: required, - token_number: parser.tokens_parsed + (len(parser.tokens) - parser.tokens_head), - mark: parser.mark, - } - - if !yaml_parser_remove_simple_key(parser) { - return false - } - parser.simple_keys[len(parser.simple_keys)-1] = simple_key - parser.simple_keys_by_tok[simple_key.token_number] = len(parser.simple_keys) - 1 - } - return true -} - -// Remove a potential simple key at the current flow level. -func yaml_parser_remove_simple_key(parser *yaml_parser_t) bool { - i := len(parser.simple_keys) - 1 - if parser.simple_keys[i].possible { - // If the key is required, it is an error. - if parser.simple_keys[i].required { - return yaml_parser_set_scanner_error(parser, - "while scanning a simple key", parser.simple_keys[i].mark, - "could not find expected ':'") - } - // Remove the key from the stack. - parser.simple_keys[i].possible = false - delete(parser.simple_keys_by_tok, parser.simple_keys[i].token_number) - } - return true -} - -// max_flow_level limits the flow_level -const max_flow_level = 10000 - -// Increase the flow level and resize the simple key list if needed. -func yaml_parser_increase_flow_level(parser *yaml_parser_t) bool { - // Reset the simple key on the next level. - parser.simple_keys = append(parser.simple_keys, yaml_simple_key_t{ - possible: false, - required: false, - token_number: parser.tokens_parsed + (len(parser.tokens) - parser.tokens_head), - mark: parser.mark, - }) - - // Increase the flow level. - parser.flow_level++ - if parser.flow_level > max_flow_level { - return yaml_parser_set_scanner_error(parser, - "while increasing flow level", parser.simple_keys[len(parser.simple_keys)-1].mark, - fmt.Sprintf("exceeded max depth of %d", max_flow_level)) - } - return true -} - -// Decrease the flow level. -func yaml_parser_decrease_flow_level(parser *yaml_parser_t) bool { - if parser.flow_level > 0 { - parser.flow_level-- - last := len(parser.simple_keys) - 1 - delete(parser.simple_keys_by_tok, parser.simple_keys[last].token_number) - parser.simple_keys = parser.simple_keys[:last] - } - return true -} - -// max_indents limits the indents stack size -const max_indents = 10000 - -// Push the current indentation level to the stack and set the new level -// the current column is greater than the indentation level. In this case, -// append or insert the specified token into the token queue. -func yaml_parser_roll_indent(parser *yaml_parser_t, column, number int, typ yaml_token_type_t, mark yaml_mark_t) bool { - // In the flow context, do nothing. - if parser.flow_level > 0 { - return true - } - - if parser.indent < column { - // Push the current indentation level to the stack and set the new - // indentation level. - parser.indents = append(parser.indents, parser.indent) - parser.indent = column - if len(parser.indents) > max_indents { - return yaml_parser_set_scanner_error(parser, - "while increasing indent level", parser.simple_keys[len(parser.simple_keys)-1].mark, - fmt.Sprintf("exceeded max depth of %d", max_indents)) - } - - // Create a token and insert it into the queue. - token := yaml_token_t{ - typ: typ, - start_mark: mark, - end_mark: mark, - } - if number > -1 { - number -= parser.tokens_parsed - } - yaml_insert_token(parser, number, &token) - } - return true -} - -// Pop indentation levels from the indents stack until the current level -// becomes less or equal to the column. For each indentation level, append -// the BLOCK-END token. -func yaml_parser_unroll_indent(parser *yaml_parser_t, column int, scan_mark yaml_mark_t) bool { - // In the flow context, do nothing. - if parser.flow_level > 0 { - return true - } - - block_mark := scan_mark - block_mark.index-- - - // Loop through the indentation levels in the stack. - for parser.indent > column { - - // [Go] Reposition the end token before potential following - // foot comments of parent blocks. For that, search - // backwards for recent comments that were at the same - // indent as the block that is ending now. - stop_index := block_mark.index - for i := len(parser.comments) - 1; i >= 0; i-- { - comment := &parser.comments[i] - - if comment.end_mark.index < stop_index { - // Don't go back beyond the start of the comment/whitespace scan, unless column < 0. - // If requested indent column is < 0, then the document is over and everything else - // is a foot anyway. - break - } - if comment.start_mark.column == parser.indent+1 { - // This is a good match. But maybe there's a former comment - // at that same indent level, so keep searching. - block_mark = comment.start_mark - } - - // While the end of the former comment matches with - // the start of the following one, we know there's - // nothing in between and scanning is still safe. - stop_index = comment.scan_mark.index - } - - // Create a token and append it to the queue. - token := yaml_token_t{ - typ: yaml_BLOCK_END_TOKEN, - start_mark: block_mark, - end_mark: block_mark, - } - yaml_insert_token(parser, -1, &token) - - // Pop the indentation level. - parser.indent = parser.indents[len(parser.indents)-1] - parser.indents = parser.indents[:len(parser.indents)-1] - } - return true -} - -// Initialize the scanner and produce the STREAM-START token. -func yaml_parser_fetch_stream_start(parser *yaml_parser_t) bool { - - // Set the initial indentation. - parser.indent = -1 - - // Initialize the simple key stack. - parser.simple_keys = append(parser.simple_keys, yaml_simple_key_t{}) - - parser.simple_keys_by_tok = make(map[int]int) - - // A simple key is allowed at the beginning of the stream. - parser.simple_key_allowed = true - - // We have started. - parser.stream_start_produced = true - - // Create the STREAM-START token and append it to the queue. - token := yaml_token_t{ - typ: yaml_STREAM_START_TOKEN, - start_mark: parser.mark, - end_mark: parser.mark, - encoding: parser.encoding, - } - yaml_insert_token(parser, -1, &token) - return true -} - -// Produce the STREAM-END token and shut down the scanner. -func yaml_parser_fetch_stream_end(parser *yaml_parser_t) bool { - - // Force new line. - if parser.mark.column != 0 { - parser.mark.column = 0 - parser.mark.line++ - } - - // Reset the indentation level. - if !yaml_parser_unroll_indent(parser, -1, parser.mark) { - return false - } - - // Reset simple keys. - if !yaml_parser_remove_simple_key(parser) { - return false - } - - parser.simple_key_allowed = false - - // Create the STREAM-END token and append it to the queue. - token := yaml_token_t{ - typ: yaml_STREAM_END_TOKEN, - start_mark: parser.mark, - end_mark: parser.mark, - } - yaml_insert_token(parser, -1, &token) - return true -} - -// Produce a VERSION-DIRECTIVE or TAG-DIRECTIVE token. -func yaml_parser_fetch_directive(parser *yaml_parser_t) bool { - // Reset the indentation level. - if !yaml_parser_unroll_indent(parser, -1, parser.mark) { - return false - } - - // Reset simple keys. - if !yaml_parser_remove_simple_key(parser) { - return false - } - - parser.simple_key_allowed = false - - // Create the YAML-DIRECTIVE or TAG-DIRECTIVE token. - token := yaml_token_t{} - if !yaml_parser_scan_directive(parser, &token) { - return false - } - // Append the token to the queue. - yaml_insert_token(parser, -1, &token) - return true -} - -// Produce the DOCUMENT-START or DOCUMENT-END token. -func yaml_parser_fetch_document_indicator(parser *yaml_parser_t, typ yaml_token_type_t) bool { - // Reset the indentation level. - if !yaml_parser_unroll_indent(parser, -1, parser.mark) { - return false - } - - // Reset simple keys. - if !yaml_parser_remove_simple_key(parser) { - return false - } - - parser.simple_key_allowed = false - - // Consume the token. - start_mark := parser.mark - - skip(parser) - skip(parser) - skip(parser) - - end_mark := parser.mark - - // Create the DOCUMENT-START or DOCUMENT-END token. - token := yaml_token_t{ - typ: typ, - start_mark: start_mark, - end_mark: end_mark, - } - // Append the token to the queue. - yaml_insert_token(parser, -1, &token) - return true -} - -// Produce the FLOW-SEQUENCE-START or FLOW-MAPPING-START token. -func yaml_parser_fetch_flow_collection_start(parser *yaml_parser_t, typ yaml_token_type_t) bool { - - // The indicators '[' and '{' may start a simple key. - if !yaml_parser_save_simple_key(parser) { - return false - } - - // Increase the flow level. - if !yaml_parser_increase_flow_level(parser) { - return false - } - - // A simple key may follow the indicators '[' and '{'. - parser.simple_key_allowed = true - - // Consume the token. - start_mark := parser.mark - skip(parser) - end_mark := parser.mark - - // Create the FLOW-SEQUENCE-START of FLOW-MAPPING-START token. - token := yaml_token_t{ - typ: typ, - start_mark: start_mark, - end_mark: end_mark, - } - // Append the token to the queue. - yaml_insert_token(parser, -1, &token) - return true -} - -// Produce the FLOW-SEQUENCE-END or FLOW-MAPPING-END token. -func yaml_parser_fetch_flow_collection_end(parser *yaml_parser_t, typ yaml_token_type_t) bool { - // Reset any potential simple key on the current flow level. - if !yaml_parser_remove_simple_key(parser) { - return false - } - - // Decrease the flow level. - if !yaml_parser_decrease_flow_level(parser) { - return false - } - - // No simple keys after the indicators ']' and '}'. - parser.simple_key_allowed = false - - // Consume the token. - - start_mark := parser.mark - skip(parser) - end_mark := parser.mark - - // Create the FLOW-SEQUENCE-END of FLOW-MAPPING-END token. - token := yaml_token_t{ - typ: typ, - start_mark: start_mark, - end_mark: end_mark, - } - // Append the token to the queue. - yaml_insert_token(parser, -1, &token) - return true -} - -// Produce the FLOW-ENTRY token. -func yaml_parser_fetch_flow_entry(parser *yaml_parser_t) bool { - // Reset any potential simple keys on the current flow level. - if !yaml_parser_remove_simple_key(parser) { - return false - } - - // Simple keys are allowed after ','. - parser.simple_key_allowed = true - - // Consume the token. - start_mark := parser.mark - skip(parser) - end_mark := parser.mark - - // Create the FLOW-ENTRY token and append it to the queue. - token := yaml_token_t{ - typ: yaml_FLOW_ENTRY_TOKEN, - start_mark: start_mark, - end_mark: end_mark, - } - yaml_insert_token(parser, -1, &token) - return true -} - -// Produce the BLOCK-ENTRY token. -func yaml_parser_fetch_block_entry(parser *yaml_parser_t) bool { - // Check if the scanner is in the block context. - if parser.flow_level == 0 { - // Check if we are allowed to start a new entry. - if !parser.simple_key_allowed { - return yaml_parser_set_scanner_error(parser, "", parser.mark, - "block sequence entries are not allowed in this context") - } - // Add the BLOCK-SEQUENCE-START token if needed. - if !yaml_parser_roll_indent(parser, parser.mark.column, -1, yaml_BLOCK_SEQUENCE_START_TOKEN, parser.mark) { - return false - } - } else { - // It is an error for the '-' indicator to occur in the flow context, - // but we let the Parser detect and report about it because the Parser - // is able to point to the context. - } - - // Reset any potential simple keys on the current flow level. - if !yaml_parser_remove_simple_key(parser) { - return false - } - - // Simple keys are allowed after '-'. - parser.simple_key_allowed = true - - // Consume the token. - start_mark := parser.mark - skip(parser) - end_mark := parser.mark - - // Create the BLOCK-ENTRY token and append it to the queue. - token := yaml_token_t{ - typ: yaml_BLOCK_ENTRY_TOKEN, - start_mark: start_mark, - end_mark: end_mark, - } - yaml_insert_token(parser, -1, &token) - return true -} - -// Produce the KEY token. -func yaml_parser_fetch_key(parser *yaml_parser_t) bool { - - // In the block context, additional checks are required. - if parser.flow_level == 0 { - // Check if we are allowed to start a new key (not nessesary simple). - if !parser.simple_key_allowed { - return yaml_parser_set_scanner_error(parser, "", parser.mark, - "mapping keys are not allowed in this context") - } - // Add the BLOCK-MAPPING-START token if needed. - if !yaml_parser_roll_indent(parser, parser.mark.column, -1, yaml_BLOCK_MAPPING_START_TOKEN, parser.mark) { - return false - } - } - - // Reset any potential simple keys on the current flow level. - if !yaml_parser_remove_simple_key(parser) { - return false - } - - // Simple keys are allowed after '?' in the block context. - parser.simple_key_allowed = parser.flow_level == 0 - - // Consume the token. - start_mark := parser.mark - skip(parser) - end_mark := parser.mark - - // Create the KEY token and append it to the queue. - token := yaml_token_t{ - typ: yaml_KEY_TOKEN, - start_mark: start_mark, - end_mark: end_mark, - } - yaml_insert_token(parser, -1, &token) - return true -} - -// Produce the VALUE token. -func yaml_parser_fetch_value(parser *yaml_parser_t) bool { - - simple_key := &parser.simple_keys[len(parser.simple_keys)-1] - - // Have we found a simple key? - if valid, ok := yaml_simple_key_is_valid(parser, simple_key); !ok { - return false - - } else if valid { - - // Create the KEY token and insert it into the queue. - token := yaml_token_t{ - typ: yaml_KEY_TOKEN, - start_mark: simple_key.mark, - end_mark: simple_key.mark, - } - yaml_insert_token(parser, simple_key.token_number-parser.tokens_parsed, &token) - - // In the block context, we may need to add the BLOCK-MAPPING-START token. - if !yaml_parser_roll_indent(parser, simple_key.mark.column, - simple_key.token_number, - yaml_BLOCK_MAPPING_START_TOKEN, simple_key.mark) { - return false - } - - // Remove the simple key. - simple_key.possible = false - delete(parser.simple_keys_by_tok, simple_key.token_number) - - // A simple key cannot follow another simple key. - parser.simple_key_allowed = false - - } else { - // The ':' indicator follows a complex key. - - // In the block context, extra checks are required. - if parser.flow_level == 0 { - - // Check if we are allowed to start a complex value. - if !parser.simple_key_allowed { - return yaml_parser_set_scanner_error(parser, "", parser.mark, - "mapping values are not allowed in this context") - } - - // Add the BLOCK-MAPPING-START token if needed. - if !yaml_parser_roll_indent(parser, parser.mark.column, -1, yaml_BLOCK_MAPPING_START_TOKEN, parser.mark) { - return false - } - } - - // Simple keys after ':' are allowed in the block context. - parser.simple_key_allowed = parser.flow_level == 0 - } - - // Consume the token. - start_mark := parser.mark - skip(parser) - end_mark := parser.mark - - // Create the VALUE token and append it to the queue. - token := yaml_token_t{ - typ: yaml_VALUE_TOKEN, - start_mark: start_mark, - end_mark: end_mark, - } - yaml_insert_token(parser, -1, &token) - return true -} - -// Produce the ALIAS or ANCHOR token. -func yaml_parser_fetch_anchor(parser *yaml_parser_t, typ yaml_token_type_t) bool { - // An anchor or an alias could be a simple key. - if !yaml_parser_save_simple_key(parser) { - return false - } - - // A simple key cannot follow an anchor or an alias. - parser.simple_key_allowed = false - - // Create the ALIAS or ANCHOR token and append it to the queue. - var token yaml_token_t - if !yaml_parser_scan_anchor(parser, &token, typ) { - return false - } - yaml_insert_token(parser, -1, &token) - return true -} - -// Produce the TAG token. -func yaml_parser_fetch_tag(parser *yaml_parser_t) bool { - // A tag could be a simple key. - if !yaml_parser_save_simple_key(parser) { - return false - } - - // A simple key cannot follow a tag. - parser.simple_key_allowed = false - - // Create the TAG token and append it to the queue. - var token yaml_token_t - if !yaml_parser_scan_tag(parser, &token) { - return false - } - yaml_insert_token(parser, -1, &token) - return true -} - -// Produce the SCALAR(...,literal) or SCALAR(...,folded) tokens. -func yaml_parser_fetch_block_scalar(parser *yaml_parser_t, literal bool) bool { - // Remove any potential simple keys. - if !yaml_parser_remove_simple_key(parser) { - return false - } - - // A simple key may follow a block scalar. - parser.simple_key_allowed = true - - // Create the SCALAR token and append it to the queue. - var token yaml_token_t - if !yaml_parser_scan_block_scalar(parser, &token, literal) { - return false - } - yaml_insert_token(parser, -1, &token) - return true -} - -// Produce the SCALAR(...,single-quoted) or SCALAR(...,double-quoted) tokens. -func yaml_parser_fetch_flow_scalar(parser *yaml_parser_t, single bool) bool { - // A plain scalar could be a simple key. - if !yaml_parser_save_simple_key(parser) { - return false - } - - // A simple key cannot follow a flow scalar. - parser.simple_key_allowed = false - - // Create the SCALAR token and append it to the queue. - var token yaml_token_t - if !yaml_parser_scan_flow_scalar(parser, &token, single) { - return false - } - yaml_insert_token(parser, -1, &token) - return true -} - -// Produce the SCALAR(...,plain) token. -func yaml_parser_fetch_plain_scalar(parser *yaml_parser_t) bool { - // A plain scalar could be a simple key. - if !yaml_parser_save_simple_key(parser) { - return false - } - - // A simple key cannot follow a flow scalar. - parser.simple_key_allowed = false - - // Create the SCALAR token and append it to the queue. - var token yaml_token_t - if !yaml_parser_scan_plain_scalar(parser, &token) { - return false - } - yaml_insert_token(parser, -1, &token) - return true -} - -// Eat whitespaces and comments until the next token is found. -func yaml_parser_scan_to_next_token(parser *yaml_parser_t) bool { - - scan_mark := parser.mark - - // Until the next token is not found. - for { - // Allow the BOM mark to start a line. - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - if parser.mark.column == 0 && is_bom(parser.buffer, parser.buffer_pos) { - skip(parser) - } - - // Eat whitespaces. - // Tabs are allowed: - // - in the flow context - // - in the block context, but not at the beginning of the line or - // after '-', '?', or ':' (complex value). - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - - for parser.buffer[parser.buffer_pos] == ' ' || ((parser.flow_level > 0 || !parser.simple_key_allowed) && parser.buffer[parser.buffer_pos] == '\t') { - skip(parser) - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - } - - // Check if we just had a line comment under a sequence entry that - // looks more like a header to the following content. Similar to this: - // - // - # The comment - // - Some data - // - // If so, transform the line comment to a head comment and reposition. - if len(parser.comments) > 0 && len(parser.tokens) > 1 { - tokenA := parser.tokens[len(parser.tokens)-2] - tokenB := parser.tokens[len(parser.tokens)-1] - comment := &parser.comments[len(parser.comments)-1] - if tokenA.typ == yaml_BLOCK_SEQUENCE_START_TOKEN && tokenB.typ == yaml_BLOCK_ENTRY_TOKEN && len(comment.line) > 0 && !is_break(parser.buffer, parser.buffer_pos) { - // If it was in the prior line, reposition so it becomes a - // header of the follow up token. Otherwise, keep it in place - // so it becomes a header of the former. - comment.head = comment.line - comment.line = nil - if comment.start_mark.line == parser.mark.line-1 { - comment.token_mark = parser.mark - } - } - } - - // Eat a comment until a line break. - if parser.buffer[parser.buffer_pos] == '#' { - if !yaml_parser_scan_comments(parser, scan_mark) { - return false - } - } - - // If it is a line break, eat it. - if is_break(parser.buffer, parser.buffer_pos) { - if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { - return false - } - skip_line(parser) - - // In the block context, a new line may start a simple key. - if parser.flow_level == 0 { - parser.simple_key_allowed = true - } - } else { - break // We have found a token. - } - } - - return true -} - -// Scan a YAML-DIRECTIVE or TAG-DIRECTIVE token. -// -// Scope: -// %YAML 1.1 # a comment \n -// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -// %TAG !yaml! tag:yaml.org,2002: \n -// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -// -func yaml_parser_scan_directive(parser *yaml_parser_t, token *yaml_token_t) bool { - // Eat '%'. - start_mark := parser.mark - skip(parser) - - // Scan the directive name. - var name []byte - if !yaml_parser_scan_directive_name(parser, start_mark, &name) { - return false - } - - // Is it a YAML directive? - if bytes.Equal(name, []byte("YAML")) { - // Scan the VERSION directive value. - var major, minor int8 - if !yaml_parser_scan_version_directive_value(parser, start_mark, &major, &minor) { - return false - } - end_mark := parser.mark - - // Create a VERSION-DIRECTIVE token. - *token = yaml_token_t{ - typ: yaml_VERSION_DIRECTIVE_TOKEN, - start_mark: start_mark, - end_mark: end_mark, - major: major, - minor: minor, - } - - // Is it a TAG directive? - } else if bytes.Equal(name, []byte("TAG")) { - // Scan the TAG directive value. - var handle, prefix []byte - if !yaml_parser_scan_tag_directive_value(parser, start_mark, &handle, &prefix) { - return false - } - end_mark := parser.mark - - // Create a TAG-DIRECTIVE token. - *token = yaml_token_t{ - typ: yaml_TAG_DIRECTIVE_TOKEN, - start_mark: start_mark, - end_mark: end_mark, - value: handle, - prefix: prefix, - } - - // Unknown directive. - } else { - yaml_parser_set_scanner_error(parser, "while scanning a directive", - start_mark, "found unknown directive name") - return false - } - - // Eat the rest of the line including any comments. - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - - for is_blank(parser.buffer, parser.buffer_pos) { - skip(parser) - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - } - - if parser.buffer[parser.buffer_pos] == '#' { - // [Go] Discard this inline comment for the time being. - //if !yaml_parser_scan_line_comment(parser, start_mark) { - // return false - //} - for !is_breakz(parser.buffer, parser.buffer_pos) { - skip(parser) - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - } - } - - // Check if we are at the end of the line. - if !is_breakz(parser.buffer, parser.buffer_pos) { - yaml_parser_set_scanner_error(parser, "while scanning a directive", - start_mark, "did not find expected comment or line break") - return false - } - - // Eat a line break. - if is_break(parser.buffer, parser.buffer_pos) { - if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { - return false - } - skip_line(parser) - } - - return true -} - -// Scan the directive name. -// -// Scope: -// %YAML 1.1 # a comment \n -// ^^^^ -// %TAG !yaml! tag:yaml.org,2002: \n -// ^^^ -// -func yaml_parser_scan_directive_name(parser *yaml_parser_t, start_mark yaml_mark_t, name *[]byte) bool { - // Consume the directive name. - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - - var s []byte - for is_alpha(parser.buffer, parser.buffer_pos) { - s = read(parser, s) - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - } - - // Check if the name is empty. - if len(s) == 0 { - yaml_parser_set_scanner_error(parser, "while scanning a directive", - start_mark, "could not find expected directive name") - return false - } - - // Check for an blank character after the name. - if !is_blankz(parser.buffer, parser.buffer_pos) { - yaml_parser_set_scanner_error(parser, "while scanning a directive", - start_mark, "found unexpected non-alphabetical character") - return false - } - *name = s - return true -} - -// Scan the value of VERSION-DIRECTIVE. -// -// Scope: -// %YAML 1.1 # a comment \n -// ^^^^^^ -func yaml_parser_scan_version_directive_value(parser *yaml_parser_t, start_mark yaml_mark_t, major, minor *int8) bool { - // Eat whitespaces. - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - for is_blank(parser.buffer, parser.buffer_pos) { - skip(parser) - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - } - - // Consume the major version number. - if !yaml_parser_scan_version_directive_number(parser, start_mark, major) { - return false - } - - // Eat '.'. - if parser.buffer[parser.buffer_pos] != '.' { - return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive", - start_mark, "did not find expected digit or '.' character") - } - - skip(parser) - - // Consume the minor version number. - if !yaml_parser_scan_version_directive_number(parser, start_mark, minor) { - return false - } - return true -} - -const max_number_length = 2 - -// Scan the version number of VERSION-DIRECTIVE. -// -// Scope: -// %YAML 1.1 # a comment \n -// ^ -// %YAML 1.1 # a comment \n -// ^ -func yaml_parser_scan_version_directive_number(parser *yaml_parser_t, start_mark yaml_mark_t, number *int8) bool { - - // Repeat while the next character is digit. - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - var value, length int8 - for is_digit(parser.buffer, parser.buffer_pos) { - // Check if the number is too long. - length++ - if length > max_number_length { - return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive", - start_mark, "found extremely long version number") - } - value = value*10 + int8(as_digit(parser.buffer, parser.buffer_pos)) - skip(parser) - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - } - - // Check if the number was present. - if length == 0 { - return yaml_parser_set_scanner_error(parser, "while scanning a %YAML directive", - start_mark, "did not find expected version number") - } - *number = value - return true -} - -// Scan the value of a TAG-DIRECTIVE token. -// -// Scope: -// %TAG !yaml! tag:yaml.org,2002: \n -// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -// -func yaml_parser_scan_tag_directive_value(parser *yaml_parser_t, start_mark yaml_mark_t, handle, prefix *[]byte) bool { - var handle_value, prefix_value []byte - - // Eat whitespaces. - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - - for is_blank(parser.buffer, parser.buffer_pos) { - skip(parser) - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - } - - // Scan a handle. - if !yaml_parser_scan_tag_handle(parser, true, start_mark, &handle_value) { - return false - } - - // Expect a whitespace. - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - if !is_blank(parser.buffer, parser.buffer_pos) { - yaml_parser_set_scanner_error(parser, "while scanning a %TAG directive", - start_mark, "did not find expected whitespace") - return false - } - - // Eat whitespaces. - for is_blank(parser.buffer, parser.buffer_pos) { - skip(parser) - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - } - - // Scan a prefix. - if !yaml_parser_scan_tag_uri(parser, true, nil, start_mark, &prefix_value) { - return false - } - - // Expect a whitespace or line break. - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - if !is_blankz(parser.buffer, parser.buffer_pos) { - yaml_parser_set_scanner_error(parser, "while scanning a %TAG directive", - start_mark, "did not find expected whitespace or line break") - return false - } - - *handle = handle_value - *prefix = prefix_value - return true -} - -func yaml_parser_scan_anchor(parser *yaml_parser_t, token *yaml_token_t, typ yaml_token_type_t) bool { - var s []byte - - // Eat the indicator character. - start_mark := parser.mark - skip(parser) - - // Consume the value. - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - - for is_alpha(parser.buffer, parser.buffer_pos) { - s = read(parser, s) - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - } - - end_mark := parser.mark - - /* - * Check if length of the anchor is greater than 0 and it is followed by - * a whitespace character or one of the indicators: - * - * '?', ':', ',', ']', '}', '%', '@', '`'. - */ - - if len(s) == 0 || - !(is_blankz(parser.buffer, parser.buffer_pos) || parser.buffer[parser.buffer_pos] == '?' || - parser.buffer[parser.buffer_pos] == ':' || parser.buffer[parser.buffer_pos] == ',' || - parser.buffer[parser.buffer_pos] == ']' || parser.buffer[parser.buffer_pos] == '}' || - parser.buffer[parser.buffer_pos] == '%' || parser.buffer[parser.buffer_pos] == '@' || - parser.buffer[parser.buffer_pos] == '`') { - context := "while scanning an alias" - if typ == yaml_ANCHOR_TOKEN { - context = "while scanning an anchor" - } - yaml_parser_set_scanner_error(parser, context, start_mark, - "did not find expected alphabetic or numeric character") - return false - } - - // Create a token. - *token = yaml_token_t{ - typ: typ, - start_mark: start_mark, - end_mark: end_mark, - value: s, - } - - return true -} - -/* - * Scan a TAG token. - */ - -func yaml_parser_scan_tag(parser *yaml_parser_t, token *yaml_token_t) bool { - var handle, suffix []byte - - start_mark := parser.mark - - // Check if the tag is in the canonical form. - if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { - return false - } - - if parser.buffer[parser.buffer_pos+1] == '<' { - // Keep the handle as '' - - // Eat '!<' - skip(parser) - skip(parser) - - // Consume the tag value. - if !yaml_parser_scan_tag_uri(parser, false, nil, start_mark, &suffix) { - return false - } - - // Check for '>' and eat it. - if parser.buffer[parser.buffer_pos] != '>' { - yaml_parser_set_scanner_error(parser, "while scanning a tag", - start_mark, "did not find the expected '>'") - return false - } - - skip(parser) - } else { - // The tag has either the '!suffix' or the '!handle!suffix' form. - - // First, try to scan a handle. - if !yaml_parser_scan_tag_handle(parser, false, start_mark, &handle) { - return false - } - - // Check if it is, indeed, handle. - if handle[0] == '!' && len(handle) > 1 && handle[len(handle)-1] == '!' { - // Scan the suffix now. - if !yaml_parser_scan_tag_uri(parser, false, nil, start_mark, &suffix) { - return false - } - } else { - // It wasn't a handle after all. Scan the rest of the tag. - if !yaml_parser_scan_tag_uri(parser, false, handle, start_mark, &suffix) { - return false - } - - // Set the handle to '!'. - handle = []byte{'!'} - - // A special case: the '!' tag. Set the handle to '' and the - // suffix to '!'. - if len(suffix) == 0 { - handle, suffix = suffix, handle - } - } - } - - // Check the character which ends the tag. - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - if !is_blankz(parser.buffer, parser.buffer_pos) { - yaml_parser_set_scanner_error(parser, "while scanning a tag", - start_mark, "did not find expected whitespace or line break") - return false - } - - end_mark := parser.mark - - // Create a token. - *token = yaml_token_t{ - typ: yaml_TAG_TOKEN, - start_mark: start_mark, - end_mark: end_mark, - value: handle, - suffix: suffix, - } - return true -} - -// Scan a tag handle. -func yaml_parser_scan_tag_handle(parser *yaml_parser_t, directive bool, start_mark yaml_mark_t, handle *[]byte) bool { - // Check the initial '!' character. - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - if parser.buffer[parser.buffer_pos] != '!' { - yaml_parser_set_scanner_tag_error(parser, directive, - start_mark, "did not find expected '!'") - return false - } - - var s []byte - - // Copy the '!' character. - s = read(parser, s) - - // Copy all subsequent alphabetical and numerical characters. - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - for is_alpha(parser.buffer, parser.buffer_pos) { - s = read(parser, s) - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - } - - // Check if the trailing character is '!' and copy it. - if parser.buffer[parser.buffer_pos] == '!' { - s = read(parser, s) - } else { - // It's either the '!' tag or not really a tag handle. If it's a %TAG - // directive, it's an error. If it's a tag token, it must be a part of URI. - if directive && string(s) != "!" { - yaml_parser_set_scanner_tag_error(parser, directive, - start_mark, "did not find expected '!'") - return false - } - } - - *handle = s - return true -} - -// Scan a tag. -func yaml_parser_scan_tag_uri(parser *yaml_parser_t, directive bool, head []byte, start_mark yaml_mark_t, uri *[]byte) bool { - //size_t length = head ? strlen((char *)head) : 0 - var s []byte - hasTag := len(head) > 0 - - // Copy the head if needed. - // - // Note that we don't copy the leading '!' character. - if len(head) > 1 { - s = append(s, head[1:]...) - } - - // Scan the tag. - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - - // The set of characters that may appear in URI is as follows: - // - // '0'-'9', 'A'-'Z', 'a'-'z', '_', '-', ';', '/', '?', ':', '@', '&', - // '=', '+', '$', ',', '.', '!', '~', '*', '\'', '(', ')', '[', ']', - // '%'. - // [Go] TODO Convert this into more reasonable logic. - for is_alpha(parser.buffer, parser.buffer_pos) || parser.buffer[parser.buffer_pos] == ';' || - parser.buffer[parser.buffer_pos] == '/' || parser.buffer[parser.buffer_pos] == '?' || - parser.buffer[parser.buffer_pos] == ':' || parser.buffer[parser.buffer_pos] == '@' || - parser.buffer[parser.buffer_pos] == '&' || parser.buffer[parser.buffer_pos] == '=' || - parser.buffer[parser.buffer_pos] == '+' || parser.buffer[parser.buffer_pos] == '$' || - parser.buffer[parser.buffer_pos] == ',' || parser.buffer[parser.buffer_pos] == '.' || - parser.buffer[parser.buffer_pos] == '!' || parser.buffer[parser.buffer_pos] == '~' || - parser.buffer[parser.buffer_pos] == '*' || parser.buffer[parser.buffer_pos] == '\'' || - parser.buffer[parser.buffer_pos] == '(' || parser.buffer[parser.buffer_pos] == ')' || - parser.buffer[parser.buffer_pos] == '[' || parser.buffer[parser.buffer_pos] == ']' || - parser.buffer[parser.buffer_pos] == '%' { - // Check if it is a URI-escape sequence. - if parser.buffer[parser.buffer_pos] == '%' { - if !yaml_parser_scan_uri_escapes(parser, directive, start_mark, &s) { - return false - } - } else { - s = read(parser, s) - } - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - hasTag = true - } - - if !hasTag { - yaml_parser_set_scanner_tag_error(parser, directive, - start_mark, "did not find expected tag URI") - return false - } - *uri = s - return true -} - -// Decode an URI-escape sequence corresponding to a single UTF-8 character. -func yaml_parser_scan_uri_escapes(parser *yaml_parser_t, directive bool, start_mark yaml_mark_t, s *[]byte) bool { - - // Decode the required number of characters. - w := 1024 - for w > 0 { - // Check for a URI-escaped octet. - if parser.unread < 3 && !yaml_parser_update_buffer(parser, 3) { - return false - } - - if !(parser.buffer[parser.buffer_pos] == '%' && - is_hex(parser.buffer, parser.buffer_pos+1) && - is_hex(parser.buffer, parser.buffer_pos+2)) { - return yaml_parser_set_scanner_tag_error(parser, directive, - start_mark, "did not find URI escaped octet") - } - - // Get the octet. - octet := byte((as_hex(parser.buffer, parser.buffer_pos+1) << 4) + as_hex(parser.buffer, parser.buffer_pos+2)) - - // If it is the leading octet, determine the length of the UTF-8 sequence. - if w == 1024 { - w = width(octet) - if w == 0 { - return yaml_parser_set_scanner_tag_error(parser, directive, - start_mark, "found an incorrect leading UTF-8 octet") - } - } else { - // Check if the trailing octet is correct. - if octet&0xC0 != 0x80 { - return yaml_parser_set_scanner_tag_error(parser, directive, - start_mark, "found an incorrect trailing UTF-8 octet") - } - } - - // Copy the octet and move the pointers. - *s = append(*s, octet) - skip(parser) - skip(parser) - skip(parser) - w-- - } - return true -} - -// Scan a block scalar. -func yaml_parser_scan_block_scalar(parser *yaml_parser_t, token *yaml_token_t, literal bool) bool { - // Eat the indicator '|' or '>'. - start_mark := parser.mark - skip(parser) - - // Scan the additional block scalar indicators. - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - - // Check for a chomping indicator. - var chomping, increment int - if parser.buffer[parser.buffer_pos] == '+' || parser.buffer[parser.buffer_pos] == '-' { - // Set the chomping method and eat the indicator. - if parser.buffer[parser.buffer_pos] == '+' { - chomping = +1 - } else { - chomping = -1 - } - skip(parser) - - // Check for an indentation indicator. - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - if is_digit(parser.buffer, parser.buffer_pos) { - // Check that the indentation is greater than 0. - if parser.buffer[parser.buffer_pos] == '0' { - yaml_parser_set_scanner_error(parser, "while scanning a block scalar", - start_mark, "found an indentation indicator equal to 0") - return false - } - - // Get the indentation level and eat the indicator. - increment = as_digit(parser.buffer, parser.buffer_pos) - skip(parser) - } - - } else if is_digit(parser.buffer, parser.buffer_pos) { - // Do the same as above, but in the opposite order. - - if parser.buffer[parser.buffer_pos] == '0' { - yaml_parser_set_scanner_error(parser, "while scanning a block scalar", - start_mark, "found an indentation indicator equal to 0") - return false - } - increment = as_digit(parser.buffer, parser.buffer_pos) - skip(parser) - - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - if parser.buffer[parser.buffer_pos] == '+' || parser.buffer[parser.buffer_pos] == '-' { - if parser.buffer[parser.buffer_pos] == '+' { - chomping = +1 - } else { - chomping = -1 - } - skip(parser) - } - } - - // Eat whitespaces and comments to the end of the line. - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - for is_blank(parser.buffer, parser.buffer_pos) { - skip(parser) - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - } - if parser.buffer[parser.buffer_pos] == '#' { - if !yaml_parser_scan_line_comment(parser, start_mark) { - return false - } - for !is_breakz(parser.buffer, parser.buffer_pos) { - skip(parser) - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - } - } - - // Check if we are at the end of the line. - if !is_breakz(parser.buffer, parser.buffer_pos) { - yaml_parser_set_scanner_error(parser, "while scanning a block scalar", - start_mark, "did not find expected comment or line break") - return false - } - - // Eat a line break. - if is_break(parser.buffer, parser.buffer_pos) { - if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { - return false - } - skip_line(parser) - } - - end_mark := parser.mark - - // Set the indentation level if it was specified. - var indent int - if increment > 0 { - if parser.indent >= 0 { - indent = parser.indent + increment - } else { - indent = increment - } - } - - // Scan the leading line breaks and determine the indentation level if needed. - var s, leading_break, trailing_breaks []byte - if !yaml_parser_scan_block_scalar_breaks(parser, &indent, &trailing_breaks, start_mark, &end_mark) { - return false - } - - // Scan the block scalar content. - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - var leading_blank, trailing_blank bool - for parser.mark.column == indent && !is_z(parser.buffer, parser.buffer_pos) { - // We are at the beginning of a non-empty line. - - // Is it a trailing whitespace? - trailing_blank = is_blank(parser.buffer, parser.buffer_pos) - - // Check if we need to fold the leading line break. - if !literal && !leading_blank && !trailing_blank && len(leading_break) > 0 && leading_break[0] == '\n' { - // Do we need to join the lines by space? - if len(trailing_breaks) == 0 { - s = append(s, ' ') - } - } else { - s = append(s, leading_break...) - } - leading_break = leading_break[:0] - - // Append the remaining line breaks. - s = append(s, trailing_breaks...) - trailing_breaks = trailing_breaks[:0] - - // Is it a leading whitespace? - leading_blank = is_blank(parser.buffer, parser.buffer_pos) - - // Consume the current line. - for !is_breakz(parser.buffer, parser.buffer_pos) { - s = read(parser, s) - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - } - - // Consume the line break. - if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { - return false - } - - leading_break = read_line(parser, leading_break) - - // Eat the following indentation spaces and line breaks. - if !yaml_parser_scan_block_scalar_breaks(parser, &indent, &trailing_breaks, start_mark, &end_mark) { - return false - } - } - - // Chomp the tail. - if chomping != -1 { - s = append(s, leading_break...) - } - if chomping == 1 { - s = append(s, trailing_breaks...) - } - - // Create a token. - *token = yaml_token_t{ - typ: yaml_SCALAR_TOKEN, - start_mark: start_mark, - end_mark: end_mark, - value: s, - style: yaml_LITERAL_SCALAR_STYLE, - } - if !literal { - token.style = yaml_FOLDED_SCALAR_STYLE - } - return true -} - -// Scan indentation spaces and line breaks for a block scalar. Determine the -// indentation level if needed. -func yaml_parser_scan_block_scalar_breaks(parser *yaml_parser_t, indent *int, breaks *[]byte, start_mark yaml_mark_t, end_mark *yaml_mark_t) bool { - *end_mark = parser.mark - - // Eat the indentation spaces and line breaks. - max_indent := 0 - for { - // Eat the indentation spaces. - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - for (*indent == 0 || parser.mark.column < *indent) && is_space(parser.buffer, parser.buffer_pos) { - skip(parser) - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - } - if parser.mark.column > max_indent { - max_indent = parser.mark.column - } - - // Check for a tab character messing the indentation. - if (*indent == 0 || parser.mark.column < *indent) && is_tab(parser.buffer, parser.buffer_pos) { - return yaml_parser_set_scanner_error(parser, "while scanning a block scalar", - start_mark, "found a tab character where an indentation space is expected") - } - - // Have we found a non-empty line? - if !is_break(parser.buffer, parser.buffer_pos) { - break - } - - // Consume the line break. - if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { - return false - } - // [Go] Should really be returning breaks instead. - *breaks = read_line(parser, *breaks) - *end_mark = parser.mark - } - - // Determine the indentation level if needed. - if *indent == 0 { - *indent = max_indent - if *indent < parser.indent+1 { - *indent = parser.indent + 1 - } - if *indent < 1 { - *indent = 1 - } - } - return true -} - -// Scan a quoted scalar. -func yaml_parser_scan_flow_scalar(parser *yaml_parser_t, token *yaml_token_t, single bool) bool { - // Eat the left quote. - start_mark := parser.mark - skip(parser) - - // Consume the content of the quoted scalar. - var s, leading_break, trailing_breaks, whitespaces []byte - for { - // Check that there are no document indicators at the beginning of the line. - if parser.unread < 4 && !yaml_parser_update_buffer(parser, 4) { - return false - } - - if parser.mark.column == 0 && - ((parser.buffer[parser.buffer_pos+0] == '-' && - parser.buffer[parser.buffer_pos+1] == '-' && - parser.buffer[parser.buffer_pos+2] == '-') || - (parser.buffer[parser.buffer_pos+0] == '.' && - parser.buffer[parser.buffer_pos+1] == '.' && - parser.buffer[parser.buffer_pos+2] == '.')) && - is_blankz(parser.buffer, parser.buffer_pos+3) { - yaml_parser_set_scanner_error(parser, "while scanning a quoted scalar", - start_mark, "found unexpected document indicator") - return false - } - - // Check for EOF. - if is_z(parser.buffer, parser.buffer_pos) { - yaml_parser_set_scanner_error(parser, "while scanning a quoted scalar", - start_mark, "found unexpected end of stream") - return false - } - - // Consume non-blank characters. - leading_blanks := false - for !is_blankz(parser.buffer, parser.buffer_pos) { - if single && parser.buffer[parser.buffer_pos] == '\'' && parser.buffer[parser.buffer_pos+1] == '\'' { - // Is is an escaped single quote. - s = append(s, '\'') - skip(parser) - skip(parser) - - } else if single && parser.buffer[parser.buffer_pos] == '\'' { - // It is a right single quote. - break - } else if !single && parser.buffer[parser.buffer_pos] == '"' { - // It is a right double quote. - break - - } else if !single && parser.buffer[parser.buffer_pos] == '\\' && is_break(parser.buffer, parser.buffer_pos+1) { - // It is an escaped line break. - if parser.unread < 3 && !yaml_parser_update_buffer(parser, 3) { - return false - } - skip(parser) - skip_line(parser) - leading_blanks = true - break - - } else if !single && parser.buffer[parser.buffer_pos] == '\\' { - // It is an escape sequence. - code_length := 0 - - // Check the escape character. - switch parser.buffer[parser.buffer_pos+1] { - case '0': - s = append(s, 0) - case 'a': - s = append(s, '\x07') - case 'b': - s = append(s, '\x08') - case 't', '\t': - s = append(s, '\x09') - case 'n': - s = append(s, '\x0A') - case 'v': - s = append(s, '\x0B') - case 'f': - s = append(s, '\x0C') - case 'r': - s = append(s, '\x0D') - case 'e': - s = append(s, '\x1B') - case ' ': - s = append(s, '\x20') - case '"': - s = append(s, '"') - case '\'': - s = append(s, '\'') - case '\\': - s = append(s, '\\') - case 'N': // NEL (#x85) - s = append(s, '\xC2') - s = append(s, '\x85') - case '_': // #xA0 - s = append(s, '\xC2') - s = append(s, '\xA0') - case 'L': // LS (#x2028) - s = append(s, '\xE2') - s = append(s, '\x80') - s = append(s, '\xA8') - case 'P': // PS (#x2029) - s = append(s, '\xE2') - s = append(s, '\x80') - s = append(s, '\xA9') - case 'x': - code_length = 2 - case 'u': - code_length = 4 - case 'U': - code_length = 8 - default: - yaml_parser_set_scanner_error(parser, "while parsing a quoted scalar", - start_mark, "found unknown escape character") - return false - } - - skip(parser) - skip(parser) - - // Consume an arbitrary escape code. - if code_length > 0 { - var value int - - // Scan the character value. - if parser.unread < code_length && !yaml_parser_update_buffer(parser, code_length) { - return false - } - for k := 0; k < code_length; k++ { - if !is_hex(parser.buffer, parser.buffer_pos+k) { - yaml_parser_set_scanner_error(parser, "while parsing a quoted scalar", - start_mark, "did not find expected hexdecimal number") - return false - } - value = (value << 4) + as_hex(parser.buffer, parser.buffer_pos+k) - } - - // Check the value and write the character. - if (value >= 0xD800 && value <= 0xDFFF) || value > 0x10FFFF { - yaml_parser_set_scanner_error(parser, "while parsing a quoted scalar", - start_mark, "found invalid Unicode character escape code") - return false - } - if value <= 0x7F { - s = append(s, byte(value)) - } else if value <= 0x7FF { - s = append(s, byte(0xC0+(value>>6))) - s = append(s, byte(0x80+(value&0x3F))) - } else if value <= 0xFFFF { - s = append(s, byte(0xE0+(value>>12))) - s = append(s, byte(0x80+((value>>6)&0x3F))) - s = append(s, byte(0x80+(value&0x3F))) - } else { - s = append(s, byte(0xF0+(value>>18))) - s = append(s, byte(0x80+((value>>12)&0x3F))) - s = append(s, byte(0x80+((value>>6)&0x3F))) - s = append(s, byte(0x80+(value&0x3F))) - } - - // Advance the pointer. - for k := 0; k < code_length; k++ { - skip(parser) - } - } - } else { - // It is a non-escaped non-blank character. - s = read(parser, s) - } - if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { - return false - } - } - - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - - // Check if we are at the end of the scalar. - if single { - if parser.buffer[parser.buffer_pos] == '\'' { - break - } - } else { - if parser.buffer[parser.buffer_pos] == '"' { - break - } - } - - // Consume blank characters. - for is_blank(parser.buffer, parser.buffer_pos) || is_break(parser.buffer, parser.buffer_pos) { - if is_blank(parser.buffer, parser.buffer_pos) { - // Consume a space or a tab character. - if !leading_blanks { - whitespaces = read(parser, whitespaces) - } else { - skip(parser) - } - } else { - if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { - return false - } - - // Check if it is a first line break. - if !leading_blanks { - whitespaces = whitespaces[:0] - leading_break = read_line(parser, leading_break) - leading_blanks = true - } else { - trailing_breaks = read_line(parser, trailing_breaks) - } - } - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - } - - // Join the whitespaces or fold line breaks. - if leading_blanks { - // Do we need to fold line breaks? - if len(leading_break) > 0 && leading_break[0] == '\n' { - if len(trailing_breaks) == 0 { - s = append(s, ' ') - } else { - s = append(s, trailing_breaks...) - } - } else { - s = append(s, leading_break...) - s = append(s, trailing_breaks...) - } - trailing_breaks = trailing_breaks[:0] - leading_break = leading_break[:0] - } else { - s = append(s, whitespaces...) - whitespaces = whitespaces[:0] - } - } - - // Eat the right quote. - skip(parser) - end_mark := parser.mark - - // Create a token. - *token = yaml_token_t{ - typ: yaml_SCALAR_TOKEN, - start_mark: start_mark, - end_mark: end_mark, - value: s, - style: yaml_SINGLE_QUOTED_SCALAR_STYLE, - } - if !single { - token.style = yaml_DOUBLE_QUOTED_SCALAR_STYLE - } - return true -} - -// Scan a plain scalar. -func yaml_parser_scan_plain_scalar(parser *yaml_parser_t, token *yaml_token_t) bool { - - var s, leading_break, trailing_breaks, whitespaces []byte - var leading_blanks bool - var indent = parser.indent + 1 - - start_mark := parser.mark - end_mark := parser.mark - - // Consume the content of the plain scalar. - for { - // Check for a document indicator. - if parser.unread < 4 && !yaml_parser_update_buffer(parser, 4) { - return false - } - if parser.mark.column == 0 && - ((parser.buffer[parser.buffer_pos+0] == '-' && - parser.buffer[parser.buffer_pos+1] == '-' && - parser.buffer[parser.buffer_pos+2] == '-') || - (parser.buffer[parser.buffer_pos+0] == '.' && - parser.buffer[parser.buffer_pos+1] == '.' && - parser.buffer[parser.buffer_pos+2] == '.')) && - is_blankz(parser.buffer, parser.buffer_pos+3) { - break - } - - // Check for a comment. - if parser.buffer[parser.buffer_pos] == '#' { - break - } - - // Consume non-blank characters. - for !is_blankz(parser.buffer, parser.buffer_pos) { - - // Check for indicators that may end a plain scalar. - if (parser.buffer[parser.buffer_pos] == ':' && is_blankz(parser.buffer, parser.buffer_pos+1)) || - (parser.flow_level > 0 && - (parser.buffer[parser.buffer_pos] == ',' || - parser.buffer[parser.buffer_pos] == '?' || parser.buffer[parser.buffer_pos] == '[' || - parser.buffer[parser.buffer_pos] == ']' || parser.buffer[parser.buffer_pos] == '{' || - parser.buffer[parser.buffer_pos] == '}')) { - break - } - - // Check if we need to join whitespaces and breaks. - if leading_blanks || len(whitespaces) > 0 { - if leading_blanks { - // Do we need to fold line breaks? - if leading_break[0] == '\n' { - if len(trailing_breaks) == 0 { - s = append(s, ' ') - } else { - s = append(s, trailing_breaks...) - } - } else { - s = append(s, leading_break...) - s = append(s, trailing_breaks...) - } - trailing_breaks = trailing_breaks[:0] - leading_break = leading_break[:0] - leading_blanks = false - } else { - s = append(s, whitespaces...) - whitespaces = whitespaces[:0] - } - } - - // Copy the character. - s = read(parser, s) - - end_mark = parser.mark - if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { - return false - } - } - - // Is it the end? - if !(is_blank(parser.buffer, parser.buffer_pos) || is_break(parser.buffer, parser.buffer_pos)) { - break - } - - // Consume blank characters. - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - - for is_blank(parser.buffer, parser.buffer_pos) || is_break(parser.buffer, parser.buffer_pos) { - if is_blank(parser.buffer, parser.buffer_pos) { - - // Check for tab characters that abuse indentation. - if leading_blanks && parser.mark.column < indent && is_tab(parser.buffer, parser.buffer_pos) { - yaml_parser_set_scanner_error(parser, "while scanning a plain scalar", - start_mark, "found a tab character that violates indentation") - return false - } - - // Consume a space or a tab character. - if !leading_blanks { - whitespaces = read(parser, whitespaces) - } else { - skip(parser) - } - } else { - if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { - return false - } - - // Check if it is a first line break. - if !leading_blanks { - whitespaces = whitespaces[:0] - leading_break = read_line(parser, leading_break) - leading_blanks = true - } else { - trailing_breaks = read_line(parser, trailing_breaks) - } - } - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - } - - // Check indentation level. - if parser.flow_level == 0 && parser.mark.column < indent { - break - } - } - - // Create a token. - *token = yaml_token_t{ - typ: yaml_SCALAR_TOKEN, - start_mark: start_mark, - end_mark: end_mark, - value: s, - style: yaml_PLAIN_SCALAR_STYLE, - } - - // Note that we change the 'simple_key_allowed' flag. - if leading_blanks { - parser.simple_key_allowed = true - } - return true -} - -func yaml_parser_scan_line_comment(parser *yaml_parser_t, token_mark yaml_mark_t) bool { - if parser.newlines > 0 { - return true - } - - var start_mark yaml_mark_t - var text []byte - - for peek := 0; peek < 512; peek++ { - if parser.unread < peek+1 && !yaml_parser_update_buffer(parser, peek+1) { - break - } - if is_blank(parser.buffer, parser.buffer_pos+peek) { - continue - } - if parser.buffer[parser.buffer_pos+peek] == '#' { - seen := parser.mark.index+peek - for { - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - if is_breakz(parser.buffer, parser.buffer_pos) { - if parser.mark.index >= seen { - break - } - if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { - return false - } - skip_line(parser) - } else if parser.mark.index >= seen { - if len(text) == 0 { - start_mark = parser.mark - } - text = read(parser, text) - } else { - skip(parser) - } - } - } - break - } - if len(text) > 0 { - parser.comments = append(parser.comments, yaml_comment_t{ - token_mark: token_mark, - start_mark: start_mark, - line: text, - }) - } - return true -} - -func yaml_parser_scan_comments(parser *yaml_parser_t, scan_mark yaml_mark_t) bool { - token := parser.tokens[len(parser.tokens)-1] - - if token.typ == yaml_FLOW_ENTRY_TOKEN && len(parser.tokens) > 1 { - token = parser.tokens[len(parser.tokens)-2] - } - - var token_mark = token.start_mark - var start_mark yaml_mark_t - var next_indent = parser.indent - if next_indent < 0 { - next_indent = 0 - } - - var recent_empty = false - var first_empty = parser.newlines <= 1 - - var line = parser.mark.line - var column = parser.mark.column - - var text []byte - - // The foot line is the place where a comment must start to - // still be considered as a foot of the prior content. - // If there's some content in the currently parsed line, then - // the foot is the line below it. - var foot_line = -1 - if scan_mark.line > 0 { - foot_line = parser.mark.line-parser.newlines+1 - if parser.newlines == 0 && parser.mark.column > 1 { - foot_line++ - } - } - - var peek = 0 - for ; peek < 512; peek++ { - if parser.unread < peek+1 && !yaml_parser_update_buffer(parser, peek+1) { - break - } - column++ - if is_blank(parser.buffer, parser.buffer_pos+peek) { - continue - } - c := parser.buffer[parser.buffer_pos+peek] - var close_flow = parser.flow_level > 0 && (c == ']' || c == '}') - if close_flow || is_breakz(parser.buffer, parser.buffer_pos+peek) { - // Got line break or terminator. - if close_flow || !recent_empty { - if close_flow || first_empty && (start_mark.line == foot_line && token.typ != yaml_VALUE_TOKEN || start_mark.column-1 < next_indent) { - // This is the first empty line and there were no empty lines before, - // so this initial part of the comment is a foot of the prior token - // instead of being a head for the following one. Split it up. - // Alternatively, this might also be the last comment inside a flow - // scope, so it must be a footer. - if len(text) > 0 { - if start_mark.column-1 < next_indent { - // If dedented it's unrelated to the prior token. - token_mark = start_mark - } - parser.comments = append(parser.comments, yaml_comment_t{ - scan_mark: scan_mark, - token_mark: token_mark, - start_mark: start_mark, - end_mark: yaml_mark_t{parser.mark.index + peek, line, column}, - foot: text, - }) - scan_mark = yaml_mark_t{parser.mark.index + peek, line, column} - token_mark = scan_mark - text = nil - } - } else { - if len(text) > 0 && parser.buffer[parser.buffer_pos+peek] != 0 { - text = append(text, '\n') - } - } - } - if !is_break(parser.buffer, parser.buffer_pos+peek) { - break - } - first_empty = false - recent_empty = true - column = 0 - line++ - continue - } - - if len(text) > 0 && (close_flow || column-1 < next_indent && column != start_mark.column) { - // The comment at the different indentation is a foot of the - // preceding data rather than a head of the upcoming one. - parser.comments = append(parser.comments, yaml_comment_t{ - scan_mark: scan_mark, - token_mark: token_mark, - start_mark: start_mark, - end_mark: yaml_mark_t{parser.mark.index + peek, line, column}, - foot: text, - }) - scan_mark = yaml_mark_t{parser.mark.index + peek, line, column} - token_mark = scan_mark - text = nil - } - - if parser.buffer[parser.buffer_pos+peek] != '#' { - break - } - - if len(text) == 0 { - start_mark = yaml_mark_t{parser.mark.index + peek, line, column} - } else { - text = append(text, '\n') - } - - recent_empty = false - - // Consume until after the consumed comment line. - seen := parser.mark.index+peek - for { - if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) { - return false - } - if is_breakz(parser.buffer, parser.buffer_pos) { - if parser.mark.index >= seen { - break - } - if parser.unread < 2 && !yaml_parser_update_buffer(parser, 2) { - return false - } - skip_line(parser) - } else if parser.mark.index >= seen { - text = read(parser, text) - } else { - skip(parser) - } - } - - peek = 0 - column = 0 - line = parser.mark.line - next_indent = parser.indent - if next_indent < 0 { - next_indent = 0 - } - } - - if len(text) > 0 { - parser.comments = append(parser.comments, yaml_comment_t{ - scan_mark: scan_mark, - token_mark: start_mark, - start_mark: start_mark, - end_mark: yaml_mark_t{parser.mark.index + peek - 1, line, column}, - head: text, - }) - } - return true -} diff --git a/trunk/3rdparty/srs-bench/vendor/gopkg.in/yaml.v3/sorter.go b/trunk/3rdparty/srs-bench/vendor/gopkg.in/yaml.v3/sorter.go deleted file mode 100644 index 9210ece7e..000000000 --- a/trunk/3rdparty/srs-bench/vendor/gopkg.in/yaml.v3/sorter.go +++ /dev/null @@ -1,134 +0,0 @@ -// -// Copyright (c) 2011-2019 Canonical Ltd -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package yaml - -import ( - "reflect" - "unicode" -) - -type keyList []reflect.Value - -func (l keyList) Len() int { return len(l) } -func (l keyList) Swap(i, j int) { l[i], l[j] = l[j], l[i] } -func (l keyList) Less(i, j int) bool { - a := l[i] - b := l[j] - ak := a.Kind() - bk := b.Kind() - for (ak == reflect.Interface || ak == reflect.Ptr) && !a.IsNil() { - a = a.Elem() - ak = a.Kind() - } - for (bk == reflect.Interface || bk == reflect.Ptr) && !b.IsNil() { - b = b.Elem() - bk = b.Kind() - } - af, aok := keyFloat(a) - bf, bok := keyFloat(b) - if aok && bok { - if af != bf { - return af < bf - } - if ak != bk { - return ak < bk - } - return numLess(a, b) - } - if ak != reflect.String || bk != reflect.String { - return ak < bk - } - ar, br := []rune(a.String()), []rune(b.String()) - digits := false - for i := 0; i < len(ar) && i < len(br); i++ { - if ar[i] == br[i] { - digits = unicode.IsDigit(ar[i]) - continue - } - al := unicode.IsLetter(ar[i]) - bl := unicode.IsLetter(br[i]) - if al && bl { - return ar[i] < br[i] - } - if al || bl { - if digits { - return al - } else { - return bl - } - } - var ai, bi int - var an, bn int64 - if ar[i] == '0' || br[i] == '0' { - for j := i - 1; j >= 0 && unicode.IsDigit(ar[j]); j-- { - if ar[j] != '0' { - an = 1 - bn = 1 - break - } - } - } - for ai = i; ai < len(ar) && unicode.IsDigit(ar[ai]); ai++ { - an = an*10 + int64(ar[ai]-'0') - } - for bi = i; bi < len(br) && unicode.IsDigit(br[bi]); bi++ { - bn = bn*10 + int64(br[bi]-'0') - } - if an != bn { - return an < bn - } - if ai != bi { - return ai < bi - } - return ar[i] < br[i] - } - return len(ar) < len(br) -} - -// keyFloat returns a float value for v if it is a number/bool -// and whether it is a number/bool or not. -func keyFloat(v reflect.Value) (f float64, ok bool) { - switch v.Kind() { - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - return float64(v.Int()), true - case reflect.Float32, reflect.Float64: - return v.Float(), true - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - return float64(v.Uint()), true - case reflect.Bool: - if v.Bool() { - return 1, true - } - return 0, true - } - return 0, false -} - -// numLess returns whether a < b. -// a and b must necessarily have the same kind. -func numLess(a, b reflect.Value) bool { - switch a.Kind() { - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - return a.Int() < b.Int() - case reflect.Float32, reflect.Float64: - return a.Float() < b.Float() - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - return a.Uint() < b.Uint() - case reflect.Bool: - return !a.Bool() && b.Bool() - } - panic("not a number") -} diff --git a/trunk/3rdparty/srs-bench/vendor/gopkg.in/yaml.v3/writerc.go b/trunk/3rdparty/srs-bench/vendor/gopkg.in/yaml.v3/writerc.go deleted file mode 100644 index b8a116bf9..000000000 --- a/trunk/3rdparty/srs-bench/vendor/gopkg.in/yaml.v3/writerc.go +++ /dev/null @@ -1,48 +0,0 @@ -// -// Copyright (c) 2011-2019 Canonical Ltd -// Copyright (c) 2006-2010 Kirill Simonov -// -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -// of the Software, and to permit persons to whom the Software is furnished to do -// so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -package yaml - -// Set the writer error and return false. -func yaml_emitter_set_writer_error(emitter *yaml_emitter_t, problem string) bool { - emitter.error = yaml_WRITER_ERROR - emitter.problem = problem - return false -} - -// Flush the output buffer. -func yaml_emitter_flush(emitter *yaml_emitter_t) bool { - if emitter.write_handler == nil { - panic("write handler not set") - } - - // Check if the buffer is empty. - if emitter.buffer_pos == 0 { - return true - } - - if err := emitter.write_handler(emitter, emitter.buffer[:emitter.buffer_pos]); err != nil { - return yaml_emitter_set_writer_error(emitter, "write error: "+err.Error()) - } - emitter.buffer_pos = 0 - return true -} diff --git a/trunk/3rdparty/srs-bench/vendor/gopkg.in/yaml.v3/yaml.go b/trunk/3rdparty/srs-bench/vendor/gopkg.in/yaml.v3/yaml.go deleted file mode 100644 index 8cec6da48..000000000 --- a/trunk/3rdparty/srs-bench/vendor/gopkg.in/yaml.v3/yaml.go +++ /dev/null @@ -1,698 +0,0 @@ -// -// Copyright (c) 2011-2019 Canonical Ltd -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Package yaml implements YAML support for the Go language. -// -// Source code and other details for the project are available at GitHub: -// -// https://github.com/go-yaml/yaml -// -package yaml - -import ( - "errors" - "fmt" - "io" - "reflect" - "strings" - "sync" - "unicode/utf8" -) - -// The Unmarshaler interface may be implemented by types to customize their -// behavior when being unmarshaled from a YAML document. -type Unmarshaler interface { - UnmarshalYAML(value *Node) error -} - -type obsoleteUnmarshaler interface { - UnmarshalYAML(unmarshal func(interface{}) error) error -} - -// The Marshaler interface may be implemented by types to customize their -// behavior when being marshaled into a YAML document. The returned value -// is marshaled in place of the original value implementing Marshaler. -// -// If an error is returned by MarshalYAML, the marshaling procedure stops -// and returns with the provided error. -type Marshaler interface { - MarshalYAML() (interface{}, error) -} - -// Unmarshal decodes the first document found within the in byte slice -// and assigns decoded values into the out value. -// -// Maps and pointers (to a struct, string, int, etc) are accepted as out -// values. If an internal pointer within a struct is not initialized, -// the yaml package will initialize it if necessary for unmarshalling -// the provided data. The out parameter must not be nil. -// -// The type of the decoded values should be compatible with the respective -// values in out. If one or more values cannot be decoded due to a type -// mismatches, decoding continues partially until the end of the YAML -// content, and a *yaml.TypeError is returned with details for all -// missed values. -// -// Struct fields are only unmarshalled if they are exported (have an -// upper case first letter), and are unmarshalled using the field name -// lowercased as the default key. Custom keys may be defined via the -// "yaml" name in the field tag: the content preceding the first comma -// is used as the key, and the following comma-separated options are -// used to tweak the marshalling process (see Marshal). -// Conflicting names result in a runtime error. -// -// For example: -// -// type T struct { -// F int `yaml:"a,omitempty"` -// B int -// } -// var t T -// yaml.Unmarshal([]byte("a: 1\nb: 2"), &t) -// -// See the documentation of Marshal for the format of tags and a list of -// supported tag options. -// -func Unmarshal(in []byte, out interface{}) (err error) { - return unmarshal(in, out, false) -} - -// A Decoder reads and decodes YAML values from an input stream. -type Decoder struct { - parser *parser - knownFields bool -} - -// NewDecoder returns a new decoder that reads from r. -// -// The decoder introduces its own buffering and may read -// data from r beyond the YAML values requested. -func NewDecoder(r io.Reader) *Decoder { - return &Decoder{ - parser: newParserFromReader(r), - } -} - -// KnownFields ensures that the keys in decoded mappings to -// exist as fields in the struct being decoded into. -func (dec *Decoder) KnownFields(enable bool) { - dec.knownFields = enable -} - -// Decode reads the next YAML-encoded value from its input -// and stores it in the value pointed to by v. -// -// See the documentation for Unmarshal for details about the -// conversion of YAML into a Go value. -func (dec *Decoder) Decode(v interface{}) (err error) { - d := newDecoder() - d.knownFields = dec.knownFields - defer handleErr(&err) - node := dec.parser.parse() - if node == nil { - return io.EOF - } - out := reflect.ValueOf(v) - if out.Kind() == reflect.Ptr && !out.IsNil() { - out = out.Elem() - } - d.unmarshal(node, out) - if len(d.terrors) > 0 { - return &TypeError{d.terrors} - } - return nil -} - -// Decode decodes the node and stores its data into the value pointed to by v. -// -// See the documentation for Unmarshal for details about the -// conversion of YAML into a Go value. -func (n *Node) Decode(v interface{}) (err error) { - d := newDecoder() - defer handleErr(&err) - out := reflect.ValueOf(v) - if out.Kind() == reflect.Ptr && !out.IsNil() { - out = out.Elem() - } - d.unmarshal(n, out) - if len(d.terrors) > 0 { - return &TypeError{d.terrors} - } - return nil -} - -func unmarshal(in []byte, out interface{}, strict bool) (err error) { - defer handleErr(&err) - d := newDecoder() - p := newParser(in) - defer p.destroy() - node := p.parse() - if node != nil { - v := reflect.ValueOf(out) - if v.Kind() == reflect.Ptr && !v.IsNil() { - v = v.Elem() - } - d.unmarshal(node, v) - } - if len(d.terrors) > 0 { - return &TypeError{d.terrors} - } - return nil -} - -// Marshal serializes the value provided into a YAML document. The structure -// of the generated document will reflect the structure of the value itself. -// Maps and pointers (to struct, string, int, etc) are accepted as the in value. -// -// Struct fields are only marshalled if they are exported (have an upper case -// first letter), and are marshalled using the field name lowercased as the -// default key. Custom keys may be defined via the "yaml" name in the field -// tag: the content preceding the first comma is used as the key, and the -// following comma-separated options are used to tweak the marshalling process. -// Conflicting names result in a runtime error. -// -// The field tag format accepted is: -// -// `(...) yaml:"[][,[,]]" (...)` -// -// The following flags are currently supported: -// -// omitempty Only include the field if it's not set to the zero -// value for the type or to empty slices or maps. -// Zero valued structs will be omitted if all their public -// fields are zero, unless they implement an IsZero -// method (see the IsZeroer interface type), in which -// case the field will be excluded if IsZero returns true. -// -// flow Marshal using a flow style (useful for structs, -// sequences and maps). -// -// inline Inline the field, which must be a struct or a map, -// causing all of its fields or keys to be processed as if -// they were part of the outer struct. For maps, keys must -// not conflict with the yaml keys of other struct fields. -// -// In addition, if the key is "-", the field is ignored. -// -// For example: -// -// type T struct { -// F int `yaml:"a,omitempty"` -// B int -// } -// yaml.Marshal(&T{B: 2}) // Returns "b: 2\n" -// yaml.Marshal(&T{F: 1}} // Returns "a: 1\nb: 0\n" -// -func Marshal(in interface{}) (out []byte, err error) { - defer handleErr(&err) - e := newEncoder() - defer e.destroy() - e.marshalDoc("", reflect.ValueOf(in)) - e.finish() - out = e.out - return -} - -// An Encoder writes YAML values to an output stream. -type Encoder struct { - encoder *encoder -} - -// NewEncoder returns a new encoder that writes to w. -// The Encoder should be closed after use to flush all data -// to w. -func NewEncoder(w io.Writer) *Encoder { - return &Encoder{ - encoder: newEncoderWithWriter(w), - } -} - -// Encode writes the YAML encoding of v to the stream. -// If multiple items are encoded to the stream, the -// second and subsequent document will be preceded -// with a "---" document separator, but the first will not. -// -// See the documentation for Marshal for details about the conversion of Go -// values to YAML. -func (e *Encoder) Encode(v interface{}) (err error) { - defer handleErr(&err) - e.encoder.marshalDoc("", reflect.ValueOf(v)) - return nil -} - -// Encode encodes value v and stores its representation in n. -// -// See the documentation for Marshal for details about the -// conversion of Go values into YAML. -func (n *Node) Encode(v interface{}) (err error) { - defer handleErr(&err) - e := newEncoder() - defer e.destroy() - e.marshalDoc("", reflect.ValueOf(v)) - e.finish() - p := newParser(e.out) - p.textless = true - defer p.destroy() - doc := p.parse() - *n = *doc.Content[0] - return nil -} - -// SetIndent changes the used indentation used when encoding. -func (e *Encoder) SetIndent(spaces int) { - if spaces < 0 { - panic("yaml: cannot indent to a negative number of spaces") - } - e.encoder.indent = spaces -} - -// Close closes the encoder by writing any remaining data. -// It does not write a stream terminating string "...". -func (e *Encoder) Close() (err error) { - defer handleErr(&err) - e.encoder.finish() - return nil -} - -func handleErr(err *error) { - if v := recover(); v != nil { - if e, ok := v.(yamlError); ok { - *err = e.err - } else { - panic(v) - } - } -} - -type yamlError struct { - err error -} - -func fail(err error) { - panic(yamlError{err}) -} - -func failf(format string, args ...interface{}) { - panic(yamlError{fmt.Errorf("yaml: "+format, args...)}) -} - -// A TypeError is returned by Unmarshal when one or more fields in -// the YAML document cannot be properly decoded into the requested -// types. When this error is returned, the value is still -// unmarshaled partially. -type TypeError struct { - Errors []string -} - -func (e *TypeError) Error() string { - return fmt.Sprintf("yaml: unmarshal errors:\n %s", strings.Join(e.Errors, "\n ")) -} - -type Kind uint32 - -const ( - DocumentNode Kind = 1 << iota - SequenceNode - MappingNode - ScalarNode - AliasNode -) - -type Style uint32 - -const ( - TaggedStyle Style = 1 << iota - DoubleQuotedStyle - SingleQuotedStyle - LiteralStyle - FoldedStyle - FlowStyle -) - -// Node represents an element in the YAML document hierarchy. While documents -// are typically encoded and decoded into higher level types, such as structs -// and maps, Node is an intermediate representation that allows detailed -// control over the content being decoded or encoded. -// -// It's worth noting that although Node offers access into details such as -// line numbers, colums, and comments, the content when re-encoded will not -// have its original textual representation preserved. An effort is made to -// render the data plesantly, and to preserve comments near the data they -// describe, though. -// -// Values that make use of the Node type interact with the yaml package in the -// same way any other type would do, by encoding and decoding yaml data -// directly or indirectly into them. -// -// For example: -// -// var person struct { -// Name string -// Address yaml.Node -// } -// err := yaml.Unmarshal(data, &person) -// -// Or by itself: -// -// var person Node -// err := yaml.Unmarshal(data, &person) -// -type Node struct { - // Kind defines whether the node is a document, a mapping, a sequence, - // a scalar value, or an alias to another node. The specific data type of - // scalar nodes may be obtained via the ShortTag and LongTag methods. - Kind Kind - - // Style allows customizing the apperance of the node in the tree. - Style Style - - // Tag holds the YAML tag defining the data type for the value. - // When decoding, this field will always be set to the resolved tag, - // even when it wasn't explicitly provided in the YAML content. - // When encoding, if this field is unset the value type will be - // implied from the node properties, and if it is set, it will only - // be serialized into the representation if TaggedStyle is used or - // the implicit tag diverges from the provided one. - Tag string - - // Value holds the unescaped and unquoted represenation of the value. - Value string - - // Anchor holds the anchor name for this node, which allows aliases to point to it. - Anchor string - - // Alias holds the node that this alias points to. Only valid when Kind is AliasNode. - Alias *Node - - // Content holds contained nodes for documents, mappings, and sequences. - Content []*Node - - // HeadComment holds any comments in the lines preceding the node and - // not separated by an empty line. - HeadComment string - - // LineComment holds any comments at the end of the line where the node is in. - LineComment string - - // FootComment holds any comments following the node and before empty lines. - FootComment string - - // Line and Column hold the node position in the decoded YAML text. - // These fields are not respected when encoding the node. - Line int - Column int -} - -// IsZero returns whether the node has all of its fields unset. -func (n *Node) IsZero() bool { - return n.Kind == 0 && n.Style == 0 && n.Tag == "" && n.Value == "" && n.Anchor == "" && n.Alias == nil && n.Content == nil && - n.HeadComment == "" && n.LineComment == "" && n.FootComment == "" && n.Line == 0 && n.Column == 0 -} - - -// LongTag returns the long form of the tag that indicates the data type for -// the node. If the Tag field isn't explicitly defined, one will be computed -// based on the node properties. -func (n *Node) LongTag() string { - return longTag(n.ShortTag()) -} - -// ShortTag returns the short form of the YAML tag that indicates data type for -// the node. If the Tag field isn't explicitly defined, one will be computed -// based on the node properties. -func (n *Node) ShortTag() string { - if n.indicatedString() { - return strTag - } - if n.Tag == "" || n.Tag == "!" { - switch n.Kind { - case MappingNode: - return mapTag - case SequenceNode: - return seqTag - case AliasNode: - if n.Alias != nil { - return n.Alias.ShortTag() - } - case ScalarNode: - tag, _ := resolve("", n.Value) - return tag - case 0: - // Special case to make the zero value convenient. - if n.IsZero() { - return nullTag - } - } - return "" - } - return shortTag(n.Tag) -} - -func (n *Node) indicatedString() bool { - return n.Kind == ScalarNode && - (shortTag(n.Tag) == strTag || - (n.Tag == "" || n.Tag == "!") && n.Style&(SingleQuotedStyle|DoubleQuotedStyle|LiteralStyle|FoldedStyle) != 0) -} - -// SetString is a convenience function that sets the node to a string value -// and defines its style in a pleasant way depending on its content. -func (n *Node) SetString(s string) { - n.Kind = ScalarNode - if utf8.ValidString(s) { - n.Value = s - n.Tag = strTag - } else { - n.Value = encodeBase64(s) - n.Tag = binaryTag - } - if strings.Contains(n.Value, "\n") { - n.Style = LiteralStyle - } -} - -// -------------------------------------------------------------------------- -// Maintain a mapping of keys to structure field indexes - -// The code in this section was copied from mgo/bson. - -// structInfo holds details for the serialization of fields of -// a given struct. -type structInfo struct { - FieldsMap map[string]fieldInfo - FieldsList []fieldInfo - - // InlineMap is the number of the field in the struct that - // contains an ,inline map, or -1 if there's none. - InlineMap int - - // InlineUnmarshalers holds indexes to inlined fields that - // contain unmarshaler values. - InlineUnmarshalers [][]int -} - -type fieldInfo struct { - Key string - Num int - OmitEmpty bool - Flow bool - // Id holds the unique field identifier, so we can cheaply - // check for field duplicates without maintaining an extra map. - Id int - - // Inline holds the field index if the field is part of an inlined struct. - Inline []int -} - -var structMap = make(map[reflect.Type]*structInfo) -var fieldMapMutex sync.RWMutex -var unmarshalerType reflect.Type - -func init() { - var v Unmarshaler - unmarshalerType = reflect.ValueOf(&v).Elem().Type() -} - -func getStructInfo(st reflect.Type) (*structInfo, error) { - fieldMapMutex.RLock() - sinfo, found := structMap[st] - fieldMapMutex.RUnlock() - if found { - return sinfo, nil - } - - n := st.NumField() - fieldsMap := make(map[string]fieldInfo) - fieldsList := make([]fieldInfo, 0, n) - inlineMap := -1 - inlineUnmarshalers := [][]int(nil) - for i := 0; i != n; i++ { - field := st.Field(i) - if field.PkgPath != "" && !field.Anonymous { - continue // Private field - } - - info := fieldInfo{Num: i} - - tag := field.Tag.Get("yaml") - if tag == "" && strings.Index(string(field.Tag), ":") < 0 { - tag = string(field.Tag) - } - if tag == "-" { - continue - } - - inline := false - fields := strings.Split(tag, ",") - if len(fields) > 1 { - for _, flag := range fields[1:] { - switch flag { - case "omitempty": - info.OmitEmpty = true - case "flow": - info.Flow = true - case "inline": - inline = true - default: - return nil, errors.New(fmt.Sprintf("unsupported flag %q in tag %q of type %s", flag, tag, st)) - } - } - tag = fields[0] - } - - if inline { - switch field.Type.Kind() { - case reflect.Map: - if inlineMap >= 0 { - return nil, errors.New("multiple ,inline maps in struct " + st.String()) - } - if field.Type.Key() != reflect.TypeOf("") { - return nil, errors.New("option ,inline needs a map with string keys in struct " + st.String()) - } - inlineMap = info.Num - case reflect.Struct, reflect.Ptr: - ftype := field.Type - for ftype.Kind() == reflect.Ptr { - ftype = ftype.Elem() - } - if ftype.Kind() != reflect.Struct { - return nil, errors.New("option ,inline may only be used on a struct or map field") - } - if reflect.PtrTo(ftype).Implements(unmarshalerType) { - inlineUnmarshalers = append(inlineUnmarshalers, []int{i}) - } else { - sinfo, err := getStructInfo(ftype) - if err != nil { - return nil, err - } - for _, index := range sinfo.InlineUnmarshalers { - inlineUnmarshalers = append(inlineUnmarshalers, append([]int{i}, index...)) - } - for _, finfo := range sinfo.FieldsList { - if _, found := fieldsMap[finfo.Key]; found { - msg := "duplicated key '" + finfo.Key + "' in struct " + st.String() - return nil, errors.New(msg) - } - if finfo.Inline == nil { - finfo.Inline = []int{i, finfo.Num} - } else { - finfo.Inline = append([]int{i}, finfo.Inline...) - } - finfo.Id = len(fieldsList) - fieldsMap[finfo.Key] = finfo - fieldsList = append(fieldsList, finfo) - } - } - default: - return nil, errors.New("option ,inline may only be used on a struct or map field") - } - continue - } - - if tag != "" { - info.Key = tag - } else { - info.Key = strings.ToLower(field.Name) - } - - if _, found = fieldsMap[info.Key]; found { - msg := "duplicated key '" + info.Key + "' in struct " + st.String() - return nil, errors.New(msg) - } - - info.Id = len(fieldsList) - fieldsList = append(fieldsList, info) - fieldsMap[info.Key] = info - } - - sinfo = &structInfo{ - FieldsMap: fieldsMap, - FieldsList: fieldsList, - InlineMap: inlineMap, - InlineUnmarshalers: inlineUnmarshalers, - } - - fieldMapMutex.Lock() - structMap[st] = sinfo - fieldMapMutex.Unlock() - return sinfo, nil -} - -// IsZeroer is used to check whether an object is zero to -// determine whether it should be omitted when marshaling -// with the omitempty flag. One notable implementation -// is time.Time. -type IsZeroer interface { - IsZero() bool -} - -func isZero(v reflect.Value) bool { - kind := v.Kind() - if z, ok := v.Interface().(IsZeroer); ok { - if (kind == reflect.Ptr || kind == reflect.Interface) && v.IsNil() { - return true - } - return z.IsZero() - } - switch kind { - case reflect.String: - return len(v.String()) == 0 - case reflect.Interface, reflect.Ptr: - return v.IsNil() - case reflect.Slice: - return v.Len() == 0 - case reflect.Map: - return v.Len() == 0 - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - return v.Int() == 0 - case reflect.Float32, reflect.Float64: - return v.Float() == 0 - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - return v.Uint() == 0 - case reflect.Bool: - return !v.Bool() - case reflect.Struct: - vt := v.Type() - for i := v.NumField() - 1; i >= 0; i-- { - if vt.Field(i).PkgPath != "" { - continue // Private field - } - if !isZero(v.Field(i)) { - return false - } - } - return true - } - return false -} diff --git a/trunk/3rdparty/srs-bench/vendor/gopkg.in/yaml.v3/yamlh.go b/trunk/3rdparty/srs-bench/vendor/gopkg.in/yaml.v3/yamlh.go deleted file mode 100644 index 7c6d00770..000000000 --- a/trunk/3rdparty/srs-bench/vendor/gopkg.in/yaml.v3/yamlh.go +++ /dev/null @@ -1,807 +0,0 @@ -// -// Copyright (c) 2011-2019 Canonical Ltd -// Copyright (c) 2006-2010 Kirill Simonov -// -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -// of the Software, and to permit persons to whom the Software is furnished to do -// so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -package yaml - -import ( - "fmt" - "io" -) - -// The version directive data. -type yaml_version_directive_t struct { - major int8 // The major version number. - minor int8 // The minor version number. -} - -// The tag directive data. -type yaml_tag_directive_t struct { - handle []byte // The tag handle. - prefix []byte // The tag prefix. -} - -type yaml_encoding_t int - -// The stream encoding. -const ( - // Let the parser choose the encoding. - yaml_ANY_ENCODING yaml_encoding_t = iota - - yaml_UTF8_ENCODING // The default UTF-8 encoding. - yaml_UTF16LE_ENCODING // The UTF-16-LE encoding with BOM. - yaml_UTF16BE_ENCODING // The UTF-16-BE encoding with BOM. -) - -type yaml_break_t int - -// Line break types. -const ( - // Let the parser choose the break type. - yaml_ANY_BREAK yaml_break_t = iota - - yaml_CR_BREAK // Use CR for line breaks (Mac style). - yaml_LN_BREAK // Use LN for line breaks (Unix style). - yaml_CRLN_BREAK // Use CR LN for line breaks (DOS style). -) - -type yaml_error_type_t int - -// Many bad things could happen with the parser and emitter. -const ( - // No error is produced. - yaml_NO_ERROR yaml_error_type_t = iota - - yaml_MEMORY_ERROR // Cannot allocate or reallocate a block of memory. - yaml_READER_ERROR // Cannot read or decode the input stream. - yaml_SCANNER_ERROR // Cannot scan the input stream. - yaml_PARSER_ERROR // Cannot parse the input stream. - yaml_COMPOSER_ERROR // Cannot compose a YAML document. - yaml_WRITER_ERROR // Cannot write to the output stream. - yaml_EMITTER_ERROR // Cannot emit a YAML stream. -) - -// The pointer position. -type yaml_mark_t struct { - index int // The position index. - line int // The position line. - column int // The position column. -} - -// Node Styles - -type yaml_style_t int8 - -type yaml_scalar_style_t yaml_style_t - -// Scalar styles. -const ( - // Let the emitter choose the style. - yaml_ANY_SCALAR_STYLE yaml_scalar_style_t = 0 - - yaml_PLAIN_SCALAR_STYLE yaml_scalar_style_t = 1 << iota // The plain scalar style. - yaml_SINGLE_QUOTED_SCALAR_STYLE // The single-quoted scalar style. - yaml_DOUBLE_QUOTED_SCALAR_STYLE // The double-quoted scalar style. - yaml_LITERAL_SCALAR_STYLE // The literal scalar style. - yaml_FOLDED_SCALAR_STYLE // The folded scalar style. -) - -type yaml_sequence_style_t yaml_style_t - -// Sequence styles. -const ( - // Let the emitter choose the style. - yaml_ANY_SEQUENCE_STYLE yaml_sequence_style_t = iota - - yaml_BLOCK_SEQUENCE_STYLE // The block sequence style. - yaml_FLOW_SEQUENCE_STYLE // The flow sequence style. -) - -type yaml_mapping_style_t yaml_style_t - -// Mapping styles. -const ( - // Let the emitter choose the style. - yaml_ANY_MAPPING_STYLE yaml_mapping_style_t = iota - - yaml_BLOCK_MAPPING_STYLE // The block mapping style. - yaml_FLOW_MAPPING_STYLE // The flow mapping style. -) - -// Tokens - -type yaml_token_type_t int - -// Token types. -const ( - // An empty token. - yaml_NO_TOKEN yaml_token_type_t = iota - - yaml_STREAM_START_TOKEN // A STREAM-START token. - yaml_STREAM_END_TOKEN // A STREAM-END token. - - yaml_VERSION_DIRECTIVE_TOKEN // A VERSION-DIRECTIVE token. - yaml_TAG_DIRECTIVE_TOKEN // A TAG-DIRECTIVE token. - yaml_DOCUMENT_START_TOKEN // A DOCUMENT-START token. - yaml_DOCUMENT_END_TOKEN // A DOCUMENT-END token. - - yaml_BLOCK_SEQUENCE_START_TOKEN // A BLOCK-SEQUENCE-START token. - yaml_BLOCK_MAPPING_START_TOKEN // A BLOCK-SEQUENCE-END token. - yaml_BLOCK_END_TOKEN // A BLOCK-END token. - - yaml_FLOW_SEQUENCE_START_TOKEN // A FLOW-SEQUENCE-START token. - yaml_FLOW_SEQUENCE_END_TOKEN // A FLOW-SEQUENCE-END token. - yaml_FLOW_MAPPING_START_TOKEN // A FLOW-MAPPING-START token. - yaml_FLOW_MAPPING_END_TOKEN // A FLOW-MAPPING-END token. - - yaml_BLOCK_ENTRY_TOKEN // A BLOCK-ENTRY token. - yaml_FLOW_ENTRY_TOKEN // A FLOW-ENTRY token. - yaml_KEY_TOKEN // A KEY token. - yaml_VALUE_TOKEN // A VALUE token. - - yaml_ALIAS_TOKEN // An ALIAS token. - yaml_ANCHOR_TOKEN // An ANCHOR token. - yaml_TAG_TOKEN // A TAG token. - yaml_SCALAR_TOKEN // A SCALAR token. -) - -func (tt yaml_token_type_t) String() string { - switch tt { - case yaml_NO_TOKEN: - return "yaml_NO_TOKEN" - case yaml_STREAM_START_TOKEN: - return "yaml_STREAM_START_TOKEN" - case yaml_STREAM_END_TOKEN: - return "yaml_STREAM_END_TOKEN" - case yaml_VERSION_DIRECTIVE_TOKEN: - return "yaml_VERSION_DIRECTIVE_TOKEN" - case yaml_TAG_DIRECTIVE_TOKEN: - return "yaml_TAG_DIRECTIVE_TOKEN" - case yaml_DOCUMENT_START_TOKEN: - return "yaml_DOCUMENT_START_TOKEN" - case yaml_DOCUMENT_END_TOKEN: - return "yaml_DOCUMENT_END_TOKEN" - case yaml_BLOCK_SEQUENCE_START_TOKEN: - return "yaml_BLOCK_SEQUENCE_START_TOKEN" - case yaml_BLOCK_MAPPING_START_TOKEN: - return "yaml_BLOCK_MAPPING_START_TOKEN" - case yaml_BLOCK_END_TOKEN: - return "yaml_BLOCK_END_TOKEN" - case yaml_FLOW_SEQUENCE_START_TOKEN: - return "yaml_FLOW_SEQUENCE_START_TOKEN" - case yaml_FLOW_SEQUENCE_END_TOKEN: - return "yaml_FLOW_SEQUENCE_END_TOKEN" - case yaml_FLOW_MAPPING_START_TOKEN: - return "yaml_FLOW_MAPPING_START_TOKEN" - case yaml_FLOW_MAPPING_END_TOKEN: - return "yaml_FLOW_MAPPING_END_TOKEN" - case yaml_BLOCK_ENTRY_TOKEN: - return "yaml_BLOCK_ENTRY_TOKEN" - case yaml_FLOW_ENTRY_TOKEN: - return "yaml_FLOW_ENTRY_TOKEN" - case yaml_KEY_TOKEN: - return "yaml_KEY_TOKEN" - case yaml_VALUE_TOKEN: - return "yaml_VALUE_TOKEN" - case yaml_ALIAS_TOKEN: - return "yaml_ALIAS_TOKEN" - case yaml_ANCHOR_TOKEN: - return "yaml_ANCHOR_TOKEN" - case yaml_TAG_TOKEN: - return "yaml_TAG_TOKEN" - case yaml_SCALAR_TOKEN: - return "yaml_SCALAR_TOKEN" - } - return "" -} - -// The token structure. -type yaml_token_t struct { - // The token type. - typ yaml_token_type_t - - // The start/end of the token. - start_mark, end_mark yaml_mark_t - - // The stream encoding (for yaml_STREAM_START_TOKEN). - encoding yaml_encoding_t - - // The alias/anchor/scalar value or tag/tag directive handle - // (for yaml_ALIAS_TOKEN, yaml_ANCHOR_TOKEN, yaml_SCALAR_TOKEN, yaml_TAG_TOKEN, yaml_TAG_DIRECTIVE_TOKEN). - value []byte - - // The tag suffix (for yaml_TAG_TOKEN). - suffix []byte - - // The tag directive prefix (for yaml_TAG_DIRECTIVE_TOKEN). - prefix []byte - - // The scalar style (for yaml_SCALAR_TOKEN). - style yaml_scalar_style_t - - // The version directive major/minor (for yaml_VERSION_DIRECTIVE_TOKEN). - major, minor int8 -} - -// Events - -type yaml_event_type_t int8 - -// Event types. -const ( - // An empty event. - yaml_NO_EVENT yaml_event_type_t = iota - - yaml_STREAM_START_EVENT // A STREAM-START event. - yaml_STREAM_END_EVENT // A STREAM-END event. - yaml_DOCUMENT_START_EVENT // A DOCUMENT-START event. - yaml_DOCUMENT_END_EVENT // A DOCUMENT-END event. - yaml_ALIAS_EVENT // An ALIAS event. - yaml_SCALAR_EVENT // A SCALAR event. - yaml_SEQUENCE_START_EVENT // A SEQUENCE-START event. - yaml_SEQUENCE_END_EVENT // A SEQUENCE-END event. - yaml_MAPPING_START_EVENT // A MAPPING-START event. - yaml_MAPPING_END_EVENT // A MAPPING-END event. - yaml_TAIL_COMMENT_EVENT -) - -var eventStrings = []string{ - yaml_NO_EVENT: "none", - yaml_STREAM_START_EVENT: "stream start", - yaml_STREAM_END_EVENT: "stream end", - yaml_DOCUMENT_START_EVENT: "document start", - yaml_DOCUMENT_END_EVENT: "document end", - yaml_ALIAS_EVENT: "alias", - yaml_SCALAR_EVENT: "scalar", - yaml_SEQUENCE_START_EVENT: "sequence start", - yaml_SEQUENCE_END_EVENT: "sequence end", - yaml_MAPPING_START_EVENT: "mapping start", - yaml_MAPPING_END_EVENT: "mapping end", - yaml_TAIL_COMMENT_EVENT: "tail comment", -} - -func (e yaml_event_type_t) String() string { - if e < 0 || int(e) >= len(eventStrings) { - return fmt.Sprintf("unknown event %d", e) - } - return eventStrings[e] -} - -// The event structure. -type yaml_event_t struct { - - // The event type. - typ yaml_event_type_t - - // The start and end of the event. - start_mark, end_mark yaml_mark_t - - // The document encoding (for yaml_STREAM_START_EVENT). - encoding yaml_encoding_t - - // The version directive (for yaml_DOCUMENT_START_EVENT). - version_directive *yaml_version_directive_t - - // The list of tag directives (for yaml_DOCUMENT_START_EVENT). - tag_directives []yaml_tag_directive_t - - // The comments - head_comment []byte - line_comment []byte - foot_comment []byte - tail_comment []byte - - // The anchor (for yaml_SCALAR_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT, yaml_ALIAS_EVENT). - anchor []byte - - // The tag (for yaml_SCALAR_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT). - tag []byte - - // The scalar value (for yaml_SCALAR_EVENT). - value []byte - - // Is the document start/end indicator implicit, or the tag optional? - // (for yaml_DOCUMENT_START_EVENT, yaml_DOCUMENT_END_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT, yaml_SCALAR_EVENT). - implicit bool - - // Is the tag optional for any non-plain style? (for yaml_SCALAR_EVENT). - quoted_implicit bool - - // The style (for yaml_SCALAR_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT). - style yaml_style_t -} - -func (e *yaml_event_t) scalar_style() yaml_scalar_style_t { return yaml_scalar_style_t(e.style) } -func (e *yaml_event_t) sequence_style() yaml_sequence_style_t { return yaml_sequence_style_t(e.style) } -func (e *yaml_event_t) mapping_style() yaml_mapping_style_t { return yaml_mapping_style_t(e.style) } - -// Nodes - -const ( - yaml_NULL_TAG = "tag:yaml.org,2002:null" // The tag !!null with the only possible value: null. - yaml_BOOL_TAG = "tag:yaml.org,2002:bool" // The tag !!bool with the values: true and false. - yaml_STR_TAG = "tag:yaml.org,2002:str" // The tag !!str for string values. - yaml_INT_TAG = "tag:yaml.org,2002:int" // The tag !!int for integer values. - yaml_FLOAT_TAG = "tag:yaml.org,2002:float" // The tag !!float for float values. - yaml_TIMESTAMP_TAG = "tag:yaml.org,2002:timestamp" // The tag !!timestamp for date and time values. - - yaml_SEQ_TAG = "tag:yaml.org,2002:seq" // The tag !!seq is used to denote sequences. - yaml_MAP_TAG = "tag:yaml.org,2002:map" // The tag !!map is used to denote mapping. - - // Not in original libyaml. - yaml_BINARY_TAG = "tag:yaml.org,2002:binary" - yaml_MERGE_TAG = "tag:yaml.org,2002:merge" - - yaml_DEFAULT_SCALAR_TAG = yaml_STR_TAG // The default scalar tag is !!str. - yaml_DEFAULT_SEQUENCE_TAG = yaml_SEQ_TAG // The default sequence tag is !!seq. - yaml_DEFAULT_MAPPING_TAG = yaml_MAP_TAG // The default mapping tag is !!map. -) - -type yaml_node_type_t int - -// Node types. -const ( - // An empty node. - yaml_NO_NODE yaml_node_type_t = iota - - yaml_SCALAR_NODE // A scalar node. - yaml_SEQUENCE_NODE // A sequence node. - yaml_MAPPING_NODE // A mapping node. -) - -// An element of a sequence node. -type yaml_node_item_t int - -// An element of a mapping node. -type yaml_node_pair_t struct { - key int // The key of the element. - value int // The value of the element. -} - -// The node structure. -type yaml_node_t struct { - typ yaml_node_type_t // The node type. - tag []byte // The node tag. - - // The node data. - - // The scalar parameters (for yaml_SCALAR_NODE). - scalar struct { - value []byte // The scalar value. - length int // The length of the scalar value. - style yaml_scalar_style_t // The scalar style. - } - - // The sequence parameters (for YAML_SEQUENCE_NODE). - sequence struct { - items_data []yaml_node_item_t // The stack of sequence items. - style yaml_sequence_style_t // The sequence style. - } - - // The mapping parameters (for yaml_MAPPING_NODE). - mapping struct { - pairs_data []yaml_node_pair_t // The stack of mapping pairs (key, value). - pairs_start *yaml_node_pair_t // The beginning of the stack. - pairs_end *yaml_node_pair_t // The end of the stack. - pairs_top *yaml_node_pair_t // The top of the stack. - style yaml_mapping_style_t // The mapping style. - } - - start_mark yaml_mark_t // The beginning of the node. - end_mark yaml_mark_t // The end of the node. - -} - -// The document structure. -type yaml_document_t struct { - - // The document nodes. - nodes []yaml_node_t - - // The version directive. - version_directive *yaml_version_directive_t - - // The list of tag directives. - tag_directives_data []yaml_tag_directive_t - tag_directives_start int // The beginning of the tag directives list. - tag_directives_end int // The end of the tag directives list. - - start_implicit int // Is the document start indicator implicit? - end_implicit int // Is the document end indicator implicit? - - // The start/end of the document. - start_mark, end_mark yaml_mark_t -} - -// The prototype of a read handler. -// -// The read handler is called when the parser needs to read more bytes from the -// source. The handler should write not more than size bytes to the buffer. -// The number of written bytes should be set to the size_read variable. -// -// [in,out] data A pointer to an application data specified by -// yaml_parser_set_input(). -// [out] buffer The buffer to write the data from the source. -// [in] size The size of the buffer. -// [out] size_read The actual number of bytes read from the source. -// -// On success, the handler should return 1. If the handler failed, -// the returned value should be 0. On EOF, the handler should set the -// size_read to 0 and return 1. -type yaml_read_handler_t func(parser *yaml_parser_t, buffer []byte) (n int, err error) - -// This structure holds information about a potential simple key. -type yaml_simple_key_t struct { - possible bool // Is a simple key possible? - required bool // Is a simple key required? - token_number int // The number of the token. - mark yaml_mark_t // The position mark. -} - -// The states of the parser. -type yaml_parser_state_t int - -const ( - yaml_PARSE_STREAM_START_STATE yaml_parser_state_t = iota - - yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE // Expect the beginning of an implicit document. - yaml_PARSE_DOCUMENT_START_STATE // Expect DOCUMENT-START. - yaml_PARSE_DOCUMENT_CONTENT_STATE // Expect the content of a document. - yaml_PARSE_DOCUMENT_END_STATE // Expect DOCUMENT-END. - yaml_PARSE_BLOCK_NODE_STATE // Expect a block node. - yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE // Expect a block node or indentless sequence. - yaml_PARSE_FLOW_NODE_STATE // Expect a flow node. - yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE // Expect the first entry of a block sequence. - yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE // Expect an entry of a block sequence. - yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE // Expect an entry of an indentless sequence. - yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE // Expect the first key of a block mapping. - yaml_PARSE_BLOCK_MAPPING_KEY_STATE // Expect a block mapping key. - yaml_PARSE_BLOCK_MAPPING_VALUE_STATE // Expect a block mapping value. - yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE // Expect the first entry of a flow sequence. - yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE // Expect an entry of a flow sequence. - yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE // Expect a key of an ordered mapping. - yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE // Expect a value of an ordered mapping. - yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE // Expect the and of an ordered mapping entry. - yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE // Expect the first key of a flow mapping. - yaml_PARSE_FLOW_MAPPING_KEY_STATE // Expect a key of a flow mapping. - yaml_PARSE_FLOW_MAPPING_VALUE_STATE // Expect a value of a flow mapping. - yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE // Expect an empty value of a flow mapping. - yaml_PARSE_END_STATE // Expect nothing. -) - -func (ps yaml_parser_state_t) String() string { - switch ps { - case yaml_PARSE_STREAM_START_STATE: - return "yaml_PARSE_STREAM_START_STATE" - case yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE: - return "yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE" - case yaml_PARSE_DOCUMENT_START_STATE: - return "yaml_PARSE_DOCUMENT_START_STATE" - case yaml_PARSE_DOCUMENT_CONTENT_STATE: - return "yaml_PARSE_DOCUMENT_CONTENT_STATE" - case yaml_PARSE_DOCUMENT_END_STATE: - return "yaml_PARSE_DOCUMENT_END_STATE" - case yaml_PARSE_BLOCK_NODE_STATE: - return "yaml_PARSE_BLOCK_NODE_STATE" - case yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE: - return "yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE" - case yaml_PARSE_FLOW_NODE_STATE: - return "yaml_PARSE_FLOW_NODE_STATE" - case yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE: - return "yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE" - case yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE: - return "yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE" - case yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE: - return "yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE" - case yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE: - return "yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE" - case yaml_PARSE_BLOCK_MAPPING_KEY_STATE: - return "yaml_PARSE_BLOCK_MAPPING_KEY_STATE" - case yaml_PARSE_BLOCK_MAPPING_VALUE_STATE: - return "yaml_PARSE_BLOCK_MAPPING_VALUE_STATE" - case yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE: - return "yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE" - case yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE: - return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE" - case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE: - return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE" - case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE: - return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE" - case yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE: - return "yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE" - case yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE: - return "yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE" - case yaml_PARSE_FLOW_MAPPING_KEY_STATE: - return "yaml_PARSE_FLOW_MAPPING_KEY_STATE" - case yaml_PARSE_FLOW_MAPPING_VALUE_STATE: - return "yaml_PARSE_FLOW_MAPPING_VALUE_STATE" - case yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE: - return "yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE" - case yaml_PARSE_END_STATE: - return "yaml_PARSE_END_STATE" - } - return "" -} - -// This structure holds aliases data. -type yaml_alias_data_t struct { - anchor []byte // The anchor. - index int // The node id. - mark yaml_mark_t // The anchor mark. -} - -// The parser structure. -// -// All members are internal. Manage the structure using the -// yaml_parser_ family of functions. -type yaml_parser_t struct { - - // Error handling - - error yaml_error_type_t // Error type. - - problem string // Error description. - - // The byte about which the problem occurred. - problem_offset int - problem_value int - problem_mark yaml_mark_t - - // The error context. - context string - context_mark yaml_mark_t - - // Reader stuff - - read_handler yaml_read_handler_t // Read handler. - - input_reader io.Reader // File input data. - input []byte // String input data. - input_pos int - - eof bool // EOF flag - - buffer []byte // The working buffer. - buffer_pos int // The current position of the buffer. - - unread int // The number of unread characters in the buffer. - - newlines int // The number of line breaks since last non-break/non-blank character - - raw_buffer []byte // The raw buffer. - raw_buffer_pos int // The current position of the buffer. - - encoding yaml_encoding_t // The input encoding. - - offset int // The offset of the current position (in bytes). - mark yaml_mark_t // The mark of the current position. - - // Comments - - head_comment []byte // The current head comments - line_comment []byte // The current line comments - foot_comment []byte // The current foot comments - tail_comment []byte // Foot comment that happens at the end of a block. - stem_comment []byte // Comment in item preceding a nested structure (list inside list item, etc) - - comments []yaml_comment_t // The folded comments for all parsed tokens - comments_head int - - // Scanner stuff - - stream_start_produced bool // Have we started to scan the input stream? - stream_end_produced bool // Have we reached the end of the input stream? - - flow_level int // The number of unclosed '[' and '{' indicators. - - tokens []yaml_token_t // The tokens queue. - tokens_head int // The head of the tokens queue. - tokens_parsed int // The number of tokens fetched from the queue. - token_available bool // Does the tokens queue contain a token ready for dequeueing. - - indent int // The current indentation level. - indents []int // The indentation levels stack. - - simple_key_allowed bool // May a simple key occur at the current position? - simple_keys []yaml_simple_key_t // The stack of simple keys. - simple_keys_by_tok map[int]int // possible simple_key indexes indexed by token_number - - // Parser stuff - - state yaml_parser_state_t // The current parser state. - states []yaml_parser_state_t // The parser states stack. - marks []yaml_mark_t // The stack of marks. - tag_directives []yaml_tag_directive_t // The list of TAG directives. - - // Dumper stuff - - aliases []yaml_alias_data_t // The alias data. - - document *yaml_document_t // The currently parsed document. -} - -type yaml_comment_t struct { - - scan_mark yaml_mark_t // Position where scanning for comments started - token_mark yaml_mark_t // Position after which tokens will be associated with this comment - start_mark yaml_mark_t // Position of '#' comment mark - end_mark yaml_mark_t // Position where comment terminated - - head []byte - line []byte - foot []byte -} - -// Emitter Definitions - -// The prototype of a write handler. -// -// The write handler is called when the emitter needs to flush the accumulated -// characters to the output. The handler should write @a size bytes of the -// @a buffer to the output. -// -// @param[in,out] data A pointer to an application data specified by -// yaml_emitter_set_output(). -// @param[in] buffer The buffer with bytes to be written. -// @param[in] size The size of the buffer. -// -// @returns On success, the handler should return @c 1. If the handler failed, -// the returned value should be @c 0. -// -type yaml_write_handler_t func(emitter *yaml_emitter_t, buffer []byte) error - -type yaml_emitter_state_t int - -// The emitter states. -const ( - // Expect STREAM-START. - yaml_EMIT_STREAM_START_STATE yaml_emitter_state_t = iota - - yaml_EMIT_FIRST_DOCUMENT_START_STATE // Expect the first DOCUMENT-START or STREAM-END. - yaml_EMIT_DOCUMENT_START_STATE // Expect DOCUMENT-START or STREAM-END. - yaml_EMIT_DOCUMENT_CONTENT_STATE // Expect the content of a document. - yaml_EMIT_DOCUMENT_END_STATE // Expect DOCUMENT-END. - yaml_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE // Expect the first item of a flow sequence. - yaml_EMIT_FLOW_SEQUENCE_TRAIL_ITEM_STATE // Expect the next item of a flow sequence, with the comma already written out - yaml_EMIT_FLOW_SEQUENCE_ITEM_STATE // Expect an item of a flow sequence. - yaml_EMIT_FLOW_MAPPING_FIRST_KEY_STATE // Expect the first key of a flow mapping. - yaml_EMIT_FLOW_MAPPING_TRAIL_KEY_STATE // Expect the next key of a flow mapping, with the comma already written out - yaml_EMIT_FLOW_MAPPING_KEY_STATE // Expect a key of a flow mapping. - yaml_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE // Expect a value for a simple key of a flow mapping. - yaml_EMIT_FLOW_MAPPING_VALUE_STATE // Expect a value of a flow mapping. - yaml_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE // Expect the first item of a block sequence. - yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE // Expect an item of a block sequence. - yaml_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE // Expect the first key of a block mapping. - yaml_EMIT_BLOCK_MAPPING_KEY_STATE // Expect the key of a block mapping. - yaml_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE // Expect a value for a simple key of a block mapping. - yaml_EMIT_BLOCK_MAPPING_VALUE_STATE // Expect a value of a block mapping. - yaml_EMIT_END_STATE // Expect nothing. -) - -// The emitter structure. -// -// All members are internal. Manage the structure using the @c yaml_emitter_ -// family of functions. -type yaml_emitter_t struct { - - // Error handling - - error yaml_error_type_t // Error type. - problem string // Error description. - - // Writer stuff - - write_handler yaml_write_handler_t // Write handler. - - output_buffer *[]byte // String output data. - output_writer io.Writer // File output data. - - buffer []byte // The working buffer. - buffer_pos int // The current position of the buffer. - - raw_buffer []byte // The raw buffer. - raw_buffer_pos int // The current position of the buffer. - - encoding yaml_encoding_t // The stream encoding. - - // Emitter stuff - - canonical bool // If the output is in the canonical style? - best_indent int // The number of indentation spaces. - best_width int // The preferred width of the output lines. - unicode bool // Allow unescaped non-ASCII characters? - line_break yaml_break_t // The preferred line break. - - state yaml_emitter_state_t // The current emitter state. - states []yaml_emitter_state_t // The stack of states. - - events []yaml_event_t // The event queue. - events_head int // The head of the event queue. - - indents []int // The stack of indentation levels. - - tag_directives []yaml_tag_directive_t // The list of tag directives. - - indent int // The current indentation level. - - flow_level int // The current flow level. - - root_context bool // Is it the document root context? - sequence_context bool // Is it a sequence context? - mapping_context bool // Is it a mapping context? - simple_key_context bool // Is it a simple mapping key context? - - line int // The current line. - column int // The current column. - whitespace bool // If the last character was a whitespace? - indention bool // If the last character was an indentation character (' ', '-', '?', ':')? - open_ended bool // If an explicit document end is required? - - space_above bool // Is there's an empty line above? - foot_indent int // The indent used to write the foot comment above, or -1 if none. - - // Anchor analysis. - anchor_data struct { - anchor []byte // The anchor value. - alias bool // Is it an alias? - } - - // Tag analysis. - tag_data struct { - handle []byte // The tag handle. - suffix []byte // The tag suffix. - } - - // Scalar analysis. - scalar_data struct { - value []byte // The scalar value. - multiline bool // Does the scalar contain line breaks? - flow_plain_allowed bool // Can the scalar be expessed in the flow plain style? - block_plain_allowed bool // Can the scalar be expressed in the block plain style? - single_quoted_allowed bool // Can the scalar be expressed in the single quoted style? - block_allowed bool // Can the scalar be expressed in the literal or folded styles? - style yaml_scalar_style_t // The output style. - } - - // Comments - head_comment []byte - line_comment []byte - foot_comment []byte - tail_comment []byte - - key_line_comment []byte - - // Dumper stuff - - opened bool // If the stream was already opened? - closed bool // If the stream was already closed? - - // The information associated with the document nodes. - anchors *struct { - references int // The number of references. - anchor int // The anchor id. - serialized bool // If the node has been emitted? - } - - last_anchor_id int // The last assigned anchor id. - - document *yaml_document_t // The currently emitted document. -} diff --git a/trunk/3rdparty/srs-bench/vendor/gopkg.in/yaml.v3/yamlprivateh.go b/trunk/3rdparty/srs-bench/vendor/gopkg.in/yaml.v3/yamlprivateh.go deleted file mode 100644 index e88f9c54a..000000000 --- a/trunk/3rdparty/srs-bench/vendor/gopkg.in/yaml.v3/yamlprivateh.go +++ /dev/null @@ -1,198 +0,0 @@ -// -// Copyright (c) 2011-2019 Canonical Ltd -// Copyright (c) 2006-2010 Kirill Simonov -// -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -// of the Software, and to permit persons to whom the Software is furnished to do -// so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -package yaml - -const ( - // The size of the input raw buffer. - input_raw_buffer_size = 512 - - // The size of the input buffer. - // It should be possible to decode the whole raw buffer. - input_buffer_size = input_raw_buffer_size * 3 - - // The size of the output buffer. - output_buffer_size = 128 - - // The size of the output raw buffer. - // It should be possible to encode the whole output buffer. - output_raw_buffer_size = (output_buffer_size*2 + 2) - - // The size of other stacks and queues. - initial_stack_size = 16 - initial_queue_size = 16 - initial_string_size = 16 -) - -// Check if the character at the specified position is an alphabetical -// character, a digit, '_', or '-'. -func is_alpha(b []byte, i int) bool { - return b[i] >= '0' && b[i] <= '9' || b[i] >= 'A' && b[i] <= 'Z' || b[i] >= 'a' && b[i] <= 'z' || b[i] == '_' || b[i] == '-' -} - -// Check if the character at the specified position is a digit. -func is_digit(b []byte, i int) bool { - return b[i] >= '0' && b[i] <= '9' -} - -// Get the value of a digit. -func as_digit(b []byte, i int) int { - return int(b[i]) - '0' -} - -// Check if the character at the specified position is a hex-digit. -func is_hex(b []byte, i int) bool { - return b[i] >= '0' && b[i] <= '9' || b[i] >= 'A' && b[i] <= 'F' || b[i] >= 'a' && b[i] <= 'f' -} - -// Get the value of a hex-digit. -func as_hex(b []byte, i int) int { - bi := b[i] - if bi >= 'A' && bi <= 'F' { - return int(bi) - 'A' + 10 - } - if bi >= 'a' && bi <= 'f' { - return int(bi) - 'a' + 10 - } - return int(bi) - '0' -} - -// Check if the character is ASCII. -func is_ascii(b []byte, i int) bool { - return b[i] <= 0x7F -} - -// Check if the character at the start of the buffer can be printed unescaped. -func is_printable(b []byte, i int) bool { - return ((b[i] == 0x0A) || // . == #x0A - (b[i] >= 0x20 && b[i] <= 0x7E) || // #x20 <= . <= #x7E - (b[i] == 0xC2 && b[i+1] >= 0xA0) || // #0xA0 <= . <= #xD7FF - (b[i] > 0xC2 && b[i] < 0xED) || - (b[i] == 0xED && b[i+1] < 0xA0) || - (b[i] == 0xEE) || - (b[i] == 0xEF && // #xE000 <= . <= #xFFFD - !(b[i+1] == 0xBB && b[i+2] == 0xBF) && // && . != #xFEFF - !(b[i+1] == 0xBF && (b[i+2] == 0xBE || b[i+2] == 0xBF)))) -} - -// Check if the character at the specified position is NUL. -func is_z(b []byte, i int) bool { - return b[i] == 0x00 -} - -// Check if the beginning of the buffer is a BOM. -func is_bom(b []byte, i int) bool { - return b[0] == 0xEF && b[1] == 0xBB && b[2] == 0xBF -} - -// Check if the character at the specified position is space. -func is_space(b []byte, i int) bool { - return b[i] == ' ' -} - -// Check if the character at the specified position is tab. -func is_tab(b []byte, i int) bool { - return b[i] == '\t' -} - -// Check if the character at the specified position is blank (space or tab). -func is_blank(b []byte, i int) bool { - //return is_space(b, i) || is_tab(b, i) - return b[i] == ' ' || b[i] == '\t' -} - -// Check if the character at the specified position is a line break. -func is_break(b []byte, i int) bool { - return (b[i] == '\r' || // CR (#xD) - b[i] == '\n' || // LF (#xA) - b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85) - b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028) - b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9) // PS (#x2029) -} - -func is_crlf(b []byte, i int) bool { - return b[i] == '\r' && b[i+1] == '\n' -} - -// Check if the character is a line break or NUL. -func is_breakz(b []byte, i int) bool { - //return is_break(b, i) || is_z(b, i) - return ( - // is_break: - b[i] == '\r' || // CR (#xD) - b[i] == '\n' || // LF (#xA) - b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85) - b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028) - b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029) - // is_z: - b[i] == 0) -} - -// Check if the character is a line break, space, or NUL. -func is_spacez(b []byte, i int) bool { - //return is_space(b, i) || is_breakz(b, i) - return ( - // is_space: - b[i] == ' ' || - // is_breakz: - b[i] == '\r' || // CR (#xD) - b[i] == '\n' || // LF (#xA) - b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85) - b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028) - b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029) - b[i] == 0) -} - -// Check if the character is a line break, space, tab, or NUL. -func is_blankz(b []byte, i int) bool { - //return is_blank(b, i) || is_breakz(b, i) - return ( - // is_blank: - b[i] == ' ' || b[i] == '\t' || - // is_breakz: - b[i] == '\r' || // CR (#xD) - b[i] == '\n' || // LF (#xA) - b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85) - b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028) - b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029) - b[i] == 0) -} - -// Determine the width of the character. -func width(b byte) int { - // Don't replace these by a switch without first - // confirming that it is being inlined. - if b&0x80 == 0x00 { - return 1 - } - if b&0xE0 == 0xC0 { - return 2 - } - if b&0xF0 == 0xE0 { - return 3 - } - if b&0xF8 == 0xF0 { - return 4 - } - return 0 - -} diff --git a/trunk/3rdparty/srs-bench/vendor/modules.txt b/trunk/3rdparty/srs-bench/vendor/modules.txt index 6bc127668..a04d82823 100644 --- a/trunk/3rdparty/srs-bench/vendor/modules.txt +++ b/trunk/3rdparty/srs-bench/vendor/modules.txt @@ -1,6 +1,3 @@ -# github.com/davecgh/go-spew v1.1.1 -## explicit -github.com/davecgh/go-spew/spew # github.com/ghettovoice/gosip v0.0.0-20220929080231-de8ba881be83 ## explicit; go 1.13 github.com/ghettovoice/gosip/log @@ -27,7 +24,7 @@ github.com/gobwas/ws/wsutil github.com/google/gopacket github.com/google/gopacket/layers github.com/google/gopacket/pcapgo -# github.com/google/uuid v1.3.0 +# github.com/google/uuid v1.6.0 ## explicit github.com/google/uuid # github.com/haivision/srtgo v0.0.0-20230627061225-a70d53fcd618 @@ -58,125 +55,126 @@ github.com/ossrs/go-oryx-lib/flv github.com/ossrs/go-oryx-lib/http github.com/ossrs/go-oryx-lib/logger github.com/ossrs/go-oryx-lib/rtmp -# github.com/pion/datachannel v1.5.5 -## explicit; go 1.13 +# github.com/pion/datachannel v1.5.10 +## explicit; go 1.20 github.com/pion/datachannel -# github.com/pion/dtls/v2 v2.2.7 -## explicit; go 1.13 -github.com/pion/dtls/v2 -github.com/pion/dtls/v2/internal/ciphersuite -github.com/pion/dtls/v2/internal/ciphersuite/types -github.com/pion/dtls/v2/internal/closer -github.com/pion/dtls/v2/internal/util -github.com/pion/dtls/v2/pkg/crypto/ccm -github.com/pion/dtls/v2/pkg/crypto/ciphersuite -github.com/pion/dtls/v2/pkg/crypto/clientcertificate -github.com/pion/dtls/v2/pkg/crypto/elliptic -github.com/pion/dtls/v2/pkg/crypto/fingerprint -github.com/pion/dtls/v2/pkg/crypto/hash -github.com/pion/dtls/v2/pkg/crypto/prf -github.com/pion/dtls/v2/pkg/crypto/signature -github.com/pion/dtls/v2/pkg/crypto/signaturehash -github.com/pion/dtls/v2/pkg/protocol -github.com/pion/dtls/v2/pkg/protocol/alert -github.com/pion/dtls/v2/pkg/protocol/extension -github.com/pion/dtls/v2/pkg/protocol/handshake -github.com/pion/dtls/v2/pkg/protocol/recordlayer -# github.com/pion/ice/v2 v2.3.6 -## explicit; go 1.13 -github.com/pion/ice/v2 -github.com/pion/ice/v2/internal/atomic -github.com/pion/ice/v2/internal/fakenet -github.com/pion/ice/v2/internal/stun -# github.com/pion/interceptor v0.1.17 -## explicit; go 1.15 +# github.com/pion/dtls/v3 v3.0.6 +## explicit; go 1.20 +github.com/pion/dtls/v3 +github.com/pion/dtls/v3/internal/ciphersuite +github.com/pion/dtls/v3/internal/ciphersuite/types +github.com/pion/dtls/v3/internal/closer +github.com/pion/dtls/v3/internal/net +github.com/pion/dtls/v3/internal/net/udp +github.com/pion/dtls/v3/internal/util +github.com/pion/dtls/v3/pkg/crypto/ccm +github.com/pion/dtls/v3/pkg/crypto/ciphersuite +github.com/pion/dtls/v3/pkg/crypto/clientcertificate +github.com/pion/dtls/v3/pkg/crypto/elliptic +github.com/pion/dtls/v3/pkg/crypto/fingerprint +github.com/pion/dtls/v3/pkg/crypto/hash +github.com/pion/dtls/v3/pkg/crypto/prf +github.com/pion/dtls/v3/pkg/crypto/signature +github.com/pion/dtls/v3/pkg/crypto/signaturehash +github.com/pion/dtls/v3/pkg/net +github.com/pion/dtls/v3/pkg/protocol +github.com/pion/dtls/v3/pkg/protocol/alert +github.com/pion/dtls/v3/pkg/protocol/extension +github.com/pion/dtls/v3/pkg/protocol/handshake +github.com/pion/dtls/v3/pkg/protocol/recordlayer +# github.com/pion/ice/v4 v4.0.10 +## explicit; go 1.20 +github.com/pion/ice/v4 +github.com/pion/ice/v4/internal/atomic +github.com/pion/ice/v4/internal/fakenet +github.com/pion/ice/v4/internal/stun +github.com/pion/ice/v4/internal/taskloop +# github.com/pion/interceptor v0.1.37 +## explicit; go 1.20 github.com/pion/interceptor github.com/pion/interceptor/internal/ntp +github.com/pion/interceptor/internal/sequencenumber github.com/pion/interceptor/pkg/nack github.com/pion/interceptor/pkg/report +github.com/pion/interceptor/pkg/rfc8888 github.com/pion/interceptor/pkg/twcc -# github.com/pion/logging v0.2.2 -## explicit; go 1.12 +# github.com/pion/logging v0.2.3 +## explicit; go 1.20 github.com/pion/logging -# github.com/pion/mdns v0.0.7 -## explicit; go 1.12 -github.com/pion/mdns +# github.com/pion/mdns/v2 v2.0.7 +## explicit; go 1.19 +github.com/pion/mdns/v2 # github.com/pion/randutil v0.1.0 ## explicit; go 1.14 github.com/pion/randutil -# github.com/pion/rtcp v1.2.10 -## explicit; go 1.13 +# github.com/pion/rtcp v1.2.15 +## explicit; go 1.20 github.com/pion/rtcp -# github.com/pion/rtp v1.7.13 -## explicit; go 1.13 +# github.com/pion/rtp v1.8.15 +## explicit; go 1.20 github.com/pion/rtp github.com/pion/rtp/codecs -github.com/pion/rtp/pkg/frame -github.com/pion/rtp/pkg/obu -# github.com/pion/sctp v1.8.7 -## explicit; go 1.13 +github.com/pion/rtp/codecs/av1/obu +github.com/pion/rtp/codecs/vp9 +# github.com/pion/sctp v1.8.39 +## explicit; go 1.20 github.com/pion/sctp -# github.com/pion/sdp/v3 v3.0.6 -## explicit; go 1.13 +# github.com/pion/sdp/v3 v3.0.11 +## explicit; go 1.20 github.com/pion/sdp/v3 -# github.com/pion/srtp/v2 v2.0.15 -## explicit; go 1.14 -github.com/pion/srtp/v2 -# github.com/pion/stun v0.6.0 -## explicit; go 1.12 -github.com/pion/stun -github.com/pion/stun/internal/hmac -# github.com/pion/transport/v2 v2.2.1 -## explicit; go 1.12 -github.com/pion/transport/v2 -github.com/pion/transport/v2/connctx -github.com/pion/transport/v2/deadline -github.com/pion/transport/v2/packetio -github.com/pion/transport/v2/replaydetector -github.com/pion/transport/v2/stdnet -github.com/pion/transport/v2/udp -github.com/pion/transport/v2/utils/xor -github.com/pion/transport/v2/vnet -# github.com/pion/turn/v2 v2.1.0 -## explicit; go 1.13 -github.com/pion/turn/v2 -github.com/pion/turn/v2/internal/allocation -github.com/pion/turn/v2/internal/client -github.com/pion/turn/v2/internal/ipnet -github.com/pion/turn/v2/internal/proto -github.com/pion/turn/v2/internal/server -# github.com/pion/webrtc/v3 v3.2.9 -## explicit; go 1.13 -github.com/pion/webrtc/v3 -github.com/pion/webrtc/v3/internal/fmtp -github.com/pion/webrtc/v3/internal/mux -github.com/pion/webrtc/v3/internal/util -github.com/pion/webrtc/v3/pkg/media -github.com/pion/webrtc/v3/pkg/media/h264reader -github.com/pion/webrtc/v3/pkg/media/h264writer -github.com/pion/webrtc/v3/pkg/media/ivfwriter -github.com/pion/webrtc/v3/pkg/media/oggreader -github.com/pion/webrtc/v3/pkg/media/oggwriter -github.com/pion/webrtc/v3/pkg/rtcerr +# github.com/pion/srtp/v3 v3.0.4 +## explicit; go 1.20 +github.com/pion/srtp/v3 +# github.com/pion/stun/v3 v3.0.0 +## explicit; go 1.19 +github.com/pion/stun/v3 +github.com/pion/stun/v3/internal/hmac +# github.com/pion/transport/v3 v3.0.7 +## explicit; go 1.19 +github.com/pion/transport/v3 +github.com/pion/transport/v3/deadline +github.com/pion/transport/v3/netctx +github.com/pion/transport/v3/packetio +github.com/pion/transport/v3/replaydetector +github.com/pion/transport/v3/stdnet +github.com/pion/transport/v3/utils/xor +github.com/pion/transport/v3/vnet +# github.com/pion/turn/v4 v4.0.0 +## explicit; go 1.19 +github.com/pion/turn/v4 +github.com/pion/turn/v4/internal/allocation +github.com/pion/turn/v4/internal/client +github.com/pion/turn/v4/internal/ipnet +github.com/pion/turn/v4/internal/proto +github.com/pion/turn/v4/internal/server +# github.com/pion/webrtc/v4 v4.1.1 +## explicit; go 1.20 +github.com/pion/webrtc/v4 +github.com/pion/webrtc/v4/internal/fmtp +github.com/pion/webrtc/v4/internal/mux +github.com/pion/webrtc/v4/internal/util +github.com/pion/webrtc/v4/pkg/media +github.com/pion/webrtc/v4/pkg/media/h264reader +github.com/pion/webrtc/v4/pkg/media/h264writer +github.com/pion/webrtc/v4/pkg/media/ivfwriter +github.com/pion/webrtc/v4/pkg/media/oggreader +github.com/pion/webrtc/v4/pkg/media/oggwriter +github.com/pion/webrtc/v4/pkg/rtcerr # github.com/pkg/errors v0.9.1 ## explicit github.com/pkg/errors -# github.com/pmezard/go-difflib v1.0.0 -## explicit -github.com/pmezard/go-difflib/difflib # github.com/satori/go.uuid v1.2.1-0.20181028125025-b2ce2384e17b ## explicit github.com/satori/go.uuid # github.com/sirupsen/logrus v1.4.2 ## explicit github.com/sirupsen/logrus -# github.com/stretchr/testify v1.9.0 -## explicit; go 1.17 -github.com/stretchr/testify/assert -github.com/stretchr/testify/require # github.com/tevino/abool v0.0.0-20170917061928-9b9efcf221b5 ## explicit github.com/tevino/abool +# github.com/wlynxg/anet v0.0.5 +## explicit; go 1.20 +github.com/wlynxg/anet # github.com/x-cray/logrus-prefixed-formatter v0.5.2 ## explicit github.com/x-cray/logrus-prefixed-formatter @@ -186,14 +184,13 @@ github.com/yapingcat/gomedia/codec # github.com/yapingcat/gomedia/mpeg2 v0.0.0-20220617074658-94762898dc25 ## explicit; go 1.16 github.com/yapingcat/gomedia/mpeg2 -# golang.org/x/crypto v0.21.0 -## explicit; go 1.18 +# golang.org/x/crypto v0.33.0 +## explicit; go 1.20 golang.org/x/crypto/cryptobyte golang.org/x/crypto/cryptobyte/asn1 golang.org/x/crypto/curve25519 -golang.org/x/crypto/curve25519/internal/field golang.org/x/crypto/ssh/terminal -# golang.org/x/net v0.21.0 +# golang.org/x/net v0.35.0 ## explicit; go 1.18 golang.org/x/net/bpf golang.org/x/net/dns/dnsmessage @@ -201,16 +198,14 @@ golang.org/x/net/internal/iana golang.org/x/net/internal/socket golang.org/x/net/internal/socks golang.org/x/net/ipv4 +golang.org/x/net/ipv6 golang.org/x/net/proxy -# golang.org/x/sys v0.18.0 +# golang.org/x/sys v0.30.0 ## explicit; go 1.18 golang.org/x/sys/cpu golang.org/x/sys/plan9 golang.org/x/sys/unix golang.org/x/sys/windows -# golang.org/x/term v0.18.0 +# golang.org/x/term v0.29.0 ## explicit; go 1.18 golang.org/x/term -# gopkg.in/yaml.v3 v3.0.1 -## explicit -gopkg.in/yaml.v3 diff --git a/trunk/3rdparty/srs-bench/vnet/example_udpproxy_test.go b/trunk/3rdparty/srs-bench/vnet/example_udpproxy_test.go index 0ba6aa54a..57e35a200 100644 --- a/trunk/3rdparty/srs-bench/vnet/example_udpproxy_test.go +++ b/trunk/3rdparty/srs-bench/vnet/example_udpproxy_test.go @@ -25,7 +25,7 @@ import ( vnet_proxy "github.com/ossrs/srs-bench/vnet" "github.com/pion/logging" - "github.com/pion/transport/v2/vnet" + "github.com/pion/transport/v3/vnet" ) // Proxy many vnet endpoint to one real server endpoint. diff --git a/trunk/3rdparty/srs-bench/vnet/vnet.go b/trunk/3rdparty/srs-bench/vnet/vnet.go index 20c45d979..845410eee 100644 --- a/trunk/3rdparty/srs-bench/vnet/vnet.go +++ b/trunk/3rdparty/srs-bench/vnet/vnet.go @@ -21,7 +21,7 @@ package vnet import ( - "github.com/pion/transport/v2/vnet" + "github.com/pion/transport/v3/vnet" ) type Router = vnet.Router diff --git a/trunk/doc/CHANGELOG.md b/trunk/doc/CHANGELOG.md index e8d08d468..556e78acc 100644 --- a/trunk/doc/CHANGELOG.md +++ b/trunk/doc/CHANGELOG.md @@ -7,6 +7,7 @@ The changelog for SRS. ## SRS 7.0 Changelog +* v7.0, 2025-05-26, Merge [#4359](https://github.com/ossrs/srs/pull/4359): update pion/webrtc to v4. v7.0.34 (#4359) * v7.0, 2025-05-13, Merge [#4289](https://github.com/ossrs/srs/pull/4289): rtmp2rtc: Support RTMP-to-WebRTC conversion with HEVC. v7.0.33 (#4289) * v7.0, 2025-04-30, Merge [#4308](https://github.com/ossrs/srs/pull/4308): Fix memory leaks from errors skipping resource release. v7.0.32 (#4308) * v7.0, 2025-04-26, Merge [#4292](https://github.com/ossrs/srs/pull/4309): Support custom deleter for SrsUniquePtr. v7.0.31 (#4309) diff --git a/trunk/src/core/srs_core_version7.hpp b/trunk/src/core/srs_core_version7.hpp index 6e9507f88..aadc2f8e5 100644 --- a/trunk/src/core/srs_core_version7.hpp +++ b/trunk/src/core/srs_core_version7.hpp @@ -9,6 +9,6 @@ #define VERSION_MAJOR 7 #define VERSION_MINOR 0 -#define VERSION_REVISION 33 +#define VERSION_REVISION 34 #endif \ No newline at end of file