1 /* 2 * Copyright 2005-2010, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7 #include <util/KMessage.h> 8 9 #include <stdlib.h> 10 #include <string.h> 11 12 #include <ByteOrder.h> 13 #include <Debug.h> 14 #include <KernelExport.h> 15 #include <TypeConstants.h> 16 17 18 #if defined(_BOOT_MODE) || defined(_LOADER_MODE) 19 # include <util/kernel_cpp.h> 20 #else 21 # include <new> 22 #endif 23 24 25 // TODO: Add a field index using a hash map, so that lookup improves to O(1) 26 // (is now O(n)). 27 28 29 // define the PANIC macro 30 #ifndef PANIC 31 # ifdef _KERNEL_MODE 32 # define PANIC(str) panic(str) 33 # else 34 # define PANIC(str) debugger(str) 35 # endif 36 #endif 37 38 39 #if !defined(HAIKU_TARGET_PLATFORM_HAIKU) || defined(_BOOT_MODE) \ 40 || defined(_LOADER_MODE) 41 # define MEMALIGN(alignment, size) malloc(size) 42 // Built as part of a build tool or the boot or runtime loader. 43 #else 44 # include <malloc.h> 45 # define MEMALIGN(alignment, size) memalign(alignment, size) 46 // Built as part of the kernel or userland. Using memalign allows use of 47 // special heap implementations that might otherwise return unaligned 48 // buffers for debugging purposes. 49 #endif 50 51 52 static const int32 kMessageReallocChunkSize = 64; 53 static const size_t kMessageBufferAlignment = 4; 54 55 const uint32 KMessage::kMessageHeaderMagic = 'kMsG'; 56 57 58 // #pragma mark - Helper Functions 59 60 static inline int32 61 _Align(int32 offset) 62 { 63 return (offset + kMessageBufferAlignment - 1) 64 & ~(kMessageBufferAlignment - 1); 65 } 66 67 68 static inline void* 69 _Align(void* address, int32 offset = 0) 70 { 71 return (void*)(((addr_t)address + offset + kMessageBufferAlignment - 1) 72 & ~(kMessageBufferAlignment - 1)); 73 } 74 75 76 // #pragma mark - FieldValueHeader 77 78 79 struct KMessage::FieldValueHeader { 80 int32 size; 81 82 void* Data() 83 { 84 return _Align(this, sizeof(FieldValueHeader)); 85 } 86 87 FieldValueHeader* NextFieldValueHeader() 88 { 89 return (FieldValueHeader*)_Align(Data(), size); 90 } 91 }; 92 93 94 // #pragma mark - FieldHeader 95 96 97 struct KMessage::FieldHeader { 98 type_code type; 99 int32 elementSize; // if < 0: non-fixed size 100 int32 elementCount; 101 int32 fieldSize; 102 int16 headerSize; 103 char name[1]; 104 105 void* Data() 106 { 107 return (uint8*)this + headerSize; 108 } 109 110 bool HasFixedElementSize() 111 { 112 return elementSize >= 0; 113 } 114 115 void* ElementAt(int32 index, int32* size) 116 { 117 if (index < 0 || index >= elementCount) 118 return NULL; 119 uint8* data = (uint8*)this + headerSize; 120 if (HasFixedElementSize()) { 121 *size = elementSize; 122 return data + elementSize * index; 123 } 124 // non-fixed element size: we need to iterate 125 FieldValueHeader* valueHeader = (FieldValueHeader*)data; 126 for (int i = 0; i < index; i++) 127 valueHeader = valueHeader->NextFieldValueHeader(); 128 *size = valueHeader->size; 129 return valueHeader->Data(); 130 } 131 132 FieldHeader* NextFieldHeader() 133 { 134 return (FieldHeader*)_Align(this, fieldSize); 135 } 136 }; 137 138 139 // #pragma mark - KMessage 140 141 142 KMessage::KMessage() 143 : 144 fBuffer(NULL), 145 fBufferCapacity(0), 146 fFlags(0), 147 fLastFieldOffset(0) 148 { 149 Unset(); 150 } 151 152 153 KMessage::KMessage(uint32 what) 154 : 155 fBuffer(NULL), 156 fBufferCapacity(0), 157 fFlags(0), 158 fLastFieldOffset(0) 159 { 160 Unset(); 161 SetWhat(what); 162 } 163 164 165 KMessage::~KMessage() 166 { 167 Unset(); 168 } 169 170 171 status_t 172 KMessage::SetTo(uint32 what, uint32 flags) 173 { 174 // There are no flags interesting in this case at the moment. 175 Unset(); 176 SetWhat(what); 177 return B_OK; 178 } 179 180 181 status_t 182 KMessage::SetTo(void* buffer, int32 bufferSize, uint32 what, uint32 flags) 183 { 184 Unset(); 185 186 if (!buffer) 187 return B_BAD_VALUE; 188 189 if (bufferSize < 0) { 190 if (!(flags & KMESSAGE_INIT_FROM_BUFFER)) 191 return B_BAD_VALUE; 192 } else if (bufferSize < (int)sizeof(Header)) 193 return B_BAD_VALUE; 194 195 // if read-only, we need to init from the buffer, too 196 if ((flags & KMESSAGE_READ_ONLY) != 0 197 && (flags & KMESSAGE_INIT_FROM_BUFFER) == 0) { 198 return B_BAD_VALUE; 199 } 200 201 // if not initializing from the given buffer, cloning it doesn't make sense 202 if ((flags & KMESSAGE_INIT_FROM_BUFFER) == 0 203 && (flags & KMESSAGE_CLONE_BUFFER) != 0) { 204 return B_BAD_VALUE; 205 } 206 207 fBuffer = buffer; 208 fBufferCapacity = bufferSize; 209 fFlags = flags; 210 211 status_t error = B_OK; 212 if (flags & KMESSAGE_INIT_FROM_BUFFER) 213 error = _InitFromBuffer(bufferSize < 0); 214 else 215 _InitBuffer(what); 216 217 if (error != B_OK) 218 Unset(); 219 220 return error; 221 } 222 223 224 status_t 225 KMessage::SetTo(const void* buffer, int32 bufferSize, uint32 flags) 226 { 227 return SetTo(const_cast<void*>(buffer), bufferSize, 0, 228 KMESSAGE_INIT_FROM_BUFFER | KMESSAGE_READ_ONLY | flags); 229 } 230 231 232 void 233 KMessage::Unset() 234 { 235 // free buffer 236 if (fBuffer && fBuffer != &fHeader && (fFlags & KMESSAGE_OWNS_BUFFER)) 237 free(fBuffer); 238 fBuffer = &fHeader; 239 fBufferCapacity = sizeof(Header); 240 _InitBuffer(0); 241 } 242 243 244 void 245 KMessage::SetWhat(uint32 what) 246 { 247 _Header()->what = what; 248 } 249 250 251 uint32 252 KMessage::What() const 253 { 254 return _Header()->what; 255 } 256 257 258 const void* 259 KMessage::Buffer() const 260 { 261 return fBuffer; 262 } 263 264 265 int32 266 KMessage::BufferCapacity() const 267 { 268 return fBufferCapacity; 269 } 270 271 272 int32 273 KMessage::ContentSize() const 274 { 275 return _Header()->size; 276 } 277 278 279 status_t 280 KMessage::AddField(const char* name, type_code type, int32 elementSize, 281 KMessageField* field) 282 { 283 if (!name || type == B_ANY_TYPE) 284 return B_BAD_VALUE; 285 KMessageField existingField; 286 if (FindField(name, &existingField) == B_OK) 287 return B_NAME_IN_USE; 288 return _AddField(name, type, elementSize, field); 289 } 290 291 292 status_t 293 KMessage::FindField(const char* name, KMessageField* field) const 294 { 295 return FindField(name, B_ANY_TYPE, field); 296 } 297 298 299 status_t 300 KMessage::FindField(const char* name, type_code type, 301 KMessageField* field) const 302 { 303 if (!name) 304 return B_BAD_VALUE; 305 KMessageField stackField; 306 if (field) 307 field->Unset(); 308 else 309 field = &stackField; 310 while (GetNextField(field) == B_OK) { 311 if ((type == B_ANY_TYPE || field->TypeCode() == type) 312 && strcmp(name, field->Name()) == 0) { 313 return B_OK; 314 } 315 } 316 return B_NAME_NOT_FOUND; 317 } 318 319 320 status_t 321 KMessage::GetNextField(KMessageField* field) const 322 { 323 if (!field || (field->Message() != NULL && field->Message() != this)) 324 return B_BAD_VALUE; 325 FieldHeader* fieldHeader = field->_Header(); 326 FieldHeader* lastField = _LastFieldHeader(); 327 if (!lastField) 328 return B_NAME_NOT_FOUND; 329 if (fieldHeader == NULL) { 330 fieldHeader = _FirstFieldHeader(); 331 } else { 332 if ((uint8*)fieldHeader < (uint8*)_FirstFieldHeader() 333 || (uint8*)fieldHeader > (uint8*)lastField) { 334 return B_BAD_VALUE; 335 } 336 if (fieldHeader == lastField) 337 return B_NAME_NOT_FOUND; 338 fieldHeader = fieldHeader->NextFieldHeader(); 339 } 340 field->SetTo(const_cast<KMessage*>(this), _BufferOffsetFor(fieldHeader)); 341 return B_OK; 342 } 343 344 345 bool 346 KMessage::IsEmpty() const 347 { 348 return _LastFieldHeader() == NULL; 349 } 350 351 352 status_t 353 KMessage::AddData(const char* name, type_code type, const void* data, 354 int32 numBytes, bool isFixedSize) 355 { 356 if (!name || type == B_ANY_TYPE || !data || numBytes < 0) 357 return B_BAD_VALUE; 358 KMessageField field; 359 if (FindField(name, &field) == B_OK) { 360 // field with that name already exists: check its type 361 if (field.TypeCode() != type) 362 return B_BAD_TYPE; 363 } else { 364 // no such field yet: add it 365 status_t error = _AddField(name, type, (isFixedSize ? numBytes : -1), 366 &field); 367 if (error != B_OK) 368 return error; 369 } 370 return _AddFieldData(&field, data, numBytes, 1); 371 } 372 373 374 status_t 375 KMessage::AddArray(const char* name, type_code type, const void* data, 376 int32 elementSize, int32 elementCount) 377 { 378 if (!name || type == B_ANY_TYPE || !data || elementSize < 0 379 || elementCount < 0) { 380 return B_BAD_VALUE; 381 } 382 KMessageField field; 383 if (FindField(name, &field) == B_OK) { 384 // field with that name already exists: check its type 385 if (field.TypeCode() != type) 386 return B_BAD_TYPE; 387 } else { 388 // no such field yet: add it 389 status_t error = _AddField(name, type, elementSize, &field); 390 if (error != B_OK) 391 return error; 392 } 393 return _AddFieldData(&field, data, elementSize, elementCount); 394 } 395 396 397 status_t 398 KMessage::SetData(const char* name, type_code type, const void* data, 399 int32 numBytes) 400 { 401 if (fBuffer != &fHeader && (fFlags & KMESSAGE_READ_ONLY)) 402 return B_NOT_ALLOWED; 403 404 KMessageField field; 405 406 if (FindField(name, &field) == B_OK) { 407 // field already known 408 if (field.TypeCode() != type || !field.HasFixedElementSize() 409 || field.ElementSize() != numBytes) { 410 return B_BAD_VALUE; 411 } 412 413 // if it has an element, just replace its value 414 if (field.CountElements() > 0) { 415 const void* element = field.ElementAt(0); 416 memcpy(const_cast<void*>(element), data, numBytes); 417 return B_OK; 418 } 419 } else { 420 // no such field yet -- add it 421 status_t error = _AddField(name, type, numBytes, &field); 422 if (error != B_OK) 423 return error; 424 } 425 426 // we've got an empty field -- add the element 427 return _AddFieldData(&field, data, numBytes, 1); 428 } 429 430 431 status_t 432 KMessage::FindData(const char* name, type_code type, const void** data, 433 int32* numBytes) const 434 { 435 return FindData(name, type, 0, data, numBytes); 436 } 437 438 439 status_t 440 KMessage::FindData(const char* name, type_code type, int32 index, 441 const void** data, int32* numBytes) const 442 { 443 if (!name || !data || !numBytes) 444 return B_BAD_VALUE; 445 KMessageField field; 446 status_t error = FindField(name, type, &field); 447 if (error != B_OK) 448 return error; 449 const void* foundData = field.ElementAt(index, numBytes); 450 if (!foundData) 451 return B_BAD_INDEX; 452 if (data) 453 *data = foundData; 454 return B_OK; 455 } 456 457 458 team_id 459 KMessage::Sender() const 460 { 461 return _Header()->sender; 462 } 463 464 465 int32 466 KMessage::TargetToken() const 467 { 468 return _Header()->targetToken; 469 } 470 471 472 port_id 473 KMessage::ReplyPort() const 474 { 475 return _Header()->replyPort; 476 } 477 478 479 int32 480 KMessage::ReplyToken() const 481 { 482 return _Header()->replyToken; 483 } 484 485 486 void 487 KMessage::SetDeliveryInfo(int32 targetToken, port_id replyPort, 488 int32 replyToken, team_id senderTeam) 489 { 490 Header* header = _Header(); 491 header->sender = senderTeam; 492 header->targetToken = targetToken; 493 header->replyPort = replyPort; 494 header->replyToken = replyToken; 495 header->sender = senderTeam; 496 } 497 498 499 #ifndef KMESSAGE_CONTAINER_ONLY 500 501 502 status_t 503 KMessage::SendTo(port_id targetPort, int32 targetToken, port_id replyPort, 504 int32 replyToken, bigtime_t timeout, team_id senderTeam) 505 { 506 // get the sender team 507 if (senderTeam < 0) { 508 thread_info info; 509 status_t error = get_thread_info(find_thread(NULL), &info); 510 if (error != B_OK) 511 return error; 512 513 senderTeam = info.team; 514 } 515 516 SetDeliveryInfo(targetToken, replyPort, replyToken, senderTeam); 517 518 // send the message 519 if (timeout < 0) 520 return write_port(targetPort, 'KMSG', fBuffer, ContentSize()); 521 522 return write_port_etc(targetPort, 'KMSG', fBuffer, ContentSize(), 523 B_RELATIVE_TIMEOUT, timeout); 524 } 525 526 527 status_t 528 KMessage::SendTo(port_id targetPort, int32 targetToken, KMessage* reply, 529 bigtime_t deliveryTimeout, bigtime_t replyTimeout, team_id senderTeam) 530 { 531 // get the team the target port belongs to 532 port_info portInfo; 533 status_t error = get_port_info(targetPort, &portInfo); 534 if (error != B_OK) 535 return error; 536 team_id targetTeam = portInfo.team; 537 // allocate a reply port, if a reply is desired 538 port_id replyPort = -1; 539 if (reply) { 540 // get our team 541 team_id ourTeam = B_SYSTEM_TEAM; 542 #ifndef _KERNEL_MODE 543 if (targetTeam != B_SYSTEM_TEAM) { 544 thread_info threadInfo; 545 error = get_thread_info(find_thread(NULL), &threadInfo); 546 if (error != B_OK) 547 return error; 548 ourTeam = threadInfo.team; 549 } 550 #endif 551 // create the port 552 replyPort = create_port(1, "KMessage reply port"); 553 if (replyPort < 0) 554 return replyPort; 555 // If the target team is not our team and not the kernel team either, 556 // we transfer the ownership of the port to it, so we will not block 557 if (targetTeam != ourTeam && targetTeam != B_SYSTEM_TEAM) 558 set_port_owner(replyPort, targetTeam); 559 } 560 struct PortDeleter { 561 PortDeleter(port_id port) : port(port) {} 562 ~PortDeleter() 563 { 564 if (port >= 0) 565 delete_port(port); 566 } 567 568 port_id port; 569 } replyPortDeleter(replyPort); 570 // send the message 571 error = SendTo(targetPort, targetToken, replyPort, 0, 572 deliveryTimeout, senderTeam); 573 if (error != B_OK) 574 return error; 575 // get the reply 576 if (reply) 577 return reply->ReceiveFrom(replyPort, replyTimeout); 578 return B_OK; 579 } 580 581 582 status_t 583 KMessage::SendReply(KMessage* message, port_id replyPort, int32 replyToken, 584 bigtime_t timeout, team_id senderTeam) 585 { 586 if (!message) 587 return B_BAD_VALUE; 588 return message->SendTo(ReplyPort(), ReplyToken(), replyPort, replyToken, 589 timeout, senderTeam); 590 } 591 592 593 status_t 594 KMessage::SendReply(KMessage* message, KMessage* reply, 595 bigtime_t deliveryTimeout, bigtime_t replyTimeout, team_id senderTeam) 596 { 597 if (!message) 598 return B_BAD_VALUE; 599 return message->SendTo(ReplyPort(), ReplyToken(), reply, deliveryTimeout, 600 replyTimeout, senderTeam); 601 } 602 603 604 status_t 605 KMessage::ReceiveFrom(port_id fromPort, bigtime_t timeout, 606 port_message_info* messageInfo) 607 { 608 port_message_info _messageInfo; 609 if (messageInfo == NULL) 610 messageInfo = &_messageInfo; 611 612 // get the port buffer size 613 status_t error; 614 if (timeout < 0) { 615 error = get_port_message_info_etc(fromPort, messageInfo, 0, 0); 616 } else { 617 error = get_port_message_info_etc(fromPort, messageInfo, 618 B_RELATIVE_TIMEOUT, timeout); 619 } 620 if (error != B_OK) 621 return error; 622 623 // allocate a buffer 624 uint8* buffer = (uint8*)MEMALIGN(kMessageBufferAlignment, 625 messageInfo->size); 626 if (!buffer) 627 return B_NO_MEMORY; 628 629 // read the message 630 int32 what; 631 ssize_t realSize = read_port_etc(fromPort, &what, buffer, messageInfo->size, 632 B_RELATIVE_TIMEOUT, 0); 633 if (realSize < 0) { 634 free(buffer); 635 return realSize; 636 } 637 if (messageInfo->size != (size_t)realSize) { 638 free(buffer); 639 return B_ERROR; 640 } 641 642 // init the message 643 return SetTo(buffer, messageInfo->size, 0, 644 KMESSAGE_OWNS_BUFFER | KMESSAGE_INIT_FROM_BUFFER); 645 } 646 647 648 #endif // !KMESSAGE_CONTAINER_ONLY 649 650 651 void 652 KMessage::Dump(void (*printFunc)(const char*, ...)) const 653 { 654 Header* header = _Header(); 655 printFunc("KMessage: buffer: %p (size/capacity: %ld/%ld), flags: %#" 656 B_PRIx32 "\n", fBuffer, header->size, fBufferCapacity, fFlags); 657 658 KMessageField field; 659 while (GetNextField(&field) == B_OK) { 660 type_code type = field.TypeCode(); 661 uint32 bigEndianType = B_HOST_TO_BENDIAN_INT32(type); 662 int nameSpacing = 17 - strlen(field.Name()); 663 if (nameSpacing < 0) 664 nameSpacing = 0; 665 666 printFunc(" field: \"%s\"%*s (%.4s): ", field.Name(), nameSpacing, "", 667 (char*)&bigEndianType); 668 669 if (field.CountElements() != 1) 670 printFunc("\n"); 671 672 int32 size; 673 for (int i = 0; const void* data = field.ElementAt(i, &size); i++) { 674 if (field.CountElements() != 1) 675 printFunc(" [%2d] ", i); 676 677 bool isIntType = false; 678 int64 intData = 0; 679 switch (type) { 680 case B_BOOL_TYPE: 681 printFunc("%s\n", (*(bool*)data ? "true" : "false")); 682 break; 683 case B_INT8_TYPE: 684 isIntType = true; 685 intData = *(int8*)data; 686 break; 687 case B_INT16_TYPE: 688 isIntType = true; 689 intData = *(int16*)data; 690 break; 691 case B_INT32_TYPE: 692 isIntType = true; 693 intData = *(int32*)data; 694 break; 695 case B_INT64_TYPE: 696 isIntType = true; 697 intData = *(int64*)data; 698 break; 699 case B_STRING_TYPE: 700 printFunc("\"%s\"\n", (char*)data); 701 break; 702 default: 703 printFunc("data at %p, %ld bytes\n", (char*)data, size); 704 break; 705 } 706 if (isIntType) 707 printFunc("%lld (0x%llx)\n", intData, intData); 708 } 709 } 710 } 711 712 713 KMessage::Header* 714 KMessage::_Header() const 715 { 716 return (Header*)fBuffer; 717 } 718 719 720 int32 721 KMessage::_BufferOffsetFor(const void* data) const 722 { 723 if (!data) 724 return -1; 725 return (uint8*)data - (uint8*)fBuffer; 726 } 727 728 729 KMessage::FieldHeader* 730 KMessage::_FirstFieldHeader() const 731 { 732 return (FieldHeader*)_Align(fBuffer, sizeof(Header)); 733 } 734 735 736 KMessage::FieldHeader* 737 KMessage::_LastFieldHeader() const 738 { 739 return _FieldHeaderForOffset(fLastFieldOffset); 740 } 741 742 743 KMessage::FieldHeader* 744 KMessage::_FieldHeaderForOffset(int32 offset) const 745 { 746 if (offset <= 0 || offset >= _Header()->size) 747 return NULL; 748 return (FieldHeader*)((uint8*)fBuffer + offset); 749 } 750 751 752 status_t 753 KMessage::_AddField(const char* name, type_code type, int32 elementSize, 754 KMessageField* field) 755 { 756 FieldHeader* fieldHeader; 757 int32 alignedSize; 758 status_t error = _AllocateSpace(sizeof(FieldHeader) + strlen(name), true, 759 true, (void**)&fieldHeader, &alignedSize); 760 if (error != B_OK) 761 return error; 762 fieldHeader->type = type; 763 fieldHeader->elementSize = elementSize; 764 fieldHeader->elementCount = 0; 765 fieldHeader->fieldSize = alignedSize; 766 fieldHeader->headerSize = alignedSize; 767 strcpy(fieldHeader->name, name); 768 fLastFieldOffset = _BufferOffsetFor(fieldHeader); 769 if (field) 770 field->SetTo(this, _BufferOffsetFor(fieldHeader)); 771 return B_OK; 772 } 773 774 775 status_t 776 KMessage::_AddFieldData(KMessageField* field, const void* data, 777 int32 elementSize, int32 elementCount) 778 { 779 if (!field) 780 return B_BAD_VALUE; 781 FieldHeader* fieldHeader = field->_Header(); 782 FieldHeader* lastField = _LastFieldHeader(); 783 if (!fieldHeader || fieldHeader != lastField || !data 784 || elementSize < 0 || elementCount < 0) { 785 return B_BAD_VALUE; 786 } 787 if (elementCount == 0) 788 return B_OK; 789 // fixed size values 790 if (fieldHeader->HasFixedElementSize()) { 791 if (elementSize != fieldHeader->elementSize) 792 return B_BAD_VALUE; 793 void* address; 794 int32 alignedSize; 795 status_t error = _AllocateSpace(elementSize * elementCount, 796 (fieldHeader->elementCount == 0), false, &address, &alignedSize); 797 if (error != B_OK) 798 return error; 799 fieldHeader = field->_Header(); // might have been relocated 800 memcpy(address, data, elementSize * elementCount); 801 fieldHeader->elementCount += elementCount; 802 fieldHeader->fieldSize = (uint8*)address + alignedSize 803 - (uint8*)fieldHeader; 804 return B_OK; 805 } 806 // non-fixed size values 807 // add the elements individually (TODO: Optimize!) 808 int32 valueHeaderSize = _Align(sizeof(FieldValueHeader)); 809 int32 entrySize = valueHeaderSize + elementSize; 810 for (int32 i = 0; i < elementCount; i++) { 811 void* address; 812 int32 alignedSize; 813 status_t error = _AllocateSpace(entrySize, true, false, &address, 814 &alignedSize); 815 if (error != B_OK) 816 return error; 817 fieldHeader = field->_Header(); // might have been relocated 818 FieldValueHeader* valueHeader = (FieldValueHeader*)address; 819 valueHeader->size = elementSize; 820 memcpy(valueHeader->Data(), (const uint8*)data + i * elementSize, 821 elementSize); 822 fieldHeader->elementCount++; 823 fieldHeader->fieldSize = (uint8*)address + alignedSize 824 - (uint8*)fieldHeader; 825 } 826 return B_OK; 827 } 828 829 830 status_t 831 KMessage::_InitFromBuffer(bool sizeFromBuffer) 832 { 833 if (fBuffer == NULL) 834 return B_BAD_DATA; 835 836 // clone the buffer, if requested 837 if ((fFlags & KMESSAGE_CLONE_BUFFER) != 0 || _Align(fBuffer) != fBuffer) { 838 if (sizeFromBuffer) { 839 int32 size = fBufferCapacity; 840 memcpy(&size, &_Header()->size, 4); 841 fBufferCapacity = size; 842 } 843 844 void* buffer = MEMALIGN(kMessageBufferAlignment, fBufferCapacity); 845 if (buffer == NULL) 846 return B_NO_MEMORY; 847 848 memcpy(buffer, fBuffer, fBufferCapacity); 849 850 if ((fFlags & KMESSAGE_OWNS_BUFFER) != 0) 851 free(fBuffer); 852 853 fBuffer = buffer; 854 fFlags &= ~(uint32)(KMESSAGE_READ_ONLY | KMESSAGE_CLONE_BUFFER); 855 fFlags |= KMESSAGE_OWNS_BUFFER; 856 } 857 858 if (_Align(fBuffer) != fBuffer) 859 return B_BAD_DATA; 860 861 Header* header = _Header(); 862 863 if (sizeFromBuffer) 864 fBufferCapacity = header->size; 865 866 if (fBufferCapacity < (int)sizeof(Header)) 867 return B_BAD_DATA; 868 869 // check header 870 if (header->magic != kMessageHeaderMagic) 871 return B_BAD_DATA; 872 if (header->size < (int)sizeof(Header) || header->size > fBufferCapacity) 873 return B_BAD_DATA; 874 875 // check the fields 876 FieldHeader* fieldHeader = NULL; 877 uint8* data = (uint8*)_FirstFieldHeader(); 878 int32 remainingBytes = (uint8*)fBuffer + header->size - data; 879 while (remainingBytes > 0) { 880 if (remainingBytes < (int)sizeof(FieldHeader)) 881 return B_BAD_DATA; 882 fieldHeader = (FieldHeader*)data; 883 // check field header 884 if (fieldHeader->type == B_ANY_TYPE) 885 return B_BAD_DATA; 886 if (fieldHeader->elementCount < 0) 887 return B_BAD_DATA; 888 if (fieldHeader->fieldSize < (int)sizeof(FieldHeader) 889 || fieldHeader->fieldSize > remainingBytes) { 890 return B_BAD_DATA; 891 } 892 if (fieldHeader->headerSize < (int)sizeof(FieldHeader) 893 || fieldHeader->headerSize > fieldHeader->fieldSize) { 894 return B_BAD_DATA; 895 } 896 int32 maxNameLen = data + fieldHeader->headerSize 897 - (uint8*)fieldHeader->name; 898 int32 nameLen = strnlen(fieldHeader->name, maxNameLen); 899 if (nameLen == maxNameLen || nameLen == 0) 900 return B_BAD_DATA; 901 int32 fieldSize = fieldHeader->headerSize; 902 if (fieldHeader->HasFixedElementSize()) { 903 // fixed element size 904 int32 dataSize = fieldHeader->elementSize 905 * fieldHeader->elementCount; 906 fieldSize = (uint8*)fieldHeader->Data() + dataSize - data; 907 } else { 908 // non-fixed element size 909 FieldValueHeader* valueHeader 910 = (FieldValueHeader*)fieldHeader->Data(); 911 for (int32 i = 0; i < fieldHeader->elementCount; i++) { 912 remainingBytes = (uint8*)fBuffer + header->size 913 - (uint8*)valueHeader; 914 if (remainingBytes < (int)sizeof(FieldValueHeader)) 915 return B_BAD_DATA; 916 uint8* value = (uint8*)valueHeader->Data(); 917 remainingBytes = (uint8*)fBuffer + header->size - (uint8*)value; 918 if (remainingBytes < valueHeader->size) 919 return B_BAD_DATA; 920 fieldSize = value + valueHeader->size - data; 921 valueHeader = valueHeader->NextFieldValueHeader(); 922 } 923 if (fieldSize > fieldHeader->fieldSize) 924 return B_BAD_DATA; 925 } 926 data = (uint8*)fieldHeader->NextFieldHeader(); 927 remainingBytes = (uint8*)fBuffer + header->size - data; 928 } 929 fLastFieldOffset = _BufferOffsetFor(fieldHeader); 930 return B_OK; 931 } 932 933 934 void 935 KMessage::_InitBuffer(uint32 what) 936 { 937 Header* header = _Header(); 938 header->magic = kMessageHeaderMagic; 939 header->size = sizeof(Header); 940 header->what = what; 941 header->sender = -1; 942 header->targetToken = -1; 943 header->replyPort = -1; 944 header->replyToken = -1; 945 fLastFieldOffset = 0; 946 } 947 948 949 void 950 KMessage::_CheckBuffer() 951 { 952 int32 lastFieldOffset = fLastFieldOffset; 953 if (_InitFromBuffer(false) != B_OK) { 954 PANIC("internal data mangled"); 955 } 956 if (fLastFieldOffset != lastFieldOffset) { 957 PANIC("fLastFieldOffset changed during KMessage::_CheckBuffer()"); 958 } 959 } 960 961 962 status_t 963 KMessage::_AllocateSpace(int32 size, bool alignAddress, bool alignSize, 964 void** address, int32* alignedSize) 965 { 966 if (fBuffer != &fHeader && (fFlags & KMESSAGE_READ_ONLY)) 967 return B_NOT_ALLOWED; 968 969 int32 offset = ContentSize(); 970 if (alignAddress) 971 offset = _Align(offset); 972 int32 newSize = offset + size; 973 if (alignSize) 974 newSize = _Align(newSize); 975 // reallocate if necessary 976 if (fBuffer == &fHeader) { 977 int32 newCapacity = _CapacityFor(newSize); 978 void* newBuffer = MEMALIGN(kMessageBufferAlignment, newCapacity); 979 if (!newBuffer) 980 return B_NO_MEMORY; 981 fBuffer = newBuffer; 982 fBufferCapacity = newCapacity; 983 fFlags |= KMESSAGE_OWNS_BUFFER; 984 memcpy(fBuffer, &fHeader, sizeof(fHeader)); 985 } else { 986 if (newSize > fBufferCapacity) { 987 // if we don't own the buffer, we can't resize it 988 if (!(fFlags & KMESSAGE_OWNS_BUFFER)) { 989 #if defined(_KERNEL_MODE) && 0 990 // optional debugging to find insufficiently sized KMessage 991 // buffers (e.g. for in-kernel notifications) 992 panic("KMessage: out of space: available: %" B_PRId32 993 ", needed: %" B_PRId32 "\n", fBufferCapacity, newSize); 994 #endif 995 return B_BUFFER_OVERFLOW; 996 } 997 998 int32 newCapacity = _CapacityFor(newSize); 999 void* newBuffer = realloc(fBuffer, newCapacity); 1000 if (!newBuffer) 1001 return B_NO_MEMORY; 1002 fBuffer = newBuffer; 1003 fBufferCapacity = newCapacity; 1004 } 1005 } 1006 _Header()->size = newSize; 1007 *address = (char*)fBuffer + offset; 1008 *alignedSize = newSize - offset; 1009 return B_OK; 1010 } 1011 1012 1013 int32 1014 KMessage::_CapacityFor(int32 size) 1015 { 1016 return (size + kMessageReallocChunkSize - 1) / kMessageReallocChunkSize 1017 * kMessageReallocChunkSize; 1018 } 1019 1020 1021 // #pragma mark - KMessageField 1022 1023 1024 KMessageField::KMessageField() 1025 : 1026 fMessage(NULL), 1027 fHeaderOffset(0) 1028 { 1029 } 1030 1031 1032 void 1033 KMessageField::Unset() 1034 { 1035 fMessage = NULL; 1036 fHeaderOffset = 0; 1037 } 1038 1039 1040 KMessage* 1041 KMessageField::Message() const 1042 { 1043 return fMessage; 1044 } 1045 1046 1047 const char* 1048 KMessageField::Name() const 1049 { 1050 KMessage::FieldHeader* header = _Header(); 1051 return header ? header->name : NULL; 1052 } 1053 1054 1055 type_code 1056 KMessageField::TypeCode() const 1057 { 1058 KMessage::FieldHeader* header = _Header(); 1059 return header ? header->type : 0; 1060 } 1061 1062 1063 bool 1064 KMessageField::HasFixedElementSize() const 1065 { 1066 KMessage::FieldHeader* header = _Header(); 1067 return header ? header->HasFixedElementSize() : false; 1068 } 1069 1070 1071 int32 1072 KMessageField::ElementSize() const 1073 { 1074 KMessage::FieldHeader* header = _Header(); 1075 return header ? header->elementSize : -1; 1076 } 1077 1078 1079 status_t 1080 KMessageField::AddElement(const void* data, int32 size) 1081 { 1082 KMessage::FieldHeader* header = _Header(); 1083 if (!header || !data) 1084 return B_BAD_VALUE; 1085 if (size < 0) { 1086 size = ElementSize(); 1087 if (size < 0) 1088 return B_BAD_VALUE; 1089 } 1090 return fMessage->_AddFieldData(this, data, size, 1); 1091 } 1092 1093 1094 status_t 1095 KMessageField::AddElements(const void* data, int32 count, int32 elementSize) 1096 { 1097 KMessage::FieldHeader* header = _Header(); 1098 if (!header || !data || count < 0) 1099 return B_BAD_VALUE; 1100 if (elementSize < 0) { 1101 elementSize = ElementSize(); 1102 if (elementSize < 0) 1103 return B_BAD_VALUE; 1104 } 1105 return fMessage->_AddFieldData(this, data, elementSize, count); 1106 } 1107 1108 1109 const void* 1110 KMessageField::ElementAt(int32 index, int32* size) const 1111 { 1112 KMessage::FieldHeader* header = _Header(); 1113 return header ? header->ElementAt(index, size) : NULL; 1114 } 1115 1116 1117 int32 1118 KMessageField::CountElements() const 1119 { 1120 KMessage::FieldHeader* header = _Header(); 1121 return header ? header->elementCount : 0; 1122 } 1123 1124 1125 void 1126 KMessageField::SetTo(KMessage* message, int32 headerOffset) 1127 { 1128 fMessage = message; 1129 fHeaderOffset = headerOffset; 1130 } 1131 1132 1133 KMessage::FieldHeader* 1134 KMessageField::_Header() const 1135 { 1136 return fMessage ? fMessage->_FieldHeaderForOffset(fHeaderOffset) : NULL; 1137 } 1138