Signed-off-by: arraykeys@gmail.com <arraykeys@gmail.com>

This commit is contained in:
arraykeys@gmail.com
2017-09-25 15:31:07 +08:00
parent b17c09aa1e
commit 3f7b57740d
8 changed files with 370 additions and 198 deletions

View File

@ -13,7 +13,7 @@ import (
var ( var (
app *kingpin.Application app *kingpin.Application
service services.ServiceItem service *services.ServiceItem
) )
func initConfig() (err error) { func initConfig() (err error) {
@ -21,7 +21,7 @@ func initConfig() (err error) {
//define args //define args
tcpArgs := services.TCPArgs{} tcpArgs := services.TCPArgs{}
httpArgs := services.HTTPArgs{} httpArgs := services.HTTPArgs{}
tlsArgs := services.TLSArgs{} // tlsArgs := services.TLSArgs{}
udpArgs := services.UDPArgs{} udpArgs := services.UDPArgs{}
//build srvice args //build srvice args
@ -31,8 +31,8 @@ func initConfig() (err error) {
args.Local = app.Flag("local", "local ip:port to listen").Short('p').Default(":33080").String() args.Local = app.Flag("local", "local ip:port to listen").Short('p').Default(":33080").String()
certTLS := app.Flag("cert", "cert file for tls").Short('C').Default("proxy.crt").String() certTLS := app.Flag("cert", "cert file for tls").Short('C').Default("proxy.crt").String()
keyTLS := app.Flag("key", "key file for tls").Short('K').Default("proxy.key").String() keyTLS := app.Flag("key", "key file for tls").Short('K').Default("proxy.key").String()
args.PoolSize = app.Flag("pool-size", "conn pool size , which connect to parent proxy, zero: means turn off pool").Default("50").Int() args.PoolSize = app.Flag("pool-size", "conn pool size , which connect to parent proxy, zero: means turn off pool").Short('L').Default("50").Int()
args.CheckParentInterval = app.Flag("check-parent-interval", "check if proxy is okay every interval seconds,zero: means no check").Default("3").Int() args.CheckParentInterval = app.Flag("check-parent-interval", "check if proxy is okay every interval seconds,zero: means no check").Short('I').Default("3").Int()
//########http######### //########http#########
http := app.Command("http", "proxy on http mode") http := app.Command("http", "proxy on http mode")
@ -49,13 +49,13 @@ func initConfig() (err error) {
//########tcp######### //########tcp#########
tcp := app.Command("tcp", "proxy on tcp mode") tcp := app.Command("tcp", "proxy on tcp mode")
tcpArgs.Timeout = tcp.Flag("timeout", "tcp timeout milliseconds when connect to real server or parent proxy").Default("2000").Int() tcpArgs.Timeout = tcp.Flag("timeout", "tcp timeout milliseconds when connect to real server or parent proxy").Short('t').Default("2000").Int()
tcpArgs.ParentType = tcp.Flag("parent-type", "parent protocol type <tls|tcp|udp>").Short('T').Enum("tls", "tcp", "udp") tcpArgs.ParentType = tcp.Flag("parent-type", "parent protocol type <tls|tcp|udp>").Short('T').Enum("tls", "tcp", "udp")
tcpArgs.IsTLS = tcp.Flag("tls", "proxy on tls mode").Default("false").Bool()
//########tls######### //########udp#########
tls := app.Command("tls", "proxy on tls mode") udp := app.Command("udp", "proxy on udp mode")
tlsArgs.Timeout = tls.Flag("timeout", "tcp timeout milliseconds when connect to real server or parent proxy").Default("2000").Int() udpArgs.Timeout = udp.Flag("timeout", "tcp timeout milliseconds when connect to parent proxy").Short('t').Default("2000").Int()
tlsArgs.ParentType = tls.Flag("parent-type", "parent protocol type <tls|tcp|udp>").Short('T').Enum("tls", "tcp", "udp") udpArgs.ParentType = udp.Flag("parent-type", "parent protocol type <tls|tcp|udp>").Short('T').Enum("tls", "tcp", "udp")
kingpin.MustParse(app.Parse(os.Args[1:])) kingpin.MustParse(app.Parse(os.Args[1:]))
@ -64,7 +64,7 @@ func initConfig() (err error) {
} }
httpArgs.Args = args httpArgs.Args = args
tcpArgs.Args = args tcpArgs.Args = args
tlsArgs.Args = args // tlsArgs.Args = args
udpArgs.Args = args udpArgs.Args = args
//keygen //keygen
@ -78,7 +78,6 @@ func initConfig() (err error) {
serviceName := kingpin.MustParse(app.Parse(os.Args[1:])) serviceName := kingpin.MustParse(app.Parse(os.Args[1:]))
services.Regist("http", services.NewHTTP(), httpArgs) services.Regist("http", services.NewHTTP(), httpArgs)
services.Regist("tcp", services.NewTCP(), tcpArgs) services.Regist("tcp", services.NewTCP(), tcpArgs)
services.Regist("tls", services.NewTLS(), tlsArgs)
services.Regist("udp", services.NewUDP(), udpArgs) services.Regist("udp", services.NewUDP(), udpArgs)
service, err = services.Run(serviceName) service, err = services.Run(serviceName)
if err != nil { if err != nil {

View File

@ -22,12 +22,9 @@ type TCPArgs struct {
Args Args
Timeout *int Timeout *int
ParentType *string ParentType *string
IsTLS *bool
} }
type TLSArgs struct {
Args
Timeout *int
ParentType *string
}
type HTTPArgs struct { type HTTPArgs struct {
Args Args
Always *bool Always *bool
@ -43,4 +40,13 @@ type HTTPArgs struct {
} }
type UDPArgs struct { type UDPArgs struct {
Args Args
ParentType *string
Timeout *int
}
func (a *TCPArgs) Protocol() string {
if *a.IsTLS {
return "tls"
}
return "tcp"
} }

View File

@ -2,6 +2,7 @@ package services
import ( import (
"fmt" "fmt"
"io"
"log" "log"
"net" "net"
"proxy/utils" "proxy/utils"
@ -61,7 +62,6 @@ func (s *HTTP) Clean() {
s.StopService() s.StopService()
} }
func (s *HTTP) callback(inConn net.Conn) { func (s *HTTP) callback(inConn net.Conn) {
go func() {
defer func() { defer func() {
if err := recover(); err != nil { if err := recover(); err != nil {
log.Printf("http(s) conn handler crashed with err : %s \nstack: %s", err, string(debug.Stack())) log.Printf("http(s) conn handler crashed with err : %s \nstack: %s", err, string(debug.Stack()))
@ -69,7 +69,9 @@ func (s *HTTP) callback(inConn net.Conn) {
}() }()
req, err := utils.NewHTTPRequest(&inConn, 4096, s.IsBasicAuth(), &s.basicAuth) req, err := utils.NewHTTPRequest(&inConn, 4096, s.IsBasicAuth(), &s.basicAuth)
if err != nil { if err != nil {
if err != io.EOF {
log.Printf("decoder error , form %s, ERR:%s", err, inConn.RemoteAddr()) log.Printf("decoder error , form %s, ERR:%s", err, inConn.RemoteAddr())
}
utils.CloseConn(&inConn) utils.CloseConn(&inConn)
return return
} }
@ -93,7 +95,6 @@ func (s *HTTP) callback(inConn net.Conn) {
} }
utils.CloseConn(&inConn) utils.CloseConn(&inConn)
} }
}()
} }
func (s *HTTP) OutToTCP(useProxy bool, address string, inConn *net.Conn, req *utils.HTTPRequest) (err error) { func (s *HTTP) OutToTCP(useProxy bool, address string, inConn *net.Conn, req *utils.HTTPRequest) (err error) {
inAddr := (*inConn).RemoteAddr().String() inAddr := (*inConn).RemoteAddr().String()

View File

@ -16,16 +16,16 @@ type ServiceItem struct {
Name string Name string
} }
var servicesMap = map[string]ServiceItem{} var servicesMap = map[string]*ServiceItem{}
func Regist(name string, s Service, args interface{}) { func Regist(name string, s Service, args interface{}) {
servicesMap[name] = ServiceItem{ servicesMap[name] = &ServiceItem{
S: s, S: s,
Args: args, Args: args,
Name: name, Name: name,
} }
} }
func Run(name string) (service ServiceItem, err error) { func Run(name string) (service *ServiceItem, err error) {
service, ok := servicesMap[name] service, ok := servicesMap[name]
if ok { if ok {
go func() { go func() {

View File

@ -2,10 +2,12 @@ package services
import ( import (
"fmt" "fmt"
"io"
"log" "log"
"net" "net"
"proxy/utils" "proxy/utils"
"runtime/debug" "runtime/debug"
"time"
"strconv" "strconv"
) )
@ -34,7 +36,7 @@ func (s *TCP) Start(args interface{}) (err error) {
if *s.cfg.Parent != "" { if *s.cfg.Parent != "" {
log.Printf("use %s parent %s", *s.cfg.ParentType, *s.cfg.Parent) log.Printf("use %s parent %s", *s.cfg.ParentType, *s.cfg.Parent)
} else { } else {
log.Fatalf("parent required for tcp", *s.cfg.Local) log.Fatalf("parent required for %s %s", s.cfg.Protocol(), *s.cfg.Local)
} }
s.InitService() s.InitService()
@ -42,11 +44,25 @@ func (s *TCP) Start(args interface{}) (err error) {
host, port, _ := net.SplitHostPort(*s.cfg.Local) host, port, _ := net.SplitHostPort(*s.cfg.Local)
p, _ := strconv.Atoi(port) p, _ := strconv.Atoi(port)
sc := utils.NewServerChannel(host, p) sc := utils.NewServerChannel(host, p)
err = sc.ListenTCP(func(inConn net.Conn) { if !*s.cfg.IsTLS {
go func() { err = sc.ListenTCP(s.callback)
} else {
err = sc.ListenTls(s.cfg.CertBytes, s.cfg.KeyBytes, s.callback)
}
if err != nil {
return
}
log.Printf("%s proxy on %s", s.cfg.Protocol(), (*sc.Listener).Addr())
return
}
func (s *TCP) Clean() {
s.StopService()
}
func (s *TCP) callback(inConn net.Conn) {
defer func() { defer func() {
if err := recover(); err != nil { if err := recover(); err != nil {
log.Printf("tcp conn handler crashed with err : %s \nstack: %s", err, string(debug.Stack())) log.Printf("%s conn handler crashed with err : %s \nstack: %s", s.cfg.Protocol(), err, string(debug.Stack()))
} }
}() }()
var err error var err error
@ -64,19 +80,7 @@ func (s *TCP) Start(args interface{}) (err error) {
log.Printf("connect to %s parent %s fail, ERR:%s", *s.cfg.ParentType, *s.cfg.Parent, err) log.Printf("connect to %s parent %s fail, ERR:%s", *s.cfg.ParentType, *s.cfg.Parent, err)
utils.CloseConn(&inConn) utils.CloseConn(&inConn)
} }
}()
})
if err != nil {
return
}
log.Printf("tcp proxy on %s", (*sc.Listener).Addr())
return
} }
func (s *TCP) Clean() {
s.StopService()
}
func (s *TCP) OutToTCP(inConn *net.Conn) (err error) { func (s *TCP) OutToTCP(inConn *net.Conn) (err error) {
var outConn net.Conn var outConn net.Conn
var _outConn interface{} var _outConn interface{}
@ -102,7 +106,52 @@ func (s *TCP) OutToTCP(inConn *net.Conn) (err error) {
return return
} }
func (s *TCP) OutToUDP(inConn *net.Conn) (err error) { func (s *TCP) OutToUDP(inConn *net.Conn) (err error) {
log.Printf("conn created , remote : %s ", (*inConn).RemoteAddr())
for {
srcAddr, body, err := utils.ReadUDPPacket(inConn)
if err == io.EOF || err == io.ErrUnexpectedEOF {
//log.Printf("connection %s released", srcAddr)
utils.CloseConn(inConn)
break
}
//log.Debugf("udp packet revecived:%s,%v", srcAddr, body)
dstAddr, err := net.ResolveUDPAddr("udp", *s.cfg.Parent)
if err != nil {
log.Printf("can't resolve address: %s", err)
utils.CloseConn(inConn)
break
}
clientSrcAddr := &net.UDPAddr{IP: net.IPv4zero, Port: 0}
conn, err := net.DialUDP("udp", clientSrcAddr, dstAddr)
if err != nil {
log.Printf("connect to udp %s fail,ERR:%s", dstAddr.String(), err)
continue
}
conn.SetDeadline(time.Now().Add(time.Millisecond * time.Duration(*s.cfg.Timeout)))
_, err = conn.Write(body)
if err != nil {
log.Printf("send udp packet to %s fail,ERR:%s", dstAddr.String(), err)
continue
}
//log.Debugf("send udp packet to %s success", dstAddr.String())
buf := make([]byte, 512)
len, _, err := conn.ReadFromUDP(buf)
if err != nil {
log.Printf("read udp response from %s fail ,ERR:%s", dstAddr.String(), err)
continue
}
respBody := buf[0:len]
//log.Debugf("revecived udp packet from %s , %v", dstAddr.String(), respBody)
_, err = (*inConn).Write(utils.UDPPacket(srcAddr, respBody))
if err != nil {
log.Printf("send udp response fail ,ERR:%s", err)
utils.CloseConn(inConn)
break
}
//log.Printf("send udp response success ,from:%s", dstAddr.String())
}
return return
} }
func (s *TCP) InitOutConnPool() { func (s *TCP) InitOutConnPool() {
if *s.cfg.ParentType == TYPE_TLS || *s.cfg.ParentType == TYPE_TCP { if *s.cfg.ParentType == TYPE_TLS || *s.cfg.ParentType == TYPE_TCP {

View File

@ -1,117 +0,0 @@
package services
import (
"fmt"
"log"
"net"
"proxy/utils"
"runtime/debug"
"strconv"
)
type TLS struct {
outPool utils.OutPool
cfg TLSArgs
}
func NewTLS() Service {
return &TLS{}
}
func (s *TLS) InitService() {
s.InitOutConnPool()
}
func (s *TLS) StopService() {
if s.outPool.Pool != nil {
s.outPool.Pool.ReleaseAll()
}
}
func (s *TLS) Start(args interface{}) (err error) {
s.cfg = args.(TLSArgs)
if *s.cfg.Parent != "" {
log.Printf("use %s parent %s", *s.cfg.ParentType, *s.cfg.Parent)
} else {
log.Fatalf("parent required for tls")
}
s.InitService()
host, port, _ := net.SplitHostPort(*s.cfg.Local)
p, _ := strconv.Atoi(port)
sc := utils.NewServerChannel(host, p)
err = sc.ListenTls(s.cfg.CertBytes, s.cfg.KeyBytes, func(inConn net.Conn) {
go func() {
defer func() {
if err := recover(); err != nil {
log.Printf("tls conn handler crashed with err : %s \nstack: %s", err, string(debug.Stack()))
}
}()
var err error
switch *s.cfg.ParentType {
case TYPE_TCP:
fallthrough
case TYPE_TLS:
err = s.OutToTCP(&inConn)
case TYPE_UDP:
err = s.OutToUDP(&inConn)
default:
err = fmt.Errorf("unkown parent type %s", *s.cfg.ParentType)
}
if err != nil {
log.Printf("connect to %s parent %s fail, ERR:%s", *s.cfg.ParentType, *s.cfg.Parent, err)
utils.CloseConn(&inConn)
}
}()
})
if err != nil {
return
}
log.Printf("tls proxy on %s", (*sc.Listener).Addr())
return
}
func (s *TLS) Clean() {
s.StopService()
}
func (s *TLS) OutToTCP(inConn *net.Conn) (err error) {
var outConn net.Conn
var _outConn interface{}
_outConn, err = s.outPool.Pool.Get()
if err == nil {
outConn = _outConn.(net.Conn)
}
if err != nil {
log.Printf("connect to %s , err:%s", *s.cfg.Parent, err)
utils.CloseConn(inConn)
return
}
inAddr := (*inConn).RemoteAddr().String()
inLocalAddr := (*inConn).LocalAddr().String()
outAddr := outConn.RemoteAddr().String()
outLocalAddr := outConn.LocalAddr().String()
utils.IoBind((*inConn), outConn, func(err error) {
log.Printf("conn %s - %s - %s -%s released", inAddr, inLocalAddr, outLocalAddr, outAddr)
utils.CloseConn(inConn)
utils.CloseConn(&outConn)
}, func(n int, d bool) {}, 0)
log.Printf("conn %s - %s - %s -%s connected", inAddr, inLocalAddr, outLocalAddr, outAddr)
return
}
func (s *TLS) OutToUDP(inConn *net.Conn) (err error) {
return
}
func (s *TLS) InitOutConnPool() {
if *s.cfg.ParentType == TYPE_TLS || *s.cfg.ParentType == TYPE_TCP {
//dur int, isTLS bool, certBytes, keyBytes []byte,
//parent string, timeout int, InitialCap int, MaxCap int
s.outPool = utils.NewOutPool(
*s.cfg.CheckParentInterval,
*s.cfg.ParentType == TYPE_TLS,
s.cfg.CertBytes, s.cfg.KeyBytes,
*s.cfg.Parent,
*s.cfg.Timeout,
*s.cfg.PoolSize,
*s.cfg.PoolSize*2,
)
}
}

View File

@ -1,19 +1,207 @@
package services package services
import ( import (
"bufio"
"fmt"
"hash/crc32"
"io"
"log" "log"
"net"
"proxy/utils"
"runtime/debug"
"strconv"
"strings"
"time"
) )
type UDP struct { type UDP struct {
p utils.ConcurrentMap
outPool utils.OutPool
cfg UDPArgs
sc *utils.ServerChannel
} }
func NewUDP() Service { func NewUDP() Service {
return &UDP{} return &UDP{
outPool: utils.OutPool{},
p: utils.NewConcurrentMap(),
}
}
func (s *UDP) InitService() {
if *s.cfg.ParentType != TYPE_UDP {
s.InitOutConnPool()
}
}
func (s *UDP) StopService() {
if s.outPool.Pool != nil {
s.outPool.Pool.ReleaseAll()
}
} }
func (s *UDP) Start(args interface{}) (err error) { func (s *UDP) Start(args interface{}) (err error) {
log.Printf("called") s.cfg = args.(UDPArgs)
if *s.cfg.Parent != "" {
log.Printf("use %s parent %s", *s.cfg.ParentType, *s.cfg.Parent)
} else {
log.Fatalf("parent required for udp %s", *s.cfg.Local)
}
s.InitService()
host, port, _ := net.SplitHostPort(*s.cfg.Local)
p, _ := strconv.Atoi(port)
sc := utils.NewServerChannel(host, p)
s.sc = &sc
err = sc.ListenUDP(s.callback)
if err != nil {
return
}
log.Printf("udp proxy on %s", (*sc.UDPListener).LocalAddr())
return return
} }
func (s *UDP) Clean() {
func (s *UDP) Clean() {
s.StopService()
}
func (s *UDP) callback(packet []byte, localAddr, srcAddr *net.UDPAddr) {
defer func() {
if err := recover(); err != nil {
log.Printf("udp conn handler crashed with err : %s \nstack: %s", err, string(debug.Stack()))
}
}()
var err error
switch *s.cfg.ParentType {
case TYPE_TCP:
fallthrough
case TYPE_TLS:
err = s.OutToTCP(packet, localAddr, srcAddr)
case TYPE_UDP:
err = s.OutToUDP(packet, localAddr, srcAddr)
default:
err = fmt.Errorf("unkown parent type %s", *s.cfg.ParentType)
}
if err != nil {
log.Printf("connect to %s parent %s fail, ERR:%s", *s.cfg.ParentType, *s.cfg.Parent, err)
}
}
func (s *UDP) GetConn(connKey string) (conn net.Conn, isNew bool, err error) {
isNew = !s.p.Has(connKey)
var _conn interface{}
if isNew {
_conn, err = s.outPool.Pool.Get()
if err != nil {
return nil, false, err
}
s.p.Set(connKey, _conn)
} else {
_conn, _ = s.p.Get(connKey)
}
conn = _conn.(net.Conn)
return
}
func (s *UDP) OutToTCP(packet []byte, localAddr, srcAddr *net.UDPAddr) (err error) {
numLocal := crc32.ChecksumIEEE([]byte(localAddr.String()))
numSrc := crc32.ChecksumIEEE([]byte(srcAddr.String()))
connKey := uint64((numLocal/10)*10 + numSrc%10)
conn, isNew, err := s.GetConn(fmt.Sprintf("%d", connKey))
if err != nil {
log.Printf("upd get conn to %s parent %s fail, ERR:%s", *s.cfg.ParentType, *s.cfg.Parent, err)
return
}
if isNew {
go func() {
defer func() {
if err := recover(); err != nil {
log.Printf("udp conn handler out to tcp crashed with err : %s \nstack: %s", err, string(debug.Stack()))
}
}()
log.Printf("conn %d created , local: %s", connKey, srcAddr.String())
for {
srcAddrFromConn, body, err := utils.ReadUDPPacket(&conn)
if err == io.EOF || err == io.ErrUnexpectedEOF {
//log.Printf("connection %d released", connKey)
s.p.Remove(fmt.Sprintf("%d", connKey))
break
}
if err != nil {
log.Printf("parse revecived udp packet fail, err: %s", err)
continue
}
//log.Printf("udp packet revecived over parent , local:%s", srcAddrFromConn)
_srcAddr := strings.Split(srcAddrFromConn, ":")
if len(_srcAddr) != 2 {
log.Printf("parse revecived udp packet fail, addr error : %s", srcAddrFromConn)
continue
}
port, _ := strconv.Atoi(_srcAddr[1])
dstAddr := &net.UDPAddr{IP: net.ParseIP(_srcAddr[0]), Port: port}
_, err = s.sc.UDPListener.WriteToUDP(body, dstAddr)
if err != nil {
log.Printf("udp response to local %s fail,ERR:%s", srcAddr, err)
continue
}
//log.Printf("udp response to local %s success", srcAddr)
}
}()
}
//log.Printf("select conn %d , local: %s", connKey, srcAddr.String())
writer := bufio.NewWriter(conn)
//fmt.Println(conn, writer)
writer.Write(utils.UDPPacket(srcAddr.String(), packet))
err = writer.Flush()
if err != nil {
log.Printf("write udp packet to %s fail ,flush err:%s", *s.cfg.Parent, err)
return
}
//log.Printf("write packet %v", packet)
return
}
func (s *UDP) OutToUDP(packet []byte, localAddr, srcAddr *net.UDPAddr) (err error) {
//log.Printf("udp packet revecived:%s,%v", srcAddr, packet)
dstAddr, err := net.ResolveUDPAddr("udp", *s.cfg.Parent)
if err != nil {
log.Printf("resolve udp addr %s fail fail,ERR:%s", dstAddr.String(), err)
return
}
clientSrcAddr := &net.UDPAddr{IP: net.IPv4zero, Port: 0}
conn, err := net.DialUDP("udp", clientSrcAddr, dstAddr)
if err != nil {
log.Printf("connect to udp %s fail,ERR:%s", dstAddr.String(), err)
return
}
conn.SetDeadline(time.Now().Add(time.Millisecond * time.Duration(*s.cfg.Timeout)))
_, err = conn.Write(packet)
if err != nil {
log.Printf("send udp packet to %s fail,ERR:%s", dstAddr.String(), err)
return
}
//log.Printf("send udp packet to %s success", dstAddr.String())
buf := make([]byte, 512)
len, _, err := conn.ReadFromUDP(buf)
if err != nil {
log.Printf("read udp response from %s fail ,ERR:%s", dstAddr.String(), err)
return
}
//log.Printf("revecived udp packet from %s , %v", dstAddr.String(), respBody)
_, err = s.sc.UDPListener.WriteToUDP(buf[0:len], srcAddr)
if err != nil {
log.Printf("send udp response to cluster fail ,ERR:%s", err)
return
}
//log.Printf("send udp response to cluster success ,from:%s", dstAddr.String())
return
}
func (s *UDP) InitOutConnPool() {
if *s.cfg.ParentType == TYPE_TLS || *s.cfg.ParentType == TYPE_TCP {
//dur int, isTLS bool, certBytes, keyBytes []byte,
//parent string, timeout int, InitialCap int, MaxCap int
s.outPool = utils.NewOutPool(
*s.cfg.CheckParentInterval,
*s.cfg.ParentType == TYPE_TLS,
s.cfg.CertBytes, s.cfg.KeyBytes,
*s.cfg.Parent,
*s.cfg.Timeout,
*s.cfg.PoolSize,
*s.cfg.PoolSize*2,
)
}
} }

View File

@ -1,8 +1,11 @@
package utils package utils
import ( import (
"bufio"
"bytes"
"crypto/tls" "crypto/tls"
"crypto/x509" "crypto/x509"
"encoding/binary"
"errors" "errors"
"fmt" "fmt"
"io" "io"
@ -254,6 +257,49 @@ func GetAllInterfaceAddr() ([]net.IP, error) {
//only need first //only need first
return addresses, nil return addresses, nil
} }
func UDPPacket(srcAddr string, packet []byte) []byte {
addrBytes := []byte(srcAddr)
addrLength := uint16(len(addrBytes))
bodyLength := uint16(len(packet))
pkg := new(bytes.Buffer)
binary.Write(pkg, binary.LittleEndian, addrLength)
binary.Write(pkg, binary.LittleEndian, addrBytes)
binary.Write(pkg, binary.LittleEndian, bodyLength)
binary.Write(pkg, binary.LittleEndian, packet)
return pkg.Bytes()
}
func ReadUDPPacket(conn *net.Conn) (srcAddr string, packet []byte, err error) {
reader := bufio.NewReader(*conn)
var addrLength uint16
var bodyLength uint16
err = binary.Read(reader, binary.LittleEndian, &addrLength)
if err != nil {
return
}
_srcAddr := make([]byte, addrLength)
n, err := reader.Read(_srcAddr)
if err != nil {
return
}
if n != int(addrLength) {
return
}
srcAddr = string(_srcAddr)
err = binary.Read(reader, binary.LittleEndian, &bodyLength)
if err != nil {
return
}
packet = make([]byte, bodyLength)
n, err = reader.Read(packet)
if err != nil {
return
}
if n != int(bodyLength) {
return
}
return
}
// type sockaddr struct { // type sockaddr struct {
// family uint16 // family uint16