Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
michael@0 | 1 | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
michael@0 | 2 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 4 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 5 | |
michael@0 | 6 | /*********************************************************************** |
michael@0 | 7 | ** |
michael@0 | 8 | ** Name: socket.c |
michael@0 | 9 | ** |
michael@0 | 10 | ** Description: Test socket functionality. |
michael@0 | 11 | ** |
michael@0 | 12 | ** Modification History: |
michael@0 | 13 | */ |
michael@0 | 14 | #include "primpl.h" |
michael@0 | 15 | |
michael@0 | 16 | #include "plgetopt.h" |
michael@0 | 17 | |
michael@0 | 18 | #include <stdio.h> |
michael@0 | 19 | #include <string.h> |
michael@0 | 20 | #include <errno.h> |
michael@0 | 21 | #ifdef XP_UNIX |
michael@0 | 22 | #include <sys/mman.h> |
michael@0 | 23 | #endif |
michael@0 | 24 | #if defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS) |
michael@0 | 25 | #include <pthread.h> |
michael@0 | 26 | #endif |
michael@0 | 27 | |
michael@0 | 28 | #ifdef WIN32 |
michael@0 | 29 | #include <process.h> |
michael@0 | 30 | #endif |
michael@0 | 31 | |
michael@0 | 32 | static int _debug_on = 0; |
michael@0 | 33 | static int test_cancelio = 0; |
michael@0 | 34 | |
michael@0 | 35 | #include "obsolete/prsem.h" |
michael@0 | 36 | |
michael@0 | 37 | #ifdef XP_PC |
michael@0 | 38 | #define mode_t int |
michael@0 | 39 | #endif |
michael@0 | 40 | |
michael@0 | 41 | #define DPRINTF(arg) if (_debug_on) printf arg |
michael@0 | 42 | |
michael@0 | 43 | #ifdef XP_PC |
michael@0 | 44 | char *TEST_DIR = "prdir"; |
michael@0 | 45 | char *SMALL_FILE_NAME = "prsmallf"; |
michael@0 | 46 | char *LARGE_FILE_NAME = "prlargef"; |
michael@0 | 47 | #elif defined(SYMBIAN) |
michael@0 | 48 | char *TEST_DIR = "c:\\data\\prsocket"; |
michael@0 | 49 | char *SMALL_FILE_NAME = "c:\\data\\prsocket\\small_file"; |
michael@0 | 50 | char *LARGE_FILE_NAME = "c:\\data\\prsocket\\large_file"; |
michael@0 | 51 | #else |
michael@0 | 52 | char *TEST_DIR = "/tmp/prsocket_test_dir"; |
michael@0 | 53 | char *SMALL_FILE_NAME = "/tmp/prsocket_test_dir/small_file"; |
michael@0 | 54 | char *LARGE_FILE_NAME = "/tmp/prsocket_test_dir/large_file"; |
michael@0 | 55 | #endif |
michael@0 | 56 | #define SMALL_FILE_SIZE (3 * 1024) /* 3 KB */ |
michael@0 | 57 | #define SMALL_FILE_OFFSET_1 (512) |
michael@0 | 58 | #define SMALL_FILE_LEN_1 (1 * 1024) /* 1 KB */ |
michael@0 | 59 | #define SMALL_FILE_OFFSET_2 (75) |
michael@0 | 60 | #define SMALL_FILE_LEN_2 (758) |
michael@0 | 61 | #define SMALL_FILE_OFFSET_3 (1024) |
michael@0 | 62 | #define SMALL_FILE_LEN_3 (SMALL_FILE_SIZE - SMALL_FILE_OFFSET_3) |
michael@0 | 63 | #define SMALL_FILE_HEADER_SIZE (64) /* 64 bytes */ |
michael@0 | 64 | #define SMALL_FILE_TRAILER_SIZE (128) /* 128 bytes */ |
michael@0 | 65 | |
michael@0 | 66 | #define LARGE_FILE_SIZE (3 * 1024 * 1024) /* 3 MB */ |
michael@0 | 67 | #define LARGE_FILE_OFFSET_1 (0) |
michael@0 | 68 | #define LARGE_FILE_LEN_1 (2 * 1024 * 1024) /* 2 MB */ |
michael@0 | 69 | #define LARGE_FILE_OFFSET_2 (64) |
michael@0 | 70 | #define LARGE_FILE_LEN_2 (1 * 1024 * 1024 + 75) |
michael@0 | 71 | #define LARGE_FILE_OFFSET_3 (2 * 1024 * 1024 - 128) |
michael@0 | 72 | #define LARGE_FILE_LEN_3 (LARGE_FILE_SIZE - LARGE_FILE_OFFSET_3) |
michael@0 | 73 | #define LARGE_FILE_OFFSET_4 PR_GetPageSize() |
michael@0 | 74 | #define LARGE_FILE_LEN_4 769 |
michael@0 | 75 | #define LARGE_FILE_HEADER_SIZE (512) |
michael@0 | 76 | #define LARGE_FILE_TRAILER_SIZE (64) |
michael@0 | 77 | |
michael@0 | 78 | #define BUF_DATA_SIZE (2 * 1024) |
michael@0 | 79 | #define TCP_MESG_SIZE 1024 |
michael@0 | 80 | /* |
michael@0 | 81 | * set UDP datagram size small enough that datagrams sent to a port on the |
michael@0 | 82 | * local host will not be lost |
michael@0 | 83 | */ |
michael@0 | 84 | #define UDP_DGRAM_SIZE 128 |
michael@0 | 85 | #define NUM_TCP_CLIENTS 5 /* for a listen queue depth of 5 */ |
michael@0 | 86 | #define NUM_UDP_CLIENTS 10 |
michael@0 | 87 | |
michael@0 | 88 | #ifdef SYMBIAN |
michael@0 | 89 | #define NUM_TRANSMITFILE_CLIENTS 1 |
michael@0 | 90 | #else |
michael@0 | 91 | #define NUM_TRANSMITFILE_CLIENTS 4 |
michael@0 | 92 | #endif |
michael@0 | 93 | |
michael@0 | 94 | #define NUM_TCP_CONNECTIONS_PER_CLIENT 5 |
michael@0 | 95 | #define NUM_TCP_MESGS_PER_CONNECTION 10 |
michael@0 | 96 | #define NUM_UDP_DATAGRAMS_PER_CLIENT 5 |
michael@0 | 97 | #define TCP_SERVER_PORT 10000 |
michael@0 | 98 | #define UDP_SERVER_PORT TCP_SERVER_PORT |
michael@0 | 99 | #define SERVER_MAX_BIND_COUNT 100 |
michael@0 | 100 | |
michael@0 | 101 | #ifdef WINCE |
michael@0 | 102 | #define perror(s) |
michael@0 | 103 | #endif |
michael@0 | 104 | |
michael@0 | 105 | static PRInt32 num_tcp_clients = NUM_TCP_CLIENTS; |
michael@0 | 106 | static PRInt32 num_udp_clients = NUM_UDP_CLIENTS; |
michael@0 | 107 | static PRInt32 num_transmitfile_clients = NUM_TRANSMITFILE_CLIENTS; |
michael@0 | 108 | static PRInt32 num_tcp_connections_per_client = NUM_TCP_CONNECTIONS_PER_CLIENT; |
michael@0 | 109 | static PRInt32 tcp_mesg_size = TCP_MESG_SIZE; |
michael@0 | 110 | static PRInt32 num_tcp_mesgs_per_connection = NUM_TCP_MESGS_PER_CONNECTION; |
michael@0 | 111 | static PRInt32 num_udp_datagrams_per_client = NUM_UDP_DATAGRAMS_PER_CLIENT; |
michael@0 | 112 | static PRInt32 udp_datagram_size = UDP_DGRAM_SIZE; |
michael@0 | 113 | |
michael@0 | 114 | static PRInt32 thread_count; |
michael@0 | 115 | PRUint16 server_domain = PR_AF_INET, client_domain = PR_AF_INET; |
michael@0 | 116 | |
michael@0 | 117 | /* an I/O layer that uses the emulated senfile method */ |
michael@0 | 118 | static PRDescIdentity emuSendFileIdentity; |
michael@0 | 119 | static PRIOMethods emuSendFileMethods; |
michael@0 | 120 | |
michael@0 | 121 | int failed_already=0; |
michael@0 | 122 | typedef struct buffer { |
michael@0 | 123 | char data[BUF_DATA_SIZE]; |
michael@0 | 124 | } buffer; |
michael@0 | 125 | |
michael@0 | 126 | PRNetAddr tcp_server_addr, udp_server_addr; |
michael@0 | 127 | |
michael@0 | 128 | typedef struct Serve_Client_Param { |
michael@0 | 129 | PRFileDesc *sockfd; /* socket to read from/write to */ |
michael@0 | 130 | PRInt32 datalen; /* bytes of data transfered in each read/write */ |
michael@0 | 131 | } Serve_Client_Param; |
michael@0 | 132 | |
michael@0 | 133 | typedef struct Server_Param { |
michael@0 | 134 | PRSemaphore *addr_sem; /* sem to post on, after setting up the address */ |
michael@0 | 135 | PRMonitor *exit_mon; /* monitor to signal on exit */ |
michael@0 | 136 | PRInt32 *exit_counter; /* counter to decrement, before exit */ |
michael@0 | 137 | PRInt32 datalen; /* bytes of data transfered in each read/write */ |
michael@0 | 138 | } Server_Param; |
michael@0 | 139 | |
michael@0 | 140 | |
michael@0 | 141 | typedef struct Client_Param { |
michael@0 | 142 | PRNetAddr server_addr; |
michael@0 | 143 | PRMonitor *exit_mon; /* monitor to signal on exit */ |
michael@0 | 144 | PRInt32 *exit_counter; /* counter to decrement, before exit */ |
michael@0 | 145 | PRInt32 datalen; |
michael@0 | 146 | PRInt32 udp_connect; /* if set clients connect udp sockets */ |
michael@0 | 147 | } Client_Param; |
michael@0 | 148 | |
michael@0 | 149 | /* the sendfile method in emuSendFileMethods */ |
michael@0 | 150 | static PRInt32 PR_CALLBACK |
michael@0 | 151 | emu_SendFile(PRFileDesc *sd, PRSendFileData *sfd, |
michael@0 | 152 | PRTransmitFileFlags flags, PRIntervalTime timeout) |
michael@0 | 153 | { |
michael@0 | 154 | return PR_EmulateSendFile(sd, sfd, flags, timeout); |
michael@0 | 155 | } |
michael@0 | 156 | |
michael@0 | 157 | /* the transmitfile method in emuSendFileMethods */ |
michael@0 | 158 | static PRInt32 PR_CALLBACK |
michael@0 | 159 | emu_TransmitFile(PRFileDesc *sd, PRFileDesc *fd, const void *headers, |
michael@0 | 160 | PRInt32 hlen, PRTransmitFileFlags flags, PRIntervalTime timeout) |
michael@0 | 161 | { |
michael@0 | 162 | PRSendFileData sfd; |
michael@0 | 163 | |
michael@0 | 164 | sfd.fd = fd; |
michael@0 | 165 | sfd.file_offset = 0; |
michael@0 | 166 | sfd.file_nbytes = 0; |
michael@0 | 167 | sfd.header = headers; |
michael@0 | 168 | sfd.hlen = hlen; |
michael@0 | 169 | sfd.trailer = NULL; |
michael@0 | 170 | sfd.tlen = 0; |
michael@0 | 171 | return emu_SendFile(sd, &sfd, flags, timeout); |
michael@0 | 172 | } |
michael@0 | 173 | |
michael@0 | 174 | /* |
michael@0 | 175 | * readn |
michael@0 | 176 | * read data from sockfd into buf |
michael@0 | 177 | */ |
michael@0 | 178 | static PRInt32 |
michael@0 | 179 | readn(PRFileDesc *sockfd, char *buf, int len) |
michael@0 | 180 | { |
michael@0 | 181 | int rem; |
michael@0 | 182 | int bytes; |
michael@0 | 183 | int offset = 0; |
michael@0 | 184 | int err; |
michael@0 | 185 | PRIntervalTime timeout = PR_INTERVAL_NO_TIMEOUT; |
michael@0 | 186 | |
michael@0 | 187 | if (test_cancelio) |
michael@0 | 188 | timeout = PR_SecondsToInterval(2); |
michael@0 | 189 | |
michael@0 | 190 | for (rem=len; rem; offset += bytes, rem -= bytes) { |
michael@0 | 191 | DPRINTF(("thread = 0x%lx: calling PR_Recv, bytes = %d\n", |
michael@0 | 192 | PR_GetCurrentThread(), rem)); |
michael@0 | 193 | retry: |
michael@0 | 194 | bytes = PR_Recv(sockfd, buf + offset, rem, 0, |
michael@0 | 195 | timeout); |
michael@0 | 196 | DPRINTF(("thread = 0x%lx: returning from PR_Recv, bytes = %d\n", |
michael@0 | 197 | PR_GetCurrentThread(), bytes)); |
michael@0 | 198 | if (bytes < 0) { |
michael@0 | 199 | #ifdef WINNT |
michael@0 | 200 | printf("PR_Recv: error = %d oserr = %d\n",(err = PR_GetError()), |
michael@0 | 201 | PR_GetOSError()); |
michael@0 | 202 | if ((test_cancelio) && (err == PR_IO_TIMEOUT_ERROR)) { |
michael@0 | 203 | if (PR_NT_CancelIo(sockfd) != PR_SUCCESS) |
michael@0 | 204 | printf("PR_NT_CancelIO: error = %d\n",PR_GetError()); |
michael@0 | 205 | timeout = PR_INTERVAL_NO_TIMEOUT; |
michael@0 | 206 | goto retry; |
michael@0 | 207 | } |
michael@0 | 208 | #endif |
michael@0 | 209 | return -1; |
michael@0 | 210 | } |
michael@0 | 211 | } |
michael@0 | 212 | return len; |
michael@0 | 213 | } |
michael@0 | 214 | |
michael@0 | 215 | /* |
michael@0 | 216 | * writen |
michael@0 | 217 | * write data from buf to sockfd |
michael@0 | 218 | */ |
michael@0 | 219 | static PRInt32 |
michael@0 | 220 | writen(PRFileDesc *sockfd, char *buf, int len) |
michael@0 | 221 | { |
michael@0 | 222 | int rem; |
michael@0 | 223 | int bytes; |
michael@0 | 224 | int offset = 0; |
michael@0 | 225 | |
michael@0 | 226 | for (rem=len; rem; offset += bytes, rem -= bytes) { |
michael@0 | 227 | DPRINTF(("thread = 0x%lx: calling PR_Send, bytes = %d\n", |
michael@0 | 228 | PR_GetCurrentThread(), rem)); |
michael@0 | 229 | bytes = PR_Send(sockfd, buf + offset, rem, 0, |
michael@0 | 230 | PR_INTERVAL_NO_TIMEOUT); |
michael@0 | 231 | DPRINTF(("thread = 0x%lx: returning from PR_Send, bytes = %d\n", |
michael@0 | 232 | PR_GetCurrentThread(), bytes)); |
michael@0 | 233 | if (bytes <= 0) |
michael@0 | 234 | return -1; |
michael@0 | 235 | } |
michael@0 | 236 | return len; |
michael@0 | 237 | } |
michael@0 | 238 | |
michael@0 | 239 | /* |
michael@0 | 240 | * Serve_Client |
michael@0 | 241 | * Thread, started by the server, for serving a client connection. |
michael@0 | 242 | * Reads data from socket and writes it back, unmodified, and |
michael@0 | 243 | * closes the socket |
michael@0 | 244 | */ |
michael@0 | 245 | static void PR_CALLBACK |
michael@0 | 246 | Serve_Client(void *arg) |
michael@0 | 247 | { |
michael@0 | 248 | Serve_Client_Param *scp = (Serve_Client_Param *) arg; |
michael@0 | 249 | PRFileDesc *sockfd; |
michael@0 | 250 | buffer *in_buf; |
michael@0 | 251 | PRInt32 bytes, j; |
michael@0 | 252 | |
michael@0 | 253 | sockfd = scp->sockfd; |
michael@0 | 254 | bytes = scp->datalen; |
michael@0 | 255 | in_buf = PR_NEW(buffer); |
michael@0 | 256 | if (in_buf == NULL) { |
michael@0 | 257 | fprintf(stderr,"prsocket_test: failed to alloc buffer struct\n"); |
michael@0 | 258 | failed_already=1; |
michael@0 | 259 | goto exit; |
michael@0 | 260 | } |
michael@0 | 261 | |
michael@0 | 262 | |
michael@0 | 263 | for (j = 0; j < num_tcp_mesgs_per_connection; j++) { |
michael@0 | 264 | /* |
michael@0 | 265 | * Read data from client and send it back to the client unmodified |
michael@0 | 266 | */ |
michael@0 | 267 | if (readn(sockfd, in_buf->data, bytes) < bytes) { |
michael@0 | 268 | fprintf(stderr,"prsocket_test: ERROR - Serve_Client:readn\n"); |
michael@0 | 269 | failed_already=1; |
michael@0 | 270 | goto exit; |
michael@0 | 271 | } |
michael@0 | 272 | /* Shutdown only RCV will cause error on Symbian OS */ |
michael@0 | 273 | #if !defined(SYMBIAN) |
michael@0 | 274 | /* |
michael@0 | 275 | * shutdown reads, after the last read |
michael@0 | 276 | */ |
michael@0 | 277 | if (j == num_tcp_mesgs_per_connection - 1) |
michael@0 | 278 | if (PR_Shutdown(sockfd, PR_SHUTDOWN_RCV) < 0) { |
michael@0 | 279 | fprintf(stderr,"prsocket_test: ERROR - PR_Shutdown\n"); |
michael@0 | 280 | } |
michael@0 | 281 | #endif |
michael@0 | 282 | DPRINTF(("Serve_Client [0x%lx]: inbuf[0] = 0x%lx\n",PR_GetCurrentThread(), |
michael@0 | 283 | (*((int *) in_buf->data)))); |
michael@0 | 284 | if (writen(sockfd, in_buf->data, bytes) < bytes) { |
michael@0 | 285 | fprintf(stderr,"prsocket_test: ERROR - Serve_Client:writen\n"); |
michael@0 | 286 | failed_already=1; |
michael@0 | 287 | goto exit; |
michael@0 | 288 | } |
michael@0 | 289 | } |
michael@0 | 290 | /* |
michael@0 | 291 | * shutdown reads and writes |
michael@0 | 292 | */ |
michael@0 | 293 | if (PR_Shutdown(sockfd, PR_SHUTDOWN_BOTH) < 0) { |
michael@0 | 294 | fprintf(stderr,"prsocket_test: ERROR - PR_Shutdown\n"); |
michael@0 | 295 | failed_already=1; |
michael@0 | 296 | } |
michael@0 | 297 | |
michael@0 | 298 | exit: |
michael@0 | 299 | PR_Close(sockfd); |
michael@0 | 300 | if (in_buf) { |
michael@0 | 301 | PR_DELETE(in_buf); |
michael@0 | 302 | } |
michael@0 | 303 | } |
michael@0 | 304 | |
michael@0 | 305 | PRThread* create_new_thread(PRThreadType type, |
michael@0 | 306 | void (*start)(void *arg), |
michael@0 | 307 | void *arg, |
michael@0 | 308 | PRThreadPriority priority, |
michael@0 | 309 | PRThreadScope scope, |
michael@0 | 310 | PRThreadState state, |
michael@0 | 311 | PRUint32 stackSize, PRInt32 index) |
michael@0 | 312 | { |
michael@0 | 313 | PRInt32 native_thread = 0; |
michael@0 | 314 | |
michael@0 | 315 | PR_ASSERT(state == PR_UNJOINABLE_THREAD); |
michael@0 | 316 | #if (defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS)) || defined(WIN32) |
michael@0 | 317 | switch(index % 4) { |
michael@0 | 318 | case 0: |
michael@0 | 319 | scope = (PR_LOCAL_THREAD); |
michael@0 | 320 | break; |
michael@0 | 321 | case 1: |
michael@0 | 322 | scope = (PR_GLOBAL_THREAD); |
michael@0 | 323 | break; |
michael@0 | 324 | case 2: |
michael@0 | 325 | scope = (PR_GLOBAL_BOUND_THREAD); |
michael@0 | 326 | break; |
michael@0 | 327 | case 3: |
michael@0 | 328 | native_thread = 1; |
michael@0 | 329 | break; |
michael@0 | 330 | default: |
michael@0 | 331 | PR_ASSERT(!"Invalid scope"); |
michael@0 | 332 | break; |
michael@0 | 333 | } |
michael@0 | 334 | if (native_thread) { |
michael@0 | 335 | #if defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS) |
michael@0 | 336 | pthread_t tid; |
michael@0 | 337 | if (!pthread_create(&tid, NULL, (void * (*)(void *)) start, arg)) |
michael@0 | 338 | return((PRThread *) tid); |
michael@0 | 339 | else |
michael@0 | 340 | return (NULL); |
michael@0 | 341 | #else |
michael@0 | 342 | HANDLE thandle; |
michael@0 | 343 | unsigned tid; |
michael@0 | 344 | |
michael@0 | 345 | thandle = (HANDLE) _beginthreadex( |
michael@0 | 346 | NULL, |
michael@0 | 347 | stackSize, |
michael@0 | 348 | (unsigned (__stdcall *)(void *))start, |
michael@0 | 349 | arg, |
michael@0 | 350 | STACK_SIZE_PARAM_IS_A_RESERVATION, |
michael@0 | 351 | &tid); |
michael@0 | 352 | return((PRThread *) thandle); |
michael@0 | 353 | #endif |
michael@0 | 354 | } else { |
michael@0 | 355 | return(PR_CreateThread(type,start,arg,priority,scope,state,stackSize)); |
michael@0 | 356 | } |
michael@0 | 357 | #else |
michael@0 | 358 | return(PR_CreateThread(type,start,arg,priority,scope,state,stackSize)); |
michael@0 | 359 | #endif |
michael@0 | 360 | } |
michael@0 | 361 | |
michael@0 | 362 | /* |
michael@0 | 363 | * TCP Server |
michael@0 | 364 | * Server Thread |
michael@0 | 365 | * Bind an address to a socket and listen for incoming connections |
michael@0 | 366 | * Start a Serve_Client thread for each incoming connection. |
michael@0 | 367 | */ |
michael@0 | 368 | static void PR_CALLBACK |
michael@0 | 369 | TCP_Server(void *arg) |
michael@0 | 370 | { |
michael@0 | 371 | PRThread *t; |
michael@0 | 372 | Server_Param *sp = (Server_Param *) arg; |
michael@0 | 373 | Serve_Client_Param *scp; |
michael@0 | 374 | PRFileDesc *sockfd, *newsockfd; |
michael@0 | 375 | PRNetAddr netaddr; |
michael@0 | 376 | PRInt32 i; |
michael@0 | 377 | /* |
michael@0 | 378 | * Create a tcp socket |
michael@0 | 379 | */ |
michael@0 | 380 | if ((sockfd = PR_OpenTCPSocket(server_domain)) == NULL) { |
michael@0 | 381 | fprintf(stderr,"prsocket_test: PR_NewTCPSocket failed\n"); |
michael@0 | 382 | goto exit; |
michael@0 | 383 | } |
michael@0 | 384 | memset(&netaddr, 0 , sizeof(netaddr)); |
michael@0 | 385 | |
michael@0 | 386 | if (PR_SetNetAddr(PR_IpAddrAny, server_domain, TCP_SERVER_PORT, |
michael@0 | 387 | &netaddr) == PR_FAILURE) { |
michael@0 | 388 | fprintf(stderr,"prsocket_test: PR_SetNetAddr failed\n"); |
michael@0 | 389 | goto exit; |
michael@0 | 390 | } |
michael@0 | 391 | /* |
michael@0 | 392 | * try a few times to bind server's address, if addresses are in |
michael@0 | 393 | * use |
michael@0 | 394 | */ |
michael@0 | 395 | i = 0; |
michael@0 | 396 | |
michael@0 | 397 | while (PR_Bind(sockfd, &netaddr) < 0) { |
michael@0 | 398 | if (PR_GetError() == PR_ADDRESS_IN_USE_ERROR) { |
michael@0 | 399 | netaddr.inet.port += 2; |
michael@0 | 400 | if (i++ < SERVER_MAX_BIND_COUNT) |
michael@0 | 401 | continue; |
michael@0 | 402 | } |
michael@0 | 403 | fprintf(stderr,"prsocket_test: ERROR - PR_Bind failed\n"); |
michael@0 | 404 | perror("PR_Bind"); |
michael@0 | 405 | failed_already=1; |
michael@0 | 406 | goto exit; |
michael@0 | 407 | } |
michael@0 | 408 | |
michael@0 | 409 | if (PR_Listen(sockfd, 32) < 0) { |
michael@0 | 410 | fprintf(stderr,"prsocket_test: ERROR - PR_Listen failed\n"); |
michael@0 | 411 | failed_already=1; |
michael@0 | 412 | goto exit; |
michael@0 | 413 | } |
michael@0 | 414 | |
michael@0 | 415 | if (PR_GetSockName(sockfd, &netaddr) < 0) { |
michael@0 | 416 | fprintf(stderr,"prsocket_test: ERROR - PR_GetSockName failed\n"); |
michael@0 | 417 | failed_already=1; |
michael@0 | 418 | goto exit; |
michael@0 | 419 | } |
michael@0 | 420 | |
michael@0 | 421 | DPRINTF(("TCP_Server: PR_BIND netaddr.inet.ip = 0x%lx, netaddr.inet.port = %d\n", |
michael@0 | 422 | netaddr.inet.ip, netaddr.inet.port)); |
michael@0 | 423 | if (PR_SetNetAddr(PR_IpAddrLoopback, client_domain, |
michael@0 | 424 | PR_ntohs(PR_NetAddrInetPort(&netaddr)), |
michael@0 | 425 | &tcp_server_addr) == PR_FAILURE) { |
michael@0 | 426 | fprintf(stderr,"prsocket_test: PR_SetNetAddr failed\n"); |
michael@0 | 427 | goto exit; |
michael@0 | 428 | } |
michael@0 | 429 | if ((client_domain == PR_AF_INET6) && (server_domain == PR_AF_INET)) |
michael@0 | 430 | PR_ConvertIPv4AddrToIPv6(PR_htonl(INADDR_LOOPBACK), |
michael@0 | 431 | &tcp_server_addr.ipv6.ip); |
michael@0 | 432 | |
michael@0 | 433 | /* |
michael@0 | 434 | * Wake up parent thread because server address is bound and made |
michael@0 | 435 | * available in the global variable 'tcp_server_addr' |
michael@0 | 436 | */ |
michael@0 | 437 | PR_PostSem(sp->addr_sem); |
michael@0 | 438 | |
michael@0 | 439 | for (i = 0; i < (num_tcp_clients * num_tcp_connections_per_client); i++) { |
michael@0 | 440 | /* test both null and non-null 'addr' argument to PR_Accept */ |
michael@0 | 441 | PRNetAddr *addrp = (i%2 ? &netaddr: NULL); |
michael@0 | 442 | |
michael@0 | 443 | DPRINTF(("TCP_Server: Accepting connection\n")); |
michael@0 | 444 | if ((newsockfd = PR_Accept(sockfd, addrp, |
michael@0 | 445 | PR_INTERVAL_NO_TIMEOUT)) == NULL) { |
michael@0 | 446 | fprintf(stderr,"prsocket_test: ERROR - PR_Accept failed\n"); |
michael@0 | 447 | goto exit; |
michael@0 | 448 | } |
michael@0 | 449 | DPRINTF(("TCP_Server: Accepted connection\n")); |
michael@0 | 450 | scp = PR_NEW(Serve_Client_Param); |
michael@0 | 451 | if (scp == NULL) { |
michael@0 | 452 | fprintf(stderr,"prsocket_test: PR_NEW failed\n"); |
michael@0 | 453 | goto exit; |
michael@0 | 454 | } |
michael@0 | 455 | |
michael@0 | 456 | /* |
michael@0 | 457 | * Start a Serve_Client thread for each incoming connection |
michael@0 | 458 | */ |
michael@0 | 459 | scp->sockfd = newsockfd; |
michael@0 | 460 | scp->datalen = sp->datalen; |
michael@0 | 461 | |
michael@0 | 462 | t = create_new_thread(PR_USER_THREAD, |
michael@0 | 463 | Serve_Client, (void *)scp, |
michael@0 | 464 | PR_PRIORITY_NORMAL, |
michael@0 | 465 | PR_LOCAL_THREAD, |
michael@0 | 466 | PR_UNJOINABLE_THREAD, |
michael@0 | 467 | 0, i); |
michael@0 | 468 | if (t == NULL) { |
michael@0 | 469 | fprintf(stderr,"prsocket_test: PR_CreateThread failed\n"); |
michael@0 | 470 | failed_already=1; |
michael@0 | 471 | goto exit; |
michael@0 | 472 | } |
michael@0 | 473 | DPRINTF(("TCP_Server: Created Serve_Client = 0x%lx\n", t)); |
michael@0 | 474 | } |
michael@0 | 475 | |
michael@0 | 476 | exit: |
michael@0 | 477 | if (sockfd) { |
michael@0 | 478 | PR_Close(sockfd); |
michael@0 | 479 | } |
michael@0 | 480 | |
michael@0 | 481 | /* |
michael@0 | 482 | * Decrement exit_counter and notify parent thread |
michael@0 | 483 | */ |
michael@0 | 484 | |
michael@0 | 485 | PR_EnterMonitor(sp->exit_mon); |
michael@0 | 486 | --(*sp->exit_counter); |
michael@0 | 487 | PR_Notify(sp->exit_mon); |
michael@0 | 488 | PR_ExitMonitor(sp->exit_mon); |
michael@0 | 489 | DPRINTF(("TCP_Server [0x%lx] exiting\n", PR_GetCurrentThread())); |
michael@0 | 490 | } |
michael@0 | 491 | |
michael@0 | 492 | /* |
michael@0 | 493 | * UDP Server |
michael@0 | 494 | * Server Thread |
michael@0 | 495 | * Bind an address to a socket, read data from clients and send data |
michael@0 | 496 | * back to clients |
michael@0 | 497 | */ |
michael@0 | 498 | static void PR_CALLBACK |
michael@0 | 499 | UDP_Server(void *arg) |
michael@0 | 500 | { |
michael@0 | 501 | Server_Param *sp = (Server_Param *) arg; |
michael@0 | 502 | PRFileDesc *sockfd; |
michael@0 | 503 | buffer *in_buf; |
michael@0 | 504 | PRNetAddr netaddr; |
michael@0 | 505 | PRInt32 bytes, i, rv = 0; |
michael@0 | 506 | |
michael@0 | 507 | |
michael@0 | 508 | bytes = sp->datalen; |
michael@0 | 509 | /* |
michael@0 | 510 | * Create a udp socket |
michael@0 | 511 | */ |
michael@0 | 512 | if ((sockfd = PR_OpenUDPSocket(server_domain)) == NULL) { |
michael@0 | 513 | fprintf(stderr,"prsocket_test: PR_NewUDPSocket failed\n"); |
michael@0 | 514 | failed_already=1; |
michael@0 | 515 | return; |
michael@0 | 516 | } |
michael@0 | 517 | memset(&netaddr, 0 , sizeof(netaddr)); |
michael@0 | 518 | if (PR_SetNetAddr(PR_IpAddrAny, server_domain, UDP_SERVER_PORT, |
michael@0 | 519 | &netaddr) == PR_FAILURE) { |
michael@0 | 520 | fprintf(stderr,"prsocket_test: PR_SetNetAddr failed\n"); |
michael@0 | 521 | failed_already=1; |
michael@0 | 522 | return; |
michael@0 | 523 | } |
michael@0 | 524 | /* |
michael@0 | 525 | * try a few times to bind server's address, if addresses are in |
michael@0 | 526 | * use |
michael@0 | 527 | */ |
michael@0 | 528 | i = 0; |
michael@0 | 529 | while (PR_Bind(sockfd, &netaddr) < 0) { |
michael@0 | 530 | if (PR_GetError() == PR_ADDRESS_IN_USE_ERROR) { |
michael@0 | 531 | netaddr.inet.port += 2; |
michael@0 | 532 | if (i++ < SERVER_MAX_BIND_COUNT) |
michael@0 | 533 | continue; |
michael@0 | 534 | } |
michael@0 | 535 | fprintf(stderr,"prsocket_test: ERROR - PR_Bind failed\n"); |
michael@0 | 536 | perror("PR_Bind"); |
michael@0 | 537 | failed_already=1; |
michael@0 | 538 | return; |
michael@0 | 539 | } |
michael@0 | 540 | |
michael@0 | 541 | if (PR_GetSockName(sockfd, &netaddr) < 0) { |
michael@0 | 542 | fprintf(stderr,"prsocket_test: ERROR - PR_GetSockName failed\n"); |
michael@0 | 543 | failed_already=1; |
michael@0 | 544 | return; |
michael@0 | 545 | } |
michael@0 | 546 | |
michael@0 | 547 | DPRINTF(("PR_Bind: UDP Server netaddr.inet.ip = 0x%lx, netaddr.inet.port = %d\n", |
michael@0 | 548 | netaddr.inet.ip, netaddr.inet.port)); |
michael@0 | 549 | /* |
michael@0 | 550 | * We can't use the IP address returned by PR_GetSockName in |
michael@0 | 551 | * netaddr.inet.ip because netaddr.inet.ip is returned |
michael@0 | 552 | * as 0 (= PR_INADDR_ANY). |
michael@0 | 553 | */ |
michael@0 | 554 | |
michael@0 | 555 | if (PR_SetNetAddr(PR_IpAddrLoopback, client_domain, |
michael@0 | 556 | PR_ntohs(PR_NetAddrInetPort(&netaddr)), |
michael@0 | 557 | &udp_server_addr) == PR_FAILURE) { |
michael@0 | 558 | fprintf(stderr,"prsocket_test: PR_SetNetAddr failed\n"); |
michael@0 | 559 | failed_already=1; |
michael@0 | 560 | return; |
michael@0 | 561 | } |
michael@0 | 562 | if ((client_domain == PR_AF_INET6) && (server_domain == PR_AF_INET)) |
michael@0 | 563 | PR_ConvertIPv4AddrToIPv6(PR_htonl(INADDR_LOOPBACK), |
michael@0 | 564 | &udp_server_addr.ipv6.ip); |
michael@0 | 565 | |
michael@0 | 566 | /* |
michael@0 | 567 | * Wake up parent thread because server address is bound and made |
michael@0 | 568 | * available in the global variable 'udp_server_addr' |
michael@0 | 569 | */ |
michael@0 | 570 | PR_PostSem(sp->addr_sem); |
michael@0 | 571 | |
michael@0 | 572 | bytes = sp->datalen; |
michael@0 | 573 | in_buf = PR_NEW(buffer); |
michael@0 | 574 | if (in_buf == NULL) { |
michael@0 | 575 | fprintf(stderr,"prsocket_test: failed to alloc buffer struct\n"); |
michael@0 | 576 | failed_already=1; |
michael@0 | 577 | return; |
michael@0 | 578 | } |
michael@0 | 579 | /* |
michael@0 | 580 | * Receive datagrams from clients and send them back, unmodified, to the |
michael@0 | 581 | * clients |
michael@0 | 582 | */ |
michael@0 | 583 | memset(&netaddr, 0 , sizeof(netaddr)); |
michael@0 | 584 | for (i = 0; i < (num_udp_clients * num_udp_datagrams_per_client); i++) { |
michael@0 | 585 | DPRINTF(("UDP_Server: calling PR_RecvFrom client - ip = 0x%lx, port = %d bytes = %d inbuf = 0x%lx, inbuf[0] = 0x%lx\n", |
michael@0 | 586 | netaddr.inet.ip, netaddr.inet.port, bytes, in_buf->data, |
michael@0 | 587 | in_buf->data[0])); |
michael@0 | 588 | |
michael@0 | 589 | rv = PR_RecvFrom(sockfd, in_buf->data, bytes, 0, &netaddr, |
michael@0 | 590 | PR_INTERVAL_NO_TIMEOUT); |
michael@0 | 591 | DPRINTF(("UDP_Server: PR_RecvFrom client - ip = 0x%lx, port = %d bytes = %d inbuf = 0x%lx, inbuf[0] = 0x%lx\n", |
michael@0 | 592 | netaddr.inet.ip, netaddr.inet.port, rv, in_buf->data, |
michael@0 | 593 | in_buf->data[0])); |
michael@0 | 594 | if (rv != bytes) { |
michael@0 | 595 | return; |
michael@0 | 596 | } |
michael@0 | 597 | rv = PR_SendTo(sockfd, in_buf->data, bytes, 0, &netaddr, |
michael@0 | 598 | PR_INTERVAL_NO_TIMEOUT); |
michael@0 | 599 | if (rv != bytes) { |
michael@0 | 600 | return; |
michael@0 | 601 | } |
michael@0 | 602 | } |
michael@0 | 603 | |
michael@0 | 604 | PR_DELETE(in_buf); |
michael@0 | 605 | PR_Close(sockfd); |
michael@0 | 606 | |
michael@0 | 607 | /* |
michael@0 | 608 | * Decrement exit_counter and notify parent thread |
michael@0 | 609 | */ |
michael@0 | 610 | PR_EnterMonitor(sp->exit_mon); |
michael@0 | 611 | --(*sp->exit_counter); |
michael@0 | 612 | PR_Notify(sp->exit_mon); |
michael@0 | 613 | PR_ExitMonitor(sp->exit_mon); |
michael@0 | 614 | DPRINTF(("UDP_Server [0x%x] exiting\n", PR_GetCurrentThread())); |
michael@0 | 615 | } |
michael@0 | 616 | |
michael@0 | 617 | /* |
michael@0 | 618 | * TCP_Client |
michael@0 | 619 | * Client Thread |
michael@0 | 620 | * Connect to the server at the address specified in the argument. |
michael@0 | 621 | * Fill in a buffer, write data to server, read it back and check |
michael@0 | 622 | * for data corruption. |
michael@0 | 623 | * Close the socket for server connection |
michael@0 | 624 | */ |
michael@0 | 625 | static void PR_CALLBACK |
michael@0 | 626 | TCP_Client(void *arg) |
michael@0 | 627 | { |
michael@0 | 628 | Client_Param *cp = (Client_Param *) arg; |
michael@0 | 629 | PRFileDesc *sockfd; |
michael@0 | 630 | buffer *in_buf, *out_buf; |
michael@0 | 631 | union PRNetAddr netaddr; |
michael@0 | 632 | PRInt32 bytes, i, j; |
michael@0 | 633 | |
michael@0 | 634 | |
michael@0 | 635 | bytes = cp->datalen; |
michael@0 | 636 | out_buf = PR_NEW(buffer); |
michael@0 | 637 | if (out_buf == NULL) { |
michael@0 | 638 | fprintf(stderr,"prsocket_test: failed to alloc buffer struct\n"); |
michael@0 | 639 | failed_already=1; |
michael@0 | 640 | return; |
michael@0 | 641 | } |
michael@0 | 642 | in_buf = PR_NEW(buffer); |
michael@0 | 643 | if (in_buf == NULL) { |
michael@0 | 644 | fprintf(stderr,"prsocket_test: failed to alloc buffer struct\n"); |
michael@0 | 645 | failed_already=1; |
michael@0 | 646 | return; |
michael@0 | 647 | } |
michael@0 | 648 | netaddr = cp->server_addr; |
michael@0 | 649 | |
michael@0 | 650 | for (i = 0; i < num_tcp_connections_per_client; i++) { |
michael@0 | 651 | if ((sockfd = PR_OpenTCPSocket(client_domain)) == NULL) { |
michael@0 | 652 | fprintf(stderr,"prsocket_test: PR_OpenTCPSocket failed\n"); |
michael@0 | 653 | failed_already=1; |
michael@0 | 654 | return; |
michael@0 | 655 | } |
michael@0 | 656 | if (PR_Connect(sockfd, &netaddr,PR_INTERVAL_NO_TIMEOUT) < 0){ |
michael@0 | 657 | fprintf(stderr, "PR_Connect failed: (%ld, %ld)\n", |
michael@0 | 658 | PR_GetError(), PR_GetOSError()); |
michael@0 | 659 | failed_already=1; |
michael@0 | 660 | return; |
michael@0 | 661 | } |
michael@0 | 662 | for (j = 0; j < num_tcp_mesgs_per_connection; j++) { |
michael@0 | 663 | /* |
michael@0 | 664 | * fill in random data |
michael@0 | 665 | */ |
michael@0 | 666 | memset(out_buf->data, ((PRInt32) (&netaddr)) + i + j, bytes); |
michael@0 | 667 | /* |
michael@0 | 668 | * write to server |
michael@0 | 669 | */ |
michael@0 | 670 | #ifdef WINNT |
michael@0 | 671 | if (test_cancelio && (j == 0)) |
michael@0 | 672 | PR_Sleep(PR_SecondsToInterval(12)); |
michael@0 | 673 | #endif |
michael@0 | 674 | if (writen(sockfd, out_buf->data, bytes) < bytes) { |
michael@0 | 675 | fprintf(stderr,"prsocket_test: ERROR - TCP_Client:writen\n"); |
michael@0 | 676 | failed_already=1; |
michael@0 | 677 | return; |
michael@0 | 678 | } |
michael@0 | 679 | DPRINTF(("TCP Client [0x%lx]: out_buf = 0x%lx out_buf[0] = 0x%lx\n", |
michael@0 | 680 | PR_GetCurrentThread(), out_buf, (*((int *) out_buf->data)))); |
michael@0 | 681 | if (readn(sockfd, in_buf->data, bytes) < bytes) { |
michael@0 | 682 | fprintf(stderr,"prsocket_test: ERROR - TCP_Client:readn\n"); |
michael@0 | 683 | failed_already=1; |
michael@0 | 684 | return; |
michael@0 | 685 | } |
michael@0 | 686 | /* |
michael@0 | 687 | * verify the data read |
michael@0 | 688 | */ |
michael@0 | 689 | if (memcmp(in_buf->data, out_buf->data, bytes) != 0) { |
michael@0 | 690 | fprintf(stderr,"prsocket_test: ERROR - data corruption\n"); |
michael@0 | 691 | failed_already=1; |
michael@0 | 692 | return; |
michael@0 | 693 | } |
michael@0 | 694 | } |
michael@0 | 695 | /* |
michael@0 | 696 | * shutdown reads and writes |
michael@0 | 697 | */ |
michael@0 | 698 | if (PR_Shutdown(sockfd, PR_SHUTDOWN_BOTH) < 0) { |
michael@0 | 699 | fprintf(stderr,"prsocket_test: ERROR - PR_Shutdown\n"); |
michael@0 | 700 | #if defined(SYMBIAN) |
michael@0 | 701 | if (EPIPE != errno) |
michael@0 | 702 | #endif |
michael@0 | 703 | failed_already=1; |
michael@0 | 704 | } |
michael@0 | 705 | PR_Close(sockfd); |
michael@0 | 706 | } |
michael@0 | 707 | |
michael@0 | 708 | PR_DELETE(out_buf); |
michael@0 | 709 | PR_DELETE(in_buf); |
michael@0 | 710 | |
michael@0 | 711 | /* |
michael@0 | 712 | * Decrement exit_counter and notify parent thread |
michael@0 | 713 | */ |
michael@0 | 714 | |
michael@0 | 715 | PR_EnterMonitor(cp->exit_mon); |
michael@0 | 716 | --(*cp->exit_counter); |
michael@0 | 717 | PR_Notify(cp->exit_mon); |
michael@0 | 718 | PR_ExitMonitor(cp->exit_mon); |
michael@0 | 719 | DPRINTF(("TCP_Client [0x%x] exiting\n", PR_GetCurrentThread())); |
michael@0 | 720 | } |
michael@0 | 721 | |
michael@0 | 722 | /* |
michael@0 | 723 | * UDP_Client |
michael@0 | 724 | * Client Thread |
michael@0 | 725 | * Create a socket and bind an address |
michael@0 | 726 | * Communicate with the server at the address specified in the argument. |
michael@0 | 727 | * Fill in a buffer, write data to server, read it back and check |
michael@0 | 728 | * for data corruption. |
michael@0 | 729 | * Close the socket |
michael@0 | 730 | */ |
michael@0 | 731 | static void PR_CALLBACK |
michael@0 | 732 | UDP_Client(void *arg) |
michael@0 | 733 | { |
michael@0 | 734 | Client_Param *cp = (Client_Param *) arg; |
michael@0 | 735 | PRFileDesc *sockfd; |
michael@0 | 736 | buffer *in_buf, *out_buf; |
michael@0 | 737 | union PRNetAddr netaddr; |
michael@0 | 738 | PRInt32 bytes, i, rv; |
michael@0 | 739 | |
michael@0 | 740 | |
michael@0 | 741 | bytes = cp->datalen; |
michael@0 | 742 | out_buf = PR_NEW(buffer); |
michael@0 | 743 | if (out_buf == NULL) { |
michael@0 | 744 | fprintf(stderr,"prsocket_test: failed to alloc buffer struct\n"); |
michael@0 | 745 | failed_already=1; |
michael@0 | 746 | return; |
michael@0 | 747 | } |
michael@0 | 748 | in_buf = PR_NEW(buffer); |
michael@0 | 749 | if (in_buf == NULL) { |
michael@0 | 750 | fprintf(stderr,"prsocket_test: failed to alloc buffer struct\n"); |
michael@0 | 751 | failed_already=1; |
michael@0 | 752 | return; |
michael@0 | 753 | } |
michael@0 | 754 | if ((sockfd = PR_OpenUDPSocket(client_domain)) == NULL) { |
michael@0 | 755 | fprintf(stderr,"prsocket_test: PR_OpenUDPSocket failed\n"); |
michael@0 | 756 | failed_already=1; |
michael@0 | 757 | return; |
michael@0 | 758 | } |
michael@0 | 759 | |
michael@0 | 760 | /* |
michael@0 | 761 | * bind an address for the client, let the system chose the port |
michael@0 | 762 | * number |
michael@0 | 763 | */ |
michael@0 | 764 | memset(&netaddr, 0 , sizeof(netaddr)); |
michael@0 | 765 | if (PR_SetNetAddr(PR_IpAddrAny, client_domain, 0, |
michael@0 | 766 | &netaddr) == PR_FAILURE) { |
michael@0 | 767 | fprintf(stderr,"prsocket_test: PR_SetNetAddr failed\n"); |
michael@0 | 768 | failed_already=1; |
michael@0 | 769 | return; |
michael@0 | 770 | } |
michael@0 | 771 | if (PR_Bind(sockfd, &netaddr) < 0) { |
michael@0 | 772 | fprintf(stderr,"prsocket_test: ERROR - PR_Bind failed\n"); |
michael@0 | 773 | perror("PR_Bind"); |
michael@0 | 774 | return; |
michael@0 | 775 | } |
michael@0 | 776 | |
michael@0 | 777 | if (PR_GetSockName(sockfd, &netaddr) < 0) { |
michael@0 | 778 | fprintf(stderr,"prsocket_test: ERROR - PR_GetSockName failed\n"); |
michael@0 | 779 | failed_already=1; |
michael@0 | 780 | return; |
michael@0 | 781 | } |
michael@0 | 782 | |
michael@0 | 783 | DPRINTF(("PR_Bind: UDP Client netaddr.inet.ip = 0x%lx, netaddr.inet.port = %d\n", |
michael@0 | 784 | netaddr.inet.ip, netaddr.inet.port)); |
michael@0 | 785 | |
michael@0 | 786 | netaddr = cp->server_addr; |
michael@0 | 787 | |
michael@0 | 788 | if (cp->udp_connect) { |
michael@0 | 789 | if (PR_Connect(sockfd, &netaddr,PR_INTERVAL_NO_TIMEOUT) < 0){ |
michael@0 | 790 | fprintf(stderr,"prsocket_test: PR_Connect failed\n"); |
michael@0 | 791 | failed_already=1; |
michael@0 | 792 | return; |
michael@0 | 793 | } |
michael@0 | 794 | } |
michael@0 | 795 | |
michael@0 | 796 | for (i = 0; i < num_udp_datagrams_per_client; i++) { |
michael@0 | 797 | /* |
michael@0 | 798 | * fill in random data |
michael@0 | 799 | */ |
michael@0 | 800 | DPRINTF(("UDP_Client [0x%lx]: out_buf = 0x%lx bytes = 0x%lx\n", |
michael@0 | 801 | PR_GetCurrentThread(), out_buf->data, bytes)); |
michael@0 | 802 | memset(out_buf->data, ((PRInt32) (&netaddr)) + i, bytes); |
michael@0 | 803 | /* |
michael@0 | 804 | * write to server |
michael@0 | 805 | */ |
michael@0 | 806 | if (cp->udp_connect) |
michael@0 | 807 | rv = PR_Send(sockfd, out_buf->data, bytes, 0, |
michael@0 | 808 | PR_INTERVAL_NO_TIMEOUT); |
michael@0 | 809 | else |
michael@0 | 810 | rv = PR_SendTo(sockfd, out_buf->data, bytes, 0, &netaddr, |
michael@0 | 811 | PR_INTERVAL_NO_TIMEOUT); |
michael@0 | 812 | if (rv != bytes) { |
michael@0 | 813 | return; |
michael@0 | 814 | } |
michael@0 | 815 | DPRINTF(("UDP_Client [0x%lx]: out_buf = 0x%lx out_buf[0] = 0x%lx\n", |
michael@0 | 816 | PR_GetCurrentThread(), out_buf, (*((int *) out_buf->data)))); |
michael@0 | 817 | if (cp->udp_connect) |
michael@0 | 818 | rv = PR_Recv(sockfd, in_buf->data, bytes, 0, |
michael@0 | 819 | PR_INTERVAL_NO_TIMEOUT); |
michael@0 | 820 | else |
michael@0 | 821 | rv = PR_RecvFrom(sockfd, in_buf->data, bytes, 0, &netaddr, |
michael@0 | 822 | PR_INTERVAL_NO_TIMEOUT); |
michael@0 | 823 | if (rv != bytes) { |
michael@0 | 824 | return; |
michael@0 | 825 | } |
michael@0 | 826 | DPRINTF(("UDP_Client [0x%lx]: in_buf = 0x%lx in_buf[0] = 0x%lx\n", |
michael@0 | 827 | PR_GetCurrentThread(), in_buf, (*((int *) in_buf->data)))); |
michael@0 | 828 | /* |
michael@0 | 829 | * verify the data read |
michael@0 | 830 | */ |
michael@0 | 831 | if (memcmp(in_buf->data, out_buf->data, bytes) != 0) { |
michael@0 | 832 | fprintf(stderr,"prsocket_test: ERROR - UDP data corruption\n"); |
michael@0 | 833 | failed_already=1; |
michael@0 | 834 | return; |
michael@0 | 835 | } |
michael@0 | 836 | } |
michael@0 | 837 | PR_Close(sockfd); |
michael@0 | 838 | |
michael@0 | 839 | PR_DELETE(in_buf); |
michael@0 | 840 | PR_DELETE(out_buf); |
michael@0 | 841 | |
michael@0 | 842 | /* |
michael@0 | 843 | * Decrement exit_counter and notify parent thread |
michael@0 | 844 | */ |
michael@0 | 845 | |
michael@0 | 846 | PR_EnterMonitor(cp->exit_mon); |
michael@0 | 847 | --(*cp->exit_counter); |
michael@0 | 848 | PR_Notify(cp->exit_mon); |
michael@0 | 849 | PR_ExitMonitor(cp->exit_mon); |
michael@0 | 850 | PR_DELETE(cp); |
michael@0 | 851 | DPRINTF(("UDP_Client [0x%x] exiting\n", PR_GetCurrentThread())); |
michael@0 | 852 | } |
michael@0 | 853 | |
michael@0 | 854 | /* |
michael@0 | 855 | * TCP_Socket_Client_Server_Test - concurrent server test |
michael@0 | 856 | * |
michael@0 | 857 | * One server and several clients are started |
michael@0 | 858 | * Each client connects to the server and sends a chunk of data |
michael@0 | 859 | * For each connection, server starts another thread to read the data |
michael@0 | 860 | * from the client and send it back to the client, unmodified. |
michael@0 | 861 | * Each client checks that data received from server is same as the |
michael@0 | 862 | * data it sent to the server. |
michael@0 | 863 | * |
michael@0 | 864 | */ |
michael@0 | 865 | |
michael@0 | 866 | static PRInt32 |
michael@0 | 867 | TCP_Socket_Client_Server_Test(void) |
michael@0 | 868 | { |
michael@0 | 869 | int i; |
michael@0 | 870 | PRThread *t; |
michael@0 | 871 | PRSemaphore *server_sem; |
michael@0 | 872 | Server_Param *sparamp; |
michael@0 | 873 | Client_Param *cparamp; |
michael@0 | 874 | PRMonitor *mon2; |
michael@0 | 875 | PRInt32 datalen; |
michael@0 | 876 | |
michael@0 | 877 | |
michael@0 | 878 | datalen = tcp_mesg_size; |
michael@0 | 879 | thread_count = 0; |
michael@0 | 880 | /* |
michael@0 | 881 | * start the server thread |
michael@0 | 882 | */ |
michael@0 | 883 | sparamp = PR_NEW(Server_Param); |
michael@0 | 884 | if (sparamp == NULL) { |
michael@0 | 885 | fprintf(stderr,"prsocket_test: PR_NEW failed\n"); |
michael@0 | 886 | failed_already=1; |
michael@0 | 887 | return -1; |
michael@0 | 888 | } |
michael@0 | 889 | server_sem = PR_NewSem(0); |
michael@0 | 890 | if (server_sem == NULL) { |
michael@0 | 891 | fprintf(stderr,"prsocket_test: PR_NewSem failed\n"); |
michael@0 | 892 | failed_already=1; |
michael@0 | 893 | return -1; |
michael@0 | 894 | } |
michael@0 | 895 | mon2 = PR_NewMonitor(); |
michael@0 | 896 | if (mon2 == NULL) { |
michael@0 | 897 | fprintf(stderr,"prsocket_test: PR_NewMonitor failed\n"); |
michael@0 | 898 | failed_already=1; |
michael@0 | 899 | return -1; |
michael@0 | 900 | } |
michael@0 | 901 | PR_EnterMonitor(mon2); |
michael@0 | 902 | |
michael@0 | 903 | sparamp->addr_sem = server_sem; |
michael@0 | 904 | sparamp->exit_mon = mon2; |
michael@0 | 905 | sparamp->exit_counter = &thread_count; |
michael@0 | 906 | sparamp->datalen = datalen; |
michael@0 | 907 | t = PR_CreateThread(PR_USER_THREAD, |
michael@0 | 908 | TCP_Server, (void *)sparamp, |
michael@0 | 909 | PR_PRIORITY_NORMAL, |
michael@0 | 910 | PR_LOCAL_THREAD, |
michael@0 | 911 | PR_UNJOINABLE_THREAD, |
michael@0 | 912 | 0); |
michael@0 | 913 | if (t == NULL) { |
michael@0 | 914 | fprintf(stderr,"prsocket_test: PR_CreateThread failed\n"); |
michael@0 | 915 | failed_already=1; |
michael@0 | 916 | return -1; |
michael@0 | 917 | } |
michael@0 | 918 | DPRINTF(("Created TCP server = 0x%lx\n", t)); |
michael@0 | 919 | thread_count++; |
michael@0 | 920 | |
michael@0 | 921 | /* |
michael@0 | 922 | * wait till the server address is setup |
michael@0 | 923 | */ |
michael@0 | 924 | PR_WaitSem(server_sem); |
michael@0 | 925 | |
michael@0 | 926 | /* |
michael@0 | 927 | * Now start a bunch of client threads |
michael@0 | 928 | */ |
michael@0 | 929 | |
michael@0 | 930 | cparamp = PR_NEW(Client_Param); |
michael@0 | 931 | if (cparamp == NULL) { |
michael@0 | 932 | fprintf(stderr,"prsocket_test: PR_NEW failed\n"); |
michael@0 | 933 | failed_already=1; |
michael@0 | 934 | return -1; |
michael@0 | 935 | } |
michael@0 | 936 | cparamp->server_addr = tcp_server_addr; |
michael@0 | 937 | cparamp->exit_mon = mon2; |
michael@0 | 938 | cparamp->exit_counter = &thread_count; |
michael@0 | 939 | cparamp->datalen = datalen; |
michael@0 | 940 | for (i = 0; i < num_tcp_clients; i++) { |
michael@0 | 941 | t = create_new_thread(PR_USER_THREAD, |
michael@0 | 942 | TCP_Client, (void *) cparamp, |
michael@0 | 943 | PR_PRIORITY_NORMAL, |
michael@0 | 944 | PR_LOCAL_THREAD, |
michael@0 | 945 | PR_UNJOINABLE_THREAD, |
michael@0 | 946 | 0, i); |
michael@0 | 947 | if (t == NULL) { |
michael@0 | 948 | fprintf(stderr,"prsocket_test: PR_CreateThread failed\n"); |
michael@0 | 949 | failed_already=1; |
michael@0 | 950 | return -1; |
michael@0 | 951 | } |
michael@0 | 952 | DPRINTF(("Created TCP client = 0x%lx\n", t)); |
michael@0 | 953 | thread_count++; |
michael@0 | 954 | } |
michael@0 | 955 | /* Wait for server and client threads to exit */ |
michael@0 | 956 | while (thread_count) { |
michael@0 | 957 | PR_Wait(mon2, PR_INTERVAL_NO_TIMEOUT); |
michael@0 | 958 | DPRINTF(("TCP Server - thread_count = %d\n", thread_count)); |
michael@0 | 959 | } |
michael@0 | 960 | PR_ExitMonitor(mon2); |
michael@0 | 961 | printf("%30s","TCP_Socket_Client_Server_Test:"); |
michael@0 | 962 | printf("%2ld Server %2ld Clients %2ld connections_per_client\n",1l, |
michael@0 | 963 | num_tcp_clients, num_tcp_connections_per_client); |
michael@0 | 964 | printf("%30s %2ld messages_per_connection %4ld bytes_per_message\n",":", |
michael@0 | 965 | num_tcp_mesgs_per_connection, tcp_mesg_size); |
michael@0 | 966 | |
michael@0 | 967 | return 0; |
michael@0 | 968 | } |
michael@0 | 969 | |
michael@0 | 970 | /* |
michael@0 | 971 | * UDP_Socket_Client_Server_Test - iterative server test |
michael@0 | 972 | * |
michael@0 | 973 | * One server and several clients are started |
michael@0 | 974 | * Each client connects to the server and sends a chunk of data |
michael@0 | 975 | * For each connection, server starts another thread to read the data |
michael@0 | 976 | * from the client and send it back to the client, unmodified. |
michael@0 | 977 | * Each client checks that data received from server is same as the |
michael@0 | 978 | * data it sent to the server. |
michael@0 | 979 | * |
michael@0 | 980 | */ |
michael@0 | 981 | |
michael@0 | 982 | static PRInt32 |
michael@0 | 983 | UDP_Socket_Client_Server_Test(void) |
michael@0 | 984 | { |
michael@0 | 985 | int i; |
michael@0 | 986 | PRThread *t; |
michael@0 | 987 | PRSemaphore *server_sem; |
michael@0 | 988 | Server_Param *sparamp; |
michael@0 | 989 | Client_Param *cparamp; |
michael@0 | 990 | PRMonitor *mon2; |
michael@0 | 991 | PRInt32 datalen; |
michael@0 | 992 | PRInt32 udp_connect = 1; |
michael@0 | 993 | |
michael@0 | 994 | |
michael@0 | 995 | datalen = udp_datagram_size; |
michael@0 | 996 | thread_count = 0; |
michael@0 | 997 | /* |
michael@0 | 998 | * start the server thread |
michael@0 | 999 | */ |
michael@0 | 1000 | sparamp = PR_NEW(Server_Param); |
michael@0 | 1001 | if (sparamp == NULL) { |
michael@0 | 1002 | fprintf(stderr,"prsocket_test: PR_NEW failed\n"); |
michael@0 | 1003 | failed_already=1; |
michael@0 | 1004 | return -1; |
michael@0 | 1005 | } |
michael@0 | 1006 | server_sem = PR_NewSem(0); |
michael@0 | 1007 | if (server_sem == NULL) { |
michael@0 | 1008 | fprintf(stderr,"prsocket_test: PR_NewSem failed\n"); |
michael@0 | 1009 | failed_already=1; |
michael@0 | 1010 | return -1; |
michael@0 | 1011 | } |
michael@0 | 1012 | mon2 = PR_NewMonitor(); |
michael@0 | 1013 | if (mon2 == NULL) { |
michael@0 | 1014 | fprintf(stderr,"prsocket_test: PR_NewMonitor failed\n"); |
michael@0 | 1015 | failed_already=1; |
michael@0 | 1016 | return -1; |
michael@0 | 1017 | } |
michael@0 | 1018 | PR_EnterMonitor(mon2); |
michael@0 | 1019 | |
michael@0 | 1020 | sparamp->addr_sem = server_sem; |
michael@0 | 1021 | sparamp->exit_mon = mon2; |
michael@0 | 1022 | sparamp->exit_counter = &thread_count; |
michael@0 | 1023 | sparamp->datalen = datalen; |
michael@0 | 1024 | DPRINTF(("Creating UDP server")); |
michael@0 | 1025 | t = PR_CreateThread(PR_USER_THREAD, |
michael@0 | 1026 | UDP_Server, (void *)sparamp, |
michael@0 | 1027 | PR_PRIORITY_NORMAL, |
michael@0 | 1028 | PR_LOCAL_THREAD, |
michael@0 | 1029 | PR_UNJOINABLE_THREAD, |
michael@0 | 1030 | 0); |
michael@0 | 1031 | if (t == NULL) { |
michael@0 | 1032 | fprintf(stderr,"prsocket_test: PR_CreateThread failed\n"); |
michael@0 | 1033 | failed_already=1; |
michael@0 | 1034 | return -1; |
michael@0 | 1035 | } |
michael@0 | 1036 | thread_count++; |
michael@0 | 1037 | |
michael@0 | 1038 | /* |
michael@0 | 1039 | * wait till the server address is setup |
michael@0 | 1040 | */ |
michael@0 | 1041 | PR_WaitSem(server_sem); |
michael@0 | 1042 | |
michael@0 | 1043 | /* |
michael@0 | 1044 | * Now start a bunch of client threads |
michael@0 | 1045 | */ |
michael@0 | 1046 | |
michael@0 | 1047 | for (i = 0; i < num_udp_clients; i++) { |
michael@0 | 1048 | cparamp = PR_NEW(Client_Param); |
michael@0 | 1049 | if (cparamp == NULL) { |
michael@0 | 1050 | fprintf(stderr,"prsocket_test: PR_NEW failed\n"); |
michael@0 | 1051 | failed_already=1; |
michael@0 | 1052 | return -1; |
michael@0 | 1053 | } |
michael@0 | 1054 | cparamp->server_addr = udp_server_addr; |
michael@0 | 1055 | cparamp->exit_mon = mon2; |
michael@0 | 1056 | cparamp->exit_counter = &thread_count; |
michael@0 | 1057 | cparamp->datalen = datalen; |
michael@0 | 1058 | /* |
michael@0 | 1059 | * Cause every other client thread to connect udp sockets |
michael@0 | 1060 | */ |
michael@0 | 1061 | cparamp->udp_connect = udp_connect; |
michael@0 | 1062 | if (udp_connect) |
michael@0 | 1063 | udp_connect = 0; |
michael@0 | 1064 | else |
michael@0 | 1065 | udp_connect = 1; |
michael@0 | 1066 | DPRINTF(("Creating UDP client %d\n", i)); |
michael@0 | 1067 | t = PR_CreateThread(PR_USER_THREAD, |
michael@0 | 1068 | UDP_Client, (void *) cparamp, |
michael@0 | 1069 | PR_PRIORITY_NORMAL, |
michael@0 | 1070 | PR_LOCAL_THREAD, |
michael@0 | 1071 | PR_UNJOINABLE_THREAD, |
michael@0 | 1072 | 0); |
michael@0 | 1073 | if (t == NULL) { |
michael@0 | 1074 | fprintf(stderr,"prsocket_test: PR_CreateThread failed\n"); |
michael@0 | 1075 | failed_already=1; |
michael@0 | 1076 | return -1; |
michael@0 | 1077 | } |
michael@0 | 1078 | thread_count++; |
michael@0 | 1079 | } |
michael@0 | 1080 | /* Wait for server and client threads to exit */ |
michael@0 | 1081 | while (thread_count) { |
michael@0 | 1082 | PR_Wait(mon2, PR_INTERVAL_NO_TIMEOUT); |
michael@0 | 1083 | DPRINTF(("UDP Server - thread_count = %d\n", thread_count)); |
michael@0 | 1084 | } |
michael@0 | 1085 | PR_ExitMonitor(mon2); |
michael@0 | 1086 | printf("%30s","UDP_Socket_Client_Server_Test: "); |
michael@0 | 1087 | printf("%2ld Server %2ld Clients\n",1l, num_udp_clients); |
michael@0 | 1088 | printf("%30s %2ld datagrams_per_client %4ld bytes_per_datagram\n",":", |
michael@0 | 1089 | num_udp_datagrams_per_client, udp_datagram_size); |
michael@0 | 1090 | |
michael@0 | 1091 | return 0; |
michael@0 | 1092 | } |
michael@0 | 1093 | |
michael@0 | 1094 | static PRFileDesc *small_file_fd, *large_file_fd; |
michael@0 | 1095 | static void *small_file_addr, *small_file_header, *large_file_addr; |
michael@0 | 1096 | static void *small_file_trailer, *large_file_header, *large_file_trailer; |
michael@0 | 1097 | /* |
michael@0 | 1098 | * TransmitFile_Client |
michael@0 | 1099 | * Client Thread |
michael@0 | 1100 | */ |
michael@0 | 1101 | static void |
michael@0 | 1102 | TransmitFile_Client(void *arg) |
michael@0 | 1103 | { |
michael@0 | 1104 | PRFileDesc *sockfd; |
michael@0 | 1105 | union PRNetAddr netaddr; |
michael@0 | 1106 | char *small_buf, *large_buf; |
michael@0 | 1107 | Client_Param *cp = (Client_Param *) arg; |
michael@0 | 1108 | PRInt32 rlen; |
michael@0 | 1109 | |
michael@0 | 1110 | small_buf = (char*)PR_Malloc(SMALL_FILE_SIZE + SMALL_FILE_HEADER_SIZE + |
michael@0 | 1111 | SMALL_FILE_TRAILER_SIZE); |
michael@0 | 1112 | if (small_buf == NULL) { |
michael@0 | 1113 | fprintf(stderr,"prsocket_test: failed to alloc buffer\n"); |
michael@0 | 1114 | failed_already=1; |
michael@0 | 1115 | return; |
michael@0 | 1116 | } |
michael@0 | 1117 | large_buf = (char*)PR_Malloc(LARGE_FILE_SIZE + LARGE_FILE_HEADER_SIZE + |
michael@0 | 1118 | LARGE_FILE_TRAILER_SIZE); |
michael@0 | 1119 | if (large_buf == NULL) { |
michael@0 | 1120 | fprintf(stderr,"prsocket_test: failed to alloc buffer\n"); |
michael@0 | 1121 | failed_already=1; |
michael@0 | 1122 | return; |
michael@0 | 1123 | } |
michael@0 | 1124 | netaddr.inet.family = cp->server_addr.inet.family; |
michael@0 | 1125 | netaddr.inet.port = cp->server_addr.inet.port; |
michael@0 | 1126 | netaddr.inet.ip = cp->server_addr.inet.ip; |
michael@0 | 1127 | |
michael@0 | 1128 | if ((sockfd = PR_NewTCPSocket()) == NULL) { |
michael@0 | 1129 | fprintf(stderr,"prsocket_test: PR_NewTCPSocket failed\n"); |
michael@0 | 1130 | failed_already=1; |
michael@0 | 1131 | return; |
michael@0 | 1132 | } |
michael@0 | 1133 | |
michael@0 | 1134 | if (PR_Connect(sockfd, &netaddr,PR_INTERVAL_NO_TIMEOUT) < 0){ |
michael@0 | 1135 | fprintf(stderr,"prsocket_test: PR_Connect failed\n"); |
michael@0 | 1136 | failed_already=1; |
michael@0 | 1137 | return; |
michael@0 | 1138 | } |
michael@0 | 1139 | /* |
michael@0 | 1140 | * read the small file and verify the data |
michael@0 | 1141 | */ |
michael@0 | 1142 | if (readn(sockfd, small_buf, SMALL_FILE_SIZE + SMALL_FILE_HEADER_SIZE) |
michael@0 | 1143 | != (SMALL_FILE_SIZE + SMALL_FILE_HEADER_SIZE)) { |
michael@0 | 1144 | fprintf(stderr, |
michael@0 | 1145 | "prsocket_test: TransmitFile_Client failed to receive file\n"); |
michael@0 | 1146 | failed_already=1; |
michael@0 | 1147 | return; |
michael@0 | 1148 | } |
michael@0 | 1149 | #if defined(XP_UNIX) && !defined(SYMBIAN) |
michael@0 | 1150 | /* File transmission test can not be done because of large file's size */ |
michael@0 | 1151 | if (memcmp(small_file_header, small_buf, SMALL_FILE_HEADER_SIZE) != 0){ |
michael@0 | 1152 | fprintf(stderr, |
michael@0 | 1153 | "prsocket_test: TransmitFile_Client ERROR - small file header data corruption\n"); |
michael@0 | 1154 | failed_already=1; |
michael@0 | 1155 | return; |
michael@0 | 1156 | } |
michael@0 | 1157 | if (memcmp(small_file_addr, small_buf + SMALL_FILE_HEADER_SIZE, |
michael@0 | 1158 | SMALL_FILE_SIZE) != 0) { |
michael@0 | 1159 | fprintf(stderr, |
michael@0 | 1160 | "prsocket_test: TransmitFile_Client ERROR - small file data corruption\n"); |
michael@0 | 1161 | failed_already=1; |
michael@0 | 1162 | return; |
michael@0 | 1163 | } |
michael@0 | 1164 | #endif |
michael@0 | 1165 | /* |
michael@0 | 1166 | * read the large file and verify the data |
michael@0 | 1167 | */ |
michael@0 | 1168 | if (readn(sockfd, large_buf, LARGE_FILE_SIZE) != LARGE_FILE_SIZE) { |
michael@0 | 1169 | fprintf(stderr, |
michael@0 | 1170 | "prsocket_test: TransmitFile_Client failed to receive file\n"); |
michael@0 | 1171 | failed_already=1; |
michael@0 | 1172 | return; |
michael@0 | 1173 | } |
michael@0 | 1174 | #if defined(XP_UNIX) && !defined(SYMBIAN) |
michael@0 | 1175 | if (memcmp(large_file_addr, large_buf, LARGE_FILE_SIZE) != 0) { |
michael@0 | 1176 | fprintf(stderr, |
michael@0 | 1177 | "prsocket_test: TransmitFile_Client ERROR - large file data corruption\n"); |
michael@0 | 1178 | failed_already=1; |
michael@0 | 1179 | } |
michael@0 | 1180 | #endif |
michael@0 | 1181 | |
michael@0 | 1182 | |
michael@0 | 1183 | /* |
michael@0 | 1184 | * receive data from PR_SendFile |
michael@0 | 1185 | */ |
michael@0 | 1186 | /* |
michael@0 | 1187 | * case 1: small file with header and trailer |
michael@0 | 1188 | */ |
michael@0 | 1189 | rlen = SMALL_FILE_SIZE + SMALL_FILE_HEADER_SIZE + |
michael@0 | 1190 | SMALL_FILE_TRAILER_SIZE; |
michael@0 | 1191 | if (readn(sockfd, small_buf, rlen) != rlen) { |
michael@0 | 1192 | fprintf(stderr, |
michael@0 | 1193 | "prsocket_test: SendFile_Client failed to receive file\n"); |
michael@0 | 1194 | failed_already=1; |
michael@0 | 1195 | return; |
michael@0 | 1196 | } |
michael@0 | 1197 | #if defined(XP_UNIX) && !defined(SYMBIAN) |
michael@0 | 1198 | if (memcmp(small_file_header, small_buf, SMALL_FILE_HEADER_SIZE) != 0){ |
michael@0 | 1199 | fprintf(stderr, |
michael@0 | 1200 | "SendFile 1. ERROR - small file header corruption\n"); |
michael@0 | 1201 | failed_already=1; |
michael@0 | 1202 | return; |
michael@0 | 1203 | } |
michael@0 | 1204 | if (memcmp(small_file_addr, small_buf + SMALL_FILE_HEADER_SIZE, |
michael@0 | 1205 | SMALL_FILE_SIZE) != 0) { |
michael@0 | 1206 | fprintf(stderr, |
michael@0 | 1207 | "SendFile 1. ERROR - small file data corruption\n"); |
michael@0 | 1208 | failed_already=1; |
michael@0 | 1209 | return; |
michael@0 | 1210 | } |
michael@0 | 1211 | if (memcmp(small_file_trailer, |
michael@0 | 1212 | small_buf + SMALL_FILE_HEADER_SIZE + SMALL_FILE_SIZE, |
michael@0 | 1213 | SMALL_FILE_TRAILER_SIZE) != 0) { |
michael@0 | 1214 | fprintf(stderr, |
michael@0 | 1215 | "SendFile 1. ERROR - small file trailer corruption\n"); |
michael@0 | 1216 | failed_already=1; |
michael@0 | 1217 | return; |
michael@0 | 1218 | } |
michael@0 | 1219 | #endif |
michael@0 | 1220 | /* |
michael@0 | 1221 | * case 2: partial large file at zero offset, file with header and trailer |
michael@0 | 1222 | */ |
michael@0 | 1223 | rlen = LARGE_FILE_LEN_1 + LARGE_FILE_HEADER_SIZE + |
michael@0 | 1224 | LARGE_FILE_TRAILER_SIZE; |
michael@0 | 1225 | if (readn(sockfd, large_buf, rlen) != rlen) { |
michael@0 | 1226 | fprintf(stderr, |
michael@0 | 1227 | "prsocket_test: SendFile_Client failed to receive file\n"); |
michael@0 | 1228 | failed_already=1; |
michael@0 | 1229 | return; |
michael@0 | 1230 | } |
michael@0 | 1231 | #if defined(XP_UNIX) && !defined(SYMBIAN) |
michael@0 | 1232 | if (memcmp(large_file_header, large_buf, LARGE_FILE_HEADER_SIZE) != 0){ |
michael@0 | 1233 | fprintf(stderr, |
michael@0 | 1234 | "SendFile 2. ERROR - large file header corruption\n"); |
michael@0 | 1235 | failed_already=1; |
michael@0 | 1236 | return; |
michael@0 | 1237 | } |
michael@0 | 1238 | if (memcmp(large_file_addr, large_buf + LARGE_FILE_HEADER_SIZE, |
michael@0 | 1239 | LARGE_FILE_LEN_1) != 0) { |
michael@0 | 1240 | fprintf(stderr, |
michael@0 | 1241 | "SendFile 2. ERROR - large file data corruption\n"); |
michael@0 | 1242 | failed_already=1; |
michael@0 | 1243 | return; |
michael@0 | 1244 | } |
michael@0 | 1245 | if (memcmp(large_file_trailer, |
michael@0 | 1246 | large_buf + LARGE_FILE_HEADER_SIZE + LARGE_FILE_LEN_1, |
michael@0 | 1247 | LARGE_FILE_TRAILER_SIZE) != 0) { |
michael@0 | 1248 | fprintf(stderr, |
michael@0 | 1249 | "SendFile 2. ERROR - large file trailer corruption\n"); |
michael@0 | 1250 | failed_already=1; |
michael@0 | 1251 | return; |
michael@0 | 1252 | } |
michael@0 | 1253 | #endif |
michael@0 | 1254 | /* |
michael@0 | 1255 | * case 3: partial small file at non-zero offset, with header |
michael@0 | 1256 | */ |
michael@0 | 1257 | rlen = SMALL_FILE_LEN_1 + SMALL_FILE_HEADER_SIZE; |
michael@0 | 1258 | if (readn(sockfd, small_buf, rlen) != rlen) { |
michael@0 | 1259 | fprintf(stderr, |
michael@0 | 1260 | "prsocket_test: SendFile_Client failed to receive file\n"); |
michael@0 | 1261 | failed_already=1; |
michael@0 | 1262 | return; |
michael@0 | 1263 | } |
michael@0 | 1264 | #if defined(XP_UNIX) && !defined(SYMBIAN) |
michael@0 | 1265 | if (memcmp(small_file_header, small_buf, SMALL_FILE_HEADER_SIZE) != 0){ |
michael@0 | 1266 | fprintf(stderr, |
michael@0 | 1267 | "SendFile 3. ERROR - small file header corruption\n"); |
michael@0 | 1268 | failed_already=1; |
michael@0 | 1269 | return; |
michael@0 | 1270 | } |
michael@0 | 1271 | if (memcmp((char *) small_file_addr + SMALL_FILE_OFFSET_1, |
michael@0 | 1272 | small_buf + SMALL_FILE_HEADER_SIZE, SMALL_FILE_LEN_1) != 0) { |
michael@0 | 1273 | fprintf(stderr, |
michael@0 | 1274 | "SendFile 3. ERROR - small file data corruption\n"); |
michael@0 | 1275 | failed_already=1; |
michael@0 | 1276 | return; |
michael@0 | 1277 | } |
michael@0 | 1278 | #endif |
michael@0 | 1279 | /* |
michael@0 | 1280 | * case 4: partial small file at non-zero offset, with trailer |
michael@0 | 1281 | */ |
michael@0 | 1282 | rlen = SMALL_FILE_LEN_2 + SMALL_FILE_TRAILER_SIZE; |
michael@0 | 1283 | if (readn(sockfd, small_buf, rlen) != rlen) { |
michael@0 | 1284 | fprintf(stderr, |
michael@0 | 1285 | "prsocket_test: SendFile_Client failed to receive file\n"); |
michael@0 | 1286 | failed_already=1; |
michael@0 | 1287 | return; |
michael@0 | 1288 | } |
michael@0 | 1289 | #if defined(XP_UNIX) && !defined(SYMBIAN) |
michael@0 | 1290 | if (memcmp((char *) small_file_addr + SMALL_FILE_OFFSET_2, small_buf, |
michael@0 | 1291 | SMALL_FILE_LEN_2) != 0) { |
michael@0 | 1292 | fprintf(stderr, |
michael@0 | 1293 | "SendFile 4. ERROR - small file data corruption\n"); |
michael@0 | 1294 | failed_already=1; |
michael@0 | 1295 | return; |
michael@0 | 1296 | } |
michael@0 | 1297 | if (memcmp(small_file_trailer, small_buf + SMALL_FILE_LEN_2, |
michael@0 | 1298 | SMALL_FILE_TRAILER_SIZE) != 0) { |
michael@0 | 1299 | fprintf(stderr, |
michael@0 | 1300 | "SendFile 4. ERROR - small file trailer corruption\n"); |
michael@0 | 1301 | failed_already=1; |
michael@0 | 1302 | return; |
michael@0 | 1303 | } |
michael@0 | 1304 | #endif |
michael@0 | 1305 | /* |
michael@0 | 1306 | * case 5: partial large file at non-zero offset, file with header |
michael@0 | 1307 | */ |
michael@0 | 1308 | rlen = LARGE_FILE_LEN_2 + LARGE_FILE_HEADER_SIZE; |
michael@0 | 1309 | if (readn(sockfd, large_buf, rlen) != rlen) { |
michael@0 | 1310 | fprintf(stderr, |
michael@0 | 1311 | "prsocket_test: SendFile_Client failed to receive file\n"); |
michael@0 | 1312 | failed_already=1; |
michael@0 | 1313 | return; |
michael@0 | 1314 | } |
michael@0 | 1315 | #if defined(XP_UNIX) && !defined(SYMBIAN) |
michael@0 | 1316 | if (memcmp(large_file_header, large_buf, LARGE_FILE_HEADER_SIZE) != 0){ |
michael@0 | 1317 | fprintf(stderr, |
michael@0 | 1318 | "SendFile 5. ERROR - large file header corruption\n"); |
michael@0 | 1319 | failed_already=1; |
michael@0 | 1320 | return; |
michael@0 | 1321 | } |
michael@0 | 1322 | if (memcmp((char *)large_file_addr + LARGE_FILE_OFFSET_2, |
michael@0 | 1323 | large_buf + LARGE_FILE_HEADER_SIZE, |
michael@0 | 1324 | LARGE_FILE_LEN_2) != 0) { |
michael@0 | 1325 | fprintf(stderr, |
michael@0 | 1326 | "SendFile 5. ERROR - large file data corruption\n"); |
michael@0 | 1327 | failed_already=1; |
michael@0 | 1328 | return; |
michael@0 | 1329 | } |
michael@0 | 1330 | #endif |
michael@0 | 1331 | /* |
michael@0 | 1332 | * case 6: partial small file at non-zero offset, with header |
michael@0 | 1333 | */ |
michael@0 | 1334 | rlen = SMALL_FILE_LEN_3 + SMALL_FILE_HEADER_SIZE; |
michael@0 | 1335 | if (readn(sockfd, small_buf, rlen) != rlen) { |
michael@0 | 1336 | fprintf(stderr, |
michael@0 | 1337 | "prsocket_test: SendFile_Client failed to receive file\n"); |
michael@0 | 1338 | failed_already=1; |
michael@0 | 1339 | return; |
michael@0 | 1340 | } |
michael@0 | 1341 | #if defined(XP_UNIX) && !defined(SYMBIAN) |
michael@0 | 1342 | if (memcmp(small_file_header, small_buf, SMALL_FILE_HEADER_SIZE) != 0){ |
michael@0 | 1343 | fprintf(stderr, |
michael@0 | 1344 | "SendFile 6. ERROR - small file header corruption\n"); |
michael@0 | 1345 | return; |
michael@0 | 1346 | } |
michael@0 | 1347 | if (memcmp((char *) small_file_addr + SMALL_FILE_OFFSET_3, |
michael@0 | 1348 | small_buf + SMALL_FILE_HEADER_SIZE, SMALL_FILE_LEN_3) != 0) { |
michael@0 | 1349 | #if 0 |
michael@0 | 1350 | char *i, *j; |
michael@0 | 1351 | int k; |
michael@0 | 1352 | |
michael@0 | 1353 | i = (char *) small_file_addr + SMALL_FILE_OFFSET_3; |
michael@0 | 1354 | j = small_buf + SMALL_FILE_HEADER_SIZE; |
michael@0 | 1355 | k = SMALL_FILE_LEN_3; |
michael@0 | 1356 | while (k-- > 0) { |
michael@0 | 1357 | if (*i++ != *j++) |
michael@0 | 1358 | printf("i = %d j = %d\n", |
michael@0 | 1359 | (int) (i - ((char *) small_file_addr + SMALL_FILE_OFFSET_3)), |
michael@0 | 1360 | (int) (j - (small_buf + SMALL_FILE_HEADER_SIZE))); |
michael@0 | 1361 | } |
michael@0 | 1362 | #endif |
michael@0 | 1363 | fprintf(stderr, |
michael@0 | 1364 | "SendFile 6. ERROR - small file data corruption\n"); |
michael@0 | 1365 | failed_already=1; |
michael@0 | 1366 | return; |
michael@0 | 1367 | } |
michael@0 | 1368 | #endif |
michael@0 | 1369 | /* |
michael@0 | 1370 | * case 7: partial large file at non-zero offset, with header |
michael@0 | 1371 | */ |
michael@0 | 1372 | rlen = LARGE_FILE_LEN_3 + LARGE_FILE_HEADER_SIZE; |
michael@0 | 1373 | if (readn(sockfd, large_buf, rlen) != rlen) { |
michael@0 | 1374 | fprintf(stderr, |
michael@0 | 1375 | "prsocket_test: SendFile_Client failed to receive file\n"); |
michael@0 | 1376 | failed_already=1; |
michael@0 | 1377 | return; |
michael@0 | 1378 | } |
michael@0 | 1379 | #if defined(XP_UNIX) && !defined(SYMBIAN) |
michael@0 | 1380 | if (memcmp(large_file_header, large_buf, LARGE_FILE_HEADER_SIZE) != 0){ |
michael@0 | 1381 | fprintf(stderr, |
michael@0 | 1382 | "SendFile 7. ERROR - large file header corruption\n"); |
michael@0 | 1383 | failed_already=1; |
michael@0 | 1384 | return; |
michael@0 | 1385 | } |
michael@0 | 1386 | if (memcmp((char *)large_file_addr + LARGE_FILE_OFFSET_3, |
michael@0 | 1387 | large_buf + LARGE_FILE_HEADER_SIZE, |
michael@0 | 1388 | LARGE_FILE_LEN_3) != 0) { |
michael@0 | 1389 | fprintf(stderr, |
michael@0 | 1390 | "SendFile 7. ERROR - large file data corruption\n"); |
michael@0 | 1391 | failed_already=1; |
michael@0 | 1392 | return; |
michael@0 | 1393 | } |
michael@0 | 1394 | #endif |
michael@0 | 1395 | /* |
michael@0 | 1396 | * case 8: partial large file at non-zero, page-aligned offset, with |
michael@0 | 1397 | * header and trailer |
michael@0 | 1398 | */ |
michael@0 | 1399 | rlen = LARGE_FILE_LEN_4 + LARGE_FILE_HEADER_SIZE + |
michael@0 | 1400 | LARGE_FILE_TRAILER_SIZE; |
michael@0 | 1401 | if (readn(sockfd, large_buf, rlen) != rlen) { |
michael@0 | 1402 | fprintf(stderr, |
michael@0 | 1403 | "prsocket_test: SendFile_Client failed to receive file\n"); |
michael@0 | 1404 | failed_already=1; |
michael@0 | 1405 | return; |
michael@0 | 1406 | } |
michael@0 | 1407 | #if defined(XP_UNIX) && !defined(SYMBIAN) |
michael@0 | 1408 | if (memcmp(large_file_header, large_buf, LARGE_FILE_HEADER_SIZE) != 0){ |
michael@0 | 1409 | fprintf(stderr, |
michael@0 | 1410 | "SendFile 2. ERROR - large file header corruption\n"); |
michael@0 | 1411 | failed_already=1; |
michael@0 | 1412 | return; |
michael@0 | 1413 | } |
michael@0 | 1414 | if (memcmp((char *)large_file_addr + LARGE_FILE_OFFSET_4, |
michael@0 | 1415 | large_buf + LARGE_FILE_HEADER_SIZE, |
michael@0 | 1416 | LARGE_FILE_LEN_4) != 0) { |
michael@0 | 1417 | fprintf(stderr, |
michael@0 | 1418 | "SendFile 2. ERROR - large file data corruption\n"); |
michael@0 | 1419 | failed_already=1; |
michael@0 | 1420 | return; |
michael@0 | 1421 | } |
michael@0 | 1422 | if (memcmp(large_file_trailer, |
michael@0 | 1423 | large_buf + LARGE_FILE_HEADER_SIZE + LARGE_FILE_LEN_4, |
michael@0 | 1424 | LARGE_FILE_TRAILER_SIZE) != 0) { |
michael@0 | 1425 | fprintf(stderr, |
michael@0 | 1426 | "SendFile 2. ERROR - large file trailer corruption\n"); |
michael@0 | 1427 | failed_already=1; |
michael@0 | 1428 | return; |
michael@0 | 1429 | } |
michael@0 | 1430 | #endif |
michael@0 | 1431 | PR_DELETE(small_buf); |
michael@0 | 1432 | PR_DELETE(large_buf); |
michael@0 | 1433 | PR_Close(sockfd); |
michael@0 | 1434 | |
michael@0 | 1435 | |
michael@0 | 1436 | /* |
michael@0 | 1437 | * Decrement exit_counter and notify parent thread |
michael@0 | 1438 | */ |
michael@0 | 1439 | |
michael@0 | 1440 | PR_EnterMonitor(cp->exit_mon); |
michael@0 | 1441 | --(*cp->exit_counter); |
michael@0 | 1442 | PR_Notify(cp->exit_mon); |
michael@0 | 1443 | PR_ExitMonitor(cp->exit_mon); |
michael@0 | 1444 | DPRINTF(("TransmitFile_Client [0x%lx] exiting\n", PR_GetCurrentThread())); |
michael@0 | 1445 | } |
michael@0 | 1446 | |
michael@0 | 1447 | /* |
michael@0 | 1448 | * Serve_TransmitFile_Client |
michael@0 | 1449 | * Thread, started by the server, for serving a client connection. |
michael@0 | 1450 | * Trasmits a small file, with a header, and a large file, without |
michael@0 | 1451 | * a header |
michael@0 | 1452 | */ |
michael@0 | 1453 | static void |
michael@0 | 1454 | Serve_TransmitFile_Client(void *arg) |
michael@0 | 1455 | { |
michael@0 | 1456 | Serve_Client_Param *scp = (Serve_Client_Param *) arg; |
michael@0 | 1457 | PRFileDesc *sockfd; |
michael@0 | 1458 | PRInt32 bytes; |
michael@0 | 1459 | PRFileDesc *local_small_file_fd=NULL; |
michael@0 | 1460 | PRFileDesc *local_large_file_fd=NULL; |
michael@0 | 1461 | PRSendFileData sfd; |
michael@0 | 1462 | PRInt32 slen; |
michael@0 | 1463 | |
michael@0 | 1464 | sockfd = scp->sockfd; |
michael@0 | 1465 | local_small_file_fd = PR_Open(SMALL_FILE_NAME, PR_RDONLY,0); |
michael@0 | 1466 | |
michael@0 | 1467 | if (local_small_file_fd == NULL) { |
michael@0 | 1468 | fprintf(stderr,"prsocket_test failed to open file for transmitting %s\n", |
michael@0 | 1469 | SMALL_FILE_NAME); |
michael@0 | 1470 | failed_already=1; |
michael@0 | 1471 | goto done; |
michael@0 | 1472 | } |
michael@0 | 1473 | local_large_file_fd = PR_Open(LARGE_FILE_NAME, PR_RDONLY,0); |
michael@0 | 1474 | |
michael@0 | 1475 | if (local_large_file_fd == NULL) { |
michael@0 | 1476 | fprintf(stderr,"prsocket_test failed to open file for transmitting %s\n", |
michael@0 | 1477 | LARGE_FILE_NAME); |
michael@0 | 1478 | failed_already=1; |
michael@0 | 1479 | goto done; |
michael@0 | 1480 | } |
michael@0 | 1481 | bytes = PR_TransmitFile(sockfd, local_small_file_fd, small_file_header, |
michael@0 | 1482 | SMALL_FILE_HEADER_SIZE, PR_TRANSMITFILE_KEEP_OPEN, |
michael@0 | 1483 | PR_INTERVAL_NO_TIMEOUT); |
michael@0 | 1484 | if (bytes != (SMALL_FILE_SIZE+ SMALL_FILE_HEADER_SIZE)) { |
michael@0 | 1485 | fprintf(stderr, |
michael@0 | 1486 | "prsocet_test: PR_TransmitFile failed: (%ld, %ld)\n", |
michael@0 | 1487 | PR_GetError(), PR_GetOSError()); |
michael@0 | 1488 | failed_already=1; |
michael@0 | 1489 | } |
michael@0 | 1490 | bytes = PR_TransmitFile(sockfd, local_large_file_fd, NULL, 0, |
michael@0 | 1491 | PR_TRANSMITFILE_KEEP_OPEN, PR_INTERVAL_NO_TIMEOUT); |
michael@0 | 1492 | if (bytes != LARGE_FILE_SIZE) { |
michael@0 | 1493 | fprintf(stderr, |
michael@0 | 1494 | "prsocket_test: PR_TransmitFile failed: (%ld, %ld)\n", |
michael@0 | 1495 | PR_GetError(), PR_GetOSError()); |
michael@0 | 1496 | failed_already=1; |
michael@0 | 1497 | } |
michael@0 | 1498 | |
michael@0 | 1499 | /* |
michael@0 | 1500 | * PR_SendFile test cases |
michael@0 | 1501 | */ |
michael@0 | 1502 | |
michael@0 | 1503 | /* |
michael@0 | 1504 | * case 1: small file with header and trailer |
michael@0 | 1505 | */ |
michael@0 | 1506 | sfd.fd = local_small_file_fd; |
michael@0 | 1507 | sfd.file_offset = 0; |
michael@0 | 1508 | sfd.file_nbytes = 0; |
michael@0 | 1509 | sfd.header = small_file_header; |
michael@0 | 1510 | sfd.hlen = SMALL_FILE_HEADER_SIZE; |
michael@0 | 1511 | sfd.trailer = small_file_trailer; |
michael@0 | 1512 | sfd.tlen = SMALL_FILE_TRAILER_SIZE; |
michael@0 | 1513 | bytes = PR_SendFile(sockfd, &sfd, PR_TRANSMITFILE_KEEP_OPEN, |
michael@0 | 1514 | PR_INTERVAL_NO_TIMEOUT); |
michael@0 | 1515 | slen = SMALL_FILE_SIZE+ SMALL_FILE_HEADER_SIZE + |
michael@0 | 1516 | SMALL_FILE_TRAILER_SIZE; |
michael@0 | 1517 | if (bytes != slen) { |
michael@0 | 1518 | fprintf(stderr, |
michael@0 | 1519 | "socket: Error - 1. PR_SendFile send_size = %d, bytes sent = %d\n", |
michael@0 | 1520 | slen, bytes); |
michael@0 | 1521 | fprintf(stderr, |
michael@0 | 1522 | "prsocket_test: PR_SendFile failed: (%ld, %ld)\n", |
michael@0 | 1523 | PR_GetError(), PR_GetOSError()); |
michael@0 | 1524 | failed_already=1; |
michael@0 | 1525 | } |
michael@0 | 1526 | |
michael@0 | 1527 | /* |
michael@0 | 1528 | * case 2: partial large file at zero offset, file with header and trailer |
michael@0 | 1529 | */ |
michael@0 | 1530 | sfd.fd = local_large_file_fd; |
michael@0 | 1531 | sfd.file_offset = 0; |
michael@0 | 1532 | sfd.file_nbytes = LARGE_FILE_LEN_1; |
michael@0 | 1533 | sfd.header = large_file_header; |
michael@0 | 1534 | sfd.hlen = LARGE_FILE_HEADER_SIZE; |
michael@0 | 1535 | sfd.trailer = large_file_trailer; |
michael@0 | 1536 | sfd.tlen = LARGE_FILE_TRAILER_SIZE; |
michael@0 | 1537 | bytes = PR_SendFile(sockfd, &sfd, PR_TRANSMITFILE_KEEP_OPEN, |
michael@0 | 1538 | PR_INTERVAL_NO_TIMEOUT); |
michael@0 | 1539 | slen = LARGE_FILE_LEN_1 + LARGE_FILE_HEADER_SIZE + |
michael@0 | 1540 | LARGE_FILE_TRAILER_SIZE; |
michael@0 | 1541 | if (bytes != slen) { |
michael@0 | 1542 | fprintf(stderr, |
michael@0 | 1543 | "socket: Error - 2. PR_SendFile send_size = %d, bytes sent = %d\n", |
michael@0 | 1544 | slen, bytes); |
michael@0 | 1545 | fprintf(stderr, |
michael@0 | 1546 | "prsocket_test: PR_SendFile failed: (%ld, %ld)\n", |
michael@0 | 1547 | PR_GetError(), PR_GetOSError()); |
michael@0 | 1548 | failed_already=1; |
michael@0 | 1549 | } |
michael@0 | 1550 | /* |
michael@0 | 1551 | * case 3: partial small file at non-zero offset, with header |
michael@0 | 1552 | */ |
michael@0 | 1553 | sfd.fd = local_small_file_fd; |
michael@0 | 1554 | sfd.file_offset = SMALL_FILE_OFFSET_1; |
michael@0 | 1555 | sfd.file_nbytes = SMALL_FILE_LEN_1; |
michael@0 | 1556 | sfd.header = small_file_header; |
michael@0 | 1557 | sfd.hlen = SMALL_FILE_HEADER_SIZE; |
michael@0 | 1558 | sfd.trailer = NULL; |
michael@0 | 1559 | sfd.tlen = 0; |
michael@0 | 1560 | bytes = PR_SendFile(sockfd, &sfd, PR_TRANSMITFILE_KEEP_OPEN, |
michael@0 | 1561 | PR_INTERVAL_NO_TIMEOUT); |
michael@0 | 1562 | slen = SMALL_FILE_LEN_1 + SMALL_FILE_HEADER_SIZE; |
michael@0 | 1563 | if (bytes != slen) { |
michael@0 | 1564 | fprintf(stderr, |
michael@0 | 1565 | "socket: Error - 3. PR_SendFile send_size = %d, bytes sent = %d\n", |
michael@0 | 1566 | slen, bytes); |
michael@0 | 1567 | fprintf(stderr, |
michael@0 | 1568 | "prsocket_test: PR_SendFile failed: (%ld, %ld)\n", |
michael@0 | 1569 | PR_GetError(), PR_GetOSError()); |
michael@0 | 1570 | failed_already=1; |
michael@0 | 1571 | } |
michael@0 | 1572 | /* |
michael@0 | 1573 | * case 4: partial small file at non-zero offset, with trailer |
michael@0 | 1574 | */ |
michael@0 | 1575 | sfd.fd = local_small_file_fd; |
michael@0 | 1576 | sfd.file_offset = SMALL_FILE_OFFSET_2; |
michael@0 | 1577 | sfd.file_nbytes = SMALL_FILE_LEN_2; |
michael@0 | 1578 | sfd.header = NULL; |
michael@0 | 1579 | sfd.hlen = 0; |
michael@0 | 1580 | sfd.trailer = small_file_trailer; |
michael@0 | 1581 | sfd.tlen = SMALL_FILE_TRAILER_SIZE; |
michael@0 | 1582 | bytes = PR_SendFile(sockfd, &sfd, PR_TRANSMITFILE_KEEP_OPEN, |
michael@0 | 1583 | PR_INTERVAL_NO_TIMEOUT); |
michael@0 | 1584 | slen = SMALL_FILE_LEN_2 + SMALL_FILE_TRAILER_SIZE; |
michael@0 | 1585 | if (bytes != slen) { |
michael@0 | 1586 | fprintf(stderr, |
michael@0 | 1587 | "socket: Error - 4. PR_SendFile send_size = %d, bytes sent = %d\n", |
michael@0 | 1588 | slen, bytes); |
michael@0 | 1589 | fprintf(stderr, |
michael@0 | 1590 | "prsocket_test: PR_SendFile failed: (%ld, %ld)\n", |
michael@0 | 1591 | PR_GetError(), PR_GetOSError()); |
michael@0 | 1592 | failed_already=1; |
michael@0 | 1593 | } |
michael@0 | 1594 | /* |
michael@0 | 1595 | * case 5: partial large file at non-zero offset, file with header |
michael@0 | 1596 | */ |
michael@0 | 1597 | sfd.fd = local_large_file_fd; |
michael@0 | 1598 | sfd.file_offset = LARGE_FILE_OFFSET_2; |
michael@0 | 1599 | sfd.file_nbytes = LARGE_FILE_LEN_2; |
michael@0 | 1600 | sfd.header = large_file_header; |
michael@0 | 1601 | sfd.hlen = LARGE_FILE_HEADER_SIZE; |
michael@0 | 1602 | sfd.trailer = NULL; |
michael@0 | 1603 | sfd.tlen = 0; |
michael@0 | 1604 | bytes = PR_SendFile(sockfd, &sfd, PR_TRANSMITFILE_KEEP_OPEN, |
michael@0 | 1605 | PR_INTERVAL_NO_TIMEOUT); |
michael@0 | 1606 | slen = LARGE_FILE_LEN_2 + LARGE_FILE_HEADER_SIZE; |
michael@0 | 1607 | if (bytes != slen) { |
michael@0 | 1608 | fprintf(stderr, |
michael@0 | 1609 | "socket: Error - 5. PR_SendFile send_size = %d, bytes sent = %d\n", |
michael@0 | 1610 | slen, bytes); |
michael@0 | 1611 | fprintf(stderr, |
michael@0 | 1612 | "prsocket_test: PR_SendFile failed: (%ld, %ld)\n", |
michael@0 | 1613 | PR_GetError(), PR_GetOSError()); |
michael@0 | 1614 | failed_already=1; |
michael@0 | 1615 | } |
michael@0 | 1616 | /* |
michael@0 | 1617 | * case 6: partial small file from non-zero offset till end of file, with header |
michael@0 | 1618 | */ |
michael@0 | 1619 | sfd.fd = local_small_file_fd; |
michael@0 | 1620 | sfd.file_offset = SMALL_FILE_OFFSET_3; |
michael@0 | 1621 | sfd.file_nbytes = 0; /* data from offset to end-of-file */ |
michael@0 | 1622 | sfd.header = small_file_header; |
michael@0 | 1623 | sfd.hlen = SMALL_FILE_HEADER_SIZE; |
michael@0 | 1624 | sfd.trailer = NULL; |
michael@0 | 1625 | sfd.tlen = 0; |
michael@0 | 1626 | bytes = PR_SendFile(sockfd, &sfd, PR_TRANSMITFILE_KEEP_OPEN, |
michael@0 | 1627 | PR_INTERVAL_NO_TIMEOUT); |
michael@0 | 1628 | slen = SMALL_FILE_LEN_3 + SMALL_FILE_HEADER_SIZE; |
michael@0 | 1629 | if (bytes != slen) { |
michael@0 | 1630 | fprintf(stderr, |
michael@0 | 1631 | "socket: Error - 6. PR_SendFile send_size = %d, bytes sent = %d\n", |
michael@0 | 1632 | slen, bytes); |
michael@0 | 1633 | fprintf(stderr, |
michael@0 | 1634 | "prsocket_test: PR_SendFile failed: (%ld, %ld)\n", |
michael@0 | 1635 | PR_GetError(), PR_GetOSError()); |
michael@0 | 1636 | failed_already=1; |
michael@0 | 1637 | } |
michael@0 | 1638 | /* |
michael@0 | 1639 | * case 7: partial large file at non-zero offset till end-of-file, with header |
michael@0 | 1640 | */ |
michael@0 | 1641 | sfd.fd = local_large_file_fd; |
michael@0 | 1642 | sfd.file_offset = LARGE_FILE_OFFSET_3; |
michael@0 | 1643 | sfd.file_nbytes = 0; /* data until end-of-file */ |
michael@0 | 1644 | sfd.header = large_file_header; |
michael@0 | 1645 | sfd.hlen = LARGE_FILE_HEADER_SIZE; |
michael@0 | 1646 | sfd.trailer = NULL; |
michael@0 | 1647 | sfd.tlen = 0; |
michael@0 | 1648 | bytes = PR_SendFile(sockfd, &sfd, PR_TRANSMITFILE_KEEP_OPEN, |
michael@0 | 1649 | PR_INTERVAL_NO_TIMEOUT); |
michael@0 | 1650 | slen = LARGE_FILE_LEN_3 + LARGE_FILE_HEADER_SIZE; |
michael@0 | 1651 | if (bytes != slen) { |
michael@0 | 1652 | fprintf(stderr, |
michael@0 | 1653 | "socket: Error - 7. PR_SendFile send_size = %d, bytes sent = %d\n", |
michael@0 | 1654 | slen, bytes); |
michael@0 | 1655 | fprintf(stderr, |
michael@0 | 1656 | "prsocket_test: PR_SendFile failed: (%ld, %ld)\n", |
michael@0 | 1657 | PR_GetError(), PR_GetOSError()); |
michael@0 | 1658 | failed_already=1; |
michael@0 | 1659 | } |
michael@0 | 1660 | /* |
michael@0 | 1661 | * case 8: partial large file at non-zero page-aligned offset, |
michael@0 | 1662 | * with header and trailer |
michael@0 | 1663 | */ |
michael@0 | 1664 | sfd.fd = local_large_file_fd; |
michael@0 | 1665 | sfd.file_offset = LARGE_FILE_OFFSET_4; |
michael@0 | 1666 | sfd.file_nbytes = LARGE_FILE_LEN_4; |
michael@0 | 1667 | sfd.header = large_file_header; |
michael@0 | 1668 | sfd.hlen = LARGE_FILE_HEADER_SIZE; |
michael@0 | 1669 | sfd.trailer = large_file_trailer; |
michael@0 | 1670 | sfd.tlen = LARGE_FILE_TRAILER_SIZE; |
michael@0 | 1671 | bytes = PR_SendFile(sockfd, &sfd, PR_TRANSMITFILE_CLOSE_SOCKET, |
michael@0 | 1672 | PR_INTERVAL_NO_TIMEOUT); |
michael@0 | 1673 | slen = LARGE_FILE_LEN_4 + LARGE_FILE_HEADER_SIZE + |
michael@0 | 1674 | LARGE_FILE_TRAILER_SIZE; |
michael@0 | 1675 | if (bytes != slen) { |
michael@0 | 1676 | fprintf(stderr, |
michael@0 | 1677 | "socket: Error - 2. PR_SendFile send_size = %d, bytes sent = %d\n", |
michael@0 | 1678 | slen, bytes); |
michael@0 | 1679 | fprintf(stderr, |
michael@0 | 1680 | "prsocket_test: PR_SendFile failed: (%ld, %ld)\n", |
michael@0 | 1681 | PR_GetError(), PR_GetOSError()); |
michael@0 | 1682 | failed_already=1; |
michael@0 | 1683 | } |
michael@0 | 1684 | done: |
michael@0 | 1685 | if (local_small_file_fd != NULL) |
michael@0 | 1686 | PR_Close(local_small_file_fd); |
michael@0 | 1687 | if (local_large_file_fd != NULL) |
michael@0 | 1688 | PR_Close(local_large_file_fd); |
michael@0 | 1689 | } |
michael@0 | 1690 | |
michael@0 | 1691 | /* |
michael@0 | 1692 | * TransmitFile Server |
michael@0 | 1693 | * Server Thread |
michael@0 | 1694 | * Bind an address to a socket and listen for incoming connections |
michael@0 | 1695 | * Create worker threads to service clients |
michael@0 | 1696 | */ |
michael@0 | 1697 | static void |
michael@0 | 1698 | TransmitFile_Server(void *arg) |
michael@0 | 1699 | { |
michael@0 | 1700 | PRThread **t = NULL; /* an array of PRThread pointers */ |
michael@0 | 1701 | Server_Param *sp = (Server_Param *) arg; |
michael@0 | 1702 | Serve_Client_Param *scp; |
michael@0 | 1703 | PRFileDesc *sockfd = NULL, *newsockfd; |
michael@0 | 1704 | PRNetAddr netaddr; |
michael@0 | 1705 | PRInt32 i; |
michael@0 | 1706 | |
michael@0 | 1707 | t = (PRThread**)PR_MALLOC(num_transmitfile_clients * sizeof(PRThread *)); |
michael@0 | 1708 | if (t == NULL) { |
michael@0 | 1709 | fprintf(stderr, "prsocket_test: run out of memory\n"); |
michael@0 | 1710 | failed_already=1; |
michael@0 | 1711 | goto exit; |
michael@0 | 1712 | } |
michael@0 | 1713 | /* |
michael@0 | 1714 | * Create a tcp socket |
michael@0 | 1715 | */ |
michael@0 | 1716 | if ((sockfd = PR_OpenTCPSocket(PR_AF_INET)) == NULL) { |
michael@0 | 1717 | fprintf(stderr,"prsocket_test: PR_OpenTCPSocket failed\n"); |
michael@0 | 1718 | failed_already=1; |
michael@0 | 1719 | goto exit; |
michael@0 | 1720 | } |
michael@0 | 1721 | memset(&netaddr, 0 , sizeof(netaddr)); |
michael@0 | 1722 | netaddr.inet.family = PR_AF_INET; |
michael@0 | 1723 | netaddr.inet.port = PR_htons(TCP_SERVER_PORT); |
michael@0 | 1724 | netaddr.inet.ip = PR_htonl(PR_INADDR_ANY); |
michael@0 | 1725 | /* |
michael@0 | 1726 | * try a few times to bind server's address, if addresses are in |
michael@0 | 1727 | * use |
michael@0 | 1728 | */ |
michael@0 | 1729 | i = 0; |
michael@0 | 1730 | while (PR_Bind(sockfd, &netaddr) < 0) { |
michael@0 | 1731 | if (PR_GetError() == PR_ADDRESS_IN_USE_ERROR) { |
michael@0 | 1732 | netaddr.inet.port += 2; |
michael@0 | 1733 | if (i++ < SERVER_MAX_BIND_COUNT) |
michael@0 | 1734 | continue; |
michael@0 | 1735 | } |
michael@0 | 1736 | fprintf(stderr,"prsocket_test: ERROR - PR_Bind failed\n"); |
michael@0 | 1737 | failed_already=1; |
michael@0 | 1738 | perror("PR_Bind"); |
michael@0 | 1739 | goto exit; |
michael@0 | 1740 | } |
michael@0 | 1741 | |
michael@0 | 1742 | if (PR_Listen(sockfd, 32) < 0) { |
michael@0 | 1743 | fprintf(stderr,"prsocket_test: ERROR - PR_Listen failed\n"); |
michael@0 | 1744 | failed_already=1; |
michael@0 | 1745 | goto exit; |
michael@0 | 1746 | } |
michael@0 | 1747 | |
michael@0 | 1748 | if (PR_GetSockName(sockfd, &netaddr) < 0) { |
michael@0 | 1749 | fprintf(stderr, |
michael@0 | 1750 | "prsocket_test: ERROR - PR_GetSockName failed\n"); |
michael@0 | 1751 | failed_already=1; |
michael@0 | 1752 | goto exit; |
michael@0 | 1753 | } |
michael@0 | 1754 | |
michael@0 | 1755 | DPRINTF(("TCP_Server: PR_BIND netaddr.inet.ip = 0x%lx, netaddr.inet.port = %d\n", |
michael@0 | 1756 | netaddr.inet.ip, netaddr.inet.port)); |
michael@0 | 1757 | tcp_server_addr.inet.family = netaddr.inet.family; |
michael@0 | 1758 | tcp_server_addr.inet.port = netaddr.inet.port; |
michael@0 | 1759 | tcp_server_addr.inet.ip = netaddr.inet.ip; |
michael@0 | 1760 | |
michael@0 | 1761 | /* |
michael@0 | 1762 | * Wake up parent thread because server address is bound and made |
michael@0 | 1763 | * available in the global variable 'tcp_server_addr' |
michael@0 | 1764 | */ |
michael@0 | 1765 | PR_PostSem(sp->addr_sem); |
michael@0 | 1766 | |
michael@0 | 1767 | for (i = 0; i < num_transmitfile_clients ; i++) { |
michael@0 | 1768 | /* test both null and non-null 'addr' argument to PR_Accept */ |
michael@0 | 1769 | PRNetAddr *addrp = (i%2 ? &netaddr: NULL); |
michael@0 | 1770 | |
michael@0 | 1771 | if ((newsockfd = PR_Accept(sockfd, addrp, |
michael@0 | 1772 | PR_INTERVAL_NO_TIMEOUT)) == NULL) { |
michael@0 | 1773 | fprintf(stderr, |
michael@0 | 1774 | "prsocket_test: ERROR - PR_Accept failed\n"); |
michael@0 | 1775 | failed_already=1; |
michael@0 | 1776 | goto exit; |
michael@0 | 1777 | } |
michael@0 | 1778 | /* test both regular and emulated PR_SendFile */ |
michael@0 | 1779 | if (i%2) { |
michael@0 | 1780 | PRFileDesc *layer = PR_CreateIOLayerStub( |
michael@0 | 1781 | emuSendFileIdentity, &emuSendFileMethods); |
michael@0 | 1782 | if (layer == NULL) { |
michael@0 | 1783 | fprintf(stderr, |
michael@0 | 1784 | "prsocket_test: ERROR - PR_CreateIOLayerStub failed\n"); |
michael@0 | 1785 | failed_already=1; |
michael@0 | 1786 | goto exit; |
michael@0 | 1787 | } |
michael@0 | 1788 | if (PR_PushIOLayer(newsockfd, PR_TOP_IO_LAYER, layer) |
michael@0 | 1789 | == PR_FAILURE) { |
michael@0 | 1790 | fprintf(stderr, |
michael@0 | 1791 | "prsocket_test: ERROR - PR_PushIOLayer failed\n"); |
michael@0 | 1792 | failed_already=1; |
michael@0 | 1793 | goto exit; |
michael@0 | 1794 | } |
michael@0 | 1795 | } |
michael@0 | 1796 | scp = PR_NEW(Serve_Client_Param); |
michael@0 | 1797 | if (scp == NULL) { |
michael@0 | 1798 | fprintf(stderr,"prsocket_test: PR_NEW failed\n"); |
michael@0 | 1799 | failed_already=1; |
michael@0 | 1800 | goto exit; |
michael@0 | 1801 | } |
michael@0 | 1802 | |
michael@0 | 1803 | /* |
michael@0 | 1804 | * Start a Serve_Client thread for each incoming connection |
michael@0 | 1805 | */ |
michael@0 | 1806 | scp->sockfd = newsockfd; |
michael@0 | 1807 | scp->datalen = sp->datalen; |
michael@0 | 1808 | |
michael@0 | 1809 | t[i] = PR_CreateThread(PR_USER_THREAD, |
michael@0 | 1810 | Serve_TransmitFile_Client, (void *)scp, |
michael@0 | 1811 | PR_PRIORITY_NORMAL, |
michael@0 | 1812 | PR_LOCAL_THREAD, |
michael@0 | 1813 | PR_JOINABLE_THREAD, |
michael@0 | 1814 | 0); |
michael@0 | 1815 | if (t[i] == NULL) { |
michael@0 | 1816 | fprintf(stderr, |
michael@0 | 1817 | "prsocket_test: PR_CreateThread failed\n"); |
michael@0 | 1818 | failed_already=1; |
michael@0 | 1819 | goto exit; |
michael@0 | 1820 | } |
michael@0 | 1821 | DPRINTF(("TransmitFile_Server: Created Serve_TransmitFile_Client = 0x%lx\n", t)); |
michael@0 | 1822 | } |
michael@0 | 1823 | |
michael@0 | 1824 | /* |
michael@0 | 1825 | * Wait for all the worker threads to end, so that we know |
michael@0 | 1826 | * they are no longer using the small and large file fd's. |
michael@0 | 1827 | */ |
michael@0 | 1828 | |
michael@0 | 1829 | for (i = 0; i < num_transmitfile_clients; i++) { |
michael@0 | 1830 | PR_JoinThread(t[i]); |
michael@0 | 1831 | } |
michael@0 | 1832 | |
michael@0 | 1833 | exit: |
michael@0 | 1834 | if (t) { |
michael@0 | 1835 | PR_DELETE(t); |
michael@0 | 1836 | } |
michael@0 | 1837 | if (sockfd) { |
michael@0 | 1838 | PR_Close(sockfd); |
michael@0 | 1839 | } |
michael@0 | 1840 | |
michael@0 | 1841 | /* |
michael@0 | 1842 | * Decrement exit_counter and notify parent thread |
michael@0 | 1843 | */ |
michael@0 | 1844 | |
michael@0 | 1845 | PR_EnterMonitor(sp->exit_mon); |
michael@0 | 1846 | --(*sp->exit_counter); |
michael@0 | 1847 | PR_Notify(sp->exit_mon); |
michael@0 | 1848 | PR_ExitMonitor(sp->exit_mon); |
michael@0 | 1849 | DPRINTF(("TransmitFile_Server [0x%lx] exiting\n", PR_GetCurrentThread())); |
michael@0 | 1850 | } |
michael@0 | 1851 | |
michael@0 | 1852 | /* |
michael@0 | 1853 | * Socket_Misc_Test - test miscellaneous functions |
michael@0 | 1854 | * |
michael@0 | 1855 | */ |
michael@0 | 1856 | static PRInt32 |
michael@0 | 1857 | Socket_Misc_Test(void) |
michael@0 | 1858 | { |
michael@0 | 1859 | PRIntn i, rv = 0, bytes, count, len; |
michael@0 | 1860 | PRThread *t; |
michael@0 | 1861 | PRSemaphore *server_sem; |
michael@0 | 1862 | Server_Param *sparamp; |
michael@0 | 1863 | Client_Param *cparamp; |
michael@0 | 1864 | PRMonitor *mon2; |
michael@0 | 1865 | PRInt32 datalen; |
michael@0 | 1866 | |
michael@0 | 1867 | /* |
michael@0 | 1868 | * We deliberately pick a buffer size that is not a nice multiple |
michael@0 | 1869 | * of 1024. |
michael@0 | 1870 | */ |
michael@0 | 1871 | #define TRANSMITFILE_BUF_SIZE (4 * 1024 - 11) |
michael@0 | 1872 | |
michael@0 | 1873 | typedef struct { |
michael@0 | 1874 | char data[TRANSMITFILE_BUF_SIZE]; |
michael@0 | 1875 | } file_buf; |
michael@0 | 1876 | file_buf *buf = NULL; |
michael@0 | 1877 | |
michael@0 | 1878 | /* |
michael@0 | 1879 | * create file(s) to be transmitted |
michael@0 | 1880 | */ |
michael@0 | 1881 | if ((PR_MkDir(TEST_DIR, 0777)) < 0) { |
michael@0 | 1882 | printf("prsocket_test failed to create dir %s\n",TEST_DIR); |
michael@0 | 1883 | failed_already=1; |
michael@0 | 1884 | return -1; |
michael@0 | 1885 | } |
michael@0 | 1886 | |
michael@0 | 1887 | small_file_fd = PR_Open(SMALL_FILE_NAME, PR_RDWR | PR_CREATE_FILE,0777); |
michael@0 | 1888 | |
michael@0 | 1889 | if (small_file_fd == NULL) { |
michael@0 | 1890 | fprintf(stderr,"prsocket_test failed to create/open file %s\n", |
michael@0 | 1891 | SMALL_FILE_NAME); |
michael@0 | 1892 | failed_already=1; |
michael@0 | 1893 | rv = -1; |
michael@0 | 1894 | goto done; |
michael@0 | 1895 | } |
michael@0 | 1896 | buf = PR_NEW(file_buf); |
michael@0 | 1897 | if (buf == NULL) { |
michael@0 | 1898 | fprintf(stderr,"prsocket_test failed to allocate buffer\n"); |
michael@0 | 1899 | failed_already=1; |
michael@0 | 1900 | rv = -1; |
michael@0 | 1901 | goto done; |
michael@0 | 1902 | } |
michael@0 | 1903 | /* |
michael@0 | 1904 | * fill in random data |
michael@0 | 1905 | */ |
michael@0 | 1906 | for (i = 0; i < TRANSMITFILE_BUF_SIZE; i++) { |
michael@0 | 1907 | buf->data[i] = i; |
michael@0 | 1908 | } |
michael@0 | 1909 | count = 0; |
michael@0 | 1910 | do { |
michael@0 | 1911 | len = (SMALL_FILE_SIZE - count) > TRANSMITFILE_BUF_SIZE ? |
michael@0 | 1912 | TRANSMITFILE_BUF_SIZE : (SMALL_FILE_SIZE - count); |
michael@0 | 1913 | bytes = PR_Write(small_file_fd, buf->data, len); |
michael@0 | 1914 | if (bytes <= 0) { |
michael@0 | 1915 | fprintf(stderr, |
michael@0 | 1916 | "prsocket_test failed to write to file %s\n", |
michael@0 | 1917 | SMALL_FILE_NAME); |
michael@0 | 1918 | failed_already=1; |
michael@0 | 1919 | rv = -1; |
michael@0 | 1920 | goto done; |
michael@0 | 1921 | } |
michael@0 | 1922 | count += bytes; |
michael@0 | 1923 | } while (count < SMALL_FILE_SIZE); |
michael@0 | 1924 | #ifdef XP_UNIX |
michael@0 | 1925 | /* |
michael@0 | 1926 | * map the small file; used in checking for data corruption |
michael@0 | 1927 | */ |
michael@0 | 1928 | small_file_addr = mmap(0, SMALL_FILE_SIZE, PROT_READ, |
michael@0 | 1929 | MAP_SHARED, small_file_fd->secret->md.osfd, 0); |
michael@0 | 1930 | if (small_file_addr == (void *) -1) { |
michael@0 | 1931 | fprintf(stderr,"prsocket_test failed to mmap file %s\n", |
michael@0 | 1932 | SMALL_FILE_NAME); |
michael@0 | 1933 | failed_already=1; |
michael@0 | 1934 | rv = -1; |
michael@0 | 1935 | goto done; |
michael@0 | 1936 | } |
michael@0 | 1937 | #endif |
michael@0 | 1938 | /* |
michael@0 | 1939 | * header for small file |
michael@0 | 1940 | */ |
michael@0 | 1941 | small_file_header = PR_MALLOC(SMALL_FILE_HEADER_SIZE); |
michael@0 | 1942 | if (small_file_header == NULL) { |
michael@0 | 1943 | fprintf(stderr,"prsocket_test failed to malloc header file\n"); |
michael@0 | 1944 | failed_already=1; |
michael@0 | 1945 | rv = -1; |
michael@0 | 1946 | goto done; |
michael@0 | 1947 | } |
michael@0 | 1948 | memset(small_file_header, (int) PR_IntervalNow(), |
michael@0 | 1949 | SMALL_FILE_HEADER_SIZE); |
michael@0 | 1950 | /* |
michael@0 | 1951 | * trailer for small file |
michael@0 | 1952 | */ |
michael@0 | 1953 | small_file_trailer = PR_MALLOC(SMALL_FILE_TRAILER_SIZE); |
michael@0 | 1954 | if (small_file_trailer == NULL) { |
michael@0 | 1955 | fprintf(stderr,"prsocket_test failed to malloc header trailer\n"); |
michael@0 | 1956 | failed_already=1; |
michael@0 | 1957 | rv = -1; |
michael@0 | 1958 | goto done; |
michael@0 | 1959 | } |
michael@0 | 1960 | memset(small_file_trailer, (int) PR_IntervalNow(), |
michael@0 | 1961 | SMALL_FILE_TRAILER_SIZE); |
michael@0 | 1962 | /* |
michael@0 | 1963 | * setup large file |
michael@0 | 1964 | */ |
michael@0 | 1965 | large_file_fd = PR_Open(LARGE_FILE_NAME, PR_RDWR | PR_CREATE_FILE,0777); |
michael@0 | 1966 | |
michael@0 | 1967 | if (large_file_fd == NULL) { |
michael@0 | 1968 | fprintf(stderr,"prsocket_test failed to create/open file %s\n", |
michael@0 | 1969 | LARGE_FILE_NAME); |
michael@0 | 1970 | failed_already=1; |
michael@0 | 1971 | rv = -1; |
michael@0 | 1972 | goto done; |
michael@0 | 1973 | } |
michael@0 | 1974 | /* |
michael@0 | 1975 | * fill in random data |
michael@0 | 1976 | */ |
michael@0 | 1977 | for (i = 0; i < TRANSMITFILE_BUF_SIZE; i++) { |
michael@0 | 1978 | buf->data[i] = i; |
michael@0 | 1979 | } |
michael@0 | 1980 | count = 0; |
michael@0 | 1981 | do { |
michael@0 | 1982 | len = (LARGE_FILE_SIZE - count) > TRANSMITFILE_BUF_SIZE ? |
michael@0 | 1983 | TRANSMITFILE_BUF_SIZE : (LARGE_FILE_SIZE - count); |
michael@0 | 1984 | bytes = PR_Write(large_file_fd, buf->data, len); |
michael@0 | 1985 | if (bytes <= 0) { |
michael@0 | 1986 | fprintf(stderr, |
michael@0 | 1987 | "prsocket_test failed to write to file %s: (%ld, %ld)\n", |
michael@0 | 1988 | LARGE_FILE_NAME, |
michael@0 | 1989 | PR_GetError(), PR_GetOSError()); |
michael@0 | 1990 | failed_already=1; |
michael@0 | 1991 | rv = -1; |
michael@0 | 1992 | goto done; |
michael@0 | 1993 | } |
michael@0 | 1994 | count += bytes; |
michael@0 | 1995 | } while (count < LARGE_FILE_SIZE); |
michael@0 | 1996 | #if defined(XP_UNIX) && !defined(SYMBIAN) |
michael@0 | 1997 | /* |
michael@0 | 1998 | * map the large file; used in checking for data corruption |
michael@0 | 1999 | */ |
michael@0 | 2000 | large_file_addr = mmap(0, LARGE_FILE_SIZE, PROT_READ, |
michael@0 | 2001 | MAP_SHARED, large_file_fd->secret->md.osfd, 0); |
michael@0 | 2002 | if (large_file_addr == (void *) -1) { |
michael@0 | 2003 | fprintf(stderr,"prsocket_test failed to mmap file %s\n", |
michael@0 | 2004 | LARGE_FILE_NAME); |
michael@0 | 2005 | failed_already=1; |
michael@0 | 2006 | rv = -1; |
michael@0 | 2007 | goto done; |
michael@0 | 2008 | } |
michael@0 | 2009 | #endif |
michael@0 | 2010 | /* |
michael@0 | 2011 | * header for large file |
michael@0 | 2012 | */ |
michael@0 | 2013 | large_file_header = PR_MALLOC(LARGE_FILE_HEADER_SIZE); |
michael@0 | 2014 | if (large_file_header == NULL) { |
michael@0 | 2015 | fprintf(stderr,"prsocket_test failed to malloc header file\n"); |
michael@0 | 2016 | failed_already=1; |
michael@0 | 2017 | rv = -1; |
michael@0 | 2018 | goto done; |
michael@0 | 2019 | } |
michael@0 | 2020 | memset(large_file_header, (int) PR_IntervalNow(), |
michael@0 | 2021 | LARGE_FILE_HEADER_SIZE); |
michael@0 | 2022 | /* |
michael@0 | 2023 | * trailer for large file |
michael@0 | 2024 | */ |
michael@0 | 2025 | large_file_trailer = PR_MALLOC(LARGE_FILE_TRAILER_SIZE); |
michael@0 | 2026 | if (large_file_trailer == NULL) { |
michael@0 | 2027 | fprintf(stderr,"prsocket_test failed to malloc header trailer\n"); |
michael@0 | 2028 | failed_already=1; |
michael@0 | 2029 | rv = -1; |
michael@0 | 2030 | goto done; |
michael@0 | 2031 | } |
michael@0 | 2032 | memset(large_file_trailer, (int) PR_IntervalNow(), |
michael@0 | 2033 | LARGE_FILE_TRAILER_SIZE); |
michael@0 | 2034 | |
michael@0 | 2035 | datalen = tcp_mesg_size; |
michael@0 | 2036 | thread_count = 0; |
michael@0 | 2037 | /* |
michael@0 | 2038 | * start the server thread |
michael@0 | 2039 | */ |
michael@0 | 2040 | sparamp = PR_NEW(Server_Param); |
michael@0 | 2041 | if (sparamp == NULL) { |
michael@0 | 2042 | fprintf(stderr,"prsocket_test: PR_NEW failed\n"); |
michael@0 | 2043 | failed_already=1; |
michael@0 | 2044 | rv = -1; |
michael@0 | 2045 | goto done; |
michael@0 | 2046 | } |
michael@0 | 2047 | server_sem = PR_NewSem(0); |
michael@0 | 2048 | if (server_sem == NULL) { |
michael@0 | 2049 | fprintf(stderr,"prsocket_test: PR_NewSem failed\n"); |
michael@0 | 2050 | failed_already=1; |
michael@0 | 2051 | rv = -1; |
michael@0 | 2052 | goto done; |
michael@0 | 2053 | } |
michael@0 | 2054 | mon2 = PR_NewMonitor(); |
michael@0 | 2055 | if (mon2 == NULL) { |
michael@0 | 2056 | fprintf(stderr,"prsocket_test: PR_NewMonitor failed\n"); |
michael@0 | 2057 | failed_already=1; |
michael@0 | 2058 | rv = -1; |
michael@0 | 2059 | goto done; |
michael@0 | 2060 | } |
michael@0 | 2061 | PR_EnterMonitor(mon2); |
michael@0 | 2062 | |
michael@0 | 2063 | sparamp->addr_sem = server_sem; |
michael@0 | 2064 | sparamp->exit_mon = mon2; |
michael@0 | 2065 | sparamp->exit_counter = &thread_count; |
michael@0 | 2066 | sparamp->datalen = datalen; |
michael@0 | 2067 | t = PR_CreateThread(PR_USER_THREAD, |
michael@0 | 2068 | TransmitFile_Server, (void *)sparamp, |
michael@0 | 2069 | PR_PRIORITY_NORMAL, |
michael@0 | 2070 | PR_LOCAL_THREAD, |
michael@0 | 2071 | PR_UNJOINABLE_THREAD, |
michael@0 | 2072 | 0); |
michael@0 | 2073 | if (t == NULL) { |
michael@0 | 2074 | fprintf(stderr,"prsocket_test: PR_CreateThread failed\n"); |
michael@0 | 2075 | failed_already=1; |
michael@0 | 2076 | rv = -1; |
michael@0 | 2077 | goto done; |
michael@0 | 2078 | } |
michael@0 | 2079 | DPRINTF(("Created TCP server = 0x%x\n", t)); |
michael@0 | 2080 | thread_count++; |
michael@0 | 2081 | |
michael@0 | 2082 | /* |
michael@0 | 2083 | * wait till the server address is setup |
michael@0 | 2084 | */ |
michael@0 | 2085 | PR_WaitSem(server_sem); |
michael@0 | 2086 | |
michael@0 | 2087 | /* |
michael@0 | 2088 | * Now start a bunch of client threads |
michael@0 | 2089 | */ |
michael@0 | 2090 | |
michael@0 | 2091 | cparamp = PR_NEW(Client_Param); |
michael@0 | 2092 | if (cparamp == NULL) { |
michael@0 | 2093 | fprintf(stderr,"prsocket_test: PR_NEW failed\n"); |
michael@0 | 2094 | failed_already=1; |
michael@0 | 2095 | rv = -1; |
michael@0 | 2096 | goto done; |
michael@0 | 2097 | } |
michael@0 | 2098 | cparamp->server_addr = tcp_server_addr; |
michael@0 | 2099 | cparamp->server_addr.inet.ip = PR_htonl(PR_INADDR_LOOPBACK); |
michael@0 | 2100 | cparamp->exit_mon = mon2; |
michael@0 | 2101 | cparamp->exit_counter = &thread_count; |
michael@0 | 2102 | cparamp->datalen = datalen; |
michael@0 | 2103 | for (i = 0; i < num_transmitfile_clients; i++) { |
michael@0 | 2104 | t = create_new_thread(PR_USER_THREAD, |
michael@0 | 2105 | TransmitFile_Client, (void *) cparamp, |
michael@0 | 2106 | PR_PRIORITY_NORMAL, |
michael@0 | 2107 | PR_LOCAL_THREAD, |
michael@0 | 2108 | PR_UNJOINABLE_THREAD, |
michael@0 | 2109 | 0, i); |
michael@0 | 2110 | if (t == NULL) { |
michael@0 | 2111 | fprintf(stderr,"prsocket_test: PR_CreateThread failed\n"); |
michael@0 | 2112 | rv = -1; |
michael@0 | 2113 | failed_already=1; |
michael@0 | 2114 | goto done; |
michael@0 | 2115 | } |
michael@0 | 2116 | DPRINTF(("Created TransmitFile client = 0x%lx\n", t)); |
michael@0 | 2117 | thread_count++; |
michael@0 | 2118 | } |
michael@0 | 2119 | /* Wait for server and client threads to exit */ |
michael@0 | 2120 | while (thread_count) { |
michael@0 | 2121 | PR_Wait(mon2, PR_INTERVAL_NO_TIMEOUT); |
michael@0 | 2122 | DPRINTF(("Socket_Misc_Test - thread_count = %d\n", thread_count)); |
michael@0 | 2123 | } |
michael@0 | 2124 | PR_ExitMonitor(mon2); |
michael@0 | 2125 | done: |
michael@0 | 2126 | if (buf) { |
michael@0 | 2127 | PR_DELETE(buf); |
michael@0 | 2128 | } |
michael@0 | 2129 | #if defined(XP_UNIX) && !defined(SYMBIAN) |
michael@0 | 2130 | munmap((char*)small_file_addr, SMALL_FILE_SIZE); |
michael@0 | 2131 | munmap((char*)large_file_addr, LARGE_FILE_SIZE); |
michael@0 | 2132 | #endif |
michael@0 | 2133 | PR_Close(small_file_fd); |
michael@0 | 2134 | PR_Close(large_file_fd); |
michael@0 | 2135 | if ((PR_Delete(SMALL_FILE_NAME)) == PR_FAILURE) { |
michael@0 | 2136 | fprintf(stderr,"prsocket_test: failed to unlink file %s\n", |
michael@0 | 2137 | SMALL_FILE_NAME); |
michael@0 | 2138 | failed_already=1; |
michael@0 | 2139 | } |
michael@0 | 2140 | if ((PR_Delete(LARGE_FILE_NAME)) == PR_FAILURE) { |
michael@0 | 2141 | fprintf(stderr,"prsocket_test: failed to unlink file %s\n", |
michael@0 | 2142 | LARGE_FILE_NAME); |
michael@0 | 2143 | failed_already=1; |
michael@0 | 2144 | } |
michael@0 | 2145 | if ((PR_RmDir(TEST_DIR)) == PR_FAILURE) { |
michael@0 | 2146 | fprintf(stderr,"prsocket_test failed to rmdir %s: (%ld, %ld)\n", |
michael@0 | 2147 | TEST_DIR, PR_GetError(), PR_GetOSError()); |
michael@0 | 2148 | failed_already=1; |
michael@0 | 2149 | } |
michael@0 | 2150 | |
michael@0 | 2151 | printf("%-29s%s","Socket_Misc_Test",":"); |
michael@0 | 2152 | printf("%2d Server %2d Clients\n",1, num_transmitfile_clients); |
michael@0 | 2153 | printf("%30s Sizes of Transmitted Files - %4d KB, %2d MB \n",":", |
michael@0 | 2154 | SMALL_FILE_SIZE/1024, LARGE_FILE_SIZE/(1024 * 1024)); |
michael@0 | 2155 | |
michael@0 | 2156 | |
michael@0 | 2157 | return rv; |
michael@0 | 2158 | } |
michael@0 | 2159 | /************************************************************************/ |
michael@0 | 2160 | |
michael@0 | 2161 | /* |
michael@0 | 2162 | * Test Socket NSPR APIs |
michael@0 | 2163 | */ |
michael@0 | 2164 | |
michael@0 | 2165 | int main(int argc, char **argv) |
michael@0 | 2166 | { |
michael@0 | 2167 | /* |
michael@0 | 2168 | * -d debug mode |
michael@0 | 2169 | */ |
michael@0 | 2170 | |
michael@0 | 2171 | PLOptStatus os; |
michael@0 | 2172 | PLOptState *opt = PL_CreateOptState(argc, argv, "d"); |
michael@0 | 2173 | while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) |
michael@0 | 2174 | { |
michael@0 | 2175 | if (PL_OPT_BAD == os) continue; |
michael@0 | 2176 | switch (opt->option) |
michael@0 | 2177 | { |
michael@0 | 2178 | case 'd': /* debug mode */ |
michael@0 | 2179 | _debug_on = 1; |
michael@0 | 2180 | break; |
michael@0 | 2181 | default: |
michael@0 | 2182 | break; |
michael@0 | 2183 | } |
michael@0 | 2184 | } |
michael@0 | 2185 | PL_DestroyOptState(opt); |
michael@0 | 2186 | |
michael@0 | 2187 | PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); |
michael@0 | 2188 | PR_STDIO_INIT(); |
michael@0 | 2189 | |
michael@0 | 2190 | PR_SetConcurrency(4); |
michael@0 | 2191 | |
michael@0 | 2192 | emuSendFileIdentity = PR_GetUniqueIdentity("Emulated SendFile"); |
michael@0 | 2193 | emuSendFileMethods = *PR_GetDefaultIOMethods(); |
michael@0 | 2194 | emuSendFileMethods.transmitfile = emu_TransmitFile; |
michael@0 | 2195 | emuSendFileMethods.sendfile = emu_SendFile; |
michael@0 | 2196 | |
michael@0 | 2197 | /* |
michael@0 | 2198 | * run client-server test with TCP, Ipv4-Ipv4 |
michael@0 | 2199 | */ |
michael@0 | 2200 | printf("TCP Client/Server Test - IPv4/Ipv4\n"); |
michael@0 | 2201 | if (TCP_Socket_Client_Server_Test() < 0) { |
michael@0 | 2202 | printf("TCP_Socket_Client_Server_Test failed\n"); |
michael@0 | 2203 | goto done; |
michael@0 | 2204 | } else |
michael@0 | 2205 | printf("TCP_Socket_Client_Server_Test Passed\n"); |
michael@0 | 2206 | /* |
michael@0 | 2207 | * client-server test, Ipv6-Ipv4 |
michael@0 | 2208 | */ |
michael@0 | 2209 | client_domain = PR_AF_INET6; |
michael@0 | 2210 | printf("TCP Client/Server Test - IPv6/Ipv4\n"); |
michael@0 | 2211 | if (TCP_Socket_Client_Server_Test() < 0) { |
michael@0 | 2212 | printf("TCP_Socket_Client_Server_Test failed\n"); |
michael@0 | 2213 | goto done; |
michael@0 | 2214 | } else |
michael@0 | 2215 | printf("TCP_Socket_Client_Server_Test Passed\n"); |
michael@0 | 2216 | /* |
michael@0 | 2217 | * client-server test, Ipv4-Ipv6 |
michael@0 | 2218 | */ |
michael@0 | 2219 | client_domain = PR_AF_INET; |
michael@0 | 2220 | server_domain = PR_AF_INET6; |
michael@0 | 2221 | printf("TCP Client/Server Test - IPv4/Ipv6\n"); |
michael@0 | 2222 | if (TCP_Socket_Client_Server_Test() < 0) { |
michael@0 | 2223 | printf("TCP_Socket_Client_Server_Test failed\n"); |
michael@0 | 2224 | goto done; |
michael@0 | 2225 | } else |
michael@0 | 2226 | printf("TCP_Socket_Client_Server_Test Passed\n"); |
michael@0 | 2227 | /* |
michael@0 | 2228 | * client-server test, Ipv6-Ipv6 |
michael@0 | 2229 | */ |
michael@0 | 2230 | client_domain = PR_AF_INET6; |
michael@0 | 2231 | server_domain = PR_AF_INET6; |
michael@0 | 2232 | printf("TCP Client/Server Test - IPv6/Ipv6\n"); |
michael@0 | 2233 | if (TCP_Socket_Client_Server_Test() < 0) { |
michael@0 | 2234 | printf("TCP_Socket_Client_Server_Test failed\n"); |
michael@0 | 2235 | goto done; |
michael@0 | 2236 | } else |
michael@0 | 2237 | printf("TCP_Socket_Client_Server_Test Passed\n"); |
michael@0 | 2238 | test_cancelio = 0; |
michael@0 | 2239 | |
michael@0 | 2240 | #if defined(SYMBIAN) && !defined(__WINSCW__) |
michael@0 | 2241 | /* UDP tests only run on Symbian devices but not emulator */ |
michael@0 | 2242 | /* |
michael@0 | 2243 | * run client-server test with UDP, IPv4/IPv4 |
michael@0 | 2244 | */ |
michael@0 | 2245 | printf("UDP Client/Server Test - IPv4/Ipv4\n"); |
michael@0 | 2246 | client_domain = PR_AF_INET; |
michael@0 | 2247 | server_domain = PR_AF_INET; |
michael@0 | 2248 | if (UDP_Socket_Client_Server_Test() < 0) { |
michael@0 | 2249 | printf("UDP_Socket_Client_Server_Test failed\n"); |
michael@0 | 2250 | goto done; |
michael@0 | 2251 | } else |
michael@0 | 2252 | printf("UDP_Socket_Client_Server_Test Passed\n"); |
michael@0 | 2253 | /* |
michael@0 | 2254 | * run client-server test with UDP, IPv6/IPv4 |
michael@0 | 2255 | */ |
michael@0 | 2256 | printf("UDP Client/Server Test - IPv6/Ipv4\n"); |
michael@0 | 2257 | client_domain = PR_AF_INET6; |
michael@0 | 2258 | server_domain = PR_AF_INET; |
michael@0 | 2259 | if (UDP_Socket_Client_Server_Test() < 0) { |
michael@0 | 2260 | printf("UDP_Socket_Client_Server_Test failed\n"); |
michael@0 | 2261 | goto done; |
michael@0 | 2262 | } else |
michael@0 | 2263 | printf("UDP_Socket_Client_Server_Test Passed\n"); |
michael@0 | 2264 | /* |
michael@0 | 2265 | * run client-server test with UDP,IPv4-IPv6 |
michael@0 | 2266 | */ |
michael@0 | 2267 | printf("UDP Client/Server Test - IPv4/Ipv6\n"); |
michael@0 | 2268 | client_domain = PR_AF_INET; |
michael@0 | 2269 | server_domain = PR_AF_INET6; |
michael@0 | 2270 | if (UDP_Socket_Client_Server_Test() < 0) { |
michael@0 | 2271 | printf("UDP_Socket_Client_Server_Test failed\n"); |
michael@0 | 2272 | goto done; |
michael@0 | 2273 | } else |
michael@0 | 2274 | printf("UDP_Socket_Client_Server_Test Passed\n"); |
michael@0 | 2275 | /* |
michael@0 | 2276 | * run client-server test with UDP,IPv6-IPv6 |
michael@0 | 2277 | */ |
michael@0 | 2278 | printf("UDP Client/Server Test - IPv6/Ipv6\n"); |
michael@0 | 2279 | client_domain = PR_AF_INET6; |
michael@0 | 2280 | server_domain = PR_AF_INET6; |
michael@0 | 2281 | if (UDP_Socket_Client_Server_Test() < 0) { |
michael@0 | 2282 | printf("UDP_Socket_Client_Server_Test failed\n"); |
michael@0 | 2283 | goto done; |
michael@0 | 2284 | } else |
michael@0 | 2285 | printf("UDP_Socket_Client_Server_Test Passed\n"); |
michael@0 | 2286 | #endif |
michael@0 | 2287 | |
michael@0 | 2288 | /* |
michael@0 | 2289 | * Misc socket tests - including transmitfile, etc. |
michael@0 | 2290 | */ |
michael@0 | 2291 | |
michael@0 | 2292 | /* File transmission test can not be done in Symbian OS because of |
michael@0 | 2293 | * large file's size and the incomplete mmap() implementation. */ |
michael@0 | 2294 | #if !defined(WIN16) && !defined(SYMBIAN) |
michael@0 | 2295 | /* |
michael@0 | 2296 | ** The 'transmit file' test does not run because |
michael@0 | 2297 | ** transmit file is not implemented in NSPR yet. |
michael@0 | 2298 | ** |
michael@0 | 2299 | */ |
michael@0 | 2300 | if (Socket_Misc_Test() < 0) { |
michael@0 | 2301 | printf("Socket_Misc_Test failed\n"); |
michael@0 | 2302 | failed_already=1; |
michael@0 | 2303 | goto done; |
michael@0 | 2304 | } else |
michael@0 | 2305 | printf("Socket_Misc_Test passed\n"); |
michael@0 | 2306 | |
michael@0 | 2307 | /* |
michael@0 | 2308 | * run client-server test with TCP again to test |
michael@0 | 2309 | * recycling used sockets from PR_TransmitFile(). |
michael@0 | 2310 | */ |
michael@0 | 2311 | if (TCP_Socket_Client_Server_Test() < 0) { |
michael@0 | 2312 | printf("TCP_Socket_Client_Server_Test failed\n"); |
michael@0 | 2313 | goto done; |
michael@0 | 2314 | } else |
michael@0 | 2315 | printf("TCP_Socket_Client_Server_Test Passed\n"); |
michael@0 | 2316 | #endif |
michael@0 | 2317 | |
michael@0 | 2318 | done: |
michael@0 | 2319 | PR_Cleanup(); |
michael@0 | 2320 | if (failed_already) return 1; |
michael@0 | 2321 | else return 0; |
michael@0 | 2322 | } |