// Deletes the given port from the system port table. void delete_port(Port::Id id) { if (port_table.find(id)) port_table.dealloc(id); }
// 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; }