kcp-go
kcp-go copied to clipboard
encrypt时并发读写同一个block的encbuf导致重传或超时
type aesBlockCrypt struct {
encbuf [aes.BlockSize]byte
decbuf [2 * aes.BlockSize]byte
block cipher.Block
}
block, _ = kcp.NewAESBlockCrypt(aesKey)
listener, err := kcp.ListenWithOptions(port, block, 0, 0)
由于listener使用了同一个block的encbuf进行encrypt,当多个updSession同时output给客户端时,会并发调用Encrypt,导致encbuf同时被多个goroute读写,encrypt后的数据不对,客户端校验数据失败导致重传或超时
后面文档说明一下不能并发
func TestEncrypt(t *testing.T) {
block, _ := kcp.NewAESBlockCrypt(make([]byte, 32))
src := make([]byte, 128)
for k := range src {
src[k] = byte(k)
}
dst := make([]byte, 128)
block.Encrypt(dst, src)
closeCh := make(chan struct{})
for i := 0; i < 2; i++ {
go func() {
for {
select {
case <-closeCh:
return
default:
dst1 := make([]byte, 128)
block.Encrypt(dst1, src)
if bytes.Compare(dst, dst1) != 0 {
t.Errorf("not equal")
close(closeCh)
}
}
}
}()
}
<-closeCh
}
上述TestEncrypt用于测试并发Encrypt;
func (s *UDPSession) output(buf []byte) {
...
s.block.Encrypt(ecc[k], ecc[k])
...
}
当多个UDPSession同时调用output方法,同样会出现上述‘not equal’
UDPSession的WriteBuffers和Close是加了锁的,直接使用UDPSession的接口,不会有你这里提到的并发问题,这也不能算是kcp-go的问题 如果你想自己操作Block,应该由你自己对Block封装的代码来保证一致性