Annotation of libwww/Library/src/HTEvtLst.c, revision 2.3
2.1 frystyk 1: /* HTEvntrg.c
2: ** EVENT MANAGER
3: **
4: ** (c) COPYRIGHT MIT 1995.
5: ** Please first read the full copyright statement in the file COPYRIGH.
2.3 ! eric 6: ** @(#) $Id: HTEvtLst.c,v 2.2 1996/12/03 05:45:36 eric Exp $
2.1 frystyk 7: **
8: ** Updated HTEvent module
9: ** This new module combines the functions of the old HTEvent module and
10: ** the HTThread module. We retain the old HTThread module, but it
11: ** consists of calls to the HTEvent interfaces
12: **
13: ** Authors:
14: ** HFN Henrik Frystyk <frystyk@w3.org>
15: ** CLB Charlie Brooks <cbrooks@osf.org>
16: ** Bugs
17: **
18: */
19:
20: /* WSAAsyncSelect and windows app stuff need the following definitions:
21: * WWW_WIN_ASYNC - enable WSAAsyncSelect instead of select
22: * _WIN23 - win32 libararies - may be window or console app
23: * _WINSOCKAPI_ - using WINSOCK.DLL - not necessarily the async routines.
24: * _CONSOLE - the console app for NT
25: *
26: * first pass: EGP - 10/26/95
27: */
28:
29: /* Implementation dependent include files */
30: #include "sysdep.h"
31: #include "WWWUtil.h"
32: #include "WWWCore.h"
33: #include "HTReqMan.h"
34: #include "HTTimer.h"
35: #include "HTEvtLst.h" /* Implemented here */
36:
37: /* Type definitions and global variables etc. local to this module */
38: #define PRIME_TABLE_SIZE 67
39: #define MILLI_PER_SECOND 1000
40: #define HASH(s) ((s) % PRIME_TABLE_SIZE)
2.2 eric 41: #define HT_EVENT_ORDER /* use event ordering code */
42: #define EVENTS_TO_EXECUTE 5 /* how many to execute in one select loop */
2.1 frystyk 43:
2.3 ! eric 44: #ifdef WWW_WIN_ASYNC
! 45: #define TIMEOUT 1 /* WM_TIMER id */
! 46: PRIVATE HWND HTSocketWin;
! 47: PRIVATE unsigned long HTwinMsg;
! 48: #else /* WWW_WIN_ASYNC */
! 49: PRIVATE fd_set FdArray[HTEvent_TYPES];
! 50: PRIVATE SOCKET MaxSock = 0 ; /* max socket value in use */
! 51: #endif /* !WWW_WIN_ASYNC */
2.1 frystyk 52:
2.3 ! eric 53: typedef struct {
! 54: SOCKET s ; /* our socket */
! 55: HTEvent * events[HTEvent_TYPES]; /* event parameters for read, write, oob */
! 56: HTTimer * timeouts[HTEvent_TYPES];/* timeout for each of the events */
! 57: } SockEvents;
! 58:
! 59: typedef enum {
! 60: SockEvents_mayCreate,
! 61: SockEvents_find
! 62: } SockEvents_action;
2.1 frystyk 63:
2.2 eric 64: HTList * HashTable[PRIME_TABLE_SIZE];
2.1 frystyk 65: PRIVATE int HTEndLoop = 0; /* If !0 then exit event loop */
66:
67: /* ------------------------------------------------------------------------- */
68:
2.3 ! eric 69: PRIVATE SockEvents * SockEvents_get (SOCKET s, SockEvents_action action)
2.1 frystyk 70: {
71: long v = HASH(s);
2.2 eric 72: HTList* cur;
2.3 ! eric 73: SockEvents * pres;
2.2 eric 74:
75: if (HashTable[v] == NULL)
76: HashTable[v] = HTList_new();
77: cur = HashTable[v];
2.3 ! eric 78: while ((pres = (SockEvents *) HTList_nextObject(cur)))
2.2 eric 79: if (pres->s == s)
80: return pres;
81:
2.3 ! eric 82: if (action == SockEvents_mayCreate) {
! 83: if ((pres = (SockEvents *) HT_CALLOC(1, sizeof(SockEvents))) == NULL)
2.1 frystyk 84: HT_OUTOFMEM("HTEventList_register");
2.2 eric 85: pres->s = s;
86: HTList_addObject(HashTable[v], (void *)pres);
87: return pres;
2.1 frystyk 88: }
89: return NULL;
90: }
91:
2.3 ! eric 92: PUBLIC void HTEvent_traceHead(void)
! 93: {
! 94: HTTrace(" event: pri millis callback param request ");
! 95: }
! 96: PUBLIC void HTEvent_trace(HTEvent * event)
! 97: {
! 98: if (event == NULL)
! 99: return;
! 100: HTTrace("%8p: %3d %6d %8p %8p %8p", event, event->priority, event->millis, event->cbf, event->param, event->request);
! 101: }
! 102: PUBLIC void HTTimer_traceHead(void)
! 103: {
! 104: HTTrace(" timer: millis expires ? param callback ");
! 105: }
! 106: PRIVATE char * MyTime(unsigned long int time, int len)
! 107: {
! 108: static char space[100];
! 109: sprintf(space, "1234567");
! 110: return space;
! 111: }
! 112: struct _HTTimer {
! 113: HTTimer * next; /* The next guy in line */
! 114: ms_t millis; /* Relative value in millis */
! 115: ms_t expires; /* Absolute value in millis */
! 116: BOOL relative;
! 117: void * param; /* Client supplied context */
! 118: HTTimerCallback * cbf;
! 119: };
! 120:
! 121: PUBLIC void HTTimer_trace(HTTimer * timer)
! 122: {
! 123: if (timer == NULL)
! 124: return;
! 125: HTTrace("%8p: %6d %7s %c %8p %8p", timer, timer->millis, MyTime(timer->expires, 7),
! 126: timer->relative == YES ? 'R' : 'A', timer->param, timer->cbf);
! 127: }
2.1 frystyk 128: /*
129: ** A simple debug function that dumps all the socket arrays
130: ** as trace messages
131: */
2.3 ! eric 132: PRIVATE void EventList_dump (void)
2.1 frystyk 133: {
2.3 ! eric 134: long v;
! 135: HTList* cur;
! 136: SockEvents * pres;
! 137:
! 138: if (HashTable[v] == NULL) {
! 139: HTTrace("Event....... No sockets registered\n");
! 140: return;
! 141: }
! 142: HTTrace("Event....... Dumping socket events\n");
! 143: HTTrace("soc ");
! 144: HTEvent_traceHead();
! 145: HTTrace(" ");
! 146: HTTimer_traceHead();
! 147: HTTrace("\n");
! 148: for (v = 0; v < PRIME_TABLE_SIZE; v++) {
! 149: cur = HashTable[v];
! 150: while ((pres = (SockEvents *) HTList_nextObject(cur))) {
! 151: int i;
! 152: HTTrace("%3d \n", pres->s);
! 153: for (i = 0; i < HTEvent_TYPES; i++)
! 154: if (pres->events[i]) {
! 155: static char * names[HTEvent_TYPES] = {"read", "writ", "xcpt"};
! 156: HTTrace("%s", names[i]);
! 157: HTEvent_trace(pres->events[i]);
! 158: HTTrace(" ");
! 159: HTTimer_trace(pres->timeouts[i]);
! 160: HTTrace(" ");
! 161: }
! 162: HTTrace("\n");
! 163: }
! 164: }
2.1 frystyk 165: }
166:
167: /* ------------------------------------------------------------------------- */
2.2 eric 168: /* E V E N T O R D E R I N G S T U F F */
169: #ifdef HT_EVENT_ORDER
170: typedef struct {
171: HTEvent * event;
172: SOCKET s;
173: HTEventType type;
174: HTPriority skipped;
175: } EventOrder;
2.1 frystyk 176:
2.2 eric 177: HTList * EventOrderList = NULL;
178: #if 0
179: /*
180: ** return -1 if a should be after b
181: */
182: int EventOrderComparer (const void * a, const void * b)
183: {
184: EventOrder * placeMe = (EventOrder *)a;
185: EventOrder * maybeHere = (EventOrder *)b;
186: if (placeMe->event->priority+placeMe->skipped >= maybeHere->event->priority+maybeHere->skipped)
187: return 1;
188: return -1;
189: }
190: #endif
191:
192: int EventOrder_add (SOCKET s, HTEventType type)
193: {
194: EventOrder * pres;
195: HTList * cur = EventOrderList;
196: HTList * insertAfter = cur;
197: HTEvent * event = HTEventList_lookup(s, type);
198:
199: if (event == NULL) {
200: HTTrace("EventOrder.. no event found for socket %d, type %x.\n", s, type);
201: return HT_ERROR;
202: }
203:
204: /*
205: ** Look to see if it's already here from before
206: */
207: while ((pres = (EventOrder *) HTList_nextObject(cur))) {
208: if (pres->s == s && pres->event == event && pres->type == type) {
209: pres->skipped++;
210: return HT_OK;
211: }
212: if (pres->event->priority+pres->skipped > event->priority)
213: insertAfter = cur;
214: }
215:
216: /*
217: ** No, so create a new element
218: */
219: if ((pres = (EventOrder *) HT_CALLOC(1, sizeof(EventOrder))) == NULL)
220: HT_OUTOFMEM("EventOrder_add");
221: pres->event = event;
222: pres->s = s;
223: pres->type = type;
224: HTList_addObject(insertAfter, (void *)pres);
225: return HT_OK;
226: }
227:
228: PUBLIC int EventOrder_executeAndDelete (void)
229: {
230: HTList * cur;
231: EventOrder * pres;
232: int i = 0;
233:
234: if (cur == NULL)
235: return NO;
236: #if 0
237: HTList_insertionSort(EventOrderList, EventOrderComparer);
238: #endif
239: cur = EventOrderList;
240: if (THD_TRACE) HTTrace("EventOrder.. execute ordered events\n");
241: while ((pres = (EventOrder *) HTList_removeLastObject(cur)) && i < EVENTS_TO_EXECUTE) {
242: int ret = (*pres->event->cbf)(pres->s, pres->event->param, pres->type);
243: HT_FREE(pres);
244: if (ret != HT_OK)
245: return ret;
246: i++;
247: }
248: return HT_OK;
249: }
250:
251: PUBLIC BOOL EventOrder_deleteAll (void)
252: {
253: HTList * cur = EventOrderList;
254: EventOrder * pres;
255:
256: if (cur == NULL)
257: return NO;
258: if (THD_TRACE) HTTrace("EventOrder.. all ordered events\n");
259: while ((pres = (EventOrder *) HTList_nextObject(cur)))
260: HT_FREE(pres);
261: HTList_delete(EventOrderList);
262: EventOrderList = NULL;
263: return YES;
264: }
265: #endif /* HT_EVENT_ORDER */
266:
267: /* ------------------------------------------------------------------------- */
268: /* T I M E O U T H A N D L E R */
2.1 frystyk 269: PRIVATE int EventListTimerHandler (HTTimer * timer, void * param)
270: {
2.3 ! eric 271: SockEvents * sockp = (SockEvents *)param;
2.1 frystyk 272: HTEvent * event;
2.3 ! eric 273: if (sockp->timeouts[HTEvent_INDEX(HTEvent_READ)] == timer) {
! 274: event = sockp->events[HTEvent_INDEX(HTEvent_READ)];
! 275: if (THD_TRACE) HTTrace("Event....... READ timed out on %d.\n", sockp->s);
! 276: return (*event->cbf) (sockp->s, event->param, HTEvent_TIMEOUT);
! 277: }
! 278: if (sockp->timeouts[HTEvent_INDEX(HTEvent_WRITE)] == timer) {
! 279: event = sockp->events[HTEvent_INDEX(HTEvent_WRITE)];
! 280: if (THD_TRACE) HTTrace("Event....... WRITE timed out on %d.\n", sockp->s);
! 281: return (*event->cbf) (sockp->s, event->param, HTEvent_TIMEOUT);
! 282: }
! 283: if (sockp->timeouts[HTEvent_INDEX(HTEvent_OOB)] == timer) {
! 284: event = sockp->events[HTEvent_INDEX(HTEvent_OOB)];
! 285: if (THD_TRACE) HTTrace("Event....... OOB timed out on %d.\n", sockp->s);
! 286: return (*event->cbf) (sockp->s, event->param, HTEvent_TIMEOUT);
2.1 frystyk 287: }
288: HTTrace("Event....... can't find event for timer %p.\n", timer);
289: return HT_ERROR;
290: }
291:
292: /* ------------------------------------------------------------------------- */
293:
294: /*
295: ** For a given socket, reqister a request structure, a set of operations,
296: ** a HTEventCallback function, and a priority. For this implementation,
297: ** we allow only a single HTEventCallback function for all operations.
298: ** and the priority field is ignored.
299: */
300: PUBLIC int HTEventList_register (SOCKET s, HTEventType type, HTEvent * event)
301: {
2.3 ! eric 302: SockEvents * sockp;
2.1 frystyk 303: if (THD_TRACE)
304: HTTrace("Event....... Register socket %d, request %p handler %p type %x at priority %d\n",
305: s, (void *) event->request,
306: (void *) event->cbf, (unsigned) type,
307: (unsigned) event->priority);
308: if (s==INVSOC || HTEvent_INDEX(type) > 2)
309: return 0;
310: #if 0
311: /*
2.3 ! eric 312: ** Don't write down TIMEOUT events in the SockEvents list or the fd sets.
2.1 frystyk 313: ** They just manifest in the HTTimer
314: */
315: if (type == HTEvent_TIMEOUT)
316: return HT_OK;
317: #endif /* 0 */
318:
319: /*
320: ** Insert socket into appropriate file descriptor set. We also make sure
321: ** that it is registered in the global set.
322: */
323: if (THD_TRACE) HTTrace("Event....... Registering socket for %d\n", type);
2.3 ! eric 324: sockp = SockEvents_get(s, SockEvents_mayCreate);
! 325: sockp->s = s;
! 326: sockp->events[HTEvent_INDEX(type)] = event;
! 327: #ifdef WWW_WIN_ASYNC
! 328: if (WSAAsyncSelect(s, HTSocketWin, HTwinMsg, HTEvent_INDEX(type)) < 0)
! 329: return HT_ERROR;
! 330: #else /* WWW_WIN_ASYNC */
2.1 frystyk 331: FD_SET(s, FdArray+HTEvent_INDEX(type));
2.3 ! eric 332: if (s > MaxSock) MaxSock = s ;
! 333: #endif /* !WWW_WIN_ASYNC */
2.1 frystyk 334: /*
335: ** If the timeout has been set (relative in millis) then we register
336: ** a new timeout for this event
337: */
338: if (event->millis >= 0) {
2.3 ! eric 339: sockp->timeouts[HTEvent_INDEX(type)] = HTTimer_new(NULL, EventListTimerHandler, sockp, event->millis, YES);
2.1 frystyk 340: }
341:
342: return HT_OK;
343: }
344:
2.3 ! eric 345: PRIVATE int EventList_remaining(SockEvents * pres)
! 346: {
! 347: int ret = 0;
! 348: int i;
! 349: for (i = 0; i < HTEvent_TYPES; i++)
! 350: if (pres->events[i] != NULL)
! 351: ret |= 1<<i;
! 352: return ret;
! 353: }
! 354:
2.1 frystyk 355: /*
356: ** Remove the registered information for the specified socket for the actions
357: ** specified in ops. if no actions remain after the unregister, the registered
358: ** info is deleted, and, if the socket has been registered for notification,
359: ** the HTEventCallback will be invoked.
360: */
361: PUBLIC int HTEventList_unregister(SOCKET s, HTEventType type)
362: {
2.3 ! eric 363: long v = HASH(s);
! 364: HTList * cur = HashTable[v];
! 365: HTList * last = cur;
! 366: SockEvents * pres;
2.2 eric 367:
2.3 ! eric 368: while ((pres = (SockEvents *) HTList_nextObject(cur))) {
2.2 eric 369: if (pres->s == s) {
2.3 ! eric 370: int remaining;
2.1 frystyk 371:
372: /*
373: ** Unregister the event from this action
374: */
2.2 eric 375: pres->events[HTEvent_INDEX(type)] = NULL;
2.1 frystyk 376:
377: /*
378: ** Check to see of there was a timeout connected with the event.
379: ** If so then delete the timeout as well.
380: */
381: {
2.2 eric 382: HTTimer * timer = pres->timeouts[HTEvent_INDEX(type)];
2.1 frystyk 383: if (timer) HTTimer_delete(timer);
384: }
385:
386: /*
387: ** Check to see if we can delete the action completely. We do this
388: ** if there are no more events registered.
389: */
2.3 ! eric 390: if ((remaining = EventList_remaining(pres)) == 0) {
2.1 frystyk 391: if (THD_TRACE)
392: HTTrace("Event....... No more events registered for socket %d\n", s);
2.2 eric 393: HT_FREE(pres);
2.3 ! eric 394: HTList_quickRemoveElement(cur, last);
2.2 eric 395: } else
396: last = cur; /* to set next pointer when creating new */
2.3 ! eric 397: #ifdef WWW_WIN_ASYNC
! 398: if (WSAAsyncSelect(s, HTSocketWin, HTwinMsg, remaining) < 0)
! 399: return HT_ERROR;
! 400: #else /* WWW_WIN_ASYNC */
! 401: FD_CLR(s, FdArray+HTEvent_INDEX(type));
! 402: #endif /* !WWW_WIN_ASYNC */
! 403: if (THD_TRACE)
2.1 frystyk 404: HTTrace("Event....... Socket %d unregisterd for %x\n", s, type);
405: return HT_OK;
406: }
407: }
408: if (THD_TRACE) HTTrace("Event....... Couldn't find socket %d.\n", s);
409: return HT_ERROR;
410: }
411:
412: /*
413: ** Unregister all sockets
414: ** N.B. we just remove them for our internal data structures: it is up to the
415: ** application to actually close the socket.
416: */
2.2 eric 417: PUBLIC int HTEventList_unregisterAll (void)
2.1 frystyk 418: {
419: int i;
420: if (THD_TRACE) HTTrace("Unregister.. all sockets\n");
421: for (i = 0 ; i < PRIME_TABLE_SIZE; i++) {
2.2 eric 422: HTList * cur = HashTable[i];
2.3 ! eric 423: SockEvents * pres;
! 424: while ((pres = (SockEvents *) HTList_nextObject(cur))) {
! 425: #ifdef WWW_WIN_ASYNC
! 426: WSAAsyncSelect(pres->s, HTSocketWin, HTwinMsg, 0);
! 427: #endif /* WWW_WIN_ASYNC */
2.2 eric 428: HT_FREE(pres);
2.3 ! eric 429: }
2.2 eric 430: HTList_delete(HashTable[i]);
431: HashTable[i] = NULL;
2.1 frystyk 432: }
2.3 ! eric 433: #ifndef WWW_WIN_ASYNC
! 434: MaxSock = 0 ;
2.1 frystyk 435: FD_ZERO(FdArray+HTEvent_INDEX(HTEvent_READ));
436: FD_ZERO(FdArray+HTEvent_INDEX(HTEvent_WRITE));
437: FD_ZERO(FdArray+HTEvent_INDEX(HTEvent_OOB));
2.3 ! eric 438: #endif /* !WWW_WIN_ASYNC */
2.2 eric 439: #ifdef HT_EVENT_ORDER
440: EventOrder_deleteAll();
441: #endif /* HT_EVENT_ORDER */
2.1 frystyk 442: return 0;
443: }
444:
445: /*
446: ** Dispatch the event to the appropriate event handler.
447: ** If no event handler is found then just return.
448: */
449: PUBLIC int HTEventList_dispatch (SOCKET s, HTEventType type)
450: {
2.3 ! eric 451: SockEvents * sockp = SockEvents_get(s, SockEvents_find);
! 452: if (sockp) {
! 453: HTEvent * event = sockp->events[HTEvent_INDEX(type)];
2.1 frystyk 454:
455: /*
456: ** If we have found an event object for this event then see
457: ** is we should call it.
458: */
459: if (event && event->priority!=HT_PRIORITY_OFF)
460: return (*event->cbf) (s, event->param, type);
2.3 ! eric 461: if (THD_TRACE) HTTrace("Dispatch.... Handler %p NOT called\n", sockp);
2.1 frystyk 462: return HT_OK;
463: }
464: if (THD_TRACE) HTTrace("Dispatch.... Bad socket %d\n", s);
465: return NO;
466: }
467:
468: /*
469: ** Stops the (select based) event loop. The function does not guarantee
470: ** that all requests have terminated. This is for the app to do
471: */
472: PUBLIC void HTEventList_stopLoop (void)
473: {
474: HTEndLoop = 1;
475: }
476:
2.3 ! eric 477: PUBLIC HTEvent * HTEventList_lookup (SOCKET s, HTEventType type)
! 478: {
! 479: SockEvents * sockp = NULL;
! 480: if ((sockp = SockEvents_get(s, SockEvents_find)) == NULL)
! 481: return NULL;
! 482: return sockp->events[HTEvent_INDEX(type)];
! 483: }
! 484:
! 485: /* REGISTER DEFULT EVENT MANAGER
! 486: ** -----------------------------
! 487: ** Not done automaticly - may be done by application!
! 488: */
! 489: PUBLIC BOOL HTEventInit (void)
! 490: {
! 491: HTEvent_setRegisterCallback(HTEventList_register);
! 492: HTEvent_setUnregisterCallback(HTEventList_unregister);
! 493: return YES;
! 494: }
! 495:
! 496: PUBLIC BOOL HTEventTerminate (void)
! 497: {
! 498: return YES;
! 499: }
! 500:
! 501: #ifdef WWW_WIN_ASYNC
! 502:
! 503: /* HTEventrg_get/setWinHandle
! 504: ** --------------------------
! 505: ** Managing the windows handle on Windows
! 506: */
! 507: PUBLIC BOOL HTEventList_setWinHandle (HWND window, unsigned long message)
! 508: {
! 509: HTSocketWin = window;
! 510: HTwinMsg = message;
! 511: return YES;
! 512: }
! 513:
! 514: PUBLIC HWND HTEventList_getWinHandle (unsigned long * pMessage)
! 515: {
! 516: if (pMessage)
! 517: *pMessage = HTwinMsg;
! 518: return (HTSocketWin);
! 519: }
! 520:
! 521: PUBLIC BOOL HTEventList_asyncWindowsTimer(HTTimer * timer, ms_t millis)
! 522: {
! 523: if (SetTimer(HTSocketWin, (UINT)timer, millis) > 0)
! 524: return YES;
! 525: return NO;
! 526: }
! 527:
! 528: /* only responsible for WM_TIMER and WSA_AsyncSelect */
! 529: PUBLIC LRESULT CALLBACK AsyncWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
! 530: {
! 531: WORD event;
! 532: SOCKET sock;
! 533:
! 534: /* timeout stuff */
! 535: if (uMsg == WM_TIMER) {
! 536: HTTimer_dispatch((HTTimer *)lParam);
! 537: return (0);
! 538: }
! 539:
! 540: if (uMsg != HTwinMsg) /* not our async message */
! 541: return (DefWindowProc(hwnd, uMsg, wParam, lParam));
! 542:
! 543: event = LOWORD(lParam);
! 544: sock = (SOCKET)wParam;
! 545: if (event & (FD_READ | FD_ACCEPT | FD_CLOSE))
! 546: if (HTEventrg_dispatch((int)sock, FD_READ) != HT_OK) {
! 547: HTEndLoop = -1;
! 548: return 0;
! 549: }
! 550: if (event & (FD_WRITE | FD_CONNECT))
! 551: if (HTEventrg_dispatch((int)sock, FD_WRITE) != HT_OK) {
! 552: HTEndLoop = -1;
! 553: return 0;
! 554: }
! 555: if (event & FD_OOB)
! 556: if (HTEventrg_dispatch((int)sock, FD_OOB) != HT_OK) {
! 557: HTEndLoop = -1;
! 558: return 0;
! 559: }
! 560: return (0);
! 561: }
! 562:
! 563: PUBLIC int HTEventrg_loop (HTRequest * theRequest )
! 564: {
! 565: MSG msg;
! 566: while (GetMessage(&msg,0,0,0)) {
! 567: TranslateMessage(&msg);
! 568: DispatchMessage(&msg);
! 569: }
! 570: return (HTEndLoop == 1 ? HT_OK : HT_ERROR);
! 571: }
! 572:
! 573: #else /* WWW_WIN_ASYNC */
! 574:
2.1 frystyk 575: /*
576: ** We wait for activity from one of our registered
577: ** channels, and dispatch on that.
578: **
579: ** There are now two versions of the event loop. The first is if you want
580: ** to use async I/O on windows, and the other is if you want to use normal
581: ** Unix setup with sockets
582: */
583: PUBLIC int HTEventList_loop (HTRequest * theRequest)
584: {
585: fd_set treadset, twriteset, texceptset;
586: struct timeval waittime, * wt;
587: int active_sockets;
588: int maxfds;
589: int timeout;
590: SOCKET s;
591: int status = 0;
592: HTEndLoop = 0;
593:
2.2 eric 594: EventOrderList = HTList_new(); /* is kept around until EventOrder_deleteAll */
595:
2.1 frystyk 596: /* Don't leave this loop until we leave the application */
597: do {
598: treadset = FdArray[HTEvent_INDEX(HTEvent_READ)];
599: twriteset = FdArray[HTEvent_INDEX(HTEvent_WRITE)];
600: texceptset = FdArray[HTEvent_INDEX(HTEvent_OOB)];
2.3 ! eric 601: maxfds = MaxSock;
2.1 frystyk 602:
603: if (THD_TRACE) HTTrace("Event Loop.. calling select: maxfds is %d\n", maxfds);
604:
605: /*
606: ** Timeval struct copy needed for linux, as it set the value to the
607: ** remaining timeout while exiting the select. (and perhaps for
608: ** other OS). Code borrowed from X server.
609: */
610: wt = NULL;
611: if ((timeout = HTTimer_soonest())) {
612: waittime.tv_sec = timeout / MILLI_PER_SECOND;
613: waittime.tv_usec = (timeout % MILLI_PER_SECOND) *
614: (1000000 / MILLI_PER_SECOND);
615: wt = &waittime;
616: }
617:
2.2 eric 618: HTTraceData((char*)&treadset, maxfds/8 + 1, "HTEventList_loop pre treadset: (maxfd:%d)", maxfds);
619: HTTraceData((char*)&twriteset, maxfds/8 + 1, "HTEventList_loop pre twriteset:");
620: HTTraceData((char*)&texceptset, maxfds/8 + 1, "HTEventList_loop pre texceptset:");
621:
2.1 frystyk 622: #ifdef __hpux
623: active_sockets = select(maxfds+1, (int *)&treadset, (int *)&twriteset,
624: (int *)&texceptset, wt);
625: #else
626: active_sockets = select(maxfds+1, &treadset, &twriteset, &texceptset, wt);
627: #endif
2.2 eric 628:
629: HTTraceData((char*)&treadset, maxfds/8 + 1, "HTEventList_loop post treadset: (active_sockets:%d)", active_sockets);
630: HTTraceData((char*)&twriteset, maxfds/8 + 1, "HTEventList_loop post twriteset: (errno:%d)", errno);
631: HTTraceData((char*)&texceptset, maxfds/8 + 1, "HTEventList_loop post texceptset:");
632:
2.1 frystyk 633: if (THD_TRACE) HTTrace("Event Loop.. select returns %d\n", active_sockets);
634:
635: if (active_sockets == -1) {
636: HTRequest_addSystemError( theRequest, ERR_FATAL, socerrno, NO, "select");
2.3 ! eric 637: EventList_dump();
! 638: #if 0
2.1 frystyk 639: __DumpFDSet(FdArray+HTEvent_INDEX(HTEvent_READ), "Read");
640: __DumpFDSet(FdArray+HTEvent_INDEX(HTEvent_WRITE), "Write") ;
641: __DumpFDSet(FdArray+HTEvent_INDEX(HTEvent_OOB), "Exceptions");
2.3 ! eric 642: #endif /* 0 */
2.1 frystyk 643: return HT_ERROR;
644: }
645:
646: /*
647: ** We had a timeout so now we check and see if we have a timeout
648: ** handler to call
649: */
650: if (active_sockets == 0) {
651: HTTimer_dispatchAll();
652: continue;
653: }
654:
655: /*
656: ** There were active sockets. Determine which fd sets they were in
657: */
2.2 eric 658: #ifdef HT_EVENT_ORDER
659: #define DISPATCH(socket, type) EventOrder_add(socket, type)
660: #else /* HT_EVENT_ORDER */
661: #define DISPATCH(socket, type) HTEventList_dispatch(socket, type)
662: #endif /* !HT_EVENT_ORDER */
2.1 frystyk 663: for (s = 0 ; s <= maxfds ; s++) {
664: if (FD_ISSET(s, &texceptset))
2.2 eric 665: if ((status = DISPATCH(s, HTEvent_OOB)) != HT_OK)
2.1 frystyk 666: return status;
667: if (FD_ISSET(s, &twriteset))
2.2 eric 668: if ((status = DISPATCH(s, HTEvent_WRITE)) != HT_OK)
2.1 frystyk 669: return status;
670: if (FD_ISSET(s, &treadset))
2.2 eric 671: if ((status = DISPATCH(s, HTEvent_READ)) != HT_OK)
2.1 frystyk 672: return status;
673: }
2.2 eric 674: #ifdef HT_EVENT_ORDER
675: if ((status = EventOrder_executeAndDelete()) != HT_OK)
676: return status;
677: #endif /* HT_EVENT_ORDER */
2.1 frystyk 678: } while (!HTEndLoop);
679:
680: return HT_OK;
681: }
682:
2.3 ! eric 683: #endif /* !WWW_WIN_ASYNC */
Webmaster