Mercurial > pidgin.yaz
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 |