project_files/frontlib/ipc/mapconn.c
changeset 10017 de822cd3df3a
parent 7576 65d29988fd3d
equal deleted inserted replaced
10015:4feced261c68 10017:de822cd3df3a
    26 #include "../util/util.h"
    26 #include "../util/util.h"
    27 
    27 
    28 #include <stdlib.h>
    28 #include <stdlib.h>
    29 
    29 
    30 typedef enum {
    30 typedef enum {
    31 	AWAIT_CONNECTION,
    31     AWAIT_CONNECTION,
    32 	AWAIT_REPLY,
    32     AWAIT_REPLY,
    33 	AWAIT_CLOSE,
    33     AWAIT_CLOSE,
    34 	FINISHED
    34     FINISHED
    35 } mapconn_state;
    35 } mapconn_state;
    36 
    36 
    37 struct _flib_mapconn {
    37 struct _flib_mapconn {
    38 	uint8_t mapBuffer[IPCBASE_MAPMSG_BYTES];
    38     uint8_t mapBuffer[IPCBASE_MAPMSG_BYTES];
    39 	flib_ipcbase *ipcBase;
    39     flib_ipcbase *ipcBase;
    40 	flib_vector *configBuffer;
    40     flib_vector *configBuffer;
    41 
    41 
    42 	mapconn_state progress;
    42     mapconn_state progress;
    43 
    43 
    44 	void (*onSuccessCb)(void*, const uint8_t*, int);
    44     void (*onSuccessCb)(void*, const uint8_t*, int);
    45 	void *onSuccessCtx;
    45     void *onSuccessCtx;
    46 
    46 
    47 	void (*onFailureCb)(void*, const char*);
    47     void (*onFailureCb)(void*, const char*);
    48 	void *onFailureCtx;
    48     void *onFailureCtx;
    49 
    49 
    50 	bool running;
    50     bool running;
    51 	bool destroyRequested;
    51     bool destroyRequested;
    52 };
    52 };
    53 
    53 
    54 static void noop_handleSuccess(void *context, const uint8_t *bitmap, int numHedgehogs) {}
    54 static void noop_handleSuccess(void *context, const uint8_t *bitmap, int numHedgehogs) {}
    55 static void noop_handleFailure(void *context, const char *errormessage) {}
    55 static void noop_handleFailure(void *context, const char *errormessage) {}
    56 
    56 
    57 static void clearCallbacks(flib_mapconn *conn) {
    57 static void clearCallbacks(flib_mapconn *conn) {
    58 	conn->onSuccessCb = &noop_handleSuccess;
    58     conn->onSuccessCb = &noop_handleSuccess;
    59 	conn->onFailureCb = &noop_handleFailure;
    59     conn->onFailureCb = &noop_handleFailure;
    60 }
    60 }
    61 
    61 
    62 static flib_vector *createConfigBuffer(const flib_map *mapdesc) {
    62 static flib_vector *createConfigBuffer(const flib_map *mapdesc) {
    63 	flib_vector *result = NULL;
    63     flib_vector *result = NULL;
    64 	flib_vector *tempbuffer = flib_vector_create();
    64     flib_vector *tempbuffer = flib_vector_create();
    65 	if(tempbuffer) {
    65     if(tempbuffer) {
    66 		bool error = false;
    66         bool error = false;
    67 		error |= flib_ipc_append_mapconf(tempbuffer, mapdesc, true);
    67         error |= flib_ipc_append_mapconf(tempbuffer, mapdesc, true);
    68 		error |= flib_ipc_append_message(tempbuffer, "!");
    68         error |= flib_ipc_append_message(tempbuffer, "!");
    69 		if(!error) {
    69         if(!error) {
    70 			result = tempbuffer;
    70             result = tempbuffer;
    71 			tempbuffer = NULL;
    71             tempbuffer = NULL;
    72 		}
    72         }
    73 	}
    73     }
    74 	flib_vector_destroy(tempbuffer);
    74     flib_vector_destroy(tempbuffer);
    75 	return result;
    75     return result;
    76 }
    76 }
    77 
    77 
    78 flib_mapconn *flib_mapconn_create(const flib_map *mapdesc) {
    78 flib_mapconn *flib_mapconn_create(const flib_map *mapdesc) {
    79 	if(log_badargs_if(mapdesc==NULL)) {
    79     if(log_badargs_if(mapdesc==NULL)) {
    80 		return NULL;
    80         return NULL;
    81 	}
    81     }
    82 	flib_mapconn *result = NULL;
    82     flib_mapconn *result = NULL;
    83 	flib_mapconn *tempConn = flib_calloc(1, sizeof(flib_mapconn));
    83     flib_mapconn *tempConn = flib_calloc(1, sizeof(flib_mapconn));
    84 	if(tempConn) {
    84     if(tempConn) {
    85 		tempConn->ipcBase = flib_ipcbase_create();
    85         tempConn->ipcBase = flib_ipcbase_create();
    86 		tempConn->configBuffer = createConfigBuffer(mapdesc);
    86         tempConn->configBuffer = createConfigBuffer(mapdesc);
    87 		if(tempConn->ipcBase && tempConn->configBuffer) {
    87         if(tempConn->ipcBase && tempConn->configBuffer) {
    88 			tempConn->progress = AWAIT_CONNECTION;
    88             tempConn->progress = AWAIT_CONNECTION;
    89 			clearCallbacks(tempConn);
    89             clearCallbacks(tempConn);
    90 			result = tempConn;
    90             result = tempConn;
    91 			tempConn = NULL;
    91             tempConn = NULL;
    92 		}
    92         }
    93 	}
    93     }
    94 	flib_mapconn_destroy(tempConn);
    94     flib_mapconn_destroy(tempConn);
    95 	return result;
    95     return result;
    96 }
    96 }
    97 
    97 
    98 void flib_mapconn_destroy(flib_mapconn *conn) {
    98 void flib_mapconn_destroy(flib_mapconn *conn) {
    99 	if(conn) {
    99     if(conn) {
   100 		if(conn->running) {
   100         if(conn->running) {
   101 			/*
   101             /*
   102 			 * The function was called from a callback, so the tick function is still running
   102              * The function was called from a callback, so the tick function is still running
   103 			 * and we delay the actual destruction. We ensure no further callbacks will be
   103              * and we delay the actual destruction. We ensure no further callbacks will be
   104 			 * sent to prevent surprises.
   104              * sent to prevent surprises.
   105 			 */
   105              */
   106 			clearCallbacks(conn);
   106             clearCallbacks(conn);
   107 			conn->destroyRequested = true;
   107             conn->destroyRequested = true;
   108 		} else {
   108         } else {
   109 			flib_ipcbase_destroy(conn->ipcBase);
   109             flib_ipcbase_destroy(conn->ipcBase);
   110 			flib_vector_destroy(conn->configBuffer);
   110             flib_vector_destroy(conn->configBuffer);
   111 			free(conn);
   111             free(conn);
   112 		}
   112         }
   113 	}
   113     }
   114 }
   114 }
   115 
   115 
   116 int flib_mapconn_getport(flib_mapconn *conn) {
   116 int flib_mapconn_getport(flib_mapconn *conn) {
   117 	if(log_badargs_if(conn==NULL)) {
   117     if(log_badargs_if(conn==NULL)) {
   118 		return 0;
   118         return 0;
   119 	}
   119     }
   120 	return flib_ipcbase_port(conn->ipcBase);
   120     return flib_ipcbase_port(conn->ipcBase);
   121 }
   121 }
   122 
   122 
   123 void flib_mapconn_onSuccess(flib_mapconn *conn, void (*callback)(void* context, const uint8_t *bitmap, int numHedgehogs), void *context) {
   123 void flib_mapconn_onSuccess(flib_mapconn *conn, void (*callback)(void* context, const uint8_t *bitmap, int numHedgehogs), void *context) {
   124 	if(!log_badargs_if(conn==NULL)) {
   124     if(!log_badargs_if(conn==NULL)) {
   125 		conn->onSuccessCb = callback ? callback : &noop_handleSuccess;
   125         conn->onSuccessCb = callback ? callback : &noop_handleSuccess;
   126 		conn->onSuccessCtx = context;
   126         conn->onSuccessCtx = context;
   127 	}
   127     }
   128 }
   128 }
   129 
   129 
   130 void flib_mapconn_onFailure(flib_mapconn *conn, void (*callback)(void* context, const char *errormessage), void *context) {
   130 void flib_mapconn_onFailure(flib_mapconn *conn, void (*callback)(void* context, const char *errormessage), void *context) {
   131 	if(!log_badargs_if(conn==NULL)) {
   131     if(!log_badargs_if(conn==NULL)) {
   132 		conn->onFailureCb = callback ? callback : &noop_handleFailure;
   132         conn->onFailureCb = callback ? callback : &noop_handleFailure;
   133 		conn->onFailureCtx = context;
   133         conn->onFailureCtx = context;
   134 	}
   134     }
   135 }
   135 }
   136 
   136 
   137 static void flib_mapconn_wrappedtick(flib_mapconn *conn) {
   137 static void flib_mapconn_wrappedtick(flib_mapconn *conn) {
   138 	if(conn->progress == AWAIT_CONNECTION) {
   138     if(conn->progress == AWAIT_CONNECTION) {
   139 		flib_ipcbase_accept(conn->ipcBase);
   139         flib_ipcbase_accept(conn->ipcBase);
   140 		switch(flib_ipcbase_state(conn->ipcBase)) {
   140         switch(flib_ipcbase_state(conn->ipcBase)) {
   141 		case IPC_CONNECTED:
   141         case IPC_CONNECTED:
   142 			{
   142             {
   143 				flib_constbuffer configBuffer = flib_vector_as_constbuffer(conn->configBuffer);
   143                 flib_constbuffer configBuffer = flib_vector_as_constbuffer(conn->configBuffer);
   144 				if(flib_ipcbase_send_raw(conn->ipcBase, configBuffer.data, configBuffer.size)) {
   144                 if(flib_ipcbase_send_raw(conn->ipcBase, configBuffer.data, configBuffer.size)) {
   145 					conn->progress = FINISHED;
   145                     conn->progress = FINISHED;
   146 					conn->onFailureCb(conn->onFailureCtx, "Error sending map information to the engine.");
   146                     conn->onFailureCb(conn->onFailureCtx, "Error sending map information to the engine.");
   147 					return;
   147                     return;
   148 				} else {
   148                 } else {
   149 					conn->progress = AWAIT_REPLY;
   149                     conn->progress = AWAIT_REPLY;
   150 				}
   150                 }
   151 			}
   151             }
   152 			break;
   152             break;
   153 		case IPC_NOT_CONNECTED:
   153         case IPC_NOT_CONNECTED:
   154 			conn->progress = FINISHED;
   154             conn->progress = FINISHED;
   155 			conn->onFailureCb(conn->onFailureCtx, "Engine connection closed unexpectedly.");
   155             conn->onFailureCb(conn->onFailureCtx, "Engine connection closed unexpectedly.");
   156 			return;
   156             return;
   157 		default:
   157         default:
   158 			break;
   158             break;
   159 		}
   159         }
   160 	}
   160     }
   161 
   161 
   162 	if(conn->progress == AWAIT_REPLY) {
   162     if(conn->progress == AWAIT_REPLY) {
   163 		if(flib_ipcbase_recv_map(conn->ipcBase, conn->mapBuffer) >= 0) {
   163         if(flib_ipcbase_recv_map(conn->ipcBase, conn->mapBuffer) >= 0) {
   164 			conn->progress = AWAIT_CLOSE;
   164             conn->progress = AWAIT_CLOSE;
   165 		} else if(flib_ipcbase_state(conn->ipcBase) != IPC_CONNECTED) {
   165         } else if(flib_ipcbase_state(conn->ipcBase) != IPC_CONNECTED) {
   166 			conn->progress = FINISHED;
   166             conn->progress = FINISHED;
   167 			conn->onFailureCb(conn->onSuccessCtx, "Engine connection closed unexpectedly.");
   167             conn->onFailureCb(conn->onSuccessCtx, "Engine connection closed unexpectedly.");
   168 			return;
   168             return;
   169 		}
   169         }
   170 	}
   170     }
   171 
   171 
   172 	if(conn->progress == AWAIT_CLOSE) {
   172     if(conn->progress == AWAIT_CLOSE) {
   173 		// Just do throwaway reads so we find out when the engine disconnects
   173         // Just do throwaway reads so we find out when the engine disconnects
   174 		uint8_t buf[256];
   174         uint8_t buf[256];
   175 		flib_ipcbase_recv_message(conn->ipcBase, buf);
   175         flib_ipcbase_recv_message(conn->ipcBase, buf);
   176 		if(flib_ipcbase_state(conn->ipcBase) != IPC_CONNECTED) {
   176         if(flib_ipcbase_state(conn->ipcBase) != IPC_CONNECTED) {
   177 			conn->progress = FINISHED;
   177             conn->progress = FINISHED;
   178 			conn->onSuccessCb(conn->onSuccessCtx, conn->mapBuffer, conn->mapBuffer[IPCBASE_MAPMSG_BYTES-1]);
   178             conn->onSuccessCb(conn->onSuccessCtx, conn->mapBuffer, conn->mapBuffer[IPCBASE_MAPMSG_BYTES-1]);
   179 			return;
   179             return;
   180 		}
   180         }
   181 	}
   181     }
   182 }
   182 }
   183 
   183 
   184 void flib_mapconn_tick(flib_mapconn *conn) {
   184 void flib_mapconn_tick(flib_mapconn *conn) {
   185 	if(!log_badargs_if(conn==NULL)
   185     if(!log_badargs_if(conn==NULL)
   186 			&& !log_w_if(conn->running, "Call to flib_mapconn_tick from a callback")
   186             && !log_w_if(conn->running, "Call to flib_mapconn_tick from a callback")
   187 			&& !log_w_if(conn->progress == FINISHED, "We are already done.")) {
   187             && !log_w_if(conn->progress == FINISHED, "We are already done.")) {
   188 		conn->running = true;
   188         conn->running = true;
   189 		flib_mapconn_wrappedtick(conn);
   189         flib_mapconn_wrappedtick(conn);
   190 		conn->running = false;
   190         conn->running = false;
   191 
   191 
   192 		if(conn->destroyRequested) {
   192         if(conn->destroyRequested) {
   193 			flib_mapconn_destroy(conn);
   193             flib_mapconn_destroy(conn);
   194 		}
   194         }
   195 	}
   195     }
   196 }
   196 }