This commit is contained in:
Nonoo 2020-10-16 17:13:46 +02:00
parent e6d94bff52
commit 6ba02ae285
9 changed files with 295 additions and 0 deletions

2
.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
kappanhang
__debug_bin

16
.vscode/launch.json vendored Normal file
View file

@ -0,0 +1,16 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Launch",
"type": "go",
"request": "launch",
"mode": "auto",
"program": "${workspaceFolder}",
"args": []
}
]
}

3
.vscode/settings.json vendored Normal file
View file

@ -0,0 +1,3 @@
{
"go.lintTool": "golangci-lint"
}

17
.vscode/tasks.json vendored Normal file
View file

@ -0,0 +1,17 @@
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"label": "debug",
"type": "shell",
"command": "build/build.sh",
"problemMatcher": [],
"group": {
"kind": "build",
"isDefault": true
}
}
]
}

26
args.go Normal file
View file

@ -0,0 +1,26 @@
package main
import (
"os"
"github.com/pborman/getopt"
)
var connectAddress string
var connectPort uint16
func parseArgs() {
h := getopt.BoolLong("help", 'h', "display help")
a := getopt.StringLong("address", 'a', "IC-705", "Connect to address")
p := getopt.Uint16Long("port", 'p', 50001, "Connect to UDP port")
getopt.Parse()
if *h || *a == "" {
getopt.Usage()
os.Exit(1)
}
connectAddress = *a
connectPort = *p
}

14
build/build.sh Executable file
View file

@ -0,0 +1,14 @@
#!/bin/sh
self=`readlink "$0"`
if [ -z "$self" ]; then
self=$0
fi
scriptname=`basename "$self"`
scriptdir=${self%$scriptname}
cd $scriptdir
scriptdir=`pwd`
cd ..
go build

View file

@ -0,0 +1,7 @@
{
"folders": [
{
"path": "."
}
]
}

73
log/log.go Normal file
View file

@ -0,0 +1,73 @@
package log
import (
"fmt"
"os"
"path/filepath"
"runtime"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)
var logger *zap.SugaredLogger
var filenameTrimChars int
func getCallerFileName(withLine bool) string {
_, filename, line, _ := runtime.Caller(2)
extension := filepath.Ext(filename)
if withLine {
return fmt.Sprint(filename[filenameTrimChars:len(filename)-len(extension)], "@", line)
} else {
return filename[filenameTrimChars : len(filename)-len(extension)]
}
}
func Printf(a string, b ...interface{}) {
logger.Infof(getCallerFileName(false)+": "+a, b...)
}
func Print(a ...interface{}) {
logger.Info(append([]interface{}{getCallerFileName(false) + ": "}, a...)...)
}
func Debugf(a string, b ...interface{}) {
logger.Debugf(getCallerFileName(true)+": "+a, b...)
}
func Debug(a ...interface{}) {
logger.Debug(append([]interface{}{getCallerFileName(true) + ": "}, a...)...)
}
func Errorf(a string, b ...interface{}) {
logger.Errorf(getCallerFileName(true)+": "+a, b...)
}
func Error(a ...interface{}) {
logger.Error(append([]interface{}{getCallerFileName(true) + ": "}, a...)...)
}
func Fatalf(a string, b ...interface{}) {
logger.Fatalf(getCallerFileName(true)+": "+a, b...)
}
func Fatal(a ...interface{}) {
logger.Fatal(append([]interface{}{getCallerFileName(true) + ": "}, a...)...)
}
func Init() {
// Example: https://stackoverflow.com/questions/50933936/zap-logger-does-not-print-on-console-rather-print-in-the-log-file/50936341
pe := zap.NewProductionEncoderConfig()
pe.EncodeTime = zapcore.ISO8601TimeEncoder
// pe.LevelKey = ""
consoleEncoder := zapcore.NewConsoleEncoder(pe)
level := zap.DebugLevel
core := zapcore.NewCore(consoleEncoder, zapcore.AddSync(os.Stdout), level)
logger = zap.New(core).Sugar()
var callerFilename string
_, callerFilename, _, _ = runtime.Caller(1)
filenameTrimChars = len(filepath.Dir(callerFilename)) + 1
}

137
main.go Normal file
View file

@ -0,0 +1,137 @@
package main
import (
"bytes"
"encoding/binary"
"fmt"
"net"
"time"
"github.com/nonoo/kappanhang/log"
)
var conn *net.UDPConn
func send(d []byte) {
_, err := conn.Write(d)
if err != nil {
log.Fatal(err)
}
}
func read() ([]byte, error) {
err := conn.SetReadDeadline(time.Now().Add(time.Second))
if err != nil {
log.Fatal(err)
}
b := make([]byte, 1500)
n, _, err := conn.ReadFromUDP(b)
if err != nil {
if err, ok := err.(net.Error); ok && !err.Timeout() {
log.Fatal(err)
}
}
return b[:n], err
}
func main() {
log.Init()
parseArgs()
hostPort := fmt.Sprint(connectAddress, ":", connectPort)
log.Print("connecting to ", hostPort)
raddr, err := net.ResolveUDPAddr("udp", hostPort)
if err != nil {
log.Fatal(err)
}
conn, err = net.DialUDP("udp", nil, raddr)
if err != nil {
log.Fatal(err)
}
// Constructing the local session ID by combining the local IP address and port.
laddr := conn.LocalAddr().(*net.UDPAddr)
localSID := binary.BigEndian.Uint32(laddr.IP[len(laddr.IP)-4:])<<16 | uint32(laddr.Port&0xffff)
log.Debugf("using session id %.8x", localSID)
send([]byte{0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, byte(localSID >> 24), byte(localSID >> 16), byte(localSID >> 8), byte(localSID), 0x00, 0x00, 0x00, 0x00})
// send([]byte{0x15, 0x00, 0x00, 0x00, 0x07, 0x00, 0x01, 0x00, byte(localSID >> 24), byte(localSID >> 16), byte(localSID >> 8), byte(localSID), 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x3e, 0x10, 0x00})
// send([]byte{0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, byte(localSID >> 24), byte(localSID >> 16), byte(localSID >> 8), byte(localSID), 0x00, 0x00, 0x00, 0x00})
// send([]byte{0x15, 0x00, 0x00, 0x00, 0x07, 0x00, 0x02, 0x00, byte(localSID >> 24), byte(localSID >> 16), byte(localSID >> 8), byte(localSID), 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x3e, 0x10, 0x00})
// send([]byte{0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, byte(localSID >> 24), byte(localSID >> 16), byte(localSID >> 8), byte(localSID), 0x00, 0x00, 0x00, 0x00})
var remoteSID uint32
for {
r, _ := read()
if bytes.Equal(r[:8], []byte{0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00}) {
remoteSID = binary.BigEndian.Uint32(r[8:12])
break
}
}
log.Debugf("got remote session id %.8x", remoteSID)
send([]byte{0x10, 0x00, 0x00, 0x00, 0x06, 0x00, 0x01, 0x00, byte(localSID >> 24), byte(localSID >> 16), byte(localSID >> 8), byte(localSID), byte(remoteSID >> 24), byte(remoteSID >> 16), byte(remoteSID >> 8), byte(remoteSID)})
send([]byte{0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, byte(localSID >> 24), byte(localSID >> 16), byte(localSID >> 8), byte(localSID), byte(remoteSID >> 24), byte(remoteSID >> 16), byte(remoteSID >> 8), byte(remoteSID),
0x00, 0x00, 0x00, 0x70, 0x01, 0x00, 0x00, 0x22,
0x00, 0x00, 0x09, 0x27, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x3e, 0x71, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x5e, 0x3e, 0x2c, 0x54, 0x3a, 0x4f, 0x75, 0x79,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x69, 0x63, 0x6f, 0x6d, 0x2d, 0x70, 0x63, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})
var sendSeq uint8
var lastReceivedSeq uint8
var receivedSeq bool
var lastPingAt time.Time
var errCount int
for {
r, err := read()
if err != nil {
errCount++
if errCount > 5 {
log.Fatal("timeout")
}
log.Error("stream break detected")
}
errCount = 0
if bytes.Equal(r[:6], []byte{0x00, 0x00, 0x00, 0x00, 0x07, 0x00}) {
gotSeq := r[6]
if receivedSeq && lastReceivedSeq+1 != gotSeq {
log.Error("packet loss detected")
}
lastReceivedSeq = gotSeq
receivedSeq = true
}
if time.Since(lastPingAt) >= time.Second {
// 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0xf0, 0xa4, 0xf5, 0x9d, 0xad, 0x89, 0x2b, 0x14
// 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x00, 0xf0, 0xa4, 0xf5, 0x9d, 0xad, 0x89, 0x2b, 0x14
send([]byte{0x10, 0x00, 0x00, 0x00, 0x00, 0x00, sendSeq, 0x00, byte(remoteSID >> 24), byte(remoteSID >> 16), byte(remoteSID >> 8), byte(remoteSID), byte(localSID >> 24), byte(localSID >> 16), byte(localSID >> 8), byte(localSID)})
// 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x86, 0x08, 0xf0, 0xa4, 0xf5, 0x9d, 0xad, 0x89, 0x2b, 0x14, 0x00, 0x08, 0xdf, 0x10, 0x00
// 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x87, 0x08, 0xf0, 0xa4, 0xf5, 0x9d, 0xad, 0x89, 0x2b, 0x14, 0x00, 0x6c, 0xdf, 0x10, 0x00
send([]byte{0x00, 0x00, 0x00, 0x00, 0x07, 0x00, sendSeq, 0x08, byte(remoteSID >> 24), byte(remoteSID >> 16), byte(remoteSID >> 8), byte(remoteSID), byte(localSID >> 24), byte(localSID >> 16), byte(localSID >> 8), byte(localSID), 0x00, 0xd0, 0xdf, 0x10, 0x00})
// 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x1c, 0x00, 0xf0, 0xa4, 0xf5, 0x9d, 0xad, 0x89, 0x2b, 0x14, 0x01, 0xb2, 0x48, 0x10, 0x00
// 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x1d, 0x00, 0xf0, 0xa4, 0xf5, 0x9d, 0xad, 0x89, 0x2b, 0x14, 0x01, 0x17, 0x49, 0x10, 0x00
// 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x1e, 0x00, 0xf0, 0xa4, 0xf5, 0x9d, 0xad, 0x89, 0x2b, 0x14, 0x01, 0x7c, 0x49, 0x10, 0x00
send([]byte{0x00, 0x00, 0x00, 0x00, 0x07, 0x00, sendSeq, 0x00, byte(remoteSID >> 24), byte(remoteSID >> 16), byte(remoteSID >> 8), byte(remoteSID), byte(localSID >> 24), byte(localSID >> 16), byte(localSID >> 8), byte(localSID), 0x01, 0xe1, 0x49, 0x10, 0x00})
sendSeq++
//send([]byte{0x10, 0x00, 0x00, 0x00, 0x06, 0x00, 0x01, 0x00, byte(localSID >> 24), byte(localSID >> 16), byte(localSID >> 8), byte(localSID), byte(remoteSID >> 24), byte(remoteSID >> 16), byte(remoteSID >> 8), byte(remoteSID)})
lastPingAt = time.Now()
}
}
}