TestOverlappedIO.cpp 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  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>
  8. #ifdef WIN32
  9. #include <windows.h>
  10. #endif
  11. #include "nspr.h"
  12. #include "nscore.h"
  13. #include "nsISocketTransportService.h"
  14. #include "nsIEventQueueService.h"
  15. #include "nsIServiceManager.h"
  16. #include "nsITransport.h"
  17. #include "nsIRequest.h"
  18. #include "nsIStreamProvider.h"
  19. #include "nsIStreamListener.h"
  20. #include "nsIPipe.h"
  21. #include "nsIOutputStream.h"
  22. #include "nsIInputStream.h"
  23. #include "nsCRT.h"
  24. #include "nsCOMPtr.h"
  25. #include "nsIByteArrayInputStream.h"
  26. static PRLogModuleInfo *gTestSocketIOLog;
  27. #define LOG(args) MOZ_LOG(gTestSocketIOLog, mozilla::LogLevel::Debug, args)
  28. static NS_DEFINE_CID(kSocketTransportServiceCID, NS_SOCKETTRANSPORTSERVICE_CID);
  29. static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
  30. static PRTime gElapsedTime;
  31. static int gKeepRunning = 1;
  32. static nsIEventQueue* gEventQ = nullptr;
  33. //
  34. //----------------------------------------------------------------------------
  35. // Test Listener
  36. //----------------------------------------------------------------------------
  37. //
  38. class TestListener : public nsIStreamListener
  39. {
  40. public:
  41. TestListener() { }
  42. virtual ~TestListener() {}
  43. NS_DECL_ISUPPORTS
  44. NS_DECL_NSIREQUESTOBSERVER
  45. NS_DECL_NSISTREAMLISTENER
  46. };
  47. NS_IMPL_ISUPPORTS(TestListener,
  48. nsIRequestObserver,
  49. nsIStreamListener);
  50. NS_IMETHODIMP
  51. TestListener::OnStartRequest(nsIRequest* request, nsISupports* context)
  52. {
  53. LOG(("TestListener::OnStartRequest\n"));
  54. return NS_OK;
  55. }
  56. NS_IMETHODIMP
  57. TestListener::OnDataAvailable(nsIRequest* request,
  58. nsISupports* context,
  59. nsIInputStream *aIStream,
  60. uint64_t aSourceOffset,
  61. uint32_t aLength)
  62. {
  63. LOG(("TestListener::OnDataAvailable [offset=%llu length=%u]\n",
  64. aSourceOffset, aLength));
  65. char buf[1025];
  66. uint32_t amt;
  67. while (1) {
  68. aIStream->Read(buf, 1024, &amt);
  69. if (amt == 0)
  70. break;
  71. buf[amt] = '\0';
  72. //puts(buf);
  73. printf("read %d bytes\n", amt);
  74. }
  75. return NS_OK;
  76. }
  77. NS_IMETHODIMP
  78. TestListener::OnStopRequest(nsIRequest* request, nsISupports* context,
  79. nsresult aStatus)
  80. {
  81. LOG(("TestListener::OnStopRequest [aStatus=%x]\n", aStatus));
  82. //gKeepRunning = 0;
  83. return NS_OK;
  84. }
  85. //
  86. //----------------------------------------------------------------------------
  87. // Test Provider
  88. //----------------------------------------------------------------------------
  89. //
  90. class TestProvider : public nsIStreamProvider
  91. {
  92. public:
  93. TestProvider(char *data);
  94. virtual ~TestProvider();
  95. NS_DECL_ISUPPORTS
  96. NS_DECL_NSIREQUESTOBSERVER
  97. NS_DECL_NSISTREAMPROVIDER
  98. protected:
  99. char *mData;
  100. uint32_t mOffset;
  101. uint32_t mDataLen;
  102. uint32_t mRequestCount;
  103. };
  104. NS_IMPL_ISUPPORTS(TestProvider,
  105. nsIStreamProvider,
  106. nsIRequestObserver)
  107. TestProvider::TestProvider(char *data)
  108. {
  109. mData = data;
  110. mDataLen = strlen(data);
  111. mOffset = 0;
  112. mRequestCount = 0;
  113. LOG(("Constructing TestProvider [this=%p]\n", this));
  114. }
  115. TestProvider::~TestProvider()
  116. {
  117. LOG(("Destroying TestProvider [this=%p]\n", this));
  118. }
  119. NS_IMETHODIMP
  120. TestProvider::OnStartRequest(nsIRequest* request, nsISupports* context)
  121. {
  122. LOG(("TestProvider::OnStartRequest [this=%p]\n", this));
  123. return NS_OK;
  124. }
  125. NS_IMETHODIMP
  126. TestProvider::OnStopRequest(nsIRequest* request, nsISupports* context,
  127. nsresult aStatus)
  128. {
  129. LOG(("TestProvider::OnStopRequest [status=%x]\n", aStatus));
  130. return NS_OK;
  131. }
  132. NS_IMETHODIMP
  133. TestProvider::OnDataWritable(nsIRequest *request, nsISupports *context,
  134. nsIOutputStream *output, uint32_t offset, uint32_t count)
  135. {
  136. LOG(("TestProvider::OnDataWritable [offset=%u, count=%u]\n", offset, count));
  137. // Stop at 5 requests
  138. if (mRequestCount == 5)
  139. return NS_BASE_STREAM_CLOSED;
  140. uint32_t writeCount, amount;
  141. amount = std::min(count, mDataLen - mOffset);
  142. nsresult rv = output->Write(mData + mOffset, amount, &writeCount);
  143. if (NS_SUCCEEDED(rv)) {
  144. printf("wrote %u bytes\n", writeCount);
  145. mOffset += writeCount;
  146. if (mOffset == mDataLen) {
  147. printf("done sending packet %u\n", mRequestCount);
  148. mOffset = 0;
  149. mRequestCount++;
  150. }
  151. }
  152. return NS_OK;
  153. }
  154. //
  155. //----------------------------------------------------------------------------
  156. // Synchronous IO
  157. //----------------------------------------------------------------------------
  158. //
  159. nsresult
  160. WriteRequest(nsIOutputStream *os, const char *request)
  161. {
  162. LOG(("WriteRequest [request=%s]\n", request));
  163. uint32_t n;
  164. return os->Write(request, strlen(request), &n);
  165. }
  166. nsresult
  167. ReadResponse(nsIInputStream *is)
  168. {
  169. uint32_t bytesRead;
  170. char buf[2048];
  171. do {
  172. is->Read(buf, sizeof(buf), &bytesRead);
  173. if (bytesRead > 0)
  174. fwrite(buf, 1, bytesRead, stdout);
  175. } while (bytesRead > 0);
  176. return NS_OK;
  177. }
  178. //
  179. //----------------------------------------------------------------------------
  180. // Startup...
  181. //----------------------------------------------------------------------------
  182. //
  183. void
  184. sighandler(int sig)
  185. {
  186. LOG(("got signal: %d\n", sig));
  187. NS_BREAK();
  188. }
  189. void
  190. usage(char **argv)
  191. {
  192. printf("usage: %s <host> <path>\n", argv[0]);
  193. exit(1);
  194. }
  195. int
  196. main(int argc, char* argv[])
  197. {
  198. nsresult rv;
  199. signal(SIGSEGV, sighandler);
  200. gTestSocketIOLog = PR_NewLogModule("TestSocketIO");
  201. if (argc < 3)
  202. usage(argv);
  203. char *hostName = argv[1];
  204. char *fileName = argv[2];
  205. int port = 80;
  206. // Create the Event Queue for this thread...
  207. nsCOMPtr<nsIEventQueueService> eventQService =
  208. do_GetService(kEventQueueServiceCID, &rv);
  209. if (NS_FAILED(rv)) {
  210. NS_WARNING("failed to create: event queue service!");
  211. return rv;
  212. }
  213. rv = eventQService->CreateMonitoredThreadEventQueue();
  214. if (NS_FAILED(rv)) {
  215. NS_WARNING("failed to create: thread event queue!");
  216. return rv;
  217. }
  218. eventQService->GetThreadEventQueue(NS_CURRENT_THREAD, &gEventQ);
  219. // Create the Socket transport service...
  220. nsCOMPtr<nsISocketTransportService> sts =
  221. do_GetService(kSocketTransportServiceCID, &rv);
  222. if (NS_FAILED(rv)) {
  223. NS_WARNING("failed to create: socket transport service!");
  224. return rv;
  225. }
  226. char *buffer = PR_smprintf("GET %s HTTP/1.1" CRLF
  227. "host: %s" CRLF
  228. "user-agent: Mozilla/5.0 (X11; N; Linux 2.2.16-22smp i686; en-US; m18) Gecko/20001220" CRLF
  229. "accept: */*" CRLF
  230. "accept-language: en" CRLF
  231. "accept-encoding: gzip,deflate,compress,identity" CRLF
  232. "keep-alive: 300" CRLF
  233. "connection: keep-alive" CRLF
  234. CRLF,
  235. fileName, hostName);
  236. LOG(("Request [\n%s]\n", buffer));
  237. // Create the socket transport...
  238. nsCOMPtr<nsITransport> transport;
  239. rv = sts->CreateTransport(hostName, port, nullptr, -1, 0, 0, getter_AddRefs(transport));
  240. if (NS_FAILED(rv)) {
  241. NS_WARNING("failed to create: socket transport!");
  242. return rv;
  243. }
  244. gElapsedTime = PR_Now();
  245. nsCOMPtr<nsIRequest> writeRequest, readRequest;
  246. rv = transport->AsyncWrite(new TestProvider(buffer), nullptr, 0, 0, 0, getter_AddRefs(writeRequest));
  247. if (NS_FAILED(rv)) {
  248. NS_WARNING("failed calling: AsyncWrite!");
  249. return rv;
  250. }
  251. rv = transport->AsyncRead(new TestListener(), nullptr, 0, 0, 0, getter_AddRefs(readRequest));
  252. if (NS_FAILED(rv)) {
  253. NS_WARNING("failed calling: AsyncWrite!");
  254. return rv;
  255. }
  256. // Enter the message pump
  257. while ( gKeepRunning ) {
  258. PLEvent *gEvent;
  259. gEventQ->WaitForEvent(&gEvent);
  260. gEventQ->HandleEvent(gEvent);
  261. }
  262. PRTime endTime;
  263. endTime = PR_Now();
  264. LOG(("Elapsed time: %d\n", (int32_t)(endTime/1000UL - gElapsedTime/1000UL)));
  265. sts->Shutdown();
  266. return 0;
  267. }