nsprpub/pr/tests/prpoll.c

Wed, 31 Dec 2014 06:55:46 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:55:46 +0100
changeset 1
ca08bd8f51b2
permissions
-rw-r--r--

Added tag TORBROWSER_REPLICA for changeset 6474c204b198

     1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 #ifdef WIN32
     7 #include <windows.h>
     8 #endif
    10 #ifdef XP_UNIX
    11 #include <unistd.h>  /* for close() */
    12 #endif
    14 #include "prinit.h"
    15 #include "prio.h"
    16 #include "prlog.h"
    17 #include "prprf.h"
    18 #include "prnetdb.h"
    20 #include "private/pprio.h"
    22 #define CLIENT_LOOPS	5
    23 #define BUF_SIZE		128
    25 #include <stdio.h>
    26 #include <string.h>
    27 #include <stdlib.h>
    29 #ifdef WINCE
    31 int main(int argc, char **argv)
    32 {
    33     fprintf(stderr, "Invalid/Broken Test for WinCE/WinMobile\n");
    34     exit(1);
    35 }
    37 #else
    39 static void
    40 clientThreadFunc(void *arg)
    41 {
    42     PRUint16 port = (PRUint16) arg;
    43     PRFileDesc *sock;
    44     PRNetAddr addr;
    45     char buf[BUF_SIZE];
    46     int i;
    48     addr.inet.family = PR_AF_INET;
    49     addr.inet.port = PR_htons(port);
    50     addr.inet.ip = PR_htonl(PR_INADDR_LOOPBACK);
    51     PR_snprintf(buf, sizeof(buf), "%hu", port);
    53     for (i = 0; i < 5; i++) {
    54 	sock = PR_NewTCPSocket();
    55         PR_Connect(sock, &addr, PR_INTERVAL_NO_TIMEOUT);
    57 	PR_Write(sock, buf, sizeof(buf));
    58 	PR_Close(sock);
    59     }
    60 }
    62 int main(int argc, char **argv)
    63 {
    64     PRFileDesc *listenSock1, *listenSock2;
    65     PRFileDesc *badFD;
    66     PRUint16 listenPort1, listenPort2;
    67     PRNetAddr addr;
    68     char buf[BUF_SIZE];
    69     PRThread *clientThread;
    70     PRPollDesc pds0[10], pds1[10], *pds, *other_pds;
    71     PRIntn npds;
    72     PRInt32 retVal;
    73     PRInt32 rv;
    74     PROsfd sd;
    75     struct sockaddr_in saddr;
    76     PRIntn saddr_len;
    77     PRUint16 listenPort3;
    78     PRFileDesc *socket_poll_fd;
    79     PRIntn i, j;
    81     PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
    82     PR_STDIO_INIT();
    84     printf("This program tests PR_Poll with sockets.\n");
    85     printf("Timeout, error reporting, and normal operation are tested.\n\n");
    87     /* Create two listening sockets */
    88     if ((listenSock1 = PR_NewTCPSocket()) == NULL) {
    89 	fprintf(stderr, "Can't create a new TCP socket\n");
    90 	exit(1);
    91     }
    92     addr.inet.family = PR_AF_INET;
    93     addr.inet.ip = PR_htonl(PR_INADDR_ANY);
    94     addr.inet.port = PR_htons(0);
    95     if (PR_Bind(listenSock1, &addr) == PR_FAILURE) {
    96 	fprintf(stderr, "Can't bind socket\n");
    97 	exit(1);
    98     }
    99     if (PR_GetSockName(listenSock1, &addr) == PR_FAILURE) {
   100 	fprintf(stderr, "PR_GetSockName failed\n");
   101 	exit(1);
   102     }
   103     listenPort1 = PR_ntohs(addr.inet.port);
   104     if (PR_Listen(listenSock1, 5) == PR_FAILURE) {
   105 	fprintf(stderr, "Can't listen on a socket\n");
   106 	exit(1);
   107     }
   109     if ((listenSock2  = PR_NewTCPSocket()) == NULL) {
   110 	fprintf(stderr, "Can't create a new TCP socket\n");
   111 	exit(1);
   112     }
   113     addr.inet.family = PR_AF_INET;
   114     addr.inet.ip = PR_htonl(PR_INADDR_ANY);
   115     addr.inet.port = PR_htons(0);
   116     if (PR_Bind(listenSock2, &addr) == PR_FAILURE) {
   117 	fprintf(stderr, "Can't bind socket\n");
   118 	exit(1);
   119     }
   120     if (PR_GetSockName(listenSock2, &addr) == PR_FAILURE) {
   121 	fprintf(stderr, "PR_GetSockName failed\n");
   122 	exit(1);
   123     }
   124     listenPort2 = PR_ntohs(addr.inet.port);
   125     if (PR_Listen(listenSock2, 5) == PR_FAILURE) {
   126 	fprintf(stderr, "Can't listen on a socket\n");
   127 	exit(1);
   128     }
   129     /* Set up the poll descriptor array */
   130     pds = pds0;
   131     other_pds = pds1;
   132     memset(pds, 0, sizeof(pds));
   133 	npds = 0;
   134     pds[npds].fd = listenSock1;
   135     pds[npds].in_flags = PR_POLL_READ;
   136 	npds++;
   137     pds[npds].fd = listenSock2;
   138     pds[npds].in_flags = PR_POLL_READ;
   139 	npds++;
   141 	sd = socket(AF_INET, SOCK_STREAM, 0);
   142 	PR_ASSERT(sd >= 0);
   143 	memset((char *) &saddr, 0, sizeof(saddr));
   144 	saddr.sin_family = AF_INET;
   145 	saddr.sin_addr.s_addr = htonl(INADDR_ANY);
   146 	saddr.sin_port = htons(0);
   148 	rv = bind(sd, (struct sockaddr *)&saddr, sizeof(saddr));
   149 	PR_ASSERT(rv == 0);
   150 	saddr_len = sizeof(saddr);
   151 	rv = getsockname(sd, (struct sockaddr *) &saddr, &saddr_len);
   152 	PR_ASSERT(rv == 0);
   153     listenPort3 = ntohs(saddr.sin_port);
   155 	rv = listen(sd, 5);
   156 	PR_ASSERT(rv == 0);
   157     pds[npds].fd = socket_poll_fd = PR_CreateSocketPollFd(sd);
   158 	PR_ASSERT(pds[npds].fd);
   159     pds[npds].in_flags = PR_POLL_READ;
   160     npds++;
   161     PR_snprintf(buf, sizeof(buf),
   162 	    "The server thread is listening on ports %hu, %hu and %hu\n\n",
   163 	    listenPort1, listenPort2, listenPort3);
   164     printf("%s", buf);
   166     /* Testing timeout */
   167     printf("PR_Poll should time out in 5 seconds\n");
   168     retVal = PR_Poll(pds, npds, PR_SecondsToInterval(5));
   169     if (retVal != 0) {
   170 	PR_snprintf(buf, sizeof(buf),
   171 		"PR_Poll should time out and return 0, but it returns %ld\n",
   172 		retVal);
   173 	fprintf(stderr, "%s", buf);
   174 	exit(1);
   175     }
   176     printf("PR_Poll timed out.  Test passed.\n\n");
   178     /* Testing bad fd */
   179     printf("PR_Poll should detect a bad file descriptor\n");
   180     if ((badFD = PR_NewTCPSocket()) == NULL) {
   181 	fprintf(stderr, "Can't create a TCP socket\n");
   182 	exit(1);
   183     }
   185     pds[npds].fd = badFD;
   186     pds[npds].in_flags = PR_POLL_READ;
   187     npds++;
   188     PR_Close(badFD);  /* make the fd bad */
   189 #if 0
   190     retVal = PR_Poll(pds, npds, PR_INTERVAL_NO_TIMEOUT);
   191     if (retVal != 1 || (unsigned short) pds[2].out_flags != PR_POLL_NVAL) {
   192 	fprintf(stderr, "Failed to detect the bad fd: "
   193 		"PR_Poll returns %d, out_flags is 0x%hx\n",
   194 		retVal, pds[npds - 1].out_flags);
   195 	exit(1);
   196     }
   197     printf("PR_Poll detected the bad fd.  Test passed.\n\n");
   198 #endif
   199     npds--;
   201     clientThread = PR_CreateThread(PR_USER_THREAD,
   202 	    clientThreadFunc, (void *) listenPort1,
   203 	    PR_PRIORITY_NORMAL, PR_LOCAL_THREAD,
   204 	    PR_UNJOINABLE_THREAD, 0);
   205     if (clientThread == NULL) {
   206 	fprintf(stderr, "can't create thread\n");
   207 	exit(1);
   208     }
   210     clientThread = PR_CreateThread(PR_USER_THREAD,
   211 	    clientThreadFunc, (void *) listenPort2,
   212 	    PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
   213 	    PR_UNJOINABLE_THREAD, 0);
   214     if (clientThread == NULL) {
   215 	fprintf(stderr, "can't create thread\n");
   216 	exit(1);
   217     }
   219     clientThread = PR_CreateThread(PR_USER_THREAD,
   220 	    clientThreadFunc, (void *) listenPort3,
   221 	    PR_PRIORITY_NORMAL, PR_GLOBAL_BOUND_THREAD,
   222 	    PR_UNJOINABLE_THREAD, 0);
   223     if (clientThread == NULL) {
   224 	fprintf(stderr, "can't create thread\n");
   225 	exit(1);
   226     }
   229     printf("Three client threads are created.  Each of them will\n");
   230     printf("send data to one of the three ports the server is listening on.\n");
   231     printf("The data they send is the port number.  Each of them send\n");
   232     printf("the data five times, so you should see ten lines below,\n");
   233     printf("interleaved in an arbitrary order.\n");
   235     /* 30 events total */
   236     i = 0;
   237     while (i < 30) {
   238 		PRPollDesc *tmp;
   239 		int nextIndex;
   240 		int nEvents = 0;
   242 		retVal = PR_Poll(pds, npds, PR_INTERVAL_NO_TIMEOUT);
   243 		PR_ASSERT(retVal != 0);  /* no timeout */
   244 		if (retVal == -1) {
   245 			fprintf(stderr, "PR_Poll failed\n");
   246 			exit(1);
   247 		}
   249 		nextIndex = 3;
   250 		/* the three listening sockets */
   251 		for (j = 0; j < 3; j++) {
   252 			other_pds[j] = pds[j];
   253 			PR_ASSERT((pds[j].out_flags & PR_POLL_WRITE) == 0
   254 				&& (pds[j].out_flags & PR_POLL_EXCEPT) == 0);
   255 			if (pds[j].out_flags & PR_POLL_READ) {
   256 				PRFileDesc *sock;
   258 				nEvents++;
   259 				if (j == 2) {
   260 					PROsfd newsd;
   261 					newsd = accept(PR_FileDesc2NativeHandle(pds[j].fd), NULL, 0);
   262 					if (newsd == -1) {
   263 						fprintf(stderr, "accept() failed\n");
   264 						exit(1);
   265 					}
   266 					other_pds[nextIndex].fd  = PR_CreateSocketPollFd(newsd);
   267 					PR_ASSERT(other_pds[nextIndex].fd);
   268 					other_pds[nextIndex].in_flags = PR_POLL_READ;
   269 				} else {
   270 					sock = PR_Accept(pds[j].fd, NULL, PR_INTERVAL_NO_TIMEOUT);
   271 					if (sock == NULL) {
   272 						fprintf(stderr, "PR_Accept() failed\n");
   273 						exit(1);
   274 					}
   275 					other_pds[nextIndex].fd = sock;
   276 					other_pds[nextIndex].in_flags = PR_POLL_READ;
   277 				}
   278 				nextIndex++;
   279 			} else if (pds[j].out_flags & PR_POLL_ERR) {
   280 				fprintf(stderr, "PR_Poll() indicates that an fd has error\n");
   281 				exit(1);
   282 			} else if (pds[j].out_flags & PR_POLL_NVAL) {
   283 				fprintf(stderr, "PR_Poll() indicates that fd %d is invalid\n",
   284 					PR_FileDesc2NativeHandle(pds[j].fd));
   285 				exit(1);
   286 			}
   287 		}
   289 		for (j = 3; j < npds; j++) {
   290 			PR_ASSERT((pds[j].out_flags & PR_POLL_WRITE) == 0
   291 				&& (pds[j].out_flags & PR_POLL_EXCEPT) == 0);
   292 			if (pds[j].out_flags & PR_POLL_READ) {
   293 				PRInt32 nBytes;
   295 				nEvents++;
   296 				/* XXX: This call is a hack and should be fixed */
   297 				if (PR_GetDescType(pds[j].fd) == (PRDescType) 0) {
   298 					nBytes = recv(PR_FileDesc2NativeHandle(pds[j].fd), buf,
   299 										sizeof(buf), 0);
   300 					if (nBytes == -1) {
   301 						fprintf(stderr, "recv() failed\n");
   302 						exit(1);
   303 					}
   304 					printf("Server read %d bytes from native fd %d\n",nBytes,
   305 										PR_FileDesc2NativeHandle(pds[j].fd));
   306 #ifdef WIN32
   307 					closesocket((SOCKET)PR_FileDesc2NativeHandle(pds[j].fd));
   308 #else
   309 					close(PR_FileDesc2NativeHandle(pds[j].fd));
   310 #endif
   311 					PR_DestroySocketPollFd(pds[j].fd);
   312 				} else {
   313 					nBytes = PR_Read(pds[j].fd, buf, sizeof(buf));
   314 					if (nBytes == -1) {
   315 						fprintf(stderr, "PR_Read() failed\n");
   316 						exit(1);
   317 					}
   318 					PR_Close(pds[j].fd);
   319 				}
   320 				/* Just to be safe */
   321 				buf[BUF_SIZE - 1] = '\0';
   322 				printf("The server received \"%s\" from a client\n", buf);
   323 			} else if (pds[j].out_flags & PR_POLL_ERR) {
   324 				fprintf(stderr, "PR_Poll() indicates that an fd has error\n");
   325 				exit(1);
   326 			} else if (pds[j].out_flags & PR_POLL_NVAL) {
   327 				fprintf(stderr, "PR_Poll() indicates that an fd is invalid\n");
   328 				exit(1);
   329 			} else {
   330 				other_pds[nextIndex] = pds[j];
   331 				nextIndex++;
   332 			}
   333 		}
   335 		PR_ASSERT(retVal == nEvents);
   336 		/* swap */
   337 		tmp = pds;
   338 		pds = other_pds;
   339 		other_pds = tmp;
   340 		npds = nextIndex;
   341 		i += nEvents;
   342     }
   343     PR_DestroySocketPollFd(socket_poll_fd);
   345     printf("All tests finished\n");
   346     PR_Cleanup();
   347     return 0;
   348 }
   351 #endif   /* ifdef WINCE */

mercurial