Просмотр исходного кода

send disconnect flap when server shuts down

Mike 11 месяцев назад
Родитель
Сommit
7d637bbca3
2 измененных файлов с 58 добавлено и 0 удалено
  1. 6 0
      server/oscar/server.go
  2. 52 0
      server/oscar/server_test.go

+ 6 - 0
server/oscar/server.go

@@ -574,6 +574,12 @@ func (s oscarServer) dispatchIncomingMessages(
 			}
 			return nil
 		case <-ctx.Done():
+			block := wire.TLVRestBlock{}
+			// send explicit disconnect notification to client since proxies
+			// between client and server may not properly terminate connections
+			if err := flapc.SendSignoffFrame(block); err != nil {
+				return fmt.Errorf("unable to gracefully disconnect user. %w", err)
+			}
 			// application is shutting down
 			if err := flapc.Disconnect(); err != nil {
 				return fmt.Errorf("unable to gracefully disconnect user. %w", err)

+ 52 - 0
server/oscar/server_test.go

@@ -619,3 +619,55 @@ func TestOscarServer_RouteConnection_Admin(t *testing.T) {
 
 	wg.Wait()
 }
+
+// Make sure the client receives signoff FLAP when the server shuts down via
+// context cancellation.
+func Test_oscarServer_dispatchIncomingMessages_shutdownSignoff(t *testing.T) {
+	clientConn, serverConn := net.Pipe()
+	ctx, cancel := context.WithCancel(context.Background())
+
+	var wg sync.WaitGroup
+	wg.Add(1)
+	go func() {
+		defer wg.Done()
+		srv := oscarServer{
+			Logger: slog.Default(),
+		}
+		sess := state.NewSession()
+		flapc := wire.NewFlapClient(0, serverConn, serverConn)
+		err := srv.dispatchIncomingMessages(ctx, wire.BOS, sess, flapc, serverConn, "")
+		assert.NoError(t, err)
+	}()
+
+	cancel()
+	flapc := wire.NewFlapClient(0, clientConn, clientConn)
+	frame, err := flapc.ReceiveFLAP()
+	assert.NoError(t, err)
+	assert.Equal(t, wire.FLAPFrameSignoff, frame.FrameType)
+}
+
+// Make sure the client receives disconnection signoff FLAP when the session
+// gets logged off by a new session.
+func Test_oscarServer_dispatchIncomingMessages_disconnect(t *testing.T) {
+	clientConn, serverConn := net.Pipe()
+	ctx := context.Background()
+	sess := state.NewSession()
+
+	var wg sync.WaitGroup
+	wg.Add(1)
+	go func() {
+		defer wg.Done()
+		srv := oscarServer{
+			Logger: slog.Default(),
+		}
+		flapc := wire.NewFlapClient(0, serverConn, serverConn)
+		err := srv.dispatchIncomingMessages(ctx, wire.BOS, sess, flapc, serverConn, "")
+		assert.NoError(t, err)
+	}()
+
+	sess.Close()
+	flapc := wire.NewFlapClient(0, clientConn, clientConn)
+	frame, err := flapc.ReceiveFLAP()
+	assert.NoError(t, err)
+	assert.Equal(t, wire.FLAPFrameSignoff, frame.FrameType)
+}