/* * Copyright (c) 2002, Stefan Farfeleder * $Id: network.h,v 1.4 2002/09/10 22:29:38 stefan Exp $ */ #ifndef JFK_NETWORK_H #define JFK_NETWORK_H #include #include #include #include /* So we can avoid including system-specific headers. */ #if defined(HAVE_POLL) struct pollfd; #endif struct sockaddr; namespace JFK { /* This is actually an implementation detail, but I see no way but putting * it here. */ class host { friend class network_client; friend class network_server; public: host() : fd(-1), lost(false), written_chars(0), enabled(false) {} host(int fd_) : fd(fd_), lost(false), written_chars(0), enabled(false) {} private: int fd; bool lost; /* Set to true if an error occured. */ std::queue writeq; /* Lines to send to the peer */ size_t written_chars; /* Number of chars of writeq.front() already written */ std::queue readq; /* Lines already received from the peer */ std::string incomplete; /* A yet incompletely recieved line */ bool enabled; /* disabled clients aren't included in TO_ALL */ void flush_writeq(); /* Try to write lines from writeq to the peer. On failure lost is set to true. */ void fill_readq(); /* Try to read lines from the peer and store them into readq. */ }; class network_client { public: /* Connect to 'server' at port 'port'. */ network_client(const std::string& servername, const std::string& service); ~network_client(); /* Send 'msg' to the server. */ void send(const std::string& msg); /* If true is returned, *msg contains a line from the server. */ bool receive(std::string* msg); /* Do the actual work. */ void dispatch(); private: host server; }; extern const int TO_ALL; /* Special value for 'to' in network_server::send() */ class network_server { public: network_server(const std::string& service); ~network_server(); /* If true is returned, 'hostname' is a new client with the id 'id'. */ bool new_client(std::string* hostname, int* id); /* If true is returned, client 'id' has/was disconnected. */ bool lost_client(int* id); /* Get rid of client 'id'. */ void remove_client(int id); void enable_client(int id); void disable_client(int id); /* Passing TO_ALL to 'to' means sending msg to all clients. */ void send(const std::string& msg, int to); bool receive(std::string* msg, int from); void dispatch(); private: typedef std::vector::iterator client_iter; client_iter find_id(std::vector& vh, int id); int listenfd; std::vector client; #if defined(HAVE_POLL) pollfd* fds; /* Structs for poll() */ size_t fd_alloc; /* Number of pollfd's allocated */ #endif sockaddr* sa; /* Memory for accept() */ }; } #endif