#ifndef HOST_H #define HOST_H #include "sys.h" #include "sock.h" #define HOST_CHANNEL_ID_NIL (struct host_channel_id) { .gen = 0, .idx = 0 } #define HOST_CHANNEL_ID_ALL (struct host_channel_id) { .gen = U32_MAX, .idx = U32_MAX } struct buddy_ctx; struct host_snd_packet; struct host_channel_lookup_bin; struct host_rcv_buffer; enum host_cmd_kind { HOST_CMD_KIND_NONE, HOST_CMD_KIND_TRY_CONNECT, HOST_CMD_KIND_CONNECT_SUCCESS, HOST_CMD_KIND_DISCONNECT, HOST_CMD_KIND_HEARTBEAT, HOST_CMD_KIND_WRITE }; enum host_event_kind { HOST_EVENT_KIND_NONE, HOST_EVENT_KIND_CHANNEL_OPENED, HOST_EVENT_KIND_CHANNEL_CLOSED, HOST_EVENT_KIND_MSG }; enum host_write_flag { HOST_WRITE_FLAG_NONE = 0, HOST_WRITE_FLAG_RELIABLE = (1 << 0) }; struct host_cmd { enum host_cmd_kind kind; struct host_channel_id channel_id; u16 heartbeat_id; u16 heartbeat_ack_id; b32 write_reliable; struct string write_msg; struct host_cmd *next; }; struct host_event { enum host_event_kind kind; struct host_channel_id channel_id; struct string msg; struct host_event *next; }; struct host_event_list { struct host_event *first; struct host_event *last; }; struct host { struct arena *arena; struct sock *sock; struct buddy_ctx *buddy; /* For storing msg assembler data */ struct arena *cmd_arena; struct host_cmd *first_cmd; struct host_cmd *last_cmd; struct host_cmd *first_free_cmd; struct arena *channel_arena; struct host_channel *channels; struct host_channel *first_free_channel; u64 num_channels_reserved; struct host_snd_packet *first_free_packet; /* Allocated in `arena` */ struct host_msg_assembler *first_free_msg_assembler; /* Allocated in `arena` */ struct host_channel_lookup_bin *channel_lookup_bins; /* Allocated in `arena` */ u64 num_channel_lookup_bins; struct host_msg_assembler_lookup_bin *msg_assembler_lookup_bins; /* Allocated in `arena` */ u64 num_msg_assembler_lookup_bins; /* Double buffer for incoming data */ struct sys_mutex *rcv_buffer_write_mutex; struct host_rcv_buffer *rcv_buffer_read; struct host_rcv_buffer *rcv_buffer_write; u64 bytes_received; u64 bytes_sent; struct atomic_i32 receiver_thread_shutdown_flag; struct sys_thread *receiver_thread; }; /* ========================== * * Startup * ========================== */ struct host_startup_receipt { i32 _; }; struct host_startup_receipt host_startup(struct sock_startup_receipt *sock_sr); /* ========================== * * Host * ========================== */ struct host *host_alloc(u16 listen_port); void host_release(struct host *host); /* ========================== * * Queue * ========================== */ void host_queue_connect_to_address(struct host *host, struct sock_address connect_address); void host_queue_disconnect(struct host *host, struct host_channel_id channel_id); void host_queue_write(struct host *host, struct host_channel_id channel_id, struct string msg, u32 flags); /* ========================== * * Info * ========================== */ i64 host_get_channel_last_rtt_ns(struct host *host, struct host_channel_id channel_id); INLINE b32 host_channel_id_eq(struct host_channel_id a, struct host_channel_id b) { return a.idx == b.idx && a.gen == b.gen; } INLINE b32 host_channel_id_is_nil(struct host_channel_id id) { return id.gen == 0 && id.idx == 0; } /* ========================== * * Update * ========================== */ struct host_event_list host_update_begin(struct arena *arena, struct host *host); void host_update_end(struct host *host); #endif