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
23e681b91c27439907f216cb6c88426929bc5194bfAndreas Huber#include <cutils/properties.h>
24e681b91c27439907f216cb6c88426929bc5194bfAndreas Huber
25cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include <media/stagefright/foundation/ABuffer.h>
26cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include <media/stagefright/foundation/ADebug.h>
27cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include <media/stagefright/foundation/AMessage.h>
284579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber#include <media/stagefright/foundation/base64.h>
290792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber#include <media/stagefright/MediaErrors.h>
30cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
31cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include <arpa/inet.h>
32cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include <fcntl.h>
33cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include <netdb.h>
344579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber#include <openssl/md5.h>
35cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber#include <sys/socket.h>
36cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
37dab718bba3945332dc75e268e1e7f0fe2eb91c4aAndreas Huber#include "HTTPBase.h"
389b80c2bdb205bc143104f54d0743b6eedd67b14eAndreas Huber
39cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Hubernamespace android {
40cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
41cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber// static
42cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huberconst int64_t ARTSPConnection::kSelectTimeoutUs = 1000ll;
43cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
449b80c2bdb205bc143104f54d0743b6eedd67b14eAndreas HuberARTSPConnection::ARTSPConnection(bool uidValid, uid_t uid)
459b80c2bdb205bc143104f54d0743b6eedd67b14eAndreas Huber    : mUIDValid(uidValid),
469b80c2bdb205bc143104f54d0743b6eedd67b14eAndreas Huber      mUID(uid),
479b80c2bdb205bc143104f54d0743b6eedd67b14eAndreas Huber      mState(DISCONNECTED),
484579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber      mAuthType(NONE),
49cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber      mSocket(-1),
50cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber      mConnectionID(0),
51cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber      mNextCSeq(0),
52cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber      mReceiveResponseEventPending(false) {
53e681b91c27439907f216cb6c88426929bc5194bfAndreas Huber    MakeUserAgent(&mUserAgent);
54cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber}
55cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
56cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas HuberARTSPConnection::~ARTSPConnection() {
57cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    if (mSocket >= 0) {
5829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Connection is still open, closing the socket.");
59a23456b306f35b9ecf973bf5818ca39295e9e029Ashish Sharma        if (mUIDValid) {
60a23456b306f35b9ecf973bf5818ca39295e9e029Ashish Sharma            HTTPBase::UnRegisterSocketUserTag(mSocket);
61a23456b306f35b9ecf973bf5818ca39295e9e029Ashish Sharma        }
62cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        close(mSocket);
63cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        mSocket = -1;
64cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
65cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber}
66cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
67cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Hubervoid ARTSPConnection::connect(const char *url, const sp<AMessage> &reply) {
68cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    sp<AMessage> msg = new AMessage(kWhatConnect, id());
69cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    msg->setString("url", url);
70cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    msg->setMessage("reply", reply);
71cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    msg->post();
72cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber}
73cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
74cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Hubervoid ARTSPConnection::disconnect(const sp<AMessage> &reply) {
75cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    sp<AMessage> msg = new AMessage(kWhatDisconnect, id());
76cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    msg->setMessage("reply", reply);
77cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    msg->post();
78cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber}
79cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
80cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Hubervoid ARTSPConnection::sendRequest(
81cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        const char *request, const sp<AMessage> &reply) {
82cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    sp<AMessage> msg = new AMessage(kWhatSendRequest, id());
83cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    msg->setString("request", request);
84cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    msg->setMessage("reply", reply);
85cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    msg->post();
86cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber}
87cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
880792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Hubervoid ARTSPConnection::observeBinaryData(const sp<AMessage> &reply) {
890792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber    sp<AMessage> msg = new AMessage(kWhatObserveBinaryData, id());
900792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber    msg->setMessage("reply", reply);
910792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber    msg->post();
920792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber}
930792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber
94cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Hubervoid ARTSPConnection::onMessageReceived(const sp<AMessage> &msg) {
95cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    switch (msg->what()) {
96cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        case kWhatConnect:
97cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            onConnect(msg);
98cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            break;
99cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
100cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        case kWhatDisconnect:
101cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            onDisconnect(msg);
102cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            break;
103cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
104cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        case kWhatCompleteConnection:
105cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            onCompleteConnection(msg);
106cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            break;
107cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
108cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        case kWhatSendRequest:
109cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            onSendRequest(msg);
110cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            break;
111cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
112cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        case kWhatReceiveResponse:
113cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            onReceiveResponse();
114cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            break;
115cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
1160792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber        case kWhatObserveBinaryData:
1170792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber        {
1180792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber            CHECK(msg->findMessage("reply", &mObserveBinaryMessage));
1190792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber            break;
1200792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber        }
1210792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber
122cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        default:
123cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            TRESPASS();
124cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            break;
125cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
126cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber}
127cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
128cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber// static
129cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huberbool ARTSPConnection::ParseURL(
1304579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        const char *url, AString *host, unsigned *port, AString *path,
1314579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        AString *user, AString *pass) {
132cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    host->clear();
133cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    *port = 0;
134cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    path->clear();
1354579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    user->clear();
1364579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    pass->clear();
137cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
138cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    if (strncasecmp("rtsp://", url, 7)) {
139cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        return false;
140cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
141cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
142cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    const char *slashPos = strchr(&url[7], '/');
143cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
144cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    if (slashPos == NULL) {
145cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        host->setTo(&url[7]);
146cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        path->setTo("/");
147cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    } else {
148cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        host->setTo(&url[7], slashPos - &url[7]);
149cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        path->setTo(slashPos);
150cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
151cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
1524579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    ssize_t atPos = host->find("@");
1534579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
1544579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    if (atPos >= 0) {
1554579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        // Split of user:pass@ from hostname.
1564579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
1574579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        AString userPass(*host, 0, atPos);
1584579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        host->erase(0, atPos + 1);
1594579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
1604579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        ssize_t colonPos = userPass.find(":");
1614579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
1624579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        if (colonPos < 0) {
1634579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber            *user = userPass;
1644579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        } else {
1654579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber            user->setTo(userPass, 0, colonPos);
1664579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber            pass->setTo(userPass, colonPos + 1, userPass.size() - colonPos - 1);
1674579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        }
1684579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    }
1694579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
1704e2ffa400b82559cab2c5717c8dcdff393d334a9Mike Lockwood    const char *colonPos = strchr(host->c_str(), ':');
171cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
172cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    if (colonPos != NULL) {
173cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        unsigned long x;
174cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        if (!ParseSingleUnsignedLong(colonPos + 1, &x) || x >= 65536) {
175cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            return false;
176cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        }
177cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
178cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        *port = x;
179cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
180cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        size_t colonOffset = colonPos - host->c_str();
181cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        size_t trailing = host->size() - colonOffset;
182cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        host->erase(colonOffset, trailing);
183cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    } else {
184cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        *port = 554;
185cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
186cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
187cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    return true;
188cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber}
189cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
1900fbe0577cfeda28bd016110e670708cce0752044Andreas Huberstatic status_t MakeSocketBlocking(int s, bool blocking) {
191ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber    // Make socket non-blocking.
192ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber    int flags = fcntl(s, F_GETFL, 0);
1930fbe0577cfeda28bd016110e670708cce0752044Andreas Huber
1940fbe0577cfeda28bd016110e670708cce0752044Andreas Huber    if (flags == -1) {
1950fbe0577cfeda28bd016110e670708cce0752044Andreas Huber        return UNKNOWN_ERROR;
1960fbe0577cfeda28bd016110e670708cce0752044Andreas Huber    }
197ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber
198ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber    if (blocking) {
199ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber        flags &= ~O_NONBLOCK;
200ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber    } else {
201ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber        flags |= O_NONBLOCK;
202ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber    }
203ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber
2040fbe0577cfeda28bd016110e670708cce0752044Andreas Huber    flags = fcntl(s, F_SETFL, flags);
2050fbe0577cfeda28bd016110e670708cce0752044Andreas Huber
2060fbe0577cfeda28bd016110e670708cce0752044Andreas Huber    return flags == -1 ? UNKNOWN_ERROR : OK;
207ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber}
208ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber
209cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Hubervoid ARTSPConnection::onConnect(const sp<AMessage> &msg) {
210cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    ++mConnectionID;
211cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
212cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    if (mState != DISCONNECTED) {
213a23456b306f35b9ecf973bf5818ca39295e9e029Ashish Sharma        if (mUIDValid) {
214a23456b306f35b9ecf973bf5818ca39295e9e029Ashish Sharma            HTTPBase::UnRegisterSocketUserTag(mSocket);
215a23456b306f35b9ecf973bf5818ca39295e9e029Ashish Sharma        }
216cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        close(mSocket);
217cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        mSocket = -1;
218cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
219cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        flushPendingRequests();
220cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
221cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
222cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    mState = CONNECTING;
223cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
224cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    AString url;
225cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    CHECK(msg->findString("url", &url));
226cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
2276f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber    sp<AMessage> reply;
2286f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber    CHECK(msg->findMessage("reply", &reply));
2296f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber
230cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    AString host, path;
231cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    unsigned port;
2324579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    if (!ParseURL(url.c_str(), &host, &port, &path, &mUser, &mPass)
2334579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber            || (mUser.size() > 0 && mPass.size() == 0)) {
2344579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        // If we have a user name but no password we have to give up
2354579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        // right here, since we currently have no way of asking the user
2364579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        // for this information.
2374579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
23829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Malformed rtsp url %s", url.c_str());
2396f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber
2406f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber        reply->setInt32("result", ERROR_MALFORMED);
2416f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber        reply->post();
2426f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber
2436f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber        mState = DISCONNECTED;
2446f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber        return;
2456f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber    }
246cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
2474579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    if (mUser.size() > 0) {
2483856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("user = '%s', pass = '%s'", mUser.c_str(), mPass.c_str());
2494579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    }
2504579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
251cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    struct hostent *ent = gethostbyname(host.c_str());
2526f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber    if (ent == NULL) {
25329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Unknown host %s", host.c_str());
2546f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber
2556f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber        reply->setInt32("result", -ENOENT);
2566f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber        reply->post();
2576f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber
2586f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber        mState = DISCONNECTED;
2596f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber        return;
2606f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber    }
2616f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber
2626f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber    mSocket = socket(AF_INET, SOCK_STREAM, 0);
2636f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber
2649b80c2bdb205bc143104f54d0743b6eedd67b14eAndreas Huber    if (mUIDValid) {
265a23456b306f35b9ecf973bf5818ca39295e9e029Ashish Sharma        HTTPBase::RegisterSocketUserTag(mSocket, mUID,
266a23456b306f35b9ecf973bf5818ca39295e9e029Ashish Sharma                                        (uint32_t)*(uint32_t*) "RTSP");
2679b80c2bdb205bc143104f54d0743b6eedd67b14eAndreas Huber    }
2689b80c2bdb205bc143104f54d0743b6eedd67b14eAndreas Huber
2696f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber    MakeSocketBlocking(mSocket, false);
270cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
271cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    struct sockaddr_in remote;
272cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    memset(remote.sin_zero, 0, sizeof(remote.sin_zero));
273cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    remote.sin_family = AF_INET;
274cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    remote.sin_addr.s_addr = *(in_addr_t *)ent->h_addr;
275cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    remote.sin_port = htons(port);
276cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
277cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    int err = ::connect(
278cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            mSocket, (const struct sockaddr *)&remote, sizeof(remote));
279cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
280cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    reply->setInt32("server-ip", ntohl(remote.sin_addr.s_addr));
281cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
282cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    if (err < 0) {
283cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        if (errno == EINPROGRESS) {
284cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            sp<AMessage> msg = new AMessage(kWhatCompleteConnection, id());
285cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            msg->setMessage("reply", reply);
286cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            msg->setInt32("connection-id", mConnectionID);
287cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            msg->post();
288cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            return;
289cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        }
290cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
291cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        reply->setInt32("result", -errno);
292cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        mState = DISCONNECTED;
293cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
294a23456b306f35b9ecf973bf5818ca39295e9e029Ashish Sharma        if (mUIDValid) {
295a23456b306f35b9ecf973bf5818ca39295e9e029Ashish Sharma            HTTPBase::UnRegisterSocketUserTag(mSocket);
296a23456b306f35b9ecf973bf5818ca39295e9e029Ashish Sharma        }
297cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        close(mSocket);
298cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        mSocket = -1;
299cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    } else {
300cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        reply->setInt32("result", OK);
301cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        mState = CONNECTED;
302cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        mNextCSeq = 1;
303cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
304cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        postReceiveReponseEvent();
305cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
306cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
307cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    reply->post();
308cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber}
309cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
3100fbe0577cfeda28bd016110e670708cce0752044Andreas Hubervoid ARTSPConnection::performDisconnect() {
3110fbe0577cfeda28bd016110e670708cce0752044Andreas Huber    if (mUIDValid) {
3120fbe0577cfeda28bd016110e670708cce0752044Andreas Huber        HTTPBase::UnRegisterSocketUserTag(mSocket);
3130fbe0577cfeda28bd016110e670708cce0752044Andreas Huber    }
3140fbe0577cfeda28bd016110e670708cce0752044Andreas Huber    close(mSocket);
3150fbe0577cfeda28bd016110e670708cce0752044Andreas Huber    mSocket = -1;
3160fbe0577cfeda28bd016110e670708cce0752044Andreas Huber
3170fbe0577cfeda28bd016110e670708cce0752044Andreas Huber    flushPendingRequests();
3180fbe0577cfeda28bd016110e670708cce0752044Andreas Huber
3190fbe0577cfeda28bd016110e670708cce0752044Andreas Huber    mUser.clear();
3200fbe0577cfeda28bd016110e670708cce0752044Andreas Huber    mPass.clear();
3210fbe0577cfeda28bd016110e670708cce0752044Andreas Huber    mAuthType = NONE;
3220fbe0577cfeda28bd016110e670708cce0752044Andreas Huber    mNonce.clear();
3230fbe0577cfeda28bd016110e670708cce0752044Andreas Huber
3240fbe0577cfeda28bd016110e670708cce0752044Andreas Huber    mState = DISCONNECTED;
3250fbe0577cfeda28bd016110e670708cce0752044Andreas Huber}
3260fbe0577cfeda28bd016110e670708cce0752044Andreas Huber
327cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Hubervoid ARTSPConnection::onDisconnect(const sp<AMessage> &msg) {
328cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    if (mState == CONNECTED || mState == CONNECTING) {
3290fbe0577cfeda28bd016110e670708cce0752044Andreas Huber        performDisconnect();
330ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber    }
331cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
332cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    sp<AMessage> reply;
333cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    CHECK(msg->findMessage("reply", &reply));
334cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
335cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    reply->setInt32("result", OK);
3364579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
337cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    reply->post();
338cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber}
339cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
340cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Hubervoid ARTSPConnection::onCompleteConnection(const sp<AMessage> &msg) {
341cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    sp<AMessage> reply;
342cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    CHECK(msg->findMessage("reply", &reply));
343cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
344cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    int32_t connectionID;
345cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    CHECK(msg->findInt32("connection-id", &connectionID));
346cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
347cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    if ((connectionID != mConnectionID) || mState != CONNECTING) {
348cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        // While we were attempting to connect, the attempt was
349cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        // cancelled.
350cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        reply->setInt32("result", -ECONNABORTED);
351cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        reply->post();
352cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        return;
353cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
354cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
355cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    struct timeval tv;
356cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    tv.tv_sec = 0;
357cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    tv.tv_usec = kSelectTimeoutUs;
358cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
359cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    fd_set ws;
360cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    FD_ZERO(&ws);
361cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    FD_SET(mSocket, &ws);
362cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
363cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    int res = select(mSocket + 1, NULL, &ws, NULL, &tv);
364cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    CHECK_GE(res, 0);
365cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
366cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    if (res == 0) {
367cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        // Timed out. Not yet connected.
368cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
369cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        msg->post();
370cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        return;
371cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
372cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
373cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    int err;
374cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    socklen_t optionLen = sizeof(err);
375cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    CHECK_EQ(getsockopt(mSocket, SOL_SOCKET, SO_ERROR, &err, &optionLen), 0);
376cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    CHECK_EQ(optionLen, (socklen_t)sizeof(err));
377cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
378cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    if (err != 0) {
37929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("err = %d (%s)", err, strerror(err));
380cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
381cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        reply->setInt32("result", -err);
382cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
383cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        mState = DISCONNECTED;
384a23456b306f35b9ecf973bf5818ca39295e9e029Ashish Sharma        if (mUIDValid) {
385a23456b306f35b9ecf973bf5818ca39295e9e029Ashish Sharma            HTTPBase::UnRegisterSocketUserTag(mSocket);
386a23456b306f35b9ecf973bf5818ca39295e9e029Ashish Sharma        }
387cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        close(mSocket);
388cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        mSocket = -1;
389cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    } else {
390cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        reply->setInt32("result", OK);
391cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        mState = CONNECTED;
392cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        mNextCSeq = 1;
393cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
394cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        postReceiveReponseEvent();
395cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
396cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
397cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    reply->post();
398cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber}
399cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
400cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Hubervoid ARTSPConnection::onSendRequest(const sp<AMessage> &msg) {
401cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    sp<AMessage> reply;
402cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    CHECK(msg->findMessage("reply", &reply));
403cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
404cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    if (mState != CONNECTED) {
405cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        reply->setInt32("result", -ENOTCONN);
406cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        reply->post();
407cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        return;
408cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
409cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
410cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    AString request;
411cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    CHECK(msg->findString("request", &request));
412cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
4134579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    // Just in case we need to re-issue the request with proper authentication
4144579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    // later, stash it away.
4154579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    reply->setString("original-request", request.c_str(), request.size());
4164579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
4174579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    addAuthentication(&request);
418e681b91c27439907f216cb6c88426929bc5194bfAndreas Huber    addUserAgent(&request);
4194579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
420cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    // Find the boundary between headers and the body.
421cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    ssize_t i = request.find("\r\n\r\n");
422cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    CHECK_GE(i, 0);
423cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
424cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    int32_t cseq = mNextCSeq++;
425cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
426cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    AString cseqHeader = "CSeq: ";
427cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    cseqHeader.append(cseq);
428cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    cseqHeader.append("\r\n");
429cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
430cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    request.insert(cseqHeader, i + 2);
431cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
4323856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("request: '%s'", request.c_str());
433cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
434cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    size_t numBytesSent = 0;
435cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    while (numBytesSent < request.size()) {
436cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        ssize_t n =
437cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            send(mSocket, request.c_str() + numBytesSent,
438cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber                 request.size() - numBytesSent, 0);
439cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
4400fbe0577cfeda28bd016110e670708cce0752044Andreas Huber        if (n < 0 && errno == EINTR) {
4410fbe0577cfeda28bd016110e670708cce0752044Andreas Huber            continue;
4420fbe0577cfeda28bd016110e670708cce0752044Andreas Huber        }
4436f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber
4440fbe0577cfeda28bd016110e670708cce0752044Andreas Huber        if (n <= 0) {
4450fbe0577cfeda28bd016110e670708cce0752044Andreas Huber            performDisconnect();
4460fbe0577cfeda28bd016110e670708cce0752044Andreas Huber
4470fbe0577cfeda28bd016110e670708cce0752044Andreas Huber            if (n == 0) {
4480fbe0577cfeda28bd016110e670708cce0752044Andreas Huber                // Server closed the connection.
44929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("Server unexpectedly closed the connection.");
4500fbe0577cfeda28bd016110e670708cce0752044Andreas Huber
4510fbe0577cfeda28bd016110e670708cce0752044Andreas Huber                reply->setInt32("result", ERROR_IO);
4520fbe0577cfeda28bd016110e670708cce0752044Andreas Huber                reply->post();
4530fbe0577cfeda28bd016110e670708cce0752044Andreas Huber            } else {
45429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("Error sending rtsp request. (%s)", strerror(errno));
4550fbe0577cfeda28bd016110e670708cce0752044Andreas Huber                reply->setInt32("result", -errno);
4560fbe0577cfeda28bd016110e670708cce0752044Andreas Huber                reply->post();
457cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            }
458cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
4596f85dba3768089679ff5e35ad2f1841918d0adb2Andreas Huber            return;
460cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        }
461cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
462cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        numBytesSent += (size_t)n;
463cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
464cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
465cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    mPendingRequests.add(cseq, reply);
466cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber}
467cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
468cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Hubervoid ARTSPConnection::onReceiveResponse() {
469cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    mReceiveResponseEventPending = false;
470cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
471cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    if (mState != CONNECTED) {
472cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        return;
473cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
474cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
475cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    struct timeval tv;
476cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    tv.tv_sec = 0;
477cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    tv.tv_usec = kSelectTimeoutUs;
478cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
479cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    fd_set rs;
480cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    FD_ZERO(&rs);
481cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    FD_SET(mSocket, &rs);
482cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
483cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    int res = select(mSocket + 1, &rs, NULL, NULL, &tv);
484cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    CHECK_GE(res, 0);
485cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
486cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    if (res == 1) {
487ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber        MakeSocketBlocking(mSocket, true);
488ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber
489ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber        bool success = receiveRTSPReponse();
490ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber
491ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber        MakeSocketBlocking(mSocket, false);
492ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber
493ef7af7fec702db2fde72b16dedf9064585e6db77Andreas Huber        if (!success) {
494cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            // Something horrible, irreparable has happened.
495cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            flushPendingRequests();
496cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            return;
497cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        }
498cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
499cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
500cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    postReceiveReponseEvent();
501cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber}
502cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
503cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Hubervoid ARTSPConnection::flushPendingRequests() {
504cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    for (size_t i = 0; i < mPendingRequests.size(); ++i) {
505cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        sp<AMessage> reply = mPendingRequests.valueAt(i);
506cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
507cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        reply->setInt32("result", -ECONNABORTED);
508cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        reply->post();
509cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
510cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
511cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    mPendingRequests.clear();
512cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber}
513cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
514cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Hubervoid ARTSPConnection::postReceiveReponseEvent() {
515cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    if (mReceiveResponseEventPending) {
516cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        return;
517cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
518cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
519cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    sp<AMessage> msg = new AMessage(kWhatReceiveResponse, id());
520cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    msg->post();
521cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
522cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    mReceiveResponseEventPending = true;
523cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber}
524cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
5250792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huberstatus_t ARTSPConnection::receive(void *data, size_t size) {
5260792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber    size_t offset = 0;
5270792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber    while (offset < size) {
5280792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber        ssize_t n = recv(mSocket, (uint8_t *)data + offset, size - offset, 0);
529cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
5300fbe0577cfeda28bd016110e670708cce0752044Andreas Huber        if (n < 0 && errno == EINTR) {
5310fbe0577cfeda28bd016110e670708cce0752044Andreas Huber            continue;
5320fbe0577cfeda28bd016110e670708cce0752044Andreas Huber        }
5330fbe0577cfeda28bd016110e670708cce0752044Andreas Huber
5340fbe0577cfeda28bd016110e670708cce0752044Andreas Huber        if (n <= 0) {
5350fbe0577cfeda28bd016110e670708cce0752044Andreas Huber            performDisconnect();
5360fbe0577cfeda28bd016110e670708cce0752044Andreas Huber
5370fbe0577cfeda28bd016110e670708cce0752044Andreas Huber            if (n == 0) {
5380fbe0577cfeda28bd016110e670708cce0752044Andreas Huber                // Server closed the connection.
53929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("Server unexpectedly closed the connection.");
5400fbe0577cfeda28bd016110e670708cce0752044Andreas Huber                return ERROR_IO;
5410fbe0577cfeda28bd016110e670708cce0752044Andreas Huber            } else {
54229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("Error reading rtsp response. (%s)", strerror(errno));
5430fbe0577cfeda28bd016110e670708cce0752044Andreas Huber                return -errno;
5440fbe0577cfeda28bd016110e670708cce0752044Andreas Huber            }
545cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        }
546cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
5470792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber        offset += (size_t)n;
5480792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber    }
5490792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber
5500792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber    return OK;
5510792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber}
5520792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber
5530792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huberbool ARTSPConnection::receiveLine(AString *line) {
5540792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber    line->clear();
5550792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber
5560792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber    bool sawCR = false;
5570792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber    for (;;) {
5580792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber        char c;
5590792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber        if (receive(&c, 1) != OK) {
5600792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber            return false;
5610792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber        }
5620792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber
563cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        if (sawCR && c == '\n') {
564cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            line->erase(line->size() - 1, 1);
565cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            return true;
566cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        }
567cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
568cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        line->append(&c, 1);
569cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
5700792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber        if (c == '$' && line->size() == 1) {
5710792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber            // Special-case for interleaved binary data.
5720792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber            return true;
5730792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber        }
5740792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber
575cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        sawCR = (c == '\r');
576cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
577cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber}
578cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
5790792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Hubersp<ABuffer> ARTSPConnection::receiveBinaryData() {
5800792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber    uint8_t x[3];
5810792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber    if (receive(x, 3) != OK) {
5820792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber        return NULL;
5830792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber    }
5840792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber
5850792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber    sp<ABuffer> buffer = new ABuffer((x[1] << 8) | x[2]);
5860792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber    if (receive(buffer->data(), buffer->size()) != OK) {
5870792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber        return NULL;
5880792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber    }
5890792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber
5900792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber    buffer->meta()->setInt32("index", (int32_t)x[0]);
5910792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber
5920792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber    return buffer;
5930792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber}
5940792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber
5955ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huberstatic bool IsRTSPVersion(const AString &s) {
5965ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber    return s == "RTSP/1.0";
5975ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber}
5985ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber
599cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huberbool ARTSPConnection::receiveRTSPReponse() {
6000792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber    AString statusLine;
601cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
6020792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber    if (!receiveLine(&statusLine)) {
603cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        return false;
604cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
605cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
6060792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber    if (statusLine == "$") {
6070792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber        sp<ABuffer> buffer = receiveBinaryData();
6080792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber
6090792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber        if (buffer == NULL) {
6100792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber            return false;
6110792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber        }
6120792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber
6130792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber        if (mObserveBinaryMessage != NULL) {
6140792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber            sp<AMessage> notify = mObserveBinaryMessage->dup();
6152d8bedd05437b6fccdbc6bf70f673ffd86744d59Andreas Huber            notify->setBuffer("buffer", buffer);
6160792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber            notify->post();
6170792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber        } else {
6185ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block            ALOGW("received binary data, but no one cares.");
6190792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber        }
6200792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber
6210792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber        return true;
6220792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber    }
6230792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber
6240792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber    sp<ARTSPResponse> response = new ARTSPResponse;
6250792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber    response->mStatusLine = statusLine;
6260792ce7e0924ebb0dbe7b7cfcd79d12cbdb03ed2Andreas Huber
627df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block    ALOGI("status: %s", response->mStatusLine.c_str());
628cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
629cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    ssize_t space1 = response->mStatusLine.find(" ");
630cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    if (space1 < 0) {
631cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        return false;
632cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
633cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    ssize_t space2 = response->mStatusLine.find(" ", space1 + 1);
634cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    if (space2 < 0) {
635cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        return false;
636cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
637cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
6385ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber    bool isRequest = false;
639cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
6405ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber    if (!IsRTSPVersion(AString(response->mStatusLine, 0, space1))) {
6415ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber        CHECK(IsRTSPVersion(
6425ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber                    AString(
6435ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber                        response->mStatusLine,
6445ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber                        space2 + 1,
6455ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber                        response->mStatusLine.size() - space2 - 1)));
6465ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber
6475ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber        isRequest = true;
6485ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber
6495ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber        response->mStatusCode = 0;
6505ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber    } else {
6515ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber        AString statusCodeStr(
6525ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber                response->mStatusLine, space1 + 1, space2 - space1 - 1);
6535ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber
6545ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber        if (!ParseSingleUnsignedLong(
6555ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber                    statusCodeStr.c_str(), &response->mStatusCode)
6565ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber                || response->mStatusCode < 100 || response->mStatusCode > 999) {
6575ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber            return false;
6585ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber        }
659cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
660cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
661cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    AString line;
6624aae77cbe1bf4369910314a55c2bc2349af10d3cAndreas Huber    ssize_t lastDictIndex = -1;
663cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    for (;;) {
664cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        if (!receiveLine(&line)) {
665cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            break;
666cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        }
667cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
668cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        if (line.empty()) {
669cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            break;
670cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        }
671cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
6724aae77cbe1bf4369910314a55c2bc2349af10d3cAndreas Huber        ALOGV("line: '%s'", line.c_str());
6734aae77cbe1bf4369910314a55c2bc2349af10d3cAndreas Huber
6744aae77cbe1bf4369910314a55c2bc2349af10d3cAndreas Huber        if (line.c_str()[0] == ' ' || line.c_str()[0] == '\t') {
6754aae77cbe1bf4369910314a55c2bc2349af10d3cAndreas Huber            // Support for folded header values.
6764aae77cbe1bf4369910314a55c2bc2349af10d3cAndreas Huber
6774aae77cbe1bf4369910314a55c2bc2349af10d3cAndreas Huber            if (lastDictIndex < 0) {
6784aae77cbe1bf4369910314a55c2bc2349af10d3cAndreas Huber                // First line cannot be a continuation of the previous one.
6794aae77cbe1bf4369910314a55c2bc2349af10d3cAndreas Huber                return false;
6804aae77cbe1bf4369910314a55c2bc2349af10d3cAndreas Huber            }
6814aae77cbe1bf4369910314a55c2bc2349af10d3cAndreas Huber
6824aae77cbe1bf4369910314a55c2bc2349af10d3cAndreas Huber            AString &value = response->mHeaders.editValueAt(lastDictIndex);
6834aae77cbe1bf4369910314a55c2bc2349af10d3cAndreas Huber            value.append(line);
6844aae77cbe1bf4369910314a55c2bc2349af10d3cAndreas Huber
6854aae77cbe1bf4369910314a55c2bc2349af10d3cAndreas Huber            continue;
6864aae77cbe1bf4369910314a55c2bc2349af10d3cAndreas Huber        }
687cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
688cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        ssize_t colonPos = line.find(":");
689cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        if (colonPos < 0) {
690cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            // Malformed header line.
691cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            return false;
692cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        }
693cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
694cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        AString key(line, 0, colonPos);
695cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        key.trim();
696cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        key.tolower();
697cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
698cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        line.erase(0, colonPos + 1);
699cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
7004aae77cbe1bf4369910314a55c2bc2349af10d3cAndreas Huber        lastDictIndex = response->mHeaders.add(key, line);
7014aae77cbe1bf4369910314a55c2bc2349af10d3cAndreas Huber    }
7024aae77cbe1bf4369910314a55c2bc2349af10d3cAndreas Huber
7034aae77cbe1bf4369910314a55c2bc2349af10d3cAndreas Huber    for (size_t i = 0; i < response->mHeaders.size(); ++i) {
7044aae77cbe1bf4369910314a55c2bc2349af10d3cAndreas Huber        response->mHeaders.editValueAt(i).trim();
705cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
706cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
707cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    unsigned long contentLength = 0;
708cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
709cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    ssize_t i = response->mHeaders.indexOfKey("content-length");
710cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
711cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    if (i >= 0) {
712cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        AString value = response->mHeaders.valueAt(i);
713cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        if (!ParseSingleUnsignedLong(value.c_str(), &contentLength)) {
714cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber            return false;
715cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        }
716cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
717cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
718cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    if (contentLength > 0) {
719cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        response->mContent = new ABuffer(contentLength);
720cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
7210fbe0577cfeda28bd016110e670708cce0752044Andreas Huber        if (receive(response->mContent->data(), contentLength) != OK) {
7220fbe0577cfeda28bd016110e670708cce0752044Andreas Huber            return false;
723cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        }
724cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
725cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
7264579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    if (response->mStatusCode == 401) {
7274579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        if (mAuthType == NONE && mUser.size() > 0
7284579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber                && parseAuthMethod(response)) {
7294579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber            ssize_t i;
7304579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber            CHECK_EQ((status_t)OK, findPendingRequest(response, &i));
7314579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber            CHECK_GE(i, 0);
7324579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
7334579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber            sp<AMessage> reply = mPendingRequests.valueAt(i);
7344579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber            mPendingRequests.removeItemsAt(i);
7354579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
7364579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber            AString request;
7374579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber            CHECK(reply->findString("original-request", &request));
7384579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
7394579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber            sp<AMessage> msg = new AMessage(kWhatSendRequest, id());
7404579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber            msg->setMessage("reply", reply);
7414579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber            msg->setString("request", request.c_str(), request.size());
7424579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
743df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block            ALOGI("re-sending request with authentication headers...");
7444579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber            onSendRequest(msg);
7454579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
7464579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber            return true;
7474579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        }
7484579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    }
7494579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
7505ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber    return isRequest
7515ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber        ? handleServerRequest(response)
7525ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber        : notifyResponseListener(response);
7535ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber}
7545ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber
7555ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huberbool ARTSPConnection::handleServerRequest(const sp<ARTSPResponse> &request) {
7565ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber    // Implementation of server->client requests is optional for all methods
7575ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber    // but we do need to respond, even if it's just to say that we don't
7585ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber    // support the method.
7595ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber
7605ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber    ssize_t space1 = request->mStatusLine.find(" ");
7615ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber    CHECK_GE(space1, 0);
7625ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber
7635ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber    AString response;
7645ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber    response.append("RTSP/1.0 501 Not Implemented\r\n");
7655ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber
7665ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber    ssize_t i = request->mHeaders.indexOfKey("cseq");
7675ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber
7685ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber    if (i >= 0) {
7695ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber        AString value = request->mHeaders.valueAt(i);
7705ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber
7715ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber        unsigned long cseq;
7725ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber        if (!ParseSingleUnsignedLong(value.c_str(), &cseq)) {
7735ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber            return false;
7745ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber        }
7755ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber
7765ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber        response.append("CSeq: ");
7775ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber        response.append(cseq);
7785ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber        response.append("\r\n");
7795ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber    }
7805ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber
7815ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber    response.append("\r\n");
7825ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber
7835ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber    size_t numBytesSent = 0;
7845ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber    while (numBytesSent < response.size()) {
7855ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber        ssize_t n =
7865ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber            send(mSocket, response.c_str() + numBytesSent,
7875ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber                 response.size() - numBytesSent, 0);
7885ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber
7890fbe0577cfeda28bd016110e670708cce0752044Andreas Huber        if (n < 0 && errno == EINTR) {
7900fbe0577cfeda28bd016110e670708cce0752044Andreas Huber            continue;
7910fbe0577cfeda28bd016110e670708cce0752044Andreas Huber        }
7925ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber
7930fbe0577cfeda28bd016110e670708cce0752044Andreas Huber        if (n <= 0) {
7940fbe0577cfeda28bd016110e670708cce0752044Andreas Huber            if (n == 0) {
7950fbe0577cfeda28bd016110e670708cce0752044Andreas Huber                // Server closed the connection.
79629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("Server unexpectedly closed the connection.");
7970fbe0577cfeda28bd016110e670708cce0752044Andreas Huber            } else {
79829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("Error sending rtsp response (%s).", strerror(errno));
7995ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber            }
8005ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber
8010fbe0577cfeda28bd016110e670708cce0752044Andreas Huber            performDisconnect();
8020fbe0577cfeda28bd016110e670708cce0752044Andreas Huber
8035ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber            return false;
8045ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber        }
8055ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber
8065ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber        numBytesSent += (size_t)n;
8075ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber    }
8085ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber
8095ef152132b477a07fa31b2ddd39f4cf7a29f68b4Andreas Huber    return true;
810cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber}
811cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
812cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber// static
813cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huberbool ARTSPConnection::ParseSingleUnsignedLong(
814cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        const char *from, unsigned long *x) {
815cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    char *end;
816cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    *x = strtoul(from, &end, 10);
817cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
818cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    if (end == from || *end != '\0') {
819cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber        return false;
820cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
821cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
822cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    return true;
823cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber}
824cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
8254579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huberstatus_t ARTSPConnection::findPendingRequest(
8264579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        const sp<ARTSPResponse> &response, ssize_t *index) const {
8274579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    *index = 0;
8284579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
829cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    ssize_t i = response->mHeaders.indexOfKey("cseq");
830cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
831cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    if (i < 0) {
8324579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        // This is an unsolicited server->client message.
8334579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        return OK;
834cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
835cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
836cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    AString value = response->mHeaders.valueAt(i);
837cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
838cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    unsigned long cseq;
839cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    if (!ParseSingleUnsignedLong(value.c_str(), &cseq)) {
8404579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        return ERROR_MALFORMED;
841cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
842cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
843cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    i = mPendingRequests.indexOfKey(cseq);
844cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
845cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    if (i < 0) {
8464579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        return -ENOENT;
8474579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    }
8484579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
8494579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    *index = i;
8504579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
8514579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    return OK;
8524579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber}
8534579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
8544579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huberbool ARTSPConnection::notifyResponseListener(
8554579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        const sp<ARTSPResponse> &response) {
8564579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    ssize_t i;
8574579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    status_t err = findPendingRequest(response, &i);
8584579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
8594579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    if (err == OK && i < 0) {
8604579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        // An unsolicited server response is not a problem.
8614579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        return true;
8624579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    }
8634579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
8644579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    if (err != OK) {
8654579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        return false;
866cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    }
867cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
868cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    sp<AMessage> reply = mPendingRequests.valueAt(i);
869cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    mPendingRequests.removeItemsAt(i);
870cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
871cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    reply->setInt32("result", OK);
872cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    reply->setObject("response", response);
873cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    reply->post();
874cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
875cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber    return true;
876cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber}
877cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber
8784579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huberbool ARTSPConnection::parseAuthMethod(const sp<ARTSPResponse> &response) {
8794579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    ssize_t i = response->mHeaders.indexOfKey("www-authenticate");
8804579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
8814579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    if (i < 0) {
8824579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        return false;
8834579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    }
8844579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
8854579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    AString value = response->mHeaders.valueAt(i);
8864579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
8874579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    if (!strncmp(value.c_str(), "Basic", 5)) {
8884579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        mAuthType = BASIC;
8894579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    } else {
890c21143636f2c6078c8ad6b096f69a9208591342bAndreas Huber#if !defined(HAVE_ANDROID_OS)
891c21143636f2c6078c8ad6b096f69a9208591342bAndreas Huber        // We don't have access to the MD5 implementation on the simulator,
892c21143636f2c6078c8ad6b096f69a9208591342bAndreas Huber        // so we won't support digest authentication.
893c21143636f2c6078c8ad6b096f69a9208591342bAndreas Huber        return false;
894c21143636f2c6078c8ad6b096f69a9208591342bAndreas Huber#endif
895c21143636f2c6078c8ad6b096f69a9208591342bAndreas Huber
8964579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        CHECK(!strncmp(value.c_str(), "Digest", 6));
8974579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        mAuthType = DIGEST;
8984579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
8994579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        i = value.find("nonce=");
9004579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        CHECK_GE(i, 0);
9014579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        CHECK_EQ(value.c_str()[i + 6], '\"');
9024579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        ssize_t j = value.find("\"", i + 7);
9034579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        CHECK_GE(j, 0);
9044579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
9054579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        mNonce.setTo(value, i + 7, j - i - 7);
9064579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    }
9074579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
9084579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    return true;
9094579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber}
9104579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
911c21143636f2c6078c8ad6b096f69a9208591342bAndreas Huber#if defined(HAVE_ANDROID_OS)
9124579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huberstatic void H(const AString &s, AString *out) {
9134579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    out->clear();
9144579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
9154579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    MD5_CTX m;
9164579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    MD5_Init(&m);
9174579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    MD5_Update(&m, s.c_str(), s.size());
9184579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
9194579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    uint8_t key[16];
9204579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    MD5_Final(key, &m);
9214579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
9224579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    for (size_t i = 0; i < 16; ++i) {
9234579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        char nibble = key[i] >> 4;
9244579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        if (nibble <= 9) {
9254579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber            nibble += '0';
9264579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        } else {
9274579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber            nibble += 'a' - 10;
9284579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        }
9294579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        out->append(&nibble, 1);
9304579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
9314579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        nibble = key[i] & 0x0f;
9324579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        if (nibble <= 9) {
9334579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber            nibble += '0';
9344579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        } else {
9354579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber            nibble += 'a' - 10;
9364579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        }
9374579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        out->append(&nibble, 1);
9384579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    }
9394579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber}
940c21143636f2c6078c8ad6b096f69a9208591342bAndreas Huber#endif
9414579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
9424579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huberstatic void GetMethodAndURL(
9434579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        const AString &request, AString *method, AString *url) {
9444579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    ssize_t space1 = request.find(" ");
9454579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    CHECK_GE(space1, 0);
9464579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
9474579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    ssize_t space2 = request.find(" ", space1 + 1);
9484579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    CHECK_GE(space2, 0);
9494579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
9504579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    method->setTo(request, 0, space1);
9514579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    url->setTo(request, space1 + 1, space2 - space1);
9524579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber}
9534579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
9544579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Hubervoid ARTSPConnection::addAuthentication(AString *request) {
9554579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    if (mAuthType == NONE) {
9564579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        return;
9574579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    }
9584579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
9594579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    // Find the boundary between headers and the body.
9604579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    ssize_t i = request->find("\r\n\r\n");
9614579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    CHECK_GE(i, 0);
9624579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
9634579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    if (mAuthType == BASIC) {
9644579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        AString tmp;
9654579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        tmp.append(mUser);
9664579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        tmp.append(":");
9674579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        tmp.append(mPass);
9684579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
9694579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        AString out;
9704579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        encodeBase64(tmp.c_str(), tmp.size(), &out);
9714579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
9724579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        AString fragment;
9734579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        fragment.append("Authorization: Basic ");
9744579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        fragment.append(out);
9754579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        fragment.append("\r\n");
9764579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
9774579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        request->insert(fragment, i + 2);
9784579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
9794579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber        return;
9804579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    }
9814579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
982c21143636f2c6078c8ad6b096f69a9208591342bAndreas Huber#if defined(HAVE_ANDROID_OS)
9834579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    CHECK_EQ((int)mAuthType, (int)DIGEST);
9844579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
9854579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    AString method, url;
9864579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    GetMethodAndURL(*request, &method, &url);
9874579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
9884579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    AString A1;
9894579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    A1.append(mUser);
9904579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    A1.append(":");
9914579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    A1.append("Streaming Server");
9924579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    A1.append(":");
9934579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    A1.append(mPass);
9944579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
9954579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    AString A2;
9964579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    A2.append(method);
9974579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    A2.append(":");
9984579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    A2.append(url);
9994579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
10004579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    AString HA1, HA2;
10014579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    H(A1, &HA1);
10024579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    H(A2, &HA2);
10034579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
10044579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    AString tmp;
10054579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    tmp.append(HA1);
10064579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    tmp.append(":");
10074579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    tmp.append(mNonce);
10084579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    tmp.append(":");
10094579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    tmp.append(HA2);
10104579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
10114579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    AString digest;
10124579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    H(tmp, &digest);
10134579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
10144579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    AString fragment;
10154579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    fragment.append("Authorization: Digest ");
10164579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    fragment.append("nonce=\"");
10174579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    fragment.append(mNonce);
10184579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    fragment.append("\", ");
10194579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    fragment.append("username=\"");
10204579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    fragment.append(mUser);
10214579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    fragment.append("\", ");
10224579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    fragment.append("uri=\"");
10234579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    fragment.append(url);
10244579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    fragment.append("\", ");
10254579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    fragment.append("response=\"");
10264579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    fragment.append(digest);
10274579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    fragment.append("\"");
10284579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    fragment.append("\r\n");
10294579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
10304579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber    request->insert(fragment, i + 2);
1031c21143636f2c6078c8ad6b096f69a9208591342bAndreas Huber#endif
10324579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber}
10334579b7d49f6dd4f37e6043e59debfd72d69b8e7bAndreas Huber
1034e681b91c27439907f216cb6c88426929bc5194bfAndreas Huber// static
1035e681b91c27439907f216cb6c88426929bc5194bfAndreas Hubervoid ARTSPConnection::MakeUserAgent(AString *userAgent) {
1036e681b91c27439907f216cb6c88426929bc5194bfAndreas Huber    userAgent->clear();
1037e681b91c27439907f216cb6c88426929bc5194bfAndreas Huber    userAgent->setTo("User-Agent: stagefright/1.1 (Linux;Android ");
1038e681b91c27439907f216cb6c88426929bc5194bfAndreas Huber
1039e681b91c27439907f216cb6c88426929bc5194bfAndreas Huber#if (PROPERTY_VALUE_MAX < 8)
1040e681b91c27439907f216cb6c88426929bc5194bfAndreas Huber#error "PROPERTY_VALUE_MAX must be at least 8"
1041e681b91c27439907f216cb6c88426929bc5194bfAndreas Huber#endif
1042e681b91c27439907f216cb6c88426929bc5194bfAndreas Huber
1043e681b91c27439907f216cb6c88426929bc5194bfAndreas Huber    char value[PROPERTY_VALUE_MAX];
1044e681b91c27439907f216cb6c88426929bc5194bfAndreas Huber    property_get("ro.build.version.release", value, "Unknown");
1045e681b91c27439907f216cb6c88426929bc5194bfAndreas Huber    userAgent->append(value);
1046e681b91c27439907f216cb6c88426929bc5194bfAndreas Huber    userAgent->append(")\r\n");
1047e681b91c27439907f216cb6c88426929bc5194bfAndreas Huber}
1048e681b91c27439907f216cb6c88426929bc5194bfAndreas Huber
1049e681b91c27439907f216cb6c88426929bc5194bfAndreas Hubervoid ARTSPConnection::addUserAgent(AString *request) const {
1050e681b91c27439907f216cb6c88426929bc5194bfAndreas Huber    // Find the boundary between headers and the body.
1051e681b91c27439907f216cb6c88426929bc5194bfAndreas Huber    ssize_t i = request->find("\r\n\r\n");
1052e681b91c27439907f216cb6c88426929bc5194bfAndreas Huber    CHECK_GE(i, 0);
1053e681b91c27439907f216cb6c88426929bc5194bfAndreas Huber
1054e681b91c27439907f216cb6c88426929bc5194bfAndreas Huber    request->insert(mUserAgent, i + 2);
1055e681b91c27439907f216cb6c88426929bc5194bfAndreas Huber}
1056e681b91c27439907f216cb6c88426929bc5194bfAndreas Huber
1057cf7b9c7aae758ac0b99833915053c63c2ac46e09Andreas Huber}  // namespace android
1058