Skip to content

Commit

Permalink
lint
Browse files Browse the repository at this point in the history
  • Loading branch information
xtaci committed Jun 29, 2016
0 parents commit 4976678
Show file tree
Hide file tree
Showing 15 changed files with 3,038 additions and 0 deletions.
24 changes: 24 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Compiled Object files, Static and Dynamic libs (Shared Objects)
*.o
*.a
*.so

# Folders
_obj
_test

# Architecture specific extensions/prefixes
*.[568vq]
[568vq].out

*.cgo1.go
*.cgo2.c
_cgo_defun.c
_cgo_gotypes.go
_cgo_export.*

_testmain.go

*.exe
*.test
*.prof
12 changes: 12 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
language: go
go:
- 1.6
before_install:
- go get github.com/mattn/goveralls
- go get golang.org/x/tools/cmd/cover
install:
- go get github.com/xtaci/kcp-go
before_script:
script:
- $HOME/gopath/bin/goveralls -service=travis-ci
- exit 0
22 changes: 22 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
The MIT License (MIT)

Copyright (c) 2015 Daniel Fu

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

60 changes: 60 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# ***kcp-go*** :pisces:
[![GoDoc][1]][2] [![Powered][9]][10] [![Build Status][3]][4] [![Go Report Card][5]][6] [![Coverage Statusd][7]][8]

[1]: https://godoc.org/github.com/xtaci/kcp-go?status.svg
[2]: https://godoc.org/github.com/xtaci/kcp-go
[3]: https://travis-ci.org/xtaci/kcp-go.svg?branch=master
[4]: https://travis-ci.org/xtaci/kcp-go
[5]: https://goreportcard.com/badge/github.com/xtaci/kcp-go
[6]: https://goreportcard.com/report/github.com/xtaci/kcp-go
[7]: https://coveralls.io/repos/github/xtaci/kcp-go/badge.svg?branch=master
[8]: https://coveralls.io/github/xtaci/kcp-go?branch=master
[9]: https://img.shields.io/badge/KCP-Powered-blue.svg
[10]: https://github.com/skywind3000/kcp

***A full-featured reliable UDP communication library for various usage***

# ***Features*** :zap:
1. Optimized for ***game development***.
1. Compatible with [skywind3000's](https://github.com/skywind3000) C version with modificiations.
1. ***Cache friendly*** and ***Memory optimized*** design in golang.
1. A [session manager](https://github.com/xtaci/kcp-go/blob/master/sess.go) has provided with compatiablity for [net.Conn](https://golang.org/pkg/net/#Conn) and [net.Listener](https://golang.org/pkg/net/#Listener).
1. Support [FEC(Forward Error Correction)](https://en.wikipedia.org/wiki/Forward_error_correction) with [Reed-Solomon Codes](https://en.wikipedia.org/wiki/Reed%E2%80%93Solomon_error_correction)
1. Support packet level encryption with [AES](https://en.wikipedia.org/wiki/Advanced_Encryption_Standard), [TEA](https://en.wikipedia.org/wiki/Tiny_Encryption_Algorithm).

# ***Conventions*** :zap:
1. [UDP](https://en.wikipedia.org/wiki/User_Datagram_Protocol) for packet delivery.
2. ```conv uint32``` in session manager is a ***random number*** initiated by client.
3. KCP doesn't define control messages like SYN/ACK/FIN/RST in TCP, a real world example is to use some ***multiplexing*** protocol over session, such as [yamux](https://github.com/hashicorp/yamux), see [kcptun](https://github.com/xtaci/kcptun) for example.

# ***Examples*** :zap:
Client: [full demo](https://github.com/xtaci/kcptun/blob/master/client/main.go#L231)
```go
kcpconn, err := kcp.DialWithOptions("192.168.0.1:10000", nil, 10, 3)
```
Server: [full demo](https://github.com/xtaci/kcptun/blob/master/server/main.go#L235)
```go
lis, err := kcp.ListenWithOptions(":10000", nil, 10, 3)
```

# ***Performance*** :zap:
```
型号名称: MacBook Pro
型号标识符: MacBookPro12,1
处理器名称: Intel Core i5
处理器速度: 2.7 GHz
处理器数目: 1
核总数: 2
L2 缓存(每个核): 256 KB
L3 缓存: 3 MB
内存: 8 GB
```
```
$ go test -run Speed
new client 127.0.0.1:61165
total recv: 16777216
time for 16MB rtt with encryption 570.41176ms
&{BytesSent:33554432 BytesReceived:33554432 MaxConn:2 ActiveOpens:1 PassiveOpens:1 CurrEstab:1 InErrs:0 InCsumErrors:0 InSegs:42577 OutSegs:42641 OutBytes:48111336 RetransSegs:92 FastRetransSegs:92 LostSegs:0 RepeatSegs:0 FECRecovered:1 FECErrs:0 FECSegs:8514}
PASS
ok github.com/xtaci/kcp-go 0.600s
```
155 changes: 155 additions & 0 deletions crypt.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
package kcp

import (
"crypto/aes"
"crypto/cipher"
"crypto/sha1"

"golang.org/x/crypto/pbkdf2"
"golang.org/x/crypto/tea"
)

var (
initialVector = []byte{167, 115, 79, 156, 18, 172, 27, 1, 164, 21, 242, 193, 252, 120, 230, 107}
saltxor = `sH3CIVoF#rWLtJo6`
)

// BlockCrypt defines encryption/decryption methods for a given byte slice
type BlockCrypt interface {
// Encrypt encrypts the whole block in src into dst.
// Dst and src may point at the same memory.
Encrypt(dst, src []byte)

// Decrypt decrypts the whole block in src into dst.
// Dst and src may point at the same memory.
Decrypt(dst, src []byte)
}

// AESBlockCrypt implements BlockCrypt with AES
type AESBlockCrypt struct {
encbuf []byte
decbuf []byte
block cipher.Block
}

// NewAESBlockCrypt initates AES BlockCrypt by the given key
func NewAESBlockCrypt(key []byte) (BlockCrypt, error) {
c := new(AESBlockCrypt)
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
c.block = block
c.encbuf = make([]byte, aes.BlockSize)
c.decbuf = make([]byte, 2*aes.BlockSize)
return c, nil
}

// Encrypt implements Encrypt interface
func (c *AESBlockCrypt) Encrypt(dst, src []byte) {
encrypt(c.block, dst, src, c.encbuf)
}

// Decrypt implements Decrypt interface
func (c *AESBlockCrypt) Decrypt(dst, src []byte) {
decrypt(c.block, dst, src, c.decbuf)
}

// TEABlockCrypt implements BlockCrypt with TEA
type TEABlockCrypt struct {
encbuf []byte
decbuf []byte
block cipher.Block
}

// NewTEABlockCrypt initate TEA BlockCrypt by the given key
func NewTEABlockCrypt(key []byte) (BlockCrypt, error) {
c := new(TEABlockCrypt)
block, err := tea.NewCipherWithRounds(key, 16)
if err != nil {
return nil, err
}
c.block = block
c.encbuf = make([]byte, tea.BlockSize)
c.decbuf = make([]byte, 2*tea.BlockSize)
return c, nil
}

// Encrypt implements Encrypt interface
func (c *TEABlockCrypt) Encrypt(dst, src []byte) {
encrypt(c.block, dst, src, c.encbuf)
}

// Decrypt implements Decrypt interface
func (c *TEABlockCrypt) Decrypt(dst, src []byte) {
decrypt(c.block, dst, src, c.decbuf)
}

// SimpleXORBlockCrypt implements BlockCrypt with simple xor to a table
type SimpleXORBlockCrypt struct {
xortbl []byte
}

// NewSimpleXORBlockCrypt initate SimpleXORBlockCrypt by the given key
func NewSimpleXORBlockCrypt(key []byte) (BlockCrypt, error) {
c := new(SimpleXORBlockCrypt)
c.xortbl = pbkdf2.Key(key, []byte(saltxor), 32, mtuLimit, sha1.New)
return c, nil
}

// Encrypt implements Encrypt interface
func (c *SimpleXORBlockCrypt) Encrypt(dst, src []byte) {
xorBytes(dst, src, c.xortbl)
}

// Decrypt implements Decrypt interface
func (c *SimpleXORBlockCrypt) Decrypt(dst, src []byte) {
xorBytes(dst, src, c.xortbl)
}

// NoneBlockCrypt simple returns the plaintext
type NoneBlockCrypt struct {
xortbl []byte
}

// NewNoneBlockCrypt initate NoneBlockCrypt by the given key
func NewNoneBlockCrypt(key []byte) (BlockCrypt, error) {
return new(NoneBlockCrypt), nil
}

// Encrypt implements Encrypt interface
func (c *NoneBlockCrypt) Encrypt(dst, src []byte) {}

// Decrypt implements Decrypt interface
func (c *NoneBlockCrypt) Decrypt(dst, src []byte) {}

// packet encryption with local CFB mode
func encrypt(block cipher.Block, dst, src, buf []byte) {
blocksize := block.BlockSize()
tbl := buf[:blocksize]
block.Encrypt(tbl, initialVector)
n := len(src) / blocksize
base := 0
for i := 0; i < n; i++ {
xorWords(dst[base:], src[base:], tbl)
block.Encrypt(tbl, dst[base:])
base += blocksize
}
xorBytes(dst[base:], src[base:], tbl)
}

func decrypt(block cipher.Block, dst, src, buf []byte) {
blocksize := block.BlockSize()
tbl := buf[:blocksize]
next := buf[blocksize:]
block.Encrypt(tbl, initialVector)
n := len(src) / blocksize
base := 0
for i := 0; i < n; i++ {
block.Encrypt(next, src[base:])
xorWords(dst[base:], src[base:], tbl)
tbl, next = next, tbl
base += blocksize
}
xorBytes(dst[base:], src[base:], tbl)
}
56 changes: 56 additions & 0 deletions crypt_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package kcp

import (
"crypto/sha1"
"testing"

"golang.org/x/crypto/pbkdf2"
)

const crypt_key = "testkey"
const crypt_salt = "kcptest"

func TestAES(t *testing.T) {
pass := pbkdf2.Key(key, []byte(salt), 4096, 32, sha1.New)
bc, err := NewAESBlockCrypt(pass)
if err != nil {
t.Fatal(err)
}
data := make([]byte, 4096)
for i := 0; i < 4096; i++ {
data[i] = byte(i & 0xff)
}
bc.Encrypt(data, data)
bc.Decrypt(data, data)
t.Log(data)
}

func TestTEA(t *testing.T) {
pass := pbkdf2.Key(key, []byte(salt), 4096, 16, sha1.New)
bc, err := NewTEABlockCrypt(pass)
if err != nil {
t.Fatal(err)
}
data := make([]byte, 4096)
for i := 0; i < 4096; i++ {
data[i] = byte(i & 0xff)
}
bc.Encrypt(data, data)
bc.Decrypt(data, data)
t.Log(data)
}

func TestSimpleXOR(t *testing.T) {
pass := pbkdf2.Key(key, []byte(salt), 4096, 16, sha1.New)
bc, err := NewSimpleXORBlockCrypt(pass)
if err != nil {
t.Fatal(err)
}
data := make([]byte, 4096)
for i := 0; i < 4096; i++ {
data[i] = byte(i & 0xff)
}
bc.Encrypt(data, data)
bc.Decrypt(data, data)
t.Log(data)
}
Loading

0 comments on commit 4976678

Please sign in to comment.