source: trunk/src/wsock32/async.cpp@ 1460

Last change on this file since 1460 was 1460, checked in by phaller, 26 years ago

Fix: debug info

File size: 41.3 KB
Line 
1/* $Id: async.cpp,v 1.9 1999-10-26 21:43:00 phaller Exp $ */
2
3/*
4 *
5 * Project Odin Software License can be found in LICENSE.TXT
6 *
7 * Asynchronous Winsock code
8 *
9 * Copyright 1999 Patrick Haller
10 *
11 *
12 * Idea is to separate requests:
13 * - all database requests and DNS requests are handled by one thread
14 * - asynchronous selects are each handled by its own thread
15 */
16
17
18/*****************************************************************************
19 * Includes *
20 *****************************************************************************/
21
22#include <odin.h>
23#include <odinwrap.h>
24#include <os2sel.h>
25#define INCL_DOSERRORS
26#define INCL_DOSSEMAPHORES
27#include <os2.h>
28
29#include <netdb.h>
30#include <nerrno.h>
31#include <sys/socket.h>
32#include <sys/ioctl.h>
33#include <sys/select.h>
34
35#include <wsock32const.h>
36
37#include <process.h>
38#include <string.h>
39#include <stdlib.h>
40
41#include <misc.h>
42
43
44/*****************************************************************************
45 * Definitions *
46 *****************************************************************************/
47
48ODINDEBUGCHANNEL(WSOCK32-ASYNC)
49
50
51// prototype of the OS/2 select!
52int _System os2_select(int* socket,
53 int fd_read,
54 int fd_write,
55 int fd_exception,
56 long timeout);
57
58int _System bsd_select(int,
59 fd_set *,
60 fd_set *,
61 fd_set *,
62 struct timeval);
63
64
65
66/*****************************************************************************
67 * Structures *
68 *****************************************************************************/
69
70// request types
71enum tagAsyncRequestType
72{
73 WSAASYNC_TERMINATE, // internal message
74 WSAASYNC_GETHOSTBYADDR,
75 WSAASYNC_GETHOSTBYNAME,
76 WSAASYNC_GETPROTOBYNAME,
77 WSAASYNC_GETPROTOBYNUMBER,
78 WSAASYNC_GETSERVBYNAME,
79 WSAASYNC_GETSERVBYPORT,
80 WSAASYNC_SELECT
81};
82
83
84// request states
85enum tagAsyncRequestStates
86{
87 RS_WAITING, // request is waiting in queue
88 RS_BUSY, // request is currently being serviced
89 RS_CANCELLED, // request has been cancelled
90 RS_DONE
91};
92
93
94typedef struct tagAsyncRequest
95{
96 struct tagAsyncRequest* pPrev; // pointer to previous request
97 struct tagAsyncRequest* pNext; // pointer to next request
98
99 ULONG ulType; // type of request
100 ULONG ulState; // state of request
101
102 HWND hwnd; // window handle to post message to
103 ULONG ulMessage; // message to post
104
105 PVOID pBuffer; // result buffer
106 ULONG ulBufferLength; // length of the return buffer
107
108 ULONG ul1; // multi purpose parameters
109 ULONG ul2;
110 ULONG ul3;
111
112} ASYNCREQUEST, *PASYNCREQUEST;
113
114
115/*****************************************************************************
116 * Prototypes *
117 *****************************************************************************/
118
119void _Optlink WorkerThreadProc(void* pParam);
120BOOL _System PostMessageA(HWND hwnd, UINT ulMessage, WPARAM wParam, LPARAM lParam);
121
122void _System SetLastError(int iError);
123int _System GetLastError(void);
124#define WSASetLastError(a) SetLastError(a)
125
126
127/*****************************************************************************
128 * Implementation *
129 *****************************************************************************/
130
131class WSAAsyncWorker
132{
133 // protected members
134 protected:
135 PASYNCREQUEST pRequestHead; // chain root
136 PASYNCREQUEST pRequestTail; // chain root
137 TID tidWorker; // worker thread id
138 HEV hevRequest; // fired upon new request
139 HMTX hmtxRequestQueue; // request queue protection
140 BOOL fTerminate; // got to die ?
141 BOOL fBlocking; // currently busy ?
142
143 TID startWorker (void); // start worker thread
144 void processingLoop (void); // "work"
145 int dispatchRequest(PASYNCREQUEST pRequest); // complete request
146 PASYNCREQUEST popRequest (void); // get one request from queue
147 BOOL deleteRequest (PASYNCREQUEST pRequest); // remove particular request
148
149 void lockQueue (void); // enter mutex
150 void unlockQueue (void); // leave mutex
151
152 // the real worker methods
153 void asyncGetHostByAddr (PASYNCREQUEST pRequest);
154 void asyncGetHostByName (PASYNCREQUEST pRequest);
155 void asyncGetProtoByName (PASYNCREQUEST pRequest);
156 void asyncGetProtoByNumber(PASYNCREQUEST pRequest);
157 void asyncGetServByName (PASYNCREQUEST pRequest);
158 void asyncGetServByPort (PASYNCREQUEST pRequest);
159 void asyncSelect (PASYNCREQUEST pRequest);
160
161 // public members
162 public:
163 WSAAsyncWorker(void); // constructor
164 ~WSAAsyncWorker(); // destructor
165
166 PASYNCREQUEST createRequest (ULONG ulType,
167 HWND hwnd,
168 ULONG ulMessage,
169 PVOID pBuffer,
170 ULONG ulBufferLength,
171 ULONG ul1 = 0,
172 ULONG ul2 = 0,
173 ULONG ul3 = 0);
174
175 void pushRequest (PASYNCREQUEST pRequest); // put request on queue
176 BOOL cancelAsyncRequest (PASYNCREQUEST pRequest);
177 BOOL isBlocking (void) {return fBlocking;}
178
179 // the thread procedure
180 friend void _Optlink WorkerThreadProc(void* pParam);
181};
182
183
184/*****************************************************************************
185 * Local variables *
186 *****************************************************************************/
187
188//static WSAAsyncWorker* wsaWorker = NULL;
189static WSAAsyncWorker* wsaWorker = new WSAAsyncWorker();
190
191
192/*****************************************************************************
193 * Name :
194 * Purpose :
195 * Parameters:
196 * Variables :
197 * Result :
198 * Remark :
199 * Status : UNTESTED STUB
200 *
201 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
202 *****************************************************************************/
203// constructor
204WSAAsyncWorker::WSAAsyncWorker(void)
205{
206 dprintf(("WSOCK32-ASYNC: WSAAsyncWorker::WSAAsyncWorker\n"));
207
208 pRequestHead = NULL; // chain root
209 pRequestTail = NULL; // chain root
210 tidWorker = 0; // worker thread id
211 fTerminate = FALSE; // got to die ?
212
213 startWorker();
214}
215
216
217/*****************************************************************************
218 * Name :
219 * Purpose :
220 * Parameters:
221 * Variables :
222 * Result :
223 * Remark :
224 * Status : UNTESTED STUB
225 *
226 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
227 *****************************************************************************/
228// destructor
229WSAAsyncWorker::~WSAAsyncWorker(void)
230{
231 dprintf(("WSOCK32-ASYNC: WSAAsyncWorker::~WSAAsyncWorker (%08xh)\n",
232 this));
233
234 // remove all requests
235 while (popRequest() != NULL);
236
237 // just in case ... terminate worker thread
238 if (tidWorker != 0)
239 {
240 fTerminate = TRUE;
241 DosPostEventSem(hevRequest);
242 }
243
244 DosCloseEventSem(hevRequest);
245 DosCloseMutexSem(hmtxRequestQueue);
246}
247
248
249
250/*****************************************************************************
251 * Name :
252 * Purpose :
253 * Parameters:
254 * Variables :
255 * Result :
256 * Remark :
257 * Status : UNTESTED STUB
258 *
259 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
260 *****************************************************************************/
261// start worker thread if necessary
262TID WSAAsyncWorker::startWorker(void)
263{
264 APIRET rc;
265
266 dprintf(("WSOCK32-ASYNC: WSAAsyncWorker::startWorker (%08xh)\n",
267 this));
268
269 if (tidWorker == 0)
270 {
271 // create semaphores
272 rc = DosCreateEventSem(NULL, // unnamed
273 &hevRequest,
274 0, // unshared
275 FALSE); // reset
276 if (rc != NO_ERROR)
277 {
278 dprintf(("WSOCK32: WSAAsyncWorker::startWorker - DosCreateEventSem = %08xh\n",
279 rc));
280
281 return 0;
282 }
283
284 rc = DosCreateMutexSem(NULL, // unnamed
285 &hmtxRequestQueue,
286 0, // unshared
287 FALSE); // unowned
288 if (rc != NO_ERROR)
289 {
290 dprintf(("WSOCK32: WSAAsyncWorker::startWorker - DosCreateMutexSem = %08xh\n",
291 rc));
292
293 DosCloseEventSem(hevRequest);
294 return 0;
295 }
296
297 // create thread
298#if defined(__IBMCPP__)
299 tidWorker = _beginthread(WorkerThreadProc,
300 NULL,
301 16384,
302 (PVOID)this);
303#else
304 tidWorker = _beginthread(WorkerThreadProc,
305 16384,
306 (PVOID)this);
307#endif
308 if (tidWorker == -1)
309 {
310 // cancel the whole thing
311 tidWorker = 0;
312 DosCloseEventSem(hevRequest);
313 DosCloseMutexSem(hmtxRequestQueue);
314 }
315 }
316
317 return tidWorker; // thread already running
318}
319
320
321/*****************************************************************************
322 * Name :
323 * Purpose :
324 * Parameters:
325 * Variables :
326 * Result :
327 * Remark :
328 * Status : UNTESTED STUB
329 *
330 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
331 *****************************************************************************/
332// lock double-linked request chain
333void WSAAsyncWorker::lockQueue(void)
334{
335 DosRequestMutexSem(hmtxRequestQueue, SEM_INDEFINITE_WAIT);
336}
337
338
339/*****************************************************************************
340 * Name :
341 * Purpose :
342 * Parameters:
343 * Variables :
344 * Result :
345 * Remark :
346 * Status : UNTESTED STUB
347 *
348 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
349 *****************************************************************************/
350// unlock double-linked request chain
351void WSAAsyncWorker::unlockQueue(void)
352{
353 DosReleaseMutexSem(hmtxRequestQueue);
354}
355
356
357/*****************************************************************************
358 * Name :
359 * Purpose :
360 * Parameters:
361 * Variables :
362 * Result :
363 * Remark :
364 * Status : UNTESTED STUB
365 *
366 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
367 *****************************************************************************/
368// get request from queue
369PASYNCREQUEST WSAAsyncWorker::popRequest(void)
370{
371 PASYNCREQUEST pLast;
372
373 lockQueue(); // lock queue
374
375 // alter queue
376 pLast = pRequestTail;
377
378 if (pRequestTail != NULL)
379 {
380 if (pRequestTail->pPrev)
381 {
382 pRequestTail->pPrev->pNext = NULL; // cut off element
383 pRequestTail = pRequestTail->pPrev; // unlink previous element
384 }
385 else
386 {
387 // this is the last request on the queue
388 pRequestTail = NULL;
389 pRequestHead = NULL;
390 }
391 }
392
393 unlockQueue(); // unlock queue
394
395 return (pLast); // return element
396}
397
398
399/*****************************************************************************
400 * Name :
401 * Purpose :
402 * Parameters:
403 * Variables :
404 * Result :
405 * Remark :
406 * Status : UNTESTED STUB
407 *
408 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
409 *****************************************************************************/
410// insert request into queue
411void WSAAsyncWorker::pushRequest(PASYNCREQUEST pNew)
412{
413 lockQueue(); // lock queue
414
415 // alter queue
416 if (pRequestHead == NULL)
417 {
418 // first element in queue
419 pRequestHead = pNew;
420 pRequestTail = pNew;
421 pNew->pPrev = NULL;
422 pNew->pNext = NULL;
423 }
424 else
425 {
426 // chain in request
427 pNew->pPrev = NULL;
428 pNew->pNext = pRequestHead;
429 pRequestHead->pPrev = pNew;
430 pRequestHead = pNew;
431 }
432
433 // trigger thread!
434 DosPostEventSem(hevRequest);
435
436 unlockQueue(); // unlock queue
437}
438
439
440/*****************************************************************************
441 * Name :
442 * Purpose :
443 * Parameters:
444 * Variables :
445 * Result :
446 * Remark :
447 * Status : UNTESTED STUB
448 *
449 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
450 *****************************************************************************/
451// delete particular request from queue
452BOOL WSAAsyncWorker::deleteRequest(PASYNCREQUEST pDelete)
453{
454 PASYNCREQUEST pRequest; // for verification
455 BOOL bResult = FALSE;
456
457 lockQueue(); // lock queue
458
459 // find request (optional, just for verification)
460 for (pRequest = pRequestHead;
461 pRequest != NULL;
462 pRequest = pRequest->pNext)
463 if (pRequest == pDelete)
464 break;
465
466 if (pRequest == pDelete) // if request has been found
467 {
468 // is request the head of the list ?
469 if (pDelete == pRequestHead)
470 {
471 pRequestHead = pDelete->pNext;
472 if (pRequestHead == NULL) // last element ?
473 pRequestTail = NULL;
474 else
475 pRequestHead->pPrev = NULL;
476 }
477 else
478 // if request the last in the list ?
479 if (pDelete == pRequestTail)
480 {
481 pRequestTail = pDelete->pPrev;
482 if (pRequestTail == NULL) // last element ?
483 pRequestHead = NULL;
484 else
485 pRequestTail->pNext = NULL;
486 }
487 else
488 // request is somewhere in the middle of the list
489 {
490 if (pDelete->pPrev != NULL)
491 pDelete->pPrev->pNext = pDelete->pNext;
492
493 if (pDelete->pNext != NULL)
494 pDelete->pNext->pPrev = pDelete->pPrev;
495 }
496
497 delete pDelete; // free the memory
498 bResult = TRUE; // OK
499 }
500
501 unlockQueue(); // unlock queue
502 return bResult;
503}
504
505
506/*****************************************************************************
507 * Name :
508 * Purpose :
509 * Parameters:
510 * Variables :
511 * Result :
512 * Remark :
513 * Status : UNTESTED STUB
514 *
515 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
516 *****************************************************************************/
517
518BOOL WSAAsyncWorker::cancelAsyncRequest(PASYNCREQUEST pRequest)
519{
520 PASYNCREQUEST pRequestTemp;
521 BOOL rc = TRUE;
522
523 lockQueue();
524
525 // verify pRequest
526 // find request (optional, just for verification)
527 for (pRequestTemp = pRequestHead;
528 pRequestTemp != NULL;
529 pRequestTemp = pRequestTemp->pNext)
530 if (pRequestTemp == pRequest)
531 break;
532
533 // is request in queue ?
534 if (pRequestTemp == pRequest)
535 {
536 // is it busy?
537 if (pRequest->ulState != RS_BUSY)
538 {
539 // if not: set RS_CANCELLED
540 pRequest->ulState = RS_CANCELLED;
541 }
542 else
543 {
544 // if busy: ???
545 dprintf(("WSOCK32:Async: WSAAsyncWorker::cancelAsyncRequest(%08xh, %08xh) how to cancel?\n",
546 this,
547 pRequest));
548 rc = FALSE;
549 }
550 }
551 else
552 rc = FALSE;
553
554 unlockQueue();
555 return rc;
556}
557
558
559/*****************************************************************************
560 * Name :
561 * Purpose :
562 * Parameters:
563 * Variables :
564 * Result :
565 * Remark :
566 * Status : UNTESTED STUB
567 *
568 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
569 *****************************************************************************/
570
571PASYNCREQUEST WSAAsyncWorker::createRequest (ULONG ulType,
572 HWND hwnd,
573 ULONG ulMessage,
574 PVOID pBuffer,
575 ULONG ulBufferLength,
576 ULONG ul1,
577 ULONG ul2,
578 ULONG ul3)
579{
580 PASYNCREQUEST pNew = new ASYNCREQUEST();
581
582 // fill the structure
583 pNew->pPrev = NULL;
584 pNew->pNext = NULL;
585 pNew->ulType = ulType;
586 pNew->ulState = RS_WAITING;
587 pNew->hwnd = hwnd;
588 pNew->ulMessage = ulMessage;
589 pNew->pBuffer = pBuffer;
590 pNew->ulBufferLength = ulBufferLength;
591 pNew->ul1 = ul1;
592 pNew->ul2 = ul2;
593 pNew->ul3 = ul3;
594
595 return pNew;
596}
597
598
599/*****************************************************************************
600 * Name :
601 * Purpose :
602 * Parameters:
603 * Variables :
604 * Result :
605 * Remark :
606 * Status : UNTESTED STUB
607 *
608 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
609 *****************************************************************************/
610
611void WSAAsyncWorker::asyncGetHostByAddr (PASYNCREQUEST pRequest)
612{
613 struct hostent* pHostent;
614 USHORT usLength = sizeof(struct Whostent);
615 USHORT rc;
616 struct Whostent* pwhostent = (struct Whostent*)pRequest->pBuffer;
617
618 dprintf(("WSOCK32-ASYNC: WSAAsyncWorker::asyncGetHostByAddr (%08xh, %08xh)\n",
619 this,
620 pRequest));
621
622 // result buffer length
623 if (pRequest->ulBufferLength < sizeof(struct Whostent))
624 {
625 rc = WSAEINVAL;
626 WSASetLastError(rc); // same as Winsock return codes
627 }
628 else
629 {
630 // call API
631 pHostent = gethostbyaddr((char*)pRequest->ul1,
632 (int) pRequest->ul2,
633 (int) pRequest->ul3);
634 if (pHostent == NULL) // error ?
635 {
636 rc = sock_errno(); // assuming OS/2 return codes are
637 WSASetLastError(rc); // same as Winsock return codes
638 }
639 else
640 {
641 // translate result to Wsock32-style structure
642 pwhostent->h_name = pHostent->h_name;
643 pwhostent->h_aliases = pHostent->h_aliases;
644 pwhostent->h_addrtype = pHostent->h_addrtype;
645 pwhostent->h_length = pHostent->h_length;
646 pwhostent->h_addr_list = pHostent->h_addr_list;
647 rc = 0;
648 }
649 }
650
651 // post result
652 PostMessageA(pRequest->hwnd,
653 pRequest->ulMessage,
654 (WPARAM)pRequest,
655 (LPARAM)(rc << 16 | usLength));
656
657 // M$ says, if PostMessageA fails, spin as long as window exists
658}
659
660
661/*****************************************************************************
662 * Name :
663 * Purpose :
664 * Parameters:
665 * Variables :
666 * Result :
667 * Remark :
668 * Status : UNTESTED STUB
669 *
670 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
671 *****************************************************************************/
672
673void WSAAsyncWorker::asyncGetHostByName (PASYNCREQUEST pRequest)
674{
675 struct hostent* pHostent;
676 USHORT usLength = sizeof(struct Whostent);
677 USHORT rc;
678 struct Whostent* pwhostent = (struct Whostent*)pRequest->pBuffer;
679
680 dprintf(("WSOCK32-ASYNC: WSAAsyncWorker::asyncGetHostByName (%08xh, %08xh)\n",
681 this,
682 pRequest));
683
684 // result buffer length
685 if (pRequest->ulBufferLength < sizeof(struct Whostent))
686 {
687 rc = WSAEINVAL;
688 WSASetLastError(rc); // same as Winsock return codes
689 }
690 else
691 {
692 // call API
693 pHostent = gethostbyname((char*)pRequest->ul1);
694 if (pHostent == NULL) // error ?
695 {
696 rc = sock_errno(); // assuming OS/2 return codes are
697 WSASetLastError(rc); // same as Winsock return codes
698
699 dprintf ((" pHostent==NULL -> rc=%d\n", rc));
700 }
701 else
702 {
703 // translate result to Wsock32-style structure
704 pwhostent->h_name = pHostent->h_name;
705 pwhostent->h_aliases = pHostent->h_aliases;
706 pwhostent->h_addrtype = pHostent->h_addrtype;
707 pwhostent->h_length = pHostent->h_length;
708 pwhostent->h_addr_list = pHostent->h_addr_list;
709 rc = 0;
710 }
711 }
712
713 // post result
714 PostMessageA(pRequest->hwnd,
715 pRequest->ulMessage,
716 (WPARAM)pRequest,
717 (LPARAM)(rc << 16 | usLength));
718
719 // M$ says, if PostMessageA fails, spin as long as window exists
720}
721
722
723/*****************************************************************************
724 * Name :
725 * Purpose :
726 * Parameters:
727 * Variables :
728 * Result :
729 * Remark :
730 * Status : UNTESTED STUB
731 *
732 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
733 *****************************************************************************/
734
735void WSAAsyncWorker::asyncGetProtoByName (PASYNCREQUEST pRequest)
736{
737 struct protoent* pProtoent;
738 USHORT usLength = sizeof(struct Wprotoent);
739 USHORT rc;
740 struct Wprotoent* pwprotoent= (struct Wprotoent*)pRequest->pBuffer;
741
742 dprintf(("WSOCK32-ASYNC: WSAAsyncWorker::asyncGetProtoByName (%08xh, %08xh)\n",
743 this,
744 pRequest));
745
746 // result buffer length
747 if (pRequest->ulBufferLength < sizeof(struct Wprotoent))
748 {
749 rc = WSAEINVAL;
750 WSASetLastError(rc); // same as Winsock return codes
751 }
752 else
753 {
754 // call API
755 pProtoent = getprotobyname((char*)pRequest->ul1);
756 if (pProtoent == NULL) // error ?
757 {
758 rc = sock_errno(); // assuming OS/2 return codes are
759 WSASetLastError(rc); // same as Winsock return codes
760 }
761 else
762 {
763 // build result buffer
764 pwprotoent->p_name = pProtoent->p_name;
765 pwprotoent->p_aliases = pProtoent->p_aliases;
766 pwprotoent->p_proto = pProtoent->p_proto;
767 rc = 0;
768 }
769 }
770
771 // post result
772 PostMessageA(pRequest->hwnd,
773 pRequest->ulMessage,
774 (WPARAM)pRequest,
775 (LPARAM)(rc << 16 | usLength));
776
777 // M$ says, if PostMessageA fails, spin as long as window exists
778}
779
780
781/*****************************************************************************
782 * Name :
783 * Purpose :
784 * Parameters:
785 * Variables :
786 * Result :
787 * Remark :
788 * Status : UNTESTED STUB
789 *
790 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
791 *****************************************************************************/
792
793void WSAAsyncWorker::asyncGetProtoByNumber(PASYNCREQUEST pRequest)
794{
795 struct protoent* pProtoent;
796 USHORT usLength = sizeof(struct Wprotoent);
797 USHORT rc;
798 struct Wprotoent* pwprotoent= (struct Wprotoent*)pRequest->pBuffer;
799
800 dprintf(("WSOCK32-ASYNC: WSAAsyncWorker::asyncGetProtoByNumber (%08xh, %08xh)\n",
801 this,
802 pRequest));
803
804 // result buffer length
805 if (pRequest->ulBufferLength < sizeof(struct Wprotoent))
806 {
807 rc = WSAEINVAL;
808 WSASetLastError(rc); // same as Winsock return codes
809 }
810 else
811 {
812 // call API
813 pProtoent = getprotobyname(( char*)pRequest->ul1);
814 if (pProtoent == NULL) // error ?
815 {
816 rc = sock_errno(); // assuming OS/2 return codes are
817 WSASetLastError(rc); // same as Winsock return codes
818 }
819 else
820 {
821 // build result buffer
822 pwprotoent->p_name = pProtoent->p_name;
823 pwprotoent->p_aliases = pProtoent->p_aliases;
824 pwprotoent->p_proto = pProtoent->p_proto;
825 rc = 0;
826 }
827 }
828
829 // post result
830 PostMessageA(pRequest->hwnd,
831 pRequest->ulMessage,
832 (WPARAM)pRequest,
833 (LPARAM)(rc << 16 | usLength));
834
835 // M$ says, if PostMessageA fails, spin as long as window exists
836}
837
838
839/*****************************************************************************
840 * Name :
841 * Purpose :
842 * Parameters:
843 * Variables :
844 * Result :
845 * Remark :
846 * Status : UNTESTED STUB
847 *
848 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
849 *****************************************************************************/
850
851void WSAAsyncWorker::asyncGetServByName(PASYNCREQUEST pRequest)
852{
853 struct servent* pServent;
854 USHORT usLength = sizeof(struct Wservent);
855 USHORT rc;
856 struct Wservent* pwservent= (struct Wservent*)pRequest->pBuffer;
857
858 dprintf(("WSOCK32-ASYNC: WSAAsyncWorker::asyncGetServByName (%08xh, %08xh)\n",
859 this,
860 pRequest));
861
862 // result buffer length
863 if (pRequest->ulBufferLength < sizeof(struct Wservent))
864 {
865 rc = WSAEINVAL;
866 WSASetLastError(rc); // same as Winsock return codes
867 }
868 else
869 {
870 // call API
871 pServent = getservbyname((char*)pRequest->ul1,
872 (char*)pRequest->ul2);
873 if (pServent == NULL) // error ?
874 {
875 rc = sock_errno(); // assuming OS/2 return codes are
876 WSASetLastError(rc); // same as Winsock return codes
877 }
878 else
879 {
880 // build result buffer
881 pwservent->s_name = pServent->s_name;
882 pwservent->s_aliases = pServent->s_aliases;
883 pwservent->s_port = pServent->s_port;
884 pwservent->s_proto = pServent->s_proto;
885 rc = 0;
886 }
887 }
888
889 // post result
890 PostMessageA(pRequest->hwnd,
891 pRequest->ulMessage,
892 (WPARAM)pRequest,
893 (LPARAM)(rc << 16 | usLength));
894
895 // M$ says, if PostMessageA fails, spin as long as window exists
896}
897
898
899/*****************************************************************************
900 * Name :
901 * Purpose :
902 * Parameters:
903 * Variables :
904 * Result :
905 * Remark :
906 * Status : UNTESTED STUB
907 *
908 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
909 *****************************************************************************/
910
911void WSAAsyncWorker::asyncGetServByPort(PASYNCREQUEST pRequest)
912{
913 struct servent* pServent;
914 USHORT usLength = sizeof(struct Wservent);
915 USHORT rc;
916 struct Wservent* pwservent= (struct Wservent*)pRequest->pBuffer;
917
918 dprintf(("WSOCK32-ASYNC: WSAAsyncWorker::asyncGetServByPort (%08xh, %08xh)\n",
919 this,
920 pRequest));
921
922 // result buffer length
923 if (pRequest->ulBufferLength < sizeof(struct Whostent))
924 {
925 rc = WSAEINVAL;
926 WSASetLastError(rc); // same as Winsock return codes
927 }
928 else
929 {
930 // call API
931 pServent = getservbyport((int )pRequest->ul1,
932 (char*)pRequest->ul2);
933 if (pServent == NULL) // error ?
934 {
935 rc = sock_errno(); // assuming OS/2 return codes are
936 WSASetLastError(rc); // same as Winsock return codes
937 }
938 else
939 {
940 // build result buffer
941 pwservent->s_name = pServent->s_name;
942 pwservent->s_aliases = pServent->s_aliases;
943 pwservent->s_port = pServent->s_port;
944 pwservent->s_proto = pServent->s_proto;
945
946 rc = 0;
947 }
948 }
949
950 // post result
951 PostMessageA(pRequest->hwnd,
952 pRequest->ulMessage,
953 (WPARAM)pRequest,
954 (LPARAM)(rc << 16 | usLength));
955
956 // M$ says, if PostMessageA fails, spin as long as window exists
957}
958
959
960
961/*****************************************************************************
962 * Name : WSAAsyncWorker::asyncSelect
963 * Purpose :
964 * Parameters:
965 * Variables :
966 * Result :
967 * Remark :
968 * Status : UNTESTED
969 *
970 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
971 *****************************************************************************/
972
973typedef int SOCKET;
974
975void WSAAsyncWorker::asyncSelect(PASYNCREQUEST pRequest)
976{
977 ULONG wParam;
978 ULONG lParam;
979 int irc;
980 int iUnknown;
981
982 SOCKET sockWin;
983 ULONG ulEvent;
984 USHORT usResult = 0;
985
986 dprintf(("WSOCK32-ASYNC: WSAAsyncWorker::asyncSelect (%08xh, %08xh) not correctly implemented\n",
987 this,
988 pRequest));
989
990
991 // setup variables
992 sockWin = (SOCKET)pRequest->ul1;
993 ulEvent = (ULONG) pRequest->ul2;
994
995 //@@@PH how to implement other events?
996
997 // finally do the select!
998 irc = os2_select(&sockWin,
999 (ulEvent & FD_READ) ? 1 : 0,
1000 (ulEvent & FD_WRITE) ? 1 : 0,
1001 (ulEvent & FD_OOB) ? 1 : 0,
1002 10000); // @@@PH timeout
1003 if (irc < 0) /* an error occurred */
1004 {
1005 lParam = sock_errno(); /* raise error condition */
1006 if (lParam == SOCENOTSOCK)
1007 {
1008 usResult = FD_CLOSE;
1009 lParam = 0;
1010 }
1011 }
1012 else
1013 if (irc == 0) /* this means timeout */
1014 {
1015 lParam = WSAETIMEDOUT; /* raise error condition */
1016 }
1017 else
1018 {
1019 //@@@PH check the socket for any event and report!
1020 usResult = 0;
1021
1022 // readiness for reading bytes ?
1023 irc = ioctl(sockWin, FIONREAD, (char *)&iUnknown, sizeof(iUnknown));
1024 if ( (irc == 0) && (iUnknown > 0))
1025 usResult |= FD_READ;
1026 }
1027
1028 // post result
1029 PostMessageA(pRequest->hwnd,
1030 pRequest->ulMessage,
1031 (WPARAM)sockWin,
1032 (LPARAM)((lParam << 16) | usResult));
1033
1034 // M$ says, if PostMessageA fails, spin as long as window exists
1035}
1036
1037
1038
1039/*****************************************************************************
1040 * Name :
1041 * Purpose :
1042 * Parameters:
1043 * Variables :
1044 * Result :
1045 * Remark :
1046 * Status : UNTESTED STUB
1047 *
1048 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
1049 *****************************************************************************/
1050// process one request
1051int WSAAsyncWorker::dispatchRequest(PASYNCREQUEST pRequest)
1052{
1053 int rc;
1054
1055 dprintf(("WSOCK32-ASYNC: WSAAsyncWorker::dispatchRequest (%08xh, %08xh)\n",
1056 this,
1057 pRequest));
1058
1059 // check request state first
1060 switch(pRequest->ulState)
1061 {
1062 case RS_WAITING: // OK, proceed
1063 break;
1064
1065 case RS_BUSY: // oops, shouldn't happen
1066 dprintf(("WSOCK32: WSAAsyncWorker::dispatchRequest - got already busy request %08xh\n",
1067 pRequest));
1068 return 1;
1069
1070 case RS_CANCELLED: // don't service request
1071 // request has been removed from queue already
1072 return 1;
1073 }
1074
1075 // OK, servicing request
1076 pRequest->ulState = RS_BUSY;
1077 fBlocking = TRUE;
1078
1079 switch(pRequest->ulType)
1080 {
1081 case WSAASYNC_TERMINATE: // internal message
1082 fTerminate = TRUE;
1083 return 1;
1084
1085 case WSAASYNC_GETHOSTBYADDR: asyncGetHostByAddr (pRequest); rc = 1; break;
1086 case WSAASYNC_GETHOSTBYNAME: asyncGetHostByName (pRequest); rc = 1; break;
1087 case WSAASYNC_GETPROTOBYNAME: asyncGetProtoByName (pRequest); rc = 1; break;
1088 case WSAASYNC_GETPROTOBYNUMBER: asyncGetProtoByNumber(pRequest); rc = 1; break;
1089 case WSAASYNC_GETSERVBYNAME: asyncGetServByName (pRequest); rc = 1; break;
1090 case WSAASYNC_GETSERVBYPORT: asyncGetServByPort (pRequest); rc = 1; break;
1091 case WSAASYNC_SELECT: asyncSelect (pRequest); rc = 1; break;
1092
1093 default:
1094 dprintf(("WSOCK32: WSAAsyncWorker::dispatchRequest - invalid request type %d\n",
1095 pRequest->ulType));
1096 rc = 1; break;
1097 }
1098
1099 pRequest->ulState = RS_DONE;
1100 fBlocking = FALSE;
1101 return rc;
1102}
1103
1104
1105/*****************************************************************************
1106 * Name :
1107 * Purpose :
1108 * Parameters:
1109 * Variables :
1110 * Result :
1111 * Remark :
1112 * Status : UNTESTED STUB
1113 *
1114 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
1115 *****************************************************************************/
1116// process all requests in queue until termination
1117void WSAAsyncWorker::processingLoop(void)
1118{
1119 PASYNCREQUEST pRequest;
1120 APIRET rc;
1121 ULONG ulPostCount;
1122
1123 do
1124 {
1125 // work as long as there are requests
1126 do
1127 {
1128 pRequest = popRequest(); // get request from queue
1129 if (pRequest != NULL)
1130 {
1131 dispatchRequest(pRequest); // process request
1132 delete pRequest; // free the memory
1133 }
1134 }
1135 while (pRequest != NULL);
1136
1137 // wait for semaphore
1138 rc = DosWaitEventSem(hevRequest, SEM_INDEFINITE_WAIT);
1139 rc = DosResetEventSem(hevRequest, &ulPostCount);
1140 }
1141 while (fTerminate == FALSE);
1142
1143 tidWorker = 0; // clear worker thread id
1144}
1145
1146
1147/*****************************************************************************
1148 * Name :
1149 * Purpose :
1150 * Parameters:
1151 * Variables :
1152 * Result :
1153 * Remark :
1154 * Status : UNTESTED STUB
1155 *
1156 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
1157 *****************************************************************************/
1158// thread procedure
1159void _Optlink WorkerThreadProc(void* pParam)
1160{
1161 // convert object pointer
1162 WSAAsyncWorker* pWSAAsyncWorker = (WSAAsyncWorker*)pParam;
1163 pWSAAsyncWorker->processingLoop(); // processing loop
1164}
1165
1166
1167/*****************************************************************************
1168 * Name :
1169 * Purpose :
1170 * Parameters:
1171 * Variables :
1172 * Result :
1173 * Remark :
1174 * Status : UNTESTED STUB
1175 *
1176 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
1177 *****************************************************************************/
1178// the real function calls
1179ODINFUNCTION5(HANDLE, WSAAsyncGetHostByName, HWND, hwnd,
1180 unsigned int, wMsg,
1181 const char*, name,
1182 char*, buf,
1183 int, buflen)
1184{
1185 dprintf(("name = %s\n", name));
1186 PASYNCREQUEST pRequest = wsaWorker->createRequest(WSAASYNC_GETHOSTBYNAME,
1187 (HWND) hwnd,
1188 (ULONG)wMsg,
1189 (PVOID)buf,
1190 (ULONG)buflen,
1191 (ULONG)name);
1192 wsaWorker->pushRequest(pRequest);
1193 return (HANDLE)pRequest;
1194}
1195
1196
1197/*****************************************************************************
1198 * Name :
1199 * Purpose :
1200 * Parameters:
1201 * Variables :
1202 * Result :
1203 * Remark :
1204 * Status : UNTESTED STUB
1205 *
1206 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
1207 *****************************************************************************/
1208// the real function calls
1209ODINFUNCTION7(HANDLE, WSAAsyncGetHostByAddr, HWND, hwnd,
1210 unsigned int, wMsg,
1211 const char*, addr,
1212 int, len,
1213 int, type,
1214 char*, buf,
1215 int, buflen)
1216{
1217 PASYNCREQUEST pRequest = wsaWorker->createRequest(WSAASYNC_GETHOSTBYADDR,
1218 (HWND) hwnd,
1219 (ULONG)wMsg,
1220 (PVOID)buf,
1221 (ULONG)buflen,
1222 (ULONG)addr,
1223 (ULONG)len,
1224 (ULONG)type);
1225 wsaWorker->pushRequest(pRequest);
1226 return (HANDLE)pRequest;
1227}
1228
1229
1230/*****************************************************************************
1231 * Name :
1232 * Purpose :
1233 * Parameters:
1234 * Variables :
1235 * Result :
1236 * Remark :
1237 * Status : UNTESTED STUB
1238 *
1239 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
1240 *****************************************************************************/
1241// the real function calls
1242ODINFUNCTION6(HANDLE, WSAAsyncGetServByName, HWND, hwnd,
1243 unsigned int, wMsg,
1244 const char*, name,
1245 const char*, proto,
1246 char*, buf,
1247 int, buflen)
1248{
1249 dprintf(("name = %s, proto = %s\n", name, proto));
1250 PASYNCREQUEST pRequest = wsaWorker->createRequest(WSAASYNC_GETSERVBYNAME,
1251 (HWND) hwnd,
1252 (ULONG)wMsg,
1253 (PVOID)buf,
1254 (ULONG)buflen,
1255 (ULONG)name,
1256 (ULONG)proto);
1257 wsaWorker->pushRequest(pRequest);
1258 return (HANDLE)pRequest;
1259}
1260
1261
1262/*****************************************************************************
1263 * Name :
1264 * Purpose :
1265 * Parameters:
1266 * Variables :
1267 * Result :
1268 * Remark :
1269 * Status : UNTESTED STUB
1270 *
1271 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
1272 *****************************************************************************/
1273// the real function calls
1274ODINFUNCTION6(HANDLE, WSAAsyncGetServByPort, HWND, hwnd,
1275 unsigned int, wMsg,
1276 int, port,
1277 const char*, proto,
1278 char*, buf,
1279 int, buflen)
1280{
1281 dprintf(("proto = %s\n", proto));
1282 PASYNCREQUEST pRequest = wsaWorker->createRequest(WSAASYNC_GETSERVBYPORT,
1283 (HWND) hwnd,
1284 (ULONG)wMsg,
1285 (PVOID)buf,
1286 (ULONG)buflen,
1287 (ULONG)port,
1288 (ULONG)proto);
1289 wsaWorker->pushRequest(pRequest);
1290 return (HANDLE)pRequest;
1291}
1292
1293
1294/*****************************************************************************
1295 * Name :
1296 * Purpose :
1297 * Parameters:
1298 * Variables :
1299 * Result :
1300 * Remark :
1301 * Status : UNTESTED STUB
1302 *
1303 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
1304 *****************************************************************************/
1305// the real function calls
1306ODINFUNCTION5(HANDLE, WSAAsyncGetProtoByName, HWND, hwnd,
1307 unsigned int, wMsg,
1308 const char*, name,
1309 char*, buf,
1310 int, buflen)
1311{
1312 dprintf(("name = %s\n", name));
1313 PASYNCREQUEST pRequest = wsaWorker->createRequest(WSAASYNC_GETPROTOBYNAME,
1314 (HWND) hwnd,
1315 (ULONG)wMsg,
1316 (PVOID)buf,
1317 (ULONG)buflen,
1318 (ULONG)name);
1319 wsaWorker->pushRequest(pRequest);
1320 return (HANDLE)pRequest;
1321}
1322
1323
1324/*****************************************************************************
1325 * Name :
1326 * Purpose :
1327 * Parameters:
1328 * Variables :
1329 * Result :
1330 * Remark :
1331 * Status : UNTESTED STUB
1332 *
1333 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
1334 *****************************************************************************/
1335// the real function calls
1336ODINFUNCTION5(HANDLE, WSAAsyncGetProtoByNumber, HWND, hwnd,
1337 unsigned int, wMsg,
1338 int, number,
1339 char*, buf,
1340 int, buflen)
1341{
1342 PASYNCREQUEST pRequest = wsaWorker->createRequest(WSAASYNC_GETPROTOBYNUMBER,
1343 (HWND) hwnd,
1344 (ULONG)wMsg,
1345 (PVOID)buf,
1346 (ULONG)buflen,
1347 (ULONG)number);
1348 wsaWorker->pushRequest(pRequest);
1349 return (HANDLE)pRequest;
1350}
1351
1352
1353/*****************************************************************************
1354 * Name :
1355 * Purpose : cancel a queued or busy request
1356 * Parameters:
1357 * Variables :
1358 * Result :
1359 * Remark :
1360 * Status : UNTESTED STUB
1361 *
1362 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
1363 *****************************************************************************/
1364
1365ODINFUNCTION1(int, WSACancelAsyncRequest, HANDLE, hAsyncTaskHandle)
1366{
1367 PASYNCREQUEST pRequest = (PASYNCREQUEST)hAsyncTaskHandle;
1368 BOOL rc;
1369
1370 // remove request from queue
1371 rc = wsaWorker->cancelAsyncRequest(pRequest);
1372 if (rc == TRUE)
1373 return 0; // success
1374 else
1375 {
1376 WSASetLastError(WSAEINVAL);
1377 return (SOCKET_ERROR);
1378 }
1379}
1380
1381
1382/*****************************************************************************
1383 * Name : WSAIsBlocking
1384 * Purpose :
1385 * Parameters:
1386 * Variables :
1387 * Result :
1388 * Remark :
1389 * Status : UNTESTED STUB
1390 *
1391 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
1392 *****************************************************************************/
1393
1394ODINFUNCTION0(BOOL, WSAIsBlocking)
1395{
1396 return(wsaWorker->isBlocking());
1397}
1398
1399
1400/*****************************************************************************
1401 * Name :
1402 * Purpose :
1403 * Parameters:
1404 * Variables :
1405 * Result :
1406 * Remark :
1407 * Status : UNTESTED STUB
1408 *
1409 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
1410 *****************************************************************************/
1411// the real function calls
1412ODINFUNCTION4(HANDLE, WSAAsyncSelect,SOCKET, s,
1413 HWND, hwnd,
1414 unsigned int, wMsg,
1415 long, lEvent)
1416{
1417 PASYNCREQUEST pRequest = wsaWorker->createRequest(WSAASYNC_SELECT,
1418 (HWND) hwnd,
1419 (ULONG)wMsg,
1420 (PVOID)NULL,
1421 (ULONG)0,
1422 (ULONG)s,
1423 (ULONG)lEvent);
1424 wsaWorker->pushRequest(pRequest);
1425 return (HANDLE)pRequest;
1426}
1427
Note: See TracBrowser for help on using the repository browser.