Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 2 additions & 10 deletions go/netcode/README.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,13 @@
Draft Implementation of netcode.io for Go
Implementation of netcode.io for Go
=========================================

This is the main repository for the Go implementation of [netcode.io](https://netcode.io). This repository and the API are highly violatile until the client and server implementations have been completed.
This is the main repository for the Go implementation of [netcode.io](https://netcode.io).

## Dependencies
[https://godoc.org/golang.org/x/crypto/chacha20poly1305](https://godoc.org/golang.org/x/crypto/chacha20poly1305). Note that this has been vendored so it should not be necessary to retrieve any packages outside of netcode.

## Documentation
[godocs](https://godoc.org/github.com/networkprotocol/netcode.io/go/netcode/)

## TODO
- More performance testing, possibly change synchronization method.

## Completed
- Implemented packet and token portion of protocol, verified to work with C server implementation.
- Implemented initial server
- Implement initial client

## Author
[Isaac Dawson](https://github.com/wirepair)
106 changes: 106 additions & 0 deletions go/netcode/client_manager_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
package netcode

import (
"net"
"testing"
)

func TestNewClientManager(t *testing.T) {
timeout := float64(4)
maxClients := 2
cm := NewClientManager(timeout, maxClients)

if cm.FindFreeClientIndex() == -1 {
t.Fatalf("free client index should not return -1 when empty")
}

addr := &net.UDPAddr{}
if cm.FindClientIndexByAddress(addr) != -1 {
t.Fatalf("client index by empty address should return -1")
}

if cm.FindClientIndexById(0) != -1 {
t.Fatalf("should not have any clients")
}

}

func TestAddEncryptionMapping(t *testing.T) {
timeout := float64(4)
maxClients := 2
servers := make([]net.UDPAddr, 1)
servers[0] = net.UDPAddr{IP: net.ParseIP("::1"), Port: 40000}

addr := &net.UDPAddr{IP: net.ParseIP("::1"), Port: 62424}
addr2 := &net.UDPAddr{IP: net.ParseIP("::1"), Port: 62425}
overAddrs := make([]*net.UDPAddr, (maxClients)*8)
for i := 0; i < len(overAddrs); i++ {
overAddrs[i] = &net.UDPAddr{IP: net.ParseIP("::1"), Port: 6000 + i}
}

connectToken := testGenerateConnectToken(servers, TEST_PRIVATE_KEY, t)

cm := NewClientManager(timeout, maxClients)

serverTime := float64(1.0)
expireTime := float64(1.1)
if !cm.AddEncryptionMapping(connectToken.PrivateData, addr, serverTime, expireTime) {
t.Fatalf("error adding encryption mapping\n")
}

// add it again
if !cm.AddEncryptionMapping(connectToken.PrivateData, addr, serverTime, expireTime) {
t.Fatalf("error re-adding encryption mapping\n")
}

if !cm.AddEncryptionMapping(connectToken.PrivateData, addr2, serverTime, expireTime) {
t.Fatalf("error adding 2nd encryption mapping\n")
}

failed := false
for i := 0; i < len(overAddrs); i++ {
if cm.AddEncryptionMapping(connectToken.PrivateData, overAddrs[i], serverTime, expireTime) {
failed = true
}
}

if !failed {
t.Fatalf("error we added more encryption mappings than should have been allowed\n")
}
}

func TestAddEncryptionMappingTimeout(t *testing.T) {
timeout := float64(4)
maxClients := 2
servers := make([]net.UDPAddr, 1)
servers[0] = net.UDPAddr{IP: net.ParseIP("::1"), Port: 40000}

addr := &net.UDPAddr{IP: net.ParseIP("::1"), Port: 62424}
connectToken := testGenerateConnectToken(servers, TEST_PRIVATE_KEY, t)

cm := NewClientManager(timeout, maxClients)

serverTime := float64(1.0)
expireTime := float64(1.1)

if !cm.AddEncryptionMapping(connectToken.PrivateData, addr, serverTime, expireTime) {
t.Fatalf("error adding encryption mapping\n")
}

idx := cm.FindEncryptionEntryIndex(addr, serverTime)
if idx == -1 {
t.Fatalf("error getting encryption entry index\n")
}

if !cm.SetEncryptionEntryExpiration(idx, float64(0.1)) {
t.Fatalf("error setting entry expiration\n")
}

// remove the client.
cm.CheckTimeouts(serverTime)

idx = cm.FindEncryptionEntryIndex(addr, serverTime)
if idx != -1 {
t.Fatalf("error got encryption entry index when it should have been removed\n")
}
}
7 changes: 0 additions & 7 deletions go/netcode/connect_token.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,6 @@ import (
"time"
)

// ip types used in serialization of server addresses
const (
ADDRESS_NONE = iota
ADDRESS_IPV4
ADDRESS_IPV6
)

// number of bytes for connect tokens
const CONNECT_TOKEN_BYTES = 2048

Expand Down
7 changes: 7 additions & 0 deletions go/netcode/connect_token_shared.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@ import (
"strconv"
)

// ip types used in serialization of server addresses
const (
ADDRESS_NONE = iota
ADDRESS_IPV4
ADDRESS_IPV6
)

// This struct contains data that is shared in both public and private parts of the
// connect token.
type sharedTokenData struct {
Expand Down
6 changes: 3 additions & 3 deletions go/netcode/packet.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,6 @@ const MAX_SERVERS_PER_CONNECT = 32

const VERSION_INFO = "NETCODE 1.00\x00"

// Used for determining the type of packet, part of the serialization protocol
type PacketType uint8

const (
ConnectionRequest PacketType = iota
ConnectionDenied
Expand All @@ -34,6 +31,9 @@ const (
ConnectionDisconnect
)

// Used for determining the type of packet, part of the serialization protocol
type PacketType uint8

func (p PacketType) Peek(packetBuffer []byte) PacketType {
prefix := uint8(packetBuffer[0])
return PacketType(prefix & 0xF)
Expand Down