فهرست منبع

split SessionManager into MessageRelayer and ChatMessageRelayer

Mike 2 سال پیش
والد
کامیت
32f5827171

+ 5 - 2
.mockery.yaml

@@ -46,6 +46,9 @@ packages:
       SessionManager:
         config:
           filename: "session_manager_mock.go"
-      ChatSessionManager:
+      MessageRelayer:
         config:
-          filename: "chat_session_manager_mock.go"
+          filename: "session_message_relayer.go"
+      ChatMessageRelayer:
+        config:
+          filename: "session_chat_message_relayer.go"

+ 17 - 17
cmd/main.go

@@ -21,34 +21,34 @@ func main() {
 		os.Exit(1)
 	}
 
-	fm, err := state.NewSQLiteFeedbagStore(cfg.DBPath)
+	feedbagStore, err := state.NewSQLiteFeedbagStore(cfg.DBPath)
 	if err != nil {
 		_, _ = fmt.Fprintf(os.Stderr, "unable to create feedbag store: %s", err.Error())
 		os.Exit(1)
 	}
 
 	logger := server.NewLogger(cfg)
-	sm := state.NewSessionManager(logger)
-	cr := state.NewChatRegistry()
+	sessionManager := state.NewSessionManager(logger)
+	chatRegistry := state.NewChatRegistry()
 
 	wg := sync.WaitGroup{}
 	wg.Add(4)
 
 	go func() {
-		server.StartManagementAPI(fm, logger)
+		server.StartManagementAPI(feedbagStore, logger)
 		wg.Done()
 	}()
 	go func(logger *slog.Logger) {
 		logger = logger.With("svc", "BOS")
-		authHandler := handler.NewAuthService(cfg, sm, fm, fm, cr)
+		authHandler := handler.NewAuthService(cfg, sessionManager, feedbagStore, feedbagStore, chatRegistry)
 		buddyHandler := handler.NewBuddyService()
-		oserviceHandler := handler.NewOServiceService(cfg, sm, fm)
-		oserviceBOSHandler := handler.NewOServiceServiceForBOS(*oserviceHandler, cr)
-		locateHandler := handler.NewLocateService(sm, fm, fm)
-		newChatSessMgr := func() handler.ChatSessionManager { return state.NewSessionManager(logger) }
-		chatNavHandler := handler.NewChatNavService(logger, cr, handler.NewChatRoom, newChatSessMgr)
-		feedbagHandler := handler.NewFeedbagService(sm, fm)
-		icbmHandler := handler.NewICBMService(sm, fm)
+		oserviceHandler := handler.NewOServiceService(cfg, sessionManager, feedbagStore)
+		oserviceBOSHandler := handler.NewOServiceServiceForBOS(*oserviceHandler, chatRegistry)
+		locateHandler := handler.NewLocateService(sessionManager, feedbagStore, feedbagStore)
+		newChatSessMgr := func() handler.SessionManager { return state.NewSessionManager(logger) }
+		chatNavHandler := handler.NewChatNavService(logger, chatRegistry, newChatSessMgr)
+		feedbagHandler := handler.NewFeedbagService(sessionManager, feedbagStore)
+		icbmHandler := handler.NewICBMService(sessionManager, feedbagStore)
 
 		server.BOSService{
 			AlertRouter:       server.NewAlertRouter(logger),
@@ -68,10 +68,10 @@ func main() {
 	}(logger)
 	go func(logger *slog.Logger) {
 		logger = logger.With("svc", "CHAT")
-		authHandler := handler.NewAuthService(cfg, sm, fm, fm, cr)
-		oserviceHandler := handler.NewOServiceService(cfg, sm, fm)
-		chatHandler := handler.NewChatService(cr)
-		oserviceChatHandler := handler.NewOServiceServiceForChat(*oserviceHandler, cr)
+		authHandler := handler.NewAuthService(cfg, sessionManager, feedbagStore, feedbagStore, chatRegistry)
+		oserviceHandler := handler.NewOServiceService(cfg, sessionManager, feedbagStore)
+		chatHandler := handler.NewChatService(chatRegistry)
+		oserviceChatHandler := handler.NewOServiceServiceForChat(*oserviceHandler, chatRegistry)
 
 		server.ChatService{
 			AuthHandler:        authHandler,
@@ -86,7 +86,7 @@ func main() {
 	}(logger)
 	go func(logger *slog.Logger) {
 		logger = logger.With("svc", "AUTH")
-		authHandler := handler.NewAuthService(cfg, sm, fm, fm, cr)
+		authHandler := handler.NewAuthService(cfg, sessionManager, feedbagStore, feedbagStore, chatRegistry)
 
 		server.AuthService{
 			AuthHandler: authHandler,

+ 11 - 10
handler/auth.go

@@ -13,18 +13,19 @@ import (
 	"github.com/mkaminski/goaim/state"
 )
 
-func NewAuthService(cfg server.Config, sm SessionManager, fm FeedbagManager, um UserManager, cr *state.ChatRegistry) *AuthService {
+func NewAuthService(cfg server.Config, sessionManager SessionManager, feedbagManager FeedbagManager, userManager UserManager, cchatRegistry *state.ChatRegistry) *AuthService {
 	return &AuthService{
-		sessionManager: sm,
-		feedbagManager: fm,
+		sessionManager: sessionManager,
+		feedbagManager: feedbagManager,
 		config:         cfg,
-		userManager:    um,
-		chatRegistry:   cr,
+		userManager:    userManager,
+		chatRegistry:   cchatRegistry,
 	}
 }
 
 type AuthService struct {
 	sessionManager SessionManager
+	messageRelayer MessageRelayer
 	feedbagManager FeedbagManager
 	userManager    UserManager
 	config         server.Config
@@ -36,7 +37,7 @@ func (s AuthService) RetrieveChatSession(ctx context.Context, chatID string, ses
 	if err != nil {
 		return nil, err
 	}
-	chatSess, found := chatSessMgr.(ChatSessionManager).Retrieve(sessID)
+	chatSess, found := chatSessMgr.(SessionManager).Retrieve(sessID)
 	if !found {
 		return nil, fmt.Errorf("unable to find user for session. chat id: %s, sess id: %s", chatID, sessID)
 	}
@@ -44,7 +45,7 @@ func (s AuthService) RetrieveChatSession(ctx context.Context, chatID string, ses
 }
 
 func (s AuthService) Signout(ctx context.Context, sess *state.Session) error {
-	if err := broadcastDeparture(ctx, sess, s.sessionManager, s.feedbagManager); err != nil {
+	if err := broadcastDeparture(ctx, sess, s.messageRelayer, s.feedbagManager); err != nil {
 		return err
 	}
 	s.sessionManager.Remove(sess)
@@ -57,9 +58,9 @@ func (s AuthService) SignoutChat(ctx context.Context, sess *state.Session, chatI
 		fmt.Println("error getting chat room to remove")
 		return
 	}
-	alertUserLeft(ctx, sess, chatSessMgr.(ChatSessionManager))
-	chatSessMgr.(ChatSessionManager).Remove(sess)
-	if chatSessMgr.(ChatSessionManager).Empty() {
+	alertUserLeft(ctx, sess, chatSessMgr.(ChatMessageRelayer))
+	chatSessMgr.(SessionManager).Remove(sess)
+	if chatSessMgr.(SessionManager).Empty() {
 		s.chatRegistry.RemoveRoom(chatRoom.Cookie)
 	}
 }

+ 10 - 10
handler/auth_test.go

@@ -131,24 +131,24 @@ func TestReceiveAndSendBUCPLoginRequest(t *testing.T) {
 	for _, tc := range cases {
 		t.Run(tc.name, func(t *testing.T) {
 			sess := newTestSession(tc.userInDB.ScreenName, sessOptID(tc.sessionUUID.String()))
-			um := newMockUserManager(t)
-			um.EXPECT().
+			userManager := newMockUserManager(t)
+			userManager.EXPECT().
 				GetUser(tc.userInDB.ScreenName).
 				Return(&userGoodPwd, nil).
 				Maybe()
-			um.EXPECT().
+			userManager.EXPECT().
 				UpsertUser(mock.Anything).
 				Return(nil).
 				Maybe()
-			sm := newMockSessionManager(t)
-			sm.EXPECT().
+			sessionManager := newMockSessionManager(t)
+			sessionManager.EXPECT().
 				NewSessionWithSN(tc.sessionUUID.String(), tc.userInDB.ScreenName).
 				Return(sess).
 				Maybe()
 			svc := AuthService{
 				config:         tc.cfg,
-				sessionManager: sm,
-				userManager:    um,
+				sessionManager: sessionManager,
+				userManager:    userManager,
 			}
 			fnNewUUID := func() uuid.UUID {
 				return tc.sessionUUID
@@ -256,14 +256,14 @@ func TestReceiveAndSendAuthChallenge(t *testing.T) {
 
 	for _, tc := range cases {
 		t.Run(tc.name, func(t *testing.T) {
-			um := newMockUserManager(t)
-			um.EXPECT().
+			userManager := newMockUserManager(t)
+			userManager.EXPECT().
 				GetUser(string(tc.inputSNAC.TLVList[0].Val)).
 				Return(tc.userInDB, nil).
 				Maybe()
 			svc := AuthService{
 				config:      tc.cfg,
-				userManager: um,
+				userManager: userManager,
 			}
 			fnNewUUID := func() uuid.UUID {
 				return tc.fnNewUUID

+ 12 - 12
handler/buddy.go

@@ -34,13 +34,13 @@ func (s BuddyService) RightsQueryHandler(_ context.Context, frameIn oscar.SNACFr
 	}
 }
 
-func broadcastArrival(ctx context.Context, sess *state.Session, sm SessionManager, fm FeedbagManager) error {
-	screenNames, err := fm.InterestedUsers(sess.ScreenName())
+func broadcastArrival(ctx context.Context, sess *state.Session, messageRelayer MessageRelayer, feedbagManager FeedbagManager) error {
+	screenNames, err := feedbagManager.InterestedUsers(sess.ScreenName())
 	if err != nil {
 		return err
 	}
 
-	sm.BroadcastToScreenNames(ctx, screenNames, oscar.SNACMessage{
+	messageRelayer.BroadcastToScreenNames(ctx, screenNames, oscar.SNACMessage{
 		Frame: oscar.SNACFrame{
 			FoodGroup: oscar.Buddy,
 			SubGroup:  oscar.BuddyArrived,
@@ -59,13 +59,13 @@ func broadcastArrival(ctx context.Context, sess *state.Session, sm SessionManage
 	return nil
 }
 
-func broadcastDeparture(ctx context.Context, sess *state.Session, sm SessionManager, fm FeedbagManager) error {
-	screenNames, err := fm.InterestedUsers(sess.ScreenName())
+func broadcastDeparture(ctx context.Context, sess *state.Session, messageRelayer MessageRelayer, feedbagManager FeedbagManager) error {
+	screenNames, err := feedbagManager.InterestedUsers(sess.ScreenName())
 	if err != nil {
 		return err
 	}
 
-	sm.BroadcastToScreenNames(ctx, screenNames, oscar.SNACMessage{
+	messageRelayer.BroadcastToScreenNames(ctx, screenNames, oscar.SNACMessage{
 		Frame: oscar.SNACFrame{
 			FoodGroup: oscar.Buddy,
 			SubGroup:  oscar.BuddyDeparted,
@@ -83,15 +83,15 @@ func broadcastDeparture(ctx context.Context, sess *state.Session, sm SessionMana
 	return nil
 }
 
-func unicastArrival(ctx context.Context, srcScreenName, destScreenName string, sm SessionManager) {
-	sess := sm.RetrieveByScreenName(srcScreenName)
+func unicastArrival(ctx context.Context, srcScreenName, destScreenName string, messageRelayer MessageRelayer) {
+	sess := messageRelayer.RetrieveByScreenName(srcScreenName)
 	switch {
 	case sess == nil:
 		fallthrough
 	case sess.Invisible(): // don't tell user this buddy is online
 		return
 	}
-	sm.SendToScreenName(ctx, destScreenName, oscar.SNACMessage{
+	messageRelayer.SendToScreenName(ctx, destScreenName, oscar.SNACMessage{
 		Frame: oscar.SNACFrame{
 			FoodGroup: oscar.Buddy,
 			SubGroup:  oscar.BuddyArrived,
@@ -102,8 +102,8 @@ func unicastArrival(ctx context.Context, srcScreenName, destScreenName string, s
 	})
 }
 
-func unicastDeparture(ctx context.Context, srcScreenName, destScreenName string, sm SessionManager) {
-	sess := sm.RetrieveByScreenName(srcScreenName)
+func unicastDeparture(ctx context.Context, srcScreenName, destScreenName string, messageRelayer MessageRelayer) {
+	sess := messageRelayer.RetrieveByScreenName(srcScreenName)
 	switch {
 	case sess == nil:
 		fallthrough
@@ -111,7 +111,7 @@ func unicastDeparture(ctx context.Context, srcScreenName, destScreenName string,
 		return
 	}
 
-	sm.SendToScreenName(ctx, destScreenName, oscar.SNACMessage{
+	messageRelayer.SendToScreenName(ctx, destScreenName, oscar.SNACMessage{
 		Frame: oscar.SNACFrame{
 			FoodGroup: oscar.Buddy,
 			SubGroup:  oscar.BuddyDeparted,

+ 10 - 10
handler/chat.go

@@ -45,7 +45,7 @@ func (s ChatService) ChannelMsgToHostHandler(ctx context.Context, sess *state.Se
 	}
 
 	// send message to all the participants except sender
-	chatSessMgr.(ChatSessionManager).BroadcastExcept(ctx, sess, oscar.SNACMessage{
+	chatSessMgr.(ChatMessageRelayer).BroadcastExcept(ctx, sess, oscar.SNACMessage{
 		Frame: frameOut,
 		Body:  bodyOut,
 	})
@@ -63,9 +63,9 @@ func (s ChatService) ChannelMsgToHostHandler(ctx context.Context, sess *state.Se
 	return ret, nil
 }
 
-func setOnlineChatUsers(ctx context.Context, sess *state.Session, chatSessMgr ChatSessionManager) {
+func setOnlineChatUsers(ctx context.Context, sess *state.Session, chatMessageRelayer ChatMessageRelayer) {
 	snacPayloadOut := oscar.SNAC_0x0E_0x03_ChatUsersJoined{}
-	sessions := chatSessMgr.Participants()
+	sessions := chatMessageRelayer.Participants()
 
 	for _, uSess := range sessions {
 		snacPayloadOut.Users = append(snacPayloadOut.Users, oscar.TLVUserInfo{
@@ -77,7 +77,7 @@ func setOnlineChatUsers(ctx context.Context, sess *state.Session, chatSessMgr Ch
 		})
 	}
 
-	chatSessMgr.SendToScreenName(ctx, sess.ScreenName(), oscar.SNACMessage{
+	chatMessageRelayer.SendToScreenName(ctx, sess.ScreenName(), oscar.SNACMessage{
 		Frame: oscar.SNACFrame{
 			FoodGroup: oscar.Chat,
 			SubGroup:  oscar.ChatUsersJoined,
@@ -86,8 +86,8 @@ func setOnlineChatUsers(ctx context.Context, sess *state.Session, chatSessMgr Ch
 	})
 }
 
-func alertUserJoined(ctx context.Context, sess *state.Session, chatSessMgr ChatSessionManager) {
-	chatSessMgr.BroadcastExcept(ctx, sess, oscar.SNACMessage{
+func alertUserJoined(ctx context.Context, sess *state.Session, chatMessageRelayer ChatMessageRelayer) {
+	chatMessageRelayer.BroadcastExcept(ctx, sess, oscar.SNACMessage{
 		Frame: oscar.SNACFrame{
 			FoodGroup: oscar.Chat,
 			SubGroup:  oscar.ChatUsersJoined,
@@ -106,8 +106,8 @@ func alertUserJoined(ctx context.Context, sess *state.Session, chatSessMgr ChatS
 	})
 }
 
-func alertUserLeft(ctx context.Context, sess *state.Session, chatSessMgr ChatSessionManager) {
-	chatSessMgr.BroadcastExcept(ctx, sess, oscar.SNACMessage{
+func alertUserLeft(ctx context.Context, sess *state.Session, chatMessageRelayer ChatMessageRelayer) {
+	chatMessageRelayer.BroadcastExcept(ctx, sess, oscar.SNACMessage{
 		Frame: oscar.SNACFrame{
 			FoodGroup: oscar.Chat,
 			SubGroup:  oscar.ChatUsersLeft,
@@ -126,8 +126,8 @@ func alertUserLeft(ctx context.Context, sess *state.Session, chatSessMgr ChatSes
 	})
 }
 
-func sendChatRoomInfoUpdate(ctx context.Context, sess *state.Session, chatSessMgr ChatSessionManager, room state.ChatRoom) {
-	chatSessMgr.SendToScreenName(ctx, sess.ScreenName(), oscar.SNACMessage{
+func sendChatRoomInfoUpdate(ctx context.Context, sess *state.Session, chatMessageRelayer ChatMessageRelayer, room state.ChatRoom) {
+	chatMessageRelayer.SendToScreenName(ctx, sess.ScreenName(), oscar.SNACMessage{
 		Frame: oscar.SNACFrame{
 			FoodGroup: oscar.Chat,
 			SubGroup:  oscar.ChatRoomInfoUpdate,

+ 3 - 3
handler/chat_nav.go

@@ -18,10 +18,10 @@ func NewChatRoom() state.ChatRoom {
 	}
 }
 
-func NewChatNavService(logger *slog.Logger, cr *state.ChatRegistry, newChatRoom func() state.ChatRoom, newChatSessMgr func() ChatSessionManager) *ChatNavService {
+func NewChatNavService(logger *slog.Logger, chatRegistry *state.ChatRegistry, newChatSessMgr func() SessionManager) *ChatNavService {
 	return &ChatNavService{
 		logger:         logger,
-		chatRegistry:   cr,
+		chatRegistry:   chatRegistry,
 		newChatRoom:    NewChatRoom,
 		newChatSessMgr: newChatSessMgr,
 	}
@@ -31,7 +31,7 @@ type ChatNavService struct {
 	logger         *slog.Logger
 	chatRegistry   *state.ChatRegistry
 	newChatRoom    func() state.ChatRoom
-	newChatSessMgr func() ChatSessionManager
+	newChatSessMgr func() SessionManager
 }
 
 func (s ChatNavService) RequestChatRightsHandler(_ context.Context, inFrame oscar.SNACFrame) oscar.SNACMessage {

+ 7 - 7
handler/chat_nav_test.go

@@ -16,10 +16,10 @@ func TestSendAndReceiveCreateRoom(t *testing.T) {
 	//
 	userSess := newTestSession("user-screen-name", sessOptCannedID)
 
-	cr := state.NewChatRegistry()
+	chatRegistry := state.NewChatRegistry()
 
-	sm := newMockChatSessionManager(t)
-	sm.EXPECT().NewSessionWithSN(userSess.ID(), userSess.ScreenName()).
+	sessionManager := newMockSessionManager(t)
+	sessionManager.EXPECT().NewSessionWithSN(userSess.ID(), userSess.ScreenName()).
 		Return(&state.Session{})
 
 	//
@@ -40,15 +40,15 @@ func TestSendAndReceiveCreateRoom(t *testing.T) {
 		},
 	}
 	svc := ChatNavService{
-		chatRegistry: cr,
+		chatRegistry: chatRegistry,
 		newChatRoom: func() state.ChatRoom {
 			return state.ChatRoom{
 				Cookie:     "dummy-cookie",
 				CreateTime: time.UnixMilli(0),
 			}
 		},
-		newChatSessMgr: func() ChatSessionManager {
-			return sm
+		newChatSessMgr: func() SessionManager {
+			return sessionManager
 		},
 	}
 	outputSNAC, err := svc.CreateRoomHandler(context.Background(), userSess, inFrame, inBody)
@@ -65,7 +65,7 @@ func TestSendAndReceiveCreateRoom(t *testing.T) {
 		InstanceNumber: 2,
 		Name:           "the-chat-room-name",
 	}
-	chatRoom, _, err := cr.Retrieve("dummy-cookie")
+	chatRoom, _, err := chatRegistry.Retrieve("dummy-cookie")
 	assert.NoError(t, err)
 	assert.Equal(t, expectChatRoom, chatRoom)
 

+ 0 - 438
handler/chat_session_manager_mock.go

@@ -1,438 +0,0 @@
-// Code generated by mockery v2.35.2. DO NOT EDIT.
-
-package handler
-
-import (
-	context "context"
-
-	oscar "github.com/mkaminski/goaim/oscar"
-	mock "github.com/stretchr/testify/mock"
-
-	state "github.com/mkaminski/goaim/state"
-)
-
-// mockChatSessionManager is an autogenerated mock type for the ChatSessionManager type
-type mockChatSessionManager struct {
-	mock.Mock
-}
-
-type mockChatSessionManager_Expecter struct {
-	mock *mock.Mock
-}
-
-func (_m *mockChatSessionManager) EXPECT() *mockChatSessionManager_Expecter {
-	return &mockChatSessionManager_Expecter{mock: &_m.Mock}
-}
-
-// Broadcast provides a mock function with given fields: ctx, msg
-func (_m *mockChatSessionManager) Broadcast(ctx context.Context, msg oscar.SNACMessage) {
-	_m.Called(ctx, msg)
-}
-
-// mockChatSessionManager_Broadcast_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Broadcast'
-type mockChatSessionManager_Broadcast_Call struct {
-	*mock.Call
-}
-
-// Broadcast is a helper method to define mock.On call
-//   - ctx context.Context
-//   - msg oscar.SNACMessage
-func (_e *mockChatSessionManager_Expecter) Broadcast(ctx interface{}, msg interface{}) *mockChatSessionManager_Broadcast_Call {
-	return &mockChatSessionManager_Broadcast_Call{Call: _e.mock.On("Broadcast", ctx, msg)}
-}
-
-func (_c *mockChatSessionManager_Broadcast_Call) Run(run func(ctx context.Context, msg oscar.SNACMessage)) *mockChatSessionManager_Broadcast_Call {
-	_c.Call.Run(func(args mock.Arguments) {
-		run(args[0].(context.Context), args[1].(oscar.SNACMessage))
-	})
-	return _c
-}
-
-func (_c *mockChatSessionManager_Broadcast_Call) Return() *mockChatSessionManager_Broadcast_Call {
-	_c.Call.Return()
-	return _c
-}
-
-func (_c *mockChatSessionManager_Broadcast_Call) RunAndReturn(run func(context.Context, oscar.SNACMessage)) *mockChatSessionManager_Broadcast_Call {
-	_c.Call.Return(run)
-	return _c
-}
-
-// BroadcastExcept provides a mock function with given fields: ctx, except, msg
-func (_m *mockChatSessionManager) BroadcastExcept(ctx context.Context, except *state.Session, msg oscar.SNACMessage) {
-	_m.Called(ctx, except, msg)
-}
-
-// mockChatSessionManager_BroadcastExcept_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'BroadcastExcept'
-type mockChatSessionManager_BroadcastExcept_Call struct {
-	*mock.Call
-}
-
-// BroadcastExcept is a helper method to define mock.On call
-//   - ctx context.Context
-//   - except *state.Session
-//   - msg oscar.SNACMessage
-func (_e *mockChatSessionManager_Expecter) BroadcastExcept(ctx interface{}, except interface{}, msg interface{}) *mockChatSessionManager_BroadcastExcept_Call {
-	return &mockChatSessionManager_BroadcastExcept_Call{Call: _e.mock.On("BroadcastExcept", ctx, except, msg)}
-}
-
-func (_c *mockChatSessionManager_BroadcastExcept_Call) Run(run func(ctx context.Context, except *state.Session, msg oscar.SNACMessage)) *mockChatSessionManager_BroadcastExcept_Call {
-	_c.Call.Run(func(args mock.Arguments) {
-		run(args[0].(context.Context), args[1].(*state.Session), args[2].(oscar.SNACMessage))
-	})
-	return _c
-}
-
-func (_c *mockChatSessionManager_BroadcastExcept_Call) Return() *mockChatSessionManager_BroadcastExcept_Call {
-	_c.Call.Return()
-	return _c
-}
-
-func (_c *mockChatSessionManager_BroadcastExcept_Call) RunAndReturn(run func(context.Context, *state.Session, oscar.SNACMessage)) *mockChatSessionManager_BroadcastExcept_Call {
-	_c.Call.Return(run)
-	return _c
-}
-
-// BroadcastToScreenNames provides a mock function with given fields: ctx, screenNames, msg
-func (_m *mockChatSessionManager) BroadcastToScreenNames(ctx context.Context, screenNames []string, msg oscar.SNACMessage) {
-	_m.Called(ctx, screenNames, msg)
-}
-
-// mockChatSessionManager_BroadcastToScreenNames_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'BroadcastToScreenNames'
-type mockChatSessionManager_BroadcastToScreenNames_Call struct {
-	*mock.Call
-}
-
-// BroadcastToScreenNames is a helper method to define mock.On call
-//   - ctx context.Context
-//   - screenNames []string
-//   - msg oscar.SNACMessage
-func (_e *mockChatSessionManager_Expecter) BroadcastToScreenNames(ctx interface{}, screenNames interface{}, msg interface{}) *mockChatSessionManager_BroadcastToScreenNames_Call {
-	return &mockChatSessionManager_BroadcastToScreenNames_Call{Call: _e.mock.On("BroadcastToScreenNames", ctx, screenNames, msg)}
-}
-
-func (_c *mockChatSessionManager_BroadcastToScreenNames_Call) Run(run func(ctx context.Context, screenNames []string, msg oscar.SNACMessage)) *mockChatSessionManager_BroadcastToScreenNames_Call {
-	_c.Call.Run(func(args mock.Arguments) {
-		run(args[0].(context.Context), args[1].([]string), args[2].(oscar.SNACMessage))
-	})
-	return _c
-}
-
-func (_c *mockChatSessionManager_BroadcastToScreenNames_Call) Return() *mockChatSessionManager_BroadcastToScreenNames_Call {
-	_c.Call.Return()
-	return _c
-}
-
-func (_c *mockChatSessionManager_BroadcastToScreenNames_Call) RunAndReturn(run func(context.Context, []string, oscar.SNACMessage)) *mockChatSessionManager_BroadcastToScreenNames_Call {
-	_c.Call.Return(run)
-	return _c
-}
-
-// Empty provides a mock function with given fields:
-func (_m *mockChatSessionManager) Empty() bool {
-	ret := _m.Called()
-
-	var r0 bool
-	if rf, ok := ret.Get(0).(func() bool); ok {
-		r0 = rf()
-	} else {
-		r0 = ret.Get(0).(bool)
-	}
-
-	return r0
-}
-
-// mockChatSessionManager_Empty_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Empty'
-type mockChatSessionManager_Empty_Call struct {
-	*mock.Call
-}
-
-// Empty is a helper method to define mock.On call
-func (_e *mockChatSessionManager_Expecter) Empty() *mockChatSessionManager_Empty_Call {
-	return &mockChatSessionManager_Empty_Call{Call: _e.mock.On("Empty")}
-}
-
-func (_c *mockChatSessionManager_Empty_Call) Run(run func()) *mockChatSessionManager_Empty_Call {
-	_c.Call.Run(func(args mock.Arguments) {
-		run()
-	})
-	return _c
-}
-
-func (_c *mockChatSessionManager_Empty_Call) Return(_a0 bool) *mockChatSessionManager_Empty_Call {
-	_c.Call.Return(_a0)
-	return _c
-}
-
-func (_c *mockChatSessionManager_Empty_Call) RunAndReturn(run func() bool) *mockChatSessionManager_Empty_Call {
-	_c.Call.Return(run)
-	return _c
-}
-
-// NewSessionWithSN provides a mock function with given fields: sessID, screenName
-func (_m *mockChatSessionManager) NewSessionWithSN(sessID string, screenName string) *state.Session {
-	ret := _m.Called(sessID, screenName)
-
-	var r0 *state.Session
-	if rf, ok := ret.Get(0).(func(string, string) *state.Session); ok {
-		r0 = rf(sessID, screenName)
-	} else {
-		if ret.Get(0) != nil {
-			r0 = ret.Get(0).(*state.Session)
-		}
-	}
-
-	return r0
-}
-
-// mockChatSessionManager_NewSessionWithSN_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'NewSessionWithSN'
-type mockChatSessionManager_NewSessionWithSN_Call struct {
-	*mock.Call
-}
-
-// NewSessionWithSN is a helper method to define mock.On call
-//   - sessID string
-//   - screenName string
-func (_e *mockChatSessionManager_Expecter) NewSessionWithSN(sessID interface{}, screenName interface{}) *mockChatSessionManager_NewSessionWithSN_Call {
-	return &mockChatSessionManager_NewSessionWithSN_Call{Call: _e.mock.On("NewSessionWithSN", sessID, screenName)}
-}
-
-func (_c *mockChatSessionManager_NewSessionWithSN_Call) Run(run func(sessID string, screenName string)) *mockChatSessionManager_NewSessionWithSN_Call {
-	_c.Call.Run(func(args mock.Arguments) {
-		run(args[0].(string), args[1].(string))
-	})
-	return _c
-}
-
-func (_c *mockChatSessionManager_NewSessionWithSN_Call) Return(_a0 *state.Session) *mockChatSessionManager_NewSessionWithSN_Call {
-	_c.Call.Return(_a0)
-	return _c
-}
-
-func (_c *mockChatSessionManager_NewSessionWithSN_Call) RunAndReturn(run func(string, string) *state.Session) *mockChatSessionManager_NewSessionWithSN_Call {
-	_c.Call.Return(run)
-	return _c
-}
-
-// Participants provides a mock function with given fields:
-func (_m *mockChatSessionManager) Participants() []*state.Session {
-	ret := _m.Called()
-
-	var r0 []*state.Session
-	if rf, ok := ret.Get(0).(func() []*state.Session); ok {
-		r0 = rf()
-	} else {
-		if ret.Get(0) != nil {
-			r0 = ret.Get(0).([]*state.Session)
-		}
-	}
-
-	return r0
-}
-
-// mockChatSessionManager_Participants_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Participants'
-type mockChatSessionManager_Participants_Call struct {
-	*mock.Call
-}
-
-// Participants is a helper method to define mock.On call
-func (_e *mockChatSessionManager_Expecter) Participants() *mockChatSessionManager_Participants_Call {
-	return &mockChatSessionManager_Participants_Call{Call: _e.mock.On("Participants")}
-}
-
-func (_c *mockChatSessionManager_Participants_Call) Run(run func()) *mockChatSessionManager_Participants_Call {
-	_c.Call.Run(func(args mock.Arguments) {
-		run()
-	})
-	return _c
-}
-
-func (_c *mockChatSessionManager_Participants_Call) Return(_a0 []*state.Session) *mockChatSessionManager_Participants_Call {
-	_c.Call.Return(_a0)
-	return _c
-}
-
-func (_c *mockChatSessionManager_Participants_Call) RunAndReturn(run func() []*state.Session) *mockChatSessionManager_Participants_Call {
-	_c.Call.Return(run)
-	return _c
-}
-
-// Remove provides a mock function with given fields: sess
-func (_m *mockChatSessionManager) Remove(sess *state.Session) {
-	_m.Called(sess)
-}
-
-// mockChatSessionManager_Remove_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Remove'
-type mockChatSessionManager_Remove_Call struct {
-	*mock.Call
-}
-
-// Remove is a helper method to define mock.On call
-//   - sess *state.Session
-func (_e *mockChatSessionManager_Expecter) Remove(sess interface{}) *mockChatSessionManager_Remove_Call {
-	return &mockChatSessionManager_Remove_Call{Call: _e.mock.On("Remove", sess)}
-}
-
-func (_c *mockChatSessionManager_Remove_Call) Run(run func(sess *state.Session)) *mockChatSessionManager_Remove_Call {
-	_c.Call.Run(func(args mock.Arguments) {
-		run(args[0].(*state.Session))
-	})
-	return _c
-}
-
-func (_c *mockChatSessionManager_Remove_Call) Return() *mockChatSessionManager_Remove_Call {
-	_c.Call.Return()
-	return _c
-}
-
-func (_c *mockChatSessionManager_Remove_Call) RunAndReturn(run func(*state.Session)) *mockChatSessionManager_Remove_Call {
-	_c.Call.Return(run)
-	return _c
-}
-
-// Retrieve provides a mock function with given fields: ID
-func (_m *mockChatSessionManager) Retrieve(ID string) (*state.Session, bool) {
-	ret := _m.Called(ID)
-
-	var r0 *state.Session
-	var r1 bool
-	if rf, ok := ret.Get(0).(func(string) (*state.Session, bool)); ok {
-		return rf(ID)
-	}
-	if rf, ok := ret.Get(0).(func(string) *state.Session); ok {
-		r0 = rf(ID)
-	} else {
-		if ret.Get(0) != nil {
-			r0 = ret.Get(0).(*state.Session)
-		}
-	}
-
-	if rf, ok := ret.Get(1).(func(string) bool); ok {
-		r1 = rf(ID)
-	} else {
-		r1 = ret.Get(1).(bool)
-	}
-
-	return r0, r1
-}
-
-// mockChatSessionManager_Retrieve_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Retrieve'
-type mockChatSessionManager_Retrieve_Call struct {
-	*mock.Call
-}
-
-// Retrieve is a helper method to define mock.On call
-//   - ID string
-func (_e *mockChatSessionManager_Expecter) Retrieve(ID interface{}) *mockChatSessionManager_Retrieve_Call {
-	return &mockChatSessionManager_Retrieve_Call{Call: _e.mock.On("Retrieve", ID)}
-}
-
-func (_c *mockChatSessionManager_Retrieve_Call) Run(run func(ID string)) *mockChatSessionManager_Retrieve_Call {
-	_c.Call.Run(func(args mock.Arguments) {
-		run(args[0].(string))
-	})
-	return _c
-}
-
-func (_c *mockChatSessionManager_Retrieve_Call) Return(_a0 *state.Session, _a1 bool) *mockChatSessionManager_Retrieve_Call {
-	_c.Call.Return(_a0, _a1)
-	return _c
-}
-
-func (_c *mockChatSessionManager_Retrieve_Call) RunAndReturn(run func(string) (*state.Session, bool)) *mockChatSessionManager_Retrieve_Call {
-	_c.Call.Return(run)
-	return _c
-}
-
-// RetrieveByScreenName provides a mock function with given fields: screenName
-func (_m *mockChatSessionManager) RetrieveByScreenName(screenName string) *state.Session {
-	ret := _m.Called(screenName)
-
-	var r0 *state.Session
-	if rf, ok := ret.Get(0).(func(string) *state.Session); ok {
-		r0 = rf(screenName)
-	} else {
-		if ret.Get(0) != nil {
-			r0 = ret.Get(0).(*state.Session)
-		}
-	}
-
-	return r0
-}
-
-// mockChatSessionManager_RetrieveByScreenName_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'RetrieveByScreenName'
-type mockChatSessionManager_RetrieveByScreenName_Call struct {
-	*mock.Call
-}
-
-// RetrieveByScreenName is a helper method to define mock.On call
-//   - screenName string
-func (_e *mockChatSessionManager_Expecter) RetrieveByScreenName(screenName interface{}) *mockChatSessionManager_RetrieveByScreenName_Call {
-	return &mockChatSessionManager_RetrieveByScreenName_Call{Call: _e.mock.On("RetrieveByScreenName", screenName)}
-}
-
-func (_c *mockChatSessionManager_RetrieveByScreenName_Call) Run(run func(screenName string)) *mockChatSessionManager_RetrieveByScreenName_Call {
-	_c.Call.Run(func(args mock.Arguments) {
-		run(args[0].(string))
-	})
-	return _c
-}
-
-func (_c *mockChatSessionManager_RetrieveByScreenName_Call) Return(_a0 *state.Session) *mockChatSessionManager_RetrieveByScreenName_Call {
-	_c.Call.Return(_a0)
-	return _c
-}
-
-func (_c *mockChatSessionManager_RetrieveByScreenName_Call) RunAndReturn(run func(string) *state.Session) *mockChatSessionManager_RetrieveByScreenName_Call {
-	_c.Call.Return(run)
-	return _c
-}
-
-// SendToScreenName provides a mock function with given fields: ctx, screenName, msg
-func (_m *mockChatSessionManager) SendToScreenName(ctx context.Context, screenName string, msg oscar.SNACMessage) {
-	_m.Called(ctx, screenName, msg)
-}
-
-// mockChatSessionManager_SendToScreenName_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SendToScreenName'
-type mockChatSessionManager_SendToScreenName_Call struct {
-	*mock.Call
-}
-
-// SendToScreenName is a helper method to define mock.On call
-//   - ctx context.Context
-//   - screenName string
-//   - msg oscar.SNACMessage
-func (_e *mockChatSessionManager_Expecter) SendToScreenName(ctx interface{}, screenName interface{}, msg interface{}) *mockChatSessionManager_SendToScreenName_Call {
-	return &mockChatSessionManager_SendToScreenName_Call{Call: _e.mock.On("SendToScreenName", ctx, screenName, msg)}
-}
-
-func (_c *mockChatSessionManager_SendToScreenName_Call) Run(run func(ctx context.Context, screenName string, msg oscar.SNACMessage)) *mockChatSessionManager_SendToScreenName_Call {
-	_c.Call.Run(func(args mock.Arguments) {
-		run(args[0].(context.Context), args[1].(string), args[2].(oscar.SNACMessage))
-	})
-	return _c
-}
-
-func (_c *mockChatSessionManager_SendToScreenName_Call) Return() *mockChatSessionManager_SendToScreenName_Call {
-	_c.Call.Return()
-	return _c
-}
-
-func (_c *mockChatSessionManager_SendToScreenName_Call) RunAndReturn(run func(context.Context, string, oscar.SNACMessage)) *mockChatSessionManager_SendToScreenName_Call {
-	_c.Call.Return(run)
-	return _c
-}
-
-// newMockChatSessionManager creates a new instance of mockChatSessionManager. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
-// The first argument is typically a *testing.T value.
-func newMockChatSessionManager(t interface {
-	mock.TestingT
-	Cleanup(func())
-}) *mockChatSessionManager {
-	mock := &mockChatSessionManager{}
-	mock.Mock.Test(t)
-
-	t.Cleanup(func() { mock.AssertExpectations(t) })
-
-	return mock
-}

+ 1 - 1
handler/chat_test.go

@@ -129,7 +129,7 @@ func TestSendAndReceiveChatChannelMsgToHost(t *testing.T) {
 		t.Run(tc.name, func(t *testing.T) {
 			chatID := "the-chat-id"
 
-			chatSessMgr := newMockChatSessionManager(t)
+			chatSessMgr := newMockChatMessageRelayer(t)
 			chatSessMgr.EXPECT().
 				BroadcastExcept(mock.Anything, tc.userSession, tc.expectSNACToParticipants)
 

+ 9 - 9
handler/feedbag.go

@@ -8,12 +8,12 @@ import (
 	"github.com/mkaminski/goaim/state"
 )
 
-func NewFeedbagService(sm SessionManager, fm FeedbagManager) *FeedbagService {
-	return &FeedbagService{sessionManager: sm, feedbagManager: fm}
+func NewFeedbagService(messageRelayer MessageRelayer, feedbagManager FeedbagManager) *FeedbagService {
+	return &FeedbagService{messageRelayer: messageRelayer, feedbagManager: feedbagManager}
 }
 
 type FeedbagService struct {
-	sessionManager SessionManager
+	messageRelayer MessageRelayer
 	feedbagManager FeedbagManager
 }
 
@@ -162,12 +162,12 @@ func (s FeedbagService) InsertItemHandler(ctx context.Context, sess *state.Sessi
 	for _, item := range inBody.Items {
 		switch item.ClassID {
 		case oscar.FeedbagClassIdBuddy, oscar.FeedbagClassIDPermit: // add new buddy
-			unicastArrival(ctx, item.Name, sess.ScreenName(), s.sessionManager)
+			unicastArrival(ctx, item.Name, sess.ScreenName(), s.messageRelayer)
 		case oscar.FeedbagClassIDDeny: // block buddy
 			// notify this user that buddy is offline
-			unicastDeparture(ctx, item.Name, sess.ScreenName(), s.sessionManager)
+			unicastDeparture(ctx, item.Name, sess.ScreenName(), s.messageRelayer)
 			// notify former buddy that this user is offline
-			unicastDeparture(ctx, sess.ScreenName(), item.Name, s.sessionManager)
+			unicastDeparture(ctx, sess.ScreenName(), item.Name, s.messageRelayer)
 		}
 	}
 
@@ -194,7 +194,7 @@ func (s FeedbagService) UpdateItemHandler(ctx context.Context, sess *state.Sessi
 	for _, item := range inBody.Items {
 		switch item.ClassID {
 		case oscar.FeedbagClassIdBuddy, oscar.FeedbagClassIDPermit:
-			unicastArrival(ctx, item.Name, sess.ScreenName(), s.sessionManager)
+			unicastArrival(ctx, item.Name, sess.ScreenName(), s.messageRelayer)
 		}
 	}
 
@@ -220,8 +220,8 @@ func (s FeedbagService) DeleteItemHandler(ctx context.Context, sess *state.Sessi
 
 	for _, item := range inBody.Items {
 		if item.ClassID == oscar.FeedbagClassIDDeny {
-			unicastArrival(ctx, item.Name, sess.ScreenName(), s.sessionManager)
-			unicastArrival(ctx, sess.ScreenName(), item.Name, s.sessionManager)
+			unicastArrival(ctx, item.Name, sess.ScreenName(), s.messageRelayer)
+			unicastArrival(ctx, sess.ScreenName(), item.Name, s.messageRelayer)
 		}
 	}
 

+ 16 - 16
handler/feedbag_test.go

@@ -91,12 +91,12 @@ func TestQueryHandler(t *testing.T) {
 			//
 			// initialize dependencies
 			//
-			fm := newMockFeedbagManager(t)
-			fm.EXPECT().
+			feedbagManager := newMockFeedbagManager(t)
+			feedbagManager.EXPECT().
 				Retrieve(tc.screenName).
 				Return(tc.feedbagItems, nil).
 				Maybe()
-			fm.EXPECT().
+			feedbagManager.EXPECT().
 				LastModified(tc.screenName).
 				Return(tc.lastModified, nil).
 				Maybe()
@@ -105,7 +105,7 @@ func TestQueryHandler(t *testing.T) {
 			//
 			senderSession := newTestSession(tc.screenName)
 			svc := FeedbagService{
-				feedbagManager: fm,
+				feedbagManager: feedbagManager,
 			}
 			outputSNAC, err := svc.QueryHandler(nil, senderSession, tc.inputSNAC.Frame)
 			assert.NoError(t, err)
@@ -233,12 +233,12 @@ func TestQueryIfModifiedHandler(t *testing.T) {
 			//
 			// initialize dependencies
 			//
-			fm := newMockFeedbagManager(t)
-			fm.EXPECT().
+			feedbagManager := newMockFeedbagManager(t)
+			feedbagManager.EXPECT().
 				Retrieve(tc.screenName).
 				Return(tc.feedbagItems, nil).
 				Maybe()
-			fm.EXPECT().
+			feedbagManager.EXPECT().
 				LastModified(tc.screenName).
 				Return(tc.lastModified, nil).
 				Maybe()
@@ -247,7 +247,7 @@ func TestQueryIfModifiedHandler(t *testing.T) {
 			//
 			senderSession := newTestSession(tc.screenName)
 			svc := FeedbagService{
-				feedbagManager: fm,
+				feedbagManager: feedbagManager,
 			}
 			outputSNAC, err := svc.QueryIfModifiedHandler(nil, senderSession, tc.inputSNAC.Frame,
 				tc.inputSNAC.Body.(oscar.SNAC_0x13_0x05_FeedbagQueryIfModified))
@@ -603,24 +603,24 @@ func TestInsertItemHandler(t *testing.T) {
 			//
 			// initialize dependencies
 			//
-			fm := newMockFeedbagManager(t)
-			fm.EXPECT().
+			feedbagManager := newMockFeedbagManager(t)
+			feedbagManager.EXPECT().
 				Upsert(tc.userSession.ScreenName(), tc.inputSNAC.Body.(oscar.SNAC_0x13_0x08_FeedbagInsertItem).Items).
 				Return(nil).
 				Maybe()
-			fm.EXPECT().
+			feedbagManager.EXPECT().
 				Buddies(tc.userSession.ScreenName()).
 				Return([]string{}, nil).
 				Maybe()
-			sm := newMockSessionManager(t)
+			messageRelayer := newMockMessageRelayer(t)
 			for screenName, val := range tc.screenNameLookups {
-				sm.EXPECT().
+				messageRelayer.EXPECT().
 					RetrieveByScreenName(screenName).
 					Return(val.sess).
 					Maybe()
 			}
 			for _, n := range tc.buddyMessages {
-				sm.EXPECT().
+				messageRelayer.EXPECT().
 					SendToScreenName(mock.Anything, n.user, n.msg).
 					Maybe()
 			}
@@ -628,8 +628,8 @@ func TestInsertItemHandler(t *testing.T) {
 			// send input SNAC
 			//
 			svc := FeedbagService{
-				feedbagManager: fm,
-				sessionManager: sm,
+				feedbagManager: feedbagManager,
+				messageRelayer: messageRelayer,
 			}
 			output, err := svc.InsertItemHandler(nil, tc.userSession, tc.inputSNAC.Frame,
 				tc.inputSNAC.Body.(oscar.SNAC_0x13_0x08_FeedbagInsertItem))

+ 9 - 9
handler/icbm.go

@@ -12,12 +12,12 @@ const (
 	evilDeltaAnon = uint16(30)
 )
 
-func NewICBMService(sm SessionManager, fm FeedbagManager) *ICBMService {
-	return &ICBMService{sessionManager: sm, feedbagManager: fm}
+func NewICBMService(messageRelayer MessageRelayer, feedbagManager FeedbagManager) *ICBMService {
+	return &ICBMService{messageRelayer: messageRelayer, feedbagManager: feedbagManager}
 }
 
 type ICBMService struct {
-	sessionManager SessionManager
+	messageRelayer MessageRelayer
 	feedbagManager FeedbagManager
 }
 
@@ -62,7 +62,7 @@ func (s ICBMService) ChannelMsgToHostHandler(ctx context.Context, sess *state.Se
 		}, nil
 	}
 
-	recipSess := s.sessionManager.RetrieveByScreenName(inBody.ScreenName)
+	recipSess := s.messageRelayer.RetrieveByScreenName(inBody.ScreenName)
 	if recipSess == nil {
 		return &oscar.SNACMessage{
 			Frame: oscar.SNACFrame{
@@ -97,7 +97,7 @@ func (s ICBMService) ChannelMsgToHostHandler(ctx context.Context, sess *state.Se
 	// far as I can tell.
 	clientIM.AddTLVList(inBody.TLVRestBlock.TLVList)
 
-	s.sessionManager.SendToScreenName(ctx, recipSess.ScreenName(), oscar.SNACMessage{
+	s.messageRelayer.SendToScreenName(ctx, recipSess.ScreenName(), oscar.SNACMessage{
 		Frame: oscar.SNACFrame{
 			FoodGroup: oscar.ICBM,
 			SubGroup:  oscar.ICBMChannelMsgToClient,
@@ -134,7 +134,7 @@ func (s ICBMService) ClientEventHandler(ctx context.Context, sess *state.Session
 	case blocked != state.BlockedNo:
 		return nil
 	default:
-		s.sessionManager.SendToScreenName(ctx, inBody.ScreenName, oscar.SNACMessage{
+		s.messageRelayer.SendToScreenName(ctx, inBody.ScreenName, oscar.SNACMessage{
 			Frame: oscar.SNACFrame{
 				FoodGroup: oscar.ICBM,
 				SubGroup:  oscar.ICBMClientEvent,
@@ -184,7 +184,7 @@ func (s ICBMService) EvilRequestHandler(ctx context.Context, sess *state.Session
 		}, nil
 	}
 
-	recipSess := s.sessionManager.RetrieveByScreenName(inBody.ScreenName)
+	recipSess := s.messageRelayer.RetrieveByScreenName(inBody.ScreenName)
 	if recipSess == nil {
 		return oscar.SNACMessage{}, nil
 	}
@@ -210,7 +210,7 @@ func (s ICBMService) EvilRequestHandler(ctx context.Context, sess *state.Session
 		}
 	}
 
-	s.sessionManager.SendToScreenName(ctx, recipSess.ScreenName(), oscar.SNACMessage{
+	s.messageRelayer.SendToScreenName(ctx, recipSess.ScreenName(), oscar.SNACMessage{
 		Frame: oscar.SNACFrame{
 			FoodGroup: oscar.OService,
 			SubGroup:  oscar.OServiceEvilNotification,
@@ -218,7 +218,7 @@ func (s ICBMService) EvilRequestHandler(ctx context.Context, sess *state.Session
 		Body: notif,
 	})
 
-	if err := broadcastArrival(ctx, recipSess, s.sessionManager, s.feedbagManager); err != nil {
+	if err := broadcastArrival(ctx, recipSess, s.messageRelayer, s.feedbagManager); err != nil {
 		return oscar.SNACMessage{}, nil
 	}
 

+ 22 - 22
handler/icbm_test.go

@@ -226,19 +226,19 @@ func TestSendAndReceiveChannelMsgToHost(t *testing.T) {
 			//
 			// initialize dependencies
 			//
-			fm := newMockFeedbagManager(t)
-			fm.EXPECT().
+			feedbagManager := newMockFeedbagManager(t)
+			feedbagManager.EXPECT().
 				Blocked(tc.senderSession.ScreenName(),
 					tc.inputSNAC.Body.(oscar.SNAC_0x04_0x06_ICBMChannelMsgToHost).ScreenName).
 				Return(tc.blockedState, nil).
 				Maybe()
-			sm := newMockSessionManager(t)
-			sm.EXPECT().
+			messageRelayer := newMockMessageRelayer(t)
+			messageRelayer.EXPECT().
 				RetrieveByScreenName(tc.inputSNAC.Body.(oscar.SNAC_0x04_0x06_ICBMChannelMsgToHost).ScreenName).
 				Return(tc.recipientSession).
 				Maybe()
 			if tc.recipientSession != nil {
-				sm.EXPECT().
+				messageRelayer.EXPECT().
 					SendToScreenName(mock.Anything, tc.recipientSession.ScreenName(), tc.expectSNACToClient).
 					Maybe()
 			}
@@ -246,8 +246,8 @@ func TestSendAndReceiveChannelMsgToHost(t *testing.T) {
 			// send input SNAC
 			//
 			svc := ICBMService{
-				sessionManager: sm,
-				feedbagManager: fm,
+				messageRelayer: messageRelayer,
+				feedbagManager: feedbagManager,
 			}
 			outputSNAC, err := svc.ChannelMsgToHostHandler(nil, tc.senderSession, tc.inputSNAC.Frame,
 				tc.inputSNAC.Body.(oscar.SNAC_0x04_0x06_ICBMChannelMsgToHost))
@@ -323,14 +323,14 @@ func TestSendAndReceiveClientEvent(t *testing.T) {
 			//
 			// initialize dependencies
 			//
-			fm := newMockFeedbagManager(t)
-			fm.EXPECT().
+			feedbagManager := newMockFeedbagManager(t)
+			feedbagManager.EXPECT().
 				Blocked(tc.senderScreenName, tc.inputSNAC.Body.(oscar.SNAC_0x04_0x14_ICBMClientEvent).ScreenName).
 				Return(tc.blockedState, nil).
 				Maybe()
-			sm := newMockSessionManager(t)
+			messageRelayer := newMockMessageRelayer(t)
 			if tc.blockedState == state.BlockedNo {
-				sm.EXPECT().
+				messageRelayer.EXPECT().
 					SendToScreenName(mock.Anything, tc.inputSNAC.Body.(oscar.SNAC_0x04_0x14_ICBMClientEvent).ScreenName,
 						tc.expectSNACToClient)
 			}
@@ -339,8 +339,8 @@ func TestSendAndReceiveClientEvent(t *testing.T) {
 			//
 			senderSession := newTestSession(tc.senderScreenName)
 			svc := ICBMService{
-				sessionManager: sm,
-				feedbagManager: fm,
+				messageRelayer: messageRelayer,
+				feedbagManager: feedbagManager,
 			}
 			assert.NoError(t, svc.ClientEventHandler(nil, senderSession, tc.inputSNAC.Frame,
 				tc.inputSNAC.Body.(oscar.SNAC_0x04_0x14_ICBMClientEvent)))
@@ -562,25 +562,25 @@ func TestSendAndReceiveEvilRequest(t *testing.T) {
 			//
 			// initialize dependencies
 			//
-			fm := newMockFeedbagManager(t)
-			fm.EXPECT().
+			feedbagManager := newMockFeedbagManager(t)
+			feedbagManager.EXPECT().
 				Blocked(tc.senderSession.ScreenName(), tc.recipientScreenName).
 				Return(tc.blockedState, nil).
 				Maybe()
-			fm.EXPECT().
+			feedbagManager.EXPECT().
 				InterestedUsers(tc.recipientScreenName).
 				Return(tc.recipientBuddies, nil).
 				Maybe()
 			recipSess := newTestSession(tc.recipientScreenName, sessOptCannedSignonTime)
-			sm := newMockSessionManager(t)
-			sm.EXPECT().
+			messageRelayer := newMockMessageRelayer(t)
+			messageRelayer.EXPECT().
 				RetrieveByScreenName(tc.recipientScreenName).
 				Return(recipSess).
 				Maybe()
-			sm.EXPECT().
+			messageRelayer.EXPECT().
 				SendToScreenName(mock.Anything, tc.recipientScreenName, tc.expectSNACToClient).
 				Maybe()
-			sm.EXPECT().
+			messageRelayer.EXPECT().
 				BroadcastToScreenNames(mock.Anything, tc.recipientBuddies, tc.broadcastMessage).
 				Maybe()
 			//
@@ -588,8 +588,8 @@ func TestSendAndReceiveEvilRequest(t *testing.T) {
 			//
 			senderSession := newTestSession(tc.senderSession.ScreenName())
 			svc := ICBMService{
-				sessionManager: sm,
-				feedbagManager: fm,
+				messageRelayer: messageRelayer,
+				feedbagManager: feedbagManager,
 			}
 			outputSNAC, err := svc.EvilRequestHandler(nil, senderSession, tc.inputSNAC.Frame,
 				tc.inputSNAC.Body.(oscar.SNAC_0x04_0x08_ICBMEvilRequest))

+ 5 - 5
handler/locate.go

@@ -7,16 +7,16 @@ import (
 	"github.com/mkaminski/goaim/state"
 )
 
-func NewLocateService(sm SessionManager, fm FeedbagManager, pm ProfileManager) LocateService {
+func NewLocateService(messageRelayer MessageRelayer, feedbagManager FeedbagManager, profileManager ProfileManager) LocateService {
 	return LocateService{
-		sessionManager: sm,
-		feedbagManager: fm,
-		profileManager: pm,
+		sessionManager: messageRelayer,
+		feedbagManager: feedbagManager,
+		profileManager: profileManager,
 	}
 }
 
 type LocateService struct {
-	sessionManager SessionManager
+	sessionManager MessageRelayer
 	feedbagManager FeedbagManager
 	profileManager ProfileManager
 }

+ 9 - 9
handler/locate_test.go

@@ -277,30 +277,30 @@ func TestSendAndReceiveUserInfoQuery2(t *testing.T) {
 
 	for _, tc := range cases {
 		t.Run(tc.name, func(t *testing.T) {
-			fm := newMockFeedbagManager(t)
-			fm.EXPECT().
+			feedbagManager := newMockFeedbagManager(t)
+			feedbagManager.EXPECT().
 				Blocked(tc.userSession.ScreenName(),
 					tc.inputSNAC.Body.(oscar.SNAC_0x02_0x15_LocateUserInfoQuery2).ScreenName).
 				Return(tc.blockedState, nil).
 				Maybe()
-			sm := newMockSessionManager(t)
+			messageRelayer := newMockMessageRelayer(t)
 			for screenName, val := range tc.screenNameLookups {
-				sm.EXPECT().
+				messageRelayer.EXPECT().
 					RetrieveByScreenName(screenName).
 					Return(val.sess).
 					Maybe()
 			}
-			pm := newMockProfileManager(t)
+			profileManager := newMockProfileManager(t)
 			for screenName, val := range tc.profileLookups {
-				pm.EXPECT().
+				profileManager.EXPECT().
 					RetrieveProfile(screenName).
 					Return(val.payload, val.err).
 					Maybe()
 			}
 			svc := LocateService{
-				sessionManager: sm,
-				feedbagManager: fm,
-				profileManager: pm,
+				sessionManager: messageRelayer,
+				feedbagManager: feedbagManager,
+				profileManager: profileManager,
 			}
 			outputSNAC, err := svc.UserInfoQuery2Handler(context.Background(), tc.userSession, tc.inputSNAC.Frame,
 				tc.inputSNAC.Body.(oscar.SNAC_0x02_0x15_LocateUserInfoQuery2))

+ 15 - 15
handler/oservice.go

@@ -12,14 +12,14 @@ import (
 	"github.com/mkaminski/goaim/state"
 )
 
-func NewOServiceService(cfg server.Config, sm SessionManager, fm FeedbagManager) *OServiceService {
-	return &OServiceService{cfg: cfg, sessionManager: sm, feedbagManager: fm}
+func NewOServiceService(cfg server.Config, messageRelayer MessageRelayer, feedbagManager FeedbagManager) *OServiceService {
+	return &OServiceService{cfg: cfg, messageRelayer: messageRelayer, feedbagManager: feedbagManager}
 }
 
 type OServiceService struct {
 	cfg            server.Config
 	feedbagManager FeedbagManager
-	sessionManager SessionManager
+	messageRelayer MessageRelayer
 }
 
 func (s OServiceService) ClientVersionsHandler(_ context.Context, frame oscar.SNACFrame, inBody oscar.SNAC_0x01_0x17_OServiceClientVersions) oscar.SNACMessage {
@@ -134,12 +134,12 @@ func (s OServiceService) SetUserInfoFieldsHandler(ctx context.Context, sess *sta
 		switch status {
 		case 0x0000:
 			sess.SetInvisible(false)
-			if err := broadcastArrival(ctx, sess, s.sessionManager, s.feedbagManager); err != nil {
+			if err := broadcastArrival(ctx, sess, s.messageRelayer, s.feedbagManager); err != nil {
 				return oscar.SNACMessage{}, err
 			}
 		case 0x0100:
 			sess.SetInvisible(true)
-			if err := broadcastDeparture(ctx, sess, s.sessionManager, s.feedbagManager); err != nil {
+			if err := broadcastDeparture(ctx, sess, s.messageRelayer, s.feedbagManager); err != nil {
 				return oscar.SNACMessage{}, err
 			}
 		default:
@@ -164,7 +164,7 @@ func (s OServiceService) IdleNotificationHandler(ctx context.Context, sess *stat
 	} else {
 		sess.SetIdle(time.Duration(bodyIn.IdleTime) * time.Second)
 	}
-	return broadcastArrival(ctx, sess, s.sessionManager, s.feedbagManager)
+	return broadcastArrival(ctx, sess, s.messageRelayer, s.feedbagManager)
 }
 
 // RateParamsSubAddHandler exists to capture the SNAC input in unit tests to
@@ -175,13 +175,13 @@ func (s OServiceService) RateParamsSubAddHandler(context.Context, oscar.SNAC_0x0
 func NewOServiceServiceForBOS(oserviceService OServiceService, cr *state.ChatRegistry) *OServiceServiceForBOS {
 	return &OServiceServiceForBOS{
 		OServiceService: oserviceService,
-		cr:              cr,
+		chatRegistry:    cr,
 	}
 }
 
 type OServiceServiceForBOS struct {
 	OServiceService
-	cr *state.ChatRegistry
+	chatRegistry *state.ChatRegistry
 }
 
 func (s OServiceServiceForBOS) ServiceRequestHandler(_ context.Context, sess *state.Session, inFrame oscar.SNACFrame, inBody oscar.SNAC_0x01_0x04_OServiceServiceRequest) (oscar.SNACMessage, error) {
@@ -199,11 +199,11 @@ func (s OServiceServiceForBOS) ServiceRequestHandler(_ context.Context, sess *st
 		return oscar.SNACMessage{}, err
 	}
 
-	room, chatSessMgr, err := s.cr.Retrieve(string(roomSnac.Cookie))
+	room, chatSessMgr, err := s.chatRegistry.Retrieve(string(roomSnac.Cookie))
 	if err != nil {
 		return oscar.SNACMessage{}, server.ErrUnsupportedSubGroup
 	}
-	chatSessMgr.(ChatSessionManager).NewSessionWithSN(sess.ID(), sess.ScreenName())
+	chatSessMgr.(SessionManager).NewSessionWithSN(sess.ID(), sess.ScreenName())
 
 	return oscar.SNACMessage{
 		Frame: oscar.SNACFrame{
@@ -249,7 +249,7 @@ func (s OServiceServiceForBOS) WriteOServiceHostOnline() oscar.SNACMessage {
 }
 
 func (s OServiceServiceForBOS) ClientOnlineHandler(ctx context.Context, _ oscar.SNAC_0x01_0x02_OServiceClientOnline, sess *state.Session) error {
-	if err := broadcastArrival(ctx, sess, s.sessionManager, s.feedbagManager); err != nil {
+	if err := broadcastArrival(ctx, sess, s.messageRelayer, s.feedbagManager); err != nil {
 		return err
 	}
 	buddies, err := s.feedbagManager.Buddies(sess.ScreenName())
@@ -257,7 +257,7 @@ func (s OServiceServiceForBOS) ClientOnlineHandler(ctx context.Context, _ oscar.
 		return err
 	}
 	for _, buddy := range buddies {
-		unicastArrival(ctx, buddy, sess.ScreenName(), s.sessionManager)
+		unicastArrival(ctx, buddy, sess.ScreenName(), s.messageRelayer)
 	}
 	return nil
 }
@@ -291,8 +291,8 @@ func (s OServiceServiceForChat) ClientOnlineHandler(ctx context.Context, bodyIn
 	if err != nil {
 		return err
 	}
-	sendChatRoomInfoUpdate(ctx, sess, chatSessMgr.(ChatSessionManager), room)
-	alertUserJoined(ctx, sess, chatSessMgr.(ChatSessionManager))
-	setOnlineChatUsers(ctx, sess, chatSessMgr.(ChatSessionManager))
+	sendChatRoomInfoUpdate(ctx, sess, chatSessMgr.(ChatMessageRelayer), room)
+	alertUserJoined(ctx, sess, chatSessMgr.(ChatMessageRelayer))
+	setOnlineChatUsers(ctx, sess, chatSessMgr.(ChatMessageRelayer))
 	return nil
 }

+ 12 - 13
handler/oservice_test.go

@@ -131,24 +131,23 @@ func TestReceiveAndSendServiceRequest(t *testing.T) {
 			//
 			// initialize dependencies
 			//
-			sm := newMockChatSessionManager(t)
-			cr := state.NewChatRegistry()
+			sessionManager := newMockSessionManager(t)
+			chatRegistry := state.NewChatRegistry()
 			if tc.chatRoom != nil {
-				sm.EXPECT().
+				sessionManager.EXPECT().
 					NewSessionWithSN(tc.userSession.ID(), tc.userSession.ScreenName()).
 					Return(&state.Session{}).
 					Maybe()
-				cr.Register(*tc.chatRoom, sm)
+				chatRegistry.Register(*tc.chatRoom, sessionManager)
 			}
 			//
 			// send input SNAC
 			//
 			svc := OServiceServiceForBOS{
 				OServiceService: OServiceService{
-					cfg:            tc.cfg,
-					sessionManager: sm,
+					cfg: tc.cfg,
 				},
-				cr: cr,
+				chatRegistry: chatRegistry,
 			}
 
 			outputSNAC, err := svc.ServiceRequestHandler(nil, tc.userSession, tc.inputSNAC.Frame,
@@ -289,23 +288,23 @@ func TestSetUserInfoFieldsHandler(t *testing.T) {
 			//
 			// initialize dependencies
 			//
-			fm := newMockFeedbagManager(t)
+			feedbagManager := newMockFeedbagManager(t)
 			for user, friends := range tc.interestedUserLookups {
-				fm.EXPECT().
+				feedbagManager.EXPECT().
 					InterestedUsers(user).
 					Return(friends, nil).
 					Maybe()
 			}
-			sm := newMockSessionManager(t)
+			messageRelayer := newMockMessageRelayer(t)
 			for _, broadcastMsg := range tc.broadcastMessage {
-				sm.EXPECT().BroadcastToScreenNames(mock.Anything, broadcastMsg.recipients, broadcastMsg.msg)
+				messageRelayer.EXPECT().BroadcastToScreenNames(mock.Anything, broadcastMsg.recipients, broadcastMsg.msg)
 			}
 			//
 			// send input SNAC
 			//
 			svc := OServiceService{
-				feedbagManager: fm,
-				sessionManager: sm,
+				feedbagManager: feedbagManager,
+				messageRelayer: messageRelayer,
 			}
 			outputSNAC, err := svc.SetUserInfoFieldsHandler(nil, tc.userSession, tc.inputSNAC.Frame,
 				tc.inputSNAC.Body.(oscar.SNAC_0x01_0x1E_OServiceSetUserInfoFields))

+ 231 - 0
handler/session_chat_message_relayer.go

@@ -0,0 +1,231 @@
+// Code generated by mockery v2.35.2. DO NOT EDIT.
+
+package handler
+
+import (
+	context "context"
+
+	oscar "github.com/mkaminski/goaim/oscar"
+	mock "github.com/stretchr/testify/mock"
+
+	state "github.com/mkaminski/goaim/state"
+)
+
+// mockChatMessageRelayer is an autogenerated mock type for the ChatMessageRelayer type
+type mockChatMessageRelayer struct {
+	mock.Mock
+}
+
+type mockChatMessageRelayer_Expecter struct {
+	mock *mock.Mock
+}
+
+func (_m *mockChatMessageRelayer) EXPECT() *mockChatMessageRelayer_Expecter {
+	return &mockChatMessageRelayer_Expecter{mock: &_m.Mock}
+}
+
+// BroadcastExcept provides a mock function with given fields: ctx, except, msg
+func (_m *mockChatMessageRelayer) BroadcastExcept(ctx context.Context, except *state.Session, msg oscar.SNACMessage) {
+	_m.Called(ctx, except, msg)
+}
+
+// mockChatMessageRelayer_BroadcastExcept_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'BroadcastExcept'
+type mockChatMessageRelayer_BroadcastExcept_Call struct {
+	*mock.Call
+}
+
+// BroadcastExcept is a helper method to define mock.On call
+//   - ctx context.Context
+//   - except *state.Session
+//   - msg oscar.SNACMessage
+func (_e *mockChatMessageRelayer_Expecter) BroadcastExcept(ctx interface{}, except interface{}, msg interface{}) *mockChatMessageRelayer_BroadcastExcept_Call {
+	return &mockChatMessageRelayer_BroadcastExcept_Call{Call: _e.mock.On("BroadcastExcept", ctx, except, msg)}
+}
+
+func (_c *mockChatMessageRelayer_BroadcastExcept_Call) Run(run func(ctx context.Context, except *state.Session, msg oscar.SNACMessage)) *mockChatMessageRelayer_BroadcastExcept_Call {
+	_c.Call.Run(func(args mock.Arguments) {
+		run(args[0].(context.Context), args[1].(*state.Session), args[2].(oscar.SNACMessage))
+	})
+	return _c
+}
+
+func (_c *mockChatMessageRelayer_BroadcastExcept_Call) Return() *mockChatMessageRelayer_BroadcastExcept_Call {
+	_c.Call.Return()
+	return _c
+}
+
+func (_c *mockChatMessageRelayer_BroadcastExcept_Call) RunAndReturn(run func(context.Context, *state.Session, oscar.SNACMessage)) *mockChatMessageRelayer_BroadcastExcept_Call {
+	_c.Call.Return(run)
+	return _c
+}
+
+// BroadcastToScreenNames provides a mock function with given fields: ctx, screenNames, msg
+func (_m *mockChatMessageRelayer) BroadcastToScreenNames(ctx context.Context, screenNames []string, msg oscar.SNACMessage) {
+	_m.Called(ctx, screenNames, msg)
+}
+
+// mockChatMessageRelayer_BroadcastToScreenNames_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'BroadcastToScreenNames'
+type mockChatMessageRelayer_BroadcastToScreenNames_Call struct {
+	*mock.Call
+}
+
+// BroadcastToScreenNames is a helper method to define mock.On call
+//   - ctx context.Context
+//   - screenNames []string
+//   - msg oscar.SNACMessage
+func (_e *mockChatMessageRelayer_Expecter) BroadcastToScreenNames(ctx interface{}, screenNames interface{}, msg interface{}) *mockChatMessageRelayer_BroadcastToScreenNames_Call {
+	return &mockChatMessageRelayer_BroadcastToScreenNames_Call{Call: _e.mock.On("BroadcastToScreenNames", ctx, screenNames, msg)}
+}
+
+func (_c *mockChatMessageRelayer_BroadcastToScreenNames_Call) Run(run func(ctx context.Context, screenNames []string, msg oscar.SNACMessage)) *mockChatMessageRelayer_BroadcastToScreenNames_Call {
+	_c.Call.Run(func(args mock.Arguments) {
+		run(args[0].(context.Context), args[1].([]string), args[2].(oscar.SNACMessage))
+	})
+	return _c
+}
+
+func (_c *mockChatMessageRelayer_BroadcastToScreenNames_Call) Return() *mockChatMessageRelayer_BroadcastToScreenNames_Call {
+	_c.Call.Return()
+	return _c
+}
+
+func (_c *mockChatMessageRelayer_BroadcastToScreenNames_Call) RunAndReturn(run func(context.Context, []string, oscar.SNACMessage)) *mockChatMessageRelayer_BroadcastToScreenNames_Call {
+	_c.Call.Return(run)
+	return _c
+}
+
+// Participants provides a mock function with given fields:
+func (_m *mockChatMessageRelayer) Participants() []*state.Session {
+	ret := _m.Called()
+
+	var r0 []*state.Session
+	if rf, ok := ret.Get(0).(func() []*state.Session); ok {
+		r0 = rf()
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).([]*state.Session)
+		}
+	}
+
+	return r0
+}
+
+// mockChatMessageRelayer_Participants_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Participants'
+type mockChatMessageRelayer_Participants_Call struct {
+	*mock.Call
+}
+
+// Participants is a helper method to define mock.On call
+func (_e *mockChatMessageRelayer_Expecter) Participants() *mockChatMessageRelayer_Participants_Call {
+	return &mockChatMessageRelayer_Participants_Call{Call: _e.mock.On("Participants")}
+}
+
+func (_c *mockChatMessageRelayer_Participants_Call) Run(run func()) *mockChatMessageRelayer_Participants_Call {
+	_c.Call.Run(func(args mock.Arguments) {
+		run()
+	})
+	return _c
+}
+
+func (_c *mockChatMessageRelayer_Participants_Call) Return(_a0 []*state.Session) *mockChatMessageRelayer_Participants_Call {
+	_c.Call.Return(_a0)
+	return _c
+}
+
+func (_c *mockChatMessageRelayer_Participants_Call) RunAndReturn(run func() []*state.Session) *mockChatMessageRelayer_Participants_Call {
+	_c.Call.Return(run)
+	return _c
+}
+
+// RetrieveByScreenName provides a mock function with given fields: screenName
+func (_m *mockChatMessageRelayer) RetrieveByScreenName(screenName string) *state.Session {
+	ret := _m.Called(screenName)
+
+	var r0 *state.Session
+	if rf, ok := ret.Get(0).(func(string) *state.Session); ok {
+		r0 = rf(screenName)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*state.Session)
+		}
+	}
+
+	return r0
+}
+
+// mockChatMessageRelayer_RetrieveByScreenName_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'RetrieveByScreenName'
+type mockChatMessageRelayer_RetrieveByScreenName_Call struct {
+	*mock.Call
+}
+
+// RetrieveByScreenName is a helper method to define mock.On call
+//   - screenName string
+func (_e *mockChatMessageRelayer_Expecter) RetrieveByScreenName(screenName interface{}) *mockChatMessageRelayer_RetrieveByScreenName_Call {
+	return &mockChatMessageRelayer_RetrieveByScreenName_Call{Call: _e.mock.On("RetrieveByScreenName", screenName)}
+}
+
+func (_c *mockChatMessageRelayer_RetrieveByScreenName_Call) Run(run func(screenName string)) *mockChatMessageRelayer_RetrieveByScreenName_Call {
+	_c.Call.Run(func(args mock.Arguments) {
+		run(args[0].(string))
+	})
+	return _c
+}
+
+func (_c *mockChatMessageRelayer_RetrieveByScreenName_Call) Return(_a0 *state.Session) *mockChatMessageRelayer_RetrieveByScreenName_Call {
+	_c.Call.Return(_a0)
+	return _c
+}
+
+func (_c *mockChatMessageRelayer_RetrieveByScreenName_Call) RunAndReturn(run func(string) *state.Session) *mockChatMessageRelayer_RetrieveByScreenName_Call {
+	_c.Call.Return(run)
+	return _c
+}
+
+// SendToScreenName provides a mock function with given fields: ctx, screenName, msg
+func (_m *mockChatMessageRelayer) SendToScreenName(ctx context.Context, screenName string, msg oscar.SNACMessage) {
+	_m.Called(ctx, screenName, msg)
+}
+
+// mockChatMessageRelayer_SendToScreenName_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SendToScreenName'
+type mockChatMessageRelayer_SendToScreenName_Call struct {
+	*mock.Call
+}
+
+// SendToScreenName is a helper method to define mock.On call
+//   - ctx context.Context
+//   - screenName string
+//   - msg oscar.SNACMessage
+func (_e *mockChatMessageRelayer_Expecter) SendToScreenName(ctx interface{}, screenName interface{}, msg interface{}) *mockChatMessageRelayer_SendToScreenName_Call {
+	return &mockChatMessageRelayer_SendToScreenName_Call{Call: _e.mock.On("SendToScreenName", ctx, screenName, msg)}
+}
+
+func (_c *mockChatMessageRelayer_SendToScreenName_Call) Run(run func(ctx context.Context, screenName string, msg oscar.SNACMessage)) *mockChatMessageRelayer_SendToScreenName_Call {
+	_c.Call.Run(func(args mock.Arguments) {
+		run(args[0].(context.Context), args[1].(string), args[2].(oscar.SNACMessage))
+	})
+	return _c
+}
+
+func (_c *mockChatMessageRelayer_SendToScreenName_Call) Return() *mockChatMessageRelayer_SendToScreenName_Call {
+	_c.Call.Return()
+	return _c
+}
+
+func (_c *mockChatMessageRelayer_SendToScreenName_Call) RunAndReturn(run func(context.Context, string, oscar.SNACMessage)) *mockChatMessageRelayer_SendToScreenName_Call {
+	_c.Call.Return(run)
+	return _c
+}
+
+// newMockChatMessageRelayer creates a new instance of mockChatMessageRelayer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func newMockChatMessageRelayer(t interface {
+	mock.TestingT
+	Cleanup(func())
+}) *mockChatMessageRelayer {
+	mock := &mockChatMessageRelayer{}
+	mock.Mock.Test(t)
+
+	t.Cleanup(func() { mock.AssertExpectations(t) })
+
+	return mock
+}

+ 1 - 153
handler/session_manager_mock.go

@@ -3,12 +3,8 @@
 package handler
 
 import (
-	context "context"
-
-	oscar "github.com/mkaminski/goaim/oscar"
-	mock "github.com/stretchr/testify/mock"
-
 	state "github.com/mkaminski/goaim/state"
+	mock "github.com/stretchr/testify/mock"
 )
 
 // mockSessionManager is an autogenerated mock type for the SessionManager type
@@ -24,75 +20,6 @@ func (_m *mockSessionManager) EXPECT() *mockSessionManager_Expecter {
 	return &mockSessionManager_Expecter{mock: &_m.Mock}
 }
 
-// Broadcast provides a mock function with given fields: ctx, msg
-func (_m *mockSessionManager) Broadcast(ctx context.Context, msg oscar.SNACMessage) {
-	_m.Called(ctx, msg)
-}
-
-// mockSessionManager_Broadcast_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Broadcast'
-type mockSessionManager_Broadcast_Call struct {
-	*mock.Call
-}
-
-// Broadcast is a helper method to define mock.On call
-//   - ctx context.Context
-//   - msg oscar.SNACMessage
-func (_e *mockSessionManager_Expecter) Broadcast(ctx interface{}, msg interface{}) *mockSessionManager_Broadcast_Call {
-	return &mockSessionManager_Broadcast_Call{Call: _e.mock.On("Broadcast", ctx, msg)}
-}
-
-func (_c *mockSessionManager_Broadcast_Call) Run(run func(ctx context.Context, msg oscar.SNACMessage)) *mockSessionManager_Broadcast_Call {
-	_c.Call.Run(func(args mock.Arguments) {
-		run(args[0].(context.Context), args[1].(oscar.SNACMessage))
-	})
-	return _c
-}
-
-func (_c *mockSessionManager_Broadcast_Call) Return() *mockSessionManager_Broadcast_Call {
-	_c.Call.Return()
-	return _c
-}
-
-func (_c *mockSessionManager_Broadcast_Call) RunAndReturn(run func(context.Context, oscar.SNACMessage)) *mockSessionManager_Broadcast_Call {
-	_c.Call.Return(run)
-	return _c
-}
-
-// BroadcastToScreenNames provides a mock function with given fields: ctx, screenNames, msg
-func (_m *mockSessionManager) BroadcastToScreenNames(ctx context.Context, screenNames []string, msg oscar.SNACMessage) {
-	_m.Called(ctx, screenNames, msg)
-}
-
-// mockSessionManager_BroadcastToScreenNames_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'BroadcastToScreenNames'
-type mockSessionManager_BroadcastToScreenNames_Call struct {
-	*mock.Call
-}
-
-// BroadcastToScreenNames is a helper method to define mock.On call
-//   - ctx context.Context
-//   - screenNames []string
-//   - msg oscar.SNACMessage
-func (_e *mockSessionManager_Expecter) BroadcastToScreenNames(ctx interface{}, screenNames interface{}, msg interface{}) *mockSessionManager_BroadcastToScreenNames_Call {
-	return &mockSessionManager_BroadcastToScreenNames_Call{Call: _e.mock.On("BroadcastToScreenNames", ctx, screenNames, msg)}
-}
-
-func (_c *mockSessionManager_BroadcastToScreenNames_Call) Run(run func(ctx context.Context, screenNames []string, msg oscar.SNACMessage)) *mockSessionManager_BroadcastToScreenNames_Call {
-	_c.Call.Run(func(args mock.Arguments) {
-		run(args[0].(context.Context), args[1].([]string), args[2].(oscar.SNACMessage))
-	})
-	return _c
-}
-
-func (_c *mockSessionManager_BroadcastToScreenNames_Call) Return() *mockSessionManager_BroadcastToScreenNames_Call {
-	_c.Call.Return()
-	return _c
-}
-
-func (_c *mockSessionManager_BroadcastToScreenNames_Call) RunAndReturn(run func(context.Context, []string, oscar.SNACMessage)) *mockSessionManager_BroadcastToScreenNames_Call {
-	_c.Call.Return(run)
-	return _c
-}
-
 // Empty provides a mock function with given fields:
 func (_m *mockSessionManager) Empty() bool {
 	ret := _m.Called()
@@ -266,85 +193,6 @@ func (_c *mockSessionManager_Retrieve_Call) RunAndReturn(run func(string) (*stat
 	return _c
 }
 
-// RetrieveByScreenName provides a mock function with given fields: screenName
-func (_m *mockSessionManager) RetrieveByScreenName(screenName string) *state.Session {
-	ret := _m.Called(screenName)
-
-	var r0 *state.Session
-	if rf, ok := ret.Get(0).(func(string) *state.Session); ok {
-		r0 = rf(screenName)
-	} else {
-		if ret.Get(0) != nil {
-			r0 = ret.Get(0).(*state.Session)
-		}
-	}
-
-	return r0
-}
-
-// mockSessionManager_RetrieveByScreenName_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'RetrieveByScreenName'
-type mockSessionManager_RetrieveByScreenName_Call struct {
-	*mock.Call
-}
-
-// RetrieveByScreenName is a helper method to define mock.On call
-//   - screenName string
-func (_e *mockSessionManager_Expecter) RetrieveByScreenName(screenName interface{}) *mockSessionManager_RetrieveByScreenName_Call {
-	return &mockSessionManager_RetrieveByScreenName_Call{Call: _e.mock.On("RetrieveByScreenName", screenName)}
-}
-
-func (_c *mockSessionManager_RetrieveByScreenName_Call) Run(run func(screenName string)) *mockSessionManager_RetrieveByScreenName_Call {
-	_c.Call.Run(func(args mock.Arguments) {
-		run(args[0].(string))
-	})
-	return _c
-}
-
-func (_c *mockSessionManager_RetrieveByScreenName_Call) Return(_a0 *state.Session) *mockSessionManager_RetrieveByScreenName_Call {
-	_c.Call.Return(_a0)
-	return _c
-}
-
-func (_c *mockSessionManager_RetrieveByScreenName_Call) RunAndReturn(run func(string) *state.Session) *mockSessionManager_RetrieveByScreenName_Call {
-	_c.Call.Return(run)
-	return _c
-}
-
-// SendToScreenName provides a mock function with given fields: ctx, screenName, msg
-func (_m *mockSessionManager) SendToScreenName(ctx context.Context, screenName string, msg oscar.SNACMessage) {
-	_m.Called(ctx, screenName, msg)
-}
-
-// mockSessionManager_SendToScreenName_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SendToScreenName'
-type mockSessionManager_SendToScreenName_Call struct {
-	*mock.Call
-}
-
-// SendToScreenName is a helper method to define mock.On call
-//   - ctx context.Context
-//   - screenName string
-//   - msg oscar.SNACMessage
-func (_e *mockSessionManager_Expecter) SendToScreenName(ctx interface{}, screenName interface{}, msg interface{}) *mockSessionManager_SendToScreenName_Call {
-	return &mockSessionManager_SendToScreenName_Call{Call: _e.mock.On("SendToScreenName", ctx, screenName, msg)}
-}
-
-func (_c *mockSessionManager_SendToScreenName_Call) Run(run func(ctx context.Context, screenName string, msg oscar.SNACMessage)) *mockSessionManager_SendToScreenName_Call {
-	_c.Call.Run(func(args mock.Arguments) {
-		run(args[0].(context.Context), args[1].(string), args[2].(oscar.SNACMessage))
-	})
-	return _c
-}
-
-func (_c *mockSessionManager_SendToScreenName_Call) Return() *mockSessionManager_SendToScreenName_Call {
-	_c.Call.Return()
-	return _c
-}
-
-func (_c *mockSessionManager_SendToScreenName_Call) RunAndReturn(run func(context.Context, string, oscar.SNACMessage)) *mockSessionManager_SendToScreenName_Call {
-	_c.Call.Return(run)
-	return _c
-}
-
 // newMockSessionManager creates a new instance of mockSessionManager. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
 // The first argument is typically a *testing.T value.
 func newMockSessionManager(t interface {

+ 153 - 0
handler/session_message_relayer.go

@@ -0,0 +1,153 @@
+// Code generated by mockery v2.35.2. DO NOT EDIT.
+
+package handler
+
+import (
+	context "context"
+
+	oscar "github.com/mkaminski/goaim/oscar"
+	mock "github.com/stretchr/testify/mock"
+
+	state "github.com/mkaminski/goaim/state"
+)
+
+// mockMessageRelayer is an autogenerated mock type for the MessageRelayer type
+type mockMessageRelayer struct {
+	mock.Mock
+}
+
+type mockMessageRelayer_Expecter struct {
+	mock *mock.Mock
+}
+
+func (_m *mockMessageRelayer) EXPECT() *mockMessageRelayer_Expecter {
+	return &mockMessageRelayer_Expecter{mock: &_m.Mock}
+}
+
+// BroadcastToScreenNames provides a mock function with given fields: ctx, screenNames, msg
+func (_m *mockMessageRelayer) BroadcastToScreenNames(ctx context.Context, screenNames []string, msg oscar.SNACMessage) {
+	_m.Called(ctx, screenNames, msg)
+}
+
+// mockMessageRelayer_BroadcastToScreenNames_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'BroadcastToScreenNames'
+type mockMessageRelayer_BroadcastToScreenNames_Call struct {
+	*mock.Call
+}
+
+// BroadcastToScreenNames is a helper method to define mock.On call
+//   - ctx context.Context
+//   - screenNames []string
+//   - msg oscar.SNACMessage
+func (_e *mockMessageRelayer_Expecter) BroadcastToScreenNames(ctx interface{}, screenNames interface{}, msg interface{}) *mockMessageRelayer_BroadcastToScreenNames_Call {
+	return &mockMessageRelayer_BroadcastToScreenNames_Call{Call: _e.mock.On("BroadcastToScreenNames", ctx, screenNames, msg)}
+}
+
+func (_c *mockMessageRelayer_BroadcastToScreenNames_Call) Run(run func(ctx context.Context, screenNames []string, msg oscar.SNACMessage)) *mockMessageRelayer_BroadcastToScreenNames_Call {
+	_c.Call.Run(func(args mock.Arguments) {
+		run(args[0].(context.Context), args[1].([]string), args[2].(oscar.SNACMessage))
+	})
+	return _c
+}
+
+func (_c *mockMessageRelayer_BroadcastToScreenNames_Call) Return() *mockMessageRelayer_BroadcastToScreenNames_Call {
+	_c.Call.Return()
+	return _c
+}
+
+func (_c *mockMessageRelayer_BroadcastToScreenNames_Call) RunAndReturn(run func(context.Context, []string, oscar.SNACMessage)) *mockMessageRelayer_BroadcastToScreenNames_Call {
+	_c.Call.Return(run)
+	return _c
+}
+
+// RetrieveByScreenName provides a mock function with given fields: screenName
+func (_m *mockMessageRelayer) RetrieveByScreenName(screenName string) *state.Session {
+	ret := _m.Called(screenName)
+
+	var r0 *state.Session
+	if rf, ok := ret.Get(0).(func(string) *state.Session); ok {
+		r0 = rf(screenName)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*state.Session)
+		}
+	}
+
+	return r0
+}
+
+// mockMessageRelayer_RetrieveByScreenName_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'RetrieveByScreenName'
+type mockMessageRelayer_RetrieveByScreenName_Call struct {
+	*mock.Call
+}
+
+// RetrieveByScreenName is a helper method to define mock.On call
+//   - screenName string
+func (_e *mockMessageRelayer_Expecter) RetrieveByScreenName(screenName interface{}) *mockMessageRelayer_RetrieveByScreenName_Call {
+	return &mockMessageRelayer_RetrieveByScreenName_Call{Call: _e.mock.On("RetrieveByScreenName", screenName)}
+}
+
+func (_c *mockMessageRelayer_RetrieveByScreenName_Call) Run(run func(screenName string)) *mockMessageRelayer_RetrieveByScreenName_Call {
+	_c.Call.Run(func(args mock.Arguments) {
+		run(args[0].(string))
+	})
+	return _c
+}
+
+func (_c *mockMessageRelayer_RetrieveByScreenName_Call) Return(_a0 *state.Session) *mockMessageRelayer_RetrieveByScreenName_Call {
+	_c.Call.Return(_a0)
+	return _c
+}
+
+func (_c *mockMessageRelayer_RetrieveByScreenName_Call) RunAndReturn(run func(string) *state.Session) *mockMessageRelayer_RetrieveByScreenName_Call {
+	_c.Call.Return(run)
+	return _c
+}
+
+// SendToScreenName provides a mock function with given fields: ctx, screenName, msg
+func (_m *mockMessageRelayer) SendToScreenName(ctx context.Context, screenName string, msg oscar.SNACMessage) {
+	_m.Called(ctx, screenName, msg)
+}
+
+// mockMessageRelayer_SendToScreenName_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SendToScreenName'
+type mockMessageRelayer_SendToScreenName_Call struct {
+	*mock.Call
+}
+
+// SendToScreenName is a helper method to define mock.On call
+//   - ctx context.Context
+//   - screenName string
+//   - msg oscar.SNACMessage
+func (_e *mockMessageRelayer_Expecter) SendToScreenName(ctx interface{}, screenName interface{}, msg interface{}) *mockMessageRelayer_SendToScreenName_Call {
+	return &mockMessageRelayer_SendToScreenName_Call{Call: _e.mock.On("SendToScreenName", ctx, screenName, msg)}
+}
+
+func (_c *mockMessageRelayer_SendToScreenName_Call) Run(run func(ctx context.Context, screenName string, msg oscar.SNACMessage)) *mockMessageRelayer_SendToScreenName_Call {
+	_c.Call.Run(func(args mock.Arguments) {
+		run(args[0].(context.Context), args[1].(string), args[2].(oscar.SNACMessage))
+	})
+	return _c
+}
+
+func (_c *mockMessageRelayer_SendToScreenName_Call) Return() *mockMessageRelayer_SendToScreenName_Call {
+	_c.Call.Return()
+	return _c
+}
+
+func (_c *mockMessageRelayer_SendToScreenName_Call) RunAndReturn(run func(context.Context, string, oscar.SNACMessage)) *mockMessageRelayer_SendToScreenName_Call {
+	_c.Call.Return(run)
+	return _c
+}
+
+// newMockMessageRelayer creates a new instance of mockMessageRelayer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+// The first argument is typically a *testing.T value.
+func newMockMessageRelayer(t interface {
+	mock.TestingT
+	Cleanup(func())
+}) *mockMessageRelayer {
+	mock := &mockMessageRelayer{}
+	mock.Mock.Test(t)
+
+	t.Cleanup(func() { mock.AssertExpectations(t) })
+
+	return mock
+}

+ 11 - 9
handler/types.go

@@ -24,23 +24,25 @@ type UserManager interface {
 }
 
 type SessionManager interface {
-	Broadcast(ctx context.Context, msg oscar.SNACMessage)
-	BroadcastToScreenNames(ctx context.Context, screenNames []string, msg oscar.SNACMessage)
 	Empty() bool
 	NewSessionWithSN(sessID string, screenName string) *state.Session
 	Remove(sess *state.Session)
 	Retrieve(ID string) (*state.Session, bool)
+}
+
+type ProfileManager interface {
+	RetrieveProfile(screenName string) (string, error)
+	UpsertProfile(screenName string, body string) error
+}
+
+type MessageRelayer interface {
+	BroadcastToScreenNames(ctx context.Context, screenNames []string, msg oscar.SNACMessage)
 	RetrieveByScreenName(screenName string) *state.Session
 	SendToScreenName(ctx context.Context, screenName string, msg oscar.SNACMessage)
 }
 
-type ChatSessionManager interface {
-	SessionManager
+type ChatMessageRelayer interface {
+	MessageRelayer
 	BroadcastExcept(ctx context.Context, except *state.Session, msg oscar.SNACMessage)
 	Participants() []*state.Session
 }
-
-type ProfileManager interface {
-	RetrieveProfile(screenName string) (string, error)
-	UpsertProfile(screenName string, body string) error
-}

+ 7 - 7
server/connection_test.go

@@ -19,8 +19,8 @@ func TestHandleChatConnection_Notification(t *testing.T) {
 	cfg := Config{}
 	logger := NewLogger(cfg)
 
-	sm := state.NewSessionManager(logger)
-	sess := sm.NewSessionWithSN("bob-sess-id", "bob")
+	sessionManager := state.NewSessionManager(logger)
+	sess := sessionManager.NewSessionWithSN("bob-sess-id", "bob")
 
 	msgIn := []oscar.SNACMessage{
 		{
@@ -68,7 +68,7 @@ func TestHandleChatConnection_Notification(t *testing.T) {
 	rw := bufio.NewReadWriter(bufio.NewReader(pr), bufio.NewWriter(&bytes.Buffer{}))
 
 	for _, msg := range msgIn {
-		sm.SendToScreenName(ctx, "bob", msg)
+		sessionManager.SendToScreenName(ctx, "bob", msg)
 	}
 
 	dispatchIncomingMessages(ctx, sess, uint32(0), rw, logger, routeSig, alertHandler)
@@ -82,8 +82,8 @@ func TestHandleChatConnection_ClientRequestFLAP(t *testing.T) {
 	cfg := Config{}
 	logger := NewLogger(cfg)
 
-	sm := state.NewSessionManager(logger)
-	sess := sm.NewSessionWithSN("bob-sess-id", "bob")
+	sessionManager := state.NewSessionManager(logger)
+	sess := sessionManager.NewSessionWithSN("bob-sess-id", "bob")
 
 	payloads := [][]byte{
 		{'a', 'b', 'c', 'd'},
@@ -137,8 +137,8 @@ func TestHandleChatConnection_SessionClosed(t *testing.T) {
 	cfg := Config{}
 	logger := NewLogger(cfg)
 
-	sm := state.NewSessionManager(logger)
-	sess := sm.NewSessionWithSN("bob-sess-id", "bob")
+	sessionManager := state.NewSessionManager(logger)
+	sess := sessionManager.NewSessionWithSN("bob-sess-id", "bob")
 
 	routeSig := func(ctx context.Context, buf io.Reader, w io.Writer, u *uint32) error {
 		t.Fatal("not expecting any output")

+ 5 - 5
state/chat_registry.go

@@ -21,25 +21,25 @@ func NewChatRegistry() *ChatRegistry {
 	}
 }
 
-func (c *ChatRegistry) Register(room ChatRoom, sm any) {
+func (c *ChatRegistry) Register(room ChatRoom, sessionManager any) {
 	c.mapMutex.Lock()
 	defer c.mapMutex.Unlock()
 	c.chatRoomStore[room.Cookie] = room
-	c.smStore[room.Cookie] = sm
+	c.smStore[room.Cookie] = sessionManager
 }
 
 func (c *ChatRegistry) Retrieve(chatID string) (ChatRoom, any, error) {
 	c.mapMutex.RLock()
 	defer c.mapMutex.RUnlock()
-	cr, found := c.chatRoomStore[chatID]
+	chatRoom, found := c.chatRoomStore[chatID]
 	if !found {
 		return ChatRoom{}, nil, errors.New("unable to find chat room")
 	}
-	sm, found := c.smStore[chatID]
+	sessionManager, found := c.smStore[chatID]
 	if !found {
 		panic("unable to find session manager for chat")
 	}
-	return cr, sm, nil
+	return chatRoom, sessionManager, nil
 }
 
 func (c *ChatRegistry) RemoveRoom(chatID string) {