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