📄 macsocket.cpp
字号:
/* * A simple socket-like package. * This could undoubtedly be improved, since it does polling and busy-waiting. * At least it uses asynch I/O and implements timeouts! * * Other funkiness includes the use of my own (possibly brain-damaged) error-handling infrastructure. * * -Roy Wood (roy@centricsystems.ca) * *//* ==================================================================== * Copyright (c) 1998-1999 The OpenSSL Project. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. All advertising materials mentioning features or use of this * software must display the following acknowledgment: * "This product includes software developed by the OpenSSL Project * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" * * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to * endorse or promote products derived from this software without * prior written permission. For written permission, please contact * openssl-core@openssl.org. * * 5. Products derived from this software may not be called "OpenSSL" * nor may "OpenSSL" appear in their names without prior written * permission of the OpenSSL Project. * * 6. Redistributions of any form whatsoever must retain the following * acknowledgment: * "This product includes software developed by the OpenSSL Project * for use in the OpenSSL Toolkit (http://www.openssl.org/)" * * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * ==================================================================== * * This product includes cryptographic software written by Eric Young * (eay@cryptsoft.com). This product includes software written by Tim * Hudson (tjh@cryptsoft.com). * */ #include "MacSocket.h"#include <Threads.h>#include <OpenTransport.h>#include <OpenTpTInternet.h>#include <OpenTptClient.h>#include "CPStringUtils.hpp"#include "ErrorHandling.hpp"// #define MACSOCKET_DEBUG 1#ifdef MACSOCKET_DEBUG #include <stdio.h>#endifextern int errno;#define kMaxNumSockets 4struct SocketStruct{ Boolean mIsInUse; Boolean mEndpointIsBound; Boolean mLocalEndIsConnected; Boolean mRemoteEndIsConnected; Boolean mReceivedTOpenComplete; Boolean mReceivedTBindComplete; Boolean mReceivedTConnect; Boolean mReceivedTListen; Boolean mReceivedTPassCon; Boolean mReceivedTDisconnect; Boolean mReceivedTOrdRel; Boolean mReceivedTDisconnectComplete; long mTimeoutTicks; long mOperationStartTicks; MacSocket_IdleWaitCallback mIdleWaitCallback; void *mUserRefPtr; OTEventCode mExpectedCode; OTResult mAsyncOperationResult; EndpointRef mEndPointRef; TBind *mBindRequestedAddrInfo; TBind *mAssignedAddrInfo; TCall *mRemoteAddrInfo; Boolean mReadyToReadData; Boolean mReadyToWriteData; Ptr mReadBuffer; Ptr mWriteBuffer; int mLastError; char mErrMessage[256];};typedef struct SocketStruct SocketStruct;static SocketStruct sSockets[kMaxNumSockets];static Boolean sSocketsSetup = false;static OSErr MyBusyWait(SocketStruct *ioSocket,Boolean returnImmediatelyOnError,OTResult *outOTResult,Boolean *inAsyncOperationCompleteFlag);static pascal void OTNonYieldingNotifier(void *contextPtr,OTEventCode code,OTResult result,void *cookie);static Boolean SocketIndexIsValid(const int inSocketNum);static void InitSocket(SocketStruct *ioSocket);static void PrepareForAsyncOperation(SocketStruct *ioSocket,const OTEventCode inExpectedCode);static Boolean TimeoutElapsed(const SocketStruct *inSocket);static OSStatus NegotiateIPReuseAddrOption(EndpointRef inEndpoint,const Boolean inEnableReuseIP);void MacSocket_GetSocketErrorInfo(const int inSocketNum,int *outSocketErrCode,char *outSocketErrString,const int inSocketErrStringMaxLength){ if (outSocketErrCode != nil) { *outSocketErrCode = -1; } if (outSocketErrString != nil) { CopyCStrToCStr("",outSocketErrString,inSocketErrStringMaxLength); } if (SocketIndexIsValid(inSocketNum)) { SocketStruct *theSocketStruct = &(sSockets[inSocketNum]); if (outSocketErrCode != nil) { *outSocketErrCode = theSocketStruct->mLastError; } if (outSocketErrString != nil) { CopyCStrToCStr(theSocketStruct->mErrMessage,outSocketErrString,inSocketErrStringMaxLength); } }}void MacSocket_SetUserRefPtr(const int inSocketNum,void *inNewRefPtr){ if (SocketIndexIsValid(inSocketNum)) { SocketStruct *theSocketStruct = &(sSockets[inSocketNum]); theSocketStruct->mUserRefPtr = inNewRefPtr; }}void MacSocket_GetLocalIPAndPort(const int inSocketNum,char *outIPAndPort,const int inIPAndPortLength){ if (outIPAndPort != nil && SocketIndexIsValid(inSocketNum)) { char tempString[256]; SocketStruct *theSocketStruct = &(sSockets[inSocketNum]); CopyCStrToCStr("",tempString,sizeof(tempString)); if (theSocketStruct->mAssignedAddrInfo != nil) { InetAddress *theInetAddress = (InetAddress *) theSocketStruct->mAssignedAddrInfo->addr.buf; InetHost theInetHost = theInetAddress->fHost; if (theInetHost == 0) { InetInterfaceInfo theInetInterfaceInfo; if (::OTInetGetInterfaceInfo(&theInetInterfaceInfo,kDefaultInetInterface) == noErr) { theInetHost = theInetInterfaceInfo.fAddress; } } ::OTInetHostToString(theInetHost,tempString); ConcatCStrToCStr(":",tempString,sizeof(tempString)); ConcatLongIntToCStr(theInetAddress->fPort,tempString,sizeof(tempString)); } CopyCStrToCStr(tempString,outIPAndPort,inIPAndPortLength); }}void MacSocket_GetRemoteIPAndPort(const int inSocketNum,char *outIPAndPort,const int inIPAndPortLength){ if (outIPAndPort != nil && SocketIndexIsValid(inSocketNum)) { char tempString[256]; SocketStruct *theSocketStruct = &(sSockets[inSocketNum]); CopyCStrToCStr("",tempString,sizeof(tempString)); if (theSocketStruct->mRemoteAddrInfo != nil) { InetAddress *theInetAddress = (InetAddress *) theSocketStruct->mRemoteAddrInfo->addr.buf; InetHost theInetHost = theInetAddress->fHost; if (theInetHost == 0) { InetInterfaceInfo theInetInterfaceInfo; if (::OTInetGetInterfaceInfo(&theInetInterfaceInfo,kDefaultInetInterface) == noErr) { theInetHost = theInetInterfaceInfo.fAddress; } } ::OTInetHostToString(theInetHost,tempString); ConcatCStrToCStr(":",tempString,sizeof(tempString)); ConcatLongIntToCStr(theInetAddress->fPort,tempString,sizeof(tempString)); } CopyCStrToCStr(tempString,outIPAndPort,inIPAndPortLength); }}Boolean MacSocket_RemoteEndIsClosing(const int inSocketNum){Boolean theResult = false; if (SocketIndexIsValid(inSocketNum)) { SocketStruct *theSocketStruct = &(sSockets[inSocketNum]); theResult = theSocketStruct->mReceivedTOrdRel; } return(theResult);}Boolean MacSocket_ListenCompleted(const int inSocketNum){Boolean theResult = false; if (SocketIndexIsValid(inSocketNum)) { SocketStruct *theSocketStruct = &(sSockets[inSocketNum]); theResult = theSocketStruct->mReceivedTPassCon; } return(theResult);}Boolean MacSocket_RemoteEndIsOpen(const int inSocketNum){ if (SocketIndexIsValid(inSocketNum)) { SocketStruct *theSocketStruct = &(sSockets[inSocketNum]); return(theSocketStruct->mRemoteEndIsConnected); } else { return(false); }}Boolean MacSocket_LocalEndIsOpen(const int inSocketNum){ if (SocketIndexIsValid(inSocketNum)) { SocketStruct *theSocketStruct = &(sSockets[inSocketNum]); return(theSocketStruct->mLocalEndIsConnected); } else { return(false); }}static Boolean TimeoutElapsed(const SocketStruct *inSocket){Boolean timeIsUp = false; if (inSocket != nil && inSocket->mTimeoutTicks > 0 && ::TickCount() > inSocket->mOperationStartTicks + inSocket->mTimeoutTicks) { timeIsUp = true; } return(timeIsUp);}static Boolean SocketIndexIsValid(const int inSocketNum){ if (inSocketNum >= 0 && inSocketNum < kMaxNumSockets && sSockets[inSocketNum].mEndPointRef != kOTInvalidEndpointRef) { return(true); } else { return(false); }}static void InitSocket(SocketStruct *ioSocket){ ioSocket->mIsInUse = false; ioSocket->mEndpointIsBound = false; ioSocket->mLocalEndIsConnected = false; ioSocket->mRemoteEndIsConnected = false; ioSocket->mReceivedTOpenComplete = false; ioSocket->mReceivedTBindComplete = false; ioSocket->mReceivedTConnect = false; ioSocket->mReceivedTListen = false; ioSocket->mReceivedTPassCon = false; ioSocket->mReceivedTDisconnect = false; ioSocket->mReceivedTOrdRel = false; ioSocket->mReceivedTDisconnectComplete = false; ioSocket->mTimeoutTicks = 30 * 60; ioSocket->mOperationStartTicks = -1; ioSocket->mIdleWaitCallback = nil; ioSocket->mUserRefPtr = nil; ioSocket->mExpectedCode = 0; ioSocket->mAsyncOperationResult = noErr; ioSocket->mEndPointRef = kOTInvalidEndpointRef; ioSocket->mBindRequestedAddrInfo = nil; ioSocket->mAssignedAddrInfo = nil; ioSocket->mRemoteAddrInfo = nil; ioSocket->mReadyToReadData = false; ioSocket->mReadyToWriteData = true; ioSocket->mReadBuffer = nil; ioSocket->mWriteBuffer = nil; ioSocket->mLastError = noErr; CopyCStrToCStr("",ioSocket->mErrMessage,sizeof(ioSocket->mErrMessage));}static void PrepareForAsyncOperation(SocketStruct *ioSocket,const OTEventCode inExpectedCode){ ioSocket->mOperationStartTicks = ::TickCount(); ioSocket->mAsyncOperationResult = noErr; ioSocket->mExpectedCode = inExpectedCode;}// The wait function....static OSErr MyBusyWait(SocketStruct *ioSocket,Boolean returnImmediatelyOnError,OTResult *outOTResult,Boolean *inAsyncOperationCompleteFlag){OSErr errCode = noErr;OTResult theOTResult = noErr; SetErrorMessageAndBailIfNil(ioSocket,"MyBusyWait: Bad parameter, ioSocket = nil"); SetErrorMessageAndBailIfNil(inAsyncOperationCompleteFlag,"MyBusyWait: Bad parameter, inAsyncOperationCompleteFlag = nil"); for (;;) { if (*inAsyncOperationCompleteFlag) { theOTResult = ioSocket->mAsyncOperationResult; break; } if (ioSocket->mIdleWaitCallback != nil) { theOTResult = (*(ioSocket->mIdleWaitCallback))(ioSocket->mUserRefPtr); if (theOTResult != noErr && returnImmediatelyOnError) { break; } } if (TimeoutElapsed(ioSocket)) { theOTResult = kMacSocket_TimeoutErr; break; } }EXITPOINT: if (outOTResult != nil) { *outOTResult = theOTResult; } return(errCode);}// I used to do thread switching, but stopped. It could easily be rolled back in though....static pascal void OTNonYieldingNotifier(void *contextPtr,OTEventCode code,OTResult result,void *cookie){SocketStruct *theSocketStruct = (SocketStruct *) contextPtr; if (theSocketStruct != nil) { if (theSocketStruct->mExpectedCode != 0 && code == theSocketStruct->mExpectedCode) { theSocketStruct->mAsyncOperationResult = result; theSocketStruct->mExpectedCode = 0; } switch (code) { case T_OPENCOMPLETE: { theSocketStruct->mReceivedTOpenComplete = true; theSocketStruct->mEndPointRef = (EndpointRef) cookie; break; } case T_BINDCOMPLETE: { theSocketStruct->mReceivedTBindComplete = true; break; } case T_CONNECT: { theSocketStruct->mReceivedTConnect = true; theSocketStruct->mLocalEndIsConnected = true; theSocketStruct->mRemoteEndIsConnected = true; break; } case T_LISTEN: { theSocketStruct->mReceivedTListen = true;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -