Fawkes API Fawkes Development Version
|
00001 00002 /*************************************************************************** 00003 * message.cpp - Fawkes network message 00004 * 00005 * Created: Tue Nov 21 16:21:28 2006 00006 * Copyright 2006 Tim Niemueller [www.niemueller.de] 00007 * 00008 ****************************************************************************/ 00009 00010 /* This program is free software; you can redistribute it and/or modify 00011 * it under the terms of the GNU General Public License as published by 00012 * the Free Software Foundation; either version 2 of the License, or 00013 * (at your option) any later version. A runtime exception applies to 00014 * this software (see LICENSE.GPL_WRE file mentioned below for details). 00015 * 00016 * This program is distributed in the hope that it will be useful, 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 * GNU Library General Public License for more details. 00020 * 00021 * Read the full text in the LICENSE.GPL_WRE file in the doc directory. 00022 */ 00023 00024 #include <core/exception.h> 00025 00026 #include <netcomm/fawkes/message.h> 00027 #include <netcomm/fawkes/message_content.h> 00028 00029 #include <netinet/in.h> 00030 #include <cstring> 00031 #include <cstdlib> 00032 #include <cstddef> 00033 00034 namespace fawkes { 00035 00036 /** @class FawkesNetworkMessageTooBigException message.h <netcomm/fawkes/message.h> 00037 * The given message size exceeds the limit. 00038 * The message payload can only be of a certain size, which is limited especially 00039 * by the data type used for the payload size in the header. If you try to assign too 00040 * much data to a message this exception is thrown. 00041 * @ingroup NetComm 00042 * @author Tim Niemueller 00043 */ 00044 00045 /** Constructor. 00046 * @param message_size size of the message that is too big 00047 */ 00048 FawkesNetworkMessageTooBigException::FawkesNetworkMessageTooBigException(size_t message_size) 00049 : Exception("Network message size too big") 00050 { 00051 fawkes_message_header_t fmh; 00052 append("Tried to create message of %l bytes, while only %l bytes allowed", message_size, 00053 sizeof(fmh.payload_size)); 00054 } 00055 00056 /** @class FawkesNetworkMessage message.h <netcomm/fawkes/message.h> 00057 * Representation of a message that is sent over the network. 00058 * 00059 * For the basic format of a message see fawkes_message_t. This class 00060 * provides access to all of the fields in a convenient manner. Additionally 00061 * it can handle the client ID, which is either the sender or the recipient 00062 * of a message (depending if it's in an inbound or outbound queue). 00063 * 00064 * Note that the message takes over ownership of the payload. This means that it 00065 * is internally held and freed (using free()) if the message is deleted (if the 00066 * reference count reaches zero). Because of this you can NOT supply a local variable. 00067 * The following code is illegal: 00068 * @code 00069 * unsigned int u = 0; 00070 * FawkesNetworkMessage *m = new FawkesNetworkMessage(clid, cid, msgid, &u, sizeof(u)); 00071 * @endcode 00072 * Rather you have to use the following code: 00073 * @code 00074 * unsigned int *u = (unsigned int *)malloc(sizeof(unsigned int)); 00075 * *u = 0; 00076 * FawkesNetworkMessage *m = new FawkesNetworkMessage(clid, cid, msgid, u, sizeof(unsigned int)); 00077 * @endcode 00078 * 00079 * @ingroup NetComm 00080 * @author Tim Niemueller 00081 */ 00082 00083 /** Constructor. 00084 * Plain constructor. All values initialized to zero, including the 00085 * client ID. 00086 */ 00087 FawkesNetworkMessage::FawkesNetworkMessage() 00088 { 00089 memset(&_msg, 0, sizeof(_msg)); 00090 _clid = 0; 00091 _content = NULL; 00092 } 00093 00094 00095 /** Constructor to set message and client ID. 00096 * @param clid client ID 00097 * @param msg reference to message, deep-copied into local message. 00098 */ 00099 FawkesNetworkMessage::FawkesNetworkMessage(unsigned int clid, fawkes_message_t &msg) 00100 { 00101 _content = NULL; 00102 _clid = clid; 00103 memcpy(&_msg, &msg, sizeof(fawkes_message_t)); 00104 } 00105 00106 00107 /** Constructor that only sets message. 00108 * The client ID is zero. 00109 * @param msg reference to message, deep-copied into local message. 00110 */ 00111 FawkesNetworkMessage::FawkesNetworkMessage(fawkes_message_t &msg) 00112 { 00113 _content = NULL; 00114 _clid = 0; 00115 memcpy(&_msg, &msg, sizeof(fawkes_message_t)); 00116 } 00117 00118 00119 /** Constructor to set single fields. 00120 * The client ID is set to zero. 00121 * @param cid component ID 00122 * @param msg_id message type ID 00123 * @param payload pointer to payload buffer 00124 * @param payload_size size of payload buffer 00125 */ 00126 FawkesNetworkMessage::FawkesNetworkMessage(unsigned short int cid, unsigned short int msg_id, 00127 void *payload, size_t payload_size) 00128 { 00129 _clid = 0; 00130 _content = NULL; 00131 if ( payload_size > 0xFFFFFFFF ) { 00132 // cannot carry that many bytes 00133 throw FawkesNetworkMessageTooBigException(payload_size); 00134 } 00135 _msg.header.cid = htons(cid); 00136 _msg.header.msg_id = htons(msg_id); 00137 _msg.header.payload_size = htonl(payload_size); 00138 _msg.payload = payload; 00139 } 00140 00141 00142 00143 /** Constructor to set single fields and allocate memory. 00144 * The client ID is set to zero. The payload memory is allocated on the heap. 00145 * @param cid component ID 00146 * @param msg_id message type ID 00147 * @param payload_size size of payload buffer 00148 */ 00149 FawkesNetworkMessage::FawkesNetworkMessage(unsigned short int cid, unsigned short int msg_id, 00150 size_t payload_size) 00151 { 00152 _content = NULL; 00153 _clid = 0; 00154 if ( payload_size > 0xFFFFFFFF ) { 00155 // cannot carry that many bytes 00156 throw FawkesNetworkMessageTooBigException(payload_size); 00157 } 00158 _msg.header.cid = htons(cid); 00159 _msg.header.msg_id = htons(msg_id); 00160 _msg.header.payload_size = htonl(payload_size); 00161 _msg.payload = calloc(1, payload_size); 00162 } 00163 00164 00165 /** Constructor to set single fields without payload. 00166 * The client ID is set to zero. 00167 * @param cid component ID 00168 * @param msg_id message type ID 00169 */ 00170 FawkesNetworkMessage::FawkesNetworkMessage(unsigned short int cid, unsigned short int msg_id) 00171 { 00172 _content = NULL; 00173 _clid = 0; 00174 _msg.header.cid = htons(cid); 00175 _msg.header.msg_id = htons(msg_id); 00176 _msg.header.payload_size = 0; 00177 _msg.payload = NULL; 00178 } 00179 00180 00181 /** Constructor to set single fields. 00182 * The client ID is set to zero. 00183 * @param cid component ID 00184 * @param msg_id message type ID 00185 * @param content complex content object 00186 */ 00187 FawkesNetworkMessage::FawkesNetworkMessage(unsigned short int cid, unsigned short int msg_id, 00188 FawkesNetworkMessageContent *content) 00189 { 00190 _content = content; 00191 _clid = 0; 00192 _msg.header.cid = htons(cid); 00193 _msg.header.msg_id = htons(msg_id); 00194 _msg.header.payload_size = 0; 00195 _msg.payload = NULL; 00196 } 00197 00198 00199 /** Constructor to set single fields and client ID. 00200 * @param clid client ID 00201 * @param cid component ID 00202 * @param msg_id message type ID 00203 * @param content complex content object 00204 */ 00205 FawkesNetworkMessage::FawkesNetworkMessage(unsigned int clid, 00206 unsigned short int cid, unsigned short int msg_id, 00207 FawkesNetworkMessageContent *content) 00208 { 00209 _content = content; 00210 _clid = clid; 00211 _msg.header.cid = htons(cid); 00212 _msg.header.msg_id = htons(msg_id); 00213 _msg.header.payload_size = 0; 00214 _msg.payload = NULL; 00215 } 00216 00217 00218 00219 /** Constructor to set single fields and client ID. 00220 * @param clid client ID 00221 * @param cid component ID 00222 * @param msg_id message type ID 00223 * @param payload pointer to payload buffer 00224 * @param payload_size size of payload buffer 00225 */ 00226 FawkesNetworkMessage::FawkesNetworkMessage(unsigned int clid, 00227 unsigned short int cid, unsigned short int msg_id, 00228 void *payload, size_t payload_size) 00229 { 00230 _content = NULL; 00231 if ( payload_size > 0xFFFFFFFF ) { 00232 // cannot carry that many bytes 00233 throw FawkesNetworkMessageTooBigException(payload_size); 00234 } 00235 _clid = clid; 00236 _msg.header.cid = htons(cid); 00237 _msg.header.msg_id = htons(msg_id); 00238 _msg.header.payload_size = htonl(payload_size); 00239 _msg.payload = payload; 00240 } 00241 00242 00243 /** Constructor to set single fields and client ID without payload. 00244 * @param clid client ID 00245 * @param cid component ID 00246 * @param msg_id message type ID 00247 */ 00248 FawkesNetworkMessage::FawkesNetworkMessage(unsigned int clid, 00249 unsigned short int cid, unsigned short int msg_id) 00250 { 00251 _content = NULL; 00252 _clid = clid; 00253 _msg.header.cid = htons(cid); 00254 _msg.header.msg_id = htons(msg_id); 00255 _msg.header.payload_size = 0; 00256 _msg.payload = NULL; 00257 } 00258 00259 00260 /** Destructor. 00261 * This destructor also frees the payload buffer if set! 00262 */ 00263 FawkesNetworkMessage::~FawkesNetworkMessage() 00264 { 00265 if ( _content == NULL ) { 00266 if ( _msg.payload != NULL ) { 00267 free(_msg.payload); 00268 _msg.payload = NULL; 00269 } 00270 } else { 00271 delete _content; 00272 _content = NULL; 00273 } 00274 } 00275 00276 00277 /** Get client ID. 00278 * @return client ID 00279 */ 00280 unsigned int 00281 FawkesNetworkMessage::clid() const 00282 { 00283 return _clid; 00284 } 00285 00286 00287 /** Get component ID. 00288 * @return component ID 00289 */ 00290 unsigned short int 00291 FawkesNetworkMessage::cid() const 00292 { 00293 return ntohs(_msg.header.cid); 00294 } 00295 00296 00297 /** Get message type ID. 00298 * @return message type ID 00299 */ 00300 unsigned short int 00301 FawkesNetworkMessage::msgid() const 00302 { 00303 return ntohs(_msg.header.msg_id); 00304 } 00305 00306 00307 /** Get payload size. 00308 * @return payload size. 00309 */ 00310 size_t 00311 FawkesNetworkMessage::payload_size() const 00312 { 00313 return ntohl(_msg.header.payload_size); 00314 } 00315 00316 00317 /** Get payload buffer. 00318 * @return pointer to payload buffer. 00319 */ 00320 void * 00321 FawkesNetworkMessage::payload() const 00322 { 00323 return _msg.payload; 00324 } 00325 00326 00327 /** Get message reference. 00328 * @return reference to internal fawkes_message_t, use with care! 00329 */ 00330 const fawkes_message_t & 00331 FawkesNetworkMessage::fmsg() const 00332 { 00333 return _msg; 00334 } 00335 00336 00337 /** Set client ID. 00338 * @param clid client ID 00339 */ 00340 void 00341 FawkesNetworkMessage::set_client_id(unsigned int clid) 00342 { 00343 _clid = clid; 00344 } 00345 00346 00347 /** Set component ID. 00348 * @param cid component ID 00349 */ 00350 void 00351 FawkesNetworkMessage::set_component_id(unsigned short int cid) 00352 { 00353 _msg.header.cid = htons(cid); 00354 } 00355 00356 00357 /** Set message type ID. 00358 * @param msg_id message type ID 00359 */ 00360 void 00361 FawkesNetworkMessage::set_message_id(unsigned short int msg_id) 00362 { 00363 _msg.header.msg_id = htons(msg_id); 00364 } 00365 00366 00367 /** Set payload. 00368 * @param payload pointer to payload buffer 00369 * @param payload_size size of payload buffer 00370 */ 00371 void 00372 FawkesNetworkMessage::set_payload(void *payload, size_t payload_size) 00373 { 00374 if ( payload_size > 0xFFFFFFFF ) { 00375 // cannot carry that many bytes 00376 throw FawkesNetworkMessageTooBigException(payload_size); 00377 } 00378 _msg.payload = payload; 00379 _msg.header.payload_size = htonl(payload_size); 00380 } 00381 00382 00383 /** Set from message. 00384 * @param msg reference to message. Content is deep-copied. 00385 */ 00386 void 00387 FawkesNetworkMessage::set(fawkes_message_t &msg) 00388 { 00389 memcpy(&_msg, &msg, sizeof(fawkes_message_t)); 00390 } 00391 00392 00393 /** Set complex message content. 00394 * @param content complex message content. 00395 */ 00396 void 00397 FawkesNetworkMessage::set_content(FawkesNetworkMessageContent *content) 00398 { 00399 _content = content; 00400 } 00401 00402 00403 /** Pack data for sending. 00404 * If complex message sending is required (message content object has been set) 00405 * then serialize() is called for the content and the message is prepared for 00406 * sending. 00407 */ 00408 void 00409 FawkesNetworkMessage::pack() 00410 { 00411 if ( _content != NULL ) { 00412 _content->serialize(); 00413 _msg.payload = _content->payload(); 00414 _msg.header.payload_size = htonl(_content->payload_size()); 00415 } 00416 } 00417 00418 } // end namespace fawkes