45#define ALLEGRO_UNSTABLE 1
60#define NETMSG_CHAT 100
107 NETWORK* cn = (NETWORK*)node->data.ptr;
109 char entry[256] =
"";
110 snprintf(entry, sizeof(entry),
"%s:%s (sock %d)",
111 cn->link.ip ? cn->link.ip :
"?",
112 cn->link.port ? cn->link.port :
"?",
114 n_gui_listbox_add_item(gui, listbox_clients, entry);
118 char header[64] =
"";
133 if (!msg)
return NULL;
174 if (!ok && out_text) {
192 if (!text || text[0] ==
'\0')
return;
195 if (!msg_str)
return;
200 char logbuf[512] =
"";
201 snprintf(logbuf,
sizeof(logbuf),
"[server] %s", text);
209 char logbuf[512] =
"";
210 snprintf(logbuf,
sizeof(logbuf),
"[me] %s", text);
224 N_STR* incoming = NULL;
228 char logbuf[512] =
"";
229 snprintf(logbuf,
sizeof(logbuf),
"[%s] %s", prefix, text);
249 " Server: ex_gui_network -p PORT\n"
250 " Client: ex_gui_network -s ADDRESS -p PORT\n"
252 " -s addr : server address to connect to (client mode)\n"
253 " -p port : port number\n"
254 " -V level : log level (LOG_DEBUG, LOG_INFO, LOG_ERR)\n"
258int main(
int argc,
char** argv) {
262 while ((
getoptret = getopt(argc, argv,
"hs:p:V:")) != EOF) {
271 if (!strcmp(
"LOG_DEBUG", optarg))
273 else if (!strcmp(
"LOG_INFO", optarg))
275 else if (!strcmp(
"LOG_NOTICE", optarg))
277 else if (!strcmp(
"LOG_ERR", optarg))
289 fprintf(stderr,
"Port is required. Use -p PORT\n");
301 al_install_keyboard();
303 al_init_primitives_addon();
304 al_init_font_addon();
306 al_init_image_addon();
308 al_set_new_display_flags(ALLEGRO_OPENGL | ALLEGRO_WINDOWED);
314 al_set_window_title(
display,
mode == 0 ?
"GUI Network - Server" :
"GUI Network - Client");
316 ALLEGRO_FONT* font = al_create_builtin_font();
317 ALLEGRO_EVENT_QUEUE* event_queue = al_create_event_queue();
318 ALLEGRO_TIMER* timer = al_create_timer(1.0 / 30.0);
320 al_register_event_source(event_queue, al_get_display_event_source(
display));
321 al_register_event_source(event_queue, al_get_keyboard_event_source());
322 al_register_event_source(event_queue, al_get_mouse_event_source());
323 al_register_event_source(event_queue, al_get_timer_event_source(timer));
365 chat_log_add(
"Failed to allocate server connection pool");
370 snprintf(buf,
sizeof(buf),
"Server listening on port %s",
port_str);
392 al_start_timer(timer);
397 al_wait_for_event(event_queue, &ev);
399 if (ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE) {
403 if (ev.type == ALLEGRO_EVENT_KEY_DOWN && ev.keyboard.keycode == ALLEGRO_KEY_ESCAPE) {
407 if (ev.type == ALLEGRO_EVENT_TIMER) {
418 chat_log_add(
"Failed to add new client to pool, closing connection");
422 snprintf(buf,
sizeof(buf),
"Client connected from %s (total: %zu)",
440 NETWORK* cn = (NETWORK*)node->data.ptr;
444 netw_get_state(cn, &state, &thr_state);
445 if (state & NETW_EXITED || state & NETW_ERROR || state & NETW_EXIT_ASKED) {
446 list_push(dead_clients, cn, NULL);
448 poll_network_msgs(cn, cn->link.ip ? cn->link.ip :
"client");
456 char disc_buf[128] =
"";
457 snprintf(disc_buf,
sizeof(disc_buf),
"Client %s:%s disconnected",
489 if (redraw && al_is_event_queue_empty(event_queue)) {
491 al_clear_to_color(al_map_rgb(40, 40, 50));
507 if (clients_to_close) {
509 NETWORK* cn = (NETWORK*)node->data.ptr;
511 list_push(clients_to_close, cn, NULL);
520 n_log(
LOG_ERR,
"failed to allocate client list for pool cleanup; pool clients may leak");
530 al_destroy_font(font);
531 al_destroy_timer(timer);
532 al_destroy_event_queue(event_queue);
ALLEGRO_DISPLAY * display
N_STR * build_chat_msg(const char *text)
build a chat network message
static NETWORK * netw_server
static int textarea_input
void poll_network_msgs(NETWORK *netw, const char *prefix)
process incoming messages on a single network connection
void refresh_clients_list(void)
refresh the connected clients listbox (server only)
static char * server_addr
static int lbl_clients_header
void on_send_click(int widget_id, void *user_data)
send button callback
static NETWORK * netw_client
void chat_log_add(const char *text)
add a line to the chat log listbox
static int listbox_clients
static NETWORK_POOL * pool
int decode_chat_msg(N_STR *str, char **out_text)
decode a received chat message
NETWORK * netw
Network for server mode, accepting incomming.
#define FreeNoLog(__ptr)
Free Handler without log.
#define Free(__ptr)
Free Handler to get errors.
void n_gui_set_display_size(N_GUI_CTX *ctx, float w, float h)
Set the display (viewport) size for global scrollbar computation.
#define N_GUI_ALIGN_LEFT
left aligned text
void n_gui_textarea_set_text(N_GUI_CTX *ctx, int widget_id, const char *text)
set the text content of a textarea widget
void n_gui_label_set_text(N_GUI_CTX *ctx, int widget_id, const char *text)
set the text of a label widget
int n_gui_add_listbox(N_GUI_CTX *ctx, int window_id, float x, float y, float w, float h, int selection_mode, void(*on_select)(int, int, int, void *), void *user_data)
Add a listbox widget.
int n_gui_process_event(N_GUI_CTX *ctx, ALLEGRO_EVENT event)
Process an allegro event through the GUI system.
int n_gui_add_label(N_GUI_CTX *ctx, int window_id, const char *text, float x, float y, float w, float h, int align)
Add a static text label.
#define N_GUI_WIN_FIXED_POSITION
disable window dragging (default:enable)
#define N_GUI_SELECT_NONE
no selection allowed (display only)
int n_gui_listbox_add_item(N_GUI_CTX *ctx, int widget_id, const char *text)
add an item to a listbox widget
void n_gui_draw(N_GUI_CTX *ctx)
Draw all visible windows and their widgets.
void n_gui_button_set_keycode(N_GUI_CTX *ctx, int widget_id, int keycode, int modifiers)
Bind a keyboard key with optional modifier requirements to a button.
int n_gui_add_window(N_GUI_CTX *ctx, const char *title, float x, float y, float w, float h)
Add a new pseudo-window to the context.
N_GUI_CTX * n_gui_new_ctx(ALLEGRO_FONT *default_font)
Create a new GUI context.
void n_gui_listbox_clear(N_GUI_CTX *ctx, int widget_id)
remove all items from a listbox widget
void n_gui_destroy_ctx(N_GUI_CTX **ctx)
Destroy a GUI context and all its windows/widgets.
const char * n_gui_textarea_get_text(N_GUI_CTX *ctx, int widget_id)
get the text content of a textarea widget
#define N_GUI_SHAPE_ROUNDED
rounded rectangle shape
void n_gui_window_set_flags(N_GUI_CTX *ctx, int window_id, int flags)
Set feature flags on a window.
int n_gui_add_textarea(N_GUI_CTX *ctx, int window_id, float x, float y, float w, float h, int multiline, size_t char_limit, void(*on_change)(int, const char *, void *), void *user_data)
Add a text area widget.
int n_gui_add_button(N_GUI_CTX *ctx, int window_id, const char *label, float x, float y, float w, float h, int shape, void(*on_click)(int, void *), void *user_data)
Add a button widget to a window.
#define N_GUI_WIN_RESIZABLE
enable user-resizable window with a drag handle at bottom-right
The top-level GUI context that holds all windows.
#define HT_FOREACH(__ITEM_, __HASH_,...)
ForEach macro helper.
#define UNLIMITED_LIST_ITEMS
flag to pass to new_generic_list for an unlimited number of item in the list.
#define list_foreach(__ITEM_, __LIST_)
ForEach macro helper, safe for node removal during iteration.
int list_destroy(LIST **list)
Empty and Free a list container.
LIST * new_generic_list(size_t max_items)
Initialiaze a generic list container to max_items pointers.
#define MAX_LIST_ITEMS
flag to pass to new_generic_list for the maximum possible number of item in a list
Structure of a generic LIST container.
#define n_log(__LEVEL__,...)
Logging function wrapper to get line and func.
#define LOG_DEBUG
debug-level messages
#define LOG_ERR
error conditions
void set_log_level(const int log_level)
Set the global log level value ( static int LOG_LEVEL )
#define LOG_NOTICE
normal but significant condition
#define LOG_INFO
informational
#define free_nstr(__ptr)
free a N_STR structure and set the pointer to NULL
N_STR * nstrdup(N_STR *str)
Duplicate a N_STR.
A box including a string and his lenght.
int get_str_from_msg(NETW_MSG *msg, char **value)
Get a string from a message string list.
int add_strdup_to_msg(NETW_MSG *msg, const char *str)
Add a copy of char *str to the string list in the message.
NETW_MSG * make_msg_from_str(N_STR *str)
Make a single message of the string.
N_STR * make_str_from_msg(NETW_MSG *msg)
Make a single string of the message.
int create_msg(NETW_MSG **msg)
Create a NETW_MSG *object.
int add_int_to_msg(NETW_MSG *msg, int value)
Add an int to the int list int the message.
int delete_msg(NETW_MSG **msg)
Delete a NETW_MSG *object.
int get_int_from_msg(NETW_MSG *msg, int *value)
Get an int from a message int list.
network message, array of char and int
char * ip
ip of the connected socket
N_SOCKET link
networking socket
char * port
port of socket
HASH_TABLE * pool
table of clients
N_STR * netw_get_msg(NETWORK *netw)
Get a message from aimed NETWORK.
int netw_add_msg(NETWORK *netw, N_STR *msg)
Add a message to send in aimed NETWORK.
NETWORK_POOL * netw_new_pool(size_t nb_min_element)
return a new network pool of nb_min_element
int netw_make_listening(NETWORK **netw, char *addr, char *port, int nbpending, int ip_version)
Make a NETWORK be a Listening network.
int netw_start_thr_engine(NETWORK *netw)
Start the NETWORK netw Threaded Engine.
int netw_destroy_pool(NETWORK_POOL **netw_pool)
free a NETWORK_POOL *pool
size_t netw_pool_nbclients(NETWORK_POOL *netw_pool)
return the number of networks in netw_pool
NETWORK * netw_accept_from_ex(NETWORK *from, size_t send_list_limit, size_t recv_list_limit, int blocking, int *retval)
make a normal 'accept' .
#define NETWORK_IPALL
Flag for auto detection by OS of ip version to use.
int netw_pool_broadcast(NETWORK_POOL *netw_pool, const NETWORK *from, N_STR *net_msg)
add net_msg to all network in netork pool
int netw_get_state(NETWORK *netw, uint32_t *state, int *thr_engine_status)
Get the state of a network.
int netw_close(NETWORK **netw)
Closing a specified Network, destroy queues, free the structure.
int netw_set_blocking(NETWORK *netw, unsigned long int is_blocking)
Modify blocking socket mode.
int netw_connect(NETWORK **netw, char *host, char *port, int ip_version)
Use this to connect a NETWORK to any listening one, unrestricted send/recv lists.
int netw_pool_add(NETWORK_POOL *netw_pool, NETWORK *netw)
add a NETWORK *netw to a NETWORK_POOL *pool
int netw_pool_remove(NETWORK_POOL *netw_pool, NETWORK *netw)
remove a NETWORK *netw to a NETWORK_POOL *pool
structure of a network pool
Common headers and low-level functions & define.
GUI system: buttons, sliders, text areas, checkboxes, scrollbars, dropdown menus, windows.
Network messages , serialization tools.
N_STR and string function declaration.