diff --git a/event_bus.go b/event_bus.go index 3f4111f..f679938 100644 --- a/event_bus.go +++ b/event_bus.go @@ -45,6 +45,7 @@ func FireEvent(inst HandlerInst, event any, handlers map[reflect.Type]reflect.Va } func (c *Conn) Start(inst HandlerInst) (err error) { + _ = *c // exit early on nil connection handlers := FindHandlers(inst) err = FireEvent(inst, OnStart{}, handlers) for err == nil { diff --git a/examples/client/main.go b/examples/client/main.go index 679d8c3..4a4d222 100644 --- a/examples/client/main.go +++ b/examples/client/main.go @@ -5,17 +5,18 @@ import ( "encoding/json" "math/rand/v2" "net/http" - "strom" - "strom/modules" "sync" "time" + "github.com/admin-else/strom" + "github.com/admin-else/strom/modules" + "github.com/admin-else/queser/generated/v1_21_8" ) type Client struct { *strom.Conn - Ticker *modules.Ticker + Ticker *modules.Timer Message string AltAccount strom.Account } @@ -62,7 +63,7 @@ func spawnSpammer(message, connectTo string, account strom.Account, wg *sync.Wai } defer conn.Close() c := &Client{Conn: conn, Message: message} - t := modules.Ticker{} + t := modules.Timer{} t.Interval = append(t.Interval, modules.IntervalTask{ F: c.Spam, Interval: time.Second, diff --git a/examples/proxy/main.go b/examples/proxy/main.go index 362eec7..d4ba285 100644 --- a/examples/proxy/main.go +++ b/examples/proxy/main.go @@ -1,10 +1,12 @@ package main import ( + "errors" "fmt" "log" "net" - "strom" + + "github.com/admin-else/strom" "github.com/admin-else/queser" "github.com/admin-else/queser/generated/v1_21_8" @@ -15,6 +17,10 @@ type ProxyClient struct { Proxy *Proxy } +func (p *ProxyClient) OnLoopCycle(event strom.OnLoopCycle) (err error) { + return +} + func (p *ProxyClient) Default(event any) (err error) { fmt.Printf("S2C %#v\n", event) err = p.Proxy.Send(event) @@ -43,8 +49,12 @@ type Proxy struct { ProxyClient *ProxyClient } +func (p *Proxy) OnLastTrigger(event strom.OnLoopCycle) (err error) { + return +} + func (p *Proxy) Default(event any) (err error) { - fmt.Printf("C2S LastTrigger%#v\n", event) + fmt.Printf("C2S %#v\n", event) err = p.ProxyClient.Send(event) return } @@ -54,6 +64,9 @@ func (p *Proxy) OnHandshake(packet v1_21_8.HandshakingToServerPacketSetProtocol) if err != nil { return } + if packet.NextState != queser.VarInt(queser.Status) && packet.NextState != queser.VarInt(queser.Login) { + err = errors.New("invalid next state") + } p.State = queser.State(packet.NextState) p.ProxyClient.State = queser.State(packet.NextState) return diff --git a/examples/secureexpreiment/main.go b/examples/secureexpreiment/main.go deleted file mode 100644 index f617024..0000000 --- a/examples/secureexpreiment/main.go +++ /dev/null @@ -1,201 +0,0 @@ -package main - -import ( - "bytes" - "crypto" - cryptorand "crypto/rand" - "crypto/rsa" - "crypto/sha256" - "crypto/x509" - "encoding/base64" - "encoding/binary" - "encoding/json" - "encoding/pem" - "fmt" - "math/rand/v2" - "net/http" - "strom" - "strom/modules" - "time" - - "github.com/admin-else/queser/generated/v1_21_8" - "github.com/google/uuid" -) - -type Client struct { - *strom.Conn - Ticker *modules.Ticker - Message string - AltAccount strom.Account - - SessionId uuid.UUID - PrivateKey *rsa.PrivateKey -} - -func (c *Client) Default(event any) (err error) { - return -} - -func (c *Client) MakeChatSession() (err error) { - c.SessionId, err = uuid.NewRandom() - if err != nil { - return - } - keys, err := c.AltAccount.FetchKeys() - if err != nil { - return - } - block, _ := pem.Decode([]byte(keys.KeyPair.PrivateKey)) - privateKey, err := x509.ParsePKCS8PrivateKey(block.Bytes) - if err != nil { - return - } - c.PrivateKey = privateKey.(*rsa.PrivateKey) - - x509encoded, _ := pem.Decode([]byte(keys.KeyPair.PublicKey)) - sigBytes, err := base64.StdEncoding.DecodeString(keys.PublicKeySignatureV2) - if err != nil { - return - } - - packet := v1_21_8.PlayToServerPacketChatSessionUpdate{ - SessionUUID: c.SessionId, - ExpireTime: keys.ExpiresAt.UnixMilli(), - PublicKey: v1_21_8.ByteArray{Val: x509encoded.Bytes}, - Signature: v1_21_8.ByteArray{Val: sigBytes}, - } - err = c.Send(packet) - return -} - -func (c *Client) MakeMessageSum(salt, timestamp int64, message string) (sum []byte, err error) { - h := sha256.New() - err = binary.Write(h, binary.BigEndian, int32(1)) - if err != nil { - return - } - _, err = h.Write(c.AltAccount.Uuid[:]) - if err != nil { - return - } - _, err = h.Write(c.SessionId[:]) - if err != nil { - return - } - err = binary.Write(h, binary.BigEndian, int32(0)) // message index unimplemented - if err != nil { - return - } - err = binary.Write(h, binary.BigEndian, salt) - if err != nil { - return - } - err = binary.Write(h, binary.BigEndian, timestamp) - if err != nil { - return - } - err = binary.Write(h, binary.BigEndian, int32(len(message))) - if err != nil { - return - } - _, err = h.Write([]byte(message)) - if err != nil { - return - } - err = binary.Write(h, binary.BigEndian, int32(0)) // number of last seen messages unimplemented - if err != nil { - return - } - sum = h.Sum(nil) - return -} - -func (c *Client) SendReportableChat(message string) (err error) { - salt := rand.Int64() - timestamp := time.Now().UnixMilli() - sum, err := c.MakeMessageSum(salt, timestamp, message) - if err != nil { - return - } - signature, err := rsa.SignPSS(cryptorand.Reader, c.PrivateKey, crypto.SHA256, sum, nil) - return c.Send(v1_21_8.PlayToServerPacketChatMessage{Message: message, Timestamp: timestamp, Salt: salt, Signature: (*[256]byte)(signature), Offset: 0, Acknowledged: [3]uint8{0x0, 0x0, 0x0}, Checksum: 0x1}) -} - -func (c *Client) OnStart(_ strom.OnStart) (err error) { - err = modules.Login(c.Conn, c.AltAccount) - if err != nil { - return - } - err = modules.IgnoreConfig(c.Conn) - if err != nil { - return - } - err = c.MakeChatSession() - if err != nil { - return - } - c.Ticker.Active = true - return -} - -func (c *Client) OnLoopCycle(strom.OnLoopCycle) (err error) { - err = c.Ticker.Tick() - return -} - -func (c *Client) KeepAlive(packet v1_21_8.PlayToClientPacketKeepAlive) (err error) { - return c.Send(v1_21_8.PlayToServerPacketKeepAlive(packet)) -} - -func (c *Client) Spam() (err error) { - err = c.SendReportableChat(c.Message) - return -} - -func DownloadAccounts(token string) (accounts []strom.Account, err error) { - r, err := http.NewRequest("GET", "https://griefing.homes/api/list/active", nil) - if err != nil { - return - } - r.Header.Set("Accept", "application/json") - r.Header.Set("Authorization", token) - resp, err := http.DefaultClient.Do(r) - if err != nil { - return - } - defer resp.Body.Close() - b := bytes.NewBuffer(nil) - _, err = b.ReadFrom(resp.Body) - if err != nil { - return - } - err = json.Unmarshal(b.Bytes(), &accounts) - return -} - -func main() { - conn, err := strom.Connect("127.0.0.1:25566") - if err != nil { - panic(err) - } - defer conn.Close() - c := &Client{Conn: conn, Message: "LOBA ONTOP XD"} - t := modules.Ticker{} - t.Interval = append(t.Interval, modules.IntervalTask{ - F: c.Spam, - Interval: time.Second, - }) - c.Ticker = &t - c.AltAccount = strom.Account{ - Name: "blossom_varJ5_11", - Uuid: uuid.MustParse("28ea954b7a9144d192081d686df32e56"), - Ygg: "eyJraWQiOiIwNDkxODEiLCJhbGciOiJSUzI1NiJ9.eyJ4dWlkIjoiMjUzNTQ2NjA5NDkzNTk1NyIsImFnZyI6IkFkdWx0Iiwic3ViIjoiODRmY2JhZTgtNmZlMS00ZDc5LWI4NTMtOGMzNGIwYzI5MGM2IiwiYXV0aCI6IlhCT1giLCJucyI6ImRlZmF1bHQiLCJyb2xlcyI6W10sImlzcyI6ImF1dGhlbnRpY2F0aW9uIiwiZmxhZ3MiOlsidHdvZmFjdG9yYXV0aCIsIm11bHRpcGxheWVyIiwib3JkZXJzXzIwMjIiLCJtc2FtaWdyYXRpb25fc3RhZ2U0Il0sInByb2ZpbGVzIjp7Im1jIjoiMjhlYTk1NGItN2E5MS00NGQxLTkyMDgtMWQ2ODZkZjMyZTU2In0sInBsYXRmb3JtIjoiUENfTEFVTkNIRVIiLCJwZmQiOlt7InR5cGUiOiJtYyIsImlkIjoiMjhlYTk1NGItN2E5MS00NGQxLTkyMDgtMWQ2ODZkZjMyZTU2IiwibmFtZSI6ImJsb3Nzb21fdmFySjVfMTEifV0sIm5iZiI6MTc2NDQ0ODE4NywiZXhwIjoxNzY0NTM0NTg3LCJpYXQiOjE3NjQ0NDgxODcsImFpZCI6IjAwMDAwMDAwLTAwMDAtMDAwMC0wMDAwLTAwMDA0YzEyYWU2ZiJ9.EC2LOt06Q4L9gyhufn97y2bqqzqJfv_kSQCdbRUNNyfhTTKonAlgi9LFv-OKN2sCcA96azTEQzpAiOTvL5jQ4H6nFT8sFz6kTMxD7vmii7ztCsCRrshJeZmW7mPCEn8WNpZukXbxVcaOhyjrNwA47RXEm-GazuPheDpWi_fvDSnY1vsLLk4ouIoW_r3kwA9bRakCJRF6r-p0feyi-bJamjLq2yDp7SEyZRVLeBhNA6pxVVU0WtyP6mgVO4cg0XeGwlMpktcs4IiYaD2C7AFjvedCdy7WJQOImLIcsc-gV4kFOn6oFROEf3EGN0RDcsrrlOJalAM01-rZTve6tUKGZQ", - } - - keys, err := c.AltAccount.FetchKeys() - fmt.Println(keys) - err = conn.Start(c) - if err != nil { - panic(err) - } -} diff --git a/go.mod b/go.mod index c0d3625..191c167 100644 --- a/go.mod +++ b/go.mod @@ -1,9 +1,9 @@ -module strom +module github.com/admin-else/strom replace github.com/admin-else/queser => ../queser go 1.24 -require github.com/admin-else/queser v0.0.0-00010101000000-000000000000 +require github.com/admin-else/queser v0.0.0-20251204142744-84a884c09415 -require github.com/google/uuid v1.6.0 // indirect +require github.com/google/uuid v1.6.0 diff --git a/modules/config_ignorer.go b/modules/config_ignorer.go index 32efd49..3747145 100644 --- a/modules/config_ignorer.go +++ b/modules/config_ignorer.go @@ -1,7 +1,10 @@ package modules import ( - "strom" + "errors" + "fmt" + + "github.com/admin-else/strom" "github.com/admin-else/queser" "github.com/admin-else/queser/generated/v1_21_8" @@ -12,6 +15,7 @@ type ConfigIgnorer struct { } func (c *ConfigIgnorer) Default(event any) (err error) { + fmt.Printf("%#v\n", event) return } @@ -29,6 +33,20 @@ func (c *ConfigIgnorer) OnFinish(packet v1_21_8.ConfigurationToClientPacketFinis return } +func (c *ConfigIgnorer) OnPing(packet v1_21_8.ConfigurationToClientPacketPing) (err error) { + err = c.Send(v1_21_8.ConfigurationToServerPacketPong(packet)) + return +} + +func (c *ConfigIgnorer) OnKeepAlive(packet v1_21_8.ConfigurationToClientPacketKeepAlive) (err error) { + err = c.Send(v1_21_8.ConfigurationToServerPacketKeepAlive(packet)) + return +} + func IgnoreConfig(c *strom.Conn) (err error) { - return c.Start(&ConfigIgnorer{c}) + err = c.Start(&ConfigIgnorer{c}) + if err != nil { + err = errors.Join(err, errors.New("failed to ignore config")) + } + return } diff --git a/modules/login.go b/modules/login.go index 9283f3d..2ab615a 100644 --- a/modules/login.go +++ b/modules/login.go @@ -8,10 +8,13 @@ import ( "crypto/sha1" "crypto/x509" "encoding/hex" + "errors" "fmt" + "net" "strconv" "strings" - "strom" + + "github.com/admin-else/strom" "github.com/admin-else/queser" "github.com/admin-else/queser/data" @@ -35,18 +38,21 @@ func (s *LoginClient) OnCycle(_ strom.OnLoopCycle) (err error) { } func (s *LoginClient) OnStart(_ strom.OnStart) (err error) { - parts := strings.Split(s.RemoteAddr().String(), ":") + host, portStr, err := net.SplitHostPort(s.RemoteAddr().String()) + if err != nil { + return + } versionData, err := data.LookUpProtocolVersionByName(s.Version) if err != nil { return } - port, err := strconv.Atoi(parts[1]) + port, err := strconv.Atoi(portStr) if err != nil { return } err = s.Send(v1_21_8.HandshakingToServerPacketSetProtocol{ ProtocolVersion: queser.VarInt(versionData.Version), - ServerHost: parts[0], + ServerHost: host, ServerPort: uint16(port), NextState: queser.VarInt(queser.Login), }) @@ -164,8 +170,12 @@ func (s *LoginClient) OnSuccess(success v1_21_8.LoginToClientPacketSuccess) (err } func Login(c *strom.Conn, account strom.Account) (err error) { - return c.Start(&LoginClient{ + err = c.Start(&LoginClient{ Conn: c, Account: account, }) + if err != nil { + err = errors.Join(err, errors.New("failed to login")) + } + return } diff --git a/modules/status.go b/modules/status.go index 258053e..7a7e8d6 100644 --- a/modules/status.go +++ b/modules/status.go @@ -4,7 +4,8 @@ import ( "fmt" "strconv" "strings" - "strom" + + "github.com/admin-else/strom" "github.com/admin-else/queser" "github.com/admin-else/queser/data" diff --git a/modules/ticker.go b/modules/ticker.go index 40ca813..6d16dbd 100644 --- a/modules/ticker.go +++ b/modules/ticker.go @@ -13,13 +13,13 @@ type OnceTask struct { Trigger time.Time } -type Ticker struct { +type Timer struct { Once []OnceTask Interval []IntervalTask Active bool } -func (t *Ticker) Tick() (err error) { +func (t *Timer) Tick() (err error) { if !t.Active { return } @@ -47,3 +47,17 @@ func (t *Ticker) Tick() (err error) { t.Once = triggerLater return } + +func (t *Timer) Every(interval time.Duration, f func() error) { + t.Interval = append(t.Interval, IntervalTask{ + F: f, + Interval: interval, + }) +} + +func (t *Timer) In(interval time.Duration, f func() error) { + t.Once = append(t.Once, OnceTask{ + F: f, + Trigger: time.Now().Add(interval), + }) +}