aboutsummaryrefslogtreecommitdiff
path: root/hotline
diff options
context:
space:
mode:
authorJeff Halter <868228+jhalter@users.noreply.github.com>2022-11-07 13:19:12 -0800
committerJeff Halter <868228+jhalter@users.noreply.github.com>2022-11-07 13:19:12 -0800
commit361928c9ad8945d525534e3d7178755f49ff6c1f (patch)
tree980d2fe55cf92ce8d16fc49bd6d10167d1d32930 /hotline
parent5a3f2adada6094ab99ca9a612c327730be2b0040 (diff)
Improve Frogblast client compatibility
Diffstat (limited to 'hotline')
-rw-r--r--hotline/server.go3
-rw-r--r--hotline/transaction_handlers.go5
-rw-r--r--hotline/transaction_handlers_test.go62
3 files changed, 67 insertions, 3 deletions
diff --git a/hotline/server.go b/hotline/server.go
index ec83522..8d6803b 100644
--- a/hotline/server.go
+++ b/hotline/server.go
@@ -34,6 +34,7 @@ type requestCtx struct {
}
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
type Server struct {
Port int
@@ -667,7 +668,7 @@ func (s *Server) handleNewConnection(ctx context.Context, rwc io.ReadWriteCloser
}
// 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) {
+ if c.Version == nil || bytes.Equal(c.Version, nostalgiaVersion) || bytes.Equal(c.Version, frogblastVersion) {
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 }()))
diff --git a/hotline/transaction_handlers.go b/hotline/transaction_handlers.go
index 5a9ea5e..6816456 100644
--- a/hotline/transaction_handlers.go
+++ b/hotline/transaction_handlers.go
@@ -253,9 +253,10 @@ func HandleChatSend(cc *ClientConn, t *Transaction) (res []Transaction, err erro
formattedMsg = fmt.Sprintf("\r*** %s %s", cc.UserName, t.GetField(fieldData).Data)
}
+ // The ChatID field is used to identify messages as belonging to a private chat.
+ // All clients *except* Frogblast omit this field for public chat, but Frogblast sends a value of 00 00 00 00.
chatID := t.GetField(fieldChatID).Data
- // a non-nil chatID indicates the message belongs to a private chat
- if chatID != nil {
+ if chatID != nil && !bytes.Equal([]byte{0, 0, 0, 0}, chatID) {
chatInt := binary.BigEndian.Uint32(chatID)
privChat := cc.Server.PrivateChats[chatInt]
diff --git a/hotline/transaction_handlers_test.go b/hotline/transaction_handlers_test.go
index bc40254..8898594 100644
--- a/hotline/transaction_handlers_test.go
+++ b/hotline/transaction_handlers_test.go
@@ -364,6 +364,68 @@ func TestHandleChatSend(t *testing.T) {
wantErr: false,
},
{
+ name: "treats Chat ID 00 00 00 00 as a public chat message",
+ args: args{
+ cc: &ClientConn{
+ Account: &Account{
+ Access: func() accessBitmap {
+ var bits accessBitmap
+ bits.Set(accessSendChat)
+ return bits
+ }(),
+ },
+ UserName: []byte{0x00, 0x01},
+ Server: &Server{
+ Clients: map[uint16]*ClientConn{
+ uint16(1): {
+ Account: &Account{
+ Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
+ },
+ ID: &[]byte{0, 1},
+ },
+ uint16(2): {
+ Account: &Account{
+ Access: accessBitmap{255, 255, 255, 255, 255, 255, 255, 255},
+ },
+ ID: &[]byte{0, 2},
+ },
+ },
+ },
+ },
+ t: &Transaction{
+ Fields: []Field{
+ NewField(fieldData, []byte("hai")),
+ NewField(fieldChatID, []byte{0, 0, 0, 0}),
+ },
+ },
+ },
+ want: []Transaction{
+ {
+ clientID: &[]byte{0, 1},
+ Flags: 0x00,
+ IsReply: 0x00,
+ Type: []byte{0, 0x6a},
+ ID: []byte{0x9a, 0xcb, 0x04, 0x42}, // Random ID from rand.Seed(1)
+ ErrorCode: []byte{0, 0, 0, 0},
+ Fields: []Field{
+ NewField(fieldData, []byte{0x0d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x01, 0x3a, 0x20, 0x20, 0x68, 0x61, 0x69}),
+ },
+ },
+ {
+ clientID: &[]byte{0, 2},
+ Flags: 0x00,
+ IsReply: 0x00,
+ Type: []byte{0, 0x6a},
+ ID: []byte{0xf0, 0xc5, 0x34, 0x1e}, // Random ID from rand.Seed(1)
+ ErrorCode: []byte{0, 0, 0, 0},
+ Fields: []Field{
+ NewField(fieldData, []byte{0x0d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x01, 0x3a, 0x20, 0x20, 0x68, 0x61, 0x69}),
+ },
+ },
+ },
+ wantErr: false,
+ },
+ {
name: "when user does not have required permission",
args: args{
cc: &ClientConn{