protohack-0.cpp (1404B)
1 #include "inet.hpp" 2 3 #include <poll.h> 4 5 #include <algorithm> 6 #include <iostream> 7 #include <map> 8 9 int poll(std::span<struct pollfd> pfds, int timeout = INFTIM) 10 { 11 if (int n = ::poll(pfds.data(), pfds.size(), timeout); n != -1) 12 return n; 13 err(1, "poll"); 14 } 15 16 int main() 17 { 18 std::map<int, descriptor> clients; 19 auto incoming_socket = inet::listen(SOCK_STREAM); 20 std::cout << "Protohack 0: Smoke Test\n"; 21 22 for (;;) 23 { 24 size_t const pollen = clients.size() + 1; 25 pollfd events_buf[pollen]; 26 std::span events{events_buf, pollen}; 27 28 auto& socket_event = events.front(); 29 auto client_events = events.subspan(1); 30 31 socket_event = pollfd{incoming_socket, POLLIN, 0}; 32 33 std::transform(clients.cbegin(), clients.cend(), client_events.begin(), [](auto& c) { 34 return pollfd{c.second, POLLIN, 0}; 35 }); 36 37 int ready = poll(events); 38 39 if (socket_event.revents & POLLIN) 40 { 41 auto conn = inet::accept(incoming_socket); 42 clients[conn] = std::move(conn); 43 if (not --ready) 44 continue; 45 } 46 47 for (auto& ev : client_events) 48 { 49 if (~ev.revents & POLLIN) 50 continue; 51 52 char data_buf[0x1000]; 53 auto data = read(ev.fd, std::span{data_buf}); 54 55 if (data.empty()) 56 { 57 std::cout << "* " << ev.fd << " disconnected\n"; 58 clients.erase(ev.fd); 59 continue; 60 } 61 62 std::cout << "* " << ev.fd << ": " << data.size() << " bytes\n"; 63 write(ev.fd, data); 64 65 if (not --ready) 66 break; 67 } 68 } 69 }