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