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