PageRenderTime 66ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 0ms

/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_socket.c

https://bitbucket.org/dineshkummarc/mozilla-1.9.0-win64
C | 1723 lines | 931 code | 203 blank | 589 comment | 157 complexity | 7ca7b61521ef18f809afc31f14ac3276 MD5 | raw file
Possible License(s): LGPL-2.1, LGPL-3.0, MIT, BSD-3-Clause, MPL-2.0-no-copyleft-exception, GPL-2.0

Large files files are truncated, but you can click here to view the full file

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

Large files files are truncated, but you can click here to view the full file