netwerk/test/TestProtocols.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* vim: set ts=2 sw=2 et cindent: */
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 /*
michael@0 8 The TestProtocols tests the basic protocols architecture and can
michael@0 9 be used to test individual protocols as well. If this grows too
michael@0 10 big then we should split it to individual protocols.
michael@0 11
michael@0 12 -Gagan Saksena 04/29/99
michael@0 13 */
michael@0 14
michael@0 15 #include "TestCommon.h"
michael@0 16 #include <algorithm>
michael@0 17
michael@0 18 #define FORCE_PR_LOG
michael@0 19 #include <stdio.h>
michael@0 20 #ifdef WIN32
michael@0 21 #include <windows.h>
michael@0 22 #endif
michael@0 23 #ifdef XP_UNIX
michael@0 24 #include <unistd.h>
michael@0 25 #endif
michael@0 26 #include "nspr.h"
michael@0 27 #include "nscore.h"
michael@0 28 #include "nsCOMPtr.h"
michael@0 29 #include "nsIIOService.h"
michael@0 30 #include "nsIServiceManager.h"
michael@0 31 #include "nsIStreamListener.h"
michael@0 32 #include "nsIInputStream.h"
michael@0 33 #include "nsIInputStream.h"
michael@0 34 #include "nsCRT.h"
michael@0 35 #include "nsIChannel.h"
michael@0 36 #include "nsIResumableChannel.h"
michael@0 37 #include "nsIURL.h"
michael@0 38 #include "nsIHttpChannel.h"
michael@0 39 #include "nsIHttpChannelInternal.h"
michael@0 40 #include "nsIHttpHeaderVisitor.h"
michael@0 41 #include "nsIChannelEventSink.h"
michael@0 42 #include "nsIAsyncVerifyRedirectCallback.h"
michael@0 43 #include "nsIInterfaceRequestor.h"
michael@0 44 #include "nsIInterfaceRequestorUtils.h"
michael@0 45 #include "nsIDNSService.h"
michael@0 46 #include "nsIAuthPrompt.h"
michael@0 47 #include "nsIPrefService.h"
michael@0 48 #include "nsIPrefBranch.h"
michael@0 49 #include "nsIPropertyBag2.h"
michael@0 50 #include "nsIWritablePropertyBag2.h"
michael@0 51 #include "nsITimedChannel.h"
michael@0 52 #include "nsChannelProperties.h"
michael@0 53 #include "mozilla/Attributes.h"
michael@0 54 #include "mozilla/unused.h"
michael@0 55
michael@0 56 #include "nsISimpleEnumerator.h"
michael@0 57 #include "nsStringAPI.h"
michael@0 58 #include "nsNetUtil.h"
michael@0 59 #include "prlog.h"
michael@0 60
michael@0 61 using namespace mozilla;
michael@0 62
michael@0 63 namespace TestProtocols {
michael@0 64
michael@0 65 #if defined(PR_LOGGING)
michael@0 66 //
michael@0 67 // set NSPR_LOG_MODULES=Test:5
michael@0 68 //
michael@0 69 static PRLogModuleInfo *gTestLog = nullptr;
michael@0 70 #endif
michael@0 71 #define LOG(args) PR_LOG(gTestLog, PR_LOG_DEBUG, args)
michael@0 72
michael@0 73 static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
michael@0 74
michael@0 75 //static PRTime gElapsedTime; // enable when we time it...
michael@0 76 static int gKeepRunning = 0;
michael@0 77 static bool gVerbose = false;
michael@0 78 static bool gAskUserForInput = false;
michael@0 79 static bool gResume = false;
michael@0 80 static uint64_t gStartAt = 0;
michael@0 81
michael@0 82 static const char* gEntityID;
michael@0 83
michael@0 84 //-----------------------------------------------------------------------------
michael@0 85 // Set proxy preferences for testing
michael@0 86 //-----------------------------------------------------------------------------
michael@0 87
michael@0 88 static nsresult
michael@0 89 SetHttpProxy(const char *proxy)
michael@0 90 {
michael@0 91 const char *colon = strchr(proxy, ':');
michael@0 92 if (!colon)
michael@0 93 {
michael@0 94 NS_WARNING("invalid proxy token; use host:port");
michael@0 95 return NS_ERROR_UNEXPECTED;
michael@0 96 }
michael@0 97 int port = atoi(colon + 1);
michael@0 98 if (port == 0)
michael@0 99 {
michael@0 100 NS_WARNING("invalid proxy port; must be an integer");
michael@0 101 return NS_ERROR_UNEXPECTED;
michael@0 102 }
michael@0 103 nsAutoCString proxyHost;
michael@0 104 proxyHost = Substring(proxy, colon);
michael@0 105
michael@0 106 nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
michael@0 107 if (prefs)
michael@0 108 {
michael@0 109 prefs->SetCharPref("network.proxy.http", proxyHost.get());
michael@0 110 prefs->SetIntPref("network.proxy.http_port", port);
michael@0 111 prefs->SetIntPref("network.proxy.type", 1); // manual proxy config
michael@0 112 }
michael@0 113 LOG(("connecting via proxy=%s:%d\n", proxyHost.get(), port));
michael@0 114 return NS_OK;
michael@0 115 }
michael@0 116
michael@0 117 static nsresult
michael@0 118 SetPACFile(const char* pacURL)
michael@0 119 {
michael@0 120 nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
michael@0 121 if (prefs)
michael@0 122 {
michael@0 123 prefs->SetCharPref("network.proxy.autoconfig_url", pacURL);
michael@0 124 prefs->SetIntPref("network.proxy.type", 2); // PAC file
michael@0 125 }
michael@0 126 LOG(("connecting using PAC file %s\n", pacURL));
michael@0 127 return NS_OK;
michael@0 128 }
michael@0 129
michael@0 130 //-----------------------------------------------------------------------------
michael@0 131 // Timing information
michael@0 132 //-----------------------------------------------------------------------------
michael@0 133
michael@0 134 void PrintTimingInformation(nsITimedChannel* channel) {
michael@0 135 #define PRINT_VALUE(property) \
michael@0 136 { \
michael@0 137 PRTime value; \
michael@0 138 channel->Get##property(&value); \
michael@0 139 if (value) { \
michael@0 140 PRExplodedTime exploded; \
michael@0 141 PR_ExplodeTime(value, PR_LocalTimeParameters, &exploded); \
michael@0 142 char buf[256]; \
michael@0 143 PR_FormatTime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", &exploded); \
michael@0 144 LOG((" " #property ":\t%s (%i usec)", buf, exploded.tm_usec)); \
michael@0 145 } else { \
michael@0 146 LOG((" " #property ":\t0")); \
michael@0 147 } \
michael@0 148 }
michael@0 149 LOG(("Timing data:"));
michael@0 150 PRINT_VALUE(ChannelCreationTime)
michael@0 151 PRINT_VALUE(AsyncOpenTime)
michael@0 152 PRINT_VALUE(DomainLookupStartTime)
michael@0 153 PRINT_VALUE(DomainLookupEndTime)
michael@0 154 PRINT_VALUE(ConnectStartTime)
michael@0 155 PRINT_VALUE(ConnectEndTime)
michael@0 156 PRINT_VALUE(RequestStartTime)
michael@0 157 PRINT_VALUE(ResponseStartTime)
michael@0 158 PRINT_VALUE(ResponseEndTime)
michael@0 159 PRINT_VALUE(CacheReadStartTime)
michael@0 160 PRINT_VALUE(CacheReadEndTime)
michael@0 161 }
michael@0 162
michael@0 163 //-----------------------------------------------------------------------------
michael@0 164 // HeaderVisitor
michael@0 165 //-----------------------------------------------------------------------------
michael@0 166
michael@0 167 class HeaderVisitor : public nsIHttpHeaderVisitor
michael@0 168 {
michael@0 169 public:
michael@0 170 NS_DECL_ISUPPORTS
michael@0 171 NS_DECL_NSIHTTPHEADERVISITOR
michael@0 172
michael@0 173 HeaderVisitor() { }
michael@0 174 virtual ~HeaderVisitor() {}
michael@0 175 };
michael@0 176 NS_IMPL_ISUPPORTS(HeaderVisitor, nsIHttpHeaderVisitor)
michael@0 177
michael@0 178 NS_IMETHODIMP
michael@0 179 HeaderVisitor::VisitHeader(const nsACString &header, const nsACString &value)
michael@0 180 {
michael@0 181 LOG((" %s: %s\n",
michael@0 182 PromiseFlatCString(header).get(),
michael@0 183 PromiseFlatCString(value).get()));
michael@0 184 return NS_OK;
michael@0 185 }
michael@0 186
michael@0 187 //-----------------------------------------------------------------------------
michael@0 188 // URLLoadInfo
michael@0 189 //-----------------------------------------------------------------------------
michael@0 190
michael@0 191 class URLLoadInfo : public nsISupports
michael@0 192 {
michael@0 193 public:
michael@0 194
michael@0 195 URLLoadInfo(const char* aUrl);
michael@0 196 virtual ~URLLoadInfo();
michael@0 197
michael@0 198 // ISupports interface...
michael@0 199 NS_DECL_THREADSAFE_ISUPPORTS
michael@0 200
michael@0 201 const char* Name() { return mURLString.get(); }
michael@0 202 int64_t mBytesRead;
michael@0 203 PRTime mTotalTime;
michael@0 204 PRTime mConnectTime;
michael@0 205 nsCString mURLString;
michael@0 206 };
michael@0 207
michael@0 208 URLLoadInfo::URLLoadInfo(const char *aUrl) : mURLString(aUrl)
michael@0 209 {
michael@0 210 mBytesRead = 0;
michael@0 211 mConnectTime = mTotalTime = PR_Now();
michael@0 212 }
michael@0 213
michael@0 214 URLLoadInfo::~URLLoadInfo()
michael@0 215 {
michael@0 216 }
michael@0 217
michael@0 218
michael@0 219 NS_IMPL_ISUPPORTS0(URLLoadInfo)
michael@0 220
michael@0 221 //-----------------------------------------------------------------------------
michael@0 222 // TestChannelEventSink
michael@0 223 //-----------------------------------------------------------------------------
michael@0 224
michael@0 225 class TestChannelEventSink : public nsIChannelEventSink
michael@0 226 {
michael@0 227 public:
michael@0 228 NS_DECL_ISUPPORTS
michael@0 229 NS_DECL_NSICHANNELEVENTSINK
michael@0 230
michael@0 231 TestChannelEventSink();
michael@0 232 virtual ~TestChannelEventSink();
michael@0 233 };
michael@0 234
michael@0 235 TestChannelEventSink::TestChannelEventSink()
michael@0 236 {
michael@0 237 }
michael@0 238
michael@0 239 TestChannelEventSink::~TestChannelEventSink()
michael@0 240 {
michael@0 241 }
michael@0 242
michael@0 243
michael@0 244 NS_IMPL_ISUPPORTS(TestChannelEventSink, nsIChannelEventSink)
michael@0 245
michael@0 246 NS_IMETHODIMP
michael@0 247 TestChannelEventSink::AsyncOnChannelRedirect(nsIChannel *channel,
michael@0 248 nsIChannel *newChannel,
michael@0 249 uint32_t flags,
michael@0 250 nsIAsyncVerifyRedirectCallback *callback)
michael@0 251 {
michael@0 252 LOG(("\n+++ TestChannelEventSink::OnChannelRedirect (with flags %x) +++\n",
michael@0 253 flags));
michael@0 254 callback->OnRedirectVerifyCallback(NS_OK);
michael@0 255 return NS_OK;
michael@0 256 }
michael@0 257
michael@0 258 //-----------------------------------------------------------------------------
michael@0 259 // TestAuthPrompt
michael@0 260 //-----------------------------------------------------------------------------
michael@0 261
michael@0 262 class TestAuthPrompt : public nsIAuthPrompt
michael@0 263 {
michael@0 264 public:
michael@0 265 NS_DECL_ISUPPORTS
michael@0 266 NS_DECL_NSIAUTHPROMPT
michael@0 267
michael@0 268 TestAuthPrompt();
michael@0 269 virtual ~TestAuthPrompt();
michael@0 270 };
michael@0 271
michael@0 272 NS_IMPL_ISUPPORTS(TestAuthPrompt, nsIAuthPrompt)
michael@0 273
michael@0 274 TestAuthPrompt::TestAuthPrompt()
michael@0 275 {
michael@0 276 }
michael@0 277
michael@0 278 TestAuthPrompt::~TestAuthPrompt()
michael@0 279 {
michael@0 280 }
michael@0 281
michael@0 282 NS_IMETHODIMP
michael@0 283 TestAuthPrompt::Prompt(const char16_t *dialogTitle,
michael@0 284 const char16_t *text,
michael@0 285 const char16_t *passwordRealm,
michael@0 286 uint32_t savePassword,
michael@0 287 const char16_t *defaultText,
michael@0 288 char16_t **result,
michael@0 289 bool *_retval)
michael@0 290 {
michael@0 291 *_retval = false;
michael@0 292 return NS_ERROR_NOT_IMPLEMENTED;
michael@0 293 }
michael@0 294
michael@0 295 NS_IMETHODIMP
michael@0 296 TestAuthPrompt::PromptUsernameAndPassword(const char16_t *dialogTitle,
michael@0 297 const char16_t *dialogText,
michael@0 298 const char16_t *passwordRealm,
michael@0 299 uint32_t savePassword,
michael@0 300 char16_t **user,
michael@0 301 char16_t **pwd,
michael@0 302 bool *_retval)
michael@0 303 {
michael@0 304 NS_ConvertUTF16toUTF8 text(passwordRealm);
michael@0 305 printf("* --------------------------------------------------------------------------- *\n");
michael@0 306 printf("* Authentication Required [%s]\n", text.get());
michael@0 307 printf("* --------------------------------------------------------------------------- *\n");
michael@0 308
michael@0 309 char buf[256];
michael@0 310 int n;
michael@0 311
michael@0 312 printf("Enter username: ");
michael@0 313 unused << fgets(buf, sizeof(buf), stdin);
michael@0 314 n = strlen(buf);
michael@0 315 buf[n-1] = '\0'; // trim trailing newline
michael@0 316 *user = NS_StringCloneData(NS_ConvertUTF8toUTF16(buf));
michael@0 317
michael@0 318 const char *p;
michael@0 319 #if defined(XP_UNIX) && !defined(ANDROID)
michael@0 320 p = getpass("Enter password: ");
michael@0 321 #else
michael@0 322 printf("Enter password: ");
michael@0 323 fgets(buf, sizeof(buf), stdin);
michael@0 324 n = strlen(buf);
michael@0 325 buf[n-1] = '\0'; // trim trailing newline
michael@0 326 p = buf;
michael@0 327 #endif
michael@0 328 *pwd = NS_StringCloneData(NS_ConvertUTF8toUTF16(p));
michael@0 329
michael@0 330 // zap buf
michael@0 331 memset(buf, 0, sizeof(buf));
michael@0 332
michael@0 333 *_retval = true;
michael@0 334 return NS_OK;
michael@0 335 }
michael@0 336
michael@0 337 NS_IMETHODIMP
michael@0 338 TestAuthPrompt::PromptPassword(const char16_t *dialogTitle,
michael@0 339 const char16_t *text,
michael@0 340 const char16_t *passwordRealm,
michael@0 341 uint32_t savePassword,
michael@0 342 char16_t **pwd,
michael@0 343 bool *_retval)
michael@0 344 {
michael@0 345 *_retval = false;
michael@0 346 return NS_ERROR_NOT_IMPLEMENTED;
michael@0 347 }
michael@0 348
michael@0 349 //-----------------------------------------------------------------------------
michael@0 350 // InputTestConsumer
michael@0 351 //-----------------------------------------------------------------------------
michael@0 352
michael@0 353 class InputTestConsumer : public nsIStreamListener
michael@0 354 {
michael@0 355 public:
michael@0 356
michael@0 357 InputTestConsumer();
michael@0 358 virtual ~InputTestConsumer();
michael@0 359
michael@0 360 NS_DECL_ISUPPORTS
michael@0 361 NS_DECL_NSIREQUESTOBSERVER
michael@0 362 NS_DECL_NSISTREAMLISTENER
michael@0 363 };
michael@0 364
michael@0 365 InputTestConsumer::InputTestConsumer()
michael@0 366 {
michael@0 367 }
michael@0 368
michael@0 369 InputTestConsumer::~InputTestConsumer()
michael@0 370 {
michael@0 371 }
michael@0 372
michael@0 373 NS_IMPL_ISUPPORTS(InputTestConsumer, nsIStreamListener, nsIRequestObserver)
michael@0 374
michael@0 375 NS_IMETHODIMP
michael@0 376 InputTestConsumer::OnStartRequest(nsIRequest *request, nsISupports* context)
michael@0 377 {
michael@0 378 LOG(("InputTestConsumer::OnStartRequest\n"));
michael@0 379
michael@0 380 URLLoadInfo* info = (URLLoadInfo*)context;
michael@0 381 if (info)
michael@0 382 info->mConnectTime = PR_Now() - info->mConnectTime;
michael@0 383
michael@0 384 if (gVerbose) {
michael@0 385 LOG(("\nStarted loading: %s\n", info ? info->Name() : "UNKNOWN URL"));
michael@0 386 }
michael@0 387
michael@0 388 nsAutoCString value;
michael@0 389
michael@0 390 nsCOMPtr<nsIChannel> channel = do_QueryInterface(request);
michael@0 391 if (channel) {
michael@0 392 nsresult status;
michael@0 393 channel->GetStatus(&status);
michael@0 394 LOG(("Channel Status: %08x\n", status));
michael@0 395 if (NS_SUCCEEDED(status)) {
michael@0 396 LOG(("Channel Info:\n"));
michael@0 397
michael@0 398 channel->GetName(value);
michael@0 399 LOG(("\tName: %s\n", value.get()));
michael@0 400
michael@0 401 channel->GetContentType(value);
michael@0 402 LOG(("\tContent-Type: %s\n", value.get()));
michael@0 403
michael@0 404 channel->GetContentCharset(value);
michael@0 405 LOG(("\tContent-Charset: %s\n", value.get()));
michael@0 406
michael@0 407 int64_t length = -1;
michael@0 408 if (NS_SUCCEEDED(channel->GetContentLength(&length))) {
michael@0 409 LOG(("\tContent-Length: %lld\n", length));
michael@0 410 } else {
michael@0 411 LOG(("\tContent-Length: Unknown\n"));
michael@0 412 }
michael@0 413 }
michael@0 414
michael@0 415 nsCOMPtr<nsISupports> owner;
michael@0 416 channel->GetOwner(getter_AddRefs(owner));
michael@0 417 LOG(("\tChannel Owner: %x\n", owner.get()));
michael@0 418 }
michael@0 419
michael@0 420 nsCOMPtr<nsIPropertyBag2> props = do_QueryInterface(request);
michael@0 421 if (props) {
michael@0 422 nsCOMPtr<nsIURI> foo;
michael@0 423 props->GetPropertyAsInterface(NS_LITERAL_STRING("test.foo"),
michael@0 424 NS_GET_IID(nsIURI),
michael@0 425 getter_AddRefs(foo));
michael@0 426 if (foo) {
michael@0 427 nsAutoCString spec;
michael@0 428 foo->GetSpec(spec);
michael@0 429 LOG(("\ttest.foo: %s\n", spec.get()));
michael@0 430 }
michael@0 431 }
michael@0 432
michael@0 433 nsCOMPtr<nsIHttpChannelInternal> httpChannelInt(do_QueryInterface(request));
michael@0 434 if (httpChannelInt) {
michael@0 435 uint32_t majorVer, minorVer;
michael@0 436 nsresult rv = httpChannelInt->GetResponseVersion(&majorVer, &minorVer);
michael@0 437 if (NS_SUCCEEDED(rv)) {
michael@0 438 LOG(("HTTP Response version: %u.%u\n", majorVer, minorVer));
michael@0 439 }
michael@0 440 }
michael@0 441 nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(request));
michael@0 442 if (httpChannel) {
michael@0 443 HeaderVisitor *visitor = new HeaderVisitor();
michael@0 444 if (!visitor)
michael@0 445 return NS_ERROR_OUT_OF_MEMORY;
michael@0 446 NS_ADDREF(visitor);
michael@0 447
michael@0 448 LOG(("HTTP request headers:\n"));
michael@0 449 httpChannel->VisitRequestHeaders(visitor);
michael@0 450
michael@0 451 LOG(("HTTP response headers:\n"));
michael@0 452 httpChannel->VisitResponseHeaders(visitor);
michael@0 453
michael@0 454 NS_RELEASE(visitor);
michael@0 455 }
michael@0 456
michael@0 457 nsCOMPtr<nsIResumableChannel> resChannel = do_QueryInterface(request);
michael@0 458 if (resChannel) {
michael@0 459 LOG(("Resumable entity identification:\n"));
michael@0 460 nsAutoCString entityID;
michael@0 461 nsresult rv = resChannel->GetEntityID(entityID);
michael@0 462 if (NS_SUCCEEDED(rv)) {
michael@0 463 LOG(("\t|%s|\n", entityID.get()));
michael@0 464 }
michael@0 465 else {
michael@0 466 LOG(("\t<none>\n"));
michael@0 467 }
michael@0 468 }
michael@0 469
michael@0 470 return NS_OK;
michael@0 471 }
michael@0 472
michael@0 473 NS_IMETHODIMP
michael@0 474 InputTestConsumer::OnDataAvailable(nsIRequest *request,
michael@0 475 nsISupports* context,
michael@0 476 nsIInputStream *aIStream,
michael@0 477 uint64_t aSourceOffset,
michael@0 478 uint32_t aLength)
michael@0 479 {
michael@0 480 char buf[1025];
michael@0 481 uint32_t amt, size;
michael@0 482 nsresult rv;
michael@0 483 URLLoadInfo* info = (URLLoadInfo*)context;
michael@0 484
michael@0 485 while (aLength) {
michael@0 486 size = std::min<uint32_t>(aLength, sizeof(buf));
michael@0 487
michael@0 488 rv = aIStream->Read(buf, size, &amt);
michael@0 489 if (NS_FAILED(rv)) {
michael@0 490 NS_ASSERTION((NS_BASE_STREAM_WOULD_BLOCK != rv),
michael@0 491 "The stream should never block.");
michael@0 492 return rv;
michael@0 493 }
michael@0 494 if (gVerbose) {
michael@0 495 buf[amt] = '\0';
michael@0 496 puts(buf);
michael@0 497 }
michael@0 498 if (info) {
michael@0 499 info->mBytesRead += amt;
michael@0 500 }
michael@0 501
michael@0 502 aLength -= amt;
michael@0 503 }
michael@0 504 return NS_OK;
michael@0 505 }
michael@0 506
michael@0 507 NS_IMETHODIMP
michael@0 508 InputTestConsumer::OnStopRequest(nsIRequest *request, nsISupports* context,
michael@0 509 nsresult aStatus)
michael@0 510 {
michael@0 511 LOG(("InputTestConsumer::OnStopRequest [status=%x]\n", aStatus));
michael@0 512
michael@0 513 URLLoadInfo* info = (URLLoadInfo*)context;
michael@0 514
michael@0 515 if (info) {
michael@0 516 uint32_t httpStatus;
michael@0 517 bool bHTTPURL = false;
michael@0 518
michael@0 519 info->mTotalTime = PR_Now() - info->mTotalTime;
michael@0 520
michael@0 521 double readTime = ((info->mTotalTime-info->mConnectTime)/1000.0)/1000.0;
michael@0 522
michael@0 523 nsCOMPtr<nsIHttpChannel> pHTTPCon(do_QueryInterface(request));
michael@0 524 if (pHTTPCon) {
michael@0 525 pHTTPCon->GetResponseStatus(&httpStatus);
michael@0 526 bHTTPURL = true;
michael@0 527 }
michael@0 528
michael@0 529 LOG(("\nFinished loading: %s Status Code: %x\n", info->Name(), aStatus));
michael@0 530 if (bHTTPURL) {
michael@0 531 LOG(("\tHTTP Status: %u\n", httpStatus));
michael@0 532 }
michael@0 533 if (NS_ERROR_UNKNOWN_HOST == aStatus ||
michael@0 534 NS_ERROR_UNKNOWN_PROXY_HOST == aStatus) {
michael@0 535 LOG(("\tDNS lookup failed.\n"));
michael@0 536 }
michael@0 537 LOG(("\tTime to connect: %.3f seconds\n", (info->mConnectTime/1000.0)/1000.0));
michael@0 538 LOG(("\tTime to read: %.3f seconds.\n", readTime));
michael@0 539 LOG(("\tRead: %lld bytes.\n", info->mBytesRead));
michael@0 540 if (info->mBytesRead == int64_t(0)) {
michael@0 541 } else if (readTime > 0.0) {
michael@0 542 LOG(("\tThroughput: %.0f bps.\n", (double)(info->mBytesRead*int64_t(8))/readTime));
michael@0 543 } else {
michael@0 544 LOG(("\tThroughput: REAL FAST!!\n"));
michael@0 545 }
michael@0 546
michael@0 547 nsCOMPtr<nsITimedChannel> timed(do_QueryInterface(request));
michael@0 548 if (timed)
michael@0 549 PrintTimingInformation(timed);
michael@0 550 } else {
michael@0 551 LOG(("\nFinished loading: UNKNOWN URL. Status Code: %x\n", aStatus));
michael@0 552 }
michael@0 553
michael@0 554 if (--gKeepRunning == 0)
michael@0 555 QuitPumpingEvents();
michael@0 556 return NS_OK;
michael@0 557 }
michael@0 558
michael@0 559 //-----------------------------------------------------------------------------
michael@0 560 // NotificationCallbacks
michael@0 561 //-----------------------------------------------------------------------------
michael@0 562
michael@0 563 class NotificationCallbacks MOZ_FINAL : public nsIInterfaceRequestor {
michael@0 564 public:
michael@0 565 NS_DECL_ISUPPORTS
michael@0 566
michael@0 567 NotificationCallbacks() {
michael@0 568 }
michael@0 569
michael@0 570 NS_IMETHOD GetInterface(const nsIID& iid, void* *result) {
michael@0 571 nsresult rv = NS_ERROR_FAILURE;
michael@0 572
michael@0 573 if (iid.Equals(NS_GET_IID(nsIChannelEventSink))) {
michael@0 574 TestChannelEventSink *sink;
michael@0 575
michael@0 576 sink = new TestChannelEventSink();
michael@0 577 if (sink == nullptr)
michael@0 578 return NS_ERROR_OUT_OF_MEMORY;
michael@0 579 NS_ADDREF(sink);
michael@0 580 rv = sink->QueryInterface(iid, result);
michael@0 581 NS_RELEASE(sink);
michael@0 582 }
michael@0 583
michael@0 584 if (iid.Equals(NS_GET_IID(nsIAuthPrompt))) {
michael@0 585 TestAuthPrompt *prompt;
michael@0 586
michael@0 587 prompt = new TestAuthPrompt();
michael@0 588 if (prompt == nullptr)
michael@0 589 return NS_ERROR_OUT_OF_MEMORY;
michael@0 590 NS_ADDREF(prompt);
michael@0 591 rv = prompt->QueryInterface(iid, result);
michael@0 592 NS_RELEASE(prompt);
michael@0 593 }
michael@0 594 return rv;
michael@0 595 }
michael@0 596 };
michael@0 597
michael@0 598 NS_IMPL_ISUPPORTS(NotificationCallbacks, nsIInterfaceRequestor)
michael@0 599
michael@0 600 //-----------------------------------------------------------------------------
michael@0 601 // helpers...
michael@0 602 //-----------------------------------------------------------------------------
michael@0 603
michael@0 604 nsresult StartLoadingURL(const char* aUrlString)
michael@0 605 {
michael@0 606 nsresult rv;
michael@0 607
michael@0 608 nsCOMPtr<nsIIOService> pService(do_GetService(kIOServiceCID, &rv));
michael@0 609 if (pService) {
michael@0 610 nsCOMPtr<nsIURI> pURL;
michael@0 611
michael@0 612 rv = pService->NewURI(nsDependentCString(aUrlString), nullptr, nullptr, getter_AddRefs(pURL));
michael@0 613 if (NS_FAILED(rv)) {
michael@0 614 LOG(("ERROR: NewURI failed for %s [rv=%x]\n", aUrlString));
michael@0 615 return rv;
michael@0 616 }
michael@0 617 nsCOMPtr<nsIChannel> pChannel;
michael@0 618
michael@0 619 NotificationCallbacks* callbacks = new NotificationCallbacks();
michael@0 620 if (!callbacks) {
michael@0 621 LOG(("Failed to create a new consumer!"));
michael@0 622 return NS_ERROR_OUT_OF_MEMORY;;
michael@0 623 }
michael@0 624 NS_ADDREF(callbacks);
michael@0 625
michael@0 626 // Async reading thru the calls of the event sink interface
michael@0 627 rv = NS_NewChannel(getter_AddRefs(pChannel), pURL, pService,
michael@0 628 nullptr, // loadGroup
michael@0 629 callbacks); // notificationCallbacks
michael@0 630 NS_RELEASE(callbacks);
michael@0 631 if (NS_FAILED(rv)) {
michael@0 632 LOG(("ERROR: NS_OpenURI failed for %s [rv=%x]\n", aUrlString, rv));
michael@0 633 return rv;
michael@0 634 }
michael@0 635
michael@0 636 nsCOMPtr<nsITimedChannel> timed(do_QueryInterface(pChannel));
michael@0 637 if (timed)
michael@0 638 timed->SetTimingEnabled(true);
michael@0 639
michael@0 640 nsCOMPtr<nsIWritablePropertyBag2> props = do_QueryInterface(pChannel);
michael@0 641 if (props) {
michael@0 642 rv = props->SetPropertyAsInterface(NS_LITERAL_STRING("test.foo"),
michael@0 643 pURL);
michael@0 644 if (NS_SUCCEEDED(rv)) {
michael@0 645 LOG(("set prop 'test.foo'\n"));
michael@0 646 }
michael@0 647 }
michael@0 648
michael@0 649 /*
michael@0 650 You may optionally add/set other headers on this
michael@0 651 request object. This is done by QI for the specific
michael@0 652 protocolConnection.
michael@0 653 */
michael@0 654 nsCOMPtr<nsIHttpChannel> pHTTPCon(do_QueryInterface(pChannel));
michael@0 655
michael@0 656 if (pHTTPCon) {
michael@0 657 // Setting a sample header.
michael@0 658 rv = pHTTPCon->SetRequestHeader(NS_LITERAL_CSTRING("sample-header"),
michael@0 659 NS_LITERAL_CSTRING("Sample-Value"),
michael@0 660 false);
michael@0 661 if (NS_FAILED(rv)) return rv;
michael@0 662 }
michael@0 663 InputTestConsumer* listener;
michael@0 664
michael@0 665 listener = new InputTestConsumer;
michael@0 666 NS_IF_ADDREF(listener);
michael@0 667 if (!listener) {
michael@0 668 NS_ERROR("Failed to create a new stream listener!");
michael@0 669 return NS_ERROR_OUT_OF_MEMORY;;
michael@0 670 }
michael@0 671
michael@0 672 URLLoadInfo* info;
michael@0 673 info = new URLLoadInfo(aUrlString);
michael@0 674 NS_IF_ADDREF(info);
michael@0 675 if (!info) {
michael@0 676 NS_ERROR("Failed to create a load info!");
michael@0 677 return NS_ERROR_OUT_OF_MEMORY;
michael@0 678 }
michael@0 679
michael@0 680 if (gResume) {
michael@0 681 nsCOMPtr<nsIResumableChannel> res = do_QueryInterface(pChannel);
michael@0 682 if (!res) {
michael@0 683 NS_ERROR("Channel is not resumable!");
michael@0 684 return NS_ERROR_UNEXPECTED;
michael@0 685 }
michael@0 686 nsAutoCString id;
michael@0 687 if (gEntityID)
michael@0 688 id = gEntityID;
michael@0 689 LOG(("* resuming at %llu bytes, with entity id |%s|\n", gStartAt, id.get()));
michael@0 690 res->ResumeAt(gStartAt, id);
michael@0 691 }
michael@0 692 rv = pChannel->AsyncOpen(listener, // IStreamListener consumer
michael@0 693 info);
michael@0 694
michael@0 695 if (NS_SUCCEEDED(rv)) {
michael@0 696 gKeepRunning++;
michael@0 697 }
michael@0 698 else {
michael@0 699 LOG(("ERROR: AsyncOpen failed [rv=%x]\n", rv));
michael@0 700 }
michael@0 701 NS_RELEASE(listener);
michael@0 702 NS_RELEASE(info);
michael@0 703 }
michael@0 704
michael@0 705 return rv;
michael@0 706 }
michael@0 707
michael@0 708 static int32_t
michael@0 709 FindChar(nsCString& buffer, char c)
michael@0 710 {
michael@0 711 const char *b;
michael@0 712 int32_t len = NS_CStringGetData(buffer, &b);
michael@0 713
michael@0 714 for (int32_t offset = 0; offset < len; ++offset) {
michael@0 715 if (b[offset] == c)
michael@0 716 return offset;
michael@0 717 }
michael@0 718
michael@0 719 return -1;
michael@0 720 }
michael@0 721
michael@0 722
michael@0 723 static void
michael@0 724 StripChar(nsCString& buffer, char c)
michael@0 725 {
michael@0 726 const char *b;
michael@0 727 uint32_t len = NS_CStringGetData(buffer, &b) - 1;
michael@0 728
michael@0 729 for (; len > 0; --len) {
michael@0 730 if (b[len] == c) {
michael@0 731 buffer.Cut(len, 1);
michael@0 732 NS_CStringGetData(buffer, &b);
michael@0 733 }
michael@0 734 }
michael@0 735 }
michael@0 736
michael@0 737 nsresult LoadURLsFromFile(char *aFileName)
michael@0 738 {
michael@0 739 nsresult rv = NS_OK;
michael@0 740 int32_t len, offset;
michael@0 741 PRFileDesc* fd;
michael@0 742 char buffer[1024];
michael@0 743 nsCString fileBuffer;
michael@0 744 nsCString urlString;
michael@0 745
michael@0 746 fd = PR_Open(aFileName, PR_RDONLY, 777);
michael@0 747 if (!fd) {
michael@0 748 return NS_ERROR_FAILURE;
michael@0 749 }
michael@0 750
michael@0 751 // Keep reading the file until EOF (or an error) is reached...
michael@0 752 do {
michael@0 753 len = PR_Read(fd, buffer, sizeof(buffer));
michael@0 754 if (len>0) {
michael@0 755 fileBuffer.Append(buffer, len);
michael@0 756 // Treat each line as a URL...
michael@0 757 while ((offset = FindChar(fileBuffer, '\n')) != -1) {
michael@0 758 urlString = StringHead(fileBuffer, offset);
michael@0 759 fileBuffer.Cut(0, offset+1);
michael@0 760
michael@0 761 StripChar(urlString, '\r');
michael@0 762 if (urlString.Length()) {
michael@0 763 LOG(("\t%s\n", urlString.get()));
michael@0 764 rv = StartLoadingURL(urlString.get());
michael@0 765 if (NS_FAILED(rv)) {
michael@0 766 // No need to log an error -- StartLoadingURL already
michael@0 767 // did that for us, probably.
michael@0 768 PR_Close(fd);
michael@0 769 return rv;
michael@0 770 }
michael@0 771 }
michael@0 772 }
michael@0 773 }
michael@0 774 } while (len>0);
michael@0 775
michael@0 776 // If anything is left in the fileBuffer, treat it as a URL...
michael@0 777 StripChar(fileBuffer, '\r');
michael@0 778 if (fileBuffer.Length()) {
michael@0 779 LOG(("\t%s\n", fileBuffer.get()));
michael@0 780 StartLoadingURL(fileBuffer.get());
michael@0 781 }
michael@0 782
michael@0 783 PR_Close(fd);
michael@0 784 return NS_OK;
michael@0 785 }
michael@0 786
michael@0 787
michael@0 788 nsresult LoadURLFromConsole()
michael@0 789 {
michael@0 790 char buffer[1024];
michael@0 791 printf("Enter URL (\"q\" to start): ");
michael@0 792 unused << scanf("%s", buffer);
michael@0 793 if (buffer[0]=='q')
michael@0 794 gAskUserForInput = false;
michael@0 795 else
michael@0 796 StartLoadingURL(buffer);
michael@0 797 return NS_OK;
michael@0 798 }
michael@0 799
michael@0 800 } // namespace
michael@0 801
michael@0 802 using namespace TestProtocols;
michael@0 803
michael@0 804 int
michael@0 805 main(int argc, char* argv[])
michael@0 806 {
michael@0 807 if (test_common_init(&argc, &argv) != 0)
michael@0 808 return -1;
michael@0 809
michael@0 810 nsresult rv= (nsresult)-1;
michael@0 811 if (argc < 2) {
michael@0 812 printf("usage: %s [-verbose] [-file <name>] [-resume <startoffset>"
michael@0 813 "[-entityid <entityid>]] [-proxy <proxy>] [-pac <pacURL>]"
michael@0 814 "[-console] <url> <url> ... \n", argv[0]);
michael@0 815 return -1;
michael@0 816 }
michael@0 817
michael@0 818 #if defined(PR_LOGGING)
michael@0 819 gTestLog = PR_NewLogModule("Test");
michael@0 820 #endif
michael@0 821
michael@0 822 /*
michael@0 823 The following code only deals with XPCOM registration stuff. and setting
michael@0 824 up the event queues. Copied from TestSocketIO.cpp
michael@0 825 */
michael@0 826
michael@0 827 rv = NS_InitXPCOM2(nullptr, nullptr, nullptr);
michael@0 828 if (NS_FAILED(rv)) return -1;
michael@0 829
michael@0 830 {
michael@0 831 int i;
michael@0 832 LOG(("Trying to load:\n"));
michael@0 833 for (i=1; i<argc; i++) {
michael@0 834 // Turn on verbose printing...
michael@0 835 if (PL_strcasecmp(argv[i], "-verbose") == 0) {
michael@0 836 gVerbose = true;
michael@0 837 continue;
michael@0 838 }
michael@0 839
michael@0 840 // Turn on netlib tracing...
michael@0 841 if (PL_strcasecmp(argv[i], "-file") == 0) {
michael@0 842 LoadURLsFromFile(argv[++i]);
michael@0 843 continue;
michael@0 844 }
michael@0 845
michael@0 846 if (PL_strcasecmp(argv[i], "-console") == 0) {
michael@0 847 gAskUserForInput = true;
michael@0 848 continue;
michael@0 849 }
michael@0 850
michael@0 851 if (PL_strcasecmp(argv[i], "-resume") == 0) {
michael@0 852 gResume = true;
michael@0 853 PR_sscanf(argv[++i], "%llu", &gStartAt);
michael@0 854 continue;
michael@0 855 }
michael@0 856
michael@0 857 if (PL_strcasecmp(argv[i], "-entityid") == 0) {
michael@0 858 gEntityID = argv[++i];
michael@0 859 continue;
michael@0 860 }
michael@0 861
michael@0 862 if (PL_strcasecmp(argv[i], "-proxy") == 0) {
michael@0 863 SetHttpProxy(argv[++i]);
michael@0 864 continue;
michael@0 865 }
michael@0 866
michael@0 867 if (PL_strcasecmp(argv[i], "-pac") == 0) {
michael@0 868 SetPACFile(argv[++i]);
michael@0 869 continue;
michael@0 870 }
michael@0 871
michael@0 872 LOG(("\t%s\n", argv[i]));
michael@0 873 rv = StartLoadingURL(argv[i]);
michael@0 874 }
michael@0 875 // Enter the message pump to allow the URL load to proceed.
michael@0 876 PumpEvents();
michael@0 877 } // this scopes the nsCOMPtrs
michael@0 878 // no nsCOMPtrs are allowed to be alive when you call NS_ShutdownXPCOM
michael@0 879 NS_ShutdownXPCOM(nullptr);
michael@0 880 return NS_FAILED(rv) ? -1 : 0;
michael@0 881 }

mercurial