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

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

Fix: WSA async rewrite

File size: 33.9 KB
Line 
1/* $Id: async.cpp,v 1.2 1999-10-20 10:03:52 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 <wsock32const.h>
33
34#include <process.h>
35#include <string.h>
36#include <stdlib.h>
37
38#include <misc.h>
39
40
41/*****************************************************************************
42 * Definitions *
43 *****************************************************************************/
44
45ODINDEBUGCHANNEL(WSOCK32-ASYNC)
46
47
48
49/*****************************************************************************
50 * Structures *
51 *****************************************************************************/
52
53// request types
54enum tagAsyncRequestType
55{
56 WSAASYNC_TERMINATE, // internal message
57 WSAASYNC_GETHOSTBYADDR,
58 WSAASYNC_GETHOSTBYNAME,
59 WSAASYNC_GETPROTOBYNAME,
60 WSAASYNC_GETPROTOBYNUMBER,
61 WSAASYNC_GETSERVBYNAME,
62 WSAASYNC_GETSERVBYPORT,
63 WSAASYNC_SELECT
64};
65
66
67// request states
68enum tagAsyncRequestStates
69{
70 RS_WAITING, // request is waiting in queue
71 RS_BUSY, // request is currently being serviced
72 RS_CANCELLED, // request has been cancelled
73 RS_DONE
74};
75
76
77typedef struct tagAsyncRequest
78{
79 struct tagAsyncRequest* pPrev; // pointer to previous request
80 struct tagAsyncRequest* pNext; // pointer to next request
81
82 ULONG ulType; // type of request
83 ULONG ulState; // state of request
84
85 HWND hwnd; // window handle to post message to
86 ULONG ulMessage; // message to post
87
88 PVOID pBuffer; // result buffer
89 ULONG ulBufferLength; // length of the return buffer
90
91 ULONG ul1; // multi purpose parameters
92 ULONG ul2;
93 ULONG ul3;
94
95} ASYNCREQUEST, *PASYNCREQUEST;
96
97
98/*****************************************************************************
99 * Prototypes *
100 *****************************************************************************/
101
102void _Optlink WorkerThreadProc(void* pParam);
103BOOL _System PostMessageA(HWND hwnd, UINT ulMessage, WPARAM wParam, LPARAM lParam);
104
105void _System SetLastError(int iError);
106int _System GetLastError(void);
107#define WSASetLastError(a) SetLastError(a)
108
109
110/*****************************************************************************
111 * Implementation *
112 *****************************************************************************/
113
114class WSAAsyncWorker
115{
116 // public members
117 public:
118 WSAAsyncWorker(void); // constructor
119 ~WSAAsyncWorker(); // destructor
120
121 PASYNCREQUEST createRequest (ULONG ulType,
122 HWND hwnd,
123 ULONG ulMessage,
124 PVOID pBuffer,
125 ULONG ulBufferLength,
126 ULONG ul1 = 0,
127 ULONG ul2 = 0,
128 ULONG ul3 = 0);
129
130 void pushRequest (PASYNCREQUEST pRequest); // put request on queue
131 BOOL deleteRequest (PASYNCREQUEST pRequest); // remove particular request
132
133 // the thread procedure
134 friend void _Optlink WorkerThreadProc(void* pParam);
135
136
137 // protected members
138 protected:
139 PASYNCREQUEST pRequestHead; // chain root
140 PASYNCREQUEST pRequestTail; // chain root
141 TID tidWorker; // worker thread id
142 HEV hevRequest; // fired upon new request
143 HMTX hmtxRequestQueue; // request queue protection
144 BOOL fTerminate; // got to die ?
145
146 TID startWorker (void); // start worker thread
147 void processingLoop (void); // "work"
148 int dispatchRequest(PASYNCREQUEST pRequest); // complete request
149 PASYNCREQUEST popRequest (void); // get one request from queue
150
151 void lockQueue (void); // enter mutex
152 void unlockQueue (void); // leave mutex
153
154 // the real worker methods
155 void asyncGetHostByAddr (PASYNCREQUEST pRequest);
156 void asyncGetHostByName (PASYNCREQUEST pRequest);
157 void asyncGetProtoByName (PASYNCREQUEST pRequest);
158 void asyncGetProtoByNumber(PASYNCREQUEST pRequest);
159 void asyncGetServByName (PASYNCREQUEST pRequest);
160 void asyncGetServByPort (PASYNCREQUEST pRequest);
161};
162
163
164/*****************************************************************************
165 * Local variables *
166 *****************************************************************************/
167
168static WSAAsyncWorker* wsaWorker = NULL;
169
170
171/*****************************************************************************
172 * Name :
173 * Purpose :
174 * Parameters:
175 * Variables :
176 * Result :
177 * Remark :
178 * Status : UNTESTED STUB
179 *
180 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
181 *****************************************************************************/
182// constructor
183WSAAsyncWorker::WSAAsyncWorker(void)
184{
185 dprintf(("WSOCK32-ASYNC: WSAAsyncWorker::WSAAsyncWorker\n"));
186
187 pRequestHead = NULL; // chain root
188 pRequestTail = NULL; // chain root
189 tidWorker = 0; // worker thread id
190 fTerminate = FALSE; // got to die ?
191
192 startWorker();
193}
194
195
196/*****************************************************************************
197 * Name :
198 * Purpose :
199 * Parameters:
200 * Variables :
201 * Result :
202 * Remark :
203 * Status : UNTESTED STUB
204 *
205 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
206 *****************************************************************************/
207// destructor
208WSAAsyncWorker::~WSAAsyncWorker(void)
209{
210 dprintf(("WSOCK32-ASYNC: WSAAsyncWorker::~WSAAsyncWorker (%08xh)\n",
211 this));
212
213 // remove all requests
214 while (popRequest() != NULL);
215
216 // just in case ... terminate worker thread
217 if (tidWorker != 0)
218 {
219 fTerminate = TRUE;
220 DosPostEventSem(hevRequest);
221 }
222
223 DosCloseEventSem(hevRequest);
224 DosCloseMutexSem(hmtxRequestQueue);
225}
226
227
228
229/*****************************************************************************
230 * Name :
231 * Purpose :
232 * Parameters:
233 * Variables :
234 * Result :
235 * Remark :
236 * Status : UNTESTED STUB
237 *
238 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
239 *****************************************************************************/
240// start worker thread if necessary
241TID WSAAsyncWorker::startWorker(void)
242{
243 APIRET rc;
244
245 dprintf(("WSOCK32-ASYNC: WSAAsyncWorker::startWorker (%08xh)\n",
246 this));
247
248 if (tidWorker == 0)
249 {
250 // create semaphores
251 rc = DosCreateEventSem(NULL, // unnamed
252 &hevRequest,
253 0, // unshared
254 FALSE); // reset
255 if (rc != NO_ERROR)
256 {
257 dprintf(("WSOCK32: WSAAsyncWorker::startWorker - DosCreateEventSem = %08xh\n",
258 rc));
259
260 return 0;
261 }
262
263 rc = DosCreateMutexSem(NULL, // unnamed
264 &hmtxRequestQueue,
265 0, // unshared
266 FALSE); // unowned
267 if (rc != NO_ERROR)
268 {
269 dprintf(("WSOCK32: WSAAsyncWorker::startWorker - DosCreateMutexSem = %08xh\n",
270 rc));
271
272 DosCloseEventSem(hevRequest);
273 return 0;
274 }
275
276 // create thread
277#if defined(__IBMCPP__)
278 tidWorker = _beginthread(WorkerThreadProc,
279 (PVOID)this,
280 4096,
281 NULL);
282#else
283 tidWorker = _beginthread(WorkerThreadProc,
284 (PVOID)this,
285 4096);
286#endif
287 if (tidWorker == -1)
288 {
289 // cancel the whole thing
290 tidWorker = 0;
291 DosCloseEventSem(hevRequest);
292 DosCloseMutexSem(hmtxRequestQueue);
293 }
294 }
295
296 return tidWorker; // thread already running
297}
298
299
300/*****************************************************************************
301 * Name :
302 * Purpose :
303 * Parameters:
304 * Variables :
305 * Result :
306 * Remark :
307 * Status : UNTESTED STUB
308 *
309 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
310 *****************************************************************************/
311// lock double-linked request chain
312void WSAAsyncWorker::lockQueue(void)
313{
314 DosRequestMutexSem(hmtxRequestQueue, SEM_INDEFINITE_WAIT);
315}
316
317
318/*****************************************************************************
319 * Name :
320 * Purpose :
321 * Parameters:
322 * Variables :
323 * Result :
324 * Remark :
325 * Status : UNTESTED STUB
326 *
327 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
328 *****************************************************************************/
329// unlock double-linked request chain
330void WSAAsyncWorker::unlockQueue(void)
331{
332 DosReleaseMutexSem(hmtxRequestQueue);
333}
334
335
336/*****************************************************************************
337 * Name :
338 * Purpose :
339 * Parameters:
340 * Variables :
341 * Result :
342 * Remark :
343 * Status : UNTESTED STUB
344 *
345 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
346 *****************************************************************************/
347// get request from queue
348PASYNCREQUEST WSAAsyncWorker::popRequest(void)
349{
350 PASYNCREQUEST pLast;
351
352 lockQueue(); // lock queue
353
354 // alter queue
355 pLast = pRequestTail;
356
357 if (pRequestTail != NULL)
358 if (pRequestTail->pPrev)
359 {
360 pRequestTail->pPrev->pNext = NULL; // cut off element
361 pRequestTail = pRequestTail->pPrev; // unlink previous element
362 }
363
364 unlockQueue(); // unlock queue
365
366 return (pLast); // return element
367}
368
369
370/*****************************************************************************
371 * Name :
372 * Purpose :
373 * Parameters:
374 * Variables :
375 * Result :
376 * Remark :
377 * Status : UNTESTED STUB
378 *
379 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
380 *****************************************************************************/
381// insert request into queue
382void WSAAsyncWorker::pushRequest(PASYNCREQUEST pNew)
383{
384 lockQueue(); // lock queue
385
386 // alter queue
387 if (pRequestHead == NULL)
388 {
389 // first element in queue
390 pRequestHead = pNew;
391 pRequestTail = pNew;
392 pNew->pPrev = NULL;
393 pNew->pNext = NULL;
394 }
395 else
396 {
397 // chain in request
398 pNew->pPrev = NULL;
399 pNew->pNext = pRequestHead;
400 pRequestHead->pPrev = pNew;
401 pRequestHead = pNew;
402 }
403
404 // trigger thread!
405 DosPostEventSem(hevRequest);
406
407 unlockQueue(); // unlock queue
408}
409
410
411/*****************************************************************************
412 * Name :
413 * Purpose :
414 * Parameters:
415 * Variables :
416 * Result :
417 * Remark :
418 * Status : UNTESTED STUB
419 *
420 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
421 *****************************************************************************/
422// delete particular request from queue
423BOOL WSAAsyncWorker::deleteRequest(PASYNCREQUEST pDelete)
424{
425 PASYNCREQUEST pRequest; // for verification
426 BOOL bResult = FALSE;
427
428 lockQueue(); // lock queue
429
430 // find request (optional, just for verification)
431 for (pRequest = pRequestHead;
432 pRequest != NULL;
433 pRequest = pRequest->pNext)
434 if (pRequest == pDelete)
435 break;
436
437 if (pRequest == pDelete) // if request has been found
438 {
439 // is request the head of the list ?
440 if (pDelete == pRequestHead)
441 {
442 pRequestHead = pDelete->pNext;
443 if (pRequestHead == NULL) // last element ?
444 pRequestTail = NULL;
445 else
446 pRequestHead->pPrev = NULL;
447 }
448 else
449 // if request the last in the list ?
450 if (pDelete == pRequestTail)
451 {
452 pRequestTail = pDelete->pPrev;
453 if (pRequestTail == NULL) // last element ?
454 pRequestHead = NULL;
455 else
456 pRequestTail->pNext = NULL;
457 }
458 else
459 // request is somewhere in the middle of the list
460 {
461 if (pDelete->pPrev != NULL)
462 pDelete->pPrev->pNext = pDelete->pNext;
463
464 if (pDelete->pNext != NULL)
465 pDelete->pNext->pPrev = pDelete->pPrev;
466 }
467
468 delete pDelete; // free the memory
469 bResult = TRUE; // OK
470 }
471
472 unlockQueue(); // unlock queue
473 return bResult;
474}
475
476
477/*****************************************************************************
478 * Name :
479 * Purpose :
480 * Parameters:
481 * Variables :
482 * Result :
483 * Remark :
484 * Status : UNTESTED STUB
485 *
486 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
487 *****************************************************************************/
488
489PASYNCREQUEST WSAAsyncWorker::createRequest (ULONG ulType,
490 HWND hwnd,
491 ULONG ulMessage,
492 PVOID pBuffer,
493 ULONG ulBufferLength,
494 ULONG ul1,
495 ULONG ul2,
496 ULONG ul3)
497{
498 PASYNCREQUEST pNew = new ASYNCREQUEST();
499
500 // fill the structure
501 pNew->pPrev = NULL;
502 pNew->pNext = NULL;
503 pNew->ulType = ulType;
504 pNew->ulState = RS_WAITING;
505 pNew->hwnd = hwnd;
506 pNew->ulMessage = ulMessage;
507 pNew->pBuffer = pBuffer;
508 pNew->ulBufferLength = ulBufferLength;
509 pNew->ul1 = ul1;
510 pNew->ul2 = ul2;
511 pNew->ul3 = ul3;
512
513 return pNew;
514}
515
516
517/*****************************************************************************
518 * Name :
519 * Purpose :
520 * Parameters:
521 * Variables :
522 * Result :
523 * Remark :
524 * Status : UNTESTED STUB
525 *
526 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
527 *****************************************************************************/
528
529void WSAAsyncWorker::asyncGetHostByAddr (PASYNCREQUEST pRequest)
530{
531 struct hostent* pHostent;
532 USHORT usLength;
533 ULONG wParam;
534 ULONG lParam;
535 USHORT rc;
536
537 dprintf(("WSOCK32-ASYNC: WSAAsyncWorker::asyncGetHostByAddr (%08xh, %08xh)\n",
538 this,
539 pRequest));
540
541 // result buffer length
542 usLength = min(pRequest->ulBufferLength, sizeof(struct hostent));
543
544 // call API
545 pHostent = gethostbyaddr((const char*)pRequest->ul1,
546 (int) pRequest->ul2,
547 (int) pRequest->ul3);
548 if (pHostent == NULL) // error ?
549 {
550 rc = sock_errno(); // assuming OS/2 return codes are
551 WSASetLastError(rc); // same as Winsock return codes
552 }
553 else
554 {
555 // build result buffer
556 memcpy (pRequest->pBuffer,
557 pHostent,
558 usLength);
559 rc = 0;
560 }
561
562 // post result
563 PostMessageA(pRequest->hwnd,
564 pRequest->ulMessage,
565 (WPARAM)pRequest,
566 (LPARAM)(rc << 16 | usLength));
567
568 // M$ says, if PostMessageA fails, spin as long as window exists
569}
570
571
572/*****************************************************************************
573 * Name :
574 * Purpose :
575 * Parameters:
576 * Variables :
577 * Result :
578 * Remark :
579 * Status : UNTESTED STUB
580 *
581 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
582 *****************************************************************************/
583
584void WSAAsyncWorker::asyncGetHostByName (PASYNCREQUEST pRequest)
585{
586 struct hostent* pHostent;
587 USHORT usLength;
588 ULONG wParam;
589 ULONG lParam;
590 USHORT rc;
591
592 dprintf(("WSOCK32-ASYNC: WSAAsyncWorker::asyncGetHostByName (%08xh, %08xh)\n",
593 this,
594 pRequest));
595
596 // result buffer length
597 usLength = min(pRequest->ulBufferLength, sizeof(struct hostent));
598
599 // call API
600 pHostent = gethostbyname((const char*)pRequest->ul1);
601 if (pHostent == NULL) // error ?
602 {
603 rc = sock_errno(); // assuming OS/2 return codes are
604 WSASetLastError(rc); // same as Winsock return codes
605 }
606 else
607 {
608 // build result buffer
609 memcpy (pRequest->pBuffer,
610 pHostent,
611 usLength);
612 rc = 0;
613 }
614
615 // post result
616 PostMessageA(pRequest->hwnd,
617 pRequest->ulMessage,
618 (WPARAM)pRequest,
619 (LPARAM)(rc << 16 | usLength));
620
621 // M$ says, if PostMessageA fails, spin as long as window exists
622}
623
624
625/*****************************************************************************
626 * Name :
627 * Purpose :
628 * Parameters:
629 * Variables :
630 * Result :
631 * Remark :
632 * Status : UNTESTED STUB
633 *
634 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
635 *****************************************************************************/
636
637void WSAAsyncWorker::asyncGetProtoByName (PASYNCREQUEST pRequest)
638{
639 struct protoent* pProtoent;
640 USHORT usLength;
641 ULONG wParam;
642 ULONG lParam;
643 USHORT rc;
644
645 dprintf(("WSOCK32-ASYNC: WSAAsyncWorker::asyncGetProtoByName (%08xh, %08xh)\n",
646 this,
647 pRequest));
648
649 // result buffer length
650 usLength = min(pRequest->ulBufferLength, sizeof(struct protoent));
651
652 // call API
653 pProtoent = getprotobyname((const char*)pRequest->ul1);
654 if (pProtoent == NULL) // error ?
655 {
656 rc = sock_errno(); // assuming OS/2 return codes are
657 WSASetLastError(rc); // same as Winsock return codes
658 }
659 else
660 {
661 // build result buffer
662 memcpy (pRequest->pBuffer,
663 pProtoent,
664 usLength);
665 rc = 0;
666 }
667
668 // post result
669 PostMessageA(pRequest->hwnd,
670 pRequest->ulMessage,
671 (WPARAM)pRequest,
672 (LPARAM)(rc << 16 | usLength));
673
674 // M$ says, if PostMessageA fails, spin as long as window exists
675}
676
677
678/*****************************************************************************
679 * Name :
680 * Purpose :
681 * Parameters:
682 * Variables :
683 * Result :
684 * Remark :
685 * Status : UNTESTED STUB
686 *
687 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
688 *****************************************************************************/
689
690void WSAAsyncWorker::asyncGetProtoByNumber(PASYNCREQUEST pRequest)
691{
692 struct protoent* pProtoent;
693 USHORT usLength;
694 ULONG wParam;
695 ULONG lParam;
696 USHORT rc;
697
698 dprintf(("WSOCK32-ASYNC: WSAAsyncWorker::asyncGetProtoByNumber (%08xh, %08xh)\n",
699 this,
700 pRequest));
701
702 // result buffer length
703 usLength = min(pRequest->ulBufferLength, sizeof(struct protoent));
704
705 // call API
706 pProtoent = getprotobyname((const char*)pRequest->ul1);
707 if (pProtoent == NULL) // error ?
708 {
709 rc = sock_errno(); // assuming OS/2 return codes are
710 WSASetLastError(rc); // same as Winsock return codes
711 }
712 else
713 {
714 // build result buffer
715 memcpy (pRequest->pBuffer,
716 pProtoent,
717 usLength);
718 rc = 0;
719 }
720
721 // post result
722 PostMessageA(pRequest->hwnd,
723 pRequest->ulMessage,
724 (WPARAM)pRequest,
725 (LPARAM)(rc << 16 | usLength));
726
727 // M$ says, if PostMessageA fails, spin as long as window exists
728}
729
730
731/*****************************************************************************
732 * Name :
733 * Purpose :
734 * Parameters:
735 * Variables :
736 * Result :
737 * Remark :
738 * Status : UNTESTED STUB
739 *
740 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
741 *****************************************************************************/
742
743void WSAAsyncWorker::asyncGetServByName(PASYNCREQUEST pRequest)
744{
745 struct servent* pServent;
746 USHORT usLength;
747 ULONG wParam;
748 ULONG lParam;
749 USHORT rc;
750
751 dprintf(("WSOCK32-ASYNC: WSAAsyncWorker::asyncGetServByName (%08xh, %08xh)\n",
752 this,
753 pRequest));
754
755 // result buffer length
756 usLength = min(pRequest->ulBufferLength, sizeof(struct servent));
757
758 // call API
759 pServent = getservbyname((const char*)pRequest->ul1,
760 (const char*)pRequest->ul2);
761 if (pServent == NULL) // error ?
762 {
763 rc = sock_errno(); // assuming OS/2 return codes are
764 WSASetLastError(rc); // same as Winsock return codes
765 }
766 else
767 {
768 // build result buffer
769 memcpy (pRequest->pBuffer,
770 pServent,
771 usLength);
772 rc = 0;
773 }
774
775 // post result
776 PostMessageA(pRequest->hwnd,
777 pRequest->ulMessage,
778 (WPARAM)pRequest,
779 (LPARAM)(rc << 16 | usLength));
780
781 // M$ says, if PostMessageA fails, spin as long as window exists
782}
783
784
785/*****************************************************************************
786 * Name :
787 * Purpose :
788 * Parameters:
789 * Variables :
790 * Result :
791 * Remark :
792 * Status : UNTESTED STUB
793 *
794 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
795 *****************************************************************************/
796
797void WSAAsyncWorker::asyncGetServByPort(PASYNCREQUEST pRequest)
798{
799 struct servent* pServent;
800 USHORT usLength;
801 ULONG wParam;
802 ULONG lParam;
803 USHORT rc;
804
805 dprintf(("WSOCK32-ASYNC: WSAAsyncWorker::asyncGetServByPort (%08xh, %08xh)\n",
806 this,
807 pRequest));
808
809 // result buffer length
810 usLength = min(pRequest->ulBufferLength, sizeof(struct servent));
811
812 // call API
813 pServent = getservbyport((int )pRequest->ul1,
814 (const char*)pRequest->ul2);
815 if (pServent == NULL) // error ?
816 {
817 rc = sock_errno(); // assuming OS/2 return codes are
818 WSASetLastError(rc); // same as Winsock return codes
819 }
820 else
821 {
822 // build result buffer
823 memcpy (pRequest->pBuffer,
824 pServent,
825 usLength);
826 rc = 0;
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// process one request
851int WSAAsyncWorker::dispatchRequest(PASYNCREQUEST pRequest)
852{
853 dprintf(("WSOCK32-ASYNC: WSAAsyncWorker::dispatchRequest (%08xh, %08xh)\n",
854 this,
855 pRequest));
856
857 // check request state first
858 switch(pRequest->ulState)
859 {
860 case RS_WAITING: // OK, proceed
861 break;
862
863 case RS_BUSY: // oops, shouldn't happen
864 dprintf(("WSOCK32: WSAAsyncWorker::dispatchRequest - got already busy request %08xh\n",
865 pRequest));
866 return 1;
867
868 case RS_CANCELLED: // don't service request
869 // request has been removed from queue already
870 return 1;
871 }
872
873 // OK, servicing request
874 pRequest->ulState = RS_BUSY;
875
876 switch(pRequest->ulType)
877 {
878 case WSAASYNC_TERMINATE: // internal message
879 fTerminate = TRUE;
880 return 1;
881
882 case WSAASYNC_GETHOSTBYADDR: asyncGetHostByAddr (pRequest); return 1;
883 case WSAASYNC_GETHOSTBYNAME: asyncGetHostByName (pRequest); return 1;
884 case WSAASYNC_GETPROTOBYNAME: asyncGetProtoByName (pRequest); return 1;
885 case WSAASYNC_GETPROTOBYNUMBER: asyncGetProtoByNumber(pRequest); return 1;
886 case WSAASYNC_GETSERVBYNAME: asyncGetServByName (pRequest); return 1;
887 case WSAASYNC_GETSERVBYPORT: asyncGetServByPort (pRequest); return 1;
888
889// case WSAASYNC_SELECT:
890// break;
891
892 default:
893 dprintf(("WSOCK32: WSAAsyncWorker::dispatchRequest - invalid request type %d\n",
894 pRequest->ulType));
895 return 1;
896 }
897
898 pRequest->ulState = RS_DONE;
899 return 0;
900}
901
902
903/*****************************************************************************
904 * Name :
905 * Purpose :
906 * Parameters:
907 * Variables :
908 * Result :
909 * Remark :
910 * Status : UNTESTED STUB
911 *
912 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
913 *****************************************************************************/
914// process all requests in queue until termination
915void WSAAsyncWorker::processingLoop(void)
916{
917 PASYNCREQUEST pRequest;
918 APIRET rc;
919 ULONG ulPostCount;
920
921 do
922 {
923 // work as long as there are requests
924 do
925 {
926 pRequest = popRequest(); // get request from queue
927 if (pRequest != NULL)
928 {
929 dispatchRequest(pRequest); // process request
930 delete pRequest; // free the memory
931 }
932 }
933 while (pRequest != NULL);
934
935 // wait for semaphore
936 rc = DosWaitEventSem(hevRequest, SEM_INDEFINITE_WAIT);
937 rc = DosResetEventSem(hevRequest, &ulPostCount);
938 }
939 while (fTerminate == FALSE);
940
941 tidWorker = 0; // clear worker thread id
942}
943
944
945/*****************************************************************************
946 * Name :
947 * Purpose :
948 * Parameters:
949 * Variables :
950 * Result :
951 * Remark :
952 * Status : UNTESTED STUB
953 *
954 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
955 *****************************************************************************/
956// thread procedure
957void _Optlink WorkerThreadProc(void* pParam)
958{
959 // convert object pointer
960 WSAAsyncWorker* pWSAAsyncWorker = (WSAAsyncWorker*)pParam;
961 pWSAAsyncWorker->processingLoop(); // processing loop
962}
963
964
965/*****************************************************************************
966 * Name :
967 * Purpose :
968 * Parameters:
969 * Variables :
970 * Result :
971 * Remark :
972 * Status : UNTESTED STUB
973 *
974 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
975 *****************************************************************************/
976// the real function calls
977ODINFUNCTION5(HANDLE, WSAAsyncGetHostByName, HWND, hwnd,
978 unsigned int, wMsg,
979 const char*, name,
980 char*, buf,
981 int, buflen)
982{
983 dprintf(("name = %s\n", name));
984 PASYNCREQUEST pRequest = wsaWorker->createRequest(WSAASYNC_GETHOSTBYNAME,
985 (HWND) hwnd,
986 (ULONG)wMsg,
987 (PVOID)buf,
988 (ULONG)buflen,
989 (ULONG)name);
990 wsaWorker->pushRequest(pRequest);
991 return (HANDLE)pRequest;
992}
993
994
995/*****************************************************************************
996 * Name :
997 * Purpose :
998 * Parameters:
999 * Variables :
1000 * Result :
1001 * Remark :
1002 * Status : UNTESTED STUB
1003 *
1004 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
1005 *****************************************************************************/
1006// the real function calls
1007ODINFUNCTION7(HANDLE, WSAAsyncGetHostByAddr, HWND, hwnd,
1008 unsigned int, wMsg,
1009 const char*, addr,
1010 int, len,
1011 int, type,
1012 char*, buf,
1013 int, buflen)
1014{
1015 PASYNCREQUEST pRequest = wsaWorker->createRequest(WSAASYNC_GETHOSTBYADDR,
1016 (HWND) hwnd,
1017 (ULONG)wMsg,
1018 (PVOID)buf,
1019 (ULONG)buflen,
1020 (ULONG)addr,
1021 (ULONG)len,
1022 (ULONG)type);
1023 wsaWorker->pushRequest(pRequest);
1024 return (HANDLE)pRequest;
1025}
1026
1027
1028/*****************************************************************************
1029 * Name :
1030 * Purpose :
1031 * Parameters:
1032 * Variables :
1033 * Result :
1034 * Remark :
1035 * Status : UNTESTED STUB
1036 *
1037 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
1038 *****************************************************************************/
1039// the real function calls
1040ODINFUNCTION6(HANDLE, WSAAsyncGetServByName, HWND, hwnd,
1041 unsigned int, wMsg,
1042 const char*, name,
1043 const char*, proto,
1044 char*, buf,
1045 int, buflen)
1046{
1047 dprintf(("name = %s, proto = %s\n", name, proto));
1048 PASYNCREQUEST pRequest = wsaWorker->createRequest(WSAASYNC_GETSERVBYNAME,
1049 (HWND) hwnd,
1050 (ULONG)wMsg,
1051 (PVOID)buf,
1052 (ULONG)buflen,
1053 (ULONG)name,
1054 (ULONG)proto);
1055 wsaWorker->pushRequest(pRequest);
1056 return (HANDLE)pRequest;
1057}
1058
1059
1060/*****************************************************************************
1061 * Name :
1062 * Purpose :
1063 * Parameters:
1064 * Variables :
1065 * Result :
1066 * Remark :
1067 * Status : UNTESTED STUB
1068 *
1069 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
1070 *****************************************************************************/
1071// the real function calls
1072ODINFUNCTION6(HANDLE, WSAAsyncGetServByPort, HWND, hwnd,
1073 unsigned int, wMsg,
1074 int, port,
1075 const char*, proto,
1076 char*, buf,
1077 int, buflen)
1078{
1079 dprintf(("proto = %s\n", proto));
1080 PASYNCREQUEST pRequest = wsaWorker->createRequest(WSAASYNC_GETSERVBYPORT,
1081 (HWND) hwnd,
1082 (ULONG)wMsg,
1083 (PVOID)buf,
1084 (ULONG)buflen,
1085 (ULONG)port,
1086 (ULONG)proto);
1087 wsaWorker->pushRequest(pRequest);
1088 return (HANDLE)pRequest;
1089}
1090
1091
1092/*****************************************************************************
1093 * Name :
1094 * Purpose :
1095 * Parameters:
1096 * Variables :
1097 * Result :
1098 * Remark :
1099 * Status : UNTESTED STUB
1100 *
1101 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
1102 *****************************************************************************/
1103// the real function calls
1104ODINFUNCTION5(HANDLE, WSAAsyncGetProtoByName, HWND, hwnd,
1105 unsigned int, wMsg,
1106 const char*, name,
1107 char*, buf,
1108 int, buflen)
1109{
1110 dprintf(("name = %s\n", name));
1111 PASYNCREQUEST pRequest = wsaWorker->createRequest(WSAASYNC_GETPROTOBYNAME,
1112 (HWND) hwnd,
1113 (ULONG)wMsg,
1114 (PVOID)buf,
1115 (ULONG)buflen,
1116 (ULONG)name);
1117 wsaWorker->pushRequest(pRequest);
1118 return (HANDLE)pRequest;
1119}
1120
1121
1122/*****************************************************************************
1123 * Name :
1124 * Purpose :
1125 * Parameters:
1126 * Variables :
1127 * Result :
1128 * Remark :
1129 * Status : UNTESTED STUB
1130 *
1131 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
1132 *****************************************************************************/
1133// the real function calls
1134ODINFUNCTION5(HANDLE, WSAAsyncGetProtoByNumber, HWND, hwnd,
1135 unsigned int, wMsg,
1136 int, number,
1137 char*, buf,
1138 int, buflen)
1139{
1140 PASYNCREQUEST pRequest = wsaWorker->createRequest(WSAASYNC_GETPROTOBYNUMBER,
1141 (HWND) hwnd,
1142 (ULONG)wMsg,
1143 (PVOID)buf,
1144 (ULONG)buflen,
1145 (ULONG)number);
1146 wsaWorker->pushRequest(pRequest);
1147 return (HANDLE)pRequest;
1148}
1149
1150
1151/*****************************************************************************
1152 * Name :
1153 * Purpose : cancel a queued or busy request
1154 * Parameters:
1155 * Variables :
1156 * Result :
1157 * Remark :
1158 * Status : UNTESTED STUB
1159 *
1160 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
1161 *****************************************************************************/
1162
1163ODINFUNCTION1(int, WSACancelAsyncRequest, HANDLE, hAsyncTaskHandle)
1164{
1165 PASYNCREQUEST pRequest = (PASYNCREQUEST)hAsyncTaskHandle;
1166 BOOL rc;
1167
1168 // remove request from queue
1169 rc = wsaWorker->deleteRequest(pRequest);
1170 if (rc == TRUE)
1171 return 0; // success
1172 else
1173 {
1174 WSASetLastError(WSAEINVAL);
1175 return (SOCKET_ERROR);
1176 }
1177}
Note: See TracBrowser for help on using the repository browser.