netwerk/protocol/rtsp/controller/RtspController.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 "RtspController.h"
michael@0 8 #include "RtspMetaData.h"
michael@0 9 #include "nsIURI.h"
michael@0 10 #include "nsICryptoHash.h"
michael@0 11 #include "nsIRunnable.h"
michael@0 12 #include "nsIPrefBranch.h"
michael@0 13 #include "nsIPrefService.h"
michael@0 14 #include "nsICancelable.h"
michael@0 15 #include "nsIStreamConverterService.h"
michael@0 16 #include "nsIIOService2.h"
michael@0 17 #include "nsIProtocolProxyService.h"
michael@0 18 #include "nsIProxyInfo.h"
michael@0 19 #include "nsIProxiedChannel.h"
michael@0 20
michael@0 21 #include "nsAutoPtr.h"
michael@0 22 #include "nsStandardURL.h"
michael@0 23 #include "nsNetCID.h"
michael@0 24 #include "nsServiceManagerUtils.h"
michael@0 25 #include "nsXPIDLString.h"
michael@0 26 #include "nsCRT.h"
michael@0 27 #include "nsThreadUtils.h"
michael@0 28 #include "nsError.h"
michael@0 29 #include "nsStringStream.h"
michael@0 30 #include "nsAlgorithm.h"
michael@0 31 #include "nsProxyRelease.h"
michael@0 32 #include "nsNetUtil.h"
michael@0 33 #include "mozilla/Attributes.h"
michael@0 34 #include "mozilla/Telemetry.h"
michael@0 35 #include "mozilla/TimeStamp.h"
michael@0 36 #include "prlog.h"
michael@0 37
michael@0 38 #include "plbase64.h"
michael@0 39 #include "prmem.h"
michael@0 40 #include "prnetdb.h"
michael@0 41 #include "zlib.h"
michael@0 42 #include <algorithm>
michael@0 43 #include "nsDebug.h"
michael@0 44
michael@0 45 extern PRLogModuleInfo* gRtspLog;
michael@0 46 #undef LOG
michael@0 47 #define LOG(args) PR_LOG(gRtspLog, PR_LOG_DEBUG, args)
michael@0 48
michael@0 49 namespace mozilla {
michael@0 50 namespace net {
michael@0 51
michael@0 52 NS_IMPL_ISUPPORTS(RtspController,
michael@0 53 nsIStreamingProtocolController)
michael@0 54
michael@0 55 RtspController::RtspController(nsIChannel *channel)
michael@0 56 : mState(INIT)
michael@0 57 {
michael@0 58 LOG(("RtspController::RtspController()"));
michael@0 59 }
michael@0 60
michael@0 61 RtspController::~RtspController()
michael@0 62 {
michael@0 63 LOG(("RtspController::~RtspController()"));
michael@0 64 if (mRtspSource.get()) {
michael@0 65 mRtspSource.clear();
michael@0 66 }
michael@0 67 }
michael@0 68
michael@0 69 NS_IMETHODIMP
michael@0 70 RtspController::GetTrackMetaData(uint8_t index,
michael@0 71 nsIStreamingProtocolMetaData * *_retval)
michael@0 72 {
michael@0 73 LOG(("RtspController::GetTrackMetaData()"));
michael@0 74 return NS_OK;
michael@0 75 }
michael@0 76
michael@0 77 NS_IMETHODIMP
michael@0 78 RtspController::Play(void)
michael@0 79 {
michael@0 80 LOG(("RtspController::Play()"));
michael@0 81 if (!mRtspSource.get()) {
michael@0 82 MOZ_ASSERT(mRtspSource.get(), "mRtspSource should not be null!");
michael@0 83 return NS_ERROR_NOT_INITIALIZED;
michael@0 84 }
michael@0 85
michael@0 86 if (mState != CONNECTED) {
michael@0 87 return NS_ERROR_NOT_CONNECTED;
michael@0 88 }
michael@0 89
michael@0 90 mRtspSource->play();
michael@0 91 return NS_OK;
michael@0 92 }
michael@0 93
michael@0 94 NS_IMETHODIMP
michael@0 95 RtspController::Pause(void)
michael@0 96 {
michael@0 97 LOG(("RtspController::Pause()"));
michael@0 98 if (!mRtspSource.get()) {
michael@0 99 MOZ_ASSERT(mRtspSource.get(), "mRtspSource should not be null!");
michael@0 100 return NS_ERROR_NOT_INITIALIZED;
michael@0 101 }
michael@0 102
michael@0 103 if (mState != CONNECTED) {
michael@0 104 return NS_ERROR_NOT_CONNECTED;
michael@0 105 }
michael@0 106
michael@0 107 mRtspSource->pause();
michael@0 108 return NS_OK;
michael@0 109 }
michael@0 110
michael@0 111 NS_IMETHODIMP
michael@0 112 RtspController::Resume(void)
michael@0 113 {
michael@0 114 LOG(("RtspController::Resume()"));
michael@0 115 if (!mRtspSource.get()) {
michael@0 116 MOZ_ASSERT(mRtspSource.get(), "mRtspSource should not be null!");
michael@0 117 return NS_ERROR_NOT_INITIALIZED;
michael@0 118 }
michael@0 119
michael@0 120 if (mState != CONNECTED) {
michael@0 121 return NS_ERROR_NOT_CONNECTED;
michael@0 122 }
michael@0 123
michael@0 124 mRtspSource->play();
michael@0 125 return NS_OK;
michael@0 126 }
michael@0 127
michael@0 128 NS_IMETHODIMP
michael@0 129 RtspController::Suspend(void)
michael@0 130 {
michael@0 131 LOG(("RtspController::Suspend()"));
michael@0 132 if (!mRtspSource.get()) {
michael@0 133 MOZ_ASSERT(mRtspSource.get(), "mRtspSource should not be null!");
michael@0 134 return NS_ERROR_NOT_INITIALIZED;
michael@0 135 }
michael@0 136
michael@0 137 if (mState != CONNECTED) {
michael@0 138 return NS_ERROR_NOT_CONNECTED;
michael@0 139 }
michael@0 140
michael@0 141 mRtspSource->pause();
michael@0 142 return NS_OK;
michael@0 143 }
michael@0 144
michael@0 145 NS_IMETHODIMP
michael@0 146 RtspController::Seek(uint64_t seekTimeUs)
michael@0 147 {
michael@0 148 LOG(("RtspController::Seek() %llu", seekTimeUs));
michael@0 149 if (!mRtspSource.get()) {
michael@0 150 MOZ_ASSERT(mRtspSource.get(), "mRtspSource should not be null!");
michael@0 151 return NS_ERROR_NOT_INITIALIZED;
michael@0 152 }
michael@0 153
michael@0 154 if (mState != CONNECTED) {
michael@0 155 return NS_ERROR_NOT_CONNECTED;
michael@0 156 }
michael@0 157
michael@0 158 mRtspSource->seek(seekTimeUs);
michael@0 159 return NS_OK;
michael@0 160 }
michael@0 161
michael@0 162 NS_IMETHODIMP
michael@0 163 RtspController::Stop()
michael@0 164 {
michael@0 165 LOG(("RtspController::Stop()"));
michael@0 166 mState = INIT;
michael@0 167 if (!mRtspSource.get()) {
michael@0 168 MOZ_ASSERT(mRtspSource.get(), "mRtspSource should not be null!");
michael@0 169 return NS_ERROR_NOT_INITIALIZED;
michael@0 170 }
michael@0 171
michael@0 172 mRtspSource->stop();
michael@0 173 return NS_OK;
michael@0 174 }
michael@0 175
michael@0 176 NS_IMETHODIMP
michael@0 177 RtspController::GetTotalTracks(uint8_t *aTracks)
michael@0 178 {
michael@0 179 LOG(("RtspController::GetTotalTracks()"));
michael@0 180 return NS_ERROR_NOT_IMPLEMENTED;
michael@0 181 }
michael@0 182
michael@0 183 NS_IMETHODIMP
michael@0 184 RtspController::AsyncOpen(nsIStreamingProtocolListener *aListener)
michael@0 185 {
michael@0 186 if (!aListener) {
michael@0 187 LOG(("RtspController::AsyncOpen() illegal listener"));
michael@0 188 return NS_ERROR_NOT_INITIALIZED;
michael@0 189 }
michael@0 190
michael@0 191 mListener = aListener;
michael@0 192
michael@0 193 if (!mURI) {
michael@0 194 LOG(("RtspController::AsyncOpen() illegal URI"));
michael@0 195 return NS_ERROR_ILLEGAL_VALUE;
michael@0 196 }
michael@0 197
michael@0 198 nsAutoCString uriSpec;
michael@0 199 mURI->GetSpec(uriSpec);
michael@0 200 LOG(("RtspController AsyncOpen uri=%s", uriSpec.get()));
michael@0 201
michael@0 202 if (!mRtspSource.get()) {
michael@0 203 mRtspSource = new android::RTSPSource(this, uriSpec.get(), false, 0);
michael@0 204 }
michael@0 205 // Connect to Rtsp Server.
michael@0 206 mRtspSource->start();
michael@0 207
michael@0 208 return NS_OK;
michael@0 209 }
michael@0 210
michael@0 211 class SendMediaDataTask : public nsRunnable
michael@0 212 {
michael@0 213 public:
michael@0 214 SendMediaDataTask(nsIStreamingProtocolListener *listener,
michael@0 215 uint8_t index,
michael@0 216 const nsACString & data,
michael@0 217 uint32_t length,
michael@0 218 uint32_t offset,
michael@0 219 nsIStreamingProtocolMetaData *meta)
michael@0 220 : mIndex(index)
michael@0 221 , mLength(length)
michael@0 222 , mOffset(offset)
michael@0 223 , mMetaData(meta)
michael@0 224 , mListener(listener)
michael@0 225 {
michael@0 226 mData.Assign(data);
michael@0 227 }
michael@0 228
michael@0 229 NS_IMETHOD Run()
michael@0 230 {
michael@0 231 MOZ_ASSERT(NS_IsMainThread());
michael@0 232 mListener->OnMediaDataAvailable(mIndex, mData, mLength,
michael@0 233 mOffset, mMetaData);
michael@0 234 return NS_OK;
michael@0 235 }
michael@0 236
michael@0 237 private:
michael@0 238 uint8_t mIndex;
michael@0 239 nsCString mData;
michael@0 240 uint32_t mLength;
michael@0 241 uint32_t mOffset;
michael@0 242 nsRefPtr<nsIStreamingProtocolMetaData> mMetaData;
michael@0 243 nsCOMPtr<nsIStreamingProtocolListener> mListener;
michael@0 244 };
michael@0 245
michael@0 246 NS_IMETHODIMP
michael@0 247 RtspController::OnMediaDataAvailable(uint8_t index,
michael@0 248 const nsACString & data,
michael@0 249 uint32_t length,
michael@0 250 uint32_t offset,
michael@0 251 nsIStreamingProtocolMetaData *meta)
michael@0 252 {
michael@0 253 if (mListener && mState == CONNECTED) {
michael@0 254 nsRefPtr<SendMediaDataTask> task =
michael@0 255 new SendMediaDataTask(mListener, index, data, length, offset, meta);
michael@0 256 return NS_DispatchToMainThread(task);
michael@0 257 }
michael@0 258 return NS_ERROR_NOT_AVAILABLE;
michael@0 259 }
michael@0 260
michael@0 261 class SendOnConnectedTask : public nsRunnable
michael@0 262 {
michael@0 263 public:
michael@0 264 SendOnConnectedTask(nsIStreamingProtocolListener *listener,
michael@0 265 uint8_t index,
michael@0 266 nsIStreamingProtocolMetaData *meta)
michael@0 267 : mListener(listener)
michael@0 268 , mIndex(index)
michael@0 269 , mMetaData(meta)
michael@0 270 { }
michael@0 271
michael@0 272 NS_IMETHOD Run()
michael@0 273 {
michael@0 274 MOZ_ASSERT(NS_IsMainThread());
michael@0 275 mListener->OnConnected(mIndex, mMetaData);
michael@0 276 return NS_OK;
michael@0 277 }
michael@0 278
michael@0 279 private:
michael@0 280 nsCOMPtr<nsIStreamingProtocolListener> mListener;
michael@0 281 uint8_t mIndex;
michael@0 282 nsRefPtr<nsIStreamingProtocolMetaData> mMetaData;
michael@0 283 };
michael@0 284
michael@0 285
michael@0 286 NS_IMETHODIMP
michael@0 287 RtspController::OnConnected(uint8_t index,
michael@0 288 nsIStreamingProtocolMetaData *meta)
michael@0 289 {
michael@0 290 LOG(("RtspController::OnConnected()"));
michael@0 291 mState = CONNECTED;
michael@0 292 if (mListener) {
michael@0 293 nsRefPtr<SendOnConnectedTask> task =
michael@0 294 new SendOnConnectedTask(mListener, index, meta);
michael@0 295 return NS_DispatchToMainThread(task);
michael@0 296 }
michael@0 297 return NS_ERROR_NOT_AVAILABLE;
michael@0 298 }
michael@0 299
michael@0 300 class SendOnDisconnectedTask : public nsRunnable
michael@0 301 {
michael@0 302 public:
michael@0 303 SendOnDisconnectedTask(nsIStreamingProtocolListener *listener,
michael@0 304 uint8_t index,
michael@0 305 nsresult reason)
michael@0 306 : mListener(listener)
michael@0 307 , mIndex(index)
michael@0 308 , mReason(reason)
michael@0 309 { }
michael@0 310
michael@0 311 NS_IMETHOD Run()
michael@0 312 {
michael@0 313 MOZ_ASSERT(NS_IsMainThread());
michael@0 314 mListener->OnDisconnected(mIndex, mReason);
michael@0 315 return NS_OK;
michael@0 316 }
michael@0 317
michael@0 318 private:
michael@0 319 nsCOMPtr<nsIStreamingProtocolListener> mListener;
michael@0 320 uint8_t mIndex;
michael@0 321 nsresult mReason;
michael@0 322 };
michael@0 323
michael@0 324 NS_IMETHODIMP
michael@0 325 RtspController::OnDisconnected(uint8_t index,
michael@0 326 nsresult reason)
michael@0 327 {
michael@0 328 LOG(("RtspController::OnDisconnected() for track %d reason = 0x%x", index, reason));
michael@0 329 mState = DISCONNECTED;
michael@0 330 if (mListener) {
michael@0 331 nsRefPtr<SendOnDisconnectedTask> task =
michael@0 332 new SendOnDisconnectedTask(mListener, index, reason);
michael@0 333 // Break the cycle reference between the Listener (RtspControllerParent) and
michael@0 334 // us.
michael@0 335 mListener = nullptr;
michael@0 336 return NS_DispatchToMainThread(task);
michael@0 337 }
michael@0 338 return NS_ERROR_NOT_AVAILABLE;
michael@0 339 }
michael@0 340
michael@0 341 NS_IMETHODIMP
michael@0 342 RtspController::Init(nsIURI *aURI)
michael@0 343 {
michael@0 344 nsresult rv;
michael@0 345
michael@0 346 if (!aURI) {
michael@0 347 LOG(("RtspController::Init() - invalid URI"));
michael@0 348 return NS_ERROR_NOT_INITIALIZED;
michael@0 349 }
michael@0 350
michael@0 351 nsAutoCString host;
michael@0 352 int32_t port = -1;
michael@0 353
michael@0 354 rv = aURI->GetAsciiHost(host);
michael@0 355 if (NS_FAILED(rv)) return rv;
michael@0 356
michael@0 357 // Reject the URL if it doesn't specify a host
michael@0 358 if (host.IsEmpty())
michael@0 359 return NS_ERROR_MALFORMED_URI;
michael@0 360
michael@0 361 rv = aURI->GetPort(&port);
michael@0 362 if (NS_FAILED(rv)) return rv;
michael@0 363
michael@0 364 rv = aURI->GetAsciiSpec(mSpec);
michael@0 365 if (NS_FAILED(rv)) return rv;
michael@0 366
michael@0 367 mURI = aURI;
michael@0 368
michael@0 369 return NS_OK;
michael@0 370 }
michael@0 371
michael@0 372 } // namespace mozilla::net
michael@0 373 } // namespace mozilla

mercurial