#ifndef DP_COMMON_H #define DP_COMMON_H #include #include #include #include "dp_types.h" #include "log.h" #ifdef __cplusplus extern "C" { #endif #define dp_fatal(...) log_fatal(__VA_ARGS__) typedef pid_t doomid_t; // unique id for each doom instance typedef u16 dmt_t; // for DP_MessageType values #define DoomScreenWidth 320 #define DoomScreenHeight 240 #define DoomBytesPerPixel 4 #define DoomFramePitch (DoomScreenWidth * DoomBytesPerPixel) #define DoomFrameSize (DoomScreenWidth * DoomScreenHeight * DoomBytesPerPixel) #define DoomMaxEvents 64 typedef enum DP_MessageType { DP_MT_Invalid, DP_MT_DoomState, // dooms can publish their state (MsgDoomState) DP_MT_DoomFrame, // doom framebuffer data DP_MT_Command, // DP_DoomCommand message to a specific doom instance DP_MT_McstCommand, // DP_DoomCmannd multicast message to all dooms DP_MT_Inputs, // controller publishes input state for dooms to consume DP_MT_COUNT } DP_MessageType; typedef enum DP_DoomState { DP_DS_Unknown, DP_DS_Ready, DP_DS_Running, DP_DS_Endoom, DP_DS_COUNT, } DP_DoomState; typedef enum DP_DoomCommand { DP_DC_Noop, DP_DC_RunDoom, DP_DC_Endoom, DP_DC_COUNT, } DP_DoomCommand; typedef struct { dmt_t msgType; } MessageBase; typedef struct __attribute__((packed, aligned(4))) { MessageBase head; doomid_t doomId; DP_DoomState doomState; } MsgDoomState; typedef struct __attribute__((packed, aligned(4))) { MessageBase head; doomid_t doomId; u8 frame[DoomFrameSize]; } MsgDoomFrame; typedef struct __attribute__((packed, aligned(4))) { MessageBase head; doomid_t doomId; DP_DoomCommand cmd; } MsgCommand; typedef struct __attribute__((packed, aligned(4))) { MessageBase head; DP_DoomCommand cmd; } MsgMcstCommand; // Doom input event types (from d_event.h). typedef enum doom_evtype_t { DP_ev_keydown, DP_ev_keyup, DP_ev_mouse, DP_ev_joystick } dp_doom_evtype_t; // Doom event structure (from d_event.h). typedef struct { dp_doom_evtype_t type; int data1; // keys / mouse/joystick buttons int data2; // mouse/joystick x move int data3; // mouse/joystick y move } dp_doom_event_t; typedef struct __attribute__((packed, aligned(4))) { MessageBase head; u8 eventCount; dp_doom_event_t events[DoomMaxEvents]; } MsgInputs; void dp_errno_fatal(const char *const msg); void dp_nng_fatal(const char *const msg, int rv); void dp_nng_init_limits(int ncpu_max, int pool_thread_limit_max, int resolv_thread_limit); static inline bool dp_nng_is_timeout(int res) { return res == NNG_ETIMEDOUT || res == NNG_EAGAIN; } // Controller listens, dooms dial. static const char *const CtrlUrlIpc = "ipc://666_ctrl.socket"; // controller publishes here static const char *const DoomUrlIpc = "ipc://666_doom.socket"; // dooms publish here static const char *const CtrlUrlTcp = "tcp://:42666"; // controller publishes here static const char *const DoomUrlTcp = "tcp://:42667"; // dooms publish here static const int CtrlPort = 42666; // controller publishes on this port static const int DoomPort = 42667; // dooms publish here nng_socket make_doom_pub(const char *url); nng_socket make_doom_sub(const char *url); int dp_recv_new_msg(nng_socket sock, nng_msg **msg_ptr); int dp_recv_new_msg_nonblock(nng_socket sock, nng_msg **msg_ptr); int dp_recv_new_msg_flags(nng_socket sock, nng_msg **msg_ptr, int flags); static inline void *dp_nng_msg_body_if_size_ge(nng_msg *msg, size_t size, bool isFatal) { if (nng_msg_len(msg) >= size) return nng_msg_body(msg); if (isFatal) dp_fatal("message body too short"); return NULL; } // Size checked cast of message body to type, fatal version #define DP_NNG_BODY_AS(msg, ToType) (ToType *) dp_nng_msg_body_if_size_ge(msg, sizeof(ToType), true) // Size checked cast of message body to type, non-fatal version #define DP_NNG_BODY_AS_NF(msg, ToType) (ToType *) dp_nng_msg_body_if_size_ge(msg, sizeof(ToType), false) extern const char *const DP_DoomState_Strings[]; static inline const char *doomstate_to_string(DP_DoomState ds) { return DP_DoomState_Strings[ds]; } #ifdef __cplusplus } #endif #endif /* DP_COMMON_H */