Home | History | Annotate | Download | only in rtsp
      1 /*
      2  * Copyright (C) 2010 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 //#define LOG_NDEBUG 0
     18 #define LOG_TAG "ARTSPConnection"
     19 #include <utils/Log.h>
     20 
     21 #include "ARTSPConnection.h"
     22 
     23 #include <media/stagefright/foundation/ABuffer.h>
     24 #include <media/stagefright/foundation/ADebug.h>
     25 #include <media/stagefright/foundation/AMessage.h>
     26 #include <media/stagefright/foundation/base64.h>
     27 #include <media/stagefright/MediaErrors.h>
     28 #include <media/stagefright/Utils.h>
     29 
     30 #include <arpa/inet.h>
     31 #include <fcntl.h>
     32 #include <netdb.h>
     33 #include <openssl/md5.h>
     34 #include <sys/socket.h>
     35 
     36 #include "include/HTTPBase.h"
     37 
     38 namespace android {
     39 
     40 // static
     41 const int64_t ARTSPConnection::kSelectTimeoutUs = 1000ll;
     42 
     43 // static
     44 const AString ARTSPConnection::sUserAgent =
     45     AStringPrintf("User-Agent: %s\r\n", MakeUserAgent().c_str());
     46 
     47 ARTSPConnection::ARTSPConnection(bool uidValid, uid_t uid)
     48     : mUIDValid(uidValid),
     49       mUID(uid),
     50       mState(DISCONNECTED),
     51       mAuthType(NONE),
     52       mSocket(-1),
     53       mConnectionID(0),
     54       mNextCSeq(0),
     55       mReceiveResponseEventPending(false) {
     56 }
     57 
     58 ARTSPConnection::~ARTSPConnection() {
     59     if (mSocket >= 0) {
     60         ALOGE("Connection is still open, closing the socket.");
     61         if (mUIDValid) {
     62             HTTPBase::UnRegisterSocketUserTag(mSocket);
     63             HTTPBase::UnRegisterSocketUserMark(mSocket);
     64         }
     65         close(mSocket);
     66         mSocket = -1;
     67     }
     68 }
     69 
     70 void ARTSPConnection::connect(const char *url, const sp<AMessage> &reply) {
     71     sp<AMessage> msg = new AMessage(kWhatConnect, this);
     72     msg->setString("url", url);
     73     msg->setMessage("reply", reply);
     74     msg->post();
     75 }
     76 
     77 void ARTSPConnection::disconnect(const sp<AMessage> &reply) {
     78     sp<AMessage> msg = new AMessage(kWhatDisconnect, this);
     79     msg->setMessage("reply", reply);
     80     msg->post();
     81 }
     82 
     83 void ARTSPConnection::sendRequest(
     84         const char *request, const sp<AMessage> &reply) {
     85     sp<AMessage> msg = new AMessage(kWhatSendRequest, this);
     86     msg->setString("request", request);
     87     msg->setMessage("reply", reply);
     88     msg->post();
     89 }
     90 
     91 void ARTSPConnection::observeBinaryData(const sp<AMessage> &reply) {
     92     sp<AMessage> msg = new AMessage(kWhatObserveBinaryData, this);
     93     msg->setMessage("reply", reply);
     94     msg->post();
     95 }
     96 
     97 void ARTSPConnection::onMessageReceived(const sp<AMessage> &msg) {
     98     switch (msg->what()) {
     99         case kWhatConnect:
    100             onConnect(msg);
    101             break;
    102 
    103         case kWhatDisconnect:
    104             onDisconnect(msg);
    105             break;
    106 
    107         case kWhatCompleteConnection:
    108             onCompleteConnection(msg);
    109             break;
    110 
    111         case kWhatSendRequest:
    112             onSendRequest(msg);
    113             break;
    114 
    115         case kWhatReceiveResponse:
    116             onReceiveResponse();
    117             break;
    118 
    119         case kWhatObserveBinaryData:
    120         {
    121             CHECK(msg->findMessage("reply", &mObserveBinaryMessage));
    122             break;
    123         }
    124 
    125         default:
    126             TRESPASS();
    127             break;
    128     }
    129 }
    130 
    131 // static
    132 bool ARTSPConnection::ParseURL(
    133         const char *url, AString *host, unsigned *port, AString *path,
    134         AString *user, AString *pass) {
    135     host->clear();
    136     *port = 0;
    137     path->clear();
    138     user->clear();
    139     pass->clear();
    140 
    141     if (strncasecmp("rtsp://", url, 7)) {
    142         return false;
    143     }
    144 
    145     const char *slashPos = strchr(&url[7], '/');
    146 
    147     if (slashPos == NULL) {
    148         host->setTo(&url[7]);
    149         path->setTo("/");
    150     } else {
    151         host->setTo(&url[7], slashPos - &url[7]);
    152         path->setTo(slashPos);
    153     }
    154 
    155     ssize_t atPos = host->find("@");
    156 
    157     if (atPos >= 0) {
    158         // Split of user:pass@ from hostname.
    159 
    160         AString userPass(*host, 0, atPos);
    161         host->erase(0, atPos + 1);
    162 
    163         ssize_t colonPos = userPass.find(":");
    164 
    165         if (colonPos < 0) {
    166             *user = userPass;
    167         } else {
    168             user->setTo(userPass, 0, colonPos);
    169             pass->setTo(userPass, colonPos + 1, userPass.size() - colonPos - 1);
    170         }
    171     }
    172 
    173     const char *colonPos = strchr(host->c_str(), ':');
    174 
    175     if (colonPos != NULL) {
    176         unsigned long x;
    177         if (!ParseSingleUnsignedLong(colonPos + 1, &x) || x >= 65536) {
    178             return false;
    179         }
    180 
    181         *port = x;
    182 
    183         size_t colonOffset = colonPos - host->c_str();
    184         size_t trailing = host->size() - colonOffset;
    185         host->erase(colonOffset, trailing);
    186     } else {
    187         *port = 554;
    188     }
    189 
    190     return true;
    191 }
    192 
    193 static status_t MakeSocketBlocking(int s, bool blocking) {
    194     // Make socket non-blocking.
    195     int flags = fcntl(s, F_GETFL, 0);
    196 
    197     if (flags == -1) {
    198         return UNKNOWN_ERROR;
    199     }
    200 
    201     if (blocking) {
    202         flags &= ~O_NONBLOCK;
    203     } else {
    204         flags |= O_NONBLOCK;
    205     }
    206 
    207     flags = fcntl(s, F_SETFL, flags);
    208 
    209     return flags == -1 ? UNKNOWN_ERROR : OK;
    210 }
    211 
    212 void ARTSPConnection::onConnect(const sp<AMessage> &msg) {
    213     ++mConnectionID;
    214 
    215     if (mState != DISCONNECTED) {
    216         if (mUIDValid) {
    217             HTTPBase::UnRegisterSocketUserTag(mSocket);
    218             HTTPBase::UnRegisterSocketUserMark(mSocket);
    219         }
    220         close(mSocket);
    221         mSocket = -1;
    222 
    223         flushPendingRequests();
    224     }
    225 
    226     mState = CONNECTING;
    227 
    228     AString url;
    229     CHECK(msg->findString("url", &url));
    230 
    231     sp<AMessage> reply;
    232     CHECK(msg->findMessage("reply", &reply));
    233 
    234     AString host, path;
    235     unsigned port;
    236     if (!ParseURL(url.c_str(), &host, &port, &path, &mUser, &mPass)
    237             || (mUser.size() > 0 && mPass.size() == 0)) {
    238         // If we have a user name but no password we have to give up
    239         // right here, since we currently have no way of asking the user
    240         // for this information.
    241 
    242         ALOGE("Malformed rtsp url %s", uriDebugString(url).c_str());
    243 
    244         reply->setInt32("result", ERROR_MALFORMED);
    245         reply->post();
    246 
    247         mState = DISCONNECTED;
    248         return;
    249     }
    250 
    251     if (mUser.size() > 0) {
    252         ALOGV("user = '%s', pass = '%s'", mUser.c_str(), mPass.c_str());
    253     }
    254 
    255     struct hostent *ent = gethostbyname(host.c_str());
    256     if (ent == NULL) {
    257         ALOGE("Unknown host %s", host.c_str());
    258 
    259         reply->setInt32("result", -ENOENT);
    260         reply->post();
    261 
    262         mState = DISCONNECTED;
    263         return;
    264     }
    265 
    266     mSocket = socket(AF_INET, SOCK_STREAM, 0);
    267 
    268     if (mUIDValid) {
    269         HTTPBase::RegisterSocketUserTag(mSocket, mUID,
    270                                         (uint32_t)*(uint32_t*) "RTSP");
    271         HTTPBase::RegisterSocketUserMark(mSocket, mUID);
    272     }
    273 
    274     MakeSocketBlocking(mSocket, false);
    275 
    276     struct sockaddr_in remote;
    277     memset(remote.sin_zero, 0, sizeof(remote.sin_zero));
    278     remote.sin_family = AF_INET;
    279     remote.sin_addr.s_addr = *(in_addr_t *)ent->h_addr;
    280     remote.sin_port = htons(port);
    281 
    282     int err = ::connect(
    283             mSocket, (const struct sockaddr *)&remote, sizeof(remote));
    284 
    285     reply->setInt32("server-ip", ntohl(remote.sin_addr.s_addr));
    286 
    287     if (err < 0) {
    288         if (errno == EINPROGRESS) {
    289             sp<AMessage> msg = new AMessage(kWhatCompleteConnection, this);
    290             msg->setMessage("reply", reply);
    291             msg->setInt32("connection-id", mConnectionID);
    292             msg->post();
    293             return;
    294         }
    295 
    296         reply->setInt32("result", -errno);
    297         mState = DISCONNECTED;
    298 
    299         if (mUIDValid) {
    300             HTTPBase::UnRegisterSocketUserTag(mSocket);
    301             HTTPBase::UnRegisterSocketUserMark(mSocket);
    302         }
    303         close(mSocket);
    304         mSocket = -1;
    305     } else {
    306         reply->setInt32("result", OK);
    307         mState = CONNECTED;
    308         mNextCSeq = 1;
    309 
    310         postReceiveReponseEvent();
    311     }
    312 
    313     reply->post();
    314 }
    315 
    316 void ARTSPConnection::performDisconnect() {
    317     if (mUIDValid) {
    318         HTTPBase::UnRegisterSocketUserTag(mSocket);
    319         HTTPBase::UnRegisterSocketUserMark(mSocket);
    320     }
    321     close(mSocket);
    322     mSocket = -1;
    323 
    324     flushPendingRequests();
    325 
    326     mUser.clear();
    327     mPass.clear();
    328     mAuthType = NONE;
    329     mNonce.clear();
    330 
    331     mState = DISCONNECTED;
    332 }
    333 
    334 void ARTSPConnection::onDisconnect(const sp<AMessage> &msg) {
    335     if (mState == CONNECTED || mState == CONNECTING) {
    336         performDisconnect();
    337     }
    338 
    339     sp<AMessage> reply;
    340     CHECK(msg->findMessage("reply", &reply));
    341 
    342     reply->setInt32("result", OK);
    343 
    344     reply->post();
    345 }
    346 
    347 void ARTSPConnection::onCompleteConnection(const sp<AMessage> &msg) {
    348     sp<AMessage> reply;
    349     CHECK(msg->findMessage("reply", &reply));
    350 
    351     int32_t connectionID;
    352     CHECK(msg->findInt32("connection-id", &connectionID));
    353 
    354     if ((connectionID != mConnectionID) || mState != CONNECTING) {
    355         // While we were attempting to connect, the attempt was
    356         // cancelled.
    357         reply->setInt32("result", -ECONNABORTED);
    358         reply->post();
    359         return;
    360     }
    361 
    362     struct timeval tv;
    363     tv.tv_sec = 0;
    364     tv.tv_usec = kSelectTimeoutUs;
    365 
    366     fd_set ws;
    367     FD_ZERO(&ws);
    368     FD_SET(mSocket, &ws);
    369 
    370     int res = select(mSocket + 1, NULL, &ws, NULL, &tv);
    371     CHECK_GE(res, 0);
    372 
    373     if (res == 0) {
    374         // Timed out. Not yet connected.
    375 
    376         msg->post();
    377         return;
    378     }
    379 
    380     int err;
    381     socklen_t optionLen = sizeof(err);
    382     CHECK_EQ(getsockopt(mSocket, SOL_SOCKET, SO_ERROR, &err, &optionLen), 0);
    383     CHECK_EQ(optionLen, (socklen_t)sizeof(err));
    384 
    385     if (err != 0) {
    386         ALOGE("err = %d (%s)", err, strerror(err));
    387 
    388         reply->setInt32("result", -err);
    389 
    390         mState = DISCONNECTED;
    391         if (mUIDValid) {
    392             HTTPBase::UnRegisterSocketUserTag(mSocket);
    393             HTTPBase::UnRegisterSocketUserMark(mSocket);
    394         }
    395         close(mSocket);
    396         mSocket = -1;
    397     } else {
    398         reply->setInt32("result", OK);
    399         mState = CONNECTED;
    400         mNextCSeq = 1;
    401 
    402         postReceiveReponseEvent();
    403     }
    404 
    405     reply->post();
    406 }
    407 
    408 void ARTSPConnection::onSendRequest(const sp<AMessage> &msg) {
    409     sp<AMessage> reply;
    410     CHECK(msg->findMessage("reply", &reply));
    411 
    412     if (mState != CONNECTED) {
    413         reply->setInt32("result", -ENOTCONN);
    414         reply->post();
    415         return;
    416     }
    417 
    418     AString request;
    419     CHECK(msg->findString("request", &request));
    420 
    421     // Just in case we need to re-issue the request with proper authentication
    422     // later, stash it away.
    423     reply->setString("original-request", request.c_str(), request.size());
    424 
    425     addAuthentication(&request);
    426     addUserAgent(&request);
    427 
    428     // Find the boundary between headers and the body.
    429     ssize_t i = request.find("\r\n\r\n");
    430     CHECK_GE(i, 0);
    431 
    432     int32_t cseq = mNextCSeq++;
    433 
    434     AString cseqHeader = "CSeq: ";
    435     cseqHeader.append(cseq);
    436     cseqHeader.append("\r\n");
    437 
    438     request.insert(cseqHeader, i + 2);
    439 
    440     ALOGV("request: '%s'", request.c_str());
    441 
    442     size_t numBytesSent = 0;
    443     while (numBytesSent < request.size()) {
    444         ssize_t n =
    445             send(mSocket, request.c_str() + numBytesSent,
    446                  request.size() - numBytesSent, 0);
    447 
    448         if (n < 0 && errno == EINTR) {
    449             continue;
    450         }
    451 
    452         if (n <= 0) {
    453             performDisconnect();
    454 
    455             if (n == 0) {
    456                 // Server closed the connection.
    457                 ALOGE("Server unexpectedly closed the connection.");
    458 
    459                 reply->setInt32("result", ERROR_IO);
    460                 reply->post();
    461             } else {
    462                 ALOGE("Error sending rtsp request. (%s)", strerror(errno));
    463                 reply->setInt32("result", -errno);
    464                 reply->post();
    465             }
    466 
    467             return;
    468         }
    469 
    470         numBytesSent += (size_t)n;
    471     }
    472 
    473     mPendingRequests.add(cseq, reply);
    474 }
    475 
    476 void ARTSPConnection::onReceiveResponse() {
    477     mReceiveResponseEventPending = false;
    478 
    479     if (mState != CONNECTED) {
    480         return;
    481     }
    482 
    483     struct timeval tv;
    484     tv.tv_sec = 0;
    485     tv.tv_usec = kSelectTimeoutUs;
    486 
    487     fd_set rs;
    488     FD_ZERO(&rs);
    489     FD_SET(mSocket, &rs);
    490 
    491     int res = select(mSocket + 1, &rs, NULL, NULL, &tv);
    492 
    493     if (res == 1) {
    494         MakeSocketBlocking(mSocket, true);
    495 
    496         bool success = receiveRTSPReponse();
    497 
    498         MakeSocketBlocking(mSocket, false);
    499 
    500         if (!success) {
    501             // Something horrible, irreparable has happened.
    502             flushPendingRequests();
    503             return;
    504         }
    505     }
    506 
    507     postReceiveReponseEvent();
    508 }
    509 
    510 void ARTSPConnection::flushPendingRequests() {
    511     for (size_t i = 0; i < mPendingRequests.size(); ++i) {
    512         sp<AMessage> reply = mPendingRequests.valueAt(i);
    513 
    514         reply->setInt32("result", -ECONNABORTED);
    515         reply->post();
    516     }
    517 
    518     mPendingRequests.clear();
    519 }
    520 
    521 void ARTSPConnection::postReceiveReponseEvent() {
    522     if (mReceiveResponseEventPending) {
    523         return;
    524     }
    525 
    526     sp<AMessage> msg = new AMessage(kWhatReceiveResponse, this);
    527     msg->post();
    528 
    529     mReceiveResponseEventPending = true;
    530 }
    531 
    532 status_t ARTSPConnection::receive(void *data, size_t size) {
    533     size_t offset = 0;
    534     while (offset < size) {
    535         ssize_t n = recv(mSocket, (uint8_t *)data + offset, size - offset, 0);
    536 
    537         if (n < 0 && errno == EINTR) {
    538             continue;
    539         }
    540 
    541         if (n <= 0) {
    542             performDisconnect();
    543 
    544             if (n == 0) {
    545                 // Server closed the connection.
    546                 ALOGE("Server unexpectedly closed the connection.");
    547                 return ERROR_IO;
    548             } else {
    549                 ALOGE("Error reading rtsp response. (%s)", strerror(errno));
    550                 return -errno;
    551             }
    552         }
    553 
    554         offset += (size_t)n;
    555     }
    556 
    557     return OK;
    558 }
    559 
    560 bool ARTSPConnection::receiveLine(AString *line) {
    561     line->clear();
    562 
    563     bool sawCR = false;
    564     for (;;) {
    565         char c;
    566         if (receive(&c, 1) != OK) {
    567             return false;
    568         }
    569 
    570         if (sawCR && c == '\n') {
    571             line->erase(line->size() - 1, 1);
    572             return true;
    573         } else if (c == '\n') {
    574             // some reponse line ended with '\n', instead of '\r\n'.
    575             return true;
    576         }
    577 
    578         line->append(&c, 1);
    579 
    580         if (c == '$' && line->size() == 1) {
    581             // Special-case for interleaved binary data.
    582             return true;
    583         }
    584 
    585         sawCR = (c == '\r');
    586     }
    587 }
    588 
    589 sp<ABuffer> ARTSPConnection::receiveBinaryData() {
    590     uint8_t x[3];
    591     if (receive(x, 3) != OK) {
    592         return NULL;
    593     }
    594 
    595     sp<ABuffer> buffer = new ABuffer((x[1] << 8) | x[2]);
    596     if (receive(buffer->data(), buffer->size()) != OK) {
    597         return NULL;
    598     }
    599 
    600     buffer->meta()->setInt32("index", (int32_t)x[0]);
    601 
    602     return buffer;
    603 }
    604 
    605 static bool IsRTSPVersion(const AString &s) {
    606     return s == "RTSP/1.0";
    607 }
    608 
    609 bool ARTSPConnection::receiveRTSPReponse() {
    610     AString statusLine;
    611 
    612     if (!receiveLine(&statusLine)) {
    613         return false;
    614     }
    615 
    616     if (statusLine == "$") {
    617         sp<ABuffer> buffer = receiveBinaryData();
    618 
    619         if (buffer == NULL) {
    620             return false;
    621         }
    622 
    623         if (mObserveBinaryMessage != NULL) {
    624             sp<AMessage> notify = mObserveBinaryMessage->dup();
    625             notify->setBuffer("buffer", buffer);
    626             notify->post();
    627         } else {
    628             ALOGW("received binary data, but no one cares.");
    629         }
    630 
    631         return true;
    632     }
    633 
    634     sp<ARTSPResponse> response = new ARTSPResponse;
    635     response->mStatusLine = statusLine;
    636 
    637     ALOGI("status: %s", response->mStatusLine.c_str());
    638 
    639     ssize_t space1 = response->mStatusLine.find(" ");
    640     if (space1 < 0) {
    641         return false;
    642     }
    643     ssize_t space2 = response->mStatusLine.find(" ", space1 + 1);
    644     if (space2 < 0) {
    645         return false;
    646     }
    647 
    648     bool isRequest = false;
    649 
    650     if (!IsRTSPVersion(AString(response->mStatusLine, 0, space1))) {
    651         CHECK(IsRTSPVersion(
    652                     AString(
    653                         response->mStatusLine,
    654                         space2 + 1,
    655                         response->mStatusLine.size() - space2 - 1)));
    656 
    657         isRequest = true;
    658 
    659         response->mStatusCode = 0;
    660     } else {
    661         AString statusCodeStr(
    662                 response->mStatusLine, space1 + 1, space2 - space1 - 1);
    663 
    664         if (!ParseSingleUnsignedLong(
    665                     statusCodeStr.c_str(), &response->mStatusCode)
    666                 || response->mStatusCode < 100 || response->mStatusCode > 999) {
    667             return false;
    668         }
    669     }
    670 
    671     AString line;
    672     ssize_t lastDictIndex = -1;
    673     for (;;) {
    674         if (!receiveLine(&line)) {
    675             break;
    676         }
    677 
    678         if (line.empty()) {
    679             break;
    680         }
    681 
    682         ALOGV("line: '%s'", line.c_str());
    683 
    684         if (line.c_str()[0] == ' ' || line.c_str()[0] == '\t') {
    685             // Support for folded header values.
    686 
    687             if (lastDictIndex < 0) {
    688                 // First line cannot be a continuation of the previous one.
    689                 return false;
    690             }
    691 
    692             AString &value = response->mHeaders.editValueAt(lastDictIndex);
    693             value.append(line);
    694 
    695             continue;
    696         }
    697 
    698         ssize_t colonPos = line.find(":");
    699         if (colonPos < 0) {
    700             // Malformed header line.
    701             return false;
    702         }
    703 
    704         AString key(line, 0, colonPos);
    705         key.trim();
    706         key.tolower();
    707 
    708         line.erase(0, colonPos + 1);
    709 
    710         lastDictIndex = response->mHeaders.add(key, line);
    711     }
    712 
    713     for (size_t i = 0; i < response->mHeaders.size(); ++i) {
    714         response->mHeaders.editValueAt(i).trim();
    715     }
    716 
    717     unsigned long contentLength = 0;
    718 
    719     ssize_t i = response->mHeaders.indexOfKey("content-length");
    720 
    721     if (i >= 0) {
    722         AString value = response->mHeaders.valueAt(i);
    723         if (!ParseSingleUnsignedLong(value.c_str(), &contentLength)) {
    724             return false;
    725         }
    726     }
    727 
    728     if (contentLength > 0) {
    729         response->mContent = new ABuffer(contentLength);
    730 
    731         if (receive(response->mContent->data(), contentLength) != OK) {
    732             return false;
    733         }
    734     }
    735 
    736     if (response->mStatusCode == 401) {
    737         if (mAuthType == NONE && mUser.size() > 0
    738                 && parseAuthMethod(response)) {
    739             ssize_t i;
    740             CHECK_EQ((status_t)OK, findPendingRequest(response, &i));
    741             CHECK_GE(i, 0);
    742 
    743             sp<AMessage> reply = mPendingRequests.valueAt(i);
    744             mPendingRequests.removeItemsAt(i);
    745 
    746             AString request;
    747             CHECK(reply->findString("original-request", &request));
    748 
    749             sp<AMessage> msg = new AMessage(kWhatSendRequest, this);
    750             msg->setMessage("reply", reply);
    751             msg->setString("request", request.c_str(), request.size());
    752 
    753             ALOGI("re-sending request with authentication headers...");
    754             onSendRequest(msg);
    755 
    756             return true;
    757         }
    758     }
    759 
    760     return isRequest
    761         ? handleServerRequest(response)
    762         : notifyResponseListener(response);
    763 }
    764 
    765 bool ARTSPConnection::handleServerRequest(const sp<ARTSPResponse> &request) {
    766     // Implementation of server->client requests is optional for all methods
    767     // but we do need to respond, even if it's just to say that we don't
    768     // support the method.
    769 
    770     ssize_t space1 = request->mStatusLine.find(" ");
    771     CHECK_GE(space1, 0);
    772 
    773     AString response;
    774     response.append("RTSP/1.0 501 Not Implemented\r\n");
    775 
    776     ssize_t i = request->mHeaders.indexOfKey("cseq");
    777 
    778     if (i >= 0) {
    779         AString value = request->mHeaders.valueAt(i);
    780 
    781         unsigned long cseq;
    782         if (!ParseSingleUnsignedLong(value.c_str(), &cseq)) {
    783             return false;
    784         }
    785 
    786         response.append("CSeq: ");
    787         response.append(cseq);
    788         response.append("\r\n");
    789     }
    790 
    791     response.append("\r\n");
    792 
    793     size_t numBytesSent = 0;
    794     while (numBytesSent < response.size()) {
    795         ssize_t n =
    796             send(mSocket, response.c_str() + numBytesSent,
    797                  response.size() - numBytesSent, 0);
    798 
    799         if (n < 0 && errno == EINTR) {
    800             continue;
    801         }
    802 
    803         if (n <= 0) {
    804             if (n == 0) {
    805                 // Server closed the connection.
    806                 ALOGE("Server unexpectedly closed the connection.");
    807             } else {
    808                 ALOGE("Error sending rtsp response (%s).", strerror(errno));
    809             }
    810 
    811             performDisconnect();
    812 
    813             return false;
    814         }
    815 
    816         numBytesSent += (size_t)n;
    817     }
    818 
    819     return true;
    820 }
    821 
    822 // static
    823 bool ARTSPConnection::ParseSingleUnsignedLong(
    824         const char *from, unsigned long *x) {
    825     char *end;
    826     *x = strtoul(from, &end, 10);
    827 
    828     if (end == from || *end != '\0') {
    829         return false;
    830     }
    831 
    832     return true;
    833 }
    834 
    835 status_t ARTSPConnection::findPendingRequest(
    836         const sp<ARTSPResponse> &response, ssize_t *index) const {
    837     *index = 0;
    838 
    839     ssize_t i = response->mHeaders.indexOfKey("cseq");
    840 
    841     if (i < 0) {
    842         // This is an unsolicited server->client message.
    843         *index = -1;
    844         return OK;
    845     }
    846 
    847     AString value = response->mHeaders.valueAt(i);
    848 
    849     unsigned long cseq;
    850     if (!ParseSingleUnsignedLong(value.c_str(), &cseq)) {
    851         return ERROR_MALFORMED;
    852     }
    853 
    854     i = mPendingRequests.indexOfKey(cseq);
    855 
    856     if (i < 0) {
    857         return -ENOENT;
    858     }
    859 
    860     *index = i;
    861 
    862     return OK;
    863 }
    864 
    865 bool ARTSPConnection::notifyResponseListener(
    866         const sp<ARTSPResponse> &response) {
    867     ssize_t i;
    868     status_t err = findPendingRequest(response, &i);
    869 
    870     if (err == OK && i < 0) {
    871         // An unsolicited server response is not a problem.
    872         return true;
    873     }
    874 
    875     if (err != OK) {
    876         return false;
    877     }
    878 
    879     sp<AMessage> reply = mPendingRequests.valueAt(i);
    880     mPendingRequests.removeItemsAt(i);
    881 
    882     reply->setInt32("result", OK);
    883     reply->setObject("response", response);
    884     reply->post();
    885 
    886     return true;
    887 }
    888 
    889 bool ARTSPConnection::parseAuthMethod(const sp<ARTSPResponse> &response) {
    890     ssize_t i = response->mHeaders.indexOfKey("www-authenticate");
    891 
    892     if (i < 0) {
    893         return false;
    894     }
    895 
    896     AString value = response->mHeaders.valueAt(i);
    897 
    898     if (!strncmp(value.c_str(), "Basic", 5)) {
    899         mAuthType = BASIC;
    900     } else {
    901 
    902         CHECK(!strncmp(value.c_str(), "Digest", 6));
    903         mAuthType = DIGEST;
    904 
    905         i = value.find("nonce=");
    906         CHECK_GE(i, 0);
    907         CHECK_EQ(value.c_str()[i + 6], '\"');
    908         ssize_t j = value.find("\"", i + 7);
    909         CHECK_GE(j, 0);
    910 
    911         mNonce.setTo(value, i + 7, j - i - 7);
    912     }
    913 
    914     return true;
    915 }
    916 
    917 static void H(const AString &s, AString *out) {
    918     out->clear();
    919 
    920     MD5_CTX m;
    921     MD5_Init(&m);
    922     MD5_Update(&m, s.c_str(), s.size());
    923 
    924     uint8_t key[16];
    925     MD5_Final(key, &m);
    926 
    927     for (size_t i = 0; i < 16; ++i) {
    928         char nibble = key[i] >> 4;
    929         if (nibble <= 9) {
    930             nibble += '0';
    931         } else {
    932             nibble += 'a' - 10;
    933         }
    934         out->append(&nibble, 1);
    935 
    936         nibble = key[i] & 0x0f;
    937         if (nibble <= 9) {
    938             nibble += '0';
    939         } else {
    940             nibble += 'a' - 10;
    941         }
    942         out->append(&nibble, 1);
    943     }
    944 }
    945 
    946 static void GetMethodAndURL(
    947         const AString &request, AString *method, AString *url) {
    948     ssize_t space1 = request.find(" ");
    949     CHECK_GE(space1, 0);
    950 
    951     ssize_t space2 = request.find(" ", space1 + 1);
    952     CHECK_GE(space2, 0);
    953 
    954     method->setTo(request, 0, space1);
    955     url->setTo(request, space1 + 1, space2 - space1);
    956 }
    957 
    958 void ARTSPConnection::addAuthentication(AString *request) {
    959     if (mAuthType == NONE) {
    960         return;
    961     }
    962 
    963     // Find the boundary between headers and the body.
    964     ssize_t i = request->find("\r\n\r\n");
    965     CHECK_GE(i, 0);
    966 
    967     if (mAuthType == BASIC) {
    968         AString tmp;
    969         tmp.append(mUser);
    970         tmp.append(":");
    971         tmp.append(mPass);
    972 
    973         AString out;
    974         encodeBase64(tmp.c_str(), tmp.size(), &out);
    975 
    976         AString fragment;
    977         fragment.append("Authorization: Basic ");
    978         fragment.append(out);
    979         fragment.append("\r\n");
    980 
    981         request->insert(fragment, i + 2);
    982 
    983         return;
    984     }
    985 
    986     CHECK_EQ((int)mAuthType, (int)DIGEST);
    987 
    988     AString method, url;
    989     GetMethodAndURL(*request, &method, &url);
    990 
    991     AString A1;
    992     A1.append(mUser);
    993     A1.append(":");
    994     A1.append("Streaming Server");
    995     A1.append(":");
    996     A1.append(mPass);
    997 
    998     AString A2;
    999     A2.append(method);
   1000     A2.append(":");
   1001     A2.append(url);
   1002 
   1003     AString HA1, HA2;
   1004     H(A1, &HA1);
   1005     H(A2, &HA2);
   1006 
   1007     AString tmp;
   1008     tmp.append(HA1);
   1009     tmp.append(":");
   1010     tmp.append(mNonce);
   1011     tmp.append(":");
   1012     tmp.append(HA2);
   1013 
   1014     AString digest;
   1015     H(tmp, &digest);
   1016 
   1017     AString fragment;
   1018     fragment.append("Authorization: Digest ");
   1019     fragment.append("nonce=\"");
   1020     fragment.append(mNonce);
   1021     fragment.append("\", ");
   1022     fragment.append("username=\"");
   1023     fragment.append(mUser);
   1024     fragment.append("\", ");
   1025     fragment.append("uri=\"");
   1026     fragment.append(url);
   1027     fragment.append("\", ");
   1028     fragment.append("response=\"");
   1029     fragment.append(digest);
   1030     fragment.append("\"");
   1031     fragment.append("\r\n");
   1032 
   1033     request->insert(fragment, i + 2);
   1034 }
   1035 
   1036 void ARTSPConnection::addUserAgent(AString *request) const {
   1037     // Find the boundary between headers and the body.
   1038     ssize_t i = request->find("\r\n\r\n");
   1039     CHECK_GE(i, 0);
   1040 
   1041     request->insert(sUserAgent, i + 2);
   1042 }
   1043 
   1044 }  // namespace android
   1045