comparison src/protocols/qq/recv_core.c @ 14021:ef8490f9e823

[gaim-migrate @ 16618] Replaced all C++-style comments with C-style ones. Cleaned up some comments and implemented a more consistent formatting scheme. committer: Tailor Script <tailor@pidgin.im>
author Mark Huetsch <markhuetsch>
date Wed, 02 Aug 2006 15:35:36 +0000
parents 983fd420e86b
children 8294485b79db
comparison
equal deleted inserted replaced
14020:13e7ba964993 14021:ef8490f9e823
18 * You should have received a copy of the GNU General Public License 18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software 19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */ 21 */
22 22
23 // START OF FILE 23 #include "debug.h"
24 /*****************************************************************************/ 24 #include "internal.h"
25 #include "debug.h" // gaim_debug 25
26 #include "internal.h" // _("get_text") 26 #include "buddy_info.h"
27 27 #include "buddy_list.h"
28 #include "utils.h" // hex_dump_to_str 28 #include "buddy_opt.h"
29 #include "packet_parse.h" // MAX_PACKET_SIZE 29 #include "buddy_status.h"
30 #include "buddy_info.h" // qq_process_modify_info_reply 30 #include "char_conv.h"
31 #include "buddy_list.h" // qq_process_get_buddies_list_reply 31 #include "crypt.h"
32 #include "buddy_opt.h" // qq_process_add_buddy_reply 32 #include "group_network.h"
33 #include "buddy_status.h" // qq_process_friend_change_status 33 #include "header_info.h"
34 #include "char_conv.h" // qq_to_utf8 34 #include "keep_alive.h"
35 #include "crypt.h" // qq_crypt 35 #include "im.h"
36 #include "group_network.h" // qq_process_group_cmd_reply 36 #include "login_logout.h"
37 #include "header_info.h" // cmd alias 37 #include "packet_parse.h"
38 #include "keep_alive.h" // qq_process_keep_alive_reply 38 #include "qq_proxy.h"
39 #include "im.h" // qq_process_send_im_reply
40 #include "login_logout.h" // qq_process_login_reply
41 #include "qq_proxy.h" // qq_proxy_read
42 #include "recv_core.h" 39 #include "recv_core.h"
43 #include "sendqueue.h" // qq_sendqueue_remove 40 #include "sendqueue.h"
44 #include "sys_msg.h" // qq_process_msg_sys 41 #include "sys_msg.h"
42 #include "utils.h"
45 43
46 typedef struct _packet_before_login packet_before_login; 44 typedef struct _packet_before_login packet_before_login;
47 typedef struct _qq_recv_msg_header qq_recv_msg_header; 45 typedef struct _qq_recv_msg_header qq_recv_msg_header;
48 46
49 struct _packet_before_login { 47 struct _packet_before_login {
53 51
54 struct _qq_recv_msg_header { 52 struct _qq_recv_msg_header {
55 guint8 header_tag; 53 guint8 header_tag;
56 guint16 source_tag; 54 guint16 source_tag;
57 guint16 cmd; 55 guint16 cmd;
58 guint16 seq; // can be ack_seq or send_seq, depends on cmd 56 guint16 seq; /* can be ack_seq or send_seq, depends on cmd */
59 }; 57 };
60 58
61 /*****************************************************************************/ 59 /* check whether one sequence number is duplicated or not
62 // check whether one sequence number is duplicated or not 60 * return TRUE if it is duplicated, otherwise FALSE */
63 // return TRUE if it is duplicated, otherwise FALSE 61 static gboolean _qq_check_packet_set_window(guint16 seq, GaimConnection *gc)
64 static gboolean _qq_check_packet_set_window(guint16 seq, GaimConnection * gc)
65 { 62 {
66 qq_data *qd; 63 qq_data *qd;
67 gchar *byte, mask; 64 gchar *byte, mask;
68 65
69 g_return_val_if_fail(gc != NULL && gc->proto_data != NULL, FALSE); 66 g_return_val_if_fail(gc != NULL && gc->proto_data != NULL, FALSE);
70 qd = (qq_data *) gc->proto_data; 67 qd = (qq_data *) gc->proto_data;
71 byte = &(qd->window[seq / 8]); 68 byte = &(qd->window[seq / 8]);
72 mask = (1 << (seq % 8)); 69 mask = (1 << (seq % 8));
73 70
74 if ((*byte) & mask) 71 if ((*byte) & mask)
75 return TRUE; // check mask 72 return TRUE; /* check mask */
76 (*byte) |= mask; 73 (*byte) |= mask;
77 return FALSE; // set mask 74 return FALSE; /* set mask */
78 } // _qq_check_packet_set_window 75 } /* _qq_check_packet_set_window */
79 76
80 /*****************************************************************************/ 77 /* default process, decrypt and dump */
81 // default process, decrypt and dump 78 static void _qq_process_packet_default(guint8 *buf, gint buf_len, guint16 cmd, guint16 seq, GaimConnection *gc)
82 static void _qq_process_packet_default(guint8 * buf, gint buf_len, guint16 cmd, guint16 seq, GaimConnection * gc) { 79 {
83
84 qq_data *qd; 80 qq_data *qd;
85 guint8 *data; 81 guint8 *data;
86 gchar *msg_utf8; 82 gchar *msg_utf8;
87 gint len; 83 gint len;
88 84
97 if (qq_crypt(DECRYPT, buf, buf_len, qd->session_key, data, &len)) { 93 if (qq_crypt(DECRYPT, buf, buf_len, qd->session_key, data, &len)) {
98 gaim_debug(GAIM_DEBUG_WARNING, "QQ", 94 gaim_debug(GAIM_DEBUG_WARNING, "QQ",
99 ">>> [%d] %s, %d bytes -> [default] decrypt and dump\n%s", 95 ">>> [%d] %s, %d bytes -> [default] decrypt and dump\n%s",
100 seq, qq_get_cmd_desc(cmd), buf_len, hex_dump_to_str(data, len)); 96 seq, qq_get_cmd_desc(cmd), buf_len, hex_dump_to_str(data, len));
101 try_dump_as_gbk(data, len); 97 try_dump_as_gbk(data, len);
102 } else 98 } else {
103 gaim_debug(GAIM_DEBUG_ERROR, "QQ", "Fail decrypt packet with default process\n"); 99 gaim_debug(GAIM_DEBUG_ERROR, "QQ", "Fail decrypt packet with default process\n");
104 100 }
105 } // _qq_process_packet_default 101 }
106 102
107 /*****************************************************************************/ 103 /* process the incoming packet from qq_pending */
108 // process the incoming packet from qq_pending 104 static void _qq_packet_process(guint8 *buf, gint buf_len, GaimConnection *gc)
109 static void _qq_packet_process(guint8 * buf, gint buf_len, GaimConnection * gc)
110 { 105 {
111 qq_data *qd; 106 qq_data *qd;
112 gint len, bytes_expected, bytes_read; 107 gint len, bytes_expected, bytes_read;
113 guint16 buf_len_read; // two bytes in the begining of TCP packet 108 guint16 buf_len_read; /* two bytes in the begining of TCP packet */
114 guint8 *cursor; 109 guint8 *cursor;
115 qq_recv_msg_header header; 110 qq_recv_msg_header header;
116 packet_before_login *b4_packet; 111 packet_before_login *b4_packet;
117 112
118 g_return_if_fail(gc != NULL && gc->proto_data != NULL); 113 g_return_if_fail(gc != NULL && gc->proto_data != NULL);
124 if (buf_len < bytes_expected) { 119 if (buf_len < bytes_expected) {
125 gaim_debug(GAIM_DEBUG_ERROR, 120 gaim_debug(GAIM_DEBUG_ERROR,
126 "QQ", "Received packet is too short, dump and drop\n%s", hex_dump_to_str(buf, buf_len)); 121 "QQ", "Received packet is too short, dump and drop\n%s", hex_dump_to_str(buf, buf_len));
127 return; 122 return;
128 } 123 }
129 // initialize 124 /* initialize */
130 cursor = buf; 125 cursor = buf;
131 bytes_read = 0; 126 bytes_read = 0;
132 127
133 // QQ TCP packet returns first 2 bytes the length of this packet 128 /* QQ TCP packet returns first 2 bytes the length of this packet */
134 if (qd->use_tcp) { 129 if (qd->use_tcp) {
135 bytes_read += read_packet_w(buf, &cursor, buf_len, &buf_len_read); 130 bytes_read += read_packet_w(buf, &cursor, buf_len, &buf_len_read);
136 if (buf_len_read != buf_len) { // wrong 131 if (buf_len_read != buf_len) { /* wrong */
137 gaim_debug 132 gaim_debug
138 (GAIM_DEBUG_ERROR, 133 (GAIM_DEBUG_ERROR,
139 "QQ", 134 "QQ",
140 "TCP read %d bytes, header says %d bytes, use header anyway\n", buf_len, buf_len_read); 135 "TCP read %d bytes, header says %d bytes, use header anyway\n", buf_len, buf_len_read);
141 buf_len = buf_len_read; // we believe header is more accurate 136 buf_len = buf_len_read; /* we believe header is more accurate */
142 } // if buf_len_read 137 }
143 } // if use_tcp 138 }
144 139
145 // now goes the normal QQ packet as UDP packet 140 /* now goes the normal QQ packet as UDP packet */
146 bytes_read += read_packet_b(buf, &cursor, buf_len, &header.header_tag); 141 bytes_read += read_packet_b(buf, &cursor, buf_len, &header.header_tag);
147 bytes_read += read_packet_w(buf, &cursor, buf_len, &header.source_tag); 142 bytes_read += read_packet_w(buf, &cursor, buf_len, &header.source_tag);
148 bytes_read += read_packet_w(buf, &cursor, buf_len, &header.cmd); 143 bytes_read += read_packet_w(buf, &cursor, buf_len, &header.cmd);
149 bytes_read += read_packet_w(buf, &cursor, buf_len, &header.seq); 144 bytes_read += read_packet_w(buf, &cursor, buf_len, &header.seq);
150 145
151 if (bytes_read != bytes_expected) { // read error 146 if (bytes_read != bytes_expected) { /* read error */
152 gaim_debug(GAIM_DEBUG_ERROR, "QQ", 147 gaim_debug(GAIM_DEBUG_ERROR, "QQ",
153 "Fail reading packet header, expect %d bytes, read %d bytes\n", bytes_expected, bytes_read); 148 "Fail reading packet header, expect %d bytes, read %d bytes\n",
149 bytes_expected, bytes_read);
154 return; 150 return;
155 } // if bytes_read 151 }
156 152
157 if ((buf[buf_len - 1] != QQ_PACKET_TAIL) || (header.header_tag != QQ_PACKET_TAG)) { 153 if ((buf[buf_len - 1] != QQ_PACKET_TAIL) || (header.header_tag != QQ_PACKET_TAG)) {
158 gaim_debug(GAIM_DEBUG_ERROR, 154 gaim_debug(GAIM_DEBUG_ERROR,
159 "QQ", "Unknown QQ proctocol, dump and drop\n%s", hex_dump_to_str(buf, buf_len)); 155 "QQ", "Unknown QQ proctocol, dump and drop\n%s", hex_dump_to_str(buf, buf_len));
160 return; 156 return;
161 } // if header_tag 157 }
162 158
163 if (QQ_DEBUG) 159 if (QQ_DEBUG)
164 gaim_debug(GAIM_DEBUG_INFO, "QQ", 160 gaim_debug(GAIM_DEBUG_INFO, "QQ",
165 "==> [%05d] %s, from (%s)\n", 161 "==> [%05d] %s, from (%s)\n",
166 header.seq, qq_get_cmd_desc(header.cmd), qq_get_source_str(header.source_tag)); 162 header.seq, qq_get_cmd_desc(header.cmd), qq_get_source_str(header.source_tag));
167 163
168 if (header.cmd != QQ_CMD_LOGIN && header.cmd != QQ_CMD_REQUEST_LOGIN_TOKEN /* gfhuang */) { 164 if (header.cmd != QQ_CMD_LOGIN && header.cmd != QQ_CMD_REQUEST_LOGIN_TOKEN) {
169 if (!qd->logged_in) { // packets before login 165 if (!qd->logged_in) { /* packets before login */
170 b4_packet = g_new0(packet_before_login, 1); 166 b4_packet = g_new0(packet_before_login, 1);
171 // must duplicate, buffer will be freed after exiting this function 167 /* must duplicate, buffer will be freed after exiting this function */
172 b4_packet->buf = g_memdup(buf, buf_len); 168 b4_packet->buf = g_memdup(buf, buf_len);
173 b4_packet->len = buf_len; 169 b4_packet->len = buf_len;
174 if (qd->before_login_packets == NULL) 170 if (qd->before_login_packets == NULL)
175 qd->before_login_packets = g_queue_new(); 171 qd->before_login_packets = g_queue_new();
176 g_queue_push_head(qd->before_login_packets, b4_packet); 172 g_queue_push_head(qd->before_login_packets, b4_packet);
177 return; // do not process it now 173 return; /* do not process it now */
178 } else if (!g_queue_is_empty(qd->before_login_packets)) { 174 } else if (!g_queue_is_empty(qd->before_login_packets)) {
179 // logged_in, but we have packets before login 175 /* logged_in, but we have packets before login */
180 b4_packet = (packet_before_login *) 176 b4_packet = (packet_before_login *)
181 g_queue_pop_head(qd->before_login_packets); 177 g_queue_pop_head(qd->before_login_packets);
182 _qq_packet_process(b4_packet->buf, b4_packet->len, gc); 178 _qq_packet_process(b4_packet->buf, b4_packet->len, gc);
183 // in fact this is a recursive call, 179 /* in fact this is a recursive call,
184 // all packets before login will be processed before goes on 180 * all packets before login will be processed before goes on */
185 g_free(b4_packet->buf); // the buf is duplicated, need to be freed 181 g_free(b4_packet->buf); /* the buf is duplicated, need to be freed */
186 g_free(b4_packet); 182 g_free(b4_packet);
187 } // if logged_in 183 }
188 } //if header.cmd != QQ_CMD_LOGIN 184 }
189 185
190 // this is the length of all the encrypted data (also remove tail tag 186 /* this is the length of all the encrypted data (also remove tail tag */
191 len = buf_len - (bytes_read) - 1; 187 len = buf_len - (bytes_read) - 1;
192 188
193 // whether it is an ack 189 /* whether it is an ack */
194 switch (header.cmd) { 190 switch (header.cmd) {
195 case QQ_CMD_RECV_IM: 191 case QQ_CMD_RECV_IM:
196 case QQ_CMD_RECV_MSG_SYS: 192 case QQ_CMD_RECV_MSG_SYS:
197 case QQ_CMD_RECV_MSG_FRIEND_CHANGE_STATUS: 193 case QQ_CMD_RECV_MSG_FRIEND_CHANGE_STATUS:
198 // server intiated packet, we need to send ack and check duplicaion 194 /* server intiated packet, we need to send ack and check duplicaion
199 // this must be put after processing b4_packet 195 * this must be put after processing b4_packet
200 // as these packets will be passed in twice 196 * as these packets will be passed in twice */
201 if (_qq_check_packet_set_window(header.seq, gc)) { 197 if (_qq_check_packet_set_window(header.seq, gc)) {
202 gaim_debug(GAIM_DEBUG_WARNING, 198 gaim_debug(GAIM_DEBUG_WARNING,
203 "QQ", "dup [%05d] %s, discard...\n", header.seq, qq_get_cmd_desc(header.cmd)); 199 "QQ", "dup [%05d] %s, discard...\n", header.seq, qq_get_cmd_desc(header.cmd));
204 return; 200 return;
205 } 201 }
206 break; 202 break;
207 default:{ // ack packet, we need to update sendqueue 203 default:{ /* ack packet, we need to update sendqueue */
208 // we do not check duplication for server ack 204 /* we do not check duplication for server ack */
209 qq_sendqueue_remove(qd, header.seq); 205 qq_sendqueue_remove(qd, header.seq);
210 if (QQ_DEBUG) 206 if (QQ_DEBUG)
211 gaim_debug(GAIM_DEBUG_INFO, "QQ", 207 gaim_debug(GAIM_DEBUG_INFO, "QQ",
212 "ack [%05d] %s, remove from sendqueue\n", 208 "ack [%05d] %s, remove from sendqueue\n",
213 header.seq, qq_get_cmd_desc(header.cmd)); 209 header.seq, qq_get_cmd_desc(header.cmd));
214 } // default 210 }
215 } // switch header.cmd 211 }
216 212
217 // now process the packet 213 /* now process the packet */
218 switch (header.cmd) { 214 switch (header.cmd) {
219 case QQ_CMD_KEEP_ALIVE: 215 case QQ_CMD_KEEP_ALIVE:
220 qq_process_keep_alive_reply(cursor, len, gc); 216 qq_process_keep_alive_reply(cursor, len, gc);
221 break; 217 break;
222 case QQ_CMD_UPDATE_INFO: 218 case QQ_CMD_UPDATE_INFO:
256 qq_process_get_buddies_online_reply(cursor, len, gc); 252 qq_process_get_buddies_online_reply(cursor, len, gc);
257 break; 253 break;
258 case QQ_CMD_GROUP_CMD: 254 case QQ_CMD_GROUP_CMD:
259 qq_process_group_cmd_reply(cursor, len, header.seq, gc); 255 qq_process_group_cmd_reply(cursor, len, header.seq, gc);
260 break; 256 break;
261 case QQ_CMD_GET_ALL_LIST_WITH_GROUP: //added by gfhuang 257 case QQ_CMD_GET_ALL_LIST_WITH_GROUP:
262 qq_process_get_all_list_with_group_reply(cursor, len, gc); 258 qq_process_get_all_list_with_group_reply(cursor, len, gc);
263 break; 259 break;
264 case QQ_CMD_REQUEST_LOGIN_TOKEN: //added by gfhuang 260 case QQ_CMD_REQUEST_LOGIN_TOKEN:
265 qq_process_request_login_token_reply(cursor, len, gc); 261 qq_process_request_login_token_reply(cursor, len, gc);
266 break; 262 break;
267 case QQ_CMD_RECV_MSG_SYS: 263 case QQ_CMD_RECV_MSG_SYS:
268 qq_process_msg_sys(cursor, len, header.seq, gc); 264 qq_process_msg_sys(cursor, len, header.seq, gc);
269 break; 265 break;
271 qq_process_friend_change_status(cursor, len, gc); 267 qq_process_friend_change_status(cursor, len, gc);
272 break; 268 break;
273 default: 269 default:
274 _qq_process_packet_default(cursor, len, header.cmd, header.seq, gc); 270 _qq_process_packet_default(cursor, len, header.cmd, header.seq, gc);
275 break; 271 break;
276 } // switch header.cmd 272 }
277 } // _qq_packet_process 273 }
278 274
279 /*****************************************************************************/ 275 /* clean up the packets before login */
280 // clean up the packets before login 276 void qq_b4_packets_free(qq_data *qd)
281 void qq_b4_packets_free(qq_data * qd)
282 { 277 {
283 packet_before_login *b4_packet; 278 packet_before_login *b4_packet;
284 g_return_if_fail(qd != NULL); 279 g_return_if_fail(qd != NULL);
285 // now clean up my own data structures 280 /* now clean up my own data structures */
286 if (qd->before_login_packets != NULL) { 281 if (qd->before_login_packets != NULL) {
287 while (NULL != (b4_packet = g_queue_pop_tail(qd->before_login_packets))) { 282 while (NULL != (b4_packet = g_queue_pop_tail(qd->before_login_packets))) {
288 g_free(b4_packet->buf); 283 g_free(b4_packet->buf);
289 g_free(b4_packet); 284 g_free(b4_packet);
290 } 285 }
291 g_queue_free(qd->before_login_packets); 286 g_queue_free(qd->before_login_packets);
292 } // if 287 }
293 } // qq_b4_packets_free 288 }
294 289
295 /*****************************************************************************/
296 void qq_input_pending(gpointer data, gint source, GaimInputCondition cond) 290 void qq_input_pending(gpointer data, gint source, GaimInputCondition cond)
297 { 291 {
298 GaimConnection *gc; 292 GaimConnection *gc;
299 qq_data *qd;; 293 qq_data *qd;;
300 guint8 *buf; 294 guint8 *buf;
302 296
303 gc = (GaimConnection *) data; 297 gc = (GaimConnection *) data;
304 g_return_if_fail(gc != NULL && gc->proto_data != NULL && cond == GAIM_INPUT_READ); 298 g_return_if_fail(gc != NULL && gc->proto_data != NULL && cond == GAIM_INPUT_READ);
305 299
306 qd = (qq_data *) gc->proto_data; 300 qd = (qq_data *) gc->proto_data;
307 // according to glib manual memory allocated by g_newa could be
308 // automatically freed when the current stack frame is cleaned up
309 buf = g_newa(guint8, MAX_PACKET_SIZE); 301 buf = g_newa(guint8, MAX_PACKET_SIZE);
310 302
311 // here we have UDP proxy suppport 303 /* here we have UDP proxy suppport */
312 len = qq_proxy_read(qd, buf, MAX_PACKET_SIZE); 304 len = qq_proxy_read(qd, buf, MAX_PACKET_SIZE);
313 if (len <= 0) { 305 if (len <= 0) {
314 gaim_connection_error(gc, _("Unable to read from socket")); 306 gaim_connection_error(gc, _("Unable to read from socket"));
315 return; 307 return;
316 } else 308 } else {
317 _qq_packet_process(buf, len, gc); 309 _qq_packet_process(buf, len, gc);
318 } // qq_input_pending 310 }
319 311 }
320 /*****************************************************************************/
321 // END OF FILE