source: trunk/src/wsock32/new/asyncapi.cpp@ 3205

Last change on this file since 3205 was 3205, checked in by sandervl, 25 years ago

wsock32\new update

File size: 18.7 KB
Line 
1/* $Id: asyncapi.cpp,v 1.2 2000-03-23 19:21:53 sandervl Exp $ */
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
33ODINDEBUGCHANNEL(WSOCK32-ASYNC)
34
35//******************************************************************************
36//******************************************************************************
37void ASYNCCNV WSAsyncThreadProc(void *pparm)
38{
39 PASYNCTHREADPARM pThreadParm = (PASYNCTHREADPARM)pparm;
40 LPARAM lParam;
41 int size = 0;
42 int fail = NO_ERROR;
43
44 if(!pThreadParm->fCancelled)
45 {
46 switch(pThreadParm->request)
47 {
48 case ASYNC_GETHOSTBYNAME:
49 case ASYNC_GETHOSTBYADDR:
50 {
51 struct hostent *ret;
52
53 if(pThreadParm->request == ASYNC_GETHOSTBYNAME) {
54 ret = gethostbyname(pThreadParm->u.gethostbyname.name);
55
56 free(pThreadParm->u.gethostbyname.name);
57 pThreadParm->u.gethostbyname.name = 0;
58 }
59 else {
60 ret = gethostbyaddr(pThreadParm->u.gethostbyaddr.addr,
61 pThreadParm->u.gethostbyaddr.len,
62 pThreadParm->u.gethostbyaddr.type);
63
64 free(pThreadParm->u.gethostbyaddr.addr);
65 pThreadParm->u.gethostbyaddr.addr = 0;
66 }
67 if (ret != NULL) {
68 size = WS_copy_he((struct ws_hostent *)pThreadParm->buf,
69 pThreadParm->buf,
70 pThreadParm->buflen,
71 ret);
72 if(size < 0) {
73 fail = WSAENOBUFS;
74 size = -size;
75 }
76 }
77 else fail = WSANO_DATA;
78 break;
79 }
80
81 case ASYNC_GETPROTOBYNAME:
82 case ASYNC_GETPROTOBYNUMBER:
83 {
84 struct protoent *ret;
85
86 if(pThreadParm->request == ASYNC_GETPROTOBYNAME) {
87 ret = getprotobyname(pThreadParm->u.getprotobyname.name);
88
89 free(pThreadParm->u.getprotobyname.name);
90 pThreadParm->u.getprotobyname.name = 0;
91 }
92 else ret = getprotobynumber(pThreadParm->u.getprotobynumber.number);
93
94 if (ret != NULL) {
95 size = WS_copy_pe((struct ws_protoent *)pThreadParm->buf,
96 pThreadParm->buf,
97 pThreadParm->buflen,
98 ret);
99 if(size < 0) {
100 fail = WSAENOBUFS;
101 size = -size;
102 }
103 }
104 else fail = WSANO_DATA;
105
106 break;
107 }
108
109 case ASYNC_GETSERVBYNAME:
110 case ASYNC_GETSERVBYPORT:
111 {
112 struct servent *ret;
113
114 if(pThreadParm->request == ASYNC_GETSERVBYNAME) {
115 ret = getservbyname(pThreadParm->u.getservbyname.name, pThreadParm->u.getservbyname.proto);
116
117 free(pThreadParm->u.getservbyname.name);
118 pThreadParm->u.getservbyname.name = 0;
119
120 if(pThreadParm->u.getservbyname.proto) {
121 free(pThreadParm->u.getservbyname.proto);
122 pThreadParm->u.getservbyname.proto = 0;
123 }
124
125 }
126 else {
127 ret = getservbyport(pThreadParm->u.getservbyport.port, pThreadParm->u.getservbyport.proto);
128 if(pThreadParm->u.getservbyport.proto) {
129 free(pThreadParm->u.getservbyport.proto);
130 pThreadParm->u.getservbyport.proto = 0;
131 }
132 }
133
134 if (ret != NULL) {
135 size = WS_copy_se((struct ws_servent *)pThreadParm->buf,
136 pThreadParm->buf,
137 pThreadParm->buflen,
138 ret);
139 if(size < 0) {
140 fail = WSAENOBUFS;
141 size = -size;
142 }
143 }
144 else fail = WSANO_DATA;
145 break;
146 }
147 }
148 }
149 lParam = (fail << 16) | size;
150
151 if(!pThreadParm->fCancelled) {
152 PostMessageA(pThreadParm->hwnd, pThreadParm->msg,
153 (WPARAM)pThreadParm->hAsyncTaskHandle, lParam);
154 }
155}
156//******************************************************************************
157//******************************************************************************
158LHANDLE WSAAsyncRequest(AsyncRequestType requesttype, HWND hwnd, int msg, char *buf,
159 int buflen, PVOID param1, PVOID param2, PVOID param3,
160 PVOID param4)
161{
162 PASYNCTHREADPARM pThreadParm;
163 LHANDLE hAsyncRequest = 0;
164 LPSTR tempname = 0;
165 LPSTR tempproto = 0;
166 LPSTR tempaddr = 0;
167
168 if(!fWSAInitialized)
169 {
170 WSASetLastError(WSANOTINITIALISED);
171 }
172 else
173 if(WSAIsBlocking())
174 {
175 WSASetLastError(WSAEINPROGRESS); // blocking call in progress
176 }
177 else
178 if(!IsWindow(hwnd))
179 {
180 WSASetLastError(WSAEINVAL); // invalid parameter
181 }
182 else
183 if(buf == NULL || buflen == 0) {
184 WSASetLastError(WSAENOBUFS); // invalid parameter
185 }
186 else
187 {
188 pThreadParm = (PASYNCTHREADPARM)malloc(sizeof(ASYNCTHREADPARM));
189 if(pThreadParm == NULL) {
190 dprintf(("WSAAsyncRequest: malloc failure!"));
191 DebugInt3();
192 WSASetLastError(WSAEFAULT);
193 return 0;
194 }
195 memset(pThreadParm, 0, sizeof(*pThreadParm));
196 pThreadParm->request= requesttype;
197 pThreadParm->hwnd = hwnd;
198 pThreadParm->msg = msg;
199 pThreadParm->buf = buf;
200 pThreadParm->buflen = buflen;
201
202 switch(requesttype) {
203 case ASYNC_GETHOSTBYNAME:
204 tempname = (LPSTR)malloc(strlen((char *)param1)+1);
205 if(tempname == NULL)
206 {
207 dprintf(("WSAAsyncGetHostByName: malloc failure!"));
208 DebugInt3();
209 WSASetLastError(WSAEFAULT);
210 return 0;
211 }
212 pThreadParm->u.gethostbyname.name = tempname;
213 strcpy(pThreadParm->u.gethostbyname.name, (char *)param1);
214 break;
215
216 case ASYNC_GETHOSTBYADDR:
217 tempaddr = (LPSTR)malloc(strlen((char *)param1)+1);
218 if(tempaddr == NULL)
219 {
220 dprintf(("WSAAsyncGetHostByAddr: malloc failure!"));
221 DebugInt3();
222 WSASetLastError(WSAEFAULT);
223 return 0;
224 }
225
226 pThreadParm->u.gethostbyaddr.len = (int)param2;
227 pThreadParm->u.gethostbyaddr.type = (int)param3;
228 pThreadParm->u.gethostbyaddr.addr = tempaddr;
229 strcpy(pThreadParm->u.gethostbyaddr.addr, (char *)param1);
230 break;
231
232 case ASYNC_GETPROTOBYNAME:
233 tempname = (LPSTR)malloc(strlen((char *)param1)+1);
234 if(tempname == NULL)
235 {
236 dprintf(("WSAAsyncGetProtoByName: malloc failure!"));
237 DebugInt3();
238 WSASetLastError(WSAEFAULT);
239 return 0;
240 }
241 pThreadParm->u.getprotobyname.name = tempname;
242 strcpy(pThreadParm->u.getprotobyname.name, (char *)param1);
243 break;
244
245 case ASYNC_GETPROTOBYNUMBER:
246 pThreadParm->u.getprotobynumber.number = (int)param1;
247 break;
248
249 case ASYNC_GETSERVBYNAME:
250 tempname = (LPSTR)malloc(strlen((char *)param1)+1);
251 tempproto = NULL;
252 if(param2) {
253 tempproto = (LPSTR)malloc(strlen((char *)param2)+1);
254 }
255 if(tempname == NULL || (param2 && !tempproto))
256 {
257 dprintf(("WSAAsyncGetServByName: malloc failure!"));
258 DebugInt3();
259 WSASetLastError(WSAEFAULT);
260 return 0;
261 }
262 pThreadParm->u.getservbyname.name = tempname;
263 strcpy(pThreadParm->u.getservbyname.name, (char *)param1);
264 pThreadParm->u.getservbyname.proto = tempproto;
265 if(param2)
266 strcpy(pThreadParm->u.getservbyname.proto, (char *)param2);
267 break;
268
269 case ASYNC_GETSERVBYPORT:
270 if(param2) {
271 tempproto = (LPSTR)malloc(strlen((char *)param2)+1);
272 }
273 if(param2 && !tempproto)
274 {
275 dprintf(("WSAAsyncGetServByPort: malloc failure!"));
276 DebugInt3();
277 WSASetLastError(WSAEFAULT);
278 return 0;
279 }
280 pThreadParm->u.getservbyport.port = (int)param1;
281 pThreadParm->u.getservbyport.proto = tempproto;
282 if(param2)
283 strcpy(pThreadParm->u.getservbyport.proto, (char *)param2);
284 break;
285 }
286 hAsyncRequest = (LHANDLE)QueueAsyncJob(WSAsyncThreadProc, pThreadParm);
287 if(hAsyncRequest == 0) {
288 free(pThreadParm);
289 if(tempname) free(tempname);
290 if(tempaddr) free(tempaddr);
291 if(tempproto) free(tempproto);
292
293 dprintf(("WSAAsyncRequest: QueueAsyncJob failure!"));
294 DebugInt3();
295 WSASetLastError(WSAEFAULT);
296 return 0;
297 }
298 return hAsyncRequest;
299 }
300 return 0;
301}
302//******************************************************************************
303//******************************************************************************
304ODINFUNCTION5(LHANDLE,WSAAsyncGetHostByName,
305 HWND,hWnd,
306 u_int,wMsg,
307 const char *,name,
308 char *,buf,
309 int,buflen)
310{
311 dprintf(("WSAAsyncGetHostByName %s", name));
312
313 return WSAAsyncRequest(ASYNC_GETHOSTBYNAME, hWnd, wMsg, buf, buflen,
314 (PVOID)name, 0, 0, 0);
315}
316//******************************************************************************
317//******************************************************************************
318ODINFUNCTION7(LHANDLE,WSAAsyncGetHostByAddr,
319 HWND,hWnd,
320 u_int,wMsg,
321 const char *,addr,
322 int,len,
323 int,type,
324 char *,buf,
325 int,buflen)
326{
327 dprintf(("WSAAsyncGetHostByAddr %s", addr));
328
329 return WSAAsyncRequest(ASYNC_GETHOSTBYADDR, hWnd, wMsg, buf, buflen,
330 (PVOID)addr, (PVOID)len, (PVOID)type, 0);
331}
332//******************************************************************************
333//******************************************************************************
334ODINFUNCTION5(LHANDLE,WSAAsyncGetProtoByName,
335 HWND,hWnd,
336 u_int,wMsg,
337 const char *,name,
338 char *,buf,
339 int,buflen)
340{
341 dprintf(("WSAAsyncGetProtoByName %s", name));
342
343 return WSAAsyncRequest(ASYNC_GETPROTOBYNAME, hWnd, wMsg, buf, buflen,
344 (PVOID)name, 0, 0, 0);
345}
346//******************************************************************************
347//******************************************************************************
348ODINFUNCTION5(LHANDLE,WSAAsyncGetProtoByNumber,
349 HWND,hWnd,
350 u_int,wMsg,
351 int,number,
352 char *,buf,
353 int,buflen)
354{
355 dprintf(("WSAAsyncGetProtoByNumber %d", number));
356
357 return WSAAsyncRequest(ASYNC_GETPROTOBYNUMBER, hWnd, wMsg, buf, buflen,
358 (PVOID)number, 0, 0, 0);
359}
360//******************************************************************************
361//******************************************************************************
362ODINFUNCTION6(LHANDLE,WSAAsyncGetServByName,
363 HWND,hWnd,
364 u_int,wMsg,
365 const char *,name,
366 const char *,proto,
367 char *,buf,
368 int,buflen)
369{
370 dprintf(("WSAAsyncGetServByName %s", name));
371
372 return WSAAsyncRequest(ASYNC_GETSERVBYNAME, hWnd, wMsg, buf, buflen,
373 (PVOID)name, (PVOID)proto, 0, 0);
374}
375//******************************************************************************
376//******************************************************************************
377ODINFUNCTION6(LHANDLE,WSAAsyncGetServByPort,
378 HWND,hWnd,
379 u_int,wMsg,
380 int,port,
381 const char *,proto,
382 char *,buf,
383 int,buflen)
384{
385 dprintf(("WSAAsyncGetServByPort %d %s", port, proto));
386
387 return WSAAsyncRequest(ASYNC_GETSERVBYPORT, hWnd, wMsg, buf, buflen,
388 (PVOID)port, (PVOID)proto, 0, 0);
389}
390//******************************************************************************
391//******************************************************************************
392void AsyncNotifyEvent(PASYNCTHREADPARM pThreadParm, ULONG event, ULONG socket_error)
393{
394 pThreadParm->u.asyncselect.lEventsPending &= ~event;
395
396 event = WSAMAKESELECTREPLY(event, socket_error);
397
398 PostMessageA(pThreadParm->hwnd, pThreadParm->msg, (WPARAM)pThreadParm->u.asyncselect.s,
399 (LPARAM)event);
400}
401//******************************************************************************
402#define nr(i) ((i != -1) ? 1 : 0)
403#define ready(i) ((i != -1) && (sockets[i] != -1))
404//******************************************************************************
405void ASYNCCNV WSAsyncSelectThreadProc(void *pparm)
406{
407 PASYNCTHREADPARM pThreadParm = (PASYNCTHREADPARM)pparm;
408 SOCKET sockets[3];
409 SOCKET s = pThreadParm->u.asyncselect.s;
410 int noread, nowrite, noexcept, state, sockoptlen, sockoptval;
411 int tmp, i, lEventsPending, ret, bytesread;
412
413 while(TRUE)
414 {
415asyncloopstart:
416 i = 0;
417 noread = nowrite = noexcept = -1;
418
419 //break if user cancelled request
420 if(pThreadParm->u.asyncselect.lEvents == 0) {
421 break;
422 }
423
424 lEventsPending = pThreadParm->u.asyncselect.lEventsPending;
425 //block if no events are pending
426 if(lEventsPending == 0)
427 {
428 //wait for events to be enabled
429 pThreadParm->u.asyncselect.asyncSem->wait();
430 //reset event semaphore
431 pThreadParm->u.asyncselect.asyncSem->reset();
432 continue;
433 }
434
435 if(lEventsPending & (FD_READ | FD_CLOSE | FD_ACCEPT)) {
436 noread = i++;
437 sockets[noread] = s;
438 }
439 if(lEventsPending & (FD_WRITE | FD_CONNECT)) {
440 nowrite = i++;
441 sockets[nowrite] = s;
442 }
443 if(lEventsPending & FD_OOB) {
444 noexcept = i++;
445 sockets[noexcept] = s;
446 }
447
448 dprintf(("WSAsyncSelectThreadProc %x wrs=%d, rds=%d, oos =%d, pending = %x", pThreadParm->u.asyncselect.s, noread, nowrite, noexcept, lEventsPending));
449
450 ret = select((int *)sockets, nr(noread), nr(nowrite), nr(noexcept), -1);
451 if(ret == SOCKET_ERROR) {
452 int selecterr = sock_errno();
453 switch(selecterr)
454 {
455 case SOCEINTR:
456 goto asyncloopstart; //so_cancel was called
457
458 case SOCECONNRESET:
459 case SOCEPIPE:
460 if(lEventsPending & FD_CLOSE)
461 AsyncNotifyEvent(pThreadParm, FD_CLOSE, WSAECONNRESET);
462
463 //remote connection broken (so can't receive data anymore)
464 //but can still send
465 pThreadParm->u.asyncselect.lEventsPending &= ~(FD_READ | FD_ACCEPT);
466 goto asyncloopstart;
467
468 case SOCEINVAL:
469 if(lEventsPending & FD_CLOSE)
470 AsyncNotifyEvent(pThreadParm, FD_CLOSE, selecterr);
471 break;
472 default:
473 dprintf(("WSAsyncSelectThreadProc: select SOCKET_ERROR %x", selecterr));
474 break; //something bad happened
475 }
476 break;
477 }
478
479 if(ready(nowrite))
480 {
481 state = ioctl(s, FIOBSTATUS, (char *)&tmp, sizeof(tmp));
482
483 if(lEventsPending & FD_CONNECT) {
484 if(state & SS_ISCONNECTED) {
485 AsyncNotifyEvent(pThreadParm, FD_CONNECT, NO_ERROR);
486 }
487 else {
488 sockoptlen = sizeof(int);
489
490 ret = getsockopt(s, SOL_SOCKET, SO_ERROR,
491 (char *) &sockoptval, &sockoptlen);
492 if(sockoptval == (WSAECONNREFUSED-WSABASEERR)) {
493 AsyncNotifyEvent(pThreadParm, FD_CONNECT, WSAECONNREFUSED);
494 }
495 }
496 }
497 else
498 if(!(state & SS_CANTSENDMORE) && (lEventsPending & FD_WRITE)) {
499 AsyncNotifyEvent(pThreadParm, FD_WRITE, NO_ERROR);
500 }
501 }
502
503 if(ready(noread))
504 {
505 state = ioctl(s, FIONREAD, (CHAR *) &bytesread, sizeof(bytesread));
506 if(state == SOCKET_ERROR) {
507 if(lEventsPending & FD_CLOSE)
508 {
509 AsyncNotifyEvent(pThreadParm, FD_CLOSE, NO_ERROR);
510 //remote connection broken (so can't receive data anymore)
511 //but can still send
512 pThreadParm->u.asyncselect.lEventsPending &= ~(FD_READ | FD_ACCEPT);
513 continue;
514 }
515 else {
516 dprintf(("WSAsyncSelectThreadProc: ioctl SOCKET_ERROR!"));
517 break; //todo: correct???
518 }
519 }
520 if(lEventsPending & FD_ACCEPT)
521 {
522 sockoptlen = sizeof(sockoptlen);
523
524 ret = getsockopt(s, SOL_SOCKET, SO_OPTIONS,
525 (char *) &sockoptval, &sockoptlen);
526 if(ret == SOCKET_ERROR) {
527 dprintf(("WSAsyncSelectThreadProc: getsockopt SOCKET_ERROR!"));
528 break;
529 }
530 if((sockoptval & SO_ACCEPTCONN) == SO_ACCEPTCONN) {
531 AsyncNotifyEvent(pThreadParm, FD_ACCEPT, NO_ERROR);
532 }
533 }
534 if((lEventsPending & FD_READ) && bytesread > 0) {
535 AsyncNotifyEvent(pThreadParm, FD_READ, NO_ERROR);
536 }
537 }
538 if(ready(noexcept))
539 {
540 if(lEventsPending & FD_OOB) {
541 AsyncNotifyEvent(pThreadParm, FD_OOB, NO_ERROR);
542 }
543 }
544 if((pThreadParm->u.asyncselect.lEventsPending & (FD_ACCEPT|FD_CLOSE|FD_CONNECT)) ==
545 (lEventsPending & (FD_ACCEPT|FD_CLOSE|FD_CONNECT))) {
546 DosSleep(10);
547 }
548 }
549 delete pThreadParm->u.asyncselect.asyncSem;
550}
551//******************************************************************************
552//******************************************************************************
553ODINFUNCTION4(int,WSAAsyncSelect,
554 SOCKET,s,
555 HWND,hWnd,
556 u_int,wMsg,
557 long,lEvent)
558{
559 PASYNCTHREADPARM pThreadParm;
560 int nonblock = 1;
561 int ret;
562
563 if(!fWSAInitialized)
564 {
565 WSASetLastError(WSANOTINITIALISED);
566 return SOCKET_ERROR;
567 }
568 else
569 if(WSAIsBlocking())
570 {
571 WSASetLastError(WSAEINPROGRESS); // blocking call in progress
572 return SOCKET_ERROR;
573 }
574 else
575 if(hWnd && !IsWindow(hWnd))
576 {
577 WSASetLastError(WSAEINVAL); // invalid parameter
578 return SOCKET_ERROR;
579 }
580 //Set socket to non-blocking mode
581 ret = ioctl(s, FIONBIO, (char *) &nonblock, sizeof(nonblock));
582 if(ret == SOCKET_ERROR) {
583 WSASetLastError(wsaErrno());
584 return SOCKET_ERROR;
585 }
586 if(FindAndSetAsyncEvent(s, hWnd, wMsg, lEvent) == TRUE) {
587 //found and changed active async event
588 WSASetLastError(NO_ERROR);
589 return NO_ERROR;
590 }
591 pThreadParm = (PASYNCTHREADPARM)malloc(sizeof(ASYNCTHREADPARM));
592 if(pThreadParm == NULL) {
593 dprintf(("WSAAsyncSelect: malloc failure!"));
594 DebugInt3();
595 WSASetLastError(WSAEFAULT);
596 return SOCKET_ERROR;
597 }
598 memset(pThreadParm, 0, sizeof(*pThreadParm));
599 pThreadParm->request= ASYNC_SELECT;
600 pThreadParm->hwnd = hWnd;
601 pThreadParm->msg = wMsg;
602 pThreadParm->u.asyncselect.lEvents = lEvent;
603 pThreadParm->u.asyncselect.lEventsPending = lEvent;
604 pThreadParm->u.asyncselect.s = s;
605 pThreadParm->u.asyncselect.asyncSem = new VSemaphore;
606 if(pThreadParm->u.asyncselect.asyncSem == NULL) {
607 dprintf(("WSAAsyncSelect: VSemaphore alloc failure!"));
608 DebugInt3();
609 WSASetLastError(WSAEFAULT);
610 return SOCKET_ERROR;
611 }
612 if(QueueAsyncJob(WSAsyncSelectThreadProc, pThreadParm) == 0) {
613 delete pThreadParm->u.asyncselect.asyncSem;
614 free(pThreadParm);
615 dprintf(("WSAAsyncSelect: QueueAsyncJob failure!"));
616 DebugInt3();
617 WSASetLastError(WSAEFAULT);
618 return SOCKET_ERROR;
619 }
620 WSASetLastError(NO_ERROR);
621 return NO_ERROR;
622}
623//******************************************************************************
624//******************************************************************************
Note: See TracBrowser for help on using the repository browser.