6 * Copyright (C) 2011-2016 SIPE Project <http://sipe.sourceforge.net/>
7 * Copyright (C) 2010 Jakub Adam <jakub.adam@ktknet.cz>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
34 #include "sipe-common.h"
36 #include "sip-transport.h"
37 #include "sipe-backend.h"
39 #include "sipe-chat.h"
40 #include "sipe-conf.h"
41 #include "sipe-core.h"
42 #include "sipe-core-private.h"
43 #include "sipe-dialog.h"
44 #include "sipe-media.h"
45 #include "sipe-ocs2007.h"
46 #include "sipe-session.h"
47 #include "sipe-utils.h"
49 #include "sipe-schedule.h"
52 struct sipe_media_call_private
{
53 struct sipe_media_call
public;
55 /* private part starts here */
56 struct sipe_core_private
*sipe_private
;
58 struct sip_session
*conference_session
;
62 struct sipmsg
*invitation
;
63 SipeIceVersion ice_version
;
64 gboolean encryption_compatible
;
65 gchar
*extra_invite_section
;
66 gchar
*invite_content_type
;
71 #define SIPE_MEDIA_CALL ((struct sipe_media_call *) call_private)
72 #define SIPE_MEDIA_CALL_PRIVATE ((struct sipe_media_call_private *) call)
74 struct sipe_media_stream_private
{
75 struct sipe_media_stream
public;
77 guchar
*encryption_key
;
78 int encryption_key_id
;
79 gboolean remote_candidates_and_codecs_set
;
90 /* User data associated with the stream. */
92 GDestroyNotify data_free_func
;
94 #define SIPE_MEDIA_STREAM ((struct sipe_media_stream *) stream_private)
95 #define SIPE_MEDIA_STREAM_PRIVATE ((struct sipe_media_stream_private *) stream)
97 struct async_read_data
{
100 sipe_media_stream_read_callback callback
;
103 static void sipe_media_codec_list_free(GList
*codecs
)
105 for (; codecs
; codecs
= g_list_delete_link(codecs
, codecs
))
106 sipe_backend_codec_free(codecs
->data
);
109 static void sipe_media_candidate_list_free(GList
*candidates
)
111 for (; candidates
; candidates
= g_list_delete_link(candidates
, candidates
))
112 sipe_backend_candidate_free(candidates
->data
);
116 remove_stream(struct sipe_media_call
* call
,
117 struct sipe_media_stream_private
*stream_private
)
119 struct sipe_media_call_private
*call_private
= SIPE_MEDIA_CALL_PRIVATE
;
121 sipe_media_stream_set_data(SIPE_MEDIA_STREAM
, NULL
, NULL
);
123 call_private
->streams
=
124 g_slist_remove(call_private
->streams
, stream_private
);
125 sipe_backend_media_stream_free(SIPE_MEDIA_STREAM
->backend_private
);
126 g_free(SIPE_MEDIA_STREAM
->id
);
127 g_free(stream_private
->encryption_key
);
128 g_queue_free_full(stream_private
->write_queue
,
129 (GDestroyNotify
)g_byte_array_unref
);
130 g_queue_free_full(stream_private
->async_reads
, g_free
);
131 sipe_utils_nameval_free(stream_private
->extra_sdp
);
132 g_free(stream_private
);
136 call_private_equals(SIPE_UNUSED_PARAMETER
const gchar
*callid
,
137 struct sipe_media_call_private
*call_private1
,
138 struct sipe_media_call_private
*call_private2
)
140 return call_private1
== call_private2
;
144 sipe_media_call_free(struct sipe_media_call_private
*call_private
)
147 struct sip_session
*session
;
149 g_hash_table_foreach_remove(call_private
->sipe_private
->media_calls
,
150 (GHRFunc
) call_private_equals
, call_private
);
152 while (call_private
->streams
) {
153 remove_stream(SIPE_MEDIA_CALL
,
154 call_private
->streams
->data
);
157 sipe_backend_media_free(call_private
->public.backend_private
);
159 session
= sipe_session_find_call(call_private
->sipe_private
,
160 SIPE_MEDIA_CALL
->with
);
162 sipe_session_remove(call_private
->sipe_private
, session
);
164 if (call_private
->invitation
)
165 sipmsg_free(call_private
->invitation
);
167 // Frees any referenced extra invite data.
168 sipe_media_add_extra_invite_section(SIPE_MEDIA_CALL
, NULL
, NULL
);
170 sdpmsg_free(call_private
->smsg
);
171 sipe_utils_slist_free_full(call_private
->failed_media
,
172 (GDestroyNotify
)sdpmedia_free
);
173 g_free(SIPE_MEDIA_CALL
->with
);
174 g_free(call_private
);
179 candidate_sort_cb(struct sdpcandidate
*c1
, struct sdpcandidate
*c2
)
181 int cmp
= sipe_strcompare(c1
->foundation
, c2
->foundation
);
183 cmp
= sipe_strcompare(c1
->username
, c2
->username
);
185 cmp
= c1
->component
- c2
->component
;
192 backend_candidates_to_sdpcandidate(GList
*candidates
)
194 GSList
*result
= NULL
;
197 for (i
= candidates
; i
; i
= i
->next
) {
198 struct sipe_backend_candidate
*candidate
= i
->data
;
199 struct sdpcandidate
*c
;
201 gchar
*ip
= sipe_backend_candidate_get_ip(candidate
);
202 gchar
*base_ip
= sipe_backend_candidate_get_base_ip(candidate
);
203 if (is_empty(ip
) || strchr(ip
, ':') ||
204 (base_ip
&& strchr(base_ip
, ':'))) {
205 /* Ignore IPv6 candidates. */
211 c
= g_new(struct sdpcandidate
, 1);
212 c
->foundation
= sipe_backend_candidate_get_foundation(candidate
);
213 c
->component
= sipe_backend_candidate_get_component_type(candidate
);
214 c
->type
= sipe_backend_candidate_get_type(candidate
);
215 c
->protocol
= sipe_backend_candidate_get_protocol(candidate
);
217 c
->port
= sipe_backend_candidate_get_port(candidate
);
218 c
->base_ip
= base_ip
;
219 c
->base_port
= sipe_backend_candidate_get_base_port(candidate
);
220 c
->priority
= sipe_backend_candidate_get_priority(candidate
);
221 c
->username
= sipe_backend_candidate_get_username(candidate
);
222 c
->password
= sipe_backend_candidate_get_password(candidate
);
224 result
= g_slist_insert_sorted(result
, c
,
225 (GCompareFunc
)candidate_sort_cb
);
232 get_stream_ip_and_ports(GSList
*candidates
,
233 gchar
**ip
, guint
*rtp_port
, guint
*rtcp_port
)
235 guint32 rtp_max_priority
= 0;
236 guint32 rtcp_max_priority
= 0;
242 for (; candidates
; candidates
= candidates
->next
) {
243 struct sdpcandidate
*candidate
= candidates
->data
;
245 if (candidate
->component
== SIPE_COMPONENT_RTP
&&
246 candidate
->priority
> rtp_max_priority
) {
247 rtp_max_priority
= candidate
->priority
;
248 *rtp_port
= candidate
->port
;
251 *ip
= g_strdup(candidate
->ip
);
252 } else if (candidate
->component
== SIPE_COMPONENT_RTCP
&&
253 candidate
->priority
> rtcp_max_priority
) {
254 rtcp_max_priority
= candidate
->priority
;
255 *rtcp_port
= candidate
->port
;
261 sdpcodec_compare(gconstpointer a
, gconstpointer b
)
263 return ((const struct sdpcodec
*)a
)->id
-
264 ((const struct sdpcodec
*)b
)->id
;
268 remove_wrong_farstream_0_1_tcp_candidates(GList
*candidates
)
270 GList
*i
= candidates
;
271 GHashTable
*foundation_to_candidate
= g_hash_table_new_full(g_str_hash
,
277 GList
*next
= i
->next
;
278 struct sipe_backend_candidate
*c1
= i
->data
;
280 if (sipe_backend_candidate_get_protocol(c1
) == SIPE_NETWORK_PROTOCOL_UDP
) {
281 gchar
*foundation
= sipe_backend_candidate_get_foundation(c1
);
282 struct sipe_backend_candidate
*c2
= g_hash_table_lookup(foundation_to_candidate
,
288 if (sipe_backend_candidate_get_port(c1
) ==
289 sipe_backend_candidate_get_port(c2
) ||
290 (sipe_backend_candidate_get_type(c1
) !=
291 SIPE_CANDIDATE_TYPE_HOST
&&
292 sipe_backend_candidate_get_base_port(c1
) ==
293 sipe_backend_candidate_get_base_port(c2
))) {
295 * We assume that RTP+RTCP UDP pairs
296 * that share the same port are
297 * actually mistagged TCP candidates.
299 candidates
= g_list_remove(candidates
, c2
);
300 candidates
= g_list_delete_link(candidates
, i
);
301 sipe_backend_candidate_free(c1
);
302 sipe_backend_candidate_free(c2
);
305 /* hash table takes ownership of "foundation" */
306 g_hash_table_insert(foundation_to_candidate
, foundation
, c1
);
312 g_hash_table_destroy(foundation_to_candidate
);
318 fill_zero_tcp_act_ports_from_tcp_pass(GSList
*candidates
, GSList
*all_candidates
)
321 GHashTable
*ip_to_port
= g_hash_table_new(g_str_hash
, g_str_equal
);
323 for (i
= candidates
; i
; i
= i
->next
) {
324 struct sdpcandidate
*c
= i
->data
;
327 if (c
->protocol
!= SIPE_NETWORK_PROTOCOL_TCP_ACTIVE
) {
331 for (j
= all_candidates
; j
; j
= j
->next
) {
332 struct sdpcandidate
*passive
= j
->data
;
333 if (passive
->protocol
!= SIPE_NETWORK_PROTOCOL_TCP_PASSIVE
||
334 c
->type
!= passive
->type
) {
338 if (sipe_strequal(c
->ip
, passive
->ip
) &&
339 sipe_strequal(c
->base_ip
, passive
->base_ip
)) {
341 c
->port
= passive
->port
;
344 if (c
->base_port
== 0) {
345 c
->base_port
= passive
->base_port
;
352 for (i
= all_candidates
; i
; i
= i
->next
) {
353 struct sdpcandidate
*c
= i
->data
;
355 if (c
->protocol
== SIPE_NETWORK_PROTOCOL_TCP_PASSIVE
&&
356 c
->type
== SIPE_CANDIDATE_TYPE_HOST
) {
357 g_hash_table_insert(ip_to_port
, c
->ip
, &c
->port
);
361 /* Fill base ports of all TCP relay candidates using what we have
362 * collected from host candidates. */
363 for (i
= candidates
; i
; i
= i
->next
) {
364 struct sdpcandidate
*c
= i
->data
;
365 if (c
->type
== SIPE_CANDIDATE_TYPE_RELAY
&& c
->base_port
== 0) {
366 guint
*base_port
= (guint
*)g_hash_table_lookup(ip_to_port
, c
->base_ip
);
368 c
->base_port
= *base_port
;
370 SIPE_DEBUG_WARNING("Couldn't determine base port for candidate "
371 "with foundation %s", c
->foundation
);
376 g_hash_table_destroy(ip_to_port
);
379 static SipeEncryptionPolicy
380 get_encryption_policy(struct sipe_core_private
*sipe_private
)
382 SipeEncryptionPolicy result
=
383 sipe_backend_media_get_encryption_policy(SIPE_CORE_PUBLIC
);
384 if (result
== SIPE_ENCRYPTION_POLICY_OBEY_SERVER
) {
385 result
= sipe_private
->server_av_encryption_policy
;
391 static struct sdpmedia
*
392 media_stream_to_sdpmedia(struct sipe_media_call_private
*call_private
,
393 struct sipe_media_stream_private
*stream_private
)
395 struct sdpmedia
*sdpmedia
= g_new0(struct sdpmedia
, 1);
396 GList
*codecs
= sipe_backend_get_local_codecs(SIPE_MEDIA_CALL
,
398 SipeEncryptionPolicy encryption_policy
=
399 get_encryption_policy(call_private
->sipe_private
);
402 GSList
*attributes
= NULL
;
403 GSList
*sdpcandidates
;
404 GSList
*all_sdpcandidates
;
409 sdpmedia
->name
= g_strdup(SIPE_MEDIA_STREAM
->id
);
411 if (sipe_strequal(sdpmedia
->name
, "audio"))
412 type
= SIPE_MEDIA_AUDIO
;
413 else if (sipe_strequal(sdpmedia
->name
, "video"))
414 type
= SIPE_MEDIA_VIDEO
;
415 else if (sipe_strequal(sdpmedia
->name
, "data"))
416 type
= SIPE_MEDIA_APPLICATION
;
418 // TODO: incompatible media, should not happen here
419 g_free(sdpmedia
->name
);
421 sipe_media_codec_list_free(codecs
);
426 for (i
= codecs
; i
; i
= i
->next
) {
427 struct sipe_backend_codec
*codec
= i
->data
;
428 struct sdpcodec
*c
= g_new0(struct sdpcodec
, 1);
431 c
->id
= sipe_backend_codec_get_id(codec
);
432 c
->name
= sipe_backend_codec_get_name(codec
);
433 c
->clock_rate
= sipe_backend_codec_get_clock_rate(codec
);
436 params
= sipe_backend_codec_get_optional_parameters(codec
);
437 for (; params
; params
= params
->next
) {
438 struct sipnameval
*param
= params
->data
;
439 struct sipnameval
*copy
= g_new0(struct sipnameval
, 1);
441 copy
->name
= g_strdup(param
->name
);
442 copy
->value
= g_strdup(param
->value
);
444 c
->parameters
= g_slist_append(c
->parameters
, copy
);
447 /* Buggy(?) codecs may report non-unique id (a.k.a. payload
448 * type) that must not appear in SDP messages we send. Thus,
449 * let's ignore any codec having the same id as one we already
450 * have in the converted list. */
451 sdpmedia
->codecs
= sipe_utils_slist_insert_unique_sorted(
452 sdpmedia
->codecs
, c
, sdpcodec_compare
,
453 (GDestroyNotify
)sdpcodec_free
);
456 sipe_media_codec_list_free(codecs
);
458 // Process local candidates
459 // If we have established candidate pairs, send them in SDP response.
460 // Otherwise send all available local candidates.
461 candidates
= sipe_backend_media_stream_get_active_local_candidates(SIPE_MEDIA_STREAM
);
462 sdpcandidates
= backend_candidates_to_sdpcandidate(candidates
);
463 sipe_media_candidate_list_free(candidates
);
465 candidates
= sipe_backend_get_local_candidates(SIPE_MEDIA_CALL
,
467 candidates
= remove_wrong_farstream_0_1_tcp_candidates(candidates
);
468 all_sdpcandidates
= backend_candidates_to_sdpcandidate(candidates
);
469 sipe_media_candidate_list_free(candidates
);
471 if (!sdpcandidates
) {
472 sdpcandidates
= all_sdpcandidates
;
475 fill_zero_tcp_act_ports_from_tcp_pass(sdpcandidates
, all_sdpcandidates
);
477 sdpmedia
->candidates
= sdpcandidates
;
479 if (all_sdpcandidates
!= sdpcandidates
) {
480 sipe_utils_slist_free_full(all_sdpcandidates
,
481 (GDestroyNotify
)sdpcandidate_free
);
484 get_stream_ip_and_ports(sdpmedia
->candidates
, &sdpmedia
->ip
,
485 &sdpmedia
->port
, &rtcp_port
);
487 if (sipe_backend_stream_is_held(SIPE_MEDIA_STREAM
))
488 attributes
= sipe_utils_nameval_add(attributes
, "inactive", "");
491 gchar
*tmp
= g_strdup_printf("%u", rtcp_port
);
492 attributes
= sipe_utils_nameval_add(attributes
, "rtcp", tmp
);
496 if (encryption_policy
!= call_private
->sipe_private
->server_av_encryption_policy
) {
497 const gchar
*encryption
= NULL
;
498 switch (encryption_policy
) {
499 case SIPE_ENCRYPTION_POLICY_REJECTED
:
500 encryption
= "rejected";
502 case SIPE_ENCRYPTION_POLICY_OPTIONAL
:
503 encryption
= "optional";
505 case SIPE_ENCRYPTION_POLICY_REQUIRED
:
507 encryption
= "required";
511 attributes
= sipe_utils_nameval_add(attributes
, "encryption", encryption
);
514 // Process remote candidates
515 candidates
= sipe_backend_media_stream_get_active_remote_candidates(SIPE_MEDIA_STREAM
);
516 sdpmedia
->remote_candidates
= backend_candidates_to_sdpcandidate(candidates
);
517 sipe_media_candidate_list_free(candidates
);
519 sdpmedia
->encryption_active
= stream_private
->encryption_key
&&
520 call_private
->encryption_compatible
&&
521 stream_private
->remote_candidates_and_codecs_set
&&
522 encryption_policy
!= SIPE_ENCRYPTION_POLICY_REJECTED
;
524 // Set our key if encryption is enabled.
525 if (stream_private
->encryption_key
&&
526 encryption_policy
!= SIPE_ENCRYPTION_POLICY_REJECTED
) {
527 sdpmedia
->encryption_key
= g_memdup(stream_private
->encryption_key
,
529 sdpmedia
->encryption_key_id
= stream_private
->encryption_key_id
;
532 // Append extra attributes assigned to the stream.
533 for (j
= stream_private
->extra_sdp
; j
; j
= g_slist_next(j
)) {
534 struct sipnameval
*attr
= j
->data
;
535 attributes
= sipe_utils_nameval_add(attributes
,
536 attr
->name
, attr
->value
);
539 sdpmedia
->attributes
= attributes
;
544 static struct sdpmsg
*
545 sipe_media_to_sdpmsg(struct sipe_media_call_private
*call_private
)
547 struct sdpmsg
*msg
= g_new0(struct sdpmsg
, 1);
548 GSList
*streams
= call_private
->streams
;
550 for (; streams
; streams
= streams
->next
) {
551 struct sdpmedia
*media
= media_stream_to_sdpmedia(call_private
,
554 msg
->media
= g_slist_append(msg
->media
, media
);
557 msg
->ip
= g_strdup(media
->ip
);
561 msg
->media
= g_slist_concat(msg
->media
, call_private
->failed_media
);
562 call_private
->failed_media
= NULL
;
564 msg
->ice_version
= call_private
->ice_version
;
570 sipe_invite_call(struct sipe_media_call_private
*call_private
, TransCallback tc
)
572 struct sipe_core_private
*sipe_private
= call_private
->sipe_private
;
575 gchar
*p_preferred_identity
= NULL
;
577 struct sip_session
*session
;
578 struct sip_dialog
*dialog
;
581 session
= sipe_session_find_call(sipe_private
, SIPE_MEDIA_CALL
->with
);
582 dialog
= session
->dialogs
->data
;
584 contact
= get_contact(sipe_private
);
586 if (sipe_private
->uc_line_uri
) {
587 gchar
*self
= sip_uri_self(sipe_private
);
588 p_preferred_identity
= g_strdup_printf(
589 "P-Preferred-Identity: <%s>, <%s>\r\n",
590 self
, sipe_private
->uc_line_uri
);
594 hdr
= g_strdup_printf(
595 "ms-keep-alive: UAC;hop-hop=yes\r\n"
598 "Content-Type: %s%s\r\n",
600 p_preferred_identity
? p_preferred_identity
: "",
601 call_private
->invite_content_type
?
602 call_private
->invite_content_type
: "application/sdp",
603 call_private
->invite_content_type
?
604 ";boundary=\"----=_NextPart_000_001E_01CB4397.0B5EB570\"" : "");
607 g_free(p_preferred_identity
);
609 msg
= sipe_media_to_sdpmsg(call_private
);
610 body
= sdpmsg_to_string(msg
);
612 if (call_private
->extra_invite_section
) {
614 tmp
= g_strdup_printf(
615 "------=_NextPart_000_001E_01CB4397.0B5EB570\r\n"
618 "------=_NextPart_000_001E_01CB4397.0B5EB570\r\n"
619 "Content-Type: application/sdp\r\n"
620 "Content-Transfer-Encoding: 7bit\r\n"
621 "Content-Disposition: session; handling=optional\r\n"
625 "------=_NextPart_000_001E_01CB4397.0B5EB570--\r\n",
626 call_private
->extra_invite_section
, body
);
629 sipe_media_add_extra_invite_section(SIPE_MEDIA_CALL
, NULL
, NULL
);
634 dialog
->outgoing_invite
= sip_transport_invite(sipe_private
,
645 send_response_with_session_description(struct sipe_media_call_private
*call_private
, int code
, gchar
*text
)
647 struct sdpmsg
*msg
= sipe_media_to_sdpmsg(call_private
);
648 gchar
*body
= sdpmsg_to_string(msg
);
650 sipmsg_add_header(call_private
->invitation
, "Content-Type", "application/sdp");
651 sip_transport_response(call_private
->sipe_private
, call_private
->invitation
, code
, text
, body
);
656 process_invite_call_response(struct sipe_core_private
*sipe_private
,
658 struct transaction
*trans
);
660 struct sipe_media_stream
*
661 sipe_core_media_get_stream_by_id(struct sipe_media_call
*call
, const gchar
*id
)
664 for (i
= SIPE_MEDIA_CALL_PRIVATE
->streams
; i
; i
= i
->next
) {
665 struct sipe_media_stream
*stream
= i
->data
;
666 if (sipe_strequal(stream
->id
, id
))
673 update_call_from_remote_sdp(struct sipe_media_call_private
* call_private
,
674 struct sdpmedia
*media
)
676 struct sipe_media_stream
*stream
;
677 GList
*backend_candidates
= NULL
;
678 GList
*backend_codecs
= NULL
;
680 gboolean result
= TRUE
;
682 stream
= sipe_core_media_get_stream_by_id(SIPE_MEDIA_CALL
, media
->name
);
683 if (media
->port
== 0) {
685 sipe_backend_media_stream_end(SIPE_MEDIA_CALL
, stream
);
693 if (sipe_utils_nameval_find(media
->attributes
, "inactive")) {
694 sipe_backend_stream_hold(SIPE_MEDIA_CALL
, stream
, FALSE
);
695 } else if (sipe_backend_stream_is_held(stream
)) {
696 sipe_backend_stream_unhold(SIPE_MEDIA_CALL
, stream
, FALSE
);
699 if (SIPE_MEDIA_STREAM_PRIVATE
->remote_candidates_and_codecs_set
) {
703 for (i
= media
->codecs
; i
; i
= i
->next
) {
704 struct sdpcodec
*c
= i
->data
;
705 struct sipe_backend_codec
*codec
;
708 codec
= sipe_backend_codec_new(c
->id
,
713 for (j
= c
->parameters
; j
; j
= j
->next
) {
714 struct sipnameval
*attr
= j
->data
;
716 sipe_backend_codec_add_optional_parameter(codec
,
721 backend_codecs
= g_list_append(backend_codecs
, codec
);
724 if (media
->encryption_key
&& SIPE_MEDIA_STREAM_PRIVATE
->encryption_key
) {
725 sipe_backend_media_set_encryption_keys(SIPE_MEDIA_CALL
, stream
,
726 SIPE_MEDIA_STREAM_PRIVATE
->encryption_key
,
727 media
->encryption_key
);
728 SIPE_MEDIA_STREAM_PRIVATE
->encryption_key_id
= media
->encryption_key_id
;
731 result
= sipe_backend_set_remote_codecs(SIPE_MEDIA_CALL
, stream
,
733 sipe_media_codec_list_free(backend_codecs
);
735 if (result
== FALSE
) {
736 sipe_backend_media_stream_end(SIPE_MEDIA_CALL
, stream
);
740 for (i
= media
->candidates
; i
; i
= i
->next
) {
741 struct sdpcandidate
*c
= i
->data
;
742 struct sipe_backend_candidate
*candidate
;
743 candidate
= sipe_backend_candidate_new(c
->foundation
,
751 sipe_backend_candidate_set_priority(candidate
, c
->priority
);
753 backend_candidates
= g_list_append(backend_candidates
, candidate
);
756 sipe_backend_media_add_remote_candidates(SIPE_MEDIA_CALL
, stream
,
758 sipe_media_candidate_list_free(backend_candidates
);
760 SIPE_MEDIA_STREAM_PRIVATE
->remote_candidates_and_codecs_set
= TRUE
;
766 apply_remote_message(struct sipe_media_call_private
* call_private
,
771 sipe_utils_slist_free_full(call_private
->failed_media
, (GDestroyNotify
)sdpmedia_free
);
772 call_private
->failed_media
= NULL
;
773 call_private
->encryption_compatible
= TRUE
;
775 for (i
= msg
->media
; i
; i
= i
->next
) {
776 struct sdpmedia
*media
= i
->data
;
777 const gchar
*enc_level
=
778 sipe_utils_nameval_find(media
->attributes
, "encryption");
779 if (sipe_strequal(enc_level
, "rejected") &&
780 get_encryption_policy(call_private
->sipe_private
) == SIPE_ENCRYPTION_POLICY_REQUIRED
) {
781 call_private
->encryption_compatible
= FALSE
;
784 if (!update_call_from_remote_sdp(call_private
, media
)) {
786 call_private
->failed_media
=
787 g_slist_append(call_private
->failed_media
, media
);
791 /* We need to keep failed medias until response is sent, remove them
792 * from sdpmsg that is to be freed. */
793 for (i
= call_private
->failed_media
; i
; i
= i
->next
) {
794 msg
->media
= g_slist_remove(msg
->media
, i
->data
);
799 call_initialized(struct sipe_media_call
*call
)
801 GSList
*streams
= SIPE_MEDIA_CALL_PRIVATE
->streams
;
802 for (; streams
; streams
= streams
->next
) {
803 if (!sipe_backend_stream_initialized(call
, streams
->data
)) {
811 // Sends an invite response when the call is accepted and local candidates were
812 // prepared, otherwise does nothing. If error response is sent, call_private is
813 // disposed before function returns.
815 maybe_send_first_invite_response(struct sipe_media_call_private
*call_private
)
817 struct sipe_backend_media
*backend_media
;
819 backend_media
= call_private
->public.backend_private
;
821 if (!sipe_backend_media_accepted(backend_media
) ||
822 !call_initialized(&call_private
->public))
825 if (!call_private
->encryption_compatible
) {
826 struct sipe_core_private
*sipe_private
= call_private
->sipe_private
;
828 sipmsg_add_header(call_private
->invitation
, "Warning",
829 "308 lcs.microsoft.com \"Encryption Levels not compatible\"");
830 sip_transport_response(sipe_private
,
831 call_private
->invitation
,
832 488, "Encryption Levels not compatible",
834 sipe_backend_media_reject(backend_media
, FALSE
);
835 sipe_backend_notify_error(SIPE_CORE_PUBLIC
,
836 _("Unable to establish a call"),
837 _("Encryption settings of peer are incompatible with ours."));
839 send_response_with_session_description(call_private
, 200, "OK");
840 sipmsg_free(call_private
->invitation
);
841 call_private
->invitation
= NULL
;
846 stream_initialized_cb(struct sipe_media_call
*call
,
847 struct sipe_media_stream
*stream
)
849 if (call_initialized(call
)) {
850 struct sipe_media_call_private
*call_private
= SIPE_MEDIA_CALL_PRIVATE
;
852 if (sipe_backend_media_is_initiator(call
, stream
)) {
853 sipe_invite_call(call_private
,
854 process_invite_call_response
);
855 } else if (call_private
->smsg
) {
856 struct sdpmsg
*smsg
= call_private
->smsg
;
857 call_private
->smsg
= NULL
;
859 apply_remote_message(call_private
, smsg
);
860 maybe_send_first_invite_response(call_private
);
866 static void phone_state_publish(struct sipe_core_private
*sipe_private
)
868 if (SIPE_CORE_PRIVATE_FLAG_IS(OCS2007
)) {
869 sipe_ocs2007_phone_state_publish(sipe_private
);
871 // TODO: OCS 2005 support. Is anyone still using it at all?
876 stream_end_cb(struct sipe_media_call
* call
, struct sipe_media_stream
* stream
)
878 remove_stream(call
, SIPE_MEDIA_STREAM_PRIVATE
);
882 media_end_cb(struct sipe_media_call
*call
)
884 struct sipe_core_private
*sipe_private
;
886 g_return_if_fail(call
);
888 sipe_private
= SIPE_MEDIA_CALL_PRIVATE
->sipe_private
;
890 sipe_media_call_free(SIPE_MEDIA_CALL_PRIVATE
);
891 phone_state_publish(sipe_private
);
895 call_accept_cb(struct sipe_media_call
*call
, gboolean local
)
898 maybe_send_first_invite_response(SIPE_MEDIA_CALL_PRIVATE
);
900 phone_state_publish(SIPE_MEDIA_CALL_PRIVATE
->sipe_private
);
904 call_reject_cb(struct sipe_media_call
*call
, gboolean local
)
907 struct sipe_media_call_private
*call_private
= SIPE_MEDIA_CALL_PRIVATE
;
908 struct sip_session
*session
= NULL
;
910 sip_transport_response(call_private
->sipe_private
,
911 call_private
->invitation
,
912 603, "Decline", NULL
);
914 session
= sipe_session_find_call(call_private
->sipe_private
,
917 sipe_session_remove(call_private
->sipe_private
, session
);
923 av_call_reject_cb(struct sipe_media_call
*call
, gboolean local
)
926 struct sipe_core_private
*sipe_private
;
929 sipe_private
= SIPE_MEDIA_CALL_PRIVATE
->sipe_private
;
931 desc
= g_strdup_printf(_("User %s rejected call"), call
->with
);
932 sipe_backend_notify_error(SIPE_CORE_PUBLIC
, _("Call rejected"),
937 call_reject_cb(call
, local
);
941 sipe_media_send_ack(struct sipe_core_private
*sipe_private
, struct sipmsg
*msg
,
942 struct transaction
*trans
);
944 static void call_hold_cb(struct sipe_media_call
*call
,
946 SIPE_UNUSED_PARAMETER gboolean state
)
949 sipe_invite_call(SIPE_MEDIA_CALL_PRIVATE
, sipe_media_send_ack
);
953 static void call_hangup_cb(struct sipe_media_call
*call
, gboolean local
)
956 struct sipe_media_call_private
*call_private
= SIPE_MEDIA_CALL_PRIVATE
;
957 struct sip_session
*session
;
958 session
= sipe_session_find_call(call_private
->sipe_private
,
962 sipe_session_close(call_private
->sipe_private
, session
);
968 error_cb(struct sipe_media_call
*call
, gchar
*message
)
970 struct sipe_media_call_private
*call_private
= SIPE_MEDIA_CALL_PRIVATE
;
971 struct sipe_core_private
*sipe_private
= call_private
->sipe_private
;
972 gboolean initiator
= sipe_backend_media_is_initiator(call
, NULL
);
973 gboolean accepted
= sipe_backend_media_accepted(call
->backend_private
);
975 gchar
*title
= g_strdup_printf("Call with %s failed", call
->with
);
976 sipe_backend_notify_error(SIPE_CORE_PUBLIC
, title
, message
);
979 if (!initiator
&& !accepted
) {
980 sip_transport_response(sipe_private
,
981 call_private
->invitation
,
982 488, "Not Acceptable Here", NULL
);
985 sipe_backend_media_hangup(call
->backend_private
, initiator
|| accepted
);
988 struct sipe_media_call
*
989 sipe_media_call_new(struct sipe_core_private
*sipe_private
, const gchar
* with
,
990 struct sipmsg
*msg
, SipeIceVersion ice_version
,
991 SipeMediaCallFlags flags
)
993 struct sipe_media_call_private
*call_private
;
994 struct sip_session
*session
;
995 struct sip_dialog
*dialog
;
998 session
= sipe_session_add_call(sipe_private
, with
);
1000 dialog
= sipe_dialog_add(session
);
1001 dialog
->with
= g_strdup(with
);
1004 gchar
*newTag
= gentag();
1005 const gchar
*oldHeader
;
1008 oldHeader
= sipmsg_find_header(msg
, "To");
1009 newHeader
= g_strdup_printf("%s;tag=%s", oldHeader
, newTag
);
1010 sipmsg_remove_header_now(msg
, "To");
1011 sipmsg_add_header_now(msg
, "To", newHeader
);
1015 dialog
->callid
= g_strdup(sipmsg_find_header(msg
, "Call-ID"));
1016 sipe_dialog_parse(dialog
, msg
, FALSE
);
1018 dialog
->callid
= gencallid();
1019 dialog
->ourtag
= gentag();
1020 flags
|= SIPE_MEDIA_CALL_INITIATOR
;
1023 if (g_hash_table_lookup(sipe_private
->media_calls
, dialog
->callid
)) {
1024 SIPE_DEBUG_ERROR("sipe_media_call_new: call already exists for "
1025 "Call-ID %s", dialog
->callid
);
1026 sipe_session_remove(sipe_private
, session
);
1030 call_private
= g_new0(struct sipe_media_call_private
, 1);
1031 call_private
->sipe_private
= sipe_private
;
1032 SIPE_MEDIA_CALL
->with
= g_strdup(with
);
1034 g_hash_table_insert(sipe_private
->media_calls
,
1035 g_strdup(dialog
->callid
), call_private
);
1037 cname
= g_strdup(sipe_private
->contact
+ 1);
1038 cname
[strlen(cname
) - 1] = '\0';
1040 call_private
->public.backend_private
= sipe_backend_media_new(SIPE_CORE_PUBLIC
,
1044 sipe_backend_media_set_cname(call_private
->public.backend_private
, cname
);
1046 call_private
->ice_version
= ice_version
;
1047 call_private
->encryption_compatible
= TRUE
;
1049 call_private
->public.stream_initialized_cb
= stream_initialized_cb
;
1050 call_private
->public.stream_end_cb
= stream_end_cb
;
1051 call_private
->public.media_end_cb
= media_end_cb
;
1052 call_private
->public.call_accept_cb
= call_accept_cb
;
1053 call_private
->public.call_reject_cb
= call_reject_cb
;
1054 call_private
->public.call_hold_cb
= call_hold_cb
;
1055 call_private
->public.call_hangup_cb
= call_hangup_cb
;
1056 call_private
->public.error_cb
= error_cb
;
1060 return SIPE_MEDIA_CALL
;
1063 void sipe_media_hangup(struct sipe_media_call_private
*call_private
)
1066 sipe_backend_media_hangup(call_private
->public.backend_private
,
1071 struct sipe_media_stream
*
1072 sipe_media_stream_add(struct sipe_media_call
*call
, const gchar
*id
,
1073 SipeMediaType type
, SipeIceVersion ice_version
,
1076 struct sipe_core_private
*sipe_private
;
1077 struct sipe_media_stream_private
*stream_private
;
1078 struct sipe_backend_media_stream
*backend_stream
;
1079 struct sipe_backend_media_relays
*backend_media_relays
;
1081 sipe_private
= SIPE_MEDIA_CALL_PRIVATE
->sipe_private
;
1083 backend_media_relays
= sipe_backend_media_relays_convert(
1084 sipe_private
->media_relays
,
1085 sipe_private
->media_relay_username
,
1086 sipe_private
->media_relay_password
);
1088 backend_stream
= sipe_backend_media_add_stream(call
, id
, call
->with
,
1091 backend_media_relays
);
1093 sipe_backend_media_relays_free(backend_media_relays
);
1095 if (!backend_stream
) {
1099 stream_private
= g_new0(struct sipe_media_stream_private
, 1);
1100 SIPE_MEDIA_STREAM
->call
= call
;
1101 SIPE_MEDIA_STREAM
->id
= g_strdup(id
);
1102 SIPE_MEDIA_STREAM
->backend_private
= backend_stream
;
1107 stream_private
->encryption_key
= g_new0(guchar
, SIPE_SRTP_KEY_LEN
);
1108 for (i
= 0; i
!= SIPE_SRTP_KEY_LEN
; ++i
) {
1109 stream_private
->encryption_key
[i
] = rand() & 0xff;
1111 stream_private
->encryption_key_id
= 1;
1115 stream_private
->write_queue
= g_queue_new();
1116 stream_private
->async_reads
= g_queue_new();
1118 SIPE_MEDIA_CALL_PRIVATE
->streams
=
1119 g_slist_append(SIPE_MEDIA_CALL_PRIVATE
->streams
,
1122 return SIPE_MEDIA_STREAM
;
1126 append_2007_fallback_if_needed(struct sipe_media_call_private
*call_private
)
1128 struct sipe_core_private
*sipe_private
= call_private
->sipe_private
;
1129 const gchar
*ip
= sipe_backend_network_ip_address(SIPE_CORE_PUBLIC
);
1132 if (sipe_media_get_sip_dialog(SIPE_MEDIA_CALL
)->cseq
!= 0 ||
1133 call_private
->ice_version
!= SIPE_ICE_RFC_5245
||
1134 sipe_strequal(SIPE_MEDIA_CALL
->with
, sipe_private
->test_call_bot_uri
)) {
1138 body
= g_strdup_printf("Content-Type: application/sdp\r\n"
1139 "Content-Transfer-Encoding: 7bit\r\n"
1140 "Content-Disposition: session; handling=optional; ms-proxy-2007fallback\r\n"
1142 "o=- 0 0 IN IP4 %s\r\n"
1145 "m=audio 0 RTP/AVP\r\n",
1147 sipe_media_add_extra_invite_section(SIPE_MEDIA_CALL
,
1148 "multipart/alternative", body
);
1152 sipe_media_initiate_call(struct sipe_core_private
*sipe_private
,
1153 const char *with
, SipeIceVersion ice_version
,
1154 gboolean with_video
)
1156 struct sipe_media_call_private
*call_private
;
1158 if (sipe_core_media_get_call(SIPE_CORE_PUBLIC
)) {
1162 call_private
= (struct sipe_media_call_private
*)
1163 sipe_media_call_new(sipe_private
, with
, NULL
,
1166 SIPE_MEDIA_CALL
->call_reject_cb
= av_call_reject_cb
;
1168 if (!sipe_media_stream_add(SIPE_MEDIA_CALL
, "audio", SIPE_MEDIA_AUDIO
,
1169 call_private
->ice_version
,
1171 sipe_backend_notify_error(SIPE_CORE_PUBLIC
,
1173 _("Error creating audio stream"));
1174 sipe_media_hangup(call_private
);
1179 !sipe_media_stream_add(SIPE_MEDIA_CALL
, "video", SIPE_MEDIA_VIDEO
,
1180 call_private
->ice_version
,
1182 sipe_backend_notify_error(SIPE_CORE_PUBLIC
,
1184 _("Error creating video stream"));
1185 sipe_media_hangup(call_private
);
1189 append_2007_fallback_if_needed(call_private
);
1191 // Processing continues in stream_initialized_cb
1195 sipe_core_media_initiate_call(struct sipe_core_public
*sipe_public
,
1197 gboolean with_video
)
1199 sipe_media_initiate_call(SIPE_CORE_PRIVATE
, with
,
1200 SIPE_ICE_RFC_5245
, with_video
);
1204 conference_audio_muted_cb(struct sipe_media_stream
*stream
, gboolean is_muted
)
1206 struct sipe_media_call
*call
= stream
->call
;
1208 if (!SIPE_MEDIA_CALL_PRIVATE
->conference_session
) {
1212 sipe_conf_announce_audio_mute_state(SIPE_MEDIA_CALL_PRIVATE
->sipe_private
,
1213 SIPE_MEDIA_CALL_PRIVATE
->conference_session
,
1217 void sipe_core_media_connect_conference(struct sipe_core_public
*sipe_public
,
1218 struct sipe_chat_session
*chat_session
)
1220 struct sipe_core_private
*sipe_private
= SIPE_CORE_PRIVATE
;
1221 struct sipe_media_call_private
*call_private
;
1222 struct sipe_media_stream
*stream
;
1223 struct sip_session
*session
;
1224 SipeIceVersion ice_version
;
1227 if (!sipe_conf_supports_mcu_type(sipe_private
, "audio-video")) {
1228 sipe_backend_notify_error(sipe_public
, _("Join conference call"),
1229 _("Conference calls are not supported on this server."));
1233 session
= sipe_session_find_chat(sipe_private
, chat_session
);
1235 if (sipe_core_media_get_call(sipe_public
) || !session
) {
1239 av_uri
= sipe_conf_build_uri(chat_session
->id
, "audio-video");
1244 session
->is_call
= TRUE
;
1246 ice_version
= SIPE_CORE_PRIVATE_FLAG_IS(LYNC2013
) ? SIPE_ICE_RFC_5245
:
1249 call_private
= (struct sipe_media_call_private
*)
1250 sipe_media_call_new(sipe_private
, av_uri
, NULL
,
1252 call_private
->conference_session
= session
;
1253 SIPE_MEDIA_CALL
->call_reject_cb
= av_call_reject_cb
;
1255 stream
= sipe_media_stream_add(SIPE_MEDIA_CALL
, "audio",
1257 call_private
->ice_version
,
1260 sipe_backend_notify_error(sipe_public
,
1261 _("Error occurred"),
1262 _("Error creating audio stream"));
1264 sipe_media_hangup(call_private
);
1267 stream
->mute_cb
= conference_audio_muted_cb
;
1271 // Processing continues in stream_initialized_cb
1274 struct sipe_media_call
*
1275 sipe_core_media_get_call(struct sipe_core_public
*sipe_public
)
1277 struct sipe_media_call
* result
= NULL
;
1278 GList
*calls
= g_hash_table_get_values(SIPE_CORE_PRIVATE
->media_calls
);
1280 for (; calls
; calls
= g_list_delete_link(calls
, calls
)) {
1281 if (sipe_core_media_get_stream_by_id(calls
->data
, "audio")) {
1282 result
= calls
->data
;
1290 static gboolean
phone_number_is_valid(const gchar
*phone_number
)
1292 if (!phone_number
|| sipe_strequal(phone_number
, "")) {
1296 if (*phone_number
== '+') {
1300 while (*phone_number
!= '\0') {
1301 if (!g_ascii_isdigit(*phone_number
)) {
1310 void sipe_core_media_phone_call(struct sipe_core_public
*sipe_public
,
1311 const gchar
*phone_number
)
1313 g_return_if_fail(sipe_public
);
1315 if (phone_number_is_valid(phone_number
)) {
1316 gchar
*phone_uri
= g_strdup_printf("sip:%s@%s;user=phone",
1317 phone_number
, sipe_public
->sip_domain
);
1319 sipe_core_media_initiate_call(sipe_public
, phone_uri
, FALSE
);
1323 sipe_backend_notify_error(sipe_public
,
1324 _("Unable to establish a call"),
1325 _("Invalid phone number"));
1329 void sipe_core_media_test_call(struct sipe_core_public
*sipe_public
)
1331 struct sipe_core_private
*sipe_private
= SIPE_CORE_PRIVATE
;
1332 if (!sipe_private
->test_call_bot_uri
) {
1333 sipe_backend_notify_error(sipe_public
,
1334 _("Unable to establish a call"),
1335 _("Audio Test Service is not available."));
1339 sipe_core_media_initiate_call(sipe_public
,
1340 sipe_private
->test_call_bot_uri
, FALSE
);
1343 static struct sipe_media_call_private
*
1344 sipe_media_from_sipmsg(struct sipe_core_private
*sipe_private
,
1347 return g_hash_table_lookup(sipe_private
->media_calls
,
1348 sipmsg_find_header(msg
, "Call-ID"));
1352 transport_response_unsupported_sdp(struct sipe_core_private
*sipe_private
,
1355 sipmsg_add_header(msg
, "ms-client-diagnostics",
1356 "52063;reason=\"Unsupported session description\"");
1357 sip_transport_response(sipe_private
, msg
,
1358 488, "Not Acceptable Here", NULL
);
1362 maybe_send_second_invite_response(struct sipe_media_call_private
*call_private
)
1366 /* Second INVITE request had to be received and all streams must have
1367 * established candidate pairs before the response can be sent. */
1369 if (!call_private
->invitation
) {
1373 for (it
= call_private
->streams
; it
; it
= it
->next
) {
1374 struct sipe_media_stream_private
*stream_private
= it
->data
;
1375 if (!stream_private
->established
) {
1380 send_response_with_session_description(call_private
, 200, "OK");
1383 struct sipe_media_call
*
1384 process_incoming_invite_call(struct sipe_core_private
*sipe_private
,
1387 struct sipe_media_call_private
*call_private
;
1388 struct sdpmsg
*smsg
;
1389 gboolean has_new_media
= FALSE
;
1392 // Don't allow two voice calls in parallel.
1393 if (!strstr(msg
->body
, "m=data") &&
1394 !strstr(msg
->body
, "m=applicationsharing")) {
1395 struct sipe_media_call
*call
=
1396 sipe_core_media_get_call(SIPE_CORE_PUBLIC
);
1397 if (call
&& !is_media_session_msg(SIPE_MEDIA_CALL_PRIVATE
, msg
)) {
1398 sip_transport_response(sipe_private
, msg
,
1399 486, "Busy Here", NULL
);
1404 call_private
= sipe_media_from_sipmsg(sipe_private
, msg
);
1407 char *self
= sip_uri_self(sipe_private
);
1408 if (sipe_strequal(SIPE_MEDIA_CALL
->with
, self
)) {
1410 sip_transport_response(sipe_private
, msg
, 488, "Not Acceptable Here", NULL
);
1416 smsg
= sdpmsg_parse_msg(msg
->body
);
1418 transport_response_unsupported_sdp(sipe_private
, msg
);
1420 sipe_media_hangup(call_private
);
1425 if (!call_private
) {
1426 gchar
*with
= parse_from(sipmsg_find_header(msg
, "From"));
1427 SipeMediaCallFlags flags
= 0;
1429 if (strstr(msg
->body
, "m=data")) {
1430 flags
|= SIPE_MEDIA_CALL_NO_UI
;
1433 call_private
= (struct sipe_media_call_private
*)
1434 sipe_media_call_new(sipe_private
, with
,
1435 msg
, smsg
->ice_version
,
1438 if (!(flags
& SIPE_MEDIA_CALL_NO_UI
)) {
1439 SIPE_MEDIA_CALL
->call_reject_cb
= av_call_reject_cb
;
1444 if (call_private
->invitation
)
1445 sipmsg_free(call_private
->invitation
);
1446 call_private
->invitation
= sipmsg_copy(msg
);
1448 // Create any new media streams
1449 for (i
= smsg
->media
; i
; i
= i
->next
) {
1450 struct sdpmedia
*media
= i
->data
;
1451 gchar
*id
= media
->name
;
1454 if ( media
->port
!= 0
1455 && !sipe_core_media_get_stream_by_id(SIPE_MEDIA_CALL
, id
)) {
1456 if (sipe_strequal(id
, "audio"))
1457 type
= SIPE_MEDIA_AUDIO
;
1458 else if (sipe_strequal(id
, "video"))
1459 type
= SIPE_MEDIA_VIDEO
;
1460 else if (sipe_strequal(id
, "data"))
1461 type
= SIPE_MEDIA_APPLICATION
;
1465 sipe_media_stream_add(SIPE_MEDIA_CALL
, id
, type
,
1466 smsg
->ice_version
, FALSE
);
1467 has_new_media
= TRUE
;
1471 if (has_new_media
) {
1472 sdpmsg_free(call_private
->smsg
);
1473 call_private
->smsg
= smsg
;
1474 sip_transport_response(sipe_private
, call_private
->invitation
,
1475 180, "Ringing", NULL
);
1476 // Processing continues in stream_initialized_cb
1478 apply_remote_message(call_private
, smsg
);
1480 maybe_send_second_invite_response(call_private
);
1483 return SIPE_MEDIA_CALL
;
1486 void process_incoming_cancel_call(struct sipe_media_call_private
*call_private
,
1489 // We respond to the CANCEL request with 200 OK response and
1490 // with 487 Request Terminated to the remote INVITE in progress.
1491 sip_transport_response(call_private
->sipe_private
, msg
, 200, "OK", NULL
);
1493 if (call_private
->invitation
) {
1494 sip_transport_response(call_private
->sipe_private
,
1495 call_private
->invitation
,
1496 487, "Request Terminated", NULL
);
1499 sipe_backend_media_reject(SIPE_MEDIA_CALL
->backend_private
, FALSE
);
1503 sipe_media_send_ack(struct sipe_core_private
*sipe_private
,
1505 struct transaction
*trans
)
1507 struct sipe_media_call_private
*call_private
;
1508 struct sip_session
*session
;
1509 struct sip_dialog
*dialog
;
1512 call_private
= sipe_media_from_sipmsg(sipe_private
, msg
);
1514 if (!is_media_session_msg(call_private
, msg
))
1517 session
= sipe_session_find_call(sipe_private
, SIPE_MEDIA_CALL
->with
);
1518 dialog
= session
->dialogs
->data
;
1522 tmp_cseq
= dialog
->cseq
;
1524 dialog
->cseq
= sip_transaction_cseq(trans
) - 1;
1525 sip_transport_ack(sipe_private
, dialog
);
1526 dialog
->cseq
= tmp_cseq
;
1528 dialog
->outgoing_invite
= NULL
;
1534 sipe_media_send_final_ack(struct sipe_core_private
*sipe_private
,
1536 struct transaction
*trans
)
1538 struct sipe_media_call_private
*call_private
;
1540 if (!sipe_media_send_ack(sipe_private
, msg
, trans
))
1543 call_private
= sipe_media_from_sipmsg(sipe_private
, msg
);
1545 sipe_backend_media_accept(SIPE_MEDIA_CALL
->backend_private
, FALSE
);
1551 sipe_core_media_stream_candidate_pair_established(struct sipe_media_stream
*stream
)
1553 struct sipe_media_call
*call
= stream
->call
;
1555 GList
*active_candidates
=
1556 sipe_backend_media_stream_get_active_local_candidates(stream
);
1557 guint ready_components
= g_list_length(active_candidates
);
1559 sipe_media_candidate_list_free(active_candidates
);
1561 if (ready_components
!= 2) {
1562 // We must have both RTP+RTCP candidate pairs established first.
1566 if (SIPE_MEDIA_STREAM_PRIVATE
->established
) {
1569 SIPE_MEDIA_STREAM_PRIVATE
->established
= TRUE
;
1571 if (stream
->candidate_pairs_established_cb
) {
1572 stream
->candidate_pairs_established_cb(stream
);
1575 if (sipe_backend_media_is_initiator(stream
->call
, NULL
)) {
1576 GSList
*streams
= SIPE_MEDIA_CALL_PRIVATE
->streams
;
1577 for (; streams
; streams
= streams
->next
) {
1578 struct sipe_media_stream_private
*s
= streams
->data
;
1579 if (!s
->established
) {
1584 if (streams
== NULL
) {
1585 // All call streams have been established.
1586 sipe_invite_call(SIPE_MEDIA_CALL_PRIVATE
,
1587 sipe_media_send_final_ack
);
1590 maybe_send_second_invite_response(SIPE_MEDIA_CALL_PRIVATE
);
1595 maybe_retry_call_with_ice_version(struct sipe_media_call_private
*call_private
,
1596 SipeIceVersion ice_version
,
1597 struct transaction
*trans
)
1599 if (call_private
->ice_version
!= ice_version
&&
1600 sip_transaction_cseq(trans
) == 1) {
1603 gboolean with_video
= FALSE
;
1605 for (i
= call_private
->streams
; i
; i
= i
->next
) {
1606 struct sipe_media_stream
*stream
= i
->data
;
1608 if (sipe_strequal(stream
->id
, "video")) {
1610 } else if (!sipe_strequal(stream
->id
, "audio")) {
1611 /* Don't retry calls which are neither audio
1617 with
= g_strdup(SIPE_MEDIA_CALL
->with
);
1619 sipe_media_hangup(call_private
);
1620 SIPE_DEBUG_INFO("Retrying call with ICEv%d.",
1621 ice_version
== SIPE_ICE_DRAFT_6
? 6 : 19);
1622 sipe_media_initiate_call(call_private
->sipe_private
, with
,
1623 ice_version
, with_video
);
1633 process_invite_call_response(struct sipe_core_private
*sipe_private
,
1635 struct transaction
*trans
)
1638 struct sipe_media_call_private
*call_private
;
1639 struct sip_session
*session
;
1640 struct sip_dialog
*dialog
;
1641 struct sdpmsg
*smsg
;
1643 call_private
= sipe_media_from_sipmsg(sipe_private
,msg
);
1645 if (!is_media_session_msg(call_private
, msg
))
1648 session
= sipe_session_find_call(sipe_private
, SIPE_MEDIA_CALL
->with
);
1649 dialog
= session
->dialogs
->data
;
1651 with
= dialog
->with
;
1653 dialog
->outgoing_invite
= NULL
;
1655 if (msg
->response
== 603 || msg
->response
== 605) {
1656 // Call rejected by remote peer
1657 sipe_media_send_ack(sipe_private
, msg
, trans
);
1658 sipe_backend_media_reject(SIPE_MEDIA_CALL
->backend_private
, FALSE
);
1663 if (msg
->response
>= 400) {
1664 // An error occurred
1666 GString
*desc
= g_string_new("");
1667 gboolean append_responsestr
= FALSE
;
1669 switch (msg
->response
) {
1671 title
= _("User unavailable");
1673 if (sipmsg_parse_warning(msg
, NULL
) == 391) {
1674 g_string_append_printf(desc
, _("%s does not want to be disturbed"), with
);
1676 g_string_append_printf(desc
, _("User %s is not available"), with
);
1680 // OCS/Lync really sends response string with 'Mutipart' typo.
1681 if (sipe_strequal(msg
->responsestr
, "Mutipart mime in content type not supported by Archiving CDR service") &&
1682 maybe_retry_call_with_ice_version(call_private
, SIPE_ICE_DRAFT_6
, trans
)) {
1685 title
= _("Unsupported media type");
1688 /* Check for incompatible encryption levels error.
1691 * 488 Not Acceptable Here
1692 * ms-client-diagnostics: 52017;reason="Encryption levels dont match"
1694 * older clients (and SIPE itself):
1695 * 488 Encryption Levels not compatible
1697 const gchar
*ms_diag
= sipmsg_find_header(msg
, "ms-client-diagnostics");
1698 SipeIceVersion retry_ice_version
= SIPE_ICE_DRAFT_6
;
1700 if (sipe_strequal(msg
->responsestr
, "Encryption Levels not compatible") ||
1701 (ms_diag
&& g_str_has_prefix(ms_diag
, "52017;"))) {
1702 title
= _("Unable to establish a call");
1703 g_string_append(desc
, _("Encryption settings of peer are incompatible with ours."));
1707 /* Check if this is failed conference using
1708 * ICEv6 with reason "Error parsing SDP" and
1709 * retry using ICEv19. */
1710 ms_diag
= sipmsg_find_header(msg
, "ms-diagnostics");
1711 if (ms_diag
&& g_str_has_prefix(ms_diag
, "7008;")) {
1712 retry_ice_version
= SIPE_ICE_RFC_5245
;
1715 if (maybe_retry_call_with_ice_version(call_private
, retry_ice_version
, trans
)) {
1718 // Break intentionally omitted
1721 title
= _("Error occured");
1722 g_string_append(desc
, _("Unable to establish a call"));
1723 append_responsestr
= TRUE
;
1727 if (append_responsestr
) {
1728 gchar
*reason
= sipmsg_get_ms_diagnostics_reason(msg
);
1730 g_string_append_printf(desc
, "\n%d %s",
1731 msg
->response
, msg
->responsestr
);
1733 g_string_append_printf(desc
, "\n\n%s", reason
);
1738 sipe_backend_notify_error(SIPE_CORE_PUBLIC
, title
, desc
->str
);
1739 g_string_free(desc
, TRUE
);
1741 sipe_media_send_ack(sipe_private
, msg
, trans
);
1742 sipe_media_hangup(call_private
);
1747 sipe_dialog_parse(dialog
, msg
, TRUE
);
1748 smsg
= sdpmsg_parse_msg(msg
->body
);
1750 transport_response_unsupported_sdp(sipe_private
, msg
);
1751 sipe_media_hangup(call_private
);
1755 apply_remote_message(call_private
, smsg
);
1758 sipe_media_send_ack(sipe_private
, msg
, trans
);
1762 // Waits until sipe_core_media_candidate_pair_established() is invoked.
1765 gboolean
is_media_session_msg(struct sipe_media_call_private
*call_private
,
1768 if (!call_private
) {
1772 return sipe_media_from_sipmsg(call_private
->sipe_private
, msg
) == call_private
;
1776 end_call(SIPE_UNUSED_PARAMETER gpointer key
,
1777 struct sipe_media_call_private
*call_private
,
1778 SIPE_UNUSED_PARAMETER gpointer user_data
)
1780 struct sipe_backend_media
*backend_private
;
1782 backend_private
= call_private
->public.backend_private
;
1784 if (!sipe_backend_media_is_initiator(SIPE_MEDIA_CALL
, NULL
) &&
1785 !sipe_backend_media_accepted(backend_private
)) {
1786 sip_transport_response(call_private
->sipe_private
,
1787 call_private
->invitation
,
1788 480, "Temporarily Unavailable", NULL
);
1790 struct sip_session
*session
;
1792 session
= sipe_session_find_call(call_private
->sipe_private
,
1793 SIPE_MEDIA_CALL
->with
);
1795 sipe_session_close(call_private
->sipe_private
, session
);
1798 sipe_media_hangup(call_private
);
1802 sipe_media_handle_going_offline(struct sipe_core_private
*sipe_private
)
1804 g_hash_table_foreach(sipe_private
->media_calls
, (GHFunc
) end_call
, NULL
);
1807 gboolean
sipe_media_is_conference_call(struct sipe_media_call_private
*call_private
)
1809 return g_strstr_len(SIPE_MEDIA_CALL
->with
, -1, "app:conf:audio-video:") != NULL
;
1812 struct sipe_core_private
*
1813 sipe_media_get_sipe_core_private(struct sipe_media_call
*call
)
1815 g_return_val_if_fail(call
, NULL
);
1817 return SIPE_MEDIA_CALL_PRIVATE
->sipe_private
;
1821 sipe_media_get_sip_dialog(struct sipe_media_call
*call
)
1823 struct sip_session
*session
;
1825 g_return_val_if_fail(call
, NULL
);
1827 session
= sipe_session_find_call(SIPE_MEDIA_CALL_PRIVATE
->sipe_private
,
1830 if (!session
|| !session
->dialogs
) {
1834 return session
->dialogs
->data
;
1838 sipe_media_relay_free(struct sipe_media_relay
*relay
)
1840 g_free(relay
->hostname
);
1841 if (relay
->dns_query
)
1842 sipe_backend_dns_query_cancel(relay
->dns_query
);
1847 sipe_media_relay_list_free(GSList
*list
)
1849 for (; list
; list
= g_slist_delete_link(list
, list
))
1850 sipe_media_relay_free(list
->data
);
1854 relay_ip_resolved_cb(struct sipe_media_relay
* relay
,
1855 const gchar
*ip
, SIPE_UNUSED_PARAMETER guint port
)
1857 gchar
*hostname
= relay
->hostname
;
1858 relay
->dns_query
= NULL
;
1861 relay
->hostname
= g_strdup(ip
);
1862 SIPE_DEBUG_INFO("Media relay %s resolved to %s.", hostname
, ip
);
1864 relay
->hostname
= NULL
;
1865 SIPE_DEBUG_INFO("Unable to resolve media relay %s.", hostname
);
1872 process_get_av_edge_credentials_response(struct sipe_core_private
*sipe_private
,
1874 SIPE_UNUSED_PARAMETER
struct transaction
*trans
)
1876 g_free(sipe_private
->media_relay_username
);
1877 g_free(sipe_private
->media_relay_password
);
1878 sipe_media_relay_list_free(sipe_private
->media_relays
);
1879 sipe_private
->media_relay_username
= NULL
;
1880 sipe_private
->media_relay_password
= NULL
;
1881 sipe_private
->media_relays
= NULL
;
1883 if (msg
->response
>= 400) {
1884 SIPE_DEBUG_INFO_NOFORMAT("process_get_av_edge_credentials_response: SERVICE response is not 200. "
1885 "Failed to obtain A/V Edge credentials.");
1889 if (msg
->response
== 200) {
1890 sipe_xml
*xn_response
= sipe_xml_parse(msg
->body
, msg
->bodylen
);
1892 if (sipe_strequal("OK", sipe_xml_attribute(xn_response
, "reasonPhrase"))) {
1893 const sipe_xml
*xn_credentials
= sipe_xml_child(xn_response
, "credentialsResponse/credentials");
1894 const sipe_xml
*xn_relays
= sipe_xml_child(xn_response
, "credentialsResponse/mediaRelayList");
1895 const sipe_xml
*item
;
1896 GSList
*relays
= NULL
;
1898 item
= sipe_xml_child(xn_credentials
, "username");
1899 sipe_private
->media_relay_username
= sipe_xml_data(item
);
1900 item
= sipe_xml_child(xn_credentials
, "password");
1901 sipe_private
->media_relay_password
= sipe_xml_data(item
);
1903 for (item
= sipe_xml_child(xn_relays
, "mediaRelay"); item
; item
= sipe_xml_twin(item
)) {
1904 struct sipe_media_relay
*relay
= g_new0(struct sipe_media_relay
, 1);
1905 const sipe_xml
*node
;
1908 node
= sipe_xml_child(item
, "hostName");
1909 relay
->hostname
= sipe_xml_data(node
);
1911 node
= sipe_xml_child(item
, "udpPort");
1913 tmp
= sipe_xml_data(node
);
1915 relay
->udp_port
= atoi(tmp
);
1920 node
= sipe_xml_child(item
, "tcpPort");
1922 tmp
= sipe_xml_data(node
);
1924 relay
->tcp_port
= atoi(tmp
);
1929 relays
= g_slist_append(relays
, relay
);
1931 relay
->dns_query
= sipe_backend_dns_query_a(
1935 (sipe_dns_resolved_cb
) relay_ip_resolved_cb
,
1938 SIPE_DEBUG_INFO("Media relay: %s TCP: %d UDP: %d",
1940 relay
->tcp_port
, relay
->udp_port
);
1943 sipe_private
->media_relays
= relays
;
1946 sipe_xml_free(xn_response
);
1953 sipe_media_get_av_edge_credentials(struct sipe_core_private
*sipe_private
)
1955 // TODO: re-request credentials after duration expires?
1956 static const char CRED_REQUEST_XML
[] =
1957 "<request requestID=\"%d\" "
1961 "xmlns=\"http://schemas.microsoft.com/2006/09/sip/mrasp\" "
1962 "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">"
1963 "<credentialsRequest credentialsRequestID=\"%d\">"
1964 "<identity>%s</identity>"
1965 "<location>%s</location>"
1966 "<duration>480</duration>"
1967 "</credentialsRequest>"
1970 int request_id
= rand();
1974 if (!sipe_private
->mras_uri
)
1977 self
= sip_uri_self(sipe_private
);
1979 body
= g_strdup_printf(
1983 sipe_private
->mras_uri
,
1986 SIPE_CORE_PRIVATE_FLAG_IS(REMOTE_USER
) ? "internet" : "intranet");
1989 sip_transport_service(sipe_private
,
1990 sipe_private
->mras_uri
,
1991 "Content-Type: application/msrtc-media-relay-auth+xml\r\n",
1993 process_get_av_edge_credentials_response
);
1999 sipe_media_add_extra_invite_section(struct sipe_media_call
*call
,
2000 const gchar
*invite_content_type
,
2003 g_free(SIPE_MEDIA_CALL_PRIVATE
->extra_invite_section
);
2004 g_free(SIPE_MEDIA_CALL_PRIVATE
->invite_content_type
);
2005 SIPE_MEDIA_CALL_PRIVATE
->extra_invite_section
= body
;
2006 SIPE_MEDIA_CALL_PRIVATE
->invite_content_type
=
2007 g_strdup(invite_content_type
);
2011 sipe_media_stream_add_extra_attribute(struct sipe_media_stream
*stream
,
2012 const gchar
*name
, const gchar
*value
)
2014 SIPE_MEDIA_STREAM_PRIVATE
->extra_sdp
=
2015 sipe_utils_nameval_add(SIPE_MEDIA_STREAM_PRIVATE
->extra_sdp
,
2021 sipe_core_media_stream_readable(struct sipe_media_stream
*stream
)
2023 g_return_if_fail(stream
);
2025 if (g_queue_is_empty(SIPE_MEDIA_STREAM_PRIVATE
->async_reads
) &&
2027 stream
->read_cb(stream
);
2030 while (!g_queue_is_empty(SIPE_MEDIA_STREAM_PRIVATE
->async_reads
)) {
2031 struct async_read_data
*data
;
2036 data
= g_queue_peek_head(SIPE_MEDIA_STREAM_PRIVATE
->async_reads
);
2037 pos
= data
->buffer
+ SIPE_MEDIA_STREAM_PRIVATE
->read_pos
;
2038 len
= data
->len
- SIPE_MEDIA_STREAM_PRIVATE
->read_pos
;
2040 bytes_read
= sipe_backend_media_stream_read(stream
, pos
, len
);
2041 if (bytes_read
== -1) {
2042 struct sipe_media_call
*call
= stream
->call
;
2043 struct sipe_core_private
*sipe_private
=
2044 SIPE_MEDIA_CALL_PRIVATE
->sipe_private
;
2046 sipe_backend_notify_error(SIPE_CORE_PUBLIC
,
2048 _("Error while reading from stream"));
2049 sipe_media_hangup(SIPE_MEDIA_CALL_PRIVATE
);
2053 SIPE_MEDIA_STREAM_PRIVATE
->read_pos
+= bytes_read
;
2055 if (SIPE_MEDIA_STREAM_PRIVATE
->read_pos
== data
->len
) {
2056 data
->callback(stream
, data
->buffer
, data
->len
);
2057 SIPE_MEDIA_STREAM_PRIVATE
->read_pos
= 0;
2058 g_queue_pop_head(SIPE_MEDIA_STREAM_PRIVATE
->async_reads
);
2061 // Still not enough data to finish the read.
2068 sipe_media_stream_read_async(struct sipe_media_stream
*stream
,
2069 gpointer buffer
, gsize len
,
2070 sipe_media_stream_read_callback callback
)
2072 struct async_read_data
*data
;
2074 g_return_if_fail(stream
&& buffer
&& callback
);
2076 data
= g_new0(struct async_read_data
, 1);
2077 data
->buffer
= buffer
;
2079 data
->callback
= callback
;
2081 g_queue_push_tail(SIPE_MEDIA_STREAM_PRIVATE
->async_reads
, data
);
2085 stream_append_buffer(struct sipe_media_stream
*stream
,
2086 guint8
*buffer
, guint len
)
2088 GByteArray
*b
= g_byte_array_sized_new(len
);
2089 g_byte_array_append(b
, buffer
, len
);
2090 g_queue_push_tail(SIPE_MEDIA_STREAM_PRIVATE
->write_queue
, b
);
2094 sipe_media_stream_write(struct sipe_media_stream
*stream
,
2095 gpointer buffer
, gsize len
)
2097 if (!sipe_media_stream_is_writable(stream
)) {
2098 stream_append_buffer(stream
, buffer
, len
);
2103 written
= sipe_backend_media_stream_write(stream
, buffer
, len
);
2104 if (written
== len
) {
2108 stream_append_buffer(stream
,
2109 (guint8
*)buffer
+ written
, len
- written
);
2115 sipe_core_media_stream_writable(struct sipe_media_stream
*stream
,
2118 SIPE_MEDIA_STREAM_PRIVATE
->writable
= writable
;
2124 while (!g_queue_is_empty(SIPE_MEDIA_STREAM_PRIVATE
->write_queue
)) {
2128 b
= g_queue_peek_head(SIPE_MEDIA_STREAM_PRIVATE
->write_queue
);
2130 written
= sipe_backend_media_stream_write(stream
, b
->data
, b
->len
);
2131 if (written
!= b
->len
) {
2132 g_byte_array_remove_range(b
, 0, written
);
2136 g_byte_array_unref(b
);
2137 g_queue_pop_head(SIPE_MEDIA_STREAM_PRIVATE
->write_queue
);
2140 if (sipe_media_stream_is_writable(stream
) && stream
->writable_cb
) {
2141 stream
->writable_cb(stream
);
2146 sipe_media_stream_is_writable(struct sipe_media_stream
*stream
)
2148 return SIPE_MEDIA_STREAM_PRIVATE
->writable
&&
2149 g_queue_is_empty(SIPE_MEDIA_STREAM_PRIVATE
->write_queue
);
2154 sipe_media_stream_set_data(struct sipe_media_stream
*stream
, gpointer data
,
2155 GDestroyNotify free_func
)
2157 struct sipe_media_stream_private
*stream_private
=
2158 SIPE_MEDIA_STREAM_PRIVATE
;
2160 g_return_if_fail(stream_private
);
2162 if (stream_private
->data
&& stream_private
->data_free_func
) {
2163 stream_private
->data_free_func(stream_private
->data
);
2166 stream_private
->data
= data
;
2167 stream_private
->data_free_func
= free_func
;
2171 sipe_media_stream_get_data(struct sipe_media_stream
*stream
)
2173 g_return_val_if_fail(stream
, NULL
);
2175 return SIPE_MEDIA_STREAM_PRIVATE
->data
;