11 "bitbucket.org/anacrolix/go.torrent/peer_protocol"
14 // Maintains the state of a connection with a peer.
15 type connection struct {
18 mu sync.Mutex // Only for closing.
19 post chan encoding.BinaryMarshaler
22 // Stuff controlled by the local peer.
25 Requests map[request]struct{}
27 // Stuff controlled by the remote peer.
31 PeerRequests map[request]struct{}
32 PeerExtensions [8]byte
34 PeerMaxRequests int // Maximum pending requests the peer allows.
37 func (c *connection) Close() {
48 func (c *connection) getClosed() bool {
54 func (c *connection) PeerHasPiece(index peer_protocol.Integer) bool {
55 if c.PeerPieces == nil {
58 return c.PeerPieces[index]
61 func (c *connection) Post(msg encoding.BinaryMarshaler) {
65 // Returns true if more requests can be sent.
66 func (c *connection) Request(chunk request) bool {
67 if len(c.Requests) >= c.PeerMaxRequests {
70 if !c.PeerHasPiece(chunk.Index) {
77 if _, ok := c.Requests[chunk]; !ok {
78 c.Post(peer_protocol.Message{
79 Type: peer_protocol.Request,
85 if c.Requests == nil {
86 c.Requests = make(map[request]struct{}, c.PeerMaxRequests)
88 c.Requests[chunk] = struct{}{}
92 // Returns true if an unsatisfied request was canceled.
93 func (c *connection) PeerCancel(r request) bool {
94 if c.PeerRequests == nil {
97 if _, ok := c.PeerRequests[r]; !ok {
100 delete(c.PeerRequests, r)
104 func (c *connection) Unchoke() {
108 c.Post(peer_protocol.Message{
109 Type: peer_protocol.Unchoke,
114 func (c *connection) SetInterested(interested bool) {
115 if c.Interested == interested {
118 c.Post(peer_protocol.Message{
119 Type: func() peer_protocol.MessageType {
121 return peer_protocol.Interested
123 return peer_protocol.NotInterested
127 c.Interested = interested
131 // Four consecutive zero bytes that comprise a keep alive on the wire.
132 keepAliveBytes [4]byte
135 func (conn *connection) writer() {
136 timer := time.NewTimer(0)
139 if !timer.Reset(time.Minute) {
145 b = keepAliveBytes[:]
146 case b = <-conn.write:
151 _, err := conn.Socket.Write(b)
152 if conn.getClosed() {
162 func (conn *connection) writeOptimizer() {
163 pending := list.New()
165 defer close(conn.write)
168 if pending.Len() == 0 {
172 nextWrite, err = pending.Front().Value.(encoding.BinaryMarshaler).MarshalBinary()
178 case msg, ok := <-conn.post:
182 pending.PushBack(msg)
183 case write <- nextWrite:
184 pending.Remove(pending.Front())