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