mirror of https://github.com/cbeuw/Cloak
Lazy allocation
This commit is contained in:
parent
8a76afabf7
commit
008fd8f0a3
|
|
@ -17,7 +17,9 @@ var ErrTimeout = errors.New("deadline exceeded")
|
|||
|
||||
// The point of a bufferedPipe is that Read() will block until data is available
|
||||
type bufferedPipe struct {
|
||||
// only alloc when on first Read or Write
|
||||
buf *bytes.Buffer
|
||||
|
||||
closed uint32
|
||||
rwCond *sync.Cond
|
||||
rDeadline time.Time
|
||||
|
|
@ -25,7 +27,6 @@ type bufferedPipe struct {
|
|||
|
||||
func NewBufferedPipe() *bufferedPipe {
|
||||
p := &bufferedPipe{
|
||||
buf: new(bytes.Buffer),
|
||||
rwCond: sync.NewCond(&sync.Mutex{}),
|
||||
}
|
||||
return p
|
||||
|
|
@ -34,6 +35,9 @@ func NewBufferedPipe() *bufferedPipe {
|
|||
func (p *bufferedPipe) Read(target []byte) (int, error) {
|
||||
p.rwCond.L.Lock()
|
||||
defer p.rwCond.L.Unlock()
|
||||
if p.buf == nil {
|
||||
p.buf = new(bytes.Buffer)
|
||||
}
|
||||
for {
|
||||
if atomic.LoadUint32(&p.closed) == 1 && p.buf.Len() == 0 {
|
||||
return 0, io.EOF
|
||||
|
|
@ -59,6 +63,9 @@ func (p *bufferedPipe) Read(target []byte) (int, error) {
|
|||
func (p *bufferedPipe) Write(input []byte) (int, error) {
|
||||
p.rwCond.L.Lock()
|
||||
defer p.rwCond.L.Unlock()
|
||||
if p.buf == nil {
|
||||
p.buf = new(bytes.Buffer)
|
||||
}
|
||||
for {
|
||||
if atomic.LoadUint32(&p.closed) == 1 {
|
||||
return 0, io.ErrClosedPipe
|
||||
|
|
|
|||
|
|
@ -164,6 +164,8 @@ func (sesh *Session) closeStream(s *Stream, active bool) error {
|
|||
Closing: C_STREAM,
|
||||
Payload: pad,
|
||||
}
|
||||
|
||||
s.allocIdempot.Do(func() { s.obfsBuf = make([]byte, s.session.SendBufferSize) })
|
||||
i, err := s.session.Obfs(f, s.obfsBuf)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
|||
|
|
@ -28,6 +28,8 @@ type Stream struct {
|
|||
// atomic
|
||||
closed uint32
|
||||
|
||||
// only alloc when writing to the stream
|
||||
allocIdempot sync.Once
|
||||
obfsBuf []byte
|
||||
|
||||
// we assign each stream a fixed underlying TCP connection to utilise order guarantee provided by TCP itself
|
||||
|
|
@ -49,7 +51,6 @@ func makeStream(sesh *Session, id uint32, assignedConnId uint32) *Stream {
|
|||
id: id,
|
||||
session: sesh,
|
||||
recvBuf: recvBuf,
|
||||
obfsBuf: make([]byte, sesh.SendBufferSize),
|
||||
assignedConnId: assignedConnId,
|
||||
}
|
||||
|
||||
|
|
@ -90,12 +91,15 @@ func (s *Stream) Write(in []byte) (n int, err error) {
|
|||
// in the middle of the execution of Write. This may cause the closing frame
|
||||
// to be sent before the data frame and cause loss of packet.
|
||||
//log.Tracef("attempting to write %v bytes to stream %v",len(in),s.id)
|
||||
// todo: forbid concurrent write
|
||||
s.writingM.RLock()
|
||||
defer s.writingM.RUnlock()
|
||||
if s.isClosed() {
|
||||
return 0, ErrBrokenStream
|
||||
}
|
||||
|
||||
s.allocIdempot.Do(func() { s.obfsBuf = make([]byte, s.session.SendBufferSize) })
|
||||
|
||||
for n < len(in) {
|
||||
var framePayload []byte
|
||||
if len(in)-n <= s.session.maxStreamUnitWrite {
|
||||
|
|
|
|||
Loading…
Reference in New Issue