1/*
2 * Copyright 2005-2010, 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#ifndef _MESSAGE_PRIVATE_H_
9#define _MESSAGE_PRIVATE_H_
10
11#include <Message.h>
12#include <Messenger.h>
13#include <MessengerPrivate.h>
14#include <TokenSpace.h>
15
16
17#define MESSAGE_BODY_HASH_TABLE_SIZE	5
18#define MAX_DATA_PREALLOCATION			B_PAGE_SIZE * 10
19#define MAX_FIELD_PREALLOCATION			50
20
21
22static const int32 kPortMessageCode = 'pjpp';
23
24
25enum {
26	MESSAGE_FLAG_VALID = 0x0001,
27	MESSAGE_FLAG_REPLY_REQUIRED = 0x0002,
28	MESSAGE_FLAG_REPLY_DONE = 0x0004,
29	MESSAGE_FLAG_IS_REPLY = 0x0008,
30	MESSAGE_FLAG_WAS_DELIVERED = 0x0010,
31	MESSAGE_FLAG_HAS_SPECIFIERS = 0x0020,
32	MESSAGE_FLAG_WAS_DROPPED = 0x0040,
33	MESSAGE_FLAG_PASS_BY_AREA = 0x0080
34};
35
36
37enum {
38	FIELD_FLAG_VALID = 0x0001,
39	FIELD_FLAG_FIXED_SIZE = 0x0002,
40};
41
42
43struct BMessage::field_header {
44	uint16		flags;
45	uint16		name_length;
46	type_code	type;
47	uint32		count;
48	uint32		data_size;
49	uint32		offset;
50	int32		next_field;
51} _PACKED;
52
53
54struct BMessage::message_header {
55	uint32		format;
56	uint32		what;
57	uint32		flags;
58
59	int32		target;
60	int32		current_specifier;
61	area_id		message_area;
62
63	// reply info
64	port_id		reply_port;
65	int32		reply_target;
66	team_id		reply_team;
67
68	// body info
69	uint32		data_size;
70	uint32		field_count;
71	uint32		hash_table_size;
72	int32		hash_table[MESSAGE_BODY_HASH_TABLE_SIZE];
73
74	/*	The hash table does contain indexes into the field list and
75		not direct offsets to the fields. This has the advantage
76		of not needing to update offsets in two locations.
77		The hash table must be reevaluated when we remove a field
78		though.
79	*/
80} _PACKED;
81
82
83class BMessage::Private {
84	public:
85		Private(BMessage *msg)
86			:
87			fMessage(msg)
88		{
89		}
90
91		Private(BMessage &msg)
92			:
93			fMessage(&msg)
94		{
95		}
96
97		void
98		SetTarget(int32 token)
99		{
100			fMessage->fHeader->target = token;
101		}
102
103		void
104		SetReply(BMessenger messenger)
105		{
106			BMessenger::Private messengerPrivate(messenger);
107			fMessage->fHeader->reply_port = messengerPrivate.Port();
108			fMessage->fHeader->reply_target = messengerPrivate.Token();
109			fMessage->fHeader->reply_team = messengerPrivate.Team();
110		}
111
112		void
113		SetReply(team_id team, port_id port, int32 target)
114		{
115			fMessage->fHeader->reply_port = port;
116			fMessage->fHeader->reply_target = target;
117			fMessage->fHeader->reply_team = team;
118		}
119
120		int32
121		GetTarget()
122		{
123			return fMessage->fHeader->target;
124		}
125
126		bool
127		UsePreferredTarget()
128		{
129			return fMessage->fHeader->target == B_PREFERRED_TOKEN;
130		}
131
132		void
133		SetWasDropped(bool wasDropped)
134		{
135			if (wasDropped)
136				fMessage->fHeader->flags |= MESSAGE_FLAG_WAS_DROPPED;
137			else
138				fMessage->fHeader->flags &= ~MESSAGE_FLAG_WAS_DROPPED;
139		}
140
141		status_t
142		Clear()
143		{
144			return fMessage->_Clear();
145		}
146
147		status_t
148		InitHeader()
149		{
150			return fMessage->_InitHeader();
151		}
152
153		BMessage::message_header*
154		GetMessageHeader()
155		{
156			return fMessage->fHeader;
157		}
158
159		BMessage::field_header*
160		GetMessageFields()
161		{
162			return fMessage->fFields;
163		}
164
165		uint8*
166		GetMessageData()
167		{
168			return fMessage->fData;
169		}
170
171		status_t
172		FlattenToArea(message_header **header) const
173		{
174			return fMessage->_FlattenToArea(header);
175		}
176
177		status_t
178		SendMessage(port_id port, team_id portOwner, int32 token,
179			bigtime_t timeout, bool replyRequired, BMessenger &replyTo) const
180		{
181			return fMessage->_SendMessage(port, portOwner, token,
182				timeout, replyRequired, replyTo);
183		}
184
185		status_t
186		SendMessage(port_id port, team_id portOwner, int32 token,
187			BMessage *reply, bigtime_t sendTimeout,
188			bigtime_t replyTimeout) const
189		{
190			return fMessage->_SendMessage(port, portOwner, token,
191				reply, sendTimeout, replyTimeout);
192		}
193
194		void*
195		ArchivingPointer()
196		{
197			return fMessage->fArchivingPointer;
198		}
199
200		void
201		SetArchivingPointer(void* pointer)
202		{
203			fMessage->fArchivingPointer = pointer;
204		}
205
206		// static methods
207
208		static status_t
209		SendFlattenedMessage(void *data, int32 size, port_id port,
210			int32 token, bigtime_t timeout)
211		{
212			return BMessage::_SendFlattenedMessage(data, size,
213				port, token, timeout);
214		}
215
216		static void
217		StaticInit()
218		{
219			BMessage::_StaticInit();
220		}
221
222		static void
223		StaticReInitForkedChild()
224		{
225			BMessage::_StaticReInitForkedChild();
226		}
227
228		static void
229		StaticCleanup()
230		{
231			BMessage::_StaticCleanup();
232		}
233
234		static void
235		StaticCacheCleanup()
236		{
237			BMessage::_StaticCacheCleanup();
238		}
239
240	private:
241		BMessage* fMessage;
242};
243
244#endif	// _MESSAGE_PRIVATE_H_
245