Retired Document
Important: This sample code may not represent best practices for current development. The project may use deprecated symbols and illustrate technologies and techniques that are no longer recommended.
•OT_Classes/TNetworkSession.cp
// TNetworkSession.cp - Macintosh OpenTransport Network Server class object |
// |
// Apple Macintosh Developer Technical Support |
// Written by: Vinne Moscaritolo |
// |
// Copyright (work in progress) Apple Computer, Inc All rights reserved. |
// |
// You may incorporate this sample code into your applications without |
// restriction, though the sample code has been provided "AS IS" and the |
// responsibility for its operation is 100% yours. However, what you are |
// not permitted to do is to redistribute the source as "DSC Sample Code" |
// after having made changes. If you're going to re-distribute the source, |
// we require that you make it clear in the source that the code was |
// descended from Apple Sample Code, but that you've made changes. |
// |
#include "TNetworkSession.h" |
#include "TNetworkAcceptor.h" |
// --------------------------------------------------------------------------- |
// NotifyProc (queue up an event) |
// --------------------------------------------------------------------------- |
// TNetworkSession OT Notifier Proc |
pascal void TNetworkSession::NotifyProc( TNetworkSession* theSession, OTEventCode theEvent, OTResult theResult, void* theParam) |
{ |
try |
{ |
//// No-copy memory was released |
if(theEvent == T_MEMORYRELEASED) TNetworkBuf::Release(theParam); |
// Data avail at endpoint |
else if (theEvent == T_DATA) theSession->EventDataAvail(); |
// queue all others |
else QUEUE_NET_EVENT( theSession, theEvent, theResult, theParam); |
} |
catch (TNetworkException &ex) |
{ |
DebugStr("\p TNetworkSession::NotifyProc -- Network Exception.. "); |
} |
catch(TMacException &ex) |
{ |
DebugStr("\p TNetworkSession::NotifyProc -- Mac Exception.. "); |
} |
catch(...) // catch everything |
{ |
DebugStr("\p TNetworkSession::NotifyProc -- Other Exception.. "); |
} |
} |
// --------------------------------------------------------------------------- |
// TNetworkSession |
// --------------------------------------------------------------------------- |
// Default Constructor |
TNetworkSession::TNetworkSession(TNetworkAcceptor* theServer) |
{ |
TNetworkEndpointDescriptor* theEPD; |
// Setup a new endpoint |
fEndPoint = kOTInvalidEndpointRef; |
fData = nil; |
fServer = theServer; |
theEPD = theServer->GetEPD(); |
ThrowIfOTErr( ::OTAsyncOpenEndpoint(theEPD->GetConfiguration() ,0,&fInfo, NotifyProc, this ) ); |
} |
// --------------------------------------------------------------------------- |
// ~TNetworkListener |
// --------------------------------------------------------------------------- |
// Destructor |
TNetworkSession::~TNetworkSession() |
{ |
// close up enpoint |
if(fEndPoint != kOTInvalidEndpointRef) ::OTCloseProvider(fEndPoint); |
if( fData) delete fData; |
}; |
// --------------------------------------------------------------------------- |
// TNetworkAcceptor::Done( ) |
// --------------------------------------------------------------------------- |
// Session Thread completed.. |
void TNetworkSession::Done() |
{ |
OTResult state = ::OTGetEndpointState(fEndPoint); |
// If your not shutdown yet |
if(state == T_DATAXFER) { |
// flush out all waiting data |
fioStream << flush; |
// and disconnect the endpoint |
if( (fInfo.flags == T_COTS_ORD) || (fInfo.flags == T_TRANS_ORD)) |
::OTSndOrderlyDisconnect(fEndPoint); |
else |
::OTSndDisconnect (fEndPoint,&fCallInfo); |
} |
} |
// --------------------------------------------------------------------------- |
// TNetworkSession::HandleEvent (TNetworkEvent*) |
// --------------------------------------------------------------------------- |
// Network Server Event Handler |
void TNetworkSession::HandleEvent (TNetworkEvent* theEvent) |
{ |
switch ( theEvent->fEvent ){ |
///// OpenEndpoint Completed |
case T_OPENCOMPLETE: |
EventOpenComplete(theEvent); |
break; |
///// Endpoint accepted connection |
case T_PASSCON: |
EventPassCon(theEvent); |
break; |
///// Client Quit |
case T_DISCONNECT: |
EventDisconnect(theEvent); |
break; |
///// remote client request release |
case T_ORDREL: |
EventOrdRelease(theEvent); |
break; |
///// Connection Torn Down |
case T_DISCONNECTCOMPLETE: |
EventDisconnectComplete(theEvent); |
break; |
///// Winding down |
case T_UNBINDCOMPLETE: |
EventUnbindComplete(theEvent); |
break; |
//// Data Available |
case T_DATA: |
EventDataAvail(theEvent); |
break; |
//// Expidited Data Available |
case T_EXDATA: |
EventExDataAvail(theEvent); |
break; |
//// No-copy memory was released // DEBUG ONLY... |
case T_MEMORYRELEASED: |
EventMemoryReleased(theEvent); |
break; |
////..Other ... |
default: |
EventOther(theEvent); |
break; |
} |
} |
// --------------------------------------------------------------------------- |
// TNetworkSession::EventOpenComplete(theEvent ) |
// --------------------------------------------------------------------------- |
// Network Endpoint Open Completion Handler |
void TNetworkSession::EventOpenComplete(TNetworkEvent* theEvent) |
{ |
// record endpoint |
fEndPoint = (EndpointRef) theEvent->fParam; |
// Setup Tcall/Tdisconnect area |
fCallInfo.addr.len = 0; |
fCallInfo.opt.len = 0; |
fCallInfo.udata.len = 0; |
fDisconInfo.udata.len = 0; |
fCallInfo.addr.maxlen = (fInfo.addr == T_INVALID)?0:fInfo.addr; |
fCallInfo.opt.maxlen = (fInfo.options == T_INVALID)?0:fInfo.options; |
fCallInfo.udata.maxlen = (fInfo.connect == T_INVALID)?0:fInfo.connect; |
fDisconInfo.udata.maxlen= (fInfo.discon == T_INVALID)?0:fInfo.discon; |
// Alloacte enough ram for Tcall & TDiscon buffers |
size_t buffSize = fCallInfo.addr.maxlen |
+ fCallInfo.opt.maxlen |
+ (fCallInfo.udata.maxlen > fDisconInfo.udata.maxlen |
? fCallInfo.udata.maxlen |
: fDisconInfo.udata.maxlen); |
fData = new UInt8[buffSize]; |
fCallInfo.addr.buf = &fData[0]; |
fCallInfo.opt.buf = fCallInfo.addr.buf + fCallInfo.addr.maxlen; |
fCallInfo.udata.buf = fCallInfo.opt.buf + fCallInfo.opt.maxlen; |
fDisconInfo.udata.buf = fCallInfo.udata.buf; // Disconnect and connect share the same data area |
// Enable AckSends |
ThrowIfOTErr( ::OTAckSends(fEndPoint)); |
// attach endpoint to stream; |
fioStream.attach(fEndPoint,&fInfo); |
// Inform Server that we are ready to be used |
QUEUE_NET_EVENT( fServer, TNetworkAcceptor::kSessionAvailable, noErr, this); |
} |
// --------------------------------------------------------------------------- |
// TNetworkSession::EventPassCon(theEvent) |
// --------------------------------------------------------------------------- |
// Network Endpoint Handoff Completion Handler |
void TNetworkSession::EventPassCon(TNetworkEvent* theEvent) |
{ |
try{ |
Start(); // start thread. |
} |
catch(...){ |
Done(); |
} |
} |
// --------------------------------------------------------------------------- |
// TNetworkAcceptor::EventDisconnect |
// --------------------------------------------------------------------------- |
// Connecting client quit |
void TNetworkSession::EventDisconnect(TNetworkEvent* theEvent) |
{ |
OSStatus ErrNo; |
if( ErrNo = ::OTRcvDisconnect(fEndPoint, &fDisconInfo)) |
ErrNo = ErrNo ; |
if( ErrNo = ::OTUnbind(fEndPoint)) ; |
ErrNo = ErrNo ; |
} |
// --------------------------------------------------------------------------- |
// TNetworkSession::EventOrdRelease |
// --------------------------------------------------------------------------- |
// remote client request release |
void TNetworkSession::EventOrdRelease(TNetworkEvent* theEvent) |
{ |
OSStatus ErrNo; |
if( ErrNo = ::OTRcvOrderlyDisconnect(fEndPoint)) |
ErrNo = ErrNo ; |
if( ErrNo = ::OTUnbind(fEndPoint)) ; |
ErrNo = ErrNo ; |
// shut down thread if still running |
Stop(); |
} |
// --------------------------------------------------------------------------- |
// TNetworkSession::EventDisconnectComplete |
// --------------------------------------------------------------------------- |
// Connection Torn Down |
void TNetworkSession::EventDisconnectComplete(TNetworkEvent* theEvent) |
{ |
OSStatus ErrNo; |
if( ErrNo = ::OTUnbind(fEndPoint)) ; |
ErrNo = ErrNo ; |
} |
// --------------------------------------------------------------------------- |
// TNetworkSession::EventUnbindComplete |
// --------------------------------------------------------------------------- |
// Network Endpoint Unbind Completion Handler |
void TNetworkSession::EventUnbindComplete(TNetworkEvent* theEvent) |
{ |
// notify server that your done... |
QUEUE_NET_EVENT( fServer, TNetworkAcceptor::kSessionAvailable , noErr, this); |
} |
// --------------------------------------------------------------------------- |
// TNetworkSession::EventDataAvail |
// --------------------------------------------------------------------------- |
// Data Available |
void TNetworkSession::EventDataAvail(TNetworkEvent* theEvent) |
{ |
#pragma unused (theEvent) |
OTFlags flags; |
OTResult status; |
OTBuffer* buffP; |
OTBufferInfo buffInfo; |
size_t actCount; |
char* buffer; |
// do while data left in OT |
while((status = ::OTRcv(fEndPoint, &buffP, kOTNetbufDataIsOTBufferStar, &flags)) > 0) { |
// get count of bytes in buffer |
OTInitBufferInfo(&buffInfo, buffP); |
// loop until no longer hungry |
do{ |
// reserve buffer space |
ThrowIfNil( buffer = fioStream.ReserveBuffer(status, &actCount)); |
// read data into buffer |
::OTReadBuffer(&buffInfo, buffer, &actCount); |
fioStream.EnqueueBuffer(buffer,actCount); |
status -= actCount; |
} while( status > 0 ); |
// return OTBuffer to system |
::OTReleaseBuffer(buffP); |
} |
// Did we read all the data |
if(status == kOTNoDataErr) return; |
// was the endpoint not ready yet |
else if(status == kOTStateChangeErr) QUEUE_NET_EVENT(this, T_DATA, 0, 0); |
// Check for Rcv Error |
else ThrowIfOTErr( status ); |
}; |
// --------------------------------------------------------------------------- |
// TNetworkSession::EventExDataAvail |
// --------------------------------------------------------------------------- |
// Expidited Data Available |
void TNetworkSession::EventExDataAvail(TNetworkEvent* theEvent) |
{ |
}; |
// --------------------------------------------------------------------------- |
// TNetworkSession::EventMemoryReleased(theEvent ) |
// --------------------------------------------------------------------------- |
// Network Endpoint Memory released hander |
void TNetworkSession::EventMemoryReleased(TNetworkEvent* theEvent) |
{ |
TNetworkBuf::Release((void*)theEvent->fParam ); |
} |
// --------------------------------------------------------------------------- |
// TNetworkSession::EventOther |
// --------------------------------------------------------------------------- |
// Other random event |
void TNetworkSession::EventOther(TNetworkEvent* theEvent) |
{ |
if(theEvent) |
ThrowIfOTErr(noErr); |
}; |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-01-14