comparison src/protocols/jabber/si.c @ 7395:b250288fa948

[gaim-migrate @ 7990] this would be the non-working start of file transfer (the real way) for jabber also approximately eleventy billion jabber tweaks committer: Tailor Script <tailor@pidgin.im>
author Nathan Walp <nwalp@pidgin.im>
date Fri, 31 Oct 2003 02:43:58 +0000
parents
children 8f4ce853e685
comparison
equal deleted inserted replaced
7394:c6ff3c1fb1b3 7395:b250288fa948
1 /*
2 * gaim - Jabber Protocol Plugin
3 *
4 * Copyright (C) 2003, Nathan Walp <faceprint@faceprint.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21 #include "internal.h"
22 #include "debug.h"
23 #include "ft.h"
24 #include "notify.h"
25 #include "util.h"
26
27 #include "buddy.h"
28 #include "jabber.h"
29 #include "iq.h"
30 #include "si.h"
31
32 #include "si.h"
33
34 static GaimXfer *jabber_si_xfer_find_by_id(JabberStream *js, const char *id)
35 {
36 GList *xfers;
37
38 if(!id)
39 return NULL;
40
41 for(xfers = js->file_transfers; xfers; xfers = xfers->next) {
42 GaimXfer *xfer = xfers->data;
43 JabberSIXfer *jsx = xfer->data;
44
45 if(!strcmp(jsx->id, id))
46 return xfer;
47 }
48
49 return NULL;
50 }
51
52 static void
53 jabber_si_xfer_ibb_start(JabberStream *js, xmlnode *packet, gpointer data) {
54 GaimXfer *xfer = data;
55 JabberSIXfer *jsx = xfer->data;
56
57 /* Make sure we didn't get an error back */
58
59 /* XXX: OK, here we need to set up a g_idle thing to send messages
60 * until our eyes bleed, but do it without interfering with normal
61 * gaim operations. When we're done, we have to send a <close> like
62 * we sent the <open> to start this damn thing. If we're really
63 * fortunate, Exodus or someone else will implement something to test
64 * against soon */
65 }
66
67 void jabber_si_parse(JabberStream *js, xmlnode *packet)
68 {
69 GaimXfer *xfer;
70 JabberSIXfer *jsx;
71 xmlnode *si, *feature, *x, *field, *value;
72
73 si = xmlnode_get_child(packet, "si");
74
75 xfer = jabber_si_xfer_find_by_id(js, xmlnode_get_attrib(si, "id"));
76
77 if(!xfer)
78 return;
79
80 jsx = xfer->data;
81
82 if(!(feature = xmlnode_get_child(si, "feature")))
83 return;
84
85 for(x = feature->child; x; x = x->next) {
86 const char *xmlns;
87 if(x->type != NODE_TYPE_TAG)
88 continue;
89 if(!(xmlns = xmlnode_get_attrib(x, "xmlns")))
90 continue;
91 if(strcmp(xmlns, "jabber:x:data"))
92 continue;
93 for(field = x->child; field; field = field->next) {
94 const char *var;
95 if(field->type != NODE_TYPE_TAG)
96 continue;
97 if(!(var = xmlnode_get_attrib(field, "var")))
98 continue;
99 if(!strcmp(var, "stream-method")) {
100 if((value = xmlnode_get_child(field, "value"))) {
101 char *val_data = xmlnode_get_data(value);
102 if(!val_data)
103 jsx->stream_method = STREAM_METHOD_UNKNOWN;
104 else if(!strcmp(val_data,
105 "http://jabber.org/protocol/bytestreams"))
106 jsx->stream_method = STREAM_METHOD_BYTESTREAMS;
107 else if(!strcmp(val_data, "http://jabber.org/protocol/ibb"))
108 jsx->stream_method = STREAM_METHOD_IBB;
109 else
110 jsx->stream_method = STREAM_METHOD_UNSUPPORTED;
111 g_free(val_data);
112 }
113 }
114 }
115 }
116 if(jsx->stream_method == STREAM_METHOD_UNKNOWN) {
117 /* XXX */
118 } else if(jsx->stream_method == STREAM_METHOD_UNSUPPORTED) {
119 /* XXX */
120 } else if(jsx->stream_method == STREAM_METHOD_BYTESTREAMS) {
121 /* XXX: open the port and stuff */
122 char *buf;
123 xmlnode *query, *streamhost;
124 JabberIq *iq = jabber_iq_new_query(js, JABBER_IQ_SET,
125 "http://jabber.org/protocol/bytestreams");
126
127 buf = g_strdup_printf("%s/%s", xfer->who, jsx->resource);
128 xmlnode_set_attrib(iq->node, "to", buf);
129 g_free(buf);
130
131 query = xmlnode_get_child(iq->node, "query");
132 xmlnode_set_attrib(query, "sid", jsx->id);
133 streamhost = xmlnode_new_child(query, "streamhost");
134 xmlnode_set_attrib(streamhost, "jid",
135 gaim_account_get_username(js->gc->account));
136 xmlnode_set_attrib(streamhost, "host", xfer->local_ip);
137 buf = g_strdup_printf("%d", xfer->local_port);
138 xmlnode_set_attrib(streamhost, "port", buf);
139 g_free(buf);
140 jabber_iq_send(iq);
141 } else if(jsx->stream_method == STREAM_METHOD_IBB) {
142 char *buf;
143 xmlnode *open;
144 JabberIq *iq = jabber_iq_new(js, JABBER_IQ_SET);
145 buf = g_strdup_printf("%s/%s", xfer->who, jsx->resource);
146 xmlnode_set_attrib(iq->node, "to", buf);
147 g_free(buf);
148
149 open = xmlnode_new_child(iq->node, "open");
150 xmlnode_set_attrib(open, "xmlns", "http://jabber.org/protocol/ibb");
151 xmlnode_set_attrib(open, "sid", jsx->id);
152
153 jabber_iq_set_callback(iq, jabber_si_xfer_ibb_start, xfer);
154
155 jabber_iq_send(iq);
156
157 }
158 }
159
160 static void jabber_si_xfer_send_request(GaimXfer *xfer)
161 {
162 JabberSIXfer *jsx = xfer->data;
163 JabberIq *iq;
164 xmlnode *si, *file, *feature, *x, *field, *option, *value;
165 char buf[32];
166 char *to;
167
168 xfer->filename = g_path_get_basename(xfer->local_filename);
169
170 iq = jabber_iq_new(jsx->js, JABBER_IQ_SET);
171 to = g_strdup_printf("%s/%s", xfer->who, jsx->resource);
172 xmlnode_set_attrib(iq->node, "to", to);
173 g_free(to);
174 si = xmlnode_new_child(iq->node, "si");
175 xmlnode_set_attrib(si, "xmlns", "http://jabber.org/protocol/si");
176 jsx->id = jabber_get_next_id(jsx->js);
177 xmlnode_set_attrib(si, "id", jsx->id);
178 xmlnode_set_attrib(si, "profile",
179 "http://jabber.org/protocol/si/profile/file-transfer");
180
181 file = xmlnode_new_child(si, "file");
182 xmlnode_set_attrib(file, "xmlns",
183 "http://jabber.org/protocol/si/profile/file-transfer");
184 xmlnode_set_attrib(file, "name", xfer->filename);
185 g_snprintf(buf, sizeof(buf), "%d", xfer->size);
186 xmlnode_set_attrib(file, "size", buf);
187 /* maybe later we'll do hash and date attribs */
188
189 feature = xmlnode_new_child(si, "feature");
190 xmlnode_set_attrib(feature, "xmlns",
191 "http://jabber.org/protocol/feature-neg");
192 x = xmlnode_new_child(feature, "x");
193 xmlnode_set_attrib(x, "xmlns", "jabber:x:data");
194 xmlnode_set_attrib(x, "type", "form");
195 field = xmlnode_new_child(x, "field");
196 xmlnode_set_attrib(field, "var", "stream-method");
197 xmlnode_set_attrib(field, "type", "list-single");
198 option = xmlnode_new_child(field, "option");
199 value = xmlnode_new_child(option, "value");
200 xmlnode_insert_data(value, "http://jabber.org/protocol/bytestreams",
201 -1);
202 option = xmlnode_new_child(field, "option");
203 value = xmlnode_new_child(option, "value");
204 xmlnode_insert_data(value, "http://jabber.org/protocol/ibb", -1);
205
206 jabber_iq_send(iq);
207 }
208
209 void jabber_si_xfer_init(GaimXfer *xfer)
210 {
211 JabberSIXfer *jsx = xfer->data;
212 if(gaim_xfer_get_type(xfer) == GAIM_XFER_SEND) {
213 JabberBuddy *jb;
214 JabberBuddyResource *jbr = NULL;
215 GList *resources;
216 GList *xfer_resources = NULL;
217
218 jb = jabber_buddy_find(jsx->js, xfer->who, TRUE);
219 if(!jb)
220 return;
221
222 for(resources = jb->resources; resources; resources = resources->next) {
223 jbr = resources->data;
224 if(jbr->capabilities & JABBER_CAP_SI_FILE_XFER)
225 xfer_resources = g_list_append(xfer_resources, jbr);
226 }
227
228 if(g_list_length(xfer_resources) == 1) {
229 jbr = xfer_resources->data;
230 jsx->resource = g_strdup(jbr->name);
231 jabber_si_xfer_send_request(xfer);
232 } else if(g_list_length(xfer_resources) == 0) {
233 char *buf = g_strdup_printf(_("Could not send %s to %s, protocol not supported."), xfer->filename, xfer->who);
234 gaim_notify_error(jsx->js->gc, _("File Send Failed"),
235 _("File Send Failed"), buf);
236 g_free(buf);
237 } else {
238 /* XXX: ask which resource to send to! */
239 }
240 g_list_free(xfer_resources);
241 }
242 }
243
244 void jabber_si_xfer_start(GaimXfer *xfer)
245 {
246 gaim_debug(GAIM_DEBUG_INFO, "jabber", "in jabber_si_xfer_start\n");
247 }
248
249 void jabber_si_xfer_end(GaimXfer *xfer)
250 {
251 gaim_debug(GAIM_DEBUG_INFO, "jabber", "in jabber_si_xfer_end\n");
252 }
253
254 void jabber_si_xfer_cancel_send(GaimXfer *xfer)
255 {
256 gaim_debug(GAIM_DEBUG_INFO, "jabber", "in jabber_si_xfer_cancel_send\n");
257 }
258
259
260 void jabber_si_xfer_cancel_recv(GaimXfer *xfer)
261 {
262 gaim_debug(GAIM_DEBUG_INFO, "jabber", "in jabber_si_xfer_cancel_recv\n");
263 }
264
265
266 void jabber_si_xfer_ack(GaimXfer *xfer, const char *buffer, size_t size)
267 {
268 gaim_debug(GAIM_DEBUG_INFO, "jabber", "in jabber_si_xfer_ack\n");
269 }
270