reSIProcate
SIP stack, Dialog Usage Manager and related libraries
Loading...
Searching...
No Matches
TuIM.cxx
Go to the documentation of this file.
1#if defined(HAVE_CONFIG_H)
2#include "config.h"
3#endif
4
5/* TODO list for this file ....
6 handle 302 in message
7 handle 302 in subscribe
8
9 sort out how contact is formed
10 keep track of ourstanding message dialogs
11 add a publish sending dialogs
12 send options to register, see if do publish, if so use
13
14 suppport loading destination certificates from server
15*/
16
17#include "rutil/ResipAssert.h"
18#include <memory>
19
23#include "resip/stack/TuIM.hxx"
35#include "rutil/Data.hxx"
36#include "rutil/Logger.hxx"
37#include "rutil/Random.hxx"
38#include "rutil/Socket.hxx"
40
41#ifdef USE_SSL
43#endif
44
45#define RESIPROCATE_SUBSYSTEM Subsystem::SIP
46
47using namespace resip;
48using namespace std;
49
50static int IMMethodList[] = { (int) REGISTER,
51 (int) MESSAGE,
52 (int) SUBSCRIBE,
53 (int) NOTIFY };
54const int IMMethodListSize = sizeof(IMMethodList) / sizeof(*IMMethodList);
55
56
60
61
63 const Uri& aor,
64 const Uri& contact,
66 const int registrationTimeSeconds,
67 const int subscriptionTimeSeconds)
68 : mCallback(callback),
69 mStack(stack),
70 mAor(aor),
71 mContact(contact),
72 mPidf( new GenericPidfContents ),
73 mRegistrationDialog(NameAddr(contact)),
74 mNextTimeToRegister(0),
75 mRegistrationPassword( Data::Empty ),
76 mLastAuthCSeq(0),
77 mRegistrationTimeSeconds(registrationTimeSeconds),
78 mSubscriptionTimeSeconds(subscriptionTimeSeconds),
79 mDefaultProtocol( UNKNOWN_TRANSPORT )
80{
81 resip_assert( mStack );
82 resip_assert(mCallback);
83 resip_assert(mPidf);
84
85 mPidf->setEntity(mAor);
87}
88
89
90bool
91TuIM::haveCerts( bool sign, const Data& encryptFor )
92{
93/* assert(0); */
94
95#if defined( USE_SSL )
96 Security* sec = mStack->getSecurity();
97 resip_assert(sec);
98
99 if ( sign )
100 {
101 if ( !sec->hasUserPrivateKey(mAor.getAor()) )
102 {
103 return false;
104 }
105 }
106 if ( !encryptFor.empty() )
107 {
108 if ( !sec->hasUserCert( encryptFor ) )
109 {
110 return false;
111 }
112 }
113#else
114 if ( (!encryptFor.empty()) || (sign) )
115 {
116 return false;
117 }
118#endif
119 return true;
120}
121
122
123void
124TuIM::sendPage(const Data& text, const Uri& dest,
125 const bool sign, const Data& encryptFor)
126{
127 if ( text.empty() )
128 {
129 DebugLog( << "tried to send blank message - dropped " );
130 return;
131 }
132 DebugLog( << "send to <" << dest << ">" << "\n" << text );
133
134 NameAddr target;
135 target.uri() = dest;
136
137 NameAddr from;
138 from.uri() = mAor;
139
140 NameAddr contact;
141 contact.uri() = mContact;
142
143 DeprecatedDialog* dialog = new DeprecatedDialog( NameAddr(mContact) );
144
145 unique_ptr<SipMessage> msg( dialog->makeInitialMessage(NameAddr(target),NameAddr(from)) );
146
147 Page page;
148 page.text = text;
149 page.uri = dest;
150 page.sign = sign;
151 page.encryptFor = encryptFor;
152 page.dialog = dialog;
153
154 mPages.push_back(page);
155
156 Contents* body = ( new PlainContents(text) );
157#if 1
158 msg->header(h_ContentTransferEncoding) = StringCategory(Data("binary"));
159#endif
160
161#if defined( USE_SSL )
162 if ( !encryptFor.empty() )
163 {
164 Security* sec = mStack->getSecurity();
165 resip_assert(sec);
166
167 Contents* old = body;
168 old->header(h_ContentTransferEncoding) = msg->header(h_ContentTransferEncoding);
169 body = sec->encrypt( old, encryptFor );
170 delete old;
171
172 if ( !body )
173 {
174 mCallback->sendPageFailed( dest, -2 );
175 return;
176 }
177
178#if 0
179 msg->header(h_ContentTransferEncoding) = StringCategory(Data("binary"));
180#endif
181 }
182
183 if ( sign )
184 {
185 Security* sec = mStack->getSecurity();
186 resip_assert(sec);
187
188 Contents* old = body;
189 old->header(h_ContentTransferEncoding) = msg->header(h_ContentTransferEncoding);
190 body = sec->sign( mAor.getAor(), old );
191 delete old;
192
193 if ( !body )
194 {
195 mCallback->sendPageFailed( dest, -1 );
196 return;
197 }
198
199#if 0
200 msg->header(h_ContentTransferEncoding) = StringCategory(Data("binary"));
201#endif
202 }
203#endif
204
205 msg->setContents(body);
206
207 if (1) // Compute the identity header.
208 {
209 //Security* sec = mStack->getSecurity();
210 //assert(sec);
211
212 DateCategory now;
213 msg->header(h_Date) = now;
214
215 //Data token = msg->getCanonicalIdentityString();
216 //Data res = sec->computeIdentity( token );
217
218 // TODO !SLG! RFC4474 has been deprecated by RFC8224 (Authenticated Identity Management). We should remove/adjust this code.
219 msg->header(h_Identities).push_back(IdentityCategory(Data::Empty));
220 }
221
222 setOutbound( *msg );
223 //ErrLog( "About to send " << *msg );
224
225 mStack->send( *msg );
226
227 delete body;
228}
229
230
231void
232TuIM::processRequest(SipMessage* msg)
233{
234 if ( msg->header(h_RequestLine).getMethod() == MESSAGE )
235 {
236 processMessageRequest(msg);
237 return;
238 }
239 if ( msg->header(h_RequestLine).getMethod() == SUBSCRIBE )
240 {
241 processSubscribeRequest(msg);
242 return;
243 }
244 if ( msg->header(h_RequestLine).getMethod() == REGISTER )
245 {
246 processRegisterRequest(msg);
247 return;
248 }
249 if ( msg->header(h_RequestLine).getMethod() == NOTIFY )
250 {
251 processNotifyRequest(msg);
252 return;
253 }
254
255 InfoLog(<< "Don't support this METHOD, send 405" );
256
258 mStack->send(*resp);
259 delete resp;
260}
261
262
263void
264TuIM::processSipFrag(SipMessage* msg)
265{
266 Contents* contents = msg->getContents();
267 if ( !contents )
268 {
269 InfoLog(<< "Received message with no contents" );
270 return;
271 }
272
273 InfoLog(<< "Received message with body contents" );
274
275 resip_assert( contents );
276 Mime mime = contents->getType();
277 DebugLog ( << "got body of type " << mime.type() << "/" << mime.subType() );
278
279 Data signedBy;
280
281#if defined( USE_SSL )
283 MultipartSignedContents* mBody = dynamic_cast<MultipartSignedContents*>(contents);
284 if ( mBody )
285 {
286 Security* sec = mStack->getSecurity();
287 resip_assert(sec);
288
289 contents = sec->checkSignature( mBody, &signedBy, &sigStat );
290
291 if ( !contents )
292 {
293 InfoLog( << "Some problem decoding multipart/signed message");
294 return;
295 }
296
297 InfoLog( << "Signed by " << signedBy << " stat = " << sigStat );
298 }
299#endif
300
301 if ( contents )
302 {
303 MultipartMixedContents* mixed = dynamic_cast<MultipartMixedContents*>(contents);
304 if ( mixed )
305 {
306 InfoLog( << "Got a multipart mixed" );
307
308 contents = NULL;
309
310 MultipartMixedContents::Parts& parts = mixed->parts();
311 for( MultipartMixedContents::Parts::const_iterator i = parts.begin();
312 i != parts.end();
313 ++i)
314 {
315 Contents* c = *i;
316 resip_assert( c );
317 InfoLog ( << "mixed has a " << c->getType() );
318
319 if ( c->getType() == Mime("application","sipfrag") )
320 {
321 InfoLog ( << "mixed has sipfrag " << c->getType() );
322
323 SipFrag* frag = dynamic_cast<SipFrag*>(c);
324 if ( frag )
325 {
326 InfoLog( << "Got a sipFrag inside mixed" );
327
328 SipMessage& m = frag->message();
329
330 InfoLog( <<"Frag is " << m );
331 }
332 }
333 }
334 }
335 }
336
337 if ( contents )
338 {
339 SipFrag* frag = dynamic_cast<SipFrag*>(contents);
340 if ( frag )
341 {
342 InfoLog( << "Got a sipFrag" );
343
344 SipMessage& m = frag->message();
345
346 InfoLog( <<"Frag is " << m );
347 }
348 else
349 {
350 InfoLog ( << "Can not handle type " << contents->getType() );
351
352 return;
353 }
354 }
355}
356
357
358void
359TuIM::processSubscribeRequest(SipMessage* msg)
360{
361 resip_assert( msg->header(h_RequestLine).getMethod() == SUBSCRIBE );
362 CallId id = msg->header(h_CallId);
363
364 processSipFrag( msg );
365
366 int expires=mSubscriptionTimeSeconds;
367 if ( msg->exists(h_Expires) )
368 {
369 expires = msg->header(h_Expires).value();
370 }
371 if (expires > mSubscriptionTimeSeconds )
372 {
373 expires = mSubscriptionTimeSeconds;
374 }
375
376 DeprecatedDialog* dialog = NULL;
377
378 // see if we already have this subscription
379 for ( SubscriberIterator i=mSubscribers.begin(); i != mSubscribers.end(); i++)
380 {
381 DeprecatedDialog* d = i->dialog;
382 resip_assert( d );
383
384 if ( d->getCallId() == id )
385 {
386 // found the subscrition in list of current subscrbtions
387 dialog = d;
388 break;
389 }
390 }
391
392 if ( !dialog )
393 {
394 // create a new subscriber
395 DebugLog ( << "Creating new subscrition dialog ");
396
397 Subscriber s;
398
399 s.dialog = new DeprecatedDialog( NameAddr(mContact) );
400 dialog = s.dialog;
401
402 Uri from = msg->header(h_From).uri();
403 s.aor = from.getAorNoPort();
404
405 resip_assert( mCallback );
406 s.authorized = mCallback->authorizeSubscription( from );
407
408 mSubscribers.push_back( s );
409 }
410
411 resip_assert( dialog );
412 dialog->setExpirySeconds( expires );
413
414 unique_ptr<SipMessage> response( dialog->makeResponse( *msg, 200 ));
415
416 response->header(h_Expires).value() = expires;
417 response->header(h_Event).value() = Data("presence");
418
419 mStack->send( *response );
420
421 sendNotify( dialog );
422
423#if 1
424 // do symetric subscriptions
425 // See if this person is our buddy list and if we are not subscribed to them
426
428 Uri from = msg->header(h_From).uri();
429
430 for ( BuddyIterator i=mBuddies.begin(); i != mBuddies.end(); i++)
431 {
432 Data buddyAor = i->uri.getAor();
433
434 if ( ! (i->presDialog->isCreated()) )
435 {
436 if ( from.getAor() == i->uri.getAor() )
437 {
438 if ( from.getAor() != mAor.getAor() )
439 {
440 i->mNextTimeToSubscribe = now;
441 }
442 }
443 }
444 }
445#endif
446}
447
448
449void
450TuIM::processRegisterRequest(SipMessage* msg)
451{
452 resip_assert( msg->header(h_RequestLine).getMethod() == REGISTER );
453 CallId id = msg->header(h_CallId);
454
455 int expires = msg->header(h_Expires).value();
456 if ( expires == 0 )
457 {
458 expires = 3600;
459 }
460
461 SipMessage* response = Helper::makeResponse( *msg, 200 );
462
463 // the Contacts from the default Helper are wrong for a Registration
464 response->remove(h_Contacts);
465
466 if ( msg->exists(h_Contacts) )
467 {
468 ParserContainer<NameAddr> &providedContacts(msg->header(h_Contacts));
469
470 int multipleContacts = (int)providedContacts.size();
471
472 DebugLog ( << multipleContacts << " contacts were in received message." );
473
474 ParserContainer<NameAddr>::iterator i(providedContacts.begin());
475 for ( ; i != providedContacts.end() ; ++ i) {
476 if ( i->isAllContacts() && multipleContacts ) // oops, multiple Contacts and one is "*"
477 {
478 delete response; // do I need to do this?
479 response = Helper::makeResponse( *msg, 400 );
480 mStack->send( *response );
481 delete response;
482 return;
483 }
484 if ( !i->exists(p_expires) ) // add expires params where they don't exist
485 {
486 i->param(p_expires) = expires;
487 }
488 response->header(h_Contacts).push_back(*i); // copy each Contact into response
489 }
490 }
491 // else the REGISTER is a query, just send the message with no Contacts
492
493 mStack->send( *response );
494
495 delete response;
496}
497
498
499void
500TuIM::processNotifyRequest(SipMessage* msg)
501{
502 resip_assert( mCallback );
503 resip_assert( msg->header(h_RequestLine).getMethod() == NOTIFY );
504
505 processSipFrag( msg );
506
507 unique_ptr<SipMessage> response( Helper::makeResponse( *msg, 200 ));
508 mStack->send( *response );
509
510 Uri from = msg->header(h_From).uri();
511 DebugLog ( << "got notify from " << from );
512
513 Contents* contents = msg->getContents();
514 if ( !contents )
515 {
516 InfoLog(<< "Received NOTIFY message event with no contents" );
517 mCallback->presenceUpdate( from, true, Data::Empty );
518 return;
519 }
520
521 Mime mime = contents->getType();
522 DebugLog ( << "got NOTIFY event with body of type " << mime.type() << "/" << mime.subType() );
523
524 GenericPidfContents* body = dynamic_cast<GenericPidfContents*>(contents);
525 if ( !body )
526 {
527 InfoLog(<< "Received NOTIFY message event with no PIDF contents" );
528 mCallback->presenceUpdate( from, true, Data::Empty );
529 return;
530 }
531
532 bool open = body->getSimplePresenceOnline();
533 Data note = body->getSimplePresenceNote();
534
535 bool changed = true;
536
537
538 // update if found in budy list
539 for ( BuddyIterator i=mBuddies.begin(); i != mBuddies.end(); i++)
540 {
541 Uri u = i->uri; // getBuddyUri(i);
542
543 if ( u.getAor() == from.getAor() )
544 {
545
546 if ( (i->status == note) &&
547 (i->online == open) )
548 {
549 changed = false;
550 }
551
552 i->status = note;
553 i->online = open;
554 }
555 }
556
557 InfoLog(<< "Processed NOTIFY message : Presence changed: " << changed );
558 // notify callback
559 if (changed)
560 {
561 resip_assert(mCallback);
562 mCallback->presenceUpdate( from, open, note );
563 }
564}
565
566
567void
568TuIM::processMessageRequest(SipMessage* msg)
569{
570 resip_assert( msg );
571 resip_assert( msg->header(h_RequestLine).getMethod() == MESSAGE );
572
573 NameAddr contact;
574 contact.uri() = mContact;
575
576 SipMessage* response = Helper::makeResponse(*msg, 200, contact, "OK");
577 mStack->send( *response );
578 delete response; response=0;
579
580 Contents* contents = msg->getContents();
581 if ( !contents )
582 {
583 InfoLog(<< "Received Message message with no contents" );
584 // .kw. NO: delete msg; msg=0; // our caller owns msg
585 return;
586 }
587
588 Mime mime = contents->getType();
589 DebugLog ( << "got body of type " << mime.type() << "/" << mime.subType() );
590
591 Data signedBy;
593 bool encrypted=false;
594
595#if defined( USE_SSL )
596 Uri from = msg->header(h_From).uri();
597 signedBy = from.getAorNoPort();
598
599 InfoLog ( << "assuming signedBy is " << signedBy );
600
601 MultipartSignedContents* mBody = dynamic_cast<MultipartSignedContents*>(contents);
602 if ( mBody )
603 {
604 Security* sec = mStack->getSecurity();
605 resip_assert(sec);
606
607 contents = sec->checkSignature( mBody, &signedBy, &sigStat );
608
609 //ErrLog("Signed by " << signedBy << " stat = " << sigStat );
610
611 if ( !contents )
612 {
613 Uri from = msg->header(h_From).uri();
614 InfoLog( << "Some problem decoding multipart/signed message");
615
616 mCallback->receivePageFailed( from );
617 return;
618 }
619 }
620
621 Pkcs7SignedContents* sBody = dynamic_cast<Pkcs7SignedContents*>(contents);
622 if ( sBody )
623 {
624 resip_assert( sBody );
625 Security* sec = mStack->getSecurity();
626 resip_assert(sec);
627
628 contents = sec->decrypt( mAor.getAor(), sBody );
629
630 if ( !contents )
631 {
632 Uri from = msg->header(h_From).uri();
633 InfoLog( << "Some problem decoding signed SMIME message");
634
635 mCallback->receivePageFailed( from );
636 return;
637 }
638
639 encrypted=true;
640 }
641
642 Pkcs7Contents* eBody = dynamic_cast<Pkcs7Contents*>(contents);
643 if ( eBody )
644 {
645 resip_assert( eBody );
646 Security* sec = mStack->getSecurity();
647 resip_assert(sec);
648
649 contents = sec->decrypt( mAor.getAor(), eBody );
650
651 if ( !contents )
652 {
653 Uri from = msg->header(h_From).uri();
654 InfoLog( << "Some problem decoding SMIME message");
655
656 mCallback->receivePageFailed( from );
657 return;
658 }
659
660 encrypted=true;
661 }
662
663#endif
664
665 if ( contents )
666 {
667 PlainContents* plain = dynamic_cast<PlainContents*>(contents);
668 if ( plain )
669 {
670 resip_assert( plain );
671 const Data& text = plain->text();
672 DebugLog ( << "got message from with text of <" << text << ">" );
673
674 Uri from = msg->header(h_From).uri();
675 DebugLog ( << "got message from " << from );
676
677 resip_assert( mCallback );
678 mCallback->receivedPage( text, from, signedBy, sigStat, encrypted );
679 return;
680 }
681
682 CpimContents* cpim = dynamic_cast<CpimContents*>(contents);
683 if ( cpim )
684 {
685 resip_assert( cpim );
686 const Data& text = cpim->text();
687 DebugLog ( << "got CPIM message from with text of <" << text << ">" );
688
689 // !cj! TODO - should get from out of CPIM message
690 Uri from = msg->header(h_From).uri();
691 DebugLog ( << "got message from " << from );
692
693 resip_assert( mCallback );
694 mCallback->receivedPage( text, from, signedBy, sigStat, encrypted );
695 return;
696 }
697
698 MultipartMixedContents* mixed = dynamic_cast<MultipartMixedContents*>(contents);
699 if ( mixed )
700 {
701 InfoLog( << "Got a multipart mixed" );
702
703 contents = NULL;
704
705 MultipartMixedContents::Parts& parts = mixed->parts();
706 for( MultipartMixedContents::Parts::const_iterator i = parts.begin();
707 i != parts.end();
708 ++i)
709 {
710 Contents* c = *i;
711 resip_assert( c );
712 InfoLog ( << "mixed has a " << c->getType() );
713
714 if ( c->getType() == Mime("text","plain") )
715 {
716 InfoLog ( << "mixed has sipfrag " << c->getType() );
717
718 PlainContents* plainBody = dynamic_cast<PlainContents*>(c);
719 if ( plainBody )
720 {
721 resip_assert( plainBody );
722 const Data& text = plainBody->text();
723 DebugLog ( << "got message from with text of <" << text << ">" );
724
725 Uri from = msg->header(h_From).uri();
726 DebugLog ( << "got message from " << from );
727
728 resip_assert( mCallback );
729 mCallback->receivedPage( text, from, signedBy, sigStat, encrypted );
730 return;
731 }
732
733 // !cj! TODO - should deal with CPIM too
734 }
735
736 }
737
738 return;
739 }
740
741#if 1 // !cj! TODO remove
742 OctetContents* octets = dynamic_cast<OctetContents*>(contents);
743 if (octets)
744 {
745 resip_assert( contents );
746 const Data& text = octets->getBodyData();
747 DebugLog ( << "got message from with text of <" << text << ">" );
748
749 Uri from = msg->header(h_From).uri();
750 DebugLog ( << "got message from " << from );
751
752 resip_assert( mCallback );
753 mCallback->receivedPage( text, from, signedBy, sigStat, encrypted );
754 return;
755 }
756#endif
757
758 // deal with it if no one else has
759 {
760 InfoLog ( << "Can not handle type " << contents->getType() );
761 Uri from = msg->header(h_From).uri();
762 mCallback->receivePageFailed( from );
763 return;
764 }
765 }
766}
767
768
769void
770TuIM::processResponse(SipMessage* msg)
771{
773 CallId id = msg->header(h_CallId);
774 resip_assert( id.value() != Data::Empty );
775
776 processSipFrag( msg );
777
778 // see if it is a registraition response
779 CallId regId = mRegistrationDialog.getCallId();
780
781 Data v1 = id.value();
782 Data v2 = regId.value();
783
784 InfoLog( << "want id =" << id );
785
786 if ( id == regId )
787 {
788 InfoLog ( << "matched the reg dialog"
789 << mRegistrationDialog.getCallId() << " = " << id );
790 processRegisterResponse( msg );
791 return;
792 }
793
794 // see if it is a subscribe response
795 for ( BuddyIterator i=mBuddies.begin(); i != mBuddies.end(); i++)
796 {
797 Buddy& buddy = *i;
798 resip_assert( buddy.presDialog );
799 InfoLog( << "check buddy id =" << buddy.presDialog->getCallId() );
800 if ( buddy.presDialog->getCallId() == id )
801 {
802 DebugLog ( << "matched the subscribe dialog" );
803 processSubscribeResponse( msg, buddy );
804 return;
805 }
806 }
807
808 // see if it is a publish response
809 for ( StateAgentIterator i=mStateAgents.begin(); i != mStateAgents.end(); i++)
810 {
811 resip_assert( i->dialog );
812 InfoLog( << "check publish id =" << i->dialog->getCallId() );
813 if ( i->dialog->getCallId() == id )
814 {
815 DebugLog ( << "matched the publish dialog" );
816 processPublishResponse( msg, *i );
817 return;
818 }
819 }
820
821 // see if it is a notify response
822 for ( SubscriberIterator i=mSubscribers.begin(); i != mSubscribers.end(); i++)
823 {
824 DeprecatedDialog* dialog = i->dialog;
825 resip_assert( dialog );
826 InfoLog( << "check subscriber id =" << dialog->getCallId() );
827 if ( dialog->getCallId() == id )
828 {
829 DebugLog ( << "matched the notify dialog" );
830 processNotifyResponse( msg, *dialog );
831 return;
832 }
833 }
834
835 // see if it is a page response
836 for ( PageIterator i=mPages.begin(); i != mPages.end(); i++)
837 {
838 resip_assert( i->dialog );
839 InfoLog( << "check page id =" << i->dialog->getCallId() );
840 if ( i->dialog->getCallId() == id )
841 {
842 DebugLog ( << "matched the MESSAGE dialog" );
843 processPageResponse( msg, *i );
844 return;
845 }
846 }
847
848 int number = msg->header(h_StatusLine).responseCode();
849 InfoLog( << "got response that DID NOT MATCH of type " << number );
850}
851
852
853void
854TuIM::processRegisterResponse(SipMessage* msg)
855{
856 int number = msg->header(h_StatusLine).responseCode();
857 Uri to = msg->header(h_To).uri();
858 InfoLog ( << "register of " << to << " got response " << number );
859 unsigned int cSeq = msg->header(h_CSeq).sequence();
860
861 if ( number<200 )
862 {
863 return;
864 }
865
866 if ( number >= 200 )
867 {
868 mRegistrationDialog.createDialogAsUAC( *msg );
869 }
870
871 if ( ((number == 401) || (number == 407)) && (cSeq != mLastAuthCSeq) )
872 {
873 SipMessage* reg = mRegistrationDialog.makeRegister();
874
875 const Data cnonce = Data::Empty;
876 unsigned int nonceCount=0;
877
878 Helper::addAuthorization(*reg,*msg,mAor.user(),mRegistrationPassword,cnonce,nonceCount);
879
880 mLastAuthCSeq = reg->header(h_CSeq).sequence();
881
882 reg->header(h_Expires).value() = mRegistrationTimeSeconds;
883 reg->header(h_Contacts).front().param(p_expires) = mRegistrationTimeSeconds;
884
885 mNextTimeToRegister = Timer::getRandomFutureTimeMs( mRegistrationTimeSeconds*1000 );
886
887 InfoLog( << *reg );
888
889 setOutbound( *reg );
890
891 mStack->send( *reg );
892
893 delete reg; reg=NULL;
894
895 return;
896 }
897
898 if ( number >= 300 )
899 {
900 resip_assert( mCallback );
901 mCallback->registrationFailed( to, number );
902 return;
903 }
904
905 if ( (number>=200) && (number<300) )
906 {
907 int expires = mRegistrationTimeSeconds;
908
909 if ( msg->exists(h_Expires) )
910 {
911 expires = msg->header(h_Expires).value();
912 }
913
914 // loop throught the contacts, find me, and extract expire time
916 while ( i != msg->header(h_Contacts).end() )
917 {
918 try
919 {
920 Uri uri = i->uri();
921
922 if ( uri.getAor() == mContact.getAor() )
923 {
924 int e = i->param(p_expires);
925 DebugLog(<< "match " << uri.getAor() << " e=" << e );
926
927 expires = e;
928 }
929 }
930 catch ( exception* )
931 {
932 InfoLog(<< "Bad contact in 2xx to register - skipped" );
933 }
934
935 i++;
936 }
937
938 if ( expires < 15 )
939 {
940 InfoLog(<< "Got very small expiers of " << expires );
941 expires = 15;
942 }
943
944 mNextTimeToRegister = Timer::getRandomFutureTimeMs( expires*1000 );
945
946 mCallback->registrationWorked( to );
947
948 return;
949 }
950}
951
952
953void
954TuIM::processNotifyResponse(SipMessage* msg, DeprecatedDialog& d )
955{
956 int number = msg->header(h_StatusLine).responseCode();
957 DebugLog( << "got NOTIFY response of type " << number );
958
959 if ( number >= 300 )
960 {
961 // TODO
962 }
963}
964
965
966void
967TuIM::processPublishResponse(SipMessage* msg, StateAgent& sa )
968{
969 int number = msg->header(h_StatusLine).responseCode();
970 DebugLog( << "got PUBLISH response of type " << number );
971
972 if ( number >= 300 )
973 {
974 // TODO
975 }
976}
977
978
979void
980TuIM::processPageResponse(SipMessage* msg, Page& page )
981{
982 int number = msg->header(h_StatusLine).responseCode();
983 DebugLog( << "got MESSAGE response of type " << number );
984
985 if ( number >= 400 )
986 {
987 Uri dest = msg->header(h_To).uri();
988 resip_assert( mCallback );
989 mCallback->sendPageFailed( dest,number );
990 }
991
992 if ( (number>=300) && (number<400) )
993 {
994 ParserContainer<NameAddr>::iterator dest = msg->header(h_Contacts).begin();
995 while ( dest != msg->header(h_Contacts).end() )
996 {
997 DebugLog(<< "Got a 3xx to" << *dest );
998
999 // send a message to redirected location
1000 Uri uri = dest->uri();
1001 sendPage( page.text, uri, page.sign, page.encryptFor );
1002
1003 dest++;
1004 }
1005 }
1006
1007 if ( (number>=200) && (number<300) )
1008 {
1009 // got a final response for notify - can remove this dialog information
1010 CallId id = msg->header(h_CallId);
1011
1012 for( PageIterator i=mPages.begin(); i != mPages.end(); i++ )
1013 {
1014 if ( i->dialog->getCallId() == id )
1015 {
1016 i = mPages.erase( i );
1017 }
1018 }
1019 }
1020}
1021
1022
1023void
1024TuIM::processSubscribeResponse(SipMessage* msg, Buddy& buddy)
1025{
1026 int number = msg->header(h_StatusLine).responseCode();
1027 Uri to = msg->header(h_To).uri();
1028 InfoLog ( << "subscribe got response " << number << " from " << to );
1029
1030 if ( (number>=200) && (number<300) )
1031 {
1032 int expires = mSubscriptionTimeSeconds;
1033 if ( msg->exists(h_Expires) )
1034 {
1035 expires = msg->header(h_Expires).value();
1036 }
1037 if ( expires < 15 )
1038 {
1039 InfoLog( << "Got very small expiers of " << expires );
1040 expires = 15;
1041 }
1042
1043 resip_assert( buddy.presDialog );
1044 buddy.presDialog->createDialogAsUAC( *msg );
1045
1046 buddy.mNextTimeToSubscribe = Timer::getRandomFutureTimeMs( expires*1000 );
1047 }
1048
1049 if ( (number>=300) && (number<400) )
1050 {
1051 ParserContainer<NameAddr>::iterator dest = msg->header(h_Contacts).begin();
1052 while ( dest != msg->header(h_Contacts).end() )
1053 {
1054 DebugLog(<< "Got a 3xx to" << *dest );
1055 Uri uri = dest->uri();
1056
1057 addBuddy( uri , buddy.group );
1058
1059 buddy.mNextTimeToSubscribe = Timer::getForever();
1060
1061 dest++;
1062 }
1063 }
1064
1065 if ( (number>=400) )
1066 {
1067 DebugLog( << "Got an error to some subscription" );
1068
1069 // take this buddy off line
1070 Uri to = msg->header(h_To).uri();
1071 resip_assert( mCallback );
1072
1073 bool changed = true;
1074
1075 for ( BuddyIterator i=mBuddies.begin(); i != mBuddies.end(); i++)
1076 {
1077 Uri u = i->uri; // getBuddyUri(i);
1078
1079 if ( u.getAor() == to.getAor() )
1080 {
1081 if ( i->online == false )
1082 {
1083 changed = false;
1084 }
1085
1086 i->online = false;
1087 }
1088 }
1089
1090 if ( changed )
1091 {
1092 mCallback->presenceUpdate( to, false, Data::Empty );
1093 }
1094
1095 // try to contact this buddy again later
1096 buddy.mNextTimeToSubscribe = Timer::getRandomFutureTimeMs( mSubscriptionTimeSeconds*1000 );
1097 }
1098}
1099
1100
1101void
1103{
1104 resip_assert( mStack );
1105
1106 uint64_t now = Timer::getTimeMs();
1107
1108 // check if register needs refresh
1109 if ( now > mNextTimeToRegister )
1110 {
1111 if ( mRegistrationDialog.isCreated() )
1112 {
1113 unique_ptr<SipMessage> msg( mRegistrationDialog.makeRegister() );
1114 msg->header(h_Expires).value() = mRegistrationTimeSeconds;
1115 setOutbound( *msg );
1116 mStack->send( *msg );
1117 }
1118 mNextTimeToRegister = Timer::getRandomFutureTimeMs( mRegistrationTimeSeconds*1000 );
1119 }
1120
1121 // check if any subscribes need refresh
1122 for ( BuddyIterator i=mBuddies.begin(); i != mBuddies.end(); i++)
1123 {
1124 if ( now > i->mNextTimeToSubscribe )
1125 {
1126 Buddy& buddy = *i;
1127
1128 buddy.mNextTimeToSubscribe
1129 = Timer::getRandomFutureTimeMs( mSubscriptionTimeSeconds*1000 );
1130
1131 resip_assert( buddy.presDialog );
1132 if ( buddy.presDialog->isCreated() )
1133 {
1134 unique_ptr<SipMessage> msg( buddy.presDialog->makeSubscribe() );
1135
1136 msg->header(h_Event).value() = Data("presence");;
1137 msg->header(h_Accepts).push_back( Mime( "application","pidf+xml") );
1138 msg->header(h_Expires).value() = mSubscriptionTimeSeconds;
1139
1140 setOutbound( *msg );
1141
1142 mStack->send( *msg );
1143 }
1144 else
1145 {
1146 // person was not available last time - try to subscribe now
1147 subscribeBuddy( buddy );
1148 }
1149 }
1150 }
1151
1152 // TODO - go and clean out any subscrption to us that have expired
1153
1154 // check for any messages from the sip stack
1155 SipMessage* msg( mStack->receive() );
1156 if ( msg )
1157 {
1158 DebugLog ( << "got message: " << *msg);
1159
1160 if ( msg->isResponse() )
1161 {
1162 processResponse( msg );
1163 }
1164
1165 if ( msg->isRequest() )
1166 {
1167 processRequest( msg );
1168 }
1169
1170 delete msg; msg=0;
1171 }
1172}
1173
1174
1175void
1176TuIM::registerAor( const Uri& uri, const Data& password )
1177{
1178 mRegistrationPassword = password;
1179
1180 //const NameAddr aorName;
1181 //const NameAddr contactName;
1182 //aorName.uri() = uri;
1183 //contactName.uri() = mContact;
1184 //SipMessage* msg = Helper::makeRegister(aorName,aorName,contactName);
1185
1186 unique_ptr<SipMessage> msg( mRegistrationDialog.makeInitialRegister(NameAddr(uri),NameAddr(uri)) );
1187
1188 msg->header(h_Expires).value() = mRegistrationTimeSeconds;
1189 msg->header(h_Contacts).front().param(p_expires) = mRegistrationTimeSeconds;
1190
1191 Token t;
1192 t = Token(Data("presence"));
1193 msg->header(h_AllowEvents).push_back( t );
1194
1195 mNextTimeToRegister = Timer::getRandomFutureTimeMs( mRegistrationTimeSeconds*1000 );
1196
1197 setOutbound( *msg );
1198
1199 mStack->send( *msg );
1200}
1201
1202
1203int
1205{
1206 return int(mBuddies.size());
1207}
1208
1209
1210const Uri
1211TuIM::getBuddyUri(const int index)
1212{
1213 resip_assert( index >= 0 );
1214 resip_assert( index < getNumBuddies() );
1215
1216 return mBuddies[index].uri;
1217}
1218
1219
1220const Data
1221TuIM::getBuddyGroup(const int index)
1222{
1223 resip_assert( index >= 0 );
1224 resip_assert( index < getNumBuddies() );
1225
1226 return mBuddies[index].group;
1227}
1228
1229
1230bool
1231TuIM::getBuddyStatus(const int index, Data* status)
1232{
1233 resip_assert( index >= 0 );
1234 resip_assert( index < getNumBuddies() );
1235
1236 if (status)
1237 {
1238 *status = mBuddies[index].status;
1239 }
1240
1241 bool online = mBuddies[index].online;
1242
1243 return online;
1244}
1245
1246
1247void
1248TuIM::subscribeBuddy( Buddy& buddy )
1249{
1250 // subscribe to this budy
1251 unique_ptr<SipMessage> msg( buddy.presDialog->makeInitialSubscribe(NameAddr(buddy.uri),NameAddr(mAor)) );
1252
1253 msg->header(h_Event).value() = Data("presence");;
1254 msg->header(h_Accepts).push_back( Mime( "application","pidf+xml") );
1255 msg->header(h_Expires).value() = mSubscriptionTimeSeconds;
1256
1257 buddy.mNextTimeToSubscribe = Timer::getRandomFutureTimeMs( mSubscriptionTimeSeconds*1000 );
1258
1259 setOutbound( *msg );
1260
1261 mStack->send( *msg );
1262}
1263
1264
1265void
1266TuIM::addBuddy( const Uri& uri, const Data& group )
1267{
1268 Buddy buddy;
1269 buddy.uri = uri;
1270 buddy.online = false;
1271 buddy.status = Data::Empty;
1272 buddy.group = group;
1273 buddy.presDialog = new DeprecatedDialog( NameAddr(mContact) );
1274 resip_assert( buddy.presDialog );
1275
1276 subscribeBuddy( buddy );
1277
1278 mBuddies.push_back( buddy );
1279}
1280
1281
1282void
1284{
1285 TuIM::BuddyIterator i;
1286
1287 i = mBuddies.begin();
1288 while ( i != mBuddies.end() )
1289 {
1290 Uri u = i->uri;
1291
1292 if ( u.getAor() == name.getAor() )
1293 {
1294 // remove this buddy
1295 // !cj! - should unsubscribe
1296 i = mBuddies.erase(i);
1297 }
1298 else
1299 {
1300 i++;
1301 }
1302 }
1303}
1304
1305
1306void
1307TuIM::sendNotify(DeprecatedDialog* dialog)
1308{
1309 resip_assert( dialog );
1310
1311 unique_ptr<SipMessage> msg( dialog->makeNotify() );
1312
1313 GenericPidfContents* pidf = new GenericPidfContents( *mPidf );
1314
1315 msg->header(h_Event).value() = "presence";
1316
1317 Token state;
1318 state.value() = Data("active");
1319 state.param(p_expires) = dialog->getExpirySeconds();
1320 msg->header(h_SubscriptionState) = state;
1321
1322 msg->setContents( pidf );
1323
1324 setOutbound( *msg );
1325
1326 mStack->send( *msg );
1327}
1328
1329
1330void
1331TuIM::sendPublish(StateAgent& sa)
1332{
1333 resip_assert( sa.dialog );
1334
1335 unique_ptr<SipMessage> msg( sa.dialog->makeInitialPublish(NameAddr(sa.uri),NameAddr(mAor)) );
1336
1337 GenericPidfContents* pidf = new GenericPidfContents( *mPidf );
1338
1339 msg->header(h_Event).value() = "presence";
1340
1341 msg->setContents( pidf );
1342
1343 setOutbound( *msg );
1344
1345 mStack->send( *msg );
1346}
1347
1348
1349void
1351{
1352 // TODO implement this
1353}
1354
1355
1356void
1357TuIM::setMyPresence( const bool open, const Data& status, const Data& user )
1358{
1359 // TODO implement the pser user status (when user is not empty)
1360 resip_assert( mPidf );
1361 mPidf->setSimplePresenceTupleNode(mPidf->getSimplePresenceTupleId(), open, Data::Empty, status, mContact.getAor());
1362
1363 for ( SubscriberIterator i=mSubscribers.begin(); i != mSubscribers.end(); i++)
1364 {
1365 DeprecatedDialog* dialog = i->dialog;
1366 resip_assert( dialog );
1367
1368 sendNotify(dialog);
1369 }
1370
1371 for ( StateAgentIterator i=mStateAgents.begin(); i != mStateAgents.end(); i++)
1372 {
1373 sendPublish( *i );
1374 }
1375}
1376
1377
1378void
1380{
1381 InfoLog( << "Set outbound proxy to " << uri );
1382 mOutboundProxy = uri;
1383}
1384
1385
1386void
1387TuIM::setUAName( const Data& name )
1388{
1389 DebugLog( << "Set User Agent Name to " << name );
1390 mUAName = name;
1391}
1392
1393
1394void
1395TuIM::setOutbound( SipMessage& msg )
1396{
1397 if ( msg.isResponse() )
1398 {
1399 return;
1400 }
1401
1402 if ( !mOutboundProxy.host().empty() )
1403 {
1404 NameAddr proxy( mOutboundProxy );
1405 msg.header(h_Routes).push_front( proxy );
1406 }
1407
1408 if ( !mUAName.empty() )
1409 {
1410 DebugLog( << "UserAgent name=" << mUAName );
1411 msg.header(h_UserAgent).value() = mUAName;
1412 }
1413
1414 if ( mDefaultProtocol != UNKNOWN_TRANSPORT )
1415 {
1416 if ( ! msg.header(h_RequestLine).uri().exists(p_transport) )
1417 {
1418 msg.header(h_RequestLine).uri().param(p_transport) = Tuple::toDataLower(mDefaultProtocol);
1419 }
1420 }
1421}
1422
1423
1424void
1426{
1427 mDefaultProtocol = protocol;
1428}
1429
1430
1431void
1433{
1434 StateAgent sa;
1435
1436 sa.dialog = new DeprecatedDialog( NameAddr(mContact) );
1437 sa.uri = uri;
1438
1439 mStateAgents.push_back( sa );
1440
1441 sendPublish( sa );
1442}
1443
1444
1445bool
1447{
1448 return true;
1449}
1450
1451
1452/* ====================================================================
1453 * The Vovida Software License, Version 1.0
1454 *
1455 * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved.
1456 *
1457 * Redistribution and use in source and binary forms, with or without
1458 * modification, are permitted provi
1459ded that the following conditions
1460 * are met:
1461 *
1462 * 1. Redistributions of source code must retain the above copyright
1463 * notice, this list of conditions and the following disclaimer.
1464 *
1465 * 2. Redistributions in binary form must reproduce the above copyright
1466 * notice, this list of conditions and the following disclaimer in
1467 * the documentation and/or other materials provided with the
1468 * distribution.
1469 *
1470 * 3. The names "VOCAL", "Vovida Open Communication Application Library",
1471 * and "Vovida Open Communication Application Library (VOCAL)" must
1472 * not be used to endorse or promote products derived from this
1473 * software without prior written permission. For written
1474 * permission, please contact vocal@vovida.org.
1475 *
1476 * 4. Products derived from this software may not be called "VOCAL", nor
1477 * may "VOCAL" appear in their name, without prior written
1478 * permission of Vovida Networks, Inc.
1479 *
1480 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
1481 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1482 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
1483 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA
1484 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
1485 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
1486 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
1487 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
1488 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
1489 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1490 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
1491 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
1492 * DAMAGE.
1493 *
1494 * ====================================================================
1495 *
1496 * This software consists of voluntary contributions made by Vovida
1497 * Networks, Inc. and many individuals on behalf of Vovida Networks,
1498 * Inc. For more information on Vovida Networks, Inc., please see
1499 * <http://www.vovida.org/>.
1500 *
1501 */
#define DebugLog(args_)
Definition Logger.hxx:128
#define InfoLog(args_)
Definition Logger.hxx:131
#define resip_assert(x)
This file needs to work for both C and C++ code.
Handles cross-platform sockets compatibility.
static int IMMethodList[]
Definition TuIM.cxx:50
const int IMMethodListSize
Definition TuIM.cxx:54
static void callback(void *arg, int status, unsigned char *abuf, int alen)
Definition adig.c:388
bool hasUserCert(const Data &aor) const
Contents * checkSignature(MultipartSignedContents *, Data *signedBy, SignatureStatus *sigStat)
Contents * decrypt(const Data &decryptorAor, const Pkcs7Contents *)
bool hasUserPrivateKey(const Data &aor) const
MultipartSignedContents * sign(const Data &senderAor, Contents *)
Pkcs7Contents * encrypt(Contents *, const Data &recipCertName)
Represents the "callid" element in the SIP grammar.
Definition CallId.hxx:18
Data & value()
Definition CallId.cxx:75
Base class for all SIP body types.
Definition Contents.hxx:51
virtual Data getBodyData() const
Definition Contents.cxx:661
const H_ContentType::Type & header(const H_ContentType &headerType) const
returns the value of the Content-Type header Throws an Contents::Exception if the header doesn't exis...
Definition Contents.cxx:280
const Mime & getType() const
getter for mime type of message
Definition Contents.hxx:118
SIP body type for holding CPIM (Common Profile for Instant Messaging) contents (MIME content-type mes...
Data & text()
Get the CPIM message text.
An alternative to std::string, encapsulates an arbitrary buffer of bytes.
Definition Data.hxx:90
static const Data Empty
Constant that represents a zero-length data.
Definition Data.hxx:882
bool empty() const noexcept
Checks whether the Data is empty.
Definition Data.hxx:591
Represents the "SIP-date" element in the RFC 3261 grammar.
const CallID & getCallId() const
SipMessage * makeInitialMessage(const NameAddr &target, const NameAddr &from)
SipMessage * makeInitialRegister(const NameAddr &registrar, const NameAddr &from)
void setExpirySeconds(int secondsInFuture)
SipMessage * makeResponse(const SipMessage &request, int code=200)
void createDialogAsUAC(const SipMessage &response)
SIP body type for holding PIDF contents (MIME content-type application/pidf+xml).
void setSimplePresenceTupleNode(const Data &id, bool online, const Data &timestamp=Data::Empty, const Data &note=Data::Empty, const Data &contact=Data::Empty, const Data &contactPriority=Data::Empty)
void setEntity(const Uri &entity)
static SipMessage & addAuthorization(SipMessage &request, const SipMessage &challenge, const Data &username, const Data &password, const Data &cnonce, unsigned int &nonceCount)
Definition Helper.cxx:1368
static SipMessage * make405(const SipMessage &request, const int *allowedMethods=0, int nMethods=-1)
Make a 405 response to a provided request.
Definition Helper.cxx:573
static void makeResponse(SipMessage &response, const SipMessage &request, int responseCode, const Data &reason=Data::Empty, const Data &hostname=Data::Empty, const Data &warning=Data::Empty)
Make a response to a provided request.
Definition Helper.cxx:412
Represents an Identity header from RFC8824.
Represents the "media-type" element in the RFC 3261 grammar.
Definition Mime.hxx:20
const Data & subType() const
Definition Mime.cxx:100
const Data & type() const
Definition Mime.cxx:94
SIP body type for holding Multipart-Mixed body contents (MIME content-type multipart/mixed).
SIP body type for holding Multipart-Signed body contents (MIME content-type multipart/signed).
Represents the "name-addr" and the "addr-spec" elements in the RFC 3261 grammar.
Definition NameAddr.hxx:19
SIP body type for holding Octet contents (MIME content-type application/octet-stream).
An iterator class (bidirectional)
Container class for ParserCategory, used by SipMessage to represent multi-valued headers (Contact,...
SIP body type for holding PKCS7 contents (MIME content-type application/pkcs7-mime).
SIP body type for holding PKCS7 Signed contents (MIME content-type application/pkcs7-signature).
SIP body type for holding plain contents (MIME content-type text/plain).
const Data & text() const
static Data getRandomHex(unsigned int numBytes)
Definition Random.cxx:382
MethodTypes getMethod() const
const Uri & uri() const
SIP body type for holding SipFrag contents (MIME content-type message/sipfrag).
Definition SipFrag.hxx:22
SipMessage & message()
Definition SipFrag.cxx:82
Represents a SIP message.
void setContents(const Contents *contents)
Set the contents of the message.
bool isRequest() const
Returns true if message is a request, false otherwise.
Contents * getContents() const
Retrieves the body of a SIP message.
const RequestLine & header(const RequestLineType &l) const
Returns the RequestLine. This is only valid for request messages.
bool isResponse() const
Returns true if message is a response, false otherwise.
bool exists(const HeaderBase &headerType) const
Returns true if the given header field is present, false otherwise.
void remove(const HeaderBase &headerType)
Prevents a header field from being present when the message is prepared for sending to a transport.
This is the primary point of interaction between the app-layer and the stack.
Definition SipStack.hxx:160
Security * getSecurity() const
Returns a pointer to the embedded Security object, 0 if not set.
void send(const SipMessage &msg, TransactionUser *tu=0)
allows a TU to send a message
Definition SipStack.cxx:867
SipMessage * receive()
retrieve a SipMessage off the old TuFifo
Represents the "header-value" element in the RFC 3261 grammar (ie, an unknown header field value).
static uint64_t getRandomFutureTimeMs(uint64_t futureMs)
Returns an absolute time in ms that is between 50% and 90% of passed in ms from now.
Definition Timer.hxx:85
static uint64_t getTimeMs()
Returns the current clock time in milliseconds.
Definition Timer.hxx:72
static uint64_t getForever()
Infinit time in future.
Definition Timer.hxx:91
Represents the "token" element in the RFC 3261 grammar.
Definition Token.hxx:18
const Data & value() const
Gets the value (ie; no parameters) of this Token as a Data&.
Definition Token.cxx:77
const Data & param(const ExtensionParameter &param) const
Const accessor for non-natively-supported parameter types.
virtual void registrationWorked(const Uri &dest)=0
virtual void registrationFailed(const Uri &dest, int respNumber)=0
virtual void sendPageFailed(const Uri &dest, int respNumber)=0
virtual bool authorizeSubscription(const Uri &user)
Definition TuIM.cxx:1446
virtual ~Callback()
Definition TuIM.cxx:57
virtual void presenceUpdate(const Uri &user, bool open, const Data &status)=0
virtual void receivePageFailed(const Uri &sender)=0
virtual void receivedPage(const Data &msg, const Uri &from, const Data &signedBy, SignatureStatus sigStatus, bool wasEncryped)=0
void process()
Definition TuIM.cxx:1102
bool getBuddyStatus(const int index, Data *status=NULL)
Definition TuIM.cxx:1231
const Uri getBuddyUri(const int index)
Definition TuIM.cxx:1211
void setDefaultProtocol(TransportType protocol)
Definition TuIM.cxx:1425
void authorizeSubscription(const Data &user)
Definition TuIM.cxx:1350
void registerAor(const Uri &uri, const Data &password=Data::Empty)
Definition TuIM.cxx:1176
const Data getBuddyGroup(const int index)
Definition TuIM.cxx:1221
void sendPage(const Data &text, const Uri &dest, const bool sign=false, const Data &encryptFor=Data::Empty)
Definition TuIM.cxx:124
void setOutboundProxy(const Uri &uri)
Definition TuIM.cxx:1379
void removeBuddy(const Uri &name)
Definition TuIM.cxx:1283
void setMyPresence(const bool open, const Data &status=Data::Empty, const Data &user=Data::Empty)
Definition TuIM.cxx:1357
TuIM(SipStack *stack, const Uri &aor, const Uri &contact, Callback *callback, const int registrationTimeSeconds=1 *60 *60, const int subscriptionTimeSeconds=10 *60)
Definition TuIM.cxx:62
void setUAName(const Data &name)
Definition TuIM.cxx:1387
void addBuddy(const Uri &uri, const Data &group)
Definition TuIM.cxx:1266
int getNumBuddies() const
Definition TuIM.cxx:1204
bool haveCerts(bool sign, const Data &encryptFor)
Definition TuIM.cxx:91
void addStateAgent(const Uri &uri)
Definition TuIM.cxx:1432
static const Data & toDataLower(TransportType type)
Definition Tuple.cxx:933
Represents the "SIP-URI" and "SIPS-URI" elements in the RFC 3261 grammar.
Definition Uri.hxx:22
Data getAor() const
Definition Uri.cxx:1095
Data getAorNoPort() const
Definition Uri.cxx:1087
bool exists(const Param< Uri > &paramType) const
Definition Uri.cxx:1701
Data & user()
Definition Uri.hxx:42
Data & host()
Definition Uri.hxx:40
const Data & param(const ExtensionParameter &param) const
Const accessor for non-natively-supported parameter types.
dcm! – add UnusedChecking(_enum) below;
StatusLineType h_StatusLine
Definition Headers.cxx:348
unsigned long long uint64_t
Definition Stun.hxx:39
TransportType
An enumeration of transport protocols.
@ UNKNOWN_TRANSPORT
H_Identitys h_Identities
Definition Headers.cxx:315
RequestLineType h_RequestLine
Definition Headers.cxx:347
H_AllowEventss h_AllowEvents
Definition Headers.cxx:143
H_CallId h_CallId
Definition Headers.cxx:266
unsigned __int64 uint64_t
Definition stdint.h:95