source: trunk/src/wsock32/asyncapi.cpp

Last change on this file was 21916, checked in by dmik, 14 years ago

Merge branch gcc-kmk to trunk.

File size: 27.1 KB
RevLine 
[10428]1/* $Id: asyncapi.cpp,v 1.21 2004-01-30 22:02:11 bird Exp $ */
[3229]2
3/*
4 *
5 * Win32 SOCK32 for OS/2 (Async apis)
6 *
7 * Copyright (C) 2000 Sander van Leeuwen (sandervl@xs4all.nl)
8 *
9 * Parts based on Wine code: (dlls\winsock\async.c)
10 * (C) 1993,1994,1996,1997 John Brezak, Erik Bos, Alex Korobka.
11 * (C) 1999 Marcus Meissner
12 *
13 * Project Odin Software License can be found in LICENSE.TXT
14 *
15 */
16#define INCL_BASE
17#include <os2wrap.h>
18#include <stdio.h>
19#include <stdlib.h>
20#include <string.h>
21#include <odin.h>
22#include <odinwrap.h>
23#include <os2sel.h>
24#include <misc.h>
25#include <win32api.h>
26#include "wsock32.h"
27#include "asyncthread.h"
28#include "wsastruct.h"
29
30#define DBG_LOCALLOG DBG_async
31#include "dbglocal.h"
32
[3472]33//kso: dirty fix to make this compile! not permanent!
34BOOL WINAPI QueryPerformanceCounter(LARGE_INTEGER *p);
35#define LowPart u.LowPart
36
37
[3229]38ODINDEBUGCHANNEL(WSOCK32-ASYNC)
39
40//******************************************************************************
41//NOTE: Must execute RemoveFromQueue before returning
42//******************************************************************************
43void ASYNCCNV WSAsyncThreadProc(void *pparm)
44{
45 PASYNCTHREADPARM pThreadParm = (PASYNCTHREADPARM)pparm;
46 LPARAM lParam;
47 int size = 0;
48 int fail = NO_ERROR;
[3472]49
[3229]50 if(!pThreadParm->fCancelled)
51 {
52 switch(pThreadParm->request)
53 {
54 case ASYNC_GETHOSTBYNAME:
55 case ASYNC_GETHOSTBYADDR:
56 {
57 struct hostent *ret;
58
59 if(pThreadParm->request == ASYNC_GETHOSTBYNAME) {
60 ret = gethostbyname(pThreadParm->u.gethostbyname.name);
61
62 free(pThreadParm->u.gethostbyname.name);
63 pThreadParm->u.gethostbyname.name = 0;
64 }
65 else {
[3472]66 ret = gethostbyaddr(pThreadParm->u.gethostbyaddr.addr,
[3229]67 pThreadParm->u.gethostbyaddr.len,
68 pThreadParm->u.gethostbyaddr.type);
69
70 free(pThreadParm->u.gethostbyaddr.addr);
71 pThreadParm->u.gethostbyaddr.addr = 0;
72 }
73 if (ret != NULL) {
74 size = WS_copy_he((struct ws_hostent *)pThreadParm->buf,
75 pThreadParm->buf,
76 pThreadParm->buflen,
77 ret);
78 if(size < 0) {
79 fail = WSAENOBUFS;
80 size = -size;
81 }
82 }
83 else fail = wsaHerrno();
84 break;
85 }
86
87 case ASYNC_GETPROTOBYNAME:
88 case ASYNC_GETPROTOBYNUMBER:
89 {
90 struct protoent *ret;
91
92 if(pThreadParm->request == ASYNC_GETPROTOBYNAME) {
93 ret = getprotobyname(pThreadParm->u.getprotobyname.name);
94
95 free(pThreadParm->u.getprotobyname.name);
96 pThreadParm->u.getprotobyname.name = 0;
97 }
98 else ret = getprotobynumber(pThreadParm->u.getprotobynumber.number);
99
100 if (ret != NULL) {
101 size = WS_copy_pe((struct ws_protoent *)pThreadParm->buf,
102 pThreadParm->buf,
103 pThreadParm->buflen,
104 ret);
105 if(size < 0) {
106 fail = WSAENOBUFS;
107 size = -size;
108 }
109 }
110 else fail = WSANO_DATA;
111
112 break;
113 }
114
115 case ASYNC_GETSERVBYNAME:
116 case ASYNC_GETSERVBYPORT:
117 {
118 struct servent *ret;
119
120 if(pThreadParm->request == ASYNC_GETSERVBYNAME) {
121 ret = getservbyname(pThreadParm->u.getservbyname.name, pThreadParm->u.getservbyname.proto);
122
123 free(pThreadParm->u.getservbyname.name);
124 pThreadParm->u.getservbyname.name = 0;
125
126 if(pThreadParm->u.getservbyname.proto) {
127 free(pThreadParm->u.getservbyname.proto);
128 pThreadParm->u.getservbyname.proto = 0;
129 }
130
131 }
132 else {
133 ret = getservbyport(pThreadParm->u.getservbyport.port, pThreadParm->u.getservbyport.proto);
134 if(pThreadParm->u.getservbyport.proto) {
135 free(pThreadParm->u.getservbyport.proto);
136 pThreadParm->u.getservbyport.proto = 0;
137 }
138 }
139
140 if (ret != NULL) {
141 size = WS_copy_se((struct ws_servent *)pThreadParm->buf,
142 pThreadParm->buf,
143 pThreadParm->buflen,
144 ret);
145 if(size < 0) {
146 fail = WSAENOBUFS;
147 size = -size;
148 }
149 }
150 else fail = WSANO_DATA;
151 break;
152 }
153 }
154 }
155 lParam = (fail << 16) | size;
156
157 if(!pThreadParm->fCancelled) {
[6196]158 dprintf(("WSAsyncThreadProc %x %x %x %x", pThreadParm->notifyHandle, pThreadParm->notifyData, pThreadParm->hAsyncTaskHandle, lParam));
159 PostMessageA((HWND)pThreadParm->notifyHandle, (DWORD)pThreadParm->notifyData,
[3229]160 (WPARAM)pThreadParm->hAsyncTaskHandle, lParam);
161 }
162 pThreadParm->fActive = FALSE;
[3472]163 RemoveFromQueue(pThreadParm);
[3229]164}
165//******************************************************************************
166//******************************************************************************
[3472]167LHANDLE WSAAsyncRequest(AsyncRequestType requesttype, HWND hwnd, int msg, char *buf,
[3229]168 int buflen, PVOID param1, PVOID param2, PVOID param3,
169 PVOID param4)
170{
171 PASYNCTHREADPARM pThreadParm;
172 LHANDLE hAsyncRequest = 0;
173 LPSTR tempname = 0;
174 LPSTR tempproto = 0;
175 LPSTR tempaddr = 0;
176
177 if(!fWSAInitialized)
178 {
179 WSASetLastError(WSANOTINITIALISED);
180 }
181 else
182 if(WSAIsBlocking())
183 {
184 WSASetLastError(WSAEINPROGRESS); // blocking call in progress
185 }
186 else
187 if(!IsWindow(hwnd))
188 {
189 WSASetLastError(WSAEINVAL); // invalid parameter
190 }
191 else
192 if(buf == NULL || buflen == 0) {
193 WSASetLastError(WSAENOBUFS); // invalid parameter
194 }
195 else
196 {
197 pThreadParm = (PASYNCTHREADPARM)malloc(sizeof(ASYNCTHREADPARM));
198 if(pThreadParm == NULL) {
199 dprintf(("WSAAsyncRequest: malloc failure!"));
200 DebugInt3();
201 WSASetLastError(WSAEFAULT);
202 return 0;
203 }
204 memset(pThreadParm, 0, sizeof(*pThreadParm));
[6196]205 pThreadParm->request = requesttype;
206 pThreadParm->notifyHandle = (int)hwnd;
207 pThreadParm->notifyData = (int)msg;
208 pThreadParm->buf = buf;
209 pThreadParm->buflen = buflen;
[3229]210
211 switch(requesttype) {
212 case ASYNC_GETHOSTBYNAME:
213 tempname = (LPSTR)malloc(strlen((char *)param1)+1);
214 if(tempname == NULL)
215 {
216 dprintf(("WSAAsyncGetHostByName: malloc failure!"));
217 DebugInt3();
218 WSASetLastError(WSAEFAULT);
219 return 0;
220 }
221 pThreadParm->u.gethostbyname.name = tempname;
222 strcpy(pThreadParm->u.gethostbyname.name, (char *)param1);
223 break;
224
225 case ASYNC_GETHOSTBYADDR:
226 tempaddr = (LPSTR)malloc(strlen((char *)param1)+1);
227 if(tempaddr == NULL)
228 {
229 dprintf(("WSAAsyncGetHostByAddr: malloc failure!"));
230 DebugInt3();
231 WSASetLastError(WSAEFAULT);
232 return 0;
233 }
234
235 pThreadParm->u.gethostbyaddr.len = (int)param2;
236 pThreadParm->u.gethostbyaddr.type = (int)param3;
237 pThreadParm->u.gethostbyaddr.addr = tempaddr;
238 strcpy(pThreadParm->u.gethostbyaddr.addr, (char *)param1);
239 break;
240
241 case ASYNC_GETPROTOBYNAME:
242 tempname = (LPSTR)malloc(strlen((char *)param1)+1);
243 if(tempname == NULL)
244 {
245 dprintf(("WSAAsyncGetProtoByName: malloc failure!"));
246 DebugInt3();
247 WSASetLastError(WSAEFAULT);
248 return 0;
249 }
250 pThreadParm->u.getprotobyname.name = tempname;
251 strcpy(pThreadParm->u.getprotobyname.name, (char *)param1);
252 break;
253
254 case ASYNC_GETPROTOBYNUMBER:
255 pThreadParm->u.getprotobynumber.number = (int)param1;
256 break;
257
258 case ASYNC_GETSERVBYNAME:
259 tempname = (LPSTR)malloc(strlen((char *)param1)+1);
260 tempproto = NULL;
261 if(param2) {
262 tempproto = (LPSTR)malloc(strlen((char *)param2)+1);
263 }
264 if(tempname == NULL || (param2 && !tempproto))
265 {
266 dprintf(("WSAAsyncGetServByName: malloc failure!"));
267 DebugInt3();
268 WSASetLastError(WSAEFAULT);
269 return 0;
270 }
271 pThreadParm->u.getservbyname.name = tempname;
272 strcpy(pThreadParm->u.getservbyname.name, (char *)param1);
273 pThreadParm->u.getservbyname.proto = tempproto;
274 if(param2)
275 strcpy(pThreadParm->u.getservbyname.proto, (char *)param2);
276 break;
277
278 case ASYNC_GETSERVBYPORT:
279 if(param2) {
280 tempproto = (LPSTR)malloc(strlen((char *)param2)+1);
281 }
282 if(param2 && !tempproto)
283 {
284 dprintf(("WSAAsyncGetServByPort: malloc failure!"));
285 DebugInt3();
286 WSASetLastError(WSAEFAULT);
287 return 0;
288 }
289 pThreadParm->u.getservbyport.port = (int)param1;
290 pThreadParm->u.getservbyport.proto = tempproto;
291 if(param2)
292 strcpy(pThreadParm->u.getservbyport.proto, (char *)param2);
293 break;
294 }
295 hAsyncRequest = (LHANDLE)QueueAsyncJob(WSAsyncThreadProc, pThreadParm);
296 if(hAsyncRequest == 0) {
297 free(pThreadParm);
298 if(tempname) free(tempname);
299 if(tempaddr) free(tempaddr);
300 if(tempproto) free(tempproto);
301
302 dprintf(("WSAAsyncRequest: QueueAsyncJob failure!"));
303 DebugInt3();
304 WSASetLastError(WSAEFAULT);
305 return 0;
306 }
307 return hAsyncRequest;
308 }
309 return 0;
[3472]310}
[3229]311//******************************************************************************
312//******************************************************************************
313ODINFUNCTION5(LHANDLE,WSAAsyncGetHostByName,
314 HWND,hWnd,
315 u_int,wMsg,
316 const char *,name,
317 char *,buf,
318 int,buflen)
319{
320 dprintf(("WSAAsyncGetHostByName %s", name));
321
[3472]322 return WSAAsyncRequest(ASYNC_GETHOSTBYNAME, hWnd, wMsg, buf, buflen,
[3229]323 (PVOID)name, 0, 0, 0);
324}
325//******************************************************************************
326//******************************************************************************
327ODINFUNCTION7(LHANDLE,WSAAsyncGetHostByAddr,
328 HWND,hWnd,
329 u_int,wMsg,
330 const char *,addr,
331 int,len,
332 int,type,
333 char *,buf,
334 int,buflen)
335{
336 dprintf(("WSAAsyncGetHostByAddr %s", addr));
337
[3472]338 return WSAAsyncRequest(ASYNC_GETHOSTBYADDR, hWnd, wMsg, buf, buflen,
[3229]339 (PVOID)addr, (PVOID)len, (PVOID)type, 0);
340}
341//******************************************************************************
342//******************************************************************************
343ODINFUNCTION5(LHANDLE,WSAAsyncGetProtoByName,
344 HWND,hWnd,
345 u_int,wMsg,
346 const char *,name,
347 char *,buf,
348 int,buflen)
349{
350 dprintf(("WSAAsyncGetProtoByName %s", name));
351
[3472]352 return WSAAsyncRequest(ASYNC_GETPROTOBYNAME, hWnd, wMsg, buf, buflen,
[3229]353 (PVOID)name, 0, 0, 0);
354}
355//******************************************************************************
356//******************************************************************************
357ODINFUNCTION5(LHANDLE,WSAAsyncGetProtoByNumber,
358 HWND,hWnd,
359 u_int,wMsg,
360 int,number,
361 char *,buf,
362 int,buflen)
363{
364 dprintf(("WSAAsyncGetProtoByNumber %d", number));
365
[3472]366 return WSAAsyncRequest(ASYNC_GETPROTOBYNUMBER, hWnd, wMsg, buf, buflen,
[3229]367 (PVOID)number, 0, 0, 0);
368}
369//******************************************************************************
370//******************************************************************************
371ODINFUNCTION6(LHANDLE,WSAAsyncGetServByName,
372 HWND,hWnd,
373 u_int,wMsg,
374 const char *,name,
375 const char *,proto,
376 char *,buf,
377 int,buflen)
378{
379 dprintf(("WSAAsyncGetServByName %s", name));
380
[3472]381 return WSAAsyncRequest(ASYNC_GETSERVBYNAME, hWnd, wMsg, buf, buflen,
[3229]382 (PVOID)name, (PVOID)proto, 0, 0);
383}
384//******************************************************************************
385//******************************************************************************
386ODINFUNCTION6(LHANDLE,WSAAsyncGetServByPort,
387 HWND,hWnd,
388 u_int,wMsg,
389 int,port,
390 const char *,proto,
391 char *,buf,
392 int,buflen)
393{
394 dprintf(("WSAAsyncGetServByPort %d %s", port, proto));
395
[3472]396 return WSAAsyncRequest(ASYNC_GETSERVBYPORT, hWnd, wMsg, buf, buflen,
[3229]397 (PVOID)port, (PVOID)proto, 0, 0);
398}
399//******************************************************************************
400//******************************************************************************
[6196]401void AsyncSelectNotifyEvent(PASYNCTHREADPARM pThreadParm, ULONG event, ULONG socket_error)
[3229]402{
[6196]403 pThreadParm->u.asyncselect.lEventsPending &= ~event;
[3229]404
[7140]405 // @@@AH 20011019 this changes the event code. Don' think we can do this
406 // for the semaphore notification...
407 ULONG eventReply = WSAMAKESELECTREPLY(event, socket_error);
[3229]408
[10428]409#ifdef DEBUG_LOGGING
[21916]410 const char *pszEvent = NULL;
[7146]411
412 switch(event) {
413 case FD_READ:
414 pszEvent = "FD_READ";
415 break;
416 case FD_WRITE:
417 pszEvent = "FD_WRITE";
418 break;
419 case FD_OOB:
420 pszEvent = "FD_OOB";
421 break;
422 case FD_ACCEPT:
423 pszEvent = "FD_ACCEPT";
424 break;
425 case FD_CONNECT:
426 pszEvent = "FD_CONNECT";
427 break;
428 case FD_CLOSE:
429 pszEvent = "FD_CLOSE";
430 break;
431 case FD_QOS:
432 pszEvent = "FD_QOS";
433 break;
434 case FD_GROUP_QOS:
435 pszEvent = "FD_GROUP_QOS";
436 break;
437 case FD_ROUTING_INTERFACE_CHANGE:
438 pszEvent = "FD_ROUTING_INTERFACE_CHANGE";
439 break;
440 case FD_ADDRESS_LIST_CHANGE:
441 pszEvent = "FD_ADDRESS_LIST_CHANGE";
442 break;
443 }
444#endif
445
[6196]446 if (pThreadParm->u.asyncselect.mode == WSA_SELECT_HWND)
447 {
[7146]448 dprintf(("AsyncSelectNotifyEvent: WINDOW, socket: 0x%x, window handle: 0x%x, window message: 0x%x, event: %s (0x%x)", pThreadParm->u.asyncselect.s, pThreadParm->notifyHandle, pThreadParm->notifyData, pszEvent, eventReply));
[6196]449 PostMessageA((HWND)pThreadParm->notifyHandle, (DWORD)pThreadParm->notifyData, (WPARAM)pThreadParm->u.asyncselect.s,
[7140]450 (LPARAM)eventReply);
[6196]451 }
452 else
453 if (pThreadParm->u.asyncselect.mode == WSA_SELECT_HEVENT)
454 {
[7146]455 dprintf(("AsyncSelectNotifyEvent: SEM, socket: 0x%x, HEVENT: 0x%x, event: %s (0x%x)", pThreadParm->u.asyncselect.s, pThreadParm->notifyHandle, pszEvent, event));
[7140]456 // set the event bit in the mask
[7041]457 pThreadParm->u.asyncselect.lLastEvent |= event;
[7140]458 // set the error code for the right value
459 // for this, we first have to find out which bit field to write to
460 char slot = 0;
461 ULONG eventValue = event;
462 while (eventValue > 0)
463 {
464 slot++;
465 eventValue = eventValue >> 1;
466 }
467 pThreadParm->u.asyncselect.iErrorCode[slot] = socket_error;
468 // now post the semaphore so that the client can check the event
[6196]469 SetEvent(pThreadParm->notifyHandle);
470 }
471 else
472 {
473 dprintf(("AsyncSelectNotifyEvent: error, unknown mode"));
474 }
[3229]475}
476//******************************************************************************
477#define nr(i) ((i != -1) ? 1 : 0)
478#define ready(i) ((i != -1) && (sockets[i] != -1))
479//NOTE: Must execute RemoveFromQueue before returning
480//******************************************************************************
481void ASYNCCNV WSAsyncSelectThreadProc(void *pparm)
482{
483 PASYNCTHREADPARM pThreadParm = (PASYNCTHREADPARM)pparm;
484 SOCKET sockets[3];
485 SOCKET s = pThreadParm->u.asyncselect.s;
486 int noread, nowrite, noexcept, state, sockoptlen, sockoptval;
487 int tmp, i, lEventsPending, ret, bytesread;
[3472]488
[3229]489 while(TRUE)
490 {
491asyncloopstart:
492 i = 0;
493 noread = nowrite = noexcept = -1;
494
495 //break if user cancelled request
[7041]496 if(pThreadParm->u.asyncselect.lEvents == 0 || pThreadParm->fCancelled) {
[3229]497 break;
498 }
499
500 lEventsPending = pThreadParm->u.asyncselect.lEventsPending;
501 //block if no events are pending
502 if(lEventsPending == 0)
503 {
[5625]504 dprintf2(("WSAsyncSelectThreadProc: waiting for new events"));
[3229]505 //wait for events to be enabled
506 pThreadParm->u.asyncselect.asyncSem->wait();
507 //reset event semaphore
508 pThreadParm->u.asyncselect.asyncSem->reset();
509 continue;
510 }
511
512 if(lEventsPending & (FD_READ | FD_CLOSE | FD_ACCEPT)) {
513 noread = i++;
514 sockets[noread] = s;
515 }
516 if((lEventsPending & FD_CONNECT) ||
517 ((lEventsPending & FD_WRITE) &&
518 (!(ioctl(s, FIOBSTATUS, (char *)&tmp, sizeof(tmp)) & SS_CANTSENDMORE))))
519 {
520 nowrite = i++;
521 sockets[nowrite] = s;
522 }
523 if(lEventsPending & FD_OOB) {
524 noexcept = i++;
525 sockets[noexcept] = s;
526 }
527
[5625]528 dprintf2(("WSAsyncSelectThreadProc %x rds=%d, wrs=%d, oos =%d, pending = %x", pThreadParm->u.asyncselect.s, noread, nowrite, noexcept, lEventsPending));
[3229]529
[3557]530 pThreadParm->fWaitSelect = TRUE;
[3229]531 ret = select((int *)sockets, nr(noread), nr(nowrite), nr(noexcept), -1);
[3557]532 pThreadParm->fWaitSelect = FALSE;
[7992]533
[3229]534 if(ret == SOCKET_ERROR) {
535 int selecterr = sock_errno();
[7146]536 dprintf(("WSAsyncSelectThreadProc %x rds=%d, wrs=%d, oos =%d, pending = %x select returned %x", pThreadParm->u.asyncselect.s, noread, nowrite, noexcept, lEventsPending, selecterr));
[3260]537 if(selecterr && selecterr < SOCBASEERR) {
538 selecterr += SOCBASEERR;
539 }
[3472]540 switch(selecterr)
[3229]541 {
542 case SOCEINTR:
[3265]543//// state = ioctl(s, FIOBSTATUS, (char *)&tmp, sizeof(tmp));
544//// dprintf(("SOCEINTR; state = %x", state));
[7992]545 goto asyncloopstart; //so_cancel/closesocket was called
[3229]546
547 case SOCECONNRESET:
548 case SOCEPIPE:
[7140]549 if(lEventsPending & FD_CLOSE)
550 {
[3439]551 dprintf(("FD_CLOSE; broken connection"));
[7140]552 AsyncSelectNotifyEvent(pThreadParm, FD_CLOSE, WSAECONNRESET);
[3439]553 }
[3229]554
555 //remote connection broken (so can't receive data anymore)
556 //but can still send
557 pThreadParm->u.asyncselect.lEventsPending &= ~(FD_READ | FD_ACCEPT);
[3472]558 goto asyncloopstart;
[3229]559
560 case SOCEINVAL:
[3439]561 if(lEventsPending & FD_CLOSE) {
562 dprintf(("FD_CLOSE; SOCEINVAL"));
[6196]563 AsyncSelectNotifyEvent(pThreadParm, FD_CLOSE, selecterr);
[3439]564 }
[3229]565 break;
566 default:
567 dprintf(("WSAsyncSelectThreadProc: select SOCKET_ERROR %x", selecterr));
568 break; //something bad happened
569 }
570 break;
571 }
572
573 if(ready(nowrite))
574 {
575 state = ioctl(s, FIOBSTATUS, (char *)&tmp, sizeof(tmp));
576
[7992]577 //Don't send FD_CONNECT is socket was already connected (accept returns connected socket)
[10428]578 if(!pThreadParm->fConnected && (lEventsPending & FD_CONNECT))
[7992]579 {
[3229]580 if(state & SS_ISCONNECTED) {
[6196]581 AsyncSelectNotifyEvent(pThreadParm, FD_CONNECT, NO_ERROR);
[7992]582 pThreadParm->fConnected = TRUE;
[3229]583 }
584 else {
585 sockoptlen = sizeof(int);
586
587 ret = getsockopt(s, SOL_SOCKET, SO_ERROR,
588 (char *) &sockoptval, &sockoptlen);
589 //SvL: WSeB returns SOCECONNREFUSED, Warp 4 0x3d
590 if(sockoptval == SOCECONNREFUSED || sockoptval == (SOCECONNREFUSED - SOCBASEERR)) {
[6196]591 AsyncSelectNotifyEvent(pThreadParm, FD_CONNECT, WSAECONNREFUSED);
[3229]592 }
[3472]593 }
[3229]594 }
595 else
596 if(!(state & SS_CANTSENDMORE) && (lEventsPending & FD_WRITE)) {
[6196]597 AsyncSelectNotifyEvent(pThreadParm, FD_WRITE, NO_ERROR);
[3229]598 }
599 }
600 if(ready(noread))
601 {
602 state = ioctl(s, FIONREAD, (CHAR *) &bytesread, sizeof(bytesread));
[7992]603 dprintf2(("state %x, bytesread %d", state, bytesread));
[3472]604 if(state == SOCKET_ERROR)
[3265]605 {
[3472]606 if(lEventsPending & FD_CLOSE)
[3229]607 {
[3439]608 dprintf(("FD_CLOSE; ioctl; socket error"));
[6196]609 AsyncSelectNotifyEvent(pThreadParm, FD_CLOSE, NO_ERROR);
[3229]610 //remote connection broken (so can't receive data anymore)
611 //but can still send
612 pThreadParm->u.asyncselect.lEventsPending &= ~(FD_READ | FD_ACCEPT);
613 continue;
614 }
615 else {
616 dprintf(("WSAsyncSelectThreadProc: ioctl SOCKET_ERROR!"));
617 break; //todo: correct???
618 }
619 }
[3472]620 if(lEventsPending & FD_ACCEPT)
[3229]621 {
622 sockoptlen = sizeof(sockoptlen);
623
624 ret = getsockopt(s, SOL_SOCKET, SO_OPTIONS,
625 (char *) &sockoptval, &sockoptlen);
626 if(ret == SOCKET_ERROR) {
627 dprintf(("WSAsyncSelectThreadProc: getsockopt SOCKET_ERROR!"));
628 break;
629 }
630 if((sockoptval & SO_ACCEPTCONN) == SO_ACCEPTCONN) {
[6196]631 AsyncSelectNotifyEvent(pThreadParm, FD_ACCEPT, NO_ERROR);
[3229]632 }
633 }
[7146]634 if((lEventsPending & FD_READ) && bytesread > 0) {
[6196]635 AsyncSelectNotifyEvent(pThreadParm, FD_READ, NO_ERROR);
[3229]636 }
[3472]637 else
[10428]638 if((lEventsPending & FD_CLOSE) && (state == 0 && bytesread == 0))
[7146]639 {
640 state = ioctl(s, FIOBSTATUS, (char *)&tmp, sizeof(tmp));
641
[10428]642 //Have to make sure this doesn't generates FD_CLOSE
643 //messages when the connection is just fine (recv
[7146]644 //executed in another thread when select returns)
645 if(state & (SS_CANTRCVMORE|SS_CANTSENDMORE|SS_ISDISCONNECTING|SS_ISDISCONNECTED)) {
646 dprintf(("FD_CLOSE; state == 0 && bytesread == 0, state = %x", state));
647 AsyncSelectNotifyEvent(pThreadParm, FD_CLOSE, NO_ERROR);
648 }
[3265]649 }
[3229]650 }
651 if(ready(noexcept))
652 {
653 if(lEventsPending & FD_OOB) {
[6196]654 AsyncSelectNotifyEvent(pThreadParm, FD_OOB, NO_ERROR);
[3229]655 }
656 }
[3472]657 if((pThreadParm->u.asyncselect.lEventsPending & (FD_ACCEPT|FD_CLOSE|FD_CONNECT)) ==
[3229]658 (lEventsPending & (FD_ACCEPT|FD_CLOSE|FD_CONNECT))) {
659 DosSleep(10);
660 }
661 }
662 //remove it first, then delete semaphore object
663 pThreadParm->fActive = FALSE;
[3472]664 RemoveFromQueue(pThreadParm);
[3229]665 delete pThreadParm->u.asyncselect.asyncSem;
666 pThreadParm->u.asyncselect.asyncSem = 0;
667}
668//******************************************************************************
669//******************************************************************************
670ODINFUNCTION4(int,WSAAsyncSelect,
671 SOCKET,s,
672 HWND,hWnd,
673 u_int,wMsg,
674 long,lEvent)
675{
[6196]676 /* just forward call to worker method */
677 return WSAAsyncSelectWorker(s, WSA_SELECT_HWND, (int)hWnd, (int)wMsg, lEvent);
678}
679//******************************************************************************
680//******************************************************************************
[7977]681int WSAAsyncSelectWorker(SOCKET s, int mode, DWORD notifyHandle, DWORD notifyData, DWORD lEventMask)
[6196]682{
[3229]683 PASYNCTHREADPARM pThreadParm;
684 int nonblock = 1;
685 int ret;
686
[6196]687#ifdef DEBUG
688 // log all event bits that are set
689 char tmpbuf[300];
690 strcpy(tmpbuf, "");
691 if (lEventMask & FD_READ)
692 strcat(tmpbuf, " FD_READ");
693 if (lEventMask & FD_WRITE)
694 strcat(tmpbuf, " FD_WRITE");
695 if (lEventMask & FD_OOB)
[10428]696 strcat(tmpbuf, " FD_OOB");
[6196]697 if (lEventMask & FD_ACCEPT)
698 strcat(tmpbuf, " FD_ACCEPT");
699 if (lEventMask & FD_CONNECT)
700 strcat(tmpbuf, " FD_CONNECT");
701 if (lEventMask & FD_CLOSE)
702 strcat(tmpbuf, " FD_CLOSE");
703 if (lEventMask & FD_QOS)
704 strcat(tmpbuf, " FD_QOS");
705 if (lEventMask & FD_GROUP_QOS)
706 strcat(tmpbuf, " FD_GROUP_QOS");
707 if (lEventMask & FD_ROUTING_INTERFACE_CHANGE)
708 strcat(tmpbuf, " FD_ROUTING_INTERFACE_CHANGE");
709 if (lEventMask & FD_ADDRESS_LIST_CHANGE)
710 strcat(tmpbuf, " FD_ADDRESS_LIST_CHANGE");
711 dprintf(("event bits:%s", tmpbuf));
712#endif
713
[3229]714 if(!fWSAInitialized)
715 {
[6196]716 dprintf(("WSA sockets not initialized"));
[3229]717 WSASetLastError(WSANOTINITIALISED);
718 return SOCKET_ERROR;
719 }
720 else
721 if(WSAIsBlocking())
722 {
[6196]723 dprintf(("blocking call in progress"));
[3229]724 WSASetLastError(WSAEINPROGRESS); // blocking call in progress
725 return SOCKET_ERROR;
726 }
727 else
[6196]728 if((mode == WSA_SELECT_HWND) && (HWND)notifyHandle && !IsWindow((HWND)notifyHandle))
[3229]729 {
[6196]730 dprintf(("invalid window handle"));
[3229]731 WSASetLastError(WSAEINVAL); // invalid parameter
732 return SOCKET_ERROR;
733 }
[6196]734
[6253]735 // Set socket to non-blocking mode
736 ret = ioctl(s, FIONBIO, (char *)&nonblock, sizeof(nonblock));
[3229]737 if(ret == SOCKET_ERROR) {
[6196]738 dprintf(("setting socket to non blocking mode failed"));
[3229]739 WSASetLastError(wsaErrno());
740 return SOCKET_ERROR;
741 }
[6196]742 if(FindAndSetAsyncEvent(s, mode, notifyHandle, notifyData, lEventMask) == TRUE)
743 {
744 dprintf(("already got socket, just changing event mask"));
[3229]745 //found and changed active async event
746 WSASetLastError(NO_ERROR);
747 return NO_ERROR;
748 }
[21656]749 if(lEventMask == 0) {
750 // it's a call to cancel the non-existing association on this socket,
751 // return shortly (existing associations are canceled by the "if" above)
752 WSASetLastError(NO_ERROR);
753 return NO_ERROR;
754 }
755
[3229]756 pThreadParm = (PASYNCTHREADPARM)malloc(sizeof(ASYNCTHREADPARM));
757 if(pThreadParm == NULL) {
758 dprintf(("WSAAsyncSelect: malloc failure!"));
759 DebugInt3();
760 WSASetLastError(WSAEFAULT);
761 return SOCKET_ERROR;
762 }
763 memset(pThreadParm, 0, sizeof(*pThreadParm));
[6196]764 pThreadParm->request = ASYNC_SELECT;
765 pThreadParm->notifyHandle = notifyHandle;
766 pThreadParm->notifyData = notifyData;
767 pThreadParm->u.asyncselect.mode = mode;
768 pThreadParm->u.asyncselect.lEvents = lEventMask;
769 pThreadParm->u.asyncselect.lEventsPending = lEventMask;
[7140]770 pThreadParm->u.asyncselect.s = s;
771 // reset all event bits
[7041]772 pThreadParm->u.asyncselect.lLastEvent = 0;
[7140]773 // reset all error bits
[7146]774 memset(pThreadParm->u.asyncselect.iErrorCode, 0, sizeof(pThreadParm->u.asyncselect.iErrorCode));
[3229]775 pThreadParm->u.asyncselect.asyncSem = new VSemaphore;
776 if(pThreadParm->u.asyncselect.asyncSem == NULL) {
777 dprintf(("WSAAsyncSelect: VSemaphore alloc failure!"));
778 DebugInt3();
779 WSASetLastError(WSAEFAULT);
780 return SOCKET_ERROR;
781 }
[7992]782
783 int size, state, tmp;
784 state = ioctl(s, FIOBSTATUS, (char *)&tmp, sizeof(tmp));
785 dprintf(("QueueAsyncJob: state %x", state));
786
787 //Don't send FD_CONNECT is socket was already connected (accept returns connected socket)
788 if(state & SS_ISCONNECTED) {
789 pThreadParm->fConnected = TRUE;
790 }
791 else pThreadParm->fConnected = FALSE;
792
[3229]793 if(QueueAsyncJob(WSAsyncSelectThreadProc, pThreadParm) == 0) {
794 delete pThreadParm->u.asyncselect.asyncSem;
795 free(pThreadParm);
796 dprintf(("WSAAsyncSelect: QueueAsyncJob failure!"));
797 DebugInt3();
798 WSASetLastError(WSAEFAULT);
799 return SOCKET_ERROR;
800 }
801 WSASetLastError(NO_ERROR);
802 return NO_ERROR;
803}
804//******************************************************************************
805//******************************************************************************
[6201]806int WSAEnumNetworkEventsWorker(SOCKET s, WSAEVENT hEvent, LPWSANETWORKEVENTS lpEvent)
807{
808 PASYNCTHREADPARM pThreadInfo;
809
810 asyncThreadMutex.enter();
811 pThreadInfo = FindAsyncEvent(s);
812 if (pThreadInfo)
813 {
[7140]814 // return our internal error bit representation
815 memcpy(&lpEvent->iErrorCode, &pThreadInfo->u.asyncselect.iErrorCode, sizeof(int) * FD_MAX_EVENTS);
816 // return our internal event bit representation
[7041]817 lpEvent->lNetworkEvents = InterlockedExchange((LPLONG)&pThreadInfo->u.asyncselect.lLastEvent, 0);
[10428]818 }
[7041]819 else
[6201]820 {
[6205]821 asyncThreadMutex.leave();
[6201]822 dprintf(("no async registration for socket %x", s));
823 // TODO: correct behavior?
824 WSASetLastError(WSAEINVAL);
825 return SOCKET_ERROR;
826 }
[7041]827 asyncThreadMutex.leave();
[6201]828
[6203]829 // reset event semaphore if present
[6201]830 if (hEvent)
831 {
832// dprintf(("posting event semaphore 0x%x", hEvent));
[6203]833 ResetEvent(hEvent);
[6201]834 }
835
836 WSASetLastError(NO_ERROR);
837 return NO_ERROR;
838}
839//******************************************************************************
[21916]840//******************************************************************************
Note: See TracBrowser for help on using the repository browser.