1cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber/*
2cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber * Copyright (C) 2010 The Android Open Source Project
3cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber *
4cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
5cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber * you may not use this file except in compliance with the License.
6cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber * You may obtain a copy of the License at
7cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber *
8cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
9cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber *
10cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber * Unless required by applicable law or agreed to in writing, software
11cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
12cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber * See the License for the specific language governing permissions and
14cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber * limitations under the License.
15cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber */
16cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
176e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber//#define LOG_NDEBUG 0
186e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber#define LOG_TAG "ARTSPConnection"
196e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber#include <utils/Log.h>
206e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber
21cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include "ARTSPConnection.h"
22cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
23cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include <media/stagefright/foundation/ABuffer.h>
24cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include <media/stagefright/foundation/ADebug.h>
25cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include <media/stagefright/foundation/AMessage.h>
264579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber#include <media/stagefright/foundation/base64.h>
270792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber#include <media/stagefright/MediaErrors.h>
28cd77d4a1d38b7609a03f6826a1ff5fa7c98aa34fAndreas Huber#include <media/stagefright/Utils.h>
29cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
30cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include <arpa/inet.h>
31cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include <fcntl.h>
32cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include <netdb.h>
334579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber#include <openssl/md5.h>
34cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include <sys/socket.h>
35cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
361b86fe063badb5f28c467ade39be0f4008688947Andreas Huber#include "include/HTTPBase.h"
379b80c2bdb205bc143104f54d0743b6eedd67b14eAndreas Huber
38cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Hubernamespace android {
39cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
40cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber// static
41cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huberconst int64_t ARTSPConnection::kSelectTimeoutUs = 1000ll;
42cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
43cd77d4a1d38b7609a03f6826a1ff5fa7c98aa34fAndreas Huber// static
44cd77d4a1d38b7609a03f6826a1ff5fa7c98aa34fAndreas Huberconst AString ARTSPConnection::sUserAgent =
45a1e8944a21e5833b7aadc451776f11797f5f9273Elliott Hughes    AStringPrintf("User-Agent: %s\r\n", MakeUserAgent().c_str());
46cd77d4a1d38b7609a03f6826a1ff5fa7c98aa34fAndreas Huber
479b80c2bdb205bc143104f54d0743b6eedd67b14eAndreas HuberARTSPConnection::ARTSPConnection(bool uidValid, uid_t uid)
489b80c2bdb205bc143104f54d0743b6eedd67b14eAndreas Huber    : mUIDValid(uidValid),
499b80c2bdb205bc143104f54d0743b6eedd67b14eAndreas Huber      mUID(uid),
509b80c2bdb205bc143104f54d0743b6eedd67b14eAndreas Huber      mState(DISCONNECTED),
514579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber      mAuthType(NONE),
52cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber      mSocket(-1),
53cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber      mConnectionID(0),
54cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber      mNextCSeq(0),
55cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber      mReceiveResponseEventPending(false) {
56cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber}
57cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
58cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas HuberARTSPConnection::~ARTSPConnection() {
59cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    if (mSocket >= 0) {
6029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Connection is still open, closing the socket.");
61a23456b306f35b9ecf973bf5818ca39295e9e029Ashish Sharma        if (mUIDValid) {
62a23456b306f35b9ecf973bf5818ca39295e9e029Ashish Sharma            HTTPBase::UnRegisterSocketUserTag(mSocket);
635908f88a7e45380a9b0d71a3b1ea535d76c420b3Chad Brubaker            HTTPBase::UnRegisterSocketUserMark(mSocket);
64a23456b306f35b9ecf973bf5818ca39295e9e029Ashish Sharma        }
65cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        close(mSocket);
66cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        mSocket = -1;
67cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
68cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber}
69cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
70cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Hubervoid ARTSPConnection::connect(const char *url, const sp<AMessage> &reply) {
711d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatConnect, this);
72cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    msg->setString("url", url);
73cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    msg->setMessage("reply", reply);
74cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    msg->post();
75cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber}
76cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
77cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Hubervoid ARTSPConnection::disconnect(const sp<AMessage> &reply) {
781d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatDisconnect, this);
79cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    msg->setMessage("reply", reply);
80cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    msg->post();
81cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber}
82cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
83cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Hubervoid ARTSPConnection::sendRequest(
84cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        const char *request, const sp<AMessage> &reply) {
851d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatSendRequest, this);
86cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    msg->setString("request", request);
87cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    msg->setMessage("reply", reply);
88cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    msg->post();
89cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber}
90cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
910792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Hubervoid ARTSPConnection::observeBinaryData(const sp<AMessage> &reply) {
921d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatObserveBinaryData, this);
930792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber    msg->setMessage("reply", reply);
940792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber    msg->post();
950792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber}
960792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber
97cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Hubervoid ARTSPConnection::onMessageReceived(const sp<AMessage> &msg) {
98cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    switch (msg->what()) {
99cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        case kWhatConnect:
100cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            onConnect(msg);
101cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            break;
102cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
103cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        case kWhatDisconnect:
104cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            onDisconnect(msg);
105cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            break;
106cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
107cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        case kWhatCompleteConnection:
108cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            onCompleteConnection(msg);
109cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            break;
110cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
111cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        case kWhatSendRequest:
112cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            onSendRequest(msg);
113cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            break;
114cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
115cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        case kWhatReceiveResponse:
116cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            onReceiveResponse();
117cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            break;
118cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
1190792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber        case kWhatObserveBinaryData:
1200792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber        {
1210792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber            CHECK(msg->findMessage("reply", &mObserveBinaryMessage));
1220792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber            break;
1230792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber        }
1240792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber
125cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        default:
126cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            TRESPASS();
127cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            break;
128cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
129cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber}
130cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
131cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber// static
132cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huberbool ARTSPConnection::ParseURL(
1334579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        const char *url, AString *host, unsigned *port, AString *path,
1344579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        AString *user, AString *pass) {
135cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    host->clear();
136cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    *port = 0;
137cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    path->clear();
1384579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    user->clear();
1394579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    pass->clear();
140cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
141cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    if (strncasecmp("rtsp://", url, 7)) {
142cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        return false;
143cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
144cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
145cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    const char *slashPos = strchr(&url[7], '/');
146cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
147cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    if (slashPos == NULL) {
148cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        host->setTo(&url[7]);
149cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        path->setTo("/");
150cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    } else {
151cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        host->setTo(&url[7], slashPos - &url[7]);
152cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        path->setTo(slashPos);
153cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
154cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
1554579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    ssize_t atPos = host->find("@");
1564579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
1574579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    if (atPos >= 0) {
1584579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        // Split of user:pass@ from hostname.
1594579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
1604579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        AString userPass(*host, 0, atPos);
1614579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        host->erase(0, atPos + 1);
1624579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
1634579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        ssize_t colonPos = userPass.find(":");
1644579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
1654579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        if (colonPos < 0) {
1664579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber            *user = userPass;
1674579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        } else {
1684579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber            user->setTo(userPass, 0, colonPos);
1694579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber            pass->setTo(userPass, colonPos + 1, userPass.size() - colonPos - 1);
1704579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        }
1714579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    }
1724579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
1734e2ffa400b82559cab2c5717c8dcdff393d334a9Mike Lockwood    const char *colonPos = strchr(host->c_str(), ':');
174cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
175cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    if (colonPos != NULL) {
176cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        unsigned long x;
177cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        if (!ParseSingleUnsignedLong(colonPos + 1, &x) || x >= 65536) {
178cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            return false;
179cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        }
180cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
181cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        *port = x;
182cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
183cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        size_t colonOffset = colonPos - host->c_str();
184cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        size_t trailing = host->size() - colonOffset;
185cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        host->erase(colonOffset, trailing);
186cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    } else {
187cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        *port = 554;
188cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
189cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
190cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    return true;
191cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber}
192cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
1930fbe0577cfeda28bd016110e670708cce0752044Andreas Huberstatic status_t MakeSocketBlocking(int s, bool blocking) {
194ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber    // Make socket non-blocking.
195ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber    int flags = fcntl(s, F_GETFL, 0);
1960fbe0577cfeda28bd016110e670708cce0752044Andreas Huber
1970fbe0577cfeda28bd016110e670708cce0752044Andreas Huber    if (flags == -1) {
1980fbe0577cfeda28bd016110e670708cce0752044Andreas Huber        return UNKNOWN_ERROR;
1990fbe0577cfeda28bd016110e670708cce0752044Andreas Huber    }
200ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber
201ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber    if (blocking) {
202ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber        flags &= ~O_NONBLOCK;
203ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber    } else {
204ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber        flags |= O_NONBLOCK;
205ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber    }
206ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber
2070fbe0577cfeda28bd016110e670708cce0752044Andreas Huber    flags = fcntl(s, F_SETFL, flags);
2080fbe0577cfeda28bd016110e670708cce0752044Andreas Huber
2090fbe0577cfeda28bd016110e670708cce0752044Andreas Huber    return flags == -1 ? UNKNOWN_ERROR : OK;
210ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber}
211ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber
212cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Hubervoid ARTSPConnection::onConnect(const sp<AMessage> &msg) {
213cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    ++mConnectionID;
214cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
215cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    if (mState != DISCONNECTED) {
216a23456b306f35b9ecf973bf5818ca39295e9e029Ashish Sharma        if (mUIDValid) {
217a23456b306f35b9ecf973bf5818ca39295e9e029Ashish Sharma            HTTPBase::UnRegisterSocketUserTag(mSocket);
2185908f88a7e45380a9b0d71a3b1ea535d76c420b3Chad Brubaker            HTTPBase::UnRegisterSocketUserMark(mSocket);
219a23456b306f35b9ecf973bf5818ca39295e9e029Ashish Sharma        }
220cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        close(mSocket);
221cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        mSocket = -1;
222cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
223cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        flushPendingRequests();
224cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
225cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
226cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    mState = CONNECTING;
227cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
228cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    AString url;
229cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    CHECK(msg->findString("url", &url));
230cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
2316f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber    sp<AMessage> reply;
2326f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber    CHECK(msg->findMessage("reply", &reply));
2336f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber
234cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    AString host, path;
235cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    unsigned port;
2364579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    if (!ParseURL(url.c_str(), &host, &port, &path, &mUser, &mPass)
2374579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber            || (mUser.size() > 0 && mPass.size() == 0)) {
2384579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        // If we have a user name but no password we have to give up
2394579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        // right here, since we currently have no way of asking the user
2404579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        // for this information.
2414579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
242a1df816c0677185534babba6ffc29970b048e52eLajos Molnar        ALOGE("Malformed rtsp url %s", uriDebugString(url).c_str());
2436f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber
2446f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber        reply->setInt32("result", ERROR_MALFORMED);
2456f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber        reply->post();
2466f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber
2476f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber        mState = DISCONNECTED;
2486f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber        return;
2496f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber    }
250cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
2514579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    if (mUser.size() > 0) {
2523856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("user = '%s', pass = '%s'", mUser.c_str(), mPass.c_str());
2534579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    }
2544579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
255cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    struct hostent *ent = gethostbyname(host.c_str());
2566f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber    if (ent == NULL) {
25729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Unknown host %s", host.c_str());
2586f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber
2596f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber        reply->setInt32("result", -ENOENT);
2606f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber        reply->post();
2616f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber
2626f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber        mState = DISCONNECTED;
2636f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber        return;
2646f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber    }
2656f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber
2666f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber    mSocket = socket(AF_INET, SOCK_STREAM, 0);
2676f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber
2689b80c2bdb205bc143104f54d0743b6eedd67b14eAndreas Huber    if (mUIDValid) {
269a23456b306f35b9ecf973bf5818ca39295e9e029Ashish Sharma        HTTPBase::RegisterSocketUserTag(mSocket, mUID,
270a23456b306f35b9ecf973bf5818ca39295e9e029Ashish Sharma                                        (uint32_t)*(uint32_t*) "RTSP");
2715908f88a7e45380a9b0d71a3b1ea535d76c420b3Chad Brubaker        HTTPBase::RegisterSocketUserMark(mSocket, mUID);
2729b80c2bdb205bc143104f54d0743b6eedd67b14eAndreas Huber    }
2739b80c2bdb205bc143104f54d0743b6eedd67b14eAndreas Huber
2746f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber    MakeSocketBlocking(mSocket, false);
275cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
276cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    struct sockaddr_in remote;
277cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    memset(remote.sin_zero, 0, sizeof(remote.sin_zero));
278cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    remote.sin_family = AF_INET;
279cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    remote.sin_addr.s_addr = *(in_addr_t *)ent->h_addr;
280cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    remote.sin_port = htons(port);
281cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
282cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    int err = ::connect(
283cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            mSocket, (const struct sockaddr *)&remote, sizeof(remote));
284cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
285cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    reply->setInt32("server-ip", ntohl(remote.sin_addr.s_addr));
286cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
287cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    if (err < 0) {
288cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        if (errno == EINPROGRESS) {
2891d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar            sp<AMessage> msg = new AMessage(kWhatCompleteConnection, this);
290cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            msg->setMessage("reply", reply);
291cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            msg->setInt32("connection-id", mConnectionID);
292cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            msg->post();
293cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            return;
294cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        }
295cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
296cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        reply->setInt32("result", -errno);
297cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        mState = DISCONNECTED;
298cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
299a23456b306f35b9ecf973bf5818ca39295e9e029Ashish Sharma        if (mUIDValid) {
300a23456b306f35b9ecf973bf5818ca39295e9e029Ashish Sharma            HTTPBase::UnRegisterSocketUserTag(mSocket);
3015908f88a7e45380a9b0d71a3b1ea535d76c420b3Chad Brubaker            HTTPBase::UnRegisterSocketUserMark(mSocket);
302a23456b306f35b9ecf973bf5818ca39295e9e029Ashish Sharma        }
303cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        close(mSocket);
304cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        mSocket = -1;
305cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    } else {
306cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        reply->setInt32("result", OK);
307cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        mState = CONNECTED;
308cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        mNextCSeq = 1;
309cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
310cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        postReceiveReponseEvent();
311cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
312cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
313cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    reply->post();
314cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber}
315cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
3160fbe0577cfeda28bd016110e670708cce0752044Andreas Hubervoid ARTSPConnection::performDisconnect() {
3170fbe0577cfeda28bd016110e670708cce0752044Andreas Huber    if (mUIDValid) {
3180fbe0577cfeda28bd016110e670708cce0752044Andreas Huber        HTTPBase::UnRegisterSocketUserTag(mSocket);
3195908f88a7e45380a9b0d71a3b1ea535d76c420b3Chad Brubaker        HTTPBase::UnRegisterSocketUserMark(mSocket);
3200fbe0577cfeda28bd016110e670708cce0752044Andreas Huber    }
3210fbe0577cfeda28bd016110e670708cce0752044Andreas Huber    close(mSocket);
3220fbe0577cfeda28bd016110e670708cce0752044Andreas Huber    mSocket = -1;
3230fbe0577cfeda28bd016110e670708cce0752044Andreas Huber
3240fbe0577cfeda28bd016110e670708cce0752044Andreas Huber    flushPendingRequests();
3250fbe0577cfeda28bd016110e670708cce0752044Andreas Huber
3260fbe0577cfeda28bd016110e670708cce0752044Andreas Huber    mUser.clear();
3270fbe0577cfeda28bd016110e670708cce0752044Andreas Huber    mPass.clear();
3280fbe0577cfeda28bd016110e670708cce0752044Andreas Huber    mAuthType = NONE;
3290fbe0577cfeda28bd016110e670708cce0752044Andreas Huber    mNonce.clear();
3300fbe0577cfeda28bd016110e670708cce0752044Andreas Huber
3310fbe0577cfeda28bd016110e670708cce0752044Andreas Huber    mState = DISCONNECTED;
3320fbe0577cfeda28bd016110e670708cce0752044Andreas Huber}
3330fbe0577cfeda28bd016110e670708cce0752044Andreas Huber
334cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Hubervoid ARTSPConnection::onDisconnect(const sp<AMessage> &msg) {
335cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    if (mState == CONNECTED || mState == CONNECTING) {
3360fbe0577cfeda28bd016110e670708cce0752044Andreas Huber        performDisconnect();
337ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber    }
338cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
339cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    sp<AMessage> reply;
340cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    CHECK(msg->findMessage("reply", &reply));
341cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
342cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    reply->setInt32("result", OK);
3434579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
344cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    reply->post();
345cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber}
346cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
347cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Hubervoid ARTSPConnection::onCompleteConnection(const sp<AMessage> &msg) {
348cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    sp<AMessage> reply;
349cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    CHECK(msg->findMessage("reply", &reply));
350cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
351cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    int32_t connectionID;
352cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    CHECK(msg->findInt32("connection-id", &connectionID));
353cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
354cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    if ((connectionID != mConnectionID) || mState != CONNECTING) {
355cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        // While we were attempting to connect, the attempt was
356cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        // cancelled.
357cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        reply->setInt32("result", -ECONNABORTED);
358cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        reply->post();
359cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        return;
360cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
361cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
362cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    struct timeval tv;
363cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    tv.tv_sec = 0;
364cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    tv.tv_usec = kSelectTimeoutUs;
365cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
366cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    fd_set ws;
367cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    FD_ZERO(&ws);
368cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    FD_SET(mSocket, &ws);
369cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
370cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    int res = select(mSocket + 1, NULL, &ws, NULL, &tv);
371cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    CHECK_GE(res, 0);
372cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
373cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    if (res == 0) {
374cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        // Timed out. Not yet connected.
375cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
376cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        msg->post();
377cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        return;
378cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
379cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
380cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    int err;
381cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    socklen_t optionLen = sizeof(err);
382cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    CHECK_EQ(getsockopt(mSocket, SOL_SOCKET, SO_ERROR, &err, &optionLen), 0);
383cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    CHECK_EQ(optionLen, (socklen_t)sizeof(err));
384cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
385cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    if (err != 0) {
38629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("err = %d (%s)", err, strerror(err));
387cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
388cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        reply->setInt32("result", -err);
389cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
390cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        mState = DISCONNECTED;
391a23456b306f35b9ecf973bf5818ca39295e9e029Ashish Sharma        if (mUIDValid) {
392a23456b306f35b9ecf973bf5818ca39295e9e029Ashish Sharma            HTTPBase::UnRegisterSocketUserTag(mSocket);
3935908f88a7e45380a9b0d71a3b1ea535d76c420b3Chad Brubaker            HTTPBase::UnRegisterSocketUserMark(mSocket);
394a23456b306f35b9ecf973bf5818ca39295e9e029Ashish Sharma        }
395cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        close(mSocket);
396cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        mSocket = -1;
397cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    } else {
398cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        reply->setInt32("result", OK);
399cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        mState = CONNECTED;
400cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        mNextCSeq = 1;
401cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
402cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        postReceiveReponseEvent();
403cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
404cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
405cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    reply->post();
406cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber}
407cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
408cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Hubervoid ARTSPConnection::onSendRequest(const sp<AMessage> &msg) {
409cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    sp<AMessage> reply;
410cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    CHECK(msg->findMessage("reply", &reply));
411cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
412cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    if (mState != CONNECTED) {
413cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        reply->setInt32("result", -ENOTCONN);
414cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        reply->post();
415cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        return;
416cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
417cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
418cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    AString request;
419cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    CHECK(msg->findString("request", &request));
420cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
4214579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    // Just in case we need to re-issue the request with proper authentication
4224579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    // later, stash it away.
4234579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    reply->setString("original-request", request.c_str(), request.size());
4244579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
4254579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    addAuthentication(&request);
426e681b91c27439907f216cb6c88426929bc5194bfAndreas Huber    addUserAgent(&request);
4274579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
428cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    // Find the boundary between headers and the body.
429cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    ssize_t i = request.find("\r\n\r\n");
430cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    CHECK_GE(i, 0);
431cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
432cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    int32_t cseq = mNextCSeq++;
433cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
434cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    AString cseqHeader = "CSeq: ";
435cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    cseqHeader.append(cseq);
436cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    cseqHeader.append("\r\n");
437cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
438cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    request.insert(cseqHeader, i + 2);
439cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
4403856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("request: '%s'", request.c_str());
441cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
442cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    size_t numBytesSent = 0;
443cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    while (numBytesSent < request.size()) {
444cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        ssize_t n =
445cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            send(mSocket, request.c_str() + numBytesSent,
446cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                 request.size() - numBytesSent, 0);
447cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
4480fbe0577cfeda28bd016110e670708cce0752044Andreas Huber        if (n < 0 && errno == EINTR) {
4490fbe0577cfeda28bd016110e670708cce0752044Andreas Huber            continue;
4500fbe0577cfeda28bd016110e670708cce0752044Andreas Huber        }
4516f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber
4520fbe0577cfeda28bd016110e670708cce0752044Andreas Huber        if (n <= 0) {
4530fbe0577cfeda28bd016110e670708cce0752044Andreas Huber            performDisconnect();
4540fbe0577cfeda28bd016110e670708cce0752044Andreas Huber
4550fbe0577cfeda28bd016110e670708cce0752044Andreas Huber            if (n == 0) {
4560fbe0577cfeda28bd016110e670708cce0752044Andreas Huber                // Server closed the connection.
45729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("Server unexpectedly closed the connection.");
4580fbe0577cfeda28bd016110e670708cce0752044Andreas Huber
4590fbe0577cfeda28bd016110e670708cce0752044Andreas Huber                reply->setInt32("result", ERROR_IO);
4600fbe0577cfeda28bd016110e670708cce0752044Andreas Huber                reply->post();
4610fbe0577cfeda28bd016110e670708cce0752044Andreas Huber            } else {
46229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("Error sending rtsp request. (%s)", strerror(errno));
4630fbe0577cfeda28bd016110e670708cce0752044Andreas Huber                reply->setInt32("result", -errno);
4640fbe0577cfeda28bd016110e670708cce0752044Andreas Huber                reply->post();
465cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            }
466cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
4676f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber            return;
468cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        }
469cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
470cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        numBytesSent += (size_t)n;
471cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
472cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
473cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    mPendingRequests.add(cseq, reply);
474cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber}
475cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
476cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Hubervoid ARTSPConnection::onReceiveResponse() {
477cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    mReceiveResponseEventPending = false;
478cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
479cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    if (mState != CONNECTED) {
480cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        return;
481cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
482cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
483cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    struct timeval tv;
484cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    tv.tv_sec = 0;
485cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    tv.tv_usec = kSelectTimeoutUs;
486cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
487cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    fd_set rs;
488cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    FD_ZERO(&rs);
489cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    FD_SET(mSocket, &rs);
490cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
491cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    int res = select(mSocket + 1, &rs, NULL, NULL, &tv);
492cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
493cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    if (res == 1) {
494ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber        MakeSocketBlocking(mSocket, true);
495ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber
496ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber        bool success = receiveRTSPReponse();
497ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber
498ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber        MakeSocketBlocking(mSocket, false);
499ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber
500ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber        if (!success) {
501cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            // Something horrible, irreparable has happened.
502cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            flushPendingRequests();
503cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            return;
504cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        }
505cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
506cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
507cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    postReceiveReponseEvent();
508cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber}
509cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
510cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Hubervoid ARTSPConnection::flushPendingRequests() {
511cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    for (size_t i = 0; i < mPendingRequests.size(); ++i) {
512cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        sp<AMessage> reply = mPendingRequests.valueAt(i);
513cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
514cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        reply->setInt32("result", -ECONNABORTED);
515cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        reply->post();
516cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
517cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
518cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    mPendingRequests.clear();
519cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber}
520cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
521cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Hubervoid ARTSPConnection::postReceiveReponseEvent() {
522cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    if (mReceiveResponseEventPending) {
523cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        return;
524cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
525cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
5261d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatReceiveResponse, this);
527cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    msg->post();
528cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
529cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    mReceiveResponseEventPending = true;
530cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber}
531cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
5320792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huberstatus_t ARTSPConnection::receive(void *data, size_t size) {
5330792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber    size_t offset = 0;
5340792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber    while (offset < size) {
5350792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber        ssize_t n = recv(mSocket, (uint8_t *)data + offset, size - offset, 0);
536cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
5370fbe0577cfeda28bd016110e670708cce0752044Andreas Huber        if (n < 0 && errno == EINTR) {
5380fbe0577cfeda28bd016110e670708cce0752044Andreas Huber            continue;
5390fbe0577cfeda28bd016110e670708cce0752044Andreas Huber        }
5400fbe0577cfeda28bd016110e670708cce0752044Andreas Huber
5410fbe0577cfeda28bd016110e670708cce0752044Andreas Huber        if (n <= 0) {
5420fbe0577cfeda28bd016110e670708cce0752044Andreas Huber            performDisconnect();
5430fbe0577cfeda28bd016110e670708cce0752044Andreas Huber
5440fbe0577cfeda28bd016110e670708cce0752044Andreas Huber            if (n == 0) {
5450fbe0577cfeda28bd016110e670708cce0752044Andreas Huber                // Server closed the connection.
54629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("Server unexpectedly closed the connection.");
5470fbe0577cfeda28bd016110e670708cce0752044Andreas Huber                return ERROR_IO;
5480fbe0577cfeda28bd016110e670708cce0752044Andreas Huber            } else {
54929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("Error reading rtsp response. (%s)", strerror(errno));
5500fbe0577cfeda28bd016110e670708cce0752044Andreas Huber                return -errno;
5510fbe0577cfeda28bd016110e670708cce0752044Andreas Huber            }
552cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        }
553cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
5540792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber        offset += (size_t)n;
5550792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber    }
5560792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber
5570792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber    return OK;
5580792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber}
5590792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber
5600792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huberbool ARTSPConnection::receiveLine(AString *line) {
5610792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber    line->clear();
5620792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber
5630792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber    bool sawCR = false;
5640792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber    for (;;) {
5650792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber        char c;
5660792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber        if (receive(&c, 1) != OK) {
5670792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber            return false;
5680792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber        }
5690792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber
570cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        if (sawCR && c == '\n') {
571cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            line->erase(line->size() - 1, 1);
572cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            return true;
5733e3af91f70b20623fa5f3845f26260235c0b212dYajun Zeng        } else if (c == '\n') {
5743e3af91f70b20623fa5f3845f26260235c0b212dYajun Zeng            // some reponse line ended with '\n', instead of '\r\n'.
5753e3af91f70b20623fa5f3845f26260235c0b212dYajun Zeng            return true;
576cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        }
577cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
578cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        line->append(&c, 1);
579cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
5800792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber        if (c == '$' && line->size() == 1) {
5810792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber            // Special-case for interleaved binary data.
5820792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber            return true;
5830792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber        }
5840792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber
585cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        sawCR = (c == '\r');
586cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
587cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber}
588cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
5890792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Hubersp<ABuffer> ARTSPConnection::receiveBinaryData() {
5900792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber    uint8_t x[3];
5910792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber    if (receive(x, 3) != OK) {
5920792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber        return NULL;
5930792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber    }
5940792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber
5950792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber    sp<ABuffer> buffer = new ABuffer((x[1] << 8) | x[2]);
5960792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber    if (receive(buffer->data(), buffer->size()) != OK) {
5970792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber        return NULL;
5980792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber    }
5990792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber
6000792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber    buffer->meta()->setInt32("index", (int32_t)x[0]);
6010792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber
6020792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber    return buffer;
6030792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber}
6040792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber
6055ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huberstatic bool IsRTSPVersion(const AString &s) {
6065ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber    return s == "RTSP/1.0";
6075ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber}
6085ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber
609cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huberbool ARTSPConnection::receiveRTSPReponse() {
6100792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber    AString statusLine;
611cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
6120792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber    if (!receiveLine(&statusLine)) {
613cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        return false;
614cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
615cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
6160792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber    if (statusLine == "$") {
6170792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber        sp<ABuffer> buffer = receiveBinaryData();
6180792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber
6190792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber        if (buffer == NULL) {
6200792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber            return false;
6210792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber        }
6220792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber
6230792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber        if (mObserveBinaryMessage != NULL) {
6240792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber            sp<AMessage> notify = mObserveBinaryMessage->dup();
6252d8bedd05437b6fccdbc6bf70f673ffd86744d59Andreas Huber            notify->setBuffer("buffer", buffer);
6260792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber            notify->post();
6270792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber        } else {
6285ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block            ALOGW("received binary data, but no one cares.");
6290792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber        }
6300792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber
6310792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber        return true;
6320792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber    }
6330792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber
6340792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber    sp<ARTSPResponse> response = new ARTSPResponse;
6350792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber    response->mStatusLine = statusLine;
6360792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber
637df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block    ALOGI("status: %s", response->mStatusLine.c_str());
638cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
639cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    ssize_t space1 = response->mStatusLine.find(" ");
640cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    if (space1 < 0) {
641cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        return false;
642cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
643cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    ssize_t space2 = response->mStatusLine.find(" ", space1 + 1);
644cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    if (space2 < 0) {
645cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        return false;
646cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
647cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
6485ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber    bool isRequest = false;
649cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
6505ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber    if (!IsRTSPVersion(AString(response->mStatusLine, 0, space1))) {
6515ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber        CHECK(IsRTSPVersion(
6525ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber                    AString(
6535ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber                        response->mStatusLine,
6545ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber                        space2 + 1,
6555ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber                        response->mStatusLine.size() - space2 - 1)));
6565ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber
6575ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber        isRequest = true;
6585ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber
6595ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber        response->mStatusCode = 0;
6605ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber    } else {
6615ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber        AString statusCodeStr(
6625ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber                response->mStatusLine, space1 + 1, space2 - space1 - 1);
6635ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber
6645ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber        if (!ParseSingleUnsignedLong(
6655ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber                    statusCodeStr.c_str(), &response->mStatusCode)
6665ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber                || response->mStatusCode < 100 || response->mStatusCode > 999) {
6675ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber            return false;
6685ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber        }
669cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
670cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
671cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    AString line;
6724aae77cbe1bf4369910314a55c2bc2349af10d3cAndreas Huber    ssize_t lastDictIndex = -1;
673cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    for (;;) {
674cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        if (!receiveLine(&line)) {
675cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            break;
676cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        }
677cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
678cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        if (line.empty()) {
679cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            break;
680cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        }
681cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
6824aae77cbe1bf4369910314a55c2bc2349af10d3cAndreas Huber        ALOGV("line: '%s'", line.c_str());
6834aae77cbe1bf4369910314a55c2bc2349af10d3cAndreas Huber
6844aae77cbe1bf4369910314a55c2bc2349af10d3cAndreas Huber        if (line.c_str()[0] == ' ' || line.c_str()[0] == '\t') {
6854aae77cbe1bf4369910314a55c2bc2349af10d3cAndreas Huber            // Support for folded header values.
6864aae77cbe1bf4369910314a55c2bc2349af10d3cAndreas Huber
6874aae77cbe1bf4369910314a55c2bc2349af10d3cAndreas Huber            if (lastDictIndex < 0) {
6884aae77cbe1bf4369910314a55c2bc2349af10d3cAndreas Huber                // First line cannot be a continuation of the previous one.
6894aae77cbe1bf4369910314a55c2bc2349af10d3cAndreas Huber                return false;
6904aae77cbe1bf4369910314a55c2bc2349af10d3cAndreas Huber            }
6914aae77cbe1bf4369910314a55c2bc2349af10d3cAndreas Huber
6924aae77cbe1bf4369910314a55c2bc2349af10d3cAndreas Huber            AString &value = response->mHeaders.editValueAt(lastDictIndex);
6934aae77cbe1bf4369910314a55c2bc2349af10d3cAndreas Huber            value.append(line);
6944aae77cbe1bf4369910314a55c2bc2349af10d3cAndreas Huber
6954aae77cbe1bf4369910314a55c2bc2349af10d3cAndreas Huber            continue;
6964aae77cbe1bf4369910314a55c2bc2349af10d3cAndreas Huber        }
697cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
698cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        ssize_t colonPos = line.find(":");
699cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        if (colonPos < 0) {
700cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            // Malformed header line.
701cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            return false;
702cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        }
703cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
704cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        AString key(line, 0, colonPos);
705cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        key.trim();
706cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        key.tolower();
707cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
708cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        line.erase(0, colonPos + 1);
709cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
7104aae77cbe1bf4369910314a55c2bc2349af10d3cAndreas Huber        lastDictIndex = response->mHeaders.add(key, line);
7114aae77cbe1bf4369910314a55c2bc2349af10d3cAndreas Huber    }
7124aae77cbe1bf4369910314a55c2bc2349af10d3cAndreas Huber
7134aae77cbe1bf4369910314a55c2bc2349af10d3cAndreas Huber    for (size_t i = 0; i < response->mHeaders.size(); ++i) {
7144aae77cbe1bf4369910314a55c2bc2349af10d3cAndreas Huber        response->mHeaders.editValueAt(i).trim();
715cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
716cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
717cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    unsigned long contentLength = 0;
718cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
719cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    ssize_t i = response->mHeaders.indexOfKey("content-length");
720cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
721cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    if (i >= 0) {
722cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        AString value = response->mHeaders.valueAt(i);
723cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        if (!ParseSingleUnsignedLong(value.c_str(), &contentLength)) {
724cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            return false;
725cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        }
726cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
727cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
728cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    if (contentLength > 0) {
729cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        response->mContent = new ABuffer(contentLength);
730cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
7310fbe0577cfeda28bd016110e670708cce0752044Andreas Huber        if (receive(response->mContent->data(), contentLength) != OK) {
7320fbe0577cfeda28bd016110e670708cce0752044Andreas Huber            return false;
733cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        }
734cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
735cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
7364579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    if (response->mStatusCode == 401) {
7374579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        if (mAuthType == NONE && mUser.size() > 0
7384579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber                && parseAuthMethod(response)) {
7394579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber            ssize_t i;
7404579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber            CHECK_EQ((status_t)OK, findPendingRequest(response, &i));
7414579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber            CHECK_GE(i, 0);
7424579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
7434579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber            sp<AMessage> reply = mPendingRequests.valueAt(i);
7444579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber            mPendingRequests.removeItemsAt(i);
7454579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
7464579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber            AString request;
7474579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber            CHECK(reply->findString("original-request", &request));
7484579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
7491d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar            sp<AMessage> msg = new AMessage(kWhatSendRequest, this);
7504579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber            msg->setMessage("reply", reply);
7514579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber            msg->setString("request", request.c_str(), request.size());
7524579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
753df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block            ALOGI("re-sending request with authentication headers...");
7544579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber            onSendRequest(msg);
7554579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
7564579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber            return true;
7574579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        }
7584579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    }
7594579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
7605ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber    return isRequest
7615ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber        ? handleServerRequest(response)
7625ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber        : notifyResponseListener(response);
7635ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber}
7645ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber
7655ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huberbool ARTSPConnection::handleServerRequest(const sp<ARTSPResponse> &request) {
7665ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber    // Implementation of server->client requests is optional for all methods
7675ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber    // but we do need to respond, even if it's just to say that we don't
7685ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber    // support the method.
7695ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber
7705ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber    ssize_t space1 = request->mStatusLine.find(" ");
7715ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber    CHECK_GE(space1, 0);
7725ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber
7735ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber    AString response;
7745ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber    response.append("RTSP/1.0 501 Not Implemented\r\n");
7755ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber
7765ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber    ssize_t i = request->mHeaders.indexOfKey("cseq");
7775ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber
7785ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber    if (i >= 0) {
7795ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber        AString value = request->mHeaders.valueAt(i);
7805ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber
7815ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber        unsigned long cseq;
7825ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber        if (!ParseSingleUnsignedLong(value.c_str(), &cseq)) {
7835ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber            return false;
7845ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber        }
7855ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber
7865ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber        response.append("CSeq: ");
7875ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber        response.append(cseq);
7885ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber        response.append("\r\n");
7895ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber    }
7905ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber
7915ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber    response.append("\r\n");
7925ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber
7935ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber    size_t numBytesSent = 0;
7945ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber    while (numBytesSent < response.size()) {
7955ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber        ssize_t n =
7965ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber            send(mSocket, response.c_str() + numBytesSent,
7975ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber                 response.size() - numBytesSent, 0);
7985ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber
7990fbe0577cfeda28bd016110e670708cce0752044Andreas Huber        if (n < 0 && errno == EINTR) {
8000fbe0577cfeda28bd016110e670708cce0752044Andreas Huber            continue;
8010fbe0577cfeda28bd016110e670708cce0752044Andreas Huber        }
8025ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber
8030fbe0577cfeda28bd016110e670708cce0752044Andreas Huber        if (n <= 0) {
8040fbe0577cfeda28bd016110e670708cce0752044Andreas Huber            if (n == 0) {
8050fbe0577cfeda28bd016110e670708cce0752044Andreas Huber                // Server closed the connection.
80629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("Server unexpectedly closed the connection.");
8070fbe0577cfeda28bd016110e670708cce0752044Andreas Huber            } else {
80829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("Error sending rtsp response (%s).", strerror(errno));
8095ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber            }
8105ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber
8110fbe0577cfeda28bd016110e670708cce0752044Andreas Huber            performDisconnect();
8120fbe0577cfeda28bd016110e670708cce0752044Andreas Huber
8135ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber            return false;
8145ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber        }
8155ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber
8165ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber        numBytesSent += (size_t)n;
8175ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber    }
8185ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber
8195ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber    return true;
820cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber}
821cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
822cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber// static
823cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huberbool ARTSPConnection::ParseSingleUnsignedLong(
824cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        const char *from, unsigned long *x) {
825cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    char *end;
826cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    *x = strtoul(from, &end, 10);
827cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
828cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    if (end == from || *end != '\0') {
829cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        return false;
830cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
831cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
832cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    return true;
833cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber}
834cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
8354579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huberstatus_t ARTSPConnection::findPendingRequest(
8364579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        const sp<ARTSPResponse> &response, ssize_t *index) const {
8374579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    *index = 0;
8384579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
839cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    ssize_t i = response->mHeaders.indexOfKey("cseq");
840cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
841cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    if (i < 0) {
8424579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        // This is an unsolicited server->client message.
8438b96e5df9f085e285d23beb96fd41c3d4b8005a3Lena Magnusson        *index = -1;
8444579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        return OK;
845cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
846cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
847cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    AString value = response->mHeaders.valueAt(i);
848cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
849cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    unsigned long cseq;
850cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    if (!ParseSingleUnsignedLong(value.c_str(), &cseq)) {
8514579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        return ERROR_MALFORMED;
852cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
853cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
854cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    i = mPendingRequests.indexOfKey(cseq);
855cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
856cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    if (i < 0) {
8574579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        return -ENOENT;
8584579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    }
8594579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
8604579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    *index = i;
8614579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
8624579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    return OK;
8634579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber}
8644579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
8654579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huberbool ARTSPConnection::notifyResponseListener(
8664579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        const sp<ARTSPResponse> &response) {
8674579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    ssize_t i;
8684579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    status_t err = findPendingRequest(response, &i);
8694579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
8704579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    if (err == OK && i < 0) {
8714579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        // An unsolicited server response is not a problem.
8724579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        return true;
8734579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    }
8744579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
8754579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    if (err != OK) {
8764579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        return false;
877cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
878cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
879cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    sp<AMessage> reply = mPendingRequests.valueAt(i);
880cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    mPendingRequests.removeItemsAt(i);
881cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
882cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    reply->setInt32("result", OK);
883cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    reply->setObject("response", response);
884cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    reply->post();
885cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
886cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    return true;
887cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber}
888cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
8894579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huberbool ARTSPConnection::parseAuthMethod(const sp<ARTSPResponse> &response) {
8904579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    ssize_t i = response->mHeaders.indexOfKey("www-authenticate");
8914579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
8924579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    if (i < 0) {
8934579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        return false;
8944579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    }
8954579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
8964579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    AString value = response->mHeaders.valueAt(i);
8974579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
8984579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    if (!strncmp(value.c_str(), "Basic", 5)) {
8994579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        mAuthType = BASIC;
9004579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    } else {
901c21143636f2c6078c8ad6b096f69a9208591342bAndreas Huber
9024579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        CHECK(!strncmp(value.c_str(), "Digest", 6));
9034579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        mAuthType = DIGEST;
9044579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
9054579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        i = value.find("nonce=");
9064579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        CHECK_GE(i, 0);
9074579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        CHECK_EQ(value.c_str()[i + 6], '\"');
9084579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        ssize_t j = value.find("\"", i + 7);
9094579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        CHECK_GE(j, 0);
9104579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
9114579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        mNonce.setTo(value, i + 7, j - i - 7);
9124579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    }
9134579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
9144579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    return true;
9154579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber}
9164579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
9174579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huberstatic void H(const AString &s, AString *out) {
9184579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    out->clear();
9194579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
9204579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    MD5_CTX m;
9214579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    MD5_Init(&m);
9224579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    MD5_Update(&m, s.c_str(), s.size());
9234579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
9244579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    uint8_t key[16];
9254579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    MD5_Final(key, &m);
9264579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
9274579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    for (size_t i = 0; i < 16; ++i) {
9284579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        char nibble = key[i] >> 4;
9294579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        if (nibble <= 9) {
9304579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber            nibble += '0';
9314579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        } else {
9324579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber            nibble += 'a' - 10;
9334579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        }
9344579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        out->append(&nibble, 1);
9354579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
9364579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        nibble = key[i] & 0x0f;
9374579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        if (nibble <= 9) {
9384579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber            nibble += '0';
9394579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        } else {
9404579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber            nibble += 'a' - 10;
9414579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        }
9424579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        out->append(&nibble, 1);
9434579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    }
9444579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber}
9454579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
9464579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huberstatic void GetMethodAndURL(
9474579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        const AString &request, AString *method, AString *url) {
9484579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    ssize_t space1 = request.find(" ");
9494579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    CHECK_GE(space1, 0);
9504579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
9514579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    ssize_t space2 = request.find(" ", space1 + 1);
9524579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    CHECK_GE(space2, 0);
9534579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
9544579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    method->setTo(request, 0, space1);
9554579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    url->setTo(request, space1 + 1, space2 - space1);
9564579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber}
9574579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
9584579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Hubervoid ARTSPConnection::addAuthentication(AString *request) {
9594579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    if (mAuthType == NONE) {
9604579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        return;
9614579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    }
9624579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
9634579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    // Find the boundary between headers and the body.
9644579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    ssize_t i = request->find("\r\n\r\n");
9654579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    CHECK_GE(i, 0);
9664579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
9674579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    if (mAuthType == BASIC) {
9684579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        AString tmp;
9694579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        tmp.append(mUser);
9704579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        tmp.append(":");
9714579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        tmp.append(mPass);
9724579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
9734579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        AString out;
9744579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        encodeBase64(tmp.c_str(), tmp.size(), &out);
9754579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
9764579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        AString fragment;
9774579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        fragment.append("Authorization: Basic ");
9784579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        fragment.append(out);
9794579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        fragment.append("\r\n");
9804579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
9814579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        request->insert(fragment, i + 2);
9824579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
9834579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        return;
9844579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    }
9854579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
9864579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    CHECK_EQ((int)mAuthType, (int)DIGEST);
9874579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
9884579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    AString method, url;
9894579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    GetMethodAndURL(*request, &method, &url);
9904579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
9914579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    AString A1;
9924579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    A1.append(mUser);
9934579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    A1.append(":");
9944579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    A1.append("Streaming Server");
9954579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    A1.append(":");
9964579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    A1.append(mPass);
9974579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
9984579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    AString A2;
9994579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    A2.append(method);
10004579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    A2.append(":");
10014579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    A2.append(url);
10024579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
10034579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    AString HA1, HA2;
10044579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    H(A1, &HA1);
10054579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    H(A2, &HA2);
10064579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
10074579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    AString tmp;
10084579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    tmp.append(HA1);
10094579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    tmp.append(":");
10104579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    tmp.append(mNonce);
10114579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    tmp.append(":");
10124579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    tmp.append(HA2);
10134579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
10144579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    AString digest;
10154579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    H(tmp, &digest);
10164579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
10174579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    AString fragment;
10184579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    fragment.append("Authorization: Digest ");
10194579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    fragment.append("nonce=\"");
10204579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    fragment.append(mNonce);
10214579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    fragment.append("\", ");
10224579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    fragment.append("username=\"");
10234579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    fragment.append(mUser);
10244579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    fragment.append("\", ");
10254579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    fragment.append("uri=\"");
10264579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    fragment.append(url);
10274579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    fragment.append("\", ");
10284579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    fragment.append("response=\"");
10294579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    fragment.append(digest);
10304579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    fragment.append("\"");
10314579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    fragment.append("\r\n");
10324579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
10334579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    request->insert(fragment, i + 2);
10344579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber}
10354579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
1036e681b91c27439907f216cb6c88426929bc5194bfAndreas Hubervoid ARTSPConnection::addUserAgent(AString *request) const {
1037e681b91c27439907f216cb6c88426929bc5194bfAndreas Huber    // Find the boundary between headers and the body.
1038e681b91c27439907f216cb6c88426929bc5194bfAndreas Huber    ssize_t i = request->find("\r\n\r\n");
1039e681b91c27439907f216cb6c88426929bc5194bfAndreas Huber    CHECK_GE(i, 0);
1040e681b91c27439907f216cb6c88426929bc5194bfAndreas Huber
1041cd77d4a1d38b7609a03f6826a1ff5fa7c98aa34fAndreas Huber    request->insert(sUserAgent, i + 2);
1042e681b91c27439907f216cb6c88426929bc5194bfAndreas Huber}
1043e681b91c27439907f216cb6c88426929bc5194bfAndreas Huber
1044cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber}  // namespace android
1045