Mercurial > pidgin
comparison libpurple/protocols/jabber/si.c @ 27879:b2dd32ce7353
jabber: Migrate IBB to the new code added in the previous commit.
author | Paul Aurich <paul@darkrain42.org> |
---|---|
date | Wed, 12 Aug 2009 04:32:16 +0000 |
parents | 6adbdd4b2963 |
children | c585572e80dd 52cb819c6668 |
comparison
equal
deleted
inserted
replaced
27878:b7b25f580637 | 27879:b2dd32ce7353 |
---|---|
65 gsize rxmaxlen; | 65 gsize rxmaxlen; |
66 int local_streamhost_fd; | 66 int local_streamhost_fd; |
67 | 67 |
68 JabberIBBSession *ibb_session; | 68 JabberIBBSession *ibb_session; |
69 guint ibb_timeout_handle; | 69 guint ibb_timeout_handle; |
70 FILE *fp; | 70 PurpleCircBuffer *ibb_buffer; |
71 } JabberSIXfer; | 71 } JabberSIXfer; |
72 | 72 |
73 /* some forward declarations */ | 73 /* some forward declarations */ |
74 static void jabber_si_xfer_ibb_send_init(JabberStream *js, PurpleXfer *xfer); | 74 static void jabber_si_xfer_ibb_send_init(JabberStream *js, PurpleXfer *xfer); |
75 | 75 |
1010 JabberSIXfer *jsx = (JabberSIXfer *) xfer->data; | 1010 JabberSIXfer *jsx = (JabberSIXfer *) xfer->data; |
1011 | 1011 |
1012 if (size <= purple_xfer_get_bytes_remaining(xfer)) { | 1012 if (size <= purple_xfer_get_bytes_remaining(xfer)) { |
1013 purple_debug_info("jabber", "about to write %" G_GSIZE_FORMAT " bytes from IBB stream\n", | 1013 purple_debug_info("jabber", "about to write %" G_GSIZE_FORMAT " bytes from IBB stream\n", |
1014 size); | 1014 size); |
1015 if(!fwrite(data, size, 1, jsx->fp)) { | 1015 purple_circ_buffer_append(jsx->ibb_buffer, data, size); |
1016 purple_debug_error("jabber", "error writing to file\n"); | 1016 purple_xfer_prpl_ready(xfer); |
1017 purple_xfer_cancel_remote(xfer); | |
1018 return; | |
1019 } | |
1020 purple_xfer_set_bytes_sent(xfer, purple_xfer_get_bytes_sent(xfer) + size); | |
1021 purple_xfer_update_progress(xfer); | |
1022 | |
1023 if (purple_xfer_get_bytes_remaining(xfer) == 0) { | |
1024 purple_xfer_set_completed(xfer, TRUE); | |
1025 purple_xfer_end(xfer); | |
1026 } | |
1027 } else { | 1017 } else { |
1028 /* trying to write past size of file transfers negotiated size, | 1018 /* trying to write past size of file transfers negotiated size, |
1029 reject transfer to protect against malicious behaviour */ | 1019 reject transfer to protect against malicious behaviour */ |
1030 purple_debug_error("jabber", | 1020 purple_debug_error("jabber", |
1031 "IBB file transfer send more data than expected\n"); | 1021 "IBB file transfer send more data than expected\n"); |
1032 purple_xfer_cancel_remote(xfer); | 1022 purple_xfer_cancel_remote(xfer); |
1033 } | 1023 } |
1034 | 1024 |
1035 } | 1025 } |
1036 | 1026 |
1027 static gssize | |
1028 jabber_si_xfer_ibb_read(guchar **out_buffer, PurpleXfer *xfer) | |
1029 { | |
1030 JabberSIXfer *jsx = xfer->data; | |
1031 guchar *buffer; | |
1032 gsize size; | |
1033 gsize tmp; | |
1034 | |
1035 size = jsx->ibb_buffer->bufused; | |
1036 *out_buffer = buffer = g_malloc(size); | |
1037 while ((tmp = purple_circ_buffer_get_max_read(jsx->ibb_buffer))) { | |
1038 memcpy(buffer, jsx->ibb_buffer->outptr, tmp); | |
1039 buffer += tmp; | |
1040 purple_circ_buffer_mark_read(jsx->ibb_buffer, tmp); | |
1041 } | |
1042 | |
1043 return size; | |
1044 } | |
1045 | |
1037 static gboolean | 1046 static gboolean |
1038 jabber_si_xfer_ibb_open_cb(JabberStream *js, const char *who, const char *id, | 1047 jabber_si_xfer_ibb_open_cb(JabberStream *js, const char *who, const char *id, |
1039 xmlnode *open) | 1048 xmlnode *open) |
1040 { | 1049 { |
1041 const gchar *sid = xmlnode_get_attrib(open, "sid"); | 1050 const gchar *sid = xmlnode_get_attrib(open, "sid"); |
1042 PurpleXfer *xfer = jabber_si_xfer_find(js, sid, who); | 1051 PurpleXfer *xfer = jabber_si_xfer_find(js, sid, who); |
1043 if (xfer) { | 1052 if (xfer) { |
1044 JabberSIXfer *jsx = (JabberSIXfer *) xfer->data; | 1053 JabberSIXfer *jsx = (JabberSIXfer *) xfer->data; |
1045 JabberIBBSession *sess = | 1054 JabberIBBSession *sess = |
1046 jabber_ibb_session_create_from_xmlnode(js, who, id, open, xfer); | 1055 jabber_ibb_session_create_from_xmlnode(js, who, id, open, xfer); |
1047 const char *filename; | |
1048 | 1056 |
1049 jabber_si_bytestreams_ibb_timeout_remove(jsx); | 1057 jabber_si_bytestreams_ibb_timeout_remove(jsx); |
1050 | 1058 |
1051 if (sess) { | 1059 if (sess) { |
1052 /* open the file to write to */ | |
1053 filename = purple_xfer_get_local_filename(xfer); | |
1054 jsx->fp = g_fopen(filename, "wb"); | |
1055 if (jsx->fp == NULL) { | |
1056 purple_debug_error("jabber", "failed to open file %s for writing: %s\n", | |
1057 filename, g_strerror(errno)); | |
1058 purple_xfer_cancel_remote(xfer); | |
1059 return FALSE; | |
1060 } | |
1061 | |
1062 /* setup callbacks here...*/ | 1060 /* setup callbacks here...*/ |
1063 jabber_ibb_session_set_data_received_callback(sess, | 1061 jabber_ibb_session_set_data_received_callback(sess, |
1064 jabber_si_xfer_ibb_recv_data_cb); | 1062 jabber_si_xfer_ibb_recv_data_cb); |
1065 jabber_ibb_session_set_closed_callback(sess, | 1063 jabber_ibb_session_set_closed_callback(sess, |
1066 jabber_si_xfer_ibb_closed_cb); | 1064 jabber_si_xfer_ibb_closed_cb); |
1067 jabber_ibb_session_set_error_callback(sess, | 1065 jabber_ibb_session_set_error_callback(sess, |
1068 jabber_si_xfer_ibb_error_cb); | 1066 jabber_si_xfer_ibb_error_cb); |
1069 | 1067 |
1070 jsx->ibb_session = sess; | 1068 jsx->ibb_session = sess; |
1069 jsx->ibb_buffer = | |
1070 purple_circ_buffer_new(jabber_ibb_session_get_block_size(sess)); | |
1071 | |
1072 /* set up read function */ | |
1073 purple_xfer_set_read_fnc(xfer, jabber_si_xfer_ibb_read); | |
1071 | 1074 |
1072 /* start the transfer */ | 1075 /* start the transfer */ |
1073 purple_xfer_start(xfer, -1, NULL, 0); | 1076 purple_xfer_start(xfer, -1, NULL, 0); |
1074 return TRUE; | 1077 return TRUE; |
1075 } else { | 1078 } else { |
1084 "IBB open did not match any SI file transfer\n"); | 1087 "IBB open did not match any SI file transfer\n"); |
1085 return FALSE; | 1088 return FALSE; |
1086 } | 1089 } |
1087 } | 1090 } |
1088 | 1091 |
1089 static void | 1092 static gssize |
1090 jabber_si_xfer_ibb_send_data(JabberIBBSession *sess) | 1093 jabber_si_xfer_ibb_write(const guchar *buffer, size_t len, PurpleXfer *xfer) |
1091 { | 1094 { |
1092 PurpleXfer *xfer = (PurpleXfer *) jabber_ibb_session_get_user_data(sess); | |
1093 JabberSIXfer *jsx = (JabberSIXfer *) xfer->data; | 1095 JabberSIXfer *jsx = (JabberSIXfer *) xfer->data; |
1094 gsize remaining = purple_xfer_get_bytes_remaining(xfer); | 1096 JabberIBBSession *sess = jsx->ibb_session; |
1095 gsize packet_size = remaining < jabber_ibb_session_get_block_size(sess) ? | 1097 gsize packet_size = len < jabber_ibb_session_get_block_size(sess) ? |
1096 remaining : jabber_ibb_session_get_block_size(sess); | 1098 len : jabber_ibb_session_get_block_size(sess); |
1097 gpointer data = g_malloc(packet_size); | 1099 |
1098 int res; | 1100 jabber_ibb_session_send_data(sess, buffer, packet_size); |
1099 | 1101 |
1100 purple_debug_info("jabber", "IBB: about to read %" G_GSIZE_FORMAT " bytes from file %p\n", | 1102 return packet_size; |
1101 packet_size, jsx->fp); | |
1102 res = fread(data, packet_size, 1, jsx->fp); | |
1103 | |
1104 if (res == 1) { | |
1105 jabber_ibb_session_send_data(sess, data, packet_size); | |
1106 purple_xfer_set_bytes_sent(xfer, | |
1107 purple_xfer_get_bytes_sent(xfer) + packet_size); | |
1108 purple_xfer_update_progress(xfer); | |
1109 } else { | |
1110 purple_debug_error("jabber", | |
1111 "jabber_si_xfer_ibb_send_data: error reading from file\n"); | |
1112 purple_xfer_cancel_local(xfer); | |
1113 } | |
1114 g_free(data); | |
1115 } | 1103 } |
1116 | 1104 |
1117 static void | 1105 static void |
1118 jabber_si_xfer_ibb_sent_cb(JabberIBBSession *sess) | 1106 jabber_si_xfer_ibb_sent_cb(JabberIBBSession *sess) |
1119 { | 1107 { |
1125 jabber_ibb_session_close(sess); | 1113 jabber_ibb_session_close(sess); |
1126 purple_xfer_set_completed(xfer, TRUE); | 1114 purple_xfer_set_completed(xfer, TRUE); |
1127 purple_xfer_end(xfer); | 1115 purple_xfer_end(xfer); |
1128 } else { | 1116 } else { |
1129 /* send more... */ | 1117 /* send more... */ |
1130 jabber_si_xfer_ibb_send_data(sess); | 1118 purple_xfer_prpl_ready(xfer); |
1131 } | 1119 } |
1132 } | 1120 } |
1133 | 1121 |
1134 static void | 1122 static void |
1135 jabber_si_xfer_ibb_opened_cb(JabberIBBSession *sess) | 1123 jabber_si_xfer_ibb_opened_cb(JabberIBBSession *sess) |
1136 { | 1124 { |
1137 PurpleXfer *xfer = (PurpleXfer *) jabber_ibb_session_get_user_data(sess); | 1125 PurpleXfer *xfer = (PurpleXfer *) jabber_ibb_session_get_user_data(sess); |
1138 JabberSIXfer *jsx = (JabberSIXfer *) xfer->data; | |
1139 JabberStream *js = jabber_ibb_session_get_js(sess); | 1126 JabberStream *js = jabber_ibb_session_get_js(sess); |
1140 PurpleConnection *gc = js->gc; | 1127 PurpleConnection *gc = js->gc; |
1141 PurpleAccount *account = purple_connection_get_account(gc); | 1128 PurpleAccount *account = purple_connection_get_account(gc); |
1142 | 1129 |
1143 if (jabber_ibb_session_get_state(sess) == JABBER_IBB_SESSION_OPENED) { | 1130 if (jabber_ibb_session_get_state(sess) == JABBER_IBB_SESSION_OPENED) { |
1144 const char *filename = purple_xfer_get_local_filename(xfer); | |
1145 jsx->fp = g_fopen(filename, "rb"); | |
1146 if (jsx->fp == NULL) { | |
1147 purple_debug_error("jabber", "Failed to open file %s for reading: %s\n", | |
1148 filename, g_strerror(errno)); | |
1149 purple_xfer_error(purple_xfer_get_type(xfer), account, | |
1150 jabber_ibb_session_get_who(sess), | |
1151 _("Failed to open the file")); | |
1152 purple_xfer_cancel_local(xfer); | |
1153 return; | |
1154 } | |
1155 | |
1156 purple_xfer_start(xfer, -1, NULL, 0); | 1131 purple_xfer_start(xfer, -1, NULL, 0); |
1157 purple_xfer_set_bytes_sent(xfer, 0); | 1132 purple_xfer_prpl_ready(xfer); |
1158 purple_xfer_update_progress(xfer); | |
1159 jabber_si_xfer_ibb_send_data(sess); | |
1160 } else { | 1133 } else { |
1161 /* error */ | 1134 /* error */ |
1162 purple_xfer_error(purple_xfer_get_type(xfer), account, | 1135 purple_xfer_error(purple_xfer_get_type(xfer), account, |
1163 jabber_ibb_session_get_who(sess), | 1136 jabber_ibb_session_get_who(sess), |
1164 _("Failed to open in-band bytestream")); | 1137 _("Failed to open in-band bytestream")); |
1168 | 1141 |
1169 static void | 1142 static void |
1170 jabber_si_xfer_ibb_send_init(JabberStream *js, PurpleXfer *xfer) | 1143 jabber_si_xfer_ibb_send_init(JabberStream *js, PurpleXfer *xfer) |
1171 { | 1144 { |
1172 JabberSIXfer *jsx = (JabberSIXfer *) xfer->data; | 1145 JabberSIXfer *jsx = (JabberSIXfer *) xfer->data; |
1173 | |
1174 purple_xfer_ref(xfer); | |
1175 | 1146 |
1176 jsx->ibb_session = jabber_ibb_session_create(js, jsx->stream_id, | 1147 jsx->ibb_session = jabber_ibb_session_create(js, jsx->stream_id, |
1177 purple_xfer_get_remote_user(xfer), xfer); | 1148 purple_xfer_get_remote_user(xfer), xfer); |
1178 | 1149 |
1179 if (jsx->ibb_session) { | 1150 if (jsx->ibb_session) { |
1184 jabber_si_xfer_ibb_sent_cb); | 1155 jabber_si_xfer_ibb_sent_cb); |
1185 jabber_ibb_session_set_closed_callback(jsx->ibb_session, | 1156 jabber_ibb_session_set_closed_callback(jsx->ibb_session, |
1186 jabber_si_xfer_ibb_closed_cb); | 1157 jabber_si_xfer_ibb_closed_cb); |
1187 jabber_ibb_session_set_error_callback(jsx->ibb_session, | 1158 jabber_ibb_session_set_error_callback(jsx->ibb_session, |
1188 jabber_si_xfer_ibb_error_cb); | 1159 jabber_si_xfer_ibb_error_cb); |
1160 | |
1161 purple_xfer_set_write_fnc(xfer, jabber_si_xfer_ibb_write); | |
1162 | |
1163 jsx->ibb_buffer = | |
1164 purple_circ_buffer_new(jabber_ibb_session_get_block_size(jsx->ibb_session)); | |
1189 | 1165 |
1190 /* open the IBB session */ | 1166 /* open the IBB session */ |
1191 jabber_ibb_session_open(jsx->ibb_session); | 1167 jabber_ibb_session_open(jsx->ibb_session); |
1192 | 1168 |
1193 } else { | 1169 } else { |
1340 purple_debug_info("jabber", | 1316 purple_debug_info("jabber", |
1341 "jabber_si_xfer_free: destroying IBB session\n"); | 1317 "jabber_si_xfer_free: destroying IBB session\n"); |
1342 jabber_ibb_session_destroy(jsx->ibb_session); | 1318 jabber_ibb_session_destroy(jsx->ibb_session); |
1343 } | 1319 } |
1344 | 1320 |
1345 if (jsx->fp) { | 1321 if (jsx->ibb_buffer) { |
1346 purple_debug_info("jabber", | 1322 purple_circ_buffer_destroy(jsx->ibb_buffer); |
1347 "jabber_si_xfer_free: closing file for IBB transfer\n"); | |
1348 fclose(jsx->fp); | |
1349 } | 1323 } |
1350 | 1324 |
1351 purple_debug_info("jabber", "jabber_si_xfer_free(): freeing jsx %p\n", jsx); | 1325 purple_debug_info("jabber", "jabber_si_xfer_free(): freeing jsx %p\n", jsx); |
1352 | 1326 |
1353 g_free(jsx->stream_id); | 1327 g_free(jsx->stream_id); |
1354 g_free(jsx->iq_id); | 1328 g_free(jsx->iq_id); |
1355 /* XXX: free other stuff */ | 1329 /* XXX: free other stuff */ |
1356 g_free(jsx->rxqueue); | 1330 g_free(jsx->rxqueue); |
1357 g_free(jsx); | 1331 g_free(jsx); |
1358 xfer->data = NULL; | 1332 xfer->data = NULL; |
1359 | |
1360 } | 1333 } |
1361 } | 1334 } |
1362 | 1335 |
1363 /* | 1336 /* |
1364 * These four functions should only be called from the PurpleXfer functions | 1337 * These four functions should only be called from the PurpleXfer functions |
1630 xfer->data = jsx = g_new0(JabberSIXfer, 1); | 1603 xfer->data = jsx = g_new0(JabberSIXfer, 1); |
1631 jsx->js = js; | 1604 jsx->js = js; |
1632 jsx->local_streamhost_fd = -1; | 1605 jsx->local_streamhost_fd = -1; |
1633 | 1606 |
1634 jsx->ibb_session = NULL; | 1607 jsx->ibb_session = NULL; |
1635 jsx->fp = NULL; | |
1636 | 1608 |
1637 purple_xfer_set_init_fnc(xfer, jabber_si_xfer_init); | 1609 purple_xfer_set_init_fnc(xfer, jabber_si_xfer_init); |
1638 purple_xfer_set_cancel_send_fnc(xfer, jabber_si_xfer_cancel_send); | 1610 purple_xfer_set_cancel_send_fnc(xfer, jabber_si_xfer_cancel_send); |
1639 purple_xfer_set_end_fnc(xfer, jabber_si_xfer_end); | 1611 purple_xfer_set_end_fnc(xfer, jabber_si_xfer_end); |
1640 | 1612 |