live555 RTSPClient类和RTSPServer类

//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))

posted @ 2013-12-18 14:25  Cai00  阅读(1499)  评论(0编辑  收藏  举报