Ejemplo n.º 1
0
// This should be called on the STS thread.
int NrSocket::sendto(const void *msg, size_t len,
                     int flags, nr_transport_addr *to) {
  ASSERT_ON_THREAD(ststhread_);
  int r,_status;
  PRNetAddr naddr;
  int32_t status;

  if ((r=nr_transport_addr_to_praddr(to, &naddr)))
    ABORT(r);

  if(fd_==nullptr)
    ABORT(R_EOD);

  if (nr_is_stun_request_message((UCHAR*)msg, len)) {
    // Global rate limiting for stun requests, to mitigate the ice hammer DoS
    // (see http://tools.ietf.org/html/draft-thomson-mmusic-ice-webrtc)

    // Tolerate rate of 8k/sec, for one second.
    static SimpleTokenBucket burst(8192*1, 8192);
    // Tolerate rate of 3.6k/sec over twenty seconds.
    static SimpleTokenBucket sustained(3686*20, 3686);

    // Check number of tokens in each bucket.
    if (burst.getTokens(UINT32_MAX) < len ||
        sustained.getTokens(UINT32_MAX) < len) {
      r_log(LOG_GENERIC, LOG_ERR,
                 "Global rate limit for STUN requests exceeded.");
      MOZ_ASSERT("Global rate limit for STUN requests exceeded. Go bug "
                 "[email protected] if you weren't intentionally spamming "
                 "ICE candidates, or don't know what that means.");
      ABORT(R_WOULDBLOCK);
    }

    // Take len tokens from both buckets.
    // (not threadsafe, but no problem since this is only called from STS)
    burst.getTokens(len);
    sustained.getTokens(len);
  }

  // TODO: Convert flags?
  status = PR_SendTo(fd_, msg, len, flags, &naddr, PR_INTERVAL_NO_WAIT);
  if (status < 0 || (size_t)status != len) {
    if (PR_GetError() == PR_WOULD_BLOCK_ERROR)
      ABORT(R_WOULDBLOCK);

    r_log(LOG_GENERIC, LOG_INFO, "Error in sendto %s", to->as_string);
    ABORT(R_IO_ERROR);
  }

  _status=0;
abort:
  return(_status);
}
Ejemplo n.º 2
0
// This should be called on the STS thread.
int NrSocket::sendto(const void *msg, size_t len,
                     int flags, nr_transport_addr *to) {
  ASSERT_ON_THREAD(ststhread_);
  int r,_status;
  PRNetAddr naddr;
  int32_t status;

  if ((r=nr_transport_addr_to_praddr(to, &naddr)))
    ABORT(r);

  if(fd_==nullptr)
    ABORT(R_EOD);

  if (nr_is_stun_request_message((UCHAR*)msg, len)) {
    // Global rate limiting for stun requests, to mitigate the ice hammer DoS
    // (see http://tools.ietf.org/html/draft-thomson-mmusic-ice-webrtc)

    // Tolerate rate of 8k/sec, for one second.
    static SimpleTokenBucket burst(16384*1, 16384);
    // Tolerate rate of 7.2k/sec over twenty seconds.
    static SimpleTokenBucket sustained(7372*20, 7372);

    // Check number of tokens in each bucket.
    if (burst.getTokens(UINT32_MAX) < len) {
      r_log(LOG_GENERIC, LOG_ERR,
                 "Short term global rate limit for STUN requests exceeded.");
#ifdef MOZILLA_INTERNAL_API
      nr_socket_short_term_violation_time = TimeStamp::Now();
#endif

// Bug 1013007
#if !EARLY_BETA_OR_EARLIER
      ABORT(R_WOULDBLOCK);
#else
      MOZ_ASSERT(false,
                 "Short term global rate limit for STUN requests exceeded. Go "
                 "bug [email protected] if you weren't intentionally "
                 "spamming ICE candidates, or don't know what that means.");
#endif
    }

    if (sustained.getTokens(UINT32_MAX) < len) {
      r_log(LOG_GENERIC, LOG_ERR,
                 "Long term global rate limit for STUN requests exceeded.");
#ifdef MOZILLA_INTERNAL_API
      nr_socket_long_term_violation_time = TimeStamp::Now();
#endif
// Bug 1013007
#if !EARLY_BETA_OR_EARLIER
      ABORT(R_WOULDBLOCK);
#else
      MOZ_ASSERT(false,
                 "Long term global rate limit for STUN requests exceeded. Go "
                 "bug [email protected] if you weren't intentionally "
                 "spamming ICE candidates, or don't know what that means.");
#endif
    }

    // Take len tokens from both buckets.
    // (not threadsafe, but no problem since this is only called from STS)
    burst.getTokens(len);
    sustained.getTokens(len);
  }

  // TODO: Convert flags?
  status = PR_SendTo(fd_, msg, len, flags, &naddr, PR_INTERVAL_NO_WAIT);
  if (status < 0 || (size_t)status != len) {
    if (PR_GetError() == PR_WOULD_BLOCK_ERROR)
      ABORT(R_WOULDBLOCK);

    r_log(LOG_GENERIC, LOG_INFO, "Error in sendto %s", to->as_string);
    ABORT(R_IO_ERROR);
  }

  _status=0;
abort:
  return(_status);
}