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