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

Last change on this file since 1726 was 1726, checked in by achimha, 26 years ago

WSAAsyncSelect should return 0 on succes, not the request packet pointer

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