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 }
This site is hosted by Intevation GmbH (Datenschutzerklärung und Impressum | Privacy Policy and Imprint)