ARTSPConnection::receiveRTSPReponse

bool ARTSPConnection::receiveRTSPReponse() {
    AString statusLine;

    //调用函数receiveLine从套接口获取服务端消息的第一行,在下文被称为状态行statusLine
    if (!receiveLine(&statusLine)) {
        return false;
    }

    if (statusLine == "$") {
        //如果状态行statusLine为字符"$",则需要接收二进制数据
        //这里不具体讨论如何接收二进制数据
        sp<ABuffer> buffer = receiveBinaryData();

        if (buffer == NULL) {
            return false;
        }

        if (mObserveBinaryMessage != NULL) {
            sp<AMessage> notify = mObserveBinaryMessage->dup();
            notify->setBuffer("buffer", buffer);
            notify->post();
        } else {
            ALOGW("received binary data, but no one cares.");
        }

        return true;
    }

    //创建一个ARTSPResponse类对象来表述一个服务端的消息
    //将状态行赋给该对象的成员变量mStatusLine
    sp<ARTSPResponse> response = new ARTSPResponse;
    response->mStatusLine = statusLine;

    ALOGI("status: %s", response->mStatusLine.c_str());

    ssize_t space1 = response->mStatusLine.find(" ");
    if (space1 < 0) {
        return false;
    }
    ssize_t space2 = response->mStatusLine.find(" ", space1 + 1);
    if (space2 < 0) {
        return false;
    }

    //布尔变量isRequest 是用来表示该RTSP消息是请求消息还是应答消息
    //即用来判断该消息是服务端发送过来的请求消息还是服务端发送来的应答消息
    //具体的判别方法是根据版本号"RTSP/1.0"在状态行statusLine存放的位置
    //对于请求消息的第一行:方法 URI RTSP版本 CR LF 
    //对于回应消息的第一行:RTSP版本 状态码 解释 CR LF
    bool isRequest = false;

    if (!IsRTSPVersion(AString(response->mStatusLine, 0, space1))) {
        //如果IsRTSPVersion(AString(response->mStatusLine, 0, space1)的返回值不为真说明mStatusLine[0,space1]存放的不是版本号"RTSP/1.0"
        //如果IsRTSPVersion(
        //            AString(
        //                response->mStatusLine,
        //                space2 + 1,
        //                response->mStatusLine.size() - space2 - 1))
        //的调用值为真说明mStatusLine[space2 + 1,response->mStatusLine.size() - space2 - 1]存放的是版本号"RTSP/1.0"
        //则该消息为服务端发送过来的请求消息,将isRequest 设置为 true
        //将response对象的成员变量mStatusCode状态码设置为0,因为只有回应消息才有状态码
        CHECK(IsRTSPVersion(
                    AString(
                        response->mStatusLine,
                        space2 + 1,
                        response->mStatusLine.size() - space2 - 1)));

        isRequest = true;

        response->mStatusCode = 0;
    } else {
        //代码执行到else分支说明IsRTSPVersion(AString(response->mStatusLine, 0, space1)返回值为真
        //说明mStatusLine[0,space1]存放的是版本号"RTSP/1.0",由于isRequest初始值为false,所以在这里不需要再赋值为false了
        //从mStatusLine[space1 + 1,space2 - space1 - 1]获取到状态码的字符表示
        AString statusCodeStr(
                response->mStatusLine, space1 + 1, space2 - space1 - 1);

        //调用ParseSingleUnsignedLong函数将字符表示的状态码转换成整数表示的状态码,并赋值为response的成员变量mStatusCode
        //状态码有效的整数值范围为100~999(包括100和999)
        if (!ParseSingleUnsignedLong(
                    statusCodeStr.c_str(), &response->mStatusCode)
                || response->mStatusCode < 100 || response->mStatusCode > 999) {
            return false;
        }
    }

    //代码执行到这里成功判断了该消息是服务端发送来的回应消息还是请求消息,由布尔变量isRequest表示
    //接下来要获取消息后续的行,紧接着是消息头headers,会有多个消息头
    //一个消息头占据一到多个行,若占据多个行,后续的行开头用空格' '或者制表符'\t'来标识
    AString line;
    //lastDictIndex变量用来标识上一个消息头在对象response的成员变量mHeaders容器里存放的位置
    ssize_t lastDictIndex = -1;

    //采用一个无限循环来获取剩余的所有的行
    for (;;) {
        //调用函数receiveLine来获取一行
        if (!receiveLine(&line)) {
            break;
        }

        //如果该行为空,则停止获取,终止循环
        if (line.empty()) {
            break;
        }

        ALOGV("line: '%s'", line.c_str());

        //如果获取的该行首字符为' '或者'\t'则,说明该回去的一行是上一行携带的参数值
        //将该行和上一行合并在一起
        if (line.c_str()[0] == ' ' || line.c_str()[0] == '\t') {
            // Support for folded header values.

            if (lastDictIndex < 0) {
                //lastDictIndex变的值为负,说明没有任何行添加到了对象response的成员变量mHeaders容器里
                //既然该获取的行又被表示为上一行携带的参数,显然是发生了错误
                // First line cannot be a continuation of the previous one.
                return false;
            }

            //根据lastDictIndex变量得到上一行在response的成员变量mHeaders容器里存放的引用
            AString &value = response->mHeaders.editValueAt(lastDictIndex);
            //将该被表示为上一行引用的一行和上一行进行合并
            //continue跳出本次循环继续获取下一行
            value.append(line);

            continue;
        }

        //代码执行到这里说明该行的首字符不是' '或者'\t',说明该行是一个header
        //给一个header的例子,Accept: application/rtsl, application/sdp;level=2
        //冒号前的字符是该header的key
        //查找冒号在改行的位置colonPos
        ssize_t colonPos = line.find(":");
        if (colonPos < 0) {
            //如果colonPos的值小于0,则说明该行是一个错误的header line
            // Malformed header line.
            return false;
        }

        //从该行获取该行的header line的key
        AString key(line, 0, colonPos);
        key.trim();
        key.tolower();

        //将该行的header line的key从该行删除
        line.erase(0, colonPos + 1);

        //用key,value的方式将该header line的key与其内容保存在response->mHeaders容器里
        //并将其保存的位置索引保存在变量lastDictIndex中
        lastDictIndex = response->mHeaders.add(key, line);
    }

    //代码执行到这里,已经跳出了for循环
    for (size_t i = 0; i < response->mHeaders.size(); ++i) {

        response->mHeaders.editValueAt(i).trim();
    }

    //开始分析key为content-length的header line
    unsigned long contentLength = 0;

    ssize_t i = response->mHeaders.indexOfKey("content-length");

    if (i >= 0) {
        //根据content-length这一个header line存放的位置索引i得到该header line 的value
        AString value = response->mHeaders.valueAt(i);
        //调用ParseSingleUnsignedLong将该content-length的值的字符表示转换成整数表示
        if (!ParseSingleUnsignedLong(value.c_str(), &contentLength)) {
            return false;
        }
    }

    if (contentLength > 0) {
        //如果contentLength的值大于0,则需要创建一个buffer并调用receive函数从创建的套接口获取内容
        //并将缓冲区的引用赋值给response->mContent
        response->mContent = new ABuffer(contentLength);

        if (receive(response->mContent->data(), contentLength) != OK) {
            return false;
        }
    }

    if (response->mStatusCode == 401) {
        //对状态码为401的回应消息做特别的处理
        if (mAuthType == NONE && mUser.size() > 0
                && parseAuthMethod(response)) {
            ssize_t i;
            CHECK_EQ((status_t)OK, findPendingRequest(response, &i));
            CHECK_GE(i, 0);

            sp<AMessage> reply = mPendingRequests.valueAt(i);
            mPendingRequests.removeItemsAt(i);

            AString request;
            CHECK(reply->findString("original-request", &request));

            sp<AMessage> msg = new AMessage(kWhatSendRequest, this);
            msg->setMessage("reply", reply);
            msg->setString("request", request.c_str(), request.size());

            ALOGI("re-sending request with authentication headers...");
            onSendRequest(msg);

            return true;
        }
    }


    //对RTSP消息进行处理
    //如果isRequest为真,说明response是服务端发送过来的请求消息则调用handleServerRequest(response)处理服务端发送来的请求消息
    //如果isRequest不为真说明response是服务端发送过来的回应消息,调用notifyResponseListener(response)函数处理服务端发送过来的消息
    return isRequest
        ? handleServerRequest(response)
        : notifyResponseListener(response);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值