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