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

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

Fix: compiler + library + stack issues fixed

File size: 39.0 KB
Line 
1/* $Id: async.cpp,v 1.6 1999-10-21 14:58:53 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
1034// case WSAASYNC_SELECT:
1035// break;
1036
1037 default:
1038 dprintf(("WSOCK32: WSAAsyncWorker::dispatchRequest - invalid request type %d\n",
1039 pRequest->ulType));
1040 rc = 1; break;
1041 }
1042
1043 pRequest->ulState = RS_DONE;
1044 fBlocking = FALSE;
1045 return rc;
1046}
1047
1048
1049/*****************************************************************************
1050 * Name :
1051 * Purpose :
1052 * Parameters:
1053 * Variables :
1054 * Result :
1055 * Remark :
1056 * Status : UNTESTED STUB
1057 *
1058 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
1059 *****************************************************************************/
1060// process all requests in queue until termination
1061void WSAAsyncWorker::processingLoop(void)
1062{
1063 PASYNCREQUEST pRequest;
1064 APIRET rc;
1065 ULONG ulPostCount;
1066
1067 do
1068 {
1069 // work as long as there are requests
1070 do
1071 {
1072 pRequest = popRequest(); // get request from queue
1073 if (pRequest != NULL)
1074 {
1075 dispatchRequest(pRequest); // process request
1076 delete pRequest; // free the memory
1077 }
1078 }
1079 while (pRequest != NULL);
1080
1081 // wait for semaphore
1082 rc = DosWaitEventSem(hevRequest, SEM_INDEFINITE_WAIT);
1083 rc = DosResetEventSem(hevRequest, &ulPostCount);
1084 }
1085 while (fTerminate == FALSE);
1086
1087 tidWorker = 0; // clear worker thread id
1088}
1089
1090
1091/*****************************************************************************
1092 * Name :
1093 * Purpose :
1094 * Parameters:
1095 * Variables :
1096 * Result :
1097 * Remark :
1098 * Status : UNTESTED STUB
1099 *
1100 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
1101 *****************************************************************************/
1102// thread procedure
1103void _Optlink WorkerThreadProc(void* pParam)
1104{
1105 // convert object pointer
1106 WSAAsyncWorker* pWSAAsyncWorker = (WSAAsyncWorker*)pParam;
1107 pWSAAsyncWorker->processingLoop(); // processing loop
1108}
1109
1110
1111/*****************************************************************************
1112 * Name :
1113 * Purpose :
1114 * Parameters:
1115 * Variables :
1116 * Result :
1117 * Remark :
1118 * Status : UNTESTED STUB
1119 *
1120 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
1121 *****************************************************************************/
1122// the real function calls
1123ODINFUNCTION5(HANDLE, WSAAsyncGetHostByName, HWND, hwnd,
1124 unsigned int, wMsg,
1125 const char*, name,
1126 char*, buf,
1127 int, buflen)
1128{
1129 dprintf(("name = %s\n", name));
1130 PASYNCREQUEST pRequest = wsaWorker->createRequest(WSAASYNC_GETHOSTBYNAME,
1131 (HWND) hwnd,
1132 (ULONG)wMsg,
1133 (PVOID)buf,
1134 (ULONG)buflen,
1135 (ULONG)name);
1136 wsaWorker->pushRequest(pRequest);
1137 return (HANDLE)pRequest;
1138}
1139
1140
1141/*****************************************************************************
1142 * Name :
1143 * Purpose :
1144 * Parameters:
1145 * Variables :
1146 * Result :
1147 * Remark :
1148 * Status : UNTESTED STUB
1149 *
1150 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
1151 *****************************************************************************/
1152// the real function calls
1153ODINFUNCTION7(HANDLE, WSAAsyncGetHostByAddr, HWND, hwnd,
1154 unsigned int, wMsg,
1155 const char*, addr,
1156 int, len,
1157 int, type,
1158 char*, buf,
1159 int, buflen)
1160{
1161 PASYNCREQUEST pRequest = wsaWorker->createRequest(WSAASYNC_GETHOSTBYADDR,
1162 (HWND) hwnd,
1163 (ULONG)wMsg,
1164 (PVOID)buf,
1165 (ULONG)buflen,
1166 (ULONG)addr,
1167 (ULONG)len,
1168 (ULONG)type);
1169 wsaWorker->pushRequest(pRequest);
1170 return (HANDLE)pRequest;
1171}
1172
1173
1174/*****************************************************************************
1175 * Name :
1176 * Purpose :
1177 * Parameters:
1178 * Variables :
1179 * Result :
1180 * Remark :
1181 * Status : UNTESTED STUB
1182 *
1183 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
1184 *****************************************************************************/
1185// the real function calls
1186ODINFUNCTION6(HANDLE, WSAAsyncGetServByName, HWND, hwnd,
1187 unsigned int, wMsg,
1188 const char*, name,
1189 const char*, proto,
1190 char*, buf,
1191 int, buflen)
1192{
1193 dprintf(("name = %s, proto = %s\n", name, proto));
1194 PASYNCREQUEST pRequest = wsaWorker->createRequest(WSAASYNC_GETSERVBYNAME,
1195 (HWND) hwnd,
1196 (ULONG)wMsg,
1197 (PVOID)buf,
1198 (ULONG)buflen,
1199 (ULONG)name,
1200 (ULONG)proto);
1201 wsaWorker->pushRequest(pRequest);
1202 return (HANDLE)pRequest;
1203}
1204
1205
1206/*****************************************************************************
1207 * Name :
1208 * Purpose :
1209 * Parameters:
1210 * Variables :
1211 * Result :
1212 * Remark :
1213 * Status : UNTESTED STUB
1214 *
1215 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
1216 *****************************************************************************/
1217// the real function calls
1218ODINFUNCTION6(HANDLE, WSAAsyncGetServByPort, HWND, hwnd,
1219 unsigned int, wMsg,
1220 int, port,
1221 const char*, proto,
1222 char*, buf,
1223 int, buflen)
1224{
1225 dprintf(("proto = %s\n", proto));
1226 PASYNCREQUEST pRequest = wsaWorker->createRequest(WSAASYNC_GETSERVBYPORT,
1227 (HWND) hwnd,
1228 (ULONG)wMsg,
1229 (PVOID)buf,
1230 (ULONG)buflen,
1231 (ULONG)port,
1232 (ULONG)proto);
1233 wsaWorker->pushRequest(pRequest);
1234 return (HANDLE)pRequest;
1235}
1236
1237
1238/*****************************************************************************
1239 * Name :
1240 * Purpose :
1241 * Parameters:
1242 * Variables :
1243 * Result :
1244 * Remark :
1245 * Status : UNTESTED STUB
1246 *
1247 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
1248 *****************************************************************************/
1249// the real function calls
1250ODINFUNCTION5(HANDLE, WSAAsyncGetProtoByName, HWND, hwnd,
1251 unsigned int, wMsg,
1252 const char*, name,
1253 char*, buf,
1254 int, buflen)
1255{
1256 dprintf(("name = %s\n", name));
1257 PASYNCREQUEST pRequest = wsaWorker->createRequest(WSAASYNC_GETPROTOBYNAME,
1258 (HWND) hwnd,
1259 (ULONG)wMsg,
1260 (PVOID)buf,
1261 (ULONG)buflen,
1262 (ULONG)name);
1263 wsaWorker->pushRequest(pRequest);
1264 return (HANDLE)pRequest;
1265}
1266
1267
1268/*****************************************************************************
1269 * Name :
1270 * Purpose :
1271 * Parameters:
1272 * Variables :
1273 * Result :
1274 * Remark :
1275 * Status : UNTESTED STUB
1276 *
1277 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
1278 *****************************************************************************/
1279// the real function calls
1280ODINFUNCTION5(HANDLE, WSAAsyncGetProtoByNumber, HWND, hwnd,
1281 unsigned int, wMsg,
1282 int, number,
1283 char*, buf,
1284 int, buflen)
1285{
1286 PASYNCREQUEST pRequest = wsaWorker->createRequest(WSAASYNC_GETPROTOBYNUMBER,
1287 (HWND) hwnd,
1288 (ULONG)wMsg,
1289 (PVOID)buf,
1290 (ULONG)buflen,
1291 (ULONG)number);
1292 wsaWorker->pushRequest(pRequest);
1293 return (HANDLE)pRequest;
1294}
1295
1296
1297/*****************************************************************************
1298 * Name :
1299 * Purpose : cancel a queued or busy request
1300 * Parameters:
1301 * Variables :
1302 * Result :
1303 * Remark :
1304 * Status : UNTESTED STUB
1305 *
1306 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
1307 *****************************************************************************/
1308
1309ODINFUNCTION1(int, WSACancelAsyncRequest, HANDLE, hAsyncTaskHandle)
1310{
1311 PASYNCREQUEST pRequest = (PASYNCREQUEST)hAsyncTaskHandle;
1312 BOOL rc;
1313
1314 // remove request from queue
1315 rc = wsaWorker->cancelAsyncRequest(pRequest);
1316 if (rc == TRUE)
1317 return 0; // success
1318 else
1319 {
1320 WSASetLastError(WSAEINVAL);
1321 return (SOCKET_ERROR);
1322 }
1323}
1324
1325
1326/*****************************************************************************
1327 * Name : WSAIsBlocking
1328 * Purpose :
1329 * Parameters:
1330 * Variables :
1331 * Result :
1332 * Remark :
1333 * Status : UNTESTED STUB
1334 *
1335 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
1336 *****************************************************************************/
1337
1338ODINFUNCTION0(BOOL, WSAIsBlocking)
1339{
1340 return(wsaWorker->isBlocking());
1341}
1342
1343
1344/*****************************************************************************
1345 * Name :
1346 * Purpose :
1347 * Parameters:
1348 * Variables :
1349 * Result :
1350 * Remark :
1351 * Status : UNTESTED STUB
1352 *
1353 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
1354 *****************************************************************************/
1355// the real function calls
1356ODINFUNCTION4(HANDLE, WSAAsyncSelect,SOCKET, s,
1357 HWND, hwnd,
1358 unsigned int, wMsg,
1359 long, lEvent)
1360{
1361 PASYNCREQUEST pRequest = wsaWorker->createRequest(WSAASYNC_SELECT,
1362 (HWND) hwnd,
1363 (ULONG)wMsg,
1364 (PVOID)NULL,
1365 (ULONG)0,
1366 (ULONG)s,
1367 (ULONG)lEvent);
1368 wsaWorker->pushRequest(pRequest);
1369 return (HANDLE)pRequest;
1370}
1371
Note: See TracBrowser for help on using the repository browser.