reSIProcate
SIP stack, Dialog Usage Manager and related libraries
Loading...
Searching...
No Matches
DnsResult.cxx
Go to the documentation of this file.
1#if defined(HAVE_CONFIG_H)
2#include "config.h"
3#endif
4
5#include <algorithm>
6#include <stack>
7
8#ifndef WIN32
9#include <sys/types.h>
10#include <sys/socket.h>
11#include <arpa/inet.h>
12#ifndef __CYGWIN__
13# include <netinet/in.h>
14# include <arpa/nameser.h>
15# include <resolv.h>
16#endif
17#include <netdb.h>
18#include <netinet/in.h>
19#else
20#include <Winsock2.h>
21#include <svcguid.h>
22#ifdef USE_IPV6
23#include <ws2tcpip.h>
24#endif
25#endif
26
27#include "rutil/DnsUtil.hxx"
28#include "rutil/Inserter.hxx"
29#include "rutil/Logger.hxx"
30#include "rutil/ParseBuffer.hxx"
31#include "rutil/Random.hxx"
32#include "rutil/compat.hxx"
33#include "rutil/Timer.hxx"
36#include "rutil/dns/DnsStub.hxx"
40#include "resip/stack/Tuple.hxx"
41#include "resip/stack/Uri.hxx"
42#include "rutil/WinLeakCheck.hxx" // not compatible with placement new used below
43
44using namespace resip;
45using namespace std;
46
47#define RESIPROCATE_SUBSYSTEM resip::Subsystem::DNS
48
50 : mResultSink(resultSink),
51 mOrder(order)
52{
53}
54
58
59void
61{
62 resip_assert(0);
63 delete this;
64}
65
66void
68{
69 resip_assert(0);
70 delete this;
71}
72
73void
75{
76 resip_assert(0);
77 delete this;
78}
79
80void
82{
83 mResultSink.onEnumResult(result, mOrder);
84 delete this;
85}
86
87void
89{
90 resip_assert(0);
91 delete this;
92}
93
94DnsResult::DnsResult(DnsInterface& interfaceObj, DnsStub& dns, RRVip& vip, DnsHandler* handler)
95 : mInterface(interfaceObj),
96 mDnsStub(dns),
97 mVip(vip),
98 mHandler(handler),
99 mSRVCount(0),
100 mDoingEnum(0),
101 mSips(false),
102 mTransport(UNKNOWN_TRANSPORT),
103 mPort(-1),
104 mHaveChosenTransport(false),
105 mType(Pending),
106 mCumulativeWeight(0),
107 mHaveReturnedResults(false)
108{
109}
110
112{
113 //DebugLog (<< "DnsResult::~DnsResult() " << *this);
114 resip_assert(mType != Pending);
115}
116
117void
118DnsResult::transition(Type t)
119{
120 if((t == Pending || t== Available) &&
121 (mType== Finished || mType == Destroyed) )
122 {
123 resip_assert(0);
124 }
125
126 mType = t;
127}
128
129void
131{
133 //DebugLog (<< "DnsResult::destroy() " << *this);
134
135 if (mType == Pending)
136 {
137 transition(Destroyed);
138 }
139 else
140 {
141 transition(Finished);
142 delete this;
143 }
144}
145
146bool
148{
149 if(mHaveReturnedResults)
150 {
151 resip_assert(!mLastReturnedPath.empty());
152 resip_assert(mLastReturnedPath.size()<=3);
153 GreyOrBlacklistCommand* command = new GreyOrBlacklistCommand(mVip, mInterface.getMarkManager(),
154 mLastReturnedPath.back(),
155 mLastResult,
156 expiry,
158 mDnsStub.queueCommand(command);
159 return true;
160 }
161 return false;
162}
163
164bool
166{
167 if(mHaveReturnedResults)
168 {
169 resip_assert(!mLastReturnedPath.empty());
170 resip_assert(mLastReturnedPath.size()<=3);
171 GreyOrBlacklistCommand* command = new GreyOrBlacklistCommand(mVip, mInterface.getMarkManager(),
172 mLastReturnedPath.back(),
173 mLastResult,
174 expiry,
176 mDnsStub.queueCommand(command);
177 return true;
178 }
179 return false;
180}
181
182void
183DnsResult::GreyOrBlacklistCommand::execute()
184{
185 mMarkManager.mark(mResult, mExpiry, mMarkType);
186
187 DebugLog( << "Remove vip " << mPathTop.domain << "(" << mPathTop.rrType << ")");
188 mVip.removeVip(mPathTop.domain, mPathTop.rrType);
189}
190
193{
194 resip_assert(mType != Destroyed);
195 if (mType == Available)
196 {
197 if (!mResults.empty())
198 {
199 return Available;
200 }
201 else
202 {
203 primeResults();
204 return available(); // recurse
205 }
206 }
207 else
208 {
209 return mType;
210 }
211}
212
213Tuple
215{
217 resip_assert(mCurrentPath.size()<=3);
218
219 mLastResult=mResults.front();
220 mResults.pop_front();
221
222 if(!mCurrentPath.empty() &&
223 (mCurrentPath.back().rrType==T_A || mCurrentPath.back().rrType==T_AAAA))
224 {
225 mCurrentPath.pop_back();
226 }
227
228 Item AorAAAA;
229 AorAAAA.domain = mLastResult.getTargetDomain();
230 AorAAAA.rrType = mLastResult.isV4() ? T_A : T_AAAA;
231 AorAAAA.value = Tuple::inet_ntop(mLastResult);
232 mCurrentPath.push_back(AorAAAA);
233
234 StackLog (<< "Returning next dns entry: " << mLastResult);
235 mLastReturnedPath=mCurrentPath;
236 mHaveReturnedResults=true;
237 return mLastResult;
238}
239
240void
242{
243 WhitelistCommand* command = new WhitelistCommand(mVip, mInterface.getMarkManager(), mLastReturnedPath, mLastResult);
244 mDnsStub.queueCommand(command);
245}
246
247void
248DnsResult::WhitelistCommand::execute()
249{
250 std::vector<Item>::iterator i;
251 for (i=mPath.begin(); i!=mPath.end(); ++i)
252 {
253 DebugLog( << "Whitelisting " << i->domain << "(" << i->rrType << "): " << i->value);
254 mVip.vip(i->domain, i->rrType, i->value);
255 }
256 // Remove greylist (if present)
257 mMarkManager.unmark(mResult, TupleMarkManager::GREY);
258}
259
260void
262{
263 DebugLog (<< "DnsResult::lookup " << uri);
264
265 // Dispatch lookup request to DnsThread
266 LookupCommand *command = new LookupCommand(*this, uri);
267 mDnsStub.queueCommand(command);
268}
269
270void
271DnsResult::lookupInternalWithEnum(const Uri& uri)
272{
273 if ( mType == Destroyed )
274 {
275 destroy();
276 return;
277 }
278 if (!mDnsStub.getEnumSuffixes().empty() &&
279 uri.isEnumSearchable() &&
280 mDnsStub.getEnumDomains().find(uri.host()) != mDnsStub.getEnumDomains().end())
281 {
282 mInputUri = uri;
283 int order = 0;
284 std::vector<Data> enums = uri.getEnumLookups(mDnsStub.getEnumSuffixes());
285 resip_assert(enums.size() >= 1);
286 if (!enums.empty())
287 {
288 mDoingEnum = (int)enums.size();
289 for(std::vector<Data>::iterator it = enums.begin(); it != enums.end(); it++)
290 {
291 InfoLog (<< "Doing ENUM lookup on " << *it);
292 mDnsStub.lookup<RR_NAPTR>(*it, Protocol::Enum, new EnumResult(*this, order++));
293 }
294 return;
295 }
296 }
297
298 mDoingEnum = 0;
299 lookupInternal(uri);
300}
301
302void
303DnsResult::lookupInternal(const Uri& uri)
304{
305 //assert(uri.scheme() == Symbols::Sips || uri.scheme() == Symbols::Sip);
306 mSips = (uri.scheme() == Symbols::Sips);
307 mTarget = (!mSips && uri.exists(p_maddr)) ? uri.param(p_maddr) : uri.host();
308 // remove brackets around ipv6 address if present
309 if (mTarget.size() >= 2 && mTarget[0] == '[' && mTarget[mTarget.size()-1] == ']')
310 {
311 mTarget = mTarget.substr(1,mTarget.size()-2);
312 }
313 mSrvKey = Symbols::UNDERSCORE + uri.scheme().substr(0, uri.scheme().size()) + Symbols::DOT;
314 bool isNumeric = DnsUtil::isIpAddress(mTarget);
315
316 if (uri.exists(p_transport))
317 {
318 mTransport = Tuple::toTransport(uri.param(p_transport));
319 mHaveChosenTransport=true;
320
321 if (isNumeric) // IP address specified
322 {
323 mPort = getDefaultPort(mTransport, uri.port());
324 // If the target Uri has a netns specified, we need to copy it into the Tuple
325 // We need to distinguish between the Uri not having an netns set and the
326 // the default/global netns "" (emtpy string).
327 Tuple tuple(mTarget, mPort, mTransport, mTarget, uri.netNs());
328#ifdef USE_NETNS
329 DebugLog(<< "DnsResult netns: " << uri.netNs());
330#endif
331
332 // ?bwc? If this is greylisted, what can we do? This is the only result
333 if(!(mInterface.getMarkManager().getMarkType(tuple)==TupleMarkManager::BLACK))
334 {
335 DebugLog (<< "Found immediate result: " << tuple);
336 mResults.push_back(tuple);
337 transition(Available);
338 if (mHandler) mHandler->handle(this);
339 }
340 else
341 {
342 transition(Available);
343 if (mHandler) mHandler->handle(this);
344 }
345
346 }
347 else if (uri.port() != 0)
348 {
349 mPort = uri.port();
350 lookupHost(mTarget); // for current target and port
351 }
352 else
353 {
354 if (mSips)
355 {
356 if (mTransport == UDP)
357 {
358 mTransport = DTLS;
359 if (!mInterface.isSupportedProtocol(mTransport))
360 {
361 DebugLog(<<"transport " << toData(mTransport) << " not supported");
362 transition(Finished);
363 if (mHandler) mHandler->handle(this);
364 return;
365 }
366 if(!mDnsStub.supportedType(T_SRV))
367 {
368 mPort = getDefaultPort(mTransport, uri.port());
369 lookupHost(mTarget); // for current target and port
370 }
371 else
372 {
373 mSRVCount++;
374 mDnsStub.lookup<RR_SRV>("_sips._udp." + mTarget, Protocol::Sip, this);
375 StackLog (<< "Doing SRV lookup of _sips._udp." << mTarget);
376 }
377 }
378 else
379 {
380 mTransport = TLS;
381 mHaveChosenTransport=true;
382 if (!mInterface.isSupportedProtocol(mTransport))
383 {
384 DebugLog(<<"transport " << toData(mTransport) << " not supported");
385 transition(Finished);
386 if (mHandler) mHandler->handle(this);
387 return;
388 }
389 if(!mDnsStub.supportedType(T_SRV))
390 {
391 mPort = getDefaultPort(mTransport, uri.port());
392 lookupHost(mTarget); // for current target and port
393 }
394 else
395 {
396 mSRVCount++;
397 mDnsStub.lookup<RR_SRV>("_sips._tcp." + mTarget, Protocol::Sip, this);
398 StackLog (<< "Doing SRV lookup of _sips._tcp." << mTarget);
399 }
400 }
401 }
402 else
403 {
404 if (!mInterface.isSupportedProtocol(mTransport))
405 {
406 DebugLog(<<"transport " << toData(mTransport) << " not supported");
407 transition(Finished);
408 if (mHandler) mHandler->handle(this);
409 return;
410 }
411
412 if(!mDnsStub.supportedType(T_SRV))
413 {
414 mPort = getDefaultPort(mTransport, uri.port());
415 lookupHost(mTarget); // for current target and port
416 return;
417 }
418
419 switch(mTransport)
420 {
421 case TLS: //deprecated, mean TLS over TCP
422 mSRVCount++;
423 mDnsStub.lookup<RR_SRV>("_sips._tcp." + mTarget, Protocol::Sip, this);
424 StackLog (<< "Doing SRV lookup of _sips._tcp." << mTarget);
425 break;
426 case DTLS: //deprecated, mean TLS over TCP
427 mSRVCount++;
428 mDnsStub.lookup<RR_SRV>("_sip._dtls." + mTarget, Protocol::Sip, this);
429 StackLog (<< "Doing SRV lookup of _sip._dtls." << mTarget);
430 break;
431 case TCP:
432 mSRVCount++;
433 mDnsStub.lookup<RR_SRV>("_sip._tcp." + mTarget, Protocol::Sip, this);
434 StackLog (<< "Doing SRV lookup of _sip._tcp." << mTarget);
435 break;
436 case SCTP:
437 case DCCP:
438 case UDP:
439 default: //fall through to UDP for unimplemented & unknown
440 mSRVCount++;
441 mDnsStub.lookup<RR_SRV>("_sip._udp." + mTarget, Protocol::Sip, this);
442 StackLog (<< "Doing SRV lookup of _sip._udp." << mTarget);
443 }
444 }
445 }
446 }
447 else // transport parameter is not specified
448 {
449 // if hostname is numeric, a port is specified, or NAPTR queries are not support by the DNS layer - skip NAPTR lookup
450 if (isNumeric || uri.port() != 0 || !mDnsStub.supportedType(T_NAPTR))
451 {
453 Tuple tuple;
454
455 if(isNumeric)
456 {
457 if(mSips)
458 {
459 if((mInterface.isSupported(TLS, V4) ||
460 mInterface.isSupported(TLS, V6)))
461 {
462 mTransport=TLS;
463 mPort = getDefaultPort(mTransport,uri.port());
464 tuple=Tuple(mTarget,mPort,mTransport,mTarget);
465 mark=mInterface.getMarkManager().getMarkType(tuple);
466 }
467 }
468 else
469 {
470 bool udpSupported = false;;
471 if(mark!=TupleMarkManager::OK && (mInterface.isSupported(UDP, V4) ||
472 mInterface.isSupported(UDP, V6)))
473 {
474 mTransport=UDP;
475 mPort = getDefaultPort(mTransport,uri.port());
476 tuple=Tuple(mTarget,mPort,mTransport,mTarget);
477 mark=mInterface.getMarkManager().getMarkType(tuple);
478 udpSupported = true;
479 }
480
481 if (!mInterface.getUdpOnlyOnNumeric())
482 {
483 bool allMarksNotOK = mark != TupleMarkManager::OK;
484 bool tcpSupported = false;
485 if(mark!=TupleMarkManager::OK && (mInterface.isSupported(TCP, V4) ||
486 mInterface.isSupported(TCP, V6)))
487 {
488 mTransport=TCP;
489 mPort = getDefaultPort(mTransport,uri.port());
490 // Need to get netns from Uri if set and set it in
491 // the Tuple for this IP address case
492 tuple=Tuple(mTarget, mPort, mTransport, mTarget, uri.netNs());
493#ifdef USE_NETNS
494 DebugLog(<< "DnsResult netns: " << uri.netNs());
495#endif
496 mark=mInterface.getMarkManager().getMarkType(tuple);
497 allMarksNotOK = mark != TupleMarkManager::OK;
498 tcpSupported = true;
499 }
500
501 if(mark!=TupleMarkManager::OK && (mInterface.isSupported(TLS, V4) ||
502 mInterface.isSupported(TLS, V6)))
503 {
504 mTransport=TLS;
505 mPort = getDefaultPort(mTransport,uri.port());
506 tuple=Tuple(mTarget,mPort,mTransport,mTarget);
507 mark=mInterface.getMarkManager().getMarkType(tuple);
508 allMarksNotOK = mark != TupleMarkManager::OK;
509 }
510
511 // If all transports are grey or blacklisted, then just fallback to UDP, assuming it is available
512 // or TCP if it is available. We don't want to end up continually trying TCP or TLS because all
513 // transports for this IP Address are greylisted.
514 if (allMarksNotOK)
515 {
516 if (udpSupported && mTransport != UDP)
517 {
518 mTransport = UDP;
519 mPort = getDefaultPort(mTransport, uri.port());
520 tuple = Tuple(mTarget, mPort, mTransport, mTarget);
521 mark = mInterface.getMarkManager().getMarkType(tuple);
522 }
523 else if (tcpSupported && mTransport != TCP)
524 {
525 mTransport = TCP;
526 mPort = getDefaultPort(mTransport, uri.port());
527 tuple = Tuple(mTarget, mPort, mTransport, mTarget, uri.netNs());
528 mark = mInterface.getMarkManager().getMarkType(tuple);
529 }
530 }
531 }
532 }
533
535 {
536 mHaveChosenTransport=true;
537 mResults.push_back(tuple);
538 transition(Available);
539 DebugLog (<< "Numeric result so return immediately: " << tuple);
540 }
541 else
542 {
543 // .bwc. Numeric result is blacklisted. Oh well.
544 resip_assert(mResults.empty());
545 transition(Available);
546 DebugLog(<< "Numeric result, but this result is currently blacklisted: " << tuple);
547 }
548
549 if (mHandler) mHandler->handle(this);
550
551 }
552 else // host is not numeric, so we need to make a query
553 {
554 mTransport=UNKNOWN_TRANSPORT;
555
556 if(mSips)
557 {
558 if(mInterface.isSupported(TLS, V4) || mInterface.isSupported(TLS, V6))
559 {
560 mTransport=TLS;
561 }
562 }
563 else if(mInterface.isSupported(UDP, V4) || mInterface.isSupported(UDP, V6))
564 {
565 mTransport=UDP;
566 }
567 else if(mInterface.isSupported(TCP, V4) || mInterface.isSupported(TCP, V6))
568 {
569 mTransport=TCP;
570 }
571 else if(mInterface.isSupported(TLS, V4) || mInterface.isSupported(TLS, V6))
572 {
573 mTransport=TLS;
574 }
575
576 if(mTransport!=UNKNOWN_TRANSPORT)
577 {
578 mPort=getDefaultPort(mTransport,uri.port());
579 lookupHost(mTarget);
580 }
581 else
582 {
583 // !bwc! Debatable.
584 resip_assert(0);
585 if (mHandler) mHandler->handle(this);
586 }
587 }
588 }
589 else // do NAPTR
590 {
591 mDnsStub.lookup<RR_NAPTR>(mTarget, Protocol::Sip, this); // for current target
592 }
593 }
594}
595
596void DnsResult::lookupHost(const Data& target)
597{
598 if (mInterface.isSupported(mTransport, V6))
599 {
600#ifdef USE_IPV6
601 DebugLog(<< "Doing host (AAAA) lookup: " << target);
602 mPassHostFromAAAAtoA = target;
603 mDnsStub.lookup<RR_AAAA>(target, Protocol::Sip, this);
604#else
605 resip_assert(0);
606 mDnsStub.lookup<RR_A>(target, Protocol::Sip, this);
607#endif
608 }
609 else if (mInterface.isSupported(mTransport, V4))
610 {
611 mDnsStub.lookup<RR_A>(target, Protocol::Sip, this);
612 }
613 else
614 {
615 CritLog(<<"Cannot lookup target="<<target
616 <<" because DnsInterface doesn't support transport="<<mTransport);
617 resip_assert(0);
618 }
619}
620
621int
622DnsResult::getDefaultPort(TransportType transport, int port)
623{
624 if (port == 0)
625 {
626 switch (transport)
627 {
628 case UDP:
630 case TCP:
632 case TLS:
633 case DTLS:
635 case WS:
636 return Symbols::SipWsPort;
637 case WSS:
638 return Symbols::SipWssPort;
639 default:
640 ErrLog( << "Should not get this - unknown transport" );
641 return Symbols::DefaultSipPort; // !cj! todo - remove
642 resip_assert(0);
643 }
644 }
645 else
646 {
647 return port;
648 }
649
650 resip_assert(0);
651 return 0;
652}
653
654void
655DnsResult::primeResults()
656{
657 StackLog(<< "Priming " << Inserter(mSRVResults));
658 //assert(mType != Pending);
659 //assert(mType != Finished);
660 resip_assert(mResults.empty());
661
662 if (!mSRVResults.empty())
663 {
664 SRV next = retrieveSRV();
665 StackLog (<< "Primed with SRV=" << next);
666 transition(Pending);
667 mPort = next.port;
668 mTransport = next.transport;
669 StackLog (<< "No A or AAAA record for " << next.target << " in additional records");
670 if (mInterface.isSupported(mTransport, V6) || mInterface.isSupported(mTransport, V4))
671 {
672 Item item;
673 clearCurrPath();
674 // Check if SRV came from a NAPTR look up
675 std::map<Data, NAPTR>::iterator it = mTopOrderedNAPTRs.find(next.key);
676 if(it != mTopOrderedNAPTRs.end())
677 {
678 item.domain = (*it).second.key;
679 item.rrType = T_NAPTR;
680 item.value = (*it).second.replacement;
681 mCurrentPath.push_back(item);
682 }
683 item.domain = next.key;
684 item.rrType = T_SRV;
685 item.value = next.target + ":" + Data(next.port);
686 mCurrentPath.push_back(item);
687 lookupHost(next.target);
688 }
689 else
690 {
691 resip_assert(0);
692 if (mHandler) mHandler->handle(this);
693 }
694 // don't call primeResults since we need to wait for the response to
695 // AAAA/A query first
696 }
697 else if(!mGreylistedTuples.empty())
698 {
699 for(std::vector<Tuple>::iterator i = mGreylistedTuples.begin(); i != mGreylistedTuples.end(); ++i)
700 {
701 mResults.push_back(*i);
702 }
703 mGreylistedTuples.clear();
704 transition(Available);
705 }
706 else
707 {
708 bool changed = (mType == Pending);
709 transition(Finished);
710 if (changed && mHandler) mHandler->handle(this);
711 }
712
713 // Either we are finished or there are results primed
714}
715
716// implement the selection algorithm from rfc2782 (SRV records)
718DnsResult::retrieveSRV()
719{
720 // !ah! if mTransport is known -- should we ignore those that don't match?!
721 resip_assert(!mSRVResults.empty());
722 resip_assert(mSRVCount==0);
723
724 const SRV& srv = *mSRVResults.begin();
725 int priority = srv.priority;
727
728 if(!mHaveChosenTransport)
729 {
730 // .bwc. We have not chosen a transport yet; this happens when we fail
731 // to find a NAPTR record, and the transport is not specified in the uri.
732 // In this contingency, we manufacture best-guess SRV queries for each
733 // transport we support, and try one transport at a time. This
734 // means we might try more than one transport for the uri in question.
735 transport = srv.transport;
736 }
737 else
738 {
739 // .bwc. We chose our transport before we started looking up SRVs.
740 // All SRVs must match.
741
742 transport=mTransport;
743 resip_assert(mSRVResults.begin()->transport==transport);
744 }
745
746 if (mCumulativeWeight == 0)
747 {
748 for (std::vector<SRV>::iterator i=mSRVResults.begin();
749 i!=mSRVResults.end()
750 && i->priority == priority
751 && i->transport == transport; i++)
752 {
753 resip_assert(i->weight>=0);
754 mCumulativeWeight += i->weight;
755 }
756 }
757
758 int selected =0;
759 if(mCumulativeWeight!=0)
760 {
761 selected = Random::getRandom() % (mCumulativeWeight);
762 }
763 else
764 {
765 // .bwc. All of the remaining SRVs (at this priority/type) have a weight
766 // of 0. The best we can do here is pick arbitrarily. In this case, we
767 // will end up picking the first.
768 // (selected will be less than the weight of the first SRV, causing the
769 // loop below to break on the first iteration)
770 selected=-1;
771 }
772
773 StackLog (<< "cumulative weight = " << mCumulativeWeight << " selected=" << selected);
774
775 std::vector<SRV>::iterator i;
776 int cumulativeWeight=0;
777 for (i=mSRVResults.begin(); i!=mSRVResults.end(); ++i)
778 {
779 cumulativeWeight+=i->weight;
780 if (cumulativeWeight > selected)
781 {
782 break;
783 }
784 }
785
786 if (i == mSRVResults.end())
787 {
788 InfoLog (<< "SRV Results problem selected=" << selected << " cum=" << mCumulativeWeight);
789 }
790 resip_assert(i != mSRVResults.end());
791 SRV next = *i;
792 mCumulativeWeight -= next.weight;
793 mSRVResults.erase(i);
794
795 if(!mSRVResults.empty())
796 {
797 int nextPriority=mSRVResults.begin()->priority;
798 TransportType nextTransport=mSRVResults.begin()->transport;
799
800 // .bwc. If we have finished traversing a priority value/transport type,
801 // we reset the cumulative weight to 0, to prompt its recalculation.
802 if(priority!=nextPriority || transport!=nextTransport)
803 {
804 mCumulativeWeight=0;
805 }
806 }
807
808 StackLog (<< "SRV: " << Inserter(mSRVResults));
809
810 return next;
811}
812
813DnsResult::NAPTR::NAPTR() : order(0), pref(0)
814{
815}
816
817bool
819{
820 if (key.empty()) // default value
821 {
822 return false;
823 }
824 else if (rhs.key.empty()) // default value
825 {
826 return true;
827 }
828 else if (order < rhs.order)
829 {
830 return true;
831 }
832 else if (order == rhs.order)
833 {
834 if (pref < rhs.pref)
835 {
836 return true;
837 }
838 else if (pref == rhs.pref)
839 {
840 return replacement < rhs.replacement;
841 }
842 }
843 return false;
844}
845
846DnsResult::SRV::SRV() : priority(0), weight(0), port(0)
847{
848 // .kw. member "transport" is not initialized. good default?
849}
850
851bool
853{
854 if (naptrpref < rhs.naptrpref)
855 {
856 return true;
857 }
858 else if(naptrpref == rhs.naptrpref)
859 {
860 if (transport < rhs.transport)
861 {
862 return true;
863 }
864 else if (transport == rhs.transport)
865 {
866 if (priority < rhs.priority)
867 {
868 return true;
869 }
870 else if (priority == rhs.priority)
871 {
872 if (weight < rhs.weight)
873 {
874 return true;
875 }
876 else if (weight == rhs.weight)
877 {
878 if (target < rhs.target)
879 {
880 return true;
881 }
882 }
883 }
884 }
885 }
886 return false;
887}
888
889void DnsResult::onDnsResult(const DNSResult<DnsHostRecord>& result)
890{
891 if (!mInterface.isSupported(mTransport, V4) && !mInterface.isSupported(mTransport, V6))
892 {
893 StackLog(<< "DnsResult::onDnsResult(): A record, for unsupported transport: target=" << mTarget << ", status=" << result.status);
894 return;
895 }
896 StackLog (<< "DnsResult::onDnsResult(): A record, target=" << mTarget << ", status=" << result.status);
897
898 // This function assumes that the A query that caused this callback
899 // is the _only_ outstanding DNS query that might result in a
900 // callback into this function
901 if ( mType == Destroyed )
902 {
903 destroy();
904 return;
905 }
906
907 if (result.status == 0)
908 {
909 for (vector<DnsHostRecord>::const_iterator it = result.records.begin(); it != result.records.end(); ++it)
910 {
911 in_addr addr;
912 addr.s_addr = (*it).addr().s_addr;
913 Tuple tuple(addr, mPort, mTransport, mTarget);
914
915 switch(mInterface.getMarkManager().getMarkType(tuple))
916 {
918 StackLog (<< "Adding " << tuple << " to result set");
919 mResults.push_back(tuple);
920 break;
922 StackLog(<< "Adding greylisted tuple " << tuple);
923 mGreylistedTuples.push_back(tuple);
924 break;
926 default:
927 ;// .bwc. Do nothing.
928 }
929
930 }
931
932 }
933 else
934 {
935 StackLog (<< "Failed async A query: " << result.msg);
936 }
937
938 if (mSRVCount == 0)
939 {
940 bool changed = (mType == Pending);
941 if (mResults.empty())
942 {
943#ifdef WIN32_SYNCRONOUS_RESOLUTION_ON_ARES_FAILURE
944 // Try Windows Name Resolution (not asyncronous)
945 WSAQUERYSET QuerySet = { 0 };
946 GUID guidServiceTypeUDP = SVCID_UDP(mPort);
947 GUID guidServiceTypeTCP = SVCID_TCP(mPort);
948 HANDLE hQuery;
949 QuerySet.dwSize = sizeof(WSAQUERYSET);
950 QuerySet.lpServiceClassId = mTransport == UDP ? &guidServiceTypeUDP : &guidServiceTypeTCP;
951 QuerySet.dwNameSpace = NS_ALL;
952 QuerySet.lpszServiceInstanceName = (char *)mTarget.c_str();
953 if(WSALookupServiceBegin(&QuerySet, LUP_RETURN_ADDR, &hQuery) == 0)
954 {
955 DWORD dwQuerySize = 256; // Starting size
956 int iRet = 0;
957 bool fDone = false;
958 LPWSAQUERYSET pQueryResult = (LPWSAQUERYSET) new char[dwQuerySize];
959 while(iRet == 0 && pQueryResult)
960 {
961 iRet = WSALookupServiceNext(hQuery, 0, &dwQuerySize, pQueryResult);
962 if(pQueryResult && iRet == -1 && GetLastError() == WSAEFAULT)
963 {
964 delete [] pQueryResult;
965 pQueryResult = (LPWSAQUERYSET) new char[dwQuerySize]; // Re-allocate new size
966 iRet = WSALookupServiceNext(hQuery, 0, &dwQuerySize, pQueryResult);
967 }
968 if(pQueryResult && iRet == 0)
969 {
970 for(DWORD i = 0; i < pQueryResult->dwNumberOfCsAddrs; i++)
971 {
972 SOCKADDR_IN *pSockAddrIn = (SOCKADDR_IN *)pQueryResult->lpcsaBuffer[i].RemoteAddr.lpSockaddr;
973 Tuple tuple(pSockAddrIn->sin_addr, mPort, mTransport, mTarget);
974
975 if(mInterface.getMarkManager().getMarkType(tuple)!=TupleMarkManager::BLACK)
976 {
977 // .bwc. This is the only result we have, so it doesn't
978 // matter if it is greylisted.
979 StackLog (<< "Adding (WIN) " << tuple << " to result set");
980 mResults.push_back(tuple);
981 transition(Available);
982 }
983
984 }
985 }
986 }
987 delete [] pQueryResult;
988 WSALookupServiceEnd(hQuery);
989 }
990
991 if(mResults.empty())
992 {
993 if(mSRVResults.empty())
994 {
995 if (mGreylistedTuples.empty())
996 {
997 transition(Finished);
998 clearCurrPath();
999 }
1000 else
1001 {
1002 for(std::vector<Tuple>::iterator i = mGreylistedTuples.begin(); i != mGreylistedTuples.end(); ++i)
1003 {
1004 mResults.push_back(*i);
1005 }
1006 mGreylistedTuples.clear();
1007 transition(Available);
1008 }
1009 }
1010 else
1011 {
1012 transition(Available);
1013 }
1014 }
1015#else
1016 // .bwc. If this A query failed, don't give up if there are more SRVs!
1017 if(mSRVResults.empty())
1018 {
1019 if (mGreylistedTuples.empty())
1020 {
1021 transition(Finished);
1022 clearCurrPath();
1023 }
1024 else
1025 {
1026 for(std::vector<Tuple>::iterator i = mGreylistedTuples.begin(); i != mGreylistedTuples.end(); ++i)
1027 {
1028 mResults.push_back(*i);
1029 }
1030 mGreylistedTuples.clear();
1031 transition(Available);
1032 }
1033 }
1034 else
1035 {
1036 transition(Available);
1037 }
1038#endif
1039 }
1040 else
1041 {
1042 transition(Available);
1043 }
1044 if (changed && mHandler) mHandler->handle(this);
1045 }
1046}
1047
1048void DnsResult::onDnsResult(const DNSResult<DnsAAAARecord>& result)
1049{
1050#ifdef USE_IPV6
1051 if (!mInterface.isSupported(mTransport, V6))
1052 {
1053 StackLog(<< "DnsResult::onDnsResult(): AAAA record, for unsupported transport: target=" << mTarget << ", status=" << result.status);
1054 return;
1055 }
1056 StackLog(<< "DnsResult::onDnsResult(): AAAA record, target=" << mTarget << ", status=" << result.status);
1057 resip_assert(mInterface.isSupported(mTransport, V6));
1058
1059 // This function assumes that the AAAA query that caused this callback
1060 // is the _only_ outstanding DNS query that might result in a
1061 // callback into this function
1062 if ( mType == Destroyed )
1063 {
1064 destroy();
1065 return;
1066 }
1067
1068 if (result.status == 0)
1069 {
1070 for (vector<DnsAAAARecord>::const_iterator it = result.records.begin(); it != result.records.end(); ++it)
1071 {
1072 Tuple tuple((*it).v6Address(), mPort, mTransport, mTarget);
1073
1074 switch(mInterface.getMarkManager().getMarkType(tuple))
1075 {
1077 StackLog (<< "Adding " << tuple << " to result set");
1078 mResults.push_back(tuple);
1079 break;
1081 StackLog(<< "Adding greylisted tuple " << tuple);
1082 mGreylistedTuples.push_back(tuple);
1083 break;
1085 default:
1086 ;// .bwc. Do nothing.
1087 }
1088 }
1089 }
1090 else
1091 {
1092 StackLog (<< "Failed async AAAA query: " << result.msg);
1093 }
1094 // funnel through to host processing
1095 mDnsStub.lookup<RR_A>(mPassHostFromAAAAtoA, Protocol::Sip, this);
1096#else
1097 resip_assert(0);
1098#endif
1099}
1100
1101void DnsResult::onDnsResult(const DNSResult<DnsSrvRecord>& result)
1102{
1103 resip_assert(mSRVCount>=0);
1104 mSRVCount--;
1105
1106 StackLog(<< "DnsResult::onDnsResult(): SRV record, target=" << mTarget << ", numRemainingSRV=" << mSRVCount << ", status = " << result.status);
1107
1108 // There could be multiple SRV queries outstanding, but there will be no
1109 // other DNS queries outstanding that might cause a callback into this
1110 // object.
1111 if (mType == Destroyed && mSRVCount == 0)
1112 {
1113 destroy();
1114 return;
1115 }
1116
1117 if (result.status == 0)
1118 {
1119 for (vector<DnsSrvRecord>::const_iterator it = result.records.begin(); it != result.records.end(); ++it)
1120 {
1121 SRV srv;
1122 srv.key = (*it).name();
1123 srv.key.lowercase();
1124 srv.priority = (*it).priority();
1125 srv.weight = (*it).weight();
1126 srv.port = (*it).port();
1127 srv.target = (*it).target();
1128 // fillin srv.naptrpref - if found in NAPTR map, then SRV query was driven from a NAPTR lookup
1129 std::map<Data, NAPTR>::iterator itNaptr = mTopOrderedNAPTRs.find(srv.key);
1130 if(itNaptr != mTopOrderedNAPTRs.end())
1131 {
1132 srv.naptrpref = itNaptr->second.pref;
1133 }
1134 else
1135 {
1136 srv.naptrpref = 0;
1137 }
1138 if (srv.key.find("_sips._udp") != Data::npos)
1139 {
1140 srv.transport = DTLS;
1141 }
1142 else if (srv.key.find("_sips._tcp") != Data::npos)
1143 {
1144 srv.transport = TLS;
1145 }
1146 else if (srv.key.find("_udp") != Data::npos)
1147 {
1148 srv.transport = UDP;
1149 }
1150 else if (srv.key.find("_dtls") != Data::npos)
1151 {
1152 srv.transport = DTLS;
1153 }
1154 else if (srv.key.find("_tls") != Data::npos)
1155 {
1156 srv.transport = TLS;
1157 }
1158 else if (srv.key.find("_tcp") != Data::npos)
1159 {
1160 srv.transport = TCP;
1161 }
1162 else
1163 {
1164 StackLog (<< "Skipping SRV " << srv.key);
1165 continue;
1166 }
1167
1168 if(!mHaveChosenTransport || srv.transport==mTransport)
1169 {
1170 // .bwc. If we have not committed to a given transport, or we have
1171 // committed to a given transport which this SRV matches, we will
1172 // add this SRV. We do not add SRVs that do not match a transport
1173 // we have committed to.
1174 mSRVResults.push_back(srv);
1175 }
1176 }
1177 }
1178 else
1179 {
1180 StackLog (<< "SRV lookup failed: " << result.domain << " " << result.status);
1181 }
1182
1183 // no outstanding queries
1184 if (mSRVCount == 0)
1185 {
1186 if (mSRVResults.empty())
1187 {
1188 if (mTransport == UNKNOWN_TRANSPORT)
1189 {
1190 if (mSips)
1191 {
1192 mTransport = TLS;
1193 mHaveChosenTransport=true;
1195 }
1196 else
1197 {
1198 if (mInterface.isSupported(UDP, V4))
1199 {
1200 mTransport = UDP;
1201 mHaveChosenTransport=true;
1202 }
1203 else if (mInterface.isSupported(TCP, V4))
1204 {
1205 mTransport = TCP;
1206 mHaveChosenTransport=true;
1207 }
1208 /* Yes, there is the possibility that at this point mTransport
1209 is still UNKNOWN_TRANSPORT, but this is likely to fail just as
1210 well as defaulting to UDP when there isn't an interface that
1211 supports UDP.
1212 It doesn't support failover to TCP when there is a UDP failure,
1213 but neither does the original code.
1214 This fixes the case where there is no UDP transport, but
1215 there was no explicit ;transport=tcp on the uri.
1216 (mjf)
1217 */
1219 }
1220 }
1221 else
1222 {
1223 mPort = getDefaultPort(mTransport, 0);
1224 }
1225
1226 StackLog (<< "No SRV records for " << mTarget << ". Trying A records");
1227 if (mInterface.isSupported(mTransport, V6) || mInterface.isSupported(mTransport, V4))
1228 {
1229 lookupHost(mTarget);
1230 }
1231 else
1232 {
1233 primeResults();
1234 }
1235 }
1236 else
1237 {
1238 std::sort(mSRVResults.begin(),mSRVResults.end()); // !jf! uggh
1239 primeResults();
1240 }
1241 }
1242}
1243
1244static Data enumService1("e2u+sip");
1245static Data enumService2("sip+e2u");
1246void
1247DnsResult::onEnumResult(const DNSResult<DnsNaptrRecord>& result, int order)
1248{
1249 DnsNaptrRecord best;
1250
1251 if (result.status == 0)
1252 {
1253 for (vector<DnsNaptrRecord>::const_iterator i = result.records.begin(); i != result.records.end(); ++i)
1254 {
1255 InfoLog(<< "service=" << i->service()
1256 << " order=" << i->order()
1257 << " flags=" << i->flags()
1258 << " regexp substitution=" << i->regexp().replacement()
1259 << " replacement=" << i->replacement());
1260
1261 if ((isEqualNoCase(i->service(), enumService1) ||
1262 isEqualNoCase(i->service(), enumService2)) && // only E2U records
1263 //i->flags().find("u") != Data::npos && // must be terminal record
1264 i->replacement().empty())
1265
1266 {
1267 if (best.order() == -1)
1268 {
1269 best = *i;
1270 }
1271 else if (i->order() < best.order())
1272 {
1273 best = *i;
1274 }
1275 else if (i->order() == best.order() &&
1276 i->preference() < best.preference())
1277 {
1278 best = *i;
1279 }
1280 }
1281 }
1282 }
1283
1284 Lock l(mEnumDestinationsMutex);
1285 resip_assert(mDoingEnum > 0);
1286
1287 mDoingEnum--;
1288
1289 StackLog(<< "DnsResult::onDnsResult(): ENUM NAPTR record, target=" << mTarget << ", numRemainingEnum=" << mDoingEnum << ", status = " << result.status);
1290
1291 if (best.order() != -1)
1292 {
1293 InfoLog(<< "Found an enum result: " << best.regexp().replacement());
1294 try
1295 {
1296 Uri rewrite(best.regexp().apply(Data::from(mInputUri)));
1297 InfoLog(<< "Rewrote uri " << mInputUri << " -> " << rewrite);
1298 mEnumDestinations[order] = rewrite;
1299 }
1300 catch (ParseException& e)
1301 {
1302 ErrLog(<< "Caught exception: " << e);
1303 // we just don't add anything to mEnumDestinations...
1304 // later, if mEnumDestinations is empty after all ENUM queries,
1305 // it will fall back to mInputUri
1306 }
1307 }
1308
1309 if(mDoingEnum == 0)
1310 {
1311 DebugLog(<< "All ENUM DNS queries done, checking for results...");
1312 std::map<int,Uri>::iterator it = mEnumDestinations.begin();
1313 if(it != mEnumDestinations.end())
1314 {
1315 DebugLog(<< "Using result for suffix " << (it->first + 1));
1316 mHandler->rewriteRequest(it->second);
1317 lookupInternal(it->second);
1318 }
1319 else
1320 {
1321 DebugLog(<< "No valid ENUM query result, falling back to request URI");
1322 lookupInternal(mInputUri);
1323 }
1324 }
1325}
1326
1327void
1328DnsResult::onNaptrResult(const DNSResult<DnsNaptrRecord>& result)
1329{
1330 bool bFail = false;
1331 if (result.status == 0)
1332 {
1333 int preferredNAPTROrder=65536; // order is unsigned short - so max is 65535, initialize to one higher
1334 std::list<NAPTR> supportedNAPTRs;
1335 for (vector<DnsNaptrRecord>::const_iterator it = result.records.begin(); it != result.records.end(); ++it)
1336 {
1337 NAPTR naptr;
1338 naptr.key = (*it).name();
1339 naptr.flags = (*it).flags();
1340 naptr.order = (*it).order();
1341 naptr.pref = (*it).preference();
1342 naptr.regex = (*it).regexp();
1343 naptr.replacement = (*it).replacement();
1344 naptr.service = (*it).service();
1345
1346 StackLog (<< "Received NAPTR record: " << naptr);
1347
1348 if ( !mSips || naptr.service.find("SIPS") == 0)
1349 {
1350 if (mInterface.isSupported(naptr.service))
1351 {
1352 supportedNAPTRs.push_back(naptr);
1353 if(naptr.order < preferredNAPTROrder)
1354 {
1355 preferredNAPTROrder = naptr.order;
1356 }
1357 }
1358 }
1359 }
1360
1361 // This means that dns / NAPTR is misconfigured for this client
1362 if (supportedNAPTRs.empty())
1363 {
1364 StackLog (<< "There are no NAPTR records supported by this client so do an SRV lookup instead");
1365 bFail = true;
1366 }
1367 else
1368 {
1369 // Go through NAPTR's and issue SRV queries for each supported record, that has equal
1370 // ordering to the most preferred order discovered above
1371 transition(Pending);
1372 for (std::list<NAPTR>::const_iterator it = supportedNAPTRs.begin(); it != supportedNAPTRs.end(); ++it)
1373 {
1374 if(preferredNAPTROrder == (*it).order)
1375 {
1376 StackLog (<< "NAPTR record is supported and matches highest priority order. doing SRV query: " << (*it));
1377 mTopOrderedNAPTRs[(*it).replacement] = (*it);
1378 mSRVCount++;
1379 mDnsStub.lookup<RR_SRV>((*it).replacement, Protocol::Sip, this);
1380 }
1381 }
1382 }
1383 }
1384 else
1385 {
1386 if (result.status > 6)
1387 {
1388 DebugLog (<< "NAPTR lookup failed: " << result.domain << " " << result.msg);
1389 }
1390 else
1391 {
1392 StackLog (<< "NAPTR lookup failed: " << result.domain << " " << result.msg);
1393 }
1394 bFail = true;
1395 }
1396
1397 if (bFail)
1398 {
1399 if (mSips)
1400 {
1401 if (!mInterface.isSupportedProtocol(TLS))
1402 {
1403 transition(Finished);
1404 if (mHandler) mHandler->handle(this);
1405 return;
1406 }
1407
1408 mSRVCount++;
1409 mDnsStub.lookup<RR_SRV>("_sips._tcp." + mTarget, Protocol::Sip, this);
1410 StackLog (<< "Doing SRV lookup of _sips._tcp." << mTarget);
1411 }
1412 else
1413 {
1414 if (mInterface.isSupportedProtocol(TLS))
1415 {
1416 mDnsStub.lookup<RR_SRV>("_sips._tcp." + mTarget, Protocol::Sip, this);
1417 ++mSRVCount;
1418 StackLog (<< "Doing SRV lookup of _sips._tcp." << mTarget);
1419 }
1420 if (mInterface.isSupportedProtocol(DTLS))
1421 {
1422 mDnsStub.lookup<RR_SRV>("_sips._udp." + mTarget, Protocol::Sip, this);
1423 ++mSRVCount;
1424 StackLog (<< "Doing SRV lookup of _sips._udp." << mTarget);
1425 }
1426 if (mInterface.isSupportedProtocol(TCP))
1427 {
1428 mDnsStub.lookup<RR_SRV>("_sip._tcp." + mTarget, Protocol::Sip, this);
1429 ++mSRVCount;
1430 StackLog (<< "Doing SRV lookup of _sip._tcp." << mTarget);
1431 }
1432 if (mInterface.isSupportedProtocol(UDP))
1433 {
1434 mDnsStub.lookup<RR_SRV>("_sip._udp." + mTarget, Protocol::Sip, this);
1435 ++mSRVCount;
1436 StackLog (<< "Doing SRV lookup of _sip._udp." << mTarget);
1437 }
1438 }
1439 }
1440}
1441
1442void
1443DnsResult::onDnsResult(const DNSResult<DnsNaptrRecord>& result)
1444{
1445 StackLog(<< "DnsResult::onDnsResult(): NAPTR record, inputUri=" << mInputUri << ", target=" << mTarget << ", status=" << result.status);
1446
1447 // This function assumes that the NAPTR query that caused this
1448 // callback is the ONLY outstanding query that might cause
1449 // a callback into this object
1450 if (mType == Destroyed)
1451 {
1452 destroy();
1453 return;
1454 }
1455
1456 onNaptrResult(result);
1457}
1458
1459void DnsResult::onDnsResult(const DNSResult<DnsCnameRecord>& result)
1460{
1461}
1462
1463void DnsResult::clearCurrPath()
1464{
1465 while (!mCurrentPath.empty())
1466 {
1467 mCurrentPath.pop_back();
1468 }
1469}
1470
1472resip::operator<<(EncodeStream& strm, const resip::DnsResult& result)
1473{
1474 strm << result.mTarget << " --> " << Inserter(result.mResults);
1475 return strm;
1476}
1477
1478
1480resip::operator<<(EncodeStream& strm, const resip::DnsResult::NAPTR& naptr)
1481{
1482 strm << "key=" << naptr.key
1483 << " order=" << naptr.order
1484 << " pref=" << naptr.pref
1485 << " flags=" << naptr.flags
1486 << " service=" << naptr.service
1487 << " regex=" << naptr.regex.regexp() << " -> " << naptr.regex.replacement()
1488 << " replacement=" << naptr.replacement;
1489 return strm;
1490}
1491
1493resip::operator<<(EncodeStream& strm, const resip::DnsResult::SRV& srv)
1494{
1495 strm << "key=" << srv.key
1496 << " t=" << Tuple::toData(srv.transport)
1497 << " p=" << srv.priority
1498 << " w=" << srv.weight
1499 << " port=" << srv.port
1500 << " target=" << srv.target;
1501 return strm;
1502}
1503
1504// Copyright (c) 2003, Jason Fischl
1505/* ====================================================================
1506 * The Vovida Software License, Version 1.0
1507 *
1508 * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved.
1509 *
1510 * Redistribution and use in source and binary forms, with or without
1511 * modification, are permitted provided that the following conditions
1512 * are met:
1513 *
1514 * 1. Redistributions of source code must retain the above copyright
1515 * notice, this list of conditions and the following disclaimer.
1516 *
1517 * 2. Redistributions in binary form must reproduce the above copyright
1518 * notice, this list of conditions and the following disclaimer in
1519 * the documentation and/or other materials provided with the
1520 * distribution.
1521 *
1522 * 3. The names "VOCAL", "Vovida Open Communication Application Library",
1523 * and "Vovida Open Communication Application Library (VOCAL)" must
1524 * not be used to endorse or promote products derived from this
1525 * software without prior written permission. For written
1526 * permission, please contact vocal@vovida.org.
1527 *
1528 * 4. Products derived from this software may not be called "VOCAL", nor
1529 * may "VOCAL" appear in their name, without prior written
1530 * permission of Vovida Networks, Inc.
1531 *
1532 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
1533 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1534 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
1535 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA
1536 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
1537 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
1538 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
1539 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
1540 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
1541 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1542 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
1543 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
1544 * DAMAGE.
1545 *
1546 * ====================================================================
1547 *
1548 * This software consists of voluntary contributions made by Vovida
1549 * Networks, Inc. and many individuals on behalf of Vovida Networks,
1550 * Inc. For more information on Vovida Networks, Inc., please see
1551 * <http://www.vovida.org/>.
1552 *
1553 */
1554
1555// vim: softtabstop=3:shiftwidth=3:expandtab
static Data enumService1("e2u+sip")
static Data enumService2("sip+e2u")
#define DebugLog(args_)
Definition Logger.hxx:128
#define StackLog(args_)
Definition Logger.hxx:125
#define InfoLog(args_)
Definition Logger.hxx:131
#define CritLog(args_)
Definition Logger.hxx:140
#define ErrLog(args_)
Definition Logger.hxx:137
#define resip_assert(x)
This file needs to work for both C and C++ code.
#define resip_assert_not_null(x)
std::vector< T > records
Definition DnsStub.hxx:52
An alternative to std::string, encapsulates an arbitrary buffer of bytes.
Definition Data.hxx:90
const char * c_str() const
Returns a null-terminated string representing.
Definition Data.cxx:1097
Data substr(size_type first, size_type count=Data::npos) const
Copies a portion of this Data into a new Data.
Definition Data.cxx:1932
bool empty() const noexcept
Checks whether the Data is empty.
Definition Data.hxx:591
size_type size() const noexcept
Returns the number of bytes in this Data.
Definition Data.hxx:599
static Data from(const T &x)
Converts from arbitrary other type to Data.
Definition Data.hxx:398
static const size_type npos
Represents an impossible position; returned to indicate failure to find.
Definition Data.hxx:887
virtual void handle(DnsResult *result)=0
virtual void rewriteRequest(const Uri &uri)=0
TupleMarkManager & getMarkManager()
bool isSupportedProtocol(TransportType t)
bool getUdpOnlyOnNumeric() const
bool isSupported(const Data &service)
Data apply(const Data &input) const
const Data & replacement() const
const RegExp & regexp() const
DnsNaptrRecord::RegExp regex
bool operator<(const NAPTR &rhs) const
TransportType transport
bool operator<(const SRV &rhs) const
void lookup(const Uri &uri)
bool greylistLast(uint64_t expiry)
friend class LookupCommand
bool blacklistLast(uint64_t expiry)
Data target() const
DnsResult(DnsInterface &interfaceObj, DnsStub &dns, RRVip &vip, DnsHandler *handler)
Definition DnsResult.cxx:94
virtual ~DnsResult()
const std::map< Data, Data > & getEnumDomains() const
Definition DnsStub.cxx:844
const std::vector< Data > & getEnumSuffixes() const
Definition DnsStub.cxx:825
void lookup(const Data &target, DnsResultSink *sink)
Definition DnsStub.hxx:189
virtual void queueCommand(Command *command)
Definition DnsStub.cxx:165
bool supportedType(int)
Definition DnsStub.cxx:324
static bool isIpAddress(const Data &ipAddress)
Definition DnsUtil.cxx:453
virtual void onEnumResult(const DNSResult< DnsNaptrRecord > &result, int order)=0
EnumResult(EnumResultSink &resultSink, int order)
Definition DnsResult.cxx:49
void onDnsResult(const DNSResult< DnsHostRecord > &)
Definition DnsResult.cxx:60
BaseException used to indicate parse failures.
static const int Enum
Definition RRList.hxx:25
static const int Sip
Definition RRList.hxx:22
static int getRandom()
Returns a postive integer (31 bits) of randomness.
Definition Random.cxx:261
static const char * Sips
Definition Symbols.hxx:63
static const int SipWssPort
Definition Symbols.hxx:84
static const int DefaultSipsPort
Definition Symbols.hxx:85
static const char * DOT
Definition Symbols.hxx:19
static const int SipWsPort
Definition Symbols.hxx:83
static const int DefaultSipPort
Definition Symbols.hxx:81
static const char * UNDERSCORE
Definition Symbols.hxx:46
MarkType getMarkType(const Tuple &tuple)
Represents a network address.
Definition Tuple.hxx:59
static const Data & toData(TransportType)
Converts the TransportType to a string representation of the transport type, e.g.
Definition Tuple.cxx:927
bool isV4() const
Definition Tuple.cxx:531
static Data inet_ntop(const Tuple &tuple)
Converts the binary socket address to presentation format, via the DnsUtil::inet_ntop() method.
Definition Tuple.cxx:939
static TransportType toTransport(const Data &)
Converts a string representation of transport type, i.e.
Definition Tuple.cxx:921
const Data & getTargetDomain() const
Get the domain name this address tuple intends to represent.
Definition Tuple.hxx:259
Represents the "SIP-URI" and "SIPS-URI" elements in the RFC 3261 grammar.
Definition Uri.hxx:22
bool isEnumSearchable() const
Returns true if the uri can be converted into a string that can be used as an enum lookup.
Definition Uri.cxx:265
std::vector< Data > getEnumLookups(const std::vector< Data > &suffixes) const
Return a vector of domains to do a NAPTR lookup for enum.
Definition Uri.cxx:318
int & port()
Definition Uri.hxx:145
Data & scheme()
Definition Uri.hxx:143
bool exists(const Param< Uri > &paramType) const
Definition Uri.cxx:1701
Data & netNs()
Definition Uri.hxx:150
Data & host()
Definition Uri.hxx:40
const Data & param(const ExtensionParameter &param) const
Const accessor for non-natively-supported parameter types.
This file is used to handle compatibility fixes/tweaks so reSIProcate can function on multiple platfo...
#define T_NAPTR
Definition compat.hxx:140
#define T_A
Definition compat.hxx:152
#define T_AAAA
Definition compat.hxx:148
#define T_SRV
Definition compat.hxx:144
dcm! – add UnusedChecking(_enum) below;
const resip::Data & toData(const TransportType typeEnum)
InserterClass< T > Inserter(const T &t)
Templatized function to construct an instance of InserterClass for a container to be inserted.
Definition Inserter.hxx:312
bool isEqualNoCase(const Data &left, const Data &right)
Definition Data.hxx:1116
std::unique_lock< Mutex > Lock
A convenience class to lock a Lockable (such as a Mutex) on object creation, and unlock on destructio...
Definition Lock.hxx:28
unsigned long long uint64_t
Definition Stun.hxx:39
TransportType
An enumeration of transport protocols.
@ UNKNOWN_TRANSPORT
EncodeStream & operator<<(EncodeStream &strm, const BaseException &e)
#define EncodeStream