Skip to content

Commit

Permalink
noxnet: Add proxy for capturing the network data, decode some messages.
Browse files Browse the repository at this point in the history
  • Loading branch information
dennwc committed Aug 29, 2023
1 parent f813887 commit 80a82b0
Show file tree
Hide file tree
Showing 28 changed files with 1,616 additions and 0 deletions.
153 changes: 153 additions & 0 deletions cmd/opennox-packet-decode/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
package main

import (
"encoding/hex"
"encoding/json"
"flag"
"fmt"
"io"
"os"

"github.com/noxworld-dev/opennox-lib/noxnet"
)

var (
fIn = flag.String("i", "network.jsonl", "input file with packet capture")
fOut = flag.String("o", "network-dec.jsonl", "output file for decoded packets")
)

func main() {
flag.Parse()
if err := run(); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
}

func run() error {
f, err := os.Open(*fIn)
if err != nil {
return err
}
defer f.Close()
dec := json.NewDecoder(f)

w, err := os.Create(*fOut)
if err != nil {
return err
}
defer w.Close()
enc := json.NewEncoder(w)

for {
var r RecordIn
err := dec.Decode(&r)
if err == io.EOF {
break
} else if err != nil {
return err
}
r2 := r.Decode()
if err = enc.Encode(r2); err != nil {
return err
}
}
return w.Close()
}

type RecordIn struct {
SrcID uint32 `json:"src_id"`
DstID uint32 `json:"dst_id"`
Src string `json:"src"`
Dst string `json:"dst"`
Data string `json:"data"`
}

func (r RecordIn) Decode() RecordOut {
o := RecordOut{
SrcID: r.SrcID,
DstID: r.DstID,
Src: r.Src,
Dst: r.Dst,
Data: r.Data,
}
raw, err := hex.DecodeString(r.Data)
if err != nil {
return o
}
o.Len = len(raw)
if len(raw) < 2 {
return o
}
hdr, data := raw[:2], raw[2:]
o.Hdr = hex.EncodeToString(hdr)
if hdr[0] == 0xff {
o.SID = 0xff
} else {
o.Reliable = hdr[0]&0x80 != 0
o.SID = hdr[0] &^ 0x80
o.Seq = hdr[1]
}
if len(data) == 1 {
op := noxnet.Op(data[0])
if _, _, err := noxnet.DecodeAnyPacket(o.SrcID == 0, data); err != nil {
s := op.String()
o.Op = &s
return o
}
}
allSplit := true
for len(data) != 0 {
op := noxnet.Op(data[0])
sz := len(data)
var v any
lenOK := false
if n := op.Len(); n >= 0 && n <= len(data) {
sz = n + 1
lenOK = true
}
if m, n, err := noxnet.DecodeAnyPacket(o.SrcID == 0, data); err == nil && n > 0 {
sz = n
v = m
lenOK = true
}
if !lenOK {
allSplit = false
}
msg := data[:sz]
data = data[sz:]
m := Msg{
Op: op.String(),
Len: len(msg),
Data: hex.EncodeToString(msg),
Fields: v,
}
o.Msgs = append(o.Msgs, m)
}
if allSplit {
o.Data = ""
}
return o
}

type RecordOut struct {
SrcID uint32 `json:"src_id"`
DstID uint32 `json:"dst_id"`
Src string `json:"src"`
Dst string `json:"dst"`
Hdr string `json:"hdr"`
Reliable bool `json:"reliable"`
SID byte `json:"sid"`
Seq byte `json:"seq"`
Len int `json:"len"`
Op *string `json:"op,omitempty"`
Msgs []Msg `json:"msgs,omitempty"`
Data string `json:"data,omitempty"`
}

type Msg struct {
Op string `json:"op,omitempty"`
Fields any `json:"fields,omitempty"`
Len int `json:"len"`
Data string `json:"data"`
}
40 changes: 40 additions & 0 deletions cmd/opennox-proxy/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# OpenNox net proxy

This tool helps debug networking problems by sitting between Nox/OpenNox clients and the server.

```
/ \<--| |<--| |<--| |
|Client 1| | | | C1 proxy port | | |
\ /-->| Proxy |-->| |-->| Real Nox |
| server | | server |
/ \-->| port |-->| |-->| |
|Client 2| | | | C2 proxy port | | |
\ /<--| |<--| |<--| |
```

## Flow from client
1. Packets from clients are accepted on the server proxy port.
2. Proxy then allocates a unique proxy port for each client (since Nox uses ip+port for client id).
3. Client packets are then sent from client proxy port to the real server.

## Flow from server
1. Packets are received on unique client proxy port.
2. They are then sent from server proxy port to the client.

## How to run

```shell
go run ./cmd/opennox-proxy --server=<server-ip>:18590 --host=0.0.0.0:18600 --file=network.jsonl
```

This will run a proxy on port `18600`, which is not standard for Nox, thus server discovery will not find it.

You must add the proxy address to `game_ip.txt` file in Nox directory (as `127.0.0.1:18600`).

After this, you should see a new server in the server list, you will recognize it by "Proxy:" prefix.

While you are connected to this server, all network messages are logged to `network.jsonl`.
Once you're done with testing, disconnect from the proxy, and close it.

Now you can run `go run ./cmd/opennox-packet-decode` that will decode known network messages
in `network.jsonl` and will write them to `network-dec.jsonl`, which can then be inspected.
Loading

0 comments on commit 80a82b0

Please sign in to comment.