[Live-devel] RTSPServer may stop sending data when tunnelling over TCP
Kirill Zhegulev
kzhegulev at icontrol.com
Thu Apr 30 18:35:12 PDT 2015
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:
More information about the live-devel
mailing list