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

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

Fix: invalid structure alignment for asynchronous operations

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