📄 ot_tcp.cp
字号:
if ( mNewConnection )
{
mNewConnection->done();
HX_RELEASE(mNewConnection);
}
mNewConnection = conn::actual_new_socket(HX_TCP_SOCKET);
mNewConnection->AddRef();
// we can wait here, because we should not be called
// from deffered task time.
theErr = mNewConnection->SetupEndpoint(TRUE);
}
return theErr;
}
HX_RESULT OT_TCP::resolve_address (void)
{
//dprintf("this:%X OT_TCP::resulve_address\n", this);
mState = TCP_STATE_RESOLVE_DNS;
return ::OTInetStringToAddress(mDNSRef, mRemoteHostName, &mHInfoOT);
}
HX_RESULT
OT_TCP::open_resolver(void)
{
//dprintf("this:%X OT_TCP::open_resolver\n", this);
mState = TCP_STATE_OPEN_RESOLVER;
#ifdef USE_DEFERRED_IMPL
HX_RESULT theErr = ::OTAsyncOpenInternetServices(kDefaultInternetServicesPath, 0,UDPTCPNotifyProc, this);
#else
#ifdef _CARBON
HX_RESULT theErr = ::OTAsyncOpenInternetServicesInContext(kDefaultInternetServicesPath,
0,::NewOTNotifyUPP(TCPNotifyProc), this, NULL);
#else
HX_RESULT theErr = ::OTAsyncOpenInternetServices(kDefaultInternetServicesPath,
0,TCPNotifyProc, this);
#endif
#endif
if (theErr != HXR_OK)
theErr = HXR_BIND;
return theErr;
}
void
OT_TCP::close_resolver(void)
{
//dprintf("this:%X OT_TCP::close_resolver\n", this);
if(mDNSRef != 0)
{
::OTRemoveNotifier(mDNSRef); // remove the DNR notification function
::OTCloseProvider(mDNSRef); // close the DNR endpoint
mDNSRef = 0;
}
}
HX_RESULT
OT_TCP::open_socket(void)
{
//dprintf("this:%X OT_TCP::open_socket\n", this);
HX_RESULT theErr = HXR_OK;
// Open TCP endpoint
mState = TCP_STATE_OPEN_SOCKET;
#ifdef USE_DEFERRED_IMPL
theErr = ::OTAsyncOpenEndpoint(OTCreateConfiguration(kTCPName), 0,NULL, UDPTCPNotifyProc, this);
#else
#ifdef _CARBON
theErr = ::OTAsyncOpenEndpointInContext(OTCreateConfiguration(kTCPName), 0,NULL,
::NewOTNotifyUPP(TCPNotifyProc), this, NULL);
#else
theErr = ::OTAsyncOpenEndpoint(OTCreateConfiguration(kTCPName), 0,NULL,
TCPNotifyProc, this);
#endif
#endif
return theErr;
}
HX_RESULT
OT_TCP::do_bind (void)
{
//dprintf("this:%X OT_TCP::do_bind\n", this);
HX_RESULT theErr = HXR_OK;
mState = TCP_STATE_BIND_SOCKET;
mBindRet.addr.maxlen = sizeof(struct InetAddress);
mBindRet.addr.len = sizeof(struct InetAddress);
mBindRet.addr.buf = (unsigned char *) &mAddr;
// bind provider to return structure
theErr = ::OTBind(mRef, nil, &mBindRet);
if(theErr == kOTNoDataErr)
theErr = HXR_OK;
if(theErr)
theErr = HXR_BIND;
return theErr;
}
HX_RESULT
OT_TCP::do_connect(void)
{
//dprintf("this:%X OT_TCP::do_connect\n", this);
mState = TCP_STATE_CONNECT_SOCKET;
::memset(&mCall,0,sizeof(TCall));
mCall.addr.buf = (UInt8 *)&mAddr;
mCall.addr.maxlen = sizeof(InetAddress);
mCall.addr.len = sizeof(InetAddress);
// set up address of remote host
::OTInitInetAddress((InetAddress*)mCall.addr.buf, mRemotePort, mRemoteHost);
// connect client to remote endpoint
HX_RESULT theErr = ::OTConnect(mRef, &mCall, nil);
if(theErr == kOTNoDataErr)
theErr = HXR_OK;
if(theErr)
theErr = HXR_SERVER_DISCONNECTED;
return theErr;
}
/*----------------------------------------------------------------------------
TCPNotifyProc
Open Transport notifier proc for TCP streams.
Entry: s = pointer to stream.
code = OT event code.
result = OT result.
cookie = OT cookie.
----------------------------------------------------------------------------*/
pascal void OT_TCP::TCPNotifyProc (
void *stream,
OTEventCode code,
OTResult result,
void *cookie)
{
//dprintf("this:%X OT_TCP::TCPNotifyProc cookie:%X code:%X result:%X\n", stream, cookie, code, result);
HX_RESULT theErr = HXR_OK;
OT_TCP* s = (OT_TCP*) stream;
HXMM_INTERRUPTON();
s->ProcessCmd(code, result, cookie);
HXMM_INTERRUPTOFF();
return;
}
void OT_TCP::ProcessCmd(OTEventCode code, OTResult result, void* cookie)
{
HX_RESULT theErr = HXR_OK;
switch (code)
{
case T_OPENCOMPLETE:
{
//dprintf("this:%X T_OPENCOMPLETE ", this);
// check if T_OPENCOMPLETE was for DNS or socket
if(mState == TCP_STATE_OPEN_RESOLVER)
{
//dprintf(" TCP_STATE_OPEN_RESOLVER\n");
theErr = result;
if(!theErr)
{
// save DNS provider endpoint ref
mDNSRef = (InetSvcRef) cookie;
mDNSOpen = TRUE;
theErr = resolve_address();
}
else
theErr = HXR_BIND;
}
else if(mState == TCP_STATE_OPEN_SOCKET)
{
// DebugWrite("T_OPENCOMPLETE TCP_STATE_OPEN_SOCKET");
//dprintf(" TCP_STATE_OPEN_SOCKET\n");
theErr = result;
if(!theErr)
{
// save TCP provider endpoint ref
mRef = (EndpointRef) cookie;
mSocketOpen = TRUE;
theErr = do_bind();
}
else
theErr = HXR_SOCKET_CREATE;
}
else if (mState == TCP_STATE_OPEN_LISTEN)
{
//dprintf(" TCP_STATE_OPEN_LISTEN\n");
theErr = result;
if ( !theErr )
{
mRef = (EndpointRef) cookie;
mSocketOpen = TRUE;
mCode = code;
mComplete = true;
}
else
theErr = HXR_SOCKET_CREATE;
}
else if (mState == TCP_STATE_OPEN_ACCEPT)
{
//dprintf(" TCP_STATE_OPEN_ACCEPT\n");
theErr = result;
if ( !theErr )
{
mRef = (EndpointRef) cookie;
mSocketOpen = TRUE;
mCode = code;
mState = TCP_STATE_READY;
mComplete = true;
}
else
theErr = HXR_SOCKET_CREATE;
}
break;
}
case T_DNRSTRINGTOADDRCOMPLETE:
case T_DNRADDRTONAMECOMPLETE:
{
// DebugWrite("T_DNRSTRINGTOADDRCOMPLETE");
//dprintf("this:%X T_DNRSTRINGTOADDRCOMPLETE\n", this);
theErr = result;
if(!theErr)
{
// extract DNS result from InetHostInfo struct
mRemoteHost = mHInfoOT.addrs[0];
// close the DNS endpoint
// close_resolver();
// open a TCP socket
// next message should be T_OPEN_COMPLETE
theErr = open_socket();
}
else
theErr = HXR_BIND;
break;
}
case T_BINDCOMPLETE:
{
// DebugWrite("T_BINDCOMPLETE");
//dprintf("this:%X T_BINDCOMPLETE ", this);
if ( mState == TCP_STATE_BIND_LISTEN )
{
//dprintf(" - Listen\n");
theErr = result;
if ( !theErr )
{
mCode = code;
mComplete = true;
}
else
{
theErr = HXR_BIND;
}
}
else
{
//dprintf(" - Regular\n");
theErr = result;
if(!theErr)
{
mComplete = true;
// get inet address
InetAddress *inetAddr = (InetAddress*)mBindRet.addr.buf;
// save local port we are bound to
mLocalPort = inetAddr->fPort;
// now connect to the remote host
theErr = do_connect();
}
else
theErr = HXR_BIND;
}
break;
}
case T_CONNECT:
// DebugWrite("T_CONNECT");
//dprintf("this:%X T_CONNECT\n", this);
theErr = result;
if(!theErr)
theErr = ::OTRcvConnect(mRef, nil);
if(!theErr)
{
mConnectionOpen = TRUE;
mWriteReady = TRUE;
mCallBack->Func(CONNECT_NOTIFICATION); //z
}
else
theErr = HXR_SERVER_DISCONNECTED;
break;
case T_DISCONNECT:
// DebugWrite("T_DISCONNECT");
//dprintf("this:%X T_DISCONNECT\n", this);
/* Other side has aborted. */
mCode = code;
mOtherSideHasClosed = true;
mComplete = true;
mConnectionOpen = FALSE;
mWeHaveClosed = TRUE; //cz
mStartedReceivingData = FALSE;
mWriteReady = FALSE;
::OTRcvDisconnect(mRef, NULL);
if (mCallBack) mCallBack->Func(CONNECT_NOTIFICATION, FALSE); // rml cr zach, rahul
break;
case T_ORDREL:
// DebugWrite("T_ORDREL");
//dprintf("this:%X T_ORDREL\n", this);
/* Other side has closed. Close our side if necessary. */
mCode = code;
mOtherSideHasClosed = true;
mComplete = true;
mConnectionOpen = FALSE;
mStartedReceivingData = FALSE;
mWriteReady = FALSE;
::OTRcvOrderlyDisconnect(mRef);
if (!mWeHaveClosed)
{
::OTSndOrderlyDisconnect(mRef);
mWeHaveClosed = true;
}
if (mClosing) mRelease = true;
break;
case T_DATA:
// DebugWrite("T_DATA");
//dprintf("this:%X T_DATA\n", this);
mStartedReceivingData = TRUE;
if (mClosing)
{
/* Consume and discard response to "QUIT" comand. */
do
{
result = ::OTRcv(mRef, mBuf, kBufSize, nil);
} while (result >= 0);
}
else if ( mState == TCP_STATE_ACCEPT_PENDING )
{
//dprintf("TCP_STAT_ACCEPT_PENDING - hold data.\n");
mDataReady = TRUE;
}
else
{
mDataArrived = TRUE;
if(mCallBack)
// mCallBack->callback_task(HX_TCP_CALLBACK);
mCallBack->Func(READ_NOTIFICATION);
}
break;
case T_DISCONNECTCOMPLETE:
case T_PASSCON:
//dprintf("this:%X T_PASSCON ", this);
// DebugWrite("T_DISCONNECTCOMPLETE");
if ( mState == TCP_STATE_ACCEPT_PENDING )
{
//dprintf("TCP_STATE_ACCEPT_PENDING\n");
mConnectionOpen = TRUE;
mWriteReady = TRUE;
mOtherSideHasClosed = false;
mState = TCP_STATE_READY;
if ( mDataReady )
{
//dprintf("Data is waiting so give notification\n");
mDataArrived = TRUE;
if ( mCallBack )
mCallBack->Func(READ_NOTIFICATION);
}
}
else
{
//dprintf("Regular\n");
mComplete = true;
mCode = code;
mResult = result;
mCookie = cookie;
}
break;
case T_GODATA:
// DebugWrite("T_GODATA");
//dprintf("this:%X T_GODATA\n", this);
mDataFlowOn = FALSE;
mWriteReady = TRUE;
break;
case T_LISTEN:
//dprintf("this:%X T_LISTEN\n", this);
::memset(&mNewAddr,0,sizeof(TCall));
mCall.addr.buf = (UInt8 *)&mNewAddr;
mCall.addr.maxlen = sizeof(InetAddress);
mCall.addr.len = sizeof(InetAddress);
//HX_ASSERT(mState == TCP_SOCKET_LISTEN);
HX_ASSERT(mNewConnection);
EndpointRef pRef;
#ifdef _CARBON
mNewConnection->GetEndpoint((void*&)pRef);
#else
mNewConnection->GetEndpoint((void*)pRef);
#endif
if ( pRef )
{
theErr = OTListen(mRef,&mCall);
if ( !theErr )
{
if ( !theErr )
{
theErr = OTAccept(mRef, pRef, &mCall);
}
}
}
else
{
// some how we got messed up
// not much we can do... we will
// just ignor the listen request...
}
break;
case T_ACCEPTCOMPLETE:
{
//dprintf("this:%X T_ACCEPTCOMPLETE\n", this);
mCallBack->Func(ACCEPT_NOTIFICATION,
TRUE, mNewConnection);
// it is the callback's job to call done...
HX_RELEASE(mNewConnection);
mNewConnection = conn::actual_new_socket(HX_TCP_SOCKET);
mNewConnection->AddRef();
// we are in deffered task time so this will not finish
// until wait for event is called again... therefore
// we pass in false for wait. We will wait at the
// beginning to GetEndpoint() if it hasn't finished yet.
HX_RESULT theErr = mNewConnection->SetupEndpoint(FALSE);
}
break;
case kOTProviderIsClosed:
{
// This event is triggered by OpenTransport when the network is gone
// i.e. network cable has been unpluged
mCode = code;
mResult = result;
mOtherSideHasClosed = true;
mComplete = true;
mConnectionOpen = FALSE;
mWeHaveClosed = TRUE;
mStartedReceivingData = FALSE;
mWriteReady = FALSE;
::OTRcvDisconnect(mRef, NULL);
if (mCallBack) mCallBack->Func(CONNECT_NOTIFICATION, FALSE);
}
break;
default:
//dprintf("this:%X Uncaugt message - %X\n", this, code);
break;
}
mAsyncError = theErr;
}
HX_RESULT OT_TCP::SetupEndpoint(BOOL bWait)
{
//dprintf("this:%X OT_TCP::SetupEndpoint\n", this);
// Open TCP endpoint
mState = TCP_STATE_OPEN_ACCEPT;
mComplete = false;
mConnectionOpen = FALSE;
mDataFlowOn = FALSE;
mDataArrived = FALSE;
mDataReady = FALSE;
mAsyncError = HXR_OK;
#ifdef USE_DEFERRED_IMPL
HX_RESULT theErr = ::OTAsyncOpenEndpoint(OTCreateConfiguration(kTCPName), 0,NULL, UDPTCPNotifyProc, this);
#else
#ifdef _CARBON
HX_RESULT theErr = ::OTAsyncOpenEndpointInContext(OTCreateConfiguration(kTCPName),
0,NULL, (OTNotifyUPP)TCPNotifyProc, this, NULL);
#else
HX_RESULT theErr = ::OTAsyncOpenEndpoint(OTCreateConfiguration(kTCPName),
0,NULL, TCPNotifyProc, this);
#endif
#endif
if ( theErr )
{
mLastError = theErr;
theErr = HXR_SOCKET_CREATE;
}
// wait for open completion.. if we were called from deffered task time
// or Interupt time we don't want to wait though... Because the creation
// of the end point will not finish until control is passed back to the
// application.
if( bWait )
{
if ( !theErr)
{
theErr = OTWait();
if(theErr == kOTNoDataErr) theErr = HXR_OK;
if(theErr || mCode != T_OPENCOMPLETE)
{
theErr = theErr ? theErr : HXR_SOCKET_CREATE;
mLastError = theErr;
theErr = HXR_SOCKET_CREATE;
}
}
}
return theErr;
}
HX_RESULT OT_TCP::GetEndpoint(REF(void*) pRef)
{
////dprintf("this:%X OT_TCP::GetEndpoint\n", this);
HX_RESULT theErr = HXR_OK;
if ( mState == TCP_STATE_OPEN_ACCEPT )
{
theErr = OTWait();
if(theErr == kOTNoDataErr) theErr = HXR_OK;
if ( theErr || mCode != T_OPENCOMPLETE )
{
theErr = theErr ? theErr : HXR_SOCKET_CREATE;
mLastError = theErr;
return HXR_SOCKET_CREATE;
}
}
if ( mRef )
{
mState = TCP_STATE_ACCEPT_PENDING;
pRef = (void*)mRef;
return HXR_OK;
}
else
{
return HXR_NOT_INITIALIZED;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -