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 
26 #include <netcomm/fawkes/message.h>
27 #include <netcomm/fawkes/message_content.h>
28 
29 #include <netinet/in.h>
30 #include <cstring>
31 #include <cstdlib>
32 #include <cstddef>
33 
34 namespace fawkes {
35 
36 /** @class FawkesNetworkMessageTooBigException message.h <netcomm/fawkes/message.h>
37  * The given message size exceeds the limit.
38  * The message payload can only be of a certain size, which is limited especially
39  * by the data type used for the payload size in the header. If you try to assign too
40  * much data to a message this exception is thrown.
41  * @ingroup NetComm
42  * @author Tim Niemueller
43  */
44 
45 /** Constructor.
46  * @param message_size size of the message that is too big
47  */
49  : Exception("Network message size too big")
50 {
52  append("Tried to create message of %l bytes, while only %l bytes allowed", 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 
95 /** Constructor to set message and client ID.
96  * @param clid client ID
97  * @param msg reference to message, deep-copied into local message.
98  */
100 {
101  _content = NULL;
102  _clid = clid;
103  memcpy(&_msg, &msg, sizeof(fawkes_message_t));
104 }
105 
106 
107 /** Constructor that only sets message.
108  * The client ID is zero.
109  * @param msg reference to message, deep-copied into local message.
110  */
112 {
113  _content = NULL;
114  _clid = 0;
115  memcpy(&_msg, &msg, sizeof(fawkes_message_t));
116 }
117 
118 
119 /** Constructor to set single fields.
120  * The client ID is set to zero.
121  * @param cid component ID
122  * @param msg_id message type ID
123  * @param payload pointer to payload buffer
124  * @param payload_size size of payload buffer
125  */
126 FawkesNetworkMessage::FawkesNetworkMessage(unsigned short int cid, unsigned short int msg_id,
127  void *payload, size_t payload_size)
128 {
129  _clid = 0;
130  _content = NULL;
131  if ( payload_size > 0xFFFFFFFF ) {
132  // cannot carry that many bytes
133  throw FawkesNetworkMessageTooBigException(payload_size);
134  }
135  _msg.header.cid = htons(cid);
136  _msg.header.msg_id = htons(msg_id);
137  _msg.header.payload_size = htonl(payload_size);
138  _msg.payload = payload;
139 }
140 
141 
142 
143 /** Constructor to set single fields and allocate memory.
144  * The client ID is set to zero. The payload memory is allocated on the heap.
145  * @param cid component ID
146  * @param msg_id message type ID
147  * @param payload_size size of payload buffer
148  */
149 FawkesNetworkMessage::FawkesNetworkMessage(unsigned short int cid, unsigned short int msg_id,
150  size_t payload_size)
151 {
152  _content = NULL;
153  _clid = 0;
154  if ( payload_size > 0xFFFFFFFF ) {
155  // cannot carry that many bytes
156  throw FawkesNetworkMessageTooBigException(payload_size);
157  }
158  _msg.header.cid = htons(cid);
159  _msg.header.msg_id = htons(msg_id);
160  _msg.header.payload_size = htonl(payload_size);
161  _msg.payload = calloc(1, payload_size);
162 }
163 
164 
165 /** Constructor to set single fields without payload.
166  * The client ID is set to zero.
167  * @param cid component ID
168  * @param msg_id message type ID
169  */
170 FawkesNetworkMessage::FawkesNetworkMessage(unsigned short int cid, unsigned short int msg_id)
171 {
172  _content = NULL;
173  _clid = 0;
174  _msg.header.cid = htons(cid);
175  _msg.header.msg_id = htons(msg_id);
176  _msg.header.payload_size = 0;
177  _msg.payload = NULL;
178 }
179 
180 
181 /** Constructor to set single fields.
182  * The client ID is set to zero.
183  * @param cid component ID
184  * @param msg_id message type ID
185  * @param content complex content object
186  */
187 FawkesNetworkMessage::FawkesNetworkMessage(unsigned short int cid, unsigned short int msg_id,
189 {
190  _content = content;
191  _clid = 0;
192  _msg.header.cid = htons(cid);
193  _msg.header.msg_id = htons(msg_id);
194  _msg.header.payload_size = 0;
195  _msg.payload = NULL;
196 }
197 
198 
199 /** Constructor to set single fields and client ID.
200  * @param clid client ID
201  * @param cid component ID
202  * @param msg_id message type ID
203  * @param content complex content object
204  */
206  unsigned short int cid, unsigned short int msg_id,
208 {
209  _content = content;
210  _clid = clid;
211  _msg.header.cid = htons(cid);
212  _msg.header.msg_id = htons(msg_id);
213  _msg.header.payload_size = 0;
214  _msg.payload = NULL;
215 }
216 
217 
218 
219 /** Constructor to set single fields and client ID.
220  * @param clid client ID
221  * @param cid component ID
222  * @param msg_id message type ID
223  * @param payload pointer to payload buffer
224  * @param payload_size size of payload buffer
225  */
227  unsigned short int cid, unsigned short int msg_id,
228  void *payload, size_t payload_size)
229 {
230  _content = NULL;
231  if ( payload_size > 0xFFFFFFFF ) {
232  // cannot carry that many bytes
233  throw FawkesNetworkMessageTooBigException(payload_size);
234  }
235  _clid = clid;
236  _msg.header.cid = htons(cid);
237  _msg.header.msg_id = htons(msg_id);
238  _msg.header.payload_size = htonl(payload_size);
239  _msg.payload = payload;
240 }
241 
242 
243 /** Constructor to set single fields and client ID without payload.
244  * @param clid client ID
245  * @param cid component ID
246  * @param msg_id message type ID
247  */
249  unsigned short int cid, unsigned short int msg_id)
250 {
251  _content = NULL;
252  _clid = clid;
253  _msg.header.cid = htons(cid);
254  _msg.header.msg_id = htons(msg_id);
255  _msg.header.payload_size = 0;
256  _msg.payload = NULL;
257 }
258 
259 
260 /** Destructor.
261  * This destructor also frees the payload buffer if set!
262  */
264 {
265  if ( _content == NULL ) {
266  if ( _msg.payload != NULL ) {
267  free(_msg.payload);
268  _msg.payload = NULL;
269  }
270  } else {
271  delete _content;
272  _content = NULL;
273  }
274 }
275 
276 
277 /** Get client ID.
278  * @return client ID
279  */
280 unsigned int
282 {
283  return _clid;
284 }
285 
286 
287 /** Get component ID.
288  * @return component ID
289  */
290 unsigned short int
292 {
293  return ntohs(_msg.header.cid);
294 }
295 
296 
297 /** Get message type ID.
298  * @return message type ID
299  */
300 unsigned short int
302 {
303  return ntohs(_msg.header.msg_id);
304 }
305 
306 
307 /** Get payload size.
308  * @return payload size.
309  */
310 size_t
312 {
313  return ntohl(_msg.header.payload_size);
314 }
315 
316 
317 /** Get payload buffer.
318  * @return pointer to payload buffer.
319  */
320 void *
322 {
323  return _msg.payload;
324 }
325 
326 
327 /** Get message reference.
328  * @return reference to internal fawkes_message_t, use with care!
329  */
330 const fawkes_message_t &
332 {
333  return _msg;
334 }
335 
336 
337 /** Set client ID.
338  * @param clid client ID
339  */
340 void
342 {
343  _clid = clid;
344 }
345 
346 
347 /** Set component ID.
348  * @param cid component ID
349  */
350 void
352 {
353  _msg.header.cid = htons(cid);
354 }
355 
356 
357 /** Set message type ID.
358  * @param msg_id message type ID
359  */
360 void
361 FawkesNetworkMessage::set_message_id(unsigned short int msg_id)
362 {
363  _msg.header.msg_id = htons(msg_id);
364 }
365 
366 
367 /** Set payload.
368  * @param payload pointer to payload buffer
369  * @param payload_size size of payload buffer
370  */
371 void
372 FawkesNetworkMessage::set_payload(void *payload, size_t payload_size)
373 {
374  if ( payload_size > 0xFFFFFFFF ) {
375  // cannot carry that many bytes
376  throw FawkesNetworkMessageTooBigException(payload_size);
377  }
378  _msg.payload = payload;
379  _msg.header.payload_size = htonl(payload_size);
380 }
381 
382 
383 /** Set from message.
384  * @param msg reference to message. Content is deep-copied.
385  */
386 void
388 {
389  memcpy(&_msg, &msg, sizeof(fawkes_message_t));
390 }
391 
392 
393 /** Set complex message content.
394  * @param content complex message content.
395  */
396 void
398 {
399  _content = content;
400 }
401 
402 
403 /** Pack data for sending.
404  * If complex message sending is required (message content object has been set)
405  * then serialize() is called for the content and the message is prepared for
406  * sending.
407  */
408 void
410 {
411  if ( _content != NULL ) {
412  _content->serialize();
413  _msg.payload = _content->payload();
414  _msg.header.payload_size = htonl(_content->payload_size());
415  }
416 }
417 
418 } // end namespace fawkes
void * payload() const
Get payload buffer.
Definition: message.cpp:321
void set_content(FawkesNetworkMessageContent *content)
Set complex message content.
Definition: message.cpp:397
void set_client_id(unsigned int clid)
Set client ID.
Definition: message.cpp:341
virtual ~FawkesNetworkMessage()
Destructor.
Definition: message.cpp:263
unsigned short int cid() const
Get component ID.
Definition: message.cpp:291
Fawkes library namespace.
unsigned int clid() const
Get client ID.
Definition: message.cpp:281
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:351
void pack()
Pack data for sending.
Definition: message.cpp:409
void set_message_id(unsigned short int msg_id)
Set message type ID.
Definition: message.cpp:361
Base class for exceptions in Fawkes.
Definition: exception.h:36
unsigned int payload_size
payload size in bytes
Definition: message.h:42
Message as stored in local queues.
Definition: message.h:52
const fawkes_message_t & fmsg() const
Get message reference.
Definition: message.cpp:331
FawkesNetworkMessageTooBigException(size_t message_size)
Constructor.
Definition: message.cpp:48
void set_payload(void *payload, size_t payload_size)
Set payload.
Definition: message.cpp:372
unsigned short int msgid() const
Get message type ID.
Definition: message.cpp:301
void set(fawkes_message_t &msg)
Set from message.
Definition: message.cpp:387
void append(const char *format,...)
Append messages to the message list.
Definition: exception.cpp:341
size_t payload_size() const
Get payload size.
Definition: message.cpp:311