Hi.

Noted this when using RTSP relay.

Use case (probably can be simplified):
- RTSP relay based on RTSPServer with RTP over TCP.
- Open connection (#1) and let it run. At this point relay connects to the 
source stream and starts forwarding packets.
- Open another connection (#2) to the same stream and close it once start 
receiving data.
- Open third connection (#3) to the same stream. It will likely be through the 
same socket descriptor as connection (#2). This is important for the scenario.
- 60 seconds after connection #2 was closed, server will stop sending data to 
connection #3. It won’t close the socket, it will just stop sending data.

Explanation.
- When RTSPServer::RTSPClientSession is created livenessTimeoutTask() is 
scheduled and it gets rescheduled while connection is on.
- 60 seconds after connection is closed livenessTimeoutTask() is executed. It 
will delete clientSession, which will call reclaimStreamStates(), which deletes 
stream. Eventually RTPInterface::removeStreamSocket() gets called with file 
descriptor from connection #2
- At that time this file descriptor belongs to connection #3 and 
tcpStreamRecord for connection #3 is removed from the list.

I assume that it is not expected that RTSPClientSession outlives 
RTSPClientConnection and suggest destroying them at the same time.

Something like this:

--- a/liveMedia/RTSPServer.cpp
+++ b/liveMedia/RTSPServer.cpp
@@ -433,7 +433,8 @@ RTSPServer::RTSPClientConnection
 ::RTSPClientConnection(RTSPServer& ourServer, int clientSocket, struct 
sockaddr_in clientAddr)
   : fOurServer(ourServer), fIsActive(True),
     fClientInputSocket(clientSocket), fClientOutputSocket(clientSocket), 
fClientAddr(clientAddr),
-    fRecursionCount(0), fOurSessionCookie(NULL) {
+    fRecursionCount(0), fOurSessionCookie(NULL),
+    fConnectionSessions(HashTable::create(STRING_HASH_KEYS)) {
   // Add ourself to our 'client connections' table:
   fOurServer.fClientConnections->Add((char const*)this, this);
   
@@ -452,8 +453,19 @@ RTSPServer::RTSPClientConnection::~RTSPClientConnection() {
     fOurServer.fClientConnectionsForHTTPTunneling->Remove(fOurSessionCookie);
     delete[] fOurSessionCookie;
   }
+
+  HashTable::Iterator* iter = 
HashTable::Iterator::create(*fConnectionSessions);
+  RTSPServer::RTSPClientSession* clientSession;
+  char const* key;
+  while ((clientSession = (RTSPServer::RTSPClientSession*)(iter->next(key))) 
!= NULL) {
+    clientSession = 
(RTSPServer::RTSPClientSession*)(fOurServer.fClientSessions->Lookup(key));
+    if (clientSession == NULL) continue;
+    delete clientSession;
+  }
+  delete iter;
   
   closeSockets();
+  delete fConnectionSessions;
 }
 
 // Special mechanism for handling our custom "REGISTER" command:
@@ -1029,6 +1041,7 @@ void 
RTSPServer::RTSPClientConnection::handleRequestBytes(int newBytesRead) {
            } while (sessionId == 0 || 
fOurServer.fClientSessions->Lookup(sessionIdStr) != NULL);
            clientSession = fOurServer.createNewClientSession(sessionId);
            fOurServer.fClientSessions->Add(sessionIdStr, clientSession);
+            fConnectionSessions->Add(sessionIdStr, clientSession);
          } else {
            areAuthenticated = False;
          }
diff --git a/liveMedia/include/RTSPServer.hh b/liveMedia/include/RTSPServer.hh
index c998e29..4d77b89 100644
--- a/liveMedia/include/RTSPServer.hh
+++ b/liveMedia/include/RTSPServer.hh
@@ -264,6 +264,7 @@ public: // should be protected, but some old compilers 
complain otherwise
     Authenticator fCurrentAuthenticator; // used if access control is needed
     char* fOurSessionCookie; // used for optional RTSP-over-HTTP tunneling
     unsigned fBase64RemainderCount; // used for optional RTSP-over-HTTP 
tunneling (possible values: 0,1,2,3)
+    HashTable* fConnectionSessions; // maps 'session id' strings to 
"RTSPClientSession" objects
   };
 
   // The state of an individual client session (using one or more sequential 
TCP connections) handled by a RTSP server:


_______________________________________________
live-devel mailing list
live-devel@lists.live555.com
http://lists.live555.com/mailman/listinfo/live-devel

Reply via email to