WifiDisplaySource.cpp revision c92bed3a73c06e90217f8f199ca0b517aa7595d2
1/* 2 * Copyright 2012, 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 "WifiDisplaySource" 19#include <utils/Log.h> 20 21#include "WifiDisplaySource.h" 22#include "PlaybackSession.h" 23#include "ParsedMessage.h" 24 25#include <gui/ISurfaceTexture.h> 26 27#include <media/IRemoteDisplayClient.h> 28#include <media/stagefright/foundation/ABuffer.h> 29#include <media/stagefright/foundation/ADebug.h> 30#include <media/stagefright/foundation/AMessage.h> 31#include <media/stagefright/MediaErrors.h> 32 33#include <arpa/inet.h> 34#include <cutils/properties.h> 35 36namespace android { 37 38WifiDisplaySource::WifiDisplaySource( 39 const sp<ANetworkSession> &netSession, 40 const sp<IRemoteDisplayClient> &client) 41 : mNetSession(netSession), 42 mClient(client), 43 mSessionID(0), 44 mClientSessionID(0), 45 mReaperPending(false), 46 mNextCSeq(1) { 47} 48 49WifiDisplaySource::~WifiDisplaySource() { 50} 51 52status_t WifiDisplaySource::start(const char *iface) { 53 sp<AMessage> msg = new AMessage(kWhatStart, id()); 54 msg->setString("iface", iface); 55 56 sp<AMessage> response; 57 status_t err = msg->postAndAwaitResponse(&response); 58 59 if (err != OK) { 60 return err; 61 } 62 63 if (!response->findInt32("err", &err)) { 64 err = OK; 65 } 66 67 return err; 68} 69 70status_t WifiDisplaySource::stop() { 71 sp<AMessage> msg = new AMessage(kWhatStop, id()); 72 73 sp<AMessage> response; 74 status_t err = msg->postAndAwaitResponse(&response); 75 76 if (err != OK) { 77 return err; 78 } 79 80 if (!response->findInt32("err", &err)) { 81 err = OK; 82 } 83 84 return err; 85} 86 87void WifiDisplaySource::onMessageReceived(const sp<AMessage> &msg) { 88 switch (msg->what()) { 89 case kWhatStart: 90 { 91 uint32_t replyID; 92 CHECK(msg->senderAwaitsResponse(&replyID)); 93 94 AString iface; 95 CHECK(msg->findString("iface", &iface)); 96 97 status_t err = OK; 98 99 ssize_t colonPos = iface.find(":"); 100 101 unsigned long port; 102 103 if (colonPos >= 0) { 104 const char *s = iface.c_str() + colonPos + 1; 105 106 char *end; 107 port = strtoul(s, &end, 10); 108 109 if (end == s || *end != '\0' || port > 65535) { 110 err = -EINVAL; 111 } else { 112 iface.erase(colonPos, iface.size() - colonPos); 113 } 114 } else { 115 port = kWifiDisplayDefaultPort; 116 } 117 118 if (err == OK) { 119 if (inet_aton(iface.c_str(), &mInterfaceAddr) != 0) { 120 sp<AMessage> notify = new AMessage(kWhatRTSPNotify, id()); 121 122 err = mNetSession->createRTSPServer( 123 mInterfaceAddr, port, notify, &mSessionID); 124 } else { 125 err = -EINVAL; 126 } 127 } 128 129 sp<AMessage> response = new AMessage; 130 response->setInt32("err", err); 131 response->postReply(replyID); 132 break; 133 } 134 135 case kWhatRTSPNotify: 136 { 137 int32_t reason; 138 CHECK(msg->findInt32("reason", &reason)); 139 140 switch (reason) { 141 case ANetworkSession::kWhatError: 142 { 143 int32_t sessionID; 144 CHECK(msg->findInt32("sessionID", &sessionID)); 145 146 int32_t err; 147 CHECK(msg->findInt32("err", &err)); 148 149 AString detail; 150 CHECK(msg->findString("detail", &detail)); 151 152 ALOGE("An error occurred in session %d (%d, '%s/%s').", 153 sessionID, 154 err, 155 detail.c_str(), 156 strerror(-err)); 157 158 mNetSession->destroySession(sessionID); 159 160 if (sessionID == mClientSessionID) { 161 mClientSessionID = -1; 162 163 disconnectClient(UNKNOWN_ERROR); 164 } 165 break; 166 } 167 168 case ANetworkSession::kWhatClientConnected: 169 { 170 int32_t sessionID; 171 CHECK(msg->findInt32("sessionID", &sessionID)); 172 173 if (mClientSessionID > 0) { 174 ALOGW("A client tried to connect, but we already " 175 "have one."); 176 177 mNetSession->destroySession(sessionID); 178 break; 179 } 180 181 CHECK(msg->findString("client-ip", &mClientInfo.mRemoteIP)); 182 CHECK(msg->findString("server-ip", &mClientInfo.mLocalIP)); 183 184 if (mClientInfo.mRemoteIP == mClientInfo.mLocalIP) { 185 // Disallow connections from the local interface 186 // for security reasons. 187 mNetSession->destroySession(sessionID); 188 break; 189 } 190 191 CHECK(msg->findInt32( 192 "server-port", &mClientInfo.mLocalPort)); 193 mClientInfo.mPlaybackSessionID = -1; 194 195 mClientSessionID = sessionID; 196 197 ALOGI("We now have a client (%d) connected.", sessionID); 198 199 status_t err = sendM1(sessionID); 200 CHECK_EQ(err, (status_t)OK); 201 break; 202 } 203 204 case ANetworkSession::kWhatData: 205 { 206 onReceiveClientData(msg); 207 break; 208 } 209 210 default: 211 TRESPASS(); 212 } 213 break; 214 } 215 216 case kWhatStop: 217 { 218 uint32_t replyID; 219 CHECK(msg->senderAwaitsResponse(&replyID)); 220 221 disconnectClient(OK); 222 223 status_t err = OK; 224 225 sp<AMessage> response = new AMessage; 226 response->setInt32("err", err); 227 response->postReply(replyID); 228 break; 229 } 230 231 case kWhatReapDeadClients: 232 { 233 mReaperPending = false; 234 235 if (mClientSessionID == 0 236 || mClientInfo.mPlaybackSession == NULL) { 237 break; 238 } 239 240 if (mClientInfo.mPlaybackSession->getLastLifesignUs() 241 + kPlaybackSessionTimeoutUs < ALooper::GetNowUs()) { 242 ALOGI("playback session timed out, reaping."); 243 244 disconnectClient(-ETIMEDOUT); 245 } else { 246 scheduleReaper(); 247 } 248 break; 249 } 250 251 case kWhatPlaybackSessionNotify: 252 { 253 int32_t playbackSessionID; 254 CHECK(msg->findInt32("playbackSessionID", &playbackSessionID)); 255 256 int32_t what; 257 CHECK(msg->findInt32("what", &what)); 258 259 if (what == PlaybackSession::kWhatSessionDead) { 260 ALOGI("playback session wants to quit."); 261 262 disconnectClient(UNKNOWN_ERROR); 263 } else if (what == PlaybackSession::kWhatSessionEstablished) { 264 if (mClient != NULL) { 265 mClient->onDisplayConnected( 266 mClientInfo.mPlaybackSession->getSurfaceTexture(), 267 mClientInfo.mPlaybackSession->width(), 268 mClientInfo.mPlaybackSession->height(), 269 0 /* flags */); 270 } 271 } else { 272 CHECK_EQ(what, PlaybackSession::kWhatBinaryData); 273 274 int32_t channel; 275 CHECK(msg->findInt32("channel", &channel)); 276 277 sp<ABuffer> data; 278 CHECK(msg->findBuffer("data", &data)); 279 280 CHECK_LE(channel, 0xffu); 281 CHECK_LE(data->size(), 0xffffu); 282 283 int32_t sessionID; 284 CHECK(msg->findInt32("sessionID", &sessionID)); 285 286 char header[4]; 287 header[0] = '$'; 288 header[1] = channel; 289 header[2] = data->size() >> 8; 290 header[3] = data->size() & 0xff; 291 292 mNetSession->sendRequest( 293 sessionID, header, sizeof(header)); 294 295 mNetSession->sendRequest( 296 sessionID, data->data(), data->size()); 297 } 298 break; 299 } 300 301 case kWhatKeepAlive: 302 { 303 int32_t sessionID; 304 CHECK(msg->findInt32("sessionID", &sessionID)); 305 306 if (mClientSessionID != sessionID) { 307 // Obsolete event, client is already gone. 308 break; 309 } 310 311 sendM16(sessionID); 312 break; 313 } 314 315 default: 316 TRESPASS(); 317 } 318} 319 320void WifiDisplaySource::registerResponseHandler( 321 int32_t sessionID, int32_t cseq, HandleRTSPResponseFunc func) { 322 ResponseID id; 323 id.mSessionID = sessionID; 324 id.mCSeq = cseq; 325 mResponseHandlers.add(id, func); 326} 327 328status_t WifiDisplaySource::sendM1(int32_t sessionID) { 329 AString request = "OPTIONS * RTSP/1.0\r\n"; 330 AppendCommonResponse(&request, mNextCSeq); 331 332 request.append( 333 "Require: org.wfa.wfd1.0\r\n" 334 "\r\n"); 335 336 status_t err = 337 mNetSession->sendRequest(sessionID, request.c_str(), request.size()); 338 339 if (err != OK) { 340 return err; 341 } 342 343 registerResponseHandler( 344 sessionID, mNextCSeq, &WifiDisplaySource::onReceiveM1Response); 345 346 ++mNextCSeq; 347 348 return OK; 349} 350 351status_t WifiDisplaySource::sendM3(int32_t sessionID) { 352 AString body = 353 "wfd_video_formats\r\n" 354 "wfd_audio_codecs\r\n" 355 "wfd_client_rtp_ports\r\n"; 356 357 AString request = "GET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0\r\n"; 358 AppendCommonResponse(&request, mNextCSeq); 359 360 request.append("Content-Type: text/parameters\r\n"); 361 request.append(StringPrintf("Content-Length: %d\r\n", body.size())); 362 request.append("\r\n"); 363 request.append(body); 364 365 status_t err = 366 mNetSession->sendRequest(sessionID, request.c_str(), request.size()); 367 368 if (err != OK) { 369 return err; 370 } 371 372 registerResponseHandler( 373 sessionID, mNextCSeq, &WifiDisplaySource::onReceiveM3Response); 374 375 ++mNextCSeq; 376 377 return OK; 378} 379 380status_t WifiDisplaySource::sendM4(int32_t sessionID) { 381 // wfd_video_formats: 382 // 1 byte "native" 383 // 1 byte "preferred-display-mode-supported" 0 or 1 384 // one or more avc codec structures 385 // 1 byte profile 386 // 1 byte level 387 // 4 byte CEA mask 388 // 4 byte VESA mask 389 // 4 byte HH mask 390 // 1 byte latency 391 // 2 byte min-slice-slice 392 // 2 byte slice-enc-params 393 // 1 byte framerate-control-support 394 // max-hres (none or 2 byte) 395 // max-vres (none or 2 byte) 396 397 CHECK_EQ(sessionID, mClientSessionID); 398 399 AString transportString = "UDP"; 400 401 char val[PROPERTY_VALUE_MAX]; 402 if (property_get("media.wfd.enable-tcp", val, NULL) 403 && (!strcasecmp("true", val) || !strcmp("1", val))) { 404 ALOGI("Using TCP transport."); 405 transportString = "TCP"; 406 } 407 408 AString body = StringPrintf( 409 "wfd_video_formats: " 410 "30 00 02 02 00000040 00000000 00000000 00 0000 0000 00 none none\r\n" 411 "wfd_audio_codecs: AAC 00000001 00\r\n" // 2 ch AAC 48kHz 412 "wfd_presentation_URL: rtsp://%s:%d/wfd1.0/streamid=0 none\r\n" 413 "wfd_client_rtp_ports: RTP/AVP/%s;unicast 19000 0 mode=play\r\n", 414 mClientInfo.mLocalIP.c_str(), mClientInfo.mLocalPort, 415 transportString.c_str()); 416 417 AString request = "SET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0\r\n"; 418 AppendCommonResponse(&request, mNextCSeq); 419 420 request.append("Content-Type: text/parameters\r\n"); 421 request.append(StringPrintf("Content-Length: %d\r\n", body.size())); 422 request.append("\r\n"); 423 request.append(body); 424 425 status_t err = 426 mNetSession->sendRequest(sessionID, request.c_str(), request.size()); 427 428 if (err != OK) { 429 return err; 430 } 431 432 registerResponseHandler( 433 sessionID, mNextCSeq, &WifiDisplaySource::onReceiveM4Response); 434 435 ++mNextCSeq; 436 437 return OK; 438} 439 440status_t WifiDisplaySource::sendM5(int32_t sessionID) { 441 AString body = "wfd_trigger_method: SETUP\r\n"; 442 443 AString request = "SET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0\r\n"; 444 AppendCommonResponse(&request, mNextCSeq); 445 446 request.append("Content-Type: text/parameters\r\n"); 447 request.append(StringPrintf("Content-Length: %d\r\n", body.size())); 448 request.append("\r\n"); 449 request.append(body); 450 451 status_t err = 452 mNetSession->sendRequest(sessionID, request.c_str(), request.size()); 453 454 if (err != OK) { 455 return err; 456 } 457 458 registerResponseHandler( 459 sessionID, mNextCSeq, &WifiDisplaySource::onReceiveM5Response); 460 461 ++mNextCSeq; 462 463 return OK; 464} 465 466status_t WifiDisplaySource::sendM16(int32_t sessionID) { 467 AString request = "GET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0\r\n"; 468 AppendCommonResponse(&request, mNextCSeq); 469 470 CHECK_EQ(sessionID, mClientSessionID); 471 request.append( 472 StringPrintf("Session: %d\r\n", mClientInfo.mPlaybackSessionID)); 473 request.append("\r\n"); // Empty body 474 475 status_t err = 476 mNetSession->sendRequest(sessionID, request.c_str(), request.size()); 477 478 if (err != OK) { 479 return err; 480 } 481 482 registerResponseHandler( 483 sessionID, mNextCSeq, &WifiDisplaySource::onReceiveM16Response); 484 485 ++mNextCSeq; 486 487 return OK; 488} 489 490status_t WifiDisplaySource::onReceiveM1Response( 491 int32_t sessionID, const sp<ParsedMessage> &msg) { 492 int32_t statusCode; 493 if (!msg->getStatusCode(&statusCode)) { 494 return ERROR_MALFORMED; 495 } 496 497 if (statusCode != 200) { 498 return ERROR_UNSUPPORTED; 499 } 500 501 return OK; 502} 503 504status_t WifiDisplaySource::onReceiveM3Response( 505 int32_t sessionID, const sp<ParsedMessage> &msg) { 506 int32_t statusCode; 507 if (!msg->getStatusCode(&statusCode)) { 508 return ERROR_MALFORMED; 509 } 510 511 if (statusCode != 200) { 512 return ERROR_UNSUPPORTED; 513 } 514 515 return sendM4(sessionID); 516} 517 518status_t WifiDisplaySource::onReceiveM4Response( 519 int32_t sessionID, const sp<ParsedMessage> &msg) { 520 int32_t statusCode; 521 if (!msg->getStatusCode(&statusCode)) { 522 return ERROR_MALFORMED; 523 } 524 525 if (statusCode != 200) { 526 return ERROR_UNSUPPORTED; 527 } 528 529 return sendM5(sessionID); 530} 531 532status_t WifiDisplaySource::onReceiveM5Response( 533 int32_t sessionID, const sp<ParsedMessage> &msg) { 534 int32_t statusCode; 535 if (!msg->getStatusCode(&statusCode)) { 536 return ERROR_MALFORMED; 537 } 538 539 if (statusCode != 200) { 540 return ERROR_UNSUPPORTED; 541 } 542 543 return OK; 544} 545 546status_t WifiDisplaySource::onReceiveM16Response( 547 int32_t sessionID, const sp<ParsedMessage> &msg) { 548 // If only the response was required to include a "Session:" header... 549 550 CHECK_EQ(sessionID, mClientSessionID); 551 552 if (mClientInfo.mPlaybackSession != NULL) { 553 mClientInfo.mPlaybackSession->updateLiveness(); 554 555 scheduleKeepAlive(sessionID); 556 } 557 558 return OK; 559} 560 561void WifiDisplaySource::scheduleReaper() { 562 if (mReaperPending) { 563 return; 564 } 565 566 mReaperPending = true; 567 (new AMessage(kWhatReapDeadClients, id()))->post(kReaperIntervalUs); 568} 569 570void WifiDisplaySource::scheduleKeepAlive(int32_t sessionID) { 571 // We need to send updates at least 5 secs before the timeout is set to 572 // expire, make sure the timeout is greater than 5 secs to begin with. 573 CHECK_GT(kPlaybackSessionTimeoutUs, 5000000ll); 574 575 sp<AMessage> msg = new AMessage(kWhatKeepAlive, id()); 576 msg->setInt32("sessionID", sessionID); 577 msg->post(kPlaybackSessionTimeoutUs - 5000000ll); 578} 579 580void WifiDisplaySource::onReceiveClientData(const sp<AMessage> &msg) { 581 int32_t sessionID; 582 CHECK(msg->findInt32("sessionID", &sessionID)); 583 584 sp<RefBase> obj; 585 CHECK(msg->findObject("data", &obj)); 586 587 sp<ParsedMessage> data = 588 static_cast<ParsedMessage *>(obj.get()); 589 590 ALOGV("session %d received '%s'", 591 sessionID, data->debugString().c_str()); 592 593 AString method; 594 AString uri; 595 data->getRequestField(0, &method); 596 597 int32_t cseq; 598 if (!data->findInt32("cseq", &cseq)) { 599 sendErrorResponse(sessionID, "400 Bad Request", -1 /* cseq */); 600 return; 601 } 602 603 if (method.startsWith("RTSP/")) { 604 // This is a response. 605 606 ResponseID id; 607 id.mSessionID = sessionID; 608 id.mCSeq = cseq; 609 610 ssize_t index = mResponseHandlers.indexOfKey(id); 611 612 if (index < 0) { 613 ALOGW("Received unsolicited server response, cseq %d", cseq); 614 return; 615 } 616 617 HandleRTSPResponseFunc func = mResponseHandlers.valueAt(index); 618 mResponseHandlers.removeItemsAt(index); 619 620 status_t err = (this->*func)(sessionID, data); 621 622 if (err != OK) { 623 ALOGW("Response handler for session %d, cseq %d returned " 624 "err %d (%s)", 625 sessionID, cseq, err, strerror(-err)); 626 } 627 } else { 628 AString version; 629 data->getRequestField(2, &version); 630 if (!(version == AString("RTSP/1.0"))) { 631 sendErrorResponse(sessionID, "505 RTSP Version not supported", cseq); 632 return; 633 } 634 635 if (method == "DESCRIBE") { 636 onDescribeRequest(sessionID, cseq, data); 637 } else if (method == "OPTIONS") { 638 onOptionsRequest(sessionID, cseq, data); 639 } else if (method == "SETUP") { 640 onSetupRequest(sessionID, cseq, data); 641 } else if (method == "PLAY") { 642 onPlayRequest(sessionID, cseq, data); 643 } else if (method == "PAUSE") { 644 onPauseRequest(sessionID, cseq, data); 645 } else if (method == "TEARDOWN") { 646 onTeardownRequest(sessionID, cseq, data); 647 } else if (method == "GET_PARAMETER") { 648 onGetParameterRequest(sessionID, cseq, data); 649 } else if (method == "SET_PARAMETER") { 650 onSetParameterRequest(sessionID, cseq, data); 651 } else { 652 sendErrorResponse(sessionID, "405 Method Not Allowed", cseq); 653 } 654 } 655} 656 657void WifiDisplaySource::onDescribeRequest( 658 int32_t sessionID, 659 int32_t cseq, 660 const sp<ParsedMessage> &data) { 661 int64_t nowUs = ALooper::GetNowUs(); 662 663 AString sdp; 664 sdp.append("v=0\r\n"); 665 666 sdp.append(StringPrintf( 667 "o=- %lld %lld IN IP4 0.0.0.0\r\n", nowUs, nowUs)); 668 669 sdp.append( 670 "o=- 0 0 IN IP4 127.0.0.0\r\n" 671 "s=Sample\r\n" 672 "c=IN IP4 0.0.0.0\r\n" 673 "b=AS:502\r\n" 674 "t=0 0\r\n" 675 "a=control:*\r\n" 676 "a=range:npt=now-\r\n" 677 "m=video 0 RTP/AVP 33\r\n" 678 "a=rtpmap:33 MP2T/90000\r\n" 679 "a=control:\r\n"); 680 681 AString response = "RTSP/1.0 200 OK\r\n"; 682 AppendCommonResponse(&response, cseq); 683 684 response.append("Content-Type: application/sdp\r\n"); 685 686 // response.append("Content-Base: rtsp://0.0.0.0:7236\r\n"); 687 response.append(StringPrintf("Content-Length: %d\r\n", sdp.size())); 688 response.append("\r\n"); 689 response.append(sdp); 690 691 status_t err = mNetSession->sendRequest(sessionID, response.c_str()); 692 CHECK_EQ(err, (status_t)OK); 693} 694 695void WifiDisplaySource::onOptionsRequest( 696 int32_t sessionID, 697 int32_t cseq, 698 const sp<ParsedMessage> &data) { 699 int32_t playbackSessionID; 700 sp<PlaybackSession> playbackSession = 701 findPlaybackSession(data, &playbackSessionID); 702 703 if (playbackSession != NULL) { 704 playbackSession->updateLiveness(); 705 } 706 707 AString response = "RTSP/1.0 200 OK\r\n"; 708 AppendCommonResponse(&response, cseq); 709 710 response.append( 711 "Public: org.wfa.wfd1.0, DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE, " 712 "GET_PARAMETER, SET_PARAMETER\r\n"); 713 714 response.append("\r\n"); 715 716 status_t err = mNetSession->sendRequest(sessionID, response.c_str()); 717 CHECK_EQ(err, (status_t)OK); 718 719 err = sendM3(sessionID); 720 CHECK_EQ(err, (status_t)OK); 721} 722 723void WifiDisplaySource::onSetupRequest( 724 int32_t sessionID, 725 int32_t cseq, 726 const sp<ParsedMessage> &data) { 727 CHECK_EQ(sessionID, mClientSessionID); 728 if (mClientInfo.mPlaybackSessionID != -1) { 729 // We only support a single playback session per client. 730 // This is due to the reversed keep-alive design in the wfd specs... 731 sendErrorResponse(sessionID, "400 Bad Request", cseq); 732 return; 733 } 734 735 AString transport; 736 if (!data->findString("transport", &transport)) { 737 sendErrorResponse(sessionID, "400 Bad Request", cseq); 738 return; 739 } 740 741 PlaybackSession::TransportMode transportMode = 742 PlaybackSession::TRANSPORT_UDP; 743 744 int clientRtp, clientRtcp; 745 if (transport.startsWith("RTP/AVP/TCP;")) { 746 AString interleaved; 747 if (ParsedMessage::GetAttribute( 748 transport.c_str(), "interleaved", &interleaved) 749 && sscanf(interleaved.c_str(), "%d-%d", 750 &clientRtp, &clientRtcp) == 2) { 751 transportMode = PlaybackSession::TRANSPORT_TCP_INTERLEAVED; 752 } else { 753 bool badRequest = false; 754 755 AString clientPort; 756 if (!ParsedMessage::GetAttribute( 757 transport.c_str(), "client_port", &clientPort)) { 758 badRequest = true; 759 } else if (sscanf(clientPort.c_str(), "%d-%d", 760 &clientRtp, &clientRtcp) == 2) { 761 } else if (sscanf(clientPort.c_str(), "%d", &clientRtp) == 1) { 762 // No RTCP. 763 clientRtcp = -1; 764 } else { 765 badRequest = true; 766 } 767 768 if (badRequest) { 769 sendErrorResponse(sessionID, "400 Bad Request", cseq); 770 return; 771 } 772 773 transportMode = PlaybackSession::TRANSPORT_TCP; 774 } 775 } else if (transport.startsWith("RTP/AVP;unicast;") 776 || transport.startsWith("RTP/AVP/UDP;unicast;")) { 777 bool badRequest = false; 778 779 AString clientPort; 780 if (!ParsedMessage::GetAttribute( 781 transport.c_str(), "client_port", &clientPort)) { 782 badRequest = true; 783 } else if (sscanf(clientPort.c_str(), "%d-%d", 784 &clientRtp, &clientRtcp) == 2) { 785 } else if (sscanf(clientPort.c_str(), "%d", &clientRtp) == 1) { 786 // No RTCP. 787 clientRtcp = -1; 788 } else { 789 badRequest = true; 790 } 791 792 if (badRequest) { 793 sendErrorResponse(sessionID, "400 Bad Request", cseq); 794 return; 795 } 796#if 1 797 // The older LG dongles doesn't specify client_port=xxx apparently. 798 } else if (transport == "RTP/AVP/UDP;unicast") { 799 clientRtp = 19000; 800 clientRtcp = clientRtp + 1; 801#endif 802 } else { 803 sendErrorResponse(sessionID, "461 Unsupported Transport", cseq); 804 return; 805 } 806 807 int32_t playbackSessionID = makeUniquePlaybackSessionID(); 808 809 sp<AMessage> notify = new AMessage(kWhatPlaybackSessionNotify, id()); 810 notify->setInt32("playbackSessionID", playbackSessionID); 811 notify->setInt32("sessionID", sessionID); 812 813 sp<PlaybackSession> playbackSession = 814 new PlaybackSession( 815 mNetSession, notify, mInterfaceAddr, 816 mClient == NULL /* legacyMode */); 817 818 looper()->registerHandler(playbackSession); 819 820 AString uri; 821 data->getRequestField(1, &uri); 822 823 if (strncasecmp("rtsp://", uri.c_str(), 7)) { 824 sendErrorResponse(sessionID, "400 Bad Request", cseq); 825 return; 826 } 827 828 if (!(uri.startsWith("rtsp://") && uri.endsWith("/wfd1.0/streamid=0"))) { 829 sendErrorResponse(sessionID, "404 Not found", cseq); 830 return; 831 } 832 833 status_t err = playbackSession->init( 834 mClientInfo.mRemoteIP.c_str(), 835 clientRtp, 836 clientRtcp, 837 transportMode); 838 839 if (err != OK) { 840 looper()->unregisterHandler(playbackSession->id()); 841 playbackSession.clear(); 842 } 843 844 switch (err) { 845 case OK: 846 break; 847 case -ENOENT: 848 sendErrorResponse(sessionID, "404 Not Found", cseq); 849 return; 850 default: 851 sendErrorResponse(sessionID, "403 Forbidden", cseq); 852 return; 853 } 854 855 mClientInfo.mPlaybackSessionID = playbackSessionID; 856 mClientInfo.mPlaybackSession = playbackSession; 857 858 AString response = "RTSP/1.0 200 OK\r\n"; 859 AppendCommonResponse(&response, cseq, playbackSessionID); 860 861 if (transportMode == PlaybackSession::TRANSPORT_TCP_INTERLEAVED) { 862 response.append( 863 StringPrintf( 864 "Transport: RTP/AVP/TCP;interleaved=%d-%d;", 865 clientRtp, clientRtcp)); 866 } else { 867 int32_t serverRtp = playbackSession->getRTPPort(); 868 869 AString transportString = "UDP"; 870 if (transportMode == PlaybackSession::TRANSPORT_TCP) { 871 transportString = "TCP"; 872 } 873 874 if (clientRtcp >= 0) { 875 response.append( 876 StringPrintf( 877 "Transport: RTP/AVP/%s;unicast;client_port=%d-%d;" 878 "server_port=%d-%d\r\n", 879 transportString.c_str(), 880 clientRtp, clientRtcp, serverRtp, serverRtp + 1)); 881 } else { 882 response.append( 883 StringPrintf( 884 "Transport: RTP/AVP/%s;unicast;client_port=%d;" 885 "server_port=%d\r\n", 886 transportString.c_str(), 887 clientRtp, serverRtp)); 888 } 889 } 890 891 response.append("\r\n"); 892 893 err = mNetSession->sendRequest(sessionID, response.c_str()); 894 CHECK_EQ(err, (status_t)OK); 895 896 scheduleReaper(); 897 scheduleKeepAlive(sessionID); 898} 899 900void WifiDisplaySource::onPlayRequest( 901 int32_t sessionID, 902 int32_t cseq, 903 const sp<ParsedMessage> &data) { 904 int32_t playbackSessionID; 905 sp<PlaybackSession> playbackSession = 906 findPlaybackSession(data, &playbackSessionID); 907 908 if (playbackSession == NULL) { 909 sendErrorResponse(sessionID, "454 Session Not Found", cseq); 910 return; 911 } 912 913 status_t err = playbackSession->play(); 914 CHECK_EQ(err, (status_t)OK); 915 916 AString response = "RTSP/1.0 200 OK\r\n"; 917 AppendCommonResponse(&response, cseq, playbackSessionID); 918 response.append("Range: npt=now-\r\n"); 919 response.append("\r\n"); 920 921 err = mNetSession->sendRequest(sessionID, response.c_str()); 922 CHECK_EQ(err, (status_t)OK); 923 924 playbackSession->finishPlay(); 925} 926 927void WifiDisplaySource::onPauseRequest( 928 int32_t sessionID, 929 int32_t cseq, 930 const sp<ParsedMessage> &data) { 931 int32_t playbackSessionID; 932 sp<PlaybackSession> playbackSession = 933 findPlaybackSession(data, &playbackSessionID); 934 935 if (playbackSession == NULL) { 936 sendErrorResponse(sessionID, "454 Session Not Found", cseq); 937 return; 938 } 939 940 status_t err = playbackSession->pause(); 941 CHECK_EQ(err, (status_t)OK); 942 943 AString response = "RTSP/1.0 200 OK\r\n"; 944 AppendCommonResponse(&response, cseq, playbackSessionID); 945 response.append("\r\n"); 946 947 err = mNetSession->sendRequest(sessionID, response.c_str()); 948 CHECK_EQ(err, (status_t)OK); 949} 950 951void WifiDisplaySource::onTeardownRequest( 952 int32_t sessionID, 953 int32_t cseq, 954 const sp<ParsedMessage> &data) { 955 int32_t playbackSessionID; 956 sp<PlaybackSession> playbackSession = 957 findPlaybackSession(data, &playbackSessionID); 958 959 if (playbackSession == NULL) { 960 sendErrorResponse(sessionID, "454 Session Not Found", cseq); 961 return; 962 } 963 964 AString response = "RTSP/1.0 200 OK\r\n"; 965 AppendCommonResponse(&response, cseq, playbackSessionID); 966 response.append("Connection: close\r\n"); 967 response.append("\r\n"); 968 969 status_t err = mNetSession->sendRequest(sessionID, response.c_str()); 970 CHECK_EQ(err, (status_t)OK); 971 972 disconnectClient(UNKNOWN_ERROR); 973} 974 975void WifiDisplaySource::onGetParameterRequest( 976 int32_t sessionID, 977 int32_t cseq, 978 const sp<ParsedMessage> &data) { 979 int32_t playbackSessionID; 980 sp<PlaybackSession> playbackSession = 981 findPlaybackSession(data, &playbackSessionID); 982 983 if (playbackSession == NULL) { 984 sendErrorResponse(sessionID, "454 Session Not Found", cseq); 985 return; 986 } 987 988 playbackSession->updateLiveness(); 989 990 AString response = "RTSP/1.0 200 OK\r\n"; 991 AppendCommonResponse(&response, cseq, playbackSessionID); 992 response.append("\r\n"); 993 994 status_t err = mNetSession->sendRequest(sessionID, response.c_str()); 995 CHECK_EQ(err, (status_t)OK); 996} 997 998void WifiDisplaySource::onSetParameterRequest( 999 int32_t sessionID, 1000 int32_t cseq, 1001 const sp<ParsedMessage> &data) { 1002 int32_t playbackSessionID; 1003 sp<PlaybackSession> playbackSession = 1004 findPlaybackSession(data, &playbackSessionID); 1005 1006 if (playbackSession == NULL) { 1007 sendErrorResponse(sessionID, "454 Session Not Found", cseq); 1008 return; 1009 } 1010 1011 // XXX check that the parameter is about that. 1012 playbackSession->requestIDRFrame(); 1013 1014 playbackSession->updateLiveness(); 1015 1016 AString response = "RTSP/1.0 200 OK\r\n"; 1017 AppendCommonResponse(&response, cseq, playbackSessionID); 1018 response.append("\r\n"); 1019 1020 status_t err = mNetSession->sendRequest(sessionID, response.c_str()); 1021 CHECK_EQ(err, (status_t)OK); 1022} 1023 1024// static 1025void WifiDisplaySource::AppendCommonResponse( 1026 AString *response, int32_t cseq, int32_t playbackSessionID) { 1027 time_t now = time(NULL); 1028 struct tm *now2 = gmtime(&now); 1029 char buf[128]; 1030 strftime(buf, sizeof(buf), "%a, %d %b %Y %H:%M:%S %z", now2); 1031 1032 response->append("Date: "); 1033 response->append(buf); 1034 response->append("\r\n"); 1035 1036 response->append("Server: Mine/1.0\r\n"); 1037 1038 if (cseq >= 0) { 1039 response->append(StringPrintf("CSeq: %d\r\n", cseq)); 1040 } 1041 1042 if (playbackSessionID >= 0ll) { 1043 response->append( 1044 StringPrintf( 1045 "Session: %d;timeout=%lld\r\n", 1046 playbackSessionID, kPlaybackSessionTimeoutSecs)); 1047 } 1048} 1049 1050void WifiDisplaySource::sendErrorResponse( 1051 int32_t sessionID, 1052 const char *errorDetail, 1053 int32_t cseq) { 1054 AString response; 1055 response.append("RTSP/1.0 "); 1056 response.append(errorDetail); 1057 response.append("\r\n"); 1058 1059 AppendCommonResponse(&response, cseq); 1060 1061 response.append("\r\n"); 1062 1063 status_t err = mNetSession->sendRequest(sessionID, response.c_str()); 1064 CHECK_EQ(err, (status_t)OK); 1065} 1066 1067int32_t WifiDisplaySource::makeUniquePlaybackSessionID() const { 1068 return rand(); 1069} 1070 1071sp<WifiDisplaySource::PlaybackSession> WifiDisplaySource::findPlaybackSession( 1072 const sp<ParsedMessage> &data, int32_t *playbackSessionID) const { 1073 if (!data->findInt32("session", playbackSessionID)) { 1074 // XXX the older dongles do not always include a "Session:" header. 1075 *playbackSessionID = mClientInfo.mPlaybackSessionID; 1076 return mClientInfo.mPlaybackSession; 1077 } 1078 1079 if (*playbackSessionID != mClientInfo.mPlaybackSessionID) { 1080 return NULL; 1081 } 1082 1083 return mClientInfo.mPlaybackSession; 1084} 1085 1086void WifiDisplaySource::disconnectClient(status_t err) { 1087 if (mClientSessionID != 0) { 1088 if (mClientInfo.mPlaybackSession != NULL) { 1089 looper()->unregisterHandler(mClientInfo.mPlaybackSession->id()); 1090 mClientInfo.mPlaybackSession.clear(); 1091 } 1092 1093 mNetSession->destroySession(mClientSessionID); 1094 mClientSessionID = 0; 1095 } 1096 1097 if (mClient != NULL) { 1098 if (err != OK) { 1099 mClient->onDisplayError(IRemoteDisplayClient::kDisplayErrorUnknown); 1100 } else { 1101 mClient->onDisplayDisconnected(); 1102 } 1103 } 1104} 1105 1106} // namespace android 1107 1108