go-teeworlds-protocol/teeworlds.go
ChillerDragon 72bf459d79 Refactor: separate packet parsing and connection state
Computing a response to a packet is now separate from unpacking a packet
2024-06-22 12:25:29 +08:00

130 lines
2.6 KiB
Go

package main
import (
"bufio"
"fmt"
"net"
"os"
"strconv"
"time"
"github.com/teeworlds-go/teeworlds/messages7"
"github.com/teeworlds-go/teeworlds/network7"
"github.com/teeworlds-go/teeworlds/protocol7"
)
const (
maxPacksize = 1400
)
func getConnection(serverIp string, serverPort int) (net.Conn, error) {
conn, err := net.Dial("udp", fmt.Sprintf("%s:%d", serverIp, serverPort))
if err != nil {
fmt.Printf("Some error %v", err)
}
return conn, err
}
func readNetwork(ch chan<- []byte, conn net.Conn) {
buf := make([]byte, maxPacksize)
for {
len, err := bufio.NewReader(conn).Read(buf)
packet := make([]byte, len)
copy(packet[:], buf[:])
if err == nil {
ch <- packet
} else {
fmt.Printf("Some error %v\n", err)
break
}
}
conn.Close()
}
func main() {
ch := make(chan []byte, maxPacksize)
serverIp := "127.0.0.1"
serverPort := 8303
if len(os.Args) > 1 {
if os.Args[1][0] == '-' {
fmt.Println("usage: ./teeworlds [serverIp] [serverPort]")
os.Exit(1)
}
serverIp = os.Args[1]
}
if len(os.Args) > 2 {
var err error
serverPort, err = strconv.Atoi(os.Args[2])
if err != nil {
panic(err)
}
}
conn, err := getConnection(serverIp, serverPort)
if err != nil {
fmt.Printf("error connecting %v\n", err)
os.Exit(1)
}
client := &protocol7.Connection{
ClientToken: [4]byte{0x01, 0x02, 0x03, 0x04},
ServerToken: [4]byte{0xff, 0xff, 0xff, 0xff},
Ack: 0,
Players: make([]protocol7.Player, network7.MaxClients),
}
go readNetwork(ch, conn)
tokenPacket := client.CtrlToken()
conn.Write(tokenPacket.Pack(client))
for {
time.Sleep(10_000_000)
select {
case msg := <-ch:
packet := &protocol7.Packet{}
err := packet.Unpack(msg)
if err != nil {
panic(err)
}
response := client.OnPacket(packet)
if response != nil {
// example of inspecting incoming trafic
for i, _ := range packet.Messages {
var chat *messages7.SvChat
var ok bool
if chat, ok = packet.Messages[i].(*messages7.SvChat); ok {
fmt.Printf("got chat msg: %s\n", chat.Message)
// modify chat if this was a proxy
packet.Messages[i] = chat
}
}
// example of modifying outgoing traffic
for i, msg := range response.Messages {
if msg.MsgId() == network7.MsgCtrlConnect {
var connect *messages7.CtrlConnect
var ok bool
if connect, ok = response.Messages[i].(*messages7.CtrlConnect); ok {
connect.Token = [4]byte{0xaa, 0xaa, 0xaa, 0xaa}
response.Messages[i] = connect
}
}
}
if len(response.Messages) > 0 || response.Header.Flags.Resend {
conn.Write(response.Pack(client))
}
}
default:
// do nothing
}
}
}