Переглянути джерело

toc: remove chat sessions on signoff

Mike 1 рік тому
батько
коміт
14b79f84aa
3 змінених файлів з 62 додано та 5 видалено
  1. 26 1
      server/toc/cmd_client.go
  2. 33 1
      server/toc/cmd_client_test.go
  3. 3 3
      server/toc/server.go

+ 26 - 1
server/toc/cmd_client.go

@@ -89,6 +89,24 @@ func (c *ChatRegistry) RetrieveSess(chatID int) *state.Session {
 	return c.sessions[chatID]
 }
 
+// RemoveSess removes a chat session.
+func (c *ChatRegistry) RemoveSess(chatID int) {
+	c.m.Lock()
+	defer c.m.Unlock()
+	delete(c.sessions, chatID)
+}
+
+// Sessions retrieves all the chat sessions.
+func (c *ChatRegistry) Sessions() []*state.Session {
+	c.m.RLock()
+	defer c.m.RUnlock()
+	sessions := make([]*state.Session, 0, len(c.sessions))
+	for _, s := range c.sessions {
+		sessions = append(sessions, s)
+	}
+	return sessions
+}
+
 // OSCARProxy acts as a bridge between TOC clients and the OSCAR server,
 // translating protocol messages between the two.
 //
@@ -638,6 +656,8 @@ func (s OSCARProxy) ChatLeave(ctx context.Context, chatRegistry *ChatRegistry, c
 
 	me.Close() // stop async server SNAC reply handler for this chat room
 
+	chatRegistry.RemoveSess(chatID)
+
 	return fmt.Sprintf("CHAT_LEFT:%d", chatID)
 }
 
@@ -1481,7 +1501,7 @@ func (s OSCARProxy) Signon(ctx context.Context, cmd []byte) (*state.Session, []s
 
 // Signout terminates a TOC session. It sends departure notifications to
 // buddies, de-registers buddy list and session.
-func (s OSCARProxy) Signout(ctx context.Context, me *state.Session) {
+func (s OSCARProxy) Signout(ctx context.Context, me *state.Session, chatRegistry *ChatRegistry) {
 	if err := s.BuddyService.BroadcastBuddyDeparted(ctx, me); err != nil {
 		s.Logger.ErrorContext(ctx, "error sending departure notifications", "err", err.Error())
 	}
@@ -1489,6 +1509,11 @@ func (s OSCARProxy) Signout(ctx context.Context, me *state.Session) {
 		s.Logger.ErrorContext(ctx, "error removing buddy list entry", "err", err.Error())
 	}
 	s.AuthService.Signout(ctx, me)
+
+	for _, sess := range chatRegistry.Sessions() {
+		s.AuthService.SignoutChat(ctx, sess)
+		sess.Close() // stop async server SNAC reply handler for this chat room
+	}
 }
 
 // newHTTPAuthToken creates a HMAC token for authenticating TOC HTTP requests

+ 33 - 1
server/toc/cmd_client_test.go

@@ -3898,6 +3898,8 @@ func TestOSCARProxy_Signout(t *testing.T) {
 		name string
 		// me is the TOC user session
 		me *state.Session
+		// givenChatRegistry is the chat registry passed to the function
+		chatRegistry *ChatRegistry
 		// mockParams is the list of params sent to mocks that satisfy this
 		// method's dependencies
 		mockParams mockParams
@@ -3905,6 +3907,19 @@ func TestOSCARProxy_Signout(t *testing.T) {
 		{
 			name: "successfully sign out",
 			me:   newTestSession("me"),
+			chatRegistry: func() *ChatRegistry {
+				cr := NewChatRegistry()
+
+				s1 := state.NewSession()
+				s1.SetIdentScreenName(state.NewIdentScreenName("me1"))
+				cr.RegisterSess(0, s1)
+
+				s2 := state.NewSession()
+				s2.SetIdentScreenName(state.NewIdentScreenName("me2"))
+				cr.RegisterSess(1, s2)
+
+				return cr
+			}(),
 			mockParams: mockParams{
 				buddyParams: buddyParams{
 					broadcastBuddyDepartedParams: broadcastBuddyDepartedParams{
@@ -3926,12 +3941,23 @@ func TestOSCARProxy_Signout(t *testing.T) {
 							me: state.NewIdentScreenName("me"),
 						},
 					},
+					signoutChatParams: signoutChatParams{
+						{
+							me: state.NewIdentScreenName("me1"),
+						},
+						{
+							me: state.NewIdentScreenName("me2"),
+						},
+					},
 				},
 			},
 		},
 		{
 			name: "sign out, receive error from buddy service",
 			me:   newTestSession("me"),
+			chatRegistry: func() *ChatRegistry {
+				return NewChatRegistry()
+			}(),
 			mockParams: mockParams{
 				buddyParams: buddyParams{
 					broadcastBuddyDepartedParams: broadcastBuddyDepartedParams{
@@ -3960,6 +3986,9 @@ func TestOSCARProxy_Signout(t *testing.T) {
 		{
 			name: "sign out, receive error from buddy list registry",
 			me:   newTestSession("me"),
+			chatRegistry: func() *ChatRegistry {
+				return NewChatRegistry()
+			}(),
 			mockParams: mockParams{
 				buddyParams: buddyParams{
 					broadcastBuddyDepartedParams: broadcastBuddyDepartedParams{
@@ -4009,6 +4038,9 @@ func TestOSCARProxy_Signout(t *testing.T) {
 			for _, params := range tc.mockParams.signoutParams {
 				authSvc.EXPECT().Signout(ctx, matchSession(params.me))
 			}
+			for _, params := range tc.mockParams.signoutChatParams {
+				authSvc.EXPECT().SignoutChat(ctx, matchSession(params.me))
+			}
 
 			svc := OSCARProxy{
 				AuthService:       authSvc,
@@ -4016,7 +4048,7 @@ func TestOSCARProxy_Signout(t *testing.T) {
 				BuddyService:      buddySvc,
 				Logger:            slog.Default(),
 			}
-			svc.Signout(ctx, tc.me)
+			svc.Signout(ctx, tc.me, tc.chatRegistry)
 		})
 	}
 }

+ 3 - 3
server/toc/server.go

@@ -196,7 +196,9 @@ func (rt Server) dispatchFLAP(ctx context.Context, conn net.Conn) error {
 		sessBOS.SetRemoteAddr(&ip)
 	}
 
-	defer rt.BOSProxy.Signout(ctx, sessBOS)
+	chatRegistry := NewChatRegistry()
+
+	defer rt.BOSProxy.Signout(ctx, sessBOS, chatRegistry)
 
 	// messages from TOC client
 	fromCh := make(chan wire.FLAPFrame, 1)
@@ -208,8 +210,6 @@ func (rt Server) dispatchFLAP(ctx context.Context, conn net.Conn) error {
 
 	g, gCtx := errgroup.WithContext(ctx)
 
-	chatRegistry := NewChatRegistry()
-
 	g.Go(func() error {
 		return rt.BOSProxy.RecvBOS(gCtx, sessBOS, chatRegistry, toCh)
 	})