Constification needed.
[openssl.git] / MacOS / GetHTTPS.src / MacSocket.cpp
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 */