Skip to content

Commit

Permalink
Add GetFreePort in both TCP and UDP to avoid UDP listen fail
Browse files Browse the repository at this point in the history
Signed-off-by: bill fort <[email protected]>
  • Loading branch information
billfort authored and yilunzhang committed Aug 21, 2023
1 parent 2d58551 commit 3e6e2ef
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 1 deletion.
6 changes: 5 additions & 1 deletion client.go
Original file line number Diff line number Diff line change
Expand Up @@ -898,7 +898,11 @@ func (c *TunaSessionClient) startExits() error {
listeners := make([]net.Listener, c.config.NumTunaListeners)
var err error
for i := 0; i < len(listeners); i++ {
listeners[i], err = net.Listen("tcp", "127.0.0.1:")
port, err := GetFreePort(0)
if err != nil {
return err
}
listeners[i], err = net.Listen("tcp", fmt.Sprintf("127.0.0.1:%v", port))
if err != nil {
return err
}
Expand Down
4 changes: 4 additions & 0 deletions udp.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,10 @@ func (c *TunaSessionClient) DialUDPWithConfig(remoteAddr string, config *nkn.Dia
}

func (c *TunaSessionClient) handleUdpListenerTcp(tcpConn *Conn, remoteAddr string, sessionID []byte) {
if c.listenerUdpSess == nil { // Udp listener not started
tcpConn.Close()
return
}
sessKey := sessionKey(remoteAddr, sessionID)

c.listenerUdpSess.Lock()
Expand Down
41 changes: 41 additions & 0 deletions util.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@ package session

import (
"encoding/hex"
"errors"
"fmt"
"net"
"strconv"
"sync"
"time"
)

Expand All @@ -17,3 +21,40 @@ func sessionKey(remoteAddr string, sessionID []byte) string {
func connID(i int) string {
return strconv.Itoa(i)
}

// Get free port start from parameter `port`
// If paramenter `port` is 0, return system available port
// The returned port is free in both TCP and UDP
var lock sync.Mutex

func GetFreePort(port int) (int, error) {
// to avoid race condition
lock.Lock()
defer lock.Unlock()

for i := 0; i < 100; i++ {
addr, err := net.ResolveTCPAddr("tcp", fmt.Sprintf("127.0.0.1:%d", port))
if err != nil {
return 0, err
}

l, err := net.ListenTCP("tcp", addr)
if err != nil {
return 0, err
}
defer l.Close()

port = l.Addr().(*net.TCPAddr).Port
u, err := net.ListenUDP("udp", &net.UDPAddr{IP: net.ParseIP("127.0.0.1"), Port: port})
if err != nil {
l.Close()
port++
continue
}
u.Close()

return port, nil
}

return 0, errors.New("failed to find free port after 100 tries")
}
12 changes: 12 additions & 0 deletions util_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package session

import "testing"

// go test -v -run=TestGetFreePort
func TestGetFreePort(t *testing.T) {
port, err := GetFreePort(0)
if err != nil {
t.Error(err)
}
t.Log(port)
}

0 comments on commit 3e6e2ef

Please sign in to comment.