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

/home/tetron/hack/vos/libs/vos/vos/message.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 #ifndef _MESSAGE_HH_
00024 #define _MESSAGE_HH_
00025 
00026 #include <stdexcept>
00027 #include <string>
00028 #include <deque>
00029 #include <iostream>
00030 
00031 #include <vos/vos/vosdefs.hh>
00032 #include <vos/vutil/refcount.hh>
00033 #include <vos/vos/site.hh>
00034 
00035 /** @file
00036     Defines Message.
00037 */
00038 
00039 namespace VOS
00040 {
00041     class Site;
00042     class MessageContext;
00043     class Vobject;
00044 
00045     /** @class NoSuchFieldError message.hh vos/vos/message.hh
00046         @ingroup libvos
00047         Thrown when getField() is passed an out-of-range parameter
00048     */
00049     class VOS_API NoSuchFieldError : public std::runtime_error {
00050     public:
00051         NoSuchFieldError(const std::string& s) : std::runtime_error(s) { };
00052         static const char* errorCode() { return "400"; }
00053     };
00054 
00055     /**
00056      */
00057     struct VOS_API SendingCompletedCallback
00058     {
00059         virtual ~SendingCompletedCallback() { }
00060         virtual void notifySendingCompleted(VOS::Message* m) = 0;
00061     };
00062 
00063     /** @class MsgField message.hh vos/vos/message.hh
00064         @ingroup libvos
00065         A key-value field pair used to store the fields of a Message
00066     */
00067     class VOS_API MsgField : public VUtil::RefCounted {
00068     public:
00069         MsgField(const std::string& k, const std::string v, bool q) : key(k), value(v), quoted(q) { };
00070         std::string key; /**< the key or tag for this field */
00071         std::string value; /**< the value of this field */
00072         bool quoted;
00073 
00074         const std::string &getKey()
00075             { return key; }
00076         const std::string &getValue()
00077             { return value; }
00078 
00079         bool operator==(const MsgField &otherfield) const
00080             {
00081                 return (this->key == otherfield.key
00082                         && this->value == otherfield.value
00083                         && this->quoted == otherfield.quoted);
00084             }
00085         bool operator!=(const MsgField &otherfield) const
00086             { return !operator==( otherfield ); }
00087     };
00088 
00089 /** @class Message message.hh vos/vos/message.hh
00090     @ingroup libvos
00091 
00092     This class handles storing, generating and parsing of the messages
00093     that are sent between virtual objects.
00094  */
00095 class VOS_API Message : public VUtil::RefCounted
00096 {
00097 public:
00098     enum Priority { Normal, LowLatency, Bulk };
00099 private:
00100     mutable boost::mutex message_mutex;
00101 
00102     std::string type;
00103     std::string to;
00104     std::string from;
00105     std::string method;
00106     uint32_t nonce;
00107     std::string timestamp;
00108 
00109     VUtil::vRef<Site> source_site;
00110     mutable std::string* formattedString;
00111     std::deque< VUtil::vRef<MsgField> > fields;
00112 
00113     std::string* (*format_func)(const std::string& type,
00114                                 const std::string& to,
00115                                 const std::string& from,
00116                                 const std::string& method,
00117                                 uint32_t nonce,
00118                                 const std::string& timestamp,
00119                                 const std::deque< VUtil::vRef<MsgField> >& fields,
00120                                 bool withLength);
00121 
00122     Priority priority;
00123     SendingCompletedCallback* sendComplete;
00124 
00125 public:
00126     /** Create a new message. */
00127     Message();
00128 
00129     /** Initialize this message.  Will set the message type as
00130         "message", set the "to" field to v->getURLstr(), set
00131         the method field with the supplied method, and optionally
00132         generate a random value for the nonce field.
00133         @param v used to set the "to" field
00134         @param method used to set the "method" field
00135         @param withnonce if true, generate a random string for the nonce field
00136     */
00137     Message(Vobject* v, const std::string& method, bool withnonce,
00138             Priority priority = Normal);
00139 
00140     /** Initialize this message as a reply to a message.  Will set the
00141         message type as "update", set "to" using
00142         in_reply_to->getFrom(), set "from" using v->getURLstr(), and
00143         set the nonce using in_reply_to->getNonce(), and set the
00144         method to the supplied.
00145         @param v used to initialize the "from" fields
00146         @param in_reply_to used to initalize the "to" and "nonce" fields
00147         @param method used to initialize the "method" field
00148     */
00149     Message(Vobject* v, Message* in_reply_to, const std::string& method,
00150             Priority priority = Normal);
00151 
00152     /** Copy a message. */
00153     Message(Message& m);
00154 
00155     /** Destroy this message. */
00156     ~Message();
00157 
00158     /** Set what type of message this is.  You probably want it to be either
00159         "message" or "update".
00160         @param s the types
00161     */
00162     void setType(const std::string& s);
00163 
00164     /** Set whom this message is intended for.  This should probably
00165         be the URL std::string of the object to which the message is destined.
00166         @param s the to field
00167     */
00168     void setTo(const std::string& s);
00169 
00170     /** Set whom this message is sent by.  This should probably
00171         be the URL std::string of the object which is generating this message.
00172         @param s the from field
00173     */
00174     void setFrom(const std::string& s);
00175 
00176     /** Set the method action this message is expressing.
00177         @param s the method field
00178     */
00179     void setMethod(const std::string& s);
00180 
00181     /** Set the nonce field.  The nonce is used to match a match a
00182         reply against a request (because the reply bears the same
00183         nonce as the originating message.)
00184         @param s the nonce field
00185     */
00186     void setNonce(uint32_t n);
00187 
00188     /** Set the timestamp (optional, useful for applications, not
00189         actually used by VOS core).
00190         @param s the timestamp field
00191     */
00192     void setTimestamp(const std::string& s);
00193 
00194     /** Set the source site.  This is not a field in the message
00195         itself, but rather is used to set the site originating this
00196         message (that is to say, which socket the message was received
00197         on.)  This is compared against the "from" field to provide a
00198         simple filter against really obvious spoofing.  You do not
00199         need to set this if you are creating a new message to be sent;
00200         rather it is set for messages received from the network.
00201         @param source_site the source site
00202     */
00203     void setSourceSite(Site* source_site);
00204 
00205     /** @return the type field.  setType() has a bit more information about this field. */
00206     std::string getType() const;
00207 
00208     /** Get the to field.
00209         @return the to field  setTo() has a bit more information about this field. */
00210     std::string getTo() const;
00211 
00212     /** Get the from field.
00213         @return the from field  setFrom() has a bit more information about this field. */
00214     std::string getFrom() const;
00215 
00216     /** Get the method field.
00217         @return the method field  setMethod() has a bit more information about this field. */
00218     std::string getMethod() const;
00219 
00220     /** Get the nonce field.
00221         @return the nonce field  setNonce() has a bit more information about this field. */
00222     uint32_t getNonce() const;
00223 
00224     /** Get the timestamp field.
00225         @return the timestamp field  setTimestamp() has a bit more information about this field. */
00226     std::string getTimestamp() const;
00227 
00228     /** Get whether there is anything in the to field.
00229         @return if there is a to field  setTo() has a bit more information about this field. */
00230     bool hasTo() const;
00231 
00232     /** Get whether there is anything in the from field.
00233         @return if there is a from field  setFrom() has a bit more information about this field. */
00234     bool hasFrom() const;
00235 
00236     /** Get whether there is anything in the method field.
00237         @return if there is a method field  setMethod() has a bit more information about this field. */
00238     bool hasMethod() const;
00239 
00240     /** Get whether there is anything in the nonce field.
00241         @return if there is a nonce field  setNonce() has a bit more information about this field. */
00242     bool hasNonce() const;
00243 
00244     /** Get whether there is anything in the timestamp field.
00245         @return if there is a timestamp field  setTimestamp() has a bit more information about this field. */
00246     bool hasTimestamp() const;
00247 
00248     /** Get the source site.  This is the site that actually generated
00249         this message.  MAY BE ZERO IF THE MESSAGE WAS GENERATED
00250         LOCALLY.  If so, you'll need to do the following to determine
00251         the source site:
00252         Site::findSite(URL(themsg.getFrom()).getHostAndPort())
00253         @return the source site
00254     */
00255     VUtil::vRef<Site> getSourceSite() const;
00256 
00257     /** Get the number of ordinary fields.
00258         @return the number of ordinary fields in this message */
00259     int numFields() const;
00260 
00261     /** Have the message fill in the nonce field with a random nonce. */
00262     void generateNonce();
00263 
00264     bool hasField(const std::string& key) const;
00265 
00266     /** Get the first field which matches the supplied key.  Note that
00267         this field list is SEPARATE from the type/to/from/method/nonce
00268         fields.
00269         @param key the tag to match
00270         @return the first instance of a field which matchs that tag
00271         @throw NoSuchFieldError if the field is not found
00272     */
00273     VUtil::vRef<MsgField> getField(const std::string& key) const;
00274 
00275     /** Get the first field which matches the supplied key.  Note that
00276         this field list is SEPARATE from the type/to/from/method/nonce
00277         fields.
00278         @param n the field at position n, where n is the array offset from 0.
00279         @return the first instance of a field which matchs that tag
00280         @throw NoSuchFieldError if the field is not found
00281     */
00282     VUtil::vRef<MsgField> getField(int n) const;
00283 
00284     /** Insert a new field.
00285         @note On positions: if a position is zero or positive, its
00286         meaning is as you would expect, expressing the offset into an
00287         array of fields.  However, if the position is negative, it
00288         expresses the offset from the end of the list.  This means for
00289         a list of length m, -1 is the last item in the list (equal to
00290         position position m - 1) and -m is the first item (equal to
00291         positive position 0).  If the position is positive, the field
00292         is inserted such that it now occupies that position, and all
00293         fields starting from the previous occupant of that position
00294         onward are moved up one.  If the position in negative, the
00295         field is similarly inserted so that it now occupies that
00296         position.  For example, position -1 will append the field to
00297         the end of the list, position -2 will insert the field in the
00298         second-to-last position, etc.
00299         @param n the position, as explained above
00300         @param key the key (or tag) to associate the value with
00301         @param val the value of this field
00302         @param quoted not really used and should be removed...
00303     */
00304     void insertField(int n, const std::string& key, const std::string& val, bool quoted = false);
00305 
00306     /** Insert a new field.
00307         @copydoc insertField(int n, const std::string& key, const std::string& val, bool quoted = false)
00308         @param n the position, as explained above
00309         @param key the key (or tag) to associate the value with
00310         @param val the value of this field
00311     */
00312     void insertField(int n, const std::string& key, double val);
00313 
00314     /** Insert a new field.
00315         @param n the position, as explained above
00316         @param key the key (or tag) to associate the value with
00317         @param val the value of this field
00318     */
00319     void insertField(int n, const std::string& key, int val);
00320 
00321     /** Insert a new field.
00322         @param n the position, as explained above
00323         @param key the key (or tag) to associate the value with
00324         @param val the value of this field
00325     */
00326     void insertField(int n, const std::string& key, unsigned int val);
00327 
00328     /** Append a new field.
00329         @param key the key (or tag) to associate the value with
00330         @param val the value of this field
00331         @param quoted not used and should be removed...
00332      */
00333     inline void appendField(const std::string& key, const std::string& val, bool quoted = false)
00334         { insertField(-1, key, val, quoted); }
00335 
00336     /** Append a new field.
00337         @param key the key (or tag) to associate the value with
00338         @param val the value of this field
00339      */
00340     inline void appendField(const std::string& key, double val)
00341         { insertField(-1, key, val); }
00342 
00343     /** Append a new field.
00344         @param key the key (or tag) to associate the value with
00345         @param val the value of this field
00346      */
00347     inline void appendField(const std::string& key, int val)
00348         { insertField(-1, key, val); }
00349 
00350     /** Remove an existing field at some position.  See insertField()
00351         for details about the legal numerical values of the position.
00352         @param n the position
00353     */
00354     void removeField(int n);
00355 
00356     /** Remove the first instance of a field with the supplied key.
00357         @param s the key of the field to remove
00358     */
00359     void removeField(const std::string& s);
00360 
00361     /** Clear all the fields of this message added with insertField()
00362         or appendField().
00363     */
00364     void clearFields();
00365 
00366 #ifndef SWIG
00367     /** Set the function which converts this message structure into a
00368         string.  End users don't need to call this, as it is set to
00369         the default when the message is constructed.
00370         @note The more object-oriented way of doing this would be to
00371         create a function object type.  This interface may change.
00372     */
00373     void setFormatFunc(std::string* (*func)(const std::string& type,
00374                                             const std::string& to,
00375                                             const std::string& from,
00376                                             const std::string& method,
00377                                             uint32_t nonce,
00378                                             const std::string& timestamp,
00379                                             const std::deque< VUtil::vRef<MsgField> >& fields,
00380                                             bool withLength));
00381 #endif
00382 
00383     /** Get the message formatted with the function supplied
00384         in setFormatFunc().
00385         @return the formatted std::string
00386     */
00387     const std::string& getFormattedString(bool withLength = true) const;
00388 
00389     void setPriority(Priority p) { priority = p; }
00390     Priority getPriority() { return priority; }
00391 
00392     void setSendingCompletedCallback(SendingCompletedCallback* scc);
00393     SendingCompletedCallback* getSendingCompletedCallback();
00394 
00395     friend class msgFlexLexer;
00396 };
00397 
00398 #ifndef SWIG
00399 /** Converts a message into an XML format message */
00400 std::string* xmlFormatting(const std::string& type,
00401                            const std::string& to,
00402                            const std::string& from,
00403                            const std::string& method,
00404                            uint32_t nonce,
00405                            const std::string& timestamp,
00406                            const std::deque< VUtil::vRef<MsgField> >& fields,
00407                            bool withLength);
00408 
00409 std::string* binaryFormatting(const std::string& type,
00410                                    const std::string& to,
00411                                    const std::string& from,
00412                                    const std::string& method,
00413                                    uint32_t nonce,
00414                                    const std::string& timestamp,
00415                                    const std::deque< VUtil::vRef<MsgField> >& fields,
00416                                    bool withLength);
00417 #endif
00418 
00419 }
00420 
00421 #endif