project_files/frontlib/ipc/gameconn.c
changeset 7234 613998625a3c
parent 7230 240620f46dd7
child 7271 5608ac657362
equal deleted inserted replaced
7230:240620f46dd7 7234:613998625a3c
     1 #include "gameconn.h"
     1 #include "gameconn.h"
     2 #include "ipcconn.h"
     2 #include "ipcbase.h"
     3 #include "ipcprotocol.h"
     3 #include "ipcprotocol.h"
     4 #include "../util/logging.h"
     4 #include "../util/logging.h"
     5 #include "../util/util.h"
     5 #include "../util/util.h"
     6 #include "../hwconsts.h"
     6 #include "../hwconsts.h"
     7 #include <stdbool.h>
     7 #include <stdbool.h>
    13 	CONNECTED,
    13 	CONNECTED,
    14 	FINISHED
    14 	FINISHED
    15 } gameconn_state;
    15 } gameconn_state;
    16 
    16 
    17 struct _flib_gameconn {
    17 struct _flib_gameconn {
    18 	flib_ipcconn *connection;
    18 	flib_ipcbase *ipcBase;
    19 	flib_vector *configBuffer;
    19 	flib_vector *configBuffer;
    20 	flib_vector *demoBuffer;
    20 	flib_vector *demoBuffer;
    21 	char *playerName;
    21 	char *playerName;
    22 
    22 
    23 	gameconn_state state;
    23 	gameconn_state state;
    36 	void *onChatCtx;
    36 	void *onChatCtx;
    37 
    37 
    38 	void (*onGameRecordedCb)(void *context, const uint8_t *record, int size, bool isSavegame);
    38 	void (*onGameRecordedCb)(void *context, const uint8_t *record, int size, bool isSavegame);
    39 	void *onGameRecordedCtx;
    39 	void *onGameRecordedCtx;
    40 
    40 
    41 	void (*onNetMessageCb)(void *context, const uint8_t *em, int size);
    41 	void (*onEngineMessageCb)(void *context, const uint8_t *em, int size);
    42 	void *onNetMessageCtx;
    42 	void *onEngineMessageCtx;
    43 
    43 
    44 	bool running;
    44 	bool running;
    45 	bool destroyRequested;
    45 	bool destroyRequested;
    46 };
    46 };
    47 
    47 
    50 static void defaultCallback_onErrorMessage(void* context, const char *msg) {
    50 static void defaultCallback_onErrorMessage(void* context, const char *msg) {
    51 	flib_log_w("Error from engine (no callback set): %s", msg);
    51 	flib_log_w("Error from engine (no callback set): %s", msg);
    52 }
    52 }
    53 static void defaultCallback_onChat(void* context, const char *msg, bool teamchat) {}
    53 static void defaultCallback_onChat(void* context, const char *msg, bool teamchat) {}
    54 static void defaultCallback_onGameRecorded(void *context, const uint8_t *record, int size, bool isSavegame) {}
    54 static void defaultCallback_onGameRecorded(void *context, const uint8_t *record, int size, bool isSavegame) {}
    55 static void defaultCallback_onNetMessage(void *context, const uint8_t *em, int size) {}
    55 static void defaultCallback_onEngineMessage(void *context, const uint8_t *em, int size) {}
    56 
    56 
    57 static void clearCallbacks(flib_gameconn *conn) {
    57 static void clearCallbacks(flib_gameconn *conn) {
    58 	conn->onConnectCb = &defaultCallback_onConnect;
    58 	conn->onConnectCb = &defaultCallback_onConnect;
    59 	conn->onDisconnectCb = &defaultCallback_onDisconnect;
    59 	conn->onDisconnectCb = &defaultCallback_onDisconnect;
    60 	conn->onErrorMessageCb = &defaultCallback_onErrorMessage;
    60 	conn->onErrorMessageCb = &defaultCallback_onErrorMessage;
    61 	conn->onChatCb = &defaultCallback_onChat;
    61 	conn->onChatCb = &defaultCallback_onChat;
    62 	conn->onGameRecordedCb = &defaultCallback_onGameRecorded;
    62 	conn->onGameRecordedCb = &defaultCallback_onGameRecorded;
    63 	conn->onNetMessageCb = &defaultCallback_onNetMessage;
    63 	conn->onEngineMessageCb = &defaultCallback_onEngineMessage;
    64 }
    64 }
    65 
    65 
    66 static flib_gameconn *flib_gameconn_create_partial(bool record, const char *playerName, bool netGame) {
    66 static flib_gameconn *flib_gameconn_create_partial(bool record, const char *playerName, bool netGame) {
    67 	flib_gameconn *result = NULL;
    67 	flib_gameconn *result = NULL;
    68 	flib_gameconn *tempConn = flib_calloc(1, sizeof(flib_gameconn));
    68 	flib_gameconn *tempConn = flib_calloc(1, sizeof(flib_gameconn));
    69 	if(tempConn) {
    69 	if(tempConn) {
    70 		tempConn->connection = flib_ipcconn_create();
    70 		tempConn->ipcBase = flib_ipcbase_create();
    71 		tempConn->configBuffer = flib_vector_create();
    71 		tempConn->configBuffer = flib_vector_create();
    72 		tempConn->playerName = flib_strdupnull(playerName);
    72 		tempConn->playerName = flib_strdupnull(playerName);
    73 		if(tempConn->connection && tempConn->configBuffer && tempConn->playerName) {
    73 		if(tempConn->ipcBase && tempConn->configBuffer && tempConn->playerName) {
    74 			if(record) {
    74 			if(record) {
    75 				tempConn->demoBuffer = flib_vector_create();
    75 				tempConn->demoBuffer = flib_vector_create();
    76 			}
    76 			}
    77 			tempConn->state = AWAIT_CONNECTION;
    77 			tempConn->state = AWAIT_CONNECTION;
    78 			tempConn->netgame = netGame;
    78 			tempConn->netgame = netGame;
   133 			 * sent to prevent surprises.
   133 			 * sent to prevent surprises.
   134 			 */
   134 			 */
   135 			clearCallbacks(conn);
   135 			clearCallbacks(conn);
   136 			conn->destroyRequested = true;
   136 			conn->destroyRequested = true;
   137 		} else {
   137 		} else {
   138 			flib_ipcconn_destroy(conn->connection);
   138 			flib_ipcbase_destroy(conn->ipcBase);
   139 			flib_vector_destroy(conn->configBuffer);
   139 			flib_vector_destroy(conn->configBuffer);
   140 			flib_vector_destroy(conn->demoBuffer);
   140 			flib_vector_destroy(conn->demoBuffer);
   141 			free(conn->playerName);
   141 			free(conn->playerName);
   142 			free(conn);
   142 			free(conn);
   143 		}
   143 		}
   147 int flib_gameconn_getport(flib_gameconn *conn) {
   147 int flib_gameconn_getport(flib_gameconn *conn) {
   148 	if(!conn) {
   148 	if(!conn) {
   149 		flib_log_e("null parameter in flib_gameconn_getport");
   149 		flib_log_e("null parameter in flib_gameconn_getport");
   150 		return 0;
   150 		return 0;
   151 	} else {
   151 	} else {
   152 		return flib_ipcconn_port(conn->connection);
   152 		return flib_ipcbase_port(conn->ipcBase);
   153 	}
   153 	}
   154 }
   154 }
   155 
   155 
   156 static void demo_append(flib_gameconn *conn, const void *data, size_t len) {
   156 static void demo_append(flib_gameconn *conn, const void *data, size_t len) {
   157 	if(conn->demoBuffer) {
   157 	if(conn->demoBuffer) {
   199 
   199 
   200 int flib_gameconn_send_enginemsg(flib_gameconn *conn, uint8_t *data, int len) {
   200 int flib_gameconn_send_enginemsg(flib_gameconn *conn, uint8_t *data, int len) {
   201 	int result = -1;
   201 	int result = -1;
   202 	if(!conn || (!data && len>0)) {
   202 	if(!conn || (!data && len>0)) {
   203 		flib_log_e("null parameter in flib_gameconn_send_enginemsg");
   203 		flib_log_e("null parameter in flib_gameconn_send_enginemsg");
   204 	} else if(!flib_ipcconn_send_raw(conn->connection, data, len)) {
   204 	} else if(!flib_ipcbase_send_raw(conn->ipcBase, data, len)) {
   205 		demo_append(conn, data, len);
   205 		demo_append(conn, data, len);
   206 		result = 0;
   206 		result = 0;
   207 	}
   207 	}
   208 	return result;
   208 	return result;
   209 }
   209 }
   215 	} else {
   215 	} else {
   216 		uint8_t converted[257];
   216 		uint8_t converted[257];
   217 		int size = snprintf((char*)converted+1, 256, "s%c%s", (char)msgtype, msg);
   217 		int size = snprintf((char*)converted+1, 256, "s%c%s", (char)msgtype, msg);
   218 		if(size>0) {
   218 		if(size>0) {
   219 			converted[0] = size>255 ? 255 : size;
   219 			converted[0] = size>255 ? 255 : size;
   220 			if(!flib_ipcconn_send_raw(conn->connection, converted, converted[0]+1)) {
   220 			if(!flib_ipcbase_send_raw(conn->ipcBase, converted, converted[0]+1)) {
   221 				demo_append(conn, converted, converted[0]+1);
   221 				demo_append(conn, converted, converted[0]+1);
   222 				result = 0;
   222 				result = 0;
   223 			}
   223 			}
   224 		}
   224 		}
   225 	}
   225 	}
   231 	uint8_t converted[257];
   231 	uint8_t converted[257];
   232 	if(!conn || !playername || !msg) {
   232 	if(!conn || !playername || !msg) {
   233 		flib_log_e("null parameter in flib_gameconn_send_chatmsg");
   233 		flib_log_e("null parameter in flib_gameconn_send_chatmsg");
   234 	} else if(format_chatmessage(converted, playername, msg)) {
   234 	} else if(format_chatmessage(converted, playername, msg)) {
   235 		flib_log_e("Error formatting message in flib_gameconn_send_chatmsg");
   235 		flib_log_e("Error formatting message in flib_gameconn_send_chatmsg");
   236 	} else if(!flib_ipcconn_send_raw(conn->connection, converted, converted[0]+1)) {
   236 	} else if(!flib_ipcbase_send_raw(conn->ipcBase, converted, converted[0]+1)) {
   237 		demo_append(conn, converted, converted[0]+1);
   237 		demo_append(conn, converted, converted[0]+1);
   238 		result = 0;
   238 		result = 0;
   239 	}
   239 	}
   240 	return result;
   240 	return result;
   241 }
   241 }
   283 		conn->onGameRecordedCb = callback ? callback : &defaultCallback_onGameRecorded;
   283 		conn->onGameRecordedCb = callback ? callback : &defaultCallback_onGameRecorded;
   284 		conn->onGameRecordedCtx = context;
   284 		conn->onGameRecordedCtx = context;
   285 	}
   285 	}
   286 }
   286 }
   287 
   287 
   288 void flib_gameconn_onNetMessage(flib_gameconn *conn, void (*callback)(void *context, const uint8_t *em, int size), void* context) {
   288 void flib_gameconn_onEngineMessage(flib_gameconn *conn, void (*callback)(void *context, const uint8_t *em, int size), void* context) {
   289 	if(!conn) {
   289 	if(!conn) {
   290 		flib_log_e("null parameter in flib_gameconn_onNetMessage");
   290 		flib_log_e("null parameter in flib_gameconn_onEngineMessage");
   291 	} else {
   291 	} else {
   292 		conn->onNetMessageCb = callback ? callback : &defaultCallback_onNetMessage;
   292 		conn->onEngineMessageCb = callback ? callback : &defaultCallback_onEngineMessage;
   293 		conn->onNetMessageCtx = context;
   293 		conn->onEngineMessageCtx = context;
   294 	}
   294 	}
   295 }
   295 }
   296 
   296 
   297 static void flib_gameconn_wrappedtick(flib_gameconn *conn) {
   297 static void flib_gameconn_wrappedtick(flib_gameconn *conn) {
   298 	if(conn->state == AWAIT_CONNECTION) {
   298 	if(conn->state == AWAIT_CONNECTION) {
   299 		flib_ipcconn_accept(conn->connection);
   299 		flib_ipcbase_accept(conn->ipcBase);
   300 		switch(flib_ipcconn_state(conn->connection)) {
   300 		switch(flib_ipcbase_state(conn->ipcBase)) {
   301 		case IPC_CONNECTED:
   301 		case IPC_CONNECTED:
   302 			{
   302 			{
   303 				flib_constbuffer configBuffer = flib_vector_as_constbuffer(conn->configBuffer);
   303 				flib_constbuffer configBuffer = flib_vector_as_constbuffer(conn->configBuffer);
   304 				if(flib_ipcconn_send_raw(conn->connection, configBuffer.data, configBuffer.size)) {
   304 				if(flib_ipcbase_send_raw(conn->ipcBase, configBuffer.data, configBuffer.size)) {
   305 					conn->state = FINISHED;
   305 					conn->state = FINISHED;
   306 					conn->onDisconnectCb(conn->onDisconnectCtx, GAME_END_ERROR);
   306 					conn->onDisconnectCb(conn->onDisconnectCtx, GAME_END_ERROR);
   307 					return;
   307 					return;
   308 				} else {
   308 				} else {
   309 					demo_append(conn, configBuffer.data, configBuffer.size);
   309 					demo_append(conn, configBuffer.data, configBuffer.size);
   325 	}
   325 	}
   326 
   326 
   327 	if(conn->state == CONNECTED) {
   327 	if(conn->state == CONNECTED) {
   328 		uint8_t msgbuffer[257];
   328 		uint8_t msgbuffer[257];
   329 		int len;
   329 		int len;
   330 		while(!conn->destroyRequested && (len = flib_ipcconn_recv_message(conn->connection, msgbuffer))>=0) {
   330 		while(!conn->destroyRequested && (len = flib_ipcbase_recv_message(conn->ipcBase, msgbuffer))>=0) {
   331 			if(len<2) {
   331 			if(len<2) {
   332 				flib_log_w("Received short message from IPC (<2 bytes)");
   332 				flib_log_w("Received short message from IPC (<2 bytes)");
   333 				continue;
   333 				continue;
   334 			}
   334 			}
   335 			switch(msgbuffer[1]) {
   335 			switch(msgbuffer[1]) {
   381 				}
   381 				}
   382 				break;
   382 				break;
   383 			default:	// Engine message
   383 			default:	// Engine message
   384 				demo_append(conn, msgbuffer, len);
   384 				demo_append(conn, msgbuffer, len);
   385 
   385 
   386 				conn->onNetMessageCb(conn->onNetMessageCtx, msgbuffer, len);
   386 				conn->onEngineMessageCb(conn->onEngineMessageCtx, msgbuffer, len);
   387 				break;
   387 				break;
   388 			}
   388 			}
   389 		}
   389 		}
   390 	}
   390 	}
   391 
   391 
   392 	if(flib_ipcconn_state(conn->connection) == IPC_NOT_CONNECTED) {
   392 	if(flib_ipcbase_state(conn->ipcBase) == IPC_NOT_CONNECTED) {
   393 		conn->state = FINISHED;
   393 		conn->state = FINISHED;
   394 		conn->onDisconnectCb(conn->onDisconnectCtx, GAME_END_ERROR);
   394 		conn->onDisconnectCb(conn->onDisconnectCtx, GAME_END_ERROR);
   395 	}
   395 	}
   396 }
   396 }
   397 
   397