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

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

Fix: socket fix

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