-
Notifications
You must be signed in to change notification settings - Fork 7
/
cisco-usecallmanager-20.9.0.patch
8765 lines (8500 loc) · 334 KB
/
cisco-usecallmanager-20.9.0.patch
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
diff -durN asterisk-20.9.0.orig/channels/chan_sip.c asterisk-20.9.0/channels/chan_sip.c
--- asterisk-20.9.0.orig/channels/chan_sip.c 2024-07-29 23:46:33.303903014 +1200
+++ asterisk-20.9.0/channels/chan_sip.c 2024-07-29 23:47:49.593888562 +1200
@@ -176,7 +176,7 @@
/*** MODULEINFO
<use type="module">res_crypto</use>
<use type="module">res_http_websocket</use>
- <defaultenabled>no</defaultenabled>
+ <defaultenabled>yes</defaultenabled>
<support_level>deprecated</support_level>
<replacement>chan_pjsip</replacement>
<deprecated_in>17</deprecated_in>
@@ -369,6 +369,67 @@
application is only available if TEST_FRAMEWORK is defined.</para>
</description>
</application>
+ <application name="SIPCiscoPage" language="en_US">
+ <synopsis>
+ Page a series of Cisco USECALLMANAGER phones
+ </synopsis>
+ <syntax>
+ <parameter name="peers" required="true" argsep="&">
+ <argument name="peer" required="true">
+ <para>Name of the SIP peer to page</para>
+ </argument>
+ <argument name="peer2" multiple="true">
+ <para>Name of the second peer to page, additional peers are
+ specified as peer&peer2&peer3...</para>
+ </argument>
+ </parameter>
+ <parameter name="options" required="false">
+ <optionlist>
+ <option name="m">
+ <argument name="x" required="true">
+ <para>Multicast IP address</para>
+ </argument>
+ <para>Use a single multicast RTP stream instead of
+ multiple unicast RTP streams.</para>
+ </option>
+ <option name="p">
+ <argument name="x" required="true">
+ <para>Port number. Must be an even number between
+ 20480 (default) and 32768</para>
+ </argument>
+ <para>Port the phone will use to receive the audio</para>
+ </option>
+ <option name="b">
+ <para>Page phone even if it busy (off-hook, ringing, busy
+ or do-not-disturb)</para>
+ </option>
+ <option name="v">
+ <argument name="x" required="true">
+ <para>Volume. Must be a number between 1 and 100</para>
+ </argument>
+ <para>Force the receive volume on the phone</para>
+ </option>
+ <option name="d">
+ <argument name="x" required="true">
+ <para>Message to display</para>
+ </argument>
+ <para>Display a message in status line of the phone</para>
+ </option>
+ <option name="o">
+ <para>Mark the phones as off-hook during paging.</para>
+ </option>
+ <option name="a">
+ <para>Play an alert beep on the paged phone.</para>
+ </option>
+ </optionlist>
+ </parameter>
+ </syntax>
+ <description>
+ <para>Using the RTP streaming API, send a request to the specified peers to
+ receive RTP audio. Supported codecs are G711 (mulaw and alaw), G722 and
+ G729a. RTP is transmitted as unicast unless the m() option is used.</para>
+ </description>
+ </application>
<function name="SIP_HEADER" language="en_US">
<synopsis>
Gets the specified SIP header from an incoming INVITE message.
@@ -511,6 +572,27 @@
<enum name="codec[x]">
<para>Preferred codec index number <replaceable>x</replaceable> (beginning with zero).</para>
</enum>
+ <enum name="vmexten">
+ <para>The vmexten for this peer.</para>
+ </enum>
+ <enum name="donotdisturb">
+ <para>Is DoNotDisturb set on this peer (yes/no).</para>
+ </enum>
+ <enum name="callforward">
+ <para>The call forwarding extension for this peer.</para>
+ </enum>
+ <enum name="huntgroup">
+ <para>Is HuntGroup login set on this peer (yes/no).</para>
+ </enum>
+ <enum name="regcallid">
+ <para>The Call-ID of the REGISTER dialog.</para>
+ </enum>
+ <enum name="ciscodevicename">
+ <para>The device name of the Cisco USECALLMANAGER peer</para>
+ </enum>
+ <enum name="ciscolineindex">
+ <para>The line index of the Cisco USECALLMANAGER peer</para>
+ </enum>
</enumlist>
</parameter>
</syntax>
@@ -729,7 +811,9 @@
{ CPIM_PIDF_XML, "presence", "application/cpim-pidf+xml", "cpim-pidf+xml" }, /* RFC 3863 */
{ PIDF_XML, "presence", "application/pidf+xml", "pidf+xml" }, /* RFC 3863 */
{ XPIDF_XML, "presence", "application/xpidf+xml", "xpidf+xml" }, /* Pre-RFC 3863 with MS additions */
- { MWI_NOTIFICATION, "message-summary", "application/simple-message-summary", "mwi" } /* RFC 3842: Mailbox notification */
+ { MWI_NOTIFICATION, "message-summary", "application/simple-message-summary", "mwi" }, /* RFC 3842: Mailbox notification */
+ { FEATURE_EVENTS, "as-feature-event", "application/x-as-feature-event+xml", "as-feature-event" }, /* EMCA-323 application server feature events */
+ { REMOTECC_XML, "refer", "application/x-cisco-remotecc-request+xml", "remotecc" } /* Cisco remotecc request/respones */
};
/*! \brief The core structure to setup dialogs. We parse incoming messages by using
@@ -894,6 +978,7 @@
static struct stasis_subscription *network_change_sub; /*!< subscription id for network change events */
static struct stasis_subscription *acl_change_sub; /*!< subscription id for named ACL system change events */
static int network_change_sched_id = -1;
+static struct stasis_subscription *pickup_notify_sub; /*!< subscription id for call ringing events */
static char used_context[AST_MAX_CONTEXT]; /*!< name of automatically created context for unloading */
@@ -928,6 +1013,68 @@
*/
static int sipdebug_text;
+/*! \brief Remotecc applications */
+enum {
+ REMOTECC_CONFLIST = 1,
+ REMOTECC_CALLBACK = 2
+};
+
+/*! \brief Contains the parsed-out xml elements from a remotecc request */
+struct remotecc_dialog {
+ char *callid;
+ char *localtag;
+ char *remotetag;
+};
+
+struct remotecc_data {
+ char *softkeyevent;
+ struct remotecc_dialog dialogid;
+ struct remotecc_dialog consultdialogid;
+ struct remotecc_dialog joindialogid;
+ int applicationid;
+ int confid;
+ char *usercalldata;
+};
+
+/*! \brief Information required to start or join an ad-hoc conference */
+struct conference_data {
+ struct sip_pvt *pvt;
+ AST_LIST_HEAD_NOLOCK(, sip_selected) selected;
+ int joining:1;
+ AST_DECLARE_STRING_FIELDS(
+ AST_STRING_FIELD(callid);
+ AST_STRING_FIELD(tag);
+ AST_STRING_FIELD(theirtag);
+ AST_STRING_FIELD(join_callid);
+ AST_STRING_FIELD(join_tag);
+ AST_STRING_FIELD(join_theirtag);
+ );
+};
+
+/*! \brief Informtion required to park a call */
+struct park_data {
+ struct sip_pvt *pvt;
+ struct ast_channel *chan;
+ int monitor:1;
+ AST_DECLARE_STRING_FIELDS(
+ AST_STRING_FIELD(context);
+ AST_STRING_FIELD(callid);
+ AST_STRING_FIELD(tag);
+ AST_STRING_FIELD(theirtag);
+ AST_STRING_FIELD(uniqueid);
+ );
+};
+
+/*! \brief Information required to record a call */
+struct record_data {
+ int outgoing:1;
+ AST_DECLARE_STRING_FIELDS(
+ AST_STRING_FIELD(callid);
+ AST_STRING_FIELD(tag);
+ AST_STRING_FIELD(theirtag);
+ );
+};
+
static const struct _map_x_s referstatusstrings[] = {
{ REFER_IDLE, "<none>" },
{ REFER_SENT, "Request sent" },
@@ -981,11 +1128,17 @@
#ifdef HAVE_LIBXML2
static int cc_esc_publish_handler(struct sip_pvt *pvt, struct sip_request *req, struct event_state_compositor *esc, struct sip_esc_entry *esc_entry);
+static int presence_esc_publish_handler(struct sip_pvt *pvt, struct sip_request *req, struct event_state_compositor *esc, struct sip_esc_entry *esc_entry);
static const struct sip_esc_publish_callbacks cc_esc_publish_callbacks = {
.initial_handler = cc_esc_publish_handler,
.modify_handler = cc_esc_publish_handler,
};
+
+static const struct sip_esc_publish_callbacks presence_esc_publish_callbacks = {
+ .initial_handler = presence_esc_publish_handler,
+ .modify_handler = presence_esc_publish_handler,
+};
#endif
/*!
@@ -1008,6 +1161,7 @@
} event_state_compositors [] = {
#ifdef HAVE_LIBXML2
{CALL_COMPLETION, "call-completion", &cc_esc_publish_callbacks},
+ {PRESENCE, "presence", &presence_esc_publish_callbacks},
#endif
};
@@ -1073,6 +1227,10 @@
static int temp_pvt_init(void *);
static void temp_pvt_cleanup(void *);
+/*! \brief The ad-hoc conference list */
+static AST_LIST_HEAD_STATIC(conferences, sip_conference);
+static int next_confid = 0;
+
/*! \brief A per-thread temporary pvt structure */
AST_THREADSTORAGE_CUSTOM(ts_temp_pvt, temp_pvt_init, temp_pvt_cleanup);
@@ -1179,6 +1337,7 @@
/*--- PBX interface functions */
static struct ast_channel *sip_request_call(const char *type, struct ast_format_cap *cap, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *dest, int *cause);
static int sip_devicestate(const char *data);
+static int sip_presencestate(const char *data, char **subtype, char **message);
static int sip_sendtext(struct ast_channel *ast, const char *text);
static int sip_call(struct ast_channel *ast, const char *dest, int timeout);
static int sip_sendhtml(struct ast_channel *chan, int subclass, const char *data, int datalen);
@@ -1204,7 +1363,8 @@
static int sipsock_read(int *id, int fd, short events, void *ignore);
static int __sip_xmit(struct sip_pvt *p, struct ast_str *data);
static int __sip_reliable_xmit(struct sip_pvt *p, uint32_t seqno, int resp, struct ast_str *data, int fatal, int sipmethod);
-static void add_cc_call_info_to_response(struct sip_pvt *p, struct sip_request *resp);
+static void add_cc_call_info(struct sip_request *resp, struct sip_pvt *p);
+static void add_remotecc_call_info(struct sip_request *req, struct sip_pvt *p);
static int __transmit_response(struct sip_pvt *p, const char *msg, const struct sip_request *req, enum xmittype reliable);
static int retrans_pkt(const void *data);
static int transmit_response_using_temp(ast_string_field callid, struct ast_sockaddr *addr, int useglobal_nat, const int intended_method, const struct sip_request *req, const char *msg);
@@ -1214,6 +1374,7 @@
static int transmit_response_with_sdp(struct sip_pvt *p, const char *msg, const struct sip_request *req, enum xmittype reliable, int oldsdp, int rpid);
static int transmit_response_with_unsupported(struct sip_pvt *p, const char *msg, const struct sip_request *req, const char *unsupported);
static int transmit_response_with_auth(struct sip_pvt *p, const char *msg, const struct sip_request *req, const char *rand, enum xmittype reliable, const char *header, int stale);
+static int transmit_response_with_optionsind(struct sip_pvt *p, const struct sip_request *req);
static int transmit_provisional_response(struct sip_pvt *p, const char *msg, const struct sip_request *req, int with_sdp);
static int transmit_response_with_allow(struct sip_pvt *p, const char *msg, const struct sip_request *req, enum xmittype reliable);
static void transmit_fake_auth_response(struct sip_pvt *p, struct sip_request *req, enum xmittype reliable);
@@ -1227,6 +1388,7 @@
static int transmit_info_with_vidupdate(struct sip_pvt *p);
static int transmit_message(struct sip_pvt *p, int init, int auth);
static int transmit_refer(struct sip_pvt *p, const char *dest);
+static int transmit_refer_with_content(struct sip_pvt *p, const char *type, const char *content);
static int transmit_notify_with_mwi(struct sip_pvt *p, int newmsgs, int oldmsgs, const char *vmexten);
static int transmit_notify_with_sipfrag(struct sip_pvt *p, int cseq, char *message, int terminate);
static int transmit_cc_notify(struct ast_cc_agent *agent, struct sip_pvt *subscription, enum sip_cc_notify_state state);
@@ -1236,7 +1398,11 @@
static void copy_request(struct sip_request *dst, const struct sip_request *src);
static void receive_message(struct sip_pvt *p, struct sip_request *req, struct ast_sockaddr *addr, const char *e);
static void parse_moved_contact(struct sip_pvt *p, struct sip_request *req, char **name, char **number, int set_call_forward);
-static int sip_send_mwi_to_peer(struct sip_peer *peer, int cache_only);
+static int sip_send_mwi(struct sip_peer *peer, int cache_only);
+static int sip_send_bulkupdate(struct sip_peer *peer);
+static void extensionstate_subscriptions(struct sip_peer *peer);
+static void register_peer_aliases(struct sip_peer *peer);
+static void expire_peer_aliases(struct sip_peer *peer);
/* Misc dialog routines */
static int __sip_autodestruct(const void *data);
@@ -1251,6 +1417,7 @@
static int build_path(struct sip_pvt *p, struct sip_peer *peer, struct sip_request *req, const char *pathbuf);
static enum check_auth_result register_verify(struct sip_pvt *p, struct ast_sockaddr *addr,
struct sip_request *req, const char *uri);
+struct sip_pvt *get_sip_pvt(const char *callid, const char *totag, const char *fromtag);
static int get_sip_pvt_from_replaces(const char *callid, const char *totag, const char *fromtag,
struct sip_pvt **out_pvt, struct ast_channel **out_chan);
static void check_pendings(struct sip_pvt *p);
@@ -1261,6 +1428,7 @@
static int sip_sipredirect(struct sip_pvt *p, const char *dest);
static int is_method_allowed(unsigned int *allowed_methods, enum sipmethod method);
+static void start_record_thread(const char *callid, const char *tag, const char *theirtag, int outgoing);
/*--- Codec handling / SDP */
static void try_suggested_sip_codec(struct sip_pvt *p);
@@ -1274,9 +1442,9 @@
static int process_sdp_a_ice(const char *a, struct sip_pvt *p, struct ast_rtp_instance *instance, int rtcp_mux);
static int process_sdp_a_rtcp_mux(const char *a, struct sip_pvt *p, int *requested);
static int process_sdp_a_dtls(const char *a, struct sip_pvt *p, struct ast_rtp_instance *instance);
-static int process_sdp_a_audio(const char *a, struct sip_pvt *p, struct ast_rtp_codecs *newaudiortp, int *last_rtpmap_codec);
-static int process_sdp_a_video(const char *a, struct sip_pvt *p, struct ast_rtp_codecs *newvideortp, int *last_rtpmap_codec);
-static int process_sdp_a_text(const char *a, struct sip_pvt *p, struct ast_rtp_codecs *newtextrtp, char *red_fmtp, int *red_num_gen, int *red_data_pt, int *last_rtpmap_codec);
+static int process_sdp_a_audio(const char *a, struct sip_pvt *p, struct ast_rtp_codecs *newaudiortp, int *audio_codec, int *rtpmap_codecs);
+static int process_sdp_a_video(const char *a, struct sip_pvt *p, struct ast_rtp_codecs *newvideortp, int *video_codec, int *rtpmap_codecs);
+static int process_sdp_a_text(const char *a, struct sip_pvt *p, struct ast_rtp_codecs *newtextrtp, char *red_fmtp, int *red_num_gen, int *red_data_pt, int *rtpmap_codecs);
static int process_sdp_a_image(const char *a, struct sip_pvt *p);
static void add_ice_to_sdp(struct ast_rtp_instance *instance, struct ast_str **a_buf);
static void add_dtls_to_sdp(struct ast_rtp_instance *instance, struct ast_str **a_buf);
@@ -1318,7 +1486,7 @@
static int expire_register(const void *data);
static void *do_monitor(void *data);
static int restart_monitor(void);
-static void peer_mailboxes_to_str(struct ast_str **mailbox_str, struct sip_peer *peer);
+static void get_peer_mailboxes(struct ast_str **mailbox_str, struct sip_peer *peer);
static struct ast_variable *copy_vars(struct ast_variable *src);
static int dialog_find_multiple(void *obj, void *arg, int flags);
static struct ast_channel *sip_pvt_lock_full(struct sip_pvt *pvt);
@@ -1340,6 +1508,7 @@
static void mwi_event_cb(void *, struct stasis_subscription *, struct stasis_message *);
static void network_change_stasis_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message);
static void acl_change_stasis_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message);
+static void pickup_notify_stasis_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message);
static void sip_keepalive_all_peers(void);
#define peer_in_destruction(peer) (ao2_ref(peer, 0) == 0)
@@ -1404,6 +1573,8 @@
static inline int sip_debug_test_pvt(struct sip_pvt *p);
static void append_history_full(struct sip_pvt *p, const char *fmt, ...);
static void sip_dump_history(struct sip_pvt *dialog);
+static void parse_rtp_stats(struct sip_pvt *pvt, struct sip_request *req);
+static void send_qrt_url(struct sip_peer *peer);
/*--- Device object handling */
static struct sip_peer *build_peer(const char *name, struct ast_variable *v, struct ast_variable *alt, int realtime, int devstate_only);
@@ -1414,7 +1585,7 @@
static struct sip_peer *temp_peer(const char *name);
static void register_peer_exten(struct sip_peer *peer, int onoff);
static int sip_poke_peer_s(const void *data);
-static enum parse_register_result parse_register_contact(struct sip_pvt *pvt, struct sip_peer *p, struct sip_request *req);
+static enum parse_register_result parse_register_contact(struct sip_pvt *pvt, struct sip_peer *p, struct sip_request *req, int *addrchanged);
static void reg_source_db(struct sip_peer *peer);
static void destroy_association(struct sip_peer *peer);
static void set_insecure_flags(struct ast_flags *flags, const char *value, int lineno);
@@ -1469,9 +1640,14 @@
static int transmit_state_notify(struct sip_pvt *p, struct state_notify_data *data, int full, int timeout);
static void update_connectedline(struct sip_pvt *p, const void *data, size_t datalen);
static void update_redirecting(struct sip_pvt *p, const void *data, size_t datalen);
+static int sip_send_donotdisturb(struct sip_peer *peer);
+static int sip_send_huntgroup(struct sip_peer *peer);
+static int sip_send_callforward(struct sip_peer *peer);
static int get_domain(const char *str, char *domain, int len);
static void get_realm(struct sip_pvt *p, const struct sip_request *req);
-static char *get_content(struct sip_request *req);
+static char *get_content(struct sip_request *req, int start, int end);
+static int find_boundary(struct sip_request *req, const char *boundary, int start, int *done);
+const char *find_content_type(struct sip_request *req);
/*-- TCP connection handling ---*/
static void *_sip_tcp_helper_thread(struct ast_tcptls_session_instance *tcptls_session);
@@ -1518,7 +1694,7 @@
static int handle_incoming(struct sip_pvt *p, struct sip_request *req, struct ast_sockaddr *addr, int *recount, int *nounlock);
static int handle_request_update(struct sip_pvt *p, struct sip_request *req);
static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, struct ast_sockaddr *addr, uint32_t seqno, int *recount, const char *e, int *nounlock);
-static int handle_request_refer(struct sip_pvt *p, struct sip_request *req, uint32_t seqno, int *nounlock);
+static int handle_request_refer(struct sip_pvt *p, struct sip_request *req, struct ast_sockaddr *addr, uint32_t seqno, const char *e, int *nounlock);
static int handle_request_bye(struct sip_pvt *p, struct sip_request *req);
static int handle_request_register(struct sip_pvt *p, struct sip_request *req, struct ast_sockaddr *sin, const char *e);
static int handle_request_cancel(struct sip_pvt *p, struct sip_request *req);
@@ -1583,6 +1759,7 @@
.properties = AST_CHAN_TP_WANTSJITTER | AST_CHAN_TP_CREATESJITTER,
.requester = sip_request_call, /* called with chan unlocked */
.devicestate = sip_devicestate, /* called with chan unlocked (not chan-specific) */
+ .presencestate = sip_presencestate, /* called with chan unlocked (not chan-specific) */
.call = sip_call, /* called with chan locked */
.send_html = sip_sendhtml,
.hangup = sip_hangup, /* called with chan locked */
@@ -3409,9 +3586,23 @@
if (dialog->relatedpeer && dialog->relatedpeer->mwipvt == dialog) {
dialog->relatedpeer->mwipvt = dialog_unref(dialog->relatedpeer->mwipvt, "delete ->relatedpeer->mwipvt");
}
+ /* Remove link from peer to subscription for Feature Events */
+ if (dialog->relatedpeer && dialog->relatedpeer->fepvt == dialog) {
+ dialog->relatedpeer->fepvt = dialog_unref(dialog->relatedpeer->fepvt, "delete ->relatedpeer->fepvt");
+ }
if (dialog->relatedpeer && dialog->relatedpeer->call == dialog) {
dialog->relatedpeer->call = dialog_unref(dialog->relatedpeer->call, "unset the relatedpeer->call field in tandem with relatedpeer field itself");
}
+ if (dialog->conference) {
+ ao2_ref(dialog->conference, -1);
+ dialog->conference = NULL;
+ }
+ if (dialog->recordoutpvt) {
+ dialog->recordoutpvt = dialog_unref(dialog->recordoutpvt, "delete ->recordoutpvt");
+ }
+ if (dialog->recordinpvt) {
+ dialog->recordinpvt = dialog_unref(dialog->recordinpvt, "delete ->recordinpvt");
+ }
dialog_ref(dialog, "Stop scheduled items for unlink action");
if (ast_sched_add(sched, 0, __dialog_unlink_sched_items, dialog) < 0) {
@@ -5311,6 +5502,85 @@
}
}
+static void destroy_alias(struct sip_alias *alias)
+{
+ if (alias->peer) {
+ alias->peer->lastms = 0;
+
+ if (alias->peer->socket.tcptls_session) {
+ ao2_ref(alias->peer->socket.tcptls_session, -1);
+ } else if (alias->peer->socket.ws_session) {
+ ast_websocket_unref(alias->peer->socket.ws_session);
+ }
+
+ ast_string_field_set(alias->peer, fullcontact, "");
+ ast_string_field_set(alias->peer, username, "");
+ ast_string_field_set(alias->peer, useragent, "");
+
+ if (!ast_sockaddr_isnull(&alias->peer->addr)) {
+ manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: SIP\r\nPeer: SIP/%s\r\nPeerStatus: Unregistered\r\nCause: Expired\r\n",
+ alias->peer->name);
+ ast_devstate_changed(AST_DEVICE_UNKNOWN, AST_DEVSTATE_CACHABLE, "SIP/%s", alias->peer->name);
+ register_peer_exten(alias->peer, FALSE);
+
+ memset(&alias->peer->addr, 0, sizeof(alias->peer->addr));
+ }
+ sip_unref_peer(alias->peer, "destroy_alias removing peer ref");
+ }
+ ast_free(alias->name);
+ ast_free(alias);
+}
+
+static void clear_peer_aliases(struct sip_peer *peer)
+{
+ struct sip_alias *alias;
+
+ while ((alias = AST_LIST_REMOVE_HEAD(&peer->aliases, entry)))
+ destroy_alias(alias);
+}
+
+/*! Destroy extension state subscription */
+static void destroy_subscription(struct sip_subscription *subscription)
+{
+ if (subscription->pvt) {
+ dialog_unlink_all(subscription->pvt);
+ dialog_unref(subscription->pvt, "destroying subscription");
+ }
+ ast_string_field_free_memory(subscription);
+ ast_free(subscription);
+}
+
+/* Destroy all peer-related extension state subscriptions */
+static void clear_peer_subscriptions(struct sip_peer *peer)
+{
+ struct sip_subscription *subscription;
+
+ while ((subscription = AST_LIST_REMOVE_HEAD(&peer->subscriptions, entry)))
+ destroy_subscription(subscription);
+}
+
+static void destroy_callback(struct sip_peer *peer)
+{
+ ast_extension_state_del(peer->callback->stateid, NULL);
+ sip_unref_peer(peer, "destroy_callback: removing callback ref");
+ ast_free(peer->callback->exten);
+ ast_free(peer->callback);
+}
+
+static void destroy_selected(struct sip_selected *selected)
+{
+ ast_string_field_free_memory(selected);
+ ast_free(selected);
+}
+
+static void clear_peer_selected(struct sip_peer *peer)
+{
+ struct sip_selected *selected;
+
+ while ((selected = AST_LIST_REMOVE_HEAD(&peer->selected, entry)))
+ destroy_selected(selected);
+}
+
static void sip_destroy_peer_fn(void *peer)
{
sip_destroy_peer(peer);
@@ -5327,6 +5597,9 @@
* happening right now.
*/
clear_peer_mailboxes(peer);
+ clear_peer_aliases(peer);
+ clear_peer_subscriptions(peer);
+ clear_peer_selected(peer);
if (peer->outboundproxy) {
ao2_ref(peer->outboundproxy, -1);
@@ -5344,6 +5617,16 @@
peer->mwipvt = dialog_unref(peer->mwipvt, "unreffing peer->mwipvt");
}
+ if (peer->fepvt) { /* We have an active subscription, delete it */
+ dialog_unlink_all(peer->fepvt);
+ peer->fepvt = dialog_unref(peer->fepvt, "unreffing peer->fepvt");
+ }
+
+ if (peer->callback) {
+ destroy_callback(peer);
+ peer->callback = NULL;
+ }
+
if (peer->chanvars) {
ast_variables_destroy(peer->chanvars);
peer->chanvars = NULL;
@@ -6011,6 +6294,31 @@
}
}
+static void copy_pvt_data(struct sip_pvt *to_pvt, struct sip_pvt *from_pvt)
+{
+ sip_pvt_lock(from_pvt);
+ to_pvt->sa = from_pvt->sa;
+ to_pvt->recv = from_pvt->recv;
+ copy_socket_data(&to_pvt->socket, &from_pvt->socket);
+ ast_copy_flags(&to_pvt->flags[0], &from_pvt->flags[0], SIP_FLAGS_TO_COPY);
+ ast_copy_flags(&to_pvt->flags[1], &from_pvt->flags[1], SIP_PAGE2_FLAGS_TO_COPY);
+ ast_copy_flags(&to_pvt->flags[2], &from_pvt->flags[2], SIP_PAGE3_FLAGS_TO_COPY);
+
+ /* Recalculate our side, and recalculate Call ID */
+ ast_sip_ouraddrfor(&to_pvt->sa, &to_pvt->ourip, to_pvt);
+ change_callid_pvt(to_pvt, NULL);
+
+ ast_string_field_set(to_pvt, tohost, from_pvt->tohost);
+ to_pvt->portinuri = from_pvt->portinuri;
+ to_pvt->fromdomainport = from_pvt->fromdomainport;
+
+ ast_string_field_set(to_pvt, fullcontact, from_pvt->fullcontact);
+ ast_string_field_set(to_pvt, username, from_pvt->username);
+ ast_string_field_set(to_pvt, fromuser, from_pvt->fromuser);
+ ast_string_field_set(to_pvt, fromname, from_pvt->fromname);
+ sip_pvt_unlock(from_pvt);
+}
+
/*! \brief Initialize DTLS-SRTP support on an RTP instance */
static int dialog_initialize_dtls_srtp(const struct sip_pvt *dialog, struct ast_rtp_instance *rtp, struct ast_sdp_srtp **srtp)
{
@@ -6314,6 +6622,10 @@
dialog->fromdomainport = peer->fromdomainport;
}
dialog->callingpres = peer->callingpres;
+ dialog->donotdisturb = peer->donotdisturb;
+ if (!ast_strlen_zero(peer->callforward)) {
+ ast_string_field_set(dialog, callforward, peer->callforward);
+ }
return 0;
}
@@ -6482,6 +6794,15 @@
}
}
+ if (p->donotdisturb && ast_test_flag(&p->flags[2], SIP_PAGE3_DND_BUSY)) {
+ ast_queue_control(p->owner, AST_CONTROL_BUSY);
+ return 0;
+ } else if (!ast_strlen_zero(p->callforward)) {
+ ast_channel_call_forward_set(ast, p->callforward);
+ ast_queue_control(p->owner, AST_CONTROL_BUSY);
+ return 0;
+ }
+
/* Check whether there is vxml_url, distinctive ring variables */
headp = ast_channel_varshead(ast);
AST_LIST_TRAVERSE(headp, current, entries) {
@@ -6717,6 +7038,9 @@
/* Remove link from peer to subscription of MWI */
if (p->relatedpeer && p->relatedpeer->mwipvt == p)
p->relatedpeer->mwipvt = dialog_unref(p->relatedpeer->mwipvt, "delete ->relatedpeer->mwipvt");
+ /* Remove link from peer to subscription for Feature Events */
+ if (p->relatedpeer && p->relatedpeer->fepvt)
+ p->relatedpeer->fepvt = dialog_unref(p->relatedpeer->fepvt, "delete ->relatedpeer->fepvt");
if (p->relatedpeer && p->relatedpeer->call == p)
p->relatedpeer->call = dialog_unref(p->relatedpeer->call, "unset the relatedpeer->call field in tandem with relatedpeer field itself");
@@ -7255,6 +7579,11 @@
if (sipdebug)
ast_debug(1, "update_call_counter(%s) - decrement call limit counter on hangup\n", p->username);
update_call_counter(p, DEC_CALL_LIMIT);
+ if (!ast_test_flag(&p->flags[0], SIP_INC_COUNT) && p->relatedpeer) {
+ ao2_lock(p->relatedpeer);
+ clear_peer_selected(p->relatedpeer);
+ ao2_unlock(p->relatedpeer);
+ }
}
/* Determine how to disconnect */
@@ -7321,7 +7650,9 @@
const char *res;
stop_provisional_keepalive(p);
- if (p->hangupcause && (res = hangup_cause2sip(p->hangupcause)))
+ if (ast_test_flag(&p->flags[2], SIP_PAGE3_TRANSFER_RESPONSE))
+ transmit_response_reliable(p, "500 Internal Server Error", &p->initreq);
+ else if (p->hangupcause && (res = hangup_cause2sip(p->hangupcause)))
transmit_response_reliable(p, res, &p->initreq);
else
transmit_response_reliable(p, "603 Declined", &p->initreq);
@@ -8144,6 +8475,7 @@
case AST_CONTROL_UPDATE_RTP_PEER: /* Absorb this since it is handled by the bridge */
break;
case AST_CONTROL_FLASH: /* We don't currently handle AST_CONTROL_FLASH here, but it is expected, so we don't need to warn either. */
+ case AST_CONTROL_MCID:
res = -1;
break;
case AST_CONTROL_PVT_CAUSE_CODE: /* these should be handled by the code in channel.c */
@@ -8616,14 +8948,12 @@
return __get_header(req, name, &start);
}
-
AST_THREADSTORAGE(sip_content_buf);
/*! \brief Get message body content */
-static char *get_content(struct sip_request *req)
+static char *get_content(struct sip_request *req, int start, int end)
{
struct ast_str *str;
- int i;
if (!(str = ast_str_thread_get(&sip_content_buf, 128))) {
return NULL;
@@ -8631,8 +8961,8 @@
ast_str_reset(str);
- for (i = 0; i < req->lines; i++) {
- if (ast_str_append(&str, 0, "%s\n", REQ_OFFSET_TO_STR(req, line[i])) < 0) {
+ while (start < req->lines && start <= end) {
+ if (ast_str_append(&str, 0, "%s\n", REQ_OFFSET_TO_STR(req, line[start++])) < 0) {
return NULL;
}
}
@@ -8640,6 +8970,68 @@
return ast_str_buffer(str);
}
+/*! \brief find the content boundary */
+static int find_boundary(struct sip_request *req, const char *boundary, int start, int *done)
+{
+ char *line;
+ int len = strlen(boundary);
+
+ for (*done = 0; start < req->lines; start++) {
+ line = REQ_OFFSET_TO_STR(req, line[start]);
+ if (strncmp(line, "--", 2)) {
+ continue;
+ }
+ if (!strncmp(boundary, line + 2, len)) {
+ if (!strcmp(line + 2 + len, "--")) {
+ *done = 1;
+ } else if (strcmp(line + 2 + len, "")) {
+ continue;
+ }
+ return start;
+ }
+ }
+
+ return -1;
+}
+
+/*! \brief get the content type from either the Content-Type header or the Content-Type of the first part */
+const char *find_content_type(struct sip_request *req)
+{
+ const char *type = sip_get_header(req, "Content-Type");
+ char *boundary;
+ const char *line;
+ int start, done;
+
+ if (ast_strlen_zero(type) || strncasecmp(type, "multipart/mixed", 15)) {
+ return type;
+ }
+
+ if ((boundary = strcasestr(type, ";boundary="))) {
+ boundary += 10;
+ } else if ((boundary = strcasestr(type, "; boundary="))) {
+ boundary += 11;
+ } else {
+ return "";
+ }
+ boundary = ast_strdupa(boundary);
+ boundary = strsep(&boundary, ";");
+
+ if ((start = find_boundary(req, boundary, 0, &done)) == -1) {
+ return "";
+ }
+
+ for (++start; start < req->lines; start++) {
+ line = REQ_OFFSET_TO_STR(req, line[start]);
+ if (!strncasecmp(line, "Content-Type:", 13)) {
+ return ast_skip_blanks(line + 13);
+ } else if (!strcasecmp(line, "")) {
+ break;
+ }
+ }
+
+ return "";
+}
+
/*! \brief Read RTP from network */
static struct ast_frame *sip_rtp_read(struct ast_channel *ast, struct sip_pvt *p, int *faxdetect)
{
@@ -10322,7 +10714,9 @@
/* Others */
int sendonly = -1;
unsigned int numberofports;
- int last_rtpmap_codec = 0;
+ int audio_codec = 255;
+ int video_codec = 255;
+ int rtpmap_codecs = 0;
int red_data_pt[10]; /* For T.140 RED */
int red_num_gen = 0; /* For T.140 RED */
char red_fmtp[100] = "empty"; /* For T.140 RED */
@@ -10390,11 +10784,11 @@
if (process_sdp_a_sendonly(value, &sendonly)) {
processed = TRUE;
}
- else if (process_sdp_a_audio(value, p, &newaudiortp, &last_rtpmap_codec))
+ else if (process_sdp_a_audio(value, p, &newaudiortp, &audio_codec, &rtpmap_codecs))
processed = TRUE;
- else if (process_sdp_a_video(value, p, &newvideortp, &last_rtpmap_codec))
+ else if (process_sdp_a_video(value, p, &newvideortp, &video_codec, &rtpmap_codecs))
processed = TRUE;
- else if (process_sdp_a_text(value, p, &newtextrtp, red_fmtp, &red_num_gen, red_data_pt, &last_rtpmap_codec))
+ else if (process_sdp_a_text(value, p, &newtextrtp, red_fmtp, &red_num_gen, red_data_pt, &rtpmap_codecs))
processed = TRUE;
else if (process_sdp_a_image(value, p))
processed = TRUE;
@@ -10851,7 +11245,7 @@
ast_log(AST_LOG_NOTICE, "Processed audio crypto attribute without SAVP specified; accepting anyway\n");
secure_audio = TRUE;
}
- } else if (process_sdp_a_audio(value, p, &newaudiortp, &last_rtpmap_codec)) {
+ } else if (process_sdp_a_audio(value, p, &newaudiortp, &audio_codec, &rtpmap_codecs)) {
processed = TRUE;
} else if (process_sdp_a_rtcp_mux(value, p, &remote_rtcp_mux_audio)) {
processed = TRUE;
@@ -10874,7 +11268,7 @@
ast_log(AST_LOG_NOTICE, "Processed video crypto attribute without SAVP specified; accepting anyway\n");
secure_video = TRUE;
}
- } else if (process_sdp_a_video(value, p, &newvideortp, &last_rtpmap_codec)) {
+ } else if (process_sdp_a_video(value, p, &newvideortp, &video_codec, &rtpmap_codecs)) {
processed = TRUE;
} else if (process_sdp_a_rtcp_mux(value, p, &remote_rtcp_mux_video)) {
processed = TRUE;
@@ -10884,7 +11278,7 @@
else if (text) {
if (process_sdp_a_ice(value, p, p->trtp, rtcp_mux_offered)) {
processed = TRUE;
- } else if (process_sdp_a_text(value, p, &newtextrtp, red_fmtp, &red_num_gen, red_data_pt, &last_rtpmap_codec)) {
+ } else if (process_sdp_a_text(value, p, &newtextrtp, red_fmtp, &red_num_gen, red_data_pt, &rtpmap_codecs)) {
processed = TRUE;
} else if (!processed_crypto && process_crypto(p, p->trtp, &p->tsrtp, value)) {
processed_crypto = TRUE;
@@ -11566,11 +11960,11 @@
return found;
}
-static int process_sdp_a_audio(const char *a, struct sip_pvt *p, struct ast_rtp_codecs *newaudiortp, int *last_rtpmap_codec)
+static int process_sdp_a_audio(const char *a, struct sip_pvt *p, struct ast_rtp_codecs *newaudiortp, int *audio_codec, int *rtpmap_codecs)
{
int found = FALSE;
unsigned int codec;
- char mimeSubtype[128];
+ char mime_subtype[128];
char fmtp_string[256];
unsigned int sample_rate;
int debug = sip_debug_test_pvt(p);
@@ -11593,24 +11987,24 @@
ast_rtp_codecs_set_framing(newaudiortp, framing);
}
found = TRUE;
- } else if (sscanf(a, "rtpmap: %30u %127[^/]/%30u", &codec, mimeSubtype, &sample_rate) == 3) {
+ } else if (sscanf(a, "rtpmap: %30u %127[^/]/%30u", &codec, mime_subtype, &sample_rate) == 3) {
/* We have a rtpmap to handle */
- if (*last_rtpmap_codec < SDP_MAX_RTPMAP_CODECS) {
- if (!(ast_rtp_codecs_payloads_set_rtpmap_type_rate(newaudiortp, NULL, codec, "audio", mimeSubtype,
+ if (*rtpmap_codecs < SDP_MAX_RTPMAP_CODECS) {
+ if (!(ast_rtp_codecs_payloads_set_rtpmap_type_rate(newaudiortp, NULL, codec, "audio", mime_subtype,
ast_test_flag(&p->flags[0], SIP_G726_NONSTANDARD) ? AST_RTP_OPT_G726_NONSTANDARD : 0, sample_rate))) {
if (debug)
- ast_verbose("Found audio description format %s for ID %u\n", mimeSubtype, codec);
- //found_rtpmap_codecs[last_rtpmap_codec] = codec;
- (*last_rtpmap_codec)++;
+ ast_verbose("Found audio description format %s for ID %u\n", mime_subtype, codec);
+ *audio_codec = codec;
+ (*rtpmap_codecs)++;
found = TRUE;
} else {
ast_rtp_codecs_payloads_unset(newaudiortp, NULL, codec);
if (debug)
- ast_verbose("Found unknown media description format %s for ID %u\n", mimeSubtype, codec);
+ ast_verbose("Found unknown media description format %s for ID %u\n", mime_subtype, codec);
}
} else {
if (debug)
- ast_verbose("Discarded description format %s for ID %u\n", mimeSubtype, codec);
+ ast_verbose("Discarded description format %s for ID %u\n", mime_subtype, codec);
}
} else if (sscanf(a, "fmtp: %30u %255[^\t\n]", &codec, fmtp_string) == 2) {
struct ast_format *format;
@@ -11646,36 +12040,37 @@
return found;
}
-static int process_sdp_a_video(const char *a, struct sip_pvt *p, struct ast_rtp_codecs *newvideortp, int *last_rtpmap_codec)
+static int process_sdp_a_video(const char *a, struct sip_pvt *p, struct ast_rtp_codecs *newvideortp, int *video_codec, int *rtpmap_codecs)
{
int found = FALSE;
unsigned int codec;
- char mimeSubtype[128];
+ char mime_subtype[128];
unsigned int sample_rate;
int debug = sip_debug_test_pvt(p);
char fmtp_string[256];
+ char imageattr[256];
- if (sscanf(a, "rtpmap: %30u %127[^/]/%30u", &codec, mimeSubtype, &sample_rate) == 3) {
+ if (sscanf(a, "rtpmap: %30u %127[^/]/%30u", &codec, mime_subtype, &sample_rate) == 3) {
/* We have a rtpmap to handle */
- if (*last_rtpmap_codec < SDP_MAX_RTPMAP_CODECS) {
+ if (*rtpmap_codecs < SDP_MAX_RTPMAP_CODECS) {
/* Note: should really look at the '#chans' params too */
- if (!strncasecmp(mimeSubtype, "H26", 3) || !strncasecmp(mimeSubtype, "MP4", 3)
- || !strncasecmp(mimeSubtype, "VP8", 3)) {
- if (!(ast_rtp_codecs_payloads_set_rtpmap_type_rate(newvideortp, NULL, codec, "video", mimeSubtype, 0, sample_rate))) {
+ if (!strncasecmp(mime_subtype, "H26", 3) || !strncasecmp(mime_subtype, "MP4", 3)
+ || !strncasecmp(mime_subtype, "VP8", 3)) {
+ if (!(ast_rtp_codecs_payloads_set_rtpmap_type_rate(newvideortp, NULL, codec, "video", mime_subtype, 0, sample_rate))) {
if (debug)
- ast_verbose("Found video description format %s for ID %u\n", mimeSubtype, codec);
- //found_rtpmap_codecs[last_rtpmap_codec] = codec;
- (*last_rtpmap_codec)++;
+ ast_verbose("Found video description format %s for ID %u\n", mime_subtype, codec);
+ *video_codec = codec;
+ (*rtpmap_codecs)++;
found = TRUE;
} else {
ast_rtp_codecs_payloads_unset(newvideortp, NULL, codec);
if (debug)
- ast_verbose("Found unknown media description format %s for ID %u\n", mimeSubtype, codec);
+ ast_verbose("Found unknown media description format %s for ID %u\n", mime_subtype, codec);
}
}
} else {
if (debug)
- ast_verbose("Discarded description format %s for ID %u\n", mimeSubtype, codec);
+ ast_verbose("Discarded description format %s for ID %u\n", mime_subtype, codec);
}
} else if (sscanf(a, "fmtp: %30u %255[^\t\n]", &codec, fmtp_string) == 2) {
struct ast_format *format;
@@ -11695,41 +12090,61 @@
}
ao2_ref(format, -1);
}
+ } else if (sscanf(a, "imageattr: %30u recv %255[^\t\n]", &codec, imageattr) == 2
+ || (codec = *video_codec, sscanf(a, "imageattr:* recv %255[^\t\n]", imageattr) == 1)) {
+ struct ast_format *format;
+
+ if ((format = ast_rtp_codecs_get_payload_format(newvideortp, codec))) {
+ struct ast_format *format_parsed;
+
+ format_parsed = ast_format_attribute_set(format, "imageattr", imageattr);
+
+ if (format_parsed) {
+ ast_rtp_codecs_payload_replace_format(newvideortp, codec, format_parsed);
+ ao2_replace(format, format_parsed);
+ ao2_ref(format_parsed, -1);
+ found = TRUE;
+ } else {
+ ast_rtp_codecs_payloads_unset(newvideortp, NULL, codec);
+ }
+ ao2_ref(format, -1);
+ }
}
return found;
}
-static int process_sdp_a_text(const char *a, struct sip_pvt *p, struct ast_rtp_codecs *newtextrtp, char *red_fmtp, int *red_num_gen, int *red_data_pt, int *last_rtpmap_codec)
+static int process_sdp_a_text(const char *a, struct sip_pvt *p, struct ast_rtp_codecs *newtextrtp, char *red_fmtp, int *red_num_gen, int *red_data_pt, int *rtpmap_codecs)
{
int found = FALSE;
unsigned int codec;
- char mimeSubtype[128];
+ char mime_subtype[128];
unsigned int sample_rate;
char *red_cp;
int debug = sip_debug_test_pvt(p);
- if (sscanf(a, "rtpmap: %30u %127[^/]/%30u", &codec, mimeSubtype, &sample_rate) == 3) {
+ if (sscanf(a, "rtpmap: %30u %127[^/]/%30u", &codec, mime_subtype, &sample_rate) == 3) {
/* We have a rtpmap to handle */
- if (*last_rtpmap_codec < SDP_MAX_RTPMAP_CODECS) {
- if (!strncasecmp(mimeSubtype, "T140", 4)) { /* Text */
+ if (*rtpmap_codecs < SDP_MAX_RTPMAP_CODECS) {
+ if (!strncasecmp(mime_subtype, "T140", 4)) { /* Text */
if (p->trtp) {
- /* ast_verbose("Adding t140 mimeSubtype to textrtp struct\n"); */
- ast_rtp_codecs_payloads_set_rtpmap_type_rate(newtextrtp, NULL, codec, "text", mimeSubtype, 0, sample_rate);
+ /* ast_verbose("Adding t140 mime_subtype to textrtp struct\n"); */
+ ast_rtp_codecs_payloads_set_rtpmap_type_rate(newtextrtp, NULL, codec, "text", mime_subtype, 0, sample_rate);
found = TRUE;
}
- } else if (!strncasecmp(mimeSubtype, "RED", 3)) { /* Text with Redudancy */
+ } else if (!strncasecmp(mime_subtype, "RED", 3)) { /* Text with Redudancy */
if (p->trtp) {
- ast_rtp_codecs_payloads_set_rtpmap_type_rate(newtextrtp, NULL, codec, "text", mimeSubtype, 0, sample_rate);
+ ast_rtp_codecs_payloads_set_rtpmap_type_rate(newtextrtp, NULL, codec, "text", mime_subtype, 0, sample_rate);
sprintf(red_fmtp, "fmtp:%u ", codec);
if (debug)
ast_verbose("RED submimetype has payload type: %u\n", codec);
found = TRUE;
}
}
+ (*rtpmap_codecs)++;
} else {
if (debug)
- ast_verbose("Discarded description format %s for ID %u\n", mimeSubtype, codec);
+ ast_verbose("Discarded description format %s for ID %u\n", mime_subtype, codec);
}
} else if (!strncmp(a, red_fmtp, strlen(red_fmtp))) {
char *rest = NULL;
@@ -11870,15 +12285,20 @@
* is supported for this dialog. */
static int add_supported(struct sip_pvt *pvt, struct sip_request *req)
{
- char supported_value[SIPBUFSIZE];
- int res;
+ struct ast_str *supported = ast_str_alloca(128);
- sprintf(supported_value, "replaces%s%s",
- (st_get_mode(pvt, 0) != SESSION_TIMER_MODE_REFUSE) ? ", timer" : "",
- ast_test_flag(&pvt->flags[0], SIP_USEPATH) ? ", path" : "");
- res = add_header(req, "Supported", supported_value);
+ ast_str_append(&supported, -1, "replaces");
+ if (st_get_mode(pvt, 0) != SESSION_TIMER_MODE_REFUSE) {
+ ast_str_append(&supported, -1, ",timer");
+ }
+ if (ast_test_flag(&pvt->flags[0], SIP_USEPATH)) {
+ ast_str_append(&supported, -1, ",path");
+ }
+ if (ast_test_flag(&pvt->flags[1], SIP_PAGE2_CISCO_USECALLMANAGER)) {
+ ast_str_append(&supported, -1, ",X-cisco-sis-10.0.0");
+ }
- return res;
+ return add_header(req, "Supported", ast_str_buffer(supported));
}
/*! \brief Add header to SIP message */
@@ -12539,8 +12959,11 @@
ast_clear_flag(&p->flags[1], SIP_PAGE2_CONNECTLINEUPDATE_PEND);
add_rpid(&resp, p);
}
+ if (p->method == SIP_INVITE) {
+ add_remotecc_call_info(&resp, p);
+ }
if (ast_test_flag(&p->flags[0], SIP_OFFER_CC)) {
- add_cc_call_info_to_response(p, &resp);
+ add_cc_call_info(&resp, p);
}
/* If we are sending a 302 Redirect we can add a diversion header if the redirect information is set */
@@ -12787,6 +13210,36 @@
return send_response(p, &resp, reliable, seqno);
}
+/*! \brief Respond with an optionind response */
+static int transmit_response_with_optionsind(struct sip_pvt *p, const struct sip_request *req)
+{
+ struct sip_request resp;
+
+ respprep(&resp, p, "200 OK", req);
+
+ add_header(&resp, "Content-Type", "application/x-cisco-remotecc-response+xml");
+ add_date(&resp);
+
+ add_content(&resp, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
+ add_content(&resp, "<x-cisco-remotecc-response>\n");
+ add_content(&resp, "<response>\n");
+ add_content(&resp, "<code>200</code>\n");
+ add_content(&resp, "<optionsind>\n");
+ add_content(&resp, "<combine max=\"6\">\n");
+ add_content(&resp, "<remotecc><status /></remotecc>\n");
+ add_content(&resp, "<service-control />\n");
+ add_content(&resp, "</combine>\n");
+ add_content(&resp, "<dialog usage=\"hook status\"><unot /></dialog>\n");
+ add_content(&resp, "<dialog usage=\"shared line\"><unot /></dialog>\n");
+ add_content(&resp, "<presence usage=\"blf speed dial\"><unot /></presence>\n");
+ add_content(&resp, "<joinreq></joinreq>\n");