Exemplo n.º 1
0
void FileRegion::FileWriteRequest::FileReadHandler::handlerReady(
    uint16_t events) noexcept {
  CHECK(events & EventHandler::WRITE);
  if (bytesToRead_ == 0) {
    unregisterHandler();
    return;
  }

  int flags = SPLICE_F_NONBLOCK | SPLICE_F_MORE;
  ssize_t spliced = ::splice(req_->readFd_, &req_->offset_,
                             pipe_in_, nullptr,
                             bytesToRead_, flags);
  if (spliced == -1) {
    if (errno == EAGAIN) {
      return;
    } else {
      req_->fail(__func__, AsyncSocketException(
          AsyncSocketException::INTERNAL_ERROR,
          "splice failed", errno));
      return;
    }
  }

  if (spliced > 0) {
    bytesToRead_ -= spliced;
    try {
      req_->queue_.putMessage(static_cast<size_t>(spliced));
    } catch (...) {
      req_->fail(__func__, AsyncSocketException(
          AsyncSocketException::INTERNAL_ERROR,
          "putMessage failed"));
      return;
    }
  }
}
Exemplo n.º 2
0
void TunIntf::handlerReady(uint16_t events) noexcept {
  CHECK(fd_ != -1);
  const int MaxSentOneTime = 16;
  // TODO: The packet size should be as same as MTU (hard code 1500 for now).
  // Since this is L3 packet size, we should also reserve some space for L2
  // header, which is 18 bytes (including one vlan tag)
  const int l3Len = 1500;
  int sent = 0;
  int dropped = 0;
  uint64_t bytes = 0;
  bool fdFail = false;
  try {
    while (sent + dropped < MaxSentOneTime) {
      std::unique_ptr<TxPacket> pkt;
      pkt = sw_->allocateL3TxPacket(l3Len);
      auto buf = pkt->buf();
      int ret = 0;
      do {
        ret = read(fd_, buf->writableTail(), buf->tailroom());
      } while (ret == -1 && errno == EINTR);
      if (ret < 0) {
        if (errno != EAGAIN) {
          sysLogError(ret, "Failed to read on ", fd_);
          // Cannot continue read on this fd
          fdFail = true;
        }
        break;
      } else if (ret == 0) {
        // Nothing to read. It shall not happen as the fd is non-blocking.
        // Just add this case to be safe.
        break;
      } else if (ret > buf->tailroom()) {
        // The pkt is larger than the buffer. We don't have complete packet.
        // It shall not happen unless the MTU is mis-match. Drop the packet.
        LOG(ERROR) << "Too large packet (" << ret << " > " << buf->tailroom()
                   << ") received from host. Drop the packet.";
        dropped++;
      } else {
        bytes += ret;
        buf->append(ret);
        sw_->sendL3Packet(rid_, std::move(pkt));
        sent++;
      }
    }
  } catch (const std::exception& ex) {
    LOG(ERROR) << "Hit some error when forwarding packets :"
               << folly::exceptionStr(ex);
  }
  if (fdFail) {
    unregisterHandler();
  }
  VLOG(4) << "Forwarded " << sent << " packets (" << bytes
          << " bytes) from host @ fd " << fd_ << " for router " << rid_
          << " dropped:" << dropped;
}
Exemplo n.º 3
0
void AsyncPipeReader::close() {
  unregisterHandler();
  if (fd_ != NetworkSocket()) {
    changeHandlerFD(NetworkSocket());

    if (closeCb_) {
      closeCb_(fd_);
    } else {
      netops::close(fd_);
    }
    fd_ = NetworkSocket();
  }
}
Exemplo n.º 4
0
void AsyncPipeReader::close() {
  unregisterHandler();
  if (fd_ >= 0) {
    changeHandlerFD(-1);

    if (closeCb_) {
      closeCb_(fd_);
    } else {
      ::close(fd_);
    }
    fd_ = -1;
  }
}
Exemplo n.º 5
0
void AsyncPipeWriter::handleWrite() {
  DestructorGuard dg(this);
  assert(!queue_.empty());
  do {
    auto& front = queue_.front();
    folly::IOBufQueue& curQueue = front.first;
    DCHECK(!curQueue.empty());
    // someday, support writev.  The logic for partial writes is a bit complex
    const IOBuf* head = curQueue.front();
    CHECK(head->length());
#if _WIN32
    // On Windows you can't call write on a socket.
    ssize_t rc = folly::fileutil_detail::wrapNoInt(
        send_internal, fd_, head->data(), head->length());
#else
    ssize_t rc = folly::writeNoInt(fd_.toFd(), head->data(), head->length());
#endif
    if (rc < 0) {
      if (errno == EAGAIN || errno == EWOULDBLOCK) {
        // pipe is full
        VLOG(5) << "write blocked";
        registerHandler(EventHandler::WRITE);
        return;
      } else {
        failAllWrites(AsyncSocketException(
            AsyncSocketException::INTERNAL_ERROR, "write failed", errno));
        closeNow();
        return;
      }
    } else if (rc == 0) {
      registerHandler(EventHandler::WRITE);
      return;
    }
    curQueue.trimStart(size_t(rc));
    if (curQueue.empty()) {
      auto cb = front.second;
      queue_.pop_front();
      if (cb) {
        cb->writeSuccess();
      }
    } else {
      VLOG(5) << "partial write blocked";
    }
  } while (!queue_.empty());

  if (closeOnEmpty_) {
    closeNow();
  } else {
    unregisterHandler();
  }
}
Exemplo n.º 6
0
/*  
 *  unhookSSPInterrupt
 *      unregister SSP Interrupt function.
 */
unsigned short unhookSSPInterrupt(
    ssp_ctrl_t sspControl,
    void (*handler)(void)
)
{
    ssp_interrupt_t *pfnHandler, *prev, *pfnInterruptHandler;
    uint32_t mask;
    
    if (sspControl == SSP1)
        pfnInterruptHandler = ssp1IntHandlers;
    else
        pfnInterruptHandler = ssp0IntHandlers;

    /* Find the requested handle to unregister */
    for (pfnHandler = pfnInterruptHandler, prev = ((ssp_interrupt_t *)0); 
         pfnHandler != ((ssp_interrupt_t *)0); 
         prev = pfnHandler, pfnHandler = pfnHandler->next)
    {
        if (pfnHandler->handler == handler)
        {
            /* Remove the interrupt handler */
            if (prev == ((ssp_interrupt_t *)0))
            {
                pfnInterruptHandler = pfnHandler->next;
                
                /* Update the actual handler */
                if (sspControl == SSP1)
                    ssp1IntHandlers = pfnInterruptHandler;
                else
                    ssp0IntHandlers = pfnInterruptHandler;
            }
            else
            {
                prev->next = pfnHandler->next;
            }
            free(pfnHandler);
            
            /* If this was the last interrupt handler, remove the IRQ handler */
            if (pfnInterruptHandler == ((ssp_interrupt_t *)0))
            {
                unregisterHandler((sspControl == SSP1) ? ssp1ISR : ssp0ISR);
            }
            
            /* Success */
            return (0);
        }
    }

    /* Oops, handler is not registered */
    return (-1);
}
Exemplo n.º 7
0
void AsyncPipeWriter::closeNow() {
  VLOG(5) << "close now";
  if (!queue_.empty()) {
    failAllWrites(AsyncSocketException(
        AsyncSocketException::NOT_OPEN, "closed with pending writes"));
  }
  if (fd_ != NetworkSocket()) {
    unregisterHandler();
    changeHandlerFD(NetworkSocket());
    if (closeCb_) {
      closeCb_(fd_);
    } else {
      netops::close(fd_);
    }
    fd_ = NetworkSocket();
  }
}
Exemplo n.º 8
0
void AsyncUDPSocket::close() {
  eventBase_->dcheckIsInEventBaseThread();

  if (readCallback_) {
    auto cob = readCallback_;
    readCallback_ = nullptr;

    cob->onReadClosed();
  }

  // Unregister any events we are registered for
  unregisterHandler();

  if (fd_ != -1 && ownership_ == FDOwnership::OWNS) {
    ::close(fd_);
  }

  fd_ = -1;
}
Exemplo n.º 9
0
/*
 * This function un-register 2D Interrupt handler.
 */
int32_t unhookDEInterrupt(
    uint32_t deMask,
    void (*handler)(void)
)
{
    de_interrupt_t *pfnHandler, *prev;
    uint32_t mask;

    if (deMask == 0)
        mask = FIELD_SET(0, DE_STATUS, 2D, ACTIVE);
    else
        mask = FIELD_SET(0, DE_STATUS, CSC, ACTIVE);

    /* Find the requested handle to unregister */
    for (pfnHandler = pDEIntHandlers, prev = ((de_interrupt_t *)0); 
         pfnHandler != ((de_interrupt_t *)0); 
         prev = pfnHandler, pfnHandler = pfnHandler->next)
    {
        if ((pfnHandler->deMask == mask) && (pfnHandler->handler == handler))
        {
            /* Remove the interrupt handler */
            if (prev == ((de_interrupt_t *)0))
                pDEIntHandlers = pfnHandler->next;
            else
                prev->next = pfnHandler->next;

            free(pfnHandler);
            
            /* If this was the last interrupt handler, remove the IRQ handler */
            if (pDEIntHandlers == ((de_interrupt_t *)0))
                unregisterHandler(deISR);
            
            /* Success */
            return (0);
        }
    }

    /* Oops, handler is not registered */
    return (-1);
}
Exemplo n.º 10
0
EventHandler::~EventHandler() {
  unregisterHandler();
}
Exemplo n.º 11
0
void AsyncPipeReader::handlerReady(uint16_t events) noexcept {
  DestructorGuard dg(this);
  CHECK(events & EventHandler::READ);

  VLOG(5) << "AsyncPipeReader::handlerReady() this=" << this << ", fd=" << fd_;
  assert(readCallback_ != nullptr);

  while (readCallback_) {
    // - What API does callback support?
    const auto movable = readCallback_->isBufferMovable(); // noexcept

    // Get the buffer to read into.
    void* buf = nullptr;
    size_t buflen = 0;
    std::unique_ptr<IOBuf> ioBuf;

    if (movable) {
      ioBuf = IOBuf::create(readCallback_->maxBufferSize());
      buf = ioBuf->writableBuffer();
      buflen = ioBuf->capacity();
    } else {
      try {
        readCallback_->getReadBuffer(&buf, &buflen);
      } catch (const std::exception& ex) {
        AsyncSocketException aex(
            AsyncSocketException::BAD_ARGS,
            string("ReadCallback::getReadBuffer() "
                   "threw exception: ") +
                ex.what());
        failRead(aex);
        return;
      } catch (...) {
        AsyncSocketException aex(
            AsyncSocketException::BAD_ARGS,
            string("ReadCallback::getReadBuffer() "
                   "threw non-exception type"));
        failRead(aex);
        return;
      }
      if (buf == nullptr || buflen == 0) {
        AsyncSocketException aex(
            AsyncSocketException::INVALID_STATE,
            string("ReadCallback::getReadBuffer() "
                   "returned empty buffer"));
        failRead(aex);
        return;
      }
    }

    // Perform the read
#if _WIN32
    // On Windows you can't call read on a socket, so call recv instead.
    ssize_t bytesRead =
        folly::fileutil_detail::wrapNoInt(recv_internal, fd_, buf, buflen);
#else
    ssize_t bytesRead = folly::readNoInt(fd_.toFd(), buf, buflen);
#endif

    if (bytesRead > 0) {
      if (movable) {
        ioBuf->append(std::size_t(bytesRead));
        readCallback_->readBufferAvailable(std::move(ioBuf));
      } else {
        readCallback_->readDataAvailable(size_t(bytesRead));
      }
      // Fall through and continue around the loop if the read
      // completely filled the available buffer.
      // Note that readCallback_ may have been uninstalled or changed inside
      // readDataAvailable().
      if (static_cast<size_t>(bytesRead) < buflen) {
        return;
      }
    } else if (bytesRead < 0 && (errno == EAGAIN || errno == EWOULDBLOCK)) {
      // No more data to read right now.
      return;
    } else if (bytesRead < 0) {
      AsyncSocketException ex(
          AsyncSocketException::INVALID_STATE, "read failed", errno);
      failRead(ex);
      return;
    } else {
      assert(bytesRead == 0);
      // EOF

      unregisterHandler();
      AsyncReader::ReadCallback* callback = readCallback_;
      readCallback_ = nullptr;
      callback->readEOF();
      return;
    }
    // Max reads per loop?
  }
}
Exemplo n.º 12
0
MessageHandler::~MessageHandler()
{
    unregisterHandler(this);
}
Exemplo n.º 13
0
FileRegion::FileWriteRequest::FileReadHandler::~FileReadHandler() {
  CHECK(req_->readBase_->isInEventBaseThread());
  unregisterHandler();
  ::close(pipe_in_);
}
Exemplo n.º 14
0
	void EventManager::unregisterHandler(std::function<void(void*, Event*)> handler) {
		for(HandlerMap::iterator ite = handlers.begin(); ite != handlers.end(); ite++)
			unregisterHandler(ite->first, handler);
	}
Exemplo n.º 15
0
void AsyncPipeReader::handlerReady(uint16_t events) noexcept {
  DestructorGuard dg(this);
  CHECK(events & EventHandler::READ);

  VLOG(5) << "AsyncPipeReader::handlerReady() this=" << this << ", fd=" << fd_;
  assert(readCallback_ != nullptr);

  while (readCallback_) {
    // Get the buffer to read into.
    void* buf = nullptr;
    size_t buflen = 0;
    try {
      readCallback_->getReadBuffer(&buf, &buflen);
    } catch (const std::exception& ex) {
      AsyncSocketException aex(AsyncSocketException::BAD_ARGS,
                               string("ReadCallback::getReadBuffer() "
                                      "threw exception: ") + ex.what());
      failRead(aex);
      return;
    } catch (...) {
      AsyncSocketException ex(AsyncSocketException::BAD_ARGS,
                              string("ReadCallback::getReadBuffer() "
                                     "threw non-exception type"));
      failRead(ex);
      return;
    }
    if (buf == nullptr || buflen == 0) {
      AsyncSocketException ex(AsyncSocketException::INVALID_STATE,
                              string("ReadCallback::getReadBuffer() "
                                     "returned empty buffer"));
      failRead(ex);
      return;
    }

    // Perform the read
    ssize_t bytesRead = folly::readNoInt(fd_, buf, buflen);
    if (bytesRead > 0) {
      readCallback_->readDataAvailable(bytesRead);
      // Fall through and continue around the loop if the read
      // completely filled the available buffer.
      // Note that readCallback_ may have been uninstalled or changed inside
      // readDataAvailable().
      if (static_cast<size_t>(bytesRead) < buflen) {
        return;
      }
    } else if (bytesRead < 0 && (errno == EAGAIN || errno == EWOULDBLOCK)) {
      // No more data to read right now.
      return;
    } else if (bytesRead < 0) {
      AsyncSocketException ex(AsyncSocketException::INVALID_STATE,
                              "read failed", errno);
      failRead(ex);
      return;
    } else {
      assert(bytesRead == 0);
      // EOF

      unregisterHandler();
      AsyncReader::ReadCallback* callback = readCallback_;
      readCallback_ = nullptr;
      callback->readEOF();
      return;
    }
    // Max reads per loop?
  }
}
Exemplo n.º 16
0
void TunIntf::stop() {
  unregisterHandler();
}