Back to index

lightning-sunbird  0.9+nobinonly
TestProtocols.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
00002 /* vim: set ts=4 sw=4 et cindent: */
00003 /* ***** BEGIN LICENSE BLOCK *****
00004  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00005  *
00006  * The contents of this file are subject to the Mozilla Public License Version
00007  * 1.1 (the "License"); you may not use this file except in compliance with
00008  * the License. You may obtain a copy of the License at
00009  * http://www.mozilla.org/MPL/
00010  *
00011  * Software distributed under the License is distributed on an "AS IS" basis,
00012  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00013  * for the specific language governing rights and limitations under the
00014  * License.
00015  *
00016  * The Original Code is mozilla.org code.
00017  *
00018  * The Initial Developer of the Original Code is
00019  * Netscape Communications Corporation.
00020  * Portions created by the Initial Developer are Copyright (C) 1998
00021  * the Initial Developer. All Rights Reserved.
00022  *
00023  * Contributor(s):
00024  *
00025  * Alternatively, the contents of this file may be used under the terms of
00026  * either the GNU General Public License Version 2 or later (the "GPL"), or
00027  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00028  * in which case the provisions of the GPL or the LGPL are applicable instead
00029  * of those above. If you wish to allow use of your version of this file only
00030  * under the terms of either the GPL or the LGPL, and not to allow others to
00031  * use your version of this file under the terms of the MPL, indicate your
00032  * decision by deleting the provisions above and replace them with the notice
00033  * and other provisions required by the GPL or the LGPL. If you do not delete
00034  * the provisions above, a recipient may use your version of this file under
00035  * the terms of any one of the MPL, the GPL or the LGPL.
00036  *
00037  * ***** END LICENSE BLOCK ***** */
00038 
00039 /* 
00040     The TestProtocols tests the basic protocols architecture and can 
00041     be used to test individual protocols as well. If this grows too
00042     big then we should split it to individual protocols. 
00043 
00044     -Gagan Saksena 04/29/99
00045 */
00046 
00047 #include "TestCommon.h"
00048 
00049 #define FORCE_PR_LOG
00050 #include <stdio.h>
00051 #ifdef WIN32 
00052 #include <windows.h>
00053 #endif
00054 #ifdef XP_UNIX
00055 #include <unistd.h>
00056 #endif
00057 #include "nspr.h"
00058 #include "nscore.h"
00059 #include "nsCOMPtr.h"
00060 #include "nsIEventQueueService.h"
00061 #include "nsIIOService.h"
00062 #include "nsIServiceManager.h"
00063 #include "nsIStreamListener.h"
00064 #include "nsIInputStream.h"
00065 #include "nsIInputStream.h"
00066 #include "nsCRT.h"
00067 #include "nsIChannel.h"
00068 #include "nsIResumableChannel.h"
00069 #include "nsIURL.h"
00070 #include "nsIHttpChannel.h"
00071 #include "nsIHttpChannelInternal.h"
00072 #include "nsIHttpHeaderVisitor.h"
00073 #include "nsIChannelEventSink.h" 
00074 #include "nsIInterfaceRequestor.h" 
00075 #include "nsIInterfaceRequestorUtils.h"
00076 #include "nsIDNSService.h" 
00077 #include "nsIAuthPrompt.h"
00078 #include "nsIPrefService.h"
00079 #include "nsIPrefBranch.h"
00080 #include "nsIPropertyBag2.h"
00081 #include "nsIWritablePropertyBag2.h"
00082 #include "nsChannelProperties.h"
00083 
00084 #include "nsISimpleEnumerator.h"
00085 #include "nsXPIDLString.h"
00086 #include "nsNetUtil.h"
00087 #include "prlog.h"
00088 #include "prtime.h"
00089 
00090 #include "nsInt64.h"
00091 
00092 #if defined(PR_LOGGING)
00093 //
00094 // set NSPR_LOG_MODULES=Test:5
00095 //
00096 static PRLogModuleInfo *gTestLog = nsnull;
00097 #endif
00098 #define LOG(args) PR_LOG(gTestLog, PR_LOG_DEBUG, args)
00099 
00100 static NS_DEFINE_CID(kEventQueueServiceCID,      NS_EVENTQUEUESERVICE_CID);
00101 static NS_DEFINE_CID(kIOServiceCID,              NS_IOSERVICE_CID);
00102 
00103 //static PRTime gElapsedTime; // enable when we time it...
00104 static int gKeepRunning = 0;
00105 static PRBool gVerbose = PR_FALSE;
00106 static nsIEventQueue* gEventQ = nsnull;
00107 static PRBool gAskUserForInput = PR_FALSE;
00108 static PRBool gResume = PR_FALSE;
00109 static PRUint64 gStartAt = 0;
00110 
00111 static const char* gEntityID;
00112 
00113 //-----------------------------------------------------------------------------
00114 // Set proxy preferences for testing
00115 //-----------------------------------------------------------------------------
00116 
00117 static nsresult
00118 SetHttpProxy(const char *proxy)
00119 {
00120   const char *colon = strchr(proxy, ':');
00121   if (!colon)
00122   {
00123     NS_WARNING("invalid proxy token; use host:port");
00124     return NS_ERROR_UNEXPECTED;
00125   }
00126   int port = atoi(colon + 1);
00127   if (port == 0)
00128   {
00129     NS_WARNING("invalid proxy port; must be an integer");
00130     return NS_ERROR_UNEXPECTED;
00131   }
00132   nsCAutoString proxyHost;
00133   proxyHost = Substring(proxy, colon);
00134 
00135   nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
00136   if (prefs)
00137   {
00138     prefs->SetCharPref("network.proxy.http", proxyHost.get());
00139     prefs->SetIntPref("network.proxy.http_port", port);
00140     prefs->SetIntPref("network.proxy.type", 1); // manual proxy config
00141   }
00142   LOG(("connecting via proxy=%s:%d\n", proxyHost.get(), port));
00143   return NS_OK;
00144 }
00145 
00146 //-----------------------------------------------------------------------------
00147 // HeaderVisitor
00148 //-----------------------------------------------------------------------------
00149 
00150 class HeaderVisitor : public nsIHttpHeaderVisitor
00151 {
00152 public:
00153   NS_DECL_ISUPPORTS
00154   NS_DECL_NSIHTTPHEADERVISITOR
00155 
00156   HeaderVisitor() { }
00157   virtual ~HeaderVisitor() {}
00158 };
00159 NS_IMPL_ISUPPORTS1(HeaderVisitor, nsIHttpHeaderVisitor)
00160 
00161 NS_IMETHODIMP
00162 HeaderVisitor::VisitHeader(const nsACString &header, const nsACString &value)
00163 {
00164   LOG(("  %s: %s\n",
00165     PromiseFlatCString(header).get(),
00166     PromiseFlatCString(value).get()));
00167   return NS_OK;
00168 }
00169 
00170 //-----------------------------------------------------------------------------
00171 // URLLoadInfo
00172 //-----------------------------------------------------------------------------
00173 
00174 class URLLoadInfo : public nsISupports
00175 {
00176 public:
00177 
00178   URLLoadInfo(const char* aUrl);
00179   virtual ~URLLoadInfo();
00180 
00181   // ISupports interface...
00182   NS_DECL_ISUPPORTS
00183 
00184   const char* Name() { return mURLString.get(); }
00185   nsInt64   mBytesRead;
00186   PRTime    mTotalTime;
00187   PRTime    mConnectTime;
00188   nsCString mURLString;
00189 };
00190 
00191 URLLoadInfo::URLLoadInfo(const char *aUrl) : mURLString(aUrl)
00192 {
00193   mBytesRead = 0;
00194   mConnectTime = mTotalTime = PR_Now();
00195 }
00196 
00197 URLLoadInfo::~URLLoadInfo()
00198 {
00199 }
00200 
00201 
00202 NS_IMPL_THREADSAFE_ISUPPORTS0(URLLoadInfo)
00203 
00204 //-----------------------------------------------------------------------------
00205 // TestChannelEventSink
00206 //-----------------------------------------------------------------------------
00207 
00208 class TestChannelEventSink : public nsIChannelEventSink
00209 {
00210 public:
00211   NS_DECL_ISUPPORTS
00212   NS_DECL_NSICHANNELEVENTSINK
00213 
00214   TestChannelEventSink();
00215   virtual ~TestChannelEventSink();
00216 };
00217 
00218 TestChannelEventSink::TestChannelEventSink()
00219 {
00220 }
00221 
00222 TestChannelEventSink::~TestChannelEventSink()
00223 {
00224 }
00225 
00226 
00227 NS_IMPL_ISUPPORTS1(TestChannelEventSink, nsIChannelEventSink)
00228 
00229 NS_IMETHODIMP
00230 TestChannelEventSink::OnChannelRedirect(nsIChannel *channel,
00231                                         nsIChannel *newChannel,
00232                                         PRUint32 flags)
00233 {
00234     LOG(("\n+++ TestChannelEventSink::OnChannelRedirect (with flags %x) +++\n",
00235          flags));
00236     return NS_OK;
00237 }
00238 
00239 //-----------------------------------------------------------------------------
00240 // TestAuthPrompt
00241 //-----------------------------------------------------------------------------
00242 
00243 class TestAuthPrompt : public nsIAuthPrompt
00244 {
00245 public:
00246   NS_DECL_ISUPPORTS
00247   NS_DECL_NSIAUTHPROMPT
00248 
00249   TestAuthPrompt();
00250   virtual ~TestAuthPrompt();
00251 };
00252 
00253 NS_IMPL_ISUPPORTS1(TestAuthPrompt, nsIAuthPrompt)
00254 
00255 TestAuthPrompt::TestAuthPrompt()
00256 {
00257 }
00258 
00259 TestAuthPrompt::~TestAuthPrompt()
00260 {
00261 }
00262 
00263 NS_IMETHODIMP
00264 TestAuthPrompt::Prompt(const PRUnichar *dialogTitle,
00265                        const PRUnichar *text,
00266                        const PRUnichar *passwordRealm,
00267                        PRUint32 savePassword,
00268                        const PRUnichar *defaultText,
00269                        PRUnichar **result,
00270                        PRBool *_retval)
00271 {
00272     *_retval = PR_FALSE;
00273     return NS_ERROR_NOT_IMPLEMENTED;
00274 }
00275 
00276 NS_IMETHODIMP
00277 TestAuthPrompt::PromptUsernameAndPassword(const PRUnichar *dialogTitle,
00278                                           const PRUnichar *dialogText,
00279                                           const PRUnichar *passwordRealm,
00280                                           PRUint32 savePassword,
00281                                           PRUnichar **user,
00282                                           PRUnichar **pwd,
00283                                           PRBool *_retval)
00284 {
00285     NS_ConvertUTF16toUTF8 text(passwordRealm);
00286     printf("* --------------------------------------------------------------------------- *\n");
00287     printf("* Authentication Required [%s]\n", text.get());
00288     printf("* --------------------------------------------------------------------------- *\n");
00289 
00290     char buf[256];
00291     int n;
00292 
00293     printf("Enter username: ");
00294     fgets(buf, sizeof(buf), stdin);
00295     n = strlen(buf);
00296     buf[n-1] = '\0'; // trim trailing newline
00297     *user = ToNewUnicode(nsDependentCString(buf));
00298 
00299     const char *p;
00300 #ifdef XP_UNIX
00301     p = getpass("Enter password: ");
00302 #else
00303     printf("Enter password: ");
00304     fgets(buf, sizeof(buf), stdin);
00305     n = strlen(buf);
00306     buf[n-1] = '\0'; // trim trailing newline
00307     p = buf;
00308 #endif
00309     *pwd = ToNewUnicode(nsDependentCString(p));
00310 
00311     // zap buf 
00312     memset(buf, 0, sizeof(buf));
00313 
00314     *_retval = PR_TRUE;
00315     return NS_OK;
00316 }
00317 
00318 NS_IMETHODIMP
00319 TestAuthPrompt::PromptPassword(const PRUnichar *dialogTitle,
00320                                const PRUnichar *text,
00321                                const PRUnichar *passwordRealm,
00322                                PRUint32 savePassword,
00323                                PRUnichar **pwd,
00324                                PRBool *_retval)
00325 {
00326     *_retval = PR_FALSE;
00327     return NS_ERROR_NOT_IMPLEMENTED;
00328 }
00329 
00330 //-----------------------------------------------------------------------------
00331 // InputTestConsumer
00332 //-----------------------------------------------------------------------------
00333 
00334 class InputTestConsumer : public nsIStreamListener
00335 {
00336 public:
00337 
00338   InputTestConsumer();
00339   virtual ~InputTestConsumer();
00340 
00341   NS_DECL_ISUPPORTS
00342   NS_DECL_NSIREQUESTOBSERVER
00343   NS_DECL_NSISTREAMLISTENER
00344 };
00345 
00346 InputTestConsumer::InputTestConsumer()
00347 {
00348 }
00349 
00350 InputTestConsumer::~InputTestConsumer()
00351 {
00352 }
00353 
00354 NS_IMPL_ISUPPORTS2(InputTestConsumer, nsIStreamListener, nsIRequestObserver)
00355 
00356 NS_IMETHODIMP
00357 InputTestConsumer::OnStartRequest(nsIRequest *request, nsISupports* context)
00358 {
00359   LOG(("InputTestConsumer::OnStartRequest\n"));
00360 
00361   URLLoadInfo* info = (URLLoadInfo*)context;
00362   if (info)
00363     info->mConnectTime = PR_Now() - info->mConnectTime;
00364 
00365   if (gVerbose)
00366     LOG(("\nStarted loading: %s\n", info ? info->Name() : "UNKNOWN URL"));
00367 
00368   nsCAutoString value;
00369 
00370   nsCOMPtr<nsIChannel> channel = do_QueryInterface(request);
00371   if (channel) {
00372     nsresult status;
00373     channel->GetStatus(&status);
00374     LOG(("Channel Status: %08x\n", status));
00375     if (NS_SUCCEEDED(status)) {
00376       LOG(("Channel Info:\n"));
00377 
00378       channel->GetName(value);
00379       LOG(("\tName: %s\n", value.get()));
00380 
00381       channel->GetContentType(value);
00382       LOG(("\tContent-Type: %s\n", value.get()));
00383 
00384       channel->GetContentCharset(value);
00385       LOG(("\tContent-Charset: %s\n", value.get()));
00386 
00387       PRInt32 length = -1;
00388       if (NS_SUCCEEDED(channel->GetContentLength(&length)))
00389         LOG(("\tContent-Length: %d\n", length));
00390       else
00391         LOG(("\tContent-Length: Unknown\n"));
00392     }
00393 
00394     nsCOMPtr<nsISupports> owner;
00395     channel->GetOwner(getter_AddRefs(owner));
00396     LOG(("\tChannel Owner: %x\n", owner.get()));
00397   }
00398 
00399   nsCOMPtr<nsIPropertyBag2> props = do_QueryInterface(request);
00400   if (props) {
00401       nsCOMPtr<nsIURI> foo;
00402       props->GetPropertyAsInterface(NS_LITERAL_STRING("test.foo"),
00403                                     NS_GET_IID(nsIURI),
00404                                     getter_AddRefs(foo));
00405       if (foo) {
00406           nsCAutoString spec;
00407           foo->GetSpec(spec);
00408           LOG(("\ttest.foo: %s\n", spec.get()));
00409       }
00410   }
00411 
00412   nsCOMPtr<nsIPropertyBag2> propbag = do_QueryInterface(request);
00413   if (propbag) {
00414       PRInt64 len;
00415       nsresult rv = propbag->GetPropertyAsInt64(NS_CHANNEL_PROP_CONTENT_LENGTH,
00416                                                 &len);
00417       if (NS_SUCCEEDED(rv))
00418           LOG(("\t64-bit length: %lli\n", len));
00419   }
00420 
00421   nsCOMPtr<nsIHttpChannelInternal> httpChannelInt(do_QueryInterface(request));
00422   if (httpChannelInt) {
00423       PRUint32 majorVer, minorVer;
00424       nsresult rv = httpChannelInt->GetResponseVersion(&majorVer, &minorVer);
00425       if (NS_SUCCEEDED(rv))
00426           LOG(("HTTP Response version: %u.%u\n", majorVer, minorVer));
00427   }
00428   nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(request));
00429   if (httpChannel) {
00430     HeaderVisitor *visitor = new HeaderVisitor();
00431     if (!visitor)
00432       return NS_ERROR_OUT_OF_MEMORY;
00433     NS_ADDREF(visitor);
00434 
00435     LOG(("HTTP request headers:\n"));
00436     httpChannel->VisitRequestHeaders(visitor);
00437 
00438     LOG(("HTTP response headers:\n"));
00439     httpChannel->VisitResponseHeaders(visitor);
00440 
00441     NS_RELEASE(visitor);
00442   }
00443 
00444   nsCOMPtr<nsIResumableChannel> resChannel = do_QueryInterface(request);
00445   if (resChannel) {
00446       LOG(("Resumable entity identification:\n"));
00447       nsCAutoString entityID;
00448       nsresult rv = resChannel->GetEntityID(entityID);
00449       if (NS_SUCCEEDED(rv)) {
00450           LOG(("\t|%s|\n", entityID.get()));
00451       }
00452       else {
00453           LOG(("\t<none>\n"));
00454       }
00455   }
00456 
00457   return NS_OK;
00458 }
00459 
00460 NS_IMETHODIMP
00461 InputTestConsumer::OnDataAvailable(nsIRequest *request, 
00462                                    nsISupports* context,
00463                                    nsIInputStream *aIStream, 
00464                                    PRUint32 aSourceOffset,
00465                                    PRUint32 aLength)
00466 {
00467   char buf[1025];
00468   PRUint32 amt, size;
00469   nsresult rv;
00470   URLLoadInfo* info = (URLLoadInfo*)context;
00471 
00472   while (aLength) {
00473     size = PR_MIN(aLength, sizeof(buf));
00474 
00475     rv = aIStream->Read(buf, size, &amt);
00476     if (NS_FAILED(rv)) {
00477       NS_ASSERTION((NS_BASE_STREAM_WOULD_BLOCK != rv), 
00478                    "The stream should never block.");
00479       return rv;
00480     }
00481     if (gVerbose) {
00482       buf[amt] = '\0';
00483       puts(buf);
00484     }
00485     if (info) {
00486       info->mBytesRead += amt;
00487     }
00488 
00489     aLength -= amt;
00490   }
00491   return NS_OK;
00492 }
00493 
00494 PR_STATIC_CALLBACK(void) DecrementDestroyHandler(PLEvent *self) 
00495 {
00496     PR_Free(self);
00497 }
00498 
00499 
00500 PR_STATIC_CALLBACK(void*) DecrementEventHandler(PLEvent *self) 
00501 {
00502     gKeepRunning--;
00503     return nsnull;
00504 }
00505 
00506 void FireDecrement()
00507 {
00508     PLEvent *event = PR_NEW(PLEvent);
00509     PL_InitEvent(event, 
00510                nsnull,
00511                DecrementEventHandler,
00512                DecrementDestroyHandler);
00513 
00514     gEventQ->PostEvent(event);
00515 }
00516 
00517 NS_IMETHODIMP
00518 InputTestConsumer::OnStopRequest(nsIRequest *request, nsISupports* context,
00519                                  nsresult aStatus)
00520 {
00521   LOG(("InputTestConsumer::OnStopRequest [status=%x]\n", aStatus));
00522 
00523   URLLoadInfo* info = (URLLoadInfo*)context;
00524 
00525   if (info) {
00526     double connectTime;
00527     double readTime;
00528     PRUint32 httpStatus;
00529     PRBool bHTTPURL = PR_FALSE;
00530 
00531     info->mTotalTime = PR_Now() - info->mTotalTime;
00532 
00533     connectTime = (info->mConnectTime/1000.0)/1000.0;
00534     readTime    = ((info->mTotalTime-info->mConnectTime)/1000.0)/1000.0;
00535 
00536     nsCOMPtr<nsIHttpChannel> pHTTPCon(do_QueryInterface(request));
00537     if (pHTTPCon) {
00538         pHTTPCon->GetResponseStatus(&httpStatus);
00539         bHTTPURL = PR_TRUE;
00540     }
00541 
00542     LOG(("\nFinished loading: %s  Status Code: %x\n", info->Name(), aStatus));
00543     if (bHTTPURL)
00544         LOG(("\tHTTP Status: %u\n", httpStatus));
00545      if (NS_ERROR_UNKNOWN_HOST == aStatus ||
00546          NS_ERROR_UNKNOWN_PROXY_HOST == aStatus) {
00547          LOG(("\tDNS lookup failed.\n"));
00548      }
00549     LOG(("\tTime to connect: %.3f seconds\n", connectTime));
00550     LOG(("\tTime to read: %.3f seconds.\n", readTime));
00551     LOG(("\tRead: %lld bytes.\n", info->mBytesRead.mValue));
00552     if (info->mBytesRead == nsInt64(0)) {
00553     } else if (readTime > 0.0) {
00554       LOG(("\tThroughput: %.0f bps.\n", (PRFloat64)(info->mBytesRead*nsInt64(8))/readTime));
00555     } else {
00556       LOG(("\tThroughput: REAL FAST!!\n"));
00557     }
00558   } else {
00559     LOG(("\nFinished loading: UNKNOWN URL. Status Code: %x\n", aStatus));
00560   }
00561 
00562   FireDecrement();
00563   return NS_OK;
00564 }
00565 
00566 //-----------------------------------------------------------------------------
00567 // NotificationCallbacks
00568 //-----------------------------------------------------------------------------
00569 
00570 class NotificationCallbacks : public nsIInterfaceRequestor {
00571 public:
00572     NS_DECL_ISUPPORTS
00573 
00574     NotificationCallbacks() {
00575     }
00576 
00577     NS_IMETHOD GetInterface(const nsIID& iid, void* *result) {
00578         nsresult rv = NS_ERROR_FAILURE;
00579 
00580         if (iid.Equals(NS_GET_IID(nsIChannelEventSink))) {
00581           TestChannelEventSink *sink;
00582 
00583           sink = new TestChannelEventSink();
00584           if (sink == nsnull)
00585             return NS_ERROR_OUT_OF_MEMORY;
00586           NS_ADDREF(sink);
00587           rv = sink->QueryInterface(iid, result);
00588           NS_RELEASE(sink);
00589         }
00590 
00591         if (iid.Equals(NS_GET_IID(nsIAuthPrompt))) {
00592           TestAuthPrompt *prompt;
00593 
00594           prompt = new TestAuthPrompt();
00595           if (prompt == nsnull)
00596             return NS_ERROR_OUT_OF_MEMORY;
00597           NS_ADDREF(prompt);
00598           rv = prompt->QueryInterface(iid, result);
00599           NS_RELEASE(prompt);
00600         }
00601         return rv;
00602     }
00603 };
00604 
00605 NS_IMPL_ISUPPORTS1(NotificationCallbacks, nsIInterfaceRequestor)
00606 
00607 //-----------------------------------------------------------------------------
00608 // helpers...
00609 //-----------------------------------------------------------------------------
00610 
00611 nsresult StartLoadingURL(const char* aUrlString)
00612 {
00613     nsresult rv;
00614 
00615     nsCOMPtr<nsIIOService> pService(do_GetService(kIOServiceCID, &rv));
00616     if (pService) {
00617         nsCOMPtr<nsIURI> pURL;
00618 
00619         rv = pService->NewURI(nsDependentCString(aUrlString), nsnull, nsnull, getter_AddRefs(pURL));
00620         if (NS_FAILED(rv)) {
00621             LOG(("ERROR: NewURI failed for %s [rv=%x]\n", aUrlString));
00622             return rv;
00623         }
00624         nsCOMPtr<nsIChannel> pChannel;
00625 
00626         NotificationCallbacks* callbacks = new NotificationCallbacks();
00627         if (!callbacks) {
00628             LOG(("Failed to create a new consumer!"));
00629             return NS_ERROR_OUT_OF_MEMORY;;
00630         }
00631         NS_ADDREF(callbacks);
00632 
00633         // Async reading thru the calls of the event sink interface
00634         rv = NS_NewChannel(getter_AddRefs(pChannel), pURL, pService,
00635                            nsnull,     // loadGroup
00636                            callbacks); // notificationCallbacks
00637         NS_RELEASE(callbacks);
00638         if (NS_FAILED(rv)) {
00639             LOG(("ERROR: NS_OpenURI failed for %s [rv=%x]\n", aUrlString, rv));
00640             return rv;
00641         }
00642 
00643         nsCOMPtr<nsIWritablePropertyBag2> props = do_QueryInterface(pChannel);
00644         if (props) {
00645             rv = props->SetPropertyAsInterface(NS_LITERAL_STRING("test.foo"),
00646                                                pURL);
00647             if (NS_SUCCEEDED(rv))
00648                 LOG(("set prop 'test.foo'\n"));
00649         }
00650 
00651         /* 
00652            You may optionally add/set other headers on this
00653            request object. This is done by QI for the specific
00654            protocolConnection.
00655         */
00656         nsCOMPtr<nsIHttpChannel> pHTTPCon(do_QueryInterface(pChannel));
00657 
00658         if (pHTTPCon) {
00659             // Setting a sample header.
00660             rv = pHTTPCon->SetRequestHeader(NS_LITERAL_CSTRING("sample-header"),
00661                                             NS_LITERAL_CSTRING("Sample-Value"),
00662                                             PR_FALSE);
00663             if (NS_FAILED(rv)) return rv;
00664         }            
00665         InputTestConsumer* listener;
00666 
00667         listener = new InputTestConsumer;
00668         NS_IF_ADDREF(listener);
00669         if (!listener) {
00670             NS_ERROR("Failed to create a new stream listener!");
00671             return NS_ERROR_OUT_OF_MEMORY;;
00672         }
00673 
00674         URLLoadInfo* info;
00675         info = new URLLoadInfo(aUrlString);
00676         NS_IF_ADDREF(info);
00677         if (!info) {
00678             NS_ERROR("Failed to create a load info!");
00679             return NS_ERROR_OUT_OF_MEMORY;
00680         }
00681 
00682         if (gResume) {
00683             nsCOMPtr<nsIResumableChannel> res = do_QueryInterface(pChannel);
00684             if (!res) {
00685                 NS_ERROR("Channel is not resumable!");
00686                 return NS_ERROR_UNEXPECTED;
00687             }
00688             nsCAutoString id;
00689             if (gEntityID)
00690                 id = gEntityID;
00691             LOG(("* resuming at %llu bytes, with entity id |%s|\n", gStartAt, id.get()));
00692             res->ResumeAt(gStartAt, id);
00693         }
00694         rv = pChannel->AsyncOpen(listener,  // IStreamListener consumer
00695                                  info);
00696 
00697         if (NS_SUCCEEDED(rv)) {
00698             gKeepRunning += 1;
00699         }
00700         else {
00701             LOG(("ERROR: AsyncOpen failed [rv=%x]\n", rv));
00702         }
00703         NS_RELEASE(listener);
00704         NS_RELEASE(info);
00705     }
00706 
00707     return rv;
00708 }
00709 
00710 
00711 nsresult LoadURLsFromFile(char *aFileName)
00712 {
00713     nsresult rv = NS_OK;
00714     PRInt32 len, offset;
00715     PRFileDesc* fd;
00716     char buffer[1024];
00717     nsCString fileBuffer;
00718     nsCAutoString urlString;
00719 
00720     fd = PR_Open(aFileName, PR_RDONLY, 777);
00721     if (!fd) {
00722         return NS_ERROR_FAILURE;
00723     }
00724 
00725     // Keep reading the file until EOF (or an error) is reached...        
00726     do {
00727         len = PR_Read(fd, buffer, sizeof(buffer));
00728         if (len>0) {
00729             fileBuffer.Append(buffer, len);
00730             // Treat each line as a URL...
00731             while ((offset = fileBuffer.FindChar('\n')) != -1) {
00732                 fileBuffer.Left(urlString, offset);
00733                 fileBuffer.Cut(0, offset+1);
00734 
00735                 urlString.StripChars("\r");
00736                 if (urlString.Length()) {
00737                     LOG(("\t%s\n", urlString.get()));
00738                     rv = StartLoadingURL(urlString.get());
00739                 }
00740             }
00741         }
00742     } while (len>0);
00743 
00744     // If anything is left in the fileBuffer, treat it as a URL...
00745     fileBuffer.StripChars("\r");
00746     if (fileBuffer.Length()) {
00747         LOG(("\t%s\n", fileBuffer.get()));
00748         StartLoadingURL(fileBuffer.get());
00749     }
00750 
00751     PR_Close(fd);
00752     return NS_OK;
00753 }
00754 
00755 
00756 nsresult LoadURLFromConsole()
00757 {
00758     char buffer[1024];
00759     printf("Enter URL (\"q\" to start): ");
00760     scanf("%s", buffer);
00761     if (buffer[0]=='q') 
00762         gAskUserForInput = PR_FALSE;
00763     else
00764         StartLoadingURL(buffer);
00765     return NS_OK;
00766 }
00767 
00768 int
00769 main(int argc, char* argv[])
00770 {
00771     if (test_common_init(&argc, &argv) != 0)
00772         return -1;
00773 
00774     nsresult rv= (nsresult)-1;
00775     if (argc < 2) {
00776         printf("usage: %s [-verbose] [-file <name>] [-resume <startoffset> [-entityid <entityid>]] [-proxy <proxy>] [-console] <url> <url> ... \n", argv[0]);
00777         return -1;
00778     }
00779 
00780 #if defined(PR_LOGGING)
00781     gTestLog = PR_NewLogModule("Test");
00782 #endif
00783 
00784     /* 
00785       The following code only deals with XPCOM registration stuff. and setting
00786       up the event queues. Copied from TestSocketIO.cpp
00787     */
00788 
00789     rv = NS_InitXPCOM2(nsnull, nsnull, nsnull);
00790     if (NS_FAILED(rv)) return rv;
00791 
00792     {
00793         // Create the Event Queue for this thread...
00794         nsCOMPtr<nsIEventQueueService> eventQService =
00795                  do_GetService(kEventQueueServiceCID, &rv);
00796         if (NS_FAILED(rv)) return rv;
00797 
00798         eventQService->GetThreadEventQueue(NS_CURRENT_THREAD, &gEventQ);
00799 
00800         int i;
00801         LOG(("Trying to load:\n"));
00802         for (i=1; i<argc; i++) {
00803             // Turn on verbose printing...
00804             if (PL_strcasecmp(argv[i], "-verbose") == 0) {
00805                 gVerbose = PR_TRUE;
00806                 continue;
00807             }
00808 
00809             // Turn on netlib tracing...
00810             if (PL_strcasecmp(argv[i], "-file") == 0) {
00811                 LoadURLsFromFile(argv[++i]);
00812                 continue;
00813             }
00814 
00815             if (PL_strcasecmp(argv[i], "-console") == 0) {
00816                 gAskUserForInput = PR_TRUE;
00817                 continue;
00818             }
00819 
00820             if (PL_strcasecmp(argv[i], "-resume") == 0) {
00821                 gResume = PR_TRUE;
00822                 PR_sscanf(argv[++i], "%llu", &gStartAt);
00823                 continue;
00824             }
00825 
00826             if (PL_strcasecmp(argv[i], "-entityid") == 0) {
00827                 gEntityID = argv[++i];
00828                 continue;
00829             }
00830 
00831             if (PL_strcasecmp(argv[i], "-proxy") == 0) {
00832                 SetHttpProxy(argv[++i]);
00833                 continue;
00834             }
00835 
00836             LOG(("\t%s\n", argv[i]));
00837             rv = StartLoadingURL(argv[i]);
00838         }
00839       // Enter the message pump to allow the URL load to proceed.
00840         while ( gKeepRunning ) {
00841             PLEvent *gEvent;
00842             gEventQ->WaitForEvent(&gEvent);
00843             gEventQ->HandleEvent(gEvent);
00844         }
00845     } // this scopes the nsCOMPtrs
00846     // no nsCOMPtrs are allowed to be alive when you call NS_ShutdownXPCOM
00847     NS_ShutdownXPCOM(nsnull);
00848     return rv;
00849 }