Mercurial > pidgin
diff libpurple/protocols/qq/qq_network.c @ 24113:5c030dc88356
merge of '035bfdb2d9357e8feaf49c1fea3daa75cd90d74d'
and 'e0d4adfcd908978bcad627bd8212730ce8775292'
author | Daniel Atallah <daniel.atallah@gmail.com> |
---|---|
date | Mon, 15 Sep 2008 03:05:34 +0000 |
parents | fb8204e956a1 6408be948d56 |
children | 225e0e9e1055 |
line wrap: on
line diff
--- a/libpurple/protocols/qq/qq_network.c Mon Sep 15 03:05:11 2008 +0000 +++ b/libpurple/protocols/qq/qq_network.c Mon Sep 15 03:05:34 2008 +0000 @@ -234,6 +234,8 @@ qq_data *qd; gint bytes, bytes_not_read; + gboolean prev_update_status; + guint8 header_tag; guint16 source_tag; guint16 cmd; @@ -254,8 +256,8 @@ bytes += packet_get_header(&header_tag, &source_tag, &cmd, &seq, buf + bytes); #if 1 - purple_debug_info("QQ", "==> [%05d] %s 0x%04X, source tag 0x%04X len %d\n", - seq, qq_get_cmd_desc(cmd), cmd, source_tag, buf_len); + purple_debug_info("QQ", "==> [%05d] 0x%04X %s, source tag 0x%04X len %d\n", + seq, cmd, qq_get_cmd_desc(cmd), source_tag, buf_len); #endif /* this is the length of all the encrypted data (also remove tail tag) */ bytes_not_read = buf_len - bytes - 1; @@ -265,11 +267,9 @@ trans = qq_trans_find_rcved(gc, cmd, seq); if (trans == NULL) { /* new server command */ - if ( !qd->is_login ) { - qq_trans_add_remain(gc, cmd, seq, buf + bytes, bytes_not_read); - } else { - qq_trans_add_server_cmd(gc, cmd, seq, buf + bytes, bytes_not_read); - qq_proc_server_cmd(gc, cmd, seq, buf + bytes, bytes_not_read); + qq_trans_add_server_cmd(gc, cmd, seq, buf + bytes, bytes_not_read); + if ( qd->is_finish_update ) { + qq_proc_cmd_server(gc, cmd, seq, buf + bytes, bytes_not_read); } return TRUE; } @@ -279,9 +279,17 @@ return TRUE; } + if (qq_trans_is_server(trans)) { + if ( qd->is_finish_update ) { + qq_proc_cmd_server(gc, cmd, seq, buf + bytes, bytes_not_read); + } + return TRUE; + } + update_class = qq_trans_get_class(trans); ship32 = qq_trans_get_ship(trans); + prev_update_status = qd->is_finish_update; switch (cmd) { case QQ_CMD_TOKEN: if (qq_process_token_reply(gc, buf + bytes, bytes_not_read) == QQ_TOKEN_REPLY_OK) { @@ -289,7 +297,7 @@ } break; case QQ_CMD_LOGIN: - qq_proc_login_cmd(gc, buf + bytes, bytes_not_read); + qq_proc_cmd_login(gc, buf + bytes, bytes_not_read); /* check is redirect or not, and do it now */ if (qd->redirect_ip.s_addr != 0) { if (qd->check_watcher > 0) { @@ -308,13 +316,18 @@ purple_debug_info("QQ", "%s (0x%02X) for room %d, len %d\n", qq_get_room_cmd_desc(room_cmd), room_cmd, room_id, buf_len); #endif - qq_proc_room_cmd(gc, seq, room_cmd, room_id, buf + bytes, bytes_not_read, update_class, ship32); + qq_proc_room_cmd_reply(gc, seq, room_cmd, room_id, buf + bytes, bytes_not_read, update_class, ship32); break; default: - qq_proc_client_cmd(gc, cmd, seq, buf + bytes, bytes_not_read, update_class, ship32); + qq_proc_cmd_reply(gc, cmd, seq, buf + bytes, bytes_not_read, update_class, ship32); break; } + if (prev_update_status != qd->is_finish_update && qd->is_finish_update == TRUE) { + /* is_login, but we have packets before login */ + qq_trans_process_before_login(gc); + return TRUE; + } return TRUE; } @@ -671,6 +684,7 @@ qd->send_seq = rand() & 0xffff; qd->is_login = FALSE; + qd->is_finish_update = FALSE; qd->channel = 1; qd->uid = strtol(purple_account_get_username(purple_connection_get_account(gc)), NULL, 10); @@ -739,140 +753,6 @@ do_request_token( gc ); } -#ifndef purple_proxy_connect_udp -static void udp_can_write(gpointer data, gint source, PurpleInputCondition cond) -{ - PurpleConnection *gc; - qq_data *qd; - socklen_t len; - int error=0, ret; - - gc = (PurpleConnection *) data; - g_return_if_fail(gc != NULL && gc->proto_data != NULL); - - qd = (qq_data *) gc->proto_data; - - - purple_debug_info("proxy", "Connected.\n"); - - /* - * getsockopt after a non-blocking connect returns -1 if something is - * really messed up (bad descriptor, usually). Otherwise, it returns 0 and - * error holds what connect would have returned if it blocked until now. - * Thus, error == 0 is success, error == EINPROGRESS means "try again", - * and anything else is a real error. - * - * (error == EINPROGRESS can happen after a select because the kernel can - * be overly optimistic sometimes. select is just a hint that you might be - * able to do something.) - */ - len = sizeof(error); - ret = getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len); - if (ret == 0 && error == EINPROGRESS) - return; /* we'll be called again later */ - - purple_input_remove(qd->udp_can_write_handler); - qd->udp_can_write_handler = 0; - if (ret < 0 || error != 0) { - if(ret != 0) - error = errno; - - close(source); - - purple_debug_error("proxy", "getsockopt SO_ERROR check: %s\n", g_strerror(error)); - - connect_cb(gc, -1, _("Unable to connect")); - return; - } - - connect_cb(gc, source, NULL); -} - -static void udp_host_resolved(GSList *hosts, gpointer data, const char *error_message) { - PurpleConnection *gc; - qq_data *qd; - struct sockaddr server_addr; - int addr_size; - gint fd = -1; - int flags; - - gc = (PurpleConnection *) data; - g_return_if_fail(gc != NULL && gc->proto_data != NULL); - - qd = (qq_data *) gc->proto_data; - - /* udp_query_data must be set as NULL. - * Otherwise purple_dnsquery_destroy in qq_disconnect cause glib double free error */ - qd->udp_query_data = NULL; - - if (!hosts || !hosts->data) { - purple_connection_error_reason(gc, - PURPLE_CONNECTION_ERROR_NETWORK_ERROR, - _("Couldn't resolve host")); - return; - } - - addr_size = GPOINTER_TO_INT(hosts->data); - hosts = g_slist_remove(hosts, hosts->data); - memcpy(&server_addr, hosts->data, addr_size); - g_free(hosts->data); - - hosts = g_slist_remove(hosts, hosts->data); - while(hosts) { - hosts = g_slist_remove(hosts, hosts->data); - g_free(hosts->data); - hosts = g_slist_remove(hosts, hosts->data); - } - - fd = socket(PF_INET, SOCK_DGRAM, 0); - if (fd < 0) { - purple_debug_error("QQ", - "Unable to create socket: %s\n", g_strerror(errno)); - return; - } - - /* we use non-blocking mode to speed up connection */ - flags = fcntl(fd, F_GETFL); - fcntl(fd, F_SETFL, flags | O_NONBLOCK); - - /* From Unix-socket-FAQ: http://www.faqs.org/faqs/unix-faq/socket/ - * - * If a UDP socket is unconnected, which is the normal state after a - * bind() call, then send() or write() are not allowed, since no - * destination is available; only sendto() can be used to send data. - * - * Calling connect() on the socket simply records the specified address - * and port number as being the desired communications partner. That - * means that send() or write() are now allowed; they use the destination - * address and port given on the connect call as the destination of packets. - */ - if (connect(fd, &server_addr, addr_size) >= 0) { - purple_debug_info("QQ", "Connected.\n"); - flags = fcntl(fd, F_GETFL); - fcntl(fd, F_SETFL, flags & ~O_NONBLOCK); - connect_cb(gc, fd, NULL); - return; - } - - /* [EINPROGRESS] - * The socket is marked as non-blocking and the connection cannot be - * completed immediately. It is possible to select for completion by - * selecting the socket for writing. - * [EINTR] - * A signal interrupted the call. - * The connection is established asynchronously. - */ - if ((errno == EINPROGRESS) || (errno == EINTR)) { - purple_debug_warning( "QQ", "Connect in asynchronous mode.\n"); - qd->udp_can_write_handler = purple_input_add(fd, PURPLE_INPUT_WRITE, udp_can_write, gc); - return; - } - - purple_debug_error("QQ", "Connection failed: %s\n", g_strerror(errno)); - close(fd); -} -#endif - gboolean connect_to_server(PurpleConnection *gc, gchar *server, gint port) { PurpleAccount *account ; @@ -899,37 +779,11 @@ purple_proxy_connect_cancel(qd->conn_data); qd->conn_data = NULL; } - -#ifdef purple_proxy_connect_udp - if (qd->use_tcp) { - qd->conn_data = purple_proxy_connect(gc, account, server, port, connect_cb, gc); - } else { - qd->conn_data = purple_proxy_connect_udp(gc, account, server, port, connect_cb, gc); - } + qd->conn_data = purple_proxy_connect(gc, account, server, port, connect_cb, gc); if ( qd->conn_data == NULL ) { purple_debug_error("QQ", _("Couldn't create socket")); return FALSE; } -#else - /* QQ connection via UDP/TCP. - * Now use Purple proxy function to provide TCP proxy support, - * and qq_udp_proxy.c to add UDP proxy support (thanks henry) */ - if(qd->use_tcp) { - qd->conn_data = purple_proxy_connect(gc, account, server, port, connect_cb, gc); - if ( qd->conn_data == NULL ) { - purple_debug_error("QQ", "Unable to connect."); - return FALSE; - } - return TRUE; - } - - purple_debug_info("QQ", "UDP Connect to %s:%d\n", server, port); - qd->udp_query_data = purple_dnsquery_a(server, port, udp_host_resolved, gc); - if ( qd->udp_query_data == NULL ) { - purple_debug_error("QQ", "Could not resolve hostname"); - return FALSE; - } -#endif return TRUE; } @@ -961,17 +815,6 @@ purple_proxy_connect_cancel(qd->conn_data); qd->conn_data = NULL; } -#ifndef purple_proxy_connect_udp - if (qd->udp_can_write_handler) { - purple_input_remove(qd->udp_can_write_handler); - qd->udp_can_write_handler = 0; - } - if (qd->udp_query_data != NULL) { - purple_debug_info("QQ", "destroy udp_query_data\n"); - purple_dnsquery_destroy(qd->udp_query_data); - qd->udp_query_data = NULL; - } -#endif connection_free_all(qd); qd->fd = -1;