NS_IMETHODIMP nsFileStream::SetEOF() { if (mFD == nsnull) return NS_BASE_STREAM_CLOSED; #if defined(XP_UNIX) || defined(XP_OS2) || defined(XP_BEOS) // Some system calls require an EOF offset. PRInt64 offset; nsresult rv = Tell(&offset); if (NS_FAILED(rv)) return rv; #endif #if defined(XP_UNIX) || defined(XP_BEOS) if (ftruncate(PR_FileDesc2NativeHandle(mFD), offset) != 0) { NS_ERROR("ftruncate failed"); return NS_ERROR_FAILURE; } #elif defined(XP_WIN) if (!SetEndOfFile((HANDLE) PR_FileDesc2NativeHandle(mFD))) { NS_ERROR("SetEndOfFile failed"); return NS_ERROR_FAILURE; } #elif defined(XP_OS2) if (DosSetFileSize((HFILE) PR_FileDesc2NativeHandle(mFD), offset) != NO_ERROR) { NS_ERROR("DosSetFileSize failed"); return NS_ERROR_FAILURE; } #else // XXX not implemented #endif return NS_OK; }
PollableEvent::PollableEvent() : mWriteFD(nullptr) , mReadFD(nullptr) , mSignaled(false) { MOZ_COUNT_CTOR(PollableEvent); MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread); // create pair of prfiledesc that can be used as a poll()ble // signal. on windows use a localhost socket pair, and on // unix use a pipe. #ifdef USEPIPE SOCKET_LOG(("PollableEvent() using pipe\n")); if (PR_CreatePipe(&mReadFD, &mWriteFD) == PR_SUCCESS) { // make the pipe non blocking. NSPR asserts at // trying to use SockOpt here PROsfd fd = PR_FileDesc2NativeHandle(mReadFD); int flags = fcntl(fd, F_GETFL, 0); (void)fcntl(fd, F_SETFL, flags | O_NONBLOCK); fd = PR_FileDesc2NativeHandle(mWriteFD); flags = fcntl(fd, F_GETFL, 0); (void)fcntl(fd, F_SETFL, flags | O_NONBLOCK); } else { mReadFD = nullptr; mWriteFD = nullptr; SOCKET_LOG(("PollableEvent() pipe failed\n")); } #else SOCKET_LOG(("PollableEvent() using socket pair\n")); PRFileDesc *fd[2]; LazyInitSocket(); if (NewTCPSocketPair(fd)) { mReadFD = fd[0]; mWriteFD = fd[1]; // compatibility with LSPs such as McAfee that assume a NSPR // layer for read ala the nspr Pollable Event - Bug 698882. This layer is a nop. PRFileDesc *topLayer = PR_CreateIOLayerStub(sPollableEventLayerIdentity, sPollableEventLayerMethodsPtr); if (topLayer) { if (PR_PushIOLayer(fd[0], PR_TOP_IO_LAYER, topLayer) == PR_FAILURE) { topLayer->dtor(topLayer); } else { SOCKET_LOG(("PollableEvent() nspr layer ok\n")); mReadFD = topLayer; } } } else { SOCKET_LOG(("PollableEvent() socketpair failed\n")); } #endif if (mReadFD && mWriteFD) { // prime the system to deal with races invovled in [dc]tor cycle SOCKET_LOG(("PollableEvent() ctor ok\n")); mSignaled = true; PR_Write(mWriteFD, "I", 1); } }
void nsSOCKSSocketInfo::FixupAddressFamily(PRFileDesc *fd, PRNetAddr *proxy) { int32_t proxyFamily = PR_NetAddrFamily(&mInternalProxyAddr); // Do nothing if the address family is already matched if (proxyFamily == mDestinationFamily) { return; } // If the system does not support IPv6 and the proxy address is IPv6, // We can do nothing here. if (proxyFamily == PR_AF_INET6 && !ipv6Supported) { return; } // If the system does not support IPv6 and the destination address is // IPv6, convert IPv4 address to IPv4-mapped IPv6 address to satisfy // the emulation layer if (mDestinationFamily == PR_AF_INET6 && !ipv6Supported) { proxy->ipv6.family = PR_AF_INET6; proxy->ipv6.port = mInternalProxyAddr.inet.port; uint8_t *proxyp = proxy->ipv6.ip.pr_s6_addr; memset(proxyp, 0, 10); memset(proxyp + 10, 0xff, 2); memcpy(proxyp + 12,(char *) &mInternalProxyAddr.inet.ip, 4); // mDestinationFamily should not be updated return; } // Get an OS native handle from a specified FileDesc PROsfd osfd = PR_FileDesc2NativeHandle(fd); if (osfd == -1) { return; } // Create a new FileDesc with a specified family PRFileDesc *tmpfd = PR_OpenTCPSocket(proxyFamily); if (!tmpfd) { return; } PROsfd newsd = PR_FileDesc2NativeHandle(tmpfd); if (newsd == -1) { PR_Close(tmpfd); return; } // Must succeed because PR_FileDesc2NativeHandle succeeded fd = PR_GetIdentitiesLayer(fd, PR_NSPR_IO_LAYER); MOZ_ASSERT(fd); // Swap OS native handles PR_ChangeFileDescNativeHandle(fd, newsd); PR_ChangeFileDescNativeHandle(tmpfd, osfd); // Close temporary FileDesc which is now associated with // old OS native handle PR_Close(tmpfd); mDestinationFamily = proxyFamily; }
NSAPI_PUBLIC SYS_NETFD net_dup2(SYS_NETFD prfd, int osfd) { SYS_NETFD newfd = NULL; if (prfd && PR_FileDesc2NativeHandle(prfd) != osfd) { if (dup2(PR_FileDesc2NativeHandle(prfd), osfd) != -1) { newfd = PR_ImportFile(osfd); if (!newfd) close(osfd); } else { NsprError::mapUnixErrno(); } } return newfd; }
mozilla::ipc::IPCResult TemporaryIPCBlobParent::CreateAndShareFile() { MOZ_ASSERT(mActive); MOZ_ASSERT(!mFile); nsresult rv = NS_OpenAnonymousTemporaryNsIFile(getter_AddRefs(mFile)); if (NS_WARN_IF(NS_FAILED(rv))) { return SendDeleteError(rv); } PRFileDesc* fd; rv = mFile->OpenNSPRFileDesc(PR_RDWR, PR_IRWXU, &fd); if (NS_WARN_IF(NS_FAILED(rv))) { return SendDeleteError(rv); } FileDescriptor fdd = FileDescriptor(FileDescriptor::PlatformHandleType(PR_FileDesc2NativeHandle(fd))); // The FileDescriptor object owns a duplicate of the file handle; we // must close the original (and clean up the NSPR descriptor). PR_Close(fd); Unused << SendFileDesc(fdd); return IPC_OK(); }
NSAPI_PUBLIC int net_ioctl(SYS_NETFD s, int tag, void *result) { int rv; #ifdef XP_WIN32 rv = ioctlsocket(PR_FileDesc2NativeHandle(s),tag,(unsigned long *)result); if (rv == -1) NsprError::mapWinsock2Error(); #else rv = ioctl(PR_FileDesc2NativeHandle(s), tag, result); if (rv == -1) NsprError::mapUnixErrno(); #endif return rv; }
void nsTemporaryFileInputStream::Serialize(InputStreamParams& aParams, FileDescriptorArray& aFileDescriptors) { TemporaryFileInputStreamParams params; MutexAutoLock lock(mFileDescOwner->FileMutex()); MOZ_ASSERT(mFileDescOwner->mFD); if (!mClosed) { FileHandleType fd = FileHandleType(PR_FileDesc2NativeHandle(mFileDescOwner->mFD)); NS_ASSERTION(fd, "This should never be null!"); DebugOnly<FileDescriptor*> dbgFD = aFileDescriptors.AppendElement(fd); NS_ASSERTION(dbgFD->IsValid(), "Sending an invalid file descriptor!"); params.fileDescriptorIndex() = aFileDescriptors.Length() - 1; Close(); } else { NS_WARNING("The stream is already closed. " "Sending an invalid file descriptor to the other process!"); params.fileDescriptorIndex() = UINT32_MAX; } params.startPos() = mCurPos; params.endPos() = mEndPos; aParams = params; }
NSAPI_PUBLIC void INTnet_cancelIO(PRFileDesc* fd) { #ifdef XP_WIN32 // In the case of filters, only the highest layer in the stack (e.g. // original net_read call) will make the PR_NT_CancelIo call if (fd->higher) return; // If we're using WIN95 NSPR, we don't need to do anything if (net_pfn_PR_NT_CancelIo == NULL) return; NsprError error; error.save(); // If this isn't a custom, non-socket PRFileDesc... if (PR_FileDesc2NativeHandle(fd) != -1) { PFN_PR_NT_CancelIo pfn = net_get_PR_NT_CancelIo(); if (pfn != NULL) { // Found a PR_NT_CancelIo() function. We're using WINNT NSPR. // Call PR_NT_CancelIo(). (*pfn)(fd); } } error.restore(); #endif }
void file_seteof(file_t file) { #if defined(XP_WIN) SetEndOfFile((HANDLE)PR_FileDesc2NativeHandle((PRFileDesc*)file)); #elif defined(XP_UNIX) PRInt64 offset = PR_Seek64((PRFileDesc*)file, 0, SEEK_CUR); if (offset < 1) { return; } ftruncate(PR_FileDesc2NativeHandle((PRFileDesc*)file), offset); #else #error not implemented #endif }
static void ClientThreadFunc(void *arg) { PRFileDesc *badFD = (PRFileDesc *) arg; /* * Make the fd invalid */ #if defined(XP_UNIX) || defined(XP_AMIGAOS) close(PR_FileDesc2NativeHandle(badFD)); #elif defined(XP_OS2) soclose(PR_FileDesc2NativeHandle(badFD)); #elif defined(WIN32) || defined(WIN16) closesocket(PR_FileDesc2NativeHandle(badFD)); #else #error "Unknown architecture" #endif }
NSAPI_PUBLIC int net_getpeername(SYS_NETFD s, struct sockaddr *name, int *namelen) { int rv; rv = getpeername(PR_FileDesc2NativeHandle(s), name, (TCPLEN_T *)namelen); if (rv == -1) NsprError::mapSocketError(); return rv; }
NSAPI_PUBLIC int net_setsockopt(SYS_NETFD s, int level, int optname, const void *optval, int optlen) { int rv; rv = setsockopt(PR_FileDesc2NativeHandle(s), level, optname, (char *)optval, optlen); if (rv == -1) NsprError::mapSocketError(); return rv; }
PR_IMPLEMENT(PRUint32) PR_vfprintf(PRFileDesc* fd, const char *fmt, va_list ap) { /* XXX this could be better */ PRUint32 rv, len; char* msg = PR_vsmprintf(fmt, ap); len = strlen(msg); #ifdef XP_OS2 /* * OS/2 really needs a \r for every \n. * In the future we should try to use scatter-gather instead of a * succession of PR_Write. */ if (isatty(PR_FileDesc2NativeHandle(fd))) { PRUint32 last = 0, idx; PRInt32 tmp; rv = 0; for (idx = 0; idx < len+1; idx++) { if ((idx - last > 0) && (('\n' == msg[idx]) || (idx == len))) { tmp = PR_Write(fd, msg + last, idx - last); if (tmp >= 0) { rv += tmp; } last = idx; } /* * if current character is \n, and * previous character isn't \r, and * next character isn't \r */ if (('\n' == msg[idx]) && ((0 == idx) || ('\r' != msg[idx-1])) && ('\r' != msg[idx+1])) { /* add extra \r */ tmp = PR_Write(fd, "\r", 1); if (tmp >= 0) { rv += tmp; } } } } else { rv = PR_Write(fd, msg, len); } #else rv = PR_Write(fd, msg, len); #endif PR_DELETE(msg); return rv; }
//----------------------------------------------------------------------------- // FcgiServerChannel::~FcgiServerChannel //----------------------------------------------------------------------------- FcgiServerChannel::~FcgiServerChannel() { if (fd) { #ifdef XP_WIN32 if (config->udsName) { HANDLE hd = (HANDLE)PR_FileDesc2NativeHandle(fd); CloseHandle(hd); } else { #endif // XP_WIN32 PR_Close(fd); #ifdef XP_WIN32 } #endif // XP_WIN32 fd = NULL; } }
OsConnectionSocket* OsTLSServerSocket::accept() { OsConnectionSocket* newSocket = NULL; if (socketDescriptor == OS_INVALID_SOCKET_DESCRIPTOR) { OsSysLog::add(FAC_KERNEL, PRI_ERR , "OsTLSServerSocket: accept exiting because socketDescriptor is %d" ,socketDescriptor); } else { /* Block while waiting for a client to connect. */ struct sockaddr_in clientSocketAddr; int clientAddrLength = sizeof clientSocketAddr; PRNetAddr addr; PRFileDesc *tcpSocket; PRFileDesc* listenSocket = PR_ImportTCPSocket(socketDescriptor); /* Accept a connection to the socket. */ tcpSocket = PR_Accept(listenSocket, &addr, PR_INTERVAL_NO_TIMEOUT); if (!tcpSocket) { int error = OsSocketGetERRNO(); OsSysLog::add(FAC_KERNEL, PRI_ERR, "OsTLSServerSocket: accept call failed with error: %d=%x", error, error); socketDescriptor = OS_INVALID_SOCKET_DESCRIPTOR; } else { // need to create a new OsTLSConnectionSocket int socketDescriptor = PR_FileDesc2NativeHandle(tcpSocket); newSocket = new OsTLSServerConnectionSocket(socketDescriptor, mCertNickname, mCertPassword, mDbLocation ); if (newSocket) { } } } return(newSocket); }
static PRStatus DoSecurityCheck(PRFileDesc *fd, const char *path) { #ifndef IPC_SKIP_SECURITY_CHECKS // // now that we have a connected socket; do some security checks on the // file descriptor. // // (1) make sure owner matches // (2) make sure permissions match expected permissions // // if these conditions aren't met then bail. // int unix_fd = PR_FileDesc2NativeHandle(fd); struct stat st; if (fstat(unix_fd, &st) == -1) { LOG(("stat failed")); return PR_FAILURE; } if (st.st_uid != getuid() && st.st_uid != geteuid()) { // // on OSX 10.1.5, |fstat| has a bug when passed a file descriptor to // a socket. it incorrectly returns a UID of 0. however, |stat| // succeeds, but using |stat| introduces a race condition. // // XXX come up with a better security check. // if (st.st_uid != 0) { LOG(("userid check failed")); return PR_FAILURE; } if (stat(path, &st) == -1) { LOG(("stat failed")); return PR_FAILURE; } if (st.st_uid != getuid() && st.st_uid != geteuid()) { LOG(("userid check failed")); return PR_FAILURE; } } #endif return PR_SUCCESS; }
NSAPI_PUBLIC int net_is_STDIN(SYS_NETFD prfd) { if (PR_FileDesc2NativeHandle(prfd) == STDIN_FILENO) return 1; return 0; }
PollableEvent::PollableEvent() : mWriteFD(nullptr) , mReadFD(nullptr) , mSignaled(false) { MOZ_COUNT_CTOR(PollableEvent); MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread); // create pair of prfiledesc that can be used as a poll()ble // signal. on windows use a localhost socket pair, and on // unix use a pipe. #ifdef USEPIPE SOCKET_LOG(("PollableEvent() using pipe\n")); if (PR_CreatePipe(&mReadFD, &mWriteFD) == PR_SUCCESS) { // make the pipe non blocking. NSPR asserts at // trying to use SockOpt here PROsfd fd = PR_FileDesc2NativeHandle(mReadFD); int flags = fcntl(fd, F_GETFL, 0); (void)fcntl(fd, F_SETFL, flags | O_NONBLOCK); fd = PR_FileDesc2NativeHandle(mWriteFD); flags = fcntl(fd, F_GETFL, 0); (void)fcntl(fd, F_SETFL, flags | O_NONBLOCK); } else { mReadFD = nullptr; mWriteFD = nullptr; SOCKET_LOG(("PollableEvent() pipe failed\n")); } #else SOCKET_LOG(("PollableEvent() using socket pair\n")); PRFileDesc *fd[2]; LazyInitSocket(); // Try with a increased recv buffer first (bug 1248358). if (NewTCPSocketPair(fd, true)) { mReadFD = fd[0]; mWriteFD = fd[1]; // If the previous fails try without recv buffer increase (bug 1305436). } else if (NewTCPSocketPair(fd, false)) { mReadFD = fd[0]; mWriteFD = fd[1]; // If both fail, try the old version. } else if (PR_NewTCPSocketPair(fd) == PR_SUCCESS) { mReadFD = fd[0]; mWriteFD = fd[1]; PRSocketOptionData socket_opt; DebugOnly<PRStatus> status; socket_opt.option = PR_SockOpt_NoDelay; socket_opt.value.no_delay = true; PR_SetSocketOption(mWriteFD, &socket_opt); PR_SetSocketOption(mReadFD, &socket_opt); socket_opt.option = PR_SockOpt_Nonblocking; socket_opt.value.non_blocking = true; status = PR_SetSocketOption(mWriteFD, &socket_opt); MOZ_ASSERT(status == PR_SUCCESS); status = PR_SetSocketOption(mReadFD, &socket_opt); MOZ_ASSERT(status == PR_SUCCESS); } if (mReadFD && mWriteFD) { // compatibility with LSPs such as McAfee that assume a NSPR // layer for read ala the nspr Pollable Event - Bug 698882. This layer is a nop. PRFileDesc *topLayer = PR_CreateIOLayerStub(sPollableEventLayerIdentity, sPollableEventLayerMethodsPtr); if (topLayer) { if (PR_PushIOLayer(fd[0], PR_TOP_IO_LAYER, topLayer) == PR_FAILURE) { topLayer->dtor(topLayer); } else { SOCKET_LOG(("PollableEvent() nspr layer ok\n")); mReadFD = topLayer; } } } else { SOCKET_LOG(("PollableEvent() socketpair failed\n")); } #endif if (mReadFD && mWriteFD) { // prime the system to deal with races invovled in [dc]tor cycle SOCKET_LOG(("PollableEvent() ctor ok\n")); mSignaled = true; PR_Write(mWriteFD, "I", 1); } }
int main(int argc, char **argv) { PRFileDesc *listenSock1, *listenSock2; PRFileDesc *badFD; PRUint16 listenPort1, listenPort2; PRNetAddr addr; PR_fd_set readFdSet; char buf[128]; PRInt32 retVal; /* The command line argument: -d is used to determine if the test is being run in debug mode. The regress tool requires only one line output:PASS or FAIL. All of the printfs associated with this test has been handled with a if (debug_mode) test. Usage: test_name -d */ PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "d:"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'd': /* debug mode */ debug_mode = 1; break; default: break; } } PL_DestroyOptState(opt); /* main test */ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); PR_STDIO_INIT(); if (debug_mode) { printf("This program tests PR_Select with sockets. Error\n"); printf("reporting operations are tested.\n\n"); } /* Create two listening sockets */ if ((listenSock1 = PR_NewTCPSocket()) == NULL) { fprintf(stderr, "Can't create a new TCP socket\n"); failed_already=1; goto exit_now; } addr.inet.family = AF_INET; addr.inet.ip = PR_htonl(INADDR_ANY); addr.inet.port = PR_htons(0); if (PR_Bind(listenSock1, &addr) == PR_FAILURE) { fprintf(stderr, "Can't bind socket\n"); failed_already=1; goto exit_now; } if (PR_GetSockName(listenSock1, &addr) == PR_FAILURE) { fprintf(stderr, "PR_GetSockName failed\n"); failed_already=1; goto exit_now; } listenPort1 = PR_ntohs(addr.inet.port); if (PR_Listen(listenSock1, 5) == PR_FAILURE) { fprintf(stderr, "Can't listen on a socket\n"); failed_already=1; goto exit_now; } if ((listenSock2 = PR_NewTCPSocket()) == NULL) { fprintf(stderr, "Can't create a new TCP socket\n"); failed_already=1; goto exit_now; } addr.inet.family = AF_INET; addr.inet.ip = PR_htonl(INADDR_ANY); addr.inet.port = PR_htons(0); if (PR_Bind(listenSock2, &addr) == PR_FAILURE) { fprintf(stderr, "Can't bind socket\n"); failed_already=1; goto exit_now; } if (PR_GetSockName(listenSock2, &addr) == PR_FAILURE) { fprintf(stderr, "PR_GetSockName failed\n"); failed_already=1; goto exit_now; } listenPort2 = PR_ntohs(addr.inet.port); if (PR_Listen(listenSock2, 5) == PR_FAILURE) { fprintf(stderr, "Can't listen on a socket\n"); failed_already=1; goto exit_now; } PR_snprintf(buf, sizeof(buf), "The server thread is listening on ports %hu and %hu\n\n", listenPort1, listenPort2); if (debug_mode) printf("%s", buf); /* Set up the fd set */ PR_FD_ZERO(&readFdSet); PR_FD_SET(listenSock1, &readFdSet); PR_FD_SET(listenSock2, &readFdSet); /* Testing bad fd */ if (debug_mode) printf("PR_Select should detect a bad file descriptor\n"); if ((badFD = PR_NewTCPSocket()) == NULL) { fprintf(stderr, "Can't create a TCP socket\n"); failed_already=1; goto exit_now; } PR_FD_SET(badFD, &readFdSet); /* * Make the fd invalid */ #if defined(XP_UNIX) close(PR_FileDesc2NativeHandle(badFD)); #elif defined(XP_OS2) soclose(PR_FileDesc2NativeHandle(badFD)); #elif defined(WIN32) || defined(WIN16) closesocket(PR_FileDesc2NativeHandle(badFD)); #else #error "Unknown architecture" #endif retVal = PR_Select(0 /* unused */, &readFdSet, NULL, NULL, PR_INTERVAL_NO_TIMEOUT); if (retVal != -1 || PR_GetError() != PR_BAD_DESCRIPTOR_ERROR) { fprintf(stderr, "Failed to detect the bad fd: " "PR_Select returns %d\n", retVal); if (retVal == -1) { fprintf(stderr, "Error %d, oserror %d\n", PR_GetError(), PR_GetOSError()); failed_already=1; } goto exit_now; } if (debug_mode) printf("PR_Select detected a bad fd. Test passed.\n\n"); PR_FD_CLR(badFD, &readFdSet); PR_Cleanup(); goto exit_now; exit_now: if(failed_already) return 1; else return 0; }
int main(int argc, char **argv) { PRFileDesc *listenSock1, *listenSock2; PRFileDesc *badFD; PRUint16 listenPort1, listenPort2; PRNetAddr addr; char buf[BUF_SIZE]; PRThread *clientThread; PRPollDesc pds0[10], pds1[10], *pds, *other_pds; PRIntn npds; PRInt32 retVal; PRInt32 rv; PROsfd sd; struct sockaddr_in saddr; PRIntn saddr_len; PRUint16 listenPort3; PRFileDesc *socket_poll_fd; PRIntn i, j; PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); PR_STDIO_INIT(); printf("This program tests PR_Poll with sockets.\n"); printf("Timeout, error reporting, and normal operation are tested.\n\n"); /* Create two listening sockets */ if ((listenSock1 = PR_NewTCPSocket()) == NULL) { fprintf(stderr, "Can't create a new TCP socket\n"); exit(1); } addr.inet.family = PR_AF_INET; addr.inet.ip = PR_htonl(PR_INADDR_ANY); addr.inet.port = PR_htons(0); if (PR_Bind(listenSock1, &addr) == PR_FAILURE) { fprintf(stderr, "Can't bind socket\n"); exit(1); } if (PR_GetSockName(listenSock1, &addr) == PR_FAILURE) { fprintf(stderr, "PR_GetSockName failed\n"); exit(1); } listenPort1 = PR_ntohs(addr.inet.port); if (PR_Listen(listenSock1, 5) == PR_FAILURE) { fprintf(stderr, "Can't listen on a socket\n"); exit(1); } if ((listenSock2 = PR_NewTCPSocket()) == NULL) { fprintf(stderr, "Can't create a new TCP socket\n"); exit(1); } addr.inet.family = PR_AF_INET; addr.inet.ip = PR_htonl(PR_INADDR_ANY); addr.inet.port = PR_htons(0); if (PR_Bind(listenSock2, &addr) == PR_FAILURE) { fprintf(stderr, "Can't bind socket\n"); exit(1); } if (PR_GetSockName(listenSock2, &addr) == PR_FAILURE) { fprintf(stderr, "PR_GetSockName failed\n"); exit(1); } listenPort2 = PR_ntohs(addr.inet.port); if (PR_Listen(listenSock2, 5) == PR_FAILURE) { fprintf(stderr, "Can't listen on a socket\n"); exit(1); } /* Set up the poll descriptor array */ pds = pds0; other_pds = pds1; memset(pds, 0, sizeof(pds)); npds = 0; pds[npds].fd = listenSock1; pds[npds].in_flags = PR_POLL_READ; npds++; pds[npds].fd = listenSock2; pds[npds].in_flags = PR_POLL_READ; npds++; sd = socket(AF_INET, SOCK_STREAM, 0); PR_ASSERT(sd >= 0); memset((char *) &saddr, 0, sizeof(saddr)); saddr.sin_family = AF_INET; saddr.sin_addr.s_addr = htonl(INADDR_ANY); saddr.sin_port = htons(0); rv = bind(sd, (struct sockaddr *)&saddr, sizeof(saddr)); PR_ASSERT(rv == 0); saddr_len = sizeof(saddr); rv = getsockname(sd, (struct sockaddr *) &saddr, &saddr_len); PR_ASSERT(rv == 0); listenPort3 = ntohs(saddr.sin_port); rv = listen(sd, 5); PR_ASSERT(rv == 0); pds[npds].fd = socket_poll_fd = PR_CreateSocketPollFd(sd); PR_ASSERT(pds[npds].fd); pds[npds].in_flags = PR_POLL_READ; npds++; PR_snprintf(buf, sizeof(buf), "The server thread is listening on ports %hu, %hu and %hu\n\n", listenPort1, listenPort2, listenPort3); printf("%s", buf); /* Testing timeout */ printf("PR_Poll should time out in 5 seconds\n"); retVal = PR_Poll(pds, npds, PR_SecondsToInterval(5)); if (retVal != 0) { PR_snprintf(buf, sizeof(buf), "PR_Poll should time out and return 0, but it returns %ld\n", retVal); fprintf(stderr, "%s", buf); exit(1); } printf("PR_Poll timed out. Test passed.\n\n"); /* Testing bad fd */ printf("PR_Poll should detect a bad file descriptor\n"); if ((badFD = PR_NewTCPSocket()) == NULL) { fprintf(stderr, "Can't create a TCP socket\n"); exit(1); } pds[npds].fd = badFD; pds[npds].in_flags = PR_POLL_READ; npds++; PR_Close(badFD); /* make the fd bad */ #if 0 retVal = PR_Poll(pds, npds, PR_INTERVAL_NO_TIMEOUT); if (retVal != 1 || (unsigned short) pds[2].out_flags != PR_POLL_NVAL) { fprintf(stderr, "Failed to detect the bad fd: " "PR_Poll returns %d, out_flags is 0x%hx\n", retVal, pds[npds - 1].out_flags); exit(1); } printf("PR_Poll detected the bad fd. Test passed.\n\n"); #endif npds--; clientThread = PR_CreateThread(PR_USER_THREAD, clientThreadFunc, (void *) listenPort1, PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_UNJOINABLE_THREAD, 0); if (clientThread == NULL) { fprintf(stderr, "can't create thread\n"); exit(1); } clientThread = PR_CreateThread(PR_USER_THREAD, clientThreadFunc, (void *) listenPort2, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_UNJOINABLE_THREAD, 0); if (clientThread == NULL) { fprintf(stderr, "can't create thread\n"); exit(1); } clientThread = PR_CreateThread(PR_USER_THREAD, clientThreadFunc, (void *) listenPort3, PR_PRIORITY_NORMAL, PR_GLOBAL_BOUND_THREAD, PR_UNJOINABLE_THREAD, 0); if (clientThread == NULL) { fprintf(stderr, "can't create thread\n"); exit(1); } printf("Three client threads are created. Each of them will\n"); printf("send data to one of the three ports the server is listening on.\n"); printf("The data they send is the port number. Each of them send\n"); printf("the data five times, so you should see ten lines below,\n"); printf("interleaved in an arbitrary order.\n"); /* 30 events total */ i = 0; while (i < 30) { PRPollDesc *tmp; int nextIndex; int nEvents = 0; retVal = PR_Poll(pds, npds, PR_INTERVAL_NO_TIMEOUT); PR_ASSERT(retVal != 0); /* no timeout */ if (retVal == -1) { fprintf(stderr, "PR_Poll failed\n"); exit(1); } nextIndex = 3; /* the three listening sockets */ for (j = 0; j < 3; j++) { other_pds[j] = pds[j]; PR_ASSERT((pds[j].out_flags & PR_POLL_WRITE) == 0 && (pds[j].out_flags & PR_POLL_EXCEPT) == 0); if (pds[j].out_flags & PR_POLL_READ) { PRFileDesc *sock; nEvents++; if (j == 2) { PROsfd newsd; newsd = accept(PR_FileDesc2NativeHandle(pds[j].fd), NULL, 0); if (newsd == -1) { fprintf(stderr, "accept() failed\n"); exit(1); } other_pds[nextIndex].fd = PR_CreateSocketPollFd(newsd); PR_ASSERT(other_pds[nextIndex].fd); other_pds[nextIndex].in_flags = PR_POLL_READ; } else { sock = PR_Accept(pds[j].fd, NULL, PR_INTERVAL_NO_TIMEOUT); if (sock == NULL) { fprintf(stderr, "PR_Accept() failed\n"); exit(1); } other_pds[nextIndex].fd = sock; other_pds[nextIndex].in_flags = PR_POLL_READ; } nextIndex++; } else if (pds[j].out_flags & PR_POLL_ERR) { fprintf(stderr, "PR_Poll() indicates that an fd has error\n"); exit(1); } else if (pds[j].out_flags & PR_POLL_NVAL) { fprintf(stderr, "PR_Poll() indicates that fd %d is invalid\n", PR_FileDesc2NativeHandle(pds[j].fd)); exit(1); } } for (j = 3; j < npds; j++) { PR_ASSERT((pds[j].out_flags & PR_POLL_WRITE) == 0 && (pds[j].out_flags & PR_POLL_EXCEPT) == 0); if (pds[j].out_flags & PR_POLL_READ) { PRInt32 nBytes; nEvents++; /* XXX: This call is a hack and should be fixed */ if (PR_GetDescType(pds[j].fd) == (PRDescType) 0) { nBytes = recv(PR_FileDesc2NativeHandle(pds[j].fd), buf, sizeof(buf), 0); if (nBytes == -1) { fprintf(stderr, "recv() failed\n"); exit(1); } printf("Server read %d bytes from native fd %d\n",nBytes, PR_FileDesc2NativeHandle(pds[j].fd)); #ifdef WIN32 closesocket((SOCKET)PR_FileDesc2NativeHandle(pds[j].fd)); #else close(PR_FileDesc2NativeHandle(pds[j].fd)); #endif PR_DestroySocketPollFd(pds[j].fd); } else { nBytes = PR_Read(pds[j].fd, buf, sizeof(buf)); if (nBytes == -1) { fprintf(stderr, "PR_Read() failed\n"); exit(1); } PR_Close(pds[j].fd); } /* Just to be safe */ buf[BUF_SIZE - 1] = '\0'; printf("The server received \"%s\" from a client\n", buf); } else if (pds[j].out_flags & PR_POLL_ERR) { fprintf(stderr, "PR_Poll() indicates that an fd has error\n"); exit(1); } else if (pds[j].out_flags & PR_POLL_NVAL) { fprintf(stderr, "PR_Poll() indicates that an fd is invalid\n"); exit(1); } else { other_pds[nextIndex] = pds[j]; nextIndex++; } } PR_ASSERT(retVal == nEvents); /* swap */ tmp = pds; pds = other_pds; other_pds = tmp; npds = nextIndex; i += nEvents; } PR_DestroySocketPollFd(socket_poll_fd); printf("All tests finished\n"); PR_Cleanup(); return 0; }
static void NativeSelectTest(void) { PRFileDesc *listenSocket; PRNetAddr serverAddr; if ( (listenSocket = PR_NewTCPSocket()) == NULL) { if (debug_mode) printf("\tServer error creating listen socket\n"); return; } memset(&serverAddr, 0, sizeof(PRNetAddr)); serverAddr.inet.family = AF_INET; serverAddr.inet.port = PR_htons(PORT); serverAddr.inet.ip = PR_htonl(INADDR_ANY); if ( PR_Bind(listenSocket, &serverAddr) == PR_FAILURE) { if (debug_mode) printf("\tServer error binding to server address\n"); PR_Close(listenSocket); return; } if ( PR_Listen(listenSocket, 128) == PR_FAILURE) { if (debug_mode) printf("\tServer error listening to server socket\n"); PR_Close(listenSocket); return; } if (debug_mode) printf("Listening on port %d\n", PORT); { PRIntn osfd; char buf[11]; fd_set rdset; PRNetAddr rAddr; PRFileDesc *newSock; struct timeval timeout; PRInt32 bytesRead, rv, loops = 0; loops++; if (debug_mode) printf("Going into accept\n"); newSock = PR_Accept(listenSocket, &rAddr, PR_INTERVAL_NO_TIMEOUT); if (newSock) { if (debug_mode) printf("Got connection!\n"); } else { if (debug_mode) printf("PR_Accept failed: error code %d\n", PR_GetError()); else Test_Result (FAIL); } osfd = PR_FileDesc2NativeHandle(newSock); FD_ZERO(&rdset); FD_SET(osfd, &rdset); if (debug_mode) printf("Going into select \n"); timeout.tv_sec = 2; timeout.tv_usec = 0; rv = select(osfd + 1, &rdset, NULL, NULL, &timeout); if (debug_mode) printf("return from select is %d\n", rv); if (FD_ISSET(osfd, &rdset)) { if (debug_mode) printf("I can't believe it- the socket is ready okay!\n"); } else { if (debug_mode) printf("Damn; the select test failed...\n"); else Test_Result (FAIL); } strcpy(buf, "XXXXXXXXXX"); bytesRead = PR_Recv(newSock, buf, 10, 0, PR_INTERVAL_NO_TIMEOUT); buf[10] = '\0'; if (debug_mode) printf("Recv completed with %d bytes, %s\n", bytesRead, buf); PR_Close(newSock); } } /* NativeSelectTest */
NSAPI_PUBLIC int INTnet_native_handle(SYS_NETFD s) { return (int)PR_FileDesc2NativeHandle(s); }
NSAPI_PUBLIC HANDLE INTnet_native_handle(SYS_NETFD s) { return (HANDLE)PR_FileDesc2NativeHandle(s); }
NSAPI_PUBLIC int net_isalive(SYS_NETFD sd) { // JRP fix 355991 - deprecate this function in NES 4.0 /* * Reintroduced for Proxy 4.0. * * We can't reliably detect whether a peer has disconnected, but we can * detect one situation that occurs commonly in Proxy: if sn->csd polls * ready for reading but there's no data available to be read, the user * probably got tired of waiting for a slow origin server. * * There are numerous caveats. Here are a few: * * 1. if the client did a shutdown(s, SHUT_WR), we'll mistakenly assume * that it disconnected * 2. if the client sent a pipelined request before it disconnected, we'll * never notice it's gone * 3. if the client's network connection died, TCP can take a long time (up * to and including forever) to notice * * Note that the underlying fd may be O_NONBLOCK or ~O_NONBLOCK, but we * must always avoid blocking. */ int fd = PR_FileDesc2NativeHandle(sd); if (fd != -1) { int rv; do { #if defined(POLLIN) && defined(POLLHUP) struct pollfd pfd; pfd.fd = fd; pfd.events = POLLIN | POLLHUP; pfd.revents = 0; rv = poll(&pfd, 1, 0); #else fd_set fds; FD_ZERO(&fds); FD_SET(fd, &fds); struct timeval timeout; timeout.tv_sec = 0; timeout.tv_usec = 0; rv = select(fd + 1, &fds, NULL, NULL, &timeout); #endif } while (rv == -1 && errno == EINTR); if (rv == -1) return 0; if (rv == 1) { do { char c; rv = recv(fd, &c, 1, MSG_PEEK); } while (rv == -1 && errno == EINTR); if (rv == -1 && #if defined(EWOULDBLOCK) && (EWOULDBLOCK != EAGAIN) errno != EWOULDBLOCK && #endif errno != EAGAIN) { return 0; } if (rv == 0) return 0; } } return 1; }
bool mozilla::fallocate(PRFileDesc *aFD, int64_t aLength) { #if defined(HAVE_POSIX_FALLOCATE) return posix_fallocate(PR_FileDesc2NativeHandle(aFD), 0, aLength) == 0; #elif defined(XP_WIN) int64_t oldpos = PR_Seek64(aFD, 0, PR_SEEK_CUR); if (oldpos == -1) return false; if (PR_Seek64(aFD, aLength, PR_SEEK_SET) != aLength) return false; bool retval = (0 != SetEndOfFile((HANDLE)PR_FileDesc2NativeHandle(aFD))); PR_Seek64(aFD, oldpos, PR_SEEK_SET); return retval; #elif defined(XP_OS2) return aLength <= UINT32_MAX && 0 == DosSetFileSize(PR_FileDesc2NativeHandle(aFD), (uint32_t)aLength); #elif defined(XP_MACOSX) int fd = PR_FileDesc2NativeHandle(aFD); fstore_t store = {F_ALLOCATECONTIG, F_PEOFPOSMODE, 0, aLength}; // Try to get a continous chunk of disk space int ret = fcntl(fd, F_PREALLOCATE, &store); if (-1 == ret) { // OK, perhaps we are too fragmented, allocate non-continuous store.fst_flags = F_ALLOCATEALL; ret = fcntl(fd, F_PREALLOCATE, &store); if (-1 == ret) return false; } return 0 == ftruncate(fd, aLength); #elif defined(XP_UNIX) // The following is copied from fcntlSizeHint in sqlite /* If the OS does not have posix_fallocate(), fake it. First use ** ftruncate() to set the file size, then write a single byte to ** the last byte in each block within the extended region. This ** is the same technique used by glibc to implement posix_fallocate() ** on systems that do not have a real fallocate() system call. */ int64_t oldpos = PR_Seek64(aFD, 0, PR_SEEK_CUR); if (oldpos == -1) return false; struct stat buf; int fd = PR_FileDesc2NativeHandle(aFD); if (fstat(fd, &buf)) return false; if (buf.st_size >= aLength) return false; const int nBlk = buf.st_blksize; if (!nBlk) return false; if (ftruncate(fd, aLength)) return false; int nWrite; // Return value from write() int64_t iWrite = ((buf.st_size + 2 * nBlk - 1) / nBlk) * nBlk - 1; // Next offset to write to while (iWrite < aLength) { nWrite = 0; if (PR_Seek64(aFD, iWrite, PR_SEEK_SET) == iWrite) nWrite = PR_Write(aFD, "", 1); if (nWrite != 1) break; iWrite += nBlk; } PR_Seek64(aFD, oldpos, PR_SEEK_SET); return nWrite == 1; #endif return false; }
int main(int argc, char **argv) { PRFileDesc *listenSock1 = NULL, *listenSock2 = NULL; PRUint16 listenPort1, listenPort2; PRNetAddr addr; char buf[128]; PRThread *clientThread; PRPollDesc pds0[20], pds1[20], *pds, *other_pds; PRIntn npds; PRInt32 retVal; PRIntn i, j; PRSocketOptionData optval; /* The command line argument: -d is used to determine if the test is being run in debug mode. The regress tool requires only one line output:PASS or FAIL. All of the printfs associated with this test has been handled with a if (debug_mode) test. Usage: test_name -d */ PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "d:"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'd': /* debug mode */ debug_mode = 1; break; default: break; } } PL_DestroyOptState(opt); /* main test */ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); PR_STDIO_INIT(); if (debug_mode) { printf("This program tests PR_Poll with sockets.\n"); printf("Normal operation are tested.\n\n"); } /* Create two listening sockets */ if ((listenSock1 = PR_NewTCPSocket()) == NULL) { fprintf(stderr, "Can't create a new TCP socket\n"); failed_already=1; goto exit_now; } memset(&addr, 0, sizeof(addr)); addr.inet.family = PR_AF_INET; addr.inet.ip = PR_htonl(PR_INADDR_ANY); addr.inet.port = PR_htons(0); if (PR_Bind(listenSock1, &addr) == PR_FAILURE) { fprintf(stderr, "Can't bind socket\n"); failed_already=1; goto exit_now; } if (PR_GetSockName(listenSock1, &addr) == PR_FAILURE) { fprintf(stderr, "PR_GetSockName failed\n"); failed_already=1; goto exit_now; } listenPort1 = PR_ntohs(addr.inet.port); optval.option = PR_SockOpt_Nonblocking; optval.value.non_blocking = PR_TRUE; PR_SetSocketOption(listenSock1, &optval); if (PR_Listen(listenSock1, 5) == PR_FAILURE) { fprintf(stderr, "Can't listen on a socket\n"); failed_already=1; goto exit_now; } if ((listenSock2 = PR_NewTCPSocket()) == NULL) { fprintf(stderr, "Can't create a new TCP socket\n"); failed_already=1; goto exit_now; } addr.inet.family = PR_AF_INET; addr.inet.ip = PR_htonl(PR_INADDR_ANY); addr.inet.port = PR_htons(0); if (PR_Bind(listenSock2, &addr) == PR_FAILURE) { fprintf(stderr, "Can't bind socket\n"); failed_already=1; goto exit_now; } if (PR_GetSockName(listenSock2, &addr) == PR_FAILURE) { fprintf(stderr, "PR_GetSockName failed\n"); failed_already=1; goto exit_now; } listenPort2 = PR_ntohs(addr.inet.port); PR_SetSocketOption(listenSock2, &optval); if (PR_Listen(listenSock2, 5) == PR_FAILURE) { fprintf(stderr, "Can't listen on a socket\n"); failed_already=1; goto exit_now; } PR_snprintf(buf, sizeof(buf), "The server thread is listening on ports %hu and %hu\n\n", listenPort1, listenPort2); if (debug_mode) printf("%s", buf); /* Set up the poll descriptor array */ pds = pds0; other_pds = pds1; memset(pds, 0, sizeof(pds)); pds[0].fd = listenSock1; pds[0].in_flags = PR_POLL_READ; pds[1].fd = listenSock2; pds[1].in_flags = PR_POLL_READ; /* Add some unused entries to test if they are ignored by PR_Poll() */ memset(&pds[2], 0, sizeof(pds[2])); memset(&pds[3], 0, sizeof(pds[3])); memset(&pds[4], 0, sizeof(pds[4])); npds = 5; clientThread = PR_CreateThread(PR_USER_THREAD, clientThreadFunc, (void *) listenPort1, PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_UNJOINABLE_THREAD, 0); if (clientThread == NULL) { fprintf(stderr, "can't create thread\n"); failed_already=1; goto exit_now; } clientThread = PR_CreateThread(PR_USER_THREAD, clientThreadFunc, (void *) listenPort2, PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_UNJOINABLE_THREAD, 0); if (clientThread == NULL) { fprintf(stderr, "can't create thread\n"); failed_already=1; goto exit_now; } if (debug_mode) { printf("Two client threads are created. Each of them will\n"); printf("send data to one of the two ports the server is listening on.\n"); printf("The data they send is the port number. Each of them send\n"); printf("the data five times, so you should see ten lines below,\n"); printf("interleaved in an arbitrary order.\n"); } /* two clients, three events per iteration: accept, read, close */ i = 0; while (i < 2 * 3 * NUM_ITERATIONS) { PRPollDesc *tmp; int nextIndex; int nEvents = 0; retVal = PR_Poll(pds, npds, PR_INTERVAL_NO_TIMEOUT); PR_ASSERT(retVal != 0); /* no timeout */ if (retVal == -1) { fprintf(stderr, "PR_Poll failed\n"); failed_already=1; goto exit_now; } nextIndex = 2; /* the two listening sockets */ for (j = 0; j < 2; j++) { other_pds[j] = pds[j]; PR_ASSERT((pds[j].out_flags & PR_POLL_WRITE) == 0 && (pds[j].out_flags & PR_POLL_EXCEPT) == 0); if (pds[j].out_flags & PR_POLL_READ) { PRFileDesc *sock; nEvents++; sock = PR_Accept(pds[j].fd, NULL, PR_INTERVAL_NO_TIMEOUT); if (sock == NULL) { fprintf(stderr, "PR_Accept() failed\n"); failed_already=1; goto exit_now; } other_pds[nextIndex].fd = sock; other_pds[nextIndex].in_flags = PR_POLL_READ; nextIndex++; } else if (pds[j].out_flags & PR_POLL_ERR) { fprintf(stderr, "PR_Poll() indicates that an fd has error\n"); failed_already=1; goto exit_now; } else if (pds[j].out_flags & PR_POLL_NVAL) { fprintf(stderr, "PR_Poll() indicates that fd %d is invalid\n", PR_FileDesc2NativeHandle(pds[j].fd)); failed_already=1; goto exit_now; } } for (j = 2; j < npds; j++) { if (NULL == pds[j].fd) { /* * Keep the unused entries in the poll descriptor array * for testing purposes. */ other_pds[nextIndex] = pds[j]; nextIndex++; continue; } PR_ASSERT((pds[j].out_flags & PR_POLL_WRITE) == 0 && (pds[j].out_flags & PR_POLL_EXCEPT) == 0); if (pds[j].out_flags & PR_POLL_READ) { PRInt32 nAvail; PRInt32 nRead; nEvents++; nAvail = PR_Available(pds[j].fd); nRead = PR_Read(pds[j].fd, buf, sizeof(buf)); PR_ASSERT(nAvail == nRead); if (nRead == -1) { fprintf(stderr, "PR_Read() failed\n"); failed_already=1; goto exit_now; } else if (nRead == 0) { PR_Close(pds[j].fd); continue; } else { /* Just to be safe */ buf[127] = '\0'; if (debug_mode) printf("The server received \"%s\" from a client\n", buf); } } else if (pds[j].out_flags & PR_POLL_ERR) { fprintf(stderr, "PR_Poll() indicates that an fd has error\n"); failed_already=1; goto exit_now; } else if (pds[j].out_flags & PR_POLL_NVAL) { fprintf(stderr, "PR_Poll() indicates that an fd is invalid\n"); failed_already=1; goto exit_now; } other_pds[nextIndex] = pds[j]; nextIndex++; } PR_ASSERT(retVal == nEvents); /* swap */ tmp = pds; pds = other_pds; other_pds = tmp; npds = nextIndex; i += nEvents; } if (debug_mode) printf("Tests passed\n"); exit_now: if (listenSock1) { PR_Close(listenSock1); } if (listenSock2) { PR_Close(listenSock2); } PR_Cleanup(); if(failed_already) return 1; else return 0; }