// 1. DynamicRTSPServer (): DynamicRTSPServer. cpp
// | --- RTSPServerSupportingHTTPStreaming (): RTSPServerSupportingHTTPStreaming. cpp
// 2. createNew (): DynamicRTSPServer. cpp
// | --- SetUpOurSocket (): RTSPServer. cpp
// | --- SetupStreamSocket (): GroupsockHelper. cpp
// | --- CreateSocket (): Same as above
// | --- MAKE_SOCKADDR_IN (): Initialize struct sockaddr_in, GroupsockHelper. h,
// | --- Bind ()
// | --- Sock = socket (AF_INET, type | SOCK_CLOEXEC, 0 );
// | --- DynamicRTSPServer (): DynamicRTSPServer. cpp
// | --- RTSPServerSupportingHTTPStreaming (): RTSPServerSupportingHTTPStreaming. cpp 3. RTSPServerSupportingHTTPStreaming (): RTSPServerSupportingHTTPStreaming. cpp
| --- RTSPServer (): RTSPServer. cpp
4. RTSPServer (): RTSPServer. cpp
| --- Medium (): Media. cpp
| --- FRTSPServerPort ():
| --- FRTSPServerSocket ():
| --- FHTTPServerSocket ():
| --- FHTTPServerPort ():
| --- FServerMediaSessions ():
| --- FClientConnections ():
| --- FClientSessions ():
| --- FPendingRegisterRequests ():
All above are Initialization
| --- Env. taskScheduler (). turnOnBackgroundReadHandling (fRTSPServerSocket, (taskschedsocket: BackgroundHandlerProc *) & incomingConnectionHandlerRTSP, this );
The connection handler handle (RTSPServer: incomingConnectionHandler) and socket handle are passed to the tasksched Task Scheduler to put the socket handle into the socket handle set (fReadSet) used in the select call) medium,
Link the socket handle with the incomingConnectionHandler handle.
Next, the main program starts to enter the main loop of the task scheduler (doEventLoop), and calls the system function select in the main loop to block the network connection. 5. incomingConnectionHandler (): RTSPServer. cpp
| --- ClientSocket = accept ()
6. turnOnBackgroundReadHandling (): UsageEnvironment. h
| --- SetBackgroundHandling () :( virtual)
7. RTSPServer. cpp contains various message processing functions: handleapps_setup (), handle+_teardown (), handle+_play (), handle+_pause (), handle%_get_parameter (), handle%_set_parameter ().
8. Medium (): Media. cpp
| ---
9. RTSPClient class:
10. createNew (): RTSPClient. cpp
| --- RTSPClient (): Constructor
11. RTSPClient ():
| --- Medium ():
| --- FVerbosityLevel ():
| --- FServerAddress ():
| --- FTunnelOverHTTPPortNum ():
| --- FInputSocketNum ():
| --- FLastSessionId ():
All of the above are Initialization
| --- SetBaseURL (rtspURL ):
| --- Envir (). taskScheduler (). setBackgroundHandling (fInputSocketNum, SOCKET_READABLE | SOCKET_EXCEPTION, (TaskScheduler: BackgroundHandlerProc * & incomingDataHandler, this );
12. incomingDataHandler (): RTSPClient. cpp
| --- IncomingDataHandler1 ():
| --- ReadSocket (): GroupsockHelper. cpp
| --- Recvfrom ()
| --- HandleResponseBytes ():
| --- RequestQueue requestQueue (fRequestsAwaitingResponse );
| --- Request = requestQueue. dequeue ()
| --- Request = fRequestsAwaitingResponse. dequeue ()
| --- HandleSETUPResponse ()
| --- HandlePLAYResponse ()
| --- HandleTEARDOWNResponse ()
| --- HandleGET_PARAMETERResponse ()
13. handlePLAYResponse (): RTSPClient. cpp
| --- MediaSubsessionIterator iter (session ):
Puts the session into iter () and returns the sub-session iterator.
| --- While (subsession = iter. next ())! = NULL ):
Round Robin of all sub-sessions
| --- If (subsession-> rtpSource ()! = NULL) subsession-> rtpSource ()-> enableRTCPReports () = True;
// Start sending RTCP "RR" s now
HandlePLAYResponse () searches for both sessions and subsessions and calls the preceding three steps;
// The command was on a subsession
14. sendRequest (RequestRecord * request): RTSPClient. cpp
Send requests, which are encapsulated in RequestRecord
| --- If (! FRequestsAwaitingConnection. isEmpty ())
// A connection is currently pending (with at least one enqueued request ). enqueue this request also determines whether the connection exists. If yes, the request is sent to the queue and a serial number is returned. Otherwise, a connection is created:
| --- ConnectResult = openConnection ()
// Construct and send the command:
| --- AuthenticatorStr = createAuthenticatorString ()
| --- Send ()
// The command send succeeded, so enqueue the request record, so that its response (when it comes) can be handled.
If the request is sent successfully, the request is recorded in the queue, so that the request can be processed when the request arrives.
| --- Cseq = request-> cseq ()
Returns a serial number.
15. lookupByName ()
Find the RTSPClient specified by sourceName
| --- If (! Medium: lookupByName (env, instanceName, medium) return False;
| ---! Medium-> isRTSPClient ()
| --- ResultClient = (RTSPClient *) medium; return True;
16. Other functions of RTSPClient. cpp:
| --- Reset ()
Reset RTSPClient, 1. Disable socket; 2. Reset the directive variable of responseBuffer; 3. Clear BaseURL, etc.
| --- SetBaseURL (char const * url)
Set the request URL Information fBaseURL
| --- RTSPClient: RequestRecord ()
This class encapsulates request commands and is only used to save request information, such as command names and callback functions: RTSPClient: RequestRecord (unsigned cseq, responseHandler * handler, char const * absStartTime, char const * absEndTime, float scale, MediaSession * session, MediaSubsession * subsession): fNext (NULL), fCSeq (cseq), fCommandName ("PLAY "), fSession, fSubsession, fBooleanFlags (0), fStart (0.0f), fEnd (-1.0f), fAbsStartTime (strDup (absStartTime )), fAbsEndTime (strDup (absEndTime), fScale (scale), fContentStr (NULL), fHandler (handler ){}
All information is passed in during initialization, and the class provides an access method for each information. | --- RTSPClient: RequestQueue ()
This class defines the RequestRecord queue, which can store request information, and provides some tools and methods as follows:
PutAtHead (RequestRecord * request );
// "Request" must not be NULL
RequestRecord * findByCSeq (unsigned cseq );
| --- SendPlayCommand ()
| --- SendPauseCommand ()
| --- SendRecordCommand ()
| --- SendTeardownCommand ()
17. RTSPServer class: RTSPServer. cpp
18. createNew (): RTSPServer. cpp
| --- OurSocket = setUpOurSocket (env, ourPort): RTSPServer. cpp
| --- SetupStreamSocket (): GroupsockHelper. cpp
| --- CreateSocket (): GroupsockHelper. cpp
| --- Sock = socket (AF_INET, type | SOCK_CLOEXEC, 0 );
// Make sure we have a big send buffer:
| --- IncreaseSendBufferTo (env, ourSocket, 50*1024)
| --- GetSourcePort (env, ourSocket, ourPort): RTSPServer. cpp
| --- GetSourcePort0 ()
// Getsockname () returns the current address to which the socket socketfd is bound,
// In the buffer pointed to by addr.
| --- Getsockname (socket, (struct sockaddr *) & test, & len)
| --- ResultPortNum = ntohs (test. sin_port );
Return True;
| --- MAKE_SOCKADDR_IN (): Initialize struct sockaddr_in, GroupsockHelper. h,
| --- Bind ()
| --- Port = Port (portNum);/* in host byte order */
| --- RTSPServer (): Constructor
19. For RTSPServer (), see the fourth point.
20. addServerMediaSession ()
Add serverMediaSession corresponding to sessionName to the hash table
| --- FServerMediaSessions-> Add (sessionName, (void *) serverMediaSession) 21. removeServerMediaSession ()
Delete the "ServerMediaSession" object from the query table. The new RTSP client cannot access the object.
However, the original RTSP client session still works.
Only when all RTSP client sessions are closed can the "ServerMediaSession" object be deleted.
22. deleteServerMediaSession ()
CloseAllClientSessionsForServerMediaSession () and removeServerMediaSession () are called ().
23. class RegisterRequestRecord: public RTSPRegisterSender RegisterRequestRecord () | --- RTSPRegisterSender ()
| --- FOurServer (ourServer)
| --- FRequestId (requestId)
| --- FResponseHandler (responseHandler)
| --- OurServer. fPendingRegisterRequests-> Add (char const *) this, this)
// Add ourself to our server's 'pending REGISTER requests' table:
Add the RTSPServer to the REGISTER request wait table
24. handleResponse (): belongs to class RegisterRequestRecord
// The "REGISTER" request succeeded, so use the still-open RTSP socket
To await incoming commands from the remote endpoint
If the REGISTER request table is successfully added, create an RTSP socket and wait for the remote connection command
| --- GrabConnection (sock, remoteAddress)
| --- GrabSocket ()
| --- MAKE_SOCKADDR_IN
| --- FOurServer. createNewClientConnection (sock, remoteAddress)
| --- Return new RTSPClientConnection (* this, clientSocket, clientAddr)
This is a constructor.
// Call our (REGISTER-specific) response handler now
| --- (* FResponseHandler) (& fOurServer, fRequestId, resultCode, resultString );
25. RTSPClientConnection ()
| --- FOurServer. fClientConnections-> Add (char const *) this, this)
| --- Envir (). taskScheduler (). setBackgroundHandling (fClientInputSocket, SOCKET_READABLE | SOCKET_EXCEPTION, (TaskScheduler: BackgroundHandlerProc *) & incomingRequestHandler, this );
Pass the incomingRequestHandler and socket handle to the task scheduler ),
Link the socket handle with the incomingConnectionHandler handle.
26. registerStream ()
// Create a new "RegisterRequestRecord" that will send the "REGISTER" command.
// (This object will automatically get deleted after we get a response to the "REGISTER" command, or if we're re deleted .)
Create a "RegisterRequestRecord" object to send the "REGISTER" command
When we receive the "REGISTER" command, this object will be automatically deleted.
| --- Authenticator = new Authenticator (username, password)
| --- New RegisterRequestRecord ()
27. setUpOurSocket ()
| --- OurSocket = setupStreamSocket (env, ourPort): GroupsockHelper. cpp
// Call "socket ()" to create a (IPv4) socket of the specified type.
// But also set it to have the 'close on exec 'property (if we can)
| --- CreateSocket (SOCK_STREAM): GroupsockHelper. cpp
| --- Sock = socket (AF_INET, type | SOCK_CLOEXEC, 0 );
| --- Setsockopt (newSocket, SOL_SOCKET, SO_REUSEADDR, (const char *) & reuseFlag, sizeof reuseFlag)
| --- # Ifdef SO_REUSEPORT
Setsockopt (newSocket, SOL_SOCKET, SO_REUSEPORT, (const char *) & reuseFlag, sizeof reuseFlag)
| --- MAKE_SOCKADDR_IN
| --- Bind (newSocket, (struct sockaddr *) & name, sizeof name)
| --- If (makeNonBlocking)
MakeSocketNonBlocking (newSocket)
| --- IncreaseSendBufferTo (env, ourSocket, 50*1024)
// Make sure we have a big send buffer
Ensure sufficient sending Buffer
| --- Listen (ourSocket, LISTEN_BACKLOG_SIZE)
// Allow multiple simultaneous connections
Allow concurrent connections
// Bind () will have chosen a port for us; return it also
The bind () function has already selected a port number for us. We can also customize it.
| --- GetSourcePort (env, ourSocket, ourPort): GroupsockHelper. cpp
| --- GetSourcePort0 (socket, portNum)
Allocate a port number
| --- Getsockname ()
| --- ResultPortNum = ntohs (test. sin_port)
28. incomingConnectionHandlerRTSP ()
| --- IncomingConnectionHandlerRTSP1 ()
| --- IncomingConnectionHandler (fRTSPServerSocket)
| --- ClientSocket = accept ()
| --- MakeSocketNonBlocking (clientSocket)
| --- IncreaseSendBufferTo (envir (), clientSocket, 50*1024)
29. handleapps_options ()
| --- Snprintf (char *) fResponseBuffer, sizeof fResponseBuffer, "RTSP/1.0 200 OK \ r \ nCSeq: % s \ r \ n % sPublic: % s \ r \ n ", fCurrentCSeq, dateHeader (), fOurServer. allowedCommandNames ());
30. handleCmd_GET_PARAMETER ()
31. handleCmd_SET_PARAMETER ()
32. handleapps_describe ()
33. There are several handleCmd Functions
34. RTSPServer: RTSPClientConnection: incomingRequestHandler
| --- Session-> incomingRequestHandler1 ()
| --- BytesRead = readSocket (): GroupsockHelper. cpp
| --- Int bytesRead = recvfrom ()
| --- HandleRequestBytes (bytesRead)
35. handleRequestBytes ()
| --- ParseRTSPRequestString ()
// If the request was ded a "Session:" id, and it refers to a client session that's current ongoing, then use this
// Command to indicate 'liveness 'on that client session:
| --- FOurServer. fClientSessions-> Lookup (sessionIdStr)
| --- Handleapps_options ()
| --- HandleCmd_GET_PARAMETER ()
| --- HandleCmd_SET_PARAMETER ()
| --- Handleapps_describe ()
| --- If (sessionIdStr [0] = '\ 0 ')
// No session id was present in the request. so create a new "RTSPClientSession" object for this request. // Choose a random (unused) 32-bit integer for the session id (it will be encoded as a 8-digit hex number ).
// (We avoid choosing session id 0, because that has a special use (by "OnDemandServerMediaSubsession ").)
If there is no session ID in the request, create a new "RTSPClientSession" object for the request.
U_int32_t sessionId;
SessionId = (u_int32_t) our_random32 ()
| --- ClientSession = fOurServer. createNewClientSession (sessionId );
FOurServer. fClientSessions-> Add (sessionIdStr, clientSession );
// The request was ded a session id. Make sure it's one that we have already set up:
| --- ClientSession = (RTSPServer: RTSPClientSession *) (fOurServer. fClientSessions-> Lookup (sessionIdStr ));
| --- ClientSession-> handleapps_setup () 36. RTSPServer: RTSPClientSession ()
37. RTSPServer: ServerMediaSessionIterator ()
This is the constructor.
| ---: FOurIterator (server. fServerMediaSessions = NULL )? NULL: HashTable: Iterator: create (* server. fServerMediaSessions ))