1 /* 2 * Copyright 2001-2005, Haiku. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Erik Jaesler (erik@cgsoftware.com) 7 * DarkWyrm <bpmagic@columbus.rr.com> 8 * Ingo Weinhold <bonefish@users.sf.net> 9 */ 10 11 #ifdef USING_MESSAGE4 12 # include "Message4.cpp" 13 #else 14 15 /** BMessage class creates objects that store data and that 16 * can be processed in a message loop. BMessage objects 17 * are also used as data containers by the archiving and 18 * the scripting mechanisms. 19 */ 20 21 // debugging 22 //#define DBG(x) x 23 #define DBG(x) ; 24 #define PRINT(x) DBG({ printf("[%6ld] ", find_thread(NULL)); printf x; }) 25 26 #include <stdio.h> 27 28 #include <Application.h> 29 #include <BlockCache.h> 30 #include <ByteOrder.h> 31 #include <Errors.h> 32 #include <Message.h> 33 #include <Messenger.h> 34 #include <MessengerPrivate.h> 35 #include <String.h> 36 37 #include <AppMisc.h> 38 #include <DataBuffer.h> 39 #include <KMessage.h> 40 #include <MessageBody.h> 41 #include <MessageUtils.h> 42 #include <TokenSpace.h> 43 44 #include "dano_message.h" 45 46 47 static const uint32 kMessageMagic = 'FOB1'; 48 static const uint32 kMessageMagicSwapped = '1BOF'; 49 50 static const uint32 kMessageMagicDano = 'FOB2'; 51 static const uint32 kMessageMagicDanoSwapped = '2BOF'; 52 53 // flags for the overall message (the bitfield is 1 byte) 54 #define MSG_FLAG_BIG_ENDIAN 0x01 55 #define MSG_FLAG_INCL_TARGET 0x02 56 #define MSG_FLAG_INCL_REPLY 0x04 57 #define MSG_FLAG_SCRIPT_MSG 0x08 58 // These are for future improvement 59 #if 0 60 #define MSG_FLAG_USE_PREFERRED 0x10 61 #define MSG_FLAG_REPLY_WANTED 0x20 62 #define MSG_FLAG_REPLY_DONE 0x40 63 #define MSG_FLAG_IS_REPLY 0x80 64 65 #define MSG_FLAG_HDR_MASK 0xF0 66 #endif 67 68 #define MSG_HEADER_MAX_SIZE 38 69 #define MSG_NAME_MAX_SIZE 256 70 71 // Globals --------------------------------------------------------------------- 72 73 using namespace BPrivate; 74 75 const char* B_SPECIFIER_ENTRY = "specifiers"; 76 const char* B_PROPERTY_ENTRY = "property"; 77 const char* B_PROPERTY_NAME_ENTRY = "name"; 78 79 BBlockCache* BMessage::sMsgCache = NULL; 80 port_id BMessage::sReplyPorts[sNumReplyPorts]; 81 long BMessage::sReplyPortInUse[sNumReplyPorts]; 82 83 84 static status_t handle_reply(port_id reply_port, 85 int32* pCode, 86 bigtime_t timeout, 87 BMessage* reply); 88 89 static status_t convert_message(const KMessage *fromMessage, 90 BMessage *toMessage); 91 92 static ssize_t min_hdr_size(); 93 94 95 // #pragma mark - 96 97 class BMessage::Header { 98 public: 99 Header() {} 100 Header(const BMessage &message) { ReadFrom(message); } 101 102 status_t SetMagic(uint32 magic); 103 104 status_t ReadFrom(BDataIO &stream); 105 void ReadFrom(const BMessage &message); 106 status_t WriteTo(BDataIO &stream, bool calculateCheckSum = true) const; 107 void WriteTo(BMessage &message) const; 108 109 uint32 CalculateCheckSum() const; 110 uint32 CalculateHeaderSize() const; 111 112 bool IsSwapped() const { return fSwapped; } 113 114 bool HasTarget() const { return (fFlags & MSG_FLAG_INCL_TARGET); } 115 void SetTarget(int32 token); 116 117 void Dump() const; 118 119 private: 120 uint32 fMagic; 121 int32 fBodySize; 122 uint32 fWhat; 123 uint8 fFlags; 124 int32 fTargetToken; 125 port_id fReplyPort; 126 int32 fReplyToken; 127 team_id fReplyTeam; 128 bool fReplyRequired; 129 bool fReplyDone; 130 bool fIsReply; 131 bool fSwapped; 132 }; 133 134 135 status_t 136 BMessage::Header::SetMagic(uint32 magic) 137 { 138 if (magic == kMessageMagicSwapped) { 139 fSwapped = true; 140 } else if (magic == kMessageMagic) { 141 fSwapped = false; 142 } else { 143 // This is *not* a message 144 return B_NOT_A_MESSAGE; 145 } 146 147 fMagic = magic; 148 return B_OK; 149 } 150 151 152 // ReadFrom 153 status_t 154 BMessage::Header::ReadFrom(BDataIO &stream) 155 { 156 int32 checkSum; 157 uchar csBuffer[MSG_HEADER_MAX_SIZE]; 158 159 TReadHelper read_helper(&stream); 160 TChecksumHelper checksum_helper(csBuffer); 161 int32 flattenedSize; 162 163 try { 164 read_helper.SetSwap(fSwapped); 165 166 // get the checksum 167 read_helper(checkSum); 168 // get the size 169 read_helper(flattenedSize); 170 checksum_helper.Cache(flattenedSize); 171 // Get the what 172 read_helper(fWhat); 173 checksum_helper.Cache(fWhat); 174 // Get the flags 175 read_helper(fFlags); 176 checksum_helper.Cache(fFlags); 177 178 if (fFlags & MSG_FLAG_BIG_ENDIAN) { 179 // TODO: ??? 180 // Isn't this already indicated by the byte order of the message version? 181 } 182 if (fFlags & MSG_FLAG_INCL_TARGET) { 183 // Get the target data 184 read_helper(fTargetToken); 185 checksum_helper.Cache(fTargetToken); 186 } 187 if (fFlags & MSG_FLAG_INCL_REPLY) { 188 // Get the reply port 189 read_helper(fReplyPort); 190 read_helper(fReplyToken); 191 read_helper(fReplyTeam); 192 checksum_helper.Cache(fReplyPort); 193 checksum_helper.Cache(fReplyToken); 194 checksum_helper.Cache(fReplyTeam); 195 196 // Get the "big flags" 197 uint8 bigFlags; 198 // Get the preferred flag 199 read_helper(bigFlags); 200 checksum_helper.Cache(bigFlags); 201 if (bigFlags) 202 fTargetToken = B_PREFERRED_TOKEN; 203 204 // Get the reply requirement flag 205 read_helper(bigFlags); 206 checksum_helper.Cache(bigFlags); 207 fReplyRequired = bigFlags; 208 209 // Get the reply done flag 210 read_helper(bigFlags); 211 checksum_helper.Cache(bigFlags); 212 fReplyDone = bigFlags; 213 214 // Get the "is reply" flag 215 read_helper(bigFlags); 216 checksum_helper.Cache(bigFlags); 217 fIsReply = bigFlags; 218 } 219 } catch (status_t& e) { 220 return e; 221 } 222 223 fBodySize = flattenedSize - CalculateHeaderSize(); 224 225 if (checkSum != checksum_helper.CheckSum()) 226 return B_NOT_A_MESSAGE; 227 228 return B_OK; 229 } 230 231 // ReadFrom 232 void 233 BMessage::Header::ReadFrom(const BMessage &message) 234 { 235 fMagic = kMessageMagic; 236 237 fBodySize = message.fBody->FlattenedSize(); 238 fWhat = message.what; 239 fFlags = 0; 240 #ifdef B_HOST_IS_BENDIAN 241 fFlags |= MSG_FLAG_BIG_ENDIAN; 242 #endif 243 if (message.HasSpecifiers()) 244 fFlags |= MSG_FLAG_SCRIPT_MSG; 245 if (message.fTarget != B_NULL_TOKEN) 246 fFlags |= MSG_FLAG_INCL_TARGET; 247 if (message.fReplyTo.port >= 0 && 248 message.fReplyTo.target != B_NULL_TOKEN && 249 message.fReplyTo.team >= 0) { 250 fFlags |= MSG_FLAG_INCL_REPLY; 251 } 252 fTargetToken = message.fTarget; 253 fReplyPort = message.fReplyTo.port; 254 fReplyToken = message.fReplyTo.target; 255 fReplyTeam = message.fReplyTo.team; 256 fReplyRequired = message.fReplyRequired; 257 fReplyDone = message.fReplyDone; 258 fIsReply = message.fIsReply; 259 } 260 261 // WriteTo 262 status_t 263 BMessage::Header::WriteTo(BDataIO &stream, bool calculateCheckSum) const 264 { 265 status_t err = B_OK; 266 int32 data; 267 268 // Write the version of the binary data format 269 data = fMagic; 270 write_helper(&stream, (const void*)&data, sizeof (data), err); 271 if (!err) { 272 // compute checksum 273 data = (calculateCheckSum ? CalculateCheckSum() : 0); 274 write_helper(&stream, (const void*)&data, sizeof (data), err); 275 } 276 if (!err) { 277 // Write the flattened size of the entire message 278 data = CalculateHeaderSize() + fBodySize; 279 write_helper(&stream, (const void*)&data, sizeof (data), err); 280 } 281 if (!err) { 282 // Write the 'what' member 283 write_helper(&stream, (const void*)&fWhat, sizeof (fWhat), err); 284 } 285 if (!err) { 286 // Write the header flags 287 write_helper(&stream, (const void*)&fFlags, sizeof (fFlags), err); 288 } 289 290 // Write targeting info if necessary 291 if (!err && (fFlags & MSG_FLAG_INCL_TARGET)) { 292 data = fTargetToken; 293 write_helper(&stream, (const void*)&data, sizeof (data), err); 294 } 295 296 // Write reply info if necessary 297 if (!err && (fFlags & MSG_FLAG_INCL_REPLY)) { 298 write_helper(&stream, (const void*)&fReplyPort, sizeof(fReplyPort), 299 err); 300 if (!err) { 301 write_helper(&stream, (const void*)&fReplyToken, 302 sizeof(fReplyToken), err); 303 } 304 if (!err) { 305 write_helper(&stream, (const void*)&fReplyTeam, 306 sizeof(fReplyTeam), err); 307 } 308 309 uint8 bigFlags; 310 if (!err) { 311 bigFlags = fTargetToken == B_PREFERRED_TOKEN ? 1 : 0; 312 write_helper(&stream, (const void*)&bigFlags, sizeof(bigFlags), 313 err); 314 } 315 if (!err) 316 { 317 bigFlags = fReplyRequired ? 1 : 0; 318 write_helper(&stream, (const void*)&bigFlags, sizeof(bigFlags), 319 err); 320 } 321 if (!err) 322 { 323 bigFlags = fReplyDone ? 1 : 0; 324 write_helper(&stream, (const void*)&bigFlags, sizeof(bigFlags), 325 err); 326 } 327 if (!err) 328 { 329 bigFlags = fIsReply ? 1 : 0; 330 write_helper(&stream, (const void*)&bigFlags, sizeof(bigFlags), 331 err); 332 } 333 } 334 335 return err; 336 } 337 338 // WriteTo 339 void 340 BMessage::Header::WriteTo(BMessage &message) const 341 { 342 // Make way for the new data 343 message.MakeEmpty(); 344 345 message.what = fWhat; 346 message.fHasSpecifiers = fFlags & MSG_FLAG_SCRIPT_MSG; 347 348 message.fPreferred = fTargetToken == B_PREFERRED_TOKEN; 349 message.fTarget = fTargetToken; 350 351 if (fFlags & MSG_FLAG_INCL_REPLY) { 352 // Get the reply port 353 message.fReplyTo.port = fReplyPort; 354 message.fReplyTo.target = fReplyToken; 355 message.fReplyTo.team = fReplyTeam; 356 357 message.fWasDelivered = true; 358 359 message.fReplyRequired = fReplyRequired; 360 message.fReplyDone = fReplyDone; 361 message.fIsReply = fIsReply; 362 } 363 } 364 365 // CalculateCheckSum 366 uint32 367 BMessage::Header::CalculateCheckSum() const 368 { 369 uchar buffer[MSG_HEADER_MAX_SIZE]; 370 BMemoryIO stream(buffer, sizeof(buffer)); 371 WriteTo(stream, false); 372 int32 size = stream.Position(); 373 return _checksum_(buffer + 8, size - 8); 374 } 375 376 // CalculateHeaderSize 377 uint32 378 BMessage::Header::CalculateHeaderSize() const 379 { 380 ssize_t size = min_hdr_size(); 381 382 if (fTargetToken != B_NULL_TOKEN) 383 size += sizeof (fTargetToken); 384 385 if (fReplyPort >= 0 && fReplyToken != B_NULL_TOKEN && fReplyTeam >= 0) { 386 size += sizeof (fReplyPort); 387 size += sizeof (fReplyToken); 388 size += sizeof (fReplyTeam); 389 390 size += 4; // For the "big" flags 391 } 392 393 return size; 394 } 395 396 // SetTarget 397 void 398 BMessage::Header::SetTarget(int32 token) 399 { 400 fTargetToken = token; 401 if (fTargetToken == B_NULL_TOKEN) 402 fFlags &= ~MSG_FLAG_INCL_TARGET; 403 else 404 fFlags |= MSG_FLAG_INCL_TARGET; 405 } 406 407 // Dump 408 void 409 BMessage::Header::Dump() const 410 { 411 printf("BMessage::Header:\n"); 412 printf(" magic: %lx\n", fMagic); 413 printf(" body size: %ld\n", fBodySize); 414 printf(" what: %lx\n", fWhat); 415 printf(" flags: %x\n", fFlags); 416 printf(" target token: %ld\n", fTargetToken); 417 printf(" reply port: %ld\n", fReplyPort); 418 printf(" reply token: %ld\n", fReplyToken); 419 printf(" reply team: %ld\n", fReplyTeam); 420 printf(" reply required: %d\n", fReplyRequired); 421 printf(" reply done: %d\n", fReplyDone); 422 printf(" is reply: %d\n", fIsReply); 423 printf(" swapped: %d\n", fSwapped); 424 } 425 426 // #pragma mark - 427 428 void BMessage::_ReservedMessage1() {} 429 void BMessage::_ReservedMessage2() {} 430 void BMessage::_ReservedMessage3() {} 431 432 //------------------------------------------------------------------------------ 433 BMessage::BMessage() 434 : what(0), fBody(NULL) 435 { 436 init_data(); 437 } 438 //------------------------------------------------------------------------------ 439 BMessage::BMessage(uint32 w) 440 : fBody(NULL) 441 { 442 init_data(); 443 what = w; 444 } 445 //------------------------------------------------------------------------------ 446 BMessage::BMessage(const BMessage& a_message) 447 : fBody(NULL) 448 { 449 init_data(); 450 *this = a_message; 451 } 452 //------------------------------------------------------------------------------ 453 BMessage::BMessage(BMessage *a_message) 454 : fBody(NULL) 455 { 456 init_data(); 457 *this = *a_message; 458 } 459 //------------------------------------------------------------------------------ 460 BMessage::~BMessage() 461 { 462 if (IsSourceWaiting()) 463 { 464 SendReply(B_NO_REPLY); 465 } 466 delete fBody; 467 } 468 //------------------------------------------------------------------------------ 469 BMessage& BMessage::operator=(const BMessage& msg) 470 { 471 what = msg.what; 472 473 fQueueLink = msg.fQueueLink; 474 fTarget = msg.fTarget; 475 fOriginal = msg.fOriginal; 476 fChangeCount = msg.fChangeCount; 477 fCurSpecifier = msg.fCurSpecifier; 478 fPtrOffset = msg.fPtrOffset; 479 480 fEntries = msg.fEntries; 481 482 fReplyTo.port = msg.fReplyTo.port; 483 fReplyTo.target = msg.fReplyTo.target; 484 fReplyTo.team = msg.fReplyTo.team; 485 fReplyTo.preferred = msg.fReplyTo.preferred; 486 487 fPreferred = msg.fPreferred; 488 fReplyRequired = msg.fReplyRequired; 489 fReplyDone = msg.fReplyDone; 490 fIsReply = msg.fIsReply; 491 fWasDelivered = msg.fWasDelivered; 492 fReadOnly = msg.fReadOnly; 493 fHasSpecifiers = msg.fHasSpecifiers; 494 495 *fBody = *(msg.fBody); 496 return *this; 497 } 498 //------------------------------------------------------------------------------ 499 void BMessage::init_data() 500 { 501 what = 0; 502 503 fQueueLink = NULL; 504 fTarget = B_NULL_TOKEN; 505 fOriginal = NULL; 506 fChangeCount = 0; 507 fCurSpecifier = -1; 508 fPtrOffset = 0; 509 510 fEntries = NULL; 511 512 fReplyTo.port = -1; 513 fReplyTo.target = B_NULL_TOKEN; 514 fReplyTo.team = -1; 515 fReplyTo.preferred = false; 516 517 fPreferred = false; 518 fReplyRequired = false; 519 fReplyDone = false; 520 fIsReply = false; 521 fWasDelivered = false; 522 fReadOnly = false; 523 fHasSpecifiers = false; 524 525 if (fBody) 526 { 527 fBody->MakeEmpty(); 528 } 529 else 530 { 531 fBody = new BPrivate::BMessageBody; 532 } 533 } 534 //------------------------------------------------------------------------------ 535 status_t BMessage::GetInfo(type_code typeRequested, int32 which, char** name, 536 type_code* typeReturned, int32* count) const 537 { 538 return fBody->GetInfo(typeRequested, which, name, typeReturned, count); 539 } 540 //------------------------------------------------------------------------------ 541 status_t BMessage::GetInfo(const char* name, type_code* type, int32* c) const 542 { 543 return fBody->GetInfo(name, type, c); 544 } 545 //------------------------------------------------------------------------------ 546 status_t BMessage::GetInfo(const char* name, type_code* type, 547 bool* fixed_size) const 548 { 549 return fBody->GetInfo(name, type, fixed_size); 550 } 551 //------------------------------------------------------------------------------ 552 int32 BMessage::CountNames(type_code type) const 553 { 554 return fBody->CountNames(type); 555 } 556 //------------------------------------------------------------------------------ 557 bool BMessage::IsEmpty() const 558 { 559 return fBody->IsEmpty(); 560 } 561 //------------------------------------------------------------------------------ 562 bool BMessage::IsSystem() const 563 { 564 char a = char(what >> 24); 565 char b = char(what >> 16); 566 char c = char(what >> 8); 567 char d = char(what); 568 569 // The BeBook says: 570 // ... we've adopted a strict convention for assigning values to all 571 // Be-defined constants. The value assigned will always be formed by 572 // combining four characters into a multicharacter constant, with the 573 // characters limited to uppercase letters and the underbar 574 // Between that and what's in AppDefs.h, this algo seems like a safe bet: 575 if (a == '_' && isupper(b) && isupper(c) && isupper(d)) 576 { 577 return true; 578 } 579 580 return false; 581 } 582 //------------------------------------------------------------------------------ 583 bool BMessage::IsReply() const 584 { 585 return fIsReply; 586 } 587 //------------------------------------------------------------------------------ 588 void BMessage::PrintToStream() const 589 { 590 printf("\nBMessage: what = (0x%lX or %ld)\n", what, what); 591 fBody->PrintToStream(); 592 } 593 //------------------------------------------------------------------------------ 594 status_t BMessage::Rename(const char* old_entry, const char* new_entry) 595 { 596 return fBody->Rename(old_entry, new_entry); 597 } 598 //------------------------------------------------------------------------------ 599 bool BMessage::WasDelivered() const 600 { 601 return fWasDelivered; 602 } 603 //------------------------------------------------------------------------------ 604 bool BMessage::IsSourceWaiting() const 605 { 606 return fReplyRequired && !fReplyDone; 607 } 608 //------------------------------------------------------------------------------ 609 bool BMessage::IsSourceRemote() const 610 { 611 return WasDelivered() && fReplyTo.team != BPrivate::current_team(); 612 } 613 //------------------------------------------------------------------------------ 614 BMessenger BMessage::ReturnAddress() const 615 { 616 if (WasDelivered()) 617 { 618 BMessenger messenger; 619 BMessenger::Private(messenger).SetTo(fReplyTo.team, fReplyTo.port, 620 fReplyTo.target); 621 return messenger; 622 } 623 624 return BMessenger(); 625 } 626 //------------------------------------------------------------------------------ 627 const BMessage* BMessage::Previous() const 628 { 629 // TODO: test 630 // In particular, look to see if the "_previous_" field is used in R5 631 if (!fOriginal) 632 { 633 BMessage* fOriginal = new BMessage; 634 if (FindMessage("_previous_", fOriginal) != B_OK) 635 { 636 delete fOriginal; 637 fOriginal = NULL; 638 } 639 } 640 641 return fOriginal; 642 } 643 //------------------------------------------------------------------------------ 644 bool BMessage::WasDropped() const 645 { 646 return fReadOnly; 647 } 648 //------------------------------------------------------------------------------ 649 BPoint BMessage::DropPoint(BPoint* offset) const 650 { 651 // TODO: Where do we get this stuff??? 652 if (offset) 653 { 654 *offset = FindPoint("_drop_offset_"); 655 } 656 return FindPoint("_drop_point_"); 657 } 658 //------------------------------------------------------------------------------ 659 status_t BMessage::SendReply(uint32 command, BHandler* reply_to) 660 { 661 BMessage msg(command); 662 return SendReply(&msg, reply_to); 663 } 664 //------------------------------------------------------------------------------ 665 status_t BMessage::SendReply(BMessage* the_reply, BHandler* reply_to, 666 bigtime_t timeout) 667 { 668 BMessenger messenger(reply_to); 669 return SendReply(the_reply, messenger, timeout); 670 } 671 //------------------------------------------------------------------------------ 672 #if 0 673 template<class Sender> 674 status_t SendReplyHelper(BMessage* the_message, BMessage* the_reply, 675 Sender& the_sender) 676 { 677 BMessenger messenger(the_message->fReplyTo.team, the_message->fReplyTo.port, 678 the_message->fReplyTo.target, 679 the_message->fReplyTo.preferred); 680 if (the_message->fReplyRequired) 681 { 682 if (the_message->fReplyDone) 683 { 684 return B_DUPLICATE_REPLY; 685 } 686 the_message->fReplyDone = true; 687 the_reply->fIsReply = true; 688 status_t err = the_sender.Send(messenger, the_reply); 689 the_reply->fIsReply = false; 690 if (err) 691 { 692 if (set_port_owner(messenger.fPort, messenger.fTeam) == B_BAD_TEAM_ID) 693 { 694 delete_port(messenger.fPort); 695 } 696 } 697 return err; 698 } 699 // no reply required 700 if (!the_message->fWasDelivered) 701 { 702 return B_BAD_REPLY; 703 } 704 705 #if 0 706 char tmp[0x800]; 707 ssize_t size; 708 char* p = stack_flatten(tmp, sizeof(tmp), true /* include reply */, &size); 709 the_reply->AddData("_previous_", B_RAW_TYPE, p ? p : tmp, &size); 710 if (p) 711 { 712 free(p); 713 } 714 #endif 715 the_reply->AddMessage("_previous_", the_message); 716 the_reply->fIsReply = true; 717 status_t err = the_sender.Send(messenger, the_reply); 718 the_reply->fIsReply = false; 719 the_reply->RemoveName("_previous_"); 720 return err; 721 }; 722 #endif 723 //------------------------------------------------------------------------------ 724 #if 0 725 struct Sender1 726 { 727 BMessenger& reply_to; 728 bigtime_t timeout; 729 730 Sender1(BMessenger& m, bigtime_t t) : reply_to(m), timeout(t) {;} 731 732 status_t Send(BMessenger& messenger, BMessage* the_reply) 733 { 734 return messenger.SendMessage(the_reply, reply_to, timeout); 735 } 736 }; 737 status_t BMessage::SendReply(BMessage* the_reply, BMessenger reply_to, 738 bigtime_t timeout) 739 { 740 Sender1 mySender(reply_to, timeout); 741 return SendReplyHelper(this, the_reply, mySender); 742 } 743 #endif 744 status_t BMessage::SendReply(BMessage* the_reply, BMessenger reply_to, 745 bigtime_t timeout) 746 { 747 // TODO: test 748 BMessenger messenger; 749 750 BMessenger::Private messengerPrivate(messenger); 751 messengerPrivate.SetTo(fReplyTo.team, fReplyTo.port, fReplyTo.target); 752 if (fReplyRequired) 753 { 754 if (fReplyDone) 755 { 756 return B_DUPLICATE_REPLY; 757 } 758 fReplyDone = true; 759 the_reply->fIsReply = true; 760 status_t err = messenger.SendMessage(the_reply, reply_to, timeout); 761 the_reply->fIsReply = false; 762 if (err) 763 { 764 if (set_port_owner(messengerPrivate.Port(), 765 messengerPrivate.Team()) == B_BAD_TEAM_ID) { 766 delete_port(messengerPrivate.Port()); 767 } 768 } 769 return err; 770 } 771 // no reply required 772 if (!fWasDelivered) 773 { 774 return B_BAD_REPLY; 775 } 776 777 the_reply->AddMessage("_previous_", this); 778 the_reply->fIsReply = true; 779 status_t err = messenger.SendMessage(the_reply, reply_to, timeout); 780 the_reply->fIsReply = false; 781 the_reply->RemoveName("_previous_"); 782 return err; 783 } 784 //------------------------------------------------------------------------------ 785 status_t BMessage::SendReply(uint32 command, BMessage* reply_to_reply) 786 { 787 BMessage msg(command); 788 return SendReply(&msg, reply_to_reply); 789 } 790 //------------------------------------------------------------------------------ 791 #if 0 792 struct Sender2 793 { 794 BMessage* reply_to_reply; 795 bigtime_t send_timeout; 796 bigtime_t reply_timeout; 797 798 Sender2(BMessage* m, bigtime_t t1, bigtime_t t2) 799 : reply_to_reply(m), send_timeout(t1), reply_timeout(t2) {;} 800 801 status_t Send(BMessenger& messenger, BMessage* the_reply) 802 { 803 return messenger.SendMessage(the_reply, reply_to_reply, 804 send_timeout, reply_timeout); 805 } 806 }; 807 status_t BMessage::SendReply(BMessage* the_reply, BMessage* reply_to_reply, 808 bigtime_t send_timeout, bigtime_t reply_timeout) 809 { 810 Sender2 mySender(reply_to_reply, send_timeout, reply_timeout); 811 return SendReplyHelper(this, the_reply, mySender); 812 } 813 #endif 814 status_t BMessage::SendReply(BMessage* the_reply, BMessage* reply_to_reply, 815 bigtime_t send_timeout, bigtime_t reply_timeout) 816 { 817 // TODO: test 818 BMessenger messenger; 819 BMessenger::Private messengerPrivate(messenger); 820 messengerPrivate.SetTo(fReplyTo.team, fReplyTo.port, fReplyTo.target); 821 if (fReplyRequired) 822 { 823 if (fReplyDone) 824 { 825 return B_DUPLICATE_REPLY; 826 } 827 fReplyDone = true; 828 the_reply->fIsReply = true; 829 status_t err = messenger.SendMessage(the_reply, reply_to_reply, 830 send_timeout, reply_timeout); 831 the_reply->fIsReply = false; 832 if (err) 833 { 834 if (set_port_owner(messengerPrivate.Port(), 835 messengerPrivate.Team()) == B_BAD_TEAM_ID) { 836 delete_port(messengerPrivate.Port()); 837 } 838 } 839 return err; 840 } 841 // no reply required 842 if (!fWasDelivered) 843 { 844 return B_BAD_REPLY; 845 } 846 847 the_reply->AddMessage("_previous_", this); 848 the_reply->fIsReply = true; 849 status_t err = messenger.SendMessage(the_reply, reply_to_reply, 850 send_timeout, reply_timeout); 851 the_reply->fIsReply = false; 852 the_reply->RemoveName("_previous_"); 853 return err; 854 } 855 //------------------------------------------------------------------------------ 856 ssize_t BMessage::FlattenedSize() const 857 { 858 return calc_hdr_size(0) + fBody->FlattenedSize(); 859 } 860 //------------------------------------------------------------------------------ 861 status_t BMessage::Flatten(char* buffer, ssize_t size) const 862 { 863 return real_flatten(buffer, size); 864 } 865 //------------------------------------------------------------------------------ 866 status_t BMessage::Flatten(BDataIO* stream, ssize_t* size) const 867 { 868 status_t err = B_OK; 869 ssize_t len = FlattenedSize(); 870 char* buffer = new(nothrow) char[len]; 871 if (buffer) 872 { 873 err = Flatten(buffer, len); 874 if (!err) 875 { 876 // size is an optional parameter, don't crash on NULL 877 if (size != NULL) 878 { 879 *size = len; 880 } 881 err = stream->Write(buffer, len); 882 if (err > B_OK) 883 err = B_OK; 884 } 885 886 delete[] buffer; 887 } 888 else 889 { 890 err = B_NO_MEMORY; 891 } 892 893 return err; 894 } 895 896 897 status_t 898 BMessage::Unflatten(const char* buffer) 899 { 900 if (!buffer) 901 return B_BAD_VALUE; 902 903 uint32 magic = *(uint32*)buffer; 904 905 // we support several message formats - this list is ordered 906 // by importance and frequency 907 908 if (magic == kMessageMagic) { 909 // it appears to be a normal flattened BMessage 910 BMemoryIO memoryStream(buffer, ((uint32*)buffer)[2]); 911 return Unflatten(&memoryStream); 912 } 913 914 // check whether this is a KMessage 915 if (((KMessage::Header*)buffer)->magic 916 == KMessage::kMessageHeaderMagic) 917 return _UnflattenKMessage(buffer); 918 919 if (magic == kMessageMagicSwapped) { 920 // it appears to be a swapped flattened BMessage 921 uint32 size = ((uint32*)buffer)[2]; 922 923 BMemoryIO memoryStream(buffer, __swap_int32(size)); 924 return Unflatten(&memoryStream); 925 } 926 927 if (magic == kMessageMagicDano || magic == kMessageMagicDanoSwapped) { 928 // dano style message 929 BMemoryIO memoryStream(buffer, 930 BPrivate::dano_message_flattened_size(buffer)); 931 return Unflatten(&memoryStream); 932 } 933 934 return B_NOT_A_MESSAGE; 935 } 936 937 938 status_t 939 BMessage::Unflatten(BDataIO* stream) 940 { 941 TReadHelper reader(stream); 942 Header header; 943 status_t status = B_OK; 944 945 // ToDo: while reading from a stream is certainly more convenient than 946 // from a buffer, it causes a lot of unnecessary copies, and therefore 947 // probably shouldn't be the preferred (or only) route. 948 949 try { 950 uint32 magic; 951 reader(magic); 952 953 status = header.SetMagic(magic); 954 if (status < B_OK) { 955 // we support reading Dano messages from disk as well 956 if (magic == kMessageMagicDano) 957 return BPrivate::unflatten_dano_message(magic, *stream, *this); 958 959 return status; 960 } 961 962 status = header.ReadFrom(*stream); 963 if (status < B_OK) { 964 printf("BMessage::Unflatten(): Reading the header failed: %lx\n", status); 965 return status; 966 } 967 968 header.WriteTo(*this); 969 bool swap = header.IsSwapped(); 970 971 uint32 count; 972 uint32 dataLen; 973 uint8 nameLen; 974 char name[MSG_NAME_MAX_SIZE]; 975 unsigned char* databuffer = NULL; 976 977 int8 flags; 978 reader(flags); 979 980 while (flags != MSG_LAST_ENTRY) { 981 type_code type; 982 reader(type); 983 984 // Is there more than one data item? 985 if (flags & MSG_FLAG_SINGLE_ITEM) { 986 count = 1; 987 if (flags & MSG_FLAG_MINI_DATA) { 988 uint8 littleLen; 989 reader(littleLen); 990 dataLen = littleLen; 991 } else 992 reader(dataLen); 993 } else { 994 // Is there a little data? 995 if (flags & MSG_FLAG_MINI_DATA) { 996 // Get item count (1 byte) 997 uint8 littleCount; 998 reader(littleCount); 999 count = littleCount; 1000 1001 // Get data length (1 byte) 1002 uint8 littleLen; 1003 reader(littleLen); 1004 dataLen = littleLen; 1005 } else { 1006 // Is there a lot of data? 1007 // Get item count (4 bytes) 1008 reader(count); 1009 // Get data length (4 bytes) 1010 reader(dataLen); 1011 } 1012 } 1013 1014 // Get the name length (1 byte) 1015 reader(nameLen); 1016 // Get the name (name length bytes) 1017 reader(name, nameLen); 1018 name[nameLen] = '\0'; 1019 1020 // Copy the data into a new buffer to byte align it 1021 databuffer = (unsigned char*)realloc(databuffer, dataLen); 1022 if (!databuffer) 1023 throw B_NO_MEMORY; 1024 // Get the data 1025 reader(databuffer, dataLen); 1026 1027 if (swap) { 1028 // Is the data fixed size? 1029 if ((flags & MSG_FLAG_FIXED_SIZE) != 0) { 1030 // Make sure to swap the data 1031 status = swap_data(type, (void*)databuffer, dataLen, 1032 B_SWAP_ALWAYS); 1033 if (status < B_OK) 1034 throw status; 1035 } else if (type == B_REF_TYPE) { 1036 // Is the data variable size? 1037 // Apparently, entry_refs are the only variable-length data 1038 // explicitely swapped -- the dev_t and ino_t 1039 // specifically 1040 byte_swap(*(entry_ref*)databuffer); 1041 } 1042 } 1043 1044 // Add each data field to the message 1045 uint32 itemSize = 0; 1046 if (flags & MSG_FLAG_FIXED_SIZE) 1047 itemSize = dataLen / count; 1048 1049 unsigned char* dataPtr = databuffer; 1050 1051 for (uint32 i = 0; i < count; ++i) { 1052 // Line up for the next item 1053 if (i) { 1054 if (flags & MSG_FLAG_FIXED_SIZE) { 1055 dataPtr += itemSize; 1056 } else { 1057 // Have to account for 8-byte boundary padding 1058 // We add 4 because padding as calculated during 1059 // flattening includes the four-byte size header 1060 dataPtr += itemSize + calc_padding(itemSize + 4, 8); 1061 } 1062 } 1063 1064 if ((flags & MSG_FLAG_FIXED_SIZE) == 0) { 1065 itemSize = *(uint32*)dataPtr; 1066 dataPtr += sizeof (uint32); 1067 } 1068 1069 status = AddData(name, type, dataPtr, itemSize, 1070 flags & MSG_FLAG_FIXED_SIZE); 1071 if (status < B_OK) 1072 throw status; 1073 } 1074 1075 reader(flags); 1076 } 1077 } catch (status_t& e) { 1078 status = e; 1079 } 1080 1081 return status; 1082 } 1083 //------------------------------------------------------------------------------ 1084 status_t BMessage::AddSpecifier(const char* property) 1085 { 1086 BMessage message(B_DIRECT_SPECIFIER); 1087 status_t err = message.AddString(B_PROPERTY_ENTRY, property); 1088 if (err) 1089 return err; 1090 1091 return AddSpecifier(&message); 1092 } 1093 //------------------------------------------------------------------------------ 1094 status_t BMessage::AddSpecifier(const char* property, int32 index) 1095 { 1096 BMessage message(B_INDEX_SPECIFIER); 1097 status_t err = message.AddString(B_PROPERTY_ENTRY, property); 1098 if (err) 1099 return err; 1100 1101 err = message.AddInt32("index", index); 1102 if (err) 1103 return err; 1104 1105 return AddSpecifier(&message); 1106 } 1107 //------------------------------------------------------------------------------ 1108 status_t BMessage::AddSpecifier(const char* property, int32 index, int32 range) 1109 { 1110 if (range < 0) 1111 return B_BAD_VALUE; 1112 1113 BMessage message(B_RANGE_SPECIFIER); 1114 status_t err = message.AddString(B_PROPERTY_ENTRY, property); 1115 if (err) 1116 return err; 1117 1118 err = message.AddInt32("index", index); 1119 if (err) 1120 return err; 1121 1122 err = message.AddInt32("range", range); 1123 if (err) 1124 return err; 1125 1126 return AddSpecifier(&message); 1127 } 1128 //------------------------------------------------------------------------------ 1129 status_t BMessage::AddSpecifier(const char* property, const char* name) 1130 { 1131 BMessage message(B_NAME_SPECIFIER); 1132 status_t err = message.AddString(B_PROPERTY_ENTRY, property); 1133 if (err) 1134 return err; 1135 1136 err = message.AddString(B_PROPERTY_NAME_ENTRY, name); 1137 if (err) 1138 return err; 1139 1140 return AddSpecifier(&message); 1141 } 1142 //------------------------------------------------------------------------------ 1143 status_t BMessage::AddSpecifier(const BMessage* specifier) 1144 { 1145 status_t err = AddMessage(B_SPECIFIER_ENTRY, specifier); 1146 if (!err) 1147 { 1148 ++fCurSpecifier; 1149 fHasSpecifiers = true; 1150 } 1151 return err; 1152 } 1153 //------------------------------------------------------------------------------ 1154 status_t BMessage::SetCurrentSpecifier(int32 index) 1155 { 1156 type_code type; 1157 int32 count; 1158 status_t err = GetInfo(B_SPECIFIER_ENTRY, &type, &count); 1159 if (err) 1160 return err; 1161 1162 if (index < 0 || index >= count) 1163 return B_BAD_INDEX; 1164 1165 fCurSpecifier = index; 1166 1167 return B_OK; 1168 } 1169 //------------------------------------------------------------------------------ 1170 status_t BMessage::GetCurrentSpecifier(int32* index, BMessage* specifier, 1171 int32* what, const char** property) const 1172 { 1173 if (fCurSpecifier == -1 || !WasDelivered()) 1174 return B_BAD_SCRIPT_SYNTAX; 1175 1176 if (index) 1177 *index = fCurSpecifier; 1178 1179 if (specifier) 1180 { 1181 if (FindMessage(B_SPECIFIER_ENTRY, fCurSpecifier, specifier)) 1182 return B_BAD_SCRIPT_SYNTAX; 1183 1184 if (what) 1185 *what = specifier->what; 1186 1187 if (property) 1188 { 1189 if (specifier->FindString(B_PROPERTY_ENTRY, property)) 1190 return B_BAD_SCRIPT_SYNTAX; 1191 } 1192 } 1193 1194 return B_OK; 1195 } 1196 //------------------------------------------------------------------------------ 1197 bool BMessage::HasSpecifiers() const 1198 { 1199 return fHasSpecifiers; 1200 } 1201 //------------------------------------------------------------------------------ 1202 status_t BMessage::PopSpecifier() 1203 { 1204 if (fCurSpecifier < 0 || !WasDelivered()) 1205 { 1206 return B_BAD_VALUE; 1207 } 1208 1209 --fCurSpecifier; 1210 return B_OK; 1211 } 1212 //------------------------------------------------------------------------------ 1213 // return fBody->AddData<TYPE>(name, val, TYPESPEC); 1214 // return fBody->FindData<TYPE>(name, index, val, TYPESPEC); 1215 // return fBody->ReplaceData<TYPE>(name, index, val, TYPESPEC); 1216 // return fBody->HasData(name, TYPESPEC, n); 1217 1218 #define DEFINE_FUNCTIONS(TYPE, fnName, TYPESPEC) \ 1219 status_t BMessage::Add ## fnName(const char* name, TYPE val) \ 1220 { return AddData(name, TYPESPEC, &val, sizeof(TYPE)); } \ 1221 status_t BMessage::Find ## fnName(const char* name, TYPE* p) const \ 1222 { return Find ## fnName(name, 0, p); } \ 1223 status_t BMessage::Find ## fnName(const char* name, int32 index, TYPE* p) const \ 1224 { \ 1225 void* ptr = NULL; ssize_t bytes = 0; status_t err = B_OK;\ 1226 *p = TYPE(); \ 1227 err = FindData(name, TYPESPEC, index, (const void**)&ptr, &bytes); \ 1228 if (err == B_OK) \ 1229 memcpy(p, ptr, sizeof(TYPE)); \ 1230 return err; \ 1231 } \ 1232 status_t BMessage::Replace ## fnName(const char* name, TYPE val) \ 1233 { return Replace ## fnName(name, 0, val); } \ 1234 status_t BMessage::Replace ## fnName(const char *name, int32 index, TYPE val) \ 1235 { return ReplaceData(name, TYPESPEC, index, &val, sizeof(TYPE)); } \ 1236 bool BMessage::Has ## fnName(const char* name, int32 n) const \ 1237 { return fBody->HasData(name, TYPESPEC, n); } 1238 1239 DEFINE_FUNCTIONS(int8 , Int8 , B_INT8_TYPE) 1240 DEFINE_FUNCTIONS(int16 , Int16 , B_INT16_TYPE) 1241 DEFINE_FUNCTIONS(int32 , Int32 , B_INT32_TYPE) 1242 DEFINE_FUNCTIONS(int64 , Int64 , B_INT64_TYPE) 1243 DEFINE_FUNCTIONS(BPoint, Point , B_POINT_TYPE) 1244 DEFINE_FUNCTIONS(BRect , Rect , B_RECT_TYPE) 1245 DEFINE_FUNCTIONS(float , Float , B_FLOAT_TYPE) 1246 DEFINE_FUNCTIONS(double, Double, B_DOUBLE_TYPE) 1247 DEFINE_FUNCTIONS(bool , Bool , B_BOOL_TYPE) 1248 1249 #undef DEFINE_FUNCTIONS 1250 1251 1252 #define DEFINE_HAS_FUNCTION(fnName, TYPESPEC) \ 1253 bool BMessage::Has ## fnName(const char* name, int32 n) const \ 1254 { return HasData(name, TYPESPEC, n); } 1255 1256 DEFINE_HAS_FUNCTION(Message , B_MESSAGE_TYPE) 1257 DEFINE_HAS_FUNCTION(String , B_STRING_TYPE) 1258 DEFINE_HAS_FUNCTION(Pointer , B_POINTER_TYPE) 1259 DEFINE_HAS_FUNCTION(Messenger, B_MESSENGER_TYPE) 1260 DEFINE_HAS_FUNCTION(Ref , B_REF_TYPE) 1261 1262 #undef DEFINE_HAS_FUNCTION 1263 1264 #define DEFINE_LAZY_FIND_FUNCTION(TYPE, fnName) \ 1265 TYPE BMessage::Find ## fnName(const char* name, int32 n) const \ 1266 { \ 1267 TYPE i = 0; \ 1268 Find ## fnName(name, n, &i); \ 1269 return i; \ 1270 } 1271 1272 DEFINE_LAZY_FIND_FUNCTION(int8 , Int8) 1273 DEFINE_LAZY_FIND_FUNCTION(int16 , Int16) 1274 DEFINE_LAZY_FIND_FUNCTION(int32 , Int32) 1275 DEFINE_LAZY_FIND_FUNCTION(int64 , Int64) 1276 DEFINE_LAZY_FIND_FUNCTION(float , Float) 1277 DEFINE_LAZY_FIND_FUNCTION(double , Double) 1278 DEFINE_LAZY_FIND_FUNCTION(bool , Bool) 1279 DEFINE_LAZY_FIND_FUNCTION(const char* , String) 1280 1281 #undef DEFINE_LAZY_FIND_FUNCTION 1282 1283 //------------------------------------------------------------------------------ 1284 1285 1286 status_t 1287 BMessage::AddString(const char* name, const char* string) 1288 { 1289 return AddData(name, B_STRING_TYPE, string, strlen(string) + 1); 1290 } 1291 1292 1293 status_t 1294 BMessage::AddString(const char* name, const BString& string) 1295 { 1296 return AddData(name, B_STRING_TYPE, string.String(), string.Length() + 1); 1297 } 1298 1299 1300 status_t 1301 BMessage::AddPointer(const char* name, const void* pointer) 1302 { 1303 return AddData(name, B_POINTER_TYPE, &pointer, sizeof(pointer)); 1304 } 1305 1306 1307 status_t 1308 BMessage::AddMessenger(const char* name, BMessenger messenger) 1309 { 1310 return AddData(name, B_MESSENGER_TYPE, &messenger, sizeof(messenger)); 1311 } 1312 1313 1314 status_t 1315 BMessage::AddRef(const char* name, const entry_ref* ref) 1316 { 1317 char* buffer = new(nothrow) char[sizeof(entry_ref) + B_PATH_NAME_LENGTH]; 1318 if (buffer == NULL) 1319 return B_NO_MEMORY; 1320 1321 size_t size; 1322 status_t err = entry_ref_flatten(buffer, &size, ref); 1323 if (err >= B_OK) { 1324 BDataBuffer databuffer((void*)buffer, size); 1325 err = fBody->AddData<BDataBuffer>(name, databuffer, B_REF_TYPE); 1326 // ToDo: even if the code looks like it, test this for real 1327 // if AddData() fails here, the buffer is freed automatically 1328 // as part of the BDataBuffer destruction 1329 } else 1330 delete[] buffer; 1331 1332 return err; 1333 } 1334 1335 1336 status_t 1337 BMessage::AddMessage(const char* name, const BMessage* msg) 1338 { 1339 ssize_t size = msg->FlattenedSize(); 1340 char* buffer = new(nothrow) char[size]; 1341 if (buffer == NULL) 1342 return B_NO_MEMORY; 1343 1344 status_t err = msg->Flatten(buffer, size); 1345 if (err >= B_OK) { 1346 BDataBuffer dataBuffer((void*)buffer, size); 1347 err = fBody->AddData<BDataBuffer>(name, dataBuffer, B_MESSAGE_TYPE); 1348 // if AddData() fails here, the buffer is freed automatically 1349 // as part of the BDataBuffer destruction 1350 } else 1351 delete[] buffer; 1352 1353 return err; 1354 } 1355 1356 1357 status_t 1358 BMessage::AddFlat(const char* name, BFlattenable* object, int32 count) 1359 { 1360 ssize_t size = object->FlattenedSize(); 1361 char* buffer = new(nothrow) char[size]; 1362 if (buffer == NULL) 1363 return B_NO_MEMORY; 1364 1365 status_t err = object->Flatten((void*)buffer, size); 1366 if (err >= B_OK) { 1367 BDataBuffer dataBuffer((void*)buffer, size); 1368 err = fBody->AddData<BDataBuffer>(name, dataBuffer, object->TypeCode()); 1369 // if AddData() fails here, the buffer is freed automatically 1370 // as part of the BDataBuffer destruction 1371 } else 1372 delete[] buffer; 1373 1374 return err; 1375 } 1376 1377 1378 status_t 1379 BMessage::AddData(const char* name, type_code type, const void* data, 1380 ssize_t numBytes, bool is_fixed_size, int32 /*count*/) 1381 { 1382 /** @note 1383 Because we're using vectors for our item storage, the count param 1384 is no longer useful to us: dynamically adding more items is not 1385 really a performance issue, so pre-allocating space for objects 1386 gives us no real advantage. 1387 */ 1388 1389 // TODO: test 1390 // In particular, we want to see what happens if is_fixed_size == true and 1391 // the user attempts to add something bigger or smaller. We may need to 1392 // enforce the size thing. 1393 1394 BDataBuffer buffer((void*)data, numBytes, true); 1395 return fBody->AddData<BDataBuffer>(name, buffer, type); 1396 } 1397 1398 1399 status_t 1400 BMessage::RemoveData(const char* name, int32 index) 1401 { 1402 return fReadOnly ? B_ERROR : fBody->RemoveData(name, index); 1403 } 1404 1405 1406 status_t 1407 BMessage::RemoveName(const char* name) 1408 { 1409 return fReadOnly ? B_ERROR : fBody->RemoveName(name); 1410 } 1411 1412 1413 status_t 1414 BMessage::MakeEmpty() 1415 { 1416 return fReadOnly ? B_ERROR : fBody->MakeEmpty(); 1417 } 1418 1419 1420 status_t 1421 BMessage::FindString(const char* name, const char** string) const 1422 { 1423 return FindString(name, 0, string); 1424 } 1425 1426 1427 status_t 1428 BMessage::FindString(const char* name, int32 index, 1429 const char** string) const 1430 { 1431 ssize_t bytes; 1432 return FindData(name, B_STRING_TYPE, index, 1433 (const void**)string, &bytes); 1434 } 1435 1436 1437 status_t 1438 BMessage::FindString(const char* name, BString* string) const 1439 { 1440 return FindString(name, 0, string); 1441 } 1442 1443 1444 status_t 1445 BMessage::FindString(const char* name, int32 index, BString* string) const 1446 { 1447 const char* cstr; 1448 status_t err = FindString(name, index, &cstr); 1449 if (err < B_OK) 1450 return err; 1451 1452 *string = cstr; 1453 return B_OK; 1454 } 1455 1456 1457 status_t 1458 BMessage::FindPointer(const char* name, void** ptr) const 1459 { 1460 return FindPointer(name, 0, ptr); 1461 } 1462 1463 1464 status_t 1465 BMessage::FindPointer(const char* name, int32 index, void** ptr) const 1466 { 1467 void** data = NULL; 1468 ssize_t size = 0; 1469 status_t err = FindData(name, B_POINTER_TYPE, index, (const void**)&data, &size); 1470 if (err == B_OK) 1471 *ptr = *data; 1472 else 1473 *ptr = NULL; 1474 return err; 1475 } 1476 1477 1478 status_t 1479 BMessage::FindMessenger(const char* name, BMessenger* m) const 1480 { 1481 return FindMessenger(name, 0, m); 1482 } 1483 1484 1485 status_t 1486 BMessage::FindMessenger(const char* name, int32 index, BMessenger* m) const 1487 { 1488 void* data = NULL; 1489 ssize_t size = 0; 1490 status_t err = FindData(name, B_MESSENGER_TYPE, index, (const void **)&data, &size); 1491 if (err == B_OK) 1492 memcpy(m, data, sizeof(BMessenger)); 1493 else 1494 *m = BMessenger(); 1495 return err; 1496 } 1497 1498 1499 status_t 1500 BMessage::FindRef(const char* name, entry_ref* ref) const 1501 { 1502 return FindRef(name, 0, ref); 1503 } 1504 1505 1506 status_t 1507 BMessage::FindRef(const char* name, int32 index, entry_ref* ref) const 1508 { 1509 void* data = NULL; 1510 ssize_t size = 0; 1511 status_t err = FindData(name, B_REF_TYPE, index, (const void**)&data, &size); 1512 if (err == B_OK) 1513 err = entry_ref_unflatten(ref, (char*)data, size); 1514 else 1515 *ref = entry_ref(); 1516 return err; 1517 } 1518 1519 1520 status_t 1521 BMessage::FindMessage(const char* name, BMessage* msg) const 1522 { 1523 return FindMessage(name, 0, msg); 1524 } 1525 1526 1527 status_t 1528 BMessage::FindMessage(const char* name, int32 index, BMessage* msg) const 1529 { 1530 void* data = NULL; 1531 ssize_t size = 0; 1532 status_t err = FindData(name, B_MESSAGE_TYPE, index, (const void**)&data, &size); 1533 if (!err) 1534 err = msg->Unflatten((const char*)data); 1535 else 1536 *msg = BMessage(); 1537 return err; 1538 } 1539 1540 1541 status_t 1542 BMessage::FindFlat(const char* name, BFlattenable* obj) const 1543 { 1544 return FindFlat(name, 0, obj); 1545 } 1546 1547 1548 status_t 1549 BMessage::FindFlat(const char* name, int32 index, BFlattenable* obj) const 1550 { 1551 void* data = NULL; 1552 ssize_t numBytes = 0; 1553 status_t err = FindData(name, obj->TypeCode(), index, (const void**)&data, &numBytes); 1554 if (!err) 1555 err = obj->Unflatten(obj->TypeCode(), data, numBytes); 1556 return err; 1557 } 1558 1559 1560 status_t 1561 BMessage::FindData(const char* name, type_code type, const void** data, 1562 ssize_t* numBytes) const 1563 { 1564 return FindData(name, type, 0, data, numBytes); 1565 } 1566 1567 1568 status_t 1569 BMessage::FindData(const char* name, type_code type, int32 index, 1570 const void** data, ssize_t* numBytes) const 1571 { 1572 return fBody->FindData(name, type, index, data, numBytes); 1573 } 1574 1575 1576 status_t 1577 BMessage::ReplaceString(const char* name, const char* string) 1578 { 1579 return ReplaceString(name, 0, string); 1580 } 1581 1582 1583 status_t 1584 BMessage::ReplaceString(const char* name, int32 index, const char* string) 1585 { 1586 return ReplaceData(name, B_STRING_TYPE, index, string, strlen(string)+1); 1587 } 1588 1589 1590 status_t 1591 BMessage::ReplaceString(const char* name, const BString& string) 1592 { 1593 return ReplaceString(name, 0, string); 1594 } 1595 1596 1597 status_t 1598 BMessage::ReplaceString(const char* name, int32 index, const BString& string) 1599 { 1600 return ReplaceData(name, B_STRING_TYPE, index, string.String(), string.Length()+1); 1601 } 1602 1603 1604 status_t 1605 BMessage::ReplacePointer(const char* name, const void* ptr) 1606 { 1607 return ReplacePointer(name, 0, ptr); 1608 } 1609 1610 1611 status_t 1612 BMessage::ReplacePointer(const char* name, int32 index, const void* ptr) 1613 { 1614 return ReplaceData(name, B_POINTER_TYPE, index, &ptr, sizeof(ptr)); 1615 } 1616 1617 1618 status_t 1619 BMessage::ReplaceMessenger(const char* name, BMessenger messenger) 1620 { 1621 return ReplaceData(name, B_MESSENGER_TYPE, 0, &messenger, sizeof(BMessenger)); 1622 } 1623 1624 1625 status_t 1626 BMessage::ReplaceMessenger(const char* name, int32 index, BMessenger messenger) 1627 { 1628 return ReplaceData(name, B_MESSENGER_TYPE, index, &messenger, sizeof(BMessenger)); 1629 } 1630 1631 1632 status_t 1633 BMessage::ReplaceRef(const char* name, const entry_ref* ref) 1634 { 1635 return ReplaceRef(name, 0, ref); 1636 } 1637 1638 1639 status_t 1640 BMessage::ReplaceRef(const char* name, int32 index, const entry_ref* ref) 1641 { 1642 char* buffer = new(nothrow) char[sizeof (entry_ref) + B_PATH_NAME_LENGTH]; 1643 if (buffer == NULL) 1644 return B_NO_MEMORY; 1645 1646 size_t size; 1647 status_t err = entry_ref_flatten(buffer, &size, ref); 1648 if (err >= B_OK) { 1649 BDataBuffer dataBuffer((void*)buffer, size); 1650 err = fBody->ReplaceData<BDataBuffer>(name, index, dataBuffer, B_REF_TYPE); 1651 } else 1652 delete[] buffer; 1653 1654 return err; 1655 } 1656 1657 1658 status_t 1659 BMessage::ReplaceMessage(const char* name, const BMessage* msg) 1660 { 1661 return ReplaceMessage(name, 0, msg); 1662 } 1663 1664 1665 status_t 1666 BMessage::ReplaceMessage(const char* name, int32 index, const BMessage* msg) 1667 { 1668 ssize_t size = msg->FlattenedSize(); 1669 char* buffer = new(nothrow) char[size]; 1670 if (buffer == NULL) 1671 return B_NO_MEMORY; 1672 1673 status_t err = msg->Flatten(buffer, size); 1674 if (err >= B_OK) { 1675 BDataBuffer dataBuffer((void*)buffer, size); 1676 err = fBody->ReplaceData<BDataBuffer>(name, index, dataBuffer, B_MESSAGE_TYPE); 1677 } else 1678 delete[] buffer; 1679 1680 return err; 1681 } 1682 1683 1684 status_t 1685 BMessage::ReplaceFlat(const char* name, BFlattenable* object) 1686 { 1687 return ReplaceFlat(name, 0, object); 1688 } 1689 1690 1691 status_t 1692 BMessage::ReplaceFlat(const char* name, int32 index, BFlattenable* object) 1693 { 1694 ssize_t size = object->FlattenedSize(); 1695 char* buffer = new(nothrow) char[size]; 1696 if (buffer == NULL) 1697 return B_NO_MEMORY; 1698 1699 status_t err = object->Flatten(buffer, size); 1700 if (err >= B_OK) { 1701 BDataBuffer dataBuffer((void*)buffer, size); 1702 err = fBody->ReplaceData<BDataBuffer>(name, index, dataBuffer, object->TypeCode()); 1703 } else 1704 delete[] buffer; 1705 1706 return err; 1707 } 1708 1709 1710 status_t 1711 BMessage::ReplaceData(const char* name, type_code type, 1712 const void* data, ssize_t data_size) 1713 { 1714 return ReplaceData(name, type, 0, data, data_size); 1715 } 1716 1717 1718 status_t 1719 BMessage::ReplaceData(const char* name, type_code type, int32 index, 1720 const void* data, ssize_t data_size) 1721 { 1722 BDataBuffer databuffer((void*)data, data_size, true); 1723 return fBody->ReplaceData<BDataBuffer>(name, index, databuffer, type); 1724 } 1725 1726 1727 void* 1728 BMessage::operator new(size_t size) 1729 { 1730 if (!sMsgCache) 1731 sMsgCache = new BBlockCache(10, size, B_OBJECT_CACHE); 1732 1733 return sMsgCache->Get(size); 1734 } 1735 1736 1737 void* 1738 BMessage::operator new(size_t, void* p) 1739 { 1740 return p; 1741 } 1742 1743 1744 void 1745 BMessage::operator delete(void* ptr, size_t size) 1746 { 1747 sMsgCache->Save(ptr, size); 1748 } 1749 1750 1751 bool 1752 BMessage::HasFlat(const char* name, const BFlattenable* flat) const 1753 { 1754 return HasFlat(name, 0, flat); 1755 } 1756 1757 1758 bool 1759 BMessage::HasFlat(const char* name, int32 n, const BFlattenable* flat) const 1760 { 1761 return fBody->HasData(name, flat->TypeCode(), n); 1762 } 1763 1764 1765 bool 1766 BMessage::HasData(const char* name, type_code t, int32 n) const 1767 { 1768 return fBody->HasData(name, t, n); 1769 } 1770 1771 1772 BRect 1773 BMessage::FindRect(const char* name, int32 n) const 1774 { 1775 BRect r(0, 0, -1, -1); 1776 FindRect(name, n, &r); 1777 return r; 1778 } 1779 1780 1781 BPoint 1782 BMessage::FindPoint(const char* name, int32 n) const 1783 { 1784 BPoint p(0, 0); 1785 FindPoint(name, n, &p); 1786 return p; 1787 } 1788 1789 1790 status_t 1791 BMessage::real_flatten(char* result, ssize_t size) const 1792 { 1793 BMemoryIO stream((void*)result, size); 1794 return real_flatten(&stream); 1795 } 1796 1797 1798 status_t 1799 BMessage::real_flatten(BDataIO* stream) const 1800 { 1801 Header header(*this); 1802 1803 status_t err = header.WriteTo(*stream); 1804 1805 if (!err) 1806 err = fBody->Flatten(stream); 1807 1808 return err; 1809 } 1810 1811 1812 char* 1813 BMessage::stack_flatten(char* stack_ptr, ssize_t stack_size, 1814 bool /*incl_reply*/, ssize_t* size) const 1815 { 1816 const ssize_t calcd_size = calc_hdr_size(0) + fBody->FlattenedSize(); 1817 char* new_ptr = NULL; 1818 if (calcd_size > stack_size) { 1819 stack_ptr = new char[calcd_size]; 1820 new_ptr = stack_ptr; 1821 } 1822 1823 real_flatten(stack_ptr, calcd_size); 1824 if (size) 1825 *size = calcd_size; 1826 1827 return new_ptr; 1828 } 1829 1830 1831 status_t 1832 BMessage::_UnflattenKMessage(const char *buffer) 1833 { 1834 // init a real KMessage 1835 KMessage message; 1836 status_t error = message.SetTo(buffer, ((KMessage::Header*)buffer)->size); 1837 if (error != B_OK) 1838 return error; 1839 1840 // let convert_message() do the real job 1841 return convert_message(&message, this); 1842 } 1843 1844 1845 ssize_t 1846 BMessage::calc_hdr_size(uchar flags) const 1847 { 1848 ssize_t size = min_hdr_size(); 1849 1850 if (fTarget != B_NULL_TOKEN) 1851 size += sizeof (fTarget); 1852 1853 if (fReplyTo.port >= 0 1854 && fReplyTo.target != B_NULL_TOKEN 1855 && fReplyTo.team >= 0) { 1856 size += sizeof (fReplyTo.port); 1857 size += sizeof (fReplyTo.target); 1858 size += sizeof (fReplyTo.team); 1859 1860 size += 4; // For the "big" flags 1861 } 1862 1863 return size; 1864 } 1865 1866 1867 status_t 1868 BMessage::_send_(port_id port, int32 token, bigtime_t timeout, 1869 bool reply_required, BMessenger& reply_to) const 1870 { 1871 PRINT(("BMessage::_send_(port: %ld, token: %ld): " 1872 "what: %lx (%.4s)\n", port, token, what, (char*)&what)); 1873 1874 bool oldPreferred = fPreferred; 1875 int32 oldTarget = fTarget; 1876 reply_to_info oldReplyTo = fReplyTo; 1877 1878 if (!reply_to.IsValid()) { 1879 BMessenger::Private(reply_to).SetTo(fReplyTo.team, 1880 fReplyTo.port, fReplyTo.target); 1881 if (!reply_to.IsValid()) 1882 reply_to = be_app_messenger; 1883 } 1884 1885 BMessage* self = const_cast<BMessage*>(this); 1886 BMessenger::Private replyToPrivate(reply_to); 1887 self->fPreferred = token == B_PREFERRED_TOKEN; 1888 self->fTarget = token; 1889 self->fReplyRequired = reply_required; 1890 self->fReplyTo.team = replyToPrivate.Team(); 1891 self->fReplyTo.port = replyToPrivate.Port(); 1892 self->fReplyTo.target = (replyToPrivate.IsPreferredTarget() 1893 ? B_PREFERRED_TOKEN : replyToPrivate.Token()); 1894 self->fReplyTo.preferred = replyToPrivate.IsPreferredTarget(); 1895 1896 char tmp[0x800]; 1897 ssize_t size; 1898 char* p = stack_flatten(tmp, sizeof(tmp), true /* include reply */, &size); 1899 char* pMem = p ? p : tmp; 1900 status_t err; 1901 do { 1902 err = write_port_etc(port, 'pjpp', pMem, size, B_RELATIVE_TIMEOUT, timeout); 1903 } while (err == B_INTERRUPTED); 1904 if (p) 1905 delete[] p; 1906 1907 self->fPreferred = oldPreferred; 1908 self->fTarget = oldTarget; 1909 self->fReplyRequired = false; // To this copy, no reply is required. 1910 // Only relevant when forwarding anyway. 1911 self->fReplyTo = oldReplyTo; 1912 1913 PRINT(("BMessage::_send_() done: %lx\n", err)); 1914 return err; 1915 } 1916 1917 1918 status_t 1919 BMessage::send_message(port_id port, team_id port_owner, int32 token, 1920 BMessage* reply, bigtime_t send_timeout, 1921 bigtime_t reply_timeout) const 1922 { 1923 const int32 cached_reply_port = sGetCachedReplyPort(); 1924 port_id reply_port; 1925 status_t err; 1926 if (cached_reply_port == -1) { 1927 // All the cached reply ports are in use; create a new one 1928 reply_port = create_port(1 /* for one message */, "tmp_reply_port"); 1929 if (reply_port < 0) 1930 return reply_port; 1931 } else { 1932 assert(cached_reply_port < sNumReplyPorts); 1933 reply_port = sReplyPorts[cached_reply_port]; 1934 } 1935 1936 team_id team = B_BAD_TEAM_ID; 1937 if (be_app != NULL) 1938 team = be_app->Team(); 1939 else { 1940 port_info pi; 1941 err = get_port_info(reply_port, &pi); 1942 if (err) 1943 goto error; 1944 1945 team = pi.team; 1946 } 1947 1948 err = set_port_owner(reply_port, port_owner); 1949 if (err) 1950 goto error; 1951 1952 { 1953 BMessenger messenger; 1954 BMessenger::Private(messenger).SetTo(team, reply_port, 1955 B_PREFERRED_TOKEN); 1956 err = _send_(port, token, send_timeout, true, messenger); 1957 } 1958 if (err) 1959 goto error; 1960 1961 int32 code; 1962 err = handle_reply(reply_port, &code, reply_timeout, reply); 1963 if (err && cached_reply_port >= 0) { 1964 delete_port(reply_port); 1965 sReplyPorts[cached_reply_port] = create_port(1, "tmp_rport"); 1966 } 1967 1968 error: 1969 if (cached_reply_port >= 0) { 1970 // Reclaim ownership of cached port 1971 set_port_owner(reply_port, team); 1972 // Flag as available 1973 atomic_add(&sReplyPortInUse[cached_reply_port], -1); 1974 return err; 1975 } 1976 delete_port(reply_port); 1977 return err; 1978 } 1979 1980 1981 // Note, that in case of a flattened BMessage setting the target token will 1982 // change the header size, if no token was set when the message was flattened. 1983 // Hence the message would need to unflattened and flattened again before it 1984 // can be sent. 1985 status_t 1986 BMessage::_SendFlattenedMessage(void *data, int32 size, port_id port, 1987 int32 token, bigtime_t timeout) 1988 { 1989 if (!data) 1990 return B_BAD_VALUE; 1991 1992 uint32 magic = *(uint32*)data; 1993 1994 // prepare flattened fields 1995 if (((KMessage::Header*)data)->magic == KMessage::kMessageHeaderMagic) { 1996 // a KMessage 1997 KMessage::Header *header = (KMessage::Header*)data; 1998 header->targetToken = token; 1999 } else if (magic == kMessageMagic || magic == kMessageMagicSwapped) { 2000 // get the header 2001 BMemoryIO stream(data, size); 2002 2003 stream.Read(&magic, sizeof(uint32)); 2004 // "discard" the magic (we already know it anyway) 2005 2006 Header header; 2007 status_t error = header.SetMagic(magic); 2008 if (error != B_OK) 2009 return error; 2010 2011 error = header.ReadFrom(stream); 2012 if (error != B_OK) 2013 return error; 2014 2015 if (!header.HasTarget()) { 2016 // fallback implementation -- the header size would change by 2017 // setting the token 2018 2019 // unflatten the message 2020 BMessage message; 2021 error = message.Unflatten((const char*)data); 2022 if (error != B_OK) 2023 return error; 2024 2025 // send the message 2026 BMessenger messenger; 2027 return message._send_(port, token, timeout, false, 2028 messenger); 2029 } 2030 2031 // set the target token and replace the header 2032 header.SetTarget(token); 2033 stream.Seek(0LL, SEEK_SET); 2034 error = header.WriteTo(stream); 2035 if (error != B_OK) 2036 return error; 2037 } else { 2038 return B_NOT_A_MESSAGE; 2039 } 2040 2041 // send the message 2042 status_t error; 2043 do { 2044 error = write_port_etc(port, 'pjpp', data, size, B_RELATIVE_TIMEOUT, 2045 timeout); 2046 } while (error == B_INTERRUPTED); 2047 2048 return error; 2049 } 2050 2051 2052 void 2053 BMessage::_StaticCacheCleanup() 2054 { 2055 delete sMsgCache; 2056 sMsgCache = NULL; 2057 } 2058 2059 2060 void 2061 BMessage::_StaticInit() 2062 { 2063 sReplyPorts[0] = create_port(1, "tmp_rport0"); 2064 sReplyPorts[1] = create_port(1, "tmp_rport1"); 2065 sReplyPorts[2] = create_port(1, "tmp_rport2"); 2066 2067 sReplyPortInUse[0] = 0; 2068 sReplyPortInUse[1] = 0; 2069 sReplyPortInUse[2] = 0; 2070 } 2071 2072 2073 void 2074 BMessage::_StaticCleanup() 2075 { 2076 delete_port(sReplyPorts[0]); 2077 sReplyPorts[0] = -1; 2078 delete_port(sReplyPorts[1]); 2079 sReplyPorts[1] = -1; 2080 delete_port(sReplyPorts[2]); 2081 sReplyPorts[2] = -1; 2082 } 2083 2084 2085 int32 2086 BMessage::sGetCachedReplyPort() 2087 { 2088 int index = -1; 2089 for (int32 i = 0; i < sNumReplyPorts; i++) 2090 { 2091 int32 old = atomic_add(&(sReplyPortInUse[i]), 1); 2092 if (old == 0) 2093 { 2094 // This entry is free 2095 index = i; 2096 break; 2097 } 2098 else 2099 { 2100 // This entry is being used. 2101 atomic_add(&(sReplyPortInUse[i]), -1); 2102 } 2103 } 2104 2105 return index; 2106 } 2107 2108 2109 static status_t 2110 handle_reply(port_id reply_port, int32* pCode, 2111 bigtime_t timeout, BMessage* reply) 2112 { 2113 PRINT(("handle_reply(port: %ld)\n", reply_port)); 2114 2115 status_t err; 2116 do { 2117 err = port_buffer_size_etc(reply_port, 8, timeout); 2118 } while (err == B_INTERRUPTED); 2119 2120 if (err < 0) { 2121 PRINT(("handle_reply() error 1: %lx\n", err)); 2122 return err; 2123 } 2124 2125 // The API lied. It really isn't an error code, but the message size... 2126 char* pAllocd = NULL; 2127 char* pMem = NULL; 2128 char tmp[0x800]; 2129 if (err < 0x800) 2130 pMem = tmp; 2131 else { 2132 pAllocd = new char[err]; 2133 pMem = pAllocd; 2134 } 2135 2136 do { 2137 err = read_port(reply_port, pCode, pMem, err); 2138 } while (err == B_INTERRUPTED); 2139 2140 if (err < 0) { 2141 PRINT(("handle_reply() error 2: %lx\n", err)); 2142 return err; 2143 } 2144 2145 if (*pCode == 'PUSH') { 2146 PRINT(("handle_reply() error 3: %x\n", B_ERROR)); 2147 return B_ERROR; 2148 } 2149 if (*pCode != 'pjpp') { 2150 PRINT(("handle_reply() error 4: port message code not 'pjpp' but " 2151 "'%lx'\n", *pCode)); 2152 return B_ERROR; 2153 } 2154 2155 err = reply->Unflatten(pMem); 2156 2157 // There seems to be a bug in the original Be implementation. 2158 // It never free'd pAllocd ! 2159 if (pAllocd) 2160 delete[] pAllocd; 2161 2162 PRINT(("handle_reply() done: %lx\n", err)); 2163 return err; 2164 } 2165 2166 2167 // convert_message 2168 static status_t 2169 convert_message(const KMessage *fromMessage, BMessage *toMessage) 2170 { 2171 if (!fromMessage || !toMessage) 2172 return B_BAD_VALUE; 2173 2174 // make empty and init what of the target message 2175 toMessage->MakeEmpty(); 2176 toMessage->what = fromMessage->What(); 2177 2178 // iterate through the fields and import them in the target message 2179 KMessageField field; 2180 while (fromMessage->GetNextField(&field) == B_OK) { 2181 int32 elementCount = field.CountElements(); 2182 if (elementCount > 0) { 2183 for (int32 i = 0; i < elementCount; i++) { 2184 int32 size; 2185 const void *data = field.ElementAt(i, &size); 2186 status_t error; 2187 if (field.TypeCode() == B_MESSAGE_TYPE) { 2188 // message type: if it's a KMessage, convert it 2189 KMessage message; 2190 if (message.SetTo(data, size) == B_OK) { 2191 BMessage bMessage; 2192 error = convert_message(&message, &bMessage); 2193 if (error != B_OK) 2194 return error; 2195 error = toMessage->AddMessage(field.Name(), &bMessage); 2196 } else { 2197 // just add it 2198 error = toMessage->AddData(field.Name(), 2199 field.TypeCode(), data, size, 2200 field.HasFixedElementSize(), 1); 2201 } 2202 } else { 2203 error = toMessage->AddData(field.Name(), field.TypeCode(), 2204 data, size, field.HasFixedElementSize(), 1); 2205 } 2206 2207 if (error != B_OK) 2208 return error; 2209 } 2210 } 2211 } 2212 return B_OK; 2213 } 2214 2215 2216 static ssize_t 2217 min_hdr_size() 2218 { 2219 ssize_t size = 0; 2220 2221 size += 4; // version 2222 size += 4; // checksum 2223 size += 4; // flattened size 2224 size += 4; // 'what' 2225 size += 1; // flags 2226 2227 return size; 2228 } 2229 2230 #endif // USING_MESSAGE4 2231