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