Hosted rooms (internal/hosted): room calls for them answered here, their IMQ queues served (a new proxy.IMQRouter hook takes them out of subscriptions to IMVU), chat relayed through the hub's WebSocket (hub.Client gains Send, OnRoom and OnConnect), the room list extended, room products checked against the real owner, and anything else naming a hosted room kept from IMVU. T5DE_INSTANCE gives a second client's proxy its own data folder and log. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
455dae1013
commit
d8332b21a8
12 files changed
+1492
-12
No files matched your search
@@ -123,6 +123,13 @@ type IMQWatcher interface {
|
||||
Closed(c *IMQConn)
|
||||
}
|
||||
|
||||
// IMQRouter is an IMQWatcher that serves some queues itself (T5DE-hosted rooms' queues): it takes them out of the
|
||||
// client's subscriptions before they go to the gateway, and answers the client for them.
|
||||
type IMQRouter interface {
|
||||
// Route returns the part of a subscription (or unsubscription) for the gateway.
|
||||
Route(c *IMQConn, unsubscribe bool, s imq.Subscription) imq.Subscription
|
||||
}
|
||||
|
||||
// IMQConn is one IMQ connection of the client's.
|
||||
type IMQConn struct {
|
||||
ID int64
|
||||
@@ -132,6 +139,12 @@ type IMQConn struct {
|
||||
// NewIMQConn is a connection writing frames to w (for tests of watchers).
|
||||
func NewIMQConn(id int64, w io.Writer) *IMQConn { return &IMQConn{ID: id, w: w} }
|
||||
|
||||
// Send gives the client a frame of the given type as if the gateway had sent it.
|
||||
func (c *IMQConn) Send(frameType uint64, data []byte) error {
|
||||
_, err := c.w.Write(imq.EncodeFrame(frameType, data))
|
||||
return err
|
||||
}
|
||||
|
||||
// Deliver gives the client a message as if the gateway had delivered it.
|
||||
func (c *IMQConn) Deliver(m imq.Delivered) error {
|
||||
_, err := c.w.Write(imq.EncodeFrame(imq.G2cSendMessage, m.Marshal()))
|
||||
@@ -225,14 +238,27 @@ func (st *stream) filtered(f imq.Frame, frame []byte) []byte {
|
||||
if st.watcher != nil {
|
||||
switch f.Type {
|
||||
case imq.C2gSubscribe, imq.C2gUnsubscribe:
|
||||
if queues, err := imq.ParseSubscription(f.Data); err == nil {
|
||||
if f.Type == imq.C2gSubscribe {
|
||||
st.watcher.Subscribed(st.conn, queues)
|
||||
} else {
|
||||
st.watcher.Unsubscribed(st.conn, queues)
|
||||
}
|
||||
sub, err := imq.ParseSubscriptionOps(f.Data)
|
||||
if err != nil {
|
||||
return frame
|
||||
}
|
||||
return frame
|
||||
if f.Type == imq.C2gSubscribe {
|
||||
st.watcher.Subscribed(st.conn, sub.All())
|
||||
} else {
|
||||
st.watcher.Unsubscribed(st.conn, sub.All())
|
||||
}
|
||||
router, ok := st.watcher.(IMQRouter)
|
||||
if !ok {
|
||||
return frame
|
||||
}
|
||||
rest := router.Route(st.conn, f.Type == imq.C2gUnsubscribe, sub)
|
||||
if rest.Empty() {
|
||||
return nil
|
||||
}
|
||||
if len(rest.All()) == len(sub.All()) {
|
||||
return frame
|
||||
}
|
||||
return imq.EncodeFrame(f.Type, rest.Marshal())
|
||||
case imq.G2cSendMessage:
|
||||
m, err := imq.ParseDelivered(f.Data)
|
||||
if err != nil {
|
||||
|
||||
Reference in new issue
Block a user