ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/libio/comm/win32.c
Revision: 153
Committed: Mon Oct 17 21:20:34 2005 UTC (20 years, 9 months ago) by adx
Content type: text/x-csrc
File size: 8427 byte(s)
Log Message:
- compile libio as a dll on win32
- next step is compiling the whole ircd as a dll to export its symbols
- after that, we'll be able to support loadable *.dll modules.

NOTE: m_operspy.c doesn't compile now (error at localClient->iline)

File Contents

# Content
1 /*
2 * ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
3 * win32.c: Winsock WSAAsyncSelect() compatible network routines.
4 *
5 * Copyright (C) 2002 by the past and present ircd coders, and others.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20 * USA
21 *
22 * $Id$
23 */
24
25 #include "stdinc.h"
26 #include <iphlpapi.h>
27 #include "restart.h"
28
29 #define WM_SIGNAL (WM_USER + 0)
30 #define WM_SOCKET (WM_USER + 1)
31 #define WM_DNS (WM_USER + 2)
32
33 void (* dispatch_wm_signal) (int) = NULL;
34 struct irc_ssaddr irc_nsaddr_list[IRCD_MAXNS];
35 int irc_nscount = 0;
36
37 static HWND wndhandle;
38 static dlink_list dns_queries = {NULL, NULL, 0};
39 static dlink_node *setupfd_hook;
40
41 /*
42 * Handler for Win32 messages.
43 */
44 static LRESULT CALLBACK
45 hybrid_wndproc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
46 {
47 switch (uMsg)
48 {
49 case WM_SOCKET:
50 {
51 fde_t *F = lookup_fd((int) wParam);
52 PF *hdl;
53
54 if (F != NULL && F->flags.open)
55 switch (WSAGETSELECTEVENT(lParam))
56 {
57 case FD_ACCEPT:
58 case FD_CLOSE:
59 case FD_READ:
60 if ((hdl = F->read_handler) != NULL)
61 {
62 F->read_handler = NULL;
63 hdl(F, F->read_data);
64 if (F->flags.open)
65 comm_setselect(F, 0, NULL, NULL, 0);
66 }
67 break;
68
69 case FD_CONNECT:
70 case FD_WRITE:
71 if ((hdl = F->write_handler) != NULL)
72 {
73 F->write_handler = NULL;
74 hdl(F, F->write_data);
75 if (F->flags.open)
76 comm_setselect(F, 0, NULL, NULL, 0);
77 }
78 }
79
80 return 0;
81 }
82
83 case WM_DNS:
84 {
85 dlink_node *ptr;
86
87 DLINK_FOREACH(ptr, dns_queries.head)
88 if (((struct DNSQuery *) ptr->data)->handle == wParam)
89 {
90 struct DNSQuery *query = ptr->data;
91 struct DNSReply *reply = NULL;
92
93 dlinkDelete(&query->node, &dns_queries);
94
95 if (WSAGETASYNCERROR(lParam) == 0)
96 {
97 struct hostent *h = (struct hostent *) &query->reply;
98 static struct DNSReply _reply;
99 reply = &_reply;
100
101 reply->h_name = h->h_name;
102 reply->addr.ss.ss_family = h->h_addrtype;
103
104 switch (h->h_addrtype)
105 {
106 case AF_INET:
107 memcpy(&((struct sockaddr_in *) &reply->addr)->sin_addr,
108 h->h_addr_list[0], h->h_length);
109 break;
110
111 #ifdef IPV6
112 case AF_INET6:
113 memcpy(&((struct sockaddr_in6 *) &reply->addr)->sin6_addr,
114 h->h_addr_list[0], h->h_length);
115 break;
116 #endif
117
118 default: /* shouldn't happen */
119 reply = NULL;
120 }
121 }
122
123 query->callback(query->ptr, reply);
124 return 0;
125 }
126
127 return 0;
128 }
129
130 case WM_SIGNAL:
131 if (dispatch_wm_signal != NULL)
132 dispatch_wm_signal(wParam);
133 return 0;
134
135 case WM_DESTROY:
136 PostQuitMessage(0);
137 return 0;
138
139 default:
140 return DefWindowProc(hwnd, uMsg, wParam, lParam);
141 }
142 }
143
144 /*
145 * Associates a window message with the given socket.
146 * This will automagically switch it to nonblocking.
147 */
148 static void *
149 setup_winsock_fd(va_list args)
150 {
151 int fd = va_arg(args, int);
152
153 WSAAsyncSelect(fd, wndhandle, WM_SOCKET, 0);
154
155 return pass_callback(setupfd_hook, fd);
156 }
157
158 /*
159 * Initialize Winsock, create a window handle.
160 */
161 void
162 init_netio(void)
163 {
164 WNDCLASS wndclass;
165 WSADATA wsa;
166 HMODULE lib;
167 DWORD (WINAPI * _GetNetworkParams) (PFIXED_INFO, PULONG) = NULL;
168
169 /* Initialize Winsock networking */
170 if (WSAStartup(0x101, &wsa) != 0)
171 {
172 MessageBox(NULL, "Cannot initialize Winsock -- terminating ircd",
173 NULL, MB_OK | MB_ICONERROR);
174 exit(1);
175 }
176
177 /* First, we need a class for our window that has message handler
178 * set to hybrid_wndproc() */
179 memset(&wndclass, 0, sizeof(wndclass));
180
181 wndclass.lpfnWndProc = hybrid_wndproc;
182 wndclass.hInstance = GetModuleHandle(NULL);
183 wndclass.lpszClassName = PACKAGE_NAME;
184
185 RegisterClass(&wndclass);
186
187 /* Now, initialize the window */
188 wndhandle = CreateWindow(PACKAGE_NAME, NULL, 0,
189 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
190 NULL, NULL, wndclass.hInstance, NULL);
191
192 if (!wndhandle)
193 {
194 MessageBox(NULL, "Cannot allocate window handle -- terminating ircd",
195 NULL, MB_OK | MB_ICONERROR);
196 exit(1);
197 }
198
199 /* Set up a timer which will periodically post a message to our queue.
200 * This way, ircd won't wait infinitely for a network event */
201 SetTimer(wndhandle, 0, SELECT_DELAY, NULL);
202
203 setupfd_hook = install_hook(setup_socket_cb, setup_winsock_fd);
204
205 /* Fill out the nameserver table */
206 if ((lib = LoadLibrary("IPHLPAPI.DLL")) != NULL)
207 if ((_GetNetworkParams = GetProcAddress(lib, "GetNetworkParams")) != NULL)
208 {
209 FIXED_INFO *FixedInfo;
210 ULONG ulOutBufLen;
211 IP_ADDR_STRING *ip;
212 int idx;
213
214 FixedInfo = MyMalloc(sizeof(FIXED_INFO));
215 ulOutBufLen = sizeof(FIXED_INFO);
216
217 if (_GetNetworkParams(FixedInfo, &ulOutBufLen) == ERROR_BUFFER_OVERFLOW)
218 {
219 MyFree(FixedInfo);
220 FixedInfo = MyMalloc(ulOutBufLen);
221
222 if (_GetNetworkParams(FixedInfo, &ulOutBufLen) != ERROR_SUCCESS)
223 return;
224 }
225
226 for (ip = &FixedInfo->DnsServerList; ip != NULL && irc_nscount < IRCD_MAXNS;
227 ip = ip->Next, irc_nscount++)
228 {
229 struct addrinfo *res;
230
231 if (irc_getaddrinfo(ip->IpAddress.String, NULL, NULL, &res))
232 {
233 memcpy(&irc_nsaddr_list[idx], res->ai_addr, res->ai_addrlen);
234 irc_nsaddr_list[idx].ss_len = res->ai_addrlen;
235 }
236 }
237
238 MyFree(FixedInfo);
239 }
240 }
241
242 /*
243 * comm_setselect
244 *
245 * This is a needed exported function which will be called to register
246 * and deregister interest in a pending IO state for a given FD.
247 */
248 void
249 comm_setselect(fde_t *F, unsigned int type, PF *handler,
250 void *client_data, time_t timeout)
251 {
252 int new_events = 0;
253
254 if ((type & COMM_SELECT_READ))
255 {
256 F->read_handler = handler;
257 F->read_data = client_data;
258 }
259
260 if ((type & COMM_SELECT_WRITE))
261 {
262 F->write_handler = handler;
263 F->write_data = client_data;
264 }
265
266 new_events = (F->read_handler ? (FD_ACCEPT | FD_CLOSE | FD_READ) : 0) |
267 (F->write_handler ? (FD_CONNECT | FD_WRITE) : 0);
268
269 if (timeout != 0)
270 F->timeout = CurrentTime + (timeout / 1000);
271
272 if (new_events != F->evcache)
273 {
274 WSAAsyncSelect(F->fd, wndhandle, WM_SOCKET, new_events);
275 F->evcache = new_events;
276 }
277 }
278
279 /*
280 * Waits until a message is posted in our window queue and deals with it.
281 */
282 void
283 comm_select(void)
284 {
285 MSG msg;
286
287 if (!GetMessage(&msg, NULL, 0, 0))
288 {
289 if (dispatch_wm_signal != NULL)
290 dispatch_wm_signal(0);
291 exit(0);
292 }
293
294 set_time();
295
296 DispatchMessage(&msg);
297 }
298
299 /* This is our win32 super-light resolver ;) */
300
301 void
302 delete_resolver_queries(const struct DNSQuery *query)
303 {
304 WSACancelAsyncRequest(query->handle);
305 dlinkDelete(&query->node, &dns_queries);
306 }
307
308 void
309 gethost_byname_type(const char *name, struct DNSQuery *query, int type)
310 {
311 gethost_byname(name, query);
312 }
313
314 void
315 gethost_byname(const char *name, struct DNSQuery *query)
316 {
317 query->handle = WSAAsyncGetHostByName(wndhandle, WM_DNS, name, query->reply,
318 sizeof(query->reply));
319
320 if (!query->handle)
321 query->callback(query->ptr, NULL);
322 else
323 dlinkAdd(query, &query->node, &dns_queries);
324 }
325
326 void
327 gethost_byaddr(const struct irc_ssaddr *addr, struct DNSQuery *query)
328 {
329 query->handle = WSAAsyncGetHostByAddr(
330 wndhandle, WM_DNS,
331 #ifdef IPV6
332 addr.ss.ss_family == AF_INET6 ? &((struct sockaddr_in6*)addr)->sin6_addr) :
333 #endif
334 &((struct sockaddr_in *) addr)->sin_addr,
335 #ifdef IPV6
336 addr.ss.ss_family == AF_INET6 ? sizeof(struct in6_addr) :
337 #endif
338 sizeof(struct in_addr),
339 addr->ss.ss_family, query->reply, sizeof(query->reply)
340 );
341
342 if (!query->handle)
343 query->callback(query->ptr, NULL);
344 else
345 dlinkAdd(query, &query->node, &dns_queries);
346 }

Properties

Name Value
svn:eol-style native
svn:keywords Id Revision