message.cpp

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

Generated on Tue Feb 22 13:31:23 2011 for Fawkes API by  doxygen 1.4.7