Keep the gateway connection alive and resume hosted queues after reconnecting
CI / build (push) Successful in 30s
CI / build (push) Successful in 30s
The client doesn't ping while it's sending, so when the proxy answers its frames itself (everything it sends in a hosted room), IMVU's gateway saw an idle connection and closed it after about a minute. A ping now goes to the gateway in place of each answered frame. And after a reconnect, hosted rooms' queues are taken out of C2gOpenFloodgates and answered here (the gateway never answered them, so the client gave up and closed the room). Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
c483099558
commit
08a2ed94a3
4 files changed
+94
-12
No files matched your search
@@ -4,15 +4,17 @@ import "errors"
|
||||
|
||||
// Message types the proxy reads or writes.
|
||||
const (
|
||||
C2gSendMessage = 1304
|
||||
C2gUnsubscribe = 1308
|
||||
C2gSubscribe = 1309
|
||||
G2cResult = 3102
|
||||
G2cSendMessage = 3104
|
||||
G2cStateChange = 3105
|
||||
G2cJoinedQueue = 3106
|
||||
G2cLeftQueue = 3107
|
||||
G2cCreateMount = 3108
|
||||
C2gPing = 1301
|
||||
C2gSendMessage = 1304
|
||||
C2gOpenFloodgates = 1306
|
||||
C2gUnsubscribe = 1308
|
||||
C2gSubscribe = 1309
|
||||
G2cResult = 3102
|
||||
G2cSendMessage = 3104
|
||||
G2cStateChange = 3105
|
||||
G2cJoinedQueue = 3106
|
||||
G2cLeftQueue = 3107
|
||||
G2cCreateMount = 3108
|
||||
)
|
||||
|
||||
// Mount types (G2cCreateMount).
|
||||
@@ -314,3 +316,42 @@ func StateChange(opID uint64, userID, queue, mount string, props []Property, seq
|
||||
b = appendBytesField(appendBytesField(appendBytesField(b, 2, []byte(userID)), 3, []byte(queue)), 4, []byte(mount))
|
||||
return appendVarintField(appendProperties(b, 5, props), 6, sequence)
|
||||
}
|
||||
|
||||
// ParseFloodgates reads a C2gOpenFloodgates's data (after reconnecting, the queues to resume): each queue's state
|
||||
// as a QueueOp (its op ID for a result), keeping the entry as sent.
|
||||
func ParseFloodgates(data []byte) ([]QueueOp, error) {
|
||||
fs, err := fields(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var out []QueueOp
|
||||
for _, f := range fs {
|
||||
if f.num != 1 || !f.isLen {
|
||||
return nil, errors.New("imq: unexpected field in C2gOpenFloodgates")
|
||||
}
|
||||
sub, err := fields(f.bytes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
q := QueueOp{raw: f.bytes}
|
||||
for _, sf := range sub {
|
||||
switch {
|
||||
case sf.num == 1 && sf.isLen:
|
||||
q.Queue = string(sf.bytes)
|
||||
case sf.num == 3 && !sf.isLen:
|
||||
q.OpID = sf.varint
|
||||
}
|
||||
}
|
||||
out = append(out, q)
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// MarshalFloodgates encodes a C2gOpenFloodgates's data from queue states read by ParseFloodgates.
|
||||
func MarshalFloodgates(states []QueueOp) []byte {
|
||||
var b []byte
|
||||
for _, q := range states {
|
||||
b = appendBytesField(b, 1, q.raw)
|
||||
}
|
||||
return b
|
||||
}
|
||||
Reference in new issue
Block a user