Full Code of datarhei/gosrt for AI

main 6ab34b20337a cached
722 files
9.4 MB
2.5M tokens
100675 symbols
1 requests
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>

[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
![Tests](https://github.com/datarhei/gosrt/actions/workflows/go-tests.yml/badge.svg)
[![codecov](https://codecov.io/gh/datarhei/gosrt/branch/main/graph/badge.svg?token=90YMPZRAFK)](https://codecov.io/gh/datarhei/gosrt)
[![Go Report Card](https://goreportcard.com/badge/github.com/datarhei/gosrt)](https://goreportcard.com/report/github.com/datarhei/gosrt)
[![PkgGoDev](https://pkg.go.dev/badge/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
Download .txt
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
Download .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": "[![go.dev reference](https://img.shields.io/badge/go.dev-reference-007d9c?logo=go)](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[![Build Status](https://travis-ci.org/pkg/profile.svg?branch="
  },
  {
    "path": "vendor/github.com/pkg/profile/profile.go",
    "chars": 8749,
    "preview": "// Package profile provides a simple way to manage runtime/pprof\n// profiling of your Go application.\npackage profile\n\ni"
  },
  {
    "path": "vendor/github.com/pmezard/go-difflib/LICENSE",
    "chars": 1445,
    "preview": "Copyright (c) 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.

Copied to clipboard!