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

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

Fix: error codes for async operations

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