Skip to content

Commit

Permalink
refactor: handshake response
Browse files Browse the repository at this point in the history
  • Loading branch information
haveachin committed Jun 19, 2024
1 parent 020d7a8 commit 202df92
Show file tree
Hide file tree
Showing 10 changed files with 134 additions and 68 deletions.
35 changes: 34 additions & 1 deletion configs/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,37 @@ filters:

# Windows Length is the time frame for the Request Limit.
#
windowLength: 1s
windowLength: 1s

# Reponse that the player sees when there is no server for that domain.
#
notFoundResponse:
# The status response that should be displayed to the players
#
status:

# The name of the version.
# This is displayed on the client side when the version is incompatible.
#
versionName: "Infrared 1.20.6"

# The protocol version number determens if the version of the client is compatible with the server.
# A list of protocol versions can be found here: https://wiki.vg/Protocol_version_numbers
# Set this to -1 to mirror the client version back.
#
protocolNumber: -1
maxPlayerCount: 0
playerCount: 0
playerSamples: []

# Server icon can be provided as base64 or path to a file.
#
icon: ""

# MOTD can be just a string or a JSON Text Component.
#
motd: "Server not found"

# Reason why the player was disconnected during login.
#
message: "Server not found"
28 changes: 2 additions & 26 deletions configs/proxy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,36 +19,14 @@ addresses:
# times out during status or login request.
#
dialTimeoutResponse:
# The status response that should be displayed to the players
#
status:

# The name of the version.
# This is displayed on the client side when the version is incompatible.
#
versionName: "Infrared 1.20.6"

# The protocol version number determens if the version of the client is compatible with the server.
# A list of protocol versions can be found here: https://wiki.vg/Protocol_version_numbers
# Set this to -1 to mirror the client version back.
#
protocolNumber: 766
maxPlayerCount: 20
playerCount: 0
playerSamples:
- name: ""
uuid: ""

# Server icon can be provided as base64 or path to a file.
#
playerSamples: []
icon: ""

# MOTD can be just a string or a JSON Text Component.
#
motd: "Unable to reach backend server"

# Reason why the player was disconnected during login.
#
message: "Unable to reach backend server"

# Override Status is similar to the dial timeout response status
Expand All @@ -59,8 +37,6 @@ overrideStatus:
protocolNumber: 766
maxPlayerCount: 20
playerCount: 0
playerSamples:
- name: ""
uuid: ""
playerSamples: []
icon: ""
motd: "Unable to reach backend server"
6 changes: 6 additions & 0 deletions docs/faq.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# FAQ

## Will you add (Query)[https://wiki.vg/Query]?

No, it is fundamentally not compatibale with reverse proxies.

10 changes: 10 additions & 0 deletions docs/features/status-cache.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Status Cache

The status cache aims to reduces the ping frequency and the general load on your backend servers and Infrared.
It is implemented by via a double hash map to reduce it's memory footprint.

## Enable Status Caching

```yaml

```
4 changes: 4 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,9 @@ require (
require (
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/tidwall/gjson v1.17.1 // indirect
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.1 // indirect
github.com/tidwall/sjson v1.2.5 // indirect
golang.org/x/sys v0.21.0 // indirect
)
10 changes: 10 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,16 @@ github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8=
github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/gjson v1.17.1 h1:wlYEnwqAHgzmhNUFfw7Xalt2JzQvsMx2Se4PcoFCT/U=
github.com/tidwall/gjson v1.17.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4=
github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY=
github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o=
Expand Down
42 changes: 23 additions & 19 deletions pkg/infrared/handshake_response.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ type HandshakeStatusResponseConfig struct {
MOTD string `yaml:"motd"`
}

func (cfg HandshakeStatusResponseConfig) IsProtocolNumberDynamic() bool {
return cfg.ProtocolNumber == -1
}

type HandshakeResponseConfig struct {
StatusConfig HandshakeStatusResponseConfig `yaml:"status"`
Message string `yaml:"message"`
Expand All @@ -49,29 +53,36 @@ type HandshakeResponseConfig struct {
type HandshakeResponse struct {
Config HandshakeResponseConfig

statusOnce sync.Once
statusRespJSON status.ResponseJSON
statusRespPk protocol.Packet
statusOnce sync.Once
statusResp status.ClientBoundResponse
statusRespPk protocol.Packet

loginOnce sync.Once
loginRespPk protocol.Packet
}

func (r *HandshakeResponse) StatusResponse(protVer protocol.Version) (status.ResponseJSON, protocol.Packet) {
func (r *HandshakeResponse) StatusResponse(protVer protocol.Version) protocol.Packet {
cfg := r.Config.StatusConfig
if cfg.ProtocolNumber < 0 {
return r.renderStatusPacket(protVer)
}

r.statusOnce.Do(func() {
protVer = protocol.Version(cfg.ProtocolNumber)
r.statusRespJSON, r.statusRespPk = r.renderStatusPacket(protVer)
r.renderStatusPacket(protVer)
})

return r.statusRespJSON, r.statusRespPk
if cfg.IsProtocolNumberDynamic() {
if err := r.statusResp.SetVersionProtocol(protVer); err != nil {
panic(err)
}

if err := r.statusResp.Marshal(&r.statusRespPk); err != nil {
panic(err)
}
}

return r.statusRespPk
}

func (r *HandshakeResponse) renderStatusPacket(protVer protocol.Version) (status.ResponseJSON, protocol.Packet) {
func (r *HandshakeResponse) renderStatusPacket(protVer protocol.Version) {
cfg := r.Config.StatusConfig
respJSON := status.ResponseJSON{
Version: status.VersionJSON{
Expand All @@ -87,21 +98,14 @@ func (r *HandshakeResponse) renderStatusPacket(protVer protocol.Version) (status
Description: parseJSONTextComponent(cfg.MOTD),
}

respBytes, err := json.Marshal(r.statusRespJSON)
respBytes, err := json.Marshal(respJSON)
if err != nil {
panic(err)
}

statusPk := status.ClientBoundResponse{
r.statusResp = status.ClientBoundResponse{
JSONResponse: protocol.String(string(respBytes)),
}

var respPk protocol.Packet
if err := statusPk.Marshal(&respPk); err != nil {
panic(err)
}

return respJSON, respPk
}

func (r *HandshakeResponse) LoginReponse() protocol.Packet {
Expand Down
10 changes: 8 additions & 2 deletions pkg/infrared/infrared.go
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,8 @@ func (ir *Infrared) handleConn(c *clientConn) error {
switch {
case errors.Is(err, ErrServerNotReachable) && c.handshake.IsLoginRequest():
return ir.handleLoginDisconnect(c, resp)
case errors.Is(err, ErrServerNotFound):
return ir.handleServerNotFound(c)
default:
return err
}
Expand All @@ -262,7 +264,7 @@ func (ir *Infrared) handleConn(c *clientConn) error {
}

func handleStatus(c *clientConn, resp ServerResponse) error {
if err := c.WritePacket(resp.StatusResponse); err != nil {
if err := c.WritePacket(resp.Packet); err != nil {
return err
}

Expand All @@ -279,7 +281,11 @@ func handleStatus(c *clientConn, resp ServerResponse) error {
}

func (ir *Infrared) handleLoginDisconnect(c *clientConn, resp ServerResponse) error {
return c.WritePacket(resp.StatusResponse)
return c.WritePacket(resp.Packet)
}

func (ir *Infrared) handleServerNotFound(c *clientConn) error {

Check warning on line 287 in pkg/infrared/infrared.go

View workflow job for this annotation

GitHub Actions / Lint

unused-parameter: parameter 'c' seems to be unused, consider removing or renaming it as _ (revive)
return nil
}

func (ir *Infrared) handleLogin(c *clientConn, resp ServerResponse) error {
Expand Down
19 changes: 19 additions & 0 deletions pkg/infrared/protocol/status/clientbound_response.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@ package status

import (
"encoding/json"
"errors"
"fmt"

"github.com/haveachin/infrared/pkg/infrared/protocol"
"github.com/tidwall/sjson"
)

const (
Expand Down Expand Up @@ -31,6 +34,22 @@ func (pk *ClientBoundResponse) Unmarshal(packet protocol.Packet) error {
)
}

func (pk *ClientBoundResponse) SetVersionProtocol(protVer protocol.Version) error {
jsonStr := string(pk.JSONResponse)
if jsonStr == "" {
return errors.New("no json in packet")
}

version := int32(protVer)
jsonStr, err := sjson.Set(jsonStr, "version.protocol", version)
if err != nil {
return fmt.Errorf("set version.protocol: %w", err)
}
pk.JSONResponse = protocol.String(jsonStr)

return nil
}

type ResponseJSON struct {
Version VersionJSON `json:"version"`
Players PlayersJSON `json:"players"`
Expand Down
Loading

0 comments on commit 202df92

Please sign in to comment.