Mercurial > pidgin.yaz
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 { |