This commit is contained in:
adman
2026-01-12 17:33:26 +01:00
parent 08ddf8dc41
commit 11bf0624a4
16 changed files with 132 additions and 58 deletions
+5 -2
View File
@@ -9,8 +9,11 @@ import (
func Connect(addr string) (ret *proto.Conn, err error) { func Connect(addr string) (ret *proto.Conn, err error) {
ret = &proto.Conn{} ret = &proto.Conn{}
ret.Version = "1.21.8" err = ret.SetVersion("1.21.8")
ret.State = proto_base.Handshaking if err != nil {
return
}
ret.SetState(proto_base.Handshaking)
ret.CompressionThreshold = -1 ret.CompressionThreshold = -1
ret.Actor = proto_base.Client ret.Actor = proto_base.Client
ret.Conn, err = net.Dial("tcp", addr) ret.Conn, err = net.Dial("tcp", addr)
+20
View File
@@ -0,0 +1,20 @@
package client
import (
"net"
"strings"
)
func LookupMinecraftSRV(host string, port uint16) (hostRet string, portRet uint16) {
if port != 25565 {
return
}
_, srvs, err := net.LookupSRV("minecraft", "tcp", host)
if err != nil || len(srvs) == 0 {
return
}
target := strings.TrimSuffix(srvs[0].Target, ".")
hostRet = target
portRet = srvs[0].Port
return
}
+2 -2
View File
@@ -28,7 +28,7 @@ func (c *ConfigIgnorer) OnFinish(_ v1_21_8.ConfigurationToClientPacketFinishConf
if err != nil { if err != nil {
return return
} }
c.State = proto_base.Play c.SetState(proto_base.Play)
err = event.ErrHandlerDone err = event.ErrHandlerDone
return return
} }
@@ -44,7 +44,7 @@ func (c *ConfigIgnorer) OnKeepAlive(packet *v1_21_8.ConfigurationToClientPacketK
} }
func IgnoreConfig(c *proto.Conn) (err error) { func IgnoreConfig(c *proto.Conn) (err error) {
err = c.StartOne(&ConfigIgnorer{c}) err = c.Start(&ConfigIgnorer{c})
if err != nil { if err != nil {
err = errors.Join(err, errors.New("failed to ignore config")) err = errors.Join(err, errors.New("failed to ignore config"))
} }
+23 -21
View File
@@ -16,13 +16,14 @@ import (
"github.com/admin-else/strom/proto" "github.com/admin-else/strom/proto"
"github.com/admin-else/strom/proto_base" "github.com/admin-else/strom/proto_base"
"github.com/admin-else/strom/data"
"github.com/admin-else/strom/proto_generated/v1_21_8" "github.com/admin-else/strom/proto_generated/v1_21_8"
) )
type LoginClient struct { type LoginClient struct {
*proto.Conn *proto.Conn
Account *api.Account Account *api.Account
ServerHost string
ServerPort uint16
GivenAccount *v1_21_8.LoginToClientPacketSuccess GivenAccount *v1_21_8.LoginToClientPacketSuccess
} }
@@ -37,29 +38,30 @@ func (s *LoginClient) OnCycle(_ event.Tick) (err error) {
} }
func (s *LoginClient) OnStart(_ event.OnStart) (err error) { func (s *LoginClient) OnStart(_ event.OnStart) (err error) {
host, portStr, err := net.SplitHostPort(s.RemoteAddr().String()) if s.ServerHost == "" && s.ServerPort == 0 {
if err != nil { var portStr string
return s.ServerHost, portStr, err = net.SplitHostPort(s.RemoteAddr().String())
} if err != nil {
versionData, err := data.LookUpProtocolVersionByName(s.Version) return
if err != nil { }
return var portUint uint64
} portUint, err = strconv.ParseUint(portStr, 10, 16)
s.ProtocolVersion = int32(versionData.Version) if err != nil {
port, err := strconv.Atoi(portStr) return
if err != nil { }
return s.ServerPort = uint16(portUint)
} }
err = s.Send(&v1_21_8.HandshakingToServerPacketSetProtocol{ err = s.Send(&v1_21_8.HandshakingToServerPacketSetProtocol{
ProtocolVersion: s.ProtocolVersion, ProtocolVersion: s.ProtocolVersion,
ServerHost: host, ServerHost: s.ServerHost,
ServerPort: uint16(port), ServerPort: s.ServerPort,
NextState: int32(proto_base.Login), NextState: int32(proto_base.Login),
}) })
if err != nil { if err != nil {
return return
} }
s.State = proto_base.Login s.SetState(proto_base.Login)
err = s.Send(&v1_21_8.LoginToServerPacketLoginStart{Username: s.Account.Name, PlayerUUID: s.Account.Uuid}) err = s.Send(&v1_21_8.LoginToServerPacketLoginStart{Username: s.Account.Name, PlayerUUID: s.Account.Uuid})
return return
} }
@@ -118,13 +120,13 @@ func (s *LoginClient) OnSuccess(success *v1_21_8.LoginToClientPacketSuccess) (er
if err != nil { if err != nil {
return return
} }
s.State = proto_base.Configuration s.SetState(proto_base.Configuration)
err = event.ErrHandlerDone err = event.ErrHandlerDone
return return
} }
func Login(c *proto.Conn, account *api.Account) (err error) { func Login(c *proto.Conn, account *api.Account) (err error) {
err = c.StartOne(&LoginClient{ err = c.Start(&LoginClient{
Conn: c, Conn: c,
Account: account, Account: account,
}) })
@@ -139,12 +141,12 @@ func ConnectAndLogin(connectTo string, account *api.Account) (c *proto.Conn, err
if err != nil { if err != nil {
return return
} }
err = c.StartOne(&LoginClient{ err = c.Start(&LoginClient{
Conn: c, Conn: c,
Account: account, Account: account,
}) })
if err != nil { if err != nil {
err = errors.Join(err, errors.New("failed to login")) err = errors.Join(errors.New("failed to login"), err)
} }
return return
} }
+1 -1
View File
@@ -42,7 +42,7 @@ func (s *StatusClient) OnStart(_ event.OnStart) (err error) {
if err != nil { if err != nil {
return return
} }
s.State = proto_base.Status s.SetState(proto_base.Status)
err = s.Send(&v1_21_8.StatusToServerPacketPingStart{}) err = s.Send(&v1_21_8.StatusToServerPacketPingStart{})
return return
} }
+22
View File
@@ -3,6 +3,28 @@ package crypto
// https://github.com/Tnze/go-mc/blob/master/net/CFB8/cfb8.go // https://github.com/Tnze/go-mc/blob/master/net/CFB8/cfb8.go
// Package CFB8 implements CFB8 block cipher mode of operation used by Minecraft protocol. // Package CFB8 implements CFB8 block cipher mode of operation used by Minecraft protocol.
// MIT License
//
//Copyright (c) 2019 Tnze
//
//Permission is hereby granted, free of charge, to any person obtaining a copy
//of this software and associated documentation files (the "Software"), to deal
//in the Software without restriction, including without limitation the rights
//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//copies of the Software, and to permit persons to whom the Software is
//furnished to do so, subject to the following conditions:
//
//The above copyright notice and this permission notice shall be included in all
//copies or substantial portions of the Software.
//
//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
//SOFTWARE.
import ( import (
"crypto/cipher" "crypto/cipher"
"crypto/subtle" "crypto/subtle"
+2 -1
View File
@@ -33,6 +33,7 @@ var ErrHandlerDone = errors.New("handler done")
// ErrDontForward will stop the event from being forwarded to other handlers, including anything handlers. // ErrDontForward will stop the event from being forwarded to other handlers, including anything handlers.
var ErrDontForward = errors.New("dont forward") var ErrDontForward = errors.New("dont forward")
// FindHandlers initializes and populates the HandlerFunctions map by reflecting over methods of registered handlers.
func (l *Loop) FindHandlers() { func (l *Loop) FindHandlers() {
l.HandlerFunctions = make(map[reflect.Type][]reflect.Value) l.HandlerFunctions = make(map[reflect.Type][]reflect.Value)
for _, inst := range l.Handlers { for _, inst := range l.Handlers {
@@ -62,7 +63,7 @@ func (l *Loop) FireFound(event any) (found bool, err error) {
errV := handler.Call([]reflect.Value{reflect.ValueOf(event)})[0] errV := handler.Call([]reflect.Value{reflect.ValueOf(event)})[0]
if !errV.IsNil() { if !errV.IsNil() {
err = errV.Interface().(error) err = errV.Interface().(error)
err = errors.Join(err, fmt.Errorf("event handler failed: at ")) err = errors.Join(fmt.Errorf("event handler failed at: %s(%T)", handler.Type().In(0), event), err)
return return
} }
} }
+17 -7
View File
@@ -4,6 +4,7 @@ import (
"bytes" "bytes"
"errors" "errors"
"io" "io"
"sync"
"github.com/admin-else/strom/data" "github.com/admin-else/strom/data"
"github.com/admin-else/strom/event" "github.com/admin-else/strom/event"
@@ -34,12 +35,25 @@ func (u *UnCodablePacket) Decode(r io.Reader) (err error) {
type Conn struct { type Conn struct {
RawConn RawConn
*event.Loop *event.Loop
State proto_base.State state proto_base.State
stateMutex sync.RWMutex
Actor proto_base.Actor Actor proto_base.Actor
Version string Version string
ProtocolVersion int32 ProtocolVersion int32
} }
func (c *Conn) SetState(state proto_base.State) {
c.stateMutex.Lock()
defer c.stateMutex.Unlock()
c.state = state
}
func (c *Conn) State() proto_base.State {
c.stateMutex.RLock()
defer c.stateMutex.RUnlock()
return c.state
}
func (c *Conn) SetVersion(version string) (err error) { func (c *Conn) SetVersion(version string) (err error) {
c.Version = version c.Version = version
versionData, err := data.LookUpProtocolVersionByName(c.Version) versionData, err := data.LookUpProtocolVersionByName(c.Version)
@@ -55,7 +69,7 @@ func (c *Conn) Send(packet proto_base.EncodeDecodeAble) (err error) {
case *UnCodablePacket: case *UnCodablePacket:
err = c.SendRaw(packet.Data) err = c.SendRaw(packet.Data)
default: default:
i, ok := LookupPacketInfoByTypeLookupPacketInfoByTypeAndMore(packet, c.State) i, ok := LookupPacketInfoByTypeLookupPacketInfoByTypeAndMore(packet, c.State())
if !ok { if !ok {
err = BadPacketTypeError err = BadPacketTypeError
} }
@@ -83,7 +97,7 @@ func (c *Conn) Receive() (packet proto_base.EncodeDecodeAble, err error) {
if err != nil { if err != nil {
return return
} }
packet, ok := LookUpTypeByPacketInfoAndCopyType(c.Actor.ReceiveDirection(), c.State, id, c.ProtocolVersion) packet, ok := LookUpTypeByPacketInfoAndCopyType(c.Actor.ReceiveDirection(), c.State(), id, c.ProtocolVersion)
if !ok { if !ok {
packet = &UnCodablePacket{Err: BadPacketIdError, Data: packetBytes, Direction: c.Actor.ReceiveDirection()} packet = &UnCodablePacket{Err: BadPacketIdError, Data: packetBytes, Direction: c.Actor.ReceiveDirection()}
return return
@@ -110,10 +124,6 @@ func (c *Conn) OnTick(_ event.Tick) (err error) {
return return
} }
func (c *Conn) StartOne(handler any) (err error) {
return c.Start(handler)
}
func (c *Conn) Start(handlers ...any) (err error) { func (c *Conn) Start(handlers ...any) (err error) {
c.Loop = &event.Loop{} c.Loop = &event.Loop{}
c.Handlers = append(c.Handlers, c) c.Handlers = append(c.Handlers, c)
+1 -1
View File
@@ -25,7 +25,7 @@ func NewStateFuzzer(state proto_base.State, actor proto_base.Actor) func(t *test
b1 := bytes.NewBuffer(inbytes) b1 := bytes.NewBuffer(inbytes)
b2 := bytes.NewBuffer(nil) b2 := bytes.NewBuffer(nil)
conn := server.Servee(nil) conn := server.Servee(nil)
conn.State = state conn.SetState(state)
conn.Actor = actor conn.Actor = actor
conn.R = b1 conn.R = b1
conn.W = b2 conn.W = b2
+18 -6
View File
@@ -21,15 +21,21 @@ type RawConn struct {
} }
func (c *RawConn) SendRaw(rawPacketBytes []byte) (err error) { func (c *RawConn) SendRaw(rawPacketBytes []byte) (err error) {
//fmt.Println("send:", rawPacketBytes)
var packetBytes []byte var packetBytes []byte
if c.CompressionThreshold > 0 { if c.CompressionThreshold > 0 {
packetBuffer := bytes.NewBuffer(nil) packetBuffer := bytes.NewBuffer(nil)
if int32(len(packetBytes)) >= c.CompressionThreshold { if int32(len(rawPacketBytes)) >= c.CompressionThreshold {
err = proto_base.EncodeVarInt(packetBuffer, int32(len(packetBytes))) err = proto_base.EncodeVarInt(packetBuffer, int32(len(rawPacketBytes)))
if err != nil { if err != nil {
return return
} }
_, err = zlib.NewWriter(packetBuffer).Write(rawPacketBytes) zW := zlib.NewWriter(packetBuffer)
_, err = zW.Write(rawPacketBytes)
if err != nil {
return
}
err = zW.Close()
if err != nil { if err != nil {
return return
} }
@@ -47,11 +53,16 @@ func (c *RawConn) SendRaw(rawPacketBytes []byte) (err error) {
} else { } else {
packetBytes = rawPacketBytes packetBytes = rawPacketBytes
} }
err = proto_base.EncodeVarInt(c.W, int32(len(packetBytes))) packetWithLenBuffer := bytes.NewBuffer(nil)
err = proto_base.EncodeVarInt(packetWithLenBuffer, int32(len(packetBytes)))
if err != nil { if err != nil {
return return
} }
_, err = c.W.Write(packetBytes) _, err = packetWithLenBuffer.Write(packetBytes)
if err != nil {
return
}
_, err = c.W.Write(packetWithLenBuffer.Bytes())
return return
} }
@@ -86,15 +97,16 @@ func (c *RawConn) ReceiveRaw() (packetBytes []byte, err error) {
if err != nil { if err != nil {
return return
} }
defer zReader.Close()
packetBytes, err = io.ReadAll(zReader) packetBytes, err = io.ReadAll(zReader)
if err != nil { if err != nil {
return return
} }
err = zReader.Close()
} }
} else { } else {
packetBytes = rawPacketBytes packetBytes = rawPacketBytes
} }
//fmt.Println("recv:", packetBytes)
return return
} }
+5 -2
View File
@@ -28,7 +28,7 @@ func (d Direction) Opposite() Direction {
return d ^ 1 return d ^ 1
} }
type State int type State int32
const ( const (
Handshaking State = iota Handshaking State = iota
@@ -82,7 +82,10 @@ var ToDoError = errors.New("to do")
var BadTypeError = errors.New("bad type") var BadTypeError = errors.New("bad type")
func (b *RestBuffer) Encode(w io.Writer) (err error) { func (b *RestBuffer) Encode(w io.Writer) (err error) {
_, err = w.Write(*b) n, err := w.Write(*b)
if n != len(*b) {
panic("fucking write not writing all")
}
return return
} }
+1 -1
View File
@@ -46,7 +46,7 @@ func GeneratePacketInfoFile(versions []string, packetInfos []PacketInfo) (err er
KeyValueExpr(Ident("Type"), AddrOf(CompLit(typeExpr, nil))), KeyValueExpr(Ident("Type"), AddrOf(CompLit(typeExpr, nil))),
KeyValueExpr(Ident("Name"), StrLit(p.Name)), KeyValueExpr(Ident("Name"), StrLit(p.Name)),
KeyValueExpr(Ident("Direction"), Selector("proto_base", p.Direction)), KeyValueExpr(Ident("Direction"), Selector("proto_base", p.Direction)),
KeyValueExpr(Ident("State"), Selector("proto_base", p.State)), KeyValueExpr(Ident("state"), Selector("proto_base", p.State)),
KeyValueExpr(Ident("PacketId"), NumLit(int(packetId))), KeyValueExpr(Ident("PacketId"), NumLit(int(packetId))),
KeyValueExpr(Ident("ProtocolVersion"), NumLit(protocolVersion)), KeyValueExpr(Ident("ProtocolVersion"), NumLit(protocolVersion)),
})) }))
+3 -4
View File
@@ -10,9 +10,8 @@ import (
func Servee(c net.Conn) (ret *proto.Conn) { func Servee(c net.Conn) (ret *proto.Conn) {
ret = &proto.Conn{} ret = &proto.Conn{}
ret.Version = "1.21.8" _ = ret.SetVersion("1.21.8") // cant fail
ret.ProtocolVersion = 772 ret.SetState(proto_base.Handshaking)
ret.State = proto_base.Handshaking
ret.CompressionThreshold = -1 ret.CompressionThreshold = -1
ret.Actor = proto_base.Server ret.Actor = proto_base.Server
ret.Conn = c ret.Conn = c
@@ -27,7 +26,7 @@ func ServeClient(cNet net.Conn, factory func(c *proto.Conn) (h any, err error))
if err != nil { if err != nil {
return return
} }
err = c.StartOne(h) err = c.Start(h)
return return
} }
+7 -5
View File
@@ -28,14 +28,16 @@ func (u UnexpectedNextStateError) Error() string {
type LoginServer struct { type LoginServer struct {
*proto.Conn *proto.Conn
//OnlineMode bool TODO: implement this //OnlineMode bool FIXME: implement this
ServerHost string
Requested NameAndUUID Requested NameAndUUID
Given *NameAndUUID Given *NameAndUUID
CompressionThreshold int32 CompressionThreshold int32
} }
func (l *LoginServer) OnHandshake(packet *v1_21_8.HandshakingToServerPacketSetProtocol) (err error) { func (l *LoginServer) OnHandshake(packet *v1_21_8.HandshakingToServerPacketSetProtocol) (err error) {
l.State = proto_base.State(packet.NextState) l.SetState(proto_base.State(packet.NextState))
l.ServerHost = packet.ServerHost
if packet.NextState != int32(proto_base.Login) { if packet.NextState != int32(proto_base.Login) {
err = UnexpectedNextStateError{proto_base.State(packet.NextState)} err = UnexpectedNextStateError{proto_base.State(packet.NextState)}
return return
@@ -70,7 +72,7 @@ func (l *LoginServer) OnLoginStart(packet *v1_21_8.LoginToServerPacketLoginStart
} }
func (l *LoginServer) OnLoginAcknowledged(_ *v1_21_8.LoginToServerPacketLoginAcknowledged) (err error) { func (l *LoginServer) OnLoginAcknowledged(_ *v1_21_8.LoginToServerPacketLoginAcknowledged) (err error) {
l.State = proto_base.Configuration l.SetState(proto_base.Configuration)
err = event.ErrHandlerDone err = event.ErrHandlerDone
return return
} }
@@ -92,7 +94,7 @@ func (l *LoginServer) OnCycle(_ event.Tick) (err error) {
func ServeLogin(c *proto.Conn) (ret *LoginServer, err error) { func ServeLogin(c *proto.Conn) (ret *LoginServer, err error) {
ret = &LoginServer{Conn: c} ret = &LoginServer{Conn: c}
ret.CompressionThreshold = 256 ret.CompressionThreshold = 256
err = ret.StartOne(ret) err = ret.Start(ret)
return return
} }
@@ -102,6 +104,6 @@ func ServeLoginWithOtherAccount(c *proto.Conn, a *api.Account) (ret *LoginServer
UUID: a.Uuid, UUID: a.Uuid,
}} }}
ret.CompressionThreshold = 256 ret.CompressionThreshold = 256
err = ret.StartOne(ret) err = ret.Start(ret)
return return
} }
+1 -1
View File
@@ -54,6 +54,6 @@ func ServeStatus(c *proto.Conn, s StatusResponse) (err error) {
Conn: c, Conn: c,
Status: string(status), Status: string(status),
} }
err = server.StartOne(server) err = server.Start(server)
return return
} }
+4 -4
View File
@@ -74,8 +74,8 @@ func (p *Proxy) OnFinishConfiguration(packet *v1_21_8.ConfigurationToServerPacke
if err != nil { if err != nil {
return return
} }
p.State = proto_base.Play p.SetState(proto_base.Play)
p.Client.State = proto_base.Play p.Client.SetState(proto_base.Play)
return return
} }
@@ -151,10 +151,10 @@ func main() {
defer pc.Close() defer pc.Close()
defer p.Close() defer p.Close()
go func() { go func() {
errChan <- pc.StartOne(pc) errChan <- pc.Start(pc)
}() }()
go func() { go func() {
errChan <- p.StartOne(p) errChan <- p.Start(p)
}() }()
err = <-errChan err = <-errChan
return return