5 /*-------------------- Extern Headers Including --------------------*/
10 #include <windows.h> /* WSAStartup WSACleanup */
11 #define MSG_DONTWAIT 0
15 #include <string.h> /* memset */
16 #include <errno.h> /* errno */
18 #include <neuro/NEURO.h>
20 /*-------------------- Local Headers Including ---------------------*/
24 #include <neuro/nnet/epoll.h>
32 /*-------------------- Main Module Header --------------------------*/
35 /*-------------------- Other ----------------------------*/
37 NEURO_MODULE_CHANNEL("netmaster");
39 /*-------------------- Global Variables ----------------------------*/
41 /*-------------------- Static Variables ----------------------------*/
43 /*-------------------- Static Prototypes ---------------------------*/
47 /*-------------------- Static Functions ----------------------------*/
50 clean_statuses_elem(void *src
)
63 poll_disconnect_clients(Master
*msr
)
67 if (Neuro_LBufIsEmpty(msr
->disco_clients
))
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
);
79 Client_Disconnect(*tmp
);
81 Neuro_SCleanLBuf(msr
->disco_clients
, tmp
);
85 /* add a client to disconnect */
87 add_client_disconnect(Slave
*slv
)
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"));
103 ERROR(Neuro_s("Slave %x already in the disconnection buffer!", slv
));
110 Neuro_AllocLBuf(slv
->master
->disco_clients
, sizeof(Slave
**));
112 tmp
= Neuro_GiveCurLBuf(slv
->master
->disco_clients
);
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 ----------------------------*/
125 Master_AddUfds(Master
*msr
, Slave
*slv
)
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
);
138 Master_RmUfds(Master
*msr
, Slave
*slv
)
142 memset(&event
, 0, sizeof(EPOLL_EVENT
));
144 Epoll_Ctl(msr
->ep
, EPOLL_CTL_DEL
, slv
->socket
, &event
);
148 Master_EditEvent(Event
*event
, Slave
*slave
, int sigmask
)
150 event
->slave
= slave
;
151 event
->sigmask
= sigmask
;
155 Master_PushEvent(Master
*msr
, Slave
*slave
, int sigmask
)
165 Neuro_AllocEBuf(ce
, sizeof(Event
*), sizeof(Event
));
167 tmp
= Neuro_GiveCurEBuf(ce
);
169 tmp
->sigmask
= sigmask
;
174 Master_PollEvent(Master
*msr
)
179 events
= Epoll_Wait(msr
->ep
, 0, &i
);
186 ERROR(Neuro_s("Error raised by Epoll_Wait : returned the value %d", errno
));
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
)
208 if (msr
->protocolType
== SOCK_DGRAM
&& slave
->type
== TYPE_SERVER
)
211 _err
= Client_PollRead(slave
);
217 Client_PopData(slave
);
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
);
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
);
257 Master_SetSendPacketSize(Master
*msr
)
262 if (msr
->inclpacket_size
== 0)
264 msr
->inclpacket_size
= 1;
269 msr
->inclpacket_size
= 0;
275 Master_SetQuitFlag(Master
*msr
)
283 /*-------------------- Poll ----------------------------------------*/
286 Master_Poll(Master
*msr
)
293 TRACE("End user application flagged the Master as quit, exiting");
295 Status_Set(msr
->status
, State_Disconnect
, NULL
, 0, NULL
);
302 ERROR("Attempted to poll without a properly initialized slave");
306 if (msr
->type
== TYPE_SERVER
)
308 if (!msr
->slave
->cType
.server
)
310 ERROR("Attempted to poll without a properly initialized server");
314 else if (msr
->type
== TYPE_CLIENT
)
316 if (!msr
->slave
->cType
.client
)
318 ERROR("Attempted to poll without a properly initialized client");
324 ERROR("Invalid Master type, bailing out");
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
))
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
);
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
);
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);
393 /*-------------------- Constructor Destructor ----------------------*/
395 /* see Master for the connection_type */
397 Master_Create(u32 connection_type
)
402 msr
= calloc(1, sizeof(Master
));
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
;
424 _err
= WSAStartup(MAKEWORD(1, 1), &msr
->wsaData
);
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
;
444 Master_Destroy(Master
*msr
)
454 Neuro_CleanEBuf(&msr
->cevents
);
457 Neuro_CleanLBuf(msr
->disco_clients
);
460 Neuro_CleanLBuf(msr
->statuses
);
462 Status_Destroy(msr
->status
);
465 Slave_Destroy(msr
->slave
);
467 Epoll_Destroy(msr
->ep
);