2 The oSIP library implements the Session Initiation Protocol (SIP -rfc3261-)
3 Copyright (C) 2001,2002,2003 Aymeric MOIZARD jack@atosc.org
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include <osip2/osip_negotiation.h>
22 #include <osip2/internal.h>
24 static int sdp_partial_clone (osip_negotiation_t * config,
25 osip_negotiation_ctx_t * con,
26 sdp_message_t * remote, sdp_message_t ** dest);
27 static int sdp_confirm_media (osip_negotiation_t * config,
28 osip_negotiation_ctx_t * context,
29 sdp_message_t * remote, sdp_message_t ** dest);
30 static __payload_t *osip_negotiation_find_audio_payload (osip_negotiation_t *
32 static __payload_t *osip_negotiation_find_video_payload (osip_negotiation_t *
34 static __payload_t *osip_negotiation_find_other_payload (osip_negotiation_t *
40 osip_negotiation_ctx_init (osip_negotiation_ctx_t ** con)
43 (osip_negotiation_ctx_t *) osip_malloc (sizeof (osip_negotiation_ctx_t));
46 (*con)->mycontext = NULL; /* fixed Sep 24 2003 */
47 (*con)->remote = NULL;
53 osip_negotiation_ctx_free (osip_negotiation_ctx_t * con)
57 sdp_message_free (con->remote);
58 sdp_message_free (con->local);
62 /* this method is used by end-user application so any pointer can
63 be associated with this context (usefull to link with your own context */
65 osip_negotiation_ctx_set_mycontext (osip_negotiation_ctx_t * con,
70 con->mycontext = my_instance;
75 osip_negotiation_ctx_get_mycontext (osip_negotiation_ctx_t * con)
79 return con->mycontext;
83 osip_negotiation_ctx_get_local_sdp (osip_negotiation_ctx_t * con)
91 osip_negotiation_ctx_set_local_sdp (osip_negotiation_ctx_t * con,
101 osip_negotiation_ctx_get_remote_sdp (osip_negotiation_ctx_t * con)
109 osip_negotiation_ctx_set_remote_sdp (osip_negotiation_ctx_t * con,
119 __payload_init (__payload_t ** payload)
121 *payload = (__payload_t *) osip_malloc (sizeof (__payload_t));
122 if (*payload == NULL)
124 (*payload)->payload = NULL;
125 (*payload)->number_of_port = NULL;
126 (*payload)->proto = NULL;
127 (*payload)->c_nettype = NULL;
128 (*payload)->c_addrtype = NULL;
129 (*payload)->c_addr = NULL;
130 (*payload)->c_addr_multicast_ttl = NULL;
131 (*payload)->c_addr_multicast_int = NULL;
132 (*payload)->a_rtpmap = NULL;
137 __payload_free (__payload_t * payload)
141 osip_free (payload->payload);
142 osip_free (payload->number_of_port);
143 osip_free (payload->proto);
144 osip_free (payload->c_nettype);
145 osip_free (payload->c_addrtype);
146 osip_free (payload->c_addr);
147 osip_free (payload->c_addr_multicast_ttl);
148 osip_free (payload->c_addr_multicast_int);
149 osip_free (payload->a_rtpmap);
154 osip_negotiation_init (osip_negotiation_t ** config_out)
156 osip_negotiation_t *config;
158 config = (osip_negotiation_t *) osip_malloc (sizeof (osip_negotiation_t));
161 config->o_username = NULL;
162 config->o_session_id = NULL;
163 config->o_session_version = NULL;
164 config->o_nettype = NULL;
165 config->o_addrtype = NULL;
166 config->o_addr = NULL;
168 config->c_nettype = NULL;
169 config->c_addrtype = NULL;
170 config->c_addr = NULL;
171 config->c_addr_multicast_ttl = NULL;
172 config->c_addr_multicast_int = NULL;
174 /* supported codec for the SIP User Agent */
175 config->audio_codec = (osip_list_t *) osip_malloc (sizeof (osip_list_t));
176 osip_list_init (config->audio_codec);
177 config->video_codec = (osip_list_t *) osip_malloc (sizeof (osip_list_t));
178 osip_list_init (config->video_codec);
179 config->other_codec = (osip_list_t *) osip_malloc (sizeof (osip_list_t));
180 osip_list_init (config->other_codec);
182 config->fcn_set_info = NULL;
183 config->fcn_set_uri = NULL;
184 config->fcn_set_emails = NULL;
185 config->fcn_set_phones = NULL;
186 config->fcn_set_attributes = NULL;
187 config->fcn_accept_audio_codec = NULL;
188 config->fcn_accept_video_codec = NULL;
189 config->fcn_accept_other_codec = NULL;
191 *config_out = config;
197 osip_negotiation_free (osip_negotiation_t * config)
201 osip_free (config->o_username);
202 osip_free (config->o_session_id);
203 osip_free (config->o_session_version);
204 osip_free (config->o_nettype);
205 osip_free (config->o_addrtype);
206 osip_free (config->o_addr);
208 osip_free (config->c_nettype);
209 osip_free (config->c_addrtype);
210 osip_free (config->c_addr);
211 osip_free (config->c_addr_multicast_ttl);
212 osip_free (config->c_addr_multicast_int);
214 osip_list_special_free (config->audio_codec,
215 (void *(*)(void *)) &__payload_free);
216 osip_list_special_free (config->video_codec,
217 (void *(*)(void *)) &__payload_free);
218 osip_list_special_free (config->other_codec,
219 (void *(*)(void *)) &__payload_free);
221 /* other are pointer to func, they don't need free() calls */
223 /* yes, this is done here... :) */
228 osip_negotiation_set_o_username (osip_negotiation_t * config, char *tmp)
232 config->o_username = tmp;
237 osip_negotiation_set_o_session_id (osip_negotiation_t * config, char *tmp)
241 config->o_session_id = tmp;
246 osip_negotiation_set_o_session_version (osip_negotiation_t * config,
251 config->o_session_version = tmp;
256 osip_negotiation_set_o_nettype (osip_negotiation_t * config, char *tmp)
260 config->o_nettype = tmp;
265 osip_negotiation_set_o_addrtype (osip_negotiation_t * config, char *tmp)
269 config->o_addrtype = tmp;
274 osip_negotiation_set_o_addr (osip_negotiation_t * config, char *tmp)
278 config->o_addr = tmp;
283 osip_negotiation_set_c_nettype (osip_negotiation_t * config, char *tmp)
287 config->c_nettype = tmp;
292 osip_negotiation_set_c_addrtype (osip_negotiation_t * config, char *tmp)
296 config->c_addrtype = tmp;
301 osip_negotiation_set_c_addr (osip_negotiation_t * config, char *tmp)
305 config->c_addr = tmp;
310 osip_negotiation_set_c_addr_multicast_ttl (osip_negotiation_t * config,
315 config->c_addr_multicast_ttl = tmp;
320 osip_negotiation_set_c_addr_multicast_int (osip_negotiation_t * config,
325 config->c_addr_multicast_int = tmp;
330 osip_negotiation_add_support_for_audio_codec (osip_negotiation_t * config,
332 char *number_of_port,
333 char *proto, char *c_nettype,
334 char *c_addrtype, char *c_addr,
335 char *c_addr_multicast_ttl,
336 char *c_addr_multicast_int,
340 __payload_t *my_payload;
342 i = __payload_init (&my_payload);
345 my_payload->payload = payload;
346 my_payload->number_of_port = number_of_port;
347 my_payload->proto = proto;
348 my_payload->c_nettype = c_nettype;
349 my_payload->c_addrtype = c_addrtype;
350 my_payload->c_addr = c_addr;
351 my_payload->c_addr_multicast_ttl = c_addr_multicast_ttl;
352 my_payload->c_addr_multicast_int = c_addr_multicast_int;
353 my_payload->a_rtpmap = a_rtpmap;
354 osip_list_add (config->audio_codec, my_payload, -1);
359 osip_negotiation_add_support_for_video_codec (osip_negotiation_t * config,
361 char *number_of_port,
362 char *proto, char *c_nettype,
363 char *c_addrtype, char *c_addr,
364 char *c_addr_multicast_ttl,
365 char *c_addr_multicast_int,
369 __payload_t *my_payload;
371 i = __payload_init (&my_payload);
374 my_payload->payload = payload;
375 my_payload->number_of_port = number_of_port;
376 my_payload->proto = proto;
377 my_payload->c_nettype = c_nettype;
378 my_payload->c_addrtype = c_addrtype;
379 my_payload->c_addr = c_addr;
380 my_payload->c_addr_multicast_ttl = c_addr_multicast_ttl;
381 my_payload->c_addr_multicast_int = c_addr_multicast_int;
382 my_payload->a_rtpmap = a_rtpmap;
383 osip_list_add (config->video_codec, my_payload, -1);
388 osip_negotiation_add_support_for_other_codec (osip_negotiation_t * config,
390 char *number_of_port,
391 char *proto, char *c_nettype,
392 char *c_addrtype, char *c_addr,
393 char *c_addr_multicast_ttl,
394 char *c_addr_multicast_int,
398 __payload_t *my_payload;
400 i = __payload_init (&my_payload);
403 my_payload->payload = payload;
404 my_payload->number_of_port = number_of_port;
405 my_payload->proto = proto;
406 my_payload->c_nettype = c_nettype;
407 my_payload->c_addrtype = c_addrtype;
408 my_payload->c_addr = c_addr;
409 my_payload->c_addr_multicast_ttl = c_addr_multicast_ttl;
410 my_payload->c_addr_multicast_int = c_addr_multicast_int;
411 my_payload->a_rtpmap = a_rtpmap;
412 osip_list_add (config->other_codec, my_payload, -1);
417 osip_negotiation_remove_audio_payloads (osip_negotiation_t * config)
419 osip_list_special_free (config->audio_codec,
420 (void *(*)(void *)) &__payload_free);
421 config->audio_codec = (osip_list_t *) osip_malloc (sizeof (osip_list_t));
422 osip_list_init (config->audio_codec);
427 osip_negotiation_remove_video_payloads (osip_negotiation_t * config)
429 osip_list_special_free (config->video_codec,
430 (void *(*)(void *)) &__payload_free);
431 config->video_codec = (osip_list_t *) osip_malloc (sizeof (osip_list_t));
432 osip_list_init (config->video_codec);
437 osip_negotiation_remove_other_payloads (osip_negotiation_t * config)
439 osip_list_special_free (config->other_codec,
440 (void *(*)(void *)) &__payload_free);
441 config->other_codec = (osip_list_t *) osip_malloc (sizeof (osip_list_t));
442 osip_list_init (config->other_codec);
447 osip_negotiation_find_audio_payload (osip_negotiation_t * config,
451 size_t length = strlen (payload);
456 while (!osip_list_eol (config->audio_codec, pos))
458 my = (__payload_t *) osip_list_get (config->audio_codec, pos);
459 if (strlen (my->payload) == length)
460 if (0 == strncmp (my->payload, payload, length))
468 osip_negotiation_find_video_payload (osip_negotiation_t * config,
472 size_t length = strlen (payload);
477 while (!osip_list_eol (config->video_codec, pos))
479 my = (__payload_t *) osip_list_get (config->video_codec, pos);
480 if (strlen (my->payload) == length)
481 if (0 == strncmp (my->payload, payload, length))
489 osip_negotiation_find_other_payload (osip_negotiation_t * config,
493 size_t length = strlen (payload);
498 while (!osip_list_eol (config->other_codec, pos))
500 my = (__payload_t *) osip_list_get (config->other_codec, pos);
501 if (strlen (my->payload) == length)
502 if (0 == strncmp (my->payload, payload, length))
510 osip_negotiation_set_fcn_set_info (osip_negotiation_t * config,
511 int (*fcn) (osip_negotiation_ctx_t *,
516 config->fcn_set_info = (int (*)(void *, sdp_message_t *)) fcn;
521 osip_negotiation_set_fcn_set_uri (osip_negotiation_t * config,
522 int (*fcn) (osip_negotiation_ctx_t *,
527 config->fcn_set_uri = (int (*)(void *, sdp_message_t *)) fcn;
532 osip_negotiation_set_fcn_set_emails (osip_negotiation_t * config,
533 int (*fcn) (osip_negotiation_ctx_t *,
538 config->fcn_set_emails = (int (*)(void *, sdp_message_t *)) fcn;
543 osip_negotiation_set_fcn_set_phones (osip_negotiation_t * config,
544 int (*fcn) (osip_negotiation_ctx_t *,
549 config->fcn_set_phones = (int (*)(void *, sdp_message_t *)) fcn;
554 osip_negotiation_set_fcn_set_attributes (osip_negotiation_t * config,
555 int (*fcn) (osip_negotiation_ctx_t *,
556 sdp_message_t *, int))
560 config->fcn_set_attributes = (int (*)(void *, sdp_message_t *, int)) fcn;
565 osip_negotiation_set_fcn_accept_audio_codec (osip_negotiation_t * config,
567 (osip_negotiation_ctx_t *,
568 char *, char *, int, char *))
572 config->fcn_accept_audio_codec = (int (*)(void *, char *,
573 char *, int, char *)) fcn;
578 osip_negotiation_set_fcn_accept_video_codec (osip_negotiation_t * config,
580 (osip_negotiation_ctx_t *,
581 char *, char *, int, char *))
585 config->fcn_accept_video_codec = (int (*)(void *, char *,
586 char *, int, char *)) fcn;
591 osip_negotiation_set_fcn_accept_other_codec (osip_negotiation_t * config,
593 (osip_negotiation_ctx_t *,
594 char *, char *, char *, char *))
598 config->fcn_accept_other_codec = (int (*)(void *, char *,
599 char *, char *, char *)) fcn;
604 osip_negotiation_set_fcn_get_audio_port (osip_negotiation_t * config,
605 char *(*fcn) (osip_negotiation_ctx_t
610 config->fcn_get_audio_port = (char *(*)(void *, int)) fcn;
615 osip_negotiation_set_fcn_get_video_port (osip_negotiation_t * config,
616 char *(*fcn) (osip_negotiation_ctx_t
621 config->fcn_get_video_port = (char *(*)(void *, int)) fcn;
626 osip_negotiation_set_fcn_get_other_port (osip_negotiation_t * config,
627 char *(*fcn) (osip_negotiation_ctx_t
632 config->fcn_get_other_port = (char *(*)(void *, int)) fcn;
637 sdp_partial_clone (osip_negotiation_t * config,
638 osip_negotiation_ctx_t * con, sdp_message_t * remote,
639 sdp_message_t ** dest)
643 sdp_message_v_version_set (*dest, osip_strdup ("0"));
645 /* those fields MUST be set */
646 sdp_message_o_origin_set (*dest,
647 osip_strdup (config->o_username),
648 osip_strdup (config->o_session_id),
649 osip_strdup (config->o_session_version),
650 osip_strdup (config->o_nettype),
651 osip_strdup (config->o_addrtype),
652 osip_strdup (config->o_addr));
653 sdp_message_s_name_set (*dest, osip_strdup (remote->s_name));
654 if (config->fcn_set_info != NULL)
655 config->fcn_set_info (con, *dest);
656 if (config->fcn_set_uri != NULL)
657 config->fcn_set_uri (con, *dest);
658 if (config->fcn_set_emails != NULL)
659 config->fcn_set_emails (con, *dest);
660 if (config->fcn_set_phones != NULL)
661 config->fcn_set_phones (con, *dest);
662 if (config->c_nettype != NULL)
663 sdp_message_c_connection_add (*dest, -1,
664 osip_strdup (config->c_nettype),
665 osip_strdup (config->c_addrtype),
666 osip_strdup (config->c_addr),
667 osip_strdup (config->c_addr_multicast_ttl),
668 osip_strdup (config->c_addr_multicast_int));
670 { /* offer-answer draft says we must copy the "t=" line */
671 char *tmp = sdp_message_t_start_time_get (remote, 0);
672 char *tmp2 = sdp_message_t_stop_time_get (remote, 0);
674 if (tmp == NULL || tmp2 == NULL)
675 return -1; /* no t line?? */
677 sdp_message_t_time_descr_add (*dest, osip_strdup (tmp),
682 if (config->fcn_set_attributes != NULL)
683 config->fcn_set_attributes (con, *dest, -1);
688 sdp_confirm_media (osip_negotiation_t * config,
689 osip_negotiation_ctx_t * context, sdp_message_t * remote,
690 sdp_message_t ** dest)
693 char *tmp, *tmp2, *tmp3, *tmp4;
697 int audio_qty = 0; /* accepted audio line: do not accept more than one */
701 while (!sdp_message_endof_media (remote, i))
703 tmp = sdp_message_m_media_get (remote, i);
704 tmp2 = sdp_message_m_port_get (remote, i);
705 tmp3 = sdp_message_m_number_of_port_get (remote, i);
706 tmp4 = sdp_message_m_proto_get (remote, i);
710 sdp_message_m_media_add (*dest, osip_strdup (tmp), osip_strdup ("0"),
711 NULL, osip_strdup (tmp4));
713 if (0 == strncmp (tmp, "audio", 5))
717 payload = sdp_message_m_payload_get (remote, i, k);
720 __payload_t *my_payload =
721 osip_negotiation_find_audio_payload (config, payload);
723 if (my_payload != NULL) /* payload is supported */
725 ret = -1; /* somtimes, codec can be refused even if supported */
726 if (config->fcn_accept_audio_codec != NULL)
727 ret = config->fcn_accept_audio_codec (context, tmp2,
732 sdp_message_m_payload_add (*dest, i,
733 osip_strdup (payload));
734 if (my_payload->a_rtpmap != NULL)
735 sdp_message_a_attribute_add (*dest, i,
741 if (my_payload->c_nettype != NULL)
744 osip_list_get ((*dest)->m_medias, i);
746 if (osip_list_eol (med->c_connections, 0))
747 sdp_message_c_connection_add (*dest, i,
759 c_addr_multicast_ttl),
762 c_addr_multicast_int));
769 while (payload != NULL);
770 if (NULL != sdp_message_m_payload_get (*dest, i, 0))
773 else if (0 == strncmp (tmp, "video", 5))
777 payload = sdp_message_m_payload_get (remote, i, k);
780 __payload_t *my_payload =
781 osip_negotiation_find_video_payload (config, payload);
783 if (my_payload != NULL) /* payload is supported */
786 if (config->fcn_accept_video_codec != NULL)
788 config->fcn_accept_video_codec (context, tmp2, tmp3,
792 sdp_message_m_payload_add (*dest, i,
793 osip_strdup (payload));
794 /* TODO set the attribute list (rtpmap..) */
795 if (my_payload->a_rtpmap != NULL)
796 sdp_message_a_attribute_add (*dest, i,
802 if (my_payload->c_nettype != NULL)
805 osip_list_get ((*dest)->m_medias, i);
807 if (osip_list_eol (med->c_connections, 0))
808 sdp_message_c_connection_add (*dest, i,
820 c_addr_multicast_ttl),
823 c_addr_multicast_int));
830 while (payload != NULL);
831 if (NULL != sdp_message_m_payload_get (*dest, i, 0))
838 payload = sdp_message_m_payload_get (remote, i, k);
841 __payload_t *my_payload =
842 osip_negotiation_find_other_payload (config, payload);
844 if (my_payload != NULL) /* payload is supported */
847 if (config->fcn_accept_other_codec != NULL)
849 config->fcn_accept_other_codec (context, tmp, tmp2,
853 sdp_message_m_payload_add (*dest, i,
854 osip_strdup (payload));
855 /* rtpmap has no meaning here! */
856 if (my_payload->c_nettype != NULL)
859 osip_list_get ((*dest)->m_medias, i);
861 if (osip_list_eol (med->c_connections, 0))
862 sdp_message_c_connection_add (*dest, i,
874 c_addr_multicast_ttl),
877 c_addr_multicast_int));
884 while (payload != NULL);
892 osip_negotiation_ctx_execute_negotiation (osip_negotiation_t * config,
893 osip_negotiation_ctx_t * context)
895 int m_lines_that_match = 0;
896 sdp_message_t *remote;
897 sdp_message_t *local;
902 remote = context->remote;
906 i = sdp_message_init (&local);
910 if (0 != strncmp (remote->v_version, "0", 1))
912 sdp_message_free (local);
913 /* sdp_context->fcn_wrong_version(context); */
914 return 406; /* Not Acceptable */
917 i = sdp_partial_clone (config, context, remote, &local);
920 sdp_message_free (local);
923 i = sdp_confirm_media (config, context, remote, &local);
926 sdp_message_free (local);
931 while (!sdp_message_endof_media (local, i))
933 /* this is to refuse each line with no codec that matches! */
934 if (NULL == sdp_message_m_payload_get (local, i, 0))
936 sdp_media_t *med = osip_list_get ((local)->m_medias, i);
937 char *str = sdp_message_m_payload_get (remote, i, 0);
939 sdp_message_m_payload_add (local, i, osip_strdup (str));
940 osip_free (med->m_port);
941 med->m_port = osip_strdup ("0"); /* refuse this line */
944 { /* number of "m" lines that match */
945 sdp_media_t *med = osip_list_get (local->m_medias, i);
947 m_lines_that_match++;
948 osip_free (med->m_port);
949 /* AMD: use the correct fcn_get_xxx_port method: */
950 if (0 == strcmp (med->m_media, "audio"))
952 if (config->fcn_get_audio_port != NULL)
953 med->m_port = config->fcn_get_audio_port (context, i);
955 med->m_port = osip_strdup ("0"); /* should never happen */
957 else if (0 == strcmp (med->m_media, "video"))
959 if (config->fcn_get_video_port != NULL)
960 med->m_port = config->fcn_get_video_port (context, i);
962 med->m_port = osip_strdup ("0"); /* should never happen */
966 if (config->fcn_get_other_port != NULL)
967 med->m_port = config->fcn_get_other_port (context, i);
969 med->m_port = osip_strdup ("0"); /* should never happen */
974 if (m_lines_that_match > 0)
976 context->local = local;
981 sdp_message_free (local);
988 osip_negotiation_sdp_build_offer (osip_negotiation_t * config,
989 osip_negotiation_ctx_t * con,
990 sdp_message_t ** sdp, char *audio_port,
996 i = sdp_message_init (sdp);
1000 sdp_message_v_version_set (*sdp, osip_strdup ("0"));
1002 /* those fields MUST be set */
1003 sdp_message_o_origin_set (*sdp,
1004 osip_strdup (config->o_username),
1005 osip_strdup (config->o_session_id),
1006 osip_strdup (config->o_session_version),
1007 osip_strdup (config->o_nettype),
1008 osip_strdup (config->o_addrtype),
1009 osip_strdup (config->o_addr));
1010 sdp_message_s_name_set (*sdp, osip_strdup ("A call"));
1011 if (config->fcn_set_info != NULL)
1012 config->fcn_set_info (con, *sdp);
1013 if (config->fcn_set_uri != NULL)
1014 config->fcn_set_uri (con, *sdp);
1015 if (config->fcn_set_emails != NULL)
1016 config->fcn_set_emails (con, *sdp);
1017 if (config->fcn_set_phones != NULL)
1018 config->fcn_set_phones (con, *sdp);
1019 if (config->c_nettype != NULL)
1020 sdp_message_c_connection_add (*sdp, -1,
1021 osip_strdup (config->c_nettype),
1022 osip_strdup (config->c_addrtype),
1023 osip_strdup (config->c_addr),
1024 osip_strdup (config->c_addr_multicast_ttl),
1025 osip_strdup (config->c_addr_multicast_int));
1027 { /* offer-answer draft says we must copy the "t=" line */
1028 int now = time (NULL);
1029 char *tmp = osip_malloc (15);
1030 char *tmp2 = osip_malloc (15);
1032 sprintf (tmp, "%i", now);
1033 sprintf (tmp2, "%i", now + 3600);
1035 i = sdp_message_t_time_descr_add (*sdp, tmp, tmp2);
1039 if (config->fcn_set_attributes != NULL)
1040 config->fcn_set_attributes (con, *sdp, -1);
1043 /* add all audio codec */
1044 if (!osip_list_eol (config->audio_codec, 0))
1048 (__payload_t *) osip_list_get (config->audio_codec, pos);
1050 /* all media MUST have the same PROTO, PORT. */
1051 sdp_message_m_media_add (*sdp, osip_strdup ("audio"),
1052 osip_strdup (audio_port),
1053 osip_strdup (my->number_of_port),
1054 osip_strdup (my->proto));
1056 while (!osip_list_eol (config->audio_codec, pos))
1058 my = (__payload_t *) osip_list_get (config->audio_codec, pos);
1059 sdp_message_m_payload_add (*sdp, media_line,
1060 osip_strdup (my->payload));
1061 if (my->a_rtpmap != NULL)
1062 sdp_message_a_attribute_add (*sdp, media_line,
1063 osip_strdup ("rtpmap"),
1064 osip_strdup (my->a_rtpmap));
1070 /* add all video codec */
1071 if (!osip_list_eol (config->video_codec, 0))
1075 (__payload_t *) osip_list_get (config->video_codec, pos);
1077 /* all media MUST have the same PROTO, PORT. */
1078 sdp_message_m_media_add (*sdp, osip_strdup ("video"),
1079 osip_strdup (video_port),
1080 osip_strdup (my->number_of_port),
1081 osip_strdup (my->proto));
1083 while (!osip_list_eol (config->video_codec, pos))
1085 my = (__payload_t *) osip_list_get (config->video_codec, pos);
1086 sdp_message_m_payload_add (*sdp, media_line,
1087 osip_strdup (my->payload));
1088 if (my->a_rtpmap != NULL)
1089 sdp_message_a_attribute_add (*sdp, media_line,
1090 osip_strdup ("rtpmap"),
1091 osip_strdup (my->a_rtpmap));
1099 /* build the SDP packet with only one audio codec and one video codec.
1100 * - Usefull if you don't want to restrict proposal to one codec only -
1101 * - Limitation, only one codec will be proposed
1104 __osip_negotiation_sdp_build_offer (osip_negotiation_t * config,
1105 osip_negotiation_ctx_t * con,
1106 sdp_message_t ** sdp, char *audio_port,
1107 char *video_port, char *audio_codec,
1113 i = sdp_message_init (sdp);
1117 sdp_message_v_version_set (*sdp, osip_strdup ("0"));
1119 /* those fields MUST be set */
1120 sdp_message_o_origin_set (*sdp,
1121 osip_strdup (config->o_username),
1122 osip_strdup (config->o_session_id),
1123 osip_strdup (config->o_session_version),
1124 osip_strdup (config->o_nettype),
1125 osip_strdup (config->o_addrtype),
1126 osip_strdup (config->o_addr));
1127 sdp_message_s_name_set (*sdp, osip_strdup ("A call"));
1128 if (config->fcn_set_info != NULL)
1129 config->fcn_set_info (con, *sdp);
1130 if (config->fcn_set_uri != NULL)
1131 config->fcn_set_uri (con, *sdp);
1132 if (config->fcn_set_emails != NULL)
1133 config->fcn_set_emails (con, *sdp);
1134 if (config->fcn_set_phones != NULL)
1135 config->fcn_set_phones (con, *sdp);
1136 if (config->c_nettype != NULL)
1137 sdp_message_c_connection_add (*sdp, -1,
1138 osip_strdup (config->c_nettype),
1139 osip_strdup (config->c_addrtype),
1140 osip_strdup (config->c_addr),
1141 osip_strdup (config->c_addr_multicast_ttl),
1142 osip_strdup (config->c_addr_multicast_int));
1144 { /* offer-answer draft says we must copy the "t=" line */
1145 int now = time (NULL);
1146 char *tmp = osip_malloc (15);
1147 char *tmp2 = osip_malloc (15);
1149 sprintf (tmp, "%i", now);
1150 sprintf (tmp2, "%i", now + 3600);
1152 i = sdp_message_t_time_descr_add (*sdp, tmp, tmp2);
1156 if (config->fcn_set_attributes != NULL)
1157 config->fcn_set_attributes (con, *sdp, -1);
1160 /* add all audio codec */
1161 if (audio_codec != NULL)
1163 if (!osip_list_eol (config->audio_codec, 0))
1167 (__payload_t *) osip_list_get (config->audio_codec, pos);
1169 while (!osip_list_eol (config->audio_codec, pos))
1171 my = (__payload_t *) osip_list_get (config->audio_codec, pos);
1172 if (0 == strcmp (audio_codec, my->payload))
1174 /* all media MUST have the same PROTO, PORT. */
1175 sdp_message_m_media_add (*sdp, osip_strdup ("audio"),
1176 osip_strdup (audio_port),
1177 osip_strdup (my->number_of_port),
1178 osip_strdup (my->proto));
1179 sdp_message_m_payload_add (*sdp, media_line,
1180 osip_strdup (my->payload));
1181 if (my->a_rtpmap != NULL)
1182 sdp_message_a_attribute_add (*sdp, media_line,
1183 osip_strdup ("rtpmap"),
1184 osip_strdup (my->a_rtpmap));
1193 /* add all video codec */
1194 if (video_codec != NULL)
1196 if (!osip_list_eol (config->video_codec, 0))
1200 (__payload_t *) osip_list_get (config->video_codec, pos);
1202 while (!osip_list_eol (config->video_codec, pos))
1204 my = (__payload_t *) osip_list_get (config->video_codec, pos);
1205 if (0 == strcmp (video_codec, my->payload))
1207 /* all media MUST have the same PROTO, PORT. */
1208 sdp_message_m_media_add (*sdp, osip_strdup ("video"),
1209 osip_strdup (video_port),
1210 osip_strdup (my->number_of_port),
1211 osip_strdup (my->proto));
1212 sdp_message_m_payload_add (*sdp, media_line,
1213 osip_strdup (my->payload));
1214 if (my->a_rtpmap != NULL)
1215 sdp_message_a_attribute_add (*sdp, media_line,
1216 osip_strdup ("rtpmap"),
1217 osip_strdup (my->a_rtpmap));
1230 osip_negotiation_sdp_message_put_on_hold (sdp_message_t * sdp)
1238 rcvsnd = sdp_message_a_att_field_get (sdp, pos_media, pos);
1239 while (rcvsnd != NULL)
1241 if (rcvsnd != NULL && 0 == strcmp (rcvsnd, "sendonly"))
1245 else if (rcvsnd != NULL && (0 == strcmp (rcvsnd, "recvonly")
1246 || 0 == strcmp (rcvsnd, "sendrecv")))
1249 sprintf (rcvsnd, "sendonly");
1252 rcvsnd = sdp_message_a_att_field_get (sdp, pos_media, pos);
1256 while (!sdp_message_endof_media (sdp, pos_media))
1259 rcvsnd = sdp_message_a_att_field_get (sdp, pos_media, pos);
1260 while (rcvsnd != NULL)
1262 if (rcvsnd != NULL && 0 == strcmp (rcvsnd, "sendonly"))
1266 else if (rcvsnd != NULL && (0 == strcmp (rcvsnd, "recvonly")
1267 || 0 == strcmp (rcvsnd, "sendrecv")))
1270 sprintf (rcvsnd, "sendonly");
1273 rcvsnd = sdp_message_a_att_field_get (sdp, pos_media, pos);
1278 if (recv_send == -1)
1280 /* we need to add a global attribute with a field set to "sendonly" */
1281 sdp_message_a_attribute_add (sdp, -1, osip_strdup ("sendonly"), NULL);
1288 osip_negotiation_sdp_message_put_off_hold (sdp_message_t * sdp)
1295 rcvsnd = sdp_message_a_att_field_get (sdp, pos_media, pos);
1296 while (rcvsnd != NULL)
1298 if (rcvsnd != NULL && (0 == strcmp (rcvsnd, "sendonly")
1299 || 0 == strcmp (rcvsnd, "recvonly")))
1301 sprintf (rcvsnd, "sendrecv");
1304 rcvsnd = sdp_message_a_att_field_get (sdp, pos_media, pos);
1308 while (!sdp_message_endof_media (sdp, pos_media))
1311 rcvsnd = sdp_message_a_att_field_get (sdp, pos_media, pos);
1312 while (rcvsnd != NULL)
1314 if (rcvsnd != NULL && (0 == strcmp (rcvsnd, "sendonly")
1315 || 0 == strcmp (rcvsnd, "recvonly")))
1317 sprintf (rcvsnd, "sendrecv");
1320 rcvsnd = sdp_message_a_att_field_get (sdp, pos_media, pos);