jabberd2
2.2.16
|
00001 /* 00002 * jabberd - Jabber Open Source Server 00003 * Copyright (c) 2007 Adam Strzelecki 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License as published by 00007 * the Free Software Foundation; either version 2 of the License, or 00008 * (at your option) any later version. 00009 * 00010 * This program is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the 00013 * GNU General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU General Public License 00016 * along with this program; if not, write to the Free Software 00017 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA02111-1307USA 00018 */ 00019 00020 /* MIO backend for select() */ 00021 00022 #ifdef HAVE_SYS_SELECT_H 00023 # include <sys/select.h> 00024 #endif 00025 00026 #define WM_MIO_EVENT (WM_APP + 100) 00027 00028 #define MIO_FUNCS \ 00029 static ATOM mio_class = NULL; \ 00030 \ 00031 LONG CALLBACK _mio_wnd_proc(HWND hwnd, UINT msg, WPARAM wParam, LONG lParam); \ 00032 \ 00033 static mio_fd_t _mio_alloc_fd(mio_t m, int fd) \ 00034 { \ 00035 mio_priv_fd_t priv_fd = MIO(m)->next_free; \ 00036 \ 00037 if(priv_fd == NULL) \ 00038 return NULL; \ 00039 \ 00040 MIO(m)->next_free = priv_fd->next_free; \ 00041 priv_fd->mio_fd.fd = fd; \ 00042 priv_fd->next_free = NULL; \ 00043 \ 00044 return (mio_fd_t)priv_fd; \ 00045 } \ 00046 \ 00047 static void _mio_free_fd(mio_t m, mio_priv_fd_t priv_fd) \ 00048 { \ 00049 priv_fd->next_free = MIO(m)->next_free; \ 00050 priv_fd->mio_fd.fd = 0; \ 00051 priv_fd->revent = 0; \ 00052 priv_fd->event = 0; \ 00053 MIO(m)->next_free = priv_fd; \ 00054 } \ 00055 \ 00056 static int _mio_select(mio_priv_t m, int t) \ 00057 { \ 00058 MSG msg; int lResult = 0; \ 00059 MIO(m)->select_fd = NULL; \ 00060 MIO(m)->timer = SetTimer(MIO(m)->hwnd, \ 00061 MIO(m)->timer ? MIO(m)->timer : 0, 1000 * t, NULL); \ 00062 while(!lResult && GetMessage(&msg, NULL, 0, 0)) \ 00063 { \ 00064 TranslateMessage(&msg); \ 00065 lResult = DispatchMessage(&msg); \ 00066 } \ 00067 return MIO(m)->select_fd ? 1 : 0; \ 00068 } \ 00069 \ 00070 static mio_priv_fd_t _mio_peek(mio_priv_t m) \ 00071 { \ 00072 MSG msg; \ 00073 MIO(m)->select_fd = NULL; \ 00074 if(PeekMessage(&msg, MIO(m)->hwnd, WM_MIO_EVENT, WM_MIO_EVENT + MIO(m)->maxfd, PM_REMOVE)) \ 00075 { \ 00076 TranslateMessage(&msg); \ 00077 DispatchMessage(&msg); \ 00078 } \ 00079 return MIO(m)->select_fd; \ 00080 } 00081 00082 #define MIO_FD_VARS \ 00083 struct mio_priv_fd_st *next_free; \ 00084 long event; \ 00085 long revent; \ 00086 int idx; 00087 00088 #define MIO_VARS \ 00089 HWND hwnd; \ 00090 UINT_PTR timer; \ 00091 int defer_free; \ 00092 int count; \ 00093 mio_priv_fd_t select_fd; \ 00094 mio_priv_fd_t fds; \ 00095 mio_priv_fd_t next_free; 00096 00097 #define MIO_INIT_VARS(m) \ 00098 do { \ 00099 int i; \ 00100 HINSTANCE hInstance = GetModuleHandle(NULL); \ 00101 MIO(m)->defer_free = 0; \ 00102 if(mio_class == NULL) { \ 00103 WNDCLASS wndclass; \ 00104 memset(&wndclass, 0, sizeof(WNDCLASS)); \ 00105 wndclass.style = CS_NOCLOSE; \ 00106 wndclass.lpfnWndProc = _mio_wnd_proc; \ 00107 wndclass.lpszClassName = "jabberd2mio"; \ 00108 wndclass.hInstance = hInstance; \ 00109 \ 00110 if((mio_class = RegisterClass(&wndclass)) == NULL) { \ 00111 mio_debug(ZONE, "cannot create listener class (%d, %x)", GetLastError(), hInstance); \ 00112 free(m); \ 00113 return NULL; \ 00114 } \ 00115 mio_debug(ZONE, "created listener class"); \ 00116 } \ 00117 MIO(m)->hwnd = CreateWindow("jabberd2mio", "jabberd2mio", \ 00118 0, CW_USEDEFAULT, CW_USEDEFAULT, 400, 300, \ 00119 NULL, NULL, hInstance, m); \ 00120 if(MIO(m)->hwnd == NULL) { \ 00121 mio_debug(ZONE, "cannot create listener window (%d, %x)", GetLastError(), hInstance); \ 00122 free(m); \ 00123 return NULL; \ 00124 } \ 00125 mio_debug(ZONE, "created listener window (%x)", MIO(m)->hwnd); \ 00126 if((MIO(m)->fds = malloc(sizeof(struct mio_priv_fd_st) * maxfd)) == NULL) { \ 00127 mio_debug(ZONE, "cannot allocate descriptors table"); \ 00128 free(m); \ 00129 return NULL; \ 00130 } \ 00131 memset(MIO(m)->fds, 0, sizeof(struct mio_priv_fd_st) * maxfd); \ 00132 MIO(m)->count = maxfd; \ 00133 for(i = 0; i < maxfd; i++) \ 00134 MIO(m)->fds[i].idx = i; \ 00135 for(i = 0; i < maxfd - 1; i++) \ 00136 MIO(m)->fds[i].next_free = &(MIO(m)->fds[i + 1]); \ 00137 MIO(m)->fds[maxfd - 1].next_free = NULL; \ 00138 MIO(m)->next_free = &(MIO(m)->fds[0]); \ 00139 MIO(m)->select_fd = NULL; \ 00140 } while(0) 00141 00142 #define MIO_FREE_VARS(m) \ 00143 do { \ 00144 DestroyWindow(MIO(m)->hwnd); \ 00145 free(MIO(m)->fds); \ 00146 } while(0) 00147 00148 #define MIO_ALLOC_FD(m, rfd) _mio_alloc_fd(MIO(m), rfd) 00149 #define MIO_FREE_FD(m, mfd) _mio_free_fd(m, mfd) 00150 00151 #define MIO_DEQUEUE(m, mfd) \ 00152 if(mfd->event) { \ 00153 MSG msg; \ 00154 WSAAsyncSelect(mfd->mio_fd.fd, MIO(m)->hwnd, WM_MIO_EVENT + mfd->idx, 0); \ 00155 while(PeekMessage(&msg, MIO(m)->hwnd, WM_MIO_EVENT + mfd->idx, WM_MIO_EVENT + mfd->idx, PM_REMOVE)); \ 00156 } \ 00157 00158 #define MIO_REMOVE_FD(m, mfd) MIO_DEQUEUE(m, mfd) 00159 00160 #define MIO_CHECK(m, t) _mio_select(m, t) 00161 00162 #define MIO_SET_READ(m, mfd) \ 00163 if(!(mfd->event & FD_READ)) { \ 00164 MIO_DEQUEUE(m, mfd); \ 00165 WSAAsyncSelect(mfd->mio_fd.fd, MIO(m)->hwnd, WM_MIO_EVENT + mfd->idx, (mfd->event |= FD_READ|FD_ACCEPT|FD_CONNECT|FD_CLOSE)); \ 00166 } 00167 #define MIO_SET_WRITE(m, mfd) \ 00168 if(!(mfd->event & FD_WRITE)) { \ 00169 MIO_DEQUEUE(m, mfd); \ 00170 WSAAsyncSelect(mfd->mio_fd.fd, MIO(m)->hwnd, WM_MIO_EVENT + mfd->idx, (mfd->event |= FD_WRITE|FD_CONNECT|FD_CLOSE)); \ 00171 } 00172 00173 #define MIO_UNSET_READ(m, mfd) \ 00174 if(mfd->event & FD_READ) { \ 00175 mfd->event &= ~(FD_READ|FD_ACCEPT|FD_CONNECT|FD_CLOSE); \ 00176 if(mfd->event & FD_WRITE) \ 00177 mfd->event = FD_WRITE|FD_CONNECT|FD_CLOSE; \ 00178 MIO_DEQUEUE(m, mfd); \ 00179 WSAAsyncSelect(mfd->mio_fd.fd, MIO(m)->hwnd, WM_MIO_EVENT + mfd->idx, mfd->event); \ 00180 } 00181 #define MIO_UNSET_WRITE(m, mfd) \ 00182 if(mfd->event & FD_WRITE) { \ 00183 mfd->event &= ~FD_WRITE; \ 00184 if(!(mfd->event & FD_READ)) \ 00185 mfd->event = 0; \ 00186 MIO_DEQUEUE(m, mfd); \ 00187 WSAAsyncSelect(mfd->mio_fd.fd, MIO(m)->hwnd, WM_MIO_EVENT + mfd->idx, mfd->event); \ 00188 } 00189 00190 #define MIO_CAN_READ(m, iter) (iter->revent & (FD_READ|FD_ACCEPT|FD_CONNECT|FD_CLOSE)) 00191 #define MIO_CAN_WRITE(m, iter) ((iter->revent & FD_WRITE) || !(iter->revent & FD_READ) && (iter->revent & (FD_CONNECT|FD_CLOSE))) 00192 #define MIO_CAN_FREE(m) (!MIO(m)->defer_free) 00193 00194 #define MIO_INIT_ITERATOR(iter) \ 00195 mio_priv_fd_t iter = NULL 00196 00197 #define MIO_ITERATE_RESULTS(m, retval, iter) \ 00198 for(MIO(m)->defer_free = 1, iter = MIO(m)->select_fd; iter || ((MIO(m)->defer_free = 0)); iter = _mio_peek(m)) 00199 00200 #define MIO_ITERATOR_FD(m, iter) \ 00201 (&iter->mio_fd)