void ClosingService::SendPRCloseTelemetry(PRIntervalTime aStart, mozilla::Telemetry::ID aIDNormal, mozilla::Telemetry::ID aIDShutdown, mozilla::Telemetry::ID aIDConnectivityChange, mozilla::Telemetry::ID aIDLinkChange, mozilla::Telemetry::ID aIDOffline) { PRIntervalTime now = PR_IntervalNow(); if (gIOService->IsShutdown()) { Telemetry::Accumulate(aIDShutdown, PR_IntervalToMilliseconds(now - aStart)); } else if (PR_IntervalToSeconds(now - gIOService->LastConnectivityChange()) < 60) { Telemetry::Accumulate(aIDConnectivityChange, PR_IntervalToMilliseconds(now - aStart)); } else if (PR_IntervalToSeconds(now - gIOService->LastNetworkLinkChange()) < 60) { Telemetry::Accumulate(aIDLinkChange, PR_IntervalToMilliseconds(now - aStart)); } else if (PR_IntervalToSeconds(now - gIOService->LastOfflineStateChange()) < 60) { Telemetry::Accumulate(aIDOffline, PR_IntervalToMilliseconds(now - aStart)); } else { Telemetry::Accumulate(aIDNormal, PR_IntervalToMilliseconds(now - aStart)); } }
SECStatus ImportCRL (CERTCertDBHandle *certHandle, char *url, int type, PRFileDesc *inFile, PRInt32 importOptions, PRInt32 decodeOptions) { CERTSignedCrl *crl = NULL; SECItem crlDER; PK11SlotInfo* slot = NULL; int rv; #if defined(DEBUG_jp96085) PRIntervalTime starttime, endtime, elapsed; PRUint32 mins, secs, msecs; #endif crlDER.data = NULL; /* Read in the entire file specified with the -f argument */ rv = SECU_ReadDERFromFile(&crlDER, inFile, PR_FALSE); if (rv != SECSuccess) { SECU_PrintError(progName, "unable to read input file"); return (SECFailure); } decodeOptions |= CRL_DECODE_DONT_COPY_DER; slot = PK11_GetInternalKeySlot(); #if defined(DEBUG_jp96085) starttime = PR_IntervalNow(); #endif crl = PK11_ImportCRL(slot, &crlDER, url, type, NULL, importOptions, NULL, decodeOptions); #if defined(DEBUG_jp96085) endtime = PR_IntervalNow(); elapsed = endtime - starttime; mins = PR_IntervalToSeconds(elapsed) / 60; secs = PR_IntervalToSeconds(elapsed) % 60; msecs = PR_IntervalToMilliseconds(elapsed) % 1000; printf("Elapsed : %2d:%2d.%3d\n", mins, secs, msecs); #endif if (!crl) { const char *errString; rv = SECFailure; errString = SECU_Strerror(PORT_GetError()); if ( errString && PORT_Strlen (errString) == 0) SECU_PrintError (progName, "CRL is not imported (error: input CRL is not up to date.)"); else SECU_PrintError (progName, "unable to import CRL"); } else { SEC_DestroyCrl (crl); } if (slot) { PK11_FreeSlot(slot); } return (rv); }
JNIEXPORT jint JNICALL Java_org_mozilla_jss_ssl_SSLSocket_getSoLinger(JNIEnv *env, jobject self) { PRSocketOptionData sockOptions; JSSL_SocketData *sock = NULL; jint retval; PRStatus status; if( JSSL_getSockData(env, self, &sock) != PR_SUCCESS ) { goto finish; } sockOptions.option = PR_SockOpt_Linger; status = PR_GetSocketOption(sock->fd, &sockOptions); if( status != PR_SUCCESS ) { JSSL_throwSSLSocketException(env, "PR_GetSocketOption failed"); goto finish; } if( sockOptions.value.linger.polarity == PR_TRUE ) { retval = PR_IntervalToSeconds(sockOptions.value.linger.linger); } else { retval = -1; } finish: EXCEPTION_CHECK(env, sock) return retval; }
void ThreadMain(void*) { MonitorAutoLock lock(*gMonitor); // In order to avoid issues with the hang monitor incorrectly triggering // during a general system stop such as sleeping, the monitor thread must // run twice to trigger hang protection. PRIntervalTime lastTimestamp = 0; int waitCount = 0; while (true) { if (gShutdown) { return; // Exit the thread } // avoid rereading the volatile value in this loop PRIntervalTime timestamp = gTimestamp; PRIntervalTime now = PR_IntervalNow(); if (timestamp != PR_INTERVAL_NO_WAIT && now < timestamp) { // 32-bit overflow, reset for another waiting period timestamp = 1; // lowest legal PRInterval value } if (timestamp != PR_INTERVAL_NO_WAIT && timestamp == lastTimestamp && gTimeout > 0) { ++waitCount; if (waitCount == 2) { PRInt32 delay = PRInt32(PR_IntervalToSeconds(now - timestamp)); if (delay > gTimeout) { MonitorAutoUnlock unlock(*gMonitor); Crash(); } } } else { lastTimestamp = timestamp; waitCount = 0; } PRIntervalTime timeout; if (gTimeout <= 0) { timeout = PR_INTERVAL_NO_TIMEOUT; } else { timeout = PR_MillisecondsToInterval(gTimeout * 500); } lock.Wait(timeout); } }
int32_t nsSocketTransportService::Poll(uint32_t *interval, TimeDuration *pollDuration) { PRPollDesc *pollList; uint32_t pollCount; PRIntervalTime pollTimeout; *pollDuration = 0; // If there are pending events for this thread then // DoPollIteration() should service the network without blocking. bool pendingEvents = false; mRawThread->HasPendingEvents(&pendingEvents); if (mPollList[0].fd) { mPollList[0].out_flags = 0; pollList = mPollList; pollCount = mActiveCount + 1; pollTimeout = pendingEvents ? PR_INTERVAL_NO_WAIT : PollTimeout(); } else { // no pollable event, so busy wait... pollCount = mActiveCount; if (pollCount) pollList = &mPollList[1]; else pollList = nullptr; pollTimeout = pendingEvents ? PR_INTERVAL_NO_WAIT : PR_MillisecondsToInterval(25); } PRIntervalTime ts = PR_IntervalNow(); TimeStamp pollStart; if (mTelemetryEnabledPref) { pollStart = TimeStamp::NowLoRes(); } SOCKET_LOG((" timeout = %i milliseconds\n", PR_IntervalToMilliseconds(pollTimeout))); int32_t rv = PR_Poll(pollList, pollCount, pollTimeout); PRIntervalTime passedInterval = PR_IntervalNow() - ts; if (mTelemetryEnabledPref && !pollStart.IsNull()) { *pollDuration = TimeStamp::NowLoRes() - pollStart; } SOCKET_LOG((" ...returned after %i milliseconds\n", PR_IntervalToMilliseconds(passedInterval))); *interval = PR_IntervalToSeconds(passedInterval); return rv; }
PRBool Reset() { // reset no more than once per second if (PR_IntervalToSeconds(PR_IntervalNow() - mLastReset) < 1) return PR_FALSE; LOG(("calling res_ninit\n")); mLastReset = PR_IntervalNow(); return (res_ninit(&_res) == 0); }
static PRStatus PR_CALLBACK SocketSetSockOpt( PRFileDesc *fd, PRSockOption optname, const void* optval, PRInt32 optlen) { PRInt32 level, name; PRStatus rv; /* * PR_SockOpt_Nonblocking is a special case that does not * translate to a setsockopt call. */ if (PR_SockOpt_Nonblocking == optname) { PRBool fNonblocking = *((PRIntn *) optval) ? PR_TRUE : PR_FALSE; PR_ASSERT(sizeof(PRIntn) == optlen); #ifdef WINNT PR_ASSERT((fd->secret->md.io_model_committed == PR_FALSE) || (fd->secret->nonblocking == fNonblocking)); if (fd->secret->md.io_model_committed && (fd->secret->nonblocking != fNonblocking)) { /* * On NT, once we have associated a socket with the io * completion port, we can't disassociate it. So we * can't change the nonblocking option of the socket * afterwards. */ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return PR_FAILURE; } #endif fd->secret->nonblocking = fNonblocking; return PR_SUCCESS; } rv = _PR_MapOptionName(optname, &level, &name); if (PR_SUCCESS == rv) { if (PR_SockOpt_Linger == optname) { struct linger linger; linger.l_onoff = ((PRLinger*)(optval))->polarity ? 1 : 0; linger.l_linger = PR_IntervalToSeconds( ((PRLinger*)(optval))->linger); rv = _PR_MD_SETSOCKOPT( fd, level, name, (char *) &linger, sizeof(linger)); } else { rv = _PR_MD_SETSOCKOPT( fd, level, name, optval, optlen); } } return rv; }
static void TestConversions(void) { PRIntervalTime ticks = PR_TicksPerSecond(); if (debug_mode) { PR_fprintf(output, "PR_TicksPerSecond: %ld\n\n", ticks); PR_fprintf(output, "PR_SecondsToInterval(1): %ld\n", PR_SecondsToInterval(1)); PR_fprintf(output, "PR_MillisecondsToInterval(1000): %ld\n", PR_MillisecondsToInterval(1000)); PR_fprintf(output, "PR_MicrosecondsToInterval(1000000): %ld\n\n", PR_MicrosecondsToInterval(1000000)); PR_fprintf(output, "PR_SecondsToInterval(3): %ld\n", PR_SecondsToInterval(3)); PR_fprintf(output, "PR_MillisecondsToInterval(3000): %ld\n", PR_MillisecondsToInterval(3000)); PR_fprintf(output, "PR_MicrosecondsToInterval(3000000): %ld\n\n", PR_MicrosecondsToInterval(3000000)); PR_fprintf(output, "PR_IntervalToSeconds(%ld): %ld\n", ticks, PR_IntervalToSeconds(ticks)); PR_fprintf(output, "PR_IntervalToMilliseconds(%ld): %ld\n", ticks, PR_IntervalToMilliseconds(ticks)); PR_fprintf(output, "PR_IntervalToMicroseconds(%ld): %ld\n\n", ticks, PR_IntervalToMicroseconds(ticks)); ticks *= 3; PR_fprintf(output, "PR_IntervalToSeconds(%ld): %ld\n", ticks, PR_IntervalToSeconds(ticks)); PR_fprintf(output, "PR_IntervalToMilliseconds(%ld): %ld\n", ticks, PR_IntervalToMilliseconds(ticks)); PR_fprintf(output, "PR_IntervalToMicroseconds(%ld): %ld\n\n", ticks, PR_IntervalToMicroseconds(ticks)); } /*end debug mode */ } /* TestConversions */
static PRInt32 filtermethod_emulate_recv(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags, PRIntervalTime timeout) { PR_ASSERT(fd->identity == _filter_identity); FilterLayer *layer = (FilterLayer *)fd; int net_timeout; if (timeout == PR_INTERVAL_NO_WAIT) { net_timeout = NET_ZERO_TIMEOUT; } else if (timeout == PR_INTERVAL_NO_TIMEOUT) { net_timeout = NET_INFINITE_TIMEOUT; } else { net_timeout = PR_IntervalToSeconds(timeout); } return layer->filter->read(layer, buf, amount, net_timeout); }
NSAPI_PUBLIC int INTnet_nspr_interval_to_nsapi_timeout(PRIntervalTime interval) { int timeout; if (interval == PR_INTERVAL_NO_TIMEOUT) { timeout = NET_INFINITE_TIMEOUT; // 0 } else if (interval == PR_INTERVAL_NO_WAIT) { timeout = NET_ZERO_TIMEOUT; // -1 } else { timeout = PR_IntervalToSeconds(interval); if (timeout < 1) timeout = 1; } return timeout; }
PRInt32 nsSocketTransportService::Poll(PRBool wait, PRUint32 *interval) { PRPollDesc *pollList; PRUint32 pollCount; PRIntervalTime pollTimeout; if (mPollList[0].fd) { mPollList[0].out_flags = 0; pollList = mPollList; pollCount = mActiveCount + 1; pollTimeout = PollTimeout(); } else { // no pollable event, so busy wait... pollCount = mActiveCount; if (pollCount) pollList = &mPollList[1]; else pollList = nsnull; pollTimeout = PR_MillisecondsToInterval(25); } if (!wait) pollTimeout = PR_INTERVAL_NO_WAIT; PRIntervalTime ts = PR_IntervalNow(); LOG((" timeout = %i milliseconds\n", PR_IntervalToMilliseconds(pollTimeout))); PRInt32 rv = PR_Poll(pollList, pollCount, pollTimeout); PRIntervalTime passedInterval = PR_IntervalNow() - ts; LOG((" ...returned after %i milliseconds\n", PR_IntervalToMilliseconds(passedInterval))); *interval = PR_IntervalToSeconds(passedInterval); return rv; }
void nsUrlClassifierHashCompleter::NoteServerResponse(PRBool success) { LOG(("nsUrlClassifierHashCompleter::NoteServerResponse [%p, %d]", this, success)); if (success) { mBackoff = PR_FALSE; mNextRequestTime = 0; mBackoffTime = 0; return; } PRIntervalTime now = PR_IntervalNow(); // Record the error time. mErrorTimes.AppendElement(now); if (mErrorTimes.Length() > gBackoffErrors) { mErrorTimes.RemoveElementAt(0); } if (mBackoff) { mBackoffTime *= 2; LOG(("Doubled backoff time to %d seconds", mBackoffTime)); } else if (mErrorTimes.Length() == gBackoffErrors && PR_IntervalToSeconds(now - mErrorTimes[0]) <= gBackoffTime) { mBackoff = PR_TRUE; mBackoffTime = gBackoffInterval; LOG(("Starting backoff, backoff time is %d seconds", mBackoffTime)); } if (mBackoff) { mBackoffTime = PR_MIN(mBackoffTime, gBackoffMax); LOG(("Using %d for backoff time", mBackoffTime)); mNextRequestTime = now + PR_SecondsToInterval(mBackoffTime); } }
void ThreadMain(void*) { PR_SetCurrentThreadName("Hang Monitor"); MonitorAutoLock lock(*gMonitor); // In order to avoid issues with the hang monitor incorrectly triggering // during a general system stop such as sleeping, the monitor thread must // run twice to trigger hang protection. PRIntervalTime lastTimestamp = 0; int waitCount = 0; #ifdef REPORT_CHROME_HANGS Telemetry::ProcessedStack stack; int32_t systemUptime = -1; int32_t firefoxUptime = -1; auto annotations = MakeUnique<ChromeHangAnnotations>(); #endif while (true) { if (gShutdown) { return; // Exit the thread } // avoid rereading the volatile value in this loop PRIntervalTime timestamp = gTimestamp; PRIntervalTime now = PR_IntervalNow(); if (timestamp != PR_INTERVAL_NO_WAIT && now < timestamp) { // 32-bit overflow, reset for another waiting period timestamp = 1; // lowest legal PRInterval value } if (timestamp != PR_INTERVAL_NO_WAIT && timestamp == lastTimestamp && gTimeout > 0) { ++waitCount; #ifdef REPORT_CHROME_HANGS // Capture the chrome-hang stack + Firefox & system uptimes after // the minimum hang duration has been reached (not when the hang ends) if (waitCount == 2) { GetChromeHangReport(stack, systemUptime, firefoxUptime); ChromeHangAnnotatorCallout(*annotations); } #else // This is the crash-on-hang feature. // See bug 867313 for the quirk in the waitCount comparison if (waitCount >= 2) { int32_t delay = int32_t(PR_IntervalToSeconds(now - timestamp)); if (delay >= gTimeout) { MonitorAutoUnlock unlock(*gMonitor); Crash(); } } #endif } else { #ifdef REPORT_CHROME_HANGS if (waitCount >= 2) { uint32_t hangDuration = PR_IntervalToSeconds(now - lastTimestamp); Telemetry::RecordChromeHang(hangDuration, stack, systemUptime, firefoxUptime, Move(annotations)); stack.Clear(); annotations = MakeUnique<ChromeHangAnnotations>(); } #endif lastTimestamp = timestamp; waitCount = 0; } PRIntervalTime timeout; if (gTimeout <= 0) { timeout = PR_INTERVAL_NO_TIMEOUT; } else { timeout = PR_MillisecondsToInterval(gTimeout * 500); } lock.Wait(timeout); } }
static PRInt32 socket_io_wait( PROsfd osfd, PRInt32 fd_type, PRIntervalTime timeout) { PRInt32 rv = -1; struct timeval tv; PRThread *me = _PR_MD_CURRENT_THREAD(); PRIntervalTime elapsed, remaining; PRBool wait_for_remaining; fd_set rd_wr, ex; int err, len; switch (timeout) { case PR_INTERVAL_NO_WAIT: PR_SetError(PR_IO_TIMEOUT_ERROR, 0); break; case PR_INTERVAL_NO_TIMEOUT: /* * This is a special case of the 'default' case below. * Please see the comments there. */ tv.tv_sec = _PR_INTERRUPT_CHECK_INTERVAL_SECS; tv.tv_usec = 0; FD_ZERO(&rd_wr); FD_ZERO(&ex); do { FD_SET(osfd, &rd_wr); FD_SET(osfd, &ex); switch( fd_type ) { case READ_FD: rv = _MD_SELECT(0, &rd_wr, NULL, NULL, &tv); break; case WRITE_FD: rv = _MD_SELECT(0, NULL, &rd_wr, NULL, &tv); break; case CONNECT_FD: rv = _MD_SELECT(0, NULL, &rd_wr, &ex, &tv); break; default: PR_ASSERT(0); break; } /* end switch() */ if (rv == -1 ) { _PR_MD_MAP_SELECT_ERROR(WSAGetLastError()); break; } if ( rv > 0 && fd_type == CONNECT_FD ) { /* * Call Sleep(0) to work around a Winsock timing bug. */ Sleep(0); if (FD_ISSET((SOCKET)osfd, &ex)) { len = sizeof(err); if (getsockopt(osfd, SOL_SOCKET, SO_ERROR, (char *) &err, &len) == SOCKET_ERROR) { _PR_MD_MAP_GETSOCKOPT_ERROR(WSAGetLastError()); return -1; } if (err != 0) _PR_MD_MAP_CONNECT_ERROR(err); else PR_SetError(PR_UNKNOWN_ERROR, 0); return -1; } if (FD_ISSET((SOCKET)osfd, &rd_wr)) { /* it's connected */ return 1; } PR_ASSERT(0); } if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); rv = -1; break; } } while (rv == 0); break; default: remaining = timeout; FD_ZERO(&rd_wr); FD_ZERO(&ex); do { /* * We block in _MD_SELECT for at most * _PR_INTERRUPT_CHECK_INTERVAL_SECS seconds, * so that there is an upper limit on the delay * before the interrupt bit is checked. */ wait_for_remaining = PR_TRUE; tv.tv_sec = PR_IntervalToSeconds(remaining); if (tv.tv_sec > _PR_INTERRUPT_CHECK_INTERVAL_SECS) { wait_for_remaining = PR_FALSE; tv.tv_sec = _PR_INTERRUPT_CHECK_INTERVAL_SECS; tv.tv_usec = 0; } else { tv.tv_usec = PR_IntervalToMicroseconds( remaining - PR_SecondsToInterval(tv.tv_sec)); } FD_SET(osfd, &rd_wr); FD_SET(osfd, &ex); switch( fd_type ) { case READ_FD: rv = _MD_SELECT(0, &rd_wr, NULL, NULL, &tv); break; case WRITE_FD: rv = _MD_SELECT(0, NULL, &rd_wr, NULL, &tv); break; case CONNECT_FD: rv = _MD_SELECT(0, NULL, &rd_wr, &ex, &tv); break; default: PR_ASSERT(0); break; } /* end switch() */ if (rv == -1) { _PR_MD_MAP_SELECT_ERROR(WSAGetLastError()); break; } if ( rv > 0 && fd_type == CONNECT_FD ) { /* * Call Sleep(0) to work around a Winsock timing bug. */ Sleep(0); if (FD_ISSET((SOCKET)osfd, &ex)) { len = sizeof(err); if (getsockopt(osfd, SOL_SOCKET, SO_ERROR, (char *) &err, &len) == SOCKET_ERROR) { _PR_MD_MAP_GETSOCKOPT_ERROR(WSAGetLastError()); return -1; } if (err != 0) _PR_MD_MAP_CONNECT_ERROR(err); else PR_SetError(PR_UNKNOWN_ERROR, 0); return -1; } if (FD_ISSET((SOCKET)osfd, &rd_wr)) { /* it's connected */ return 1; } PR_ASSERT(0); } if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); rv = -1; break; } /* * We loop again if _MD_SELECT timed out and the * timeout deadline has not passed yet. */ if (rv == 0 ) { if (wait_for_remaining) { elapsed = remaining; } else { elapsed = PR_SecondsToInterval(tv.tv_sec) + PR_MicrosecondsToInterval(tv.tv_usec); } if (elapsed >= remaining) { PR_SetError(PR_IO_TIMEOUT_ERROR, 0); rv = -1; break; } else { remaining = remaining - elapsed; } } } while (rv == 0 ); break; } return(rv); } /* end socket_io_wait() */
void ThreadMain(void*) { PR_SetCurrentThreadName("Hang Monitor"); MonitorAutoLock lock(*gMonitor); // In order to avoid issues with the hang monitor incorrectly triggering // during a general system stop such as sleeping, the monitor thread must // run twice to trigger hang protection. PRIntervalTime lastTimestamp = 0; int waitCount = 0; #ifdef REPORT_CHROME_HANGS Telemetry::ProcessedStack stack; #endif while (true) { if (gShutdown) { return; // Exit the thread } // avoid rereading the volatile value in this loop PRIntervalTime timestamp = gTimestamp; PRIntervalTime now = PR_IntervalNow(); if (timestamp != PR_INTERVAL_NO_WAIT && now < timestamp) { // 32-bit overflow, reset for another waiting period timestamp = 1; // lowest legal PRInterval value } if (timestamp != PR_INTERVAL_NO_WAIT && timestamp == lastTimestamp && gTimeout > 0) { ++waitCount; if (waitCount == 2) { #ifdef REPORT_CHROME_HANGS GetChromeHangReport(stack); #else int32_t delay = int32_t(PR_IntervalToSeconds(now - timestamp)); if (delay > gTimeout) { MonitorAutoUnlock unlock(*gMonitor); Crash(); } #endif } } else { #ifdef REPORT_CHROME_HANGS if (waitCount >= 2) { uint32_t hangDuration = PR_IntervalToSeconds(now - lastTimestamp); Telemetry::RecordChromeHang(hangDuration, stack); stack.Clear(); } #endif lastTimestamp = timestamp; waitCount = 0; } PRIntervalTime timeout; if (gTimeout <= 0) { timeout = PR_INTERVAL_NO_TIMEOUT; } else { timeout = PR_MillisecondsToInterval(gTimeout * 500); } lock.Wait(timeout); } }
PRStatus PR_CALLBACK _PR_SocketSetSocketOption(PRFileDesc *fd, const PRSocketOptionData *data) { PRStatus rv; PRInt32 level, name; /* * PR_SockOpt_Nonblocking is a special case that does not * translate to a setsockopt call. */ if (PR_SockOpt_Nonblocking == data->option) { #ifdef WINNT PR_ASSERT((fd->secret->md.io_model_committed == PR_FALSE) || (fd->secret->nonblocking == data->value.non_blocking)); if (fd->secret->md.io_model_committed && (fd->secret->nonblocking != data->value.non_blocking)) { /* * On NT, once we have associated a socket with the io * completion port, we can't disassociate it. So we * can't change the nonblocking option of the socket * afterwards. */ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return PR_FAILURE; } #endif fd->secret->nonblocking = data->value.non_blocking; return PR_SUCCESS; } rv = _PR_MapOptionName(data->option, &level, &name); if (PR_SUCCESS == rv) { switch (data->option) { case PR_SockOpt_Linger: { #if !defined(XP_BEOS) || defined(BONE_VERSION) struct linger linger; linger.l_onoff = data->value.linger.polarity; linger.l_linger = PR_IntervalToSeconds(data->value.linger.linger); rv = _PR_MD_SETSOCKOPT( fd, level, name, (char*)&linger, sizeof(linger)); break; #else PR_SetError( PR_NOT_IMPLEMENTED_ERROR, 0 ); return PR_FAILURE; #endif } case PR_SockOpt_Reuseaddr: case PR_SockOpt_Keepalive: case PR_SockOpt_NoDelay: case PR_SockOpt_Broadcast: { #ifdef WIN32 /* Winsock */ BOOL value; #else PRIntn value; #endif value = (data->value.reuse_addr) ? 1 : 0; rv = _PR_MD_SETSOCKOPT( fd, level, name, (char*)&value, sizeof(value)); break; } case PR_SockOpt_McastLoopback: { #ifdef WIN32 /* Winsock */ BOOL bool; #else PRUint8 bool; #endif bool = data->value.mcast_loopback ? 1 : 0; rv = _PR_MD_SETSOCKOPT( fd, level, name, (char*)&bool, sizeof(bool)); break; } case PR_SockOpt_RecvBufferSize: case PR_SockOpt_SendBufferSize: case PR_SockOpt_MaxSegment: { PRIntn value = data->value.recv_buffer_size; rv = _PR_MD_SETSOCKOPT( fd, level, name, (char*)&value, sizeof(value)); break; } case PR_SockOpt_IpTimeToLive: case PR_SockOpt_IpTypeOfService: { /* These options should really be an int (or PRIntn). */ rv = _PR_MD_SETSOCKOPT( fd, level, name, (char*)&data->value.ip_ttl, sizeof(PRUintn)); break; } case PR_SockOpt_McastTimeToLive: { #ifdef WIN32 /* Winsock */ int ttl; #else PRUint8 ttl; #endif ttl = data->value.mcast_ttl; rv = _PR_MD_SETSOCKOPT( fd, level, name, (char*)&ttl, sizeof(ttl)); break; } #ifdef IP_ADD_MEMBERSHIP case PR_SockOpt_AddMember: case PR_SockOpt_DropMember: { struct ip_mreq mreq; mreq.imr_multiaddr.s_addr = data->value.add_member.mcaddr.inet.ip; mreq.imr_interface.s_addr = data->value.add_member.ifaddr.inet.ip; rv = _PR_MD_SETSOCKOPT( fd, level, name, (char*)&mreq, sizeof(mreq)); break; } #endif /* IP_ADD_MEMBERSHIP */ case PR_SockOpt_McastInterface: { /* This option is a struct in_addr. */ rv = _PR_MD_SETSOCKOPT( fd, level, name, (char*)&data->value.mcast_if.inet.ip, sizeof(data->value.mcast_if.inet.ip)); break; } default: PR_NOT_REACHED("Unknown socket option"); break; } } return rv; } /* _PR_SocketSetSocketOption */
static PRInt32 PR_CALLBACK SocketWritev(PRFileDesc *fd, PRIOVec *iov, PRInt32 iov_size, PRIntervalTime timeout) { PRThread *me = _PR_MD_CURRENT_THREAD(); int w = 0; PRIOVec *tmp_iov = NULL; int tmp_out; int index, iov_cnt; int count=0, sz = 0; /* 'count' is the return value. */ #if defined(XP_UNIX) struct timeval tv, *tvp; fd_set wd; FD_ZERO(&wd); if (timeout == PR_INTERVAL_NO_TIMEOUT) tvp = NULL; else if (timeout != PR_INTERVAL_NO_WAIT) { tv.tv_sec = PR_IntervalToSeconds(timeout); tv.tv_usec = PR_IntervalToMicroseconds( timeout - PR_SecondsToInterval(tv.tv_sec)); tvp = &tv; } #endif if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); return -1; } if (_PR_IO_PENDING(me)) { PR_SetError(PR_IO_PENDING_ERROR, 0); return -1; } tmp_iov = (PRIOVec *)PR_CALLOC(iov_size * sizeof(PRIOVec)); if (!tmp_iov) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); return -1; } for (index=0; index<iov_size; index++) { sz += iov[index].iov_len; tmp_iov[index].iov_base = iov[index].iov_base; tmp_iov[index].iov_len = iov[index].iov_len; } iov_cnt = iov_size; while (sz > 0) { w = _PR_MD_WRITEV(fd, tmp_iov, iov_cnt, timeout); if (w < 0) { count = -1; break; } count += w; if (fd->secret->nonblocking) { break; } sz -= w; if (sz > 0) { /* find the next unwritten vector */ for ( index = 0, tmp_out = count; tmp_out >= iov[index].iov_len; tmp_out -= iov[index].iov_len, index++){;} /* nothing to execute */ /* fill in the first partial read */ tmp_iov[0].iov_base = &(((char *)iov[index].iov_base)[tmp_out]); tmp_iov[0].iov_len = iov[index].iov_len - tmp_out; index++; /* copy the remaining vectors */ for (iov_cnt=1; index<iov_size; iov_cnt++, index++) { tmp_iov[iov_cnt].iov_base = iov[index].iov_base; tmp_iov[iov_cnt].iov_len = iov[index].iov_len; } } } if (tmp_iov) PR_DELETE(tmp_iov); return count; }