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

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

.

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