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 while (iterator != handlers.end()) { 686 BMessenger target(*iterator); 687 if (!target.IsValid()) { 688 iterator++; 689 continue; 690 } 691 692 Add(target, what); 693 iterator = handlers.erase(iterator); 694 } 695 } 696 697 698 void 699 ObserverList::_SendNotices(uint32 what, BMessage* message) 700 { 701 // first iterate over the list of handlers and try to make valid messengers out of them 702 _ValidateHandlers(what); 703 704 // now send it to all messengers we know 705 vector<BMessenger>& messengers = fMessengerMap[what]; 706 vector<BMessenger>::iterator iterator = messengers.begin(); 707 708 while (iterator != messengers.end()) { 709 if (!(*iterator).IsValid()) { 710 iterator = messengers.erase(iterator); 711 continue; 712 } 713 714 (*iterator).SendMessage(message); 715 iterator++; 716 } 717 } 718 719 720 status_t 721 ObserverList::SendNotices(uint32 what, const BMessage* message) 722 { 723 BMessage *copy = NULL; 724 if (message) { 725 copy = new BMessage(*message); 726 copy->what = B_OBSERVER_NOTICE_CHANGE; 727 copy->AddInt32(B_OBSERVE_ORIGINAL_WHAT, message->what); 728 } else 729 copy = new BMessage(B_OBSERVER_NOTICE_CHANGE); 730 731 copy->AddInt32(B_OBSERVE_WHAT_CHANGE, what); 732 733 _SendNotices(what, copy); 734 _SendNotices(B_OBSERVER_OBSERVE_ALL, copy); 735 736 delete copy; 737 return B_OK; 738 } 739 740 741 status_t 742 ObserverList::Add(const BHandler *handler, uint32 what) 743 { 744 if (handler == NULL) 745 return B_BAD_HANDLER; 746 747 // if this handler already represents a valid target, add its messenger 748 BMessenger target(handler); 749 if (target.IsValid()) 750 return Add(target, what); 751 752 vector<const BHandler*> &handlers = fHandlerMap[what]; 753 754 vector<const BHandler*>::iterator iter; 755 iter = find(handlers.begin(), handlers.end(), handler); 756 if (iter != handlers.end()) { 757 // TODO: do we want to have a reference count for this? 758 return B_OK; 759 } 760 761 handlers.push_back(handler); 762 return B_OK; 763 } 764 765 766 status_t 767 ObserverList::Add(const BMessenger &messenger, uint32 what) 768 { 769 vector<BMessenger> &messengers = fMessengerMap[what]; 770 771 vector<BMessenger>::iterator iter; 772 iter = find(messengers.begin(), messengers.end(), messenger); 773 if (iter != messengers.end()) { 774 // TODO: do we want to have a reference count for this? 775 return B_OK; 776 } 777 778 messengers.push_back(messenger); 779 return B_OK; 780 } 781 782 783 status_t 784 ObserverList::Remove(const BHandler *handler, uint32 what) 785 { 786 if (handler == NULL) 787 return B_BAD_HANDLER; 788 789 // look into the list of messengers 790 BMessenger target(handler); 791 if (target.IsValid() && Remove(target, what) == B_OK) 792 return B_OK; 793 794 vector<const BHandler*> &handlers = fHandlerMap[what]; 795 796 vector<const BHandler*>::iterator iterator = find(handlers.begin(), 797 handlers.end(), handler); 798 if (iterator != handlers.end()) { 799 handlers.erase(iterator); 800 if (handlers.empty()) 801 fHandlerMap.erase(what); 802 803 return B_OK; 804 } 805 806 return B_BAD_HANDLER; 807 } 808 809 810 status_t 811 ObserverList::Remove(const BMessenger &messenger, uint32 what) 812 { 813 vector<BMessenger> &messengers = fMessengerMap[what]; 814 815 vector<BMessenger>::iterator iterator = find(messengers.begin(), 816 messengers.end(), messenger); 817 if (iterator != messengers.end()) { 818 messengers.erase(iterator); 819 if (messengers.empty()) 820 fMessengerMap.erase(what); 821 822 return B_OK; 823 } 824 825 return B_BAD_HANDLER; 826 } 827 828 829 bool 830 ObserverList::IsEmpty() 831 { 832 return fHandlerMap.empty() && fMessengerMap.empty(); 833 } 834 835 836 // #pragma mark - 837 838 839 bool 840 FilterDeleter(void *_filter) 841 { 842 delete static_cast<BMessageFilter *>(_filter); 843 return false; 844 } 845 846