Annotation of libwww/Library/src/HTEvtLst.c, revision 2.4
2.4 ! eric 1: /* HTEvtLst.c
2.1 frystyk 2: ** EVENT MANAGER
3: **
4: ** (c) COPYRIGHT MIT 1995.
5: ** Please first read the full copyright statement in the file COPYRIGH.
2.4 ! eric 6: ** @(#) $Id: HTEvtLst.c,v 2.3 1996/12/05 23:19:59 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: {
2.4 ! eric 230: HTList * cur = EventOrderList;
2.2 eric 231: EventOrder * pres;
232: int i = 0;
233: if (THD_TRACE) HTTrace("EventOrder.. execute ordered events\n");
2.4 ! eric 234: if (cur == NULL) return NO;
2.2 eric 235: while ((pres = (EventOrder *) HTList_removeLastObject(cur)) && i < EVENTS_TO_EXECUTE) {
236: int ret = (*pres->event->cbf)(pres->s, pres->event->param, pres->type);
237: HT_FREE(pres);
238: if (ret != HT_OK)
239: return ret;
240: i++;
241: }
242: return HT_OK;
243: }
244:
245: PUBLIC BOOL EventOrder_deleteAll (void)
246: {
247: HTList * cur = EventOrderList;
248: EventOrder * pres;
249: if (THD_TRACE) HTTrace("EventOrder.. all ordered events\n");
2.4 ! eric 250: if (cur == NULL) return NO;
2.2 eric 251: while ((pres = (EventOrder *) HTList_nextObject(cur)))
252: HT_FREE(pres);
253: HTList_delete(EventOrderList);
254: EventOrderList = NULL;
255: return YES;
256: }
257: #endif /* HT_EVENT_ORDER */
258:
259: /* ------------------------------------------------------------------------- */
260: /* T I M E O U T H A N D L E R */
2.1 frystyk 261: PRIVATE int EventListTimerHandler (HTTimer * timer, void * param)
262: {
2.3 eric 263: SockEvents * sockp = (SockEvents *)param;
2.1 frystyk 264: HTEvent * event;
2.3 eric 265: if (sockp->timeouts[HTEvent_INDEX(HTEvent_READ)] == timer) {
266: event = sockp->events[HTEvent_INDEX(HTEvent_READ)];
267: if (THD_TRACE) HTTrace("Event....... READ timed out on %d.\n", sockp->s);
268: return (*event->cbf) (sockp->s, event->param, HTEvent_TIMEOUT);
269: }
270: if (sockp->timeouts[HTEvent_INDEX(HTEvent_WRITE)] == timer) {
271: event = sockp->events[HTEvent_INDEX(HTEvent_WRITE)];
272: if (THD_TRACE) HTTrace("Event....... WRITE timed out on %d.\n", sockp->s);
273: return (*event->cbf) (sockp->s, event->param, HTEvent_TIMEOUT);
274: }
275: if (sockp->timeouts[HTEvent_INDEX(HTEvent_OOB)] == timer) {
276: event = sockp->events[HTEvent_INDEX(HTEvent_OOB)];
277: if (THD_TRACE) HTTrace("Event....... OOB timed out on %d.\n", sockp->s);
278: return (*event->cbf) (sockp->s, event->param, HTEvent_TIMEOUT);
2.1 frystyk 279: }
280: HTTrace("Event....... can't find event for timer %p.\n", timer);
281: return HT_ERROR;
282: }
283:
284: /* ------------------------------------------------------------------------- */
285:
286: /*
287: ** For a given socket, reqister a request structure, a set of operations,
288: ** a HTEventCallback function, and a priority. For this implementation,
289: ** we allow only a single HTEventCallback function for all operations.
290: ** and the priority field is ignored.
291: */
292: PUBLIC int HTEventList_register (SOCKET s, HTEventType type, HTEvent * event)
293: {
2.3 eric 294: SockEvents * sockp;
2.1 frystyk 295: if (THD_TRACE)
296: HTTrace("Event....... Register socket %d, request %p handler %p type %x at priority %d\n",
297: s, (void *) event->request,
298: (void *) event->cbf, (unsigned) type,
299: (unsigned) event->priority);
2.4 ! eric 300: if (s==INVSOC || HTEvent_INDEX(type) >= HTEvent_TYPES)
2.1 frystyk 301: return 0;
302: #if 0
303: /*
2.3 eric 304: ** Don't write down TIMEOUT events in the SockEvents list or the fd sets.
2.1 frystyk 305: ** They just manifest in the HTTimer
306: */
307: if (type == HTEvent_TIMEOUT)
308: return HT_OK;
309: #endif /* 0 */
310:
311: /*
312: ** Insert socket into appropriate file descriptor set. We also make sure
313: ** that it is registered in the global set.
314: */
315: if (THD_TRACE) HTTrace("Event....... Registering socket for %d\n", type);
2.3 eric 316: sockp = SockEvents_get(s, SockEvents_mayCreate);
317: sockp->s = s;
318: sockp->events[HTEvent_INDEX(type)] = event;
319: #ifdef WWW_WIN_ASYNC
2.4 ! eric 320: if (WSAAsyncSelect(s, HTSocketWin, HTwinMsg, HTEvent_BITS(type)) < 0)
2.3 eric 321: return HT_ERROR;
322: #else /* WWW_WIN_ASYNC */
2.1 frystyk 323: FD_SET(s, FdArray+HTEvent_INDEX(type));
2.3 eric 324: if (s > MaxSock) MaxSock = s ;
325: #endif /* !WWW_WIN_ASYNC */
2.1 frystyk 326: /*
327: ** If the timeout has been set (relative in millis) then we register
328: ** a new timeout for this event
329: */
330: if (event->millis >= 0) {
2.3 eric 331: sockp->timeouts[HTEvent_INDEX(type)] = HTTimer_new(NULL, EventListTimerHandler, sockp, event->millis, YES);
2.1 frystyk 332: }
333:
334: return HT_OK;
335: }
336:
2.3 eric 337: PRIVATE int EventList_remaining(SockEvents * pres)
338: {
339: int ret = 0;
340: int i;
341: for (i = 0; i < HTEvent_TYPES; i++)
342: if (pres->events[i] != NULL)
343: ret |= 1<<i;
344: return ret;
345: }
346:
2.1 frystyk 347: /*
348: ** Remove the registered information for the specified socket for the actions
349: ** specified in ops. if no actions remain after the unregister, the registered
350: ** info is deleted, and, if the socket has been registered for notification,
351: ** the HTEventCallback will be invoked.
352: */
353: PUBLIC int HTEventList_unregister(SOCKET s, HTEventType type)
354: {
2.3 eric 355: long v = HASH(s);
356: HTList * cur = HashTable[v];
357: HTList * last = cur;
358: SockEvents * pres;
2.2 eric 359:
2.3 eric 360: while ((pres = (SockEvents *) HTList_nextObject(cur))) {
2.2 eric 361: if (pres->s == s) {
2.3 eric 362: int remaining;
2.1 frystyk 363:
364: /*
365: ** Unregister the event from this action
366: */
2.2 eric 367: pres->events[HTEvent_INDEX(type)] = NULL;
2.1 frystyk 368:
369: /*
370: ** Check to see of there was a timeout connected with the event.
371: ** If so then delete the timeout as well.
372: */
373: {
2.2 eric 374: HTTimer * timer = pres->timeouts[HTEvent_INDEX(type)];
2.1 frystyk 375: if (timer) HTTimer_delete(timer);
376: }
377:
378: /*
379: ** Check to see if we can delete the action completely. We do this
380: ** if there are no more events registered.
381: */
2.3 eric 382: if ((remaining = EventList_remaining(pres)) == 0) {
2.1 frystyk 383: if (THD_TRACE)
384: HTTrace("Event....... No more events registered for socket %d\n", s);
2.2 eric 385: HT_FREE(pres);
2.3 eric 386: HTList_quickRemoveElement(cur, last);
2.2 eric 387: } else
388: last = cur; /* to set next pointer when creating new */
2.3 eric 389: #ifdef WWW_WIN_ASYNC
390: if (WSAAsyncSelect(s, HTSocketWin, HTwinMsg, remaining) < 0)
391: return HT_ERROR;
392: #else /* WWW_WIN_ASYNC */
393: FD_CLR(s, FdArray+HTEvent_INDEX(type));
394: #endif /* !WWW_WIN_ASYNC */
395: if (THD_TRACE)
2.1 frystyk 396: HTTrace("Event....... Socket %d unregisterd for %x\n", s, type);
397: return HT_OK;
398: }
399: }
400: if (THD_TRACE) HTTrace("Event....... Couldn't find socket %d.\n", s);
401: return HT_ERROR;
402: }
403:
404: /*
405: ** Unregister all sockets
406: ** N.B. we just remove them for our internal data structures: it is up to the
407: ** application to actually close the socket.
408: */
2.2 eric 409: PUBLIC int HTEventList_unregisterAll (void)
2.1 frystyk 410: {
411: int i;
412: if (THD_TRACE) HTTrace("Unregister.. all sockets\n");
413: for (i = 0 ; i < PRIME_TABLE_SIZE; i++) {
2.2 eric 414: HTList * cur = HashTable[i];
2.3 eric 415: SockEvents * pres;
416: while ((pres = (SockEvents *) HTList_nextObject(cur))) {
417: #ifdef WWW_WIN_ASYNC
418: WSAAsyncSelect(pres->s, HTSocketWin, HTwinMsg, 0);
419: #endif /* WWW_WIN_ASYNC */
2.2 eric 420: HT_FREE(pres);
2.3 eric 421: }
2.2 eric 422: HTList_delete(HashTable[i]);
423: HashTable[i] = NULL;
2.1 frystyk 424: }
2.3 eric 425: #ifndef WWW_WIN_ASYNC
426: MaxSock = 0 ;
2.1 frystyk 427: FD_ZERO(FdArray+HTEvent_INDEX(HTEvent_READ));
428: FD_ZERO(FdArray+HTEvent_INDEX(HTEvent_WRITE));
429: FD_ZERO(FdArray+HTEvent_INDEX(HTEvent_OOB));
2.3 eric 430: #endif /* !WWW_WIN_ASYNC */
2.2 eric 431: #ifdef HT_EVENT_ORDER
432: EventOrder_deleteAll();
433: #endif /* HT_EVENT_ORDER */
2.1 frystyk 434: return 0;
435: }
436:
437: /*
438: ** Dispatch the event to the appropriate event handler.
439: ** If no event handler is found then just return.
440: */
441: PUBLIC int HTEventList_dispatch (SOCKET s, HTEventType type)
442: {
2.3 eric 443: SockEvents * sockp = SockEvents_get(s, SockEvents_find);
444: if (sockp) {
445: HTEvent * event = sockp->events[HTEvent_INDEX(type)];
2.1 frystyk 446:
447: /*
448: ** If we have found an event object for this event then see
449: ** is we should call it.
450: */
451: if (event && event->priority!=HT_PRIORITY_OFF)
452: return (*event->cbf) (s, event->param, type);
2.3 eric 453: if (THD_TRACE) HTTrace("Dispatch.... Handler %p NOT called\n", sockp);
2.1 frystyk 454: return HT_OK;
455: }
456: if (THD_TRACE) HTTrace("Dispatch.... Bad socket %d\n", s);
457: return NO;
458: }
459:
460: /*
461: ** Stops the (select based) event loop. The function does not guarantee
462: ** that all requests have terminated. This is for the app to do
463: */
464: PUBLIC void HTEventList_stopLoop (void)
465: {
466: HTEndLoop = 1;
467: }
468:
2.3 eric 469: PUBLIC HTEvent * HTEventList_lookup (SOCKET s, HTEventType type)
470: {
471: SockEvents * sockp = NULL;
472: if ((sockp = SockEvents_get(s, SockEvents_find)) == NULL)
473: return NULL;
474: return sockp->events[HTEvent_INDEX(type)];
475: }
476:
477: /* REGISTER DEFULT EVENT MANAGER
478: ** -----------------------------
479: ** Not done automaticly - may be done by application!
480: */
481: PUBLIC BOOL HTEventInit (void)
482: {
2.4 ! eric 483: #ifdef WWW_WIN_ASYNC
! 484: /*
! 485: ** We are here starting a hidden window to take care of events from
! 486: ** the async select() call in the async version of the event loop in
! 487: ** the Internal event manager (HTEvtLst.c)
! 488: */
! 489: static char className[] = "AsyncWindowClass";
! 490: WNDCLASS wc;
! 491: OSVERSIONINFO osInfo;
! 492:
! 493: wc.style=0;
! 494: wc.lpfnWndProc=(WNDPROC)AsyncWindowProc;
! 495: wc.cbClsExtra=0;
! 496: wc.cbWndExtra=0;
! 497: wc.hIcon=0;
! 498: wc.hCursor=0;
! 499: wc.hbrBackground=0;
! 500: wc.lpszMenuName=(LPSTR)0;
! 501: wc.lpszClassName=className;
! 502:
! 503: osInfo.dwOSVersionInfoSize = sizeof(osInfo);
! 504: GetVersionEx(&osInfo);
! 505: if (osInfo.dwPlatformId == VER_PLATFORM_WIN32s || osInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
! 506: wc.hInstance=GetModuleHandle(NULL); /* 95 and non threaded platforms */
! 507: else
! 508: wc.hInstance=GetCurrentProcess(); /* NT and hopefully everything following */
! 509: if (!RegisterClass(&wc)) {
! 510: HTTrace("HTLibInit.. Can't RegisterClass \"%s\"\n", className);
! 511: return NO;
! 512: }
! 513: if (!(HTSocketWin = CreateWindow(className, "WWW_WIN_ASYNC", WS_POPUP, CW_USEDEFAULT, CW_USEDEFAULT,
! 514: CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, wc.hInstance,0))) {
! 515: char space[50];
! 516: HTTrace("HTLibInit.. Can't CreateWindow \"WWW_WIN_ASYNC\" - error:");
! 517: sprintf(space, "%ld\n", GetLastError());
! 518: HTTrace(space);
! 519: return NO;
! 520: }
! 521: HTwinMsg = WM_USER; /* use first available message since app uses none */
! 522: #endif /* WWW_WIN_ASYNC */
! 523:
! 524: #ifdef _WINSOCKAPI_
! 525: /*
! 526: ** Initialise WinSock DLL. This must also be shut down! PMH
! 527: */
! 528: {
! 529: WSADATA wsadata;
! 530: if (WSAStartup(DESIRED_WINSOCK_VERSION, &wsadata)) {
! 531: if (WWWTRACE)
! 532: HTTrace("HTEventInit. Can't initialize WinSoc\n");
! 533: WSACleanup();
! 534: return NO;
! 535: }
! 536: if (wsadata.wVersion < MINIMUM_WINSOCK_VERSION) {
! 537: if (WWWTRACE)
! 538: HTTrace("HTEventInit. Bad version of WinSoc\n");
! 539: WSACleanup();
! 540: return NO;
! 541: }
! 542: if (APP_TRACE)
! 543: HTTrace("HTEventInit. Using WinSoc version \"%s\".\n",
! 544: wsadata.szDescription);
! 545: }
! 546: #endif /* _WINSOCKAPI_ */
! 547:
2.3 eric 548: HTEvent_setRegisterCallback(HTEventList_register);
549: HTEvent_setUnregisterCallback(HTEventList_unregister);
550: return YES;
551: }
552:
553: PUBLIC BOOL HTEventTerminate (void)
554: {
555: return YES;
556: }
557:
558: #ifdef WWW_WIN_ASYNC
559:
2.4 ! eric 560: /* HTEventList_get/setWinHandle
2.3 eric 561: ** --------------------------
562: ** Managing the windows handle on Windows
563: */
564: PUBLIC BOOL HTEventList_setWinHandle (HWND window, unsigned long message)
565: {
566: HTSocketWin = window;
567: HTwinMsg = message;
568: return YES;
569: }
570:
571: PUBLIC HWND HTEventList_getWinHandle (unsigned long * pMessage)
572: {
573: if (pMessage)
574: *pMessage = HTwinMsg;
575: return (HTSocketWin);
576: }
577:
578: /* only responsible for WM_TIMER and WSA_AsyncSelect */
579: PUBLIC LRESULT CALLBACK AsyncWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
580: {
581: WORD event;
582: SOCKET sock;
2.4 ! eric 583: HTEventType type;
2.3 eric 584:
585: /* timeout stuff */
586: if (uMsg == WM_TIMER) {
2.4 ! eric 587: HTTimer_dispatch((HTTimer *)wParam);
2.3 eric 588: return (0);
589: }
590:
591: if (uMsg != HTwinMsg) /* not our async message */
592: return (DefWindowProc(hwnd, uMsg, wParam, lParam));
593:
594: event = LOWORD(lParam);
595: sock = (SOCKET)wParam;
2.4 ! eric 596: switch (event) {
! 597: case FD_READ: type = HTEvent_READ; break;
! 598: case FD_WRITE: type = HTEvent_WRITE; break;
! 599: case FD_ACCEPT: type = HTEvent_ACCEPT; break;
! 600: case FD_CONNECT: type = HTEvent_CONNECT; break;
! 601: case FD_OOB: type = HTEvent_OOB; break;
! 602: case FD_CLOSE: type = HTEvent_CLOSE; break;
! 603: default: HTDebugBreak();
! 604: }
! 605: if (HTEventList_dispatch((int)sock, type) != HT_OK)
! 606: HTEndLoop = -1;
2.3 eric 607: return (0);
608: }
609:
2.4 ! eric 610: PUBLIC int HTEventList_loop (HTRequest * theRequest )
2.3 eric 611: {
612: MSG msg;
613: while (GetMessage(&msg,0,0,0)) {
614: TranslateMessage(&msg);
615: DispatchMessage(&msg);
616: }
617: return (HTEndLoop == 1 ? HT_OK : HT_ERROR);
618: }
619:
620: #else /* WWW_WIN_ASYNC */
621:
2.1 frystyk 622: /*
623: ** We wait for activity from one of our registered
624: ** channels, and dispatch on that.
625: **
626: ** There are now two versions of the event loop. The first is if you want
627: ** to use async I/O on windows, and the other is if you want to use normal
628: ** Unix setup with sockets
629: */
630: PUBLIC int HTEventList_loop (HTRequest * theRequest)
631: {
632: fd_set treadset, twriteset, texceptset;
633: struct timeval waittime, * wt;
634: int active_sockets;
635: int maxfds;
636: int timeout;
637: SOCKET s;
638: int status = 0;
639: HTEndLoop = 0;
640:
2.2 eric 641: EventOrderList = HTList_new(); /* is kept around until EventOrder_deleteAll */
642:
2.1 frystyk 643: /* Don't leave this loop until we leave the application */
644: do {
645: treadset = FdArray[HTEvent_INDEX(HTEvent_READ)];
646: twriteset = FdArray[HTEvent_INDEX(HTEvent_WRITE)];
647: texceptset = FdArray[HTEvent_INDEX(HTEvent_OOB)];
2.3 eric 648: maxfds = MaxSock;
2.1 frystyk 649:
650: if (THD_TRACE) HTTrace("Event Loop.. calling select: maxfds is %d\n", maxfds);
651:
652: /*
653: ** Timeval struct copy needed for linux, as it set the value to the
654: ** remaining timeout while exiting the select. (and perhaps for
655: ** other OS). Code borrowed from X server.
656: */
657: wt = NULL;
658: if ((timeout = HTTimer_soonest())) {
659: waittime.tv_sec = timeout / MILLI_PER_SECOND;
660: waittime.tv_usec = (timeout % MILLI_PER_SECOND) *
661: (1000000 / MILLI_PER_SECOND);
662: wt = &waittime;
663: }
664:
2.2 eric 665: HTTraceData((char*)&treadset, maxfds/8 + 1, "HTEventList_loop pre treadset: (maxfd:%d)", maxfds);
666: HTTraceData((char*)&twriteset, maxfds/8 + 1, "HTEventList_loop pre twriteset:");
667: HTTraceData((char*)&texceptset, maxfds/8 + 1, "HTEventList_loop pre texceptset:");
668:
2.1 frystyk 669: #ifdef __hpux
670: active_sockets = select(maxfds+1, (int *)&treadset, (int *)&twriteset,
671: (int *)&texceptset, wt);
672: #else
673: active_sockets = select(maxfds+1, &treadset, &twriteset, &texceptset, wt);
674: #endif
2.2 eric 675:
676: HTTraceData((char*)&treadset, maxfds/8 + 1, "HTEventList_loop post treadset: (active_sockets:%d)", active_sockets);
677: HTTraceData((char*)&twriteset, maxfds/8 + 1, "HTEventList_loop post twriteset: (errno:%d)", errno);
678: HTTraceData((char*)&texceptset, maxfds/8 + 1, "HTEventList_loop post texceptset:");
679:
2.1 frystyk 680: if (THD_TRACE) HTTrace("Event Loop.. select returns %d\n", active_sockets);
681:
682: if (active_sockets == -1) {
683: HTRequest_addSystemError( theRequest, ERR_FATAL, socerrno, NO, "select");
2.3 eric 684: EventList_dump();
685: #if 0
2.1 frystyk 686: __DumpFDSet(FdArray+HTEvent_INDEX(HTEvent_READ), "Read");
687: __DumpFDSet(FdArray+HTEvent_INDEX(HTEvent_WRITE), "Write") ;
688: __DumpFDSet(FdArray+HTEvent_INDEX(HTEvent_OOB), "Exceptions");
2.3 eric 689: #endif /* 0 */
2.1 frystyk 690: return HT_ERROR;
691: }
692:
693: /*
694: ** We had a timeout so now we check and see if we have a timeout
695: ** handler to call
696: */
697: if (active_sockets == 0) {
698: HTTimer_dispatchAll();
699: continue;
700: }
701:
702: /*
703: ** There were active sockets. Determine which fd sets they were in
704: */
2.2 eric 705: #ifdef HT_EVENT_ORDER
706: #define DISPATCH(socket, type) EventOrder_add(socket, type)
707: #else /* HT_EVENT_ORDER */
708: #define DISPATCH(socket, type) HTEventList_dispatch(socket, type)
709: #endif /* !HT_EVENT_ORDER */
2.1 frystyk 710: for (s = 0 ; s <= maxfds ; s++) {
711: if (FD_ISSET(s, &texceptset))
2.2 eric 712: if ((status = DISPATCH(s, HTEvent_OOB)) != HT_OK)
2.1 frystyk 713: return status;
714: if (FD_ISSET(s, &twriteset))
2.2 eric 715: if ((status = DISPATCH(s, HTEvent_WRITE)) != HT_OK)
2.1 frystyk 716: return status;
717: if (FD_ISSET(s, &treadset))
2.2 eric 718: if ((status = DISPATCH(s, HTEvent_READ)) != HT_OK)
2.1 frystyk 719: return status;
720: }
2.2 eric 721: #ifdef HT_EVENT_ORDER
722: if ((status = EventOrder_executeAndDelete()) != HT_OK)
723: return status;
724: #endif /* HT_EVENT_ORDER */
2.1 frystyk 725: } while (!HTEndLoop);
726:
727: return HT_OK;
728: }
729:
2.3 eric 730: #endif /* !WWW_WIN_ASYNC */
Webmaster