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