📄 htevtlst.c
字号:
} #ifdef WWW_WIN_ASYNC if (WSAAsyncSelect(s, HTSocketWin, HTwinMsg, remaining) < 0) ret = HT_ERROR;#else /* WWW_WIN_ASYNC */ FD_CLR(s, FdArray+HTEvent_INDEX(type)); HTTRACEDATA((char*)FdArray+HTEvent_INDEX(type), 8, "HTEventList_unregister: (s:%d)" _ s);#endif /* !WWW_WIN_ASYNC */ /* ** Check to see if we can delete the action completely. We do this ** if there are no more events registered. */ if (remaining == 0) { HTList * doomed = cur; HTTRACE(THD_TRACE, "Event....... No more events registered for socket %d\n" _ s);#ifndef WWW_WIN_ASYNC /* Check to see if we have to update MaxSock */ if (pres->s >= MaxSock) __ResetMaxSock();#endif /* !WWW_WIN_ASYNC */ HT_FREE(pres); pres = (SockEvents *) HTList_nextObject(cur); HTList_quickRemoveElement(doomed, last); } ret = HT_OK; HTTRACE(THD_TRACE, "Event....... Socket %d unregistered for %s\n" _ s _ HTEvent_type2str(type)); /* We found the socket and can break */ break; } last = cur; } if (THD_TRACE) { if (ret == HT_ERROR) HTTRACE(THD_TRACE, "Event....... Couldn't find socket %d. Can't unregister type %s\n" _ s _ HTEvent_type2str(type)); } return ret;}/*** Unregister all sockets ** N.B. we just remove them for our internal data structures: it is up to the ** application to actually close the socket. */PUBLIC int HTEventList_unregisterAll (void) { int i; HTTRACE(THD_TRACE, "Unregister.. all sockets\n"); for (i = 0 ; i < HT_M_HASH_SIZE; i++) { HTList * cur = HashTable[i]; SockEvents * pres; while ((pres = (SockEvents *) HTList_nextObject(cur))) {#ifdef WWW_WIN_ASYNC WSAAsyncSelect(pres->s, HTSocketWin, HTwinMsg, 0);#endif /* WWW_WIN_ASYNC */ HT_FREE(pres); } HTList_delete(HashTable[i]); HashTable[i] = NULL; }#ifndef WWW_WIN_ASYNC MaxSock = 0 ; HTTRACE(THD_TRACE, "Event....... New value for MaxSock is %d\n" _ MaxSock); FD_ZERO(FdArray+HTEvent_INDEX(HTEvent_READ)); FD_ZERO(FdArray+HTEvent_INDEX(HTEvent_WRITE)); FD_ZERO(FdArray+HTEvent_INDEX(HTEvent_OOB));#endif /* !WWW_WIN_ASYNC */ EventOrder_deleteAll(); return 0;}/*** Dispatch the event to the appropriate event handler.** If no event handler is found then just return.*/PUBLIC int HTEventList_dispatch (SOCKET s, HTEventType type, ms_t now){ SockEvents * sockp = SockEvents_get(s, SockEvents_find); if (sockp) { HTEvent * event = sockp->events[HTEvent_INDEX(type)]; /* Fixup the timeout */ if (sockp->timeouts[HTEvent_INDEX(type)]) HTTimer_refresh(sockp->timeouts[HTEvent_INDEX(type)], now); /* ** If we have found an event object for this event then see ** is we should call it. */ if (event && event->priority!=HT_PRIORITY_OFF) return (*event->cbf) (s, event->param, type); HTTRACE(THD_TRACE, "Dispatch.... Handler %p NOT called\n" _ sockp); return HT_OK; } HTTRACE(THD_TRACE, "Dispatch.... Bad socket %d\n" _ s); return NO;}PUBLIC HTEvent * HTEventList_lookup (SOCKET s, HTEventType type){ SockEvents * sockp = NULL; if ((sockp = SockEvents_get(s, SockEvents_find)) == NULL) return NULL; return sockp->events[HTEvent_INDEX(type)];}/* ------------------------------------------------------------------------- *//* THE EVENT LOOP *//* ------------------------------------------------------------------------- *//*** Start eventloop*/PUBLIC int HTEventList_newLoop (void){ return HTEventList_loop (NULL);}/*** Stops the event loop. The function does not guarantee** that all requests have terminated. This is for the app to do*/PUBLIC void HTEventList_stopLoop (void){ HTEndLoop = 1;}/*** There are now two versions of the event loop. The first is if you want** to use async I/O on windows, and the other is if you want to use normal** Unix setup with sockets*/PUBLIC int HTEventList_loop (HTRequest * theRequest){#ifdef WWW_WIN_ASYNC MSG msg; int status; while (!HTEndLoop && GetMessage(&msg,0,0,0)) { TranslateMessage(&msg); DispatchMessage(&msg); } status = HTEndLoop; /* Reset HTEndLoop in case we want to start again */ HTEndLoop = 0; return (status == 1 ? HT_OK : HT_ERROR);#else /* WWW_WIN_ASYNC */ fd_set treadset, twriteset, texceptset; struct timeval waittime, * wt; int active_sockets; int maxfds; ms_t timeout; ms_t now; SOCKET s; int status = HT_OK; /* Check that we don't have multiple loops started at once */ if (HTInLoop) { HTTRACE(THD_TRACE, "Event Loop.. Already one loop running - exiting\n"); return HT_ERROR; } HTInLoop = YES; /* Set up list of events - is kept around until EventOrder_deleteAll */ if (!EventOrderList) EventOrderList = HTList_new(); else EventOrder_clearAll(); /* Don't leave this loop until we leave the application */ while (!HTEndLoop) { /* ** Timeval struct copy needed for linux, as it set the value to the ** remaining timeout while exiting the select. (and perhaps for ** other OS). Code borrowed from X server. */ wt = NULL; if ((status = HTTimer_next(&timeout))) break; if (timeout != 0) { waittime.tv_sec = timeout / MILLI_PER_SECOND; waittime.tv_usec = (timeout % MILLI_PER_SECOND) * (1000000 / MILLI_PER_SECOND); wt = &waittime; } /* ** Check whether we still have to continue the event loop. It could ** be that one of the timer handlers ended the loop. */ if (HTEndLoop) break; /* ** Now we copy the current active file descriptors to pass them to select. */ treadset = FdArray[HTEvent_INDEX(HTEvent_READ)]; twriteset = FdArray[HTEvent_INDEX(HTEvent_WRITE)]; texceptset = FdArray[HTEvent_INDEX(HTEvent_OOB)]; /* And also get the max socket value */ maxfds = MaxSock; HTTRACE(THD_TRACE, "Event Loop.. calling select: maxfds is %d\n" _ maxfds);#ifdef HTDEBUG fd_dump(maxfds, &treadset, &twriteset, &texceptset, wt);#endif#ifdef __hpux active_sockets = select(maxfds+1, (int *)&treadset, (int *)&twriteset, (int *)&texceptset, wt);#elif defined(_WINSOCKAPI_) /* * yovavm@contact.com * * On some WINSOCK versions select() with 3 empty sets and NULL timeout * returns 0 and in some it returns -1. * If 0 is returned in such situation, we will go into an infinite loop * (cause the sets will stay empty forever ...), * so make sure to set the active_sockets = -1 which will take us out * of the loop. */ if ((treadset.fd_count || twriteset.fd_count || texceptset.fd_count) && wt) active_sockets = select(maxfds+1, &treadset, &twriteset, &texceptset, wt); else active_sockets = -1; #else active_sockets = select(maxfds+1, &treadset, &twriteset, &texceptset, wt);#endif now = HTGetTimeInMillis(); HTTRACE(THD_TRACE, "Event Loop.. select returns %d\n" _ active_sockets);#ifdef HTDEBUG fd_dump(maxfds, &treadset, &twriteset, &texceptset, wt);#endif if (active_sockets == -1) {#ifdef EINTR if (socerrno == EINTR) { /* ** EINTR The select() function was interrupted before any ** of the selected events occurred and before the ** timeout interval expired. ** ** If SA_RESTART has been set for the interrupting ** signal, it is implementation-dependent whether ** select() restarts or returns with EINTR. */ HTTRACE(THD_TRACE, "Event Loop.. select was interruted - try again\n"); continue; }#endif /* EINTR */#ifdef EBADF if (socerrno == EBADF) { /* ** EBADF One or more of the file descriptor sets specified ** a file descriptor that is not a valid open file ** descriptor. */ HTTRACE(THD_TRACE, "Event Loop.. One or more sockets were not through their connect phase - try again\n"); continue; }#endif HTTRACE(THD_TRACE, "Event Loop.. select returned error %d\n" _ socerrno);#ifdef HTDEBUG EventList_dump();#endif /* HTDEBUG */ status = HT_ERROR; break; } /* ** We had a timeout so now we check and see if we have a timeout ** handler to call. Let HTTimer_next get it. */ if (active_sockets == 0) continue; /* There were active sockets. Determine which fd sets they were in */ for (s = 0 ; s <= maxfds ; s++) { if (FD_ISSET(s, &texceptset)) if ((status = EventOrder_add(s, HTEvent_OOB, now)) != HT_OK) goto stop_loop; if (FD_ISSET(s, &twriteset)) if ((status = EventOrder_add(s, HTEvent_WRITE, now)) != HT_OK) goto stop_loop; if (FD_ISSET(s, &treadset)) if ((status = EventOrder_add(s, HTEvent_READ, now)) != HT_OK) goto stop_loop; } if ((status = EventOrder_executeAndDelete()) != HT_OK) break; }; /* Reset HTEndLoop in case we want to start again */ stop_loop: HTEndLoop = 0; HTInLoop = NO; return status;#endif /* !WWW_WIN_ASYNC */}/* ------------------------------------------------------------------------- *//* EVENT INITIALIZATION AND TERMINATION *//* ------------------------------------------------------------------------- */#ifdef WWW_WIN_ASYNC/* Only responsible for WM_TIMER and WSA_AsyncSelect */ PRIVATE LRESULT CALLBACK AsyncWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam){ WORD event; SOCKET sock; HTEventType type; ms_t now = HTGetTimeInMillis(); /* timeout stuff */ if (uMsg == WM_TIMER) { HTTimer_dispatch((HTTimer *)wParam); return (0); } if (uMsg != HTwinMsg) /* not our async message */ return (DefWindowProc(hwnd, uMsg, wParam, lParam)); event = LOWORD(lParam); sock = (SOCKET)wParam; switch (event) { case FD_READ: type = HTEvent_READ; break; case FD_WRITE: type = HTEvent_WRITE; break; case FD_ACCEPT: type = HTEvent_ACCEPT; break; case FD_CONNECT: type = HTEvent_CONNECT; break; case FD_OOB: type = HTEvent_OOB; break; /* JK: was returning HTEvent_CLOSE before, and this was a source of errors, as libwww detects the socket shutdown with a call to recv */ case FD_CLOSE: type = HTEvent_READ; break; default: HTDEBUGBREAK("Unknown event %d\n" _ event); } if (HTEventList_dispatch((int)sock, type, now) != HT_OK) HTEndLoop = -1; return (0);}/* HTEventList_get/setWinHandle** --------------------------** Managing the windows handle on Windows*/PUBLIC BOOL HTEventList_setWinHandle (HWND window, unsigned long message){ HTSocketWin = window; HTwinMsg = message; return YES;}PUBLIC HWND HTEventList_getWinHandle (unsigned long * pMessage){ if (pMessage) *pMessage = HTwinMsg; return (HTSocketWin);}#endif /* WWW_WIN_ASYNC */PUBLIC BOOL HTEventInit (void){#ifdef WWW_WIN_ASYNC /* ** We are here starting a hidden window to take care of events from ** the async select() call in the async version of the event loop in ** the Internal event manager (HTEvtLst.c) */ static char className[] = "AsyncWindowClass"; WNDCLASS wc; OSVERSIONINFO osInfo; wc.style=0; wc.lpfnWndProc=(WNDPROC)AsyncWindowProc; wc.cbClsExtra=0; wc.cbWndExtra=0; wc.hIcon=0; wc.hCursor=0; wc.hbrBackground=0; wc.lpszMenuName=(LPSTR)0; wc.lpszClassName=className; osInfo.dwOSVersionInfoSize = sizeof(osInfo); GetVersionEx(&osInfo); /* According to Gary Johnson, GetModuleHandle() works for NT as well */#if 0 if (osInfo.dwPlatformId == VER_PLATFORM_WIN32s || osInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) wc.hInstance=GetModuleHandle(NULL); /* 95 and non threaded platforms */ else wc.hInstance=GetCurrentProcess(); /* NT and hopefully everything following */#else wc.hInstance=GetModuleHandle(NULL); /* Should work on all win32 stuff */#endif HTinstance = wc.hInstance; HTclass = RegisterClass(&wc); if (!HTclass) { HTTRACE(THD_TRACE, "HTLibInit.. Can't RegisterClass \"%s\"\n" _ className); return NO; } if (!(HTSocketWin = CreateWindow(className, "WWW_WIN_ASYNC", WS_POPUP, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, wc.hInstance,0))) {#ifdef HTDEBUG char space[50]; HTTRACE(THD_TRACE, "HTLibInit.. Can't Create Window \"WWW_WIN_ASYNC\" - error:"); sprintf(space, "%ld\n", GetLastError()); HTTRACE(THD_TRACE, space);#endif /* HTDEBUG */ return NO; } HTwinMsg = WM_USER; /* use first available message since app uses none */ /* Register platform specific timer handlers for windows */ HTTimer_registerSetTimerCallback(Timer_setWindowsTimer); HTTimer_registerDeleteTimerCallback(Timer_deleteWindowsTimer);#endif /* WWW_WIN_ASYNC */#ifdef _WINSOCKAPI_ /* ** Initialise WinSock DLL. This must also be shut down! PMH */ { WSADATA wsadata; if (WSAStartup(DESIRED_WINSOCK_VERSION, &wsadata)) { HTTRACE(THD_TRACE, "HTEventInit. Can't initialize WinSoc\n"); WSACleanup(); return NO; } if (wsadata.wVersion < MINIMUM_WINSOCK_VERSION) { HTTRACE(THD_TRACE, "HTEventInit. Bad version of WinSoc\n"); WSACleanup(); return NO; } HTTRACE(APP_TRACE, "HTEventInit. Using WinSoc version \"%s\".\n" _ wsadata.szDescription); }#endif /* _WINSOCKAPI_ */ HTEvent_setRegisterCallback(HTEventList_register); HTEvent_setUnregisterCallback(HTEventList_unregister); return YES;}PUBLIC BOOL HTEventTerminate (void){#ifdef _WINSOCKAPI_ WSACleanup();#endif /* _WINSOCKAPI_ */#ifdef WWW_WIN_ASYNC DestroyWindow(HTSocketWin); UnregisterClass((LPCTSTR)HTclass, HTinstance);#endif /* WWW_WIN_ASYNC */ return YES;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -