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