comparison libpurple/ft.c @ 29712:d5fe33c3a765

propagate from branch 'im.pidgin.pidgin' (head 42a8485e73af5f2091d307b51c09dded94eceb24) to branch 'im.pidgin.pidgin.next.minor' (head 4edcf8da14be654127117da5af0cbdd7a0616439)
author John Bailey <rekkanoryo@rekkanoryo.org>
date Tue, 17 Nov 2009 07:33:47 +0000
parents 18667ce1f55d
children 1e19c439fa7a
comparison
equal deleted inserted replaced
28963:546e870dc506 29712:d5fe33c3a765
55 enum { 55 enum {
56 PURPLE_XFER_READY_NONE = 0x0, 56 PURPLE_XFER_READY_NONE = 0x0,
57 PURPLE_XFER_READY_UI = 0x1, 57 PURPLE_XFER_READY_UI = 0x1,
58 PURPLE_XFER_READY_PRPL = 0x2, 58 PURPLE_XFER_READY_PRPL = 0x2,
59 } ready; 59 } ready;
60 GByteArray *buffer;
60 } PurpleXferPrivData; 61 } PurpleXferPrivData;
61 62
62 static int purple_xfer_choose_file(PurpleXfer *xfer); 63 static int purple_xfer_choose_file(PurpleXfer *xfer);
63 64
64 static void 65 static void
65 purple_xfer_priv_data_destroy(gpointer data) 66 purple_xfer_priv_data_destroy(gpointer data)
66 { 67 {
67 PurpleXferPrivData *priv = data; 68 PurpleXferPrivData *priv = data;
68 69
70 if (priv->buffer)
71 g_byte_array_free(priv->buffer, TRUE);
72
69 g_free(priv); 73 g_free(priv);
70 } 74 }
71 75
72 GList * 76 GList *
73 purple_xfers_get_all() 77 purple_xfers_get_all()
91 95
92 xfer->ref = 1; 96 xfer->ref = 1;
93 xfer->type = type; 97 xfer->type = type;
94 xfer->account = account; 98 xfer->account = account;
95 xfer->who = g_strdup(who); 99 xfer->who = g_strdup(who);
96 xfer->ui_ops = purple_xfers_get_ui_ops(); 100 xfer->ui_ops = ui_ops = purple_xfers_get_ui_ops();
97 xfer->message = NULL; 101 xfer->message = NULL;
98 xfer->current_buffer_size = FT_INITIAL_BUFFER_SIZE; 102 xfer->current_buffer_size = FT_INITIAL_BUFFER_SIZE;
99 xfer->fd = -1; 103 xfer->fd = -1;
100 104
101 priv = g_new0(PurpleXferPrivData, 1); 105 priv = g_new0(PurpleXferPrivData, 1);
102 priv->ready = PURPLE_XFER_READY_NONE; 106 priv->ready = PURPLE_XFER_READY_NONE;
103 107
108 if (ui_ops && ui_ops->data_not_sent) {
109 /* If the ui will handle unsent data no need for buffer */
110 priv->buffer = NULL;
111 } else {
112 priv->buffer = g_byte_array_sized_new(FT_INITIAL_BUFFER_SIZE);
113 }
114
104 g_hash_table_insert(xfers_data, xfer, priv); 115 g_hash_table_insert(xfers_data, xfer, priv);
105 116
106 ui_ops = purple_xfer_get_ui_ops(xfer); 117 ui_ops = purple_xfer_get_ui_ops(xfer);
107 118
108 if (ui_ops != NULL && ui_ops->new_xfer != NULL) 119 if (ui_ops != NULL && ui_ops->new_xfer != NULL)
114 125
115 static void 126 static void
116 purple_xfer_destroy(PurpleXfer *xfer) 127 purple_xfer_destroy(PurpleXfer *xfer)
117 { 128 {
118 PurpleXferUiOps *ui_ops; 129 PurpleXferUiOps *ui_ops;
119 130 PurpleXferPrivData *priv;
120 g_return_if_fail(xfer != NULL); 131
132 g_return_if_fail(xfer != NULL);
133
134 priv = g_hash_table_lookup(xfers_data, xfer);
121 135
122 /* Close the file browser, if it's open */ 136 /* Close the file browser, if it's open */
123 purple_request_close_with_handle(xfer); 137 purple_request_close_with_handle(xfer);
124 138
125 if (purple_xfer_get_status(xfer) == PURPLE_XFER_STATUS_STARTED) 139 if (purple_xfer_get_status(xfer) == PURPLE_XFER_STATUS_STARTED)
965 r = (xfer->ops.write)(buffer, s, xfer); 979 r = (xfer->ops.write)(buffer, s, xfer);
966 } else { 980 } else {
967 r = write(xfer->fd, buffer, s); 981 r = write(xfer->fd, buffer, s);
968 if (r < 0 && errno == EAGAIN) 982 if (r < 0 && errno == EAGAIN)
969 r = 0; 983 r = 0;
970 if ((purple_xfer_get_bytes_sent(xfer)+r) >= purple_xfer_get_size(xfer))
971 purple_xfer_set_completed(xfer, TRUE);
972 } 984 }
973 985
974 return r; 986 return r;
975 } 987 }
976 988
997 purple_xfer_cancel_local(xfer); 1009 purple_xfer_cancel_local(xfer);
998 g_free(buffer); 1010 g_free(buffer);
999 return; 1011 return;
1000 } 1012 }
1001 1013
1002 if ((purple_xfer_get_size(xfer) > 0) &&
1003 ((purple_xfer_get_bytes_sent(xfer)+r) >= purple_xfer_get_size(xfer)))
1004 purple_xfer_set_completed(xfer, TRUE);
1005 } else if(r < 0) { 1014 } else if(r < 0) {
1006 purple_xfer_cancel_remote(xfer); 1015 purple_xfer_cancel_remote(xfer);
1007 g_free(buffer); 1016 g_free(buffer);
1008 return; 1017 return;
1009 } 1018 }
1010 } else if (xfer->type == PURPLE_XFER_SEND) { 1019 } else if (xfer->type == PURPLE_XFER_SEND) {
1011 size_t result; 1020 size_t result;
1012 size_t s = MIN(purple_xfer_get_bytes_remaining(xfer), xfer->current_buffer_size); 1021 size_t s = MIN(purple_xfer_get_bytes_remaining(xfer), xfer->current_buffer_size);
1022 PurpleXferPrivData *priv = g_hash_table_lookup(xfers_data, xfer);
1013 1023
1014 /* this is so the prpl can keep the connection open 1024 /* this is so the prpl can keep the connection open
1015 if it needs to for some odd reason. */ 1025 if it needs to for some odd reason. */
1016 if (s == 0) { 1026 if (s == 0) {
1017 if (xfer->watcher) { 1027 if (xfer->watcher) {
1018 purple_input_remove(xfer->watcher); 1028 purple_input_remove(xfer->watcher);
1019 xfer->watcher = 0; 1029 xfer->watcher = 0;
1020 } 1030 }
1021 return; 1031 return;
1022 } 1032 }
1033
1034 if (priv->buffer) {
1035 s = s - priv->buffer->len;
1036 }
1023 1037
1024 if (ui_ops && ui_ops->ui_read) { 1038 if (ui_ops && ui_ops->ui_read) {
1025 gssize tmp = ui_ops->ui_read(xfer, &buffer, s); 1039 gssize tmp = ui_ops->ui_read(xfer, &buffer, s);
1026 if (tmp == 0) { 1040 if (tmp == 0) {
1027 /* 1041 /*
1031 */ 1045 */
1032 if (xfer->watcher != 0) { 1046 if (xfer->watcher != 0) {
1033 purple_input_remove(xfer->watcher); 1047 purple_input_remove(xfer->watcher);
1034 xfer->watcher = 0; 1048 xfer->watcher = 0;
1035 } 1049 }
1036 1050 /*
1037 return; 1051 * if we requested 0 bytes it's only normal that en up here
1052 * we shouldn't return as we still have something to
1053 * write in priv->buffer
1054 */
1055 if (s != 0)
1056 return;
1038 } else if (tmp < 0) { 1057 } else if (tmp < 0) {
1039 purple_debug_error("filetransfer", "Unable to read whole buffer.\n"); 1058 purple_debug_error("filetransfer", "Unable to read whole buffer.\n");
1040 purple_xfer_cancel_local(xfer); 1059 purple_xfer_cancel_local(xfer);
1041 return; 1060 return;
1042 } 1061 }
1050 purple_xfer_cancel_local(xfer); 1069 purple_xfer_cancel_local(xfer);
1051 g_free(buffer); 1070 g_free(buffer);
1052 return; 1071 return;
1053 } 1072 }
1054 } 1073 }
1055 1074
1056 /* Write as much as we're allowed to. */ 1075 if (priv->buffer) {
1076 priv->buffer = g_byte_array_append(priv->buffer, buffer, result);
1077 g_free(buffer);
1078 buffer = priv->buffer->data;
1079 result = priv->buffer->len;
1080 }
1081
1057 r = purple_xfer_write(xfer, buffer, result); 1082 r = purple_xfer_write(xfer, buffer, result);
1058 1083
1059 if (r == -1) { 1084 if (r == -1) {
1060 purple_xfer_cancel_remote(xfer); 1085 purple_xfer_cancel_remote(xfer);
1061 g_free(buffer); 1086 g_free(buffer);
1062 return; 1087 return;
1063 } else if (r < result) { 1088 } else if (r == result) {
1064 if (ui_ops == NULL || (ui_ops->ui_read == NULL && ui_ops->ui_write == NULL)) {
1065 /* We have to seek back in the file now. */
1066 fseek(xfer->dest_fp, r - s, SEEK_CUR);
1067 }
1068 else {
1069 ui_ops->data_not_sent(xfer, buffer + r, result - r);
1070 }
1071 } else {
1072 /* 1089 /*
1073 * We managed to write the entire buffer. This means our 1090 * We managed to write the entire buffer. This means our
1074 * network is fast and our buffer is too small, so make it 1091 * network is fast and our buffer is too small, so make it
1075 * bigger. 1092 * bigger.
1076 */ 1093 */
1077 purple_xfer_increase_buffer_size(xfer); 1094 purple_xfer_increase_buffer_size(xfer);
1095 } else {
1096 if (ui_ops && ui_ops->data_not_sent)
1097 ui_ops->data_not_sent(xfer, buffer + r, result -r);
1098 }
1099
1100 if (priv->buffer) {
1101 /*
1102 * Remove what we wrote
1103 * If we wrote the whole buffer the byte array will be empty
1104 * Otherwise we'll kee what wasn't sent for next time.
1105 */
1106 buffer = NULL;
1107 priv->buffer = g_byte_array_remove_range(priv->buffer, 0, r);
1078 } 1108 }
1079 } 1109 }
1080 1110
1081 if (r > 0) { 1111 if (r > 0) {
1082 if (purple_xfer_get_size(xfer) > 0) 1112 if (purple_xfer_get_size(xfer) > 0)
1092 if (ui_ops != NULL && ui_ops->update_progress != NULL) 1122 if (ui_ops != NULL && ui_ops->update_progress != NULL)
1093 ui_ops->update_progress(xfer, 1123 ui_ops->update_progress(xfer,
1094 purple_xfer_get_progress(xfer)); 1124 purple_xfer_get_progress(xfer));
1095 } 1125 }
1096 1126
1097 if (purple_xfer_is_completed(xfer)) 1127 if ((purple_xfer_get_size(xfer) > 0) &&
1128 ((purple_xfer_get_bytes_sent(xfer)) >= purple_xfer_get_size(xfer))) {
1129 purple_xfer_set_completed(xfer, TRUE);
1098 purple_xfer_end(xfer); 1130 purple_xfer_end(xfer);
1131 }
1099 } 1132 }
1100 1133
1101 static void 1134 static void
1102 transfer_cb(gpointer data, gint source, PurpleInputCondition condition) 1135 transfer_cb(gpointer data, gint source, PurpleInputCondition condition)
1103 { 1136 {