00001
00025 #include <network.h>
00026
00027 #include "send_file.h"
00028 #include "debug.h"
00029 #include "notify.h"
00030 #include "network.h"
00031
00032 #include "im.h"
00033 #include "packet_parse.h"
00034 #include "crypt.h"
00035 #include "header_info.h"
00036 #include "send_core.h"
00037 #include "utils.h"
00038 #include "file_trans.h"
00039 #include "qq.h"
00040
00041
00042 enum
00043 {
00044 QQ_FILE_TRANS_REQ = 0x0035,
00045 QQ_FILE_TRANS_ACC_UDP = 0x0037,
00046 QQ_FILE_TRANS_ACC_TCP = 0x0003,
00047 QQ_FILE_TRANS_DENY_UDP = 0x0039,
00048 QQ_FILE_TRANS_DENY_TCP = 0x0005,
00049 QQ_FILE_TRANS_NOTIFY = 0x003b,
00050 QQ_FILE_TRANS_NOTIFY_ACK = 0x003c,
00051 QQ_FILE_TRANS_CANCEL = 0x0049,
00052 QQ_FILE_TRANS_PASV = 0x003f
00053 };
00054
00055 int _qq_in_same_lan(ft_info *info)
00056 {
00057 if (info->remote_internet_ip == info->local_internet_ip) return 1;
00058 gaim_debug(GAIM_DEBUG_INFO, "QQ", "Not in the same LAN, remote internet ip[%x], local internet ip[%x]\n", info->remote_internet_ip
00059 , info->local_internet_ip);
00060 return 0;
00061 }
00062
00063 int _qq_xfer_init_udp_channel(ft_info *info)
00064 {
00065 struct sockaddr_in sin;
00066 memset(&sin, 0, sizeof(sin));
00067 sin.sin_family = AF_INET;
00068 if (!_qq_in_same_lan(info)) {
00069 sin.sin_port = htons(info->remote_major_port);
00070 sin.sin_addr.s_addr = htonl(info->remote_internet_ip);
00071 } else {
00072 sin.sin_port = htons(info->remote_minor_port);
00073 sin.sin_addr.s_addr = htonl(info->remote_real_ip);
00074 }
00075 return 0;
00076
00077 }
00078
00079
00080 ssize_t _qq_xfer_udp_recv(char *buf, size_t len, GaimXfer *xfer)
00081 {
00082 struct sockaddr_in sin;
00083 int sinlen;
00084 ft_info *info;
00085 int r;
00086
00087 info = (ft_info *) xfer->data;
00088 sinlen = sizeof(sin);
00089 r = recvfrom(info->recv_fd, buf, len, 0, (struct sockaddr *) &sin, &sinlen);
00090 gaim_debug(GAIM_DEBUG_INFO, "QQ", "==> recv %d bytes from File UDP Channel, remote ip[%s], remote port[%d]\n",
00091 r, inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
00092 return r;
00093 }
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104 ssize_t _qq_xfer_udp_send(const char *buf, size_t len, GaimXfer *xfer)
00105 {
00106 struct sockaddr_in sin;
00107 ft_info *info;
00108
00109 info = (ft_info *) xfer->data;
00110 memset(&sin, 0, sizeof(sin));
00111 sin.sin_family = AF_INET;
00112 if (!_qq_in_same_lan(info)) {
00113 sin.sin_port = htons(info->remote_major_port);
00114 sin.sin_addr.s_addr = htonl(info->remote_internet_ip);
00115 } else if (info->use_major) {
00116 sin.sin_port = htons(info->remote_major_port);
00117 sin.sin_addr.s_addr = htonl(info->remote_real_ip);
00118 } else {
00119 sin.sin_port = htons(info->remote_minor_port);
00120 sin.sin_addr.s_addr = htonl(info->remote_real_ip);
00121 }
00122 gaim_debug(GAIM_DEBUG_INFO, "QQ", "sending to channel: %d.%d.%d.%d:%d\n",
00123 sin.sin_addr.s_addr & 0xff,
00124 (sin.sin_addr.s_addr >> 8) & 0xff,
00125 (sin.sin_addr.s_addr >> 16) & 0xff,
00126 sin.sin_addr.s_addr >> 24,
00127 ntohs(sin.sin_port)
00128 );
00129 return sendto(info->sender_fd, buf, len, 0, (struct sockaddr *) &sin, sizeof(sin));
00130 }
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142 ssize_t _qq_xfer_write(const char *buf, size_t len, GaimXfer *xfer)
00143 {
00144 return _qq_xfer_udp_send(buf, len, xfer);
00145 }
00146
00147 void
00148 _qq_xfer_recv_packet(gpointer data, gint source, GaimInputCondition condition)
00149 {
00150 GaimXfer *xfer = (GaimXfer *) data;
00151 GaimAccount *account = gaim_xfer_get_account(xfer);
00152 GaimConnection *gc = gaim_account_get_connection(account);
00153 guint8 *buf;
00154 gint size;
00155
00156
00157
00158
00159
00160 ft_info *info;
00161 info = xfer->data;
00162 g_return_if_fail (source == info->recv_fd);
00163 buf = g_newa(guint8, 1500);
00164 size = _qq_xfer_udp_recv(buf, 1500, xfer);
00165 qq_process_recv_file(gc, buf, size);
00166 }
00167
00168
00169 void
00170 _qq_xfer_send_start (GaimXfer * xfer)
00171 {
00172 GaimAccount *account;
00173 GaimConnection *gc;
00174 ft_info *info;
00175
00176 account = gaim_xfer_get_account(xfer);
00177 gc = gaim_account_get_connection(account);
00178 info = (ft_info *) xfer->data;
00179 }
00180
00181 void
00182 _qq_xfer_send_ack (GaimXfer *xfer, const char *buffer, size_t len)
00183 {
00184
00185 GaimAccount *account;
00186 GaimConnection *gc;
00187
00188 account = gaim_xfer_get_account(xfer);
00189 gc = gaim_account_get_connection(account);
00190 qq_process_recv_file(gc, (guint8 *) buffer, len);
00191 }
00192
00193 void
00194 _qq_xfer_recv_start(GaimXfer *xfer)
00195 {
00196 }
00197
00198 void
00199 _qq_xfer_end(GaimXfer *xfer)
00200 {
00201 ft_info *info;
00202 g_return_if_fail(xfer != NULL && xfer->data != NULL);
00203 info = (ft_info *) xfer->data;
00204
00205 qq_xfer_close_file(xfer);
00206 if (info->dest_fp != NULL) {
00207 fclose(info->dest_fp);
00208 gaim_debug(GAIM_DEBUG_INFO, "QQ", "file closed\n");
00209 }
00210 if (info->major_fd != 0) {
00211 close(info->major_fd);
00212 gaim_debug(GAIM_DEBUG_INFO, "QQ", "major port closed\n");
00213 }
00214 if (info->minor_fd != 0) {
00215 close(info->minor_fd);
00216 gaim_debug(GAIM_DEBUG_INFO, "QQ", "minor port closed\n");
00217 }
00218
00219
00220
00221
00222 g_free(info);
00223 }
00224
00225 void qq_show_conn_info(ft_info *info)
00226 {
00227 gchar *internet_ip_str, *real_ip_str;
00228 guint32 ip;
00229
00230 ip = htonl(info->remote_real_ip);
00231 real_ip_str = gen_ip_str((guint8 *) &ip);
00232 ip = htonl(info->remote_internet_ip);
00233 internet_ip_str = gen_ip_str((guint8 *) &ip);
00234 gaim_debug(GAIM_DEBUG_INFO, "QQ", "remote internet ip[%s:%d], major port[%d], real ip[%s], minor port[%d]\n",
00235 internet_ip_str, info->remote_internet_port,
00236 info->remote_major_port, real_ip_str, info->remote_minor_port
00237 );
00238 g_free(real_ip_str);
00239 g_free(internet_ip_str);
00240 }
00241
00242 void qq_get_conn_info(guint8 *data, guint8 **cursor, gint data_len, ft_info *info)
00243 {
00244 read_packet_data(data, cursor, data_len, info->file_session_key, 16);
00245 *cursor += 30;
00246 read_packet_b(data, cursor, data_len, &info->conn_method);
00247 read_packet_dw(data, cursor, data_len, &info->remote_internet_ip);
00248 read_packet_w(data, cursor, data_len, &info->remote_internet_port);
00249 read_packet_w(data, cursor, data_len, &info->remote_major_port);
00250 read_packet_dw(data, cursor, data_len, &info->remote_real_ip);
00251 read_packet_w(data, cursor, data_len, &info->remote_minor_port);
00252 qq_show_conn_info(info);
00253 }
00254
00255 gint qq_fill_conn_info(guint8 *raw_data, guint8 ** cursor, ft_info *info)
00256 {
00257 gint bytes;
00258 bytes = 0;
00259
00260 bytes += create_packet_b (raw_data, cursor, info->conn_method);
00261
00262 bytes += create_packet_dw (raw_data, cursor, info->local_internet_ip);
00263
00264 bytes += create_packet_w (raw_data, cursor, info->local_internet_port);
00265
00266 bytes += create_packet_w (raw_data, cursor, info->local_major_port);
00267
00268 bytes += create_packet_dw (raw_data, cursor, info->local_real_ip);
00269
00270 bytes += create_packet_w (raw_data, cursor, info->local_minor_port);
00271 return bytes;
00272 }
00273
00274
00275 extern gchar *_gen_session_md5(gint uid, gchar *session_key);
00276
00277
00278
00279 gint _qq_create_packet_file_header
00280 (guint8 *raw_data, guint8 ** cursor, guint32 to_uid, guint16 message_type, qq_data *qd, gboolean seq_ack)
00281 {
00282 gint bytes;
00283 time_t now;
00284 gchar *md5;
00285 guint16 seq;
00286 ft_info *info;
00287
00288 bytes = 0;
00289 now = time(NULL);
00290 md5 = _gen_session_md5(qd->uid, qd->session_key);
00291 if (!seq_ack) seq = qd->send_seq;
00292 else {
00293 info = (ft_info *) qd->xfer->data;
00294 seq = info->send_seq;
00295 }
00296
00297
00298 bytes += create_packet_dw (raw_data, cursor, qd->uid);
00299
00300 bytes += create_packet_dw (raw_data, cursor, to_uid);
00301
00302 bytes += create_packet_w (raw_data, cursor, QQ_CLIENT);
00303
00304 bytes += create_packet_dw (raw_data, cursor, qd->uid);
00305
00306 bytes += create_packet_dw (raw_data, cursor, to_uid);
00307
00308 bytes += create_packet_data (raw_data, cursor, md5, 16);
00309
00310 bytes += create_packet_w (raw_data, cursor, message_type);
00311
00312 bytes += create_packet_w (raw_data, cursor, seq);
00313
00314 bytes += create_packet_dw (raw_data, cursor, (guint32) now);
00315
00316 bytes += create_packet_b (raw_data, cursor, 0x00);
00317
00318 bytes += create_packet_b (raw_data, cursor, qd->my_icon);
00319
00320 bytes += create_packet_w (raw_data, cursor, 0x0000);
00321 bytes += create_packet_b (raw_data, cursor, 0x00);
00322
00323 bytes += create_packet_b (raw_data, cursor, 0x01);
00324
00325 bytes += create_packet_dw (raw_data, cursor, 0x00000000);
00326
00327
00328 bytes += create_packet_dw (raw_data, cursor, 0x00000000);
00329 bytes += create_packet_dw (raw_data, cursor, 0x00000000);
00330 bytes += create_packet_w (raw_data, cursor, 0x0000);
00331 bytes += create_packet_b (raw_data, cursor, 0x00);
00332
00333 bytes += create_packet_b (raw_data, cursor, 0x65);
00334
00335 g_free (md5);
00336 return bytes;
00337 }
00338
00339
00340 #if 0
00341 in_addr_t get_real_ip()
00342 {
00343 char hostname[40];
00344 struct hostent *host;
00345
00346 gethostname(hostname, sizeof(hostname));
00347 host = gethostbyname(hostname);
00348 return *(host->h_addr);
00349 }
00350
00351
00352 #include <sys/ioctl.h>
00353 #include <net/if.h>
00354
00355 #define MAXINTERFACES 16
00356 in_addr_t get_real_ip()
00357 {
00358 int fd, intrface, i;
00359 struct ifconf ifc;
00360 struct ifreq buf[MAXINTERFACES];
00361 in_addr_t ret;
00362
00363 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) return 0;
00364 ifc.ifc_len = sizeof(buf);
00365 ifc.ifc_buf = (caddr_t) buf;
00366 if (ioctl(fd, SIOCGIFCONF, (char *) &ifc) < 0) return 0;
00367 intrface = ifc.ifc_len / sizeof(struct ifreq);
00368 for (i = 0; i < intrface; i++) {
00369
00370 if (ioctl(fd, SIOCGIFADDR, (char *) &buf[i]) >= 0)
00371 {
00372 ret = (((struct sockaddr_in *)(&buf[i].ifr_addr))->sin_addr).s_addr;
00373 if (ret == ntohl(0x7f000001)) continue;
00374 return ret;
00375 }
00376 }
00377 return 0;
00378 }
00379 #endif
00380
00381 void
00382 _qq_xfer_init_socket(GaimXfer *xfer)
00383 {
00384 int sockfd, listen_port = 0, i, sin_len;
00385 struct sockaddr_in sin;
00386 ft_info *info;
00387
00388 g_return_if_fail(xfer != NULL);
00389 g_return_if_fail(xfer->data != NULL);
00390 info = (ft_info *) xfer->data;
00391
00392
00393
00394
00395 info->local_real_ip = ntohl(inet_addr(gaim_network_get_my_ip(-1)));
00396 gaim_debug(GAIM_DEBUG_INFO, "QQ", "local real ip is %x", info->local_real_ip);
00397
00398 for (i = 0; i < 2; i++) {
00399 sockfd = socket(PF_INET, SOCK_DGRAM, 0);
00400 g_return_if_fail(sockfd >= 0);
00401
00402 memset(&sin, 0, sizeof(sin));
00403 sin.sin_family = AF_INET;
00404 sin.sin_port = 0;
00405 sin.sin_addr.s_addr = INADDR_ANY;
00406 sin_len = sizeof(sin);
00407 bind(sockfd, (struct sockaddr *) &sin, sin_len);
00408 getsockname(sockfd, (struct sockaddr *) &sin, &sin_len);
00409 listen_port = ntohs(sin.sin_port);
00410
00411 switch (i) {
00412 case 0:
00413 info->local_major_port = listen_port;
00414 info->major_fd = sockfd;
00415 gaim_debug(GAIM_DEBUG_INFO, "QQ", "UDP Major Channel created on port[%d]\n",
00416 info->local_major_port);
00417 break;
00418 case 1:
00419 info->local_minor_port = listen_port;
00420 info->minor_fd = sockfd;
00421 gaim_debug(GAIM_DEBUG_INFO, "QQ", "UDP Minor Channel created on port[%d]\n",
00422 info->local_minor_port);
00423 break;
00424 }
00425 }
00426
00427 if (_qq_in_same_lan(info)) {
00428 info->sender_fd = info->recv_fd = info->minor_fd;
00429 } else {
00430 info->sender_fd = info->recv_fd = info->major_fd;
00431 }
00432
00433
00434 }
00435
00436
00437
00438 void
00439 _qq_send_packet_file_request (GaimConnection * gc, guint32 to_uid,
00440 gchar * filename, gint filesize)
00441 {
00442 qq_data *qd;
00443 guint8 *cursor, *raw_data;
00444 gchar *filelen_str;
00445 gint filename_len, filelen_strlen, packet_len, bytes;
00446 ft_info *info;
00447
00448 qd = (qq_data *) gc->proto_data;
00449
00450 info = g_new0(ft_info, 1);
00451 info->to_uid = to_uid;
00452 info->send_seq = qd->send_seq;
00453 info->local_internet_ip = ntohl(inet_addr(qd->my_ip));
00454 info->local_internet_port = qd->my_port;
00455 info->local_real_ip = 0x00000000;
00456 info->conn_method = 0x00;
00457 qd->xfer->data = info;
00458
00459 filename_len = strlen (filename);
00460 filelen_str = g_strdup_printf ("%d 字节", filesize);
00461 filelen_strlen = strlen (filelen_str);
00462
00463 packet_len = 82 + filename_len + filelen_strlen;
00464 raw_data = g_newa (guint8, packet_len);
00465 cursor = raw_data;
00466
00467 bytes = _qq_create_packet_file_header(raw_data, &cursor, to_uid, QQ_FILE_TRANS_REQ, qd, FALSE);
00468 bytes += qq_fill_conn_info(raw_data, &cursor, info);
00469
00470 bytes += create_packet_b (raw_data, &cursor, 0x20);
00471
00472 bytes += create_packet_b (raw_data, &cursor, 0x1f);
00473
00474 bytes += create_packet_data (raw_data, &cursor, filename,
00475 filename_len);
00476
00477 bytes += create_packet_b (raw_data, &cursor, 0x1f);
00478
00479 bytes += create_packet_data (raw_data, &cursor, filelen_str,
00480 filelen_strlen);
00481
00482 if (packet_len == bytes)
00483 qq_send_cmd (gc, QQ_CMD_SEND_IM, TRUE, 0, TRUE, raw_data,
00484 cursor - raw_data);
00485 else
00486 gaim_debug (GAIM_DEBUG_INFO, "qq_send_packet_file_request",
00487 "%d bytes expected but got %d bytes\n",
00488 packet_len, bytes);
00489
00490 g_free (filelen_str);
00491 }
00492
00493
00494
00495 void
00496 _qq_send_packet_file_accept(GaimConnection *gc, guint32 to_uid)
00497 {
00498 qq_data *qd;
00499 guint8 *cursor, *raw_data;
00500 gint packet_len, bytes;
00501 ft_info *info;
00502
00503 g_return_if_fail (gc != NULL && gc->proto_data != NULL);
00504 qd = (qq_data *) gc->proto_data;
00505 info = (ft_info *) qd->xfer->data;
00506
00507 gaim_debug(GAIM_DEBUG_INFO, "QQ", "I've accepted the file transfer request from %d\n", to_uid);
00508 _qq_xfer_init_socket(qd->xfer);
00509 guint16 minor_port;
00510 guint32 real_ip;
00511
00512 packet_len = 79;
00513 raw_data = g_newa (guint8, packet_len);
00514 cursor = raw_data;
00515
00516 minor_port = info->local_minor_port;
00517 real_ip = info->local_real_ip;
00518 info->local_minor_port = 0;
00519 info->local_real_ip = 0;
00520
00521 bytes = _qq_create_packet_file_header(raw_data, &cursor, to_uid, QQ_FILE_TRANS_ACC_UDP, qd, TRUE);
00522 bytes += qq_fill_conn_info(raw_data, &cursor, info);
00523
00524 info->local_minor_port = minor_port;
00525 info->local_real_ip = real_ip;
00526
00527 if (packet_len == bytes)
00528 qq_send_cmd (gc, QQ_CMD_SEND_IM, TRUE, 0, TRUE, raw_data,
00529 cursor - raw_data);
00530 else
00531 gaim_debug (GAIM_DEBUG_INFO, "qq_send_packet_file_accept",
00532 "%d bytes expected but got %d bytes\n",
00533 packet_len, bytes);
00534 }
00535
00536 void _qq_send_packet_file_notifyip(GaimConnection *gc, guint32 to_uid)
00537 {
00538 GaimXfer *xfer;
00539 ft_info *info;
00540 qq_data *qd;
00541 guint8 *cursor, *raw_data;
00542 gint packet_len, bytes;
00543
00544 qd = (qq_data *) gc->proto_data;
00545 xfer = qd->xfer;
00546 info = xfer->data;
00547
00548 packet_len = 79;
00549 raw_data = g_newa (guint8, packet_len);
00550 cursor = raw_data;
00551
00552 gaim_debug(GAIM_DEBUG_INFO, "QQ", "<== sending qq file notify ip packet\n");
00553 bytes = _qq_create_packet_file_header(raw_data, &cursor, to_uid, QQ_FILE_TRANS_NOTIFY, qd, TRUE);
00554 bytes += qq_fill_conn_info(raw_data, &cursor, info);
00555 if (packet_len == bytes)
00556 qq_send_cmd (gc, QQ_CMD_SEND_IM, TRUE, 0, TRUE, raw_data,
00557 cursor - raw_data);
00558 else
00559 gaim_debug (GAIM_DEBUG_INFO, "qq_send_packet_file_notify",
00560 "%d bytes expected but got %d bytes\n",
00561 packet_len, bytes);
00562
00563 if (xfer->watcher) gaim_input_remove(xfer->watcher);
00564 xfer->watcher = gaim_input_add(info->recv_fd, GAIM_INPUT_READ, _qq_xfer_recv_packet, xfer);
00565 gaim_input_add(info->major_fd, GAIM_INPUT_READ, _qq_xfer_recv_packet, xfer);
00566
00567 }
00568
00569
00570
00571 void
00572 _qq_send_packet_file_reject (GaimConnection *gc, guint32 to_uid)
00573 {
00574 qq_data *qd;
00575 guint8 *cursor, *raw_data;
00576 gint packet_len, bytes;
00577
00578 gaim_debug(GAIM_DEBUG_INFO, "_qq_send_packet_file_reject", "start");
00579 g_return_if_fail(gc != NULL && gc->proto_data != NULL);
00580 qd = (qq_data *) gc->proto_data;
00581
00582 packet_len = 64;
00583 raw_data = g_newa (guint8, packet_len);
00584 cursor = raw_data;
00585 bytes = 0;
00586
00587 bytes = _qq_create_packet_file_header(raw_data, &cursor, to_uid, QQ_FILE_TRANS_DENY_UDP, qd, TRUE);
00588
00589 if (packet_len == bytes)
00590 qq_send_cmd (gc, QQ_CMD_SEND_IM, TRUE, 0, TRUE, raw_data,
00591 cursor - raw_data);
00592 else
00593 gaim_debug (GAIM_DEBUG_INFO, "qq_send_packet_file",
00594 "%d bytes expected but got %d bytes\n",
00595 packet_len, bytes);
00596
00597
00598 }
00599
00600
00601
00602 void
00603 _qq_send_packet_file_cancel (GaimConnection *gc, guint32 to_uid)
00604 {
00605 qq_data *qd;
00606 guint8 *cursor, *raw_data;
00607 gint packet_len, bytes;
00608
00609 gaim_debug(GAIM_DEBUG_INFO, "_qq_send_packet_file_cancel", "start\n");
00610 g_return_if_fail(gc != NULL && gc->proto_data != NULL);
00611 qd = (qq_data *) gc->proto_data;
00612
00613 packet_len = 64;
00614 raw_data = g_newa (guint8, packet_len);
00615 cursor = raw_data;
00616 bytes = 0;
00617
00618 bytes = _qq_create_packet_file_header(raw_data, &cursor, to_uid, QQ_FILE_TRANS_CANCEL, qd, TRUE);
00619
00620 if (packet_len == bytes)
00621 qq_send_cmd (gc, QQ_CMD_SEND_IM, TRUE, 0, TRUE, raw_data,
00622 cursor - raw_data);
00623 else
00624 gaim_debug (GAIM_DEBUG_INFO, "qq_send_packet_file",
00625 "%d bytes expected but got %d bytes\n",
00626 packet_len, bytes);
00627
00628
00629 }
00630
00631
00632
00633 void
00634 _qq_xfer_init (GaimXfer * xfer)
00635 {
00636 GaimConnection *gc;
00637 GaimAccount *account;
00638 guint32 to_uid;
00639 gchar *filename, *filename_without_path;
00640
00641 g_return_if_fail (xfer != NULL);
00642 account = gaim_xfer_get_account(xfer);
00643 gc = gaim_account_get_connection(account);
00644 g_return_if_fail (gc != NULL && gc->proto_data != NULL);
00645
00646 to_uid = gaim_name_to_uid (xfer->who);
00647 g_return_if_fail (to_uid != 0);
00648
00649 filename = (gchar *) gaim_xfer_get_local_filename (xfer);
00650 g_return_if_fail (filename != NULL);
00651
00652 filename_without_path = strrchr (filename, '/') + 1;
00653
00654 _qq_send_packet_file_request (gc, to_uid, filename_without_path,
00655 gaim_xfer_get_size(xfer));
00656 }
00657
00658
00659
00660 void
00661 _qq_xfer_cancel(GaimXfer *xfer)
00662 {
00663 GaimConnection *gc;
00664 GaimAccount *account;
00665 guint16 *seq;
00666
00667 g_return_if_fail (xfer != NULL);
00668 seq = (guint16 *) xfer->data;
00669 account = gaim_xfer_get_account(xfer);
00670 gc = gaim_account_get_connection(account);
00671
00672 switch (gaim_xfer_get_status(xfer)) {
00673 case GAIM_XFER_STATUS_CANCEL_LOCAL:
00674 _qq_send_packet_file_cancel(gc, gaim_name_to_uid(xfer->who));
00675 break;
00676 case GAIM_XFER_STATUS_CANCEL_REMOTE:
00677 _qq_send_packet_file_cancel(gc, gaim_name_to_uid(xfer->who));
00678 break;
00679 case GAIM_XFER_STATUS_NOT_STARTED:
00680 break;
00681 case GAIM_XFER_STATUS_UNKNOWN:
00682 _qq_send_packet_file_reject(gc, gaim_name_to_uid(xfer->who));
00683 break;
00684 case GAIM_XFER_STATUS_DONE:
00685 break;
00686 case GAIM_XFER_STATUS_ACCEPTED:
00687 break;
00688 case GAIM_XFER_STATUS_STARTED:
00689 break;
00690 }
00691 }
00692
00693
00694
00695 void
00696 _qq_xfer_recv_init(GaimXfer *xfer)
00697 {
00698 GaimConnection *gc;
00699 GaimAccount *account;
00700 ft_info *info;
00701
00702 g_return_if_fail (xfer != NULL && xfer->data != NULL);
00703 info = (ft_info *) xfer->data;
00704 account = gaim_xfer_get_account(xfer);
00705 gc = gaim_account_get_connection(account);
00706
00707 _qq_send_packet_file_accept(gc, gaim_name_to_uid(xfer->who));
00708 }
00709
00710
00711
00712 void qq_process_recv_file_reject
00713 (guint8 * data, guint8 ** cursor, gint data_len, guint32 sender_uid,
00714 GaimConnection * gc)
00715 {
00716 gchar *msg, *filename;
00717 qq_data *qd;
00718
00719 g_return_if_fail (gc != NULL && data != NULL && data_len != 0);
00720 qd = (qq_data *) gc->proto_data;
00721 g_return_if_fail (qd != NULL && qd->xfer != NULL);
00722
00723 if (*cursor >= (data + data_len - 1)) {
00724 gaim_debug (GAIM_DEBUG_WARNING, "QQ",
00725 "Received file reject message is empty\n");
00726 return;
00727 }
00728 filename = strrchr(gaim_xfer_get_local_filename(qd->xfer), '/') + 1;
00729 msg = g_strdup_printf
00730 (_
00731 ("Your request to send file[%s] has been rejected by buddy[%d]"),
00732 filename, sender_uid);
00733
00734 gaim_notify_warning (gc, _("File Send"), msg, NULL);
00735 gaim_xfer_request_denied(qd->xfer);
00736 qd->xfer = NULL;
00737
00738 g_free (msg);
00739 }
00740
00741
00742
00743 void qq_process_recv_file_cancel
00744 (guint8 * data, guint8 ** cursor, gint data_len, guint32 sender_uid,
00745 GaimConnection * gc)
00746 {
00747 gchar *msg, *filename;
00748 qq_data *qd;
00749
00750 g_return_if_fail (gc != NULL && data != NULL && data_len != 0);
00751 qd = (qq_data *) gc->proto_data;
00752 g_return_if_fail (qd != NULL && qd->xfer != NULL
00753 && gaim_xfer_get_filename(qd->xfer) != NULL);
00754
00755 if (*cursor >= (data + data_len - 1)) {
00756 gaim_debug (GAIM_DEBUG_WARNING, "QQ",
00757 "Received file reject message is empty\n");
00758 return;
00759 }
00760 filename = strrchr(gaim_xfer_get_local_filename(qd->xfer), '/') + 1;
00761 msg = g_strdup_printf
00762 (_("The sending process of file[%s] has been cancaled by buddy[%d]"),
00763 filename, sender_uid);
00764
00765 gaim_notify_warning (gc, _("File Send"), msg, NULL);
00766 gaim_xfer_cancel_remote(qd->xfer);
00767 qd->xfer = NULL;
00768
00769 g_free (msg);
00770 }
00771
00772
00773
00774 void qq_process_recv_file_accept
00775 (guint8 * data, guint8 ** cursor, gint data_len, guint32 sender_uid,
00776 GaimConnection * gc)
00777 {
00778 qq_data *qd;
00779 ft_info *info;
00780 GaimXfer *xfer;
00781
00782 g_return_if_fail (gc != NULL && data != NULL && data_len != 0);
00783 qd = (qq_data *) gc->proto_data;
00784 xfer = qd->xfer;
00785
00786 if (*cursor >= (data + data_len - 1)) {
00787 gaim_debug (GAIM_DEBUG_WARNING, "QQ",
00788 "Received file reject message is empty\n");
00789 return;
00790 }
00791
00792 info = (ft_info *) qd->xfer->data;
00793
00794 *cursor = data + 18 + 12;
00795 qq_get_conn_info(data, cursor, data_len, info);
00796 _qq_xfer_init_socket(qd->xfer);
00797
00798 _qq_xfer_init_udp_channel(info);
00799 _qq_send_packet_file_notifyip(gc, sender_uid);
00800 }
00801
00802
00803
00804 void qq_process_recv_file_request
00805 (guint8 * data, guint8 ** cursor, gint data_len, guint32 sender_uid,
00806 GaimConnection * gc)
00807 {
00808 qq_data *qd;
00809 GaimXfer *xfer;
00810 gchar *sender_name;
00811 ft_info *info;
00812
00813 g_return_if_fail (gc != NULL && data != NULL && data_len != 0);
00814 qd = (qq_data *) gc->proto_data;
00815
00816 if (*cursor >= (data + data_len - 1)) {
00817 gaim_debug (GAIM_DEBUG_WARNING, "QQ",
00818 "Received file reject message is empty\n");
00819 return;
00820 }
00821
00822 info = g_new0(ft_info, 1);
00823 info->local_internet_ip = ntohl(inet_addr(qd->my_ip));
00824 info->local_internet_port = qd->my_port;
00825 info->local_real_ip = 0x00000000;
00826 info->to_uid = sender_uid;
00827 read_packet_w(data, cursor, data_len, &(info->send_seq));
00828
00829 *cursor = data + 18 + 12;
00830 qq_get_conn_info(data, cursor, data_len, info);
00831
00832 sender_name = uid_to_gaim_name(sender_uid);
00833 xfer = gaim_xfer_new(gaim_connection_get_account(gc),
00834 GAIM_XFER_RECEIVE,
00835 sender_name);
00836
00837 gchar **fileinfo;
00838 fileinfo = g_strsplit(data + 81 + 12, "\x1f", 2);
00839 g_return_if_fail (fileinfo != NULL && fileinfo[0] != NULL && fileinfo[1] != NULL);
00840 gaim_xfer_set_filename(xfer, fileinfo[0]);
00841 gaim_xfer_set_size(xfer, atoi(fileinfo[1]));
00842
00843 gaim_xfer_set_init_fnc(xfer, _qq_xfer_recv_init);
00844 gaim_xfer_set_request_denied_fnc(xfer, _qq_xfer_cancel);
00845 gaim_xfer_set_cancel_recv_fnc(xfer, _qq_xfer_cancel);
00846 gaim_xfer_set_end_fnc(xfer, _qq_xfer_end);
00847 gaim_xfer_set_write_fnc(xfer, _qq_xfer_write);
00848
00849 xfer->data = info;
00850 qd->xfer = xfer;
00851
00852 gaim_xfer_request(xfer);
00853
00854 g_free(sender_name);
00855 g_strfreev(fileinfo);
00856
00857
00858 }
00859
00860 void
00861 _qq_xfer_send_notify_ip_ack(gpointer data, gint source, GaimInputCondition cond)
00862 {
00863 GaimXfer *xfer = (GaimXfer *) data;
00864 GaimAccount *account = gaim_xfer_get_account(xfer);
00865 GaimConnection *gc = gaim_account_get_connection(account);
00866 ft_info *info = (ft_info *) xfer->data;
00867
00868 gaim_input_remove(xfer->watcher);
00869 xfer->watcher = gaim_input_add(info->recv_fd, GAIM_INPUT_READ, _qq_xfer_recv_packet, xfer);
00870 qq_send_file_ctl_packet(gc, QQ_FILE_CMD_NOTIFY_IP_ACK, info->to_uid, 0);
00871
00872
00873
00874 }
00875
00876 void qq_process_recv_file_notify
00877 (guint8 * data, guint8 ** cursor, gint data_len, guint32 sender_uid,
00878 GaimConnection * gc)
00879 {
00880 qq_data *qd;
00881 ft_info *info;
00882 GaimXfer *xfer;
00883
00884 g_return_if_fail (gc != NULL && data != NULL && data_len != 0);
00885 qd = (qq_data *) gc->proto_data;
00886
00887 if (*cursor >= (data + data_len - 1)) {
00888 gaim_debug (GAIM_DEBUG_WARNING, "QQ",
00889 "Received file notify message is empty\n");
00890 return;
00891 }
00892
00893 xfer = qd->xfer;
00894 info = (ft_info *) qd->xfer->data;
00895
00896 read_packet_w(data, cursor, data_len, &(info->send_seq));
00897
00898 *cursor = data + 18 + 12;
00899 qq_get_conn_info(data, cursor, data_len, info);
00900
00901 _qq_xfer_init_udp_channel(info);
00902
00903 xfer->watcher = gaim_input_add(info->sender_fd, GAIM_INPUT_WRITE, _qq_xfer_send_notify_ip_ack, xfer);
00904 }
00905
00906 void qq_send_file(GaimConnection *gc, const char *who, const char *file)
00907 {
00908 qq_data *qd;
00909 GaimXfer *xfer;
00910
00911 g_return_if_fail (gc != NULL && gc->proto_data != NULL);
00912 qd = (qq_data *) gc->proto_data;
00913
00914 xfer = gaim_xfer_new (gc->account, GAIM_XFER_SEND,
00915 who);
00916 gaim_xfer_set_init_fnc (xfer, _qq_xfer_init);
00917 gaim_xfer_set_cancel_send_fnc (xfer, _qq_xfer_cancel);
00918 gaim_xfer_set_write_fnc(xfer, _qq_xfer_write);
00919
00920 qd->xfer = xfer;
00921 gaim_xfer_request (xfer);
00922 }
00923
00924 void qq_send_packet_request_key(GaimConnection *gc, guint8 key)
00925 {
00926 qq_send_cmd(gc, QQ_CMD_REQUEST_KEY, TRUE, 0, TRUE, &key, 1);
00927 }
00928
00929 void qq_process_recv_request_key(GaimConnection *gc)
00930 {
00931 }