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

send_core.c

浏览该文件的文档。
00001 
00023 // START OF FILE
00024 /*****************************************************************************/
00025 #include "debug.h"              // gaim_debug
00026 #include "internal.h"           // send, socket
00027 
00028 #include "packet_parse.h"       // MAX_PACKET_SIZE
00029 #include "crypt.h"              // qq_crypt
00030 #include "header_info.h"        // cmd alias
00031 #include "qq_proxy.h"           // qq_proxy_write
00032 #include "send_core.h"
00033 #include "sendqueue.h"          // qq_sendpacket
00034 #include "qq.h"                 // qq_data, QQ_DEBUG
00035 
00036 /*****************************************************************************/
00037 // create qq packet header with given sequence
00038 // return the number of bytes in header if succeeds
00039 // return -1 if there is any error
00040 gint _create_packet_head_seq(guint8 * buf, guint8 ** cursor,
00041                              GaimConnection * gc, guint16 cmd, gboolean is_auto_seq, guint16 * seq)
00042 {
00043         qq_data *qd;
00044         gint bytes_expected, bytes_written;
00045 
00046         g_return_val_if_fail(gc != NULL &&
00047                              gc->proto_data != NULL && buf != NULL && cursor != NULL && *cursor != NULL, -1);
00048 
00049         qd = (qq_data *) gc->proto_data;
00050         if (is_auto_seq)
00051                 *seq = ++(qd->send_seq);
00052 
00053         *cursor = buf;
00054         bytes_written = 0;
00055         bytes_expected = (qd->use_tcp) ? QQ_TCP_HEADER_LENGTH : QQ_UDP_HEADER_LENGTH;
00056 
00057         // QQ TCP packet has two bytes in the begining defines packet length
00058         // so I leave room here for size
00059         if (qd->use_tcp)
00060                 bytes_written += create_packet_w(buf, cursor, 0x0000);
00061 
00062         // now comes the normal QQ packet as UDP
00063         bytes_written += create_packet_b(buf, cursor, QQ_PACKET_TAG);
00064         bytes_written += create_packet_w(buf, cursor, QQ_CLIENT);
00065         bytes_written += create_packet_w(buf, cursor, cmd);
00066         bytes_written += create_packet_w(buf, cursor, *seq);
00067 
00068         if (bytes_written != bytes_expected) {
00069                 gaim_debug(GAIM_DEBUG_ERROR, "QQ",
00070                            "Fail create qq header, expect %d bytes, written %d bytes\n", bytes_expected, bytes_written);
00071                 bytes_written = -1;
00072         }
00073         return bytes_written;
00074 }                               // _create_packet_head_seq
00075 
00076 /*****************************************************************************/
00077 // for those need ack and resend no ack feed back from server
00078 // return number of bytes written to the socket,
00079 // return -1 if there is any error
00080 gint _qq_send_packet(GaimConnection * gc, guint8 * buf, gint len, guint16 cmd)
00081 {
00082         qq_data *qd;
00083         qq_sendpacket *p;
00084         gint bytes_sent;
00085         guint8 *cursor;
00086 
00087         g_return_val_if_fail(gc != NULL && gc->proto_data != NULL, -1);
00088 
00089         qd = (qq_data *) gc->proto_data;
00090 
00091         if (qd->use_tcp) {
00092                 if (len > MAX_PACKET_SIZE) {
00093                         gaim_debug(GAIM_DEBUG_ERROR, "QQ",
00094                                    "xxx [%05d] %s, %d bytes is too large, do not send\n",
00095                                    qq_get_cmd_desc(cmd), qd->send_seq, len);
00096                         return -1;
00097                 } else {        // I update the len for TCP packet
00098                         cursor = buf;
00099                         create_packet_w(buf, &cursor, len);
00100                 }               // if len
00101         }                       // if use_tcp
00102 
00103         bytes_sent = qq_proxy_write(qd, buf, len);
00104 
00105         if (bytes_sent >= 0) {
00106                 p = g_new0(qq_sendpacket, 1);
00107                 p->fd = qd->fd;
00108                 p->cmd = cmd;
00109                 p->send_seq = qd->send_seq;
00110                 p->resend_times = 0;
00111                 p->sendtime = time(NULL);
00112                 p->buf = g_memdup(buf, len);    // don't use g_strdup, may have 0x00
00113                 p->len = len;
00114                 qd->sendqueue = g_list_append(qd->sendqueue, p);
00115         }                       // if bytes_sent
00116 
00117         return bytes_sent;
00118 
00119 }                               // _qq_send_packet
00120 
00121 /*****************************************************************************/
00122 // send the packet generated with the given cmd and data
00123 // return the number of bytes sent to socket if succeeds
00124 // return -1 if there is any error
00125 gint qq_send_cmd(GaimConnection * gc, guint16 cmd,
00126                  gboolean is_auto_seq, guint16 seq, gboolean need_ack, guint8 * data, gint len)
00127 {
00128         qq_data *qd;
00129         guint8 *buf, *cursor, *encrypted_data;
00130         guint16 seq_ret;
00131         gint encrypted_len, bytes_written, bytes_expected, bytes_sent;
00132 
00133         g_return_val_if_fail(gc != NULL && gc->proto_data != NULL, -1);
00134 
00135         qd = (qq_data *) gc->proto_data;
00136         g_return_val_if_fail(qd->session_key != NULL, -1);
00137 
00138         // use g_newa, so that the allocated memory will be freed
00139         // when the current stack frame is cleaned up
00140         buf = g_newa(guint8, MAX_PACKET_SIZE);
00141         encrypted_len = len + 16;       // at most 16 bytes more
00142         encrypted_data = g_newa(guint8, encrypted_len);
00143         cursor = buf;
00144         bytes_written = 0;
00145 
00146         qq_crypt(ENCRYPT, data, len, qd->session_key, encrypted_data, &encrypted_len);
00147 
00148         seq_ret = seq;
00149         if (_create_packet_head_seq(buf, &cursor, gc, cmd, is_auto_seq, &seq_ret) >= 0) {
00150                 bytes_expected = 4 + encrypted_len + 1;
00151                 bytes_written += create_packet_dw(buf, &cursor, (guint32) qd->uid);
00152                 bytes_written += create_packet_data(buf, &cursor, encrypted_data, encrypted_len);
00153                 bytes_written += create_packet_b(buf, &cursor, QQ_PACKET_TAIL);
00154                 if (bytes_written == bytes_expected) {  // packet OK
00155                         // if it does not need ACK, we send ACK manually several times
00156                         if (need_ack)
00157                                 bytes_sent = _qq_send_packet(gc, buf, cursor - buf, cmd);
00158                         else
00159                                 bytes_sent = qq_proxy_write(qd, buf, cursor - buf);
00160 
00161                         if (QQ_DEBUG)
00162                                 gaim_debug(GAIM_DEBUG_INFO, "QQ",
00163                                            "<== [%05d] %s, %d bytes\n", seq_ret, qq_get_cmd_desc(cmd), bytes_sent);
00164                         return bytes_sent;
00165                 } else {        // bad packet
00166                         gaim_debug(GAIM_DEBUG_ERROR, "QQ",
00167                                    "Fail creating packet, expect %d bytes, written %d bytes\n",
00168                                    bytes_expected, bytes_written);
00169                         return -1;
00170                 }               // if bytes_written
00171         }                       // if create_packet_head_seq
00172         return -1;
00173 }                               // qq_send_cmd
00174 
00175 /*****************************************************************************/
00176 // END OF FILE

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