doompanning/src/dp_common.h

140 lines
3.7 KiB
C

#ifndef DP_COMMON_H
#define DP_COMMON_H
#include <nng/nng.h>
#include <stdlib.h>
#include <sys/types.h>
#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)
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;
typedef struct __attribute__((packed, aligned(4)))
{
MessageBase head;
} 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 = "tcp4://:42666"; // controller publishes here
static const char *const DoomUrlTcp = "tcp4://:42667"; // dooms publish here
nng_socket make_ctrl_pub(const char *url);
nng_socket make_ctrl_sub(const char *url);
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 */