This commit is contained in:
2018-11-04 15:58:15 +01:00
commit f956bcee28
1178 changed files with 584552 additions and 0 deletions

19
vendor/github.com/anacrolix/go-libutp/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,19 @@
Copyright (c) 2010-2013 BitTorrent, Inc.
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.

8
vendor/github.com/anacrolix/go-libutp/README.md generated vendored Normal file
View File

@@ -0,0 +1,8 @@
# go-libutp
[![GoDoc](https://godoc.org/github.com/anacrolix/go-libutp?status.svg)](http://godoc.org/github.com/anacrolix/go-libutp)
[![CircleCI](https://circleci.com/gh/anacrolix/go-libutp.svg?style=shield)](https://circleci.com/gh/anacrolix/go-libutp)
[![Go Report Card](https://goreportcard.com/badge/github.com/anacrolix/go-libutp)](https://goreportcard.com/report/github.com/anacrolix/go-libutp)
[![Appveyor Status](https://ci.appveyor.com/api/projects/status/github/anacrolix/go-libutp?branch=master&svg=true)](https://ci.appveyor.com/project/anacrolix/go-libutp)
This is a Go wrapper for [libutp](https://github.com/bittorrent/libutp).

21
vendor/github.com/anacrolix/go-libutp/appveyor.yml generated vendored Normal file
View File

@@ -0,0 +1,21 @@
image:
- Visual Studio 2017
environment:
GOPATH: c:\gopath
install:
- set PATH=%GOPATH%\bin;%PATH%
- set PATH=C:\msys64\mingw64\bin;%PATH%
- go get github.com/anacrolix/envpprof
- go get github.com/anacrolix/tagflag
- go get github.com/stretchr/testify/assert
- go get github.com/anacrolix/mmsg
- go get golang.org/x/net/nettest
- go get github.com/anacrolix/sync
build_script:
- go build -v -x -a
before_test:
- go test -v

173
vendor/github.com/anacrolix/go-libutp/callbacks.go generated vendored Normal file
View File

@@ -0,0 +1,173 @@
package utp
/*
#include "utp.h"
*/
import "C"
import (
"log"
"reflect"
"strings"
"sync/atomic"
"unsafe"
)
func (a *C.utp_callback_arguments) bufBytes() []byte {
return *(*[]byte)(unsafe.Pointer(&reflect.SliceHeader{
uintptr(unsafe.Pointer(a.buf)),
int(a.len),
int(a.len),
}))
}
func (a *C.utp_callback_arguments) state() C.int {
return *(*C.int)(unsafe.Pointer(&a.anon0))
}
func (a *C.utp_callback_arguments) error_code() C.int {
return *(*C.int)(unsafe.Pointer(&a.anon0))
}
func (a *C.utp_callback_arguments) address() *C.struct_sockaddr {
return *(**C.struct_sockaddr)(unsafe.Pointer(&a.anon0[0]))
}
func (a *C.utp_callback_arguments) addressLen() C.socklen_t {
return *(*C.socklen_t)(unsafe.Pointer(&a.anon1[0]))
}
var sends int64
//export sendtoCallback
func sendtoCallback(a *C.utp_callback_arguments) (ret C.uint64) {
s := getSocketForLibContext(a.context)
b := a.bufBytes()
addr := structSockaddrToUDPAddr(a.address())
newSends := atomic.AddInt64(&sends, 1)
if logCallbacks {
Logger.Printf("sending %d bytes, %d packets", len(b), newSends)
}
expMap.Add("socket PacketConn writes", 1)
n, err := s.pc.WriteTo(b, addr)
c := s.conns[a.socket]
if err != nil {
expMap.Add("socket PacketConn write errors", 1)
if c != nil && c.userOnError != nil {
go c.userOnError(err)
} else if c != nil &&
(strings.Contains(err.Error(), "can't assign requested address") ||
strings.Contains(err.Error(), "invalid argument")) {
// Should be an bad argument or network configuration problem we
// can't recover from.
c.onError(err)
} else if c != nil && strings.Contains(err.Error(), "operation not permitted") {
// Rate-limited. Probably Linux. The implementation might try
// again later.
} else {
Logger.Printf("error sending packet: %s", err)
}
return
}
if n != len(b) {
expMap.Add("socket PacketConn short writes", 1)
Logger.Printf("expected to send %d bytes but only sent %d", len(b), n)
}
return
}
//export errorCallback
func errorCallback(a *C.utp_callback_arguments) C.uint64 {
err := errorForCode(a.error_code())
if logCallbacks {
log.Printf("error callback: socket %p: %s", a.socket, err)
}
libContextToSocket[a.context].conns[a.socket].onError(err)
return 0
}
//export logCallback
func logCallback(a *C.utp_callback_arguments) C.uint64 {
Logger.Printf("libutp: %s", C.GoString((*C.char)(unsafe.Pointer(a.buf))))
return 0
}
//export stateChangeCallback
func stateChangeCallback(a *C.utp_callback_arguments) C.uint64 {
s := libContextToSocket[a.context]
c := s.conns[a.socket]
if logCallbacks {
Logger.Printf("state changed: conn %p: %s", c, libStateName(a.state()))
}
switch a.state() {
case C.UTP_STATE_CONNECT:
c.setConnected()
// A dialled connection will not tell the remote it's ready until it
// writes. If the dialer has no intention of writing, this will stall
// everything. We do an empty write to get things rolling again. This
// circumstance occurs when c1 in the RacyRead nettest is the dialer.
C.utp_write(a.socket, nil, 0)
case C.UTP_STATE_WRITABLE:
c.cond.Broadcast()
case C.UTP_STATE_EOF:
c.setGotEOF()
case C.UTP_STATE_DESTROYING:
c.onDestroyed()
s.onLibSocketDestroyed(a.socket)
default:
panic(a.state)
}
return 0
}
//export readCallback
func readCallback(a *C.utp_callback_arguments) C.uint64 {
s := libContextToSocket[a.context]
c := s.conns[a.socket]
b := a.bufBytes()
if logCallbacks {
log.Printf("read callback: conn %p: %d bytes", c, len(b))
}
if len(b) == 0 {
panic("that will break the read drain invariant")
}
c.readBuf.Write(b)
c.cond.Broadcast()
return 0
}
//export acceptCallback
func acceptCallback(a *C.utp_callback_arguments) C.uint64 {
if logCallbacks {
log.Printf("accept callback: %#v", *a)
}
s := getSocketForLibContext(a.context)
c := s.newConn(a.socket)
c.setRemoteAddr()
c.inited = true
s.pushBacklog(c)
return 0
}
//export getReadBufferSizeCallback
func getReadBufferSizeCallback(a *C.utp_callback_arguments) (ret C.uint64) {
s := libContextToSocket[a.context]
c := s.conns[a.socket]
if c == nil {
// socket hasn't been added to the Socket.conns yet. The read buffer
// starts out empty, and the default implementation for this callback
// returns 0, so we'll return that.
return 0
}
ret = C.uint64(c.readBuf.Len())
return
}
//export firewallCallback
func firewallCallback(a *C.utp_callback_arguments) C.uint64 {
s := getSocketForLibContext(a.context)
if s.block {
return 1
} else {
return 0
}
}

327
vendor/github.com/anacrolix/go-libutp/conn.go generated vendored Normal file
View File

@@ -0,0 +1,327 @@
package utp
/*
#include "utp.h"
*/
import "C"
import (
"bytes"
"context"
"errors"
"fmt"
"io"
"net"
"runtime/pprof"
"sync"
"syscall"
"time"
"unsafe"
)
var (
ErrConnClosed = errors.New("closed")
errConnDestroyed = errors.New("destroyed")
)
type Conn struct {
s *Socket
us *C.utp_socket
cond sync.Cond
readBuf bytes.Buffer
gotEOF bool
gotConnect bool
// Set on state changed to UTP_STATE_DESTROYING. Not valid to refer to the
// socket after getting this.
destroyed bool
// Conn.Close was called.
closed bool
// Corresponds to utp_socket.state != CS_UNITIALIZED. This requires the
// utp_socket was obtained from the accept callback, or has had
// utp_connect called on it. We can't call utp_close until it's true.
inited bool
err error
writeDeadline time.Time
writeDeadlineTimer *time.Timer
readDeadline time.Time
readDeadlineTimer *time.Timer
numBytesRead int64
numBytesWritten int64
localAddr net.Addr
remoteAddr net.Addr
// Called for non-fatal errors, such as packet write errors.
userOnError func(error)
}
func (c *Conn) onError(err error) {
c.err = err
c.cond.Broadcast()
}
func (c *Conn) setConnected() {
c.gotConnect = true
c.cond.Broadcast()
}
func (c *Conn) waitForConnect(ctx context.Context) error {
ctx, cancel := context.WithCancel(ctx)
defer cancel()
go func() {
<-ctx.Done()
c.cond.Broadcast()
}()
for {
if c.closed {
return ErrConnClosed
}
if c.err != nil {
return c.err
}
if c.gotConnect {
return nil
}
if ctx.Err() != nil {
return ctx.Err()
}
c.cond.Wait()
}
}
func (c *Conn) Close() error {
mu.Lock()
defer mu.Unlock()
c.close()
return nil
}
func (c *Conn) close() {
if c.inited && !c.destroyed && !c.closed {
C.utp_close(c.us)
}
if !c.inited {
// We'll never receive a destroy message, so we should remove it now.
delete(c.s.conns, c.us)
}
c.closed = true
c.cond.Broadcast()
}
func (c *Conn) LocalAddr() net.Addr {
return c.localAddr
}
func (c *Conn) readNoWait(b []byte) (n int, err error) {
n, _ = c.readBuf.Read(b)
if n != 0 && c.readBuf.Len() == 0 {
// Can we call this if the utp_socket is closed, destroyed or errored?
if c.us != nil {
C.utp_read_drained(c.us)
// C.utp_issue_deferred_acks(C.utp_get_context(c.s))
}
}
if c.readBuf.Len() != 0 {
return
}
err = func() error {
switch {
case c.gotEOF:
return io.EOF
case c.err != nil:
return c.err
case c.destroyed:
return errConnDestroyed
case c.closed:
return errors.New("closed")
case !c.readDeadline.IsZero() && !time.Now().Before(c.readDeadline):
return errDeadlineExceeded{}
default:
return nil
}
}()
return
}
func (c *Conn) Read(b []byte) (int, error) {
mu.Lock()
defer mu.Unlock()
for {
n, err := c.readNoWait(b)
c.numBytesRead += int64(n)
// log.Printf("read %d bytes", c.numBytesRead)
if n != 0 || len(b) == 0 || err != nil {
// log.Printf("conn %p: read %d bytes: %s", c, n, err)
return n, err
}
c.cond.Wait()
}
}
func (c *Conn) writeNoWait(b []byte) (n int, err error) {
err = func() error {
switch {
case c.err != nil:
return c.err
case c.closed:
return ErrConnClosed
case c.destroyed:
return errConnDestroyed
case !c.writeDeadline.IsZero() && !time.Now().Before(c.writeDeadline):
return errDeadlineExceeded{}
default:
return nil
}
}()
if err != nil {
return
}
pprof.Do(context.Background(), pprof.Labels("cgo", "utp_write"), func(context.Context) {
n = int(C.utp_write(c.us, unsafe.Pointer(&b[0]), C.size_t(len(b))))
})
if n < 0 {
panic(n)
}
return
}
func (c *Conn) Write(b []byte) (n int, err error) {
mu.Lock()
defer mu.Unlock()
for len(b) != 0 {
var n1 int
n1, err = c.writeNoWait(b)
b = b[n1:]
n += n1
if err != nil {
break
}
if n1 != 0 {
continue
}
c.cond.Wait()
}
c.numBytesWritten += int64(n)
// log.Printf("wrote %d bytes", c.numBytesWritten)
return
}
func (c *Conn) setRemoteAddr() {
var rsa syscall.RawSockaddrAny
var addrlen C.socklen_t = C.socklen_t(unsafe.Sizeof(rsa))
C.utp_getpeername(c.us, (*C.struct_sockaddr)(unsafe.Pointer(&rsa)), &addrlen)
sa, err := anyToSockaddr(&rsa)
if err != nil {
panic(err)
}
c.remoteAddr = sockaddrToUDP(sa)
}
func (c *Conn) RemoteAddr() net.Addr {
return c.remoteAddr
}
func (c *Conn) SetDeadline(t time.Time) error {
mu.Lock()
defer mu.Unlock()
c.readDeadline = t
c.writeDeadline = t
if t.IsZero() {
c.readDeadlineTimer.Stop()
c.writeDeadlineTimer.Stop()
} else {
d := t.Sub(time.Now())
c.readDeadlineTimer.Reset(d)
c.writeDeadlineTimer.Reset(d)
}
c.cond.Broadcast()
return nil
}
func (c *Conn) SetReadDeadline(t time.Time) error {
mu.Lock()
defer mu.Unlock()
c.readDeadline = t
if t.IsZero() {
c.readDeadlineTimer.Stop()
} else {
d := t.Sub(time.Now())
c.readDeadlineTimer.Reset(d)
}
c.cond.Broadcast()
return nil
}
func (c *Conn) SetWriteDeadline(t time.Time) error {
mu.Lock()
defer mu.Unlock()
c.writeDeadline = t
if t.IsZero() {
c.writeDeadlineTimer.Stop()
} else {
d := t.Sub(time.Now())
c.writeDeadlineTimer.Reset(d)
}
c.cond.Broadcast()
return nil
}
func (c *Conn) setGotEOF() {
c.gotEOF = true
c.cond.Broadcast()
}
func (c *Conn) onDestroyed() {
c.destroyed = true
c.us = nil
c.cond.Broadcast()
}
func (c *Conn) WriteBufferLen() int {
mu.Lock()
defer mu.Unlock()
return int(C.utp_getsockopt(c.us, C.UTP_SNDBUF))
}
func (c *Conn) SetWriteBufferLen(len int) {
mu.Lock()
defer mu.Unlock()
i := C.utp_setsockopt(c.us, C.UTP_SNDBUF, C.int(len))
if i != 0 {
panic(i)
}
}
// Connect an unconnected Conn (obtained through Socket.NewConn).
func (c *Conn) Connect(ctx context.Context, network, addr string) error {
if network == "" {
network = c.localAddr.Network()
}
ua, err := resolveAddr(network, addr)
if err != nil {
return fmt.Errorf("error resolving address: %v", err)
}
sa, sl := netAddrToLibSockaddr(ua)
mu.Lock()
defer mu.Unlock()
if c.s.closed {
return errSocketClosed
}
if n := C.utp_connect(c.us, sa, sl); n != 0 {
panic(n)
}
c.inited = true
c.setRemoteAddr()
err = c.waitForConnect(ctx)
if err != nil {
c.close()
return err
}
return nil
}
func (c *Conn) OnError(f func(error)) {
mu.Lock()
c.userOnError = f
mu.Unlock()
}

11
vendor/github.com/anacrolix/go-libutp/deadline.go generated vendored Normal file
View File

@@ -0,0 +1,11 @@
package utp
import "net"
type errDeadlineExceeded struct{}
var _ net.Error = errDeadlineExceeded{}
func (errDeadlineExceeded) Error() string { return "deadline exceeded" }
func (errDeadlineExceeded) Temporary() bool { return false }
func (errDeadlineExceeded) Timeout() bool { return true }

14
vendor/github.com/anacrolix/go-libutp/expvars.go generated vendored Normal file
View File

@@ -0,0 +1,14 @@
package utp
import (
"expvar"
)
var (
expMap = expvar.NewMap("go-libutp")
socketUtpPacketsReceived = expvar.NewInt("utpSocketUtpPacketsReceived")
socketNonUtpPacketsReceived = expvar.NewInt("utpSocketNonUtpPacketsReceived")
nonUtpPacketsDropped = expvar.NewInt("utpNonUtpPacketsDropped")
multiMsgRecvs = expvar.NewInt("utpMultiMsgRecvs")
singleMsgRecvs = expvar.NewInt("utpSingleMsgRecvs")
)

16
vendor/github.com/anacrolix/go-libutp/go.mod generated vendored Normal file
View File

@@ -0,0 +1,16 @@
module github.com/anacrolix/go-libutp
require (
github.com/anacrolix/envpprof v0.0.0-20180404065416-323002cec2fa
github.com/anacrolix/missinggo v0.0.0-20180725070939-60ef2fbf63df
github.com/anacrolix/mmsg v0.0.0-20180515031531-a4a3ba1fc8bb
github.com/anacrolix/sync v0.0.0-20180808010631-44578de4e778
github.com/anacrolix/tagflag v0.0.0-20180109131632-2146c8d41bf0
github.com/bradfitz/iter v0.0.0-20140124041915-454541ec3da2
github.com/davecgh/go-spew v1.1.0 // indirect
github.com/dustin/go-humanize v0.0.0-20180421182945-02af3965c54e
github.com/huandu/xstrings v1.0.0
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/stretchr/testify v1.2.1
golang.org/x/net v0.0.0-20180524181706-dfa909b99c79
)

36
vendor/github.com/anacrolix/go-libutp/go.sum generated vendored Normal file
View File

@@ -0,0 +1,36 @@
github.com/RoaringBitmap/roaring v0.4.7/go.mod h1:8khRDP4HmeXns4xIj9oGrKSz7XTQiJx2zgh7AcNke4w=
github.com/anacrolix/envpprof v0.0.0-20180404065416-323002cec2fa h1:xCaATLKmn39QqLs3tUZYr6eKvezJV+FYvVOLTklxK6U=
github.com/anacrolix/envpprof v0.0.0-20180404065416-323002cec2fa/go.mod h1:KgHhUaQMc8cC0+cEflSgCFNFbKwi5h54gqtVn8yhP7c=
github.com/anacrolix/missinggo v0.0.0-20180522035225-b4a5853e62ff h1:c2Hrwd+LaVrsLJQ5nV8dAP4z6iM0G6aewsbrj3x515s=
github.com/anacrolix/missinggo v0.0.0-20180522035225-b4a5853e62ff/go.mod h1:b0p+7cn+rWMIphK1gDH2hrDuwGOcbB6V4VXeSsEfHVk=
github.com/anacrolix/missinggo v0.0.0-20180725070939-60ef2fbf63df h1:+se8qhX5ivmSCkP+gZXyFx2ETjk1pmnrYJ0Iyc+hZKY=
github.com/anacrolix/missinggo v0.0.0-20180725070939-60ef2fbf63df/go.mod h1:kwGiTUTZ0+p4vAz3VbAI5a30t2YbvemcmspjKwrAz5s=
github.com/anacrolix/mmsg v0.0.0-20180515031531-a4a3ba1fc8bb h1:2Or5ccMoY4Kfao+WdL2w6tpY6ZEe+2VTVbIPd7A/Ajk=
github.com/anacrolix/mmsg v0.0.0-20180515031531-a4a3ba1fc8bb/go.mod h1:x2/ErsYUmT77kezS63+wzZp8E3byYB0gzirM/WMBLfw=
github.com/anacrolix/sync v0.0.0-20180725074606-fda11526ff08 h1:w0QQ3EPXGMOFLBRvBk7vCeNkfreNQ5xhTzUIDIEdNm0=
github.com/anacrolix/sync v0.0.0-20180725074606-fda11526ff08/go.mod h1:+u91KiUuf0lyILI6x3n/XrW7iFROCZCG+TjgK8nW52w=
github.com/anacrolix/sync v0.0.0-20180808010631-44578de4e778 h1:XpCDEixzXOB8yaTW/4YBzKrJdMcFI0DzpPTYNv75wzk=
github.com/anacrolix/sync v0.0.0-20180808010631-44578de4e778/go.mod h1:s735Etp3joe/voe2sdaXLcqDdJSay1O0OPnM0ystjqk=
github.com/anacrolix/tagflag v0.0.0-20180109131632-2146c8d41bf0 h1:xcd2GmlPWBsGNjdbwriHXvJJtagl1AnbjTPhJTksJDQ=
github.com/anacrolix/tagflag v0.0.0-20180109131632-2146c8d41bf0/go.mod h1:1m2U/K6ZT+JZG0+bdMK6qauP49QT4wE5pmhJXOKKCHw=
github.com/bradfitz/iter v0.0.0-20140124041915-454541ec3da2 h1:1B/+1BcRhOMG1KH/YhNIU8OppSWk5d/NGyfRla88CuY=
github.com/bradfitz/iter v0.0.0-20140124041915-454541ec3da2/go.mod h1:PyRFw1Lt2wKX4ZVSQ2mk+PeDa1rxyObEDlApuIsUKuo=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
github.com/dustin/go-humanize v0.0.0-20180421182945-02af3965c54e h1:Fw7ZmgiklsLh5EQWyHh1sumKSCG1+yjEctIpGKib87s=
github.com/dustin/go-humanize v0.0.0-20180421182945-02af3965c54e/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/glycerine/go-unsnap-stream v0.0.0-20180323001048-9f0cb55181dd/go.mod h1:/20jfyN9Y5QPEAprSgKAUr+glWDY39ZiUEAYOEv5dsE=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/btree v0.0.0-20180124185431-e89373fe6b4a/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/huandu/xstrings v1.0.0 h1:pO2K/gKgKaat5LdpAhxhluX2GPQMaI3W5FUz/I/UnWk=
github.com/huandu/xstrings v1.0.0/go.mod h1:4qWG/gcEcfX4z/mBDHJ++3ReCw9ibxbsNJbcucJdbSo=
github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/ryszard/goskiplist v0.0.0-20150312221310-2dfbae5fcf46/go.mod h1:uAQ5PCi+MFsC7HjREoAz1BU+Mq60+05gifQSsHSDG/8=
github.com/stretchr/testify v1.2.1 h1:52QO5WkIUcHGIR7EnGagH88x1bUzqGXTC5/1bDTUQ7U=
github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/tinylib/msgp v1.0.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE=
golang.org/x/net v0.0.0-20180524181706-dfa909b99c79 h1:1FDlG4HI84rVePw1/0E/crL5tt2N+1blLJpY6UZ6krs=
golang.org/x/net v0.0.0-20180524181706-dfa909b99c79/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=

37
vendor/github.com/anacrolix/go-libutp/libapi.go generated vendored Normal file
View File

@@ -0,0 +1,37 @@
package utp
/*
#include "utp.h"
*/
import "C"
import (
"errors"
"github.com/anacrolix/sync"
)
type Option = C.int
const (
LogNormal Option = C.UTP_LOG_NORMAL
LogMtu Option = C.UTP_LOG_MTU
LogDebug Option = C.UTP_LOG_DEBUG
SendBuffer Option = C.UTP_SNDBUF
RecvBuffer Option = C.UTP_RCVBUF
TargetDelay Option = C.UTP_TARGET_DELAY
TimedOut = C.UTP_ETIMEDOUT
)
var (
mu sync.Mutex
libContextToSocket = map[*C.utp_context]*Socket{}
)
func getSocketForLibContext(uc *C.utp_context) *Socket {
return libContextToSocket[uc]
}
func errorForCode(code C.int) error {
return errors.New(libErrorCodeNames(code))
}

View File

@@ -0,0 +1,65 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="utp_templates.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="utp_callbacks.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="utp_hash.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="utp_internal.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="utp_packedsockaddr.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="utp_utils.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="utp_types.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="utp.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="libutp_inet_ntop.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="utp_api.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="utp_callbacks.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="utp_hash.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="utp_internal.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="utp_packedsockaddr.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="utp_utils.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="libutp_inet_ntop.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

258
vendor/github.com/anacrolix/go-libutp/libutp.vcxproj generated vendored Normal file
View File

@@ -0,0 +1,258 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="WinRTDebug|Win32">
<Configuration>WinRTDebug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="WinRTDebug|x64">
<Configuration>WinRTDebug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="WinRTRelease|Win32">
<Configuration>WinRTRelease</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="WinRTRelease|x64">
<Configuration>WinRTRelease</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClInclude Include="utp_templates.h" />
<ClInclude Include="utp.h" />
<ClInclude Include="utp_callbacks.h" />
<ClInclude Include="utp_hash.h" />
<ClInclude Include="utp_internal.h" />
<ClInclude Include="utp_packedsockaddr.h" />
<ClInclude Include="utp_utils.h" />
<ClInclude Include="utp_types.h" />
<ClInclude Include="libutp_inet_ntop.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="libutp_inet_ntop.cpp" />
<ClCompile Include="utp_api.cpp" />
<ClCompile Include="utp_callbacks.cpp" />
<ClCompile Include="utp_hash.cpp" />
<ClCompile Include="utp_internal.cpp" />
<ClCompile Include="utp_packedsockaddr.cpp" />
<ClCompile Include="utp_utils.cpp" />
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{5984D5CD-6ADD-4EB7-82E7-A555888FBBBD}</ProjectGuid>
<RootNamespace>libutp2012</RootNamespace>
<ProjectName>libutp</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140_xp</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='WinRTDebug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v120_xp</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='WinRTDebug|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140_xp</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='WinRTRelease|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v120_xp</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='WinRTRelease|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="prop_sheets\win32-2012.props" />
<Import Project="prop_sheets\debug-2012.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='WinRTDebug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="prop_sheets\win32-2012.props" />
<Import Project="prop_sheets\debug-2012.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="prop_sheets\x64-2012.props" />
<Import Project="prop_sheets\debug-2012.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='WinRTDebug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="prop_sheets\x64-2012.props" />
<Import Project="prop_sheets\debug-2012.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="prop_sheets\win32-2012.props" />
<Import Project="prop_sheets\release-2012.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='WinRTRelease|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="prop_sheets\win32-2012.props" />
<Import Project="prop_sheets\release-2012.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="prop_sheets\x64-2012.props" />
<Import Project="prop_sheets\release-2012.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='WinRTRelease|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="prop_sheets\x64-2012.props" />
<Import Project="prop_sheets\release-2012.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<ExceptionHandling>Sync</ExceptionHandling>
<DisableSpecificWarnings>4996</DisableSpecificWarnings>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='WinRTDebug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='WinRTDebug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>_WIN32_WINNT=0x501;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ExceptionHandling>Sync</ExceptionHandling>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='WinRTRelease|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='WinRTRelease|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@@ -0,0 +1,68 @@
#ifndef LIBUTP_INET_NTOP_H
#define LIBUTP_INET_NTOP_H
/*
* Copyright (c) 2010-2013 BitTorrent, Inc.
*
* 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.
*/
// About us linking the system inet_pton and inet_ntop symbols:
// 1) These symbols are usually defined on POSIX systems
// 2) They are not defined on Windows versions earlier than Vista
// Defined in:
// ut_utils/src/sockaddr.cpp
// libutp/win32_inet_ntop.obj
//
// When we drop support for XP we can just #include <ws2tcpip.h>, and use the system functions
// For now, we will always use our functions on windows, on all builds
// The reason is: we would like the debug build to behave as much as the release build as possible
// It is much better to catch a problem in the debug build, than to link the system version
// in debug, and our version int he wild.
#if defined(_WIN32_WINNT)
#if _WIN32_WINNT >= 0x600 // Win32, post-XP
#include <ws2tcpip.h> // for inet_ntop, inet_pton
#define INET_NTOP inet_ntop
#define INET_PTON inet_pton
#else
#define INET_NTOP libutp::inet_ntop // Win32, pre-XP: Use ours
#define INET_PTON libutp::inet_pton
#endif
#else // not WIN32
#include <arpa/inet.h> // for inet_ntop, inet_pton
#define INET_NTOP inet_ntop
#define INET_PTON inet_pton
#endif
//######################################################################
//######################################################################
namespace libutp {
//######################################################################
const char *inet_ntop(int af, const void *src, char *dest, size_t length);
//######################################################################
int inet_pton(int af, const char* src, void* dest);
} //namespace libutp
#endif // LIBUTP_INET_NTOP_H

13
vendor/github.com/anacrolix/go-libutp/logging.go generated vendored Normal file
View File

@@ -0,0 +1,13 @@
package utp
import (
"log"
"os"
)
const (
logCallbacks = false
utpLogging = false
)
var Logger = log.New(os.Stderr, "go-libutp: ", log.LstdFlags|log.Lshortfile)

288
vendor/github.com/anacrolix/go-libutp/parse_log.py generated vendored Normal file
View File

@@ -0,0 +1,288 @@
import os, sys, time
# usage: parse_log.py log-file [socket-index to focus on]
socket_filter = None
if len(sys.argv) >= 3:
socket_filter = sys.argv[2].strip()
if socket_filter == None:
print "scanning for socket with the most packets"
file = open(sys.argv[1], 'rb')
sockets = {}
for l in file:
if not 'our_delay' in l: continue
try:
a = l.strip().split(" ")
socket_index = a[1][:-1]
except:
continue
# msvc's runtime library doesn't prefix pointers
# with '0x'
# if socket_index[:2] != '0x':
# continue
if socket_index in sockets:
sockets[socket_index] += 1
else:
sockets[socket_index] = 1
items = sockets.items()
items.sort(lambda x, y: y[1] - x[1])
count = 0
for i in items:
print '%s: %d' % (i[0], i[1])
count += 1
if count > 5: break
file.close()
socket_filter = items[0][0]
print '\nfocusing on socket %s' % socket_filter
file = open(sys.argv[1], 'rb')
out_file = 'utp.out%s' % socket_filter;
out = open(out_file, 'wb')
delay_samples = 'dots lc rgb "blue"'
delay_base = 'steps lw 2 lc rgb "purple"'
target_delay = 'steps lw 2 lc rgb "red"'
off_target = 'dots lc rgb "blue"'
cwnd = 'steps lc rgb "green"'
window_size = 'steps lc rgb "sea-green"'
rtt = 'lines lc rgb "light-blue"'
metrics = {
'our_delay':['our delay (ms)', 'x1y2', delay_samples],
'upload_rate':['send rate (B/s)', 'x1y1', 'lines'],
'max_window':['cwnd (B)', 'x1y1', cwnd],
'target_delay':['target delay (ms)', 'x1y2', target_delay],
'cur_window':['bytes in-flight (B)', 'x1y1', window_size],
'cur_window_packets':['number of packets in-flight', 'x1y2', 'steps'],
'packet_size':['current packet size (B)', 'x1y2', 'steps'],
'rtt':['rtt (ms)', 'x1y2', rtt],
'off_target':['off-target (ms)', 'x1y2', off_target],
'delay_sum':['delay sum (ms)', 'x1y2', 'steps'],
'their_delay':['their delay (ms)', 'x1y2', delay_samples],
'get_microseconds':['clock (us)', 'x1y1', 'steps'],
'wnduser':['advertised window size (B)', 'x1y1', 'steps'],
'delay_base':['delay base (us)', 'x1y1', delay_base],
'their_delay_base':['their delay base (us)', 'x1y1', delay_base],
'their_actual_delay':['their actual delay (us)', 'x1y1', delay_samples],
'actual_delay':['actual_delay (us)', 'x1y1', delay_samples]
}
histogram_quantization = 1
socket_index = None
columns = []
begin = None
title = "-"
packet_loss = 0
packet_timeout = 0
delay_histogram = {}
window_size = {'0': 0, '1': 0}
# [35301484] 0x00ec1190: actual_delay:1021583 our_delay:102 their_delay:-1021345 off_target:297 max_window:2687 upload_rate:18942 delay_base:1021481154 delay_sum:-1021242 target_delay:400 acked_bytes:1441 cur_window:2882 scaled_gain:2.432
counter = 0
print "reading log file"
for l in file:
if "UTP_Connect" in l:
title = l[:-2]
if socket_filter != None:
title += ' socket: %s' % socket_filter
else:
title += ' sum of all sockets'
continue
try:
a = l.strip().split(" ")
t = a[0][1:-1]
socket_index = a[1][:-1]
except:
continue
# if socket_index[:2] != '0x':
# continue
if socket_filter != None and socket_index != socket_filter:
continue
counter += 1
if (counter % 300 == 0):
print "\r%d " % counter,
if "lost." in l:
packet_loss = packet_loss + 1
continue
if "Packet timeout" in l:
packet_timeout = packet_timeout + 1
continue
if "our_delay:" not in l:
continue
# used for Logf timestamps
# t, m = t.split(".")
# t = time.strptime(t, "%H:%M:%S")
# t = list(t)
# t[0] += 107
# t = tuple(t)
# m = float(m)
# m /= 1000.0
# t = time.mktime(t) + m
# used for tick count timestamps
t = int(t)
if begin is None:
begin = t
t = t - begin
# print time. Convert from milliseconds to seconds
print >>out, '%f\t' % (float(t)/1000.),
#if t > 200000:
# break
fill_columns = not columns
for i in a[2:]:
try:
n, v = i.split(':')
except:
continue
v = float(v)
if n == "our_delay":
bucket = v / histogram_quantization
delay_histogram[bucket] = 1 + delay_histogram.get(bucket, 0)
if not n in metrics: continue
if fill_columns:
columns.append(n)
if n == "max_window":
window_size[socket_index] = v
print >>out, '%f\t' % int(reduce(lambda a,b: a+b, window_size.values())),
else:
print >>out, '%f\t' % v,
print >>out, float(packet_loss * 8000), float(packet_timeout * 8000)
packet_loss = 0
packet_timeout = 0
out.close()
out = open('%s.histogram' % out_file, 'wb')
for d,f in delay_histogram.iteritems():
print >>out, float(d*histogram_quantization) + histogram_quantization / 2, f
out.close()
plot = [
{
'data': ['upload_rate', 'max_window', 'cur_window', 'wnduser', 'cur_window_packets', 'packet_size', 'rtt'],
'title': 'send-packet-size',
'y1': 'Bytes',
'y2': 'Time (ms)'
},
{
'data': ['our_delay', 'max_window', 'target_delay', 'cur_window', 'wnduser', 'cur_window_packets'],
'title': 'uploading',
'y1': 'Bytes',
'y2': 'Time (ms)'
},
{
'data': ['our_delay', 'max_window', 'target_delay', 'cur_window', 'cur_window_packets'],
'title': 'uploading_packets',
'y1': 'Bytes',
'y2': 'Time (ms)'
},
{
'data': ['get_microseconds'],
'title': 'timer',
'y1': 'Time microseconds',
'y2': 'Time (ms)'
},
{
'data': ['their_delay', 'target_delay', 'rtt'],
'title': 'their_delay',
'y1': '',
'y2': 'Time (ms)'
},
{
'data': ['their_actual_delay','their_delay_base'],
'title': 'their_delay_base',
'y1': 'Time (us)',
'y2': ''
},
{
'data': ['our_delay', 'target_delay', 'rtt'],
'title': 'our-delay',
'y1': '',
'y2': 'Time (ms)'
},
{
'data': ['actual_delay', 'delay_base'],
'title': 'our_delay_base',
'y1': 'Time (us)',
'y2': ''
}
]
out = open('utp.gnuplot', 'w+')
files = ''
#print >>out, 'set xtics 0, 20'
print >>out, "set term png size 1280,800"
print >>out, 'set output "%s.delays.png"' % out_file
print >>out, 'set xrange [0:250]'
print >>out, 'set xlabel "delay (ms)"'
print >>out, 'set boxwidth 1'
print >>out, 'set style fill solid'
print >>out, 'set ylabel "number of packets"'
print >>out, 'plot "%s.histogram" using 1:2 with boxes' % out_file
print >>out, "set style data steps"
#print >>out, "set yrange [0:*]"
print >>out, "set y2range [*:*]"
files += out_file + '.delays.png '
#set hidden3d
#set title "Peer bandwidth distribution"
#set xlabel "Ratio"
for p in plot:
print >>out, 'set title "%s %s"' % (p['title'], title)
print >>out, 'set xlabel "time (s)"'
print >>out, 'set ylabel "%s"' % p['y1']
print >>out, "set tics nomirror"
print >>out, 'set y2tics'
print >>out, 'set y2label "%s"' % p['y2']
print >>out, 'set xrange [0:*]'
print >>out, "set key box"
print >>out, "set term png size 1280,800"
print >>out, 'set output "%s-%s.png"' % (out_file, p['title'])
files += '%s-%s.png ' % (out_file, p['title'])
comma = ''
print >>out, "plot",
for c in p['data']:
if not c in metrics: continue
i = columns.index(c)
print >>out, '%s"%s" using 1:%d title "%s-%s" axes %s with %s' % (comma, out_file, i + 2, metrics[c][0], metrics[c][1], metrics[c][1], metrics[c][2]),
comma = ', '
print >>out, ''
out.close()
os.system("gnuplot utp.gnuplot")
os.system("open %s" % files)

115
vendor/github.com/anacrolix/go-libutp/sockaddr.go generated vendored Normal file
View File

@@ -0,0 +1,115 @@
package utp
/*
#include "utp.h"
*/
import "C"
import (
"net"
"strconv"
"syscall"
"unsafe"
"github.com/anacrolix/missinggo/inproc"
)
func toSockaddrInet(ip net.IP, port int, zone string) (*C.struct_sockaddr, C.socklen_t) {
if ip4 := ip.To4(); ip4 != nil && zone == "" {
rsa := syscall.RawSockaddrInet4{
// Len: syscall.SizeofSockaddrInet4,
Family: syscall.AF_INET,
Port: uint16(port),
}
if n := copy(rsa.Addr[:], ip4); n != 4 {
panic(n)
}
return (*C.struct_sockaddr)(unsafe.Pointer(&rsa)), C.socklen_t(unsafe.Sizeof(rsa))
}
rsa := syscall.RawSockaddrInet6{
// Len: syscall.SizeofSockaddrInet6,
Family: syscall.AF_INET6,
Scope_id: zoneToScopeId(zone),
Port: uint16(port),
}
if ip != nil {
if n := copy(rsa.Addr[:], ip); n != 16 {
panic(n)
}
}
return (*C.struct_sockaddr)(unsafe.Pointer(&rsa)), C.socklen_t(unsafe.Sizeof(rsa))
}
func zoneToScopeId(zone string) uint32 {
if zone == "" {
return 0
}
if ifi, err := net.InterfaceByName(zone); err == nil {
return uint32(ifi.Index)
}
ui64, _ := strconv.ParseUint(zone, 10, 32)
return uint32(ui64)
}
func structSockaddrToUDPAddr(sa *C.struct_sockaddr) *net.UDPAddr {
meh, err := anyToSockaddr((*syscall.RawSockaddrAny)(unsafe.Pointer(sa)))
if err != nil {
panic(err)
}
return sockaddrToUDP(meh).(*net.UDPAddr)
}
func anyToSockaddr(rsa *syscall.RawSockaddrAny) (syscall.Sockaddr, error) {
// log.Printf("anyToSockaddr %#v", rsa)
switch rsa.Addr.Family {
case syscall.AF_INET:
pp := (*syscall.RawSockaddrInet4)(unsafe.Pointer(rsa))
sa := new(syscall.SockaddrInet4)
// p := (*[2]byte)(unsafe.Pointer(&pp.Port))
// sa.Port = int(p[0])<<8 + int(p[1])
// I don't know why the port isn't reversed when it comes from utp.
sa.Port = int(pp.Port)
for i := 0; i < len(sa.Addr); i++ {
sa.Addr[i] = pp.Addr[i]
}
return sa, nil
case syscall.AF_INET6:
pp := (*syscall.RawSockaddrInet6)(unsafe.Pointer(rsa))
sa := new(syscall.SockaddrInet6)
// p := (*[2]byte)(unsafe.Pointer(&pp.Port))
// sa.Port = int(p[0])<<8 + int(p[1])
// I don't know why the port isn't reversed when it comes from utp.
sa.Port = int(pp.Port)
sa.ZoneId = pp.Scope_id
for i := 0; i < len(sa.Addr); i++ {
sa.Addr[i] = pp.Addr[i]
}
return sa, nil
}
return nil, syscall.EAFNOSUPPORT
}
func sockaddrToUDP(sa syscall.Sockaddr) net.Addr {
switch sa := sa.(type) {
case *syscall.SockaddrInet4:
return &net.UDPAddr{IP: sa.Addr[0:], Port: sa.Port}
case *syscall.SockaddrInet6:
return &net.UDPAddr{IP: sa.Addr[0:], Port: sa.Port /*Zone: zoneToString(int(sa.ZoneId))*/}
}
return nil
}
func netAddrToLibSockaddr(na net.Addr) (*C.struct_sockaddr, C.socklen_t) {
switch v := na.(type) {
case *net.UDPAddr:
return toSockaddrInet(v.IP, v.Port, v.Zone)
case inproc.Addr:
rsa := syscall.RawSockaddrInet6{
Port: uint16(v.Port),
}
return (*C.struct_sockaddr)(unsafe.Pointer(&rsa)), C.socklen_t(unsafe.Sizeof(rsa))
default:
panic(na)
}
}

454
vendor/github.com/anacrolix/go-libutp/socket.go generated vendored Normal file
View File

@@ -0,0 +1,454 @@
package utp
/*
#include "utp.h"
#include <stdbool.h>
struct utp_process_udp_args {
const byte *buf;
size_t len;
const struct sockaddr *sa;
socklen_t sal;
};
void process_received_messages(utp_context *ctx, struct utp_process_udp_args *args, size_t argslen)
{
bool gotUtp = false;
size_t i;
for (i = 0; i < argslen; i++) {
struct utp_process_udp_args *a = &args[i];
//if (!a->len) continue;
if (utp_process_udp(ctx, a->buf, a->len, a->sa, a->sal)) {
gotUtp = true;
}
}
if (gotUtp) {
utp_issue_deferred_acks(ctx);
utp_check_timeouts(ctx);
}
}
*/
import "C"
import (
"context"
"errors"
"net"
"runtime/pprof"
"time"
"github.com/anacrolix/missinggo"
"github.com/anacrolix/missinggo/inproc"
"github.com/anacrolix/mmsg"
)
type Socket struct {
pc net.PacketConn
ctx *C.utp_context
backlog chan *Conn
closed bool
conns map[*C.utp_socket]*Conn
nonUtpReads chan packet
writeDeadline time.Time
readDeadline time.Time
firewallCallback FirewallCallback
// Whether the next accept is to be blocked.
block bool
}
type FirewallCallback func(net.Addr) bool
var (
_ net.PacketConn = (*Socket)(nil)
_ net.Listener = (*Socket)(nil)
errSocketClosed = errors.New("Socket closed")
)
type packet struct {
b []byte
from net.Addr
}
func listenPacket(network, addr string) (pc net.PacketConn, err error) {
if network == "inproc" {
return inproc.ListenPacket(network, addr)
}
return net.ListenPacket(network, addr)
}
func NewSocket(network, addr string) (*Socket, error) {
pc, err := listenPacket(network, addr)
if err != nil {
return nil, err
}
mu.Lock()
defer mu.Unlock()
ctx := C.utp_init(2)
if ctx == nil {
panic(ctx)
}
ctx.setCallbacks()
if utpLogging {
ctx.setOption(C.UTP_LOG_NORMAL, 1)
ctx.setOption(C.UTP_LOG_MTU, 1)
ctx.setOption(C.UTP_LOG_DEBUG, 1)
}
s := &Socket{
pc: pc,
ctx: ctx,
backlog: make(chan *Conn, 5),
conns: make(map[*C.utp_socket]*Conn),
nonUtpReads: make(chan packet, 100),
}
libContextToSocket[ctx] = s
go s.timeoutChecker()
go s.packetReader()
return s, nil
}
func (s *Socket) onLibSocketDestroyed(ls *C.utp_socket) {
delete(s.conns, ls)
}
func (s *Socket) newConn(us *C.utp_socket) *Conn {
c := &Conn{
s: s,
us: us,
localAddr: s.pc.LocalAddr(),
}
c.cond.L = &mu
s.conns[us] = c
c.writeDeadlineTimer = time.AfterFunc(-1, c.cond.Broadcast)
c.readDeadlineTimer = time.AfterFunc(-1, c.cond.Broadcast)
return c
}
const maxNumBuffers = 16
func (s *Socket) packetReader() {
mc := mmsg.NewConn(s.pc)
// Increasing the messages increases the memory use, but also means we can
// reduces utp_issue_deferred_acks and syscalls which should improve
// efficiency. On the flip side, not all OSs implement batched reads.
ms := make([]mmsg.Message, func() int {
if mc.Err() == nil {
return maxNumBuffers
} else {
return 1
}
}())
for i := range ms {
// The IPv4 UDP limit is allegedly about 64 KiB, and this message has
// been seen on receiving on Windows with just 0x1000: wsarecvfrom: A
// message sent on a datagram socket was larger than the internal
// message buffer or some other network limit, or the buffer used to
// receive a datagram into was smaller than the datagram itself.
ms[i].Buffers = [][]byte{make([]byte, 0x10000)}
}
// Some crap OSs like Windoze will raise errors in Reads that don't
// actually mean we should stop.
consecutiveErrors := 0
for {
// In C, all the reads are processed and when it threatens to block,
// we're supposed to call utp_issue_deferred_acks.
n, err := mc.RecvMsgs(ms)
if n == 1 {
singleMsgRecvs.Add(1)
}
if n > 1 {
multiMsgRecvs.Add(1)
}
if err != nil {
mu.Lock()
closed := s.closed
mu.Unlock()
if closed {
// We don't care.
return
}
// See https://github.com/anacrolix/torrent/issues/83. If we get
// an endless stream of errors (such as the PacketConn being
// Closed outside of our control, this work around may need to be
// reconsidered.
Logger.Printf("ignoring socket read error: %s", err)
consecutiveErrors++
if consecutiveErrors >= 100 {
Logger.Print("too many consecutive errors, closing socket")
s.Close()
return
}
continue
}
consecutiveErrors = 0
expMap.Add("successful mmsg receive calls", 1)
expMap.Add("received messages", int64(n))
s.processReceivedMessages(ms[:n])
}
}
func (s *Socket) processReceivedMessages(ms []mmsg.Message) {
mu.Lock()
defer mu.Unlock()
if s.closed {
return
}
if processPacketsInC {
var args [maxNumBuffers]C.struct_utp_process_udp_args
for i, m := range ms {
a := &args[i]
a.buf = (*C.byte)(&m.Buffers[0][0])
a.len = C.size_t(m.N)
a.sa, a.sal = netAddrToLibSockaddr(m.Addr)
}
C.process_received_messages(s.ctx, &args[0], C.size_t(len(ms)))
} else {
gotUtp := false
for _, m := range ms {
gotUtp = s.processReceivedMessage(m.Buffers[0][:m.N], m.Addr) || gotUtp
}
if gotUtp && !s.closed {
s.afterReceivingUtpMessages()
}
}
}
func (s *Socket) afterReceivingUtpMessages() {
pprof.Do(context.Background(), pprof.Labels("go-libutp", "afterReceivingUtpMessages"), func(context.Context) {
C.utp_issue_deferred_acks(s.ctx)
// TODO: When is this done in C?
C.utp_check_timeouts(s.ctx)
})
}
func (s *Socket) processReceivedMessage(b []byte, addr net.Addr) (utp bool) {
if s.utpProcessUdp(b, addr) {
socketUtpPacketsReceived.Add(1)
return true
} else {
s.onReadNonUtp(b, addr)
return false
}
}
// Process packet batches entirely from C, reducing CGO overhead. Currently
// requires GODEBUG=cgocheck=0.
const processPacketsInC = false
// Wraps libutp's utp_process_udp, returning relevant information.
func (s *Socket) utpProcessUdp(b []byte, addr net.Addr) (utp bool) {
sa, sal := netAddrToLibSockaddr(addr)
if len(b) == 0 {
// The implementation of utp_process_udp rejects null buffers, and
// anything smaller than the UTP header size. It's also prone to
// assert on those, which we don't want to trigger.
return false
}
if missinggo.AddrPort(addr) == 0 {
return false
}
mu.Unlock()
block := func() bool {
if s.firewallCallback == nil {
return false
}
return s.firewallCallback(addr)
}()
mu.Lock()
s.block = block
if s.closed {
return false
}
ret := C.utp_process_udp(s.ctx, (*C.byte)(&b[0]), C.size_t(len(b)), sa, sal)
switch ret {
case 1:
return true
case 0:
return false
default:
panic(ret)
}
}
func (s *Socket) timeoutChecker() {
for {
mu.Lock()
if s.closed {
mu.Unlock()
return
}
// C.utp_issue_deferred_acks(s.ctx)
C.utp_check_timeouts(s.ctx)
mu.Unlock()
time.Sleep(500 * time.Millisecond)
}
}
func (s *Socket) Close() error {
mu.Lock()
defer mu.Unlock()
return s.closeLocked()
}
func (s *Socket) closeLocked() error {
if s.closed {
return nil
}
// Calling this deletes the pointer. It must not be referred to after
// this.
C.utp_destroy(s.ctx)
s.ctx = nil
s.pc.Close()
close(s.backlog)
close(s.nonUtpReads)
s.closed = true
return nil
}
func (s *Socket) Addr() net.Addr {
return s.pc.LocalAddr()
}
func (s *Socket) LocalAddr() net.Addr {
return s.pc.LocalAddr()
}
func (s *Socket) Accept() (net.Conn, error) {
nc, ok := <-s.backlog
if !ok {
return nil, errors.New("closed")
}
return nc, nil
}
func (s *Socket) Dial(addr string) (net.Conn, error) {
return s.DialTimeout(addr, 0)
}
func (s *Socket) DialTimeout(addr string, timeout time.Duration) (net.Conn, error) {
ctx := context.Background()
if timeout != 0 {
var cancel context.CancelFunc
ctx, cancel = context.WithTimeout(ctx, timeout)
defer cancel()
}
return s.DialContext(ctx, "", addr)
}
func (s *Socket) resolveAddr(network, addr string) (net.Addr, error) {
if network == "" {
network = s.Addr().Network()
}
return resolveAddr(network, addr)
}
func resolveAddr(network, addr string) (net.Addr, error) {
switch network {
case "inproc":
return inproc.ResolveAddr(network, addr)
default:
return net.ResolveUDPAddr(network, addr)
}
}
// Passing an empty network will use the network of the Socket's listener.
func (s *Socket) DialContext(ctx context.Context, network, addr string) (net.Conn, error) {
c, err := s.NewConn()
if err != nil {
return nil, err
}
err = c.Connect(ctx, network, addr)
if err != nil {
c.Close()
return nil, err
}
return c, nil
}
func (s *Socket) NewConn() (*Conn, error) {
mu.Lock()
defer mu.Unlock()
if s.closed {
return nil, errors.New("socket closed")
}
return s.newConn(C.utp_create_socket(s.ctx)), nil
}
func (s *Socket) pushBacklog(c *Conn) {
select {
case s.backlog <- c:
default:
c.close()
}
}
func (s *Socket) ReadFrom(b []byte) (n int, addr net.Addr, err error) {
p, ok := <-s.nonUtpReads
if !ok {
err = errors.New("closed")
return
}
n = copy(b, p.b)
addr = p.from
return
}
func (s *Socket) onReadNonUtp(b []byte, from net.Addr) {
if s.closed {
return
}
socketNonUtpPacketsReceived.Add(1)
select {
case s.nonUtpReads <- packet{append([]byte(nil), b...), from}:
default:
// log.Printf("dropped non utp packet: no room in buffer")
nonUtpPacketsDropped.Add(1)
}
}
func (s *Socket) SetReadDeadline(t time.Time) error {
panic("not implemented")
}
func (s *Socket) SetWriteDeadline(t time.Time) error {
panic("not implemented")
}
func (s *Socket) SetDeadline(t time.Time) error {
panic("not implemented")
}
func (s *Socket) WriteTo(b []byte, addr net.Addr) (int, error) {
return s.pc.WriteTo(b, addr)
}
func (s *Socket) ReadBufferLen() int {
mu.Lock()
defer mu.Unlock()
return int(C.utp_context_get_option(s.ctx, C.UTP_RCVBUF))
}
func (s *Socket) WriteBufferLen() int {
mu.Lock()
defer mu.Unlock()
return int(C.utp_context_get_option(s.ctx, C.UTP_SNDBUF))
}
func (s *Socket) SetWriteBufferLen(len int) {
mu.Lock()
defer mu.Unlock()
i := C.utp_context_set_option(s.ctx, C.UTP_SNDBUF, C.int(len))
if i != 0 {
panic(i)
}
}
func (s *Socket) SetOption(opt Option, val int) int {
mu.Lock()
defer mu.Unlock()
return int(C.utp_context_set_option(s.ctx, opt, C.int(val)))
}
func (s *Socket) SetFirewallCallback(f FirewallCallback) {
mu.Lock()
s.firewallCallback = f
mu.Unlock()
}

17
vendor/github.com/anacrolix/go-libutp/status.go generated vendored Normal file
View File

@@ -0,0 +1,17 @@
package utp
import (
"fmt"
"io"
)
func WriteStatus(w io.Writer) {
mu.Lock()
defer mu.Unlock()
for _, s := range libContextToSocket {
fmt.Fprintf(w, "listening at %s\n", s.Addr())
fmt.Fprintf(w, "has %d conns\n", len(s.conns))
fmt.Fprintf(w, "backlog: %d\n", len(s.backlog))
fmt.Fprintf(w, "\n")
}
}

50
vendor/github.com/anacrolix/go-libutp/utp.go generated vendored Normal file
View File

@@ -0,0 +1,50 @@
package utp
/*
#cgo CPPFLAGS: -DPOSIX -DUTP_DEBUG_LOGGING=0
#cgo CFLAGS: -Wall -O3
// These are all copied from the libutp Makefile.
#cgo CXXFLAGS: -Wall -O3 -fPIC -Wno-sign-compare
// There are some variables that aren't used unless UTP_DEBUG_LOGGING is defined.
#cgo CXXFLAGS: -Wno-unused-const-variable
// Windows additional flags
#cgo windows LDFLAGS: -lws2_32
#cgo windows CXXFLAGS: -D_WIN32_WINNT=0x600
#include "utp.h"
uint64_t firewallCallback(utp_callback_arguments *);
uint64_t errorCallback(utp_callback_arguments *);
uint64_t logCallback(utp_callback_arguments *);
uint64_t acceptCallback(utp_callback_arguments *);
uint64_t sendtoCallback(utp_callback_arguments *);
uint64_t stateChangeCallback(utp_callback_arguments *);
uint64_t readCallback(utp_callback_arguments *);
uint64_t getReadBufferSizeCallback(utp_callback_arguments *);
*/
import "C"
import "unsafe"
type socklen C.socklen_t
func (ctx *C.utp_context) setCallbacks() {
C.utp_set_callback(ctx, C.UTP_ON_FIREWALL, (*C.utp_callback_t)(C.firewallCallback))
C.utp_set_callback(ctx, C.UTP_LOG, (*C.utp_callback_t)(C.logCallback))
C.utp_set_callback(ctx, C.UTP_ON_ACCEPT, (*C.utp_callback_t)(C.acceptCallback))
C.utp_set_callback(ctx, C.UTP_SENDTO, (*C.utp_callback_t)(C.sendtoCallback))
C.utp_set_callback(ctx, C.UTP_ON_STATE_CHANGE, (*C.utp_callback_t)(C.stateChangeCallback))
C.utp_set_callback(ctx, C.UTP_ON_READ, (*C.utp_callback_t)(C.readCallback))
C.utp_set_callback(ctx, C.UTP_ON_ERROR, (*C.utp_callback_t)(C.errorCallback))
C.utp_set_callback(ctx, C.UTP_GET_READ_BUFFER_SIZE, (*C.utp_callback_t)(C.getReadBufferSizeCallback))
}
func (ctx *C.utp_context) setOption(opt Option, val int) int {
return int(C.utp_context_set_option(ctx, opt, C.int(val)))
}
func libStateName(state C.int) string {
return C.GoString((*[5]*C.char)(unsafe.Pointer(&C.utp_state_names))[state])
}
func libErrorCodeNames(error_code C.int) string {
return C.GoString((*[3]*C.char)(unsafe.Pointer(&C.utp_error_code_names))[error_code])
}

187
vendor/github.com/anacrolix/go-libutp/utp.h generated vendored Normal file
View File

@@ -0,0 +1,187 @@
/*
* Copyright (c) 2010-2013 BitTorrent, Inc.
*
* 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.
*/
#ifndef __UTP_H__
#define __UTP_H__
#ifdef __cplusplus
extern "C" {
#endif
#ifdef _WIN32
#include <stdint.h>
#endif
#include <stdarg.h>
#include "utp_types.h"
typedef struct UTPSocket utp_socket;
typedef struct struct_utp_context utp_context;
enum {
UTP_UDP_DONTFRAG = 2, // Used to be a #define as UDP_IP_DONTFRAG
};
enum {
// socket has reveived syn-ack (notification only for outgoing connection completion)
// this implies writability
UTP_STATE_CONNECT = 1,
// socket is able to send more data
UTP_STATE_WRITABLE = 2,
// connection closed
UTP_STATE_EOF = 3,
// socket is being destroyed, meaning all data has been sent if possible.
// it is not valid to refer to the socket after this state change occurs
UTP_STATE_DESTROYING = 4,
};
extern const char *utp_state_names[];
// Errors codes that can be passed to UTP_ON_ERROR callback
enum {
UTP_ECONNREFUSED = 0,
UTP_ECONNRESET,
UTP_ETIMEDOUT,
};
extern const char *utp_error_code_names[];
enum {
// callback names
UTP_ON_FIREWALL = 0,
UTP_ON_ACCEPT,
UTP_ON_CONNECT,
UTP_ON_ERROR,
UTP_ON_READ,
UTP_ON_OVERHEAD_STATISTICS,
UTP_ON_STATE_CHANGE,
UTP_GET_READ_BUFFER_SIZE,
UTP_ON_DELAY_SAMPLE,
UTP_GET_UDP_MTU,
UTP_GET_UDP_OVERHEAD,
UTP_GET_MILLISECONDS,
UTP_GET_MICROSECONDS,
UTP_GET_RANDOM,
UTP_LOG,
UTP_SENDTO,
// context and socket options that may be set/queried
UTP_LOG_NORMAL,
UTP_LOG_MTU,
UTP_LOG_DEBUG,
UTP_SNDBUF,
UTP_RCVBUF,
UTP_TARGET_DELAY,
UTP_ARRAY_SIZE, // must be last
};
extern const char *utp_callback_names[];
typedef struct {
utp_context *context;
utp_socket *socket;
size_t len;
uint32 flags;
int callback_type;
const byte *buf;
union {
const struct sockaddr *address;
int send;
int sample_ms;
int error_code;
int state;
};
union {
socklen_t address_len;
int type;
};
} utp_callback_arguments;
typedef uint64 utp_callback_t(utp_callback_arguments *);
// Returned by utp_get_context_stats()
typedef struct {
uint32 _nraw_recv[5]; // total packets recieved less than 300/600/1200/MTU bytes fpr all connections (context-wide)
uint32 _nraw_send[5]; // total packets sent less than 300/600/1200/MTU bytes for all connections (context-wide)
} utp_context_stats;
// Returned by utp_get_stats()
typedef struct {
uint64 nbytes_recv; // total bytes received
uint64 nbytes_xmit; // total bytes transmitted
uint32 rexmit; // retransmit counter
uint32 fastrexmit; // fast retransmit counter
uint32 nxmit; // transmit counter
uint32 nrecv; // receive counter (total)
uint32 nduprecv; // duplicate receive counter
uint32 mtu_guess; // Best guess at MTU
} utp_socket_stats;
#define UTP_IOV_MAX 1024
// For utp_writev, to writes data from multiple buffers
struct utp_iovec {
void *iov_base;
size_t iov_len;
};
// Public Functions
utp_context* utp_init (int version);
void utp_destroy (utp_context *ctx);
void utp_set_callback (utp_context *ctx, int callback_name, utp_callback_t *proc);
void* utp_context_set_userdata (utp_context *ctx, void *userdata);
void* utp_context_get_userdata (utp_context *ctx);
int utp_context_set_option (utp_context *ctx, int opt, int val);
int utp_context_get_option (utp_context *ctx, int opt);
int utp_process_udp (utp_context *ctx, const byte *buf, size_t len, const struct sockaddr *to, socklen_t tolen);
int utp_process_icmp_error (utp_context *ctx, const byte *buffer, size_t len, const struct sockaddr *to, socklen_t tolen);
int utp_process_icmp_fragmentation (utp_context *ctx, const byte *buffer, size_t len, const struct sockaddr *to, socklen_t tolen, uint16 next_hop_mtu);
void utp_check_timeouts (utp_context *ctx);
void utp_issue_deferred_acks (utp_context *ctx);
utp_context_stats* utp_get_context_stats (utp_context *ctx);
utp_socket* utp_create_socket (utp_context *ctx);
void* utp_set_userdata (utp_socket *s, void *userdata);
void* utp_get_userdata (utp_socket *s);
int utp_setsockopt (utp_socket *s, int opt, int val);
int utp_getsockopt (utp_socket *s, int opt);
int utp_connect (utp_socket *s, const struct sockaddr *to, socklen_t tolen);
ssize_t utp_write (utp_socket *s, void *buf, size_t count);
ssize_t utp_writev (utp_socket *s, struct utp_iovec *iovec, size_t num_iovecs);
int utp_getpeername (utp_socket *s, struct sockaddr *addr, socklen_t *addrlen);
void utp_read_drained (utp_socket *s);
int utp_get_delays (utp_socket *s, uint32 *ours, uint32 *theirs, uint32 *age);
utp_socket_stats* utp_get_stats (utp_socket *s);
utp_context* utp_get_context (utp_socket *s);
void utp_shutdown (utp_socket *s, int how);
void utp_close (utp_socket *s);
#ifdef __cplusplus
}
#endif
#endif //__UTP_H__

139
vendor/github.com/anacrolix/go-libutp/utp_api.cpp generated vendored Normal file
View File

@@ -0,0 +1,139 @@
// vim:set ts=4 sw=4 ai:
/*
* Copyright (c) 2010-2013 BitTorrent, Inc.
*
* 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.
*/
#include <stdio.h>
#include "utp_internal.h"
#include "utp_utils.h"
extern "C" {
const char * utp_callback_names[] = {
"UTP_ON_FIREWALL",
"UTP_ON_ACCEPT",
"UTP_ON_CONNECT",
"UTP_ON_ERROR",
"UTP_ON_READ",
"UTP_ON_OVERHEAD_STATISTICS",
"UTP_ON_STATE_CHANGE",
"UTP_GET_READ_BUFFER_SIZE",
"UTP_ON_DELAY_SAMPLE",
"UTP_GET_UDP_MTU",
"UTP_GET_UDP_OVERHEAD",
"UTP_GET_MILLISECONDS",
"UTP_GET_MICROSECONDS",
"UTP_GET_RANDOM",
"UTP_LOG",
"UTP_SENDTO",
};
const char * utp_error_code_names[] = {
"UTP_ECONNREFUSED",
"UTP_ECONNRESET",
"UTP_ETIMEDOUT",
};
const char *utp_state_names[] = {
NULL,
"UTP_STATE_CONNECT",
"UTP_STATE_WRITABLE",
"UTP_STATE_EOF",
"UTP_STATE_DESTROYING",
};
struct_utp_context::struct_utp_context()
: userdata(NULL)
, current_ms(0)
, last_utp_socket(NULL)
, log_normal(false)
, log_mtu(false)
, log_debug(false)
{
memset(&context_stats, 0, sizeof(context_stats));
memset(callbacks, 0, sizeof(callbacks));
target_delay = CCONTROL_TARGET;
utp_sockets = new UTPSocketHT;
callbacks[UTP_GET_UDP_MTU] = &utp_default_get_udp_mtu;
callbacks[UTP_GET_UDP_OVERHEAD] = &utp_default_get_udp_overhead;
callbacks[UTP_GET_MILLISECONDS] = &utp_default_get_milliseconds;
callbacks[UTP_GET_MICROSECONDS] = &utp_default_get_microseconds;
callbacks[UTP_GET_RANDOM] = &utp_default_get_random;
// 1 MB of receive buffer (i.e. max bandwidth delay product)
// means that from a peer with 200 ms RTT, we cannot receive
// faster than 5 MB/s
// from a peer with 10 ms RTT, we cannot receive faster than
// 100 MB/s. This is assumed to be good enough, since bandwidth
// often is proportional to RTT anyway
// when setting a download rate limit, all sockets should have
// their receive buffer set much lower, to say 60 kiB or so
opt_rcvbuf = opt_sndbuf = 1024 * 1024;
last_check = 0;
}
struct_utp_context::~struct_utp_context() {
delete this->utp_sockets;
}
utp_context* utp_init (int version)
{
assert(version == 2);
if (version != 2)
return NULL;
utp_context *ctx = new utp_context;
return ctx;
}
void utp_destroy(utp_context *ctx) {
assert(ctx);
if (ctx) delete ctx;
}
void utp_set_callback(utp_context *ctx, int callback_name, utp_callback_t *proc) {
assert(ctx);
if (ctx) ctx->callbacks[callback_name] = proc;
}
void* utp_context_set_userdata(utp_context *ctx, void *userdata) {
assert(ctx);
if (ctx) ctx->userdata = userdata;
return ctx ? ctx->userdata : NULL;
}
void* utp_context_get_userdata(utp_context *ctx) {
assert(ctx);
return ctx ? ctx->userdata : NULL;
}
utp_context_stats* utp_get_context_stats(utp_context *ctx) {
assert(ctx);
return ctx ? &ctx->context_stats : NULL;
}
ssize_t utp_write(utp_socket *socket, void *buf, size_t len) {
struct utp_iovec iovec = { buf, len };
return utp_writev(socket, &iovec, 1);
}
}

208
vendor/github.com/anacrolix/go-libutp/utp_callbacks.cpp generated vendored Normal file
View File

@@ -0,0 +1,208 @@
// vim:set ts=4 sw=4 ai:
/*
* Copyright (c) 2010-2013 BitTorrent, Inc.
*
* 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.
*/
#include "utp_callbacks.h"
int utp_call_on_firewall(utp_context *ctx, const struct sockaddr *address, socklen_t address_len)
{
utp_callback_arguments args;
if (!ctx->callbacks[UTP_ON_FIREWALL]) return 0;
args.callback_type = UTP_ON_FIREWALL;
args.context = ctx;
args.socket = NULL;
args.address = address;
args.address_len = address_len;
return (int)ctx->callbacks[UTP_ON_FIREWALL](&args);
}
void utp_call_on_accept(utp_context *ctx, utp_socket *socket, const struct sockaddr *address, socklen_t address_len)
{
utp_callback_arguments args;
if (!ctx->callbacks[UTP_ON_ACCEPT]) return;
args.callback_type = UTP_ON_ACCEPT;
args.context = ctx;
args.socket = socket;
args.address = address;
args.address_len = address_len;
ctx->callbacks[UTP_ON_ACCEPT](&args);
}
void utp_call_on_connect(utp_context *ctx, utp_socket *socket)
{
utp_callback_arguments args;
if (!ctx->callbacks[UTP_ON_CONNECT]) return;
args.callback_type = UTP_ON_CONNECT;
args.context = ctx;
args.socket = socket;
ctx->callbacks[UTP_ON_CONNECT](&args);
}
void utp_call_on_error(utp_context *ctx, utp_socket *socket, int error_code)
{
utp_callback_arguments args;
if (!ctx->callbacks[UTP_ON_ERROR]) return;
args.callback_type = UTP_ON_ERROR;
args.context = ctx;
args.socket = socket;
args.error_code = error_code;
ctx->callbacks[UTP_ON_ERROR](&args);
}
void utp_call_on_read(utp_context *ctx, utp_socket *socket, const byte *buf, size_t len)
{
utp_callback_arguments args;
if (!ctx->callbacks[UTP_ON_READ]) return;
args.callback_type = UTP_ON_READ;
args.context = ctx;
args.socket = socket;
args.buf = buf;
args.len = len;
ctx->callbacks[UTP_ON_READ](&args);
}
void utp_call_on_overhead_statistics(utp_context *ctx, utp_socket *socket, int send, size_t len, int type)
{
utp_callback_arguments args;
if (!ctx->callbacks[UTP_ON_OVERHEAD_STATISTICS]) return;
args.callback_type = UTP_ON_OVERHEAD_STATISTICS;
args.context = ctx;
args.socket = socket;
args.send = send;
args.len = len;
args.type = type;
ctx->callbacks[UTP_ON_OVERHEAD_STATISTICS](&args);
}
void utp_call_on_delay_sample(utp_context *ctx, utp_socket *socket, int sample_ms)
{
utp_callback_arguments args;
if (!ctx->callbacks[UTP_ON_DELAY_SAMPLE]) return;
args.callback_type = UTP_ON_DELAY_SAMPLE;
args.context = ctx;
args.socket = socket;
args.sample_ms = sample_ms;
ctx->callbacks[UTP_ON_DELAY_SAMPLE](&args);
}
void utp_call_on_state_change(utp_context *ctx, utp_socket *socket, int state)
{
utp_callback_arguments args;
if (!ctx->callbacks[UTP_ON_STATE_CHANGE]) return;
args.callback_type = UTP_ON_STATE_CHANGE;
args.context = ctx;
args.socket = socket;
args.state = state;
ctx->callbacks[UTP_ON_STATE_CHANGE](&args);
}
uint16 utp_call_get_udp_mtu(utp_context *ctx, utp_socket *socket, const struct sockaddr *address, socklen_t address_len)
{
utp_callback_arguments args;
if (!ctx->callbacks[UTP_GET_UDP_MTU]) return 0;
args.callback_type = UTP_GET_UDP_MTU;
args.context = ctx;
args.socket = socket;
args.address = address;
args.address_len = address_len;
return (uint16)ctx->callbacks[UTP_GET_UDP_MTU](&args);
}
uint16 utp_call_get_udp_overhead(utp_context *ctx, utp_socket *socket, const struct sockaddr *address, socklen_t address_len)
{
utp_callback_arguments args;
if (!ctx->callbacks[UTP_GET_UDP_OVERHEAD]) return 0;
args.callback_type = UTP_GET_UDP_OVERHEAD;
args.context = ctx;
args.socket = socket;
args.address = address;
args.address_len = address_len;
return (uint16)ctx->callbacks[UTP_GET_UDP_OVERHEAD](&args);
}
uint64 utp_call_get_milliseconds(utp_context *ctx, utp_socket *socket)
{
utp_callback_arguments args;
if (!ctx->callbacks[UTP_GET_MILLISECONDS]) return 0;
args.callback_type = UTP_GET_MILLISECONDS;
args.context = ctx;
args.socket = socket;
return ctx->callbacks[UTP_GET_MILLISECONDS](&args);
}
uint64 utp_call_get_microseconds(utp_context *ctx, utp_socket *socket)
{
utp_callback_arguments args;
if (!ctx->callbacks[UTP_GET_MICROSECONDS]) return 0;
args.callback_type = UTP_GET_MICROSECONDS;
args.context = ctx;
args.socket = socket;
return ctx->callbacks[UTP_GET_MICROSECONDS](&args);
}
uint32 utp_call_get_random(utp_context *ctx, utp_socket *socket)
{
utp_callback_arguments args;
if (!ctx->callbacks[UTP_GET_RANDOM]) return 0;
args.callback_type = UTP_GET_RANDOM;
args.context = ctx;
args.socket = socket;
return (uint32)ctx->callbacks[UTP_GET_RANDOM](&args);
}
size_t utp_call_get_read_buffer_size(utp_context *ctx, utp_socket *socket)
{
utp_callback_arguments args;
if (!ctx->callbacks[UTP_GET_READ_BUFFER_SIZE]) return 0;
args.callback_type = UTP_GET_READ_BUFFER_SIZE;
args.context = ctx;
args.socket = socket;
return (size_t)ctx->callbacks[UTP_GET_READ_BUFFER_SIZE](&args);
}
void utp_call_log(utp_context *ctx, utp_socket *socket, const byte *buf)
{
utp_callback_arguments args;
if (!ctx->callbacks[UTP_LOG]) return;
args.callback_type = UTP_LOG;
args.context = ctx;
args.socket = socket;
args.buf = buf;
ctx->callbacks[UTP_LOG](&args);
}
void utp_call_sendto(utp_context *ctx, utp_socket *socket, const byte *buf, size_t len, const struct sockaddr *address, socklen_t address_len, uint32 flags)
{
utp_callback_arguments args;
if (!ctx->callbacks[UTP_SENDTO]) return;
args.callback_type = UTP_SENDTO;
args.context = ctx;
args.socket = socket;
args.buf = buf;
args.len = len;
args.address = address;
args.address_len = address_len;
args.flags = flags;
ctx->callbacks[UTP_SENDTO](&args);
}

47
vendor/github.com/anacrolix/go-libutp/utp_callbacks.h generated vendored Normal file
View File

@@ -0,0 +1,47 @@
/*
* Copyright (c) 2010-2013 BitTorrent, Inc.
*
* 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.
*/
#ifndef __UTP_CALLBACKS_H__
#define __UTP_CALLBACKS_H__
#include "utp.h"
#include "utp_internal.h"
// Generated by running: grep ^[a-z] utp_callbacks.cpp | sed 's/$/;/'
int utp_call_on_firewall(utp_context *ctx, const struct sockaddr *address, socklen_t address_len);
void utp_call_on_accept(utp_context *ctx, utp_socket *s, const struct sockaddr *address, socklen_t address_len);
void utp_call_on_connect(utp_context *ctx, utp_socket *s);
void utp_call_on_error(utp_context *ctx, utp_socket *s, int error_code);
void utp_call_on_read(utp_context *ctx, utp_socket *s, const byte *buf, size_t len);
void utp_call_on_overhead_statistics(utp_context *ctx, utp_socket *s, int send, size_t len, int type);
void utp_call_on_delay_sample(utp_context *ctx, utp_socket *s, int sample_ms);
void utp_call_on_state_change(utp_context *ctx, utp_socket *s, int state);
uint16 utp_call_get_udp_mtu(utp_context *ctx, utp_socket *s, const struct sockaddr *address, socklen_t address_len);
uint16 utp_call_get_udp_overhead(utp_context *ctx, utp_socket *s, const struct sockaddr *address, socklen_t address_len);
uint64 utp_call_get_milliseconds(utp_context *ctx, utp_socket *s);
uint64 utp_call_get_microseconds(utp_context *ctx, utp_socket *s);
uint32 utp_call_get_random(utp_context *ctx, utp_socket *s);
size_t utp_call_get_read_buffer_size(utp_context *ctx, utp_socket *s);
void utp_call_log(utp_context *ctx, utp_socket *s, const byte *buf);
void utp_call_sendto(utp_context *ctx, utp_socket *s, const byte *buf, size_t len, const struct sockaddr *address, socklen_t address_len, uint32 flags);
#endif // __UTP_CALLBACKS_H__

246
vendor/github.com/anacrolix/go-libutp/utp_hash.cpp generated vendored Normal file
View File

@@ -0,0 +1,246 @@
/*
* Copyright (c) 2010-2013 BitTorrent, Inc.
*
* 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.
*/
#include "utp_hash.h"
#include "utp_types.h"
#define LIBUTP_HASH_UNUSED ((utp_link_t)-1)
#ifdef STRICT_ALIGN
inline uint32 Read32(const void *p)
{
uint32 tmp;
memcpy(&tmp, p, sizeof tmp);
return tmp;
}
#else
inline uint32 Read32(const void *p) { return *(uint32*)p; }
#endif
// Get the amount of memory required for the hash parameters and the bucket set
// Waste a space for an unused bucket in order to ensure the following managed memory have 32-bit aligned addresses
// TODO: make this 64-bit clean
#define BASE_SIZE(bc) (sizeof(utp_hash_t) + sizeof(utp_link_t) * ((bc) + 1))
// Get a pointer to the base of the structure array managed by the hash table
#define get_bep(h) ((byte*)(h)) + BASE_SIZE((h)->N)
// Get the address of the information associated with a specific structure in the array,
// given the address of the base of the structure.
// This assumes a utp_link_t link member is at the end of the structure.
// Given compilers filling out the memory to a 32-bit clean value, this may mean that
// the location named in the structure may not be the location actually used by the hash table,
// since the compiler may have padded the end of the structure with 2 bytes after the utp_link_t member.
// TODO: this macro should not require that the variable pointing at the hash table be named 'hash'
#define ptr_to_link(p) (utp_link_t *) (((byte *) (p)) + hash->E - sizeof(utp_link_t))
// Calculate how much to allocate for a hash table with bucket count, total size, and structure count
// TODO: make this 64-bit clean
#define ALLOCATION_SIZE(bc, ts, sc) (BASE_SIZE((bc)) + (ts) * (sc))
utp_hash_t *utp_hash_create(int N, int key_size, int total_size, int initial, utp_hash_compute_t hashfun, utp_hash_equal_t compfun)
{
// Must have odd number of hash buckets (prime number is best)
assert(N % 2);
// Ensure structures will be at aligned memory addresses
// TODO: make this 64-bit clean
assert(0 == (total_size % 4));
int size = ALLOCATION_SIZE(N, total_size, initial);
utp_hash_t *hash = (utp_hash_t *) malloc( size );
memset( hash, 0, size );
for (int i = 0; i < N + 1; ++i)
hash->inits[i] = LIBUTP_HASH_UNUSED;
hash->N = N;
hash->K = key_size;
hash->E = total_size;
hash->hash_compute = hashfun;
hash->hash_equal = compfun;
hash->allocated = initial;
hash->count = 0;
hash->used = 0;
hash->free = LIBUTP_HASH_UNUSED;
return hash;
}
uint utp_hash_mem(const void *keyp, size_t keysize)
{
uint hash = 0;
uint n = keysize;
while (n >= 4) {
hash ^= Read32(keyp);
keyp = (byte*)keyp + sizeof(uint32);
hash = (hash << 13) | (hash >> 19);
n -= 4;
}
while (n != 0) {
hash ^= *(byte*)keyp;
keyp = (byte*)keyp + sizeof(byte);
hash = (hash << 8) | (hash >> 24);
n--;
}
return hash;
}
uint utp_hash_mkidx(utp_hash_t *hash, const void *keyp)
{
// Generate a key from the hash
return hash->hash_compute(keyp, hash->K) % hash->N;
}
static inline bool compare(byte *a, byte *b,int n)
{
assert(n >= 4);
if (Read32(a) != Read32(b)) return false;
return memcmp(a+4, b+4, n-4) == 0;
}
#define COMPARE(h,k1,k2,ks) (((h)->hash_equal) ? (h)->hash_equal((void*)k1,(void*)k2,ks) : compare(k1,k2,ks))
// Look-up a key in the hash table.
// Returns NULL if not found
void *utp_hash_lookup(utp_hash_t *hash, const void *key)
{
utp_link_t idx = utp_hash_mkidx(hash, key);
// base pointer
byte *bep = get_bep(hash);
utp_link_t cur = hash->inits[idx];
while (cur != LIBUTP_HASH_UNUSED) {
byte *key2 = bep + (cur * hash->E);
if (COMPARE(hash, (byte*)key, key2, hash->K))
return key2;
cur = *ptr_to_link(key2);
}
return NULL;
}
// Add a new element to the hash table.
// Returns a pointer to the new element.
// This assumes the element is not already present!
void *utp_hash_add(utp_hash_t **hashp, const void *key)
{
//Allocate a new entry
byte *elemp;
utp_link_t elem;
utp_hash_t *hash = *hashp;
utp_link_t idx = utp_hash_mkidx(hash, key);
if ((elem=hash->free) == LIBUTP_HASH_UNUSED) {
utp_link_t all = hash->allocated;
if (hash->used == all) {
utp_hash_t *nhash;
if (all <= (LIBUTP_HASH_UNUSED/2)) {
all *= 2;
} else if (all != LIBUTP_HASH_UNUSED) {
all = LIBUTP_HASH_UNUSED;
} else {
// too many items! can't grow!
assert(0);
return NULL;
}
// otherwise need to allocate.
nhash = (utp_hash_t*)realloc(hash, ALLOCATION_SIZE(hash->N, hash->E, all));
if (!nhash) {
// out of memory (or too big to allocate)
assert(nhash);
return NULL;
}
hash = *hashp = nhash;
hash->allocated = all;
}
elem = hash->used++;
elemp = get_bep(hash) + elem * hash->E;
} else {
elemp = get_bep(hash) + elem * hash->E;
hash->free = *ptr_to_link(elemp);
}
*ptr_to_link(elemp) = hash->inits[idx];
hash->inits[idx] = elem;
hash->count++;
// copy key into it
memcpy(elemp, key, hash->K);
return elemp;
}
// Delete an element from the utp_hash_t
// Returns a pointer to the already deleted element.
void *utp_hash_del(utp_hash_t *hash, const void *key)
{
utp_link_t idx = utp_hash_mkidx(hash, key);
// base pointer
byte *bep = get_bep(hash);
utp_link_t *curp = &hash->inits[idx];
utp_link_t cur;
while ((cur=*curp) != LIBUTP_HASH_UNUSED) {
byte *key2 = bep + (cur * hash->E);
if (COMPARE(hash,(byte*)key,(byte*)key2, hash->K )) {
// found an item that matched. unlink it
*curp = *ptr_to_link(key2);
// Insert into freelist
*ptr_to_link(key2) = hash->free;
hash->free = cur;
hash->count--;
return key2;
}
curp = ptr_to_link(key2);
}
return NULL;
}
void *utp_hash_iterate(utp_hash_t *hash, utp_hash_iterator_t *iter)
{
utp_link_t elem;
if ((elem=iter->elem) == LIBUTP_HASH_UNUSED) {
// Find a bucket with an element
utp_link_t buck = iter->bucket + 1;
for(;;) {
if (buck >= hash->N)
return NULL;
if ((elem = hash->inits[buck]) != LIBUTP_HASH_UNUSED)
break;
buck++;
}
iter->bucket = buck;
}
byte *elemp = get_bep(hash) + (elem * hash->E);
iter->elem = *ptr_to_link(elemp);
return elemp;
}
void utp_hash_free_mem(utp_hash_t* hash)
{
free(hash);
}

146
vendor/github.com/anacrolix/go-libutp/utp_hash.h generated vendored Normal file
View File

@@ -0,0 +1,146 @@
/*
* Copyright (c) 2010-2013 BitTorrent, Inc.
*
* 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.
*/
#ifndef __UTP_HASH_H__
#define __UTP_HASH_H__
#include <string.h> // memset
#include <stdlib.h> // malloc
#include "utp_types.h"
#include "utp_templates.h"
// TODO: make utp_link_t a template parameter to HashTable
typedef uint32 utp_link_t;
#ifdef _MSC_VER
// Silence the warning about the C99-compliant zero-length array at the end of the structure
#pragma warning (disable: 4200)
#endif
typedef uint32 (*utp_hash_compute_t)(const void *keyp, size_t keysize);
typedef uint (*utp_hash_equal_t)(const void *key_a, const void *key_b, size_t keysize);
// In memory the HashTable is laid out as follows:
// ---------------------------- low
// | hash table data members |
// ---------------------------- _
// | indices | ^
// | . | | utp_link_t indices into the key-values.
// | . | .
// ---------------------------- - <----- bep
// | keys and values | each key-value pair has size total_size
// | . |
// | . |
// ---------------------------- high
//
// The code depends on the ability of the compiler to pad the length
// of the hash table data members structure to
// a length divisible by 32-bits with no remainder.
//
// Since the number of hash buckets (indices) should be odd, the code
// asserts this and adds one to the hash bucket count to ensure that the
// following key-value pairs array starts on a 32-bit boundary.
//
// The key-value pairs array should start on a 32-bit boundary, otherwise
// processors like the ARM will silently mangle 32-bit data in these structures
// (e.g., turning 0xABCD into 0XCDAB when moving a value from memory to register
// when the memory address is 16 bits offset from a 32-bit boundary),
// also, the value will be stored at an address two bytes lower than the address
// value would ordinarily indicate.
//
// The key-value pair is of type T. The first field in T must
// be the key, i.e., the first K bytes of T contains the key.
// total_size = sizeof(T) and thus sizeof(T) >= sizeof(K)
//
// N is the number of buckets.
//
struct utp_hash_t {
utp_link_t N;
byte K;
byte E;
size_t count;
utp_hash_compute_t hash_compute;
utp_hash_equal_t hash_equal;
utp_link_t allocated;
utp_link_t used;
utp_link_t free;
utp_link_t inits[0];
};
#ifdef _MSC_VER
#pragma warning (default: 4200)
#endif
struct utp_hash_iterator_t {
utp_link_t bucket;
utp_link_t elem;
utp_hash_iterator_t() : bucket(0xffffffff), elem(0xffffffff) {}
};
uint utp_hash_mem(const void *keyp, size_t keysize);
uint utp_hash_comp(const void *key_a, const void *key_b, size_t keysize);
utp_hash_t *utp_hash_create(int N, int key_size, int total_size, int initial, utp_hash_compute_t hashfun = utp_hash_mem, utp_hash_equal_t eqfun = NULL);
void *utp_hash_lookup(utp_hash_t *hash, const void *key);
void *utp_hash_add(utp_hash_t **hashp, const void *key);
void *utp_hash_del(utp_hash_t *hash, const void *key);
void *utp_hash_iterate(utp_hash_t *hash, utp_hash_iterator_t *iter);
void utp_hash_free_mem(utp_hash_t *hash);
/*
This HashTable requires that T have at least sizeof(K)+sizeof(utp_link_t) bytes.
Usually done like this:
struct K {
int whatever;
};
struct T {
K wtf;
utp_link_t link; // also wtf
};
*/
template<typename K, typename T> class utpHashTable {
utp_hash_t *hash;
public:
static uint compare(const void *k1, const void *k2, size_t ks) {
return *((K*)k1) == *((K*)k2);
}
static uint32 compute_hash(const void *k, size_t ks) {
return ((K*)k)->compute_hash();
}
void Init() { hash = NULL; }
bool Allocated() { return (hash != NULL); }
void Free() { utp_hash_free_mem(hash); hash = NULL; }
void Create(int N, int initial) { hash = utp_hash_create(N, sizeof(K), sizeof(T), initial, &compute_hash, &compare); }
T *Lookup(const K &key) { return (T*)utp_hash_lookup(hash, &key); }
T *Add(const K &key) { return (T*)utp_hash_add(&hash, &key); }
T *Delete(const K &key) { return (T*)utp_hash_del(hash, &key); }
T *Iterate(utp_hash_iterator_t &iterator) { return (T*)utp_hash_iterate(hash, &iterator); }
size_t GetCount() { return hash->count; }
};
#endif //__UTP_HASH_H__

3489
vendor/github.com/anacrolix/go-libutp/utp_internal.cpp generated vendored Normal file

File diff suppressed because it is too large Load Diff

141
vendor/github.com/anacrolix/go-libutp/utp_internal.h generated vendored Normal file
View File

@@ -0,0 +1,141 @@
/*
* Copyright (c) 2010-2013 BitTorrent, Inc.
*
* 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.
*/
#ifndef __UTP_INTERNAL_H__
#define __UTP_INTERNAL_H__
#include <stdarg.h>
#include <string.h>
#include <assert.h>
#include <stdio.h>
#include "utp.h"
#include "utp_callbacks.h"
#include "utp_templates.h"
#include "utp_hash.h"
#include "utp_hash.h"
#include "utp_packedsockaddr.h"
/* These originally lived in utp_config.h */
#define CCONTROL_TARGET (100 * 1000) // us
enum bandwidth_type_t {
payload_bandwidth, connect_overhead,
close_overhead, ack_overhead,
header_overhead, retransmit_overhead
};
#ifdef WIN32
#ifdef _MSC_VER
#include "libutp_inet_ntop.h"
#endif
// newer versions of MSVC define these in errno.h
#ifndef ECONNRESET
#define ECONNRESET WSAECONNRESET
#define EMSGSIZE WSAEMSGSIZE
#define ECONNREFUSED WSAECONNREFUSED
#define ETIMEDOUT WSAETIMEDOUT
#endif
#endif
struct PACKED_ATTRIBUTE RST_Info {
PackedSockAddr addr;
uint32 connid;
uint16 ack_nr;
uint64 timestamp;
};
// It's really important that we don't have duplicate keys in the hash table.
// If we do, we'll eventually crash. if we try to remove the second instance
// of the key, we'll accidentally remove the first instead. then later,
// checkTimeouts will try to access the second one's already freed memory.
void UTP_FreeAll(struct UTPSocketHT *utp_sockets);
struct UTPSocketKey {
PackedSockAddr addr;
uint32 recv_id; // "conn_seed", "conn_id"
UTPSocketKey(const PackedSockAddr& _addr, uint32 _recv_id) {
memset(this, 0, sizeof(*this));
addr = _addr;
recv_id = _recv_id;
}
bool operator == (const UTPSocketKey &other) const {
return recv_id == other.recv_id && addr == other.addr;
}
uint32 compute_hash() const {
return recv_id ^ addr.compute_hash();
}
};
struct UTPSocketKeyData {
UTPSocketKey key;
UTPSocket *socket;
utp_link_t link;
};
#define UTP_SOCKET_BUCKETS 79
#define UTP_SOCKET_INIT 15
struct UTPSocketHT : utpHashTable<UTPSocketKey, UTPSocketKeyData> {
UTPSocketHT() {
const int buckets = UTP_SOCKET_BUCKETS;
const int initial = UTP_SOCKET_INIT;
this->Create(buckets, initial);
}
~UTPSocketHT() {
UTP_FreeAll(this);
this->Free();
}
};
struct struct_utp_context {
void *userdata;
utp_callback_t* callbacks[UTP_ARRAY_SIZE];
uint64 current_ms;
utp_context_stats context_stats;
UTPSocket *last_utp_socket;
Array<UTPSocket*> ack_sockets;
Array<RST_Info> rst_info;
UTPSocketHT *utp_sockets;
size_t target_delay;
size_t opt_sndbuf;
size_t opt_rcvbuf;
uint64 last_check;
struct_utp_context();
~struct_utp_context();
void log(int level, utp_socket *socket, char const *fmt, ...);
void log_unchecked(utp_socket *socket, char const *fmt, ...);
bool would_log(int level);
bool log_normal:1; // log normal events?
bool log_mtu:1; // log MTU related events?
bool log_debug:1; // log debugging events? (Must also compile with UTP_DEBUG_LOGGING defined)
};
#endif //__UTP_INTERNAL_H__

View File

@@ -0,0 +1,139 @@
// vim:set ts=4 sw=4 ai:
/*
* Copyright (c) 2010-2013 BitTorrent, Inc.
*
* 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.
*/
#include <string.h>
#include <assert.h>
#include <stdio.h>
#include "utp_types.h"
#include "utp_hash.h"
#include "utp_packedsockaddr.h"
#include "libutp_inet_ntop.h"
byte PackedSockAddr::get_family() const
{
#if defined(__sh__)
return ((_sin6d[0] == 0) && (_sin6d[1] == 0) && (_sin6d[2] == htonl(0xffff)) != 0) ?
AF_INET : AF_INET6;
#else
return (IN6_IS_ADDR_V4MAPPED(&_in._in6addr) != 0) ? AF_INET : AF_INET6;
#endif // defined(__sh__)
}
bool PackedSockAddr::operator==(const PackedSockAddr& rhs) const
{
if (&rhs == this)
return true;
if (_port != rhs._port)
return false;
return memcmp(_sin6, rhs._sin6, sizeof(_sin6)) == 0;
}
bool PackedSockAddr::operator!=(const PackedSockAddr& rhs) const
{
return !(*this == rhs);
}
uint32 PackedSockAddr::compute_hash() const {
return utp_hash_mem(&_in, sizeof(_in)) ^ _port;
}
void PackedSockAddr::set(const SOCKADDR_STORAGE* sa, socklen_t len)
{
if (sa->ss_family == AF_INET) {
assert(len >= sizeof(sockaddr_in));
const sockaddr_in *sin = (sockaddr_in*)sa;
_sin6w[0] = 0;
_sin6w[1] = 0;
_sin6w[2] = 0;
_sin6w[3] = 0;
_sin6w[4] = 0;
_sin6w[5] = 0xffff;
_sin4 = sin->sin_addr.s_addr;
_port = ntohs(sin->sin_port);
} else {
assert(len >= sizeof(sockaddr_in6));
const sockaddr_in6 *sin6 = (sockaddr_in6*)sa;
_in._in6addr = sin6->sin6_addr;
_port = ntohs(sin6->sin6_port);
}
}
PackedSockAddr::PackedSockAddr(const SOCKADDR_STORAGE* sa, socklen_t len)
{
set(sa, len);
}
PackedSockAddr::PackedSockAddr(void)
{
SOCKADDR_STORAGE sa;
socklen_t len = sizeof(SOCKADDR_STORAGE);
memset(&sa, 0, len);
sa.ss_family = AF_INET;
set(&sa, len);
}
SOCKADDR_STORAGE PackedSockAddr::get_sockaddr_storage(socklen_t *len = NULL) const
{
SOCKADDR_STORAGE sa;
const byte family = get_family();
if (family == AF_INET) {
sockaddr_in *sin = (sockaddr_in*)&sa;
if (len) *len = sizeof(sockaddr_in);
memset(sin, 0, sizeof(sockaddr_in));
sin->sin_family = family;
sin->sin_port = htons(_port);
sin->sin_addr.s_addr = _sin4;
} else {
sockaddr_in6 *sin6 = (sockaddr_in6*)&sa;
memset(sin6, 0, sizeof(sockaddr_in6));
if (len) *len = sizeof(sockaddr_in6);
sin6->sin6_family = family;
sin6->sin6_addr = _in._in6addr;
sin6->sin6_port = htons(_port);
}
return sa;
}
// #define addrfmt(x, s) x.fmt(s, sizeof(s))
cstr PackedSockAddr::fmt(str s, size_t len) const
{
memset(s, 0, len);
const byte family = get_family();
str i;
if (family == AF_INET) {
INET_NTOP(family, (uint32*)&_sin4, s, len);
i = s;
while (*++i) {}
} else {
i = s;
*i++ = '[';
INET_NTOP(family, (in6_addr*)&_in._in6addr, i, len-1);
while (*++i) {}
*i++ = ']';
}
snprintf(i, len - (i-s), ":%u", _port);
return s;
}

View File

@@ -0,0 +1,60 @@
/*
* Copyright (c) 2010-2013 BitTorrent, Inc.
*
* 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.
*/
#ifndef __UTP_PACKEDSOCKADDR_H__
#define __UTP_PACKEDSOCKADDR_H__
#include "utp_types.h"
struct PACKED_ATTRIBUTE PackedSockAddr {
// The values are always stored here in network byte order
union {
byte _in6[16]; // IPv6
uint16 _in6w[8]; // IPv6, word based (for convenience)
uint32 _in6d[4]; // Dword access
in6_addr _in6addr; // For convenience
} _in;
// Host byte order
uint16 _port;
#define _sin4 _in._in6d[3] // IPv4 is stored where it goes if mapped
#define _sin6 _in._in6
#define _sin6w _in._in6w
#define _sin6d _in._in6d
byte get_family() const;
bool operator==(const PackedSockAddr& rhs) const;
bool operator!=(const PackedSockAddr& rhs) const;
void set(const SOCKADDR_STORAGE* sa, socklen_t len);
PackedSockAddr(const SOCKADDR_STORAGE* sa, socklen_t len);
PackedSockAddr(void);
SOCKADDR_STORAGE get_sockaddr_storage(socklen_t *len) const;
cstr fmt(str s, size_t len) const;
uint32 compute_hash() const;
} ALIGNED_ATTRIBUTE(4);
#endif //__UTP_PACKEDSOCKADDR_H__

195
vendor/github.com/anacrolix/go-libutp/utp_templates.h generated vendored Normal file
View File

@@ -0,0 +1,195 @@
/*
* Copyright (c) 2010-2013 BitTorrent, Inc.
*
* 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.
*/
#ifndef __TEMPLATES_H__
#define __TEMPLATES_H__
#include "utp_types.h"
#include <assert.h>
#if defined(POSIX)
/* Allow over-writing FORCEINLINE from makefile because gcc 3.4.4 for buffalo
doesn't seem to support __attribute__((always_inline)) in -O0 build
(strangely, it works in -Os build) */
#ifndef FORCEINLINE
// The always_inline attribute asks gcc to inline the function even if no optimization is being requested.
// This macro should be used exclusive-or with the inline directive (use one or the other but not both)
// since Microsoft uses __forceinline to also mean inline,
// and this code is following a Microsoft compatibility model.
// Just setting the attribute without also specifying the inline directive apparently won't inline the function,
// as evidenced by multiply-defined symbols found at link time.
#define FORCEINLINE inline __attribute__((always_inline))
#endif
#endif
// Utility templates
#undef min
#undef max
template <typename T> static inline T min(T a, T b) { if (a < b) return a; return b; }
template <typename T> static inline T max(T a, T b) { if (a > b) return a; return b; }
template <typename T> static inline T min(T a, T b, T c) { return min(min(a,b),c); }
template <typename T> static inline T max(T a, T b, T c) { return max(max(a,b),c); }
template <typename T> static inline T clamp(T v, T mi, T ma)
{
if (v > ma) v = ma;
if (v < mi) v = mi;
return v;
}
#if (defined(__SVR4) && defined(__sun))
#pragma pack(1)
#else
#pragma pack(push,1)
#endif
namespace aux
{
FORCEINLINE uint16 host_to_network(uint16 i) { return htons(i); }
FORCEINLINE uint32 host_to_network(uint32 i) { return htonl(i); }
FORCEINLINE int32 host_to_network(int32 i) { return htonl(i); }
FORCEINLINE uint16 network_to_host(uint16 i) { return ntohs(i); }
FORCEINLINE uint32 network_to_host(uint32 i) { return ntohl(i); }
FORCEINLINE int32 network_to_host(int32 i) { return ntohl(i); }
}
template <class T>
struct PACKED_ATTRIBUTE big_endian
{
T operator=(T i) { m_integer = aux::host_to_network(i); return i; }
operator T() const { return aux::network_to_host(m_integer); }
private:
T m_integer;
};
typedef big_endian<int32> int32_big;
typedef big_endian<uint32> uint32_big;
typedef big_endian<uint16> uint16_big;
#if (defined(__SVR4) && defined(__sun))
#pragma pack(0)
#else
#pragma pack(pop)
#endif
template<typename T> static inline void zeromem(T *a, size_t count = 1) { memset(a, 0, count * sizeof(T)); }
typedef int SortCompareProc(const void *, const void *);
template<typename T> static FORCEINLINE void QuickSortT(T *base, size_t num, int (*comp)(const T *, const T *)) { qsort(base, num, sizeof(T), (SortCompareProc*)comp); }
// WARNING: The template parameter MUST be a POD type!
template <typename T, size_t minsize = 16> class Array {
protected:
T *mem;
size_t alloc,count;
public:
Array(size_t init) { Init(init); }
Array() { Init(); }
~Array() { Free(); }
void inline Init() { mem = NULL; alloc = count = 0; }
void inline Init(size_t init) { Init(); if (init) Resize(init); }
size_t inline GetCount() const { return count; }
size_t inline GetAlloc() const { return alloc; }
void inline SetCount(size_t c) { count = c; }
inline T& operator[](size_t offset) { assert(offset ==0 || offset<alloc); return mem[offset]; }
inline const T& operator[](size_t offset) const { assert(offset ==0 || offset<alloc); return mem[offset]; }
void inline Resize(size_t a) {
if (a == 0) { free(mem); Init(); }
else { mem = (T*)realloc(mem, (alloc=a) * sizeof(T)); }
}
void Grow() { Resize(::max<size_t>(minsize, alloc * 2)); }
inline size_t Append(const T &t) {
if (count >= alloc) Grow();
size_t r=count++;
mem[r] = t;
return r;
}
T inline &Append() {
if (count >= alloc) Grow();
return mem[count++];
}
void inline Compact() {
Resize(count);
}
void inline Free() {
free(mem);
Init();
}
void inline Clear() {
count = 0;
}
bool inline MoveUpLast(size_t index) {
assert(index < count);
size_t c = --count;
if (index != c) {
mem[index] = mem[c];
return true;
}
return false;
}
bool inline MoveUpLastExist(const T &v) {
return MoveUpLast(LookupElementExist(v));
}
size_t inline LookupElement(const T &v) const {
for(size_t i = 0; i != count; i++)
if (mem[i] == v)
return i;
return (size_t) -1;
}
bool inline HasElement(const T &v) const {
return LookupElement(v) != -1;
}
typedef int SortCompareProc(const T *a, const T *b);
void Sort(SortCompareProc* proc, size_t start, size_t end) {
QuickSortT(&mem[start], end - start, proc);
}
void Sort(SortCompareProc* proc, size_t start) {
Sort(proc, start, count);
}
void Sort(SortCompareProc* proc) {
Sort(proc, 0, count);
}
};
#endif //__TEMPLATES_H__

123
vendor/github.com/anacrolix/go-libutp/utp_types.h generated vendored Normal file
View File

@@ -0,0 +1,123 @@
/*
* Copyright (c) 2010-2013 BitTorrent, Inc.
*
* 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.
*/
#ifndef __UTP_TYPES_H__
#define __UTP_TYPES_H__
// Allow libutp consumers or prerequisites to override PACKED_ATTRIBUTE
#ifndef PACKED_ATTRIBUTE
#if defined BROKEN_GCC_STRUCTURE_PACKING && defined __GNUC__
// Used for gcc tool chains accepting but not supporting pragma pack
// See http://gcc.gnu.org/onlinedocs/gcc/Type-Attributes.html
#define PACKED_ATTRIBUTE __attribute__((__packed__))
#else
#define PACKED_ATTRIBUTE
#endif // defined BROKEN_GCC_STRUCTURE_PACKING && defined __GNUC__
#endif // ndef PACKED_ATTRIBUTE
#ifdef __GNUC__
#define ALIGNED_ATTRIBUTE(x) __attribute__((aligned (x)))
#else
#define ALIGNED_ATTRIBUTE(x)
#endif
// hash.cpp needs socket definitions, which is why this networking specific
// code is inclued in utypes.h
#ifdef WIN32
#define _CRT_SECURE_NO_DEPRECATE
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#define IP_OPT_DONTFRAG IP_DONTFRAGMENT
#define SHUT_RD SD_RECEIVE
#define SHUT_WR SD_SEND
#define SHUT_RDWR SD_BOTH
#else
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/socket.h>
#ifdef IP_DONTFRAG
#define IP_OPT_DONTFRAG IP_DONTFRAG
#elif defined IP_DONTFRAGMENT
#define IP_OPT_DONTFRAG IP_DONTFRAGMENT
#else
//#warning "I don't know how to set DF bit on this system"
#endif
#endif
#ifdef _MSC_VER
#include <BaseTsd.h>
typedef SSIZE_T ssize_t;
#endif
#ifdef POSIX
typedef struct sockaddr_storage SOCKADDR_STORAGE;
#endif
#ifdef WIN32
#define I64u "%I64u"
#else
#define I64u "%Lu"
#endif
// standard types
typedef unsigned char byte;
typedef unsigned char uint8;
typedef signed char int8;
typedef unsigned short uint16;
typedef signed short int16;
typedef unsigned int uint;
typedef unsigned int uint32;
typedef signed int int32;
#ifdef _MSC_VER
typedef unsigned __int64 uint64;
typedef signed __int64 int64;
#else
typedef unsigned long long uint64;
typedef long long int64;
#endif
/* compile-time assert */
#ifndef CASSERT
#define CASSERT( exp, name ) typedef int is_not_##name [ (exp ) ? 1 : -1 ];
#endif
CASSERT(8 == sizeof(uint64), sizeof_uint64_is_8)
CASSERT(8 == sizeof(int64), sizeof_int64_is_8)
#ifndef INT64_MAX
#define INT64_MAX 0x7fffffffffffffffLL
#endif
// always ANSI
typedef const char * cstr;
typedef char * str;
#ifndef __cplusplus
typedef uint8 bool;
#endif
#endif //__UTP_TYPES_H__

254
vendor/github.com/anacrolix/go-libutp/utp_utils.cpp generated vendored Normal file
View File

@@ -0,0 +1,254 @@
/*
* Copyright (c) 2010-2013 BitTorrent, Inc.
*
* 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.
*/
#include <stdlib.h>
#include <assert.h>
#include "utp.h"
#include "utp_types.h"
#ifdef WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#else //!WIN32
#include <time.h>
#include <sys/time.h> // Linux needs both time.h and sys/time.h
#endif
#if defined(__APPLE__)
#include <mach/mach_time.h>
#endif
#include "utp_utils.h"
#ifdef WIN32
typedef ULONGLONG (WINAPI GetTickCount64Proc)(void);
static GetTickCount64Proc *pt2GetTickCount64;
static GetTickCount64Proc *pt2RealGetTickCount;
static uint64 startPerformanceCounter;
static uint64 startGetTickCount;
// MSVC 6 standard doesn't like division with uint64s
static double counterPerMicrosecond;
static uint64 UTGetTickCount64()
{
if (pt2GetTickCount64) {
return pt2GetTickCount64();
}
if (pt2RealGetTickCount) {
uint64 v = pt2RealGetTickCount();
// fix return value from GetTickCount
return (DWORD)v | ((v >> 0x18) & 0xFFFFFFFF00000000);
}
return (uint64)GetTickCount();
}
static void Time_Initialize()
{
HMODULE kernel32 = GetModuleHandleA("kernel32.dll");
pt2GetTickCount64 = (GetTickCount64Proc*)GetProcAddress(kernel32, "GetTickCount64");
// not a typo. GetTickCount actually returns 64 bits
pt2RealGetTickCount = (GetTickCount64Proc*)GetProcAddress(kernel32, "GetTickCount");
uint64 frequency;
QueryPerformanceCounter((LARGE_INTEGER*)&startPerformanceCounter);
QueryPerformanceFrequency((LARGE_INTEGER*)&frequency);
counterPerMicrosecond = (double)frequency / 1000000.0f;
startGetTickCount = UTGetTickCount64();
}
static int64 abs64(int64 x) { return x < 0 ? -x : x; }
static uint64 __GetMicroseconds()
{
static bool time_init = false;
if (!time_init) {
time_init = true;
Time_Initialize();
}
uint64 counter;
uint64 tick;
QueryPerformanceCounter((LARGE_INTEGER*) &counter);
tick = UTGetTickCount64();
// unfortunately, QueryPerformanceCounter is not guaranteed
// to be monotonic. Make it so.
int64 ret = (int64)(((int64)counter - (int64)startPerformanceCounter) / counterPerMicrosecond);
// if the QPC clock leaps more than one second off GetTickCount64()
// something is seriously fishy. Adjust QPC to stay monotonic
int64 tick_diff = tick - startGetTickCount;
if (abs64(ret / 100000 - tick_diff / 100) > 10) {
startPerformanceCounter -= (uint64)((int64)(tick_diff * 1000 - ret) * counterPerMicrosecond);
ret = (int64)((counter - startPerformanceCounter) / counterPerMicrosecond);
}
return ret;
}
static inline uint64 UTP_GetMilliseconds()
{
return GetTickCount();
}
#else //!WIN32
static inline uint64 UTP_GetMicroseconds(void);
static inline uint64 UTP_GetMilliseconds()
{
return UTP_GetMicroseconds() / 1000;
}
#if defined(__APPLE__)
static uint64 __GetMicroseconds()
{
// http://developer.apple.com/mac/library/qa/qa2004/qa1398.html
// http://www.macresearch.org/tutorial_performance_and_time
static mach_timebase_info_data_t sTimebaseInfo;
static uint64_t start_tick = 0;
uint64_t tick;
// Returns a counter in some fraction of a nanoseconds
tick = mach_absolute_time();
if (sTimebaseInfo.denom == 0) {
// Get the timer ratio to convert mach_absolute_time to nanoseconds
mach_timebase_info(&sTimebaseInfo);
start_tick = tick;
}
// Calculate the elapsed time, convert it to microseconds and return it.
return ((tick - start_tick) * sTimebaseInfo.numer) / (sTimebaseInfo.denom * 1000);
}
#else // !__APPLE__
#if ! (defined(_POSIX_TIMERS) && _POSIX_TIMERS > 0 && defined(CLOCK_MONOTONIC))
#warning "Using non-monotonic function gettimeofday() in UTP_GetMicroseconds()"
#endif
/* Unfortunately, #ifdef CLOCK_MONOTONIC is not enough to make sure that
POSIX clocks work -- we could be running a recent libc with an ancient
kernel (think OpenWRT). -- jch */
static uint64_t __GetMicroseconds()
{
struct timeval tv;
#if defined(_POSIX_TIMERS) && _POSIX_TIMERS > 0 && defined(CLOCK_MONOTONIC)
static int have_posix_clocks = -1;
int rc;
if (have_posix_clocks < 0) {
struct timespec ts;
rc = clock_gettime(CLOCK_MONOTONIC, &ts);
if (rc < 0) {
have_posix_clocks = 0;
} else {
have_posix_clocks = 1;
}
}
if (have_posix_clocks) {
struct timespec ts;
rc = clock_gettime(CLOCK_MONOTONIC, &ts);
return uint64(ts.tv_sec) * 1000000 + uint64(ts.tv_nsec) / 1000;
}
#endif
gettimeofday(&tv, NULL);
return uint64(tv.tv_sec) * 1000000 + tv.tv_usec;
}
#endif //!__APPLE__
#endif //!WIN32
/*
* Whew. Okay. After that #ifdef maze above, we now know we have a working
* __GetMicroseconds() implementation on all platforms.
*
* Because there are a number of assertions in libutp that will cause a crash
* if monotonic time isn't monotonic, now apply some safety checks. While in
* principle we're already protecting ourselves in cases where non-monotonic
* time is likely to happen, this protects all versions.
*/
static inline uint64 UTP_GetMicroseconds()
{
static uint64 offset = 0, previous = 0;
uint64 now = __GetMicroseconds() + offset;
if (previous > now) {
/* Eek! */
offset += previous - now;
now = previous;
}
previous = now;
return now;
}
#define ETHERNET_MTU 1500
#define IPV4_HEADER_SIZE 20
#define IPV6_HEADER_SIZE 40
#define UDP_HEADER_SIZE 8
#define GRE_HEADER_SIZE 24
#define PPPOE_HEADER_SIZE 8
#define MPPE_HEADER_SIZE 2
// packets have been observed in the wild that were fragmented
// with a payload of 1416 for the first fragment
// There are reports of routers that have MTU sizes as small as 1392
#define FUDGE_HEADER_SIZE 36
#define TEREDO_MTU 1280
#define UDP_IPV4_OVERHEAD (IPV4_HEADER_SIZE + UDP_HEADER_SIZE)
#define UDP_IPV6_OVERHEAD (IPV6_HEADER_SIZE + UDP_HEADER_SIZE)
#define UDP_TEREDO_OVERHEAD (UDP_IPV4_OVERHEAD + UDP_IPV6_OVERHEAD)
#define UDP_IPV4_MTU (ETHERNET_MTU - IPV4_HEADER_SIZE - UDP_HEADER_SIZE - GRE_HEADER_SIZE - PPPOE_HEADER_SIZE - MPPE_HEADER_SIZE - FUDGE_HEADER_SIZE)
#define UDP_IPV6_MTU (ETHERNET_MTU - IPV6_HEADER_SIZE - UDP_HEADER_SIZE - GRE_HEADER_SIZE - PPPOE_HEADER_SIZE - MPPE_HEADER_SIZE - FUDGE_HEADER_SIZE)
#define UDP_TEREDO_MTU (TEREDO_MTU - IPV6_HEADER_SIZE - UDP_HEADER_SIZE)
uint64 utp_default_get_udp_mtu(utp_callback_arguments *args) {
// Since we don't know the local address of the interface,
// be conservative and assume all IPv6 connections are Teredo.
return (args->address->sa_family == AF_INET6) ? UDP_TEREDO_MTU : UDP_IPV4_MTU;
}
uint64 utp_default_get_udp_overhead(utp_callback_arguments *args) {
// Since we don't know the local address of the interface,
// be conservative and assume all IPv6 connections are Teredo.
return (args->address->sa_family == AF_INET6) ? UDP_TEREDO_OVERHEAD : UDP_IPV4_OVERHEAD;
}
uint64 utp_default_get_random(utp_callback_arguments *args) {
return rand();
}
uint64 utp_default_get_milliseconds(utp_callback_arguments *args) {
return UTP_GetMilliseconds();
}
uint64 utp_default_get_microseconds(utp_callback_arguments *args) {
return UTP_GetMicroseconds();
}

27
vendor/github.com/anacrolix/go-libutp/utp_utils.h generated vendored Normal file
View File

@@ -0,0 +1,27 @@
/*
* Copyright (c) 2010-2013 BitTorrent, Inc.
*
* 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.
*/
uint64 utp_default_get_udp_mtu(utp_callback_arguments *args);
uint64 utp_default_get_udp_overhead(utp_callback_arguments *args);
uint64 utp_default_get_random(utp_callback_arguments *args);
uint64 utp_default_get_milliseconds(utp_callback_arguments *args);
uint64 utp_default_get_microseconds(utp_callback_arguments *args);