project_files/frontlib/ipc/mapconn.c
changeset 7177 bf6cf4dd847a
child 7179 f84805e6df03
equal deleted inserted replaced
7175:038e3415100a 7177:bf6cf4dd847a
       
     1 #include "mapconn.h"
       
     2 #include "ipcconn.h"
       
     3 #include "ipcprotocol.h"
       
     4 
       
     5 #include "../logging.h"
       
     6 #include "../buffer.h"
       
     7 
       
     8 #include <stdlib.h>
       
     9 
       
    10 typedef enum {
       
    11 	AWAIT_CONNECTION,
       
    12 	AWAIT_REPLY,
       
    13 	FINISHED
       
    14 } mapconn_progress;
       
    15 
       
    16 struct _flib_mapconn {
       
    17 	uint8_t mapBuffer[IPCCONN_MAPMSG_BYTES];
       
    18 	flib_ipcconn connection;
       
    19 	flib_vector configBuffer;
       
    20 
       
    21 	mapconn_progress progress;
       
    22 
       
    23 	void (*onSuccessCb)(void*, const uint8_t*, int);
       
    24 	void *onSuccessCtx;
       
    25 
       
    26 	void (*onFailureCb)(void*, const char*);
       
    27 	void *onFailureCtx;
       
    28 
       
    29 	bool running;
       
    30 	bool destroyRequested;
       
    31 };
       
    32 
       
    33 static void noop_handleSuccess(void *context, const uint8_t *bitmap, int numHedgehogs) {}
       
    34 static void noop_handleFailure(void *context, const char *errormessage) {}
       
    35 
       
    36 static void clearCallbacks(flib_mapconn *conn) {
       
    37 	conn->onSuccessCb = &noop_handleSuccess;
       
    38 	conn->onFailureCb = &noop_handleFailure;
       
    39 }
       
    40 
       
    41 static flib_vector createConfigBuffer(char *seed, flib_map *mapdesc) {
       
    42 	flib_vector result = NULL;
       
    43 	flib_vector tempbuffer = flib_vector_create();
       
    44 	if(tempbuffer) {
       
    45 		bool error = false;
       
    46 		error |= flib_ipc_append_seed(tempbuffer, seed);
       
    47 		error |= flib_ipc_append_mapconf(tempbuffer, mapdesc, true);
       
    48 		error |= flib_ipc_append_message(tempbuffer, "!");
       
    49 		if(!error) {
       
    50 			result = tempbuffer;
       
    51 			tempbuffer = NULL;
       
    52 		}
       
    53 	}
       
    54 	flib_vector_destroy(&tempbuffer);
       
    55 	return result;
       
    56 }
       
    57 
       
    58 flib_mapconn *flib_mapconn_create(char *seed, flib_map *mapdesc) {
       
    59 	flib_mapconn *result = NULL;
       
    60 	flib_mapconn *tempConn = calloc(1, sizeof(flib_mapconn));
       
    61 	if(tempConn) {
       
    62 		tempConn->connection = flib_ipcconn_create(false, "Player");
       
    63 		tempConn->configBuffer = createConfigBuffer(seed, mapdesc);
       
    64 		if(tempConn->connection && tempConn->configBuffer) {
       
    65 			tempConn->progress = AWAIT_CONNECTION;
       
    66 			clearCallbacks(tempConn);
       
    67 			result = tempConn;
       
    68 			tempConn = NULL;
       
    69 		}
       
    70 	}
       
    71 	flib_mapconn_destroy(tempConn);
       
    72 	return result;
       
    73 }
       
    74 
       
    75 void flib_mapconn_destroy(flib_mapconn *conn) {
       
    76 	if(conn) {
       
    77 		if(conn->running) {
       
    78 			/*
       
    79 			 * The function was called from a callback, so the tick function is still running
       
    80 			 * and we delay the actual destruction. We ensure no further callbacks will be
       
    81 			 * sent to prevent surprises.
       
    82 			 */
       
    83 			clearCallbacks(conn);
       
    84 			conn->destroyRequested = true;
       
    85 		} else {
       
    86 			flib_ipcconn_destroy(&conn->connection);
       
    87 			flib_vector_destroy(&conn->configBuffer);
       
    88 			free(conn);
       
    89 		}
       
    90 	}
       
    91 }
       
    92 
       
    93 int flib_mapconn_getport(flib_mapconn *conn) {
       
    94 	if(!conn) {
       
    95 		flib_log_e("null parameter in flib_mapconn_getport");
       
    96 		return 0;
       
    97 	} else {
       
    98 		return flib_ipcconn_port(conn->connection);
       
    99 	}
       
   100 }
       
   101 
       
   102 void flib_mapconn_onSuccess(flib_mapconn *conn, void (*callback)(void* context, const uint8_t *bitmap, int numHedgehogs), void *context) {
       
   103 	if(!conn) {
       
   104 		flib_log_e("null parameter in flib_mapconn_onSuccess");
       
   105 	} else {
       
   106 		conn->onSuccessCb = callback ? callback : &noop_handleSuccess;
       
   107 		conn->onSuccessCtx = context;
       
   108 	}
       
   109 }
       
   110 
       
   111 void flib_mapconn_onFailure(flib_mapconn *conn, void (*callback)(void* context, const char *errormessage), void *context) {
       
   112 	if(!conn) {
       
   113 		flib_log_e("null parameter in flib_mapconn_onError");
       
   114 	} else {
       
   115 		conn->onFailureCb = callback ? callback : &noop_handleFailure;
       
   116 		conn->onFailureCtx = context;
       
   117 	}
       
   118 }
       
   119 
       
   120 static void flib_mapconn_wrappedtick(flib_mapconn *conn) {
       
   121 	if(conn->progress == AWAIT_CONNECTION) {
       
   122 		flib_ipcconn_accept(conn->connection);
       
   123 		switch(flib_ipcconn_state(conn->connection)) {
       
   124 		case IPC_CONNECTED:
       
   125 			{
       
   126 				flib_constbuffer configBuffer = flib_vector_as_constbuffer(conn->configBuffer);
       
   127 				if(flib_ipcconn_send_raw(conn->connection, configBuffer.data, configBuffer.size)) {
       
   128 					conn->progress = FINISHED;
       
   129 					conn->onFailureCb(conn->onFailureCtx, "Error sending map information to the engine.");
       
   130 					return;
       
   131 				} else {
       
   132 					conn->progress = AWAIT_REPLY;
       
   133 				}
       
   134 			}
       
   135 			break;
       
   136 		case IPC_NOT_CONNECTED:
       
   137 			conn->progress = FINISHED;
       
   138 			conn->onFailureCb(conn->onFailureCtx, "Engine connection closed unexpectedly.");
       
   139 			return;
       
   140 		default:
       
   141 			break;
       
   142 		}
       
   143 	}
       
   144 
       
   145 	if(conn->progress == AWAIT_REPLY) {
       
   146 		if(flib_ipcconn_recv_map(conn->connection, conn->mapBuffer) >= 0) {
       
   147 			conn->progress = FINISHED;
       
   148 			conn->onSuccessCb(conn->onSuccessCtx, conn->mapBuffer, conn->mapBuffer[IPCCONN_MAPMSG_BYTES-1]);
       
   149 			return;
       
   150 		} else if(flib_ipcconn_state(conn->connection) != IPC_CONNECTED) {
       
   151 			conn->progress = FINISHED;
       
   152 			conn->onFailureCb(conn->onSuccessCtx, "Engine connection closed unexpectedly.");
       
   153 			return;
       
   154 		}
       
   155 	}
       
   156 }
       
   157 
       
   158 void flib_mapconn_tick(flib_mapconn *conn) {
       
   159 	if(!conn) {
       
   160 		flib_log_e("null parameter in flib_mapconn_tick");
       
   161 	} else if(conn->running) {
       
   162 		flib_log_w("Call to flib_mapconn_tick from a callback");
       
   163 	} else if(conn->progress == FINISHED) {
       
   164 		flib_log_w("Call to flib_mapconn_tick, but we are already done. Best destroy your flib_mapconn object in the callbacks.");
       
   165 	} else {
       
   166 		conn->running = true;
       
   167 		flib_mapconn_wrappedtick(conn);
       
   168 		conn->running = false;
       
   169 
       
   170 		if(conn->destroyRequested) {
       
   171 			flib_mapconn_destroy(conn);
       
   172 		}
       
   173 	}
       
   174 }