Example #1
0
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;
}
Example #2
0
void
register_handler(Resource_set& rs, Handler& h) {
  rs.insert(h.fd());
}