Mercurial > pidgin.yaz
comparison libpurple/protocols/yahoo/yahoo_filexfer.c @ 25622:2fb8c39d0494
Send file by p2p when we are server
author | Sulabh Mahajan <sulabh@soc.pidgin.im> |
---|---|
date | Wed, 09 Jul 2008 15:05:09 +0000 |
parents | ccbded331513 |
children | d96190de653a |
comparison
equal
deleted
inserted
replaced
25621:860d8ed4f7a6 | 25622:2fb8c39d0494 |
---|---|
24 #include "dnsquery.h" | 24 #include "dnsquery.h" |
25 | 25 |
26 #include "prpl.h" | 26 #include "prpl.h" |
27 #include "util.h" | 27 #include "util.h" |
28 #include "debug.h" | 28 #include "debug.h" |
29 #include "network.h" | |
29 #include "notify.h" | 30 #include "notify.h" |
30 #include "proxy.h" | 31 #include "proxy.h" |
31 #include "ft.h" | 32 #include "ft.h" |
32 #include "yahoo.h" | 33 #include "yahoo.h" |
33 #include "yahoo_packet.h" | 34 #include "yahoo_packet.h" |
56 enum { | 57 enum { |
57 STARTED = 0, | 58 STARTED = 0, |
58 HEAD_REQUESTED, | 59 HEAD_REQUESTED, |
59 HEAD_REPLY_RECEIVED, | 60 HEAD_REPLY_RECEIVED, |
60 TRANSFER_PHASE, | 61 TRANSFER_PHASE, |
61 ACCEPTED | 62 ACCEPTED, |
63 P2P_HEAD_REQUESTED, | |
64 P2P_HEAD_REPLIED, | |
65 P2P_GET_REQUESTED | |
62 } status_15; | 66 } status_15; |
63 | 67 |
64 /* contains all filenames, in case of multiple transfers, with the first | 68 /* contains all filenames, in case of multiple transfers, with the first |
65 * one in the list being the current file's name (ymsg15) */ | 69 * one in the list being the current file's name (ymsg15) */ |
66 GSList *filename_list; | 70 GSList *filename_list; |
67 GSList *size_list; /*corresponds to filename_list, with size as **STRING** */ | 71 GSList *size_list; /*corresponds to filename_list, with size as **STRING** */ |
68 gboolean firstoflist; | 72 gboolean firstoflist; |
73 gchar *xfer_url; /* url of the file, used when we are p2p server */ | |
74 int yahoo_local_p2p_ft_server_fd; | |
75 int yahoo_local_p2p_ft_server_port; | |
76 int yahoo_p2p_ft_server_watcher; | |
77 int input_event; | |
69 }; | 78 }; |
70 | 79 |
71 static void yahoo_xfer_data_free(struct yahoo_xfer_data *xd) | 80 static void yahoo_xfer_data_free(struct yahoo_xfer_data *xd) |
72 { | 81 { |
73 PurpleConnection *gc; | 82 PurpleConnection *gc; |
1028 | 1037 |
1029 g_free(filename); | 1038 g_free(filename); |
1030 yahoo_packet_send_and_free(pkt, yd); | 1039 yahoo_packet_send_and_free(pkt, yd); |
1031 } | 1040 } |
1032 | 1041 |
1033 | |
1034 void yahoo_send_file(PurpleConnection *gc, const char *who, const char *file) | 1042 void yahoo_send_file(PurpleConnection *gc, const char *who, const char *file) |
1035 { | 1043 { |
1036 struct yahoo_xfer_data *xfer_data; | 1044 struct yahoo_xfer_data *xfer_data; |
1037 struct yahoo_data *yd = gc->proto_data; | 1045 struct yahoo_data *yd = gc->proto_data; |
1038 int ver = 0; | 1046 int ver = 0; |
1060 purple_xfer_request_accepted(xfer, file); | 1068 purple_xfer_request_accepted(xfer, file); |
1061 else | 1069 else |
1062 purple_xfer_request(xfer); | 1070 purple_xfer_request(xfer); |
1063 } | 1071 } |
1064 | 1072 |
1073 static void yahoo_p2p_ft_server_listen_cb(int listenfd, gpointer data); /* using this in yahoo_xfer_send_cb_15 */ | |
1065 static void yahoo_xfer_connected_15(gpointer data, gint source, const gchar *error_message);/*using this in recv_cb*/ | 1074 static void yahoo_xfer_connected_15(gpointer data, gint source, const gchar *error_message);/*using this in recv_cb*/ |
1075 | |
1066 static void yahoo_xfer_recv_cb_15(gpointer data, gint source, PurpleInputCondition condition) | 1076 static void yahoo_xfer_recv_cb_15(gpointer data, gint source, PurpleInputCondition condition) |
1067 { | 1077 { |
1068 PurpleXfer *xfer; | 1078 PurpleXfer *xfer; |
1069 struct yahoo_xfer_data *xd; | 1079 struct yahoo_xfer_data *xd; |
1070 int did; | 1080 int did; |
1149 xd->txbuf = NULL; | 1159 xd->txbuf = NULL; |
1150 xd->txbuflen = 0; | 1160 xd->txbuflen = 0; |
1151 xd->txbuf_written = 0; | 1161 xd->txbuf_written = 0; |
1152 | 1162 |
1153 if(purple_xfer_get_type(xfer) == PURPLE_XFER_RECEIVE && xd->status_15 == STARTED) | 1163 if(purple_xfer_get_type(xfer) == PURPLE_XFER_RECEIVE && xd->status_15 == STARTED) |
1154 { | 1164 { |
1155 xd->status_15 = HEAD_REQUESTED; | 1165 xd->status_15 = HEAD_REQUESTED; |
1156 xd->tx_handler = purple_input_add(source, PURPLE_INPUT_READ, yahoo_xfer_recv_cb_15, xfer); | 1166 xd->tx_handler = purple_input_add(source, PURPLE_INPUT_READ, yahoo_xfer_recv_cb_15, xfer); |
1157 yahoo_xfer_recv_cb_15(xfer, source, PURPLE_INPUT_READ); | 1167 yahoo_xfer_recv_cb_15(xfer, source, PURPLE_INPUT_READ); |
1158 } | 1168 } |
1159 else if(purple_xfer_get_type(xfer) == PURPLE_XFER_RECEIVE && xd->status_15 == HEAD_REPLY_RECEIVED) | 1169 else if(purple_xfer_get_type(xfer) == PURPLE_XFER_RECEIVE && xd->status_15 == HEAD_REPLY_RECEIVED) |
1160 { | 1170 { |
1161 xd->status_15 = TRANSFER_PHASE; | 1171 xd->status_15 = TRANSFER_PHASE; |
1162 xfer->fd = source; | 1172 xfer->fd = source; |
1163 purple_xfer_start(xfer, source, NULL, 0); | 1173 purple_xfer_start(xfer, source, NULL, 0); |
1164 } | 1174 } |
1165 else if(purple_xfer_get_type(xfer) == PURPLE_XFER_SEND && xd->status_15 == ACCEPTED) | 1175 else if(purple_xfer_get_type(xfer) == PURPLE_XFER_SEND && (xd->status_15 == ACCEPTED || xd->status_15 == P2P_GET_REQUESTED) ) |
1166 { | 1176 { |
1167 xd->status_15 = TRANSFER_PHASE; | 1177 xd->status_15 = TRANSFER_PHASE; |
1168 xfer->fd = source; | 1178 xfer->fd = source; |
1179 /* Remove Read event */ | |
1180 purple_input_remove(xd->input_event); | |
1181 xd->input_event = 0; | |
1169 purple_xfer_start(xfer, source, NULL, 0); | 1182 purple_xfer_start(xfer, source, NULL, 0); |
1170 } | 1183 } |
1184 else if(purple_xfer_get_type(xfer) == PURPLE_XFER_SEND && xd->status_15 == P2P_HEAD_REQUESTED) | |
1185 { | |
1186 xd->status_15 = P2P_HEAD_REPLIED; | |
1187 /* Remove Read event and close descriptor */ | |
1188 purple_input_remove(xd->input_event); | |
1189 xd->input_event = 0; | |
1190 close(source); | |
1191 xfer->fd = -1; | |
1192 /* start local server, listen for connections */ | |
1193 purple_network_listen(xd->yahoo_local_p2p_ft_server_port, SOCK_STREAM, yahoo_p2p_ft_server_listen_cb, xfer); | |
1194 } | |
1171 else | 1195 else |
1172 { | 1196 { |
1173 purple_debug_error("yahoo", "Unrecognized yahoo file transfer mode and stage (ymsg15):%d,%d\n", purple_xfer_get_type(xfer), xd->status_15); | 1197 purple_debug_error("yahoo", "Unrecognized yahoo file transfer mode and stage (ymsg15):%d,%d\n", purple_xfer_get_type(xfer), xd->status_15); |
1174 return; | 1198 return; |
1175 } | 1199 } |
1176 | 1200 } |
1177 } | |
1178 | |
1179 | 1201 |
1180 static void yahoo_xfer_connected_15(gpointer data, gint source, const gchar *error_message) | 1202 static void yahoo_xfer_connected_15(gpointer data, gint source, const gchar *error_message) |
1181 { | 1203 { |
1182 PurpleXfer *xfer; | 1204 PurpleXfer *xfer; |
1183 struct yahoo_xfer_data *xd; | 1205 struct yahoo_xfer_data *xd; |
1276 yahoo_xfer_send_cb_15, xfer); | 1298 yahoo_xfer_send_cb_15, xfer); |
1277 yahoo_xfer_send_cb_15(xfer, source, PURPLE_INPUT_WRITE); | 1299 yahoo_xfer_send_cb_15(xfer, source, PURPLE_INPUT_WRITE); |
1278 } | 1300 } |
1279 } | 1301 } |
1280 | 1302 |
1281 /*send (p2p) file transfer information when we are connected as client*/ | 1303 static void yahoo_p2p_ft_HEAD_GET_cb(gpointer data, gint source, PurpleInputCondition cond) |
1282 static void yahoo_p2p_client_send_ft_info(PurpleConnection *gc, PurpleXfer *xfer) | 1304 { |
1283 { | 1305 PurpleXfer *xfer; |
1306 struct yahoo_xfer_data *xd; | |
1307 guchar buf[1024]; | |
1308 int len; | |
1309 char *url_head; | |
1310 char *url_get; | |
1311 time_t unix_time; | |
1312 char *time_str; | |
1313 | |
1314 xfer = data; | |
1315 if (!(xd = xfer->data)) { | |
1316 purple_xfer_cancel_remote(xfer); | |
1317 purple_input_remove(xd->input_event); | |
1318 return; | |
1319 } | |
1320 | |
1321 len = read(source, buf, sizeof(buf)); | |
1322 if ((len < 0) && ((errno == EAGAIN) || (errno == EWOULDBLOCK))) | |
1323 return ; /* No Worries*/ | |
1324 else if (len <= 0) { | |
1325 purple_debug_warning("yahoo","p2p-ft: Error in connection, or host disconnected\n"); | |
1326 purple_xfer_cancel_remote(xfer); | |
1327 purple_input_remove(xd->input_event); | |
1328 return; | |
1329 } | |
1330 | |
1331 url_head = g_strdup_printf("HEAD %s", xd->xfer_url); | |
1332 url_get = g_strdup_printf("GET %s", xd->xfer_url); | |
1333 | |
1334 if( strncmp(url_head, (char *)buf, strlen(url_head)) == 0 ) | |
1335 xd->status_15 = P2P_HEAD_REQUESTED; | |
1336 else if( strncmp(url_get, (char *)buf, strlen(url_get)) == 0 ) | |
1337 xd->status_15 = P2P_GET_REQUESTED; | |
1338 else { | |
1339 purple_debug_warning("yahoo","p2p-ft: Wrong HEAD/GET request from peer, disconnecting host\n"); | |
1340 purple_xfer_cancel_remote(xfer); | |
1341 purple_input_remove(xd->input_event); | |
1342 g_free(url_head); | |
1343 return; | |
1344 } | |
1345 | |
1346 unix_time = time(NULL); | |
1347 time_str = ctime(&unix_time); | |
1348 strcpy(time_str + strlen(time_str) - 1, "\0"); | |
1349 | |
1350 if (xd->txbuflen == 0) { | |
1351 xd->txbuf = g_strdup_printf("HTTP/1.0 200 OK\r\nDate: %s GMT\r\nServer: Y!/1.0\r\nMIME-version: 1.0\r\nLast-modified: %s GMT\r\nContent-length: %d\r\n\r\n", time_str, time_str, xfer->size); | |
1352 xd->txbuflen = strlen(xd->txbuf); | |
1353 xd->txbuf_written = 0; | |
1354 } | |
1355 | |
1356 if (!xd->tx_handler) { | |
1357 xd->tx_handler = purple_input_add(source, PURPLE_INPUT_WRITE, yahoo_xfer_send_cb_15, xfer); | |
1358 yahoo_xfer_send_cb_15(xfer, source, PURPLE_INPUT_WRITE); | |
1359 } | |
1360 | |
1361 g_free(url_head); | |
1362 g_free(url_get); | |
1363 } | |
1364 | |
1365 static void yahoo_p2p_ft_server_send_connected_cb(gpointer data, gint source, PurpleInputCondition cond) | |
1366 { | |
1367 int acceptfd; | |
1368 PurpleXfer *xfer; | |
1369 struct yahoo_xfer_data *xd; | |
1370 | |
1371 xfer = data; | |
1372 if (!(xd = xfer->data)) { | |
1373 purple_xfer_cancel_remote(xfer); | |
1374 return; | |
1375 } | |
1376 | |
1377 acceptfd = accept(source, NULL, 0); | |
1378 if(acceptfd == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)) | |
1379 return; | |
1380 else if(acceptfd == -1) { | |
1381 purple_debug_warning("yahoo","yahoo_p2p_server_send_connected_cb: accept: %s\n", g_strerror(errno)); | |
1382 purple_xfer_cancel_remote(xfer); | |
1383 /*remove watcher and close p2p ft server*/ | |
1384 purple_input_remove(xd->yahoo_p2p_ft_server_watcher); | |
1385 close(xd->yahoo_local_p2p_ft_server_fd); | |
1386 return; | |
1387 } | |
1388 | |
1389 /*remove watcher and close p2p ft server*/ | |
1390 purple_input_remove(xd->yahoo_p2p_ft_server_watcher); | |
1391 close(xd->yahoo_local_p2p_ft_server_fd); | |
1392 | |
1393 /*Add an Input Read event to the file descriptor*/ | |
1394 xfer->fd = acceptfd; | |
1395 xd->input_event = purple_input_add(acceptfd, PURPLE_INPUT_READ, yahoo_p2p_ft_HEAD_GET_cb, data); | |
1396 } | |
1397 | |
1398 static void yahoo_p2p_ft_server_listen_cb(int listenfd, gpointer data) | |
1399 { | |
1400 PurpleXfer *xfer; | |
1284 struct yahoo_xfer_data *xd; | 1401 struct yahoo_xfer_data *xd; |
1285 struct yahoo_packet *pkt; | 1402 struct yahoo_packet *pkt; |
1286 PurpleAccount *account; | 1403 PurpleAccount *account; |
1287 struct yahoo_data *yd; | 1404 struct yahoo_data *yd; |
1288 gchar *filename; | 1405 gchar *filename; |
1406 const char *local_ip; | |
1407 gchar *url_to_send = NULL; | |
1408 | |
1409 xfer = data; | |
1410 if ( !( (xd = xfer->data) || (listenfd != -1) ) ) { | |
1411 purple_debug_warning("yahoo","p2p: error starting server for p2p file transfer\n"); | |
1412 purple_xfer_cancel_remote(xfer); | |
1413 return; | |
1414 } | |
1415 | |
1416 if(xd->status_15 != P2P_HEAD_REPLIED) { | |
1417 yd = xd->gc->proto_data; | |
1418 account = purple_connection_get_account(xd->gc); | |
1419 | |
1420 pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANS_INFO_15, YAHOO_STATUS_AVAILABLE, yd->session_id); | |
1421 filename = g_path_get_basename(purple_xfer_get_local_filename(xfer)); | |
1422 | |
1423 local_ip = purple_network_get_my_ip(listenfd); | |
1424 xd->yahoo_local_p2p_ft_server_port = purple_network_get_port_from_fd(listenfd); | |
1425 xd->xfer_url = g_strdup_printf("/Messenger.%s.%d000%s?AppID=Messenger&UserID=%s&K=lc9lu2u89gz1llmplwksajkjx", xfer->who, (int)time(NULL), filename, xfer->who); | |
1426 url_to_send = g_strdup_printf("http://%s:%d%s", local_ip, xd->yahoo_local_p2p_ft_server_port, xd->xfer_url); | |
1427 xd->info_val_249 = 1; /* 249=1: we are p2p server */ | |
1428 | |
1429 yahoo_packet_hash(pkt, "ssssis", | |
1430 1, purple_normalize(account, purple_account_get_username(account)), | |
1431 5, xfer->who, | |
1432 265, xd->xfer_peer_idstring, | |
1433 27, filename, | |
1434 249, 1, | |
1435 250, url_to_send); | |
1436 yahoo_packet_send_and_free(pkt, yd); | |
1437 | |
1438 g_free(filename); | |
1439 g_free(url_to_send); | |
1440 } | |
1441 | |
1442 /* Add an Input Read event to the file descriptor */ | |
1443 xd->yahoo_local_p2p_ft_server_fd = listenfd; | |
1444 xd->yahoo_p2p_ft_server_watcher = purple_input_add(listenfd, PURPLE_INPUT_READ, yahoo_p2p_ft_server_send_connected_cb, data); | |
1445 } | |
1446 | |
1447 /* send (p2p) file transfer information */ | |
1448 static void yahoo_p2p_client_send_ft_info(PurpleConnection *gc, PurpleXfer *xfer) | |
1449 { | |
1450 struct yahoo_xfer_data *xd; | |
1451 struct yahoo_packet *pkt; | |
1452 PurpleAccount *account; | |
1453 struct yahoo_data *yd; | |
1454 gchar *filename; | |
1455 struct yahoo_p2p_data *p2p_data; | |
1289 | 1456 |
1290 if (!(xd = xfer->data)) | 1457 if (!(xd = xfer->data)) |
1291 return; | 1458 return; |
1292 | 1459 |
1293 account = purple_connection_get_account(gc); | 1460 account = purple_connection_get_account(gc); |
1294 yd = gc->proto_data; | 1461 yd = gc->proto_data; |
1295 | 1462 |
1296 pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANS_INFO_15, YAHOO_STATUS_AVAILABLE, yd->session_id); | 1463 pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANS_INFO_15, YAHOO_STATUS_AVAILABLE, yd->session_id); |
1297 filename = g_path_get_basename(purple_xfer_get_local_filename(xfer)); | 1464 filename = g_path_get_basename(purple_xfer_get_local_filename(xfer)); |
1465 | |
1466 p2p_data = g_hash_table_lookup(yd->peers, xfer->who); | |
1467 if( p2p_data->connection_type == 1 ) | |
1468 if(purple_network_listen_range(0, 0, SOCK_STREAM, yahoo_p2p_ft_server_listen_cb, xfer)) { | |
1469 g_free(filename); | |
1470 return; | |
1471 } | |
1298 | 1472 |
1299 yahoo_packet_hash(pkt, "ssssi", | 1473 yahoo_packet_hash(pkt, "ssssi", |
1300 1, purple_normalize(account, purple_account_get_username(account)), | 1474 1, purple_normalize(account, purple_account_get_username(account)), |
1301 5, xfer->who, | 1475 5, xfer->who, |
1302 265, xd->xfer_peer_idstring, | 1476 265, xd->xfer_peer_idstring, |
1303 27, filename, | 1477 27, filename, |
1304 249, 2); /*249= 2:we are connected as p2p client, and sending file*/ | 1478 249, 2); /* 249=2: we are p2p client */ |
1305 xd->info_val_249 = 2; | 1479 xd->info_val_249 = 2; |
1480 yahoo_packet_send_and_free(pkt, yd); | |
1306 | 1481 |
1307 g_free(filename); | 1482 g_free(filename); |
1308 yahoo_packet_send_and_free(pkt, yd); | |
1309 } | 1483 } |
1310 | 1484 |
1311 void yahoo_process_filetrans_15(PurpleConnection *gc, struct yahoo_packet *pkt) | 1485 void yahoo_process_filetrans_15(PurpleConnection *gc, struct yahoo_packet *pkt) |
1312 { | 1486 { |
1313 char *from = NULL; | 1487 char *from = NULL; |
1387 * purple connect does not give me a way of finding the ip address... | 1561 * purple connect does not give me a way of finding the ip address... |
1388 * so, purple dnsquery is used... but retries, trying with next ip | 1562 * so, purple dnsquery is used... but retries, trying with next ip |
1389 * address etc. is not implemented..TODO | 1563 * address etc. is not implemented..TODO |
1390 */ | 1564 */ |
1391 | 1565 |
1392 /*p2p connection exists, we being p2p client*/ | 1566 /* To send through p2p */ |
1393 if( g_hash_table_lookup(yd->peers, from) ) { | 1567 if( g_hash_table_lookup(yd->peers, from) ) { |
1394 /*send p2p file transfer information when we are connected as client*/ | 1568 /*send p2p file transfer information */ |
1395 yahoo_p2p_client_send_ft_info(gc, xfer); | 1569 yahoo_p2p_client_send_ft_info(gc, xfer); |
1396 return; | 1570 return; |
1397 } | 1571 } |
1398 | 1572 |
1399 if (yd->jp) | 1573 if (yd->jp) |