1cf10934eSMichael Lotz/*
208a4536bSAxel Dörfler * Copyright 2005-2017 Haiku, Inc. All rights reserved.
3cf10934eSMichael Lotz * Distributed under the terms of the MIT License.
4cf10934eSMichael Lotz *
5cf10934eSMichael Lotz * Authors:
6be902ac4SJohn Scipione *		Michael Lotz, mmlr@mlotz.ch
7cf10934eSMichael Lotz */
83ba0ac74SAxel Dörfler
981147288SAxel Dörfler
10e4890297SAxel Dörfler#include <Message.h>
115dc45eb4SMichael Lotz#include <MessageAdapter.h>
12e4890297SAxel Dörfler#include <MessagePrivate.h>
13e4890297SAxel Dörfler#include <MessageUtils.h>
14cf10934eSMichael Lotz
159dbe170aSAxel Dörfler#include <DirectMessageTarget.h>
169dbe170aSAxel Dörfler#include <MessengerPrivate.h>
179dbe170aSAxel Dörfler#include <TokenSpace.h>
189dbe170aSAxel Dörfler#include <util/KMessage.h>
199dbe170aSAxel Dörfler
20b1008df2SStephan Aßmus#include <Alignment.h>
21cf10934eSMichael Lotz#include <Application.h>
22cf10934eSMichael Lotz#include <AppMisc.h>
23cf10934eSMichael Lotz#include <BlockCache.h>
24cf10934eSMichael Lotz#include <Entry.h>
257f9368caSlooncraz#include <GraphicsDefs.h>
269dbe170aSAxel Dörfler#include <MessageQueue.h>
27cf10934eSMichael Lotz#include <Messenger.h>
28cf10934eSMichael Lotz#include <Path.h>
29cf10934eSMichael Lotz#include <Point.h>
30cf10934eSMichael Lotz#include <Rect.h>
31cf10934eSMichael Lotz#include <String.h>
32cf0a957fSIngo Weinhold#include <StringList.h>
33cf10934eSMichael Lotz
34eb9b1980SIngo Weinhold#include <assert.h>
35e4890297SAxel Dörfler#include <ctype.h>
36e4890297SAxel Dörfler#include <stdio.h>
37ccaa095fSIngo Weinhold#include <stdlib.h>
38e4890297SAxel Dörfler#include <string.h>
39e4890297SAxel Dörfler
40071f9c3aSIngo Weinhold#include "tracing_config.h"
4190e3bbf0SIngo Weinhold	// kernel tracing configuration
42cf10934eSMichael Lotz
43d7a16b23SMichael Lotz//#define VERBOSE_DEBUG_OUTPUT
44d7a16b23SMichael Lotz#ifdef VERBOSE_DEBUG_OUTPUT
45d7a16b23SMichael Lotz#define DEBUG_FUNCTION_ENTER	\
46d7a16b23SMichael Lotz	debug_printf("msg thread: %ld; this: %p; header: %p; fields: %p;" \
47d7a16b23SMichael Lotz		" data: %p; what: 0x%08lx '%.4s'; line: %d; func: %s\n", \
48be902ac4SJohn Scipione		find_thread(NULL), this, fHeader, fFields, fData, what, (char*)&what, \
49d7a16b23SMichael Lotz		__LINE__, __PRETTY_FUNCTION__);
50d7a16b23SMichael Lotz
51d7a16b23SMichael Lotz#define DEBUG_FUNCTION_ENTER2	\
52d7a16b23SMichael Lotz	debug_printf("msg thread: %ld; line: %d: func: %s\n", find_thread(NULL), \
53d7a16b23SMichael Lotz		__LINE__, __PRETTY_FUNCTION__);
54d7a16b23SMichael Lotz#else
55d7a16b23SMichael Lotz#define DEBUG_FUNCTION_ENTER	/* nothing */
56d7a16b23SMichael Lotz#define DEBUG_FUNCTION_ENTER2	/* nothing */
57d7a16b23SMichael Lotz#endif
58cf10934eSMichael Lotz
596bf15ffcSIngo Weinhold#if BMESSAGE_TRACING
6090e3bbf0SIngo Weinhold#	define KTRACE(format...)	ktrace_printf(format)
6190e3bbf0SIngo Weinhold#else
62e3114809SAxel Dörfler#	define KTRACE(format...)	;
6390e3bbf0SIngo Weinhold#endif
6490e3bbf0SIngo Weinhold
6590e3bbf0SIngo Weinhold
66be902ac4SJohn Scipioneconst char* B_SPECIFIER_ENTRY = "specifiers";
67be902ac4SJohn Scipioneconst char* B_PROPERTY_ENTRY = "property";
68be902ac4SJohn Scipioneconst char* B_PROPERTY_NAME_ENTRY = "name";
69cf10934eSMichael Lotz
70cf10934eSMichael Lotz
71be902ac4SJohn Scipionestatic status_t handle_reply(port_id replyPort, int32* pCode,
72be902ac4SJohn Scipione	bigtime_t timeout, BMessage* reply);
73be902ac4SJohn Scipione
74cf10934eSMichael Lotz
75be25ae86SMichael Lotzextern "C" {
763ba0ac74SAxel Dörfler	// private os function to set the owning team of an area
77be902ac4SJohn Scipione	status_t _kern_transfer_area(area_id area, void** _address,
783ba0ac74SAxel Dörfler		uint32 addressSpec, team_id target);
79be25ae86SMichael Lotz}
80be25ae86SMichael Lotz
81cf10934eSMichael Lotz
82be902ac4SJohn ScipioneBBlockCache* BMessage::sMsgCache = NULL;
83cf10934eSMichael Lotzport_id BMessage::sReplyPorts[sNumReplyPorts];
8454cf3a72SIngo Weinholdint32 BMessage::sReplyPortInUse[sNumReplyPorts];
85cf10934eSMichael Lotz
86cf10934eSMichael Lotz
87d7a16b23SMichael Lotztemplate<typename Type>
88d7a16b23SMichael Lotzstatic void
89be902ac4SJohn Scipioneprint_to_stream_type(uint8* pointer)
903ba0ac74SAxel Dörfler{
91be902ac4SJohn Scipione	Type* item = (Type*)pointer;
923ba0ac74SAxel Dörfler	item->PrintToStream();
933ba0ac74SAxel Dörfler}
943ba0ac74SAxel Dörfler
953ba0ac74SAxel Dörfler
96d7a16b23SMichael Lotztemplate<typename Type>
97d7a16b23SMichael Lotzstatic void
98be902ac4SJohn Scipioneprint_type(const char* format, uint8* pointer)
993ba0ac74SAxel Dörfler{
100be902ac4SJohn Scipione	Type* item = (Type*)pointer;
101be902ac4SJohn Scipione	printf(format,* item,* item);
1023ba0ac74SAxel Dörfler}
1033ba0ac74SAxel Dörfler
1043ba0ac74SAxel Dörfler
105e6dc15caSStefano Ceccherinitemplate<typename Type>
106e6dc15caSStefano Ceccherinistatic void
107be902ac4SJohn Scipioneprint_type3(const char* format, uint8* pointer)
108e6dc15caSStefano Ceccherini{
109be902ac4SJohn Scipione	Type* item = (Type*)pointer;
110e6dc15caSStefano Ceccherini	printf(format, *item, *item, *item);
111e6dc15caSStefano Ceccherini}
112e6dc15caSStefano Ceccherini
113e6dc15caSStefano Ceccherini
1143ba0ac74SAxel Dörflerstatic status_t
115be902ac4SJohn Scipionehandle_reply(port_id replyPort, int32* _code, bigtime_t timeout,
116be902ac4SJohn Scipione	BMessage* reply)
1173ba0ac74SAxel Dörfler{
1183ba0ac74SAxel Dörfler	DEBUG_FUNCTION_ENTER2;
1193ba0ac74SAxel Dörfler	ssize_t size;
1203ba0ac74SAxel Dörfler	do {
1213ba0ac74SAxel Dörfler		size = port_buffer_size_etc(replyPort, B_RELATIVE_TIMEOUT, timeout);
1223ba0ac74SAxel Dörfler	} while (size == B_INTERRUPTED);
1233ba0ac74SAxel Dörfler
124d7a16b23SMichael Lotz	if (size < 0)
1253ba0ac74SAxel Dörfler		return size;
1263ba0ac74SAxel Dörfler
1273ba0ac74SAxel Dörfler	status_t result;
128be902ac4SJohn Scipione	char* buffer = (char*)malloc(size);
129a433b9feSMichael Lotz	if (buffer == NULL)
130a433b9feSMichael Lotz		return B_NO_MEMORY;
131a433b9feSMichael Lotz
1323ba0ac74SAxel Dörfler	do {
1333ba0ac74SAxel Dörfler		result = read_port(replyPort, _code, buffer, size);
1343ba0ac74SAxel Dörfler	} while (result == B_INTERRUPTED);
1353ba0ac74SAxel Dörfler
136d7a16b23SMichael Lotz	if (result < 0 || *_code != kPortMessageCode) {
1373ba0ac74SAxel Dörfler		free(buffer);
138d7a16b23SMichael Lotz		return result < 0 ? result : B_ERROR;
1393ba0ac74SAxel Dörfler	}
1403ba0ac74SAxel Dörfler
1413ba0ac74SAxel Dörfler	result = reply->Unflatten(buffer);
1423ba0ac74SAxel Dörfler	free(buffer);
1433ba0ac74SAxel Dörfler	return result;
1443ba0ac74SAxel Dörfler}
1453ba0ac74SAxel Dörfler
1463ba0ac74SAxel Dörfler
1473ba0ac74SAxel Dörfler//	#pragma mark -
1483ba0ac74SAxel Dörfler
1493ba0ac74SAxel Dörfler
150cf10934eSMichael LotzBMessage::BMessage()
151cf10934eSMichael Lotz{
152cf10934eSMichael Lotz	DEBUG_FUNCTION_ENTER;
153a433b9feSMichael Lotz	_InitCommon(true);
154cf10934eSMichael Lotz}
155cf10934eSMichael Lotz
1565dc45eb4SMichael Lotz
157be902ac4SJohn ScipioneBMessage::BMessage(BMessage* other)
1594ac06083SDarkWyrm	DEBUG_FUNCTION_ENTER;
160a433b9feSMichael Lotz	_InitCommon(false);
1614ac06083SDarkWyrm	*this = *other;
163cf10934eSMichael Lotz
1645dc45eb4SMichael Lotz
165cf10934eSMichael LotzBMessage::BMessage(uint32 _what)
166cf10934eSMichael Lotz{
167cf10934eSMichael Lotz	DEBUG_FUNCTION_ENTER;
168d761df9fSAdrien Destugues	if (_InitCommon(true))
169d761df9fSAdrien Destugues		fHeader->what = _what;
170d761df9fSAdrien Destugues	what = _what;
171cf10934eSMichael Lotz}
172cf10934eSMichael Lotz
173cf10934eSMichael Lotz
174be902ac4SJohn ScipioneBMessage::BMessage(const BMessage& other)
175cf10934eSMichael Lotz{
176cf10934eSMichael Lotz	DEBUG_FUNCTION_ENTER;
177a433b9feSMichael Lotz	_InitCommon(false);
178cf10934eSMichael Lotz	*this = other;
179cf10934eSMichael Lotz}
180cf10934eSMichael Lotz
181cf10934eSMichael Lotz
182cf10934eSMichael LotzBMessage::~BMessage()
183cf10934eSMichael Lotz{
184cf10934eSMichael Lotz	DEBUG_FUNCTION_ENTER;
185cf10934eSMichael Lotz	_Clear();
186cf10934eSMichael Lotz}
187cf10934eSMichael Lotz
188cf10934eSMichael Lotz
189be902ac4SJohn ScipioneBMessage&
190be902ac4SJohn ScipioneBMessage::operator=(const BMessage& other)
191cf10934eSMichael Lotz{
192cf10934eSMichael Lotz	DEBUG_FUNCTION_ENTER;
193721a0fe3SMichael Lotz
194cd15d8c3SPhilippe Saint-Pierre	if (this == &other)
195cd15d8c3SPhilippe Saint-Pierre		return *this;
1968f73c97dSStephan Aßmus
197cf10934eSMichael Lotz	_Clear();
198cf10934eSMichael Lotz
199be902ac4SJohn Scipione	fHeader = (message_header*)malloc(sizeof(message_header));
200d7a16b23SMichael Lotz	if (fHeader == NULL)
201d7a16b23SMichael Lotz		return *this;
202d7a16b23SMichael Lotz
2033270af3cSMichael Lotz	if (other.fHeader == NULL)
2043270af3cSMichael Lotz		return *this;
2053270af3cSMichael Lotz
206e4890297SAxel Dörfler	memcpy(fHeader, other.fHeader, sizeof(message_header));
207cf10934eSMichael Lotz
208c1c0c220SIngo Weinhold	// Clear some header flags inherited from the original message that don't
209c1c0c220SIngo Weinhold	// apply to the clone.
210c1c0c220SIngo Weinhold	fHeader->flags &= ~(MESSAGE_FLAG_REPLY_REQUIRED | MESSAGE_FLAG_REPLY_DONE
21259fa665dSMichael Lotz		| MESSAGE_FLAG_PASS_BY_AREA);
213c1c0c220SIngo Weinhold	// Note, that BeOS R5 seems to keep the reply info.
214c1c0c220SIngo Weinhold
215d7a16b23SMichael Lotz	if (fHeader->field_count > 0) {
216d7a16b23SMichael Lotz		size_t fieldsSize = fHeader->field_count * sizeof(field_header);
2173270af3cSMichael Lotz		if (other.fFields != NULL)
218be902ac4SJohn Scipione			fFields = (field_header*)malloc(fieldsSize);
2193270af3cSMichael Lotz
220d7a16b23SMichael Lotz		if (fFields == NULL) {
221d7a16b23SMichael Lotz			fHeader->field_count = 0;
222d7a16b23SMichael Lotz			fHeader->data_size = 0;
22345888dabSPhilippe Saint-Pierre		} else if (other.fFields != NULL)
224d7a16b23SMichael Lotz			memcpy(fFields, other.fFields, fieldsSize);
225cf10934eSMichael Lotz	}
226cf10934eSMichael Lotz
227e4890297SAxel Dörfler	if (fHeader->data_size > 0) {
2283270af3cSMichael Lotz		if (other.fData != NULL)
229be902ac4SJohn Scipione			fData = (uint8*)malloc(fHeader->data_size);
2303270af3cSMichael Lotz
231d7a16b23SMichael Lotz		if (fData == NULL) {
232d7a16b23SMichael Lotz			fHeader->field_count = 0;
233d7a16b23SMichael Lotz			free(fFields);
234d7a16b23SMichael Lotz			fFields = NULL;
23545888dabSPhilippe Saint-Pierre		} else if (other.fData != NULL)
236d7a16b23SMichael Lotz			memcpy(fData, other.fData, fHeader->data_size);
237cf10934eSMichael Lotz	}
238cf10934eSMichael Lotz
2395b62df9dSMichael Lotz	fHeader->what = what = other.what;
240d7a16b23SMichael Lotz	fHeader->message_area = -1;
241d7a16b23SMichael Lotz	fFieldsAvailable = 0;
242d7a16b23SMichael Lotz	fDataAvailable = 0;
243035eafc5SMichael Lotz
244cf10934eSMichael Lotz	return *this;
245cf10934eSMichael Lotz}
246cf10934eSMichael Lotz
247cf10934eSMichael Lotz
248be902ac4SJohn Scipionevoid*
249cf10934eSMichael LotzBMessage::operator new(size_t size)
250cf10934eSMichael Lotz{
251721a0fe3SMichael Lotz	DEBUG_FUNCTION_ENTER2;
252009fd257SAxel Dörfler	return sMsgCache->Get(size);
253009fd257SAxel Dörfler}
254009fd257SAxel Dörfler
255009fd257SAxel Dörfler
256be902ac4SJohn Scipionevoid*
257be902ac4SJohn ScipioneBMessage::operator new(size_t size, const std::nothrow_t& noThrow)
258009fd257SAxel Dörfler{
259009fd257SAxel Dörfler	DEBUG_FUNCTION_ENTER2;
260009fd257SAxel Dörfler	return sMsgCache->Get(size);
261cf10934eSMichael Lotz}
262cf10934eSMichael Lotz
263cf10934eSMichael Lotz
264be902ac4SJohn Scipionevoid*
265be902ac4SJohn ScipioneBMessage::operator new(size_t, void* pointer)
266cf10934eSMichael Lotz{
267721a0fe3SMichael Lotz	DEBUG_FUNCTION_ENTER2;
268cf10934eSMichael Lotz	return pointer;
269cf10934eSMichael Lotz}
270cf10934eSMichael Lotz
271cf10934eSMichael Lotz
272cf10934eSMichael Lotzvoid
273be902ac4SJohn ScipioneBMessage::operator delete(void* pointer, size_t size)
274cf10934eSMichael Lotz{
275721a0fe3SMichael Lotz	DEBUG_FUNCTION_ENTER2;
2766e24fc67SAdrien Destugues	if (pointer == NULL)
2776e24fc67SAdrien Destugues		return;
278cf10934eSMichael Lotz	sMsgCache->Save(pointer, size);
279cf10934eSMichael Lotz}
280cf10934eSMichael Lotz
281cf10934eSMichael Lotz
2825b25b917SMichael Lotzbool
283be902ac4SJohn ScipioneBMessage::HasSameData(const BMessage& other, bool ignoreFieldOrder,
2845b25b917SMichael Lotz	bool deep) const
2855b25b917SMichael Lotz{
2865b25b917SMichael Lotz	if (this == &other)
2875b25b917SMichael Lotz		return true;
2885b25b917SMichael Lotz
2893270af3cSMichael Lotz	if (fHeader == NULL)
2903270af3cSMichael Lotz		return other.fHeader == NULL;
2913270af3cSMichael Lotz
2925b25b917SMichael Lotz	if (fHeader->field_count != other.fHeader->field_count)
2935b25b917SMichael Lotz		return false;
2945b25b917SMichael Lotz
295d7a16b23SMichael Lotz	for (uint32 i = 0; i < fHeader->field_count; i++) {
296be902ac4SJohn Scipione		field_header* field = &fFields[i];
297be902ac4SJohn Scipione		field_header* otherField = NULL;
2985b25b917SMichael Lotz
299be902ac4SJohn Scipione		const char* name = (const char*)fData + field->offset;
3005b25b917SMichael Lotz		if (ignoreFieldOrder) {
3015b25b917SMichael Lotz			if (other._FindField(name, B_ANY_TYPE, &otherField) != B_OK)
3025b25b917SMichael Lotz				return false;
3035b25b917SMichael Lotz		} else {
3045b25b917SMichael Lotz			otherField = &other.fFields[i];
3055b25b917SMichael Lotz			if (otherField->name_length != field->name_length)
3065b25b917SMichael Lotz				return false;
3075b25b917SMichael Lotz
308be902ac4SJohn Scipione			const char* otherName = (const char*)other.fData
3095b25b917SMichael Lotz				+ otherField->offset;
3105b25b917SMichael Lotz			if (strncmp(name, otherName, field->name_length) != 0)
3115b25b917SMichael Lotz				return false;
3125b25b917SMichael Lotz		}
3135b25b917SMichael Lotz
3143270af3cSMichael Lotz		if (otherField->type != field->type
3153270af3cSMichael Lotz			|| otherField->count != field->count) {
3165b25b917SMichael Lotz			return false;
3173270af3cSMichael Lotz		}
3185b25b917SMichael Lotz
319be902ac4SJohn Scipione		uint8* data = fData + field->offset + field->name_length;
320be902ac4SJohn Scipione		uint8* otherData = other.fData + otherField->offset
3215b25b917SMichael Lotz			+ otherField->name_length;
3225b25b917SMichael Lotz
3235b25b917SMichael Lotz		bool needsMemCompare = true;
3245b25b917SMichael Lotz		if (deep && field->type == B_MESSAGE_TYPE) {
3255b25b917SMichael Lotz			BMessage message, otherMessage;
326be902ac4SJohn Scipione			if (message.Unflatten((const char*)data) == B_OK
327be902ac4SJohn Scipione				&& otherMessage.Unflatten((const char*)otherData) == B_OK) {
32860a068c8SMichael Lotz				if (!message.HasSameData(ignoreFieldOrder, deep))
3295b25b917SMichael Lotz					return false;
3305b25b917SMichael Lotz				needsMemCompare = false;
3315b25b917SMichael Lotz			}
3325b25b917SMichael Lotz		}
3335b25b917SMichael Lotz
3345b25b917SMichael Lotz		if (needsMemCompare) {
3355b25b917SMichael Lotz			if (otherField->data_size != field->data_size)
3365b25b917SMichael Lotz				return false;
3375b25b917SMichael Lotz			if (memcmp(data, otherData, field->data_size) != 0)
3385b25b917SMichael Lotz				return false;
3395b25b917SMichael Lotz		}
3405b25b917SMichael Lotz	}
3415b25b917SMichael Lotz
3425b25b917SMichael Lotz	return true;
3435b25b917SMichael Lotz}
3445b25b917SMichael Lotz
3455b25b917SMichael Lotz
346cf10934eSMichael Lotzstatus_t
347a433b9feSMichael LotzBMessage::_InitCommon(bool initHeader)
348cf10934eSMichael Lotz{
349cf10934eSMichael Lotz	DEBUG_FUNCTION_ENTER;
350cf10934eSMichael Lotz	what = 0;
351cf10934eSMichael Lotz
352cf10934eSMichael Lotz	fHeader = NULL;
353cf10934eSMichael Lotz	fFields = NULL;
354cf10934eSMichael Lotz	fData = NULL;
355cf10934eSMichael Lotz
356d7a16b23SMichael Lotz	fFieldsAvailable = 0;
357d7a16b23SMichael Lotz	fDataAvailable = 0;
358d7a16b23SMichael Lotz
359cf10934eSMichael Lotz	fOriginal = NULL;
360cf10934eSMichael Lotz	fQueueLink = NULL;
361035eafc5SMichael Lotz
362e5150e28SIngo Weinhold	fArchivingPointer = NULL;
363e5150e28SIngo Weinhold
364a433b9feSMichael Lotz	if (initHeader)
365a433b9feSMichael Lotz		return _InitHeader();
366a433b9feSMichael Lotz
367a433b9feSMichael Lotz	return B_OK;
368cf10934eSMichael Lotz}
369cf10934eSMichael Lotz
370cf10934eSMichael Lotz
371cf10934eSMichael Lotzstatus_t
372cf10934eSMichael LotzBMessage::_InitHeader()
373cf10934eSMichael Lotz{
374cf10934eSMichael Lotz	DEBUG_FUNCTION_ENTER;
375d7a16b23SMichael Lotz	if (fHeader == NULL) {
376be902ac4SJohn Scipione		fHeader = (message_header*)malloc(sizeof(message_header));
377d7a16b23SMichael Lotz		if (fHeader == NULL)
378d7a16b23SMichael Lotz			return B_NO_MEMORY;
379d7a16b23SMichael Lotz	}
380d7a16b23SMichael Lotz
381b0bc48fbSAxel Dörfler	memset(fHeader, 0, sizeof(message_header) - sizeof(fHeader->hash_table));
382cf10934eSMichael Lotz
3835dc45eb4SMichael Lotz	fHeader->format = MESSAGE_FORMAT_HAIKU;
384cf10934eSMichael Lotz	fHeader->flags = MESSAGE_FLAG_VALID;
3855b62df9dSMichael Lotz	fHeader->what = what;
386e4890297SAxel Dörfler	fHeader->current_specifier = -1;
387a433b9feSMichael Lotz	fHeader->message_area = -1;
388cf10934eSMichael Lotz
389cf10934eSMichael Lotz	fHeader->target = B_NULL_TOKEN;
390e4890297SAxel Dörfler	fHeader->reply_target = B_NULL_TOKEN;
391e4890297SAxel Dörfler	fHeader->reply_port = -1;
392e4890297SAxel Dörfler	fHeader->reply_team = -1;
393cf10934eSMichael Lotz
394cf10934eSMichael Lotz	// initializing the hash table to -1 because 0 is a valid index
395e4890297SAxel Dörfler	fHeader->hash_table_size = MESSAGE_BODY_HASH_TABLE_SIZE;
396e4890297SAxel Dörfler	memset(&fHeader->hash_table, 255, sizeof(fHeader->hash_table));
397cf10934eSMichael Lotz	return B_OK;
398cf10934eSMichael Lotz}
399cf10934eSMichael Lotz
400cf10934eSMichael Lotz
401cf10934eSMichael Lotzstatus_t
402cf10934eSMichael LotzBMessage::_Clear()
403cf10934eSMichael Lotz{
404721a0fe3SMichael Lotz	DEBUG_FUNCTION_ENTER;
405d7a16b23SMichael Lotz	if (fHeader != NULL) {
406a433b9feSMichael Lotz		// We're going to destroy all information of this message. If there's
407a433b9feSMichael Lotz		// still someone waiting for a reply to this message, we have to send
408a433b9feSMichael Lotz		// one now.
409a433b9feSMichael Lotz		if (IsSourceWaiting())
410a433b9feSMichael Lotz			SendReply(B_NO_REPLY);
411cd9660c7SIngo Weinhold
412a433b9feSMichael Lotz		if (fHeader->message_area >= 0)
413a433b9feSMichael Lotz			_Dereference();
414a433b9feSMichael Lotz
415a433b9feSMichael Lotz		free(fHeader);
416a433b9feSMichael Lotz		fHeader = NULL;
417a433b9feSMichael Lotz	}
418cf10934eSMichael Lotz
419cf10934eSMichael Lotz	free(fFields);
420cf10934eSMichael Lotz	fFields = NULL;
421cf10934eSMichael Lotz	free(fData);
422cf10934eSMichael Lotz	fData = NULL;
423cf10934eSMichael Lotz
424e5150e28SIngo Weinhold	fArchivingPointer = NULL;
425e5150e28SIngo Weinhold
426d7a16b23SMichael Lotz	fFieldsAvailable = 0;
427d7a16b23SMichael Lotz	fDataAvailable = 0;
428d7a16b23SMichael Lotz
429721a0fe3SMichael Lotz	delete fOriginal;
430721a0fe3SMichael Lotz	fOriginal = NULL;
431721a0fe3SMichael Lotz
432cf10934eSMichael Lotz	return B_OK;
433cf10934eSMichael Lotz}
434cf10934eSMichael Lotz
435cf10934eSMichael Lotz
436cf10934eSMichael Lotzstatus_t
437be902ac4SJohn ScipioneBMessage::GetInfo(type_code typeRequested, int32 index, char** nameFound,
438be902ac4SJohn Scipione	type_code* typeFound, int32* countFound) const
439cf10934eSMichael Lotz{
440cf10934eSMichael Lotz	DEBUG_FUNCTION_ENTER;
4413270af3cSMichael Lotz	if (fHeader == NULL)
4423270af3cSMichael Lotz		return B_NO_INIT;
4433270af3cSMichael Lotz
444d7a16b23SMichael Lotz	if (index < 0 || (uint32)index >= fHeader->field_count)
445d7a16b23SMichael Lotz		return B_BAD_INDEX;
446cf10934eSMichael Lotz
447d7a16b23SMichael Lotz	if (typeRequested == B_ANY_TYPE) {
4483270af3cSMichael Lotz		if (nameFound != NULL)
449be902ac4SJohn Scipione			*nameFound = (char*)fData + fFields[index].offset;
4503270af3cSMichael Lotz		if (typeFound != NULL)
4514ad46aa9SAxel Dörfler			*typeFound = fFields[index].type;
4523270af3cSMichael Lotz		if (countFound != NULL)
453cf10934eSMichael Lotz			*countFound = fFields[index].count;
454cf10934eSMichael Lotz		return B_OK;
455cf10934eSMichael Lotz	}
456cf10934eSMichael Lotz
457cf10934eSMichael Lotz	int32 counter = -1;
458be902ac4SJohn Scipione	field_header* field = fFields;
459d7a16b23SMichael Lotz	for (uint32 i = 0; i < fHeader->field_count; i++, field++) {
460cf10934eSMichael Lotz		if (field->type == typeRequested)
461cf10934eSMichael Lotz			counter++;
462cf10934eSMichael Lotz
463cf10934eSMichael Lotz		if (counter == index) {
4643270af3cSMichael Lotz			if (nameFound != NULL)
465be902ac4SJohn Scipione				*nameFound = (char*)fData + field->offset;
4663270af3cSMichael Lotz			if (typeFound != NULL)
4674ad46aa9SAxel Dörfler				*typeFound = field->type;
4683270af3cSMichael Lotz			if (countFound != NULL)
469cf10934eSMichael Lotz				*countFound = field->count;
470cf10934eSMichael Lotz			return B_OK;
471cf10934eSMichael Lotz		}
472cf10934eSMichael Lotz	}
473cf10934eSMichael Lotz
474cf10934eSMichael Lotz	if (counter == -1)
475cf10934eSMichael Lotz		return B_BAD_TYPE;
476cf10934eSMichael Lotz
477cf10934eSMichael Lotz	return B_BAD_INDEX;
478cf10934eSMichael Lotz}
479cf10934eSMichael Lotz
480cf10934eSMichael Lotz
481cf10934eSMichael Lotzstatus_t
482be902ac4SJohn ScipioneBMessage::GetInfo(const char* name, type_code* typeFound,
483be902ac4SJohn Scipione	int32* countFound) const
484cf10934eSMichael Lotz{
485cf10934eSMichael Lotz	DEBUG_FUNCTION_ENTER;
4863270af3cSMichael Lotz	if (countFound != NULL)
487cf10934eSMichael Lotz		*countFound = 0;
488cf10934eSMichael Lotz
489be902ac4SJohn Scipione	field_header* field = NULL;
490cf10934eSMichael Lotz	status_t result = _FindField(name, B_ANY_TYPE, &field);
4913270af3cSMichael Lotz	if (result != B_OK)
492cf10934eSMichael Lotz		return result;
493cf10934eSMichael Lotz
4943270af3cSMichael Lotz	if (typeFound != NULL)
4954ad46aa9SAxel Dörfler		*typeFound = field->type;
4963270af3cSMichael Lotz	if (countFound != NULL)
497cf10934eSMichael Lotz		*countFound = field->count;
498cf10934eSMichael Lotz
499cf10934eSMichael Lotz	return B_OK;
500cf10934eSMichael Lotz}
501cf10934eSMichael Lotz
502cf10934eSMichael Lotz
503cf10934eSMichael Lotzstatus_t
504be902ac4SJohn ScipioneBMessage::GetInfo(const char* name, type_code* typeFound, bool* fixedSize)
505cf10934eSMichael Lotz	const
506cf10934eSMichael Lotz{
507cf10934eSMichael Lotz	DEBUG_FUNCTION_ENTER;
508be902ac4SJohn Scipione	field_header* field = NULL;
509cf10934eSMichael Lotz	status_t result = _FindField(name, B_ANY_TYPE, &field);
5103270af3cSMichael Lotz	if (result != B_OK)
511cf10934eSMichael Lotz		return result;
512cf10934eSMichael Lotz
5133270af3cSMichael Lotz	if (typeFound != NULL)
5144ad46aa9SAxel Dörfler		*typeFound = field->type;
5153270af3cSMichael Lotz	if (fixedSize != NULL)
516d7a16b23SMichael Lotz		*fixedSize = (field->flags & FIELD_FLAG_FIXED_SIZE) != 0;
517cf10934eSMichael Lotz
518cf10934eSMichael Lotz	return B_OK;
519cf10934eSMichael Lotz}
520cf10934eSMichael Lotz
521cf10934eSMichael Lotz
5222b526613SStephan Aßmusstatus_t
523be902ac4SJohn ScipioneBMessage::GetInfo(const char* name, type_code* typeFound, int32* countFound,
524be902ac4SJohn Scipione	bool* fixedSize) const
5252b526613SStephan Aßmus{
5262b526613SStephan Aßmus	DEBUG_FUNCTION_ENTER;
527be902ac4SJohn Scipione	field_header* field = NULL;
5282b526613SStephan Aßmus	status_t result = _FindField(name, B_ANY_TYPE, &field);
5293270af3cSMichael Lotz	if (result != B_OK)
5302b526613SStephan Aßmus		return result;
5312b526613SStephan Aßmus
5323270af3cSMichael Lotz	if (typeFound != NULL)
5332b526613SStephan Aßmus		*typeFound = field->type;
5343270af3cSMichael Lotz	if (countFound != NULL)
5352b526613SStephan Aßmus		*countFound = field->count;
5363270af3cSMichael Lotz	if (fixedSize != NULL)
5372b526613SStephan Aßmus		*fixedSize = (field->flags & FIELD_FLAG_FIXED_SIZE) != 0;
5382b526613SStephan Aßmus
5392b526613SStephan Aßmus	return B_OK;
5402b526613SStephan Aßmus}
5412b526613SStephan Aßmus
5422b526613SStephan Aßmus
543cf10934eSMichael Lotzint32
544cf10934eSMichael LotzBMessage::CountNames(type_code type) const
545cf10934eSMichael Lotz{
546cf10934eSMichael Lotz	DEBUG_FUNCTION_ENTER;
5473270af3cSMichael Lotz	if (fHeader == NULL)
5483270af3cSMichael Lotz		return 0;
5493270af3cSMichael Lotz
550cf10934eSMichael Lotz	if (type == B_ANY_TYPE)
551e4890297SAxel Dörfler		return fHeader->field_count;
552cf10934eSMichael Lotz
553cf10934eSMichael Lotz	int32 count = 0;
554be902ac4SJohn Scipione	field_header* field = fFields;
555d7a16b23SMichael Lotz	for (uint32 i = 0; i < fHeader->field_count; i++, field++) {
556cf10934eSMichael Lotz		if (field->type == type)
557cf10934eSMichael Lotz			count++;
558cf10934eSMichael Lotz	}
559cf10934eSMichael Lotz
560cf10934eSMichael Lotz	return count;
561cf10934eSMichael Lotz}
562cf10934eSMichael Lotz
563cf10934eSMichael Lotz
564cf10934eSMichael Lotzbool
565cf10934eSMichael LotzBMessage::IsEmpty() const
566cf10934eSMichael Lotz{
567cf10934eSMichael Lotz	DEBUG_FUNCTION_ENTER;
5683270af3cSMichael Lotz	return fHeader == NULL || fHeader->field_count == 0;
569cf10934eSMichael Lotz}
570cf10934eSMichael Lotz
571cf10934eSMichael Lotz
572cf10934eSMichael Lotzbool
573cf10934eSMichael LotzBMessage::IsSystem() const
574cf10934eSMichael Lotz{
575cf10934eSMichael Lotz	DEBUG_FUNCTION_ENTER;
576cf10934eSMichael Lotz	char a = char(what >> 24);
577cf10934eSMichael Lotz	char b = char(what >> 16);
578cf10934eSMichael Lotz	char c = char(what >> 8);
579cf10934eSMichael Lotz	char d = char(what);
580cf10934eSMichael Lotz
581cf10934eSMichael Lotz	// The BeBook says:
582cf10934eSMichael Lotz	//		... we've adopted a strict convention for assigning values to all
583cf10934eSMichael Lotz	//		Be-defined constants.  The value assigned will always be formed by
584cf10934eSMichael Lotz	//		combining four characters into a multicharacter constant, with the
585cf10934eSMichael Lotz	//		characters limited to uppercase letters and the underbar
586cf10934eSMichael Lotz	// Between that and what's in AppDefs.h, this algo seems like a safe bet:
587cf10934eSMichael Lotz	if (a == '_' && isupper(b) && isupper(c) && isupper(d))
588cf10934eSMichael Lotz		return true;
589cf10934eSMichael Lotz
590cf10934eSMichael Lotz	return false;
591cf10934eSMichael Lotz}
592cf10934eSMichael Lotz
593cf10934eSMichael Lotz
594cf10934eSMichael Lotzbool
595cf10934eSMichael LotzBMessage::IsReply() const
596cf10934eSMichael Lotz{
597cf10934eSMichael Lotz	DEBUG_FUNCTION_ENTER;
5983270af3cSMichael Lotz	return fHeader != NULL && (fHeader->flags & MESSAGE_FLAG_IS_REPLY) != 0;
599cf10934eSMichael Lotz}
600cf10934eSMichael Lotz
601cf10934eSMichael Lotz
60267bdea52SJérôme Duvalvoid
60367bdea52SJérôme DuvalBMessage::PrintToStream() const
6044ceb1e51SAxel Dörfler{
60567bdea52SJérôme Duval	_PrintToStream("");
60667bdea52SJérôme Duval	printf("}\n");
6074ceb1e51SAxel Dörfler}
608cf10934eSMichael Lotz
609cf10934eSMichael Lotz
610cf10934eSMichael Lotzvoid
611be902ac4SJohn ScipioneBMessage::_PrintToStream(const char* indent) const
612cf10934eSMichael Lotz{
613cf10934eSMichael Lotz	DEBUG_FUNCTION_ENTER;
614cf10934eSMichael Lotz
615cf10934eSMichael Lotz	int32 value = B_BENDIAN_TO_HOST_INT32(what);
61667bdea52SJérôme Duval	printf("BMessage(");
617be902ac4SJohn Scipione	if (isprint(*(char*)&value))
618be902ac4SJohn Scipione		printf("'%.4s'", (char*)&value);
619d7a16b23SMichael Lotz	else
62041975f20SIngo Weinhold		printf("0x%" B_PRIx32, what);
62167bdea52SJérôme Duval	printf(") {\n");
6225dc45eb4SMichael Lotz
623d7a16b23SMichael Lotz	if (fHeader == NULL || fFields == NULL || fData == NULL)
624d7a16b23SMichael Lotz		return;
625d7a16b23SMichael Lotz
626be902ac4SJohn Scipione	field_header* field = fFields;
627d7a16b23SMichael Lotz	for (uint32 i = 0; i < fHeader->field_count; i++, field++) {
628cf10934eSMichael Lotz		value = B_BENDIAN_TO_HOST_INT32(field->type);
629cf10934eSMichael Lotz		ssize_t size = 0;
630d7a16b23SMichael Lotz		if ((field->flags & FIELD_FLAG_FIXED_SIZE) != 0 && field->count > 0)
631e4890297SAxel Dörfler			size = field->data_size / field->count;
632cf10934eSMichael Lotz
633be902ac4SJohn Scipione		uint8* pointer = fData + field->offset + field->name_length;
634d7a16b23SMichael Lotz		for (uint32 j = 0; j < field->count; j++) {
63567bdea52SJérôme Duval			if (field->count == 1) {
63667bdea52SJérôme Duval				printf("%s        %s = ", indent,
637be902ac4SJohn Scipione					(char*)(fData + field->offset));
63867bdea52SJérôme Duval			} else {
63941975f20SIngo Weinhold				printf("%s        %s[%" B_PRIu32 "] = ", indent,
640be902ac4SJohn Scipione					(char*)(fData + field->offset), j);
64167bdea52SJérôme Duval			}
64267bdea52SJérôme Duval
64317ec4668SMichael Lotz			if ((field->flags & FIELD_FLAG_FIXED_SIZE) == 0) {
644be902ac4SJohn Scipione				size = *(uint32*)pointer;
64517ec4668SMichael Lotz				pointer += sizeof(uint32);
64617ec4668SMichael Lotz			}
64717ec4668SMichael Lotz
64867bdea52SJérôme Duval			switch (field->type) {
64967bdea52SJérôme Duval				case B_RECT_TYPE:
650d7a16b23SMichael Lotz					print_to_stream_type<BRect>(pointer);
65167bdea52SJérôme Duval					break;
652cf10934eSMichael Lotz
65367bdea52SJérôme Duval				case B_POINT_TYPE:
654d7a16b23SMichael Lotz					print_to_stream_type<BPoint>(pointer);
65567bdea52SJérôme Duval					break;
65667bdea52SJérôme Duval
657d7a16b23SMichael Lotz				case B_STRING_TYPE:
658e8e5e0caSStephan Aßmus					printf("string(\"%.*s\", %ld bytes)\n", (int)size,
659be902ac4SJohn Scipione						(char*)pointer, (long)size);
66067bdea52SJérôme Duval					break;
661cf10934eSMichael Lotz
66267bdea52SJérôme Duval				case B_INT8_TYPE:
663393127dfSStefano Ceccherini					print_type3<int8>("int8(0x%hx or %d or '%c')\n",
664e6dc15caSStefano Ceccherini						pointer);
665d7a16b23SMichael Lotz					break;
666d7a16b23SMichael Lotz
667d7a16b23SMichael Lotz				case B_UINT8_TYPE:
668393127dfSStefano Ceccherini					print_type3<uint8>("uint8(0x%hx or %u or '%c')\n",
669d7a16b23SMichael Lotz						pointer);
67067bdea52SJérôme Duval					break;
67167bdea52SJérôme Duval
67267bdea52SJérôme Duval				case B_INT16_TYPE:
673d7a16b23SMichael Lotz					print_type<int16>("int16(0x%x or %d)\n", pointer);
674d7a16b23SMichael Lotz					break;
675d7a16b23SMichael Lotz
676d7a16b23SMichael Lotz				case B_UINT16_TYPE:
677d7a16b23SMichael Lotz					print_type<uint16>("uint16(0x%x or %u\n", pointer);
67867bdea52SJérôme Duval					break;
67967bdea52SJérôme Duval
68067bdea52SJérôme Duval				case B_INT32_TYPE:
681d7a16b23SMichael Lotz					print_type<int32>("int32(0x%lx or %ld)\n", pointer);
682d7a16b23SMichael Lotz					break;
683d7a16b23SMichael Lotz
684d7a16b23SMichael Lotz				case B_UINT32_TYPE:
685d7a16b23SMichael Lotz					print_type<uint32>("uint32(0x%lx or %lu\n", pointer);
68667bdea52SJérôme Duval					break;
68767bdea52SJérôme Duval
68867bdea52SJérôme Duval				case B_INT64_TYPE:
689d7a16b23SMichael Lotz					print_type<int64>("int64(0x%Lx or %Ld)\n", pointer);
690d7a16b23SMichael Lotz					break;
691d7a16b23SMichael Lotz