1 /*
2 * A simple socket-like package.
3 * This could undoubtedly be improved, since it does polling and busy-waiting.
4 * At least it uses asynch I/O and implements timeouts!
5 *
6 * Other funkiness includes the use of my own (possibly brain-damaged) error-handling infrastructure.
7 *
8 * -Roy Wood (roy@centricsystems.ca)
9 *
10 */
11
12
13 /* ====================================================================
14 * Copyright (c) 1998-1999 The OpenSSL Project. All rights reserved.
15 *
16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions
18 * are met:
19 *
20 * 1. Redistributions of source code must retain the above copyright
21 * notice, this list of conditions and the following disclaimer.
22 *
23 * 2. Redistributions in binary form must reproduce the above copyright
24 * notice, this list of conditions and the following disclaimer in
25 * the documentation and/or other materials provided with the
26 * distribution.
27 *
28 * 3. All advertising materials mentioning features or use of this
29 * software must display the following acknowledgment:
30 * "This product includes software developed by the OpenSSL Project
31 * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
32 *
33 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
34 * endorse or promote products derived from this software without
35 * prior written permission. For written permission, please contact
36 * openssl-core@openssl.org.
37 *
38 * 5. Products derived from this software may not be called "OpenSSL"
39 * nor may "OpenSSL" appear in their names without prior written
40 * permission of the OpenSSL Project.
41 *
42 * 6. Redistributions of any form whatsoever must retain the following
43 * acknowledgment:
44 * "This product includes software developed by the OpenSSL Project
45 * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
46 *
47 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
48 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
49 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
50 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
51 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
52 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
53 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
54 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
56 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
57 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
58 * OF THE POSSIBILITY OF SUCH DAMAGE.
59 * ====================================================================
60 *
61 * This product includes cryptographic software written by Eric Young
62 * (eay@cryptsoft.com). This product includes software written by Tim
63 * Hudson (tjh@cryptsoft.com).
64 *
65 */
66
67
68
69
70
71 #include "MacSocket.h"
72
73 #include <Threads.h>
74
75 #include <OpenTransport.h>
76 #include <OpenTpTInternet.h>
77 #include <OpenTptClient.h>
78
79
80
81 #include "CPStringUtils.hpp"
82 #include "ErrorHandling.hpp"
83
84
85 // #define MACSOCKET_DEBUG 1
86
87 #ifdef MACSOCKET_DEBUG
88 #include <stdio.h>
89 #endif
90
91
92
93 extern int errno;
94
95
96 #define kMaxNumSockets 4
97
98
99 struct SocketStruct
100 {
101 Boolean mIsInUse;
102
103 Boolean mEndpointIsBound;
104
105 Boolean mLocalEndIsConnected;
106 Boolean mRemoteEndIsConnected;
107
108 Boolean mReceivedTOpenComplete;
109 Boolean mReceivedTBindComplete;
110 Boolean mReceivedTConnect;
111 Boolean mReceivedTListen;
112 Boolean mReceivedTPassCon;
113 Boolean mReceivedTDisconnect;
114 Boolean mReceivedTOrdRel;
115 Boolean mReceivedTDisconnectComplete;
116
117 long mTimeoutTicks;
118 long mOperationStartTicks;
119
120 MacSocket_IdleWaitCallback mIdleWaitCallback;
121 void *mUserRefPtr;
122
123 OTEventCode mExpectedCode;
124 OTResult mAsyncOperationResult;
125
126 EndpointRef mEndPointRef;
127 TBind *mBindRequestedAddrInfo;
128 TBind *mAssignedAddrInfo;
129 TCall *mRemoteAddrInfo;
130
131 Boolean mReadyToReadData;
132 Boolean mReadyToWriteData;
133
134 Ptr mReadBuffer;
135 Ptr mWriteBuffer;
136
137 int mLastError;
138 char mErrMessage[256];
139 };
140
141 typedef struct SocketStruct SocketStruct;
142
143
144 static SocketStruct sSockets[kMaxNumSockets];
145 static Boolean sSocketsSetup = false;
146
147
148
149
150 static OSErr MyBusyWait(SocketStruct *ioSocket,Boolean returnImmediatelyOnError,OTResult *outOTResult,Boolean *inAsyncOperationCompleteFlag);
151
152 static pascal void OTNonYieldingNotifier(void *contextPtr,OTEventCode code,OTResult result,void *cookie);
153
154 static Boolean SocketIndexIsValid(const int inSocketNum);
155
156 static void InitSocket(SocketStruct *ioSocket);
157
158 static void PrepareForAsyncOperation(SocketStruct *ioSocket,const OTEventCode inExpectedCode);
159
160 static Boolean TimeoutElapsed(const SocketStruct *inSocket);
161
162 static OSStatus NegotiateIPReuseAddrOption(EndpointRef inEndpoint,const Boolean inEnableReuseIP);
163
164
165
MacSocket_GetSocketErrorInfo(const int inSocketNum,int * outSocketErrCode,char * outSocketErrString,const int inSocketErrStringMaxLength)166 void MacSocket_GetSocketErrorInfo(const int inSocketNum,int *outSocketErrCode,char *outSocketErrString,const int inSocketErrStringMaxLength)
167 {
168 if (outSocketErrCode != nil)
169 {
170 *outSocketErrCode = -1;
171 }
172
173 if (outSocketErrString != nil)
174 {
175 CopyCStrToCStr("",outSocketErrString,inSocketErrStringMaxLength);
176 }
177
178
179 if (SocketIndexIsValid(inSocketNum))
180 {
181 SocketStruct *theSocketStruct = &(sSockets[inSocketNum]);
182
183
184 if (outSocketErrCode != nil)
185 {
186 *outSocketErrCode = theSocketStruct->mLastError;
187 }
188
189 if (outSocketErrString != nil)
190 {
191 CopyCStrToCStr(theSocketStruct->mErrMessage,outSocketErrString,inSocketErrStringMaxLength);
192 }
193 }
194 }
195
196
MacSocket_SetUserRefPtr(const int inSocketNum,void * inNewRefPtr)197 void MacSocket_SetUserRefPtr(const int inSocketNum,void *inNewRefPtr)
198 {
199 if (SocketIndexIsValid(inSocketNum))
200 {
201 SocketStruct *theSocketStruct = &(sSockets[inSocketNum]);
202
203 theSocketStruct->mUserRefPtr = inNewRefPtr;
204 }
205 }
206
207
208
MacSocket_GetLocalIPAndPort(const int inSocketNum,char * outIPAndPort,const int inIPAndPortLength)209 void MacSocket_GetLocalIPAndPort(const int inSocketNum,char *outIPAndPort,const int inIPAndPortLength)
210 {
211 if (outIPAndPort != nil && SocketIndexIsValid(inSocketNum))
212 {
213 char tempString[256];
214 SocketStruct *theSocketStruct = &(sSockets[inSocketNum]);
215
216
217 CopyCStrToCStr("",tempString,sizeof(tempString));
218
219 if (theSocketStruct->mAssignedAddrInfo != nil)
220 {
221 InetAddress *theInetAddress = (InetAddress *) theSocketStruct->mAssignedAddrInfo->addr.buf;
222 InetHost theInetHost = theInetAddress->fHost;
223
224 if (theInetHost == 0)
225 {
226 InetInterfaceInfo theInetInterfaceInfo;
227
228 if (::OTInetGetInterfaceInfo(&theInetInterfaceInfo,kDefaultInetInterface) == noErr)
229 {
230 theInetHost = theInetInterfaceInfo.fAddress;
231 }
232 }
233
234 ::OTInetHostToString(theInetHost,tempString);
235
236 ConcatCStrToCStr(":",tempString,sizeof(tempString));
237 ConcatLongIntToCStr(theInetAddress->fPort,tempString,sizeof(tempString));
238 }
239
240 CopyCStrToCStr(tempString,outIPAndPort,inIPAndPortLength);
241 }
242 }
243
244
245
MacSocket_GetRemoteIPAndPort(const int inSocketNum,char * outIPAndPort,const int inIPAndPortLength)246 void MacSocket_GetRemoteIPAndPort(const int inSocketNum,char *outIPAndPort,const int inIPAndPortLength)
247 {
248 if (outIPAndPort != nil && SocketIndexIsValid(inSocketNum))
249 {
250 char tempString[256];
251 SocketStruct *theSocketStruct = &(sSockets[inSocketNum]);
252
253
254 CopyCStrToCStr("",tempString,sizeof(tempString));
255
256 if (theSocketStruct->mRemoteAddrInfo != nil)
257 {
258 InetAddress *theInetAddress = (InetAddress *) theSocketStruct->mRemoteAddrInfo->addr.buf;
259 InetHost theInetHost = theInetAddress->fHost;
260
261 if (theInetHost == 0)
262 {
263 InetInterfaceInfo theInetInterfaceInfo;
264
265 if (::OTInetGetInterfaceInfo(&theInetInterfaceInfo,kDefaultInetInterface) == noErr)
266 {
267 theInetHost = theInetInterfaceInfo.fAddress;
268 }
269 }
270
271 ::OTInetHostToString(theInetHost,tempString);
272
273 ConcatCStrToCStr(":",tempString,sizeof(tempString));
274 ConcatLongIntToCStr(theInetAddress->fPort,tempString,sizeof(tempString));
275 }
276
277 CopyCStrToCStr(tempString,outIPAndPort,inIPAndPortLength);
278 }
279 }
280
281
282
MacSocket_RemoteEndIsClosing(const int inSocketNum)283 Boolean MacSocket_RemoteEndIsClosing(const int inSocketNum)
284 {
285 Boolean theResult = false;
286
287 if (SocketIndexIsValid(inSocketNum))
288 {
289 SocketStruct *theSocketStruct = &(sSockets[inSocketNum]);
290
291 theResult = theSocketStruct->mReceivedTOrdRel;
292 }
293
294 return(theResult);
295 }
296
297
298
MacSocket_ListenCompleted(const int inSocketNum)299 Boolean MacSocket_ListenCompleted(const int inSocketNum)
300 {
301 Boolean theResult = false;
302
303 if (SocketIndexIsValid(inSocketNum))
304 {
305 SocketStruct *theSocketStruct = &(sSockets[inSocketNum]);
306
307 theResult = theSocketStruct->mReceivedTPassCon;
308 }
309
310 return(theResult);
311 }
312
313
314
MacSocket_RemoteEndIsOpen(const int inSocketNum)315 Boolean MacSocket_RemoteEndIsOpen(const int inSocketNum)
316 {
317 if (SocketIndexIsValid(inSocketNum))
318 {
319 SocketStruct *theSocketStruct = &(sSockets[inSocketNum]);
320
321 return(theSocketStruct->mRemoteEndIsConnected);
322 }
323
324 else
325 {
326 return(false);
327 }
328 }
329
330
331
MacSocket_LocalEndIsOpen(const int inSocketNum)332 Boolean MacSocket_LocalEndIsOpen(const int inSocketNum)
333 {
334 if (SocketIndexIsValid(inSocketNum))
335 {
336 SocketStruct *theSocketStruct = &(sSockets[inSocketNum]);
337
338 return(theSocketStruct->mLocalEndIsConnected);
339 }
340
341 else
342 {
343 return(false);
344 }
345 }
346
347
348
TimeoutElapsed(const SocketStruct * inSocket)349 static Boolean TimeoutElapsed(const SocketStruct *inSocket)
350 {
351 Boolean timeIsUp = false;
352
353 if (inSocket != nil && inSocket->mTimeoutTicks > 0 && ::TickCount() > inSocket->mOperationStartTicks + inSocket->mTimeoutTicks)
354 {
355 timeIsUp = true;
356 }
357
358
359 return(timeIsUp);
360 }
361
362
363
SocketIndexIsValid(const int inSocketNum)364 static Boolean SocketIndexIsValid(const int inSocketNum)
365 {
366 if (inSocketNum >= 0 && inSocketNum < kMaxNumSockets && sSockets[inSocketNum].mEndPointRef != kOTInvalidEndpointRef)
367 {
368 return(true);
369 }
370
371 else
372 {
373 return(false);
374 }
375 }
376
377
378
InitSocket(SocketStruct * ioSocket)379 static void InitSocket(SocketStruct *ioSocket)
380 {
381 ioSocket->mIsInUse = false;
382
383 ioSocket->mEndpointIsBound = false;
384
385 ioSocket->mLocalEndIsConnected = false;
386 ioSocket->mRemoteEndIsConnected = false;
387
388 ioSocket->mReceivedTOpenComplete = false;
389 ioSocket->mReceivedTBindComplete = false;
390 ioSocket->mReceivedTConnect = false;
391 ioSocket->mReceivedTListen = false;
392 ioSocket->mReceivedTPassCon = false;
393 ioSocket->mReceivedTDisconnect = false;
394 ioSocket->mReceivedTOrdRel = false;
395 ioSocket->mReceivedTDisconnectComplete = false;
396
397 ioSocket->mTimeoutTicks = 30 * 60;
398 ioSocket->mOperationStartTicks = -1;
399
400 ioSocket->mIdleWaitCallback = nil;
401 ioSocket->mUserRefPtr = nil;
402
403 ioSocket->mExpectedCode = 0;
404 ioSocket->mAsyncOperationResult = noErr;
405
406 ioSocket->mEndPointRef = kOTInvalidEndpointRef;
407
408 ioSocket->mBindRequestedAddrInfo = nil;
409 ioSocket->mAssignedAddrInfo = nil;
410 ioSocket->mRemoteAddrInfo = nil;
411
412 ioSocket->mReadyToReadData = false;
413 ioSocket->mReadyToWriteData = true;
414
415 ioSocket->mReadBuffer = nil;
416 ioSocket->mWriteBuffer = nil;
417
418 ioSocket->mLastError = noErr;
419 CopyCStrToCStr("",ioSocket->mErrMessage,sizeof(ioSocket->mErrMessage));
420 }
421
422
423
PrepareForAsyncOperation(SocketStruct * ioSocket,const OTEventCode inExpectedCode)424 static void PrepareForAsyncOperation(SocketStruct *ioSocket,const OTEventCode inExpectedCode)
425 {
426 ioSocket->mOperationStartTicks = ::TickCount();
427
428 ioSocket->mAsyncOperationResult = noErr;
429
430 ioSocket->mExpectedCode = inExpectedCode;
431 }
432
433
434 // The wait function....
435
MyBusyWait(SocketStruct * ioSocket,Boolean returnImmediatelyOnError,OTResult * outOTResult,Boolean * inAsyncOperationCompleteFlag)436 static OSErr MyBusyWait(SocketStruct *ioSocket,Boolean returnImmediatelyOnError,OTResult *outOTResult,Boolean *inAsyncOperationCompleteFlag)
437 {
438 OSErr errCode = noErr;
439 OTResult theOTResult = noErr;
440
441
442 SetErrorMessageAndBailIfNil(ioSocket,"MyBusyWait: Bad parameter, ioSocket = nil");
443 SetErrorMessageAndBailIfNil(inAsyncOperationCompleteFlag,"MyBusyWait: Bad parameter, inAsyncOperationCompleteFlag = nil");
444
445 for (;;)
446 {
447 if (*inAsyncOperationCompleteFlag)
448 {
449 theOTResult = ioSocket->mAsyncOperationResult;
450
451 break;
452 }
453
454 if (ioSocket->mIdleWaitCallback != nil)
455 {
456 theOTResult = (*(ioSocket->mIdleWaitCallback))(ioSocket->mUserRefPtr);
457
458 if (theOTResult != noErr && returnImmediatelyOnError)
459 {
460 break;
461 }
462 }
463
464 if (TimeoutElapsed(ioSocket))
465 {
466 theOTResult = kMacSocket_TimeoutErr;
467
468 break;
469 }
470 }
471
472
473 EXITPOINT:
474
475 if (outOTResult != nil)
476 {
477 *outOTResult = theOTResult;
478 }
479
480 return(errCode);
481 }
482
483
484
485 // I used to do thread switching, but stopped. It could easily be rolled back in though....
486
OTNonYieldingNotifier(void * contextPtr,OTEventCode code,OTResult result,void * cookie)487 static pascal void OTNonYieldingNotifier(void *contextPtr,OTEventCode code,OTResult result,void *cookie)
488 {
489 SocketStruct *theSocketStruct = (SocketStruct *) contextPtr;
490
491 if (theSocketStruct != nil)
492 {
493 if (theSocketStruct->mExpectedCode != 0 && code == theSocketStruct->mExpectedCode)
494 {
495 theSocketStruct->mAsyncOperationResult = result;
496
497 theSocketStruct->mExpectedCode = 0;
498 }
499
500
501 switch (code)
502 {
503 case T_OPENCOMPLETE:
504 {
505 theSocketStruct->mReceivedTOpenComplete = true;
506
507 theSocketStruct->mEndPointRef = (EndpointRef) cookie;
508
509 break;
510 }
511
512
513 case T_BINDCOMPLETE:
514 {
515 theSocketStruct->mReceivedTBindComplete = true;
516
517 break;
518 }
519
520
521 case T_CONNECT:
522 {
523 theSocketStruct->mReceivedTConnect = true;
524
525 theSocketStruct->mLocalEndIsConnected = true;
526
527 theSocketStruct->mRemoteEndIsConnected = true;
528
529 break;
530 }
531
532
533 case T_LISTEN:
534 {
535 theSocketStruct->mReceivedTListen = true;
536
537 break;
538 }
539
540
541 case T_PASSCON:
542 {
543 theSocketStruct->mReceivedTPassCon = true;
544
545 theSocketStruct->mLocalEndIsConnected = true;
546
547 theSocketStruct->mRemoteEndIsConnected = true;
548
549 break;
550 }
551
552
553 case T_DATA:
554 {
555 theSocketStruct->mReadyToReadData = true;
556
557 break;
558 }
559
560 case T_GODATA:
561 {
562 theSocketStruct->mReadyToWriteData = true;
563
564 break;
565 }
566
567 case T_DISCONNECT:
568 {
569 theSocketStruct->mReceivedTDisconnect = true;
570
571 theSocketStruct->mRemoteEndIsConnected = false;
572
573 theSocketStruct->mLocalEndIsConnected = false;
574
575 ::OTRcvDisconnect(theSocketStruct->mEndPointRef,nil);
576
577 break;
578 }
579
580 case T_ORDREL:
581 {
582 theSocketStruct->mReceivedTOrdRel = true;
583
584 // We can still write data, so don't clear mRemoteEndIsConnected
585
586 ::OTRcvOrderlyDisconnect(theSocketStruct->mEndPointRef);
587
588 break;
589 }
590
591 case T_DISCONNECTCOMPLETE:
592 {
593 theSocketStruct->mReceivedTDisconnectComplete = true;
594
595 theSocketStruct->mRemoteEndIsConnected = false;
596
597 theSocketStruct->mLocalEndIsConnected = false;
598
599 break;
600 }
601 }
602 }
603 /*
604 T_LISTEN OTListen
605 T_CONNECT OTRcvConnect
606 T_DATA OTRcv, OTRcvUData
607 T_DISCONNECT OTRcvDisconnect
608 T_ORDREL OTRcvOrderlyDisconnect
609 T_GODATA OTSnd, OTSndUData, OTLook
610 T_PASSCON none
611
612 T_EXDATA OTRcv
613 T_GOEXDATA OTSnd, OTLook
614 T_UDERR OTRcvUDErr
615 */
616 }
617
618
619
620 // Initialize the main socket data structure
621
MacSocket_Startup(void)622 OSErr MacSocket_Startup(void)
623 {
624 if (!sSocketsSetup)
625 {
626 for (int i = 0;i < kMaxNumSockets;i++)
627 {
628 InitSocket(&(sSockets[i]));
629 }
630
631 ::InitOpenTransport();
632
633 sSocketsSetup = true;
634 }
635
636
637 return(noErr);
638 }
639
640
641
642 // Cleanup before exiting
643
MacSocket_Shutdown(void)644 OSErr MacSocket_Shutdown(void)
645 {
646 if (sSocketsSetup)
647 {
648 for (int i = 0;i < kMaxNumSockets;i++)
649 {
650 SocketStruct *theSocketStruct = &(sSockets[i]);
651
652 if (theSocketStruct->mIsInUse)
653 {
654 if (theSocketStruct->mEndPointRef != kOTInvalidEndpointRef)
655 {
656 OTResult theOTResult;
657
658
659 // Since we're killing the endpoint, I don't bother to send the disconnect (sorry!)
660
661 /*
662 if (theSocketStruct->mLocalEndIsConnected)
663 {
664 // This is an abortive action, so we do a hard disconnect instead of an OTSndOrderlyDisconnect
665
666 theOTResult = ::OTSndDisconnect(theSocketStruct->mEndPointRef, nil);
667
668 // Now we have to watch for T_DISCONNECTCOMPLETE event
669
670 theSocketStruct->mLocalEndIsConnected = false;
671 }
672 */
673
674 theOTResult = ::OTCloseProvider(theSocketStruct->mEndPointRef);
675
676
677 theSocketStruct->mEndPointRef = kOTInvalidEndpointRef;
678 }
679
680 if (theSocketStruct->mBindRequestedAddrInfo != nil)
681 {
682 ::OTFree((void *) theSocketStruct->mBindRequestedAddrInfo,T_BIND);
683
684 theSocketStruct->mBindRequestedAddrInfo = nil;
685 }
686
687 if (theSocketStruct->mAssignedAddrInfo != nil)
688 {
689 ::OTFree((void *) theSocketStruct->mAssignedAddrInfo,T_BIND);
690
691 theSocketStruct->mAssignedAddrInfo = nil;
692 }
693
694 if (theSocketStruct->mRemoteAddrInfo != nil)
695 {
696 ::OTFree((void *) theSocketStruct->mRemoteAddrInfo,T_CALL);
697
698 theSocketStruct->mRemoteAddrInfo = nil;
699 }
700
701
702 }
703 }
704
705 ::CloseOpenTransport();
706
707 sSocketsSetup = false;
708 }
709
710 return(noErr);
711 }
712
713
714
715
716
717
718 // Allocate a socket
719
MacSocket_socket(int * outSocketNum,const Boolean inDoThreadSwitching,const long inTimeoutTicks,MacSocket_IdleWaitCallback inIdleWaitCallback,void * inUserRefPtr)720 OSErr MacSocket_socket(int *outSocketNum,const Boolean inDoThreadSwitching,const long inTimeoutTicks,MacSocket_IdleWaitCallback inIdleWaitCallback,void *inUserRefPtr)
721 {
722 // Gotta roll support back in for threads eventually.....
723
724 #pragma unused(inDoThreadSwitching)
725
726
727 OSErr errCode = noErr;
728
729
730 SetErrorMessageAndBailIfNil(outSocketNum,"MacSocket_socket: Bad parameter, outSocketNum == nil");
731
732 *outSocketNum = -1;
733
734
735 // Find an unused socket
736
737 for (int i = 0;i < kMaxNumSockets;i++)
738 {
739 if (sSockets[i].mIsInUse == false)
740 {
741 OTResult theOTResult;
742 SocketStruct *theSocketStruct = &(sSockets[i]);
743
744
745 InitSocket(theSocketStruct);
746
747 theSocketStruct->mIdleWaitCallback = inIdleWaitCallback;
748 theSocketStruct->mUserRefPtr = inUserRefPtr;
749
750 theSocketStruct->mTimeoutTicks = inTimeoutTicks;
751
752
753 // Set up OT endpoint
754
755 PrepareForAsyncOperation(theSocketStruct,T_OPENCOMPLETE);
756
757 theOTResult = ::OTAsyncOpenEndpoint(OTCreateConfiguration(kTCPName),0,nil,OTNonYieldingNotifier,(void *) theSocketStruct);
758
759 SetErrorMessageAndLongIntAndBailIfError(theOTResult,"MacSocket_socket: Can't create OT endpoint, OTAsyncOpenEndpoint() = ",theOTResult);
760
761 BailIfError(MyBusyWait(theSocketStruct,false,&theOTResult,&(theSocketStruct->mReceivedTOpenComplete)));
762
763 SetErrorMessageAndLongIntAndBailIfError(theOTResult,"MacSocket_socket: Can't create OT endpoint, OTAsyncOpenEndpoint() = ",theOTResult);
764
765
766 *outSocketNum = i;
767
768 errCode = noErr;
769
770 theSocketStruct->mIsInUse = true;
771
772 break;
773 }
774
775 else if (i == kMaxNumSockets - 1)
776 {
777 SetErrorMessageAndBail("MacSocket_socket: No sockets available");
778 }
779 }
780
781
782 EXITPOINT:
783
784 errno = errCode;
785
786 return(errCode);
787 }
788
789
790
791
MacSocket_listen(const int inSocketNum,const int inPortNum)792 OSErr MacSocket_listen(const int inSocketNum,const int inPortNum)
793 {
794 OSErr errCode = noErr;
795 SocketStruct *theSocketStruct = nil;
796
797
798 if (!SocketIndexIsValid(inSocketNum))
799 {
800 SetErrorMessageAndBail("MacSocket_listen: Invalid socket number specified");
801 }
802
803
804 theSocketStruct = &(sSockets[inSocketNum]);
805
806
807 OTResult theOTResult;
808
809
810 if (theSocketStruct->mBindRequestedAddrInfo == nil)
811 {
812 theSocketStruct->mBindRequestedAddrInfo = (TBind *) ::OTAlloc(theSocketStruct->mEndPointRef,T_BIND,T_ADDR,&theOTResult);
813
814 SetErrorMessageAndLongIntAndBailIfError(theOTResult,"MacSocket_listen: Can't allocate OT T_BIND structure, OTAlloc() = ",theOTResult);
815 SetErrorMessageAndBailIfNil(theSocketStruct->mBindRequestedAddrInfo,"MacSocket_listen: Can't allocate OT T_BIND structure, OTAlloc() returned nil");
816 }
817
818 if (theSocketStruct->mAssignedAddrInfo == nil)
819 {
820 theSocketStruct->mAssignedAddrInfo = (TBind *) ::OTAlloc(theSocketStruct->mEndPointRef,T_BIND,T_ADDR,&theOTResult);
821
822 SetErrorMessageAndLongIntAndBailIfError(theOTResult,"MacSocket_listen: Can't allocate OT T_BIND structure, OTAlloc() = ",theOTResult);
823 SetErrorMessageAndBailIfNil(theSocketStruct->mAssignedAddrInfo,"MacSocket_listen: Can't allocate OT T_BIND structure, OTAlloc() returned nil");
824 }
825
826 if (theSocketStruct->mRemoteAddrInfo == nil)
827 {
828 theSocketStruct->mRemoteAddrInfo = (TCall *) ::OTAlloc(theSocketStruct->mEndPointRef,T_CALL,T_ADDR,&theOTResult);
829
830 SetErrorMessageAndLongIntAndBailIfError(theOTResult,"MacSocket_listen: Can't allocate OT T_CALL structure, OTAlloc() = ",theOTResult);
831 SetErrorMessageAndBailIfNil(theSocketStruct->mRemoteAddrInfo,"MacSocket_listen: Can't allocate OT T_CALL structure, OTAlloc() returned nil");
832 }
833
834
835 if (!theSocketStruct->mEndpointIsBound)
836 {
837 InetInterfaceInfo theInetInterfaceInfo;
838
839 theOTResult = ::OTInetGetInterfaceInfo(&theInetInterfaceInfo,kDefaultInetInterface);
840
841 SetErrorMessageAndLongIntAndBailIfError(theOTResult,"MacSocket_listen: Can't determine OT interface info, OTInetGetInterfaceInfo() = ",theOTResult);
842
843
844 InetAddress *theInetAddress = (InetAddress *) theSocketStruct->mBindRequestedAddrInfo->addr.buf;
845
846 // theInetAddress->fAddressType = AF_INET;
847 // theInetAddress->fPort = inPortNum;
848 // theInetAddress->fHost = theInetInterfaceInfo.fAddress;
849
850 ::OTInitInetAddress(theInetAddress,inPortNum,theInetInterfaceInfo.fAddress);
851
852 theSocketStruct->mBindRequestedAddrInfo->addr.len = sizeof(InetAddress);
853
854 theSocketStruct->mBindRequestedAddrInfo->qlen = 1;
855
856
857 theOTResult = ::OTSetSynchronous(theSocketStruct->mEndPointRef);
858
859 SetErrorMessageAndLongIntAndBailIfError(theOTResult,"MacSocket_listen: Can't set OT endpoint mode, OTSetSynchronous() = ",theOTResult);
860
861 theOTResult = NegotiateIPReuseAddrOption(theSocketStruct->mEndPointRef,true);
862
863 SetErrorMessageAndLongIntAndBailIfError(theOTResult,"MacSocket_listen: Can't set OT IP address reuse flag, NegotiateIPReuseAddrOption() = ",theOTResult);
864
865 theOTResult = ::OTSetAsynchronous(theSocketStruct->mEndPointRef);
866
867 SetErrorMessageAndLongIntAndBailIfError(theOTResult,"MacSocket_listen: Can't set OT endpoint mode, OTSetAsynchronous() = ",theOTResult);
868
869
870 PrepareForAsyncOperation(theSocketStruct,T_BINDCOMPLETE);
871
872 theOTResult = ::OTBind(theSocketStruct->mEndPointRef,theSocketStruct->mBindRequestedAddrInfo,theSocketStruct->mAssignedAddrInfo);
873
874 SetErrorMessageAndLongIntAndBailIfError(theOTResult,"MacSocket_listen: Can't bind OT endpoint, OTBind() = ",theOTResult);
875
876 BailIfError(MyBusyWait(theSocketStruct,false,&theOTResult,&(theSocketStruct->mReceivedTBindComplete)));
877
878 SetErrorMessageAndLongIntAndBailIfError(theOTResult,"MacSocket_listen: Can't bind OT endpoint, OTBind() = ",theOTResult);
879
880
881 theSocketStruct->mEndpointIsBound = true;
882 }
883
884
885 PrepareForAsyncOperation(theSocketStruct,T_LISTEN);
886
887 theOTResult = ::OTListen(theSocketStruct->mEndPointRef,theSocketStruct->mRemoteAddrInfo);
888
889 if (theOTResult == noErr)
890 {
891 PrepareForAsyncOperation(theSocketStruct,T_PASSCON);
892
893 theOTResult = ::OTAccept(theSocketStruct->mEndPointRef,theSocketStruct->mEndPointRef,theSocketStruct->mRemoteAddrInfo);
894
895 SetErrorMessageAndLongIntAndBailIfError(theOTResult,"MacSocket_listen: Can't begin OT accept, OTAccept() = ",theOTResult);
896
897 BailIfError(MyBusyWait(theSocketStruct,false,&theOTResult,&(theSocketStruct->mReceivedTPassCon)));
898
899 SetErrorMessageAndLongIntAndBailIfError(theOTResult,"MacSocket_listen: Can't accept OT connection, OTAccept() = ",theOTResult);
900 }
901
902 else if (theOTResult == kOTNoDataErr)
903 {
904 theOTResult = noErr;
905 }
906
907 else
908 {
909 SetErrorMessageAndLongIntAndBail("MacSocket_listen: Can't begin OT listen, OTListen() = ",theOTResult);
910 }
911
912
913 errCode = noErr;
914
915
916 EXITPOINT:
917
918 if (theSocketStruct != nil)
919 {
920 theSocketStruct->mLastError = noErr;
921
922 CopyCStrToCStr("",theSocketStruct->mErrMessage,sizeof(theSocketStruct->mErrMessage));
923
924 if (errCode != noErr)
925 {
926 theSocketStruct->mLastError = errCode;
927
928 CopyCStrToCStr(GetErrorMessage(),theSocketStruct->mErrMessage,sizeof(theSocketStruct->mErrMessage));
929 }
930 }
931
932 errno = errCode;
933
934 return(errCode);
935 }
936
937
938
939
MacSocket_connect(const int inSocketNum,char * inTargetAddressAndPort)940 OSErr MacSocket_connect(const int inSocketNum,char *inTargetAddressAndPort)
941 {
942 OSErr errCode = noErr;
943 SocketStruct *theSocketStruct = nil;
944
945
946 if (!SocketIndexIsValid(inSocketNum))
947 {
948 SetErrorMessageAndBail("MacSocket_connect: Invalid socket number specified");
949 }
950
951 theSocketStruct = &(sSockets[inSocketNum]);
952
953 if (theSocketStruct->mEndpointIsBound)
954 {
955 SetErrorMessageAndBail("MacSocket_connect: Socket previously bound");
956 }
957
958
959 OTResult theOTResult;
960
961 theSocketStruct->mBindRequestedAddrInfo = (TBind *) ::OTAlloc(theSocketStruct->mEndPointRef,T_BIND,T_ADDR,&theOTResult);
962
963 SetErrorMessageAndLongIntAndBailIfError(theOTResult,"MacSocket_connect: Can't allocate OT T_BIND structure, OTAlloc() = ",theOTResult);
964 SetErrorMessageAndBailIfNil(theSocketStruct->mBindRequestedAddrInfo,"MacSocket_connect: Can't allocate OT T_BIND structure, OTAlloc() returned nil");
965
966
967 theSocketStruct->mAssignedAddrInfo = (TBind *) ::OTAlloc(theSocketStruct->mEndPointRef,T_BIND,T_ADDR,&theOTResult);
968
969 SetErrorMessageAndLongIntAndBailIfError(theOTResult,"MacSocket_connect: Can't allocate OT T_BIND structure, OTAlloc() = ",theOTResult);
970 SetErrorMessageAndBailIfNil(theSocketStruct->mAssignedAddrInfo,"MacSocket_connect: Can't allocate OT T_BIND structure, OTAlloc() returned nil");
971
972
973 theSocketStruct->mRemoteAddrInfo = (TCall *) ::OTAlloc(theSocketStruct->mEndPointRef,T_CALL,T_ADDR,&theOTResult);
974
975 SetErrorMessageAndLongIntAndBailIfError(theOTResult,"MacSocket_connect: Can't allocate OT T_CALL structure, OTAlloc() = ",theOTResult);
976 SetErrorMessageAndBailIfNil(theSocketStruct->mRemoteAddrInfo,"MacSocket_connect: Can't allocate OT T_CALL structure, OTAlloc() returned nil");
977
978
979 PrepareForAsyncOperation(theSocketStruct,T_BINDCOMPLETE);
980
981 theOTResult = ::OTBind(theSocketStruct->mEndPointRef,nil,theSocketStruct->mAssignedAddrInfo);
982
983 SetErrorMessageAndLongIntAndBailIfError(theOTResult,"MacSocket_connect: Can't bind OT endpoint, OTBind() = ",theOTResult);
984
985 BailIfError(MyBusyWait(theSocketStruct,false,&theOTResult,&(theSocketStruct->mReceivedTBindComplete)));
986
987 SetErrorMessageAndLongIntAndBailIfError(theOTResult,"MacSocket_connect: Can't bind OT endpoint, OTBind() = ",theOTResult);
988
989 theSocketStruct->mEndpointIsBound = true;
990
991
992 TCall sndCall;
993 DNSAddress hostDNSAddress;
994
995 // Set up target address
996
997 sndCall.addr.buf = (UInt8 *) &hostDNSAddress;
998 sndCall.addr.len = ::OTInitDNSAddress(&hostDNSAddress,inTargetAddressAndPort);
999 sndCall.opt.buf = nil;
1000 sndCall.opt.len = 0;
1001 sndCall.udata.buf = nil;
1002 sndCall.udata.len = 0;
1003 sndCall.sequence = 0;
1004
1005 // Connect!
1006
1007 PrepareForAsyncOperation(theSocketStruct,T_CONNECT);
1008
1009 theOTResult = ::OTConnect(theSocketStruct->mEndPointRef,&sndCall,nil);
1010
1011 if (theOTResult == kOTNoDataErr)
1012 {
1013 theOTResult = noErr;
1014 }
1015
1016 SetErrorMessageAndLongIntAndBailIfError(theOTResult,"MacSocket_connect: Can't connect OT endpoint, OTConnect() = ",theOTResult);
1017
1018 BailIfError(MyBusyWait(theSocketStruct,false,&theOTResult,&(theSocketStruct->mReceivedTConnect)));
1019
1020 if (theOTResult == kMacSocket_TimeoutErr)
1021 {
1022 SetErrorMessageAndBail("MacSocket_connect: Can't connect OT endpoint, OTConnect() = kMacSocket_TimeoutErr");
1023 }
1024
1025 else
1026 {
1027 SetErrorMessageAndLongIntAndBailIfError(theOTResult,"MacSocket_connect: Can't connect OT endpoint, OTConnect() = ",theOTResult);
1028 }
1029
1030 theOTResult = ::OTRcvConnect(theSocketStruct->mEndPointRef,nil);
1031
1032 SetErrorMessageAndLongIntAndBailIfError(theOTResult,"MacSocket_connect: Can't complete connect on OT endpoint, OTRcvConnect() = ",theOTResult);
1033
1034
1035 errCode = noErr;
1036
1037
1038 #ifdef MACSOCKET_DEBUG
1039 printf("MacSocket_connect: connect completed\n");
1040 #endif
1041
1042 EXITPOINT:
1043
1044 if (theSocketStruct != nil)
1045 {
1046 theSocketStruct->mLastError = noErr;
1047
1048 CopyCStrToCStr("",theSocketStruct->mErrMessage,sizeof(theSocketStruct->mErrMessage));
1049
1050 if (errCode != noErr)
1051 {
1052 theSocketStruct->mLastError = errCode;
1053
1054 CopyCStrToCStr(GetErrorMessage(),theSocketStruct->mErrMessage,sizeof(theSocketStruct->mErrMessage));
1055 }
1056 }
1057
1058 errno = errCode;
1059
1060 return(errCode);
1061 }
1062
1063
1064
1065
1066 // Close a connection
1067
MacSocket_close(const int inSocketNum)1068 OSErr MacSocket_close(const int inSocketNum)
1069 {
1070 OSErr errCode = noErr;
1071 SocketStruct *theSocketStruct = nil;
1072
1073
1074 if (!SocketIndexIsValid(inSocketNum))
1075 {
1076 SetErrorMessageAndBail("MacSocket_close: Invalid socket number specified");
1077 }
1078
1079
1080 theSocketStruct = &(sSockets[inSocketNum]);
1081
1082 if (theSocketStruct->mEndPointRef != kOTInvalidEndpointRef)
1083 {
1084 OTResult theOTResult = noErr;
1085
1086 // Try to play nice
1087
1088 if (theSocketStruct->mReceivedTOrdRel)
1089 {
1090 // Already did an OTRcvOrderlyDisconnect() in the notifier
1091
1092 if (theSocketStruct->mLocalEndIsConnected)
1093 {
1094 theOTResult = ::OTSndOrderlyDisconnect(theSocketStruct->mEndPointRef);
1095
1096 theSocketStruct->mLocalEndIsConnected = false;
1097 }
1098 }
1099
1100 else if (theSocketStruct->mLocalEndIsConnected)
1101 {
1102 theOTResult = ::OTSndOrderlyDisconnect(theSocketStruct->mEndPointRef);
1103
1104 theSocketStruct->mLocalEndIsConnected = false;
1105
1106 // Wait for other end to hang up too!
1107
1108 // PrepareForAsyncOperation(theSocketStruct,T_ORDREL);
1109 //
1110 // errCode = MyBusyWait(theSocketStruct,false,&theOTResult,&(theSocketStruct->mReceivedTOrdRel));
1111 }
1112
1113
1114 if (theOTResult != noErr)
1115 {
1116 ::OTCloseProvider(theSocketStruct->mEndPointRef);
1117 }
1118
1119 else
1120 {
1121 theOTResult = ::OTCloseProvider(theSocketStruct->mEndPointRef);
1122 }
1123
1124 theSocketStruct->mEndPointRef = kOTInvalidEndpointRef;
1125
1126 errCode = theOTResult;
1127 }
1128
1129
1130 theSocketStruct->mIsInUse = false;
1131
1132
1133 EXITPOINT:
1134
1135 if (theSocketStruct != nil)
1136 {
1137 theSocketStruct->mLastError = noErr;
1138
1139 CopyCStrToCStr("",theSocketStruct->mErrMessage,sizeof(theSocketStruct->mErrMessage));
1140
1141 if (errCode != noErr)
1142 {
1143 theSocketStruct->mLastError = errCode;
1144
1145 CopyCStrToCStr(GetErrorMessage(),theSocketStruct->mErrMessage,sizeof(theSocketStruct->mErrMessage));
1146 }
1147 }
1148
1149 errno = errCode;
1150
1151 return(errCode);
1152 }
1153
1154
1155
1156
1157 // Receive some bytes
1158
MacSocket_recv(const int inSocketNum,void * outBuff,int outBuffLength,const Boolean inBlock)1159 int MacSocket_recv(const int inSocketNum,void *outBuff,int outBuffLength,const Boolean inBlock)
1160 {
1161 OSErr errCode = noErr;
1162 int totalBytesRead = 0;
1163 SocketStruct *theSocketStruct = nil;
1164
1165
1166 SetErrorMessageAndBailIfNil(outBuff,"MacSocket_recv: Bad parameter, outBuff = nil");
1167
1168 if (outBuffLength <= 0)
1169 {
1170 SetErrorMessageAndBail("MacSocket_recv: Bad parameter, outBuffLength <= 0");
1171 }
1172
1173 if (!SocketIndexIsValid(inSocketNum))
1174 {
1175 SetErrorMessageAndBail("MacSocket_recv: Invalid socket number specified");
1176 }
1177
1178 theSocketStruct = &(sSockets[inSocketNum]);
1179
1180 if (!theSocketStruct->mLocalEndIsConnected)
1181 {
1182 SetErrorMessageAndBail("MacSocket_recv: Socket not connected");
1183 }
1184
1185 if (theSocketStruct->mReceivedTOrdRel)
1186 {
1187 totalBytesRead = 0;
1188
1189 goto EXITPOINT;
1190 }
1191
1192
1193 PrepareForAsyncOperation(theSocketStruct,0);
1194
1195 for (;;)
1196 {
1197 int bytesRead;
1198 OTResult theOTResult;
1199
1200
1201 theOTResult = ::OTRcv(theSocketStruct->mEndPointRef,(void *) ((unsigned long) outBuff + (unsigned long) totalBytesRead),outBuffLength - totalBytesRead,nil);
1202
1203 if (theOTResult >= 0)
1204 {
1205 bytesRead = theOTResult;
1206
1207 #ifdef MACSOCKET_DEBUG
1208 printf("MacSocket_recv: read %d bytes in part\n",bytesRead);
1209 #endif
1210 }
1211
1212 else if (theOTResult == kOTNoDataErr)
1213 {
1214 bytesRead = 0;
1215 }
1216
1217 else
1218 {
1219 SetErrorMessageAndLongIntAndBail("MacSocket_recv: Can't receive OT data, OTRcv() = ",theOTResult);
1220 }
1221
1222
1223 totalBytesRead += bytesRead;
1224
1225
1226 if (totalBytesRead <= 0)
1227 {
1228 if (theSocketStruct->mReceivedTOrdRel)
1229 {
1230 break;
1231 }
1232
1233 // This seems pretty stupid to me now. Maybe I'll delete this blocking garbage.
1234
1235 if (inBlock)
1236 {
1237 if (TimeoutElapsed(theSocketStruct))
1238 {
1239 SetErrorCodeAndMessageAndBail(kMacSocket_TimeoutErr,"MacSocket_recv: Receive operation timed-out");
1240 }
1241
1242 if (theSocketStruct->mIdleWaitCallback != nil)
1243 {
1244 theOTResult = (*(theSocketStruct->mIdleWaitCallback))(theSocketStruct->mUserRefPtr);
1245
1246 SetErrorMessageAndBailIfError(theOTResult,"MacSocket_recv: User cancelled operation");
1247 }
1248
1249 continue;
1250 }
1251 }
1252
1253
1254 break;
1255 }
1256
1257 errCode = noErr;
1258
1259
1260 #ifdef MACSOCKET_DEBUG
1261 printf("MacSocket_recv: read %d bytes in total\n",totalBytesRead);
1262 #endif
1263
1264
1265 EXITPOINT:
1266
1267 if (theSocketStruct != nil)
1268 {
1269 theSocketStruct->mLastError = noErr;
1270
1271 CopyCStrToCStr("",theSocketStruct->mErrMessage,sizeof(theSocketStruct->mErrMessage));
1272
1273 if (errCode != noErr)
1274 {
1275 theSocketStruct->mLastError = errCode;
1276
1277 CopyCStrToCStr(GetErrorMessage(),theSocketStruct->mErrMessage,sizeof(theSocketStruct->mErrMessage));
1278 }
1279 }
1280
1281 errno = errCode;
1282
1283 return(totalBytesRead);
1284 }
1285
1286
1287
1288 // Send some bytes
1289
MacSocket_send(const int inSocketNum,const void * inBuff,int inBuffLength)1290 int MacSocket_send(const int inSocketNum,const void *inBuff,int inBuffLength)
1291 {
1292 OSErr errCode = noErr;
1293 int bytesSent = 0;
1294 SocketStruct *theSocketStruct = nil;
1295
1296
1297 SetErrorMessageAndBailIfNil(inBuff,"MacSocket_send: Bad parameter, inBuff = nil");
1298
1299 if (inBuffLength <= 0)
1300 {
1301 SetErrorMessageAndBail("MacSocket_send: Bad parameter, inBuffLength <= 0");
1302 }
1303
1304 if (!SocketIndexIsValid(inSocketNum))
1305 {
1306 SetErrorMessageAndBail("MacSocket_send: Invalid socket number specified");
1307 }
1308
1309
1310 theSocketStruct = &(sSockets[inSocketNum]);
1311
1312 if (!theSocketStruct->mLocalEndIsConnected)
1313 {
1314 SetErrorMessageAndBail("MacSocket_send: Socket not connected");
1315 }
1316
1317
1318 OTResult theOTResult;
1319
1320
1321 PrepareForAsyncOperation(theSocketStruct,0);
1322
1323 while (bytesSent < inBuffLength)
1324 {
1325 if (theSocketStruct->mIdleWaitCallback != nil)
1326 {
1327 theOTResult = (*(theSocketStruct->mIdleWaitCallback))(theSocketStruct->mUserRefPtr);
1328
1329 SetErrorMessageAndBailIfError(theOTResult,"MacSocket_send: User cancelled");
1330 }
1331
1332
1333 theOTResult = ::OTSnd(theSocketStruct->mEndPointRef,(void *) ((unsigned long) inBuff + bytesSent),inBuffLength - bytesSent,0);
1334
1335 if (theOTResult >= 0)
1336 {
1337 bytesSent += theOTResult;
1338
1339 theOTResult = noErr;
1340
1341 // Reset timer....
1342
1343 PrepareForAsyncOperation(theSocketStruct,0);
1344 }
1345
1346 if (theOTResult == kOTFlowErr)
1347 {
1348 if (TimeoutElapsed(theSocketStruct))
1349 {
1350 SetErrorCodeAndMessageAndBail(kMacSocket_TimeoutErr,"MacSocket_send: Send timed-out")
1351 }
1352
1353 theOTResult = noErr;
1354 }
1355
1356 SetErrorMessageAndLongIntAndBailIfError(theOTResult,"MacSocket_send: Can't send OT data, OTSnd() = ",theOTResult);
1357 }
1358
1359
1360 errCode = noErr;
1361
1362 #ifdef MACSOCKET_DEBUG
1363 printf("MacSocket_send: sent %d bytes\n",bytesSent);
1364 #endif
1365
1366
1367 EXITPOINT:
1368
1369 if (theSocketStruct != nil)
1370 {
1371 theSocketStruct->mLastError = noErr;
1372
1373 CopyCStrToCStr("",theSocketStruct->mErrMessage,sizeof(theSocketStruct->mErrMessage));
1374
1375 if (errCode != noErr)
1376 {
1377 theSocketStruct->mLastError = errCode;
1378
1379 CopyCStrToCStr(GetErrorMessage(),theSocketStruct->mErrMessage,sizeof(theSocketStruct->mErrMessage));
1380 }
1381 }
1382
1383 if (errCode != noErr)
1384 {
1385 ::SysBeep(1);
1386 }
1387
1388 errno = errCode;
1389
1390 return(bytesSent);
1391 }
1392
1393
1394
1395
1396
NegotiateIPReuseAddrOption(EndpointRef inEndpoint,const Boolean inEnableReuseIP)1397 static OSStatus NegotiateIPReuseAddrOption(EndpointRef inEndpoint,const Boolean inEnableReuseIP)
1398 {
1399 OSStatus errCode;
1400 UInt8 buf[kOTFourByteOptionSize];
1401 TOption* theOTOption;
1402 TOptMgmt theOTRequest;
1403 TOptMgmt theOTResult;
1404
1405
1406 if (!OTIsSynchronous(inEndpoint))
1407 {
1408 SetErrorMessageAndBail("NegotiateIPReuseAddrOption: Open Transport endpoint is not synchronous");
1409 }
1410
1411 theOTRequest.opt.buf = buf;
1412 theOTRequest.opt.len = sizeof(buf);
1413 theOTRequest.flags = T_NEGOTIATE;
1414
1415 theOTResult.opt.buf = buf;
1416 theOTResult.opt.maxlen = kOTFourByteOptionSize;
1417
1418
1419 theOTOption = (TOption *) buf;
1420
1421 theOTOption->level = INET_IP;
1422 theOTOption->name = IP_REUSEADDR;
1423 theOTOption->len = kOTFourByteOptionSize;
1424 theOTOption->status = 0;
1425 *((UInt32 *) (theOTOption->value)) = inEnableReuseIP;
1426
1427 errCode = ::OTOptionManagement(inEndpoint,&theOTRequest,&theOTResult);
1428
1429 if (errCode == kOTNoError)
1430 {
1431 if (theOTOption->status != T_SUCCESS)
1432 {
1433 errCode = theOTOption->status;
1434 }
1435
1436 else
1437 {
1438 errCode = kOTNoError;
1439 }
1440 }
1441
1442
1443 EXITPOINT:
1444
1445 errno = errCode;
1446
1447 return(errCode);
1448 }
1449
1450
1451
1452
1453
1454 // Some rough notes....
1455
1456
1457
1458 // OTAckSends(ep);
1459 // OTAckSends(ep) // enable AckSend option
1460 // ......
1461 // buf = OTAllocMem( nbytes); // Allocate nbytes of memory from OT
1462 // OTSnd(ep, buf, nbytes, 0); // send a packet
1463 // ......
1464 // NotifyProc( .... void* theParam) // Notifier Proc
1465 // case T_MEMORYRELEASED: // process event
1466 // OTFreeMem( theParam); // free up memory
1467 // break;
1468
1469
1470
1471 /*
1472 struct InetInterfaceInfo
1473 {
1474 InetHost fAddress;
1475 InetHost fNetmask;
1476 InetHost fBroadcastAddr;
1477 InetHost fDefaultGatewayAddr;
1478 InetHost fDNSAddr;
1479 UInt16 fVersion;
1480 UInt16 fHWAddrLen;
1481 UInt8* fHWAddr;
1482 UInt32 fIfMTU;
1483 UInt8* fReservedPtrs[2];
1484 InetDomainName fDomainName;
1485 UInt32 fIPSecondaryCount;
1486 UInt8 fReserved[252];
1487 };
1488 typedef struct InetInterfaceInfo InetInterfaceInfo;
1489
1490
1491
1492 ((InetAddress *) addr.buf)->fHost
1493
1494 struct TBind
1495 {
1496 TNetbuf addr;
1497 OTQLen qlen;
1498 };
1499
1500 typedef struct TBind TBind;
1501
1502 struct TNetbuf
1503 {
1504 size_t maxlen;
1505 size_t len;
1506 UInt8* buf;
1507 };
1508
1509 typedef struct TNetbuf TNetbuf;
1510
1511
1512 struct InetAddress
1513 {
1514 OTAddressType fAddressType; // always AF_INET
1515 InetPort fPort; // Port number
1516 InetHost fHost; // Host address in net byte order
1517 UInt8 fUnused[8]; // Traditional unused bytes
1518 };
1519 typedef struct InetAddress InetAddress;
1520 */
1521
1522
1523
1524 /*
1525 static pascal void Notifier(void* context, OTEventCode event, OTResult result, void* cookie)
1526 {
1527 EPInfo* epi = (EPInfo*) context;
1528
1529 switch (event)
1530 {
1531 case T_LISTEN:
1532 {
1533 DoListenAccept();
1534 return;
1535 }
1536
1537 case T_ACCEPTCOMPLETE:
1538 {
1539 if (result != kOTNoError)
1540 DBAlert1("Notifier: T_ACCEPTCOMPLETE - result %d",result);
1541 return;
1542 }
1543
1544 case T_PASSCON:
1545 {
1546 if (result != kOTNoError)
1547 {
1548 DBAlert1("Notifier: T_PASSCON result %d", result);
1549 return;
1550 }
1551
1552 OTAtomicAdd32(1, &gCntrConnections);
1553 OTAtomicAdd32(1, &gCntrTotalConnections);
1554 OTAtomicAdd32(1, &gCntrIntervalConnects);
1555
1556 if ( OTAtomicSetBit(&epi->stateFlags, kPassconBit) != 0 )
1557 {
1558 ReadData(epi);
1559 }
1560
1561 return;
1562 }
1563
1564 case T_DATA:
1565 {
1566 if ( OTAtomicSetBit(&epi->stateFlags, kPassconBit) != 0 )
1567 {
1568 ReadData(epi);
1569 }
1570
1571 return;
1572 }
1573
1574 case T_GODATA:
1575 {
1576 SendData(epi);
1577 return;
1578 }
1579
1580 case T_DISCONNECT:
1581 {
1582 DoRcvDisconnect(epi);
1583 return;
1584 }
1585
1586 case T_DISCONNECTCOMPLETE:
1587 {
1588 if (result != kOTNoError)
1589 DBAlert1("Notifier: T_DISCONNECT_COMPLETE result %d",result);
1590
1591 return;
1592 }
1593
1594 case T_MEMORYRELEASED:
1595 {
1596 OTAtomicAdd32(-1, &epi->outstandingSends);
1597 return;
1598 }
1599
1600 default:
1601 {
1602 DBAlert1("Notifier: unknown event <%x>", event);
1603 return;
1604 }
1605 }
1606 }
1607 */
1608