1 /* 2 * Copyright 2005-2017 Haiku, Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Michael Lotz, mmlr@mlotz.ch 7 */ 8 9 10 #include <Message.h> 11 #include <MessageAdapter.h> 12 #include <MessagePrivate.h> 13 #include <MessageUtils.h> 14 15 #include <DirectMessageTarget.h> 16 #include <MessengerPrivate.h> 17 #include <TokenSpace.h> 18 #include <util/KMessage.h> 19 20 #include <Alignment.h> 21 #include <Application.h> 22 #include <AppMisc.h> 23 #include <BlockCache.h> 24 #include <GraphicsDefs.h> 25 #include <MessageQueue.h> 26 #include <Messenger.h> 27 #include <Path.h> 28 #include <Point.h> 29 #include <String.h> 30 #include <StringList.h> 31 32 #include <assert.h> 33 #include <ctype.h> 34 #include <stdio.h> 35 #include <stdlib.h> 36 #include <string.h> 37 38 #include "tracing_config.h" 39 // kernel tracing configuration 40 41 //#define VERBOSE_DEBUG_OUTPUT 42 #ifdef VERBOSE_DEBUG_OUTPUT 43 #define DEBUG_FUNCTION_ENTER \ 44 debug_printf("msg thread: %ld; this: %p; header: %p; fields: %p;" \ 45 " data: %p; what: 0x%08lx '%.4s'; line: %d; func: %s\n", \ 46 find_thread(NULL), this, fHeader, fFields, fData, what, (char*)&what, \ 47 __LINE__, __PRETTY_FUNCTION__); 48 49 #define DEBUG_FUNCTION_ENTER2 \ 50 debug_printf("msg thread: %ld; line: %d: func: %s\n", find_thread(NULL), \ 51 __LINE__, __PRETTY_FUNCTION__); 52 #else 53 #define DEBUG_FUNCTION_ENTER /* nothing */ 54 #define DEBUG_FUNCTION_ENTER2 /* nothing */ 55 #endif 56 57 #if BMESSAGE_TRACING 58 # define KTRACE(format...) ktrace_printf(format) 59 #else 60 # define KTRACE(format...) ; 61 #endif 62 63 64 const char* B_SPECIFIER_ENTRY = "specifiers"; 65 const char* B_PROPERTY_ENTRY = "property"; 66 const char* B_PROPERTY_NAME_ENTRY = "name"; 67 68 69 static status_t handle_reply(port_id replyPort, int32* pCode, 70 bigtime_t timeout, BMessage* reply); 71 72 73 extern "C" { 74 // private os function to set the owning team of an area 75 status_t _kern_transfer_area(area_id area, void** _address, 76 uint32 addressSpec, team_id target); 77 } 78 79 80 BBlockCache* BMessage::sMsgCache = NULL; 81 port_id BMessage::sReplyPorts[sNumReplyPorts]; 82 int32 BMessage::sReplyPortInUse[sNumReplyPorts]; 83 84 85 template<typename Type> 86 static void 87 print_to_stream_type(uint8* pointer) 88 { 89 Type* item = (Type*)pointer; 90 item->PrintToStream(); 91 } 92 93 94 template<typename Type> 95 static void 96 print_type(const char* format, uint8* pointer) 97 { 98 Type* item = (Type*)pointer; 99 printf(format,* item,* item); 100 } 101 102 103 template<typename Type> 104 static void 105 print_type3(const char* format, uint8* pointer) 106 { 107 Type* item = (Type*)pointer; 108 printf(format, *item, *item, *item); 109 } 110 111 112 static status_t 113 handle_reply(port_id replyPort, int32* _code, bigtime_t timeout, 114 BMessage* reply) 115 { 116 DEBUG_FUNCTION_ENTER2; 117 ssize_t size; 118 do { 119 size = port_buffer_size_etc(replyPort, B_RELATIVE_TIMEOUT, timeout); 120 } while (size == B_INTERRUPTED); 121 122 if (size < 0) 123 return size; 124 125 status_t result; 126 char* buffer = (char*)malloc(size); 127 if (buffer == NULL) 128 return B_NO_MEMORY; 129 130 do { 131 result = read_port(replyPort, _code, buffer, size); 132 } while (result == B_INTERRUPTED); 133 134 if (result < 0 || *_code != kPortMessageCode) { 135 free(buffer); 136 return result < 0 ? result : B_ERROR; 137 } 138 139 result = reply->Unflatten(buffer); 140 free(buffer); 141 return result; 142 } 143 144 145 // #pragma mark - 146 147 148 BMessage::BMessage() 149 { 150 DEBUG_FUNCTION_ENTER; 151 _InitCommon(true); 152 } 153 154 155 BMessage::BMessage(BMessage* other) 156 { 157 DEBUG_FUNCTION_ENTER; 158 _InitCommon(false); 159 *this = *other; 160 } 161 162 163 BMessage::BMessage(uint32 _what) 164 { 165 DEBUG_FUNCTION_ENTER; 166 if (_InitCommon(true)) 167 fHeader->what = _what; 168 what = _what; 169 } 170 171 172 BMessage::BMessage(const BMessage& other) 173 { 174 DEBUG_FUNCTION_ENTER; 175 _InitCommon(false); 176 *this = other; 177 } 178 179 180 BMessage::~BMessage() 181 { 182 DEBUG_FUNCTION_ENTER; 183 _Clear(); 184 } 185 186 187 BMessage& 188 BMessage::operator=(const BMessage& other) 189 { 190 DEBUG_FUNCTION_ENTER; 191 192 if (this == &other) 193 return *this; 194 195 _Clear(); 196 197 fHeader = (message_header*)malloc(sizeof(message_header)); 198 if (fHeader == NULL) 199 return *this; 200 201 if (other.fHeader == NULL) 202 return *this; 203 204 memcpy(fHeader, other.fHeader, sizeof(message_header)); 205 206 // Clear some header flags inherited from the original message that don't 207 // apply to the clone. 208 fHeader->flags &= ~(MESSAGE_FLAG_REPLY_REQUIRED | MESSAGE_FLAG_REPLY_DONE 209 | MESSAGE_FLAG_IS_REPLY | MESSAGE_FLAG_WAS_DELIVERED 210 | MESSAGE_FLAG_PASS_BY_AREA); 211 // Note, that BeOS R5 seems to keep the reply info. 212 213 if (fHeader->field_count > 0) { 214 size_t fieldsSize = fHeader->field_count * sizeof(field_header); 215 if (other.fFields != NULL) 216 fFields = (field_header*)malloc(fieldsSize); 217 218 if (fFields == NULL) { 219 fHeader->field_count = 0; 220 fHeader->data_size = 0; 221 } else if (other.fFields != NULL) 222 memcpy(fFields, other.fFields, fieldsSize); 223 } 224 225 if (fHeader->data_size > 0) { 226 if (other.fData != NULL) 227 fData = (uint8*)malloc(fHeader->data_size); 228 229 if (fData == NULL) { 230 fHeader->field_count = 0; 231 free(fFields); 232 fFields = NULL; 233 } else if (other.fData != NULL) 234 memcpy(fData, other.fData, fHeader->data_size); 235 } 236 237 fHeader->what = what = other.what; 238 fHeader->message_area = -1; 239 fFieldsAvailable = 0; 240 fDataAvailable = 0; 241 242 return *this; 243 } 244 245 246 void* 247 BMessage::operator new(size_t size) 248 { 249 DEBUG_FUNCTION_ENTER2; 250 return sMsgCache->Get(size); 251 } 252 253 254 void* 255 BMessage::operator new(size_t size, const std::nothrow_t& noThrow) 256 { 257 DEBUG_FUNCTION_ENTER2; 258 return sMsgCache->Get(size); 259 } 260 261 262 void* 263 BMessage::operator new(size_t, void* pointer) 264 { 265 DEBUG_FUNCTION_ENTER2; 266 return pointer; 267 } 268 269 270 void 271 BMessage::operator delete(void* pointer, size_t size) 272 { 273 DEBUG_FUNCTION_ENTER2; 274 if (pointer == NULL) 275 return; 276 sMsgCache->Save(pointer, size); 277 } 278 279 280 bool 281 BMessage::HasSameData(const BMessage& other, bool ignoreFieldOrder, 282 bool deep) const 283 { 284 if (this == &other) 285 return true; 286 287 if (fHeader == NULL) 288 return other.fHeader == NULL; 289 290 if (fHeader->field_count != other.fHeader->field_count) 291 return false; 292 293 for (uint32 i = 0; i < fHeader->field_count; i++) { 294 field_header* field = &fFields[i]; 295 field_header* otherField = NULL; 296 297 const char* name = (const char*)fData + field->offset; 298 if (ignoreFieldOrder) { 299 if (other._FindField(name, B_ANY_TYPE, &otherField) != B_OK) 300 return false; 301 } else { 302 otherField = &other.fFields[i]; 303 if (otherField->name_length != field->name_length) 304 return false; 305 306 const char* otherName = (const char*)other.fData 307 + otherField->offset; 308 if (strncmp(name, otherName, field->name_length) != 0) 309 return false; 310 } 311 312 if (otherField->type != field->type 313 || otherField->count != field->count) { 314 return false; 315 } 316 317 uint8* data = fData + field->offset + field->name_length; 318 uint8* otherData = other.fData + otherField->offset 319 + otherField->name_length; 320 321 bool needsMemCompare = true; 322 if (deep && field->type == B_MESSAGE_TYPE) { 323 BMessage message, otherMessage; 324 if (message.Unflatten((const char*)data) == B_OK 325 && otherMessage.Unflatten((const char*)otherData) == B_OK) { 326 if (!message.HasSameData(ignoreFieldOrder, deep)) 327 return false; 328 needsMemCompare = false; 329 } 330 } 331 332 if (needsMemCompare) { 333 if (otherField->data_size != field->data_size) 334 return false; 335 if (memcmp(data, otherData, field->data_size) != 0) 336 return false; 337 } 338 } 339 340 return true; 341 } 342 343 344 status_t 345 BMessage::_InitCommon(bool initHeader) 346 { 347 DEBUG_FUNCTION_ENTER; 348 what = 0; 349 350 fHeader = NULL; 351 fFields = NULL; 352 fData = NULL; 353 354 fFieldsAvailable = 0; 355 fDataAvailable = 0; 356 357 fOriginal = NULL; 358 fQueueLink = NULL; 359 360 fArchivingPointer = NULL; 361 362 if (initHeader) 363 return _InitHeader(); 364 365 return B_OK; 366 } 367 368 369 status_t 370 BMessage::_InitHeader() 371 { 372 DEBUG_FUNCTION_ENTER; 373 if (fHeader == NULL) { 374 fHeader = (message_header*)malloc(sizeof(message_header)); 375 if (fHeader == NULL) 376 return B_NO_MEMORY; 377 } 378 379 memset(fHeader, 0, sizeof(message_header) - sizeof(fHeader->hash_table)); 380 381 fHeader->format = MESSAGE_FORMAT_HAIKU; 382 fHeader->flags = MESSAGE_FLAG_VALID; 383 fHeader->what = what; 384 fHeader->current_specifier = -1; 385 fHeader->message_area = -1; 386 387 fHeader->target = B_NULL_TOKEN; 388 fHeader->reply_target = B_NULL_TOKEN; 389 fHeader->reply_port = -1; 390 fHeader->reply_team = -1; 391 392 // initializing the hash table to -1 because 0 is a valid index 393 fHeader->hash_table_size = MESSAGE_BODY_HASH_TABLE_SIZE; 394 memset(&fHeader->hash_table, 255, sizeof(fHeader->hash_table)); 395 return B_OK; 396 } 397 398 399 status_t 400 BMessage::_Clear() 401 { 402 DEBUG_FUNCTION_ENTER; 403 if (fHeader != NULL) { 404 // We're going to destroy all information of this message. If there's 405 // still someone waiting for a reply to this message, we have to send 406 // one now. 407 if (IsSourceWaiting()) 408 SendReply(B_NO_REPLY); 409 410 if (fHeader->message_area >= 0) 411 _Dereference(); 412 413 free(fHeader); 414 fHeader = NULL; 415 } 416 417 free(fFields); 418 fFields = NULL; 419 free(fData); 420 fData = NULL; 421 422 fArchivingPointer = NULL; 423 424 fFieldsAvailable = 0; 425 fDataAvailable = 0; 426 427 delete fOriginal; 428 fOriginal = NULL; 429 430 return B_OK; 431 } 432 433 434 status_t 435 BMessage::GetInfo(type_code typeRequested, int32 index, char** nameFound, 436 type_code* typeFound, int32* countFound) const 437 { 438 DEBUG_FUNCTION_ENTER; 439 if (fHeader == NULL) 440 return B_NO_INIT; 441 442 if (index < 0 || (uint32)index >= fHeader->field_count) 443 return B_BAD_INDEX; 444 445 if (typeRequested == B_ANY_TYPE) { 446 if (nameFound != NULL) 447 *nameFound = (char*)fData + fFields[index].offset; 448 if (typeFound != NULL) 449 *typeFound = fFields[index].type; 450 if (countFound != NULL) 451 *countFound = fFields[index].count; 452 return B_OK; 453 } 454 455 int32 counter = -1; 456 field_header* field = fFields; 457 for (uint32 i = 0; i < fHeader->field_count; i++, field++) { 458 if (field->type == typeRequested) 459 counter++; 460 461 if (counter == index) { 462 if (nameFound != NULL) 463 *nameFound = (char*)fData + field->offset; 464 if (typeFound != NULL) 465 *typeFound = field->type; 466 if (countFound != NULL) 467 *countFound = field->count; 468 return B_OK; 469 } 470 } 471 472 if (counter == -1) 473 return B_BAD_TYPE; 474 475 return B_BAD_INDEX; 476 } 477 478 479 status_t 480 BMessage::GetInfo(const char* name, type_code* typeFound, 481 int32* countFound) const 482 { 483 DEBUG_FUNCTION_ENTER; 484 if (countFound != NULL) 485 *countFound = 0; 486 487 field_header* field = NULL; 488 status_t result = _FindField(name, B_ANY_TYPE, &field); 489 if (result != B_OK) 490 return result; 491 492 if (typeFound != NULL) 493 *typeFound = field->type; 494 if (countFound != NULL) 495 *countFound = field->count; 496 497 return B_OK; 498 } 499 500 501 status_t 502 BMessage::GetInfo(const char* name, type_code* typeFound, bool* fixedSize) 503 const 504 { 505 DEBUG_FUNCTION_ENTER; 506 field_header* field = NULL; 507 status_t result = _FindField(name, B_ANY_TYPE, &field); 508 if (result != B_OK) 509 return result; 510 511 if (typeFound != NULL) 512 *typeFound = field->type; 513 if (fixedSize != NULL) 514 *fixedSize = (field->flags & FIELD_FLAG_FIXED_SIZE) != 0; 515 516 return B_OK; 517 } 518 519 520 status_t 521 BMessage::GetInfo(const char* name, type_code* typeFound, int32* countFound, 522 bool* fixedSize) const 523 { 524 DEBUG_FUNCTION_ENTER; 525 field_header* field = NULL; 526 status_t result = _FindField(name, B_ANY_TYPE, &field); 527 if (result != B_OK) 528 return result; 529 530 if (typeFound != NULL) 531 *typeFound = field->type; 532 if (countFound != NULL) 533 *countFound = field->count; 534 if (fixedSize != NULL) 535 *fixedSize = (field->flags & FIELD_FLAG_FIXED_SIZE) != 0; 536 537 return B_OK; 538 } 539 540 541 int32 542 BMessage::CountNames(type_code type) const 543 { 544 DEBUG_FUNCTION_ENTER; 545 if (fHeader == NULL) 546 return 0; 547 548 if (type == B_ANY_TYPE) 549 return fHeader->field_count; 550 551 int32 count = 0; 552 field_header* field = fFields; 553 for (uint32 i = 0; i < fHeader->field_count; i++, field++) { 554 if (field->type == type) 555 count++; 556 } 557 558 return count; 559 } 560 561 562 bool 563 BMessage::IsEmpty() const 564 { 565 DEBUG_FUNCTION_ENTER; 566 return fHeader == NULL || fHeader->field_count == 0; 567 } 568 569 570 bool 571 BMessage::IsSystem() const 572 { 573 DEBUG_FUNCTION_ENTER; 574 char a = char(what >> 24); 575 char b = char(what >> 16); 576 char c = char(what >> 8); 577 char d = char(what); 578 579 // The BeBook says: 580 // ... we've adopted a strict convention for assigning values to all 581 // Be-defined constants. The value assigned will always be formed by 582 // combining four characters into a multicharacter constant, with the 583 // characters limited to uppercase letters and the underbar 584 // Between that and what's in AppDefs.h, this algo seems like a safe bet: 585 if (a == '_' && isupper(b) && isupper(c) && isupper(d)) 586 return true; 587 588 return false; 589 } 590 591 592 bool 593 BMessage::IsReply() const 594 { 595 DEBUG_FUNCTION_ENTER; 596 return fHeader != NULL && (fHeader->flags & MESSAGE_FLAG_IS_REPLY) != 0; 597 } 598 599 600 void 601 BMessage::PrintToStream() const 602 { 603 _PrintToStream(""); 604 printf("}\n"); 605 } 606 607 608 void 609 BMessage::_PrintToStream(const char* indent) const 610 { 611 DEBUG_FUNCTION_ENTER; 612 613 int32 value = B_BENDIAN_TO_HOST_INT32(what); 614 printf("BMessage("); 615 if (isprint(*(char*)&value)) 616 printf("'%.4s'", (char*)&value); 617 else 618 printf("0x%" B_PRIx32, what); 619 printf(") {\n"); 620 621 if (fHeader == NULL || fFields == NULL || fData == NULL) 622 return; 623 624 field_header* field = fFields; 625 for (uint32 i = 0; i < fHeader->field_count; i++, field++) { 626 value = B_BENDIAN_TO_HOST_INT32(field->type); 627 ssize_t size = 0; 628 if ((field->flags & FIELD_FLAG_FIXED_SIZE) != 0 && field->count > 0) 629 size = field->data_size / field->count; 630 631 uint8* pointer = fData + field->offset + field->name_length; 632 for (uint32 j = 0; j < field->count; j++) { 633 if (field->count == 1) { 634 printf("%s %s = ", indent, 635 (char*)(fData + field->offset)); 636 } else { 637 printf("%s %s[%" B_PRIu32 "] = ", indent, 638 (char*)(fData + field->offset), j); 639 } 640 641 if ((field->flags & FIELD_FLAG_FIXED_SIZE) == 0) { 642 size = *(uint32*)pointer; 643 pointer += sizeof(uint32); 644 } 645 646 switch (field->type) { 647 case B_RECT_TYPE: 648 print_to_stream_type<BRect>(pointer); 649 break; 650 651 case B_POINT_TYPE: 652 print_to_stream_type<BPoint>(pointer); 653 break; 654 655 case B_STRING_TYPE: 656 printf("string(\"%.*s\", %ld bytes)\n", (int)size, 657 (char*)pointer, (long)size); 658 break; 659 660 case B_INT8_TYPE: 661 print_type3<int8>("int8(0x%hx or %d or '%c')\n", 662 pointer); 663 break; 664 665 case B_UINT8_TYPE: 666 print_type3<uint8>("uint8(0x%hx or %u or '%c')\n", 667 pointer); 668 break; 669 670 case B_INT16_TYPE: 671 print_type<int16>("int16(0x%x or %d)\n", pointer); 672 break; 673 674 case B_UINT16_TYPE: 675 print_type<uint16>("uint16(0x%x or %u)\n", pointer); 676 break; 677 678 case B_INT32_TYPE: 679 print_type<int32>("int32(0x%lx or %ld)\n", pointer); 680 break; 681 682 case B_UINT32_TYPE: 683 print_type<uint32>("uint32(0x%lx or %lu)\n", pointer); 684 break; 685 686 case B_INT64_TYPE: 687 print_type<int64>("int64(0x%Lx or %Ld)\n", pointer); 688 break; 689 690 case B_UINT64_TYPE: 691 print_type<uint64>("uint64(0x%Lx or %Ld)\n", pointer); 692 break; 693 694 case B_BOOL_TYPE: 695 printf("bool(%s)\n", *((bool*)pointer) != 0 696 ? "true" : "false"); 697 break; 698 699 case B_FLOAT_TYPE: 700 print_type<float>("float(%.4f)\n", pointer); 701 break; 702 703 case B_DOUBLE_TYPE: 704 print_type<double>("double(%.8f)\n", pointer); 705 break; 706 707 case B_REF_TYPE: 708 { 709 entry_ref ref; 710 BPrivate::entry_ref_unflatten(&ref, (char*)pointer, size); 711 712 printf("entry_ref(device=%d, directory=%" B_PRIdINO 713 ", name=\"%s\", ", (int)ref.device, ref.directory, 714 ref.name); 715 716 BPath path(&ref); 717 printf("path=\"%s\")\n", path.Path()); 718 break; 719 } 720 721 case B_NODE_REF_TYPE: 722 { 723 node_ref ref; 724 BPrivate::node_ref_unflatten(&ref, (char*)pointer, size); 725 726 printf("node_ref(device=%d, node=%" B_PRIdINO ", ", 727 (int)ref.device, ref.node); 728 break; 729 } 730 731 case B_MESSAGE_TYPE: 732 { 733 char buffer[1024]; 734 snprintf(buffer, sizeof(buffer), "%s ", indent); 735 736 BMessage message; 737 status_t result = message.Unflatten((const char*)pointer); 738 if (result != B_OK) { 739 printf("failed unflatten: %s\n", strerror(result)); 740 break; 741 } 742 743 message._PrintToStream(buffer); 744 printf("%s }\n", indent); 745 break; 746 } 747 748 case B_RGB_32_BIT_TYPE: 749 { 750 rgb_color* color = (rgb_color*)pointer; 751 printf("rgb_color(%u, %u, %u, %u)\n", color->red, 752 color->green, color->blue, color->alpha); 753 break; 754 } 755 756 default: 757 { 758 printf("(type = '%.4s')(size = %ld)\n", (char*)&value, 759 (long)size); 760 break; 761 } 762 } 763 764 pointer += size; 765 } 766 } 767 } 768 769 770 status_t 771 BMessage::Rename(const char* oldEntry, const char* newEntry) 772 { 773 DEBUG_FUNCTION_ENTER; 774 if (oldEntry == NULL || newEntry == NULL) 775 return B_BAD_VALUE; 776 777 if (fHeader == NULL) 778 return B_NO_INIT; 779 780 status_t result; 781 if (fHeader->message_area >= 0) { 782 result = _CopyForWrite(); 783 if (result != B_OK) 784 return result; 785 } 786 787 uint32 hash = _HashName(oldEntry) % fHeader->hash_table_size; 788 int32* nextField = &fHeader->hash_table[hash]; 789 790 while (*nextField >= 0) { 791 field_header* field = &fFields[*nextField]; 792 793 if (strncmp((const char*)(fData + field->offset), oldEntry, 794 field->name_length) == 0) { 795 // nextField points to the field for oldEntry, save it and unlink 796 int32 index = *nextField; 797 *nextField = field->next_field; 798 field->next_field = -1; 799 800 hash = _HashName(newEntry) % fHeader->hash_table_size; 801 nextField = &fHeader->hash_table[hash]; 802 while (*nextField >= 0) 803 nextField = &fFields[*nextField].next_field; 804 *nextField = index; 805 806 int32 newLength = strlen(newEntry) + 1; 807 result = _ResizeData(field->offset + 1, 808 newLength - field->name_length); 809 if (result != B_OK) 810 return result; 811 812 memcpy(fData + field->offset, newEntry, newLength); 813 field->name_length = newLength; 814 return B_OK; 815 } 816 817 nextField = &field->next_field; 818 } 819 820 return B_NAME_NOT_FOUND; 821 } 822 823 824 bool 825 BMessage::WasDelivered() const 826 { 827 DEBUG_FUNCTION_ENTER; 828 return fHeader != NULL 829 && (fHeader->flags & MESSAGE_FLAG_WAS_DELIVERED) != 0; 830 } 831 832 833 bool 834 BMessage::IsSourceWaiting() const 835 { 836 DEBUG_FUNCTION_ENTER; 837 return fHeader != NULL 838 && (fHeader->flags & MESSAGE_FLAG_REPLY_REQUIRED) != 0 839 && (fHeader->flags & MESSAGE_FLAG_REPLY_DONE) == 0; 840 } 841 842 843 bool 844 BMessage::IsSourceRemote() const 845 { 846 DEBUG_FUNCTION_ENTER; 847 return fHeader != NULL 848 && (fHeader->flags & MESSAGE_FLAG_WAS_DELIVERED) != 0 849 && fHeader->reply_team != BPrivate::current_team(); 850 } 851 852 853 BMessenger 854 BMessage::ReturnAddress() const 855 { 856 DEBUG_FUNCTION_ENTER; 857 if (fHeader == NULL || (fHeader->flags & MESSAGE_FLAG_WAS_DELIVERED) == 0) 858 return BMessenger(); 859 860 BMessenger messenger; 861 BMessenger::Private(messenger).SetTo(fHeader->reply_team, 862 fHeader->reply_port, fHeader->reply_target); 863 return messenger; 864 } 865 866 867 const BMessage* 868 BMessage::Previous() const 869 { 870 DEBUG_FUNCTION_ENTER; 871 /* ToDo: test if the "_previous_" field is used in R5 */ 872 if (fOriginal == NULL) { 873 fOriginal = new BMessage(); 874 875 if (FindMessage("_previous_", fOriginal) != B_OK) { 876 delete fOriginal; 877 fOriginal = NULL; 878 } 879 } 880 881 return fOriginal; 882 } 883 884 885 bool 886 BMessage::WasDropped() const 887 { 888 DEBUG_FUNCTION_ENTER; 889 return fHeader != NULL 890 && (fHeader->flags & MESSAGE_FLAG_WAS_DROPPED) != 0; 891 } 892 893 894 BPoint 895 BMessage::DropPoint(BPoint* offset) const 896 { 897 DEBUG_FUNCTION_ENTER; 898 if (offset != NULL) 899 *offset = FindPoint("_drop_offset_"); 900 901 return FindPoint("_drop_point_"); 902 } 903 904 905 status_t 906 BMessage::SendReply(uint32 command, BHandler* replyTo) 907 { 908 DEBUG_FUNCTION_ENTER; 909 BMessage message(command); 910 return SendReply(&message, replyTo); 911 } 912 913 914 status_t 915 BMessage::SendReply(BMessage* reply, BHandler* replyTo, bigtime_t timeout) 916 { 917 DEBUG_FUNCTION_ENTER; 918 BMessenger messenger(replyTo); 919 return SendReply(reply, messenger, timeout); 920 } 921 922 923 status_t 924 BMessage::SendReply(BMessage* reply, BMessenger replyTo, bigtime_t timeout) 925 { 926 DEBUG_FUNCTION_ENTER; 927 if (fHeader == NULL) 928 return B_NO_INIT; 929 930 BMessenger messenger; 931 BMessenger::Private messengerPrivate(messenger); 932 messengerPrivate.SetTo(fHeader->reply_team, fHeader->reply_port, 933 fHeader->reply_target); 934 if ((fHeader->flags & MESSAGE_FLAG_REPLY_AS_KMESSAGE) != 0) 935 reply->fHeader->flags |= MESSAGE_FLAG_REPLY_AS_KMESSAGE; 936 937 if ((fHeader->flags & MESSAGE_FLAG_REPLY_REQUIRED) != 0) { 938 if ((fHeader->flags & MESSAGE_FLAG_REPLY_DONE) != 0) 939 return B_DUPLICATE_REPLY; 940 941 fHeader->flags |= MESSAGE_FLAG_REPLY_DONE; 942 reply->fHeader->flags |= MESSAGE_FLAG_IS_REPLY; 943 status_t result = messenger.SendMessage(reply, replyTo, timeout); 944 reply->fHeader->flags &= ~MESSAGE_FLAG_IS_REPLY; 945 946 if (result != B_OK && set_port_owner(messengerPrivate.Port(), 947 messengerPrivate.Team()) == B_BAD_TEAM_ID) { 948 delete_port(messengerPrivate.Port()); 949 } 950 951 return result; 952 } 953 954 // no reply required 955 if ((fHeader->flags & MESSAGE_FLAG_WAS_DELIVERED) == 0) 956 return B_BAD_REPLY; 957 958 reply->AddMessage("_previous_", this); 959 reply->fHeader->flags |= MESSAGE_FLAG_IS_REPLY; 960 status_t result = messenger.SendMessage(reply, replyTo, timeout); 961 reply->fHeader->flags &= ~MESSAGE_FLAG_IS_REPLY; 962 reply->RemoveName("_previous_"); 963 return result; 964 } 965 966 967 status_t 968 BMessage::SendReply(uint32 command, BMessage* replyToReply) 969 { 970 DEBUG_FUNCTION_ENTER; 971 BMessage message(command); 972 return SendReply(&message, replyToReply); 973 } 974 975 976 status_t 977 BMessage::SendReply(BMessage* reply, BMessage* replyToReply, 978 bigtime_t sendTimeout, bigtime_t replyTimeout) 979 { 980 DEBUG_FUNCTION_ENTER; 981 if (fHeader == NULL) 982 return B_NO_INIT; 983 984 BMessenger messenger; 985 BMessenger::Private messengerPrivate(messenger); 986 messengerPrivate.SetTo(fHeader->reply_team, fHeader->reply_port, 987 fHeader->reply_target); 988 989 if ((fHeader->flags & MESSAGE_FLAG_REPLY_REQUIRED) != 0) { 990 if ((fHeader->flags & MESSAGE_FLAG_REPLY_DONE) != 0) 991 return B_DUPLICATE_REPLY; 992 993 fHeader->flags |= MESSAGE_FLAG_REPLY_DONE; 994 reply->fHeader->flags |= MESSAGE_FLAG_IS_REPLY; 995 status_t result = messenger.SendMessage(reply, replyToReply, 996 sendTimeout, replyTimeout); 997 reply->fHeader->flags &= ~MESSAGE_FLAG_IS_REPLY; 998 999 if (result != B_OK) { 1000 if (set_port_owner(messengerPrivate.Port(), 1001 messengerPrivate.Team()) == B_BAD_TEAM_ID) { 1002 delete_port(messengerPrivate.Port()); 1003 } 1004 } 1005 1006 return result; 1007 } 1008 1009 // no reply required 1010 if ((fHeader->flags & MESSAGE_FLAG_WAS_DELIVERED) == 0) 1011 return B_BAD_REPLY; 1012 1013 reply->AddMessage("_previous_", this); 1014 reply->fHeader->flags |= MESSAGE_FLAG_IS_REPLY 1015 | (fHeader->flags & MESSAGE_FLAG_REPLY_AS_KMESSAGE); 1016 status_t result = messenger.SendMessage(reply, replyToReply, sendTimeout, 1017 replyTimeout); 1018 reply->fHeader->flags &= ~MESSAGE_FLAG_IS_REPLY; 1019 reply->RemoveName("_previous_"); 1020 return result; 1021 } 1022 1023 1024 ssize_t 1025 BMessage::FlattenedSize() const 1026 { 1027 DEBUG_FUNCTION_ENTER; 1028 if (fHeader == NULL) 1029 return B_NO_INIT; 1030 1031 return sizeof(message_header) + fHeader->field_count * sizeof(field_header) 1032 + fHeader->data_size; 1033 } 1034 1035 1036 status_t 1037 BMessage::Flatten(char* buffer, ssize_t size) const 1038 { 1039 DEBUG_FUNCTION_ENTER; 1040 if (buffer == NULL || size < 0) 1041 return B_BAD_VALUE; 1042 1043 if (fHeader == NULL) 1044 return B_NO_INIT; 1045 1046 if (size < FlattenedSize()) 1047 return B_BUFFER_OVERFLOW; 1048 1049 /* we have to sync the what code as it is a public member */ 1050 fHeader->what = what; 1051 1052 memcpy(buffer, fHeader, sizeof(message_header)); 1053 buffer += sizeof(message_header); 1054 1055 size_t fieldsSize = fHeader->field_count * sizeof(field_header); 1056 memcpy(buffer, fFields, fieldsSize); 1057 buffer += fieldsSize; 1058 1059 memcpy(buffer, fData, fHeader->data_size); 1060 1061 return B_OK; 1062 } 1063 1064 1065 status_t 1066 BMessage::Flatten(BDataIO* stream, ssize_t* size) const 1067 { 1068 DEBUG_FUNCTION_ENTER; 1069 if (stream == NULL) 1070 return B_BAD_VALUE; 1071 1072 if (fHeader == NULL) 1073 return B_NO_INIT; 1074 1075 /* we have to sync the what code as it is a public member */ 1076 fHeader->what = what; 1077 1078 ssize_t result1 = stream->Write(fHeader, sizeof(message_header)); 1079 if (result1 != sizeof(message_header)) 1080 return result1 < 0 ? result1 : B_ERROR; 1081 1082 ssize_t result2 = 0; 1083 if (fHeader->field_count > 0) { 1084 ssize_t fieldsSize = fHeader->field_count * sizeof(field_header); 1085 result2 = stream->Write(fFields, fieldsSize); 1086 if (result2 != fieldsSize) 1087 return result2 < 0 ? result2 : B_ERROR; 1088 } 1089 1090 ssize_t result3 = 0; 1091 if (fHeader->data_size > 0) { 1092 result3 = stream->Write(fData, fHeader->data_size); 1093 if (result3 != (ssize_t)fHeader->data_size) 1094 return result3 < 0 ? result3 : B_ERROR; 1095 } 1096 1097 if (size) 1098 *size = result1 + result2 + result3; 1099 1100 return B_OK; 1101 } 1102 1103 1104 /* The concept of message sending by area: 1105 1106 The traditional way of sending a message is to send it by flattening it to 1107 a buffer, pushing it through a port, reading it into the outputbuffer and 1108 unflattening it from there (copying the data again). While this works ok 1109 for small messages it does not make any sense for larger ones and may even 1110 hit some port capacity limit. 1111 Often in the life of a BMessage, it will be sent to someone. Almost as 1112 often the one receiving the message will not need to change the message 1113 in any way, but uses it "read only" to get information from it. This means 1114 that all that copying is pretty pointless in the first place since we 1115 could simply pass the original buffers on. 1116 It's obviously not exactly as simple as this, since we cannot just use the 1117 memory of one application in another - but we can share areas with 1118 eachother. 1119 Therefore instead of flattening into a buffer, we copy the message data 1120 into an area, put this information into the message header and only push 1121 this through the port. The receiving looper then builds a BMessage from 1122 the header, that only references the data in the area (not copying it), 1123 allowing read only access to it. 1124 Only if write access is necessary the message will be copyed from the area 1125 to its own buffers (like in the unflatten step before). 1126 The double copying is reduced to a single copy in most cases and we safe 1127 the slower route of moving the data through a port. 1128 Additionally we save us the reference counting with the use of areas that 1129 are reference counted internally. So we don't have to worry about leaving 1130 an area behind or deleting one that is still in use. 1131 */ 1132 1133 status_t 1134 BMessage::_FlattenToArea(message_header** _header) const 1135 { 1136 DEBUG_FUNCTION_ENTER; 1137 if (fHeader == NULL) 1138 return B_NO_INIT; 1139 1140 message_header* header = (message_header*)malloc(sizeof(message_header)); 1141 if (header == NULL) 1142 return B_NO_MEMORY; 1143 1144 memcpy(header, fHeader, sizeof(message_header)); 1145 1146 header->what = what; 1147 header->message_area = -1; 1148 *_header = header; 1149 1150 if (header->field_count == 0 && header->data_size == 0) 1151 return B_OK; 1152 1153 char* address = NULL; 1154 size_t fieldsSize = header->field_count * sizeof(field_header); 1155 size_t size = fieldsSize + header->data_size; 1156 size = (size + B_PAGE_SIZE) & ~(B_PAGE_SIZE - 1); 1157 area_id area = create_area("BMessage data", (void**)&address, 1158 B_ANY_ADDRESS, size, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA); 1159 1160 if (area < 0) { 1161 free(header); 1162 *_header = NULL; 1163 return area; 1164 } 1165 1166 memcpy(address, fFields, fieldsSize); 1167 memcpy(address + fieldsSize, fData, fHeader->data_size); 1168 header->flags |= MESSAGE_FLAG_PASS_BY_AREA; 1169 header->message_area = area; 1170 return B_OK; 1171 } 1172 1173 1174 status_t 1175 BMessage::_Reference() 1176 { 1177 DEBUG_FUNCTION_ENTER; 1178 if (fHeader == NULL) 1179 return B_NO_INIT; 1180 1181 fHeader->flags &= ~MESSAGE_FLAG_PASS_BY_AREA; 1182 1183 /* if there is no data at all we don't need the area */ 1184 if (fHeader->field_count == 0 && fHeader->data_size == 0) 1185 return B_OK; 1186 1187 area_info areaInfo; 1188 status_t result = get_area_info(fHeader->message_area, &areaInfo); 1189 if (result != B_OK) 1190 return result; 1191 1192 if (areaInfo.team != BPrivate::current_team()) 1193 return B_BAD_VALUE; 1194 1195 set_area_protection(fHeader->message_area, B_READ_AREA); 1196 1197 uint8* address = (uint8*)areaInfo.address; 1198 1199 fFields = (field_header*)address; 1200 fData = address + fHeader->field_count * sizeof(field_header); 1201 return B_OK; 1202 } 1203 1204 1205 status_t 1206 BMessage::_Dereference() 1207 { 1208 DEBUG_FUNCTION_ENTER; 1209 if (fHeader == NULL) 1210 return B_NO_INIT; 1211 1212 delete_area(fHeader->message_area); 1213 fHeader->message_area = -1; 1214 fFields = NULL; 1215 fData = NULL; 1216 return B_OK; 1217 } 1218 1219 1220 status_t 1221 BMessage::_CopyForWrite() 1222 { 1223 DEBUG_FUNCTION_ENTER; 1224 if (fHeader == NULL) 1225 return B_NO_INIT; 1226 1227 field_header* newFields = NULL; 1228 uint8* newData = NULL; 1229 1230 if (fHeader->field_count > 0) { 1231 size_t fieldsSize = fHeader->field_count * sizeof(field_header); 1232 newFields = (field_header*)malloc(fieldsSize); 1233 if (newFields == NULL) 1234 return B_NO_MEMORY; 1235 1236 memcpy(newFields, fFields, fieldsSize); 1237 } 1238 1239 if (fHeader->data_size > 0) { 1240 newData = (uint8*)malloc(fHeader->data_size); 1241 if (newData == NULL) { 1242 free(newFields); 1243 return B_NO_MEMORY; 1244 } 1245 1246 memcpy(newData, fData, fHeader->data_size); 1247 } 1248 1249 _Dereference(); 1250 1251 fFieldsAvailable = 0; 1252 fDataAvailable = 0; 1253 1254 fFields = newFields; 1255 fData = newData; 1256 return B_OK; 1257 } 1258 1259 1260 status_t 1261 BMessage::_ValidateMessage() 1262 { 1263 DEBUG_FUNCTION_ENTER; 1264 if (fHeader == NULL) 1265 return B_NO_INIT; 1266 1267 if (fHeader->field_count == 0) 1268 return B_OK; 1269 1270 if (fFields == NULL) 1271 return B_NO_INIT; 1272 1273 for (uint32 i = 0; i < fHeader->field_count; i++) { 1274 field_header* field = &fFields[i]; 1275 if ((field->next_field >= 0 1276 && (uint32)field->next_field > fHeader->field_count) 1277 || (field->offset + field->name_length + field->data_size 1278 > fHeader->data_size)) { 1279 // the message is corrupt 1280 MakeEmpty(); 1281 return B_BAD_VALUE; 1282 } 1283 } 1284 1285 return B_OK; 1286 } 1287 1288 1289 status_t 1290 BMessage::Unflatten(const char* flatBuffer) 1291 { 1292 DEBUG_FUNCTION_ENTER; 1293 if (flatBuffer == NULL) 1294 return B_BAD_VALUE; 1295 1296 uint32 format = *(uint32*)flatBuffer; 1297 if (format != MESSAGE_FORMAT_HAIKU) 1298 return BPrivate::MessageAdapter::Unflatten(format, this, flatBuffer); 1299 1300 BMemoryIO io(flatBuffer, SSIZE_MAX); 1301 return Unflatten(&io); 1302 } 1303 1304 1305 status_t 1306 BMessage::Unflatten(BDataIO* stream) 1307 { 1308 DEBUG_FUNCTION_ENTER; 1309 if (stream == NULL) 1310 return B_BAD_VALUE; 1311 1312 uint32 format = 0; 1313 stream->Read(&format, sizeof(uint32)); 1314 if (format != MESSAGE_FORMAT_HAIKU) 1315 return BPrivate::MessageAdapter::Unflatten(format, this, stream); 1316 1317 // native message unflattening 1318 1319 _Clear(); 1320 1321 fHeader = (message_header*)malloc(sizeof(message_header)); 1322 if (fHeader == NULL) 1323 return B_NO_MEMORY; 1324 1325 fHeader->format = format; 1326 uint8* header = (uint8*)fHeader; 1327 ssize_t result = stream->Read(header + sizeof(uint32), 1328 sizeof(message_header) - sizeof(uint32)); 1329 if (result != sizeof(message_header) - sizeof(uint32) 1330 || (fHeader->flags & MESSAGE_FLAG_VALID) == 0) { 1331 _InitHeader(); 1332 return result < 0 ? result : B_BAD_VALUE; 1333 } 1334 1335 what = fHeader->what; 1336 1337 if ((fHeader->flags & MESSAGE_FLAG_PASS_BY_AREA) != 0 1338 && fHeader->message_area >= 0) { 1339 status_t result = _Reference(); 1340 if (result != B_OK) { 1341 _InitHeader(); 1342 return result; 1343 } 1344 } else { 1345 fHeader->message_area = -1; 1346 1347 if (fHeader->field_count > 0) { 1348 ssize_t fieldsSize = fHeader->field_count * sizeof(field_header); 1349 fFields = (field_header*)malloc(fieldsSize); 1350 if (fFields == NULL) { 1351 _InitHeader(); 1352 return B_NO_MEMORY; 1353 } 1354 1355 result = stream->Read(fFields, fieldsSize); 1356 if (result != fieldsSize) 1357 return result < 0 ? result : B_BAD_VALUE; 1358 } 1359 1360 if (fHeader->data_size > 0) { 1361 fData = (uint8*)malloc(fHeader->data_size); 1362 if (fData == NULL) { 1363 free(fFields); 1364 fFields = NULL; 1365 _InitHeader(); 1366 return B_NO_MEMORY; 1367 } 1368 1369 result = stream->Read(fData, fHeader->data_size); 1370 if (result != (ssize_t)fHeader->data_size) 1371 return result < 0 ? result : B_BAD_VALUE; 1372 } 1373 } 1374 1375 return _ValidateMessage(); 1376 } 1377 1378 1379 status_t 1380 BMessage::AddSpecifier(const char* property) 1381 { 1382 DEBUG_FUNCTION_ENTER; 1383 BMessage message(B_DIRECT_SPECIFIER); 1384 status_t result = message.AddString(B_PROPERTY_ENTRY, property); 1385 if (result != B_OK) 1386 return result; 1387 1388 return AddSpecifier(&message); 1389 } 1390 1391 1392 status_t 1393 BMessage::AddSpecifier(const char* property, int32 index) 1394 { 1395 DEBUG_FUNCTION_ENTER; 1396 BMessage message(B_INDEX_SPECIFIER); 1397 status_t result = message.AddString(B_PROPERTY_ENTRY, property); 1398 if (result != B_OK) 1399 return result; 1400 1401 result = message.AddInt32("index", index); 1402 if (result != B_OK) 1403 return result; 1404 1405 return AddSpecifier(&message); 1406 } 1407 1408 1409 status_t 1410 BMessage::AddSpecifier(const char* property, int32 index, int32 range) 1411 { 1412 DEBUG_FUNCTION_ENTER; 1413 if (range < 0) 1414 return B_BAD_VALUE; 1415 1416 BMessage message(B_RANGE_SPECIFIER); 1417 status_t result = message.AddString(B_PROPERTY_ENTRY, property); 1418 if (result != B_OK) 1419 return result; 1420 1421 result = message.AddInt32("index", index); 1422 if (result != B_OK) 1423 return result; 1424 1425 result = message.AddInt32("range", range); 1426 if (result != B_OK) 1427 return result; 1428 1429 return AddSpecifier(&message); 1430 } 1431 1432 1433 status_t 1434 BMessage::AddSpecifier(const char* property, const char* name) 1435 { 1436 DEBUG_FUNCTION_ENTER; 1437 BMessage message(B_NAME_SPECIFIER); 1438 status_t result = message.AddString(B_PROPERTY_ENTRY, property); 1439 if (result != B_OK) 1440 return result; 1441 1442 result = message.AddString(B_PROPERTY_NAME_ENTRY, name); 1443 if (result != B_OK) 1444 return result; 1445 1446 return AddSpecifier(&message); 1447 } 1448 1449 1450 status_t 1451 BMessage::AddSpecifier(const BMessage* specifier) 1452 { 1453 DEBUG_FUNCTION_ENTER; 1454 status_t result = AddMessage(B_SPECIFIER_ENTRY, specifier); 1455 if (result != B_OK) 1456 return result; 1457 1458 fHeader->current_specifier++; 1459 fHeader->flags |= MESSAGE_FLAG_HAS_SPECIFIERS; 1460 return B_OK; 1461 } 1462 1463 1464 status_t 1465 BMessage::SetCurrentSpecifier(int32 index) 1466 { 1467 DEBUG_FUNCTION_ENTER; 1468 if (index < 0) 1469 return B_BAD_INDEX; 1470 1471 type_code type; 1472 int32 count; 1473 status_t result = GetInfo(B_SPECIFIER_ENTRY, &type, &count); 1474 if (result != B_OK) 1475 return result; 1476 1477 if (index >= count) 1478 return B_BAD_INDEX; 1479 1480 fHeader->current_specifier = index; 1481 return B_OK; 1482 } 1483 1484 1485 status_t 1486 BMessage::GetCurrentSpecifier(int32* index, BMessage* specifier, int32* _what, 1487 const char** property) const 1488 { 1489 DEBUG_FUNCTION_ENTER; 1490 if (fHeader == NULL) 1491 return B_NO_INIT; 1492 1493 if (index != NULL) 1494 *index = fHeader->current_specifier; 1495 1496 if (fHeader->current_specifier < 0 1497 || (fHeader->flags & MESSAGE_FLAG_WAS_DELIVERED) == 0) 1498 return B_BAD_SCRIPT_SYNTAX; 1499 1500 if (specifier) { 1501 if (FindMessage(B_SPECIFIER_ENTRY, fHeader->current_specifier, 1502 specifier) != B_OK) 1503 return B_BAD_SCRIPT_SYNTAX; 1504 1505 if (_what != NULL) 1506 *_what = specifier->what; 1507 1508 if (property) { 1509 if (specifier->FindString(B_PROPERTY_ENTRY, property) != B_OK) 1510 return B_BAD_SCRIPT_SYNTAX; 1511 } 1512 } 1513 1514 return B_OK; 1515 } 1516 1517 1518 bool 1519 BMessage::HasSpecifiers() const 1520 { 1521 DEBUG_FUNCTION_ENTER; 1522 return fHeader != NULL 1523 && (fHeader->flags & MESSAGE_FLAG_HAS_SPECIFIERS) != 0; 1524 } 1525 1526 1527 status_t 1528 BMessage::PopSpecifier() 1529 { 1530 DEBUG_FUNCTION_ENTER; 1531 if (fHeader == NULL) 1532 return B_NO_INIT; 1533 1534 if (fHeader->current_specifier < 0 || 1535 (fHeader->flags & MESSAGE_FLAG_WAS_DELIVERED) == 0) 1536 return B_BAD_VALUE; 1537 1538 if (fHeader->current_specifier >= 0) 1539 fHeader->current_specifier--; 1540 1541 return B_OK; 1542 } 1543 1544 1545 void 1546 BMessage::_UpdateOffsets(uint32 offset, int32 change) 1547 { 1548 // Update the header to match the new position of the fields 1549 if (offset < fHeader->data_size) { 1550 field_header* field = fFields; 1551 for (uint32 i = 0; i < fHeader->field_count; i++, field++) { 1552 if (field->offset >= offset) 1553 field->offset += change; 1554 } 1555 } 1556 } 1557 1558 1559 status_t 1560 BMessage::_ResizeData(uint32 offset, int32 change) 1561 { 1562 if (change == 0) 1563 return B_OK; 1564 1565 /* optimize for the most usual case: appending data */ 1566 1567 if (change > 0) { 1568 // We need to make the field bigger 1569 // check if there is enough free space allocated 1570 if (fDataAvailable >= (uint32)change) { 1571 // In this case, we just need to move the data after the growing 1572 // field to get the space at the right place 1573 if (offset < fHeader->data_size) { 1574 memmove(fData + offset + change, fData + offset, 1575 fHeader->data_size - offset); 1576 } 1577 1578 _UpdateOffsets(offset, change); 1579 1580 fDataAvailable -= change; 1581 fHeader->data_size += change; 1582 return B_OK; 1583 } 1584 1585 // We need to grow the buffer. We try to optimize reallocations by 1586 // preallocating space for more fields. 1587 size_t size = fHeader->data_size * 2; 1588 size = min_c(size, fHeader->data_size + MAX_DATA_PREALLOCATION); 1589 size = max_c(size, fHeader->data_size + change); 1590 1591 uint8* newData = (uint8*)realloc(fData, size); 1592 if (size > 0 && newData == NULL) 1593 return B_NO_MEMORY; 1594 1595 fData = newData; 1596 if (offset < fHeader->data_size) { 1597 memmove(fData + offset + change, fData + offset, 1598 fHeader->data_size - offset); 1599 } 1600 1601 fHeader->data_size += change; 1602 fDataAvailable = size - fHeader->data_size; 1603 } else { 1604 ssize_t length = fHeader->data_size - offset + change; 1605 if (length > 0) 1606 memmove(fData + offset, fData + offset - change, length); 1607 1608 // change is negative 1609 fHeader->data_size += change; 1610 fDataAvailable -= change; 1611 1612 if (fDataAvailable > MAX_DATA_PREALLOCATION) { 1613 ssize_t available = MAX_DATA_PREALLOCATION / 2; 1614 ssize_t size = fHeader->data_size + available; 1615 uint8* newData = (uint8*)realloc(fData, size); 1616 if (size > 0 && newData == NULL) { 1617 // this is strange, but not really fatal 1618 _UpdateOffsets(offset, change); 1619 return B_OK; 1620 } 1621 1622 fData = newData; 1623 fDataAvailable = available; 1624 } 1625 } 1626 1627 _UpdateOffsets(offset, change); 1628 return B_OK; 1629 } 1630 1631 1632 uint32 1633 BMessage::_HashName(const char* name) const 1634 { 1635 char ch; 1636 uint32 result = 0; 1637 1638 while ((ch = *name++) != 0) { 1639 result = (result << 7) ^ (result >> 24); 1640 result ^= ch; 1641 } 1642 1643 result ^= result << 12; 1644 return result; 1645 } 1646 1647 1648 status_t 1649 BMessage::_FindField(const char* name, type_code type, field_header** result) 1650 const 1651 { 1652 if (name == NULL) 1653 return B_BAD_VALUE; 1654 1655 if (fHeader == NULL) 1656 return B_NO_INIT; 1657 1658 if (fHeader->field_count == 0 || fFields == NULL || fData == NULL) 1659 return B_NAME_NOT_FOUND; 1660 1661 uint32 hash = _HashName(name) % fHeader->hash_table_size; 1662 int32 nextField = fHeader->hash_table[hash]; 1663 1664 while (nextField >= 0) { 1665 field_header* field = &fFields[nextField]; 1666 if ((field->flags & FIELD_FLAG_VALID) == 0) 1667 break; 1668 1669 if (strncmp((const char*)(fData + field->offset), name, 1670 field->name_length) == 0) { 1671 if (type != B_ANY_TYPE && field->type != type) 1672 return B_BAD_TYPE; 1673 1674 *result = field; 1675 return B_OK; 1676 } 1677 1678 nextField = field->next_field; 1679 } 1680 1681 return B_NAME_NOT_FOUND; 1682 } 1683 1684 1685 status_t 1686 BMessage::_AddField(const char* name, type_code type, bool isFixedSize, 1687 field_header** result) 1688 { 1689 if (fHeader == NULL) 1690 return B_NO_INIT; 1691 1692 if (fFieldsAvailable <= 0) { 1693 uint32 count = fHeader->field_count * 2 + 1; 1694 count = min_c(count, fHeader->field_count + MAX_FIELD_PREALLOCATION); 1695 1696 field_header* newFields = (field_header*)realloc(fFields, 1697 count * sizeof(field_header)); 1698 if (count > 0 && newFields == NULL) 1699 return B_NO_MEMORY; 1700 1701 fFields = newFields; 1702 fFieldsAvailable = count - fHeader->field_count; 1703 } 1704 1705 uint32 hash = _HashName(name) % fHeader->hash_table_size; 1706 int32* nextField = &fHeader->hash_table[hash]; 1707 while (*nextField >= 0) 1708 nextField = &fFields[*nextField].next_field; 1709 *nextField = fHeader->field_count; 1710 1711 field_header* field = &fFields[fHeader->field_count]; 1712 field->type = type; 1713 field->count = 0; 1714 field->data_size = 0; 1715 field->next_field = -1; 1716 field->offset = fHeader->data_size; 1717 field->name_length = strlen(name) + 1; 1718 status_t status = _ResizeData(field->offset, field->name_length); 1719 if (status != B_OK) 1720 return status; 1721 1722 memcpy(fData + field->offset, name, field->name_length); 1723 field->flags = FIELD_FLAG_VALID; 1724 if (isFixedSize) 1725 field->flags |= FIELD_FLAG_FIXED_SIZE; 1726 1727 fFieldsAvailable--; 1728 fHeader->field_count++; 1729 *result = field; 1730 return B_OK; 1731 } 1732 1733 1734 status_t 1735 BMessage::_RemoveField(field_header* field) 1736 { 1737 status_t result = _ResizeData(field->offset, -(field->data_size 1738 + field->name_length)); 1739 if (result != B_OK) 1740 return result; 1741 1742 int32 index = ((uint8*)field - (uint8*)fFields) / sizeof(field_header); 1743 int32 nextField = field->next_field; 1744 if (nextField > index) 1745 nextField--; 1746 1747 int32* value = fHeader->hash_table; 1748 for (uint32 i = 0; i < fHeader->hash_table_size; i++, value++) { 1749 if (*value > index) 1750 *value -= 1; 1751 else if (*value == index) 1752 *value = nextField; 1753 } 1754 1755 field_header* other = fFields; 1756 for (uint32 i = 0; i < fHeader->field_count; i++, other++) { 1757 if (other->next_field > index) 1758 other->next_field--; 1759 else if (other->next_field == index) 1760 other->next_field = nextField; 1761 } 1762 1763 size_t size = (fHeader->field_count - index - 1) * sizeof(field_header); 1764 memmove(fFields + index, fFields + index + 1, size); 1765 fHeader->field_count--; 1766 fFieldsAvailable++; 1767 1768 if (fFieldsAvailable > MAX_FIELD_PREALLOCATION) { 1769 ssize_t available = MAX_FIELD_PREALLOCATION / 2; 1770 size = (fHeader->field_count + available) * sizeof(field_header); 1771 field_header* newFields = (field_header*)realloc(fFields, size); 1772 if (size > 0 && newFields == NULL) { 1773 // this is strange, but not really fatal 1774 return B_OK; 1775 } 1776 1777 fFields = newFields; 1778 fFieldsAvailable = available; 1779 } 1780 1781 return B_OK; 1782 } 1783 1784 1785 status_t 1786 BMessage::AddData(const char* name, type_code type, const void* data, 1787 ssize_t numBytes, bool isFixedSize, int32 count) 1788 { 1789 // Note that the "count" argument is only a hint at how many items 1790 // the caller expects to add to this field. Since we do no item pre- 1791 // allocation, we ignore this argument. 1792 DEBUG_FUNCTION_ENTER; 1793 if (numBytes <= 0 || data == NULL) 1794 return B_BAD_VALUE; 1795 1796 if (fHeader == NULL) 1797 return B_NO_INIT; 1798 1799 status_t result; 1800 if (fHeader->message_area >= 0) { 1801 result = _CopyForWrite(); 1802 if (result != B_OK) 1803 return result; 1804 } 1805 1806 field_header* field = NULL; 1807 result = _FindField(name, type, &field); 1808 if (result == B_NAME_NOT_FOUND) 1809 result = _AddField(name, type, isFixedSize, &field); 1810 1811 if (result != B_OK) 1812 return result; 1813 1814 if (field == NULL) 1815 return B_ERROR; 1816 1817 uint32 offset = field->offset + field->name_length + field->data_size; 1818 if ((field->flags & FIELD_FLAG_FIXED_SIZE) != 0) { 1819 if (field->count) { 1820 ssize_t size = field->data_size / field->count; 1821 if (size != numBytes) 1822 return B_BAD_VALUE; 1823 } 1824 1825 result = _ResizeData(offset, numBytes); 1826 if (result != B_OK) { 1827 if (field->count == 0) 1828 _RemoveField(field); 1829 return result; 1830 } 1831 1832 memcpy(fData + offset, data, numBytes); 1833 field->data_size += numBytes; 1834 } else { 1835 int32 change = numBytes + sizeof(uint32); 1836 result = _ResizeData(offset, change); 1837 if (result != B_OK) { 1838 if (field->count == 0) 1839 _RemoveField(field); 1840 return result; 1841 } 1842 1843 uint32 size = (uint32)numBytes; 1844 memcpy(fData + offset, &size, sizeof(uint32)); 1845 memcpy(fData + offset + sizeof(uint32), data, size); 1846 field->data_size += change; 1847 } 1848 1849 field->count++; 1850 return B_OK; 1851 } 1852 1853 1854 status_t 1855 BMessage::RemoveData(const char* name, int32 index) 1856 { 1857 DEBUG_FUNCTION_ENTER; 1858 if (index < 0) 1859 return B_BAD_INDEX; 1860 1861 if (fHeader == NULL) 1862 return B_NO_INIT; 1863 1864 status_t result; 1865 if (fHeader->message_area >= 0) { 1866 result = _CopyForWrite(); 1867 if (result != B_OK) 1868 return result; 1869 } 1870 1871 field_header* field = NULL; 1872 result = _FindField(name, B_ANY_TYPE, &field); 1873 if (result != B_OK) 1874 return result; 1875 1876 if ((uint32)index >= field->count) 1877 return B_BAD_INDEX; 1878 1879 if (field->count == 1) 1880 return _RemoveField(field); 1881 1882 uint32 offset = field->offset + field->name_length; 1883 if ((field->flags & FIELD_FLAG_FIXED_SIZE) != 0) { 1884 ssize_t size = field->data_size / field->count; 1885 result = _ResizeData(offset + index * size, -size); 1886 if (result != B_OK) 1887 return result; 1888 1889 field->data_size -= size; 1890 } else { 1891 uint8* pointer = fData + offset; 1892 for (int32 i = 0; i < index; i++) { 1893 offset += *(uint32*)pointer + sizeof(uint32); 1894 pointer = fData + offset; 1895 } 1896 1897 size_t currentSize = *(uint32*)pointer + sizeof(uint32); 1898 result = _ResizeData(offset, -currentSize); 1899 if (result != B_OK) 1900 return result; 1901 1902 field->data_size -= currentSize; 1903 } 1904 1905 field->count--; 1906 return B_OK; 1907 } 1908 1909 1910 status_t 1911 BMessage::RemoveName(const char* name) 1912 { 1913 DEBUG_FUNCTION_ENTER; 1914 if (fHeader == NULL) 1915 return B_NO_INIT; 1916 1917 status_t result; 1918 if (fHeader->message_area >= 0) { 1919 result = _CopyForWrite(); 1920 if (result != B_OK) 1921 return result; 1922 } 1923 1924 field_header* field = NULL; 1925 result = _FindField(name, B_ANY_TYPE, &field); 1926 if (result != B_OK) 1927 return result; 1928 1929 return _RemoveField(field); 1930 } 1931 1932 1933 status_t 1934 BMessage::MakeEmpty() 1935 { 1936 DEBUG_FUNCTION_ENTER; 1937 _Clear(); 1938 return _InitHeader(); 1939 } 1940 1941 1942 status_t 1943 BMessage::FindData(const char* name, type_code type, int32 index, 1944 const void** data, ssize_t* numBytes) const 1945 { 1946 DEBUG_FUNCTION_ENTER; 1947 if (data == NULL) 1948 return B_BAD_VALUE; 1949 1950 *data = NULL; 1951 field_header* field = NULL; 1952 status_t result = _FindField(name, type, &field); 1953 if (result != B_OK) 1954 return result; 1955 1956 if (index < 0 || (uint32)index >= field->count) 1957 return B_BAD_INDEX; 1958 1959 if ((field->flags & FIELD_FLAG_FIXED_SIZE) != 0) { 1960 size_t bytes = field->data_size / field->count; 1961 *data = fData + field->offset + field->name_length + index * bytes; 1962 if (numBytes != NULL) 1963 *numBytes = bytes; 1964 } else { 1965 uint8* pointer = fData + field->offset + field->name_length; 1966 for (int32 i = 0; i < index; i++) 1967 pointer += *(uint32*)pointer + sizeof(uint32); 1968 1969 *data = pointer + sizeof(uint32); 1970 if (numBytes != NULL) 1971 *numBytes = *(uint32*)pointer; 1972 } 1973 1974 return B_OK; 1975 } 1976 1977 1978 status_t 1979 BMessage::ReplaceData(const char* name, type_code type, int32 index, 1980 const void* data, ssize_t numBytes) 1981 { 1982 DEBUG_FUNCTION_ENTER; 1983 if (numBytes <= 0 || data == NULL) 1984 return B_BAD_VALUE; 1985 1986 status_t result; 1987 if (fHeader->message_area >= 0) { 1988 result = _CopyForWrite(); 1989 if (result != B_OK) 1990 return result; 1991 } 1992 1993 field_header* field = NULL; 1994 result = _FindField(name, type, &field); 1995 if (result != B_OK) 1996 return result; 1997 1998 if (index < 0 || (uint32)index >= field->count) 1999 return B_BAD_INDEX; 2000 2001 if ((field->flags & FIELD_FLAG_FIXED_SIZE) != 0) { 2002 ssize_t size = field->data_size / field->count; 2003 if (size != numBytes) 2004 return B_BAD_VALUE; 2005 2006 memcpy(fData + field->offset + field->name_length + index * size, data, 2007 size); 2008 } else { 2009 uint32 offset = field->offset + field->name_length; 2010 uint8* pointer = fData + offset; 2011 2012 for (int32 i = 0; i < index; i++) { 2013 offset += *(uint32*)pointer + sizeof(uint32); 2014 pointer = fData + offset; 2015 } 2016 2017 size_t currentSize = *(uint32*)pointer; 2018 int32 change = numBytes - currentSize; 2019 result = _ResizeData(offset, change); 2020 if (result != B_OK) 2021 return result; 2022 2023 uint32 newSize = (uint32)numBytes; 2024 memcpy(fData + offset, &newSize, sizeof(uint32)); 2025 memcpy(fData + offset + sizeof(uint32), data, newSize); 2026 field->data_size += change; 2027 } 2028 2029 return B_OK; 2030 } 2031 2032 2033 bool 2034 BMessage::HasData(const char* name, type_code type, int32 index) const 2035 { 2036 DEBUG_FUNCTION_ENTER; 2037 field_header* field = NULL; 2038 status_t result = _FindField(name, type, &field); 2039 if (result != B_OK) 2040 return false; 2041 2042 if (index < 0 || (uint32)index >= field->count) 2043 return false; 2044 2045 return true; 2046 } 2047 2048 2049 /* Static functions for cache initialization and cleanup */ 2050 void 2051 BMessage::_StaticInit() 2052 { 2053 DEBUG_FUNCTION_ENTER2; 2054 sReplyPorts[0] = create_port(1, "tmp_rport0"); 2055 sReplyPorts[1] = create_port(1, "tmp_rport1"); 2056 sReplyPorts[2] = create_port(1, "tmp_rport2"); 2057 2058 sReplyPortInUse[0] = 0; 2059 sReplyPortInUse[1] = 0; 2060 sReplyPortInUse[2] = 0; 2061 2062 sMsgCache = new BBlockCache(20, sizeof(BMessage), B_OBJECT_CACHE); 2063 } 2064 2065 2066 void 2067 BMessage::_StaticReInitForkedChild() 2068 { 2069 DEBUG_FUNCTION_ENTER2; 2070 2071 // overwrite the inherited ports with a set of our own 2072 sReplyPorts[0] = create_port(1, "tmp_rport0"); 2073 sReplyPorts[1] = create_port(1, "tmp_rport1"); 2074 sReplyPorts[2] = create_port(1, "tmp_rport2"); 2075 2076 sReplyPortInUse[0] = 0; 2077 sReplyPortInUse[1] = 0; 2078 sReplyPortInUse[2] = 0; 2079 } 2080 2081 2082 void 2083 BMessage::_StaticCleanup() 2084 { 2085 DEBUG_FUNCTION_ENTER2; 2086 delete_port(sReplyPorts[0]); 2087 sReplyPorts[0] = -1; 2088 delete_port(sReplyPorts[1]); 2089 sReplyPorts[1] = -1; 2090 delete_port(sReplyPorts[2]); 2091 sReplyPorts[2] = -1; 2092 } 2093 2094 2095 void 2096 BMessage::_StaticCacheCleanup() 2097 { 2098 DEBUG_FUNCTION_ENTER2; 2099 delete sMsgCache; 2100 sMsgCache = NULL; 2101 } 2102 2103 2104 int32 2105 BMessage::_StaticGetCachedReplyPort() 2106 { 2107 DEBUG_FUNCTION_ENTER2; 2108 int index = -1; 2109 for (int32 i = 0; i < sNumReplyPorts; i++) { 2110 int32 old = atomic_add(&(sReplyPortInUse[i]), 1); 2111 if (old == 0) { 2112 // This entry is free 2113 index = i; 2114 break; 2115 } else { 2116 // This entry is being used. 2117 atomic_add(&(sReplyPortInUse[i]), -1); 2118 } 2119 } 2120 2121 return index; 2122 } 2123 2124 2125 status_t 2126 BMessage::_SendMessage(port_id port, team_id portOwner, int32 token, 2127 bigtime_t timeout, bool replyRequired, BMessenger& replyTo) const 2128 { 2129 DEBUG_FUNCTION_ENTER; 2130 ssize_t size = 0; 2131 char* buffer = NULL; 2132 message_header* header = NULL; 2133 status_t result = B_OK; 2134 2135 BPrivate::BDirectMessageTarget* direct = NULL; 2136 BMessage* copy = NULL; 2137 if (portOwner == BPrivate::current_team()) 2138 BPrivate::gDefaultTokens.AcquireHandlerTarget(token, &direct); 2139 2140 if (direct != NULL) { 2141 // We have a direct local message target - we can just enqueue the 2142 // message in its message queue. This will also prevent possible 2143 // deadlocks when the queue is full. 2144 copy = new BMessage(*this); 2145 if (copy != NULL) { 2146 header = copy->fHeader; 2147 header->flags = fHeader->flags; 2148 } else { 2149 direct->Release(); 2150 return B_NO_MEMORY; 2151 } 2152 #ifndef HAIKU_TARGET_PLATFORM_LIBBE_TEST 2153 } else if ((fHeader->flags & MESSAGE_FLAG_REPLY_AS_KMESSAGE) != 0) { 2154 KMessage toMessage; 2155 result = BPrivate::MessageAdapter::ConvertToKMessage(this, toMessage); 2156 if (result != B_OK) 2157 return result; 2158 2159 return toMessage.SendTo(port, token); 2160 } else if (fHeader->data_size > B_PAGE_SIZE * 10) { 2161 // ToDo: bind the above size to the max port message size 2162 // use message passing by area for such a large message 2163 result = _FlattenToArea(&header); 2164 if (result != B_OK) 2165 return result; 2166 2167 buffer = (char*)header; 2168 size = sizeof(message_header); 2169 2170 if (header->message_area >= 0) { 2171 team_id target = portOwner; 2172 if (target < 0) { 2173 port_info info; 2174 result = get_port_info(port, &info); 2175 if (result != B_OK) { 2176 free(header); 2177 return result; 2178 } 2179 target = info.team; 2180 } 2181 2182 void* address = NULL; 2183 area_id transfered = _kern_transfer_area(header->message_area, 2184 &address, B_ANY_ADDRESS, target); 2185 if (transfered < 0) { 2186 delete_area(header->message_area); 2187 free(header); 2188 return transfered; 2189 } 2190 2191 header->message_area = transfered; 2192 } 2193 #endif 2194 } else { 2195 size = FlattenedSize(); 2196 buffer = (char*)malloc(size); 2197 if (buffer == NULL) 2198 return B_NO_MEMORY; 2199 2200 result = Flatten(buffer, size); 2201 if (result != B_OK) { 2202 free(buffer); 2203 return result; 2204 } 2205 2206 header = (message_header*)buffer; 2207 } 2208 2209 if (!replyTo.IsValid()) { 2210 BMessenger::Private(replyTo).SetTo(fHeader->reply_team, 2211 fHeader->reply_port, fHeader->reply_target); 2212 2213 if (!replyTo.IsValid()) 2214 replyTo = be_app_messenger; 2215 } 2216 2217 BMessenger::Private replyToPrivate(replyTo); 2218 2219 if (replyRequired) { 2220 header->flags |= MESSAGE_FLAG_REPLY_REQUIRED; 2221 header->flags &= ~MESSAGE_FLAG_REPLY_DONE; 2222 } 2223 2224 header->target = token; 2225 header->reply_team = replyToPrivate.Team(); 2226 header->reply_port = replyToPrivate.Port(); 2227 header->reply_target = replyToPrivate.Token(); 2228 header->flags |= MESSAGE_FLAG_WAS_DELIVERED; 2229 2230 if (direct == NULL) { 2231 KTRACE("BMessage send remote: team: %ld, port: %ld, token: %ld, " 2232 "message: '%c%c%c%c'", portOwner, port, token, 2233 char(what >> 24), char(what >> 16), char(what >> 8), (char)what); 2234 2235 do { 2236 result = write_port_etc(port, kPortMessageCode, (void*)buffer, 2237 size, B_RELATIVE_TIMEOUT, timeout); 2238 } while (result == B_INTERRUPTED); 2239 } 2240 2241 if (result == B_OK && IsSourceWaiting()) { 2242 // the forwarded message will handle the reply - we must not do 2243 // this anymore 2244 fHeader->flags |= MESSAGE_FLAG_REPLY_DONE; 2245 } 2246 2247 // we need to do this last because it is possible our 2248 // message might be destroyed after it's enqueued in the 2249 // target looper. Thus we don't want to do any ops that depend on 2250 // members of this after the enqueue. 2251 if (direct != NULL) { 2252 KTRACE("BMessage send direct: port: %ld, token: %ld, " 2253 "message: '%c%c%c%c'", port, token, 2254 char(what >> 24), char(what >> 16), char(what >> 8), (char)what); 2255 2256 // this is a local message transmission 2257 direct->AddMessage(copy); 2258 if (direct->Queue()->IsNextMessage(copy) && port_count(port) <= 0) { 2259 // there is currently no message waiting, and we need to wakeup the 2260 // looper 2261 write_port_etc(port, 0, NULL, 0, B_RELATIVE_TIMEOUT, 0); 2262 } 2263 direct->Release(); 2264 } 2265 2266 free(buffer); 2267 return result; 2268 } 2269 2270 2271 // Sends a message and waits synchronously for a reply. 2272 status_t 2273 BMessage::_SendMessage(port_id port, team_id portOwner, int32 token, 2274 BMessage* reply, bigtime_t sendTimeout, bigtime_t replyTimeout) const 2275 { 2276 if (IsSourceWaiting()) { 2277 // we can't forward this message synchronously when it's already 2278 // waiting for a reply 2279 return B_ERROR; 2280 } 2281 2282 DEBUG_FUNCTION_ENTER; 2283 const int32 cachedReplyPort = _StaticGetCachedReplyPort(); 2284 port_id replyPort = B_BAD_PORT_ID; 2285 status_t result = B_OK; 2286 2287 if (cachedReplyPort < 0) { 2288 // All the cached reply ports are in use; create a new one 2289 replyPort = create_port(1 /* for one message */, "tmp_reply_port"); 2290 if (replyPort < 0) 2291 return replyPort; 2292 } else { 2293 assert(cachedReplyPort < sNumReplyPorts); 2294 replyPort = sReplyPorts[cachedReplyPort]; 2295 } 2296 2297 bool recreateCachedPort = false; 2298 2299 team_id team = B_BAD_TEAM_ID; 2300 if (be_app != NULL) 2301 team = be_app->Team(); 2302 else { 2303 port_info portInfo; 2304 result = get_port_info(replyPort, &portInfo); 2305 if (result != B_OK) 2306 goto error; 2307 2308 team = portInfo.team; 2309 } 2310 2311 result = set_port_owner(replyPort, portOwner); 2312 if (result != B_OK) 2313 goto error; 2314 2315 // tests if the queue of the reply port is really empty 2316 #if 0 2317 port_info portInfo; 2318 if (get_port_info(replyPort, &portInfo) == B_OK 2319 && portInfo.queue_count > 0) { 2320 debugger("reply port not empty!"); 2321 printf(" reply port not empty! %ld message(s) in queue\n", 2322 portInfo.queue_count); 2323 2324 // fetch and print the messages 2325 for (int32 i = 0; i < portInfo.queue_count; i++) { 2326 char buffer[1024]; 2327 int32 code; 2328 ssize_t size = read_port(replyPort, &code, buffer, sizeof(buffer)); 2329 if (size < 0) { 2330 printf("failed to read message from reply port\n"); 2331 continue; 2332 } 2333 if (size >= (ssize_t)sizeof(buffer)) { 2334 printf("message from reply port too big\n"); 2335 continue; 2336 } 2337 2338 BMemoryIO stream(buffer, size); 2339 BMessage reply; 2340 if (reply.Unflatten(&stream) != B_OK) { 2341 printf("failed to unflatten message from reply port\n"); 2342 continue; 2343 } 2344 2345 printf("message %ld from reply port:\n", i); 2346 reply.PrintToStream(); 2347 } 2348 } 2349 #endif 2350 2351 { 2352 BMessenger replyTarget; 2353 BMessenger::Private(replyTarget).SetTo(team, replyPort, 2354 B_PREFERRED_TOKEN); 2355 // TODO: replying could also use a BDirectMessageTarget like mechanism 2356 // for local targets 2357 result = _SendMessage(port, -1, token, sendTimeout, true, 2358 replyTarget); 2359 } 2360 2361 if (result != B_OK) 2362 goto error; 2363 2364 int32 code; 2365 result = handle_reply(replyPort, &code, replyTimeout, reply); 2366 if (result != B_OK && cachedReplyPort >= 0) { 2367 delete_port(replyPort); 2368 recreateCachedPort = true; 2369 } 2370 2371 error: 2372 if (cachedReplyPort >= 0) { 2373 // Reclaim ownership of cached port, if possible 2374 if (!recreateCachedPort && set_port_owner(replyPort, team) == B_OK) { 2375 // Flag as available 2376 atomic_add(&sReplyPortInUse[cachedReplyPort], -1); 2377 } else 2378 sReplyPorts[cachedReplyPort] = create_port(1, "tmp_rport"); 2379 2380 return result; 2381 } 2382 2383 delete_port(replyPort); 2384 return result; 2385 } 2386 2387 2388 status_t 2389 BMessage::_SendFlattenedMessage(void* data, int32 size, port_id port, 2390 int32 token, bigtime_t timeout) 2391 { 2392 DEBUG_FUNCTION_ENTER2; 2393 if (data == NULL) 2394 return B_BAD_VALUE; 2395 2396 uint32 magic = *(uint32*)data; 2397 2398 if (magic == MESSAGE_FORMAT_HAIKU 2399 || magic == MESSAGE_FORMAT_HAIKU_SWAPPED) { 2400 message_header* header = (message_header*)data; 2401 header->target = token; 2402 header->flags |= MESSAGE_FLAG_WAS_DELIVERED; 2403 } else if (magic == MESSAGE_FORMAT_R5) { 2404 uint8* header = (uint8*)data; 2405 header += sizeof(uint32) /* magic */ + sizeof(uint32) /* checksum */ 2406 + sizeof(ssize_t) /* flattenedSize */ + sizeof(int32) /* what */ 2407 + sizeof(uint8) /* flags */; 2408 *(int32*)header = token; 2409 } else if (((KMessage::Header*)data)->magic 2410 == KMessage::kMessageHeaderMagic) { 2411 KMessage::Header* header = (KMessage::Header*)data; 2412 header->targetToken = token; 2413 } else { 2414 return B_NOT_A_MESSAGE; 2415 } 2416 2417 // send the message 2418 status_t result; 2419 2420 do { 2421 result = write_port_etc(port, kPortMessageCode, data, size, 2422 B_RELATIVE_TIMEOUT, timeout); 2423 } while (result == B_INTERRUPTED); 2424 2425 return result; 2426 } 2427 2428 2429 void BMessage::_ReservedMessage1() {} 2430 void BMessage::_ReservedMessage2() {} 2431 void BMessage::_ReservedMessage3() {} 2432 2433 2434 // #pragma mark - Macro definitions for data access methods 2435 2436 2437 /* Relay functions from here on (Add... -> AddData, Find... -> FindData) */ 2438 2439 #define DEFINE_FUNCTIONS(type, typeName, typeCode) \ 2440 status_t \ 2441 BMessage::Add##typeName(const char* name, type val) \ 2442 { \ 2443 return AddData(name, typeCode, &val, sizeof(type), true); \ 2444 } \ 2445 \ 2446 \ 2447 status_t \ 2448 BMessage::Find##typeName(const char* name, type* p) const \ 2449 { \ 2450 return Find##typeName(name, 0, p); \ 2451 } \ 2452 \ 2453 \ 2454 status_t \ 2455 BMessage::Find##typeName(const char* name, int32 index, type* p) const \ 2456 { \ 2457 type* ptr = NULL; \ 2458 ssize_t bytes = 0; \ 2459 status_t error = B_OK; \ 2460 \ 2461 *p = type(); \ 2462 error = FindData(name, typeCode, index, (const void**)&ptr, &bytes); \ 2463 \ 2464 if (error == B_OK) \ 2465 memcpy((void *)p, ptr, sizeof(type)); \ 2466 \ 2467 return error; \ 2468 } \ 2469 \ 2470 \ 2471 status_t \ 2472 BMessage::Replace##typeName(const char* name, type value) \ 2473 { \ 2474 return ReplaceData(name, typeCode, 0, &value, sizeof(type)); \ 2475 } \ 2476 \ 2477 \ 2478 status_t \ 2479 BMessage::Replace##typeName(const char* name, int32 index, type value) \ 2480 { \ 2481 return ReplaceData(name, typeCode, index, &value, sizeof(type)); \ 2482 } \ 2483 \ 2484 \ 2485 bool \ 2486 BMessage::Has##typeName(const char* name, int32 index) const \ 2487 { \ 2488 return HasData(name, typeCode, index); \ 2489 } 2490 2491 DEFINE_FUNCTIONS(BPoint, Point, B_POINT_TYPE); 2492 DEFINE_FUNCTIONS(BRect, Rect, B_RECT_TYPE); 2493 DEFINE_FUNCTIONS(BSize, Size, B_SIZE_TYPE); 2494 DEFINE_FUNCTIONS(int8, Int8, B_INT8_TYPE); 2495 DEFINE_FUNCTIONS(uint8, UInt8, B_UINT8_TYPE); 2496 DEFINE_FUNCTIONS(int16, Int16, B_INT16_TYPE); 2497 DEFINE_FUNCTIONS(uint16, UInt16, B_UINT16_TYPE); 2498 DEFINE_FUNCTIONS(int32, Int32, B_INT32_TYPE); 2499 DEFINE_FUNCTIONS(uint32, UInt32, B_UINT32_TYPE); 2500 DEFINE_FUNCTIONS(int64, Int64, B_INT64_TYPE); 2501 DEFINE_FUNCTIONS(uint64, UInt64, B_UINT64_TYPE); 2502 DEFINE_FUNCTIONS(bool, Bool, B_BOOL_TYPE); 2503 DEFINE_FUNCTIONS(float, Float, B_FLOAT_TYPE); 2504 DEFINE_FUNCTIONS(double, Double, B_DOUBLE_TYPE); 2505 DEFINE_FUNCTIONS(rgb_color, Color, B_RGB_32_BIT_TYPE); 2506 2507 #undef DEFINE_FUNCTIONS 2508 2509 #define DEFINE_HAS_FUNCTION(typeName, typeCode) \ 2510 bool \ 2511 BMessage::Has##typeName(const char* name, int32 index) const \ 2512 { \ 2513 return HasData(name, typeCode, index); \ 2514 } 2515 2516 2517 DEFINE_HAS_FUNCTION(Alignment, B_ALIGNMENT_TYPE); 2518 DEFINE_HAS_FUNCTION(String, B_STRING_TYPE); 2519 DEFINE_HAS_FUNCTION(Pointer, B_POINTER_TYPE); 2520 DEFINE_HAS_FUNCTION(Messenger, B_MESSENGER_TYPE); 2521 DEFINE_HAS_FUNCTION(Ref, B_REF_TYPE); 2522 DEFINE_HAS_FUNCTION(NodeRef, B_NODE_REF_TYPE); 2523 DEFINE_HAS_FUNCTION(Message, B_MESSAGE_TYPE); 2524 2525 #undef DEFINE_HAS_FUNCTION 2526 2527 2528 #define DEFINE_LAZY_FIND_FUNCTION(type, typeName, initialize) \ 2529 type \ 2530 BMessage::Find##typeName(const char* name, int32 index) const \ 2531 { \ 2532 type val = initialize; \ 2533 Find##typeName(name, index, &val); \ 2534 return val; \ 2535 } 2536 2537 2538 DEFINE_LAZY_FIND_FUNCTION(BRect, Rect, BRect()); 2539 DEFINE_LAZY_FIND_FUNCTION(BPoint, Point, BPoint()); 2540 DEFINE_LAZY_FIND_FUNCTION(const char*, String, NULL); 2541 DEFINE_LAZY_FIND_FUNCTION(int8, Int8, 0); 2542 DEFINE_LAZY_FIND_FUNCTION(int16, Int16, 0); 2543 DEFINE_LAZY_FIND_FUNCTION(int32, Int32, 0); 2544 DEFINE_LAZY_FIND_FUNCTION(int64, Int64, 0); 2545 DEFINE_LAZY_FIND_FUNCTION(bool, Bool, false); 2546 DEFINE_LAZY_FIND_FUNCTION(float, Float, 0); 2547 DEFINE_LAZY_FIND_FUNCTION(double, Double, 0); 2548 2549 #undef DEFINE_LAZY_FIND_FUNCTION 2550 2551 2552 #define DEFINE_SET_GET_FUNCTIONS(type, typeName, typeCode) \ 2553 type \ 2554 BMessage::Get##typeName(const char* name, type defaultValue) const \ 2555 { \ 2556 return Get##typeName(name, 0, defaultValue); \ 2557 } \ 2558 \ 2559 \ 2560 type \ 2561 BMessage::Get##typeName(const char* name, int32 index, \ 2562 type defaultValue) const \ 2563 { \ 2564 type value; \ 2565 if (Find##typeName(name, index, &value) == B_OK) \ 2566 return value; \ 2567 \ 2568 return defaultValue; \ 2569 } \ 2570 \ 2571 \ 2572 status_t \ 2573 BMessage::Set##typeName(const char* name, type value) \ 2574 { \ 2575 return SetData(name, typeCode, &value, sizeof(type)); \ 2576 } \ 2577 2578 2579 DEFINE_SET_GET_FUNCTIONS(int8, Int8, B_INT8_TYPE); 2580 DEFINE_SET_GET_FUNCTIONS(uint8, UInt8, B_UINT8_TYPE); 2581 DEFINE_SET_GET_FUNCTIONS(int16, Int16, B_INT16_TYPE); 2582 DEFINE_SET_GET_FUNCTIONS(uint16, UInt16, B_UINT16_TYPE); 2583 DEFINE_SET_GET_FUNCTIONS(int32, Int32, B_INT32_TYPE); 2584 DEFINE_SET_GET_FUNCTIONS(uint32, UInt32, B_UINT32_TYPE); 2585 DEFINE_SET_GET_FUNCTIONS(int64, Int64, B_INT64_TYPE); 2586 DEFINE_SET_GET_FUNCTIONS(uint64, UInt64, B_UINT64_TYPE); 2587 DEFINE_SET_GET_FUNCTIONS(bool, Bool, B_BOOL_TYPE); 2588 DEFINE_SET_GET_FUNCTIONS(float, Float, B_FLOAT_TYPE); 2589 DEFINE_SET_GET_FUNCTIONS(double, Double, B_DOUBLE_TYPE); 2590 DEFINE_SET_GET_FUNCTIONS(rgb_color, Color, B_RGB_32_BIT_TYPE); 2591 2592 #undef DEFINE_SET_GET_FUNCTION 2593 2594 2595 const void* 2596 BMessage::GetPointer(const char* name, const void* defaultValue) const 2597 { 2598 return GetPointer(name, 0, defaultValue); 2599 } 2600 2601 2602 const void* 2603 BMessage::GetPointer(const char* name, int32 index, 2604 const void* defaultValue) const 2605 { 2606 void* value; 2607 if (FindPointer(name, index, &value) == B_OK) 2608 return value; 2609 2610 return defaultValue; 2611 } 2612 2613 2614 status_t 2615 BMessage::SetPointer(const char* name, const void* value) 2616 { 2617 return SetData(name, B_POINTER_TYPE, &value, sizeof(void*)); 2618 } 2619 2620 2621 #define DEFINE_SET_GET_BY_REFERENCE_FUNCTIONS(type, typeName, typeCode) \ 2622 type \ 2623 BMessage::Get##typeName(const char* name, const type& defaultValue) const \ 2624 { \ 2625 return Get##typeName(name, 0, defaultValue); \ 2626 } \ 2627 \ 2628 \ 2629 type \ 2630 BMessage::Get##typeName(const char* name, int32 index, \ 2631 const type& defaultValue) const \ 2632 { \ 2633 type value; \ 2634 if (Find##typeName(name, index, &value) == B_OK) \ 2635 return value; \ 2636 \ 2637 return defaultValue; \ 2638 } \ 2639 \ 2640 \ 2641 status_t \ 2642 BMessage::Set##typeName(const char* name, const type& value) \ 2643 { \ 2644 return SetData(name, typeCode, &value, sizeof(type)); \ 2645 } \ 2646 2647 2648 DEFINE_SET_GET_BY_REFERENCE_FUNCTIONS(BPoint, Point, B_POINT_TYPE); 2649 DEFINE_SET_GET_BY_REFERENCE_FUNCTIONS(BRect, Rect, B_RECT_TYPE); 2650 DEFINE_SET_GET_BY_REFERENCE_FUNCTIONS(BSize, Size, B_SIZE_TYPE); 2651 2652 #undef DEFINE_SET_GET_BY_REFERENCE_FUNCTIONS 2653 2654 2655 status_t 2656 BMessage::AddAlignment(const char* name, const BAlignment& alignment) 2657 { 2658 int32 data[2] = { alignment.horizontal, alignment.vertical }; 2659 return AddData(name, B_ALIGNMENT_TYPE, data, sizeof(data)); 2660 } 2661 2662 2663 status_t 2664 BMessage::AddString(const char* name, const char* string) 2665 { 2666 return AddData(name, B_STRING_TYPE, string, string ? strlen(string) + 1 : 0, 2667 false); 2668 } 2669 2670 2671 status_t 2672 BMessage::AddString(const char* name, const BString& string) 2673 { 2674 return AddData(name, B_STRING_TYPE, string.String(), string.Length() + 1, 2675 false); 2676 } 2677 2678 2679 status_t 2680 BMessage::AddStrings(const char* name, const BStringList& list) 2681 { 2682 int32 count = list.CountStrings(); 2683 for (int32 i = 0; i < count; i++) { 2684 status_t error = AddString(name, list.StringAt(i)); 2685 if (error != B_OK) 2686 return error; 2687 } 2688 2689 return B_OK; 2690 } 2691 2692 2693 status_t 2694 BMessage::AddPointer(const char* name, const void* pointer) 2695 { 2696 return AddData(name, B_POINTER_TYPE, &pointer, sizeof(pointer), true); 2697 } 2698 2699 2700 status_t 2701 BMessage::AddMessenger(const char* name, BMessenger messenger) 2702 { 2703 return AddData(name, B_MESSENGER_TYPE, &messenger, sizeof(messenger), true); 2704 } 2705 2706 2707 status_t 2708 BMessage::AddRef(const char* name, const entry_ref* ref) 2709 { 2710 size_t size = sizeof(entry_ref) + B_PATH_NAME_LENGTH; 2711 char buffer[size]; 2712 2713 status_t error = BPrivate::entry_ref_flatten(buffer, &size, ref); 2714 2715 if (error >= B_OK) 2716 error = AddData(name, B_REF_TYPE, buffer, size, false); 2717 2718 return error; 2719 } 2720 2721 2722 status_t 2723 BMessage::AddNodeRef(const char* name, const node_ref* ref) 2724 { 2725 size_t size = sizeof(node_ref); 2726 char buffer[size]; 2727 2728 status_t error = BPrivate::node_ref_flatten(buffer, &size, ref); 2729 2730 if (error >= B_OK) 2731 error = AddData(name, B_NODE_REF_TYPE, buffer, size, false); 2732 2733 return error; 2734 } 2735 2736 2737 status_t 2738 BMessage::AddMessage(const char* name, const BMessage* message) 2739 { 2740 if (message == NULL) 2741 return B_BAD_VALUE; 2742 2743 // TODO: This and the following functions waste time by allocating and 2744 // copying an extra buffer. Functions can be added that return a direct 2745 // pointer into the message. 2746 2747 char stackBuffer[16384]; 2748 ssize_t size = message->FlattenedSize(); 2749 2750 char* buffer; 2751 if (size > (ssize_t)sizeof(stackBuffer)) { 2752 buffer = (char*)malloc(size); 2753 if (buffer == NULL) 2754 return B_NO_MEMORY; 2755 } else 2756 buffer = stackBuffer; 2757 2758 status_t error = message->Flatten(buffer, size); 2759 2760 if (error >= B_OK) 2761 error = AddData(name, B_MESSAGE_TYPE, buffer, size, false); 2762 2763 if (buffer != stackBuffer) 2764 free(buffer); 2765 2766 return error; 2767 } 2768 2769 2770 status_t 2771 BMessage::AddFlat(const char* name, BFlattenable* object, int32 count) 2772 { 2773 return AddFlat(name, (const BFlattenable*)object, count); 2774 } 2775 2776 2777 status_t 2778 BMessage::AddFlat(const char* name, const BFlattenable* object, int32 count) 2779 { 2780 if (object == NULL) 2781 return B_BAD_VALUE; 2782 2783 char stackBuffer[16384]; 2784 ssize_t size = object->FlattenedSize(); 2785 2786 char* buffer; 2787 if (size > (ssize_t)sizeof(stackBuffer)) { 2788 buffer = (char*)malloc(size); 2789 if (buffer == NULL) 2790 return B_NO_MEMORY; 2791 } else 2792 buffer = stackBuffer; 2793 2794 status_t error = object->Flatten(buffer, size); 2795 2796 if (error >= B_OK) 2797 error = AddData(name, object->TypeCode(), buffer, size, false); 2798 2799 if (buffer != stackBuffer) 2800 free(buffer); 2801 2802 return error; 2803 } 2804 2805 2806 status_t 2807 BMessage::Append(const BMessage& other) 2808 { 2809 field_header* field = other.fFields; 2810 for (uint32 i = 0; i < other.fHeader->field_count; i++, field++) { 2811 const char* name = (const char*)(other.fData + field->offset); 2812 const void* data = (const void*)(other.fData + field->offset 2813 + field->name_length); 2814 bool isFixed = (field->flags & FIELD_FLAG_FIXED_SIZE) != 0; 2815 size_t size = field->data_size / field->count; 2816 2817 for (uint32 j = 0; j < field->count; j++) { 2818 if (!isFixed) { 2819 size = *(uint32*)data; 2820 data = (const void*)((const char*)data + sizeof(uint32)); 2821 } 2822 2823 status_t status = AddData(name, field->type, data, size, 2824 isFixed, 1); 2825 if (status != B_OK) 2826 return status; 2827 2828 data = (const void*)((const char*)data + size); 2829 } 2830 } 2831 return B_OK; 2832 } 2833 2834 2835 status_t 2836 BMessage::FindAlignment(const char* name, BAlignment* alignment) const 2837 { 2838 return FindAlignment(name, 0, alignment); 2839 } 2840 2841 2842 status_t 2843 BMessage::FindAlignment(const char* name, int32 index, BAlignment* alignment) 2844 const 2845 { 2846 if (!alignment) 2847 return B_BAD_VALUE; 2848 2849 int32* data; 2850 ssize_t bytes; 2851 2852 status_t err = FindData(name, B_ALIGNMENT_TYPE, index, 2853 (const void**)&data, &bytes); 2854 2855 if (err == B_OK) { 2856 if (bytes != sizeof(int32[2])) 2857 return B_ERROR; 2858 2859 alignment->horizontal = (enum alignment)(*data); 2860 alignment->vertical = (vertical_alignment)*(data + 1); 2861 } 2862 2863 return err; 2864 } 2865 2866 2867 status_t 2868 BMessage::FindString(const char* name, const char** string) const 2869 { 2870 return FindString(name, 0, string); 2871 } 2872 2873 2874 status_t 2875 BMessage::FindString(const char* name, int32 index, const char** string) const 2876 { 2877 ssize_t bytes; 2878 return FindData(name, B_STRING_TYPE, index, (const void**)string, &bytes); 2879 } 2880 2881 2882 status_t 2883 BMessage::FindString(const char* name, BString* string) const 2884 { 2885 return FindString(name, 0, string); 2886 } 2887 2888 2889 status_t 2890 BMessage::FindString(const char* name, int32 index, BString* string) const 2891 { 2892 if (string == NULL) 2893 return B_BAD_VALUE; 2894 2895 const char* value; 2896 status_t error = FindString(name, index, &value); 2897 2898 // Find*() clobbers the object even on failure 2899 string->SetTo(value); 2900 return error; 2901 } 2902 2903 2904 status_t 2905 BMessage::FindStrings(const char* name, BStringList* list) const 2906 { 2907 if (list == NULL) 2908 return B_BAD_VALUE; 2909 2910 list->MakeEmpty(); 2911 2912 // get the number of items 2913 type_code type; 2914 int32 count; 2915 if (GetInfo(name, &type, &count) != B_OK) 2916 return B_NAME_NOT_FOUND; 2917 2918 if (type != B_STRING_TYPE) 2919 return B_BAD_DATA; 2920 2921 for (int32 i = 0; i < count; i++) { 2922 BString string; 2923 status_t error = FindString(name, i, &string); 2924 if (error != B_OK) 2925 return error; 2926 if (!list->Add(string)) 2927 return B_NO_MEMORY; 2928 } 2929 2930 return B_OK; 2931 } 2932 2933 2934 status_t 2935 BMessage::FindPointer(const char* name, void** pointer) const 2936 { 2937 return FindPointer(name, 0, pointer); 2938 } 2939 2940 2941 status_t 2942 BMessage::FindPointer(const char* name, int32 index, void** pointer) const 2943 { 2944 if (pointer == NULL) 2945 return B_BAD_VALUE; 2946 2947 void** data = NULL; 2948 ssize_t size = 0; 2949 status_t error = FindData(name, B_POINTER_TYPE, index, 2950 (const void**)&data, &size); 2951 2952 if (error == B_OK) 2953 *pointer = *data; 2954 else 2955 *pointer = NULL; 2956 2957 return error; 2958 } 2959 2960 2961 status_t 2962 BMessage::FindMessenger(const char* name, BMessenger* messenger) const 2963 { 2964 return FindMessenger(name, 0, messenger); 2965 } 2966 2967 2968 status_t 2969 BMessage::FindMessenger(const char* name, int32 index, 2970 BMessenger* messenger) const 2971 { 2972 if (messenger == NULL) 2973 return B_BAD_VALUE; 2974 2975 BMessenger* data = NULL; 2976 ssize_t size = 0; 2977 status_t error = FindData(name, B_MESSENGER_TYPE, index, 2978 (const void**)&data, &size); 2979 2980 if (error == B_OK) 2981 *messenger = *data; 2982 else 2983 *messenger = BMessenger(); 2984 2985 return error; 2986 } 2987 2988 2989 status_t 2990 BMessage::FindRef(const char* name, entry_ref* ref) const 2991 { 2992 return FindRef(name, 0, ref); 2993 } 2994 2995 2996 status_t 2997 BMessage::FindRef(const char* name, int32 index, entry_ref* ref) const 2998 { 2999 if (ref == NULL) 3000 return B_BAD_VALUE; 3001 3002 void* data = NULL; 3003 ssize_t size = 0; 3004 status_t error = FindData(name, B_REF_TYPE, index, 3005 (const void**)&data, &size); 3006 3007 if (error == B_OK) 3008 error = BPrivate::entry_ref_unflatten(ref, (char*)data, size); 3009 else 3010 *ref = entry_ref(); 3011 3012 return error; 3013 } 3014 3015 3016 status_t 3017 BMessage::FindNodeRef(const char* name, node_ref* ref) const 3018 { 3019 return FindNodeRef(name, 0, ref); 3020 } 3021 3022 3023 status_t 3024 BMessage::FindNodeRef(const char* name, int32 index, node_ref* ref) const 3025 { 3026 if (ref == NULL) 3027 return B_BAD_VALUE; 3028 3029 void* data = NULL; 3030 ssize_t size = 0; 3031 status_t error = FindData(name, B_NODE_REF_TYPE, index, 3032 (const void**)&data, &size); 3033 3034 if (error == B_OK) 3035 error = BPrivate::node_ref_unflatten(ref, (char*)data, size); 3036 else 3037 *ref = node_ref(); 3038 3039 return error; 3040 } 3041 3042 3043 status_t 3044 BMessage::FindMessage(const char* name, BMessage* message) const 3045 { 3046 return FindMessage(name, 0, message); 3047 } 3048 3049 3050 status_t 3051 BMessage::FindMessage(const char* name, int32 index, BMessage* message) const 3052 { 3053 if (message == NULL) 3054 return B_BAD_VALUE; 3055 3056 void* data = NULL; 3057 ssize_t size = 0; 3058 status_t error = FindData(name, B_MESSAGE_TYPE, index, 3059 (const void**)&data, &size); 3060 3061 if (error == B_OK) 3062 error = message->Unflatten((const char*)data); 3063 else 3064 *message = BMessage(); 3065 3066 return error; 3067 } 3068 3069 3070 status_t 3071 BMessage::FindFlat(const char* name, BFlattenable* object) const 3072 { 3073 return FindFlat(name, 0, object); 3074 } 3075 3076 3077 status_t 3078 BMessage::FindFlat(const char* name, int32 index, BFlattenable* object) const 3079 { 3080 if (object == NULL) 3081 return B_BAD_VALUE; 3082 3083 void* data = NULL; 3084 ssize_t numBytes = 0; 3085 status_t error = FindData(name, object->TypeCode(), index, 3086 (const void**)&data, &numBytes); 3087 3088 if (error == B_OK) 3089 error = object->Unflatten(object->TypeCode(), data, numBytes); 3090 3091 return error; 3092 } 3093 3094 3095 status_t 3096 BMessage::FindData(const char* name, type_code type, const void** data, 3097 ssize_t* numBytes) const 3098 { 3099 return FindData(name, type, 0, data, numBytes); 3100 } 3101 3102 3103 status_t 3104 BMessage::ReplaceAlignment(const char* name, const BAlignment& alignment) 3105 { 3106 int32 data[2] = {alignment.horizontal, alignment.vertical}; 3107 return ReplaceData(name, B_ALIGNMENT_TYPE, 0, data, sizeof(data)); 3108 } 3109 3110 3111 status_t 3112 BMessage::ReplaceAlignment(const char* name, int32 index, 3113 const BAlignment& alignment) 3114 { 3115 int32 data[2] = {alignment.horizontal, alignment.vertical}; 3116 return ReplaceData(name, B_ALIGNMENT_TYPE, index, data, sizeof(data)); 3117 } 3118 3119 3120 status_t 3121 BMessage::ReplaceString(const char* name, const char* string) 3122 { 3123 if (string == NULL) 3124 return B_BAD_VALUE; 3125 3126 return ReplaceData(name, B_STRING_TYPE, 0, string, strlen(string) + 1); 3127 } 3128 3129 3130 status_t 3131 BMessage::ReplaceString(const char* name, int32 index, const char* string) 3132 { 3133 if (string == NULL) 3134 return B_BAD_VALUE; 3135 3136 return ReplaceData(name, B_STRING_TYPE, index, string, strlen(string) + 1); 3137 } 3138 3139 3140 status_t 3141 BMessage::ReplaceString(const char* name, const BString& string) 3142 { 3143 return ReplaceData(name, B_STRING_TYPE, 0, string.String(), 3144 string.Length() + 1); 3145 } 3146 3147 3148 status_t 3149 BMessage::ReplaceString(const char* name, int32 index, const BString& string) 3150 { 3151 return ReplaceData(name, B_STRING_TYPE, index, string.String(), 3152 string.Length() + 1); 3153 } 3154 3155 3156 status_t 3157 BMessage::ReplacePointer(const char* name, const void* pointer) 3158 { 3159 return ReplaceData(name, B_POINTER_TYPE, 0, &pointer, sizeof(pointer)); 3160 } 3161 3162 3163 status_t 3164 BMessage::ReplacePointer(const char* name, int32 index, const void* pointer) 3165 { 3166 return ReplaceData(name, B_POINTER_TYPE, index, &pointer, sizeof(pointer)); 3167 } 3168 3169 3170 status_t 3171 BMessage::ReplaceMessenger(const char* name, BMessenger messenger) 3172 { 3173 return ReplaceData(name, B_MESSENGER_TYPE, 0, &messenger, 3174 sizeof(BMessenger)); 3175 } 3176 3177 3178 status_t 3179 BMessage::ReplaceMessenger(const char* name, int32 index, BMessenger messenger) 3180 { 3181 return ReplaceData(name, B_MESSENGER_TYPE, index, &messenger, 3182 sizeof(BMessenger)); 3183 } 3184 3185 3186 status_t 3187 BMessage::ReplaceRef(const char* name, const entry_ref* ref) 3188 { 3189 return ReplaceRef(name, 0, ref); 3190 } 3191 3192 3193 status_t 3194 BMessage::ReplaceRef(const char* name, int32 index, const entry_ref* ref) 3195 { 3196 size_t size = sizeof(entry_ref) + B_PATH_NAME_LENGTH; 3197 char buffer[size]; 3198 3199 status_t error = BPrivate::entry_ref_flatten(buffer, &size, ref); 3200 3201 if (error >= B_OK) 3202 error = ReplaceData(name, B_REF_TYPE, index, buffer, size); 3203 3204 return error; 3205 } 3206 3207 3208 status_t 3209 BMessage::ReplaceNodeRef(const char* name, const node_ref* ref) 3210 { 3211 return ReplaceNodeRef(name, 0, ref); 3212 } 3213 3214 3215 status_t 3216 BMessage::ReplaceNodeRef(const char* name, int32 index, const node_ref* ref) 3217 { 3218 size_t size = sizeof(node_ref) + B_PATH_NAME_LENGTH; 3219 char buffer[size]; 3220 3221 status_t error = BPrivate::node_ref_flatten(buffer, &size, ref); 3222 3223 if (error >= B_OK) 3224 error = ReplaceData(name, B_NODE_REF_TYPE, index, buffer, size); 3225 3226 return error; 3227 } 3228 3229 3230 status_t 3231 BMessage::ReplaceMessage(const char* name, const BMessage* message) 3232 { 3233 return ReplaceMessage(name, 0, message); 3234 } 3235 3236 3237 status_t 3238 BMessage::ReplaceMessage(const char* name, int32 index, const BMessage* message) 3239 { 3240 if (message == NULL) 3241 return B_BAD_VALUE; 3242 3243 ssize_t size = message->FlattenedSize(); 3244 if (size < 0) 3245 return B_BAD_VALUE; 3246 3247 char buffer[size]; 3248 3249 status_t error = message->Flatten(buffer, size); 3250 3251 if (error >= B_OK) 3252 error = ReplaceData(name, B_MESSAGE_TYPE, index, &buffer, size); 3253 3254 return error; 3255 } 3256 3257 3258 status_t 3259 BMessage::ReplaceFlat(const char* name, BFlattenable* object) 3260 { 3261 return ReplaceFlat(name, 0, object); 3262 } 3263 3264 3265 status_t 3266 BMessage::ReplaceFlat(const char* name, int32 index, BFlattenable* object) 3267 { 3268 if (object == NULL) 3269 return B_BAD_VALUE; 3270 3271 ssize_t size = object->FlattenedSize(); 3272 if (size < 0) 3273 return B_BAD_VALUE; 3274 3275 char buffer[size]; 3276 3277 status_t error = object->Flatten(buffer, size); 3278 3279 if (error >= B_OK) 3280 error = ReplaceData(name, object->TypeCode(), index, &buffer, size); 3281 3282 return error; 3283 } 3284 3285 3286 status_t 3287 BMessage::ReplaceData(const char* name, type_code type, const void* data, 3288 ssize_t numBytes) 3289 { 3290 return ReplaceData(name, type, 0, data, numBytes); 3291 } 3292 3293 3294 bool 3295 BMessage::HasFlat(const char* name, const BFlattenable* object) const 3296 { 3297 return HasFlat(name, 0, object); 3298 } 3299 3300 3301 bool 3302 BMessage::HasFlat(const char* name, int32 index, const BFlattenable* object) 3303 const 3304 { 3305 return HasData(name, object->TypeCode(), index); 3306 } 3307 3308 3309 const char* 3310 BMessage::GetString(const char* name, const char* defaultValue) const 3311 { 3312 return GetString(name, 0, defaultValue); 3313 } 3314 3315 3316 const char* 3317 BMessage::GetString(const char* name, int32 index, 3318 const char* defaultValue) const 3319 { 3320 const char* value; 3321 if (FindString(name, index, &value) == B_OK) 3322 return value; 3323 3324 return defaultValue; 3325 } 3326 3327 3328 status_t 3329 BMessage::SetString(const char* name, const BString& value) 3330 { 3331 return SetData(name, B_STRING_TYPE, value.String(), value.Length() + 1, 3332 false); 3333 } 3334 3335 3336 status_t 3337 BMessage::SetString(const char* name, const char* value) 3338 { 3339 return SetData(name, B_STRING_TYPE, value, strlen(value) + 1, false); 3340 } 3341 3342 3343 status_t 3344 BMessage::SetData(const char* name, type_code type, const void* data, 3345 ssize_t numBytes, bool fixedSize, int count) 3346 { 3347 if (numBytes <= 0 || data == NULL) 3348 return B_BAD_VALUE; 3349 3350 if (ReplaceData(name, type, data, numBytes) == B_OK) 3351 return B_OK; 3352 3353 return AddData(name, type, data, numBytes, fixedSize, count); 3354 } 3355