├── README.md ├── udt ├── packet_keepalive_test.go ├── packet_shutdown_test.go ├── packet_ack2_test.go ├── packet_nak_test.go ├── packet_msgdropreq_test.go ├── udpwriter.go ├── packet_ack_test.go ├── listener.go ├── time_test.go ├── packet_shutdown.go ├── packet_handshake_test.go ├── packet_keepalive.go ├── packet_ack2.go ├── packet_test.go ├── packet_nak.go ├── packetqueue_test.go ├── packet_msgdropreq.go ├── packetqueue.go ├── udtsocketqueue.go ├── udtsocketqueue_test.go ├── packet_ack.go ├── packet_handshake.go ├── udt.go ├── packet.go ├── multiplexer.go └── udtsocket.go ├── example.go └── LICENSE.txt /README.md: -------------------------------------------------------------------------------- 1 | Recently I've been using KCP and so far it's working really well for me. 2 | 3 | Here's a Go implementation - https://github.com/xtaci/kcp-go. Go check it out! 4 | -------------------------------------------------------------------------------- /udt/packet_keepalive_test.go: -------------------------------------------------------------------------------- 1 | package udt 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestKeepAlivePacket(t *testing.T) { 8 | testPacket( 9 | &keepAlivePacket{ 10 | h: header{ 11 | ts: 100, 12 | dstSockId: 59, 13 | }, 14 | }, t) 15 | } 16 | -------------------------------------------------------------------------------- /udt/packet_shutdown_test.go: -------------------------------------------------------------------------------- 1 | package udt 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestShutdownPacket(t *testing.T) { 8 | testPacket( 9 | &shutdownPacket{ 10 | h: header{ 11 | ts: 100, 12 | dstSockId: 59, 13 | }, 14 | }, t) 15 | } 16 | -------------------------------------------------------------------------------- /udt/packet_ack2_test.go: -------------------------------------------------------------------------------- 1 | package udt 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestACK2Packet(t *testing.T) { 8 | testPacket( 9 | &ack2Packet{ 10 | h: header{ 11 | ts: 100, 12 | dstSockId: 59, 13 | }, 14 | ackSeqNo: 90, 15 | }, t) 16 | } 17 | -------------------------------------------------------------------------------- /udt/packet_nak_test.go: -------------------------------------------------------------------------------- 1 | package udt 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestNAKPacket(t *testing.T) { 8 | testPacket( 9 | &nakPacket{ 10 | h: header{ 11 | ts: 100, 12 | dstSockId: 59, 13 | }, 14 | cmpLossInfo: 90, 15 | }, t) 16 | } 17 | -------------------------------------------------------------------------------- /udt/packet_msgdropreq_test.go: -------------------------------------------------------------------------------- 1 | package udt 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestMsgDropReqPacket(t *testing.T) { 8 | testPacket( 9 | &msgDropReqPacket{ 10 | h: header{ 11 | ts: 100, 12 | dstSockId: 59, 13 | }, 14 | msgId: 90, 15 | firstSeq: 91, 16 | lastSeq: 92, 17 | }, t) 18 | } 19 | -------------------------------------------------------------------------------- /udt/udpwriter.go: -------------------------------------------------------------------------------- 1 | package udt 2 | 3 | import ( 4 | "net" 5 | ) 6 | 7 | /* 8 | boundUDPWriter is an io.Writer that writes everything to a *net.UDPConn with 9 | a specific destination *net.UDPAddr. 10 | */ 11 | type boundUDPWriter struct { 12 | conn *net.UDPConn 13 | addr *net.UDPAddr 14 | } 15 | 16 | func (w *boundUDPWriter) Write(b []byte) (int, error) { 17 | return w.conn.WriteToUDP(b, w.addr) 18 | } 19 | -------------------------------------------------------------------------------- /udt/packet_ack_test.go: -------------------------------------------------------------------------------- 1 | package udt 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestACKPacket(t *testing.T) { 8 | testPacket( 9 | &ackPacket{ 10 | h: header{ 11 | ts: 100, 12 | dstSockId: 59, 13 | }, 14 | ackSeqNo: 90, 15 | pktSeqHi: 91, 16 | rtt: 92, 17 | rttVar: 93, 18 | buffAvail: 94, 19 | pktRecvRate: 95, 20 | estLinkCap: 96, 21 | }, t) 22 | } 23 | -------------------------------------------------------------------------------- /udt/listener.go: -------------------------------------------------------------------------------- 1 | package udt 2 | 3 | import ( 4 | "net" 5 | "io" 6 | ) 7 | 8 | /* 9 | listener implements the io.Listener interface for UDT. 10 | */ 11 | type listener struct { 12 | conn *net.UDPConn 13 | } 14 | 15 | func (m *multiplexer) Accept() (c io.ReadWriteCloser, err error) { 16 | return 17 | } 18 | 19 | func (m *multiplexer) Close() (err error) { 20 | return 21 | } 22 | 23 | func (m *multiplexer) Addr() (addr net.Addr) { 24 | return 25 | } 26 | 27 | -------------------------------------------------------------------------------- /udt/time_test.go: -------------------------------------------------------------------------------- 1 | package udt 2 | 3 | import ( 4 | "log" 5 | "testing" 6 | "time" 7 | ) 8 | 9 | func TestTime(t *testing.T) { 10 | start := time.Now() 11 | // for time.Now().Sub(start) < 10000 { 12 | // } 13 | time.Sleep(10 * time.Microsecond) 14 | end := time.Now() 15 | log.Printf("\nStart: %s\nEnd: %s\nElapsed:", start, end, end.Sub(start)) 16 | 17 | id := 820208164 18 | log.Printf("%x", id) 19 | 20 | log.Printf("%d", 0x20c55bf6) 21 | 22 | a := 0x0100007f 23 | log.Printf("%d.%d.%d.%d", byte(a), byte(a>>8), byte(a>>16), byte(a>>24)) 24 | } 25 | -------------------------------------------------------------------------------- /udt/packet_shutdown.go: -------------------------------------------------------------------------------- 1 | package udt 2 | 3 | // Structure of packets and functions for writing/reading them 4 | 5 | import ( 6 | "io" 7 | ) 8 | 9 | func (p *shutdownPacket) socketId() (sockId uint32) { 10 | return p.h.dstSockId 11 | } 12 | 13 | type shutdownPacket struct { 14 | h header 15 | } 16 | 17 | func (p *shutdownPacket) sendTime() (ts uint32) { 18 | return p.h.ts 19 | } 20 | 21 | func (p *shutdownPacket) writeTo(w io.Writer) (err error) { 22 | return p.h.writeTo(w, shutdown, noinfo) 23 | } 24 | 25 | func (p *shutdownPacket) readFrom(r io.Reader) (err error) { 26 | _, err = p.h.readFrom(r) 27 | return 28 | } 29 | -------------------------------------------------------------------------------- /udt/packet_handshake_test.go: -------------------------------------------------------------------------------- 1 | package udt 2 | 3 | import ( 4 | "net" 5 | "testing" 6 | "log" 7 | ) 8 | 9 | func TestHandshakePacket(t *testing.T) { 10 | read := testPacket( 11 | &handshakePacket{ 12 | h: header{ 13 | ts: 100, 14 | dstSockId: 59, 15 | }, 16 | udtVer: 4, 17 | sockType: STREAM, 18 | initPktSeq: 50, 19 | maxPktSize: 1000, 20 | maxFlowWinSize: 500, 21 | connType: 1, 22 | sockId: 59, 23 | synCookie: 978, 24 | sockAddr: net.ParseIP("127.0.0.1"), 25 | }, t) 26 | 27 | log.Println((read.(*handshakePacket)).sockAddr) 28 | } 29 | -------------------------------------------------------------------------------- /udt/packet_keepalive.go: -------------------------------------------------------------------------------- 1 | package udt 2 | 3 | // Structure of packets and functions for writing/reading them 4 | 5 | import ( 6 | "io" 7 | ) 8 | 9 | type keepAlivePacket struct { 10 | h header 11 | } 12 | 13 | func (p *keepAlivePacket) socketId() (sockId uint32) { 14 | return p.h.dstSockId 15 | } 16 | 17 | func (p *keepAlivePacket) sendTime() (ts uint32) { 18 | return p.h.ts 19 | } 20 | 21 | func (p *keepAlivePacket) writeTo(w io.Writer) (err error) { 22 | return p.h.writeTo(w, keepalive, noinfo) 23 | } 24 | 25 | func (p *keepAlivePacket) readFrom(r io.Reader) (err error) { 26 | _, err = p.h.readFrom(r) 27 | return 28 | } 29 | -------------------------------------------------------------------------------- /udt/packet_ack2.go: -------------------------------------------------------------------------------- 1 | package udt 2 | 3 | // Structure of packets and functions for writing/reading them 4 | 5 | import ( 6 | "io" 7 | ) 8 | 9 | type ack2Packet struct { 10 | h header 11 | ackSeqNo uint32 // ACK sequence number 12 | } 13 | 14 | func (p *ack2Packet) socketId() (sockId uint32) { 15 | return p.h.dstSockId 16 | } 17 | 18 | func (p *ack2Packet) sendTime() (ts uint32) { 19 | return p.h.ts 20 | } 21 | 22 | func (p *ack2Packet) writeTo(w io.Writer) (err error) { 23 | if err := p.h.writeTo(w, ack2, p.ackSeqNo); err != nil { 24 | return err 25 | } 26 | return 27 | } 28 | 29 | func (p *ack2Packet) readFrom(r io.Reader) (err error) { 30 | p.ackSeqNo, err = p.h.readFrom(r) 31 | return 32 | } 33 | -------------------------------------------------------------------------------- /example.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/oxtoacart/go-udt/udt" 5 | "log" 6 | "net" 7 | "time" 8 | ) 9 | 10 | func main() { 11 | if addr, err := net.ResolveUDPAddr("udp", "localhost:47008"); err != nil { 12 | log.Fatalf("Unable to resolve address: %s", err) 13 | } else { 14 | go server(addr) 15 | time.Sleep(200 * time.Millisecond) 16 | go client(addr) 17 | 18 | time.Sleep(50 * time.Second) 19 | } 20 | } 21 | 22 | func server(addr *net.UDPAddr) { 23 | if _, err := udt.ListenUDT("udp", addr); err != nil { 24 | log.Fatalf("Unable to listen: %s", err) 25 | } 26 | } 27 | 28 | func client(addr *net.UDPAddr) { 29 | if _, err := udt.DialUDT("udp", nil, addr); err != nil { 30 | log.Fatalf("Unable to dial: %s", err) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /udt/packet_test.go: -------------------------------------------------------------------------------- 1 | package udt 2 | 3 | import ( 4 | "bytes" 5 | "reflect" 6 | "testing" 7 | ) 8 | 9 | func TestDataPacket(t *testing.T) { 10 | testPacket( 11 | &dataPacket{ 12 | seq: 50, 13 | ts: 1409, 14 | dstSockId: 90, 15 | data: []byte("Hello UDT World!"), 16 | }, t) 17 | } 18 | 19 | func testPacket(p packet, t *testing.T) (read packet) { 20 | b := bytes.NewBuffer([]byte{}) 21 | if err := p.writeTo(b); err != nil { 22 | t.Errorf("Unable to write packet: %s", err) 23 | } 24 | if p2, err := readPacketFrom(b); err != nil { 25 | t.Errorf("Unable to read packet: %s", err) 26 | } else { 27 | if !reflect.DeepEqual(p, p2) { 28 | t.Errorf("Read did not match written.\n\nWrote: %s\nRead: %s", p, p2) 29 | } 30 | read = p2 31 | } 32 | return 33 | } 34 | -------------------------------------------------------------------------------- /udt/packet_nak.go: -------------------------------------------------------------------------------- 1 | package udt 2 | 3 | // Structure of packets and functions for writing/reading them 4 | 5 | import ( 6 | "io" 7 | ) 8 | 9 | type nakPacket struct { 10 | h header 11 | cmpLossInfo uint32 // integer array of compressed loss information 12 | } 13 | 14 | func (p *nakPacket) socketId() (sockId uint32) { 15 | return p.h.dstSockId 16 | } 17 | 18 | func (p *nakPacket) sendTime() (ts uint32) { 19 | return p.h.ts 20 | } 21 | 22 | func (p *nakPacket) writeTo(w io.Writer) (err error) { 23 | if err := p.h.writeTo(w, nak, noinfo); err != nil { 24 | return err 25 | } 26 | if err := writeBinary(w, p.cmpLossInfo); err != nil { 27 | return err 28 | } 29 | return 30 | } 31 | 32 | func (p *nakPacket) readFrom(r io.Reader) (err error) { 33 | if _, err = p.h.readFrom(r); err != nil { 34 | return 35 | } 36 | if err = readBinary(r, &p.cmpLossInfo); err != nil { 37 | return 38 | } 39 | return 40 | } 41 | -------------------------------------------------------------------------------- /udt/packetqueue_test.go: -------------------------------------------------------------------------------- 1 | package udt 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestPacketQueue(t *testing.T) { 8 | q := newPacketQueue() 9 | p1 := &dataPacket{ 10 | ts: 1, 11 | } 12 | p2 := &dataPacket{ 13 | ts: 2, 14 | } 15 | p3 := &dataPacket{ 16 | ts: 3, 17 | } 18 | q.push(p1) 19 | q.push(p3) 20 | q.push(p2) 21 | el := q.peek() 22 | if el != p1 { 23 | t.Errorf("Wrong packet peeked. Expected: %s, Got: %s", p1, el) 24 | } 25 | el = q.pop() 26 | if el != p1 { 27 | t.Errorf("Wrong packet popped. Expected: %s, Got: %s", p1, el) 28 | } 29 | 30 | el = q.peek() 31 | if el != p2 { 32 | t.Errorf("Wrong packet peeked. Expected: %s, Got: %s", p2, el) 33 | } 34 | el = q.pop() 35 | if el != p2 { 36 | t.Errorf("Wrong packet popped. Expected: %s, Got: %s", p2, el) 37 | } 38 | 39 | el = q.peek() 40 | if el != p3 { 41 | t.Errorf("Wrong packet peeked. Expected: %s, Got: %s", p3, el) 42 | } 43 | el = q.pop() 44 | if el != p3 { 45 | t.Errorf("Wrong packet popped. Expected: %s, Got: %s", p3, el) 46 | } 47 | el = q.pop() 48 | if el != nil { 49 | t.Errorf("Expected nil packet, got %s", el) 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /udt/packet_msgdropreq.go: -------------------------------------------------------------------------------- 1 | package udt 2 | 3 | // Structure of packets and functions for writing/reading them 4 | 5 | import ( 6 | "io" 7 | ) 8 | 9 | type msgDropReqPacket struct { 10 | h header 11 | msgId uint32 // Message ID 12 | firstSeq uint32 // First sequence number in the message 13 | lastSeq uint32 // Last sequence number in the message 14 | } 15 | 16 | func (p *msgDropReqPacket) socketId() (sockId uint32) { 17 | return p.h.dstSockId 18 | } 19 | 20 | func (p *msgDropReqPacket) sendTime() (ts uint32) { 21 | return p.h.ts 22 | } 23 | 24 | func (p *msgDropReqPacket) writeTo(w io.Writer) (err error) { 25 | if err := p.h.writeTo(w, msg_drop_req, p.msgId); err != nil { 26 | return err 27 | } 28 | if err := writeBinary(w, p.firstSeq); err != nil { 29 | return err 30 | } 31 | if err := writeBinary(w, p.lastSeq); err != nil { 32 | return err 33 | } 34 | return 35 | } 36 | 37 | func (p *msgDropReqPacket) readFrom(r io.Reader) (err error) { 38 | if p.msgId, err = p.h.readFrom(r); err != nil { 39 | return 40 | } 41 | if err = readBinary(r, &p.firstSeq); err != nil { 42 | return 43 | } 44 | if err = readBinary(r, &p.lastSeq); err != nil { 45 | return 46 | } 47 | return 48 | } 49 | -------------------------------------------------------------------------------- /udt/packetqueue.go: -------------------------------------------------------------------------------- 1 | package udt 2 | 3 | import ( 4 | "container/heap" 5 | ) 6 | 7 | /* 8 | A packetQueue is a priority queue of packets sorted by ts. 9 | */ 10 | type packetQueue struct { 11 | h packetHeap 12 | l uint32 13 | } 14 | 15 | func (q *packetQueue) push(p packet) { 16 | heap.Push(&q.h, p) 17 | q.l += 1 18 | } 19 | 20 | func (q *packetQueue) peek() (p packet) { 21 | if q.l == 0 { 22 | return nil 23 | } else { 24 | return q.h[0] 25 | } 26 | } 27 | 28 | func (q *packetQueue) pop() (p packet) { 29 | if q.l == 0 { 30 | return nil 31 | } else { 32 | q.l -= 1 33 | return heap.Pop(&q.h).(packet) 34 | } 35 | } 36 | 37 | func newPacketQueue() (q *packetQueue) { 38 | q = &packetQueue{} 39 | heap.Init(&q.h) 40 | return 41 | } 42 | 43 | /* 44 | A packetHeap is the internal implementation of a Heap used by packetQueue. 45 | */ 46 | type packetHeap []packet 47 | 48 | func (h packetHeap) Len() int { return len(h) } 49 | func (h packetHeap) Less(i, j int) bool { return h[i].sendTime() < h[j].sendTime() } 50 | func (h packetHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] } 51 | 52 | func (h *packetHeap) Push(x interface{}) { 53 | // Push and Pop use pointer receivers because they modify the slice's length, 54 | // not just its contents. 55 | *h = append(*h, x.(packet)) 56 | } 57 | 58 | func (h *packetHeap) Pop() interface{} { 59 | old := *h 60 | n := len(old) 61 | x := old[n-1] 62 | *h = old[0 : n-1] 63 | return x 64 | } 65 | -------------------------------------------------------------------------------- /udt/udtsocketqueue.go: -------------------------------------------------------------------------------- 1 | package udt 2 | 3 | import ( 4 | "container/heap" 5 | ) 6 | 7 | /* 8 | A udtSocketQueue is a priority queue of udtSockets sorted by the next packet sending time. 9 | */ 10 | type udtSocketQueue struct { 11 | h socketHeap 12 | l uint32 13 | } 14 | 15 | func (q *udtSocketQueue) push(s *udtSocket) { 16 | heap.Push(&q.h, s) 17 | q.l += 1 18 | } 19 | 20 | func (q *udtSocketQueue) peek() (s *udtSocket) { 21 | if q.l == 0 { 22 | return nil 23 | } else { 24 | return q.h[0] 25 | } 26 | } 27 | 28 | func (q *udtSocketQueue) pop() (s *udtSocket) { 29 | if q.l == 0 { 30 | return nil 31 | } else { 32 | q.l -= 1 33 | return heap.Pop(&q.h).(*udtSocket) 34 | } 35 | } 36 | 37 | func newUdtSocketQueue() (q *udtSocketQueue) { 38 | q = &udtSocketQueue{} 39 | heap.Init(&q.h) 40 | return 41 | } 42 | 43 | /* 44 | A socketHeap is the internal implementation of a Heap used by udtSocketQueue. 45 | */ 46 | type socketHeap []*udtSocket 47 | 48 | func (h socketHeap) Len() int { return len(h) } 49 | func (h socketHeap) Less(i, j int) bool { return h[i].nextSendTime() < h[j].nextSendTime() } 50 | func (h socketHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] } 51 | 52 | func (h *socketHeap) Push(x interface{}) { 53 | // Push and Pop use pointer receivers because they modify the slice's length, 54 | // not just its contents. 55 | *h = append(*h, x.(*udtSocket)) 56 | } 57 | 58 | func (h *socketHeap) Pop() interface{} { 59 | old := *h 60 | n := len(old) 61 | x := old[n-1] 62 | *h = old[0 : n-1] 63 | return x 64 | } 65 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013 Ox Cart. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | * Neither the name of Ox Cart nor the names of his associates may 14 | be used to endorse or promote products derived from this software 15 | without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /udt/udtsocketqueue_test.go: -------------------------------------------------------------------------------- 1 | package udt 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestUDTSocketQueue(t *testing.T) { 8 | // Set up some packets 9 | p1 := &dataPacket{ 10 | ts: 1, 11 | } 12 | p2 := &dataPacket{ 13 | ts: 2, 14 | } 15 | p3 := &dataPacket{ 16 | ts: 3, 17 | } 18 | p4 := &dataPacket{ 19 | ts: 4, 20 | } 21 | 22 | // Set up some udtSockets 23 | s1 := &udtSocket{dataOut: newPacketQueue()} 24 | s2 := &udtSocket{dataOut: newPacketQueue()} 25 | s3 := &udtSocket{dataOut: newPacketQueue()} 26 | s1.dataOut.push(p1) 27 | s1.dataOut.push(p2) 28 | s2.dataOut.push(p3) 29 | s3.dataOut.push(p4) 30 | 31 | // Add sockets to a udtSocketQueue 32 | q := newUdtSocketQueue() 33 | q.push(s1) 34 | q.push(s2) 35 | q.push(s3) 36 | 37 | el := q.peek() 38 | if el != s1 { 39 | t.Errorf("Wrong queue peeked. Expected: %s, Got: %s", s1, el) 40 | } 41 | el = q.pop() 42 | if el != s1 { 43 | t.Errorf("Wrong queue popped. Expected: %s, Got: %s", s1, el) 44 | } 45 | 46 | el = q.peek() 47 | if el != s2 { 48 | t.Errorf("Wrong queue peeked. Expected: %s, Got: %s", s2, el) 49 | } 50 | el = q.pop() 51 | if el != s2 { 52 | t.Errorf("Wrong queue popped. Expected: %s, Got: %s", s2, el) 53 | } 54 | 55 | el = q.peek() 56 | if el != s3 { 57 | t.Errorf("Wrong queue peeked. Expected: %s, Got: %s", s3, el) 58 | } 59 | el = q.pop() 60 | if el != s3 { 61 | t.Errorf("Wrong queue popped. Expected: %s, Got: %s", s3, el) 62 | } 63 | el = q.pop() 64 | if el != nil { 65 | t.Errorf("Expected nil queue, got %s", el) 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /udt/packet_ack.go: -------------------------------------------------------------------------------- 1 | package udt 2 | 3 | // Structure of packets and functions for writing/reading them 4 | 5 | import ( 6 | "io" 7 | ) 8 | 9 | type ackPacket struct { 10 | h header 11 | ackSeqNo uint32 // ACK sequence number 12 | pktSeqHi uint32 // The packet sequence number to which all the previous packets have been received (excluding) 13 | 14 | // The below are optional 15 | rtt uint32 // RTT (in microseconds) 16 | rttVar uint32 // RTT variance 17 | buffAvail uint32 // Available buffer size (in bytes) 18 | pktRecvRate uint32 // Packets receiving rate (in number of packets per second) 19 | estLinkCap uint32 // Estimated link capacity (in number of packets per second) 20 | } 21 | 22 | func (p *ackPacket) socketId() (sockId uint32) { 23 | return p.h.dstSockId 24 | } 25 | 26 | func (p *ackPacket) sendTime() (ts uint32) { 27 | return p.h.ts 28 | } 29 | 30 | func (p *ackPacket) writeTo(w io.Writer) (err error) { 31 | if err := p.h.writeTo(w, ack, p.ackSeqNo); err != nil { 32 | return err 33 | } 34 | if err := writeBinary(w, p.pktSeqHi); err != nil { 35 | return err 36 | } 37 | if err := writeBinary(w, p.rtt); err != nil { 38 | return err 39 | } 40 | if err := writeBinary(w, p.rttVar); err != nil { 41 | return err 42 | } 43 | if err := writeBinary(w, p.buffAvail); err != nil { 44 | return err 45 | } 46 | if err := writeBinary(w, p.pktRecvRate); err != nil { 47 | return err 48 | } 49 | if err := writeBinary(w, p.estLinkCap); err != nil { 50 | return err 51 | } 52 | return 53 | } 54 | 55 | func (p *ackPacket) readFrom(r io.Reader) (err error) { 56 | if p.ackSeqNo, err = p.h.readFrom(r); err != nil { 57 | return 58 | } 59 | if err = readBinary(r, &p.pktSeqHi); err != nil { 60 | return 61 | } 62 | if err = readBinary(r, &p.rtt); err != nil { 63 | return 64 | } 65 | if err = readBinary(r, &p.rttVar); err != nil { 66 | return 67 | } 68 | if err = readBinary(r, &p.buffAvail); err != nil { 69 | return 70 | } 71 | if err = readBinary(r, &p.pktRecvRate); err != nil { 72 | return 73 | } 74 | if err = readBinary(r, &p.estLinkCap); err != nil { 75 | return 76 | } 77 | return 78 | } 79 | -------------------------------------------------------------------------------- /udt/packet_handshake.go: -------------------------------------------------------------------------------- 1 | package udt 2 | 3 | // Structure of packets and functions for writing/reading them 4 | 5 | import ( 6 | "io" 7 | "net" 8 | ) 9 | 10 | type handshakePacket struct { 11 | h header 12 | udtVer uint32 // UDT version 13 | sockType uint32 // Socket Type (0 = STREAM or 1 = DGRAM) 14 | initPktSeq uint32 // initial packet sequence number 15 | maxPktSize uint32 // maximum packet size (including UDP/IP headers) 16 | maxFlowWinSize uint32 // maximum flow window size 17 | connType uint32 // connection type (regular or rendezvous) 18 | sockId uint32 // socket ID 19 | synCookie uint32 // SYN cookie 20 | sockAddr net.IP // the IP address of the UDP socket to which this packet is being sent 21 | } 22 | 23 | func (p *handshakePacket) socketId() (sockId uint32) { 24 | return p.sockId 25 | } 26 | 27 | func (p *handshakePacket) sendTime() (ts uint32) { 28 | return p.h.ts 29 | } 30 | 31 | func (p *handshakePacket) writeTo(w io.Writer) (err error) { 32 | if err := p.h.writeTo(w, handshake, noinfo); err != nil { 33 | return err 34 | } 35 | if err := writeBinary(w, p.udtVer); err != nil { 36 | return err 37 | } 38 | if err := writeBinary(w, p.sockType); err != nil { 39 | return err 40 | } 41 | if err := writeBinary(w, p.initPktSeq); err != nil { 42 | return err 43 | } 44 | if err := writeBinary(w, p.maxPktSize); err != nil { 45 | return err 46 | } 47 | if err := writeBinary(w, p.maxFlowWinSize); err != nil { 48 | return err 49 | } 50 | if err := writeBinary(w, p.connType); err != nil { 51 | return err 52 | } 53 | if err := writeBinary(w, p.sockId); err != nil { 54 | return err 55 | } 56 | if err := writeBinary(w, p.synCookie); err != nil { 57 | return err 58 | } 59 | if _, err := w.Write(p.sockAddr); err != nil { 60 | return err 61 | } 62 | l := len(p.sockAddr) 63 | if l < 16 { 64 | // pad the address field 65 | padding := make([]byte, 16-l) 66 | if _, err := w.Write(padding); err != nil { 67 | return err 68 | } 69 | } 70 | return 71 | } 72 | 73 | func (p *handshakePacket) readFrom(r io.Reader) (err error) { 74 | if _, err = p.h.readFrom(r); err != nil { 75 | return 76 | } 77 | if err = readBinary(r, &p.udtVer); err != nil { 78 | return 79 | } 80 | if err = readBinary(r, &p.sockType); err != nil { 81 | return 82 | } 83 | if err = readBinary(r, &p.initPktSeq); err != nil { 84 | return 85 | } 86 | if err = readBinary(r, &p.maxPktSize); err != nil { 87 | return 88 | } 89 | if err = readBinary(r, &p.maxFlowWinSize); err != nil { 90 | return 91 | } 92 | if err = readBinary(r, &p.connType); err != nil { 93 | return 94 | } 95 | if err = readBinary(r, &p.sockId); err != nil { 96 | return 97 | } 98 | if err = readBinary(r, &p.synCookie); err != nil { 99 | return 100 | } 101 | p.sockAddr = make(net.IP, 16) 102 | if _, err = r.Read(p.sockAddr); err != nil { 103 | return 104 | } 105 | return 106 | } 107 | -------------------------------------------------------------------------------- /udt/udt.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package udt provides a pure Go implementation of the UDT protocol per 3 | http://udt.sourceforge.net/doc/draft-gg-udt-03.txt. 4 | 5 | udt does not implement all of the spec. In particular, the following are not 6 | implemented: 7 | 8 | - Rendezvous mode 9 | - DGRAM mode (only streaming is supported) 10 | 11 | */ 12 | package udt 13 | 14 | import ( 15 | "crypto/rand" 16 | "fmt" 17 | "io" 18 | "log" 19 | "math" 20 | "math/big" 21 | _net "net" 22 | "sync" 23 | ) 24 | 25 | type Conn interface { 26 | io.ReadWriteCloser 27 | } 28 | 29 | type Listener interface { 30 | // Accept waits for and returns the next connection to the Listener. 31 | Accept() (c io.ReadWriteCloser, err error) 32 | 33 | // Close closes the Listener. 34 | // Any blocked Accept operations will be unblocked and return errors. 35 | Close() (err error) 36 | 37 | // Addr returns the Listener's network address. 38 | Addr() (addr _net.Addr) 39 | } 40 | 41 | /* 42 | DialUDT establishes an outbound UDT connection using the supplied net, laddr and 43 | raddr. See function net.DialUDP for a description of net, laddr and raddr. 44 | */ 45 | func DialUDT(net string, laddr, raddr *_net.UDPAddr) (conn Conn, err error) { 46 | var m *multiplexer 47 | 48 | dial := func() (*_net.UDPConn, error) { 49 | return _net.DialUDP(net, laddr, raddr) 50 | } 51 | 52 | if m, err = multiplexerFor(laddr, dial); err == nil { 53 | if m.mode == mode_server { 54 | err = fmt.Errorf("Attempted to dial out from a server socket") 55 | } else { 56 | m.mode = mode_client 57 | conn, err = m.newClientSocket() 58 | } 59 | } 60 | 61 | return 62 | } 63 | 64 | /* 65 | ListenUDT listens for incoming UDT connections addressed to the local address 66 | laddr. See function net.ListenUDP for a description of net and laddr. 67 | */ 68 | func ListenUDT(net string, laddr *_net.UDPAddr) (l Listener, err error) { 69 | var m *multiplexer 70 | 71 | listen := func() (*_net.UDPConn, error) { 72 | return _net.ListenUDP(net, laddr) 73 | } 74 | 75 | if m, err = multiplexerFor(laddr, listen); err == nil { 76 | if m.mode == mode_client { 77 | err = fmt.Errorf("Attempted to listen on a client socket") 78 | } else { 79 | m.mode = mode_server 80 | l = m 81 | } 82 | } 83 | 84 | return 85 | } 86 | 87 | const ( 88 | syn_time = 10000 // in microseconds 89 | max_packet_size = 576 // todo: make this tunable 90 | init_client_handshake = 1 91 | 92 | // Multiplexer modes 93 | mode_client = 1 94 | mode_server = 2 95 | ) 96 | 97 | var ( 98 | multiplexers = map[string]*multiplexer{} 99 | multiplexersMutex sync.Mutex 100 | sids uint32 // socketId sequence 101 | ) 102 | 103 | func init() { 104 | sids = randUint32() 105 | } 106 | 107 | /* 108 | randInt32 generates a secure random value between 0 and the max possible uint32 109 | */ 110 | func randUint32() (r uint32) { 111 | if _r, err := rand.Int(rand.Reader, big.NewInt(math.MaxUint32)); err != nil { 112 | log.Fatalf("Unable to generate random uint32: %s", err) 113 | } else { 114 | r = uint32(_r.Uint64()) 115 | } 116 | return 117 | } 118 | -------------------------------------------------------------------------------- /udt/packet.go: -------------------------------------------------------------------------------- 1 | package udt 2 | 3 | // Structure of packets and functions for writing/reading them 4 | 5 | import ( 6 | "bytes" 7 | "encoding/binary" 8 | "fmt" 9 | "io" 10 | ) 11 | 12 | const ( 13 | flag_bit_32 = 1 << 31 // leading bit for distinguishing control from data packets (32 bit version) 14 | flag_bit_16 = 1 << 15 // leading bit for distinguishing control from data packets (16 bit version) 15 | 16 | // Control packet types 17 | handshake = 0x0 18 | keepalive = 0x1 19 | ack = 0x2 20 | nak = 0x3 21 | unused = 0x4 22 | shutdown = 0x5 23 | ack2 = 0x6 24 | msg_drop_req = 0x7 25 | 26 | // Socket types 27 | // Note - these are reversed from the spec, as the C++ implementation of UDT 28 | // seems to have them reversed and we want to stay interoperable 29 | STREAM = 1 30 | DGRAM = 0 // not supported! 31 | 32 | // No info for info section of header 33 | noinfo = 0 34 | ) 35 | 36 | var ( 37 | endianness = binary.BigEndian 38 | ) 39 | 40 | type packet interface { 41 | // socketId retrieves the socket id of a packet 42 | socketId() (sockId uint32) 43 | 44 | // sendTime retrieves the timesamp of the packet 45 | sendTime() (ts uint32) 46 | 47 | writeTo(io.Writer) (err error) 48 | 49 | /* 50 | readFrom reads the packet from a Reader 51 | */ 52 | readFrom(r io.Reader) (err error) 53 | } 54 | 55 | type dataPacket struct { 56 | seq uint32 57 | ts uint32 58 | dstSockId uint32 59 | data []byte 60 | } 61 | 62 | type header struct { 63 | ts uint32 64 | dstSockId uint32 65 | } 66 | 67 | func (p *dataPacket) socketId() (sockId uint32) { 68 | return p.dstSockId 69 | } 70 | 71 | func (p *dataPacket) sendTime() (ts uint32) { 72 | return p.ts 73 | } 74 | 75 | func (dp *dataPacket) writeTo(w io.Writer) (err error) { 76 | if err := writeBinary(w, dp.seq); err != nil { 77 | return err 78 | } 79 | if err := writeBinary(w, dp.ts); err != nil { 80 | return err 81 | } 82 | if err := writeBinary(w, dp.dstSockId); err != nil { 83 | return err 84 | } 85 | if _, err := w.Write(dp.data); err != nil { 86 | return err 87 | } 88 | return 89 | } 90 | 91 | func (p *dataPacket) readFrom(r io.Reader) (err error) { 92 | if err = readBinary(r, &p.ts); err != nil { 93 | return 94 | } 95 | if err = readBinary(r, &p.dstSockId); err != nil { 96 | return 97 | } 98 | // The data is whatever is what comes after the 12 bytes of header 99 | var buf *bytes.Buffer 100 | switch b := r.(type) { 101 | case *bytes.Buffer: 102 | buf = b 103 | default: 104 | buf := bytes.NewBuffer([]byte{}) 105 | buf.ReadFrom(r) 106 | } 107 | p.data = buf.Bytes() 108 | return 109 | } 110 | 111 | func (h *header) writeTo(w io.Writer, msgType uint16, info uint32) (err error) { 112 | // Sets the flag bit to indicate this is a control packet 113 | if err := writeBinary(w, msgType|flag_bit_16); err != nil { 114 | return err 115 | } 116 | // Write 16 bit reserved data 117 | if err := writeBinary(w, uint16(0)); err != nil { 118 | return err 119 | } 120 | if err := writeBinary(w, info); err != nil { 121 | return err 122 | } 123 | if err := writeBinary(w, h.ts); err != nil { 124 | return err 125 | } 126 | if err := writeBinary(w, h.dstSockId); err != nil { 127 | return err 128 | } 129 | return 130 | } 131 | 132 | func (p *header) readFrom(r io.Reader) (addtlInfo uint32, err error) { 133 | if err = readBinary(r, &addtlInfo); err != nil { 134 | return 135 | } 136 | if err = readBinary(r, &p.ts); err != nil { 137 | return 138 | } 139 | if err = readBinary(r, &p.dstSockId); err != nil { 140 | return 141 | } 142 | return 143 | } 144 | 145 | func readPacketFrom(r io.Reader) (p packet, err error) { 146 | var h uint32 147 | if err = readBinary(r, &h); err != nil { 148 | return 149 | } 150 | if h&flag_bit_32 == flag_bit_32 { 151 | // this is a control packet 152 | // Remove flag bit 153 | h = h &^ flag_bit_32 154 | // Message type is leading 16 bits 155 | msgType := h >> 16 156 | switch msgType { 157 | case handshake: 158 | p = &handshakePacket{} 159 | case keepalive: 160 | p = &keepAlivePacket{} 161 | case ack: 162 | p = &ackPacket{} 163 | case nak: 164 | p = &nakPacket{} 165 | case shutdown: 166 | p = &shutdownPacket{} 167 | case ack2: 168 | p = &ack2Packet{} 169 | case msg_drop_req: 170 | p = &msgDropReqPacket{} 171 | default: 172 | err = fmt.Errorf("Unkown control packet type: %X", msgType) 173 | return nil, err 174 | } 175 | err = p.readFrom(r) 176 | return 177 | } else { 178 | // this is a data packet 179 | p = &dataPacket{ 180 | seq: h, 181 | } 182 | err = p.readFrom(r) 183 | } 184 | return 185 | } 186 | 187 | func writeBinary(w io.Writer, n interface{}) (err error) { 188 | return binary.Write(w, endianness, n) 189 | } 190 | 191 | func readBinary(r io.Reader, n interface{}) (err error) { 192 | return binary.Read(r, endianness, n) 193 | } 194 | -------------------------------------------------------------------------------- /udt/multiplexer.go: -------------------------------------------------------------------------------- 1 | package udt 2 | 3 | import ( 4 | "bytes" 5 | "github.com/oxtoacart/bpool" 6 | "log" 7 | "net" 8 | "sync" 9 | "time" 10 | ) 11 | 12 | /* 13 | A multiplexer multiplexes multiple UDT sockets over a single PacketConn. 14 | */ 15 | type multiplexer struct { 16 | laddr *net.UDPAddr // the local address handled by this multiplexer 17 | conn *net.UDPConn // the UDPConn from which we read/write 18 | mode uint8 // client or server 19 | sockets map[uint32]*udtSocket // the server udtSockets handled by this multiplexer, by sockId 20 | socketsMutex *sync.Mutex 21 | sendQ *udtSocketQueue // priority queue of udtSockets awaiting a send (actually includes ones with no packets waiting too) 22 | ctrlOut chan packet // control packets meant queued for sending 23 | in chan packetHolder // packets inbound from the PacketConn 24 | out chan packet // packets outbound to the PacketConn 25 | writeBufferPool *bpool.BufferPool // leaky buffer pool for writing to conn 26 | readBytePool *bpool.BytePool // leaky byte pool for reading from conn 27 | } 28 | 29 | type packetHolder struct { 30 | packet packet 31 | from *net.UDPAddr 32 | } 33 | 34 | /* 35 | multiplexerFor gets or creates a multiplexer for the given local address. If a 36 | new multiplexer is created, the given init function is run to obtain an 37 | io.ReadWriter. 38 | */ 39 | func multiplexerFor(laddr *net.UDPAddr, init func() (*net.UDPConn, error)) (m *multiplexer, err error) { 40 | multiplexersMutex.Lock() 41 | defer multiplexersMutex.Unlock() 42 | key := laddr.String() 43 | m = multiplexers[key] 44 | if m == nil { 45 | // No multiplexer, need to create connection 46 | var conn *net.UDPConn 47 | if conn, err = init(); err == nil { 48 | m = newMultiplexer(laddr, conn) 49 | multiplexers[key] = m 50 | } 51 | } 52 | return 53 | } 54 | 55 | func newMultiplexer(laddr *net.UDPAddr, conn *net.UDPConn) (m *multiplexer) { 56 | m = &multiplexer{ 57 | laddr: laddr, 58 | conn: conn, 59 | sockets: make(map[uint32]*udtSocket), 60 | socketsMutex: new(sync.Mutex), 61 | sendQ: newUdtSocketQueue(), 62 | ctrlOut: make(chan packet, 100), // todo: figure out how to size this 63 | in: make(chan packetHolder, 100), // todo: make this tunable 64 | out: make(chan packet, 100), // todo: make this tunable 65 | writeBufferPool: bpool.NewBufferPool(25600), // todo: make this tunable 66 | readBytePool: bpool.NewBytePool(25600, max_packet_size), // todo: make this tunable 67 | } 68 | 69 | go m.coordinate() 70 | go m.read() 71 | go m.write() 72 | 73 | return 74 | } 75 | 76 | func (m *multiplexer) newClientSocket() (s *udtSocket, err error) { 77 | m.socketsMutex.Lock() 78 | defer m.socketsMutex.Unlock() 79 | sids -= 1 80 | sid := sids 81 | if s, err = newClientSocket(m, sid); err == nil { 82 | m.sockets[sid] = s 83 | } 84 | 85 | for { 86 | s.initHandshake() 87 | time.Sleep(200 * time.Millisecond) 88 | } 89 | 90 | return 91 | } 92 | 93 | /* 94 | read runs in a goroutine and reads packets from conn using a buffer from the 95 | readBufferPool, or a new buffer. 96 | */ 97 | func (m *multiplexer) read() { 98 | for { 99 | b := m.readBytePool.Get() 100 | defer m.readBytePool.Put(b) 101 | if _, from, err := m.conn.ReadFromUDP(b); err != nil { 102 | log.Printf("Unable to read into buffer: %s", err) 103 | } else { 104 | r := bytes.NewReader(b) 105 | if p, err := readPacketFrom(r); err != nil { 106 | log.Printf("Unable to read packet: %s", err) 107 | } else { 108 | m.in <- packetHolder{p, from} 109 | } 110 | } 111 | } 112 | } 113 | 114 | /* 115 | write runs in a goroutine and writes packets to conn using a buffer from the 116 | writeBufferPool, or a new buffer. 117 | */ 118 | func (m *multiplexer) write() { 119 | for { 120 | select { 121 | case p := <-m.ctrlOut: 122 | b := m.writeBufferPool.Get() 123 | defer m.writeBufferPool.Put(b) 124 | if err := p.writeTo(b); err != nil { 125 | // TODO: handle write error 126 | log.Fatalf("Unable to buffer out: %s", err) 127 | } else { 128 | log.Printf("Writing to %s", p.socketId()) 129 | if _, err := b.WriteTo(m.sockets[p.socketId()].boundWriter); err != nil { 130 | // TODO: handle write error 131 | log.Fatalf("Unable to write out: %s", err) 132 | } 133 | } 134 | } 135 | } 136 | } 137 | 138 | // coordinate runs in a goroutine and coordinates all of the multiplexer's work 139 | func (m *multiplexer) coordinate() { 140 | for { 141 | select { 142 | case p := <-m.in: 143 | m.handleInbound(p) 144 | } 145 | } 146 | } 147 | 148 | func (m *multiplexer) handleInbound(ph packetHolder) { 149 | switch p := ph.packet.(type) { 150 | case *handshakePacket: 151 | // Only process packet if version and type are supported 152 | log.Println("Got handshake packet") 153 | if p.udtVer == 4 && p.sockType == STREAM { 154 | log.Println("Right version and type") 155 | s := m.sockets[p.sockId] 156 | if p.sockType == init_client_handshake { 157 | if s == nil { 158 | // create a new udt socket and remember it 159 | var err error 160 | if s, err = newServerSocket(m, ph.from, p); err == nil { 161 | m.sockets[p.sockId] = s 162 | log.Println("Responding to handshake") 163 | s.respondInitHandshake() 164 | } 165 | } 166 | } 167 | 168 | if s == nil { 169 | // s may still be nil if we couldn't create a new socket 170 | // in this case, we ignore the error 171 | } else { 172 | // Okay, we have a socket 173 | 174 | } 175 | } 176 | } 177 | } 178 | -------------------------------------------------------------------------------- /udt/udtsocket.go: -------------------------------------------------------------------------------- 1 | package udt 2 | 3 | import ( 4 | "io" 5 | "math" 6 | "net" 7 | "time" 8 | ) 9 | 10 | const ( 11 | sock_state_new = 0 12 | sock_state_handshake_init = 1 13 | sock_state_handshake_finish = 2 14 | sock_state_connected = 3 15 | ) 16 | 17 | /* 18 | udtSocket encapsulates a UDT socket between a local and remote address pair, as 19 | defined by the UDT specification. udtSocket implements the net.Conn interface 20 | so that it can be used anywhere that anywhere a stream-oriented network 21 | connection (like TCP) would be used. 22 | */ 23 | type udtSocket struct { 24 | m *multiplexer // the multiplexer that handles this socket 25 | raddr *net.UDPAddr // the remote address 26 | boundWriter io.Writer // a UDP writer that knows which address to send to 27 | created time.Time // the time that this socket was created 28 | sockState uint8 29 | ackPeriod uint32 // in microseconds 30 | nakPeriod uint32 // in microseconds 31 | expPeriod uint32 // in microseconds 32 | sndPeriod uint32 // in microseconds 33 | ctrlIn chan *dataPacket // inbound control packets 34 | dataIn chan *dataPacket // inbound data packets 35 | dataOut *packetQueue // queue of outbound data packets 36 | pktSeq uint32 // the current packet sequence number 37 | currDp *dataPacket // currently reading data packet (for partial reads) 38 | currDpOffset int // offset in currIn (for partial reads) 39 | 40 | // The below fields mirror what's seen on handshakePacket 41 | udtVer uint32 42 | initPktSeq uint32 43 | maxPktSize uint32 44 | maxFlowWinSize uint32 45 | sockType uint32 46 | sockId uint32 47 | synCookie uint32 48 | sockAddr net.IP 49 | } 50 | 51 | /******************************************************************************* 52 | Implementation of net.Conn interface 53 | *******************************************************************************/ 54 | 55 | func (s *udtSocket) Read(p []byte) (n int, err error) { 56 | if s.currDp == nil { 57 | // Grab the next data packet 58 | s.currDp = <-s.dataIn 59 | s.currDpOffset = 0 60 | } 61 | n = copy(p, s.currDp.data[s.currDpOffset:]) 62 | s.currDpOffset += n 63 | if s.currDpOffset >= len(s.currDp.data) { 64 | // we've exhausted the current data packet, reset to nil 65 | s.currDp = nil 66 | } 67 | 68 | return 69 | } 70 | 71 | // TODO: implement ReadFrom and WriteTo for performance(?) 72 | 73 | func (s *udtSocket) Write(p []byte) (n int, err error) { 74 | s.pktSeq += 1 75 | dp := &dataPacket{ 76 | seq: s.pktSeq, 77 | ts: uint32(time.Now().Sub(s.created) / time.Microsecond), 78 | dstSockId: s.sockId, 79 | data: p, 80 | } 81 | s.dataOut.push(dp) 82 | return 83 | } 84 | 85 | func (s *udtSocket) Close() (err error) { 86 | // TODO: implement 87 | return 88 | } 89 | 90 | func (s *udtSocket) LocalAddr() net.Addr { 91 | return s.m.laddr 92 | } 93 | 94 | func (s *udtSocket) RemoteAddr() net.Addr { 95 | return s.raddr 96 | } 97 | 98 | func (s *udtSocket) SetDeadline(t time.Time) error { 99 | // TODO: implement 100 | return nil 101 | } 102 | 103 | func (s *udtSocket) SetReadDeadline(t time.Time) error { 104 | // TODO: implement 105 | return nil 106 | } 107 | 108 | func (s *udtSocket) SetWriteDeadline(t time.Time) error { 109 | // TODO: implement 110 | return nil 111 | } 112 | 113 | /******************************************************************************* 114 | Private functions 115 | *******************************************************************************/ 116 | 117 | /* 118 | nextSendTime returns the ts of the next data packet with the lowest ts of 119 | queued packets, or math.MaxUint32 if no packets are queued. 120 | */ 121 | func (s *udtSocket) nextSendTime() (ts uint32) { 122 | p := s.dataOut.peek() 123 | if p != nil { 124 | return p.sendTime() 125 | } else { 126 | return math.MaxUint32 127 | } 128 | } 129 | 130 | /** 131 | newUdtSocket creates a new UDT socket based on an initial handshakePacket. 132 | */ 133 | func newServerSocket(m *multiplexer, raddr *net.UDPAddr, p *handshakePacket) (s *udtSocket, err error) { 134 | s = &udtSocket{ 135 | m: m, 136 | raddr: raddr, 137 | boundWriter: &boundUDPWriter{m.conn, raddr}, 138 | sockState: sock_state_new, 139 | udtVer: p.udtVer, 140 | initPktSeq: p.initPktSeq, 141 | maxPktSize: p.maxPktSize, 142 | maxFlowWinSize: p.maxFlowWinSize, 143 | sockType: p.sockType, 144 | sockId: p.sockId, 145 | sockAddr: raddr.IP, 146 | synCookie: randUint32(), 147 | dataOut: newPacketQueue(), 148 | } 149 | 150 | return 151 | } 152 | 153 | func newClientSocket(m *multiplexer, sockId uint32) (s *udtSocket, err error) { 154 | raddr := (m.conn.RemoteAddr()).(*net.UDPAddr) 155 | s = &udtSocket{ 156 | m: m, 157 | raddr: raddr, 158 | boundWriter: m.conn, 159 | sockState: sock_state_new, 160 | udtVer: 4, 161 | initPktSeq: randUint32(), 162 | maxPktSize: max_packet_size, 163 | maxFlowWinSize: 8192, // todo: figure out if/how we should calculate this and/or configure it 164 | sockType: STREAM, 165 | sockId: sockId, 166 | sockAddr: raddr.IP, 167 | dataOut: newPacketQueue(), 168 | } 169 | 170 | return 171 | } 172 | 173 | /******************************************************************************* 174 | Lifecycle functions 175 | *******************************************************************************/ 176 | 177 | func (s *udtSocket) initHandshake() { 178 | p := handshakePacket{ 179 | udtVer: s.udtVer, 180 | sockType: s.sockType, 181 | initPktSeq: s.initPktSeq, 182 | maxPktSize: s.maxPktSize, 183 | maxFlowWinSize: s.maxFlowWinSize, 184 | connType: 1, 185 | sockId: s.sockId, 186 | sockAddr: s.sockAddr, 187 | } 188 | s.sockState = sock_state_handshake_init 189 | s.m.ctrlOut <- &p 190 | } 191 | 192 | func (s *udtSocket) respondInitHandshake() { 193 | p := handshakePacket{ 194 | h: header{ 195 | dstSockId: s.sockId, 196 | }, 197 | udtVer: s.udtVer, 198 | sockType: 1, 199 | sockId: s.sockId, 200 | } 201 | s.sockState = sock_state_handshake_init 202 | s.m.ctrlOut <- &p 203 | } 204 | --------------------------------------------------------------------------------