Copy disabled (too large)
Download .txt
Showing preview only (10,056K chars total). Download the full file to get everything.
Repository: datarhei/gosrt
Branch: main
Commit: 6ab34b20337a
Files: 722
Total size: 9.4 MB
Directory structure:
gitextract_58kqutjt/
├── .dockerignore
├── .editorconfig
├── .github/
│ ├── dependabot.yml
│ └── workflows/
│ ├── codeql-analysis.yml
│ └── go-tests.yml
├── .gitignore
├── CODE_OF_CONDUCT.md
├── Dockerfile
├── LICENSE
├── Makefile
├── README.md
├── SECURITY.md
├── circular/
│ ├── circular.go
│ └── circular_test.go
├── config.go
├── config_test.go
├── congestion/
│ ├── congestion.go
│ └── live/
│ ├── doc.go
│ ├── fake.go
│ ├── receive.go
│ ├── receive_test.go
│ ├── send.go
│ └── send_test.go
├── conn_request.go
├── connection.go
├── connection_test.go
├── contrib/
│ ├── client/
│ │ ├── main.go
│ │ ├── reader.go
│ │ └── writer.go
│ └── server/
│ └── main.go
├── crypto/
│ ├── crypto.go
│ └── crypto_test.go
├── dial.go
├── dial_test.go
├── doc.go
├── go.mod
├── go.sum
├── listen.go
├── listen_test.go
├── log.go
├── log_test.go
├── net/
│ ├── ip.go
│ ├── ip_test.go
│ ├── syncookie.go
│ └── syncookie_test.go
├── net.go
├── net_windows.go
├── packet/
│ ├── packet.go
│ └── packet_test.go
├── packet_conn.go
├── pubsub.go
├── pubsub_test.go
├── rand/
│ ├── rand.go
│ └── rand_test.go
├── server.go
├── server_test.go
├── statistics.go
└── vendor/
├── github.com/
│ ├── benburkert/
│ │ └── openpgp/
│ │ └── aes/
│ │ └── keywrap/
│ │ ├── doc.go
│ │ └── keywrap.go
│ ├── davecgh/
│ │ └── go-spew/
│ │ ├── LICENSE
│ │ └── spew/
│ │ ├── bypass.go
│ │ ├── bypasssafe.go
│ │ ├── common.go
│ │ ├── config.go
│ │ ├── doc.go
│ │ ├── dump.go
│ │ ├── format.go
│ │ └── spew.go
│ ├── felixge/
│ │ └── fgprof/
│ │ ├── BenchmarkProfilerGoroutines.txt
│ │ ├── LICENSE.txt
│ │ ├── README.md
│ │ ├── fgprof.go
│ │ └── handler.go
│ ├── google/
│ │ └── pprof/
│ │ ├── AUTHORS
│ │ ├── CONTRIBUTORS
│ │ ├── LICENSE
│ │ └── profile/
│ │ ├── encode.go
│ │ ├── filter.go
│ │ ├── index.go
│ │ ├── legacy_java_profile.go
│ │ ├── legacy_profile.go
│ │ ├── merge.go
│ │ ├── profile.go
│ │ ├── proto.go
│ │ └── prune.go
│ ├── pkg/
│ │ └── profile/
│ │ ├── .travis.yml
│ │ ├── AUTHORS
│ │ ├── LICENSE
│ │ ├── README.md
│ │ └── profile.go
│ ├── pmezard/
│ │ └── go-difflib/
│ │ ├── LICENSE
│ │ └── difflib/
│ │ └── difflib.go
│ └── stretchr/
│ └── testify/
│ ├── LICENSE
│ ├── assert/
│ │ ├── assertion_compare.go
│ │ ├── assertion_format.go
│ │ ├── assertion_format.go.tmpl
│ │ ├── assertion_forward.go
│ │ ├── assertion_forward.go.tmpl
│ │ ├── assertion_order.go
│ │ ├── assertions.go
│ │ ├── doc.go
│ │ ├── errors.go
│ │ ├── forward_assertions.go
│ │ ├── http_assertions.go
│ │ └── yaml/
│ │ ├── yaml_custom.go
│ │ ├── yaml_default.go
│ │ └── yaml_fail.go
│ └── require/
│ ├── doc.go
│ ├── forward_requirements.go
│ ├── require.go
│ ├── require.go.tmpl
│ ├── require_forward.go
│ ├── require_forward.go.tmpl
│ └── requirements.go
├── golang.org/
│ └── x/
│ ├── net/
│ │ ├── LICENSE
│ │ ├── PATENTS
│ │ ├── bpf/
│ │ │ ├── asm.go
│ │ │ ├── constants.go
│ │ │ ├── doc.go
│ │ │ ├── instructions.go
│ │ │ ├── setter.go
│ │ │ ├── vm.go
│ │ │ └── vm_instructions.go
│ │ ├── internal/
│ │ │ ├── iana/
│ │ │ │ └── const.go
│ │ │ └── socket/
│ │ │ ├── cmsghdr.go
│ │ │ ├── cmsghdr_bsd.go
│ │ │ ├── cmsghdr_linux_32bit.go
│ │ │ ├── cmsghdr_linux_64bit.go
│ │ │ ├── cmsghdr_solaris_64bit.go
│ │ │ ├── cmsghdr_stub.go
│ │ │ ├── cmsghdr_unix.go
│ │ │ ├── cmsghdr_zos_s390x.go
│ │ │ ├── complete_dontwait.go
│ │ │ ├── complete_nodontwait.go
│ │ │ ├── empty.s
│ │ │ ├── error_unix.go
│ │ │ ├── error_windows.go
│ │ │ ├── iovec_32bit.go
│ │ │ ├── iovec_64bit.go
│ │ │ ├── iovec_solaris_64bit.go
│ │ │ ├── iovec_stub.go
│ │ │ ├── mmsghdr_stub.go
│ │ │ ├── mmsghdr_unix.go
│ │ │ ├── msghdr_bsd.go
│ │ │ ├── msghdr_bsdvar.go
│ │ │ ├── msghdr_linux.go
│ │ │ ├── msghdr_linux_32bit.go
│ │ │ ├── msghdr_linux_64bit.go
│ │ │ ├── msghdr_openbsd.go
│ │ │ ├── msghdr_solaris_64bit.go
│ │ │ ├── msghdr_stub.go
│ │ │ ├── msghdr_zos_s390x.go
│ │ │ ├── norace.go
│ │ │ ├── race.go
│ │ │ ├── rawconn.go
│ │ │ ├── rawconn_mmsg.go
│ │ │ ├── rawconn_msg.go
│ │ │ ├── rawconn_nommsg.go
│ │ │ ├── rawconn_nomsg.go
│ │ │ ├── socket.go
│ │ │ ├── sys_bsd.go
│ │ │ ├── sys_const_unix.go
│ │ │ ├── sys_linux.go
│ │ │ ├── sys_linux_386.go
│ │ │ ├── sys_linux_386.s
│ │ │ ├── sys_linux_amd64.go
│ │ │ ├── sys_linux_arm.go
│ │ │ ├── sys_linux_arm64.go
│ │ │ ├── sys_linux_loong64.go
│ │ │ ├── sys_linux_mips.go
│ │ │ ├── sys_linux_mips64.go
│ │ │ ├── sys_linux_mips64le.go
│ │ │ ├── sys_linux_mipsle.go
│ │ │ ├── sys_linux_ppc.go
│ │ │ ├── sys_linux_ppc64.go
│ │ │ ├── sys_linux_ppc64le.go
│ │ │ ├── sys_linux_riscv64.go
│ │ │ ├── sys_linux_s390x.go
│ │ │ ├── sys_linux_s390x.s
│ │ │ ├── sys_netbsd.go
│ │ │ ├── sys_posix.go
│ │ │ ├── sys_stub.go
│ │ │ ├── sys_unix.go
│ │ │ ├── sys_windows.go
│ │ │ ├── sys_zos_s390x.go
│ │ │ ├── sys_zos_s390x.s
│ │ │ ├── zsys_aix_ppc64.go
│ │ │ ├── zsys_darwin_amd64.go
│ │ │ ├── zsys_darwin_arm64.go
│ │ │ ├── zsys_dragonfly_amd64.go
│ │ │ ├── zsys_freebsd_386.go
│ │ │ ├── zsys_freebsd_amd64.go
│ │ │ ├── zsys_freebsd_arm.go
│ │ │ ├── zsys_freebsd_arm64.go
│ │ │ ├── zsys_freebsd_riscv64.go
│ │ │ ├── zsys_linux_386.go
│ │ │ ├── zsys_linux_amd64.go
│ │ │ ├── zsys_linux_arm.go
│ │ │ ├── zsys_linux_arm64.go
│ │ │ ├── zsys_linux_loong64.go
│ │ │ ├── zsys_linux_mips.go
│ │ │ ├── zsys_linux_mips64.go
│ │ │ ├── zsys_linux_mips64le.go
│ │ │ ├── zsys_linux_mipsle.go
│ │ │ ├── zsys_linux_ppc.go
│ │ │ ├── zsys_linux_ppc64.go
│ │ │ ├── zsys_linux_ppc64le.go
│ │ │ ├── zsys_linux_riscv64.go
│ │ │ ├── zsys_linux_s390x.go
│ │ │ ├── zsys_netbsd_386.go
│ │ │ ├── zsys_netbsd_amd64.go
│ │ │ ├── zsys_netbsd_arm.go
│ │ │ ├── zsys_netbsd_arm64.go
│ │ │ ├── zsys_openbsd_386.go
│ │ │ ├── zsys_openbsd_amd64.go
│ │ │ ├── zsys_openbsd_arm.go
│ │ │ ├── zsys_openbsd_arm64.go
│ │ │ ├── zsys_openbsd_mips64.go
│ │ │ ├── zsys_openbsd_ppc64.go
│ │ │ ├── zsys_openbsd_riscv64.go
│ │ │ ├── zsys_solaris_amd64.go
│ │ │ └── zsys_zos_s390x.go
│ │ ├── ipv4/
│ │ │ ├── batch.go
│ │ │ ├── control.go
│ │ │ ├── control_bsd.go
│ │ │ ├── control_pktinfo.go
│ │ │ ├── control_stub.go
│ │ │ ├── control_unix.go
│ │ │ ├── control_windows.go
│ │ │ ├── control_zos.go
│ │ │ ├── dgramopt.go
│ │ │ ├── doc.go
│ │ │ ├── endpoint.go
│ │ │ ├── genericopt.go
│ │ │ ├── header.go
│ │ │ ├── helper.go
│ │ │ ├── iana.go
│ │ │ ├── icmp.go
│ │ │ ├── icmp_linux.go
│ │ │ ├── icmp_stub.go
│ │ │ ├── packet.go
│ │ │ ├── payload.go
│ │ │ ├── payload_cmsg.go
│ │ │ ├── payload_nocmsg.go
│ │ │ ├── sockopt.go
│ │ │ ├── sockopt_posix.go
│ │ │ ├── sockopt_stub.go
│ │ │ ├── sys_aix.go
│ │ │ ├── sys_asmreq.go
│ │ │ ├── sys_asmreq_stub.go
│ │ │ ├── sys_asmreqn.go
│ │ │ ├── sys_asmreqn_stub.go
│ │ │ ├── sys_bpf.go
│ │ │ ├── sys_bpf_stub.go
│ │ │ ├── sys_bsd.go
│ │ │ ├── sys_darwin.go
│ │ │ ├── sys_dragonfly.go
│ │ │ ├── sys_freebsd.go
│ │ │ ├── sys_linux.go
│ │ │ ├── sys_solaris.go
│ │ │ ├── sys_ssmreq.go
│ │ │ ├── sys_ssmreq_stub.go
│ │ │ ├── sys_stub.go
│ │ │ ├── sys_windows.go
│ │ │ ├── sys_zos.go
│ │ │ ├── zsys_aix_ppc64.go
│ │ │ ├── zsys_darwin.go
│ │ │ ├── zsys_dragonfly.go
│ │ │ ├── zsys_freebsd_386.go
│ │ │ ├── zsys_freebsd_amd64.go
│ │ │ ├── zsys_freebsd_arm.go
│ │ │ ├── zsys_freebsd_arm64.go
│ │ │ ├── zsys_freebsd_riscv64.go
│ │ │ ├── zsys_linux_386.go
│ │ │ ├── zsys_linux_amd64.go
│ │ │ ├── zsys_linux_arm.go
│ │ │ ├── zsys_linux_arm64.go
│ │ │ ├── zsys_linux_loong64.go
│ │ │ ├── zsys_linux_mips.go
│ │ │ ├── zsys_linux_mips64.go
│ │ │ ├── zsys_linux_mips64le.go
│ │ │ ├── zsys_linux_mipsle.go
│ │ │ ├── zsys_linux_ppc.go
│ │ │ ├── zsys_linux_ppc64.go
│ │ │ ├── zsys_linux_ppc64le.go
│ │ │ ├── zsys_linux_riscv64.go
│ │ │ ├── zsys_linux_s390x.go
│ │ │ ├── zsys_netbsd.go
│ │ │ ├── zsys_openbsd.go
│ │ │ ├── zsys_solaris.go
│ │ │ └── zsys_zos_s390x.go
│ │ └── ipv6/
│ │ ├── batch.go
│ │ ├── control.go
│ │ ├── control_rfc2292_unix.go
│ │ ├── control_rfc3542_unix.go
│ │ ├── control_stub.go
│ │ ├── control_unix.go
│ │ ├── control_windows.go
│ │ ├── dgramopt.go
│ │ ├── doc.go
│ │ ├── endpoint.go
│ │ ├── genericopt.go
│ │ ├── header.go
│ │ ├── helper.go
│ │ ├── iana.go
│ │ ├── icmp.go
│ │ ├── icmp_bsd.go
│ │ ├── icmp_linux.go
│ │ ├── icmp_solaris.go
│ │ ├── icmp_stub.go
│ │ ├── icmp_windows.go
│ │ ├── icmp_zos.go
│ │ ├── payload.go
│ │ ├── payload_cmsg.go
│ │ ├── payload_nocmsg.go
│ │ ├── sockopt.go
│ │ ├── sockopt_posix.go
│ │ ├── sockopt_stub.go
│ │ ├── sys_aix.go
│ │ ├── sys_asmreq.go
│ │ ├── sys_asmreq_stub.go
│ │ ├── sys_bpf.go
│ │ ├── sys_bpf_stub.go
│ │ ├── sys_bsd.go
│ │ ├── sys_darwin.go
│ │ ├── sys_freebsd.go
│ │ ├── sys_linux.go
│ │ ├── sys_solaris.go
│ │ ├── sys_ssmreq.go
│ │ ├── sys_ssmreq_stub.go
│ │ ├── sys_stub.go
│ │ ├── sys_windows.go
│ │ ├── sys_zos.go
│ │ ├── zsys_aix_ppc64.go
│ │ ├── zsys_darwin.go
│ │ ├── zsys_dragonfly.go
│ │ ├── zsys_freebsd_386.go
│ │ ├── zsys_freebsd_amd64.go
│ │ ├── zsys_freebsd_arm.go
│ │ ├── zsys_freebsd_arm64.go
│ │ ├── zsys_freebsd_riscv64.go
│ │ ├── zsys_linux_386.go
│ │ ├── zsys_linux_amd64.go
│ │ ├── zsys_linux_arm.go
│ │ ├── zsys_linux_arm64.go
│ │ ├── zsys_linux_loong64.go
│ │ ├── zsys_linux_mips.go
│ │ ├── zsys_linux_mips64.go
│ │ ├── zsys_linux_mips64le.go
│ │ ├── zsys_linux_mipsle.go
│ │ ├── zsys_linux_ppc.go
│ │ ├── zsys_linux_ppc64.go
│ │ ├── zsys_linux_ppc64le.go
│ │ ├── zsys_linux_riscv64.go
│ │ ├── zsys_linux_s390x.go
│ │ ├── zsys_netbsd.go
│ │ ├── zsys_openbsd.go
│ │ ├── zsys_solaris.go
│ │ └── zsys_zos_s390x.go
│ └── sys/
│ ├── LICENSE
│ ├── PATENTS
│ ├── unix/
│ │ ├── .gitignore
│ │ ├── README.md
│ │ ├── affinity_linux.go
│ │ ├── aliases.go
│ │ ├── asm_aix_ppc64.s
│ │ ├── asm_bsd_386.s
│ │ ├── asm_bsd_amd64.s
│ │ ├── asm_bsd_arm.s
│ │ ├── asm_bsd_arm64.s
│ │ ├── asm_bsd_ppc64.s
│ │ ├── asm_bsd_riscv64.s
│ │ ├── asm_linux_386.s
│ │ ├── asm_linux_amd64.s
│ │ ├── asm_linux_arm.s
│ │ ├── asm_linux_arm64.s
│ │ ├── asm_linux_loong64.s
│ │ ├── asm_linux_mips64x.s
│ │ ├── asm_linux_mipsx.s
│ │ ├── asm_linux_ppc64x.s
│ │ ├── asm_linux_riscv64.s
│ │ ├── asm_linux_s390x.s
│ │ ├── asm_openbsd_mips64.s
│ │ ├── asm_solaris_amd64.s
│ │ ├── asm_zos_s390x.s
│ │ ├── auxv.go
│ │ ├── auxv_unsupported.go
│ │ ├── bluetooth_linux.go
│ │ ├── bpxsvc_zos.go
│ │ ├── bpxsvc_zos.s
│ │ ├── cap_freebsd.go
│ │ ├── constants.go
│ │ ├── dev_aix_ppc.go
│ │ ├── dev_aix_ppc64.go
│ │ ├── dev_darwin.go
│ │ ├── dev_dragonfly.go
│ │ ├── dev_freebsd.go
│ │ ├── dev_linux.go
│ │ ├── dev_netbsd.go
│ │ ├── dev_openbsd.go
│ │ ├── dev_zos.go
│ │ ├── dirent.go
│ │ ├── endian_big.go
│ │ ├── endian_little.go
│ │ ├── env_unix.go
│ │ ├── fcntl.go
│ │ ├── fcntl_darwin.go
│ │ ├── fcntl_linux_32bit.go
│ │ ├── fdset.go
│ │ ├── gccgo.go
│ │ ├── gccgo_c.c
│ │ ├── gccgo_linux_amd64.go
│ │ ├── ifreq_linux.go
│ │ ├── ioctl_linux.go
│ │ ├── ioctl_signed.go
│ │ ├── ioctl_unsigned.go
│ │ ├── ioctl_zos.go
│ │ ├── mkall.sh
│ │ ├── mkerrors.sh
│ │ ├── mmap_nomremap.go
│ │ ├── mremap.go
│ │ ├── pagesize_unix.go
│ │ ├── pledge_openbsd.go
│ │ ├── ptrace_darwin.go
│ │ ├── ptrace_ios.go
│ │ ├── race.go
│ │ ├── race0.go
│ │ ├── readdirent_getdents.go
│ │ ├── readdirent_getdirentries.go
│ │ ├── sockcmsg_dragonfly.go
│ │ ├── sockcmsg_linux.go
│ │ ├── sockcmsg_unix.go
│ │ ├── sockcmsg_unix_other.go
│ │ ├── sockcmsg_zos.go
│ │ ├── symaddr_zos_s390x.s
│ │ ├── syscall.go
│ │ ├── syscall_aix.go
│ │ ├── syscall_aix_ppc.go
│ │ ├── syscall_aix_ppc64.go
│ │ ├── syscall_bsd.go
│ │ ├── syscall_darwin.go
│ │ ├── syscall_darwin_amd64.go
│ │ ├── syscall_darwin_arm64.go
│ │ ├── syscall_darwin_libSystem.go
│ │ ├── syscall_dragonfly.go
│ │ ├── syscall_dragonfly_amd64.go
│ │ ├── syscall_freebsd.go
│ │ ├── syscall_freebsd_386.go
│ │ ├── syscall_freebsd_amd64.go
│ │ ├── syscall_freebsd_arm.go
│ │ ├── syscall_freebsd_arm64.go
│ │ ├── syscall_freebsd_riscv64.go
│ │ ├── syscall_hurd.go
│ │ ├── syscall_hurd_386.go
│ │ ├── syscall_illumos.go
│ │ ├── syscall_linux.go
│ │ ├── syscall_linux_386.go
│ │ ├── syscall_linux_alarm.go
│ │ ├── syscall_linux_amd64.go
│ │ ├── syscall_linux_amd64_gc.go
│ │ ├── syscall_linux_arm.go
│ │ ├── syscall_linux_arm64.go
│ │ ├── syscall_linux_gc.go
│ │ ├── syscall_linux_gc_386.go
│ │ ├── syscall_linux_gc_arm.go
│ │ ├── syscall_linux_gccgo_386.go
│ │ ├── syscall_linux_gccgo_arm.go
│ │ ├── syscall_linux_loong64.go
│ │ ├── syscall_linux_mips64x.go
│ │ ├── syscall_linux_mipsx.go
│ │ ├── syscall_linux_ppc.go
│ │ ├── syscall_linux_ppc64x.go
│ │ ├── syscall_linux_riscv64.go
│ │ ├── syscall_linux_s390x.go
│ │ ├── syscall_linux_sparc64.go
│ │ ├── syscall_netbsd.go
│ │ ├── syscall_netbsd_386.go
│ │ ├── syscall_netbsd_amd64.go
│ │ ├── syscall_netbsd_arm.go
│ │ ├── syscall_netbsd_arm64.go
│ │ ├── syscall_openbsd.go
│ │ ├── syscall_openbsd_386.go
│ │ ├── syscall_openbsd_amd64.go
│ │ ├── syscall_openbsd_arm.go
│ │ ├── syscall_openbsd_arm64.go
│ │ ├── syscall_openbsd_libc.go
│ │ ├── syscall_openbsd_mips64.go
│ │ ├── syscall_openbsd_ppc64.go
│ │ ├── syscall_openbsd_riscv64.go
│ │ ├── syscall_solaris.go
│ │ ├── syscall_solaris_amd64.go
│ │ ├── syscall_unix.go
│ │ ├── syscall_unix_gc.go
│ │ ├── syscall_unix_gc_ppc64x.go
│ │ ├── syscall_zos_s390x.go
│ │ ├── sysvshm_linux.go
│ │ ├── sysvshm_unix.go
│ │ ├── sysvshm_unix_other.go
│ │ ├── timestruct.go
│ │ ├── unveil_openbsd.go
│ │ ├── vgetrandom_linux.go
│ │ ├── vgetrandom_unsupported.go
│ │ ├── xattr_bsd.go
│ │ ├── zerrors_aix_ppc.go
│ │ ├── zerrors_aix_ppc64.go
│ │ ├── zerrors_darwin_amd64.go
│ │ ├── zerrors_darwin_arm64.go
│ │ ├── zerrors_dragonfly_amd64.go
│ │ ├── zerrors_freebsd_386.go
│ │ ├── zerrors_freebsd_amd64.go
│ │ ├── zerrors_freebsd_arm.go
│ │ ├── zerrors_freebsd_arm64.go
│ │ ├── zerrors_freebsd_riscv64.go
│ │ ├── zerrors_linux.go
│ │ ├── zerrors_linux_386.go
│ │ ├── zerrors_linux_amd64.go
│ │ ├── zerrors_linux_arm.go
│ │ ├── zerrors_linux_arm64.go
│ │ ├── zerrors_linux_loong64.go
│ │ ├── zerrors_linux_mips.go
│ │ ├── zerrors_linux_mips64.go
│ │ ├── zerrors_linux_mips64le.go
│ │ ├── zerrors_linux_mipsle.go
│ │ ├── zerrors_linux_ppc.go
│ │ ├── zerrors_linux_ppc64.go
│ │ ├── zerrors_linux_ppc64le.go
│ │ ├── zerrors_linux_riscv64.go
│ │ ├── zerrors_linux_s390x.go
│ │ ├── zerrors_linux_sparc64.go
│ │ ├── zerrors_netbsd_386.go
│ │ ├── zerrors_netbsd_amd64.go
│ │ ├── zerrors_netbsd_arm.go
│ │ ├── zerrors_netbsd_arm64.go
│ │ ├── zerrors_openbsd_386.go
│ │ ├── zerrors_openbsd_amd64.go
│ │ ├── zerrors_openbsd_arm.go
│ │ ├── zerrors_openbsd_arm64.go
│ │ ├── zerrors_openbsd_mips64.go
│ │ ├── zerrors_openbsd_ppc64.go
│ │ ├── zerrors_openbsd_riscv64.go
│ │ ├── zerrors_solaris_amd64.go
│ │ ├── zerrors_zos_s390x.go
│ │ ├── zptrace_armnn_linux.go
│ │ ├── zptrace_linux_arm64.go
│ │ ├── zptrace_mipsnn_linux.go
│ │ ├── zptrace_mipsnnle_linux.go
│ │ ├── zptrace_x86_linux.go
│ │ ├── zsymaddr_zos_s390x.s
│ │ ├── zsyscall_aix_ppc.go
│ │ ├── zsyscall_aix_ppc64.go
│ │ ├── zsyscall_aix_ppc64_gc.go
│ │ ├── zsyscall_aix_ppc64_gccgo.go
│ │ ├── zsyscall_darwin_amd64.go
│ │ ├── zsyscall_darwin_amd64.s
│ │ ├── zsyscall_darwin_arm64.go
│ │ ├── zsyscall_darwin_arm64.s
│ │ ├── zsyscall_dragonfly_amd64.go
│ │ ├── zsyscall_freebsd_386.go
│ │ ├── zsyscall_freebsd_amd64.go
│ │ ├── zsyscall_freebsd_arm.go
│ │ ├── zsyscall_freebsd_arm64.go
│ │ ├── zsyscall_freebsd_riscv64.go
│ │ ├── zsyscall_illumos_amd64.go
│ │ ├── zsyscall_linux.go
│ │ ├── zsyscall_linux_386.go
│ │ ├── zsyscall_linux_amd64.go
│ │ ├── zsyscall_linux_arm.go
│ │ ├── zsyscall_linux_arm64.go
│ │ ├── zsyscall_linux_loong64.go
│ │ ├── zsyscall_linux_mips.go
│ │ ├── zsyscall_linux_mips64.go
│ │ ├── zsyscall_linux_mips64le.go
│ │ ├── zsyscall_linux_mipsle.go
│ │ ├── zsyscall_linux_ppc.go
│ │ ├── zsyscall_linux_ppc64.go
│ │ ├── zsyscall_linux_ppc64le.go
│ │ ├── zsyscall_linux_riscv64.go
│ │ ├── zsyscall_linux_s390x.go
│ │ ├── zsyscall_linux_sparc64.go
│ │ ├── zsyscall_netbsd_386.go
│ │ ├── zsyscall_netbsd_amd64.go
│ │ ├── zsyscall_netbsd_arm.go
│ │ ├── zsyscall_netbsd_arm64.go
│ │ ├── zsyscall_openbsd_386.go
│ │ ├── zsyscall_openbsd_386.s
│ │ ├── zsyscall_openbsd_amd64.go
│ │ ├── zsyscall_openbsd_amd64.s
│ │ ├── zsyscall_openbsd_arm.go
│ │ ├── zsyscall_openbsd_arm.s
│ │ ├── zsyscall_openbsd_arm64.go
│ │ ├── zsyscall_openbsd_arm64.s
│ │ ├── zsyscall_openbsd_mips64.go
│ │ ├── zsyscall_openbsd_mips64.s
│ │ ├── zsyscall_openbsd_ppc64.go
│ │ ├── zsyscall_openbsd_ppc64.s
│ │ ├── zsyscall_openbsd_riscv64.go
│ │ ├── zsyscall_openbsd_riscv64.s
│ │ ├── zsyscall_solaris_amd64.go
│ │ ├── zsyscall_zos_s390x.go
│ │ ├── zsysctl_openbsd_386.go
│ │ ├── zsysctl_openbsd_amd64.go
│ │ ├── zsysctl_openbsd_arm.go
│ │ ├── zsysctl_openbsd_arm64.go
│ │ ├── zsysctl_openbsd_mips64.go
│ │ ├── zsysctl_openbsd_ppc64.go
│ │ ├── zsysctl_openbsd_riscv64.go
│ │ ├── zsysnum_darwin_amd64.go
│ │ ├── zsysnum_darwin_arm64.go
│ │ ├── zsysnum_dragonfly_amd64.go
│ │ ├── zsysnum_freebsd_386.go
│ │ ├── zsysnum_freebsd_amd64.go
│ │ ├── zsysnum_freebsd_arm.go
│ │ ├── zsysnum_freebsd_arm64.go
│ │ ├── zsysnum_freebsd_riscv64.go
│ │ ├── zsysnum_linux_386.go
│ │ ├── zsysnum_linux_amd64.go
│ │ ├── zsysnum_linux_arm.go
│ │ ├── zsysnum_linux_arm64.go
│ │ ├── zsysnum_linux_loong64.go
│ │ ├── zsysnum_linux_mips.go
│ │ ├── zsysnum_linux_mips64.go
│ │ ├── zsysnum_linux_mips64le.go
│ │ ├── zsysnum_linux_mipsle.go
│ │ ├── zsysnum_linux_ppc.go
│ │ ├── zsysnum_linux_ppc64.go
│ │ ├── zsysnum_linux_ppc64le.go
│ │ ├── zsysnum_linux_riscv64.go
│ │ ├── zsysnum_linux_s390x.go
│ │ ├── zsysnum_linux_sparc64.go
│ │ ├── zsysnum_netbsd_386.go
│ │ ├── zsysnum_netbsd_amd64.go
│ │ ├── zsysnum_netbsd_arm.go
│ │ ├── zsysnum_netbsd_arm64.go
│ │ ├── zsysnum_openbsd_386.go
│ │ ├── zsysnum_openbsd_amd64.go
│ │ ├── zsysnum_openbsd_arm.go
│ │ ├── zsysnum_openbsd_arm64.go
│ │ ├── zsysnum_openbsd_mips64.go
│ │ ├── zsysnum_openbsd_ppc64.go
│ │ ├── zsysnum_openbsd_riscv64.go
│ │ ├── zsysnum_zos_s390x.go
│ │ ├── ztypes_aix_ppc.go
│ │ ├── ztypes_aix_ppc64.go
│ │ ├── ztypes_darwin_amd64.go
│ │ ├── ztypes_darwin_arm64.go
│ │ ├── ztypes_dragonfly_amd64.go
│ │ ├── ztypes_freebsd_386.go
│ │ ├── ztypes_freebsd_amd64.go
│ │ ├── ztypes_freebsd_arm.go
│ │ ├── ztypes_freebsd_arm64.go
│ │ ├── ztypes_freebsd_riscv64.go
│ │ ├── ztypes_linux.go
│ │ ├── ztypes_linux_386.go
│ │ ├── ztypes_linux_amd64.go
│ │ ├── ztypes_linux_arm.go
│ │ ├── ztypes_linux_arm64.go
│ │ ├── ztypes_linux_loong64.go
│ │ ├── ztypes_linux_mips.go
│ │ ├── ztypes_linux_mips64.go
│ │ ├── ztypes_linux_mips64le.go
│ │ ├── ztypes_linux_mipsle.go
│ │ ├── ztypes_linux_ppc.go
│ │ ├── ztypes_linux_ppc64.go
│ │ ├── ztypes_linux_ppc64le.go
│ │ ├── ztypes_linux_riscv64.go
│ │ ├── ztypes_linux_s390x.go
│ │ ├── ztypes_linux_sparc64.go
│ │ ├── ztypes_netbsd_386.go
│ │ ├── ztypes_netbsd_amd64.go
│ │ ├── ztypes_netbsd_arm.go
│ │ ├── ztypes_netbsd_arm64.go
│ │ ├── ztypes_openbsd_386.go
│ │ ├── ztypes_openbsd_amd64.go
│ │ ├── ztypes_openbsd_arm.go
│ │ ├── ztypes_openbsd_arm64.go
│ │ ├── ztypes_openbsd_mips64.go
│ │ ├── ztypes_openbsd_ppc64.go
│ │ ├── ztypes_openbsd_riscv64.go
│ │ ├── ztypes_solaris_amd64.go
│ │ └── ztypes_zos_s390x.go
│ └── windows/
│ ├── aliases.go
│ ├── dll_windows.go
│ ├── env_windows.go
│ ├── eventlog.go
│ ├── exec_windows.go
│ ├── memory_windows.go
│ ├── mkerrors.bash
│ ├── mkknownfolderids.bash
│ ├── mksyscall.go
│ ├── race.go
│ ├── race0.go
│ ├── security_windows.go
│ ├── service.go
│ ├── setupapi_windows.go
│ ├── str.go
│ ├── syscall.go
│ ├── syscall_windows.go
│ ├── types_windows.go
│ ├── types_windows_386.go
│ ├── types_windows_amd64.go
│ ├── types_windows_arm.go
│ ├── types_windows_arm64.go
│ ├── zerrors_windows.go
│ ├── zknownfolderids_windows.go
│ └── zsyscall_windows.go
├── gopkg.in/
│ └── yaml.v3/
│ ├── LICENSE
│ ├── NOTICE
│ ├── README.md
│ ├── apic.go
│ ├── decode.go
│ ├── emitterc.go
│ ├── encode.go
│ ├── parserc.go
│ ├── readerc.go
│ ├── resolve.go
│ ├── scannerc.go
│ ├── sorter.go
│ ├── writerc.go
│ ├── yaml.go
│ ├── yamlh.go
│ └── yamlprivateh.go
└── modules.txt
================================================
FILE CONTENTS
================================================
================================================
FILE: .dockerignore
================================================
Dockerfile
/.git
================================================
FILE: .editorconfig
================================================
# For more information about the properties used in
# this file, please see the EditorConfig documentation:
# http://editorconfig.org/
root = true
[*]
charset = utf-8
end_of_line = lf
indent_size = 4
indent_style = tab
insert_final_newline = true
trim_trailing_whitespace = true
spaces_around_brackets = outside
[*.md]
trim_trailing_whitespace = false
indent_style = space
[*.patch]
indent_style = space
================================================
FILE: .github/dependabot.yml
================================================
version: 2
updates:
- package-ecosystem: "gomod"
directory: "/"
schedule:
interval: "daily"
================================================
FILE: .github/workflows/codeql-analysis.yml
================================================
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"
on:
push:
branches: ["main"]
pull_request:
# The branches below must be a subset of the branches above
branches: ["main"]
schedule:
- cron: "32 23 * * 2"
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: ["go"]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
steps:
- name: Checkout repository
uses: actions/checkout@v6
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v4
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
# queries: security-extended,security-and-quality
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v4
# ℹ️ Command-line programs to run using the OS shell.
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
# If the Autobuild fails above, remove it and uncomment the following three lines.
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
# - run: |
# echo "Run, Build Application using script"
# ./location_of_script_within_repo/buildscript.sh
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v4
================================================
FILE: .github/workflows/go-tests.yml
================================================
name: tests
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 2
- uses: actions/setup-go@v6
with:
go-version: "1.25"
- name: Run coverage
run: go test -coverprofile=coverage.out -covermode=atomic -race -v ./...
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v5
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: coverage.out
flags: unit-linux
================================================
FILE: .gitignore
================================================
/contrib/server/server*
/contrib/client/client*
*.prof
*.out
*.html
*.ts
*.mp4
================================================
FILE: CODE_OF_CONDUCT.md
================================================
Contributor Code of Conduct
===========================
As contributors and maintainers of this project, we pledge to respect all
people who contribute through reporting issues, posting feature requests,
updating documentation, submitting pull requests or patches, and other
activities.
Examples of unacceptable behavior by participants include:
- Sexual language or imagery.
- Derogatory comments or personal attacks.
- Trolling, public or private harassment.
- Insults.
- Other unprofessional conduct.
Examples of unacceptable behavior by participants include sexual
language or imagery, derogatory comments or personal attacks, trolling, public
or private harassment, insults, or other unprofessional conduct.
Project maintainers have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are not
aligned with this Code of Conduct. In addition, project maintainers who do not
follow the Code of Conduct may be removed from the project team.
This code of conduct applies both within a project and in public spaces when an
individual represents the project or its community.
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by opening an issue or contacting one or more of the project maintainers.
This Code of Conduct is adapted from the [Contributor
Covenant](https://contributor-covenant.org/), version 1.1.0, available at
[https://contributor-covenant.org/version/1/1/0/](https://contributor-covenant.org/version/1/1/0/)
================================================
FILE: Dockerfile
================================================
ARG BUILD_IMAGE=golang:1.25-alpine
FROM $BUILD_IMAGE AS builder
COPY . /build
RUN cd /build/contrib/client && CGO_ENABLED=0 GOOS=linux go build -ldflags="-w -s" -a -o client .
RUN cd /build/contrib/server && CGO_ENABLED=0 GOOS=linux go build -ldflags="-w -s" -a -o server .
FROM scratch
COPY --from=builder /build/contrib/client/client /bin/srt-client
COPY --from=builder /build/contrib/server/server /bin/srt-server
WORKDIR /srt
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) 2020-2022 FOSS GmbH
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.
================================================
FILE: Makefile
================================================
COMMIT := $(shell if [ -d .git ]; then git rev-parse HEAD; else echo "unknown"; fi)
SHORTCOMMIT := $(shell echo $(COMMIT) | head -c 7)
all: build
## test: Run all tests
test:
go test -race -coverprofile=/dev/null -covermode=atomic -v ./...
## fuzz: Run fuzz tests
fuzz:
go test -fuzz=Fuzz -run=^Fuzz ./packet -fuzztime 30s
## vet: Analyze code for potential errors
vet:
go vet ./...
## fmt: Format code
fmt:
go fmt ./...
## update: Update dependencies
update:
go get -u -t
@-$(MAKE) tidy
@-$(MAKE) vendor
## tidy: Tidy up go.mod
tidy:
go mod tidy
## vendor: Update vendored packages
vendor:
go mod vendor
## lint: Static analysis with staticcheck
lint:
staticcheck ./...
## client: Build import binary
client:
cd contrib/client && CGO_ENABLED=0 go build -o client -ldflags="-s -w" -a
## server: Build import binary
server:
cd contrib/server && CGO_ENABLED=0 go build -o server -ldflags="-s -w" -a
## coverage: Generate code coverage analysis
coverage:
go test -race -coverprofile=cover.out -timeout 60s -v ./...
go tool cover -html=cover.out -o cover.html
## commit: Prepare code for commit (vet, fmt, test)
commit: vet fmt lint test
@echo "No errors found. Ready for a commit."
## docker: Build standard Docker image
docker:
docker build -t gosrt:$(SHORTCOMMIT) .
## logtopics: Extract all logging topics
logtopics:
grep -ERho 'log\("([^"]+)' *.go | sed -E -e 's/log\("//' | sort -u
.PHONY: help test fuzz vet fmt vendor commit coverage lint client server update logtopics
## help: Show all commands
help: Makefile
@echo
@echo " Choose a command:"
@echo
@sed -n 's/^##//p' $< | column -t -s ':' | sed -e 's/^/ /'
@echo
================================================
FILE: README.md
================================================
# GoSRT
Implementation of the SRT protocol in pure Go with minimal dependencies.
<p align="left">
<a href="http://srtalliance.org/">
<img alt="SRT" src="https://github.com/datarhei/misc/blob/main/img/gosrt.png?raw=true" width="600"/>
</a>
</p>
[](https://opensource.org/licenses/MIT)

[](https://codecov.io/gh/datarhei/gosrt)
[](https://goreportcard.com/report/github.com/datarhei/gosrt)
[](https://pkg.go.dev/github.com/datarhei/gosrt)
- [SRT reference implementation](https://github.com/Haivision/srt)
- [SRT RFC](https://haivision.github.io/srt-rfc/draft-sharabayko-srt.html)
- [SRT Technical Overview](https://github.com/Haivision/srt/files/2489142/SRT_Protocol_TechnicalOverview_DRAFT_2018-10-17.pdf)
## Implementations
This implementation of the SRT protocol has live streaming of video/audio in mind. Because of this, the buffer mode and File Transfer
Congestion Control (FileCC) are not implemented.
| | |
| --- | ----------------------------------------- |
| ✅ | Handshake v4 and v5 |
| ✅ | Message mode |
| ✅ | Caller-Listener Handshake |
| ✅ | Timestamp-Based Packet Delivery (TSBPD) |
| ✅ | Too-Late Packet Drop (TLPKTDROP) |
| ✅ | Live Congestion Control (LiveCC) |
| ✅ | NAK and Peridoc NAK |
| ✅ | Encryption |
| ❌ | Buffer mode |
| ❌ | Rendezvous Handshake |
| ❌ | File Transfer Congestion Control (FileCC) |
| ❌ | Connection Bonding |
The parts that are implemented are based on what has been published in the SRT RFC.
## Requirements
A Go version of 1.20+ is required.
## Installation
```shell
go get github.com/datarhei/gosrt
```
## Caller example
```go
import "github.com/datarhei/gosrt"
conn, err := srt.Dial("srt", "golang.org:6000", srt.Config{
StreamId: "...",
})
if err != nil {
// handle error
}
buffer := make([]byte, 2048)
for {
n, err := conn.Read(buffer)
if err != nil {
// handle error
}
// handle received data
}
conn.Close()
```
In the `contrib/client` directory you'll find a complete example of a SRT client.
## Listener example
```go
import "github.com/datarhei/gosrt"
ln, err := srt.Listen("srt", ":6000", srt.Config{...})
if err != nil {
// handle error
}
for {
req, err := ln.Accept2()
if err != nil {
// handle error
}
go func(req ConnRequest) {
// check connection request by inspecting the connection request
// and either rejecting it ...
if somethingIsWrong {
req.Reject(srt.REJ_PEER)
return
}
// ... or accepting it ...
conn, err := req.Accept()
if err != nil {
return
}
// ... and decide whether it is a publishing or subscribing connection.
if publish {
handlePublish(conn)
} else {
handleSubscribe(conn)
}
}(req)
}
```
In the `contrib/server` directory you'll find a complete example of a SRT server. For your convenience
this module provides the `Server` type which is a light framework for creating your own SRT server. The
example server is based on this type.
## Contributed client
In the `contrib/client` directory you'll find an example implementation of a SRT client.
Build the client application with
```shell
cd contrib/client && go build
```
The application requires only two options:
| Option | Description |
| ------- | -------------------- |
| `-from` | Address to read from |
| `-to` | Address to write to |
Both options accept an address. Valid addresses are: `-` for `stdin`, resp. `stdout`, a `srt://` address, or an `udp://` address.
### SRT URL
A SRT URL is of the form `srt://[host]:[port]/?[options]` where options are in the form of a `HTTP` query string. These are the
known options (similar to [srt-live-transmit](https://github.com/Haivision/srt/blob/master/docs/apps/srt-live-transmit.md)):
| Option | Values | Description |
| -------------------- | ---------------------- | ----------------------------------------------------------------------- |
| `mode` | `listener` or `caller` | Enforce listener or caller mode. |
| `congestion` | `live` | Congestion control. Currently only `live` is supported. |
| `conntimeo` | `ms` | Connection timeout. |
| `drifttracer` | `bool` | Enable drift tracer. Not implemented. |
| `enforcedencryption` | `bool` | Accept connection only if both parties have encryption enabled. |
| `fc` | `bytes` | Flow control window size. |
| `inputbw` | `bytes` | Input bandwidth. Ignored. |
| `iptos` | 0...255 | IP socket type of service. Broken. |
| `ipttl` | 1...255 | Defines IP socket "time to live" option. Broken. |
| `ipv6only` | `bool` | Use IPv6 only. Not implemented. |
| `kmpreannounce` | `packets` | Duration of Stream Encryption key switchover. |
| `kmrefreshrate` | `packets` | Stream encryption key refresh rate. |
| `latency` | `ms` | Maximum accepted transmission latency. |
| `lossmaxttl` | `ms` | Packet reorder tolerance. Not implemented. |
| `maxbw` | `bytes` | Bandwidth limit. Ignored. |
| `mininputbw` | `bytes` | Minimum allowed estimate of `inputbw`. |
| `messageapi` | `bool` | Enable SRT message mode. Must be `false`. |
| `mss` | 76... | MTU size. |
| `nakreport` | `bool` | Enable periodic NAK reports. |
| `oheadbw` | 10...100 | Limits bandwidth overhead. Percents. Ignored. |
| `packetfilter` | `string` | Set up the packet filter. Not implemented. |
| `passphrase` | `string` | Password for the encrypted transmission. |
| `payloadsize` | `bytes` | Maximum payload size. |
| `pbkeylen` | `16`, `24`, or `32` | Crypto key length in bytes. |
| `peeridletimeo` | `ms` | Peer idle timeout. |
| `peerlatency` | `ms` | Minimum receiver latency to be requested by sender. |
| `rcvbuf` | `bytes` | Receiver buffer size. |
| `rcvlatency` | `ms` | Receiver-side latency. |
| `sndbuf` | `bytes` | Sender buffer size. |
| `snddropdelay` | `ms` | Sender's delay before dropping packets. |
| `streamid` | `string` | Stream ID (settable in caller mode only, visible on the listener peer). |
| `tlpktdrop` | `bool` | Drop too late packets. |
| `transtype` | `live` | Transmission type. Must be `live`. |
| `tsbpdmode` | `bool` | Enable timestamp-based packet delivery mode. |
### Usage
Reading from a SRT sender and play with `ffplay`:
```shell
./client -from "srt://127.0.0.1:6001/?mode=listener&streamid=..." -to - | ffplay -f mpegts -i -
```
Reading from UDP and sending to a SRT server:
```shell
./client -from udp://:6000 -to "srt://127.0.0.1:6001/?mode=caller&streamid=..."
```
Simulate point-to-point transfer on localhost. Open one console and start `ffmpeg` (you need at least version 4.3.2, built with SRT enabled) to send to an UDP address:
```shell
ffmpeg \
-f lavfi \
-re \
-i testsrc2=rate=25:size=640x360 \
-codec:v libx264 \
-b:v 1024k \
-maxrate:v 1024k \
-bufsize:v 1024k \
-preset ultrafast \
-r 25 \
-g 50 \
-pix_fmt yuv420p \
-flags2 local_header \
-f mpegts \
"udp://127.0.0.1:6000?pkt_size=1316"
```
In another console read from the UDP and start a SRT listenr:
```shell
./client -from udp://:6000 -to "srt://127.0.0.1:6001/?mode=listener&streamid=foobar"
```
In the third console connect to that stream and play the video with `ffplay`:
```shell
./client -from "srt://127.0.0.1:6001/?mode=caller&streamid=foobar" -to - | ffplay -f mpegts -i -
```
## Contributed server
In the `contrib/server` directory you'll find an example implementation of a SRT server. This server allows you to publish
a stream that can be read by many clients.
Build the client application with
```shell
cd contrib/server && go build
```
The application has these options:
| Option | Default | Description |
| ------------- | --------- | ------------------------------------------ |
| `-addr` | required | Address to listen on |
| `-app` | `/` | Path prefix for streamid |
| `-token` | (not set) | Token query param for streamid |
| `-passphrase` | (not set) | Passphrase for de- and enrcypting the data |
| `-logtopics` | (not set) | Topics for the log output |
| `-profile` | `false` | Enable profiling |
This example server expects the streamID (without any prefix) to be an URL path with optional query parameter, e.g. `/live/stream`. If the `-app`
option is used, then the path must start with that path, e.g. the value is `/live` then the streamID must start with that value. The `-token`
option can be used to define a token for that stream as some kind of access control, e.g. with `-token foobar` the streamID might look like
`/live/stream?token=foobar`.
Use `-passphrase` in order to enable and enforce encryption.
Use `-logtopics` in order to write debug output. The value are a comma separated list of topics you want to be written to `stderr`, e.g. `connection,listen`. Check the [Logging](#logging) section in order to find out more about the different topics.
Use `-profile` in order to write a CPU profile.
### StreamID
In SRT the StreamID is used to transport somewhat arbitrary information from the caller to the listener. The provided example server uses this
machanism to decide who is the sender and who is the receiver. The server must know if the connecting client wants to publish a stream or
if it wants to subscribe to a stream.
The example server looks for the `publish:` prefix in the StreamID. If this prefix is present, the server assumes that it is the receiver
and the client will send the data. The subcribing clients must use the same StreamID (withouth the `publish:` prefix) in order to be able to
receive data.
If you implement your own server you are free to interpret the streamID as you wish.
### Usage
Running a server listening on port 6001 with defaults:
```shell
./server -addr ":6001"
```
Now you can use the contributed client to publish a stream:
```shell
./client -from ... -to "srt://127.0.0.1:6001/?mode=caller&streamid=publish:/live/stream"
```
or directly from `ffmpeg`:
```shell
ffmpeg \
-f lavfi \
-re \
-i testsrc2=rate=25:size=640x360 \
-codec:v libx264 \
-b:v 1024k \
-maxrate:v 1024k \
-bufsize:v 1024k \
-preset ultrafast \
-r 25 \
-g 50 \
-pix_fmt yuv420p \
-flags2 local_header \
-f mpegts \
-transtype live \
"srt://127.0.0.1:6001?streamid=publish:/live/stream"
```
If the server is not on localhost, you might adjust the `peerlatency` in order to avoid packet loss: `-peerlatency 1000000`.
Now you can play the stream:
```shell
ffplay -f mpegts -transtype live -i "srt://127.0.0.1:6001?streamid=/live/stream"
```
You will most likely first see some error messages from `ffplay` because it tries to make sense of the received data until a keyframe arrives. If you
get more errors during playback, you might increase the receive buffer by adding e.g. `-rcvlatency 1000000` to the command line.
### Encryption
The stream can be encrypted with a passphrase. First start the server with a passphrase. If you are using `srt-live-transmit`, the passphrase has to be at least 10 characters long otherwise it will not be accepted.
```shell
./server -addr :6001 -passphrase foobarfoobar
```
Send an encrpyted stream to the server:
```shell
ffmpeg \
-f lavfi \
-re \
-i testsrc2=rate=25:size=640x360 \
-codec:v libx264 \
-b:v 1024k \
-maxrate:v 1024k \
-bufsize:v 1024k \
-preset ultrafast \
-r 25 \
-g 50 \
-pix_fmt yuv420p \
-flags2 local_header \
-f mpegts \
-transtype live \
"srt://127.0.0.1:6001?streamid=publish:/live/stream&passphrase=foobarfoobar"
```
Receive an encrypted stream from the server:
```shell
ffplay -f mpegts -transtype live -i "srt://127.0.0.1:6001?streamid=/live/stream&passphrase=foobarfoobar"
```
You will most likely first see some error messages from `ffplay` because it tries to make sense of the received data until a keyframe arrives. If you
get more errors during playback, you might increase the receive buffer by adding e.g. `-rcvlatency 1000000` to the command line.
## Logging
This SRT module has a built-in logging facility for debugging purposes. Check the `Logger` interface and the `NewLogger(topics []string)` function. Because logging everything would be too much output if you wonly want to debug something specific, you have the possibility to limit the logging to specific areas like everything regarding a connection or only the handshake. That's why there are various topics.
In the contributed server you see an example of how logging is used. Here's the essence:
```go
logger := srt.NewLogger([]string{"connection", "handshake"})
config := srt.DefaultConfig
config.Logger = logger
ln, err := srt.Listen("udp", ":6000", config)
if err != nil {
// handle error
}
go func() {
for m := range logger.Listen() {
fmt.Fprintf(os.Stderr, "%#08x %s (in %s:%d)\n%s \n", m.SocketId, m.Topic, m.File, m.Line, m.Message)
}
}()
for {
conn, mode, err := ln.Accept(acceptFn)
...
}
```
Currently known topics are:
```
connection:close
connection:error
connection:filter
connection:new
connection:rtt
connection:tsbpd
control:recv:ACK:cif
control:recv:ACK:dump
control:recv:ACK:error
control:recv:ACKACK:dump
control:recv:ACKACK:error
control:recv:KM:cif
control:recv:KM:dump
control:recv:KM:error
control:recv:NAK:cif
control:recv:NAK:dump
control:recv:NAK:error
control:recv:keepalive:dump
control:recv:shutdown:dump
control:send:ACK:cif
control:send:ACK:dump
control:send:ACKACK:dump
control:send:KM:cif
control:send:KM:dump
control:send:KM:error
control:send:NAK:cif
control:send:NAK:dump
control:send:keepalive:dump
control:send:shutdown:cif
control:send:shutdown:dump
data:recv:dump
data:send:dump
dial
handshake:recv:cif
handshake:recv:dump
handshake:recv:error
handshake:send:cif
handshake:send:dump
listen
packet:recv:dump
packet:send:dump
```
You can run `make logtopics` in order to extract the list of topics.
## Docker
The docker image you can build with `docker build -t srt .` provides the example SRT client and server as mentioned in the paragraph above.
E.g. run the server with `docker run -it --rm -p 6001:6001/udp srt srt-server -addr :6001`.
================================================
FILE: SECURITY.md
================================================
# Security Policy
## Supported Versions
All versions in the list receive security updates.
| Version | Supported |
| ------- | ------------------ |
| 0.1.1 | :white_check_mark: |
| - | :x: |
## Reporting a Vulnerability
If you have found or just suspect a security problem somewhere in Restreamer or Core, report it on support@datarhei.com.
We treat security issues with confidentiality until controlled and disclosed responsibly.
================================================
FILE: circular/circular.go
================================================
// Package circular implements "circular numbers". This is a number that can be
// increased (or decreased) indefinitely while only using up a limited amount of
// memory. This feature comes with the limitiation in how distant two such
// numbers can be. Circular numbers have a maximum. The maximum distance is
// half the maximum value. If a number that has the maximum value is
// increased by 1, it becomes 0. If a number that has the value of 0 is
// decreased by 1, it becomes the maximum value. By comparing two circular
// numbers it is not possible to tell how often they wrapped. Therefore these
// two numbers must come from the same domain in order to make sense of the
// camparison.
package circular
// Number represents a "circular number". A Number is immutable. All modification
// to a Number will result in a new instance of a Number.
type Number struct {
max uint32
threshold uint32
value uint32
}
// New returns a new circular number with the value of x and the maximum of max.
func New(x, max uint32) Number {
c := Number{
value: 0,
max: max,
threshold: max / 2,
}
if x > max {
return c.Add(x)
}
c.value = x
return c
}
// Val returns the current value of the number.
func (a Number) Val() uint32 {
return a.value
}
// Equals returns whether two circular numbers have the same value.
func (a Number) Equals(b Number) bool {
return a.value == b.value
}
// Distance returns the distance of two circular numbers.
func (a Number) Distance(b Number) uint32 {
if a.Equals(b) {
return 0
}
d := uint32(0)
if a.value > b.value {
d = a.value - b.value
} else {
d = b.value - a.value
}
if d >= a.threshold {
d = a.max - d + 1
}
return d
}
// Lt returns whether the circular number is lower than the circular number b.
func (a Number) Lt(b Number) bool {
if a.Equals(b) {
return false
}
d := uint32(0)
altb := false
if a.value > b.value {
d = a.value - b.value
} else {
d = b.value - a.value
altb = true
}
if d < a.threshold {
return altb
}
return !altb
}
// Lte returns whether the circular number is lower than or equal to the circular number b.
func (a Number) Lte(b Number) bool {
if a.Equals(b) {
return true
}
return a.Lt(b)
}
// Gt returns whether the circular number is greather than the circular number b.
func (a Number) Gt(b Number) bool {
if a.Equals(b) {
return false
}
d := uint32(0)
agtb := false
if a.value > b.value {
d = a.value - b.value
agtb = true
} else {
d = b.value - a.value
}
if d < a.threshold {
return agtb
}
return !agtb
}
// Gte returns whether the circular number is greather than or equal to the circular number b.
func (a Number) Gte(b Number) bool {
if a.Equals(b) {
return true
}
return a.Gt(b)
}
// Inc returns a new circular number with a value that is increased by 1.
func (a Number) Inc() Number {
b := a
if b.value == b.max {
b.value = 0
} else {
b.value++
}
return b
}
// Add returns a new circular number with a value that is increased by b.
func (a Number) Add(b uint32) Number {
c := a
x := c.max - c.value
if b <= x {
c.value += b
} else {
c.value = b - x - 1
}
return c
}
// Dec returns a new circular number with a value that is decreased by 1.
func (a Number) Dec() Number {
b := a
if b.value == 0 {
b.value = b.max
} else {
b.value--
}
return b
}
// Sub returns a new circular number with a value that is decreased by b.
func (a Number) Sub(b uint32) Number {
c := a
if b <= c.value {
c.value -= b
} else {
c.value = c.max - (b - c.value) + 1
}
return c
}
================================================
FILE: circular/circular_test.go
================================================
package circular
import (
"fmt"
"testing"
"github.com/stretchr/testify/require"
)
const max uint32 = 0b11111111_11111111_11111111_11111111
func ExampleNumber_Inc() {
a := New(42, max)
b := a.Inc()
fmt.Println(b.Val())
// Output: 43
}
func TestIncNoWrap(t *testing.T) {
a := New(42, max)
require.Equal(t, uint32(42), a.Val())
a = a.Inc()
require.Equal(t, uint32(43), a.Val())
}
func TestIncWrap(t *testing.T) {
a := New(max-1, max)
require.Equal(t, max-1, a.Val())
a = a.Inc()
require.Equal(t, max, a.Val())
a = a.Inc()
require.Equal(t, uint32(0), a.Val())
}
func TestDecNoWrap(t *testing.T) {
a := New(42, max)
require.Equal(t, uint32(42), a.Val())
a = a.Dec()
require.Equal(t, uint32(41), a.Val())
}
func TestDecWrap(t *testing.T) {
a := New(0, max)
require.Equal(t, uint32(0), a.Val())
a = a.Dec()
require.Equal(t, max, a.Val())
a = a.Dec()
require.Equal(t, max-1, a.Val())
}
func TestDistanceNoWrap(t *testing.T) {
a := New(42, max)
b := New(50, max)
d := a.Distance(b)
require.Equal(t, uint32(8), d)
d = b.Distance(a)
require.Equal(t, uint32(8), d)
}
func TestDistanceWrap(t *testing.T) {
a := New(2, max)
b := New(max-2, max)
d := a.Distance(b)
require.Equal(t, uint32(5), d)
d = b.Distance(a)
require.Equal(t, uint32(5), d)
}
func TestLt(t *testing.T) {
a := New(42, max)
b := New(50, max)
c := New(max-10, max)
x := a.Lt(b)
require.Equal(t, true, x)
x = b.Lt(a)
require.Equal(t, false, x)
x = a.Lt(c)
require.Equal(t, false, x)
x = c.Lt(a)
require.Equal(t, true, x)
}
func TestGt(t *testing.T) {
a := New(42, max)
b := New(50, max)
c := New(max-10, max)
x := a.Gt(b)
require.Equal(t, false, x)
x = b.Gt(a)
require.Equal(t, true, x)
x = a.Gt(c)
require.Equal(t, true, x)
x = c.Gt(a)
require.Equal(t, false, x)
}
func TestAdd(t *testing.T) {
a := New(max-42, max)
a = a.Add(42)
require.Equal(t, max, a.Val())
a = a.Add(1)
require.Equal(t, uint32(0), a.Val())
}
func TestSub(t *testing.T) {
a := New(42, max)
a = a.Sub(42)
require.Equal(t, uint32(0), a.Val())
a = a.Sub(1)
require.Equal(t, max, a.Val())
}
================================================
FILE: config.go
================================================
package srt
import (
"fmt"
"net/url"
"strconv"
"time"
)
const (
UDP_HEADER_SIZE = 28
SRT_HEADER_SIZE = 16
MIN_MSS_SIZE = 76
MAX_MSS_SIZE = 1500
MIN_PAYLOAD_SIZE = MIN_MSS_SIZE - UDP_HEADER_SIZE - SRT_HEADER_SIZE
MAX_PAYLOAD_SIZE = MAX_MSS_SIZE - UDP_HEADER_SIZE - SRT_HEADER_SIZE
MIN_PASSPHRASE_SIZE = 10
MAX_PASSPHRASE_SIZE = 80
MAX_STREAMID_SIZE = 512
SRT_VERSION = 0x010401
)
// Config is the configuration for a SRT connection
type Config struct {
// Type of congestion control. 'live' or 'file'
// SRTO_CONGESTION
Congestion string
// Connection timeout.
// SRTO_CONNTIMEO
ConnectionTimeout time.Duration
// Enable drift tracer.
// SRTO_DRIFTTRACER
DriftTracer bool
// Reject connection if parties set different passphrase.
// SRTO_ENFORCEDENCRYPTION
EnforcedEncryption bool
// Flow control window size. Packets.
// SRTO_FC
FC uint32
// Accept group connections.
// SRTO_GROUPCONNECT
GroupConnect bool
// Group stability timeout.
// SRTO_GROUPSTABTIMEO
GroupStabilityTimeout time.Duration
// Input bandwidth. Bytes.
// SRTO_INPUTBW
InputBW int64
// IP socket type of service
// SRTO_IPTOS
IPTOS int
// Defines IP socket "time to live" option.
// SRTO_IPTTL
IPTTL int
// Allow only IPv6.
// SRTO_IPV6ONLY
IPv6Only int
// Duration of Stream Encryption key switchover. Packets.
// SRTO_KMPREANNOUNCE
KMPreAnnounce uint64
// Stream encryption key refresh rate. Packets.
// SRTO_KMREFRESHRATE
KMRefreshRate uint64
// Defines the maximum accepted transmission latency.
// SRTO_LATENCY
Latency time.Duration
// Packet reorder tolerance.
// SRTO_LOSSMAXTTL
LossMaxTTL uint32
// Bandwidth limit in bytes/s.
// SRTO_MAXBW
MaxBW int64
// Enable SRT message mode.
// SRTO_MESSAGEAPI
MessageAPI bool
// Minimum input bandwidth
// This option is effective only if both SRTO_MAXBW and SRTO_INPUTBW are set to 0. It controls the minimum allowed value of the input bitrate estimate.
// SRTO_MININPUTBW
MinInputBW int64
// Minimum SRT library version of a peer.
// SRTO_MINVERSION
MinVersion uint32
// MTU size
// SRTO_MSS
MSS uint32
// Enable periodic NAK reports
// SRTO_NAKREPORT
NAKReport bool
// Limit bandwidth overhead, percents
// SRTO_OHEADBW
OverheadBW int64
// Set up the packet filter.
// SRTO_PACKETFILTER
PacketFilter string
// Password for the encrypted transmission.
// SRTO_PASSPHRASE
Passphrase string
// Maximum payload size. Bytes.
// SRTO_PAYLOADSIZE
PayloadSize uint32
// Crypto key length in bytes.
// SRTO_PBKEYLEN
PBKeylen int
// Peer idle timeout.
// SRTO_PEERIDLETIMEO
PeerIdleTimeout time.Duration
// Minimum receiver latency to be requested by sender.
// SRTO_PEERLATENCY
PeerLatency time.Duration
// Receiver buffer size. Bytes.
// SRTO_RCVBUF
ReceiverBufferSize uint32
// Receiver-side latency.
// SRTO_RCVLATENCY
ReceiverLatency time.Duration
// Sender buffer size. Bytes.
// SRTO_SNDBUF
SendBufferSize uint32
// Sender's delay before dropping packets.
// SRTO_SNDDROPDELAY
SendDropDelay time.Duration
// Stream ID (settable in caller mode only, visible on the listener peer)
// SRTO_STREAMID
StreamId string
// Drop too late packets.
// SRTO_TLPKTDROP
TooLatePacketDrop bool
// Transmission type. 'live' or 'file'.
// SRTO_TRANSTYPE
TransmissionType string
// Timestamp-based packet delivery mode.
// SRTO_TSBPDMODE
TSBPDMode bool
// An implementation of the Logger interface
Logger Logger
// if a new IP starts sending data on an existing socket id, allow it
AllowPeerIpChange bool
}
// DefaultConfig is the default configuration for a SRT connection
// if no individual configuration has been provided.
var defaultConfig Config = Config{
Congestion: "live",
ConnectionTimeout: 3 * time.Second,
DriftTracer: true,
EnforcedEncryption: true,
FC: 25600,
GroupConnect: false,
GroupStabilityTimeout: 0,
InputBW: 0,
IPTOS: 0,
IPTTL: 0,
IPv6Only: -1,
KMPreAnnounce: 1 << 12,
KMRefreshRate: 1 << 24,
Latency: -1,
LossMaxTTL: 0,
MaxBW: -1,
MessageAPI: false,
MinVersion: SRT_VERSION,
MSS: MAX_MSS_SIZE,
NAKReport: true,
OverheadBW: 25,
PacketFilter: "",
Passphrase: "",
PayloadSize: MAX_PAYLOAD_SIZE,
PBKeylen: 16,
PeerIdleTimeout: 5 * time.Second,
PeerLatency: 120 * time.Millisecond,
ReceiverBufferSize: 0,
ReceiverLatency: 120 * time.Millisecond,
SendBufferSize: 0,
SendDropDelay: 1 * time.Second,
StreamId: "",
TooLatePacketDrop: true,
TransmissionType: "live",
TSBPDMode: true,
AllowPeerIpChange: false,
}
// DefaultConfig returns the default configuration for Dial and Listen.
func DefaultConfig() Config {
return defaultConfig
}
// UnmarshalURL takes a SRT URL and parses out the configuration. A SRT URL is
// srt://[host]:[port]?[key1]=[value1]&[key2]=[value2]... It returns the host:port
// of the URL.
func (c *Config) UnmarshalURL(srturl string) (string, error) {
u, err := url.Parse(srturl)
if err != nil {
return "", err
}
if u.Scheme != "srt" {
return "", fmt.Errorf("the URL doesn't seem to be an srt:// URL")
}
return u.Host, c.UnmarshalQuery(u.RawQuery)
}
// UnmarshalQuery parses a query string and interprets it as a configuration
// for a SRT connection. The key in each key/value pair corresponds to the
// respective field in the Config type, but with only lower case letters. Bool
// values can be represented as "true"/"false", "on"/"off", "yes"/"no", or "0"/"1".
func (c *Config) UnmarshalQuery(query string) error {
v, err := url.ParseQuery(query)
if err != nil {
return err
}
// https://github.com/Haivision/srt/blob/master/docs/apps/srt-live-transmit.md
if s := v.Get("congestion"); len(s) != 0 {
c.Congestion = s
}
if s := v.Get("conntimeo"); len(s) != 0 {
if d, err := strconv.Atoi(s); err == nil {
c.ConnectionTimeout = time.Duration(d) * time.Millisecond
}
}
if s := v.Get("drifttracer"); len(s) != 0 {
switch s {
case "yes", "on", "true", "1":
c.DriftTracer = true
case "no", "off", "false", "0":
c.DriftTracer = false
}
}
if s := v.Get("enforcedencryption"); len(s) != 0 {
switch s {
case "yes", "on", "true", "1":
c.EnforcedEncryption = true
case "no", "off", "false", "0":
c.EnforcedEncryption = false
}
}
if s := v.Get("fc"); len(s) != 0 {
if d, err := strconv.ParseUint(s, 10, 32); err == nil {
c.FC = uint32(d)
}
}
if s := v.Get("groupconnect"); len(s) != 0 {
switch s {
case "yes", "on", "true", "1":
c.GroupConnect = true
case "no", "off", "false", "0":
c.GroupConnect = false
}
}
if s := v.Get("groupstabtimeo"); len(s) != 0 {
if d, err := strconv.Atoi(s); err == nil {
c.GroupStabilityTimeout = time.Duration(d) * time.Millisecond
}
}
if s := v.Get("inputbw"); len(s) != 0 {
if d, err := strconv.ParseInt(s, 10, 64); err == nil {
c.InputBW = d
}
}
if s := v.Get("iptos"); len(s) != 0 {
if d, err := strconv.Atoi(s); err == nil {
c.IPTOS = d
}
}
if s := v.Get("ipttl"); len(s) != 0 {
if d, err := strconv.Atoi(s); err == nil {
c.IPTTL = d
}
}
if s := v.Get("ipv6only"); len(s) != 0 {
if d, err := strconv.Atoi(s); err == nil {
c.IPv6Only = d
}
}
if s := v.Get("kmpreannounce"); len(s) != 0 {
if d, err := strconv.ParseUint(s, 10, 64); err == nil {
c.KMPreAnnounce = d
}
}
if s := v.Get("kmrefreshrate"); len(s) != 0 {
if d, err := strconv.ParseUint(s, 10, 64); err == nil {
c.KMRefreshRate = d
}
}
if s := v.Get("latency"); len(s) != 0 {
if d, err := strconv.Atoi(s); err == nil {
c.Latency = time.Duration(d) * time.Millisecond
}
}
if s := v.Get("lossmaxttl"); len(s) != 0 {
if d, err := strconv.ParseUint(s, 10, 32); err == nil {
c.LossMaxTTL = uint32(d)
}
}
if s := v.Get("maxbw"); len(s) != 0 {
if d, err := strconv.ParseInt(s, 10, 64); err == nil {
c.MaxBW = d
}
}
if s := v.Get("mininputbw"); len(s) != 0 {
if d, err := strconv.ParseInt(s, 10, 64); err == nil {
c.MinInputBW = d
}
}
if s := v.Get("messageapi"); len(s) != 0 {
switch s {
case "yes", "on", "true", "1":
c.MessageAPI = true
case "no", "off", "false", "0":
c.MessageAPI = false
}
}
// minversion is ignored
if s := v.Get("mss"); len(s) != 0 {
if d, err := strconv.ParseUint(s, 10, 32); err == nil {
c.MSS = uint32(d)
}
}
if s := v.Get("nakreport"); len(s) != 0 {
switch s {
case "yes", "on", "true", "1":
c.NAKReport = true
case "no", "off", "false", "0":
c.NAKReport = false
}
}
if s := v.Get("oheadbw"); len(s) != 0 {
if d, err := strconv.ParseInt(s, 10, 64); err == nil {
c.OverheadBW = d
}
}
if s := v.Get("packetfilter"); len(s) != 0 {
c.PacketFilter = s
}
if s := v.Get("passphrase"); len(s) != 0 {
c.Passphrase = s
}
if s := v.Get("payloadsize"); len(s) != 0 {
if d, err := strconv.ParseUint(s, 10, 32); err == nil {
c.PayloadSize = uint32(d)
}
}
if s := v.Get("pbkeylen"); len(s) != 0 {
if d, err := strconv.Atoi(s); err == nil {
c.PBKeylen = d
}
}
if s := v.Get("peeridletimeo"); len(s) != 0 {
if d, err := strconv.Atoi(s); err == nil {
c.PeerIdleTimeout = time.Duration(d) * time.Millisecond
}
}
if s := v.Get("peerlatency"); len(s) != 0 {
if d, err := strconv.Atoi(s); err == nil {
c.PeerLatency = time.Duration(d) * time.Millisecond
}
}
if s := v.Get("rcvbuf"); len(s) != 0 {
if d, err := strconv.ParseUint(s, 10, 32); err == nil {
c.ReceiverBufferSize = uint32(d)
}
}
if s := v.Get("rcvlatency"); len(s) != 0 {
if d, err := strconv.Atoi(s); err == nil {
c.ReceiverLatency = time.Duration(d) * time.Millisecond
}
}
// retransmitalgo not implemented (there's only one)
if s := v.Get("sndbuf"); len(s) != 0 {
if d, err := strconv.ParseUint(s, 10, 32); err == nil {
c.SendBufferSize = uint32(d)
}
}
if s := v.Get("snddropdelay"); len(s) != 0 {
if d, err := strconv.Atoi(s); err == nil {
c.SendDropDelay = time.Duration(d) * time.Millisecond
}
}
if s := v.Get("streamid"); len(s) != 0 {
c.StreamId = s
}
if s := v.Get("tlpktdrop"); len(s) != 0 {
switch s {
case "yes", "on", "true", "1":
c.TooLatePacketDrop = true
case "no", "off", "false", "0":
c.TooLatePacketDrop = false
}
}
if s := v.Get("transtype"); len(s) != 0 {
c.TransmissionType = s
}
if s := v.Get("tsbpdmode"); len(s) != 0 {
switch s {
case "yes", "on", "true", "1":
c.TSBPDMode = true
case "no", "off", "false", "0":
c.TSBPDMode = false
}
}
return nil
}
// MarshalURL returns the SRT URL for this config and the given address (host:port).
func (c *Config) MarshalURL(address string) string {
return "srt://" + address + "?" + c.MarshalQuery()
}
// MarshalQuery returns the corresponding query string for a configuration.
func (c *Config) MarshalQuery() string {
q := url.Values{}
if c.Congestion != defaultConfig.Congestion {
q.Set("congestion", c.Congestion)
}
if c.ConnectionTimeout != defaultConfig.ConnectionTimeout {
q.Set("conntimeo", strconv.FormatInt(c.ConnectionTimeout.Milliseconds(), 10))
}
if c.DriftTracer != defaultConfig.DriftTracer {
q.Set("drifttracer", strconv.FormatBool(c.DriftTracer))
}
if c.EnforcedEncryption != defaultConfig.EnforcedEncryption {
q.Set("enforcedencryption", strconv.FormatBool(c.EnforcedEncryption))
}
if c.FC != defaultConfig.FC {
q.Set("fc", strconv.FormatUint(uint64(c.FC), 10))
}
if c.GroupConnect != defaultConfig.GroupConnect {
q.Set("groupconnect", strconv.FormatBool(c.GroupConnect))
}
if c.GroupStabilityTimeout != defaultConfig.GroupStabilityTimeout {
q.Set("groupstabtimeo", strconv.FormatInt(c.GroupStabilityTimeout.Milliseconds(), 10))
}
if c.InputBW != defaultConfig.InputBW {
q.Set("inputbw", strconv.FormatInt(c.InputBW, 10))
}
if c.IPTOS != defaultConfig.IPTOS {
q.Set("iptos", strconv.FormatInt(int64(c.IPTOS), 10))
}
if c.IPTTL != defaultConfig.IPTTL {
q.Set("ipttl", strconv.FormatInt(int64(c.IPTTL), 10))
}
if c.IPv6Only != defaultConfig.IPv6Only {
q.Set("ipv6only", strconv.FormatInt(int64(c.IPv6Only), 10))
}
if len(c.Passphrase) != 0 {
if c.KMPreAnnounce != defaultConfig.KMPreAnnounce {
q.Set("kmpreannounce", strconv.FormatUint(c.KMPreAnnounce, 10))
}
if c.KMRefreshRate != defaultConfig.KMRefreshRate {
q.Set("kmrefreshrate", strconv.FormatUint(c.KMRefreshRate, 10))
}
}
if c.Latency != defaultConfig.Latency {
q.Set("latency", strconv.FormatInt(c.Latency.Milliseconds(), 10))
}
if c.LossMaxTTL != defaultConfig.LossMaxTTL {
q.Set("lossmaxttl", strconv.FormatInt(int64(c.LossMaxTTL), 10))
}
if c.MaxBW != defaultConfig.MaxBW {
q.Set("maxbw", strconv.FormatInt(c.MaxBW, 10))
}
if c.MinInputBW != defaultConfig.InputBW {
q.Set("mininputbw", strconv.FormatInt(c.MinInputBW, 10))
}
if c.MessageAPI != defaultConfig.MessageAPI {
q.Set("messageapi", strconv.FormatBool(c.MessageAPI))
}
if c.MSS != defaultConfig.MSS {
q.Set("mss", strconv.FormatUint(uint64(c.MSS), 10))
}
if c.NAKReport != defaultConfig.NAKReport {
q.Set("nakreport", strconv.FormatBool(c.NAKReport))
}
if c.OverheadBW != defaultConfig.OverheadBW {
q.Set("oheadbw", strconv.FormatInt(c.OverheadBW, 10))
}
if c.PacketFilter != defaultConfig.PacketFilter {
q.Set("packetfilter", c.PacketFilter)
}
if len(c.Passphrase) != 0 {
q.Set("passphrase", c.Passphrase)
}
if c.PayloadSize != defaultConfig.PayloadSize {
q.Set("payloadsize", strconv.FormatUint(uint64(c.PayloadSize), 10))
}
if c.PBKeylen != defaultConfig.PBKeylen {
q.Set("pbkeylen", strconv.FormatInt(int64(c.PBKeylen), 10))
}
if c.PeerIdleTimeout != defaultConfig.PeerIdleTimeout {
q.Set("peeridletimeo", strconv.FormatInt(c.PeerIdleTimeout.Milliseconds(), 10))
}
if c.PeerLatency != defaultConfig.PeerLatency {
q.Set("peerlatency", strconv.FormatInt(c.PeerLatency.Milliseconds(), 10))
}
if c.ReceiverBufferSize != defaultConfig.ReceiverBufferSize {
q.Set("rcvbuf", strconv.FormatInt(int64(c.ReceiverBufferSize), 10))
}
if c.ReceiverLatency != defaultConfig.ReceiverLatency {
q.Set("rcvlatency", strconv.FormatInt(c.ReceiverLatency.Milliseconds(), 10))
}
if c.SendBufferSize != defaultConfig.SendBufferSize {
q.Set("sndbuf", strconv.FormatInt(int64(c.SendBufferSize), 10))
}
if c.SendDropDelay != defaultConfig.SendDropDelay {
q.Set("snddropdelay", strconv.FormatInt(c.SendDropDelay.Milliseconds(), 10))
}
if len(c.StreamId) != 0 {
q.Set("streamid", c.StreamId)
}
if c.TooLatePacketDrop != defaultConfig.TooLatePacketDrop {
q.Set("tlpktdrop", strconv.FormatBool(c.TooLatePacketDrop))
}
if c.TransmissionType != defaultConfig.TransmissionType {
q.Set("transtype", c.TransmissionType)
}
if c.TSBPDMode != defaultConfig.TSBPDMode {
q.Set("tsbpdmode", strconv.FormatBool(c.TSBPDMode))
}
return q.Encode()
}
// Validate validates a configuration, returns an error if a field
// has an invalid value.
func (c *Config) Validate() error {
if c.TransmissionType != "live" {
return fmt.Errorf("config: TransmissionType must be 'live'")
}
c.Congestion = "live"
c.NAKReport = true
c.TooLatePacketDrop = true
c.TSBPDMode = true
if c.Congestion != "live" {
return fmt.Errorf("config: Congestion mode must be 'live'")
}
if c.ConnectionTimeout <= 0 {
return fmt.Errorf("config: ConnectionTimeout must be greater than 0")
}
if c.GroupConnect {
return fmt.Errorf("config: GroupConnect is not supported")
}
if c.IPTOS > 0 && c.IPTOS > 255 {
return fmt.Errorf("config: IPTOS must be lower than 255")
}
if c.IPTTL > 0 && c.IPTTL > 255 {
return fmt.Errorf("config: IPTTL must be between 1 and 255")
}
if c.IPv6Only > 0 {
return fmt.Errorf("config: IPv6Only is not supported")
}
if c.KMRefreshRate != 0 {
if c.KMPreAnnounce < 1 || c.KMPreAnnounce > c.KMRefreshRate/2 {
return fmt.Errorf("config: KMPreAnnounce must be greater than 1 and smaller than KMRefreshRate/2")
}
}
if c.Latency >= 0 {
c.PeerLatency = c.Latency
c.ReceiverLatency = c.Latency
}
if c.MinVersion != SRT_VERSION {
return fmt.Errorf("config: MinVersion must be %#06x", SRT_VERSION)
}
if c.MSS < MIN_MSS_SIZE || c.MSS > MAX_MSS_SIZE {
return fmt.Errorf("config: MSS must be between %d and %d (both inclusive)", MIN_MSS_SIZE, MAX_MSS_SIZE)
}
if !c.NAKReport {
return fmt.Errorf("config: NAKReport must be enabled")
}
if c.OverheadBW < 10 || c.OverheadBW > 100 {
return fmt.Errorf("config: OverheadBW must be between 10 and 100")
}
if len(c.PacketFilter) != 0 {
return fmt.Errorf("config: PacketFilter are not supported")
}
if len(c.Passphrase) != 0 {
if len(c.Passphrase) < MIN_PASSPHRASE_SIZE || len(c.Passphrase) > MAX_PASSPHRASE_SIZE {
return fmt.Errorf("config: Passphrase must be between %d and %d bytes long", MIN_PASSPHRASE_SIZE, MAX_PASSPHRASE_SIZE)
}
}
if c.PayloadSize < MIN_PAYLOAD_SIZE || c.PayloadSize > MAX_PAYLOAD_SIZE {
return fmt.Errorf("config: PayloadSize must be between %d and %d (both inclusive)", MIN_PAYLOAD_SIZE, MAX_PAYLOAD_SIZE)
}
if c.PayloadSize > c.MSS-uint32(SRT_HEADER_SIZE+UDP_HEADER_SIZE) {
return fmt.Errorf("config: PayloadSize must not be larger than %d (MSS - %d)", c.MSS-uint32(SRT_HEADER_SIZE+UDP_HEADER_SIZE), SRT_HEADER_SIZE-UDP_HEADER_SIZE)
}
if c.PBKeylen != 16 && c.PBKeylen != 24 && c.PBKeylen != 32 {
return fmt.Errorf("config: PBKeylen must be 16, 24, or 32 bytes")
}
if c.PeerLatency < 0 {
return fmt.Errorf("config: PeerLatency must be greater than 0")
}
if c.ReceiverLatency < 0 {
return fmt.Errorf("config: ReceiverLatency must be greater than 0")
}
if c.SendDropDelay < 0 {
return fmt.Errorf("config: SendDropDelay must be greater than 0")
}
if len(c.StreamId) > MAX_STREAMID_SIZE {
return fmt.Errorf("config: StreamId must be shorter than or equal to %d bytes", MAX_STREAMID_SIZE)
}
if !c.TooLatePacketDrop {
return fmt.Errorf("config: TooLatePacketDrop must be enabled")
}
if c.TransmissionType != "live" {
return fmt.Errorf("config: TransmissionType must be 'live'")
}
if !c.TSBPDMode {
return fmt.Errorf("config: TSBPDMode must be enabled")
}
return nil
}
================================================
FILE: config_test.go
================================================
package srt
import (
"testing"
"time"
"github.com/stretchr/testify/require"
)
func TestDefaultConfig(t *testing.T) {
config := DefaultConfig()
err := config.Validate()
if err != nil {
require.NoError(t, err, "Failed to verify the default configuration: %s", err)
}
}
func TestMarshalUnmarshal(t *testing.T) {
wantConfig := Config{
Congestion: "xxx",
ConnectionTimeout: 42 * time.Second,
DriftTracer: false,
EnforcedEncryption: false,
FC: 42,
GroupConnect: true,
GroupStabilityTimeout: 42 * time.Second,
InputBW: 42,
IPTOS: 42,
IPTTL: 42,
IPv6Only: 42,
KMPreAnnounce: 42,
KMRefreshRate: 42,
Latency: 42 * time.Second,
LossMaxTTL: 42,
MaxBW: 42,
MessageAPI: true,
MinInputBW: 42,
MSS: 42,
NAKReport: false,
OverheadBW: 42,
PacketFilter: "FEC",
Passphrase: "foobar",
PayloadSize: 42,
PBKeylen: 42,
PeerIdleTimeout: 42 * time.Second,
PeerLatency: 42 * time.Second,
ReceiverBufferSize: 42,
ReceiverLatency: 42 * time.Second,
SendBufferSize: 42,
SendDropDelay: 42 * time.Second,
StreamId: "foobaz",
TooLatePacketDrop: false,
TransmissionType: "yyy",
TSBPDMode: false,
Logger: nil,
}
url := wantConfig.MarshalURL("localhost:6000")
config := Config{}
config.UnmarshalURL(url)
require.Equal(t, wantConfig, config)
}
================================================
FILE: congestion/congestion.go
================================================
// Package congestions provides interfaces and types congestion control implementations for SRT
package congestion
import (
"github.com/datarhei/gosrt/circular"
"github.com/datarhei/gosrt/packet"
)
// Sender is the sending part of the congestion control
type Sender interface {
// Stats returns sender statistics.
Stats() SendStats
// Flush flushes all queued packages.
Flush()
// Push pushes a packet to be send on the sender queue.
Push(p packet.Packet)
// Tick gets called from a connection in order to proceed with the queued packets. The provided value for
// now is corresponds to the timestamps in the queued packets. Those timestamps are the microseconds
// since the start of the connection.
Tick(now uint64)
// ACK gets called when a sequence number has been confirmed from a receiver.
ACK(sequenceNumber circular.Number)
// NAK get called when packets with the listed sequence number should be resend.
NAK(sequenceNumbers []circular.Number)
// SetDropThreshold sets the threshold in microseconds for when to drop too late packages from the queue.
SetDropThreshold(threshold uint64)
}
// Receiver is the receiving part of the congestion control
type Receiver interface {
// Stats returns receiver statistics.
Stats() ReceiveStats
// PacketRate returns the current packets and bytes per second, and the capacity of the link.
PacketRate() (pps, bps, capacity float64)
// Flush flushes all queued packages.
Flush()
// Push pushed a recieved packet to the receiver queue.
Push(pkt packet.Packet)
// Tick gets called from a connection in order to proceed with queued packets. The provided value for
// now is corresponds to the timestamps in the queued packets. Those timestamps are the microseconds
// since the start of the connection.
Tick(now uint64)
// SetNAKInterval sets the interval between two periodic NAK messages to the sender in microseconds.
SetNAKInterval(nakInterval uint64)
}
// SendStats are collected statistics from a sender
type SendStats struct {
Pkt uint64 // Sent packets in total
Byte uint64 // Sent bytes in total
PktUnique uint64
ByteUnique uint64
PktLoss uint64
ByteLoss uint64
PktRetrans uint64
ByteRetrans uint64
UsSndDuration uint64 // microseconds
PktDrop uint64
ByteDrop uint64
// instantaneous
PktBuf uint64
ByteBuf uint64
MsBuf uint64
PktFlightSize uint64
UsPktSndPeriod float64 // microseconds
BytePayload uint64
MbpsEstimatedInputBandwidth float64
MbpsEstimatedSentBandwidth float64
PktLossRate float64
}
// ReceiveStats are collected statistics from a reciever
type ReceiveStats struct {
Pkt uint64
Byte uint64
PktUnique uint64
ByteUnique uint64
PktLoss uint64
ByteLoss uint64
PktRetrans uint64
ByteRetrans uint64
PktBelated uint64
ByteBelated uint64
PktDrop uint64
ByteDrop uint64
// instantaneous
PktBuf uint64
ByteBuf uint64
MsBuf uint64
BytePayload uint64
MbpsEstimatedRecvBandwidth float64
MbpsEstimatedLinkCapacity float64
PktLossRate float64
}
================================================
FILE: congestion/live/doc.go
================================================
// Package live provides implementations of the Sender and Receiver interfaces for live congestion control
package live
================================================
FILE: congestion/live/fake.go
================================================
package live
import (
"sync"
"time"
"github.com/datarhei/gosrt/circular"
"github.com/datarhei/gosrt/congestion"
"github.com/datarhei/gosrt/packet"
)
type fakeLiveReceive struct {
maxSeenSequenceNumber circular.Number
lastACKSequenceNumber circular.Number
lastDeliveredSequenceNumber circular.Number
nPackets uint
periodicACKInterval uint64 // config
periodicNAKInterval uint64 // config
lastPeriodicACK uint64
avgPayloadSize float64 // bytes
rate struct {
last time.Time
period time.Duration
packets uint64
bytes uint64
pps float64
bps float64
}
sendACK func(seq circular.Number, light bool)
sendNAK func(list []circular.Number)
deliver func(p packet.Packet)
lock sync.RWMutex
}
func NewFakeLiveReceive(config ReceiveConfig) congestion.Receiver {
r := &fakeLiveReceive{
maxSeenSequenceNumber: config.InitialSequenceNumber.Dec(),
lastACKSequenceNumber: config.InitialSequenceNumber.Dec(),
lastDeliveredSequenceNumber: config.InitialSequenceNumber.Dec(),
periodicACKInterval: config.PeriodicACKInterval,
periodicNAKInterval: config.PeriodicNAKInterval,
avgPayloadSize: 1456, // 5.1.2. SRT's Default LiveCC Algorithm
sendACK: config.OnSendACK,
sendNAK: config.OnSendNAK,
deliver: config.OnDeliver,
}
if r.sendACK == nil {
r.sendACK = func(seq circular.Number, light bool) {}
}
if r.sendNAK == nil {
r.sendNAK = func(list []circular.Number) {}
}
if r.deliver == nil {
r.deliver = func(p packet.Packet) {}
}
r.rate.last = time.Now()
r.rate.period = time.Second
return r
}
func (r *fakeLiveReceive) Stats() congestion.ReceiveStats { return congestion.ReceiveStats{} }
func (r *fakeLiveReceive) PacketRate() (pps, bps, capacity float64) {
r.lock.Lock()
defer r.lock.Unlock()
tdiff := time.Since(r.rate.last)
if tdiff < r.rate.period {
pps = r.rate.pps
bps = r.rate.bps
return
}
r.rate.pps = float64(r.rate.packets) / tdiff.Seconds()
r.rate.bps = float64(r.rate.bytes) / tdiff.Seconds()
r.rate.packets, r.rate.bytes = 0, 0
r.rate.last = time.Now()
pps = r.rate.pps
bps = r.rate.bps
return
}
func (r *fakeLiveReceive) Flush() {}
func (r *fakeLiveReceive) Push(pkt packet.Packet) {
r.lock.Lock()
defer r.lock.Unlock()
if pkt == nil {
return
}
r.nPackets++
pktLen := pkt.Len()
r.rate.packets++
r.rate.bytes += pktLen
// 5.1.2. SRT's Default LiveCC Algorithm
r.avgPayloadSize = 0.875*r.avgPayloadSize + 0.125*float64(pktLen)
if pkt.Header().PacketSequenceNumber.Lte(r.lastDeliveredSequenceNumber) {
// Too old, because up until r.lastDeliveredSequenceNumber, we already delivered
return
}
if pkt.Header().PacketSequenceNumber.Lt(r.lastACKSequenceNumber) {
// Already acknowledged, ignoring
return
}
if pkt.Header().PacketSequenceNumber.Lte(r.maxSeenSequenceNumber) {
return
}
r.maxSeenSequenceNumber = pkt.Header().PacketSequenceNumber
}
func (r *fakeLiveReceive) periodicACK(now uint64) (ok bool, sequenceNumber circular.Number, lite bool) {
r.lock.RLock()
defer r.lock.RUnlock()
// 4.8.1. Packet Acknowledgement (ACKs, ACKACKs)
if now-r.lastPeriodicACK < r.periodicACKInterval {
if r.nPackets >= 64 {
lite = true // Send light ACK
} else {
return
}
}
ok = true
sequenceNumber = r.maxSeenSequenceNumber.Inc()
r.lastACKSequenceNumber = r.maxSeenSequenceNumber
r.lastPeriodicACK = now
r.nPackets = 0
return
}
func (r *fakeLiveReceive) Tick(now uint64) {
if ok, sequenceNumber, lite := r.periodicACK(now); ok {
r.sendACK(sequenceNumber, lite)
}
// Deliver packets whose PktTsbpdTime is ripe
r.lock.Lock()
defer r.lock.Unlock()
r.lastDeliveredSequenceNumber = r.lastACKSequenceNumber
}
func (r *fakeLiveReceive) SetNAKInterval(nakInterval uint64) {
r.lock.Lock()
defer r.lock.Unlock()
r.periodicNAKInterval = nakInterval
}
================================================
FILE: congestion/live/receive.go
================================================
package live
import (
"container/list"
"fmt"
"strings"
"sync"
"time"
"github.com/datarhei/gosrt/circular"
"github.com/datarhei/gosrt/congestion"
"github.com/datarhei/gosrt/packet"
)
// ReceiveConfig is the configuration for the liveRecv congestion control
type ReceiveConfig struct {
InitialSequenceNumber circular.Number
PeriodicACKInterval uint64 // microseconds
PeriodicNAKInterval uint64 // microseconds
OnSendACK func(seq circular.Number, light bool)
OnSendNAK func(list []circular.Number)
OnDeliver func(p packet.Packet)
}
// receiver implements the Receiver interface
type receiver struct {
maxSeenSequenceNumber circular.Number
lastACKSequenceNumber circular.Number
lastDeliveredSequenceNumber circular.Number
packetList *list.List
lock sync.RWMutex
nPackets uint
periodicACKInterval uint64 // config
periodicNAKInterval uint64 // config
lastPeriodicACK uint64
lastPeriodicNAK uint64
avgPayloadSize float64 // bytes
avgLinkCapacity float64 // packets per second
probeTime time.Time
probeNextSeq circular.Number
statistics congestion.ReceiveStats
rate struct {
last uint64 // microseconds
period uint64
packets uint64
bytes uint64
bytesRetrans uint64
packetsPerSecond float64
bytesPerSecond float64
pktLossRate float64
}
sendACK func(seq circular.Number, light bool)
sendNAK func(list []circular.Number)
deliver func(p packet.Packet)
}
// NewReceiver takes a ReceiveConfig and returns a new Receiver
func NewReceiver(config ReceiveConfig) congestion.Receiver {
r := &receiver{
maxSeenSequenceNumber: config.InitialSequenceNumber.Dec(),
lastACKSequenceNumber: config.InitialSequenceNumber.Dec(),
lastDeliveredSequenceNumber: config.InitialSequenceNumber.Dec(),
packetList: list.New(),
periodicACKInterval: config.PeriodicACKInterval,
periodicNAKInterval: config.PeriodicNAKInterval,
avgPayloadSize: 1456, // 5.1.2. SRT's Default LiveCC Algorithm
sendACK: config.OnSendACK,
sendNAK: config.OnSendNAK,
deliver: config.OnDeliver,
}
if r.sendACK == nil {
r.sendACK = func(seq circular.Number, light bool) {}
}
if r.sendNAK == nil {
r.sendNAK = func(list []circular.Number) {}
}
if r.deliver == nil {
r.deliver = func(p packet.Packet) {}
}
r.rate.last = 0
r.rate.period = uint64(time.Second.Microseconds())
return r
}
func (r *receiver) Stats() congestion.ReceiveStats {
r.lock.Lock()
defer r.lock.Unlock()
r.statistics.BytePayload = uint64(r.avgPayloadSize)
r.statistics.MbpsEstimatedRecvBandwidth = r.rate.bytesPerSecond * 8 / 1024 / 1024
r.statistics.MbpsEstimatedLinkCapacity = r.avgLinkCapacity * packet.MAX_PAYLOAD_SIZE * 8 / 1024 / 1024
r.statistics.PktLossRate = r.rate.pktLossRate
return r.statistics
}
func (r *receiver) PacketRate() (pps, bps, capacity float64) {
r.lock.Lock()
defer r.lock.Unlock()
pps = r.rate.packetsPerSecond
bps = r.rate.bytesPerSecond
capacity = r.avgLinkCapacity
return
}
func (r *receiver) Flush() {
r.lock.Lock()
defer r.lock.Unlock()
r.packetList = r.packetList.Init()
}
func (r *receiver) Push(pkt packet.Packet) {
r.lock.Lock()
defer r.lock.Unlock()
if pkt == nil {
return
}
// This is not really well (not at all) described in the specs. See core.cpp and window.h
// and search for PUMASK_SEQNO_PROBE (0xF). Every 16th and 17th packet are
// sent in pairs. This is used as a probe for the theoretical capacity of the link.
if !pkt.Header().RetransmittedPacketFlag {
probe := pkt.Header().PacketSequenceNumber.Val() & 0xF
if probe == 0 {
r.probeTime = time.Now()
r.probeNextSeq = pkt.Header().PacketSequenceNumber.Inc()
} else if probe == 1 && pkt.Header().PacketSequenceNumber.Equals(r.probeNextSeq) && !r.probeTime.IsZero() && pkt.Len() != 0 {
// The time between packets scaled to a fully loaded packet
diff := float64(time.Since(r.probeTime).Microseconds()) * (packet.MAX_PAYLOAD_SIZE / float64(pkt.Len()))
if diff != 0 {
// Here we're doing an average of the measurements.
r.avgLinkCapacity = 0.875*r.avgLinkCapacity + 0.125*1_000_000/diff
}
} else {
r.probeTime = time.Time{}
}
} else {
r.probeTime = time.Time{}
}
r.nPackets++
pktLen := pkt.Len()
r.rate.packets++
r.rate.bytes += pktLen
r.statistics.Pkt++
r.statistics.Byte += pktLen
//pkt.PktTsbpdTime = pkt.Timestamp + r.delay
if pkt.Header().RetransmittedPacketFlag {
r.statistics.PktRetrans++
r.statistics.ByteRetrans += pktLen
r.rate.bytesRetrans += pktLen
}
// 5.1.2. SRT's Default LiveCC Algorithm
r.avgPayloadSize = 0.875*r.avgPayloadSize + 0.125*float64(pktLen)
if pkt.Header().PacketSequenceNumber.Lte(r.lastDeliveredSequenceNumber) {
// Too old, because up until r.lastDeliveredSequenceNumber, we already delivered
r.statistics.PktBelated++
r.statistics.ByteBelated += pktLen
r.statistics.PktDrop++
r.statistics.ByteDrop += pktLen
return
}
if pkt.Header().PacketSequenceNumber.Lt(r.lastACKSequenceNumber) {
// Already acknowledged, ignoring
r.statistics.PktDrop++
r.statistics.ByteDrop += pktLen
return
}
if pkt.Header().PacketSequenceNumber.Equals(r.maxSeenSequenceNumber.Inc()) {
// In order, the packet we expected
r.maxSeenSequenceNumber = pkt.Header().PacketSequenceNumber
} else if pkt.Header().PacketSequenceNumber.Lte(r.maxSeenSequenceNumber) {
// Out of order, is it a missing piece? put it in the correct position
for e := r.packetList.Front(); e != nil; e = e.Next() {
p := e.Value.(packet.Packet)
if p.Header().PacketSequenceNumber == pkt.Header().PacketSequenceNumber {
// Already received (has been sent more than once), ignoring
r.statistics.PktDrop++
r.statistics.ByteDrop += pktLen
break
} else if p.Header().PacketSequenceNumber.Gt(pkt.Header().PacketSequenceNumber) {
// Late arrival, this fills a gap
r.statistics.PktBuf++
r.statistics.PktUnique++
r.statistics.ByteBuf += pktLen
r.statistics.ByteUnique += pktLen
r.packetList.InsertBefore(pkt, e)
break
}
}
return
} else {
// Too far ahead, there are some missing sequence numbers, immediate NAK report
// here we can prevent a possibly unnecessary NAK with SRTO_LOXXMAXTTL
r.sendNAK([]circular.Number{
r.maxSeenSequenceNumber.Inc(),
pkt.Header().PacketSequenceNumber.Dec(),
})
len := uint64(pkt.Header().PacketSequenceNumber.Distance(r.maxSeenSequenceNumber))
r.statistics.PktLoss += len
r.statistics.ByteLoss += len * uint64(r.avgPayloadSize)
r.maxSeenSequenceNumber = pkt.Header().PacketSequenceNumber
}
r.statistics.PktBuf++
r.statistics.PktUnique++
r.statistics.ByteBuf += pktLen
r.statistics.ByteUnique += pktLen
r.packetList.PushBack(pkt)
}
func (r *receiver) periodicACK(now uint64) (ok bool, sequenceNumber circular.Number, lite bool) {
r.lock.Lock()
defer r.lock.Unlock()
// 4.8.1. Packet Acknowledgement (ACKs, ACKACKs)
if now-r.lastPeriodicACK < r.periodicACKInterval {
if r.nPackets >= 64 {
lite = true // Send light ACK
} else {
return
}
}
minPktTsbpdTime, maxPktTsbpdTime := uint64(0), uint64(0)
ackSequenceNumber := r.lastACKSequenceNumber
e := r.packetList.Front()
if e != nil {
p := e.Value.(packet.Packet)
minPktTsbpdTime = p.Header().PktTsbpdTime
maxPktTsbpdTime = p.Header().PktTsbpdTime
}
// Find the sequence number up until we have all in a row.
// Where the first gap is (or at the end of the list) is where we can ACK to.
for e := r.packetList.Front(); e != nil; e = e.Next() {
p := e.Value.(packet.Packet)
// Skip packets that we already ACK'd.
if p.Header().PacketSequenceNumber.Lte(ackSequenceNumber) {
continue
}
// If there are packets that should have been delivered by now, move forward.
if p.Header().PktTsbpdTime <= now {
ackSequenceNumber = p.Header().PacketSequenceNumber
continue
}
// Check if the packet is the next in the row.
if p.Header().PacketSequenceNumber.Equals(ackSequenceNumber.Inc()) {
ackSequenceNumber = p.Header().PacketSequenceNumber
maxPktTsbpdTime = p.Header().PktTsbpdTime
continue
}
break
}
ok = true
sequenceNumber = ackSequenceNumber.Inc()
// Keep track of the last ACK's sequence number. With this we can faster ignore
// packets that come in late that have a lower sequence number.
r.lastACKSequenceNumber = ackSequenceNumber
r.lastPeriodicACK = now
r.nPackets = 0
r.statistics.MsBuf = (maxPktTsbpdTime - minPktTsbpdTime) / 1_000
return
}
func (r *receiver) periodicNAK(now uint64) []circular.Number {
r.lock.RLock()
defer r.lock.RUnlock()
if now-r.lastPeriodicNAK < r.periodicNAKInterval {
return nil
}
list := []circular.Number{}
// Send a periodic NAK
ackSequenceNumber := r.lastACKSequenceNumber
// Send a NAK for all gaps.
// Not all gaps might get announced because the size of the NAK packet is limited.
for e := r.packetList.Front(); e != nil; e = e.Next() {
p := e.Value.(packet.Packet)
// Skip packets that we already ACK'd.
if p.Header().PacketSequenceNumber.Lte(ackSequenceNumber) {
continue
}
// If this packet is not in sequence, we stop here and report that gap.
if !p.Header().PacketSequenceNumber.Equals(ackSequenceNumber.Inc()) {
nackSequenceNumber := ackSequenceNumber.Inc()
list = append(list, nackSequenceNumber)
list = append(list, p.Header().PacketSequenceNumber.Dec())
}
ackSequenceNumber = p.Header().PacketSequenceNumber
}
r.lastPeriodicNAK = now
return list
}
func (r *receiver) Tick(now uint64) {
if ok, sequenceNumber, lite := r.periodicACK(now); ok {
r.sendACK(sequenceNumber, lite)
}
if list := r.periodicNAK(now); len(list) != 0 {
r.sendNAK(list)
}
// Deliver packets whose PktTsbpdTime is ripe
r.lock.Lock()
removeList := make([]*list.Element, 0, r.packetList.Len())
for e := r.packetList.Front(); e != nil; e = e.Next() {
p := e.Value.(packet.Packet)
if p.Header().PacketSequenceNumber.Lte(r.lastACKSequenceNumber) && p.Header().PktTsbpdTime <= now {
r.statistics.PktBuf--
r.statistics.ByteBuf -= p.Len()
r.lastDeliveredSequenceNumber = p.Header().PacketSequenceNumber
r.deliver(p)
removeList = append(removeList, e)
} else {
break
}
}
for _, e := range removeList {
r.packetList.Remove(e)
}
r.lock.Unlock()
r.lock.Lock()
tdiff := now - r.rate.last // microseconds
if tdiff > r.rate.period {
r.rate.packetsPerSecond = float64(r.rate.packets) / (float64(tdiff) / 1000 / 1000)
r.rate.bytesPerSecond = float64(r.rate.bytes) / (float64(tdiff) / 1000 / 1000)
if r.rate.bytes != 0 {
r.rate.pktLossRate = float64(r.rate.bytesRetrans) / float64(r.rate.bytes) * 100
} else {
r.rate.bytes = 0
}
r.rate.packets = 0
r.rate.bytes = 0
r.rate.bytesRetrans = 0
r.rate.last = now
}
r.lock.Unlock()
}
func (r *receiver) SetNAKInterval(nakInterval uint64) {
r.lock.Lock()
defer r.lock.Unlock()
r.periodicNAKInterval = nakInterval
}
func (r *receiver) String(t uint64) string {
var b strings.Builder
b.WriteString(fmt.Sprintf("maxSeen=%d lastACK=%d lastDelivered=%d\n", r.maxSeenSequenceNumber.Val(), r.lastACKSequenceNumber.Val(), r.lastDeliveredSequenceNumber.Val()))
r.lock.RLock()
for e := r.packetList.Front(); e != nil; e = e.Next() {
p := e.Value.(packet.Packet)
b.WriteString(fmt.Sprintf(" %d @ %d (in %d)\n", p.Header().PacketSequenceNumber.Val(), p.Header().PktTsbpdTime, int64(p.Header().PktTsbpdTime)-int64(t)))
}
r.lock.RUnlock()
return b.String()
}
================================================
FILE: congestion/live/receive_test.go
================================================
package live
import (
"net"
"testing"
"github.com/datarhei/gosrt/circular"
"github.com/datarhei/gosrt/packet"
"github.com/stretchr/testify/require"
)
func mockLiveRecv(onSendACK func(seq circular.Number, light bool), onSendNAK func(list []circular.Number), onDeliver func(p packet.Packet)) *receiver {
recv := NewReceiver(ReceiveConfig{
InitialSequenceNumber: circular.New(0, packet.MAX_SEQUENCENUMBER),
PeriodicACKInterval: 10,
PeriodicNAKInterval: 20,
OnSendACK: onSendACK,
OnSendNAK: onSendNAK,
OnDeliver: onDeliver,
})
return recv.(*receiver)
}
func TestRecvSequence(t *testing.T) {
nACK := 0
nNAK := 0
numbers := []uint32{}
recv := mockLiveRecv(
func(seq circular.Number, light bool) {
nACK++
},
func(list []circular.Number) {
nNAK++
},
func(p packet.Packet) {
numbers = append(numbers, p.Header().PacketSequenceNumber.Val())
},
)
addr, _ := net.ResolveIPAddr("ip", "127.0.0.1")
for i := range 10 {
p := packet.NewPacket(addr)
p.Header().PacketSequenceNumber = circular.New(uint32(i), packet.MAX_SEQUENCENUMBER)
p.Header().PktTsbpdTime = uint64(i + 1)
recv.Push(p)
}
require.Equal(t, 0, nACK)
require.Equal(t, 0, nNAK)
require.Equal(t, uint32(9), recv.maxSeenSequenceNumber.Val())
require.Equal(t, uint32(0), recv.lastACKSequenceNumber.Inc().Val())
recv.Tick(1)
require.Equal(t, 0, nACK)
require.Equal(t, 0, nNAK)
require.Equal(t, uint32(9), recv.maxSeenSequenceNumber.Val())
require.Equal(t, uint32(0), recv.lastACKSequenceNumber.Inc().Val())
recv.Tick(10) // ACK period
require.Equal(t, 1, nACK)
require.Equal(t, 0, nNAK)
require.Equal(t, uint32(9), recv.maxSeenSequenceNumber.Val())
require.Equal(t, uint32(9), recv.lastACKSequenceNumber.Val())
require.Exactly(t, []uint32{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, numbers)
}
func TestRecvTSBPD(t *testing.T) {
numbers := []uint32{}
recv := mockLiveRecv(
nil,
nil,
func(p packet.Packet) {
numbers = append(numbers, p.Header().PacketSequenceNumber.Val())
},
)
addr, _ := net.ResolveIPAddr("ip", "127.0.0.1")
for i := range 20 {
p := packet.NewPacket(addr)
p.Header().PacketSequenceNumber = circular.New(uint32(i), packet.MAX_SEQUENCENUMBER)
p.Header().PktTsbpdTime = uint64(i + 1)
recv.Push(p)
}
require.Equal(t, uint32(19), recv.maxSeenSequenceNumber.Val())
require.Equal(t, uint32(0), recv.lastACKSequenceNumber.Inc().Val())
recv.Tick(10) // ACK period
require.Equal(t, uint32(19), recv.maxSeenSequenceNumber.Val())
require.Equal(t, uint32(19), recv.lastACKSequenceNumber.Val())
require.Exactly(t, []uint32{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, numbers)
}
func TestRecvNAK(t *testing.T) {
seqACK := uint32(0)
seqNAK := []uint32{}
numbers := []uint32{}
recv := mockLiveRecv(
func(seq circular.Number, light bool) {
seqACK = seq.Val()
},
func(list []circular.Number) {
seqNAK = []uint32{}
for _, sn := range list {
seqNAK = append(seqNAK, sn.Val())
}
},
func(p packet.Packet) {
numbers = append(numbers, p.Header().PacketSequenceNumber.Val())
},
)
addr, _ := net.ResolveIPAddr("ip", "127.0.0.1")
for i := range 5 {
p := packet.NewPacket(addr)
p.Header().PacketSequenceNumber = circular.New(uint32(i), packet.MAX_SEQUENCENUMBER)
p.Header().PktTsbpdTime = uint64(i + 1)
recv.Push(p)
}
require.Equal(t, uint32(0), seqACK)
require.Equal(t, []uint32{}, seqNAK)
require.Equal(t, uint32(4), recv.maxSeenSequenceNumber.Val())
for i := 7; i < 10; i++ {
p := packet.NewPacket(addr)
p.Header().PacketSequenceNumber = circular.New(uint32(i), packet.MAX_SEQUENCENUMBER)
p.Header().PktTsbpdTime = uint64(i + 1)
recv.Push(p)
}
require.Equal(t, uint32(0), seqACK)
require.Equal(t, []uint32{5, 6}, seqNAK)
require.Equal(t, uint32(9), recv.maxSeenSequenceNumber.Val())
recv.Tick(10) // ACK period
require.Equal(t, uint32(10), seqACK)
require.Equal(t, []uint32{5, 6}, seqNAK)
require.Equal(t, uint32(9), recv.maxSeenSequenceNumber.Val())
}
func TestRecvPeriodicNAK(t *testing.T) {
seqACK := uint32(0)
seqNAK := []uint32{}
numbers := []uint32{}
recv := mockLiveRecv(
func(seq circular.Number, light bool) {
seqACK = seq.Val()
},
func(list []circular.Number) {
seqNAK = []uint32{}
for _, sn := range list {
seqNAK = append(seqNAK, sn.Val())
}
},
func(p packet.Packet) {
numbers = append(numbers, p.Header().PacketSequenceNumber.Val())
},
)
addr, _ := net.ResolveIPAddr("ip", "127.0.0.1")
for i := range 5 {
p := packet.NewPacket(addr)
p.Header().PacketSequenceNumber = circular.New(uint32(i), packet.MAX_SEQUENCENUMBER)
p.Header().PktTsbpdTime = uint64(50 + i + 1)
recv.Push(p)
}
require.Equal(t, uint32(0), seqACK)
require.Equal(t, []uint32{}, seqNAK)
require.Equal(t, uint32(4), recv.maxSeenSequenceNumber.Val())
for i := 7; i < 10; i++ {
p := packet.NewPacket(addr)
p.Header().PacketSequenceNumber = circular.New(uint32(i), packet.MAX_SEQUENCENUMBER)
p.Header().PktTsbpdTime = uint64(50 + i + 1)
recv.Push(p)
}
require.Equal(t, uint32(0), seqACK)
require.Equal(t, []uint32{5, 6}, seqNAK)
require.Equal(t, uint32(9), recv.maxSeenSequenceNumber.Val())
recv.Tick(10) // ACK period
require.Equal(t, uint32(5), seqACK)
require.Equal(t, []uint32{5, 6}, seqNAK)
require.Equal(t, uint32(9), recv.maxSeenSequenceNumber.Val())
recv.Tick(20) // ACK period, NAK period
require.Equal(t, uint32(5), seqACK)
require.Equal(t, []uint32{5, 6}, seqNAK)
require.Equal(t, uint32(9), recv.maxSeenSequenceNumber.Val())
}
func TestRecvACK(t *testing.T) {
seqACK := uint32(0)
seqNAK := []uint32{}
numbers := []uint32{}
recv := mockLiveRecv(
func(seq circular.Number, light bool) {
seqACK = seq.Val()
},
func(list []circular.Number) {
seqNAK = []uint32{}
for _, sn := range list {
seqNAK = append(seqNAK, sn.Val())
}
},
func(p packet.Packet) {
numbers = append(numbers, p.Header().PacketSequenceNumber.Val())
},
)
addr, _ := net.ResolveIPAddr("ip", "127.0.0.1")
for i := range 5 {
p := packet.NewPacket(addr)
p.Header().PacketSequenceNumber = circular.New(uint32(i), packet.MAX_SEQUENCENUMBER)
p.Header().PktTsbpdTime = uint64(10 + i + 1)
recv.Push(p)
}
require.Equal(t, uint32(0), seqACK)
require.Equal(t, []uint32{}, seqNAK)
require.Equal(t, uint32(4), recv.maxSeenSequenceNumber.Val())
require.Equal(t, uint32(0), recv.lastACKSequenceNumber.Inc().Val())
require.Equal(t, uint32(0), recv.lastDeliveredSequenceNumber.Inc().Val())
require.Exactly(t, []uint32{}, numbers)
for i := 7; i < 10; i++ {
p := packet.NewPacket(addr)
p.Header().PacketSequenceNumber = circular.New(uint32(i), packet.MAX_SEQUENCENUMBER)
p.Header().PktTsbpdTime = uint64(30 + i + 1)
recv.Push(p)
}
require.Equal(t, uint32(0), seqACK)
require.Equal(t, []uint32{5, 6}, seqNAK)
require.Equal(t, uint32(9), recv.maxSeenSequenceNumber.Val())
require.Equal(t, uint32(0), recv.lastACKSequenceNumber.Inc().Val())
require.Equal(t, uint32(0), recv.lastDeliveredSequenceNumber.Inc().Val())
require.Exactly(t, []uint32{}, numbers)
for i := 15; i < 20; i++ {
p := packet.NewPacket(addr)
p.Header().PacketSequenceNumber = circular.New(uint32(i), packet.MAX_SEQUENCENUMBER)
p.Header().PktTsbpdTime = uint64(30 + i + 1)
recv.Push(p)
}
require.Equal(t, uint32(0), seqACK)
require.Equal(t, []uint32{10, 14}, seqNAK)
require.Equal(t, uint32(19), recv.maxSeenSequenceNumber.Val())
require.Equal(t, uint32(0), recv.lastACKSequenceNumber.Inc().Val())
require.Equal(t, uint32(0), recv.lastDeliveredSequenceNumber.Inc().Val())
require.Exactly(t, []uint32{}, numbers)
recv.Tick(10)
require.Equal(t, uint32(5), seqACK)
require.Equal(t, []uint32{10, 14}, seqNAK)
require.Equal(t, uint32(19), recv.maxSeenSequenceNumber.Val())
require.Equal(t, uint32(5), recv.lastACKSequenceNumber.Inc().Val())
require.Equal(t, uint32(0), recv.lastDeliveredSequenceNumber.Inc().Val())
require.Exactly(t, []uint32{}, numbers)
recv.Tick(20)
require.Equal(t, uint32(5), seqACK)
require.Equal(t, []uint32{5, 6, 10, 14}, seqNAK)
require.Equal(t, uint32(19), recv.maxSeenSequenceNumber.Val())
require.Equal(t, uint32(5), recv.lastACKSequenceNumber.Inc().Val())
require.Equal(t, uint32(5), recv.lastDeliveredSequenceNumber.Inc().Val())
require.Exactly(t, []uint32{0, 1, 2, 3, 4}, numbers)
recv.Tick(30)
require.Equal(t, uint32(5), seqACK)
require.Equal(t, []uint32{5, 6, 10, 14}, seqNAK)
require.Equal(t, uint32(19), recv.maxSeenSequenceNumber.Val())
require.Equal(t, uint32(5), recv.lastACKSequenceNumber.Inc().Val())
require.Equal(t, uint32(5), recv.lastDeliveredSequenceNumber.Inc().Val())
require.Exactly(t, []uint32{0, 1, 2, 3, 4}, numbers)
for i := 5; i < 7; i++ {
p := packet.NewPacket(addr)
p.Header().PacketSequenceNumber = circular.New(uint32(i), packet.MAX_SEQUENCENUMBER)
p.Header().PktTsbpdTime = uint64(30 + i + 1)
recv.Push(p)
}
recv.Tick(40)
require.Equal(t, uint32(10), seqACK)
require.Equal(t, []uint32{10, 14}, seqNAK)
require.Equal(t, uint32(19), recv.maxSeenSequenceNumber.Val())
require.Equal(t, uint32(10), recv.lastACKSequenceNumber.Inc().Val())
require.Equal(t, uint32(10), recv.lastDeliveredSequenceNumber.Inc().Val())
require.Exactly(t, []uint32{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, numbers)
}
func TestRecvDropTooLate(t *testing.T) {
recv := mockLiveRecv(
nil,
nil,
nil,
)
addr, _ := net.ResolveIPAddr("ip", "127.0.0.1")
for i := range 10 {
p := packet.NewPacket(addr)
p.Header().PacketSequenceNumber = circular.New(uint32(i), packet.MAX_SEQUENCENUMBER)
p.Header().PktTsbpdTime = uint64(i + 1)
recv.Push(p)
}
recv.Tick(10) // ACK period
stats := recv.Stats()
require.Equal(t, uint32(9), recv.lastACKSequenceNumber.Val())
require.Equal(t, uint32(9), recv.lastDeliveredSequenceNumber.Val())
require.Equal(t, uint32(9), recv.maxSeenSequenceNumber.Val())
require.Equal(t, uint64(0), stats.PktDrop)
p := packet.NewPacket(addr)
p.Header().PacketSequenceNumber = circular.New(uint32(3), packet.MAX_SEQUENCENUMBER)
p.Header().PktTsbpdTime = uint64(4)
recv.Push(p)
stats = recv.Stats()
require.Equal(t, uint64(1), stats.PktDrop)
}
func TestRecvDropAlreadyACK(t *testing.T) {
recv := mockLiveRecv(
nil,
nil,
nil,
)
addr, _ := net.ResolveIPAddr("ip", "127.0.0.1")
for i := range 5 {
p := packet.NewPacket(addr)
p.Header().PacketSequenceNumber = circular.New(uint32(i), packet.MAX_SEQUENCENUMBER)
p.Header().PktTsbpdTime = uint64(i + 1)
recv.Push(p)
}
for i := 5; i < 10; i++ {
p := packet.NewPacket(addr)
p.Header().PacketSequenceNumber = circular.New(uint32(i), packet.MAX_SEQUENCENUMBER)
p.Header().PktTsbpdTime = uint64(10 + i + 1)
recv.Push(p)
}
recv.Tick(10) // ACK period
stats := recv.Stats()
require.Equal(t, uint32(9), recv.lastACKSequenceNumber.Val())
require.Equal(t, uint32(4), recv.lastDeliveredSequenceNumber.Val())
require.Equal(t, uint32(9), recv.maxSeenSequenceNumber.Val())
require.Equal(t, uint64(0), stats.PktDrop)
p := packet.NewPacket(addr)
p.Header().PacketSequenceNumber = circular.New(uint32(6), packet.MAX_SEQUENCENUMBER)
p.Header().PktTsbpdTime = uint64(7)
recv.Push(p)
stats = recv.Stats()
require.Equal(t, uint64(1), stats.PktDrop)
}
func TestRecvDropAlreadyRecvNoACK(t *testing.T) {
recv := mockLiveRecv(
nil,
nil,
nil,
)
addr, _ := net.ResolveIPAddr("ip", "127.0.0.1")
for i := range 5 {
p := packet.NewPacket(addr)
p.Header().PacketSequenceNumber = circular.New(uint32(i), packet.MAX_SEQUENCENUMBER)
p.Header().PktTsbpdTime = uint64(i + 1)
recv.Push(p)
}
for i := 5; i < 10; i++ {
p := packet.NewPacket(addr)
p.Header().PacketSequenceNumber = circular.New(uint32(i), packet.MAX_SEQUENCENUMBER)
p.Header().PktTsbpdTime = uint64(10 + i + 1)
recv.Push(p)
}
recv.Tick(10) // ACK period
for i := range 10 {
p := packet.NewPacket(addr)
p.Header().PacketSequenceNumber = circular.New(uint32(10+i), packet.MAX_SEQUENCENUMBER)
p.Header().PktTsbpdTime = uint64(20 + i + 1)
recv.Push(p)
}
stats := recv.Stats()
require.Equal(t, uint32(9), recv.lastACKSequenceNumber.Val())
require.Equal(t, uint32(4), recv.lastDeliveredSequenceNumber.Val())
require.Equal(t, uint32(19), recv.maxSeenSequenceNumber.Val())
require.Equal(t, uint64(0), stats.PktDrop)
p := packet.NewPacket(addr)
p.Header().PacketSequenceNumber = circular.New(uint32(15), packet.MAX_SEQUENCENUMBER)
p.Header().PktTsbpdTime = uint64(20 + 6)
recv.Push(p)
stats = recv.Stats()
require.Equal(t, uint64(1), stats.PktDrop)
}
func TestRecvFlush(t *testing.T) {
recv := mockLiveRecv(
nil,
nil,
nil,
)
addr, _ := net.ResolveIPAddr("ip", "127.0.0.1")
for i := range 10 {
p := packet.NewPacket(addr)
p.Header().PacketSequenceNumber = circular.New(uint32(i), packet.MAX_SEQUENCENUMBER)
p.Header().PktTsbpdTime = uint64(i + 1)
recv.Push(p)
}
require.Equal(t, 10, recv.packetList.Len())
recv.Flush()
require.Equal(t, 0, recv.packetList.Len())
}
func TestRecvPeriodicACKLite(t *testing.T) {
liteACK := false
recv := mockLiveRecv(
func(seq circular.Number, light bool) {
liteACK = light
},
nil,
nil,
)
addr, _ := net.ResolveIPAddr("ip", "127.0.0.1")
for i := range 100 {
p := packet.NewPacket(addr)
p.Header().PacketSequenceNumber = circular.New(uint32(i), packet.MAX_SEQUENCENUMBER)
p.Header().PktTsbpdTime = uint64(10 + i + 1)
recv.Push(p)
}
require.Equal(t, false, liteACK)
recv.Tick(1)
require.Equal(t, true, liteACK)
}
func TestSkipTooLate(t *testing.T) {
seqACK := uint32(0)
numbers := []uint32{}
recv := mockLiveRecv(
func(seq circular.Number, light bool) {
seqACK = seq.Val()
},
nil,
func(p packet.Packet) {
numbers = append(numbers, p.Header().PacketSequenceNumber.Val())
},
)
addr, _ := net.ResolveIPAddr("ip", "127.0.0.1")
for i := range 5 {
p := packet.NewPacket(addr)
p.Header().PacketSequenceNumber = circular.New(uint32(i), packet.MAX_SEQUENCENUMBER)
p.Header().PktTsbpdTime = uint64(i + 1)
recv.Push(p)
}
recv.Tick(10)
require.Equal(t, uint32(5), seqACK)
require.Equal(t, []uint32{0, 1, 2, 3, 4}, numbers)
for i := 5; i < 10; i++ {
p := packet.NewPacket(addr)
p.Header().PacketSequenceNumber = circular.New(uint32(3+i), packet.MAX_SEQUENCENUMBER)
p.Header().PktTsbpdTime = uint64(13 + i + 1)
recv.Push(p)
}
recv.Tick(20)
require.Equal(t, uint32(13), seqACK)
require.Equal(t, []uint32{0, 1, 2, 3, 4, 8, 9}, numbers)
}
func TestIssue67(t *testing.T) {
ackNumbers := []uint32{}
nakNumbers := [][2]uint32{}
numbers := []uint32{}
recv := mockLiveRecv(
func(seq circular.Number, light bool) {
ackNumbers = append(ackNumbers, seq.Val())
},
func(list []circular.Number) {
nakNumbers = append(nakNumbers, [2]uint32{list[0].Val(), list[1].Val()})
},
func(p packet.Packet) {
numbers = append(numbers, p.Header().PacketSequenceNumber.Val())
},
)
addr, _ := net.ResolveIPAddr("ip", "127.0.0.1")
p := packet.NewPacket(addr)
p.Header().PacketSequenceNumber = circular.New(0, packet.MAX_SEQUENCENUMBER)
p.Header().PktTsbpdTime = 1
recv.Push(p)
recv.Tick(10)
recv.Tick(20)
recv.Tick(30)
recv.Tick(40)
recv.Tick(50)
recv.Tick(60)
recv.Tick(70)
recv.Tick(80)
recv.Tick(90)
require.Equal(t, []uint32{1, 1, 1, 1, 1, 1, 1, 1, 1}, ackNumbers)
p = packet.NewPacket(addr)
p.Header().PacketSequenceNumber = circular.New(12, packet.MAX_SEQUENCENUMBER)
p.Header().PktTsbpdTime = 121
recv.Push(p)
require.Equal(t, [][2]uint32{
{1, 11},
}, nakNumbers)
p = packet.NewPacket(addr)
p.Header().PacketSequenceNumber = circular.New(1, packet.MAX_SEQUENCENUMBER)
p.Header().PktTsbpdTime = 11
recv.Push(p)
p = packet.NewPacket(addr)
p.Header().PacketSequenceNumber = circular.New(11, packet.MAX_SEQUENCENUMBER)
p.Header().PktTsbpdTime = 111
recv.Push(p)
recv.Tick(100)
require.Equal(t, []uint32{1, 1, 1, 1, 1, 1, 1, 1, 1, 2}, ackNumbers)
recv.Tick(110)
require.Equal(t, []uint32{1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2}, ackNumbers)
recv.Tick(120)
require.Equal(t, []uint32{1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 13}, ackNumbers)
recv.Tick(130)
require.Equal(t, []uint32{1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 13, 13}, ackNumbers)
}
================================================
FILE: congestion/live/send.go
================================================
package live
import (
"container/list"
"sync"
"time"
"github.com/datarhei/gosrt/circular"
"github.com/datarhei/gosrt/congestion"
"github.com/datarhei/gosrt/packet"
)
// SendConfig is the configuration for the liveSend congestion control
type SendConfig struct {
InitialSequenceNumber circular.Number
DropThreshold uint64
MaxBW int64
InputBW int64
MinInputBW int64
OverheadBW int64
OnDeliver func(p packet.Packet)
}
// sender implements the Sender interface
type sender struct {
nextSequenceNumber circular.Number
dropThreshold uint64
packetList *list.List
lossList *list.List
lock sync.RWMutex
avgPayloadSize float64 // bytes
pktSndPeriod float64 // microseconds
maxBW float64 // bytes/s
inputBW float64 // bytes/s
overheadBW float64 // percent
statistics congestion.SendStats
probeTime uint64
rate struct {
period uint64 // microseconds
last uint64
bytes uint64
bytesSent uint64
bytesRetrans uint64
estimatedInputBW float64 // bytes/s
estimatedSentBW float64 // bytes/s
pktLossRate float64
}
deliver func(p packet.Packet)
}
// NewSender takes a SendConfig and returns a new Sender
func NewSender(config SendConfig) congestion.Sender {
s := &sender{
nextSequenceNumber: config.InitialSequenceNumber,
dropThreshold: config.DropThreshold,
packetList: list.New(),
lossList: list.New(),
avgPayloadSize: packet.MAX_PAYLOAD_SIZE, // 5.1.2. SRT's Default LiveCC Algorithm
maxBW: float64(config.MaxBW),
inputBW: float64(config.InputBW),
overheadBW: float64(config.OverheadBW),
deliver: config.OnDeliver,
}
if s.deliver == nil {
s.deliver = func(p packet.Packet) {}
}
s.maxBW = 128 * 1024 * 1024 // 1 Gbit/s
s.pktSndPeriod = (s.avgPayloadSize + 16) * 1_000_000 / s.maxBW
s.rate.period = uint64(time.Second.Microseconds())
s.rate.last = 0
return s
}
func (s *sender) Stats() congestion.SendStats {
s.lock.Lock()
defer s.lock.Unlock()
s.statistics.UsPktSndPeriod = s.pktSndPeriod
s.statistics.BytePayload = uint64(s.avgPayloadSize)
s.statistics.MsBuf = 0
max := s.lossList.Back()
min := s.lossList.Front()
if max != nil && min != nil {
s.statistics.MsBuf = (max.Value.(packet.Packet).Header().PktTsbpdTime - min.Value.(packet.Packet).Header().PktTsbpdTime) / 1_000
}
s.statistics.MbpsEstimatedInputBandwidth = s.rate.estimatedInputBW * 8 / 1024 / 1024
s.statistics.MbpsEstimatedSentBandwidth = s.rate.estimatedSentBW * 8 / 1024 / 1024
s.statistics.PktLossRate = s.rate.pktLossRate
return s.statistics
}
func (s *sender) Flush() {
s.lock.Lock()
defer s.lock.Unlock()
s.packetList = s.packetList.Init()
s.lossList = s.lossList.Init()
}
func (s *sender) Push(p packet.Packet) {
s.lock.Lock()
defer s.lock.Unlock()
if p == nil {
return
}
// Give to the packet a sequence number
p.Header().PacketSequenceNumber = s.nextSequenceNumber
p.Header().PacketPositionFlag = packet.SinglePacket
p.Header().OrderFlag = false
p.Header().MessageNumber = 1
s.nextSequenceNumber = s.nextSequenceNumber.Inc()
pktLen := p.Len()
s.statistics.PktBuf++
s.statistics.ByteBuf += pktLen
// Input bandwidth calculation
s.rate.bytes += pktLen
p.Header().Timestamp = uint32(p.Header().PktTsbpdTime & uint64(packet.MAX_TIMESTAMP))
// Every 16th and 17th packet should be sent at the same time in order
// for the receiver to determine the link capacity. Not really well
// documented in the specs.
// PktTsbpdTime is used for the timing of sending the packets. Here we
// can modify it because it has already been used to set the packet's
// timestamp.
probe := p.Header().PacketSequenceNumber.Val() & 0xF
if probe == 0 {
s.probeTime = p.Header().PktTsbpdTime
} else if probe == 1 {
p.Header().PktTsbpdTime = s.probeTime
}
s.packetList.PushBack(p)
s.statistics.PktFlightSize = uint64(s.packetList.Len())
}
func (s *sender) Tick(now uint64) {
// Deliver packets whose PktTsbpdTime is ripe
s.lock.Lock()
removeList := make([]*list.Element, 0, s.packetList.Len())
for e := s.packetList.Front(); e != nil; e = e.Next() {
p := e.Value.(packet.Packet)
if p.Header().PktTsbpdTime <= now {
s.statistics.Pkt++
s.statistics.PktUnique++
pktLen := p.Len()
s.statistics.Byte += pktLen
s.statistics.ByteUnique += pktLen
s.statistics.UsSndDuration += uint64(s.pktSndPeriod)
// 5.1.2. SRT's Default LiveCC Algorithm
s.avgPayloadSize = 0.875*s.avgPayloadSize + 0.125*float64(pktLen)
s.rate.bytesSent += pktLen
s.deliver(p)
removeList = append(removeList, e)
} else {
break
}
}
for _, e := range removeList {
s.lossList.PushBack(e.Value)
s.packetList.Remove(e)
}
s.lock.Unlock()
s.lock.Lock()
removeList = make([]*list.Element, 0, s.lossList.Len())
for e := s.lossList.Front(); e != nil; e = e.Next() {
p := e.Value.(packet.Packet)
if p.Header().PktTsbpdTime+s.dropThreshold <= now {
// Dropped packet because too old
s.statistics.PktDrop++
s.statistics.PktLoss++
s.statistics.ByteDrop += p.Len()
s.statistics.ByteLoss += p.Len()
removeList = append(removeList, e)
}
}
// These packets are not needed anymore (too late)
for _, e := range removeList {
p := e.Value.(packet.Packet)
s.statistics.PktBuf--
s.statistics.ByteBuf -= p.Len()
s.lossList.Remove(e)
// This packet has been ACK'd and we don't need it anymore
p.Decommission()
}
s.lock.Unlock()
s.lock.Lock()
tdiff := now - s.rate.last
if tdiff > s.rate.period {
s.rate.estimatedInputBW = float64(s.rate.bytes) / (float64(tdiff) / 1000 / 1000)
s.rate.estimatedSentBW = float64(s.rate.bytesSent) / (float64(tdiff) / 1000 / 1000)
if s.rate.bytesSent != 0 {
s.rate.pktLossRate = float64(s.rate.bytesRetrans) / float64(s.rate.bytesSent) * 100
} else {
s.rate.pktLossRate = 0
}
s.rate.bytes = 0
s.rate.bytesSent = 0
s.rate.bytesRetrans = 0
s.rate.last = now
}
s.lock.Unlock()
}
func (s *sender) ACK(sequenceNumber circular.Number) {
s.lock.Lock()
defer s.lock.Unlock()
removeList := make([]*list.Element, 0, s.lossList.Len())
for e := s.lossList.Front(); e != nil; e = e.Next() {
p := e.Value.(packet.Packet)
if p.Header().PacketSequenceNumber.Lt(sequenceNumber) {
// Remove packet from buffer because it has been successfully transmitted
removeList = append(removeList, e)
} else {
break
}
}
// These packets are not needed anymore (ACK'd)
for _, e := range removeList {
p := e.Value.(packet.Packet)
s.statistics.PktBuf--
s.statistics.ByteBuf -= p.Len()
s.lossList.Remove(e)
// This packet has been ACK'd and we don't need it anymore
p.Decommission()
}
s.pktSndPeriod = (s.avgPayloadSize + 16) * 1000000 / s.maxBW
}
func (s *sender) NAK(sequenceNumbers []circular.Number) {
if len(sequenceNumbers) == 0 {
return
}
s.lock.Lock()
defer s.lock.Unlock()
for e := s.lossList.Back(); e != nil; e = e.Prev() {
p := e.Value.(packet.Packet)
for i := 0; i < len(sequenceNumbers); i += 2 {
if p.Header().PacketSequenceNumber.Gte(sequenceNumbers[i]) && p.Header().PacketSequenceNumber.Lte(sequenceNumbers[i+1]) {
s.statistics.PktRetrans++
s.statistics.Pkt++
s.statistics.PktLoss++
s.statistics.ByteRetrans += p.Len()
s.statistics.Byte += p.Len()
s.statistics.ByteLoss += p.Len()
// 5.1.2. SRT's Default LiveCC Algorithm
s.avgPayloadSize = 0.875*s.avgPayloadSize + 0.125*float64(p.Len())
s.rate.bytesSent += p.Len()
s.rate.bytesRetrans += p.Len()
p.Header().RetransmittedPacketFlag = true
s.deliver(p)
}
}
}
}
func (s *sender) SetDropThreshold(threshold uint64) {
s.lock.Lock()
defer s.lock.Unlock()
s.dropThreshold = threshold
}
================================================
FILE: congestion/live/send_test.go
================================================
package live
import (
"net"
"testing"
"github.com/datarhei/gosrt/circular"
"github.com/datarhei/gosrt/packet"
"github.com/stretchr/testify/require"
)
func mockLiveSend(onDeliver func(p packet.Packet)) *sender {
send := NewSender(SendConfig{
InitialSequenceNumber: circular.New(0, packet.MAX_SEQUENCENUMBER),
DropThreshold: 10,
OnDeliver: onDeliver,
})
return send.(*sender)
}
func TestSendSequence(t *testing.T) {
numbers := []uint32{}
send := mockLiveSend(func(p packet.Packet) {
numbers = append(numbers, p.Header().PacketSequenceNumber.Val())
})
addr, _ := net.ResolveIPAddr("ip", "127.0.0.1")
for i := range 10 {
p := packet.NewPacket(addr)
p.Header().PktTsbpdTime = uint64(i + 1)
send.Push(p)
}
send.Tick(5)
require.Exactly(t, []uint32{0, 1, 2, 3, 4}, numbers)
send.Tick(10)
require.Exactly(t, []uint32{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, numbers)
}
func TestSendLossListACK(t *testing.T) {
send := mockLiveSend(nil)
addr, _ := net.ResolveIPAddr("ip", "127.0.0.1")
for i := range 10 {
p := packet.NewPacket(addr)
p.Header().PktTsbpdTime = uint64(i + 1)
send.Push(p)
}
send.Tick(10)
require.Equal(t, 10, send.lossList.Len())
for i := range 10 {
send.ACK(circular.New(uint32(i+1), packet.MAX_SEQUENCENUMBER))
require.Equal(t, 10-(i+1), send.lossList.Len())
}
}
func TestSendRetransmit(t *testing.T) {
numbers := []uint32{}
nRetransmit := 0
send := mockLiveSend(func(p packet.Packet) {
numbers = append(numbers, p.Header().PacketSequenceNumber.Val())
if p.Header().RetransmittedPacketFlag {
nRetransmit++
}
})
addr, _ := net.ResolveIPAddr("ip", "127.0.0.1")
for i := range 10 {
p := packet.NewPacket(addr)
p.Header().PktTsbpdTime = uint64(i + 1)
send.Push(p)
}
send.Tick(10)
require.Equal(t, 0, nRetransmit)
send.NAK([]circular.Number{
circular.New(2, packet.MAX_SEQUENCENUMBER),
circular.New(2, packet.MAX_SEQUENCENUMBER),
})
require.Equal(t, 1, nRetransmit)
send.NAK([]circular.Number{
circular.New(5, packet.MAX_SEQUENCENUMBER),
circular.New(7, packet.MAX_SEQUENCENUMBER),
})
require.Equal(t, 4, nRetransmit)
}
func TestSendDrop(t *testing.T) {
send := mockLiveSend(nil)
addr, _ := net.ResolveIPAddr("ip", "127.0.0.1")
for i := range 10 {
p := packet.NewPacket(addr)
p.Header().PktTsbpdTime = uint64(i + 1)
send.Push(p)
}
send.Tick(10)
require.Equal(t, 10, send.lossList.Len())
send.Tick(20)
require.Equal(t, 0, send.lossList.Len())
}
func TestSendFlush(t *testing.T) {
send := mockLiveSend(nil)
addr, _ := net.ResolveIPAddr("ip", "127.0.0.1")
for i := range 10 {
p := packet.NewPacket(addr)
p.Header().PktTsbpdTime = uint64(i + 1)
send.Push(p)
}
require.Exactly(t, 10, send.packetList.Len())
require.Exactly(t, 0, send.lossList.Len())
send.Tick(5)
require.Exactly(t, 5, send.packetList.Len())
require.Exactly(t, 5, send.lossList.Len())
send.Flush()
require.Exactly(t, 0, send.packetList.Len())
require.Exactly(t, 0, send.lossList.Len())
}
================================================
FILE: conn_request.go
================================================
package srt
import (
"fmt"
"net"
"time"
"github.com/datarhei/gosrt/crypto"
"github.com/datarhei/gosrt/packet"
"github.com/datarhei/gosrt/rand"
)
// ConnRequest is an incoming connection request
type ConnRequest interface {
// RemoteAddr returns the address of the peer. The returned net.Addr
// is a copy and can be used at will.
RemoteAddr() net.Addr
// Version returns the handshake version of the incoming request. Currently
// known versions are 4 and 5. With version 4 the StreamId will always be
// empty and IsEncrypted will always return false. An incoming version 4
// connection will always be publishing.
Version() uint32
// StreamId returns the streamid of the requesting connection. Use this
// to decide what to do with the connection.
StreamId() string
// SocketId return the socketid of the connection.
SocketId() uint32
// PeerSocketId returns the socketid of the peer of the connection.
PeerSocketId() uint32
// IsEncrypted returns whether the connection is encrypted. If it is
// encrypted, use SetPassphrase to set the passphrase for decrypting.
IsEncrypted() bool
// SetPassphrase sets the passphrase in order to decrypt the incoming
// data. Returns an error if the passphrase did not work or the connection
// is not encrypted.
SetPassphrase(p string) error
// SetRejectionReason sets the rejection reason for the connection. If
// no set, REJ_PEER will be used.
//
// Deprecated: replaced by Reject().
SetRejectionReason(r RejectionReason)
// Accept accepts the request and returns a connection.
Accept() (Conn, error)
// Reject rejects the request.
Reject(r RejectionReason)
}
// connRequest implements the ConnRequest interface
type connRequest struct {
ln *listener
addr net.Addr
localAddr net.Addr
start time.Time
socketId uint32
peerSocketId uint32
timestamp uint32
config Config
handshake *packet.CIFHandshake
crypto crypto.Crypto
passphrase string
rejectionReason RejectionReason
}
func newConnRequest(ln *listener, p packet.Packet) *connRequest {
cif := &packet.CIFHandshake{}
err := p.UnmarshalCIF(cif)
ln.log("handshake:recv:dump", func() string { return p.Dump() })
ln.log("handshake:recv:cif", func() string { return cif.String() })
if err != nil {
ln.log("handshake:recv:error", func() string { return err.Error() })
return nil
}
// Assemble the response (4.3.1. Caller-Listener Handshake)
p.Header().ControlType = packet.CTRLTYPE_HANDSHAKE
p.Header().SubType = 0
p.Header().TypeSpecific = 0
p.Header().Timestamp = uint32(time.Since(ln.start).Microseconds())
p.Header().DestinationSocketId = cif.SRTSocketId
cif.PeerIP.FromNetAddr(ln.addr)
// Create a copy of the configuration for the connection
config := ln.config
if cif.HandshakeType == packet.HSTYPE_INDUCTION {
// cif
cif.Version = 5
cif.EncryptionField = 0 // Don't advertise any specific encryption method
cif.ExtensionField = 0x4A17
//cif.initialPacketSequenceNumber = newCircular(0, MAX_SEQUENCENUMBER)
//cif.maxTransmissionUnitSize = 0
//cif.maxFlowWindowSize = 0
//cif.SRTSocketId = 0
cif.SynCookie = ln.syncookie.Get(p.Header().Addr.String())
p.MarshalCIF(cif)
ln.log("handshake:send:dump", func() string { return p.Dump() })
ln.log("handshake:send:cif", func() string { return cif.String() })
ln.send(p)
} else if cif.HandshakeType == packet.HSTYPE_CONCLUSION {
// Verify the SYN cookie
if !ln.syncookie.Verify(cif.SynCookie, p.Header().Addr.String()) {
cif.HandshakeType = packet.HandshakeType(REJ_ROGUE)
ln.log("handshake:recv:error", func() string { return "invalid SYN cookie" })
p.MarshalCIF(cif)
ln.log("handshake:send:dump", func() string { return p.Dump() })
ln.log("handshake:send:cif", func() string { return cif.String() })
ln.send(p)
return nil
}
// Peer is advertising a too big MSS
if cif.MaxTransmissionUnitSize > MAX_MSS_SIZE {
cif.HandshakeType = packet.HandshakeType(REJ_ROGUE)
ln.log("handshake:recv:error", func() string { return fmt.Sprintf("MTU is too big (%d bytes)", cif.MaxTransmissionUnitSize) })
p.MarshalCIF(cif)
ln.log("handshake:send:dump", func() string { return p.Dump() })
ln.log("handshake:send:cif", func() string { return cif.String() })
ln.send(p)
return nil
}
// If the peer has a smaller MTU size, adjust to it
if cif.MaxTransmissionUnitSize < config.MSS {
config.MSS = cif.MaxTransmissionUnitSize
config.PayloadSize = config.MSS - SRT_HEADER_SIZE - UDP_HEADER_SIZE
if config.PayloadSize < MIN_PAYLOAD_SIZE {
cif.HandshakeType = packet.HandshakeType(REJ_ROGUE)
ln.log("handshake:recv:error", func() string { return fmt.Sprintf("payload size is too small (%d bytes)", config.PayloadSize) })
p.MarshalCIF(cif)
ln.log("handshake:send:dump", func() string { return p.Dump() })
ln.log("handshake:send:cif", func() string { return cif.String() })
ln.send(p)
}
}
// We only support HSv4 and HSv5
if cif.Version == 4 {
// Check if the type (encryption field + extension field) has the value 2
if cif.EncryptionField != 0 || cif.ExtensionField != 2 {
cif.HandshakeType = packet.HandshakeType(REJ_ROGUE)
ln.log("handshake:recv:error", func() string { return "invalid type, expecting a value of 2 (UDT_DGRAM)" })
p.MarshalCIF(cif)
ln.log("handshake:send:dump", func() string { return p.Dump() })
ln.log("handshake:send:cif", func() string { return cif.String() })
ln.send(p)
return nil
}
} else if cif.Version == 5 {
if cif.SRTHS == nil {
cif.HandshakeType = packet.HandshakeType(REJ_ROGUE)
ln.log("handshake:recv:error", func() string { return "missing handshake extension" })
p.MarshalCIF(cif)
ln.log("handshake:send:dump", func() string { return p.Dump() })
ln.log("handshake:send:cif", func() string { return cif.String() })
ln.send(p)
return nil
}
// Check if the peer version is sufficient
if cif.SRTHS.SRTVersion < config.MinVersion {
cif.HandshakeType = packet.HandshakeType(REJ_VERSION)
ln.log("handshake:recv:error", func() string {
return fmt.Sprintf("peer version insufficient (%#06x), expecting at least %#06x", cif.SRTHS.SRTVersion, config.MinVersion)
})
p.MarshalCIF(cif)
ln.log("handshake:send:dump", func() string { return p.Dump() })
ln.log("handshake:send:cif", func() string { return cif.String() })
ln.send(p)
return nil
}
// Check the required SRT flags
if !cif.SRTHS.SRTFlags.TSBPDSND || !cif.SRTHS.SRTFlags.TSBPDRCV || !cif.SRTHS.SRTFlags.TLPKTDROP || !cif.SRTHS.SRTFlags.PERIODICNAK || !cif.SRTHS.SRTFlags.REXMITFLG {
cif.HandshakeType = packet.HandshakeType(REJ_ROGUE)
ln.log("handshake:recv:error", func() string { return "not all required flags are set" })
p.MarshalCIF(cif)
ln.log("handshake:send:dump", func() string { return p.Dump() })
ln.log("handshake:send:cif", func() string { return cif.String() })
ln.send(p)
return nil
}
// We only support live streaming
if cif.SRTHS.SRTFlags.STREAM {
cif.HandshakeType = packet.HandshakeType(REJ_MESSAGEAPI)
ln.log("handshake:recv:error", func() string { return "only live streaming is supported" })
p.MarshalCIF(cif)
ln.log("handshake:send:dump", func() string { return p.Dump() })
ln.log("handshake:send:cif", func() string { return cif.String() })
ln.send(p)
return nil
}
// We only support live congestion control
if cif.HasCongestionCtl && cif.CongestionCtl != "live" {
cif.HandshakeType = packet.HandshakeType(REJ_CONGESTION)
ln.log("handshake:recv:error", func() string { return "only live congestion control is supported" })
p.MarshalCIF(cif)
ln.log("handshake:send:dump", func() string { return p.Dump() })
ln.log("handshake:send:cif", func() string { return cif.String() })
ln.send(p)
return nil
}
} else {
cif.HandshakeType = packet.HandshakeType(REJ_ROGUE)
ln.log("handshake:recv:error", func() string { return fmt.Sprintf("only HSv4 and HSv5 are supported (got HSv%d)", cif.Version) })
p.MarshalCIF(cif)
ln.log("handshake:send:dump", func() string { return p.Dump() })
ln.log("handshake:send:cif", func() string { return cif.String() })
ln.send(p)
return nil
}
req := &connRequest{
ln: ln,
addr: p.Header().Addr,
localAddr: p.Header().LocalAddr,
start: time.Now(),
peerSocketId: cif.SRTSocketId,
timestamp: p.Header().Timestamp,
config: config,
handshake: cif,
}
if cif.SRTKM != nil {
cr, err := crypto.New(int(cif.SRTKM.KLen))
if err != nil {
cif.HandshakeType = packet.HandshakeType(REJ_ROGUE)
ln.log("handshake:recv:error", func() string { return fmt.Sprintf("crypto: %s", err) })
p.MarshalCIF(cif)
ln.log("handshake:send:dump", func() string { return p.Dump() })
ln.log("handshake:send:cif", func() string { return cif.String() })
ln.send(p)
return nil
}
req.crypto = cr
}
ln.lock.Lock()
// We received a duplicate request: reject silently
_, exists := ln.connsByPeer[cif.SRTSocketId]
if exists {
ln.lock.Unlock()
return nil
}
// Already fill connsByPeer for this connection
ln.connsByPeer[cif.SRTSocketId] = nil
// Already reserve a socketId for this connection
socketId, err := req.generateSocketId()
if err == nil {
ln.conns[socketId] = nil
req.socketId = socketId
}
ln.lock.Unlock()
// We couldn't create a socketId: reject silently
if err != nil {
return nil
}
return req
} else {
if cif.HandshakeType.IsRejection() {
ln.log("handshake:recv:error", func() string { return fmt.Sprintf("connection rejected: %s", cif.HandshakeType.String()) })
} else {
ln.log("handshake:recv:error", func() string { return fmt.Sprintf("unsupported handshake: %s", cif.HandshakeType.String()) })
}
}
return nil
}
func (req *connRequest) RemoteAddr() net.Addr {
addr, _ := net.ResolveUDPAddr("udp", req.addr.String())
return addr
}
func (req *connRequest) Version() uint32 {
return req.handshake.Version
}
func (req *connRequest) StreamId() string {
return req.handshake.StreamId
}
func (req *connRequest) SocketId() uint32 {
return req.socketId
}
func (req *connRequest) PeerSocketId() uint32 {
return req.peerSocketId
}
func (req *connRequest) IsEncrypted() bool {
return req.crypto != nil
}
func (req *connRequest) SetPassphrase(passphrase string) error {
if req.handshake.Version == 5 {
if req.crypto == nil {
return fmt.Errorf("listen: request without encryption")
}
if err := req.crypto.UnmarshalKM(req.handshake.SRTKM, passphrase); err != nil {
return err
}
}
req.passphrase = passphrase
return nil
}
func (req *connRequest) SetRejectionReason(reason RejectionReason) {
req.rejectionReason = reason
}
func (req *connRequest) Reject(reason RejectionReason) {
req.ln.lock.Lock()
defer req.ln.lock.Unlock()
if cr, hasReq := req.ln.connsByPeer[req.peerSocketId]; !hasReq || cr != nil {
return
}
p := packet.NewPacket(req.addr)
p.Header().IsControlPacket = true
p.Header().ControlType = packet.CTRLTYPE_HANDSHAKE
p.Header().SubType = 0
p.Header().TypeSpecific = 0
p.Header().Timestamp = uint32(time.Since(req.ln.start).Microseconds())
p.Header().DestinationSocketId = req.peerSocketId
p.Header().LocalAddr = req.localAddr
req.handshake.HandshakeType = packet.HandshakeType(reason)
p.MarshalCIF(req.handshake)
req.ln.log("handshake:send:dump", func() string { return p.Dump() })
req.ln.log("handshake:send:cif", func() string { return req.handshake.String() })
req.ln.send(p)
delete(req.ln.conns, req.socketId)
delete(req.ln.connsByPeer, req.peerSocketId)
}
// generateSocketId generates an SRT SocketID that can be used for this connection
func (req *connRequest) generateSocketId() (uint32, error) {
for range 10 {
socketId, err := rand.Uint32()
if err != nil {
return 0, fmt.Errorf("could not generate random socket id")
}
// check that the socket id is not already in use
if _, found := req.ln.conns[socketId]; !found {
return socketId, nil
}
}
return 0, fmt.Errorf("could not generate unused socketid")
}
func (req *connRequest) Accept() (Conn, error) {
if req.crypto != nil && len(req.passphrase) == 0 {
req.Reject(REJ_BADSECRET)
return nil, fmt.Errorf("passphrase is missing")
}
req.ln.lock.Lock()
defer req.ln.lock.Unlock()
if cr, hasReq := req.ln.connsByPeer[req.peerSocketId]; !hasReq || cr != nil {
return nil, fmt.Errorf("connection already accepted")
}
// Select the largest TSBPD delay advertised by the caller, but at least 120ms
recvTsbpdDelay := uint16(req.config.ReceiverLatency.Milliseconds())
sendTsbpdDelay := uint16(req.config.PeerLatency.Milliseconds())
if req.handshake.Version == 5 {
if req.handshake.SRTHS.SendTSBPDDelay > recvTsbpdDelay {
recvTsbpdDelay = req.handshake.SRTHS.SendTSBPDDelay
}
if req.handshake.SRTHS.RecvTSBPDDelay > sendTsbpdDelay {
sendTsbpdDelay = req.handshake.SRTHS.RecvTSBPDDelay
}
req.config.StreamId = req.handshake.StreamId
}
req.config.Passphrase = req.passphrase
localAddr := req.localAddr
if localAddr == nil {
localAddr = req.ln.addr
}
// Create a new connection
conn := newSRTConn(srtConnConfig{
version: req.handshake.Version,
localAddr: localAddr,
remoteAddr: req.addr,
config: req.config,
start: req.start,
socketId: req.socketId,
peerSocketId: req.peerSocketId,
tsbpdTimeBase: uint64(req.timestamp),
tsbpdDelay: uint64(recvTsbpdDelay) * 1000,
peerTsbpdDelay: uint64(sendTsbpdDelay) * 1000,
initialPacketSequenceNumber: req.handshake.InitialPacketSequenceNumber,
crypto: req.crypto,
keyBaseEncryption: packet.EvenKeyEncrypted,
onSend: req.ln.send,
onShutdown: req.ln.handleShutdown,
logger: req.config.Logger,
})
req.ln.log("connection:new", func() string { return fmt.Sprintf("%#08x (%s)", conn.SocketId(), conn.StreamId()) })
req.handshake.SRTSocketId = req.socketId
req.handshake.SynCookie = 0
if req.handshake.Version == 5 {
// 3.2.1.1.1. Handshake Extension Message Flags
req.handshake.SRTHS.SRTVersion = SRT_VERSION
req.handshake.SRTHS.SRTFlags.TSBPDSND = true
req.handshake.SRTHS.SRTFlags.TSBPDRCV = true
req.handshake.SRTHS.SRTFlags.CRYPT = true
req.handshake.SRTHS.SRTFlags.TLPKTDROP = true
req.handshake.SRTHS.SRTFlags.PERIODICNAK = true
req.handshake.SRTHS.SRTFlags.REXMITFLG = true
req.handshake.SRTHS.SRTFlags.STREAM = false
req.handshake.SRTHS.SRTFlags.PACKET_FILTER = false
req.handshake.SRTHS.RecvTSBPDDelay = recvTsbpdDelay
req.handshake.SRTHS.SendTSBPDDelay = sendTsbpdDelay
}
p := packet.NewPacket(req.addr)
p.Header().IsControlPacket = true
p.Header().ControlType = packet.CTRLTYPE_HANDSHAKE
p.Header().SubType = 0
p.Header().TypeSpecific = 0
p.Header().Timestamp = uint32(time.Since(req.start).Microseconds())
p.Header().DestinationSocketId = req.peerSocketId
p.Header().LocalAddr = req.localAddr
p.MarshalCIF(req.handshake)
req.ln.log("handshake:send:dump", func() string { return p.Dump() })
req.ln.log("handshake:send:cif", func() string { return req.handshake.String() })
req.ln.send(p)
req.ln.conns[req.socketId] = conn
req.ln.connsByPeer[req.peerSocketId] = conn
return conn, nil
}
================================================
FILE: connection.go
================================================
package srt
import (
"bytes"
"context"
"fmt"
"io"
"math"
"net"
"strings"
"sync"
"time"
"github.com/datarhei/gosrt/circular"
"github.com/datarhei/gosrt/congestion"
"github.com/datarhei/gosrt/congestion/live"
"github.com/datarhei/gosrt/crypto"
"github.com/datarhei/gosrt/packet"
)
// Conn is a SRT network connection.
type Conn interface {
// Read reads data from the connection.
// Read can be made to time out and return an error after a fixed
// time limit; see SetDeadline and SetReadDeadline.
Read(p []byte) (int, error)
// ReadPacket reads a packet from the queue of received packets. It blocks
// if the queue is empty. Only data packets are returned. Using ReadPacket
// and Read at the same time may lead to data loss.
ReadPacket() (packet.Packet, error)
// Write writes data to the connection.
// Write can be made to time out and return an error after a fixed
// time limit; see SetDeadline and SetWriteDeadline.
Write(p []byte) (int, error)
// WritePacket writes a packet to the write queue. Packets on the write queue
// will be sent to the peer of the connection. Only data packets will be sent.
WritePacket(p packet.Packet) error
// Close closes the connection.
// Any blocked Read or Write operations will be unblocked and return errors.
Close() error
// LocalAddr returns the local network address. The returned net.Addr is not shared by other invocations of LocalAddr.
LocalAddr() net.Addr
// RemoteAddr returns the remote network address. The returned net.Addr is not shared by other invocations of RemoteAddr.
RemoteAddr() net.Addr
SetDeadline(t time.Time) error
SetReadDeadline(t time.Time) error
SetWriteDeadline(t time.Time) error
// SocketId return the socketid of the connection.
SocketId() uint32
// PeerSocketId returns the socketid of the peer of the connection.
PeerSocketId() uint32
// StreamId returns the streamid use for the connection.
StreamId() string
// Stats returns accumulated and instantaneous statistics of the connection.
Stats(s *Statistics)
// Version returns the connection version, either 4 or 5. With version 4, the streamid is not available
Version() uint32
}
type rtt struct {
rtt float64 // microseconds
rttVar float64 // microseconds
lock sync.RWMutex
}
func (r *rtt) Recalculate(rtt time.Duration) {
// 4.10. Round-Trip Time Estimation
lastRTT := float64(rtt.Microseconds())
r.lock.Lock()
defer r.lock.Unlock()
r.rtt = r.rtt*0.875 + lastRTT*0.125
r.rttVar = r.rttVar*0.75 + math.Abs(r.rtt-lastRTT)*0.25
}
func (r *rtt) RTT() float64 {
r.lock.RLock()
defer r.lock.RUnlock()
return r.rtt
}
func (r *rtt) RTTVar() float64 {
r.lock.RLock()
defer r.lock.RUnlock()
return r.rttVar
}
func (r *rtt) NAKInterval() float64 {
r.lock.RLock()
defer r.lock.RUnlock()
// 4.8.2. Packet Retransmission (NAKs)
nakInterval := (r.rtt + 4*r.rttVar) / 2
if nakInterval < 20000 {
nakInterval = 20000 // 20ms
}
return nakInterval
}
type connStats struct {
headerSize uint64
pktSentACK uint64
pktRecvACK uint64
pktSentACKACK uint64
pktRecvACKACK uint64
pktSentNAK uint64
pktRecvNAK uint64
pktSentKM uint64
pktRecvKM uint64
pktRecvUndecrypt uint64
byteRecvUndecrypt uint64
pktRecvInvalid uint64
pktSentKeepalive uint64
pktRecvKeepalive uint64
pktSentShutdown uint64
pktRecvShutdown uint64
mbpsLinkCapacity float64
}
// Check if we implement the net.Conn interface
var _ net.Conn = &srtConn{}
type srtConn struct {
version uint32
isCaller bool // Only relevant if version == 4
localAddr net.Addr
remoteAddr net.Addr
start time.Time
shutdownOnce sync.Once
socketId uint32
peerSocketId uint32
config Config
crypto crypto.Crypto
keyBaseEncryption packet.PacketEncryption
kmPreAnnounceCountdown uint64
kmRefreshCountdown uint64
kmConfirmed bool
cryptoLock sync.Mutex
peerIdleTimeout *time.Timer
rtt rtt // microseconds
ackLock sync.RWMutex
ackNumbers map[uint32]time.Time
nextACKNumber circular.Number
initialPacketSequenceNumber circular.Number
tsbpdTimeBase uint64 // microseconds
tsbpdWrapPeriod bool
tsbpdTimeBaseOffset uint64 // microseconds
tsbpdDelay uint64 // microseconds
tsbpdDrift uint64 // microseconds
peerTsbpdDelay uint64 // microseconds
dropThreshold uint64 // microseconds
// Queue for packets that are coming from the network
networkQueue chan packet.Packet
// Queue for packets that are written with writePacket() and will be send to the network
writeQueue chan packet.Packet
writeBuffer bytes.Buffer
writeData []byte
// Queue for packets that will be read locally with ReadPacket()
readQueue chan packet.Packet
readBuffer bytes.Buffer
onSend func(p packet.Packet)
onShutdown func(*srtConn)
tick time.Duration
// Congestion control
recv congestion.Receiver
snd congestion.Sender
// context of all channels and routines
ctx context.Context
cancelCtx context.CancelFunc
statistics connStats
statisticsLock sync.RWMutex
logger Logger
debug struct {
expectedRcvPacketSequenceNumber circular.Number
expectedReadPacketSequenceNumber circular.Number
}
// HSv4
stopHSRequests context.CancelFunc
stopKMRequests context.CancelFunc
}
type srtConnConfig struct {
version uint32
isCaller bool
localAddr net.Addr
remoteAddr net.Addr
config Config
start time.Time
socketId uint32
peerSocketId uint32
tsbpdTimeBase uint64 // microseconds
tsbpdDelay uint64 // microseconds
peerTsbpdDelay uint64 // microseconds
initialPacketSequenceNumber circular.Number
crypto crypto.Crypto
keyBaseEncryption packet.PacketEncryption
onSend func(p packet.Packet)
onShutdown func(*srtConn)
logger Logger
}
func newSRTConn(config srtConnConfig) *srtConn {
c := &srtConn{
version: config.version,
isCaller: config.isCaller,
localAddr: config.localAddr,
remoteAddr: config.remoteAddr,
config: config.config,
start: config.start,
socketId: config.socketId,
peerSocketId: config.peerSocketId,
tsbpdTimeBase: config.tsbpdTimeBase,
tsbpdDelay: config.tsbpdDelay,
peerTsbpdDelay: config.peerTsbpdDelay,
initialPacketSequenceNumber: config.initialPacketSequenceNumber,
crypto: config.crypto,
keyBaseEncryption: config.keyBaseEncryption,
onSend: config.onSend,
onShutdown: config.onShutdown,
logger: config.logger,
}
if c.onSend == nil {
c.onSend = func(p packet.Packet) {}
}
if c.onShutdown == nil {
c.onShutdown = func(*srtConn) {}
}
c.nextACKNumber = circular.New(1, packet.MAX_TIMESTAMP)
c.ackNumbers = make(map[uint32]time.Time)
c.kmPreAnnounceCountdown = c.config.KMRefreshRate - c.config.KMPreAnnounce
c.kmRefreshCountdown = c.config.KMRefreshRate
// 4.10. Round-Trip Time Estimation
c.rtt = rtt{
rtt: float64((100 * time.Millisecond).Microseconds()),
rttVar: float64((50 * time.Millisecond).Microseconds()),
}
c.networkQueue = make(chan packet.Packet, 1024)
c.writeQueue = make(chan packet.Packet, 1024)
if c.version == 4 {
// libsrt-1.2.3 receiver doesn't like it when the payload is larger than 7*188 bytes.
// Here we just take a multiple of a mpegts chunk size.
c.writeData = make([]byte, int(c.config.PayloadSize/188*188))
} else {
// For v5 we use the max. payload size: https://github.com/Haivision/srt/issues/876
c.writeData = make([]byte, int(c.config.PayloadSize))
}
c.readQueue = make(chan packet.Packet, 1024)
c.peerIdleTimeout = time.AfterFunc(c.config.PeerIdleTimeout, func() {
c.log("connection:close", func() string {
return fmt.Sprintf("no more data received from peer for %s. shutting down", c.config.PeerIdleTimeout)
})
go c.close()
})
c.tick = 10 * time.Millisecond
// 4.8.1. Packet Acknowledgement (ACKs, ACKACKs) -> periodicACK = 10 milliseconds
// 4.8.2. Packet Retransmission (NAKs) -> periodicNAK at least 20 milliseconds
c.recv = live.NewReceiver(live.ReceiveConfig{
InitialSequenceNumber: c.initialPacketSequenceNumber,
PeriodicACKInterval: 10_000,
PeriodicNAKInterval: 20_000,
OnSendACK: c.sendACK,
OnSendNAK: c.sendNAK,
OnDeliver: c.deliver,
})
// 4.6. Too-Late Packet Drop -> 125% of SRT latency, at least 1 second
// https://github.com/Haivision/srt/blob/master/docs/API/API-socket-options.md#SRTO_SNDDROPDELAY
c.dropThreshold = max(uint64(float64(c.peerTsbpdDelay)*1.25)+uint64(c.config.SendDropDelay.Microseconds()), uint64(time.Second.Microseconds()))
c.dropThreshold += 20_000
c.snd = live.NewSender(live.SendConfig{
InitialSequenceNumber: c.initialPacketSequenceNumber,
DropThreshold: c.dropThreshold,
MaxBW: c.config.MaxBW,
InputBW: c.config.InputBW,
MinInputBW: c.config.MinInputBW,
OverheadBW: c.config.OverheadBW,
OnDeliver: c.pop,
})
c.ctx, c.cancelCtx = context.WithCancel(context.Background())
go c.networkQueueReader(c.ctx)
go c.writeQueueReader(c.ctx)
go c.ticker(c.ctx)
c.debug.expectedRcvPacketSequenceNumber = c.initialPacketSequenceNumber
c.debug.expectedReadPacketSequenceNumber = c.initialPacketSequenceNumber
c.statistics.headerSize = 8 + 16 // 8 bytes UDP + 16 bytes SRT
if strings.Count(c.localAddr.String(), ":") < 2 {
c.statistics.headerSize += 20 // 20 bytes IPv4 header
} else {
c.statistics.headerSize += 40 // 40 bytes IPv6 header
}
if c.version == 4 && c.isCaller {
var hsrequestsCtx context.Context
hsrequestsCtx, c.stopHSRequests = context.WithCancel(context.Background())
go c.sendHSRequests(hsrequestsCtx)
if c.crypto != nil {
var kmrequestsCtx context.Context
kmrequestsCtx, c.stopKMRequests = context.WithCancel(context.Background())
go c.sendKMRequests(kmrequestsCtx)
}
}
return c
}
func (c *srtConn) LocalAddr() net.Addr {
if c.localAddr == nil {
return nil
}
addr, _ := net.ResolveUDPAddr("udp", c.localAddr.String())
return addr
}
func (c *srtConn) RemoteAddr() net.Addr {
if c.remoteAddr == nil {
return nil
}
addr, _ := net.ResolveUDPAddr("udp", c.remoteAddr.String())
return addr
}
func (c *srtConn) SocketId() uint32 {
return c.socketId
}
func (c *srtConn) PeerSocketId() uint32 {
return c.peerSocketId
}
func (c *srtConn) StreamId() string {
return c.config.StreamId
}
func (c *srtConn) Version() uint32 {
return c.version
}
// ticker invokes the congestion control in regular intervals with
// the current connection time.
func (c *srtConn) ticker(ctx context.Context) {
ticker := time.NewTicker(c.tick)
defer ticker.Stop()
defer func() {
c.log("connection:close", func() string { return "left ticker loop" })
}()
for {
select {
case <-ctx.Done():
return
case t := <-ticker.C:
tickTime := uint64(t.Sub(c.start).Microseconds())
c.recv.Tick(c.tsbpdTimeBase + tickTime)
c.snd.Tick(tickTime)
}
}
}
func (c *srtConn) ReadPacket() (packet.Packet, error) {
var p packet.Packet
select {
case <-c.ctx.Done():
return nil, io.EOF
case p = <-c.readQueue:
}
if p.Header().PacketSequenceNumber.Gt(c.debug.expectedReadPacketSequenceNumber) {
c.log("connection:error", func() string {
return fmt.Sprintf("lost packets. got: %d, expected: %d (%d)", p.Header().PacketSequenceNumber.Val(), c.debug.expectedReadPacketSequenceNumber.Val(), c.debug.expectedReadPacketSequenceNumber.Distance(p.Header().PacketSequenceNumber))
})
} else if p.Header().PacketSequenceNumber.Lt(c.debug.expectedReadPacketSequenceNumber) {
c.log("connection:error", func() string {
return fmt.Sprintf("packet out of order. got: %d, expected: %d (%d)", p.Header().PacketSequenceNumber.Val(), c.debug.expectedReadPacketSequenceNumber.Val(), c.debug.expectedReadPacketSequenceNumber.Distance(p.Header().PacketSequenceNumber))
})
return nil, io.EOF
}
c.debug.expectedReadPacketSequenceNumber = p.Header().PacketSequenceNumber.Inc()
return p, nil
}
func (c *srtConn) Read(b []byte) (int, error) {
if c.readBuffer.Len() != 0 {
return c.readBuffer.Read(b)
}
c.readBuffer.Reset()
p, err := c.ReadPacket()
if err != nil {
return 0, err
}
c.readBuffer.Write(p.Data())
// The packet is out of congestion control and written to the read buffer
p.Decommission()
return c.readBuffer.Read(b)
}
// WritePacket writes a packet to the write queue. Packets on the write queue
// will be sent to the peer of the connection. Only data packets will be sent.
func (c *srtConn) WritePacket(p packet.Packet) error {
if p.Header().IsControlPacket {
// Ignore control packets
return nil
}
_, err := c.Write(p.Data())
if err != nil {
return err
}
return nil
}
func (c *srtConn) Write(b []byte) (int, error) {
c.writeBuffer.Write(b)
for {
n, err := c.writeBuffer.Read(c.writeData)
if err != nil {
return 0, err
}
p := packet.NewPacket(nil)
p.SetData(c.writeData[:n])
p.Header().IsControlPacket = false
// Give the packet a deliver timestamp
p.Header().PktTsbpdTime = c.getTimestamp()
// Non-blocking write to the write queue
select {
case <-c.ctx.Done():
return 0, io.EOF
case c.writeQueue <- p:
default:
return 0, io.EOF
}
if c.writeBuffer.Len() == 0 {
break
}
}
c.writeBuffer.Reset()
return len(b), nil
}
// push puts a packet on the network queue. This is where packets go that came in from the network.
func (c *srtConn) push(p packet.Packet) {
// Non-blocking write to the network queue
select {
case <-c.ctx.Done():
case c.networkQueue <- p:
default:
c.log("connection:error", func() string { return "network queue is full" })
}
}
// getTimestamp returns the elapsed time since the start of the connection in microseconds.
func (c *srtConn) getTimestamp() uint64 {
return uint64(time.Since(c.start).Microseconds())
}
// getTimestampForPacket returns the elapsed time since the start of the connection in
// microseconds clamped a 32bit value.
func (c *srtConn) getTimestampForPacket() uint32 {
return uint32(c.getTimestamp() & uint64(packet.MAX_TIMESTAMP))
}
// pop adds the destination address and socketid to the packet and sends it out to the network.
// The packet will be encrypted if required.
func (c *srtConn) pop(p packet.Packet) {
p.Header().Addr = c.remoteAddr
p.Header().LocalAddr = c.localAddr
p.Header().DestinationSocketId = c.peerSocketId
if !p.Header().IsControlPacket {
c.cryptoLock.Lock()
if c.crypto != nil {
p.Header().KeyBaseEncryptionFlag = c.keyBaseEncryption
if !p.Header().RetransmittedPacketFlag {
c.crypto.EncryptOrDecryptPayload(p.Data(), p.Header().KeyBaseEncryptionFlag, p.Header().PacketSequenceNumber.Val())
}
c.kmPreAnnounceCountdown--
c.kmRefreshCountdown--
if c.kmPreAnnounceCountdown == 0 && !c.kmConfirmed {
c.sendKMRequest(c.keyBaseEncryption.Opposite())
// Resend the request until we get a response
c.kmPreAnnounceCountdown = c.config.KMPreAnnounce/10 + 1
}
if c.kmRefreshCountdown == 0 {
c.kmPreAnnounceCountdown = c.config.KMRefreshRate - c.config.KMPreAnnounce
c.kmRefreshCountdown = c.config.KMRefreshRate
// Switch the keys
c.keyBaseEncryption = c.keyBaseEncryption.Opposite()
c.kmConfirmed = false
}
if c.kmRefreshCountdown == c.config.KMRefreshRate-c.config.KMPreAnnounce {
// Decommission the previous key, resp. create a new SEK that will
// be used in the next switch.
c.crypto.GenerateSEK(c.keyBaseEncryption.Opposite())
}
}
c.cryptoLock.Unlock()
c.log("data:send:dump", func() string { return p.Dump() })
}
// Send the packet on the wire
c.onSend(p)
}
// networkQueueReader reads the packets from the network queue in order to process them.
func (c *srtConn) networkQueueReader(ctx context.Context) {
defer func() {
c.log("connection:close", func() string { return "left network queue reader loop" })
}()
for {
select {
case <-ctx.Done():
return
case p := <-c.networkQueue:
c.handlePacket(p)
}
}
}
// writeQueueReader reads the packets from the write queue and puts them into congestion
// control for sending.
func (c *srtConn) writeQueueReader(ctx context.Context) {
defer func() {
c.log("connection:close", func() string { return "left write queue reader loop" })
}()
for {
select {
case <-ctx.Done():
return
case p := <-c.writeQueue:
// Put the packet into the send congestion control
c.snd.Push(p)
}
}
}
// deliver writes the packets to the read queue in order to be consumed by the Read function.
func (c *srtConn) deliver(p packet.Packet) {
// Non-blocking write to the read queue
select {
case <-c.ctx.Done():
case c.readQueue <- p:
default:
c.log("connection:error", func() string { return "readQueue was blocking, dropping packet" })
}
}
// handlePacket checks the packet header. If it is a control packet it will forwarded to the
// respective handler. If it is a data packet it will be put into congestion control for
// receiving. The packet will be decrypted if required.
func (c *srtConn) handlePacket(p packet.Packet) {
if p == nil {
return
}
c.peerIdleTimeout.Reset(c.config.PeerIdleTimeout)
header := p.Header()
if header.IsControlPacket {
if header.ControlType == packet.CTRLTYPE_KEEPALIVE {
c.handleKeepAlive(p)
} else if header.ControlType == packet.CTRLTYPE_SHUTDOWN {
c.handleShutdown(p)
} else if header.ControlType == packet.CTRLTYPE_NAK {
c.handleNAK(p)
} else if header.ControlType == packet.CTRLTYPE_ACK {
c.handleACK(p)
} else if header.ControlType == packet.CTRLTYPE_ACKACK {
c.handleACKACK(p)
} else if header.ControlType == packet.CTRLTYPE_USER {
c.log("connection:recv:ctrl:user", func() string {
return fmt.Sprintf("got CTRLTYPE_USER packet, subType: %s", header.SubType)
})
// HSv4 Extension
if header.SubType == packet.EXTTYPE_HSREQ {
c.handleHSRequest(p)
} else if header.SubType == packet.EXTTYPE_HSRSP {
c.handleHSResponse(p)
}
// 3.2.2. Key Material
if header.SubType == packet.EXTTYPE_KMREQ {
c.handleKMRequest(p)
} else if header.SubType == packet.EXTTYPE_KMRSP {
c.handleKMResponse(p)
}
}
return
}
if header.PacketSequenceNumber.Gt(c.debug.expectedRcvPacketSequenceNumber) {
c.log("connection:error", func() string {
return fmt.Sprintf("recv lost packets. got: %d, expected: %d (%d)\n", header.PacketSequenceNumber.Val(), c.debug.expectedRcvPacketSequenceNumber.Val(), c.debug.expectedRcvPacketSequenceNumber.Distance(header.PacketSequenceNumber))
})
}
c.debug.expectedRcvPacketSequenceNumber = header.PacketSequenceNumber.Inc()
//fmt.Printf("%s\n", p.String())
// Ignore FEC filter control packets
// https://github.com/Haivision/srt/blob/master/docs/features/packet-filtering-and-fec.md
// "An FEC control packet is distinguished from a regular data packet by having
// its message number equal to 0. This value isn't normally used in SRT (message
// numbers start from 1, increment to a maximum, and then roll back to 1)."
if header.MessageNumber == 0 {
c.log("connection:filter", func() string { return "dropped FEC filter control packet" })
return
}
// 4.5.1.1. TSBPD Time Base Calculation
if !c.tsbpdWrapPeriod {
if header.Timestamp > packet.MAX_TIMESTAMP-(30*1000000) {
c.tsbpdWrapPeriod = true
c.log("connection:tsbpd", func() string { return "TSBPD wrapping period started" })
}
} else {
if header.Timestamp >= (30*1000000) && header.Timestamp <= (60*1000000) {
c.tsbpdWrapPeriod = false
c.tsbpdTimeBaseOffset += uint64(packet.MAX_TIMESTAMP) + 1
c.log("connection:tsbpd", func() string { return "TSBPD wrapping period finished" })
}
}
tsbpdTimeBaseOffset := c.tsbpdTimeBaseOffset
if c.tsbpdWrapPeriod {
if header.Timestamp < (30 * 1000000) {
tsbpdTimeBaseOffset += uint64(packet.MAX_TIMESTAMP) + 1
}
}
header.PktTsbpdTime = c.tsbpdTimeBase + tsbpdTimeBaseOffset + uint64(header.Timestamp) + c.tsbpdDelay + c.tsbpdDrift
c.log("data:recv:dump", func() string { return p.Dump() })
c.cryptoLock.Lock()
if c.crypto != nil {
if header.KeyBaseEncryptionFlag != 0 {
if err := c.crypto.EncryptOrDecryptPayload(p.Data(), header.KeyBaseEncryptionFlag, header.PacketSequenceNumber.Val()); err != nil {
c.statisticsLock.Lock()
c.statistics.pktRecvUndecrypt++
c.statistics.byteRecvUndecrypt += p.Len()
c.statisticsLock.Unlock()
}
} else {
c.statisticsLock.Lock()
c.statistics.pktRecvUndecrypt++
c.statistics.byteRecvUndecrypt += p.Len()
c.statisticsLock.Unlock()
}
}
c.cryptoLock.Unlock()
// Put the packet into receive congestion control
c.recv.Push(p)
}
// handleKeepAlive resets the idle timeout and sends a keepalive to the peer.
func (c *srtConn) handleKeepAlive(p packet.Packet) {
c.log("control:recv:keepalive:dump", func() string { return p.Dump() })
c.statisticsLock.Lock()
c.statistics.pktRecvKeepalive++
c.statistics.pktSentKeepalive++
c.statisticsLock.Unlock()
c.peerIdleTimeout.Reset(c.config.PeerIdleTimeout)
c.log("control:send:keepalive:dump", func() string { return p.Dump() })
c.pop(p)
}
// handleShutdown closes the connection
func (c *srtConn) handleShutdown(p packet.Packet) {
c.log("control:recv:shutdown:dump", func() string { return p.Dump() })
c.statisticsLock.Lock()
c.statistics.pktRecvShutdown++
c.statisticsLock.Unlock()
go c.close()
}
// handleACK forwards the acknowledge sequence number to the congestion control and
// returns a ACKACK (on a full ACK). The RTT is also updated in case of a full ACK.
func (c *srtConn) handleACK(p packet.Packet) {
c.log("control:recv:ACK:dump", func() string { return p.Dump() })
c.statisticsLock.Lock()
c.statistics.pktRecvACK++
c.statisticsLock.Unlock()
cif := &packet.CIFACK{}
if err := p.UnmarshalCIF(cif); err != nil {
c.statisticsLock.Lock()
c.statistics.pktRecvInvalid++
c.statisticsLock.Unlock()
c.log("control:recv:ACK:error", func() string { return fmt.Sprintf("invalid ACK: %s", err) })
return
}
c.log("control:recv:ACK:cif", func() string { return cif.String() })
c.snd.ACK(cif.LastACKPacketSequenceNumber)
if !cif.IsLite && !cif.IsSmall {
// 4.10. Round-Trip Time Estimation
c.recalculateRTT(time.Duration(int64(cif.RTT)) * time.Microsecond)
// Estimated Link Capacity (from packets/s to Mbps)
c.statisticsLock.Lock()
c.statistics.mbpsLinkCapacity = float64(cif.EstimatedLinkCapacity) * MAX_PAYLOAD_SIZE * 8 / 1024 / 1024
c.statisticsLock.Unlock()
c.sendACKACK(p.Header().TypeSpecific)
}
}
// handleNAK forwards the lost sequence number to the congestion control.
func (c *srtConn) handleNAK(p packet.Packet) {
c.log("control:recv:NAK:dump", func() string { return p.Dump() })
c.statisticsLock.Lock()
c.statistics.pktRecvNAK++
c.statisticsLock.Unlock()
cif := &packet.CIFNAK{}
if err := p.UnmarshalCIF(cif); err != nil {
c.statisticsLock.Lock()
c.statistics.pktRecvInvalid++
c.statisticsLock.Unlock()
c.log("control:recv:NAK:error", func() string { return fmt.Sprintf("invalid NAK: %s", err) })
return
}
c.log("control:recv:NAK:cif", func() string { return cif.String() })
// Inform congestion control about lost packets
c.snd.NAK(cif.LostPacketSequenceNumber)
}
// handleACKACK updates the RTT and NAK interval for the congestion control.
func (c *srtConn) handleACKACK(p packet.Packet) {
c.ackLock.Lock()
c.statisticsLock.Lock()
c.statistics.pktRecvACKACK++
c.statisticsLock.Unlock()
c.log("control:recv:ACKACK:dump", func() string { return p.Dump() })
// p.typeSpecific is the ACKNumber
if ts, ok := c.ackNumbers[p.Header().TypeSpecific]; ok {
// 4.10. Round-Trip Time Estimation
c.recalculateRTT(time.Since(ts))
delete(c.ackNumbers, p.Header().TypeSpecific)
} else {
c.log("control:recv:ACKACK:error", func() string { return fmt.Sprintf("got unknown ACKACK (%d)", p.Header().TypeSpecific) })
c.statisticsLock.Lock()
c.statistics.pktRecvInvalid++
c.statisticsLock.Unlock()
}
for i := range c.ackNumbers {
if i < p.Header().TypeSpecific {
delete(c.ackNumbers, i)
}
}
c.ackLock.Unlock()
c.recv.SetNAKInterval(uint64(c.rtt.NAKInterval()))
}
// recalculateRTT recalculates the RTT based on a full ACK exchange
func (c *srtConn) recalculateRTT(rtt time.Duration) {
c.rtt.Recalculate(rtt)
c.log("connection:rtt", func() string {
return fmt.Sprintf("RTT=%.0fus RTTVar=%.0fus NAKInterval=%.0fms", c.rtt.RTT(), c.rtt.RTTVar(), c.rtt.NAKInterval()/1000)
})
}
// handleHSRequest handles the HSv4 handshake extension request and sends the response
func (c *srtConn) handleHSRequest(p packet.Packet) {
c.log("control:recv:HSReq:dump", func() string { return p.Dump() })
cif := &packet.CIFHandshakeExtension{}
if err := p.UnmarshalCIF(cif); err != nil {
c.statisticsLock.Lock()
c.statistics.pktRecvInvalid++
c.statisticsLock.Unlock()
c.log("control:recv:HSReq:error", func() string { return fmt.Sprintf("invalid HSReq: %s", err) })
return
}
c.log("control:recv:HSReq:cif", func() string { return cif.String() })
// Check for version
if cif.SRTVersion < 0x010200 || cif.SRTVersion >= 0x010300 {
c.log("control:recv:HSReq:error", func() string { return fmt.Sprintf("unsupported version: %#08x", cif.SRTVersion) })
c.close()
return
}
// Check the required SRT flags
if !cif.SRTFlags.TSBPDSND {
c.log("control:recv:HSRes:error", func() string { return "TSBPDSND flag must be set" })
c.close()
return
}
if !cif.SRTFlags.TLPKTDROP {
c.log("control:recv:HSRes:error", func() string { return "TLPKTDROP flag must be set" })
c.close()
return
}
if !cif.SRTFlags.CRYPT {
c.log("control:recv:HSRes:error", func() string { return "CRYPT flag must be set" })
c.close()
return
}
if !cif.SRTFlags.REXMITFLG {
c.log("control:recv:HSRes:error", func() string { return "REXMITFLG flag must be set" })
c.close()
return
}
// we as receiver don't need this
cif.SRTFlags.TSBPDSND = false
// we as receiver are supporting these
cif.SRTFlags.TSBPDRCV = true
cif.SRTFlags.PERIODICNAK = true
// These flag was introduced in HSv5 and should not be set in HSv4
if cif.SRTFlags.STREAM {
c.log("control:recv:HSReq:error", func() string { return "STREAM flag is set" })
c.close()
return
}
if cif.SRTFlags.PACKET_FILTER {
c.log("control:recv:HSReq:error", func() string { return "PACKET_FILTER flag is set" })
c.close()
return
}
recvTsbpdDelay := max(cif.SendTSBPDDelay, uint16(c.config.ReceiverLatency.Milliseconds()))
c.tsbpdDelay = uint64(recvTsbpdDelay) * 1000
cif.RecvTSBPDDelay = 0
cif.SendTSBPDDelay = recvTsbpdDelay
p.MarshalCIF(cif)
// Send HS Response
p.Header().SubType = packet.EXTTYPE_HSRSP
c.pop(p)
}
// handleHSResponse handles the HSv4 handshake extension response
func (c *srtConn) handleHSResponse(p packet.Packet) {
c.log("control:recv:HSRes:dump", func() string { return p.Dump() })
cif := &packet.CIFHandshakeExtension{}
if err := p.UnmarshalCIF(cif); err != nil {
c.statisticsLock.Lock()
c.statistics.pktRecvInvalid++
c.statisticsLock.Unlock()
c.log("control:recv:HSRes:error", func() string { return fmt.Sprintf("invalid HSRes: %s", err) })
return
}
c.log("control:recv:HSRes:cif", func() string { return cif.String() })
if c.version == 4 {
// Check for version
if cif.SRTVersion < 0x010200 || cif.SRTVersion >= 0x010300 {
c.log("control:recv:HSRes:error", func() string { return fmt.Sprintf("unsupported version: %#08x", cif.SRTVersion) })
c.close()
return
}
// TSBPDSND is not relevant from the receiver
// PERIODICNAK is the sender's decision, we don't care, but will handle them
// Check the required SRT flags
if !cif.SRTFlags.TSBPDRCV {
c.log("control:recv:HSRes:error", func() string { return "TSBPDRCV flag must be set" })
c.close()
return
}
if !cif.SRTFlags.TLPKTDROP {
c.log("control:recv:HSRes:error", func() string { return "TLPKTDROP flag must be set" })
c.close()
return
}
if !cif.SRTFlags.CRYPT {
c.log("control:recv:HSRes:error", func() string { return "CRYPT flag must be set" })
c.close()
return
}
if !cif.SRTFlags.REXMITFLG {
c.log("control:recv:HSRes:error", func() string { return "REXMITFLG flag must be set" })
c.close()
return
}
// These flag was introduced in HSv5 and should not be set in HSv4
if cif.SRTFlags.STREAM {
c.log("control:recv:HSReq:error", func() string { return "STREAM flag is set" })
c.close()
return
}
if cif.SRTFlags.PACKET_FILTER {
c.log("control:recv:HSReq:error", func() string { return "PACKET_FILTER flag is set" })
c.close()
return
}
sendTsbpdDelay := max(cif.SendTSBPDDelay, uint16(c.config.PeerLatency.Milliseconds()))
c.dropThreshold = max(uint64(float64(sendTsbpdDelay)*1.25)+uint64(c.config.SendDropDelay.Microseconds()), uint64(time.Second.Microseconds()))
c.dropThreshold += 20_000
c.snd.SetDropThreshold(c.dropThreshold)
c.stopHSRequests()
}
}
// handleKMRequest checks if the key material is valid and responds with a KM response.
func (c *srtConn) handleKMRequest(p packet.Packet) {
c.log("control:recv:KMReq:dump", func() string { return p.Dump() })
c.statisticsLock.Lock()
c.statistics.pktRecvKM++
c.statisticsLock.Unlock()
cif := &packet.CIFKeyMaterialExtension{}
if err := p.UnmarshalCIF(cif); err != nil {
c.statisticsLock.Lock()
c.statistics.pktRecvInvalid++
c.statisticsLock.Unlock()
c.log("control:recv:KMReq:error", func() string { return fmt.Sprintf("invalid KMReq: %s", err) })
return
}
c.log("control:recv:KMReq:cif", func() string { return cif.String() })
c.cryptoLock.Lock()
if c.version == 4 && c.crypto == nil {
cr, err := crypto.New(int(cif.KLen))
if err != nil {
c.log("control:recv:KMReq:error", func() string { return fmt.Sprintf("crypto: %s", err) })
c.cryptoLock.Unlock()
c.close()
return
}
c.keyBaseEncryption = cif.KeyBasedEncryption.Opposite()
c.crypto = cr
}
if c.crypto == nil {
c.log("control:recv:KMReq:error", func() string { return "connection is not encrypted" })
c.cryptoLock.Unlock()
return
}
if cif.KeyBasedEncryption == c.keyBaseEncryption {
c.statisticsLock.Lock()
c.statistics.pktRecvInvalid++
c.statisticsLock.Unlock()
c.log("control:recv:KMReq:error", func() string {
return "invalid KM request. wants to reset the key that is already in use"
})
c.cryptoLock.Unlock()
return
}
if err := c.crypto.UnmarshalKM(cif, c.config.Passphrase); err != nil {
c.statisticsLock.Lock()
c.statistics.pktRecvInvalid++
c.statisticsLock.Unlock()
c.log("control:recv:KMReq:error", func() string { return fmt.Sprintf("invalid KMReq: %s", err) })
c.cryptoLock.Unlock()
return
}
// Switch the keys
c.keyBaseEncryption = c.keyBaseEncryption.Opposite()
c.cryptoLock.Unlock()
// Send KM Response
p.Header().SubType = packet.EXTTYPE_KMRSP
c.statisticsLock.Lock()
c.statistics.pktSentKM++
c.statisticsLock.Unlock()
c.pop(p)
}
// handleKMResponse confirms the change of encryption keys.
func (c *srtConn) handleKMResponse(p packet.Packet) {
c.log("control:recv:KMRes:dump", func() string { return p.Dump() })
c.statisticsLock.Lock()
c.statistics.pktRecvKM++
c.statisticsLock.Unlock()
cif := &packet.CIFKeyMaterialExtension{}
if err := p.UnmarshalCIF(cif); err != nil {
c.statisticsLock.Lock()
c.statistics.pktRecvInvalid++
c.statisticsLock.Unlock()
c.log("control:recv:KMRes:error", func() string { return fmt.Sprintf("invalid KMRes: %s", err) })
return
}
c.cryptoLock.Lock()
defer c.cryptoLock.Unlock()
if c.crypto == nil {
c.log("control:recv:KMRes:error", func() string { return "connection is not encrypted" })
return
}
if c.version == 4 {
c.stopKMRequests()
if cif.Error != 0 {
if cif.Error == packet.KM_NOSECRET {
c.log("control:recv:KMRes:error", func() string { return "peer didn't enabled encryption" })
} else if cif.Error == packet.KM_BADSECRET {
c.log("control:recv:KMRes:error", func() string { return "peer has a different passphrase" })
}
c.close()
return
}
}
c.log("control:recv:KMRes:cif", func() string { return cif.String() })
if c.kmPreAnnounceCountdown >= c.config.KMPreAnnounce {
c.log("control:recv:KMRes:error", func() string { return "not in pre-announce period, ignored" })
// Ignore the response, we're not in the pre-announce period
return
}
c.kmConfirmed = true
}
// sendShutdown sends a shutdown packet to the peer.
func (c *srtConn) sendShutdown() {
p := packet.NewPacket(c.remoteAddr)
p.Header().IsControlPacket = true
p.Header().ControlType = packet.CTRLTYPE_SHUTDOWN
p.Header().Timestamp = c.getTimestampForPacket()
cif := packet.CIFShutdown{}
p.MarshalCIF(&cif)
c.log("control:send:shutdown:dump", func() string { return p.Dump() })
c.log("control:send:shutdown:cif", func() string { return cif.String() })
c.statisticsLock.Lock()
c.statistics.pktSentShutdown++
c.statisticsLock.Unlock()
c.pop(p)
}
// sendNAK sends a NAK to the peer with the given range of sequence numbers.
func (c *srtConn) sendNAK(list []circular.Number) {
p := packet.NewPacket(c.remoteAddr)
p.Header().IsControlPacket = true
p.Header().ControlType = packet.CTRLTYPE_NAK
p.Header().Timestamp = c.getTimestampForPacket()
cif := packet.CIFNAK{}
cif.LostPacketSequenceNumber = append(cif.LostPacketSequenceNumber, list...)
p.MarshalCIF(&cif)
c.log("control:send:NAK:dump", func() string { return p.Dump() })
c.log("control:send:NAK:cif", func() string { return cif.String() })
c.statisticsLock.Lock()
c.statistics.pktSentNAK++
c.statisticsLock.Unlock()
c.pop(p)
}
// sendACK sends an ACK to the peer with the given sequence number.
func (c *srtConn) sendACK(seq circular.Number, lite bool) {
p := packet.NewPacket(c.remoteAddr)
p.Header().IsControlPacket = true
p.Header().ControlType = packet.CTRLTYPE_ACK
p.Header().Timestamp = c.getTimestampForPacket()
cif := packet.CIFACK{
LastACKPacketSequenceNumber: seq,
}
c.ackLock.Lock()
defer c.ackLock.Unlock()
if lite {
cif.IsLite = true
p.Header().TypeSpecific = 0
} else {
pps, bps, capacity := c.recv.PacketRate()
cif.RTT = uint32(c.rtt.RTT())
cif.RTTVar = uint32(c.rtt.RTTVar())
cif.AvailableBufferSize = c.config.FC // TODO: available buffer size (packets)
cif.PacketsReceivingRate = uint32(pps) // packets receiving rate (packets/s)
cif.EstimatedLinkCapacity = uint32(capacity) // estimated link capacity (packets/s), not relevant for live mode
cif.ReceivingRate = uint32(bps) // receiving rate (bytes/s), not relevant for live mode
p.Header().TypeSpecific = c.nextACKNumber.Val()
c.ackNumbers[p.Header().TypeSpecific] = time.Now()
c.nextACKNumber = c.nextACKNumber.Inc()
if c.nextACKNumber.Val() == 0 {
c.nextACKNumber = c.nextACKNumber.Inc()
}
}
p.MarshalCIF(&cif)
c.log("control:send:ACK:dump", func() string { return p.Dump() })
c.log("control:send:ACK:cif", func() string { return cif.String() })
c.statisticsLock.Lock()
c.statistics.pktSentACK++
c.statisticsLock.Unlock()
c.pop(p)
}
// sendACKACK sends an ACKACK to the peer with the given ACK sequence.
func (c *srtConn) sendACKACK(ackSequence uint32) {
p := packet.NewPacket(c.remoteAddr)
p.Header().IsControlPacket = true
p.Header().ControlType = packet.CTRLTYPE_ACKACK
p.Header().Timestamp = c.getTimestampForPacket()
p.Header().TypeSpecific = ackSequence
c.log("control:send:ACKACK:dump", func() string { return p.Dump() })
c.statisticsLock.Lock()
c.statistics.pktSentACKACK++
c.statisticsLock.Unlock()
c.pop(p)
}
func (c *srtConn) sendHSRequests(ctx context.Context) {
ticker := time.NewTicker(500 * time.Millisecond)
defer ticker.Stop()
select {
case <-ctx.Done():
return
case <-ticker.C:
c.sendHSRequest()
}
}
func (c *srtConn) sendHSRequest() {
cif := &packet.CIFHandshakeExtension{
SRTVersion: 0x00010203,
SRTFlags: packet.CIFHandshakeExtensionFlags{
TSBPDSND: true, // we send in TSBPD mode
TSBPDRCV: false, // not relevant for us as sender
CRYPT: true, // must be always set
TLPKTDROP: true, // must be set in live mode
PERIODICNAK: false, // not relevant for us as sender
REXMITFLG: true, // must alwasy be set
STREAM: false, // has been introducet in HSv5
PACKET_FILTER: false, // has been introducet in HSv5
},
RecvTSBPDDelay: 0,
SendTSBPDDelay: uint16(c.config.ReceiverLatency.Milliseconds()),
}
p := packet.NewPacket(c.remoteAddr)
p.Header().IsControlPacket = true
p.Header().ControlType = packet.CTRLTYPE_USER
p.Header().SubType = packet.EXTTYPE_HSREQ
p.Header().Timestamp = c.getTimestampForPacket()
p.MarshalCIF(cif)
c.log("control:send:HSReq:dump", func() string { return p.Dump() })
c.log("control:send:HSReq:cif", func() string { return cif.String() })
c.pop(p)
}
func (c *srtConn) sendKMRequests(ctx context.Context) {
ticker := time.NewTicker(500 * time.Millisecond)
defer ticker.Stop()
select {
case <-ctx.Done():
return
case <-ticker.C:
c.sendKMRequest(c.keyBaseEncryption)
}
}
// sendKMRequest sends a KM request to the peer.
func (c *srtConn) sendKMRequest(key packet.PacketEncryption) {
if c.crypto == nil {
c.log("control:send:KMReq:error", func() string { return "connection is not encrypted" })
return
}
cif := &packet.CIFKeyMaterialExtension{}
c.crypto.MarshalKM(cif, c.config.Passphrase, key)
p := packet.NewPacket(c.remoteAddr)
p.Header().IsControlPacket = true
p.Header().ControlType = packet.CTRLTYPE_USER
p.Header().SubType = packet.EXTTYPE_KMREQ
p.Header().Timestamp = c.getTimestampForPacket()
p.MarshalCIF(cif)
c.log("control:send:KMReq:dump", func() string { return p.Dump() })
c.log("control:send:KMReq:cif", func() string { return cif.String() })
c.statisticsLock.Lock()
c.statistics.pktSentKM++
c.statisticsLock.Unlock()
c.pop(p)
}
// Close closes the connection.
func (c *srtConn) Close() error {
c.close()
return nil
}
// close closes the connection.
func (c *srtConn) close() {
c.shutdownOnce.Do(func() {
c.log("connection:close", func() string { return "stopping peer idle timeout" })
c.peerIdleTimeout.Stop()
c.log("connection:close", func() string { return "sending shutdown message to peer" })
c.sendShutdown()
c.log("connection:close", func() string { return "stopping all routines and channels" })
c.cancelCtx()
c.log("connection:close", func() string { return "flushing congestion" })
c.snd.Flush()
c.recv.Flush()
c.log("connection:close", func() string { return "shutdown" })
go func() {
c.onShutdown(c)
}()
})
}
func (c *srtConn) log(topic string, message func() string) {
c.logger.Print(topic, c.socketId, 2, message)
}
func (c *srtConn) SetDeadline(t time.Time) error { return nil }
func (c *srtConn) SetReadDeadline(t time.Time) error { return nil }
func (c *srtConn) SetWriteDeadline(t time.Time) error { return nil }
func (c *srtConn) Stats(s *Statistics) {
if s == nil {
return
}
now := uint64(time.Since(c.start).Milliseconds())
send := c.snd.Stats()
recv := c.recv.Stats()
previous := s.Accumulated
interval := now - s.MsTimeStamp
c.statisticsLock.RLock()
defer c.statisticsLock.RUnlock()
// Accumulated
s.Accumulated = StatisticsAccumulated{
PktSent: send.Pkt,
PktRecv: recv.Pkt,
PktSentUnique: send.PktUnique,
PktRecvUnique: recv.PktUnique,
PktSendLoss: send.PktLoss,
PktRecvLoss: recv.PktLoss,
PktRetrans: send.PktRetrans,
PktRecvRetrans: recv.PktRetrans,
PktSentACK: c.statistics.pktSentACK,
PktRecvACK: c.statistics.pktRecvACK,
PktSentNAK: c.statistics.pktSentNAK,
PktRecvNAK: c.statistics.pktRecvNAK,
PktSentKM: c.statistics.pktSentKM,
PktRecvKM: c.statistics.pktRecvKM,
UsSndDuration: send.UsSndDuration,
PktSendDrop: send.PktDrop,
PktRecvDrop: recv.PktDrop,
PktRecvUndecrypt: c.statistics.pktRecvUndecrypt,
ByteSent: send.Byte + (send.Pkt * c.statistics.headerSize),
ByteRecv: recv.Byte + (recv.Pkt * c.statistics.headerSize),
ByteSentUnique: send.ByteUnique + (send.PktUnique * c.statistics.headerSize),
ByteRecvUnique: recv.ByteUnique + (recv.PktUnique * c.statistics.headerSize),
ByteRecvLoss: recv.ByteLoss + (recv.PktLoss * c.statistics.headerSize),
ByteRetrans: send.ByteRetrans + (send.PktRetrans * c.statistics.headerSize),
ByteRecvRetrans: recv.ByteRetrans + (recv.PktRetrans * c.statistics.headerSize),
ByteSendDrop: send.ByteDrop + (send.PktDrop * c.statistics.headerSize),
ByteRecvDrop: recv.ByteDrop + (recv.PktDrop * c.statistics.headerSize),
ByteRecvUndecrypt: c.statistics.byteRecvUndecrypt + (c.statistics.pktRecvUndecrypt * c.statistics.headerSize),
}
// Interval
s.Interval = StatisticsInterval{
MsInterval: interval,
PktSent: s.Accumulated.PktSent - previous.PktSent,
PktRecv: s.Accumulated.PktRecv - previous.PktRecv,
PktSentUnique: s.Accumulated.PktSentUnique - previous.PktSentUnique,
PktRecvUnique: s.Accumulated.PktRecvUnique - previous.PktRecvUnique,
PktSendLoss: s.Accumulated.PktSendLoss - previous.PktSendLoss,
PktRecvLoss: s.Accumulated.PktRecvLoss - previous.PktRecvLoss,
PktRetrans: s.Accumulated.PktRetrans - previous.PktRetrans,
PktRecvRetrans: s.Accumulated.PktRecvRetrans - previous.PktRecvRetrans,
PktSentACK: s.Accumulated.PktSentACK - previous.PktSentACK,
PktRecvACK: s.Accumulated.PktRecvACK - previous.PktRecvACK,
PktSentNAK: s.Accumulated.PktSentNAK - previous.PktSentNAK,
PktRecvNAK: s.Accumulated.PktRecvNAK - previous.PktRecvNAK,
MbpsSendRate: float64(s.Accumulated.ByteSent-previous.ByteSent) * 8 / 1024 / 1024 / (float64(interval) / 1000),
MbpsRecvRate: float64(s.Accumulated.ByteRecv-previous.ByteRecv) * 8 / 1024 / 1024 / (float64(interval) / 1000),
UsSndDuration: s.Accumulated.UsSndDuration - previous.UsSndDuration,
PktReorderDistance: 0,
PktRecvBelated: s.Accumulated.PktRecvBelated - previous.PktRecvBelated,
PktSndDrop: s.Accumulated.PktSendDrop - previous.PktSendDrop,
PktRecvDrop: s.Accumulated.PktRecvDrop - previous.PktRecvDrop,
PktRecvUndecrypt: s.Accumulated.PktRecvUndecrypt - previous.PktRecvUndecrypt,
ByteSent: s.Accumulated.ByteSent - previous.ByteSent,
ByteRecv: s.Accumulated.ByteRecv - previous.ByteRecv,
ByteSentUnique: s.Accumulated.ByteSentUnique - previous.ByteSentUnique,
ByteRecvUnique: s.Accumulated.ByteRecvUnique - previous.ByteRecvUnique,
ByteRecvLoss: s.Accumulated.ByteRecvLoss - previous.ByteRecvLoss,
ByteRetrans: s.Accumulated.ByteRetrans - previous.ByteRetrans,
ByteRecvRetrans: s.Accumulated.ByteRecvRetrans - previous.ByteRecvRetrans,
ByteRecvBelated: s.Accumulated.ByteRecvBelated - previous.ByteRecvBelated,
ByteSendDrop: s.Accumulated.ByteSendDrop - previous.ByteSendDrop,
ByteRecvDrop: s.Accumulated.ByteRecvDrop - previous.ByteRecvDrop,
ByteRecvUndecrypt: s.Accumulated.ByteRecvUndecrypt - previous.ByteRecvUndecrypt,
}
// Instantaneous
s.Instantaneous = StatisticsInstantaneous{
UsPktSendPeriod: send.UsPktSndPeriod,
PktFlowWindow: uint64(c.config.FC),
PktFlightSize: send.PktFlightSize,
MsRTT: c.rtt.RTT() / 1000,
MbpsSentRate: send.MbpsEstimatedSentBandwidth,
MbpsRecvRate: recv.MbpsEstimatedRecvBandwidth,
MbpsLinkCapacity: recv.MbpsEstimatedLinkCapacity,
ByteAvailSendBuf: 0, // unlimited
ByteAvailRecvBuf: 0, // unlimited
MbpsMaxBW: float64(c.config.MaxBW) / 1024 / 1024,
ByteMSS: uint64(c.config.MSS),
PktSendBuf: send.PktBuf,
ByteSendBuf: send.ByteBuf,
MsSendBuf: send.MsBuf,
MsSendTsbPdDelay: c.peerTsbpdDelay / 1000,
PktRecvBuf: recv.PktBuf,
ByteRecvBuf: recv.ByteBuf,
MsRecvBuf: recv.MsBuf,
MsRecvTsbPdDelay: c.tsbpdDelay / 1000,
PktReorderTolerance: uint64(c.config.LossMaxTTL),
PktRecvAvgBelatedTime: 0,
PktSendLossRate: send.PktLossRate,
PktRecvLossRate: recv.PktLossRate,
}
// If we're only sending, the receiver congestion control value for the link capacity is zero,
// use the value that we got from the receiver via the ACK packets.
if s.Instantaneous.MbpsLinkCapacity == 0 {
s.Instantaneous.MbpsLinkCapacity = c.statistics.mbpsLinkCapacity
}
if c.config.MaxBW < 0 {
s.Instantaneous.MbpsMaxBW = -1
}
s.MsTimeStamp = now
}
================================================
FILE: connection_test.go
================================================
package srt
import (
"bytes"
"strings"
"testing"
"time"
"github.com/datarhei/gosrt/packet"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestEncryption(t *testing.T) {
message := "Hello World!"
passphrase := "foobarfoobar"
channel := NewPubSub(PubSubConfig{})
config := DefaultConfig()
config.EnforcedEncryption = true
server := Server{
Addr: "127.0.0.1:6003",
Config: &config,
HandleConnect: func(req ConnRequest) ConnType {
if req.IsEncrypted() {
if err := req.SetPassphrase(passphrase); err != nil {
return REJECT
}
}
streamid := req.StreamId()
if streamid == "publish" {
return PUBLISH
} else if streamid == "subscribe" {
return SUBSCRIBE
}
return REJECT
},
HandlePublish: func(conn Conn) {
channel.Publish(conn)
conn.Close()
},
HandleSubscribe: func(conn Conn) {
channel.Subscribe(conn)
conn.Close()
},
}
err := server.Listen()
require.NoError(t, err)
defer server.Shutdown()
go func() {
err := server.Serve()
if err == ErrServerClosed {
return
}
require.NoError(t, err)
}()
{
// Reject connection if wrong password is set
config := DefaultConfig()
config.StreamId = "subscribe"
config.Passphrase = "barfoobarfoo"
_, err := Dial("srt", "127.0.0.1:6003", config)
require.Error(t, err)
}
// Test transmitting an encrypted message
readerConnected := make(chan struct{})
readerDone := make(chan struct{})
dataReader1 := bytes.Buffer{}
go func() {
defer close(readerDone)
config := DefaultConfig()
config.StreamId = "subscribe"
config.Passphrase = "foobarfoobar"
conn, err := Dial("srt", "127.0.0.1:6003", config)
if !assert.NoError(t, err) {
panic(err.Error())
}
close(readerConnected)
buffer := make([]byte, 2048)
for {
n, err := conn.Read(buffer)
if n != 0 {
dataReader1.Write(buffer[:n])
}
if err != nil {
break
}
}
err = conn.Close()
require.NoError(t, err)
}()
<-readerConnected
writerDone := make(chan struct{})
go func() {
defer close(writerDone)
config := DefaultConfig()
config.StreamId = "publish"
config.Passphrase = "foobarfoobar"
conn, err := Dial("srt", "127.0.0.1:6003", config)
if !assert.NoError(t, err) {
panic(err.Error())
}
n, err := conn.Write([]byte(message))
if !assert.NoError(t, err) {
panic(err.Error())
}
assert.Equal(t, 12, n)
time.Sleep(3 * time.Second)
err = conn.Close()
assert.NoError(t, err)
}()
<-writerDone
<-readerDone
reader1 := dataReader1.String()
require.Equal(t, message, reader1)
}
// Test for https://github.com/datarhei/gosrt/pull/94
func TestEncryptionRetransmit(t *testing.T) {
message := "Hello World!"
passphrase := "foobarfoobar"
channel := NewPubSub(PubSubConfig{})
config := DefaultConfig()
config.EnforcedEncryption = true
server := Server{
Addr: "127.0.0.1:6003",
Config: &config,
HandleConnect: func(req ConnRequest) ConnType {
if req.IsEncrypted() {
if err := req.SetPassphrase(passphrase); err != nil {
return REJECT
}
}
streamid := req.StreamId()
if streamid == "publish" {
return PUBLISH
} else if streamid == "subscribe" {
return SUBSCRIBE
}
return REJECT
},
HandlePublish: func(conn Conn) {
channel.Publish(conn)
conn.Close()
},
HandleSubscribe: func(conn Conn) {
channel.Subscribe(conn)
conn.Close()
},
}
err := server.Listen()
require.NoError(t, err)
defer server.Shutdown()
go func() {
err := server.Serve()
if err == ErrServerClosed {
return
}
require.NoError(t, err)
}()
{
// Reject connection if wrong password is set
config := DefaultConfig()
config.StreamId = "subscribe"
config.Passphrase = "barfoobarfoo"
_, err := Dial("srt", "127.0.0.1:6003", config)
require.Error(t, err)
}
// Test transmitting an encrypted message
readerConnected := make(chan struct{})
readerDone := make(chan struct{})
dataReader1 := bytes.Buffer{}
go func() {
defer close(readerDone)
config := DefaultConfig()
config.StreamId = "subscribe"
config.Passphrase = "foobarfoobar"
conn, err := Dial("srt", "127.0.0.1:6003", config)
if !assert.NoError(t, err) {
panic(err.Error())
}
close(readerConnected)
buffer := make([]byte, 2048)
for {
n, err := conn.Read(buffer)
if n != 0 {
dataReader1.Write(buffer[:n])
}
if err != nil {
break
}
}
err = conn.Close()
require.NoError(t, err)
}()
<-readerConnected
writerDone := make(chan struct{})
go func() {
defer close(writerDone)
config := DefaultConfig()
config.StreamId = "publish"
config.Passphrase = "foobarfoobar"
conn, err := Dial("srt", "127.0.0.1:6003", config)
if !assert.NoError(t, err) {
panic(err.Error())
}
counter := 0
dialer, _ := conn.(*dialer)
originalOnSend := dialer.conn.onSend
dialer.conn.onSend = func(p packet.Packet) {
if !p.Header().IsControlPacket {
// Drop every 2nd original packet
if !p.Header().RetransmittedPacketFlag {
counter++
if counter%2 == 0 {
return
}
}
}
originalOnSend(p)
}
for range 5 {
n, err := conn.Write([]byte(message))
if !assert.NoError(t, err) {
panic(err.Error())
}
assert.Equal(t, 12, n)
}
time.Sleep(3 * time.Second)
err = conn.Close()
assert.NoError(t, err)
}()
<-writerDone
<-readerDone
reader1 := dataReader1.String()
require.Equal(t, message+message+message+message+message, reader1)
}
func TestEncryptionKeySwap(t *testing.T) {
message := "Hello World!"
passphrase := "foobarfoobar"
channel := NewPubSub(PubSubConfig{})
config := DefaultConfig()
config.EnforcedEncryption = true
server := Server{
Addr: "127.0.0.1:6003",
Config: &config,
HandleConnect: func(req ConnRequest) ConnType {
if req.IsEncrypted() {
if err := req.SetPassphrase(passphrase); err != nil {
return REJECT
}
}
streamid := req.StreamId()
if streamid == "publish" {
return PUBLISH
} else if streamid == "subscribe" {
return SUBSCRIBE
}
return REJECT
},
HandlePublish: func(conn Conn) {
channel.Publish(conn)
conn.Close()
},
HandleSubscribe: func(conn Conn) {
channel.Subscribe(conn)
conn.Close()
},
}
err := server.Listen()
require.NoError(t, err)
defer server.Shutdown()
go func() {
err := server.Serve()
if err == ErrServerClosed {
return
}
require.NoError(t, err)
}()
// Test transmitting encrypted messages with key swap in between
dataReader1 := bytes.Buffer{}
readerConnected := make(chan struct{})
readerDone := make(chan struct{})
go func() {
defer close(readerDone)
config := DefaultConfig()
config.StreamId = "subscribe"
config.Passphrase = "foobarfoobar"
conn, err := Dial("srt", "127.0.0.1:6003", config)
if !assert.NoError(t, err) {
panic(err.Error())
}
buffer := make([]byte, 2048)
close(readerConnected)
for {
n, err := conn.Read(buffer)
if n != 0 {
dataReader1.Write(buffer[:n])
}
if err != nil {
break
}
}
err = conn.Close()
assert.NoError(t, err)
}()
<-readerConnected
writerDone := make(chan struct{})
go func() {
defer close(writerDone)
config := DefaultConfig()
config.StreamId = "publish"
config.Passphrase = "foobarfoobar"
// Swap encryption key after 50 sent messages
config.KMPreAnnounce = 10
config.KMRefreshRate = 30
conn, err := Dial("srt", "127.0.0.1:6003", config)
if !assert.NoError(t, err) {
panic(err.Error())
}
// Send 150 messages
for range 150 {
n, err := conn.Write([]byte(message))
if !assert.NoError(t, err) {
panic(err.Error())
}
assert.Equal(t, 12, n)
}
time.Sleep(3 * time.Second)
err = conn.Close()
assert.NoError(t, err)
}()
<-writerDone
<-readerDone
reader1 := dataReader1.String()
require.Equal(t, strings.Repeat(message, 150), reader1)
}
func TestStats(t *testing.T) {
message := "Hello World!"
channel := NewPubSub(PubSubConfig{})
config := DefaultConfig()
server := Server{
Addr: "127.0.0.1:6003",
Config: &config,
HandleConnect: func(req ConnRequest) ConnType {
streamid := req.StreamId()
if streamid == "publish" {
return PUBLISH
} else if streamid == "subscribe" {
return SUBSCRIBE
}
return REJECT
},
HandlePublish: func(conn Conn) {
channel.Publish(conn)
conn.Close()
},
HandleSubscribe: func(conn Conn) {
channel.Subscribe(conn)
conn.Close()
},
}
err := server.Listen()
require.NoError(t, err)
defer server.Shutdown()
go func() {
err := server.Serve()
if err == ErrServerClosed {
return
}
require.NoError(t, err)
}()
statsReader := Statistics{}
statsWriter := Statistics{}
readerConnected := make(chan struct{})
readerDone := make(chan struct{})
dataReader1 := bytes.Buffer{}
go func() {
defer close(readerDone)
config := DefaultConfig()
config.StreamId = "subscribe"
conn, err := Dial("srt", "127.0.0.1:6003", config)
if !assert.NoError(t, err) {
panic(err.Error())
}
close(readerConnected)
buffer := make([]byte, 2048)
for {
n, err := conn.Read(buffer)
if n != 0 {
dataReader1.Write(buffer[:n])
}
if err != nil {
break
}
}
conn.Stats(&statsReader)
err = conn.Close()
require.NoError(t, err)
}()
<-readerConnected
writerDone := make(chan struct{})
go func() {
defer close(writerDone)
config := DefaultConfig()
config.StreamId = "publish"
conn, err := Dial("srt", "127.0.0.1:6003", config)
if !assert.NoError(t, err) {
panic(err.Error())
}
n, err := conn.Write([]byte(message))
if !assert.NoError(t, err) {
panic(err.Error())
}
assert.Equal(t, 12, n)
time.Sleep(3 * time.Second)
conn.Stats(&statsWriter)
err = conn.Close()
assert.NoError(t, err)
}()
<-writerDone
<-readerDone
reader1 := dataReader1.String()
require.Equal(t, message, reader1)
require.Equal(t, uint64(len(message)+44), statsReader.Accumulated.ByteRecv)
require.Equal(t, uint64(1), statsReader.Accumulated.PktRecv)
require.Equal(t, uint64(len(message)+44), statsWriter.Accumulated.ByteSent)
require.Equal(t, uint64(1), statsWriter.Accumulated.PktSent)
}
================================================
FILE: contrib/client/main.go
================================================
package main
import (
"encoding/json"
"flag"
"fmt"
"io"
"net"
"net/url"
"os"
"os/signal"
"strconv"
"strings"
"sync"
"time"
srt "github.com/datarhei/gosrt"
)
type stats struct {
bprev uint64
btotal uint64
prev uint64
total uint64
lock sync.Mutex
period time.Duration
last time.Time
}
func (s *stats) init(period time.Duration) {
s.bprev = 0
s.btotal = 0
s.prev = 0
s.total = 0
s.period = period
s.last = time.Now()
go s.tick()
}
func (s *stats) tick() {
ticker := time.NewTicker(s.period)
defer ticker.Stop()
for c := range ticker.C {
s.lock.Lock()
diff := c.Sub(s.last)
bavg := float64(s.btotal-s.bprev) * 8 / (1000 * 1000 * diff.Seconds())
avg := float64(s.total-s.prev) / diff.Seconds()
s.bprev = s.btotal
s.prev = s.total
s.last = c
s.lock.Unlock()
fmt.Fprintf(os.Stderr, "\r%-54s: %8.3f kpackets (%8.3f packets/s), %8.3f mbytes (%8.3f Mbps)", c, float64(s.total)/1024, avg, float64(s.btotal)/1024/1024, bavg)
}
}
func (s *stats) update(n uint64) {
s.lock.Lock()
defer s.lock.Unlock()
s.btotal += n
s.total++
}
func main() {
var from string
var to string
var logtopics string
flag.StringVar(&from, "from", "", "Address to read from, sources: srt://, udp://, - (stdin)")
flag.StringVar(&to, "to", "", "Address to write to, targets: srt://, udp://, file://, - (stdout)")
flag.StringVar(&logtopics, "logtopics", "", "topics for the log output")
flag.Parse()
var logger srt.Logger
if len(logtopics) != 0 {
logger = srt.NewLogger(strings.Split(logtopics, ","))
}
go func() {
if logger == nil {
return
}
for m := range logger.Listen() {
fmt.Fprintf(os.Stderr, "%#08x %s (in %s:%d)\n%s \n", m.SocketId, m.Topic, m.File, m.Line, m.Message)
}
}()
r, err := openReader(from, logger)
if err != nil {
fmt.Fprintf(os.Stderr, "Error: from: %v\n", err)
flag.PrintDefaults()
os.Exit(1)
}
w, err := openWriter(to, logger)
if err != nil {
fmt.Fprintf(os.Stderr, "Error: to: %v\n", err)
flag.PrintDefaults()
os.Exit(1)
}
doneChan := make(chan error)
go func() {
buffer := make([]byte, 2048)
s := stats{}
s.init(200 * time.Millisecond)
for {
n, err := r.Read(buffer)
if err != nil {
doneChan <- fmt.Errorf("read: %w", err)
return
}
s.update(uint64(n))
if _, err := w.Write(buffer[:n]); err != nil {
doneChan <- fmt.Errorf("write: %w", err)
return
}
}
}()
go func() {
quit := make(chan os.Signal, 1)
signal.Notify(quit, os.Interrupt)
<-quit
doneChan <- nil
}()
if err := <-doneChan; err != nil {
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
} else {
fmt.Fprint(os.Stderr, "\n")
}
w.Close()
if srtconn, ok := w.(srt.Conn); ok {
stats := &srt.Statistics{}
srtconn.Stats(stats)
data, err := json.MarshalIndent(stats, "", " ")
if err != nil {
fmt.Fprintf(os.Stderr, "writer: %+v\n", stats)
} else {
fmt.Fprintf(os.Stderr, "writer: %s\n", string(data))
}
}
r.Close()
if srtconn, ok := r.(srt.Conn); ok {
stats := &srt.Statistics{}
srtconn.Stats(stats)
data, err := json.MarshalIndent(stats, "", " ")
if err != nil {
fmt.Fprintf(os.Stderr, "reader: %+v\n", stats)
} else {
fmt.Fprintf(os.Stderr, "reader: %s\n", string(data))
}
}
if logger != nil {
logger.Close()
}
}
func openReader(addr string, logger srt.Logger) (io.ReadCloser, error) {
if len(addr) == 0 {
return nil, fmt.Errorf("the address must not be empty")
}
if addr == "-" {
if os.Stdin == nil {
return nil, fmt.Errorf("stdin is not defined")
}
return os.Stdin, nil
}
if strings.HasPrefix(addr, "debug://") {
readerOptions := DebugReaderOptions{}
parts := strings.SplitN(strings.TrimPrefix(addr, "debug://"), "?", 2)
if len(parts) > 1 {
options, err := url.ParseQuery(parts[1])
if err != nil {
return nil, err
}
if x, err := strconv.ParseUint(options.Get("bitrate"), 10, 64); err == nil {
readerOptions.Bitrate = x
}
}
r, err := NewDebugReader(readerOptions)
return r, err
}
u, err := url.Parse(addr)
if err != nil {
return nil, err
}
if u.Scheme == "srt" {
config := srt.DefaultConfig()
if err := config.UnmarshalQuery(u.RawQuery); err != nil {
return nil, err
}
config.Logger = logger
mode := u.Query().Get("mode")
if mode == "listener" {
ln, err := srt.Listen("srt", u.Host, config)
if err != nil {
return nil, err
}
conn, _, err := ln.Accept(func(req srt.ConnRequest) srt.ConnType {
if config.StreamId != req.StreamId() {
return srt.REJECT
}
req.SetPassphrase(config.Passphrase)
return srt.PUBLISH
})
if err != nil {
return nil, err
}
if conn == nil {
return nil, fmt.Errorf("incoming connection rejected")
}
return conn, nil
} else if mode == "caller" {
conn, err := srt.Dial("srt", u.Host, config)
if err != nil {
return nil, err
}
return conn, nil
} else {
return nil, fmt.Errorf("unsupported mode")
}
} else if u.Scheme == "udp" {
laddr, err := net.ResolveUDPAddr("udp", u.Host)
if err != nil {
return nil, err
}
conn, err := net.ListenUDP("udp", laddr)
if err != nil {
return nil, err
}
return conn, nil
}
return nil, fmt.Errorf("unsupported reader")
}
func openWriter(addr string, logger srt.Logger) (io.WriteCloser, error) {
if len(addr) == 0 {
return nil, fmt.Errorf("the address must not be empty")
}
if addr == "-" {
if os.Stdout == nil {
return nil, fmt.Errorf("stdout is not defined")
}
return NewNonblockingWriter(os.Stdout, 2048), nil
}
if after, ok := strings.CutPrefix(addr, "file://"); ok {
path := after
file, err := os.Create(path)
if err != nil {
return nil, err
}
return NewNonblockingWriter(file, 2048), nil
}
u, err := url.Parse(addr)
if err != nil {
return nil, err
}
if u.Scheme == "srt" {
config := srt.DefaultConfig()
if err := config.UnmarshalQuery(u.RawQuery); err != nil {
return nil, err
}
config.Logger = logger
mode := u.Query().Get("mode")
if mode == "listener" {
ln, err := srt.Listen("srt", u.Host, config)
if err != nil {
return nil, err
}
conn, _, err := ln.Accept(func(req srt.ConnRequest) srt.ConnType {
if config.StreamId != req.StreamId() {
return srt.REJECT
}
req.SetPassphrase(config.Passphrase)
return srt.SUBSCRIBE
})
if err != nil {
return nil, err
}
if conn == nil {
return nil, fmt.Errorf("incoming connection rejected")
}
return conn, nil
} else if mode == "caller" {
conn, err := srt.Dial("srt", u.Host, config)
if err != nil {
return nil, err
}
return conn, nil
} else {
return nil, fmt.Errorf("unsupported mode")
}
} else if u.Scheme == "udp" {
raddr, err := net.ResolveUDPAddr("udp", u.Host)
if err != nil {
return nil, err
}
conn, err := net.DialUDP("udp", nil, raddr)
if err != nil {
return nil, err
}
return conn, nil
}
return nil, fmt.Errorf("unsupported writer")
}
================================================
FILE: contrib/client/reader.go
================================================
package main
import (
"context"
"io"
"time"
)
type Reader interface {
io.ReadCloser
}
type debugReader struct {
bytesPerSec uint64
cancel context.CancelFunc
data chan byte
}
type DebugReaderOptions struct {
Bitrate uint64
}
func NewDebugReader(options DebugReaderOptions) (Reader, error) {
r := &debugReader{
bytesPerSec: options.Bitrate / 8,
}
if r.bytesPerSec == 0 {
r.bytesPerSec = 262_144 // 2Mbit/s
}
r.data = make(chan byte, r.bytesPerSec)
ctx, cancel := context.WithCancel(context.Background())
r.cancel = cancel
go r.generator(ctx)
return r, nil
}
func (r *debugReader) Read(p []byte) (int, error) {
len := len(p)
if len == 0 {
return 0, nil
}
var i int = 0
for b := range r.data {
p[i] = b
i += 1
if i == len {
break
}
}
return i, nil
}
func (r *debugReader) Close() error {
r.cancel()
return nil
}
func (r *debugReader) generator(ctx context.Context) {
t := time.NewTicker(100 * time.Millisecond)
defer t.Stop()
s := "abcdefghijklmnopqrstuvwxyz*"
pivot := 0
defer func() { close(r.data) }()
for {
select {
case <-ctx.Done():
return
case <-t.C:
for i := uint64(0); i < r.bytesPerSec/10; i += 1 {
r.data <- s[pivot]
pivot += 1
if pivot >= len(s) {
pivot = 0
}
}
}
}
}
================================================
FILE: contrib/client/writer.go
================================================
package main
import (
"bytes"
"io"
"sync"
"time"
)
// NonblockingWriter is a io.Writer and io.Closer that won't block
// any writes. If the underlying writer is blocking the data will be
// buffered until it's available again.
type Writer interface {
io.WriteCloser
}
// nonblockingWriter implements the NonblockingWriter interface
type nonblockingWriter struct {
dst io.WriteCloser
buf *bytes.Buffer
lock sync.RWMutex
size int
done bool
}
// NewNonblockingWriter return a new NonBlockingWriter with writer as the
// underlying writer. The size is the number of bytes to write to the
// underlying writer in one iteration. It written as fast as possible to
// the underlying writer. If there's no more data available to write
// a pause of 10 milliseconds will be done. There's currently no limit
// for the amount of data to be buffered. A call of the Close function
// will close this writer. The underlying writer will not be closed. In
// case there's an error while writing to the underlying writer, this
// will close itself.
func NewNonblockingWriter(writer io.WriteCloser, size int) Writer {
u := &nonblockingWriter{
dst: writer,
buf: new(bytes.Buffer),
size: size,
done: false,
}
if u.size <= 0 {
u.size = 2048
}
go u.writer()
return u
}
func (u *nonblockingWriter) Write(p []byte) (int, error) {
if u.done {
return 0, io.EOF
}
u.lock.Lock()
defer u.lock.Unlock()
return u.buf.Write(p)
}
func (u *nonblockingWriter) Close() error {
u.done = true
u.dst.Close()
return nil
}
// writer writes to the underlying writer in chunks read from
// the buffer. If the buffer is empty, a short pause will be made.
func (u *nonblockingWriter) writer() {
p := make([]byte, u.size)
for {
u.lock.RLock()
n, err := u.buf.Read(p)
u.lock.RUnlock()
if n == 0 || err == io.EOF {
if u.done {
break
}
time.Sleep(10 * time.Millisecond)
continue
}
if _, err := u.dst.Write(p[:n]); err != nil {
break
}
}
u.done = true
}
================================================
FILE: contrib/server/main.go
================================================
package main
import (
"flag"
"fmt"
"net"
"net/url"
"os"
"os/signal"
"strings"
"sync"
srt "github.com/datarhei/gosrt"
"github.com/pkg/profile"
)
// server is an implementation of the Server framework
type server struct {
// Configuration parameter taken from the Config
addr string
app string
token string
passphrase string
logtopics string
profile string
server *srt.Server
// Map of publishing channels and a lock to serialize
// access to the map.
channels map[string]srt.PubSub
lock sync.RWMutex
}
func (s *server) ListenAndServe() error {
if len(s.app) == 0 {
s.app = "/"
}
return s.server.ListenAndServe()
}
func (s *server) Shutdown() {
s.server.Shutdown()
}
func main() {
s := server{
channels: make(map[string]srt.PubSub),
}
flag.StringVar(&s.addr, "addr", "", "address to listen on")
flag.StringVar(&s.app, "app", "", "path prefix for streamid")
flag.StringVar(&s.token, "token", "", "token query param for streamid")
flag.StringVar(&s.passphrase, "passphrase", "", "passphrase for de- and enrcypting the data")
flag.StringVar(&s.logtopics, "logtopics", "", "topics for the log output")
flag.StringVar(&s.profile, "profile", "", "enable profiling (cpu, mem, allocs, heap, rate, mutex, block, thread, trace)")
flag.Parse()
if len(s.addr) == 0 {
fmt.Fprintf(os.Stderr, "Provide a listen address with -addr\n")
os.Exit(1)
}
var p func(*profile.Profile)
switch s.profile {
case "cpu":
p = profile.CPUProfile
case "mem":
p = profile.MemProfile
case "allocs":
p = profile.MemProfileAllocs
case "heap":
p = profile.MemProfileHeap
case "rate":
p = profile.MemProfileRate(2048)
case "mutex":
p = profile.MutexProfile
case "block":
p = profile.BlockProfile
case "thread":
p = profile.ThreadcreationProfile
case "trace":
p = profile.TraceProfile
default:
}
if p != nil {
defer profile.Start(profile.ProfilePath("."), profile.NoShutdownHook, p).Stop()
}
config := srt.DefaultConfig()
if len(s.logtopics) != 0 {
config.Logger = srt.NewLogger(strings.Split(s.logtopics, ","))
}
config.KMPreAnnounce = 200
config.KMRefreshRate = 10000
s.server = &srt.Server{
Addr: s.addr,
HandleConnect: s.handleConnect,
HandlePublish: s.handlePublish,
HandleSubscribe: s.handleSubscribe,
Config: &config,
}
fmt.Fprintf(os.Stderr, "Listening on %s\n", s.addr)
go func() {
if config.Logger == nil {
return
}
for m := range config.Logger.Listen() {
fmt.Fprintf(os.Stderr, "%#08x %s (in %s:%d)\n%s \n", m.SocketId, m.Topic, m.File, m.Line, m.Message)
}
}()
go func() {
if err := s.ListenAndServe(); err != nil && err != srt.ErrServerClosed {
fmt.Fprintf(os.Stderr, "SRT Server: %s\n", err)
os.Exit(2)
}
}()
quit := make(chan os.Signal, 1)
signal.Notify(quit, os.Interrupt)
<-quit
s.Shutdown()
if config.Logger != nil {
config.Logger.Close()
}
}
func (s *server) log(who, action, path, message string, client net.Addr) {
fmt.Fprintf(os.Stderr, "%-10s %10s %s (%s) %s\n", who, action, path, client, message)
}
func (s *server) handleConnect(req srt.ConnRequest) srt.ConnType {
var mode srt.ConnType = srt.SUBSCRIBE
client := req.RemoteAddr()
channel := ""
if req.Version() == 4 {
mode = srt.PUBLISH
channel = "/" + client.String()
req.SetPassphrase(s.passphrase)
} else if req.Version() == 5 {
streamId := req.StreamId()
path := streamId
if strings.HasPrefix(streamId, "publish:") {
mode = srt.PUBLISH
path = strings.TrimPrefix(streamId, "publish:")
} else if after, ok := strings.CutPrefix(streamId, "subscribe:"); ok {
path = after
}
u, err := url.Parse(path)
if err != nil {
return srt.REJECT
}
if req.IsEncrypted() {
if err := req.SetPassphrase(s.passphrase); err != nil {
s.log("CONNECT", "FORBIDDEN", u.Path, err.Error(), client)
return srt.REJECT
}
}
// Check the token
token := u.Query().Get("token")
if len(s.token) != 0 && s.token != token {
s.log("CONNECT", "FORBIDDEN", u.Path, "invalid token ("+token+")", client)
return srt.REJECT
}
// Check the app patch
if !strings.HasPrefix(u.Path, s.app) {
s.log("CONNECT", "FORBIDDEN", u.Path, "invalid app", client)
return srt.REJECT
}
if len(strings.TrimPrefix(u.Path, s.app)) == 0 {
s.log("CONNECT", "INVALID", u.Path, "stream name not provided", client)
return srt.REJECT
}
channel = u.Path
} else {
return srt.REJECT
}
s.lock.RLock()
pubsub := s.channels[channel]
s.lock.RUnlock()
if mode == srt.PUBLISH && pubsub != nil {
s.log("CONNECT", "CONFLICT", channel, "already publishing", client)
return srt.REJECT
}
if mode == srt.SUBSCRIBE && pubsub == nil {
s.log("CONNECT", "NOTFOUND", channel, "not publishing", client)
return srt.REJECT
}
return mode
}
func (s *server) handlePublish(conn srt.Conn) {
channel := ""
client := conn.RemoteAddr()
if client == nil {
conn.Close()
return
}
if conn.Version() == 4 {
channel = "/" + client.String()
} else if conn.Version() == 5 {
streamId := conn.StreamId()
path := strings.TrimPrefix(streamId, "publish:")
channel = path
} else {
s.log("PUBLISH", "INVALID", channel, "unknown connection version", client)
conn.Close()
return
}
// Look for the stream
s.lock.Lock()
pubsub := s.channels[channel]
if pubsub == nil {
pubsub = srt.NewPubSub(srt.PubSubConfig{
Logger: s.server.Config.Logger,
})
s.channels[channel] = pubsub
} else {
pubsub = nil
}
s.lock.Unlock()
if pubsub == nil {
s.log("PUBLISH", "CONFLICT", channel, "already publishing", client)
conn.Close()
return
}
s.log("PUBLISH", "START", channel, "publishing", client)
pubsub.Publish(conn)
s.lock.Lock()
delete(s.channels, channel)
s.lock.Unlock()
s.log("PUBLISH", "STOP", channel, "", client)
stats := &srt.Statistics{}
conn.Stats(stats)
fmt.Fprintf(os.Stderr, "%+v\n", stats)
conn.Close()
}
func (s *server) handleSubscribe(conn srt.Conn) {
channel := ""
client := conn.RemoteAddr()
if client == nil {
conn.Close()
return
}
if conn.Version() == 4 {
channel = client.String()
} else if conn.Version() == 5 {
streamId := conn.StreamId()
path := strings.TrimPrefix(streamId, "subscribe:")
channel = path
} else {
s.log("SUBSCRIBE", "INVALID", channel, "unknown connection version", client)
conn.Close()
return
}
s.log("SUBSCRIBE", "START", channel, "", client)
// Look for the stream
s.lock.RLock()
pubsub := s.channels[channel]
s.lock.RUnlock()
if pubsub == nil {
s.log("SUBSCRIBE", "NOTFOUND", channel, "not publishing", client)
conn.Close()
return
}
pubsub.Subscribe(conn)
s.log("SUBSCRIBE", "STOP", channel, "", client)
stats := &srt.Statistics{}
conn.Stats(stats)
fmt.Fprintf(os.Stderr, "%+v\n", stats)
conn.Close()
}
================================================
FILE: crypto/crypto.go
================================================
// Package crypto provides SRT cryptography
package crypto
import (
"crypto/aes"
"crypto/cipher"
"crypto/pbkdf2"
"crypto/sha1"
"encoding/binary"
"errors"
"fmt"
"github.com/datarhei/gosrt/packet"
"github.com/datarhei/gosrt/rand"
"github.com/benburkert/openpgp/aes/keywrap"
)
// Crypto implements the SRT data encryption and decryption.
type Crypto interface {
// Generate generates an even or odd SEK.
GenerateSEK(key packet.PacketEncryption) error
// UnmarshalMK unwraps the key with the passphrase in a Key Material Extension Message. If the passphrase
// is wrong an error is returned.
UnmarshalKM(km *packet.CIFKeyMaterialExtension, passphrase string) error
// MarshalKM wraps the key with the passphrase and the odd/even SEK for a Key Material Extension Message.
MarshalKM(km *packet.CIFKeyMaterialExtension, passphrase string, key packet.PacketEncryption) error
// EncryptOrDecryptPayload encrypts or decrypts the data of a packet with an even or odd SEK and
// the sequence number.
EncryptOrDecryptPayload(data []byte, key packet.PacketEncryption, packetSequenceNumber uint32) error
}
// crypto implements the Crypto interface
type crypto struct {
salt []byte
keyLength int
evenSEK []byte
oddSEK []byte
}
// New returns a new SRT data encryption and decryption for the keyLength. On failure
// error is non-nil.
func New(keyLength int) (Crypto, error) {
// 3.2.2. Key Material
switch keyLength {
case 16:
case 24:
case 32:
default:
return nil, fmt.Errorf("crypto: invalid key size, must be either 16, 24, or 32")
}
c := &crypto{
keyLength: keyLength,
}
// 3.2.2. Key Material: "The only valid length of salt defined is 128 bits."
c.salt = make([]byte, 16)
if err := c.prng(c.salt); err != nil {
return nil, fmt.Errorf("crypto: can't generate salt: %w", err)
}
sek, err := c.generateSEK(c.keyLength)
if err != nil {
return nil, err
}
c.evenSEK = sek
sek, err = c.generateSEK(c.keyLength)
if err != nil {
return nil, err
}
c.oddSEK = sek
return c, nil
}
func (c *crypto) GenerateSEK(key packet.PacketEncryption) error {
if !key.IsValid() {
return fmt.Errorf("crypto: unknown key type")
}
sek, err := c.generateSEK(c.keyLength)
if err != nil {
return err
}
switch key {
case packet.EvenKeyEncrypted:
c.evenSEK = sek
case packet.OddKeyEncrypted:
c.oddSEK = sek
}
return nil
}
func (c *crypto) generateSEK(keyLength int) ([]byte, error) {
sek := make([]byte, keyLength)
err := c.prng(sek)
if err != nil {
return nil, fmt.Errorf("crypto: can't generate SEK: %w", err)
}
return sek, nil
}
// ErrInvalidKey is returned when the packet encryption is invalid
var ErrInvalidKey = errors.New("crypto: invalid key for encryption. Must be even, odd, or both")
// ErrInvalidWrap is returned when the packet encryption indicates a different length of the wrapped key
var ErrInvalidWrap = errors.New("crypto: the un/wrapped key has the wrong length")
func (c *crypto) UnmarshalKM(km *packet.CIFKeyMaterialExtension, passphrase string) error {
if km.KeyBasedEncryption == packet.UnencryptedPacket || !km.KeyBasedEncryption.IsValid() {
return ErrInvalidKey
}
n := 1
if km.KeyBasedEncryption == packet.EvenAndOddKey {
n = 2
}
wrapLength := n * c.keyLength
if len(km.Wrap)-8 != wrapLength {
return ErrInvalidWrap
}
if len(km.Salt) != 0 {
copy(c.salt, km.Salt)
}
kek, err := c.calculateKEK(passphrase, c.salt, c.keyLength)
if err != nil {
return err
}
unwrap, err := keywrap.Unwrap(kek, km.Wrap)
if err != nil {
return err
}
if len(unwrap) != wrapLength {
return ErrInvalidWrap
}
switch km.KeyBasedEncryption {
case packet.EvenKeyEncrypted:
copy(c.evenSEK, unwrap)
case packet.OddKeyEncrypted:
copy(c.oddSEK, unwrap)
default:
copy(c.evenSEK, unwrap[:c.keyLength])
copy(c.oddSEK, unwrap[c.keyLength:])
}
return nil
}
func (c *crypto) MarshalKM(km *packet.CIFKeyMaterialExtension, passphrase string, key packet.PacketEncryption) error {
if key == packet.UnencryptedPacket || !key.IsValid() {
return ErrInvalidKey
}
km.S = 0
km.Version = 1
km.PacketType = 2
km.Sign = 0x2029
km.KeyBasedEncryption = key // even or odd key
km.KeyEncryptionKeyIndex = 0
km.Cipher = 2
km.Authentication = 0
km.StreamEncapsulation = 2
km.SLen = 16
km.KLen = uint16(c.keyLength)
if len(km.Salt) != 16 {
km.Salt = make([]byte, 16)
}
copy(km.Salt, c.salt)
n := 1
if key == packet.EvenAndOddKey {
n = 2
}
w := make([]byte, n*c.keyLength)
switch key {
case packet.EvenKeyEncrypted:
copy(w, c.evenSEK)
case packet.OddKeyEncrypted:
copy(w, c.oddSEK)
default:
copy(w[:c.keyLength], c.evenSEK)
copy(w[c.keyLength:], c.oddSEK)
}
kek, err := c.calculateKEK(passphrase, c.salt, c.keyLength)
if err != nil {
return err
}
wrap, err := keywrap.Wrap(kek, w)
if err != nil {
return err
}
if len(km.Wrap) != len(wrap) {
km.Wrap = make([]byte, len(wrap))
}
copy(km.Wrap, wrap)
return nil
}
func (c *crypto) EncryptOrDecryptPayload(data []byte, key packet.PacketEncryption, packetSequenceNumber uint32) error {
// 6.1.2. AES Counter
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
// +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
// | 0s | psn | 0 0|
// +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
// XOR
// +---+---+---+---+---+---+---+---+---+---+---+---+---+---+
// | MSB(112, Salt) |
// +---+---+---+---+---+---+---+---+---+---+---+---+---+---+
//
// psn (32 bit): packet sequence number
// ctr (16 bit): block counter, all zeros
// nonce (112 bit): 14 most significant bytes of the salt
//
// CTR = (MSB(112, Salt) XOR psn) << 16
if len(c.salt) != 16 {
return fmt.Errorf("crypto: invalid salt. Must be of length 16 bytes")
}
ctr := make([]byte, 16)
binary.BigEndian.PutUint32(ctr[10:], packetSequenceNumber)
for i := range ctr[:14] {
ctr[i] ^= c.salt[i]
}
var sek []byte
switch key {
case packet.EvenKeyEncrypted:
sek = c.evenSEK
case packet.OddKeyEncrypted:
sek = c.oddSEK
default:
return fmt.Errorf("crypto: invalid SEK selected. Must be either even or odd")
}
// 6.2.2. Encrypting the Payload
// 6.3.2. Decrypting the Payload
block, err := aes.NewCipher(sek)
if err != nil {
return err
}
stream := cipher.NewCTR(block, ctr)
stream.XORKeyStream(data, data)
return nil
}
// calculateKEK calculates a KEK based on the passphrase.
func (c *crypto) calculateKEK(passphrase string, salt []byte, keyLength int) ([]byte, error) {
// 6.1.4. Key Encrypting Key (KEK)
return pbkdf2.Key(sha1.New, passphrase, salt[8:], 2048, keyLength)
}
// prng generates a random sequence of byte into the given slice p.
func (c *crypto) prng(p []byte) error {
_, err := rand.Read(p)
return err
}
================================================
FILE: crypto/crypto_test.go
================================================
package crypto
import (
"bytes"
"encoding/hex"
"testing"
"github.com/datarhei/gosrt/packet"
"github.com/stretchr/testify/require"
)
func mustDecodeString(s string) []byte {
b, err := hex.DecodeString(s)
if err != nil {
panic(err)
}
return b
}
func TestInvalidKeylength(t *testing.T) {
_, err := New(42)
require.Error(t, err, "succeeded to create crypto with invalid keylength")
}
func TestInvalidKM(t *testing.T) {
c, err := New(16)
require.NoError(t, err)
km := &packet.CIFKeyMaterialExtension{}
km.KeyBasedEncryption = packet.UnencryptedPacket
km.Salt = mustDecodeString("6c438852715a4d26e0e810b3132ca61f")
km.Wrap = mustDecodeString("699ab4eac6b7c66c3a9fa0d6836326c2b294a10764233356")
err = c.UnmarshalKM(km, "foobarfoobar")
require.ErrorIs(t, err, ErrInvalidKey)
km = &packet.CIFKeyMaterialExtension{}
km.KeyBasedEncryption = packet.EvenKeyEncrypted
km.Salt = mustDecodeString("6c438852715a4d26e0e810b3132ca61f")
km.Wrap = mustDecodeString("5b901889bd106609ca8a83264b12ed1bfab3f02812bad65784ac396b1f57eb16c53e1020d3a3250b")
err = c.UnmarshalKM(km, "foobarfoobar")
require.ErrorIs(t, err, ErrInvalidWrap)
}
func TestUnmarshal(t *testing.T) {
tests := []struct {
keylength int
salt string
passphrase string
evenWrap string
oddWrap string
evenOddWrap string
}{
{
keylength: 16,
salt: "6c438852715a4d26e0e810b3132ca61f",
passphrase: "foobarfoobar",
evenWrap: "699ab4eac6b7c66c3a9fa0d6836326c2b294a10764233356",
oddWrap: "ca4decaaf8d7b5c38288e84c8796929c84b7c139f1f769d5",
evenOddWrap: "5b901889bd106609ca8a83264b12ed1bfab3f02812bad65784ac396b1f57eb16c53e1020d3a3250b",
},
{
keylength: 24,
salt: "e636259ccc41e73611b9363bb58586b1",
passphrase: "foobarfoobar",
evenWrap: "8c6502d6a83e0ab894a43cb5b37b71c2755afc64a682bed9d46912138b60f384",
oddWrap: "1fe56a4475759636674a7c5e44f1cdfb365a9f11d8fe74536e8df6b97eecf1c9",
evenOddWrap: "7360357d363ebec384885b10c8120528889d1be05624bfc381c5fa090f00f9ecef5d6427f7542a58be144f4aeb07452beca546874a68197d",
},
{
keylength: 32,
salt: "3825bb4163f7d5cf2804ec0b31a7370f",
passphrase: "foobarfoobar",
evenWrap: "7d1578458e41680dd997d1a185c75753f3344c6711542b35833f881f7c480304cbe9bdbe76035914",
oddWrap: "cc1af097af558fa25b925417c4e6e9e1adacd8b96916b4ac4fac8e6ecdc3b5c48c01134e92e9e5f6",
evenOddWrap: "f7373def4e9f61f6cd6a22e78916aa07cac8e5f07669d556ec8a15b7631fa9c631e9d98a3f92dbe187f434569ec71b9e2a53171feafd909a5560233fe02ed0301e576d4992b10c86",
},
}
for _, test := range tests {
c, err := New(test.keylength)
require.NoError(t, err)
km := &packet.CIFKeyMaterialExtension{}
km.KeyBasedEncryption = packet.EvenKeyEncrypted
km.Salt = mustDe
gitextract_58kqutjt/
├── .dockerignore
├── .editorconfig
├── .github/
│ ├── dependabot.yml
│ └── workflows/
│ ├── codeql-analysis.yml
│ └── go-tests.yml
├── .gitignore
├── CODE_OF_CONDUCT.md
├── Dockerfile
├── LICENSE
├── Makefile
├── README.md
├── SECURITY.md
├── circular/
│ ├── circular.go
│ └── circular_test.go
├── config.go
├── config_test.go
├── congestion/
│ ├── congestion.go
│ └── live/
│ ├── doc.go
│ ├── fake.go
│ ├── receive.go
│ ├── receive_test.go
│ ├── send.go
│ └── send_test.go
├── conn_request.go
├── connection.go
├── connection_test.go
├── contrib/
│ ├── client/
│ │ ├── main.go
│ │ ├── reader.go
│ │ └── writer.go
│ └── server/
│ └── main.go
├── crypto/
│ ├── crypto.go
│ └── crypto_test.go
├── dial.go
├── dial_test.go
├── doc.go
├── go.mod
├── go.sum
├── listen.go
├── listen_test.go
├── log.go
├── log_test.go
├── net/
│ ├── ip.go
│ ├── ip_test.go
│ ├── syncookie.go
│ └── syncookie_test.go
├── net.go
├── net_windows.go
├── packet/
│ ├── packet.go
│ └── packet_test.go
├── packet_conn.go
├── pubsub.go
├── pubsub_test.go
├── rand/
│ ├── rand.go
│ └── rand_test.go
├── server.go
├── server_test.go
├── statistics.go
└── vendor/
├── github.com/
│ ├── benburkert/
│ │ └── openpgp/
│ │ └── aes/
│ │ └── keywrap/
│ │ ├── doc.go
│ │ └── keywrap.go
│ ├── davecgh/
│ │ └── go-spew/
│ │ ├── LICENSE
│ │ └── spew/
│ │ ├── bypass.go
│ │ ├── bypasssafe.go
│ │ ├── common.go
│ │ ├── config.go
│ │ ├── doc.go
│ │ ├── dump.go
│ │ ├── format.go
│ │ └── spew.go
│ ├── felixge/
│ │ └── fgprof/
│ │ ├── BenchmarkProfilerGoroutines.txt
│ │ ├── LICENSE.txt
│ │ ├── README.md
│ │ ├── fgprof.go
│ │ └── handler.go
│ ├── google/
│ │ └── pprof/
│ │ ├── AUTHORS
│ │ ├── CONTRIBUTORS
│ │ ├── LICENSE
│ │ └── profile/
│ │ ├── encode.go
│ │ ├── filter.go
│ │ ├── index.go
│ │ ├── legacy_java_profile.go
│ │ ├── legacy_profile.go
│ │ ├── merge.go
│ │ ├── profile.go
│ │ ├── proto.go
│ │ └── prune.go
│ ├── pkg/
│ │ └── profile/
│ │ ├── .travis.yml
│ │ ├── AUTHORS
│ │ ├── LICENSE
│ │ ├── README.md
│ │ └── profile.go
│ ├── pmezard/
│ │ └── go-difflib/
│ │ ├── LICENSE
│ │ └── difflib/
│ │ └── difflib.go
│ └── stretchr/
│ └── testify/
│ ├── LICENSE
│ ├── assert/
│ │ ├── assertion_compare.go
│ │ ├── assertion_format.go
│ │ ├── assertion_format.go.tmpl
│ │ ├── assertion_forward.go
│ │ ├── assertion_forward.go.tmpl
│ │ ├── assertion_order.go
│ │ ├── assertions.go
│ │ ├── doc.go
│ │ ├── errors.go
│ │ ├── forward_assertions.go
│ │ ├── http_assertions.go
│ │ └── yaml/
│ │ ├── yaml_custom.go
│ │ ├── yaml_default.go
│ │ └── yaml_fail.go
│ └── require/
│ ├── doc.go
│ ├── forward_requirements.go
│ ├── require.go
│ ├── require.go.tmpl
│ ├── require_forward.go
│ ├── require_forward.go.tmpl
│ └── requirements.go
├── golang.org/
│ └── x/
│ ├── net/
│ │ ├── LICENSE
│ │ ├── PATENTS
│ │ ├── bpf/
│ │ │ ├── asm.go
│ │ │ ├── constants.go
│ │ │ ├── doc.go
│ │ │ ├── instructions.go
│ │ │ ├── setter.go
│ │ │ ├── vm.go
│ │ │ └── vm_instructions.go
│ │ ├── internal/
│ │ │ ├── iana/
│ │ │ │ └── const.go
│ │ │ └── socket/
│ │ │ ├── cmsghdr.go
│ │ │ ├── cmsghdr_bsd.go
│ │ │ ├── cmsghdr_linux_32bit.go
│ │ │ ├── cmsghdr_linux_64bit.go
│ │ │ ├── cmsghdr_solaris_64bit.go
│ │ │ ├── cmsghdr_stub.go
│ │ │ ├── cmsghdr_unix.go
│ │ │ ├── cmsghdr_zos_s390x.go
│ │ │ ├── complete_dontwait.go
│ │ │ ├── complete_nodontwait.go
│ │ │ ├── empty.s
│ │ │ ├── error_unix.go
│ │ │ ├── error_windows.go
│ │ │ ├── iovec_32bit.go
│ │ │ ├── iovec_64bit.go
│ │ │ ├── iovec_solaris_64bit.go
│ │ │ ├── iovec_stub.go
│ │ │ ├── mmsghdr_stub.go
│ │ │ ├── mmsghdr_unix.go
│ │ │ ├── msghdr_bsd.go
│ │ │ ├── msghdr_bsdvar.go
│ │ │ ├── msghdr_linux.go
│ │ │ ├── msghdr_linux_32bit.go
│ │ │ ├── msghdr_linux_64bit.go
│ │ │ ├── msghdr_openbsd.go
│ │ │ ├── msghdr_solaris_64bit.go
│ │ │ ├── msghdr_stub.go
│ │ │ ├── msghdr_zos_s390x.go
│ │ │ ├── norace.go
│ │ │ ├── race.go
│ │ │ ├── rawconn.go
│ │ │ ├── rawconn_mmsg.go
│ │ │ ├── rawconn_msg.go
│ │ │ ├── rawconn_nommsg.go
│ │ │ ├── rawconn_nomsg.go
│ │ │ ├── socket.go
│ │ │ ├── sys_bsd.go
│ │ │ ├── sys_const_unix.go
│ │ │ ├── sys_linux.go
│ │ │ ├── sys_linux_386.go
│ │ │ ├── sys_linux_386.s
│ │ │ ├── sys_linux_amd64.go
│ │ │ ├── sys_linux_arm.go
│ │ │ ├── sys_linux_arm64.go
│ │ │ ├── sys_linux_loong64.go
│ │ │ ├── sys_linux_mips.go
│ │ │ ├── sys_linux_mips64.go
│ │ │ ├── sys_linux_mips64le.go
│ │ │ ├── sys_linux_mipsle.go
│ │ │ ├── sys_linux_ppc.go
│ │ │ ├── sys_linux_ppc64.go
│ │ │ ├── sys_linux_ppc64le.go
│ │ │ ├── sys_linux_riscv64.go
│ │ │ ├── sys_linux_s390x.go
│ │ │ ├── sys_linux_s390x.s
│ │ │ ├── sys_netbsd.go
│ │ │ ├── sys_posix.go
│ │ │ ├── sys_stub.go
│ │ │ ├── sys_unix.go
│ │ │ ├── sys_windows.go
│ │ │ ├── sys_zos_s390x.go
│ │ │ ├── sys_zos_s390x.s
│ │ │ ├── zsys_aix_ppc64.go
│ │ │ ├── zsys_darwin_amd64.go
│ │ │ ├── zsys_darwin_arm64.go
│ │ │ ├── zsys_dragonfly_amd64.go
│ │ │ ├── zsys_freebsd_386.go
│ │ │ ├── zsys_freebsd_amd64.go
│ │ │ ├── zsys_freebsd_arm.go
│ │ │ ├── zsys_freebsd_arm64.go
│ │ │ ├── zsys_freebsd_riscv64.go
│ │ │ ├── zsys_linux_386.go
│ │ │ ├── zsys_linux_amd64.go
│ │ │ ├── zsys_linux_arm.go
│ │ │ ├── zsys_linux_arm64.go
│ │ │ ├── zsys_linux_loong64.go
│ │ │ ├── zsys_linux_mips.go
│ │ │ ├── zsys_linux_mips64.go
│ │ │ ├── zsys_linux_mips64le.go
│ │ │ ├── zsys_linux_mipsle.go
│ │ │ ├── zsys_linux_ppc.go
│ │ │ ├── zsys_linux_ppc64.go
│ │ │ ├── zsys_linux_ppc64le.go
│ │ │ ├── zsys_linux_riscv64.go
│ │ │ ├── zsys_linux_s390x.go
│ │ │ ├── zsys_netbsd_386.go
│ │ │ ├── zsys_netbsd_amd64.go
│ │ │ ├── zsys_netbsd_arm.go
│ │ │ ├── zsys_netbsd_arm64.go
│ │ │ ├── zsys_openbsd_386.go
│ │ │ ├── zsys_openbsd_amd64.go
│ │ │ ├── zsys_openbsd_arm.go
│ │ │ ├── zsys_openbsd_arm64.go
│ │ │ ├── zsys_openbsd_mips64.go
│ │ │ ├── zsys_openbsd_ppc64.go
│ │ │ ├── zsys_openbsd_riscv64.go
│ │ │ ├── zsys_solaris_amd64.go
│ │ │ └── zsys_zos_s390x.go
│ │ ├── ipv4/
│ │ │ ├── batch.go
│ │ │ ├── control.go
│ │ │ ├── control_bsd.go
│ │ │ ├── control_pktinfo.go
│ │ │ ├── control_stub.go
│ │ │ ├── control_unix.go
│ │ │ ├── control_windows.go
│ │ │ ├── control_zos.go
│ │ │ ├── dgramopt.go
│ │ │ ├── doc.go
│ │ │ ├── endpoint.go
│ │ │ ├── genericopt.go
│ │ │ ├── header.go
│ │ │ ├── helper.go
│ │ │ ├── iana.go
│ │ │ ├── icmp.go
│ │ │ ├── icmp_linux.go
│ │ │ ├── icmp_stub.go
│ │ │ ├── packet.go
│ │ │ ├── payload.go
│ │ │ ├── payload_cmsg.go
│ │ │ ├── payload_nocmsg.go
│ │ │ ├── sockopt.go
│ │ │ ├── sockopt_posix.go
│ │ │ ├── sockopt_stub.go
│ │ │ ├── sys_aix.go
│ │ │ ├── sys_asmreq.go
│ │ │ ├── sys_asmreq_stub.go
│ │ │ ├── sys_asmreqn.go
│ │ │ ├── sys_asmreqn_stub.go
│ │ │ ├── sys_bpf.go
│ │ │ ├── sys_bpf_stub.go
│ │ │ ├── sys_bsd.go
│ │ │ ├── sys_darwin.go
│ │ │ ├── sys_dragonfly.go
│ │ │ ├── sys_freebsd.go
│ │ │ ├── sys_linux.go
│ │ │ ├── sys_solaris.go
│ │ │ ├── sys_ssmreq.go
│ │ │ ├── sys_ssmreq_stub.go
│ │ │ ├── sys_stub.go
│ │ │ ├── sys_windows.go
│ │ │ ├── sys_zos.go
│ │ │ ├── zsys_aix_ppc64.go
│ │ │ ├── zsys_darwin.go
│ │ │ ├── zsys_dragonfly.go
│ │ │ ├── zsys_freebsd_386.go
│ │ │ ├── zsys_freebsd_amd64.go
│ │ │ ├── zsys_freebsd_arm.go
│ │ │ ├── zsys_freebsd_arm64.go
│ │ │ ├── zsys_freebsd_riscv64.go
│ │ │ ├── zsys_linux_386.go
│ │ │ ├── zsys_linux_amd64.go
│ │ │ ├── zsys_linux_arm.go
│ │ │ ├── zsys_linux_arm64.go
│ │ │ ├── zsys_linux_loong64.go
│ │ │ ├── zsys_linux_mips.go
│ │ │ ├── zsys_linux_mips64.go
│ │ │ ├── zsys_linux_mips64le.go
│ │ │ ├── zsys_linux_mipsle.go
│ │ │ ├── zsys_linux_ppc.go
│ │ │ ├── zsys_linux_ppc64.go
│ │ │ ├── zsys_linux_ppc64le.go
│ │ │ ├── zsys_linux_riscv64.go
│ │ │ ├── zsys_linux_s390x.go
│ │ │ ├── zsys_netbsd.go
│ │ │ ├── zsys_openbsd.go
│ │ │ ├── zsys_solaris.go
│ │ │ └── zsys_zos_s390x.go
│ │ └── ipv6/
│ │ ├── batch.go
│ │ ├── control.go
│ │ ├── control_rfc2292_unix.go
│ │ ├── control_rfc3542_unix.go
│ │ ├── control_stub.go
│ │ ├── control_unix.go
│ │ ├── control_windows.go
│ │ ├── dgramopt.go
│ │ ├── doc.go
│ │ ├── endpoint.go
│ │ ├── genericopt.go
│ │ ├── header.go
│ │ ├── helper.go
│ │ ├── iana.go
│ │ ├── icmp.go
│ │ ├── icmp_bsd.go
│ │ ├── icmp_linux.go
│ │ ├── icmp_solaris.go
│ │ ├── icmp_stub.go
│ │ ├── icmp_windows.go
│ │ ├── icmp_zos.go
│ │ ├── payload.go
│ │ ├── payload_cmsg.go
│ │ ├── payload_nocmsg.go
│ │ ├── sockopt.go
│ │ ├── sockopt_posix.go
│ │ ├── sockopt_stub.go
│ │ ├── sys_aix.go
│ │ ├── sys_asmreq.go
│ │ ├── sys_asmreq_stub.go
│ │ ├── sys_bpf.go
│ │ ├── sys_bpf_stub.go
│ │ ├── sys_bsd.go
│ │ ├── sys_darwin.go
│ │ ├── sys_freebsd.go
│ │ ├── sys_linux.go
│ │ ├── sys_solaris.go
│ │ ├── sys_ssmreq.go
│ │ ├── sys_ssmreq_stub.go
│ │ ├── sys_stub.go
│ │ ├── sys_windows.go
│ │ ├── sys_zos.go
│ │ ├── zsys_aix_ppc64.go
│ │ ├── zsys_darwin.go
│ │ ├── zsys_dragonfly.go
│ │ ├── zsys_freebsd_386.go
│ │ ├── zsys_freebsd_amd64.go
│ │ ├── zsys_freebsd_arm.go
│ │ ├── zsys_freebsd_arm64.go
│ │ ├── zsys_freebsd_riscv64.go
│ │ ├── zsys_linux_386.go
│ │ ├── zsys_linux_amd64.go
│ │ ├── zsys_linux_arm.go
│ │ ├── zsys_linux_arm64.go
│ │ ├── zsys_linux_loong64.go
│ │ ├── zsys_linux_mips.go
│ │ ├── zsys_linux_mips64.go
│ │ ├── zsys_linux_mips64le.go
│ │ ├── zsys_linux_mipsle.go
│ │ ├── zsys_linux_ppc.go
│ │ ├── zsys_linux_ppc64.go
│ │ ├── zsys_linux_ppc64le.go
│ │ ├── zsys_linux_riscv64.go
│ │ ├── zsys_linux_s390x.go
│ │ ├── zsys_netbsd.go
│ │ ├── zsys_openbsd.go
│ │ ├── zsys_solaris.go
│ │ └── zsys_zos_s390x.go
│ └── sys/
│ ├── LICENSE
│ ├── PATENTS
│ ├── unix/
│ │ ├── .gitignore
│ │ ├── README.md
│ │ ├── affinity_linux.go
│ │ ├── aliases.go
│ │ ├── asm_aix_ppc64.s
│ │ ├── asm_bsd_386.s
│ │ ├── asm_bsd_amd64.s
│ │ ├── asm_bsd_arm.s
│ │ ├── asm_bsd_arm64.s
│ │ ├── asm_bsd_ppc64.s
│ │ ├── asm_bsd_riscv64.s
│ │ ├── asm_linux_386.s
│ │ ├── asm_linux_amd64.s
│ │ ├── asm_linux_arm.s
│ │ ├── asm_linux_arm64.s
│ │ ├── asm_linux_loong64.s
│ │ ├── asm_linux_mips64x.s
│ │ ├── asm_linux_mipsx.s
│ │ ├── asm_linux_ppc64x.s
│ │ ├── asm_linux_riscv64.s
│ │ ├── asm_linux_s390x.s
│ │ ├── asm_openbsd_mips64.s
│ │ ├── asm_solaris_amd64.s
│ │ ├── asm_zos_s390x.s
│ │ ├── auxv.go
│ │ ├── auxv_unsupported.go
│ │ ├── bluetooth_linux.go
│ │ ├── bpxsvc_zos.go
│ │ ├── bpxsvc_zos.s
│ │ ├── cap_freebsd.go
│ │ ├── constants.go
│ │ ├── dev_aix_ppc.go
│ │ ├── dev_aix_ppc64.go
│ │ ├── dev_darwin.go
│ │ ├── dev_dragonfly.go
│ │ ├── dev_freebsd.go
│ │ ├── dev_linux.go
│ │ ├── dev_netbsd.go
│ │ ├── dev_openbsd.go
│ │ ├── dev_zos.go
│ │ ├── dirent.go
│ │ ├── endian_big.go
│ │ ├── endian_little.go
│ │ ├── env_unix.go
│ │ ├── fcntl.go
│ │ ├── fcntl_darwin.go
│ │ ├── fcntl_linux_32bit.go
│ │ ├── fdset.go
│ │ ├── gccgo.go
│ │ ├── gccgo_c.c
│ │ ├── gccgo_linux_amd64.go
│ │ ├── ifreq_linux.go
│ │ ├── ioctl_linux.go
│ │ ├── ioctl_signed.go
│ │ ├── ioctl_unsigned.go
│ │ ├── ioctl_zos.go
│ │ ├── mkall.sh
│ │ ├── mkerrors.sh
│ │ ├── mmap_nomremap.go
│ │ ├── mremap.go
│ │ ├── pagesize_unix.go
│ │ ├── pledge_openbsd.go
│ │ ├── ptrace_darwin.go
│ │ ├── ptrace_ios.go
│ │ ├── race.go
│ │ ├── race0.go
│ │ ├── readdirent_getdents.go
│ │ ├── readdirent_getdirentries.go
│ │ ├── sockcmsg_dragonfly.go
│ │ ├── sockcmsg_linux.go
│ │ ├── sockcmsg_unix.go
│ │ ├── sockcmsg_unix_other.go
│ │ ├── sockcmsg_zos.go
│ │ ├── symaddr_zos_s390x.s
│ │ ├── syscall.go
│ │ ├── syscall_aix.go
│ │ ├── syscall_aix_ppc.go
│ │ ├── syscall_aix_ppc64.go
│ │ ├── syscall_bsd.go
│ │ ├── syscall_darwin.go
│ │ ├── syscall_darwin_amd64.go
│ │ ├── syscall_darwin_arm64.go
│ │ ├── syscall_darwin_libSystem.go
│ │ ├── syscall_dragonfly.go
│ │ ├── syscall_dragonfly_amd64.go
│ │ ├── syscall_freebsd.go
│ │ ├── syscall_freebsd_386.go
│ │ ├── syscall_freebsd_amd64.go
│ │ ├── syscall_freebsd_arm.go
│ │ ├── syscall_freebsd_arm64.go
│ │ ├── syscall_freebsd_riscv64.go
│ │ ├── syscall_hurd.go
│ │ ├── syscall_hurd_386.go
│ │ ├── syscall_illumos.go
│ │ ├── syscall_linux.go
│ │ ├── syscall_linux_386.go
│ │ ├── syscall_linux_alarm.go
│ │ ├── syscall_linux_amd64.go
│ │ ├── syscall_linux_amd64_gc.go
│ │ ├── syscall_linux_arm.go
│ │ ├── syscall_linux_arm64.go
│ │ ├── syscall_linux_gc.go
│ │ ├── syscall_linux_gc_386.go
│ │ ├── syscall_linux_gc_arm.go
│ │ ├── syscall_linux_gccgo_386.go
│ │ ├── syscall_linux_gccgo_arm.go
│ │ ├── syscall_linux_loong64.go
│ │ ├── syscall_linux_mips64x.go
│ │ ├── syscall_linux_mipsx.go
│ │ ├── syscall_linux_ppc.go
│ │ ├── syscall_linux_ppc64x.go
│ │ ├── syscall_linux_riscv64.go
│ │ ├── syscall_linux_s390x.go
│ │ ├── syscall_linux_sparc64.go
│ │ ├── syscall_netbsd.go
│ │ ├── syscall_netbsd_386.go
│ │ ├── syscall_netbsd_amd64.go
│ │ ├── syscall_netbsd_arm.go
│ │ ├── syscall_netbsd_arm64.go
│ │ ├── syscall_openbsd.go
│ │ ├── syscall_openbsd_386.go
│ │ ├── syscall_openbsd_amd64.go
│ │ ├── syscall_openbsd_arm.go
│ │ ├── syscall_openbsd_arm64.go
│ │ ├── syscall_openbsd_libc.go
│ │ ├── syscall_openbsd_mips64.go
│ │ ├── syscall_openbsd_ppc64.go
│ │ ├── syscall_openbsd_riscv64.go
│ │ ├── syscall_solaris.go
│ │ ├── syscall_solaris_amd64.go
│ │ ├── syscall_unix.go
│ │ ├── syscall_unix_gc.go
│ │ ├── syscall_unix_gc_ppc64x.go
│ │ ├── syscall_zos_s390x.go
│ │ ├── sysvshm_linux.go
│ │ ├── sysvshm_unix.go
│ │ ├── sysvshm_unix_other.go
│ │ ├── timestruct.go
│ │ ├── unveil_openbsd.go
│ │ ├── vgetrandom_linux.go
│ │ ├── vgetrandom_unsupported.go
│ │ ├── xattr_bsd.go
│ │ ├── zerrors_aix_ppc.go
│ │ ├── zerrors_aix_ppc64.go
│ │ ├── zerrors_darwin_amd64.go
│ │ ├── zerrors_darwin_arm64.go
│ │ ├── zerrors_dragonfly_amd64.go
│ │ ├── zerrors_freebsd_386.go
│ │ ├── zerrors_freebsd_amd64.go
│ │ ├── zerrors_freebsd_arm.go
│ │ ├── zerrors_freebsd_arm64.go
│ │ ├── zerrors_freebsd_riscv64.go
│ │ ├── zerrors_linux.go
│ │ ├── zerrors_linux_386.go
│ │ ├── zerrors_linux_amd64.go
│ │ ├── zerrors_linux_arm.go
│ │ ├── zerrors_linux_arm64.go
│ │ ├── zerrors_linux_loong64.go
│ │ ├── zerrors_linux_mips.go
│ │ ├── zerrors_linux_mips64.go
│ │ ├── zerrors_linux_mips64le.go
│ │ ├── zerrors_linux_mipsle.go
│ │ ├── zerrors_linux_ppc.go
│ │ ├── zerrors_linux_ppc64.go
│ │ ├── zerrors_linux_ppc64le.go
│ │ ├── zerrors_linux_riscv64.go
│ │ ├── zerrors_linux_s390x.go
│ │ ├── zerrors_linux_sparc64.go
│ │ ├── zerrors_netbsd_386.go
│ │ ├── zerrors_netbsd_amd64.go
│ │ ├── zerrors_netbsd_arm.go
│ │ ├── zerrors_netbsd_arm64.go
│ │ ├── zerrors_openbsd_386.go
│ │ ├── zerrors_openbsd_amd64.go
│ │ ├── zerrors_openbsd_arm.go
│ │ ├── zerrors_openbsd_arm64.go
│ │ ├── zerrors_openbsd_mips64.go
│ │ ├── zerrors_openbsd_ppc64.go
│ │ ├── zerrors_openbsd_riscv64.go
│ │ ├── zerrors_solaris_amd64.go
│ │ ├── zerrors_zos_s390x.go
│ │ ├── zptrace_armnn_linux.go
│ │ ├── zptrace_linux_arm64.go
│ │ ├── zptrace_mipsnn_linux.go
│ │ ├── zptrace_mipsnnle_linux.go
│ │ ├── zptrace_x86_linux.go
│ │ ├── zsymaddr_zos_s390x.s
│ │ ├── zsyscall_aix_ppc.go
│ │ ├── zsyscall_aix_ppc64.go
│ │ ├── zsyscall_aix_ppc64_gc.go
│ │ ├── zsyscall_aix_ppc64_gccgo.go
│ │ ├── zsyscall_darwin_amd64.go
│ │ ├── zsyscall_darwin_amd64.s
│ │ ├── zsyscall_darwin_arm64.go
│ │ ├── zsyscall_darwin_arm64.s
│ │ ├── zsyscall_dragonfly_amd64.go
│ │ ├── zsyscall_freebsd_386.go
│ │ ├── zsyscall_freebsd_amd64.go
│ │ ├── zsyscall_freebsd_arm.go
│ │ ├── zsyscall_freebsd_arm64.go
│ │ ├── zsyscall_freebsd_riscv64.go
│ │ ├── zsyscall_illumos_amd64.go
│ │ ├── zsyscall_linux.go
│ │ ├── zsyscall_linux_386.go
│ │ ├── zsyscall_linux_amd64.go
│ │ ├── zsyscall_linux_arm.go
│ │ ├── zsyscall_linux_arm64.go
│ │ ├── zsyscall_linux_loong64.go
│ │ ├── zsyscall_linux_mips.go
│ │ ├── zsyscall_linux_mips64.go
│ │ ├── zsyscall_linux_mips64le.go
│ │ ├── zsyscall_linux_mipsle.go
│ │ ├── zsyscall_linux_ppc.go
│ │ ├── zsyscall_linux_ppc64.go
│ │ ├── zsyscall_linux_ppc64le.go
│ │ ├── zsyscall_linux_riscv64.go
│ │ ├── zsyscall_linux_s390x.go
│ │ ├── zsyscall_linux_sparc64.go
│ │ ├── zsyscall_netbsd_386.go
│ │ ├── zsyscall_netbsd_amd64.go
│ │ ├── zsyscall_netbsd_arm.go
│ │ ├── zsyscall_netbsd_arm64.go
│ │ ├── zsyscall_openbsd_386.go
│ │ ├── zsyscall_openbsd_386.s
│ │ ├── zsyscall_openbsd_amd64.go
│ │ ├── zsyscall_openbsd_amd64.s
│ │ ├── zsyscall_openbsd_arm.go
│ │ ├── zsyscall_openbsd_arm.s
│ │ ├── zsyscall_openbsd_arm64.go
│ │ ├── zsyscall_openbsd_arm64.s
│ │ ├── zsyscall_openbsd_mips64.go
│ │ ├── zsyscall_openbsd_mips64.s
│ │ ├── zsyscall_openbsd_ppc64.go
│ │ ├── zsyscall_openbsd_ppc64.s
│ │ ├── zsyscall_openbsd_riscv64.go
│ │ ├── zsyscall_openbsd_riscv64.s
│ │ ├── zsyscall_solaris_amd64.go
│ │ ├── zsyscall_zos_s390x.go
│ │ ├── zsysctl_openbsd_386.go
│ │ ├── zsysctl_openbsd_amd64.go
│ │ ├── zsysctl_openbsd_arm.go
│ │ ├── zsysctl_openbsd_arm64.go
│ │ ├── zsysctl_openbsd_mips64.go
│ │ ├── zsysctl_openbsd_ppc64.go
│ │ ├── zsysctl_openbsd_riscv64.go
│ │ ├── zsysnum_darwin_amd64.go
│ │ ├── zsysnum_darwin_arm64.go
│ │ ├── zsysnum_dragonfly_amd64.go
│ │ ├── zsysnum_freebsd_386.go
│ │ ├── zsysnum_freebsd_amd64.go
│ │ ├── zsysnum_freebsd_arm.go
│ │ ├── zsysnum_freebsd_arm64.go
│ │ ├── zsysnum_freebsd_riscv64.go
│ │ ├── zsysnum_linux_386.go
│ │ ├── zsysnum_linux_amd64.go
│ │ ├── zsysnum_linux_arm.go
│ │ ├── zsysnum_linux_arm64.go
│ │ ├── zsysnum_linux_loong64.go
│ │ ├── zsysnum_linux_mips.go
│ │ ├── zsysnum_linux_mips64.go
│ │ ├── zsysnum_linux_mips64le.go
│ │ ├── zsysnum_linux_mipsle.go
│ │ ├── zsysnum_linux_ppc.go
│ │ ├── zsysnum_linux_ppc64.go
│ │ ├── zsysnum_linux_ppc64le.go
│ │ ├── zsysnum_linux_riscv64.go
│ │ ├── zsysnum_linux_s390x.go
│ │ ├── zsysnum_linux_sparc64.go
│ │ ├── zsysnum_netbsd_386.go
│ │ ├── zsysnum_netbsd_amd64.go
│ │ ├── zsysnum_netbsd_arm.go
│ │ ├── zsysnum_netbsd_arm64.go
│ │ ├── zsysnum_openbsd_386.go
│ │ ├── zsysnum_openbsd_amd64.go
│ │ ├── zsysnum_openbsd_arm.go
│ │ ├── zsysnum_openbsd_arm64.go
│ │ ├── zsysnum_openbsd_mips64.go
│ │ ├── zsysnum_openbsd_ppc64.go
│ │ ├── zsysnum_openbsd_riscv64.go
│ │ ├── zsysnum_zos_s390x.go
│ │ ├── ztypes_aix_ppc.go
│ │ ├── ztypes_aix_ppc64.go
│ │ ├── ztypes_darwin_amd64.go
│ │ ├── ztypes_darwin_arm64.go
│ │ ├── ztypes_dragonfly_amd64.go
│ │ ├── ztypes_freebsd_386.go
│ │ ├── ztypes_freebsd_amd64.go
│ │ ├── ztypes_freebsd_arm.go
│ │ ├── ztypes_freebsd_arm64.go
│ │ ├── ztypes_freebsd_riscv64.go
│ │ ├── ztypes_linux.go
│ │ ├── ztypes_linux_386.go
│ │ ├── ztypes_linux_amd64.go
│ │ ├── ztypes_linux_arm.go
│ │ ├── ztypes_linux_arm64.go
│ │ ├── ztypes_linux_loong64.go
│ │ ├── ztypes_linux_mips.go
│ │ ├── ztypes_linux_mips64.go
│ │ ├── ztypes_linux_mips64le.go
│ │ ├── ztypes_linux_mipsle.go
│ │ ├── ztypes_linux_ppc.go
│ │ ├── ztypes_linux_ppc64.go
│ │ ├── ztypes_linux_ppc64le.go
│ │ ├── ztypes_linux_riscv64.go
│ │ ├── ztypes_linux_s390x.go
│ │ ├── ztypes_linux_sparc64.go
│ │ ├── ztypes_netbsd_386.go
│ │ ├── ztypes_netbsd_amd64.go
│ │ ├── ztypes_netbsd_arm.go
│ │ ├── ztypes_netbsd_arm64.go
│ │ ├── ztypes_openbsd_386.go
│ │ ├── ztypes_openbsd_amd64.go
│ │ ├── ztypes_openbsd_arm.go
│ │ ├── ztypes_openbsd_arm64.go
│ │ ├── ztypes_openbsd_mips64.go
│ │ ├── ztypes_openbsd_ppc64.go
│ │ ├── ztypes_openbsd_riscv64.go
│ │ ├── ztypes_solaris_amd64.go
│ │ └── ztypes_zos_s390x.go
│ └── windows/
│ ├── aliases.go
│ ├── dll_windows.go
│ ├── env_windows.go
│ ├── eventlog.go
│ ├── exec_windows.go
│ ├── memory_windows.go
│ ├── mkerrors.bash
│ ├── mkknownfolderids.bash
│ ├── mksyscall.go
│ ├── race.go
│ ├── race0.go
│ ├── security_windows.go
│ ├── service.go
│ ├── setupapi_windows.go
│ ├── str.go
│ ├── syscall.go
│ ├── syscall_windows.go
│ ├── types_windows.go
│ ├── types_windows_386.go
│ ├── types_windows_amd64.go
│ ├── types_windows_arm.go
│ ├── types_windows_arm64.go
│ ├── zerrors_windows.go
│ ├── zknownfolderids_windows.go
│ └── zsyscall_windows.go
├── gopkg.in/
│ └── yaml.v3/
│ ├── LICENSE
│ ├── NOTICE
│ ├── README.md
│ ├── apic.go
│ ├── decode.go
│ ├── emitterc.go
│ ├── encode.go
│ ├── parserc.go
│ ├── readerc.go
│ ├── resolve.go
│ ├── scannerc.go
│ ├── sorter.go
│ ├── writerc.go
│ ├── yaml.go
│ ├── yamlh.go
│ └── yamlprivateh.go
└── modules.txt
Showing preview only (8,494K chars total). Download the full file or copy to clipboard to get everything.
SYMBOL INDEX (100675 symbols across 623 files)
FILE: circular/circular.go
type Number (line 15) | type Number struct
method Val (line 39) | func (a Number) Val() uint32 {
method Equals (line 44) | func (a Number) Equals(b Number) bool {
method Distance (line 49) | func (a Number) Distance(b Number) uint32 {
method Lt (line 70) | func (a Number) Lt(b Number) bool {
method Lte (line 93) | func (a Number) Lte(b Number) bool {
method Gt (line 102) | func (a Number) Gt(b Number) bool {
method Gte (line 125) | func (a Number) Gte(b Number) bool {
method Inc (line 134) | func (a Number) Inc() Number {
method Add (line 147) | func (a Number) Add(b uint32) Number {
method Dec (line 161) | func (a Number) Dec() Number {
method Sub (line 174) | func (a Number) Sub(b uint32) Number {
function New (line 22) | func New(x, max uint32) Number {
FILE: circular/circular_test.go
constant max (line 10) | max uint32 = 0b11111111_11111111_11111111_11111111
function ExampleNumber_Inc (line 12) | func ExampleNumber_Inc() {
function TestIncNoWrap (line 20) | func TestIncNoWrap(t *testing.T) {
function TestIncWrap (line 30) | func TestIncWrap(t *testing.T) {
function TestDecNoWrap (line 44) | func TestDecNoWrap(t *testing.T) {
function TestDecWrap (line 54) | func TestDecWrap(t *testing.T) {
function TestDistanceNoWrap (line 68) | func TestDistanceNoWrap(t *testing.T) {
function TestDistanceWrap (line 81) | func TestDistanceWrap(t *testing.T) {
function TestLt (line 94) | func TestLt(t *testing.T) {
function TestGt (line 116) | func TestGt(t *testing.T) {
function TestAdd (line 138) | func TestAdd(t *testing.T) {
function TestSub (line 150) | func TestSub(t *testing.T) {
FILE: config.go
constant UDP_HEADER_SIZE (line 11) | UDP_HEADER_SIZE = 28
constant SRT_HEADER_SIZE (line 12) | SRT_HEADER_SIZE = 16
constant MIN_MSS_SIZE (line 13) | MIN_MSS_SIZE = 76
constant MAX_MSS_SIZE (line 14) | MAX_MSS_SIZE = 1500
constant MIN_PAYLOAD_SIZE (line 15) | MIN_PAYLOAD_SIZE = MIN_MSS_SIZE - UDP_HEADER_SIZE - SRT_HEADER_SIZE
constant MAX_PAYLOAD_SIZE (line 16) | MAX_PAYLOAD_SIZE = MAX_MSS_SIZE - UDP_HEADER_SIZE - SRT_HEADER_SIZE
constant MIN_PASSPHRASE_SIZE (line 17) | MIN_PASSPHRASE_SIZE = 10
constant MAX_PASSPHRASE_SIZE (line 18) | MAX_PASSPHRASE_SIZE = 80
constant MAX_STREAMID_SIZE (line 19) | MAX_STREAMID_SIZE = 512
constant SRT_VERSION (line 20) | SRT_VERSION = 0x010401
type Config (line 24) | type Config struct
method UnmarshalURL (line 226) | func (c *Config) UnmarshalURL(srturl string) (string, error) {
method UnmarshalQuery (line 243) | func (c *Config) UnmarshalQuery(query string) error {
method MarshalURL (line 480) | func (c *Config) MarshalURL(address string) string {
method MarshalQuery (line 485) | func (c *Config) MarshalQuery() string {
method Validate (line 635) | func (c *Config) Validate() error {
function DefaultConfig (line 219) | func DefaultConfig() Config {
FILE: config_test.go
function TestDefaultConfig (line 10) | func TestDefaultConfig(t *testing.T) {
function TestMarshalUnmarshal (line 19) | func TestMarshalUnmarshal(t *testing.T) {
FILE: congestion/congestion.go
type Sender (line 10) | type Sender interface
type Receiver (line 36) | type Receiver interface
type SendStats (line 59) | type SendStats struct
type ReceiveStats (line 94) | type ReceiveStats struct
FILE: congestion/live/fake.go
type fakeLiveReceive (line 12) | type fakeLiveReceive struct
method Stats (line 78) | func (r *fakeLiveReceive) Stats() congestion.ReceiveStats { return con...
method PacketRate (line 79) | func (r *fakeLiveReceive) PacketRate() (pps, bps, capacity float64) {
method Flush (line 104) | func (r *fakeLiveReceive) Flush() {}
method Push (line 106) | func (r *fakeLiveReceive) Push(pkt packet.Packet) {
method periodicACK (line 141) | func (r *fakeLiveReceive) periodicACK(now uint64) (ok bool, sequenceNu...
method Tick (line 165) | func (r *fakeLiveReceive) Tick(now uint64) {
method SetNAKInterval (line 177) | func (r *fakeLiveReceive) SetNAKInterval(nakInterval uint64) {
function NewFakeLiveReceive (line 44) | func NewFakeLiveReceive(config ReceiveConfig) congestion.Receiver {
FILE: congestion/live/receive.go
type ReceiveConfig (line 16) | type ReceiveConfig struct
type receiver (line 26) | type receiver struct
method Stats (line 104) | func (r *receiver) Stats() congestion.ReceiveStats {
method PacketRate (line 116) | func (r *receiver) PacketRate() (pps, bps, capacity float64) {
method Flush (line 127) | func (r *receiver) Flush() {
method Push (line 134) | func (r *receiver) Push(pkt packet.Packet) {
method periodicACK (line 257) | func (r *receiver) periodicACK(now uint64) (ok bool, sequenceNumber ci...
method periodicNAK (line 323) | func (r *receiver) periodicNAK(now uint64) []circular.Number {
method Tick (line 363) | func (r *receiver) Tick(now uint64) {
method SetNAKInterval (line 417) | func (r *receiver) SetNAKInterval(nakInterval uint64) {
method String (line 424) | func (r *receiver) String(t uint64) string {
function NewReceiver (line 69) | func NewReceiver(config ReceiveConfig) congestion.Receiver {
FILE: congestion/live/receive_test.go
function mockLiveRecv (line 12) | func mockLiveRecv(onSendACK func(seq circular.Number, light bool), onSen...
function TestRecvSequence (line 25) | func TestRecvSequence(t *testing.T) {
function TestRecvTSBPD (line 73) | func TestRecvTSBPD(t *testing.T) {
function TestRecvNAK (line 104) | func TestRecvNAK(t *testing.T) {
function TestRecvPeriodicNAK (line 156) | func TestRecvPeriodicNAK(t *testing.T) {
function TestRecvACK (line 214) | func TestRecvACK(t *testing.T) {
function TestRecvDropTooLate (line 325) | func TestRecvDropTooLate(t *testing.T) {
function TestRecvDropAlreadyACK (line 362) | func TestRecvDropAlreadyACK(t *testing.T) {
function TestRecvDropAlreadyRecvNoACK (line 407) | func TestRecvDropAlreadyRecvNoACK(t *testing.T) {
function TestRecvFlush (line 460) | func TestRecvFlush(t *testing.T) {
function TestRecvPeriodicACKLite (line 484) | func TestRecvPeriodicACKLite(t *testing.T) {
function TestSkipTooLate (line 511) | func TestSkipTooLate(t *testing.T) {
function TestIssue67 (line 553) | func TestIssue67(t *testing.T) {
FILE: congestion/live/send.go
type SendConfig (line 14) | type SendConfig struct
type sender (line 25) | type sender struct
method Stats (line 89) | func (s *sender) Stats() congestion.SendStats {
method Flush (line 112) | func (s *sender) Flush() {
method Push (line 120) | func (s *sender) Push(p packet.Packet) {
method Tick (line 164) | func (s *sender) Tick(now uint64) {
method ACK (line 250) | func (s *sender) ACK(sequenceNumber circular.Number) {
method NAK (line 281) | func (s *sender) NAK(sequenceNumbers []circular.Number) {
method SetDropThreshold (line 315) | func (s *sender) SetDropThreshold(threshold uint64) {
function NewSender (line 61) | func NewSender(config SendConfig) congestion.Sender {
FILE: congestion/live/send_test.go
function mockLiveSend (line 12) | func mockLiveSend(onDeliver func(p packet.Packet)) *sender {
function TestSendSequence (line 22) | func TestSendSequence(t *testing.T) {
function TestSendLossListACK (line 46) | func TestSendLossListACK(t *testing.T) {
function TestSendRetransmit (line 68) | func TestSendRetransmit(t *testing.T) {
function TestSendDrop (line 106) | func TestSendDrop(t *testing.T) {
function TestSendFlush (line 127) | func TestSendFlush(t *testing.T) {
FILE: conn_request.go
type ConnRequest (line 14) | type ConnRequest interface
type connRequest (line 58) | type connRequest struct
method RemoteAddr (line 306) | func (req *connRequest) RemoteAddr() net.Addr {
method Version (line 311) | func (req *connRequest) Version() uint32 {
method StreamId (line 315) | func (req *connRequest) StreamId() string {
method SocketId (line 319) | func (req *connRequest) SocketId() uint32 {
method PeerSocketId (line 323) | func (req *connRequest) PeerSocketId() uint32 {
method IsEncrypted (line 327) | func (req *connRequest) IsEncrypted() bool {
method SetPassphrase (line 331) | func (req *connRequest) SetPassphrase(passphrase string) error {
method SetRejectionReason (line 347) | func (req *connRequest) SetRejectionReason(reason RejectionReason) {
method Reject (line 351) | func (req *connRequest) Reject(reason RejectionReason) {
method generateSocketId (line 378) | func (req *connRequest) generateSocketId() (uint32, error) {
method Accept (line 394) | func (req *connRequest) Accept() (Conn, error) {
function newConnRequest (line 73) | func newConnRequest(ln *listener, p packet.Packet) *connRequest {
FILE: connection.go
type Conn (line 22) | type Conn interface
type rtt (line 72) | type rtt struct
method Recalculate (line 79) | func (r *rtt) Recalculate(rtt time.Duration) {
method RTT (line 90) | func (r *rtt) RTT() float64 {
method RTTVar (line 97) | func (r *rtt) RTTVar() float64 {
method NAKInterval (line 104) | func (r *rtt) NAKInterval() float64 {
type connStats (line 117) | type connStats struct
type srtConn (line 140) | type srtConn struct
method LocalAddr (line 362) | func (c *srtConn) LocalAddr() net.Addr {
method RemoteAddr (line 371) | func (c *srtConn) RemoteAddr() net.Addr {
method SocketId (line 380) | func (c *srtConn) SocketId() uint32 {
method PeerSocketId (line 384) | func (c *srtConn) PeerSocketId() uint32 {
method StreamId (line 388) | func (c *srtConn) StreamId() string {
method Version (line 392) | func (c *srtConn) Version() uint32 {
method ticker (line 398) | func (c *srtConn) ticker(ctx context.Context) {
method ReadPacket (line 418) | func (c *srtConn) ReadPacket() (packet.Packet, error) {
method Read (line 442) | func (c *srtConn) Read(b []byte) (int, error) {
method WritePacket (line 464) | func (c *srtConn) WritePacket(p packet.Packet) error {
method Write (line 478) | func (c *srtConn) Write(b []byte) (int, error) {
method push (line 515) | func (c *srtConn) push(p packet.Packet) {
method getTimestamp (line 526) | func (c *srtConn) getTimestamp() uint64 {
method getTimestampForPacket (line 532) | func (c *srtConn) getTimestampForPacket() uint32 {
method pop (line 538) | func (c *srtConn) pop(p packet.Packet) {
method networkQueueReader (line 587) | func (c *srtConn) networkQueueReader(ctx context.Context) {
method writeQueueReader (line 604) | func (c *srtConn) writeQueueReader(ctx context.Context) {
method deliver (line 621) | func (c *srtConn) deliver(p packet.Packet) {
method handlePacket (line 634) | func (c *srtConn) handlePacket(p packet.Packet) {
method handleKeepAlive (line 745) | func (c *srtConn) handleKeepAlive(p packet.Packet) {
method handleShutdown (line 761) | func (c *srtConn) handleShutdown(p packet.Packet) {
method handleACK (line 773) | func (c *srtConn) handleACK(p packet.Packet) {
method handleNAK (line 808) | func (c *srtConn) handleNAK(p packet.Packet) {
method handleACKACK (line 832) | func (c *srtConn) handleACKACK(p packet.Packet) {
method recalculateRTT (line 865) | func (c *srtConn) recalculateRTT(rtt time.Duration) {
method handleHSRequest (line 874) | func (c *srtConn) handleHSRequest(p packet.Packet) {
method handleHSResponse (line 961) | func (c *srtConn) handleHSResponse(p packet.Packet) {
method handleKMRequest (line 1041) | func (c *srtConn) handleKMRequest(p packet.Packet) {
method handleKMResponse (line 1117) | func (c *srtConn) handleKMResponse(p packet.Packet) {
method sendShutdown (line 1168) | func (c *srtConn) sendShutdown() {
method sendNAK (line 1191) | func (c *srtConn) sendNAK(list []circular.Number) {
method sendACK (line 1216) | func (c *srtConn) sendACK(seq circular.Number, lite bool) {
method sendACKACK (line 1267) | func (c *srtConn) sendACKACK(ackSequence uint32) {
method sendHSRequests (line 1286) | func (c *srtConn) sendHSRequests(ctx context.Context) {
method sendHSRequest (line 1298) | func (c *srtConn) sendHSRequest() {
method sendKMRequests (line 1331) | func (c *srtConn) sendKMRequests(ctx context.Context) {
method sendKMRequest (line 1344) | func (c *srtConn) sendKMRequest(key packet.PacketEncryption) {
method Close (line 1375) | func (c *srtConn) Close() error {
method close (line 1382) | func (c *srtConn) close() {
method log (line 1410) | func (c *srtConn) log(topic string, message func() string) {
method SetDeadline (line 1414) | func (c *srtConn) SetDeadline(t time.Time) error { return nil }
method SetReadDeadline (line 1415) | func (c *srtConn) SetReadDeadline(t time.Time) error { return nil }
method SetWriteDeadline (line 1416) | func (c *srtConn) SetWriteDeadline(t time.Time) error { return nil }
method Stats (line 1418) | func (c *srtConn) Stats(s *Statistics) {
type srtConnConfig (line 221) | type srtConnConfig struct
function newSRTConn (line 241) | func newSRTConn(config srtConnConfig) *srtConn {
FILE: connection_test.go
function TestEncryption (line 14) | func TestEncryption(t *testing.T) {
function TestEncryptionRetransmit (line 151) | func TestEncryptionRetransmit(t *testing.T) {
function TestEncryptionKeySwap (line 308) | func TestEncryptionKeySwap(t *testing.T) {
function TestStats (line 441) | func TestStats(t *testing.T) {
FILE: contrib/client/main.go
type stats (line 20) | type stats struct
method init (line 32) | func (s *stats) init(period time.Duration) {
method tick (line 44) | func (s *stats) tick() {
method update (line 65) | func (s *stats) update(n uint64) {
function main (line 73) | func main() {
function openReader (line 185) | func openReader(addr string, logger srt.Logger) (io.ReadCloser, error) {
function openWriter (line 282) | func openWriter(addr string, logger srt.Logger) (io.WriteCloser, error) {
FILE: contrib/client/reader.go
type Reader (line 9) | type Reader interface
type debugReader (line 13) | type debugReader struct
method Read (line 42) | func (r *debugReader) Read(p []byte) (int, error) {
method Close (line 63) | func (r *debugReader) Close() error {
method generator (line 69) | func (r *debugReader) generator(ctx context.Context) {
type DebugReaderOptions (line 19) | type DebugReaderOptions struct
function NewDebugReader (line 23) | func NewDebugReader(options DebugReaderOptions) (Reader, error) {
FILE: contrib/client/writer.go
type Writer (line 13) | type Writer interface
type nonblockingWriter (line 18) | type nonblockingWriter struct
method Write (line 52) | func (u *nonblockingWriter) Write(p []byte) (int, error) {
method Close (line 63) | func (u *nonblockingWriter) Close() error {
method writer (line 73) | func (u *nonblockingWriter) writer() {
function NewNonblockingWriter (line 35) | func NewNonblockingWriter(writer io.WriteCloser, size int) Writer {
FILE: contrib/server/main.go
type server (line 18) | type server struct
method ListenAndServe (line 35) | func (s *server) ListenAndServe() error {
method Shutdown (line 43) | func (s *server) Shutdown() {
method log (line 140) | func (s *server) log(who, action, path, message string, client net.Add...
method handleConnect (line 144) | func (s *server) handleConnect(req srt.ConnRequest) srt.ConnType {
method handlePublish (line 218) | func (s *server) handlePublish(conn srt.Conn) {
method handleSubscribe (line 276) | func (s *server) handleSubscribe(conn srt.Conn) {
function main (line 47) | func main() {
FILE: crypto/crypto.go
type Crypto (line 20) | type Crypto interface
type crypto (line 37) | type crypto struct
method GenerateSEK (line 82) | func (c *crypto) GenerateSEK(key packet.PacketEncryption) error {
method generateSEK (line 102) | func (c *crypto) generateSEK(keyLength int) ([]byte, error) {
method UnmarshalKM (line 119) | func (c *crypto) UnmarshalKM(km *packet.CIFKeyMaterialExtension, passp...
method MarshalKM (line 166) | func (c *crypto) MarshalKM(km *packet.CIFKeyMaterialExtension, passphr...
method EncryptOrDecryptPayload (line 224) | func (c *crypto) EncryptOrDecryptPayload(data []byte, key packet.Packe...
method calculateKEK (line 277) | func (c *crypto) calculateKEK(passphrase string, salt []byte, keyLengt...
method prng (line 283) | func (c *crypto) prng(p []byte) error {
function New (line 47) | func New(keyLength int) (Crypto, error) {
FILE: crypto/crypto_test.go
function mustDecodeString (line 13) | func mustDecodeString(s string) []byte {
function TestInvalidKeylength (line 22) | func TestInvalidKeylength(t *testing.T) {
function TestInvalidKM (line 27) | func TestInvalidKM(t *testing.T) {
function TestUnmarshal (line 50) | func TestUnmarshal(t *testing.T) {
function TestMarshal (line 114) | func TestMarshal(t *testing.T) {
function TestDecode (line 199) | func TestDecode(t *testing.T) {
function TestEncode (line 268) | func TestEncode(t *testing.T) {
FILE: dial.go
type dialer (line 25) | type dialer struct
method checkConnection (line 207) | func (dl *dialer) checkConnection() error {
method reader (line 219) | func (dl *dialer) reader(ctx context.Context) {
method send (line 264) | func (dl *dialer) send(p packet.Packet) {
method handleHandshake (line 289) | func (dl *dialer) handleHandshake(p packet.Packet) {
method sendInduction (line 548) | func (dl *dialer) sendInduction() {
method sendShutdown (line 583) | func (dl *dialer) sendShutdown(peerSocketId uint32) {
method LocalAddr (line 604) | func (dl *dialer) LocalAddr() net.Addr {
method RemoteAddr (line 615) | func (dl *dialer) RemoteAddr() net.Addr {
method SocketId (line 626) | func (dl *dialer) SocketId() uint32 {
method PeerSocketId (line 637) | func (dl *dialer) PeerSocketId() uint32 {
method StreamId (line 648) | func (dl *dialer) StreamId() string {
method Version (line 659) | func (dl *dialer) Version() uint32 {
method isShutdown (line 670) | func (dl *dialer) isShutdown() bool {
method Close (line 677) | func (dl *dialer) Close() error {
method Read (line 703) | func (dl *dialer) Read(p []byte) (n int, err error) {
method ReadPacket (line 718) | func (dl *dialer) ReadPacket() (packet.Packet, error) {
method Write (line 733) | func (dl *dialer) Write(p []byte) (n int, err error) {
method WritePacket (line 748) | func (dl *dialer) WritePacket(p packet.Packet) error {
method SetDeadline (line 763) | func (dl *dialer) SetDeadline(t time.Time) error { return dl.conn...
method SetReadDeadline (line 764) | func (dl *dialer) SetReadDeadline(t time.Time) error { return dl.conn...
method SetWriteDeadline (line 765) | func (dl *dialer) SetWriteDeadline(t time.Time) error { return dl.conn...
method Stats (line 767) | func (dl *dialer) Stats(s *Statistics) {
method log (line 778) | func (dl *dialer) log(topic string, message func() string) {
type connResponse (line 60) | type connResponse struct
function Dial (line 75) | func Dial(network, address string, config Config) (Conn, error) {
FILE: dial_test.go
function TestDialReject (line 16) | func TestDialReject(t *testing.T) {
function TestDialOK (line 47) | func TestDialOK(t *testing.T) {
function TestDialV4 (line 80) | func TestDialV4(t *testing.T) {
function TestDialV5 (line 226) | func TestDialV5(t *testing.T) {
function TestDialV5Pre130 (line 400) | func TestDialV5Pre130(t *testing.T) {
function TestDialV5MissingExtension (line 525) | func TestDialV5MissingExtension(t *testing.T) {
FILE: listen.go
type ConnType (line 20) | type ConnType
method String (line 23) | func (c ConnType) String() string {
constant REJECT (line 37) | REJECT ConnType = ConnType(1 << iota)
constant PUBLISH (line 38) | PUBLISH
constant SUBSCRIBE (line 39) | SUBSCRIBE
type RejectionReason (line 44) | type RejectionReason
constant REJ_UNKNOWN (line 48) | REJ_UNKNOWN RejectionReason = 1000
constant REJ_SYSTEM (line 49) | REJ_SYSTEM RejectionReason = 1001
constant REJ_PEER (line 50) | REJ_PEER RejectionReason = 1002
constant REJ_RESOURCE (line 51) | REJ_RESOURCE RejectionReason = 1003
constant REJ_ROGUE (line 52) | REJ_ROGUE RejectionReason = 1004
constant REJ_BACKLOG (line 53) | REJ_BACKLOG RejectionReason = 1005
constant REJ_IPE (line 54) | REJ_IPE RejectionReason = 1006
constant REJ_CLOSE (line 55) | REJ_CLOSE RejectionReason = 1007
constant REJ_VERSION (line 56) | REJ_VERSION RejectionReason = 1008
constant REJ_RDVCOOKIE (line 57) | REJ_RDVCOOKIE RejectionReason = 1009
constant REJ_BADSECRET (line 58) | REJ_BADSECRET RejectionReason = 1010
constant REJ_UNSECURE (line 59) | REJ_UNSECURE RejectionReason = 1011
constant REJ_MESSAGEAPI (line 60) | REJ_MESSAGEAPI RejectionReason = 1012
constant REJ_CONGESTION (line 61) | REJ_CONGESTION RejectionReason = 1013
constant REJ_FILTER (line 62) | REJ_FILTER RejectionReason = 1014
constant REJ_GROUP (line 63) | REJ_GROUP RejectionReason = 1015
constant REJX_BAD_REQUEST (line 69) | REJX_BAD_REQUEST RejectionReason = 1400
constant REJX_UNAUTHORIZED (line 70) | REJX_UNAUTHORIZED RejectionReason = 1401
constant REJX_OVERLOAD (line 71) | REJX_OVERLOAD RejectionReason = 1402
constant REJX_FORBIDDEN (line 72) | REJX_FORBIDDEN RejectionReason = 1403
constant REJX_NOTFOUND (line 73) | REJX_NOTFOUND RejectionReason = 1404
constant REJX_BAD_MODE (line 74) | REJX_BAD_MODE RejectionReason = 1405
constant REJX_UNACCEPTABLE (line 75) | REJX_UNACCEPTABLE RejectionReason = 1406
constant REJX_CONFLICT (line 76) | REJX_CONFLICT RejectionReason = 1407
constant REJX_NOTSUP_MEDIA (line 77) | REJX_NOTSUP_MEDIA RejectionReason = 1415
constant REJX_LOCKED (line 78) | REJX_LOCKED RejectionReason = 1423
constant REJX_FAILED_DEPEND (line 79) | REJX_FAILED_DEPEND RejectionReason = 1424
constant REJX_ISE (line 80) | REJX_ISE RejectionReason = 1500
constant REJX_UNIMPLEMENTED (line 81) | REJX_UNIMPLEMENTED RejectionReason = 1501
constant REJX_GW (line 82) | REJX_GW RejectionReason = 1502
constant REJX_DOWN (line 83) | REJX_DOWN RejectionReason = 1503
constant REJX_VERSION (line 84) | REJX_VERSION RejectionReason = 1505
constant REJX_NOROOM (line 85) | REJX_NOROOM RejectionReason = 1507
type AcceptFunc (line 93) | type AcceptFunc
type Listener (line 96) | type Listener interface
type listener (line 119) | type listener struct
method Accept2 (line 284) | func (ln *listener) Accept2() (ConnRequest, error) {
method Accept (line 305) | func (ln *listener) Accept(acceptFn AcceptFunc) (Conn, ConnType, error) {
method markDone (line 339) | func (ln *listener) markDone(err error) {
method error (line 350) | func (ln *listener) error() error {
method handleShutdown (line 356) | func (ln *listener) handleShutdown(c *srtConn) {
method isShutdown (line 363) | func (ln *listener) isShutdown() bool {
method Close (line 370) | func (ln *listener) Close() {
method Addr (line 393) | func (ln *listener) Addr() net.Addr {
method reader (line 403) | func (ln *listener) reader(ctx context.Context) {
method send (line 455) | func (ln *listener) send(p packet.Packet) {
method log (line 480) | func (ln *listener) log(topic string, message func() string) {
function Listen (line 160) | func Listen(network, address string, config Config) (Listener, error) {
FILE: listen_test.go
function TestListenReuse (line 18) | func TestListenReuse(t *testing.T) {
function TestListen (line 30) | func TestListen(t *testing.T) {
function TestListenCrypt (line 69) | func TestListenCrypt(t *testing.T) {
function TestListenHSV4 (line 118) | func TestListenHSV4(t *testing.T) {
function TestListenHSV5 (line 252) | func TestListenHSV5(t *testing.T) {
function TestListenAsync (line 388) | func TestListenAsync(t *testing.T) {
function TestListenHSV5MissingExtension (line 440) | func TestListenHSV5MissingExtension(t *testing.T) {
function TestListenParallelRequests (line 534) | func TestListenParallelRequests(t *testing.T) {
function TestListenDiscardRepeatedHandshakes (line 592) | func TestListenDiscardRepeatedHandshakes(t *testing.T) {
function TestListenMultipleIPs (line 700) | func TestListenMultipleIPs(t *testing.T) {
function TestListenAcceptAndDiscardRepeatedHandshakes (line 732) | func TestListenAcceptAndDiscardRepeatedHandshakes(t *testing.T) {
FILE: log.go
type Logger (line 10) | type Logger interface
type logger (line 27) | type logger struct
method HasTopic (line 46) | func (l *logger) HasTopic(topic string) bool {
method Print (line 75) | func (l *logger) Print(topic string, socketId uint32, skip int, messag...
method Listen (line 98) | func (l *logger) Listen() <-chan Log {
method Close (line 102) | func (l *logger) Close() {
function NewLogger (line 33) | func NewLogger(topics []string) Logger {
type Log (line 107) | type Log struct
FILE: log_test.go
function TestHasTopic (line 9) | func TestHasTopic(t *testing.T) {
function BenchmarkHasTopicNil (line 29) | func BenchmarkHasTopicNil(b *testing.B) {
function BenchmarkHasTopicD1 (line 40) | func BenchmarkHasTopicD1(b *testing.B) {
function BenchmarkHasTopicD2 (line 53) | func BenchmarkHasTopicD2(b *testing.B) {
function BenchmarkHasTopicD3 (line 66) | func BenchmarkHasTopicD3(b *testing.B) {
FILE: net.go
function ListenControl (line 7) | func ListenControl(config Config) func(network, address string, c syscal...
function DialControl (line 40) | func DialControl(config Config) func(network string, address string, c s...
FILE: net/ip.go
type IP (line 10) | type IP struct
method setDefault (line 14) | func (i *IP) setDefault() {
method isValid (line 18) | func (i *IP) isValid() bool {
method String (line 26) | func (i IP) String() string {
method Parse (line 34) | func (i *IP) Parse(ip string) {
method FromNetIP (line 49) | func (i *IP) FromNetIP(ip net.IP) {
method FromNetAddr (line 66) | func (i *IP) FromNetAddr(addr net.Addr) {
method Unmarshal (line 89) | func (i *IP) Unmarshal(data []byte) error {
method Marshal (line 135) | func (i *IP) Marshal(data []byte) {
FILE: net/ip_test.go
function TestIPDefault (line 10) | func TestIPDefault(t *testing.T) {
function TestIPParse (line 18) | func TestIPParse(t *testing.T) {
function TestIPFrom (line 30) | func TestIPFrom(t *testing.T) {
function TestIPUnmarshal (line 56) | func TestIPUnmarshal(t *testing.T) {
function TestIPMarshal (line 87) | func TestIPMarshal(t *testing.T) {
FILE: net/syncookie.go
type SYNCookie (line 13) | type SYNCookie struct
method Get (line 50) | func (s *SYNCookie) Get(saddr string) uint32 {
method Verify (line 55) | func (s *SYNCookie) Verify(cookie uint32, saddr string) bool {
method calculate (line 69) | func (s *SYNCookie) calculate(counter int64, saddr string) uint32 {
function defaultCounter (line 20) | func defaultCounter() int64 {
function NewSYNCookie (line 25) | func NewSYNCookie(daddr string, counter func() int64) (*SYNCookie, error) {
FILE: net/syncookie_test.go
function TestSYNCookie (line 9) | func TestSYNCookie(t *testing.T) {
FILE: net_windows.go
function ListenControl (line 11) | func ListenControl(config Config) func(network, address string, c syscal...
function DialControl (line 44) | func DialControl(config Config) func(network string, address string, c s...
FILE: packet/packet.go
constant MAX_SEQUENCENUMBER (line 20) | MAX_SEQUENCENUMBER uint32 = 0b01111111_11111111_11111111_11111111
constant MAX_TIMESTAMP (line 21) | MAX_TIMESTAMP uint32 = 0b11111111_11111111_11111111_11111111
constant MAX_PAYLOAD_SIZE (line 22) | MAX_PAYLOAD_SIZE = 1456
type CtrlType (line 25) | type CtrlType
method String (line 40) | func (h CtrlType) String() string {
method Value (line 67) | func (h CtrlType) Value() uint16 {
constant CTRLTYPE_HANDSHAKE (line 28) | CTRLTYPE_HANDSHAKE CtrlType = 0x0000
constant CTRLTYPE_KEEPALIVE (line 29) | CTRLTYPE_KEEPALIVE CtrlType = 0x0001
constant CTRLTYPE_ACK (line 30) | CTRLTYPE_ACK CtrlType = 0x0002
constant CTRLTYPE_NAK (line 31) | CTRLTYPE_NAK CtrlType = 0x0003
constant CTRLTYPE_WARN (line 32) | CTRLTYPE_WARN CtrlType = 0x0004
constant CTRLTYPE_SHUTDOWN (line 33) | CTRLTYPE_SHUTDOWN CtrlType = 0x0005
constant CTRLTYPE_ACKACK (line 34) | CTRLTYPE_ACKACK CtrlType = 0x0006
constant CRTLTYPE_DROPREQ (line 35) | CRTLTYPE_DROPREQ CtrlType = 0x0007
constant CRTLTYPE_PEERERROR (line 36) | CRTLTYPE_PEERERROR CtrlType = 0x0008
constant CTRLTYPE_USER (line 37) | CTRLTYPE_USER CtrlType = 0x7FFF
type HandshakeType (line 71) | type HandshakeType
method String (line 82) | func (h HandshakeType) String() string {
method IsHandshake (line 99) | func (h HandshakeType) IsHandshake() bool {
method IsRejection (line 113) | func (h HandshakeType) IsRejection() bool {
method Val (line 117) | func (h HandshakeType) Val() uint32 {
constant HSTYPE_DONE (line 75) | HSTYPE_DONE HandshakeType = 0xFFFFFFFD
constant HSTYPE_AGREEMENT (line 76) | HSTYPE_AGREEMENT HandshakeType = 0xFFFFFFFE
constant HSTYPE_CONCLUSION (line 77) | HSTYPE_CONCLUSION HandshakeType = 0xFFFFFFFF
constant HSTYPE_WAVEHAND (line 78) | HSTYPE_WAVEHAND HandshakeType = 0x00000000
constant HSTYPE_INDUCTION (line 79) | HSTYPE_INDUCTION HandshakeType = 0x00000001
constant SRTFLAG_TSBPDSND (line 123) | SRTFLAG_TSBPDSND uint32 = 1 << 0
constant SRTFLAG_TSBPDRCV (line 124) | SRTFLAG_TSBPDRCV uint32 = 1 << 1
constant SRTFLAG_CRYPT (line 125) | SRTFLAG_CRYPT uint32 = 1 << 2
constant SRTFLAG_TLPKTDROP (line 126) | SRTFLAG_TLPKTDROP uint32 = 1 << 3
constant SRTFLAG_PERIODICNAK (line 127) | SRTFLAG_PERIODICNAK uint32 = 1 << 4
constant SRTFLAG_REXMITFLG (line 128) | SRTFLAG_REXMITFLG uint32 = 1 << 5
constant SRTFLAG_STREAM (line 129) | SRTFLAG_STREAM uint32 = 1 << 6
constant SRTFLAG_PACKET_FILTER (line 130) | SRTFLAG_PACKET_FILTER uint32 = 1 << 7
type CtrlSubType (line 134) | type CtrlSubType
method String (line 148) | func (h CtrlSubType) String() string {
method Value (line 173) | func (h CtrlSubType) Value() uint16 {
constant CTRLSUBTYPE_NONE (line 137) | CTRLSUBTYPE_NONE CtrlSubType = 0
constant EXTTYPE_HSREQ (line 138) | EXTTYPE_HSREQ CtrlSubType = 1
constant EXTTYPE_HSRSP (line 139) | EXTTYPE_HSRSP CtrlSubType = 2
constant EXTTYPE_KMREQ (line 140) | EXTTYPE_KMREQ CtrlSubType = 3
constant EXTTYPE_KMRSP (line 141) | EXTTYPE_KMRSP CtrlSubType = 4
constant EXTTYPE_SID (line 142) | EXTTYPE_SID CtrlSubType = 5
constant EXTTYPE_CONGESTION (line 143) | EXTTYPE_CONGESTION CtrlSubType = 6
constant EXTTYPE_FILTER (line 144) | EXTTYPE_FILTER CtrlSubType = 7
constant EXTTYPE_GROUP (line 145) | EXTTYPE_GROUP CtrlSubType = 8
type Packet (line 177) | type Packet interface
type PacketHeader (line 221) | type PacketHeader struct
type pkt (line 248) | type pkt struct
method Decommission (line 310) | func (p *pkt) Decommission() {
method String (line 319) | func (p pkt) String() string {
method Clone (line 344) | func (p *pkt) Clone() Packet {
method Header (line 353) | func (p *pkt) Header() *PacketHeader {
method SetData (line 357) | func (p *pkt) SetData(data []byte) {
method Data (line 362) | func (p *pkt) Data() []byte {
method Len (line 366) | func (p *pkt) Len() uint64 {
method Unmarshal (line 370) | func (p *pkt) Unmarshal(data []byte) error {
method Marshal (line 399) | func (p *pkt) Marshal(w io.Writer) error {
method Dump (line 444) | func (p *pkt) Dump() string {
method MarshalCIF (line 451) | func (p *pkt) MarshalCIF(c CIF) error {
method UnmarshalCIF (line 460) | func (p *pkt) UnmarshalCIF(c CIF) error {
type pool (line 254) | type pool struct
method Get (line 268) | func (p *pool) Get() *bytes.Buffer {
method Put (line 275) | func (p *pool) Put(b *bytes.Buffer) {
function newPool (line 258) | func newPool() *pool {
function NewPacketFromData (line 281) | func NewPacketFromData(addr net.Addr, rawdata []byte) (Packet, error) {
function NewPacket (line 294) | func NewPacket(addr net.Addr) Packet {
type CIF (line 469) | type CIF interface
type CIFHandshake (line 483) | type CIFHandshake struct
method String (line 515) | func (c CIFHandshake) String() string {
method Unmarshal (line 558) | func (c *CIFHandshake) Unmarshal(data []byte) error {
method Marshal (line 707) | func (c *CIFHandshake) Marshal(w io.Writer) error {
type CIFHandshakeExtensionFlags (line 851) | type CIFHandshakeExtensionFlags struct
type CIFHandshakeExtension (line 865) | type CIFHandshakeExtension struct
method String (line 872) | func (c CIFHandshakeExtension) String() string {
method Unmarshal (line 895) | func (c *CIFHandshakeExtension) Unmarshal(data []byte) error {
method Marshal (line 918) | func (c *CIFHandshakeExtension) Marshal(w io.Writer) error {
constant KM_NOSECRET (line 972) | KM_NOSECRET uint32 = 3
constant KM_BADSECRET (line 973) | KM_BADSECRET uint32 = 4
type CIFKeyMaterialExtension (line 978) | type CIFKeyMaterialExtension struct
method String (line 998) | func (c CIFKeyMaterialExtension) String() string {
method Unmarshal (line 1025) | func (c *CIFKeyMaterialExtension) Unmarshal(data []byte) error {
method Marshal (line 1120) | func (c *CIFKeyMaterialExtension) Marshal(w io.Writer) error {
type CIFACK (line 1171) | type CIFACK struct
method String (line 1183) | func (c CIFACK) String() string {
method Unmarshal (line 1211) | func (c *CIFACK) Unmarshal(data []byte) error {
method Marshal (line 1247) | func (c *CIFACK) Marshal(w io.Writer) error {
type CIFNAK (line 1276) | type CIFNAK struct
method String (line 1280) | func (c CIFNAK) String() string {
method Unmarshal (line 1303) | func (c *CIFNAK) Unmarshal(data []byte) error {
method Marshal (line 1341) | func (c *CIFNAK) Marshal(w io.Writer) error {
type CIFShutdown (line 1380) | type CIFShutdown struct
method String (line 1382) | func (c CIFShutdown) String() string {
method Unmarshal (line 1386) | func (c *CIFShutdown) Unmarshal(data []byte) error {
method Marshal (line 1394) | func (c *CIFShutdown) Marshal(w io.Writer) error {
type PacketPosition (line 1410) | type PacketPosition
method String (line 1419) | func (p PacketPosition) String() string {
method IsValid (line 1434) | func (p PacketPosition) IsValid() bool {
method Val (line 1438) | func (p PacketPosition) Val() uint32 {
constant FirstPacket (line 1413) | FirstPacket PacketPosition = 2
constant MiddlePacket (line 1414) | MiddlePacket PacketPosition = 0
constant LastPacket (line 1415) | LastPacket PacketPosition = 1
constant SinglePacket (line 1416) | SinglePacket PacketPosition = 3
type PacketEncryption (line 1444) | type PacketEncryption
method String (line 1453) | func (p PacketEncryption) String() string {
method IsValid (line 1468) | func (p PacketEncryption) IsValid() bool {
method Opposite (line 1472) | func (p PacketEncryption) Opposite() PacketEncryption {
method Val (line 1484) | func (p PacketEncryption) Val() uint32 {
constant UnencryptedPacket (line 1447) | UnencryptedPacket PacketEncryption = 0
constant EvenKeyEncrypted (line 1448) | EvenKeyEncrypted PacketEncryption = 1
constant OddKeyEncrypted (line 1449) | OddKeyEncrypted PacketEncryption = 2
constant EvenAndOddKey (line 1450) | EvenAndOddKey PacketEncryption = 3
FILE: packet/packet_test.go
function TestEmptyPacket (line 16) | func TestEmptyPacket(t *testing.T) {
function TestArbitraryPacket (line 30) | func TestArbitraryPacket(t *testing.T) {
function TestArbitraryControlPacket (line 45) | func TestArbitraryControlPacket(t *testing.T) {
function FuzzPacket (line 63) | func FuzzPacket(f *testing.F) {
function TestUnmarshalPacket (line 93) | func TestUnmarshalPacket(t *testing.T) {
function TestPacketString (line 112) | func TestPacketString(t *testing.T) {
function TestHandshakeV4 (line 121) | func TestHandshakeV4(t *testing.T) {
function TestHandshakeV5 (line 159) | func TestHandshakeV5(t *testing.T) {
function TestHandshakeV5UnsupportedExtension (line 232) | func TestHandshakeV5UnsupportedExtension(t *testing.T) {
function TestHandshakeString (line 294) | func TestHandshakeString(t *testing.T) {
function TestKM (line 336) | func TestKM(t *testing.T) {
function TestKMString (line 372) | func TestKMString(t *testing.T) {
function TestFullACK (line 395) | func TestFullACK(t *testing.T) {
function TestFullACKString (line 424) | func TestFullACKString(t *testing.T) {
function TestSmallACK (line 440) | func TestSmallACK(t *testing.T) {
function TestSmallACKString (line 469) | func TestSmallACKString(t *testing.T) {
function TestLiteACK (line 485) | func TestLiteACK(t *testing.T) {
function TestLiteACKString (line 514) | func TestLiteACKString(t *testing.T) {
function TestNAK (line 530) | func TestNAK(t *testing.T) {
function TestNAKString (line 556) | func TestNAKString(t *testing.T) {
function TestShutdown (line 569) | func TestShutdown(t *testing.T) {
function TestShutdownString (line 588) | func TestShutdownString(t *testing.T) {
function BenchmarkNewPacket (line 594) | func BenchmarkNewPacket(b *testing.B) {
function BenchmarkNewPacketWithData (line 604) | func BenchmarkNewPacketWithData(b *testing.B) {
function BenchmarkNoBufferpool (line 628) | func BenchmarkNoBufferpool(b *testing.B) {
function BenchmarkBufferpool (line 639) | func BenchmarkBufferpool(b *testing.B) {
FILE: packet_conn.go
type packetConn (line 12) | type packetConn struct
method readFromTo (line 40) | func (c *packetConn) readFromTo(buffer []byte) (int, net.Addr, net.IP,...
method writeToFrom (line 66) | func (c *packetConn) writeToFrom(buffer []byte, remoteAddr net.Addr, l...
function newPacketConn (line 19) | func newPacketConn(wrapped net.PacketConn) *packetConn {
FILE: pubsub.go
type PubSub (line 13) | type PubSub interface
type pubSub (line 27) | type pubSub struct
method broadcast (line 63) | func (pb *pubSub) broadcast() {
method Publish (line 93) | func (pb *pubSub) Publish(c Conn) error {
method Subscribe (line 131) | func (pb *pubSub) Subscribe(c Conn) error {
type PubSubConfig (line 39) | type PubSubConfig struct
function NewPubSub (line 45) | func NewPubSub(config PubSubConfig) PubSub {
FILE: pubsub_test.go
function TestPubSub (line 13) | func TestPubSub(t *testing.T) {
FILE: rand/rand.go
function RandomString (line 8) | func RandomString(length int, charset string) (string, error) {
function Read (line 21) | func Read(b []byte) (int, error) {
function Uint32 (line 25) | func Uint32() (uint32, error) {
function Int63 (line 35) | func Int63() (int64, error) {
function Int63n (line 47) | func Int63n(n int64) (int64, error) {
FILE: rand/rand_test.go
function TestRandomString (line 9) | func TestRandomString(t *testing.T) {
function TestUint32 (line 19) | func TestUint32(t *testing.T) {
function TestInt63 (line 29) | func TestInt63(t *testing.T) {
function TestInt63n (line 39) | func TestInt63n(t *testing.T) {
FILE: server.go
type Server (line 8) | type Server struct
method ListenAndServe (line 35) | func (s *Server) ListenAndServe() error {
method Listen (line 46) | func (s *Server) Listen() error {
method Serve (line 75) | func (s *Server) Serve() error {
method Shutdown (line 115) | func (s *Server) Shutdown() {
method defaultHandler (line 124) | func (s *Server) defaultHandler(conn Conn) {
FILE: server_test.go
function TestServer (line 9) | func TestServer(t *testing.T) {
FILE: statistics.go
type Statistics (line 6) | type Statistics struct
type StatisticsAccumulated (line 19) | type StatisticsAccumulated struct
type StatisticsInterval (line 53) | type StatisticsInterval struct
type StatisticsInstantaneous (line 93) | type StatisticsInstantaneous struct
FILE: vendor/github.com/benburkert/openpgp/aes/keywrap/keywrap.go
function Wrap (line 52) | func Wrap(key, plainText []byte) ([]byte, error) {
function Unwrap (line 101) | func Unwrap(key, cipherText []byte) ([]byte, error) {
FILE: vendor/github.com/davecgh/go-spew/spew/bypass.go
constant UnsafeDisabled (line 33) | UnsafeDisabled = false
constant ptrSize (line 36) | ptrSize = unsafe.Sizeof((*byte)(nil))
type flag (line 39) | type flag
constant flagKindMask (line 54) | flagKindMask = flag(0x1f)
function flagField (line 80) | func flagField(v *reflect.Value) *flag {
function unsafeReflectValue (line 93) | func unsafeReflectValue(v reflect.Value) reflect.Value {
function init (line 105) | func init() {
FILE: vendor/github.com/davecgh/go-spew/spew/bypasssafe.go
constant UnsafeDisabled (line 28) | UnsafeDisabled = true
function unsafeReflectValue (line 36) | func unsafeReflectValue(v reflect.Value) reflect.Value {
FILE: vendor/github.com/davecgh/go-spew/spew/common.go
function catchPanic (line 72) | func catchPanic(w io.Writer, v reflect.Value) {
function handleMethods (line 85) | func handleMethods(cs *ConfigState, w io.Writer, v reflect.Value) (handl...
function printBool (line 144) | func printBool(w io.Writer, val bool) {
function printInt (line 153) | func printInt(w io.Writer, val int64, base int) {
function printUint (line 158) | func printUint(w io.Writer, val uint64, base int) {
function printFloat (line 164) | func printFloat(w io.Writer, val float64, precision int) {
function printComplex (line 170) | func printComplex(w io.Writer, c complex128, floatPrecision int) {
function printHexPtr (line 185) | func printHexPtr(w io.Writer, p uintptr) {
type valuesSorter (line 219) | type valuesSorter struct
method Len (line 279) | func (s *valuesSorter) Len() int {
method Swap (line 285) | func (s *valuesSorter) Swap(i, j int) {
method Less (line 326) | func (s *valuesSorter) Less(i, j int) bool {
function newValuesSorter (line 228) | func newValuesSorter(values []reflect.Value, cs *ConfigState) sort.Inter...
function canSortSimply (line 256) | func canSortSimply(kind reflect.Kind) bool {
function valueSortLess (line 295) | func valueSortLess(a, b reflect.Value) bool {
function sortValues (line 336) | func sortValues(values []reflect.Value, cs *ConfigState) {
FILE: vendor/github.com/davecgh/go-spew/spew/config.go
type ConfigState (line 37) | type ConfigState struct
method Errorf (line 115) | func (c *ConfigState) Errorf(format string, a ...interface{}) (err err...
method Fprint (line 127) | func (c *ConfigState) Fprint(w io.Writer, a ...interface{}) (n int, er...
method Fprintf (line 139) | func (c *ConfigState) Fprintf(w io.Writer, format string, a ...interfa...
method Fprintln (line 150) | func (c *ConfigState) Fprintln(w io.Writer, a ...interface{}) (n int, ...
method Print (line 162) | func (c *ConfigState) Print(a ...interface{}) (n int, err error) {
method Printf (line 174) | func (c *ConfigState) Printf(format string, a ...interface{}) (n int, ...
method Println (line 186) | func (c *ConfigState) Println(a ...interface{}) (n int, err error) {
method Sprint (line 197) | func (c *ConfigState) Sprint(a ...interface{}) string {
method Sprintf (line 208) | func (c *ConfigState) Sprintf(format string, a ...interface{}) string {
method Sprintln (line 219) | func (c *ConfigState) Sprintln(a ...interface{}) string {
method NewFormatter (line 240) | func (c *ConfigState) NewFormatter(v interface{}) fmt.Formatter {
method Fdump (line 246) | func (c *ConfigState) Fdump(w io.Writer, a ...interface{}) {
method Dump (line 273) | func (c *ConfigState) Dump(a ...interface{}) {
method Sdump (line 279) | func (c *ConfigState) Sdump(a ...interface{}) string {
method convertArgs (line 288) | func (c *ConfigState) convertArgs(args []interface{}) (formatters []in...
function NewDefaultConfig (line 304) | func NewDefaultConfig() *ConfigState {
FILE: vendor/github.com/davecgh/go-spew/spew/dump.go
type dumpState (line 51) | type dumpState struct
method indent (line 62) | func (d *dumpState) indent() {
method unpackValue (line 73) | func (d *dumpState) unpackValue(v reflect.Value) reflect.Value {
method dumpPtr (line 81) | func (d *dumpState) dumpPtr(v reflect.Value) {
method dumpSlice (line 161) | func (d *dumpState) dumpSlice(v reflect.Value) {
method dump (line 251) | func (d *dumpState) dump(v reflect.Value) {
function fdump (line 453) | func fdump(cs *ConfigState, w io.Writer, a ...interface{}) {
function Fdump (line 472) | func Fdump(w io.Writer, a ...interface{}) {
function Sdump (line 478) | func Sdump(a ...interface{}) string {
function Dump (line 507) | func Dump(a ...interface{}) {
FILE: vendor/github.com/davecgh/go-spew/spew/format.go
constant supportedFlags (line 28) | supportedFlags = "0-+# "
type formatState (line 34) | type formatState struct
method buildDefaultFormat (line 47) | func (f *formatState) buildDefaultFormat() (format string) {
method constructOrigFormat (line 65) | func (f *formatState) constructOrigFormat(verb rune) (format string) {
method unpackValue (line 94) | func (f *formatState) unpackValue(v reflect.Value) reflect.Value {
method formatPtr (line 105) | func (f *formatState) formatPtr(v reflect.Value) {
method format (line 201) | func (f *formatState) format(v reflect.Value) {
method Format (line 371) | func (f *formatState) Format(fs fmt.State, verb rune) {
function newFormatter (line 394) | func newFormatter(cs *ConfigState, v interface{}) fmt.Formatter {
function NewFormatter (line 417) | func NewFormatter(v interface{}) fmt.Formatter {
FILE: vendor/github.com/davecgh/go-spew/spew/spew.go
function Errorf (line 32) | func Errorf(format string, a ...interface{}) (err error) {
function Fprint (line 44) | func Fprint(w io.Writer, a ...interface{}) (n int, err error) {
function Fprintf (line 56) | func Fprintf(w io.Writer, format string, a ...interface{}) (n int, err e...
function Fprintln (line 67) | func Fprintln(w io.Writer, a ...interface{}) (n int, err error) {
function Print (line 79) | func Print(a ...interface{}) (n int, err error) {
function Printf (line 91) | func Printf(format string, a ...interface{}) (n int, err error) {
function Println (line 103) | func Println(a ...interface{}) (n int, err error) {
function Sprint (line 114) | func Sprint(a ...interface{}) string {
function Sprintf (line 125) | func Sprintf(format string, a ...interface{}) string {
function Sprintln (line 136) | func Sprintln(a ...interface{}) string {
function convertArgs (line 142) | func convertArgs(args []interface{}) (formatters []interface{}) {
FILE: vendor/github.com/felixge/fgprof/fgprof.go
type Format (line 18) | type Format
constant FormatFolded (line 23) | FormatFolded Format = "folded"
constant FormatPprof (line 26) | FormatPprof Format = "pprof"
function Start (line 32) | func Start(w io.Writer, format Format) func() error {
type profiler (line 68) | type profiler struct
method GoroutineProfile (line 76) | func (p *profiler) GoroutineProfile() []runtime.StackRecord {
method SelfFrames (line 110) | func (p *profiler) SelfFrames() []*runtime.Frame {
function newWallclockProfile (line 117) | func newWallclockProfile() *wallclockProfile {
type wallclockProfile (line 123) | type wallclockProfile struct
method Ignore (line 137) | func (p *wallclockProfile) Ignore(frames ...*runtime.Frame) {
method Add (line 142) | func (p *wallclockProfile) Add(stackRecords []runtime.StackRecord) {
method Export (line 161) | func (p *wallclockProfile) Export(w io.Writer, f Format, hz int, start...
method exportStacks (line 174) | func (p *wallclockProfile) exportStacks() []*wallclockStack {
method exportFolded (line 190) | func (p *wallclockProfile) exportFolded(w io.Writer) error {
method exportPprof (line 206) | func (p *wallclockProfile) exportPprof(hz int, startTime, endTime time...
method Symbolize (line 284) | func (w wallclockProfile) Symbolize(exclude *runtime.Frame) symbolized...
type wallclockStack (line 130) | type wallclockStack struct
type symbolizedStacks (line 282) | type symbolizedStacks
type frameCount (line 304) | type frameCount struct
FILE: vendor/github.com/felixge/fgprof/handler.go
function Handler (line 14) | func Handler() http.Handler {
FILE: vendor/github.com/google/pprof/profile/encode.go
method decoder (line 22) | func (p *Profile) decoder() []decoder {
method preEncode (line 29) | func (p *Profile) preEncode() {
method encode (line 131) | func (p *Profile) encode(b *buffer) {
method postDecode (line 243) | func (p *Profile) postDecode() error {
function padStringArray (line 372) | func padStringArray(arr []string, l int) []string {
method decoder (line 379) | func (p *ValueType) decoder() []decoder {
method encode (line 383) | func (p *ValueType) encode(b *buffer) {
method decoder (line 396) | func (p *Sample) decoder() []decoder {
method encode (line 400) | func (p *Sample) encode(b *buffer) {
method decoder (line 423) | func (p label) decoder() []decoder {
method encode (line 427) | func (p label) encode(b *buffer) {
method decoder (line 446) | func (p *Mapping) decoder() []decoder {
method encode (line 450) | func (p *Mapping) encode(b *buffer) {
method decoder (line 477) | func (p *Location) decoder() []decoder {
method encode (line 481) | func (p *Location) encode(b *buffer) {
method decoder (line 505) | func (p *Line) decoder() []decoder {
method encode (line 509) | func (p *Line) encode(b *buffer) {
method decoder (line 522) | func (p *Function) decoder() []decoder {
method encode (line 526) | func (p *Function) encode(b *buffer) {
function addString (line 548) | func addString(strings map[string]int, s string) int64 {
function getString (line 557) | func getString(strings []string, strng *int64, err error) (string, error) {
FILE: vendor/github.com/google/pprof/profile/filter.go
method FilterSamplesByName (line 24) | func (p *Profile) FilterSamplesByName(focus, ignore, hide, show *regexp....
method ShowFrom (line 87) | func (p *Profile) ShowFrom(showFrom *regexp.Regexp) (matched bool) {
function filterShowFromLocation (line 118) | func filterShowFromLocation(loc *Location, showFrom *regexp.Regexp) bool {
method lastMatchedLineIndex (line 131) | func (loc *Location) lastMatchedLineIndex(re *regexp.Regexp) int {
method FilterTagsByName (line 144) | func (p *Profile) FilterTagsByName(show, hide *regexp.Regexp) (sm, hm bo...
method matchesName (line 175) | func (loc *Location) matchesName(re *regexp.Regexp) bool {
method unmatchedLines (line 191) | func (loc *Location) unmatchedLines(re *regexp.Regexp) []Line {
method matchedLines (line 209) | func (loc *Location) matchedLines(re *regexp.Regexp) []Line {
function focusedAndNotIgnored (line 229) | func focusedAndNotIgnored(locs []*Location, m map[uint64]bool) bool {
type TagMatch (line 247) | type TagMatch
method FilterSamplesByTag (line 252) | func (p *Profile) FilterSamplesByTag(focus, ignore TagMatch) (fm, im boo...
FILE: vendor/github.com/google/pprof/profile/index.go
method SampleIndexByName (line 26) | func (p *Profile) SampleIndexByName(sampleIndex string) (int, error) {
function sampleTypes (line 58) | func sampleTypes(p *Profile) []string {
FILE: vendor/github.com/google/pprof/profile/legacy_java_profile.go
function javaCPUProfile (line 42) | func javaCPUProfile(b []byte, period int64, parse func(b []byte) (uint64...
function parseJavaProfile (line 68) | func parseJavaProfile(b []byte) (*Profile, error) {
function parseJavaHeader (line 112) | func parseJavaHeader(pType string, b []byte, p *Profile) ([]byte, error) {
function parseJavaSamples (line 167) | func parseJavaSamples(pType string, b []byte, p *Profile) ([]byte, map[u...
function parseJavaLocations (line 239) | func parseJavaLocations(b []byte, locs map[uint64]*Location, p *Profile)...
FILE: vendor/github.com/google/pprof/profile/legacy_profile.go
function isSpaceOrComment (line 72) | func isSpaceOrComment(line string) bool {
function parseGoCount (line 79) | func parseGoCount(b []byte) (*Profile, error) {
method remapLocationIDs (line 151) | func (p *Profile) remapLocationIDs() {
method remapFunctionIDs (line 168) | func (p *Profile) remapFunctionIDs() {
method remapMappingIDs (line 190) | func (p *Profile) remapMappingIDs() {
function get32l (line 265) | func get32l(b []byte) (uint64, []byte) {
function get32b (line 272) | func get32b(b []byte) (uint64, []byte) {
function get64l (line 279) | func get64l(b []byte) (uint64, []byte) {
function get64b (line 286) | func get64b(b []byte) (uint64, []byte) {
function parseCPU (line 303) | func parseCPU(b []byte) (*Profile, error) {
function cpuProfile (line 330) | func cpuProfile(b []byte, period int64, parse func(b []byte) (uint64, []...
function cleanupDuplicateLocations (line 388) | func cleanupDuplicateLocations(p *Profile) {
function parseCPUSamples (line 419) | func parseCPUSamples(b []byte, parse func(b []byte) (uint64, []byte), ad...
function parseHeap (line 464) | func parseHeap(b []byte) (p *Profile, err error) {
function parseHeapHeader (line 556) | func parseHeapHeader(line string) (sampling string, period int64, hasAll...
function parseHeapSample (line 585) | func parseHeapSample(line string, rate int64, sampling string, includeAl...
function parseHexAddresses (line 637) | func parseHexAddresses(s string) ([]uint64, error) {
function scaleHeapSample (line 659) | func scaleHeapSample(count, size, rate int64) (int64, int64) {
function parseContention (line 679) | func parseContention(b []byte) (*Profile, error) {
function parseContentionSample (line 800) | func parseContentionSample(line string, period, cpuHz int64) (value []in...
function parseThread (line 836) | func parseThread(b []byte) (*Profile, error) {
function parseThreadSample (line 922) | func parseThreadSample(s *bufio.Scanner) (nextl string, addrs []uint64, ...
function parseAdditionalSections (line 956) | func parseAdditionalSections(s *bufio.Scanner, p *Profile) error {
function ParseProcMaps (line 969) | func ParseProcMaps(rd io.Reader) ([]*Mapping, error) {
function parseProcMapsFromScanner (line 974) | func parseProcMapsFromScanner(s *bufio.Scanner) ([]*Mapping, error) {
function removeLoggingInfo (line 1010) | func removeLoggingInfo(line string) string {
method ParseMemoryMap (line 1020) | func (p *Profile) ParseMemoryMap(rd io.Reader) error {
method ParseMemoryMapFromScanner (line 1028) | func (p *Profile) ParseMemoryMapFromScanner(s *bufio.Scanner) error {
function parseMappingEntry (line 1041) | func parseMappingEntry(l string) (*Mapping, error) {
function isMemoryMapSentinel (line 1081) | func isMemoryMapSentinel(line string) bool {
method addLegacyFrameInfo (line 1090) | func (p *Profile) addLegacyFrameInfo() {
function isProfileType (line 1112) | func isProfileType(p *Profile, types [][]string) bool {
FILE: vendor/github.com/google/pprof/profile/merge.go
method Compact (line 27) | func (p *Profile) Compact() *Profile {
function Merge (line 42) | func Merge(srcs []*Profile) (*Profile, error) {
method Normalize (line 94) | func (p *Profile) Normalize(pb *Profile) error {
function isZeroSample (line 126) | func isZeroSample(s *Sample) bool {
type profileMerger (line 135) | type profileMerger struct
method mapSample (line 155) | func (pm *profileMerger) mapSample(src *Sample) *Sample {
method mapLocation (line 228) | func (pm *profileMerger) mapLocation(src *Location) *Location {
method mapMapping (line 289) | func (pm *profileMerger) mapMapping(src *Mapping) mapInfo {
method mapLine (line 359) | func (pm *profileMerger) mapLine(src Line) Line {
method mapFunction (line 367) | func (pm *profileMerger) mapFunction(src *Function) *Function {
type mapInfo (line 150) | type mapInfo struct
method key (line 197) | func (sample *Sample) key() sampleKey {
type sampleKey (line 222) | type sampleKey struct
method key (line 262) | func (l *Location) key() locationKey {
type locationKey (line 283) | type locationKey struct
method key (line 328) | func (m *Mapping) key() mappingKey {
type mappingKey (line 354) | type mappingKey struct
method key (line 393) | func (f *Function) key() functionKey {
type functionKey (line 402) | type functionKey struct
function combineHeaders (line 409) | func combineHeaders(srcs []*Profile) (*Profile, error) {
method compatible (line 460) | func (p *Profile) compatible(pb *Profile) error {
function equalValueType (line 479) | func equalValueType(st1, st2 *ValueType) bool {
FILE: vendor/github.com/google/pprof/profile/profile.go
type Profile (line 35) | type Profile struct
method massageMappings (line 231) | func (p *Profile) massageMappings() {
method updateLocationMapping (line 302) | func (p *Profile) updateLocationMapping(from, to *Mapping) {
method Write (line 319) | func (p *Profile) Write(w io.Writer) error {
method WriteUncompressed (line 327) | func (p *Profile) WriteUncompressed(w io.Writer) error {
method CheckValid (line 336) | func (p *Profile) CheckValid() error {
method Aggregate (line 417) | func (p *Profile) Aggregate(inlineFrame, function, filename, linenumbe...
method NumLabelUnits (line 467) | func (p *Profile) NumLabelUnits() (map[string]string, map[string][]str...
method String (line 524) | func (p *Profile) String() string {
method SetLabel (line 682) | func (p *Profile) SetLabel(key string, value []string) {
method RemoveLabel (line 694) | func (p *Profile) RemoveLabel(key string) {
method Scale (line 718) | func (p *Profile) Scale(ratio float64) {
method ScaleN (line 731) | func (p *Profile) ScaleN(ratios []float64) error {
method HasFunctions (line 766) | func (p *Profile) HasFunctions() bool {
method HasFileLines (line 777) | func (p *Profile) HasFileLines() bool {
method Copy (line 795) | func (p *Profile) Copy() *Profile {
type ValueType (line 64) | type ValueType struct
type Sample (line 73) | type Sample struct
method string (line 626) | func (s *Sample) string() string {
method HasLabel (line 701) | func (s *Sample) HasLabel(key, value string) bool {
method DiffBaseSample (line 712) | func (s *Sample) DiffBaseSample() bool {
type label (line 85) | type label struct
type Mapping (line 95) | type Mapping struct
method string (line 569) | func (m *Mapping) string() string {
method Unsymbolizable (line 789) | func (m *Mapping) Unsymbolizable() bool {
type Location (line 112) | type Location struct
method string (line 593) | func (l *Location) string() string {
type Line (line 123) | type Line struct
type Function (line 131) | type Function struct
function Parse (line 146) | func Parse(r io.Reader) (*Profile, error) {
function ParseData (line 156) | func ParseData(data []byte) (*Profile, error) {
function parseLegacy (line 187) | func parseLegacy(data []byte) (*Profile, error) {
function ParseUncompressed (line 211) | func ParseUncompressed(data []byte) (*Profile, error) {
function adjacent (line 279) | func adjacent(m1, m2 *Mapping) bool {
function serialize (line 310) | func serialize(p *Profile) []byte {
function labelsToString (line 649) | func labelsToString(labels map[string][]string) string {
function numLabelsToString (line 660) | func numLabelsToString(numLabels map[string][]int64, numUnits map[string...
FILE: vendor/github.com/google/pprof/profile/proto.go
type buffer (line 41) | type buffer struct
type decoder (line 49) | type decoder
type message (line 51) | type message interface
function marshal (line 56) | func marshal(m message) []byte {
function encodeVarint (line 62) | func encodeVarint(b *buffer, x uint64) {
function encodeLength (line 70) | func encodeLength(b *buffer, tag int, len int) {
function encodeUint64 (line 75) | func encodeUint64(b *buffer, tag int, x uint64) {
function encodeUint64s (line 81) | func encodeUint64s(b *buffer, tag int, x []uint64) {
function encodeUint64Opt (line 101) | func encodeUint64Opt(b *buffer, tag int, x uint64) {
function encodeInt64 (line 108) | func encodeInt64(b *buffer, tag int, x int64) {
function encodeInt64s (line 113) | func encodeInt64s(b *buffer, tag int, x []int64) {
function encodeInt64Opt (line 133) | func encodeInt64Opt(b *buffer, tag int, x int64) {
function encodeString (line 140) | func encodeString(b *buffer, tag int, x string) {
function encodeStrings (line 145) | func encodeStrings(b *buffer, tag int, x []string) {
function encodeBool (line 151) | func encodeBool(b *buffer, tag int, x bool) {
function encodeBoolOpt (line 159) | func encodeBoolOpt(b *buffer, tag int, x bool) {
function encodeMessage (line 165) | func encodeMessage(b *buffer, tag int, m message) {
function unmarshal (line 176) | func unmarshal(data []byte, m message) (err error) {
function le64 (line 181) | func le64(p []byte) uint64 {
function le32 (line 185) | func le32(p []byte) uint32 {
function decodeVarint (line 189) | func decodeVarint(data []byte) (uint64, []byte, error) {
function decodeField (line 202) | func decodeField(b *buffer, data []byte) ([]byte, error) {
function checkType (line 247) | func checkType(b *buffer, typ int) error {
function decodeMessage (line 254) | func decodeMessage(b *buffer, m message) error {
function decodeInt64 (line 277) | func decodeInt64(b *buffer, x *int64) error {
function decodeInt64s (line 285) | func decodeInt64s(b *buffer, x *[]int64) error {
function decodeUint64 (line 310) | func decodeUint64(b *buffer, x *uint64) error {
function decodeUint64s (line 318) | func decodeUint64s(b *buffer, x *[]uint64) error {
function decodeString (line 343) | func decodeString(b *buffer, x *string) error {
function decodeStrings (line 351) | func decodeStrings(b *buffer, x *[]string) error {
function decodeBool (line 360) | func decodeBool(b *buffer, x *bool) error {
FILE: vendor/github.com/google/pprof/profile/prune.go
function simplifyFunc (line 37) | func simplifyFunc(f string) string {
method Prune (line 61) | func (p *Profile) Prune(dropRx, keepRx *regexp.Regexp) {
method RemoveUninteresting (line 121) | func (p *Profile) RemoveUninteresting() error {
method PruneFrom (line 151) | func (p *Profile) PruneFrom(dropRx *regexp.Regexp) {
FILE: vendor/github.com/pkg/profile/profile.go
constant cpuMode (line 20) | cpuMode = iota
constant memMode (line 21) | memMode
constant mutexMode (line 22) | mutexMode
constant blockMode (line 23) | blockMode
constant traceMode (line 24) | traceMode
constant threadCreateMode (line 25) | threadCreateMode
constant goroutineMode (line 26) | goroutineMode
constant clockMode (line 27) | clockMode
type Profile (line 31) | type Profile struct
method Stop (line 142) | func (p *Profile) Stop() {
function NoShutdownHook (line 65) | func NoShutdownHook(p *Profile) { p.noShutdownHook = true }
function Quiet (line 68) | func Quiet(p *Profile) { p.quiet = true }
function CPUProfile (line 72) | func CPUProfile(p *Profile) { p.mode = cpuMode }
constant DefaultMemProfileRate (line 76) | DefaultMemProfileRate = 4096
function MemProfile (line 80) | func MemProfile(p *Profile) {
function MemProfileRate (line 87) | func MemProfileRate(rate int) func(*Profile) {
function MemProfileHeap (line 96) | func MemProfileHeap(p *Profile) {
function MemProfileAllocs (line 103) | func MemProfileAllocs(p *Profile) {
function MutexProfile (line 110) | func MutexProfile(p *Profile) { p.mode = mutexMode }
function BlockProfile (line 114) | func BlockProfile(p *Profile) { p.mode = blockMode }
function TraceProfile (line 118) | func TraceProfile(p *Profile) { p.mode = traceMode }
function ThreadcreationProfile (line 122) | func ThreadcreationProfile(p *Profile) { p.mode = threadCreateMode }
function GoroutineProfile (line 126) | func GoroutineProfile(p *Profile) { p.mode = goroutineMode }
function ClockProfile (line 130) | func ClockProfile(p *Profile) { p.mode = clockMode }
function ProfilePath (line 135) | func ProfilePath(path string) func(*Profile) {
function Start (line 157) | func Start(options ...func(*Profile)) interface {
FILE: vendor/github.com/pmezard/go-difflib/difflib/difflib.go
function min (line 26) | func min(a, b int) int {
function max (line 33) | func max(a, b int) int {
function calculateRatio (line 40) | func calculateRatio(matches, length int) float64 {
type Match (line 47) | type Match struct
type OpCode (line 53) | type OpCode struct
type SequenceMatcher (line 87) | type SequenceMatcher struct
method SetSeqs (line 115) | func (m *SequenceMatcher) SetSeqs(a, b []string) {
method SetSeq1 (line 129) | func (m *SequenceMatcher) SetSeq1(a []string) {
method SetSeq2 (line 140) | func (m *SequenceMatcher) SetSeq2(b []string) {
method chainB (line 151) | func (m *SequenceMatcher) chainB() {
method isBJunk (line 192) | func (m *SequenceMatcher) isBJunk(s string) bool {
method findLongestMatch (line 221) | func (m *SequenceMatcher) findLongestMatch(alo, ahi, blo, bhi int) Mat...
method GetMatchingBlocks (line 305) | func (m *SequenceMatcher) GetMatchingBlocks() []Match {
method GetOpCodes (line 373) | func (m *SequenceMatcher) GetOpCodes() []OpCode {
method GetGroupedOpCodes (line 413) | func (m *SequenceMatcher) GetGroupedOpCodes(n int) [][]OpCode {
method Ratio (line 465) | func (m *SequenceMatcher) Ratio() float64 {
method QuickRatio (line 477) | func (m *SequenceMatcher) QuickRatio() float64 {
method RealQuickRatio (line 509) | func (m *SequenceMatcher) RealQuickRatio() float64 {
function NewMatcher (line 100) | func NewMatcher(a, b []string) *SequenceMatcher {
function NewMatcherWithJunk (line 106) | func NewMatcherWithJunk(a, b []string, autoJunk bool,
function formatRangeUnified (line 515) | func formatRangeUnified(start, stop int) string {
type UnifiedDiff (line 529) | type UnifiedDiff struct
function WriteUnifiedDiff (line 559) | func WriteUnifiedDiff(writer io.Writer, diff UnifiedDiff) error {
function GetUnifiedDiffString (line 635) | func GetUnifiedDiffString(diff UnifiedDiff) (string, error) {
function formatRangeContext (line 642) | func formatRangeContext(start, stop int) string {
type ContextDiff (line 655) | type ContextDiff
function WriteContextDiff (line 674) | func WriteContextDiff(writer io.Writer, diff ContextDiff) error {
function GetContextDiffString (line 760) | func GetContextDiffString(diff ContextDiff) (string, error) {
function SplitLines (line 768) | func SplitLines(s string) []string {
FILE: vendor/github.com/stretchr/testify/assert/assertion_compare.go
type compareResult (line 13) | type compareResult
constant compareLess (line 16) | compareLess compareResult = iota - 1
constant compareEqual (line 17) | compareEqual
constant compareGreater (line 18) | compareGreater
function compare (line 45) | func compare(obj1, obj2 interface{}, kind reflect.Kind) (compareResult, ...
function Greater (line 389) | func Greater(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...i...
function GreaterOrEqual (line 403) | func GreaterOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndAr...
function Less (line 416) | func Less(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...inte...
function LessOrEqual (line 430) | func LessOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...
function Positive (line 442) | func Positive(t TestingT, e interface{}, msgAndArgs ...interface{}) bool {
function Negative (line 455) | func Negative(t TestingT, e interface{}, msgAndArgs ...interface{}) bool {
function compareTwoValues (line 464) | func compareTwoValues(t TestingT, e1 interface{}, e2 interface{}, allowe...
function containsValue (line 487) | func containsValue(values []compareResult, value compareResult) bool {
FILE: vendor/github.com/stretchr/testify/assert/assertion_format.go
function Conditionf (line 12) | func Conditionf(t TestingT, comp Comparison, msg string, args ...interfa...
function Containsf (line 25) | func Containsf(t TestingT, s interface{}, contains interface{}, msg stri...
function DirExistsf (line 34) | func DirExistsf(t TestingT, path string, msg string, args ...interface{}...
function ElementsMatchf (line 46) | func ElementsMatchf(t TestingT, listA interface{}, listB interface{}, ms...
function Emptyf (line 66) | func Emptyf(t TestingT, object interface{}, msg string, args ...interfac...
function Equalf (line 80) | func Equalf(t TestingT, expected interface{}, actual interface{}, msg st...
function EqualErrorf (line 92) | func EqualErrorf(t TestingT, theError error, errString string, msg strin...
function EqualExportedValuesf (line 109) | func EqualExportedValuesf(t TestingT, expected interface{}, actual inter...
function EqualValuesf (line 120) | func EqualValuesf(t TestingT, expected interface{}, actual interface{}, ...
function Errorf (line 131) | func Errorf(t TestingT, err error, msg string, args ...interface{}) bool {
function ErrorAsf (line 140) | func ErrorAsf(t TestingT, err error, target interface{}, msg string, arg...
function ErrorContainsf (line 152) | func ErrorContainsf(t TestingT, theError error, contains string, msg str...
function ErrorIsf (line 161) | func ErrorIsf(t TestingT, err error, target error, msg string, args ...i...
function Eventuallyf (line 172) | func Eventuallyf(t TestingT, condition func() bool, waitFor time.Duratio...
function EventuallyWithTf (line 197) | func EventuallyWithTf(t TestingT, condition func(collect *CollectT), wai...
function Exactlyf (line 207) | func Exactlyf(t TestingT, expected interface{}, actual interface{}, msg ...
function Failf (line 215) | func Failf(t TestingT, failureMessage string, msg string, args ...interf...
function FailNowf (line 223) | func FailNowf(t TestingT, failureMessage string, msg string, args ...int...
function Falsef (line 233) | func Falsef(t TestingT, value bool, msg string, args ...interface{}) bool {
function FileExistsf (line 242) | func FileExistsf(t TestingT, path string, msg string, args ...interface{...
function Greaterf (line 254) | func Greaterf(t TestingT, e1 interface{}, e2 interface{}, msg string, ar...
function GreaterOrEqualf (line 267) | func GreaterOrEqualf(t TestingT, e1 interface{}, e2 interface{}, msg str...
function HTTPBodyContainsf (line 280) | func HTTPBodyContainsf(t TestingT, handler http.HandlerFunc, method stri...
function HTTPBodyNotContainsf (line 293) | func HTTPBodyNotContainsf(t TestingT, handler http.HandlerFunc, method s...
function HTTPErrorf (line 305) | func HTTPErrorf(t TestingT, handler http.HandlerFunc, method string, url...
function HTTPRedirectf (line 317) | func HTTPRedirectf(t TestingT, handler http.HandlerFunc, method string, ...
function HTTPStatusCodef (line 329) | func HTTPStatusCodef(t TestingT, handler http.HandlerFunc, method string...
function HTTPSuccessf (line 341) | func HTTPSuccessf(t TestingT, handler http.HandlerFunc, method string, u...
function Implementsf (line 351) | func Implementsf(t TestingT, interfaceObject interface{}, object interfa...
function InDeltaf (line 361) | func InDeltaf(t TestingT, expected interface{}, actual interface{}, delt...
function InDeltaMapValuesf (line 369) | func InDeltaMapValuesf(t TestingT, expected interface{}, actual interfac...
function InDeltaSlicef (line 377) | func InDeltaSlicef(t TestingT, expected interface{}, actual interface{},...
function InEpsilonf (line 385) | func InEpsilonf(t TestingT, expected interface{}, actual interface{}, ep...
function InEpsilonSlicef (line 393) | func InEpsilonSlicef(t TestingT, expected interface{}, actual interface{...
function IsDecreasingf (line 405) | func IsDecreasingf(t TestingT, object interface{}, msg string, args ...i...
function IsIncreasingf (line 417) | func IsIncreasingf(t TestingT, object interface{}, msg string, args ...i...
function IsNonDecreasingf (line 429) | func IsNonDecreasingf(t TestingT, object interface{}, msg string, args ....
function IsNonIncreasingf (line 441) | func IsNonIncreasingf(t TestingT, object interface{}, msg string, args ....
function IsNotTypef (line 451) | func IsNotTypef(t TestingT, theType interface{}, object interface{}, msg...
function IsTypef (line 461) | func IsTypef(t TestingT, expectedType interface{}, object interface{}, m...
function JSONEqf (line 471) | func JSONEqf(t TestingT, expected string, actual string, msg string, arg...
function Lenf (line 482) | func Lenf(t TestingT, object interface{}, length int, msg string, args ....
function Lessf (line 494) | func Lessf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...
function LessOrEqualf (line 507) | func LessOrEqualf(t TestingT, e1 interface{}, e2 interface{}, msg string...
function Negativef (line 518) | func Negativef(t TestingT, e interface{}, msg string, args ...interface{...
function Neverf (line 529) | func Neverf(t TestingT, condition func() bool, waitFor time.Duration, ti...
function Nilf (line 539) | func Nilf(t TestingT, object interface{}, msg string, args ...interface{...
function NoDirExistsf (line 548) | func NoDirExistsf(t TestingT, path string, msg string, args ...interface...
function NoErrorf (line 561) | func NoErrorf(t TestingT, err error, msg string, args ...interface{}) bo...
function NoFileExistsf (line 570) | func NoFileExistsf(t TestingT, path string, msg string, args ...interfac...
function NotContainsf (line 583) | func NotContainsf(t TestingT, s interface{}, contains interface{}, msg s...
function NotElementsMatchf (line 600) | func NotElementsMatchf(t TestingT, listA interface{}, listB interface{},...
function NotEmptyf (line 612) | func NotEmptyf(t TestingT, object interface{}, msg string, args ...inter...
function NotEqualf (line 625) | func NotEqualf(t TestingT, expected interface{}, actual interface{}, msg...
function NotEqualValuesf (line 635) | func NotEqualValuesf(t TestingT, expected interface{}, actual interface{...
function NotErrorAsf (line 644) | func NotErrorAsf(t TestingT, err error, target interface{}, msg string, ...
function NotErrorIsf (line 653) | func NotErrorIsf(t TestingT, err error, target error, msg string, args ....
function NotImplementsf (line 663) | func NotImplementsf(t TestingT, interfaceObject interface{}, object inte...
function NotNilf (line 673) | func NotNilf(t TestingT, object interface{}, msg string, args ...interfa...
function NotPanicsf (line 683) | func NotPanicsf(t TestingT, f PanicTestFunc, msg string, args ...interfa...
function NotRegexpf (line 694) | func NotRegexpf(t TestingT, rx interface{}, str interface{}, msg string,...
function NotSamef (line 707) | func NotSamef(t TestingT, expected interface{}, actual interface{}, msg ...
function NotSubsetf (line 723) | func NotSubsetf(t TestingT, list interface{}, subset interface{}, msg st...
function NotZerof (line 731) | func NotZerof(t TestingT, i interface{}, msg string, args ...interface{}...
function Panicsf (line 741) | func Panicsf(t TestingT, f PanicTestFunc, msg string, args ...interface{...
function PanicsWithErrorf (line 753) | func PanicsWithErrorf(t TestingT, errString string, f PanicTestFunc, msg...
function PanicsWithValuef (line 764) | func PanicsWithValuef(t TestingT, expected interface{}, f PanicTestFunc,...
function Positivef (line 775) | func Positivef(t TestingT, e interface{}, msg string, args ...interface{...
function Regexpf (line 786) | func Regexpf(t TestingT, rx interface{}, str interface{}, msg string, ar...
function Samef (line 799) | func Samef(t TestingT, expected interface{}, actual interface{}, msg str...
function Subsetf (line 815) | func Subsetf(t TestingT, list interface{}, subset interface{}, msg strin...
function Truef (line 825) | func Truef(t TestingT, value bool, msg string, args ...interface{}) bool {
function WithinDurationf (line 835) | func WithinDurationf(t TestingT, expected time.Time, actual time.Time, d...
function WithinRangef (line 845) | func WithinRangef(t TestingT, actual time.Time, start time.Time, end tim...
function YAMLEqf (line 853) | func YAMLEqf(t TestingT, expected string, actual string, msg string, arg...
function Zerof (line 861) | func Zerof(t TestingT, i interface{}, msg string, args ...interface{}) b...
FILE: vendor/github.com/stretchr/testify/assert/assertion_forward.go
method Condition (line 12) | func (a *Assertions) Condition(comp Comparison, msgAndArgs ...interface{...
method Conditionf (line 20) | func (a *Assertions) Conditionf(comp Comparison, msg string, args ...int...
method Contains (line 33) | func (a *Assertions) Contains(s interface{}, contains interface{}, msgAn...
method Containsf (line 46) | func (a *Assertions) Containsf(s interface{}, contains interface{}, msg ...
method DirExists (line 55) | func (a *Assertions) DirExists(path string, msgAndArgs ...interface{}) b...
method DirExistsf (line 64) | func (a *Assertions) DirExistsf(path string, msg string, args ...interfa...
method ElementsMatch (line 76) | func (a *Assertions) ElementsMatch(listA interface{}, listB interface{},...
method ElementsMatchf (line 88) | func (a *Assertions) ElementsMatchf(listA interface{}, listB interface{}...
method Empty (line 108) | func (a *Assertions) Empty(object interface{}, msgAndArgs ...interface{}...
method Emptyf (line 128) | func (a *Assertions) Emptyf(object interface{}, msg string, args ...inte...
method Equal (line 142) | func (a *Assertions) Equal(expected interface{}, actual interface{}, msg...
method EqualError (line 154) | func (a *Assertions) EqualError(theError error, errString string, msgAnd...
method EqualErrorf (line 166) | func (a *Assertions) EqualErrorf(theError error, errString string, msg s...
method EqualExportedValues (line 183) | func (a *Assertions) EqualExportedValues(expected interface{}, actual in...
method EqualExportedValuesf (line 200) | func (a *Assertions) EqualExportedValuesf(expected interface{}, actual i...
method EqualValues (line 211) | func (a *Assertions) EqualValues(expected interface{}, actual interface{...
method EqualValuesf (line 222) | func (a *Assertions) EqualValuesf(expected interface{}, actual interface...
method Equalf (line 236) | func (a *Assertions) Equalf(expected interface{}, actual interface{}, ms...
method Error (line 247) | func (a *Assertions) Error(err error, msgAndArgs ...interface{}) bool {
method ErrorAs (line 256) | func (a *Assertions) ErrorAs(err error, target interface{}, msgAndArgs ....
method ErrorAsf (line 265) | func (a *Assertions) ErrorAsf(err error, target interface{}, msg string,...
method ErrorContains (line 277) | func (a *Assertions) ErrorContains(theError error, contains string, msgA...
method ErrorContainsf (line 289) | func (a *Assertions) ErrorContainsf(theError error, contains string, msg...
method ErrorIs (line 298) | func (a *Assertions) ErrorIs(err error, target error, msgAndArgs ...inte...
method ErrorIsf (line 307) | func (a *Assertions) ErrorIsf(err error, target error, msg string, args ...
method Errorf (line 318) | func (a *Assertions) Errorf(err error, msg string, args ...interface{}) ...
method Eventually (line 329) | func (a *Assertions) Eventually(condition func() bool, waitFor time.Dura...
method EventuallyWithT (line 354) | func (a *Assertions) EventuallyWithT(condition func(collect *CollectT), ...
method EventuallyWithTf (line 379) | func (a *Assertions) EventuallyWithTf(condition func(collect *CollectT),...
method Eventuallyf (line 390) | func (a *Assertions) Eventuallyf(condition func() bool, waitFor time.Dur...
method Exactly (line 400) | func (a *Assertions) Exactly(expected interface{}, actual interface{}, m...
method Exactlyf (line 410) | func (a *Assertions) Exactlyf(expected interface{}, actual interface{}, ...
method Fail (line 418) | func (a *Assertions) Fail(failureMessage string, msgAndArgs ...interface...
method FailNow (line 426) | func (a *Assertions) FailNow(failureMessage string, msgAndArgs ...interf...
method FailNowf (line 434) | func (a *Assertions) FailNowf(failureMessage string, msg string, args .....
method Failf (line 442) | func (a *Assertions) Failf(failureMessage string, msg string, args ...in...
method False (line 452) | func (a *Assertions) False(value bool, msgAndArgs ...interface{}) bool {
method Falsef (line 462) | func (a *Assertions) Falsef(value bool, msg string, args ...interface{})...
method FileExists (line 471) | func (a *Assertions) FileExists(path string, msgAndArgs ...interface{}) ...
method FileExistsf (line 480) | func (a *Assertions) FileExistsf(path string, msg string, args ...interf...
method Greater (line 492) | func (a *Assertions) Greater(e1 interface{}, e2 interface{}, msgAndArgs ...
method GreaterOrEqual (line 505) | func (a *Assertions) GreaterOrEqual(e1 interface{}, e2 interface{}, msgA...
method GreaterOrEqualf (line 518) | func (a *Assertions) GreaterOrEqualf(e1 interface{}, e2 interface{}, msg...
method Greaterf (line 530) | func (a *Assertions) Greaterf(e1 interface{}, e2 interface{}, msg string...
method HTTPBodyContains (line 543) | func (a *Assertions) HTTPBodyContains(handler http.HandlerFunc, method s...
method HTTPBodyContainsf (line 556) | func (a *Assertions) HTTPBodyContainsf(handler http.HandlerFunc, method ...
method HTTPBodyNotContains (line 569) | func (a *Assertions) HTTPBodyNotContains(handler http.HandlerFunc, metho...
method HTTPBodyNotContainsf (line 582) | func (a *Assertions) HTTPBodyNotContainsf(handler http.HandlerFunc, meth...
method HTTPError (line 594) | func (a *Assertions) HTTPError(handler http.HandlerFunc, method string, ...
method HTTPErrorf (line 606) | func (a *Assertions) HTTPErrorf(handler http.HandlerFunc, method string,...
method HTTPRedirect (line 618) | func (a *Assertions) HTTPRedirect(handler http.HandlerFunc, method strin...
method HTTPRedirectf (line 630) | func (a *Assertions) HTTPRedirectf(handler http.HandlerFunc, method stri...
method HTTPStatusCode (line 642) | func (a *Assertions) HTTPStatusCode(handler http.HandlerFunc, method str...
method HTTPStatusCodef (line 654) | func (a *Assertions) HTTPStatusCodef(handler http.HandlerFunc, method st...
method HTTPSuccess (line 666) | func (a *Assertions) HTTPSuccess(handler http.HandlerFunc, method string...
method HTTPSuccessf (line 678) | func (a *Assertions) HTTPSuccessf(handler http.HandlerFunc, method strin...
method Implements (line 688) | func (a *Assertions) Implements(interfaceObject interface{}, object inte...
method Implementsf (line 698) | func (a *Assertions) Implementsf(interfaceObject interface{}, object int...
method InDelta (line 708) | func (a *Assertions) InDelta(expected interface{}, actual interface{}, d...
method InDeltaMapValues (line 716) | func (a *Assertions) InDeltaMapValues(expected interface{}, actual inter...
method InDeltaMapValuesf (line 724) | func (a *Assertions) InDeltaMapValuesf(expected interface{}, actual inte...
method InDeltaSlice (line 732) | func (a *Assertions) InDeltaSlice(expected interface{}, actual interface...
method InDeltaSlicef (line 740) | func (a *Assertions) InDeltaSlicef(expected interface{}, actual interfac...
method InDeltaf (line 750) | func (a *Assertions) InDeltaf(expected interface{}, actual interface{}, ...
method InEpsilon (line 758) | func (a *Assertions) InEpsilon(expected interface{}, actual interface{},...
method InEpsilonSlice (line 766) | func (a *Assertions) InEpsilonSlice(expected interface{}, actual interfa...
method InEpsilonSlicef (line 774) | func (a *Assertions) InEpsilonSlicef(expected interface{}, actual interf...
method InEpsilonf (line 782) | func (a *Assertions) InEpsilonf(expected interface{}, actual interface{}...
method IsDecreasing (line 794) | func (a *Assertions) IsDecreasing(object interface{}, msgAndArgs ...inte...
method IsDecreasingf (line 806) | func (a *Assertions) IsDecreasingf(object interface{}, msg string, args ...
method IsIncreasing (line 818) | func (a *Assertions) IsIncreasing(object interface{}, msgAndArgs ...inte...
method IsIncreasingf (line 830) | func (a *Assertions) IsIncreasingf(object interface{}, msg string, args ...
method IsNonDecreasing (line 842) | func (a *Assertions) IsNonDecreasing(object interface{}, msgAndArgs ...i...
method IsNonDecreasingf (line 854) | func (a *Assertions) IsNonDecreasingf(object interface{}, msg string, ar...
method IsNonIncreasing (line 866) | func (a *Assertions) IsNonIncreasing(object interface{}, msgAndArgs ...i...
method IsNonIncreasingf (line 878) | func (a *Assertions) IsNonIncreasingf(object interface{}, msg string, ar...
method IsNotType (line 888) | func (a *Assertions) IsNotType(theType interface{}, object interface{}, ...
method IsNotTypef (line 898) | func (a *Assertions) IsNotTypef(theType interface{}, object interface{},...
method IsType (line 908) | func (a *Assertions) IsType(expectedType interface{}, object interface{}...
method IsTypef (line 918) | func (a *Assertions) IsTypef(expectedType interface{}, object interface{...
method JSONEq (line 928) | func (a *Assertions) JSONEq(expected string, actual string, msgAndArgs ....
method JSONEqf (line 938) | func (a *Assertions) JSONEqf(expected string, actual string, msg string,...
method Len (line 949) | func (a *Assertions) Len(object interface{}, length int, msgAndArgs ...i...
method Lenf (line 960) | func (a *Assertions) Lenf(object interface{}, length int, msg string, ar...
method Less (line 972) | func (a *Assertions) Less(e1 interface{}, e2 interface{}, msgAndArgs ......
method LessOrEqual (line 985) | func (a *Assertions) LessOrEqual(e1 interface{}, e2 interface{}, msgAndA...
method LessOrEqualf (line 998) | func (a *Assertions) LessOrEqualf(e1 interface{}, e2 interface{}, msg st...
method Lessf (line 1010) | func (a *Assertions) Lessf(e1 interface{}, e2 interface{}, msg string, a...
method Negative (line 1021) | func (a *Assertions) Negative(e interface{}, msgAndArgs ...interface{}) ...
method Negativef (line 1032) | func (a *Assertions) Negativef(e interface{}, msg string, args ...interf...
method Never (line 1043) | func (a *Assertions) Never(condition func() bool, waitFor time.Duration,...
method Neverf (line 1054) | func (a *Assertions) Neverf(condition func() bool, waitFor time.Duration...
method Nil (line 1064) | func (a *Assertions) Nil(object interface{}, msgAndArgs ...interface{}) ...
method Nilf (line 1074) | func (a *Assertions) Nilf(object interface{}, msg string, args ...interf...
method NoDirExists (line 1083) | func (a *Assertions) NoDirExists(path string, msgAndArgs ...interface{})...
method NoDirExistsf (line 1092) | func (a *Assertions) NoDirExistsf(path string, msg string, args ...inter...
method NoError (line 1105) | func (a *Assertions) NoError(err error, msgAndArgs ...interface{}) bool {
method NoErrorf (line 1118) | func (a *Assertions) NoErrorf(err error, msg string, args ...interface{}...
method NoFileExists (line 1127) | func (a *Assertions) NoFileExists(path string, msgAndArgs ...interface{}...
method NoFileExistsf (line 1136) | func (a *Assertions) NoFileExistsf(path string, msg string, args ...inte...
method NotContains (line 1149) | func (a *Assertions) NotContains(s interface{}, contains interface{}, ms...
method NotContainsf (line 1162) | func (a *Assertions) NotContainsf(s interface{}, contains interface{}, m...
method NotElementsMatch (line 1179) | func (a *Assertions) NotElementsMatch(listA interface{}, listB interface...
method NotElementsMatchf (line 1196) | func (a *Assertions) NotElementsMatchf(listA interface{}, listB interfac...
method NotEmpty (line 1208) | func (a *Assertions) NotEmpty(object interface{}, msgAndArgs ...interfac...
method NotEmptyf (line 1220) | func (a *Assertions) NotEmptyf(object interface{}, msg string, args ...i...
method NotEqual (line 1233) | func (a *Assertions) NotEqual(expected interface{}, actual interface{}, ...
method NotEqualValues (line 1243) | func (a *Assertions) NotEqualValues(expected interface{}, actual interfa...
method NotEqualValuesf (line 1253) | func (a *Assertions) NotEqualValuesf(expected interface{}, actual interf...
method NotEqualf (line 1266) | func (a *Assertions) NotEqualf(expected interface{}, actual interface{},...
method NotErrorAs (line 1275) | func (a *Assertions) NotErrorAs(err error, target interface{}, msgAndArg...
method NotErrorAsf (line 1284) | func (a *Assertions) NotErrorAsf(err error, target interface{}, msg stri...
method NotErrorIs (line 1293) | func (a *Assertions) NotErrorIs(err error, target error, msgAndArgs ...i...
method NotErrorIsf (line 1302) | func (a *Assertions) NotErrorIsf(err error, target error, msg string, ar...
method NotImplements (line 1312) | func (a *Assertions) NotImplements(interfaceObject interface{}, object i...
method NotImplementsf (line 1322) | func (a *Assertions) NotImplementsf(interfaceObject interface{}, object ...
method NotNil (line 1332) | func (a *Assertions) NotNil(object interface{}, msgAndArgs ...interface{...
method NotNilf (line 1342) | func (a *Assertions) NotNilf(object interface{}, msg string, args ...int...
method NotPanics (line 1352) | func (a *Assertions) NotPanics(f PanicTestFunc, msgAndArgs ...interface{...
method NotPanicsf (line 1362) | func (a *Assertions) NotPanicsf(f PanicTestFunc, msg string, args ...int...
method NotRegexp (line 1373) | func (a *Assertions) NotRegexp(rx interface{}, str interface{}, msgAndAr...
method NotRegexpf (line 1384) | func (a *Assertions) NotRegexpf(rx interface{}, str interface{}, msg str...
method NotSame (line 1397) | func (a *Assertions) NotSame(expected interface{}, actual interface{}, m...
method NotSamef (line 1410) | func (a *Assertions) NotSamef(expected interface{}, actual interface{}, ...
method NotSubset (line 1426) | func (a *Assertions) NotSubset(list interface{}, subset interface{}, msg...
method NotSubsetf (line 1442) | func (a *Assertions) NotSubsetf(list interface{}, subset interface{}, ms...
method NotZero (line 1450) | func (a *Assertions) NotZero(i interface{}, msgAndArgs ...interface{}) b...
method NotZerof (line 1458) | func (a *Assertions) NotZerof(i interface{}, msg string, args ...interfa...
method Panics (line 1468) | func (a *Assertions) Panics(f PanicTestFunc, msgAndArgs ...interface{}) ...
method PanicsWithError (line 1480) | func (a *Assertions) PanicsWithError(errString string, f PanicTestFunc, ...
method PanicsWithErrorf (line 1492) | func (a *Assertions) PanicsWithErrorf(errString string, f PanicTestFunc,...
method PanicsWithValue (line 1503) | func (a *Assertions) PanicsWithValue(expected interface{}, f PanicTestFu...
method PanicsWithValuef (line 1514) | func (a *Assertions) PanicsWithValuef(expected interface{}, f PanicTestF...
method Panicsf (line 1524) | func (a *Assertions) Panicsf(f PanicTestFunc, msg string, args ...interf...
method Positive (line 1535) | func (a *Assertions) Positive(e interface{}, msgAndArgs ...interface{}) ...
method Positivef (line 1546) | func (a *Assertions) Positivef(e interface{}, msg string, args ...interf...
method Regexp (line 1557) | func (a *Assertions) Regexp(rx interface{}, str interface{}, msgAndArgs ...
method Regexpf (line 1568) | func (a *Assertions) Regexpf(rx interface{}, str interface{}, msg string...
method Same (line 1581) | func (a *Assertions) Same(expected interface{}, actual interface{}, msgA...
method Samef (line 1594) | func (a *Assertions) Samef(expected interface{}, actual interface{}, msg...
method Subset (line 1610) | func (a *Assertions) Subset(list interface{}, subset interface{}, msgAnd...
method Subsetf (line 1626) | func (a *Assertions) Subsetf(list interface{}, subset interface{}, msg s...
method True (line 1636) | func (a *Assertions) True(value bool, msgAndArgs ...interface{}) bool {
method Truef (line 1646) | func (a *Assertions) Truef(value bool, msg string, args ...interface{}) ...
method WithinDuration (line 1656) | func (a *Assertions) WithinDuration(expected time.Time, actual time.Time...
method WithinDurationf (line 1666) | func (a *Assertions) WithinDurationf(expected time.Time, actual time.Tim...
method WithinRange (line 1676) | func (a *Assertions) WithinRange(actual time.Time, start time.Time, end ...
method WithinRangef (line 1686) | func (a *Assertions) WithinRangef(actual time.Time, start time.Time, end...
method YAMLEq (line 1694) | func (a *Assertions) YAMLEq(expected string, actual string, msgAndArgs ....
method YAMLEqf (line 1702) | func (a *Assertions) YAMLEqf(expected string, actual string, msg string,...
method Zero (line 1710) | func (a *Assertions) Zero(i interface{}, msgAndArgs ...interface{}) bool {
method Zerof (line 1718) | func (a *Assertions) Zerof(i interface{}, msg string, args ...interface{...
FILE: vendor/github.com/stretchr/testify/assert/assertion_order.go
function isOrdered (line 9) | func isOrdered(t TestingT, object interface{}, allowedComparesResults []...
function IsIncreasing (line 52) | func IsIncreasing(t TestingT, object interface{}, msgAndArgs ...interfac...
function IsNonIncreasing (line 61) | func IsNonIncreasing(t TestingT, object interface{}, msgAndArgs ...inter...
function IsDecreasing (line 70) | func IsDecreasing(t TestingT, object interface{}, msgAndArgs ...interfac...
function IsNonDecreasing (line 79) | func IsNonDecreasing(t TestingT, object interface{}, msgAndArgs ...inter...
FILE: vendor/github.com/stretchr/testify/assert/assertions.go
type TestingT (line 30) | type TestingT interface
type ComparisonAssertionFunc (line 36) | type ComparisonAssertionFunc
type ValueAssertionFunc (line 40) | type ValueAssertionFunc
type BoolAssertionFunc (line 44) | type BoolAssertionFunc
type ErrorAssertionFunc (line 48) | type ErrorAssertionFunc
type Comparison (line 55) | type Comparison
function ObjectsAreEqual (line 64) | func ObjectsAreEqual(expected, actual interface{}) bool {
function copyExportedFields (line 86) | func copyExportedFields(expected interface{}) interface{} {
function ObjectsExportedFieldsAreEqual (line 156) | func ObjectsExportedFieldsAreEqual(expected, actual interface{}) bool {
function ObjectsAreEqualValues (line 164) | func ObjectsAreEqualValues(expected, actual interface{}) bool {
function isNumericType (line 201) | func isNumericType(t reflect.Type) bool {
function CallerInfo (line 212) | func CallerInfo() []string {
function isTest (line 293) | func isTest(name, prefix string) bool {
function messageFromMsgAndArgs (line 304) | func messageFromMsgAndArgs(msgAndArgs ...interface{}) string {
function indentMessageLines (line 325) | func indentMessageLines(message string, longestLabelLen int) string {
type failNower (line 340) | type failNower interface
function FailNow (line 345) | func FailNow(t TestingT, failureMessage string, msgAndArgs ...interface{...
function Fail (line 366) | func Fail(t TestingT, failureMessage string, msgAndArgs ...interface{}) ...
type labeledContent (line 392) | type labeledContent struct
function labeledOutput (line 406) | func labeledOutput(content ...labeledContent) string {
function Implements (line 423) | func Implements(t TestingT, interfaceObject interface{}, object interfac...
function NotImplements (line 442) | func NotImplements(t TestingT, interfaceObject interface{}, object inter...
function isType (line 458) | func isType(expectedType, object interface{}) bool {
function IsType (line 465) | func IsType(t TestingT, expectedType, object interface{}, msgAndArgs ......
function IsNotType (line 478) | func IsNotType(t TestingT, theType, object interface{}, msgAndArgs ...in...
function Equal (line 495) | func Equal(t TestingT, expected, actual interface{}, msgAndArgs ...inter...
function validateEqualArgs (line 517) | func validateEqualArgs(expected, actual interface{}) error {
function Same (line 534) | func Same(t TestingT, expected, actual interface{}, msgAndArgs ...interf...
function NotSame (line 561) | func NotSame(t TestingT, expected, actual interface{}, msgAndArgs ...int...
function samePointers (line 584) | func samePointers(first, second interface{}) (same bool, ok bool) {
function formatUnequalValues (line 605) | func formatUnequalValues(expected, actual interface{}) (e string, a stri...
function truncatingFormat (line 621) | func truncatingFormat(data interface{}) string {
function EqualValues (line 634) | func EqualValues(t TestingT, expected, actual interface{}, msgAndArgs .....
function EqualExportedValues (line 660) | func EqualExportedValues(t TestingT, expected, actual interface{}, msgAn...
function Exactly (line 689) | func Exactly(t TestingT, expected, actual interface{}, msgAndArgs ...int...
function NotNil (line 707) | func NotNil(t TestingT, object interface{}, msgAndArgs ...interface{}) b...
function isNil (line 718) | func isNil(object interface{}) bool {
function Nil (line 739) | func Nil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
function isEmpty (line 750) | func isEmpty(object interface{}) bool {
function isEmptyValue (line 760) | func isEmptyValue(objValue reflect.Value) bool {
function Empty (line 790) | func Empty(t TestingT, object interface{}, msgAndArgs ...interface{}) bo...
function NotEmpty (line 807) | func NotEmpty(t TestingT, object interface{}, msgAndArgs ...interface{})...
function getLen (line 821) | func getLen(x interface{}) (length int, ok bool) {
function Len (line 833) | func Len(t TestingT, object interface{}, length int, msgAndArgs ...inter...
function True (line 851) | func True(t TestingT, value bool, msgAndArgs ...interface{}) bool {
function False (line 865) | func False(t TestingT, value bool, msgAndArgs ...interface{}) bool {
function NotEqual (line 882) | func NotEqual(t TestingT, expected, actual interface{}, msgAndArgs ...in...
function NotEqualValues (line 901) | func NotEqualValues(t TestingT, expected, actual interface{}, msgAndArgs...
function containsElement (line 917) | func containsElement(list interface{}, element interface{}) (ok, found b...
function Contains (line 960) | func Contains(t TestingT, s, contains interface{}, msgAndArgs ...interfa...
function NotContains (line 982) | func NotContains(t TestingT, s, contains interface{}, msgAndArgs ...inte...
function Subset (line 1007) | func Subset(t TestingT, list, subset interface{}, msgAndArgs ...interfac...
function NotSubset (line 1075) | func NotSubset(t TestingT, list, subset interface{}, msgAndArgs ...inter...
function ElementsMatch (line 1139) | func ElementsMatch(t TestingT, listA, listB interface{}, msgAndArgs ...i...
function isList (line 1161) | func isList(t TestingT, list interface{}, msgAndArgs ...interface{}) (ok...
function diffLists (line 1173) | func diffLists(listA, listB interface{}) (extraA, extraB []interface{}) {
function formatListDiff (line 1210) | func formatListDiff(listA, listB interface{}, extraA, extraB []interface...
function NotElementsMatch (line 1240) | func NotElementsMatch(t TestingT, listA, listB interface{}, msgAndArgs ....
function Condition (line 1264) | func Condition(t TestingT, comp Comparison, msgAndArgs ...interface{}) b...
type PanicTestFunc (line 1277) | type PanicTestFunc
function didPanic (line 1280) | func didPanic(f PanicTestFunc) (didPanic bool, message interface{}, stac...
function Panics (line 1300) | func Panics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool {
function PanicsWithValue (line 1316) | func PanicsWithValue(t TestingT, expected interface{}, f PanicTestFunc, ...
function PanicsWithError (line 1337) | func PanicsWithError(t TestingT, errString string, f PanicTestFunc, msgA...
function NotPanics (line 1357) | func NotPanics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) b...
function WithinDuration (line 1372) | func WithinDuration(t TestingT, expected, actual time.Time, delta time.D...
function WithinRange (line 1388) | func WithinRange(t TestingT, actual, start, end time.Time, msgAndArgs .....
function toFloat (line 1406) | func toFloat(x interface{}) (float64, bool) {
function InDelta (line 1447) | func InDelta(t TestingT, expected, actual interface{}, delta float64, ms...
function InDeltaSlice (line 1480) | func InDeltaSlice(t TestingT, expected, actual interface{}, delta float6...
function InDeltaMapValues (line 1504) | func InDeltaMapValues(t TestingT, expected, actual interface{}, delta fl...
function calcRelativeError (line 1547) | func calcRelativeError(expected, actual interface{}) (float64, error) {
function InEpsilon (line 1570) | func InEpsilon(t TestingT, expected, actual interface{}, epsilon float64...
function InEpsilonSlice (line 1593) | func InEpsilonSlice(t TestingT, expected, actual interface{}, epsilon fl...
function NoError (line 1633) | func NoError(t TestingT, err error, msgAndArgs ...interface{}) bool {
function Error (line 1648) | func Error(t TestingT, err error, msgAndArgs ...interface{}) bool {
function EqualError (line 1664) | func EqualError(t TestingT, theError error, errString string, msgAndArgs...
function ErrorContains (line 1687) | func ErrorContains(t TestingT, theError error, contains string, msgAndAr...
function matchRegexp (line 1704) | func matchRegexp(rx interface{}, str interface{}) bool {
function Regexp (line 1726) | func Regexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...i...
function NotRegexp (line 1744) | func NotRegexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ....
function Zero (line 1758) | func Zero(t TestingT, i interface{}, msgAndArgs ...interface{}) bool {
function NotZero (line 1769) | func NotZero(t TestingT, i interface{}, msgAndArgs ...interface{}) bool {
function FileExists (line 1781) | func FileExists(t TestingT, path string, msgAndArgs ...interface{}) bool {
function NoFileExists (line 1800) | func NoFileExists(t TestingT, path string, msgAndArgs ...interface{}) bo...
function DirExists (line 1816) | func DirExists(t TestingT, path string, msgAndArgs ...interface{}) bool {
function NoDirExists (line 1835) | func NoDirExists(t TestingT, path string, msgAndArgs ...interface{}) bool {
function JSONEq (line 1855) | func JSONEq(t TestingT, expected string, actual string, msgAndArgs ...in...
function YAMLEq (line 1878) | func YAMLEq(t TestingT, expected string, actual string, msgAndArgs ...in...
function typeAndKind (line 1900) | func typeAndKind(v interface{}) (reflect.Type, reflect.Kind) {
function diff (line 1913) | func diff(expected interface{}, actual interface{}) string {
function isFunction (line 1956) | func isFunction(arg interface{}) bool {
function Eventually (line 1988) | func Eventually(t TestingT, condition func() bool, waitFor time.Duration...
type CollectT (line 2024) | type CollectT struct
method Helper (line 2032) | func (CollectT) Helper() {}
method Errorf (line 2035) | func (c *CollectT) Errorf(format string, args ...interface{}) {
method FailNow (line 2040) | func (c *CollectT) FailNow() {
method Reset (line 2046) | func (*CollectT) Reset() {
method Copy (line 2051) | func (*CollectT) Copy(TestingT) {
method fail (line 2055) | func (c *CollectT) fail() {
method failed (line 2061) | func (c *CollectT) failed() bool {
function EventuallyWithT (line 2083) | func EventuallyWithT(t TestingT, condition func(collect *CollectT), wait...
function Never (line 2135) | func Never(t TestingT, condition func() bool, waitFor time.Duration, tic...
function ErrorIs (line 2172) | func ErrorIs(t TestingT, err, target error, msgAndArgs ...interface{}) b...
function NotErrorIs (line 2198) | func NotErrorIs(t TestingT, err, target error, msgAndArgs ...interface{}...
function ErrorAs (line 2221) | func ErrorAs(t TestingT, err error, target interface{}, msgAndArgs ...in...
function NotErrorAs (line 2245) | func NotErrorAs(t TestingT, err error, target interface{}, msgAndArgs .....
function unwrapAll (line 2261) | func unwrapAll(err error) (errs []error) {
function buildErrorChainString (line 2278) | func buildErrorChainString(err error, withType bool) string {
FILE: vendor/github.com/stretchr/testify/assert/forward_assertions.go
type Assertions (line 5) | type Assertions struct
function New (line 10) | func New(t TestingT) *Assertions {
FILE: vendor/github.com/stretchr/testify/assert/http_assertions.go
function httpCode (line 13) | func httpCode(handler http.HandlerFunc, method, url string, values url.V...
function HTTPSuccess (line 29) | func HTTPSuccess(t TestingT, handler http.HandlerFunc, method, url strin...
function HTTPRedirect (line 51) | func HTTPRedirect(t TestingT, handler http.HandlerFunc, method, url stri...
function HTTPError (line 73) | func HTTPError(t TestingT, handler http.HandlerFunc, method, url string,...
function HTTPStatusCode (line 95) | func HTTPStatusCode(t TestingT, handler http.HandlerFunc, method, url st...
function HTTPBody (line 114) | func HTTPBody(handler http.HandlerFunc, method, url string, values url.V...
function HTTPBodyContains (line 133) | func HTTPBodyContains(t TestingT, handler http.HandlerFunc, method, url ...
function HTTPBodyNotContains (line 153) | func HTTPBodyNotContains(t TestingT, handler http.HandlerFunc, method, u...
FILE: vendor/github.com/stretchr/testify/assert/yaml/yaml_default.go
function Unmarshal (line 34) | func Unmarshal(in []byte, out interface{}) error {
FILE: vendor/github.com/stretchr/testify/assert/yaml/yaml_fail.go
function Unmarshal (line 15) | func Unmarshal([]byte, interface{}) error {
FILE: vendor/github.com/stretchr/testify/require/forward_requirements.go
type Assertions (line 5) | type Assertions struct
function New (line 10) | func New(t TestingT) *Assertions {
FILE: vendor/github.com/stretchr/testify/require/require.go
function Condition (line 13) | func Condition(t TestingT, comp assert.Comparison, msgAndArgs ...interfa...
function Conditionf (line 24) | func Conditionf(t TestingT, comp assert.Comparison, msg string, args ......
function Contains (line 40) | func Contains(t TestingT, s interface{}, contains interface{}, msgAndArg...
function Containsf (line 56) | func Containsf(t TestingT, s interface{}, contains interface{}, msg stri...
function DirExists (line 68) | func DirExists(t TestingT, path string, msgAndArgs ...interface{}) {
function DirExistsf (line 80) | func DirExistsf(t TestingT, path string, msg string, args ...interface{}) {
function ElementsMatch (line 95) | func ElementsMatch(t TestingT, listA interface{}, listB interface{}, msg...
function ElementsMatchf (line 110) | func ElementsMatchf(t TestingT, listA interface{}, listB interface{}, ms...
function Empty (line 133) | func Empty(t TestingT, object interface{}, msgAndArgs ...interface{}) {
function Emptyf (line 156) | func Emptyf(t TestingT, object interface{}, msg string, args ...interfac...
function Equal (line 173) | func Equal(t TestingT, expected interface{}, actual interface{}, msgAndA...
function EqualError (line 188) | func EqualError(t TestingT, theError error, errString string, msgAndArgs...
function EqualErrorf (line 203) | func EqualErrorf(t TestingT, theError error, errString string, msg strin...
function EqualExportedValues (line 223) | func EqualExportedValues(t TestingT, expected interface{}, actual interf...
function EqualExportedValuesf (line 243) | func EqualExportedValuesf(t TestingT, expected interface{}, actual inter...
function EqualValues (line 257) | func EqualValues(t TestingT, expected interface{}, actual interface{}, m...
function EqualValuesf (line 271) | func EqualValuesf(t TestingT, expected interface{}, actual interface{}, ...
function Equalf (line 288) | func Equalf(t TestingT, expected interface{}, actual interface{}, msg st...
function Error (line 302) | func Error(t TestingT, err error, msgAndArgs ...interface{}) {
function ErrorAs (line 314) | func ErrorAs(t TestingT, err error, target interface{}, msgAndArgs ...in...
function ErrorAsf (line 326) | func ErrorAsf(t TestingT, err error, target interface{}, msg string, arg...
function ErrorContains (line 341) | func ErrorContains(t TestingT, theError error, contains string, msgAndAr...
function ErrorContainsf (line 356) | func ErrorContainsf(t TestingT, theError error, contains string, msg str...
function ErrorIs (line 368) | func ErrorIs(t TestingT, err error, target error, msgAndArgs ...interfac...
function ErrorIsf (line 380) | func ErrorIsf(t TestingT, err error, target error, msg string, args ...i...
function Errorf (line 394) | func Errorf(t TestingT, err error, msg string, args ...interface{}) {
function Eventually (line 408) | func Eventually(t TestingT, condition func() bool, waitFor time.Duration...
function EventuallyWithT (line 436) | func EventuallyWithT(t TestingT, condition func(collect *assert.CollectT...
function EventuallyWithTf (line 464) | func EventuallyWithTf(t TestingT, condition func(collect *assert.Collect...
function Eventuallyf (line 478) | func Eventuallyf(t TestingT, condition func() bool, waitFor time.Duratio...
function Exactly (line 491) | func Exactly(t TestingT, expected interface{}, actual interface{}, msgAn...
function Exactlyf (line 504) | func Exactlyf(t TestingT, expected interface{}, actual interface{}, msg ...
function Fail (line 515) | func Fail(t TestingT, failureMessage string, msgAndArgs ...interface{}) {
function FailNow (line 526) | func FailNow(t TestingT, failureMessage string, msgAndArgs ...interface{...
function FailNowf (line 537) | func FailNowf(t TestingT, failureMessage string, msg string, args ...int...
function Failf (line 548) | func Failf(t TestingT, failureMessage string, msg string, args ...interf...
function False (line 561) | func False(t TestingT, value bool, msgAndArgs ...interface{}) {
function Falsef (line 574) | func Falsef(t TestingT, value bool, msg string, args ...interface{}) {
function FileExists (line 586) | func FileExists(t TestingT, path string, msgAndArgs ...interface{}) {
function FileExistsf (line 598) | func FileExistsf(t TestingT, path string, msg string, args ...interface{...
function Greater (line 613) | func Greater(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...i...
function GreaterOrEqual (line 629) | func GreaterOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndAr...
function GreaterOrEqualf (line 645) | func GreaterOrEqualf(t TestingT, e1 interface{}, e2 interface{}, msg str...
function Greaterf (line 660) | func Greaterf(t TestingT, e1 interface{}, e2 interface{}, msg string, ar...
function HTTPBodyContains (line 676) | func HTTPBodyContains(t TestingT, handler http.HandlerFunc, method strin...
function HTTPBodyContainsf (line 692) | func HTTPBodyContainsf(t TestingT, handler http.HandlerFunc, method stri...
function HTTPBodyNotContains (line 708) | func HTTPBodyNotContains(t TestingT, handler http.HandlerFunc, method st...
function HTTPBodyNotContainsf (line 724) | func HTTPBodyNotContainsf(t TestingT, handler http.HandlerFunc, method s...
function HTTPError (line 739) | func HTTPError(t TestingT, handler http.HandlerFunc, method string, url ...
function HTTPErrorf (line 754) | func HTTPErrorf(t TestingT, handler http.HandlerFunc, method string, url...
function HTTPRedirect (line 769) | func HTTPRedirect(t TestingT, handler http.HandlerFunc, method string, u...
function HTTPRedirectf (line 784) | func HTTPRedirectf(t TestingT, handler http.HandlerFunc, method string, ...
function HTTPStatusCode (line 799) | func HTTPStatusCode(t TestingT, handler http.HandlerFunc, method string,...
function HTTPStatusCodef (line 814) | func HTTPStatusCodef(t TestingT, handler http.HandlerFunc, method string...
function HTTPSuccess (line 829) | func HTTPSuccess(t TestingT, handler http.HandlerFunc, method string, ur...
function HTTPSuccessf (line 844) | func HTTPSuccessf(t TestingT, handler http.HandlerFunc, method string, u...
function Implements (line 857) | func Implements(t TestingT, interfaceObject interface{}, object interfac...
function Implementsf (line 870) | func Implementsf(t TestingT, interfaceObject interface{}, object interfa...
function InDelta (line 883) | func InDelta(t TestingT, expected interface{}, actual interface{}, delta...
function InDeltaMapValues (line 894) | func InDeltaMapValues(t TestingT, expected interface{}, actual interface...
function InDeltaMapValuesf (line 905) | func InDeltaMapValuesf(t TestingT, expected interface{}, actual interfac...
function InDeltaSlice (line 916) | func InDeltaSlice(t TestingT, expected interface{}, actual interface{}, ...
function InDeltaSlicef (line 927) | func InDeltaSlicef(t TestingT, expected interface{}, actual interface{},...
function InDeltaf (line 940) | func InDeltaf(t TestingT, expected interface{}, actual interface{}, delt...
function InEpsilon (line 951) | func InEpsilon(t TestingT, expected interface{}, actual interface{}, eps...
function InEpsilonSlice (line 962) | func InEpsilonSlice(t TestingT, expected interface{}, actual interface{}...
function InEpsilonSlicef (line 973) | func InEpsilonSlicef(t TestingT, expected interface{}, actual interface{...
function InEpsilonf (line 984) | func InEpsilonf(t TestingT, expected interface{}, actual interface{}, ep...
function IsDecreasing (line 999) | func IsDecreasing(t TestingT, object interface{}, msgAndArgs ...interfac...
function IsDecreasingf (line 1014) | func IsDecreasingf(t TestingT, object interface{}, msg string, args ...i...
function IsIncreasing (line 1029) | func IsIncreasing(t TestingT, object interface{}, msgAndArgs ...interfac...
function IsIncreasingf (line 1044) | func IsIncreasingf(t TestingT, object interface{}, msg string, args ...i...
function IsNonDecreasing (line 1059) | func IsNonDecreasing(t TestingT, object interface{}, msgAndArgs ...inter...
function IsNonDecreasingf (line 1074) | func IsNonDecreasingf(t TestingT, object interface{}, msg string, args ....
function IsNonIncreasing (line 1089) | func IsNonIncreasing(t TestingT, object interface{}, msgAndArgs ...inter...
function IsNonIncreasingf (line 1104) | func IsNonIncreasingf(t TestingT, object interface{}, msg string, args ....
function IsNotType (line 1117) | func IsNotType(t TestingT, theType interface{}, object interface{}, msgA...
function IsNotTypef (line 1130) | func IsNotTypef(t TestingT, theType interface{}, object interface{}, msg...
function IsType (line 1143) | func IsType(t TestingT, expectedType interface{}, object interface{}, ms...
function IsTypef (line 1156) | func IsTypef(t TestingT, expectedType interface{}, object interface{}, m...
function JSONEq (line 1169) | func JSONEq(t TestingT, expected string, actual string, msgAndArgs ...in...
function JSONEqf (line 1182) | func JSONEqf(t TestingT, expected string, actual string, msg string, arg...
function Len (line 1196) | func Len(t TestingT, object interface{}, length int, msgAndArgs ...inter...
function Lenf (line 1210) | func Lenf(t TestingT, object interface{}, length int, msg string, args ....
function Less (line 1225) | func Less(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...inte...
function LessOrEqual (line 1241) | func LessOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...
function LessOrEqualf (line 1257) | func LessOrEqualf(t TestingT, e1 interface{}, e2 interface{}, msg string...
function Lessf (line 1272) | func Lessf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...
function Negative (line 1286) | func Negative(t TestingT, e interface{}, msgAndArgs ...interface{}) {
function Negativef (line 1300) | func Negativef(t TestingT, e interface{}, msg string, args ...interface{...
function Never (line 1314) | func Never(t TestingT, condition func() bool, waitFor time.Duration, tic...
function Neverf (line 1328) | func Neverf(t TestingT, condition func() bool, waitFor time.Duration, ti...
function Nil (line 1341) | func Nil(t TestingT, object interface{}, msgAndArgs ...interface{}) {
function Nilf (line 1354) | func Nilf(t TestingT, object interface{}, msg string, args ...interface{...
function NoDirExists (line 1366) | func NoDirExists(t TestingT, path string, msgAndArgs ...interface{}) {
function NoDirExistsf (line 1378) | func NoDirExistsf(t TestingT, path string, msg string, args ...interface...
function NoError (line 1394) | func NoError(t TestingT, err error, msgAndArgs ...interface{}) {
function NoErrorf (line 1410) | func NoErrorf(t TestingT, err error, msg string, args ...interface{}) {
function NoFileExists (line 1422) | func NoFileExists(t TestingT, path string, msgAndArgs ...interface{}) {
function NoFileExistsf (line 1434) | func NoFileExistsf(t TestingT, path string, msg string, args ...interfac...
function NotContains (line 1450) | func NotContains(t TestingT, s interface{}, contains interface{}, msgAnd...
function NotContainsf (line 1466) | func NotContainsf(t TestingT, s interface{}, contains interface{}, msg s...
function NotElementsMatch (line 1486) | func NotElementsMatch(t TestingT, listA interface{}, listB interface{}, ...
function NotElementsMatchf (line 1506) | func NotElementsMatchf(t TestingT, listA interface{}, listB interface{},...
function NotEmpty (line 1521) | func NotEmpty(t TestingT, object interface{}, msgAndArgs ...interface{}) {
function NotEmptyf (line 1536) | func NotEmptyf(t TestingT, object interface{}, msg string, args ...inter...
function NotEqual (line 1552) | func NotEqual(t TestingT, expected interface{}, actual interface{}, msgA...
function NotEqualValues (line 1565) | func NotEqualValues(t TestingT, expected interface{}, actual interface{}...
function NotEqualValuesf (line 1578) | func NotEqualValuesf(t TestingT, expected interface{}, actual interface{...
function NotEqualf (line 1594) | func NotEqualf(t TestingT, expected interface{}, actual interface{}, msg...
function NotErrorAs (line 1606) | func NotErrorAs(t TestingT, err error, target interface{}, msgAndArgs .....
function NotErrorAsf (line 1618) | func NotErrorAsf(t TestingT, err error, target interface{}, msg string, ...
function NotErrorIs (line 1630) | func NotErrorIs(t TestingT, err error, target error, msgAndArgs ...inter...
function NotErrorIsf (line 1642) | func NotErrorIsf(t TestingT, err error, target error, msg string, args ....
function NotImplements (line 1655) | func NotImplements(t TestingT, interfaceObject interface{}, object inter...
function NotImplementsf (line 1668) | func NotImplementsf(t TestingT, interfaceObject interface{}, object inte...
function NotNil (line 1681) | func NotNil(t TestingT, object interface{}, msgAndArgs ...interface{}) {
function NotNilf (line 1694) | func NotNilf(t TestingT, object interface{}, msg string, args ...interfa...
function NotPanics (line 1707) | func NotPanics(t TestingT, f assert.PanicTestFunc, msgAndArgs ...interfa...
function NotPanicsf (line 1720) | func NotPanicsf(t TestingT, f assert.PanicTestFunc, msg string, args ......
function NotRegexp (line 1734) | func NotRegexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ....
function NotRegexpf (line 1748) | func NotRegexpf(t TestingT, rx interface{}, str interface{}, msg string,...
function NotSame (line 1764) | func NotSame(t TestingT, expected interface{}, actual interface{}, msgAn...
function NotSamef (line 1780) | func NotSamef(t TestingT, expected interface{}, actual interface{}, msg ...
function NotSubset (line 1799) | func NotSubset(t TestingT, list interface{}, subset interface{}, msgAndA...
function NotSubsetf (line 1818) | func NotSubsetf(t TestingT, list interface{}, subset interface{}, msg st...
function NotZero (line 1829) | func NotZero(t TestingT, i interface{}, msgAndArgs ...interface{}) {
function NotZerof (line 1840) | func NotZerof(t TestingT, i interface{}, msg string, args ...interface{}) {
function Panics (line 1853) | func Panics(t TestingT, f assert.PanicTestFunc, msgAndArgs ...interface{...
function PanicsWithError (line 1868) | func PanicsWithError(t TestingT, errString string, f assert.PanicTestFun...
function PanicsWithErrorf (line 1883) | func PanicsWithErrorf(t TestingT, errString string, f assert.PanicTestFu...
function PanicsWithValue (line 1897) | func PanicsWithValue(t TestingT, expected interface{}, f assert.PanicTes...
function PanicsWithValuef (line 1911) | func PanicsWithValuef(t TestingT, expected interface{}, f assert.PanicTe...
function Panicsf (line 1924) | func Panicsf(t TestingT, f assert.PanicTestFunc, msg string, args ...int...
function Positive (line 1938) | func Positive(t TestingT, e interface{}, msgAndArgs ...interface{}) {
function Positivef (line 1952) | func Positivef(t TestingT, e interface{}, msg string, args ...interface{...
function Regexp (line 1966) | func Regexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...i...
function Regexpf (line 1980) | func Regexpf(t TestingT, rx interface{}, str interface{}, msg string, ar...
function Same (line 1996) | func Same(t TestingT, expected interface{}, actual interface{}, msgAndAr...
function Samef (line 2012) | func Samef(t TestingT, expected interface{}, actual interface{}, msg str...
function Subset (line 2031) | func Subset(t TestingT, list interface{}, subset interface{}, msgAndArgs...
function Subsetf (line 2050) | func Subsetf(t TestingT, list interface{}, subset interface{}, msg strin...
function True (line 2063) | func True(t TestingT, value bool, msgAndArgs ...interface{}) {
function Truef (line 2076) | func Truef(t TestingT, value bool, msg string, args ...interface{}) {
function WithinDuration (line 2089) | func WithinDuration(t TestingT, expected time.Time, actual time.Time, de...
function WithinDurationf (line 2102) | func WithinDurationf(t TestingT, expected time.Time, actual time.Time, d...
function WithinRange (line 2115) | func WithinRange(t TestingT, actual time.Time, start time.Time, end time...
function WithinRangef (line 2128) | func WithinRangef(t TestingT, actual time.Time, start time.Time, end tim...
function YAMLEq (line 2139) | func YAMLEq(t TestingT, expected string, actual string, msgAndArgs ...in...
function YAMLEqf (line 2150) | func YAMLEqf(t TestingT, expected string, actual string, msg string, arg...
function Zero (line 2161) | func Zero(t TestingT, i interface{}, msgAndArgs ...interface{}) {
function Zerof (line 2172) | func Zerof(t TestingT, i interface{}, msg string, args ...interface{}) {
FILE: vendor/github.com/stretchr/testify/require/require_forward.go
method Condition (line 13) | func (a *Assertions) Condition(comp assert.Comparison, msgAndArgs ...int...
method Conditionf (line 21) | func (a *Assertions) Conditionf(comp assert.Comparison, msg string, args...
method Contains (line 34) | func (a *Assertions) Contains(s interface{}, contains interface{}, msgAn...
method Containsf (line 47) | func (a *Assertions) Containsf(s interface{}, contains interface{}, msg ...
method DirExists (line 56) | func (a *Assertions) DirExists(path string, msgAndArgs ...interface{}) {
method DirExistsf (line 65) | func (a *Assertions) DirExistsf(path string, msg string, args ...interfa...
method ElementsMatch (line 77) | func (a *Assertions) ElementsMatch(listA interface{}, listB interface{},...
method ElementsMatchf (line 89) | func (a *Assertions) ElementsMatchf(listA interface{}, listB interface{}...
method Empty (line 109) | func (a *Assertions) Empty(object interface{}, msgAndArgs ...interface{}) {
method Emptyf (line 129) | func (a *Assertions) Emptyf(object interface{}, msg string, args ...inte...
method Equal (line 143) | func (a *Assertions) Equal(expected interface{}, actual interface{}, msg...
method EqualError (line 155) | func (a *Assertions) EqualError(theError error, errString string, msgAnd...
method EqualErrorf (line 167) | func (a *Assertions) EqualErrorf(theError error, errString string, msg s...
method EqualExportedValues (line 184) | func (a *Assertions) EqualExportedValues(expected interface{}, actual in...
method EqualExportedValuesf (line 201) | func (a *Assertions) EqualExportedValuesf(expected interface{}, actual i...
method EqualValues (line 212) | func (a *Assertions) EqualValues(expected interface{}, actual interface{...
method EqualValuesf (line 223) | func (a *Assertions) EqualValuesf(expected interface{}, actual interface...
method Equalf (line 237) | func (a *Assertions) Equalf(expected interface{}, actual interface{}, ms...
method Error (line 248) | func (a *Assertions) Error(err error, msgAndArgs ...interface{}) {
method ErrorAs (line 257) | func (a *Assertions) ErrorAs(err error, target interface{}, msgAndArgs ....
method ErrorAsf (line 266) | func (a *Assertions) ErrorAsf(err error, target interface{}, msg string,...
method ErrorContains (line 278) | func (a *Assertions) ErrorContains(theError error, contains string, msgA...
method ErrorContainsf (line 290) | func (a *Assertions) ErrorContainsf(theError error, contains string, msg...
method ErrorIs (line 299) | func (a *Assertions) ErrorIs(err error, target error, msgAndArgs ...inte...
method ErrorIsf (line 308) | func (a *Assertions) ErrorIsf(err error, target error, msg string, args ...
method Errorf (line 319) | func (a *Assertions) Errorf(err error, msg string, args ...interface{}) {
method Eventually (line 330) | func (a *Assertions) Eventually(condition func() bool, waitFor time.Dura...
method EventuallyWithT (line 355) | func (a *Assertions) EventuallyWithT(condition func(collect *assert.Coll...
method EventuallyWithTf (line 380) | func (a *Assertions) EventuallyWithTf(condition func(collect *assert.Col...
method Eventuallyf (line 391) | func (a *Assertions) Eventuallyf(condition func() bool, waitFor time.Dur...
method Exactly (line 401) | func (a *Assertions) Exactly(expected interface{}, actual interface{}, m...
method Exactlyf (line 411) | func (a *Assertions) Exactlyf(expected interface{}, actual interface{}, ...
method Fail (line 419) | func (a *Assertions) Fail(failureMessage string, msgAndArgs ...interface...
method FailNow (line 427) | func (a *Assertions) FailNow(failureMessage string, msgAndArgs ...interf...
method FailNowf (line 435) | func (a *Assertions) FailNowf(failureMessage string, msg string, args .....
method Failf (line 443) | func (a *Assertions) Failf(failureMessage string, msg string, args ...in...
method False (line 453) | func (a *Assertions) False(value bool, msgAndArgs ...interface{}) {
method Falsef (line 463) | func (a *Assertions) Falsef(value bool, msg string, args ...interface{}) {
method FileExists (line 472) | func (a *Assertions) FileExists(path string, msgAndArgs ...interface{}) {
method FileExistsf (line 481) | func (a *Assertions) FileExistsf(path string, msg string, args ...interf...
method Greater (line 493) | func (a *Assertions) Greater(e1 interface{}, e2 interface{}, msgAndArgs ...
method GreaterOrEqual (line 506) | func (a *Assertions) GreaterOrEqual(e1 interface{}, e2 interface{}, msgA...
method GreaterOrEqualf (line 519) | func (a *Assertions) GreaterOrEqualf(e1 interface{}, e2 interface{}, msg...
method Greaterf (line 531) | func (a *Assertions) Greaterf(e1 interface{}, e2 interface{}, msg string...
method HTTPBodyContains (line 544) | func (a *Assertions) HTTPBodyContains(handler http.HandlerFunc, method s...
method HTTPBodyContainsf (line 557) | func (a *Assertions) HTTPBodyContainsf(handler http.HandlerFunc, method ...
method HTTPBodyNotContains (line 570) | func (a *Assertions) HTTPBodyNotContains(handler http.HandlerFunc, metho...
method HTTPBodyNotContainsf (line 583) | func (a *Assertions) HTTPBodyNotContainsf(handler http.HandlerFunc, meth...
method HTTPError (line 595) | func (a *Assertions) HTTPError(handler http.HandlerFunc, method string, ...
method HTTPErrorf (line 607) | func (a *Assertions) HTTPErrorf(handler http.HandlerFunc, method string,...
method HTTPRedirect (line 619) | func (a *Assertions) HTTPRedirect(handler http.HandlerFunc, method strin...
method HTTPRedirectf (line 631) | func (a *Assertions) HTTPRedirectf(handler http.HandlerFunc, method stri...
method HTTPStatusCode (line 643) | func (a *Assertions) HTTPStatusCode(handler http.HandlerFunc, method str...
method HTTPStatusCodef (line 655) | func (a *Assertions) HTTPStatusCodef(handler http.HandlerFunc, method st...
method HTTPSuccess (line 667) | func (a *Assertions) HTTPSuccess(handler http.HandlerFunc, method string...
method HTTPSuccessf (line 679) | func (a *Assertions) HTTPSuccessf(handler http.HandlerFunc, method strin...
method Implements (line 689) | func (a *Assertions) Implements(interfaceObject interface{}, object inte...
method Implementsf (line 699) | func (a *Assertions) Implementsf(interfaceObject interface{}, object int...
method InDelta (line 709) | func (a *Assertions) InDelta(expected interface{}, actual interface{}, d...
method InDeltaMapValues (line 717) | func (a *Assertions) InDeltaMapValues(expected interface{}, actual inter...
method InDeltaMapValuesf (line 725) | func (a *Assertions) InDeltaMapValuesf(expected interface{}, actual inte...
method InDeltaSlice (line 733) | func (a *Assertions) InDeltaSlice(expected interface{}, actual interface...
method InDeltaSlicef (line 741) | func (a *Assertions) InDeltaSlicef(expected interface{}, actual interfac...
method InDeltaf (line 751) | func (a *Assertions) InDeltaf(expected interface{}, actual interface{}, ...
method InEpsilon (line 759) | func (a *Assertions) InEpsilon(expected interface{}, actual interface{},...
method InEpsilonSlice (line 767) | func (a *Assertions) InEpsilonSlice(expected interface{}, actual interfa...
method InEpsilonSlicef (line 775) | func (a *Assertions) InEpsilonSlicef(expected interface{}, actual interf...
method InEpsilonf (line 783) | func (a *Assertions) InEpsilonf(expected interface{}, actual interface{}...
method IsDecreasing (line 795) | func (a *Assertions) IsDecreasing(object interface{}, msgAndArgs ...inte...
method IsDecreasingf (line 807) | func (a *Assertions) IsDecreasingf(object interface{}, msg string, args ...
method IsIncreasing (line 819) | func (a *Assertions) IsIncreasing(object interface{}, msgAndArgs ...inte...
method IsIncreasingf (line 831) | func (a *Assertions) IsIncreasingf(object interface{}, msg string, args ...
method IsNonDecreasing (line 843) | func (a *Assertions) IsNonDecreasing(object interface{}, msgAndArgs ...i...
method IsNonDecreasingf (line 855) | func (a *Assertions) IsNonDecreasingf(object interface{}, msg string, ar...
method IsNonIncreasing (line 867) | func (a *Assertions) IsNonIncreasing(object interface{}, msgAndArgs ...i...
method IsNonIncreasingf (line 879) | func (a *Assertions) IsNonIncreasingf(object interface{}, msg string, ar...
method IsNotType (line 889) | func (a *Assertions) IsNotType(theType interface{}, object interface{}, ...
method IsNotTypef (line 899) | func (a *Assertions) IsNotTypef(theType interface{}, object interface{},...
method IsType (line 909) | func (a *Assertions) IsType(expectedType interface{}, object interface{}...
method IsTypef (line 919) | func (a *Assertions) IsTypef(expectedType interface{}, object interface{...
method JSONEq (line 929) | func (a *Assertions) JSONEq(expected string, actual string, msgAndArgs ....
method JSONEqf (line 939) | func (a *Assertions) JSONEqf(expected string, actual string, msg string,...
method Len (line 950) | func (a *Assertions) Len(object interface{}, length int, msgAndArgs ...i...
method Lenf (line 961) | func (a *Assertions) Lenf(object interface{}, length int, msg string, ar...
method Less (line 973) | func (a *Assertions) Less(e1 interface{}, e2 interface{}, msgAndArgs ......
method LessOrEqual (line 986) | func (a *Assertions) LessOrEqual(e1 interface{}, e2 interface{}, msgAndA...
method LessOrEqualf (line 999) | func (a *Assertions) LessOrEqualf(e1 interface{}, e2 interface{}, msg st...
method Lessf (line 1011) | func (a *Assertions) Lessf(e1 interface{}, e2 interface{}, msg string, a...
method Negative (line 1022) | func (a *Assertions) Negative(e interface{}, msgAndArgs ...interface{}) {
method Negativef (line 1033) | func (a *Assertions) Negativef(e interface{}, msg string, args ...interf...
method Never (line 1044) | func (a *Assertions) Never(condition func() bool, waitFor time.Duration,...
method Neverf (line 1055) | func (a *Assertions) Neverf(condition func() bool, waitFor time.Duration...
method Nil (line 1065) | func (a *Assertions) Nil(object interface{}, msgAndArgs ...interface{}) {
method Nilf (line 1075) | func (a *Assertions) Nilf(object interface{}, msg string, args ...interf...
method NoDirExists (line 1084) | func (a *Assertions) NoDirExists(path string, msgAndArgs ...interface{}) {
method NoDirExistsf (line 1093) | func (a *Assertions) NoDirExistsf(path string, msg string, args ...inter...
method NoError (line 1106) | func (a *Assertions) NoError(err error, msgAndArgs ...interface{}) {
method NoErrorf (line 1119) | func (a *Assertions) NoErrorf(err error, msg string, args ...interface{}) {
method NoFileExists (line 1128) | func (a *Assertions) NoFileExists(path string, msgAndArgs ...interface{}) {
method NoFileExistsf (line 1137) | func (a *Assertions) NoFileExistsf(path string, msg string, args ...inte...
method NotContains (line 1150) | func (a *Assertions) NotContains(s interface{}, contains interface{}, ms...
method NotContainsf (line 1163) | func (a *Assertions) NotContainsf(s interface{}, contains interface{}, m...
method NotElementsMatch (line 1180) | func (a *Assertions) NotElementsMatch(listA interface{}, listB interface...
method NotElementsMatchf (line 1197) | func (a *Assertions) NotElementsMatchf(listA interface{}, listB interfac...
method NotEmpty (line 1209) | func (a *Assertions) NotEmpty(object interface{}, msgAndArgs ...interfac...
method NotEmptyf (line 1221) | func (a *Assertions) NotEmptyf(object interface{}, msg string, args ...i...
method NotEqual (line 1234) | func (a *Assertions) NotEqual(expected interface{}, actual interface{}, ...
method NotEqualValues (line 1244) | func (a *Assertions) NotEqualValues(expected interface{}, actual interfa...
method NotEqualValuesf (line 1254) | func (a *Assertions) NotEqualValuesf(expected interface{}, actual interf...
method NotEqualf (line 1267) | func (a *Assertions) NotEqualf(expected interface{}, actual interface{},...
method NotErrorAs (line 1276) | func (a *Assertions) NotErrorAs(err error, target interface{}, msgAndArg...
method NotErrorAsf (line 1285) | func (a *Assertions) NotErrorAsf(err error, target interface{}, msg stri...
method NotErrorIs (line 1294) | func (a *Assertions) NotErrorIs(err error, target error, msgAndArgs ...i...
method NotErrorIsf (line 1303) | func (a *Assertions) NotErrorIsf(err error, target error, msg string, ar...
method NotImplements (line 1313) | func (a *Assertions) NotImplements(interfaceObject interface{}, object i...
method NotImplementsf (line 1323) | func (a *Assertions) NotImplementsf(interfaceObject interface{}, object ...
method NotNil (line 1333) | func (a *Assertions) NotNil(object interface{}, msgAndArgs ...interface{...
method NotNilf (line 1343) | func (a *Assertions) NotNilf(object interface{}, msg string, args ...int...
method NotPanics (line 1353) | func (a *Assertions) NotPanics(f assert.PanicTestFunc, msgAndArgs ...int...
method NotPanicsf (line 1363) | func (a *Assertions) NotPanicsf(f assert.PanicTestFunc, msg string, args...
method NotRegexp (line 1374) | func (a *Assertions) NotRegexp(rx interface{}, str interface{}, msgAndAr...
method NotRegexpf (line 1385) | func (a *Assertions) NotRegexpf(rx interface{}, str interface{}, msg str...
method NotSame (line 1398) | func (a *Assertions) NotSame(expected interface{}, actual interface{}, m...
method NotSamef (line 1411) | func (a *Assertions) NotSamef(expected interface{}, actual interface{}, ...
method NotSubset (line 1427) | func (a *Assertions) NotSubset(list interface{}, subset interface{}, msg...
method NotSubsetf (line 1443) | func (a *Assertions) NotSubsetf(list interface{}, subset interface{}, ms...
method NotZero (line 1451) | func (a *Assertions) NotZero(i interface{}, msgAndArgs ...interface{}) {
method NotZerof (line 1459) | func (a *Assertions) NotZerof(i interface{}, msg string, args ...interfa...
method Panics (line 1469) | func (a *Assertions) Panics(f assert.PanicTestFunc, msgAndArgs ...interf...
method PanicsWithError (line 1481) | func (a *Assertions) PanicsWithError(errString string, f assert.PanicTes...
method PanicsWithErrorf (line 1493) | func (a *Assertions) PanicsWithErrorf(errString string, f assert.PanicTe...
method PanicsWithValue (line 1504) | func (a *Assertions) PanicsWithValue(expected interface{}, f assert.Pani...
method PanicsWithValuef (line 1515) | func (a *Assertions) PanicsWithValuef(expected interface{}, f assert.Pan...
method Panicsf (line 1525) | func (a *Assertions) Panicsf(f assert.PanicTestFunc, msg string, args .....
method Positive (line 1536) | func (a *Assertions) Positive(e interface{}, msgAndArgs ...interface{}) {
method Positivef (line 1547) | func (a *Assertions) Positivef(e interface{}, msg string, args ...interf...
method Regexp (line 1558) | func (a *Assertions) Regexp(rx interface{}, str interface{}, msgAndArgs ...
method Regexpf (line 1569) | func (a *Assertions) Regexpf(rx interface{}, str interface{}, msg string...
method Same (line 1582) | func (a *Assertions) Same(expected interface{}, actual interface{}, msgA...
method Samef (line 1595) | func (a *Assertions) Samef(expected interface{}, actual interface{}, msg...
method Subset (line 1611) | func (a *Assertions) Subset(list interface{}, subset interface{}, msgAnd...
method Subsetf (line 1627) | func (a *Assertions) Subsetf(list interface{}, subset interface{}, msg s...
method True (line 1637) | func (a *Assertions) True(value bool, msgAndArgs ...interface{}) {
method Truef (line 1647) | func (a *Assertions) Truef(value bool, msg string, args ...interface{}) {
method WithinDuration (line 1657) | func (a *Assertions) WithinDuration(expected time.Time, actual time.Time...
method WithinDurationf (line 1667) | func (a *Assertions) WithinDurationf(expected time.Time, actual time.Tim...
method WithinRange (line 1677) | func (a *Assertions) WithinRange(actual time.Time, start time.Time, end ...
method WithinRangef (line 1687) | func (a *Assertions) WithinRangef(actual time.Time, start time.Time, end...
method YAMLEq (line 1695) | func (a *Assertions) YAMLEq(expected string, actual string, msgAndArgs ....
method YAMLEqf (line 1703) | func (a *Assertions) YAMLEqf(expected string, actual string, msg string,...
method Zero (line 1711) | func (a *Assertions) Zero(i interface{}, msgAndArgs ...interface{}) {
method Zerof (line 1719) | func (a *Assertions) Zerof(i interface{}, msg string, args ...interface{...
FILE: vendor/github.com/stretchr/testify/require/requirements.go
type TestingT (line 4) | type TestingT interface
type ComparisonAssertionFunc (line 15) | type ComparisonAssertionFunc
type ValueAssertionFunc (line 19) | type ValueAssertionFunc
type BoolAssertionFunc (line 23) | type BoolAssertionFunc
type ErrorAssertionFunc (line 27) | type ErrorAssertionFunc
FILE: vendor/golang.org/x/net/bpf/asm.go
function Assemble (line 14) | func Assemble(insts []Instruction) ([]RawInstruction, error) {
function Disassemble (line 31) | func Disassemble(raw []RawInstruction) (insts []Instruction, allDecoded ...
FILE: vendor/golang.org/x/net/bpf/constants.go
type Register (line 8) | type Register
constant RegA (line 13) | RegA Register = iota
constant RegX (line 16) | RegX
type ALUOp (line 20) | type ALUOp
constant ALUOpAdd (line 24) | ALUOpAdd ALUOp = iota << 4
constant ALUOpSub (line 25) | ALUOpSub
constant ALUOpMul (line 26) | ALUOpMul
constant ALUOpDiv (line 27) | ALUOpDiv
constant ALUOpOr (line 28) | ALUOpOr
constant ALUOpAnd (line 29) | ALUOpAnd
constant ALUOpShiftLeft (line 30) | ALUOpShiftLeft
constant ALUOpShiftRight (line 31) | ALUOpShiftRight
constant aluOpNeg (line 32) | aluOpNeg
constant ALUOpMod (line 33) | ALUOpMod
constant ALUOpXor (line 34) | ALUOpXor
type JumpTest (line 38) | type JumpTest
constant JumpEqual (line 44) | JumpEqual JumpTest = iota
constant JumpNotEqual (line 46) | JumpNotEqual
constant JumpGreaterThan (line 48) | JumpGreaterThan
constant JumpLessThan (line 50) | JumpLessThan
constant JumpGreaterOrEqual (line 52) | JumpGreaterOrEqual
constant JumpLessOrEqual (line 54) | JumpLessOrEqual
constant JumpBitsSet (line 56) | JumpBitsSet
constant JumpBitsNotSet (line 58) | JumpBitsNotSet
type Extension (line 70) | type Extension
constant extOffset (line 76) | extOffset = -0x1000
constant ExtLen (line 78) | ExtLen Extension = 1
constant ExtProto (line 80) | ExtProto Extension = 0
constant ExtType (line 85) | ExtType Extension = 4
constant ExtPayloadOffset (line 89) | ExtPayloadOffset Extension = 52
constant ExtInterfaceIndex (line 92) | ExtInterfaceIndex Extension = 8
constant ExtNetlinkAttr (line 95) | ExtNetlinkAttr Extension = 12
constant ExtNetlinkAttrNested (line 98) | ExtNetlinkAttrNested Extension = 16
constant ExtMark (line 100) | ExtMark Extension = 20
constant ExtQueue (line 102) | ExtQueue Extension = 24
constant ExtLinkLayerType (line 105) | ExtLinkLayerType Extension = 28
constant ExtRXHash (line 109) | ExtRXHash Extension = 32
constant ExtCPUID (line 112) | ExtCPUID Extension = 36
constant ExtVLANTag (line 114) | ExtVLANTag Extension = 44
constant ExtVLANTagPresent (line 121) | ExtVLANTagPresent Extension = 48
constant ExtVLANProto (line 125) | ExtVLANProto Extension = 60
constant ExtRand (line 127) | ExtRand Extension = 56
constant opMaskCls (line 133) | opMaskCls uint16 = 0x7
constant opMaskLoadDest (line 135) | opMaskLoadDest = 0x01
constant opMaskLoadWidth (line 136) | opMaskLoadWidth = 0x18
constant opMaskLoadMode (line 137) | opMaskLoadMode = 0xe0
constant opMaskOperand (line 139) | opMaskOperand = 0x08
constant opMaskOperator (line 140) | opMaskOperator = 0xf0
constant opClsLoadA (line 147) | opClsLoadA uint16 = iota
constant opClsLoadX (line 151) | opClsLoadX
constant opClsStoreA (line 155) | opClsStoreA
constant opClsStoreX (line 159) | opClsStoreX
constant opClsALU (line 163) | opClsALU
constant opClsJump (line 167) | opClsJump
constant opClsReturn (line 171) | opClsReturn
constant opClsMisc (line 175) | opClsMisc
constant opAddrModeImmediate (line 179) | opAddrModeImmediate uint16 = iota << 5
constant opAddrModeAbsolute (line 180) | opAddrModeAbsolute
constant opAddrModeIndirect (line 181) | opAddrModeIndirect
constant opAddrModeScratch (line 182) | opAddrModeScratch
constant opAddrModePacketLen (line 183) | opAddrModePacketLen
constant opAddrModeMemShift (line 184) | opAddrModeMemShift
constant opLoadWidth4 (line 188) | opLoadWidth4 uint16 = iota << 3
constant opLoadWidth2 (line 189) | opLoadWidth2
constant opLoadWidth1 (line 190) | opLoadWidth1
type opOperand (line 194) | type opOperand
constant opOperandConstant (line 198) | opOperandConstant opOperand = iota << 3
constant opOperandX (line 199) | opOperandX
type jumpOp (line 203) | type jumpOp
constant opJumpAlways (line 207) | opJumpAlways jumpOp = iota << 4
constant opJumpEqual (line 208) | opJumpEqual
constant opJumpGT (line 209) | opJumpGT
constant opJumpGE (line 210) | opJumpGE
constant opJumpSet (line 211) | opJumpSet
constant opRetSrcConstant (line 215) | opRetSrcConstant uint16 = iota << 4
constant opRetSrcA (line 216) | opRetSrcA
constant opMiscTAX (line 220) | opMiscTAX = 0x00
constant opMiscTXA (line 221) | opMiscTXA = 0x80
FILE: vendor/golang.org/x/net/bpf/instructions.go
type Instruction (line 11) | type Instruction interface
type RawInstruction (line 17) | type RawInstruction struct
method Assemble (line 29) | func (ri RawInstruction) Assemble() (RawInstruction, error) { return r...
method Disassemble (line 33) | func (ri RawInstruction) Disassemble() Instruction {
function jumpOpToTest (line 149) | func jumpOpToTest(op jumpOp, skipTrue uint8, skipFalse uint8) (JumpTest,...
type LoadConstant (line 185) | type LoadConstant struct
method Assemble (line 191) | func (a LoadConstant) Assemble() (RawInstruction, error) {
method String (line 196) | func (a LoadConstant) String() string {
type LoadScratch (line 208) | type LoadScratch struct
method Assemble (line 214) | func (a LoadScratch) Assemble() (RawInstruction, error) {
method String (line 222) | func (a LoadScratch) String() string {
type LoadAbsolute (line 235) | type LoadAbsolute struct
method Assemble (line 241) | func (a LoadAbsolute) Assemble() (RawInstruction, error) {
method String (line 246) | func (a LoadAbsolute) String() string {
type LoadIndirect (line 264) | type LoadIndirect struct
method Assemble (line 270) | func (a LoadIndirect) Assemble() (RawInstruction, error) {
method String (line 275) | func (a LoadIndirect) String() string {
type LoadMemShift (line 294) | type LoadMemShift struct
method Assemble (line 299) | func (a LoadMemShift) Assemble() (RawInstruction, error) {
method String (line 304) | func (a LoadMemShift) String() string {
type LoadExtension (line 310) | type LoadExtension struct
method Assemble (line 315) | func (a LoadExtension) Assemble() (RawInstruction, error) {
method String (line 323) | func (a LoadExtension) String() string {
type StoreScratch (line 363) | type StoreScratch struct
method Assemble (line 369) | func (a StoreScratch) Assemble() (RawInstruction, error) {
method String (line 390) | func (a StoreScratch) String() string {
type ALUOpConstant (line 402) | type ALUOpConstant struct
method Assemble (line 408) | func (a ALUOpConstant) Assemble() (RawInstruction, error) {
method String (line 416) | func (a ALUOpConstant) String() string {
type ALUOpX (line 444) | type ALUOpX struct
method Assemble (line 449) | func (a ALUOpX) Assemble() (RawInstruction, error) {
method String (line 456) | func (a ALUOpX) String() string {
type NegateA (line 484) | type NegateA struct
method Assemble (line 487) | func (a NegateA) Assemble() (RawInstruction, error) {
method String (line 494) | func (a NegateA) String() string {
type Jump (line 499) | type Jump struct
method Assemble (line 504) | func (a Jump) Assemble() (RawInstruction, error) {
method String (line 512) | func (a Jump) String() string {
type JumpIf (line 518) | type JumpIf struct
method Assemble (line 526) | func (a JumpIf) Assemble() (RawInstruction, error) {
method String (line 531) | func (a JumpIf) String() string {
type JumpIfX (line 537) | type JumpIfX struct
method Assemble (line 544) | func (a JumpIfX) Assemble() (RawInstruction, error) {
method String (line 549) | func (a JumpIfX) String() string {
function jumpToRaw (line 554) | func jumpToRaw(test JumpTest, operand opOperand, k uint32, skipTrue, ski...
function jumpToString (line 592) | func jumpToString(cond JumpTest, operand string, skipTrue, skipFalse uin...
function conditionalJump (line 626) | func conditionalJump(operand string, skipTrue, skipFalse uint8, positive...
type RetA (line 637) | type RetA struct
method Assemble (line 640) | func (a RetA) Assemble() (RawInstruction, error) {
method String (line 647) | func (a RetA) String() string {
type RetConstant (line 652) | type RetConstant struct
method Assemble (line 657) | func (a RetConstant) Assemble() (RawInstruction, error) {
method String (line 665) | func (a RetConstant) String() string {
type TXA (line 670) | type TXA struct
method Assemble (line 673) | func (a TXA) Assemble() (RawInstruction, error) {
method String (line 680) | func (a TXA) String() string {
type TAX (line 685) | type TAX struct
method Assemble (line 688) | func (a TAX) Assemble() (RawInstruction, error) {
method String (line 695) | func (a TAX) String() string {
function assembleLoad (line 699) | func assembleLoad(dst Register, loadSize int, mode uint16, k uint32) (Ra...
FILE: vendor/golang.org/x/net/bpf/setter.go
type Setter (line 8) | type Setter interface
FILE: vendor/golang.org/x/net/bpf/vm.go
type VM (line 13) | type VM struct
method Run (line 85) | func (v *VM) Run(in []byte) (int, error) {
function NewVM (line 18) | func NewVM(filter []Instruction) (*VM, error) {
FILE: vendor/golang.org/x/net/bpf/vm_instructions.go
function aluOpConstant (line 12) | func aluOpConstant(ins ALUOpConstant, regA uint32) uint32 {
function aluOpX (line 16) | func aluOpX(ins ALUOpX, regA uint32, regX uint32) (uint32, bool) {
function aluOpCommon (line 29) | func aluOpCommon(op ALUOp, regA uint32, value uint32) uint32 {
function jumpIf (line 58) | func jumpIf(ins JumpIf, regA uint32) int {
function jumpIfX (line 62) | func jumpIfX(ins JumpIfX, regA uint32, regX uint32) int {
function jumpIfCommon (line 66) | func jumpIfCommon(cond JumpTest, skipTrue, skipFalse uint8, regA uint32,...
function loadAbsolute (line 95) | func loadAbsolute(ins LoadAbsolute, in []byte) (uint32, bool) {
function loadConstant (line 102) | func loadConstant(ins LoadConstant, regA uint32, regX uint32) (uint32, u...
function loadExtension (line 113) | func loadExtension(ins LoadExtension, in []byte) uint32 {
function loadIndirect (line 122) | func loadIndirect(ins LoadIndirect, in []byte, regX uint32) (uint32, boo...
function loadMemShift (line 129) | func loadMemShift(ins LoadMemShift, in []byte) (uint32, bool) {
function inBounds (line 141) | func inBounds(inLen int, offset int, size int) bool {
function loadCommon (line 145) | func loadCommon(in []byte, offset int, size int) (uint32, bool) {
function loadScratch (line 162) | func loadScratch(ins LoadScratch, regScratch [16]uint32, regA uint32, re...
function storeScratch (line 173) | func storeScratch(ins StoreScratch, regScratch [16]uint32, regA uint32, ...
FILE: vendor/golang.org/x/net/internal/iana/const.go
constant DiffServCS0 (line 9) | DiffServCS0 = 0x00
constant DiffServCS1 (line 10) | DiffServCS1 = 0x20
constant DiffServCS2 (line 11) | DiffServCS2 = 0x40
constant DiffServCS3 (line 12) | DiffServCS3 = 0x60
constant DiffServCS4 (line 13) | DiffServCS4 = 0x80
constant DiffServCS5 (line 14) | DiffServCS5 = 0xa0
constant DiffServCS6 (line 15) | DiffServCS6 = 0xc0
constant DiffServCS7 (line 16) | DiffServCS7 = 0xe0
constant DiffServAF11 (line 17) | DiffServAF11 = 0x28
constant DiffServAF12 (line 18) | DiffServAF12 = 0x30
constant DiffServAF13 (line 19) | DiffServAF13 = 0x38
constant DiffServAF21 (line 20) | DiffServAF21 = 0x48
constant DiffServAF22 (line 21) | DiffServAF22 = 0x50
constant DiffServAF23 (line 22) | DiffServAF23 = 0x58
constant DiffServAF31 (line 23) | DiffServAF31 = 0x68
constant DiffServAF32 (line 24) | DiffServAF32 = 0x70
constant DiffServAF33 (line 25) | DiffServAF33 = 0x78
constant DiffServAF41 (line 26) | DiffServAF41 = 0x88
constant DiffServAF42 (line 27) | DiffServAF42 = 0x90
constant DiffServAF43 (line 28) | DiffServAF43 = 0x98
constant DiffServEF (line 29) | DiffServEF = 0xb8
constant DiffServVOICEADMIT (line 30) | DiffServVOICEADMIT = 0xb0
constant NotECNTransport (line 31) | NotECNTransport = 0x00
constant ECNTransport1 (line 32) | ECNTransport1 = 0x01
constant ECNTransport0 (line 33) | ECNTransport0 = 0x02
constant CongestionExperienced (line 34) | CongestionExperienced = 0x03
constant ProtocolIP (line 39) | ProtocolIP = 0
constant ProtocolHOPOPT (line 40) | ProtocolHOPOPT = 0
constant ProtocolICMP (line 41) | ProtocolICMP = 1
constant ProtocolIGMP (line 42) | ProtocolIGMP = 2
constant ProtocolGGP (line 43) | ProtocolGGP = 3
constant ProtocolIPv4 (line 44) | ProtocolIPv4 = 4
constant ProtocolST (line 45) | ProtocolST = 5
constant ProtocolTCP (line 46) | ProtocolTCP = 6
constant ProtocolCBT (line 47) | ProtocolCBT = 7
constant ProtocolEGP (line 48) | ProtocolEGP = 8
constant ProtocolIGP (line 49) | ProtocolIGP = 9
constant ProtocolBBNRCCMON (line 50) | ProtocolBBNRCCMON = 10
constant ProtocolNVPII (line 51) | ProtocolNVPII = 11
constant ProtocolPUP (line 52) | ProtocolPUP = 12
constant ProtocolEMCON (line 53) | ProtocolEMCON = 14
constant ProtocolXNET (line 54) | ProtocolXNET = 15
constant ProtocolCHAOS (line 55) | ProtocolCHAOS = 16
constant ProtocolUDP (line 56) | ProtocolUDP = 17
constant ProtocolMUX (line 57) | ProtocolMUX = 18
constant ProtocolDCNMEAS (line 58) | ProtocolDCNMEAS = 19
constant ProtocolHMP (line 59) | ProtocolHMP = 20
constant ProtocolPRM (line 60) | ProtocolPRM = 21
constant ProtocolXNSIDP (line 61) | ProtocolXNSIDP = 22
constant ProtocolTRUNK1 (line 62) | ProtocolTRUNK1 = 23
constant ProtocolTRUNK2 (line 63) | ProtocolTRUNK2 = 24
constant ProtocolLEAF1 (line 64) | ProtocolLEAF1 = 25
constant ProtocolLEAF2 (line 65) | ProtocolLEAF2 = 26
constant ProtocolRDP (line 66) | ProtocolRDP = 27
constant ProtocolIRTP (line 67) | ProtocolIRTP = 28
constant ProtocolISOTP4 (line 68) | ProtocolISOTP4 = 29
constant ProtocolNETBLT (line 69) | ProtocolNETBLT = 30
constant ProtocolMFENSP (line 70) | ProtocolMFENSP = 31
constant ProtocolMERITINP (line 71) | ProtocolMERITINP = 32
constant ProtocolDCCP (line 72) | ProtocolDCCP = 33
constant Protocol3PC (line 73) | Protocol3PC = 34
constant ProtocolIDPR (line 74) | ProtocolIDPR = 35
constant ProtocolXTP (line 75) | ProtocolXTP = 36
constant ProtocolDDP (line 76) | ProtocolDDP = 37
constant ProtocolIDPRCMTP (line 77) | ProtocolIDPRCMTP = 38
constant ProtocolTPPP (line 78) | ProtocolTPPP = 39
constant ProtocolIL (line 79) | ProtocolIL = 40
constant ProtocolIPv6 (line 80) | ProtocolIPv6 = 41
constant ProtocolSDRP (line 81) | ProtocolSDRP = 42
constant ProtocolIPv6Route (line 82) | ProtocolIPv6Route = 43
constant ProtocolIPv6Frag (line 83) | ProtocolIPv6Frag = 44
constant ProtocolIDRP (line 84) | ProtocolIDRP = 45
constant ProtocolRSVP (line 85) | ProtocolRSVP = 46
constant ProtocolGRE (line 86) | ProtocolGRE = 47
constant ProtocolDSR (line 87) | ProtocolDSR = 48
constant ProtocolBNA (line 88) | ProtocolBNA = 49
constant ProtocolESP (line 89) | ProtocolESP = 50
constant ProtocolAH (line 90) | ProtocolAH = 51
constant ProtocolINLSP (line 91) | ProtocolINLSP = 52
constant ProtocolNARP (line 92) | ProtocolNARP = 54
constant ProtocolMOBILE (line 93) | ProtocolMOBILE = 55
constant ProtocolTLSP (line 94) | ProtocolTLSP = 56
constant ProtocolSKIP (line 95) | ProtocolSKIP = 57
constant ProtocolIPv6ICMP (line 96) | ProtocolIPv6ICMP = 58
constant ProtocolIPv6NoNxt (line 97) | ProtocolIPv6NoNxt = 59
constant ProtocolIPv6Opts (line 98) | ProtocolIPv6Opts = 60
constant ProtocolCFTP (line 99) | ProtocolCFTP = 62
constant ProtocolSATEXPAK (line 100) | ProtocolSATEXPAK = 64
constant ProtocolKRYPTOLAN (line 101) | ProtocolKRYPTOLAN = 65
constant ProtocolRVD (line 102) | ProtocolRVD = 66
constant ProtocolIPPC (line 103) | ProtocolIPPC = 67
constant ProtocolSATMON (line 104) | ProtocolSATMON = 69
constant ProtocolVISA (line 105) | ProtocolVISA = 70
constant ProtocolIPCV (line 106) | ProtocolIPCV = 71
constant ProtocolCPNX (line 107) | ProtocolCPNX = 72
constant ProtocolCPHB (line 108) | ProtocolCPHB = 73
constant ProtocolWSN (line 109) | ProtocolWSN = 74
constant ProtocolPVP (line 110) | ProtocolPVP = 75
constant ProtocolBRSATMON (line 111) | ProtocolBRSATMON = 76
constant ProtocolSUNND (line 112) | ProtocolSUNND = 77
constant ProtocolWBMON (line 113) | ProtocolWBMON = 78
constant ProtocolWBEXPAK (line 114) | ProtocolWBEXPAK = 79
constant ProtocolISOIP (line 115) | ProtocolISOIP = 80
constant ProtocolVMTP (line 116) | ProtocolVMTP = 81
constant ProtocolSECUREVMTP (line 117) | ProtocolSECUREVMTP = 82
constant ProtocolVINES (line 118) | ProtocolVINES = 83
constant ProtocolTTP (line 119) | ProtocolTTP = 84
constant ProtocolIPTM (line 120) | ProtocolIPTM = 84
constant ProtocolNSFNETIGP (line 121) | ProtocolNSFNETIGP = 85
constant ProtocolDGP (line 122) | ProtocolDGP = 86
constant ProtocolTCF (line 123) | ProtocolTCF = 87
constant ProtocolEIGRP (line 124) | ProtocolEIGRP = 88
constant ProtocolOSPFIGP (line 125) | ProtocolOSPFIGP = 89
constant ProtocolSpriteRPC (line 126) | ProtocolSpriteRPC = 90
constant ProtocolLARP (line 127) | ProtocolLARP = 91
constant ProtocolMTP (line 128) | ProtocolMTP = 92
constant ProtocolAX25 (line 129) | ProtocolAX25 = 93
constant ProtocolIPIP (line 130) | ProtocolIPIP = 94
constant ProtocolSCCSP (line 131) | ProtocolSCCSP = 96
constant ProtocolETHERIP (line 132) | ProtocolETHERIP = 97
constant ProtocolENCAP (line 133) | ProtocolENCAP = 98
constant ProtocolGMTP (line 134) | ProtocolGMTP = 100
constant ProtocolIFMP (line 135) | ProtocolIFMP = 101
constant ProtocolPNNI (line 136) | ProtocolPNNI = 102
constant ProtocolPIM (line 137) | ProtocolPIM = 103
constant ProtocolARIS (line 138) | ProtocolARIS = 104
constant ProtocolSCPS (line 139) | ProtocolSCPS = 105
constant ProtocolQNX (line 140) | ProtocolQNX = 106
constant ProtocolAN (line 141) | ProtocolAN = 107
constant ProtocolIPComp (line 142) | ProtocolIPComp = 108
constant ProtocolSNP (line 143) | ProtocolSNP = 109
constant ProtocolCompaqPeer (line 144) | ProtocolCompaqPeer = 110
constant ProtocolIPXinIP (line 145) | ProtocolIPXinIP = 111
constant ProtocolVRRP (line 146) | ProtocolVRRP = 112
constant ProtocolPGM (line 147) | ProtocolPGM = 113
constant ProtocolL2TP (line 148) | ProtocolL2TP = 115
constant ProtocolDDX (line 149) | ProtocolDDX = 116
constant ProtocolIATP (line 150) | ProtocolIATP = 117
constant ProtocolSTP (line 151) | ProtocolSTP = 118
constant ProtocolSRP (line 152) | ProtocolSRP = 119
constant ProtocolUTI (line 153) | ProtocolUTI = 120
constant ProtocolSMP (line 154) | ProtocolSMP = 121
constant ProtocolPTP (line 155) | ProtocolPTP = 123
constant ProtocolISIS (line 156) | ProtocolISIS = 124
constant ProtocolFIRE (line 157) | ProtocolFIRE = 125
constant ProtocolCRTP (line 158) | ProtocolCRTP = 126
constant ProtocolCRUDP (line 159) | ProtocolCRUDP = 127
constant ProtocolSSCOPMCE (line 160) | ProtocolSSCOPMCE = 128
constant ProtocolIPLT (line 161) | ProtocolIPLT = 129
constant ProtocolSPS (line 162) | ProtocolSPS = 130
constant ProtocolPIPE (line 163) | ProtocolPIPE = 131
constant ProtocolSCTP (line 164) | ProtocolSCTP = 132
constant ProtocolFC (line 165) | ProtocolFC = 133
constant ProtocolRSVPE2EIGNORE (line 166) | ProtocolRSVPE2EIGNORE = 134
constant ProtocolMobilityHeader (line 167) | ProtocolMobilityHeader = 135
constant ProtocolUDPLite (line 168) | ProtocolUDPLite = 136
constant ProtocolMPLSinIP (line 169) | ProtocolMPLSinIP = 137
constant ProtocolMANET (line 170) | ProtocolMANET = 138
constant ProtocolHIP (line 171) | ProtocolHIP = 139
constant ProtocolShim6 (line 172) | ProtocolShim6 = 140
constant ProtocolWESP (line 173) | ProtocolWESP = 141
constant ProtocolROHC (line 174) | ProtocolROHC = 142
constant ProtocolReserved (line 175) | ProtocolReserved = 255
constant AddrFamilyIPv4 (line 180) | AddrFamilyIPv4 = 1
constant AddrFamilyIPv6 (line 181) | AddrFamilyIPv6 = 2
constant AddrFamilyNSAP (line 182) | AddrFamilyNSAP = 3
constant AddrFamilyHDLC (line 183) | AddrFamilyHDLC = 4
constant AddrFamilyBBN1822 (line 184) | AddrFamilyBBN1822 = 5
constant AddrFamily802 (line 185) | AddrFamily802 = 6
constant AddrFamilyE163 (line 186) | AddrFamilyE163 = 7
constant AddrFamilyE164 (line 187) | AddrFamilyE164 = 8
constant AddrFamilyF69 (line 188) | AddrFamilyF69 = 9
constant AddrFamilyX121 (line 189) | AddrFamilyX121 = 10
constant AddrFamilyIPX (line 190) | AddrFamilyIPX = 11
constant AddrFamilyAppletalk (line 191) | AddrFamilyAppletalk = 12
constant AddrFamilyDecnetIV (line 192) | AddrFamilyDecnetIV = 13
constant AddrFamilyBanyanVines (line 193) | AddrFamilyBanyanVines = 14
constant AddrFamilyE164withSubaddress (line 194) | AddrFamilyE164withSubaddress = 15
constant AddrFamilyDNS (line 195) | AddrFamilyDNS = 16
constant AddrFamilyDistinguishedName (line 196) | AddrFamilyDistinguishedName = 17
constant AddrFamilyASNumber (line 197) | AddrFamilyASNumber = 18
constant AddrFamilyXTPoverIPv4 (line 198) | AddrFamilyXTPoverIPv4 = 19
constant AddrFamilyXTPoverIPv6 (line 199) | AddrFamilyXTPoverIPv6 = 20
constant AddrFamilyXTPnativemodeXTP (line 200) | AddrFamilyXTPnativemodeXTP = 21
constant AddrFamilyFibreChannelWorldWidePortName (line 201) | AddrFamilyFibreChannelWorldWidePortName = 22
constant AddrFamilyFibreChannelWorldWideNodeName (line 202) | AddrFamilyFibreChannelWorldWideNodeName = 23
constant AddrFamilyGWID (line 203) | AddrFamilyGWID = 24
constant AddrFamilyL2VPN (line 204) | AddrFamilyL2VPN = 25
constant AddrFamilyMPLSTPSectionEndpointID (line 205) | AddrFamilyMPLSTPSectionEndpointID = 26
constant AddrFamilyMPLSTPLSPEndpointID (line 206) | AddrFamilyMPLSTPLSPEndpointID = 27
constant AddrFamilyMPLSTPPseudowireEndpointID (line 207) | AddrFamilyMPLSTPPseudowireEndpointID = 28
constant AddrFamilyMTIPv4 (line 208) | AddrFamilyMTIPv4 = 29
constant AddrFamilyMTIPv6 (line 209) | AddrFamilyMTIPv6 = 30
constant AddrFamilyEIGRPCommonServiceFamily (line 210) | AddrFamilyEIGRPCommonServiceFamily = 16384
constant AddrFamilyEIGRPIPv4ServiceFamily (line 211) | AddrFamilyEIGRPIPv4ServiceFamily = 16385
constant AddrFamilyEIGRPIPv6ServiceFamily (line 212) | AddrFamilyEIGRPIPv6ServiceFamily = 16386
constant AddrFamilyLISPCanonicalAddressFormat (line 213) | AddrFamilyLISPCanonicalAddressFormat = 16387
constant AddrFamilyBGPLS (line 214) | AddrFamilyBGPLS = 16388
constant AddrFamily48bitMAC (line 215) | AddrFamily48bitMAC = 16389
constant AddrFamily64bitMAC (line 216) | AddrFamily64bitMAC = 16390
constant AddrFamilyOUI (line 217) | AddrFamilyOUI = 16391
constant AddrFamilyMACFinal24bits (line 218) | AddrFamilyMACFinal24bits = 16392
constant AddrFamilyMACFinal40bits (line 219) | AddrFamilyMACFinal40bits = 16393
constant AddrFamilyIPv6Initial64bits (line 220) | AddrFamilyIPv6Initial64bits = 16394
constant AddrFamilyRBridgePortID (line 221) | AddrFamilyRBridgePortID = 16395
constant AddrFamilyTRILLNickname (line 222) | AddrFamilyTRILLNickname = 16396
FILE: vendor/golang.org/x/net/internal/socket/cmsghdr.go
method len (line 9) | func (h *cmsghdr) len() int { return int(h.Len) }
method lvl (line 10) | func (h *cmsghdr) lvl() int { return int(h.Level) }
method typ (line 11) | func (h *cmsghdr) typ() int { return int(h.Type) }
FILE: vendor/golang.org/x/net/internal/socket/cmsghdr_bsd.go
method set (line 9) | func (h *cmsghdr) set(l, lvl, typ int) {
FILE: vendor/golang.org/x/net/internal/socket/cmsghdr_linux_32bit.go
method set (line 9) | func (h *cmsghdr) set(l, lvl, typ int) {
FILE: vendor/golang.org/x/net/internal/socket/cmsghdr_linux_64bit.go
method set (line 9) | func (h *cmsghdr) set(l, lvl, typ int) {
FILE: vendor/golang.org/x/net/internal/socket/cmsghdr_solaris_64bit.go
method set (line 9) | func (h *cmsghdr) set(l, lvl, typ int) {
FILE: vendor/golang.org/x/net/internal/socket/cmsghdr_stub.go
function controlHeaderLen (line 9) | func controlHeaderLen() int {
function controlMessageLen (line 13) | func controlMessageLen(dataLen int) int {
function controlMessageSpace (line 17) | func controlMessageSpace(dataLen int) int {
type cmsghdr (line 21) | type cmsghdr struct
method len (line 23) | func (h *cmsghdr) len() int { return 0 }
method lvl (line 24) | func (h *cmsghdr) lvl() int { return 0 }
method typ (line 25) | func (h *cmsghdr) typ() int { return 0 }
method set (line 27) | func (h *cmsghdr) set(l, lvl, typ int) {}
FILE: vendor/golang.org/x/net/internal/socket/cmsghdr_unix.go
function controlHeaderLen (line 11) | func controlHeaderLen() int {
function controlMessageLen (line 15) | func controlMessageLen(dataLen int) int {
function controlMessageSpace (line 19) | func controlMessageSpace(dataLen int) int {
FILE: vendor/golang.org/x/net/internal/socket/cmsghdr_zos_s390x.go
method set (line 7) | func (h *cmsghdr) set(l, lvl, typ int) {
FILE: vendor/golang.org/x/net/internal/socket/complete_dontwait.go
function ioComplete (line 15) | func ioComplete(flags int, operr error) bool {
FILE: vendor/golang.org/x/net/internal/socket/complete_nodontwait.go
function ioComplete (line 15) | func ioComplete(flags int, operr error) bool {
FILE: vendor/golang.org/x/net/internal/socket/error_unix.go
function errnoErr (line 19) | func errnoErr(errno syscall.Errno) error {
FILE: vendor/golang.org/x/net/internal/socket/error_windows.go
function errnoErr (line 16) | func errnoErr(errno syscall.Errno) error {
FILE: vendor/golang.org/x/net/internal/socket/iovec_32bit.go
method set (line 11) | func (v *iovec) set(b []byte) {
FILE: vendor/golang.org/x/net/internal/socket/iovec_64bit.go
method set (line 11) | func (v *iovec) set(b []byte) {
FILE: vendor/golang.org/x/net/internal/socket/iovec_solaris_64bit.go
method set (line 11) | func (v *iovec) set(b []byte) {
FILE: vendor/golang.org/x/net/internal/socket/iovec_stub.go
type iovec (line 9) | type iovec struct
method set (line 11) | func (v *iovec) set(b []byte) {}
FILE: vendor/golang.org/x/net/internal/socket/mmsghdr_stub.go
type mmsghdr (line 11) | type mmsghdr struct
type mmsghdrs (line 13) | type mmsghdrs
method pack (line 15) | func (hs mmsghdrs) pack(ms []Message, parseFn func([]byte, string) (ne...
method unpack (line 19) | func (hs mmsghdrs) unpack(ms []Message, parseFn func([]byte, string) (...
FILE: vendor/golang.org/x/net/internal/socket/mmsghdr_unix.go
type mmsghdrs (line 16) | type mmsghdrs
method unpack (line 18) | func (hs mmsghdrs) unpack(ms []Message, parseFn func([]byte, string) (...
type mmsghdrsPacker (line 35) | type mmsghdrsPacker struct
method prepare (line 47) | func (p *mmsghdrsPacker) prepare(ms []Message) {
method pack (line 71) | func (p *mmsghdrsPacker) pack(ms []Message, parseFn func([]byte, strin...
type syscaller (line 100) | type syscaller struct
method init (line 110) | func (r *syscaller) init() {
method recvmmsg (line 115) | func (r *syscaller) recvmmsg(c syscall.RawConn, hs mmsghdrs, flags int...
method recvmmsgF (line 129) | func (r *syscaller) recvmmsgF(s uintptr) bool {
method sendmmsg (line 134) | func (r *syscaller) sendmmsg(c syscall.RawConn, hs mmsghdrs, flags int...
method sendmmsgF (line 148) | func (r *syscaller) sendmmsgF(s uintptr) bool {
type mmsgTmps (line 154) | type mmsgTmps struct
type mmsgTmpsPool (line 169) | type mmsgTmpsPool struct
method Get (line 173) | func (p *mmsgTmpsPool) Get() *mmsgTmps {
method Put (line 193) | func (p *mmsgTmpsPool) Put(tmps *mmsgTmps) {
FILE: vendor/golang.org/x/net/internal/socket/msghdr_bsd.go
method pack (line 11) | func (h *msghdr) pack(vs []iovec, bs [][]byte, oob []byte, sa []byte) {
method name (line 26) | func (h *msghdr) name() []byte {
method controllen (line 33) | func (h *msghdr) controllen() int {
method flags (line 37) | func (h *msghdr) flags() int {
FILE: vendor/golang.org/x/net/internal/socket/msghdr_bsdvar.go
method setIov (line 9) | func (h *msghdr) setIov(vs []iovec) {
FILE: vendor/golang.org/x/net/internal/socket/msghdr_linux.go
method pack (line 9) | func (h *msghdr) pack(vs []iovec, bs [][]byte, oob []byte, sa []byte) {
method name (line 23) | func (h *msghdr) name() []byte {
method controllen (line 30) | func (h *msghdr) controllen() int {
method flags (line 34) | func (h *msghdr) flags() int {
FILE: vendor/golang.org/x/net/internal/socket/msghdr_linux_32bit.go
method setIov (line 11) | func (h *msghdr) setIov(vs []iovec) {
method setControl (line 20) | func (h *msghdr) setControl(b []byte) {
FILE: vendor/golang.org/x/net/internal/socket/msghdr_linux_64bit.go
method setIov (line 11) | func (h *msghdr) setIov(vs []iovec) {
method setControl (line 20) | func (h *msghdr) setControl(b []byte) {
FILE: vendor/golang.org/x/net/internal/socket/msghdr_openbsd.go
method setIov (line 7) | func (h *msghdr) setIov(vs []iovec) {
FILE: vendor/golang.org/x/net/internal/socket/msghdr_solaris_64bit.go
method pack (line 14) | func (h *msghdr) pack(vs []iovec, bs [][]byte, oob []byte, sa []byte) {
method controllen (line 32) | func (h *msghdr) controllen() int {
method flags (line 36) | func (h *msghdr) flags() int {
FILE: vendor/golang.org/x/net/internal/socket/msghdr_stub.go
type msghdr (line 9) | type msghdr struct
method pack (line 11) | func (h *msghdr) pack(vs []iovec, bs [][]byte, oob []byte, sa []byte) {}
method name (line 12) | func (h *msghdr) name() []byte ...
method controllen (line 13) | func (h *msghdr) controllen() int ...
method flags (line 14) | func (h *msghdr) flags() int ...
FILE: vendor/golang.org/x/net/internal/socket/msghdr_zos_s390x.go
method pack (line 11) | func (h *msghdr) pack(vs []iovec, bs [][]byte, oob []byte, sa []byte) {
method controllen (line 29) | func (h *msghdr) controllen() int {
method flags (line 33) | func (h *msghdr) flags() int {
FILE: vendor/golang.org/x/net/internal/socket/norace.go
method raceRead (line 9) | func (m *Message) raceRead() {
method raceWrite (line 11) | func (m *Message) raceWrite() {
FILE: vendor/golang.org/x/net/internal/socket/race.go
method raceRead (line 18) | func (m *Message) raceRead() {
method raceWrite (line 28) | func (m *Message) raceWrite() {
FILE: vendor/golang.org/x/net/internal/socket/rawconn.go
type Conn (line 15) | type Conn struct
type tcpConn (line 22) | type tcpConn interface
type udpConn (line 31) | type udpConn interface
type ipConn (line 40) | type ipConn interface
function NewConn (line 48) | func NewConn(c net.Conn) (*Conn, error) {
method get (line 70) | func (o *Option) get(c *Conn, b []byte) (int, error) {
method set (line 82) | func (o *Option) set(c *Conn, b []byte) error {
FILE: vendor/golang.org/x/net/internal/socket/rawconn_mmsg.go
method recvMsgs (line 13) | func (c *Conn) recvMsgs(ms []Message, flags int) (int, error) {
method sendMsgs (line 34) | func (c *Conn) sendMsgs(ms []Message, flags int) (int, error) {
FILE: vendor/golang.org/x/net/internal/socket/rawconn_msg.go
method recvMsg (line 14) | func (c *Conn) recvMsg(m *Message, flags int) error {
method sendMsg (line 40) | func (c *Conn) sendMsg(m *Message, flags int) error {
FILE: vendor/golang.org/x/net/internal/socket/rawconn_nommsg.go
method recvMsgs (line 9) | func (c *Conn) recvMsgs(ms []Message, flags int) (int, error) {
method sendMsgs (line 13) | func (c *Conn) sendMsgs(ms []Message, flags int) (int, error) {
FILE: vendor/golang.org/x/net/internal/socket/rawconn_nomsg.go
method recvMsg (line 9) | func (c *Conn) recvMsg(m *Message, flags int) error {
method sendMsg (line 13) | func (c *Conn) sendMsg(m *Message, flags int) error {
FILE: vendor/golang.org/x/net/internal/socket/socket.go
type Option (line 20) | type Option struct
method Get (line 28) | func (o *Option) Get(c *Conn, b []byte) (int, error) {
method GetInt (line 41) | func (o *Option) GetInt(c *Conn) (int, error) {
method Set (line 66) | func (o *Option) Set(c *Conn, b []byte) error {
method SetInt (line 79) | func (o *Option) SetInt(c *Conn, v int) error {
function ControlMessageSpace (line 95) | func ControlMessageSpace(dataLen int) int {
type ControlMessage (line 106) | type ControlMessage
method Data (line 110) | func (m ControlMessage) Data(dataLen int) []byte {
method Next (line 121) | func (m ControlMessage) Next(dataLen int) ControlMessage {
method MarshalHeader (line 131) | func (m ControlMessage) MarshalHeader(lvl, typ, dataLen int) error {
method ParseHeader (line 142) | func (m ControlMessage) ParseHeader() (lvl, typ, dataLen int, err erro...
method Marshal (line 153) | func (m ControlMessage) Marshal(lvl, typ int, data []byte) (ControlMes...
method Parse (line 169) | func (m ControlMessage) Parse() ([]ControlMessage, error) {
function NewControlMessage (line 211) | func NewControlMessage(dataLen []int) ControlMessage {
type Message (line 220) | type Message struct
method RecvMsg (line 247) | func (c *Conn) RecvMsg(m *Message, flags int) error {
method SendMsg (line 255) | func (c *Conn) SendMsg(m *Message, flags int) error {
method RecvMsgs (line 267) | func (c *Conn) RecvMsgs(ms []Message, flags int) (int, error) {
method SendMsgs (line 279) | func (c *Conn) SendMsgs(ms []Message, flags int) (int, error) {
FILE: vendor/golang.org/x/net/internal/socket/sys_bsd.go
function recvmmsg (line 9) | func recvmmsg(s uintptr, hs []mmsghdr, flags int) (int, error) {
function sendmmsg (line 13) | func sendmmsg(s uintptr, hs []mmsghdr, flags int) (int, error) {
FILE: vendor/golang.org/x/net/internal/socket/sys_const_unix.go
constant sysAF_UNSPEC (line 12) | sysAF_UNSPEC = unix.AF_UNSPEC
constant sysAF_INET (line 13) | sysAF_INET = unix.AF_INET
constant sysAF_INET6 (line 14) | sysAF_INET6 = unix.AF_INET6
constant sysSOCK_RAW (line 16) | sysSOCK_RAW = unix.SOCK_RAW
constant sizeofSockaddrInet4 (line 18) | sizeofSockaddrInet4 = unix.SizeofSockaddrInet4
constant sizeofSockaddrInet6 (line 19) | sizeofSockaddrInet6 = unix.SizeofSockaddrInet6
FILE: vendor/golang.org/x/net/internal/socket/sys_linux.go
function recvmmsg (line 14) | func recvmmsg(s uintptr, hs []mmsghdr, flags int) (int, error) {
function sendmmsg (line 19) | func sendmmsg(s uintptr, hs []mmsghdr, flags int) (int, error) {
FILE: vendor/golang.org/x/net/internal/socket/sys_linux_386.go
constant sysRECVMMSG (line 13) | sysRECVMMSG = 0x13
constant sysSENDMMSG (line 14) | sysSENDMMSG = 0x14
function socketcall (line 17) | func socketcall(call, a0, a1, a2, a3, a4, a5 uintptr) (uintptr, syscall....
function rawsocketcall (line 18) | func rawsocketcall(call, a0, a1, a2, a3, a4, a5 uintptr) (uintptr, sysca...
function recvmmsg (line 20) | func recvmmsg(s uintptr, hs []mmsghdr, flags int) (int, error) {
function sendmmsg (line 25) | func sendmmsg(s uintptr, hs []mmsghdr, flags int) (int, error) {
FILE: vendor/golang.org/x/net/internal/socket/sys_linux_amd64.go
constant sysRECVMMSG (line 8) | sysRECVMMSG = 0x12b
constant sysSENDMMSG (line 9) | sysSENDMMSG = 0x133
FILE: vendor/golang.org/x/net/internal/socket/sys_linux_arm.go
constant sysRECVMMSG (line 8) | sysRECVMMSG = 0x16d
constant sysSENDMMSG (line 9) | sysSENDMMSG = 0x176
FILE: vendor/golang.org/x/net/internal/socket/sys_linux_arm64.go
constant sysRECVMMSG (line 8) | sysRECVMMSG = 0xf3
constant sysSENDMMSG (line 9) | sysSENDMMSG = 0x10d
FILE: vendor/golang.org/x/net/internal/socket/sys_linux_loong64.go
constant sysRECVMMSG (line 10) | sysRECVMMSG = 0xf3
constant sysSENDMMSG (line 11) | sysSENDMMSG = 0x10d
FILE: vendor/golang.org/x/net/internal/socket/sys_linux_mips.go
constant sysRECVMMSG (line 8) | sysRECVMMSG = 0x10ef
constant sysSENDMMSG (line 9) | sysSENDMMSG = 0x10f7
FILE: vendor/golang.org/x/net/internal/socket/sys_linux_mips64.go
constant sysRECVMMSG (line 8) | sysRECVMMSG = 0x14ae
constant sysSENDMMSG (line 9) | sysSENDMMSG = 0x14b6
FILE: vendor/golang.org/x/net/internal/socket/sys_linux_mips64le.go
constant sysRECVMMSG (line 8) | sysRECVMMSG = 0x14ae
constant sysSENDMMSG (line 9) | sysSENDMMSG = 0x14b6
FILE: vendor/golang.org/x/net/internal/socket/sys_linux_mipsle.go
constant sysRECVMMSG (line 8) | sysRECVMMSG = 0x10ef
constant sysSENDMMSG (line 9) | sysSENDMMSG = 0x10f7
FILE: vendor/golang.org/x/net/internal/socket/sys_linux_ppc.go
constant sysRECVMMSG (line 8) | sysRECVMMSG = 0x157
constant sysSENDMMSG (line 9) | sysSENDMMSG = 0x15d
FILE: vendor/golang.org/x/net/internal/socket/sys_linux_ppc64.go
constant sysRECVMMSG (line 8) | sysRECVMMSG = 0x157
constant sysSENDMMSG (line 9) | sysSENDMMSG = 0x15d
FILE: vendor/golang.org/x/net/internal/socket/sys_linux_ppc64le.go
constant sysRECVMMSG (line 8) | sysRECVMMSG = 0x157
constant sysSENDMMSG (line 9) | sysSENDMMSG = 0x15d
FILE: vendor/golang.org/x/net/internal/socket/sys_linux_riscv64.go
constant sysRECVMMSG (line 10) | sysRECVMMSG = 0xf3
constant sysSENDMMSG (line 11) | sysSENDMMSG = 0x10d
FILE: vendor/golang.org/x/net/internal/socket/sys_linux_s390x.go
constant sysRECVMMSG (line 13) | sysRECVMMSG = 0x13
constant sysSENDMMSG (line 14) | sysSENDMMSG = 0x14
function socketcall (line 17) | func socketcall(call, a0, a1, a2, a3, a4, a5 uintptr) (uintptr, syscall....
function rawsocketcall (line 18) | func rawsocketcall(call, a0, a1, a2, a3, a4, a5 uintptr) (uintptr, sysca...
function recvmmsg (line 20) | func recvmmsg(s uintptr, hs []mmsghdr, flags int) (int, error) {
function sendmmsg (line 25) | func sendmmsg(s uintptr, hs []mmsghdr, flags int) (int, error) {
FILE: vendor/golang.org/x/net/internal/socket/sys_netbsd.go
constant sysRECVMMSG (line 13) | sysRECVMMSG = 0x1db
constant sysSENDMMSG (line 14) | sysSENDMMSG = 0x1dc
function recvmmsg (line 17) | func recvmmsg(s uintptr, hs []mmsghdr, flags int) (int, error) {
function sendmmsg (line 22) | func sendmmsg(s uintptr, hs []mmsghdr, flags int) (int, error) {
FILE: vendor/golang.org/x/net/internal/socket/sys_posix.go
function marshalInetAddr (line 22) | func marshalInetAddr(a net.Addr, b []byte) int {
function marshalSockaddr (line 35) | func marshalSockaddr(ip net.IP, port int, zone string, b []byte) int {
function parseInetAddr (line 66) | func parseInetAddr(b []byte, network string) (net.Addr, error) {
type ipv6ZoneCache (line 112) | type ipv6ZoneCache struct
method update (line 127) | func (zc *ipv6ZoneCache) update(ift []net.Interface, force bool) (upda...
method name (line 152) | func (zc *ipv6ZoneCache) name(zone int) string {
method index (line 169) | func (zc *ipv6ZoneCache) index(zone string) int {
FILE: vendor/golang.org/x/net/internal/socket/sys_stub.go
constant sysAF_UNSPEC (line 12) | sysAF_UNSPEC = 0x0
constant sysAF_INET (line 13) | sysAF_INET = 0x2
constant sysAF_INET6 (line 14) | sysAF_INET6 = 0xa
constant sysSOCK_RAW (line 16) | sysSOCK_RAW = 0x3
constant sizeofSockaddrInet4 (line 18) | sizeofSockaddrInet4 = 0x10
constant sizeofSockaddrInet6 (line 19) | sizeofSockaddrInet6 = 0x1c
function marshalInetAddr (line 22) | func marshalInetAddr(ip net.IP, port int, zone string) []byte {
function parseInetAddr (line 26) | func parseInetAddr(b []byte, network string) (net.Addr, error) {
function getsockopt (line 30) | func getsockopt(s uintptr, level, name int, b []byte) (int, error) {
function setsockopt (line 34) | func setsockopt(s uintptr, level, name int, b []byte) error {
function recvmsg (line 38) | func recvmsg(s uintptr, buffers [][]byte, oob []byte, flags int, network...
function sendmsg (line 42) | func sendmsg(s uintptr, buffers [][]byte, oob []byte, to net.Addr, flags...
function recvmmsg (line 46) | func recvmmsg(s uintptr, hs []mmsghdr, flags int) (int, error) {
function sendmmsg (line 50) | func sendmmsg(s uintptr, hs []mmsghdr, flags int) (int, error) {
FILE: vendor/golang.org/x/net/internal/socket/sys_unix.go
function syscall_getsockopt (line 17) | func syscall_getsockopt(s, level, name int, val unsafe.Pointer, vallen *...
function syscall_setsockopt (line 20) | func syscall_setsockopt(s, level, name int, val unsafe.Pointer, vallen u...
function getsockopt (line 22) | func getsockopt(s uintptr, level, name int, b []byte) (int, error) {
function setsockopt (line 28) | func setsockopt(s uintptr, level, name int, b []byte) error {
function recvmsg (line 32) | func recvmsg(s uintptr, buffers [][]byte, oob []byte, flags int, network...
function sendmsg (line 41) | func sendmsg(s uintptr, buffers [][]byte, oob []byte, to net.Addr, flags...
function addrToSockaddr (line 50) | func addrToSockaddr(a net.Addr) unix.Sockaddr {
function sockaddrToAddr (line 91) | func sockaddrToAddr(sa unix.Sockaddr, network string) net.Addr {
FILE: vendor/golang.org/x/net/internal/socket/sys_windows.go
function probeProtocolStack (line 15) | func probeProtocolStack() int {
constant sysAF_UNSPEC (line 21) | sysAF_UNSPEC = windows.AF_UNSPEC
constant sysAF_INET (line 22) | sysAF_INET = windows.AF_INET
constant sysAF_INET6 (line 23) | sysAF_INET6 = windows.AF_INET6
constant sysSOCK_RAW (line 25) | sysSOCK_RAW = windows.SOCK_RAW
constant sizeofSockaddrInet4 (line 27) | sizeofSockaddrInet4 = 0x10
constant sizeofSockaddrInet6 (line 28) | sizeofSockaddrInet6 = 0x1c
function getsockopt (line 31) | func getsockopt(s uintptr, level, name int, b []byte) (int, error) {
function setsockopt (line 37) | func setsockopt(s uintptr, level, name int, b []byte) error {
function recvmsg (line 41) | func recvmsg(s uintptr, buffers [][]byte, oob []byte, flags int, network...
function sendmsg (line 45) | func sendmsg(s uintptr, buffers [][]byte, oob []byte, to net.Addr, flags...
function recvmmsg (line 49) | func recvmmsg(s uintptr, hs []mmsghdr, flags int) (int, error) {
function sendmmsg (line 53) | func sendmmsg(s uintptr, hs []mmsghdr, flags int) (int, error) {
FILE: vendor/golang.org/x/net/internal/socket/sys_zos_s390x.go
function syscall_syscall (line 13) | func syscall_syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err sysc...
function syscall_syscall6 (line 14) | func syscall_syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uint...
function probeProtocolStack (line 16) | func probeProtocolStack() int {
function getsockopt (line 20) | func getsockopt(s uintptr, level, name int, b []byte) (int, error) {
function setsockopt (line 26) | func setsockopt(s uintptr, level, name int, b []byte) error {
function recvmsg (line 31) | func recvmsg(s uintptr, buffers [][]byte, oob []byte, flags int, network...
function sendmsg (line 54) | func sendmsg(s uintptr, buffers [][]byte, oob []byte, to net.Addr, flags...
FILE: vendor/golang.org/x/net/internal/socket/zsys_aix_ppc64.go
type iovec (line 9) | type iovec struct
type msghdr (line 14) | type msghdr struct
type mmsghdr (line 24) | type mmsghdr struct
type cmsghdr (line 30) | type cmsghdr struct
constant sizeofIovec (line 37) | sizeofIovec = 0x10
constant sizeofMsghdr (line 38) | sizeofMsghdr = 0x30
FILE: vendor/golang.org/x/net/internal/socket/zsys_darwin_amd64.go
type iovec (line 6) | type iovec struct
type msghdr (line 11) | type msghdr struct
type cmsghdr (line 23) | type cmsghdr struct
constant sizeofIovec (line 30) | sizeofIovec = 0x10
constant sizeofMsghdr (line 31) | sizeofMsghdr = 0x30
FILE: vendor/golang.org/x/net/internal/socket/zsys_darwin_arm64.go
type iovec (line 6) | type iovec struct
type msghdr (line 11) | type msghdr struct
type cmsghdr (line 23) | type cmsghdr struct
constant sizeofIovec (line 30) | sizeofIovec = 0x10
constant sizeofMsghdr (line 31) | sizeofMsghdr = 0x30
FILE: vendor/golang.org/x/net/internal/socket/zsys_dragonfly_amd64.go
type iovec (line 6) | type iovec struct
type msghdr (line 11) | type msghdr struct
type cmsghdr (line 23) | type cmsghdr struct
constant sizeofIovec (line 30) | sizeofIovec = 0x10
constant sizeofMsghdr (line 31) | sizeofMsghdr = 0x30
FILE: vendor/golang.org/x/net/internal/socket/zsys_freebsd_386.go
type iovec (line 6) | type iovec struct
type msghdr (line 11) | type msghdr struct
type cmsghdr (line 21) | type cmsghdr struct
constant sizeofIovec (line 28) | sizeofIovec = 0x8
constant sizeofMsghdr (line 29) | sizeofMsghdr = 0x1c
FILE: vendor/golang.org/x/net/internal/socket/zsys_freebsd_amd64.go
type iovec (line 6) | type iovec struct
type msghdr (line 11) | type msghdr struct
type cmsghdr (line 23) | type cmsghdr struct
constant sizeofIovec (line 30) | sizeofIovec = 0x10
constant sizeofMsghdr (line 31) | sizeofMsghdr = 0x30
FILE: vendor/golang.org/x/net/internal/socket/zsys_freebsd_arm.go
type iovec (line 6) | type iovec struct
type msghdr (line 11) | type msghdr struct
type cmsghdr (line 21) | type cmsghdr struct
constant sizeofIovec (line 28) | sizeofIovec = 0x8
constant sizeofMsghdr (line 29) | sizeofMsghdr = 0x1c
FILE: vendor/golang.org/x/net/internal/socket/zsys_freebsd_arm64.go
type iovec (line 6) | type iovec struct
type msghdr (line 11) | type msghdr struct
type cmsghdr (line 23) | type cmsghdr struct
constant sizeofIovec (line 30) | sizeofIovec = 0x10
constant sizeofMsghdr (line 31) | sizeofMsghdr = 0x30
FILE: vendor/golang.org/x/net/internal/socket/zsys_freebsd_riscv64.go
type iovec (line 6) | type iovec struct
type msghdr (line 11) | type msghdr struct
type cmsghdr (line 21) | type cmsghdr struct
constant sizeofIovec (line 28) | sizeofIovec = 0x10
constant sizeofMsghdr (line 29) | sizeofMsghdr = 0x30
FILE: vendor/golang.org/x/net/internal/socket/zsys_linux_386.go
type iovec (line 6) | type iovec struct
type msghdr (line 11) | type msghdr struct
type mmsghdr (line 21) | type mmsghdr struct
type cmsghdr (line 26) | type cmsghdr struct
constant sizeofIovec (line 33) | sizeofIovec = 0x8
constant sizeofMsghdr (line 34) | sizeofMsghdr = 0x1c
FILE: vendor/golang.org/x/net/internal/socket/zsys_linux_amd64.go
type iovec (line 6) | type iovec struct
type msghdr (line 11) | type msghdr struct
type mmsghdr (line 23) | type mmsghdr struct
type cmsghdr (line 29) | type cmsghdr struct
constant sizeofIovec (line 36) | sizeofIovec = 0x10
constant sizeofMsghdr (line 37) | sizeofMsghdr = 0x38
FILE: vendor/golang.org/x/net/internal/socket/zsys_linux_arm.go
type iovec (line 6) | type iovec struct
type msghdr (line 11) | type msghdr struct
type mmsghdr (line 21) | type mmsghdr struct
type cmsghdr (line 26) | type cmsghdr struct
constant sizeofIovec (line 33) | sizeofIovec = 0x8
constant sizeofMsghdr (line 34) | sizeofMsghdr = 0x1c
FILE: vendor/golang.org/x/net/internal/socket/zsys_linux_arm64.go
type iovec (line 6) | type iovec struct
type msghdr (line 11) | type msghdr struct
type mmsghdr (line 23) | type mmsghdr struct
type cmsghdr (line 29) | type cmsghdr struct
constant sizeofIovec (line 36) | sizeofIovec = 0x10
constant sizeofMsghdr (line 37) | sizeofMsghdr = 0x38
FILE: vendor/golang.org/x/net/internal/socket/zsys_linux_loong64.go
type iovec (line 8) | type iovec struct
type msghdr (line 13) | type msghdr struct
type mmsghdr (line 24) | type mmsghdr struct
type cmsghdr (line 30) | type cmsghdr struct
constant sizeofIovec (line 37) | sizeofIovec = 0x10
constant sizeofMsghdr (line 38) | sizeofMsghdr = 0x38
FILE: vendor/golang.org/x/net/internal/socket/zsys_linux_mips.go
type iovec (line 6) | type iovec struct
type msghdr (line 11) | type msghdr struct
type mmsghdr (line 21) | type mmsghdr struct
type cmsghdr (line 26) | type cmsghdr struct
constant sizeofIovec (line 33) | sizeofIovec = 0x8
constant sizeofMsghdr (line 34) | sizeofMsghdr = 0x1c
FILE: vendor/golang.org/x/net/internal/socket/zsys_linux_mips64.go
type iovec (line 6) | type iovec struct
type msghdr (line 11) | type msghdr struct
type mmsghdr (line 23) | type mmsghdr struct
type cmsghdr (line 29) | type cmsghdr struct
constant sizeofIovec (line 36) | sizeofIovec = 0x10
constant sizeofMsghdr (line 37) | sizeofMsghdr = 0x38
FILE: vendor/golang.org/x/net/internal/socket/zsys_linux_mips64le.go
type iovec (line 6) | type iovec struct
type msghdr (line 11) | type msghdr struct
type mmsghdr (line 23) | type mmsghdr struct
type cmsghdr (line 29) | type cmsghdr struct
constant sizeofIovec (line 36) | sizeofIovec = 0x10
constant sizeofMsghdr (line 37) | sizeofMsghdr = 0x38
FILE: vendor/golang.org/x/net/internal/socket/zsys_linux_mipsle.go
type iovec (line 6) | type iovec struct
type msghdr (line 11) | type msghdr struct
type mmsghdr (line 21) | type mmsghdr struct
type cmsghdr (line 26) | type cmsghdr struct
constant sizeofIovec (line 33) | sizeofIovec = 0x8
constant sizeofMsghdr (line 34) | sizeofMsghdr = 0x1c
FILE: vendor/golang.org/x/net/internal/socket/zsys_linux_ppc.go
type iovec (line 6) | type iovec struct
type msghdr (line 11) | type msghdr struct
type mmsghdr (line 21) | type mmsghdr struct
type cmsghdr (line 26) | type cmsghdr struct
constant sizeofIovec (line 33) | sizeofIovec = 0x8
constant sizeofMsghdr (line 34) | sizeofMsghdr = 0x1c
FILE: vendor/golang.org/x/net/internal/socket/zsys_linux_ppc64.go
type iovec (line 6) | type iovec struct
type msghdr (line 11) | type msghdr struct
type mmsghdr (line 23) | type mmsghdr struct
type cmsghdr (line 29) | type cmsghdr struct
constant sizeofIovec (line 36) | sizeofIovec = 0x10
constant sizeofMsghdr (line 37) | sizeofMsghdr = 0x38
FILE: vendor/golang.org/x/net/internal/socket/zsys_linux_ppc64le.go
type iovec (line 6) | type iovec struct
type msghdr (line 11) | type msghdr struct
type mmsghdr (line 23) | type mmsghdr struct
type cmsghdr (line 29) | type cmsghdr struct
constant sizeofIovec (line 36) | sizeofIovec = 0x10
constant sizeofMsghdr (line 37) | sizeofMsghdr = 0x38
FILE: vendor/golang.org/x/net/internal/socket/zsys_linux_riscv64.go
type iovec (line 8) | type iovec struct
type msghdr (line 13) | type msghdr struct
type mmsghdr (line 24) | type mmsghdr struct
type cmsghdr (line 30) | type cmsghdr struct
constant sizeofIovec (line 37) | sizeofIovec = 0x10
constant sizeofMsghdr (line 38) | sizeofMsghdr = 0x38
FILE: vendor/golang.org/x/net/internal/socket/zsys_linux_s390x.go
type iovec (line 6) | type iovec struct
type msghdr (line 11) | type msghdr struct
type mmsghdr (line 23) | type mmsghdr struct
type cmsghdr (line 29) | type cmsghdr struct
constant sizeofIovec (line 36) | sizeofIovec = 0x10
constant sizeofMsghdr (line 37) | sizeofMsghdr = 0x38
FILE: vendor/golang.org/x/net/internal/socket/zsys_netbsd_386.go
type iovec (line 6) | type iovec struct
type msghdr (line 11) | type msghdr struct
type mmsghdr (line 21) | type mmsghdr struct
type cmsghdr (line 26) | type cmsghdr struct
constant sizeofIovec (line 33) | sizeofIovec = 0x8
constant sizeofMsghdr (line 34) | sizeofMsghdr = 0x1c
FILE: vendor/golang.org/x/net/internal/socket/zsys_netbsd_amd64.go
type iovec (line 6) | type iovec struct
type msghdr (line 11) | type msghdr struct
type mmsghdr (line 23) | type mmsghdr struct
type cmsghdr (line 29) | type cmsghdr struct
constant sizeofIovec (line 36) | sizeofIovec = 0x10
constant sizeofMsghdr (line 37) | sizeofMsghdr = 0x30
FILE: vendor/golang.org/x/net/internal/socket/zsys_netbsd_arm.go
type iovec (line 6) | type iovec struct
type msghdr (line 11) | type msghdr struct
type mmsghdr (line 21) | type mmsghdr struct
type cmsghdr (line 26) | type cmsghdr struct
constant sizeofIovec (line 33) | sizeofIovec = 0x8
constant sizeofMsghdr (line 34) | sizeofMsghdr = 0x1c
FILE: vendor/golang.org/x/net/internal/socket/zsys_netbsd_arm64.go
type iovec (line 6) | type iovec struct
type msghdr (line 11) | type msghdr struct
type mmsghdr (line 23) | type mmsghdr struct
type cmsghdr (line 29) | type cmsghdr struct
constant sizeofIovec (line 36) | sizeofIovec = 0x10
constant sizeofMsghdr (line 37) | sizeofMsghdr = 0x30
FILE: vendor/golang.org/x/net/internal/socket/zsys_openbsd_386.go
type iovec (line 6) | type iovec struct
type msghdr (line 11) | type msghdr struct
type cmsghdr (line 21) | type cmsghdr struct
constant sizeofIovec (line 28) | sizeofIovec = 0x8
constant sizeofMsghdr (line 29) | sizeofMsghdr = 0x1c
FILE: vendor/golang.org/x/net/internal/socket/zsys_openbsd_amd64.go
type iovec (line 6) | type iovec struct
type msghdr (line 11) | type msghdr struct
type cmsghdr (line 23) | type cmsghdr struct
constant sizeofIovec (line 30) | sizeofIovec = 0x10
constant sizeofMsghdr (line 31) | sizeofMsghdr = 0x30
FILE: vendor/golang.org/x/net/internal/socket/zsys_openbsd_arm.go
type iovec (line 6) | type iovec struct
type msghdr (line 11) | type msghdr struct
type cmsghdr (line 21) | type cmsghdr struct
constant sizeofIovec (line 28) | sizeofIovec = 0x8
constant sizeofMsghdr (line 29) | sizeofMsghdr = 0x1c
FILE: vendor/golang.org/x/net/internal/socket/zsys_openbsd_arm64.go
type iovec (line 6) | type iovec struct
type msghdr (line 11) | type msghdr struct
type cmsghdr (line 23) | type cmsghdr struct
constant sizeofIovec (line 30) | sizeofIovec = 0x10
constant sizeofMsghdr (line 31) | sizeofMsghdr = 0x30
FILE: vendor/golang.org/x/net/internal/socket/zsys_openbsd_mips64.go
type iovec (line 6) | type iovec struct
type msghdr (line 11) | type msghdr struct
type cmsghdr (line 21) | type cmsghdr struct
constant sizeofIovec (line 28) | sizeofIovec = 0x10
constant sizeofMsghdr (line 29) | sizeofMsghdr = 0x30
FILE: vendor/golang.org/x/net/internal/socket/zsys_openbsd_ppc64.go
type iovec (line 6) | type iovec struct
type msghdr (line 11) | type msghdr struct
type cmsghdr (line 21) | type cmsghdr struct
constant sizeofIovec (line 28) | sizeofIovec = 0x10
constant sizeofMsghdr (line 29) | sizeofMsghdr = 0x30
FILE: vendor/golang.org/x/net/internal/socket/zsys_openbsd_riscv64.go
type iovec (line 6) | type iovec struct
type msghdr (line 11) | type msghdr struct
type cmsghdr (line 21) | type cmsghdr struct
constant sizeofIovec (line 28) | sizeofIovec = 0x10
constant sizeofMsghdr (line 29) | sizeofMsghdr = 0x30
FILE: vendor/golang.org/x/net/internal/socket/zsys_solaris_amd64.go
type iovec (line 6) | type iovec struct
type msghdr (line 11) | type msghdr struct
type cmsghdr (line 23) | type cmsghdr struct
constant sizeofIovec (line 30) | sizeofIovec = 0x10
constant sizeofMsghdr (line 31) | sizeofMsghdr = 0x30
FILE: vendor/golang.org/x/net/internal/socket/zsys_zos_s390x.go
type iovec (line 7) | type iovec struct
type msghdr (line 12) | type msghdr struct
type cmsghdr (line 22) | type cmsghdr struct
constant sizeofCmsghdr (line 28) | sizeofCmsghdr = 12
FILE: vendor/golang.org/x/net/ipv4/batch.go
method ReadBatch (line 74) | func (c *payloadHandler) ReadBatch(ms []Message, flags int) (int, error) {
method WriteBatch (line 108) | func (c *payloadHandler) WriteBatch(ms []Message, flags int) (int, error) {
method ReadBatch (line 140) | func (c *packetHandler) ReadBatch(ms []Message, flags int) (int, error) {
method WriteBatch (line 174) | func (c *packetHandler) WriteBatch(ms []Message, flags int) (int, error) {
FILE: vendor/golang.org/x/net/ipv4/control.go
type rawOpt (line 16) | type rawOpt struct
method set (line 21) | func (c *rawOpt) set(f ControlFlags) { c.cflags |= f }
method clear (line 22) | func (c *rawOpt) clear(f ControlFlags) { c.cflags &^= f }
method isset (line 23) | func (c *rawOpt) isset(f ControlFlags) bool { return c.cflags&f != 0 }
type ControlFlags (line 25) | type ControlFlags
constant FlagTTL (line 28) | FlagTTL ControlFlags = 1 << iota
constant FlagSrc (line 29) | FlagSrc
constant FlagDst (line 30) | FlagDst
constant FlagInterface (line 31) | FlagInterface
type ControlMessage (line 35) | type ControlMessage struct
method String (line 50) | func (cm *ControlMessage) String() string {
method Marshal (line 58) | func (cm *ControlMessage) Marshal() []byte {
method Parse (line 73) | func (cm *ControlMessage) Parse(b []byte) error {
function NewControlMessage (line 103) | func NewControlMessage(cf ControlFlags) []byte {
constant ctlTTL (line 130) | ctlTTL = iota
constant ctlSrc (line 131) | ctlSrc
constant ctlDst (line 132) | ctlDst
Copy disabled (too large)
Download .json
Condensed preview — 722 files, each showing path, character count, and a content snippet. Download the .json file for the full structured content (10,524K chars).
[
{
"path": ".dockerignore",
"chars": 17,
"preview": "Dockerfile\n/.git\n"
},
{
"path": ".editorconfig",
"chars": 407,
"preview": "# For more information about the properties used in\n# this file, please see the EditorConfig documentation:\n# http://edi"
},
{
"path": ".github/dependabot.yml",
"chars": 108,
"preview": "version: 2\nupdates:\n - package-ecosystem: \"gomod\"\n directory: \"/\"\n schedule:\n interval: \"daily\"\n"
},
{
"path": ".github/workflows/codeql-analysis.yml",
"chars": 3003,
"preview": "# For most projects, this workflow file will not need changing; you simply need\n# to commit it to your repository.\n#\n# Y"
},
{
"path": ".github/workflows/go-tests.yml",
"chars": 653,
"preview": "name: tests\n\non: [push, pull_request]\n\njobs:\n build:\n runs-on: ubuntu-latest\n steps:\n - uses"
},
{
"path": ".gitignore",
"chars": 79,
"preview": "/contrib/server/server*\n/contrib/client/client*\n*.prof\n*.out\n*.html\n*.ts\n*.mp4\n"
},
{
"path": "CODE_OF_CONDUCT.md",
"chars": 1545,
"preview": "Contributor Code of Conduct\n===========================\n\nAs contributors and maintainers of this project, we pledge to r"
},
{
"path": "Dockerfile",
"chars": 436,
"preview": "ARG BUILD_IMAGE=golang:1.25-alpine\n\nFROM $BUILD_IMAGE AS builder\n\nCOPY . /build\n\nRUN cd /build/contrib/client && CGO_ENA"
},
{
"path": "LICENSE",
"chars": 1071,
"preview": "MIT License\n\nCopyright (c) 2020-2022 FOSS GmbH\n\nPermission is hereby granted, free of charge, to any person obtaining a "
},
{
"path": "Makefile",
"chars": 1660,
"preview": "COMMIT := $(shell if [ -d .git ]; then git rev-parse HEAD; else echo \"unknown\"; fi)\nSHORTCOMMIT := $(shell echo $(COMMIT"
},
{
"path": "README.md",
"chars": 17068,
"preview": "# GoSRT\n\nImplementation of the SRT protocol in pure Go with minimal dependencies.\n\n<p align=\"left\">\n <a href=\"http://sr"
},
{
"path": "SECURITY.md",
"chars": 469,
"preview": "# Security Policy\n\n## Supported Versions\n\nAll versions in the list receive security updates.\n\n| Version | Supported "
},
{
"path": "circular/circular.go",
"chars": 3595,
"preview": "// Package circular implements \"circular numbers\". This is a number that can be\n// increased (or decreased) indefinitely"
},
{
"path": "circular/circular_test.go",
"chars": 2144,
"preview": "package circular\n\nimport (\n\t\"fmt\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nconst max uint32 = 0b11111111_11"
},
{
"path": "config.go",
"chars": 18469,
"preview": "package srt\n\nimport (\n\t\"fmt\"\n\t\"net/url\"\n\t\"strconv\"\n\t\"time\"\n)\n\nconst (\n\tUDP_HEADER_SIZE = 28\n\tSRT_HEADER_SIZE = 1"
},
{
"path": "config_test.go",
"chars": 1669,
"preview": "package srt\n\nimport (\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc TestDefaultConfig(t *testing.T)"
},
{
"path": "congestion/congestion.go",
"chars": 3024,
"preview": "// Package congestions provides interfaces and types congestion control implementations for SRT\npackage congestion\n\nimpo"
},
{
"path": "congestion/live/doc.go",
"chars": 120,
"preview": "// Package live provides implementations of the Sender and Receiver interfaces for live congestion control\npackage live\n"
},
{
"path": "congestion/live/fake.go",
"chars": 3836,
"preview": "package live\n\nimport (\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com/datarhei/gosrt/circular\"\n\t\"github.com/datarhei/gosrt/congestion\"\n\t\""
},
{
"path": "congestion/live/receive.go",
"chars": 11575,
"preview": "package live\n\nimport (\n\t\"container/list\"\n\t\"fmt\"\n\t\"strings\"\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com/datarhei/gosrt/circular\"\n\t\"gith"
},
{
"path": "congestion/live/receive_test.go",
"chars": 16223,
"preview": "package live\n\nimport (\n\t\"net\"\n\t\"testing\"\n\n\t\"github.com/datarhei/gosrt/circular\"\n\t\"github.com/datarhei/gosrt/packet\"\n\t\"gi"
},
{
"path": "congestion/live/send.go",
"chars": 7813,
"preview": "package live\n\nimport (\n\t\"container/list\"\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com/datarhei/gosrt/circular\"\n\t\"github.com/datarhei/go"
},
{
"path": "congestion/live/send_test.go",
"chars": 3026,
"preview": "package live\n\nimport (\n\t\"net\"\n\t\"testing\"\n\n\t\"github.com/datarhei/gosrt/circular\"\n\t\"github.com/datarhei/gosrt/packet\"\n\t\"gi"
},
{
"path": "conn_request.go",
"chars": 15628,
"preview": "package srt\n\nimport (\n\t\"fmt\"\n\t\"net\"\n\t\"time\"\n\n\t\"github.com/datarhei/gosrt/crypto\"\n\t\"github.com/datarhei/gosrt/packet\"\n\t\"g"
},
{
"path": "connection.go",
"chars": 45287,
"preview": "package srt\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"fmt\"\n\t\"io\"\n\t\"math\"\n\t\"net\"\n\t\"strings\"\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com/datarhei/"
},
{
"path": "connection_test.go",
"chars": 10237,
"preview": "package srt\n\nimport (\n\t\"bytes\"\n\t\"strings\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/datarhei/gosrt/packet\"\n\t\"github.com/stretchr/"
},
{
"path": "contrib/client/main.go",
"chars": 7007,
"preview": "package main\n\nimport (\n\t\"encoding/json\"\n\t\"flag\"\n\t\"fmt\"\n\t\"io\"\n\t\"net\"\n\t\"net/url\"\n\t\"os\"\n\t\"os/signal\"\n\t\"strconv\"\n\t\"strings\"\n"
},
{
"path": "contrib/client/reader.go",
"chars": 1298,
"preview": "package main\n\nimport (\n\t\"context\"\n\t\"io\"\n\t\"time\"\n)\n\ntype Reader interface {\n\tio.ReadCloser\n}\n\ntype debugReader struct {\n\t"
},
{
"path": "contrib/client/writer.go",
"chars": 2000,
"preview": "package main\n\nimport (\n\t\"bytes\"\n\t\"io\"\n\t\"sync\"\n\t\"time\"\n)\n\n// NonblockingWriter is a io.Writer and io.Closer that won't bl"
},
{
"path": "contrib/server/main.go",
"chars": 6825,
"preview": "package main\n\nimport (\n\t\"flag\"\n\t\"fmt\"\n\t\"net\"\n\t\"net/url\"\n\t\"os\"\n\t\"os/signal\"\n\t\"strings\"\n\t\"sync\"\n\n\tsrt \"github.com/datarhei"
},
{
"path": "crypto/crypto.go",
"chars": 6901,
"preview": "// Package crypto provides SRT cryptography\npackage crypto\n\nimport (\n\t\"crypto/aes\"\n\t\"crypto/cipher\"\n\t\"crypto/pbkdf2\"\n\t\"c"
},
{
"path": "crypto/crypto_test.go",
"chars": 47242,
"preview": "package crypto\n\nimport (\n\t\"bytes\"\n\t\"encoding/hex\"\n\t\"testing\"\n\n\t\"github.com/datarhei/gosrt/packet\"\n\n\t\"github.com/stretchr"
},
{
"path": "dial.go",
"chars": 17517,
"preview": "package srt\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"encoding/binary\"\n\t\"errors\"\n\t\"fmt\"\n\t\"net\"\n\t\"os\"\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com"
},
{
"path": "dial_test.go",
"chars": 15669,
"preview": "package srt\n\nimport (\n\t\"bytes\"\n\t\"net\"\n\t\"sync\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/datarhei/gosrt/circular\"\n\t\"github.com/dat"
},
{
"path": "doc.go",
"chars": 1329,
"preview": "/*\nPackage srt provides an interface for network I/O using the SRT protocol (https://github.com/Haivision/srt).\n\nThe pac"
},
{
"path": "go.mod",
"chars": 508,
"preview": "module github.com/datarhei/gosrt\n\ngo 1.25.0\n\nrequire (\n\tgithub.com/benburkert/openpgp v0.0.0-20160410205803-c2471f86866c"
},
{
"path": "go.sum",
"chars": 3074,
"preview": "github.com/benburkert/openpgp v0.0.0-20160410205803-c2471f86866c h1:8XZeJrs4+ZYhJeJ2aZxADI2tGADS15AzIF8MQ8XAhT4=\ngithub."
},
{
"path": "listen.go",
"chars": 13662,
"preview": "package srt\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"net\"\n\t\"net/netip\"\n\t\"os\"\n\t\"sync\"\n\t\"time\"\n\n\tsrtnet \"github.co"
},
{
"path": "listen_test.go",
"chars": 20713,
"preview": "package srt\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"net\"\n\t\"strconv\"\n\t\"sync\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/datarhei/gosrt/circ"
},
{
"path": "log.go",
"chars": 2343,
"preview": "package srt\n\nimport (\n\t\"runtime\"\n\t\"strings\"\n\t\"time\"\n)\n\n// Logger is for logging debug messages.\ntype Logger interface {\n"
},
{
"path": "log_test.go",
"chars": 1101,
"preview": "package srt\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc TestHasTopic(t *testing.T) {\n\tl := NewL"
},
{
"path": "net/ip.go",
"chars": 3192,
"preview": "package net\n\nimport (\n\t\"encoding/binary\"\n\t\"fmt\"\n\t\"net\"\n\t\"strings\"\n)\n\ntype IP struct {\n\tip net.IP\n}\n\nfunc (i *IP) setDefa"
},
{
"path": "net/ip_test.go",
"chars": 1902,
"preview": "package net\n\nimport (\n\t\"net\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc TestIPDefault(t *testing.T) {\n\ti"
},
{
"path": "net/syncookie.go",
"chars": 1491,
"preview": "package net\n\nimport (\n\t\"crypto/md5\"\n\t\"encoding/binary\"\n\t\"strconv\"\n\t\"time\"\n\n\t\"github.com/datarhei/gosrt/rand\"\n)\n\n// SYNCo"
},
{
"path": "net/syncookie_test.go",
"chars": 703,
"preview": "package net\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc TestSYNCookie(t *testing.T) {\n\tcounter "
},
{
"path": "net.go",
"chars": 1459,
"preview": "//go:build !windows\n\npackage srt\n\nimport \"syscall\"\n\nfunc ListenControl(config Config) func(network, address string, c sy"
},
{
"path": "net_windows.go",
"chars": 1547,
"preview": "//go:build windows\n\npackage srt\n\nimport (\n\t\"syscall\"\n\n\t\"golang.org/x/sys/windows\"\n)\n\nfunc ListenControl(config Config) f"
},
{
"path": "packet/packet.go",
"chars": 44600,
"preview": "// Package packet provides types and implementations for the different SRT packet types\npackage packet\n\nimport (\n\t\"bytes"
},
{
"path": "packet/packet_test.go",
"chars": 17072,
"preview": "package packet\n\nimport (\n\t\"bytes\"\n\t\"encoding/hex\"\n\t\"net\"\n\t\"sync\"\n\t\"testing\"\n\n\t\"github.com/datarhei/gosrt/circular\"\n\tsrtn"
},
{
"path": "packet_conn.go",
"chars": 2128,
"preview": "package srt\n\nimport (\n\t\"net\"\n\n\t\"golang.org/x/net/ipv4\"\n\t\"golang.org/x/net/ipv6\"\n)\n\n// this is net.PacketConn with two ad"
},
{
"path": "pubsub.go",
"chars": 3616,
"preview": "package srt\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"io\"\n\t\"sync\"\n\n\t\"github.com/datarhei/gosrt/packet\"\n)\n\n// PubSub is a publish/sub"
},
{
"path": "pubsub_test.go",
"chars": 2583,
"preview": "package srt\n\nimport (\n\t\"bytes\"\n\t\"sync\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/stretchr/t"
},
{
"path": "rand/rand.go",
"chars": 1439,
"preview": "package rand\n\nimport \"crypto/rand\"\n\nvar AlphaNumericCharset = \"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234"
},
{
"path": "rand/rand_test.go",
"chars": 901,
"preview": "package rand\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc TestRandomString(t *testing.T) {\n\ts1, "
},
{
"path": "server.go",
"chars": 2672,
"preview": "package srt\n\nimport (\n\t\"errors\"\n)\n\n// Server is a framework for a SRT server\ntype Server struct {\n\t// The address the SR"
},
{
"path": "server_test.go",
"chars": 1055,
"preview": "package srt\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc TestServer(t *testing.T) {\n\tserver := S"
},
{
"path": "statistics.go",
"chars": 10205,
"preview": "// https://github.com/Haivision/srt/blob/master/docs/API/statistics.md\n\npackage srt\n\n// Statistics represents the statis"
},
{
"path": "vendor/github.com/benburkert/openpgp/aes/keywrap/doc.go",
"chars": 153,
"preview": "// Package keywrap is an implementation of the RFC 3394 AES key wrapping\n// algorithm. This is used in OpenPGP with elli"
},
{
"path": "vendor/github.com/benburkert/openpgp/aes/keywrap/keywrap.go",
"chars": 4473,
"preview": "// Copyright 2014 Matthew Endsley\n// All rights reserved\n//\n// Redistribution and use in source and binary forms, with o"
},
{
"path": "vendor/github.com/davecgh/go-spew/LICENSE",
"chars": 766,
"preview": "ISC License\n\nCopyright (c) 2012-2016 Dave Collins <dave@davec.name>\n\nPermission to use, copy, modify, and/or distribute "
},
{
"path": "vendor/github.com/davecgh/go-spew/spew/bypass.go",
"chars": 4715,
"preview": "// Copyright (c) 2015-2016 Dave Collins <dave@davec.name>\n//\n// Permission to use, copy, modify, and distribute this sof"
},
{
"path": "vendor/github.com/davecgh/go-spew/spew/bypasssafe.go",
"chars": 1741,
"preview": "// Copyright (c) 2015-2016 Dave Collins <dave@davec.name>\n//\n// Permission to use, copy, modify, and distribute this sof"
},
{
"path": "vendor/github.com/davecgh/go-spew/spew/common.go",
"chars": 10364,
"preview": "/*\n * Copyright (c) 2013-2016 Dave Collins <dave@davec.name>\n *\n * Permission to use, copy, modify, and distribute this "
},
{
"path": "vendor/github.com/davecgh/go-spew/spew/config.go",
"chars": 12842,
"preview": "/*\n * Copyright (c) 2013-2016 Dave Collins <dave@davec.name>\n *\n * Permission to use, copy, modify, and distribute this "
},
{
"path": "vendor/github.com/davecgh/go-spew/spew/doc.go",
"chars": 8527,
"preview": "/*\n * Copyright (c) 2013-2016 Dave Collins <dave@davec.name>\n *\n * Permission to use, copy, modify, and distribute this "
},
{
"path": "vendor/github.com/davecgh/go-spew/spew/dump.go",
"chars": 13794,
"preview": "/*\n * Copyright (c) 2013-2016 Dave Collins <dave@davec.name>\n *\n * Permission to use, copy, modify, and distribute this "
},
{
"path": "vendor/github.com/davecgh/go-spew/spew/format.go",
"chars": 11314,
"preview": "/*\n * Copyright (c) 2013-2016 Dave Collins <dave@davec.name>\n *\n * Permission to use, copy, modify, and distribute this "
},
{
"path": "vendor/github.com/davecgh/go-spew/spew/spew.go",
"chars": 5969,
"preview": "/*\n * Copyright (c) 2013-2016 Dave Collins <dave@davec.name>\n *\n * Permission to use, copy, modify, and distribute this "
},
{
"path": "vendor/github.com/felixge/fgprof/BenchmarkProfilerGoroutines.txt",
"chars": 1700,
"preview": "$ go test -bench=BenchmarkProfilerGoroutines\ngoos: darwin\ngoarch: amd64\npkg: github.com/felixge/fgprof\nBenchmarkProfiler"
},
{
"path": "vendor/github.com/felixge/fgprof/LICENSE.txt",
"chars": 1101,
"preview": "The MIT License (MIT)\nCopyright © 2020 Felix Geisendörfer <felix@felixge.de>\n\nPermission is hereby granted, free of char"
},
{
"path": "vendor/github.com/felixge/fgprof/README.md",
"chars": 8478,
"preview": "[](https://pkg.go.dev/github.com/felixg"
},
{
"path": "vendor/github.com/felixge/fgprof/fgprof.go",
"chars": 8266,
"preview": "// fgprof is a sampling Go profiler that allows you to analyze On-CPU as well\n// as [Off-CPU](http://www.brendangregg.co"
},
{
"path": "vendor/github.com/felixge/fgprof/handler.go",
"chars": 951,
"preview": "package fgprof\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"strconv\"\n\t\"time\"\n)\n\n// Handler returns an http handler that takes an optio"
},
{
"path": "vendor/github.com/google/pprof/AUTHORS",
"chars": 305,
"preview": "# This is the official list of pprof authors for copyright purposes.\n# This file is distinct from the CONTRIBUTORS files"
},
{
"path": "vendor/github.com/google/pprof/CONTRIBUTORS",
"chars": 654,
"preview": "# People who have agreed to one of the CLAs and can contribute patches.\n# The AUTHORS file lists the copyright holders; "
},
{
"path": "vendor/github.com/google/pprof/LICENSE",
"chars": 11358,
"preview": "\n Apache License\n Version 2.0, January 2004\n "
},
{
"path": "vendor/github.com/google/pprof/profile/encode.go",
"chars": 16663,
"preview": "// Copyright 2014 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "vendor/github.com/google/pprof/profile/filter.go",
"chars": 7568,
"preview": "// Copyright 2014 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "vendor/github.com/google/pprof/profile/index.go",
"chars": 1954,
"preview": "// Copyright 2016 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "vendor/github.com/google/pprof/profile/legacy_java_profile.go",
"chars": 9034,
"preview": "// Copyright 2014 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "vendor/github.com/google/pprof/profile/legacy_profile.go",
"chars": 33646,
"preview": "// Copyright 2014 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "vendor/github.com/google/pprof/profile/merge.go",
"chars": 12473,
"preview": "// Copyright 2014 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "vendor/github.com/google/pprof/profile/profile.go",
"chars": 20210,
"preview": "// Copyright 2014 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "vendor/github.com/google/pprof/profile/proto.go",
"chars": 7694,
"preview": "// Copyright 2014 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "vendor/github.com/google/pprof/profile/prune.go",
"chars": 5165,
"preview": "// Copyright 2014 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");"
},
{
"path": "vendor/github.com/pkg/profile/.travis.yml",
"chars": 136,
"preview": "language: go\ngo_import_path: github.com/pkg/profile\ngo:\n - 1.13.x\n - 1.14.x\n - tip\n\nscript:\n - go test -race github."
},
{
"path": "vendor/github.com/pkg/profile/AUTHORS",
"chars": 30,
"preview": "Dave Cheney <dave@cheney.net>\n"
},
{
"path": "vendor/github.com/pkg/profile/LICENSE",
"chars": 1292,
"preview": "Copyright (c) 2013 Dave Cheney. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without"
},
{
"path": "vendor/github.com/pkg/profile/README.md",
"chars": 1552,
"preview": "profile\n=======\n\nSimple profiling support package for Go\n\n[ 2013, Patrick Mezard\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or with"
},
{
"path": "vendor/github.com/pmezard/go-difflib/difflib/difflib.go",
"chars": 22879,
"preview": "// Package difflib is a partial port of Python difflib module.\n//\n// It provides tools to compare sequences of strings a"
},
{
"path": "vendor/github.com/stretchr/testify/LICENSE",
"chars": 1103,
"preview": "MIT License\n\nCopyright (c) 2012-2020 Mat Ryer, Tyler Bunnell and contributors.\n\nPermission is hereby granted, free of ch"
},
{
"path": "vendor/github.com/stretchr/testify/assert/assertion_compare.go",
"chars": 12691,
"preview": "package assert\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"reflect\"\n\t\"time\"\n)\n\n// Deprecated: CompareType has only ever been for interna"
},
{
"path": "vendor/github.com/stretchr/testify/assert/assertion_format.go",
"chars": 35551,
"preview": "// Code generated with github.com/stretchr/testify/_codegen; DO NOT EDIT.\n\npackage assert\n\nimport (\n\thttp \"net/http\"\n\tur"
},
{
"path": "vendor/github.com/stretchr/testify/assert/assertion_format.go.tmpl",
"chars": 184,
"preview": "{{.CommentFormat}}\nfunc {{.DocInfo.Name}}f(t TestingT, {{.ParamsFormat}}) bool {\n\tif h, ok := t.(tHelper); ok { h.Helper"
},
{
"path": "vendor/github.com/stretchr/testify/assert/assertion_forward.go",
"chars": 63178,
"preview": "// Code generated with github.com/stretchr/testify/_codegen; DO NOT EDIT.\n\npackage assert\n\nimport (\n\thttp \"net/http\"\n\tur"
},
{
"path": "vendor/github.com/stretchr/testify/assert/assertion_forward.go.tmpl",
"chars": 185,
"preview": "{{.CommentWithoutT \"a\"}}\nfunc (a *Assertions) {{.DocInfo.Name}}({{.Params}}) bool {\n\tif h, ok := a.t.(tHelper); ok { h.H"
},
{
"path": "vendor/github.com/stretchr/testify/assert/assertion_order.go",
"chars": 2753,
"preview": "package assert\n\nimport (\n\t\"fmt\"\n\t\"reflect\"\n)\n\n// isOrdered checks that collection contains orderable elements.\nfunc isOr"
},
{
"path": "vendor/github.com/stretchr/testify/assert/assertions.go",
"chars": 66334,
"preview": "package assert\n\nimport (\n\t\"bufio\"\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"math\"\n\t\"os\"\n\t\"reflect\"\n\t\"regexp\"\n\t\"runtim"
},
{
"path": "vendor/github.com/stretchr/testify/assert/doc.go",
"chars": 1443,
"preview": "// Package assert provides a set of comprehensive testing tools for use with the normal Go testing system.\n//\n// # Note\n"
},
{
"path": "vendor/github.com/stretchr/testify/assert/errors.go",
"chars": 326,
"preview": "package assert\n\nimport (\n\t\"errors\"\n)\n\n// AnError is an error instance useful for testing. If the code does not care\n// "
},
{
"path": "vendor/github.com/stretchr/testify/assert/forward_assertions.go",
"chars": 428,
"preview": "package assert\n\n// Assertions provides assertion methods around the\n// TestingT interface.\ntype Assertions struct {\n\tt T"
},
{
"path": "vendor/github.com/stretchr/testify/assert/http_assertions.go",
"chars": 5724,
"preview": "package assert\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/http/httptest\"\n\t\"net/url\"\n\t\"strings\"\n)\n\n// httpCode is a helper that r"
},
{
"path": "vendor/github.com/stretchr/testify/assert/yaml/yaml_custom.go",
"chars": 727,
"preview": "//go:build testify_yaml_custom && !testify_yaml_fail && !testify_yaml_default\n\n// Package yaml is an implementation of Y"
},
{
"path": "vendor/github.com/stretchr/testify/assert/yaml/yaml_default.go",
"chars": 1510,
"preview": "//go:build !testify_yaml_fail && !testify_yaml_custom\n\n// Package yaml is just an indirection to handle YAML deserializa"
},
{
"path": "vendor/github.com/stretchr/testify/assert/yaml/yaml_fail.go",
"chars": 565,
"preview": "//go:build testify_yaml_fail && !testify_yaml_custom && !testify_yaml_default\n\n// Package yaml is an implementation of Y"
},
{
"path": "vendor/github.com/stretchr/testify/require/doc.go",
"chars": 1007,
"preview": "// Package require implements the same assertions as the `assert` package but\n// stops test execution when a test fails."
},
{
"path": "vendor/github.com/stretchr/testify/require/forward_requirements.go",
"chars": 428,
"preview": "package require\n\n// Assertions provides assertion methods around the\n// TestingT interface.\ntype Assertions struct {\n\tt "
},
{
"path": "vendor/github.com/stretchr/testify/require/require.go",
"chars": 67574,
"preview": "// Code generated with github.com/stretchr/testify/_codegen; DO NOT EDIT.\n\npackage require\n\nimport (\n\tassert \"github.com"
},
{
"path": "vendor/github.com/stretchr/testify/require/require.go.tmpl",
"chars": 217,
"preview": "{{ replace .Comment \"assert.\" \"require.\"}}\nfunc {{.DocInfo.Name}}(t TestingT, {{.Params}}) {\n\tif h, ok := t.(tHelper); o"
},
{
"path": "vendor/github.com/stretchr/testify/require/require_forward.go",
"chars": 61484,
"preview": "// Code generated with github.com/stretchr/testify/_codegen; DO NOT EDIT.\n\npackage require\n\nimport (\n\tassert \"github.com"
},
{
"path": "vendor/github.com/stretchr/testify/require/require_forward.go.tmpl",
"chars": 173,
"preview": "{{.CommentWithoutT \"a\"}}\nfunc (a *Assertions) {{.DocInfo.Name}}({{.Params}}) {\n\tif h, ok := a.t.(tHelper); ok { h.Helper"
},
{
"path": "vendor/github.com/stretchr/testify/require/requirements.go",
"chars": 1133,
"preview": "package require\n\n// TestingT is an interface wrapper around *testing.T\ntype TestingT interface {\n\tErrorf(format string, "
},
{
"path": "vendor/golang.org/x/net/LICENSE",
"chars": 1453,
"preview": "Copyright 2009 The Go Authors.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are per"
},
{
"path": "vendor/golang.org/x/net/PATENTS",
"chars": 1303,
"preview": "Additional IP Rights Grant (Patents)\n\n\"This implementation\" means the copyrightable works distributed by\nGoogle as part "
},
{
"path": "vendor/golang.org/x/net/bpf/asm.go",
"chars": 1267,
"preview": "// Copyright 2016 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/net/bpf/constants.go",
"chars": 6188,
"preview": "// Copyright 2016 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/net/bpf/doc.go",
"chars": 3217,
"preview": "// Copyright 2016 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/net/bpf/instructions.go",
"chars": 18103,
"preview": "// Copyright 2016 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/net/bpf/setter.go",
"chars": 310,
"preview": "// Copyright 2017 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/net/bpf/vm.go",
"chars": 4128,
"preview": "// Copyright 2016 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/net/bpf/vm_instructions.go",
"chars": 3964,
"preview": "// Copyright 2016 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/net/internal/iana/const.go",
"chars": 12123,
"preview": "// go generate gen.go\n// Code generated by the command above; DO NOT EDIT.\n\n// Package iana provides protocol number res"
},
{
"path": "vendor/golang.org/x/net/internal/socket/cmsghdr.go",
"chars": 427,
"preview": "// Copyright 2017 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/net/internal/socket/cmsghdr_bsd.go",
"chars": 352,
"preview": "// Copyright 2017 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/net/internal/socket/cmsghdr_linux_32bit.go",
"chars": 340,
"preview": "// Copyright 2017 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/net/internal/socket/cmsghdr_linux_64bit.go",
"chars": 392,
"preview": "// Copyright 2017 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/net/internal/socket/cmsghdr_solaris_64bit.go",
"chars": 310,
"preview": "// Copyright 2017 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/net/internal/socket/cmsghdr_stub.go",
"chars": 627,
"preview": "// Copyright 2017 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/net/internal/socket/cmsghdr_unix.go",
"chars": 516,
"preview": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/net/internal/socket/cmsghdr_zos_s390x.go",
"chars": 280,
"preview": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/net/internal/socket/complete_dontwait.go",
"chars": 734,
"preview": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/net/internal/socket/complete_nodontwait.go",
"chars": 559,
"preview": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/net/internal/socket/empty.s",
"chars": 245,
"preview": "// Copyright 2018 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/net/internal/socket/error_unix.go",
"chars": 711,
"preview": "// Copyright 2017 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/net/internal/socket/error_windows.go",
"chars": 588,
"preview": "// Copyright 2017 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/net/internal/socket/iovec_32bit.go",
"chars": 441,
"preview": "// Copyright 2017 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/net/internal/socket/iovec_64bit.go",
"chars": 507,
"preview": "// Copyright 2017 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/net/internal/socket/iovec_solaris_64bit.go",
"chars": 354,
"preview": "// Copyright 2017 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/net/internal/socket/iovec_stub.go",
"chars": 337,
"preview": "// Copyright 2017 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/net/internal/socket/mmsghdr_stub.go",
"chars": 541,
"preview": "// Copyright 2017 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/net/internal/socket/mmsghdr_unix.go",
"chars": 4564,
"preview": "// Copyright 2017 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/net/internal/socket/msghdr_bsd.go",
"chars": 872,
"preview": "// Copyright 2017 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/net/internal/socket/msghdr_bsdvar.go",
"chars": 352,
"preview": "// Copyright 2017 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/net/internal/socket/msghdr_linux.go",
"chars": 740,
"preview": "// Copyright 2017 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/net/internal/socket/msghdr_linux_32bit.go",
"chars": 487,
"preview": "// Copyright 2017 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/net/internal/socket/msghdr_linux_64bit.go",
"chars": 539,
"preview": "// Copyright 2017 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/net/internal/socket/msghdr_openbsd.go",
"chars": 293,
"preview": "// Copyright 2017 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/net/internal/socket/msghdr_solaris_64bit.go",
"chars": 784,
"preview": "// Copyright 2017 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/net/internal/socket/msghdr_stub.go",
"chars": 629,
"preview": "// Copyright 2017 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/net/internal/socket/msghdr_zos_s390x.go",
"chars": 716,
"preview": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/net/internal/socket/norace.go",
"chars": 261,
"preview": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/net/internal/socket/race.go",
"chars": 892,
"preview": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/net/internal/socket/rawconn.go",
"chars": 2206,
"preview": "// Copyright 2017 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/net/internal/socket/rawconn_mmsg.go",
"chars": 1234,
"preview": "// Copyright 2017 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/net/internal/socket/rawconn_msg.go",
"chars": 1214,
"preview": "// Copyright 2017 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/net/internal/socket/rawconn_nommsg.go",
"chars": 386,
"preview": "// Copyright 2017 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/net/internal/socket/rawconn_nomsg.go",
"chars": 460,
"preview": "// Copyright 2017 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/net/internal/socket/socket.go",
"chars": 7694,
"preview": "// Copyright 2017 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/net/internal/socket/sys_bsd.go",
"chars": 441,
"preview": "// Copyright 2017 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/net/internal/socket/sys_const_unix.go",
"chars": 533,
"preview": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/net/internal/socket/sys_linux.go",
"chars": 688,
"preview": "// Copyright 2017 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/net/internal/socket/sys_linux_386.go",
"chars": 847,
"preview": "// Copyright 2017 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/net/internal/socket/sys_linux_386.s",
"chars": 316,
"preview": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/net/internal/socket/sys_linux_amd64.go",
"chars": 228,
"preview": "// Copyright 2017 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/net/internal/socket/sys_linux_arm.go",
"chars": 228,
"preview": "// Copyright 2017 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/net/internal/socket/sys_linux_arm64.go",
"chars": 227,
"preview": "// Copyright 2017 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/net/internal/socket/sys_linux_loong64.go",
"chars": 247,
"preview": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/net/internal/socket/sys_linux_mips.go",
"chars": 230,
"preview": "// Copyright 2017 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/net/internal/socket/sys_linux_mips64.go",
"chars": 230,
"preview": "// Copyright 2017 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/net/internal/socket/sys_linux_mips64le.go",
"chars": 230,
"preview": "// Copyright 2017 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/net/internal/socket/sys_linux_mipsle.go",
"chars": 230,
"preview": "// Copyright 2017 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/net/internal/socket/sys_linux_ppc.go",
"chars": 228,
"preview": "// Copyright 2021 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/net/internal/socket/sys_linux_ppc64.go",
"chars": 228,
"preview": "// Copyright 2017 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/net/internal/socket/sys_linux_ppc64le.go",
"chars": 228,
"preview": "// Copyright 2017 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/net/internal/socket/sys_linux_riscv64.go",
"chars": 247,
"preview": "// Copyright 2019 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/net/internal/socket/sys_linux_s390x.go",
"chars": 847,
"preview": "// Copyright 2017 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/net/internal/socket/sys_linux_s390x.s",
"chars": 316,
"preview": "// Copyright 2017 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/net/internal/socket/sys_netbsd.go",
"chars": 705,
"preview": "// Copyright 2017 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/net/internal/socket/sys_posix.go",
"chars": 4979,
"preview": "// Copyright 2017 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/net/internal/socket/sys_stub.go",
"chars": 1326,
"preview": "// Copyright 2017 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/net/internal/socket/sys_unix.go",
"chars": 2950,
"preview": "// Copyright 2017 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/net/internal/socket/sys_windows.go",
"chars": 1457,
"preview": "// Copyright 2017 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/net/internal/socket/sys_zos_s390x.go",
"chars": 2052,
"preview": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/net/internal/socket/sys_zos_s390x.s",
"chars": 334,
"preview": "// Copyright 2020 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/net/internal/socket/zsys_aix_ppc64.go",
"chars": 543,
"preview": "// Code generated by cmd/cgo -godefs; DO NOT EDIT.\n// cgo -godefs defs_aix.go\n\n// Added for go1.11 compatibility\n//go:bu"
},
{
"path": "vendor/golang.org/x/net/internal/socket/zsys_darwin_amd64.go",
"chars": 456,
"preview": "// Code generated by cmd/cgo -godefs; DO NOT EDIT.\n// cgo -godefs defs_darwin.go\n\npackage socket\n\ntype iovec struct {\n\tB"
},
{
"path": "vendor/golang.org/x/net/internal/socket/zsys_darwin_arm64.go",
"chars": 456,
"preview": "// Code generated by cmd/cgo -godefs; DO NOT EDIT.\n// cgo -godefs defs_darwin.go\n\npackage socket\n\ntype iovec struct {\n\tB"
},
{
"path": "vendor/golang.org/x/net/internal/socket/zsys_dragonfly_amd64.go",
"chars": 459,
"preview": "// Code generated by cmd/cgo -godefs; DO NOT EDIT.\n// cgo -godefs defs_dragonfly.go\n\npackage socket\n\ntype iovec struct {"
},
{
"path": "vendor/golang.org/x/net/internal/socket/zsys_freebsd_386.go",
"chars": 416,
"preview": "// Code generated by cmd/cgo -godefs; DO NOT EDIT.\n// cgo -godefs defs_freebsd.go\n\npackage socket\n\ntype iovec struct {\n\t"
},
{
"path": "vendor/golang.org/x/net/internal/socket/zsys_freebsd_amd64.go",
"chars": 457,
"preview": "// Code generated by cmd/cgo -godefs; DO NOT EDIT.\n// cgo -godefs defs_freebsd.go\n\npackage socket\n\ntype iovec struct {\n\t"
},
{
"path": "vendor/golang.org/x/net/internal/socket/zsys_freebsd_arm.go",
"chars": 416,
"preview": "// Code generated by cmd/cgo -godefs; DO NOT EDIT.\n// cgo -godefs defs_freebsd.go\n\npackage socket\n\ntype iovec struct {\n\t"
},
{
"path": "vendor/golang.org/x/net/internal/socket/zsys_freebsd_arm64.go",
"chars": 457,
"preview": "// Code generated by cmd/cgo -godefs; DO NOT EDIT.\n// cgo -godefs defs_freebsd.go\n\npackage socket\n\ntype iovec struct {\n\t"
},
{
"path": "vendor/golang.org/x/net/internal/socket/zsys_freebsd_riscv64.go",
"chars": 417,
"preview": "// Code generated by cmd/cgo -godefs; DO NOT EDIT.\n// cgo -godefs defs_freebsd.go\n\npackage socket\n\ntype iovec struct {\n\t"
},
{
"path": "vendor/golang.org/x/net/internal/socket/zsys_linux_386.go",
"chars": 464,
"preview": "// Code generated by cmd/cgo -godefs; DO NOT EDIT.\n// cgo -godefs defs_linux.go\n\npackage socket\n\ntype iovec struct {\n\tBa"
},
{
"path": "vendor/golang.org/x/net/internal/socket/zsys_linux_amd64.go",
"chars": 536,
"preview": "// Code generated by cmd/cgo -godefs; DO NOT EDIT.\n// cgo -godefs defs_linux.go\n\npackage socket\n\ntype iovec struct {\n\tBa"
},
{
"path": "vendor/golang.org/x/net/internal/socket/zsys_linux_arm.go",
"chars": 464,
"preview": "// Code generated by cmd/cgo -godefs; DO NOT EDIT.\n// cgo -godefs defs_linux.go\n\npackage socket\n\ntype iovec struct {\n\tBa"
},
{
"path": "vendor/golang.org/x/net/internal/socket/zsys_linux_arm64.go",
"chars": 536,
"preview": "// Code generated by cmd/cgo -godefs; DO NOT EDIT.\n// cgo -godefs defs_linux.go\n\npackage socket\n\ntype iovec struct {\n\tBa"
},
{
"path": "vendor/golang.org/x/net/internal/socket/zsys_linux_loong64.go",
"chars": 536,
"preview": "// Code generated by cmd/cgo -godefs; DO NOT EDIT.\n// cgo -godefs defs_linux.go\n\n//go:build loong64\n\npackage socket\n\ntyp"
}
]
// ... and 522 more files (download for full content)
About this extraction
This page contains the full source code of the datarhei/gosrt GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 722 files (9.4 MB), approximately 2.5M tokens, and a symbol index with 100675 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.