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
;
31 if (sip
== NULL
|| focus_uri
== NULL
) {
35 entry
= sip
->im_sessions
;
37 session
= entry
->data
;
38 if (session
->focus_uri
&& !g_strcasecmp(focus_uri
, session
->focus_uri
)) {
47 * Generates random GUID.
48 * This method is borrowed from pidgin's msnutils.c
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);
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"
80 send_sip_request(sip
->gc
,
87 process_subscribe_response
);
91 /** Invite us to the focus callback */
93 process_invite_conf_focus_response(struct sipe_account_data
*sip
,
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
);
103 purple_debug_info("sipe", "process_invite_conf_focus_response: unable to find conf session with focus=%s\n", focus_uri
);
108 if (!session
->focus_dialog
) {
109 purple_debug_info("sipe", "process_invite_response: session's focus_dialog is NULL\n");
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
);
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
);
144 /** Invite us to the focus */
146 sipe_invite_conf_focus(struct sipe_account_data
*sip
,
147 struct sip_im_session
*session
)
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
);
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"
173 "Content-Type: application/cccp+xml\r\n",
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
,
183 session
->request_id
++,
184 session
->focus_dialog
->with
,
186 session
->focus_dialog
->endpoint_GUID
);
188 session
->focus_dialog
->outgoing_invite
= send_sip_request(sip
->gc
,
190 session
->focus_dialog
->with
,
191 session
->focus_dialog
->with
,
194 session
->focus_dialog
,
195 process_invite_conf_focus_response
);
202 process_incoming_invite_conf(struct sipe_account_data
*sip
,
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
);
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
);
233 sipe_invite_conf_focus(sip
, session
);