filetransfer: initialize backend structure for Lync FT
[siplcs.git] / src / core / sipe-ft-lync.c
blobfd2681d670b5b55ca0184dcde93b526e666ca9cf
1 /**
2 * @file sipe-ft-lync.c
4 * pidgin-sipe
6 * Copyright (C) 2014-2015 SIPE Project <http://sipe.sourceforge.net/>
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 <glib.h>
24 #include <stdlib.h>
25 #include <string.h>
27 #include "sip-transport.h"
28 #include "sipe-backend.h"
29 #include "sipe-common.h"
30 #include "sipe-core.h"
31 #include "sipe-core-private.h"
32 #include "sipe-ft-lync.h"
33 #include "sipe-media.h"
34 #include "sipe-mime.h"
35 #include "sipe-utils.h"
36 #include "sipe-xml.h"
37 #include "sipmsg.h"
39 struct sipe_file_transfer_lync {
40 struct sipe_file_transfer public;
42 gchar *sdp;
43 gchar *file_name;
44 gchar *id;
45 gsize file_size;
46 guint request_id;
48 struct sipe_media_call *call;
50 #define SIPE_FILE_TRANSFER ((struct sipe_file_transfer *) ft_private)
51 #define SIPE_FILE_TRANSFER_PRIVATE ((struct sipe_file_transfer_lync *) ft)
53 static void
54 sipe_file_transfer_lync_free(struct sipe_file_transfer_lync *ft_private)
56 g_free(ft_private->file_name);
57 g_free(ft_private->sdp);
58 g_free(ft_private->id);
59 g_free(ft_private);
62 static void
63 send_ms_filetransfer_msg(char *body, struct sipe_file_transfer_lync *ft_private,
64 TransCallback callback)
66 sip_transport_info(sipe_media_get_sipe_core_private(ft_private->call),
67 "Content-Type: application/ms-filetransfer+xml\r\n",
68 body,
69 sipe_media_get_sip_dialog(ft_private->call),
70 callback);
72 g_free(body);
75 static void
76 send_ms_filetransfer_response(struct sipe_file_transfer_lync *ft_private,
77 const gchar *code, const gchar *reason,
78 TransCallback callback)
80 static const gchar *RESPONSE_STR =
81 "<response xmlns=\"http://schemas.microsoft.com/rtc/2009/05/filetransfer\" requestId=\"%d\" code=\"%s\" %s%s%s/>";
83 send_ms_filetransfer_msg(g_strdup_printf(RESPONSE_STR,
84 ft_private->request_id, code,
85 reason ? "reason=\"" : "",
86 reason ? reason : "",
87 reason ? "\"" : ""),
88 ft_private, callback);
91 static void
92 mime_mixed_cb(gpointer user_data, const GSList *fields, const gchar *body,
93 gsize length)
95 struct sipe_file_transfer_lync *ft_private = user_data;
96 const gchar *ctype = sipe_utils_nameval_find(fields, "Content-Type");
98 /* Lync 2010 file transfer */
99 if (g_str_has_prefix(ctype, "application/ms-filetransfer+xml")) {
100 sipe_xml *xml = sipe_xml_parse(body, length);
101 const sipe_xml *node;
103 const gchar *request_id_str = sipe_xml_attribute(xml, "requestId");
104 if (request_id_str) {
105 ft_private->request_id = atoi(request_id_str);
108 node = sipe_xml_child(xml, "publishFile/fileInfo/name");
109 if (node) {
110 ft_private->file_name = sipe_xml_data(node);
113 node = sipe_xml_child(xml, "publishFile/fileInfo/id");
114 if (node) {
115 ft_private->id = sipe_xml_data(node);
118 node = sipe_xml_child(xml, "publishFile/fileInfo/size");
119 if (node) {
120 gchar *size_str = sipe_xml_data(node);
121 if (size_str) {
122 ft_private->file_size = atoi(size_str);
123 g_free(size_str);
126 } else if (g_str_has_prefix(ctype, "application/sdp")) {
127 ft_private->sdp = g_strndup(body, length);
131 static void
132 candidate_pair_established_cb(SIPE_UNUSED_PARAMETER struct sipe_media_call *call,
133 struct sipe_media_stream *stream)
135 struct sipe_file_transfer_lync *ft_private;
136 static const gchar *DOWNLOAD_FILE_REQUEST =
137 "<request xmlns=\"http://schemas.microsoft.com/rtc/2009/05/filetransfer\" requestId=\"%d\">"
138 "<downloadFile>"
139 "<fileInfo>"
140 "<id>%s</id>"
141 "<name>%s</name>"
142 "</fileInfo>"
143 "</downloadFile>"
144 "</request>";
146 g_return_if_fail(sipe_strequal(stream->id, "data"));
148 ft_private = sipe_media_stream_get_data(stream);
150 send_ms_filetransfer_response(ft_private, "success", NULL, NULL);
152 send_ms_filetransfer_msg(g_strdup_printf(DOWNLOAD_FILE_REQUEST,
153 ++ft_private->request_id,
154 ft_private->id,
155 ft_private->file_name),
156 ft_private, NULL);
159 static void
160 ft_lync_incoming_init(struct sipe_file_transfer *ft,
161 SIPE_UNUSED_PARAMETER const gchar *filename,
162 SIPE_UNUSED_PARAMETER gsize size,
163 SIPE_UNUSED_PARAMETER const gchar *who)
165 struct sipe_media_call *call = SIPE_FILE_TRANSFER_PRIVATE->call;
167 if (call) {
168 sipe_backend_media_accept(call->backend_private, TRUE);
172 static void
173 ft_lync_deallocate(struct sipe_file_transfer *ft)
175 struct sipe_media_call *call = SIPE_FILE_TRANSFER_PRIVATE->call;
177 if (call) {
178 sipe_backend_media_hangup(call->backend_private, TRUE);
180 sipe_file_transfer_lync_free(SIPE_FILE_TRANSFER_PRIVATE);
183 void
184 process_incoming_invite_ft_lync(struct sipe_core_private *sipe_private,
185 struct sipmsg *msg)
187 struct sipe_file_transfer_lync *ft_private;
188 struct sipe_media_call *call;
189 struct sipe_media_stream *stream;
191 ft_private = g_new0(struct sipe_file_transfer_lync, 1);
192 sipe_mime_parts_foreach(sipmsg_find_header(msg, "Content-Type"),
193 msg->body, mime_mixed_cb, ft_private);
195 if (!ft_private->file_name || !ft_private->file_size || !ft_private->sdp) {
196 sip_transport_response(sipe_private, msg, 488, "Not Acceptable Here", NULL);
197 sipe_file_transfer_lync_free(ft_private);
198 return;
201 /* Replace multipart message body with the selected SDP part and
202 * initialize media session as if invited to a media call. */
203 g_free(msg->body);
204 msg->body = ft_private->sdp;
205 msg->bodylen = strlen(msg->body);
206 ft_private->sdp = NULL;
208 ft_private->call = process_incoming_invite_call(sipe_private, msg);
209 if (!ft_private->call) {
210 sip_transport_response(sipe_private, msg, 500, "Server Internal Error", NULL);
211 sipe_file_transfer_lync_free(ft_private);
212 return;
215 call = ft_private->call;
216 call->candidate_pair_established_cb = candidate_pair_established_cb;
218 ft_private->public.ft_init = ft_lync_incoming_init;
219 ft_private->public.ft_deallocate = ft_lync_deallocate;
221 stream = sipe_core_media_get_stream_by_id(call, "data");
222 sipe_media_stream_add_extra_attribute(stream, "recvonly", NULL);
223 sipe_media_stream_set_data(stream, ft_private, NULL);
225 sipe_backend_ft_incoming(SIPE_CORE_PUBLIC, SIPE_FILE_TRANSFER,
226 call->with, ft_private->file_name,
227 ft_private->file_size);
231 Local Variables:
232 mode: c
233 c-file-style: "bsd"
234 indent-tabs-mode: t
235 tab-width: 8
236 End: