Use anacrolix/go-libutp instead

Overview

utp

GoDoc CircleCI

Package utp implements uTP, the micro transport protocol as used with Bittorrent. It opts for simplicity and reliability over strict adherence to the (poor) spec.

Supported

  • Multiple uTP connections switched on a single PacketConn, including those initiated locally.
  • Raw access to the PacketConn for non-uTP purposes, like sharing the PacketConn with a DHT implementation.

Implementation characteristics

  • There is no MTU path discovery.
  • A fixed 64 slot selective ack window is used in both sending and receiving.

Patches welcomed.

Comments
  • panic: listen udp :50007: bind: address already in use

    panic: listen udp :50007: bind: address already in use

    Not sure what is the reason you do not call SO_REUSEADDR or lazyDestroy() does the job but I unable to restart application. Especially It hurts on Android.

    Can you make Socket.destroy() exported if it helps? Or how to wait until socket will be destoryed?

    opened by axet 22
  • remove missinggo dep

    remove missinggo dep

    It looks like you were only using one function from missinggo, but because of that this package pulled in a whole bunch of other largeish dependencies, including some that fail to build on certain platforms.

    This copies the one function from missinggo into the test file and removes that dependency.

    opened by whyrusleeping 13
  • throughput is 5 MB/s on loopback

    throughput is 5 MB/s on loopback

    Hi

    I tested with go 1.5 on Mac Air:

    $ go get github.com/anacrolix/utp
    $ go get github.com/anacrolix/utp/cmd/ucat
    $ ./bin/ucat -l -p 9876 >/dev/null &
    $ dd if=/dev/zero bs=1m count=100 | ./bin/ucat 127.0.0.1 9876
    100+0 records in
    100+0 records out
    104857600 bytes transferred in 18.542269 secs ( *** 5655058 bytes/sec *** )
    2015/09/07 03:51:28 wrote 104857600 bytes
    2015/09/07 03:51:28 received 0 bytes
    2015/09/07 03:51:28 received 104857600 bytes
    

    This is compared to native build of ucat from https://github.com/bittorrent/libutp:

    $ ./build/Release/ucat -l -p 9876 >/dev/null &
    $ dd if=/dev/zero bs=1m count=1000 | ./build/Release/ucat -B $((256*1024)) 127.0.0.1 9876
    1000+0 records in
    1000+0 records out
    1048576000 bytes transferred in 11.888499 secs ( *** 88200875 bytes/sec *** )
    

    That's a big drop.. Cheers

    opened by guymguym 13
  • memory usage a bit high

    memory usage a bit high

    I'm having some of my ipfs nodes die of OOM, and looking at the heap profile I see that utp was using 100MB (of my machines 256MB of RAM). It all appears to have been allocated by the sendBufferPool's allocation function. That seems a bit much, and i'm sure some of this is user error on my part. Any ideas how to debug the issue?

    opened by whyrusleeping 11
  • Reasoning behind this panic

    Reasoning behind this panic

    I have been consistently hitting this panic in my application, and curious as to the reasoning of it, and how I may be triggering it?

    https://github.com/anacrolix/utp/blob/master/socket.go#L484

    The stack trace goes back to this call:

    https://github.com/anacrolix/torrent/blob/master/client.go#L383

    My application is handling tens of thousands of torrents, and it works very well, but eventually (<hr) hits this panic. I am not quite sure how to handle this. I am unable to produce sample code to trigger this, as although I am reliably producing it, it is infrequent and hard to track down which action is causing it.

    Edit: I also am getting this output fair frequently when dealing with this load. resetting conflicting syn

    opened by Emyrk 6
  • net.Listener interface

    net.Listener interface

    If i want to listen on utp packets, what i need to do? As i see package does not have Listen method, so i need to listen udp specific port and use NewSocketFromPacketConn? Does does it possible to create Listen method?

    opened by vtolstov 6
  • Ability to pass in a net.UDPConn

    Ability to pass in a net.UDPConn

    So that we could do the STUN dance or whatever is required before wrapping it in UTP. Similarly how you can wrap and unwrap a TCP connection with tls.Server or tls.Client.

    opened by AudriusButkevicius 6
  • Dial leaks file descriptors

    Dial leaks file descriptors

    calling Dial opens a new socket, then calls dial on that socket. closing the returned connection doesnt appear to close the opened socket, leading to a file descriptor leak.

    opened by whyrusleeping 5
  • panic in jitter

    panic in jitter

    Found a panic thrown in utp: https://gist.githubusercontent.com/dignifiedquire/33c5e9b5af4305491e37/raw/7c0c8731916bf8b21f723a8c1a32c2e1276bb993/fail.log

    opened by whyrusleeping 4
  • Conn `Addr` methods return udp

    Conn `Addr` methods return udp

    I'm not sure if this is actually an issue, but the LocalAddr and RemoteAddr methods on a Conn return an address whose network identifies as udp. I think these should return utp{4,6} instead, as its more accurate.

    I currently wrap the utp conn from your package to change this functionality, but if you could add it upstream that would be very helpful.

    opened by whyrusleeping 3
  • listener sockets closed when accepted connections close

    listener sockets closed when accepted connections close

    If i create a socket for accepting new connections on, I want to keep that open even if all the connections that have been made to me get closed, That expectation is violated by this line: https://github.com/anacrolix/utp/blob/master/utp.go#L1252

    I think that line only needs to be executed if the connections drop to zero AND the socket was created through a 'dial' (or even then probably not). Its probably the case that the right thing to do is to only close the actual socket when 'Close' is called.

    opened by whyrusleeping 3
  • Lots of duplicate packets are being send

    Lots of duplicate packets are being send

    I am trying to hunt down an issue I have with this library where I notice that the uTP transfer does not back-off when there is TCP background traffic.

    Tracing this issue I noticed that an extensive number of packets are being resend. I noticed this was primarily due to this call to resend which is caused by this call to ackSkipped. Using wireshark I noticed that lots of ACK packets do have the Selective ACKs extension enabled but do not have an extension bitmask:

    screen shot 2017-05-30 at 15 14 07

    According to the specification the length should be:

    Note that the len field of extensions refer to bytes, which in this extension must be at least 4, and in multiples of 4.

    There are also ACK packets that do have this set correctly:

    screen shot 2017-05-30 at 15 13 23

    Now as a quick hack I've tried not calling ackSkipped when there are no bytes in the extension:

    		switch ext.Type {
    		case extensionTypeSelectiveAck:
    			if len(ext.Bytes) > 0 {
    				c.ackSkipped(h.AckNr + 1)
    				bitmask := selectiveAckBitmask{ext.Bytes}
    				for i := 0; i < bitmask.NumBits(); i++ {
    					if bitmask.BitIsSet(i) {
    						nr := h.AckNr + 2 + uint16(i)
    						c.ack(nr)
    					} else {
    						c.ackSkipped(h.AckNr + 2 + uint16(i))
    					}
    				}
    			}
                  }
    

    and I've also changed ackSkipped to not resend the packets that often:

    	switch send.acksSkipped {
    	case 60, 120: // was 3, 60
    		if logLevel >= 1 {
    			log.Printf("acksSkipped = %d", send.acksSkipped)
    		}
    		ackSkippedResends.Add(1)
    		send.resend()
    		send.resendTimer.Reset(c.resendTimeout() * time.Duration(send.numResends))
    	default:
    	}
    

    For me this is dramatically decreasing the number of duplicates that are being send.

    However it does not fix my issue with uTP traffic throttling back when there is TCP background traffic.

    Does this make sense?

    help wanted 
    opened by eelcocramer 16
  • Starts stalling under load

    Starts stalling under load

    Using this benchmark:

    import (
        "net"
        "testing"
    
        "github.com/anacrolix/utp"
    )
    
    func getTCPConnectionPair() (net.Conn, net.Conn, error) {
        lst, err := net.Listen("tcp", "127.0.0.1:0")
        if err != nil {
            return nil, nil, err
        }
    
        var conn0 net.Conn
        var err0 error
        done := make(chan struct{})
        go func() {
            conn0, err0 = lst.Accept()
            close(done)
        }()
    
        conn1, err := net.Dial("tcp", lst.Addr().String())
        if err != nil {
            return nil, nil, err
        }
    
        <-done
        if err0 != nil {
            return nil, nil, err0
        }
        return conn0, conn1, nil
    }
    
    func getUTPConnectionPair() (net.Conn, net.Conn, error) {
        lst, err := utp.NewSocket("udp", "127.0.0.1:0")
        if err != nil {
            return nil, nil, err
        }
    
        var conn0 net.Conn
        var err0 error
        done := make(chan struct{})
        go func() {
            conn0, err0 = lst.Accept()
            close(done)
        }()
    
        conn1, err := utp.Dial(lst.Addr().String())
        if err != nil {
            return nil, nil, err
        }
    
        <-done
        if err0 != nil {
            return nil, nil, err0
        }
    
        return conn0, conn1, nil
    }
    
    
    func benchConnPair(b *testing.B, c0, c1 net.Conn) {
        b.ReportAllocs()
        b.SetBytes(128 << 10)
        b.ResetTimer()
    
        request := make([]byte, 52)
        response := make([]byte, (128<<10)+8)
    
        pair := []net.Conn{c0, c1}
        for i := 0; i < b.N; i++ {
            if i%2 == 0 {
                pair[0] = c0
                pair[1] = c1
            } else {
                pair[0] = c1
                pair[1] = c0
            }
    
            if _, err := pair[0].Write(request); err != nil {
                b.Fatal(err)
            }
    
            if _, err := pair[1].Read(request[:8]); err != nil {
                b.Fatal(err)
            }
            if _, err := pair[1].Read(request[8:]); err != nil {
                b.Fatal(err)
            }
            if _, err := pair[1].Write(response); err != nil {
                b.Fatal(err)
            }
            if _, err := pair[0].Read(response[:8]); err != nil {
                b.Fatal(err)
            }
            if _, err := pair[0].Read(response[8:]); err != nil {
                b.Fatal(err)
            }
        }
    }
    
    func BenchmarkTCP(b *testing.B) {
        conn0, conn1, err := getTCPConnectionPair()
        if err != nil {
            b.Fatal(err)
        }
    
        defer conn0.Close()
        defer conn1.Close()
    
        benchConnPair(b, conn0, conn1)
    }
    
    func BenchmarkUTP(b *testing.B) {
        conn0, conn1, err := getUTPConnectionPair()
        if err != nil {
            b.Fatal(err)
        }
    
        defer conn0.Close()
        defer conn1.Close()
    
        benchConnPair(b, conn0, conn1)
    }
    
    
    

    I get the following:

    PASS
    BenchmarkTCP-4      5000        263246 ns/op     497.91 MB/s          27 B/op          0 allocs/op
    BenchmarkUTP-4  2016/05/26 23:21:51 error resending packet: write udp [::]:56345->127.0.0.1:56344: use of closed network connection
    2016/05/26 23:21:51 error resending packet: write udp [::]:56345->127.0.0.1:56344: use of closed network connection
    2016/05/26 23:21:51 error resending packet: write udp [::]:56345->127.0.0.1:56344: use of closed network connection
         100     134251556 ns/op       0.98 MB/s     1195857 B/op       4016 allocs/op
    

    If you tweak the numbers a bit, you might get it to 0.2MB/s

    I did manage to get it to a point where it just mostly never completes and fails with "connection closed", but that was using syncthings protocol wrappers which do async read/writes. In cases where it did complete it was around 0.3MB/s

    help wanted 
    opened by AudriusButkevicius 43
Owner
Matt Joiner
I'm a functional programming and concurrency enthusiast that got sucked into Go. Please send help.
Matt Joiner
Use Consul to do service discovery, use gRPC +kafka to do message produce and consume. Use redis to store result.

目录 gRPC/consul/kafka简介 gRPC+kafka的Demo gRPC+kafka整体示意图 限流器 基于redis计数器生成唯一ID kafka生产消费 kafka生产消费示意图 本文kafka生产消费过程 基于pprof的性能分析Demo 使用pprof统计CPU/HEAP数据的

null 43 Jul 9, 2022
golibwireshark - Package use libwireshark library to decode pcap file and analyse dissection data.

golibwireshark Package golibwireshark use libwireshark library to decode pcap file and analyse dissection data. This package can only be used in OS li

Xiaoguang Wang 28 Nov 26, 2022
Go library for writing standalone Map/Reduce jobs or for use with Hadoop's streaming protocol

dmrgo is a Go library for writing map/reduce jobs. It can be used with Hadoop's streaming protocol, but also includes a standalone map/reduce impleme

Damian Gryski 103 Nov 27, 2022
HTTP proxy written in Go. COW can automatically identify blocked sites and use parent proxies to access.

COW (Climb Over the Wall) proxy COW 是一个简化穿墙的 HTTP 代理服务器。它能自动检测被墙网站,仅对这些网站使用二级代理。 English README. 当前版本:0.9.8 CHANGELOG 欢迎在 develop branch 进行开发并发送 pull

Chen Yufei 8.4k Jan 9, 2023
The easiest, most secure way to use WireGuard and 2FA.

This repository contains all the open source Tailscale client code and the tailscaled daemon and tailscale CLI tool. The tailscaled daemon runs primarily on Linux; it also works to varying degrees on FreeBSD, OpenBSD, Darwin, and Windows.

Tailscale 10.3k Jan 8, 2023
:vulcan_salute: Fast, modern, easy-to-use network scanner

sx is the command-line network scanner designed to follow the UNIX philosophy. The goal of this project is to create the fastest network scanner with

null 1.2k Jan 2, 2023
Use ICMP requests to check the alive subnet.

Doge-AliveCheck Use ICMP requests to check the alive subnet. Build go build -ldflags "-s -w" -trimpath Usage Doge-AliveCheck.exe

TimWhite 22 Nov 11, 2022
gophertunnel is composed of several packages that may be of use for creating Minecraft related tools

gophertunnel is composed of several packages that may be of use for creating Minecraft related tools. A brief overview of all packages may be found here.

Sandertv 299 Dec 31, 2022
red-tldr is a lightweight text search tool, which is used to help red team staff quickly find the commands and key points they want to execute, so it is more suitable for use by red team personnel with certain experience.

Red Team TL;DR English | 中文简体 What is Red Team TL;DR ? red-tldr is a lightweight text search tool, which is used to help red team staff quickly find t

倾旋 182 Jan 5, 2023
A golang library about socks5, supports all socks5 commands. That Provides server and client and easy to use. Compatible with socks4 and socks4a.

socks5 This is a Golang implementation of the Socks5 protocol library. To see in this SOCKS Protocol Version 5. This library is also compatible with S

chenhao zhang 40 Nov 22, 2022
Self-hostable , easy-to-use , lightweight and feature-rich torrent client written in Go

Self-hostable , easy-to-use , lightweight and feature-rich torrent client written in Go . It comes with beautiful Web UI and Optional Multi-User Support . Run Locally or Host in Server . Open/Download/Stream Torrents in Browser Right Away!

Var Bhat 1.6k Jan 1, 2023
A simple to use SSH Jump bastion.

Kangaroo ?? A simple to use SSH Jump bastion. Installation Kangaroo can be installed by downloading it from apt and yum repo, more information on thos

Hampton 9 Jul 25, 2022
An easy-to-use, flexible network simulator library in Go.

ns-x An easy-to-use, flexible network simulator library for Go. Feature Programmatically build customizable and scalable network topology from basic n

Bytedance Inc. 106 Dec 13, 2022
A modular is an opinionated, easy-to-use P2P network stack for decentralized applications written in Go.

xlibp2p xlibp2p is an opinionated, easy-to-use P2P network stack for decentralized applications written in Go. xlibp2p is made to be minimal, robust,

XFS Network 62 Nov 9, 2022
Provides easy-to-use async IO interface with io_uring

What is io_uring io_uring io_uring-wahtsnew LWN io_uring Lord of the io_uring

Iceber Gu 359 Dec 23, 2022
High-performance, non-blocking, event-driven, easy-to-use networking framework written in Go, support tls/http1.x/websocket.

High-performance, non-blocking, event-driven, easy-to-use networking framework written in Go, support tls/http1.x/websocket.

lesismal 1.1k Jan 8, 2023
the pluto is a gateway new time, high performance, high stable, high availability, easy to use

pluto the pluto is a gateway new time, high performance, high stable, high availability, easy to use Acknowledgments thanks nbio for providing low lev

mobus 2 Sep 19, 2021
Transport to allow go-libp2p applications to natively use i2p for communication

I2P Transport for go-libp2p This library can be used to build go-libp2p applications using the i2p network. Look at transport_test.go for example usag

null 2 Sep 15, 2022