Write() writes the data bytes to the encrypted connection
(data []byte)
| 125 | |
| 126 | // Write() writes the data bytes to the encrypted connection |
| 127 | func (c *EncryptedConn) Write(data []byte) (n int, err error) { |
| 128 | // fallback to regular conn in case encrypted conn is not yet set |
| 129 | if c.send.aead == nil { |
| 130 | return c.conn.Write(data) |
| 131 | } |
| 132 | // thread safety sends |
| 133 | c.send.Lock() |
| 134 | defer c.send.Unlock() |
| 135 | // setup data variables |
| 136 | chunkSize, chunk := 0, []byte(nil) |
| 137 | // loop until no more data to send |
| 138 | for dataSize := len(data); dataSize > 0; dataSize = len(data) { |
| 139 | // a 'buffer pool' saves resources by re-using buffers, take 2 buffers from the pool |
| 140 | cipherTextBuffer, plainTextBuffer := pool.Get(crypto.EncryptedFrameSize), pool.Get(crypto.FrameSize) |
| 141 | // if total data to write can be fit into a single chunk |
| 142 | if dataSize < crypto.MaxDataSize { |
| 143 | chunk = data |
| 144 | data = nil |
| 145 | } else { // else load the next chunk and save the rest of the data |
| 146 | chunk = data[:crypto.MaxDataSize] |
| 147 | data = data[crypto.MaxDataSize:] |
| 148 | } |
| 149 | chunkSize = len(chunk) |
| 150 | // size of data is the first 4 bytes of the message |
| 151 | binary.LittleEndian.PutUint32(plainTextBuffer, uint32(chunkSize)) |
| 152 | // the actual chunk comes after the first 4 bytes |
| 153 | copy(plainTextBuffer[crypto.LengthHeaderSize:], chunk) |
| 154 | // encrypt the plain text into the cipher buffer |
| 155 | c.send.aead.Seal(cipherTextBuffer[:0], c.send.nonce[:], plainTextBuffer, nil) |
| 156 | // increment the 'write state' nonce to follow the security parameters of the AEAD protocol |
| 157 | incrementNonce(c.send.nonce) |
| 158 | // write the cipher text to the underlying connection |
| 159 | if _, er := c.conn.Write(cipherTextBuffer); er != nil { |
| 160 | return 0, ErrFailedWrite(er) |
| 161 | } |
| 162 | // update number of bytes written |
| 163 | n += chunkSize |
| 164 | // release the buffers back into the pool for reuse |
| 165 | pool.Put(cipherTextBuffer) |
| 166 | pool.Put(plainTextBuffer) |
| 167 | } |
| 168 | return |
| 169 | } |
| 170 | |
| 171 | // Read() checks the connection for cipher data bytes, if found, |
| 172 | // the func decrypts and loads them into the 'data' buffer |