Back to index

lightning-sunbird  0.9+nobinonly
TestSocketIO.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either the GNU General Public License Version 2 or later (the "GPL"), or
00026  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 #include <stdio.h>
00038 #include <signal.h>
00039 
00040 #ifdef WIN32
00041 #include <windows.h>
00042 #endif
00043 #ifdef OS2
00044 #include <os2.h>
00045 #endif
00046 
00047 #include "nspr.h"
00048 #include "nscore.h"
00049 #include "nsISocketTransportService.h"
00050 #include "nsIEventQueueService.h"
00051 #include "nsIServiceManager.h"
00052 #include "nsITransport.h"
00053 #include "nsIRequest.h"
00054 #include "nsIStreamProvider.h"
00055 #include "nsIStreamListener.h"
00056 #include "nsIPipe.h"
00057 #include "nsIOutputStream.h"
00058 #include "nsIInputStream.h"
00059 #include "nsCRT.h"
00060 #include "nsCOMPtr.h"
00061 #include "nsIByteArrayInputStream.h"
00062 
00063 #if defined(PR_LOGGING)
00064 static PRLogModuleInfo *gTestSocketIOLog;
00065 #define LOG(args) PR_LOG(gTestSocketIOLog, PR_LOG_DEBUG, args)
00066 #else
00067 #define LOG(args)
00068 #endif
00069 
00070 static NS_DEFINE_CID(kSocketTransportServiceCID, NS_SOCKETTRANSPORTSERVICE_CID);
00071 static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
00072 
00073 static PRTime gElapsedTime;
00074 static int gKeepRunning = 1;
00075 static nsIEventQueue* gEventQ = nsnull;
00076 
00077 //
00078 //----------------------------------------------------------------------------
00079 // Test Listener
00080 //----------------------------------------------------------------------------
00081 //
00082 
00083 class TestListener : public nsIStreamListener
00084 {
00085 public:
00086     TestListener() {}
00087     virtual ~TestListener() {}
00088 
00089     NS_DECL_ISUPPORTS
00090     NS_DECL_NSIREQUESTOBSERVER
00091     NS_DECL_NSISTREAMLISTENER
00092 };
00093 
00094 NS_IMPL_ISUPPORTS2(TestListener,
00095                    nsIRequestObserver,
00096                    nsIStreamListener);
00097 
00098 NS_IMETHODIMP
00099 TestListener::OnStartRequest(nsIRequest* request, nsISupports* context)
00100 {
00101     LOG(("TestListener::OnStartRequest\n"));
00102     return NS_OK;
00103 }
00104 
00105 NS_IMETHODIMP
00106 TestListener::OnDataAvailable(nsIRequest* request,
00107                               nsISupports* context,
00108                               nsIInputStream *aIStream, 
00109                               PRUint32 aSourceOffset,
00110                               PRUint32 aLength)
00111 {
00112     LOG(("TestListener::OnDataAvailable [offset=%u length=%u]\n",
00113         aSourceOffset, aLength));
00114     char buf[1025];
00115     PRUint32 amt;
00116     while (1) {
00117         aIStream->Read(buf, 1024, &amt);
00118         if (amt == 0)
00119             break;
00120         buf[amt] = '\0';
00121         puts(buf);
00122     }
00123     return NS_OK;
00124 }
00125 
00126 NS_IMETHODIMP
00127 TestListener::OnStopRequest(nsIRequest* request, nsISupports* context,
00128                             nsresult aStatus)
00129 {
00130     LOG(("TestListener::OnStopRequest [aStatus=%x]\n", aStatus));
00131     gKeepRunning = 0;
00132     return NS_OK;
00133 }
00134 
00135 //
00136 //----------------------------------------------------------------------------
00137 // Test Provider
00138 //----------------------------------------------------------------------------
00139 //
00140 
00141 class TestProvider : public nsIStreamProvider
00142 {
00143 public:
00144     TestProvider(char *data);
00145     virtual ~TestProvider();
00146 
00147     NS_DECL_ISUPPORTS
00148     NS_DECL_NSIREQUESTOBSERVER
00149     NS_DECL_NSISTREAMPROVIDER
00150 
00151 protected:
00152     nsCOMPtr<nsIByteArrayInputStream> mData;
00153 };
00154 
00155 NS_IMPL_ISUPPORTS2(TestProvider,
00156                    nsIStreamProvider,
00157                    nsIRequestObserver)
00158 
00159 TestProvider::TestProvider(char *data)
00160 {
00161     NS_NewByteArrayInputStream(getter_AddRefs(mData), data, strlen(data));
00162     LOG(("Constructing TestProvider [this=%x]\n", this));
00163 }
00164 
00165 TestProvider::~TestProvider()
00166 {
00167     LOG(("Destroying TestProvider [this=%x]\n", this));
00168 }
00169 
00170 NS_IMETHODIMP
00171 TestProvider::OnStartRequest(nsIRequest* request, nsISupports* context)
00172 {
00173     LOG(("TestProvider::OnStartRequest [this=%x]\n", this));
00174     return NS_OK;
00175 }
00176 
00177 NS_IMETHODIMP
00178 TestProvider::OnStopRequest(nsIRequest* request, nsISupports* context,
00179                             nsresult aStatus)
00180 {
00181     LOG(("TestProvider::OnStopRequest [status=%x]\n", aStatus));
00182 
00183     nsCOMPtr<nsIStreamListener> listener = do_QueryInterface(new TestListener());
00184 
00185     if (NS_SUCCEEDED(aStatus)) {
00186         nsCOMPtr<nsITransportRequest> treq = do_QueryInterface(request);
00187         nsCOMPtr<nsITransport> transport;
00188         treq->GetTransport(getter_AddRefs(transport));
00189         if (transport) {
00190             nsCOMPtr<nsIRequest> readRequest;
00191             transport->AsyncRead(listener, nsnull, 0, 0, 0, getter_AddRefs(readRequest));
00192         }
00193     } else
00194         gKeepRunning = 0;
00195 
00196     return NS_OK;
00197 }
00198 
00199 NS_IMETHODIMP
00200 TestProvider::OnDataWritable(nsIRequest *request, nsISupports *context,
00201                              nsIOutputStream *output, PRUint32 offset, PRUint32 count)
00202 {
00203     LOG(("TestProvider::OnDataWritable [offset=%u, count=%u]\n", offset, count));
00204     PRUint32 writeCount;
00205     nsresult rv = output->WriteFrom(mData, count, &writeCount);
00206     // Zero bytes written on success indicates EOF
00207     if (NS_SUCCEEDED(rv) && (writeCount == 0))
00208         return NS_BASE_STREAM_CLOSED;
00209     return rv;
00210 }
00211 
00212 //
00213 //----------------------------------------------------------------------------
00214 // Synchronous IO
00215 //----------------------------------------------------------------------------
00216 //
00217 nsresult
00218 WriteRequest(nsIOutputStream *os, const char *request)
00219 {
00220     LOG(("WriteRequest [request=%s]\n", request));
00221     PRUint32 n;
00222     return os->Write(request, strlen(request), &n);
00223 }
00224 
00225 nsresult
00226 ReadResponse(nsIInputStream *is)
00227 {
00228     PRUint32 bytesRead;
00229     char buf[2048];
00230     do {
00231         is->Read(buf, sizeof(buf), &bytesRead);
00232         if (bytesRead > 0)
00233             fwrite(buf, 1, bytesRead, stdout);
00234     } while (bytesRead > 0);
00235     return NS_OK;
00236 }
00237 
00238 //
00239 //----------------------------------------------------------------------------
00240 // Startup...
00241 //----------------------------------------------------------------------------
00242 //
00243 
00244 void
00245 sighandler(int sig)
00246 {
00247     LOG(("got signal: %d\n", sig));
00248     NS_BREAK();
00249 }
00250 
00251 void
00252 usage(char **argv)
00253 {
00254     printf("usage: %s [-sync] <host> <path>\n", argv[0]);
00255     exit(1);
00256 }
00257 
00258 int
00259 main(int argc, char* argv[])
00260 {
00261     nsresult rv;
00262 
00263     signal(SIGSEGV, sighandler);
00264 
00265 #if defined(PR_LOGGING)
00266     gTestSocketIOLog = PR_NewLogModule("TestSocketIO");
00267 #endif
00268 
00269     if (argc < 3)
00270         usage(argv);
00271 
00272     PRIntn i=0;
00273     PRBool sync = PR_FALSE;
00274     if (nsCRT::strcasecmp(argv[1], "-sync") == 0) {
00275         if (argc < 4)
00276             usage(argv);
00277         sync = PR_TRUE;
00278         i = 1;
00279     }
00280 
00281     char *hostName = argv[1+i];
00282     char *fileName = argv[2+i];
00283     int port = 80;
00284 
00285     // Create the Event Queue for this thread...
00286     nsCOMPtr<nsIEventQueueService> eventQService = 
00287              do_GetService(kEventQueueServiceCID, &rv);
00288     if (NS_FAILED(rv)) {
00289         NS_WARNING("failed to create: event queue service!");
00290         return rv;
00291     }
00292 
00293     rv = eventQService->CreateMonitoredThreadEventQueue();
00294     if (NS_FAILED(rv)) {
00295         NS_WARNING("failed to create: thread event queue!");
00296         return rv;
00297     }
00298 
00299     eventQService->GetThreadEventQueue(NS_CURRENT_THREAD, &gEventQ);
00300 
00301     // Create the Socket transport service...
00302     nsCOMPtr<nsISocketTransportService> sts = 
00303              do_GetService(kSocketTransportServiceCID, &rv);
00304     if (NS_FAILED(rv)) {
00305         NS_WARNING("failed to create: socket transport service!");
00306         return rv;
00307     }
00308 
00309     char *buffer = PR_smprintf("GET %s HTTP/1.1" CRLF
00310                                "host: %s" CRLF
00311                                "user-agent: Mozilla/5.0 (X11; N; Linux 2.2.16-22smp i686; en-US; m18) Gecko/20001220" CRLF
00312                                "accept: */*" CRLF
00313                                "accept-language: en" CRLF
00314                                "accept-encoding: gzip,deflate,compress,identity" CRLF
00315                                "keep-alive: 300" CRLF
00316                                "connection: keep-alive" CRLF
00317                                 CRLF,
00318                                 fileName, hostName);
00319     LOG(("Request [\n%s]\n", buffer));
00320 
00321     // Create the socket transport...
00322     nsCOMPtr<nsITransport> transport;
00323     rv = sts->CreateTransport(hostName, port, nsnull, 0, 0, getter_AddRefs(transport));
00324     if (NS_FAILED(rv)) {
00325         NS_WARNING("failed to create: socket transport!");
00326         return rv;
00327     }
00328 
00329     gElapsedTime = PR_Now();
00330 
00331     if (!sync) {
00332         nsCOMPtr<nsIRequest> request;
00333         rv = transport->AsyncWrite(new TestProvider(buffer), nsnull, 0, 0, 0, getter_AddRefs(request));
00334         if (NS_FAILED(rv)) {
00335             NS_WARNING("failed calling: AsyncWrite!");
00336             return rv;
00337         }
00338 
00339         // Enter the message pump to allow the URL load to proceed.
00340         while ( gKeepRunning ) {
00341             PLEvent *gEvent;
00342             gEventQ->WaitForEvent(&gEvent);
00343             gEventQ->HandleEvent(gEvent);
00344         }
00345     }
00346     else {
00347         // synchronous write
00348         {
00349             nsCOMPtr<nsIOutputStream> os;
00350             rv = transport->OpenOutputStream(0, 0, 0, getter_AddRefs(os));
00351             if (NS_FAILED(rv)) {
00352                 LOG(("OpenOutputStream failed [rv=%x]\n", rv));
00353                 return rv;
00354             }
00355             rv = WriteRequest(os, buffer);
00356             if (NS_FAILED(rv)) {
00357                 LOG(("WriteRequest failed [rv=%x]\n", rv));
00358                 return rv;
00359             }
00360         }
00361         // synchronous read
00362         {
00363             nsCOMPtr<nsIInputStream> is;
00364             rv = transport->OpenInputStream(0, 0, 0, getter_AddRefs(is));
00365             if (NS_FAILED(rv)) {
00366                 LOG(("OpenInputStream failed [rv=%x]\n", rv));
00367                 return rv;
00368             }
00369             rv = ReadResponse(is);
00370             if (NS_FAILED(rv)) {
00371                 LOG(("ReadResponse failed [rv=%x]\n", rv));
00372                 return rv;
00373             }
00374         }
00375     }
00376 
00377     PRTime endTime; 
00378     endTime = PR_Now();
00379     LOG(("Elapsed time: %d\n", (PRInt32)(endTime/1000UL - gElapsedTime/1000UL)));
00380 
00381     sts->Shutdown();
00382     return 0;
00383 }
00384