var nostalgiaVersion = []byte{0, 0, 2, 0x2c} // version ID used by the Nostalgia client
var frogblastVersion = []byte{0, 0, 0, 0xb9} // version ID used by the Frogblast 1.2.4 client
+var heildrun = []byte{0, 0x97}
+
+var obsessionVersion = []byte{0xbe, 0x00} // version ID used by the Obsession client
+
type Server struct {
Port int
Accounts map[string]*Account
s.mux.Lock()
client := s.Clients[uint16(clientID)]
+ s.mux.Unlock()
if client == nil {
return fmt.Errorf("invalid client id %v", *t.clientID)
}
- s.mux.Unlock()
-
b, err := t.MarshalBinary()
if err != nil {
return err
}
- if _, err := client.Connection.Write(b); err != nil {
+ _, err = client.Connection.Write(b)
+ if err != nil {
return err
}
scanner.Scan()
+ // Make a new []byte slice and copy the scanner bytes to it. This is critical to avoid a data race as the
+ // scanner re-uses the buffer for subsequent scans.
+ buf := make([]byte, len(scanner.Bytes()))
+ copy(buf, scanner.Bytes())
+
var clientLogin Transaction
- if _, err := clientLogin.Write(scanner.Bytes()); err != nil {
+ if _, err := clientLogin.Write(buf); err != nil {
return err
}
}
// Used simplified hotline v1.2.3 login flow for clients that do not send login info in tranAgreed
- if c.Version == nil || bytes.Equal(c.Version, nostalgiaVersion) || bytes.Equal(c.Version, frogblastVersion) {
+ // TODO: figure out a generalized solution that doesn't require playing whack-a-mole for specific client versions
+ if c.Version == nil || bytes.Equal(c.Version, nostalgiaVersion) || bytes.Equal(c.Version, frogblastVersion) || bytes.Equal(c.Version, obsessionVersion) || bytes.Equal(c.Version, heildrun) {
c.Agreed = true
c.logger = c.logger.With("name", string(c.UserName))
c.logger.Infow("Login successful", "clientVersion", fmt.Sprintf("%v", func() int { i, _ := byteToInt(c.Version); return i }()))