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