1/* 2 File: CIrLSAP.c 3 4 Contains: IrDA client routines for TinyTP (and others) 5 6 7*/ 8 9 10#include "CIrLSAP.h" 11#include "IrIASClient.h" 12#include "IrIASService.h" 13#include "IrGlue.h" 14#include "IrLSAPConn.h" 15#include "CBufferSegment.h" 16#include "IrDALog.h" 17 18#if (hasTracing > 0 && hasIrLSAPTracing > 0) 19 20enum IrLSAPTraceCodes 21{ 22 kLogNew = 1, 23 kLogFree, 24 kLogInit, 25 26 kUnexpectedEvent, 27 28 kDiscoverStartEvent, 29 kDiscoverCompleteEvent, 30 kLogDiscoverCompleteErr, 31 32 kLookupStartEvent, 33 kNSClientConnectedEvent, 34 kNSClientLookupReplyEvent, 35 kNSClientLookupDisconnectEvent, 36 kLookupCompleteEvent, 37 38 kConnectStartEvent, 39 kConnectCompleteEvent, 40 41 kListenStartEvent, 42 kListenCompleteEvent, 43 kLogListenCompleteErr, 44 45 kAcceptStartEvent, 46 kAcceptCompleteEvent, 47 48 kGetStartEvent, 49 kGetCompleteEvent, 50 51 kPutStartEvent, 52 kPutCompleteEvent, 53 54 kDisconnectStartEvent, 55 kDisconnectCompleteEvent, 56 57 kGetBackFromGrabEvent, 58 kGetAboutToEnqueueEvent, 59 kGetBackFromEnqueue, 60 kCheckCBOk, 61 kCheckCBBad, 62 kLSAPEventProcess, 63 64 kCancelPuts, 65 kCancelGets, 66 kCancelPutsComplete, 67 kCancelGetsComplete, 68 69 kEnqueueEvent, 70 kDequeueEventStart, 71 kDequeueEventEnd 72 73}; 74 75static 76EventTraceCauseDesc gTraceEvents[] = { 77 {kLogNew, "CIrLSAP: new obj="}, 78 {kLogFree, "CIrLSAP: free obj="}, 79 {kLogInit, "CIrLSAP: init, obj=,lsapid="}, 80 81 {kUnexpectedEvent, "CIrLSAP: unexpected event"}, 82 83 {kDiscoverStartEvent, "CIrLSAP: Discover request"}, 84 {kDiscoverCompleteEvent, "CIrLSAP: Discover reply"}, 85 {kLogDiscoverCompleteErr, "CirLSAP: Discover reply ERROR"}, 86 87 {kLookupStartEvent, "CIrLSAP: Lookup request"}, 88 {kNSClientConnectedEvent, "CIrLSAP: Lookup IAS Client Connected"}, 89 {kNSClientLookupReplyEvent, "CIrLSAP: Lookup IAS Client Reply"}, 90 {kNSClientLookupDisconnectEvent,"CIrLSAP: Lookup IAS Client Disconnected"}, 91 {kLookupCompleteEvent, "CIrLSAP: Lookup complete"}, 92 93 {kConnectStartEvent, "CIrLSAP: Connect request"}, 94 {kConnectCompleteEvent, "CIrLSAP: Connect reply"}, 95 96 {kListenStartEvent, "CIrLSAP: Listen request"}, 97 {kListenCompleteEvent, "CIrLSAP: Listen reply"}, 98 {kLogListenCompleteErr, "CIrLSAP: Listen reply ERROR"}, 99 100 {kAcceptStartEvent, "CIrLSAP: Accept request"}, 101 {kAcceptCompleteEvent, "CIrLSAP: Accept reply"}, 102 103 {kGetStartEvent, "CIrLSAP: Get request"}, 104 {kGetCompleteEvent, "CIrLSAP: Get reply"}, 105 {kPutStartEvent, "CIrLSAP: Put request"}, 106 {kPutCompleteEvent, "CIrLSAP: Put reply"}, 107 108 {kDisconnectStartEvent, "CIrLSAP: Disconnect request"}, 109 {kDisconnectCompleteEvent, "CIrLSAP: Disconnect complete"}, 110 111 {kGetBackFromGrabEvent, "CIrLSAP: Get req back from grab event block"}, 112 {kGetAboutToEnqueueEvent, "CIrLSAP: Get req about to enqueue event"}, 113 {kGetBackFromEnqueue, "CIrLSAP: Get req back from enqueue event"}, 114 {kCheckCBOk, "CIrLSAP: check of CB looks ok"}, 115 {kCheckCBBad, "CIrLSAP: check of CB failed!"}, 116 {kLSAPEventProcess, "CIrLSAP: Next State, event, state" }, 117 118 {kCancelPuts, "CIrLSAP: cancel pending puts"}, 119 {kCancelGets, "CIrLSAP: cancel pending gets"}, 120 {kCancelPutsComplete, "CIrLSAP: cancel puts done"}, 121 {kCancelGetsComplete, "CIrLSAP: cancel gets done"}, 122 123 {kEnqueueEvent, "CIrLSAP: Event Queued"}, // these 3 need to stay in order 124 {kDequeueEventStart, "CIrLSAP: Event Start"}, 125 {kDequeueEventEnd, "CIrLSAP: Event End"} 126 127 128 129}; 130 131#define XTRACE(x, y, z) IrDALogAdd( x, y, (uintptr_t)z & 0xffff, gTraceEvents, true ) 132 133#else 134 #define XTRACE(x, y, z) ((void)0) 135#endif 136 137 138#define super TIrStream 139 OSDefineMetaClassAndAbstractStructors(CIrLSAP, TIrStream); 140 141 142void 143CIrLSAP::free() 144{ 145 TIASService *nameService; // glue's name service (if any) 146 147 XTRACE(kLogFree, 0, this); 148 149 if (fIrDA) { 150 nameService = fIrDA->GetNameService(); // get existing name service 151 if (nameService) { // if it exists, let's un-register outselves from IAS 152 nameService->RemoveAttribute(fClassName, fAttrName, kIASDeleteAttribute); 153 } 154 } 155 156 if (fDscInfo) 157 fDscInfo->RemoveServiceHints(fHints); 158 159 if (fLSAP) { // glue made this for us, but we need to release it 160 fLSAP->release(); 161 fLSAP = nil; 162 } 163 else { // else lsapconn never alloc'd so WE need to release the lsap id 164 if (fIrDA) // sanity check 165 fIrDA->ReleaseLSAPId(fMyLSAPId); // cause lsapconn delete is what normally frees our lsap id 166 } 167 168 if (fNameClient) { // jdg: delete name client when we go away 169 fNameClient->release(); 170 fNameClient = nil; 171 } 172 173 super::free(); 174} 175 176 177Boolean CIrLSAP::Init(TIrGlue *irda, UInt32 desiredLSAPId, UInt8 * className, UInt8 * attributeName, ULong hints) 178{ 179 IrDAErr err; 180 181 XTRACE(kLogInit, 0, this); 182 XTRACE(kLogInit, 0, desiredLSAPId); 183 184 fState = kIrLSAPDisconnected; 185 fPeerAddr = 0; 186 fMyLSAPId = kAssignDynamicLSAPId; 187 fPeerLSAPId = 0; 188 189 fClassName[0] = 0; // ClassName is null string 190 fAttrName[0] = 0; // attr name to null string 191 fConnectClassName[0] = 0; 192 fAttributeName[0] = 0; // peer names 193 fHints = 0; 194 195 fConnected = false; 196 197 fDiscoverCount = 0; 198 fDscInfo = nil; 199 200 fNameClient = nil; 201 fLSAP = nil; 202 fDiscovery = nil; 203 fPendingDisconnect = false; 204 fDisconnectRequest = nil; // jdg: disconnect request event we alloc'd 205 206 207#if (hasTracing > 0 && hasIrLSAPTracing > 0) 208 if (!super::Init(irda, gTraceEvents, kEnqueueEvent)) return false; 209#else 210 if (!super::Init(irda)) return false; 211#endif 212 213 fDiscovery = fIrDA->GetDiscovery(); // get the discovery stream client from glue 214 require(fDiscovery, Fail); // this could be deferred until later, but ... 215 216 fDscInfo = fDiscovery->GetDiscoveryInfo(); // get our own discovery info 217 require(fDscInfo, Fail); 218 219 fHints = hints; // remember our ("new") hint bits for clear later 220 fDscInfo->SetServiceHints(fHints); // add our hits to the system's hint bits 221 222 fMyLSAPId = desiredLSAPId; 223 224 if (className) 225 strlcpy((char *)&fClassName[0], (char *)className, sizeof(fClassName)); 226 if (attributeName) 227 strlcpy((char * )&fAttrName[0], (char *)attributeName, sizeof(fAttrName)); 228 229 230 // FIXME - this should only be done if we set up a listener 231 err = fIrDA->RegisterMyNameAndLSAPId(fClassName, fAttrName, &fMyLSAPId); 232 nrequire(err, Fail); 233 234 XTRACE(kLogInit, 1, fMyLSAPId); 235 236 return true; 237 238Fail: 239 return false; 240 241} // CIrLSAP::InitCIrLSAP 242 243#pragma mark Client Accessors 244//--------------- Client Accessors --------------- 245 246void CIrLSAP::SetPeerLAPAddr( UInt32 addr ) 247{ 248 if( ! fConnected ) // This only makes sense before a connection is 249 fPeerAddr = addr; // established. 250} 251 252 253#pragma mark Client Methods 254//--------------- Client Methods --------------- 255 256//-------------------------------------------------------------------------------------------- 257// 258// Discover: Initiates a LAP XID Discovery 259// 260//-------------------------------------------------------------------------------------------- 261IrDAErr CIrLSAP::Discover( UInt32 slots ) 262{ 263 TIrDiscoverRequest * request; 264 265 XTRACE(kDiscoverStartEvent, 0, this); 266 267 if (GetState() != kIrLSAPDisconnected) { // sanity check 268 XTRACE(kDiscoverStartEvent, 0xffff, GetState()); 269 return kIrDAErrWrongState; // bail if invalid state 270 } 271 272 request = (TIrDiscoverRequest *)fIrDA->GrabEventBlock(kIrDiscoverRequestEvent, sizeof(TIrDiscoverRequest)); 273 require( request, Fail_NewDiscoverRequest ); 274 275 request->fNumSlots = slots; 276 request->fClient = this; 277 278 SetState( kIrLSAPDiscoverStart); 279 fDiscovery->EnqueueEvent( request ); 280 281 return noErr; 282 283Fail_NewDiscoverRequest: 284 return kIrDAErrNoMemory; 285 286} // CIrLSAP::Discover 287 288//-------------------------------------------------------------------------------------------- 289// 290// LSAPLookup: Queries remote device for an LSAP id of requested service 291// 292//-------------------------------------------------------------------------------------------- 293 294IrDAErr CIrLSAP::LSAPLookup(UInt8 * className, UInt8 * attributeName, UInt32 remoteAddr) 295{ 296 297 TIrConnLstnRequest * connectRequest; 298 299 XTRACE( kLookupStartEvent, remoteAddr >> 16, remoteAddr ); 300 301 if (GetState() != kIrLSAPDisconnected) { // sanity check 302 XTRACE(kLookupStartEvent, 0xffff, GetState()); 303 return kIrDAErrWrongState; // bail if invalid state 304 } 305 306 fPeerAddr = remoteAddr; // FIXME Client should supply address with connect request 307 308 // Save connect class name until we have connected to the peer devs name server 309 strlcpy( ( char * )&fConnectClassName, ( const char * )className, sizeof(fConnectClassName)); 310 strlcpy( ( char * )&fAttributeName, ( const char * )attributeName, sizeof(fAttributeName)); 311 312 // Create, init name server client 313 if (fNameClient == nil) { // jdg: if first time we've done a lookup 314 fNameClient = TIASClient::tIASClient(fIrDA, this); // make an IAS name client to use 315 require( fNameClient, Fail_NewNameClient ); 316 } 317 318 connectRequest = (TIrConnLstnRequest*)fIrDA->GrabEventBlock(kIrConnectRequestEvent, sizeof(TIrConnLstnRequest)); 319 require( connectRequest, Fail_NewConnectRequest ); 320 321 // Connect to name server on peer device 322 connectRequest->fDevAddr = remoteAddr; 323 connectRequest->fMyQOS = fIrDA->GetMyQOS(); 324 connectRequest->fPeerQOS = fIrDA->GetPeerQOS(); 325 connectRequest->fData = nil; 326 connectRequest->fClient = this; 327 328 SetState( kIrLSAPLookupStart ); // now doing a lookup 329 fNameClient->EnqueueEvent(connectRequest); 330 return noErr; 331 332 // Out of memory error exit points 333 334Fail_NewConnectRequest: 335Fail_NewNameClient: 336 return kIrDAErrNoMemory; 337} // CIrLSAP::LSAPLookup 338 339 340//-------------------------------------------------------------------------------------------- 341// 342// Connect: Attempts to connect to remote device 343// 344//-------------------------------------------------------------------------------------------- 345 346IrDAErr CIrLSAP::Connect( UInt32 remoteAddr, UInt32 lsapID, CBufferSegment *connectData ) 347{ 348 fPeerAddr = remoteAddr; 349 return this->Connect(lsapID, connectData); 350} 351 352IrDAErr CIrLSAP::Connect( UInt32 lsapID, CBufferSegment *connectData ) 353{ 354 fPeerLSAPId = lsapID; // Punch in the user's lsap id and then connect 355 return this->Connect(connectData); 356} 357 358IrDAErr CIrLSAP::Connect( CBufferSegment *connectData ) 359{ 360 IrDAErr err; 361 XTRACE( kConnectStartEvent, fPeerLSAPId, fPeerAddr ); 362 XTRACE( kConnectStartEvent, 0, this ); 363 364 if (GetState() != kIrLSAPDisconnected) { // sanity check 365 XTRACE(kConnectStartEvent, 0xffff, GetState()); 366 return kIrDAErrWrongState; // bail if invalid state 367 } 368 369 SetState(kIrLSAPConnectStart); 370 // TODO --- allocate the lsapconn in our init and bypass glue here 371 err = fIrDA->ConnectStart( this, fMyLSAPId, fPeerAddr, fPeerLSAPId, 372 connectData, &fLSAP ); 373 374 if (err != noErr) { // if connect start failed 375 SetState(kIrLSAPDisconnected); // not connecting, we're disconnected 376 } 377 return err; 378 379} // CIrLSAP::Connect 380 381 382 383//-------------------------------------------------------------------------------------------- 384// 385// DataPut: Writes one packet of data. 386// 387//-------------------------------------------------------------------------------------------- 388 389IrDAErr CIrLSAP::DataPut( CBufferSegment * putBuffer ) 390{ 391 TIrPutRequest *putRequest; 392 XTRACE( kPutStartEvent, fMyLSAPId, fPeerLSAPId ); 393 XTRACE( kPutStartEvent, 0, this ); 394 XTRACE( kPutStartEvent, 0, putBuffer); 395 396 if (GetState() != kIrLSAPConnected) { 397 XTRACE(kPutStartEvent, 0xffff, GetState()); 398 return kIrDAErrWrongState; // bail if invalid state 399 } 400 check(fConnected == true); // checks should all pass since we're connected 401 check(putBuffer); 402 check(fLSAP); 403 404 fLastPutBuffer = putBuffer; // temp debugging 405 putRequest = ( TIrPutRequest * )fIrDA->GrabEventBlock(kIrPutDataRequestEvent, sizeof(TIrPutRequest)); 406 require( putRequest, AllocatePutRequestBlock ); 407 408 putRequest->fData = putBuffer; 409 putRequest->fOffset = 0; 410 putRequest->fLength = putBuffer->GetSize(); 411 putRequest->fClient = this; 412 fLSAP->EnqueueEvent( putRequest ); 413 return noErr; 414 415AllocatePutRequestBlock: 416 417 return kIrDAErrNoMemory; 418} // CIrLSAP::DataPut 419 420 421 422//-------------------------------------------------------------------------------------------- 423// 424// DataGet: Reads one packet of data. 425// 426//-------------------------------------------------------------------------------------------- 427 428 429IrDAErr CIrLSAP::DataGet( CBufferSegment * getBuffer ) 430{ 431 TIrGetRequest *getRequest; 432 XTRACE( kGetStartEvent, fMyLSAPId, fPeerLSAPId ); 433 XTRACE( kGetStartEvent, 0, this ); 434 435 if (GetState() != kIrLSAPConnected) { 436 XTRACE(kGetStartEvent, 0xffff, GetState()); 437 return kIrDAErrWrongState; // bail if invalid state 438 } 439 check(getBuffer); 440 441 getRequest = ( TIrGetRequest * )fIrDA->GrabEventBlock(kIrGetDataRequestEvent, sizeof(TIrGetRequest)); 442 require( getRequest, AllocatePutRequestBlock ); 443 444 getRequest->fData = getBuffer; 445 getRequest->fOffset = 0; 446 getRequest->fLength = getBuffer->GetSize(); 447 getRequest->fClient = this; 448 449 fLSAP->EnqueueEvent( getRequest ); 450 451 return noErr; 452 453AllocatePutRequestBlock: 454 455 return kIrDAErrNoMemory; 456} // CIrLSAP::DataGet 457 458 459 460//-------------------------------------------------------------------------------------------- 461// 462// Listen: Waits for a connection attempt from a remote device 463// 464//-------------------------------------------------------------------------------------------- 465 466IrDAErr CIrLSAP::Listen(CBufferSegment *connectData) 467{ 468 IrDAErr err; 469 470 XTRACE( kListenStartEvent, 0, fMyLSAPId); 471 XTRACE( kListenStartEvent, 0, this); 472 XTRACE( kListenStartEvent, 0, connectData); 473 474 if (GetState() != kIrLSAPDisconnected) { // sanity check 475 XTRACE(kListenStartEvent, 0xffff, GetState()); 476 return kIrDAErrWrongState; // bail if invalid state 477 } 478 479 fLastListenBuffer = connectData; // temp debugging 480 SetState( kIrLSAPListenStart ); 481 // TODO - get rid of glue 482 err = fIrDA->ListenStart( this, fMyLSAPId, connectData, &fLSAP ); 483 if (err != noErr) { // if listen start failed 484 SetState(kIrLSAPDisconnected); // not listening, we're disconnected 485 } 486 return err; 487 488} // CIrLSAP::Listen 489 490 491 492//-------------------------------------------------------------------------------------------- 493// 494// Accept: Accepts the remote devices connection attempt (or not) 495// 496//-------------------------------------------------------------------------------------------- 497 498IrDAErr CIrLSAP::Accept(CBufferSegment *connectData) 499{ 500 TIrConnLstnRequest *acceptRequest; 501 502 XTRACE( kAcceptStartEvent, fMyLSAPId, fPeerLSAPId); 503 XTRACE( kAcceptStartEvent, fPeerAddr>>16, fPeerAddr ); 504 XTRACE( kAcceptStartEvent, (uintptr_t)this>>16, this); 505 506 if (GetState() != kIrLSAPListenComplete) { // sanity check 507 XTRACE(kAcceptStartEvent, 0xffff, GetState()); 508 return kIrDAErrWrongState; // bail if invalid state 509 } 510 511 acceptRequest = ( TIrConnLstnRequest*) fIrDA->GrabEventBlock( kIrAcceptRequestEvent, 512 sizeof( TIrConnLstnRequest ) ); 513 require( acceptRequest, Fail_NewAcceptRequest ); 514 515 SetState( kIrLSAPAcceptStart ); 516 acceptRequest->fData = connectData; 517 fLSAP->EnqueueEvent( acceptRequest ); 518 519 return noErr; 520 521Fail_NewAcceptRequest: 522 //Disconnect(); // jdg: if out of events, disconnect request will fail too 523 return kIrDAErrNoMemory; 524 525} // CIrLSAP::Accept 526 527 528 529//-------------------------------------------------------------------------------------------- 530// 531// DoDisconnect: Disconnects the LSAP from remote 532// 533//-------------------------------------------------------------------------------------------- 534 535void CIrLSAP::Disconnect() 536{ 537 //TIrDisconnectRequest *disconnectRequest; 538 539 XTRACE( kDisconnectStartEvent, fMyLSAPId, fPeerLSAPId ); 540 XTRACE( kDisconnectStartEvent, 0, this ); 541 542 if (GetState() == kIrLSAPDisconnected) { // if we're already disconnected 543 check(fConnected == false); // sanity check 544 XTRACE(kDisconnectStartEvent, 0xffff, GetState()); 545 DisconnectComplete(); // !! virtual callback to client (hmm) 546 return; // !! could do away w/above cb if we returned an err 547 } 548 549 // JDG: if we're in the middle of a discover or lookup, wait until they finish 550 // before doing a disconnect 551 if (GetState() == kIrLSAPDiscoverStart || GetState() == kIrLSAPLookupStart) { 552 fPendingDisconnect = true; 553 return; 554 } 555 556 // and if we've already issued a disconnect request on this, another 557 // one is just a nop 558 if (GetState() == kIrLSAPDisconnectStart) 559 return; // should return an error here 560 561 check(fDisconnectRequest == nil); // shouldn't have a disconnect pending yet 562 fDisconnectRequest = (TIrDisconnectRequest*) fIrDA->GrabEventBlock(kIrDisconnectRequestEvent, 563 sizeof(TIrDisconnectRequest)); 564 if (fDisconnectRequest == nil) // out of memory 565 return; // should return an error code 566 567 SetState( kIrLSAPDisconnectStart ); 568 fLSAP->EnqueueEvent(fDisconnectRequest); 569 return; 570 571} // CIrLSAP::Disconnect 572 573//-------------------------------------------------------------------------------------------- 574// 575// CancelPuts: Aborts all pending puts. 576// 577//-------------------------------------------------------------------------------------------- 578 579IrDAErr CIrLSAP::CancelPuts( void ) 580{ 581 TIrCancelPutEvent *cancelRequest; 582 XTRACE( kCancelPuts, 0, this); 583 584 if (GetState() != kIrLSAPConnected) { // if we're not connected 585 XTRACE(kCancelPuts, 0xffff, GetState()); 586 return kIrDAErrWrongState; // bail if invalid state 587 } 588 589 cancelRequest = (TIrCancelPutEvent *)fIrDA->GrabEventBlock(kIrCancelPutRequestEvent, 590 sizeof(TIrCancelPutEvent)); 591 require(cancelRequest, AllocatePutRequestBlock); 592 593 cancelRequest->fClient = this; 594 fLSAP->EnqueueEvent(cancelRequest); 595 596 return noErr; 597 598AllocatePutRequestBlock: 599 600 return kIrDAErrNoMemory; 601 602} // CIrLSAP::CancelPuts 603 604//-------------------------------------------------------------------------------------------- 605// 606// CancelGets: Aborts all pending gets. 607// 608//-------------------------------------------------------------------------------------------- 609 610IrDAErr CIrLSAP::CancelGets( void ) 611{ 612 TIrCancelGetEvent *cancelRequest; 613 614 XTRACE( kCancelGets, 0, this); 615 616 if (GetState() != kIrLSAPConnected) { // if we're not connected 617 XTRACE(kCancelGets, 0xffff, GetState()); 618 return kIrDAErrWrongState; // bail if invalid state 619 } 620 621 cancelRequest = (TIrCancelGetEvent *)fIrDA->GrabEventBlock(kIrCancelGetRequestEvent, 622 sizeof(TIrCancelGetEvent)); 623 require(cancelRequest, AllocateRequestBlock); 624 625 cancelRequest->fClient = this; 626 fLSAP->EnqueueEvent(cancelRequest); 627 628 return noErr; 629 630AllocateRequestBlock: 631 632 return kIrDAErrNoMemory; 633 634} // CIrLSAP::CancelGets 635 636 637#pragma mark 638//--------------- Internal Event Handlers --------------- 639 640//-------------------------------------------------------------------------------------------- 641// 642// NextState 643// 644//-------------------------------------------------------------------------------------------- 645void CIrLSAP::NextState( UInt32 event ) 646{ 647 XTRACE( kLSAPEventProcess, ( UInt16 )event, GetState() ); 648 XTRACE( kLSAPEventProcess, 0, this); 649 650 // The only overlap of state/events is ConnectReply, when the connect 651 // could be either at our client's request or as part of a client 652 // ias lookup sequence 653 654 if (event == kIrConnectReplyEvent && GetState() == kIrLSAPLookupStart) { 655 HandleNameServerConnectComplete(); 656 return; 657 } 658 659 switch (event) { 660 661 case kIrDisconnectReplyEvent: 662 HandleDisconnectComplete(); 663 break; 664 665 case kIrDiscoverReplyEvent: 666 HandleDiscoverComplete(); 667 break; 668 669 case kIrLookupReplyEvent: 670 HandleNameServerLookupComplete(); 671 break; 672 673 case kIrReleaseReplyEvent: 674 HandleNameServerReleaseComplete(); 675 break; 676 677 case kIrConnectReplyEvent: 678 HandleConnectComplete(); 679 break; 680 681 case kIrListenReplyEvent: 682 HandleListenComplete(); 683 break; 684 685 case kIrAcceptReplyEvent: 686 HandleAcceptComplete(); 687 break; 688 689 case kIrGetDataReplyEvent: 690 HandleDataGetComplete(); 691 break; 692 693 case kIrPutDataReplyEvent: 694 HandleDataPutComplete(); 695 break; 696 697 case kIrCancelGetReplyEvent: 698 HandleCancelGetComplete(); 699 break; 700 701 case kIrCancelPutReplyEvent: 702 HandleCancelPutComplete(); 703 break; 704 705 default: 706 DebugLog("CIrLSAP::NextState: unexpected event"); 707 break; 708 } // switch on event 709 710} // CIrLSAP::NextState 711 712 713 714//-------------------------------------------------------------------------------- 715// 716// DiscoverComplete 717// 718//-------------------------------------------------------------------------------- 719void CIrLSAP::HandleDiscoverComplete() 720{ 721 TIrDiscoverReply * reply = ( TIrDiscoverReply * )GetCurrentEvent(); 722 723 UInt32 numFound; // number of peers discovered 724 TIrDscInfo * dscInfo; 725 CList * fDiscoverList; 726 727 if (reply->fResult == noErr) { // if it worked 728 check (GetState() == kIrLSAPDiscoverStart); 729 if (GetState() != kIrLSAPDiscoverStart) { 730 XTRACE(kLogDiscoverCompleteErr, reply->fResult, GetState()); 731 } 732 } else { // else it could have async disconnected (?) 733 check (GetState() == kIrLSAPDiscoverStart || 734 GetState() == kIrLSAPDisconnected); 735 if (GetState() != kIrLSAPDiscoverStart && GetState() != kIrLSAPDisconnected) 736 XTRACE(kLogDiscoverCompleteErr, reply->fResult, GetState()); 737 } 738 739 fDiscoverList = reply->fDiscoveredDevices; 740 741 numFound = fDiscoverList->GetArraySize(); 742 XTRACE( kDiscoverCompleteEvent, numFound, reply->fResult ); 743 if( numFound > 0 ) { 744 SInt32 index; 745 for( index = 0; index < fDiscoverList->GetArraySize(); index++ ) { 746 747 dscInfo = ( TIrDscInfo * )fDiscoverList->At( index ); 748 fDiscoverInfo[index].serviceHints = dscInfo->GetServiceHints(); 749 fDiscoverInfo[index].addr = dscInfo->GetDeviceAddr(); 750 dscInfo->GetNickname( fDiscoverInfo[index].name, sizeof(fDiscoverInfo[index].name) ); 751 } 752 } 753 SetState( kIrLSAPDisconnected ); // discover done, disconnected again 754 DiscoverComplete( numFound, reply->fResult ); // virtual dispatch 755 fIrDA->ReleaseEventBlock( reply ); 756 757 // If client asked for a disconnect while we were discovering, fake 758 // a disconnect complete now 759 if (fPendingDisconnect) { 760 XTRACE( kDiscoverCompleteEvent, 0xffff, 0xffff); 761 fPendingDisconnect = false; 762 DisconnectComplete(); // virtual callback to client 763 } 764 765} // HandleDiscoverComplete 766 767 768//-------------------------------------------------------------------------------- 769// 770// DisconnectComplete 771// 772//-------------------------------------------------------------------------------- 773void CIrLSAP::HandleDisconnectComplete() 774{ 775 TIrDisconnectReply * reply = ( TIrDisconnectReply * )GetCurrentEvent(); 776 777 //UInt32 enterState = GetState(); // Remember what the state was 778 779 XTRACE( kDisconnectCompleteEvent, reply->fResult, GetState() ); 780 fConnected = false; 781 SetState( kIrLSAPDisconnected ); 782 DisconnectComplete(); // virtual. cb to client 783 784 // If someone else generated the disconnect then I don't want to release 785 // the event block. LMP will do it for me. Most likely, the beam was broken 786 // so LMP is notifing all the LSAPs of the disconnect. It will release the 787 // event when it is done. 788 //if( enterState == kIrLSAPDisconnectStart ) 789 // fIrDA->ReleaseEventBlock( reply ); 790 791 // JDG: if reply matches that of our disconnect request, free it. 792 // note: disconnect start state isn't particularly reliable ... 793 if (fDisconnectRequest == reply) { 794 fIrDA->ReleaseEventBlock( reply ); 795 fDisconnectRequest = nil; 796 } 797 798} // CIrLSAP::HandleDisconnectComplete 799 800 801#pragma mark ----- LSAP Lookup Engine --- 802//-------------------------------------------------------------------------------- 803// 804// LSAPLookupComplete 805// 806//-------------------------------------------------------------------------------- 807void CIrLSAP::HandleLSAPLookupComplete() 808{ 809 TIrLookupEvent *reply = (TIrLookupEvent*)GetCurrentEvent(); 810 IrDAErr result = reply->fResult; 811 XTRACE(kLookupCompleteEvent, result, fPeerLSAPId ); 812 813 if (result == noErr) { // if it worked 814 check(GetState() == kIrLSAPLookupStart); 815 } else { // if it failed, we could have async disconnected 816 check(GetState() == kIrLSAPLookupStart 817 || GetState() == kIrLSAPDisconnected); 818 } 819 820 if (result == noErr) { 821 fPeerLSAPId = reply->fPeerLSAPId; // assume we want to talk to 'em! 822 } 823 else { 824 fPeerLSAPId = 0; 825 } 826 SetState(kIrLSAPDisconnected); // we're not connecting yet ... 827 828 LSAPLookupComplete(result, fPeerLSAPId); // virtual call back 829 fIrDA->ReleaseEventBlock( reply ); 830 831 // If client asked for a disconnect while we were discovering, fake 832 // a disconnect complete now 833 if (fPendingDisconnect) { 834 XTRACE(kLookupCompleteEvent, 0xffff, 0xffff); 835 fPendingDisconnect = false; 836 DisconnectComplete(); // virtual callback to client 837 } 838} // CIrLSAP::HandleLSAPLookupComplete 839 840 841//-------------------------------------------------------------------------------- 842// HandleNameServerConnectComplete 843//-------------------------------------------------------------------------------- 844void CIrLSAP::HandleNameServerConnectComplete() 845{ 846 TIrConnLstnReply * connectReply = ( TIrConnLstnReply * )GetCurrentEvent(); 847 TIrLookupRequest * lookupRequest = ( TIrLookupRequest * )GetCurrentEvent(); 848 849 XTRACE( kNSClientConnectedEvent, 0, connectReply->fResult ); 850 check(GetState() == kIrLSAPLookupStart); 851 852 // Complete request early if an error is returned 853 if (connectReply->fResult != noErr) { 854 this->HandleLSAPLookupComplete(); // virtual dispatch to client 855 } 856 else { 857 // Issue a lookup to name server on peer device 858 // Note: re-using the connect request block 859 lookupRequest->fEvent = kIrLookupRequestEvent; 860 lookupRequest->fClassName = fConnectClassName; // Client supplied 861 lookupRequest->fAttrName = fAttributeName; // Client supplied 862 fNameClient->EnqueueEvent(lookupRequest); 863 } 864 865} // TIrGlue::HandleNameServerConnectComplete 866 867 868//-------------------------------------------------------------------------------- 869// HandleNameServerLookupComplete 870//-------------------------------------------------------------------------------- 871void CIrLSAP::HandleNameServerLookupComplete() 872{ 873 TIrLookupReply * lookupReply = ( TIrLookupReply * )GetCurrentEvent(); 874 check(GetState() == kIrLSAPLookupStart); 875 876 fPeerLSAPId = 0; 877 878 if (lookupReply->fResult == noErr) { 879 // Did we successfully get the LSAPId of the remote connection end? 880 if( lookupReply->fAttribute ) { 881 TIASElement * element = ( TIASElement * )lookupReply->fAttribute->First(); 882 if( element ) { 883 if( element->GetInteger( &fPeerLSAPId ) != noErr ) { 884 fPeerLSAPId = 0; 885 } 886 } 887 //delete lookupReply->fAttribute; 888 lookupReply->fAttribute->release(); 889 } 890 } 891 892 XTRACE( kNSClientLookupReplyEvent, fPeerLSAPId, lookupReply->fResult ); 893 894 TIrDisconnectRequest * releaseRequest; 895 // Release the name server connection (re-use the reply event block) 896 releaseRequest = (TIrDisconnectRequest*)lookupReply; 897 releaseRequest->fEvent = kIrReleaseRequestEvent; 898 releaseRequest->fResult = noErr; 899 fNameClient->EnqueueEvent(releaseRequest); 900} // CIrLSAP::HandleNameServerLookupComplete 901 902 903//-------------------------------------------------------------------------------- 904// HandleNameServerReleaseComplete 905//-------------------------------------------------------------------------------- 906void CIrLSAP::HandleNameServerReleaseComplete() 907{ 908 TIrLookupReply * lookupReply = ( TIrLookupReply * )GetCurrentEvent(); 909 910 XTRACE( kNSClientLookupDisconnectEvent, 0, fPeerLSAPId ); 911 check(GetState() == kIrLSAPLookupStart); 912 913 lookupReply->fEvent = kIrLookupReplyEvent; // Reply back to the client 914 lookupReply->fPeerLSAPId = fPeerLSAPId; 915 this->HandleLSAPLookupComplete(); 916 917} // CIrLSAP::HandleNameServerReleaseComplete 918 919 920 921#pragma mark ----- Data Handlers --- 922 923//-------------------------------------------------------------------------------- 924// 925// ConnectComplete 926// 927//-------------------------------------------------------------------------------- 928void CIrLSAP::HandleConnectComplete() 929{ 930 TIrConnLstnReply *reply = (TIrConnLstnReply *)GetCurrentEvent(); 931 IrDAErr result = reply->fResult; 932 933 XTRACE( kConnectCompleteEvent, result, 0 ); 934 935 check( fLSAP == reply->fLSAPConn ); 936 937 //if (result == noErr) { // if it worked 938 // check(GetState() == kIrLSAPConnectStart); // this was failing ... sigh 939 //} else { // if aborted, could be in a disconnect state too 940 check(GetState() == kIrLSAPConnectStart || 941 GetState() == kIrLSAPDisconnectStart || 942 GetState() == kIrLSAPDisconnected); 943 //} 944 945 if( result == noErr ) { 946 SetState( kIrLSAPConnected ); 947 fConnected = true; 948 } 949 else{ 950 SetState( kIrLSAPDisconnected ); 951 fConnected = false; 952 } 953 954 // "Bug" workaround. Fixme? We'd like the QOS values, but they're 955 // not getting set by the lower layers. Grab 'em from glue and 956 // stuff 'em in. 957 reply->fPeerQOS = fIrDA->GetPeerQOS(); 958 reply->fMyQOS = fIrDA->GetMyQOS(); 959 960 ConnectComplete(result, reply->fMyQOS, reply->fPeerQOS, (CBufferSegment *)reply->fData); 961 fIrDA->ReleaseEventBlock( reply ); 962 963} // CIrLSAP::HandleConnectComplete 964 965 966 967//-------------------------------------------------------------------------------- 968// 969// DataPutComplete 970// 971//-------------------------------------------------------------------------------- 972void CIrLSAP::HandleDataPutComplete() 973{ 974 TIrPutReply * reply = ( TIrPutReply * )GetCurrentEvent(); 975 IrDAErr result = reply->fResult; 976 977 XTRACE( kPutCompleteEvent, result, 0 ); 978 979 //if (fLastListenBuffer == reply->fData) // this is how it was failing 980 // DebugPrintf("put buf done, %x %x %x", fLastListenBuffer, fLastPutBuffer, reply->fData); 981 982 DataPutComplete(result, (CBufferSegment *)reply->fData); // virtual callback 983 fIrDA->ReleaseEventBlock( reply ); 984 985} // CIrLSAP::HandleDataPutComplete 986 987 988//-------------------------------------------------------------------------------- 989// 990// ListenComplete 991// 992//-------------------------------------------------------------------------------- 993void CIrLSAP::HandleListenComplete() 994{ 995 TIrConnLstnReply *reply = (TIrConnLstnReply*)GetCurrentEvent(); 996 IrDAErr result = reply->fResult; 997 998 if (result == noErr) { // if it worked, should be in listen start state 999 check(GetState() == kIrLSAPListenStart); 1000 } else { // else probably aborted by disconnect 1001 // FIXME -- ReUdo is hitting this check ... let's debugstr to see what's up 1002 // todo: we're getting here as a reject from discover start ... why? 1003 /*****/ 1004#if defined(forDebug) 1005 int state = GetState(); 1006 if (state != kIrLSAPListenStart && 1007 state != kIrLSAPDisconnectStart && state != kIrLSAPDisconnected) 1008 DebugPrintf("CIrLSAP: listen complete %d, state %d", result, state); 1009 //****/ 1010#endif // forDebug 1011 //check(GetState() == kIrLSAPListenStart || 1012 // GetState() == kIrLSAPDisconnectStart || 1013 // GetState() == kIrLSAPDisconnected); 1014 } 1015 1016 if (result == noErr) { // if it worked, pull out peer info 1017 fPeerLSAPId = reply->fLSAPId; 1018 fPeerAddr = reply->fDevAddr; 1019 } 1020 1021 XTRACE( kListenCompleteEvent, fPeerLSAPId, fPeerAddr ); 1022 XTRACE( kListenCompleteEvent, 0, this); 1023 1024 // "Bug" workaround. Fixme? We'd like the QOS values, but they're 1025 // not getting set by the lower layers. Grab 'em from glue and 1026 // stuff 'em in. 1027 // UPDATE: this has almost been fixed but not verified. Check out lsapconn's 1028 // clobbering of the listen request event record when reused as a GetRequest 1029 reply->fPeerQOS = fIrDA->GetPeerQOS(); 1030 reply->fMyQOS = fIrDA->GetMyQOS(); 1031 1032 if (result == noErr) 1033 SetState( kIrLSAPListenComplete ); 1034 else 1035 SetState(kIrLSAPDisconnected); 1036 1037 check(fLastListenBuffer == reply->fData); 1038 if (fLastListenBuffer != reply->fData) { 1039 XTRACE(kLogListenCompleteErr, 0, fLastListenBuffer); 1040 XTRACE(kLogListenCompleteErr, 0, reply->fData); 1041 } 1042 1043 ListenComplete( result, fPeerAddr, fPeerLSAPId, reply->fMyQOS, reply->fPeerQOS, (CBufferSegment *)reply->fData); 1044 fIrDA->ReleaseEventBlock( reply ); 1045 1046} // CIrLSAP::HandleListenComplete 1047 1048 1049//-------------------------------------------------------------------------------- 1050// 1051// AcceptComplete 1052// 1053//-------------------------------------------------------------------------------- 1054void CIrLSAP::HandleAcceptComplete() 1055{ 1056 TIrConnLstnReply * reply = (TIrConnLstnReply*)GetCurrentEvent(); 1057 IrDAErr result = reply->fResult; 1058 1059 XTRACE( kAcceptCompleteEvent, result, 0 ); 1060 check(GetState() == kIrLSAPAcceptStart); 1061 1062 if( result == noErr ) { 1063 SetState( kIrLSAPConnected ); 1064 fConnected = true; 1065 } 1066 else { 1067 SetState( kIrLSAPDisconnected ); 1068 fConnected = false; 1069 } 1070 1071 AcceptComplete(result, (CBufferSegment *)reply->fData); 1072 fIrDA->ReleaseEventBlock( reply ); 1073 1074} // CIrLSAP::HandleAcceptComplete 1075 1076 1077//-------------------------------------------------------------------------------- 1078// 1079// DataGetComplete 1080// 1081//-------------------------------------------------------------------------------- 1082void CIrLSAP::HandleDataGetComplete() 1083{ 1084 TIrGetReply * reply = ( TIrGetReply * )GetCurrentEvent(); 1085 IrDAErr result = reply->fResult; 1086 1087 XTRACE( kGetCompleteEvent, result, 0 ); 1088 1089 DataGetComplete(result, (CBufferSegment *)reply->fData); 1090 fIrDA->ReleaseEventBlock( reply ); 1091 1092} // CIrLSAP::HandleDataGetComplete 1093 1094//-------------------------------------------------------------------------------- 1095// 1096// CancelPutComplete 1097// 1098//-------------------------------------------------------------------------------- 1099void CIrLSAP::HandleCancelPutComplete() 1100{ 1101 TIrCancelPutReply * reply = ( TIrCancelPutReply * )GetCurrentEvent(); 1102 IrDAErr result = reply->fResult; 1103 1104 XTRACE( kCancelPutsComplete, 0, 0 ); 1105 1106 CancelPutsComplete(result); // virtual callback 1107 fIrDA->ReleaseEventBlock( reply ); 1108} // CIrLSAP::HandleCancelPutComplete 1109 1110//-------------------------------------------------------------------------------- 1111// 1112// CancelGetComplete 1113// 1114//-------------------------------------------------------------------------------- 1115void CIrLSAP::HandleCancelGetComplete() 1116{ 1117 TIrCancelGetReply * reply = ( TIrCancelGetReply * )GetCurrentEvent(); 1118 IrDAErr result = reply->fResult; 1119 1120 XTRACE( kCancelGetsComplete, 0, 0 ); 1121 1122 CancelGetsComplete(result); // virtual callback 1123 fIrDA->ReleaseEventBlock( reply ); 1124 1125} // CIrLSAP::HandleCancelGetComplete 1126 1127