interreality.org [VOS]
[Home] [About]
[Screenshots]
[Download]
[News]
[Community]
[Documentation] [Manual]
[Bugs & Requests] [Wiki]

/home/tetron/hack/vos/libs/vos/vos/messageblock.hh

Go to the documentation of this file.
00001 /*
00002     This file is part of the Virtual Object System of
00003     the Interreality project (http://interreality.org).
00004 
00005     Copyright (C) 2001-2003 Peter Amstutz
00006 
00007     This library is free software; you can redistribute it and/or
00008     modify it under the terms of the GNU Lesser General Public
00009     License as published by the Free Software Foundation; either
00010     version 2 of the License, or (at your option) any later version.
00011 
00012     This library is distributed in the hope that it will be useful,
00013     but WITHOUT ANY WARRANTY; without even the implied warranty of
00014     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015     Lesser General Public License for more details.
00016 
00017     You should have received a copy of the GNU Lesser General Public
00018     License along with this library; if not, write to the Free Software
00019     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
00020 
00021     Peter Amstutz <http://www.interreality.org>
00022 */
00023 
00024 #ifndef _MESSAGEBLOCK_HH_
00025 #define _MESSAGEBLOCK_HH_
00026 
00027 #include <iostream>
00028 #include <deque>
00029 
00030 #include <boost/thread/recursive_mutex.hpp>
00031 
00032 #include <vos/vos/vosdefs.hh>
00033 #include <vos/vutil/refcount.hh>
00034 
00035 #define MSGENC_BINARY_SINGLE  1
00036 #define MSGENC_BINARY_BLOCK   2
00037 #define MSGENC_XML           '<'
00038 
00039 namespace VOS
00040 {
00041     class MessageBlock;
00042     class Message;
00043 
00044 /**
00045     Stores some state information needed between calls to the Message parser, when
00046     a message has only been partially parsed.
00047     @internal
00048  */
00049 struct parse_state_t
00050 {
00051     MessageBlock* m;
00052     unsigned int chars_read;
00053     unsigned int expected_length;
00054     uint32_t nonce;
00055     bool done;
00056     void* extra;
00057     int read_quoted;
00058     std::istream* input;
00059 };
00060 
00061     class MBParser
00062     {
00063     public:
00064         virtual ~MBParser() { }
00065         virtual int parseUpdate(const std::string& s, uint32_t& nonce) = 0;
00066         virtual size_t getBufferSize() = 0;
00067         virtual size_t getExpectedSize() = 0;
00068     };
00069 
00070     class BinaryParser : public MBParser
00071     {
00072     private:
00073         std::string parse_buffer;
00074         uint32_t msgsize;
00075         uint8_t encoding;
00076         MessageBlock* msgblock;
00077         void readMsgBlock(const uint8_t* s, size_t input_length);
00078         unsigned int readSingleMsg(const uint8_t* s, size_t input_length);
00079 
00080     public:
00081         BinaryParser(MessageBlock* mb);
00082         virtual ~BinaryParser() { }
00083 
00084         virtual int parseUpdate(const std::string& s, uint32_t& nonce);
00085         virtual size_t getBufferSize();
00086         virtual size_t getExpectedSize();
00087     };
00088 
00089     class XmlParser : public MBParser
00090     {
00091     private:
00092         std::string parse_buffer;
00093         uint32_t msgsize;
00094         MessageBlock* msgblock;
00095         std::string parseWord(size_t& pos);
00096         std::string parseStringAttr(size_t& pos);
00097         uint32_t parseNumberAttr(size_t& pos);
00098         void readMsgBlock(size_t& pos);
00099         void readSingleMsg(size_t& pos, uint32_t& nonce, bool withLength);
00100 
00101     public:
00102         XmlParser(MessageBlock* mb);
00103         virtual ~XmlParser() { }
00104 
00105         virtual int parseUpdate(const std::string& s, uint32_t& nonce);
00106         virtual size_t getBufferSize();
00107         virtual size_t getExpectedSize();
00108     };
00109 
00110 
00111 /**  @class MessageBlock messageblock.hh vos/vos/messageblock.hh
00112      @ingroup libvos
00113 
00114      A message block is a list of messages which have been bundled
00115      together into a single block.  It is used for various purposes.
00116      One useful feature of a message block is that it is processed all
00117      at once: the first message will not be delivered until the entire
00118      message block has been received, parsed and queued.  This may be
00119      useful for supporting transactions.
00120  */
00121     class VOS_API MessageBlock : public VUtil::RefCounted
00122 {
00123 private:
00124     boost::recursive_mutex messageblock_mutex;
00125 
00126     MBParser* parser;
00127     std::deque<Message*> messages;
00128     std::string* formattedString;
00129     std::string name;
00130 
00131 public:
00132     MessageBlock();
00133     ~MessageBlock();
00134 
00135     /** Set the message block name.  This means the message block will
00136         be saved with this name rather than executed immediately.
00137         @param s the name
00138     */
00139     void setName(const std::string& s);
00140 
00141     /** @return the message block name
00142     */
00143     std::string getName();
00144 
00145     /** Add a message to the message block.
00146         @param n The position to insert into.  May be negative, in which case the position
00147         will be counted from the end.  To append to the end, use -1.
00148         @param m the message to insert
00149     */
00150     void insertMessage(int n, Message* m);
00151 
00152     /** Add a message to the message block.
00153         @param m the message to insert
00154     */
00155     inline void appendMessage(Message* m) { insertMessage(-1, m); };
00156 
00157     /** Remove a message from the message block.
00158         @param n The position to remove.
00159     */
00160     void removeMessage(int n);
00161 
00162     /** Retrieve a message from this messageblock.
00163         @param n The desired position.  May be negative, in which case
00164         the position will be counted from the end.  The very
00165         last element can be accessed using -1.
00166         @return The message at the desired position, or 0 if the index is invalid.
00167     */
00168     VUtil::vRef<Message> getMessage(int n);
00169 
00170     /** @return The last message or a null vRef if the message block is empty. */
00171     VUtil::vRef<Message> lastMessage();
00172 
00173     /** @return the number of messages in the messageblock. */
00174     int numMessages();
00175 
00176     /** Get the XML-like textual representation of this messageblock,
00177         suitable for logging to the user
00178      */
00179     std::string getFormattedString();
00180 
00181     /** Get the binary representation of this messageblock,
00182         suitable for sending over the network.
00183      */
00184     std::string getBinaryEncoding();
00185 
00186     /** Internal parsing function.  Update the current partial parse
00187         of this messageblock with new data.
00188         @param s the new data
00189         @return The number of bytes from the beginning of 's' which
00190         were read in.
00191     */
00192     int parseUpdate(const std::string& s, uint32_t& nonce);
00193 
00194     /** @return the number of bytes received so far in the process of downloading
00195         this message or message block
00196     */
00197     unsigned int getReceivedBytes();
00198 
00199     /** @return the number of bytes expected in total for this message
00200         or message block
00201     */
00202     unsigned int getExpectedBytes();
00203 };
00204 
00205 }
00206 
00207 #endif