static gssize yahoo_xfer_write(const guchar *buffer, size_t size, PurpleXfer *xfer) { gssize len; struct yahoo_xfer_data *xd = xfer->data; if (!xd) return -1; if (purple_xfer_get_type(xfer) != PURPLE_XFER_SEND) { return -1; } len = write(xfer->fd, buffer, size); if (len == -1) { if (purple_xfer_get_bytes_sent(xfer) >= purple_xfer_get_size(xfer)) purple_xfer_set_completed(xfer, TRUE); if ((errno != EAGAIN) && (errno != EINTR)) return -1; return 0; } if ((purple_xfer_get_bytes_sent(xfer) + len) >= purple_xfer_get_size(xfer)) purple_xfer_set_completed(xfer, TRUE); return len; }
static void tgprpl_xfer_recv_on_finished (struct tgl_state *TLS, void *_data, int success, const char *filename) { debug ("tgprpl_xfer_recv_on_finished()"); struct tgp_xfer_send_data *data = _data; char *selected = g_strdup (purple_xfer_get_local_filename (data->xfer)); if (success) { debug ("purple_xfer_set_completed"); // always completed the file transfer to avoid a warning dialogue when closing (Adium) purple_xfer_set_bytes_sent (data->xfer, purple_xfer_get_size (data->xfer)); purple_xfer_set_completed (data->xfer, TRUE); if (! purple_xfer_is_canceled (data->xfer)) { purple_xfer_end (data->xfer); } } else { tgp_notify_on_error_gw (TLS, NULL, success); if (! purple_xfer_is_canceled (data->xfer)) { purple_xfer_cancel_remote (data->xfer); } failure ("recv xfer failed"); } data->loading = FALSE; data->xfer->data = NULL; purple_xfer_unref (data->xfer); tgprpl_xfer_free_data (data); debug ("moving transferred file from tgl directory %s to selected target %s", selected, filename); g_unlink (selected); g_rename (filename, selected); g_free (selected); }
static void ggp_edisc_xfer_recv_done(PurpleHttpConnection *hc, PurpleHttpResponse *response, gpointer _xfer) { PurpleXfer *xfer = _xfer; ggp_edisc_xfer *edisc_xfer = purple_xfer_get_protocol_data(xfer); if (purple_xfer_is_cancelled(xfer)) return; g_return_if_fail(edisc_xfer != NULL); edisc_xfer->hc = NULL; if (!purple_http_response_is_successful(response)) { ggp_edisc_xfer_error(xfer, _("Error while receiving a file")); return; } if (purple_xfer_get_bytes_remaining(xfer) == 0) { purple_xfer_set_completed(xfer, TRUE); purple_xfer_end(xfer); ggp_edisc_xfer_free(xfer); } else { purple_debug_warning("gg", "ggp_edisc_xfer_recv_done: didn't " "received everything\n"); ggp_edisc_xfer_error(xfer, _("Error while receiving a file")); } }
/*------------------------------------------------------------------------ * A file has been received from the MXit server. * * @param session The MXit session object * @param fileid A unique ID that identifies this file * @param data The file data * @param datalen The size of the data */ void mxit_xfer_rx_file( struct MXitSession* session, const char* fileid, const char* data, int datalen ) { PurpleXfer* xfer = NULL; struct mxitxfer* mx = NULL; purple_debug_info( MXIT_PLUGIN_ID, "mxit_xfer_rx_file: (size=%i)\n", datalen ); /* find the file-transfer object */ xfer = find_mxit_xfer( session, fileid ); if ( xfer ) { mx = xfer->data; /* this is the transfer we have been looking for */ purple_xfer_ref( xfer ); purple_xfer_start( xfer, -1, NULL, 0 ); fwrite( data, datalen, 1, xfer->dest_fp ); purple_xfer_unref( xfer ); purple_xfer_set_completed( xfer, TRUE ); purple_xfer_end( xfer ); /* inform MXit that file was successfully received */ mxit_send_file_received( session, fileid, RECV_STATUS_SUCCESS ); } else { /* file transfer not found */ mxit_send_file_received( session, fileid, RECV_STATUS_BAD_ID ); } }
static void tgprpl_xfer_send_on_finished (struct tgl_state *TLS, void *_data, int success, struct tgl_message *M) { debug ("tgprpl_xfer_on_finished()"); struct tgp_xfer_send_data *data = _data; if (success) { if (! purple_xfer_is_canceled (data->xfer)) { debug ("purple_xfer_set_completed"); purple_xfer_set_bytes_sent (data->xfer, purple_xfer_get_size (data->xfer)); purple_xfer_set_completed (data->xfer, TRUE); purple_xfer_end (data->xfer); } write_secret_chat_file (TLS); } else { tgp_notify_on_error_gw (TLS, NULL, success); if (! purple_xfer_is_canceled (data->xfer)) { purple_xfer_cancel_remote (data->xfer); } failure ("send xfer failed"); } data->loading = FALSE; data->xfer->data = NULL; purple_xfer_unref (data->xfer); tgprpl_xfer_free_data (data); }
/*------------------------------------------------------------------------ * A file has been received from the MXit server. * * @param session The MXit session object * @param fileid A unique ID that identifies this file * @param data The file data * @param datalen The size of the data */ void mxit_xfer_rx_file( struct MXitSession* session, const char* fileid, const char* data, int datalen ) { PurpleXfer* xfer = NULL; purple_debug_info( MXIT_PLUGIN_ID, "mxit_xfer_rx_file: (size=%i)\n", datalen ); /* find the file-transfer object */ xfer = find_mxit_xfer( session, fileid ); if ( xfer ) { /* this is the transfer we have been looking for */ purple_xfer_ref( xfer ); purple_xfer_start( xfer, -1, NULL, 0 ); if ( fwrite( data, datalen, 1, xfer->dest_fp ) > 0 ) { purple_xfer_unref( xfer ); purple_xfer_set_completed( xfer, TRUE ); purple_xfer_end( xfer ); /* inform MXit that file was successfully received */ mxit_send_file_received( session, fileid, RECV_STATUS_SUCCESS ); } else { /* file write error */ purple_xfer_error( purple_xfer_get_type( xfer ), purple_xfer_get_account( xfer ), purple_xfer_get_remote_user( xfer ), _( "Unable to save the file" ) ); purple_xfer_cancel_local( xfer ); } } else { /* file transfer not found */ mxit_send_file_received( session, fileid, RECV_STATUS_BAD_ID ); } }
void msn_xfer_completed_cb(MsnSlpCall *slpcall, const guchar *body, gsize size) { PurpleXfer *xfer = slpcall->xfer; purple_xfer_set_completed(xfer, TRUE); purple_xfer_end(xfer); }
static void xfer_completed_cb(struct pn_peer_call *call, const guchar *body, gsize size) { PurpleXfer *xfer = call->xfer; purple_xfer_set_completed(xfer, TRUE); purple_xfer_end(xfer); }
static void _qq_update_send_progess(PurpleConnection *gc, guint32 fragment_index) { guint32 mask; guint8 *buffer; gint readbytes; qq_data *qd = (qq_data *) gc->proto_data; PurpleXfer *xfer = qd->xfer; ft_info *info = (ft_info *) xfer->data; purple_debug_info("QQ", "receiving %dth fragment ack, slide window status %o, max_fragment_index %d\n", fragment_index, info->window, info->max_fragment_index); if (fragment_index < info->max_fragment_index || fragment_index >= info->max_fragment_index + sizeof(info->window)) { purple_debug_info("QQ", "duplicate %dth fragment, drop it!\n", fragment_index+1); return; } mask = 0x1 << (fragment_index % sizeof(info->window)); if ((info->window & mask) == 0) { info->window |= mask; if (fragment_index + 1 != info->fragment_num) { xfer->bytes_sent += info->fragment_len; } else { xfer->bytes_sent += purple_xfer_get_size(xfer) % info->fragment_len; } xfer->bytes_remaining = purple_xfer_get_size(xfer) - purple_xfer_get_bytes_sent(xfer); purple_xfer_update_progress(xfer); if (purple_xfer_get_bytes_remaining(xfer) <= 0) { /* We have finished sending the file */ purple_xfer_set_completed(xfer, TRUE); return; } mask = 0x1 << (info->max_fragment_index % sizeof(info->window)); while (info->window & mask) { /* move the slide window */ info->window &= ~mask; buffer = g_newa(guint8, info->fragment_len); readbytes = _qq_xfer_read_file(buffer, info->max_fragment_index + sizeof(info->window), info->fragment_len, xfer); if (readbytes > 0) _qq_send_file_data_packet(gc, QQ_FILE_CMD_FILE_OP, QQ_FILE_DATA_INFO, info->max_fragment_index + sizeof(info->window) + 1, 0, buffer, readbytes); info->max_fragment_index ++; if (mask & 0x8000) mask = 0x0001; else mask = mask << 1; } } purple_debug_info("QQ", "procceed %dth fragment ack, slide window status %o, max_fragment_index %d\n", fragment_index, info->window, info->max_fragment_index); }
static gssize tftp_write(const guchar *buffer, size_t size, PurpleXfer *xfer) { gssize bytes_written = sipe_core_tftp_write(PURPLE_XFER_TO_SIPE_FILE_TRANSFER, buffer, size); if ((xfer->bytes_remaining - bytes_written) == 0) purple_xfer_set_completed(xfer, TRUE); return bytes_written; }
/* just in case you were wondering, this is why DCC is gay */ static void irc_dccsend_send_read(gpointer data, int source, PurpleInputCondition cond) { PurpleXfer *xfer = data; struct irc_xfer_send_data *xd = purple_xfer_get_protocol_data(xfer); char buffer[64]; int len; len = read(source, buffer, sizeof(buffer)); if (len < 0 && errno == EAGAIN) return; else if (len <= 0) { /* XXX: Shouldn't this be canceling the transfer? */ purple_input_remove(xd->inpa); xd->inpa = 0; return; } xd->rxqueue = g_realloc(xd->rxqueue, len + xd->rxlen); memcpy(xd->rxqueue + xd->rxlen, buffer, len); xd->rxlen += len; while (1) { gint32 val; size_t acked; if (xd->rxlen < 4) break; memcpy(&val, xd->rxqueue, sizeof(val)); acked = ntohl(val); xd->rxlen -= 4; if (xd->rxlen) { unsigned char *tmp = g_memdup(xd->rxqueue + 4, xd->rxlen); g_free(xd->rxqueue); xd->rxqueue = tmp; } else { g_free(xd->rxqueue); xd->rxqueue = NULL; } if ((goffset)acked >= purple_xfer_get_size(xfer)) { purple_input_remove(xd->inpa); xd->inpa = 0; purple_xfer_set_completed(xfer, TRUE); purple_xfer_end(xfer); return; } } }
static void send_offline_file_receipt(LwqqAsyncEvent* ev,PurpleXfer* xfer) { int errno = lwqq_async_event_get_result(ev); qq_account* ac = purple_connection_get_protocol_data(purple_account_get_connection(xfer->account)); LwqqMsgOffFile* file = xfer->data; if(errno == 0){ qq_sys_msg_write(ac, LWQQ_MT_BUDDY_MSG, file->to, "发送离线文件成功", PURPLE_MESSAGE_SYSTEM, time(NULL)); }else{ qq_sys_msg_write(ac, LWQQ_MT_BUDDY_MSG, file->to, "发送离线文件失败", PURPLE_MESSAGE_ERROR, time(NULL)); } lwqq_msg_offfile_free(file); purple_xfer_set_completed(xfer,1); }
static void waprpl_check_complete_uploads(PurpleConnection * gc) { whatsapp_connection *wconn = purple_connection_get_protocol_data(gc); GList *xfers = purple_xfers_get_all(); while (xfers) { PurpleXfer *xfer = xfers->data; wa_file_upload *xinfo = (wa_file_upload *) xfer->data; if (!xinfo->done && xinfo->started && waAPI_fileuploadcomplete(wconn->waAPI, xinfo->ref_id)) { purple_debug_info("waprpl", "Upload complete\n"); purple_xfer_set_completed(xfer, TRUE); xinfo->done = 1; } xfers = g_list_next(xfers); } }
static void skypeweb_init_vm_download(PurpleXfer *xfer) { JsonObject *file = xfer->data; gint64 fileSize; const gchar *url; fileSize = json_object_get_int_member(file, "fileSize"); url = json_object_get_string_member(file, "url"); purple_xfer_set_completed(xfer, FALSE); purple_util_fetch_url_request(xfer->account, url, TRUE, NULL, FALSE, NULL, FALSE, fileSize, skypeweb_got_vm_file, xfer); json_object_unref(file); }
static void send_file(LwqqAsyncEvent* event,PurpleXfer *xfer) { //now xfer is not valid. if(event->failcode != LWQQ_CALLBACK_VALID && event->failcode != LWQQ_CALLBACK_FAILED) return; qq_account* ac = purple_connection_get_protocol_data(purple_account_get_connection(xfer->account)); LwqqClient* lc = ac->qq; long err = 0; if(event->failcode==LWQQ_CALLBACK_FAILED){ lwqq_msg_free((LwqqMsg*)xfer->data); purple_xfer_set_completed(xfer, 1); return; } err = lwqq_async_event_get_result(event); LwqqMsgOffFile* file = xfer->data; if(err) { qq_sys_msg_write(ac,LWQQ_MS_BUDDY_MSG, file->super.to,_("Send offline file failed"),PURPLE_MESSAGE_ERROR,time(NULL)); lwqq_msg_free((LwqqMsg*)file); purple_xfer_set_completed(xfer,1); } else { LwqqAsyncEvent* ev = lwqq_msg_send_offfile(lc,file); lwqq_async_add_event_listener(ev,_C_(2p,send_offline_file_receipt,ev,xfer)); } }
static void send_offline_file_receipt(LwqqAsyncEvent* ev,PurpleXfer* xfer) { int err = lwqq_async_event_get_result(ev); qq_account* ac = purple_connection_get_protocol_data(purple_account_get_connection(xfer->account)); LwqqMsgOffFile* file = xfer->data; if(err == 0){ qq_sys_msg_write(ac, LWQQ_MS_BUDDY_MSG, file->super.to, _("Send offline file successful"), PURPLE_MESSAGE_SYSTEM, time(NULL)); }else{ char buf[512]; snprintf(buf,sizeof(buf),_("Send offline file failed,Error Code:%d"),err); qq_sys_msg_write(ac, LWQQ_MS_BUDDY_MSG, file->super.to, buf, PURPLE_MESSAGE_ERROR, time(NULL)); } lwqq_msg_free((LwqqMsg*)file); purple_xfer_set_completed(xfer,1); }
static void recv_file_complete(PurpleXfer* xfer,LwqqAsyncEvent* ev) { if(ev->failcode == LWQQ_CALLBACK_CANCELED) return; qq_account* ac = purple_connection_get_protocol_data(purple_account_get_connection(xfer->account)); LwqqMsgFileMessage* file = xfer->data; char buf[512]; const char* extra = NULL; if(ev->result) { snprintf(buf,sizeof(buf),"传输失败,错误号:%d\n",ev->result); if(ev->result == 102) extra = "对方是用webqq发送的吧.\n让对方发离线文件或邮件吧."; else extra = NULL; purple_notify_error(ac->gc,"文件传输",buf,extra); } purple_xfer_set_completed(xfer,1); lwqq_msg_free((LwqqMsg*)file); }
static void skypeweb_init_vm_download(PurpleXfer *xfer) { SkypeWebAccount *sa; JsonObject *file = xfer->data; gint64 fileSize; const gchar *url; fileSize = json_object_get_int_member(file, "fileSize"); url = json_object_get_string_member(file, "url"); purple_xfer_set_completed(xfer, FALSE); sa = purple_connection_get_protocol_data(purple_account_get_connection(xfer->account)); skypeweb_fetch_url_request(sa, url, TRUE, NULL, FALSE, NULL, FALSE, fileSize, skypeweb_got_vm_file, xfer); json_object_unref(file); }
static void recv_file_complete(PurpleXfer* xfer,LwqqAsyncEvent* ev) { if(ev->failcode == LWQQ_CALLBACK_CANCELED) return; qq_account* ac = purple_connection_get_protocol_data(purple_account_get_connection(xfer->account)); LwqqMsgFileMessage* file = xfer->data; char buf[512]; const char* extra = NULL; if(ev->result){ snprintf(buf,sizeof(buf),_("Transport Failed,Error Code:%d\n"),ev->result); if(ev->result == 102) extra = _("Other may send via webqq.\nPlease call him send via email or offline file."); else extra = NULL; purple_notify_error(ac->gc,_("File Transport"),buf,extra); } purple_xfer_set_completed(xfer,1); lwqq_msg_free((LwqqMsg*)file); }
static void tgprpl_xfer_on_finished (struct tgl_state *TLS, void *_data, int success, struct tgl_message *M) { debug ("tgprpl_xfer_on_finished()"); struct tgp_xfer_send_data *data = _data; if (success) { if (!data->done) { debug ("purple_xfer_set_completed"); purple_xfer_set_bytes_sent (data->xfer, purple_xfer_get_size (data->xfer)); purple_xfer_set_completed (data->xfer, TRUE); purple_xfer_end(data->xfer); } } else { failure ("ERROR xfer failed"); } data->xfer->data = NULL; tgprpl_xfer_free_data (data); }
static void skypeweb_got_file(PurpleUtilFetchUrlData *url_data, gpointer user_data, const gchar *url_text, gsize len, const gchar *error_message) { SkypeWebFileTransfer *swft = user_data; PurpleXfer *xfer = swft->xfer; SkypeWebAccount *sa = swft->sa; sa->url_datas = g_slist_remove(sa->url_datas, url_data); if (error_message) { purple_xfer_error(purple_xfer_get_type(xfer), sa->account, swft->from, error_message); purple_xfer_cancel_local(xfer); } else { purple_xfer_write_file(xfer, (guchar *)url_text, len); purple_xfer_set_bytes_sent(xfer, len); purple_xfer_set_completed(xfer, TRUE); } //cleanup skypeweb_free_xfer(xfer); }
static void send_file(LwqqAsyncEvent* event,PurpleXfer *xfer) { qq_account* ac = purple_connection_get_protocol_data(purple_account_get_connection(xfer->account)); LwqqClient* lc = ac->qq; long errno = 0; if(lwqq_async_event_get_code(event)==LWQQ_CALLBACK_FAILED){ s_free(xfer->data); return; } errno = lwqq_async_event_get_result(event); LwqqMsgOffFile* file = xfer->data; //purple_xfer_unref(xfer); if(errno) { qq_sys_msg_write(ac,LWQQ_MT_BUDDY_MSG, file->to,"上传空间不足",PURPLE_MESSAGE_ERROR,time(NULL)); lwqq_msg_offfile_free(file); s_free(xfer->data); purple_xfer_set_completed(xfer,1); } else { LwqqAsyncEvent* ev = lwqq_msg_send_offfile(lc,file); lwqq_async_add_event_listener(ev,_C_(2p,send_offline_file_receipt,ev,xfer)); } }
static void tgprpl_xfer_recv_on_finished (struct tgl_state *TLS, void *_data, int success, const char *filename) { debug ("tgprpl_xfer_recv_on_finished()"); struct tgp_xfer_send_data *data = _data; if (success) { if (!data->done) { debug ("purple_xfer_set_completed"); purple_xfer_set_bytes_sent (data->xfer, purple_xfer_get_size (data->xfer)); purple_xfer_set_completed (data->xfer, TRUE); purple_xfer_end (data->xfer); } g_unlink (purple_xfer_get_local_filename (data->xfer)); g_rename (filename, purple_xfer_get_local_filename (data->xfer)); } else { failure ("ERROR xfer failed"); } data->xfer->data = NULL; tgprpl_xfer_free_data (data); }
/* Checks if the WA protocol has data to output and schedules a write handler */ void waprpl_check_ssl_output(PurpleConnection * gc) { whatsapp_connection *wconn = purple_connection_get_protocol_data(gc); if (wconn->sslfd < 0) return; int r = waAPI_sslhasoutdata(wconn->waAPI); if (r > 0) { /* Need to watch for output data (if we are not doing it already) */ if (wconn->sslwh == 0) wconn->sslwh = purple_input_add(wconn->sslfd, PURPLE_INPUT_WRITE, waprpl_ssl_output_cb, gc); } else if (r < 0) { waprpl_ssl_cerr_cb(0, 0, gc); /* Finished the connection! */ } else { if (wconn->sslwh != 0) purple_input_remove(wconn->sslwh); wconn->sslwh = 0; } /* Update transfer status */ int rid, bytes_sent; if (waAPI_fileuploadprogress(wconn->waAPI, &rid, &bytes_sent)) { GList *xfers = purple_xfers_get_all(); while (xfers) { PurpleXfer *xfer = xfers->data; wa_file_upload *xinfo = (wa_file_upload *) xfer->data; if (xinfo->ref_id == rid) { purple_debug_info("waprpl", "Upload progress %d bytes done\n", bytes_sent); purple_xfer_set_bytes_sent(xfer, bytes_sent); purple_xfer_update_progress(xfer); if (bytes_sent >= (signed)purple_xfer_get_size(xfer)) purple_xfer_set_completed(xfer, TRUE); break; } xfers = g_list_next(xfers); } } }
gssize purple_xfer_write(PurpleXfer *xfer, const guchar *buffer, gsize size) { gssize r, s; g_return_val_if_fail(xfer != NULL, 0); g_return_val_if_fail(buffer != NULL, 0); g_return_val_if_fail(size != 0, 0); s = MIN(purple_xfer_get_bytes_remaining(xfer), size); if (xfer->ops.write != NULL) { r = (xfer->ops.write)(buffer, s, xfer); } else { r = write(xfer->fd, buffer, s); if (r < 0 && errno == EAGAIN) r = 0; if ((purple_xfer_get_bytes_sent(xfer)+r) >= purple_xfer_get_size(xfer)) purple_xfer_set_completed(xfer, TRUE); } return r; }
/*------------------------------------------------------------------------ * Send the file data. * * @param buffer The data to sent * @param size The length of the data to send * @param xfer The file transfer object * @return The amount of data actually sent */ static gssize mxit_xfer_write( const guchar* buffer, size_t size, PurpleXfer* xfer ) { struct mxitxfer* mx = (struct mxitxfer*) xfer->data; purple_debug_info( MXIT_PLUGIN_ID, "mxit_xfer_write\n" ); if ( !mx ) { purple_debug_warning( MXIT_PLUGIN_ID, "mxit_xfer_write: invalid internal mxit xfer data\n" ); return -1; } else if ( purple_xfer_get_type( xfer ) != PURPLE_XFER_SEND ) { purple_debug_warning( MXIT_PLUGIN_ID, "mxit_xfer_write: wrong xfer type received\n" ); return -1; } /* create and send the packet to MXit */ mxit_send_file( mx->session, purple_xfer_get_remote_user( xfer ), purple_xfer_get_filename( xfer ), buffer, size ); /* the transfer is complete */ purple_xfer_set_completed( xfer, TRUE ); return size; }
static void ggp_edisc_xfer_send_done(PurpleHttpConnection *hc, PurpleHttpResponse *response, gpointer _xfer) { PurpleXfer *xfer = _xfer; ggp_edisc_xfer *edisc_xfer = purple_xfer_get_protocol_data(xfer); const gchar *data = purple_http_response_get_data(response, NULL); JsonParser *parser; JsonObject *result; int result_status = -1; if (purple_xfer_is_cancelled(xfer)) return; g_return_if_fail(edisc_xfer != NULL); edisc_xfer->hc = NULL; if (!purple_http_response_is_successful(response)) { ggp_edisc_xfer_error(xfer, _("Error while sending a file")); return; } parser = ggp_json_parse(data); result = json_node_get_object(json_parser_get_root(parser)); result = json_object_get_object_member(result, "result"); if (json_object_has_member(result, "status")) result_status = json_object_get_int_member(result, "status"); g_object_unref(parser); if (result_status == 0) { purple_xfer_set_completed(xfer, TRUE); purple_xfer_end(xfer); ggp_edisc_xfer_free(xfer); } else ggp_edisc_xfer_error(xfer, _("Error while sending a file")); }
static void yahoo_process_filetrans_15_downloaded(PurpleHttpConnection *hc, PurpleHttpResponse *response, gpointer _xfer) { PurpleXfer *xfer = _xfer; struct yahoo_xfer_data *xd; xd = purple_xfer_get_protocol_data(xfer); xd->hc = NULL; if (purple_xfer_is_cancelled(xfer)) return; if (!purple_http_response_is_successful(response) || purple_xfer_get_bytes_remaining(xfer) > 0) { purple_xfer_set_status(xfer, PURPLE_XFER_STATUS_CANCEL_REMOTE); purple_xfer_end(xfer); } else { purple_xfer_set_completed(xfer, TRUE); purple_xfer_end(xfer); } }
static void do_transfer(PurpleXfer *xfer) { PurpleXferUiOps *ui_ops; guchar *buffer = NULL; gssize r = 0; ui_ops = purple_xfer_get_ui_ops(xfer); if (xfer->type == PURPLE_XFER_RECEIVE) { r = purple_xfer_read(xfer, &buffer); if (r > 0) { size_t wc; if (ui_ops && ui_ops->ui_write) wc = ui_ops->ui_write(xfer, buffer, r); else wc = fwrite(buffer, 1, r, xfer->dest_fp); if (wc != r) { purple_debug_error("filetransfer", "Unable to write whole buffer.\n"); purple_xfer_cancel_local(xfer); g_free(buffer); return; } if ((purple_xfer_get_size(xfer) > 0) && ((purple_xfer_get_bytes_sent(xfer)+r) >= purple_xfer_get_size(xfer))) purple_xfer_set_completed(xfer, TRUE); } else if(r < 0) { purple_xfer_cancel_remote(xfer); g_free(buffer); return; } } else if (xfer->type == PURPLE_XFER_SEND) { size_t result = 0; size_t s = MIN(purple_xfer_get_bytes_remaining(xfer), xfer->current_buffer_size); PurpleXferPrivData *priv = g_hash_table_lookup(xfers_data, xfer); gboolean read = TRUE; /* this is so the prpl can keep the connection open if it needs to for some odd reason. */ if (s == 0) { if (xfer->watcher) { purple_input_remove(xfer->watcher); xfer->watcher = 0; } return; } if (priv->buffer) { if (priv->buffer->len < s) { s -= priv->buffer->len; read = TRUE; } else { read = FALSE; } } if (read) { if (ui_ops && ui_ops->ui_read) { gssize tmp = ui_ops->ui_read(xfer, &buffer, s); if (tmp == 0) { /* * The UI claimed it was ready, but didn't have any data for * us... It will call purple_xfer_ui_ready when ready, which * sets back up this watcher. */ if (xfer->watcher != 0) { purple_input_remove(xfer->watcher); xfer->watcher = 0; } /* Need to indicate the prpl is still ready... */ priv->ready |= PURPLE_XFER_READY_PRPL; g_return_if_reached(); } else if (tmp < 0) { purple_debug_error("filetransfer", "Unable to read whole buffer.\n"); purple_xfer_cancel_local(xfer); return; } result = tmp; } else { buffer = g_malloc(s); result = fread(buffer, 1, s, xfer->dest_fp); if (result != s) { purple_debug_error("filetransfer", "Unable to read whole buffer.\n"); purple_xfer_cancel_local(xfer); g_free(buffer); return; } } } if (priv->buffer) { g_byte_array_append(priv->buffer, buffer, result); g_free(buffer); buffer = priv->buffer->data; result = priv->buffer->len; } r = purple_xfer_write(xfer, buffer, result); if (r == -1) { purple_xfer_cancel_remote(xfer); if (!priv->buffer) /* We don't free buffer if priv->buffer is set, because in that case buffer doesn't belong to us. */ g_free(buffer); return; } else if (r == result) { /* * We managed to write the entire buffer. This means our * network is fast and our buffer is too small, so make it * bigger. */ purple_xfer_increase_buffer_size(xfer); } else { if (ui_ops && ui_ops->data_not_sent) ui_ops->data_not_sent(xfer, buffer + r, result - r); } if (priv->buffer) { /* * Remove what we wrote * If we wrote the whole buffer the byte array will be empty * Otherwise we'll keep what wasn't sent for next time. */ buffer = NULL; g_byte_array_remove_range(priv->buffer, 0, r); } } if (r > 0) { if (purple_xfer_get_size(xfer) > 0) xfer->bytes_remaining -= r; xfer->bytes_sent += r; if (xfer->ops.ack != NULL) xfer->ops.ack(xfer, buffer, r); g_free(buffer); if (ui_ops != NULL && ui_ops->update_progress != NULL) ui_ops->update_progress(xfer, purple_xfer_get_progress(xfer)); } if (purple_xfer_is_completed(xfer)) purple_xfer_end(xfer); }
static void _qq_process_recv_file_data(PurpleConnection *gc, guint8 *data, gint len) { gint bytes ; qq_file_header fh; guint16 packet_type; guint16 packet_seq; guint8 sub_type; guint32 fragment_index; guint16 fragment_len; guint32 fragment_offset; qq_data *qd = (qq_data *) gc->proto_data; ft_info *info = (ft_info *) qd->xfer->data; bytes = 0; bytes += _qq_get_file_header(&fh, data + bytes); bytes += 1; /* skip an unknown byte */ bytes += qq_get16(&packet_type, data + bytes); switch(packet_type) { case QQ_FILE_CMD_FILE_OP: bytes += qq_get16(&packet_seq, data + bytes); bytes += qq_get8(&sub_type, data + bytes); switch (sub_type) { case QQ_FILE_BASIC_INFO: bytes += 4; /* file length, we have already known it from xfer */ bytes += qq_get32(&info->fragment_num, data + bytes); bytes += qq_get32(&info->fragment_len, data + bytes); /* FIXME: We must check the md5 here, * if md5 doesn't match we will ignore * the packet or send sth as error number */ info->max_fragment_index = 0; info->window = 0; purple_debug_info("QQ", "start receiving data, %d fragments with %d length each\n", info->fragment_num, info->fragment_len); _qq_send_file_data_packet(gc, QQ_FILE_CMD_FILE_OP_ACK, sub_type, 0, 0, NULL, 0); break; case QQ_FILE_DATA_INFO: bytes += qq_get32(&fragment_index, data + bytes); bytes += qq_get32(&fragment_offset, data + bytes); bytes += qq_get16(&fragment_len, data + bytes); purple_debug_info("QQ", "received %dth fragment with length %d, offset %d\n", fragment_index, fragment_len, fragment_offset); _qq_send_file_data_packet(gc, QQ_FILE_CMD_FILE_OP_ACK, sub_type, fragment_index, packet_seq, NULL, 0); _qq_recv_file_progess(gc, data + bytes, fragment_len, fragment_index, fragment_offset); break; case QQ_FILE_EOF: purple_debug_info("QQ", "end of receiving\n"); _qq_send_file_data_packet(gc, QQ_FILE_CMD_FILE_OP_ACK, sub_type, 0, 0, NULL, 0); break; } break; case QQ_FILE_CMD_FILE_OP_ACK: bytes += qq_get16(&packet_seq, data + bytes); bytes += qq_get8(&sub_type, data + bytes); switch (sub_type) { case QQ_FILE_BASIC_INFO: info->max_fragment_index = 0; info->window = 0; /* It is ready to send file data */ _qq_send_file_progess(gc); break; case QQ_FILE_DATA_INFO: bytes += qq_get32(&fragment_index, data + bytes); _qq_update_send_progess(gc, fragment_index); if (purple_xfer_is_completed(qd->xfer)) _qq_send_file_data_packet(gc, QQ_FILE_CMD_FILE_OP, QQ_FILE_EOF, 0, 0, NULL, 0); /* else _qq_send_file_progess(gc); */ break; case QQ_FILE_EOF: /* FIXME: OK, we can end the connection successfully */ _qq_send_file_data_packet(gc, QQ_FILE_EOF, 0, 0, 0, NULL, 0); purple_xfer_set_completed(qd->xfer, TRUE); break; } break; case QQ_FILE_EOF: _qq_send_file_data_packet(gc, QQ_FILE_EOF, 0, 0, 0, NULL, 0); purple_xfer_set_completed(qd->xfer, TRUE); purple_xfer_end(qd->xfer); break; case QQ_FILE_BASIC_INFO: purple_debug_info("QQ", "here\n"); _qq_send_file_data_packet(gc, QQ_FILE_DATA_INFO, 0, 0, 0, NULL, 0); break; default: purple_debug_info("QQ", "_qq_process_recv_file_data: unknown packet type [%d]\n", packet_type); break; } }