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

362
vendor/github.com/anacrolix/utp/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,362 @@
Mozilla Public License, version 2.0
1. Definitions
1.1. "Contributor"
means each individual or legal entity that creates, contributes to the
creation of, or owns Covered Software.
1.2. "Contributor Version"
means the combination of the Contributions of others (if any) used by a
Contributor and that particular Contributor's Contribution.
1.3. "Contribution"
means Covered Software of a particular Contributor.
1.4. "Covered Software"
means Source Code Form to which the initial Contributor has attached the
notice in Exhibit A, the Executable Form of such Source Code Form, and
Modifications of such Source Code Form, in each case including portions
thereof.
1.5. "Incompatible With Secondary Licenses"
means
a. that the initial Contributor has attached the notice described in
Exhibit B to the Covered Software; or
b. that the Covered Software was made available under the terms of
version 1.1 or earlier of the License, but not also under the terms of
a Secondary License.
1.6. "Executable Form"
means any form of the work other than Source Code Form.
1.7. "Larger Work"
means a work that combines Covered Software with other material, in a
separate file or files, that is not Covered Software.
1.8. "License"
means this document.
1.9. "Licensable"
means having the right to grant, to the maximum extent possible, whether
at the time of the initial grant or subsequently, any and all of the
rights conveyed by this License.
1.10. "Modifications"
means any of the following:
a. any file in Source Code Form that results from an addition to,
deletion from, or modification of the contents of Covered Software; or
b. any new file in Source Code Form that contains any Covered Software.
1.11. "Patent Claims" of a Contributor
means any patent claim(s), including without limitation, method,
process, and apparatus claims, in any patent Licensable by such
Contributor that would be infringed, but for the grant of the License,
by the making, using, selling, offering for sale, having made, import,
or transfer of either its Contributions or its Contributor Version.
1.12. "Secondary License"
means either the GNU General Public License, Version 2.0, the GNU Lesser
General Public License, Version 2.1, the GNU Affero General Public
License, Version 3.0, or any later versions of those licenses.
1.13. "Source Code Form"
means the form of the work preferred for making modifications.
1.14. "You" (or "Your")
means an individual or a legal entity exercising rights under this
License. For legal entities, "You" includes any entity that controls, is
controlled by, or is under common control with You. For purposes of this
definition, "control" means (a) the power, direct or indirect, to cause
the direction or management of such entity, whether by contract or
otherwise, or (b) ownership of more than fifty percent (50%) of the
outstanding shares or beneficial ownership of such entity.
2. License Grants and Conditions
2.1. Grants
Each Contributor hereby grants You a world-wide, royalty-free,
non-exclusive license:
a. under intellectual property rights (other than patent or trademark)
Licensable by such Contributor to use, reproduce, make available,
modify, display, perform, distribute, and otherwise exploit its
Contributions, either on an unmodified basis, with Modifications, or
as part of a Larger Work; and
b. under Patent Claims of such Contributor to make, use, sell, offer for
sale, have made, import, and otherwise transfer either its
Contributions or its Contributor Version.
2.2. Effective Date
The licenses granted in Section 2.1 with respect to any Contribution
become effective for each Contribution on the date the Contributor first
distributes such Contribution.
2.3. Limitations on Grant Scope
The licenses granted in this Section 2 are the only rights granted under
this License. No additional rights or licenses will be implied from the
distribution or licensing of Covered Software under this License.
Notwithstanding Section 2.1(b) above, no patent license is granted by a
Contributor:
a. for any code that a Contributor has removed from Covered Software; or
b. for infringements caused by: (i) Your and any other third party's
modifications of Covered Software, or (ii) the combination of its
Contributions with other software (except as part of its Contributor
Version); or
c. under Patent Claims infringed by Covered Software in the absence of
its Contributions.
This License does not grant any rights in the trademarks, service marks,
or logos of any Contributor (except as may be necessary to comply with
the notice requirements in Section 3.4).
2.4. Subsequent Licenses
No Contributor makes additional grants as a result of Your choice to
distribute the Covered Software under a subsequent version of this
License (see Section 10.2) or under the terms of a Secondary License (if
permitted under the terms of Section 3.3).
2.5. Representation
Each Contributor represents that the Contributor believes its
Contributions are its original creation(s) or it has sufficient rights to
grant the rights to its Contributions conveyed by this License.
2.6. Fair Use
This License is not intended to limit any rights You have under
applicable copyright doctrines of fair use, fair dealing, or other
equivalents.
2.7. Conditions
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in
Section 2.1.
3. Responsibilities
3.1. Distribution of Source Form
All distribution of Covered Software in Source Code Form, including any
Modifications that You create or to which You contribute, must be under
the terms of this License. You must inform recipients that the Source
Code Form of the Covered Software is governed by the terms of this
License, and how they can obtain a copy of this License. You may not
attempt to alter or restrict the recipients' rights in the Source Code
Form.
3.2. Distribution of Executable Form
If You distribute Covered Software in Executable Form then:
a. such Covered Software must also be made available in Source Code Form,
as described in Section 3.1, and You must inform recipients of the
Executable Form how they can obtain a copy of such Source Code Form by
reasonable means in a timely manner, at a charge no more than the cost
of distribution to the recipient; and
b. You may distribute such Executable Form under the terms of this
License, or sublicense it under different terms, provided that the
license for the Executable Form does not attempt to limit or alter the
recipients' rights in the Source Code Form under this License.
3.3. Distribution of a Larger Work
You may create and distribute a Larger Work under terms of Your choice,
provided that You also comply with the requirements of this License for
the Covered Software. If the Larger Work is a combination of Covered
Software with a work governed by one or more Secondary Licenses, and the
Covered Software is not Incompatible With Secondary Licenses, this
License permits You to additionally distribute such Covered Software
under the terms of such Secondary License(s), so that the recipient of
the Larger Work may, at their option, further distribute the Covered
Software under the terms of either this License or such Secondary
License(s).
3.4. Notices
You may not remove or alter the substance of any license notices
(including copyright notices, patent notices, disclaimers of warranty, or
limitations of liability) contained within the Source Code Form of the
Covered Software, except that You may alter any license notices to the
extent required to remedy known factual inaccuracies.
3.5. Application of Additional Terms
You may choose to offer, and to charge a fee for, warranty, support,
indemnity or liability obligations to one or more recipients of Covered
Software. However, You may do so only on Your own behalf, and not on
behalf of any Contributor. You must make it absolutely clear that any
such warranty, support, indemnity, or liability obligation is offered by
You alone, and You hereby agree to indemnify every Contributor for any
liability incurred by such Contributor as a result of warranty, support,
indemnity or liability terms You offer. You may include additional
disclaimers of warranty and limitations of liability specific to any
jurisdiction.
4. Inability to Comply Due to Statute or Regulation
If it is impossible for You to comply with any of the terms of this License
with respect to some or all of the Covered Software due to statute,
judicial order, or regulation then You must: (a) comply with the terms of
this License to the maximum extent possible; and (b) describe the
limitations and the code they affect. Such description must be placed in a
text file included with all distributions of the Covered Software under
this License. Except to the extent prohibited by statute or regulation,
such description must be sufficiently detailed for a recipient of ordinary
skill to be able to understand it.
5. Termination
5.1. The rights granted under this License will terminate automatically if You
fail to comply with any of its terms. However, if You become compliant,
then the rights granted under this License from a particular Contributor
are reinstated (a) provisionally, unless and until such Contributor
explicitly and finally terminates Your grants, and (b) on an ongoing
basis, if such Contributor fails to notify You of the non-compliance by
some reasonable means prior to 60 days after You have come back into
compliance. Moreover, Your grants from a particular Contributor are
reinstated on an ongoing basis if such Contributor notifies You of the
non-compliance by some reasonable means, this is the first time You have
received notice of non-compliance with this License from such
Contributor, and You become compliant prior to 30 days after Your receipt
of the notice.
5.2. If You initiate litigation against any entity by asserting a patent
infringement claim (excluding declaratory judgment actions,
counter-claims, and cross-claims) alleging that a Contributor Version
directly or indirectly infringes any patent, then the rights granted to
You by any and all Contributors for the Covered Software under Section
2.1 of this License shall terminate.
5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user
license agreements (excluding distributors and resellers) which have been
validly granted by You or Your distributors under this License prior to
termination shall survive termination.
6. Disclaimer of Warranty
Covered Software is provided under this License on an "as is" basis,
without warranty of any kind, either expressed, implied, or statutory,
including, without limitation, warranties that the Covered Software is free
of defects, merchantable, fit for a particular purpose or non-infringing.
The entire risk as to the quality and performance of the Covered Software
is with You. Should any Covered Software prove defective in any respect,
You (not any Contributor) assume the cost of any necessary servicing,
repair, or correction. This disclaimer of warranty constitutes an essential
part of this License. No use of any Covered Software is authorized under
this License except under this disclaimer.
7. Limitation of Liability
Under no circumstances and under no legal theory, whether tort (including
negligence), contract, or otherwise, shall any Contributor, or anyone who
distributes Covered Software as permitted above, be liable to You for any
direct, indirect, special, incidental, or consequential damages of any
character including, without limitation, damages for lost profits, loss of
goodwill, work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses, even if such party shall have been
informed of the possibility of such damages. This limitation of liability
shall not apply to liability for death or personal injury resulting from
such party's negligence to the extent applicable law prohibits such
limitation. Some jurisdictions do not allow the exclusion or limitation of
incidental or consequential damages, so this exclusion and limitation may
not apply to You.
8. Litigation
Any litigation relating to this License may be brought only in the courts
of a jurisdiction where the defendant maintains its principal place of
business and such litigation shall be governed by laws of that
jurisdiction, without reference to its conflict-of-law provisions. Nothing
in this Section shall prevent a party's ability to bring cross-claims or
counter-claims.
9. Miscellaneous
This License represents the complete agreement concerning the subject
matter hereof. If any provision of this License is held to be
unenforceable, such provision shall be reformed only to the extent
necessary to make it enforceable. Any law or regulation which provides that
the language of a contract shall be construed against the drafter shall not
be used to construe this License against a Contributor.
10. Versions of the License
10.1. New Versions
Mozilla Foundation is the license steward. Except as provided in Section
10.3, no one other than the license steward has the right to modify or
publish new versions of this License. Each version will be given a
distinguishing version number.
10.2. Effect of New Versions
You may distribute the Covered Software under the terms of the version
of the License under which You originally received the Covered Software,
or under the terms of any subsequent version published by the license
steward.
10.3. Modified Versions
If you create software not governed by this License, and you want to
create a new license for such software, you may create and use a
modified version of this License if you rename the license and remove
any references to the name of the license steward (except to note that
such modified license differs from this License).
10.4. Distributing Source Code Form that is Incompatible With Secondary
Licenses If You choose to distribute Source Code Form that is
Incompatible With Secondary Licenses under the terms of this version of
the License, the notice described in Exhibit B of this License must be
attached.
Exhibit A - Source Code Form License Notice
This Source Code Form is subject to the
terms of the Mozilla Public License, v.
2.0. If a copy of the MPL was not
distributed with this file, You can
obtain one at
http://mozilla.org/MPL/2.0/.
If it is not possible or desirable to put the notice in a particular file,
then You may include the notice in a location (such as a LICENSE file in a
relevant directory) where a recipient would be likely to look for such a
notice.
You may add additional accurate notices of copyright ownership.
Exhibit B - "Incompatible With Secondary Licenses" Notice
This Source Code Form is "Incompatible
With Secondary Licenses", as defined by
the Mozilla Public License, v. 2.0.

1
vendor/github.com/anacrolix/utp/NOTES generated vendored Normal file
View File

@@ -0,0 +1 @@
* Perhaps state packets should be sent when the wnd_size would change because user-code has made Reads from the read buffer. Otherwise if the receive window size was advertised as zero, we might never receive a packet or send a state packet again.

17
vendor/github.com/anacrolix/utp/README.md generated vendored Normal file
View File

@@ -0,0 +1,17 @@
# utp
[![GoDoc](https://godoc.org/github.com/anacrolix/utp?status.svg)](https://godoc.org/github.com/anacrolix/utp)
[![CircleCI](https://circleci.com/gh/anacrolix/utp.svg?style=shield)](https://circleci.com/gh/anacrolix/utp)
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.

15
vendor/github.com/anacrolix/utp/addr.go generated vendored Normal file
View File

@@ -0,0 +1,15 @@
package utp
import "net"
type addr struct {
socket net.Addr
}
func (me addr) Network() string {
return "utp/" + me.socket.Network()
}
func (me addr) String() string {
return me.socket.String()
}

618
vendor/github.com/anacrolix/utp/conn.go generated vendored Normal file
View File

@@ -0,0 +1,618 @@
package utp
import (
"errors"
"fmt"
"io"
"log"
"net"
"time"
"github.com/anacrolix/missinggo"
)
// Conn is a uTP stream and implements net.Conn. It owned by a Socket, which
// handles dispatching packets to and from Conns.
type Conn struct {
recv_id, send_id uint16
seq_nr, ack_nr uint16
lastAck uint16
lastTimeDiff uint32
peerWndSize uint32
cur_window uint32
connKey connKey
// Data waiting to be Read.
readBuf []byte
readBufNotEmpty missinggo.Event
socket *Socket
remoteSocketAddr net.Addr
// The uTP timestamp.
startTimestamp uint32
// When the conn was allocated.
created time.Time
synAcked bool // Syn is acked by the acceptor. Initiator also tracks it.
gotFin missinggo.Event
wroteFin missinggo.Event
err error
closed missinggo.Event
destroyed missinggo.Event
canWrite missinggo.Event
unackedSends []*send
// Inbound payloads, the first is ack_nr+1.
inbound []recv
inboundWnd int
connDeadlines
latencies []time.Duration
// We need to send state packet.
pendingSendState bool
sendPendingSendSendStateTimer *time.Timer
// Send state is being delayed until sendStateTimer fires, which may have
// been set at the beginning of a batch of received packets.
sendPendingSendStateTimerActive bool
// This timer fires when no packet has been received for a period.
packetReadTimeoutTimer *time.Timer
}
var (
_ net.Conn = &Conn{}
)
func (c *Conn) age() time.Duration {
return time.Since(c.created)
}
func (c *Conn) timestamp() uint32 {
return nowTimestamp() - c.startTimestamp
}
func (c *Conn) sendPendingSendStateTimerCallback() {
mu.Lock()
defer mu.Unlock()
c.sendPendingSendStateTimerActive = false
c.sendPendingSendSendStateTimer.Stop()
c.sendPendingState()
}
// Send a state packet, if one is needed.
func (c *Conn) sendPendingState() {
if c.destroyed.IsSet() {
c.sendReset()
} else {
c.sendState()
}
}
// So far as the spec makes clear, this is how many more, as-yet-unacked bytes
// we can fit into our receive buffers.
func (c *Conn) wndSize() uint32 {
if len(c.readBuf)+c.inboundWnd > readBufferLen {
return 0
}
return uint32(readBufferLen - len(c.readBuf) - c.inboundWnd)
}
func (c *Conn) makePacket(_type st, connID, seqNr uint16, payload []byte) (p []byte) {
var selAck selectiveAckBitmask
for i := 1; i < len(c.inbound); i++ {
if c.inbound[i].seen {
selAck.SetBit(i - 1)
}
}
h := header{
Type: _type,
Version: 1,
ConnID: connID,
SeqNr: seqNr,
AckNr: c.ack_nr,
WndSize: c.wndSize(),
Timestamp: c.timestamp(),
TimestampDiff: c.lastTimeDiff,
}
if len(selAck.Bytes) != 0 {
// The spec requires the number of bytes for a selective ACK to be at
// least 4, and a multiple of 4.
if len(selAck.Bytes)%4 != 0 {
panic(len(selAck.Bytes))
}
h.Extensions = append(h.Extensions, extensionField{
Type: extensionTypeSelectiveAck,
Bytes: selAck.Bytes,
})
}
p = sendBufferPool.Get().([]byte)[:0:minMTU]
n := h.Marshal(p)
p = p[:n]
// Extension headers are currently fixed in size.
if n > maxHeaderSize {
panic("header has unexpected size")
}
p = append(p, payload...)
return
}
// Send the given payload with an up to date header.
func (c *Conn) send(_type st, connID uint16, payload []byte, seqNr uint16) (err error) {
p := c.makePacket(_type, connID, seqNr, payload)
n1, err := c.socket.writeTo(p, c.remoteSocketAddr)
sendBufferPool.Put(p[:0:minMTU])
if err != nil {
return
}
if n1 != len(p) {
panic(n1)
}
if c.unpendSendState() && _type != stState {
// We needed to send a state packet, but this packet suppresses that
// need.
unsentStatePackets.Add(1)
}
return
}
func (c *Conn) unpendSendState() (wasPending bool) {
wasPending = c.pendingSendState
c.pendingSendState = false
c.sendPendingSendSendStateTimer.Stop()
c.sendPendingSendStateTimerActive = false
return
}
func (c *Conn) pendSendState() {
if c.pendingSendState {
// A state packet is pending but hasn't been sent, and we want to send
// another.
unsentStatePackets.Add(1)
}
c.pendingSendState = true
if !c.sendPendingSendStateTimerActive {
c.sendPendingSendSendStateTimer.Reset(pendingSendStateDelay)
c.sendPendingSendStateTimerActive = true
}
}
func (me *Conn) writeSyn() {
me.write(stSyn, me.recv_id, nil, me.seq_nr)
return
}
func (c *Conn) write(_type st, connID uint16, payload []byte, seqNr uint16) (n int, err error) {
switch _type {
case stSyn, stFin, stData:
default:
panic(_type)
}
if c.wroteFin.IsSet() {
panic("can't write after fin")
}
if len(payload) > maxPayloadSize {
payload = payload[:maxPayloadSize]
}
err = c.send(_type, connID, payload, seqNr)
if err != nil {
c.destroy(fmt.Errorf("error sending packet: %s", err))
return
}
n = len(payload)
// Copy payload so caller to write can continue to use the buffer.
if payload != nil {
payload = append(sendBufferPool.Get().([]byte)[:0:minMTU], payload...)
}
send := &send{
payloadSize: uint32(len(payload)),
started: missinggo.MonotonicNow(),
_type: _type,
connID: connID,
payload: payload,
seqNr: seqNr,
conn: c,
}
send.resendTimer = time.AfterFunc(c.resendTimeout(), send.timeoutResend)
c.unackedSends = append(c.unackedSends, send)
c.cur_window += send.payloadSize
c.updateCanWrite()
c.seq_nr++
return
}
// TODO: Introduce a minimum latency.
func (c *Conn) latency() (ret time.Duration) {
if len(c.latencies) == 0 {
return initialLatency
}
for _, l := range c.latencies {
ret += l
}
ret = (ret + time.Duration(len(c.latencies)) - 1) / time.Duration(len(c.latencies))
return
}
func (c *Conn) sendState() {
c.send(stState, c.send_id, nil, c.seq_nr)
sentStatePackets.Add(1)
}
func (c *Conn) sendReset() {
c.send(stReset, c.send_id, nil, c.seq_nr)
}
func (c *Conn) addLatency(l time.Duration) {
c.latencies = append(c.latencies, l)
if len(c.latencies) > 10 {
c.latencies = c.latencies[len(c.latencies)-10:]
}
}
// Ack our send with the given sequence number.
func (c *Conn) ack(nr uint16) {
if !seqLess(c.lastAck, nr) {
// Already acked.
return
}
i := nr - c.lastAck - 1
if int(i) >= len(c.unackedSends) {
// Remote has acknowledged receipt of packets we haven't even sent.
acksReceivedAheadOfSyn.Add(1)
// log.Printf("got ack ahead of syn (%x > %x)", nr, c.seq_nr-1)
return
}
s := c.unackedSends[i]
latency, first := s.Ack()
if first {
c.cur_window -= s.payloadSize
c.updateCanWrite()
c.addLatency(latency)
}
// Trim sends that aren't needed anymore.
for len(c.unackedSends) != 0 {
if !c.unackedSends[0].acked.IsSet() {
// Can't trim unacked sends any further.
return
}
// Trim the front of the unacked sends.
c.unackedSends = c.unackedSends[1:]
c.updateCanWrite()
c.lastAck++
}
}
func (c *Conn) ackTo(nr uint16) {
if !seqLess(nr, c.seq_nr) {
return
}
for seqLess(c.lastAck, nr) {
c.ack(c.lastAck + 1)
}
}
// Return the send state for the sequence number. Returns nil if there's no
// outstanding send for that sequence number.
func (c *Conn) seqSend(seqNr uint16) *send {
if !seqLess(c.lastAck, seqNr) {
// Presumably already acked.
return nil
}
i := int(seqNr - c.lastAck - 1)
if i >= len(c.unackedSends) {
// No such send.
return nil
}
return c.unackedSends[i]
}
func (c *Conn) resendTimeout() time.Duration {
l := c.latency()
ret := missinggo.JitterDuration(3*l, l)
return ret
}
func (c *Conn) ackSkipped(seqNr uint16) {
send := c.seqSend(seqNr)
if send == nil {
return
}
send.acksSkipped++
if send.acked.IsSet() {
return
}
switch send.acksSkipped {
case 3, 60:
ackSkippedResends.Add(1)
send.resend()
send.resendTimer.Reset(c.resendTimeout() * time.Duration(send.numResends))
default:
}
}
// Handle a packet destined for this connection.
func (c *Conn) receivePacket(h header, payload []byte) {
c.packetReadTimeoutTimer.Reset(packetReadTimeout)
c.processDelivery(h, payload)
}
func (c *Conn) receivePacketTimeoutCallback() {
mu.Lock()
c.destroy(errors.New("no packet read timeout"))
mu.Unlock()
}
func (c *Conn) lazyDestroy() {
if c.wroteFin.IsSet() && len(c.unackedSends) <= 1 && (c.gotFin.IsSet() || c.closed.IsSet()) {
c.destroy(errors.New("lazily destroyed"))
}
}
func (c *Conn) processDelivery(h header, payload []byte) {
deliveriesProcessed.Add(1)
defer c.lazyDestroy()
c.assertHeader(h)
c.peerWndSize = h.WndSize
c.applyAcks(h)
if h.Timestamp == 0 {
c.lastTimeDiff = 0
} else {
c.lastTimeDiff = c.timestamp() - h.Timestamp
}
if h.Type == stReset {
c.destroy(errors.New("peer reset"))
return
}
if !c.synAcked {
if h.Type != stState {
return
}
c.synAcked = true
c.updateCanWrite()
c.ack_nr = h.SeqNr - 1
return
}
if h.Type == stState {
return
}
// Even if we didn't need or want this packet, we need to inform the peer
// what our state is, in case they missed something.
c.pendSendState()
if !seqLess(c.ack_nr, h.SeqNr) {
// Already received this packet.
return
}
inboundIndex := int(h.SeqNr - c.ack_nr - 1)
if inboundIndex < len(c.inbound) && c.inbound[inboundIndex].seen {
// Already received this packet.
return
}
// Derived from running in production:
// grep -oP '(?<=packet out of order, index=)\d+' log | sort -n | uniq -c
// 64 should correspond to 8 bytes of selective ack.
if inboundIndex >= maxUnackedInbound {
// Discard packet too far ahead.
if logLevel >= 1 {
log.Printf("received packet from %s %d ahead of next seqnr (%x > %x)", c.remoteSocketAddr, inboundIndex, h.SeqNr, c.ack_nr+1)
}
return
}
// Extend inbound so the new packet has a place.
for inboundIndex >= len(c.inbound) {
c.inbound = append(c.inbound, recv{})
}
c.inbound[inboundIndex] = recv{true, payload, h.Type}
c.inboundWnd += len(payload)
c.processInbound()
}
func (c *Conn) applyAcks(h header) {
c.ackTo(h.AckNr)
for _, ext := range h.Extensions {
switch ext.Type {
case extensionTypeSelectiveAck:
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)
// log.Printf("selectively acked %d", nr)
c.ack(nr)
} else {
c.ackSkipped(h.AckNr + 2 + uint16(i))
}
}
}
}
}
func (c *Conn) assertHeader(h header) {
if h.Type == stSyn {
if h.ConnID != c.send_id {
panic(fmt.Sprintf("%d != %d", h.ConnID, c.send_id))
}
} else {
if h.ConnID != c.recv_id {
panic("erroneous delivery")
}
}
}
func (c *Conn) updateReadBufNotEmpty() {
c.readBufNotEmpty.SetBool(len(c.readBuf) != 0)
}
func (c *Conn) processInbound() {
// Consume consecutive next packets.
for !c.gotFin.IsSet() && len(c.inbound) > 0 && c.inbound[0].seen && len(c.readBuf) < readBufferLen {
c.ack_nr++
p := c.inbound[0]
c.inbound = c.inbound[1:]
c.inboundWnd -= len(p.data)
c.readBuf = append(c.readBuf, p.data...)
c.updateReadBufNotEmpty()
if p.Type == stFin {
c.gotFin.Set()
}
}
}
func (c *Conn) waitAck(seq uint16) {
send := c.seqSend(seq)
if send == nil {
return
}
missinggo.WaitEvents(&mu, &send.acked, &c.destroyed)
return
}
// Waits for sent SYN to be ACKed. Returns any errors.
func (c *Conn) recvSynAck() (err error) {
mu.Lock()
defer mu.Unlock()
c.waitAck(1)
if c.err != nil {
err = c.err
}
c.synAcked = true
c.updateCanWrite()
return err
}
func (c *Conn) writeFin() {
if c.wroteFin.IsSet() {
return
}
c.write(stFin, c.send_id, nil, c.seq_nr)
c.wroteFin.Set()
return
}
func (c *Conn) destroy(reason error) {
c.destroyed.Set()
if c.err == nil {
c.err = reason
}
c.detach()
}
func (c *Conn) closeNow() (err error) {
c.closed.Set()
c.writeFin()
c.destroy(errors.New("destroyed"))
return
}
func (c *Conn) Close() (err error) {
mu.Lock()
defer mu.Unlock()
c.closed.Set()
c.writeFin()
c.lazyDestroy()
return
}
func (c *Conn) LocalAddr() net.Addr {
return addr{c.socket.Addr()}
}
func (c *Conn) Read(b []byte) (n int, err error) {
mu.Lock()
defer mu.Unlock()
for {
n = copy(b, c.readBuf)
c.readBuf = c.readBuf[n:]
c.updateReadBufNotEmpty()
if n != 0 {
// Inbound packets are backed up when the read buffer is too big.
c.processInbound()
return
}
if c.gotFin.IsSet() || c.closed.IsSet() {
err = io.EOF
return
}
if c.destroyed.IsSet() {
if c.err == nil {
panic("closed without receiving fin, and no error")
}
err = c.err
return
}
if c.connDeadlines.read.passed.IsSet() {
err = errTimeout
return
}
missinggo.WaitEvents(&mu,
&c.gotFin,
&c.closed,
&c.destroyed,
&c.connDeadlines.read.passed,
&c.readBufNotEmpty)
}
}
func (c *Conn) RemoteAddr() net.Addr {
return addr{c.remoteSocketAddr}
}
func (c *Conn) String() string {
return fmt.Sprintf("<UTPConn %s-%s (%d)>", c.LocalAddr(), c.RemoteAddr(), c.recv_id)
}
func (c *Conn) updateCanWrite() {
c.canWrite.SetBool(c.synAcked &&
len(c.unackedSends) < maxUnackedSends &&
c.cur_window <= c.peerWndSize)
}
func (c *Conn) Write(p []byte) (n int, err error) {
mu.Lock()
defer mu.Unlock()
for len(p) != 0 {
if c.wroteFin.IsSet() || c.closed.IsSet() {
err = errClosed
return
}
if c.destroyed.IsSet() {
err = c.err
return
}
if c.connDeadlines.write.passed.IsSet() {
err = errTimeout
return
}
// If peerWndSize is 0, we still want to send something, so don't
// block until we exceed it.
if c.canWrite.IsSet() {
var n1 int
n1, err = c.write(stData, c.send_id, p, c.seq_nr)
n += n1
if err != nil {
break
}
if n1 == 0 {
panic(len(p))
}
p = p[n1:]
continue
}
missinggo.WaitEvents(&mu,
&c.wroteFin,
&c.closed,
&c.destroyed,
&c.connDeadlines.write.passed,
&c.canWrite)
}
return
}
func (c *Conn) detach() {
s := c.socket
_, ok := s.conns[c.connKey]
if !ok {
return
}
delete(s.conns, c.connKey)
s.lazyDestroy()
}

71
vendor/github.com/anacrolix/utp/deadlines.go generated vendored Normal file
View File

@@ -0,0 +1,71 @@
package utp
import (
"time"
"github.com/anacrolix/missinggo"
)
type deadline struct {
t time.Time
passed missinggo.Event
timer *time.Timer
}
func (me *deadline) set(t time.Time) {
me.t = t
me.passed.Clear()
if me.timer != nil {
me.timer.Stop()
}
me.update()
}
func (me *deadline) update() {
if me.t.IsZero() {
return
}
if time.Now().Before(me.t) {
if me.timer == nil {
me.timer = time.AfterFunc(me.t.Sub(time.Now()), me.callback)
} else {
me.timer.Reset(me.t.Sub(time.Now()))
}
return
}
me.passed.Set()
}
func (me *deadline) callback() {
mu.Lock()
defer mu.Unlock()
me.update()
}
// This is embedded in Conn and Socket to provide deadline methods for
// net.Conn.
type connDeadlines struct {
read, write deadline
}
func (c *connDeadlines) SetDeadline(t time.Time) error {
mu.Lock()
defer mu.Unlock()
c.read.set(t)
c.write.set(t)
return nil
}
func (c *connDeadlines) SetReadDeadline(t time.Time) error {
mu.Lock()
defer mu.Unlock()
c.read.set(t)
return nil
}
func (c *connDeadlines) SetWriteDeadline(t time.Time) error {
mu.Lock()
defer mu.Unlock()
c.write.set(t)
return nil
}

19
vendor/github.com/anacrolix/utp/expvar.go generated vendored Normal file
View File

@@ -0,0 +1,19 @@
package utp
import "expvar"
var (
ackSkippedResends = expvar.NewInt("utpAckSkippedResends")
// Inbound packets processed by a Conn.
deliveriesProcessed = expvar.NewInt("utpDeliveriesProcessed")
sentStatePackets = expvar.NewInt("utpSentStatePackets")
acksReceivedAheadOfSyn = expvar.NewInt("utpAcksReceivedAheadOfSyn")
unexpectedPacketsRead = expvar.NewInt("utpUnexpectedPacketsRead")
// State packets that we managed not to send.
unsentStatePackets = expvar.NewInt("utpUnsentStatePackets")
unusedReads = expvar.NewInt("utpUnusedReads")
unusedReadsDropped = expvar.NewInt("utpUnusedReadsDropped")
largestReceivedUTPPacket int
largestReceivedUTPPacketExpvar = expvar.NewInt("utpLargestReceivedPacket")
)

135
vendor/github.com/anacrolix/utp/header.go generated vendored Normal file
View File

@@ -0,0 +1,135 @@
package utp
import (
"encoding/binary"
"errors"
"fmt"
)
const (
extensionTypeSelectiveAck = 1
)
type extensionField struct {
Type byte
Bytes []byte
}
type header struct {
Type st
Version int
ConnID uint16
Timestamp uint32
TimestampDiff uint32
WndSize uint32
SeqNr uint16
AckNr uint16
Extensions []extensionField
}
func unmarshalExtensions(_type byte, b []byte) (n int, ef []extensionField, err error) {
for _type != 0 {
if _type != extensionTypeSelectiveAck {
// An extension type that is not known to us. Generally we're
// unmarshalling an packet that isn't actually uTP but we don't
// yet know for sure until we try to deliver it.
// logonce.Stderr.Printf("utp extension %d", _type)
}
if len(b) < 2 || len(b) < int(b[1])+2 {
err = fmt.Errorf("buffer ends prematurely: %x", b)
return
}
ef = append(ef, extensionField{
Type: _type,
Bytes: append([]byte(nil), b[2:int(b[1])+2]...),
})
_type = b[0]
n += 2 + int(b[1])
b = b[2+int(b[1]):]
}
return
}
var errInvalidHeader = errors.New("invalid header")
func (h *header) Unmarshal(b []byte) (n int, err error) {
h.Type = st(b[0] >> 4)
h.Version = int(b[0] & 0xf)
if h.Type > stMax || h.Version != 1 {
err = errInvalidHeader
return
}
n, h.Extensions, err = unmarshalExtensions(b[1], b[20:])
if err != nil {
return
}
h.ConnID = binary.BigEndian.Uint16(b[2:4])
h.Timestamp = binary.BigEndian.Uint32(b[4:8])
h.TimestampDiff = binary.BigEndian.Uint32(b[8:12])
h.WndSize = binary.BigEndian.Uint32(b[12:16])
h.SeqNr = binary.BigEndian.Uint16(b[16:18])
h.AckNr = binary.BigEndian.Uint16(b[18:20])
n += 20
return
}
func (h *header) Marshal(p []byte) (n int) {
n = 20 + func() (ret int) {
for _, ext := range h.Extensions {
ret += 2 + len(ext.Bytes)
}
return
}()
p = p[:n]
p[0] = byte(h.Type<<4 | 1)
binary.BigEndian.PutUint16(p[2:4], h.ConnID)
binary.BigEndian.PutUint32(p[4:8], h.Timestamp)
binary.BigEndian.PutUint32(p[8:12], h.TimestampDiff)
binary.BigEndian.PutUint32(p[12:16], h.WndSize)
binary.BigEndian.PutUint16(p[16:18], h.SeqNr)
binary.BigEndian.PutUint16(p[18:20], h.AckNr)
// Pointer to the last type field so the next extension can set it.
_type := &p[1]
// We're done with the basic header.
p = p[20:]
for _, ext := range h.Extensions {
*_type = ext.Type
// The next extension's type will go here.
_type = &p[0]
p[1] = uint8(len(ext.Bytes))
if int(p[1]) != copy(p[2:], ext.Bytes) {
panic("unexpected extension length")
}
p = p[2+len(ext.Bytes):]
}
*_type = 0
if len(p) != 0 {
panic("header length changed")
}
return
}
type selectiveAckBitmask struct {
Bytes []byte
}
func (me *selectiveAckBitmask) expandBytesForBit(index int) {
minLen := (3 + (index / 8) + 1) / 4 * 4
for len(me.Bytes) < minLen {
me.Bytes = append(me.Bytes, 0)
}
}
func (me *selectiveAckBitmask) NumBits() int {
return len(me.Bytes) * 8
}
func (me *selectiveAckBitmask) SetBit(index int) {
me.expandBytesForBit(index)
me.Bytes[index/8] |= 1 << uint(index%8)
}
func (me *selectiveAckBitmask) BitIsSet(index int) bool {
return me.Bytes[index/8]>>uint(index%8)&1 == 1
}

11
vendor/github.com/anacrolix/utp/nop.go generated vendored Normal file
View File

@@ -0,0 +1,11 @@
package utp
import "net"
type packetConnNopCloser struct {
net.PacketConn
}
func (packetConnNopCloser) Close() error {
return nil
}

68
vendor/github.com/anacrolix/utp/pingpong generated vendored Executable file
View File

@@ -0,0 +1,68 @@
# This shell script uses nc-like executables to send and receive the file at
# $1, and prints the checksums. 3 such executables are
# github.com/h2so5/utp/ucat, invoked as h2so5-ucat, libutp-ucat, which is the
# ucat or ucat-static generated by the C++ libutp, and lastly, ./cmd/ucat from
# this repository. A good file in my experiments is no more than a few 100MB,
# or you'll be waiting a while.
set -eu
# set -x
# Passed to invocations of godo for package ./cmd/ucat.
#GODOFLAGS=-race
#export GO_UTP_PACKET_DROP=0.1
export GOPPROF=
# Invokes the implementation to test against. If there's an arg, then it's
# expected to listen.
function other_ucat() {
if [[ $# != 0 ]]; then
libutp-ucat -l -p "$port"
# h2so5-ucat -l :"$port"
else
libutp-ucat localhost "$port"
# h2so5-ucat localhost:"$port"
fi
}
function md5cmd() {
(which md5sum > /dev/null && md5sum "$@") || (which md5 > /dev/null && md5 "$@") || md5sum "$@"
}
# Check what the correct result is.
md5cmd "$1"
rate() {
pv -a -W -b
}
port=4000
echo 'utp->other_ucat'
# Send from this uTP implementation to another client.
other_ucat -l | rate | md5cmd &
# sleep 1
godo ${GODOFLAGS-} ./cmd/ucat localhost "$port" < "$1"
wait
echo 'other_ucat->utp'
# Send from the other implementation, to this one.
GO_UTP_LOGGING=0 godo ${GODOFLAGS-} ./cmd/ucat -l -p "$port" | rate | md5cmd &
# Never receive from h2so5's ucat without a small sleep first. Don't know why.
sleep 1
other_ucat < "$1"
wait
echo 'libutp->libutp'
libutp-ucat -l -p "$port" | rate | md5cmd &
libutp-ucat localhost "$port" < "$1"
wait
echo 'utp->utp'
godo ./cmd/ucat -l -p "$port" | rate | md5cmd &
sleep 1
godo ./cmd/ucat localhost "$port" < "$1"
wait
# Now check the hashes match (yes you).

72
vendor/github.com/anacrolix/utp/send.go generated vendored Normal file
View File

@@ -0,0 +1,72 @@
package utp
import (
"log"
"time"
"github.com/anacrolix/missinggo"
)
type send struct {
acked missinggo.Event
payloadSize uint32
started missinggo.MonotonicTime
_type st
connID uint16
payload []byte
seqNr uint16
conn *Conn
acksSkipped int
resendTimer *time.Timer
numResends int
}
// first is true if this is the first time the send is acked. latency is
// calculated for the first ack.
func (s *send) Ack() (latency time.Duration, first bool) {
first = !s.acked.IsSet()
if first {
latency = missinggo.MonotonicSince(s.started)
}
if s.payload != nil {
sendBufferPool.Put(s.payload[:0:minMTU])
s.payload = nil
}
s.acked.Set()
if s.resendTimer != nil {
s.resendTimer.Stop()
s.resendTimer = nil
}
return
}
func (s *send) timedOut() {
s.conn.destroy(errAckTimeout)
}
func (s *send) timeoutResend() {
mu.Lock()
defer mu.Unlock()
if missinggo.MonotonicSince(s.started) >= writeTimeout {
s.timedOut()
return
}
if s.acked.IsSet() || s.conn.destroyed.IsSet() {
return
}
rt := s.conn.resendTimeout()
s.resend()
s.numResends++
s.resendTimer.Reset(rt * time.Duration(s.numResends))
}
func (s *send) resend() {
if s.acked.IsSet() {
return
}
err := s.conn.send(s._type, s.connID, s.payload, s.seqNr)
if err != nil {
log.Printf("error resending packet: %s", err)
}
}

597
vendor/github.com/anacrolix/utp/socket.go generated vendored Normal file
View File

@@ -0,0 +1,597 @@
package utp
import (
"context"
"errors"
"io"
"log"
"math/rand"
"net"
"sync"
"time"
"github.com/anacrolix/missinggo"
"github.com/anacrolix/missinggo/inproc"
"github.com/anacrolix/missinggo/pproffd"
)
var (
_ net.Listener = &Socket{}
_ net.PacketConn = &Socket{}
)
// Uniquely identifies any uTP connection on top of the underlying packet
// stream.
type connKey struct {
remoteAddr resolvedAddrStr
connID uint16
}
// A Socket wraps a net.PacketConn, diverting uTP packets to its child uTP
// Conns.
type Socket struct {
pc net.PacketConn
conns map[connKey]*Conn
backlogNotEmpty missinggo.Event
backlog map[syn]struct{}
closed missinggo.Event
destroyed missinggo.Event
wgReadWrite sync.WaitGroup
unusedReads chan read
connDeadlines
// If a read error occurs on the underlying net.PacketConn, it is put
// here. This is because reading is done in its own goroutine to dispatch
// to uTP Conns.
ReadErr error
}
func listenPacket(network, addr string) (pc net.PacketConn, err error) {
if network == "inproc" {
return inproc.ListenPacket(network, addr)
}
return net.ListenPacket(network, addr)
}
// NewSocket creates a net.PacketConn with the given network and address, and
// returns a Socket dispatching on it.
func NewSocket(network, addr string) (s *Socket, err error) {
if network == "" {
network = "udp"
}
pc, err := listenPacket(network, addr)
if err != nil {
return
}
return NewSocketFromPacketConn(pc)
}
// Create a Socket, using the provided net.PacketConn. If you want to retain
// use of the net.PacketConn after the Socket closes it, override the
// net.PacketConn's Close method, or use NetSocketFromPacketConnNoClose.
func NewSocketFromPacketConn(pc net.PacketConn) (s *Socket, err error) {
s = &Socket{
backlog: make(map[syn]struct{}, backlog),
pc: pc,
unusedReads: make(chan read, 100),
wgReadWrite: sync.WaitGroup{},
}
mu.Lock()
sockets[s] = struct{}{}
mu.Unlock()
go s.reader()
return
}
// Create a Socket using the provided PacketConn, that doesn't close the
// PacketConn when the Socket is closed.
func NewSocketFromPacketConnNoClose(pc net.PacketConn) (s *Socket, err error) {
return NewSocketFromPacketConn(packetConnNopCloser{pc})
}
func (s *Socket) unusedRead(read read) {
unusedReads.Add(1)
select {
case s.unusedReads <- read:
default:
// Drop the packet.
unusedReadsDropped.Add(1)
}
}
func (s *Socket) strNetAddr(str string) (a net.Addr) {
var err error
switch n := s.network(); n {
case "udp":
a, err = net.ResolveUDPAddr(n, str)
case "inproc":
a, err = inproc.ResolveAddr(n, str)
default:
panic(n)
}
if err != nil {
panic(err)
}
return
}
func (s *Socket) pushBacklog(syn syn) {
if _, ok := s.backlog[syn]; ok {
return
}
// Pop a pseudo-random syn to make room. TODO: Use missinggo/orderedmap,
// coz that's what is wanted here.
for k := range s.backlog {
if len(s.backlog) < backlog {
break
}
delete(s.backlog, k)
// A syn is sent on the remote's recv_id, so this is where we can send
// the reset.
s.reset(s.strNetAddr(k.addr), k.seq_nr, k.conn_id)
}
s.backlog[syn] = struct{}{}
s.backlogChanged()
}
func (s *Socket) reader() {
mu.Lock()
defer mu.Unlock()
defer s.destroy()
var b [maxRecvSize]byte
for {
s.wgReadWrite.Add(1)
mu.Unlock()
n, addr, err := s.pc.ReadFrom(b[:])
s.wgReadWrite.Done()
mu.Lock()
if s.destroyed.IsSet() {
return
}
if err != nil {
log.Printf("error reading Socket PacketConn: %s", err)
s.ReadErr = err
return
}
s.handleReceivedPacket(read{
append([]byte(nil), b[:n]...),
addr,
})
}
}
func receivedUTPPacketSize(n int) {
if n > largestReceivedUTPPacket {
largestReceivedUTPPacket = n
largestReceivedUTPPacketExpvar.Set(int64(n))
}
}
func (s *Socket) connForRead(h header, from net.Addr) (c *Conn, ok bool) {
c, ok = s.conns[connKey{
resolvedAddrStr(from.String()),
func() uint16 {
if h.Type == stSyn {
// SYNs have a ConnID one lower than the eventual recvID, and we index
// the connections with that, so use it for the lookup.
return h.ConnID + 1
} else {
return h.ConnID
}
}(),
}]
return
}
func (s *Socket) handlePacketReceivedForEstablishedConn(h header, from net.Addr, data []byte, c *Conn) {
if h.Type == stSyn {
if h.ConnID == c.send_id-2 {
// This is a SYN for connection that cannot exist locally. The
// connection the remote wants to establish here with the proposed
// recv_id, already has an existing connection that was dialled
// *out* from this socket, which is why the send_id is 1 higher,
// rather than 1 lower than the recv_id.
log.Print("resetting conflicting syn")
s.reset(from, h.SeqNr, h.ConnID)
return
} else if h.ConnID != c.send_id {
panic("bad assumption")
}
}
c.receivePacket(h, data)
}
func (s *Socket) handleReceivedPacket(p read) {
if len(p.data) < 20 {
s.unusedRead(p)
return
}
var h header
hEnd, err := h.Unmarshal(p.data)
if err != nil || h.Type > stMax || h.Version != 1 {
s.unusedRead(p)
return
}
if c, ok := s.connForRead(h, p.from); ok {
receivedUTPPacketSize(len(p.data))
s.handlePacketReceivedForEstablishedConn(h, p.from, p.data[hEnd:], c)
return
}
// Packet doesn't belong to an existing connection.
switch h.Type {
case stSyn:
s.pushBacklog(syn{
seq_nr: h.SeqNr,
conn_id: h.ConnID,
addr: p.from.String(),
})
return
case stReset:
// Could be a late arriving packet for a Conn we're already done with.
// If it was for an existing connection, we would have handled it
// earlier.
default:
unexpectedPacketsRead.Add(1)
// This is an unexpected packet. We'll send a reset, but also pass it
// on. I don't think you can reset on the received packets ConnID if
// it isn't a SYN, as the send_id will differ in this case.
s.reset(p.from, h.SeqNr, h.ConnID)
// Connection initiated by remote.
s.reset(p.from, h.SeqNr, h.ConnID-1)
// Connection initiated locally.
s.reset(p.from, h.SeqNr, h.ConnID+1)
}
s.unusedRead(p)
}
// Send a reset in response to a packet with the given header.
func (s *Socket) reset(addr net.Addr, ackNr, connId uint16) {
b := make([]byte, 0, maxHeaderSize)
h := header{
Type: stReset,
Version: 1,
ConnID: connId,
AckNr: ackNr,
}
b = b[:h.Marshal(b)]
go s.writeTo(b, addr)
}
// Return a recv_id that should be free. Handling the case where it isn't is
// deferred to a more appropriate function.
func (s *Socket) newConnID(remoteAddr resolvedAddrStr) (id uint16) {
// Rather than use math.Rand, which requires generating all the IDs up
// front and allocating a slice, we do it on the stack, generating the IDs
// only as required. To do this, we use the fact that the array is
// default-initialized. IDs that are 0, are actually their index in the
// array. IDs that are non-zero, are +1 from their intended ID.
var idsBack [0x10000]int
ids := idsBack[:]
for len(ids) != 0 {
// Pick the next ID from the untried ids.
i := rand.Intn(len(ids))
id = uint16(ids[i])
// If it's zero, then treat it as though the index i was the ID.
// Otherwise the value we get is the ID+1.
if id == 0 {
id = uint16(i)
} else {
id--
}
// Check there's no connection using this ID for its recv_id...
_, ok1 := s.conns[connKey{remoteAddr, id}]
// and if we're connecting to our own Socket, that there isn't a Conn
// already receiving on what will correspond to our send_id. Note that
// we just assume that we could be connecting to our own Socket. This
// will halve the available connection IDs to each distinct remote
// address. Presumably that's ~0x8000, down from ~0x10000.
_, ok2 := s.conns[connKey{remoteAddr, id + 1}]
_, ok4 := s.conns[connKey{remoteAddr, id - 1}]
if !ok1 && !ok2 && !ok4 {
return
}
// The set of possible IDs is shrinking. The highest one will be lost, so
// it's moved to the location of the one we just tried.
ids[i] = len(ids) // Conveniently already +1.
// And shrink.
ids = ids[:len(ids)-1]
}
return
}
var (
zeroipv4 = net.ParseIP("0.0.0.0")
zeroipv6 = net.ParseIP("::")
ipv4lo = mustResolveUDP("127.0.0.1")
ipv6lo = mustResolveUDP("::1")
)
func mustResolveUDP(addr string) net.IP {
u, err := net.ResolveIPAddr("ip", addr)
if err != nil {
panic(err)
}
return u.IP
}
func realRemoteAddr(addr net.Addr) net.Addr {
udpAddr, ok := addr.(*net.UDPAddr)
if ok {
if udpAddr.IP.Equal(zeroipv4) {
udpAddr.IP = ipv4lo
}
if udpAddr.IP.Equal(zeroipv6) {
udpAddr.IP = ipv6lo
}
}
return addr
}
func (s *Socket) newConn(addr net.Addr) (c *Conn) {
addr = realRemoteAddr(addr)
c = &Conn{
socket: s,
remoteSocketAddr: addr,
created: time.Now(),
}
c.sendPendingSendSendStateTimer = missinggo.StoppedFuncTimer(c.sendPendingSendStateTimerCallback)
c.packetReadTimeoutTimer = time.AfterFunc(packetReadTimeout, c.receivePacketTimeoutCallback)
return
}
func (s *Socket) Dial(addr string) (net.Conn, error) {
return s.DialContext(context.Background(), "", addr)
}
func (s *Socket) resolveAddr(network, addr string) (net.Addr, error) {
n := s.network()
if network != "" {
n = network
}
if n == "inproc" {
return inproc.ResolveAddr(n, addr)
}
return net.ResolveUDPAddr(n, addr)
}
func (s *Socket) network() string {
return s.pc.LocalAddr().Network()
}
func (s *Socket) startOutboundConn(addr net.Addr) (c *Conn, err error) {
mu.Lock()
defer mu.Unlock()
c = s.newConn(addr)
c.recv_id = s.newConnID(resolvedAddrStr(c.RemoteAddr().String()))
c.send_id = c.recv_id + 1
if logLevel >= 1 {
log.Printf("dial registering addr: %s", c.RemoteAddr().String())
}
if !s.registerConn(c.recv_id, resolvedAddrStr(c.RemoteAddr().String()), c) {
err = errors.New("couldn't register new connection")
log.Println(c.recv_id, c.RemoteAddr().String())
for k, c := range s.conns {
log.Println(k, c, c.age())
}
log.Printf("that's %d connections", len(s.conns))
}
if err != nil {
return
}
c.seq_nr = 1
c.writeSyn()
return
}
func (s *Socket) DialContext(ctx context.Context, network, addr string) (nc net.Conn, err error) {
netAddr, err := s.resolveAddr(network, addr)
if err != nil {
return
}
c, err := s.startOutboundConn(netAddr)
if err != nil {
return
}
connErr := make(chan error, 1)
go func() {
connErr <- c.recvSynAck()
}()
select {
case err = <-connErr:
case <-ctx.Done():
err = ctx.Err()
}
if err != nil {
mu.Lock()
c.destroy(errors.New("dial timeout"))
mu.Unlock()
return
}
mu.Lock()
c.updateCanWrite()
mu.Unlock()
nc = pproffd.WrapNetConn(c)
return
}
func (me *Socket) writeTo(b []byte, addr net.Addr) (n int, err error) {
apdc := artificialPacketDropChance
if apdc != 0 {
if rand.Float64() < apdc {
n = len(b)
return
}
}
n, err = me.pc.WriteTo(b, addr)
return
}
// Returns true if the connection was newly registered, false otherwise.
func (s *Socket) registerConn(recvID uint16, remoteAddr resolvedAddrStr, c *Conn) bool {
if s.conns == nil {
s.conns = make(map[connKey]*Conn)
}
key := connKey{remoteAddr, recvID}
if _, ok := s.conns[key]; ok {
return false
}
c.connKey = key
s.conns[key] = c
return true
}
func (s *Socket) backlogChanged() {
if len(s.backlog) != 0 {
s.backlogNotEmpty.Set()
} else {
s.backlogNotEmpty.Clear()
}
}
func (s *Socket) nextSyn() (syn syn, err error) {
for {
missinggo.WaitEvents(&mu, &s.closed, &s.backlogNotEmpty, &s.destroyed)
if s.closed.IsSet() {
err = errClosed
return
}
if s.destroyed.IsSet() {
err = s.ReadErr
return
}
for k := range s.backlog {
syn = k
delete(s.backlog, k)
s.backlogChanged()
return
}
}
}
// ACK a SYN, and return a new Conn for it. ok is false if the SYN is bad, and
// the Conn invalid.
func (s *Socket) ackSyn(syn syn) (c *Conn, ok bool) {
c = s.newConn(s.strNetAddr(syn.addr))
c.send_id = syn.conn_id
c.recv_id = c.send_id + 1
c.seq_nr = uint16(rand.Int())
c.lastAck = c.seq_nr - 1
c.ack_nr = syn.seq_nr
c.synAcked = true
c.updateCanWrite()
if !s.registerConn(c.recv_id, resolvedAddrStr(syn.addr), c) {
// SYN that triggered this accept duplicates existing connection.
// Ack again in case the SYN was a resend.
c = s.conns[connKey{resolvedAddrStr(syn.addr), c.recv_id}]
if c.send_id != syn.conn_id {
panic(":|")
}
c.sendState()
return
}
c.sendState()
ok = true
return
}
// Accept and return a new uTP connection.
func (s *Socket) Accept() (net.Conn, error) {
mu.Lock()
defer mu.Unlock()
for {
syn, err := s.nextSyn()
if err != nil {
return nil, err
}
c, ok := s.ackSyn(syn)
if ok {
c.updateCanWrite()
return c, nil
}
}
}
// The address we're listening on for new uTP connections.
func (s *Socket) Addr() net.Addr {
return s.pc.LocalAddr()
}
func (s *Socket) CloseNow() error {
mu.Lock()
defer mu.Unlock()
s.closed.Set()
for _, c := range s.conns {
c.closeNow()
}
s.destroy()
s.wgReadWrite.Wait()
return nil
}
func (s *Socket) Close() error {
mu.Lock()
defer mu.Unlock()
s.closed.Set()
s.lazyDestroy()
return nil
}
func (s *Socket) lazyDestroy() {
if len(s.conns) != 0 {
return
}
if !s.closed.IsSet() {
return
}
s.destroy()
}
func (s *Socket) destroy() {
delete(sockets, s)
s.destroyed.Set()
s.pc.Close()
for _, c := range s.conns {
c.destroy(errors.New("Socket destroyed"))
}
}
func (s *Socket) LocalAddr() net.Addr {
return s.pc.LocalAddr()
}
func (s *Socket) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
select {
case read, ok := <-s.unusedReads:
if !ok {
err = io.EOF
return
}
n = copy(p, read.data)
addr = read.from
return
case <-s.connDeadlines.read.passed.LockedChan(&mu):
err = errTimeout
return
}
}
func (s *Socket) WriteTo(b []byte, addr net.Addr) (n int, err error) {
mu.Lock()
if s.connDeadlines.write.passed.IsSet() {
err = errTimeout
}
s.wgReadWrite.Add(1)
defer s.wgReadWrite.Done()
mu.Unlock()
if err != nil {
return
}
return s.pc.WriteTo(b, addr)
}

24
vendor/github.com/anacrolix/utp/status.go generated vendored Normal file
View File

@@ -0,0 +1,24 @@
package utp
import (
"fmt"
"io"
)
func WriteStatus(w io.Writer) {
mu.RLock()
defer mu.RUnlock()
for s := range sockets {
writeSocketStatus(w, s)
fmt.Fprintf(w, "\n")
}
}
func writeSocketStatus(w io.Writer, s *Socket) {
fmt.Fprintf(w, "%s\n", s.pc.LocalAddr())
fmt.Fprintf(w, "%d attached conns\n", len(s.conns))
fmt.Fprintf(w, "backlog: %d\n", len(s.backlog))
fmt.Fprintf(w, "closed: %v\n", s.closed.IsSet())
fmt.Fprintf(w, "unused reads: %d\n", len(s.unusedReads))
fmt.Fprintf(w, "readerr: %v\n", s.ReadErr)
}

193
vendor/github.com/anacrolix/utp/utp.go generated vendored Normal file
View File

@@ -0,0 +1,193 @@
// 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. It allows using the underlying OS-level transport despite
// dispatching uTP on top to allow for example, shared socket use with DHT.
// Additionally, multiple uTP connections can share the same OS socket, to
// truly realize uTP's claim to be light on system and network switching
// resources.
//
// Socket is a wrapper of net.UDPConn, and performs dispatching of uTP packets
// to attached uTP Conns. Dial and Accept is done via Socket. Conn implements
// net.Conn over uTP, via aforementioned Socket.
package utp
import (
"context"
"errors"
"fmt"
"net"
"os"
"strconv"
"sync"
"time"
pprofsync "github.com/anacrolix/sync"
)
const (
// Maximum received SYNs that haven't been accepted. If more SYNs are
// received, a pseudo randomly selected SYN is replied to with a reset to
// make room.
backlog = 50
// IPv6 min MTU is 1280, -40 for IPv6 header, and ~8 for fragment header?
minMTU = 1438 // Why?
// uTP header of 20, +2 for the next extension, and an optional selective
// ACK.
maxHeaderSize = 20 + 2 + (((maxUnackedInbound+7)/8)+3)/4*4
maxPayloadSize = minMTU - maxHeaderSize
maxRecvSize = 0x2000
// Maximum out-of-order packets to buffer.
maxUnackedInbound = 256
maxUnackedSends = 256
readBufferLen = 1 << 20 // ~1MiB
// How long to wait before sending a state packet, after one is required.
// This prevents spamming a state packet for every packet received, and
// non-state packets that are being sent also fill the role.
pendingSendStateDelay = 500 * time.Microsecond
)
var (
sendBufferPool = sync.Pool{
New: func() interface{} { return make([]byte, minMTU) },
}
// This is the latency we assume on new connections. It should be higher
// than the latency we expect on most connections to prevent excessive
// resending to peers that take a long time to respond, before we've got a
// better idea of their actual latency.
initialLatency time.Duration
// If a write isn't acked within this period, destroy the connection.
writeTimeout time.Duration
// Assume the connection has been closed by the peer getting no packets of
// any kind for this time.
packetReadTimeout time.Duration
)
func setDefaultDurations() {
// An approximate upper bound for most connections across the world.
initialLatency = 400 * time.Millisecond
// Getting no reply for this period for a packet, we can probably rule out
// latency and client lag.
writeTimeout = 15 * time.Second
// Somewhere longer than the BitTorrent grace period (90-120s), and less
// than default TCP reset (4min).
packetReadTimeout = 2 * time.Minute
}
func init() {
setDefaultDurations()
}
// Strongly-type guarantee of resolved network address.
type resolvedAddrStr string
type read struct {
data []byte
from net.Addr
}
type syn struct {
seq_nr, conn_id uint16
// net.Addr.String() of a Socket's real net.PacketConn.
addr string
}
var (
mu pprofsync.RWMutex
sockets = map[*Socket]struct{}{}
logLevel = 0
artificialPacketDropChance = 0.0
)
func init() {
logLevel, _ = strconv.Atoi(os.Getenv("GO_UTP_LOGGING"))
fmt.Sscanf(os.Getenv("GO_UTP_PACKET_DROP"), "%f", &artificialPacketDropChance)
}
var (
errClosed = errors.New("closed")
errTimeout net.Error = timeoutError{"i/o timeout"}
errAckTimeout = timeoutError{"timed out waiting for ack"}
)
type timeoutError struct {
msg string
}
func (me timeoutError) Timeout() bool { return true }
func (me timeoutError) Error() string { return me.msg }
func (me timeoutError) Temporary() bool { return false }
type st int
func (me st) String() string {
switch me {
case stData:
return "stData"
case stFin:
return "stFin"
case stState:
return "stState"
case stReset:
return "stReset"
case stSyn:
return "stSyn"
default:
panic(fmt.Sprintf("%d", me))
}
}
const (
stData st = 0
stFin = 1
stState = 2
stReset = 3
stSyn = 4
// Used for validating packet headers.
stMax = stSyn
)
type recv struct {
seen bool
data []byte
Type st
}
// Attempt to connect to a remote uTP listener, creating a Socket just for
// this connection.
func Dial(addr string) (net.Conn, error) {
return DialContext(context.Background(), addr)
}
// Same as Dial with a timeout parameter. Creates a Socket just for the
// connection, which will be closed with the Conn is. To reuse another Socket,
// see Socket.Dial.
func DialContext(ctx context.Context, addr string) (nc net.Conn, err error) {
s, err := NewSocket("udp", ":0")
if err != nil {
return
}
defer s.Close()
return s.DialContext(ctx, "", addr)
}
// Listen creates listener Socket to accept incoming connections.
func Listen(laddr string) (net.Listener, error) {
return NewSocket("udp", laddr)
}
func nowTimestamp() uint32 {
return uint32(time.Now().UnixNano() / int64(time.Microsecond))
}
func seqLess(a, b uint16) bool {
if b < 0x8000 {
return a < b || a >= b-0x8000
} else {
return a < b && a >= b-0x8000
}
}