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