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.
125 lines
3.3 KiB
Go
125 lines
3.3 KiB
Go
6 months ago
|
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
|
||
|
}
|