1 |
#include <rutil/Log.hxx> |
2 |
#include <rutil/Logger.hxx> |
3 |
#include <rutil/DnsUtil.hxx> |
4 |
#include <resip/stack/SdpContents.hxx> |
5 |
#include <resip/stack/ConnectionTerminated.hxx> |
6 |
#include <resip/stack/Helper.hxx> |
7 |
#include <resip/dum/AppDialogSetFactory.hxx> |
8 |
#include <resip/dum/ClientAuthManager.hxx> |
9 |
#include <resip/dum/KeepAliveManager.hxx> |
10 |
#include <resip/dum/ClientInviteSession.hxx> |
11 |
#include <resip/dum/ServerInviteSession.hxx> |
12 |
#include <resip/dum/ClientSubscription.hxx> |
13 |
#include <resip/dum/ServerSubscription.hxx> |
14 |
#include <resip/dum/ClientRegistration.hxx> |
15 |
#include <resip/dum/ServerRegistration.hxx> |
16 |
#include <resip/dum/ServerOutOfDialogReq.hxx> |
17 |
|
18 |
#if defined (USE_SSL) |
19 |
#if defined(WIN32) |
20 |
#include "resip/stack/ssl/WinSecurity.hxx" |
21 |
#else |
22 |
#include "resip/stack/ssl/Security.hxx" |
23 |
#endif |
24 |
#endif |
25 |
|
26 |
#include "basicClientUserAgent.hxx" |
27 |
#include "basicClientCall.hxx" |
28 |
|
29 |
using namespace resip; |
30 |
using namespace std; |
31 |
|
32 |
#define RESIPROCATE_SUBSYSTEM Subsystem::TEST |
33 |
|
34 |
static unsigned int MaxRegistrationRetryTime = 1800; // RFC5626 section 4.5 default |
35 |
static unsigned int BaseRegistrationRetryTimeAllFlowsFailed = 30; // RFC5626 section 4.5 default |
36 |
static unsigned int BaseRegistrationRetryTime = 90; // RFC5626 section 4.5 default |
37 |
|
38 |
class ClientAppDialogSetFactory : public AppDialogSetFactory |
39 |
{ |
40 |
public: |
41 |
ClientAppDialogSetFactory(BasicClientUserAgent& ua) : mUserAgent(ua) {} |
42 |
resip::AppDialogSet* createAppDialogSet(DialogUsageManager& dum, const SipMessage& msg) |
43 |
{ |
44 |
switch(msg.method()) |
45 |
{ |
46 |
case INVITE: |
47 |
return new BasicClientCall(mUserAgent); |
48 |
break; |
49 |
default: |
50 |
return AppDialogSetFactory::createAppDialogSet(dum, msg); |
51 |
break; |
52 |
} |
53 |
} |
54 |
private: |
55 |
BasicClientUserAgent& mUserAgent; |
56 |
}; |
57 |
|
58 |
// Used to set the IP Address in outbound SDP to match the IP address choosen by the stack to send the message on |
59 |
class SdpMessageDecorator : public MessageDecorator |
60 |
{ |
61 |
public: |
62 |
virtual ~SdpMessageDecorator() {} |
63 |
virtual void decorateMessage(SipMessage &msg, |
64 |
const Tuple &source, |
65 |
const Tuple &destination, |
66 |
const Data& sigcompId) |
67 |
{ |
68 |
SdpContents* sdp = dynamic_cast<SdpContents*>(msg.getContents()); |
69 |
if(sdp) |
70 |
{ |
71 |
// Fill in IP and Port from source |
72 |
sdp->session().connection().setAddress(Tuple::inet_ntop(source), source.ipVersion() == V6 ? SdpContents::IP6 : SdpContents::IP4); |
73 |
sdp->session().origin().setAddress(Tuple::inet_ntop(source), source.ipVersion() == V6 ? SdpContents::IP6 : SdpContents::IP4); |
74 |
InfoLog( << "SdpMessageDecorator: src=" << source << ", dest=" << destination << ", msg=" << endl << msg.brief()); |
75 |
} |
76 |
} |
77 |
virtual void rollbackMessage(SipMessage& msg) {} // Nothing to do |
78 |
virtual MessageDecorator* clone() const { return new SdpMessageDecorator; } |
79 |
}; |
80 |
|
81 |
BasicClientUserAgent::BasicClientUserAgent(int argc, char** argv) : |
82 |
BasicClientCmdLineParser(argc, argv), |
83 |
mProfile(new MasterProfile), |
84 |
#if defined(USE_SSL) |
85 |
mSecurity(new Security(mCertPath)), |
86 |
#else |
87 |
mSecurity(0), |
88 |
#endif |
89 |
mStack(mSecurity, DnsStub::EmptyNameserverList, &mSelectInterruptor), |
90 |
mDum(new DialogUsageManager(mStack)), |
91 |
mStackThread(mStack, mSelectInterruptor), |
92 |
mDumShutdownRequested(false), |
93 |
mDumShutdown(false), |
94 |
mRegistrationRetryDelayTime(0) |
95 |
{ |
96 |
Log::initialize(mLogType, mLogLevel, argv[0]); |
97 |
|
98 |
addTransport(UDP, mUdpPort); |
99 |
addTransport(TCP, mTcpPort); |
100 |
#if defined(USE_SSL) |
101 |
addTransport(TLS, mTlsPort); |
102 |
#endif |
103 |
#if defined(USED_DTLS) |
104 |
addTransport(DTLS, mDtlsPort); |
105 |
#endif |
106 |
|
107 |
// Disable Statistics Manager |
108 |
mStack.statisticsManagerEnabled() = false; |
109 |
|
110 |
// Supported Methods |
111 |
mProfile->clearSupportedMethods(); |
112 |
mProfile->addSupportedMethod(INVITE); |
113 |
mProfile->addSupportedMethod(ACK); |
114 |
mProfile->addSupportedMethod(CANCEL); |
115 |
mProfile->addSupportedMethod(OPTIONS); |
116 |
mProfile->addSupportedMethod(BYE); |
117 |
//mProfile->addSupportedMethod(REFER); |
118 |
//mProfile->addSupportedMethod(NOTIFY); |
119 |
//mProfile->addSupportedMethod(SUBSCRIBE); |
120 |
//mProfile->addSupportedMethod(UPDATE); |
121 |
mProfile->addSupportedMethod(INFO); |
122 |
mProfile->addSupportedMethod(PRACK); |
123 |
//mProfile->addSupportedOptionTag(Token(Symbols::C100rel)); // Automatically added when using setUacReliableProvisionalMode |
124 |
mProfile->setUacReliableProvisionalMode(MasterProfile::Supported); |
125 |
//mProfile->setUasReliableProvisionalMode(MasterProfile::Supported); // TODO - needs support in DUM, currently unimplemented |
126 |
|
127 |
// Support Languages |
128 |
mProfile->clearSupportedLanguages(); |
129 |
mProfile->addSupportedLanguage(Token("en")); |
130 |
|
131 |
// Support Mime Types |
132 |
mProfile->clearSupportedMimeTypes(); |
133 |
mProfile->addSupportedMimeType(INVITE, Mime("application", "sdp")); |
134 |
mProfile->addSupportedMimeType(INVITE, Mime("multipart", "mixed")); |
135 |
mProfile->addSupportedMimeType(INVITE, Mime("multipart", "signed")); |
136 |
mProfile->addSupportedMimeType(INVITE, Mime("multipart", "alternative")); |
137 |
mProfile->addSupportedMimeType(OPTIONS,Mime("application", "sdp")); |
138 |
mProfile->addSupportedMimeType(OPTIONS,Mime("multipart", "mixed")); |
139 |
mProfile->addSupportedMimeType(OPTIONS, Mime("multipart", "signed")); |
140 |
mProfile->addSupportedMimeType(OPTIONS, Mime("multipart", "alternative")); |
141 |
mProfile->addSupportedMimeType(PRACK, Mime("application", "sdp")); |
142 |
mProfile->addSupportedMimeType(PRACK, Mime("multipart", "mixed")); |
143 |
mProfile->addSupportedMimeType(PRACK, Mime("multipart", "signed")); |
144 |
mProfile->addSupportedMimeType(PRACK, Mime("multipart", "alternative")); |
145 |
mProfile->addSupportedMimeType(UPDATE, Mime("application", "sdp")); |
146 |
mProfile->addSupportedMimeType(UPDATE, Mime("multipart", "mixed")); |
147 |
mProfile->addSupportedMimeType(UPDATE, Mime("multipart", "signed")); |
148 |
mProfile->addSupportedMimeType(UPDATE, Mime("multipart", "alternative")); |
149 |
//mProfile->addSupportedMimeType(NOTIFY, Mime("message", "sipfrag")); |
150 |
|
151 |
// Supported Options Tags |
152 |
mProfile->clearSupportedOptionTags(); |
153 |
//mMasterProfile->addSupportedOptionTag(Token(Symbols::Replaces)); |
154 |
mProfile->addSupportedOptionTag(Token(Symbols::Timer)); // Enable Session Timers |
155 |
if(mOutboundEnabled) |
156 |
{ |
157 |
mProfile->addSupportedOptionTag(Token(Symbols::Outbound)); // RFC 5626 - outbound |
158 |
mProfile->addSupportedOptionTag(Token(Symbols::Path)); // RFC 3327 - path |
159 |
} |
160 |
//mMasterProfile->addSupportedOptionTag(Token(Symbols::NoReferSub)); |
161 |
//mMasterProfile->addSupportedOptionTag(Token(Symbols::TargetDialog)); |
162 |
|
163 |
// Supported Schemes |
164 |
mProfile->clearSupportedSchemes(); |
165 |
mProfile->addSupportedScheme("sip"); |
166 |
#if defined(USE_SSL) |
167 |
mProfile->addSupportedScheme("sips"); |
168 |
#endif |
169 |
|
170 |
// Validation Settings |
171 |
mProfile->validateContentEnabled() = false; |
172 |
mProfile->validateContentLanguageEnabled() = false; |
173 |
mProfile->validateAcceptEnabled() = false; |
174 |
|
175 |
// Have stack add Allow/Supported/Accept headers to INVITE dialog establishment messages |
176 |
mProfile->clearAdvertisedCapabilities(); // Remove Profile Defaults, then add our preferences |
177 |
mProfile->addAdvertisedCapability(Headers::Allow); |
178 |
//mProfile->addAdvertisedCapability(Headers::AcceptEncoding); // This can be misleading - it might specify what is expected in response |
179 |
mProfile->addAdvertisedCapability(Headers::AcceptLanguage); |
180 |
mProfile->addAdvertisedCapability(Headers::Supported); |
181 |
mProfile->setMethodsParamEnabled(true); |
182 |
|
183 |
// Install Sdp Message Decorator |
184 |
SharedPtr<MessageDecorator> outboundDecorator(new SdpMessageDecorator); |
185 |
mProfile->setOutboundDecorator(outboundDecorator); |
186 |
|
187 |
// Other Profile Settings |
188 |
mProfile->setUserAgent("basicClient/1.0"); |
189 |
mProfile->setDefaultRegistrationTime(mRegisterDuration); |
190 |
mProfile->setDefaultRegistrationRetryTime(120); |
191 |
if(!mContact.host().empty()) |
192 |
{ |
193 |
mProfile->setOverrideHostAndPort(mContact); |
194 |
} |
195 |
if(!mOutboundProxy.host().empty()) |
196 |
{ |
197 |
mProfile->setOutboundProxy(Uri(mOutboundProxy)); |
198 |
//mProfile->setForceOutboundProxyOnAllRequestsEnabled(true); |
199 |
mProfile->setExpressOutboundAsRouteSetEnabled(true); |
200 |
} |
201 |
|
202 |
// UserProfile Settings |
203 |
mProfile->setDefaultFrom(NameAddr(mAor)); |
204 |
mProfile->setDigestCredential(mAor.host(), mAor.user(), mPassword); |
205 |
// Generate InstanceId appropriate for testing only. Should be UUID that persists |
206 |
// across machine re-starts and is unique to this applicaiton instance. The one used |
207 |
// here is only as unique as the hostname of this machine. If someone runs two |
208 |
// instances of this application on the same host for the same Aor, then things will |
209 |
// break. See RFC5626 section 4.1 |
210 |
Data hostname = DnsUtil::getLocalHostName(); |
211 |
Data instanceHash = hostname.md5().uppercase(); |
212 |
assert(instanceHash.size() == 32); |
213 |
Data instanceId(48, Data::Preallocate); |
214 |
instanceId += "<urn:uuid:"; |
215 |
instanceId += instanceHash.substr(0, 8); |
216 |
instanceId += "-"; |
217 |
instanceId += instanceHash.substr(8, 4); |
218 |
instanceId += "-"; |
219 |
instanceId += instanceHash.substr(12, 4); |
220 |
instanceId += "-"; |
221 |
instanceId += instanceHash.substr(16, 4); |
222 |
instanceId += "-"; |
223 |
instanceId += instanceHash.substr(20, 12); |
224 |
instanceId += ">"; |
225 |
mProfile->setInstanceId(instanceId); |
226 |
if(mOutboundEnabled) |
227 |
{ |
228 |
mProfile->setRegId(1); |
229 |
mProfile->clientOutboundEnabled() = true; |
230 |
} |
231 |
|
232 |
// Install Managers |
233 |
mDum->setClientAuthManager(std::auto_ptr<ClientAuthManager>(new ClientAuthManager)); |
234 |
mDum->setKeepAliveManager(std::auto_ptr<KeepAliveManager>(new KeepAliveManager)); |
235 |
mProfile->setKeepAliveTimeForDatagram(30); |
236 |
//mProfile->setKeepAliveTimeForStream(120); |
237 |
mProfile->setKeepAliveTimeForStream(30); // !slg! TODO - testing only |
238 |
|
239 |
// Install Handlers |
240 |
mDum->setInviteSessionHandler(this); |
241 |
mDum->setDialogSetHandler(this); |
242 |
mDum->addOutOfDialogHandler(OPTIONS, this); |
243 |
//mDum->addOutOfDialogHandler(REFER, this); |
244 |
mDum->setRedirectHandler(this); |
245 |
mDum->setClientRegistrationHandler(this); |
246 |
//mDum->addClientSubscriptionHandler("refer", this); |
247 |
//mDum->addServerSubscriptionHandler("refer", this); |
248 |
|
249 |
// Set AppDialogSetFactory |
250 |
auto_ptr<AppDialogSetFactory> dsf(new ClientAppDialogSetFactory(*this)); |
251 |
mDum->setAppDialogSetFactory(dsf); |
252 |
|
253 |
mDum->setMasterProfile(mProfile); |
254 |
|
255 |
mDum->registerForConnectionTermination(this); |
256 |
} |
257 |
|
258 |
BasicClientUserAgent::~BasicClientUserAgent() |
259 |
{ |
260 |
mStackThread.shutdown(); |
261 |
mStackThread.join(); |
262 |
|
263 |
delete mDum; |
264 |
} |
265 |
|
266 |
void |
267 |
BasicClientUserAgent::startup() |
268 |
{ |
269 |
mStackThread.run(); |
270 |
|
271 |
if (mRegisterDuration) |
272 |
{ |
273 |
InfoLog (<< "register for " << mAor); |
274 |
mDum->send(mDum->makeRegistration(NameAddr(mAor))); |
275 |
} |
276 |
} |
277 |
|
278 |
void |
279 |
BasicClientUserAgent::shutdown() |
280 |
{ |
281 |
assert(mDum); |
282 |
mDumShutdownRequested = true; // Set flag so that shutdown operations can be run in dum process thread |
283 |
} |
284 |
|
285 |
bool |
286 |
BasicClientUserAgent::process(int timeoutMs) |
287 |
{ |
288 |
if(!mDumShutdown) |
289 |
{ |
290 |
if(mDumShutdownRequested) |
291 |
{ |
292 |
// unregister |
293 |
if(mRegHandle.isValid()) |
294 |
{ |
295 |
mRegHandle->end(); |
296 |
} |
297 |
|
298 |
// End all calls - !slg! TODO |
299 |
|
300 |
mDum->shutdown(this); |
301 |
mDumShutdownRequested = false; |
302 |
} |
303 |
mDum->process(timeoutMs); |
304 |
return true; |
305 |
} |
306 |
return false; |
307 |
} |
308 |
|
309 |
void |
310 |
BasicClientUserAgent::addTransport(TransportType type, int port) |
311 |
{ |
312 |
if(port == 0) return; // Transport disabled |
313 |
|
314 |
for (; port < port+10; ++port) |
315 |
{ |
316 |
try |
317 |
{ |
318 |
if (!mNoV4) |
319 |
{ |
320 |
mStack.addTransport(type, port, V4, StunEnabled, Data::Empty, mTlsDomain); |
321 |
return; |
322 |
} |
323 |
|
324 |
if (mEnableV6) |
325 |
{ |
326 |
mStack.addTransport(type, port, V6, StunEnabled, Data::Empty, mTlsDomain); |
327 |
return; |
328 |
} |
329 |
} |
330 |
catch (BaseException& e) |
331 |
{ |
332 |
InfoLog (<< "Caught: " << e); |
333 |
WarningLog (<< "Failed to add " << Tuple::toData(type) << " transport on " << port); |
334 |
} |
335 |
} |
336 |
throw Transport::Exception("Port already in use", __FILE__, __LINE__); |
337 |
} |
338 |
|
339 |
void |
340 |
BasicClientUserAgent::post(Message* msg) |
341 |
{ |
342 |
ConnectionTerminated* terminated = dynamic_cast<ConnectionTerminated*>(msg); |
343 |
if (terminated) |
344 |
{ |
345 |
InfoLog(<< "BasicClientUserAgent received connection terminated message for: " << terminated->getFlow()); |
346 |
delete msg; |
347 |
return; |
348 |
} |
349 |
assert(false); |
350 |
} |
351 |
|
352 |
void |
353 |
BasicClientUserAgent::onDumCanBeDeleted() |
354 |
{ |
355 |
mDumShutdown = true; |
356 |
} |
357 |
|
358 |
//////////////////////////////////////////////////////////////////////////////// |
359 |
// Registration Handler //////////////////////////////////////////////////////// |
360 |
//////////////////////////////////////////////////////////////////////////////// |
361 |
void |
362 |
BasicClientUserAgent::onSuccess(ClientRegistrationHandle h, const SipMessage& msg) |
363 |
{ |
364 |
InfoLog(<< "onSuccess(ClientRegistrationHandle): msg=" << msg.brief()); |
365 |
mRegHandle = h; |
366 |
mRegistrationRetryDelayTime = 0; // reset |
367 |
} |
368 |
|
369 |
void |
370 |
BasicClientUserAgent::onFailure(ClientRegistrationHandle h, const SipMessage& msg) |
371 |
{ |
372 |
InfoLog(<< "onFailure(ClientRegistrationHandle): msg=" << msg.brief()); |
373 |
mRegHandle = h; |
374 |
} |
375 |
|
376 |
void |
377 |
BasicClientUserAgent::onRemoved(ClientRegistrationHandle h, const SipMessage&msg) |
378 |
{ |
379 |
InfoLog(<< "onRemoved(ClientRegistrationHandle): msg=" << msg.brief()); |
380 |
mRegHandle = h; |
381 |
} |
382 |
|
383 |
int |
384 |
BasicClientUserAgent::onRequestRetry(ClientRegistrationHandle h, int retryMinimum, const SipMessage& msg) |
385 |
{ |
386 |
mRegHandle = h; |
387 |
|
388 |
if(mRegistrationRetryDelayTime == 0) |
389 |
{ |
390 |
mRegistrationRetryDelayTime = BaseRegistrationRetryTimeAllFlowsFailed; // We only have one flow in this test app |
391 |
} |
392 |
|
393 |
// Use back off procedures of RFC 5626 section 4.5 |
394 |
mRegistrationRetryDelayTime = resipMin(MaxRegistrationRetryTime, mRegistrationRetryDelayTime * 2); |
395 |
|
396 |
// return an evenly distributed random number between 50% and 100% of mRegistrationRetryDelayTime |
397 |
int retryTime = Helper::jitterValue(mRegistrationRetryDelayTime, 50, 100); |
398 |
InfoLog(<< "onRequestRetry(ClientRegistrationHandle): msg=" << msg.brief() << ", retryTime=" << retryTime); |
399 |
|
400 |
return retryTime; |
401 |
} |
402 |
|
403 |
|
404 |
//////////////////////////////////////////////////////////////////////////////// |
405 |
// InviteSessionHandler //////////////////////////////////////////////////////// |
406 |
//////////////////////////////////////////////////////////////////////////////// |
407 |
void |
408 |
BasicClientUserAgent::onNewSession(ClientInviteSessionHandle h, InviteSession::OfferAnswerType oat, const SipMessage& msg) |
409 |
{ |
410 |
dynamic_cast<BasicClientCall *>(h->getAppDialogSet().get())->onNewSession(h, oat, msg); |
411 |
} |
412 |
|
413 |
void |
414 |
BasicClientUserAgent::onNewSession(ServerInviteSessionHandle h, InviteSession::OfferAnswerType oat, const SipMessage& msg) |
415 |
{ |
416 |
dynamic_cast<BasicClientCall *>(h->getAppDialogSet().get())->onNewSession(h, oat, msg); |
417 |
} |
418 |
|
419 |
void |
420 |
BasicClientUserAgent::onFailure(ClientInviteSessionHandle h, const SipMessage& msg) |
421 |
{ |
422 |
dynamic_cast<BasicClientCall *>(h->getAppDialogSet().get())->onFailure(h, msg); |
423 |
} |
424 |
|
425 |
void |
426 |
BasicClientUserAgent::onEarlyMedia(ClientInviteSessionHandle h, const SipMessage& msg, const SdpContents& sdp) |
427 |
{ |
428 |
dynamic_cast<BasicClientCall *>(h->getAppDialogSet().get())->onEarlyMedia(h, msg, sdp); |
429 |
} |
430 |
|
431 |
void |
432 |
BasicClientUserAgent::onProvisional(ClientInviteSessionHandle h, const SipMessage& msg) |
433 |
{ |
434 |
dynamic_cast<BasicClientCall *>(h->getAppDialogSet().get())->onProvisional(h, msg); |
435 |
} |
436 |
|
437 |
void |
438 |
BasicClientUserAgent::onConnected(ClientInviteSessionHandle h, const SipMessage& msg) |
439 |
{ |
440 |
dynamic_cast<BasicClientCall *>(h->getAppDialogSet().get())->onConnected(h, msg); |
441 |
} |
442 |
|
443 |
void |
444 |
BasicClientUserAgent::onConnected(InviteSessionHandle h, const SipMessage& msg) |
445 |
{ |
446 |
dynamic_cast<BasicClientCall *>(h->getAppDialogSet().get())->onConnected(h, msg); |
447 |
} |
448 |
|
449 |
void |
450 |
BasicClientUserAgent::onStaleCallTimeout(ClientInviteSessionHandle h) |
451 |
{ |
452 |
dynamic_cast<BasicClientCall *>(h->getAppDialogSet().get())->onStaleCallTimeout(h); |
453 |
} |
454 |
|
455 |
void |
456 |
BasicClientUserAgent::onTerminated(InviteSessionHandle h, InviteSessionHandler::TerminatedReason reason, const SipMessage* msg) |
457 |
{ |
458 |
dynamic_cast<BasicClientCall *>(h->getAppDialogSet().get())->onTerminated(h, reason, msg); |
459 |
} |
460 |
|
461 |
void |
462 |
BasicClientUserAgent::onRedirected(ClientInviteSessionHandle h, const SipMessage& msg) |
463 |
{ |
464 |
dynamic_cast<BasicClientCall *>(h->getAppDialogSet().get())->onRedirected(h, msg); |
465 |
} |
466 |
|
467 |
void |
468 |
BasicClientUserAgent::onAnswer(InviteSessionHandle h, const SipMessage& msg, const SdpContents& sdp) |
469 |
{ |
470 |
dynamic_cast<BasicClientCall *>(h->getAppDialogSet().get())->onAnswer(h, msg, sdp); |
471 |
} |
472 |
|
473 |
void |
474 |
BasicClientUserAgent::onOffer(InviteSessionHandle h, const SipMessage& msg, const SdpContents& sdp) |
475 |
{ |
476 |
dynamic_cast<BasicClientCall *>(h->getAppDialogSet().get())->onOffer(h, msg, sdp); |
477 |
} |
478 |
|
479 |
void |
480 |
BasicClientUserAgent::onOfferRequired(InviteSessionHandle h, const SipMessage& msg) |
481 |
{ |
482 |
dynamic_cast<BasicClientCall *>(h->getAppDialogSet().get())->onOfferRequired(h, msg); |
483 |
} |
484 |
|
485 |
void |
486 |
BasicClientUserAgent::onOfferRejected(InviteSessionHandle h, const SipMessage* msg) |
487 |
{ |
488 |
dynamic_cast<BasicClientCall *>(h->getAppDialogSet().get())->onOfferRejected(h, msg); |
489 |
} |
490 |
|
491 |
void |
492 |
BasicClientUserAgent::onOfferRequestRejected(InviteSessionHandle h, const SipMessage& msg) |
493 |
{ |
494 |
dynamic_cast<BasicClientCall *>(h->getAppDialogSet().get())->onOfferRequestRejected(h, msg); |
495 |
} |
496 |
|
497 |
void |
498 |
BasicClientUserAgent::onRemoteSdpChanged(InviteSessionHandle h, const SipMessage& msg, const SdpContents& sdp) |
499 |
{ |
500 |
dynamic_cast<BasicClientCall *>(h->getAppDialogSet().get())->onRemoteSdpChanged(h, msg, sdp); |
501 |
} |
502 |
|
503 |
void |
504 |
BasicClientUserAgent::onInfo(InviteSessionHandle h, const SipMessage& msg) |
505 |
{ |
506 |
dynamic_cast<BasicClientCall *>(h->getAppDialogSet().get())->onInfo(h, msg); |
507 |
} |
508 |
|
509 |
void |
510 |
BasicClientUserAgent::onInfoSuccess(InviteSessionHandle h, const SipMessage& msg) |
511 |
{ |
512 |
dynamic_cast<BasicClientCall *>(h->getAppDialogSet().get())->onInfoSuccess(h, msg); |
513 |
} |
514 |
|
515 |
void |
516 |
BasicClientUserAgent::onInfoFailure(InviteSessionHandle h, const SipMessage& msg) |
517 |
{ |
518 |
dynamic_cast<BasicClientCall *>(h->getAppDialogSet().get())->onInfoFailure(h, msg); |
519 |
} |
520 |
|
521 |
void |
522 |
BasicClientUserAgent::onRefer(InviteSessionHandle h, ServerSubscriptionHandle ssh, const SipMessage& msg) |
523 |
{ |
524 |
dynamic_cast<BasicClientCall *>(h->getAppDialogSet().get())->onRefer(h, ssh, msg); |
525 |
} |
526 |
|
527 |
void |
528 |
BasicClientUserAgent::onReferAccepted(InviteSessionHandle h, ClientSubscriptionHandle csh, const SipMessage& msg) |
529 |
{ |
530 |
dynamic_cast<BasicClientCall *>(h->getAppDialogSet().get())->onReferAccepted(h, csh, msg); |
531 |
} |
532 |
|
533 |
void |
534 |
BasicClientUserAgent::onReferRejected(InviteSessionHandle h, const SipMessage& msg) |
535 |
{ |
536 |
dynamic_cast<BasicClientCall *>(h->getAppDialogSet().get())->onReferRejected(h, msg); |
537 |
} |
538 |
|
539 |
void |
540 |
BasicClientUserAgent::onReferNoSub(InviteSessionHandle h, const SipMessage& msg) |
541 |
{ |
542 |
dynamic_cast<BasicClientCall *>(h->getAppDialogSet().get())->onReferNoSub(h, msg); |
543 |
} |
544 |
|
545 |
void |
546 |
BasicClientUserAgent::onMessage(InviteSessionHandle h, const SipMessage& msg) |
547 |
{ |
548 |
dynamic_cast<BasicClientCall *>(h->getAppDialogSet().get())->onMessage(h, msg); |
549 |
} |
550 |
|
551 |
void |
552 |
BasicClientUserAgent::onMessageSuccess(InviteSessionHandle h, const SipMessage& msg) |
553 |
{ |
554 |
dynamic_cast<BasicClientCall *>(h->getAppDialogSet().get())->onMessageSuccess(h, msg); |
555 |
} |
556 |
|
557 |
void |
558 |
BasicClientUserAgent::onMessageFailure(InviteSessionHandle h, const SipMessage& msg) |
559 |
{ |
560 |
dynamic_cast<BasicClientCall *>(h->getAppDialogSet().get())->onMessageFailure(h, msg); |
561 |
} |
562 |
|
563 |
void |
564 |
BasicClientUserAgent::onForkDestroyed(ClientInviteSessionHandle h) |
565 |
{ |
566 |
dynamic_cast<BasicClientCall *>(h->getAppDialogSet().get())->onForkDestroyed(h); |
567 |
} |
568 |
|
569 |
void |
570 |
BasicClientUserAgent::onReadyToSend(InviteSessionHandle h, SipMessage& msg) |
571 |
{ |
572 |
dynamic_cast<BasicClientCall *>(h->getAppDialogSet().get())->onReadyToSend(h, msg); |
573 |
} |
574 |
|
575 |
|
576 |
//////////////////////////////////////////////////////////////////////////////// |
577 |
// DialogSetHandler /////////////////////////////////////////////////// |
578 |
//////////////////////////////////////////////////////////////////////////////// |
579 |
void |
580 |
BasicClientUserAgent::onTrying(AppDialogSetHandle h, const SipMessage& msg) |
581 |
{ |
582 |
BasicClientCall *call = dynamic_cast<BasicClientCall *>(h.get()); |
583 |
if(call) |
584 |
{ |
585 |
call->onTrying(h, msg); |
586 |
} |
587 |
else |
588 |
{ |
589 |
InfoLog(<< "onTrying(AppDialogSetHandle): " << msg.brief()); |
590 |
} |
591 |
} |
592 |
|
593 |
void |
594 |
BasicClientUserAgent::onNonDialogCreatingProvisional(AppDialogSetHandle h, const SipMessage& msg) |
595 |
{ |
596 |
BasicClientCall *call = dynamic_cast<BasicClientCall *>(h.get()); |
597 |
if(call) |
598 |
{ |
599 |
call->onNonDialogCreatingProvisional(h, msg); |
600 |
} |
601 |
else |
602 |
{ |
603 |
InfoLog(<< "onNonDialogCreatingProvisional(AppDialogSetHandle): " << msg.brief()); |
604 |
} |
605 |
} |
606 |
|
607 |
//////////////////////////////////////////////////////////////////////////////// |
608 |
// ClientSubscriptionHandler /////////////////////////////////////////////////// |
609 |
//////////////////////////////////////////////////////////////////////////////// |
610 |
void |
611 |
BasicClientUserAgent::onUpdatePending(ClientSubscriptionHandle h, const SipMessage& msg, bool outOfOrder) |
612 |
{ |
613 |
BasicClientCall* call = dynamic_cast<BasicClientCall *>(h->getAppDialogSet().get()); |
614 |
if(call) |
615 |
{ |
616 |
call->onUpdatePending(h, msg, outOfOrder); |
617 |
return; |
618 |
} |
619 |
InfoLog(<< "onUpdatePending(ClientSubscriptionHandle): " << msg.brief()); |
620 |
} |
621 |
|
622 |
void |
623 |
BasicClientUserAgent::onUpdateActive(ClientSubscriptionHandle h, const SipMessage& msg, bool outOfOrder) |
624 |
{ |
625 |
BasicClientCall* call = dynamic_cast<BasicClientCall *>(h->getAppDialogSet().get()); |
626 |
if(call) |
627 |
{ |
628 |
call->onUpdateActive(h, msg, outOfOrder); |
629 |
return; |
630 |
} |
631 |
InfoLog(<< "onUpdateActive(ClientSubscriptionHandle): " << msg.brief()); |
632 |
} |
633 |
|
634 |
void |
635 |
BasicClientUserAgent::onUpdateExtension(ClientSubscriptionHandle h, const SipMessage& msg, bool outOfOrder) |
636 |
{ |
637 |
BasicClientCall* call = dynamic_cast<BasicClientCall *>(h->getAppDialogSet().get()); |
638 |
if(call) |
639 |
{ |
640 |
call->onUpdateExtension(h, msg, outOfOrder); |
641 |
return; |
642 |
} |
643 |
InfoLog(<< "onUpdateExtension(ClientSubscriptionHandle): " << msg.brief()); |
644 |
} |
645 |
|
646 |
void |
647 |
BasicClientUserAgent::onNotifyNotReceived(ClientSubscriptionHandle h) |
648 |
{ |
649 |
BasicClientCall* call = dynamic_cast<BasicClientCall *>(h->getAppDialogSet().get()); |
650 |
if(call) |
651 |
{ |
652 |
call->onNotifyNotReceived(h); |
653 |
return; |
654 |
} |
655 |
WarningLog(<< "onNotifyNotReceived(ClientSubscriptionHandle)"); |
656 |
h->end(); |
657 |
} |
658 |
|
659 |
void |
660 |
BasicClientUserAgent::onTerminated(ClientSubscriptionHandle h, const SipMessage* msg) |
661 |
{ |
662 |
BasicClientCall* call = dynamic_cast<BasicClientCall *>(h->getAppDialogSet().get()); |
663 |
if(call) |
664 |
{ |
665 |
call->onTerminated(h, msg); |
666 |
return; |
667 |
} |
668 |
if(msg) |
669 |
{ |
670 |
InfoLog(<< "onTerminated(ClientSubscriptionHandle): msg=" << msg->brief()); |
671 |
} |
672 |
else |
673 |
{ |
674 |
InfoLog(<< "onTerminated(ClientSubscriptionHandle)"); |
675 |
} |
676 |
} |
677 |
|
678 |
void |
679 |
BasicClientUserAgent::onNewSubscription(ClientSubscriptionHandle h, const SipMessage& msg) |
680 |
{ |
681 |
BasicClientCall* call = dynamic_cast<BasicClientCall *>(h->getAppDialogSet().get()); |
682 |
if(call) |
683 |
{ |
684 |
call->onNewSubscription(h, msg); |
685 |
return; |
686 |
} |
687 |
InfoLog(<< "onNewSubscription(ClientSubscriptionHandle): msg=" << msg.brief()); |
688 |
} |
689 |
|
690 |
int |
691 |
BasicClientUserAgent::onRequestRetry(ClientSubscriptionHandle h, int retrySeconds, const SipMessage& msg) |
692 |
{ |
693 |
BasicClientCall* call = dynamic_cast<BasicClientCall *>(h->getAppDialogSet().get()); |
694 |
if(call) |
695 |
{ |
696 |
return call->onRequestRetry(h, retrySeconds, msg); |
697 |
} |
698 |
InfoLog(<< "onRequestRetry(ClientSubscriptionHandle): msg=" << msg.brief()); |
699 |
return -1; |
700 |
} |
701 |
|
702 |
//////////////////////////////////////////////////////////////////////////////// |
703 |
// ServerSubscriptionHandler /////////////////////////////////////////////////// |
704 |
//////////////////////////////////////////////////////////////////////////////// |
705 |
void |
706 |
BasicClientUserAgent::onNewSubscription(ServerSubscriptionHandle, const SipMessage& msg) |
707 |
{ |
708 |
InfoLog(<< "onNewSubscription(ServerSubscriptionHandle): " << msg.brief()); |
709 |
} |
710 |
|
711 |
void |
712 |
BasicClientUserAgent::onNewSubscriptionFromRefer(ServerSubscriptionHandle ss, const SipMessage& msg) |
713 |
{ |
714 |
InfoLog(<< "onNewSubscriptionFromRefer(ServerSubscriptionHandle): " << msg.brief()); |
715 |
// Received an out-of-dialog refer request with implicit subscription |
716 |
try |
717 |
{ |
718 |
if(msg.exists(h_ReferTo)) |
719 |
{ |
720 |
// Check if TargetDialog header is present |
721 |
if(msg.exists(h_TargetDialog)) |
722 |
{ |
723 |
pair<InviteSessionHandle, int> presult; |
724 |
presult = mDum->findInviteSession(msg.header(h_TargetDialog)); |
725 |
if(!(presult.first == InviteSessionHandle::NotValid())) |
726 |
{ |
727 |
BasicClientCall* callToRefer = (BasicClientCall*)presult.first->getAppDialogSet().get(); |
728 |
|
729 |
callToRefer->onRefer(presult.first, ss, msg); |
730 |
return; |
731 |
} |
732 |
} |
733 |
|
734 |
// We don't support ood refers that don't target a dialog - reject request |
735 |
WarningLog (<< "onNewSubscriptionFromRefer(ServerSubscriptionHandle): Received ood refer (noSub) w/out a Target-Dialog: " << msg.brief()); |
736 |
ss->send(ss->reject(400)); |
737 |
} |
738 |
else |
739 |
{ |
740 |
WarningLog (<< "onNewSubscriptionFromRefer(ServerSubscriptionHandle): Received refer w/out a Refer-To: " << msg.brief()); |
741 |
ss->send(ss->reject(400)); |
742 |
} |
743 |
} |
744 |
catch(BaseException &e) |
745 |
{ |
746 |
WarningLog(<< "onNewSubscriptionFromRefer(ServerSubscriptionHandle): exception " << e); |
747 |
} |
748 |
catch(...) |
749 |
{ |
750 |
WarningLog(<< "onNewSubscriptionFromRefer(ServerSubscriptionHandle): unknown exception"); |
751 |
} |
752 |
} |
753 |
|
754 |
void |
755 |
BasicClientUserAgent::onRefresh(ServerSubscriptionHandle, const SipMessage& msg) |
756 |
{ |
757 |
InfoLog(<< "onRefresh(ServerSubscriptionHandle): " << msg.brief()); |
758 |
} |
759 |
|
760 |
void |
761 |
BasicClientUserAgent::onTerminated(ServerSubscriptionHandle) |
762 |
{ |
763 |
InfoLog(<< "onTerminated(ServerSubscriptionHandle)"); |
764 |
} |
765 |
|
766 |
void |
767 |
BasicClientUserAgent::onReadyToSend(ServerSubscriptionHandle, SipMessage&) |
768 |
{ |
769 |
} |
770 |
|
771 |
void |
772 |
BasicClientUserAgent::onNotifyRejected(ServerSubscriptionHandle, const SipMessage& msg) |
773 |
{ |
774 |
WarningLog(<< "onNotifyRejected(ServerSubscriptionHandle): " << msg.brief()); |
775 |
} |
776 |
|
777 |
void |
778 |
BasicClientUserAgent::onError(ServerSubscriptionHandle, const SipMessage& msg) |
779 |
{ |
780 |
WarningLog(<< "onError(ServerSubscriptionHandle): " << msg.brief()); |
781 |
} |
782 |
|
783 |
void |
784 |
BasicClientUserAgent::onExpiredByClient(ServerSubscriptionHandle, const SipMessage& sub, SipMessage& notify) |
785 |
{ |
786 |
InfoLog(<< "onExpiredByClient(ServerSubscriptionHandle): " << notify.brief()); |
787 |
} |
788 |
|
789 |
void |
790 |
BasicClientUserAgent::onExpired(ServerSubscriptionHandle, SipMessage& msg) |
791 |
{ |
792 |
InfoLog(<< "onExpired(ServerSubscriptionHandle): " << msg.brief()); |
793 |
} |
794 |
|
795 |
bool |
796 |
BasicClientUserAgent::hasDefaultExpires() const |
797 |
{ |
798 |
return true; |
799 |
} |
800 |
|
801 |
UInt32 |
802 |
BasicClientUserAgent::getDefaultExpires() const |
803 |
{ |
804 |
return 60; |
805 |
} |
806 |
|
807 |
//////////////////////////////////////////////////////////////////////////////// |
808 |
// OutOfDialogHandler ////////////////////////////////////////////////////////// |
809 |
//////////////////////////////////////////////////////////////////////////////// |
810 |
void |
811 |
BasicClientUserAgent::onSuccess(ClientOutOfDialogReqHandle, const SipMessage& msg) |
812 |
{ |
813 |
InfoLog(<< "onSuccess(ClientOutOfDialogReqHandle): " << msg.brief()); |
814 |
} |
815 |
|
816 |
void |
817 |
BasicClientUserAgent::onFailure(ClientOutOfDialogReqHandle h, const SipMessage& msg) |
818 |
{ |
819 |
WarningLog(<< "onFailure(ClientOutOfDialogReqHandle): " << msg.brief()); |
820 |
} |
821 |
|
822 |
void |
823 |
BasicClientUserAgent::onReceivedRequest(ServerOutOfDialogReqHandle ood, const SipMessage& msg) |
824 |
{ |
825 |
InfoLog(<< "onReceivedRequest(ServerOutOfDialogReqHandle): " << msg.brief()); |
826 |
|
827 |
switch(msg.method()) |
828 |
{ |
829 |
case OPTIONS: |
830 |
{ |
831 |
SharedPtr<SipMessage> optionsAnswer = ood->answerOptions(); |
832 |
ood->send(optionsAnswer); |
833 |
break; |
834 |
} |
835 |
default: |
836 |
ood->send(ood->reject(501 /* Not Implemented*/)); |
837 |
break; |
838 |
} |
839 |
} |
840 |
|
841 |
//////////////////////////////////////////////////////////////////////////////// |
842 |
// RedirectHandler ///////////////////////////////////////////////////////////// |
843 |
//////////////////////////////////////////////////////////////////////////////// |
844 |
void |
845 |
BasicClientUserAgent::onRedirectReceived(AppDialogSetHandle h, const SipMessage& msg) |
846 |
{ |
847 |
BasicClientCall* call = dynamic_cast<BasicClientCall *>(h.get()); |
848 |
if(call) |
849 |
{ |
850 |
call->onRedirectReceived(h, msg); |
851 |
} |
852 |
else |
853 |
{ |
854 |
InfoLog(<< "onRedirectReceived(AppDialogSetHandle): " << msg.brief()); |
855 |
} |
856 |
} |
857 |
|
858 |
bool |
859 |
BasicClientUserAgent::onTryingNextTarget(AppDialogSetHandle, const SipMessage& msg) |
860 |
{ |
861 |
InfoLog(<< "onTryingNextTarget(AppDialogSetHandle): " << msg.brief()); |
862 |
|
863 |
// Always allow redirection for now |
864 |
return true; |
865 |
} |
866 |
|
867 |
|
868 |
|
869 |
|
870 |
/* ==================================================================== |
871 |
|
872 |
Copyright (c) 2011, SIP Spectrum, Inc. |
873 |
All rights reserved. |
874 |
|
875 |
Redistribution and use in source and binary forms, with or without |
876 |
modification, are permitted provided that the following conditions are |
877 |
met: |
878 |
|
879 |
1. Redistributions of source code must retain the above copyright |
880 |
notice, this list of conditions and the following disclaimer. |
881 |
|
882 |
2. Redistributions in binary form must reproduce the above copyright |
883 |
notice, this list of conditions and the following disclaimer in the |
884 |
documentation and/or other materials provided with the distribution. |
885 |
|
886 |
3. Neither the name of SIP Spectrum nor the names of its contributors |
887 |
may be used to endorse or promote products derived from this |
888 |
software without specific prior written permission. |
889 |
|
890 |
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
891 |
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
892 |
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
893 |
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
894 |
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
895 |
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
896 |
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
897 |
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
898 |
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
899 |
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
900 |
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
901 |
|
902 |
==================================================================== */ |
903 |
|