📄 peer.c
字号:
/* Cancel this timer. It'll be added again, if needed. */ return FALSE;}/** * Try to establish the given PeerConnection using a defined * sequence of steps. */voidpeer_connection_trynext(PeerConnection *conn){ PurpleAccount *account; account = purple_connection_get_account(conn->od->gc); /* * Close any remnants of a previous failed connection attempt. */ peer_connection_close(conn); /* * 1. Attempt to connect to the remote user using their verifiedip and clientip. * We try these at the same time and use whichever succeeds first, so we don't * have to wait for a timeout. */ if (!(conn->flags & PEER_CONNECTION_FLAG_TRIED_DIRECT) && (conn->verifiedip != NULL) && (conn->port != 0) && (!conn->use_proxy)) { conn->flags |= PEER_CONNECTION_FLAG_TRIED_DIRECT; if (conn->type == OSCAR_CAPABILITY_DIRECTIM) { gchar *tmp; PurpleConversation *conv; tmp = g_strdup_printf(_("Attempting to connect to %s:%hu."), conn->verifiedip, conn->port); conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, conn->sn); purple_conversation_write(conv, NULL, tmp, PURPLE_MESSAGE_SYSTEM, time(NULL)); g_free(tmp); } conn->verified_connect_data = purple_proxy_connect(NULL, account, conn->verifiedip, conn->port, peer_connection_verified_established_cb, conn); if ((conn->verifiedip == NULL) || strcmp(conn->verifiedip, conn->clientip)) { conn->client_connect_data = purple_proxy_connect(NULL, account, conn->clientip, conn->port, peer_connection_client_established_cb, conn); } if ((conn->verified_connect_data != NULL) || (conn->client_connect_data != NULL)) { /* Connecting... */ conn->connect_timeout_timer = purple_timeout_add(5000, peer_connection_tooktoolong, conn); return; } } /* * 2. Attempt to have the remote user connect to us (using both * our verifiedip and our clientip). */ if (!(conn->flags & PEER_CONNECTION_FLAG_TRIED_INCOMING) && (!conn->use_proxy)) { conn->flags |= PEER_CONNECTION_FLAG_TRIED_INCOMING; /* * Remote user is connecting to us, so we'll need to verify * that the user who connected is our friend. */ conn->flags |= PEER_CONNECTION_FLAG_IS_INCOMING; conn->listen_data = purple_network_listen_range(5190, 5290, SOCK_STREAM, peer_connection_establish_listener_cb, conn); if (conn->listen_data != NULL) { /* Opening listener socket... */ return; } } /* * 3. Attempt to have both users connect to an intermediate proxy * server. */ if (!(conn->flags & PEER_CONNECTION_FLAG_TRIED_PROXY)) { conn->flags |= PEER_CONNECTION_FLAG_TRIED_PROXY; /* * If we initiate the proxy connection, then the remote user * could be anyone, so we need to verify that the user who * connected is our friend. */ if (!conn->use_proxy) conn->flags |= PEER_CONNECTION_FLAG_IS_INCOMING; if (conn->type == OSCAR_CAPABILITY_DIRECTIM) { gchar *tmp; PurpleConversation *conv; tmp = g_strdup_printf(_("Attempting to connect via proxy server.")); conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, conn->sn); purple_conversation_write(conv, NULL, tmp, PURPLE_MESSAGE_SYSTEM, time(NULL)); g_free(tmp); } conn->verified_connect_data = purple_proxy_connect(NULL, account, (conn->proxyip != NULL) ? conn->proxyip : PEER_PROXY_SERVER, PEER_PROXY_PORT, peer_proxy_connection_established_cb, conn); if (conn->verified_connect_data != NULL) { /* Connecting... */ return; } } /* Give up! */ peer_connection_destroy(conn, OSCAR_DISCONNECT_COULD_NOT_CONNECT, NULL);}/** * Initiate a peer connection with someone. */voidpeer_connection_propose(OscarData *od, OscarCapability type, const char *sn){ PeerConnection *conn; if (type == OSCAR_CAPABILITY_DIRECTIM) { conn = peer_connection_find_by_type(od, sn, type); if (conn != NULL) { if (conn->ready) { PurpleAccount *account; PurpleConversation *conv; purple_debug_info("oscar", "Already have a direct IM " "session with %s.\n", sn); account = purple_connection_get_account(od->gc); conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, sn, account); if (conv != NULL) purple_conversation_present(conv); return; } /* Cancel the old connection and try again */ peer_connection_destroy(conn, OSCAR_DISCONNECT_RETRYING, NULL); } } conn = peer_connection_new(od, type, sn); conn->flags |= PEER_CONNECTION_FLAG_INITIATED_BY_ME; conn->flags |= PEER_CONNECTION_FLAG_APPROVED; aim_icbm_makecookie(conn->cookie); peer_connection_trynext(conn);}/** * Someone else wants to establish a peer connection with us, * and we said yes. */static voidpeer_connection_got_proposition_yes_cb(gpointer data, gint id){ PeerConnection *conn; conn = data; conn->flags |= PEER_CONNECTION_FLAG_APPROVED; peer_connection_trynext(conn);}/** * Someone else wants to establish a peer connection with us, * and we said no. * * "Well, one time my friend asked me if I wanted to play the * piccolo. But I said no." */static voidpeer_connection_got_proposition_no_cb(gpointer data, gint id){ PeerConnection *conn; conn = data; aim_im_denytransfer(conn->od, conn->sn, conn->cookie, AIM_TRANSFER_DENY_DECLINE); peer_connection_destroy(conn, OSCAR_DISCONNECT_LOCAL_CLOSED, NULL);}/** * Someone else wants to establish a peer connection with us. */voidpeer_connection_got_proposition(OscarData *od, const gchar *sn, const gchar *message, IcbmArgsCh2 *args){ PurpleConnection *gc; PurpleAccount *account; PeerConnection *conn; gchar *buf; gc = od->gc; account = purple_connection_get_account(gc); /* * If we have a connection with this same cookie then they are * probably just telling us they weren't able to connect to us * and we should try connecting to them, instead. Or they want * to go through a proxy. */ conn = peer_connection_find_by_cookie(od, sn, args->cookie); if ((conn != NULL) && (conn->type == args->type)) { purple_debug_info("oscar", "Remote user wants to try a " "different connection method\n"); g_free(conn->proxyip); g_free(conn->clientip); g_free(conn->verifiedip); if (args->use_proxy) conn->proxyip = g_strdup(args->proxyip); else conn->proxyip = NULL; conn->verifiedip = g_strdup(args->verifiedip); conn->clientip = g_strdup(args->clientip); conn->port = args->port; conn->use_proxy |= args->use_proxy; conn->lastrequestnumber++; peer_connection_trynext(conn); return; } /* If this is a direct IM, then close any existing session */ if (args->type == OSCAR_CAPABILITY_DIRECTIM) { conn = peer_connection_find_by_type(od, sn, args->type); if (conn != NULL) { /* Close the old direct IM and start a new one */ purple_debug_info("oscar", "Received new direct IM request " "from %s. Destroying old connection.\n", sn); peer_connection_destroy(conn, OSCAR_DISCONNECT_REMOTE_CLOSED, NULL); } } /* Check for proper arguments */ if (args->type == OSCAR_CAPABILITY_SENDFILE) { if ((args->info.sendfile.filename == NULL) || (args->info.sendfile.totsize == 0) || (args->info.sendfile.totfiles == 0)) { purple_debug_warning("oscar", "%s tried to send you a file with incomplete " "information.\n", sn); return; } } conn = peer_connection_new(od, args->type, sn); memcpy(conn->cookie, args->cookie, 8); if (args->use_proxy) conn->proxyip = g_strdup(args->proxyip); conn->clientip = g_strdup(args->clientip); conn->verifiedip = g_strdup(args->verifiedip); conn->port = args->port; conn->use_proxy |= args->use_proxy; conn->lastrequestnumber++; if (args->type == OSCAR_CAPABILITY_DIRECTIM) { buf = g_strdup_printf(_("%s has just asked to directly connect to %s"), sn, purple_account_get_username(account)); purple_request_action(conn, NULL, buf, _("This requires a direct connection between " "the two computers and is necessary for IM " "Images. Because your IP address will be " "revealed, this may be considered a privacy " "risk."), PURPLE_DEFAULT_ACTION_NONE, account, sn, NULL, conn, 2, _("_Connect"), G_CALLBACK(peer_connection_got_proposition_yes_cb), _("Cancel"), G_CALLBACK(peer_connection_got_proposition_no_cb)); } else if (args->type == OSCAR_CAPABILITY_SENDFILE) { gchar *filename; conn->xfer = purple_xfer_new(account, PURPLE_XFER_RECEIVE, sn); if (conn->xfer) { conn->xfer->data = conn; purple_xfer_ref(conn->xfer); purple_xfer_set_size(conn->xfer, args->info.sendfile.totsize); /* Set the file name */ if (g_utf8_validate(args->info.sendfile.filename, -1, NULL)) filename = g_strdup(args->info.sendfile.filename); else filename = purple_utf8_salvage(args->info.sendfile.filename); if (args->info.sendfile.subtype == AIM_OFT_SUBTYPE_SEND_DIR) { /* * If they are sending us a directory then the last character * of the file name will be an asterisk. We don't want to * save stuff to a directory named "*" so we remove the * asterisk from the file name. */ char *tmp = strrchr(filename, '\\'); if ((tmp != NULL) && (tmp[1] == '*')) tmp[0] = '\0'; } purple_xfer_set_filename(conn->xfer, filename); g_free(filename); /* * Set the message, unless this is the dummy message from an * ICQ client or an empty message from an AIM client. * TODO: Maybe we should strip HTML and then see if strlen>0? */ if ((message != NULL) && (g_ascii_strncasecmp(message, "<ICQ_COOL_FT>", 13) != 0) && (g_ascii_strcasecmp(message, "<HTML>") != 0)) { purple_xfer_set_message(conn->xfer, message); } /* Setup our I/O op functions */ purple_xfer_set_init_fnc(conn->xfer, peer_oft_recvcb_init); purple_xfer_set_end_fnc(conn->xfer, peer_oft_recvcb_end); purple_xfer_set_request_denied_fnc(conn->xfer, peer_oft_cb_generic_cancel); purple_xfer_set_cancel_recv_fnc(conn->xfer, peer_oft_cb_generic_cancel); purple_xfer_set_ack_fnc(conn->xfer, peer_oft_recvcb_ack_recv); /* Now perform the request */ purple_xfer_request(conn->xfer); } }}/*******************************************************************//* End code for establishing a peer connection *//*******************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -