diff options
author | Yawning Angel <yawning@schwanenlied.me> | 2014-05-14 06:27:41 +0000 |
---|---|---|
committer | Yawning Angel <yawning@schwanenlied.me> | 2014-05-14 06:27:41 +0000 |
commit | 731a926172dfd043a00ec2015f07af8f4970f7f1 (patch) | |
tree | 70c131ce0b5b25a013de6d2f8b3b671727cd9825 /obfs4.go | |
parent | 582aa3a366cb06bf793440f62fcf3d54b85d8270 (diff) |
Implement the io.WriterTo interface.
Diffstat (limited to 'obfs4.go')
-rw-r--r-- | obfs4.go | 52 |
1 files changed, 46 insertions, 6 deletions
@@ -31,6 +31,7 @@ package obfs4 import ( "bytes" "fmt" + "io" "net" "syscall" "time" @@ -55,7 +56,7 @@ const ( type Obfs4Conn struct { conn net.Conn - probDist *wDist + lenProbDist *wDist encoder *framing.Encoder decoder *framing.Decoder @@ -72,7 +73,7 @@ type Obfs4Conn struct { func (c *Obfs4Conn) calcPadLen(burstLen int) int { tailLen := burstLen % framing.MaximumSegmentLength - toPadTo := c.probDist.sample() + toPadTo := c.lenProbDist.sample() ret := 0 if toPadTo >= tailLen { @@ -258,8 +259,10 @@ func (c *Obfs4Conn) Read(b []byte) (n int, err error) { } for c.receiveDecodedBuffer.Len() == 0 { - err = c.consumeFramedPackets() - if err != nil { + _, err = c.consumeFramedPackets(nil) + if err == framing.ErrAgain { + continue + } else if err != nil { return } } @@ -268,6 +271,43 @@ func (c *Obfs4Conn) Read(b []byte) (n int, err error) { return } +func (c *Obfs4Conn) WriteTo(w io.Writer) (n int64, err error) { + if !c.isOk { + return 0, syscall.EINVAL + } + + wrLen := 0 + + // If there is buffered payload from earlier Read() calls, write. + if c.receiveDecodedBuffer.Len() > 0 { + wrLen, err = w.Write(c.receiveDecodedBuffer.Bytes()) + if wrLen < int(c.receiveDecodedBuffer.Len()) { + c.isOk = false + return int64(wrLen), io.ErrShortWrite + } else if err != nil { + c.isOk = false + return int64(wrLen), err + } + c.receiveDecodedBuffer.Reset() + } + + for { + wrLen, err = c.consumeFramedPackets(w) + n += int64(wrLen) + if err == framing.ErrAgain { + continue + } else if err != nil { + // io.EOF is treated as not an error. + if err == io.EOF { + err = nil + } + break + } + } + + return +} + func (c *Obfs4Conn) Write(b []byte) (int, error) { chopBuf := bytes.NewBuffer(b) buf := make([]byte, maxPacketPayloadLength) @@ -394,7 +434,7 @@ func Dial(network, address, nodeID, publicKey string) (net.Conn, error) { // Connect to the peer. c := new(Obfs4Conn) - c.probDist, err = newWDist(nil, 0, framing.MaximumSegmentLength) + c.lenProbDist, err = newWDist(nil, 0, framing.MaximumSegmentLength) if err != nil { return nil, err } @@ -434,7 +474,7 @@ func (l *Obfs4Listener) Accept() (net.Conn, error) { cObfs.conn = c cObfs.isServer = true cObfs.listener = l - cObfs.probDist, err = newWDist(nil, 0, framing.MaximumSegmentLength) + cObfs.lenProbDist, err = newWDist(nil, 0, framing.MaximumSegmentLength) if err != nil { c.Close() return nil, err |