package noiseimport (pool)// MaxTransportMsgLength is the Noise-imposed maximum transport message length,// inclusive of the MAC size (16 bytes, Poly1305 for noise-libp2p).constMaxTransportMsgLength = 0xffff// MaxPlaintextLength is the maximum payload size. It is MaxTransportMsgLength// minus the MAC size. Payloads over this size will be automatically chunked.constMaxPlaintextLength = MaxTransportMsgLength - chacha20poly1305.Overhead// LengthPrefixLength is the length of the length prefix itself, which precedes// all transport messages in order to delimit them. In bytes.constLengthPrefixLength = 2// Read reads from the secure connection, returning plaintext data in `buf`.//// Honours io.Reader in terms of behaviour.func ( *secureSession) ( []byte) (int, error) { .readLock.Lock()defer .readLock.Unlock()// 1. If we have queued received bytes: // 1a. If len(buf) < len(queued), saturate buf, update seek pointer, return. // 1b. If len(buf) >= len(queued), copy remaining to buf, release queued buffer back into pool, return. // // 2. Else, read the next message off the wire; next_len is length prefix. // 2a. If len(buf) >= next_len, copy the message to input buffer (zero-alloc path), and return. // 2b. If len(buf) >= (next_len - length of Authentication Tag), get buffer from pool, read encrypted message into it. // decrypt message directly into the input buffer and return the buffer obtained from the pool. // 2c. If len(buf) < next_len, obtain buffer from pool, copy entire message into it, saturate buf, update seek pointer.if .qbuf != nil {// we have queued bytes; copy as much as we can. := copy(, .qbuf[.qseek:]) .qseek += if .qseek == len(.qbuf) {// queued buffer is now empty, reset and release.pool.Put(.qbuf) .qseek, .qbuf = 0, nil }return , nil }// length of the next encrypted message. , := .readNextInsecureMsgLen()if != nil {return0, }// If the buffer is atleast as big as the encrypted message size, // we can read AND decrypt in place.iflen() >= {if := .readNextMsgInsecure([:]); != nil {return0, } , := .decrypt([:0], [:])if != nil {return0, }returnlen(), nil }// otherwise, we get a buffer from the pool so we can read the message into it // and then decrypt in place, since we're retaining the buffer (or a view thereof). := pool.Get()if := .readNextMsgInsecure(); != nil {return0, }if .qbuf, = .decrypt([:0], ); != nil {return0, }// copy as many bytes as we can; update seek pointer. .qseek = copy(, .qbuf)return .qseek, nil}// Write encrypts the plaintext `in` data and sends it on the// secure connection.func ( *secureSession) ( []byte) (int, error) { .writeLock.Lock()defer .writeLock.Unlock()var (int []byte = len() )if < MaxPlaintextLength { = pool.Get( + chacha20poly1305.Overhead + LengthPrefixLength) } else { = pool.Get(MaxTransportMsgLength + LengthPrefixLength) }deferpool.Put()for < { := + MaxPlaintextLengthif > { = } , := .encrypt([:LengthPrefixLength], [:])if != nil {return0, }binary.BigEndian.PutUint16(, uint16(len()-LengthPrefixLength)) _, = .writeMsgInsecure()if != nil {return , } = }return , nil}// readNextInsecureMsgLen reads the length of the next message on the insecureConn channel.func ( *secureSession) () (int, error) { , := io.ReadFull(.insecureReader, .rlen[:])if != nil {return0, }returnint(binary.BigEndian.Uint16(.rlen[:])), }// readNextMsgInsecure tries to read exactly len(buf) bytes into buf from// the insecureConn channel and returns the error, if any.// Ideally, for reading a message, you'd first want to call `readNextInsecureMsgLen`// to determine the size of the next message to be read from the insecureConn channel and then call// this function with a buffer of exactly that size.func ( *secureSession) ( []byte) error { , := io.ReadFull(.insecureReader, )return}// writeMsgInsecure writes to the insecureConn conn.// data will be prefixed with its length in bytes, written as a 16-bit uint in network order.func ( *secureSession) ( []byte) (int, error) {return .insecureConn.Write()}
The pages are generated with Goldsv0.8.2. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds.