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 BHandler::BHandler(const BHandler &) 646 { 647 // No copy construction allowed. 648 } 649 650 651 BHandler & 652 BHandler::operator=(const BHandler &) 653 { 654 // No assignments allowed. 655 return *this; 656 } 657 658 659 void 660 BHandler::SetLooper(BLooper* looper) 661 { 662 fLooper = looper; 663 gDefaultTokens.SetHandlerTarget(fToken, 664 looper ? looper->fDirectTarget : NULL); 665 666 if (fFilters != NULL) { 667 for (int32 i = 0; i < fFilters->CountItems(); i++) { 668 static_cast<BMessageFilter*>( 669 fFilters->ItemAtFast(i))->SetLooper(looper); 670 } 671 } 672 } 673 674 675 #if __GNUC__ < 3 676 // binary compatibility with R4.5 677 678 extern "C" void 679 _ReservedHandler1__8BHandler(BHandler* handler, uint32 what, 680 const BMessage* notice) 681 { 682 handler->BHandler::SendNotices(what, notice); 683 } 684 685 #endif 686 687 void BHandler::_ReservedHandler2() {} 688 void BHandler::_ReservedHandler3() {} 689 void BHandler::_ReservedHandler4() {} 690 691 692 // #pragma mark - 693 694 695 ObserverList::ObserverList() 696 { 697 } 698 699 700 ObserverList::~ObserverList() 701 { 702 } 703 704 705 void 706 ObserverList::_ValidateHandlers(uint32 what) 707 { 708 vector<const BHandler*>& handlers = fHandlerMap[what]; 709 vector<const BHandler*>::iterator iterator = handlers.begin(); 710 711 while (iterator != handlers.end()) { 712 BMessenger target(*iterator); 713 if (!target.IsValid()) { 714 iterator++; 715 continue; 716 } 717 718 Add(target, what); 719 iterator = handlers.erase(iterator); 720 } 721 } 722 723 724 void 725 ObserverList::_SendNotices(uint32 what, BMessage* notice) 726 { 727 // first iterate over the list of handlers and try to make valid 728 // messengers out of them 729 _ValidateHandlers(what); 730 731 // now send it to all messengers we know 732 vector<BMessenger>& messengers = fMessengerMap[what]; 733 vector<BMessenger>::iterator iterator = messengers.begin(); 734 735 while (iterator != messengers.end()) { 736 if (!(*iterator).IsValid()) { 737 iterator = messengers.erase(iterator); 738 continue; 739 } 740 741 (*iterator).SendMessage(notice); 742 iterator++; 743 } 744 } 745 746 747 status_t 748 ObserverList::SendNotices(uint32 what, const BMessage* notice) 749 { 750 BMessage* copy = NULL; 751 if (notice != NULL) { 752 copy = new BMessage(*notice); 753 copy->what = B_OBSERVER_NOTICE_CHANGE; 754 copy->AddInt32(B_OBSERVE_ORIGINAL_WHAT, notice->what); 755 } else 756 copy = new BMessage(B_OBSERVER_NOTICE_CHANGE); 757 758 copy->AddInt32(B_OBSERVE_WHAT_CHANGE, what); 759 760 _SendNotices(what, copy); 761 _SendNotices(B_OBSERVER_OBSERVE_ALL, copy); 762 763 delete copy; 764 765 return B_OK; 766 } 767 768 769 status_t 770 ObserverList::Add(const BHandler* handler, uint32 what) 771 { 772 if (handler == NULL) 773 return B_BAD_HANDLER; 774 775 // if this handler already represents a valid target, add its messenger 776 BMessenger target(handler); 777 if (target.IsValid()) 778 return Add(target, what); 779 780 vector<const BHandler*> &handlers = fHandlerMap[what]; 781 782 vector<const BHandler*>::iterator iter; 783 iter = find(handlers.begin(), handlers.end(), handler); 784 if (iter != handlers.end()) { 785 // TODO: do we want to have a reference count for this? 786 return B_OK; 787 } 788 789 handlers.push_back(handler); 790 return B_OK; 791 } 792 793 794 status_t 795 ObserverList::Add(const BMessenger &messenger, uint32 what) 796 { 797 vector<BMessenger> &messengers = fMessengerMap[what]; 798 799 vector<BMessenger>::iterator iter; 800 iter = find(messengers.begin(), messengers.end(), messenger); 801 if (iter != messengers.end()) { 802 // TODO: do we want to have a reference count for this? 803 return B_OK; 804 } 805 806 messengers.push_back(messenger); 807 return B_OK; 808 } 809 810 811 status_t 812 ObserverList::Remove(const BHandler* handler, uint32 what) 813 { 814 if (handler == NULL) 815 return B_BAD_HANDLER; 816 817 // look into the list of messengers 818 BMessenger target(handler); 819 if (target.IsValid() && Remove(target, what) == B_OK) 820 return B_OK; 821 822 vector<const BHandler*> &handlers = fHandlerMap[what]; 823 824 vector<const BHandler*>::iterator iterator = find(handlers.begin(), 825 handlers.end(), handler); 826 if (iterator != handlers.end()) { 827 handlers.erase(iterator); 828 if (handlers.empty()) 829 fHandlerMap.erase(what); 830 831 return B_OK; 832 } 833 834 return B_BAD_HANDLER; 835 } 836 837 838 status_t 839 ObserverList::Remove(const BMessenger &messenger, uint32 what) 840 { 841 vector<BMessenger> &messengers = fMessengerMap[what]; 842 843 vector<BMessenger>::iterator iterator = find(messengers.begin(), 844 messengers.end(), messenger); 845 if (iterator != messengers.end()) { 846 messengers.erase(iterator); 847 if (messengers.empty()) 848 fMessengerMap.erase(what); 849 850 return B_OK; 851 } 852 853 return B_BAD_HANDLER; 854 } 855 856 857 bool 858 ObserverList::IsEmpty() 859 { 860 return fHandlerMap.empty() && fMessengerMap.empty(); 861 } 862 863 864 // #pragma mark - 865 866 867 bool 868 FilterDeleter(void* _filter) 869 { 870 delete static_cast<BMessageFilter*>(_filter); 871 return false; 872 } 873