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