diff options
| author | Nicolas James <Eele1Ephe7uZahRie@tutanota.com> | 2025-02-13 18:00:17 +1100 |
|---|---|---|
| committer | Nicolas James <Eele1Ephe7uZahRie@tutanota.com> | 2025-02-13 18:00:17 +1100 |
| commit | 98cef5e9a772602d42acfcf233838c760424db9a (patch) | |
| tree | 5277fa1d7cc0a69a0f166fcbf10fd320f345f049 /comp3331/server/src/shared/net.hh | |
initial commit
Diffstat (limited to 'comp3331/server/src/shared/net.hh')
| -rw-r--r-- | comp3331/server/src/shared/net.hh | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/comp3331/server/src/shared/net.hh b/comp3331/server/src/shared/net.hh new file mode 100644 index 0000000..b17ca1f --- /dev/null +++ b/comp3331/server/src/shared/net.hh @@ -0,0 +1,87 @@ +#ifndef SHARED_NET_HH_ +#define SHARED_NET_HH_ + +#include <algorithm> +#include <arpa/inet.h> +#include <chrono> +#include <cstdint> +#include <cstring> +#include <errno.h> +#include <fcntl.h> +#include <memory> +#include <netdb.h> +#include <optional> +#include <stdexcept> +#include <string.h> +#include <sys/ioctl.h> +#include <sys/socket.h> +#include <sys/types.h> +#include <thread> +#include <type_traits> +#include <unistd.h> +#include <unordered_map> +#include <vector> + +#include "shared/shared.hh" + +// Functions in this namespace are common network-related wrappers with error +// checking. +namespace shared { + +using addrinfo_t = std::shared_ptr<addrinfo>; // 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<header>::value, + "header must be memcpy-able"); +struct packet { + header header; + std::vector<char> 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<std::string, std::string>; +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<recv_packet_ret> maybe_urecv_packet(const socket_t& sock); +// blocking, will throw if timeout is elapsed +std::shared_ptr<recv_packet_ret> urecv_packet(const socket_t& rsock, + const bool& timeout = true); +std::shared_ptr<packet> rrecv_packet(const socket_t& rsock, + const bool& timeout = true); + +} // namespace shared + +#endif |
