comparison libpurple/protocols/qq/qq_trans.c @ 24095:25f62d21b3f8

disapproval of revision '8cebefbc6cd5d84acb69c74e69e8821f11dd225d'
author Daniel Atallah <daniel.atallah@gmail.com>
date Mon, 15 Sep 2008 03:04:07 +0000
parents 147ada94a1d8
children 225e0e9e1055
comparison
equal deleted inserted replaced
24088:147ada94a1d8 24095:25f62d21b3f8
35 #include "qq_process.h" 35 #include "qq_process.h"
36 #include "qq_trans.h" 36 #include "qq_trans.h"
37 37
38 #define QQ_RESEND_MAX 3 /* max resend per packet */ 38 #define QQ_RESEND_MAX 3 /* max resend per packet */
39 39
40 enum { 40 qq_transaction *qq_trans_find_rcved(qq_data *qd, guint16 cmd, guint16 seq)
41 QQ_TRANS_IS_SERVER = 0x01, /* Is server command or client command */ 41 {
42 QQ_TRANS_IS_IMPORT = 0x02, /* Only notice if not get reply; or resend, disconn if reties get 0*/
43 QQ_TRANS_BEFORE_LOGIN = 0x04, /* server command before login*/
44 };
45
46 struct _qq_transaction {
47 guint8 flag;
48 guint16 seq;
49 guint16 cmd;
50
51 guint8 room_cmd;
52 guint32 room_id;
53
54 guint8 *data;
55 gint data_len;
56
57 gint fd;
58 gint send_retries;
59 gint rcved_times;
60 gint scan_times;
61
62 gint update_class;
63 guint32 ship32;
64 };
65
66 qq_transaction *qq_trans_find_rcved(PurpleConnection *gc, guint16 cmd, guint16 seq)
67 {
68 qq_data *qd = (qq_data *)gc->proto_data;
69 GList *curr; 42 GList *curr;
70 GList *next; 43 GList *next;
71 qq_transaction *trans; 44 qq_transaction *trans;
72 45
73 if (qd->transactions == NULL) { 46 if (qd->transactions == NULL) {
75 } 48 }
76 49
77 next = qd->transactions; 50 next = qd->transactions;
78 while( (curr = next) ) { 51 while( (curr = next) ) {
79 next = curr->next; 52 next = curr->next;
80 53
81 trans = (qq_transaction *) (curr->data); 54 trans = (qq_transaction *) (curr->data);
82 if(trans->cmd == cmd && trans->seq == seq) { 55 if(trans->cmd == cmd && trans->seq == seq) {
83 if (trans->rcved_times == 0) { 56 if (trans->rcved_times == 0) {
84 trans->scan_times = 0; 57 trans->scan_times = 0;
85 } 58 }
86 trans->rcved_times++; 59 trans->rcved_times++;
87 /* server may not get our confirm reply before, send reply again*/
88 /* only rcved buffer stored in transaction
89 if (qq_trans_is_server(trans) && qq_trans_is_dup(trans)) { 60 if (qq_trans_is_server(trans) && qq_trans_is_dup(trans)) {
61 /* server may not get our confirm reply before, send reply again*/
90 if (trans->data != NULL && trans->data_len > 0) { 62 if (trans->data != NULL && trans->data_len > 0) {
91 qq_send_cmd_encrypted(gc, trans->cmd, trans->seq, trans->data, trans->data_len, FALSE); 63 qq_send_data(qd, trans->cmd, trans->seq, FALSE, trans->data, trans->data_len);
92 } 64 }
93 } 65 }
94 */
95 return trans; 66 return trans;
96 } 67 }
97 } 68 }
98 69
99 return NULL; 70 return NULL;
100 } 71 }
101 72
102 gboolean qq_trans_is_server(qq_transaction *trans) 73 gboolean qq_trans_is_server(qq_transaction *trans)
103 { 74 {
104 g_return_val_if_fail(trans != NULL, FALSE); 75 g_return_val_if_fail(trans != NULL, FALSE);
105 76
106 if (trans->flag & QQ_TRANS_IS_SERVER) 77 if (trans->flag & QQ_TRANS_IS_SERVER)
107 return TRUE; 78 return TRUE;
108 else 79 else
109 return FALSE; 80 return FALSE;
110 } 81 }
111 82
112 gboolean qq_trans_is_dup(qq_transaction *trans) 83 gboolean qq_trans_is_dup(qq_transaction *trans)
113 { 84 {
114 g_return_val_if_fail(trans != NULL, TRUE); 85 g_return_val_if_fail(trans != NULL, TRUE);
115 86
116 if (trans->rcved_times > 1) 87 if (trans->rcved_times > 1)
117 return TRUE; 88 return TRUE;
118 else 89 else
119 return FALSE; 90 return FALSE;
120 } 91 }
129 { 100 {
130 g_return_val_if_fail(trans != NULL, 0); 101 g_return_val_if_fail(trans != NULL, 0);
131 return trans->room_id; 102 return trans->room_id;
132 } 103 }
133 104
134 gint qq_trans_get_class(qq_transaction *trans)
135 {
136 g_return_val_if_fail(trans != NULL, QQ_CMD_CLASS_NONE);
137 return trans->update_class;
138 }
139
140 gint qq_trans_get_ship(qq_transaction *trans)
141 {
142 g_return_val_if_fail(trans != NULL, 0);
143 return trans->ship32;
144 }
145
146 static qq_transaction *trans_create(PurpleConnection *gc, gint fd,
147 guint16 cmd, guint16 seq, guint8 *data, gint data_len, gint update_class, guint32 ship32)
148 {
149 qq_data *qd;
150 qq_transaction *trans;
151
152 g_return_val_if_fail(gc != NULL && gc->proto_data != NULL, NULL);
153 qd = (qq_data *) gc->proto_data;
154
155 trans = g_new0(qq_transaction, 1);
156
157 memset(trans, 0, sizeof(qq_transaction));
158 trans->fd = fd;
159 trans->cmd = cmd;
160 trans->seq = seq;
161
162 trans->data = NULL;
163 trans->data_len = 0;
164 if (data != NULL && data_len > 0) {
165 /* don't use g_strdup, may have 0x00 */
166 trans->data = g_memdup(data, data_len);
167 trans->data_len = data_len;
168 }
169
170 trans->update_class = update_class;
171 return trans;
172 }
173
174 /* Remove a packet with seq from send trans */ 105 /* Remove a packet with seq from send trans */
175 static void trans_remove(PurpleConnection *gc, qq_transaction *trans) 106 static void trans_remove(qq_data *qd, qq_transaction *trans)
176 { 107 {
177 qq_data *qd = (qq_data *)gc->proto_data;
178 g_return_if_fail(qd != NULL && trans != NULL); 108 g_return_if_fail(qd != NULL && trans != NULL);
179 109
180 #if 0 110 purple_debug(PURPLE_DEBUG_INFO, "QQ_TRANS",
181 purple_debug_info("QQ_TRANS",
182 "Remove [%s%05d] retry %d rcved %d scan %d %s\n", 111 "Remove [%s%05d] retry %d rcved %d scan %d %s\n",
183 (trans->flag & QQ_TRANS_IS_SERVER) ? "SRV-" : "", 112 (trans->flag & QQ_TRANS_IS_SERVER) ? "SRV-" : "",
184 trans->seq, 113 trans->seq,
185 trans->send_retries, trans->rcved_times, trans->scan_times, 114 trans->send_retries, trans->rcved_times, trans->scan_times,
186 qq_get_cmd_desc(trans->cmd)); 115 qq_get_cmd_desc(trans->cmd));
187 #endif 116
188 if (trans->data) g_free(trans->data); 117 if (trans->data) g_free(trans->data);
189 qd->transactions = g_list_remove(qd->transactions, trans); 118 qd->transactions = g_list_remove(qd->transactions, trans);
190 g_free(trans); 119 g_free(trans);
191 } 120 }
192 121
193 void qq_trans_add_client_cmd(PurpleConnection *gc, 122 void qq_trans_add_client_cmd(qq_data *qd, guint16 cmd, guint16 seq, guint8 *data, gint data_len)
194 guint16 cmd, guint16 seq, guint8 *data, gint data_len, gint update_class, guint32 ship32) 123 {
195 { 124 qq_transaction *trans = g_new0(qq_transaction, 1);
196 qq_data *qd = (qq_data *)gc->proto_data; 125
197 qq_transaction *trans = trans_create(gc, qd->fd, cmd, seq, data, data_len, update_class, ship32); 126 g_return_if_fail(trans != NULL);
198 127
128 trans->flag = 0;
199 if (cmd == QQ_CMD_TOKEN || cmd == QQ_CMD_LOGIN || cmd == QQ_CMD_KEEP_ALIVE) { 129 if (cmd == QQ_CMD_TOKEN || cmd == QQ_CMD_LOGIN || cmd == QQ_CMD_KEEP_ALIVE) {
200 trans->flag |= QQ_TRANS_IS_IMPORT; 130 trans->flag |= QQ_TRANS_CLI_IMPORT;
201 } 131 }
132 trans->fd = qd->fd;
133 trans->cmd = cmd;
134 trans->seq = seq;
135 trans->room_cmd = 0;
136 trans->room_id = 0;
202 trans->send_retries = QQ_RESEND_MAX; 137 trans->send_retries = QQ_RESEND_MAX;
203 #if 0 138 trans->rcved_times = 0;
204 purple_debug_info("QQ_TRANS", "Add client cmd, seq %d, data %p, len %d\n", 139 trans->scan_times = 0;
140
141 trans->data = NULL;
142 trans->data_len = 0;
143 if (data != NULL && data_len > 0) {
144 trans->data = g_memdup(data, data_len); /* don't use g_strdup, may have 0x00 */
145 trans->data_len = data_len;
146 }
147 purple_debug(PURPLE_DEBUG_INFO, "QQ_TRANS",
148 "Add client cmd, seq = %d, data = %p, len = %d\n",
205 trans->seq, trans->data, trans->data_len); 149 trans->seq, trans->data, trans->data_len);
206 #endif
207 qd->transactions = g_list_append(qd->transactions, trans); 150 qd->transactions = g_list_append(qd->transactions, trans);
208 } 151 }
209 152
210 void qq_trans_add_room_cmd(PurpleConnection *gc, 153 void qq_trans_add_room_cmd(qq_data *qd, guint16 seq, guint8 room_cmd, guint32 room_id,
211 guint16 seq, guint8 room_cmd, guint32 room_id, guint8 *data, gint data_len, 154 guint8 *data, gint data_len)
212 gint update_class, guint32 ship32) 155 {
213 { 156 qq_transaction *trans = g_new0(qq_transaction, 1);
214 qq_data *qd = (qq_data *)gc->proto_data; 157
215 qq_transaction *trans = trans_create(gc, qd->fd, QQ_CMD_ROOM, seq, data, data_len, 158 g_return_if_fail(trans != NULL);
216 update_class, ship32); 159
217 160 trans->flag = 0;
161 trans->fd = qd->fd;
162 trans->seq = seq;
163 trans->cmd = QQ_CMD_ROOM;
218 trans->room_cmd = room_cmd; 164 trans->room_cmd = room_cmd;
219 trans->room_id = room_id; 165 trans->room_id = room_id;
220 trans->send_retries = QQ_RESEND_MAX; 166 trans->send_retries = QQ_RESEND_MAX;
221 #if 0 167 trans->rcved_times = 0;
222 purple_debug_info("QQ_TRANS", "Add room cmd, seq %d, data %p, len %d\n", 168 trans->scan_times = 0;
169
170 trans->data = NULL;
171 trans->data_len = 0;
172 if (data != NULL && data_len > 0) {
173 trans->data = g_memdup(data, data_len); /* don't use g_strdup, may have 0x00 */
174 trans->data_len = data_len;
175 }
176 purple_debug(PURPLE_DEBUG_INFO, "QQ_TRANS",
177 "Add room cmd, seq = %d, data = %p, len = %d\n",
223 trans->seq, trans->data, trans->data_len); 178 trans->seq, trans->data, trans->data_len);
224 #endif
225 qd->transactions = g_list_append(qd->transactions, trans); 179 qd->transactions = g_list_append(qd->transactions, trans);
226 } 180 }
227 181
228 void qq_trans_add_server_cmd(PurpleConnection *gc, 182 void qq_trans_add_server_cmd(qq_data *qd, guint16 cmd, guint16 seq, guint8 *data, gint data_len)
229 guint16 cmd, guint16 seq, guint8 *data, gint data_len) 183 {
230 { 184 qq_transaction *trans = g_new0(qq_transaction, 1);
231 qq_data *qd = (qq_data *)gc->proto_data; 185
232 qq_transaction *trans = trans_create(gc, qd->fd, cmd, seq, data, data_len, QQ_CMD_CLASS_NONE, 0); 186 g_return_if_fail(trans != NULL);
233 187
234 trans->flag = QQ_TRANS_IS_SERVER; 188 trans->flag = QQ_TRANS_IS_SERVER;
235 if ( !qd->is_login ) { 189 if ( !qd->logged_in ) {
236 trans->flag |= QQ_TRANS_BEFORE_LOGIN; 190 trans->flag |= QQ_TRANS_BEFORE_LOGIN;
237 } 191 }
192 trans->fd = qd->fd;
193 trans->cmd = cmd;
194 trans->seq = seq;
195 trans->room_cmd = 0;
196 trans->room_id = 0;
238 trans->send_retries = 0; 197 trans->send_retries = 0;
239 trans->rcved_times = 1; 198 trans->rcved_times = 1;
240 #if 0 199 trans->scan_times = 0;
241 purple_debug_info("QQ_TRANS", "Add server cmd, seq %d, data %p, len %d\n", 200 trans->data = NULL;
201 trans->data_len = 0;
202 if (data != NULL && data_len > 0) {
203 trans->data = g_memdup(data, data_len); /* don't use g_strdup, may have 0x00 */
204 trans->data_len = data_len;
205 }
206 purple_debug(PURPLE_DEBUG_INFO, "QQ_TRANS",
207 "Add server cmd, seq = %d, data = %p, len = %d\n",
242 trans->seq, trans->data, trans->data_len); 208 trans->seq, trans->data, trans->data_len);
243 #endif
244 qd->transactions = g_list_append(qd->transactions, trans); 209 qd->transactions = g_list_append(qd->transactions, trans);
245 } 210 }
246 211
247 void qq_trans_process_before_login(PurpleConnection *gc) 212 void qq_trans_process_before_login(qq_data *qd)
248 { 213 {
249 qq_data *qd = (qq_data *)gc->proto_data;
250 GList *curr; 214 GList *curr;
251 GList *next; 215 GList *next;
252 qq_transaction *trans; 216 qq_transaction *trans;
253 217
254 g_return_if_fail(qd != NULL); 218 g_return_if_fail(qd != NULL);
255 219
256 next = qd->transactions; 220 next = qd->transactions;
257 while( (curr = next) ) { 221 while( (curr = next) ) {
258 next = curr->next; 222 next = curr->next;
259 trans = (qq_transaction *) (curr->data); 223 trans = (qq_transaction *) (curr->data);
260 #if 0 224 /* purple_debug(PURPLE_DEBUG_ERROR, "QQ_TRANS", "Scan [%d]\n", trans->seq); */
261 purple_debug_info("QQ_TRANS", "Scan [%d]\n", trans->seq); 225
262 #endif
263 if ( !(trans->flag & QQ_TRANS_IS_SERVER) ) { 226 if ( !(trans->flag & QQ_TRANS_IS_SERVER) ) {
264 continue; 227 continue;
265 } 228 }
266 if ( !(trans->flag & QQ_TRANS_BEFORE_LOGIN) ) { 229 if ( !(trans->flag & QQ_TRANS_BEFORE_LOGIN) ) {
267 continue; 230 continue;
268 } 231 }
269 /* set QQ_TRANS_BEFORE_LOGIN off */ 232 // set QQ_TRANS_BEFORE_LOGIN off
270 trans->flag &= ~QQ_TRANS_BEFORE_LOGIN; 233 trans->flag &= ~QQ_TRANS_BEFORE_LOGIN;
271 234
272 purple_debug_info("QQ_TRANS", 235 purple_debug(PURPLE_DEBUG_ERROR, "QQ_TRANS",
273 "Process server cmd before login, seq %d, data %p, len %d, send_retries %d\n", 236 "Process server cmd before login, seq %d, data %p, len %d, send_retries %d\n",
274 trans->seq, trans->data, trans->data_len, trans->send_retries); 237 trans->seq, trans->data, trans->data_len, trans->send_retries);
275 238
276 qq_proc_cmd_reply(gc, trans->seq, trans->cmd, trans->data, trans->data_len, trans->update_class, trans->ship32); 239 qq_proc_cmd_reply(qd->gc, trans->seq, trans->cmd, trans->data, trans->data_len);
277 } 240 }
278 241
279 /* purple_debug_info("QQ_TRANS", "Scan finished\n"); */ 242 /* purple_debug(PURPLE_DEBUG_INFO, "QQ_TRANS", "Scan finished\n"); */
280 return; 243 return;
281 } 244 }
282 245
283 gboolean qq_trans_scan(PurpleConnection *gc) 246 gboolean qq_trans_scan(qq_data *qd)
284 { 247 {
285 qq_data *qd = (qq_data *)gc->proto_data;
286 GList *curr; 248 GList *curr;
287 GList *next; 249 GList *next;
288 qq_transaction *trans; 250 qq_transaction *trans;
289 251
290 g_return_val_if_fail(qd != NULL, FALSE); 252 g_return_val_if_fail(qd != NULL, FALSE);
291 253
292 next = qd->transactions; 254 next = qd->transactions;
293 while( (curr = next) ) { 255 while( (curr = next) ) {
294 next = curr->next; 256 next = curr->next;
295 trans = (qq_transaction *) (curr->data); 257 trans = (qq_transaction *) (curr->data);
296 /* purple_debug_info("QQ_TRANS", "Scan [%d]\n", trans->seq); */ 258 /* purple_debug(PURPLE_DEBUG_INFO, "QQ_TRANS", "Scan [%d]\n", trans->seq); */
297 259
298 if (trans->flag & QQ_TRANS_BEFORE_LOGIN) { 260 if (trans->flag & QQ_TRANS_BEFORE_LOGIN) {
299 /* keep server cmd before login*/ 261 /* keep server cmd before login*/
300 continue; 262 continue;
301 } 263 }
302 264
306 continue; 268 continue;
307 } 269 }
308 270
309 if (trans->rcved_times > 0) { 271 if (trans->rcved_times > 0) {
310 /* Has been received */ 272 /* Has been received */
311 trans_remove(gc, trans); 273 trans_remove(qd, trans);
312 continue; 274 continue;
313 } 275 }
314 276
315 if (trans->flag & QQ_TRANS_IS_SERVER) { 277 if (trans->flag & QQ_TRANS_IS_SERVER) {
316 continue; 278 continue;
317 } 279 }
318 280
319 /* Never get reply */ 281 /* Never get reply */
320 trans->send_retries--; 282 trans->send_retries--;
321 if (trans->send_retries <= 0) { 283 if (trans->send_retries <= 0) {
322 purple_debug_warning("QQ_TRANS", 284 purple_debug(PURPLE_DEBUG_WARNING, "QQ_TRANS",
323 "[%d] %s is lost.\n", 285 "[%d] %s is lost.\n",
324 trans->seq, qq_get_cmd_desc(trans->cmd)); 286 trans->seq, qq_get_cmd_desc(trans->cmd));
325 if (trans->flag & QQ_TRANS_IS_IMPORT) { 287 if (trans->flag & QQ_TRANS_CLI_IMPORT) {
326 return TRUE; 288 return TRUE;
327 } 289 }
328 290
329 purple_debug_error("QQ_TRANS", 291 purple_debug(PURPLE_DEBUG_ERROR, "QQ_TRANS",
330 "Lost [%d] %s, data %p, len %d, retries %d\n", 292 "Lost [%d] %s, data %p, len %d, retries %d\n",
331 trans->seq, qq_get_cmd_desc(trans->cmd), 293 trans->seq, qq_get_cmd_desc(trans->cmd),
332 trans->data, trans->data_len, trans->send_retries); 294 trans->data, trans->data_len, trans->send_retries);
333 trans_remove(gc, trans); 295 trans_remove(qd, trans);
334 continue; 296 continue;
335 } 297 }
336 298
337 purple_debug_error("QQ_TRANS", 299 purple_debug(PURPLE_DEBUG_ERROR, "QQ_TRANS",
338 "Resend [%d] %s data %p, len %d, send_retries %d\n", 300 "Resend [%d] %s data %p, len %d, send_retries %d\n",
339 trans->seq, qq_get_cmd_desc(trans->cmd), 301 trans->seq, qq_get_cmd_desc(trans->cmd),
340 trans->data, trans->data_len, trans->send_retries); 302 trans->data, trans->data_len, trans->send_retries);
341 qq_send_cmd_encrypted(gc, trans->cmd, trans->seq, trans->data, trans->data_len, FALSE); 303 qq_send_data(qd, trans->cmd, trans->seq, FALSE, trans->data, trans->data_len);
342 } 304 }
343 305
344 /* purple_debug_info("QQ_TRANS", "Scan finished\n"); */ 306 /* purple_debug(PURPLE_DEBUG_INFO, "QQ_TRANS", "Scan finished\n"); */
345 return FALSE; 307 return FALSE;
346 } 308 }
347 309
348 /* clean up send trans and free all contents */ 310 /* clean up send trans and free all contents */
349 void qq_trans_remove_all(PurpleConnection *gc) 311 void qq_trans_remove_all(qq_data *qd)
350 { 312 {
351 qq_data *qd = (qq_data *)gc->proto_data; 313 GList *curr;
314 GList *next;
352 qq_transaction *trans; 315 qq_transaction *trans;
353 gint count = 0; 316 gint count = 0;
354 317
355 while(qd->transactions != NULL) { 318 curr = qd->transactions;
356 trans = (qq_transaction *) (qd->transactions->data); 319 while(curr) {
357 qd->transactions = g_list_remove(qd->transactions, trans); 320 next = curr->next;
358 321
359 if (trans->data) g_free(trans->data); 322 trans = (qq_transaction *) (curr->data);
360 g_free(trans); 323 /*
324 purple_debug(PURPLE_DEBUG_ERROR, "QQ_TRANS",
325 "Remove to transaction, seq = %d, buf = %p, len = %d\n",
326 trans->seq, trans->buf, trans->len);
327 */
328 trans_remove(qd, trans);
361 329
362 count++; 330 count++;
363 } 331 curr = next;
364 if (count > 0) { 332 }
365 purple_debug_info("QQ_TRANS", "Free all %d packets\n", count); 333 g_list_free(qd->transactions);
366 } 334
367 } 335 purple_debug(PURPLE_DEBUG_INFO, "QQ_TRANS", "Free all %d packets\n", count);
336 }