//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 CSeq: %s %sPublic: %s ", 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] == ' ')
// 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))