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/. */
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"
23 #include "nsIOutputStream.h"
24 #include "nsIInputStream.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)
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;
44 //----------------------------------------------------------------------------
46 //----------------------------------------------------------------------------
49 class TestListener
: public nsIStreamListener
53 virtual ~TestListener() {}
56 NS_DECL_NSIREQUESTOBSERVER
57 NS_DECL_NSISTREAMLISTENER
60 NS_IMPL_ISUPPORTS(TestListener
,
65 TestListener::OnStartRequest(nsIRequest
* request
, nsISupports
* context
)
67 LOG(("TestListener::OnStartRequest\n"));
72 TestListener::OnDataAvailable(nsIRequest
* request
,
74 nsIInputStream
*aIStream
,
75 uint64_t aSourceOffset
,
78 LOG(("TestListener::OnDataAvailable [offset=%llu length=%u]\n",
79 aSourceOffset
, aLength
));
83 aIStream
->Read(buf
, 1024, &amt
);
88 printf("read %d bytes\n", amt
);
94 TestListener::OnStopRequest(nsIRequest
* request
, nsISupports
* context
,
97 LOG(("TestListener::OnStopRequest [aStatus=%x]\n", aStatus
));
103 //----------------------------------------------------------------------------
105 //----------------------------------------------------------------------------
108 class TestProvider
: public nsIStreamProvider
111 TestProvider(char *data
);
112 virtual ~TestProvider();
115 NS_DECL_NSIREQUESTOBSERVER
116 NS_DECL_NSISTREAMPROVIDER
122 uint32_t mRequestCount
;
125 NS_IMPL_ISUPPORTS(TestProvider
,
129 TestProvider::TestProvider(char *data
)
132 mDataLen
= strlen(data
);
135 LOG(("Constructing TestProvider [this=%p]\n", this));
138 TestProvider::~TestProvider()
140 LOG(("Destroying TestProvider [this=%p]\n", this));
144 TestProvider::OnStartRequest(nsIRequest
* request
, nsISupports
* context
)
146 LOG(("TestProvider::OnStartRequest [this=%p]\n", this));
151 TestProvider::OnStopRequest(nsIRequest
* request
, nsISupports
* context
,
154 LOG(("TestProvider::OnStopRequest [status=%x]\n", aStatus
));
159 TestProvider::OnDataWritable(nsIRequest
*request
, nsISupports
*context
,
160 nsIOutputStream
*output
, uint32_t offset
, uint32_t count
)
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
);
184 //----------------------------------------------------------------------------
186 //----------------------------------------------------------------------------
189 WriteRequest(nsIOutputStream
*os
, const char *request
)
191 LOG(("WriteRequest [request=%s]\n", request
));
193 return os
->Write(request
, strlen(request
), &n
);
197 ReadResponse(nsIInputStream
*is
)
202 is
->Read(buf
, sizeof(buf
), &bytesRead
);
204 fwrite(buf
, 1, bytesRead
, stdout
);
205 } while (bytesRead
> 0);
210 //----------------------------------------------------------------------------
212 //----------------------------------------------------------------------------
218 LOG(("got signal: %d\n", sig
));
225 printf("usage: %s <host> <path>\n", argv
[0]);
230 main(int argc
, char* argv
[])
234 signal(SIGSEGV
, sighandler
);
236 #if defined(PR_LOGGING)
237 gTestSocketIOLog
= PR_NewLogModule("TestSocketIO");
243 char *hostName
= argv
[1];
244 char *fileName
= argv
[2];
247 // Create the Event Queue for this thread...
248 nsCOMPtr
<nsIEventQueueService
> eventQService
=
249 do_GetService(kEventQueueServiceCID
, &rv
);
251 NS_WARNING("failed to create: event queue service!");
255 rv
= eventQService
->CreateMonitoredThreadEventQueue();
257 NS_WARNING("failed to create: thread event queue!");
261 eventQService
->GetThreadEventQueue(NS_CURRENT_THREAD
, &gEventQ
);
263 // Create the Socket transport service...
264 nsCOMPtr
<nsISocketTransportService
> sts
=
265 do_GetService(kSocketTransportServiceCID
, &rv
);
267 NS_WARNING("failed to create: socket transport service!");
271 char *buffer
= PR_smprintf("GET %s HTTP/1.1" CRLF
273 "user-agent: Mozilla/5.0 (X11; N; Linux 2.2.16-22smp i686; en-US; m18) Gecko/20001220" CRLF
275 "accept-language: en" CRLF
276 "accept-encoding: gzip,deflate,compress,identity" CRLF
277 "keep-alive: 300" CRLF
278 "connection: keep-alive" CRLF
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
));
287 NS_WARNING("failed to create: socket transport!");
291 gElapsedTime
= PR_Now();
293 nsCOMPtr
<nsIRequest
> writeRequest
, readRequest
;
295 rv
= transport
->AsyncWrite(new TestProvider(buffer
), nullptr, 0, 0, 0, getter_AddRefs(writeRequest
));
297 NS_WARNING("failed calling: AsyncWrite!");
300 rv
= transport
->AsyncRead(new TestListener(), nullptr, 0, 0, 0, getter_AddRefs(readRequest
));
302 NS_WARNING("failed calling: AsyncWrite!");
306 // Enter the message pump
307 while ( gKeepRunning
) {
309 gEventQ
->WaitForEvent(&gEvent
);
310 gEventQ
->HandleEvent(gEvent
);
315 LOG(("Elapsed time: %d\n", (int32_t)(endTime
/1000UL - gElapsedTime
/1000UL)));