|
reSIProcate/stack
9694
|
00001 #if defined(HAVE_CONFIG_H) 00002 #include "config.h" 00003 #endif 00004 00005 #include "resip/stack/HeaderFieldValue.hxx" 00006 #include "resip/stack/ParserCategory.hxx" 00007 #include "rutil/ParseBuffer.hxx" 00008 #include "resip/stack/SipMessage.hxx" 00009 #include "rutil/DataStream.hxx" 00010 #include "rutil/ParseBuffer.hxx" 00011 #include "rutil/compat.hxx" 00012 00013 #include "resip/stack/UnknownParameter.hxx" 00014 #include "resip/stack/ExtensionParameter.hxx" 00015 00016 #include <iostream> 00017 #include <cassert> 00018 00019 #include "rutil/Logger.hxx" 00020 //#include "rutil/WinLeakCheck.hxx" // not compatible with placement new used below 00021 00022 #define RESIPROCATE_SUBSYSTEM Subsystem::SIP 00023 00024 using namespace resip; 00025 using namespace std; 00026 00027 const ParserCategory::ParameterTypeSet 00028 ParserCategory::EmptyParameterTypeSet; 00029 00030 ParserCategory::ParserCategory(const HeaderFieldValue& headerFieldValue, 00031 Headers::Type headerType, 00032 PoolBase* pool) 00033 : LazyParser(headerFieldValue), 00034 mParameters(StlPoolAllocator<Parameter*, PoolBase>(pool)), 00035 mUnknownParameters(StlPoolAllocator<Parameter*, PoolBase>(pool)), 00036 mPool(pool), 00037 mHeaderType(headerType) 00038 { 00039 } 00040 00041 ParserCategory::ParserCategory(const char* buf, 00042 int length, 00043 Headers::Type type, 00044 PoolBase* pool): 00045 LazyParser(buf, length), 00046 mParameters(StlPoolAllocator<Parameter*, PoolBase>(pool)), 00047 mUnknownParameters(StlPoolAllocator<Parameter*, PoolBase>(pool)), 00048 mPool(pool), 00049 mHeaderType(type) 00050 {} 00051 00052 ParserCategory::ParserCategory(PoolBase* pool) 00053 : LazyParser(), 00054 mParameters(StlPoolAllocator<Parameter*, PoolBase>(pool)), 00055 mUnknownParameters(StlPoolAllocator<Parameter*, PoolBase>(pool)), 00056 mPool(pool), 00057 mHeaderType(Headers::NONE) 00058 { 00059 } 00060 00061 ParserCategory::ParserCategory(const ParserCategory& rhs, 00062 PoolBase* pool) 00063 : LazyParser(rhs), 00064 mParameters(StlPoolAllocator<Parameter*, PoolBase>(pool)), 00065 mUnknownParameters(StlPoolAllocator<Parameter*, PoolBase>(pool)), 00066 mPool(pool), 00067 mHeaderType(rhs.mHeaderType) 00068 { 00069 if (isParsed()) 00070 { 00071 copyParametersFrom(rhs); 00072 } 00073 } 00074 00075 ParserCategory& 00076 ParserCategory::operator=(const ParserCategory& rhs) 00077 { 00078 if (this != &rhs) 00079 { 00080 clear(); 00081 mHeaderType = rhs.mHeaderType; 00082 LazyParser::operator=(rhs); 00083 if (rhs.isParsed()) 00084 { 00085 copyParametersFrom(rhs); 00086 } 00087 } 00088 return *this; 00089 } 00090 00091 void 00092 ParserCategory::clear() 00093 { 00094 //DebugLog(<<"ParserCategory::clear"); 00095 LazyParser::clear(); 00096 00097 while(!mParameters.empty()) 00098 { 00099 freeParameter(mParameters.back()); 00100 mParameters.pop_back(); 00101 } 00102 00103 while(!mUnknownParameters.empty()) 00104 { 00105 freeParameter(mUnknownParameters.back()); 00106 mUnknownParameters.pop_back(); 00107 } 00108 } 00109 00110 void 00111 ParserCategory::copyParametersFrom(const ParserCategory& other) 00112 { 00113 mParameters.reserve(other.mParameters.size()); 00114 mUnknownParameters.reserve(other.mUnknownParameters.size()); 00115 00116 for (ParameterList::const_iterator it = other.mParameters.begin(); 00117 it != other.mParameters.end(); it++) 00118 { 00119 mParameters.push_back((*it)->clone()); 00120 } 00121 for (ParameterList::const_iterator it = other.mUnknownParameters.begin(); 00122 it != other.mUnknownParameters.end(); it++) 00123 { 00124 mUnknownParameters.push_back((*it)->clone()); 00125 } 00126 } 00127 00128 ParserCategory::~ParserCategory() 00129 { 00130 clear(); 00131 } 00132 00133 const Data& 00134 ParserCategory::param(const ExtensionParameter& param) const 00135 { 00136 checkParsed(); 00137 Parameter* p = getParameterByData(param.getName()); 00138 if (!p) 00139 { 00140 InfoLog(<< "Referenced an unknown parameter " << param.getName()); 00141 throw Exception("Missing unknown parameter", __FILE__, __LINE__); 00142 } 00143 return static_cast<UnknownParameter*>(p)->value(); 00144 } 00145 00146 Data& 00147 ParserCategory::param(const ExtensionParameter& param) 00148 { 00149 checkParsed(); 00150 Parameter* p = getParameterByData(param.getName()); 00151 if (!p) 00152 { 00153 p = new UnknownParameter(param.getName()); 00154 mUnknownParameters.push_back(p); 00155 } 00156 return static_cast<UnknownParameter*>(p)->value(); 00157 } 00158 00159 // removing non-present parameter is allowed 00160 void 00161 ParserCategory::remove(const ParamBase& paramType) 00162 { 00163 checkParsed(); 00164 removeParameterByEnum(paramType.getTypeNum()); 00165 } 00166 00167 void 00168 ParserCategory::remove(const ExtensionParameter& param) 00169 { 00170 checkParsed(); 00171 removeParameterByData(param.getName()); 00172 } 00173 00174 bool 00175 ParserCategory::exists(const ExtensionParameter& param) const 00176 { 00177 checkParsed(); 00178 return getParameterByData(param.getName()) != NULL; 00179 } 00180 00181 void 00182 ParserCategory::removeParametersExcept(const ParameterTypeSet& set) 00183 { 00184 checkParsed(); 00185 for (ParameterList::iterator it = mParameters.begin(); 00186 it != mParameters.end();) 00187 { 00188 if (set.find((*it)->getType()) == set.end()) 00189 { 00190 freeParameter(*it); 00191 it = mParameters.erase(it); 00192 } 00193 else 00194 { 00195 ++it; 00196 } 00197 } 00198 } 00199 00200 void 00201 ParserCategory::clearUnknownParameters() 00202 { 00203 for (ParameterList::iterator it = mUnknownParameters.begin(); 00204 it != mUnknownParameters.end(); it++) 00205 { 00206 freeParameter(*it); 00207 } 00208 mUnknownParameters.clear(); 00209 } 00210 00211 void 00212 ParserCategory::parseParameters(ParseBuffer& pb) 00213 { 00214 while (!pb.eof() ) 00215 { 00216 const char* start = pb.position(); 00217 pb.skipWhitespace(); 00218 00219 if ( (!pb.eof() && *pb.position() == Symbols::SEMI_COLON[0]) ) 00220 { 00221 // extract the key 00222 pb.skipChar(); 00223 const char* keyStart = pb.skipWhitespace(); 00224 static std::bitset<256> terminators1=Data::toBitset(" \t\r\n;=?>"); 00225 const char* keyEnd = pb.skipToOneOf(terminators1); 00226 00227 if((int)(keyEnd-keyStart) != 0) 00228 { 00229 ParameterTypes::Type type = ParameterTypes::getType(keyStart, (unsigned int)(keyEnd - keyStart)); 00230 static std::bitset<256> terminators2 = Data::toBitset(" \t\r\n;?>"); 00231 Parameter* p; 00232 if (type == ParameterTypes::UNKNOWN || 00233 !(p=createParam(type, pb, terminators2,getPool()))) 00234 { 00235 mUnknownParameters.push_back(new (getPool()) UnknownParameter(keyStart, 00236 int((keyEnd - keyStart)), pb, terminators2)); 00237 } 00238 else 00239 { 00240 // invoke the particular factory 00241 mParameters.push_back(p); 00242 } 00243 } 00244 } 00245 else 00246 { 00247 pb.reset(start); 00248 return; 00249 } 00250 } 00251 } 00252 00253 Parameter* 00254 ParserCategory::createParam(ParameterTypes::Type type, ParseBuffer& pb, const std::bitset<256>& terminators, PoolBase* pool) 00255 { 00256 return 0; 00257 } 00258 00259 static Data up_Msgr("msgr"); 00260 00261 EncodeStream& 00262 ParserCategory::encodeParameters(EncodeStream& str) const 00263 { 00264 00265 for (ParameterList::const_iterator it = mParameters.begin(); 00266 it != mParameters.end(); it++) 00267 { 00268 #if 0 00269 // !cj! - may be wrong just hacking 00270 // The goal of all this is not to add a tag if the tag is empty 00271 ParameterTypes::Type type = (*it)->getType(); 00272 00273 if ( type == ParameterTypes::tag ) 00274 { 00275 Parameter* p = (*it); 00276 DataParameter* d = dynamic_cast<DataParameter*>(p); 00277 00278 Data& data = d->value(); 00279 00280 if ( !data.empty() ) 00281 { 00282 str << Symbols::SEMI_COLON; 00283 // !ah! this is a TOTAL hack to work around an MSN bug that 00284 // !ah! requires a SPACE after the SEMI following the MIME type. 00285 if (it == mParameters.begin() && getParameterByData(up_Msgr)) 00286 { 00287 str << Symbols::SPACE; 00288 } 00289 00290 (*it)->encode(str); 00291 } 00292 } 00293 else 00294 { 00295 str << Symbols::SEMI_COLON; 00296 // !ah! this is a TOTAL hack to work around an MSN bug that 00297 // !ah! requires a SPACE after the SEMI following the MIME type. 00298 if (it == mParameters.begin() && getParameterByData(up_Msgr)) 00299 { 00300 str << Symbols::SPACE; 00301 } 00302 00303 (*it)->encode(str); 00304 } 00305 00306 #else 00307 str << Symbols::SEMI_COLON; 00308 // !ah! this is a TOTAL hack to work around an MSN bug that 00309 // !ah! requires a SPACE after the SEMI following the MIME type. 00310 if (it == mParameters.begin() && getParameterByData(up_Msgr)) 00311 { 00312 str << Symbols::SPACE; 00313 } 00314 00315 (*it)->encode(str); 00316 #endif 00317 } 00318 for (ParameterList::const_iterator it = mUnknownParameters.begin(); 00319 it != mUnknownParameters.end(); it++) 00320 { 00321 str << Symbols::SEMI_COLON; 00322 (*it)->encode(str); 00323 } 00324 return str; 00325 } 00326 00327 EncodeStream& 00328 resip::operator<<(EncodeStream& stream, const ParserCategory& category) 00329 { 00330 category.checkParsed(); 00331 return category.encode(stream); 00332 } 00333 00334 Parameter* 00335 ParserCategory::getParameterByEnum(ParameterTypes::Type type) const 00336 { 00337 for (ParameterList::const_iterator it = mParameters.begin(); 00338 it != mParameters.end(); it++) 00339 { 00340 if ((*it)->getType() == type) 00341 { 00342 return *it; 00343 } 00344 } 00345 return 0; 00346 } 00347 00348 void 00349 ParserCategory::setParameter(const Parameter* parameter) 00350 { 00351 assert(parameter); 00352 00353 for (ParameterList::iterator it = mParameters.begin(); 00354 it != mParameters.end(); it++) 00355 { 00356 if ((*it)->getType() == parameter->getType()) 00357 { 00358 freeParameter(*it); 00359 mParameters.erase(it); 00360 mParameters.push_back(parameter->clone()); 00361 return; 00362 } 00363 } 00364 00365 // !dlb! kinda hacky -- what is the correct semantics here? 00366 // should be quietly add, quietly do nothing, throw? 00367 mParameters.push_back(parameter->clone()); 00368 } 00369 00370 void 00371 ParserCategory::removeParameterByEnum(ParameterTypes::Type type) 00372 { 00373 // remove all instances 00374 for (ParameterList::iterator it = mParameters.begin(); 00375 it != mParameters.end();) 00376 { 00377 if ((*it)->getType() == type) 00378 { 00379 freeParameter(*it); 00380 it = mParameters.erase(it); 00381 } 00382 else 00383 { 00384 ++it; 00385 } 00386 } 00387 } 00388 00389 Parameter* 00390 ParserCategory::getParameterByData(const Data& data) const 00391 { 00392 for (ParameterList::const_iterator it = mUnknownParameters.begin(); 00393 it != mUnknownParameters.end(); it++) 00394 { 00395 if (isEqualNoCase((*it)->getName(), data)) 00396 { 00397 return *it; 00398 } 00399 } 00400 return 0; 00401 } 00402 00403 void 00404 ParserCategory::removeParameterByData(const Data& data) 00405 { 00406 // remove all instances 00407 for (ParameterList::iterator it = mUnknownParameters.begin(); 00408 it != mUnknownParameters.end();) 00409 { 00410 if ((*it)->getName() == data) 00411 { 00412 freeParameter(*it); 00413 it = mUnknownParameters.erase(it); 00414 } 00415 else 00416 { 00417 ++it; 00418 } 00419 } 00420 } 00421 00422 Data 00423 ParserCategory::commutativeParameterHash() const 00424 { 00425 Data buffer; 00426 Data working; 00427 00428 for (ParameterList::const_iterator i = mParameters.begin(); i != mParameters.end(); ++i) 00429 { 00430 if ((*i)->getType() != ParameterTypes::lr) 00431 { 00432 buffer.clear(); 00433 { 00434 DataStream strm(buffer); 00435 (*i)->encode(strm); 00436 } 00437 working ^= buffer; 00438 } 00439 } 00440 00441 buffer.clear(); 00442 for (ParameterList::const_iterator i = mUnknownParameters.begin(); i != mUnknownParameters.end(); ++i) 00443 { 00444 UnknownParameter* p = static_cast<UnknownParameter*>(*i); 00445 buffer = p->getName(); 00446 buffer += p->value(); 00447 working ^= buffer; 00448 } 00449 00450 return working; 00451 } 00452 00453 const Data& 00454 ParserCategory::errorContext() const 00455 { 00456 return Headers::getHeaderName(mHeaderType); 00457 } 00458 00459 /* ==================================================================== 00460 * The Vovida Software License, Version 1.0 00461 * 00462 * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved. 00463 * 00464 * Redistribution and use in source and binary forms, with or without 00465 * modification, are permitted provided that the following conditions 00466 * are met: 00467 * 00468 * 1. Redistributions of source code must retain the above copyright 00469 * notice, this list of conditions and the following disclaimer. 00470 * 00471 * 2. Redistributions in binary form must reproduce the above copyright 00472 * notice, this list of conditions and the following disclaimer in 00473 * the documentation and/or other materials provided with the 00474 * distribution. 00475 * 00476 * 3. The names "VOCAL", "Vovida Open Communication Application Library", 00477 * and "Vovida Open Communication Application Library (VOCAL)" must 00478 * not be used to endorse or promote products derived from this 00479 * software without prior written permission. For written 00480 * permission, please contact vocal@vovida.org. 00481 * 00482 * 4. Products derived from this software may not be called "VOCAL", nor 00483 * may "VOCAL" appear in their name, without prior written 00484 * permission of Vovida Networks, Inc. 00485 * 00486 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED 00487 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 00488 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND 00489 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA 00490 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES 00491 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL, 00492 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00493 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00494 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 00495 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00496 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 00497 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 00498 * DAMAGE. 00499 * 00500 * ==================================================================== 00501 * 00502 * This software consists of voluntary contributions made by Vovida 00503 * Networks, Inc. and many individuals on behalf of Vovida Networks, 00504 * Inc. For more information on Vovida Networks, Inc., please see 00505 * <http://www.vovida.org/>. 00506 * 00507 */ 00508 00509 /* Local Variables: */ 00510 /* c-file-style: "ellemtel" */ 00511 /* End: */
1.7.5.1