nsprpub/pr/tests/selct_nm.c

Fri, 16 Jan 2015 04:50:19 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Fri, 16 Jan 2015 04:50:19 +0100
branch
TOR_BUG_9701
changeset 13
44a2da4a2ab2
permissions
-rw-r--r--

Replace accessor implementation with direct member state manipulation, by
request https://trac.torproject.org/projects/tor/ticket/9701#comment:32

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 ** 1997 - Netscape Communications Corporation
michael@0 8 **
michael@0 9 ** Name: prselect_norm.c
michael@0 10 **
michael@0 11 ** Description: tests PR_Select with sockets - Normal operations.
michael@0 12 **
michael@0 13 ** Modification History:
michael@0 14 ** 14-May-97 AGarcia- Converted the test to accomodate the debug_mode flag.
michael@0 15 ** The debug mode will print all of the printfs associated with this test.
michael@0 16 ** The regress mode will be the default mode. Since the regress tool limits
michael@0 17 ** the output to a one line status:PASS or FAIL,all of the printf statements
michael@0 18 ** have been handled with an if (debug_mode) statement.
michael@0 19 ** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to
michael@0 20 ** recognize the return code from tha main program.
michael@0 21 ***********************************************************************/
michael@0 22
michael@0 23 /***********************************************************************
michael@0 24 ** Includes
michael@0 25 ***********************************************************************/
michael@0 26 /* Used to get the command line option */
michael@0 27 #include "plgetopt.h"
michael@0 28
michael@0 29 #include "prinit.h"
michael@0 30 #include "prio.h"
michael@0 31 #include "prlog.h"
michael@0 32 #include "prprf.h"
michael@0 33 #include "prerror.h"
michael@0 34 #include "prnetdb.h"
michael@0 35
michael@0 36 #include "obsolete/probslet.h"
michael@0 37
michael@0 38 #include <stdio.h>
michael@0 39 #include <string.h>
michael@0 40 #include <stdlib.h>
michael@0 41
michael@0 42 PRIntn failed_already=0;
michael@0 43 PRIntn debug_mode;
michael@0 44
michael@0 45 static void
michael@0 46 clientThreadFunc(void *arg)
michael@0 47 {
michael@0 48 PRUintn port = (PRUintn) arg;
michael@0 49 PRFileDesc *sock;
michael@0 50 PRNetAddr addr;
michael@0 51 char buf[128];
michael@0 52 int i;
michael@0 53
michael@0 54 addr.inet.family = PR_AF_INET;
michael@0 55 addr.inet.port = PR_htons((PRUint16)port);
michael@0 56 addr.inet.ip = PR_htonl(PR_INADDR_LOOPBACK);
michael@0 57 PR_snprintf(buf, sizeof(buf), "%hu", addr.inet.port);
michael@0 58
michael@0 59 for (i = 0; i < 5; i++) {
michael@0 60 sock = PR_NewTCPSocket();
michael@0 61 PR_Connect(sock, &addr, PR_INTERVAL_NO_TIMEOUT);
michael@0 62 PR_Write(sock, buf, sizeof(buf));
michael@0 63 PR_Close(sock);
michael@0 64 }
michael@0 65 }
michael@0 66
michael@0 67 int main(int argc, char **argv)
michael@0 68 {
michael@0 69 PRFileDesc *listenSock1, *listenSock2;
michael@0 70 PRFileDesc *fds0[10], *fds1[10], **fds, **other_fds;
michael@0 71 PRIntn nfds;
michael@0 72 PRUint16 listenPort1, listenPort2;
michael@0 73 PRNetAddr addr;
michael@0 74 PR_fd_set readFdSet;
michael@0 75 char buf[128];
michael@0 76 PRThread *clientThread;
michael@0 77 PRInt32 retVal;
michael@0 78 PRIntn i, j;
michael@0 79
michael@0 80 /* The command line argument: -d is used to determine if the test is being run
michael@0 81 in debug mode. The regress tool requires only one line output:PASS or FAIL.
michael@0 82 All of the printfs associated with this test has been handled with a if (debug_mode)
michael@0 83 test.
michael@0 84 Usage: test_name -d
michael@0 85 */
michael@0 86 PLOptStatus os;
michael@0 87 PLOptState *opt = PL_CreateOptState(argc, argv, "d:");
michael@0 88 while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
michael@0 89 {
michael@0 90 if (PL_OPT_BAD == os) continue;
michael@0 91 switch (opt->option)
michael@0 92 {
michael@0 93 case 'd': /* debug mode */
michael@0 94 debug_mode = 1;
michael@0 95 break;
michael@0 96 default:
michael@0 97 break;
michael@0 98 }
michael@0 99 }
michael@0 100 PL_DestroyOptState(opt);
michael@0 101
michael@0 102 /* main test */
michael@0 103
michael@0 104 PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
michael@0 105 PR_STDIO_INIT();
michael@0 106
michael@0 107 if (debug_mode) {
michael@0 108 printf("This program tests PR_Select with sockets. \n");
michael@0 109 printf(" Normal operation are tested.\n\n");
michael@0 110 }
michael@0 111
michael@0 112 /* Create two listening sockets */
michael@0 113 if ((listenSock1 = PR_NewTCPSocket()) == NULL) {
michael@0 114 fprintf(stderr, "Can't create a new TCP socket\n");
michael@0 115 failed_already=1;
michael@0 116 goto exit_now;
michael@0 117 }
michael@0 118 addr.inet.family = PR_AF_INET;
michael@0 119 addr.inet.ip = PR_htonl(PR_INADDR_ANY);
michael@0 120 addr.inet.port = PR_htons(0);
michael@0 121 if (PR_Bind(listenSock1, &addr) == PR_FAILURE) {
michael@0 122 fprintf(stderr, "Can't bind socket\n");
michael@0 123 failed_already=1;
michael@0 124 goto exit_now;
michael@0 125 }
michael@0 126 if (PR_GetSockName(listenSock1, &addr) == PR_FAILURE) {
michael@0 127 fprintf(stderr, "PR_GetSockName failed\n");
michael@0 128 failed_already=1;
michael@0 129 goto exit_now;
michael@0 130 }
michael@0 131 listenPort1 = PR_ntohs(addr.inet.port);
michael@0 132 if (PR_Listen(listenSock1, 5) == PR_FAILURE) {
michael@0 133 fprintf(stderr, "Can't listen on a socket\n");
michael@0 134 failed_already=1;
michael@0 135 goto exit_now;
michael@0 136 }
michael@0 137
michael@0 138 if ((listenSock2 = PR_NewTCPSocket()) == NULL) {
michael@0 139 fprintf(stderr, "Can't create a new TCP socket\n");
michael@0 140 failed_already=1;
michael@0 141 goto exit_now;
michael@0 142 }
michael@0 143 addr.inet.family = PR_AF_INET;
michael@0 144 addr.inet.ip = PR_htonl(PR_INADDR_ANY);
michael@0 145 addr.inet.port = PR_htons(0);
michael@0 146 if (PR_Bind(listenSock2, &addr) == PR_FAILURE) {
michael@0 147 fprintf(stderr, "Can't bind socket\n");
michael@0 148 failed_already=1;
michael@0 149 goto exit_now;
michael@0 150 }
michael@0 151 if (PR_GetSockName(listenSock2, &addr) == PR_FAILURE) {
michael@0 152 fprintf(stderr, "PR_GetSockName failed\n");
michael@0 153 failed_already=1;
michael@0 154 goto exit_now;
michael@0 155 }
michael@0 156 listenPort2 = PR_ntohs(addr.inet.port);
michael@0 157 if (PR_Listen(listenSock2, 5) == PR_FAILURE) {
michael@0 158 fprintf(stderr, "Can't listen on a socket\n");
michael@0 159 failed_already=1;
michael@0 160 goto exit_now;
michael@0 161 }
michael@0 162 PR_snprintf(buf, sizeof(buf),
michael@0 163 "The server thread is listening on ports %hu and %hu\n\n",
michael@0 164 listenPort1, listenPort2);
michael@0 165 if (debug_mode) printf("%s", buf);
michael@0 166
michael@0 167 clientThread = PR_CreateThread(PR_USER_THREAD,
michael@0 168 clientThreadFunc, (void *) listenPort1,
michael@0 169 PR_PRIORITY_NORMAL, PR_LOCAL_THREAD,
michael@0 170 PR_UNJOINABLE_THREAD, 0);
michael@0 171 if (clientThread == NULL) {
michael@0 172 fprintf(stderr, "can't create thread\n");
michael@0 173 failed_already=1;
michael@0 174 goto exit_now;
michael@0 175 }
michael@0 176
michael@0 177 clientThread = PR_CreateThread(PR_USER_THREAD,
michael@0 178 clientThreadFunc, (void *) listenPort2,
michael@0 179 PR_PRIORITY_NORMAL, PR_LOCAL_THREAD,
michael@0 180 PR_UNJOINABLE_THREAD, 0);
michael@0 181 if (clientThread == NULL) {
michael@0 182 fprintf(stderr, "can't create thread\n");
michael@0 183 failed_already=1;
michael@0 184 goto exit_now;
michael@0 185 }
michael@0 186
michael@0 187 if (debug_mode) {
michael@0 188 printf("Two client threads are created. Each of them will\n");
michael@0 189 printf("send data to one of the two ports the server is listening on.\n");
michael@0 190 printf("The data they send is the port number. Each of them send\n");
michael@0 191 printf("the data five times, so you should see ten lines below,\n");
michael@0 192 printf("interleaved in an arbitrary order.\n");
michael@0 193 }
michael@0 194 /* set up the fd array */
michael@0 195 fds = fds0;
michael@0 196 other_fds = fds1;
michael@0 197 fds[0] = listenSock1;
michael@0 198 fds[1] = listenSock2;
michael@0 199 nfds = 2;
michael@0 200 /* Set up the fd set */
michael@0 201 PR_FD_ZERO(&readFdSet);
michael@0 202 PR_FD_SET(listenSock1, &readFdSet);
michael@0 203 PR_FD_SET(listenSock2, &readFdSet);
michael@0 204
michael@0 205 /* 20 events total */
michael@0 206 i = 0;
michael@0 207 while (i < 20) {
michael@0 208 PRFileDesc **tmp;
michael@0 209 int nextIndex;
michael@0 210 int nEvents = 0;
michael@0 211
michael@0 212 retVal = PR_Select(0 /* unused */, &readFdSet, NULL, NULL,
michael@0 213 PR_INTERVAL_NO_TIMEOUT);
michael@0 214 PR_ASSERT(retVal != 0); /* no timeout */
michael@0 215 if (retVal == -1) {
michael@0 216 fprintf(stderr, "PR_Select failed (%d, %d)\n", PR_GetError(),
michael@0 217 PR_GetOSError());
michael@0 218 failed_already=1;
michael@0 219 goto exit_now;
michael@0 220 }
michael@0 221
michael@0 222 nextIndex = 2;
michael@0 223 /* the two listening sockets */
michael@0 224 for (j = 0; j < 2; j++) {
michael@0 225 other_fds[j] = fds[j];
michael@0 226 if (PR_FD_ISSET(fds[j], &readFdSet)) {
michael@0 227 PRFileDesc *sock;
michael@0 228
michael@0 229 nEvents++;
michael@0 230 sock = PR_Accept(fds[j], NULL, PR_INTERVAL_NO_TIMEOUT);
michael@0 231 if (sock == NULL) {
michael@0 232 fprintf(stderr, "PR_Accept() failed\n");
michael@0 233 failed_already=1;
michael@0 234 goto exit_now;
michael@0 235 }
michael@0 236 other_fds[nextIndex] = sock;
michael@0 237 PR_FD_SET(sock, &readFdSet);
michael@0 238 nextIndex++;
michael@0 239 }
michael@0 240 PR_FD_SET(fds[j], &readFdSet);
michael@0 241 }
michael@0 242
michael@0 243 for (j = 2; j < nfds; j++) {
michael@0 244 if (PR_FD_ISSET(fds[j], &readFdSet)) {
michael@0 245 PRInt32 nBytes;
michael@0 246
michael@0 247 PR_FD_CLR(fds[j], &readFdSet);
michael@0 248 nEvents++;
michael@0 249 nBytes = PR_Read(fds[j], buf, sizeof(buf));
michael@0 250 if (nBytes == -1) {
michael@0 251 fprintf(stderr, "PR_Read() failed\n");
michael@0 252 failed_already=1;
michael@0 253 goto exit_now;
michael@0 254 }
michael@0 255 /* Just to be safe */
michael@0 256 buf[127] = '\0';
michael@0 257 PR_Close(fds[j]);
michael@0 258 if (debug_mode) printf("The server received \"%s\" from a client\n", buf);
michael@0 259 } else {
michael@0 260 PR_FD_SET(fds[j], &readFdSet);
michael@0 261 other_fds[nextIndex] = fds[j];
michael@0 262 nextIndex++;
michael@0 263 }
michael@0 264 }
michael@0 265
michael@0 266 PR_ASSERT(retVal == nEvents);
michael@0 267 /* swap */
michael@0 268 tmp = fds;
michael@0 269 fds = other_fds;
michael@0 270 other_fds = tmp;
michael@0 271 nfds = nextIndex;
michael@0 272 i += nEvents;
michael@0 273 }
michael@0 274
michael@0 275 if (debug_mode) printf("Test passed\n");
michael@0 276
michael@0 277 PR_Cleanup();
michael@0 278 goto exit_now;
michael@0 279 exit_now:
michael@0 280 if(failed_already)
michael@0 281 return 1;
michael@0 282 else
michael@0 283 return 0;
michael@0 284 }

mercurial