//1.DynamicRTSPServer():DynamicRTSPServer.cpp
// |---RTSPServerSupportingHTTPStreaming():RTSPServerSupportingHTTPStreaming.cpp
//2.createNew():DynamicRTSPServer.cpp
// |---setUpOurSocket():RTSPServer.cpp
// |---setupStreamSocket():GroupsockHelper.cpp
// |---createSocket():同上
// |---MAKE_SOCKADDR_IN():初始化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():
上述均為初始化
|---env.taskScheduler().turnOnBackgroundReadHandling(fRTSPServerSocket, (TaskScheduler::BackgroundHandlerProc*)&incomingConnectionHandlerRTSP, this);
把連接處理函數句柄(RTSPServer::incomingConnectionHandler)和socket句柄傳給任務調度器(taskScheduler) 任務調度器把socket句柄放入後面select調用中用到的socket句柄集(fReadSet)中,
同時將socket句柄和incomingConnectionHandler句柄關聯起來。
接著,主程序開始進入任務調度器的主循環(doEventLoop),在主循環中調用系統函數select阻塞,等待網絡連接。 5.incomingConnectionHandler():RTSPServer.cpp
|---clientSocket = accept()
6.turnOnBackgroundReadHandling():UsageEnvironment.h
|---setBackgroundHandling():(virtual)
7.RTSPServer.cpp中有各種消息處理函數:handleCmd_SETUP(),handleCmd_TEARDOWN(),handleCmd_PLAY(), handleCmd_PAUSE(),handleCmd_GET_PARAMETER(),handleCmd_SET_PARAMETER().
8.Medium():Media.cpp
|---
9.RTSPClient類:
10.createNew():RTSPClient.cpp
|---RTSPClient():構造函數
11.RTSPClient():
|---Medium():
|---fVerbosityLevel():
|---fServerAddress():
|---fTunnelOverHTTPPortNum():
|---fInputSocketNum():
|---fLastSessionId():
以上皆為初始化
|---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):
將會話放入iter()返回子會話迭代器
|---while ((subsession = iter.next()) != NULL):
輪詢所有的子會話
|---if (subsession->rtpSource() != NULL) subsession->rtpSource()->enableRTCPReports() = True;
// start sending RTCP "RR"s now
handlePLAYResponse()將會話和子會話都查找一遍,調用以上三步;
// The command was on a subsession
14.sendRequest(RequestRecord* request):RTSPClient.cpp
發送請求,請求統一封裝在RequestRecord
|---if (!fRequestsAwaitingConnection.isEmpty())
// A connection is currently pending (with at least one enqueued request). Enqueue this request also 判斷連接是否存在,若存在,則請求入隊,然後返回一個序列號,否則創建一個連接:
|---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.
如果發送成功就將請求記錄入隊,這樣,當請求到來時可以被處理
|---cseq = request->cseq()
最後返回一個序列號
15.lookupByName()
查找sourceName指定的RTSPClient
|---if (!Medium::lookupByName(env, instanceName, medium)) return False;
|---!medium->isRTSPClient()
|---resultClient = (RTSPClient*)medium;return True;
16.RTSPClient.cpp的其他函數:
|---reset()
重置RTSPClient,1、關閉socket;2、重置responseBuffer的指示變量;3、清除分BaseURL等
|---setBaseURL(char const* url)
設置請求的URL信息fBaseURL
|---RTSPClient::RequestRecord::RequestRecord()
該類封裝了請求命令,只用來保存請求的信息,如命令名稱、回調函數等: RTSPClient::RequestRecord::RequestRecord(unsigned cseq, responseHandler* handler, char const* absStartTime, char const* absEndTime, float scale, MediaSession* session, MediaSubsession* subsession) :fNext(NULL), fCSeq(cseq), fCommandName("PLAY"), fSession(session), fSubsession(subsession), fBooleanFlags(0), fStart(0.0f), fEnd(-1.0f), fAbsStartTime(strDup(absStartTime)), fAbsEndTime(strDup(absEndTime)), fScale(scale), fContentStr(NULL), fHandler(handler) { }
所有信息都在初始化時傳入,之後類為每一個信息都提供了訪問方法 |---RTSPClient::RequestQueue::RequestQueue()
該類定義了RequestRecord的隊列,可以保存請求信息,還提供了一些工具方法如下:
putAtHead(RequestRecord* request);
// "request" must not be NULL
RequestRecord* findByCSeq(unsigned cseq);
|---sendPlayCommand()
|---sendPauseCommand()
|---sendRecordCommand()
|---sendTeardownCommand()
17.RTSPServer類: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():初始化struct sockaddr_in,GroupsockHelper.h,
|---bind()
|---port = Port(portNum);/* in host byte order */
|---RTSPServer():構造函數
19.RTSPServer()見第四點
20.addServerMediaSession()
將sessionName對應的serverMediaSession加入到哈希表中
|---fServerMediaSessions->Add(sessionName, (void*)serverMediaSession) 21.removeServerMediaSession()
從查找表中刪除"ServerMediaSession" 對象,新到來的RTSP客戶端不能再訪問他
但是原來的RTSP客戶端會話仍然能工作。
當所有的RTSP客戶端會話都被關閉時,"ServerMediaSession" 對象才能被刪除。
22. deleteServerMediaSession()
相當於調用了closeAllClientSessionsForServerMediaSession()和removeServerMediaSession()。
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:
將這個RTSPServer加入到REGISTER請求等待表
24.handleResponse():屬於class RegisterRequestRecord
// The "REGISTER" request succeeded, so use the still-open RTSP socket
to await incoming commands from the remote endpoint
如果成功加入REGISTER請求表,創建一個RTSP socket,等待遠程連接命令
|---grabConnection(sock, remoteAddress)
|---grabSocket()
|---MAKE_SOCKADDR_IN
|---fOurServer.createNewClientConnection(sock, remoteAddress)
|---return new RTSPClientConnection(*this, clientSocket, clientAddr)
這是個構造函數
// 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);
把連接處理函數句柄(incomingRequestHandler)和socket句柄傳給任務調度器(taskScheduler),
同時將socket句柄和incomingConnectionHandler句柄關聯起來。
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 deleted.)
為發送"REGISTER"命令而創建一個"RegisterRequestRecord"對象
當我們收到"REGISTER"命令時,這個對象會自動刪除
|---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
保證有足夠的發送緩沖
|---listen(ourSocket, LISTEN_BACKLOG_SIZE)
// Allow multiple simultaneous connections
允許並發連接
// bind() will have chosen a port for us; return it also
bind()函數已經為我們選擇了一個端口號,我們也可以自定義
|---getSourcePort(env, ourSocket, ourPort):GroupsockHelper.cpp
|---getSourcePort0(socket, portNum)
分配一個端口號
|---getsockname()
|---resultPortNum = ntohs(test.sin_port)
28.incomingConnectionHandlerRTSP()
|---incomingConnectionHandlerRTSP1()
|---incomingConnectionHandler(fRTSPServerSocket)
|---clientSocket = accept()
|---makeSocketNonBlocking(clientSocket)
|---increaseSendBufferTo(envir(), clientSocket, 50*1024)
29.handleCmd_OPTIONS()
|---snprintf((char*)fResponseBuffer, sizeof fResponseBuffer, "RTSP/1.0 200 OK\r\nCSeq: %s\r\n%sPublic: %s\r\n\r\n", fCurrentCSeq, dateHeader(), fOurServer.allowedCommandNames());
30.handleCmd_GET_PARAMETER()
31.handleCmd_SET_PARAMETER()
32.handleCmd_DESCRIBE()
33.還有好幾個handleCmd函數
34.RTSPServer::RTSPClientConnection::incomingRequestHandler
|---session->incomingRequestHandler1()
|---bytesRead = readSocket():GroupsockHelper.cpp
|---int bytesRead = recvfrom()
|---handleRequestBytes(bytesRead)
35.handleRequestBytes()
|---parseRTSPRequestString()
// If the request included 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)
|---handleCmd_OPTIONS()
|---handleCmd_GET_PARAMETER()
|---handleCmd_SET_PARAMETER()
|---handleCmd_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").)
如果在請求中沒有會話ID,那就為該請求創建一個新的"RTSPClientSession"對象
u_int32_t sessionId;
sessionId = (u_int32_t)our_random32()
|---clientSession = fOurServer.createNewClientSession(sessionId);
fOurServer.fClientSessions->Add(sessionIdStr, clientSession);
// The request included a session id. Make sure it's one that we have already set up:
|---clientSession = (RTSPServer::RTSPClientSession*)(fOurServer.fClientSessions->Lookup(sessionIdStr));
|---clientSession->handleCmd_SETUP() 36.RTSPServer::RTSPClientSession::RTSPClientSession()
37.RTSPServer::ServerMediaSessionIterator::ServerMediaSessionIterator()
這個是構造函數
|---:fOurIterator((server.fServerMediaSessions == NULL) ? NULL : HashTable::Iterator::create(*server.fServerMediaSessions))