/* File: ttplmp.cpp Contains: TinyTP's impl of the virtual callbacks in CIrLSAP */ #include "ttp.h" #include "ttppdu.h" #include "CBufferSegment.h" #include "IrDALog.h" #if (hasTracing > 0 && hasTTPLMPTracing > 0) enum TTPLmpTraceCodes { kDiscoverComplete = 1, kLSAPLookupComplete, kConnected, kPutComplete, kGetComplete, kDisconnected, kConnectError, kListenComplete, kAcceptComplete, kQOSrate, kQOStimeout, kQOSdatasize, kQOSwindowsize, kQOSbofs, kQOSminturn, kQOSlinkdisc }TTPLMPTraceCodes; static EventTraceCauseDesc gTraceEvents[] = { {kDiscoverComplete, "ttplmp: discovery complete"}, {kLSAPLookupComplete, "ttplmp: LSAP lookup complete"}, {kConnected, "ttplmp: Connect complete, buf posn=, size="}, {kPutComplete, "ttplmp: put complete, result="}, {kGetComplete, "ttplmp: get complete, result=, size="}, {kDisconnected, "ttplmp: disconnect event"}, {kConnectError, "ttplmp: connect failed, result="}, {kListenComplete, "ttplmp: listen complete, peer sap=, size="}, {kAcceptComplete, "ttplmp: accept complete, result="}, {kQOSrate, "ttplmp: qos bitrate"}, {kQOStimeout, "ttplmp: qos timeout"}, {kQOSdatasize, "ttplmp: qos datasize"}, {kQOSwindowsize, "ttplmp: qos windowsize"}, {kQOSbofs, "ttplmp: qos bofs"}, {kQOSminturn, "ttplmp: qos min turn"}, {kQOSlinkdisc, "ttplmp: qos link disc"} }; #define XTRACE(x, y, z) IrDALogAdd( x, y, z, gTraceEvents, true ) #else #define XTRACE(x, y, z) ((void)0) #endif unsigned const char *className = (unsigned char *)"IrLan"; #if (hasTracing > 0 && hasTTPLMPTracing > 1) void LogOneQOS(int id, TIrQOS *q); void LogQOSData(TIrQOS *myQOS, TIrQOS *peerQOS); #else #define LogQOSData(x, y) ((void)0); #endif //Boolean putPending = false; // one per entire system! ////////////////////////////////////////////////////////////////////////////////// // the following are called by CIrLSAP via virtual function overloading ... ////////////////////////////////////////////////////////////////////////////////// void TTinyTP::DiscoverComplete( // discovery has finished UInt32 numFound, IrDAErr result ) { XTRACE( kDiscoverComplete, numFound, 0 ); discoverPending = false; // allow another discover request // TinyTP doesn't do anything with this, just pass along to our client TTPDiscoverComplete(numFound, result); this->CheckTheQueues(); // see if we have more work to do } void TTinyTP::LSAPLookupComplete ( // an IAS query has finished IrDAErr result, UInt32 peerLSAPId) { XTRACE (kLSAPLookupComplete, result, peerLSAPId); TTPLookupComplete(result, peerLSAPId); // virtual callback this->CheckTheQueues(); // see if we have more work to do } void TTinyTP::ConnectComplete ( IrDAErr result, TIrQOS *myQOS, TIrQOS *peerQOS, CBufferSegment *data) // up to my client to free this data { #pragma unused (myQOS, peerQOS) //check(data); // might be nil if connect failed if (result == noErr) { // if the connect worked check(data); // should always have data on a TTP connect LogQOSData(myQOS, peerQOS); // only if tracing > 1 XTRACE (kConnected, data->Position(), data->GetSize()); BufHideRest(data); // set eof pointer, rewind TTPHandleConnectConfirm(fPeerLSAPId, myQOS, peerQOS, data); // let TTP know we have connect } else { XTRACE (kConnectError, result >> 16, result); //Disconnect(); // tell CIrLSAP to disconnect (this is a nop and vanishes) TTPHandleDisconnectIndication(0, nil); // foo, fake a disconnect } this->CheckTheQueues(); // see if we have more work to do } void TTinyTP::DisconnectComplete (void) { XTRACE (kDisconnected, 0, 0); TTPHandleDisconnectIndication(0, nil); // sigh, where's my reason? this->CheckTheQueues(); // see if we have more work to do } void TTinyTP::DataPutComplete ( IrDAErr result, CBufferSegment *data) // TTP "copy" of data ... foo { check(data); XTRACE (kPutComplete, 0, result); if (result) { //// Try and handle hangups if (Connected) // if we think we're connected DoDisconnectRequest(nil); // force a disconnect on error } BufFree(data); // put done, don't need the buffer anymore this->CheckTheQueues(); // see if we have more work to do } void TTinyTP::DataGetComplete ( IrDAErr result, CBufferSegment *data) { XTRACE (kGetComplete, result, data->GetSize()); if (result == noErr) { // if the read worked check(data); // then, ah, there should be data BufHideRest(data); // set buffer size and rewind TTPHandleDataIndication(data); // pass up to TTP & TTP Client } else { if (Connected) DoDisconnectRequest(nil); // treat err as disconnect request BufFree(data); // get failed, don't need the buffer anymore } this->CheckTheQueues(); // see if we have more work to do } void TTinyTP::ListenComplete ( IrDAErr result, UInt32 peerAddr, UInt32 peerLSAPId, TIrQOS *myQOS, // my qos TIrQOS *peerQOS, // peer's qos CBufferSegment *data) { XTRACE (kListenComplete, (int)this >> 16, (short)this); XTRACE (kListenComplete, peerLSAPId, result); check(data); // should always have data on a listen complete fPeerAddr = peerAddr; // hang out to the address of our caller fPeerSAP = peerLSAPId; if (result == noErr) { // if the listen is ok BufHideRest(data); // set eof pointer, rewind } TTPHandleConnectIndication(result, peerLSAPId, myQOS, peerQOS, data); // let TTP know listen finished this->CheckTheQueues(); // see if we have more work to do } // // BOGUS: there isn't an accept complete return to our caller, so their // buffer has to be freed by us instead of by them. BOGUS. Pass it up. // void TTinyTP::AcceptComplete ( IrDAErr result, CBufferSegment *data) { XTRACE(kAcceptComplete, 0, result); check(data); // should always have a buffer, it's allocd by DoConnectResponse() //BufFree(data); // free the connect buffer allocated by PDU Connect TTPHandleAcceptComplete(result, data); // pass up the result code and buffer ptr (client frees it now) if (result == noErr) { // if we're fully open now CBufferSegment *getBuf; Connected = true; // change state before my callback does more work! getBuf = BufAlloc(2048+5); // need up to max lap size require(getBuf, NoMem); // not a lot I can do w/out a read buffer DataGet(getBuf); // start the read } NoMem: this->CheckTheQueues(); // see if we have more work to do } void TTinyTP::CancelGetsComplete(IrDAErr result) { #pragma unused(result) // never gets here } void TTinyTP::CancelPutsComplete(IrDAErr result) { #pragma unused(result) // never gets here } #pragma mark ---- QoS debug logging #if (hasTracing > 0 && hasTTPLMPTracing > 1) void LogOneQOS(int id, TIrQOS *q) { check(q); BitRate rate = q->GetBaudRate(); XTRACE(kQOSrate, id, rate); TTimeout timeout = q->GetMaxTurnAroundTime(); XTRACE(kQOStimeout, id, timeout); ULong datasize = q->GetDataSize(); XTRACE(kQOSdatasize, id, datasize); ULong windowsize = q->GetWindowSize(); XTRACE(kQOSwindowsize, id, windowsize); ULong bofs = q->GetExtraBOFs(); XTRACE(kQOSbofs, id, bofs); TTimeout minturn = q->GetMinTurnAroundTime(); XTRACE(kQOSminturn, id, minturn); TTimeout linkdisc = q->GetLinkDiscThresholdTime(); XTRACE(kQOSlinkdisc, id, linkdisc); } void LogQOSData(TIrQOS *myQOS, TIrQOS *peerQOS) { LogOneQOS(1, myQOS); LogOneQOS(2, peerQOS); } #endif // hasTTPLMPTracing > 1