Add connection webhook notifications (#392)

Also 

* Added decode of LoginStart message
* Add metrics backend constants
* Updated usage section
* Documented MaxFrameLength
This commit is contained in:
Geoff Bourne
2025-04-21 20:28:34 -05:00
committed by GitHub
parent a058d6e21d
commit cc590524c4
13 changed files with 585 additions and 66 deletions
+18 -38
View File
@@ -4,6 +4,7 @@ import (
"bufio"
"bytes"
"encoding/binary"
"github.com/google/uuid"
"io"
"net"
"strings"
@@ -15,22 +16,27 @@ import (
"golang.org/x/text/transform"
)
func ReadPacket(reader io.Reader, addr net.Addr, state State) (*Packet, error) {
// MaxFrameLength is declared at https://minecraft.wiki/w/Java_Edition_protocol#Packet_format
// to be 2^21 - 1
const MaxFrameLength = 2097151
// ReadPacket reads a packet from the given reader based on the provided connection state.
// Returns a pointer to the Packet and an error if reading fails.
// Handles legacy server list ping packet when in the handshaking state.
// The provided addr is used for logging purposes.
func ReadPacket(reader *bufio.Reader, addr net.Addr, state State) (*Packet, error) {
logrus.
WithField("client", addr).
Debug("Reading packet")
if state == StateHandshaking {
bufReader := bufio.NewReader(reader)
data, err := bufReader.Peek(1)
data, err := reader.Peek(1)
if err != nil {
return nil, err
}
if data[0] == PacketIdLegacyServerListPing {
return ReadLegacyServerListPing(bufReader, addr)
} else {
reader = bufReader
return ReadLegacyServerListPing(reader, addr)
}
}
@@ -161,8 +167,7 @@ func ReadFrame(reader io.Reader, addr net.Addr) (*Frame, error) {
return nil, err
}
// Limit frame length to 2^21 - 1
if frame.Length > 2097151 {
if frame.Length > MaxFrameLength {
return nil, errors.Errorf("frame length %d too large", frame.Length)
}
@@ -280,36 +285,11 @@ func ReadUnsignedInt(reader io.Reader) (uint32, error) {
return value, nil
}
func ReadHandshake(data interface{}) (*Handshake, error) {
dataBytes, ok := data.([]byte)
if !ok {
return nil, errors.New("data is not expected byte slice")
}
handshake := &Handshake{}
buffer := bytes.NewBuffer(dataBytes)
var err error
handshake.ProtocolVersion, err = ReadVarInt(buffer)
func ReadUuid(reader io.Reader) (uuid.UUID, error) {
uuidBytes := make([]byte, 16)
_, err := io.ReadFull(reader, uuidBytes)
if err != nil {
return nil, err
return uuid.UUID{}, err
}
handshake.ServerAddress, err = ReadString(buffer)
if err != nil {
return nil, err
}
handshake.ServerPort, err = ReadUnsignedShort(buffer)
if err != nil {
return nil, err
}
nextState, err := ReadVarInt(buffer)
if err != nil {
return nil, err
}
handshake.NextState = nextState
return handshake, nil
return uuid.FromBytes(uuidBytes)
}