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
@@ -253,12 +253,33 @@ func (st *stream) filtered(f imq.Frame, frame []byte) []byte {
|
||||
}
|
||||
rest := router.Route(st.conn, f.Type == imq.C2gUnsubscribe, sub)
|
||||
if rest.Empty() {
|
||||
return nil
|
||||
return keepalive()
|
||||
}
|
||||
if len(rest.All()) == len(sub.All()) {
|
||||
return frame
|
||||
}
|
||||
return imq.EncodeFrame(f.Type, rest.Marshal())
|
||||
case imq.C2gOpenFloodgates:
|
||||
// Resuming queues after a reconnect: the router's are answered here, the rest go to the gateway.
|
||||
router, ok := st.watcher.(IMQRouter)
|
||||
if !ok {
|
||||
return frame
|
||||
}
|
||||
states, err := imq.ParseFloodgates(f.Data)
|
||||
if err != nil {
|
||||
return frame
|
||||
}
|
||||
var rest []imq.QueueOp
|
||||
for _, q := range states {
|
||||
if router.Route(st.conn, false, imq.Subscription{WithResults: []imq.QueueOp{q}}).Empty() {
|
||||
continue
|
||||
}
|
||||
rest = append(rest, q)
|
||||
}
|
||||
if len(rest) == len(states) {
|
||||
return frame
|
||||
}
|
||||
return imq.EncodeFrame(imq.C2gOpenFloodgates, imq.MarshalFloodgates(rest))
|
||||
case imq.G2cSendMessage:
|
||||
m, err := imq.ParseDelivered(f.Data)
|
||||
if err != nil {
|
||||
@@ -284,7 +305,7 @@ func (st *stream) filtered(f imq.Frame, frame []byte) []byte {
|
||||
if st.reply != nil {
|
||||
st.reply.Write(imq.EncodeFrame(imq.G2cResult, imq.Result(m.OpID, 0)))
|
||||
}
|
||||
return nil
|
||||
return keepalive()
|
||||
}
|
||||
if bytes.Equal(out, m.Message) {
|
||||
return frame
|
||||
@@ -293,6 +314,11 @@ func (st *stream) filtered(f imq.Frame, frame []byte) []byte {
|
||||
return imq.EncodeFrame(imq.C2gSendMessage, m.Marshal())
|
||||
}
|
||||
|
||||
// keepalive is what goes to the gateway in place of a frame the proxy answered itself: a ping. The client doesn't
|
||||
// ping while it's sending, so without it the gateway sees an idle connection and closes it (in a hosted room, where
|
||||
// everything the client sends is answered here).
|
||||
func keepalive() []byte { return imq.EncodeFrame(imq.C2gPing, nil) }
|
||||
|
||||
func (st *stream) summary() string {
|
||||
if st.other {
|
||||
return fmt.Sprintf("%s %dB", st.name, st.bytes)
|
||||
|
||||
Reference in new issue
Block a user