00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "message.hh"
00025 #include "log.hh"
00026 #include "site.hh"
00027 #include "messagecontext.hh"
00028
00029 #include <sys/types.h>
00030 #include <stdio.h>
00031
00032 using namespace VOS;
00033
00034
00035
00036
00037
00038 int Message::refcount_debug_counter=0;
00039
00040 #ifdef LEAKYSET_DEBUG
00041 set<Message*> Message::leakySet;
00042 #endif
00043
00044 Message::Message() : mtime(0.0), source_site(0), messageContext(0), formattedString(0)
00045 {
00046 setMappingFunc(xmlFormatting);
00047 refcount_debug = ++refcount_debug_counter;
00048 incoming_debug = 0;
00049 LOG("message", 5, "created message " << refcount_debug);
00050 #ifdef LEAKYSET_DEBUG
00051 leakySet.insert(this);
00052 #endif
00053 }
00054
00055 Message::Message(Message& m) : type(m.type), to(m.to),
00056 from(m.from), method(m.method), nonce(m.nonce), mtime(m.mtime),
00057 dependsOn(m.dependsOn), source_site(m.source_site),
00058 messageContext(m.messageContext), formattedString(m.formattedString),
00059 fields(m.fields), parse_extra(m.parse_extra), parse_buffer(m.parse_buffer),
00060 format_func(m.format_func), parse_func(m.parse_func)
00061 {
00062 refcount_debug = ++refcount_debug_counter;
00063 LOG("message", 5, "created message " << refcount_debug);
00064 #ifdef LEAKYSET_DEBUG
00065 leakySet.insert(this);
00066 #endif
00067 }
00068
00069
00070 Message::~Message()
00071 {
00072 if(formattedString) delete formattedString;
00073 LOG("refcount", 5, "message: deleting message [" << refcount_debug << "]");
00074 if(source_site) {
00075 LOG("refcount", 5, "about to release source site, count is " << source_site->getCount());
00076 source_site->release();
00077 }
00078 if(messageContext) messageContext->release();
00079 #ifdef LEAKYSET_DEBUG
00080 leakySet.erase(this);
00081 #endif
00082 }
00083
00084 #ifdef LEAKYSET_DEBUG
00085 void Message::printLeakySet()
00086 {
00087 LOG("leakyset", 5, "size of set is " << leakySet.size());
00088 for(set<Message*>::iterator i = leakySet.begin(); i != leakySet.end(); i++) {
00089 pREF(Site*, s, (*i)->getSourceSite(),
00090 if(s) {
00091 LOG("leakyset", 5, "Source site is " << s->getURL().getString()
00092 << " leaky msg is " << (*i)->getFormattedString());
00093 } else {
00094 LOG("leakyset", 5, "No source site, leaky msg is " << (*i)->getFormattedString());
00095 }
00096 );
00097 }
00098 }
00099 #endif
00100
00101 #define RESET_FMTSTR { \
00102 if(formattedString) { \
00103 delete formattedString; \
00104 formattedString=0; \
00105 } \
00106 }
00107
00108
00109 void Message::setTo(const string& s) { to=s; RESET_FMTSTR; }
00110 void Message::setType(const string& s) { type=s; RESET_FMTSTR; }
00111 void Message::setFrom(const string& s) { from=s; RESET_FMTSTR; }
00112 void Message::setMethod(const string& s) { method=s; RESET_FMTSTR; }
00113 void Message::setNonce(const string& s) { nonce=s; RESET_FMTSTR; }
00114 void Message::setTime(double t) { mtime = t; RESET_FMTSTR; }
00115 void Message::setSourceSite(Site* s) {
00116 if(source_site) source_site->release();
00117 if(s) s->acquire();
00118 source_site=s;
00119 }
00120 void Message::setMessageContext(MessageContext* mb) {
00121 if(messageContext) messageContext->release();
00122 if(mb) mb->acquire();
00123 messageContext=mb;
00124 }
00125 void Message::setDependency(const string& nonce) {
00126 dependsOn = nonce;
00127 RESET_FMTSTR;
00128 }
00129
00130 bool Message::hasTo() const
00131 {
00132 return (to != "");
00133 }
00134
00135 bool Message::hasFrom() const
00136 {
00137 return (from != "");
00138 }
00139
00140 bool Message::hasMethod() const
00141 {
00142 return (method != "");
00143 }
00144
00145 bool Message::hasNonce() const
00146 {
00147 return (nonce != "");
00148 }
00149
00150 bool Message::hasDependency() const
00151 {
00152 return (dependsOn != "");
00153 }
00154
00155 string Message::getTo() const {
00156 string s = to;
00157 if(messageContext) messageContext->doSubstitution(s);
00158 return s;
00159 }
00160 string Message::getFrom() const {
00161 string s = from;
00162 if(messageContext) messageContext->doSubstitution(s);
00163 return s;
00164 }
00165 string Message::getMethod() const {
00166 string s = method;
00167 if(messageContext) messageContext->doSubstitution(s);
00168 return s;
00169 }
00170 const string& Message::getType() const { return type; }
00171 string Message::getNonce() const {
00172 string s = nonce;
00173 if(messageContext) messageContext->doSubstitution(s);
00174 return s;
00175 }
00176 double Message::getTime() const { return mtime; }
00177 Site* Message::getSourceSite() {
00178 if(source_site) {
00179 source_site->acquire();
00180 return source_site;
00181 } else return 0;
00182 }
00183 MessageContext* Message::getMessageContext()
00184 {
00185 if(messageContext) {
00186 messageContext->acquire();
00187 return messageContext;
00188 } else return 0;
00189 }
00190 string Message::getDependency() {
00191 string s = dependsOn;
00192 if(messageContext) messageContext->doSubstitution(s);
00193 return s;
00194 }
00195 int Message::getNumFields() const { return (int)fields.size(); }
00196
00197 void Message::generateNonce()
00198 {
00199 char nonce[16];
00200 snprintf(nonce, sizeof(nonce), "%i", (int)rand());
00201 setNonce(string(nonce));
00202 }
00203
00204 const Message::Field& Message::getField(const string& key) throw (NoSuchFieldError)
00205 {
00206 for(deque<Field>::iterator i = fields.begin(); i != fields.end(); i++) {
00207 if((*i).key == key) {
00208 (*i).value = (*i).source;
00209 if(messageContext && !(*i).quoted) messageContext->doSubstitution((*i).value);
00210 return (*i);
00211 }
00212 }
00213 throw NoSuchFieldError(string("No such field tag ") + key);
00214 }
00215
00216 const Message::Field& Message::getField(int n) throw (NoSuchFieldError)
00217 {
00218 if(n < 0) n = (int)fields.size() + n + 1;
00219 if(n >= (int)fields.size()) throw NoSuchFieldError("Field index out of range");
00220 Field& f = fields[n];
00221 f.value = f.source;
00222 if(messageContext && !f.quoted) messageContext->doSubstitution(f.value);
00223 return f;
00224 }
00225
00226 void Message::insertField(int n, const string& key, const string& val, bool quoted)
00227 {
00228
00229 if(n < 0) n = (int)fields.size() + n + 1;
00230 Field f;
00231 f.key = key;
00232 f.source = val;
00233 f.quoted = quoted;
00234 if(!quoted) {
00235
00236 for(unsigned int i = 0; i < val.length(); i++) {
00237 if(val[i] == '<' || val[i] == '>' || val[i] == '\0') {
00238 f.quoted = true;
00239 break;
00240 }
00241 }
00242 }
00243 fields.insert(fields.begin()+n, f);
00244 RESET_FMTSTR;
00245 }
00246
00247 void Message::insertField(int n, const string& key, int val)
00248 {
00249
00250 if(n < 0) n = (int)fields.size() + n + 1;
00251 Field f;
00252 f.key = key;
00253 char s[32];
00254 snprintf(s, sizeof(s), "%i", val);
00255 f.source = s;
00256 f.quoted = false;
00257
00258 fields.insert(fields.begin()+n, f);
00259 RESET_FMTSTR;
00260 }
00261
00262 void Message::insertField(int n, const string& key, double val)
00263 {
00264
00265 if(n < 0) n = (int)fields.size() + n + 1;
00266 Field f;
00267 f.key = key;
00268 char s[32];
00269 snprintf(s, sizeof(s), "%f", val);
00270 f.source = s;
00271 f.quoted = false;
00272 fields.insert(fields.begin()+n, f);
00273 RESET_FMTSTR;
00274 }
00275
00276 void Message::removeField(int n)
00277 {
00278 if(n < 0) n = (int)fields.size() + n;
00279 fields.erase(fields.begin()+n);
00280 RESET_FMTSTR;
00281 }
00282
00283 void Message::removeField(const string& key)
00284 {
00285 for(unsigned int i=0; i < fields.size(); i++) {
00286 if(fields[i].key==key) {
00287 fields.erase(fields.begin()+i);
00288 break;
00289 }
00290 }
00291 RESET_FMTSTR;
00292 }
00293
00294
00295 void Message::setMappingFunc(string* (*func)(const string& type,
00296 const string& to,
00297 const string& from,
00298 const string& method,
00299 const string& nonce,
00300 const string& dependsOn,
00301 double mtime,
00302 const deque<Message::Field>& fields,
00303 bool withLength))
00304 {
00305 format_func=func;
00306 RESET_FMTSTR;
00307 }
00308
00309 const string& Message::getFormattedString(bool withLength)
00310 {
00311 if(formattedString != 0) return *formattedString;
00312 else return *(formattedString = format_func(type, to, from, method, nonce, dependsOn, mtime, fields, withLength));
00313 }
00314
00315 string Message::getLoggableString()
00316 {
00317 string s;
00318 string n;
00319
00320 s += "<" + type + " ";
00321 n = to;
00322 if(messageContext) messageContext->doSubstitution(n);
00323 s += "to=\"" + n + "\"";
00324
00325 n = from;
00326 if(messageContext) messageContext->doSubstitution(n);
00327 s += "\n from=\"" + n + "\"";
00328
00329 n = method;
00330 if(messageContext) messageContext->doSubstitution(n);
00331 s += "\n method=\"" + n + "\"";
00332
00333 n = nonce;
00334 if(messageContext) messageContext->doSubstitution(n);
00335 if(n != "") s += "\n nonce=\"" + n + "\"";
00336
00337 n = dependsOn;
00338 if(messageContext) messageContext->doSubstitution(n);
00339 if(n != "") s += "\n depends=\"" + n + "\"";
00340
00341 if(mtime != 0.0) {
00342 char timing[16];
00343 snprintf(timing, sizeof(timing), "%6.6f", mtime);
00344 s += "\n time=\"";
00345 s += timing;
00346 s += "\"";
00347 }
00348
00349 if(fields.size() == 0) {
00350 s += " />";
00351 } else {
00352 s += ">";
00353 deque<Message::Field>::iterator f=fields.begin();
00354
00355 while(f != fields.end()) {
00356 if((*f).source == "") {
00357 s += "<" + (*f).key + " />\n ";
00358 } else {
00359 (*f).value = (*f).source;
00360 if(messageContext && !(*f).quoted) messageContext->doSubstitution((*f).value);
00361 s += "\n <" + (*f).key + ">" + (*f).value + "</" + (*f).key + ">";
00362 }
00363 f++;
00364 }
00365 s += "\n</" + type + ">";
00366 }
00367
00368 return s;
00369 }
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394 string* VOS::xmlFormatting(const string& type,
00395 const string& to,
00396 const string& from,
00397 const string& method,
00398 const string& nonce,
00399 const string& dependsOn,
00400 double mtime,
00401 const deque<Message::Field>& fields,
00402 bool withLength)
00403 {
00404 string* s=new string();
00405
00406 *s += "<" + type + " ";
00407 if(withLength) *s += "length=\"\"\n";
00408 if(to != "") *s += "to=\"" + to + "\"\n";
00409 if(from != "") *s += "from=\"" + from + "\"\n";
00410 if(method != "") *s += "method=\"" + method + "\"";
00411 if(nonce != "") *s += "\nnonce=\"" + nonce + "\"";
00412 if(dependsOn != "") *s += "\ndepends=\"" + dependsOn + "\"";
00413 if(mtime != 0.0) {
00414 char timing[16];
00415 snprintf(timing, sizeof(timing), "%6.6f", mtime);
00416 *s += "\ntime=\"";
00417 *s += timing;
00418 *s += "\"";
00419 }
00420
00421 if(fields.size() == 0) {
00422 *s += " />";
00423 } else {
00424 *s += ">\n";
00425 deque<Message::Field>::const_iterator f=fields.begin();
00426
00427 while(f != fields.end()) {
00428 if((*f).source == "") {
00429 *s += "<" + (*f).key + " />\n";
00430 } else {
00431 if((*f).quoted) {
00432 *s += "<" + (*f).key + " ";
00433 *s += "length=\"";
00434 char n[16];
00435 snprintf(n, sizeof(n), "%i", (*f).source.length());
00436 *s += n;
00437 *s += "\">" + (*f).source + "</" + (*f).key + ">\n";
00438 } else {
00439 *s += "<" + (*f).key + ">" + (*f).source + "</" + (*f).key + ">\n";
00440 }
00441 }
00442 f++;
00443 }
00444 *s += "</" + type + ">";
00445 }
00446
00447 if(withLength) {
00448 unsigned int size = (unsigned int)s->size();
00449 char len[16];
00450 int width=snprintf(len, sizeof(len), "%i", size);
00451 size += (unsigned int)strlen(len);
00452 if(width < snprintf(len, sizeof(len), "%i", size)) snprintf(len, sizeof(len), "%i", size+1);
00453
00454 s->insert(10+type.size(), len);
00455 LOG("message", 5, "generated message exactly " << (unsigned int)s->size() << " bytes long");
00456 }
00457
00458 return s;
00459 }
00460
00461