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