fuse_message.cpp

00001
00002 /***************************************************************************
00003  *  fuse_message.cpp - FireVision Remote Control Protocol Message Type
00004  *
00005  *  Created: Wed Nov 07 13:01:20 2007
00006  *  Copyright  2005-2007  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/exceptions/software.h>
00025 #include <fvutils/net/fuse_message.h>
00026 #include <fvutils/net/fuse_message_content.h>
00027
00028 #include <cstdio>
00029 #include <cstring>
00030 #include <cstdlib>
00031 #include <netinet/in.h>
00032 
00033 /** @class FuseNetworkMessage <fvutils/net/fuse_message.h>
00034  * FUSE Network Message.
00035  * This is the basic entity for messages that are sent over the network. Either
00036  * just use this message to send arbitrary payload or derive this class for more
00037  * complex behavior or nice encapsulations of messages.
00038  *
00039  * @ingroup FUSE
00040  * @ingroup FireVision
00041  * @author Tim Niemueller
00042  */
00043 
00044 /** Constructor. */
00045 FuseNetworkMessage::FuseNetworkMessage()
00046 {
00047   memset(&_msg, 0, sizeof(_msg));
00048   __content = NULL;
00049 }
00050
00051 
00052 /** Constructor.
00053  * @param msg message information to copy
00054  */
00055 FuseNetworkMessage::FuseNetworkMessage(FUSE_message_t *msg)
00056 {
00057   memcpy(&_msg, msg, sizeof(FUSE_message_t));
00058   __content = NULL;
00059 }
00060
00061 
00062 /** Constructor.
00063  * @param type message type
00064  * @param payload payload
00065  * @param payload_size size of payload
00066  * @param copy_payload if true payload is copied, otherwise payload is referenced
00067  * and ownership of payload is claimed.
00068  */
00069 FuseNetworkMessage::FuseNetworkMessage(FUSE_message_type_t type,
00070                                        void *payload, size_t payload_size,
00071                                        bool copy_payload)
00072 {
00073   __content = NULL;
00074   _msg.header.message_type = htonl(type);
00075   _msg.header.payload_size = htonl(payload_size);
00076
00077   if ( copy_payload ) {
00078     _msg.payload = malloc(payload_size);
00079     memcpy(_msg.payload, payload, payload_size);
00080   } else {
00081     _msg.payload = payload;
00082   }
00083 }
00084
00085 
00086 /** Constructor without payload.
00087  * Constructs message without payload.
00088  * @param type FUSE message type
00089  */
00090 FuseNetworkMessage::FuseNetworkMessage(FUSE_message_type_t type)
00091 {
00092   __content = NULL;
00093   _msg.header.message_type = htonl(type);
00094   _msg.header.payload_size = htonl(0);
00095   _msg.payload = NULL;
00096 }
00097
00098 
00099 /** Content constructor.
00100  * Construct a message with complex message content.
00101  * @param type FUSE message type
00102  * @param content complex message content.
00103  */
00104 FuseNetworkMessage::FuseNetworkMessage(FUSE_message_type_t type, FuseMessageContent *content)
00105 {
00106   __content = content;
00107   _msg.header.message_type = htonl(type);
00108   _msg.header.payload_size = htonl(0);
00109   _msg.payload = NULL;
00110 }
00111 
00112 /** Destructor. */
00113 FuseNetworkMessage::~FuseNetworkMessage()
00114 {
00115   if ( __content == NULL ) {
00116     if ( _msg.payload != NULL ) {
00117       free(_msg.payload);
00118       _msg.payload = NULL;
00119     }
00120   } else {
00121     __content->free_payload();
00122     delete __content;
00123   }
00124 }
00125 
00126 /** Get message type.
00127  * @return message type
00128  */
00129 uint32_t
00130 FuseNetworkMessage::type() const
00131 {
00132   return ntohl(_msg.header.message_type);
00133 }
00134
00135 
00136 /** Get payload size.
00137  * @return payload size
00138  */
00139 size_t
00140 FuseNetworkMessage::payload_size() const
00141 {
00142   return ntohl(_msg.header.payload_size);
00143 }
00144
00145 
00146 /** Get pointer to payload.
00147  * @return pointer to payload.
00148  */
00149 void *
00150 FuseNetworkMessage::payload() const
00151 {
00152   return _msg.payload;
00153 }
00154
00155 
00156 /** Get plain message.
00157  * @return plain message
00158  */
00159 const FUSE_message_t &
00160 FuseNetworkMessage::fmsg() const
00161 {
00162   return _msg;
00163 }
00164
00165 
00166 /** Set payload.
00167  * Payload is referenced and ownership claimed.
00168  * @param payload payload
00169  * @param payload_size size of payload
00170  */
00171 void
00172 FuseNetworkMessage::set_payload(void *payload, size_t payload_size)
00173 {
00174   if ( payload_size > 0xFFFFFFFF ) {
00175     // cannot carry that many bytes
00176     throw fawkes::OutOfBoundsException("Payload too big", payload_size, 0, 0xFFFFFFFF);
00177   }
00178   _msg.payload = payload;
00179   _msg.header.payload_size = htonl(payload_size);
00180 }
00181
00182 
00183 /** Set from message.
00184  * @param msg reference to message. Content is deep-copied.
00185  */
00186 void
00187 FuseNetworkMessage::set(FUSE_message_t &msg)
00188 {
00189   memcpy(&_msg, &msg, sizeof(FUSE_message_t));
00190 }
00191 
00192 /** Pack data for sending.
00193  * Use this if any additional packing is needed before sending the data (for
00194  * example if using a DynamicBuffer).
00195  */
00196 void
00197 FuseNetworkMessage::pack()
00198 {
00199   if ( __content != NULL ) {
00200     __content->serialize();
00201     _msg.payload = __content->payload();
00202     _msg.header.payload_size = htonl(__content->payload_size());
00203   }
00204 }