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 
33 namespace 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  */
167 FawkesNetworkMessage::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  */
275 unsigned int
277 {
278  return _clid;
279 }
280 
281 /** Get component ID.
282  * @return component ID
283  */
284 unsigned short int
286 {
287  return ntohs(_msg.header.cid);
288 }
289 
290 /** Get message type ID.
291  * @return message type ID
292  */
293 unsigned short int
295 {
296  return ntohs(_msg.header.msg_id);
297 }
298 
299 /** Get payload size.
300  * @return payload size.
301  */
302 size_t
304 {
305  return ntohl(_msg.header.payload_size);
306 }
307 
308 /** Get payload buffer.
309  * @return pointer to payload buffer.
310  */
311 void *
313 {
314  return _msg.payload;
315 }
316 
317 /** Get message reference.
318  * @return reference to internal fawkes_message_t, use with care!
319  */
320 const fawkes_message_t &
322 {
323  return _msg;
324 }
325 
326 /** Set client ID.
327  * @param clid client ID
328  */
329 void
331 {
332  _clid = clid;
333 }
334 
335 /** Set component ID.
336  * @param cid component ID
337  */
338 void
340 {
341  _msg.header.cid = htons(cid);
342 }
343 
344 /** Set message type ID.
345  * @param msg_id message type ID
346  */
347 void
348 FawkesNetworkMessage::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  */
357 void
358 FawkesNetworkMessage::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  */
371 void
373 {
374  memcpy(&_msg, &msg, sizeof(fawkes_message_t));
375 }
376 
377 /** Set complex message content.
378  * @param content complex message content.
379  */
380 void
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  */
391 void
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
void * payload() const
Get payload buffer.
Definition: message.cpp:312
unsigned short int msg_id
message id
Definition: message.h:42
void set_content(FawkesNetworkMessageContent *content)
Set complex message content.
Definition: message.cpp:381
void set_client_id(unsigned int clid)
Set client ID.
Definition: message.cpp:330
virtual ~FawkesNetworkMessage()
Destructor.
Definition: message.cpp:259
unsigned short int cid() const
Get component ID.
Definition: message.cpp:285
fawkes_message_header_t header
message header
Definition: message.h:55
Fawkes library namespace.
unsigned int clid() const
Get client ID.
Definition: message.cpp:276
unsigned short int cid
component id
Definition: message.h:41
Fawkes network message content.
FawkesNetworkMessage()
Constructor.
Definition: message.cpp:87
Fawkes network message header.
Definition: message.h:39
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
void set_message_id(unsigned short int msg_id)
Set message type ID.
Definition: message.cpp:348
virtual void serialize()=0
Serialize message content.
Base class for exceptions in Fawkes.
Definition: exception.h:35
unsigned int payload_size
payload size in bytes
Definition: message.h:43
Message as stored in local queues.
Definition: message.h:53
virtual void * payload()
Return pointer to payload.
void * payload
message payload
Definition: message.h:56
const fawkes_message_t & fmsg() const
Get message reference.
Definition: message.cpp:321
FawkesNetworkMessageTooBigException(size_t message_size)
Constructor.
Definition: message.cpp:47
void set_payload(void *payload, size_t payload_size)
Set payload.
Definition: message.cpp:358
virtual size_t payload_size()
Return payload size.
unsigned short int msgid() const
Get message type ID.
Definition: message.cpp:294
The given message size exceeds the limit.
Definition: message.h:68
void set(fawkes_message_t &msg)
Set from message.
Definition: message.cpp:372
MT * msg() const
Get correctly casted payload.
Definition: message.h:120
void append(const char *format,...)
Append messages to the message list.
Definition: exception.cpp:333
size_t payload_size() const
Get payload size.
Definition: message.cpp:303