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