00001
00023
00024
00025 #include "connection.h"
00026 #include "debug.h"
00027 #include "internal.h"
00028 #include "notify.h"
00029 #include "prefs.h"
00030 #include "request.h"
00031
00032 #include "header_info.h"
00033 #include "qq_proxy.h"
00034 #include "sendqueue.h"
00035
00036 #define QQ_RESEND_MAX 5 // max resend per packet
00037
00038 typedef struct _gc_and_packet gc_and_packet;
00039
00040 struct _gc_and_packet {
00041 GaimConnection *gc;
00042 qq_sendpacket *packet;
00043 };
00044
00045
00046
00047 void qq_sendqueue_remove(qq_data * qd, guint16 send_seq)
00048 {
00049 GList *list;
00050 qq_sendpacket *p;
00051
00052 g_return_if_fail(qd != NULL);
00053
00054 list = qd->sendqueue;
00055 while (list != NULL) {
00056 p = (qq_sendpacket *) (list->data);
00057 if (p->send_seq == send_seq) {
00058 qd->sendqueue = g_list_remove(qd->sendqueue, p);
00059 g_free(p->buf);
00060 g_free(p);
00061 break;
00062 }
00063 list = list->next;
00064 }
00065 }
00066
00067
00068
00069 void qq_sendqueue_free(qq_data * qd)
00070 {
00071 qq_sendpacket *p;
00072 gint i;
00073
00074 i = 0;
00075 while (qd->sendqueue != NULL) {
00076 p = (qq_sendpacket *) (qd->sendqueue->data);
00077 qd->sendqueue = g_list_remove(qd->sendqueue, p);
00078 g_free(p->buf);
00079 g_free(p);
00080 i++;
00081 }
00082 gaim_debug(GAIM_DEBUG_INFO, "QQ", "%d packets in sendqueue are freed!\n", i);
00083 }
00084
00085
00086
00087
00088 void _qq_send_again(gc_and_packet * gp)
00089 {
00090 GaimConnection *gc;
00091 qq_data *qd;
00092 qq_sendpacket *packet;
00093 GList *list;
00094
00095 g_return_if_fail(gp != NULL && gp->gc != NULL && gp->packet != NULL);
00096 g_return_if_fail(gp->gc->proto_data != NULL);
00097
00098 gc = gp->gc;
00099 packet = gp->packet;
00100 qd = (qq_data *) gc->proto_data;
00101
00102 list = g_list_find(qd->sendqueue, packet);
00103 if (list != NULL) {
00104 packet->resend_times = 0;
00105 packet->sendtime = time(NULL);
00106 qq_proxy_write(qd, packet->buf, packet->len);
00107 }
00108 g_free(gp);
00109 }
00110
00111
00112
00113 void _qq_send_cancel(gc_and_packet * gp)
00114 {
00115 GaimConnection *gc;
00116 qq_data *qd;
00117 qq_sendpacket *packet;
00118 GList *list;
00119
00120 g_return_if_fail(gp != NULL && gp->gc != NULL && gp->packet != NULL);
00121 g_return_if_fail(gp->gc->proto_data != NULL);
00122
00123 gc = gp->gc;
00124 packet = gp->packet;
00125 qd = (qq_data *) gc->proto_data;
00126
00127 list = g_list_find(qd->sendqueue, packet);
00128 if (list != NULL)
00129 qq_sendqueue_remove(qd, packet->send_seq);
00130
00131 g_free(gp);
00132 }
00133
00134
00135 gboolean qq_sendqueue_timeout_callback(gpointer data)
00136 {
00137 GaimConnection *gc;
00138 qq_data *qd;
00139 GList *list;
00140 qq_sendpacket *p;
00141 gc_and_packet *gp;
00142 time_t now;
00143 gint wait_time;
00144 gboolean need_action;
00145
00146 gc = (GaimConnection *) data;
00147 qd = (qq_data *) gc->proto_data;
00148 now = time(NULL);
00149 list = qd->sendqueue;
00150
00151
00152 if (qd->sendqueue == NULL)
00153 return TRUE;
00154
00155 while (list != NULL) {
00156 p = (qq_sendpacket *) list->data;
00157 if (p->resend_times == -1) {
00158 qd->sendqueue = g_list_remove(qd->sendqueue, p);
00159 g_free(p->buf);
00160 g_free(p);
00161 list = qd->sendqueue;
00162 } else
00163 list = list->next;
00164 }
00165
00166 list = qd->sendqueue;
00167 while (list != NULL) {
00168 p = (qq_sendpacket *) list->data;
00169 if (p->resend_times >= QQ_RESEND_MAX) {
00170 if (p->resend_times == QQ_RESEND_MAX) {
00171 switch (p->cmd) {
00172 case QQ_CMD_KEEP_ALIVE:
00173 if (qd->logged_in) {
00174 gaim_debug(GAIM_DEBUG_ERROR, "QQ", "Connection lost!\n");
00175 gaim_connection_error(gc, _("Connection lost!"));
00176 qd->logged_in = FALSE;
00177 }
00178 p->resend_times = -1;
00179 break;
00180 case QQ_CMD_LOGIN:
00181 if (!qd->logged_in)
00182 gaim_connection_error(gc, _("Login failed, no reply!"));
00183 p->resend_times = -1;
00184 break;
00185 case QQ_CMD_UPDATE_INFO:
00186 gaim_notify_error(gc, NULL,
00187 _("Connection timeout!"), _("User info is not updated"));
00188 p->resend_times = -1;
00189 break;
00190 default:{
00191 need_action =
00192 gaim_prefs_get_bool("/plugins/prpl/qq/prompt_for_missing_packet");
00193 if (!need_action)
00194 p->resend_times = -1;
00195 else {
00196 gp = g_new0(gc_and_packet, 1);
00197 gp->gc = gc;
00198 gp->packet = p;
00199 gaim_request_action
00200 (gc, NULL,
00201 _
00202 ("Send packet"),
00203 _
00204 ("Packets lost, send again?"),
00205 0, gp, 2,
00206 _("Send"),
00207 G_CALLBACK
00208 (_qq_send_again),
00209 _("Cancel"), G_CALLBACK(_qq_send_cancel));
00210 p->resend_times++;
00211 }
00212 }
00213 }
00214 }
00215 } else {
00216 wait_time = (gint) (QQ_SENDQUEUE_TIMEOUT / 1000);
00217 if (difftime(now, p->sendtime) > (wait_time * (p->resend_times + 1))) {
00218 qq_proxy_write(qd, p->buf, p->len);
00219 p->resend_times++;
00220 gaim_debug(GAIM_DEBUG_INFO,
00221 "QQ", "<<< [%05d] send again for %d times!\n", p->send_seq, p->resend_times);
00222 }
00223 }
00224 list = list->next;
00225 }
00226 return TRUE;
00227 }
00228
00229
00230