Mercurial > trustbridge > nss-cmake-static
comparison nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_socket.c @ 0:1e5118fa0cb1
This is NSS with a Cmake Buildsyste
To compile a static NSS library for Windows we've used the
Chromium-NSS fork and added a Cmake buildsystem to compile
it statically for Windows. See README.chromium for chromium
changes and README.trustbridge for our modifications.
author | Andre Heinecke <andre.heinecke@intevation.de> |
---|---|
date | Mon, 28 Jul 2014 10:47:06 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:1e5118fa0cb1 |
---|---|
1 /* This Source Code Form is subject to the terms of the Mozilla Public | |
2 * License, v. 2.0. If a copy of the MPL was not distributed with this | |
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | |
4 /* | |
5 * pkix_pl_socket.c | |
6 * | |
7 * Socket Function Definitions | |
8 * | |
9 */ | |
10 | |
11 /* | |
12 * If Socket Tracing is active, messages sent and received will be | |
13 * timestamped and dumped (to stdout) in standard hex-dump format. E.g., | |
14 * | |
15 * 1116612359156140: | |
16 * 28F0: 48 65 6C 6C 6F 2C 20 77 6F 72 6C 64 21 00 Hello, world!. | |
17 * | |
18 * The timestamp is not formatted to be meaningful except as an increasing | |
19 * value of seconds.microseconds, which is good enough to correlate two | |
20 * sides of a message exchange and to figure durations. | |
21 * | |
22 * Code to perform Socket tracing will be compiled in if PKIX_SOCKETTRACE | |
23 * is defined, but that doesn't mean socket tracing is active. Tracing also | |
24 * requires that the Boolean socketTraceFlag is set to PKIX_TRUE. That is | |
25 * the default value, but it can be overridden by using the debugger to | |
26 * change its value -- allowing tracing to be turned on and off at various | |
27 * breakpoints -- or by setting the environment variable SOCKETTRACE. A | |
28 * value of 1 sets socketTraceFlag to PKIX_TRUE (tracing on), and any other | |
29 * value sets socketTraceFlag to PKIX_FALSE (tracing off). The environment | |
30 * value is checked during system initialization. | |
31 */ | |
32 #ifndef BUILD_OPT | |
33 #define PKIX_SOCKETTRACE 1 | |
34 #endif | |
35 | |
36 #ifdef PKIX_SOCKETDEBUG | |
37 #define PKIX_SOCKETTRACE 1 | |
38 #endif | |
39 | |
40 #include "pkix_pl_socket.h" | |
41 | |
42 /* --Private-Socket-Functions---------------------------------- */ | |
43 | |
44 #ifdef PKIX_SOCKETTRACE | |
45 static PKIX_Boolean socketTraceFlag = PKIX_FALSE; | |
46 | |
47 /* | |
48 * FUNCTION: pkix_pl_socket_timestamp | |
49 * DESCRIPTION: | |
50 * | |
51 * This functions prints to stdout the time of day, as obtained from the | |
52 * system function gettimeofday, as seconds.microseconds. Its resolution | |
53 * is whatever the system call provides. | |
54 * | |
55 * PARAMETERS: | |
56 * none | |
57 * THREAD SAFETY: | |
58 * Thread Safe (see Thread Safety definitions in Programmer's Guide) | |
59 * RETURNS: | |
60 * none | |
61 */ | |
62 static void pkix_pl_socket_timestamp() { | |
63 PRInt64 prTime; | |
64 prTime = PR_Now(); | |
65 printf("%lld:\n", prTime); | |
66 } | |
67 | |
68 /* | |
69 * FUNCTION: pkix_pl_socket_hexDigit | |
70 * DESCRIPTION: | |
71 * | |
72 * This functions prints to stdout the byte "byteVal" as two hex digits. | |
73 * | |
74 * PARAMETERS: | |
75 * "byteVal" | |
76 * The value to be printed. | |
77 * THREAD SAFETY: | |
78 * Thread Safe (see Thread Safety definitions in Programmer's Guide) | |
79 * RETURNS: | |
80 * none | |
81 */ | |
82 static void pkix_pl_socket_hexDigit(char byteVal) { | |
83 int n = 0; | |
84 char cHi = '\0'; | |
85 char cLow = '\0'; | |
86 n = ((byteVal >> 4) & 0xf); | |
87 if (n > 9) { | |
88 cHi = (char) ((n - 10) + 'A'); | |
89 } else { | |
90 cHi = (char) (n + '0'); | |
91 } | |
92 n = byteVal & 0xf; | |
93 if (n > 9) { | |
94 cLow = (char) ((n - 10) + 'A'); | |
95 } else { | |
96 cLow = (char) (n + '0'); | |
97 } | |
98 (void) printf("%c%c", cHi, cLow); | |
99 } | |
100 | |
101 /* | |
102 * FUNCTION: pkix_pl_socket_linePrefix | |
103 * DESCRIPTION: | |
104 * | |
105 * This functions prints to stdout the address provided by "addr" as four | |
106 * hexadecimal digits followed by a colon and a space. | |
107 * | |
108 * PARAMETERS: | |
109 * "addr" | |
110 * The address to be printed | |
111 * none | |
112 * THREAD SAFETY: | |
113 * Thread Safe (see Thread Safety definitions in Programmer's Guide) | |
114 * RETURNS: | |
115 * none | |
116 */ | |
117 static void pkix_pl_socket_linePrefix(PKIX_UInt32 addr) { | |
118 pkix_pl_socket_hexDigit((char)((addr >> 8) & 0xff)); | |
119 pkix_pl_socket_hexDigit((char)(addr & 0xff)); | |
120 (void) printf(": "); | |
121 } | |
122 | |
123 /* | |
124 * FUNCTION: pkix_pl_socket_traceLine | |
125 * DESCRIPTION: | |
126 * | |
127 * This functions prints to stdout the sixteen bytes beginning at the | |
128 * address pointed to by "ptr". The bytes are printed as sixteen pairs | |
129 * of hexadecimal characters followed by an ascii interpretation, in which | |
130 * characters from 0x20 to 0x7d are shown as their ascii equivalents, and | |
131 * other values are represented as periods. | |
132 * | |
133 * PARAMETERS: | |
134 * "ptr" | |
135 * The address of the first of the bytes to be printed | |
136 * THREAD SAFETY: | |
137 * Thread Safe (see Thread Safety definitions in Programmer's Guide) | |
138 * RETURNS: | |
139 * none | |
140 */ | |
141 static void pkix_pl_socket_traceLine(char *ptr) { | |
142 PKIX_UInt32 i = 0; | |
143 pkix_pl_socket_linePrefix((PKIX_UInt32)ptr); | |
144 for (i = 0; i < 16; i++) { | |
145 printf(" "); | |
146 pkix_pl_socket_hexDigit(ptr[i]); | |
147 if (i == 7) { | |
148 printf(" "); | |
149 } | |
150 } | |
151 printf(" "); | |
152 for (i = 0; i < 16; i++) { | |
153 if ((ptr[i] < ' ') || (ptr[i] > '}')) { | |
154 printf("."); | |
155 } else { | |
156 printf("%c", ptr[i]); | |
157 } | |
158 } | |
159 printf("\n"); | |
160 } | |
161 | |
162 /* | |
163 * FUNCTION: pkix_pl_socket_tracePartialLine | |
164 * DESCRIPTION: | |
165 * | |
166 * This functions prints to stdout the number of bytes given by "nBytes", | |
167 * beginning at the address pointed to by "ptr". The bytes are printed as | |
168 * pairs of hexadecimal characters followed by an ascii interpretation, in | |
169 * which characters from 0x20 to 0x7d are shown as their ascii equivalents, | |
170 * and other values are represented as periods. | |
171 * | |
172 * PARAMETERS: | |
173 * "ptr" | |
174 * The address of the first of the bytes to be printed | |
175 * "nBytes" | |
176 * The Int32 value giving the number of bytes to be printed. If "nBytes" | |
177 * is greater than sixteen, the results will be unattractive. | |
178 * none | |
179 * THREAD SAFETY: | |
180 * Thread Safe (see Thread Safety definitions in Programmer's Guide) | |
181 * RETURNS: | |
182 * none | |
183 */ | |
184 static void pkix_pl_socket_tracePartialLine(char *ptr, PKIX_UInt32 nBytes) { | |
185 PKIX_UInt32 i = 0; | |
186 if (nBytes > 0) { | |
187 pkix_pl_socket_linePrefix((PKIX_UInt32)ptr); | |
188 } | |
189 for (i = 0; i < nBytes; i++) { | |
190 printf(" "); | |
191 pkix_pl_socket_hexDigit(ptr[i]); | |
192 if (i == 7) { | |
193 printf(" "); | |
194 } | |
195 } | |
196 for (i = nBytes; i < 16; i++) { | |
197 printf(" "); | |
198 if (i == 7) { | |
199 printf(" "); | |
200 } | |
201 } | |
202 printf(" "); | |
203 for (i = 0; i < nBytes; i++) { | |
204 if ((ptr[i] < ' ') || (ptr[i] > '}')) { | |
205 printf("."); | |
206 } else { | |
207 printf("%c", ptr[i]); | |
208 } | |
209 } | |
210 printf("\n"); | |
211 } | |
212 | |
213 /* | |
214 * FUNCTION: pkix_pl_socket_tracebuff | |
215 * DESCRIPTION: | |
216 * | |
217 * This functions prints to stdout the number of bytes given by "nBytes", | |
218 * beginning with the byte pointed to by "buf". The output is preceded by | |
219 * a timestamp, and each group of sixteen (and a remainder, if any) is | |
220 * preceded by its address. The contents are shown in hexadecimal and as | |
221 * ascii characters. If "nBytes" is zero, the timestamp and starting | |
222 * address are displayed. | |
223 * | |
224 * PARAMETERS: | |
225 * "buf" | |
226 * The starting address of the bytes to be printed | |
227 * "nBytes" | |
228 * The number of bytes to be printed | |
229 * THREAD SAFETY: | |
230 * Thread Safe (see Thread Safety definitions in Programmer's Guide) | |
231 * RETURNS: | |
232 * none | |
233 */ | |
234 void pkix_pl_socket_tracebuff(void *buf, PKIX_UInt32 nBytes) { | |
235 PKIX_UInt32 bytesRemaining = nBytes; | |
236 PKIX_UInt32 offset = 0; | |
237 char *bufptr = (char *)buf; | |
238 | |
239 if (socketTraceFlag == PKIX_FALSE) return; | |
240 | |
241 pkix_pl_socket_timestamp(); | |
242 /* | |
243 * Special case: if called with length of zero, just do address | |
244 */ | |
245 if (nBytes == 0) { | |
246 pkix_pl_socket_linePrefix((PKIX_UInt32)buf); | |
247 printf("\n"); | |
248 } else { | |
249 while (bytesRemaining >= 16) { | |
250 pkix_pl_socket_traceLine(&bufptr[offset]); | |
251 bytesRemaining -= 16; | |
252 offset += 16; | |
253 } | |
254 pkix_pl_socket_tracePartialLine | |
255 (&bufptr[offset], bytesRemaining); | |
256 } | |
257 } | |
258 | |
259 #endif | |
260 | |
261 /* | |
262 * FUNCTION: pkix_pl_Socket_SetNonBlocking | |
263 * DESCRIPTION: | |
264 * | |
265 * This functions sets the socket represented by the PRFileDesc "fileDesc" | |
266 * to nonblocking mode. | |
267 * | |
268 * PARAMETERS: | |
269 * "fileDesc" | |
270 * The address of the PRFileDesc whose I/O mode is to be set | |
271 * non-blocking. Must be non-NULL. | |
272 * "plContext" | |
273 * Platform-specific context pointer | |
274 * THREAD SAFETY: | |
275 * Thread Safe (see Thread Safety definitions in Programmer's Guide) | |
276 * RETURNS: | |
277 * none | |
278 */ | |
279 static PKIX_Error * | |
280 pkix_pl_Socket_SetNonBlocking( | |
281 PRFileDesc *fileDesc, | |
282 void *plContext) | |
283 { | |
284 PRStatus rv = PR_FAILURE; | |
285 PRSocketOptionData sockOptionData; | |
286 | |
287 PKIX_ENTER(SOCKET, "pkix_pl_Socket_SetNonBlocking"); | |
288 PKIX_NULLCHECK_ONE(fileDesc); | |
289 | |
290 sockOptionData.option = PR_SockOpt_Nonblocking; | |
291 sockOptionData.value.non_blocking = PR_TRUE; | |
292 | |
293 PKIX_PL_NSSCALLRV(SOCKET, rv, fileDesc->methods->setsocketoption, | |
294 (fileDesc, &sockOptionData)); | |
295 | |
296 if (rv != PR_SUCCESS) { | |
297 PKIX_ERROR(PKIX_UNABLETOSETSOCKETTONONBLOCKING); | |
298 } | |
299 cleanup: | |
300 | |
301 PKIX_RETURN(SOCKET); | |
302 } | |
303 | |
304 /* | |
305 * FUNCTION: pkix_pl_Socket_CreateClient | |
306 * DESCRIPTION: | |
307 * | |
308 * This functions creates a client socket for the PKIX_PL_Socket pointed to | |
309 * by "socket". If "socket" was created with a timeout value of zero, the | |
310 * client socket is set to use nonblocking I/O. | |
311 * | |
312 * PARAMETERS: | |
313 * "socket" | |
314 * The address of the Socket for which a client socket is to be | |
315 * created. Must be non-NULL. | |
316 * "plContext" | |
317 * Platform-specific context pointer | |
318 * THREAD SAFETY: | |
319 * Thread Safe (see Thread Safety definitions in Programmer's Guide) | |
320 * RETURNS: | |
321 * none | |
322 */ | |
323 | |
324 static PKIX_Error * | |
325 pkix_pl_Socket_CreateClient( | |
326 PKIX_PL_Socket *socket, | |
327 void *plContext) | |
328 { | |
329 #ifdef PKIX_SOCKETDEBUG | |
330 PRErrorCode errorcode = 0; | |
331 #endif | |
332 PRFileDesc *mySock = NULL; | |
333 | |
334 PKIX_ENTER(SOCKET, "pkix_pl_Socket_CreateClient"); | |
335 PKIX_NULLCHECK_ONE(socket); | |
336 | |
337 PKIX_PL_NSSCALLRV(SOCKET, mySock, PR_NewTCPSocket, ()); | |
338 if (!mySock) { | |
339 #ifdef PKIX_SOCKETDEBUG | |
340 errorcode = PR_GetError(); | |
341 printf | |
342 ("pkix_pl_Socket_CreateClient: %s\n", | |
343 PR_ErrorToString(errorcode, PR_LANGUAGE_EN)); | |
344 #endif | |
345 PKIX_ERROR(PKIX_PRNEWTCPSOCKETFAILED); | |
346 } | |
347 | |
348 #ifdef PKIX_SOCKETDEBUG | |
349 printf("Created socket, PRFileDesc @ %#X\n", mySock); | |
350 #endif | |
351 | |
352 socket->clientSock = mySock; | |
353 socket->status = SOCKET_UNCONNECTED; | |
354 if (socket->timeout == 0) { | |
355 PKIX_CHECK(pkix_pl_Socket_SetNonBlocking(mySock, plContext), | |
356 PKIX_SOCKETSETNONBLOCKINGFAILED); | |
357 } | |
358 | |
359 cleanup: | |
360 | |
361 PKIX_RETURN(SOCKET); | |
362 } | |
363 | |
364 /* | |
365 * FUNCTION: pkix_pl_Socket_CreateServer | |
366 * DESCRIPTION: | |
367 * | |
368 * This functions creates a server socket for the PKIX_PL_Socket pointed to | |
369 * by "socket". If "socket" was created with a timeout value of zero, the | |
370 * server socket is set to use nonblocking I/O. | |
371 * | |
372 * Warning: there seems to be a problem with operating a server socket in | |
373 * non-blocking mode. If the server calls Recv prior to a corresponding | |
374 * Send, the message may be lost. | |
375 * | |
376 * PARAMETERS: | |
377 * "socket" | |
378 * The address of the Socket for which a server socket is to be | |
379 * created. Must be non-NULL. | |
380 * "plContext" | |
381 * Platform-specific context pointer | |
382 * THREAD SAFETY: | |
383 * Thread Safe (see Thread Safety definitions in Programmer's Guide) | |
384 * RETURNS: | |
385 * none | |
386 */ | |
387 static PKIX_Error * | |
388 pkix_pl_Socket_CreateServer( | |
389 PKIX_PL_Socket *socket, | |
390 void *plContext) | |
391 { | |
392 /* #ifdef PKIX_SOCKETDEBUG */ | |
393 PRErrorCode errorcode = 0; | |
394 /* #endif */ | |
395 PRStatus rv = PR_FAILURE; | |
396 PRFileDesc *serverSock = NULL; | |
397 PRSocketOptionData sockOptionData; | |
398 | |
399 PKIX_ENTER(SOCKET, "pkix_pl_Socket_CreateServer"); | |
400 PKIX_NULLCHECK_ONE(socket); | |
401 | |
402 PKIX_PL_NSSCALLRV(SOCKET, serverSock, PR_NewTCPSocket, ()); | |
403 if (!serverSock) { | |
404 #ifdef PKIX_SOCKETDEBUG | |
405 errorcode = PR_GetError(); | |
406 printf | |
407 ("pkix_pl_Socket_CreateServer: %s\n", | |
408 PR_ErrorToString(errorcode, PR_LANGUAGE_EN)); | |
409 #endif | |
410 PKIX_ERROR(PKIX_PRNEWTCPSOCKETFAILED); | |
411 } | |
412 | |
413 socket->serverSock = serverSock; | |
414 | |
415 #ifdef PKIX_SOCKETDEBUG | |
416 printf("Created socket, PRFileDesc @ %#X\n", serverSock); | |
417 #endif | |
418 | |
419 if (socket->timeout == 0) { | |
420 PKIX_CHECK(pkix_pl_Socket_SetNonBlocking(serverSock, plContext), | |
421 PKIX_SOCKETSETNONBLOCKINGFAILED); | |
422 } | |
423 | |
424 sockOptionData.option = PR_SockOpt_Reuseaddr; | |
425 sockOptionData.value.reuse_addr = PR_TRUE; | |
426 | |
427 PKIX_PL_NSSCALLRV(SOCKET, rv, serverSock->methods->setsocketoption, | |
428 (serverSock, &sockOptionData)); | |
429 | |
430 if (rv != PR_SUCCESS) { | |
431 PKIX_ERROR(PKIX_UNABLETOSETSOCKETTONONBLOCKING); | |
432 } | |
433 | |
434 PKIX_PL_NSSCALLRV(SOCKET, rv, PR_Bind, (serverSock, socket->netAddr)); | |
435 | |
436 if (rv == PR_FAILURE) { | |
437 /* #ifdef PKIX_SOCKETDEBUG */ | |
438 errorcode = PR_GetError(); | |
439 printf | |
440 ("pkix_pl_Socket_CreateServer: %s\n", | |
441 PR_ErrorToString(errorcode, PR_LANGUAGE_EN)); | |
442 /* #endif */ | |
443 PKIX_ERROR(PKIX_PRBINDFAILED); | |
444 } | |
445 | |
446 #ifdef PKIX_SOCKETDEBUG | |
447 printf("Successful bind!\n"); | |
448 #endif | |
449 | |
450 socket->status = SOCKET_BOUND; | |
451 | |
452 cleanup: | |
453 | |
454 PKIX_RETURN(SOCKET); | |
455 } | |
456 | |
457 /* | |
458 * FUNCTION: pkix_pl_Socket_Connect | |
459 * DESCRIPTION: | |
460 * | |
461 * This functions performs the connect function for the client socket | |
462 * specified in "socket", storing the status at "pStatus". | |
463 * | |
464 * PARAMETERS: | |
465 * "socket" | |
466 * The address of the Socket for which a connect is to be performed. | |
467 * Must be non-NULL. | |
468 * "pStatus" | |
469 * The address at which the connection status is stored. Must be non-NULL. | |
470 * "plContext" | |
471 * Platform-specific context pointer | |
472 * THREAD SAFETY: | |
473 * Thread Safe (see Thread Safety definitions in Programmer's Guide) | |
474 * RETURNS: | |
475 * none | |
476 */ | |
477 static PKIX_Error * | |
478 pkix_pl_Socket_Connect( | |
479 PKIX_PL_Socket *socket, | |
480 PRErrorCode *pStatus, | |
481 void *plContext) | |
482 { | |
483 PRStatus rv = PR_FAILURE; | |
484 PRErrorCode errorcode = 0; | |
485 | |
486 PKIX_ENTER(SOCKET, "pkix_pl_Socket_Connect"); | |
487 PKIX_NULLCHECK_TWO(socket, socket->clientSock); | |
488 | |
489 PKIX_PL_NSSCALLRV(SOCKET, rv, PR_Connect, | |
490 (socket->clientSock, socket->netAddr, socket->timeout)); | |
491 | |
492 if (rv == PR_FAILURE) { | |
493 errorcode = PR_GetError(); | |
494 *pStatus = errorcode; | |
495 if (errorcode == PR_IN_PROGRESS_ERROR) { | |
496 socket->status = SOCKET_CONNECTPENDING; | |
497 goto cleanup; | |
498 } else { | |
499 #ifdef PKIX_SOCKETDEBUG | |
500 printf | |
501 ("pkix_pl_Socket_Connect: %s\n", | |
502 PR_ErrorToString(errorcode, PR_LANGUAGE_EN)); | |
503 #endif | |
504 PKIX_ERROR(PKIX_PRCONNECTFAILED); | |
505 } | |
506 } | |
507 | |
508 #ifdef PKIX_SOCKETDEBUG | |
509 printf("Successful connect!\n"); | |
510 #endif | |
511 | |
512 *pStatus = 0; | |
513 socket->status = SOCKET_CONNECTED; | |
514 | |
515 cleanup: | |
516 | |
517 PKIX_RETURN(SOCKET); | |
518 } | |
519 | |
520 /* | |
521 * FUNCTION: pkix_pl_Socket_ConnectContinue | |
522 * DESCRIPTION: | |
523 * | |
524 * This functions continues the connect function for the client socket | |
525 * specified in "socket", storing the status at "pStatus". It is expected that | |
526 * the non-blocking connect has returned PR_IN_PROGRESS_ERROR. | |
527 * | |
528 * PARAMETERS: | |
529 * "socket" | |
530 * The address of the Socket for which a connect is to be continued. | |
531 * Must be non-NULL. | |
532 * "pStatus" | |
533 * The address at which the connection status is stored. Must be non-NULL. | |
534 * "plContext" | |
535 * Platform-specific context pointer | |
536 * THREAD SAFETY: | |
537 * Thread Safe (see Thread Safety definitions in Programmer's Guide) | |
538 * RETURNS: | |
539 * none | |
540 */ | |
541 static PKIX_Error * | |
542 pkix_pl_Socket_ConnectContinue( | |
543 PKIX_PL_Socket *socket, | |
544 PRErrorCode *pStatus, | |
545 void *plContext) | |
546 { | |
547 PRStatus rv = PR_FAILURE; | |
548 PRErrorCode errorcode = 0; | |
549 PRPollDesc pollDesc; | |
550 PRInt32 numEvents = 0; | |
551 | |
552 PKIX_ENTER(SOCKET, "pkix_pl_Socket_ConnectContinue"); | |
553 PKIX_NULLCHECK_TWO(socket, socket->clientSock); | |
554 | |
555 pollDesc.fd = socket->clientSock; | |
556 pollDesc.in_flags = PR_POLL_WRITE | PR_POLL_EXCEPT; | |
557 pollDesc.out_flags = 0; | |
558 PKIX_PL_NSSCALLRV(SOCKET, numEvents, PR_Poll, (&pollDesc, 1, 0)); | |
559 if (numEvents < 0) { | |
560 PKIX_ERROR(PKIX_PRPOLLFAILED); | |
561 } | |
562 | |
563 if (numEvents == 0) { | |
564 *pStatus = PR_IN_PROGRESS_ERROR; | |
565 goto cleanup; | |
566 } | |
567 | |
568 PKIX_PL_NSSCALLRV(SOCKET, rv, PR_ConnectContinue, | |
569 (socket->clientSock, pollDesc.out_flags)); | |
570 | |
571 /* | |
572 * PR_ConnectContinue sometimes lies. It returns PR_SUCCESS | |
573 * even though the connection is not yet ready. But its deceit | |
574 * is betrayed by the contents of out_flags! | |
575 */ | |
576 if ((rv == PR_SUCCESS) && (pollDesc.out_flags == PR_POLL_ERR)) { | |
577 *pStatus = PR_IN_PROGRESS_ERROR; | |
578 goto cleanup; | |
579 } | |
580 | |
581 if (rv == PR_FAILURE) { | |
582 errorcode = PR_GetError(); | |
583 *pStatus = errorcode; | |
584 if (errorcode == PR_IN_PROGRESS_ERROR) { | |
585 goto cleanup; | |
586 } else { | |
587 #ifdef PKIX_SOCKETDEBUG | |
588 printf | |
589 ("pkix_pl_Socket_ConnectContinue: %s\n", | |
590 PR_ErrorToString(errorcode, PR_LANGUAGE_EN)); | |
591 #endif | |
592 PKIX_ERROR(PKIX_PRCONNECTCONTINUEFAILED); | |
593 } | |
594 } | |
595 | |
596 #ifdef PKIX_SOCKETDEBUG | |
597 printf("Successful connect!\n"); | |
598 #endif | |
599 | |
600 *pStatus = 0; | |
601 socket->status = SOCKET_CONNECTED; | |
602 | |
603 cleanup: | |
604 | |
605 PKIX_RETURN(SOCKET); | |
606 } | |
607 | |
608 /* | |
609 * FUNCTION: pkix_pl_Socket_Destroy | |
610 * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) | |
611 */ | |
612 static PKIX_Error * | |
613 pkix_pl_Socket_Destroy( | |
614 PKIX_PL_Object *object, | |
615 void *plContext) | |
616 { | |
617 PKIX_PL_Socket *socket = NULL; | |
618 | |
619 PKIX_ENTER(SOCKET, "pkix_pl_Socket_Destroy"); | |
620 PKIX_NULLCHECK_ONE(object); | |
621 | |
622 PKIX_CHECK(pkix_CheckType | |
623 (object, PKIX_SOCKET_TYPE, plContext), | |
624 PKIX_OBJECTNOTANSOCKET); | |
625 | |
626 socket = (PKIX_PL_Socket *)object; | |
627 | |
628 if (socket->isServer) { | |
629 if (socket->serverSock) { | |
630 PR_Close(socket->serverSock); | |
631 } | |
632 } else { | |
633 if (socket->clientSock) { | |
634 PR_Close(socket->clientSock); | |
635 } | |
636 } | |
637 | |
638 cleanup: | |
639 | |
640 PKIX_RETURN(SOCKET); | |
641 } | |
642 | |
643 /* | |
644 * FUNCTION: pkix_pl_Socket_Hashcode | |
645 * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h) | |
646 */ | |
647 static PKIX_Error * | |
648 pkix_pl_Socket_Hashcode( | |
649 PKIX_PL_Object *object, | |
650 PKIX_UInt32 *pHashcode, | |
651 void *plContext) | |
652 { | |
653 PKIX_PL_Socket *socket = NULL; | |
654 | |
655 PKIX_ENTER(SOCKET, "pkix_pl_Socket_Hashcode"); | |
656 PKIX_NULLCHECK_TWO(object, pHashcode); | |
657 | |
658 PKIX_CHECK(pkix_CheckType(object, PKIX_SOCKET_TYPE, plContext), | |
659 PKIX_OBJECTNOTSOCKET); | |
660 | |
661 socket = (PKIX_PL_Socket *)object; | |
662 | |
663 *pHashcode = (((socket->timeout << 3) + | |
664 (socket->netAddr->inet.family << 3)) + | |
665 (*((PKIX_UInt32 *)&(socket->netAddr->inet.ip)))) + | |
666 socket->netAddr->inet.port; | |
667 | |
668 cleanup: | |
669 | |
670 PKIX_RETURN(SOCKET); | |
671 } | |
672 | |
673 /* | |
674 * FUNCTION: pkix_pl_Socket_Equals | |
675 * (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h) | |
676 */ | |
677 static PKIX_Error * | |
678 pkix_pl_Socket_Equals( | |
679 PKIX_PL_Object *firstObject, | |
680 PKIX_PL_Object *secondObject, | |
681 PKIX_Int32 *pResult, | |
682 void *plContext) | |
683 { | |
684 PKIX_PL_Socket *firstSocket = NULL; | |
685 PKIX_PL_Socket *secondSocket = NULL; | |
686 | |
687 PKIX_ENTER(SOCKET, "pkix_pl_Socket_Equals"); | |
688 PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult); | |
689 | |
690 *pResult = PKIX_FALSE; | |
691 | |
692 PKIX_CHECK(pkix_CheckTypes | |
693 (firstObject, secondObject, PKIX_SOCKET_TYPE, plContext), | |
694 PKIX_OBJECTNOTSOCKET); | |
695 | |
696 firstSocket = (PKIX_PL_Socket *)firstObject; | |
697 secondSocket = (PKIX_PL_Socket *)secondObject; | |
698 | |
699 if (firstSocket->timeout != secondSocket->timeout) { | |
700 goto cleanup; | |
701 } | |
702 | |
703 if (firstSocket->netAddr == secondSocket->netAddr) { | |
704 *pResult = PKIX_TRUE; | |
705 goto cleanup; | |
706 } | |
707 | |
708 if ((firstSocket->netAddr->inet.family != | |
709 secondSocket->netAddr->inet.family) || | |
710 (*((PKIX_UInt32 *)&(firstSocket->netAddr->inet.ip)) != | |
711 *((PKIX_UInt32 *)&(secondSocket->netAddr->inet.ip))) || | |
712 (firstSocket->netAddr->inet.port != | |
713 secondSocket->netAddr->inet.port)) { | |
714 | |
715 goto cleanup; | |
716 | |
717 } | |
718 | |
719 *pResult = PKIX_TRUE; | |
720 | |
721 cleanup: | |
722 | |
723 PKIX_RETURN(SOCKET); | |
724 } | |
725 | |
726 /* | |
727 * FUNCTION: pkix_pl_Socket_RegisterSelf | |
728 * | |
729 * DESCRIPTION: | |
730 * Registers PKIX_PL_SOCKET_TYPE and its related | |
731 * functions with systemClasses[] | |
732 * | |
733 * THREAD SAFETY: | |
734 * Not Thread Safe - for performance and complexity reasons | |
735 * | |
736 * Since this function is only called by PKIX_PL_Initialize, which should | |
737 * only be called once, it is acceptable that this function is not | |
738 * thread-safe. | |
739 */ | |
740 PKIX_Error * | |
741 pkix_pl_Socket_RegisterSelf(void *plContext) | |
742 { | |
743 extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; | |
744 pkix_ClassTable_Entry entry; | |
745 | |
746 PKIX_ENTER(SOCKET, "pkix_pl_Socket_RegisterSelf"); | |
747 | |
748 entry.description = "Socket"; | |
749 entry.objCounter = 0; | |
750 entry.typeObjectSize = sizeof(PKIX_PL_Socket); | |
751 entry.destructor = pkix_pl_Socket_Destroy; | |
752 entry.equalsFunction = pkix_pl_Socket_Equals; | |
753 entry.hashcodeFunction = pkix_pl_Socket_Hashcode; | |
754 entry.toStringFunction = NULL; | |
755 entry.comparator = NULL; | |
756 entry.duplicateFunction = NULL; | |
757 | |
758 systemClasses[PKIX_SOCKET_TYPE] = entry; | |
759 | |
760 #ifdef PKIX_SOCKETTRACE | |
761 { | |
762 char *val = NULL; | |
763 val = PR_GetEnv("SOCKETTRACE"); | |
764 /* Is SOCKETTRACE set in the environment? */ | |
765 if ((val != NULL) && (*val != '\0')) { | |
766 socketTraceFlag = | |
767 ((*val == '1')?PKIX_TRUE:PKIX_FALSE); | |
768 } | |
769 } | |
770 #endif | |
771 | |
772 PKIX_RETURN(SOCKET); | |
773 } | |
774 | |
775 /* --Public-Socket-Functions----------------------------------- */ | |
776 | |
777 /* | |
778 * FUNCTION: pkix_pl_Socket_Listen | |
779 * DESCRIPTION: | |
780 * | |
781 * This functions establishes a listening queue for the server Socket | |
782 * pointed to by "socket". | |
783 * | |
784 * PARAMETERS: | |
785 * "socket" | |
786 * The address of the server socket for which the queue is to be | |
787 * established. Must be non-NULL. | |
788 * "backlog" | |
789 * The UInt32 value of the length of the queue to be established. | |
790 * "plContext" | |
791 * Platform-specific context pointer | |
792 * THREAD SAFETY: | |
793 * Thread Safe (see Thread Safety definitions in Programmer's Guide) | |
794 * RETURNS: | |
795 * none | |
796 */ | |
797 static PKIX_Error * | |
798 pkix_pl_Socket_Listen( | |
799 PKIX_PL_Socket *socket, | |
800 PKIX_UInt32 backlog, | |
801 void *plContext) | |
802 { | |
803 #ifdef PKIX_SOCKETDEBUG | |
804 PRErrorCode errorcode = 0; | |
805 #endif | |
806 PRStatus rv = PR_FAILURE; | |
807 | |
808 PKIX_ENTER(SOCKET, "pkix_pl_Socket_Listen"); | |
809 PKIX_NULLCHECK_TWO(socket, socket->serverSock); | |
810 | |
811 PKIX_PL_NSSCALLRV(SOCKET, rv, PR_Listen, | |
812 (socket->serverSock, (PRIntn)backlog)); | |
813 | |
814 if (rv == PR_FAILURE) { | |
815 #ifdef PKIX_SOCKETDEBUG | |
816 errorcode = PR_GetError(); | |
817 printf | |
818 ("pkix_pl_Socket_Listen: %s\n", | |
819 PR_ErrorToString(errorcode, PR_LANGUAGE_EN)); | |
820 #endif | |
821 PKIX_ERROR(PKIX_PRLISTENFAILED); | |
822 } | |
823 | |
824 #ifdef PKIX_SOCKETDEBUG | |
825 printf("Successful listen!\n"); | |
826 #endif | |
827 | |
828 socket->status = SOCKET_LISTENING; | |
829 cleanup: | |
830 | |
831 PKIX_RETURN(SOCKET); | |
832 } | |
833 | |
834 /* | |
835 * FUNCTION: pkix_pl_Socket_Shutdown | |
836 * DESCRIPTION: | |
837 * | |
838 * This functions performs the shutdown of any connections controlled by the | |
839 * socket pointed to by "socket". | |
840 * | |
841 * PARAMETERS: | |
842 * "socket" | |
843 * The address of the socket to be shut down. Must be non-NULL. | |
844 * "plContext" | |
845 * Platform-specific context pointer | |
846 * THREAD SAFETY: | |
847 * Thread Safe (see Thread Safety definitions in Programmer's Guide) | |
848 * RETURNS: | |
849 * none | |
850 */ | |
851 static PKIX_Error * | |
852 pkix_pl_Socket_Shutdown( | |
853 PKIX_PL_Socket *socket, | |
854 void *plContext) | |
855 { | |
856 #ifdef PKIX_SOCKETDEBUG | |
857 PRErrorCode errorcode = 0; | |
858 #endif | |
859 PRStatus rv = PR_FAILURE; | |
860 PRFileDesc *fileDesc = NULL; | |
861 | |
862 PKIX_ENTER(SOCKET, "pkix_pl_Socket_Shutdown"); | |
863 PKIX_NULLCHECK_ONE(socket); | |
864 | |
865 fileDesc = | |
866 (socket->isServer)?(socket->serverSock):(socket->clientSock); | |
867 | |
868 PKIX_PL_NSSCALLRV(SOCKET, rv, PR_Shutdown, | |
869 (fileDesc, PR_SHUTDOWN_BOTH)); | |
870 | |
871 if (rv == PR_FAILURE) { | |
872 #ifdef PKIX_SOCKETDEBUG | |
873 errorcode = PR_GetError(); | |
874 printf | |
875 ("pkix_pl_Socket_Shutdown: %s\n", | |
876 PR_ErrorToString(errorcode, PR_LANGUAGE_EN)); | |
877 #endif | |
878 PKIX_ERROR(PKIX_PRSHUTDOWNFAILED); | |
879 } | |
880 socket->status = SOCKET_SHUTDOWN; | |
881 | |
882 cleanup: | |
883 | |
884 PKIX_RETURN(SOCKET); | |
885 } | |
886 | |
887 /* | |
888 * FUNCTION: pkix_pl_Socket_Send | |
889 * DESCRIPTION: | |
890 * | |
891 * This functions sends a message using the socket pointed to by "sendSock", | |
892 * from the buffer pointed to by "buf", of the number of bytes given by | |
893 * "bytesToWrite", storing the number of bytes actually written at | |
894 * "pBytesWritten". If "socket" is in non-blocking mode, the send operation | |
895 * may store -1 at "pBytesWritten" and the write is not complete until a | |
896 * corresponding pkix_pl_Poll call has indicated its completion by returning | |
897 * a non-negative value for bytes written. | |
898 * | |
899 * PARAMETERS: | |
900 * "sendSock" | |
901 * The address of the Socket on which the message is to be sent. Must | |
902 * be non-NULL. | |
903 * "buf" | |
904 * The address of the data to be sent. Must be non-NULL. | |
905 * "bytesToWrite"" | |
906 * The UInt32 value indicating the number of bytes to write. | |
907 * "pBytesWritten" | |
908 * The address at which the Int32 value indicating the number of bytes | |
909 * actually written is to be stored. Must be non-NULL. | |
910 * "plContext" | |
911 * Platform-specific context pointer | |
912 * THREAD SAFETY: | |
913 * Thread Safe (see Thread Safety definitions in Programmer's Guide) | |
914 * RETURNS: | |
915 * none | |
916 */ | |
917 static PKIX_Error * | |
918 pkix_pl_Socket_Send( | |
919 PKIX_PL_Socket *sendSock, | |
920 void *buf, | |
921 PKIX_UInt32 bytesToWrite, | |
922 PKIX_Int32 *pBytesWritten, | |
923 void *plContext) | |
924 { | |
925 PRInt32 bytesWritten = 0; | |
926 PRErrorCode errorcode = 0; | |
927 PRFileDesc *fd = NULL; | |
928 | |
929 PKIX_ENTER(SOCKET, "pkix_pl_Socket_Send"); | |
930 PKIX_NULLCHECK_TWO(buf, pBytesWritten); | |
931 | |
932 fd = sendSock->clientSock; | |
933 | |
934 PKIX_PL_NSSCALLRV(SOCKET, bytesWritten, PR_Send, | |
935 (fd, buf, (PRInt32)bytesToWrite, 0, sendSock->timeout)); | |
936 | |
937 if (bytesWritten >= 0) { | |
938 if (sendSock->status == SOCKET_SENDRCVPENDING) { | |
939 sendSock->status = SOCKET_RCVPENDING; | |
940 } else { | |
941 sendSock->status = SOCKET_CONNECTED; | |
942 } | |
943 #ifdef PKIX_SOCKETTRACE | |
944 pkix_pl_socket_tracebuff(buf, bytesWritten); | |
945 #endif | |
946 } else { | |
947 errorcode = PR_GetError(); | |
948 if (errorcode != PR_WOULD_BLOCK_ERROR) { | |
949 #ifdef PKIX_SOCKETDEBUG | |
950 printf | |
951 ("pkix_pl_Socket_Send: %s\n", | |
952 PR_ErrorToString(errorcode, PR_LANGUAGE_EN)); | |
953 #endif | |
954 PKIX_ERROR(PKIX_PRSENDFAILED); | |
955 } | |
956 | |
957 sendSock->writeBuf = buf; | |
958 sendSock->writeBufSize = bytesToWrite; | |
959 if (sendSock->status == SOCKET_RCVPENDING) { | |
960 sendSock->status = SOCKET_SENDRCVPENDING; | |
961 } else { | |
962 sendSock->status = SOCKET_SENDPENDING; | |
963 } | |
964 } | |
965 | |
966 *pBytesWritten = (PKIX_Int32)bytesWritten; | |
967 | |
968 cleanup: | |
969 | |
970 PKIX_RETURN(SOCKET); | |
971 } | |
972 | |
973 /* | |
974 * FUNCTION: pkix_pl_Socket_Recv | |
975 * DESCRIPTION: | |
976 * | |
977 * This functions receives a message on the socket pointed to by "rcvSock", | |
978 * into the buffer pointed to by "buf", of capacity given by "capacity", | |
979 * storing the number of bytes actually received at "pBytesRead". If "socket" | |
980 * is in non-blocking mode, the receive operation may store -1 at | |
981 * "pBytesWritten". In that case the write is not complete until a | |
982 * corresponding pkix_pl_Poll call has indicated its completion by returning | |
983 * a non-negative value for bytes read. | |
984 * | |
985 * PARAMETERS: | |
986 * "rcvSock" | |
987 * The address of the Socket on which the message is to be received. | |
988 * Must be non-NULL. | |
989 * "buf" | |
990 * The address of the buffer into which the message is to be received. | |
991 * Must be non-NULL. | |
992 * "capacity" | |
993 * The UInt32 value of the size of the buffer; that is, the maximum | |
994 * number of bytes that can be received. | |
995 * "pBytesRead" | |
996 * The address at which is stored the Int32 value of the number of bytes | |
997 * actually received. | |
998 * "plContext" | |
999 * Platform-specific context pointer | |
1000 * THREAD SAFETY: | |
1001 * Thread Safe (see Thread Safety definitions in Programmer's Guide) | |
1002 * RETURNS: | |
1003 * none | |
1004 */ | |
1005 static PKIX_Error * | |
1006 pkix_pl_Socket_Recv( | |
1007 PKIX_PL_Socket *rcvSock, | |
1008 void *buf, | |
1009 PKIX_UInt32 capacity, | |
1010 PKIX_Int32 *pBytesRead, | |
1011 void *plContext) | |
1012 { | |
1013 PRErrorCode errorcode = 0; | |
1014 PRInt32 bytesRead = 0; | |
1015 PRFileDesc *fd = NULL; | |
1016 | |
1017 PKIX_ENTER(SOCKET, "pkix_pl_Socket_Recv"); | |
1018 PKIX_NULLCHECK_THREE(rcvSock, buf, pBytesRead); | |
1019 | |
1020 fd = rcvSock->clientSock; | |
1021 | |
1022 PKIX_PL_NSSCALLRV(SOCKET, bytesRead, PR_Recv, | |
1023 (fd, buf, (PRInt32)capacity, 0, rcvSock->timeout)); | |
1024 | |
1025 if (bytesRead > 0) { | |
1026 if (rcvSock->status == SOCKET_SENDRCVPENDING) { | |
1027 rcvSock->status = SOCKET_SENDPENDING; | |
1028 } else { | |
1029 rcvSock->status = SOCKET_CONNECTED; | |
1030 } | |
1031 #ifdef PKIX_SOCKETTRACE | |
1032 pkix_pl_socket_tracebuff(buf, bytesRead); | |
1033 #endif | |
1034 } else if (bytesRead == 0) { | |
1035 PKIX_ERROR(PKIX_PRRECVREPORTSNETWORKCONNECTIONCLOSED); | |
1036 } else { | |
1037 errorcode = PR_GetError(); | |
1038 if (errorcode != PR_WOULD_BLOCK_ERROR) { | |
1039 #ifdef PKIX_SOCKETDEBUG | |
1040 printf | |
1041 ("pkix_pl_Socket_Recv: %s\n", | |
1042 PR_ErrorToString(errorcode, PR_LANGUAGE_EN)); | |
1043 #endif | |
1044 PKIX_ERROR(PKIX_PRRECVFAILED); | |
1045 } | |
1046 rcvSock->readBuf = buf; | |
1047 rcvSock->readBufSize = capacity; | |
1048 if (rcvSock->status == SOCKET_SENDPENDING) { | |
1049 rcvSock->status = SOCKET_SENDRCVPENDING; | |
1050 } else { | |
1051 rcvSock->status = SOCKET_RCVPENDING; | |
1052 } | |
1053 | |
1054 } | |
1055 | |
1056 *pBytesRead = (PKIX_Int32)bytesRead; | |
1057 | |
1058 cleanup: | |
1059 | |
1060 PKIX_RETURN(SOCKET); | |
1061 } | |
1062 | |
1063 /* | |
1064 * FUNCTION: pkix_pl_Socket_Poll | |
1065 * DESCRIPTION: | |
1066 * | |
1067 * This functions checks for completion of an earlier Send or Recv on the | |
1068 * socket pointed to by "sock", storing in "pBytesWritten" the number of bytes | |
1069 * written by a completed Send and in "pBytesRead" the number of bytes | |
1070 * received in a completed Recv. A value of -1 returned indicates the | |
1071 * operation has still not completed. A NULL pointer may be supplied for | |
1072 * "pBytesWritten" to avoid checking for completion of a Send. A NULL pointer | |
1073 * may be supplied for "pBytesRead" to avoid checking for completion of a Recv. | |
1074 * | |
1075 * PARAMETERS: | |
1076 * "sock" | |
1077 * The address of the socket for which completions are to be checked. | |
1078 * "pBytesWritten" | |
1079 * The address at which the number of bytes written is to be stored, if | |
1080 * a pending Send has completed. If NULL, Sends are not checked. | |
1081 * "pBytesRead" | |
1082 * The address at which the number of bytes read is to be stored, if | |
1083 * a pending Recv has completed. If NULL, Recvs are not checked. | |
1084 * "plContext" | |
1085 * Platform-specific context pointer | |
1086 * THREAD SAFETY: | |
1087 * Thread Safe (see Thread Safety definitions in Programmer's Guide) | |
1088 * RETURNS: | |
1089 * none | |
1090 */ | |
1091 static PKIX_Error * | |
1092 pkix_pl_Socket_Poll( | |
1093 PKIX_PL_Socket *sock, | |
1094 PKIX_Int32 *pBytesWritten, | |
1095 PKIX_Int32 *pBytesRead, | |
1096 void *plContext) | |
1097 { | |
1098 PRPollDesc pollDesc; | |
1099 PRInt32 numEvents = 0; | |
1100 PKIX_Int32 bytesRead = 0; | |
1101 PKIX_Int32 bytesWritten = 0; | |
1102 PRErrorCode errorcode = 0; | |
1103 | |
1104 PKIX_ENTER(SOCKET, "pkix_pl_Socket_Poll"); | |
1105 PKIX_NULLCHECK_ONE(sock); | |
1106 | |
1107 pollDesc.fd = sock->clientSock; | |
1108 pollDesc.in_flags = 0; | |
1109 pollDesc.out_flags = 0; | |
1110 | |
1111 if ((pBytesWritten) && | |
1112 ((sock->status == SOCKET_SENDPENDING) || | |
1113 (sock->status == SOCKET_SENDRCVPENDING))) { | |
1114 pollDesc.in_flags = PR_POLL_WRITE; | |
1115 } | |
1116 | |
1117 if ((pBytesRead) && | |
1118 ((sock->status == SOCKET_RCVPENDING) || | |
1119 (sock->status == SOCKET_SENDRCVPENDING))) { | |
1120 pollDesc.in_flags |= PR_POLL_READ; | |
1121 } | |
1122 | |
1123 PKIX_PL_NSSCALLRV(SOCKET, numEvents, PR_Poll, (&pollDesc, 1, 0)); | |
1124 | |
1125 if (numEvents < 0) { | |
1126 PKIX_ERROR(PKIX_PRPOLLFAILED); | |
1127 } else if (numEvents > 0) { | |
1128 if (pollDesc.out_flags & PR_POLL_WRITE) { | |
1129 PKIX_CHECK(pkix_pl_Socket_Send | |
1130 (sock, | |
1131 sock->writeBuf, | |
1132 sock->writeBufSize, | |
1133 &bytesWritten, | |
1134 plContext), | |
1135 PKIX_SOCKETSENDFAILED); | |
1136 *pBytesWritten = (PKIX_Int32)bytesWritten; | |
1137 if (bytesWritten >= 0) { | |
1138 sock->writeBuf = NULL; | |
1139 sock->writeBufSize = 0; | |
1140 } | |
1141 } | |
1142 | |
1143 if (pollDesc.out_flags & PR_POLL_READ) { | |
1144 PKIX_CHECK(pkix_pl_Socket_Recv | |
1145 (sock, | |
1146 sock->readBuf, | |
1147 sock->readBufSize, | |
1148 &bytesRead, | |
1149 plContext), | |
1150 PKIX_SOCKETRECVFAILED); | |
1151 *pBytesRead = (PKIX_Int32)bytesRead; | |
1152 if (bytesRead >= 0) { | |
1153 sock->readBuf = NULL; | |
1154 sock->readBufSize = 0; | |
1155 } | |
1156 } | |
1157 } else if (numEvents == 0) { | |
1158 errorcode = PR_GetError(); | |
1159 if (errorcode != PR_WOULD_BLOCK_ERROR) { | |
1160 #ifdef PKIX_SOCKETDEBUG | |
1161 printf | |
1162 ("pkix_pl_Socket_Poll: %s\n", | |
1163 PR_ErrorToString(errorcode, PR_LANGUAGE_EN)); | |
1164 #endif | |
1165 PKIX_ERROR(PKIX_PRPOLLFAILED); | |
1166 } | |
1167 if (pBytesWritten) { | |
1168 *pBytesWritten = 0; | |
1169 } | |
1170 if (pBytesRead) { | |
1171 *pBytesRead = 0; | |
1172 } | |
1173 } | |
1174 | |
1175 cleanup: | |
1176 | |
1177 PKIX_RETURN(SOCKET); | |
1178 } | |
1179 | |
1180 /* | |
1181 * FUNCTION: pkix_pl_Socket_Accept | |
1182 * DESCRIPTION: | |
1183 * | |
1184 * This functions accepts a client connection for the server Socket pointed | |
1185 * to by "serverSocket", creating a new Socket and storing the result at | |
1186 * "pRendezvousSocket". If "serverSocket" is in non-blocking mode, this | |
1187 * function will return NULL if there is no client connection to accept. | |
1188 * Otherwise this function will block until a connection is available. | |
1189 * When a client connection is available the new Socket will have the same | |
1190 * blocking/non-blocking property as "serverSocket". | |
1191 * | |
1192 * PARAMETERS: | |
1193 * "serverSocket" | |
1194 * The address of the Socket for which a client connection is to be | |
1195 * accepted. Must be non-NULL. | |
1196 * "pRendezvousSocket" | |
1197 * The address at which the created Socket is stored, when a client | |
1198 * connection is available, or at which NULL is stored, if no connection | |
1199 * is available for a non-blocking "serverSocket". Must be non-NULL. | |
1200 * "plContext" | |
1201 * Platform-specific context pointer | |
1202 * THREAD SAFETY: | |
1203 * Thread Safe (see Thread Safety definitions in Programmer's Guide) | |
1204 * RETURNS: | |
1205 * none | |
1206 */ | |
1207 static PKIX_Error * | |
1208 pkix_pl_Socket_Accept( | |
1209 PKIX_PL_Socket *serverSocket, | |
1210 PKIX_PL_Socket **pRendezvousSocket, | |
1211 void *plContext) | |
1212 { | |
1213 PRErrorCode errorcode = 0; | |
1214 PRFileDesc *rendezvousSock = NULL; | |
1215 PRNetAddr *clientAddr = NULL; | |
1216 PKIX_PL_Socket *newSocket = NULL; | |
1217 | |
1218 PKIX_ENTER(SOCKET, "pkix_pl_Socket_Accept"); | |
1219 PKIX_NULLCHECK_TWO(serverSocket, pRendezvousSocket); | |
1220 | |
1221 PKIX_PL_NSSCALLRV(SOCKET, rendezvousSock, PR_Accept, | |
1222 (serverSocket->serverSock, clientAddr, serverSocket->timeout)); | |
1223 | |
1224 if (!rendezvousSock) { | |
1225 errorcode = PR_GetError(); | |
1226 if (errorcode != PR_WOULD_BLOCK_ERROR) { | |
1227 #ifdef PKIX_SOCKETDEBUG | |
1228 printf | |
1229 ("pkix_pl_Socket_Accept: %s\n", | |
1230 PR_ErrorToString(errorcode, PR_LANGUAGE_EN)); | |
1231 #endif | |
1232 PKIX_ERROR(PKIX_PRACCEPTFAILED); | |
1233 } | |
1234 serverSocket->status = SOCKET_ACCEPTPENDING; | |
1235 *pRendezvousSocket = NULL; | |
1236 goto cleanup; | |
1237 | |
1238 } | |
1239 | |
1240 #ifdef PKIX_SOCKETDEBUG | |
1241 printf("Successful accept!\n"); | |
1242 #endif | |
1243 | |
1244 PKIX_CHECK(PKIX_PL_Object_Alloc | |
1245 (PKIX_SOCKET_TYPE, | |
1246 sizeof (PKIX_PL_Socket), | |
1247 (PKIX_PL_Object **)&newSocket, | |
1248 plContext), | |
1249 PKIX_COULDNOTCREATESOCKETOBJECT); | |
1250 | |
1251 newSocket->isServer = PKIX_FALSE; | |
1252 newSocket->timeout = serverSocket->timeout; | |
1253 newSocket->clientSock = rendezvousSock; | |
1254 newSocket->serverSock = NULL; | |
1255 newSocket->netAddr = NULL; | |
1256 newSocket->status = SOCKET_CONNECTED; | |
1257 newSocket->callbackList.shutdownCallback = pkix_pl_Socket_Shutdown; | |
1258 newSocket->callbackList.listenCallback = pkix_pl_Socket_Listen; | |
1259 newSocket->callbackList.acceptCallback = pkix_pl_Socket_Accept; | |
1260 newSocket->callbackList.connectcontinueCallback = | |
1261 pkix_pl_Socket_ConnectContinue; | |
1262 newSocket->callbackList.sendCallback = pkix_pl_Socket_Send; | |
1263 newSocket->callbackList.recvCallback = pkix_pl_Socket_Recv; | |
1264 newSocket->callbackList.pollCallback = pkix_pl_Socket_Poll; | |
1265 | |
1266 if (serverSocket->timeout == 0) { | |
1267 PKIX_CHECK(pkix_pl_Socket_SetNonBlocking | |
1268 (rendezvousSock, plContext), | |
1269 PKIX_SOCKETSETNONBLOCKINGFAILED); | |
1270 } | |
1271 | |
1272 *pRendezvousSocket = newSocket; | |
1273 | |
1274 cleanup: | |
1275 | |
1276 PKIX_RETURN(SOCKET); | |
1277 } | |
1278 | |
1279 /* | |
1280 * FUNCTION: pkix_pl_Socket_Create | |
1281 * DESCRIPTION: | |
1282 * | |
1283 * This function creates a new Socket, setting it to be a server or a client | |
1284 * according to the value of "isServer", setting its timeout value from | |
1285 * "timeout" and server address from "netAddr", and stores the created Socket | |
1286 * at "pSocket". | |
1287 * | |
1288 * PARAMETERS: | |
1289 * "isServer" | |
1290 * The Boolean value indicating if PKIX_TRUE, that a server socket (using | |
1291 * Bind, Listen, and Accept) is to be created, or if PKIX_FALSE, that a | |
1292 * client socket (using Connect) is to be created. | |
1293 * "timeout" | |
1294 * A PRTimeInterval value to be used for I/O waits for this socket. If | |
1295 * zero, non-blocking I/O is to be used. | |
1296 * "netAddr" | |
1297 * The PRNetAddr to be used for the Bind function, if this is a server | |
1298 * socket, or for the Connect, if this is a client socket. | |
1299 * "pSocket" | |
1300 * The address at which the Socket is to be stored. Must be non-NULL. | |
1301 * "plContext" | |
1302 * Platform-specific context pointer. | |
1303 * THREAD SAFETY: | |
1304 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
1305 * RETURNS: | |
1306 * Returns NULL if the function succeeds. | |
1307 * Returns a Socket Error if the function fails in | |
1308 * a non-fatal way. | |
1309 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
1310 */ | |
1311 PKIX_Error * | |
1312 pkix_pl_Socket_Create( | |
1313 PKIX_Boolean isServer, | |
1314 PRIntervalTime timeout, | |
1315 PRNetAddr *netAddr, | |
1316 PRErrorCode *status, | |
1317 PKIX_PL_Socket **pSocket, | |
1318 void *plContext) | |
1319 { | |
1320 PKIX_PL_Socket *socket = NULL; | |
1321 | |
1322 PKIX_ENTER(SOCKET, "pkix_pl_Socket_Create"); | |
1323 PKIX_NULLCHECK_ONE(pSocket); | |
1324 | |
1325 PKIX_CHECK(PKIX_PL_Object_Alloc | |
1326 (PKIX_SOCKET_TYPE, | |
1327 sizeof (PKIX_PL_Socket), | |
1328 (PKIX_PL_Object **)&socket, | |
1329 plContext), | |
1330 PKIX_COULDNOTCREATESOCKETOBJECT); | |
1331 | |
1332 socket->isServer = isServer; | |
1333 socket->timeout = timeout; | |
1334 socket->clientSock = NULL; | |
1335 socket->serverSock = NULL; | |
1336 socket->netAddr = netAddr; | |
1337 | |
1338 socket->callbackList.listenCallback = pkix_pl_Socket_Listen; | |
1339 socket->callbackList.acceptCallback = pkix_pl_Socket_Accept; | |
1340 socket->callbackList.connectcontinueCallback = | |
1341 pkix_pl_Socket_ConnectContinue; | |
1342 socket->callbackList.sendCallback = pkix_pl_Socket_Send; | |
1343 socket->callbackList.recvCallback = pkix_pl_Socket_Recv; | |
1344 socket->callbackList.pollCallback = pkix_pl_Socket_Poll; | |
1345 socket->callbackList.shutdownCallback = pkix_pl_Socket_Shutdown; | |
1346 | |
1347 if (isServer) { | |
1348 PKIX_CHECK(pkix_pl_Socket_CreateServer(socket, plContext), | |
1349 PKIX_SOCKETCREATESERVERFAILED); | |
1350 *status = 0; | |
1351 } else { | |
1352 socket->timeout = timeout; | |
1353 PKIX_CHECK(pkix_pl_Socket_CreateClient(socket, plContext), | |
1354 PKIX_SOCKETCREATECLIENTFAILED); | |
1355 PKIX_CHECK(pkix_pl_Socket_Connect(socket, status, plContext), | |
1356 PKIX_SOCKETCONNECTFAILED); | |
1357 } | |
1358 | |
1359 *pSocket = socket; | |
1360 | |
1361 cleanup: | |
1362 if (PKIX_ERROR_RECEIVED) { | |
1363 PKIX_DECREF(socket); | |
1364 } | |
1365 | |
1366 PKIX_RETURN(SOCKET); | |
1367 } | |
1368 | |
1369 /* | |
1370 * FUNCTION: pkix_pl_Socket_CreateByName | |
1371 * DESCRIPTION: | |
1372 * | |
1373 * This function creates a new Socket, setting it to be a server or a client | |
1374 * according to the value of "isServer", setting its timeout value from | |
1375 * "timeout" and server address and port number from "serverName", and stores | |
1376 * the status at "pStatus" and the created Socket at "pSocket". | |
1377 * | |
1378 * If isServer is PKIX_TRUE, it is attempted to create the socket with an ip | |
1379 * address of PR_INADDR_ANY. | |
1380 * | |
1381 * PARAMETERS: | |
1382 * "isServer" | |
1383 * The Boolean value indicating if PKIX_TRUE, that a server socket (using | |
1384 * Bind, Listen, and Accept) is to be created, or if PKIX_FALSE, that a | |
1385 * client socket (using Connect) is to be created. | |
1386 * "timeout" | |
1387 * A PRTimeInterval value to be used for I/O waits for this socket. If | |
1388 * zero, non-blocking I/O is to be used. | |
1389 * "serverName" | |
1390 * Address of a character string consisting of the server's domain name | |
1391 * followed by a colon and a port number for the desired socket. | |
1392 * "pStatus" | |
1393 * Address at which the PRErrorCode resulting from the create is | |
1394 * stored. Must be non-NULL. | |
1395 * "pSocket" | |
1396 * The address at which the Socket is to be stored. Must be non-NULL. | |
1397 * "plContext" | |
1398 * Platform-specific context pointer. | |
1399 * THREAD SAFETY: | |
1400 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
1401 * RETURNS: | |
1402 * Returns NULL if the function succeeds. | |
1403 * Returns a Socket Error if the function fails in | |
1404 * a non-fatal way. | |
1405 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
1406 */ | |
1407 PKIX_Error * | |
1408 pkix_pl_Socket_CreateByName( | |
1409 PKIX_Boolean isServer, | |
1410 PRIntervalTime timeout, | |
1411 char *serverName, | |
1412 PRErrorCode *pStatus, | |
1413 PKIX_PL_Socket **pSocket, | |
1414 void *plContext) | |
1415 { | |
1416 PRNetAddr netAddr; | |
1417 PKIX_PL_Socket *socket = NULL; | |
1418 char *sepPtr = NULL; | |
1419 PRHostEnt hostent; | |
1420 PRIntn hostenum; | |
1421 PRStatus prstatus = PR_FAILURE; | |
1422 char buf[PR_NETDB_BUF_SIZE]; | |
1423 PRUint16 portNum = 0; | |
1424 char *localCopyName = NULL; | |
1425 | |
1426 PKIX_ENTER(SOCKET, "pkix_pl_Socket_CreateByName"); | |
1427 PKIX_NULLCHECK_TWO(serverName, pSocket); | |
1428 | |
1429 localCopyName = PL_strdup(serverName); | |
1430 | |
1431 sepPtr = strchr(localCopyName, ':'); | |
1432 /* First strip off the portnum, if present, from the end of the name */ | |
1433 if (sepPtr) { | |
1434 *sepPtr++ = '\0'; | |
1435 portNum = (PRUint16)atoi(sepPtr); | |
1436 } else { | |
1437 portNum = (PRUint16)LDAP_PORT; | |
1438 } | |
1439 | |
1440 prstatus = PR_GetHostByName(localCopyName, buf, sizeof(buf), &hostent); | |
1441 | |
1442 if ((prstatus != PR_SUCCESS) || (hostent.h_length != 4)) { | |
1443 /* | |
1444 * The hostname may be a fully-qualified name. Try using just | |
1445 * the leftmost component in our lookup. | |
1446 */ | |
1447 sepPtr = strchr(localCopyName, '.'); | |
1448 if (sepPtr) { | |
1449 *sepPtr++ = '\0'; | |
1450 } | |
1451 prstatus = PR_GetHostByName | |
1452 (localCopyName, buf, sizeof(buf), &hostent); | |
1453 | |
1454 if ((prstatus != PR_SUCCESS) || (hostent.h_length != 4)) { | |
1455 PKIX_ERROR | |
1456 (PKIX_PRGETHOSTBYNAMEREJECTSHOSTNAMEARGUMENT); | |
1457 } | |
1458 } | |
1459 | |
1460 netAddr.inet.family = PR_AF_INET; | |
1461 netAddr.inet.port = PR_htons(portNum); | |
1462 | |
1463 if (isServer) { | |
1464 | |
1465 netAddr.inet.ip = PR_INADDR_ANY; | |
1466 | |
1467 } else { | |
1468 | |
1469 hostenum = PR_EnumerateHostEnt(0, &hostent, portNum, &netAddr); | |
1470 if (hostenum == -1) { | |
1471 PKIX_ERROR(PKIX_PRENUMERATEHOSTENTFAILED); | |
1472 } | |
1473 } | |
1474 | |
1475 PKIX_CHECK(PKIX_PL_Object_Alloc | |
1476 (PKIX_SOCKET_TYPE, | |
1477 sizeof (PKIX_PL_Socket), | |
1478 (PKIX_PL_Object **)&socket, | |
1479 plContext), | |
1480 PKIX_COULDNOTCREATESOCKETOBJECT); | |
1481 | |
1482 socket->isServer = isServer; | |
1483 socket->timeout = timeout; | |
1484 socket->clientSock = NULL; | |
1485 socket->serverSock = NULL; | |
1486 socket->netAddr = &netAddr; | |
1487 | |
1488 socket->callbackList.listenCallback = pkix_pl_Socket_Listen; | |
1489 socket->callbackList.acceptCallback = pkix_pl_Socket_Accept; | |
1490 socket->callbackList.connectcontinueCallback = | |
1491 pkix_pl_Socket_ConnectContinue; | |
1492 socket->callbackList.sendCallback = pkix_pl_Socket_Send; | |
1493 socket->callbackList.recvCallback = pkix_pl_Socket_Recv; | |
1494 socket->callbackList.pollCallback = pkix_pl_Socket_Poll; | |
1495 socket->callbackList.shutdownCallback = pkix_pl_Socket_Shutdown; | |
1496 | |
1497 if (isServer) { | |
1498 PKIX_CHECK(pkix_pl_Socket_CreateServer(socket, plContext), | |
1499 PKIX_SOCKETCREATESERVERFAILED); | |
1500 *pStatus = 0; | |
1501 } else { | |
1502 PKIX_CHECK(pkix_pl_Socket_CreateClient(socket, plContext), | |
1503 PKIX_SOCKETCREATECLIENTFAILED); | |
1504 PKIX_CHECK(pkix_pl_Socket_Connect(socket, pStatus, plContext), | |
1505 PKIX_SOCKETCONNECTFAILED); | |
1506 } | |
1507 | |
1508 *pSocket = socket; | |
1509 | |
1510 cleanup: | |
1511 PL_strfree(localCopyName); | |
1512 | |
1513 if (PKIX_ERROR_RECEIVED) { | |
1514 PKIX_DECREF(socket); | |
1515 } | |
1516 | |
1517 PKIX_RETURN(SOCKET); | |
1518 } | |
1519 | |
1520 /* | |
1521 * FUNCTION: pkix_pl_Socket_CreateByHostAndPort | |
1522 * DESCRIPTION: | |
1523 * | |
1524 * This function creates a new Socket, setting it to be a server or a client | |
1525 * according to the value of "isServer", setting its timeout value from | |
1526 * "timeout", host from "hostname", and port number from "portNum", and stores | |
1527 * the status at "pStatus" and the created Socket at "pSocket". | |
1528 * | |
1529 * If isServer is PKIX_TRUE, it is attempted to create the socket with an ip | |
1530 * address of PR_INADDR_ANY. | |
1531 * | |
1532 * PARAMETERS: | |
1533 * "isServer" | |
1534 * The Boolean value indicating if PKIX_TRUE, that a server socket (using | |
1535 * Bind, Listen, and Accept) is to be created, or if PKIX_FALSE, that a | |
1536 * client socket (using Connect) is to be created. | |
1537 * "timeout" | |
1538 * A PRTimeInterval value to be used for I/O waits for this socket. If | |
1539 * zero, non-blocking I/O is to be used. | |
1540 * "hostname" | |
1541 * Address of a character string consisting of the server's domain name. | |
1542 * "portNum" | |
1543 * UInt16 value of the port number for the desired socket. | |
1544 * "pStatus" | |
1545 * Address at which the PRErrorCode resulting from the create is | |
1546 * stored. Must be non-NULL. | |
1547 * "pSocket" | |
1548 * The address at which the Socket is to be stored. Must be non-NULL. | |
1549 * "plContext" | |
1550 * Platform-specific context pointer. | |
1551 * THREAD SAFETY: | |
1552 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
1553 * RETURNS: | |
1554 * Returns NULL if the function succeeds. | |
1555 * Returns a Socket Error if the function fails in | |
1556 * a non-fatal way. | |
1557 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
1558 */ | |
1559 PKIX_Error * | |
1560 pkix_pl_Socket_CreateByHostAndPort( | |
1561 PKIX_Boolean isServer, | |
1562 PRIntervalTime timeout, | |
1563 char *hostname, | |
1564 PRUint16 portnum, | |
1565 PRErrorCode *pStatus, | |
1566 PKIX_PL_Socket **pSocket, | |
1567 void *plContext) | |
1568 { | |
1569 PRNetAddr netAddr; | |
1570 PKIX_PL_Socket *socket = NULL; | |
1571 char *sepPtr = NULL; | |
1572 PRHostEnt hostent; | |
1573 PRIntn hostenum; | |
1574 PRStatus prstatus = PR_FAILURE; | |
1575 char buf[PR_NETDB_BUF_SIZE]; | |
1576 | |
1577 PKIX_ENTER(SOCKET, "pkix_pl_Socket_CreateByHostAndPort"); | |
1578 PKIX_NULLCHECK_THREE(hostname, pStatus, pSocket); | |
1579 | |
1580 | |
1581 prstatus = PR_GetHostByName(hostname, buf, sizeof(buf), &hostent); | |
1582 | |
1583 if ((prstatus != PR_SUCCESS) || (hostent.h_length != 4)) { | |
1584 /* | |
1585 * The hostname may be a fully-qualified name. Try using just | |
1586 * the leftmost component in our lookup. | |
1587 */ | |
1588 sepPtr = strchr(hostname, '.'); | |
1589 if (sepPtr) { | |
1590 *sepPtr++ = '\0'; | |
1591 } | |
1592 prstatus = PR_GetHostByName(hostname, buf, sizeof(buf), &hostent); | |
1593 | |
1594 if ((prstatus != PR_SUCCESS) || (hostent.h_length != 4)) { | |
1595 PKIX_ERROR | |
1596 (PKIX_PRGETHOSTBYNAMEREJECTSHOSTNAMEARGUMENT); | |
1597 } | |
1598 } | |
1599 | |
1600 netAddr.inet.family = PR_AF_INET; | |
1601 netAddr.inet.port = PR_htons(portnum); | |
1602 | |
1603 if (isServer) { | |
1604 | |
1605 netAddr.inet.ip = PR_INADDR_ANY; | |
1606 | |
1607 } else { | |
1608 | |
1609 hostenum = PR_EnumerateHostEnt(0, &hostent, portnum, &netAddr); | |
1610 if (hostenum == -1) { | |
1611 PKIX_ERROR(PKIX_PRENUMERATEHOSTENTFAILED); | |
1612 } | |
1613 } | |
1614 | |
1615 PKIX_CHECK(PKIX_PL_Object_Alloc | |
1616 (PKIX_SOCKET_TYPE, | |
1617 sizeof (PKIX_PL_Socket), | |
1618 (PKIX_PL_Object **)&socket, | |
1619 plContext), | |
1620 PKIX_COULDNOTCREATESOCKETOBJECT); | |
1621 | |
1622 socket->isServer = isServer; | |
1623 socket->timeout = timeout; | |
1624 socket->clientSock = NULL; | |
1625 socket->serverSock = NULL; | |
1626 socket->netAddr = &netAddr; | |
1627 | |
1628 socket->callbackList.listenCallback = pkix_pl_Socket_Listen; | |
1629 socket->callbackList.acceptCallback = pkix_pl_Socket_Accept; | |
1630 socket->callbackList.connectcontinueCallback = | |
1631 pkix_pl_Socket_ConnectContinue; | |
1632 socket->callbackList.sendCallback = pkix_pl_Socket_Send; | |
1633 socket->callbackList.recvCallback = pkix_pl_Socket_Recv; | |
1634 socket->callbackList.pollCallback = pkix_pl_Socket_Poll; | |
1635 socket->callbackList.shutdownCallback = pkix_pl_Socket_Shutdown; | |
1636 | |
1637 if (isServer) { | |
1638 PKIX_CHECK(pkix_pl_Socket_CreateServer(socket, plContext), | |
1639 PKIX_SOCKETCREATESERVERFAILED); | |
1640 *pStatus = 0; | |
1641 } else { | |
1642 PKIX_CHECK(pkix_pl_Socket_CreateClient(socket, plContext), | |
1643 PKIX_SOCKETCREATECLIENTFAILED); | |
1644 PKIX_CHECK(pkix_pl_Socket_Connect(socket, pStatus, plContext), | |
1645 PKIX_SOCKETCONNECTFAILED); | |
1646 } | |
1647 | |
1648 *pSocket = socket; | |
1649 | |
1650 cleanup: | |
1651 if (PKIX_ERROR_RECEIVED) { | |
1652 PKIX_DECREF(socket); | |
1653 } | |
1654 | |
1655 PKIX_RETURN(SOCKET); | |
1656 } | |
1657 | |
1658 /* | |
1659 * FUNCTION: pkix_pl_Socket_GetCallbackList | |
1660 */ | |
1661 PKIX_Error * | |
1662 pkix_pl_Socket_GetCallbackList( | |
1663 PKIX_PL_Socket *socket, | |
1664 PKIX_PL_Socket_Callback **pCallbackList, | |
1665 void *plContext) | |
1666 { | |
1667 PKIX_ENTER(SOCKET, "pkix_pl_Socket_GetCallbackList"); | |
1668 PKIX_NULLCHECK_TWO(socket, pCallbackList); | |
1669 | |
1670 *pCallbackList = &(socket->callbackList); | |
1671 | |
1672 PKIX_RETURN(SOCKET); | |
1673 } | |
1674 | |
1675 /* | |
1676 * FUNCTION: pkix_pl_Socket_GetPRFileDesc | |
1677 */ | |
1678 PKIX_Error * | |
1679 pkix_pl_Socket_GetPRFileDesc( | |
1680 PKIX_PL_Socket *socket, | |
1681 PRFileDesc **pDesc, | |
1682 void *plContext) | |
1683 { | |
1684 PKIX_ENTER(SOCKET, "pkix_pl_Socket_GetPRFileDesc"); | |
1685 PKIX_NULLCHECK_TWO(socket, pDesc); | |
1686 | |
1687 *pDesc = socket->clientSock; | |
1688 | |
1689 PKIX_RETURN(SOCKET); | |
1690 } |