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