Skip to content

Commit

Permalink
improve padding connection's io performance
Browse files Browse the repository at this point in the history
  • Loading branch information
IrineSistiana committed Sep 20, 2020
1 parent 50b42dc commit 022820e
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 12 deletions.
11 changes: 4 additions & 7 deletions core/conn_tunnel.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,14 +120,11 @@ func copyBuffer(dst net.Conn, src net.Conn, buf []byte, timeout time.Duration, t
tc.setDeadline(src, time.Now().Add(timeout))
nr, er := src.Read(buf)
if er == nil { // only pad when src is healthy(no err)
if ps, ok := src.(*paddingConn); ok { // if src needs to pad
if ps.writePaddingEnabled() && time.Since(lastPadding) > paddingIntervalThreshold { // time to pad
if ps, ok := src.(*paddingConn); ok && ps.paddingOnWrite {
// don not pad when read is continuous
if time.Since(previousRead) > paddingIntervalThreshold {
tc.setDeadline(ps, time.Now().Add(timeout))
_, err := ps.writePadding(defaultGetPaddingSize())
if err != nil {
return written, fmt.Errorf("write padding data: %v", err)
}
lastPadding = time.Now()
ps.tryWritePaddingInOtherGoRoutine(randomPaddingSize())
}
}
}
Expand Down
51 changes: 51 additions & 0 deletions core/locker.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Copyright (C) 2020, IrineSistiana
//
// This file is part of simple-tls.
//
// simple-tls is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// simple-tls is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

package core

type locker struct {
c chan struct{}
}

func newLocker() *locker {
l := &locker{
c: make(chan struct{}, 1),
}
l.c <- struct{}{}
return l
}

func (l *locker) lock() {
<-l.c
}

func (l *locker) tryLock() bool {
select {
case <-l.c:
return true
default:
return false
}
}

func (l *locker) unlock() {
select {
case l.c <- struct{}{}:
default:
panic("locker: unlocked twice")
}
}
25 changes: 20 additions & 5 deletions core/padding.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ func (c *paddingConn) Write(b []byte) (n int, err error) {
if !c.paddingOnWrite {
return c.Conn.Write(b)
}
return c.writeFrame(headerData, b)
return c.writeFrame(headerData, b, false)
}

var errPaddingDisabled = errors.New("connection padding opt is disabled")
Expand All @@ -140,15 +140,30 @@ func (c *paddingConn) writePadding(l uint16) (n int, err error) {
if !c.paddingOnWrite {
return 0, errPaddingDisabled
}
return c.writeFrame(headerPadding, zeros[:l])
return c.writeFrame(headerPadding, zeros[:l], false)
}

func (c *paddingConn) tryWritePaddingInOtherGoRoutine(l uint16) {
if !c.paddingOnWrite {
return
}

if c.wl.tryLock() == true {
go func() {
c.writeFrame(headerPadding, zeros[:l], true)
c.wl.unlock()
}()
}
}

// wBufPool is a 64Kb buffer pool
var wBufPool = sync.Pool{New: func() interface{} { return make([]byte, 0xffff) }}

func (c *paddingConn) writeFrame(t frameType, b []byte) (n int, err error) {
c.wl.Lock()
defer c.wl.Unlock()
func (c *paddingConn) writeFrame(t frameType, b []byte, disableLocker bool) (n int, err error) {
if !disableLocker {
c.wl.lock()
defer c.wl.unlock()
}

// Note:
// We try to align this to tls frame. So, the largest frame here is 0xffff - 3 bytes.
Expand Down

0 comments on commit 022820e

Please sign in to comment.