MyHandler对消息'setu'的处理

本文详细解析了RTSP协议在客户端和服务端之间的交互过程,包括如何解析消息中的关键字段、处理响应状态码以及如何根据会话ID配置keep-alive超时时间等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

            case 'setu':
            {
                //在消息msg的字段"index"得到index的值
                size_t index;
                CHECK(msg->findSize("index", &index));

                TrackInfo *track = NULL;
                size_t trackIndex;
                //在消息msg的"track-index"字段得到trackIndex的值
                if (msg->findSize("track-index", &trackIndex)) {
                    //由trackIndex得到对应的TrackInfo
                    track = &mTracks.editItemAt(trackIndex);
                }

                //由消息msg的"result"字段得到result的值
                int32_t result;
                CHECK(msg->findInt32("result", &result));

                ALOGI("SETUP(%zu) completed with result %d (%s)",
                     index, result, strerror(-result));

                if (result == OK) {
                    //如果result的值为OK,则说明成功收到了服务端的应答消息
                    CHECK(track != NULL);

                    //由消息msg的"response"字段得到应答消息对象response
                    sp<RefBase> obj;
                    CHECK(msg->findObject("response", &obj));
                    sp<ARTSPResponse> response =
                        static_cast<ARTSPResponse *>(obj.get());

                    if (response->mStatusCode != 200) {
                        //如果应答消息的状态码不为200
                        //则将错误码UNKNOWN_ERROR赋值给result
                        result = UNKNOWN_ERROR;
                    } else {
                        //代码执行到这里说明应答消息的状态码为200
                        //从应答消息中获取头部为session的值
                        //并赋值给mSessionID成员变量
                        ssize_t i = response->mHeaders.indexOfKey("session");
                        CHECK_GE(i, 0);

                        mSessionID = response->mHeaders.valueAt(i);

                        mKeepAliveTimeoutUs = kDefaultKeepAliveTimeoutUs;
                        //从mSessionID变量的值中获取timeoutStr的值
                        AString timeoutStr;
                        if (GetAttribute(
                                    mSessionID.c_str(), "timeout", &timeoutStr)) {
                            //将字符串表示的timeoutStr的值转换成长整型数
                            char *end;
                            unsigned long timeoutSecs =
                                strtoul(timeoutStr.c_str(), &end, 10);

                            if (end == timeoutStr.c_str() || *end != '\0') {
                                ALOGW("server specified malformed timeout '%s'",
                                     timeoutStr.c_str());

                                //如果转换遇到了错误
                                //使用默认的KeepAliveTimeoutUs
                                mKeepAliveTimeoutUs = kDefaultKeepAliveTimeoutUs;
                            } else if (timeoutSecs < 15) {
                                //如果转换得到的timeoutSecs小于15,使用默认的KeepAliveTimeoutUs
                                ALOGW("server specified too short a timeout "
                                     "(%lu secs), using default.",
                                     timeoutSecs);

                                mKeepAliveTimeoutUs = kDefaultKeepAliveTimeoutUs;
                            } else {
                                //如果转换得到的timeoutSecs大于或等于15
                                //使用指定的KeepAliveTimeoutUs
                                mKeepAliveTimeoutUs = timeoutSecs * 1000000ll;

                                ALOGI("server specified timeout of %lu secs.",
                                     timeoutSecs);
                            }
                        }
                        AVMediaServiceUtils::get()->setServerTimeoutUs(mKeepAliveTimeoutUs);

                        //将"timeout=***"对应的字段从mSessionID中删除
                        i = mSessionID.find(";");
                        if (i >= 0) {
                            // Remove options, i.e. ";timeout=90"
                            mSessionID.erase(i, mSessionID.size() - i);
                        }

                        //新建一个异步通知消息notify
                        //消息名为'accu'
                        //消息处理者为this,也即MyHandler
                        //将trackIndex值设置到"track-index"字段
                        sp<AMessage> notify = new AMessage('accu', this);
                        notify->setSize("track-index", trackIndex);

                        //从应答消息里查找transport头部的值
                        i = response->mHeaders.indexOfKey("transport");
                        CHECK_GE(i, 0);

                        if (track->mRTPSocket != -1 && track->mRTCPSocket != -1) {
                            if (!track->mUsingInterleavedTCP) {
                                //得到应答消息transport头部的值
                                AString transport = response->mHeaders.valueAt(i);

                                // We are going to continue even if we were
                                // unable to poke a hole into the firewall...
                                //调用AVMediaServiceUtils::get()->pokeAHole进行防火墙处理


                               AVMediaServiceUtils::get()->pokeAHole(
                                        this,
                                        track->mRTPSocket,
                                        track->mRTCPSocket,
                                        transport,
                                        mSessionHost);
                            }

                            //调用mRTPConn->addStream添加一个RTP流
                            //该函数在后续文章详细介绍
                            mRTPConn->addStream(
                                    track->mRTPSocket, track->mRTCPSocket,
                                    mSessionDesc, index,
                                    notify, track->mUsingInterleavedTCP,
                                    mConn->isIPV6());

                            //成功创建了一个track
                            //将mSetupTracksSuccessful的值赋值为true
                            mSetupTracksSuccessful = true;
                        } else {
                            //代码执行到这里说明track->mRTPSocket != -1 && track->mRTCPSocket != -1的值不为真
                            //将错误码BAD_VALUE赋值给result
                            result = BAD_VALUE;
                        }
                    }
                }

                if (result != OK) {
                    //如果上述过程中result的值不是OK
                    //则进行相应的错误处理
                    //关闭track->mRTPSocket描述的套接口
                    //关闭track->mRTCPSocket描述的套接口
                    if (track) {
                        if (!track->mUsingInterleavedTCP) {
                            // Clear the tag
                            if (mUIDValid) {
                                HTTPBase::UnRegisterSocketUserTag(track->mRTPSocket);
                                HTTPBase::UnRegisterSocketUserMark(track->mRTPSocket);
                                HTTPBase::UnRegisterSocketUserTag(track->mRTCPSocket);
                                HTTPBase::UnRegisterSocketUserMark(track->mRTCPSocket);
                            }

                            close(track->mRTPSocket);
                            close(track->mRTCPSocket);
                        }

                        //将该track从mTracks容器里删除
                        mTracks.removeItemsAt(trackIndex);
                    }
                }

                //将index所以自增1
                ++index;
                if (result == OK && index < mSessionDesc->countTracks()) {
                    //如果还有其他的tarck
                    //继续调用setupTrack函数创建对应的tarck
                    setupTrack(index);
                } else if (mSetupTracksSuccessful) {
                    //代码执行到这里
                    //说明所有的tarck都已经创建完毕
                    ++mKeepAliveGeneration;
                    postKeepAlive();

                    //构建请求消息
                    //方法名为PLAY
                    AString request = "PLAY ";
                    request.append(mControlURL);
                    request.append(" RTSP/1.0\r\n");

                    //添加Session头部
                    request.append("Session: ");
                    request.append(mSessionID);
                    request.append("\r\n");

                    AVMediaServiceUtils::get()->appendRange(&request);
                    //添加消息头部和消息体的分隔符
                    request.append("\r\n");

                    //新建异步处理消息reply
                    //消息名为'play'
                    //消息处理者为this也即MyHandler
                    sp<AMessage> reply = new AMessage('play', this);
                    //调用mConn->sendRequest发送该请求消息
                    //异步应答消息reply会被暂时存放在mConn的mPengdingRequests里
                    //直到对应的服务端的应答消息的到来
                    //该异步处理消息reply则被发送出去
                    mConn->sendRequest(request.c_str(), reply);
                } else {
                    //代码执行到这里说明mSetupTracksSuccessful的值不为真
                    //即带创建track的时候发生了错误
                    //新建消息reply取消连接
                    sp<AMessage> reply = new AMessage('disc', this);
                    mConn->disconnect(reply);
                }
                break;
            }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值