audio: decline incoming call
[siplcs.git] / src / core / sipe-media.c
blobf8c6cb341412d7205acc34bcee5244e017128e2a
1 /**
2 * @file sipe-media.c
4 * pidgin-sipe
6 * Copyright (C) 2010 Jakub Adam <jakub.adam@tieto.com>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include <libpurple/mediamanager.h>
25 #include "sipe.h"
26 #include "sipe-utils.h"
28 struct _sipe_media_session {
29 gchar *with;
30 GSList *sdp_attrs;
31 struct sipmsg *invitation;
33 typedef struct _sipe_media_session sipe_media_session;
35 void
36 sipe_media_session_free(sipe_media_session* session)
38 if (session) {
39 g_free(session->with);
40 sipe_utils_nameval_free(session->sdp_attrs);
41 if (session->invitation)
42 sipmsg_free(session->invitation);
43 g_free(session);
47 static GList *
48 sipe_media_parse_remote_codecs(const sipe_media_session *session)
50 int i = 0;
51 const gchar *attr;
52 GList *codecs = NULL;
54 while ((attr = sipe_utils_nameval_find_instance(session->sdp_attrs, "a", i++))) {
55 gchar **tokens;
56 int id;
57 int clock_rate;
58 gchar *codec_name;
59 PurpleMediaCodec *codec;
61 if (!g_str_has_prefix(attr, "rtpmap:"))
62 continue;
64 tokens = g_strsplit_set(attr + 7, " /", 3);
66 id = atoi(tokens[0]);
67 codec_name = tokens[1];
68 clock_rate = atoi(tokens[2]);
70 codec = purple_media_codec_new(id, codec_name, PURPLE_MEDIA_AUDIO, clock_rate);
71 codecs = g_list_append(codecs, codec);
73 g_strfreev(tokens);
76 return codecs;
79 static GList *
80 sipe_media_parse_remote_candidates(const sipe_media_session *session)
82 PurpleMediaCandidate *candidate;
83 GList *candidates = NULL;
85 gchar **tokens = g_strsplit(sipe_utils_nameval_find(session->sdp_attrs, "o"), " ", 5);
86 gchar *ip = g_strdup(tokens[4]);
87 guint port;
89 g_strfreev(tokens);
91 tokens = g_strsplit(sipe_utils_nameval_find(session->sdp_attrs, "m"), " ", 3);
92 port = atoi(tokens[1]);
93 g_strfreev(tokens);
95 candidate = purple_media_candidate_new("foundation?",
96 PURPLE_MEDIA_COMPONENT_RTP,
97 PURPLE_MEDIA_CANDIDATE_TYPE_HOST,
98 PURPLE_MEDIA_NETWORK_PROTOCOL_UDP, ip, port);
99 candidates = g_list_append(candidates, candidate);
101 candidate = purple_media_candidate_new("foundation?",
102 PURPLE_MEDIA_COMPONENT_RTCP,
103 PURPLE_MEDIA_CANDIDATE_TYPE_HOST,
104 PURPLE_MEDIA_NETWORK_PROTOCOL_UDP, ip, port + 1);
105 candidates = g_list_append(candidates, candidate);
107 return candidates;
110 static void
111 sipe_media_stream_info_cb(PurpleMedia *media, PurpleMediaInfoType type,
112 SIPE_UNUSED_PARAMETER gchar *sid, SIPE_UNUSED_PARAMETER gchar *name, SIPE_UNUSED_PARAMETER gboolean local, sipe_media_session *session)
114 PurpleAccount *account = purple_media_get_account(media);
116 if (type == PURPLE_MEDIA_INFO_ACCEPT) {
117 GList *codecs = sipe_media_parse_remote_codecs(session);
118 GList *candidates;
119 gchar *body;
121 if (codecs) {
122 purple_media_set_remote_codecs(media, "sipe-voice", session->with, codecs);
124 // TODO
125 purple_media_set_send_codec(media, "sipe-voice", codecs->data);
127 for (; codecs; codecs = g_list_delete_link(codecs, codecs))
128 g_object_unref(codecs->data);
131 candidates = sipe_media_parse_remote_candidates(session);
132 if (candidates) {
133 purple_media_add_remote_candidates(media, "sipe-voice", session->with, candidates);
135 for (; candidates; candidates = g_list_delete_link(candidates, candidates))
136 g_object_unref(candidates->data);
139 body = g_strdup_printf(
140 "v=0\r\n"
141 "o=- 0 0 IN IP4 %s\r\n"
142 "s=session\r\n"
143 "c=IN IP4 %s\r\n"
144 "b=CT:1000\r\n"
145 "t=0 0\r\n"
146 "m=audio 6804 RTP/AVP 97 111 101\r\n"
147 "k=base64:oPI/otNCy6dGWwyVOIPzcIX2iSij5RISzLhSd1WZxG0\r\n"
148 "a=rtpmap:97 red/8000\r\n"
149 "a=rtpmap:111 SIREN/16000\r\n"
150 "a=fmtp:111 bitrate=16000\r\n"
151 "a=rtpmap:101 telephone-event/8000\r\n"
152 "a=fmtp:101 0-16\r\n"
153 "a=encryption:optional\r\n",
154 "192.168.1.2", "192.168.1.2");
156 send_sip_response(account->gc, session->invitation, 200, "OK", body);
157 sipmsg_free(session->invitation);
158 session->invitation = NULL;
159 g_free(body);
161 } else if (type == PURPLE_MEDIA_INFO_REJECT) {
162 send_sip_response(account->gc, session->invitation, 603, "Decline", NULL);
163 sipe_media_session_free(session);
167 static GSList *
168 sipe_media_parse_sdp_frame(gchar *frame) {
169 gchar **lines = g_strsplit(frame, "\r\n", 0);
170 GSList *sdp_attrs = NULL;
172 gboolean result = sipe_utils_parse_lines(&sdp_attrs, lines, "=");
173 g_strfreev(lines);
175 if (result == FALSE) {
176 sipe_utils_nameval_free(sdp_attrs);
177 return NULL;
180 return sdp_attrs;
183 void sipe_media_incoming_invite(PurpleAccount *account, struct sipmsg *msg)
185 struct sipe_account_data *sip = account->gc->proto_data;
187 PurpleMediaManager *manager = purple_media_manager_get();
188 PurpleMedia *media;
190 sipe_media_session *session;
192 session = g_new0(sipe_media_session, 1);
193 session->with = parse_from(sipmsg_find_header(msg,"From"));
194 session->sdp_attrs = sipe_media_parse_sdp_frame(msg->body);
195 session->invitation = msg;
197 msg->dont_free = TRUE;
199 media = purple_media_manager_create_media(manager, sip->account,
200 "fsrtpconference", session->with, FALSE);
202 g_signal_connect(G_OBJECT(media), "stream-info",
203 G_CALLBACK(sipe_media_stream_info_cb), session);
205 purple_media_add_stream(media, "sipe-voice", session->with, PURPLE_MEDIA_AUDIO,
206 FALSE, "nice", 0, NULL);
210 Local Variables:
211 mode: c
212 c-file-style: "bsd"
213 indent-tabs-mode: t
214 tab-width: 8
215 End: