Forking dependency reuseport. Close #8

This commit is contained in:
Kleissner
2021-03-16 14:24:37 +01:00
parent 3080119fc1
commit cfb0129152
10 changed files with 186 additions and 3 deletions

View File

@@ -15,8 +15,8 @@ import (
"strconv"
"time"
"github.com/PeernetOfficial/core/reuseport"
"github.com/btcsuite/btcd/btcec"
"github.com/libp2p/go-reuseport"
)
const ipv4BroadcastPort = 12912

View File

@@ -23,8 +23,8 @@ import (
"strconv"
"time"
"github.com/PeernetOfficial/core/reuseport"
"github.com/btcsuite/btcd/btcec"
"github.com/libp2p/go-reuseport"
"golang.org/x/net/ipv6"
)

View File

@@ -16,7 +16,6 @@ Go 1.16 or higher is required. Before compiling, make sure to download and updat
```
go get -u github.com/btcsuite/btcd/btcec
go get -u github.com/libp2p/go-reuseport
go get -u lukechampine.com/blake3
```

42
reuseport/README.md Normal file
View File

@@ -0,0 +1,42 @@
# reuseport
This is a fork from `https://github.com/libp2p/go-reuseport`. Last sync of changes: 16.03.2021
**NOTE:** This package REQUIRES go >= 1.11.
This package enables listening and dialing from _the same_ TCP or UDP port.
This means that the following sockopts may be set:
```
SO_REUSEADDR
SO_REUSEPORT
```
This is a simple package to help with address reuse. This is particularly
important when attempting to do TCP NAT holepunching, which requires a process
to both Listen and Dial on the same TCP port. This package provides some
utilities around enabling this behaviour on various OS.
## Examples
```Go
// listen on the same port. oh yeah.
l1, _ := reuse.Listen("tcp", "127.0.0.1:1234")
l2, _ := reuse.Listen("tcp", "127.0.0.1:1234")
```
```Go
// dial from the same port. oh yeah.
l1, _ := reuse.Listen("tcp", "127.0.0.1:1234")
l2, _ := reuse.Listen("tcp", "127.0.0.1:1235")
c, _ := reuse.Dial("tcp", "127.0.0.1:1234", "127.0.0.1:1235")
```
**Note: cant dial self because tcp/ip stacks use 4-tuples to identify connections, and doing so would clash.**
## Tested
Tested on `darwin`, `linux`, and `windows`.

20
reuseport/addr.go Normal file
View File

@@ -0,0 +1,20 @@
package reuseport
import (
"net"
)
func ResolveAddr(network, address string) (net.Addr, error) {
switch network {
default:
return nil, net.UnknownNetworkError(network)
case "ip", "ip4", "ip6":
return net.ResolveIPAddr(network, address)
case "tcp", "tcp4", "tcp6":
return net.ResolveTCPAddr(network, address)
case "udp", "udp4", "udp6":
return net.ResolveUDPAddr(network, address)
case "unix", "unixgram", "unixpacket":
return net.ResolveUnixAddr(network, address)
}
}

View File

@@ -0,0 +1,9 @@
package reuseport
import (
"syscall"
)
func Control(network, address string, c syscall.RawConn) error {
return nil
}

25
reuseport/control_unix.go Normal file
View File

@@ -0,0 +1,25 @@
// +build !plan9,!windows,!wasm
package reuseport
import (
"syscall"
"golang.org/x/sys/unix"
)
func Control(network, address string, c syscall.RawConn) error {
var err error
c.Control(func(fd uintptr) {
err = unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_REUSEADDR, 1)
if err != nil {
return
}
err = unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_REUSEPORT, 1)
if err != nil {
return
}
})
return err
}

11
reuseport/control_wasm.go Normal file
View File

@@ -0,0 +1,11 @@
// +build wasm
package reuseport
import (
"syscall"
)
func Control(network, address string, c syscall.RawConn) error {
return nil
}

View File

@@ -0,0 +1,13 @@
package reuseport
import (
"syscall"
"golang.org/x/sys/windows"
)
func Control(network, address string, c syscall.RawConn) (err error) {
return c.Control(func(fd uintptr) {
err = windows.SetsockoptInt(windows.Handle(fd), windows.SOL_SOCKET, windows.SO_REUSEADDR, 1)
})
}

64
reuseport/interface.go Normal file
View File

@@ -0,0 +1,64 @@
// Package reuseport provides Listen and Dial functions that set socket
// options in order to be able to reuse ports. You should only use this
// package if you know what SO_REUSEADDR and SO_REUSEPORT are.
//
// For example:
//
// // listen on the same port. oh yeah.
// l1, _ := reuse.Listen("tcp", "127.0.0.1:1234")
// l2, _ := reuse.Listen("tcp", "127.0.0.1:1234")
//
// // dial from the same port. oh yeah.
// l1, _ := reuse.Listen("tcp", "127.0.0.1:1234")
// l2, _ := reuse.Listen("tcp", "127.0.0.1:1235")
// c, _ := reuse.Dial("tcp", "127.0.0.1:1234", "127.0.0.1:1235")
//
// Note: cant dial self because tcp/ip stacks use 4-tuples to identify connections,
// and doing so would clash.
package reuseport
import (
"context"
"net"
"github.com/pkg/errors"
)
// Available returns whether or not SO_REUSEPORT or equivalent behaviour is
// available in the OS.
func Available() bool {
return true
}
var listenConfig = net.ListenConfig{
Control: Control,
}
// Listen listens at the given network and address. see net.Listen
// Returns a net.Listener created from a file discriptor for a socket
// with SO_REUSEPORT and SO_REUSEADDR option set.
func Listen(network, address string) (net.Listener, error) {
return listenConfig.Listen(context.Background(), network, address)
}
// ListenPacket listens at the given network and address. see net.ListenPacket
// Returns a net.Listener created from a file discriptor for a socket
// with SO_REUSEPORT and SO_REUSEADDR option set.
func ListenPacket(network, address string) (net.PacketConn, error) {
return listenConfig.ListenPacket(context.Background(), network, address)
}
// Dial dials the given network and address. see net.Dialer.Dial
// Returns a net.Conn created from a file descriptor for a socket
// with SO_REUSEPORT and SO_REUSEADDR option set.
func Dial(network, laddr, raddr string) (net.Conn, error) {
nla, err := ResolveAddr(network, laddr)
if err != nil {
return nil, errors.Wrap(err, "resolving local addr")
}
d := net.Dialer{
Control: Control,
LocalAddr: nla,
}
return d.Dial(network, raddr)
}