jabberd2  2.3.4
mio_wsasync.h
Go to the documentation of this file.
1 /*
2  * jabberd - Jabber Open Source Server
3  * Copyright (c) 2007 Adam Strzelecki
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA02111-1307USA
18  */
19 
20 /* MIO backend for select() */
21 
22 #ifdef HAVE_SYS_SELECT_H
23 # include <sys/select.h>
24 #endif
25 
26 #define WM_MIO_EVENT (WM_APP + 100)
27 
28 #define MIO_FUNCS \
29  static ATOM mio_class = NULL; \
30  \
31  LONG CALLBACK _mio_wnd_proc(HWND hwnd, UINT msg, WPARAM wParam, LONG lParam); \
32  \
33  static mio_fd_t _mio_alloc_fd(mio_t m, int fd) \
34  { \
35  mio_priv_fd_t priv_fd = MIO(m)->next_free; \
36  \
37  if(priv_fd == NULL) \
38  return NULL; \
39  \
40  MIO(m)->next_free = priv_fd->next_free; \
41  priv_fd->mio_fd.fd = fd; \
42  priv_fd->next_free = NULL; \
43  \
44  return (mio_fd_t)priv_fd; \
45  } \
46  \
47  static void _mio_free_fd(mio_t m, mio_priv_fd_t priv_fd) \
48  { \
49  priv_fd->next_free = MIO(m)->next_free; \
50  priv_fd->mio_fd.fd = 0; \
51  priv_fd->revent = 0; \
52  priv_fd->event = 0; \
53  MIO(m)->next_free = priv_fd; \
54  } \
55  \
56  static int _mio_select(mio_priv_t m, int t) \
57  { \
58  MSG msg; int lResult = 0; \
59  MIO(m)->select_fd = NULL; \
60  MIO(m)->timer = SetTimer(MIO(m)->hwnd, \
61  MIO(m)->timer ? MIO(m)->timer : 0, 1000 * t, NULL); \
62  while(!lResult && GetMessage(&msg, NULL, 0, 0)) \
63  { \
64  TranslateMessage(&msg); \
65  lResult = DispatchMessage(&msg); \
66  } \
67  return MIO(m)->select_fd ? 1 : 0; \
68  } \
69  \
70  static mio_priv_fd_t _mio_peek(mio_priv_t m) \
71  { \
72  MSG msg; \
73  MIO(m)->select_fd = NULL; \
74  if(PeekMessage(&msg, MIO(m)->hwnd, WM_MIO_EVENT, WM_MIO_EVENT + MIO(m)->maxfd, PM_REMOVE)) \
75  { \
76  TranslateMessage(&msg); \
77  DispatchMessage(&msg); \
78  } \
79  return MIO(m)->select_fd; \
80  }
81 
82 #define MIO_FD_VARS \
83  struct mio_priv_fd_st *next_free; \
84  long event; \
85  long revent; \
86  int idx;
87 
88 #define MIO_VARS \
89  HWND hwnd; \
90  UINT_PTR timer; \
91  int defer_free; \
92  int count; \
93  mio_priv_fd_t select_fd; \
94  mio_priv_fd_t fds; \
95  mio_priv_fd_t next_free;
96 
97 #define MIO_INIT_VARS(m) \
98  do { \
99  int i; \
100  HINSTANCE hInstance = GetModuleHandle(NULL); \
101  MIO(m)->defer_free = 0; \
102  if(mio_class == NULL) { \
103  WNDCLASS wndclass; \
104  memset(&wndclass, 0, sizeof(WNDCLASS)); \
105  wndclass.style = CS_NOCLOSE; \
106  wndclass.lpfnWndProc = _mio_wnd_proc; \
107  wndclass.lpszClassName = "jabberd2mio"; \
108  wndclass.hInstance = hInstance; \
109  \
110  if((mio_class = RegisterClass(&wndclass)) == NULL) { \
111  mio_debug(ZONE, "cannot create listener class (%d, %x)", GetLastError(), hInstance); \
112  free(m); \
113  return NULL; \
114  } \
115  mio_debug(ZONE, "created listener class"); \
116  } \
117  MIO(m)->hwnd = CreateWindow("jabberd2mio", "jabberd2mio", \
118  0, CW_USEDEFAULT, CW_USEDEFAULT, 400, 300, \
119  NULL, NULL, hInstance, m); \
120  if(MIO(m)->hwnd == NULL) { \
121  mio_debug(ZONE, "cannot create listener window (%d, %x)", GetLastError(), hInstance); \
122  free(m); \
123  return NULL; \
124  } \
125  mio_debug(ZONE, "created listener window (%x)", MIO(m)->hwnd); \
126  if((MIO(m)->fds = malloc(sizeof(struct mio_priv_fd_st) * maxfd)) == NULL) { \
127  mio_debug(ZONE, "cannot allocate descriptors table"); \
128  free(m); \
129  return NULL; \
130  } \
131  memset(MIO(m)->fds, 0, sizeof(struct mio_priv_fd_st) * maxfd); \
132  MIO(m)->count = maxfd; \
133  for(i = 0; i < maxfd; i++) \
134  MIO(m)->fds[i].idx = i; \
135  for(i = 0; i < maxfd - 1; i++) \
136  MIO(m)->fds[i].next_free = &(MIO(m)->fds[i + 1]); \
137  MIO(m)->fds[maxfd - 1].next_free = NULL; \
138  MIO(m)->next_free = &(MIO(m)->fds[0]); \
139  MIO(m)->select_fd = NULL; \
140  } while(0)
141 
142 #define MIO_FREE_VARS(m) \
143  do { \
144  DestroyWindow(MIO(m)->hwnd); \
145  free(MIO(m)->fds); \
146  } while(0)
147 
148 #define MIO_ALLOC_FD(m, rfd) _mio_alloc_fd(MIO(m), rfd)
149 #define MIO_FREE_FD(m, mfd) _mio_free_fd(m, mfd)
150 
151 #define MIO_DEQUEUE(m, mfd) \
152  if(mfd->event) { \
153  MSG msg; \
154  WSAAsyncSelect(mfd->mio_fd.fd, MIO(m)->hwnd, WM_MIO_EVENT + mfd->idx, 0); \
155  while(PeekMessage(&msg, MIO(m)->hwnd, WM_MIO_EVENT + mfd->idx, WM_MIO_EVENT + mfd->idx, PM_REMOVE)); \
156  } \
157 
158 #define MIO_REMOVE_FD(m, mfd) MIO_DEQUEUE(m, mfd)
159 
160 #define MIO_CHECK(m, t) _mio_select(m, t)
161 
162 #define MIO_SET_READ(m, mfd) \
163  if(!(mfd->event & FD_READ)) { \
164  MIO_DEQUEUE(m, mfd); \
165  WSAAsyncSelect(mfd->mio_fd.fd, MIO(m)->hwnd, WM_MIO_EVENT + mfd->idx, (mfd->event |= FD_READ|FD_ACCEPT|FD_CONNECT|FD_CLOSE)); \
166  }
167 #define MIO_SET_WRITE(m, mfd) \
168  if(!(mfd->event & FD_WRITE)) { \
169  MIO_DEQUEUE(m, mfd); \
170  WSAAsyncSelect(mfd->mio_fd.fd, MIO(m)->hwnd, WM_MIO_EVENT + mfd->idx, (mfd->event |= FD_WRITE|FD_CONNECT|FD_CLOSE)); \
171  }
172 
173 #define MIO_UNSET_READ(m, mfd) \
174  if(mfd->event & FD_READ) { \
175  mfd->event &= ~(FD_READ|FD_ACCEPT|FD_CONNECT|FD_CLOSE); \
176  if(mfd->event & FD_WRITE) \
177  mfd->event = FD_WRITE|FD_CONNECT|FD_CLOSE; \
178  MIO_DEQUEUE(m, mfd); \
179  WSAAsyncSelect(mfd->mio_fd.fd, MIO(m)->hwnd, WM_MIO_EVENT + mfd->idx, mfd->event); \
180  }
181 #define MIO_UNSET_WRITE(m, mfd) \
182  if(mfd->event & FD_WRITE) { \
183  mfd->event &= ~FD_WRITE; \
184  if(!(mfd->event & FD_READ)) \
185  mfd->event = 0; \
186  MIO_DEQUEUE(m, mfd); \
187  WSAAsyncSelect(mfd->mio_fd.fd, MIO(m)->hwnd, WM_MIO_EVENT + mfd->idx, mfd->event); \
188  }
189 
190 #define MIO_CAN_READ(m, iter) (iter->revent & (FD_READ|FD_ACCEPT|FD_CONNECT|FD_CLOSE))
191 #define MIO_CAN_WRITE(m, iter) ((iter->revent & FD_WRITE) || !(iter->revent & FD_READ) && (iter->revent & (FD_CONNECT|FD_CLOSE)))
192 #define MIO_CAN_FREE(m) (!MIO(m)->defer_free)
193 
194 #define MIO_INIT_ITERATOR(iter) \
195  mio_priv_fd_t iter = NULL
196 
197 #define MIO_ITERATE_RESULTS(m, retval, iter) \
198  for(MIO(m)->defer_free = 1, iter = MIO(m)->select_fd; iter || ((MIO(m)->defer_free = 0)); iter = _mio_peek(m))
199 
200 #define MIO_ITERATOR_FD(m, iter) \
201  (&iter->mio_fd)