Back to index

lightning-sunbird  0.9+nobinonly
TestOverlappedIO.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         printf("read %d bytes\n", amt);
00123     }
00124     return NS_OK;
00125 }
00126 
00127 NS_IMETHODIMP
00128 TestListener::OnStopRequest(nsIRequest* request, nsISupports* context,
00129                             nsresult aStatus)
00130 {
00131     LOG(("TestListener::OnStopRequest [aStatus=%x]\n", aStatus));
00132     //gKeepRunning = 0;
00133     return NS_OK;
00134 }
00135 
00136 //
00137 //----------------------------------------------------------------------------
00138 // Test Provider
00139 //----------------------------------------------------------------------------
00140 //
00141 
00142 class TestProvider : public nsIStreamProvider
00143 {
00144 public:
00145     TestProvider(char *data);
00146     virtual ~TestProvider();
00147 
00148     NS_DECL_ISUPPORTS
00149     NS_DECL_NSIREQUESTOBSERVER
00150     NS_DECL_NSISTREAMPROVIDER
00151 
00152 protected:
00153     char    *mData;
00154     PRUint32 mOffset;
00155     PRUint32 mDataLen;   
00156     PRUint32 mRequestCount;
00157 };
00158 
00159 NS_IMPL_ISUPPORTS2(TestProvider,
00160                    nsIStreamProvider,
00161                    nsIRequestObserver)
00162 
00163 TestProvider::TestProvider(char *data)
00164 {
00165     mData = data;
00166     mDataLen = strlen(data);
00167     mOffset = 0;
00168     mRequestCount = 0;
00169     LOG(("Constructing TestProvider [this=%x]\n", this));
00170 }
00171 
00172 TestProvider::~TestProvider()
00173 {
00174     LOG(("Destroying TestProvider [this=%x]\n", this));
00175 }
00176 
00177 NS_IMETHODIMP
00178 TestProvider::OnStartRequest(nsIRequest* request, nsISupports* context)
00179 {
00180     LOG(("TestProvider::OnStartRequest [this=%x]\n", this));
00181     return NS_OK;
00182 }
00183 
00184 NS_IMETHODIMP
00185 TestProvider::OnStopRequest(nsIRequest* request, nsISupports* context,
00186                             nsresult aStatus)
00187 {
00188     LOG(("TestProvider::OnStopRequest [status=%x]\n", aStatus));
00189     return NS_OK;
00190 }
00191 
00192 NS_IMETHODIMP
00193 TestProvider::OnDataWritable(nsIRequest *request, nsISupports *context,
00194                              nsIOutputStream *output, PRUint32 offset, PRUint32 count)
00195 {
00196     LOG(("TestProvider::OnDataWritable [offset=%u, count=%u]\n", offset, count));
00197 
00198     // Stop at 5 requests
00199     if (mRequestCount == 5)
00200         return NS_BASE_STREAM_CLOSED;
00201 
00202     PRUint32 writeCount, amount;
00203     amount = PR_MIN(count, mDataLen - mOffset);
00204     nsresult rv = output->Write(mData + mOffset, amount, &writeCount);
00205     if (NS_SUCCEEDED(rv)) {
00206         printf("wrote %u bytes\n", writeCount);
00207         mOffset += writeCount;
00208         if (mOffset == mDataLen) {
00209             printf("done sending packet %u\n", mRequestCount);
00210             mOffset = 0;
00211             mRequestCount++;
00212         }
00213     }
00214     return NS_OK;
00215 }
00216 
00217 //
00218 //----------------------------------------------------------------------------
00219 // Synchronous IO
00220 //----------------------------------------------------------------------------
00221 //
00222 nsresult
00223 WriteRequest(nsIOutputStream *os, const char *request)
00224 {
00225     LOG(("WriteRequest [request=%s]\n", request));
00226     PRUint32 n;
00227     return os->Write(request, strlen(request), &n);
00228 }
00229 
00230 nsresult
00231 ReadResponse(nsIInputStream *is)
00232 {
00233     PRUint32 bytesRead;
00234     char buf[2048];
00235     do {
00236         is->Read(buf, sizeof(buf), &bytesRead);
00237         if (bytesRead > 0)
00238             fwrite(buf, 1, bytesRead, stdout);
00239     } while (bytesRead > 0);
00240     return NS_OK;
00241 }
00242 
00243 //
00244 //----------------------------------------------------------------------------
00245 // Startup...
00246 //----------------------------------------------------------------------------
00247 //
00248 
00249 void
00250 sighandler(int sig)
00251 {
00252     LOG(("got signal: %d\n", sig));
00253     NS_BREAK();
00254 }
00255 
00256 void
00257 usage(char **argv)
00258 {
00259     printf("usage: %s <host> <path>\n", argv[0]);
00260     exit(1);
00261 }
00262 
00263 int
00264 main(int argc, char* argv[])
00265 {
00266     nsresult rv;
00267 
00268     signal(SIGSEGV, sighandler);
00269 
00270 #if defined(PR_LOGGING)
00271     gTestSocketIOLog = PR_NewLogModule("TestSocketIO");
00272 #endif
00273 
00274     if (argc < 3)
00275         usage(argv);
00276 
00277     char *hostName = argv[1];
00278     char *fileName = argv[2];
00279     int port = 80;
00280 
00281     // Create the Event Queue for this thread...
00282     nsCOMPtr<nsIEventQueueService> eventQService = 
00283              do_GetService(kEventQueueServiceCID, &rv);
00284     if (NS_FAILED(rv)) {
00285         NS_WARNING("failed to create: event queue service!");
00286         return rv;
00287     }
00288 
00289     rv = eventQService->CreateMonitoredThreadEventQueue();
00290     if (NS_FAILED(rv)) {
00291         NS_WARNING("failed to create: thread event queue!");
00292         return rv;
00293     }
00294 
00295     eventQService->GetThreadEventQueue(NS_CURRENT_THREAD, &gEventQ);
00296 
00297     // Create the Socket transport service...
00298     nsCOMPtr<nsISocketTransportService> sts = 
00299              do_GetService(kSocketTransportServiceCID, &rv);
00300     if (NS_FAILED(rv)) {
00301         NS_WARNING("failed to create: socket transport service!");
00302         return rv;
00303     }
00304 
00305     char *buffer = PR_smprintf("GET %s HTTP/1.1" CRLF
00306                                "host: %s" CRLF
00307                                "user-agent: Mozilla/5.0 (X11; N; Linux 2.2.16-22smp i686; en-US; m18) Gecko/20001220" CRLF
00308                                "accept: */*" CRLF
00309                                "accept-language: en" CRLF
00310                                "accept-encoding: gzip,deflate,compress,identity" CRLF
00311                                "keep-alive: 300" CRLF
00312                                "connection: keep-alive" CRLF
00313                                 CRLF,
00314                                 fileName, hostName);
00315     LOG(("Request [\n%s]\n", buffer));
00316 
00317     // Create the socket transport...
00318     nsCOMPtr<nsITransport> transport;
00319     rv = sts->CreateTransport(hostName, port, nsnull, -1, 0, 0, getter_AddRefs(transport));
00320     if (NS_FAILED(rv)) {
00321         NS_WARNING("failed to create: socket transport!");
00322         return rv;
00323     }
00324 
00325     gElapsedTime = PR_Now();
00326 
00327     nsCOMPtr<nsIRequest> writeRequest, readRequest;
00328 
00329     rv = transport->AsyncWrite(new TestProvider(buffer), nsnull, 0, 0, 0, getter_AddRefs(writeRequest));
00330     if (NS_FAILED(rv)) {
00331         NS_WARNING("failed calling: AsyncWrite!");
00332         return rv;
00333     }
00334     rv = transport->AsyncRead(new TestListener(), nsnull, 0, 0, 0, getter_AddRefs(readRequest));
00335     if (NS_FAILED(rv)) {
00336         NS_WARNING("failed calling: AsyncWrite!");
00337         return rv;
00338     }
00339 
00340     // Enter the message pump
00341     while ( gKeepRunning ) {
00342         PLEvent *gEvent;
00343         gEventQ->WaitForEvent(&gEvent);
00344         gEventQ->HandleEvent(gEvent);
00345     }
00346 
00347     PRTime endTime; 
00348     endTime = PR_Now();
00349     LOG(("Elapsed time: %d\n", (PRInt32)(endTime/1000UL - gElapsedTime/1000UL)));
00350 
00351     sts->Shutdown();
00352     return 0;
00353 }