diff options
author | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
---|---|---|
committer | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
commit | 5f8de423f190bbb79a62f804151bc24824fa32d8 (patch) | |
tree | 10027f336435511475e392454359edea8e25895d /netwerk/test/TestProtocols.cpp | |
parent | 49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff) | |
download | UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.lz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.xz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.zip |
Add m-esr52 at 52.6.0
Diffstat (limited to 'netwerk/test/TestProtocols.cpp')
-rw-r--r-- | netwerk/test/TestProtocols.cpp | 890 |
1 files changed, 890 insertions, 0 deletions
diff --git a/netwerk/test/TestProtocols.cpp b/netwerk/test/TestProtocols.cpp new file mode 100644 index 000000000..7bec14f85 --- /dev/null +++ b/netwerk/test/TestProtocols.cpp @@ -0,0 +1,890 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 sw=2 et cindent: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* + The TestProtocols tests the basic protocols architecture and can + be used to test individual protocols as well. If this grows too + big then we should split it to individual protocols. + + -Gagan Saksena 04/29/99 +*/ + +#include "TestCommon.h" +#include <algorithm> + +#include <stdio.h> +#ifdef WIN32 +#include <windows.h> +#endif +#ifdef XP_UNIX +#include <unistd.h> +#endif +#include "nspr.h" +#include "nscore.h" +#include "nsCOMPtr.h" +#include "nsIIOService.h" +#include "nsIServiceManager.h" +#include "nsIStreamListener.h" +#include "nsIInputStream.h" +#include "nsIInputStream.h" +#include "nsCRT.h" +#include "nsIChannel.h" +#include "nsIResumableChannel.h" +#include "nsIURL.h" +#include "nsIHttpChannel.h" +#include "nsIHttpChannelInternal.h" +#include "nsIHttpHeaderVisitor.h" +#include "nsIChannelEventSink.h" +#include "nsIAsyncVerifyRedirectCallback.h" +#include "nsIInterfaceRequestor.h" +#include "nsIInterfaceRequestorUtils.h" +#include "nsIDNSService.h" +#include "nsIAuthPrompt.h" +#include "nsIPrefService.h" +#include "nsIPrefBranch.h" +#include "nsIPropertyBag2.h" +#include "nsIWritablePropertyBag2.h" +#include "nsITimedChannel.h" +#include "mozilla/Attributes.h" +#include "mozilla/Unused.h" +#include "nsIScriptSecurityManager.h" + +#include "nsISimpleEnumerator.h" +#include "nsStringAPI.h" +#include "nsNetUtil.h" +#include "nsServiceManagerUtils.h" +#include "NetwerkTestLogging.h" + +using namespace mozilla; + +namespace TestProtocols { + +// +// set NSPR_LOG_MODULES=Test:5 +// +static PRLogModuleInfo *gTestLog = nullptr; +#define LOG(args) MOZ_LOG(gTestLog, mozilla::LogLevel::Debug, args) + +static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID); + +//static PRTime gElapsedTime; // enable when we time it... +static int gKeepRunning = 0; +static bool gVerbose = false; +static bool gAskUserForInput = false; +static bool gResume = false; +static uint64_t gStartAt = 0; + +static const char* gEntityID; + +//----------------------------------------------------------------------------- +// Set proxy preferences for testing +//----------------------------------------------------------------------------- + +static nsresult +SetHttpProxy(const char *proxy) +{ + const char *colon = strchr(proxy, ':'); + if (!colon) + { + NS_WARNING("invalid proxy token; use host:port"); + return NS_ERROR_UNEXPECTED; + } + int port = atoi(colon + 1); + if (port == 0) + { + NS_WARNING("invalid proxy port; must be an integer"); + return NS_ERROR_UNEXPECTED; + } + nsAutoCString proxyHost; + proxyHost = Substring(proxy, colon); + + nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID); + if (prefs) + { + prefs->SetCharPref("network.proxy.http", proxyHost.get()); + prefs->SetIntPref("network.proxy.http_port", port); + prefs->SetIntPref("network.proxy.type", 1); // manual proxy config + } + LOG(("connecting via proxy=%s:%d\n", proxyHost.get(), port)); + return NS_OK; +} + +static nsresult +SetPACFile(const char* pacURL) +{ + nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID); + if (prefs) + { + prefs->SetCharPref("network.proxy.autoconfig_url", pacURL); + prefs->SetIntPref("network.proxy.type", 2); // PAC file + } + LOG(("connecting using PAC file %s\n", pacURL)); + return NS_OK; +} + +//----------------------------------------------------------------------------- +// Timing information +//----------------------------------------------------------------------------- + +void PrintTimingInformation(nsITimedChannel* channel) { +#define PRINT_VALUE(property) \ + { \ + PRTime value; \ + channel->Get##property(&value); \ + if (value) { \ + PRExplodedTime exploded; \ + PR_ExplodeTime(value, PR_LocalTimeParameters, &exploded); \ + char buf[256]; \ + PR_FormatTime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", &exploded); \ + LOG((" " #property ":\t%s (%i usec)", buf, exploded.tm_usec)); \ + } else { \ + LOG((" " #property ":\t0")); \ + } \ + } + LOG(("Timing data:")); + PRINT_VALUE(ChannelCreationTime) + PRINT_VALUE(AsyncOpenTime) + PRINT_VALUE(DomainLookupStartTime) + PRINT_VALUE(DomainLookupEndTime) + PRINT_VALUE(ConnectStartTime) + PRINT_VALUE(ConnectEndTime) + PRINT_VALUE(RequestStartTime) + PRINT_VALUE(ResponseStartTime) + PRINT_VALUE(ResponseEndTime) + PRINT_VALUE(CacheReadStartTime) + PRINT_VALUE(CacheReadEndTime) +} + +//----------------------------------------------------------------------------- +// HeaderVisitor +//----------------------------------------------------------------------------- + +class HeaderVisitor : public nsIHttpHeaderVisitor +{ + virtual ~HeaderVisitor() = default; +public: + NS_DECL_ISUPPORTS + NS_DECL_NSIHTTPHEADERVISITOR + + HeaderVisitor() { } +}; +NS_IMPL_ISUPPORTS(HeaderVisitor, nsIHttpHeaderVisitor) + +NS_IMETHODIMP +HeaderVisitor::VisitHeader(const nsACString &header, const nsACString &value) +{ + LOG((" %s: %s\n", + PromiseFlatCString(header).get(), + PromiseFlatCString(value).get())); + return NS_OK; +} + +//----------------------------------------------------------------------------- +// URLLoadInfo +//----------------------------------------------------------------------------- + +class URLLoadInfo : public nsISupports +{ + virtual ~URLLoadInfo(); + +public: + + explicit URLLoadInfo(const char* aUrl); + + // ISupports interface... + NS_DECL_THREADSAFE_ISUPPORTS + + const char* Name() { return mURLString.get(); } + int64_t mBytesRead; + PRTime mTotalTime; + PRTime mConnectTime; + nsCString mURLString; +}; + +URLLoadInfo::URLLoadInfo(const char *aUrl) : mURLString(aUrl) +{ + mBytesRead = 0; + mConnectTime = mTotalTime = PR_Now(); +} + +URLLoadInfo::~URLLoadInfo() = default; + + +NS_IMPL_ISUPPORTS0(URLLoadInfo) + +//----------------------------------------------------------------------------- +// TestChannelEventSink +//----------------------------------------------------------------------------- + +class TestChannelEventSink : public nsIChannelEventSink +{ + virtual ~TestChannelEventSink(); + +public: + NS_DECL_ISUPPORTS + NS_DECL_NSICHANNELEVENTSINK + + TestChannelEventSink(); +}; + +TestChannelEventSink::TestChannelEventSink() +{ +} + +TestChannelEventSink::~TestChannelEventSink() = default; + + +NS_IMPL_ISUPPORTS(TestChannelEventSink, nsIChannelEventSink) + +NS_IMETHODIMP +TestChannelEventSink::AsyncOnChannelRedirect(nsIChannel *channel, + nsIChannel *newChannel, + uint32_t flags, + nsIAsyncVerifyRedirectCallback *callback) +{ + LOG(("\n+++ TestChannelEventSink::OnChannelRedirect (with flags %x) +++\n", + flags)); + callback->OnRedirectVerifyCallback(NS_OK); + return NS_OK; +} + +//----------------------------------------------------------------------------- +// TestAuthPrompt +//----------------------------------------------------------------------------- + +class TestAuthPrompt : public nsIAuthPrompt +{ + virtual ~TestAuthPrompt(); + +public: + NS_DECL_ISUPPORTS + NS_DECL_NSIAUTHPROMPT + + TestAuthPrompt(); +}; + +NS_IMPL_ISUPPORTS(TestAuthPrompt, nsIAuthPrompt) + +TestAuthPrompt::TestAuthPrompt() +{ +} + +TestAuthPrompt::~TestAuthPrompt() = default; + +NS_IMETHODIMP +TestAuthPrompt::Prompt(const char16_t *dialogTitle, + const char16_t *text, + const char16_t *passwordRealm, + uint32_t savePassword, + const char16_t *defaultText, + char16_t **result, + bool *_retval) +{ + *_retval = false; + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +TestAuthPrompt::PromptUsernameAndPassword(const char16_t *dialogTitle, + const char16_t *dialogText, + const char16_t *passwordRealm, + uint32_t savePassword, + char16_t **user, + char16_t **pwd, + bool *_retval) +{ + NS_ConvertUTF16toUTF8 text(passwordRealm); + printf("* --------------------------------------------------------------------------- *\n"); + printf("* Authentication Required [%s]\n", text.get()); + printf("* --------------------------------------------------------------------------- *\n"); + + char buf[256]; + int n; + + printf("Enter username: "); + Unused << fgets(buf, sizeof(buf), stdin); + n = strlen(buf); + buf[n-1] = '\0'; // trim trailing newline + *user = NS_StringCloneData(NS_ConvertUTF8toUTF16(buf)); + + const char *p; +#if defined(XP_UNIX) && !defined(ANDROID) + p = getpass("Enter password: "); +#else + printf("Enter password: "); + fgets(buf, sizeof(buf), stdin); + n = strlen(buf); + buf[n-1] = '\0'; // trim trailing newline + p = buf; +#endif + *pwd = NS_StringCloneData(NS_ConvertUTF8toUTF16(p)); + + // zap buf + memset(buf, 0, sizeof(buf)); + + *_retval = true; + return NS_OK; +} + +NS_IMETHODIMP +TestAuthPrompt::PromptPassword(const char16_t *dialogTitle, + const char16_t *text, + const char16_t *passwordRealm, + uint32_t savePassword, + char16_t **pwd, + bool *_retval) +{ + *_retval = false; + return NS_ERROR_NOT_IMPLEMENTED; +} + +//----------------------------------------------------------------------------- +// InputTestConsumer +//----------------------------------------------------------------------------- + +class InputTestConsumer : public nsIStreamListener +{ + virtual ~InputTestConsumer(); + +public: + + explicit InputTestConsumer(URLLoadInfo* aURLLoadInfo); + + NS_DECL_ISUPPORTS + NS_DECL_NSIREQUESTOBSERVER + NS_DECL_NSISTREAMLISTENER +private: + URLLoadInfo* mURLLoadInfo; +}; + +InputTestConsumer::InputTestConsumer(URLLoadInfo* aURLLoadInfo) +: mURLLoadInfo(aURLLoadInfo) +{ + NS_IF_ADDREF(mURLLoadInfo); +} + +InputTestConsumer::~InputTestConsumer() +{ + NS_RELEASE(mURLLoadInfo); +} + +NS_IMPL_ISUPPORTS(InputTestConsumer, nsIStreamListener, nsIRequestObserver) + +NS_IMETHODIMP +InputTestConsumer::OnStartRequest(nsIRequest *request, nsISupports* context) +{ + LOG(("InputTestConsumer::OnStartRequest\n")); + + NS_ASSERTION(!context, "context needs to be null when calling asyncOpen2"); + + if (mURLLoadInfo) + mURLLoadInfo->mConnectTime = PR_Now() - mURLLoadInfo->mConnectTime; + + if (gVerbose) { + LOG(("\nStarted loading: %s\n", mURLLoadInfo ? mURLLoadInfo->Name() : "UNKNOWN URL")); + } + + nsAutoCString value; + + nsCOMPtr<nsIChannel> channel = do_QueryInterface(request); + if (channel) { + nsresult status; + channel->GetStatus(&status); + LOG(("Channel Status: %08x\n", status)); + if (NS_SUCCEEDED(status)) { + LOG(("Channel Info:\n")); + + channel->GetName(value); + LOG(("\tName: %s\n", value.get())); + + channel->GetContentType(value); + LOG(("\tContent-Type: %s\n", value.get())); + + channel->GetContentCharset(value); + LOG(("\tContent-Charset: %s\n", value.get())); + + int64_t length = -1; + if (NS_SUCCEEDED(channel->GetContentLength(&length))) { + LOG(("\tContent-Length: %lld\n", length)); + } else { + LOG(("\tContent-Length: Unknown\n")); + } + } + + nsCOMPtr<nsISupports> owner; + channel->GetOwner(getter_AddRefs(owner)); + LOG(("\tChannel Owner: %x\n", owner.get())); + } + + nsCOMPtr<nsIPropertyBag2> props = do_QueryInterface(request); + if (props) { + nsCOMPtr<nsIURI> foo; + props->GetPropertyAsInterface(NS_LITERAL_STRING("test.foo"), + NS_GET_IID(nsIURI), + getter_AddRefs(foo)); + if (foo) { + LOG(("\ttest.foo: %s\n", foo->GetSpecOrDefault().get())); + } + } + + nsCOMPtr<nsIHttpChannelInternal> httpChannelInt(do_QueryInterface(request)); + if (httpChannelInt) { + uint32_t majorVer, minorVer; + nsresult rv = httpChannelInt->GetResponseVersion(&majorVer, &minorVer); + if (NS_SUCCEEDED(rv)) { + LOG(("HTTP Response version: %u.%u\n", majorVer, minorVer)); + } + } + nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(request)); + if (httpChannel) { + auto *visitor = new HeaderVisitor(); + if (!visitor) + return NS_ERROR_OUT_OF_MEMORY; + NS_ADDREF(visitor); + + LOG(("HTTP request headers:\n")); + httpChannel->VisitRequestHeaders(visitor); + + LOG(("HTTP response headers:\n")); + httpChannel->VisitResponseHeaders(visitor); + + NS_RELEASE(visitor); + } + + nsCOMPtr<nsIResumableChannel> resChannel = do_QueryInterface(request); + if (resChannel) { + LOG(("Resumable entity identification:\n")); + nsAutoCString entityID; + nsresult rv = resChannel->GetEntityID(entityID); + if (NS_SUCCEEDED(rv)) { + LOG(("\t|%s|\n", entityID.get())); + } + else { + LOG(("\t<none>\n")); + } + } + + return NS_OK; +} + +NS_IMETHODIMP +InputTestConsumer::OnDataAvailable(nsIRequest *request, + nsISupports* context, + nsIInputStream *aIStream, + uint64_t aSourceOffset, + uint32_t aLength) +{ + NS_ASSERTION(!context, "context needs to be null when calling asyncOpen2"); + + char buf[1025]; + uint32_t amt, size; + nsresult rv; + + while (aLength) { + size = std::min<uint32_t>(aLength, sizeof(buf)); + + rv = aIStream->Read(buf, size, &amt); + if (NS_FAILED(rv)) { + NS_ASSERTION((NS_BASE_STREAM_WOULD_BLOCK != rv), + "The stream should never block."); + return rv; + } + if (gVerbose) { + buf[amt] = '\0'; + puts(buf); + } + if (mURLLoadInfo) { + mURLLoadInfo->mBytesRead += amt; + } + + aLength -= amt; + } + return NS_OK; +} + +NS_IMETHODIMP +InputTestConsumer::OnStopRequest(nsIRequest *request, nsISupports* context, + nsresult aStatus) +{ + LOG(("InputTestConsumer::OnStopRequest [status=%x]\n", aStatus)); + + if (mURLLoadInfo) { + uint32_t httpStatus; + bool bHTTPURL = false; + + mURLLoadInfo->mTotalTime = PR_Now() - mURLLoadInfo->mTotalTime; + + double readTime = ((mURLLoadInfo->mTotalTime-mURLLoadInfo->mConnectTime)/1000.0)/1000.0; + + nsCOMPtr<nsIHttpChannel> pHTTPCon(do_QueryInterface(request)); + if (pHTTPCon) { + pHTTPCon->GetResponseStatus(&httpStatus); + bHTTPURL = true; + } + + LOG(("\nFinished loading: %s Status Code: %x\n", mURLLoadInfo->Name(), aStatus)); + if (bHTTPURL) { + LOG(("\tHTTP Status: %u\n", httpStatus)); + } + if (NS_ERROR_UNKNOWN_HOST == aStatus || + NS_ERROR_UNKNOWN_PROXY_HOST == aStatus) { + LOG(("\tDNS lookup failed.\n")); + } + LOG(("\tTime to connect: %.3f seconds\n", (mURLLoadInfo->mConnectTime/1000.0)/1000.0)); + LOG(("\tTime to read: %.3f seconds.\n", readTime)); + LOG(("\tRead: %lld bytes.\n", mURLLoadInfo->mBytesRead)); + if (mURLLoadInfo->mBytesRead == int64_t(0)) { + } else if (readTime > 0.0) { + LOG(("\tThroughput: %.0f bps.\n", (double)(mURLLoadInfo->mBytesRead*int64_t(8))/readTime)); + } else { + LOG(("\tThroughput: REAL FAST!!\n")); + } + + nsCOMPtr<nsITimedChannel> timed(do_QueryInterface(request)); + if (timed) + PrintTimingInformation(timed); + } else { + LOG(("\nFinished loading: UNKNOWN URL. Status Code: %x\n", aStatus)); + } + + if (--gKeepRunning == 0) + QuitPumpingEvents(); + return NS_OK; +} + +//----------------------------------------------------------------------------- +// NotificationCallbacks +//----------------------------------------------------------------------------- + +class NotificationCallbacks final : public nsIInterfaceRequestor { + + ~NotificationCallbacks() = default; + +public: + NS_DECL_ISUPPORTS + + NotificationCallbacks() { + } + + NS_IMETHOD GetInterface(const nsIID& iid, void* *result) override { + nsresult rv = NS_ERROR_FAILURE; + + if (iid.Equals(NS_GET_IID(nsIChannelEventSink))) { + TestChannelEventSink *sink; + + sink = new TestChannelEventSink(); + if (sink == nullptr) + return NS_ERROR_OUT_OF_MEMORY; + NS_ADDREF(sink); + rv = sink->QueryInterface(iid, result); + NS_RELEASE(sink); + } + + if (iid.Equals(NS_GET_IID(nsIAuthPrompt))) { + TestAuthPrompt *prompt; + + prompt = new TestAuthPrompt(); + if (prompt == nullptr) + return NS_ERROR_OUT_OF_MEMORY; + NS_ADDREF(prompt); + rv = prompt->QueryInterface(iid, result); + NS_RELEASE(prompt); + } + return rv; + } +}; + +NS_IMPL_ISUPPORTS(NotificationCallbacks, nsIInterfaceRequestor) + +//----------------------------------------------------------------------------- +// helpers... +//----------------------------------------------------------------------------- + +nsresult StartLoadingURL(const char* aUrlString) +{ + nsresult rv; + + nsCOMPtr<nsIIOService> pService(do_GetService(kIOServiceCID, &rv)); + if (pService) { + nsCOMPtr<nsIURI> pURL; + + rv = pService->NewURI(nsDependentCString(aUrlString), nullptr, nullptr, getter_AddRefs(pURL)); + if (NS_FAILED(rv)) { + LOG(("ERROR: NewURI failed for %s [rv=%x]\n", aUrlString)); + return rv; + } + nsCOMPtr<nsIChannel> pChannel; + + auto* callbacks = new NotificationCallbacks(); + if (!callbacks) { + LOG(("Failed to create a new consumer!")); + return NS_ERROR_OUT_OF_MEMORY;; + } + NS_ADDREF(callbacks); + + nsCOMPtr<nsIScriptSecurityManager> secman = + do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv); + NS_ENSURE_SUCCESS(rv, rv); + nsCOMPtr<nsIPrincipal> systemPrincipal; + rv = secman->GetSystemPrincipal(getter_AddRefs(systemPrincipal)); + NS_ENSURE_SUCCESS(rv, rv); + + // Async reading thru the calls of the event sink interface + rv = NS_NewChannel(getter_AddRefs(pChannel), + pURL, + systemPrincipal, + nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL, + nsIContentPolicy::TYPE_OTHER, + nullptr, // loadGroup + callbacks, + nsIRequest::LOAD_NORMAL, + pService); + + NS_RELEASE(callbacks); + if (NS_FAILED(rv)) { + LOG(("ERROR: NS_NewChannel failed for %s [rv=%x]\n", aUrlString, rv)); + return rv; + } + + nsCOMPtr<nsITimedChannel> timed(do_QueryInterface(pChannel)); + if (timed) + timed->SetTimingEnabled(true); + + nsCOMPtr<nsIWritablePropertyBag2> props = do_QueryInterface(pChannel); + if (props) { + rv = props->SetPropertyAsInterface(NS_LITERAL_STRING("test.foo"), + pURL); + if (NS_SUCCEEDED(rv)) { + LOG(("set prop 'test.foo'\n")); + } + } + + /* + You may optionally add/set other headers on this + request object. This is done by QI for the specific + protocolConnection. + */ + nsCOMPtr<nsIHttpChannel> pHTTPCon(do_QueryInterface(pChannel)); + + if (pHTTPCon) { + // Setting a sample header. + rv = pHTTPCon->SetRequestHeader(NS_LITERAL_CSTRING("sample-header"), + NS_LITERAL_CSTRING("Sample-Value"), + false); + if (NS_FAILED(rv)) return rv; + } + auto* info = new URLLoadInfo(aUrlString); + if (!info) { + NS_ERROR("Failed to create a load info!"); + return NS_ERROR_OUT_OF_MEMORY; + } + + auto* listener = new InputTestConsumer(info); + NS_IF_ADDREF(listener); + if (!listener) { + NS_ERROR("Failed to create a new stream listener!"); + return NS_ERROR_OUT_OF_MEMORY;; + } + + + if (gResume) { + nsCOMPtr<nsIResumableChannel> res = do_QueryInterface(pChannel); + if (!res) { + NS_ERROR("Channel is not resumable!"); + return NS_ERROR_UNEXPECTED; + } + nsAutoCString id; + if (gEntityID) + id = gEntityID; + LOG(("* resuming at %llu bytes, with entity id |%s|\n", gStartAt, id.get())); + res->ResumeAt(gStartAt, id); + } + rv = pChannel->AsyncOpen2(listener); + + if (NS_SUCCEEDED(rv)) { + gKeepRunning++; + } + else { + LOG(("ERROR: AsyncOpen failed [rv=%x]\n", rv)); + } + NS_RELEASE(listener); + } + + return rv; +} + +static int32_t +FindChar(nsCString& buffer, char c) +{ + const char *b; + int32_t len = NS_CStringGetData(buffer, &b); + + for (int32_t offset = 0; offset < len; ++offset) { + if (b[offset] == c) + return offset; + } + + return -1; +} + + +static void +StripChar(nsCString& buffer, char c) +{ + const char *b; + uint32_t len = NS_CStringGetData(buffer, &b) - 1; + + for (; len > 0; --len) { + if (b[len] == c) { + buffer.Cut(len, 1); + NS_CStringGetData(buffer, &b); + } + } +} + +nsresult LoadURLsFromFile(char *aFileName) +{ + nsresult rv = NS_OK; + int32_t len, offset; + PRFileDesc* fd; + char buffer[1024]; + nsCString fileBuffer; + nsCString urlString; + + fd = PR_Open(aFileName, PR_RDONLY, 777); + if (!fd) { + return NS_ERROR_FAILURE; + } + + // Keep reading the file until EOF (or an error) is reached... + do { + len = PR_Read(fd, buffer, sizeof(buffer)); + if (len>0) { + fileBuffer.Append(buffer, len); + // Treat each line as a URL... + while ((offset = FindChar(fileBuffer, '\n')) != -1) { + urlString = StringHead(fileBuffer, offset); + fileBuffer.Cut(0, offset+1); + + StripChar(urlString, '\r'); + if (urlString.Length()) { + LOG(("\t%s\n", urlString.get())); + rv = StartLoadingURL(urlString.get()); + if (NS_FAILED(rv)) { + // No need to log an error -- StartLoadingURL already + // did that for us, probably. + PR_Close(fd); + return rv; + } + } + } + } + } while (len>0); + + // If anything is left in the fileBuffer, treat it as a URL... + StripChar(fileBuffer, '\r'); + if (fileBuffer.Length()) { + LOG(("\t%s\n", fileBuffer.get())); + StartLoadingURL(fileBuffer.get()); + } + + PR_Close(fd); + return NS_OK; +} + + +nsresult LoadURLFromConsole() +{ + char buffer[1024]; + printf(R"(Enter URL ("q" to start): )"); + Unused << scanf("%s", buffer); + if (buffer[0]=='q') + gAskUserForInput = false; + else + StartLoadingURL(buffer); + return NS_OK; +} + +} // namespace TestProtocols + +using namespace TestProtocols; + +int +main(int argc, char* argv[]) +{ + if (test_common_init(&argc, &argv) != 0) + return -1; + + nsresult rv= (nsresult)-1; + if (argc < 2) { + printf("usage: %s [-verbose] [-file <name>] [-resume <startoffset>" + "[-entityid <entityid>]] [-proxy <proxy>] [-pac <pacURL>]" + "[-console] <url> <url> ... \n", argv[0]); + return -1; + } + + gTestLog = PR_NewLogModule("Test"); + + /* + The following code only deals with XPCOM registration stuff. and setting + up the event queues. Copied from TestSocketIO.cpp + */ + + rv = NS_InitXPCOM2(nullptr, nullptr, nullptr); + if (NS_FAILED(rv)) return -1; + + { + int i; + LOG(("Trying to load:\n")); + for (i=1; i<argc; i++) { + // Turn on verbose printing... + if (PL_strcasecmp(argv[i], "-verbose") == 0) { + gVerbose = true; + continue; + } + + // Turn on netlib tracing... + if (PL_strcasecmp(argv[i], "-file") == 0) { + LoadURLsFromFile(argv[++i]); + continue; + } + + if (PL_strcasecmp(argv[i], "-console") == 0) { + gAskUserForInput = true; + continue; + } + + if (PL_strcasecmp(argv[i], "-resume") == 0) { + gResume = true; + PR_sscanf(argv[++i], "%llu", &gStartAt); + continue; + } + + if (PL_strcasecmp(argv[i], "-entityid") == 0) { + gEntityID = argv[++i]; + continue; + } + + if (PL_strcasecmp(argv[i], "-proxy") == 0) { + SetHttpProxy(argv[++i]); + continue; + } + + if (PL_strcasecmp(argv[i], "-pac") == 0) { + SetPACFile(argv[++i]); + continue; + } + + LOG(("\t%s\n", argv[i])); + rv = StartLoadingURL(argv[i]); + } + // Enter the message pump to allow the URL load to proceed. + PumpEvents(); + } // this scopes the nsCOMPtrs + // no nsCOMPtrs are allowed to be alive when you call NS_ShutdownXPCOM + NS_ShutdownXPCOM(nullptr); + return NS_FAILED(rv) ? -1 : 0; +} |