You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
star/net/nats.go

125 lines
3.3 KiB
Go

package net
import (
"b612.me/starlog"
"context"
"fmt"
"net"
"strings"
"sync/atomic"
)
type NatTesterServer struct {
MainPort string
AltPort string
MainIP string
AltIP string
LogPath string
stopCtx context.Context
stopFn context.CancelFunc
maina *net.UDPConn
mainb *net.UDPConn
alt *net.UDPConn
running int32
}
func (n *NatTesterServer) Run() error {
if atomic.LoadInt32(&n.running) > 0 {
starlog.Errorln("already running")
return fmt.Errorf("already running")
}
atomic.StoreInt32(&n.running, 1)
defer atomic.StoreInt32(&n.running, 0)
if n.LogPath != "" {
starlog.SetLogFile(n.LogPath, starlog.Std, true)
starlog.Infof("Log file set to %s\n", n.LogPath)
}
starlog.Infof("MainPort: %s\n", n.MainPort)
starlog.Infof("AltPort: %s\n", n.AltPort)
tmp, err := net.Dial("udp", "8.8.8.8:53")
if err != nil {
return err
}
starlog.Infof("Current Output IP: %s\n", tmp.LocalAddr().(*net.UDPAddr).IP.String())
tmp.Close()
n.stopCtx, n.stopFn = context.WithCancel(context.Background())
mainaaddr, err := net.ResolveUDPAddr("udp", n.MainIP+":"+n.MainPort)
if err != nil {
return err
}
mainbaddr, err := net.ResolveUDPAddr("udp", n.MainIP+":"+n.AltPort)
if err != nil {
return err
}
n.maina, err = net.ListenUDP("udp", mainaaddr)
if err != nil {
return err
}
starlog.Infof("UDP MainIP:MainPort Listening on %s\n", n.maina.LocalAddr().String())
n.mainb, err = net.ListenUDP("udp", mainbaddr)
if err != nil {
return err
}
starlog.Infof("UDP MainIP:AltPort Listening on %s\n", n.mainb.LocalAddr().String())
altaddr, err := net.ResolveUDPAddr("udp", n.AltIP+":"+n.AltPort)
if err != nil {
return err
}
n.alt, err = net.ListenUDP("udp", altaddr)
if err != nil {
return err
}
starlog.Infof("UDP AltIP:AltPort Listening on %s\n", n.alt.LocalAddr().String())
go func() {
for {
select {
case <-n.stopCtx.Done():
starlog.Infoln("Stopping,Reason: Context Done")
return
default:
}
buf := make([]byte, 1024)
num, r, e := n.alt.ReadFromUDP(buf)
if e != nil {
continue
}
go n.Analyse(n.alt, r, strings.Split(string(buf[:num]), "::"))
}
}()
for {
select {
case <-n.stopCtx.Done():
starlog.Infoln("Stopping,Reason: Context Done")
n.maina.Close()
n.mainb.Close()
n.alt.Close()
return nil
default:
}
buf := make([]byte, 1024)
num, r, e := n.maina.ReadFromUDP(buf)
if e != nil {
continue
}
go n.Analyse(n.maina, r, strings.Split(string(buf[:num]), "::"))
}
}
func (n *NatTesterServer) Analyse(c *net.UDPConn, r *net.UDPAddr, cmds []string) error {
switch cmds[0] {
case "ip":
c.WriteToUDP([]byte("ip::"+r.String()), r)
starlog.Infof("Recv IP Request from %s,Local: %s\n", r.String(), c.LocalAddr().String())
case "startnat1":
n.alt.WriteToUDP([]byte("stage1"), r)
starlog.Infof("Start NAT1 Test from %s,Recv Local:%s Send Local:%s\n", r.String(), c.LocalAddr().String(), n.alt.LocalAddr().String())
case "startnat2":
n.mainb.WriteToUDP([]byte("stage2"), r)
starlog.Infof("Start NAT2 Test from %s,Recv Local:%s Send Local:%s\n", r.String(), c.LocalAddr().String(), n.mainb.LocalAddr().String())
case "startnat3":
n.maina.WriteToUDP([]byte("stage3"), r)
starlog.Infof("Start NAT3 Test from %s,Recv Local:%s Send Local:%s\n", r.String(), c.LocalAddr().String(), n.maina.LocalAddr().String())
}
return nil
}