diff --git a/common/alloc/buffer.go b/common/alloc/buffer.go index eea2866c2..96de75871 100644 --- a/common/alloc/buffer.go +++ b/common/alloc/buffer.go @@ -63,13 +63,8 @@ func (b *Buffer) Append(data []byte) *Buffer { // Prepend prepends bytes in front of the buffer. Caller must ensure total bytes prepended is // no more than 16 bytes. func (b *Buffer) Prepend(data []byte) *Buffer { - newoffset := b.offset - len(data) - if newoffset < 0 { - newoffset = 0 - } - copy(b.head[newoffset:], data) - b.Value = b.head[newoffset : b.offset+len(b.Value)] - b.offset = newoffset + b.SliceBack(len(data)) + copy(b.Value, data) return b } @@ -89,6 +84,16 @@ func (b *Buffer) SliceFrom(from int) *Buffer { return b } +func (b *Buffer) SliceBack(offset int) *Buffer { + newoffset := b.offset - offset + if newoffset < 0 { + newoffset = 0 + } + b.Value = b.head[newoffset : b.offset+len(b.Value)] + b.offset = newoffset + return b +} + // Len returns the length of the buffer content. func (b *Buffer) Len() int { return len(b.Value) diff --git a/proxy/shadowsocks/shadowsocks.go b/proxy/shadowsocks/shadowsocks.go index d31fed3d2..8878aca6a 100644 --- a/proxy/shadowsocks/shadowsocks.go +++ b/proxy/shadowsocks/shadowsocks.go @@ -187,20 +187,18 @@ func (this *Shadowsocks) handleConnection(conn *hub.TCPConn) { var writeFinish sync.Mutex writeFinish.Lock() go func() { - firstChunk := alloc.NewBuffer().Slice(0, this.config.Cipher.IVSize()) - defer firstChunk.Release() - - writer, err := this.config.Cipher.NewEncodingStream(key, firstChunk.Value, conn) - if err != nil { - log.Error("Shadowsocks: Failed to create encoding stream: ", err) - return - } - if payload, ok := <-ray.InboundOutput(); ok { - firstChunk.Append(payload.Value) - payload.Release() + payload.SliceBack(16) + rand.Read(payload.Value[:16]) - writer.Write(firstChunk.Value) + writer, err := this.config.Cipher.NewEncodingStream(key, payload.Value[:16], conn) + if err != nil { + log.Error("Shadowsocks: Failed to create encoding stream: ", err) + return + } + + writer.Write(payload.Value) + payload.Release() v2io.ChanToWriter(writer, ray.InboundOutput()) } writeFinish.Unlock()