conference: incoming invite (part I)
[siplcs.git] / src / sipe-conf.c
blobe86304e85440d2406911e322e7542fdf6d508e64
1 /**
2 * @file sipe-conf.c
4 * pidgin-sipe
5 *
6 * Copyright (C) 2009 pier11 <pier11@kinozal.tv>
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
25 static struct sip_im_session *
26 find_conf_session(struct sipe_account_data *sip,
27 const char *focus_uri)
29 struct sip_im_session *session;
30 GSList *entry;
31 if (sip == NULL || focus_uri == NULL) {
32 return NULL;
35 entry = sip->im_sessions;
36 while (entry) {
37 session = entry->data;
38 if (session->focus_uri && !g_strcasecmp(focus_uri, session->focus_uri)) {
39 return session;
41 entry = entry->next;
43 return NULL;
46 /**
47 * Generates random GUID.
48 * This method is borrowed from pidgin's msnutils.c
50 static char *
51 rand_guid()
53 return g_strdup_printf("%4X%4X-%4X-%4X-%4X-%4X%4X%4X",
54 rand() % 0xAAFF + 0x1111,
55 rand() % 0xAAFF + 0x1111,
56 rand() % 0xAAFF + 0x1111,
57 rand() % 0xAAFF + 0x1111,
58 rand() % 0xAAFF + 0x1111,
59 rand() % 0xAAFF + 0x1111,
60 rand() % 0xAAFF + 0x1111,
61 rand() % 0xAAFF + 0x1111);
64 static void
65 sipe_subscribe_conference(struct sipe_account_data *sip,
66 struct sip_im_session *session)
68 gchar *contact = get_contact(sip);
69 gchar *hdr = g_strdup_printf(
70 "Event: conference\r\n"
71 "Accept: application/conference-info+xml\r\n"
72 "Supported: com.microsoft.autoextend\r\n"
73 "Supported: ms-benotify\r\n"
74 "Proxy-Require: ms-benotify\r\n"
75 "Supported: ms-piggyback-first-notify\r\n"
76 "Contact: %s\r\n",
77 contact);
78 g_free(contact);
80 send_sip_request(sip->gc,
81 "SUBSCRIBE",
82 session->focus_uri,
83 session->focus_uri,
84 hdr,
85 "",
86 NULL,
87 process_subscribe_response);
88 g_free(hdr);
91 /** Invite us to the focus callback */
92 static gboolean
93 process_invite_conf_focus_response(struct sipe_account_data *sip,
94 struct sipmsg *msg,
95 struct transaction *trans)
97 struct sip_im_session * session = NULL;
98 char *focus_uri = parse_from(sipmsg_find_header(msg, "To"));
100 session = find_conf_session(sip, focus_uri);
102 if (!session) {
103 purple_debug_info("sipe", "process_invite_conf_focus_response: unable to find conf session with focus=%s\n", focus_uri);
104 g_free(focus_uri);
105 return FALSE;
108 if (!session->focus_dialog) {
109 purple_debug_info("sipe", "process_invite_response: session's focus_dialog is NULL\n");
110 g_free(focus_uri);
111 return FALSE;
114 sipe_parse_dialog(msg, session->focus_dialog, TRUE);
116 if (msg->response >= 200) {
117 /* send ACK to focus */
118 session->focus_dialog->cseq = 0;
119 send_sip_request(sip->gc, "ACK", session->focus_dialog->with, session->focus_dialog->with, NULL, NULL, session->focus_dialog, NULL);
120 session->focus_dialog->outgoing_invite = NULL;
121 session->focus_dialog->is_established = TRUE;
124 if (msg->response >= 400) {
125 purple_debug_info("sipe", "process_invite_conf_focus_response: INVITE response is not 200. Failed to join focus.\n");
126 /* @TODO notify user of failure to join focus */
127 im_session_destroy(sip, session);
128 g_free(focus_uri);
129 return FALSE;
130 } else if (msg->response == 200) {
131 xmlnode *xn_response = xmlnode_from_str(msg->body, msg->bodylen);
132 gchar *code = g_strdup(xmlnode_get_attrib(xn_response, "code"));
133 xmlnode_free(xn_response);
134 if (!strcmp(code, "success")) {
135 /* subscribe to focus */
136 sipe_subscribe_conference(sip, session);
138 g_free(code);
141 return TRUE;
144 /** Invite us to the focus */
145 static void
146 sipe_invite_conf_focus(struct sipe_account_data *sip,
147 struct sip_im_session *session)
149 gchar *hdr;
150 gchar *contact;
151 gchar *body;
152 gchar *self = g_strdup_printf("sip:%s", sip->username);
154 if (session->focus_dialog && session->focus_dialog->is_established) {
155 purple_debug_info("sipe", "session with %s already has a dialog open\n", session->focus_uri);
156 return;
159 if(!session->focus_dialog) {
160 session->focus_dialog = g_new0(struct sip_dialog, 1);
161 session->focus_dialog->callid = gencallid();
162 session->focus_dialog->with = g_strdup(session->focus_uri);
163 session->focus_dialog->endpoint_GUID = rand_guid();
165 if (!(session->focus_dialog->ourtag)) {
166 session->focus_dialog->ourtag = gentag();
169 contact = get_contact(sip);
170 hdr = g_strdup_printf(
171 "Supported: ms-sender\r\n"
172 "Contact: %s\r\n"
173 "Content-Type: application/cccp+xml\r\n",
174 contact);
175 g_free(contact);
177 /* @TODO put request_id to queue to further compare with incoming one */
178 /* focus_URI, from, request_id, focus_URI, from, endpoint_GUID */
179 body = g_strdup_printf(
180 SIPE_SEND_CONF_ADD_USER,
181 session->focus_dialog->with,
182 self,
183 session->request_id++,
184 session->focus_dialog->with,
185 self,
186 session->focus_dialog->endpoint_GUID);
188 session->focus_dialog->outgoing_invite = send_sip_request(sip->gc,
189 "INVITE",
190 session->focus_dialog->with,
191 session->focus_dialog->with,
192 hdr,
193 body,
194 session->focus_dialog,
195 process_invite_conf_focus_response);
196 g_free(self);
197 g_free(body);
198 g_free(hdr);
201 static void
202 process_incoming_invite_conf(struct sipe_account_data *sip,
203 struct sipmsg *msg)
205 struct sip_im_session *session = NULL;
206 struct sip_dialog *dialog = NULL;
207 gchar *from = parse_from(sipmsg_find_header(msg, "From"));
208 gchar *callid = sipmsg_find_header(msg, "Call-ID");
209 xmlnode *xn_conferencing = xmlnode_from_str(msg->body, msg->bodylen);
210 xmlnode *xn_focus_uri = xmlnode_get_child(xn_conferencing, "focus-uri");
211 char *focus_uri = xmlnode_get_data(xn_focus_uri);
213 xmlnode_free(xn_conferencing);
215 /* send OK */
216 purple_debug_info("sipe", "We have received invitation to Conference. Focus URI=%s\n", focus_uri);
217 send_sip_response(sip->gc, msg, 200, "OK", NULL);
219 session = create_chat_session(sip);
220 session->focus_uri = g_strdup(focus_uri);
222 /* temporaty dialog with invitor */
223 dialog = g_new0(struct sip_dialog, 1);
224 dialog->callid = g_strdup(callid);
225 dialog->with = g_strdup(from);
226 sipe_parse_dialog(msg, dialog, FALSE);
228 /* send BYE to invitor */
229 send_sip_request(sip->gc, "BYE", dialog->with, dialog->with, NULL, NULL, dialog, NULL);
230 free_dialog(dialog);
232 //add self to conf
233 sipe_invite_conf_focus(sip, session);
235 g_free(from);
236 g_free(focus_uri);
240 Local Variables:
241 mode: c
242 c-file-style: "bsd"
243 indent-tabs-mode: t
244 tab-width: 8
245 End: