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