| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192 | #include <stdint.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h> /* for sleep() */#include "civetweb.h"/* Global options for this example. */static const char WS_URL[] = "/wsURL";static const char *SERVER_OPTIONS[] =    {"listening_ports", "8081", "num_threads", "10", NULL, NULL};/* Define websocket sub-protocols. *//* This must be static data, available between mg_start and mg_stop. */static const char subprotocol_bin[] = "Company.ProtoName.bin";static const char subprotocol_json[] = "Company.ProtoName.json";static const char *subprotocols[] = {subprotocol_bin, subprotocol_json, NULL};static struct mg_websocket_subprotocols wsprot = {2, subprotocols};/* Exit flag for the server */volatile int g_exit = 0;/* User defined data structure for websocket client context. */struct tClientContext {	uint32_t connectionNumber;	uint32_t demo_var;};/* Handler for new websocket connections. */static intws_connect_handler(const struct mg_connection *conn, void *user_data){	(void)user_data; /* unused */	/* Allocate data for websocket client context, and initialize context. */	struct tClientContext *wsCliCtx =	    (struct tClientContext *)calloc(1, sizeof(struct tClientContext));	if (!wsCliCtx) {		/* reject client */		return 1;	}	static uint32_t connectionCounter = 0; /* Example data: client number */	wsCliCtx->connectionNumber = __sync_add_and_fetch(&connectionCounter, 1);	mg_set_user_connection_data(	    conn, wsCliCtx); /* client context assigned to connection */	/* DEBUG: New client connected (but not ready to receive data yet). */	const struct mg_request_info *ri = mg_get_request_info(conn);	printf("Client %u connected with subprotocol: %s\n",	       wsCliCtx->connectionNumber,	       ri->acceptedWebSocketSubprotocol);	return 0;}/* Handler indicating the client is ready to receive data. */static voidws_ready_handler(struct mg_connection *conn, void *user_data){	(void)user_data; /* unused */	/* Get websocket client context information. */	struct tClientContext *wsCliCtx =	    (struct tClientContext *)mg_get_user_connection_data(conn);	const struct mg_request_info *ri = mg_get_request_info(conn);	(void)ri; /* in this example, we do not need the request_info */	/* Send "hello" message. */	const char *hello = "{}";	size_t hello_len = strlen(hello);	mg_websocket_write(conn, MG_WEBSOCKET_OPCODE_TEXT, hello, hello_len);	/* DEBUG: New client ready to receive data. */	printf("Client %u ready to receive data\n", wsCliCtx->connectionNumber);}/* Handler indicating the client sent data to the server. */static intws_data_handler(struct mg_connection *conn,                int opcode,                char *data,                size_t datasize,                void *user_data){	(void)user_data; /* unused */	/* Get websocket client context information. */	struct tClientContext *wsCliCtx =	    (struct tClientContext *)mg_get_user_connection_data(conn);	const struct mg_request_info *ri = mg_get_request_info(conn);	(void)ri; /* in this example, we do not need the request_info */	/* DEBUG: Print data received from client. */	const char *messageType = "";	switch (opcode & 0xf) {	case MG_WEBSOCKET_OPCODE_TEXT:		messageType = "text";		break;	case MG_WEBSOCKET_OPCODE_BINARY:		messageType = "binary";		break;	case MG_WEBSOCKET_OPCODE_PING:		messageType = "ping";		break;	case MG_WEBSOCKET_OPCODE_PONG:		messageType = "pong";		break;	}	printf("Websocket received %lu bytes of %s data from client %u\n",	       (unsigned long)datasize,	       messageType,	       wsCliCtx->connectionNumber);	return 1;}/* Handler indicating the connection to the client is closing. */static voidws_close_handler(const struct mg_connection *conn, void *user_data){	(void)user_data; /* unused */	/* Get websocket client context information. */	struct tClientContext *wsCliCtx =	    (struct tClientContext *)mg_get_user_connection_data(conn);	/* DEBUG: Client has left. */	printf("Client %u closing connection\n", wsCliCtx->connectionNumber);	/* Free memory allocated for client context in ws_connect_handler() call. */	free(wsCliCtx);}intmain(int argc, char *argv[]){	/* Initialize CivetWeb library without OpenSSL/TLS support. */	mg_init_library(0);	/* Start the server using the advanced API. */	struct mg_callbacks callbacks = {0};	void *user_data = NULL;	struct mg_init_data mg_start_init_data = {0};	mg_start_init_data.callbacks = &callbacks;	mg_start_init_data.user_data = user_data;	mg_start_init_data.configuration_options = SERVER_OPTIONS;	struct mg_error_data mg_start_error_data = {0};	char errtxtbuf[256] = {0};	mg_start_error_data.text = errtxtbuf;	mg_start_error_data.text_buffer_size = sizeof(errtxtbuf);	struct mg_context *ctx =	    mg_start2(&mg_start_init_data, &mg_start_error_data);	if (!ctx) {		fprintf(stderr, "Cannot start server: %s\n", errtxtbuf);		mg_exit_library();		return 1;	}	/* Register the websocket callback functions. */	mg_set_websocket_handler_with_subprotocols(ctx,	                                           WS_URL,	                                           &wsprot,	                                           ws_connect_handler,	                                           ws_ready_handler,	                                           ws_data_handler,	                                           ws_close_handler,	                                           user_data);	/* Let the server run. */	printf("Websocket server running\n");	while (!g_exit) {		sleep(1);	}	printf("Websocket server stopping\n");	/* Stop server, disconnect all clients. Then deinitialize CivetWeb library.	 */	mg_stop(ctx);	mg_exit_library();}
 |