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