connection_test.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. package server
  2. import (
  3. "bufio"
  4. "bytes"
  5. "context"
  6. "io"
  7. "sync"
  8. "testing"
  9. "github.com/mk6i/retro-aim-server/config"
  10. "github.com/mk6i/retro-aim-server/oscar"
  11. "github.com/mk6i/retro-aim-server/state"
  12. "github.com/stretchr/testify/assert"
  13. )
  14. func TestHandleChatConnection_Notification(t *testing.T) {
  15. ctx := context.Background()
  16. cfg := config.Config{}
  17. logger := NewLogger(cfg)
  18. sessionManager := state.NewInMemorySessionManager(logger)
  19. sess := sessionManager.AddSession("bob-sess-id", "bob")
  20. msgIn := []oscar.SNACMessage{
  21. {
  22. Frame: oscar.SNACFrame{
  23. FoodGroup: oscar.Chat,
  24. SubGroup: oscar.ChatUsersJoined,
  25. },
  26. Body: oscar.SNAC_0x0E_0x03_ChatUsersJoined{
  27. Users: []oscar.TLVUserInfo{
  28. sess.TLVUserInfo(),
  29. },
  30. },
  31. },
  32. {
  33. Frame: oscar.SNACFrame{
  34. FoodGroup: oscar.Chat,
  35. SubGroup: oscar.ChatUsersLeft,
  36. },
  37. Body: oscar.SNAC_0x0E_0x03_ChatUsersJoined{
  38. Users: []oscar.TLVUserInfo{},
  39. },
  40. },
  41. }
  42. routeSig := func(ctx context.Context, buf io.Reader, w io.Writer, u *uint32) error {
  43. return nil
  44. }
  45. wg := sync.WaitGroup{}
  46. wg.Add(len(msgIn))
  47. var msgOut []oscar.SNACMessage
  48. alertHandler := func(ctx context.Context, msg oscar.SNACMessage, w io.Writer, u *uint32) error {
  49. msgOut = append(msgOut, msg)
  50. wg.Done()
  51. return nil
  52. }
  53. go func() {
  54. wg.Wait()
  55. sess.Close()
  56. }()
  57. pr, _ := io.Pipe()
  58. rw := bufio.NewReadWriter(bufio.NewReader(pr), bufio.NewWriter(&bytes.Buffer{}))
  59. for _, msg := range msgIn {
  60. sessionManager.RelayToScreenName(ctx, "bob", msg)
  61. }
  62. dispatchIncomingMessages(ctx, sess, uint32(0), rw, logger, routeSig, alertHandler)
  63. assert.Equal(t, msgIn, msgOut)
  64. }
  65. func TestHandleChatConnection_ClientRequestFLAP(t *testing.T) {
  66. ctx := context.Background()
  67. cfg := config.Config{}
  68. logger := NewLogger(cfg)
  69. sessionManager := state.NewInMemorySessionManager(logger)
  70. sess := sessionManager.AddSession("bob-sess-id", "bob")
  71. payloads := [][]byte{
  72. {'a', 'b', 'c', 'd'},
  73. {'e', 'f', 'g', 'h'},
  74. }
  75. pr, pw := io.Pipe()
  76. _, pw2 := io.Pipe()
  77. go func() {
  78. for _, buf := range payloads {
  79. flap := oscar.FLAPFrame{
  80. StartMarker: 42,
  81. FrameType: oscar.FLAPFrameData,
  82. PayloadLength: uint16(len(buf)),
  83. }
  84. assert.NoError(t, oscar.Marshal(flap, pw))
  85. assert.NoError(t, oscar.Marshal(buf, pw))
  86. }
  87. }()
  88. var msgOut [][]byte
  89. wg := sync.WaitGroup{}
  90. wg.Add(len(payloads))
  91. routeSig := func(ctx context.Context, buf io.Reader, w io.Writer, u *uint32) error {
  92. var err error
  93. b, err := io.ReadAll(buf)
  94. msgOut = append(msgOut, b)
  95. wg.Done()
  96. return err
  97. }
  98. alertHandler := func(ctx context.Context, msg oscar.SNACMessage, w io.Writer, u *uint32) error {
  99. return nil
  100. }
  101. rw := bufio.NewReadWriter(bufio.NewReader(pr), bufio.NewWriter(pw2))
  102. go func() {
  103. wg.Wait()
  104. pw.Close()
  105. }()
  106. dispatchIncomingMessages(ctx, sess, uint32(0), rw, logger, routeSig, alertHandler)
  107. assert.Equal(t, payloads, msgOut)
  108. }
  109. func TestHandleChatConnection_SessionClosed(t *testing.T) {
  110. ctx := context.Background()
  111. cfg := config.Config{}
  112. logger := NewLogger(cfg)
  113. sessionManager := state.NewInMemorySessionManager(logger)
  114. sess := sessionManager.AddSession("bob-sess-id", "bob")
  115. routeSig := func(ctx context.Context, buf io.Reader, w io.Writer, u *uint32) error {
  116. t.Fatal("not expecting any output")
  117. return nil
  118. }
  119. alertHandler := func(ctx context.Context, msg oscar.SNACMessage, w io.Writer, u *uint32) error {
  120. t.Fatal("not expecting any alerts")
  121. return nil
  122. }
  123. pr1, _ := io.Pipe()
  124. pr2, pw2 := io.Pipe()
  125. in := struct {
  126. io.Reader
  127. io.Writer
  128. }{
  129. Reader: pr1,
  130. Writer: pw2,
  131. }
  132. sess.Close()
  133. go dispatchIncomingMessages(ctx, sess, 0, in, logger, routeSig, alertHandler)
  134. flap := oscar.FLAPFrame{}
  135. assert.NoError(t, oscar.Unmarshal(&flap, pr2))
  136. assert.Equal(t, oscar.FLAPFrameSignoff, flap.FrameType)
  137. }