#ifndef SHARED_NET_HH_ #define SHARED_NET_HH_ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "shared/shared.hh" // Functions in this namespace are common network-related wrappers with error // checking. namespace shared { using addrinfo_t = std::shared_ptr; // for automatic freeaddrinfo call addrinfo_t make_addrinfo(const char* const address, const char* const port, const addrinfo&& hints); using socket_t = int; int make_socket(const addrinfo_t& info); int accept_socket(const socket_t& sock); void bind_socket(const socket_t sock, const addrinfo_t& info); void connect_socket(const socket_t sock, const addrinfo_t& info); void listen_socket(const socket_t sock); void close_socket(const socket_t sock); struct header { std::uint32_t size = 0; // size of packet, including header. std::uint32_t sequence; // sequence number of packet char command[3]; // command type, if \0\0\0 then it's an ack }; static_assert(std::is_trivially_copyable
::value, "header must be memcpy-able"); struct packet { header header; std::vector contents; }; // Our packets contents consist of data entries like so: // std::uint32_t | char[] | DATA // ^ size of data ^ name ^ data, which repeats for size length // Any packet may contain multiple, or zero, entries. The name can be any // length. This way we don't have to define structs with hardcoded length // limits, and we can use this format when sending anything, even files. // Numeric values will be encoded as strings and converted when necessary. using contents_t = std::unordered_map; void send_packet(const packet& packet, const socket_t& sock, const sockaddr_in& dest); void send_packet(const packet& packet, const socket_t& sock); packet contents_to_packet(const contents_t& contents, const char* const command); contents_t packet_to_contents(const packet& packet); // Recv's sockets, might return nullptr if no packet available. struct recv_packet_ret { sockaddr_in origin; struct packet packet; }; // non-blocking std::shared_ptr maybe_urecv_packet(const socket_t& sock); // blocking, will throw if timeout is elapsed std::shared_ptr urecv_packet(const socket_t& rsock, const bool& timeout = true); std::shared_ptr rrecv_packet(const socket_t& rsock, const bool& timeout = true); } // namespace shared #endif