netwerk/protocol/rtsp/controller/RtspControllerChild.cpp

Thu, 15 Jan 2015 15:55:04 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 15 Jan 2015 15:55:04 +0100
branch
TOR_BUG_9701
changeset 9
a63d609f5ebe
permissions
-rw-r--r--

Back out 97036ab72558 which inappropriately compared turds to third parties.

michael@0 1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* vim: set sw=2 ts=8 et tw=80 : */
michael@0 3 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 4 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 6
michael@0 7 #include "RtspControllerChild.h"
michael@0 8 #include "RtspMetaData.h"
michael@0 9 #include "mozilla/dom/TabChild.h"
michael@0 10 #include "mozilla/net/NeckoChild.h"
michael@0 11 #include "nsITabChild.h"
michael@0 12 #include "nsILoadContext.h"
michael@0 13 #include "nsNetUtil.h"
michael@0 14 #include "mozilla/ipc/InputStreamUtils.h"
michael@0 15 #include "mozilla/ipc/URIUtils.h"
michael@0 16 #include "nsStringStream.h"
michael@0 17 #include "prlog.h"
michael@0 18
michael@0 19 PRLogModuleInfo* gRtspChildLog = nullptr;
michael@0 20 #undef LOG
michael@0 21 #define LOG(args) PR_LOG(gRtspChildLog, PR_LOG_DEBUG, args)
michael@0 22
michael@0 23 const uint32_t kRtspTotalTracks = 2;
michael@0 24 using namespace mozilla::ipc;
michael@0 25
michael@0 26 namespace mozilla {
michael@0 27 namespace net {
michael@0 28
michael@0 29 NS_IMPL_ADDREF(RtspControllerChild)
michael@0 30
michael@0 31 NS_IMETHODIMP_(nsrefcnt) RtspControllerChild::Release()
michael@0 32 {
michael@0 33 NS_PRECONDITION(0 != mRefCnt, "dup release");
michael@0 34 // Enable this to find non-threadsafe destructors:
michael@0 35 // NS_ASSERT_OWNINGTHREAD(RtspControllerChild);
michael@0 36 --mRefCnt;
michael@0 37 NS_LOG_RELEASE(this, mRefCnt, "RtspControllerChild");
michael@0 38
michael@0 39 if (mRefCnt == 1 && mIPCOpen) {
michael@0 40 Send__delete__(this);
michael@0 41 return mRefCnt;
michael@0 42 }
michael@0 43
michael@0 44 if (mRefCnt == 0) {
michael@0 45 mRefCnt = 1; /* stabilize */
michael@0 46 delete this;
michael@0 47 return 0;
michael@0 48 }
michael@0 49 return mRefCnt;
michael@0 50 }
michael@0 51
michael@0 52 NS_INTERFACE_MAP_BEGIN(RtspControllerChild)
michael@0 53 NS_INTERFACE_MAP_ENTRY(nsIStreamingProtocolController)
michael@0 54 NS_INTERFACE_MAP_ENTRY(nsIStreamingProtocolListener)
michael@0 55 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIStreamingProtocolController)
michael@0 56 NS_INTERFACE_MAP_END
michael@0 57
michael@0 58 //-----------------------------------------------------------------------------
michael@0 59 // RtspControllerChild methods
michael@0 60 //-----------------------------------------------------------------------------
michael@0 61 RtspControllerChild::RtspControllerChild(nsIChannel *channel)
michael@0 62 : mIPCOpen(false)
michael@0 63 , mIPCAllowed(false)
michael@0 64 , mChannel(channel)
michael@0 65 , mTotalTracks(0)
michael@0 66 , mSuspendCount(0)
michael@0 67 {
michael@0 68 #if defined(PR_LOGGING)
michael@0 69 if (!gRtspChildLog)
michael@0 70 gRtspChildLog = PR_NewLogModule("nsRtspChild");
michael@0 71 #endif
michael@0 72 AddIPDLReference();
michael@0 73 gNeckoChild->SendPRtspControllerConstructor(this);
michael@0 74 }
michael@0 75
michael@0 76 RtspControllerChild::~RtspControllerChild()
michael@0 77 {
michael@0 78 LOG(("RtspControllerChild::~RtspControllerChild()"));
michael@0 79 }
michael@0 80
michael@0 81 void
michael@0 82 RtspControllerChild::ReleaseChannel()
michael@0 83 {
michael@0 84 static_cast<RtspChannelChild*>(mChannel.get())->ReleaseController();
michael@0 85 }
michael@0 86
michael@0 87 bool
michael@0 88 RtspControllerChild::OKToSendIPC()
michael@0 89 {
michael@0 90 MOZ_ASSERT(NS_IsMainThread());
michael@0 91 if (mIPCOpen == false) {
michael@0 92 return false;
michael@0 93 }
michael@0 94 return mIPCAllowed;
michael@0 95 }
michael@0 96
michael@0 97 void
michael@0 98 RtspControllerChild::AllowIPC()
michael@0 99 {
michael@0 100 MOZ_ASSERT(NS_IsMainThread());
michael@0 101 mIPCAllowed = true;
michael@0 102 }
michael@0 103
michael@0 104 void
michael@0 105 RtspControllerChild::DisallowIPC()
michael@0 106 {
michael@0 107 MOZ_ASSERT(NS_IsMainThread());
michael@0 108 mIPCAllowed = false;
michael@0 109 }
michael@0 110
michael@0 111 //-----------------------------------------------------------------------------
michael@0 112 // RtspControllerChild::PRtspControllerChild
michael@0 113 //-----------------------------------------------------------------------------
michael@0 114 bool
michael@0 115 RtspControllerChild::RecvOnMediaDataAvailable(
michael@0 116 const uint8_t& index,
michael@0 117 const nsCString& data,
michael@0 118 const uint32_t& length,
michael@0 119 const uint32_t& offset,
michael@0 120 const InfallibleTArray<RtspMetadataParam>& metaArray)
michael@0 121 {
michael@0 122 nsRefPtr<RtspMetaData> meta = new RtspMetaData();
michael@0 123 nsresult rv = meta->DeserializeRtspMetaData(metaArray);
michael@0 124 NS_ENSURE_SUCCESS(rv, true);
michael@0 125
michael@0 126 if (mListener) {
michael@0 127 mListener->OnMediaDataAvailable(index, data, length, offset, meta.get());
michael@0 128 }
michael@0 129 return true;
michael@0 130 }
michael@0 131
michael@0 132 void
michael@0 133 RtspControllerChild::AddMetaData(
michael@0 134 already_AddRefed<nsIStreamingProtocolMetaData>&& meta)
michael@0 135 {
michael@0 136 nsCOMPtr<nsIStreamingProtocolMetaData> data = meta;
michael@0 137 mMetaArray.AppendElement(data);
michael@0 138 }
michael@0 139
michael@0 140 int
michael@0 141 RtspControllerChild::GetMetaDataLength()
michael@0 142 {
michael@0 143 return mMetaArray.Length();
michael@0 144 }
michael@0 145
michael@0 146 bool
michael@0 147 RtspControllerChild::RecvOnConnected(
michael@0 148 const uint8_t& index,
michael@0 149 const InfallibleTArray<RtspMetadataParam>& metaArray)
michael@0 150 {
michael@0 151 // Deserialize meta data.
michael@0 152 nsRefPtr<RtspMetaData> meta = new RtspMetaData();
michael@0 153 nsresult rv = meta->DeserializeRtspMetaData(metaArray);
michael@0 154 NS_ENSURE_SUCCESS(rv, true);
michael@0 155 meta->GetTotalTracks(&mTotalTracks);
michael@0 156 if (mTotalTracks <= 0) {
michael@0 157 LOG(("RtspControllerChild::RecvOnConnected invalid tracks %d", mTotalTracks));
michael@0 158 // Set the default value.
michael@0 159 mTotalTracks = kRtspTotalTracks;
michael@0 160 }
michael@0 161 AddMetaData(meta.forget().downcast<nsIStreamingProtocolMetaData>());
michael@0 162
michael@0 163 // Notify the listener when meta data of tracks are available.
michael@0 164 if ((static_cast<uint32_t>(index) + 1) == mTotalTracks) {
michael@0 165 // The controller provide |GetTrackMetaData| method for his client.
michael@0 166 if (mListener) {
michael@0 167 mListener->OnConnected(index, nullptr);
michael@0 168 }
michael@0 169 }
michael@0 170 return true;
michael@0 171 }
michael@0 172
michael@0 173 bool
michael@0 174 RtspControllerChild::RecvOnDisconnected(
michael@0 175 const uint8_t& index,
michael@0 176 const nsresult& reason)
michael@0 177 {
michael@0 178 DisallowIPC();
michael@0 179 LOG(("RtspControllerChild::RecvOnDisconnected for track %d reason = 0x%x", index, reason));
michael@0 180 if (mListener) {
michael@0 181 mListener->OnDisconnected(index, reason);
michael@0 182 }
michael@0 183 ReleaseChannel();
michael@0 184 return true;
michael@0 185 }
michael@0 186
michael@0 187 bool
michael@0 188 RtspControllerChild::RecvAsyncOpenFailed(const nsresult& reason)
michael@0 189 {
michael@0 190 DisallowIPC();
michael@0 191 LOG(("RtspControllerChild::RecvAsyncOpenFailed reason = 0x%x", reason));
michael@0 192 if (mListener) {
michael@0 193 mListener->OnDisconnected(0, NS_ERROR_CONNECTION_REFUSED);
michael@0 194 }
michael@0 195 ReleaseChannel();
michael@0 196 return true;
michael@0 197 }
michael@0 198
michael@0 199 void
michael@0 200 RtspControllerChild::AddIPDLReference()
michael@0 201 {
michael@0 202 NS_ABORT_IF_FALSE(!mIPCOpen,
michael@0 203 "Attempt to retain more than one IPDL reference");
michael@0 204 mIPCOpen = true;
michael@0 205 AllowIPC();
michael@0 206 AddRef();
michael@0 207 }
michael@0 208
michael@0 209 void
michael@0 210 RtspControllerChild::ReleaseIPDLReference()
michael@0 211 {
michael@0 212 NS_ABORT_IF_FALSE(mIPCOpen, "Attempt to release nonexistent IPDL reference");
michael@0 213 mIPCOpen = false;
michael@0 214 DisallowIPC();
michael@0 215 Release();
michael@0 216 }
michael@0 217
michael@0 218 NS_IMETHODIMP
michael@0 219 RtspControllerChild::GetTrackMetaData(
michael@0 220 uint8_t index,
michael@0 221 nsIStreamingProtocolMetaData **result)
michael@0 222 {
michael@0 223 if (GetMetaDataLength() <= 0 || index >= GetMetaDataLength()) {
michael@0 224 LOG(("RtspControllerChild:: meta data is not available"));
michael@0 225 return NS_ERROR_NOT_INITIALIZED;
michael@0 226 }
michael@0 227 LOG(("RtspControllerChild::GetTrackMetaData() %d", index));
michael@0 228 NS_IF_ADDREF(*result = mMetaArray[index]);
michael@0 229 return NS_OK;
michael@0 230 }
michael@0 231
michael@0 232 enum IPCEvent
michael@0 233 {
michael@0 234 SendNoneEvent = 0,
michael@0 235 SendPlayEvent,
michael@0 236 SendPauseEvent,
michael@0 237 SendSeekEvent,
michael@0 238 SendResumeEvent,
michael@0 239 SendSuspendEvent,
michael@0 240 SendStopEvent
michael@0 241 };
michael@0 242
michael@0 243 class SendIPCEvent : public nsRunnable
michael@0 244 {
michael@0 245 public:
michael@0 246 SendIPCEvent(RtspControllerChild *aController, IPCEvent aEvent)
michael@0 247 : mController(aController)
michael@0 248 , mEvent(aEvent)
michael@0 249 , mSeekTime(0)
michael@0 250 {
michael@0 251 }
michael@0 252
michael@0 253 SendIPCEvent(RtspControllerChild *aController,
michael@0 254 IPCEvent aEvent,
michael@0 255 uint64_t aSeekTime)
michael@0 256 : mController(aController)
michael@0 257 , mEvent(aEvent)
michael@0 258 , mSeekTime(aSeekTime)
michael@0 259 {
michael@0 260 }
michael@0 261
michael@0 262 NS_IMETHOD Run()
michael@0 263 {
michael@0 264 MOZ_ASSERT(NS_IsMainThread());
michael@0 265 if (mController->OKToSendIPC() == false) {
michael@0 266 // Don't send any more IPC events; no guarantee that parent objects are
michael@0 267 // still alive.
michael@0 268 return NS_ERROR_FAILURE;
michael@0 269 }
michael@0 270 bool rv = true;
michael@0 271
michael@0 272 if (mEvent == SendPlayEvent) {
michael@0 273 rv = mController->SendPlay();
michael@0 274 } else if (mEvent == SendPauseEvent) {
michael@0 275 rv = mController->SendPause();
michael@0 276 } else if (mEvent == SendSeekEvent) {
michael@0 277 rv = mController->SendSeek(mSeekTime);
michael@0 278 } else if (mEvent == SendResumeEvent) {
michael@0 279 rv = mController->SendResume();
michael@0 280 } else if (mEvent == SendSuspendEvent) {
michael@0 281 rv = mController->SendSuspend();
michael@0 282 } else if (mEvent == SendStopEvent) {
michael@0 283 rv = mController->SendStop();
michael@0 284 } else {
michael@0 285 LOG(("RtspControllerChild::SendIPCEvent"));
michael@0 286 }
michael@0 287 if (!rv) {
michael@0 288 return NS_ERROR_FAILURE;
michael@0 289 }
michael@0 290 return NS_OK;
michael@0 291 }
michael@0 292 private:
michael@0 293 nsRefPtr<RtspControllerChild> mController;
michael@0 294 IPCEvent mEvent;
michael@0 295 uint64_t mSeekTime;
michael@0 296 };
michael@0 297
michael@0 298 //-----------------------------------------------------------------------------
michael@0 299 // RtspControllerChild::nsIStreamingProtocolController
michael@0 300 //-----------------------------------------------------------------------------
michael@0 301 NS_IMETHODIMP
michael@0 302 RtspControllerChild::Play(void)
michael@0 303 {
michael@0 304 LOG(("RtspControllerChild::Play()"));
michael@0 305
michael@0 306 if (NS_IsMainThread()) {
michael@0 307 if (!OKToSendIPC() || !SendPlay()) {
michael@0 308 return NS_ERROR_FAILURE;
michael@0 309 }
michael@0 310 } else {
michael@0 311 nsresult rv = NS_DispatchToMainThread(
michael@0 312 new SendIPCEvent(this, SendPlayEvent));
michael@0 313 NS_ENSURE_SUCCESS(rv, rv);
michael@0 314 }
michael@0 315
michael@0 316 return NS_OK;
michael@0 317 }
michael@0 318
michael@0 319 NS_IMETHODIMP
michael@0 320 RtspControllerChild::Pause(void)
michael@0 321 {
michael@0 322 LOG(("RtspControllerChild::Pause()"));
michael@0 323
michael@0 324 if (NS_IsMainThread()) {
michael@0 325 if (!OKToSendIPC() || !SendPause()) {
michael@0 326 return NS_ERROR_FAILURE;
michael@0 327 }
michael@0 328 } else {
michael@0 329 nsresult rv = NS_DispatchToMainThread(
michael@0 330 new SendIPCEvent(this, SendPauseEvent));
michael@0 331 NS_ENSURE_SUCCESS(rv, rv);
michael@0 332 }
michael@0 333
michael@0 334 return NS_OK;
michael@0 335 }
michael@0 336
michael@0 337 NS_IMETHODIMP
michael@0 338 RtspControllerChild::Resume(void)
michael@0 339 {
michael@0 340 LOG(("RtspControllerChild::Resume()"));
michael@0 341 NS_ENSURE_TRUE(mSuspendCount > 0, NS_ERROR_UNEXPECTED);
michael@0 342
michael@0 343 if (!--mSuspendCount) {
michael@0 344 if (NS_IsMainThread()) {
michael@0 345 if (!OKToSendIPC() || !SendResume()) {
michael@0 346 return NS_ERROR_FAILURE;
michael@0 347 }
michael@0 348 } else {
michael@0 349 nsresult rv = NS_DispatchToMainThread(
michael@0 350 new SendIPCEvent(this, SendResumeEvent));
michael@0 351 NS_ENSURE_SUCCESS(rv, rv);
michael@0 352 }
michael@0 353 }
michael@0 354
michael@0 355 return NS_OK;
michael@0 356 }
michael@0 357
michael@0 358 NS_IMETHODIMP
michael@0 359 RtspControllerChild::Suspend(void)
michael@0 360 {
michael@0 361 LOG(("RtspControllerChild::Suspend()"));
michael@0 362
michael@0 363 if (!mSuspendCount++) {
michael@0 364 if (NS_IsMainThread()) {
michael@0 365 if (!OKToSendIPC() || !SendSuspend()) {
michael@0 366 return NS_ERROR_FAILURE;
michael@0 367 }
michael@0 368 } else {
michael@0 369 nsresult rv = NS_DispatchToMainThread(
michael@0 370 new SendIPCEvent(this, SendSuspendEvent));
michael@0 371 NS_ENSURE_SUCCESS(rv, rv);
michael@0 372 }
michael@0 373 }
michael@0 374
michael@0 375 return NS_OK;
michael@0 376 }
michael@0 377
michael@0 378 NS_IMETHODIMP
michael@0 379 RtspControllerChild::Seek(uint64_t seekTimeUs)
michael@0 380 {
michael@0 381 LOG(("RtspControllerChild::Seek() %llu", seekTimeUs));
michael@0 382
michael@0 383 if (NS_IsMainThread()) {
michael@0 384 if (!OKToSendIPC() || !SendSeek(seekTimeUs)) {
michael@0 385 return NS_ERROR_FAILURE;
michael@0 386 }
michael@0 387 } else {
michael@0 388 nsresult rv = NS_DispatchToMainThread(
michael@0 389 new SendIPCEvent(this, SendSeekEvent, seekTimeUs));
michael@0 390 NS_ENSURE_SUCCESS(rv, rv);
michael@0 391 }
michael@0 392
michael@0 393 return NS_OK;
michael@0 394 }
michael@0 395
michael@0 396 NS_IMETHODIMP
michael@0 397 RtspControllerChild::Stop()
michael@0 398 {
michael@0 399 LOG(("RtspControllerChild::Stop()"));
michael@0 400
michael@0 401 if (NS_IsMainThread()) {
michael@0 402 if (!OKToSendIPC() || !SendStop()) {
michael@0 403 return NS_ERROR_FAILURE;
michael@0 404 }
michael@0 405 DisallowIPC();
michael@0 406 } else {
michael@0 407 nsresult rv = NS_DispatchToMainThread(
michael@0 408 new SendIPCEvent(this, SendStopEvent));
michael@0 409 NS_ENSURE_SUCCESS(rv, rv);
michael@0 410 }
michael@0 411
michael@0 412 return NS_OK;
michael@0 413 }
michael@0 414
michael@0 415 NS_IMETHODIMP
michael@0 416 RtspControllerChild::GetTotalTracks(uint8_t *aTracks)
michael@0 417 {
michael@0 418 NS_ENSURE_ARG_POINTER(aTracks);
michael@0 419 *aTracks = kRtspTotalTracks;
michael@0 420 if (mTotalTracks) {
michael@0 421 *aTracks = mTotalTracks;
michael@0 422 }
michael@0 423 LOG(("RtspControllerChild::GetTracks() %d", *aTracks));
michael@0 424 return NS_OK;
michael@0 425 }
michael@0 426
michael@0 427 //-----------------------------------------------------------------------------
michael@0 428 // RtspControllerChild::nsIStreamingProtocolListener
michael@0 429 //-----------------------------------------------------------------------------
michael@0 430 NS_IMETHODIMP
michael@0 431 RtspControllerChild::OnMediaDataAvailable(uint8_t index,
michael@0 432 const nsACString & data,
michael@0 433 uint32_t length,
michael@0 434 uint32_t offset,
michael@0 435 nsIStreamingProtocolMetaData *meta)
michael@0 436 {
michael@0 437 LOG(("RtspControllerChild::OnMediaDataAvailable()"));
michael@0 438 return NS_ERROR_NOT_IMPLEMENTED;
michael@0 439 }
michael@0 440
michael@0 441 NS_IMETHODIMP
michael@0 442 RtspControllerChild::OnConnected(uint8_t index,
michael@0 443 nsIStreamingProtocolMetaData *meta)
michael@0 444
michael@0 445 {
michael@0 446 LOG(("RtspControllerChild::OnConnected()"));
michael@0 447 return NS_ERROR_NOT_IMPLEMENTED;
michael@0 448 }
michael@0 449
michael@0 450 NS_IMETHODIMP
michael@0 451 RtspControllerChild::OnDisconnected(uint8_t index,
michael@0 452 nsresult reason)
michael@0 453 {
michael@0 454 LOG(("RtspControllerChild::OnDisconnected() reason = 0x%x", reason));
michael@0 455 return NS_ERROR_NOT_IMPLEMENTED;
michael@0 456 }
michael@0 457
michael@0 458 //-----------------------------------------------------------------------------
michael@0 459 // RtspControllerChild::nsIStreamingProtocoController
michael@0 460 //-----------------------------------------------------------------------------
michael@0 461 NS_IMETHODIMP
michael@0 462 RtspControllerChild::Init(nsIURI *aURI)
michael@0 463 {
michael@0 464 nsresult rv;
michael@0 465
michael@0 466 if (!aURI) {
michael@0 467 LOG(("RtspControllerChild::Init() - invalid URI"));
michael@0 468 return NS_ERROR_NOT_INITIALIZED;
michael@0 469 }
michael@0 470
michael@0 471 nsAutoCString host;
michael@0 472 int32_t port = -1;
michael@0 473
michael@0 474 rv = aURI->GetAsciiHost(host);
michael@0 475 if (NS_FAILED(rv)) return rv;
michael@0 476
michael@0 477 // Reject the URL if it doesn't specify a host
michael@0 478 if (host.IsEmpty())
michael@0 479 return NS_ERROR_MALFORMED_URI;
michael@0 480
michael@0 481 rv = aURI->GetPort(&port);
michael@0 482 if (NS_FAILED(rv)) return rv;
michael@0 483
michael@0 484 rv = aURI->GetAsciiSpec(mSpec);
michael@0 485 if (NS_FAILED(rv)) return rv;
michael@0 486
michael@0 487 if (!strncmp(mSpec.get(), "rtsp:", 5) == 0)
michael@0 488 return NS_ERROR_UNEXPECTED;
michael@0 489
michael@0 490 mURI = aURI;
michael@0 491
michael@0 492 return NS_OK;
michael@0 493 }
michael@0 494
michael@0 495 NS_IMETHODIMP
michael@0 496 RtspControllerChild::AsyncOpen(nsIStreamingProtocolListener *aListener)
michael@0 497 {
michael@0 498 LOG(("RtspControllerChild::AsyncOpen()"));
michael@0 499 if (!aListener) {
michael@0 500 LOG(("RtspControllerChild::AsyncOpen() - invalid listener"));
michael@0 501 return NS_ERROR_NOT_INITIALIZED;
michael@0 502 }
michael@0 503 mListener = aListener;
michael@0 504
michael@0 505 if (!mChannel) {
michael@0 506 LOG(("RtspControllerChild::AsyncOpen() - invalid URI"));
michael@0 507 return NS_ERROR_NOT_INITIALIZED;
michael@0 508 }
michael@0 509
michael@0 510 nsCOMPtr<nsIURI> uri;
michael@0 511 URIParams uriParams;
michael@0 512 mChannel->GetURI(getter_AddRefs(uri));
michael@0 513 if (!uri) {
michael@0 514 LOG(("RtspControllerChild::AsyncOpen() - invalid URI"));
michael@0 515 return NS_ERROR_NOT_INITIALIZED;
michael@0 516 }
michael@0 517 SerializeURI(uri, uriParams);
michael@0 518
michael@0 519 if (!OKToSendIPC() || !SendAsyncOpen(uriParams)) {
michael@0 520 return NS_ERROR_FAILURE;
michael@0 521 }
michael@0 522 return NS_OK;
michael@0 523 }
michael@0 524
michael@0 525 } // namespace net
michael@0 526 } // namespace mozilla

mercurial