Skip to content

Commit

Permalink
Simplified flow control
Browse files Browse the repository at this point in the history
  • Loading branch information
oxtoacart committed Feb 13, 2017
1 parent 76e9c93 commit e9362f9
Show file tree
Hide file tree
Showing 13 changed files with 45 additions and 228 deletions.
98 changes: 0 additions & 98 deletions buffer.go

This file was deleted.

49 changes: 0 additions & 49 deletions buffer_test.go

This file was deleted.

4 changes: 2 additions & 2 deletions crypto.go
Expand Up @@ -87,7 +87,7 @@ func buildClientInitMsg(serverPublicKey *rsa.PublicKey, windowSize int, maxPaddi
ivSize := cipherCode.ivSize()
plainText := make([]byte, 0, winSize+secretSize+ivSize*2)
_windowSize := make([]byte, winSize)
binaryEncoding.PutUint32(_windowSize, uint32(windowSize))
binaryEncoding.PutUint16(_windowSize, uint16(windowSize))
plainText = append(plainText, _windowSize...)
plainText = append(plainText, byte(maxPadding))
plainText = append(plainText, byte(cipherCode))
Expand All @@ -107,7 +107,7 @@ func decodeClientInitMsg(serverPrivateKey *rsa.PrivateKey, msg []byte) (windowSi
return 0, 0, 0, nil, nil, nil, fmt.Errorf("Unable to decrypt init message: %v", err)
}
_windowSize, pt := consume(pt, winSize)
windowSize = int(binaryEncoding.Uint32(_windowSize))
windowSize = int(binaryEncoding.Uint16(_windowSize))
_maxPadding, pt := consume(pt, 1)
maxPadding = int(_maxPadding[0])
_cipherCode, pt := consume(pt, 1)
Expand Down
20 changes: 0 additions & 20 deletions crypto_test.go
Expand Up @@ -13,26 +13,6 @@ import (
"golang.org/x/crypto/chacha20poly1305"
)

func BenchmarkAlloc(b *testing.B) {
source := make([]byte, 8192)
rand.Read(source)
b.ResetTimer()
for i := 0; i < b.N; i++ {
buf := make([]byte, 8192)
copy(buf, source)
}
}

func BenchmarkNoAlloc(b *testing.B) {
source := make([]byte, 8192)
rand.Read(source)
buf := make([]byte, 8192)
b.ResetTimer()
for i := 0; i < b.N; i++ {
copy(buf, source)
}
}

func TestInitAESCTR(t *testing.T) {
doTestInit(t, AES128CTR)
}
Expand Down
6 changes: 1 addition & 5 deletions dialer.go
Expand Up @@ -26,8 +26,7 @@ func Dialer(windowSize int, maxPadding int, maxStreamsPerConn uint16, pool Buffe
// If a new physical connection is needed but can't be established, the dialer
// returns the underlying dial error.
//
// windowSize - transmit window size in bytes. If <= 0, defaults to 500 KB. If
// 81,920, defaults to 81,920.
// windowSize - transmit window size in # of frames. If <= 0, defaults to 50.
//
// maxPadding - maximum random padding to use when necessary.
//
Expand All @@ -45,9 +44,6 @@ func StreamDialer(windowSize int, maxPadding int, maxStreamsPerConn uint16, pool
if windowSize <= 0 {
windowSize = defaultWindowSize
}
if windowSize <= minWindowSize {
windowSize = minWindowSize
}
if maxStreamsPerConn <= 0 || maxStreamsPerConn > maxID {
maxStreamsPerConn = maxID
}
Expand Down
53 changes: 16 additions & 37 deletions lampshade.go
Expand Up @@ -77,12 +77,12 @@
// +---------+-----+---------+--------+--------+---------+---------+
// | Version | Win | Max Pad | Cipher | Secret | Send IV | Recv IV |
// +---------+-----+---------+--------+--------+---------+---------+
// | 1 | 4 | 1 | 1 | 16/32 | 16/12 | 16/12 |
// | 1 | 2 | 1 | 1 | 16/32 | 16/12 | 16/12 |
// +---------+-----+---------+--------+--------+---------+---------+
//
// Version - the version of the protocol (currently 1)
//
// Win - transmit window size in bytes
// Win - transmit window size in # of frames
//
// Max Pad - maximum random padding
//
Expand All @@ -101,13 +101,11 @@
// All frames are encrypted with AES128 in CTR mode, using the secret and IV
// sent in the Init Session message.
//
// Every frame starts with this header:
//
// +--------------+-----------+
// | Message Type | Stream ID |
// +--------------+-----------+
// | 1 | 2 |
// +--------------+-----------+
// +--------------+-----------+----------+--------+
// | Message Type | Stream ID | Data Len | Data |
// +--------------+-----------+----------+--------+
// | 1 | 2 | 2 | <=8192 |
// +--------------+-----------+----------+--------+
//
// Message Type - indicates the message type.
//
Expand All @@ -118,29 +116,10 @@
//
// Stream ID - unique identifier for stream. (last field for ack and rst)
//
// Data and Padding frames include the below after the header:
//
// +----------+--------+
// | Data Len | Data |
// +----------+--------+
// | 2 | <=8192 |
// +----------+--------+
//
// Data Len - length of data.
// Data Len - length of data (or # of frames acked for ACK)
//
// Data - data (only used for message type "data" and "padding")
//
// ACK frames include the below after the header:
//
// +-------+
// | Bytes |
// +-------+
// | 4 |
// +-------+
//
// Bytes - additional number of bytes that receiver is willing to receive,
// signed 32 bit integer
//
// Padding:
//
// - used only when there weren't enough pending writes to coalesce
Expand All @@ -153,19 +132,20 @@
//
// Flow control is managed with windows similarly to HTTP/2.
//
// - windows are sized based on # of frames rather than # of bytes
// - both ends of a stream maintain a transmit window
// - the window is initialized based on the win parameter in the client
// init message
// - as the sender transmits data, its transmit window decreases by the
// amount of data sent (not including headers)
// number of frames sent (not including headers)
// - if the sender's transmit window reaches 0, it stalls
// - as the receiver's buffers free up, it sends ACKs to the sender that
// instruct it to increase its transmit window by a given amount
// - blocked senders become unblocked when their transmit window exceeds 0
// again
// - if the client requests a window larger than what the server is willing
// to buffer, the server can adjust the window by sending an ACK with a
// negative bytes value
// negative value
//
package lampshade

Expand All @@ -182,7 +162,7 @@ const (
// client init message
clientInitSize = 256
versionSize = 1
winSize = 4
winSize = 2
maxPaddingSize = 1

protocolVersion1 = 1
Expand Down Expand Up @@ -210,8 +190,7 @@ const (
frameTypeRST = 3

ackRatio = 10 // ack every 1/10 of window
minWindowSize = MaxDataLen * ackRatio
defaultWindowSize = 500 * 1024 // 500 KB
defaultWindowSize = 50
maxID = (2 << 15) - 1

coalesceThreshold = 1500 // basically this is the practical TCP MTU for anything traversing Ethernet
Expand Down Expand Up @@ -335,12 +314,12 @@ func frameType(header []byte) byte {
return header[0]
}

func ackWithBytes(header []byte, bytes int32) []byte {
// note - header and bytes field are reversed to match the usual format for
func ackWithFrames(header []byte, frames int16) []byte {
// note - header and frames field are reversed to match the usual format for
// data frames
ack := make([]byte, ackFrameSize)
copy(ack[winSize:], header)
ack[winSize] = frameTypeACK
binaryEncoding.PutUint32(ack, uint32(bytes))
binaryEncoding.PutUint16(ack, uint16(frames))
return ack
}
4 changes: 2 additions & 2 deletions lampshade_test.go
Expand Up @@ -453,7 +453,7 @@ func feed(t *testing.T, conn net.Conn) {
}
}

func BenchmarkConnMux(b *testing.B) {
func BenchmarkLampshade(b *testing.B) {
pk, err := keyman.GeneratePK(2048)
if err != nil {
b.Fatal(err)
Expand All @@ -465,7 +465,7 @@ func BenchmarkConnMux(b *testing.B) {
}
lst := WrapListener(_lst, NewBufferPool(100), pk.RSA())

conn, err := Dialer(25, maxPadding, 0, NewBufferPool(100), AES128CTR, &pk.RSA().PublicKey, func() (net.Conn, error) {
conn, err := Dialer(25, maxPadding, 0, NewBufferPool(100), ChaCha20, &pk.RSA().PublicKey, func() (net.Conn, error) {
return net.Dial("tcp", lst.Addr().String())
})()
if err != nil {
Expand Down
1 change: 1 addition & 0 deletions listener.go
Expand Up @@ -31,6 +31,7 @@ type listener struct {
// serverPrivateKey - if provided, this listener will expect connections to use
// encryption
func WrapListener(wrapped net.Listener, pool BufferPool, serverPrivateKey *rsa.PrivateKey) net.Listener {
// TODO: add a maxWindowSize
l := &listener{
wrapped: wrapped,
pool: pool,
Expand Down

0 comments on commit e9362f9

Please sign in to comment.