Skip to content

Commit

Permalink
use callback function to do some jobs after create listener
Browse files Browse the repository at this point in the history
  • Loading branch information
yin1999 committed Jul 22, 2023
1 parent dd01982 commit 5b058da
Showing 1 changed file with 33 additions and 23 deletions.
56 changes: 33 additions & 23 deletions transport/internet/system_listener.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ func getControlFunc(ctx context.Context, sockopt *SocketConfig, controllers []co
func (dl *DefaultListener) Listen(ctx context.Context, addr net.Addr, sockopt *SocketConfig) (l net.Listener, err error) {
var lc net.ListenConfig
var network, address string
// callback is called after the Listen function returns
callback := func(l net.Listener, err error) (net.Listener, error) {
return l, err
}

switch addr := addr.(type) {
case *net.TCPAddr:
Expand All @@ -71,23 +75,6 @@ func (dl *DefaultListener) Listen(ctx context.Context, addr net.Addr, sockopt *S
network = addr.Network()
address = addr.Name

if s := strings.Split(address, ","); len(s) == 2 {
address = s[0]
perm, perr := strconv.ParseUint(s[1], 8, 32)
if perr != nil {
return nil, newError("failed to parse permission: " + s[1]).Base(perr)
}

defer func(file string, permission os.FileMode) {
if err == nil {
cerr := os.Chmod(address, permission)
if cerr != nil {
err = newError("failed to set permission for " + file).Base(cerr)
}
}
}(address, os.FileMode(perm))
}

if (runtime.GOOS == "linux" || runtime.GOOS == "android") && address[0] == '@' {
// linux abstract unix domain socket is lockfree
if len(address) > 1 && address[1] == '@' {
Expand All @@ -97,25 +84,48 @@ func (dl *DefaultListener) Listen(ctx context.Context, addr net.Addr, sockopt *S
address = string(fullAddr)
}
} else {
// split permission from address
var filePerm *os.FileMode
if s := strings.Split(address, ","); len(s) == 2 {
address = s[0]
perm, perr := strconv.ParseUint(s[1], 8, 32)
if perr != nil {
return nil, newError("failed to parse permission: " + s[1]).Base(perr)
}

mode := os.FileMode(perm)
filePerm = &mode
}
// normal unix domain socket needs lock
locker := &FileLocker{
path: address + ".lock",
}
if err := locker.Acquire(); err != nil {
return nil, err
}
// combine listener and unix domain socket locker
defer func(locker *FileLocker) {
if err == nil {
l = &combinedListener{Listener: l, locker: locker}
} else {

// set callback to combine listener and set permission
callback = func(l net.Listener, err error) (net.Listener, error) {
if err != nil {
locker.Release()
return l, err
}
}(locker)
l = &combinedListener{Listener: l, locker: locker}
if filePerm == nil {
return l, nil
}
err = os.Chmod(address, *filePerm)
if err != nil {
l.Close()
return nil, newError("failed to set permission for " + address).Base(err)
}
return l, nil
}
}
}

l, err = lc.Listen(ctx, network, address)
l, err = callback(l, err)
if sockopt != nil && sockopt.AcceptProxyProtocol {
policyFunc := func(upstream net.Addr) (proxyproto.Policy, error) { return proxyproto.REQUIRE, nil }
l = &proxyproto.Listener{Listener: l, Policy: policyFunc}
Expand Down

0 comments on commit 5b058da

Please sign in to comment.