Fawkes API Fawkes Development Version
message.cpp
1
2/***************************************************************************
3 * message.cpp - Fawkes network message
4 *
5 * Created: Tue Nov 21 16:21:28 2006
6 * Copyright 2006 Tim Niemueller [www.niemueller.de]
7 *
8 ****************************************************************************/
9
10/* This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version. A runtime exception applies to
14 * this software (see LICENSE.GPL_WRE file mentioned below for details).
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Library General Public License for more details.
20 *
21 * Read the full text in the LICENSE.GPL_WRE file in the doc directory.
22 */
23
24#include <core/exception.h>
25#include <netcomm/fawkes/message.h>
26#include <netcomm/fawkes/message_content.h>
27#include <netinet/in.h>
28
29#include <cstddef>
30#include <cstdlib>
31#include <cstring>
32
33namespace fawkes {
34
35/** @class FawkesNetworkMessageTooBigException message.h <netcomm/fawkes/message.h>
36 * The given message size exceeds the limit.
37 * The message payload can only be of a certain size, which is limited especially
38 * by the data type used for the payload size in the header. If you try to assign too
39 * much data to a message this exception is thrown.
40 * @ingroup NetComm
41 * @author Tim Niemueller
42 */
43
44/** Constructor.
45 * @param message_size size of the message that is too big
46 */
48: Exception("Network message size too big")
49{
51 append("Tried to create message of %l bytes, while only %l bytes allowed",
52 message_size,
53 sizeof(fmh.payload_size));
54}
55
56/** @class FawkesNetworkMessage message.h <netcomm/fawkes/message.h>
57 * Representation of a message that is sent over the network.
58 *
59 * For the basic format of a message see fawkes_message_t. This class
60 * provides access to all of the fields in a convenient manner. Additionally
61 * it can handle the client ID, which is either the sender or the recipient
62 * of a message (depending if it's in an inbound or outbound queue).
63 *
64 * Note that the message takes over ownership of the payload. This means that it
65 * is internally held and freed (using free()) if the message is deleted (if the
66 * reference count reaches zero). Because of this you can NOT supply a local variable.
67 * The following code is illegal:
68 * @code
69 * unsigned int u = 0;
70 * FawkesNetworkMessage *m = new FawkesNetworkMessage(clid, cid, msgid, &u, sizeof(u));
71 * @endcode
72 * Rather you have to use the following code:
73 * @code
74 * unsigned int *u = (unsigned int *)malloc(sizeof(unsigned int));
75 * *u = 0;
76 * FawkesNetworkMessage *m = new FawkesNetworkMessage(clid, cid, msgid, u, sizeof(unsigned int));
77 * @endcode
78 *
79 * @ingroup NetComm
80 * @author Tim Niemueller
81 */
82
83/** Constructor.
84 * Plain constructor. All values initialized to zero, including the
85 * client ID.
86 */
88{
89 memset(&_msg, 0, sizeof(_msg));
90 _clid = 0;
91 _content = NULL;
92}
93
94/** Constructor to set message and client ID.
95 * @param clid client ID
96 * @param msg reference to message, deep-copied into local message.
97 */
99{
100 _content = NULL;
101 _clid = clid;
102 memcpy(&_msg, &msg, sizeof(fawkes_message_t));
103}
104
105/** Constructor that only sets message.
106 * The client ID is zero.
107 * @param msg reference to message, deep-copied into local message.
108 */
110{
111 _content = NULL;
112 _clid = 0;
113 memcpy(&_msg, &msg, sizeof(fawkes_message_t));
114}
115
116/** Constructor to set single fields.
117 * The client ID is set to zero.
118 * @param cid component ID
119 * @param msg_id message type ID
120 * @param payload pointer to payload buffer
121 * @param payload_size size of payload buffer
122 */
124 unsigned short int msg_id,
125 void * payload,
126 size_t payload_size)
127{
128 _clid = 0;
129 _content = NULL;
130 if (payload_size > 0xFFFFFFFF) {
131 // cannot carry that many bytes
133 }
134 _msg.header.cid = htons(cid);
135 _msg.header.msg_id = htons(msg_id);
136 _msg.header.payload_size = htonl(payload_size);
137 _msg.payload = payload;
138}
139
140/** Constructor to set single fields and allocate memory.
141 * The client ID is set to zero. The payload memory is allocated on the heap.
142 * @param cid component ID
143 * @param msg_id message type ID
144 * @param payload_size size of payload buffer
145 */
147 unsigned short int msg_id,
148 size_t payload_size)
149{
150 _content = NULL;
151 _clid = 0;
152 if (payload_size > 0xFFFFFFFF) {
153 // cannot carry that many bytes
155 }
156 _msg.header.cid = htons(cid);
157 _msg.header.msg_id = htons(msg_id);
158 _msg.header.payload_size = htonl(payload_size);
159 _msg.payload = calloc(1, payload_size);
160}
161
162/** Constructor to set single fields without payload.
163 * The client ID is set to zero.
164 * @param cid component ID
165 * @param msg_id message type ID
166 */
167FawkesNetworkMessage::FawkesNetworkMessage(unsigned short int cid, unsigned short int msg_id)
168{
169 _content = NULL;
170 _clid = 0;
171 _msg.header.cid = htons(cid);
172 _msg.header.msg_id = htons(msg_id);
173 _msg.header.payload_size = 0;
174 _msg.payload = NULL;
175}
176
177/** Constructor to set single fields.
178 * The client ID is set to zero.
179 * @param cid component ID
180 * @param msg_id message type ID
181 * @param content complex content object
182 */
184 unsigned short int msg_id,
186{
187 _content = content;
188 _clid = 0;
189 _msg.header.cid = htons(cid);
190 _msg.header.msg_id = htons(msg_id);
191 _msg.header.payload_size = 0;
192 _msg.payload = NULL;
193}
194
195/** Constructor to set single fields and client ID.
196 * @param clid client ID
197 * @param cid component ID
198 * @param msg_id message type ID
199 * @param content complex content object
200 */
202 unsigned short int cid,
203 unsigned short int msg_id,
205{
206 _content = content;
207 _clid = clid;
208 _msg.header.cid = htons(cid);
209 _msg.header.msg_id = htons(msg_id);
210 _msg.header.payload_size = 0;
211 _msg.payload = NULL;
212}
213
214/** Constructor to set single fields and client ID.
215 * @param clid client ID
216 * @param cid component ID
217 * @param msg_id message type ID
218 * @param payload pointer to payload buffer
219 * @param payload_size size of payload buffer
220 */
222 unsigned short int cid,
223 unsigned short int msg_id,
224 void * payload,
225 size_t payload_size)
226{
227 _content = NULL;
228 if (payload_size > 0xFFFFFFFF) {
229 // cannot carry that many bytes
231 }
232 _clid = clid;
233 _msg.header.cid = htons(cid);
234 _msg.header.msg_id = htons(msg_id);
235 _msg.header.payload_size = htonl(payload_size);
236 _msg.payload = payload;
237}
238
239/** Constructor to set single fields and client ID without payload.
240 * @param clid client ID
241 * @param cid component ID
242 * @param msg_id message type ID
243 */
245 unsigned short int cid,
246 unsigned short int msg_id)
247{
248 _content = NULL;
249 _clid = clid;
250 _msg.header.cid = htons(cid);
251 _msg.header.msg_id = htons(msg_id);
252 _msg.header.payload_size = 0;
253 _msg.payload = NULL;
254}
255
256/** Destructor.
257 * This destructor also frees the payload buffer if set!
258 */
260{
261 if (_content == NULL) {
262 if (_msg.payload != NULL) {
263 free(_msg.payload);
264 _msg.payload = NULL;
265 }
266 } else {
267 delete _content;
268 _content = NULL;
269 }
270}
271
272/** Get client ID.
273 * @return client ID
274 */
275unsigned int
277{
278 return _clid;
279}
280
281/** Get component ID.
282 * @return component ID
283 */
284unsigned short int
286{
287 return ntohs(_msg.header.cid);
288}
289
290/** Get message type ID.
291 * @return message type ID
292 */
293unsigned short int
295{
296 return ntohs(_msg.header.msg_id);
297}
298
299/** Get payload size.
300 * @return payload size.
301 */
302size_t
304{
305 return ntohl(_msg.header.payload_size);
306}
307
308/** Get payload buffer.
309 * @return pointer to payload buffer.
310 */
311void *
313{
314 return _msg.payload;
315}
316
317/** Get message reference.
318 * @return reference to internal fawkes_message_t, use with care!
319 */
320const fawkes_message_t &
322{
323 return _msg;
324}
325
326/** Set client ID.
327 * @param clid client ID
328 */
329void
331{
332 _clid = clid;
333}
334
335/** Set component ID.
336 * @param cid component ID
337 */
338void
340{
341 _msg.header.cid = htons(cid);
342}
343
344/** Set message type ID.
345 * @param msg_id message type ID
346 */
347void
348FawkesNetworkMessage::set_message_id(unsigned short int msg_id)
349{
350 _msg.header.msg_id = htons(msg_id);
351}
352
353/** Set payload.
354 * @param payload pointer to payload buffer
355 * @param payload_size size of payload buffer
356 */
357void
358FawkesNetworkMessage::set_payload(void *payload, size_t payload_size)
359{
360 if (payload_size > 0xFFFFFFFF) {
361 // cannot carry that many bytes
363 }
364 _msg.payload = payload;
365 _msg.header.payload_size = htonl(payload_size);
366}
367
368/** Set from message.
369 * @param msg reference to message. Content is deep-copied.
370 */
371void
373{
374 memcpy(&_msg, &msg, sizeof(fawkes_message_t));
375}
376
377/** Set complex message content.
378 * @param content complex message content.
379 */
380void
382{
383 _content = content;
384}
385
386/** Pack data for sending.
387 * If complex message sending is required (message content object has been set)
388 * then serialize() is called for the content and the message is prepared for
389 * sending.
390 */
391void
393{
394 if (_content != NULL) {
395 _content->serialize();
396 _msg.payload = _content->payload();
397 _msg.header.payload_size = htonl(_content->payload_size());
398 }
399}
400
401} // end namespace fawkes
Base class for exceptions in Fawkes.
Definition: exception.h:36
void append(const char *format,...) noexcept
Append messages to the message list.
Definition: exception.cpp:333
Fawkes network message content.
virtual size_t payload_size()
Return payload size.
virtual void serialize()=0
Serialize message content.
virtual void * payload()
Return pointer to payload.
The given message size exceeds the limit.
Definition: message.h:69
FawkesNetworkMessageTooBigException(size_t message_size)
Constructor.
Definition: message.cpp:47
const fawkes_message_t & fmsg() const
Get message reference.
Definition: message.cpp:321
unsigned short int msgid() const
Get message type ID.
Definition: message.cpp:294
unsigned short int cid() const
Get component ID.
Definition: message.cpp:285
MT * msg() const
Get correctly casted payload.
Definition: message.h:120
void set_message_id(unsigned short int msg_id)
Set message type ID.
Definition: message.cpp:348
unsigned int clid() const
Get client ID.
Definition: message.cpp:276
void * payload() const
Get payload buffer.
Definition: message.cpp:312
virtual ~FawkesNetworkMessage()
Destructor.
Definition: message.cpp:259
size_t payload_size() const
Get payload size.
Definition: message.cpp:303
void set_client_id(unsigned int clid)
Set client ID.
Definition: message.cpp:330
void set_component_id(unsigned short int cid)
Set component ID.
Definition: message.cpp:339
void pack()
Pack data for sending.
Definition: message.cpp:392
FawkesNetworkMessage()
Constructor.
Definition: message.cpp:87
void set(fawkes_message_t &msg)
Set from message.
Definition: message.cpp:372
void set_payload(void *payload, size_t payload_size)
Set payload.
Definition: message.cpp:358
void set_content(FawkesNetworkMessageContent *content)
Set complex message content.
Definition: message.cpp:381
Fawkes library namespace.
Fawkes network message header.
Definition: message.h:40
unsigned short int cid
component id
Definition: message.h:41
unsigned short int msg_id
message id
Definition: message.h:42
unsigned int payload_size
payload size in bytes
Definition: message.h:43
Message as stored in local queues.
Definition: message.h:54
fawkes_message_header_t header
message header
Definition: message.h:55
void * payload
message payload
Definition: message.h:56