/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