首页 | 数据结构 | 文件列表 | 数据字段 | 全局定义

send_file.c

浏览该文件的文档。
00001 
00025 #include <network.h>
00026 
00027 #include "send_file.h"
00028 #include "debug.h"
00029 #include "notify.h"
00030 #include "network.h"    //gaim_network_get_my_ip
00031 
00032 #include "im.h"         //qq_create_packet_im_header
00033 #include "packet_parse.h"
00034 #include "crypt.h"
00035 #include "header_info.h"
00036 #include "send_core.h"
00037 #include "utils.h"              // gaim_name_to_uid
00038 #include "file_trans.h" // qq_send_file_ctl
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 //      return connect(info->sender_fd, (struct sockaddr *) &sin, sizeof(sin));
00077 }
00078 
00079 /* these 2 functions send and recv buffer from/to UDP channel */
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 ssize_t _qq_xfer_udp_send(const char *buf, size_t len, GaimXfer *xfer)
00097 {
00098         ft_info *info;
00099 
00100         info = (ft_info *) xfer->data;
00101         return send(info->sender_fd, buf, len, 0);
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 /* user-defined functions for gaim_xfer_read and gaim_xfer_write */
00133 
00134 /*
00135 ssize_t _qq_xfer_read(char **buf, GaimXfer *xfer)
00136 {
00137         *buf = g_newa(char, QQ_FILE_FRAGMENT_MAXLEN + 100);
00138         return _qq_xfer_udp_recv(*buf, QQ_FILE_FRAGMENT_MAXLEN + 100, xfer);
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         /* FIXME: It seems that the transfer never use a packet
00156          * larger than 1500 bytes, so if it happened to be a
00157          * larger packet, either error occured or protocol should
00158          * be modified
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 // start file transfer process
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 //      if (info->buffer != NULL) {
00219 //              munmap(info->buffer, gaim_xfer_get_size(xfer));
00220 //              gaim_debug(GAIM_DEBUG_INFO, "QQ", "file mapping buffer is freed.\n");
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         // 064: connection method, UDP 0x00, TCP 0x03
00260         bytes += create_packet_b (raw_data, cursor, info->conn_method);
00261         // 065-068: outer ip address of sender (proxy address)
00262         bytes += create_packet_dw (raw_data, cursor, info->local_internet_ip);
00263         // 069-070: sender port
00264         bytes += create_packet_w (raw_data, cursor, info->local_internet_port);
00265         // 071-072: the first listening port(TCP doesn't have this part)
00266         bytes += create_packet_w (raw_data, cursor, info->local_major_port);
00267         // 073-076: real ip
00268         bytes += create_packet_dw (raw_data, cursor, info->local_real_ip);
00269         // 077-078: the second listening port
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 // fill in the common information of file transfer
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         // 000-003: receiver uid
00298         bytes += create_packet_dw (raw_data, cursor, qd->uid);
00299         // 004-007: sender uid
00300         bytes += create_packet_dw (raw_data, cursor, to_uid);
00301         // 008-009: sender client version
00302         bytes += create_packet_w (raw_data, cursor, QQ_CLIENT);
00303         // 010-013: receiver uid
00304         bytes += create_packet_dw (raw_data, cursor, qd->uid);
00305         // 014-017: sender uid
00306         bytes += create_packet_dw (raw_data, cursor, to_uid);
00307         // 018-033: md5 of (uid+session_key)
00308         bytes += create_packet_data (raw_data, cursor, md5, 16);
00309         // 034-035: message type
00310         bytes += create_packet_w (raw_data, cursor, message_type);
00311         // 036-037: sequence number
00312         bytes += create_packet_w (raw_data, cursor, seq);
00313         // 038-041: send time
00314         bytes += create_packet_dw (raw_data, cursor, (guint32) now);
00315         // 042-042: always 0x00
00316         bytes += create_packet_b (raw_data, cursor, 0x00);
00317         // 043-043: sender icon
00318         bytes += create_packet_b (raw_data, cursor, qd->my_icon);
00319         // 044-046: always 0x00
00320         bytes += create_packet_w (raw_data, cursor, 0x0000);
00321         bytes += create_packet_b (raw_data, cursor, 0x00);
00322         // 047-047: we use font attr
00323         bytes += create_packet_b (raw_data, cursor, 0x01);
00324         // 048-051: always 0x00
00325         bytes += create_packet_dw (raw_data, cursor, 0x00000000);
00326 
00327         // 052-062: always 0x00
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         // 063: unknown, always 0x65
00333         bytes += create_packet_b (raw_data, cursor, 0x65);
00334 
00335         g_free (md5);
00336         return bytes;
00337 }       //_qq_create_packet_file_header
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                 //buf[intrface].ifr_name
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 //      info->local_real_ip = ntohl(get_real_ip());
00393 //debug
00394 //      info->local_real_ip = 0x7f000001;
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 //      xfer->watcher = gaim_input_add(info->recv_fd, GAIM_INPUT_READ, _qq_xfer_recv_packet, xfer);
00434 }
00435 
00436 /*****************************************************************************/
00437 // create the QQ_FILE_TRANS_REQ packet with file infomations
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         // 079: 0x20
00470         bytes += create_packet_b (raw_data, &cursor, 0x20);
00471         // 080: 0x1f
00472         bytes += create_packet_b (raw_data, &cursor, 0x1f);
00473         // undetermined len: filename
00474         bytes += create_packet_data (raw_data, &cursor, filename,
00475                                      filename_len);
00476         // 0x1f
00477         bytes += create_packet_b (raw_data, &cursor, 0x1f);
00478         // file length
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 }       //_qq_send_packet_file_request
00492 
00493 /*****************************************************************************/
00494 // tell the buddy we want to accept the file
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 }       //_qq_send_packet_packet_accept
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 //      gaim_input_add(info->minor_fd, GAIM_INPUT_READ, _qq_xfer_recv_packet, xfer);
00567 }
00568 
00569 /*****************************************************************************/
00570 // tell the buddy we don't want the file
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 //      gaim_debug (GAIM_DEBUG_INFO, "qq_send_packet_file_reject", "end\n");
00598 }                               // qq_send_packet_file_reject
00599 
00600 /*****************************************************************************/
00601 // tell the buddy to cancel transfer
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 //      gaim_debug (GAIM_DEBUG_INFO, "qq_send_packet_file_cancel", "end\n");
00629 }                               // qq_send_packet_file_cancel
00630 
00631 /*****************************************************************************/
00632 // request to send a file
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 }                               // qq_xfer_init
00657 
00658 /*****************************************************************************/
00659 // cancel the transfer of receiving files
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 // init the transfer of receiving files
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 // process reject im for file transfer request
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 }                               // qq_process_recv_file_reject
00740 
00741 /*****************************************************************************/
00742 // process cancel im for file transfer request
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 }                               // qq_process_recv_file_cancel
00771 
00772 /*****************************************************************************/
00773 // process accept im for file transfer request
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 }                               // qq_process_recv_file_accept
00801 
00802 /*****************************************************************************/
00803 // process request from buddy's im for file transfer request
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 //      gaim_debug (GAIM_DEBUG_INFO, "qq_process_recv_file_request", "end\n");
00858 }                               // qq_process_recv_file_request
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 //      info->use_major = TRUE;
00872 //      qq_send_file_ctl_packet(gc, QQ_FILE_CMD_NOTIFY_IP_ACK, info->to_uid, 0);
00873 //      info->use_major = FALSE;
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         /* FIXME */
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 }

Generated at Mon May 8 15:41:24 2006 for OpenQ by  doxygen 1.4.4