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

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

Fix: WSA async rewrite

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