import (
"bufio"
+ "bytes"
"context"
"crypto/rand"
"errors"
func (cl *Client) dialTCP(ctx context.Context, addr string) (c net.Conn, err error) {
d := net.Dialer{
- // LocalAddr: cl.tcpListener.Addr(),
+ // LocalAddr: cl.tcpListener.Addr(),
}
c, err = d.DialContext(ctx, "tcp", addr)
countDialResult(err)
func (cl *Client) newConnection(nc net.Conn) (c *connection) {
c = &connection{
- conn: nc,
-
+ conn: nc,
Choked: true,
PeerChoked: true,
PeerMaxRequests: 250,
+ writeBuffer: new(bytes.Buffer),
}
c.writerCond.L = &cl.mu
c.setRW(connStatsReadWriter{nc, &cl.mu, c})
pieceInclination []int
pieceRequestOrder prioritybitmap.PriorityBitmap
- writeBuffer bytes.Buffer
+ writeBuffer *bytes.Buffer
uploadTimer *time.Timer
writerCond sync.Cond
}
// connection is writable.
func (cn *connection) writer(keepAliveTimeout time.Duration) {
var (
- // buf bytes.Buffer
- lastWrite time.Time = time.Now()
+ lastWrite time.Time = time.Now()
+ keepAliveTimer *time.Timer
)
- var keepAliveTimer *time.Timer
keepAliveTimer = time.AfterFunc(keepAliveTimeout, func() {
cn.mu().Lock()
defer cn.mu().Unlock()
defer cn.mu().Unlock()
defer cn.Close()
defer keepAliveTimer.Stop()
+ frontBuf := new(bytes.Buffer)
for {
if cn.closed.IsSet() {
return
cn.writerCond.Wait()
continue
}
- var buf bytes.Buffer
- buf.Write(cn.writeBuffer.Bytes())
- cn.writeBuffer.Reset()
+ // Flip the buffers.
+ frontBuf, cn.writeBuffer = cn.writeBuffer, frontBuf
cn.mu().Unlock()
- // log.Printf("writing %d bytes", buf.Len())
- n, err := cn.w.Write(buf.Bytes())
+ n, err := cn.w.Write(frontBuf.Bytes())
cn.mu().Lock()
if n != 0 {
lastWrite = time.Now()
if err != nil {
return
}
- if n != buf.Len() {
+ if n != frontBuf.Len() {
panic("short write")
}
- buf.Reset()
+ frontBuf.Reset()
}
}
// Have that would potentially alter it.
func TestSendBitfieldThenHave(t *testing.T) {
r, w := io.Pipe()
- c := &connection{
- t: &Torrent{
- cl: &Client{},
- },
- r: r,
- w: w,
- }
- c.writerCond.L = &c.t.cl.mu
+ var cl Client
+ cl.initLogger()
+ c := cl.newConnection(nil)
+ c.setTorrent(cl.newTorrent(metainfo.Hash{}, nil))
+ c.r = r
+ c.w = w
go c.writer(time.Minute)
c.mu().Lock()
c.Bitfield([]bool{false, true, false})