Skip to content

Commit

Permalink
Pong tweaks, debug logging, IPv6 support
Browse files Browse the repository at this point in the history
  • Loading branch information
jhead committed Apr 12, 2020
1 parent 269e0f4 commit cdcb69f
Show file tree
Hide file tree
Showing 8 changed files with 120 additions and 40 deletions.
5 changes: 5 additions & 0 deletions README.md
Expand Up @@ -34,11 +34,16 @@ a few seconds. If not, you did something wrong. Or I did ;)
Usage: ./phantom-<os> [options] -server <server-ip>
Options:
-6 Optional: Enables IPv6 support on port 19133 (experimental)
-bind string
Optional: IP address to listen on. Defaults to all interfaces. (default "0.0.0.0")
-bind_port int
Optional: Port to listen on. Defaults to 0, which selects a random port.
Note that phantom always binds to port 19132 as well, so both ports need to be open.
-debug
Optional: Enables debug logging
-remove_ports
Optional: Forces ports to be excluded from pong packets (experimental)
-server string
Required: Bedrock/MCPE server IP address and port (ex: 1.2.3.4:19132)
-timeout int
Expand Down
17 changes: 17 additions & 0 deletions cmd/phantom.go
Expand Up @@ -8,6 +8,8 @@ import (
"time"

"github.com/jhead/phantom/internal/proxy"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
)

var bindAddressString string
Expand All @@ -22,6 +24,9 @@ func main() {
bindArg := flag.String("bind", "0.0.0.0", "Optional: IP address to listen on. Defaults to all interfaces.")
bindPortArg := flag.Int("bind_port", 0, "Optional: Port to listen on. Defaults to 0, which selects a random port.\nNote that phantom always binds to port 19132 as well, so both ports need to be open.")
timeoutArg := flag.Int("timeout", 60, "Optional: Seconds to wait before cleaning up a disconnected client")
debugArg := flag.Bool("debug", false, "Optional: Enables debug logging")
ipv6Arg := flag.Bool("6", false, "Optional: Enables IPv6 support on port 19133 (experimental)")
removePortsArg := flag.Bool("remove_ports", false, "Optional: Forces ports to be excluded from pong packets (experimental)")

flag.Usage = usage
flag.Parse()
Expand All @@ -36,13 +41,25 @@ func main() {
idleTimeout := time.Duration(*timeoutArg) * time.Second
bindPortInt = uint16(*bindPortArg)

logLevel := zerolog.InfoLevel
if *debugArg {
logLevel = zerolog.DebugLevel
}

fmt.Printf("Starting up with remote server IP: %s\n", serverAddressString)

// Configure logging output
log.Logger = log.
Output(zerolog.ConsoleWriter{Out: os.Stdout}).
Level(logLevel)

proxyServer, err := proxy.New(proxy.ProxyPrefs{
bindAddressString,
bindPortInt,
serverAddressString,
idleTimeout,
*ipv6Arg,
*removePortsArg,
})

if err != nil {
Expand Down
2 changes: 2 additions & 0 deletions go.mod
Expand Up @@ -3,7 +3,9 @@ module github.com/jhead/phantom
go 1.12

require (
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b
github.com/libp2p/go-reuseport v0.0.1
github.com/rs/zerolog v1.18.0
github.com/stretchr/testify v1.3.0
github.com/tevino/abool v0.0.0-20170917061928-9b9efcf221b5
)
14 changes: 14 additions & 0 deletions go.sum
@@ -1,15 +1,29 @@
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/libp2p/go-reuseport v0.0.1 h1:7PhkfH73VXfPJYKQ6JwS5I/eVcoyYi9IMNGc6FWpFLw=
github.com/libp2p/go-reuseport v0.0.1/go.mod h1:jn6RmB1ufnQwl0Q1f+YxAj8isJgDCQzaaxIFYDhcYEA=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
github.com/rs/zerolog v1.18.0 h1:CbAm3kP2Tptby1i9sYy2MGRg0uxIN9cyDb59Ys7W8z8=
github.com/rs/zerolog v1.18.0/go.mod h1:9nvC1axdVrAHcu/s9taAVfBuIdTZLVQmKQyvrUjF5+I=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/tevino/abool v0.0.0-20170917061928-9b9efcf221b5 h1:hNna6Fi0eP1f2sMBe/rJicDmaHmoXGe1Ta84FPYHLuE=
github.com/tevino/abool v0.0.0-20170917061928-9b9efcf221b5/go.mod h1:f1SCnEOt6sc3fOJfPQDRDzHOtSXuTtnz0ImG9kPRDV0=
github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190228124157-a34e9553db1e h1:ZytStCyV048ZqDsWHiYDdoI2Vd4msMcrDECFxS+tL9c=
golang.org/x/sys v0.0.0-20190228124157-a34e9553db1e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20190828213141-aed303cbaa74/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
12 changes: 5 additions & 7 deletions internal/clientmap/clientmap.go
Expand Up @@ -5,7 +5,7 @@ import (
"sync"
"time"

"github.com/jhead/phantom/internal/logging"
"github.com/rs/zerolog/log"
"github.com/tevino/abool"
)

Expand All @@ -27,8 +27,6 @@ type clientEntry struct {

type ServerConnHandler func(*net.UDPConn)

var logger = logging.Get()

func New(idleTimeout time.Duration, idleCheckInterval time.Duration) *ClientMap {
clientMap := ClientMap{
idleTimeout,
Expand Down Expand Up @@ -63,7 +61,7 @@ func (cm *ClientMap) Close() {
// Cleans up clients and remote connections that have not been used in a while.
// Blocks until the ClientMap has been closed.
func (cm *ClientMap) idleCleanupLoop() {
logger.Println("Starting idle connection handler")
log.Info().Msg("Starting idle connection handler")

// Loop forever using a channel that emits every IdleCheckInterval
for currentTime := range time.Tick(cm.IdleCheckInterval) {
Expand All @@ -75,7 +73,7 @@ func (cm *ClientMap) idleCleanupLoop() {
cm.mutex.Lock()
for key, client := range cm.clients {
if client.lastActive.Add(cm.IdleTimeout).Before(currentTime) {
logger.Printf("Cleaning up idle connection: %s", key)
log.Info().Msgf("Cleaning up idle connection: %s", key)
cm.clients[key].conn.Close()
delete(cm.clients, key)
}
Expand Down Expand Up @@ -106,7 +104,7 @@ func (cm *ClientMap) Get(
}

// New connection needed
logger.Printf("Opening connection to %s for new client %s!\n", remote, clientAddr)
log.Info().Msgf("Opening connection to %s for new client %s!", remote, clientAddr)
newServerConn, err := newServerConnection(remote)
if err != nil {
return nil, err
Expand All @@ -125,7 +123,7 @@ func (cm *ClientMap) Get(

// Creates a UDP connection to the remote address
func newServerConnection(remote *net.UDPAddr) (*net.UDPConn, error) {
logger.Printf("Opening connection to %s\n", remote)
log.Info().Msgf("Opening connection to %s", remote)

conn, err := net.DialUDP("udp", nil, remote)
if err != nil {
Expand Down
12 changes: 0 additions & 12 deletions internal/logging/logging.go

This file was deleted.

16 changes: 11 additions & 5 deletions internal/proto/proto.go
Expand Up @@ -4,6 +4,7 @@ import (
"bytes"
"encoding/binary"
"fmt"
"regexp"
"strings"

"github.com/jhead/phantom/internal/util"
Expand All @@ -29,11 +30,12 @@ type PongData struct {
SubMOTD string
GameType string
NintendoLimited string
// Specifically omit these two because they cause issues
// Port4 string
// Port6 string
Port4 string
Port6 string
}

var dupeSemicolonRegex = regexp.MustCompile(";{2,}$")

func ReadUnconnectedReply(in []byte) (reply *UnconnectedReply, err error) {
reply = &UnconnectedReply{}
buf := bytes.NewBuffer(in)
Expand Down Expand Up @@ -114,8 +116,12 @@ func writePong(pong PongData) string {
var pongDataFields []string
pongDataFieldsRaw := util.MapStructToFields(&pong)
for _, value := range pongDataFieldsRaw {
pongDataFields = append(pongDataFields, fmt.Sprintf("%v", value))
stringValue := fmt.Sprintf("%v", value)
pongDataFields = append(pongDataFields, stringValue)
}

return strings.Join(pongDataFields, ";")
// Ensure that there aren't a bunch of ; on the end, but at least one
joined := strings.Join(pongDataFields, ";")
joined = dupeSemicolonRegex.ReplaceAllString(joined, "")
return fmt.Sprintf("%s;", joined)
}

0 comments on commit cdcb69f

Please sign in to comment.