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);