/[resiprocate]/main/resip/stack/Uri.cxx
ViewVC logotype

Contents of /main/resip/stack/Uri.cxx

Parent Directory Parent Directory | Revision Log Revision Log


Revision 11153 - (show annotations) (download)
Wed Apr 23 17:25:02 2014 UTC (5 years, 9 months ago) by dpetrie
File MIME type: text/plain
File size: 39371 byte(s)
added netns scope/context to Uri and Tuple

1 #if defined(HAVE_CONFIG_H)
2 #include "config.h"
3 #endif
4
5 #include <set>
6
7 #include "resip/stack/Embedded.hxx"
8 #include "resip/stack/Helper.hxx"
9 #include "resip/stack/NameAddr.hxx"
10 #include "resip/stack/SipMessage.hxx"
11 #include "resip/stack/Symbols.hxx"
12 #include "resip/stack/UnknownParameter.hxx"
13 #include "resip/stack/Uri.hxx"
14 #include "rutil/DataStream.hxx"
15 #include "rutil/DnsUtil.hxx"
16 #include "rutil/Logger.hxx"
17 #include "rutil/ParseBuffer.hxx"
18 //#include "rutil/WinLeakCheck.hxx" // not compatible with placement new used below
19
20 using namespace resip;
21
22 #define RESIPROCATE_SUBSYSTEM Subsystem::SIP
23 #define HANDLE_CHARACTER_ESCAPING //undef for old behaviour
24
25 static bool initAllTables()
26 {
27 Uri::getUserEncodingTable();
28 Uri::getPasswordEncodingTable();
29 Uri::getLocalNumberTable();
30 Uri::getGlobalNumberTable();
31 return true;
32 }
33
34 const bool Uri::tablesMightBeInitialized(initAllTables());
35
36 Uri::Uri(PoolBase* pool)
37 : ParserCategory(pool),
38 mScheme(Data::Share, Symbols::DefaultSipScheme),
39 mPort(0),
40 mHostCanonicalized(false)
41 {
42 }
43
44 Uri::Uri(const HeaderFieldValue& hfv, Headers::Type type, PoolBase* pool) :
45 ParserCategory(hfv, type, pool),
46 mPort(0),
47 mHostCanonicalized(false)
48 {}
49
50
51 static const Data parseContext("Uri constructor");
52 Uri::Uri(const Data& data)
53 : ParserCategory(),
54 mScheme(Symbols::DefaultSipScheme),
55 mPort(0),
56 mHostCanonicalized(false)
57 {
58 HeaderFieldValue hfv(data.data(), data.size());
59 // must copy because parse creates overlays
60 Uri tmp(hfv, Headers::UNKNOWN);
61 tmp.checkParsed();
62 *this = tmp;
63 }
64
65 Uri::Uri(const Uri& rhs,
66 PoolBase* pool)
67 : ParserCategory(rhs, pool),
68 mScheme(rhs.mScheme),
69 mHost(rhs.mHost),
70 mUser(rhs.mUser),
71 mUserParameters(rhs.mUserParameters),
72 mPort(rhs.mPort),
73 mPassword(rhs.mPassword),
74 mNetNs(rhs.mNetNs),
75 mHostCanonicalized(rhs.mHostCanonicalized),
76 mEmbeddedHeadersText(rhs.mEmbeddedHeadersText.get() ? new Data(*rhs.mEmbeddedHeadersText) : 0),
77 mEmbeddedHeaders(rhs.mEmbeddedHeaders.get() ? new SipMessage(*rhs.mEmbeddedHeaders) : 0)
78 {}
79
80
81 Uri::~Uri()
82 {}
83
84 // RFC 3261 19.1.6
85 #if 0 // deprecated
86 Uri
87 Uri::fromTel(const Uri& tel, const Data& host)
88 {
89 assert(tel.scheme() == Symbols::Tel);
90
91 Uri u;
92 u.scheme() = Symbols::Sip;
93 u.user() = tel.user();
94 u.host() = host;
95 u.param(p_user) = Symbols::Phone;
96
97 // need to sort the user parameters
98 if (!tel.userParameters().empty())
99 {
100 DebugLog(<< "Uri::fromTel: " << tel.userParameters());
101 Data isub;
102 Data postd;
103
104 int totalSize = 0;
105 std::set<Data> userParameters;
106
107 ParseBuffer pb(tel.userParameters().data(), tel.userParameters().size());
108 while (true)
109 {
110 const char* anchor = pb.position();
111 pb.skipToChar(Symbols::SEMI_COLON[0]);
112 Data param = pb.data(anchor);
113 // !dlb! not supposed to lowercase extension parameters
114 param.lowercase();
115 totalSize += param.size() + 1;
116
117 if (param.prefix(Symbols::Isub))
118 {
119 isub = param;
120 }
121 else if (param.prefix(Symbols::Postd))
122 {
123 postd = param;
124 }
125 else
126 {
127 userParameters.insert(param);
128 }
129 if (pb.eof())
130 {
131 break;
132 }
133 else
134 {
135 pb.skipChar();
136 }
137 }
138
139 u.userParameters().reserve(totalSize);
140 if (!isub.empty())
141 {
142 u.userParameters() = isub;
143 }
144 if (!postd.empty())
145 {
146 if (!u.userParameters().empty())
147 {
148 u.userParameters() += Symbols::SEMI_COLON[0];
149 }
150 u.userParameters() += postd;
151 }
152
153 for(std::set<Data>::const_iterator i = userParameters.begin();
154 i != userParameters.end(); ++i)
155 {
156 DebugLog(<< "Adding param: " << *i);
157 if (!u.userParameters().empty())
158 {
159 u.userParameters() += Symbols::SEMI_COLON[0];
160 }
161 u.userParameters() += *i;
162 }
163 }
164
165 return u;
166 }
167 #endif // deprecated
168
169 Uri
170 Uri::fromTel(const Uri& tel, const Uri& hostUri)
171 {
172 assert(tel.scheme() == Symbols::Tel);
173
174 Uri u(hostUri);
175 u.scheme() = Symbols::Sip;
176 u.user() = tel.user();
177 u.param(p_user) = Symbols::Phone;
178
179 // need to sort the user parameters
180 if (!tel.userParameters().empty())
181 {
182 DebugLog(<< "Uri::fromTel: " << tel.userParameters());
183 Data isub;
184 Data postd;
185
186 int totalSize = 0;
187 std::set<Data> userParameters;
188
189 ParseBuffer pb(tel.userParameters().data(), tel.userParameters().size());
190 while (true)
191 {
192 const char* anchor = pb.position();
193 pb.skipToChar(Symbols::SEMI_COLON[0]);
194 Data param = pb.data(anchor);
195 // !dlb! not supposed to lowercase extension parameters
196 param.lowercase();
197 totalSize += (int)param.size() + 1;
198
199 if (param.prefix(Symbols::Isub))
200 {
201 isub = param;
202 }
203 else if (param.prefix(Symbols::Postd))
204 {
205 postd = param;
206 }
207 else
208 {
209 userParameters.insert(param);
210 }
211 if (pb.eof())
212 {
213 break;
214 }
215 else
216 {
217 pb.skipChar();
218 }
219 }
220
221 u.userParameters().reserve(totalSize);
222 if (!isub.empty())
223 {
224 u.userParameters() = isub;
225 }
226 if (!postd.empty())
227 {
228 if (!u.userParameters().empty())
229 {
230 u.userParameters() += Symbols::SEMI_COLON[0];
231 }
232 u.userParameters() += postd;
233 }
234
235 for(std::set<Data>::const_iterator i = userParameters.begin();
236 i != userParameters.end(); ++i)
237 {
238 DebugLog(<< "Adding param: " << *i);
239 if (!u.userParameters().empty())
240 {
241 u.userParameters() += Symbols::SEMI_COLON[0];
242 }
243 u.userParameters() += *i;
244 }
245 }
246
247 return u;
248 }
249
250 bool
251 Uri::isEnumSearchable() const
252 {
253 checkParsed();
254 int digits = 0;
255
256 if(mUser.size() < 4)
257 {
258 StackLog(<< "user part of Uri empty or too short for E.164");
259 return false;
260 }
261
262 // E.164 numbers must begin with a + and have at least
263 // 3 digits
264 if(mUser[0] != '+')
265 {
266 StackLog(<< "user part of Uri does not begin with `+' or too short");
267 return false;
268 }
269
270 // count the digits (skip the leading `+')
271 for(const char* i=user().begin() + 1; i!= user().end(); i++)
272 {
273 if(isdigit(*i))
274 digits++;
275 else
276 if(*i != '-')
277 {
278 StackLog(<< "user part of Uri contains non-digit: " << *i);
279 return false; // Only digits and '-' permitted
280 }
281 }
282 if(digits > 15)
283 {
284 // E.164 only permits 15 digits in a phone number
285 StackLog(<< "user part of Uri contains more than 15 digits");
286 return false;
287 }
288
289 DebugLog(<< "is in E.164 format for ENUM: " << mUser);
290 return true;
291 }
292
293 std::vector<Data>
294 Uri::getEnumLookups(const std::vector<Data>& suffixes) const
295 {
296 std::vector<Data> results;
297 Data prefix;
298 if (isEnumSearchable())
299 {
300 // skip the leading +
301 for (const char* i=user().end()-1 ; i!= user().begin(); --i)
302 {
303 if (isdigit(*i))
304 {
305 prefix += *i;
306 prefix += Symbols::DOT;
307 }
308 }
309 StackLog(<< "E.164 number reversed for ENUM query: " << prefix);
310 for (std::vector<Data>::const_iterator j=suffixes.begin(); j != suffixes.end(); ++j)
311 {
312 results.push_back(prefix + *j);
313 }
314 }
315 return results;
316 }
317
318
319 bool
320 Uri::hasEmbedded() const
321 {
322 checkParsed();
323 return (mEmbeddedHeadersText.get() && !mEmbeddedHeadersText->empty()) || mEmbeddedHeaders.get() != 0;
324 }
325
326 void
327 Uri::removeEmbedded()
328 {
329 checkParsed();
330 mEmbeddedHeaders.reset();
331 mEmbeddedHeadersText.reset();
332 }
333
334
335
336 Uri&
337 Uri::operator=(const Uri& rhs)
338 {
339 if (this != &rhs)
340 {
341 ParserCategory::operator=(rhs);
342 mScheme = rhs.mScheme;
343 mHost = rhs.mHost;
344 mHostCanonicalized=rhs.mHostCanonicalized;
345 mUser = rhs.mUser;
346 mUserParameters = rhs.mUserParameters;
347 mPort = rhs.mPort;
348 mPassword = rhs.mPassword;
349 mNetNs = rhs.mNetNs;
350 if (rhs.mEmbeddedHeaders.get() != 0)
351 {
352 mEmbeddedHeaders.reset(new SipMessage(*rhs.mEmbeddedHeaders));
353 }
354 else if(rhs.mEmbeddedHeadersText.get() != 0)
355 {
356 if(!mEmbeddedHeadersText.get())
357 {
358 mEmbeddedHeadersText.reset(new Data(*rhs.mEmbeddedHeadersText));
359 }
360 else
361 {
362 // !bwc! Data::operator= is smart enough to handle this safely.
363 *mEmbeddedHeadersText = *rhs.mEmbeddedHeadersText;
364 }
365 }
366 }
367 return *this;
368 }
369
370 /**
371 @class OrderUnknownParameters
372 @brief used as a comparator for sorting purposes
373 */
374 class OrderUnknownParameters
375 {
376 public:
377 /**
378 @brief constructor ; never called explicitly
379 */
380 OrderUnknownParameters() { notUsed=false; };
381
382 /**
383 @brief empty destructor
384 */
385 ~OrderUnknownParameters() {};
386
387 /**
388 @brief used as a comparator for sorting purposes
389 This does a straight Data comparison for name and returns true/false
390 @param p1 pointer to parameter 1
391 @param p2 pointer to parameter 2
392 @return true if p1->getName() is less than p2->getName()
393 else return false
394 */
395 bool operator()(const Parameter* p1, const Parameter* p2) const
396 {
397 return dynamic_cast<const UnknownParameter*>(p1)->getName() < dynamic_cast<const UnknownParameter*>(p2)->getName();
398 }
399
400 private:
401 bool notUsed;
402 };
403
404 bool
405 Uri::operator==(const Uri& other) const
406 {
407 checkParsed();
408 other.checkParsed();
409
410 // compare hosts
411 if (DnsUtil::isIpV6Address(mHost) &&
412 DnsUtil::isIpV6Address(other.mHost))
413 {
414
415 // compare canonicalized IPV6 addresses
416
417 // update canonicalized if host changed
418 if (!mHostCanonicalized)
419 {
420 mHost = DnsUtil::canonicalizeIpV6Address(mHost);
421 mHostCanonicalized=true;
422 }
423
424 // update canonicalized if host changed
425 if (!other.mHostCanonicalized)
426 {
427 other.mHost = DnsUtil::canonicalizeIpV6Address(other.mHost);
428 other.mHostCanonicalized=true;
429 }
430
431 if (mHost != other.mHost)
432 {
433 return false;
434 }
435 }
436 else
437 {
438 if (!isEqualNoCase(mHost, other.mHost))
439 {
440 return false;
441 }
442 }
443
444 if (isEqualNoCase(mScheme, other.mScheme) &&
445 ((isEqualNoCase(mScheme, Symbols::Sip) || isEqualNoCase(mScheme, Symbols::Sips)) ? mUser == other.mUser : isEqualNoCase(mUser, other.mUser)) &&
446 isEqualNoCase(mUserParameters,other.mUserParameters) &&
447 mPassword == other.mPassword &&
448 mPort == other.mPort &&
449 mNetNs == other.mNetNs
450 )
451 {
452 for (ParameterList::const_iterator it = mParameters.begin(); it != mParameters.end(); ++it)
453 {
454 Parameter* otherParam = other.getParameterByEnum((*it)->getType());
455
456 switch ((*it)->getType())
457 {
458 case ParameterTypes::user:
459 {
460 if (!(otherParam &&
461 isEqualNoCase(dynamic_cast<DataParameter*>(*it)->value(),
462 dynamic_cast<DataParameter*>(otherParam)->value())))
463 {
464 return false;
465 }
466 }
467 break;
468 case ParameterTypes::ttl:
469 {
470 if (!(otherParam &&
471 (dynamic_cast<UInt32Parameter*>(*it)->value() ==
472 dynamic_cast<UInt32Parameter*>(otherParam)->value())))
473 {
474 return false;
475 }
476 break;
477 }
478 case ParameterTypes::method:
479 {
480 // this should possibly be case sensitive, but is allowed to be
481 // case insensitive for robustness.
482
483 if (otherParam)
484 {
485 DataParameter* dp1 = dynamic_cast<DataParameter*>(*it);
486 DataParameter* dp2 = dynamic_cast<DataParameter*>(otherParam);
487 (void)dp1;
488 (void)dp2;
489 // ?bwc? It looks like we're just assuming the dynamic_cast
490 // will succeed everywhere else; why are we bothering to
491 // assert()?
492 assert(dp1);
493 assert(dp2);
494 }
495 if (!(otherParam &&
496 isEqualNoCase(dynamic_cast<DataParameter*>(*it)->value(),
497 dynamic_cast<DataParameter*>(otherParam)->value())))
498 {
499 return false;
500 }
501 break;
502 }
503 case ParameterTypes::maddr:
504 {
505 if (!(otherParam &&
506 isEqualNoCase(dynamic_cast<DataParameter*>(*it)->value(),
507 dynamic_cast<DataParameter*>(otherParam)->value())))
508 {
509 return false;
510 }
511 }
512 break;
513 case ParameterTypes::transport:
514 {
515 if (!(otherParam &&
516 isEqualNoCase(dynamic_cast<DataParameter*>(*it)->value(),
517 dynamic_cast<DataParameter*>(otherParam)->value())))
518 {
519 return false;
520 }
521 }
522 break;
523 // the parameters that follow don't affect comparison if only present
524 // in one of the URI's
525 case ParameterTypes::lr:
526 break;
527 default:
528 break;
529 //treat as unknown parameter?
530 }
531 }
532
533 // now check the other way, sigh
534 for (ParameterList::const_iterator it = other.mParameters.begin(); it != other.mParameters.end(); ++it)
535 {
536 Parameter* param = getParameterByEnum((*it)->getType());
537 switch ((*it)->getType())
538 {
539 case ParameterTypes::user:
540 {
541 if (!(param &&
542 isEqualNoCase(dynamic_cast<DataParameter*>(*it)->value(),
543 dynamic_cast<DataParameter*>(param)->value())))
544 {
545 return false;
546 }
547 }
548 break;
549 case ParameterTypes::ttl:
550 {
551 if (!(param &&
552 (dynamic_cast<UInt32Parameter*>(*it)->value() ==
553 dynamic_cast<UInt32Parameter*>(param)->value())))
554 {
555 return false;
556 }
557 break;
558 }
559 case ParameterTypes::method:
560 {
561 // this should possilby be case sensitive, but is allowed to be
562 // case insensitive for robustness.
563 if (!(param &&
564 isEqualNoCase(dynamic_cast<DataParameter*>(*it)->value(),
565 dynamic_cast<DataParameter*>(param)->value())))
566 {
567 return false;
568 }
569 }
570 break;
571 case ParameterTypes::maddr:
572 {
573 if (!(param &&
574 isEqualNoCase(dynamic_cast<DataParameter*>(*it)->value(),
575 dynamic_cast<DataParameter*>(param)->value())))
576 {
577 return false;
578 }
579 }
580 break;
581 case ParameterTypes::transport:
582 {
583 if (!(param &&
584 isEqualNoCase(dynamic_cast<DataParameter*>(*it)->value(),
585 dynamic_cast<DataParameter*>(param)->value())))
586 {
587 return false;
588 }
589 }
590 break;
591 // the parameters that follow don't affect comparison if only present
592 // in one of the URI's
593 case ParameterTypes::lr:
594 break;
595 default:
596 break;
597 //treat as unknown parameter?
598 }
599 }
600 }
601 else
602 {
603 return false;
604 }
605
606 OrderUnknownParameters orderUnknown;
607
608 #if defined(__SUNPRO_CC) || defined(WIN32) || defined(__sun__)
609 // The Solaris Forte STL implementation does not support the
610 // notion of a list.sort() function taking a BinaryPredicate.
611 // The hacky workaround is to load the Parameter pointers into
612 // an STL set which does support an ordering function.
613
614 typedef std::set<Parameter*, OrderUnknownParameters> ParameterSet;
615 ParameterSet unA, unB;
616
617 for (ParameterList::const_iterator i = mUnknownParameters.begin();
618 i != mUnknownParameters.end(); ++i)
619 {
620 unA.insert(*i);
621 }
622 for (ParameterList::const_iterator i = other.mUnknownParameters.begin();
623 i != other.mUnknownParameters.end(); ++i)
624 {
625 unB.insert(*i);
626 }
627
628 ParameterSet::iterator a = unA.begin();
629 ParameterSet::iterator b = unB.begin();
630 #else
631 // .dlb. more efficient to copy to vector for sorting?
632 // Uri comparison is expensive; consider caching? ugh
633 ParameterList unA = mUnknownParameters;
634 ParameterList unB = other.mUnknownParameters;
635
636 sort(unA.begin(), unA.end(), orderUnknown);
637 sort(unB.begin(), unB.end(), orderUnknown);
638
639 ParameterList::iterator a = unA.begin();
640 ParameterList::iterator b = unB.begin();
641 #endif
642
643 while(a != unA.end() && b != unB.end())
644 {
645 if (orderUnknown(*a, *b))
646 {
647 ++a;
648 }
649 else if (orderUnknown(*b, *a))
650 {
651 ++b;
652 }
653 else
654 {
655 if (!isEqualNoCase(dynamic_cast<UnknownParameter*>(*a)->value(),
656 dynamic_cast<UnknownParameter*>(*b)->value()))
657 {
658 return false;
659 }
660 ++a;
661 ++b;
662 }
663 }
664 return true;
665 }
666
667 bool
668 Uri::operator!=(const Uri& other) const
669 {
670 return !(*this == other);
671 }
672
673 bool
674 Uri::operator<(const Uri& other) const
675 {
676 other.checkParsed();
677 checkParsed();
678 if (mUser < other.mUser)
679 {
680 return true;
681 }
682
683 if (mUser > other.mUser)
684 {
685 return false;
686 }
687
688 if (mUserParameters < other.mUserParameters)
689 {
690 return true;
691 }
692
693 if (mUserParameters > other.mUserParameters)
694 {
695 return false;
696 }
697
698 // !bwc! Canonicalize before we compare! Jeez...
699 if (!mHostCanonicalized)
700 {
701 if(DnsUtil::isIpV6Address(mHost))
702 {
703 mHost = DnsUtil::canonicalizeIpV6Address(mHost);
704 }
705 else
706 {
707 mHost.lowercase();
708 }
709 mHostCanonicalized=true;
710 }
711
712 if (!other.mHostCanonicalized)
713 {
714 if(DnsUtil::isIpV6Address(other.mHost))
715 {
716 other.mHost = DnsUtil::canonicalizeIpV6Address(other.mHost);
717 }
718 else
719 {
720 other.mHost.lowercase();
721 }
722 other.mHostCanonicalized=true;
723 }
724
725 if (mHost < other.mHost)
726 {
727 return true;
728 }
729
730 if (mHost > other.mHost)
731 {
732 return false;
733 }
734
735 return mPort < other.mPort;
736 }
737
738 bool
739 Uri::aorEqual(const resip::Uri& rhs) const
740 {
741 checkParsed();
742 rhs.checkParsed();
743
744 if (!mHostCanonicalized)
745 {
746 if(DnsUtil::isIpV6Address(mHost))
747 {
748 mHost = DnsUtil::canonicalizeIpV6Address(mHost);
749 }
750 else
751 {
752 mHost.lowercase();
753 }
754 mHostCanonicalized=true;
755 }
756
757 if (!rhs.mHostCanonicalized)
758 {
759 if(DnsUtil::isIpV6Address(rhs.mHost))
760 {
761 rhs.mHost = DnsUtil::canonicalizeIpV6Address(rhs.mHost);
762 }
763 else
764 {
765 rhs.mHost.lowercase();
766 }
767 rhs.mHostCanonicalized=true;
768 }
769
770 return (mUser==rhs.mUser) && (mHost==rhs.mHost) && (mPort==rhs.mPort) &&
771 (isEqualNoCase(mScheme,rhs.mScheme) &&
772 (mNetNs == rhs.mNetNs)
773 );
774 }
775
776 void
777 Uri::getAorInternal(bool dropScheme, bool addPort, Data& aor) const
778 {
779 checkParsed();
780 // canonicalize host
781
782 addPort = addPort && mPort!=0;
783
784 bool hostIsIpV6Address = false;
785 if(!mHostCanonicalized)
786 {
787 if (DnsUtil::isIpV6Address(mHost))
788 {
789 mHost = DnsUtil::canonicalizeIpV6Address(mHost);
790 hostIsIpV6Address = true;
791 }
792 else
793 {
794 mHost.lowercase();
795 }
796 }
797
798 // !bwc! Maybe reintroduce caching of aor. (Would use a bool instead of the
799 // mOldX cruft)
800 // @:10000
801 aor.clear();
802 aor.reserve((dropScheme ? 0 : mScheme.size()+1)
803 + mUser.size() + mHost.size() + 7);
804 if(!dropScheme)
805 {
806 aor += mScheme;
807 aor += ':';
808 }
809
810 if (!mUser.empty())
811 {
812 #ifdef HANDLE_CHARACTER_ESCAPING
813 {
814 oDataStream str(aor);
815 mUser.escapeToStream(str, getUserEncodingTable());
816 }
817 #else
818 aor += mUser;
819 #endif
820 if(!mHost.empty())
821 {
822 aor += Symbols::AT_SIGN;
823 }
824 }
825
826 if(hostIsIpV6Address && addPort)
827 {
828 aor += Symbols::LS_BRACKET;
829 aor += mHost;
830 aor += Symbols::RS_BRACKET;
831 }
832 else
833 {
834 aor += mHost;
835 }
836
837 if(addPort)
838 {
839 aor += Symbols::COLON;
840 aor += Data(mPort);
841 }
842 }
843
844 Data
845 Uri::getAOR(bool addPort) const
846 {
847 Data result;
848 getAorInternal(false, addPort, result);
849 return result;
850 }
851
852 bool
853 Uri::userIsTelephoneSubscriber() const
854 {
855 try
856 {
857 ParseBuffer pb(mUser);
858 pb.assertNotEof();
859 const char* anchor=pb.position();
860 bool local=false;
861 if(*pb.position()=='+')
862 {
863 // Might be a global phone number
864 pb.skipChar();
865 pb.skipChars(getGlobalNumberTable());
866 }
867 else
868 {
869 pb.skipChars(getLocalNumberTable());
870 local=true;
871 }
872
873 Data dialString(pb.data(anchor));
874 if(dialString.empty())
875 {
876 pb.fail(__FILE__, __LINE__, "Dial string is empty.");
877 }
878
879 // ?bwc? More dial-string checking? For instance, +/ (or simply /) is not
880 // a valid dial-string according to the BNF; the string must contain at
881 // least one actual digit (or in the local number case, one hex digit or
882 // '*' or '#'. Interestingly, this means that stuff like ///*/// is
883 // valid)
884
885 // Dial string looks ok so far; now look for params (there must be a
886 // phone-context param if this is a local number, otherwise there might
887 // or might not be one)
888 if(local || !pb.eof())
889 {
890 // The only thing that can be here is a ';'. If it does, we're going
891 // to say it is good enough for us. If something in the parameter
892 // string is malformed, it'll get caught when/if
893 // getUserAsTelephoneSubscriber() is called.
894 pb.skipChar(';');
895 }
896
897 return true;
898 }
899 catch(ParseException& /*e*/)
900 {
901 return false;
902 }
903 }
904
905 Token
906 Uri::getUserAsTelephoneSubscriber() const
907 {
908 // !bwc! Ugly. Someday, refactor all this lazy-parser stuff and make it
909 // possible to control ownership explicitly.
910 // Set this up as lazy-parsed, to prevent exceptions from being thrown.
911 HeaderFieldValue temp(mUser.data(), mUser.size());
912 Token tempToken(temp, Headers::NONE);
913 // tempToken does not own the HeaderFieldValue temp, and temp does not own
914 // its buffer.
915
916 // Here's the voodoo; invoking operator= makes a deep copy of the stuff in
917 // tempToken, with result owning the memory, and result is in the unparsed
918 // state.
919 Token result = tempToken;
920 return result;
921 }
922
923 void
924 Uri::setUserAsTelephoneSubscriber(const Token& telephoneSubscriber)
925 {
926 mUser.clear();
927 oDataStream str(mUser);
928 str << telephoneSubscriber;
929 }
930
931 Data
932 Uri::getAorNoPort() const
933 {
934 Data result;
935 getAorInternal(true, false, result);
936 return result;
937 }
938
939 Data
940 Uri::getAor() const
941 {
942 Data result;
943 getAorInternal(true, true, result);
944 return result;
945 }
946
947 Uri
948 Uri::getAorAsUri(TransportType transportTypeToRemoveDefaultPort) const
949 {
950 //.dcm. -- tel conversion?
951 checkParsed();
952 Uri ret;
953 ret.scheme() = mScheme;
954 ret.user() = mUser;
955 ret.host() = mHost;
956
957 // Remove any default ports (if required)
958 if(transportTypeToRemoveDefaultPort == UDP ||
959 transportTypeToRemoveDefaultPort == TCP)
960 {
961 if(mPort != Symbols::DefaultSipPort)
962 {
963 ret.port() = mPort;
964 }
965 }
966 else if (transportTypeToRemoveDefaultPort == TLS ||
967 transportTypeToRemoveDefaultPort == DTLS)
968 {
969 if(mPort != Symbols::DefaultSipsPort)
970 {
971 ret.port() = mPort;
972 }
973 }
974 else
975 {
976 ret.port() = mPort;
977 }
978
979 return ret;
980 }
981
982 void
983 Uri::parse(ParseBuffer& pb)
984 {
985 pb.skipWhitespace();
986 const char* start = pb.position();
987 pb.skipToOneOf(":@");
988
989 pb.assertNotEof();
990
991 pb.data(mScheme, start);
992 pb.skipChar(Symbols::COLON[0]);
993 mScheme.schemeLowercase();
994
995 if (mScheme==Symbols::Tel)
996 {
997 const char* anchor = pb.position();
998 static std::bitset<256> delimiter=Data::toBitset("\r\n\t ;>");
999 pb.skipToOneOf(delimiter);
1000 pb.data(mUser, anchor);
1001 if (!pb.eof() && *pb.position() == Symbols::SEMI_COLON[0])
1002 {
1003 anchor = pb.skipChar();
1004 pb.skipToOneOf(ParseBuffer::Whitespace, Symbols::RA_QUOTE);
1005 pb.data(mUserParameters, anchor);
1006 }
1007 return;
1008 }
1009
1010 start = pb.position();
1011 static std::bitset<256> userPortOrPasswordDelim(Data::toBitset("@:\""));
1012 // stop at double-quote to prevent matching an '@' in a quoted string param.
1013 pb.skipToOneOf(userPortOrPasswordDelim);
1014 if (!pb.eof())
1015 {
1016 const char* atSign=0;
1017 if (*pb.position() == Symbols::COLON[0])
1018 {
1019 // Either a password, or a port
1020 const char* afterColon = pb.skipChar();
1021 pb.skipToOneOf("@\"");
1022 if(!pb.eof() && *pb.position() == Symbols::AT_SIGN[0])
1023 {
1024 atSign=pb.position();
1025 // password
1026 #ifdef HANDLE_CHARACTER_ESCAPING
1027 pb.dataUnescaped(mPassword, afterColon);
1028 #else
1029 pb.data(mPassword, afterColon);
1030 #endif
1031 pb.reset(afterColon-1);
1032 }
1033 else
1034 {
1035 // port. No user part.
1036 pb.reset(start);
1037 }
1038 }
1039 else if(*pb.position() == Symbols::AT_SIGN[0])
1040 {
1041 atSign=pb.position();
1042 }
1043 else
1044 {
1045 // Only a hostpart
1046 pb.reset(start);
1047 }
1048
1049 if(atSign)
1050 {
1051 #ifdef HANDLE_CHARACTER_ESCAPING
1052 pb.dataUnescaped(mUser, start);
1053 #else
1054 pb.data(mUser, start);
1055 #endif
1056 pb.reset(atSign);
1057 start = pb.skipChar();
1058 }
1059 }
1060 else
1061 {
1062 pb.reset(start);
1063 }
1064
1065 mHostCanonicalized=false;
1066 static std::bitset<256> hostDelimiter(Data::toBitset("\r\n\t :;?>"));
1067 if (*start == '[')
1068 {
1069 start = pb.skipChar();
1070 pb.skipToChar(']');
1071 pb.data(mHost, start);
1072 // .bwc. We do not save this canonicalization, since we weren't doing so
1073 // before. This may change soon.
1074 Data canonicalizedHost=DnsUtil::canonicalizeIpV6Address(mHost);
1075 if(canonicalizedHost.empty())
1076 {
1077 // .bwc. So the V6 addy is garbage.
1078 throw ParseException("Unparsable V6 address (note, this might"
1079 " be unparsable because IPV6 support is not"
1080 " enabled)","Uri",__FILE__,
1081 __LINE__);
1082 }
1083 pb.skipChar();
1084 pb.skipToOneOf(hostDelimiter);
1085 }
1086 else
1087 {
1088 pb.skipToOneOf(hostDelimiter);
1089 pb.data(mHost, start);
1090 }
1091
1092 if (!pb.eof() && *pb.position() == ':')
1093 {
1094 start = pb.skipChar();
1095 mPort = pb.uInt32();
1096 }
1097 else
1098 {
1099 mPort = 0;
1100 }
1101
1102 parseParameters(pb);
1103
1104 if (!pb.eof() && *pb.position() == Symbols::QUESTION[0])
1105 {
1106 const char* anchor = pb.position();
1107 pb.skipToOneOf(">;", ParseBuffer::Whitespace);
1108 if(!mEmbeddedHeadersText.get()) mEmbeddedHeadersText.reset(new Data);
1109 pb.data(*mEmbeddedHeadersText, anchor);
1110 }
1111 }
1112
1113 ParserCategory*
1114 Uri::clone() const
1115 {
1116 return new Uri(*this);
1117 }
1118
1119 ParserCategory*
1120 Uri::clone(void* location) const
1121 {
1122 return new (location) Uri(*this);
1123 }
1124
1125 ParserCategory*
1126 Uri::clone(PoolBase* pool) const
1127 {
1128 return new (pool) Uri(*this);
1129 }
1130
1131 void Uri::setUriUserEncoding(unsigned char c, bool encode)
1132 {
1133 getUserEncodingTable()[c] = encode;
1134 }
1135
1136 void Uri::setUriPasswordEncoding(unsigned char c, bool encode)
1137 {
1138 getPasswordEncodingTable()[c] = encode;
1139 }
1140
1141 // should not encode user parameters unless its a tel?
1142 EncodeStream&
1143 Uri::encodeParsed(EncodeStream& str) const
1144 {
1145 str << mScheme << Symbols::COLON;
1146 if (!mUser.empty())
1147 {
1148 #ifdef HANDLE_CHARACTER_ESCAPING
1149 mUser.escapeToStream(str, getUserEncodingTable());
1150 #else
1151 str << mUser;
1152 #endif
1153 if (!mUserParameters.empty())
1154 {
1155 str << Symbols::SEMI_COLON[0] << mUserParameters;
1156 }
1157 if (!mPassword.empty())
1158 {
1159 str << Symbols::COLON;
1160 #ifdef HANDLE_CHARACTER_ESCAPING
1161 mPassword.escapeToStream(str, getPasswordEncodingTable());
1162 #else
1163 str << mPassword;
1164 #endif
1165 }
1166 }
1167 if (!mHost.empty())
1168 {
1169 if (!mUser.empty())
1170 {
1171 str << Symbols::AT_SIGN;
1172 }
1173 if (DnsUtil::isIpV6Address(mHost))
1174 {
1175 str << '[' << mHost << ']';
1176 }
1177 else
1178 {
1179 str << mHost;
1180 }
1181 }
1182 if (mPort != 0)
1183 {
1184 str << Symbols::COLON << mPort;
1185 }
1186 encodeParameters(str);
1187 encodeEmbeddedHeaders(str);
1188
1189 return str;
1190 }
1191
1192 SipMessage&
1193 Uri::embedded()
1194 {
1195 checkParsed();
1196 if (mEmbeddedHeaders.get() == 0)
1197 {
1198 this->mEmbeddedHeaders.reset(new SipMessage());
1199 if (mEmbeddedHeadersText.get() && !mEmbeddedHeadersText->empty())
1200 {
1201 ParseBuffer pb(mEmbeddedHeadersText->data(), mEmbeddedHeadersText->size());
1202 this->parseEmbeddedHeaders(pb);
1203 }
1204 }
1205
1206 return *mEmbeddedHeaders;
1207 }
1208
1209 const SipMessage&
1210 Uri::embedded() const
1211 {
1212 Uri* ncthis = const_cast<Uri*>(this);
1213 return ncthis->embedded();
1214 }
1215
1216 static const Data bodyData("Body");
1217 void
1218 Uri::parseEmbeddedHeaders(ParseBuffer& pb)
1219 {
1220 DebugLog(<< "Uri::parseEmbeddedHeaders");
1221 if (!pb.eof() && *pb.position() == Symbols::QUESTION[0])
1222 {
1223 pb.skipChar();
1224 }
1225
1226 const char* anchor;
1227 Data headerName;
1228 Data headerContents;
1229
1230 bool first = true;
1231 while (!pb.eof())
1232 {
1233 if (first)
1234 {
1235 first = false;
1236 }
1237 else
1238 {
1239 pb.skipChar(Symbols::AMPERSAND[0]);
1240 }
1241
1242 anchor = pb.position();
1243 pb.skipToChar(Symbols::EQUALS[0]);
1244 pb.data(headerName, anchor);
1245 // .dlb. in theory, need to decode header name
1246
1247 anchor = pb.skipChar(Symbols::EQUALS[0]);
1248 pb.skipToChar(Symbols::AMPERSAND[0]);
1249 pb.data(headerContents, anchor);
1250
1251 unsigned int len;
1252 char* decodedContents = Embedded::decode(headerContents, len);
1253 mEmbeddedHeaders->addBuffer(decodedContents);
1254
1255 if (isEqualNoCase(bodyData, headerName))
1256 {
1257 mEmbeddedHeaders->setBody(decodedContents, len);
1258 }
1259 else
1260 {
1261 DebugLog(<< "Uri::parseEmbeddedHeaders(" << headerName << ", " << Data(decodedContents, len) << ")");
1262 mEmbeddedHeaders->addHeader(Headers::getType(headerName.data(), (int)headerName.size()),
1263 headerName.data(), (int)headerName.size(),
1264 decodedContents, len);
1265 }
1266 }
1267 }
1268
1269 EncodeStream&
1270 Uri::encodeEmbeddedHeaders(EncodeStream& str) const
1271 {
1272 if (mEmbeddedHeaders.get())
1273 {
1274 mEmbeddedHeaders->encodeEmbedded(str);
1275 }
1276 else if(mEmbeddedHeadersText.get())
1277 {
1278 // never decoded
1279 str << *mEmbeddedHeadersText;
1280 }
1281 return str;
1282 }
1283
1284 Data
1285 Uri::toString() const
1286 {
1287 Data out;
1288 {
1289 oDataStream dataStream(out);
1290 this->encodeParsed(dataStream);
1291 }
1292 return out;
1293 }
1294
1295 ParameterTypes::Factory Uri::ParameterFactories[ParameterTypes::MAX_PARAMETER]={0};
1296
1297 Parameter*
1298 Uri::createParam(ParameterTypes::Type type, ParseBuffer& pb, const std::bitset<256>& terminators, PoolBase* pool)
1299 {
1300 if(type > ParameterTypes::UNKNOWN && type < ParameterTypes::MAX_PARAMETER && ParameterFactories[type])
1301 {
1302 return ParameterFactories[type](type, pb, terminators, pool);
1303 }
1304 return 0;
1305 }
1306
1307 bool
1308 Uri::exists(const Param<Uri>& paramType) const
1309 {
1310 checkParsed();
1311 bool ret = getParameterByEnum(paramType.getTypeNum()) != NULL;
1312 return ret;
1313 }
1314
1315 void
1316 Uri::remove(const Param<Uri>& paramType)
1317 {
1318 checkParsed();
1319 removeParameterByEnum(paramType.getTypeNum());
1320 }
1321
1322 #define defineParam(_enum, _name, _type, _RFC_ref_ignored) \
1323 _enum##_Param::DType& \
1324 Uri::param(const _enum##_Param& paramType) \
1325 { \
1326 checkParsed(); \
1327 _enum##_Param::Type* p = \
1328 static_cast<_enum##_Param::Type*>(getParameterByEnum(paramType.getTypeNum())); \
1329 if (!p) \
1330 { \
1331 p = new _enum##_Param::Type(paramType.getTypeNum()); \
1332 mParameters.push_back(p); \
1333 } \
1334 return p->value(); \
1335 } \
1336 \
1337 const _enum##_Param::DType& \
1338 Uri::param(const _enum##_Param& paramType) const \
1339 { \
1340 checkParsed(); \
1341 _enum##_Param::Type* p = \
1342 static_cast<_enum##_Param::Type*>(getParameterByEnum(paramType.getTypeNum())); \
1343 if (!p) \
1344 { \
1345 InfoLog(<< "Missing parameter " _name " " << ParameterTypes::ParameterNames[paramType.getTypeNum()]); \
1346 DebugLog(<< *this); \
1347 throw Exception("Missing parameter " _name, __FILE__, __LINE__); \
1348 } \
1349 return p->value(); \
1350 }
1351
1352 defineParam(ob,"ob",ExistsParameter,"RFC 5626");
1353 defineParam(gr, "gr", ExistsOrDataParameter, "RFC 5627");
1354 defineParam(comp, "comp", DataParameter, "RFC 3486");
1355 defineParam(duration, "duration", UInt32Parameter, "RFC 4240");
1356 defineParam(lr, "lr", ExistsParameter, "RFC 3261");
1357 defineParam(maddr, "maddr", DataParameter, "RFC 3261");
1358 defineParam(method, "method", DataParameter, "RFC 3261");
1359 defineParam(transport, "transport", DataParameter, "RFC 3261");
1360 defineParam(ttl, "ttl", UInt32Parameter, "RFC 3261");
1361 defineParam(user, "user", DataParameter, "RFC 3261, 4967");
1362 defineParam(extension, "ext", DataParameter, "RFC 3966"); // Token is used when ext is a user-parameter
1363 defineParam(sigcompId, "sigcomp-id", QuotedDataParameter, "RFC 5049");
1364 defineParam(rinstance, "rinstance", DataParameter, "proprietary (resip)");
1365 defineParam(addTransport, "addTransport", ExistsParameter, "RESIP INTERNAL");
1366 defineParam(wsSrcIp, "ws-src-ip", DataParameter, "RESIP INTERNAL (WebSocket)");
1367 defineParam(wsSrcPort, "ws-src-port", UInt32Parameter, "RESIP INTERNAL (WebSocket)");
1368
1369 #undef defineParam
1370
1371 HashValueImp(resip::Uri, resip::Data::from(data).hash());
1372
1373 /* ====================================================================
1374 * The Vovida Software License, Version 1.0
1375 *
1376 * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved.
1377 *
1378 * Redistribution and use in source and binary forms, with or without
1379 * modification, are permitted provided that the following conditions
1380 * are met:
1381 *
1382 * 1. Redistributions of source code must retain the above copyright
1383 * notice, this list of conditions and the following disclaimer.
1384 *
1385 * 2. Redistributions in binary form must reproduce the above copyright
1386 * notice, this list of conditions and the following disclaimer in
1387 * the documentation and/or other materials provided with the
1388 * distribution.
1389 *
1390 * 3. The names "VOCAL", "Vovida Open Communication Application Library",
1391 * and "Vovida Open Communication Application Library (VOCAL)" must
1392 * not be used to endorse or promote products derived from this
1393 * software without prior written permission. For written
1394 * permission, please contact vocal@vovida.org.
1395 *
1396 * 4. Products derived from this software may not be called "VOCAL", nor
1397 * may "VOCAL" appear in their name, without prior written
1398 * permission of Vovida Networks, Inc.
1399 *
1400 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
1401 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1402 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
1403 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA
1404 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
1405 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
1406 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
1407 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
1408 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
1409 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1410 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
1411 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
1412 * DAMAGE.
1413 *
1414 * ====================================================================
1415 *
1416 * This software consists of voluntary contributions made by Vovida
1417 * Networks, Inc. and many individuals on behalf of Vovida Networks,
1418 * Inc. For more information on Vovida Networks, Inc., please see
1419 * <http://www.vovida.org/>.
1420 *
1421 */

Properties

Name Value
svn:eol-style native
svn:mime-type text/plain

webmaster AT resiprocate DOT org
ViewVC Help
Powered by ViewVC 1.1.27