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 } 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