15 * |
15 * |
16 * We don't need to worry about wasting a few kb though, and I like powers of two... |
16 * We don't need to worry about wasting a few kb though, and I like powers of two... |
17 */ |
17 */ |
18 typedef struct _flib_ipcconn { |
18 typedef struct _flib_ipcconn { |
19 uint8_t readBuffer[8192]; |
19 uint8_t readBuffer[8192]; |
20 char playerName[256]; |
|
21 |
|
22 int readBufferSize; |
20 int readBufferSize; |
23 |
21 |
24 flib_acceptor acceptor; |
22 flib_acceptor *acceptor; |
25 uint16_t port; |
23 uint16_t port; |
26 |
24 |
27 flib_tcpsocket sock; |
25 flib_tcpsocket *sock; |
28 flib_vector demoBuffer; |
|
29 } _flib_ipcconn; |
26 } _flib_ipcconn; |
30 |
27 |
31 flib_ipcconn flib_ipcconn_create(bool recordDemo, const char *localPlayerName) { |
28 flib_ipcconn *flib_ipcconn_create() { |
32 flib_ipcconn result = malloc(sizeof(_flib_ipcconn)); |
29 flib_ipcconn *result = flib_malloc(sizeof(_flib_ipcconn)); |
33 flib_acceptor acceptor = flib_acceptor_create(0); |
30 flib_acceptor *acceptor = flib_acceptor_create(0); |
34 |
31 |
35 if(!result || !acceptor) { |
32 if(!result || !acceptor) { |
36 flib_log_e("Can't create ipcconn."); |
|
37 free(result); |
33 free(result); |
38 flib_acceptor_close(&acceptor); |
34 flib_acceptor_close(acceptor); |
39 return NULL; |
35 return NULL; |
40 } |
36 } |
41 |
37 |
42 result->acceptor = acceptor; |
38 result->acceptor = acceptor; |
43 result->sock = NULL; |
39 result->sock = NULL; |
44 result->readBufferSize = 0; |
40 result->readBufferSize = 0; |
45 result->port = flib_acceptor_listenport(acceptor); |
41 result->port = flib_acceptor_listenport(acceptor); |
46 |
42 |
47 if(localPlayerName) { |
|
48 strncpy(result->playerName, localPlayerName, 255); |
|
49 } else { |
|
50 strncpy(result->playerName, "Player", 255); |
|
51 } |
|
52 |
|
53 if(recordDemo) { |
|
54 result->demoBuffer = flib_vector_create(); |
|
55 } |
|
56 |
|
57 flib_log_i("Started listening for IPC connections on port %u", (unsigned)result->port); |
43 flib_log_i("Started listening for IPC connections on port %u", (unsigned)result->port); |
58 return result; |
44 return result; |
59 } |
45 } |
60 |
46 |
61 uint16_t flib_ipcconn_port(flib_ipcconn ipc) { |
47 uint16_t flib_ipcconn_port(flib_ipcconn *ipc) { |
62 if(!ipc) { |
48 if(!ipc) { |
63 flib_log_e("Call to flib_ipcconn_port with ipc==null"); |
49 flib_log_e("null parameter in flib_ipcconn_port"); |
64 return 0; |
50 return 0; |
65 } |
51 } |
66 return ipc->port; |
52 return ipc->port; |
67 } |
53 } |
68 |
54 |
69 void flib_ipcconn_destroy(flib_ipcconn *ipcptr) { |
55 void flib_ipcconn_destroy(flib_ipcconn *ipc) { |
70 if(!ipcptr) { |
56 if(ipc) { |
71 flib_log_e("Call to flib_ipcconn_destroy with ipcptr==null"); |
57 flib_acceptor_close(ipc->acceptor); |
72 } else if(*ipcptr) { |
58 flib_socket_close(ipc->sock); |
73 flib_ipcconn ipc = *ipcptr; |
|
74 flib_acceptor_close(&ipc->acceptor); |
|
75 flib_socket_close(&ipc->sock); |
|
76 flib_vector_destroy(&ipc->demoBuffer); |
|
77 free(ipc); |
59 free(ipc); |
78 *ipcptr = NULL; |
60 } |
79 } |
61 } |
80 } |
62 |
81 |
63 IpcConnState flib_ipcconn_state(flib_ipcconn *ipc) { |
82 IpcConnState flib_ipcconn_state(flib_ipcconn ipc) { |
|
83 if(!ipc) { |
64 if(!ipc) { |
84 flib_log_e("Call to flib_ipcconn_state with ipc==null"); |
65 flib_log_e("null parameter in flib_ipcconn_state"); |
85 return IPC_NOT_CONNECTED; |
66 return IPC_NOT_CONNECTED; |
86 } else if(ipc->sock) { |
67 } else if(ipc->sock) { |
87 return IPC_CONNECTED; |
68 return IPC_CONNECTED; |
88 } else if(ipc->acceptor) { |
69 } else if(ipc->acceptor) { |
89 return IPC_LISTENING; |
70 return IPC_LISTENING; |
90 } else { |
71 } else { |
91 return IPC_NOT_CONNECTED; |
72 return IPC_NOT_CONNECTED; |
92 } |
73 } |
93 } |
74 } |
94 |
75 |
95 static bool isMessageReady(flib_ipcconn ipc) { |
76 static bool isMessageReady(flib_ipcconn *ipc) { |
96 return ipc->readBufferSize >= ipc->readBuffer[0]+1; |
77 return ipc->readBufferSize >= ipc->readBuffer[0]+1; |
97 } |
78 } |
98 |
79 |
99 static void receiveToBuffer(flib_ipcconn ipc) { |
80 static void receiveToBuffer(flib_ipcconn *ipc) { |
100 if(ipc->sock) { |
81 if(ipc->sock) { |
101 int size = flib_socket_nbrecv(ipc->sock, ipc->readBuffer+ipc->readBufferSize, sizeof(ipc->readBuffer)-ipc->readBufferSize); |
82 int size = flib_socket_nbrecv(ipc->sock, ipc->readBuffer+ipc->readBufferSize, sizeof(ipc->readBuffer)-ipc->readBufferSize); |
102 if(size>=0) { |
83 if(size>=0) { |
103 ipc->readBufferSize += size; |
84 ipc->readBufferSize += size; |
104 } else { |
85 } else { |
105 flib_socket_close(&ipc->sock); |
86 flib_socket_close(ipc->sock); |
|
87 ipc->sock = NULL; |
106 } |
88 } |
107 } |
89 } |
108 } |
90 } |
109 |
91 |
110 int flib_ipcconn_recv_message(flib_ipcconn ipc, void *data) { |
92 int flib_ipcconn_recv_message(flib_ipcconn *ipc, void *data) { |
111 if(!ipc || !data) { |
93 if(!ipc || !data) { |
112 flib_log_e("Call to flib_ipcconn_recv_message with ipc==null or data==null"); |
94 flib_log_e("null parameter in flib_ipcconn_recv_message"); |
113 return -1; |
95 return -1; |
114 } |
96 } |
115 |
97 |
116 if(!isMessageReady(ipc)) { |
98 if(!isMessageReady(ipc)) { |
117 receiveToBuffer(ipc); |
99 receiveToBuffer(ipc); |
118 } |
100 } |
119 |
101 |
120 if(isMessageReady(ipc)) { |
102 if(isMessageReady(ipc)) { |
121 if(ipc->demoBuffer) { |
|
122 if(flib_demo_record_from_engine(ipc->demoBuffer, ipc->readBuffer, ipc->playerName) < 0) { |
|
123 flib_log_w("Stopping demo recording due to an error."); |
|
124 flib_vector_destroy(&ipc->demoBuffer); |
|
125 } |
|
126 } |
|
127 int msgsize = ipc->readBuffer[0]+1; |
103 int msgsize = ipc->readBuffer[0]+1; |
128 memcpy(data, ipc->readBuffer, msgsize); |
104 memcpy(data, ipc->readBuffer, msgsize); |
129 memmove(ipc->readBuffer, ipc->readBuffer+msgsize, ipc->readBufferSize-msgsize); |
105 memmove(ipc->readBuffer, ipc->readBuffer+msgsize, ipc->readBufferSize-msgsize); |
130 ipc->readBufferSize -= msgsize; |
106 ipc->readBufferSize -= msgsize; |
131 return msgsize; |
107 return msgsize; |
169 msgStart += (uint8_t)data[msgStart]+1; |
145 msgStart += (uint8_t)data[msgStart]+1; |
170 } |
146 } |
171 } |
147 } |
172 } |
148 } |
173 |
149 |
174 int flib_ipcconn_send_raw(flib_ipcconn ipc, const void *data, size_t len) { |
150 int flib_ipcconn_send_raw(flib_ipcconn *ipc, const void *data, size_t len) { |
175 if(!ipc || (!data && len>0)) { |
151 if(!ipc || (!data && len>0)) { |
176 flib_log_e("Call to flib_ipcconn_send_raw with ipc==null or data==null"); |
152 flib_log_e("null parameter in flib_ipcconn_send_raw"); |
177 return -1; |
153 return -1; |
178 } |
154 } |
179 if(!ipc->sock) { |
155 if(!ipc->sock) { |
180 flib_log_w("flib_ipcconn_send_raw: Not connected."); |
156 flib_log_w("flib_ipcconn_send_raw: Not connected."); |
181 return -1; |
157 return -1; |
182 } |
158 } |
183 |
159 |
184 if(flib_socket_send(ipc->sock, data, len) == len) { |
160 if(flib_socket_send(ipc->sock, data, len) == len) { |
185 logSentMsg(data, len); |
161 logSentMsg(data, len); |
186 if(ipc->demoBuffer) { |
|
187 if(flib_demo_record_to_engine(ipc->demoBuffer, data, len) < 0) { |
|
188 flib_log_w("Stopping demo recording due to an error."); |
|
189 flib_vector_destroy(&ipc->demoBuffer); |
|
190 } |
|
191 } |
|
192 return 0; |
162 return 0; |
193 } else { |
163 } else { |
194 flib_log_w("Failed or incomplete ICP write: engine connection lost."); |
164 flib_log_w("Failed or incomplete ICP write: engine connection lost."); |
195 flib_socket_close(&ipc->sock); |
165 flib_socket_close(ipc->sock); |
196 return -1; |
166 ipc->sock = NULL; |
197 } |
167 return -1; |
198 } |
168 } |
199 |
169 } |
200 int flib_ipcconn_send_message(flib_ipcconn ipc, void *data, size_t len) { |
170 |
201 if(!ipc || (!data && len>0) || len>255) { |
171 int flib_ipcconn_send_message(flib_ipcconn *ipc, void *data, size_t len) { |
202 flib_log_e("Call to flib_ipcconn_send_message with ipc==null or data==null or len>255"); |
172 if(!ipc || (!data && len>0)) { |
|
173 flib_log_e("null parameter in flib_ipcconn_send_message"); |
|
174 return -1; |
|
175 } else if(len>255) { |
|
176 flib_log_e("Overlong message (%zu bytes) in flib_ipcconn_send_message", len); |
203 return -1; |
177 return -1; |
204 } |
178 } |
205 |
179 |
206 uint8_t sendbuf[256]; |
180 uint8_t sendbuf[256]; |
207 sendbuf[0] = len; |
181 sendbuf[0] = len; |
208 memcpy(sendbuf+1, data, len); |
182 memcpy(sendbuf+1, data, len); |
209 return flib_ipcconn_send_raw(ipc, sendbuf, len+1); |
183 return flib_ipcconn_send_raw(ipc, sendbuf, len+1); |
210 } |
184 } |
211 |
185 |
212 int flib_ipcconn_send_messagestr(flib_ipcconn ipc, char *data) { |
186 int flib_ipcconn_send_messagestr(flib_ipcconn *ipc, char *data) { |
213 return flib_ipcconn_send_message(ipc, data, strlen(data)); |
187 return flib_ipcconn_send_message(ipc, data, strlen(data)); |
214 } |
188 } |
215 |
189 |
216 void flib_ipcconn_accept(flib_ipcconn ipc) { |
190 void flib_ipcconn_accept(flib_ipcconn *ipc) { |
217 if(!ipc) { |
191 if(!ipc) { |
218 flib_log_e("Call to flib_ipcconn_accept with ipc==null"); |
192 flib_log_e("null parameter in flib_ipcconn_accept"); |
219 } else if(!ipc->sock && ipc->acceptor) { |
193 } else if(!ipc->sock && ipc->acceptor) { |
220 ipc->sock = flib_socket_accept(ipc->acceptor, true); |
194 ipc->sock = flib_socket_accept(ipc->acceptor, true); |
221 if(ipc->sock) { |
195 if(ipc->sock) { |
222 flib_acceptor_close(&ipc->acceptor); |
196 flib_acceptor_close(ipc->acceptor); |
|
197 ipc->acceptor = NULL; |
223 } |
198 } |
224 } |
199 } |
225 } |
200 } |
226 |
|
227 flib_constbuffer flib_ipcconn_getrecord(flib_ipcconn ipc, bool save) { |
|
228 if(!ipc) { |
|
229 flib_log_e("Call to flib_ipcconn_getrecord with ipc==null"); |
|
230 } |
|
231 if(!ipc || !ipc->demoBuffer) { |
|
232 flib_constbuffer result = {NULL, 0}; |
|
233 return result; |
|
234 } |
|
235 flib_demo_replace_gamemode(flib_vector_as_buffer(ipc->demoBuffer), save ? 'S' : 'D'); |
|
236 return flib_vector_as_constbuffer(ipc->demoBuffer); |
|
237 } |
|