PageRenderTime 155ms CodeModel.GetById 37ms RepoModel.GetById 5ms app.codeStats 1ms

/libs/js/nsprpub/pr/tests/socket.c

https://github.com/ppanhoto/Freeswitch-mod_mp4
C | 1634 lines | 1229 code | 118 blank | 287 comment | 232 complexity | 9876c5dab77a348ceb56a4440b453ea9 MD5 | raw file
  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* ***** BEGIN LICENSE BLOCK *****
  3. * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  4. *
  5. * The contents of this file are subject to the Mozilla Public License Version
  6. * 1.1 (the "License"); you may not use this file except in compliance with
  7. * the License. You may obtain a copy of the License at
  8. * http://www.mozilla.org/MPL/
  9. *
  10. * Software distributed under the License is distributed on an "AS IS" basis,
  11. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  12. * for the specific language governing rights and limitations under the
  13. * License.
  14. *
  15. * The Original Code is the Netscape Portable Runtime (NSPR).
  16. *
  17. * The Initial Developer of the Original Code is
  18. * Netscape Communications Corporation.
  19. * Portions created by the Initial Developer are Copyright (C) 1998-2000
  20. * the Initial Developer. All Rights Reserved.
  21. *
  22. * Contributor(s):
  23. *
  24. * Alternatively, the contents of this file may be used under the terms of
  25. * either the GNU General Public License Version 2 or later (the "GPL"), or
  26. * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  27. * in which case the provisions of the GPL or the LGPL are applicable instead
  28. * of those above. If you wish to allow use of your version of this file only
  29. * under the terms of either the GPL or the LGPL, and not to allow others to
  30. * use your version of this file under the terms of the MPL, indicate your
  31. * decision by deleting the provisions above and replace them with the notice
  32. * and other provisions required by the GPL or the LGPL. If you do not delete
  33. * the provisions above, a recipient may use your version of this file under
  34. * the terms of any one of the MPL, the GPL or the LGPL.
  35. *
  36. * ***** END LICENSE BLOCK ***** */
  37. /***********************************************************************
  38. **
  39. ** Name: socket.c
  40. **
  41. ** Description: Test socket functionality.
  42. **
  43. ** Modification History:
  44. */
  45. #include "primpl.h"
  46. #include "plgetopt.h"
  47. #include <stdio.h>
  48. #include <string.h>
  49. #include <errno.h>
  50. #ifdef XP_UNIX
  51. #include <sys/mman.h>
  52. #endif
  53. #if defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS)
  54. #include <pthread.h>
  55. #endif
  56. #ifdef WIN32
  57. #include <process.h>
  58. #endif
  59. static int _debug_on = 0;
  60. static int test_cancelio = 0;
  61. #ifdef XP_MAC
  62. #include "prlog.h"
  63. #include "prsem.h"
  64. int fprintf(FILE *stream, const char *fmt, ...)
  65. {
  66. PR_LogPrint(fmt);
  67. return 0;
  68. }
  69. #define printf PR_LogPrint
  70. extern void SetupMacPrintfLog(char *logFile);
  71. #else
  72. #include "obsolete/prsem.h"
  73. #endif
  74. #ifdef XP_PC
  75. #define mode_t int
  76. #endif
  77. #define DPRINTF(arg) if (_debug_on) printf arg
  78. #ifdef XP_PC
  79. char *TEST_DIR = "prdir";
  80. char *SMALL_FILE_NAME = "prsmallf";
  81. char *LARGE_FILE_NAME = "prlargef";
  82. #else
  83. char *TEST_DIR = "/tmp/prsocket_test_dir";
  84. char *SMALL_FILE_NAME = "/tmp/prsocket_test_dir/small_file";
  85. char *LARGE_FILE_NAME = "/tmp/prsocket_test_dir/large_file";
  86. #endif
  87. #define SMALL_FILE_SIZE (3 * 1024) /* 3 KB */
  88. #define SMALL_FILE_OFFSET_1 (512)
  89. #define SMALL_FILE_LEN_1 (1 * 1024) /* 1 KB */
  90. #define SMALL_FILE_OFFSET_2 (75)
  91. #define SMALL_FILE_LEN_2 (758)
  92. #define SMALL_FILE_OFFSET_3 (1024)
  93. #define SMALL_FILE_LEN_3 (SMALL_FILE_SIZE - SMALL_FILE_OFFSET_3)
  94. #define SMALL_FILE_HEADER_SIZE (64) /* 64 bytes */
  95. #define SMALL_FILE_TRAILER_SIZE (128) /* 128 bytes */
  96. #define LARGE_FILE_SIZE (3 * 1024 * 1024) /* 3 MB */
  97. #define LARGE_FILE_OFFSET_1 (0)
  98. #define LARGE_FILE_LEN_1 (2 * 1024 * 1024) /* 2 MB */
  99. #define LARGE_FILE_OFFSET_2 (64)
  100. #define LARGE_FILE_LEN_2 (1 * 1024 * 1024 + 75)
  101. #define LARGE_FILE_OFFSET_3 (2 * 1024 * 1024 - 128)
  102. #define LARGE_FILE_LEN_3 (LARGE_FILE_SIZE - LARGE_FILE_OFFSET_3)
  103. #define LARGE_FILE_OFFSET_4 PR_GetPageSize()
  104. #define LARGE_FILE_LEN_4 769
  105. #define LARGE_FILE_HEADER_SIZE (512)
  106. #define LARGE_FILE_TRAILER_SIZE (64)
  107. #define BUF_DATA_SIZE (2 * 1024)
  108. #define TCP_MESG_SIZE 1024
  109. /*
  110. * set UDP datagram size small enough that datagrams sent to a port on the
  111. * local host will not be lost
  112. */
  113. #define UDP_DGRAM_SIZE 128
  114. #define NUM_TCP_CLIENTS 5 /* for a listen queue depth of 5 */
  115. #define NUM_UDP_CLIENTS 10
  116. #ifndef XP_MAC
  117. #define NUM_TRANSMITFILE_CLIENTS 4
  118. #else
  119. /* Mac can't handle more than 2* (3Mb) allocations for large file size buffers */
  120. #define NUM_TRANSMITFILE_CLIENTS 2
  121. #endif
  122. #define NUM_TCP_CONNECTIONS_PER_CLIENT 5
  123. #define NUM_TCP_MESGS_PER_CONNECTION 10
  124. #define NUM_UDP_DATAGRAMS_PER_CLIENT 5
  125. #define TCP_SERVER_PORT 10000
  126. #define UDP_SERVER_PORT TCP_SERVER_PORT
  127. #define SERVER_MAX_BIND_COUNT 100
  128. static PRInt32 num_tcp_clients = NUM_TCP_CLIENTS;
  129. static PRInt32 num_udp_clients = NUM_UDP_CLIENTS;
  130. static PRInt32 num_transmitfile_clients = NUM_TRANSMITFILE_CLIENTS;
  131. static PRInt32 num_tcp_connections_per_client = NUM_TCP_CONNECTIONS_PER_CLIENT;
  132. static PRInt32 tcp_mesg_size = TCP_MESG_SIZE;
  133. static PRInt32 num_tcp_mesgs_per_connection = NUM_TCP_MESGS_PER_CONNECTION;
  134. static PRInt32 num_udp_datagrams_per_client = NUM_UDP_DATAGRAMS_PER_CLIENT;
  135. static PRInt32 udp_datagram_size = UDP_DGRAM_SIZE;
  136. static PRInt32 thread_count;
  137. PRUint16 server_domain = PR_AF_INET, client_domain = PR_AF_INET;
  138. /* an I/O layer that uses the emulated senfile method */
  139. static PRDescIdentity emuSendFileIdentity;
  140. static PRIOMethods emuSendFileMethods;
  141. int failed_already=0;
  142. typedef struct buffer {
  143. char data[BUF_DATA_SIZE];
  144. } buffer;
  145. PRNetAddr tcp_server_addr, udp_server_addr;
  146. typedef struct Serve_Client_Param {
  147. PRFileDesc *sockfd; /* socket to read from/write to */
  148. PRInt32 datalen; /* bytes of data transfered in each read/write */
  149. } Serve_Client_Param;
  150. typedef struct Server_Param {
  151. PRSemaphore *addr_sem; /* sem to post on, after setting up the address */
  152. PRMonitor *exit_mon; /* monitor to signal on exit */
  153. PRInt32 *exit_counter; /* counter to decrement, before exit */
  154. PRInt32 datalen; /* bytes of data transfered in each read/write */
  155. } Server_Param;
  156. typedef struct Client_Param {
  157. PRNetAddr server_addr;
  158. PRMonitor *exit_mon; /* monitor to signal on exit */
  159. PRInt32 *exit_counter; /* counter to decrement, before exit */
  160. PRInt32 datalen;
  161. PRInt32 udp_connect; /* if set clients connect udp sockets */
  162. } Client_Param;
  163. /* the sendfile method in emuSendFileMethods */
  164. static PRInt32 PR_CALLBACK
  165. emu_SendFile(PRFileDesc *sd, PRSendFileData *sfd,
  166. PRTransmitFileFlags flags, PRIntervalTime timeout)
  167. {
  168. return PR_EmulateSendFile(sd, sfd, flags, timeout);
  169. }
  170. /* the transmitfile method in emuSendFileMethods */
  171. static PRInt32 PR_CALLBACK
  172. emu_TransmitFile(PRFileDesc *sd, PRFileDesc *fd, const void *headers,
  173. PRInt32 hlen, PRTransmitFileFlags flags, PRIntervalTime timeout)
  174. {
  175. PRSendFileData sfd;
  176. sfd.fd = fd;
  177. sfd.file_offset = 0;
  178. sfd.file_nbytes = 0;
  179. sfd.header = headers;
  180. sfd.hlen = hlen;
  181. sfd.trailer = NULL;
  182. sfd.tlen = 0;
  183. return emu_SendFile(sd, &sfd, flags, timeout);
  184. }
  185. /*
  186. * readn
  187. * read data from sockfd into buf
  188. */
  189. static PRInt32
  190. readn(PRFileDesc *sockfd, char *buf, int len)
  191. {
  192. int rem;
  193. int bytes;
  194. int offset = 0;
  195. int err;
  196. PRIntervalTime timeout = PR_INTERVAL_NO_TIMEOUT;
  197. if (test_cancelio)
  198. timeout = PR_SecondsToInterval(2);
  199. for (rem=len; rem; offset += bytes, rem -= bytes) {
  200. DPRINTF(("thread = 0x%lx: calling PR_Recv, bytes = %d\n",
  201. PR_GetCurrentThread(), rem));
  202. retry:
  203. bytes = PR_Recv(sockfd, buf + offset, rem, 0,
  204. timeout);
  205. DPRINTF(("thread = 0x%lx: returning from PR_Recv, bytes = %d\n",
  206. PR_GetCurrentThread(), bytes));
  207. if (bytes < 0) {
  208. #ifdef WINNT
  209. printf("PR_Recv: error = %d oserr = %d\n",(err = PR_GetError()),
  210. PR_GetOSError());
  211. if ((test_cancelio) && (err == PR_IO_TIMEOUT_ERROR)) {
  212. if (PR_NT_CancelIo(sockfd) != PR_SUCCESS)
  213. printf("PR_NT_CancelIO: error = %d\n",PR_GetError());
  214. timeout = PR_INTERVAL_NO_TIMEOUT;
  215. goto retry;
  216. }
  217. #endif
  218. return -1;
  219. }
  220. }
  221. return len;
  222. }
  223. /*
  224. * writen
  225. * write data from buf to sockfd
  226. */
  227. static PRInt32
  228. writen(PRFileDesc *sockfd, char *buf, int len)
  229. {
  230. int rem;
  231. int bytes;
  232. int offset = 0;
  233. for (rem=len; rem; offset += bytes, rem -= bytes) {
  234. DPRINTF(("thread = 0x%lx: calling PR_Send, bytes = %d\n",
  235. PR_GetCurrentThread(), rem));
  236. bytes = PR_Send(sockfd, buf + offset, rem, 0,
  237. PR_INTERVAL_NO_TIMEOUT);
  238. DPRINTF(("thread = 0x%lx: returning from PR_Send, bytes = %d\n",
  239. PR_GetCurrentThread(), bytes));
  240. if (bytes <= 0)
  241. return -1;
  242. }
  243. return len;
  244. }
  245. /*
  246. * Serve_Client
  247. * Thread, started by the server, for serving a client connection.
  248. * Reads data from socket and writes it back, unmodified, and
  249. * closes the socket
  250. */
  251. static void PR_CALLBACK
  252. Serve_Client(void *arg)
  253. {
  254. Serve_Client_Param *scp = (Serve_Client_Param *) arg;
  255. PRFileDesc *sockfd;
  256. buffer *in_buf;
  257. PRInt32 bytes, j;
  258. sockfd = scp->sockfd;
  259. bytes = scp->datalen;
  260. in_buf = PR_NEW(buffer);
  261. if (in_buf == NULL) {
  262. fprintf(stderr,"prsocket_test: failed to alloc buffer struct\n");
  263. failed_already=1;
  264. goto exit;
  265. }
  266. for (j = 0; j < num_tcp_mesgs_per_connection; j++) {
  267. /*
  268. * Read data from client and send it back to the client unmodified
  269. */
  270. if (readn(sockfd, in_buf->data, bytes) < bytes) {
  271. fprintf(stderr,"prsocket_test: ERROR - Serve_Client:readn\n");
  272. failed_already=1;
  273. goto exit;
  274. }
  275. /*
  276. * shutdown reads, after the last read
  277. */
  278. if (j == num_tcp_mesgs_per_connection - 1)
  279. if (PR_Shutdown(sockfd, PR_SHUTDOWN_RCV) < 0) {
  280. fprintf(stderr,"prsocket_test: ERROR - PR_Shutdown\n");
  281. }
  282. DPRINTF(("Serve_Client [0x%lx]: inbuf[0] = 0x%lx\n",PR_GetCurrentThread(),
  283. (*((int *) in_buf->data))));
  284. if (writen(sockfd, in_buf->data, bytes) < bytes) {
  285. fprintf(stderr,"prsocket_test: ERROR - Serve_Client:writen\n");
  286. failed_already=1;
  287. goto exit;
  288. }
  289. }
  290. /*
  291. * shutdown reads and writes
  292. */
  293. if (PR_Shutdown(sockfd, PR_SHUTDOWN_BOTH) < 0) {
  294. fprintf(stderr,"prsocket_test: ERROR - PR_Shutdown\n");
  295. failed_already=1;
  296. }
  297. exit:
  298. PR_Close(sockfd);
  299. if (in_buf) {
  300. PR_DELETE(in_buf);
  301. }
  302. }
  303. PRThread* create_new_thread(PRThreadType type,
  304. void (*start)(void *arg),
  305. void *arg,
  306. PRThreadPriority priority,
  307. PRThreadScope scope,
  308. PRThreadState state,
  309. PRUint32 stackSize, PRInt32 index)
  310. {
  311. PRInt32 native_thread = 0;
  312. PR_ASSERT(state == PR_UNJOINABLE_THREAD);
  313. #if (defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS)) || defined(WIN32)
  314. switch(index % 4) {
  315. case 0:
  316. scope = (PR_LOCAL_THREAD);
  317. break;
  318. case 1:
  319. scope = (PR_GLOBAL_THREAD);
  320. break;
  321. case 2:
  322. scope = (PR_GLOBAL_BOUND_THREAD);
  323. break;
  324. case 3:
  325. native_thread = 1;
  326. break;
  327. default:
  328. PR_ASSERT(!"Invalid scope");
  329. break;
  330. }
  331. if (native_thread) {
  332. #if defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS)
  333. pthread_t tid;
  334. if (!pthread_create(&tid, NULL, (void * (*)(void *)) start, arg))
  335. return((PRThread *) tid);
  336. else
  337. return (NULL);
  338. #else
  339. HANDLE thandle;
  340. unsigned tid;
  341. thandle = (HANDLE) _beginthreadex(
  342. NULL,
  343. stackSize,
  344. (unsigned (__stdcall *)(void *))start,
  345. arg,
  346. 0,
  347. &tid);
  348. return((PRThread *) thandle);
  349. #endif
  350. } else {
  351. return(PR_CreateThread(type,start,arg,priority,scope,state,stackSize));
  352. }
  353. #else
  354. return(PR_CreateThread(type,start,arg,priority,scope,state,stackSize));
  355. #endif
  356. }
  357. /*
  358. * TCP Server
  359. * Server Thread
  360. * Bind an address to a socket and listen for incoming connections
  361. * Start a Serve_Client thread for each incoming connection.
  362. */
  363. static void PR_CALLBACK
  364. TCP_Server(void *arg)
  365. {
  366. PRThread *t;
  367. Server_Param *sp = (Server_Param *) arg;
  368. Serve_Client_Param *scp;
  369. PRFileDesc *sockfd, *newsockfd;
  370. PRNetAddr netaddr;
  371. PRInt32 i;
  372. /*
  373. * Create a tcp socket
  374. */
  375. if ((sockfd = PR_OpenTCPSocket(server_domain)) == NULL) {
  376. fprintf(stderr,"prsocket_test: PR_NewTCPSocket failed\n");
  377. goto exit;
  378. }
  379. memset(&netaddr, 0 , sizeof(netaddr));
  380. if (PR_SetNetAddr(PR_IpAddrAny, server_domain, TCP_SERVER_PORT,
  381. &netaddr) == PR_FAILURE) {
  382. fprintf(stderr,"prsocket_test: PR_SetNetAddr failed\n");
  383. goto exit;
  384. }
  385. /*
  386. * try a few times to bind server's address, if addresses are in
  387. * use
  388. */
  389. i = 0;
  390. while (PR_Bind(sockfd, &netaddr) < 0) {
  391. if (PR_GetError() == PR_ADDRESS_IN_USE_ERROR) {
  392. netaddr.inet.port += 2;
  393. if (i++ < SERVER_MAX_BIND_COUNT)
  394. continue;
  395. }
  396. fprintf(stderr,"prsocket_test: ERROR - PR_Bind failed\n");
  397. perror("PR_Bind");
  398. failed_already=1;
  399. goto exit;
  400. }
  401. if (PR_Listen(sockfd, 32) < 0) {
  402. fprintf(stderr,"prsocket_test: ERROR - PR_Listen failed\n");
  403. failed_already=1;
  404. goto exit;
  405. }
  406. if (PR_GetSockName(sockfd, &netaddr) < 0) {
  407. fprintf(stderr,"prsocket_test: ERROR - PR_GetSockName failed\n");
  408. failed_already=1;
  409. goto exit;
  410. }
  411. DPRINTF(("TCP_Server: PR_BIND netaddr.inet.ip = 0x%lx, netaddr.inet.port = %d\n",
  412. netaddr.inet.ip, netaddr.inet.port));
  413. if (PR_SetNetAddr(PR_IpAddrLoopback, client_domain,
  414. PR_ntohs(PR_NetAddrInetPort(&netaddr)),
  415. &tcp_server_addr) == PR_FAILURE) {
  416. fprintf(stderr,"prsocket_test: PR_SetNetAddr failed\n");
  417. goto exit;
  418. }
  419. if ((client_domain == PR_AF_INET6) && (server_domain == PR_AF_INET))
  420. PR_ConvertIPv4AddrToIPv6(PR_htonl(INADDR_LOOPBACK),
  421. &tcp_server_addr.ipv6.ip);
  422. /*
  423. * Wake up parent thread because server address is bound and made
  424. * available in the global variable 'tcp_server_addr'
  425. */
  426. PR_PostSem(sp->addr_sem);
  427. for (i = 0; i < (num_tcp_clients * num_tcp_connections_per_client); i++) {
  428. /* test both null and non-null 'addr' argument to PR_Accept */
  429. PRNetAddr *addrp = (i%2 ? &netaddr: NULL);
  430. DPRINTF(("TCP_Server: Accepting connection\n"));
  431. if ((newsockfd = PR_Accept(sockfd, addrp,
  432. PR_INTERVAL_NO_TIMEOUT)) == NULL) {
  433. fprintf(stderr,"prsocket_test: ERROR - PR_Accept failed\n");
  434. goto exit;
  435. }
  436. DPRINTF(("TCP_Server: Accepted connection\n"));
  437. scp = PR_NEW(Serve_Client_Param);
  438. if (scp == NULL) {
  439. fprintf(stderr,"prsocket_test: PR_NEW failed\n");
  440. goto exit;
  441. }
  442. /*
  443. * Start a Serve_Client thread for each incoming connection
  444. */
  445. scp->sockfd = newsockfd;
  446. scp->datalen = sp->datalen;
  447. t = create_new_thread(PR_USER_THREAD,
  448. Serve_Client, (void *)scp,
  449. PR_PRIORITY_NORMAL,
  450. PR_LOCAL_THREAD,
  451. PR_UNJOINABLE_THREAD,
  452. 0, i);
  453. if (t == NULL) {
  454. fprintf(stderr,"prsocket_test: PR_CreateThread failed\n");
  455. failed_already=1;
  456. goto exit;
  457. }
  458. DPRINTF(("TCP_Server: Created Serve_Client = 0x%lx\n", t));
  459. }
  460. exit:
  461. if (sockfd) {
  462. PR_Close(sockfd);
  463. }
  464. /*
  465. * Decrement exit_counter and notify parent thread
  466. */
  467. PR_EnterMonitor(sp->exit_mon);
  468. --(*sp->exit_counter);
  469. PR_Notify(sp->exit_mon);
  470. PR_ExitMonitor(sp->exit_mon);
  471. DPRINTF(("TCP_Server [0x%lx] exiting\n", PR_GetCurrentThread()));
  472. }
  473. /*
  474. * UDP Server
  475. * Server Thread
  476. * Bind an address to a socket, read data from clients and send data
  477. * back to clients
  478. */
  479. static void PR_CALLBACK
  480. UDP_Server(void *arg)
  481. {
  482. Server_Param *sp = (Server_Param *) arg;
  483. PRFileDesc *sockfd;
  484. buffer *in_buf;
  485. PRNetAddr netaddr;
  486. PRInt32 bytes, i, rv = 0;
  487. bytes = sp->datalen;
  488. /*
  489. * Create a udp socket
  490. */
  491. if ((sockfd = PR_OpenUDPSocket(server_domain)) == NULL) {
  492. fprintf(stderr,"prsocket_test: PR_NewUDPSocket failed\n");
  493. failed_already=1;
  494. return;
  495. }
  496. memset(&netaddr, 0 , sizeof(netaddr));
  497. if (PR_SetNetAddr(PR_IpAddrAny, server_domain, UDP_SERVER_PORT,
  498. &netaddr) == PR_FAILURE) {
  499. fprintf(stderr,"prsocket_test: PR_SetNetAddr failed\n");
  500. failed_already=1;
  501. return;
  502. }
  503. /*
  504. * try a few times to bind server's address, if addresses are in
  505. * use
  506. */
  507. i = 0;
  508. while (PR_Bind(sockfd, &netaddr) < 0) {
  509. if (PR_GetError() == PR_ADDRESS_IN_USE_ERROR) {
  510. netaddr.inet.port += 2;
  511. if (i++ < SERVER_MAX_BIND_COUNT)
  512. continue;
  513. }
  514. fprintf(stderr,"prsocket_test: ERROR - PR_Bind failed\n");
  515. perror("PR_Bind");
  516. failed_already=1;
  517. return;
  518. }
  519. if (PR_GetSockName(sockfd, &netaddr) < 0) {
  520. fprintf(stderr,"prsocket_test: ERROR - PR_GetSockName failed\n");
  521. failed_already=1;
  522. return;
  523. }
  524. DPRINTF(("PR_Bind: UDP Server netaddr.inet.ip = 0x%lx, netaddr.inet.port = %d\n",
  525. netaddr.inet.ip, netaddr.inet.port));
  526. /*
  527. * We can't use the IP address returned by PR_GetSockName in
  528. * netaddr.inet.ip because netaddr.inet.ip is returned
  529. * as 0 (= PR_INADDR_ANY).
  530. */
  531. if (PR_SetNetAddr(PR_IpAddrLoopback, client_domain,
  532. PR_ntohs(PR_NetAddrInetPort(&netaddr)),
  533. &udp_server_addr) == PR_FAILURE) {
  534. fprintf(stderr,"prsocket_test: PR_SetNetAddr failed\n");
  535. failed_already=1;
  536. return;
  537. }
  538. if ((client_domain == PR_AF_INET6) && (server_domain == PR_AF_INET))
  539. PR_ConvertIPv4AddrToIPv6(PR_htonl(INADDR_LOOPBACK),
  540. &udp_server_addr.ipv6.ip);
  541. /*
  542. * Wake up parent thread because server address is bound and made
  543. * available in the global variable 'udp_server_addr'
  544. */
  545. PR_PostSem(sp->addr_sem);
  546. bytes = sp->datalen;
  547. in_buf = PR_NEW(buffer);
  548. if (in_buf == NULL) {
  549. fprintf(stderr,"prsocket_test: failed to alloc buffer struct\n");
  550. failed_already=1;
  551. return;
  552. }
  553. /*
  554. * Receive datagrams from clients and send them back, unmodified, to the
  555. * clients
  556. */
  557. memset(&netaddr, 0 , sizeof(netaddr));
  558. for (i = 0; i < (num_udp_clients * num_udp_datagrams_per_client); i++) {
  559. DPRINTF(("UDP_Server: calling PR_RecvFrom client - ip = 0x%lx, port = %d bytes = %d inbuf = 0x%lx, inbuf[0] = 0x%lx\n",
  560. netaddr.inet.ip, netaddr.inet.port, bytes, in_buf->data,
  561. in_buf->data[0]));
  562. rv = PR_RecvFrom(sockfd, in_buf->data, bytes, 0, &netaddr,
  563. PR_INTERVAL_NO_TIMEOUT);
  564. DPRINTF(("UDP_Server: PR_RecvFrom client - ip = 0x%lx, port = %d bytes = %d inbuf = 0x%lx, inbuf[0] = 0x%lx\n",
  565. netaddr.inet.ip, netaddr.inet.port, rv, in_buf->data,
  566. in_buf->data[0]));
  567. if (rv != bytes) {
  568. return;
  569. }
  570. rv = PR_SendTo(sockfd, in_buf->data, bytes, 0, &netaddr,
  571. PR_INTERVAL_NO_TIMEOUT);
  572. if (rv != bytes) {
  573. return;
  574. }
  575. }
  576. PR_DELETE(in_buf);
  577. PR_Close(sockfd);
  578. /*
  579. * Decrement exit_counter and notify parent thread
  580. */
  581. PR_EnterMonitor(sp->exit_mon);
  582. --(*sp->exit_counter);
  583. PR_Notify(sp->exit_mon);
  584. PR_ExitMonitor(sp->exit_mon);
  585. DPRINTF(("UDP_Server [0x%x] exiting\n", PR_GetCurrentThread()));
  586. }
  587. /*
  588. * TCP_Client
  589. * Client Thread
  590. * Connect to the server at the address specified in the argument.
  591. * Fill in a buffer, write data to server, read it back and check
  592. * for data corruption.
  593. * Close the socket for server connection
  594. */
  595. static void PR_CALLBACK
  596. TCP_Client(void *arg)
  597. {
  598. Client_Param *cp = (Client_Param *) arg;
  599. PRFileDesc *sockfd;
  600. buffer *in_buf, *out_buf;
  601. union PRNetAddr netaddr;
  602. PRInt32 bytes, i, j;
  603. bytes = cp->datalen;
  604. out_buf = PR_NEW(buffer);
  605. if (out_buf == NULL) {
  606. fprintf(stderr,"prsocket_test: failed to alloc buffer struct\n");
  607. failed_already=1;
  608. return;
  609. }
  610. in_buf = PR_NEW(buffer);
  611. if (in_buf == NULL) {
  612. fprintf(stderr,"prsocket_test: failed to alloc buffer struct\n");
  613. failed_already=1;
  614. return;
  615. }
  616. netaddr = cp->server_addr;
  617. for (i = 0; i < num_tcp_connections_per_client; i++) {
  618. if ((sockfd = PR_OpenTCPSocket(client_domain)) == NULL) {
  619. fprintf(stderr,"prsocket_test: PR_OpenTCPSocket failed\n");
  620. failed_already=1;
  621. return;
  622. }
  623. if (PR_Connect(sockfd, &netaddr,PR_INTERVAL_NO_TIMEOUT) < 0){
  624. fprintf(stderr, "PR_Connect failed: (%ld, %ld)\n",
  625. PR_GetError(), PR_GetOSError());
  626. failed_already=1;
  627. return;
  628. }
  629. for (j = 0; j < num_tcp_mesgs_per_connection; j++) {
  630. /*
  631. * fill in random data
  632. */
  633. memset(out_buf->data, ((PRInt32) (&netaddr)) + i + j, bytes);
  634. /*
  635. * write to server
  636. */
  637. #ifdef WINNT
  638. if (test_cancelio && (j == 0))
  639. PR_Sleep(PR_SecondsToInterval(12));
  640. #endif
  641. if (writen(sockfd, out_buf->data, bytes) < bytes) {
  642. fprintf(stderr,"prsocket_test: ERROR - TCP_Client:writen\n");
  643. failed_already=1;
  644. return;
  645. }
  646. DPRINTF(("TCP Client [0x%lx]: out_buf = 0x%lx out_buf[0] = 0x%lx\n",
  647. PR_GetCurrentThread(), out_buf, (*((int *) out_buf->data))));
  648. if (readn(sockfd, in_buf->data, bytes) < bytes) {
  649. fprintf(stderr,"prsocket_test: ERROR - TCP_Client:readn\n");
  650. failed_already=1;
  651. return;
  652. }
  653. /*
  654. * verify the data read
  655. */
  656. if (memcmp(in_buf->data, out_buf->data, bytes) != 0) {
  657. fprintf(stderr,"prsocket_test: ERROR - data corruption\n");
  658. failed_already=1;
  659. return;
  660. }
  661. }
  662. /*
  663. * shutdown reads and writes
  664. */
  665. if (PR_Shutdown(sockfd, PR_SHUTDOWN_BOTH) < 0) {
  666. fprintf(stderr,"prsocket_test: ERROR - PR_Shutdown\n");
  667. failed_already=1;
  668. }
  669. PR_Close(sockfd);
  670. }
  671. PR_DELETE(out_buf);
  672. PR_DELETE(in_buf);
  673. /*
  674. * Decrement exit_counter and notify parent thread
  675. */
  676. PR_EnterMonitor(cp->exit_mon);
  677. --(*cp->exit_counter);
  678. PR_Notify(cp->exit_mon);
  679. PR_ExitMonitor(cp->exit_mon);
  680. DPRINTF(("TCP_Client [0x%x] exiting\n", PR_GetCurrentThread()));
  681. }
  682. /*
  683. * UDP_Client
  684. * Client Thread
  685. * Create a socket and bind an address
  686. * Communicate with the server at the address specified in the argument.
  687. * Fill in a buffer, write data to server, read it back and check
  688. * for data corruption.
  689. * Close the socket
  690. */
  691. static void PR_CALLBACK
  692. UDP_Client(void *arg)
  693. {
  694. Client_Param *cp = (Client_Param *) arg;
  695. PRFileDesc *sockfd;
  696. buffer *in_buf, *out_buf;
  697. union PRNetAddr netaddr;
  698. PRInt32 bytes, i, rv;
  699. bytes = cp->datalen;
  700. out_buf = PR_NEW(buffer);
  701. if (out_buf == NULL) {
  702. fprintf(stderr,"prsocket_test: failed to alloc buffer struct\n");
  703. failed_already=1;
  704. return;
  705. }
  706. in_buf = PR_NEW(buffer);
  707. if (in_buf == NULL) {
  708. fprintf(stderr,"prsocket_test: failed to alloc buffer struct\n");
  709. failed_already=1;
  710. return;
  711. }
  712. if ((sockfd = PR_OpenUDPSocket(client_domain)) == NULL) {
  713. fprintf(stderr,"prsocket_test: PR_OpenUDPSocket failed\n");
  714. failed_already=1;
  715. return;
  716. }
  717. /*
  718. * bind an address for the client, let the system chose the port
  719. * number
  720. */
  721. memset(&netaddr, 0 , sizeof(netaddr));
  722. if (PR_SetNetAddr(PR_IpAddrAny, client_domain, 0,
  723. &netaddr) == PR_FAILURE) {
  724. fprintf(stderr,"prsocket_test: PR_SetNetAddr failed\n");
  725. failed_already=1;
  726. return;
  727. }
  728. if (PR_Bind(sockfd, &netaddr) < 0) {
  729. fprintf(stderr,"prsocket_test: ERROR - PR_Bind failed\n");
  730. perror("PR_Bind");
  731. return;
  732. }
  733. if (PR_GetSockName(sockfd, &netaddr) < 0) {
  734. fprintf(stderr,"prsocket_test: ERROR - PR_GetSockName failed\n");
  735. failed_already=1;
  736. return;
  737. }
  738. DPRINTF(("PR_Bind: UDP Client netaddr.inet.ip = 0x%lx, netaddr.inet.port = %d\n",
  739. netaddr.inet.ip, netaddr.inet.port));
  740. netaddr = cp->server_addr;
  741. if (cp->udp_connect) {
  742. if (PR_Connect(sockfd, &netaddr,PR_INTERVAL_NO_TIMEOUT) < 0){
  743. fprintf(stderr,"prsocket_test: PR_Connect failed\n");
  744. failed_already=1;
  745. return;
  746. }
  747. }
  748. for (i = 0; i < num_udp_datagrams_per_client; i++) {
  749. /*
  750. * fill in random data
  751. */
  752. DPRINTF(("UDP_Client [0x%lx]: out_buf = 0x%lx bytes = 0x%lx\n",
  753. PR_GetCurrentThread(), out_buf->data, bytes));
  754. memset(out_buf->data, ((PRInt32) (&netaddr)) + i, bytes);
  755. /*
  756. * write to server
  757. */
  758. if (cp->udp_connect)
  759. rv = PR_Send(sockfd, out_buf->data, bytes, 0,
  760. PR_INTERVAL_NO_TIMEOUT);
  761. else
  762. rv = PR_SendTo(sockfd, out_buf->data, bytes, 0, &netaddr,
  763. PR_INTERVAL_NO_TIMEOUT);
  764. if (rv != bytes) {
  765. return;
  766. }
  767. DPRINTF(("UDP_Client [0x%lx]: out_buf = 0x%lx out_buf[0] = 0x%lx\n",
  768. PR_GetCurrentThread(), out_buf, (*((int *) out_buf->data))));
  769. if (cp->udp_connect)
  770. rv = PR_Recv(sockfd, in_buf->data, bytes, 0,
  771. PR_INTERVAL_NO_TIMEOUT);
  772. else
  773. rv = PR_RecvFrom(sockfd, in_buf->data, bytes, 0, &netaddr,
  774. PR_INTERVAL_NO_TIMEOUT);
  775. if (rv != bytes) {
  776. return;
  777. }
  778. DPRINTF(("UDP_Client [0x%lx]: in_buf = 0x%lx in_buf[0] = 0x%lx\n",
  779. PR_GetCurrentThread(), in_buf, (*((int *) in_buf->data))));
  780. /*
  781. * verify the data read
  782. */
  783. if (memcmp(in_buf->data, out_buf->data, bytes) != 0) {
  784. fprintf(stderr,"prsocket_test: ERROR - UDP data corruption\n");
  785. failed_already=1;
  786. return;
  787. }
  788. }
  789. PR_Close(sockfd);
  790. PR_DELETE(in_buf);
  791. PR_DELETE(out_buf);
  792. /*
  793. * Decrement exit_counter and notify parent thread
  794. */
  795. PR_EnterMonitor(cp->exit_mon);
  796. --(*cp->exit_counter);
  797. PR_Notify(cp->exit_mon);
  798. PR_ExitMonitor(cp->exit_mon);
  799. PR_DELETE(cp);
  800. DPRINTF(("UDP_Client [0x%x] exiting\n", PR_GetCurrentThread()));
  801. }
  802. /*
  803. * TCP_Socket_Client_Server_Test - concurrent server test
  804. *
  805. * One server and several clients are started
  806. * Each client connects to the server and sends a chunk of data
  807. * For each connection, server starts another thread to read the data
  808. * from the client and send it back to the client, unmodified.
  809. * Each client checks that data received from server is same as the
  810. * data it sent to the server.
  811. *
  812. */
  813. static PRInt32
  814. TCP_Socket_Client_Server_Test(void)
  815. {
  816. int i;
  817. PRThread *t;
  818. PRSemaphore *server_sem;
  819. Server_Param *sparamp;
  820. Client_Param *cparamp;
  821. PRMonitor *mon2;
  822. PRInt32 datalen;
  823. datalen = tcp_mesg_size;
  824. thread_count = 0;
  825. /*
  826. * start the server thread
  827. */
  828. sparamp = PR_NEW(Server_Param);
  829. if (sparamp == NULL) {
  830. fprintf(stderr,"prsocket_test: PR_NEW failed\n");
  831. failed_already=1;
  832. return -1;
  833. }
  834. server_sem = PR_NewSem(0);
  835. if (server_sem == NULL) {
  836. fprintf(stderr,"prsocket_test: PR_NewSem failed\n");
  837. failed_already=1;
  838. return -1;
  839. }
  840. mon2 = PR_NewMonitor();
  841. if (mon2 == NULL) {
  842. fprintf(stderr,"prsocket_test: PR_NewMonitor failed\n");
  843. failed_already=1;
  844. return -1;
  845. }
  846. PR_EnterMonitor(mon2);
  847. sparamp->addr_sem = server_sem;
  848. sparamp->exit_mon = mon2;
  849. sparamp->exit_counter = &thread_count;
  850. sparamp->datalen = datalen;
  851. t = PR_CreateThread(PR_USER_THREAD,
  852. TCP_Server, (void *)sparamp,
  853. PR_PRIORITY_NORMAL,
  854. PR_LOCAL_THREAD,
  855. PR_UNJOINABLE_THREAD,
  856. 0);
  857. if (t == NULL) {
  858. fprintf(stderr,"prsocket_test: PR_CreateThread failed\n");
  859. failed_already=1;
  860. return -1;
  861. }
  862. DPRINTF(("Created TCP server = 0x%lx\n", t));
  863. thread_count++;
  864. /*
  865. * wait till the server address is setup
  866. */
  867. PR_WaitSem(server_sem);
  868. /*
  869. * Now start a bunch of client threads
  870. */
  871. cparamp = PR_NEW(Client_Param);
  872. if (cparamp == NULL) {
  873. fprintf(stderr,"prsocket_test: PR_NEW failed\n");
  874. failed_already=1;
  875. return -1;
  876. }
  877. cparamp->server_addr = tcp_server_addr;
  878. cparamp->exit_mon = mon2;
  879. cparamp->exit_counter = &thread_count;
  880. cparamp->datalen = datalen;
  881. for (i = 0; i < num_tcp_clients; i++) {
  882. t = create_new_thread(PR_USER_THREAD,
  883. TCP_Client, (void *) cparamp,
  884. PR_PRIORITY_NORMAL,
  885. PR_LOCAL_THREAD,
  886. PR_UNJOINABLE_THREAD,
  887. 0, i);
  888. if (t == NULL) {
  889. fprintf(stderr,"prsocket_test: PR_CreateThread failed\n");
  890. failed_already=1;
  891. return -1;
  892. }
  893. DPRINTF(("Created TCP client = 0x%lx\n", t));
  894. thread_count++;
  895. }
  896. /* Wait for server and client threads to exit */
  897. while (thread_count) {
  898. PR_Wait(mon2, PR_INTERVAL_NO_TIMEOUT);
  899. DPRINTF(("TCP Server - thread_count = %d\n", thread_count));
  900. }
  901. PR_ExitMonitor(mon2);
  902. printf("%30s","TCP_Socket_Client_Server_Test:");
  903. printf("%2ld Server %2ld Clients %2ld connections_per_client\n",1l,
  904. num_tcp_clients, num_tcp_connections_per_client);
  905. printf("%30s %2ld messages_per_connection %4ld bytes_per_message\n",":",
  906. num_tcp_mesgs_per_connection, tcp_mesg_size);
  907. return 0;
  908. }
  909. /*
  910. * UDP_Socket_Client_Server_Test - iterative server test
  911. *
  912. * One server and several clients are started
  913. * Each client connects to the server and sends a chunk of data
  914. * For each connection, server starts another thread to read the data
  915. * from the client and send it back to the client, unmodified.
  916. * Each client checks that data received from server is same as the
  917. * data it sent to the server.
  918. *
  919. */
  920. static PRInt32
  921. UDP_Socket_Client_Server_Test(void)
  922. {
  923. int i;
  924. PRThread *t;
  925. PRSemaphore *server_sem;
  926. Server_Param *sparamp;
  927. Client_Param *cparamp;
  928. PRMonitor *mon2;
  929. PRInt32 datalen;
  930. PRInt32 udp_connect = 1;
  931. datalen = udp_datagram_size;
  932. thread_count = 0;
  933. /*
  934. * start the server thread
  935. */
  936. sparamp = PR_NEW(Server_Param);
  937. if (sparamp == NULL) {
  938. fprintf(stderr,"prsocket_test: PR_NEW failed\n");
  939. failed_already=1;
  940. return -1;
  941. }
  942. server_sem = PR_NewSem(0);
  943. if (server_sem == NULL) {
  944. fprintf(stderr,"prsocket_test: PR_NewSem failed\n");
  945. failed_already=1;
  946. return -1;
  947. }
  948. mon2 = PR_NewMonitor();
  949. if (mon2 == NULL) {
  950. fprintf(stderr,"prsocket_test: PR_NewMonitor failed\n");
  951. failed_already=1;
  952. return -1;
  953. }
  954. PR_EnterMonitor(mon2);
  955. sparamp->addr_sem = server_sem;
  956. sparamp->exit_mon = mon2;
  957. sparamp->exit_counter = &thread_count;
  958. sparamp->datalen = datalen;
  959. DPRINTF(("Creating UDP server"));
  960. t = PR_CreateThread(PR_USER_THREAD,
  961. UDP_Server, (void *)sparamp,
  962. PR_PRIORITY_NORMAL,
  963. PR_LOCAL_THREAD,
  964. PR_UNJOINABLE_THREAD,
  965. 0);
  966. if (t == NULL) {
  967. fprintf(stderr,"prsocket_test: PR_CreateThread failed\n");
  968. failed_already=1;
  969. return -1;
  970. }
  971. thread_count++;
  972. /*
  973. * wait till the server address is setup
  974. */
  975. PR_WaitSem(server_sem);
  976. /*
  977. * Now start a bunch of client threads
  978. */
  979. for (i = 0; i < num_udp_clients; i++) {
  980. cparamp = PR_NEW(Client_Param);
  981. if (cparamp == NULL) {
  982. fprintf(stderr,"prsocket_test: PR_NEW failed\n");
  983. failed_already=1;
  984. return -1;
  985. }
  986. cparamp->server_addr = udp_server_addr;
  987. cparamp->exit_mon = mon2;
  988. cparamp->exit_counter = &thread_count;
  989. cparamp->datalen = datalen;
  990. /*
  991. * Cause every other client thread to connect udp sockets
  992. */
  993. #ifndef XP_MAC
  994. cparamp->udp_connect = udp_connect;
  995. #else
  996. /* No support for UDP connects on Mac */
  997. cparamp->udp_connect = 0;
  998. #endif
  999. if (udp_connect)
  1000. udp_connect = 0;
  1001. else
  1002. udp_connect = 1;
  1003. DPRINTF(("Creating UDP client %d\n", i));
  1004. t = PR_CreateThread(PR_USER_THREAD,
  1005. UDP_Client, (void *) cparamp,
  1006. PR_PRIORITY_NORMAL,
  1007. PR_LOCAL_THREAD,
  1008. PR_UNJOINABLE_THREAD,
  1009. 0);
  1010. if (t == NULL) {
  1011. fprintf(stderr,"prsocket_test: PR_CreateThread failed\n");
  1012. failed_already=1;
  1013. return -1;
  1014. }
  1015. thread_count++;
  1016. }
  1017. /* Wait for server and client threads to exit */
  1018. while (thread_count) {
  1019. PR_Wait(mon2, PR_INTERVAL_NO_TIMEOUT);
  1020. DPRINTF(("UDP Server - thread_count = %d\n", thread_count));
  1021. }
  1022. PR_ExitMonitor(mon2);
  1023. printf("%30s","UDP_Socket_Client_Server_Test: ");
  1024. printf("%2ld Server %2ld Clients\n",1l, num_udp_clients);
  1025. printf("%30s %2ld datagrams_per_client %4ld bytes_per_datagram\n",":",
  1026. num_udp_datagrams_per_client, udp_datagram_size);
  1027. return 0;
  1028. }
  1029. static PRFileDesc *small_file_fd, *large_file_fd;
  1030. static void *small_file_addr, *small_file_header, *large_file_addr;
  1031. static void *small_file_trailer, *large_file_header, *large_file_trailer;
  1032. /*
  1033. * TransmitFile_Client
  1034. * Client Thread
  1035. */
  1036. static void
  1037. TransmitFile_Client(void *arg)
  1038. {
  1039. PRFileDesc *sockfd;
  1040. union PRNetAddr netaddr;
  1041. char *small_buf, *large_buf;
  1042. Client_Param *cp = (Client_Param *) arg;
  1043. PRInt32 rlen;
  1044. small_buf = (char*)PR_Malloc(SMALL_FILE_SIZE + SMALL_FILE_HEADER_SIZE +
  1045. SMALL_FILE_TRAILER_SIZE);
  1046. if (small_buf == NULL) {
  1047. fprintf(stderr,"prsocket_test: failed to alloc buffer\n");
  1048. failed_already=1;
  1049. return;
  1050. }
  1051. large_buf = (char*)PR_Malloc(LARGE_FILE_SIZE + LARGE_FILE_HEADER_SIZE +
  1052. LARGE_FILE_TRAILER_SIZE);
  1053. if (large_buf == NULL) {
  1054. fprintf(stderr,"prsocket_test: failed to alloc buffer\n");
  1055. failed_already=1;
  1056. return;
  1057. }
  1058. netaddr.inet.family = cp->server_addr.inet.family;
  1059. netaddr.inet.port = cp->server_addr.inet.port;
  1060. netaddr.inet.ip = cp->server_addr.inet.ip;
  1061. if ((sockfd = PR_NewTCPSocket()) == NULL) {
  1062. fprintf(stderr,"prsocket_test: PR_NewTCPSocket failed\n");
  1063. failed_already=1;
  1064. return;
  1065. }
  1066. if (PR_Connect(sockfd, &netaddr,PR_INTERVAL_NO_TIMEOUT) < 0){
  1067. fprintf(stderr,"prsocket_test: PR_Connect failed\n");
  1068. failed_already=1;
  1069. return;
  1070. }
  1071. /*
  1072. * read the small file and verify the data
  1073. */
  1074. if (readn(sockfd, small_buf, SMALL_FILE_SIZE + SMALL_FILE_HEADER_SIZE)
  1075. != (SMALL_FILE_SIZE + SMALL_FILE_HEADER_SIZE)) {
  1076. fprintf(stderr,
  1077. "prsocket_test: TransmitFile_Client failed to receive file\n");
  1078. failed_already=1;
  1079. return;
  1080. }
  1081. #ifdef XP_UNIX
  1082. if (memcmp(small_file_header, small_buf, SMALL_FILE_HEADER_SIZE) != 0){
  1083. fprintf(stderr,
  1084. "prsocket_test: TransmitFile_Client ERROR - small file header data corruption\n");
  1085. failed_already=1;
  1086. return;
  1087. }
  1088. if (memcmp(small_file_addr, small_buf + SMALL_FILE_HEADER_SIZE,
  1089. SMALL_FILE_SIZE) != 0) {
  1090. fprintf(stderr,
  1091. "prsocket_test: TransmitFile_Client ERROR - small file data corruption\n");
  1092. failed_already=1;
  1093. return;
  1094. }
  1095. #endif
  1096. /*
  1097. * read the large file and verify the data
  1098. */
  1099. if (readn(sockfd, large_buf, LARGE_FILE_SIZE) != LARGE_FILE_SIZE) {
  1100. fprintf(stderr,
  1101. "prsocket_test: TransmitFile_Client failed to receive file\n");
  1102. failed_already=1;
  1103. return;
  1104. }
  1105. #ifdef XP_UNIX
  1106. if (memcmp(large_file_addr, large_buf, LARGE_FILE_SIZE) != 0) {
  1107. fprintf(stderr,
  1108. "prsocket_test: TransmitFile_Client ERROR - large file data corruption\n");
  1109. failed_already=1;
  1110. }
  1111. #endif
  1112. /*
  1113. * receive data from PR_SendFile
  1114. */
  1115. /*
  1116. * case 1: small file with header and trailer
  1117. */
  1118. rlen = SMALL_FILE_SIZE + SMALL_FILE_HEADER_SIZE +
  1119. SMALL_FILE_TRAILER_SIZE;
  1120. if (readn(sockfd, small_buf, rlen) != rlen) {
  1121. fprintf(stderr,
  1122. "prsocket_test: SendFile_Client failed to receive file\n");
  1123. failed_already=1;
  1124. return;
  1125. }
  1126. #ifdef XP_UNIX
  1127. if (memcmp(small_file_header, small_buf, SMALL_FILE_HEADER_SIZE) != 0){
  1128. fprintf(stderr,
  1129. "SendFile 1. ERROR - small file header corruption\n");
  1130. failed_already=1;
  1131. return;
  1132. }
  1133. if (memcmp(small_file_addr, small_buf + SMALL_FILE_HEADER_SIZE,
  1134. SMALL_FILE_SIZE) != 0) {
  1135. fprintf(stderr,
  1136. "SendFile 1. ERROR - small file data corruption\n");
  1137. failed_already=1;
  1138. return;
  1139. }
  1140. if (memcmp(small_file_trailer,
  1141. small_buf + SMALL_FILE_HEADER_SIZE + SMALL_FILE_SIZE,
  1142. SMALL_FILE_TRAILER_SIZE) != 0) {
  1143. fprintf(stderr,
  1144. "SendFile 1. ERROR - small file trailer corruption\n");
  1145. failed_already=1;
  1146. return;
  1147. }
  1148. #endif
  1149. /*
  1150. * case 2: partial large file at zero offset, file with header and trailer
  1151. */
  1152. rlen = LARGE_FILE_LEN_1 + LARGE_FILE_HEADER_SIZE +
  1153. LARGE_FILE_TRAILER_SIZE;
  1154. if (readn(sockfd, large_buf, rlen) != rlen) {
  1155. fprintf(stderr,
  1156. "prsocket_test: SendFile_Client failed to receive file\n");
  1157. failed_already=1;
  1158. return;
  1159. }
  1160. #ifdef XP_UNIX
  1161. if (memcmp(large_file_header, large_buf, LARGE_FILE_HEADER_SIZE) != 0){
  1162. fprintf(stderr,
  1163. "SendFile 2. ERROR - large file header corruption\n");
  1164. failed_already=1;
  1165. return;
  1166. }
  1167. if (memcmp(large_file_addr, large_buf + LARGE_FILE_HEADER_SIZE,
  1168. LARGE_FILE_LEN_1) != 0) {
  1169. fprintf(stderr,
  1170. "SendFile 2. ERROR - large file data corruption\n");
  1171. failed_already=1;
  1172. return;
  1173. }
  1174. if (memcmp(large_file_trailer,
  1175. large_buf + LARGE_FILE_HEADER_SIZE + LARGE_FILE_LEN_1,
  1176. LARGE_FILE_TRAILER_SIZE) != 0) {
  1177. fprintf(stderr,
  1178. "SendFile 2. ERROR - large file trailer corruption\n");
  1179. failed_already=1;
  1180. return;
  1181. }
  1182. #endif
  1183. /*
  1184. * case 3: partial small file at non-zero offset, with header
  1185. */
  1186. rlen = SMALL_FILE_LEN_1 + SMALL_FILE_HEADER_SIZE;
  1187. if (readn(sockfd, small_buf, rlen) != rlen) {
  1188. fprintf(stderr,
  1189. "prsocket_test: SendFile_Client failed to receive file\n");
  1190. failed_already=1;
  1191. return;
  1192. }
  1193. #ifdef XP_UNIX
  1194. if (memcmp(small_file_header, small_buf, SMALL_FILE_HEADER_SIZE) != 0){
  1195. fprintf(stderr,
  1196. "SendFile 3. ERROR - small file header corruption\n");
  1197. failed_already=1;
  1198. return;
  1199. }
  1200. if (memcmp((char *) small_file_addr + SMALL_FILE_OFFSET_1,
  1201. small_buf + SMALL_FILE_HEADER_SIZE, SMALL_FILE_LEN_1) != 0) {
  1202. fprintf(stderr,
  1203. "SendFile 3. ERROR - small file data corruption\n");
  1204. failed_already=1;
  1205. return;
  1206. }
  1207. #endif
  1208. /*
  1209. * case 4: partial small file at non-zero offset, with trailer
  1210. */
  1211. rlen = SMALL_FILE_LEN_2 + SMALL_FILE_TRAILER_SIZE;
  1212. if (readn(sockfd, small_buf, rlen) != rlen) {
  1213. fprintf(stderr,
  1214. "prsocket_test: SendFile_Client failed to receive file\n");
  1215. failed_already=1;
  1216. return;
  1217. }
  1218. #ifdef XP_UNIX
  1219. if (memcmp((char *) small_file_addr + SMALL_FILE_OFFSET_2, small_buf,
  1220. SMALL_FILE_LEN_2) != 0) {
  1221. fprintf(stderr,
  1222. "SendFile 4. ERROR - small file data corruption\n");
  1223. failed_already=1;
  1224. return;
  1225. }
  1226. if (memcmp(small_file_trailer, small_buf + SMALL_FILE_LEN_2,
  1227. SMALL_FILE_TRAILER_SIZE) != 0) {
  1228. fprintf(stderr,
  1229. "SendFile 4. ERROR - small file trailer corruption\n");
  1230. failed_already=1;
  1231. return;
  1232. }
  1233. #endif
  1234. /*
  1235. * case 5: partial large file at non-zero offset, file with header
  1236. */
  1237. rlen = LARGE_FILE_LEN_2 + LARGE_FILE_HEADER_SIZE;
  1238. if (readn(sockfd, large_buf, rlen) != rlen) {
  1239. fprintf(stderr,
  1240. "prsocket_test: SendFile_Client failed to receive file\n");
  1241. failed_already=1;
  1242. return;
  1243. }
  1244. #ifdef XP_UNIX
  1245. if (memcmp(large_file_header, large_buf, LARGE_FILE_HEADER_SIZE) != 0){
  1246. fprintf(stderr,
  1247. "SendFile 5. ERROR - large file header corruption\n");
  1248. failed_already=1;
  1249. return;
  1250. }
  1251. if (memcmp((char *)large_file_addr + LARGE_FILE_OFFSET_2,
  1252. large_buf + LARGE_FILE_HEADER_SIZE,
  1253. LARGE_FILE_LEN_2) != 0) {
  1254. fprintf(stderr,
  1255. "SendFile 5. ERROR - large file data corruption\n");
  1256. failed_already=1;
  1257. return;
  1258. }
  1259. #endif
  1260. /*
  1261. * case 6: partial small file at non-zero offset, with header
  1262. */
  1263. rlen = SMALL_FILE_LEN_3 + SMALL_FILE_HEADER_SIZE;
  1264. if (readn(sockfd, small_buf, rlen) != rlen) {
  1265. fprintf(stderr,
  1266. "prsocket_test: SendFile_Client failed to receive file\n");
  1267. failed_already=1;
  1268. return;
  1269. }
  1270. #ifdef XP_UNIX
  1271. if (memcmp(small_file_header, small_buf, SMALL_FILE_HEADER_SIZE) != 0){
  1272. fprintf(stderr,
  1273. "SendFile 6. ERROR - small file header corruption\n");
  1274. return;
  1275. }
  1276. if (memcmp((char *) small_file_addr + SMALL_FILE_OFFSET_3,
  1277. small_buf + SMALL_FILE_HEADER_SIZE, SMALL_FILE_LEN_3) != 0) {
  1278. #if 0
  1279. char *i, *j;
  1280. int k;
  1281. i = (char *) small_file_addr + SMALL_FILE_OFFSET_3;
  1282. j = small_buf + SMALL_FILE_HEADER_SIZE;
  1283. k = SMALL_FILE_LEN_3;
  1284. while (k-- > 0) {
  1285. if (*i++ != *j++)
  1286. printf("i = %d j = %d\n",
  1287. (int) (i - ((char *) small_file_addr + SMALL_FILE_OFFSET_3)),
  1288. (int) (j - (small_buf + SMALL_FILE_HEADER_SIZE)));
  1289. }
  1290. #endif
  1291. fprintf(stderr,
  1292. "SendFile 6. ERROR - small file data corruption\n");
  1293. failed_already=1;
  1294. return;
  1295. }
  1296. #endif
  1297. /*
  1298. * case 7: partial large file at non-zero offset, with header
  1299. */
  1300. rlen = LARGE_FILE_LEN_3 + LARGE_FILE_HEADER_SIZE;
  1301. if (readn(sockfd, large_buf, rlen) != rlen) {
  1302. fprintf(stderr,
  1303. "prsocket_test: SendFile_Client failed to receive file\n");
  1304. failed_already=1;
  1305. return;
  1306. }
  1307. #ifdef XP_UNIX
  1308. if (memcmp(large_file_header, large_buf, LARGE_FILE_HEADER_SIZE) != 0){
  1309. fprintf(stderr,
  1310. "SendFile 7. ERROR - large file header corruption\n");
  1311. failed_already=1;
  1312. return;
  1313. }
  1314. if (memcmp((char *)large_file_addr + LARGE_FILE_OFFSET_3,
  1315. large_buf + LARGE_FILE_HEADER_SIZE,
  1316. LARGE_FILE_LEN_3) != 0) {
  1317. fprintf(stderr,
  1318. "SendFile 7. ERROR - large file data corruption\n");
  1319. failed_already=1;
  1320. return;
  1321. }
  1322. #endif
  1323. /*
  1324. * case 8: partial large file at non-zero, page-aligned offset, with
  1325. * header and trailer
  1326. */
  1327. rlen = LARGE_FILE_LEN_4 + LARGE_FILE_HEADER_SIZE +
  1328. LARGE_FILE_TRAILER_SIZE;
  1329. if (readn(sockfd, large_buf, rlen) != rlen) {
  1330. fprintf(stderr,
  1331. "prsocket_test: SendFile_Client failed to receive file\n");
  1332. failed_already=1;
  1333. return;
  1334. }
  1335. #ifdef XP_UNIX
  1336. if (memcmp(large_file_header, large_buf, LARGE_FILE_HEADER_SIZE) != 0){
  1337. fprintf(stderr,
  1338. "SendFile 2. ERROR - large file header corruption\n");
  1339. failed_already=1;
  1340. return;
  1341. }
  1342. if (memcmp((char *)large_file_addr + LARGE_FILE_OFFSET_4,
  1343. large_buf + LARGE_FILE_HEADER_SIZE,
  1344. LARGE_FILE_LEN_4) != 0) {
  1345. fprintf(stderr,
  1346. "SendFile 2. ERROR - large file data corruption\n");
  1347. failed_already=1;
  1348. return;
  1349. }
  1350. if (memcmp(large_file_trailer,
  1351. large_buf + LARGE_FILE_HEADER_SIZE + LARGE_FILE_LEN_4,
  1352. LARGE_FILE_TRAILER_SIZE) != 0) {
  1353. fprintf(stderr,
  1354. "SendFile 2. ERROR - large file trailer corruption\n");
  1355. failed_already=1;
  1356. return;
  1357. }
  1358. #endif
  1359. PR_DELETE(small_buf);
  1360. PR_DELETE(large_buf);
  1361. PR_Close(sockfd);
  1362. /*
  1363. * Decrement exit_counter and notify parent thread
  1364. */
  1365. PR_EnterMonitor(cp->exit_mon);
  1366. --(*cp->exit_counter);
  1367. PR_Notify(cp->exit_mon);
  1368. PR_ExitMonitor(cp->exit_mon);
  1369. DPRINTF(("TransmitFile_Client [0x%lx] exiting\n", PR_GetCurrentThread()));
  1370. }
  1371. /*
  1372. * Serve_TransmitFile_Client
  1373. * Thread, started by the server, for serving a client connection.
  1374. * Trasmits a small file, with a header, and a large file, without
  1375. * a header
  1376. */
  1377. static void
  1378. Serve_TransmitFile_Client(void *arg)
  1379. {
  1380. Serve_Client_Param *scp = (Serve_Client_Param *) arg;
  1381. PRFileDesc *sockfd;
  1382. PRInt32 bytes;
  1383. PRFileDesc *local_small_file_fd=NULL;
  1384. PRFileDesc *local_large_file_fd=NULL;
  1385. PRSendFileData sfd;
  1386. PRInt32 slen;
  1387. sockfd = scp->sockfd;
  1388. local_small_file_fd = PR_Open(SMALL_FILE_NAME, PR_RDONLY,0);
  1389. if (local_small_file_fd == NULL) {
  1390. fprintf(stderr,"prsocket_test failed to open file for transmitting %s\n",
  1391. SMALL_FILE_NAME);
  1392. failed_already=1;
  1393. goto done;
  1394. }
  1395. local_large_file_fd = PR_Open(LARGE_FILE_NAME, PR_RDONLY,0);
  1396. if (local_large_file_fd == NULL) {
  1397. fprintf(stderr,"prsocket_test failed to open file for transmitting %s\n",
  1398. LARGE_FILE_NAME);
  1399. failed_already=1;
  1400. goto done;
  1401. }
  1402. bytes = PR_TransmitFile(sockfd, local_small_file_fd, small_file_header,
  1403. SMALL_FILE_HEADER_SIZE, PR_TRANSMITFILE_KEEP_OPEN,
  1404. PR_INTERVAL_NO_TIMEOUT);
  1405. if (bytes != (SMALL_FILE_SIZE+ SMALL_FILE_HEADER_SIZE)) {
  1406. fprintf(stderr,
  1407. "prsocet_test: PR_TransmitFile failed: (%ld, %ld)\n",
  1408. PR_GetError(), PR_GetOSError());
  1409. failed_already=1;
  1410. }
  1411. bytes = PR_TransmitFile(sockfd, local_large_file_fd, NULL, 0,
  1412. PR_TRANSMITFILE_KEEP_OPEN, PR_INTERVAL_NO_TIMEOUT);
  1413. if (bytes != LARGE_FILE_SIZE) {
  1414. fprintf(stderr,
  1415. "prsocket_test: PR_TransmitFile failed: (%ld, %ld)\n",
  1416. PR_GetError(), PR_GetOSError());
  1417. failed_already=1;
  1418. }
  1419. /*
  1420. * PR_SendFile test cases
  1421. */
  1422. /*
  1423. * case 1: small file with header and trailer
  1424. */
  1425. sfd.fd = local_small_file_fd;
  1426. sfd.file_offset = 0;
  1427. sfd.file_nbytes = 0;
  1428. sfd.header = small_file_header;
  1429. sfd.hlen = SMALL_FILE_HEADER_SIZE;
  1430. sfd.trailer = small_file_trailer;
  1431. sfd.tlen = SMALL_FILE_TRAILER_SIZE;
  1432. bytes = PR_SendFile(sockfd, &sfd, PR_TRANSMITFILE_KEEP_OPEN,
  1433. PR_INTERVAL_NO_TIMEOUT);
  1434. slen = SMALL_FILE_SIZE+ SMALL_FILE_HEADER_SIZE +
  1435. SMALL_FILE_TRAILER_SIZE;
  1436. if (bytes != slen) {
  1437. fprintf(stderr,
  1438. "socket: Error - 1. PR_SendFile send_size = %d, bytes sent = %d\n",
  1439. slen, bytes);
  1440. fprintf(stderr,
  1441. "prsocket_test: PR_SendFile failed: (%ld, %ld)\n",
  1442. PR_GetError(), PR_GetOSError());
  1443. failed_already=1;
  1444. }
  1445. /*
  1446. * case 2: partial large file at zero offset, file with header and trailer
  1447. */
  1448. sfd.fd = local_large_file_fd;
  1449. sfd.file_offset = 0;
  1450. sfd.file_nbytes = LARGE_FILE_LEN_1;
  1451. sfd.header = large_file_header;
  1452. sfd.hlen = LARGE_FILE_HEADER_SIZE;
  1453. sfd.trailer = large_file_trailer;
  1454. sfd.tlen = LARGE_FILE_TRAILER_SIZE;
  1455. bytes = PR_SendFile(sockfd, &sfd, PR_TRANSMITFILE_KEEP_OPEN,
  1456. PR_INTERVAL_NO_TIMEOUT);
  1457. slen = LARGE_FILE_LEN_1 + LARGE_FILE_HEADER_SIZE +
  1458. LARGE_FILE_TRAILER_SIZE;
  1459. if (bytes != slen) {
  1460. fprintf(stderr,
  1461. "socket: Error - 2. PR_SendFile send_size = %d, bytes sent = %d\n",
  1462. slen, bytes);
  1463. fprintf(stderr,
  1464. "prsocket_test: PR_SendFile failed: (%ld, %ld)\n",
  1465. PR_GetError(), PR_GetOSError());
  1466. failed_already=1;
  1467. }
  1468. /*
  1469. * case 3: partial small file at non-zero offset, with header
  1470. */
  1471. sfd.fd = local_small_file_fd;
  1472. sfd.file_offset = SMALL_FILE_OFFSET_1;
  1473. sfd.file_nbytes = SMALL_FILE_LEN_1;
  1474. sfd.header = small_file_header;
  1475. sfd.hlen = SMALL_FILE_HEADER_SIZE;
  1476. sfd.trailer = NULL;
  1477. sfd.tlen = 0;
  1478. bytes = PR_SendFile(sockfd, &sfd, PR_TRANSMITFILE_KEEP_OPEN,
  1479. PR_INTERVAL_NO_TIMEOUT);
  1480. slen = SMALL_FILE_LEN_1 + SMALL_FILE_HEADER_SIZE;
  1481. if (bytes != slen) {
  1482. fprintf(stderr,
  1483. "socket: Error - 3. PR_SendFile send_size = %d, bytes sent = %d\n",
  1484. slen, bytes);
  1485. fprintf(stderr,
  1486. "prsocket_test: PR_SendFile failed: (%ld, %ld)\n",
  1487. PR_GetError(), PR_GetOSError());
  1488. failed_already=1;
  1489. }
  1490. /*
  1491. * case 4: partial small file at non-zero offset, with trailer
  1492. */
  1493. sfd.fd = local_small_file_fd;
  1494. sfd.file_offset = SMALL_FILE_OFFSET_2;
  1495. sfd.file_nbytes = SMALL_FILE_LEN_2;
  1496. sfd.header = NULL;
  1497. sfd.hlen = 0;
  1498. sfd.trailer = small_file_trailer;
  1499. sfd.tlen = SMALL_FILE_TRAILER_SIZE;
  1500. bytes = PR_SendFile(sockfd, &sfd, PR_TRANSMITFILE_KEEP_OPEN,
  1501. PR_INTERVAL_NO_TIMEOUT);
  1502. slen = SMALL_FILE_LEN_2 + SMALL_FILE_TRAILER_SIZE;
  1503. if (bytes != slen) {
  1504. fprintf(stderr,
  1505. "socket: Error - 4. PR_SendFile send_size = %d, bytes sent = %d\n",
  1506. slen, bytes);
  1507. fprintf(stderr,
  1508. "prsocket_test: PR_SendFile failed: (%ld, %ld)\n",
  1509. PR_GetError(), PR_GetOSError());
  1510. failed_already=1;
  1511. }
  1512. /*
  1513. * case 5: partial large file at non-zero offset, file with header
  1514. */
  1515. sfd.fd = local_large_file_fd;
  1516. sfd.file_offset = LARGE_FILE_OFFSET_2;