// Write writes data to connection. func (c *Conn) Write(b []byte) (n int, err error) { // buf = [iv] + [encrypt data] // [iv] exists only at beginning of connection, else [iv] is empty. var buf = c.writeBuf var encryptData = buf dataLen := len(b) if c.iv == nil { utils.Debugf("Write iv") c.writeStart = true dataLen += c.info.ivLen if dataLen > len(buf) { buf = make([]byte, dataLen) } iv := c.initEncStream() copy(buf, iv) encryptData = buf[c.info.ivLen:] } else if !c.writeStart { c.initEncStream() utils.Debugf("init enc") c.writeStart = true } if dataLen > len(buf) { buf = make([]byte, dataLen) encryptData = buf } c.encrypt(encryptData, b) return c.Conn.Write(buf[:dataLen]) }
func (c *Mika) Read(b []byte) (n int, err error) { // recover() avoid panic var buf = c.readBuf // dataLen := len(b) if c.serverSide { // ------------------------------ // | dataLen | hmac | user data | // ------------------------------ // | 2 | 10 | Variable | // ------------------------------ const datePos = 12 if _, err := io.ReadFull(c.Conn, buf[:datePos]); err != nil { return 0, err } dataLen := int(binary.BigEndian.Uint16(buf[:2])) expectedhmac := make([]byte, 10) copy(expectedhmac, buf[2:datePos]) utils.Debugf("dataLen %d expected len %d", dataLen, len(b)) if dataLen > len(b) { utils.Errorf("Date len %d large than b %d", dataLen, len(b)) return 0, fmt.Errorf("Too large data") } if _, err := io.ReadFull(c.Conn, b[:dataLen]); err != nil { utils.Errorf("Read error %s", err) return 0, err } c.header.ChunkID++ utils.Debugf("ChunkID %d, receive %d datas, expectedhmac %#v ", c.header.ChunkID, dataLen, expectedhmac) _, hmac := otaReqChunkAuth(c.iv, c.header.ChunkID, b[:dataLen]) if !bytes.Equal(hmac, expectedhmac) { utils.Errorf("Hmac %#v mismatch with %#v, remote addr %s", hmac, expectedhmac, c.RemoteAddr()) return 0, fmt.Errorf("Hmac mismatch") } // if dataLen > b // we should buffer remains. return dataLen, nil } return c.Conn.Read(b) }
// Read reads data from connection. func (c *Conn) Read(b []byte) (n int, err error) { if c.iv == nil { utils.Debugf("Read iv") iv := make([]byte, c.info.ivLen) if _, err := io.ReadFull(c.Conn, iv); err != nil { return 0, err } c.initDecStream(iv) c.readStart = true } else if !c.readStart { c.initDecStream(c.iv) c.readStart = true } var buf = c.readBuf n, err = c.Conn.Read(buf[:len(b)]) if err != nil { return } c.decrypt(b, buf[:n]) return }
// Write writes data to connection. func (c *Mika) Write(b []byte) (n int, err error) { buf := b dataLen := len(b) if !c.serverSide { // ------------------------------ // | dataLen | hmac | user data | // ------------------------------ // | 2 | 10 | Variable | // ------------------------------ c.header.ChunkID++ // hmac := HmacSha1(append(c.iv, c.key...), b) // len(hmac)+dataLen = 12 dataLen += 12 // utils.Debugf("Send %d hmac %#v", dataLen-12, hmac) // utils.Debugf("Data write %#v", b) var hmac []byte buf, hmac = otaReqChunkAuth(c.iv, c.header.ChunkID, b) utils.Debugf("Send %d data, chunkID %d, hmac %#v", dataLen-12, c.header.ChunkID, hmac) // utils.Debugf("Data after write %#v", buf[12:dataLen]) } return c.Conn.Write(buf[:dataLen]) }
// Close closes connection and releases buf. // TODO check close state to avoid close twice. func (c *Conn) Close() error { leakyBuf.Put(c.writeBuf) leakyBuf.Put(c.readBuf) utils.Debugf("Connection %s closed", c.RemoteAddr()) return c.Conn.Close() }