1/*
2    File:       ttplmp.cpp
3
4    Contains:   TinyTP's impl of the virtual callbacks in CIrLSAP
5
6*/
7
8#include "ttp.h"
9#include "ttppdu.h"
10#include "CBufferSegment.h"
11#include "IrDALog.h"
12
13#if (hasTracing > 0 && hasTTPLMPTracing > 0)
14
15enum TTPLmpTraceCodes
16{
17    kDiscoverComplete = 1,
18    kLSAPLookupComplete,
19    kConnected,
20    kPutComplete,
21    kGetComplete,
22    kDisconnected,
23    kConnectError,
24    kListenComplete,
25    kAcceptComplete,
26
27    kQOSrate,
28    kQOStimeout,
29    kQOSdatasize,
30    kQOSwindowsize,
31    kQOSbofs,
32    kQOSminturn,
33    kQOSlinkdisc
34
35
36}TTPLMPTraceCodes;
37
38static
39EventTraceCauseDesc gTraceEvents[] = {
40    {kDiscoverComplete,             "ttplmp: discovery complete"},
41    {kLSAPLookupComplete,           "ttplmp: LSAP lookup complete"},
42    {kConnected,                    "ttplmp: Connect complete, buf posn=, size="},
43    {kPutComplete,                  "ttplmp: put complete, result="},
44    {kGetComplete,                  "ttplmp: get complete, result=, size="},
45    {kDisconnected,                 "ttplmp: disconnect event"},
46    {kConnectError,                 "ttplmp: connect failed, result="},
47    {kListenComplete,               "ttplmp: listen complete, peer sap=, size="},
48    {kAcceptComplete,               "ttplmp: accept complete, result="},
49
50    {kQOSrate,                      "ttplmp: qos bitrate"},
51    {kQOStimeout,                   "ttplmp: qos timeout"},
52    {kQOSdatasize,                  "ttplmp: qos datasize"},
53    {kQOSwindowsize,                "ttplmp: qos windowsize"},
54    {kQOSbofs,                      "ttplmp: qos bofs"},
55    {kQOSminturn,                   "ttplmp: qos min turn"},
56    {kQOSlinkdisc,                  "ttplmp: qos link disc"}
57
58
59};
60
61#define XTRACE(x, y, z)  IrDALogAdd( x, y, (uintptr_t)z & 0xffff, gTraceEvents, true )
62
63#else
64#define XTRACE(x, y, z) ((void)0)
65#endif
66
67unsigned const char *className = (unsigned char *)"IrLan";
68
69#if (hasTracing > 0 && hasTTPLMPTracing > 1)
70void    LogOneQOS(int id, TIrQOS *q);
71void    LogQOSData(TIrQOS *myQOS, TIrQOS *peerQOS);
72#else
73#define LogQOSData(x, y) ((void)0);
74#endif
75
76//Boolean putPending = false;           // one per entire system!
77
78//////////////////////////////////////////////////////////////////////////////////
79// the following are called by CIrLSAP via virtual function overloading ...
80//////////////////////////////////////////////////////////////////////////////////
81
82
83void
84TTinyTP::DiscoverComplete(                  // discovery has finished
85	    UInt32  numFound,
86	    IrDAErr result      )
87{
88    XTRACE( kDiscoverComplete, numFound, 0 );
89    discoverPending = false;                // allow another discover request
90
91    // TinyTP doesn't do anything with this, just pass along to our client
92    TTPDiscoverComplete(numFound, result);
93    this->CheckTheQueues();                 // see if we have more work to do
94}
95
96
97void
98TTinyTP::LSAPLookupComplete (       // an IAS query has finished
99	IrDAErr result,
100	UInt32  peerLSAPId)
101{
102    XTRACE (kLSAPLookupComplete, result, peerLSAPId);
103
104    TTPLookupComplete(result, peerLSAPId);  // virtual callback
105    this->CheckTheQueues();                 // see if we have more work to do
106}
107
108
109void
110TTinyTP::ConnectComplete (
111    IrDAErr result,
112    TIrQOS *myQOS,
113    TIrQOS *peerQOS,
114    CBufferSegment *data)           // up to my client to free this data
115{
116#pragma unused (myQOS, peerQOS)
117
118    //check(data);              // might be nil if connect failed
119
120    if (result == noErr) {      // if the connect worked
121	check(data);                    // should always have data on a TTP connect
122	LogQOSData(myQOS, peerQOS);     // only if tracing > 1
123	XTRACE (kConnected, data->Position(), data->GetSize());
124	BufHideRest(data);          // set eof pointer, rewind
125	TTPHandleConnectConfirm(fPeerLSAPId, myQOS, peerQOS, data);     // let TTP know we have connect
126    }
127    else {
128	XTRACE (kConnectError, result >> 16, result);
129	//Disconnect();                         // tell CIrLSAP to disconnect (this is a nop and vanishes)
130	TTPHandleDisconnectIndication(0, nil);      // foo, fake a disconnect
131    }
132    this->CheckTheQueues();                 // see if we have more work to do
133}
134
135void
136TTinyTP::DisconnectComplete (void)
137{
138    XTRACE (kDisconnected, 0, 0);
139    TTPHandleDisconnectIndication(0, nil);      // sigh, where's my reason?
140    this->CheckTheQueues();                 // see if we have more work to do
141}
142
143void
144TTinyTP::DataPutComplete (
145		IrDAErr result,
146		CBufferSegment *data)       // TTP "copy" of data ... foo
147{
148    check(data);
149    XTRACE (kPutComplete, 0, result);
150
151    if (result) {                   //// Try and handle hangups
152	if (Connected)                  // if we think we're connected
153	    DoDisconnectRequest(nil);       // force a disconnect on error
154    }
155
156    BufFree(data);                          // put done, don't need the buffer anymore
157    this->CheckTheQueues();                 // see if we have more work to do
158}
159
160void
161TTinyTP::DataGetComplete (
162		IrDAErr result,
163		CBufferSegment *data)
164{
165    XTRACE (kGetComplete, result, data->GetSize());
166
167    if (result == noErr) {          // if the read worked
168	check(data);                    // then, ah, there should be data
169	BufHideRest(data);              // set buffer size and rewind
170	TTPHandleDataIndication(data);      // pass up to TTP & TTP Client
171    }
172    else {
173	if (Connected) DoDisconnectRequest(nil);    // treat err as disconnect request
174	BufFree(data);                              // get failed, don't need the buffer anymore
175    }
176
177    this->CheckTheQueues();             // see if we have more work to do
178}
179
180
181void
182TTinyTP::ListenComplete (
183		IrDAErr result,
184		UInt32  peerAddr,
185		UInt32  peerLSAPId,
186		TIrQOS  *myQOS,                 // my qos
187		TIrQOS  *peerQOS,               // peer's qos
188		CBufferSegment *data)
189{
190    XTRACE (kListenComplete, 0, this);
191    XTRACE (kListenComplete, peerLSAPId, result);
192    check(data);                            // should always have data on a listen complete
193
194    fPeerAddr = peerAddr;                   // hang out to the address of our caller
195    fPeerSAP  = peerLSAPId;
196
197    if (result == noErr) {                  // if the listen is ok
198	BufHideRest(data);                  // set eof pointer, rewind
199    }
200    TTPHandleConnectIndication(result, peerLSAPId, myQOS, peerQOS, data);   // let TTP know listen finished
201
202    this->CheckTheQueues();                 // see if we have more work to do
203}
204
205//
206// BOGUS: there isn't an accept complete return to our caller, so their
207// buffer has to be freed by us instead of by them.  BOGUS.  Pass it up.
208//
209void
210TTinyTP::AcceptComplete (
211		IrDAErr result,
212		CBufferSegment *data)
213{
214    XTRACE(kAcceptComplete, 0, result);
215    check(data);                            // should always have a buffer, it's allocd by DoConnectResponse()
216    //BufFree(data);                        // free the connect buffer allocated by PDU Connect
217
218    TTPHandleAcceptComplete(result, data);      // pass up the result code and buffer ptr (client frees it now)
219
220    if (result == noErr) {              // if we're fully open now
221	CBufferSegment *getBuf;
222
223	Connected = true;               // change state before my callback does more work!
224	getBuf = BufAlloc(2048+5);      // need up to max lap size
225	require(getBuf, NoMem);         // not a lot I can do w/out a read buffer
226	DataGet(getBuf);                // start the read
227    }
228NoMem:
229    this->CheckTheQueues();                 // see if we have more work to do
230}
231
232void
233TTinyTP::CancelGetsComplete(IrDAErr result)
234{
235#pragma unused(result)
236    // never gets here
237}
238
239void
240TTinyTP::CancelPutsComplete(IrDAErr result)
241{
242#pragma unused(result)
243    // never gets here
244}
245
246
247#pragma mark ---- QoS debug logging
248
249#if (hasTracing > 0 && hasTTPLMPTracing > 1)
250
251void
252LogOneQOS(int id, TIrQOS *q)
253{
254    check(q);
255
256    BitRate     rate = q->GetBaudRate();
257    XTRACE(kQOSrate, id, rate);
258
259    TTimeout    timeout = q->GetMaxTurnAroundTime();
260    XTRACE(kQOStimeout, id, timeout);
261
262    ULong       datasize = q->GetDataSize();
263    XTRACE(kQOSdatasize, id, datasize);
264
265    ULong       windowsize = q->GetWindowSize();
266    XTRACE(kQOSwindowsize, id, windowsize);
267
268    ULong       bofs = q->GetExtraBOFs();
269    XTRACE(kQOSbofs, id, bofs);
270
271    TTimeout    minturn = q->GetMinTurnAroundTime();
272    XTRACE(kQOSminturn, id, minturn);
273
274    TTimeout    linkdisc = q->GetLinkDiscThresholdTime();
275    XTRACE(kQOSlinkdisc, id, linkdisc);
276
277}
278
279void
280LogQOSData(TIrQOS *myQOS, TIrQOS *peerQOS)
281{
282    LogOneQOS(1, myQOS);
283    LogOneQOS(2, peerQOS);
284}
285
286#endif // hasTTPLMPTracing > 1
287