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/. */
5 
6 /***********************************************************************
7 **
8 ** Name: prpoll_err.c
9 **
10 ** Description: This program tests PR_Poll with sockets.
11 **              error reporting operation is tested
12 **
13 ** Modification History:
14 ** 19-May-97 AGarcia- Converted the test to accomodate the debug_mode flag.
15 **           The debug mode will print all of the printfs associated with this test.
16 **           The regress mode will be the default mode. Since the regress tool limits
17 **           the output to a one line status:PASS or FAIL,all of the printf statements
18 **           have been handled with an if (debug_mode) statement.
19 ** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to
20 **          recognize the return code from tha main program.
21 ***********************************************************************/
22 
23 /***********************************************************************
24 ** Includes
25 ***********************************************************************/
26 /* Used to get the command line option */
27 #include "plgetopt.h"
28 
29 #include "primpl.h"
30 
31 #include <stdio.h>
32 #include <string.h>
33 #include <stdlib.h>
34 
35 PRIntn failed_already=0;
36 PRIntn debug_mode;
37 
38 static void
ClientThreadFunc(void * arg)39 ClientThreadFunc(void *arg)
40 {
41     PRFileDesc *badFD = (PRFileDesc *) arg;
42     /*
43      * Make the fd invalid
44      */
45 #if defined(XP_UNIX)
46     close(PR_FileDesc2NativeHandle(badFD));
47 #elif defined(XP_OS2)
48     soclose(PR_FileDesc2NativeHandle(badFD));
49 #elif defined(WIN32) || defined(WIN16)
50     closesocket(PR_FileDesc2NativeHandle(badFD));
51 #else
52 #error "Unknown architecture"
53 #endif
54 }
55 
main(int argc,char ** argv)56 int main(int argc, char **argv)
57 {
58     PRFileDesc *listenSock1, *listenSock2;
59     PRFileDesc *badFD;
60     PRUint16 listenPort1, listenPort2;
61     PRNetAddr addr;
62     char buf[128];
63     PRPollDesc pds0[10], pds1[10], *pds, *other_pds;
64     PRIntn npds;
65     PRInt32 retVal;
66 
67     /* The command line argument: -d is used to determine if the test is being run
68     in debug mode. The regress tool requires only one line output:PASS or FAIL.
69     All of the printfs associated with this test has been handled with a if (debug_mode)
70     test.
71     Usage: test_name -d
72     */
73     PLOptStatus os;
74     PLOptState *opt = PL_CreateOptState(argc, argv, "d:");
75     while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
76     {
77         if (PL_OPT_BAD == os) {
78             continue;
79         }
80         switch (opt->option)
81         {
82             case 'd':  /* debug mode */
83                 debug_mode = 1;
84                 break;
85             default:
86                 break;
87         }
88     }
89     PL_DestroyOptState(opt);
90 
91     /* main test */
92 
93     PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
94     PR_STDIO_INIT();
95 
96     if (debug_mode) {
97         printf("This program tests PR_Poll with sockets.\n");
98         printf("error reporting is  tested.\n\n");
99     }
100 
101     /* Create two listening sockets */
102     if ((listenSock1 = PR_NewTCPSocket()) == NULL) {
103         fprintf(stderr, "Can't create a new TCP socket\n");
104         failed_already=1;
105         goto exit_now;
106     }
107     addr.inet.family = AF_INET;
108     addr.inet.ip = PR_htonl(INADDR_ANY);
109     addr.inet.port = PR_htons(0);
110     if (PR_Bind(listenSock1, &addr) == PR_FAILURE) {
111         fprintf(stderr, "Can't bind socket\n");
112         failed_already=1;
113         goto exit_now;
114     }
115     if (PR_GetSockName(listenSock1, &addr) == PR_FAILURE) {
116         fprintf(stderr, "PR_GetSockName failed\n");
117         failed_already=1;
118         goto exit_now;
119     }
120     listenPort1 = PR_ntohs(addr.inet.port);
121     if (PR_Listen(listenSock1, 5) == PR_FAILURE) {
122         fprintf(stderr, "Can't listen on a socket\n");
123         failed_already=1;
124         goto exit_now;
125     }
126 
127     if ((listenSock2  = PR_NewTCPSocket()) == NULL) {
128         fprintf(stderr, "Can't create a new TCP socket\n");
129         failed_already=1;
130         goto exit_now;
131     }
132     addr.inet.family = AF_INET;
133     addr.inet.ip = PR_htonl(INADDR_ANY);
134     addr.inet.port = PR_htons(0);
135     if (PR_Bind(listenSock2, &addr) == PR_FAILURE) {
136         fprintf(stderr, "Can't bind socket\n");
137         failed_already=1;
138         goto exit_now;
139     }
140     if (PR_GetSockName(listenSock2, &addr) == PR_FAILURE) {
141         fprintf(stderr, "PR_GetSockName failed\n");
142         failed_already=1;
143         goto exit_now;
144     }
145     listenPort2 = PR_ntohs(addr.inet.port);
146     if (PR_Listen(listenSock2, 5) == PR_FAILURE) {
147         fprintf(stderr, "Can't listen on a socket\n");
148         failed_already=1;
149         goto exit_now;
150     }
151     PR_snprintf(buf, sizeof(buf),
152                 "The server thread is listening on ports %hu and %hu\n\n",
153                 listenPort1, listenPort2);
154     if (debug_mode) {
155         printf("%s", buf);
156     }
157 
158     /* Set up the poll descriptor array */
159     pds = pds0;
160     other_pds = pds1;
161     memset(pds, 0, sizeof(pds));
162     pds[0].fd = listenSock1;
163     pds[0].in_flags = PR_POLL_READ;
164     pds[1].fd = listenSock2;
165     pds[1].in_flags = PR_POLL_READ;
166     npds = 2;
167 
168 
169     /* Testing bad fd */
170     if (debug_mode) {
171         printf("PR_Poll should detect a bad file descriptor\n");
172     }
173     if ((badFD = PR_NewTCPSocket()) == NULL) {
174         fprintf(stderr, "Can't create a TCP socket\n");
175         goto exit_now;
176     }
177 
178     pds[2].fd = badFD;
179     pds[2].in_flags = PR_POLL_READ;
180     npds = 3;
181 
182     if (PR_CreateThread(PR_USER_THREAD, ClientThreadFunc,
183                         badFD, PR_PRIORITY_NORMAL, PR_LOCAL_THREAD,
184                         PR_UNJOINABLE_THREAD, 0) == NULL) {
185         fprintf(stderr, "cannot create thread\n");
186         exit(1);
187     }
188 
189     retVal = PR_Poll(pds, npds, PR_INTERVAL_NO_TIMEOUT);
190     if (retVal != 1 || (unsigned short) pds[2].out_flags != PR_POLL_NVAL) {
191         fprintf(stderr, "Failed to detect the bad fd: "
192                 "PR_Poll returns %d, out_flags is 0x%hx\n",
193                 retVal, pds[2].out_flags);
194         failed_already=1;
195         goto exit_now;
196     }
197     if (debug_mode) {
198         printf("PR_Poll detected the bad fd.  Test passed.\n\n");
199     }
200     PR_Cleanup();
201     goto exit_now;
202 exit_now:
203     if(failed_already) {
204         return 1;
205     }
206     else {
207         return 0;
208     }
209 }
210 
211