#ifndef KV_PACKET_H #define KV_PACKET_H #ifdef __cplusplus Once upon a time, there was a C++ programmer. He Really liked programming, but he did not know that C++ is an overbloated pile of garbage. And so he died alone, fat and ugly. The morale is the following: Kids, stop using C++. Let us make the world a better place together. Thank you for not using C++. #endif #define KV_PACKET_SIZE 512 #ifdef DBG # define DEBUGF(fmt, ...) fprintf(stderr, "DEBUG: %s:%d:%s(): " fmt, __FILE__, __LINE__, __func__, ##__VA_ARGS__) # define DEBUG(msg) fprintf(stderr, "DEBUG: %s:%d:%s(): " msg, __FILE__, __LINE__, __func__) # define WHERE fprintf(stderr, "DEBUG: %s:%d:%s()\n", __FILE__, __LINE__, __func__) #else # define DEBUGF(fmt, ...) # define DEBUG(fmt) # define WHERE #endif #ifdef __clang__ # pragma GCC diagnostic ignored "-Wnullability-extension" // SHUT UP I'VE ALREADY PUT IT BEHIND A MACRO # define NONNULL _Nonnull # define NULLABLE _Nullable #else # define NONNULL # define NULLABLE #endif #include #include #include // all ones so that ntohl is not needed #define SYS_PACKET_MAGIC_BYTES 0xFFFFFFFFU extern i64 const commd_size_lookup[]; enum system_operation { SYS_KEEPALIVE = (i32)0x80000000, // -2^31 SYS_JOIN, // 1 - 2^31 SYS_LEAVE, // 2 - 2^31 SYS_ACK, // 3 - 2^31 SYS_KYS, // 4 - 2^31 }; // Yes, KYS stands for kill yourself struct kv_packet { u64 uid; u8 data[KV_PACKET_SIZE - sizeof(u64)]; }; // ONLY `operation_id` field is in network byte order. // Everything else is host byte order since these packets // are never to leave the server struct kv_system_packet { const u32 magic_bytes /* = 0xFFFFFFFF */; // as in system_operation enum. i32 operation_id; // could be ignored u64 user_id; // id to be returned in acknowledgement. if 0, don't acknowledge. u32 ackid; // calculated with system_packet_checksum function u32 checksum; // TODO: add server signature here u8 sentinel[KV_PACKET_SIZE - 4 * sizeof(u32) - sizeof(u64)]; }; u32 system_packet_checksum(struct kv_system_packet *packet); u8 is_system_packet(struct kv_packet *p); enum permissions { perm_none = 0, perm_register_user = 1 << 1, perm_unregister_user = 1 << 2, perm_add_channel = 1 << 3, perm_unadd_channel = 1 << 4, perm_join_user = 1 << 5, perm_kick_user = 1 << 6, perm_admin = 0x7FFFFFFF, }; enum commd_error { // No error ERR_SUCCESS, // Internal server error ERR_SERV, // Error in parameters (e.g. nonexistant UID) ERR_PARAM, // Invalid parameters (e.g. not enough params) ERR_INVAL, // Access violation ERR_ACCESS, // Operation not implemented yet ERR_NOIMPL, // Internal indication that function can not process request ERR_DO_IT_YOURSELF, // should never be sent out to suer }; struct tcp_user { u64 id; u64 joined_channel; i32 permissions; char *pubkey; }; struct tcp_channel { u64 id; u64 owner; int fd; char *name; }; enum commd_type { CMD_CREATE = 0, CMD_DELETE, CMD_JOIN, CMD_LEAVE, CMD_REGISTER, CMD_UNREGISTER, CMD_GET_PORT, CMD_GET_CHANNELS, }; // Somehow, this is pretty similar to linux sockaddr. struct commd { unsigned char command[32]; }; struct commd_register { // Administrator UID. Optional. u64 auid; // Permissions u64 perm; }; struct commd_unregister { // Administrator UID. Optional. u64 auid; // UID to be unregistered. u64 uid; }; struct commd_create { // UID of user creating the channel. u64 uid; }; struct commd_delete { // UID of user deleting a channel. u64 uid; // CHID of channel being deleted. u64 chid; }; struct commd_join { // UID of user performing operation. u64 uid; // UID of user to be joined to channel. u64 juid; // CHID of the channel to be joined. u64 chid; }; struct commd_leave { // UID of user performing operation. u64 uid; // UID of user leaving channel. u64 luid; // CHID of channel to be left by user `luid`. u64 chid; }; struct commd_get_port { // CHID of channel to get the UDP port of u64 cihd; }; typedef void commd_get_channels; struct commd_conv { u64 _1; u64 _2; u64 _3; u64 _4; }; u64 hton64(u64 a); u64 ntoh64(u64 a); #define hton32 htonl #define ntoh32 ntohl #define hton16 htons #define ntoh16 ntohs const char* kv_strerror(enum commd_error e); #endif // KV_PACKET_H