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

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

Fix: some fixes, WSAIsBlocking

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