📄 ot_tcp.cp
字号:
mState = TCP_STATE_LISTEN; } if ( !theErr ) { // check to see if we are not being called again... // calling done() on mNewConnection should be fine, because // it should be released after a connection has been accepted. 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_RESULTOT_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;}voidOT_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_RESULTOT_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 + -