diff --git a/client/dial.go b/client/dial.go index 82840b1..7bcead1 100644 --- a/client/dial.go +++ b/client/dial.go @@ -2,11 +2,10 @@ package main import ( "fmt" - "regexp" - "strconv" "github.com/pkg/errors" kcp "github.com/xtaci/kcp-go/v5" + "github.com/xtaci/kcptun/generic" "github.com/xtaci/tcpraw" ) @@ -17,30 +16,13 @@ func dial(config *Config, block kcp.BlockCrypt) (*kcp.UDPSession, error) { dialCount++ }() - remoteAddrMatcher := regexp.MustCompile(`(.*)\:([0-9]{1,5})-?([0-9]{1,5})?`) - matches := remoteAddrMatcher.FindStringSubmatch(config.RemoteAddr) - - var remoteAddr string - if len(matches) == 3 { // single port - remoteAddr = config.RemoteAddr - } else if len(matches) == 4 { // multi port - minPort, err := strconv.Atoi(matches[2]) - if err != nil { - return nil, err - } - maxPort, err := strconv.Atoi(matches[3]) - if err != nil { - return nil, err - } - - if (minPort > maxPort) || minPort > 65535 || maxPort > 65535 || minPort == 0 || maxPort == 0 { - return nil, errors.Errorf("invalid port range specified: minport:%v -> maxport %v", minPort, maxPort) - } - - // assign remote addr - remoteAddr = fmt.Sprintf("%v:%v", matches[1], uint64(minPort)+dialCount%uint64(maxPort-minPort+1)) + mp, err := generic.ParseMultiPort(config.RemoteAddr) + if err != nil { + return nil, err } + remoteAddr := fmt.Sprintf("%v:%v", mp.Host, uint64(mp.MinPort)+dialCount%uint64(mp.MaxPort-mp.MinPort+1)) + if config.TCP { conn, err := tcpraw.Dial("tcp", remoteAddr) if err != nil { diff --git a/generic/multiport.go b/generic/multiport.go new file mode 100644 index 0000000..a953f08 --- /dev/null +++ b/generic/multiport.go @@ -0,0 +1,50 @@ +package generic + +import ( + "regexp" + "strconv" + + "github.com/pkg/errors" +) + +type MultiPort struct { + Host string + MinPort uint64 + MaxPort uint64 +} + +// Parse mulitport listener or dialer +func ParseMultiPort(addr string) (*MultiPort, error) { + remoteAddrMatcher := regexp.MustCompile(`(.*)\:([0-9]{1,5})-?([0-9]{1,5})?`) + matches := remoteAddrMatcher.FindStringSubmatch(addr) + + if len(matches) >= 3 { + var minPort, maxPort int + minPort, err := strconv.Atoi(matches[2]) + if err != nil { + return nil, err + } + maxPort = minPort + + // multiport assignment + if len(matches) >= 4 { + maxPort, err = strconv.Atoi(matches[3]) + if err != nil { + return nil, err + } + } + + if (minPort > maxPort) || minPort > 65535 || maxPort > 65535 || minPort == 0 || maxPort == 0 { + return nil, errors.Errorf("invalid port range specified: minport:%v -> maxport %v", minPort, maxPort) + } + + mp := new(MultiPort) + mp.Host = matches[1] + mp.MinPort = uint64(minPort) + mp.MaxPort = uint64(maxPort) + return mp, nil + } + + return nil, errors.Errorf("malformed address:%v", addr) + +}