Mercurial > pidgin
comparison libpurple/protocols/irc/dcc_send.c @ 32819:2c6510167895 default tip
propagate from branch 'im.pidgin.pidgin.2.x.y' (head 3315c5dfbd0ad16511bdcf865e5b07c02d07df24)
to branch 'im.pidgin.pidgin' (head cbd1eda6bcbf0565ae7766396bb8f6f419cb6a9a)
author | Elliott Sales de Andrade <qulogic@pidgin.im> |
---|---|
date | Sat, 02 Jun 2012 02:30:49 +0000 |
parents | 1f56d5102483 |
children |
comparison
equal
deleted
inserted
replaced
32818:01ff09d4a463 | 32819:2c6510167895 |
---|---|
32 * Functions related to receiving files via DCC SEND | 32 * Functions related to receiving files via DCC SEND |
33 ***************************************************************************/ | 33 ***************************************************************************/ |
34 | 34 |
35 struct irc_xfer_rx_data { | 35 struct irc_xfer_rx_data { |
36 gchar *ip; | 36 gchar *ip; |
37 unsigned int remote_port; | |
37 }; | 38 }; |
38 | 39 |
39 static void irc_dccsend_recv_destroy(PurpleXfer *xfer) | 40 static void irc_dccsend_recv_destroy(PurpleXfer *xfer) |
40 { | 41 { |
41 struct irc_xfer_rx_data *xd = xfer->data; | 42 struct irc_xfer_rx_data *xd = purple_xfer_get_protocol_data(xfer); |
42 | 43 |
43 g_free(xd->ip); | 44 g_free(xd->ip); |
44 g_free(xd); | 45 g_free(xd); |
45 } | 46 } |
46 | 47 |
49 * It sends the acknowledgement (in the form of a total byte count as an | 50 * It sends the acknowledgement (in the form of a total byte count as an |
50 * unsigned 4 byte integer in network byte order) | 51 * unsigned 4 byte integer in network byte order) |
51 */ | 52 */ |
52 static void irc_dccsend_recv_ack(PurpleXfer *xfer, const guchar *data, size_t size) { | 53 static void irc_dccsend_recv_ack(PurpleXfer *xfer, const guchar *data, size_t size) { |
53 guint32 l; | 54 guint32 l; |
54 size_t result; | 55 gssize result; |
55 | 56 |
56 l = htonl(xfer->bytes_sent); | 57 l = htonl(purple_xfer_get_bytes_sent(xfer)); |
57 result = write(xfer->fd, &l, sizeof(l)); | 58 result = purple_xfer_write(xfer, (guchar *)&l, sizeof(l)); |
58 if (result != sizeof(l)) { | 59 if (result != sizeof(l)) { |
59 purple_debug_error("irc", "unable to send acknowledgement: %s\n", g_strerror(errno)); | 60 purple_debug_error("irc", "unable to send acknowledgement: %s\n", g_strerror(errno)); |
60 /* TODO: We should probably close the connection here or something. */ | 61 /* TODO: We should probably close the connection here or something. */ |
61 } | 62 } |
62 } | 63 } |
63 | 64 |
64 static void irc_dccsend_recv_init(PurpleXfer *xfer) { | 65 static void irc_dccsend_recv_init(PurpleXfer *xfer) { |
65 struct irc_xfer_rx_data *xd = xfer->data; | 66 struct irc_xfer_rx_data *xd = purple_xfer_get_protocol_data(xfer); |
66 | 67 |
67 purple_xfer_start(xfer, -1, xd->ip, xfer->remote_port); | 68 purple_xfer_start(xfer, -1, xd->ip, xd->remote_port); |
68 g_free(xd->ip); | 69 g_free(xd->ip); |
69 xd->ip = NULL; | 70 xd->ip = NULL; |
70 } | 71 } |
71 | 72 |
72 /* This function makes the necessary arrangements for receiving files */ | 73 /* This function makes the necessary arrangements for receiving files */ |
112 | 113 |
113 xfer = purple_xfer_new(irc->account, PURPLE_XFER_RECEIVE, from); | 114 xfer = purple_xfer_new(irc->account, PURPLE_XFER_RECEIVE, from); |
114 if (xfer) | 115 if (xfer) |
115 { | 116 { |
116 xd = g_new0(struct irc_xfer_rx_data, 1); | 117 xd = g_new0(struct irc_xfer_rx_data, 1); |
117 xfer->data = xd; | 118 purple_xfer_set_protocol_data(xfer, xd); |
118 | 119 |
119 purple_xfer_set_filename(xfer, filename->str); | 120 purple_xfer_set_filename(xfer, filename->str); |
120 xfer->remote_port = atoi(token[i+1]); | 121 xd->remote_port = atoi(token[i+1]); |
121 | 122 |
122 nip = strtoul(token[i], NULL, 10); | 123 nip = strtoul(token[i], NULL, 10); |
123 if (nip) { | 124 if (nip) { |
124 addr.s_addr = htonl(nip); | 125 addr.s_addr = htonl(nip); |
125 xd->ip = g_strdup(inet_ntoa(addr)); | 126 xd->ip = g_strdup(inet_ntoa(addr)); |
155 guint rxlen; | 156 guint rxlen; |
156 }; | 157 }; |
157 | 158 |
158 static void irc_dccsend_send_destroy(PurpleXfer *xfer) | 159 static void irc_dccsend_send_destroy(PurpleXfer *xfer) |
159 { | 160 { |
160 struct irc_xfer_send_data *xd = xfer->data; | 161 struct irc_xfer_send_data *xd = purple_xfer_get_protocol_data(xfer); |
161 | 162 |
162 if (xd == NULL) | 163 if (xd == NULL) |
163 return; | 164 return; |
164 | 165 |
165 if (xd->listen_data != NULL) | 166 if (xd->listen_data != NULL) |
176 | 177 |
177 /* just in case you were wondering, this is why DCC is gay */ | 178 /* just in case you were wondering, this is why DCC is gay */ |
178 static void irc_dccsend_send_read(gpointer data, int source, PurpleInputCondition cond) | 179 static void irc_dccsend_send_read(gpointer data, int source, PurpleInputCondition cond) |
179 { | 180 { |
180 PurpleXfer *xfer = data; | 181 PurpleXfer *xfer = data; |
181 struct irc_xfer_send_data *xd = xfer->data; | 182 struct irc_xfer_send_data *xd = purple_xfer_get_protocol_data(xfer); |
182 char buffer[64]; | 183 char buffer[64]; |
183 int len; | 184 int len; |
184 | 185 |
185 len = read(source, buffer, sizeof(buffer)); | 186 len = read(source, buffer, sizeof(buffer)); |
186 | 187 |
226 } | 227 } |
227 | 228 |
228 static gssize irc_dccsend_send_write(const guchar *buffer, size_t size, PurpleXfer *xfer) | 229 static gssize irc_dccsend_send_write(const guchar *buffer, size_t size, PurpleXfer *xfer) |
229 { | 230 { |
230 gssize s; | 231 gssize s; |
231 int ret; | 232 gssize ret; |
232 | 233 |
233 s = MIN(purple_xfer_get_bytes_remaining(xfer), size); | 234 s = MIN(purple_xfer_get_bytes_remaining(xfer), size); |
234 if (!s) | 235 if (!s) |
235 return 0; | 236 return 0; |
236 | 237 |
237 ret = write(xfer->fd, buffer, s); | 238 ret = purple_xfer_write(xfer, buffer, s); |
238 | 239 |
239 if (ret < 0 && errno == EAGAIN) | 240 if (ret < 0 && errno == EAGAIN) |
240 ret = 0; | 241 ret = 0; |
241 | 242 |
242 return ret; | 243 return ret; |
243 } | 244 } |
244 | 245 |
245 static void irc_dccsend_send_connected(gpointer data, int source, PurpleInputCondition cond) { | 246 static void irc_dccsend_send_connected(gpointer data, int source, PurpleInputCondition cond) { |
246 PurpleXfer *xfer = (PurpleXfer *) data; | 247 PurpleXfer *xfer = (PurpleXfer *) data; |
247 struct irc_xfer_send_data *xd = xfer->data; | 248 struct irc_xfer_send_data *xd = purple_xfer_get_protocol_data(xfer); |
248 int conn, flags; | 249 int conn, flags; |
249 | 250 |
250 conn = accept(xd->fd, NULL, 0); | 251 conn = accept(xd->fd, NULL, 0); |
251 if (conn == -1) { | 252 if (conn == -1) { |
252 /* Accepting the connection failed. This could just be related | 253 /* Accepting the connection failed. This could just be related |
255 /* Let's print an error message anyway */ | 256 /* Let's print an error message anyway */ |
256 purple_debug_warning("irc", "accept: %s\n", g_strerror(errno)); | 257 purple_debug_warning("irc", "accept: %s\n", g_strerror(errno)); |
257 return; | 258 return; |
258 } | 259 } |
259 | 260 |
260 purple_input_remove(xfer->watcher); | 261 purple_input_remove(purple_xfer_get_watcher(xfer)); |
261 xfer->watcher = 0; | 262 purple_xfer_set_watcher(xfer, 0); |
262 close(xd->fd); | 263 close(xd->fd); |
263 xd->fd = -1; | 264 xd->fd = -1; |
264 | 265 |
265 flags = fcntl(conn, F_GETFL); | 266 flags = fcntl(conn, F_GETFL); |
266 fcntl(conn, F_SETFL, flags | O_NONBLOCK); | 267 fcntl(conn, F_SETFL, flags | O_NONBLOCK); |
283 const char *arg[2]; | 284 const char *arg[2]; |
284 char *tmp; | 285 char *tmp; |
285 struct in_addr addr; | 286 struct in_addr addr; |
286 unsigned short int port; | 287 unsigned short int port; |
287 | 288 |
288 xd = xfer->data; | 289 xd = purple_xfer_get_protocol_data(xfer); |
289 xd->listen_data = NULL; | 290 xd->listen_data = NULL; |
290 | 291 |
291 if (purple_xfer_get_status(xfer) == PURPLE_XFER_STATUS_CANCEL_LOCAL | 292 if (purple_xfer_get_status(xfer) == PURPLE_XFER_STATUS_CANCEL_LOCAL |
292 || purple_xfer_get_status(xfer) == PURPLE_XFER_STATUS_CANCEL_REMOTE) { | 293 || purple_xfer_get_status(xfer) == PURPLE_XFER_STATUS_CANCEL_REMOTE) { |
293 purple_xfer_unref(xfer); | 294 purple_xfer_unref(xfer); |
294 return; | 295 return; |
295 } | 296 } |
296 | 297 |
297 xd = xfer->data; | 298 xd = purple_xfer_get_protocol_data(xfer); |
298 gc = purple_account_get_connection(purple_xfer_get_account(xfer)); | 299 gc = purple_account_get_connection(purple_xfer_get_account(xfer)); |
299 irc = gc->proto_data; | 300 irc = purple_connection_get_protocol_data(gc); |
300 | 301 |
301 purple_xfer_unref(xfer); | 302 purple_xfer_unref(xfer); |
302 | 303 |
303 if (sock < 0) { | 304 if (sock < 0) { |
304 purple_notify_error(gc, NULL, _("File Transfer Failed"), | 305 purple_notify_error(gc, NULL, _("File Transfer Failed"), |
310 xd->fd = sock; | 311 xd->fd = sock; |
311 | 312 |
312 port = purple_network_get_port_from_fd(sock); | 313 port = purple_network_get_port_from_fd(sock); |
313 purple_debug_misc("irc", "port is %hu\n", port); | 314 purple_debug_misc("irc", "port is %hu\n", port); |
314 /* Monitor the listening socket */ | 315 /* Monitor the listening socket */ |
315 xfer->watcher = purple_input_add(sock, PURPLE_INPUT_READ, | 316 purple_xfer_set_watcher(xfer, purple_input_add(sock, PURPLE_INPUT_READ, |
316 irc_dccsend_send_connected, xfer); | 317 irc_dccsend_send_connected, xfer)); |
317 | 318 |
318 /* Send the intended recipient the DCC request */ | 319 /* Send the intended recipient the DCC request */ |
319 arg[0] = xfer->who; | 320 arg[0] = purple_xfer_get_remote_user(xfer); |
320 inet_aton(purple_network_get_my_ip(irc->fd), &addr); | 321 inet_aton(purple_network_get_my_ip(irc->fd), &addr); |
321 arg[1] = tmp = g_strdup_printf("\001DCC SEND \"%s\" %u %hu %" G_GSIZE_FORMAT "\001", | 322 arg[1] = tmp = g_strdup_printf("\001DCC SEND \"%s\" %u %hu %" G_GOFFSET_FORMAT "\001", |
322 xfer->filename, ntohl(addr.s_addr), | 323 purple_xfer_get_filename(xfer), ntohl(addr.s_addr), |
323 port, xfer->size); | 324 port, purple_xfer_get_size(xfer)); |
324 | 325 |
325 irc_cmd_privmsg(gc->proto_data, "msg", NULL, arg); | 326 irc_cmd_privmsg(purple_connection_get_protocol_data(gc), "msg", NULL, arg); |
326 g_free(tmp); | 327 g_free(tmp); |
327 } | 328 } |
328 | 329 |
329 /* | 330 /* |
330 * This function is called after the user has selected a file to send. | 331 * This function is called after the user has selected a file to send. |
331 */ | 332 */ |
332 static void irc_dccsend_send_init(PurpleXfer *xfer) { | 333 static void irc_dccsend_send_init(PurpleXfer *xfer) { |
333 PurpleConnection *gc = purple_account_get_connection(purple_xfer_get_account(xfer)); | 334 PurpleConnection *gc = purple_account_get_connection(purple_xfer_get_account(xfer)); |
334 struct irc_xfer_send_data *xd = xfer->data; | 335 struct irc_xfer_send_data *xd = purple_xfer_get_protocol_data(xfer); |
335 | 336 |
336 xfer->filename = g_path_get_basename(xfer->local_filename); | 337 purple_xfer_set_filename(xfer, g_path_get_basename(purple_xfer_get_local_filename(xfer))); |
337 | 338 |
338 purple_xfer_ref(xfer); | 339 purple_xfer_ref(xfer); |
339 | 340 |
340 /* Create a listening socket */ | 341 /* Create a listening socket */ |
341 xd->listen_data = purple_network_listen_range(0, 0, SOCK_STREAM, | 342 xd->listen_data = purple_network_listen_range(0, 0, AF_UNSPEC, SOCK_STREAM, TRUE, |
342 irc_dccsend_network_listen_cb, xfer); | 343 irc_dccsend_network_listen_cb, xfer); |
343 if (xd->listen_data == NULL) { | 344 if (xd->listen_data == NULL) { |
344 purple_xfer_unref(xfer); | 345 purple_xfer_unref(xfer); |
345 purple_notify_error(gc, NULL, _("File Transfer Failed"), | 346 purple_notify_error(gc, NULL, _("File Transfer Failed"), |
346 _("Unable to open a listening port.")); | 347 _("Unable to open a listening port.")); |
357 xfer = purple_xfer_new(purple_connection_get_account(gc), PURPLE_XFER_SEND, who); | 358 xfer = purple_xfer_new(purple_connection_get_account(gc), PURPLE_XFER_SEND, who); |
358 if (xfer) | 359 if (xfer) |
359 { | 360 { |
360 xd = g_new0(struct irc_xfer_send_data, 1); | 361 xd = g_new0(struct irc_xfer_send_data, 1); |
361 xd->fd = -1; | 362 xd->fd = -1; |
362 xfer->data = xd; | 363 purple_xfer_set_protocol_data(xfer, xd); |
363 | 364 |
364 /* Setup our I/O op functions */ | 365 /* Setup our I/O op functions */ |
365 purple_xfer_set_init_fnc(xfer, irc_dccsend_send_init); | 366 purple_xfer_set_init_fnc(xfer, irc_dccsend_send_init); |
366 purple_xfer_set_write_fnc(xfer, irc_dccsend_send_write); | 367 purple_xfer_set_write_fnc(xfer, irc_dccsend_send_write); |
367 purple_xfer_set_end_fnc(xfer, irc_dccsend_send_destroy); | 368 purple_xfer_set_end_fnc(xfer, irc_dccsend_send_destroy); |