1/* 2 File: IrLSAPConn.cpp 3 4 Contains: Implementation of the TIrLSAPConn class 5 6 7*/ 8 9#include "IrLSAPConn.h" 10#include "IrGlue.h" 11#include "IrLMP.h" 12#include "CList.h" 13#include "CListIterator.h" 14#include "CBufferSegment.h" 15#include "IrDALog.h" 16 17#if (hasTracing > 0 && hasLSAPConnTracing > 0) 18 19enum IrLSAPConnTraceCodes 20{ 21 kNullEvent = 1, 22 kDestroy, 23 kDeInit, 24 kUnexpectedEvent, 25 26 kDiscConnectEvent, 27 kDiscListenEvent, 28 kDiscDiscRequestEvent, 29 kDiscLeftoversReplyEvent, 30 31 kConnectPendConnectReplyEvent, 32 kConnectPendPutReplyEvent, 33 kConnectPendDiscRequestEvent, 34 kConnectPendDiscReplyEvent, 35 36 kConnectGetReplyEvent, 37 kConnectWatchdogTimeoutEvent, 38 kConnectDisconnectRequestEvent, 39 kConnectDisconnectReplyEvent, 40 41 kListenPendListenReplyEvent, 42 kListenPendDiscRequestEvent, 43 kListenPendDiscReplyEvent, 44 45 kListenGetReplyEvent, 46 kListenPutReplyEvent, 47 kListenDisconnectRequestEvent, 48 kListenDisconnectReplyEvent, 49 50 kAcceptConnectRequestEvent, 51 kRejectConnectRequestEvent, 52 kAccRejPutReplyEvent, 53 kAccRejDisconnectReplyEvent, 54 55 kDTRPutRequestEvent, 56 kDTRGetRequestEvent, 57 kDTRPutReplyEvent, 58 kDTRGetReplyEvent, 59 kDTRCancelPutRequestEvent, 60 kDTRCancelGetRequestEvent, 61 kDTRCancelPutReplyEvent, 62 kDTRCancelGetReplyEvent, 63 kDTRDisconnectRequestEvent, 64 kDTRDisconnectReplyEvent, 65 kDTRReleaseRequestEvent, 66 67 kMyData, 68 kDataForMe, 69 kDataWaitingForMe, 70 kLogRejectingMyData, 71 72 kGetMyId, // 73 74 kLogDiscPendingEvent, 75 kLogDiscPendingClient, 76 kLogDiscPendingRejectRequest, 77 kLogDiscPendingMiscReply, 78 kLogDiscPendingConnLstnDone, 79 kLogDiscPendingInternalDisc, 80 kLogDiscPendingWatchDog, 81 kLogDiscPendingDiscDone, 82 kLogDiscPendingRequeue, 83 84 kEnqueueEvent, 85 kDequeueEventStart, 86 kDequeueEventEnd 87 88}; 89 90static 91EventTraceCauseDesc IrLSAPConnTraceEvents[] = { 92 {kNullEvent, "IrLSAPConn: null event"}, 93 {kDestroy, "IrLSAPConn: destroy obj="}, 94 {kDeInit, "IrLSAPConn: DeInit"}, 95 {kUnexpectedEvent, "IrLSAPConn: unexpected event"}, 96 97 {kDiscConnectEvent, "IrLSAPConn: disc connect request"}, 98 {kDiscListenEvent, "IrLSAPConn: disc listen request"}, 99 {kDiscDiscRequestEvent, "IrLSAPConn: disc disconnect request"}, 100 {kDiscLeftoversReplyEvent, "IrLSAPConn: disc leftovers reply"}, 101 102 {kConnectPendConnectReplyEvent, "IrLSAPConn: conn pend got LAP reply"}, 103 {kConnectPendPutReplyEvent, "IrLSAPConn: conn pend put LM-PDU conn request"}, 104 {kConnectPendDiscRequestEvent, "IrLSAPConn: conn pend disconnect request"}, 105 {kConnectPendDiscReplyEvent, "IrLSAPConn: conn pend disconnect reply"}, 106 107 {kConnectGetReplyEvent, "IrLSAPConn: connect got LM-PDU conn reply"}, 108 {kConnectWatchdogTimeoutEvent, "IrLSAPConn: connect watchdog timed out"}, 109 {kConnectDisconnectRequestEvent,"IrLSAPConn: connect disconnect request"}, 110 {kConnectDisconnectReplyEvent, "IrLSAPConn: connect disconnect reply"}, 111 112 {kListenPendListenReplyEvent, "IrLSAPConn: lstn pend got LAP reply"}, 113 {kListenPendDiscRequestEvent, "IrLSAPConn: lstn pend disconnect request"}, 114 {kListenPendDiscReplyEvent, "IrLSAPConn: lstn pend disconnect reply"}, 115 116 {kListenGetReplyEvent, "IrLSAPConn: listen got LM-PDU conn request"}, 117 {kListenPutReplyEvent, "IrLSAPConn: listen put LM-PDU disc reply"}, 118 {kListenDisconnectRequestEvent, "IrLSAPConn: listen disconnect request"}, 119 {kListenDisconnectReplyEvent, "IrLSAPConn: listen disconnect reply"}, 120 121 {kAcceptConnectRequestEvent, "IrLSAPConn: accept connect request"}, 122 {kRejectConnectRequestEvent, "IrLSAPConn: reject connect request"}, 123 {kAccRejPutReplyEvent, "IrLSAPConn: acc/rej put LM-PDU conn/disc reply"}, 124 {kAccRejDisconnectReplyEvent, "IrLSAPConn: acc/rej disconnect reply"}, 125 126 {kDTRPutRequestEvent, "IrLSAPConn: DTR put request"}, 127 {kDTRGetRequestEvent, "IrLSAPConn: DTR get request"}, 128 {kDTRPutReplyEvent, "IrLSAPConn: DTR put reply"}, 129 {kDTRGetReplyEvent, "IrLSAPConn: DTR get reply"}, 130 {kDTRCancelPutRequestEvent, "IrLSAPConn: DTR cancel put request"}, 131 {kDTRCancelGetRequestEvent, "IrLSAPConn: DTR cancel get request"}, 132 {kDTRCancelPutReplyEvent, "IrLSAPConn: DTR cancel put reply"}, 133 {kDTRCancelGetReplyEvent, "IrLSAPConn: DTR cancel get reply"}, 134 {kDTRDisconnectRequestEvent, "IrLSAPConn: DTR disconnect request"}, 135 {kDTRDisconnectReplyEvent, "IrLSAPConn: DTR disconnect reply"}, 136 {kDTRReleaseRequestEvent, "IrLSAPConn: DTR release request"}, 137 138 {kMyData, "IrLSAPConn: checking packet header"}, 139 {kDataForMe, "IrLSAPConn: data for this LSAP" }, 140 {kDataWaitingForMe, "IrLSAPConn: data waiting for this LSAP" }, 141 {kLogRejectingMyData, "IrLSAPConn: rejecting listen attempt, state="}, 142 143 {kGetMyId, "IrLSAPConn: get my id. obj=, id="}, 144 {kLogDiscPendingEvent, "IrLSAPConn: disconnect pending, 0, event"}, 145 {kLogDiscPendingClient, "IrLSAPConn: disconnect pending, client=="}, 146 {kLogDiscPendingRejectRequest, "IrLSAPConn: disconnect pending, rejecting request"}, 147 {kLogDiscPendingMiscReply, "IrLSAPConn: disconnect pending, reply. event, pendevent"}, 148 {kLogDiscPendingConnLstnDone, "IrLSAPConn: disconnect pending, connlstn done"}, 149 {kLogDiscPendingInternalDisc, "IrLSAPConn: disconnect pending, internal discon (pending event, result)"}, 150 {kLogDiscPendingWatchDog, "IrLSAPConn: disconnect pending, watchdog timer"}, 151 {kLogDiscPendingDiscDone, "IrLSAPConn: disconnect pending, disconnect complete, result="}, 152 {kLogDiscPendingRequeue, "IrLSAPConn: disconnect pending, requeue event"}, 153 154 155 {kEnqueueEvent, "IrLSAPConn: Event Queued"}, 156 {kDequeueEventStart, "IrLSAPConn: Event Start"}, 157 {kDequeueEventEnd, "IrLSAPConn: Event End"} 158}; 159 160#define XTRACE(x, y, z) IrDALogAdd( x, y, (uintptr_t)z & 0xffff, IrLSAPConnTraceEvents, true) 161#else 162#define XTRACE(x, y, z) ((void)0) 163#endif 164 165#define GetLMP (fIrDA->GetLMP()) 166 167#define super TIrStream 168 OSDefineMetaClassAndStructors(TLSAPConn, TIrStream); 169 170//-------------------------------------------------------------------------------- 171// TLSAPConn 172//-------------------------------------------------------------------------------- 173/*static*/ 174TLSAPConn * 175TLSAPConn::tLSAPConn(TIrGlue* irda, TIrStream* client) 176{ 177 TLSAPConn *obj = new TLSAPConn; 178 179 XTRACE(kNullEvent, 0, obj); 180 181 if (obj && !obj->Init(irda, client)) { 182 obj->release(); 183 obj = nil; 184 } 185 return obj; 186} 187 188 189//-------------------------------------------------------------------------------- 190// free 191//-------------------------------------------------------------------------------- 192void 193TLSAPConn::free() 194{ 195 XTRACE(kDestroy, 0, this); 196 // Free things allocated by TLSAPConn 197 // Release my lsapId if it was obtained 198 if ((fMyLSAPId != kInvalidLSAPId) && (fMyLSAPId != kNameServerLSAPId)) { 199 fIrDA->ReleaseLSAPId(fMyLSAPId); 200 } 201 fMyLSAPId = kInvalidLSAPId; 202 203 if (fPendingRequests) { // cleanup pending event list 204 fPendingRequests->release(); 205 fPendingRequests = nil; 206 } 207 208 super::free(); 209} // TLSAPConn::free 210 211 212//-------------------------------------------------------------------------------- 213// Init 214//-------------------------------------------------------------------------------- 215Boolean TLSAPConn::Init(TIrGlue* irda, TIrStream* client) 216{ 217 218 fState = kLSAPConnDisconnected; 219 fConnecting = false; 220 fClient = nil; 221 fResult = noErr; 222 223 fPendConnLstn = nil; 224 fConnLstnUserData = nil; 225 fGetData = nil; 226 fGetOffset = fGetLength = 0; 227 228 fMyLSAPId = fPeerLSAPId = kInvalidLSAPId; 229 fDevAddr = fLSAPId = 0; 230 231 fPendingRequests = nil; 232 fWatchdogTimerActive = false; 233 fWatchdogTimerCount = 0; 234 235 236#if (hasTracing > 0 && hasLSAPConnTracing > 0) 237 if (!super::Init(irda, IrLSAPConnTraceEvents, kEnqueueEvent)) return false; 238#else 239 if (!super::Init(irda)) return false; 240#endif 241 242 // All confirms/indications directed back to the client 243 fClient = client; 244 245 fPendingRequests = CList::cList(); 246 require(fPendingRequests, Fail); 247 248 return true; 249 250Fail: 251 252 return false; 253 254} // TLSAPConn::Init 255 256 257//-------------------------------------------------------------------------------- 258// AssignId 259//-------------------------------------------------------------------------------- 260void TLSAPConn::AssignId(ULong id) 261{ 262 XASSERT(fMyLSAPId == kInvalidLSAPId); 263 fMyLSAPId = (UByte)id; 264 265} // TLSAPConn::AssignId 266 267 268//-------------------------------------------------------------------------------- 269// GetMyLSAPId 270//-------------------------------------------------------------------------------- 271UByte TLSAPConn::GetMyLSAPId(void) 272{ 273 XTRACE(kGetMyId, 0, this); 274 XTRACE(kGetMyId, 0, fMyLSAPId); 275 return fMyLSAPId; 276}; 277 278 279 280//-------------------------------------------------------------------------------- 281// NextState 282//-------------------------------------------------------------------------------- 283void TLSAPConn::NextState(ULong event) 284{ 285 switch (fState) { 286 case kLSAPConnDisconnected: 287 HandleDisconnectedStateEvent(event); 288 break; 289 290 case kLSAPConnConnectPending: 291 HandleConnectPendingStateEvent(event); 292 break; 293 294 case kLSAPConnConnect: 295 HandleConnectStateEvent(event); 296 break; 297 298 case kLSAPConnListenPending: 299 HandleListenPendingStateEvent(event); 300 break; 301 302 case kLSAPConnListen: 303 HandleListenStateEvent(event); 304 break; 305 306 case kLSAPConnAccept: 307 HandleAcceptStateEvent(event); 308 break; 309 310 case kLSAPConnDataTransferReady: 311 HandleDataTransferReadyStateEvent(event); 312 break; 313 314 case kLSAPDisconnectPending: 315 HandleDisconnectPendingStateEvent(event); 316 break; 317 318 319 default: 320 DebugLog("TLSAPConn::NextState: bad fState"); 321 break; 322 } 323 324} // TLSAPConn::NextState 325 326 327//-------------------------------------------------------------------------------- 328// HandleDisconnectedStateEvent 329//-------------------------------------------------------------------------------- 330void TLSAPConn::HandleDisconnectedStateEvent(ULong event) 331{ 332 switch (event) { 333 case kIrConnectRequestEvent: 334 case kIrListenRequestEvent: 335 { 336 XTRACE(event == kIrConnectRequestEvent ? kDiscConnectEvent : kDiscListenEvent, fMyLSAPId, 0); 337 // Forward the connect/listen request to IrLAPConn (via LMP station control) 338 TIrConnLstnRequest* connLstnReq = (TIrConnLstnRequest*)GetCurrentEvent(); 339 340 // Queue request for LMP 341 PassRequestToLMP(); 342 343 // Remember original request (to distinguish internal/external disconnect replies) 344 SaveCurrentRequest(); 345 346 // Keep track of original connect request so IrLAPConn can reply 347 XASSERT(fPendConnLstn == nil); 348 fPendConnLstn = GetCurrentEvent(); 349 350 // Remember the user data buffer until needed by GetControlFrame or PutControlFrame 351 fConnLstnUserData = connLstnReq->fData; 352 353 if (event == kIrConnectRequestEvent) { 354 fConnecting = true; 355 356 // For connect, remember lsap id we're connecting to 357 fPeerLSAPId = connLstnReq->fLSAPId; 358 359 // Wait for bind complete 360 fState = kLSAPConnConnectPending; 361 } 362 else { 363 fConnecting = false; 364 365 // For listen, set lsap id to pending connect 366 fPeerLSAPId = kPendingConnectLSAPId; 367 368 // Wait for bind complete 369 fState = kLSAPConnListenPending; 370 } 371 } 372 break; 373 374 case kIrDisconnectRequestEvent: 375 { 376 XTRACE(kDiscDiscRequestEvent, 0, 0); 377 // We're not connected - return reply back to client 378 TIrDisconnectRequest* disconnectReq = (TIrDisconnectRequest*)GetCurrentEvent(); 379 disconnectReq->fEvent = kIrDisconnectReplyEvent; 380 fClient->EnqueueEvent(disconnectReq); 381 } 382 break; 383 384 case kIrGetDataRequestEvent: 385 case kIrPutDataRequestEvent: 386 { 387 // Throw any get/put requests that were in the pipeline back with an error 388 TIrEvent* getPutReq = (TIrEvent*)GetCurrentEvent(); 389 XTRACE(kDiscLeftoversReplyEvent, event, 0); 390 XTRACE(kDiscLeftoversReplyEvent, 0, fClient); // testing 391 getPutReq->fEvent = (UByte)RequestIdToReplyId(getPutReq->fEvent); 392 getPutReq->fResult = kIrDAErrNotConnected; // ***FIXME: Better result code? 393 fClient->EnqueueEvent(getPutReq); 394 } 395 break; 396 397 case kIrGetDataReplyEvent: 398 case kIrPutDataReplyEvent: 399 case kIrDisconnectReplyEvent: 400 { 401 check(event != kIrDisconnectReplyEvent); // jdg: shouldn't be getting disconnect complete anymore 402 // Some requests unwind after going to the disconnect state 403 // Pass the replies up to the client 404 TIrEvent* reply = (TIrEvent*)GetCurrentEvent(); 405 XTRACE(kDiscLeftoversReplyEvent, event, reply->fPendEvent); 406 XTRACE(kDiscLeftoversReplyEvent, 0, fClient); // testing 407 reply->fEvent = (UByte)RequestIdToReplyId(reply->fPendEvent); 408 fClient->EnqueueEvent(reply); 409 } 410 break; 411 412 default: 413 XTRACE(kUnexpectedEvent, fState, event); 414 DebugLog("TLSAPConn::HandleDisconnectedStateEvent: bad event"); 415 break; 416 } 417 418} // TLSAPConn::HandleDisconnectedStateEvent 419 420 421//-------------------------------------------------------------------------------- 422// HandleConnectPendingStateEvent 423//-------------------------------------------------------------------------------- 424void TLSAPConn::HandleConnectPendingStateEvent(ULong event) 425{ 426 switch (event) { 427 case kIrConnectReplyEvent: 428 { 429 TIrConnLstnReply* connectReply = (TIrConnLstnReply*)GetCurrentEvent(); 430 XTRACE(kConnectPendConnectReplyEvent, 0, connectReply->fResult); 431 if (connectReply->fResult != noErr) { 432 // Connect failed - unbind from LAPConn. 433 DisconnectStart(connectReply->fResult); // need to take this lsapconn off lapconn's list 434 //fPendConnLstn = nil; // jdg 435 //fState = kLSAPConnDisconnected; // jdg added 436 //fClient->EnqueueEvent(GetCurrentEvent()); // jdg added 437 } 438 else { 439 // JDG: SAVE SOME USEFUL INFO from the connect reply event record! 440 fDevAddr = connectReply->fDevAddr; // restored to event record during listen complete 441 fLSAPId = connectReply->fLSAPId; 442 443 // Connect succeeded - send LM-PDU connect request 444 PutControlFrame(kLMPDUConnectRequest, 0); 445 } 446 } 447 break; 448 449 case kIrPutDataReplyEvent: 450 { 451 TIrPutReply* putReply = (TIrPutReply*)GetCurrentEvent(); 452 XTRACE(kConnectPendPutReplyEvent, 0, putReply->fResult); 453 // The LM-PDU connect request has been sent and received by peer device 454 if (putReply->fResult != noErr) { 455 // Put failed (perhaps IrLAP disconnected) - unbind from LAPConn. 456 DisconnectStart(putReply->fResult); 457 } 458 else { 459 // Start watchdog timer 460 StartConnectTimer(); 461 // Now wait for the LM-PDU connect reply 462 GetControlFrame(); 463 fState = kLSAPConnConnect; 464 } 465 } 466 break; 467 468 case kIrDisconnectRequestEvent: 469 { 470 XTRACE(kConnectPendDiscRequestEvent, 0, 0); 471 // Remember original request (to distinguish internal/external disconnect replies) 472 SaveCurrentRequest(); 473 fState = kLSAPDisconnectPending; // JDG: we're on the way out, change state 474 // Pass disconnect on 475 PassRequestToLMP(); 476 } 477 break; 478 479 case kIrDisconnectReplyEvent: 480 { 481 check(event != kIrDisconnectReplyEvent); // jdg: shouldn't be getting disconnect complete anymore 482 fState = kLSAPConnDisconnected; 483 if (InternalDisconnectRequest()) { 484 XTRACE(kConnectPendDiscReplyEvent, 0, fResult); 485 ConnLstnComplete(fResult); 486 } 487 else { 488 XTRACE(kConnectPendDiscReplyEvent, 0, 0); 489 fPendConnLstn = nil; // jdg: this is done by ConnLstnComplete, need it here too 490 fClient->EnqueueEvent(GetCurrentEvent()); 491 } 492 } 493 break; 494 495 default: 496 XTRACE(kUnexpectedEvent, fState, event); 497 DebugLog("TLSAPConn::HandleConnectPendingStateEvent: bad event"); 498 break; 499 } 500 501} // TLSAPConn::HandleConnectPendingStateEvent 502 503 504//-------------------------------------------------------------------------------- 505// HandleConnectStateEvent 506//-------------------------------------------------------------------------------- 507void TLSAPConn::HandleConnectStateEvent(ULong event) 508{ 509 switch (event) { 510 case kIrGetDataReplyEvent: 511 { 512 TIrGetReply* getReply = (TIrGetReply*)GetCurrentEvent(); 513 XTRACE(kConnectGetReplyEvent, getReply->fCtrlOpCode, getReply->fResult); 514 // Cancel watchdog timer 515 StopConnectTimer(); 516 if (getReply->fResult != noErr) { 517 // Get failed (perhaps IrLAP disconnected) - unbind from LAPConn. 518 DisconnectStart(getReply->fResult); 519 } 520 else { 521 switch(getReply->fCtrlOpCode) { 522 case kLMPDUConnectRequest: 523 DisconnectStart(kIrDAErrGeneric /* FIXME: kIrErrConnectionRace */); 524 break; 525 526 case kLMPDUDisconnectEvent: 527 // ***FIXME: Translate fCtrlInfo to result code? 528 DisconnectStart(kIrDAErrGeneric /* FIXME: kIrErrSomeError */); 529 break; 530 531 case kLMPDUConnectReply: 532 ConnLstnComplete(noErr); 533 fState = kLSAPConnDataTransferReady; 534 break; 535 536 default: 537 DebugLog("TLSAPConn::HandleConnectStateEvent: unexpected ctrl opcode"); 538 break; 539 } 540 } 541 } 542 break; 543 544 case kIrConnWatchdogExpiredEvent: 545 { 546 XTRACE(kConnectWatchdogTimeoutEvent, 0, 0); 547 // Cancel watchdog timer 548 StopConnectTimer(); 549 550 // JDG: I don't think we can just grab our pending listen event, since it's been turned 551 // into a 'get' event request and passed onto LMP and LAPConn and LAP 552 //DisconnectStart(kIRErrGeneric /* FIXME: kIrErrNonResponsivePeer */, (TIrDisconnectRequest*)fPendConnLstn); 553 if (1) { // let's allocate a new event block for a disconnect request 554 TIrDisconnectRequest *disconnectRequest; 555 disconnectRequest = (TIrDisconnectRequest*)fIrDA->GrabEventBlock(kIrDisconnectRequestEvent, sizeof(TIrDisconnectRequest)); 556 check(disconnectRequest); // better have one available 557 if (disconnectRequest) { 558 // we're going to use the fPendEvent field as a flag to disconnect complete that 559 // this event is one that we've allocated ourselves, not to be confused with a 560 // client disconnect request, or another internally generated disconnect request 561 // and one that should have the event record freed! 562 disconnectRequest->fPendEvent = kIrConnWatchdogExpiredEvent; // mark as ours 563 DisconnectStart(kIrDAErrGeneric, disconnectRequest); 564 // note - in disconnect reply, it frees the event record fPendingEvent is watchdog 565 } 566 } 567 } 568 break; 569 570 case kIrDisconnectRequestEvent: 571 XTRACE(kConnectDisconnectRequestEvent, 0, 0); 572 // Cancel watchdog timer 573 StopConnectTimer(); 574 // Remember original request (to distinguish internal/external disconnect replies) 575 SaveCurrentRequest(); 576 fState = kLSAPDisconnectPending; // JDG: we're on the way out, change state 577 // Pass disconnect on 578 PassRequestToLMP(); 579 break; 580 581 case kIrDisconnectReplyEvent: 582 check(event != kIrDisconnectReplyEvent); // jdg: shouldn't be getting disconnect complete anymore 583 fState = kLSAPConnDisconnected; 584 if (InternalDisconnectRequest()) { 585 XTRACE(kConnectDisconnectReplyEvent, 0, fResult); 586 ConnLstnComplete(fResult); 587 } 588 else { 589 XTRACE(kConnectDisconnectReplyEvent, 0, 0); 590 fPendConnLstn = nil; // jdg: this is done by ConnLstnComplete, need it here too 591 fClient->EnqueueEvent(GetCurrentEvent()); 592 } 593 break; 594 595 default: 596 XTRACE(kUnexpectedEvent, fState, event); 597 DebugLog("TLSAPConn::HandleConnectStateEvent: bad event"); 598 break; 599 } 600 601} // TLSAPConn::HandleConnectStateEvent 602 603 604//-------------------------------------------------------------------------------- 605// HandleListenPendingStateEvent 606//-------------------------------------------------------------------------------- 607void TLSAPConn::HandleListenPendingStateEvent(ULong event) 608{ 609 switch (event) { 610 case kIrListenReplyEvent: 611 { 612 TIrConnLstnReply* listenReply = (TIrConnLstnReply*)GetCurrentEvent(); 613 XTRACE(kListenPendListenReplyEvent, fMyLSAPId, listenReply->fResult); 614 if (listenReply->fResult != noErr) { 615 // Listen failed - unbind from LAPConn. 616 DisconnectStart(listenReply->fResult); // jdg . may be broken 617 ///////////////////////////////////////////////////////////////////////////// 618 //fPendConnLstn = nil; // jdg added 619 //fState = kLSAPConnDisconnected; // jdg added 620 //fClient->EnqueueEvent(GetCurrentEvent()); // jdg added 621 622 } 623 else { 624 // JDG: SAVE SOME USEFUL INFO from the listen reply event record! 625 fDevAddr = listenReply->fDevAddr; // restored to event record during listen complete 626 fLSAPId = listenReply->fLSAPId; 627 628 // Wait for an LM-PDU connect request 629 GetControlFrame(); 630 fState = kLSAPConnListen; 631 } 632 } 633 break; 634 635 case kIrDisconnectRequestEvent: 636 XTRACE(kListenPendDiscRequestEvent, 0, 0); 637 // Remember original request (to distinguish internal/external disconnect replies) 638 SaveCurrentRequest(); 639 fState = kLSAPDisconnectPending; // JDG: we're on the way out, change state 640 // Pass disconnect on 641 PassRequestToLMP(); 642 break; 643 644 case kIrDisconnectReplyEvent: 645 check(event != kIrDisconnectReplyEvent); // jdg: shouldn't be getting disconnect complete anymore 646 fState = kLSAPConnDisconnected; 647 if (InternalDisconnectRequest()) { 648 XTRACE(kListenPendDiscReplyEvent, 1, fResult); 649 // jdg: well if it's an internal disconnect, why bother the lsap owner with an 650 // abort? let's just requeue it and let it work later 651 ConnLstnComplete(fResult); 652 if (0) { // needs more testing 653 TIrConnLstnRequest *req = (TIrConnLstnRequest*)GetCurrentEvent(); 654 check(req->fPendEvent == kIrListenRequestEvent); 655 req->fEvent = req->fPendEvent; // restore original request 656 fPendConnLstn = nil; // reset pending 657 this->EnqueueEvent(req); // requeue back for another try 658 } 659 } 660 else { 661 XTRACE(kListenPendDiscReplyEvent, 2, 0); 662 if (1) { // jdg: new code to clean up pending listen request 663 TIrConnLstnReply* reply = (TIrConnLstnReply*)fPendConnLstn; 664 XASSERT(fPendConnLstn != nil); // there should be a pending listen at this point 665 reply->fEvent = (UByte)RequestIdToReplyId(reply->fPendEvent); // turn into listen complete 666 reply->fResult = kIrDAErrRequestCanceled; 667 fClient->EnqueueEvent(reply); 668 } 669 fPendConnLstn = nil; // jdg: this is done by ConnLstnComplete, need it here too 670 fClient->EnqueueEvent(GetCurrentEvent()); // jdg: or we can't do another listen/connect request 671 } 672 break; 673 674 default: 675 XTRACE(kUnexpectedEvent, fState, event); 676 DebugLog("TLSAPConn::HandleListenPendingStateEvent: bad event"); 677 break; 678 } 679 680} // TLSAPConn::HandleListenPendingStateEvent 681 682 683//-------------------------------------------------------------------------------- 684// HandleListenStateEvent 685//-------------------------------------------------------------------------------- 686void TLSAPConn::HandleListenStateEvent(ULong event) 687{ 688 switch (event) { 689 case kIrGetDataReplyEvent: 690 { 691 TIrGetReply *getReply = (TIrGetReply *) GetCurrentEvent(); 692 XTRACE(kListenGetReplyEvent, getReply->fCtrlOpCode, getReply->fResult); 693 if (getReply->fResult != noErr) { 694 // Get failed (perhaps IrLAP disconnected) - unbind from LAPConn. 695 DisconnectStart(getReply->fResult); // jdg - may be broken 696 //fPendConnLstn = nil; // jdg added 697 //fState = kLSAPConnDisconnected; // jdg added 698 //fClient->EnqueueEvent(GetCurrentEvent()); // jdg added 699 } 700 else { 701 switch(getReply->fCtrlOpCode) { 702 case kLMPDUDataEvent: 703 case kLMPDUConnectReply: 704 PutControlFrame(kLMPDUDisconnectEvent, kIrDataSentOnDiscLSAPConn); 705 break; 706 707 case kLMPDUConnectRequest: 708 { 709 TIrConnLstnReply* listenReply = (TIrConnLstnReply*)GetCurrentEvent(); 710 711 // Do the LM-Listen reply 712 listenReply->fLSAPId = fPeerLSAPId; 713 ConnLstnComplete(noErr); 714 fState = kLSAPConnAccept; 715 } 716 break; 717 718 default: 719 DebugLog("TLSAPConn::HandleListenStateEvent: unexpected ctrl opcode"); 720 break; 721 } 722 } 723 } 724 break; 725 726 case kIrPutDataReplyEvent: 727 { 728 TIrPutReply *putReply = (TIrPutReply *) GetCurrentEvent(); 729 XTRACE(kListenPutReplyEvent, 0, putReply->fResult); 730 // The LM-PDU disconnect event has been sent and received by peer device 731 if (putReply->fResult != noErr) { 732 // Put failed (perhaps IrLAP disconnected) - unbind from LAPConn. 733 DisconnectStart(putReply->fResult); 734 } 735 else { 736 // Wait for an LM-PDU connect request (again) 737 GetControlFrame(); 738 } 739 } 740 break; 741 742 case kIrDisconnectRequestEvent: 743 XTRACE(kListenDisconnectRequestEvent, 0, 0); 744 // Remember original request (to distinguish internal/external disconnect replies) 745 SaveCurrentRequest(); 746 fState = kLSAPDisconnectPending; // JDG: we're on the way out, change state 747 // Pass disconnect on 748 PassRequestToLMP(); 749 break; 750 751 case kIrDisconnectReplyEvent: 752 check(event != kIrDisconnectReplyEvent); // jdg: shouldn't be getting disconnect complete anymore 753 fState = kLSAPConnDisconnected; 754 if (InternalDisconnectRequest()) { 755 XTRACE(kListenDisconnectReplyEvent, 0, fResult); 756 ConnLstnComplete(fResult); 757 if (0) { // jdg: let's reissue the listen instead of aborting it 758 TIrConnLstnRequest *req = (TIrConnLstnRequest*)GetCurrentEvent(); 759 //check(req->fPendEvent == kIrListenRequestEvent); 760 if (req->fPendEvent == kIrListenRequestEvent) { // if a listen pending 761 req->fEvent = req->fPendEvent; // restore original request 762 fPendConnLstn = nil; // reset pending 763 this->EnqueueEvent(req); // requeue back for another try 764 } 765 } 766 767 } 768 else { 769 XTRACE(kListenDisconnectReplyEvent, 0, 0); 770 fPendConnLstn = nil; // jdg: this is done by ConnLstnComplete, need it here too 771 fClient->EnqueueEvent(GetCurrentEvent()); 772 } 773 break; 774 775 default: 776 XTRACE(kUnexpectedEvent, fState, event); 777 DebugLog("TLSAPConn::HandleListenStateEvent: bad event"); 778 break; 779 } 780 781} // TLSAPConn::HandleListenStateEvent 782 783 784//-------------------------------------------------------------------------------- 785// HandleAcceptStateEvent 786//-------------------------------------------------------------------------------- 787void TLSAPConn::HandleAcceptStateEvent(ULong event) 788{ 789 switch (event) { 790 case kIrAcceptRequestEvent: 791 // Client accepts the incoming connection 792 XTRACE(kAcceptConnectRequestEvent, 0, 0); 793 // Remember the accept request (to distinguish internal/external disconnect replies) 794 SaveCurrentRequest(); 795 // Remember the user data buffer until needed by PutControlFrame 796 fConnLstnUserData = ((TIrConnLstnRequest*)GetCurrentEvent())->fData; 797 // Send a LM-Listen reply 798 PutControlFrame(kLMPDUConnectReply, 0); 799 break; 800 801 case kIrDisconnectRequestEvent: 802 // Client rejects the incoming connection 803 XTRACE(kRejectConnectRequestEvent, 0, 0); 804 // Remember the disconnect request (to distinguish internal/external disconnect replies) 805 SaveCurrentRequest(); 806 // Send a Disconnect request 807 PutControlFrame(kLMPDUDisconnectEvent, kIrUserRequestedDisconnect); 808 break; 809 810 case kIrPutDataReplyEvent: 811 XTRACE(kAccRejPutReplyEvent, 0, 0); 812 if (GetCurrentEvent()->fPendEvent == kIrAcceptRequestEvent) { 813 // Finish up the accept of the connection 814 // The LM-PDU connect reply has been sent and received by peer device 815 // Now ready to send and receive data on this connection 816 // Let the caller know by replying to the accept 817 TIrPutReply* putReply = (TIrPutReply*)GetCurrentEvent(); 818 if (putReply->fResult != noErr) { 819 DisconnectStart(putReply->fResult); 820 } 821 else { 822 ConnLstnComplete(noErr); 823 fState = kLSAPConnDataTransferReady; 824 } 825 } 826 else { 827 XASSERT(GetCurrentEvent()->fPendEvent == kIrDisconnectRequestEvent); 828 // Finish up the rejection of the connection 829 // The LM-PDU disconnect has been sent and received by peer device 830 // Now unbind from LAPConn. 831 // Note: passing noErr since initiated by client. 832 // Note: Do the disconnect even if error came back from put. 833 DisconnectStart(noErr); 834 } 835 break; 836 837 case kIrDisconnectReplyEvent: 838 check(event != kIrDisconnectReplyEvent); // jdg: shouldn't be getting disconnect complete anymore 839 XTRACE(kAccRejDisconnectReplyEvent, 0, fResult); 840 // LAPConn unbind complete. Now complete the accept or disconnect request 841 ConnLstnComplete(fResult); 842 fState = kLSAPConnDisconnected; 843 break; 844 845 default: 846 XTRACE(kUnexpectedEvent, fState, event); 847 DebugLog("TLSAPConn::HandleAcceptStateEvent: bad event"); 848 break; 849 } 850 851} // TLSAPConn::HandleAcceptStateEvent 852 853 854//-------------------------------------------------------------------------------- 855// HandleDataTransferReadyStateEvent 856//-------------------------------------------------------------------------------- 857void TLSAPConn::HandleDataTransferReadyStateEvent(ULong event) 858{ 859 switch (event) { 860 case kIrGetDataRequestEvent: 861 XTRACE(kDTRGetRequestEvent, 0, 0); 862 // Remember original request (to distinguish internal/external disconnect replies) 863 SaveCurrentRequest(); 864 // Pass get request to station control (LMP) 865 GetDataFrame(); 866 break; 867 868 case kIrPutDataRequestEvent: 869 XTRACE(kDTRPutRequestEvent, 0, 0); 870 // Remember original request (to distinguish internal/external disconnect/put replies) 871 SaveCurrentRequest(); 872 // Fill in opCode, dstSel, srcSel fields and pass request to station control (LMP) 873 PutDataFrame(); 874 break; 875 876 case kIrCancelGetRequestEvent: 877 case kIrCancelPutRequestEvent: 878 XTRACE(event == kIrCancelGetRequestEvent ? kDTRCancelGetRequestEvent : kDTRCancelPutRequestEvent, 0, 0); 879 // Pass request to station control (LMP) 880 PassRequestToLMP(); 881 break; 882 883 case kIrReleaseRequestEvent: 884 case kIrDisconnectRequestEvent: 885 XTRACE(event == kIrReleaseRequestEvent ? kDTRReleaseRequestEvent : kDTRDisconnectRequestEvent, 0, 0); 886 // Remember original request (to distinguish internal/external disconnect replies) 887 SaveCurrentRequest(); 888 // Send a Disconnect request 889 fState = kLSAPDisconnectPending; // JDG: we're on the way out, change state 890 PutControlFrame(kLMPDUDisconnectEvent, kIrUserRequestedDisconnect); 891 break; 892 893 case kIrGetDataReplyEvent: 894 { 895 TIrGetReply* getReply = (TIrGetReply*)GetCurrentEvent(); 896 XTRACE(kDTRGetReplyEvent, getReply->fCtrlOpCode, 0); 897 if (getReply->fResult != noErr) { 898 // Check to see if get was cancelled (vs error from IrLAP) 899 if (getReply->fResult == kIrDAErrRequestCanceled) { 900 // Pass get reply up to the client 901 fClient->EnqueueEvent(getReply); 902 } 903 // Get failed (perhaps IrLAP disconnected) - unbind from LAPConn. 904 else { 905 DisconnectStart(getReply->fResult); 906 } 907 } 908 else { 909 switch(getReply->fCtrlOpCode) { 910 case kLMPDUDataEvent: 911 // Pass get reply up to the client 912 fClient->EnqueueEvent(getReply); 913 break; 914 915 case kLMPDUConnectRequest: 916 // Reply with half open error 917 PutControlFrame(kLMPDUDisconnectEvent, kIrHalfOpen); 918 break; 919 920 case kLMPDUDisconnectEvent: 921 // ***FIXME: Translate fCtrlInfo to result code? 922 DisconnectStart(kIrDAErrGeneric /* FIXME: kIrErrSomeError */); 923 break; 924 925 default: 926 DebugLog("TLSAPConn::HandleDataTransferReadyStateEvent: unexpected ctrl opcode"); 927 GetDataFrame(true /* re-"posting" the request*/); 928 break; 929 } 930 } 931 } 932 break; 933 934 case kIrPutDataReplyEvent: 935 { 936 TIrPutReply* putReply = (TIrPutReply*)GetCurrentEvent(); 937 XTRACE(kDTRPutReplyEvent, 0, putReply->fResult); 938 if (InternalPutRequest()) { 939 // If put reply was initiated by release or disconnect, send disconnect 940 if ((putReply->fPendEvent == kIrReleaseRequestEvent) || (putReply->fPendEvent == kIrDisconnectRequestEvent)) { 941 DisconnectStart(noErr); 942 } 943 // Else put reply was in response to an unwanted received control frame (a connect) 944 else { 945 XASSERT(putReply->fPendEvent == kIrGetDataRequestEvent); 946 DisconnectStart(kIrDAErrGeneric /* FIXME: kIrErrHalfOpen */); 947 } 948 } 949 else { 950 // Pass put reply up to the client 951 fClient->EnqueueEvent(putReply); 952 } 953 } 954 break; 955 956 case kIrCancelGetReplyEvent: 957 case kIrCancelPutReplyEvent: 958 XTRACE(event == kIrCancelGetReplyEvent ? kDTRCancelGetReplyEvent : kDTRCancelPutReplyEvent, 0, 0); 959 // Pass put reply up to the client 960 fClient->EnqueueEvent(GetCurrentEvent()); 961 break; 962 963 case kIrDisconnectReplyEvent: 964 check(event != kIrDisconnectReplyEvent); // jdg: shouldn't be getting disconnect complete anymore 965 if (InternalDisconnectRequest()) { 966 // Finish up whichever request initiated the disconnect 967 TIrEvent* reply = (TIrEvent*)GetCurrentEvent(); 968 XTRACE(kDTRDisconnectReplyEvent, 0, fResult); 969 // Pass reply up to the client 970 reply->fEvent = (UByte)RequestIdToReplyId(reply->fPendEvent); 971 reply->fResult = fResult; 972 fClient->EnqueueEvent(reply); 973 } 974 else { 975 TIrDisconnectReply* disconnectReply; 976 disconnectReply = (TIrDisconnectReply*)GetCurrentEvent(); 977 XTRACE(kDTRDisconnectReplyEvent, 0, disconnectReply->fResult); 978 // Pass disconnect reply up to the client 979 fClient->EnqueueEvent(disconnectReply); 980 } 981 fPendConnLstn = nil; // jdg: this is done by ConnLstnComplete, need it here too (?) 982 fState = kLSAPConnDisconnected; 983 break; 984 985 default: 986 XTRACE(kUnexpectedEvent, fState, event); 987 DebugLog("TLSAPConn::HandleDataTransferReadyStateEvent: bad event"); 988 break; 989 } 990 991} // TLSAPConn::HandleDataTransferReadyStateEvent 992 993//-------------------------------------------------------------------------------- 994// HandleDisconnectPendingStateEvent 995//-------------------------------------------------------------------------------- 996void TLSAPConn::HandleDisconnectPendingStateEvent(ULong event) 997{ 998 TIrEvent* eventBlock = (TIrEvent*)GetCurrentEvent(); 999 //static int rejectCount = 0; // temp debugging 1000 1001 XTRACE(kLogDiscPendingEvent, 0, event); 1002 XTRACE(kLogDiscPendingClient, 0, fClient); 1003 1004 switch (event) { 1005 1006 case kIrDisconnectRequestEvent: // stall these requests until we can handle them 1007 case kIrConnectRequestEvent: 1008 case kIrListenRequestEvent: 1009 fPendingRequests->InsertLast(GetCurrentEvent()); 1010 break; 1011 1012 // we have a disconnect pending, don't do new requests 1013 case kIrAcceptRequestEvent: // we have a disconnect pending, don't do new requests yet 1014 case kIrGetDataRequestEvent: 1015 case kIrPutDataRequestEvent: 1016 // just send these back to the client 1017 //rejectCount++; // debugging 1018 //XTRACE(kLogDiscPendingRejectRequest, rejectCount, event); 1019 eventBlock->fEvent = (UByte)RequestIdToReplyId(eventBlock->fEvent); 1020 eventBlock->fResult = kIrDAErrNotConnected; 1021 fClient->EnqueueEvent(eventBlock); 1022 //if (rejectCount == 20) DebugLog("lsapconn reject count hit 20"); 1023 break; 1024 1025 // convert event back to reply of original, who cares if it worked or not, 1026 // we have a disconnect reply coming real soon now 1027 case kIrListenReplyEvent: 1028 case kIrConnectReplyEvent: 1029 eventBlock->fResult = kIrDAErrNotConnected; // lap listen/conn reply, but we're disconnecting 1030 // continue on 1031 case kIrGetDataReplyEvent: 1032 case kIrPutDataReplyEvent: 1033 XTRACE(kLogDiscPendingMiscReply, event, eventBlock->fPendEvent); 1034 if (GetCurrentEvent() == fPendConnLstn) { 1035 XTRACE(kLogDiscPendingConnLstnDone, 0, fPendConnLstn); 1036 fPendConnLstn = nil; // there isn't a listen/connect pending event anymore 1037 } 1038 1039 eventBlock->fEvent = (UByte)RequestIdToReplyId(eventBlock->fPendEvent); 1040 // don't stop on the result, it might have worked, esp with 1041 // a lookup release request! 1042 //eventBlock->fResult = kCommErrNotConnected; 1043 1044 // oh my. if the client requested a disconnect, then the event is a putreply, even 1045 // though the client requested a disconnect. Sigh. Let's rewrite this to use a 1046 // different event record in the lsap/lmp/lap path than the one passed to us by 1047 // the client! Ok, let's see what's getting returned to the client .... 1048 if (eventBlock->fEvent == kIrDisconnectReplyEvent // client asked for a disconnect 1049 || eventBlock->fEvent == kIrReleaseReplyEvent) { // client asked for a disconnect via release 1050 check(fPendConnLstn == nil); // should already have been cleared 1051 DisconnectStart(noErr); // need to unbind from LAPConn's list of active LSAPConns 1052 } 1053 else 1054 fClient->EnqueueEvent(eventBlock); 1055 break; 1056 1057 1058 case kIrDisconnectReplyEvent: 1059 if (InternalDisconnectRequest()) { 1060 // Finish up whichever request initiated the disconnect 1061 XTRACE(kLogDiscPendingInternalDisc, eventBlock->fPendEvent, fResult); 1062 // Pass reply up to the client 1063 // but only if the event wasn't a disconnect generated by the watchdogtimer 1064 if (eventBlock->fPendEvent != kIrConnWatchdogExpiredEvent) { // have a client's event block 1065 eventBlock->fEvent = (UByte)RequestIdToReplyId(eventBlock->fPendEvent); 1066 eventBlock->fResult = fResult; 1067 fClient->EnqueueEvent(eventBlock); 1068 } 1069 else { // else we have fPendEvent of kIrConnWatchdogExpiredEvent, so it's our event record 1070 DebugLog("IrLSAPConn: just fyi, got disconnect reply after watchdog timeout"); 1071 XTRACE(kLogDiscPendingWatchDog, 0, 0); 1072 fIrDA->ReleaseEventBlock(eventBlock); 1073 } 1074 } 1075 else { // original request was a disconnect request 1076 XTRACE(kLogDiscPendingDiscDone, 0, eventBlock->fResult); 1077 // Pass disconnect reply up to the client 1078 fClient->EnqueueEvent(eventBlock); 1079 } 1080 check(fPendConnLstn == nil); // should already have been cleared 1081 fState = kLSAPConnDisconnected; 1082 1083 // Ok, now that we're cleanly disconnected (I hope), let's requeue all 1084 // the pending requests that we've collected since the disconnect started 1085 if (fPendingRequests && !fPendingRequests->Empty()) { 1086 TIrEvent* request; 1087 CListIterator *iter = CListIterator::cListIterator(fPendingRequests); 1088 for (request = (TIrEvent*)iter->FirstItem(); 1089 iter->More(); request = (TIrEvent*)iter->NextItem()) { 1090 XTRACE(kLogDiscPendingRequeue, 0, request->fEvent); 1091 this->EnqueueEvent(request); 1092 } 1093 while (!fPendingRequests->Empty()) 1094 fPendingRequests->RemoveLast(); 1095 iter->release(); 1096 } 1097 1098 break; 1099 1100 default: 1101 XTRACE(kUnexpectedEvent, fState, event); 1102 DebugLog("TLSAPConn::HandleDisconnectPendingStateEvent: bad event"); 1103 break; 1104 } 1105} // HandleDisconnectPendingStateEvent 1106 1107//================================ Helper methods ================================ 1108 1109 1110//-------------------------------------------------------------------------------- 1111// SaveCurrentRequest 1112//-------------------------------------------------------------------------------- 1113void TLSAPConn::SaveCurrentRequest() 1114{ 1115 TIrEvent* request = GetCurrentEvent(); 1116 1117 // Store the original request in fPendEvent 1118 request->fPendEvent = request->fEvent; 1119 1120} // TLSAPConn::SaveCurrentRequest 1121 1122 1123//-------------------------------------------------------------------------------- 1124// InternalDisconnectRequest? 1125//-------------------------------------------------------------------------------- 1126Boolean TLSAPConn::InternalDisconnectRequest() 1127{ 1128 // Is the current request *not* a disconnect request. If its not, then this must 1129 // be a reply to an internally generated disconnect request sent to IrLMP. 1130 return GetCurrentEvent()->fPendEvent != kIrDisconnectRequestEvent; 1131 1132} // TLSAPConn::InternalDisconnectRequest 1133 1134 1135//-------------------------------------------------------------------------------- 1136// InternalPutRequest? 1137//-------------------------------------------------------------------------------- 1138Boolean TLSAPConn::InternalPutRequest() 1139{ 1140 // Is the current request *not* a put request. If its not, then this must 1141 // be a reply to an internally generated put request sent to IrLMP. 1142 return GetCurrentEvent()->fPendEvent != kIrPutDataRequestEvent; 1143 1144} // TLSAPConn::InternalPutRequest 1145 1146 1147//-------------------------------------------------------------------------------- 1148// GetPendConnLstn 1149//-------------------------------------------------------------------------------- 1150TIrEvent* TLSAPConn::GetPendConnLstn() 1151{ 1152 // This is used by IrLAPConn so it can reply to pending conn/lstn reqs for each LSAP 1153 //XASSERT(fPendConnLstn != nil); // jdg: sometimes it's already open and the pending conn/lstn is nil 1154 return fPendConnLstn; 1155 1156} // TLSAPConn::GetPendConnLstn 1157 1158 1159//-------------------------------------------------------------------------------- 1160// PassRequestToLMP 1161//-------------------------------------------------------------------------------- 1162void TLSAPConn::PassRequestToLMP() 1163{ 1164 // All requests forwarded to LMP need to identify themselves for the reply 1165 TIrLSAPConnEvent* theEvent = (TIrLSAPConnEvent*)GetCurrentEvent(); 1166 1167 theEvent->fLSAPConn = this; 1168 GetLMP->EnqueueEvent(theEvent); 1169 1170} // TLSAPConn::PassRequestToLMP 1171 1172 1173//-------------------------------------------------------------------------------- 1174// DisconnectStart 1175//-------------------------------------------------------------------------------- 1176void TLSAPConn::DisconnectStart(IrDAErr result, TIrDisconnectRequest* discRequest) 1177{ 1178 // JDG: review review review. 1179 fPendConnLstn = nil; // jdg: TEMP TEMP TEMP TEMP 1180 1181 // Use current event block if no request block specified 1182 if (discRequest == nil) { 1183 discRequest = (TIrDisconnectRequest*)GetCurrentEvent(); 1184 } 1185 1186 discRequest->fEvent = kIrDisconnectRequestEvent; 1187 discRequest->fResult = kIrDAErrCancel; 1188 discRequest->fLSAPConn = this; 1189 1190 // Save reason for disconnection for conn/lstn complete after disconnect reply 1191 fResult = result; 1192 1193 fState = kLSAPDisconnectPending; // JDG: we're on the way out 1194 1195 GetLMP->EnqueueEvent(discRequest); 1196 1197} // TLSAPConn::DisconnectStart 1198 1199 1200//-------------------------------------------------------------------------------- 1201// GetControlFrame 1202//-------------------------------------------------------------------------------- 1203void TLSAPConn::GetControlFrame() 1204{ 1205 TIrGetRequest* getRequest = (TIrGetRequest*)GetCurrentEvent(); 1206 1207 // Reset fConnLstnUserData (unhides all) to accept maximum conn user data 1208 if (fConnLstnUserData) { 1209 fConnLstnUserData->Reset(); 1210 } 1211 1212 getRequest->fEvent = kIrGetDataRequestEvent; 1213 getRequest->fResult = noErr; 1214 getRequest->fData = fConnLstnUserData; 1215 getRequest->fOffset = 0; 1216 getRequest->fLength = fConnLstnUserData ? fConnLstnUserData->GetSize() : 0; 1217 1218 // Send get request to station control (LMP) 1219 PassRequestToLMP(); 1220 1221} // TLSAPConn::GetControlFrame 1222 1223 1224//-------------------------------------------------------------------------------- 1225// PutControlFrame 1226//-------------------------------------------------------------------------------- 1227void TLSAPConn::PutControlFrame(UByte opCode, UByte info) 1228{ 1229 CBuffer* data = nil; // Default if not connect or connect reply 1230 TIrPutRequest* putRequest = (TIrPutRequest*)GetCurrentEvent(); 1231 1232 // Only send connect/accept userData if opCode is connect or connect reply. 1233 if ((opCode == kLMPDUConnectRequest) || (opCode == kLMPDUConnectReply)) { 1234 data = fConnLstnUserData; 1235 } 1236 1237 XASSERT(fPeerLSAPId <= kLastValidLSAPId); 1238 1239 putRequest->fEvent = kIrPutDataRequestEvent; 1240 putRequest->fResult = noErr; 1241 putRequest->fData = data; 1242 putRequest->fOffset = 0; 1243 putRequest->fLength = data ? data->GetSize() : 0; 1244 putRequest->fDstLSAPId = fPeerLSAPId; 1245 putRequest->fSrcLSAPId = fMyLSAPId; 1246 putRequest->fCtrlOpCode = opCode; 1247 putRequest->fCtrlInfo = info; 1248 1249 // Send put request to station control (IrLMP) 1250 PassRequestToLMP(); 1251 1252} // TLSAPConn::PutControlFrame 1253 1254 1255//-------------------------------------------------------------------------------- 1256// GetDataFrame 1257//-------------------------------------------------------------------------------- 1258void TLSAPConn::GetDataFrame(Boolean resend) 1259{ 1260 TIrGetRequest* getRequest = (TIrGetRequest*)GetCurrentEvent(); 1261 1262 if (resend) { 1263 // Reset the fields from the original requests data 1264 getRequest->fEvent = kIrGetDataRequestEvent; 1265 getRequest->fResult = noErr; 1266 getRequest->fData = fGetData; 1267 getRequest->fOffset = fGetOffset; 1268 getRequest->fLength = fGetLength; 1269 } 1270 else { 1271 // Save the info needed to recreate the request for resends 1272 fGetData = getRequest->fData; 1273 fGetOffset = getRequest->fOffset; 1274 fGetLength = getRequest->fLength; 1275 } 1276 1277 // Send get request to station control (LMP) 1278 PassRequestToLMP(); 1279 1280} // TLSAPConn::GetDataFrame 1281 1282 1283//-------------------------------------------------------------------------------- 1284// PutDataFrame 1285//-------------------------------------------------------------------------------- 1286void TLSAPConn::PutDataFrame() 1287{ 1288 TIrPutRequest* putRequest = (TIrPutRequest*)GetCurrentEvent(); 1289 1290 XASSERT(fPeerLSAPId <= kLastValidLSAPId); 1291 1292 putRequest->fDstLSAPId = fPeerLSAPId; 1293 putRequest->fSrcLSAPId = fMyLSAPId; 1294 putRequest->fCtrlOpCode = kLMPDUDataEvent; 1295 putRequest->fCtrlInfo = 0; 1296 1297 // Send put request to station control (IrLMP) 1298 PassRequestToLMP(); 1299 1300} // TLSAPConn::PutDataFrame 1301 1302 1303//-------------------------------------------------------------------------------- 1304// ConnLstnComplete 1305//-------------------------------------------------------------------------------- 1306void TLSAPConn::ConnLstnComplete(IrDAErr result) 1307{ 1308 TIrConnLstnReply* reply = (TIrConnLstnReply*)GetCurrentEvent(); 1309 1310#ifdef forDebug 1311 if ((reply->fPendEvent == kIrConnectRequestEvent) || (reply->fPendEvent == kIrListenRequestEvent)) { 1312 XASSERT(fPendConnLstn != nil); 1313 } 1314#endif 1315 fPendConnLstn = nil; 1316 if (reply->fPendEvent == kIrConnectRequestEvent) // ONLY if connect response 1317 reply->fLSAPId = fLSAPId; // jdg: restore peer lsap id 1318 /// TODO review fLSAPID vs fPeerLSAPId 1319 1320 reply->fEvent = (UByte)RequestIdToReplyId(reply->fPendEvent); 1321 reply->fResult = result; 1322 reply->fDevAddr = fDevAddr; // jdg: restore peer address 1323 //reply->fLSAPId = fLSAPId; // jdg: restore peer lsap id 1324 fClient->EnqueueEvent(reply); 1325 1326} // TLSAPConn::ConnLstnComplete 1327 1328 1329//-------------------------------------------------------------------------------- 1330// YourData 1331//-------------------------------------------------------------------------------- 1332Boolean TLSAPConn::YourData(TLMPDUHeader& header, Boolean justChecking) 1333{ 1334 XTRACE( kMyData, header.fDstLSAPId, fMyLSAPId ); 1335 if (header.fDstLSAPId == fMyLSAPId) { 1336 if (header.fSrcLSAPId == fPeerLSAPId) { 1337 XTRACE( kDataForMe, header.fOpCode, header.fSrcLSAPId ); 1338 return true; 1339 } 1340 else if (fPeerLSAPId == kPendingConnectLSAPId) { 1341 // Listen receives its connect request 1342 // could be in listen or pending disconnect state ... jdg 1343 XASSERT(fState == kLSAPConnListen || fState == kLSAPDisconnectPending); 1344 //if (fState != kLSAPConnListen) { // bogus,jdg:: could also be in disconnect pending or... 1345 // XTRACE(kLogRejectingMyData, 0, fState); 1346 // return false; // jdg: just drop it if we don't really want it 1347 //} 1348 XTRACE( kDataWaitingForMe, header.fOpCode, header.fSrcLSAPId ); 1349 if (header.fOpCode == kLMPDUConnectRequest) { 1350 if (!justChecking) { 1351 fPeerLSAPId = header.fSrcLSAPId; 1352 } 1353 return true; 1354 } 1355 } 1356 } 1357 1358 return false; 1359 1360} // TLSAPConn::YourData 1361 1362 1363//-------------------------------------------------------------------------------- 1364// StartConnectTimer 1365//-------------------------------------------------------------------------------- 1366void TLSAPConn::StartConnectTimer() 1367{ 1368 fWatchdogTimerActive = true; 1369 fWatchdogTimerCount = 0; 1370 GetLMP->StartOneSecTicker(); 1371 1372} // TLSAPConn::StartConnectTimer 1373 1374 1375//-------------------------------------------------------------------------------- 1376// StopConnectTimer 1377//-------------------------------------------------------------------------------- 1378void TLSAPConn::StopConnectTimer() 1379{ 1380 fWatchdogTimerActive = false; 1381 GetLMP->StopOneSecTicker(); 1382 1383} // TLSAPConn::StopConnectTimer 1384 1385 1386//-------------------------------------------------------------------------------- 1387// OneSecTickerComplete 1388//-------------------------------------------------------------------------------- 1389void TLSAPConn::OneSecTickerComplete() 1390{ 1391 // Ignore the ticker complete if I'm not currently connecting 1392 if (!fWatchdogTimerActive) return; 1393 1394 // Shouldn't be active unless we're connecting 1395 XASSERT(fState == kLSAPConnConnect); 1396 1397 // Connect has timed out if reached the timeout count 1398 if (++fWatchdogTimerCount >= kWatchdogTimeoutCount) { 1399 NextState(kIrConnWatchdogExpiredEvent); 1400 } 1401 1402} // TLSAPConn::OneSecTickerComplete 1403 1404