Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Namespace Members | Compound Members | File Members | Related Pages | Examples

vos/corelibs/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 <tetron@interreality.org>
00022 */
00023 #ifndef _MESSAGE_HH_
00024 #define _MESSAGE_HH_
00025 
00026 #include <vos/corelibs/vos/vosdefs.hh>
00027 #include <vos/corelibs/vos/refcount.hh>
00028 #include <vos/corelibs/vos/msglexer.hh>
00029 
00030 #include <stdexcept>
00031 #include <string>
00032 #include <deque>
00033 
00034 // #define LEAKYSET_DEBUG
00035 
00036 /** @file
00037     Defines Message.
00038 */
00039 
00040 namespace VOS
00041 {
00042     class Site;
00043     class MessageContext;
00044 
00045 /** @class Message message.hh vos/corelibs/vos/message.hh
00046  *
00047  * This class handles storing, generating and parsing of the messages
00048  *  that are sent between virtual objects.
00049  */
00050 class VOS_API Message : public virtual RefCounted
00051 {
00052 public:
00053     /** Thrown when getField() is passed an out-of-range parameter */
00054     class NoSuchFieldError : public runtime_error {
00055     public:
00056         NoSuchFieldError(const string& s) : runtime_error(s) { }
00057     };
00058 
00059     /** A key-value field pair used to store the fields of the message */
00060     struct Field {
00061         string key; /**< the key or tag for this field */
00062         string value; /**< the value of this field */
00063         string source; /**< the value of this field before doing substitution */
00064         bool quoted;
00065     };
00066 private:
00067     string type;
00068     string to;
00069     string from;
00070     string method;
00071     string nonce;
00072     double mtime;
00073     string dependsOn;
00074     Site* source_site;
00075     MessageContext* messageContext;
00076     string* formattedString;
00077     deque<Field> fields;
00078     void* parse_extra;
00079 
00080     string parse_buffer;
00081     string* (*format_func)(const string& type,
00082                            const string& to,
00083                            const string& from,
00084                            const string& method,
00085                            const string& nonce,
00086                            const string& dependsOn,
00087                            double mtime,
00088                            const deque<Field>& fields,
00089                            bool withLength);
00090     int (*parse_func)(Message& m,
00091                       void* extra,
00092                       const string& str);
00093     static int refcount_debug_counter;
00094 #ifdef LEAKYSET_DEBUG
00095     static set<Message*> leakySet;
00096 #endif
00097 public:
00098     int refcount_debug;
00099     int incoming_debug;
00100 
00101     /** Create a new message. */
00102     Message();
00103 
00104     /** Copy a message. */
00105     Message(Message& m);
00106 
00107     /** Destroy this message. */
00108     ~Message();
00109 
00110     /** Set what type of message this is.  You probably want it to be either
00111         "message" or "update".
00112         @param s the types
00113     */
00114     void setType(const string& s);
00115 
00116     /** Set whom this message is intended for.  This should probably
00117         be the URL string of the object to which the message is destined.
00118         @param s the to field
00119     */
00120     void setTo(const string& s);
00121 
00122     /** Set whom this message is sent by.  This should probably
00123         be the URL string of the object which is generating this message.
00124         @param s the from field
00125     */
00126     void setFrom(const string& s);
00127 
00128     /** Set the method action this message is expressing.
00129         @param s the method field
00130     */
00131     void setMethod(const string& s);
00132 
00133     /** Set the nonce field.  The nonce is used to match a match a
00134         reply against a request (because the reply bears the same
00135         nonce as the originating message.)
00136         @param s the nonce field
00137     */
00138     void setNonce(const string& s);
00139 
00140     /** Set the time field, in seconds.  This is used by the message
00141         delivery scheduler to determine when to deliver this message,
00142         useful for scripted events in MessageBlock objects.
00143         @param time the time field
00144     */
00145     void setTime(double time);
00146 
00147     /** Set the source site.  This is not a field in the message
00148         itself, but rather is used to set the site originating this
00149         message (that is to say, which socket the message was received
00150         on.)  This is compared against the "from" field to provide a
00151         simple filter against really obvious spoofing.  You do NOT
00152         need to set this if you are creating a new message to be sent;
00153         it is only used for messages received from the network.
00154         @param s the source site
00155     */
00156     void setSourceSite(Site* source_site);
00157 
00158     /** Indicate the message block this message is contained in.  Does
00159         not actually add itself to the message block, however (you
00160         really want to be using MessageBlock::insertMessage())
00161         @param mb the message block
00162     */
00163     void setMessageContext(MessageContext* mb);
00164 
00165     void setDependency(const string& nonce);
00166 
00167     /** @return the type field.  setType() has a bit more information about this field. */
00168     const string& getType() const;
00169 
00170     /** Get the to field.
00171         @return the to field  setTo() has a bit more information about this field. */
00172     string getTo() const;
00173 
00174     /** Get the from field.
00175         @return the from field  setFrom() has a bit more information about this field. */
00176     string getFrom() const;
00177 
00178     /** Get the method field.
00179         @return the method field  setMethod() has a bit more information about this field. */
00180     string getMethod() const;
00181 
00182     /** Get the nonce field.
00183         @return the nonce field  setNonce() has a bit more information about this field. */
00184     string getNonce() const;
00185 
00186     /** Get whether there is anything in the to field.
00187         @return if there is a to field  setTo() has a bit more information about this field. */
00188     bool hasTo() const;
00189 
00190     /** Get whether there is anything in the from field.
00191         @return if there is a from field  setFrom() has a bit more information about this field. */
00192     bool hasFrom() const;
00193 
00194     /** Get whether there is anything in the method field.
00195         @return if there is a method field  setMethod() has a bit more information about this field. */
00196     bool hasMethod() const;
00197 
00198     /** Get whether there is anything in the nonce field.
00199         @return if there is a nonce field  setNonce() has a bit more information about this field. */
00200     bool hasNonce() const;
00201 
00202     /** Get whether there is anything in the dependency field.
00203         @return if there is a dependency field  setDependency() has a bit more information about this field. */
00204     bool hasDependency() const;
00205 
00206     /** Get time field, used for scheduling.
00207         @return the time field.  getTime() has a bit more information about this field. */
00208     double getTime() const;
00209 
00210     /** Get the source site.  This is the site that actually generated
00211         this message.  MAY BE ZERO IF THE MESSAGE WAS GENERATED
00212         LOCALLY.  If so, you'll need to do the following to determine
00213         the source site:
00214         Site::findSite(URL(themsg.getFrom()).getHostAndPort())
00215         @return the source site, if any; NOTE YOU MUST CALL release() WHEN DONE OR USE vRef.
00216     */
00217     Site* getSourceSite();
00218 
00219     /** Get the message block this message is contained in.  May be NULL.
00220         @return the message block;  NOTE YOU MUST CALL release() WHEN DONE OR USE vRef.
00221     */
00222     MessageContext* getMessageContext();
00223 
00224     /** Get the nonce of the OUTGOING REPLIES that this message depends on before
00225         it can be delivered, used to determine message context.
00226         This is a comma-separeted @em no spaces!
00227     */
00228     string getDependency();
00229 
00230     /** Get the number of ordinary fields.
00231         @return the number of ordinary fields in this message */
00232     int getNumFields() const;
00233 
00234     /** Have the message fill in the nonce field with a random nonce. */
00235     void generateNonce();
00236 
00237     /** Get the first field which matches the supplied key.  Note that
00238         this field list is SEPERATE from the type/to/from/method/nonce
00239         fields.
00240         @param key the tag to match
00241         @return the first instance of a field which matchs that tag
00242         @throw NoSuchFieldError if the field is not found
00243     */
00244     const struct Field& getField(const string& key) throw (NoSuchFieldError);
00245 
00246     /** Get the first field which matches the supplied key.  Note that
00247         this field list is SEPERATE from the type/to/from/method/nonce
00248         fields.
00249         @param n the field at position n, where n is the array offset from 0.
00250         @return the first instance of a field which matchs that tag
00251         @throw NoSuchFieldError if the field is not found
00252     */
00253     const struct Field& getField(int n) throw (NoSuchFieldError);
00254 
00255     /** Insert a new field.
00256         @note On positions: if a position is zero or positive, its
00257         meaning is as you would expect, expressing the offset into an
00258         array of fields.  However, if the position is negative, it
00259         expresses the offset from the end of the list.  This means for
00260         a list of length m, -1 is the last item in the list (equal to
00261         position position m - 1) and -m is the first item (equal to
00262         positive position 0).  If the position is positive, the field
00263         is inserted such that it now occupies that position, and all
00264         fields starting from the previous occupant of that position
00265         onward are moved up one.  If the position in negative, the
00266         field is similarly inserted so that it now occupies that
00267         position.  For example, position -1 will append the field to
00268         the end of the list, position -2 will insert the field in the
00269         second-to-last position, etc.
00270         @param n the position, as explained above
00271         @param key the key (or tag) to associate the value with
00272         @param val the value of this field
00273         @param whether this field is "quoted", eg suppress $(foo) substition
00274     */
00275     void insertField(int n, const string& key, const string& val, bool quoted = false);
00276 
00277     /** Insert a new field.
00278         @note On positions: if a position is zero or positive, its
00279         meaning is as you would expect, expressing the offset into an
00280         array of fields.  However, if the position is negative, it
00281         expresses the offset from the end of the list.  This means for
00282         a list of length m, -1 is the last item in the list (equal to
00283         position position m - 1) and -m is the first item (equal to
00284         positive position 0).  If the position is positive, the field
00285         is inserted such that it now occupies that position, and all
00286         fields starting from the previous occupant of that position
00287         onward are moved up one.  If the position in negative, the
00288         field is similarly inserted so that it now occupies that
00289         position.  For example, position -1 will append the field to
00290         the end of the list, position -2 will insert the field in the
00291         second-to-last position, etc.
00292         @param n the position, as explained above
00293         @param key the key (or tag) to associate the value with
00294         @param val the value of this field
00295     */
00296     void insertField(int n, const string& key, double val);
00297 
00298     /** Insert a new field.
00299         @note On positions: if a position is zero or positive, its
00300         meaning is as you would expect, expressing the offset into an
00301         array of fields.  However, if the position is negative, it
00302         expresses the offset from the end of the list.  This means for
00303         a list of length m, -1 is the last item in the list (equal to
00304         position position m - 1) and -m is the first item (equal to
00305         positive position 0).  If the position is positive, the field
00306         is inserted such that it now occupies that position, and all
00307         fields starting from the previous occupant of that position
00308         onward are moved up one.  If the position in negative, the
00309         field is similarly inserted so that it now occupies that
00310         position.  For example, position -1 will append the field to
00311         the end of the list, position -2 will insert the field in the
00312         second-to-last position, etc.
00313         @param n the position, as explained above
00314         @param key the key (or tag) to associate the value with
00315         @param val the value of this field
00316     */
00317     void insertField(int n, const string& key, int val);
00318 
00319     /** Remove an existing field at some position.  See insertField()
00320         for details about the legal numerical values of the position.
00321         @param n the position
00322     */
00323     void removeField(int n);
00324 
00325     /** Remove the first instance of a field with the supplied key.
00326         @param s the key of the field to remove
00327     */
00328     void removeField(const string& s);
00329 
00330     /** Set the function which converts this message structure into a
00331         string.  End users don't need to call this, as it is set to
00332         the default when the message is constructed.
00333         @note The more object-oriented way of doing this would be to
00334         create a function object type.  This interface may change.  */
00335     void setMappingFunc(string* (*func)(const string& type,
00336                                         const string& to,
00337                                         const string& from,
00338                                         const string& method,
00339                                         const string& nonce,
00340                                         const string& dependsOn,
00341                                         double mtime,
00342                                         const deque<Message::Field>& fields,
00343                                         bool withLength));
00344 
00345     /* Set the function which will parse some string into a message
00346         structure.  End users don't need to call this, as it is set to
00347         the default when the message is constructed.
00348         @note The more object-oriented way of doing this would be to
00349         create a function object type.  This interface may change.
00350 
00351         *** parsing moved to MessageBlock class
00352 
00353     void setParseFunc(int (*func)(void* extra,
00354                                   const string& s),
00355                       void* extra,
00356                       void (*delete_extra)(void* extra));
00357     */
00358 
00359     /** Get the message formatted with the function supplied
00360         in setMappingFunc().
00361         @return the formatted string
00362     */
00363     const string& getFormattedString(bool withLength=true);
00364 
00365     /** Print out a string value for the message with substitutions done,
00366         to make it easier to tell what the processed message actually looked like.
00367     */
00368     string getLoggableString();
00369 
00370     /* Add some data to be parsed using the parse function supplied
00371         in setParseFunc().
00372         @return the number of characters read
00373 
00374         *** parsing moved to MessageBlock class
00375     int parseUpdate(const string& data);
00376 */
00377 
00378     /** Internal debugging function. */
00379 #ifdef LEAKYSET_DEBUG
00380     static void printLeakySet();
00381 #endif
00382 
00383     friend int msgFlexLexer::yylex();
00384 };
00385 
00386 /** Converts a message into an XML format message */
00387 string* xmlFormatting(const string& type,
00388                       const string& to,
00389                       const string& from,
00390                       const string& method,
00391                       const string& nonce,
00392                       const string& dependsOn,
00393                       double mtime,
00394                       const deque<Message::Field>& fields,
00395                       bool withLength);
00396 }
00397 
00398 #endif

Generated on Tue Aug 12 03:55:40 2003 for Interreality Project - VOS by doxygen 1.3.2