libs/neuronet master: Fixed a bug where the debugging just ceased.
[neuro.git] / libs / neuronet / master.c
blob8380206d0bb7c041b1f68db549bccfd76b1f36c0
1 /* master.c
2 * Module : Master
3 */
5 /*-------------------- Extern Headers Including --------------------*/
6 #ifndef WIN32
8 #else /* WIN32 */
10 #include <windows.h> /* WSAStartup WSACleanup */
11 #define MSG_DONTWAIT 0
13 #endif /* WIN32 */
15 #include <string.h> /* memset */
16 #include <errno.h> /* errno */
18 #include <neuro/NEURO.h>
20 /*-------------------- Local Headers Including ---------------------*/
21 #include <global.h>
22 #include "common.h"
24 #include <neuro/nnet/epoll.h>
25 #include "slave.h"
26 #include "client.h"
27 #include "server.h"
28 #include "status.h"
29 #include "util.h"
30 #include "lbuf.h"
32 /*-------------------- Main Module Header --------------------------*/
33 #include "master.h"
35 /*-------------------- Other ----------------------------*/
37 NEURO_MODULE_CHANNEL("netmaster");
39 /*-------------------- Global Variables ----------------------------*/
41 /*-------------------- Static Variables ----------------------------*/
43 /*-------------------- Static Prototypes ---------------------------*/
47 /*-------------------- Static Functions ----------------------------*/
49 static void
50 clean_statuses_elem(void *src)
52 Status *sta;
54 sta = src;
56 if (!sta)
57 return;
59 Status_Clear(sta);
62 static void
63 poll_disconnect_clients(Master *msr)
65 Slave **tmp = NULL;
67 if (Neuro_LBufIsEmpty(msr->disco_clients))
68 return;
70 Neuro_ResetLBuf(msr->disco_clients);
72 while ((tmp = Neuro_GiveNextLBuf(msr->disco_clients)))
74 TRACE(Neuro_s("Disconnecting client %x from the buffer %x count %d", *tmp, tmp, Neuro_GiveLBufCount(msr->disco_clients)));
76 if (msr->type == TYPE_SERVER)
77 Server_DisconnectClient(*tmp);
78 else
79 Client_Disconnect(*tmp);
81 Neuro_SCleanLBuf(msr->disco_clients, tmp);
85 /* add a client to disconnect */
86 static void
87 add_client_disconnect(Slave *slv)
89 Slave **tmp = NULL;
91 if (!Neuro_LBufIsEmpty(slv->master->disco_clients))
93 TRACE("Checking the disconnection buffer for duplicate entries");
95 Neuro_ResetLBuf(slv->master->disco_clients);
97 while ((tmp = Neuro_GiveNextLBuf(slv->master->disco_clients)))
99 TRACE(Neuro_s("is %x the same as %x -- %s", *tmp, slv, *tmp == slv ? "yes" : "no"));
101 if (*tmp == slv)
103 ERROR(Neuro_s("Slave %x already in the disconnection buffer!", slv));
105 return;
110 Neuro_AllocLBuf(slv->master->disco_clients, sizeof(Slave**));
112 tmp = Neuro_GiveCurLBuf(slv->master->disco_clients);
114 *tmp = slv;
116 TRACE(Neuro_s("Adding client %x for disconnection buffer %x -- buffer total %d", slv, tmp, Neuro_GiveLBufCount(slv->master->disco_clients)));
118 /* so we no longer get any events for this client */
119 Master_RmUfds(slv->master, slv);
122 /*-------------------- Global Functions ----------------------------*/
124 void
125 Master_AddUfds(Master *msr, Slave *slv)
127 EPOLL_EVENT event;
129 memset(&event, 0, sizeof(EPOLL_EVENT));
131 event.events = EPOLLIN | EPOLLPRI | EPOLLERR;
132 event.data.ptr = slv;
134 Epoll_Ctl(msr->ep, EPOLL_CTL_ADD, slv->socket, &event);
137 void
138 Master_RmUfds(Master *msr, Slave *slv)
140 EPOLL_EVENT event;
142 memset(&event, 0, sizeof(EPOLL_EVENT));
144 Epoll_Ctl(msr->ep, EPOLL_CTL_DEL, slv->socket, &event);
147 void
148 Master_EditEvent(Event *event, Slave *slave, int sigmask)
150 event->slave = slave;
151 event->sigmask = sigmask;
154 void
155 Master_PushEvent(Master *msr, Slave *slave, int sigmask)
157 EBUF *ce;
158 Event *tmp;
160 if (!msr)
161 return;
163 ce = msr->cevents;
165 Neuro_AllocEBuf(ce, sizeof(Event*), sizeof(Event));
167 tmp = Neuro_GiveCurEBuf(ce);
169 tmp->sigmask = sigmask;
170 tmp->slave = slave;
174 Master_PollEvent(Master *msr)
176 int i = 0;
177 EPOLL_EVENT *events;
179 events = Epoll_Wait(msr->ep, 0, &i);
181 if (i == 0)
182 return 0;
184 if (i == -1)
186 ERROR(Neuro_s("Error raised by Epoll_Wait : returned the value %d", errno));
188 return 1;
191 while (i-- > 0)
193 if ((events[i].events & EPOLLIN) == EPOLLIN || (events[i].events & EPOLLPRI) == EPOLLPRI)
195 Slave *slave = events[i].data.ptr;
196 /* NEURO_TRACE("Input Event Catched", NULL); */
198 if (slave->type == TYPE_SERVER)
200 Server_Poll(slave);
202 return 0;
204 else
206 int _err = 0;
208 if (msr->protocolType == SOCK_DGRAM && slave->type == TYPE_SERVER)
209 return 0;
211 _err = Client_PollRead(slave);
213 switch (_err)
215 case 0:
217 Client_PopData(slave);
219 break;
221 case 1:
223 WARN("TODO : Disconnect client -- Client_PollRead requested it");
224 if (msr->type == TYPE_SERVER)
225 Status_AddPriority(msr, State_ClientDisconnect, NULL, 0, slave);
226 else /* TYPE_CLIENT */
227 Status_AddPriority(msr, State_Disconnect, NULL, 0, slave);
229 break;
231 case 2:
233 return 1;
235 break;
239 else if ((events[i].events & EPOLLOUT) == EPOLLOUT)
241 /* NEURO_TRACE("Output event catched", NULL); */
243 else if ((events[i].events & EPOLLERR) == EPOLLERR || (events[i].events & EPOLLHUP) == EPOLLHUP)
245 WARN("Error Event Catched, Disconnecting client");
247 if (msr->type == TYPE_SERVER)
248 Status_Add(msr, State_ClientDisconnect, NULL, 0, events[i].data.ptr);
249 else /* TYPE_CLIENT */
250 Status_AddPriority(msr, State_Disconnect, NULL, 0, events[i].data.ptr);
253 return 0;
257 Master_SetSendPacketSize(Master *msr)
259 if (!msr)
260 return -1;
262 if (msr->inclpacket_size == 0)
264 msr->inclpacket_size = 1;
266 return 1;
268 else
269 msr->inclpacket_size = 0;
271 return 0;
274 void
275 Master_SetQuitFlag(Master *msr)
277 if (!msr)
278 return;
280 msr->type = 2;
283 /*-------------------- Poll ----------------------------------------*/
285 Status *
286 Master_Poll(Master *msr)
288 if (!msr)
289 return NULL;
291 if (msr->type == 2)
293 TRACE("End user application flagged the Master as quit, exiting");
295 Status_Set(msr->status, State_Disconnect, NULL, 0, NULL);
297 return msr->status;
300 if (!msr->slave)
302 ERROR("Attempted to poll without a properly initialized slave");
303 return NULL;
306 if (msr->type == TYPE_SERVER)
308 if (!msr->slave->cType.server)
310 ERROR("Attempted to poll without a properly initialized server");
311 return NULL;
314 else if (msr->type == TYPE_CLIENT)
316 if (!msr->slave->cType.client)
318 ERROR("Attempted to poll without a properly initialized client");
319 return NULL;
322 else
324 ERROR("Invalid Master type, bailing out");
326 return NULL;
329 if (!Neuro_LBufIsEmpty(msr->statuses))
331 /* delete the first entry of msr->statuses as it was used up */
335 /* disconnect all clients that are required to be */
336 poll_disconnect_clients(msr);
338 Master_PollEvent(msr);
340 if (Neuro_LBufIsEmpty(msr->statuses))
342 if (msr->callback)
344 if (msr->status->status == State_ClientDisconnect)
346 TRACE("Sending the event to really disconnect the client");
347 /* real disconnect event */
348 /* Master_PushEvent(msr, msr->status->connection, 16); */
349 add_client_disconnect(msr->status->connection);
353 Status_Set(msr->status, State_NoData, NULL, 0, NULL);
355 else
357 Status *buf;
359 /* fetch the first element */
360 buf = Neuro_GiveLBuf(msr->statuses);
362 Status_Move(buf, msr->status);
364 Neuro_SCleanLBuf(msr->statuses, buf);
366 if (msr->status->status == State_ClientDisconnect)
368 TRACE("Sending the event to really disconnect the client");
369 /* real disconnect event */
370 /* Master_PushEvent(msr, msr->status->connection, 16); */
371 add_client_disconnect(msr->status->connection);
373 else
375 TRACE(Neuro_s("Will send Status type %d -- data address %x", msr->status->status, msr->status->packet));
380 if (Master_PollEvent(msr) > 0)
382 NEURO_WARN("Master_PollEvent raised an error", NULL);
384 Status_Set(msr->status, State_Disconnect, NULL, 0, NULL);
386 return msr->status;
390 return msr->status;
393 /*-------------------- Constructor Destructor ----------------------*/
395 /* see Master for the connection_type */
396 Master *
397 Master_Create(u32 connection_type)
399 Master *msr;
400 Slave *slv;
402 msr = calloc(1, sizeof(Master));
404 slv = NULL;
406 msr->inclpacket_size = 0;
408 msr->protocolType = SOCK_STREAM;
410 msr->ep = Epoll_Create(sizeof(Slave));
412 /* NEURO_TRACE("Creating the connect events buffer", NULL); */
413 Neuro_CreateEBuf(&msr->cevents);
415 if (connection_type >= TYPE_CLIENT)
416 connection_type = TYPE_CLIENT;
418 msr->type = connection_type;
420 #if WIN32
422 int _err = 0;
424 _err = WSAStartup(MAKEWORD(1, 1), &msr->wsaData);
426 if (_err < 0)
427 return NULL;
429 #endif /* WIN32 */
431 msr->disco_clients = Neuro_CreateLBuf();
433 msr->statuses = Neuro_CreateLBuf();
434 Neuro_SetcallbLBuf(msr->statuses, clean_statuses_elem);
436 msr->status = Status_Create();
438 msr->callback = NULL;
440 return msr;
443 void
444 Master_Destroy(Master *msr)
446 if (!msr)
447 return;
449 #ifdef WIN32
450 WSACleanup();
451 #endif /* WIN32 */
454 Neuro_CleanEBuf(&msr->cevents);
457 Neuro_CleanLBuf(msr->disco_clients);
460 Neuro_CleanLBuf(msr->statuses);
462 Status_Destroy(msr->status);
464 if (msr->slave)
465 Slave_Destroy(msr->slave);
467 Epoll_Destroy(msr->ep);
469 free(msr);