/* used to operate several inputs components at once (TCPSERVER,TCPCONNECT) */ #include #include #include #include #include #include "tlmpnet.h" #include "../tlmplib/tlmplib.h" class NETOBJECT: public ARRAY_OBJ{ public: HANDLE_SELECTS *sels; TCPSERVER *tcp; TCPSERVER_V1 *tcp_v1; /*~PROTOBEG~ NETOBJECT */ public: NETOBJECT (HANDLE_SELECTS&_sels); NETOBJECT (TCPSERVER&_tcp); NETOBJECT (TCPSERVER_V1&_tcp); ~NETOBJECT (void); /*~PROTOEND~ NETOBJECT */ }; PUBLIC NETOBJECT::NETOBJECT(HANDLE_SELECTS &_sels) { sels = &_sels; tcp = NULL; tcp_v1 = NULL; } PUBLIC NETOBJECT::NETOBJECT(TCPSERVER &_tcp) { tcp = &_tcp; tcp_v1 = NULL; sels = &_tcp; } PUBLIC NETOBJECT::NETOBJECT(TCPSERVER_V1 &_tcp) { tcp_v1 = &_tcp; tcp = NULL; sels = &_tcp; } PUBLIC NETOBJECT::~NETOBJECT() { if (tcp != NULL) tcp->forget_epoll(); if (tcp_v1 != NULL) tcp_v1->forget_epoll(); } class NETOBJECTS: public ARRAY_OBJS{ /*~PROTOBEG~ NETOBJECTS */ /*~PROTOEND~ NETOBJECTS */ }; class NETEVENT_MANAGER_PRIVATE{ public: _F_NETEVENT_MANAGER *c; NETOBJECTS objs; bool one_select; TLMPEPOLL ep; NETEVENT_MANAGER_PRIVATE(){ one_select = false; } }; void _F_NETEVENT_MANAGER::idle (int, bool &, bool) { } PUBLIC NETEVENT_MANAGER::NETEVENT_MANAGER(_F_NETEVENT_MANAGER &c) { priv = new NETEVENT_MANAGER_PRIVATE; priv->c = &c; } PUBLIC NETEVENT_MANAGER::~NETEVENT_MANAGER() { delete priv; } PUBLIC void NETEVENT_MANAGER::add (HANDLE_SELECTS &sels) { priv->objs.add (new NETOBJECT(sels)); priv->one_select = true; } PUBLIC void NETEVENT_MANAGER::add (TCPSERVER &tcp) { priv->objs.add (new NETOBJECT(tcp)); tcp.setup_epoll (priv->ep); } PUBLIC void NETEVENT_MANAGER::add (TCPSERVER_V1 &tcp) { priv->objs.add (new NETOBJECT(tcp)); tcp.setup_epoll (priv->ep); } #if 0 PUBLIC void NETEVENT_MANAGER::add (POPENHANDLER &pop) { priv->objs.add (new NETOBJECT(pop)); } #endif PRIVATE void NETEVENT_MANAGER::loopgen ( int timeout, bool gui, PRIVATE_MESSAGE &endmsg) { if (priv->one_select || gui){ // We must use select() because the GUI still does not support // epoll, nor HANDLE_SELECTS objects long since = 0; bool end = false; time_t lastidle = time(NULL); while (!end){ int maxhandle = 0; fd_set set; FD_ZERO (&set); for (int i=0; iobjs.getnb(); i++){ NETOBJECT *o = priv->objs.getitem(i); maxhandle = o->sels->setup_select (set,maxhandle); } int sel; maxhandle++; if (gui){ sel = diagui_select (maxhandle,&set,timeout,endmsg); if (sel == -2) break; }else{ struct timeval timeo; timeo.tv_sec = timeout; timeo.tv_usec = 0; sel = select (maxhandle,&set,NULL,NULL,&timeo); } if (sel == -1) break; time_t now = time(NULL); if (sel == 0){ since += timeout; priv->c->idle(since,end,maxhandle==0); lastidle = now; }else{ since = 0; if (now - lastidle >= timeout){ lastidle = now; priv->c->idle(since,end,maxhandle==0); } } for (int i=0; iobjs.getnb(); i++){ NETOBJECT *o = priv->objs.getitem(i); o->sels->process_select (sel,set,timeout); } } }else{ long since = 0; bool end = false; int mseconds = timeout * 1000; time_t lastidle = time(NULL); // Last time we called idle() while (!end){ TLMPEPOLL_EVENT events[100]; int nb = priv->ep.wait (events,100,mseconds); time_t now = time(NULL); if (nb == 0){ since += timeout; priv->c->idle(since,end,false); lastidle = now; }else{ since = 0; if (now - lastidle >= timeout){ lastidle = now; priv->c->idle(since,end,false); } for (int i=0; iobjs.getnb(); i++){ NETOBJECT *o = priv->objs.getitem(i); if (o->tcp != NULL){ o->tcp->process_epoll (priv->ep,events,nb); }else if (o->tcp_v1 != NULL){ o->tcp_v1->process_epoll (priv->ep,events,nb); }else{ tlmp_error ("netevent: no tcp object defined\n"); } } } } } } PUBLIC void NETEVENT_MANAGER::loop (int timeout) { PRIVATE_MESSAGE endmsg; loopgen (timeout,false,endmsg); } PUBLIC void NETEVENT_MANAGER::loopgui (int timeout, PRIVATE_MESSAGE &endmsg) { loopgen (timeout,true,endmsg); }