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

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

Fix: asyncSelect

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