int main(int argc, char* argv[]) { // Configure the switch address. Address addr(Ipv4_addr::any, 9000); Terminator term(0); Acceptor acc(addr); // Register default service handlers. // FIXME: nlogn lookup for file descriptors is slow. Handler_map handlers; handlers.insert({term.fd(), &term}); handlers.insert({acc.fd(), &acc}); bool done = false; while (not done) { int maxfd = (*--handlers.end()).second->fd() + 1; // Build the wait set. // // TODO: We should only have to do this if the handler set has // changed or if a handler is registered for a new event. Resource_set wait; register_handlers(wait, handlers); // Create the dispatch set. The dispatch set is modified // by select to indicate which files have events. Resource_set disp = wait; // Select events. Selector s(maxfd, &disp); int nev = s(); // The close set is the set of handlers whid Resource_set close; // Handle events for (const auto& x : handlers) { Handler* h = x.second; if (disp.test(h->fd())) { Result r = h->on_read(); if (r == STOP) close.insert(h->fd()); else if (r == EXIT) done = true; } } // Close any handlers that need to be destroyed. for (int i = 0; i < nev; ++i) { if (close.test(i)) handlers[i]->close(); } } // TODO: Actually clean up resources. /* // Create the accept socket. Address addr(Ipv4_addr::any, 9001); Socket acc(Socket::IP4, Socket::TCP); acc.bind(addr); acc.listen(); int maxfd = acc.fd() + 1; while (1) { Resource_set reads; Resource_set writes; // Build the read/write sets reads.insert(0); reads.insert(acc); for (const auto& x : cm) reads.insert(x.second.socket()); // Select which files are available and which are not. std::cout << maxfd << " -- " << reads.test(0) << '\n'; Selector s(maxfd, reads, writes); s(); // Read from stdin to see if it's been closed. if (reads.test(0)) { char c; if (::read(0, &c, 1) <= 0) break; } // Check the accept first if (reads.test(acc)) { // Accept the connection, and spin up a new service. Socket s = acc.accept(); int fd = s.fd(); cm.emplace(fd, std::move(s)); // Update the maximum fd. maxfd = fd + 1; } // Iterate over over the connections to see if any can // actually be read. for (auto& x : cm) { Connection& c = x.second; bool erase = false; // Maybe cause a read. if (reads.test(c.socket())) erase |= c.read(); // Maybe cause a write. if (reads.test(c.socket())) erase |= c.write(); // Cleanup the handler. if (erase) cm.erase(x.first); } } */ return 0; }
void register_handler(Resource_set& rs, Handler& h) { rs.insert(h.fd()); }