netwerk/test/TestOverlappedIO.cpp

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 #include <stdio.h>
     6 #include <signal.h>
     7 #include <algorithm>
     9 #ifdef WIN32
    10 #include <windows.h>
    11 #endif
    13 #include "nspr.h"
    14 #include "nscore.h"
    15 #include "nsISocketTransportService.h"
    16 #include "nsIEventQueueService.h"
    17 #include "nsIServiceManager.h"
    18 #include "nsITransport.h"
    19 #include "nsIRequest.h"
    20 #include "nsIStreamProvider.h"
    21 #include "nsIStreamListener.h"
    22 #include "nsIPipe.h"
    23 #include "nsIOutputStream.h"
    24 #include "nsIInputStream.h"
    25 #include "nsCRT.h"
    26 #include "nsCOMPtr.h"
    27 #include "nsIByteArrayInputStream.h"
    29 #if defined(PR_LOGGING)
    30 static PRLogModuleInfo *gTestSocketIOLog;
    31 #define LOG(args) PR_LOG(gTestSocketIOLog, PR_LOG_DEBUG, args)
    32 #else
    33 #define LOG(args)
    34 #endif
    36 static NS_DEFINE_CID(kSocketTransportServiceCID, NS_SOCKETTRANSPORTSERVICE_CID);
    37 static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
    39 static PRTime gElapsedTime;
    40 static int gKeepRunning = 1;
    41 static nsIEventQueue* gEventQ = nullptr;
    43 //
    44 //----------------------------------------------------------------------------
    45 // Test Listener
    46 //----------------------------------------------------------------------------
    47 //
    49 class TestListener : public nsIStreamListener
    50 {
    51 public:
    52     TestListener() { }
    53     virtual ~TestListener() {}
    55     NS_DECL_ISUPPORTS
    56     NS_DECL_NSIREQUESTOBSERVER
    57     NS_DECL_NSISTREAMLISTENER
    58 };
    60 NS_IMPL_ISUPPORTS(TestListener,
    61                   nsIRequestObserver,
    62                   nsIStreamListener);
    64 NS_IMETHODIMP
    65 TestListener::OnStartRequest(nsIRequest* request, nsISupports* context)
    66 {
    67     LOG(("TestListener::OnStartRequest\n"));
    68     return NS_OK;
    69 }
    71 NS_IMETHODIMP
    72 TestListener::OnDataAvailable(nsIRequest* request,
    73                               nsISupports* context,
    74                               nsIInputStream *aIStream, 
    75                               uint64_t aSourceOffset,
    76                               uint32_t aLength)
    77 {
    78     LOG(("TestListener::OnDataAvailable [offset=%llu length=%u]\n",
    79         aSourceOffset, aLength));
    80     char buf[1025];
    81     uint32_t amt;
    82     while (1) {
    83         aIStream->Read(buf, 1024, &amt);
    84         if (amt == 0)
    85             break;
    86         buf[amt] = '\0';
    87         //puts(buf);
    88         printf("read %d bytes\n", amt);
    89     }
    90     return NS_OK;
    91 }
    93 NS_IMETHODIMP
    94 TestListener::OnStopRequest(nsIRequest* request, nsISupports* context,
    95                             nsresult aStatus)
    96 {
    97     LOG(("TestListener::OnStopRequest [aStatus=%x]\n", aStatus));
    98     //gKeepRunning = 0;
    99     return NS_OK;
   100 }
   102 //
   103 //----------------------------------------------------------------------------
   104 // Test Provider
   105 //----------------------------------------------------------------------------
   106 //
   108 class TestProvider : public nsIStreamProvider
   109 {
   110 public:
   111     TestProvider(char *data);
   112     virtual ~TestProvider();
   114     NS_DECL_ISUPPORTS
   115     NS_DECL_NSIREQUESTOBSERVER
   116     NS_DECL_NSISTREAMPROVIDER
   118 protected:
   119     char    *mData;
   120     uint32_t mOffset;
   121     uint32_t mDataLen;   
   122     uint32_t mRequestCount;
   123 };
   125 NS_IMPL_ISUPPORTS(TestProvider,
   126                   nsIStreamProvider,
   127                   nsIRequestObserver)
   129 TestProvider::TestProvider(char *data)
   130 {
   131     mData = data;
   132     mDataLen = strlen(data);
   133     mOffset = 0;
   134     mRequestCount = 0;
   135     LOG(("Constructing TestProvider [this=%p]\n", this));
   136 }
   138 TestProvider::~TestProvider()
   139 {
   140     LOG(("Destroying TestProvider [this=%p]\n", this));
   141 }
   143 NS_IMETHODIMP
   144 TestProvider::OnStartRequest(nsIRequest* request, nsISupports* context)
   145 {
   146     LOG(("TestProvider::OnStartRequest [this=%p]\n", this));
   147     return NS_OK;
   148 }
   150 NS_IMETHODIMP
   151 TestProvider::OnStopRequest(nsIRequest* request, nsISupports* context,
   152                             nsresult aStatus)
   153 {
   154     LOG(("TestProvider::OnStopRequest [status=%x]\n", aStatus));
   155     return NS_OK;
   156 }
   158 NS_IMETHODIMP
   159 TestProvider::OnDataWritable(nsIRequest *request, nsISupports *context,
   160                              nsIOutputStream *output, uint32_t offset, uint32_t count)
   161 {
   162     LOG(("TestProvider::OnDataWritable [offset=%u, count=%u]\n", offset, count));
   164     // Stop at 5 requests
   165     if (mRequestCount == 5)
   166         return NS_BASE_STREAM_CLOSED;
   168     uint32_t writeCount, amount;
   169     amount = std::min(count, mDataLen - mOffset);
   170     nsresult rv = output->Write(mData + mOffset, amount, &writeCount);
   171     if (NS_SUCCEEDED(rv)) {
   172         printf("wrote %u bytes\n", writeCount);
   173         mOffset += writeCount;
   174         if (mOffset == mDataLen) {
   175             printf("done sending packet %u\n", mRequestCount);
   176             mOffset = 0;
   177             mRequestCount++;
   178         }
   179     }
   180     return NS_OK;
   181 }
   183 //
   184 //----------------------------------------------------------------------------
   185 // Synchronous IO
   186 //----------------------------------------------------------------------------
   187 //
   188 nsresult
   189 WriteRequest(nsIOutputStream *os, const char *request)
   190 {
   191     LOG(("WriteRequest [request=%s]\n", request));
   192     uint32_t n;
   193     return os->Write(request, strlen(request), &n);
   194 }
   196 nsresult
   197 ReadResponse(nsIInputStream *is)
   198 {
   199     uint32_t bytesRead;
   200     char buf[2048];
   201     do {
   202         is->Read(buf, sizeof(buf), &bytesRead);
   203         if (bytesRead > 0)
   204             fwrite(buf, 1, bytesRead, stdout);
   205     } while (bytesRead > 0);
   206     return NS_OK;
   207 }
   209 //
   210 //----------------------------------------------------------------------------
   211 // Startup...
   212 //----------------------------------------------------------------------------
   213 //
   215 void
   216 sighandler(int sig)
   217 {
   218     LOG(("got signal: %d\n", sig));
   219     NS_BREAK();
   220 }
   222 void
   223 usage(char **argv)
   224 {
   225     printf("usage: %s <host> <path>\n", argv[0]);
   226     exit(1);
   227 }
   229 int
   230 main(int argc, char* argv[])
   231 {
   232     nsresult rv;
   234     signal(SIGSEGV, sighandler);
   236 #if defined(PR_LOGGING)
   237     gTestSocketIOLog = PR_NewLogModule("TestSocketIO");
   238 #endif
   240     if (argc < 3)
   241         usage(argv);
   243     char *hostName = argv[1];
   244     char *fileName = argv[2];
   245     int port = 80;
   247     // Create the Event Queue for this thread...
   248     nsCOMPtr<nsIEventQueueService> eventQService = 
   249              do_GetService(kEventQueueServiceCID, &rv);
   250     if (NS_FAILED(rv)) {
   251         NS_WARNING("failed to create: event queue service!");
   252         return rv;
   253     }
   255     rv = eventQService->CreateMonitoredThreadEventQueue();
   256     if (NS_FAILED(rv)) {
   257         NS_WARNING("failed to create: thread event queue!");
   258         return rv;
   259     }
   261     eventQService->GetThreadEventQueue(NS_CURRENT_THREAD, &gEventQ);
   263     // Create the Socket transport service...
   264     nsCOMPtr<nsISocketTransportService> sts = 
   265              do_GetService(kSocketTransportServiceCID, &rv);
   266     if (NS_FAILED(rv)) {
   267         NS_WARNING("failed to create: socket transport service!");
   268         return rv;
   269     }
   271     char *buffer = PR_smprintf("GET %s HTTP/1.1" CRLF
   272                                "host: %s" CRLF
   273                                "user-agent: Mozilla/5.0 (X11; N; Linux 2.2.16-22smp i686; en-US; m18) Gecko/20001220" CRLF
   274                                "accept: */*" CRLF
   275                                "accept-language: en" CRLF
   276                                "accept-encoding: gzip,deflate,compress,identity" CRLF
   277                                "keep-alive: 300" CRLF
   278                                "connection: keep-alive" CRLF
   279                                 CRLF,
   280                                 fileName, hostName);
   281     LOG(("Request [\n%s]\n", buffer));
   283     // Create the socket transport...
   284     nsCOMPtr<nsITransport> transport;
   285     rv = sts->CreateTransport(hostName, port, nullptr, -1, 0, 0, getter_AddRefs(transport));
   286     if (NS_FAILED(rv)) {
   287         NS_WARNING("failed to create: socket transport!");
   288         return rv;
   289     }
   291     gElapsedTime = PR_Now();
   293     nsCOMPtr<nsIRequest> writeRequest, readRequest;
   295     rv = transport->AsyncWrite(new TestProvider(buffer), nullptr, 0, 0, 0, getter_AddRefs(writeRequest));
   296     if (NS_FAILED(rv)) {
   297         NS_WARNING("failed calling: AsyncWrite!");
   298         return rv;
   299     }
   300     rv = transport->AsyncRead(new TestListener(), nullptr, 0, 0, 0, getter_AddRefs(readRequest));
   301     if (NS_FAILED(rv)) {
   302         NS_WARNING("failed calling: AsyncWrite!");
   303         return rv;
   304     }
   306     // Enter the message pump
   307     while ( gKeepRunning ) {
   308         PLEvent *gEvent;
   309         gEventQ->WaitForEvent(&gEvent);
   310         gEventQ->HandleEvent(gEvent);
   311     }
   313     PRTime endTime; 
   314     endTime = PR_Now();
   315     LOG(("Elapsed time: %d\n", (int32_t)(endTime/1000UL - gElapsedTime/1000UL)));
   317     sts->Shutdown();
   318     return 0;
   319 }

mercurial