Changeset 102063 in vbox for trunk/src/libs/xpcom18a4/nsprpub
- Timestamp:
- Nov 10, 2023 2:01:03 PM (15 months ago)
- Location:
- trunk/src/libs/xpcom18a4/nsprpub/pr
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/libs/xpcom18a4/nsprpub/pr/include/prio.h
r101935 r102063 441 441 /* 442 442 ************************************************************************** 443 * FUNCTION: PR_GetSpecialFD444 * DESCRIPTION: Get the file descriptor that represents the standard input,445 * output, or error stream.446 * INPUTS:447 * PRSpecialFD id448 * A value indicating the type of stream desired:449 * PR_StandardInput: standard input450 * PR_StandardOuput: standard output451 * PR_StandardError: standard error452 * OUTPUTS: none453 * RETURNS: PRFileDesc *454 * If the argument is valid, PR_GetSpecialFD returns a file descriptor455 * that represents the corresponding standard I/O stream. Otherwise,456 * PR_GetSpecialFD returns NULL and sets error PR_INVALID_ARGUMENT_ERROR.457 **************************************************************************458 */459 460 typedef enum PRSpecialFD461 {462 PR_StandardInput, /* standard input */463 PR_StandardOutput, /* standard output */464 PR_StandardError /* standard error */465 } PRSpecialFD;466 467 NSPR_API(PRFileDesc*) PR_GetSpecialFD(PRSpecialFD id);468 469 #define PR_STDIN PR_GetSpecialFD(PR_StandardInput)470 #define PR_STDOUT PR_GetSpecialFD(PR_StandardOutput)471 #define PR_STDERR PR_GetSpecialFD(PR_StandardError)472 473 /*474 **************************************************************************475 * Layering file descriptors476 *477 * File descriptors may be layered. Each layer has it's own identity.478 * Identities are allocated by the runtime and are to be associated479 * (by the layer implementor) with all layers that are of that type.480 * It is then possible to scan the chain of layers and find a layer481 * that one recongizes and therefore predict that it will implement482 * a desired protocol.483 *484 * There are three well-known identities:485 * PR_INVALID_IO_LAYER => an invalid layer identity, for error return486 * PR_TOP_IO_LAYER => the identity of the top of the stack487 * PR_NSPR_IO_LAYER => the identity used by NSPR proper488 * PR_TOP_IO_LAYER may be used as a shorthand for identifying the topmost489 * layer of an existing stack. Ie., the following two constructs are490 * equivalent.491 *492 * rv = PR_PushIOLayer(stack, PR_TOP_IO_LAYER, my_layer);493 * rv = PR_PushIOLayer(stack, PR_GetLayersIdentity(stack), my_layer)494 *495 * A string may be associated with the creation of the identity. It496 * will be copied by the runtime. If queried the runtime will return497 * a reference to that copied string (not yet another copy). There498 * is no facility for deleting an identity.499 **************************************************************************500 */501 502 #define PR_IO_LAYER_HEAD (PRDescIdentity)-3503 #define PR_INVALID_IO_LAYER (PRDescIdentity)-1504 #define PR_TOP_IO_LAYER (PRDescIdentity)-2505 #define PR_NSPR_IO_LAYER (PRDescIdentity)0506 507 NSPR_API(PRDescIdentity) PR_GetUniqueIdentity(const char *layer_name);508 NSPR_API(const char*) PR_GetNameForIdentity(PRDescIdentity ident);509 NSPR_API(PRDescIdentity) PR_GetLayersIdentity(PRFileDesc* fd);510 NSPR_API(PRFileDesc*) PR_GetIdentitiesLayer(PRFileDesc* fd_stack, PRDescIdentity id);511 512 /*513 **************************************************************************514 * PR_GetDefaultIOMethods: Accessing the default methods table.515 * You may get a pointer to the default methods table by calling this function.516 * You may then select any elements from that table with which to build your517 * layer's methods table. You may NOT modify the table directly.518 **************************************************************************519 */520 NSPR_API(const PRIOMethods *) PR_GetDefaultIOMethods(void);521 522 /*523 **************************************************************************524 * Creating a layer525 *526 * A new layer may be allocated by calling PR_CreateIOLayerStub(). The527 * file descriptor returned will contain the pointer to the methods table528 * provided. The runtime will not modify the table nor test its correctness.529 **************************************************************************530 */531 NSPR_API(PRFileDesc*) PR_CreateIOLayerStub(532 PRDescIdentity ident, const PRIOMethods *methods);533 534 /*535 **************************************************************************536 * Creating a layer537 *538 * A new stack may be created by calling PR_CreateIOLayer(). The539 * file descriptor returned will point to the top of the stack, which has540 * the layer 'fd' as the topmost layer.541 *542 * NOTE: This function creates a new style stack, which has a fixed, dummy543 * header. The old style stack, created by a call to PR_PushIOLayer,544 * results in modifying contents of the top layer of the stack, when545 * pushing and popping layers of the stack.546 **************************************************************************547 */548 NSPR_API(PRFileDesc*) PR_CreateIOLayer(PRFileDesc* fd);549 550 /*551 **************************************************************************552 * Pushing a layer553 *554 * A file descriptor (perhaps allocated using PR_CreateIOLayerStub()) may555 * be pushed into an existing stack of file descriptors at any point the556 * caller deems appropriate. The new layer will be inserted into the stack557 * just above the layer with the indicated identity.558 *559 * Note: Even if the identity parameter indicates the top-most layer of560 * the stack, the value of the file descriptor describing the original561 * stack will not change.562 **************************************************************************563 */564 NSPR_API(PRStatus) PR_PushIOLayer(565 PRFileDesc *fd_stack, PRDescIdentity id, PRFileDesc *layer);566 567 /*568 **************************************************************************569 * Popping a layer570 *571 * A layer may be popped from a stack by indicating the identity of the572 * layer to be removed. If found, a pointer to the removed object will573 * be returned to the caller. The object then becomes the responsibility574 * of the caller.575 *576 * Note: Even if the identity indicates the top layer of the stack, the577 * reference returned will not be the file descriptor for the stack and578 * that file descriptor will remain valid.579 **************************************************************************580 */581 NSPR_API(PRFileDesc*) PR_PopIOLayer(PRFileDesc *fd_stack, PRDescIdentity id);582 583 /*584 **************************************************************************585 443 * FUNCTION: PR_Open 586 444 * DESCRIPTION: Open a file for reading, writing, or both. … … 763 621 NSPR_API(PRInt32) PR_Write(PRFileDesc *fd,const void *buf,PRInt32 amount); 764 622 765 /*766 ***************************************************************************767 * FUNCTION: PR_Writev768 * DESCRIPTION:769 * Write data to a socket. The data is organized in a PRIOVec array. The770 * operation will block until all the data is written or the operation771 * fails.772 * INPUTS:773 * PRFileDesc *fd774 * Pointer that points to a PRFileDesc object for a socket.775 * const PRIOVec *iov776 * An array of PRIOVec. PRIOVec is a struct with the following777 * two fields:778 * char *iov_base;779 * int iov_len;780 * PRInt32 iov_size781 * Number of elements in the iov array. The value of this782 * argument must not be greater than PR_MAX_IOVECTOR_SIZE.783 * If it is, the method will fail (PR_BUFFER_OVERFLOW_ERROR).784 * PRIntervalTime timeout785 * Time limit for completion of the entire write operation.786 * OUTPUTS:787 * None788 * RETURN:789 * A positive number indicates the number of bytes successfully written.790 * A -1 is an indication that the operation failed. The reason791 * for the failure is obtained by calling PR_GetError().792 ***************************************************************************793 */794 795 #define PR_MAX_IOVECTOR_SIZE 16 /* 'iov_size' must be <= */796 797 NSPR_API(PRInt32) PR_Writev(798 PRFileDesc *fd, const PRIOVec *iov, PRInt32 iov_size,799 PRIntervalTime timeout);800 801 /*802 ***************************************************************************803 * FUNCTION: PR_Delete804 * DESCRIPTION:805 * Delete a file from the filesystem. The operation may fail if the806 * file is open.807 * INPUTS:808 * const char *name809 * Path name of the file to be deleted.810 * OUTPUTS:811 * None.812 * RETURN: PRStatus813 * The function returns PR_SUCCESS if the file is successfully814 * deleted, otherwise it returns PR_FAILURE.815 ***************************************************************************816 */817 818 NSPR_API(PRStatus) PR_Delete(const char *name);819 820 623 /**************************************************************************/ 821 624 … … 861 664 NSPR_API(PRStatus) PR_GetFileInfo(const char *fn, PRFileInfo *info); 862 665 NSPR_API(PRStatus) PR_GetFileInfo64(const char *fn, PRFileInfo64 *info); 863 864 /*865 **************************************************************************866 * FUNCTION: PR_GetOpenFileInfo, PR_GetOpenFileInfo64867 * DESCRIPTION:868 * Get information about an open file referred to by the869 * given PRFileDesc object.870 * INPUTS:871 * const PRFileDesc *fd872 * A reference to a valid, open file.873 * OUTPUTS:874 * Same as PR_GetFileInfo, PR_GetFileInfo64875 * RETURN: PRStatus876 * PR_GetFileInfo returns PR_SUCCESS if file information is successfully877 * obtained, otherwise it returns PR_FAILURE.878 ***************************************************************************879 */880 881 NSPR_API(PRStatus) PR_GetOpenFileInfo(PRFileDesc *fd, PRFileInfo *info);882 NSPR_API(PRStatus) PR_GetOpenFileInfo64(PRFileDesc *fd, PRFileInfo64 *info);883 666 884 667 /* … … 918 701 NSPR_API(PROffset64) PR_Seek64(PRFileDesc *fd, PROffset64 offset, PRSeekWhence whence); 919 702 920 /*921 ************************************************************************922 * FUNCTION: PR_Available923 * DESCRIPTION:924 * Determine the amount of data in bytes available for reading925 * in the given file or socket.926 * INPUTS:927 * PRFileDesc *fd928 * Pointer to a PRFileDesc object that refers to a file or929 * socket.930 * OUTPUTS:931 * None932 * RETURN: PRInt32, PRInt64933 * Upon successful completion, PR_Available returns the number of934 * bytes beyond the current read pointer that is available for935 * reading. Otherwise, it returns a -1 and the reason for the936 * failure can be retrieved via PR_GetError().937 ************************************************************************938 */939 940 NSPR_API(PRInt32) PR_Available(PRFileDesc *fd);941 942 /*943 ************************************************************************944 * FUNCTION: PR_Sync945 * DESCRIPTION:946 * Sync any buffered data for a fd to its backing device (disk).947 * INPUTS:948 * PRFileDesc *fd949 * Pointer to a PRFileDesc object that refers to a file or950 * socket951 * OUTPUTS:952 * None953 * RETURN: PRStatus954 * PR_SUCCESS is returned if the requested access is permitted.955 * Otherwise, PR_FAILURE is returned.956 ************************************************************************957 */958 959 NSPR_API(PRStatus) PR_Sync(PRFileDesc *fd);960 961 /*962 *************************************************************************963 * FUNCTION: PR_OpenTCPSocket964 * DESCRIPTION:965 * Create a new TCP socket of the specified address family.966 * INPUTS:967 * PRIntn af968 * Address family969 * OUTPUTS:970 * None971 * RETURN: PRFileDesc*972 * Upon successful completion, PR_NewTCPSocket returns a pointer973 * to the PRFileDesc created for the newly opened TCP socket.974 * Returns a NULL pointer if the creation of a new TCP socket failed.975 *976 **************************************************************************977 */978 979 NSPR_API(PRFileDesc*) PR_OpenTCPSocket(PRIntn af);980 981 /*982 *************************************************************************983 * FUNCTION: PR_Connect984 * DESCRIPTION:985 * Initiate a connection on a socket.986 * INPUTS:987 * PRFileDesc *fd988 * Points to a PRFileDesc object representing a socket989 * PRNetAddr *addr990 * Specifies the address of the socket in its own communication991 * space.992 * PRIntervalTime timeout993 * Time limit for completion of the connect operation.994 * OUTPUTS:995 * None996 * RETURN: PRStatus997 * Upon successful completion of connection initiation, PR_Connect998 * returns PR_SUCCESS. Otherwise, it returns PR_FAILURE. Further999 * failure information can be obtained by calling PR_GetError().1000 **************************************************************************1001 */1002 1003 NSPR_API(PRStatus) PR_Connect(1004 PRFileDesc *fd, const PRNetAddr *addr, PRIntervalTime timeout);1005 1006 /*1007 *************************************************************************1008 * FUNCTION: PR_ConnectContinue1009 * DESCRIPTION:1010 * Continue a nonblocking connect. After a nonblocking connect1011 * is initiated with PR_Connect() (which fails with1012 * PR_IN_PROGRESS_ERROR), one should call PR_Poll() on the socket,1013 * with the in_flags PR_POLL_WRITE | PR_POLL_EXCEPT. When1014 * PR_Poll() returns, one calls PR_ConnectContinue() on the1015 * socket to determine whether the nonblocking connect has1016 * completed or is still in progress. Repeat the PR_Poll(),1017 * PR_ConnectContinue() sequence until the nonblocking connect1018 * has completed.1019 * INPUTS:1020 * PRFileDesc *fd1021 * the file descriptor representing a socket1022 * PRInt16 out_flags1023 * the out_flags field of the poll descriptor returned by1024 * PR_Poll()1025 * RETURN: PRStatus1026 * If the nonblocking connect has successfully completed,1027 * PR_ConnectContinue returns PR_SUCCESS. If PR_ConnectContinue()1028 * returns PR_FAILURE, call PR_GetError():1029 * - PR_IN_PROGRESS_ERROR: the nonblocking connect is still in1030 * progress and has not completed yet. The caller should poll1031 * on the file descriptor for the in_flags1032 * PR_POLL_WRITE|PR_POLL_EXCEPT and retry PR_ConnectContinue1033 * later when PR_Poll() returns.1034 * - Other errors: the nonblocking connect has failed with this1035 * error code.1036 */1037 1038 NSPR_API(PRStatus) PR_ConnectContinue(PRFileDesc *fd, PRInt16 out_flags);1039 1040 /*1041 *************************************************************************1042 * THIS FUNCTION IS DEPRECATED. USE PR_ConnectContinue INSTEAD.1043 *1044 * FUNCTION: PR_GetConnectStatus1045 * DESCRIPTION:1046 * Get the completion status of a nonblocking connect. After1047 * a nonblocking connect is initiated with PR_Connect() (which1048 * fails with PR_IN_PROGRESS_ERROR), one should call PR_Poll()1049 * on the socket, with the in_flags PR_POLL_WRITE | PR_POLL_EXCEPT.1050 * When PR_Poll() returns, one calls PR_GetConnectStatus on the1051 * PRPollDesc structure to determine whether the nonblocking1052 * connect has succeeded or failed.1053 * INPUTS:1054 * const PRPollDesc *pd1055 * Pointer to a PRPollDesc whose fd member is the socket,1056 * and in_flags must contain PR_POLL_WRITE and PR_POLL_EXCEPT.1057 * PR_Poll() should have been called and set the out_flags.1058 * RETURN: PRStatus1059 * If the nonblocking connect has successfully completed,1060 * PR_GetConnectStatus returns PR_SUCCESS. If PR_GetConnectStatus()1061 * returns PR_FAILURE, call PR_GetError():1062 * - PR_IN_PROGRESS_ERROR: the nonblocking connect is still in1063 * progress and has not completed yet.1064 * - Other errors: the nonblocking connect has failed with this1065 * error code.1066 */1067 1068 NSPR_API(PRStatus) PR_GetConnectStatus(const PRPollDesc *pd);1069 1070 /*1071 *************************************************************************1072 * FUNCTION: PR_Accept1073 * DESCRIPTION:1074 * Accept a connection on a socket.1075 * INPUTS:1076 * PRFileDesc *fd1077 * Points to a PRFileDesc object representing the rendezvous socket1078 * on which the caller is willing to accept new connections.1079 * PRIntervalTime timeout1080 * Time limit for completion of the accept operation.1081 * OUTPUTS:1082 * PRNetAddr *addr1083 * Returns the address of the connecting entity in its own1084 * communication space. It may be NULL.1085 * RETURN: PRFileDesc*1086 * Upon successful acceptance of a connection, PR_Accept1087 * returns a valid file descriptor. Otherwise, it returns NULL.1088 * Further failure information can be obtained by calling PR_GetError().1089 **************************************************************************1090 */1091 1092 NSPR_API(PRFileDesc*) PR_Accept(1093 PRFileDesc *fd, PRNetAddr *addr, PRIntervalTime timeout);1094 1095 /*1096 *************************************************************************1097 * FUNCTION: PR_Bind1098 * DESCRIPTION:1099 * Bind an address to a socket.1100 * INPUTS:1101 * PRFileDesc *fd1102 * Points to a PRFileDesc object representing a socket.1103 * PRNetAddr *addr1104 * Specifies the address to which the socket will be bound.1105 * OUTPUTS:1106 * None1107 * RETURN: PRStatus1108 * Upon successful binding of an address to a socket, PR_Bind1109 * returns PR_SUCCESS. Otherwise, it returns PR_FAILURE. Further1110 * failure information can be obtained by calling PR_GetError().1111 **************************************************************************1112 */1113 1114 NSPR_API(PRStatus) PR_Bind(PRFileDesc *fd, const PRNetAddr *addr);1115 1116 /*1117 *************************************************************************1118 * FUNCTION: PR_Listen1119 * DESCRIPTION:1120 * Listen for connections on a socket.1121 * INPUTS:1122 * PRFileDesc *fd1123 * Points to a PRFileDesc object representing a socket that will be1124 * used to listen for new connections.1125 * PRIntn backlog1126 * Specifies the maximum length of the queue of pending connections.1127 * OUTPUTS:1128 * None1129 * RETURN: PRStatus1130 * Upon successful completion of listen request, PR_Listen1131 * returns PR_SUCCESS. Otherwise, it returns PR_FAILURE. Further1132 * failure information can be obtained by calling PR_GetError().1133 **************************************************************************1134 */1135 1136 NSPR_API(PRStatus) PR_Listen(PRFileDesc *fd, PRIntn backlog);1137 1138 /*1139 *************************************************************************1140 * FUNCTION: PR_Shutdown1141 * DESCRIPTION:1142 * Shut down part of a full-duplex connection on a socket.1143 * INPUTS:1144 * PRFileDesc *fd1145 * Points to a PRFileDesc object representing a connected socket.1146 * PRIntn how1147 * Specifies the kind of disallowed operations on the socket.1148 * PR_SHUTDOWN_RCV - Further receives will be disallowed1149 * PR_SHUTDOWN_SEND - Further sends will be disallowed1150 * PR_SHUTDOWN_BOTH - Further sends and receives will be disallowed1151 * OUTPUTS:1152 * None1153 * RETURN: PRStatus1154 * Upon successful completion of shutdown request, PR_Shutdown1155 * returns PR_SUCCESS. Otherwise, it returns PR_FAILURE. Further1156 * failure information can be obtained by calling PR_GetError().1157 **************************************************************************1158 */1159 1160 typedef enum PRShutdownHow1161 {1162 PR_SHUTDOWN_RCV = 0, /* disallow further receives */1163 PR_SHUTDOWN_SEND = 1, /* disallow further sends */1164 PR_SHUTDOWN_BOTH = 2 /* disallow further receives and sends */1165 } PRShutdownHow;1166 1167 NSPR_API(PRStatus) PR_Shutdown(PRFileDesc *fd, PRShutdownHow how);1168 1169 /*1170 *************************************************************************1171 * FUNCTION: PR_Recv1172 * DESCRIPTION:1173 * Receive a specified number of bytes from a connected socket.1174 * The operation will block until some positive number of bytes are1175 * transferred, a time out has occurred, or there is an error.1176 * No more than 'amount' bytes will be transferred.1177 * INPUTS:1178 * PRFileDesc *fd1179 * points to a PRFileDesc object representing a socket.1180 * void *buf1181 * pointer to a buffer to hold the data received.1182 * PRInt32 amount1183 * the size of 'buf' (in bytes)1184 * PRIntn flags1185 * must be zero or PR_MSG_PEEK.1186 * PRIntervalTime timeout1187 * Time limit for completion of the receive operation.1188 * OUTPUTS:1189 * None1190 * RETURN: PRInt321191 * a positive number indicates the number of bytes actually received.1192 * 0 means the network connection is closed.1193 * -1 indicates a failure. The reason for the failure is obtained1194 * by calling PR_GetError().1195 **************************************************************************1196 */1197 1198 #define PR_MSG_PEEK 0x21199 1200 NSPR_API(PRInt32) PR_Recv(PRFileDesc *fd, void *buf, PRInt32 amount,1201 PRIntn flags, PRIntervalTime timeout);1202 1203 /*1204 *************************************************************************1205 * FUNCTION: PR_Send1206 * DESCRIPTION:1207 * Send a specified number of bytes from a connected socket.1208 * The operation will block until all bytes are1209 * processed, a time out has occurred, or there is an error.1210 * INPUTS:1211 * PRFileDesc *fd1212 * points to a PRFileDesc object representing a socket.1213 * void *buf1214 * pointer to a buffer from where the data is sent.1215 * PRInt32 amount1216 * the size of 'buf' (in bytes)1217 * PRIntn flags1218 * (OBSOLETE - must always be zero)1219 * PRIntervalTime timeout1220 * Time limit for completion of the send operation.1221 * OUTPUTS:1222 * None1223 * RETURN: PRInt321224 * A positive number indicates the number of bytes successfully processed.1225 * This number must always equal 'amount'. A -1 is an indication that the1226 * operation failed. The reason for the failure is obtained by calling1227 * PR_GetError().1228 **************************************************************************1229 */1230 1231 NSPR_API(PRInt32) PR_Send(PRFileDesc *fd, const void *buf, PRInt32 amount,1232 PRIntn flags, PRIntervalTime timeout);1233 1234 /*1235 *************************************************************************1236 ** FUNCTION: PR_GetSockName1237 ** DESCRIPTION:1238 ** Get socket name. Return the network address for this socket.1239 **1240 ** INPUTS:1241 ** PRFileDesc *fd1242 ** Points to a PRFileDesc object representing the socket.1243 ** OUTPUTS:1244 ** PRNetAddr *addr1245 ** Returns the address of the socket in its own communication space.1246 ** RETURN: PRStatus1247 ** Upon successful completion, PR_GetSockName returns PR_SUCCESS.1248 ** Otherwise, it returns PR_FAILURE. Further failure information can1249 ** be obtained by calling PR_GetError().1250 **************************************************************************1251 **/1252 NSPR_API(PRStatus) PR_GetSockName(PRFileDesc *fd, PRNetAddr *addr);1253 1254 /*1255 *************************************************************************1256 ** FUNCTION: PR_GetPeerName1257 ** DESCRIPTION:1258 ** Get name of the connected peer. Return the network address for the1259 ** connected peer socket.1260 **1261 ** INPUTS:1262 ** PRFileDesc *fd1263 ** Points to a PRFileDesc object representing the connected peer.1264 ** OUTPUTS:1265 ** PRNetAddr *addr1266 ** Returns the address of the connected peer in its own communication1267 ** space.1268 ** RETURN: PRStatus1269 ** Upon successful completion, PR_GetPeerName returns PR_SUCCESS.1270 ** Otherwise, it returns PR_FAILURE. Further failure information can1271 ** be obtained by calling PR_GetError().1272 **************************************************************************1273 **/1274 NSPR_API(PRStatus) PR_GetPeerName(PRFileDesc *fd, PRNetAddr *addr);1275 1276 NSPR_API(PRStatus) PR_GetSocketOption(1277 PRFileDesc *fd, PRSocketOptionData *data);1278 1279 NSPR_API(PRStatus) PR_SetSocketOption(1280 PRFileDesc *fd, const PRSocketOptionData *data);1281 1282 /*1283 *********************************************************************1284 *1285 * File descriptor inheritance1286 *1287 *********************************************************************1288 */1289 1290 /*1291 ************************************************************************1292 * FUNCTION: PR_SetFDInheritable1293 * DESCRIPTION:1294 * Set the inheritance attribute of a file descriptor.1295 *1296 * INPUTS:1297 * PRFileDesc *fd1298 * Points to a PRFileDesc object.1299 * PRBool inheritable1300 * If PR_TRUE, the file descriptor fd is set to be inheritable1301 * by a child process. If PR_FALSE, the file descriptor is set1302 * to be not inheritable by a child process.1303 * RETURN: PRStatus1304 * Upon successful completion, PR_SetFDInheritable returns PR_SUCCESS.1305 * Otherwise, it returns PR_FAILURE. Further failure information can1306 * be obtained by calling PR_GetError().1307 *************************************************************************1308 */1309 NSPR_API(PRStatus) PR_SetFDInheritable(1310 PRFileDesc *fd,1311 PRBool inheritable);1312 1313 /*1314 ************************************************************************1315 * FUNCTION: PR_GetInheritedFD1316 * DESCRIPTION:1317 * Get an inherited file descriptor with the specified name.1318 *1319 * INPUTS:1320 * const char *name1321 * The name of the inherited file descriptor.1322 * RETURN: PRFileDesc *1323 * Upon successful completion, PR_GetInheritedFD returns the1324 * inherited file descriptor with the specified name. Otherwise,1325 * it returns NULL. Further failure information can be obtained1326 * by calling PR_GetError().1327 *************************************************************************1328 */1329 NSPR_API(PRFileDesc *) PR_GetInheritedFD(const char *name);1330 1331 /*1332 ******************************************************************1333 *1334 * Interprocess communication1335 *1336 ******************************************************************1337 */1338 1339 /*1340 * Creates an anonymous pipe and returns file descriptors for the1341 * read and write ends of the pipe.1342 */1343 1344 NSPR_API(PRStatus) PR_CreatePipe(1345 PRFileDesc **readPipe,1346 PRFileDesc **writePipe1347 );1348 1349 /************************************************************************/1350 /************** The following definitions are for poll ******************/1351 /************************************************************************/1352 1353 struct PRPollDesc {1354 PRFileDesc* fd;1355 PRInt16 in_flags;1356 PRInt16 out_flags;1357 };1358 1359 /*1360 ** Bit values for PRPollDesc.in_flags or PRPollDesc.out_flags. Binary-or1361 ** these together to produce the desired poll request.1362 */1363 1364 #if defined(_PR_POLL_BACKCOMPAT)1365 1366 #include <poll.h>1367 #define PR_POLL_READ POLLIN1368 #define PR_POLL_WRITE POLLOUT1369 #define PR_POLL_EXCEPT POLLPRI1370 #define PR_POLL_ERR POLLERR /* only in out_flags */1371 #define PR_POLL_NVAL POLLNVAL /* only in out_flags when fd is bad */1372 #define PR_POLL_HUP POLLHUP /* only in out_flags */1373 1374 #else /* _PR_POLL_BACKCOMPAT */1375 1376 #define PR_POLL_READ 0x11377 #define PR_POLL_WRITE 0x21378 #define PR_POLL_EXCEPT 0x41379 #define PR_POLL_ERR 0x8 /* only in out_flags */1380 #define PR_POLL_NVAL 0x10 /* only in out_flags when fd is bad */1381 #define PR_POLL_HUP 0x20 /* only in out_flags */1382 1383 #endif /* _PR_POLL_BACKCOMPAT */1384 1385 /*1386 *************************************************************************1387 ** FUNCTION: PR_Poll1388 ** DESCRIPTION:1389 **1390 ** The call returns as soon as I/O is ready on one or more of the underlying1391 ** socket objects. A count of the number of ready descriptors is1392 ** returned unless a timeout occurs in which case zero is returned.1393 **1394 ** PRPollDesc.fd should be set to a pointer to a PRFileDesc object1395 ** representing a socket. This field can be set to NULL to indicate to1396 ** PR_Poll that this PRFileDesc object should be ignored.1397 ** PRPollDesc.in_flags should be set to the desired request1398 ** (read/write/except or some combination). Upon successful return from1399 ** this call PRPollDesc.out_flags will be set to indicate what kind of1400 ** i/o can be performed on the respective descriptor. PR_Poll() uses the1401 ** out_flags fields as scratch variables during the call. If PR_Poll()1402 ** returns 0 or -1, the out_flags fields do not contain meaningful values1403 ** and must not be used.1404 **1405 ** INPUTS:1406 ** PRPollDesc *pds A pointer to an array of PRPollDesc1407 **1408 ** PRIntn npds The number of elements in the array1409 ** If this argument is zero PR_Poll is1410 ** equivalent to a PR_Sleep(timeout).1411 **1412 ** PRIntervalTime timeout Amount of time the call will block waiting1413 ** for I/O to become ready. If this time expires1414 ** w/o any I/O becoming ready, the result will1415 ** be zero.1416 **1417 ** OUTPUTS: None1418 ** RETURN:1419 ** PRInt32 Number of PRPollDesc's with events or zero1420 ** if the function timed out or -1 on failure.1421 ** The reason for the failure is obtained by1422 ** calling PR_GetError().1423 **************************************************************************1424 */1425 NSPR_API(PRInt32) PR_Poll(1426 PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout);1427 1428 703 PR_END_EXTERN_C 1429 704 -
trunk/src/libs/xpcom18a4/nsprpub/pr/src/io/priometh.c
r102000 r102063 172 172 } 173 173 174 PR_IMPLEMENT(PRStatus) PR_Connect(175 PRFileDesc *fd, const PRNetAddr *addr, PRIntervalTime timeout)176 {177 return((fd->methods->connect)(fd,addr,timeout));178 }179 180 PR_IMPLEMENT(PRStatus) PR_ConnectContinue(181 PRFileDesc *fd, PRInt16 out_flags)182 {183 return((fd->methods->connectcontinue)(fd,out_flags));184 }185 186 PR_IMPLEMENT(PRFileDesc*) PR_Accept(PRFileDesc *fd, PRNetAddr *addr,187 PRIntervalTime timeout)188 {189 return((fd->methods->accept)(fd,addr,timeout));190 }191 192 PR_IMPLEMENT(PRStatus) PR_Bind(PRFileDesc *fd, const PRNetAddr *addr)193 {194 return((fd->methods->bind)(fd,addr));195 }196 197 PR_IMPLEMENT(PRStatus) PR_Shutdown(PRFileDesc *fd, PRShutdownHow how)198 {199 return((fd->methods->shutdown)(fd,how));200 }201 202 PR_IMPLEMENT(PRStatus) PR_Listen(PRFileDesc *fd, PRIntn backlog)203 {204 return((fd->methods->listen)(fd,backlog));205 }206 207 PR_IMPLEMENT(PRInt32) PR_Recv(PRFileDesc *fd, void *buf, PRInt32 amount,208 PRIntn flags, PRIntervalTime timeout)209 {210 return((fd->methods->recv)(fd,buf,amount,flags,timeout));211 }212 213 PR_IMPLEMENT(PRInt32) PR_Send(PRFileDesc *fd, const void *buf, PRInt32 amount,214 PRIntn flags, PRIntervalTime timeout)215 {216 return((fd->methods->send)(fd,buf,amount,flags,timeout));217 }218 219 PR_IMPLEMENT(PRInt32) PR_Writev(PRFileDesc *fd, const PRIOVec *iov,220 PRInt32 iov_size, PRIntervalTime timeout)221 {222 if (iov_size > PR_MAX_IOVECTOR_SIZE)223 {224 PR_SetError(PR_BUFFER_OVERFLOW_ERROR, 0);225 return -1;226 }227 return((fd->methods->writev)(fd,iov,iov_size,timeout));228 }229 230 PR_IMPLEMENT(PRStatus) PR_GetSockName(PRFileDesc *fd, PRNetAddr *addr)231 {232 return((fd->methods->getsockname)(fd,addr));233 }234 235 PR_IMPLEMENT(PRStatus) PR_GetPeerName(PRFileDesc *fd, PRNetAddr *addr)236 {237 return((fd->methods->getpeername)(fd,addr));238 }239 240 PR_IMPLEMENT(PRStatus) PR_GetSocketOption(241 PRFileDesc *fd, PRSocketOptionData *data)242 {243 return((fd->methods->getsocketoption)(fd, data));244 }245 246 PR_IMPLEMENT(PRStatus) PR_SetSocketOption(247 PRFileDesc *fd, const PRSocketOptionData *data)248 {249 return((fd->methods->setsocketoption)(fd, data));250 }251 252 174 /* priometh.c */ -
trunk/src/libs/xpcom18a4/nsprpub/pr/src/io/prstdio.c
r1 r102063 60 60 char* msg = PR_vsmprintf(fmt, ap); 61 61 len = strlen(msg); 62 #ifdef XP_OS263 /*64 * OS/2 really needs a \r for every \n.65 * In the future we should try to use scatter-gather instead of a66 * succession of PR_Write.67 */68 if (isatty(PR_FileDesc2NativeHandle(fd))) {69 PRUint32 last = 0, idx;70 PRInt32 tmp;71 rv = 0;72 for (idx = 0; idx < len+1; idx++) {73 if ((idx - last > 0) && (('\n' == msg[idx]) || (idx == len))) {74 tmp = PR_Write(fd, msg + last, idx - last);75 if (tmp >= 0) {76 rv += tmp;77 }78 last = idx;79 }80 /*81 * if current character is \n, and82 * previous character isn't \r, and83 * next character isn't \r84 */85 if (('\n' == msg[idx]) &&86 ((0 == idx) || ('\r' != msg[idx-1])) &&87 ('\r' != msg[idx+1])) {88 /* add extra \r */89 tmp = PR_Write(fd, "\r", 1);90 if (tmp >= 0) {91 rv += tmp;92 }93 }94 }95 } else {96 rv = PR_Write(fd, msg, len);97 }98 #else99 62 rv = PR_Write(fd, msg, len); 100 #endif101 63 PR_DELETE(msg); 102 64 return rv; -
trunk/src/libs/xpcom18a4/nsprpub/pr/src/pthreads/ptio.c
r102003 r102063 71 71 #endif 72 72 73 #include <netinet/tcp.h> /* TCP_NODELAY, TCP_MAXSEG */74 #ifdef LINUX75 /* TCP_CORK is not defined in <netinet/tcp.h> on Red Hat Linux 6.0 */76 #ifndef TCP_CORK77 #define TCP_CORK 378 #endif79 #endif80 81 73 #include <iprt/assert.h> 82 74 #include <iprt/thread.h> 83 75 84 #ifdef DARWIN85 static PRBool _pr_ipv6_v6only_on_by_default;86 /* The IPV6_V6ONLY socket option is not defined on Mac OS X 10.1. */87 #ifndef IPV6_V6ONLY88 #define IPV6_V6ONLY 2789 #endif90 #endif91 92 #if defined(SOLARIS)93 #define _PRSockOptVal_t char *94 #elif defined(IRIX) || defined(OSF1) || defined(AIX) || defined(HPUX) \95 || defined(LINUX) || defined(FREEBSD) || defined(BSDI) || defined(VMS) \96 || defined(NTO) || defined(OPENBSD) || defined(DARWIN) \97 || defined(UNIXWARE) || defined(NETBSD)98 #define _PRSockOptVal_t void *99 #else100 #error "Cannot determine architecture"101 #endif102 103 #if (defined(HPUX) && !defined(HPUX10_30) && !defined(HPUX11))104 #define _PRSelectFdSetArg_t int *105 #elif defined(AIX4_1)106 #define _PRSelectFdSetArg_t void *107 #elif defined(IRIX) || (defined(AIX) && !defined(AIX4_1)) \108 || defined(OSF1) || defined(SOLARIS) \109 || defined(HPUX10_30) || defined(HPUX11) || defined(LINUX) \110 || defined(FREEBSD) || defined(NETBSD) || defined(OPENBSD) \111 || defined(BSDI) || defined(VMS) || defined(NTO) || defined(DARWIN) \112 || defined(UNIXWARE)113 #define _PRSelectFdSetArg_t fd_set *114 #else115 #error "Cannot determine architecture"116 #endif117 118 static PRFileDesc *pt_SetMethods(119 PRIntn osfd, PRDescType type, PRBool isAcceptedSocket, PRBool imported);120 121 76 static PRLock *_pr_rename_lock; /* For PR_Rename() */ 122 77 123 78 /**************************************************************************/ 124 125 /* These two functions are only used in assertions. */126 #ifdef RT_STRICT127 128 PRBool IsValidNetAddr(const PRNetAddr *addr)129 {130 if ((addr != NULL)131 && (addr->raw.family != AF_UNIX)132 && (addr->raw.family != PR_AF_INET6)133 && (addr->raw.family != AF_INET)) {134 return PR_FALSE;135 }136 return PR_TRUE;137 }138 139 static PRBool IsValidNetAddrLen(const PRNetAddr *addr, PRInt32 addr_len)140 {141 /*142 * The definition of the length of a Unix domain socket address143 * is not uniform, so we don't check it.144 */145 if ((addr != NULL)146 && (addr->raw.family != AF_UNIX)147 && (PR_NETADDR_SIZE(addr) != addr_len)) {148 #if defined(LINUX) && __GLIBC__ == 2 && __GLIBC_MINOR__ == 1149 /*150 * In glibc 2.1, struct sockaddr_in6 is 24 bytes. In glibc 2.2151 * and in the 2.4 kernel, struct sockaddr_in6 has the scope_id152 * field and is 28 bytes. It is possible for socket functions153 * to return an addr_len greater than sizeof(struct sockaddr_in6).154 * We need to allow that. (Bugzilla bug #77264)155 */156 if ((PR_AF_INET6 == addr->raw.family)157 && (sizeof(addr->ipv6) == addr_len)) {158 return PR_TRUE;159 }160 #endif161 return PR_FALSE;162 }163 return PR_TRUE;164 }165 166 #endif /* DEBUG */167 79 168 80 /*****************************************************************************/ … … 175 87 */ 176 88 #define PT_DEFAULT_POLL_MSEC 5000 177 178 /*179 * pt_SockLen is the type for the length of a socket address180 * structure, used in the address length argument to bind,181 * connect, accept, getsockname, getpeername, etc. Posix.1g182 * defines this type as socklen_t. It is size_t or int on183 * most current systems.184 */185 #if defined(HAVE_SOCKLEN_T) \186 || (defined(LINUX) && defined(__GLIBC__) && __GLIBC__ >= 2)187 typedef socklen_t pt_SockLen;188 #elif (defined(AIX) && !defined(AIX4_1)) \189 || defined(VMS)190 typedef PRSize pt_SockLen;191 #else192 typedef PRIntn pt_SockLen;193 #endif194 89 195 90 typedef struct pt_Continuation pt_Continuation; … … 210 105 union { 211 106 PRSize amount; /* #3 - size of 'buffer', or */ 212 pt_SockLen *addr_len; /* - length of address */213 107 } arg3; 214 108 union { PRIntn flags; } arg4; /* #4 - read/write flags */ … … 290 184 fd->dtor = NULL; 291 185 fd->lower = fd->higher = NULL; 292 fd->identity = PR_NSPR_IO_LAYER;293 186 memset(fd->secret, 0, sizeof(PRFilePrivate)); 294 187 return fd; … … 453 346 /*********************** specific continuation functions *********************/ 454 347 /*****************************************************************************/ 455 static PRBool pt_connect_cont(pt_Continuation *op, PRInt16 revents)456 {457 op->syserrno = _MD_unix_get_nonblocking_connect_error(op->arg1.osfd);458 if (op->syserrno != 0) {459 op->result.code = -1;460 } else {461 op->result.code = 0;462 }463 return PR_TRUE; /* this one is cooked */464 } /* pt_connect_cont */465 466 static PRBool pt_accept_cont(pt_Continuation *op, PRInt16 revents)467 {468 op->syserrno = 0;469 op->result.code = accept(470 op->arg1.osfd, op->arg2.buffer, op->arg3.addr_len);471 if (-1 == op->result.code)472 {473 op->syserrno = errno;474 if (EWOULDBLOCK == errno || EAGAIN == errno || ECONNABORTED == errno)475 return PR_FALSE; /* do nothing - this one ain't finished */476 }477 return PR_TRUE;478 } /* pt_accept_cont */479 480 348 static PRBool pt_read_cont(pt_Continuation *op, PRInt16 revents) 481 349 { … … 492 360 PR_FALSE : PR_TRUE; 493 361 } /* pt_read_cont */ 494 495 static PRBool pt_recv_cont(pt_Continuation *op, PRInt16 revents)496 {497 /*498 * Any number of bytes will complete the operation. It need499 * not (and probably will not) satisfy the request. The only500 * error we continue is EWOULDBLOCK|EAGAIN.501 */502 #if defined(SOLARIS)503 if (0 == op->arg4.flags)504 op->result.code = read(505 op->arg1.osfd, op->arg2.buffer, op->arg3.amount);506 else507 op->result.code = recv(508 op->arg1.osfd, op->arg2.buffer, op->arg3.amount, op->arg4.flags);509 #else510 op->result.code = recv(511 op->arg1.osfd, op->arg2.buffer, op->arg3.amount, op->arg4.flags);512 #endif513 op->syserrno = errno;514 return ((-1 == op->result.code) &&515 (EWOULDBLOCK == op->syserrno || EAGAIN == op->syserrno)) ?516 PR_FALSE : PR_TRUE;517 } /* pt_recv_cont */518 519 static PRBool pt_send_cont(pt_Continuation *op, PRInt16 revents)520 {521 PRIntn bytes;522 #if defined(SOLARIS)523 PRInt32 tmp_amount = op->arg3.amount;524 #endif525 /*526 * We want to write the entire amount out, no matter how many527 * tries it takes. Keep advancing the buffer and the decrementing528 * the amount until the amount goes away. Return the total bytes529 * (which should be the original amount) when finished (or an530 * error).531 */532 #if defined(SOLARIS)533 retry:534 bytes = write(op->arg1.osfd, op->arg2.buffer, tmp_amount);535 #else536 bytes = send(537 op->arg1.osfd, op->arg2.buffer, op->arg3.amount, op->arg4.flags);538 #endif539 op->syserrno = errno;540 541 #if defined(SOLARIS)542 /*543 * The write system call has been reported to return the ERANGE error544 * on occasion. Try to write in smaller chunks to workaround this bug.545 */546 if ((bytes == -1) && (op->syserrno == ERANGE))547 {548 if (tmp_amount > 1)549 {550 tmp_amount = tmp_amount/2; /* half the bytes */551 goto retry;552 }553 }554 #endif555 556 if (bytes >= 0) /* this is progress */557 {558 char *bp = (char*)op->arg2.buffer;559 bp += bytes; /* adjust the buffer pointer */560 op->arg2.buffer = bp;561 op->result.code += bytes; /* accumulate the number sent */562 op->arg3.amount -= bytes; /* and reduce the required count */563 return (0 == op->arg3.amount) ? PR_TRUE : PR_FALSE;564 }565 else if ((EWOULDBLOCK != op->syserrno) && (EAGAIN != op->syserrno))566 {567 op->result.code = -1;568 return PR_TRUE;569 }570 else return PR_FALSE;571 } /* pt_send_cont */572 362 573 363 static PRBool pt_write_cont(pt_Continuation *op, PRInt16 revents) … … 651 441 _pr_rename_lock = PR_NewLock(); 652 442 Assert(NULL != _pr_rename_lock); 653 654 _pr_stdin = pt_SetMethods(0, PR_DESC_FILE, PR_FALSE, PR_TRUE);655 _pr_stdout = pt_SetMethods(1, PR_DESC_FILE, PR_FALSE, PR_TRUE);656 _pr_stderr = pt_SetMethods(2, PR_DESC_FILE, PR_FALSE, PR_TRUE);657 Assert(_pr_stdin && _pr_stdout && _pr_stderr);658 659 #ifdef DARWIN660 /* In Mac OS X v10.3 Panther Beta the IPV6_V6ONLY socket option661 * is turned on by default, contrary to what RFC 3493, Section662 * 5.3 says. So we have to turn it off. Find out whether we663 * are running on such a system.664 */665 {666 int osfd;667 osfd = socket(AF_INET6, SOCK_STREAM, 0);668 if (osfd != -1) {669 int on;670 int optlen = sizeof(on);671 if (getsockopt(osfd, IPPROTO_IPV6, IPV6_V6ONLY,672 &on, &optlen) == 0) {673 _pr_ipv6_v6only_on_by_default = on;674 }675 close(osfd);676 }677 }678 #endif679 443 } /* _PR_InitIO */ 680 444 681 445 void _PR_CleanupIO(void) 682 446 { 683 _PR_Putfd(_pr_stdin);684 _pr_stdin = NULL;685 _PR_Putfd(_pr_stdout);686 _pr_stdout = NULL;687 _PR_Putfd(_pr_stderr);688 _pr_stderr = NULL;689 690 447 if (_pr_rename_lock) 691 448 { … … 694 451 } 695 452 } /* _PR_CleanupIO */ 696 697 PR_IMPLEMENT(PRFileDesc*) PR_GetSpecialFD(PRSpecialFD osfd)698 {699 PRFileDesc *result = NULL;700 Assert(osfd >= PR_StandardInput && osfd <= PR_StandardError);701 702 if (!_pr_initialized) _PR_ImplicitInitialization();703 704 switch (osfd)705 {706 case PR_StandardInput: result = _pr_stdin; break;707 case PR_StandardOutput: result = _pr_stdout; break;708 case PR_StandardError: result = _pr_stderr; break;709 default:710 (void)PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);711 }712 return result;713 } /* PR_GetSpecialFD */714 453 715 454 /*****************************************************************************/ … … 852 591 } /* pt_Write */ 853 592 854 static PRInt32 pt_Writev(855 PRFileDesc *fd, const PRIOVec *iov, PRInt32 iov_len, PRIntervalTime timeout)856 {857 PRIntn iov_index;858 PRBool fNeedContinue = PR_FALSE;859 PRInt32 syserrno, bytes, rv = -1;860 struct iovec osiov_local[PR_MAX_IOVECTOR_SIZE], *osiov;861 int osiov_len;862 863 if (pt_TestAbort()) return rv;864 865 /* Ensured by PR_Writev */866 Assert(iov_len <= PR_MAX_IOVECTOR_SIZE);867 868 /*869 * We can't pass iov to writev because PRIOVec and struct iovec870 * may not be binary compatible. Make osiov a copy of iov and871 * pass osiov to writev. We can modify osiov if we need to872 * continue the operation.873 */874 osiov = osiov_local;875 osiov_len = iov_len;876 for (iov_index = 0; iov_index < osiov_len; iov_index++)877 {878 osiov[iov_index].iov_base = iov[iov_index].iov_base;879 osiov[iov_index].iov_len = iov[iov_index].iov_len;880 }881 882 rv = bytes = writev(fd->secret->md.osfd, osiov, osiov_len);883 syserrno = errno;884 885 if (!fd->secret->nonblocking)886 {887 if (bytes >= 0)888 {889 /*890 * If we moved some bytes, how does that implicate the891 * i/o vector list? In other words, exactly where are892 * we within that array? What are the parameters for893 * resumption? Maybe we're done!894 */895 for ( ;osiov_len > 0; osiov++, osiov_len--)896 {897 if (bytes < osiov->iov_len)898 {899 /* this one's not done yet */900 osiov->iov_base = (char*)osiov->iov_base + bytes;901 osiov->iov_len -= bytes;902 break; /* go off and do that */903 }904 bytes -= osiov->iov_len; /* this one's done cooked */905 }906 Assert(osiov_len > 0 || bytes == 0);907 if (osiov_len > 0)908 {909 if (PR_INTERVAL_NO_WAIT == timeout)910 {911 rv = -1;912 syserrno = ETIMEDOUT;913 }914 else fNeedContinue = PR_TRUE;915 }916 }917 else if (syserrno == EWOULDBLOCK || syserrno == EAGAIN)918 {919 if (PR_INTERVAL_NO_WAIT == timeout) syserrno = ETIMEDOUT;920 else921 {922 rv = 0;923 fNeedContinue = PR_TRUE;924 }925 }926 }927 928 if (fNeedContinue == PR_TRUE)929 {930 pt_Continuation op;931 932 op.arg1.osfd = fd->secret->md.osfd;933 op.arg2.buffer = (void*)osiov;934 op.arg3.amount = osiov_len;935 op.timeout = timeout;936 op.result.code = rv;937 op.function = pt_writev_cont;938 op.event = POLLOUT | POLLPRI;939 rv = pt_Continue(&op);940 syserrno = op.syserrno;941 }942 if (rv == -1) pt_MapError(_PR_MD_MAP_WRITEV_ERROR, syserrno);943 return rv;944 } /* pt_Writev */945 946 593 static PRInt32 pt_Seek(PRFileDesc *fd, PRInt32 offset, PRSeekWhence whence) 947 594 { … … 972 619 return result; 973 620 } /* pt_Available_f */ 974 975 static PRInt32 pt_Available_s(PRFileDesc *fd)976 {977 PRInt32 rv, bytes = -1;978 if (pt_TestAbort()) return bytes;979 980 rv = ioctl(fd->secret->md.osfd, FIONREAD, &bytes);981 982 if (rv == -1)983 pt_MapError(_PR_MD_MAP_SOCKETAVAILABLE_ERROR, errno);984 return bytes;985 } /* pt_Available_s */986 621 987 622 static PRStatus pt_FileInfo(PRFileDesc *fd, PRFileInfo *info) … … 996 631 return (-1 == rv) ? PR_FAILURE : PR_SUCCESS; 997 632 } /* pt_FileInfo64 */ 998 999 static PRStatus pt_Synch(PRFileDesc *fd)1000 {1001 return (NULL == fd) ? PR_FAILURE : PR_SUCCESS;1002 } /* pt_Synch */1003 633 1004 634 static PRStatus pt_Fsync(PRFileDesc *fd) … … 1015 645 } /* pt_Fsync */ 1016 646 1017 static PRStatus pt_Connect(1018 PRFileDesc *fd, const PRNetAddr *addr, PRIntervalTime timeout)1019 {1020 PRIntn rv = -1, syserrno;1021 pt_SockLen addr_len;1022 const PRNetAddr *addrp = addr;1023 #if defined(_PR_HAVE_SOCKADDR_LEN)1024 PRUint16 md_af = addr->raw.family;1025 PRNetAddr addrCopy;1026 #endif1027 1028 if (pt_TestAbort()) return PR_FAILURE;1029 1030 Assert(IsValidNetAddr(addr) == PR_TRUE);1031 addr_len = PR_NETADDR_SIZE(addr);1032 1033 #ifdef _PR_HAVE_SOCKADDR_LEN1034 addrCopy = *addr;1035 ((struct sockaddr*)&addrCopy)->sa_len = addr_len;1036 ((struct sockaddr*)&addrCopy)->sa_family = md_af;1037 rv = connect(fd->secret->md.osfd, (struct sockaddr*)&addrCopy, addr_len);1038 #else1039 rv = connect(fd->secret->md.osfd, (struct sockaddr*)addrp, addr_len);1040 #endif1041 syserrno = errno;1042 if ((-1 == rv) && (EINPROGRESS == syserrno) && (!fd->secret->nonblocking))1043 {1044 if (PR_INTERVAL_NO_WAIT == timeout) syserrno = ETIMEDOUT;1045 else1046 {1047 pt_Continuation op;1048 op.arg1.osfd = fd->secret->md.osfd;1049 #ifdef _PR_HAVE_SOCKADDR_LEN1050 op.arg2.buffer = (void*)&addrCopy;1051 #else1052 op.arg2.buffer = (void*)addr;1053 #endif1054 op.arg3.amount = addr_len;1055 op.timeout = timeout;1056 op.function = pt_connect_cont;1057 op.event = POLLOUT | POLLPRI;1058 rv = pt_Continue(&op);1059 syserrno = op.syserrno;1060 }1061 }1062 if (-1 == rv) {1063 pt_MapError(_PR_MD_MAP_CONNECT_ERROR, syserrno);1064 return PR_FAILURE;1065 }1066 return PR_SUCCESS;1067 } /* pt_Connect */1068 1069 static PRStatus pt_ConnectContinue(1070 PRFileDesc *fd, PRInt16 out_flags)1071 {1072 int err;1073 PRInt32 osfd;1074 1075 if (out_flags & PR_POLL_NVAL)1076 {1077 PR_SetError(PR_BAD_DESCRIPTOR_ERROR, 0);1078 return PR_FAILURE;1079 }1080 if ((out_flags & (PR_POLL_WRITE | PR_POLL_EXCEPT | PR_POLL_ERR)) == 0)1081 {1082 Assert(out_flags == 0);1083 PR_SetError(PR_IN_PROGRESS_ERROR, 0);1084 return PR_FAILURE;1085 }1086 1087 osfd = fd->secret->md.osfd;1088 1089 err = _MD_unix_get_nonblocking_connect_error(osfd);1090 if (err != 0)1091 {1092 _PR_MD_MAP_CONNECT_ERROR(err);1093 return PR_FAILURE;1094 }1095 return PR_SUCCESS;1096 } /* pt_ConnectContinue */1097 1098 PR_IMPLEMENT(PRStatus) PR_GetConnectStatus(const PRPollDesc *pd)1099 {1100 /* Find the NSPR layer and invoke its connectcontinue method */1101 PRFileDesc *bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);1102 1103 if (NULL == bottom)1104 {1105 PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);1106 return PR_FAILURE;1107 }1108 return pt_ConnectContinue(bottom, pd->out_flags);1109 } /* PR_GetConnectStatus */1110 1111 static PRFileDesc* pt_Accept(1112 PRFileDesc *fd, PRNetAddr *addr, PRIntervalTime timeout)1113 {1114 PRFileDesc *newfd = NULL;1115 PRIntn syserrno, osfd = -1;1116 pt_SockLen addr_len = sizeof(PRNetAddr);1117 1118 if (pt_TestAbort()) return newfd;1119 1120 #ifdef _PR_STRICT_ADDR_LEN1121 if (addr)1122 {1123 /*1124 * Set addr->raw.family just so that we can use the1125 * PR_NETADDR_SIZE macro.1126 */1127 addr->raw.family = fd->secret->af;1128 addr_len = PR_NETADDR_SIZE(addr);1129 }1130 #endif1131 1132 osfd = accept(fd->secret->md.osfd, (struct sockaddr*)addr, &addr_len);1133 syserrno = errno;1134 1135 if (osfd == -1)1136 {1137 if (fd->secret->nonblocking) goto failed;1138 1139 if (EWOULDBLOCK != syserrno && EAGAIN != syserrno1140 && ECONNABORTED != syserrno)1141 goto failed;1142 else1143 {1144 if (PR_INTERVAL_NO_WAIT == timeout) syserrno = ETIMEDOUT;1145 else1146 {1147 pt_Continuation op;1148 op.arg1.osfd = fd->secret->md.osfd;1149 op.arg2.buffer = addr;1150 op.arg3.addr_len = &addr_len;1151 op.timeout = timeout;1152 op.function = pt_accept_cont;1153 op.event = POLLIN | POLLPRI;1154 osfd = pt_Continue(&op);1155 syserrno = op.syserrno;1156 }1157 if (osfd < 0) goto failed;1158 }1159 }1160 #ifdef _PR_HAVE_SOCKADDR_LEN1161 /* ignore the sa_len field of struct sockaddr */1162 if (addr)1163 {1164 addr->raw.family = ((struct sockaddr*)addr)->sa_family;1165 }1166 #endif /* _PR_HAVE_SOCKADDR_LEN */1167 newfd = pt_SetMethods(osfd, PR_DESC_SOCKET_TCP, PR_TRUE, PR_FALSE);1168 if (newfd == NULL) close(osfd); /* $$$ whoops! this doesn't work $$$ */1169 else1170 {1171 Assert(IsValidNetAddr(addr) == PR_TRUE);1172 Assert(IsValidNetAddrLen(addr, addr_len) == PR_TRUE);1173 #ifdef LINUX1174 /*1175 * On Linux, experiments showed that the accepted sockets1176 * inherit the TCP_NODELAY socket option of the listening1177 * socket.1178 */1179 newfd->secret->md.tcp_nodelay = fd->secret->md.tcp_nodelay;1180 #endif1181 }1182 return newfd;1183 1184 failed:1185 pt_MapError(_PR_MD_MAP_ACCEPT_ERROR, syserrno);1186 return NULL;1187 } /* pt_Accept */1188 1189 static PRStatus pt_Bind(PRFileDesc *fd, const PRNetAddr *addr)1190 {1191 PRIntn rv;1192 pt_SockLen addr_len;1193 const PRNetAddr *addrp = addr;1194 #if defined(_PR_HAVE_SOCKADDR_LEN)1195 PRUint16 md_af = addr->raw.family;1196 PRNetAddr addrCopy;1197 #endif1198 1199 if (pt_TestAbort()) return PR_FAILURE;1200 1201 Assert(IsValidNetAddr(addr) == PR_TRUE);1202 if (addr->raw.family == AF_UNIX)1203 {1204 /* Disallow relative pathnames */1205 if (addr->local.path[0] != '/')1206 {1207 PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);1208 return PR_FAILURE;1209 }1210 }1211 1212 addr_len = PR_NETADDR_SIZE(addr);1213 #ifdef _PR_HAVE_SOCKADDR_LEN1214 addrCopy = *addr;1215 ((struct sockaddr*)&addrCopy)->sa_len = addr_len;1216 ((struct sockaddr*)&addrCopy)->sa_family = md_af;1217 rv = bind(fd->secret->md.osfd, (struct sockaddr*)&addrCopy, addr_len);1218 #else1219 rv = bind(fd->secret->md.osfd, (struct sockaddr*)addrp, addr_len);1220 #endif1221 1222 if (rv == -1) {1223 pt_MapError(_PR_MD_MAP_BIND_ERROR, errno);1224 return PR_FAILURE;1225 }1226 return PR_SUCCESS;1227 } /* pt_Bind */1228 1229 static PRStatus pt_Listen(PRFileDesc *fd, PRIntn backlog)1230 {1231 PRIntn rv;1232 1233 if (pt_TestAbort()) return PR_FAILURE;1234 1235 rv = listen(fd->secret->md.osfd, backlog);1236 if (rv == -1) {1237 pt_MapError(_PR_MD_MAP_LISTEN_ERROR, errno);1238 return PR_FAILURE;1239 }1240 return PR_SUCCESS;1241 } /* pt_Listen */1242 1243 static PRStatus pt_Shutdown(PRFileDesc *fd, PRIntn how)1244 {1245 PRIntn rv = -1;1246 if (pt_TestAbort()) return PR_FAILURE;1247 1248 rv = shutdown(fd->secret->md.osfd, how);1249 1250 if (rv == -1) {1251 pt_MapError(_PR_MD_MAP_SHUTDOWN_ERROR, errno);1252 return PR_FAILURE;1253 }1254 return PR_SUCCESS;1255 } /* pt_Shutdown */1256 1257 647 static PRInt16 pt_Poll(PRFileDesc *fd, PRInt16 in_flags, PRInt16 *out_flags) 1258 648 { … … 1260 650 return in_flags; 1261 651 } /* pt_Poll */ 1262 1263 static PRInt32 pt_Recv(1264 PRFileDesc *fd, void *buf, PRInt32 amount,1265 PRIntn flags, PRIntervalTime timeout)1266 {1267 PRInt32 syserrno, bytes = -1;1268 PRIntn osflags;1269 1270 if (0 == flags)1271 osflags = 0;1272 else if (PR_MSG_PEEK == flags)1273 osflags = MSG_PEEK;1274 else1275 {1276 PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);1277 return bytes;1278 }1279 1280 if (pt_TestAbort()) return bytes;1281 1282 /* recv() is a much slower call on pre-2.6 Solaris than read(). */1283 #if defined(SOLARIS)1284 if (0 == osflags)1285 bytes = read(fd->secret->md.osfd, buf, amount);1286 else1287 bytes = recv(fd->secret->md.osfd, buf, amount, osflags);1288 #else1289 bytes = recv(fd->secret->md.osfd, buf, amount, osflags);1290 #endif1291 syserrno = errno;1292 1293 if ((bytes == -1) && (syserrno == EWOULDBLOCK || syserrno == EAGAIN)1294 && (!fd->secret->nonblocking))1295 {1296 if (PR_INTERVAL_NO_WAIT == timeout) syserrno = ETIMEDOUT;1297 else1298 {1299 pt_Continuation op;1300 op.arg1.osfd = fd->secret->md.osfd;1301 op.arg2.buffer = buf;1302 op.arg3.amount = amount;1303 op.arg4.flags = osflags;1304 op.timeout = timeout;1305 op.function = pt_recv_cont;1306 op.event = POLLIN | POLLPRI;1307 bytes = pt_Continue(&op);1308 syserrno = op.syserrno;1309 }1310 }1311 if (bytes < 0)1312 pt_MapError(_PR_MD_MAP_RECV_ERROR, syserrno);1313 return bytes;1314 } /* pt_Recv */1315 1316 static PRInt32 pt_SocketRead(PRFileDesc *fd, void *buf, PRInt32 amount)1317 {1318 return pt_Recv(fd, buf, amount, 0, PR_INTERVAL_NO_TIMEOUT);1319 } /* pt_SocketRead */1320 1321 static PRInt32 pt_Send(1322 PRFileDesc *fd, const void *buf, PRInt32 amount,1323 PRIntn flags, PRIntervalTime timeout)1324 {1325 PRInt32 syserrno, bytes = -1;1326 PRBool fNeedContinue = PR_FALSE;1327 #if defined(SOLARIS)1328 PRInt32 tmp_amount = amount;1329 #endif1330 1331 /*1332 * Under HP-UX DCE threads, pthread.h includes dce/cma_ux.h,1333 * which has the following:1334 * # define send cma_send1335 * extern int cma_send (int , void *, int, int );1336 * So we need to cast away the 'const' of argument #2 for send().1337 */1338 #if defined (HPUX) && defined(_PR_DCETHREADS)1339 #define PT_SENDBUF_CAST (void *)1340 #else1341 #define PT_SENDBUF_CAST1342 #endif1343 1344 if (pt_TestAbort()) return bytes;1345 1346 /*1347 * On pre-2.6 Solaris, send() is much slower than write().1348 * On 2.6 and beyond, with in-kernel sockets, send() and1349 * write() are fairly equivalent in performance.1350 */1351 #if defined(SOLARIS)1352 Assert(0 == flags);1353 retry:1354 bytes = write(fd->secret->md.osfd, PT_SENDBUF_CAST buf, tmp_amount);1355 #else1356 bytes = send(fd->secret->md.osfd, PT_SENDBUF_CAST buf, amount, flags);1357 #endif1358 syserrno = errno;1359 1360 #if defined(SOLARIS)1361 /*1362 * The write system call has been reported to return the ERANGE error1363 * on occasion. Try to write in smaller chunks to workaround this bug.1364 */1365 if ((bytes == -1) && (syserrno == ERANGE))1366 {1367 if (tmp_amount > 1)1368 {1369 tmp_amount = tmp_amount/2; /* half the bytes */1370 goto retry;1371 }1372 }1373 #endif1374 1375 if ( (bytes >= 0) && (bytes < amount) && (!fd->secret->nonblocking) )1376 {1377 if (PR_INTERVAL_NO_WAIT == timeout)1378 {1379 bytes = -1;1380 syserrno = ETIMEDOUT;1381 }1382 else1383 {1384 buf = (char *) buf + bytes;1385 amount -= bytes;1386 fNeedContinue = PR_TRUE;1387 }1388 }1389 if ( (bytes == -1) && (syserrno == EWOULDBLOCK || syserrno == EAGAIN)1390 && (!fd->secret->nonblocking) )1391 {1392 if (PR_INTERVAL_NO_WAIT == timeout) syserrno = ETIMEDOUT;1393 else1394 {1395 bytes = 0;1396 fNeedContinue = PR_TRUE;1397 }1398 }1399 1400 if (fNeedContinue == PR_TRUE)1401 {1402 pt_Continuation op;1403 op.arg1.osfd = fd->secret->md.osfd;1404 op.arg2.buffer = (void*)buf;1405 op.arg3.amount = amount;1406 op.arg4.flags = flags;1407 op.timeout = timeout;1408 op.result.code = bytes; /* initialize the number sent */1409 op.function = pt_send_cont;1410 op.event = POLLOUT | POLLPRI;1411 bytes = pt_Continue(&op);1412 syserrno = op.syserrno;1413 }1414 if (bytes == -1)1415 pt_MapError(_PR_MD_MAP_SEND_ERROR, syserrno);1416 return bytes;1417 } /* pt_Send */1418 1419 static PRInt32 pt_SocketWrite(PRFileDesc *fd, const void *buf, PRInt32 amount)1420 {1421 return pt_Send(fd, buf, amount, 0, PR_INTERVAL_NO_TIMEOUT);1422 } /* pt_SocketWrite */1423 1424 static PRStatus pt_GetSockName(PRFileDesc *fd, PRNetAddr *addr)1425 {1426 PRIntn rv = -1;1427 pt_SockLen addr_len = sizeof(PRNetAddr);1428 1429 if (pt_TestAbort()) return PR_FAILURE;1430 1431 rv = getsockname(1432 fd->secret->md.osfd, (struct sockaddr*)addr, &addr_len);1433 if (rv == -1) {1434 pt_MapError(_PR_MD_MAP_GETSOCKNAME_ERROR, errno);1435 return PR_FAILURE;1436 } else {1437 #ifdef _PR_HAVE_SOCKADDR_LEN1438 /* ignore the sa_len field of struct sockaddr */1439 if (addr)1440 {1441 addr->raw.family = ((struct sockaddr*)addr)->sa_family;1442 }1443 #endif /* _PR_HAVE_SOCKADDR_LEN */1444 1445 Assert(IsValidNetAddr(addr) == PR_TRUE);1446 Assert(IsValidNetAddrLen(addr, addr_len) == PR_TRUE);1447 return PR_SUCCESS;1448 }1449 } /* pt_GetSockName */1450 1451 static PRStatus pt_GetPeerName(PRFileDesc *fd, PRNetAddr *addr)1452 {1453 PRIntn rv = -1;1454 pt_SockLen addr_len = sizeof(PRNetAddr);1455 1456 if (pt_TestAbort()) return PR_FAILURE;1457 1458 rv = getpeername(1459 fd->secret->md.osfd, (struct sockaddr*)addr, &addr_len);1460 1461 if (rv == -1) {1462 pt_MapError(_PR_MD_MAP_GETPEERNAME_ERROR, errno);1463 return PR_FAILURE;1464 } else {1465 #ifdef _PR_HAVE_SOCKADDR_LEN1466 /* ignore the sa_len field of struct sockaddr */1467 if (addr)1468 {1469 addr->raw.family = ((struct sockaddr*)addr)->sa_family;1470 }1471 #endif /* _PR_HAVE_SOCKADDR_LEN */1472 1473 Assert(IsValidNetAddr(addr) == PR_TRUE);1474 Assert(IsValidNetAddrLen(addr, addr_len) == PR_TRUE);1475 return PR_SUCCESS;1476 }1477 } /* pt_GetPeerName */1478 1479 static PRStatus pt_GetSocketOption(PRFileDesc *fd, PRSocketOptionData *data)1480 {1481 PRIntn rv;1482 pt_SockLen length;1483 PRInt32 level, name;1484 1485 /*1486 * PR_SockOpt_Nonblocking is a special case that does not1487 * translate to a getsockopt() call1488 */1489 if (PR_SockOpt_Nonblocking == data->option)1490 {1491 data->value.non_blocking = fd->secret->nonblocking;1492 return PR_SUCCESS;1493 }1494 1495 rv = _PR_MapOptionName(data->option, &level, &name);1496 if (PR_SUCCESS == rv)1497 {1498 switch (data->option)1499 {1500 case PR_SockOpt_Linger:1501 {1502 struct linger linger;1503 length = sizeof(linger);1504 rv = getsockopt(1505 fd->secret->md.osfd, level, name, (char *) &linger, &length);1506 Assert((-1 == rv) || (sizeof(linger) == length));1507 data->value.linger.polarity =1508 (linger.l_onoff) ? PR_TRUE : PR_FALSE;1509 data->value.linger.linger =1510 PR_SecondsToInterval(linger.l_linger);1511 break;1512 }1513 case PR_SockOpt_Reuseaddr:1514 case PR_SockOpt_Keepalive:1515 case PR_SockOpt_NoDelay:1516 case PR_SockOpt_Broadcast:1517 {1518 PRIntn value;1519 length = sizeof(PRIntn);1520 rv = getsockopt(1521 fd->secret->md.osfd, level, name, (char*)&value, &length);1522 Assert((-1 == rv) || (sizeof(PRIntn) == length));1523 data->value.reuse_addr = (0 == value) ? PR_FALSE : PR_TRUE;1524 break;1525 }1526 case PR_SockOpt_McastLoopback:1527 {1528 PRUint8 xbool;1529 length = sizeof(xbool);1530 rv = getsockopt(1531 fd->secret->md.osfd, level, name,1532 (char*)&xbool, &length);1533 Assert((-1 == rv) || (sizeof(xbool) == length));1534 data->value.mcast_loopback = (0 == xbool) ? PR_FALSE : PR_TRUE;1535 break;1536 }1537 case PR_SockOpt_RecvBufferSize:1538 case PR_SockOpt_SendBufferSize:1539 case PR_SockOpt_MaxSegment:1540 {1541 PRIntn value;1542 length = sizeof(PRIntn);1543 rv = getsockopt(1544 fd->secret->md.osfd, level, name, (char*)&value, &length);1545 Assert((-1 == rv) || (sizeof(PRIntn) == length));1546 data->value.recv_buffer_size = value;1547 break;1548 }1549 case PR_SockOpt_IpTimeToLive:1550 case PR_SockOpt_IpTypeOfService:1551 {1552 length = sizeof(PRUintn);1553 rv = getsockopt(1554 fd->secret->md.osfd, level, name,1555 (char*)&data->value.ip_ttl, &length);1556 Assert((-1 == rv) || (sizeof(PRIntn) == length));1557 break;1558 }1559 case PR_SockOpt_McastTimeToLive:1560 {1561 PRUint8 ttl;1562 length = sizeof(ttl);1563 rv = getsockopt(1564 fd->secret->md.osfd, level, name,1565 (char*)&ttl, &length);1566 Assert((-1 == rv) || (sizeof(ttl) == length));1567 data->value.mcast_ttl = ttl;1568 break;1569 }1570 case PR_SockOpt_AddMember:1571 case PR_SockOpt_DropMember:1572 {1573 struct ip_mreq mreq;1574 length = sizeof(mreq);1575 rv = getsockopt(1576 fd->secret->md.osfd, level, name, (char*)&mreq, &length);1577 Assert((-1 == rv) || (sizeof(mreq) == length));1578 data->value.add_member.mcaddr.inet.ip =1579 mreq.imr_multiaddr.s_addr;1580 data->value.add_member.ifaddr.inet.ip =1581 mreq.imr_interface.s_addr;1582 break;1583 }1584 case PR_SockOpt_McastInterface:1585 {1586 length = sizeof(data->value.mcast_if.inet.ip);1587 rv = getsockopt(1588 fd->secret->md.osfd, level, name,1589 (char*)&data->value.mcast_if.inet.ip, &length);1590 Assert((-1 == rv)1591 || (sizeof(data->value.mcast_if.inet.ip) == length));1592 break;1593 }1594 default:1595 break;1596 }1597 if (-1 == rv) _PR_MD_MAP_GETSOCKOPT_ERROR(errno);1598 }1599 return (-1 == rv) ? PR_FAILURE : PR_SUCCESS;1600 } /* pt_GetSocketOption */1601 1602 static PRStatus pt_SetSocketOption(PRFileDesc *fd, const PRSocketOptionData *data)1603 {1604 PRIntn rv;1605 PRInt32 level, name;1606 1607 /*1608 * PR_SockOpt_Nonblocking is a special case that does not1609 * translate to a setsockopt call.1610 */1611 if (PR_SockOpt_Nonblocking == data->option)1612 {1613 fd->secret->nonblocking = data->value.non_blocking;1614 return PR_SUCCESS;1615 }1616 1617 rv = _PR_MapOptionName(data->option, &level, &name);1618 if (PR_SUCCESS == rv)1619 {1620 switch (data->option)1621 {1622 case PR_SockOpt_Linger:1623 {1624 struct linger linger;1625 linger.l_onoff = data->value.linger.polarity;1626 linger.l_linger = PR_IntervalToSeconds(data->value.linger.linger);1627 rv = setsockopt(1628 fd->secret->md.osfd, level, name, (char*)&linger, sizeof(linger));1629 break;1630 }1631 case PR_SockOpt_Reuseaddr:1632 case PR_SockOpt_Keepalive:1633 case PR_SockOpt_NoDelay:1634 case PR_SockOpt_Broadcast:1635 {1636 PRIntn value = (data->value.reuse_addr) ? 1 : 0;1637 rv = setsockopt(1638 fd->secret->md.osfd, level, name,1639 (char*)&value, sizeof(PRIntn));1640 #ifdef LINUX1641 /* for pt_Linux1 */1642 if (name == TCP_NODELAY && rv == 0) {1643 fd->secret->md.tcp_nodelay = value;1644 }1645 #endif1646 break;1647 }1648 case PR_SockOpt_McastLoopback:1649 {1650 PRUint8 xbool = data->value.mcast_loopback ? 1 : 0;1651 rv = setsockopt(1652 fd->secret->md.osfd, level, name,1653 (char*)&xbool, sizeof(xbool));1654 break;1655 }1656 case PR_SockOpt_RecvBufferSize:1657 case PR_SockOpt_SendBufferSize:1658 case PR_SockOpt_MaxSegment:1659 {1660 PRIntn value = data->value.recv_buffer_size;1661 rv = setsockopt(1662 fd->secret->md.osfd, level, name,1663 (char*)&value, sizeof(PRIntn));1664 break;1665 }1666 case PR_SockOpt_IpTimeToLive:1667 case PR_SockOpt_IpTypeOfService:1668 {1669 rv = setsockopt(1670 fd->secret->md.osfd, level, name,1671 (char*)&data->value.ip_ttl, sizeof(PRUintn));1672 break;1673 }1674 case PR_SockOpt_McastTimeToLive:1675 {1676 PRUint8 ttl = data->value.mcast_ttl;1677 rv = setsockopt(1678 fd->secret->md.osfd, level, name,1679 (char*)&ttl, sizeof(ttl));1680 break;1681 }1682 case PR_SockOpt_AddMember:1683 case PR_SockOpt_DropMember:1684 {1685 struct ip_mreq mreq;1686 mreq.imr_multiaddr.s_addr =1687 data->value.add_member.mcaddr.inet.ip;1688 mreq.imr_interface.s_addr =1689 data->value.add_member.ifaddr.inet.ip;1690 rv = setsockopt(1691 fd->secret->md.osfd, level, name,1692 (char*)&mreq, sizeof(mreq));1693 break;1694 }1695 case PR_SockOpt_McastInterface:1696 {1697 rv = setsockopt(1698 fd->secret->md.osfd, level, name,1699 (char*)&data->value.mcast_if.inet.ip,1700 sizeof(data->value.mcast_if.inet.ip));1701 break;1702 }1703 default:1704 break;1705 }1706 if (-1 == rv) _PR_MD_MAP_SETSOCKOPT_ERROR(errno);1707 }1708 return (-1 == rv) ? PR_FAILURE : PR_SUCCESS;1709 } /* pt_SetSocketOption */1710 652 1711 653 /*****************************************************************************/ … … 1746 688 }; 1747 689 1748 static PRIOMethods _pr_pipe_methods = {1749 PR_DESC_PIPE,1750 pt_Close,1751 pt_Read,1752 pt_Write,1753 pt_Available_s,1754 pt_Synch,1755 (PRSeekFN)_PR_InvalidInt,1756 (PRSeek64FN)_PR_InvalidInt64,1757 (PRFileInfoFN)_PR_InvalidStatus,1758 (PRFileInfo64FN)_PR_InvalidStatus,1759 (PRWritevFN)_PR_InvalidInt,1760 (PRConnectFN)_PR_InvalidStatus,1761 (PRAcceptFN)_PR_InvalidDesc,1762 (PRBindFN)_PR_InvalidStatus,1763 (PRListenFN)_PR_InvalidStatus,1764 (PRShutdownFN)_PR_InvalidStatus,1765 (PRRecvFN)_PR_InvalidInt,1766 (PRSendFN)_PR_InvalidInt,1767 pt_Poll,1768 (PRGetsocknameFN)_PR_InvalidStatus,1769 (PRGetpeernameFN)_PR_InvalidStatus,1770 (PRReservedFN)_PR_InvalidInt,1771 (PRReservedFN)_PR_InvalidInt,1772 (PRGetsocketoptionFN)_PR_InvalidStatus,1773 (PRSetsocketoptionFN)_PR_InvalidStatus,1774 (PRConnectcontinueFN)_PR_InvalidStatus,1775 (PRReservedFN)_PR_InvalidInt,1776 (PRReservedFN)_PR_InvalidInt,1777 (PRReservedFN)_PR_InvalidInt,1778 (PRReservedFN)_PR_InvalidInt1779 };1780 1781 static PRIOMethods _pr_tcp_methods = {1782 PR_DESC_SOCKET_TCP,1783 pt_Close,1784 pt_SocketRead,1785 pt_SocketWrite,1786 pt_Available_s,1787 pt_Synch,1788 (PRSeekFN)_PR_InvalidInt,1789 (PRSeek64FN)_PR_InvalidInt64,1790 (PRFileInfoFN)_PR_InvalidStatus,1791 (PRFileInfo64FN)_PR_InvalidStatus,1792 pt_Writev,1793 pt_Connect,1794 pt_Accept,1795 pt_Bind,1796 pt_Listen,1797 pt_Shutdown,1798 pt_Recv,1799 pt_Send,1800 pt_Poll,1801 pt_GetSockName,1802 pt_GetPeerName,1803 (PRReservedFN)_PR_InvalidInt,1804 (PRReservedFN)_PR_InvalidInt,1805 pt_GetSocketOption,1806 pt_SetSocketOption,1807 pt_ConnectContinue,1808 (PRReservedFN)_PR_InvalidInt,1809 (PRReservedFN)_PR_InvalidInt,1810 (PRReservedFN)_PR_InvalidInt,1811 (PRReservedFN)_PR_InvalidInt1812 };1813 1814 static PRIOMethods _pr_socketpollfd_methods = {1815 (PRDescType) 0,1816 (PRCloseFN)_PR_InvalidStatus,1817 (PRReadFN)_PR_InvalidInt,1818 (PRWriteFN)_PR_InvalidInt,1819 (PRAvailableFN)_PR_InvalidInt,1820 (PRFsyncFN)_PR_InvalidStatus,1821 (PRSeekFN)_PR_InvalidInt,1822 (PRSeek64FN)_PR_InvalidInt64,1823 (PRFileInfoFN)_PR_InvalidStatus,1824 (PRFileInfo64FN)_PR_InvalidStatus,1825 (PRWritevFN)_PR_InvalidInt,1826 (PRConnectFN)_PR_InvalidStatus,1827 (PRAcceptFN)_PR_InvalidDesc,1828 (PRBindFN)_PR_InvalidStatus,1829 (PRListenFN)_PR_InvalidStatus,1830 (PRShutdownFN)_PR_InvalidStatus,1831 (PRRecvFN)_PR_InvalidInt,1832 (PRSendFN)_PR_InvalidInt,1833 pt_Poll,1834 (PRGetsocknameFN)_PR_InvalidStatus,1835 (PRGetpeernameFN)_PR_InvalidStatus,1836 (PRReservedFN)_PR_InvalidInt,1837 (PRReservedFN)_PR_InvalidInt,1838 (PRGetsocketoptionFN)_PR_InvalidStatus,1839 (PRSetsocketoptionFN)_PR_InvalidStatus,1840 (PRConnectcontinueFN)_PR_InvalidStatus,1841 (PRReservedFN)_PR_InvalidInt,1842 (PRReservedFN)_PR_InvalidInt,1843 (PRReservedFN)_PR_InvalidInt,1844 (PRReservedFN)_PR_InvalidInt1845 };1846 1847 #if defined(HPUX) || defined(OSF1) || defined(SOLARIS) || defined (IRIX) \1848 || defined(AIX) || defined(LINUX) || defined(FREEBSD) || defined(NETBSD) \1849 || defined(OPENBSD) || defined(BSDI) || defined(VMS) || defined(NTO) \1850 || defined(DARWIN) || defined(UNIXWARE)1851 #define _PR_FCNTL_FLAGS O_NONBLOCK1852 #else1853 #error "Can't determine architecture"1854 #endif1855 1856 /*1857 * Put a Unix file descriptor in non-blocking mode.1858 */1859 static void pt_MakeFdNonblock(PRIntn osfd)1860 {1861 PRIntn flags;1862 flags = fcntl(osfd, F_GETFL, 0);1863 flags |= _PR_FCNTL_FLAGS;1864 (void)fcntl(osfd, F_SETFL, flags);1865 }1866 1867 /*1868 * Put a Unix socket fd in non-blocking mode that can1869 * ideally be inherited by an accepted socket.1870 *1871 * Why doesn't pt_MakeFdNonblock do? This is to deal with1872 * the special case of HP-UX. HP-UX has three kinds of1873 * non-blocking modes for sockets: the fcntl() O_NONBLOCK1874 * and O_NDELAY flags and ioctl() FIOSNBIO request. Only1875 * the ioctl() FIOSNBIO form of non-blocking mode is1876 * inherited by an accepted socket.1877 *1878 * Other platforms just use the generic pt_MakeFdNonblock1879 * to put a socket in non-blocking mode.1880 */1881 #ifdef HPUX1882 static void pt_MakeSocketNonblock(PRIntn osfd)1883 {1884 PRIntn one = 1;1885 (void)ioctl(osfd, FIOSNBIO, &one);1886 }1887 #else1888 #define pt_MakeSocketNonblock pt_MakeFdNonblock1889 #endif1890 1891 690 static PRFileDesc *pt_SetMethods( 1892 691 PRIntn osfd, PRDescType type, PRBool isAcceptedSocket, PRBool imported) … … 1910 709 { 1911 710 case PR_DESC_FILE: 1912 fd->methods = PR_GetFileMethods(); 1913 break; 1914 case PR_DESC_SOCKET_TCP: 1915 fd->methods = PR_GetTCPMethods(); 1916 #ifdef _PR_ACCEPT_INHERIT_NONBLOCK 1917 if (!isAcceptedSocket) pt_MakeSocketNonblock(osfd); 1918 #else 1919 pt_MakeSocketNonblock(osfd); 1920 #endif 1921 break; 1922 case PR_DESC_PIPE: 1923 fd->methods = PR_GetPipeMethods(); 1924 pt_MakeFdNonblock(osfd); 711 fd->methods = &_pr_file_methods; 1925 712 break; 1926 713 default: … … 1930 717 return fd; 1931 718 } /* pt_SetMethods */ 1932 1933 PR_IMPLEMENT(const PRIOMethods*) PR_GetFileMethods(void)1934 {1935 return &_pr_file_methods;1936 } /* PR_GetFileMethods */1937 1938 PR_IMPLEMENT(const PRIOMethods*) PR_GetPipeMethods(void)1939 {1940 return &_pr_pipe_methods;1941 } /* PR_GetPipeMethods */1942 1943 PR_IMPLEMENT(const PRIOMethods*) PR_GetTCPMethods(void)1944 {1945 return &_pr_tcp_methods;1946 } /* PR_GetTCPMethods */1947 1948 static const PRIOMethods* PR_GetSocketPollFdMethods(void)1949 {1950 return &_pr_socketpollfd_methods;1951 } /* PR_GetSocketPollFdMethods */1952 1953 PR_IMPLEMENT(PRFileDesc*) PR_AllocFileDesc(1954 PRInt32 osfd, const PRIOMethods *methods)1955 {1956 PRFileDesc *fd = _PR_Getfd();1957 1958 if (NULL == fd) goto failed;1959 1960 fd->methods = methods;1961 fd->secret->md.osfd = osfd;1962 /* Make fd non-blocking */1963 if (osfd > 2)1964 {1965 /* Don't mess around with stdin, stdout or stderr */1966 if (&_pr_tcp_methods == methods) pt_MakeSocketNonblock(osfd);1967 else pt_MakeFdNonblock(osfd);1968 }1969 fd->secret->state = _PR_FILEDESC_OPEN;1970 fd->secret->inheritable = _PR_TRI_UNKNOWN;1971 return fd;1972 1973 failed:1974 PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);1975 return fd;1976 } /* PR_AllocFileDesc */1977 1978 #ifdef VBOX1979 PRUintn _PR_NetAddrSize(const PRNetAddr* addr)1980 {1981 PRUintn addrsize;1982 1983 #if defined(XP_UNIX) || defined(XP_OS2_EMX)1984 if (AF_UNIX == addr->raw.family)1985 addrsize = sizeof(addr->local);1986 #endif1987 else addrsize = 0;1988 1989 return addrsize;1990 } /* _PR_NetAddrSize */1991 #endif1992 1993 PR_IMPLEMENT(PRFileDesc*) PR_Socket(PRInt32 domain, PRInt32 type, PRInt32 proto)1994 {1995 PRIntn osfd;1996 PRDescType ftype;1997 PRFileDesc *fd = NULL;1998 PRInt32 tmp_domain = domain;1999 2000 if (!_pr_initialized) _PR_ImplicitInitialization();2001 2002 if (pt_TestAbort()) return NULL;2003 2004 if (PF_UNIX != domain)2005 {2006 PR_SetError(PR_ADDRESS_NOT_SUPPORTED_ERROR, 0);2007 return fd;2008 }2009 if (type == SOCK_STREAM) ftype = PR_DESC_SOCKET_TCP;2010 else if (type == SOCK_DGRAM) ftype = PR_DESC_SOCKET_UDP;2011 else2012 {2013 (void)PR_SetError(PR_ADDRESS_NOT_SUPPORTED_ERROR, 0);2014 return fd;2015 }2016 2017 osfd = socket(domain, type, proto);2018 if (osfd == -1) pt_MapError(_PR_MD_MAP_SOCKET_ERROR, errno);2019 else2020 {2021 fd = pt_SetMethods(osfd, ftype, PR_FALSE, PR_FALSE);2022 if (fd == NULL) close(osfd);2023 }2024 #ifdef _PR_STRICT_ADDR_LEN2025 if (fd != NULL) fd->secret->af = domain;2026 #endif2027 return fd;2028 } /* PR_Socket */2029 719 2030 720 /*****************************************************************************/ … … 2092 782 } /* PR_Open */ 2093 783 2094 PR_IMPLEMENT(PRStatus) PR_Delete(const char *name)2095 {2096 PRIntn rv = -1;2097 2098 if (!_pr_initialized) _PR_ImplicitInitialization();2099 2100 if (pt_TestAbort()) return PR_FAILURE;2101 2102 rv = unlink(name);2103 2104 if (rv == -1) {2105 pt_MapError(_PR_MD_MAP_UNLINK_ERROR, errno);2106 return PR_FAILURE;2107 } else2108 return PR_SUCCESS;2109 } /* PR_Delete */2110 2111 PR_IMPLEMENT(PRStatus) PR_GetFileInfo(const char *fn, PRFileInfo *info)2112 {2113 PRInt32 rv = _PR_MD_GETFILEINFO(fn, info);2114 return (0 == rv) ? PR_SUCCESS : PR_FAILURE;2115 } /* PR_GetFileInfo */2116 2117 784 PR_IMPLEMENT(PRStatus) PR_GetFileInfo64(const char *fn, PRFileInfo64 *info) 2118 785 { … … 2124 791 } /* PR_GetFileInfo64 */ 2125 792 2126 static PRInt32 _pr_poll_with_poll(2127 PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout)2128 {2129 PRInt32 ready = 0;2130 /*2131 * For restarting poll() if it is interrupted by a signal.2132 * We use these variables to figure out how much time has2133 * elapsed and how much of the timeout still remains.2134 */2135 PRIntervalTime start, elapsed, remaining;2136 2137 if (pt_TestAbort()) return -1;2138 2139 if (0 == npds) RTThreadSleep(PR_IntervalToMilliseconds(timeout));2140 else2141 {2142 #define STACK_POLL_DESC_COUNT 642143 struct pollfd stack_syspoll[STACK_POLL_DESC_COUNT];2144 struct pollfd *syspoll;2145 PRIntn index, msecs;2146 2147 if (npds <= STACK_POLL_DESC_COUNT)2148 {2149 syspoll = stack_syspoll;2150 }2151 else2152 {2153 PRThread *me = PR_GetCurrentThread();2154 if (npds > me->syspoll_count)2155 {2156 PR_Free(me->syspoll_list);2157 me->syspoll_list =2158 (struct pollfd*)PR_MALLOC(npds * sizeof(struct pollfd));2159 if (NULL == me->syspoll_list)2160 {2161 me->syspoll_count = 0;2162 PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);2163 return -1;2164 }2165 me->syspoll_count = npds;2166 }2167 syspoll = me->syspoll_list;2168 }2169 2170 for (index = 0; index < npds; ++index)2171 {2172 PRInt16 in_flags_read = 0, in_flags_write = 0;2173 PRInt16 out_flags_read = 0, out_flags_write = 0;2174 2175 if ((NULL != pds[index].fd) && (0 != pds[index].in_flags))2176 {2177 if (pds[index].in_flags & PR_POLL_READ)2178 {2179 in_flags_read = (pds[index].fd->methods->poll)(2180 pds[index].fd,2181 pds[index].in_flags & ~PR_POLL_WRITE,2182 &out_flags_read);2183 }2184 if (pds[index].in_flags & PR_POLL_WRITE)2185 {2186 in_flags_write = (pds[index].fd->methods->poll)(2187 pds[index].fd,2188 pds[index].in_flags & ~PR_POLL_READ,2189 &out_flags_write);2190 }2191 if ((0 != (in_flags_read & out_flags_read))2192 || (0 != (in_flags_write & out_flags_write)))2193 {2194 /* this one is ready right now */2195 if (0 == ready)2196 {2197 /*2198 * We will return without calling the system2199 * poll function. So zero the out_flags2200 * fields of all the poll descriptors before2201 * this one.2202 */2203 int i;2204 for (i = 0; i < index; i++)2205 {2206 pds[i].out_flags = 0;2207 }2208 }2209 ready += 1;2210 pds[index].out_flags = out_flags_read | out_flags_write;2211 }2212 else2213 {2214 /* now locate the NSPR layer at the bottom of the stack */2215 PRFileDesc *bottom = PR_GetIdentitiesLayer(2216 pds[index].fd, PR_NSPR_IO_LAYER);2217 Assert(NULL != bottom); /* what to do about that? */2218 pds[index].out_flags = 0; /* pre-condition */2219 if ((NULL != bottom)2220 && (_PR_FILEDESC_OPEN == bottom->secret->state))2221 {2222 if (0 == ready)2223 {2224 syspoll[index].fd = bottom->secret->md.osfd;2225 syspoll[index].events = 0;2226 if (in_flags_read & PR_POLL_READ)2227 {2228 pds[index].out_flags |=2229 _PR_POLL_READ_SYS_READ;2230 syspoll[index].events |= POLLIN;2231 }2232 if (in_flags_read & PR_POLL_WRITE)2233 {2234 pds[index].out_flags |=2235 _PR_POLL_READ_SYS_WRITE;2236 syspoll[index].events |= POLLOUT;2237 }2238 if (in_flags_write & PR_POLL_READ)2239 {2240 pds[index].out_flags |=2241 _PR_POLL_WRITE_SYS_READ;2242 syspoll[index].events |= POLLIN;2243 }2244 if (in_flags_write & PR_POLL_WRITE)2245 {2246 pds[index].out_flags |=2247 _PR_POLL_WRITE_SYS_WRITE;2248 syspoll[index].events |= POLLOUT;2249 }2250 if (pds[index].in_flags & PR_POLL_EXCEPT)2251 syspoll[index].events |= POLLPRI;2252 }2253 }2254 else2255 {2256 if (0 == ready)2257 {2258 int i;2259 for (i = 0; i < index; i++)2260 {2261 pds[i].out_flags = 0;2262 }2263 }2264 ready += 1; /* this will cause an abrupt return */2265 pds[index].out_flags = PR_POLL_NVAL; /* bogii */2266 }2267 }2268 }2269 else2270 {2271 /* make poll() ignore this entry */2272 syspoll[index].fd = -1;2273 syspoll[index].events = 0;2274 pds[index].out_flags = 0;2275 }2276 }2277 if (0 == ready)2278 {2279 switch (timeout)2280 {2281 case PR_INTERVAL_NO_WAIT: msecs = 0; break;2282 case PR_INTERVAL_NO_TIMEOUT: msecs = -1; break;2283 default:2284 msecs = PR_IntervalToMilliseconds(timeout);2285 start = PR_IntervalNow();2286 }2287 2288 retry:2289 ready = poll(syspoll, npds, msecs);2290 if (-1 == ready)2291 {2292 PRIntn oserror = errno;2293 2294 if (EINTR == oserror)2295 {2296 if (timeout == PR_INTERVAL_NO_TIMEOUT)2297 goto retry;2298 else if (timeout == PR_INTERVAL_NO_WAIT)2299 ready = 0; /* don't retry, just time out */2300 else2301 {2302 elapsed = (PRIntervalTime) (PR_IntervalNow()2303 - start);2304 if (elapsed > timeout)2305 ready = 0; /* timed out */2306 else2307 {2308 remaining = timeout - elapsed;2309 msecs = PR_IntervalToMilliseconds(remaining);2310 goto retry;2311 }2312 }2313 }2314 else2315 {2316 _PR_MD_MAP_POLL_ERROR(oserror);2317 }2318 }2319 else if (ready > 0)2320 {2321 for (index = 0; index < npds; ++index)2322 {2323 PRInt16 out_flags = 0;2324 if ((NULL != pds[index].fd) && (0 != pds[index].in_flags))2325 {2326 if (0 != syspoll[index].revents)2327 {2328 if (syspoll[index].revents & POLLIN)2329 {2330 if (pds[index].out_flags2331 & _PR_POLL_READ_SYS_READ)2332 {2333 out_flags |= PR_POLL_READ;2334 }2335 if (pds[index].out_flags2336 & _PR_POLL_WRITE_SYS_READ)2337 {2338 out_flags |= PR_POLL_WRITE;2339 }2340 }2341 if (syspoll[index].revents & POLLOUT)2342 {2343 if (pds[index].out_flags2344 & _PR_POLL_READ_SYS_WRITE)2345 {2346 out_flags |= PR_POLL_READ;2347 }2348 if (pds[index].out_flags2349 & _PR_POLL_WRITE_SYS_WRITE)2350 {2351 out_flags |= PR_POLL_WRITE;2352 }2353 }2354 if (syspoll[index].revents & POLLPRI)2355 out_flags |= PR_POLL_EXCEPT;2356 if (syspoll[index].revents & POLLERR)2357 out_flags |= PR_POLL_ERR;2358 if (syspoll[index].revents & POLLNVAL)2359 out_flags |= PR_POLL_NVAL;2360 if (syspoll[index].revents & POLLHUP)2361 out_flags |= PR_POLL_HUP;2362 }2363 }2364 pds[index].out_flags = out_flags;2365 }2366 }2367 }2368 }2369 return ready;2370 2371 } /* _pr_poll_with_poll */2372 2373 PR_IMPLEMENT(PRInt32) PR_Poll(2374 PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout)2375 {2376 return(_pr_poll_with_poll(pds, npds, timeout));2377 }2378 2379 PR_IMPLEMENT(PRFileDesc*) PR_OpenTCPSocket(PRIntn af)2380 {2381 return PR_Socket(af, SOCK_STREAM, 0);2382 } /* PR_NewTCPSocket */2383 2384 PR_IMPLEMENT(PRStatus) PR_CreatePipe(2385 PRFileDesc **readPipe,2386 PRFileDesc **writePipe2387 )2388 {2389 int pipefd[2];2390 2391 if (pt_TestAbort()) return PR_FAILURE;2392 2393 if (pipe(pipefd) == -1)2394 {2395 /* XXX map pipe error */2396 PR_SetError(PR_UNKNOWN_ERROR, errno);2397 return PR_FAILURE;2398 }2399 fcntl(pipefd[0], F_SETFD, FD_CLOEXEC);2400 fcntl(pipefd[1], F_SETFD, FD_CLOEXEC);2401 *readPipe = pt_SetMethods(pipefd[0], PR_DESC_PIPE, PR_FALSE, PR_FALSE);2402 if (NULL == *readPipe)2403 {2404 close(pipefd[0]);2405 close(pipefd[1]);2406 return PR_FAILURE;2407 }2408 *writePipe = pt_SetMethods(pipefd[1], PR_DESC_PIPE, PR_FALSE, PR_FALSE);2409 if (NULL == *writePipe)2410 {2411 PR_Close(*readPipe);2412 close(pipefd[1]);2413 return PR_FAILURE;2414 }2415 return PR_SUCCESS;2416 }2417 2418 /*2419 ** Set the inheritance attribute of a file descriptor.2420 */2421 PR_IMPLEMENT(PRStatus) PR_SetFDInheritable(2422 PRFileDesc *fd,2423 PRBool inheritable)2424 {2425 /*2426 * Only a non-layered, NSPR file descriptor can be inherited2427 * by a child process.2428 */2429 if (fd->identity != PR_NSPR_IO_LAYER)2430 {2431 PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);2432 return PR_FAILURE;2433 }2434 if (fd->secret->inheritable != inheritable)2435 {2436 if (fcntl(fd->secret->md.osfd, F_SETFD,2437 inheritable ? 0 : FD_CLOEXEC) == -1)2438 {2439 return PR_FAILURE;2440 }2441 fd->secret->inheritable = (_PRTriStateBool) inheritable;2442 }2443 return PR_SUCCESS;2444 }2445 2446 /*****************************************************************************/2447 /***************************** I/O friends methods ***************************/2448 /*****************************************************************************/2449 2450 PR_IMPLEMENT(PRFileDesc*) PR_ImportFile(PRInt32 osfd)2451 {2452 PRFileDesc *fd;2453 2454 if (!_pr_initialized) _PR_ImplicitInitialization();2455 fd = pt_SetMethods(osfd, PR_DESC_FILE, PR_FALSE, PR_TRUE);2456 if (NULL == fd) close(osfd);2457 return fd;2458 } /* PR_ImportFile */2459 2460 PR_IMPLEMENT(PRFileDesc*) PR_ImportPipe(PRInt32 osfd)2461 {2462 PRFileDesc *fd;2463 2464 if (!_pr_initialized) _PR_ImplicitInitialization();2465 fd = pt_SetMethods(osfd, PR_DESC_PIPE, PR_FALSE, PR_TRUE);2466 if (NULL == fd) close(osfd);2467 return fd;2468 } /* PR_ImportPipe */2469 2470 PR_IMPLEMENT(PRFileDesc*) PR_ImportTCPSocket(PRInt32 osfd)2471 {2472 PRFileDesc *fd;2473 2474 if (!_pr_initialized) _PR_ImplicitInitialization();2475 fd = pt_SetMethods(osfd, PR_DESC_SOCKET_TCP, PR_FALSE, PR_TRUE);2476 if (NULL == fd) close(osfd);2477 #ifdef _PR_STRICT_ADDR_LEN2478 if (NULL != fd) fd->secret->af = PF_INET;2479 #endif2480 return fd;2481 } /* PR_ImportTCPSocket */2482 2483 PR_IMPLEMENT(PRFileDesc*) PR_ImportUDPSocket(PRInt32 osfd)2484 {2485 PRFileDesc *fd;2486 2487 if (!_pr_initialized) _PR_ImplicitInitialization();2488 fd = pt_SetMethods(osfd, PR_DESC_SOCKET_UDP, PR_FALSE, PR_TRUE);2489 if (NULL != fd) close(osfd);2490 return fd;2491 } /* PR_ImportUDPSocket */2492 2493 PR_IMPLEMENT(PRFileDesc*) PR_CreateSocketPollFd(PRInt32 osfd)2494 {2495 PRFileDesc *fd;2496 2497 if (!_pr_initialized) _PR_ImplicitInitialization();2498 2499 fd = _PR_Getfd();2500 2501 if (fd == NULL) PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);2502 else2503 {2504 fd->secret->md.osfd = osfd;2505 fd->secret->inheritable = _PR_TRI_FALSE;2506 fd->secret->state = _PR_FILEDESC_OPEN;2507 fd->methods = PR_GetSocketPollFdMethods();2508 }2509 2510 return fd;2511 } /* PR_CreateSocketPollFD */2512 2513 PR_IMPLEMENT(PRStatus) PR_DestroySocketPollFd(PRFileDesc *fd)2514 {2515 if (NULL == fd)2516 {2517 PR_SetError(PR_BAD_DESCRIPTOR_ERROR, 0);2518 return PR_FAILURE;2519 }2520 fd->secret->state = _PR_FILEDESC_CLOSED;2521 _PR_Putfd(fd);2522 return PR_SUCCESS;2523 } /* PR_DestroySocketPollFd */2524 2525 #ifdef VBOX2526 PR_IMPLEMENT(PRFileDesc*) PR_GetIdentitiesLayer(PRFileDesc* fd, PRDescIdentity id)2527 {2528 PRFileDesc *layer = fd;2529 2530 if (PR_TOP_IO_LAYER == id) {2531 if (PR_IO_LAYER_HEAD == fd->identity)2532 return fd->lower;2533 else2534 return fd;2535 }2536 2537 for (layer = fd; layer != NULL; layer = layer->lower)2538 {2539 if (id == layer->identity) return layer;2540 }2541 for (layer = fd; layer != NULL; layer = layer->higher)2542 {2543 if (id == layer->identity) return layer;2544 }2545 return NULL;2546 } /* PR_GetIdentitiesLayer */2547 #endif2548 2549 PR_IMPLEMENT(PRInt32) PR_FileDesc2NativeHandle(PRFileDesc *bottom)2550 {2551 PRInt32 osfd = -1;2552 bottom = (NULL == bottom) ?2553 NULL : PR_GetIdentitiesLayer(bottom, PR_NSPR_IO_LAYER);2554 if (NULL == bottom) PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);2555 else osfd = bottom->secret->md.osfd;2556 return osfd;2557 } /* PR_FileDesc2NativeHandle */2558 2559 PR_IMPLEMENT(void) PR_ChangeFileDescNativeHandle(PRFileDesc *fd,2560 PRInt32 handle)2561 {2562 if (fd) fd->secret->md.osfd = handle;2563 } /* PR_ChangeFileDescNativeHandle*/2564 2565 793 /* ptio.c */
Note:
See TracChangeset
for help on using the changeset viewer.