Esempio n. 1
0
// Deletes the given port from the system port table.
void
delete_port(Port::Id id)
{
  if (port_table.find(id))
    port_table.dealloc(id);
}
Esempio n. 2
0
// TCP Port thread work function. Expects the internal port id to be passed
// as an argument, which is used to drive that port.
void*
tcp_work_fn(void* arg)
{
  // Grab a pointer to the port object you are driving.
  Port_tcp* self = (Port_tcp*)port_table.find(*((int*)arg));

  // Setup epoll.
  struct epoll_event event, event_list[10];
  struct sockaddr_in addr = self->dst_addr_;
  socklen_t slen = sizeof(addr);
  int sock_fd, conn_fd, epoll_fd, res;
  sock_fd = self->sock_fd_;

  if ((epoll_fd = epoll_create1(0)) == -1)
    perror(std::string("port[" + std::to_string(self->id()) +
      "] epoll_create").c_str());
  // Listen for input events.
  event.events = EPOLLIN | EPOLLET;
  event.data.fd = sock_fd;

  if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, sock_fd, &event) == -1)
    perror(std::string("port[" + std::to_string(self->id()) +
      "] epoll_ctl_add").c_str());

  // Run while the FD is valid.
  while (fcntl(sock_fd, F_GETFD) != EBADF) {
    res = epoll_wait(epoll_fd, event_list, 10, 1000);

    // Receive messages/report errors.
    if (res < 0) {
      perror(std::string("port[" + std::to_string(self->id()) +
        "]").c_str());
      continue;
    }
    else {
      for (int i = 0; i < res; i++) {
        if (event_list[i].data.fd == sock_fd) {
          // We have a new connection coming in.
          conn_fd = accept(sock_fd, (struct sockaddr*)&addr, &slen);
          if (conn_fd == -1) {
            perror(std::string("port[" + std::to_string(self->id()) +
              "]").c_str());
            continue;
          }
          else {
            // Set the socket to be non-blocking.
            int flags = fcntl(conn_fd, F_GETFL, 0);
            fcntl(conn_fd, F_SETFL, flags | O_NONBLOCK);
            // Add to the epoll set.
            event.events = EPOLLIN | EPOLLET;
            event.data.fd = conn_fd;
            if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, conn_fd, &event) == -1)
              perror(std::string("port[" + std::to_string(self->id()) +
                "]").c_str());
          }
        }
        else {
          // A message from a known client has been received. Process it.
          self->io_fd_ = event_list[i].data.fd;
          Context* cxt = self->recv();
          thread_pool.assign(new Task("pipeline", cxt));
        }
      }
    }
    // Send any packets buffered for TX.
    self->send();
  }
  return 0;
}