1 /* 2 * Copyright 2001-2014 Haiku, Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Axel Dörfler, axeld@pinc-software.de 7 * Erik Jaesler, erik@cgsoftware.com 8 */ 9 10 11 #include <TokenSpace.h> 12 13 #include <AppDefs.h> 14 #include <Handler.h> 15 #include <Looper.h> 16 #include <Message.h> 17 #include <MessageFilter.h> 18 #include <Messenger.h> 19 #include <PropertyInfo.h> 20 21 #include <algorithm> 22 #include <new> 23 #include <stdlib.h> 24 #include <stdio.h> 25 #include <string.h> 26 #include <vector> 27 28 using std::map; 29 using std::vector; 30 using BPrivate::gDefaultTokens; 31 32 33 static const char* kArchiveNameField = "_name"; 34 35 static const uint32 kMsgStartObserving = '_OBS'; 36 static const uint32 kMsgStopObserving = '_OBP'; 37 static const char* kObserveTarget = "be:observe_target"; 38 39 40 static property_info sHandlerPropInfo[] = { 41 { 42 "Suites", // name 43 { B_GET_PROPERTY }, // commands 44 { B_DIRECT_SPECIFIER }, // specifiers 45 NULL, // usage 46 0, // extra data 47 { 0 }, // types 48 { // ctypes (compound_type) 49 { // ctypes[0] 50 { // pairs[0] 51 { 52 "suites", // name 53 B_STRING_TYPE // type 54 } 55 } 56 }, 57 { // ctypes[1] 58 { // pairs[0] 59 { 60 "messages", 61 B_PROPERTY_INFO_TYPE 62 } 63 } 64 } 65 }, 66 {} // reserved 67 }, 68 { 69 "Messenger", 70 { B_GET_PROPERTY }, 71 { B_DIRECT_SPECIFIER }, 72 NULL, 0, 73 { B_MESSENGER_TYPE }, 74 {}, 75 {} 76 }, 77 { 78 "InternalName", 79 { B_GET_PROPERTY }, 80 { B_DIRECT_SPECIFIER }, 81 NULL, 0, 82 { B_STRING_TYPE }, 83 {}, 84 {} 85 }, 86 {} 87 }; 88 89 bool FilterDeleter(void* filter); 90 91 namespace BPrivate { 92 93 class ObserverList { 94 public: 95 ObserverList(); 96 ~ObserverList(); 97 98 status_t SendNotices(uint32 what, const BMessage* notice); 99 status_t Add(const BHandler* handler, uint32 what); 100 status_t Add(const BMessenger& messenger, uint32 what); 101 status_t Remove(const BHandler* handler, uint32 what); 102 status_t Remove(const BMessenger& messenger, uint32 what); 103 bool IsEmpty(); 104 105 private: 106 typedef map<uint32, vector<const BHandler*> > HandlerObserverMap; 107 typedef map<uint32, vector<BMessenger> > MessengerObserverMap; 108 109 void _ValidateHandlers(uint32 what); 110 void _SendNotices(uint32 what, BMessage* notice); 111 112 HandlerObserverMap fHandlerMap; 113 MessengerObserverMap fMessengerMap; 114 }; 115 116 } // namespace BPrivate 117 118 using namespace BPrivate; 119 120 121 // #pragma mark - 122 123 124 BHandler::BHandler(const char* name) 125 : BArchivable(), 126 fName(NULL) 127 { 128 _InitData(name); 129 } 130 131 132 BHandler::~BHandler() 133 { 134 if (LockLooper()) { 135 BLooper* looper = Looper(); 136 looper->RemoveHandler(this); 137 looper->Unlock(); 138 } 139 140 // remove all filters 141 if (fFilters) { 142 int32 count = fFilters->CountItems(); 143 for (int32 i = 0; i < count; i++) 144 delete (BMessageFilter*)fFilters->ItemAtFast(i); 145 delete fFilters; 146 } 147 148 // remove all observers (the observer list manages itself) 149 delete fObserverList; 150 151 // free rest 152 free(fName); 153 gDefaultTokens.RemoveToken(fToken); 154 } 155 156 157 BHandler::BHandler(BMessage* data) 158 : BArchivable(data), 159 fName(NULL) 160 { 161 const char* name = NULL; 162 163 if (data) 164 data->FindString(kArchiveNameField, &name); 165 166 _InitData(name); 167 } 168 169 170 BArchivable* 171 BHandler::Instantiate(BMessage* data) 172 { 173 if (!validate_instantiation(data, "BHandler")) 174 return NULL; 175 176 return new BHandler(data); 177 } 178 179 180 status_t 181 BHandler::Archive(BMessage* data, bool deep) const 182 { 183 status_t status = BArchivable::Archive(data, deep); 184 if (status < B_OK) 185 return status; 186 187 if (fName == NULL) 188 return B_OK; 189 190 return data->AddString(kArchiveNameField, fName); 191 } 192 193 194 void 195 BHandler::MessageReceived(BMessage* message) 196 { 197 BMessage reply(B_REPLY); 198 199 switch (message->what) { 200 case kMsgStartObserving: 201 case kMsgStopObserving: 202 { 203 BMessenger target; 204 uint32 what; 205 if (message->FindMessenger(kObserveTarget, &target) != B_OK 206 || message->FindInt32(B_OBSERVE_WHAT_CHANGE, (int32*)&what) 207 != B_OK) { 208 break; 209 } 210 211 ObserverList* list = _ObserverList(); 212 if (list != NULL) { 213 if (message->what == kMsgStartObserving) 214 list->Add(target, what); 215 else 216 list->Remove(target, what); 217 } 218 break; 219 } 220 221 case B_GET_PROPERTY: 222 { 223 int32 cur; 224 BMessage specifier; 225 int32 form; 226 const char* prop; 227 228 status_t err = message->GetCurrentSpecifier(&cur, &specifier, 229 &form, &prop); 230 if (err != B_OK && err != B_BAD_SCRIPT_SYNTAX) 231 break; 232 bool known = false; 233 // B_BAD_SCRIPT_SYNTAX defaults to the Messenger property 234 if (err == B_BAD_SCRIPT_SYNTAX || cur < 0 235 || (strcmp(prop, "Messenger") == 0)) { 236 err = reply.AddMessenger("result", this); 237 known = true; 238 } else if (strcmp(prop, "Suites") == 0) { 239 err = GetSupportedSuites(&reply); 240 known = true; 241 } else if (strcmp(prop, "InternalName") == 0) { 242 err = reply.AddString("result", Name()); 243 known = true; 244 } 245 246 if (known) { 247 reply.AddInt32("error", B_OK); 248 message->SendReply(&reply); 249 return; 250 } 251 // let's try next handler 252 break; 253 } 254 255 case B_GET_SUPPORTED_SUITES: 256 { 257 reply.AddInt32("error", GetSupportedSuites(&reply)); 258 message->SendReply(&reply); 259 return; 260 } 261 } 262 263 // ToDo: there is some more work needed here 264 // (someone in the know should fill in)! 265 266 if (fNextHandler) { 267 // we need to apply the next handler's filters here, too 268 BHandler* target = Looper()->_HandlerFilter(message, fNextHandler); 269 if (target != NULL && target != this) { 270 // TODO: we also need to make sure that "target" is not before 271 // us in the handler chain - at least in case it wasn't before 272 // the handler actually targeted with this message - this could 273 // get ugly, though. 274 target->MessageReceived(message); 275 } 276 } else if (message->what != B_MESSAGE_NOT_UNDERSTOOD 277 && (message->WasDropped() || message->HasSpecifiers())) { 278 printf("BHandler %s: MessageReceived() couldn't understand the message:\n", Name()); 279 message->PrintToStream(); 280 message->SendReply(B_MESSAGE_NOT_UNDERSTOOD); 281 } 282 } 283 284 285 BLooper* 286 BHandler::Looper() const 287 { 288 return fLooper; 289 } 290 291 292 void 293 BHandler::SetName(const char* name) 294 { 295 if (fName != NULL) { 296 free(fName); 297 fName = NULL; 298 } 299 300 if (name != NULL) 301 fName = strdup(name); 302 } 303 304 305 const char* 306 BHandler::Name() const 307 { 308 return fName; 309 } 310 311 312 void 313 BHandler::SetNextHandler(BHandler* handler) 314 { 315 if (fLooper == NULL) { 316 debugger("handler must belong to looper before setting NextHandler"); 317 return; 318 } 319 320 if (!fLooper->IsLocked()) { 321 debugger("The handler's looper must be locked before setting NextHandler"); 322 return; 323 } 324 325 if (handler != NULL && fLooper != handler->Looper()) { 326 debugger("The handler and its NextHandler must have the same looper"); 327 return; 328 } 329 330 fNextHandler = handler; 331 } 332 333 334 BHandler* 335 BHandler::NextHandler() const 336 { 337 return fNextHandler; 338 } 339 340 341 void 342 BHandler::AddFilter(BMessageFilter* filter) 343 { 344 BLooper* looper = fLooper; 345 if (looper != NULL && !looper->IsLocked()) { 346 debugger("Owning Looper must be locked before calling SetFilterList"); 347 return; 348 } 349 350 if (looper != NULL) 351 filter->SetLooper(looper); 352 353 if (fFilters == NULL) 354 fFilters = new BList; 355 356 fFilters->AddItem(filter); 357 } 358 359 360 bool 361 BHandler::RemoveFilter(BMessageFilter* filter) 362 { 363 BLooper* looper = fLooper; 364 if (looper != NULL && !looper->IsLocked()) { 365 debugger("Owning Looper must be locked before calling SetFilterList"); 366 return false; 367 } 368 369 if (fFilters != NULL && fFilters->RemoveItem((void*)filter)) { 370 filter->SetLooper(NULL); 371 return true; 372 } 373 374 return false; 375 } 376 377 378 void 379 BHandler::SetFilterList(BList* filters) 380 { 381 BLooper* looper = fLooper; 382 if (looper != NULL && !looper->IsLocked()) { 383 debugger("Owning Looper must be locked before calling SetFilterList"); 384 return; 385 } 386 387 /** 388 @note I would like to use BObjectList internally, but this function is 389 spec'd such that fFilters would get deleted and then assigned 390 'filters', which would obviously mess this up. Wondering if 391 anyone ever assigns a list of filters and then checks against 392 FilterList() to see if they are the same. 393 */ 394 395 // TODO: Explore issues with using BObjectList 396 if (fFilters != NULL) { 397 fFilters->DoForEach(FilterDeleter); 398 delete fFilters; 399 } 400 401 fFilters = filters; 402 if (fFilters) { 403 for (int32 i = 0; i < fFilters->CountItems(); ++i) { 404 BMessageFilter* filter = 405 static_cast<BMessageFilter*>(fFilters->ItemAt(i)); 406 if (filter != NULL) 407 filter->SetLooper(looper); 408 } 409 } 410 } 411 412 413 BList* 414 BHandler::FilterList() 415 { 416 return fFilters; 417 } 418 419 420 bool 421 BHandler::LockLooper() 422 { 423 BLooper* looper = fLooper; 424 // Locking the looper also makes sure that the looper is valid 425 if (looper != NULL && looper->Lock()) { 426 // Have we locked the right looper? That's as far as the 427 // "pseudo-atomic" operation mentioned in the BeBook. 428 if (fLooper == looper) 429 return true; 430 431 // we locked the wrong looper, bail out 432 looper->Unlock(); 433 } 434 435 return false; 436 } 437 438 439 status_t 440 BHandler::LockLooperWithTimeout(bigtime_t timeout) 441 { 442 BLooper* looper = fLooper; 443 if (looper == NULL) 444 return B_BAD_VALUE; 445 446 status_t status = looper->LockWithTimeout(timeout); 447 if (status != B_OK) 448 return status; 449 450 if (fLooper != looper) { 451 // we locked the wrong looper, bail out 452 looper->Unlock(); 453 return B_MISMATCHED_VALUES; 454 } 455 456 return B_OK; 457 } 458 459 460 void 461 BHandler::UnlockLooper() 462 { 463 fLooper->Unlock(); 464 } 465 466 467 BHandler* 468 BHandler::ResolveSpecifier(BMessage* message, int32 index, 469 BMessage* specifier, int32 what, const char* property) 470 { 471 // Straight from the BeBook 472 BPropertyInfo propertyInfo(sHandlerPropInfo); 473 if (propertyInfo.FindMatch(message, index, specifier, what, property) >= 0) 474 return this; 475 476 BMessage reply(B_MESSAGE_NOT_UNDERSTOOD); 477 reply.AddInt32("error", B_BAD_SCRIPT_SYNTAX); 478 reply.AddString("message", "Didn't understand the specifier(s)"); 479 message->SendReply(&reply); 480 481 return NULL; 482 } 483 484 485 status_t 486 BHandler::GetSupportedSuites(BMessage* data) 487 { 488 /** 489 @note This is the output from the original implementation (calling 490 PrintToStream() on both data and the contained BPropertyInfo): 491 492 BMessage: what = (0x0, or 0) 493 entry suites, type='CSTR', c=1, size=21, data[0]: "suite/vnd.Be-handler" 494 entry messages, type='SCTD', c=1, size= 0, 495 property commands types specifiers 496 -------------------------------------------------------------------------------- 497 Suites PGET 1 498 (RTSC,suites) 499 (DTCS,messages) 500 501 Messenger PGET GNSM 1 502 InternalName PGET RTSC 1 503 504 With a good deal of trial and error, I determined that the 505 parenthetical clauses are entries in the 'ctypes' field of 506 property_info. 'ctypes' is an array of 'compound_type', which 507 contains an array of 'field_pair's. I haven't the foggiest what 508 either 'compound_type' or 'field_pair' is for, being as the 509 scripting docs are so bloody horrible. The corresponding 510 property_info array is declared in the globals section. 511 */ 512 513 if (data == NULL) 514 return B_BAD_VALUE; 515 516 status_t result = data->AddString("suites", "suite/vnd.Be-handler"); 517 if (result == B_OK) { 518 BPropertyInfo propertyInfo(sHandlerPropInfo); 519 result = data->AddFlat("messages", &propertyInfo); 520 } 521 522 return result; 523 } 524 525 526 status_t 527 BHandler::StartWatching(BMessenger target, uint32 what) 528 { 529 BMessage message(kMsgStartObserving); 530 message.AddMessenger(kObserveTarget, this); 531 message.AddInt32(B_OBSERVE_WHAT_CHANGE, what); 532 533 return target.SendMessage(&message); 534 } 535 536 537 status_t 538 BHandler::StartWatchingAll(BMessenger target) 539 { 540 return StartWatching(target, B_OBSERVER_OBSERVE_ALL); 541 } 542 543 544 status_t 545 BHandler::StopWatching(BMessenger target, uint32 what) 546 { 547 BMessage message(kMsgStopObserving); 548 message.AddMessenger(kObserveTarget, this); 549 message.AddInt32(B_OBSERVE_WHAT_CHANGE, what); 550 551 return target.SendMessage(&message); 552 } 553 554 555 status_t 556 BHandler::StopWatchingAll(BMessenger target) 557 { 558 return StopWatching(target, B_OBSERVER_OBSERVE_ALL); 559 } 560 561 562 status_t 563 BHandler::StartWatching(BHandler* handler, uint32 what) 564 { 565 ObserverList* list = _ObserverList(); 566 if (list == NULL) 567 return B_NO_MEMORY; 568 569 return list->Add(handler, what); 570 } 571 572 573 status_t 574 BHandler::StartWatchingAll(BHandler* handler) 575 { 576 return StartWatching(handler, B_OBSERVER_OBSERVE_ALL); 577 } 578 579 580 status_t 581 BHandler::StopWatching(BHandler* handler, uint32 what) 582 { 583 ObserverList* list = _ObserverList(); 584 if (list == NULL) 585 return B_NO_MEMORY; 586 587 return list->Remove(handler, what); 588 } 589 590 591 status_t 592 BHandler::StopWatchingAll(BHandler* handler) 593 { 594 return StopWatching(handler, B_OBSERVER_OBSERVE_ALL); 595 } 596 597 598 status_t 599 BHandler::Perform(perform_code d, void* arg) 600 { 601 return BArchivable::Perform(d, arg); 602 } 603 604 605 void 606 BHandler::SendNotices(uint32 what, const BMessage* notice) 607 { 608 if (fObserverList != NULL) 609 fObserverList->SendNotices(what, notice); 610 } 611 612 613 bool 614 BHandler::IsWatched() const 615 { 616 return fObserverList && !fObserverList->IsEmpty(); 617 } 618 619 620 void 621 BHandler::_InitData(const char* name) 622 { 623 SetName(name); 624 625 fLooper = NULL; 626 fNextHandler = NULL; 627 fFilters = NULL; 628 fObserverList = NULL; 629 630 fToken = gDefaultTokens.NewToken(B_HANDLER_TOKEN, this); 631 } 632 633 634 ObserverList* 635 BHandler::_ObserverList() 636 { 637 if (fObserverList == NULL) 638 fObserverList = new (std::nothrow) BPrivate::ObserverList(); 639 640 return fObserverList; 641 } 642 643 644 BHandler::BHandler(const BHandler &) 645 { 646 // No copy construction allowed. 647 } 648 649 650 BHandler & 651 BHandler::operator=(const BHandler &) 652 { 653 // No assignments allowed. 654 return *this; 655 } 656 657 658 void 659 BHandler::SetLooper(BLooper* looper) 660 { 661 fLooper = looper; 662 gDefaultTokens.SetHandlerTarget(fToken, 663 looper ? looper->fDirectTarget : NULL); 664 665 if (fFilters != NULL) { 666 for (int32 i = 0; i < fFilters->CountItems(); i++) { 667 static_cast<BMessageFilter*>( 668 fFilters->ItemAtFast(i))->SetLooper(looper); 669 } 670 } 671 } 672 673 674 #if __GNUC__ < 3 675 // binary compatibility with R4.5 676 677 extern "C" void 678 _ReservedHandler1__8BHandler(BHandler* handler, uint32 what, 679 const BMessage* notice) 680 { 681 handler->BHandler::SendNotices(what, notice); 682 } 683 684 #endif 685 686 void BHandler::_ReservedHandler2() {} 687 void BHandler::_ReservedHandler3() {} 688 void BHandler::_ReservedHandler4() {} 689 690 691 // #pragma mark - 692 693 694 ObserverList::ObserverList() 695 { 696 } 697 698 699 ObserverList::~ObserverList() 700 { 701 } 702 703 704 void 705 ObserverList::_ValidateHandlers(uint32 what) 706 { 707 vector<const BHandler*>& handlers = fHandlerMap[what]; 708 vector<const BHandler*>::iterator iterator = handlers.begin(); 709 710 while (iterator != handlers.end()) { 711 BMessenger target(*iterator); 712 if (!target.IsValid()) { 713 iterator++; 714 continue; 715 } 716 717 Add(target, what); 718 iterator = handlers.erase(iterator); 719 } 720 } 721 722 723 void 724 ObserverList::_SendNotices(uint32 what, BMessage* notice) 725 { 726 // first iterate over the list of handlers and try to make valid 727 // messengers out of them 728 _ValidateHandlers(what); 729 730 // now send it to all messengers we know 731 vector<BMessenger>& messengers = fMessengerMap[what]; 732 vector<BMessenger>::iterator iterator = messengers.begin(); 733 734 while (iterator != messengers.end()) { 735 if (!(*iterator).IsValid()) { 736 iterator = messengers.erase(iterator); 737 continue; 738 } 739 740 (*iterator).SendMessage(notice); 741 iterator++; 742 } 743 } 744 745 746 status_t 747 ObserverList::SendNotices(uint32 what, const BMessage* notice) 748 { 749 BMessage* copy = NULL; 750 if (notice != NULL) { 751 copy = new BMessage(*notice); 752 copy->what = B_OBSERVER_NOTICE_CHANGE; 753 copy->AddInt32(B_OBSERVE_ORIGINAL_WHAT, notice->what); 754 } else 755 copy = new BMessage(B_OBSERVER_NOTICE_CHANGE); 756 757 copy->AddInt32(B_OBSERVE_WHAT_CHANGE, what); 758 759 _SendNotices(what, copy); 760 _SendNotices(B_OBSERVER_OBSERVE_ALL, copy); 761 762 delete copy; 763 764 return B_OK; 765 } 766 767 768 status_t 769 ObserverList::Add(const BHandler* handler, uint32 what) 770 { 771 if (handler == NULL) 772 return B_BAD_HANDLER; 773 774 // if this handler already represents a valid target, add its messenger 775 BMessenger target(handler); 776 if (target.IsValid()) 777 return Add(target, what); 778 779 vector<const BHandler*> &handlers = fHandlerMap[what]; 780 781 vector<const BHandler*>::iterator iter; 782 iter = find(handlers.begin(), handlers.end(), handler); 783 if (iter != handlers.end()) { 784 // TODO: do we want to have a reference count for this? 785 return B_OK; 786 } 787 788 handlers.push_back(handler); 789 return B_OK; 790 } 791 792 793 status_t 794 ObserverList::Add(const BMessenger &messenger, uint32 what) 795 { 796 vector<BMessenger> &messengers = fMessengerMap[what]; 797 798 vector<BMessenger>::iterator iter; 799 iter = find(messengers.begin(), messengers.end(), messenger); 800 if (iter != messengers.end()) { 801 // TODO: do we want to have a reference count for this? 802 return B_OK; 803 } 804 805 messengers.push_back(messenger); 806 return B_OK; 807 } 808 809 810 status_t 811 ObserverList::Remove(const BHandler* handler, uint32 what) 812 { 813 if (handler == NULL) 814 return B_BAD_HANDLER; 815 816 // look into the list of messengers 817 BMessenger target(handler); 818 if (target.IsValid() && Remove(target, what) == B_OK) 819 return B_OK; 820 821 vector<const BHandler*> &handlers = fHandlerMap[what]; 822 823 vector<const BHandler*>::iterator iterator = find(handlers.begin(), 824 handlers.end(), handler); 825 if (iterator != handlers.end()) { 826 handlers.erase(iterator); 827 if (handlers.empty()) 828 fHandlerMap.erase(what); 829 830 return B_OK; 831 } 832 833 return B_BAD_HANDLER; 834 } 835 836 837 status_t 838 ObserverList::Remove(const BMessenger &messenger, uint32 what) 839 { 840 vector<BMessenger> &messengers = fMessengerMap[what]; 841 842 vector<BMessenger>::iterator iterator = find(messengers.begin(), 843 messengers.end(), messenger); 844 if (iterator != messengers.end()) { 845 messengers.erase(iterator); 846 if (messengers.empty()) 847 fMessengerMap.erase(what); 848 849 return B_OK; 850 } 851 852 return B_BAD_HANDLER; 853 } 854 855 856 bool 857 ObserverList::IsEmpty() 858 { 859 return fHandlerMap.empty() && fMessengerMap.empty(); 860 } 861 862 863 // #pragma mark - 864 865 866 bool 867 FilterDeleter(void* _filter) 868 { 869 delete static_cast<BMessageFilter*>(_filter); 870 return false; 871 } 872