1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
14 * The Original Code is the PKIX-C library.
16 * The Initial Developer of the Original Code is
17 * Sun Microsystems, Inc.
18 * Portions created by the Initial Developer are
19 * Copyright 2004-2007 Sun Microsystems, Inc. All Rights Reserved.
22 * Sun Microsystems, Inc.
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
40 * Socket Function Definitions
45 * If Socket Tracing is active, messages sent and received will be
46 * timestamped and dumped (to stdout) in standard hex-dump format. E.g.,
49 * 28F0: 48 65 6C 6C 6F 2C 20 77 6F 72 6C 64 21 00 Hello, world!.
51 * The timestamp is not formatted to be meaningful except as an increasing
52 * value of seconds.microseconds, which is good enough to correlate two
53 * sides of a message exchange and to figure durations.
55 * Code to perform Socket tracing will be compiled in if PKIX_SOCKETTRACE
56 * is defined, but that doesn't mean socket tracing is active. Tracing also
57 * requires that the Boolean socketTraceFlag is set to PKIX_TRUE. That is
58 * the default value, but it can be overridden by using the debugger to
59 * change its value -- allowing tracing to be turned on and off at various
60 * breakpoints -- or by setting the environment variable SOCKETTRACE. A
61 * value of 1 sets socketTraceFlag to PKIX_TRUE (tracing on), and any other
62 * value sets socketTraceFlag to PKIX_FALSE (tracing off). The environment
63 * value is checked during system initialization.
66 #define PKIX_SOCKETTRACE 1
69 #ifdef PKIX_SOCKETDEBUG
70 #define PKIX_SOCKETTRACE 1
73 #include "pkix_pl_socket.h"
75 /* --Private-Socket-Functions---------------------------------- */
77 #ifdef PKIX_SOCKETTRACE
78 static PKIX_Boolean socketTraceFlag
= PKIX_TRUE
;
81 * FUNCTION: pkix_pl_socket_timestamp
84 * This functions prints to stdout the time of day, as obtained from the
85 * system function gettimeofday, as seconds.microseconds. Its resolution
86 * is whatever the system call provides.
91 * Thread Safe (see Thread Safety definitions in Programmer's Guide)
95 static void pkix_pl_socket_timestamp() {
98 printf("%lld:\n", prTime
);
102 * FUNCTION: pkix_pl_socket_hexDigit
105 * This functions prints to stdout the byte "byteVal" as two hex digits.
109 * The value to be printed.
111 * Thread Safe (see Thread Safety definitions in Programmer's Guide)
115 static void pkix_pl_socket_hexDigit(char byteVal
) {
119 n
= ((byteVal
>> 4) & 0xf);
121 cHi
= (char) ((n
- 10) + 'A');
123 cHi
= (char) (n
+ '0');
127 cLow
= (char) ((n
- 10) + 'A');
129 cLow
= (char) (n
+ '0');
131 (void) printf("%c%c", cHi
, cLow
);
135 * FUNCTION: pkix_pl_socket_linePrefix
138 * This functions prints to stdout the address provided by "addr" as four
139 * hexadecimal digits followed by a colon and a space.
143 * The address to be printed
146 * Thread Safe (see Thread Safety definitions in Programmer's Guide)
150 static void pkix_pl_socket_linePrefix(PKIX_UInt32 addr
) {
151 pkix_pl_socket_hexDigit((char)((addr
>> 8) & 0xff));
152 pkix_pl_socket_hexDigit((char)(addr
& 0xff));
157 * FUNCTION: pkix_pl_socket_traceLine
160 * This functions prints to stdout the sixteen bytes beginning at the
161 * address pointed to by "ptr". The bytes are printed as sixteen pairs
162 * of hexadecimal characters followed by an ascii interpretation, in which
163 * characters from 0x20 to 0x7d are shown as their ascii equivalents, and
164 * other values are represented as periods.
168 * The address of the first of the bytes to be printed
170 * Thread Safe (see Thread Safety definitions in Programmer's Guide)
174 static void pkix_pl_socket_traceLine(char *ptr
) {
176 pkix_pl_socket_linePrefix((PKIX_UInt32
)ptr
);
177 for (i
= 0; i
< 16; i
++) {
179 pkix_pl_socket_hexDigit(ptr
[i
]);
185 for (i
= 0; i
< 16; i
++) {
186 if ((ptr
[i
] < ' ') || (ptr
[i
] > '}')) {
189 printf("%c", ptr
[i
]);
196 * FUNCTION: pkix_pl_socket_tracePartialLine
199 * This functions prints to stdout the number of bytes given by "nBytes",
200 * beginning at the address pointed to by "ptr". The bytes are printed as
201 * pairs of hexadecimal characters followed by an ascii interpretation, in
202 * which characters from 0x20 to 0x7d are shown as their ascii equivalents,
203 * and other values are represented as periods.
207 * The address of the first of the bytes to be printed
209 * The Int32 value giving the number of bytes to be printed. If "nBytes"
210 * is greater than sixteen, the results will be unattractive.
213 * Thread Safe (see Thread Safety definitions in Programmer's Guide)
217 static void pkix_pl_socket_tracePartialLine(char *ptr
, PKIX_UInt32 nBytes
) {
220 pkix_pl_socket_linePrefix((PKIX_UInt32
)ptr
);
222 for (i
= 0; i
< nBytes
; i
++) {
224 pkix_pl_socket_hexDigit(ptr
[i
]);
229 for (i
= nBytes
; i
< 16; i
++) {
236 for (i
= 0; i
< nBytes
; i
++) {
237 if ((ptr
[i
] < ' ') || (ptr
[i
] > '}')) {
240 printf("%c", ptr
[i
]);
247 * FUNCTION: pkix_pl_socket_tracebuff
250 * This functions prints to stdout the number of bytes given by "nBytes",
251 * beginning with the byte pointed to by "buf". The output is preceded by
252 * a timestamp, and each group of sixteen (and a remainder, if any) is
253 * preceded by its address. The contents are shown in hexadecimal and as
254 * ascii characters. If "nBytes" is zero, the timestamp and starting
255 * address are displayed.
259 * The starting address of the bytes to be printed
261 * The number of bytes to be printed
263 * Thread Safe (see Thread Safety definitions in Programmer's Guide)
267 void pkix_pl_socket_tracebuff(void *buf
, PKIX_UInt32 nBytes
) {
268 PKIX_UInt32 bytesRemaining
= nBytes
;
269 PKIX_UInt32 offset
= 0;
270 char *bufptr
= (char *)buf
;
272 if (socketTraceFlag
== PKIX_FALSE
) return;
274 pkix_pl_socket_timestamp();
276 * Special case: if called with length of zero, just do address
279 pkix_pl_socket_linePrefix((PKIX_UInt32
)buf
);
282 while (bytesRemaining
>= 16) {
283 pkix_pl_socket_traceLine(&bufptr
[offset
]);
284 bytesRemaining
-= 16;
287 pkix_pl_socket_tracePartialLine
288 (&bufptr
[offset
], bytesRemaining
);
295 * FUNCTION: pkix_pl_Socket_SetNonBlocking
298 * This functions sets the socket represented by the PRFileDesc "fileDesc"
299 * to nonblocking mode.
303 * The address of the PRFileDesc whose I/O mode is to be set
304 * non-blocking. Must be non-NULL.
306 * Platform-specific context pointer
308 * Thread Safe (see Thread Safety definitions in Programmer's Guide)
313 pkix_pl_Socket_SetNonBlocking(
314 PRFileDesc
*fileDesc
,
317 PRStatus rv
= PR_FAILURE
;
318 PRSocketOptionData sockOptionData
;
320 PKIX_ENTER(SOCKET
, "pkix_pl_Socket_SetNonBlocking");
321 PKIX_NULLCHECK_ONE(fileDesc
);
323 sockOptionData
.option
= PR_SockOpt_Nonblocking
;
324 sockOptionData
.value
.non_blocking
= PR_TRUE
;
326 PKIX_PL_NSSCALLRV(SOCKET
, rv
, fileDesc
->methods
->setsocketoption
,
327 (fileDesc
, &sockOptionData
));
329 if (rv
!= PR_SUCCESS
) {
330 PKIX_ERROR(PKIX_UNABLETOSETSOCKETTONONBLOCKING
);
338 * FUNCTION: pkix_pl_Socket_CreateClient
341 * This functions creates a client socket for the PKIX_PL_Socket pointed to
342 * by "socket". If "socket" was created with a timeout value of zero, the
343 * client socket is set to use nonblocking I/O.
347 * The address of the Socket for which a client socket is to be
348 * created. Must be non-NULL.
350 * Platform-specific context pointer
352 * Thread Safe (see Thread Safety definitions in Programmer's Guide)
358 pkix_pl_Socket_CreateClient(
359 PKIX_PL_Socket
*socket
,
362 #ifdef PKIX_SOCKETDEBUG
363 PRErrorCode errorcode
= 0;
365 PRFileDesc
*mySock
= NULL
;
367 PKIX_ENTER(SOCKET
, "pkix_pl_Socket_CreateClient");
368 PKIX_NULLCHECK_ONE(socket
);
370 PKIX_PL_NSSCALLRV(SOCKET
, mySock
, PR_NewTCPSocket
, ());
372 #ifdef PKIX_SOCKETDEBUG
373 errorcode
= PR_GetError();
375 ("pkix_pl_Socket_CreateClient: %s\n",
376 PR_ErrorToString(errorcode
, PR_LANGUAGE_EN
));
378 PKIX_ERROR(PKIX_PRNEWTCPSOCKETFAILED
);
381 #ifdef PKIX_SOCKETDEBUG
382 printf("Created socket, PRFileDesc @ %#X\n", mySock
);
385 socket
->clientSock
= mySock
;
386 socket
->status
= SOCKET_UNCONNECTED
;
387 if (socket
->timeout
== 0) {
388 PKIX_CHECK(pkix_pl_Socket_SetNonBlocking(mySock
, plContext
),
389 PKIX_SOCKETSETNONBLOCKINGFAILED
);
398 * FUNCTION: pkix_pl_Socket_CreateServer
401 * This functions creates a server socket for the PKIX_PL_Socket pointed to
402 * by "socket". If "socket" was created with a timeout value of zero, the
403 * server socket is set to use nonblocking I/O.
405 * Warning: there seems to be a problem with operating a server socket in
406 * non-blocking mode. If the server calls Recv prior to a corresponding
407 * Send, the message may be lost.
411 * The address of the Socket for which a server socket is to be
412 * created. Must be non-NULL.
414 * Platform-specific context pointer
416 * Thread Safe (see Thread Safety definitions in Programmer's Guide)
421 pkix_pl_Socket_CreateServer(
422 PKIX_PL_Socket
*socket
,
425 /* #ifdef PKIX_SOCKETDEBUG */
426 PRErrorCode errorcode
= 0;
428 PRStatus rv
= PR_FAILURE
;
429 PRFileDesc
*serverSock
= NULL
;
430 PRSocketOptionData sockOptionData
;
432 PKIX_ENTER(SOCKET
, "pkix_pl_Socket_CreateServer");
433 PKIX_NULLCHECK_ONE(socket
);
435 PKIX_PL_NSSCALLRV(SOCKET
, serverSock
, PR_NewTCPSocket
, ());
437 #ifdef PKIX_SOCKETDEBUG
438 errorcode
= PR_GetError();
440 ("pkix_pl_Socket_CreateServer: %s\n",
441 PR_ErrorToString(errorcode
, PR_LANGUAGE_EN
));
443 PKIX_ERROR(PKIX_PRNEWTCPSOCKETFAILED
);
446 socket
->serverSock
= serverSock
;
448 #ifdef PKIX_SOCKETDEBUG
449 printf("Created socket, PRFileDesc @ %#X\n", serverSock
);
452 if (socket
->timeout
== 0) {
453 PKIX_CHECK(pkix_pl_Socket_SetNonBlocking(serverSock
, plContext
),
454 PKIX_SOCKETSETNONBLOCKINGFAILED
);
457 sockOptionData
.option
= PR_SockOpt_Reuseaddr
;
458 sockOptionData
.value
.reuse_addr
= PR_TRUE
;
460 PKIX_PL_NSSCALLRV(SOCKET
, rv
, serverSock
->methods
->setsocketoption
,
461 (serverSock
, &sockOptionData
));
463 if (rv
!= PR_SUCCESS
) {
464 PKIX_ERROR(PKIX_UNABLETOSETSOCKETTONONBLOCKING
);
467 PKIX_PL_NSSCALLRV(SOCKET
, rv
, PR_Bind
, (serverSock
, socket
->netAddr
));
469 if (rv
== PR_FAILURE
) {
470 /* #ifdef PKIX_SOCKETDEBUG */
471 errorcode
= PR_GetError();
473 ("pkix_pl_Socket_CreateServer: %s\n",
474 PR_ErrorToString(errorcode
, PR_LANGUAGE_EN
));
476 PKIX_ERROR(PKIX_PRBINDFAILED
);
479 #ifdef PKIX_SOCKETDEBUG
480 printf("Successful bind!\n");
483 socket
->status
= SOCKET_BOUND
;
491 * FUNCTION: pkix_pl_Socket_Connect
494 * This functions performs the connect function for the client socket
495 * specified in "socket", storing the status at "pStatus".
499 * The address of the Socket for which a connect is to be performed.
502 * The address at which the connection status is stored. Must be non-NULL.
504 * Platform-specific context pointer
506 * Thread Safe (see Thread Safety definitions in Programmer's Guide)
511 pkix_pl_Socket_Connect(
512 PKIX_PL_Socket
*socket
,
513 PRErrorCode
*pStatus
,
516 PRStatus rv
= PR_FAILURE
;
517 PRErrorCode errorcode
= 0;
519 PKIX_ENTER(SOCKET
, "pkix_pl_Socket_Connect");
520 PKIX_NULLCHECK_TWO(socket
, socket
->clientSock
);
522 PKIX_PL_NSSCALLRV(SOCKET
, rv
, PR_Connect
,
523 (socket
->clientSock
, socket
->netAddr
, socket
->timeout
));
525 if (rv
== PR_FAILURE
) {
526 errorcode
= PR_GetError();
527 *pStatus
= errorcode
;
528 if (errorcode
== PR_IN_PROGRESS_ERROR
) {
529 socket
->status
= SOCKET_CONNECTPENDING
;
532 #ifdef PKIX_SOCKETDEBUG
534 ("pkix_pl_Socket_Connect: %s\n",
535 PR_ErrorToString(errorcode
, PR_LANGUAGE_EN
));
537 PKIX_ERROR(PKIX_PRCONNECTFAILED
);
541 #ifdef PKIX_SOCKETDEBUG
542 printf("Successful connect!\n");
546 socket
->status
= SOCKET_CONNECTED
;
554 * FUNCTION: pkix_pl_Socket_ConnectContinue
557 * This functions continues the connect function for the client socket
558 * specified in "socket", storing the status at "pStatus". It is expected that
559 * the non-blocking connect has returned PR_IN_PROGRESS_ERROR.
563 * The address of the Socket for which a connect is to be continued.
566 * The address at which the connection status is stored. Must be non-NULL.
568 * Platform-specific context pointer
570 * Thread Safe (see Thread Safety definitions in Programmer's Guide)
575 pkix_pl_Socket_ConnectContinue(
576 PKIX_PL_Socket
*socket
,
577 PRErrorCode
*pStatus
,
580 PRStatus rv
= PR_FAILURE
;
581 PRErrorCode errorcode
= 0;
583 PRInt32 numEvents
= 0;
585 PKIX_ENTER(SOCKET
, "pkix_pl_Socket_ConnectContinue");
586 PKIX_NULLCHECK_TWO(socket
, socket
->clientSock
);
588 pollDesc
.fd
= socket
->clientSock
;
589 pollDesc
.in_flags
= PR_POLL_WRITE
| PR_POLL_EXCEPT
;
590 pollDesc
.out_flags
= 0;
591 PKIX_PL_NSSCALLRV(SOCKET
, numEvents
, PR_Poll
, (&pollDesc
, 1, 0));
593 PKIX_ERROR(PKIX_PRPOLLFAILED
);
596 if (numEvents
== 0) {
597 *pStatus
= PR_IN_PROGRESS_ERROR
;
601 PKIX_PL_NSSCALLRV(SOCKET
, rv
, PR_ConnectContinue
,
602 (socket
->clientSock
, pollDesc
.out_flags
));
605 * PR_ConnectContinue sometimes lies. It returns PR_SUCCESS
606 * even though the connection is not yet ready. But its deceit
607 * is betrayed by the contents of out_flags!
609 if ((rv
== PR_SUCCESS
) && (pollDesc
.out_flags
== PR_POLL_ERR
)) {
610 *pStatus
= PR_IN_PROGRESS_ERROR
;
614 if (rv
== PR_FAILURE
) {
615 errorcode
= PR_GetError();
616 *pStatus
= errorcode
;
617 if (errorcode
== PR_IN_PROGRESS_ERROR
) {
620 #ifdef PKIX_SOCKETDEBUG
622 ("pkix_pl_Socket_ConnectContinue: %s\n",
623 PR_ErrorToString(errorcode
, PR_LANGUAGE_EN
));
625 PKIX_ERROR(PKIX_PRCONNECTCONTINUEFAILED
);
629 #ifdef PKIX_SOCKETDEBUG
630 printf("Successful connect!\n");
634 socket
->status
= SOCKET_CONNECTED
;
642 * FUNCTION: pkix_pl_Socket_Destroy
643 * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
646 pkix_pl_Socket_Destroy(
647 PKIX_PL_Object
*object
,
650 PKIX_PL_Socket
*socket
= NULL
;
652 PKIX_ENTER(SOCKET
, "pkix_pl_Socket_Destroy");
653 PKIX_NULLCHECK_ONE(object
);
655 PKIX_CHECK(pkix_CheckType
656 (object
, PKIX_SOCKET_TYPE
, plContext
),
657 PKIX_OBJECTNOTANSOCKET
);
659 socket
= (PKIX_PL_Socket
*)object
;
661 if (socket
->isServer
) {
662 if (socket
->serverSock
) {
663 PR_Close(socket
->serverSock
);
666 if (socket
->clientSock
) {
667 PR_Close(socket
->clientSock
);
677 * FUNCTION: pkix_pl_Socket_Hashcode
678 * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
681 pkix_pl_Socket_Hashcode(
682 PKIX_PL_Object
*object
,
683 PKIX_UInt32
*pHashcode
,
686 PKIX_PL_Socket
*socket
= NULL
;
688 PKIX_ENTER(SOCKET
, "pkix_pl_Socket_Hashcode");
689 PKIX_NULLCHECK_TWO(object
, pHashcode
);
691 PKIX_CHECK(pkix_CheckType(object
, PKIX_SOCKET_TYPE
, plContext
),
692 PKIX_OBJECTNOTSOCKET
);
694 socket
= (PKIX_PL_Socket
*)object
;
696 *pHashcode
= (((socket
->timeout
<< 3) +
697 (socket
->netAddr
->inet
.family
<< 3)) +
698 (*((PKIX_UInt32
*)&(socket
->netAddr
->inet
.ip
)))) +
699 socket
->netAddr
->inet
.port
;
707 * FUNCTION: pkix_pl_Socket_Equals
708 * (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h)
711 pkix_pl_Socket_Equals(
712 PKIX_PL_Object
*firstObject
,
713 PKIX_PL_Object
*secondObject
,
717 PKIX_PL_Socket
*firstSocket
= NULL
;
718 PKIX_PL_Socket
*secondSocket
= NULL
;
720 PKIX_ENTER(SOCKET
, "pkix_pl_Socket_Equals");
721 PKIX_NULLCHECK_THREE(firstObject
, secondObject
, pResult
);
723 *pResult
= PKIX_FALSE
;
725 PKIX_CHECK(pkix_CheckTypes
726 (firstObject
, secondObject
, PKIX_SOCKET_TYPE
, plContext
),
727 PKIX_OBJECTNOTSOCKET
);
729 firstSocket
= (PKIX_PL_Socket
*)firstObject
;
730 secondSocket
= (PKIX_PL_Socket
*)secondObject
;
732 if (firstSocket
->timeout
!= secondSocket
->timeout
) {
736 if (firstSocket
->netAddr
== secondSocket
->netAddr
) {
737 *pResult
= PKIX_TRUE
;
741 if ((firstSocket
->netAddr
->inet
.family
!=
742 secondSocket
->netAddr
->inet
.family
) ||
743 (*((PKIX_UInt32
*)&(firstSocket
->netAddr
->inet
.ip
)) !=
744 *((PKIX_UInt32
*)&(secondSocket
->netAddr
->inet
.ip
))) ||
745 (firstSocket
->netAddr
->inet
.port
!=
746 secondSocket
->netAddr
->inet
.port
)) {
752 *pResult
= PKIX_TRUE
;
760 * FUNCTION: pkix_pl_Socket_RegisterSelf
763 * Registers PKIX_PL_SOCKET_TYPE and its related
764 * functions with systemClasses[]
767 * Not Thread Safe - for performance and complexity reasons
769 * Since this function is only called by PKIX_PL_Initialize, which should
770 * only be called once, it is acceptable that this function is not
774 pkix_pl_Socket_RegisterSelf(void *plContext
)
776 extern pkix_ClassTable_Entry systemClasses
[PKIX_NUMTYPES
];
777 pkix_ClassTable_Entry entry
;
779 PKIX_ENTER(SOCKET
, "pkix_pl_Socket_RegisterSelf");
781 entry
.description
= "Socket";
782 entry
.objCounter
= 0;
783 entry
.typeObjectSize
= sizeof(PKIX_PL_Socket
);
784 entry
.destructor
= pkix_pl_Socket_Destroy
;
785 entry
.equalsFunction
= pkix_pl_Socket_Equals
;
786 entry
.hashcodeFunction
= pkix_pl_Socket_Hashcode
;
787 entry
.toStringFunction
= NULL
;
788 entry
.comparator
= NULL
;
789 entry
.duplicateFunction
= NULL
;
791 systemClasses
[PKIX_SOCKET_TYPE
] = entry
;
793 #ifdef PKIX_SOCKETTRACE
796 val
= PR_GetEnv("SOCKETTRACE");
797 /* Is SOCKETTRACE set in the environment? */
798 if ((val
!= NULL
) && (*val
!= '\0')) {
800 ((*val
== '1')?PKIX_TRUE
:PKIX_FALSE
);
808 /* --Public-Socket-Functions----------------------------------- */
811 * FUNCTION: pkix_pl_Socket_Listen
814 * This functions establishes a listening queue for the server Socket
815 * pointed to by "socket".
819 * The address of the server socket for which the queue is to be
820 * established. Must be non-NULL.
822 * The UInt32 value of the length of the queue to be established.
824 * Platform-specific context pointer
826 * Thread Safe (see Thread Safety definitions in Programmer's Guide)
831 pkix_pl_Socket_Listen(
832 PKIX_PL_Socket
*socket
,
836 #ifdef PKIX_SOCKETDEBUG
837 PRErrorCode errorcode
= 0;
839 PRStatus rv
= PR_FAILURE
;
841 PKIX_ENTER(SOCKET
, "pkix_pl_Socket_Listen");
842 PKIX_NULLCHECK_TWO(socket
, socket
->serverSock
);
844 PKIX_PL_NSSCALLRV(SOCKET
, rv
, PR_Listen
,
845 (socket
->serverSock
, (PRIntn
)backlog
));
847 if (rv
== PR_FAILURE
) {
848 #ifdef PKIX_SOCKETDEBUG
849 errorcode
= PR_GetError();
851 ("pkix_pl_Socket_Listen: %s\n",
852 PR_ErrorToString(errorcode
, PR_LANGUAGE_EN
));
854 PKIX_ERROR(PKIX_PRLISTENFAILED
);
857 #ifdef PKIX_SOCKETDEBUG
858 printf("Successful listen!\n");
861 socket
->status
= SOCKET_LISTENING
;
868 * FUNCTION: pkix_pl_Socket_Shutdown
871 * This functions performs the shutdown of any connections controlled by the
872 * socket pointed to by "socket".
876 * The address of the socket to be shut down. Must be non-NULL.
878 * Platform-specific context pointer
880 * Thread Safe (see Thread Safety definitions in Programmer's Guide)
885 pkix_pl_Socket_Shutdown(
886 PKIX_PL_Socket
*socket
,
889 #ifdef PKIX_SOCKETDEBUG
890 PRErrorCode errorcode
= 0;
892 PRStatus rv
= PR_FAILURE
;
893 PRFileDesc
*fileDesc
= NULL
;
895 PKIX_ENTER(SOCKET
, "pkix_pl_Socket_Shutdown");
896 PKIX_NULLCHECK_ONE(socket
);
899 (socket
->isServer
)?(socket
->serverSock
):(socket
->clientSock
);
901 PKIX_PL_NSSCALLRV(SOCKET
, rv
, PR_Shutdown
,
902 (fileDesc
, PR_SHUTDOWN_BOTH
));
904 if (rv
== PR_FAILURE
) {
905 #ifdef PKIX_SOCKETDEBUG
906 errorcode
= PR_GetError();
908 ("pkix_pl_Socket_Shutdown: %s\n",
909 PR_ErrorToString(errorcode
, PR_LANGUAGE_EN
));
911 PKIX_ERROR(PKIX_PRSHUTDOWNFAILED
);
913 socket
->status
= SOCKET_SHUTDOWN
;
921 * FUNCTION: pkix_pl_Socket_Send
924 * This functions sends a message using the socket pointed to by "sendSock",
925 * from the buffer pointed to by "buf", of the number of bytes given by
926 * "bytesToWrite", storing the number of bytes actually written at
927 * "pBytesWritten". If "socket" is in non-blocking mode, the send operation
928 * may store -1 at "pBytesWritten" and the write is not complete until a
929 * corresponding pkix_pl_Poll call has indicated its completion by returning
930 * a non-negative value for bytes written.
934 * The address of the Socket on which the message is to be sent. Must
937 * The address of the data to be sent. Must be non-NULL.
939 * The UInt32 value indicating the number of bytes to write.
941 * The address at which the Int32 value indicating the number of bytes
942 * actually written is to be stored. Must be non-NULL.
944 * Platform-specific context pointer
946 * Thread Safe (see Thread Safety definitions in Programmer's Guide)
952 PKIX_PL_Socket
*sendSock
,
954 PKIX_UInt32 bytesToWrite
,
955 PKIX_Int32
*pBytesWritten
,
958 PRInt32 bytesWritten
= 0;
959 PRErrorCode errorcode
= 0;
960 PRFileDesc
*fd
= NULL
;
962 PKIX_ENTER(SOCKET
, "pkix_pl_Socket_Send");
963 PKIX_NULLCHECK_TWO(buf
, pBytesWritten
);
965 fd
= sendSock
->clientSock
;
967 PKIX_PL_NSSCALLRV(SOCKET
, bytesWritten
, PR_Send
,
968 (fd
, buf
, (PRInt32
)bytesToWrite
, 0, sendSock
->timeout
));
970 if (bytesWritten
>= 0) {
971 if (sendSock
->status
== SOCKET_SENDRCVPENDING
) {
972 sendSock
->status
= SOCKET_RCVPENDING
;
974 sendSock
->status
= SOCKET_CONNECTED
;
976 #ifdef PKIX_SOCKETTRACE
977 pkix_pl_socket_tracebuff(buf
, bytesWritten
);
980 errorcode
= PR_GetError();
981 if (errorcode
!= PR_WOULD_BLOCK_ERROR
) {
982 #ifdef PKIX_SOCKETDEBUG
984 ("pkix_pl_Socket_Send: %s\n",
985 PR_ErrorToString(errorcode
, PR_LANGUAGE_EN
));
987 PKIX_ERROR(PKIX_PRSENDFAILED
);
990 sendSock
->writeBuf
= buf
;
991 sendSock
->writeBufSize
= bytesToWrite
;
992 if (sendSock
->status
== SOCKET_RCVPENDING
) {
993 sendSock
->status
= SOCKET_SENDRCVPENDING
;
995 sendSock
->status
= SOCKET_SENDPENDING
;
999 *pBytesWritten
= (PKIX_Int32
)bytesWritten
;
1003 PKIX_RETURN(SOCKET
);
1007 * FUNCTION: pkix_pl_Socket_Recv
1010 * This functions receives a message on the socket pointed to by "rcvSock",
1011 * into the buffer pointed to by "buf", of capacity given by "capacity",
1012 * storing the number of bytes actually received at "pBytesRead". If "socket"
1013 * is in non-blocking mode, the receive operation may store -1 at
1014 * "pBytesWritten". In that case the write is not complete until a
1015 * corresponding pkix_pl_Poll call has indicated its completion by returning
1016 * a non-negative value for bytes read.
1020 * The address of the Socket on which the message is to be received.
1023 * The address of the buffer into which the message is to be received.
1026 * The UInt32 value of the size of the buffer; that is, the maximum
1027 * number of bytes that can be received.
1029 * The address at which is stored the Int32 value of the number of bytes
1030 * actually received.
1032 * Platform-specific context pointer
1034 * Thread Safe (see Thread Safety definitions in Programmer's Guide)
1039 pkix_pl_Socket_Recv(
1040 PKIX_PL_Socket
*rcvSock
,
1042 PKIX_UInt32 capacity
,
1043 PKIX_Int32
*pBytesRead
,
1046 PRErrorCode errorcode
= 0;
1047 PRInt32 bytesRead
= 0;
1048 PRFileDesc
*fd
= NULL
;
1050 PKIX_ENTER(SOCKET
, "pkix_pl_Socket_Recv");
1051 PKIX_NULLCHECK_THREE(rcvSock
, buf
, pBytesRead
);
1053 fd
= rcvSock
->clientSock
;
1055 PKIX_PL_NSSCALLRV(SOCKET
, bytesRead
, PR_Recv
,
1056 (fd
, buf
, (PRInt32
)capacity
, 0, rcvSock
->timeout
));
1058 if (bytesRead
> 0) {
1059 if (rcvSock
->status
== SOCKET_SENDRCVPENDING
) {
1060 rcvSock
->status
= SOCKET_SENDPENDING
;
1062 rcvSock
->status
= SOCKET_CONNECTED
;
1064 #ifdef PKIX_SOCKETTRACE
1065 pkix_pl_socket_tracebuff(buf
, bytesRead
);
1067 } else if (bytesRead
== 0) {
1068 PKIX_ERROR(PKIX_PRRECVREPORTSNETWORKCONNECTIONCLOSED
);
1070 errorcode
= PR_GetError();
1071 if (errorcode
!= PR_WOULD_BLOCK_ERROR
) {
1072 #ifdef PKIX_SOCKETDEBUG
1074 ("pkix_pl_Socket_Recv: %s\n",
1075 PR_ErrorToString(errorcode
, PR_LANGUAGE_EN
));
1077 PKIX_ERROR(PKIX_PRRECVFAILED
);
1079 rcvSock
->readBuf
= buf
;
1080 rcvSock
->readBufSize
= capacity
;
1081 if (rcvSock
->status
== SOCKET_SENDPENDING
) {
1082 rcvSock
->status
= SOCKET_SENDRCVPENDING
;
1084 rcvSock
->status
= SOCKET_RCVPENDING
;
1089 *pBytesRead
= (PKIX_Int32
)bytesRead
;
1093 PKIX_RETURN(SOCKET
);
1097 * FUNCTION: pkix_pl_Socket_Poll
1100 * This functions checks for completion of an earlier Send or Recv on the
1101 * socket pointed to by "sock", storing in "pBytesWritten" the number of bytes
1102 * written by a completed Send and in "pBytesRead" the number of bytes
1103 * received in a completed Recv. A value of -1 returned indicates the
1104 * operation has still not completed. A NULL pointer may be supplied for
1105 * "pBytesWritten" to avoid checking for completion of a Send. A NULL pointer
1106 * may be supplied for "pBytesRead" to avoid checking for completion of a Recv.
1110 * The address of the socket for which completions are to be checked.
1112 * The address at which the number of bytes written is to be stored, if
1113 * a pending Send has completed. If NULL, Sends are not checked.
1115 * The address at which the number of bytes read is to be stored, if
1116 * a pending Recv has completed. If NULL, Recvs are not checked.
1118 * Platform-specific context pointer
1120 * Thread Safe (see Thread Safety definitions in Programmer's Guide)
1125 pkix_pl_Socket_Poll(
1126 PKIX_PL_Socket
*sock
,
1127 PKIX_Int32
*pBytesWritten
,
1128 PKIX_Int32
*pBytesRead
,
1131 PRPollDesc pollDesc
;
1132 PRInt32 numEvents
= 0;
1133 PKIX_Int32 bytesRead
= 0;
1134 PKIX_Int32 bytesWritten
= 0;
1135 PRErrorCode errorcode
= 0;
1137 PKIX_ENTER(SOCKET
, "pkix_pl_Socket_Poll");
1138 PKIX_NULLCHECK_ONE(sock
);
1140 pollDesc
.fd
= sock
->clientSock
;
1141 pollDesc
.in_flags
= 0;
1142 pollDesc
.out_flags
= 0;
1144 if ((pBytesWritten
) &&
1145 ((sock
->status
== SOCKET_SENDPENDING
) ||
1146 (sock
->status
= SOCKET_SENDRCVPENDING
))) {
1147 pollDesc
.in_flags
= PR_POLL_WRITE
;
1151 ((sock
->status
= SOCKET_RCVPENDING
) ||
1152 (sock
->status
= SOCKET_SENDRCVPENDING
))) {
1153 pollDesc
.in_flags
|= PR_POLL_READ
;
1156 PKIX_PL_NSSCALLRV(SOCKET
, numEvents
, PR_Poll
, (&pollDesc
, 1, 0));
1158 if (numEvents
< 0) {
1159 PKIX_ERROR(PKIX_PRPOLLFAILED
);
1160 } else if (numEvents
> 0) {
1161 if (pollDesc
.out_flags
& PR_POLL_WRITE
) {
1162 PKIX_CHECK(pkix_pl_Socket_Send
1168 PKIX_SOCKETSENDFAILED
);
1169 *pBytesWritten
= (PKIX_Int32
)bytesWritten
;
1170 if (bytesWritten
>= 0) {
1171 sock
->writeBuf
= NULL
;
1172 sock
->writeBufSize
= 0;
1176 if (pollDesc
.out_flags
& PR_POLL_READ
) {
1177 PKIX_CHECK(pkix_pl_Socket_Recv
1183 PKIX_SOCKETRECVFAILED
);
1184 *pBytesRead
= (PKIX_Int32
)bytesRead
;
1185 if (bytesRead
>= 0) {
1186 sock
->readBuf
= NULL
;
1187 sock
->readBufSize
= 0;
1190 } else if (numEvents
== 0) {
1191 errorcode
= PR_GetError();
1192 if (errorcode
!= PR_WOULD_BLOCK_ERROR
) {
1193 #ifdef PKIX_SOCKETDEBUG
1195 ("pkix_pl_Socket_Poll: %s\n",
1196 PR_ErrorToString(errorcode
, PR_LANGUAGE_EN
));
1198 PKIX_ERROR(PKIX_PRPOLLFAILED
);
1200 if (pBytesWritten
) {
1210 PKIX_RETURN(SOCKET
);
1214 * FUNCTION: pkix_pl_Socket_Accept
1217 * This functions accepts a client connection for the server Socket pointed
1218 * to by "serverSocket", creating a new Socket and storing the result at
1219 * "pRendezvousSocket". If "serverSocket" is in non-blocking mode, this
1220 * function will return NULL if there is no client connection to accept.
1221 * Otherwise this function will block until a connection is available.
1222 * When a client connection is available the new Socket will have the same
1223 * blocking/non-blocking property as "serverSocket".
1227 * The address of the Socket for which a client connection is to be
1228 * accepted. Must be non-NULL.
1229 * "pRendezvousSocket"
1230 * The address at which the created Socket is stored, when a client
1231 * connection is available, or at which NULL is stored, if no connection
1232 * is available for a non-blocking "serverSocket". Must be non-NULL.
1234 * Platform-specific context pointer
1236 * Thread Safe (see Thread Safety definitions in Programmer's Guide)
1241 pkix_pl_Socket_Accept(
1242 PKIX_PL_Socket
*serverSocket
,
1243 PKIX_PL_Socket
**pRendezvousSocket
,
1246 PRErrorCode errorcode
= 0;
1247 PRFileDesc
*rendezvousSock
= NULL
;
1248 PRNetAddr
*clientAddr
= NULL
;
1249 PKIX_PL_Socket
*newSocket
= NULL
;
1251 PKIX_ENTER(SOCKET
, "pkix_pl_Socket_Accept");
1252 PKIX_NULLCHECK_TWO(serverSocket
, pRendezvousSocket
);
1254 PKIX_PL_NSSCALLRV(SOCKET
, rendezvousSock
, PR_Accept
,
1255 (serverSocket
->serverSock
, clientAddr
, serverSocket
->timeout
));
1257 if (!rendezvousSock
) {
1258 errorcode
= PR_GetError();
1259 if (errorcode
!= PR_WOULD_BLOCK_ERROR
) {
1260 #ifdef PKIX_SOCKETDEBUG
1262 ("pkix_pl_Socket_Accept: %s\n",
1263 PR_ErrorToString(errorcode
, PR_LANGUAGE_EN
));
1265 PKIX_ERROR(PKIX_PRACCEPTFAILED
);
1267 serverSocket
->status
= SOCKET_ACCEPTPENDING
;
1268 *pRendezvousSocket
= NULL
;
1273 #ifdef PKIX_SOCKETDEBUG
1274 printf("Successful accept!\n");
1277 PKIX_CHECK(PKIX_PL_Object_Alloc
1279 sizeof (PKIX_PL_Socket
),
1280 (PKIX_PL_Object
**)&newSocket
,
1282 PKIX_COULDNOTCREATESOCKETOBJECT
);
1284 newSocket
->isServer
= PKIX_FALSE
;
1285 newSocket
->timeout
= serverSocket
->timeout
;
1286 newSocket
->clientSock
= rendezvousSock
;
1287 newSocket
->serverSock
= NULL
;
1288 newSocket
->netAddr
= NULL
;
1289 newSocket
->status
= SOCKET_CONNECTED
;
1290 newSocket
->callbackList
.shutdownCallback
= pkix_pl_Socket_Shutdown
;
1291 newSocket
->callbackList
.listenCallback
= pkix_pl_Socket_Listen
;
1292 newSocket
->callbackList
.acceptCallback
= pkix_pl_Socket_Accept
;
1293 newSocket
->callbackList
.connectcontinueCallback
=
1294 pkix_pl_Socket_ConnectContinue
;
1295 newSocket
->callbackList
.sendCallback
= pkix_pl_Socket_Send
;
1296 newSocket
->callbackList
.recvCallback
= pkix_pl_Socket_Recv
;
1297 newSocket
->callbackList
.pollCallback
= pkix_pl_Socket_Poll
;
1299 if (serverSocket
->timeout
== 0) {
1300 PKIX_CHECK(pkix_pl_Socket_SetNonBlocking
1301 (rendezvousSock
, plContext
),
1302 PKIX_SOCKETSETNONBLOCKINGFAILED
);
1305 *pRendezvousSocket
= newSocket
;
1309 PKIX_RETURN(SOCKET
);
1313 * FUNCTION: pkix_pl_Socket_Create
1316 * This function creates a new Socket, setting it to be a server or a client
1317 * according to the value of "isServer", setting its timeout value from
1318 * "timeout" and server address from "netAddr", and stores the created Socket
1323 * The Boolean value indicating if PKIX_TRUE, that a server socket (using
1324 * Bind, Listen, and Accept) is to be created, or if PKIX_FALSE, that a
1325 * client socket (using Connect) is to be created.
1327 * A PRTimeInterval value to be used for I/O waits for this socket. If
1328 * zero, non-blocking I/O is to be used.
1330 * The PRNetAddr to be used for the Bind function, if this is a server
1331 * socket, or for the Connect, if this is a client socket.
1333 * The address at which the Socket is to be stored. Must be non-NULL.
1335 * Platform-specific context pointer.
1337 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
1339 * Returns NULL if the function succeeds.
1340 * Returns a Socket Error if the function fails in
1342 * Returns a Fatal Error if the function fails in an unrecoverable way.
1345 pkix_pl_Socket_Create(
1346 PKIX_Boolean isServer
,
1347 PRIntervalTime timeout
,
1349 PRErrorCode
*status
,
1350 PKIX_PL_Socket
**pSocket
,
1353 PKIX_PL_Socket
*socket
= NULL
;
1355 PKIX_ENTER(SOCKET
, "pkix_pl_Socket_Create");
1356 PKIX_NULLCHECK_ONE(pSocket
);
1358 PKIX_CHECK(PKIX_PL_Object_Alloc
1360 sizeof (PKIX_PL_Socket
),
1361 (PKIX_PL_Object
**)&socket
,
1363 PKIX_COULDNOTCREATESOCKETOBJECT
);
1365 socket
->isServer
= isServer
;
1366 socket
->timeout
= timeout
;
1367 socket
->clientSock
= NULL
;
1368 socket
->serverSock
= NULL
;
1369 socket
->netAddr
= netAddr
;
1371 socket
->callbackList
.listenCallback
= pkix_pl_Socket_Listen
;
1372 socket
->callbackList
.acceptCallback
= pkix_pl_Socket_Accept
;
1373 socket
->callbackList
.connectcontinueCallback
=
1374 pkix_pl_Socket_ConnectContinue
;
1375 socket
->callbackList
.sendCallback
= pkix_pl_Socket_Send
;
1376 socket
->callbackList
.recvCallback
= pkix_pl_Socket_Recv
;
1377 socket
->callbackList
.pollCallback
= pkix_pl_Socket_Poll
;
1378 socket
->callbackList
.shutdownCallback
= pkix_pl_Socket_Shutdown
;
1381 PKIX_CHECK(pkix_pl_Socket_CreateServer(socket
, plContext
),
1382 PKIX_SOCKETCREATESERVERFAILED
);
1385 socket
->timeout
= timeout
;
1386 PKIX_CHECK(pkix_pl_Socket_CreateClient(socket
, plContext
),
1387 PKIX_SOCKETCREATECLIENTFAILED
);
1388 PKIX_CHECK(pkix_pl_Socket_Connect(socket
, status
, plContext
),
1389 PKIX_SOCKETCONNECTFAILED
);
1395 if (PKIX_ERROR_RECEIVED
) {
1396 PKIX_DECREF(socket
);
1399 PKIX_RETURN(SOCKET
);
1403 * FUNCTION: pkix_pl_Socket_CreateByName
1406 * This function creates a new Socket, setting it to be a server or a client
1407 * according to the value of "isServer", setting its timeout value from
1408 * "timeout" and server address and port number from "serverName", and stores
1409 * the status at "pStatus" and the created Socket at "pSocket".
1411 * If isServer is PKIX_TRUE, it is attempted to create the socket with an ip
1412 * address of PR_INADDR_ANY.
1416 * The Boolean value indicating if PKIX_TRUE, that a server socket (using
1417 * Bind, Listen, and Accept) is to be created, or if PKIX_FALSE, that a
1418 * client socket (using Connect) is to be created.
1420 * A PRTimeInterval value to be used for I/O waits for this socket. If
1421 * zero, non-blocking I/O is to be used.
1423 * Address of a character string consisting of the server's domain name
1424 * followed by a colon and a port number for the desired socket.
1426 * Address at which the PRErrorCode resulting from the create is
1427 * stored. Must be non-NULL.
1429 * The address at which the Socket is to be stored. Must be non-NULL.
1431 * Platform-specific context pointer.
1433 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
1435 * Returns NULL if the function succeeds.
1436 * Returns a Socket Error if the function fails in
1438 * Returns a Fatal Error if the function fails in an unrecoverable way.
1441 pkix_pl_Socket_CreateByName(
1442 PKIX_Boolean isServer
,
1443 PRIntervalTime timeout
,
1445 PRErrorCode
*pStatus
,
1446 PKIX_PL_Socket
**pSocket
,
1450 PKIX_PL_Socket
*socket
= NULL
;
1451 char *sepPtr
= NULL
;
1454 PRStatus prstatus
= PR_FAILURE
;
1455 char buf
[PR_NETDB_BUF_SIZE
];
1456 PRUint16 portNum
= 0;
1457 char *localCopyName
= NULL
;
1459 PKIX_ENTER(SOCKET
, "pkix_pl_Socket_CreateByName");
1460 PKIX_NULLCHECK_TWO(serverName
, pSocket
);
1462 localCopyName
= PL_strdup(serverName
);
1464 sepPtr
= strchr(localCopyName
, ':');
1465 /* First strip off the portnum, if present, from the end of the name */
1468 portNum
= (PRUint16
)atoi(sepPtr
);
1470 portNum
= (PRUint16
)LDAP_PORT
;
1473 prstatus
= PR_GetHostByName(localCopyName
, buf
, sizeof(buf
), &hostent
);
1475 if ((prstatus
!= PR_SUCCESS
) || (hostent
.h_length
!= 4)) {
1477 * The hostname may be a fully-qualified name. Try using just
1478 * the leftmost component in our lookup.
1480 sepPtr
= strchr(localCopyName
, '.');
1484 prstatus
= PR_GetHostByName
1485 (localCopyName
, buf
, sizeof(buf
), &hostent
);
1487 if ((prstatus
!= PR_SUCCESS
) || (hostent
.h_length
!= 4)) {
1489 (PKIX_PRGETHOSTBYNAMEREJECTSHOSTNAMEARGUMENT
);
1493 netAddr
.inet
.family
= PR_AF_INET
;
1494 netAddr
.inet
.port
= PR_htons(portNum
);
1498 netAddr
.inet
.ip
= PR_INADDR_ANY
;
1502 hostenum
= PR_EnumerateHostEnt(0, &hostent
, portNum
, &netAddr
);
1503 if (hostenum
== -1) {
1504 PKIX_ERROR(PKIX_PRENUMERATEHOSTENTFAILED
);
1508 PKIX_CHECK(PKIX_PL_Object_Alloc
1510 sizeof (PKIX_PL_Socket
),
1511 (PKIX_PL_Object
**)&socket
,
1513 PKIX_COULDNOTCREATESOCKETOBJECT
);
1515 socket
->isServer
= isServer
;
1516 socket
->timeout
= timeout
;
1517 socket
->clientSock
= NULL
;
1518 socket
->serverSock
= NULL
;
1519 socket
->netAddr
= &netAddr
;
1521 socket
->callbackList
.listenCallback
= pkix_pl_Socket_Listen
;
1522 socket
->callbackList
.acceptCallback
= pkix_pl_Socket_Accept
;
1523 socket
->callbackList
.connectcontinueCallback
=
1524 pkix_pl_Socket_ConnectContinue
;
1525 socket
->callbackList
.sendCallback
= pkix_pl_Socket_Send
;
1526 socket
->callbackList
.recvCallback
= pkix_pl_Socket_Recv
;
1527 socket
->callbackList
.pollCallback
= pkix_pl_Socket_Poll
;
1528 socket
->callbackList
.shutdownCallback
= pkix_pl_Socket_Shutdown
;
1531 PKIX_CHECK(pkix_pl_Socket_CreateServer(socket
, plContext
),
1532 PKIX_SOCKETCREATESERVERFAILED
);
1535 PKIX_CHECK(pkix_pl_Socket_CreateClient(socket
, plContext
),
1536 PKIX_SOCKETCREATECLIENTFAILED
);
1537 PKIX_CHECK(pkix_pl_Socket_Connect(socket
, pStatus
, plContext
),
1538 PKIX_SOCKETCONNECTFAILED
);
1544 PL_strfree(localCopyName
);
1546 if (PKIX_ERROR_RECEIVED
) {
1547 PKIX_DECREF(socket
);
1550 PKIX_RETURN(SOCKET
);
1554 * FUNCTION: pkix_pl_Socket_CreateByHostAndPort
1557 * This function creates a new Socket, setting it to be a server or a client
1558 * according to the value of "isServer", setting its timeout value from
1559 * "timeout", host from "hostname", and port number from "portNum", and stores
1560 * the status at "pStatus" and the created Socket at "pSocket".
1562 * If isServer is PKIX_TRUE, it is attempted to create the socket with an ip
1563 * address of PR_INADDR_ANY.
1567 * The Boolean value indicating if PKIX_TRUE, that a server socket (using
1568 * Bind, Listen, and Accept) is to be created, or if PKIX_FALSE, that a
1569 * client socket (using Connect) is to be created.
1571 * A PRTimeInterval value to be used for I/O waits for this socket. If
1572 * zero, non-blocking I/O is to be used.
1574 * Address of a character string consisting of the server's domain name.
1576 * UInt16 value of the port number for the desired socket.
1578 * Address at which the PRErrorCode resulting from the create is
1579 * stored. Must be non-NULL.
1581 * The address at which the Socket is to be stored. Must be non-NULL.
1583 * Platform-specific context pointer.
1585 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
1587 * Returns NULL if the function succeeds.
1588 * Returns a Socket Error if the function fails in
1590 * Returns a Fatal Error if the function fails in an unrecoverable way.
1593 pkix_pl_Socket_CreateByHostAndPort(
1594 PKIX_Boolean isServer
,
1595 PRIntervalTime timeout
,
1598 PRErrorCode
*pStatus
,
1599 PKIX_PL_Socket
**pSocket
,
1603 PKIX_PL_Socket
*socket
= NULL
;
1604 char *sepPtr
= NULL
;
1607 PRStatus prstatus
= PR_FAILURE
;
1608 char buf
[PR_NETDB_BUF_SIZE
];
1609 char *localCopyName
= NULL
;
1611 PKIX_ENTER(SOCKET
, "pkix_pl_Socket_CreateByHostAndPort");
1612 PKIX_NULLCHECK_THREE(hostname
, pStatus
, pSocket
);
1615 prstatus
= PR_GetHostByName(hostname
, buf
, sizeof(buf
), &hostent
);
1617 if ((prstatus
!= PR_SUCCESS
) || (hostent
.h_length
!= 4)) {
1619 * The hostname may be a fully-qualified name. Try using just
1620 * the leftmost component in our lookup.
1622 sepPtr
= strchr(hostname
, '.');
1626 prstatus
= PR_GetHostByName(hostname
, buf
, sizeof(buf
), &hostent
);
1628 if ((prstatus
!= PR_SUCCESS
) || (hostent
.h_length
!= 4)) {
1630 (PKIX_PRGETHOSTBYNAMEREJECTSHOSTNAMEARGUMENT
);
1634 netAddr
.inet
.family
= PR_AF_INET
;
1635 netAddr
.inet
.port
= PR_htons(portnum
);
1639 netAddr
.inet
.ip
= PR_INADDR_ANY
;
1643 hostenum
= PR_EnumerateHostEnt(0, &hostent
, portnum
, &netAddr
);
1644 if (hostenum
== -1) {
1645 PKIX_ERROR(PKIX_PRENUMERATEHOSTENTFAILED
);
1649 PKIX_CHECK(PKIX_PL_Object_Alloc
1651 sizeof (PKIX_PL_Socket
),
1652 (PKIX_PL_Object
**)&socket
,
1654 PKIX_COULDNOTCREATESOCKETOBJECT
);
1656 socket
->isServer
= isServer
;
1657 socket
->timeout
= timeout
;
1658 socket
->clientSock
= NULL
;
1659 socket
->serverSock
= NULL
;
1660 socket
->netAddr
= &netAddr
;
1662 socket
->callbackList
.listenCallback
= pkix_pl_Socket_Listen
;
1663 socket
->callbackList
.acceptCallback
= pkix_pl_Socket_Accept
;
1664 socket
->callbackList
.connectcontinueCallback
=
1665 pkix_pl_Socket_ConnectContinue
;
1666 socket
->callbackList
.sendCallback
= pkix_pl_Socket_Send
;
1667 socket
->callbackList
.recvCallback
= pkix_pl_Socket_Recv
;
1668 socket
->callbackList
.pollCallback
= pkix_pl_Socket_Poll
;
1669 socket
->callbackList
.shutdownCallback
= pkix_pl_Socket_Shutdown
;
1672 PKIX_CHECK(pkix_pl_Socket_CreateServer(socket
, plContext
),
1673 PKIX_SOCKETCREATESERVERFAILED
);
1676 PKIX_CHECK(pkix_pl_Socket_CreateClient(socket
, plContext
),
1677 PKIX_SOCKETCREATECLIENTFAILED
);
1678 PKIX_CHECK(pkix_pl_Socket_Connect(socket
, pStatus
, plContext
),
1679 PKIX_SOCKETCONNECTFAILED
);
1685 if (PKIX_ERROR_RECEIVED
) {
1686 PKIX_DECREF(socket
);
1689 PKIX_RETURN(SOCKET
);
1693 * FUNCTION: pkix_pl_Socket_GetCallbackList
1696 pkix_pl_Socket_GetCallbackList(
1697 PKIX_PL_Socket
*socket
,
1698 PKIX_PL_Socket_Callback
**pCallbackList
,
1701 PKIX_ENTER(SOCKET
, "pkix_pl_Socket_GetCallbackList");
1702 PKIX_NULLCHECK_TWO(socket
, pCallbackList
);
1704 *pCallbackList
= &(socket
->callbackList
);
1706 PKIX_RETURN(SOCKET
);
1710 * FUNCTION: pkix_pl_Socket_GetPRFileDesc
1713 pkix_pl_Socket_GetPRFileDesc(
1714 PKIX_PL_Socket
*socket
,
1718 PKIX_ENTER(SOCKET
, "pkix_pl_Socket_GetPRFileDesc");
1719 PKIX_NULLCHECK_TWO(socket
, pDesc
);
1721 *pDesc
= socket
->clientSock
;
1723 PKIX_RETURN(SOCKET
);