Esempio n. 1
0
JSBool
TCP_connect (JSContext* cx, JSObject* object, uintN argc, jsval* argv, jsval* rval)
{
    char*    host;
    int      port    = -1;
    jsdouble timeout = 30;

    JS_BeginRequest(cx);

    if (argc < 1) {
        JS_ReportError(cx, "Not enough parameters.");
        JS_EndRequest(cx);
        return JS_FALSE;
    }

    jsval jsConnected;
    JS_GetProperty(cx, object, "connected", &jsConnected);

    if (jsConnected == JSVAL_TRUE) {
        JS_ReportError(cx, "The socket is already connected.");
        JS_EndRequest(cx);
        return JS_FALSE;
    }

    switch (argc) {
        case 3: JS_ValueToNumber(cx, argv[2], &timeout);
        case 2: JS_ValueToInt32(cx, argv[1], &port);
        case 1: host = JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
    }

    TCPInformation* data = (TCPInformation*) JS_GetPrivate(cx, object);
    PRNetAddr addr; 

    if (__Sockets_initAddr(&addr, host, port) == PR_FAILURE) {
        *rval = JSVAL_FALSE;
        JS_EndRequest(cx);
        return JS_TRUE;
    }

    if (PR_Connect(data->socket, &addr, (timeout == -1)
        ? PR_INTERVAL_NO_TIMEOUT
        : PR_MicrosecondsToInterval(timeout*1000000)) == PR_FAILURE)
    {
        if (PR_GetError() == PR_CONNECT_RESET_ERROR) {
            JS_ReportError(cx, "Connection reset by peer.");
        }

        jsConnected = JSVAL_FALSE;
        JS_SetProperty(cx, object, "connected", &jsConnected);

        JS_EndRequest(cx);
        return JS_FALSE;
    }

    jsConnected = JSVAL_TRUE;
    JS_SetProperty(cx, object, "connected", &jsConnected);

    JS_EndRequest(cx);
    return JS_TRUE;
}
Esempio n. 2
0
JSBool
TCP_accept (JSContext* cx, JSObject* object, uintN argc, jsval* argv, jsval* rval)
{
    jsdouble timeout = -1;

    if (argc) {
        JS_ValueToNumber(cx, argv[0], &timeout);
    }

    TCPInformation* data = (TCPInformation*) JS_GetPrivate(cx, object);
    
    JS_BeginRequest(cx);
    JS_EnterLocalRootScope(cx);

    JSObject* sock = JS_NewObject(cx, &TCP_class, JS_GetPrototype(cx, object), NULL);
    TCPInformation* newData = new TCPInformation;
    JS_SetPrivate(cx, sock, newData);

    PRNetAddr addr;
    newData->socket = PR_Accept(data->socket, &addr, (timeout == -1)
        ? PR_INTERVAL_NO_TIMEOUT
        : PR_MicrosecondsToInterval(timeout*1000000));

    jsval property = JSVAL_TRUE;
    JS_SetProperty(cx, sock, "connected", &property);

    *rval = OBJECT_TO_JSVAL(sock);

    JS_LeaveLocalRootScope(cx);
    JS_EndRequest(cx);
    return JS_TRUE;
}
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 */
Esempio n. 4
0
PRStatus TimelineInit(void)
{
    char *timeStr;
    char *fileName;
    PRInt32 secs, msecs;
    PRFileDesc *fd;
    PRInt64 tmp1, tmp2;

    PRStatus status = PR_NewThreadPrivateIndex( &gTLSIndex, ThreadDestruct );
    NS_WARN_IF_FALSE(status==0, "TimelineService could not allocate TLS storage.");

    timeStr = PR_GetEnv("NS_TIMELINE_INIT_TIME");
#ifdef XP_MAC    
    initInterval = PR_IntervalNow();
#endif
    // NS_TIMELINE_INIT_TIME only makes sense for the main thread, so if it
    // exists, set it there.  If not, let normal thread management code take
    // care of setting the init time.
    if (timeStr != NULL && 2 == PR_sscanf(timeStr, "%d.%d", &secs, &msecs)) {
        PRTime &initTime = GetThisThreadData()->initTime;
        LL_MUL(tmp1, (PRInt64)secs, 1000000);
        LL_MUL(tmp2, (PRInt64)msecs, 1000);
        LL_ADD(initTime, tmp1, tmp2);
#ifdef XP_MAC
        initInterval -= PR_MicrosecondsToInterval(
            (PRUint32)(PR_Now() - initTime));
#endif
    }
    // Get the log file.
#ifdef XP_MAC
    fileName = "timeline.txt";
#else
    fileName = PR_GetEnv("NS_TIMELINE_LOG_FILE");
#endif
    if (fileName != NULL
        && (fd = PR_Open(fileName, PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE,
                         0666)) != NULL) {
        timelineFD = fd;
        PR_fprintf(fd,
                   "NOTE: due to asynchrony, the indentation that you see does"
                   " not necessarily correspond to nesting in the code.\n\n");
    }

    // Runtime disable of timeline
    if (PR_GetEnv("NS_TIMELINE_ENABLE"))
        gTimelineDisabled = PR_FALSE;
    return PR_SUCCESS;
}
Esempio n. 5
0
// this is used for Send without UI
nsresult nsMapiHook::BlindSendMail (unsigned long aSession, nsIMsgCompFields * aCompFields)
{
  nsresult rv = NS_OK ;

  if (!IsBlindSendAllowed())
    return NS_ERROR_FAILURE;

  /** create nsIMsgComposeParams obj and other fields to populate it **/

  nsCOMPtr<nsIDOMWindowInternal>  hiddenWindow;
  // get parent window
  nsCOMPtr<nsIAppShellService> appService = do_GetService( "@mozilla.org/appshell/appShellService;1", &rv);
  if (NS_FAILED(rv)|| (!appService) ) return rv ;

  rv = appService->GetHiddenDOMWindow(getter_AddRefs(hiddenWindow));
  if ( NS_FAILED(rv) ) return rv ;
  // smtp password and Logged in used IdKey from MapiConfig (session obj)
  nsMAPIConfiguration * pMapiConfig = nsMAPIConfiguration::GetMAPIConfiguration() ;
  if (!pMapiConfig) return NS_ERROR_FAILURE ;  // get the singelton obj
  PRUnichar * password = pMapiConfig->GetPassword(aSession) ;
  // password
  nsCAutoString smtpPassword;
  LossyCopyUTF16toASCII(password, smtpPassword);

  // Id key
  nsCString MsgIdKey;
  pMapiConfig->GetIdKey(aSession, MsgIdKey);

  // get the MsgIdentity for the above key using AccountManager
  nsCOMPtr <nsIMsgAccountManager> accountManager = do_GetService (NS_MSGACCOUNTMANAGER_CONTRACTID) ;
  if (NS_FAILED(rv) || (!accountManager) ) return rv ;

  nsCOMPtr <nsIMsgIdentity> pMsgId ;
  rv = accountManager->GetIdentity (MsgIdKey, getter_AddRefs(pMsgId)) ;
  if (NS_FAILED(rv) ) return rv ;

  // create a send listener to get back the send status
  nsCOMPtr <nsIMsgSendListener> sendListener ;
  rv = nsMAPISendListener::CreateMAPISendListener(getter_AddRefs(sendListener)) ;
  if (NS_FAILED(rv) || (!sendListener) ) return rv;

  // create the compose params object
  nsCOMPtr<nsIMsgComposeParams> pMsgComposeParams (do_CreateInstance(NS_MSGCOMPOSEPARAMS_CONTRACTID, &rv));
  if (NS_FAILED(rv) || (!pMsgComposeParams) ) return rv ;

  // populate the compose params
  PRBool forcePlainText;
  aCompFields->GetForcePlainText(&forcePlainText);
  pMsgComposeParams->SetType(nsIMsgCompType::New);
  pMsgComposeParams->SetFormat(forcePlainText ? nsIMsgCompFormat::PlainText : nsIMsgCompFormat::HTML);
  pMsgComposeParams->SetIdentity(pMsgId);
  pMsgComposeParams->SetComposeFields(aCompFields);
  pMsgComposeParams->SetSendListener(sendListener) ;
  pMsgComposeParams->SetSmtpPassword(smtpPassword.get());

  // create the nsIMsgCompose object to send the object
  nsCOMPtr<nsIMsgCompose> pMsgCompose (do_CreateInstance(NS_MSGCOMPOSE_CONTRACTID, &rv));
  if (NS_FAILED(rv) || (!pMsgCompose) ) return rv ;

  /** initialize nsIMsgCompose, Send the message, wait for send completion response **/

  rv = pMsgCompose->Initialize(hiddenWindow, pMsgComposeParams) ;
  if (NS_FAILED(rv)) return rv ;

  return pMsgCompose->SendMsg(nsIMsgSend::nsMsgDeliverNow, pMsgId, nsnull, nsnull, nsnull) ;
  if (NS_FAILED(rv)) return rv ;

  // assign to interface pointer from nsCOMPtr to facilitate typecast below
  nsIMsgSendListener * pSendListener = sendListener ;

  // we need to wait here to make sure that we return only after send is completed
  // so we will have a event loop here which will process the events till the Send IsDone.
  nsIThread *thread = NS_GetCurrentThread();
  while ( !((nsMAPISendListener *) pSendListener)->IsDone() )
  {
    PR_CEnterMonitor(pSendListener);
    PR_CWait(pSendListener, PR_MicrosecondsToInterval(1000UL));
    PR_CExitMonitor(pSendListener);
    NS_ProcessPendingEvents(thread);
  }

  return rv ;
}
Esempio n. 6
0
nsresult
nsMsgCopy::DoCopy(nsIFile *aDiskFile, nsIMsgFolder *dstFolder,
                  nsIMsgDBHdr *aMsgToReplace, bool aIsDraft,
                  nsIMsgWindow *msgWindow,
                  nsIMsgSend   *aMsgSendObj)
{
  nsresult rv = NS_OK;

  // Check sanity
  if ((!aDiskFile) || (!dstFolder))
    return NS_ERROR_INVALID_ARG;

  //Call copyservice with dstFolder, disk file, and txnManager
  if(NS_SUCCEEDED(rv))
  {
    nsRefPtr<CopyListener> copyListener = new CopyListener();
    if (!copyListener)
      return NS_ERROR_OUT_OF_MEMORY;

    copyListener->SetMsgComposeAndSendObject(aMsgSendObj);
    nsCOMPtr<nsIThread> thread;

    if (aIsDraft)
    {
        nsCOMPtr<nsIMsgImapMailFolder> imapFolder =
            do_QueryInterface(dstFolder);
        nsCOMPtr<nsIMsgAccountManager> accountManager =
                 do_GetService(NS_MSGACCOUNTMANAGER_CONTRACTID, &rv);
        if (NS_FAILED(rv)) return rv;
        bool shutdownInProgress = false;
        rv = accountManager->GetShutdownInProgress(&shutdownInProgress);

        if (NS_SUCCEEDED(rv) && shutdownInProgress && imapFolder)
        {
          // set the following only when we were in the middle of shutdown
          // process
            copyListener->mCopyInProgress = true;
            thread = do_GetCurrentThread();
        }
    }
    nsCOMPtr<nsIMsgCopyService> copyService = do_GetService(NS_MSGCOPYSERVICE_CONTRACTID, &rv);
    NS_ENSURE_SUCCESS(rv, rv);

    rv = copyService->CopyFileMessage(aDiskFile, dstFolder, aMsgToReplace,
                                      aIsDraft,
                                      aIsDraft ? 0 : nsMsgMessageFlags::Read,
                                      EmptyCString(), copyListener, msgWindow);
    // copyListener->mCopyInProgress can only be set when we are in the
    // middle of the shutdown process
    while (copyListener->mCopyInProgress)
    {
        PR_CEnterMonitor(copyListener);
        PR_CWait(copyListener, PR_MicrosecondsToInterval(1000UL));
        PR_CExitMonitor(copyListener);
        if (thread)
            NS_ProcessPendingEvents(thread);
    }
  }

  return rv;
}
Esempio n. 7
0
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() */
Esempio n. 8
0
/* void Run(); */
NS_IMETHODIMP TimerThread::Run()
{
  nsAutoLock lock(mLock);

  // We need to know how many microseconds give a positive PRIntervalTime. This
  // is platform-dependent, we calculate it at runtime now.
  // First we find a value such that PR_MicrosecondsToInterval(high) = 1
  PRInt32 low = 0, high = 1;
  while (PR_MicrosecondsToInterval(high) == 0)
    high <<= 1;
  // We now have
  //    PR_MicrosecondsToInterval(low)  = 0
  //    PR_MicrosecondsToInterval(high) = 1
  // and we can proceed to find the critical value using binary search
  while (high-low > 1) {
    PRInt32 mid = (high+low) >> 1;
    if (PR_MicrosecondsToInterval(mid) == 0)
      low = mid;
    else
      high = mid;
  }

  // Half of the amount of microseconds needed to get positive PRIntervalTime.
  // We use this to decide how to round our wait times later
  PRInt32 halfMicrosecondsIntervalResolution = high >> 1;

  while (!mShutdown) {
    // Have to use PRIntervalTime here, since PR_WaitCondVar takes it
    PRIntervalTime waitFor;

    if (mSleeping) {
      // Sleep for 0.1 seconds while not firing timers.
      waitFor = PR_MillisecondsToInterval(100);
    } else {
      waitFor = PR_INTERVAL_NO_TIMEOUT;
      TimeStamp now = TimeStamp::Now();
      nsTimerImpl *timer = nsnull;

      if (!mTimers.IsEmpty()) {
        timer = mTimers[0];

        if (now >= timer->mTimeout + mTimeoutAdjustment) {
    next:
          // NB: AddRef before the Release under RemoveTimerInternal to avoid
          // mRefCnt passing through zero, in case all other refs than the one
          // from mTimers have gone away (the last non-mTimers[i]-ref's Release
          // must be racing with us, blocked in gThread->RemoveTimer waiting
          // for TimerThread::mLock, under nsTimerImpl::Release.

          NS_ADDREF(timer);
          RemoveTimerInternal(timer);

          // We release mLock around the Fire call to avoid deadlock.
          lock.unlock();

#ifdef DEBUG_TIMERS
          if (PR_LOG_TEST(gTimerLog, PR_LOG_DEBUG)) {
            PR_LOG(gTimerLog, PR_LOG_DEBUG,
                   ("Timer thread woke up %fms from when it was supposed to\n",
                    fabs((now - timer->mTimeout).ToMilliseconds())));
          }
#endif

          // We are going to let the call to PostTimerEvent here handle the
          // release of the timer so that we don't end up releasing the timer
          // on the TimerThread instead of on the thread it targets.
          if (NS_FAILED(timer->PostTimerEvent())) {
            nsrefcnt rc;
            NS_RELEASE2(timer, rc);
            
            // The nsITimer interface requires that its users keep a reference
            // to the timers they use while those timers are initialized but
            // have not yet fired.  If this ever happens, it is a bug in the
            // code that created and used the timer.
            //
            // Further, note that this should never happen even with a
            // misbehaving user, because nsTimerImpl::Release checks for a
            // refcount of 1 with an armed timer (a timer whose only reference
            // is from the timer thread) and when it hits this will remove the
            // timer from the timer thread and thus destroy the last reference,
            // preventing this situation from occurring.
            NS_ASSERTION(rc != 0, "destroyed timer off its target thread!");
          }
          timer = nsnull;

          lock.lock();
          if (mShutdown)
            break;

          // Update now, as PostTimerEvent plus the locking may have taken a
          // tick or two, and we may goto next below.
          now = TimeStamp::Now();
        }
      }

      if (!mTimers.IsEmpty()) {
        timer = mTimers[0];

        TimeStamp timeout = timer->mTimeout + mTimeoutAdjustment;

        // Don't wait at all (even for PR_INTERVAL_NO_WAIT) if the next timer
        // is due now or overdue.
        //
        // Note that we can only sleep for integer values of a certain
        // resolution. We use halfMicrosecondsIntervalResolution, calculated
        // before, to do the optimal rounding (i.e., of how to decide what
        // interval is so small we should not wait at all).
        double microseconds = (timeout - now).ToMilliseconds()*1000;
        if (microseconds < halfMicrosecondsIntervalResolution)
          goto next; // round down; execute event now
        waitFor = PR_MicrosecondsToInterval(microseconds);
        if (waitFor == 0)
          waitFor = 1; // round up, wait the minimum time we can wait
      }

#ifdef DEBUG_TIMERS
      if (PR_LOG_TEST(gTimerLog, PR_LOG_DEBUG)) {
        if (waitFor == PR_INTERVAL_NO_TIMEOUT)
          PR_LOG(gTimerLog, PR_LOG_DEBUG,
                 ("waiting for PR_INTERVAL_NO_TIMEOUT\n"));
        else
          PR_LOG(gTimerLog, PR_LOG_DEBUG,
                 ("waiting for %u\n", PR_IntervalToMilliseconds(waitFor)));
      }
#endif
    }

    mWaiting = PR_TRUE;
    PR_WaitCondVar(mCondVar, waitFor);
    mWaiting = PR_FALSE;
  }

  return NS_OK;
}
Esempio n. 9
0
int select(int width, fd_set *rd, fd_set *wr, fd_set *ex, struct timeval *tv)
#endif
{
    int osfd;
    _PRUnixPollDesc *unixpds, *unixpd, *eunixpd;
    PRInt32 pdcnt;
    PRIntervalTime timeout;
    int retVal;
#if defined(HPUX9) || defined(AIX_RENAME_SELECT)
    fd_set *rd = (fd_set*) rl;
    fd_set *wr = (fd_set*) wl;
    fd_set *ex = (fd_set*) el;
#endif

#if 0
    /*
     * Easy special case: zero timeout.  Simply call the native
     * select() with no fear of blocking.
     */
    if (tv != NULL && tv->tv_sec == 0 && tv->tv_usec == 0) {
#if defined(HPUX9) || defined(AIX_RENAME_SELECT)
        return _MD_SELECT(width, rl, wl, el, tv);
#else
        return _MD_SELECT(width, rd, wr, ex, tv);
#endif
    }
#endif

    if (!_pr_initialized) {
        _PR_ImplicitInitialization();
    }
		
#ifndef _PR_LOCAL_THREADS_ONLY
    if (_PR_IS_NATIVE_THREAD(_PR_MD_CURRENT_THREAD())) {
        return _MD_SELECT(width, rd, wr, ex, tv);	
    }
#endif

    if (width < 0 || width > FD_SETSIZE) {
        errno = EINVAL;
        return -1;
    }

    /* Compute timeout */
    if (tv) {
        /*
         * These acceptable ranges for t_sec and t_usec are taken
         * from the select() man pages.
         */
        if (tv->tv_sec < 0 || tv->tv_sec > 100000000
                || tv->tv_usec < 0 || tv->tv_usec >= 1000000) {
            errno = EINVAL;
            return -1;
        }

        /* Convert microseconds to ticks */
        timeout = PR_MicrosecondsToInterval(1000000*tv->tv_sec + tv->tv_usec);
    } else {
        /* tv being a NULL pointer means blocking indefinitely */
        timeout = PR_INTERVAL_NO_TIMEOUT;
    }

    /* Check for no descriptors case (just doing a timeout) */
    if ((!rd && !wr && !ex) || !width) {
        PR_Sleep(timeout);
        return 0;
    }

    /*
     * Set up for PR_Poll().  The PRPollDesc array is allocated
     * dynamically.  If this turns out to have high performance
     * penalty, one can change to use a large PRPollDesc array
     * on the stack, and allocate dynamically only when it turns
     * out to be not large enough.
     *
     * I allocate an array of size 'width', which is the maximum
     * number of fds we may need to poll.
     */
    unixpds = (_PRUnixPollDesc *) PR_CALLOC(width * sizeof(_PRUnixPollDesc));
    if (!unixpds) {
        errno = ENOMEM;
        return -1;
    }

    pdcnt = 0;
    unixpd = unixpds;
    for (osfd = 0; osfd < width; osfd++) {
        int in_flags = 0;
        if (rd && FD_ISSET(osfd, rd)) {
            in_flags |= _PR_UNIX_POLL_READ;
        }
        if (wr && FD_ISSET(osfd, wr)) {
            in_flags |= _PR_UNIX_POLL_WRITE;
        }
        if (ex && FD_ISSET(osfd, ex)) {
            in_flags |= _PR_UNIX_POLL_EXCEPT;
        }
        if (in_flags) {
            unixpd->osfd = osfd;
            unixpd->in_flags = in_flags;
            unixpd->out_flags = 0;
            unixpd++;
            pdcnt++;
        }
    }

    /*
     * see comments in mozilla/cmd/xfe/mozilla.c (look for
     * "PR_XGetXtHackFD")
     */
   {
     int needToLockXAgain;
 
     needToLockXAgain = 0;
     if (rd && (_pr_xt_hack_fd != -1)
             && FD_ISSET(_pr_xt_hack_fd, rd) && PR_XIsLocked()
             && (!_pr_xt_hack_okayToReleaseXLock
             || _pr_xt_hack_okayToReleaseXLock())) {
         PR_XUnlock();
         needToLockXAgain = 1;
     }

    /* This is the potentially blocking step */
    retVal = _PR_WaitForMultipleFDs(unixpds, pdcnt, timeout);

     if (needToLockXAgain) {
         PR_XLock();
     }
   }

    if (retVal > 0) {
        /* Compute select results */
        if (rd) ZAP_SET(rd, width);
        if (wr) ZAP_SET(wr, width);
        if (ex) ZAP_SET(ex, width);

        /*
         * The return value can be either the number of ready file
         * descriptors or the number of set bits in the three fd_set's.
         */
        retVal = 0;  /* we're going to recompute */
        eunixpd = unixpds + pdcnt;
        for (unixpd = unixpds; unixpd < eunixpd; unixpd++) {
            if (unixpd->out_flags) {
                int nbits = 0;  /* The number of set bits on for this fd */

                if (unixpd->out_flags & _PR_UNIX_POLL_NVAL) {
                    errno = EBADF;
                    PR_LOG(_pr_io_lm, PR_LOG_ERROR,
                            ("select returns EBADF for %d", unixpd->osfd));
                    retVal = -1;
                    break;
                }
                /*
                 * If a socket has a pending error, it is considered
                 * both readable and writable.  (See W. Richard Stevens,
                 * Unix Network Programming, Vol. 1, 2nd Ed., Section 6.3,
                 * pp. 153-154.)  We also consider a socket readable if
                 * it has a hangup condition.
                 */
                if (rd && (unixpd->in_flags & _PR_UNIX_POLL_READ)
                        && (unixpd->out_flags & (_PR_UNIX_POLL_READ
                        | _PR_UNIX_POLL_ERR | _PR_UNIX_POLL_HUP))) {
                    FD_SET(unixpd->osfd, rd);
                    nbits++;
                }
                if (wr && (unixpd->in_flags & _PR_UNIX_POLL_WRITE)
                        && (unixpd->out_flags & (_PR_UNIX_POLL_WRITE
                        | _PR_UNIX_POLL_ERR))) {
                    FD_SET(unixpd->osfd, wr);
                    nbits++;
                }
                if (ex && (unixpd->in_flags & _PR_UNIX_POLL_WRITE)
                        && (unixpd->out_flags & PR_POLL_EXCEPT)) {
                    FD_SET(unixpd->osfd, ex);
                    nbits++;
                }
                PR_ASSERT(nbits > 0);
#if defined(HPUX) || defined(SOLARIS) || defined(SUNOS4) || defined(OSF1) || defined(AIX)
                retVal += nbits;
#else /* IRIX */
                retVal += 1;
#endif
            }
        }
    }

    PR_ASSERT(tv || retVal != 0);
    PR_LOG(_pr_io_lm, PR_LOG_MIN, ("select returns %d", retVal));
    PR_DELETE(unixpds);

    return retVal;
}
Esempio n. 10
0
SECStatus
nsNSSHttpRequestSession::internal_send_receive_attempt(PRBool &retryable_error,
                                                       PRPollDesc **pPollDesc,
                                                       PRUint16 *http_response_code,
                                                       const char **http_response_content_type,
                                                       const char **http_response_headers,
                                                       const char **http_response_data,
                                                       PRUint32 *http_response_data_len)
{
  if (pPollDesc) *pPollDesc = nsnull;
  if (http_response_code) *http_response_code = 0;
  if (http_response_content_type) *http_response_content_type = 0;
  if (http_response_headers) *http_response_headers = 0;
  if (http_response_data) *http_response_data = 0;

  PRUint32 acceptableResultSize = 0;

  if (http_response_data_len)
  {
    acceptableResultSize = *http_response_data_len;
    *http_response_data_len = 0;
  }
  
  if (!mListener)
    return SECFailure;

  if (NS_FAILED(mListener->InitLocks()))
    return SECFailure;

  PRLock *waitLock = mListener->mLock;
  PRCondVar *waitCondition = mListener->mCondition;
  volatile PRBool &waitFlag = mListener->mWaitFlag;
  waitFlag = PR_TRUE;

  nsRefPtr<nsHTTPDownloadEvent> event = new nsHTTPDownloadEvent;
  if (!event)
    return SECFailure;

  event->mListener = mListener;
  this->AddRef();
  event->mRequestSession = this;

  nsresult rv = NS_DispatchToMainThread(event);
  if (NS_FAILED(rv))
  {
    event->mResponsibleForDoneSignal = PR_FALSE;
    return SECFailure;
  }

  PRBool request_canceled = PR_FALSE;

  {
    nsAutoLock locker(waitLock);

    const PRIntervalTime start_time = PR_IntervalNow();
    PRIntervalTime wait_interval;

    PRBool running_on_main_thread = NS_IsMainThread();
    if (running_on_main_thread)
    {
      // let's process events quickly
      wait_interval = PR_MicrosecondsToInterval(50);
    }
    else
    { 
      // On a secondary thread, it's fine to wait some more for
      // for the condition variable.
      wait_interval = PR_MillisecondsToInterval(250);
    }

    while (waitFlag)
    {
      if (running_on_main_thread)
      {
        // Networking runs on the main thread, which we happen to block here.
        // Processing events will allow the OCSP networking to run while we 
        // are waiting. Thanks a lot to Darin Fisher for rewriting the 
        // thread manager. Thanks a lot to Christian Biesinger who
        // made me aware of this possibility. (kaie)

        locker.unlock();
        NS_ProcessNextEvent(nsnull);
        locker.lock();
      }

      PR_WaitCondVar(waitCondition, wait_interval);
      
      if (!waitFlag)
        break;

      if (!request_canceled)
      {
        PRBool wantExit = nsSSLThread::exitRequested();
        PRBool timeout = 
          (PRIntervalTime)(PR_IntervalNow() - start_time) > mTimeoutInterval;

        if (wantExit || timeout)
        {
          request_canceled = PR_TRUE;

          nsRefPtr<nsCancelHTTPDownloadEvent> cancelevent = new nsCancelHTTPDownloadEvent;
          cancelevent->mListener = mListener;
          rv = NS_DispatchToMainThread(cancelevent);
          if (NS_FAILED(rv)) {
            NS_WARNING("cannot post cancel event");
          }
          break;
        }
      }
    }
  }

  if (request_canceled)
    return SECFailure;

  if (NS_FAILED(mListener->mResultCode))
  {
    if (mListener->mResultCode == NS_ERROR_CONNECTION_REFUSED
        ||
        mListener->mResultCode == NS_ERROR_NET_RESET)
    {
      retryable_error = PR_TRUE;
    }
    return SECFailure;
  }

  if (http_response_code)
    *http_response_code = mListener->mHttpResponseCode;

  if (mListener->mHttpRequestSucceeded && http_response_data && http_response_data_len) {

    *http_response_data_len = mListener->mResultLen;
  
    // acceptableResultSize == 0 means: any size is acceptable
    if (acceptableResultSize != 0
        &&
        acceptableResultSize < mListener->mResultLen)
    {
      return SECFailure;
    }

    // return data by reference, result data will be valid 
    // until "this" gets destroyed by NSS
    *http_response_data = (const char*)mListener->mResultData;
  }

  if (mListener->mHttpRequestSucceeded && http_response_content_type) {
    if (mListener->mHttpResponseContentType.Length()) {
      *http_response_content_type = mListener->mHttpResponseContentType.get();
    }
  }

  return SECSuccess;
}
Esempio n. 11
0
JSBool
TCP_read (JSContext *cx, JSObject *object, uintN argc, jsval *argv, jsval *rval)
{
    int32    size;
    uint16   flags   = 0;
    jsdouble timeout = -1;

    JS_BeginRequest(cx);

    if (argc < 1) {
        JS_ReportError(cx, "Not enough parameters.");
        JS_EndRequest(cx);
        return JS_FALSE;
    }

    switch (argc) {
        case 3: JS_ValueToNumber(cx, argv[2], &timeout);
        case 2: JS_ValueToUint16(cx, argv[1], &flags);
        case 1: JS_ValueToInt32(cx, argv[0], &size);
    }

    TCPInformation* data = (TCPInformation*) JS_GetPrivate(cx, object);

    jsval jsConnected; JS_GetProperty(cx, object, "connected", &jsConnected);
    JSBool connected; JS_ValueToBoolean(cx, jsConnected, &connected);

    if (!connected) {
        JS_ReportError(cx, "The socket isn't connected.");
        JS_LeaveLocalRootScope(cx);
        JS_EndRequest(cx);
        return JS_FALSE;
    }

    char* string = (char*) JS_malloc(cx, size*sizeof(char));

    jsrefcount req = JS_SuspendRequest(cx);
    int32 offset   = 0;
    int32 received = 0;
    while (offset < size) {
        received = PR_Recv(data->socket, (string+offset), (size-offset)*sizeof(char), flags,
            (timeout == -1) ? PR_INTERVAL_NO_TIMEOUT : PR_MicrosecondsToInterval(timeout*1000000));

        if (received == -1) {
            break;
        }
        
        offset += received;
    }
    JS_ResumeRequest(cx, req);

    if (received < 0) {
        switch (PR_GetError()) {
            default: JS_ReportError(cx, "Something went wrong."); break;
        }

        JS_EndRequest(cx);
        return JS_FALSE;
    }

    *rval = STRING_TO_JSVAL(JS_NewString(cx, string, offset));

    JS_EndRequest(cx);
    return JS_TRUE;
}
Esempio n. 12
0
JSBool
TCP_write (JSContext* cx, JSObject* object, uintN argc, jsval* argv, jsval* rval)
{
    JSString* stringObject;
    uint16    flags   = 0;
    jsdouble  timeout = -1;

    JS_BeginRequest(cx);

    if (argc < 1) {
        JS_ReportError(cx, "Not enough parameters.");
        JS_EndRequest(cx);
        return JS_FALSE;
    }

    JS_EnterLocalRootScope(cx);

    switch (argc) {
        case 3: JS_ValueToNumber(cx, argv[2], &timeout);
        case 2: JS_ValueToUint16(cx, argv[1], &flags);
        case 1: stringObject = JS_ValueToString(cx, argv[0]);
    }

    TCPInformation* data = (TCPInformation*) JS_GetPrivate(cx, object);

    jsval jsConnected; JS_GetProperty(cx, object, "connected", &jsConnected);
    JSBool connected; JS_ValueToBoolean(cx, jsConnected, &connected);

    if (!connected) {
        JS_ReportError(cx, "The socket isn't connected.");
        JS_LeaveLocalRootScope(cx);
        JS_EndRequest(cx);
        return JS_FALSE;
    }

    char*  string = JS_GetStringBytes(stringObject); 
    size_t offset = 0;
    int    sent   = 0;
    size_t length = JS_GetStringLength(stringObject);

    jsrefcount req = JS_SuspendRequest(cx);
    while (offset < length) {
        sent = PR_Send(data->socket, (string+offset), (length-offset)*sizeof(char), flags,
            (timeout == -1) ? PR_INTERVAL_NO_TIMEOUT : PR_MicrosecondsToInterval(timeout*1000000));

        if (sent < 0) {
            break;
        }

        offset += sent;
    }
    JS_ResumeRequest(cx, req);
    JS_LeaveLocalRootScope(cx);

    if (sent < 0) {
        switch (PR_GetError()) {
            default: JS_ReportError(cx, "Something went wrong."); break;
        }

        JS_EndRequest(cx);
        return JS_FALSE;
    }

    JS_EndRequest(cx);
    return JS_TRUE;
}