# HG changeset patch # User Elliott Sales de Andrade # Date 1244176073 0 # Node ID b58672890b3f61660ccc8a408d1148090b954f8a # Parent 2ab648c328cc3e4228fcd5e41487176f42999098# Parent 005d20d58ac75496459010484c3f46b7b6722d8b merge of '051b51aa2424e978f16c10511f7a4e0f45c7c5d3' and '69b3b10f3cd5853b74cace5f7247f384555cbbff' diff -r 005d20d58ac7 -r b58672890b3f ChangeLog.API --- a/ChangeLog.API Fri Jun 05 04:13:10 2009 +0000 +++ b/ChangeLog.API Fri Jun 05 04:27:53 2009 +0000 @@ -16,9 +16,6 @@ * blist-node-added and blist-node-removed signals (see blist-signals.dox) * Jabber plugin signals (see jabber-signals.dox) - * Plugins may now emit the jabber-sending-xmlnode signal in order - to send stanzas; this method is preferred to the prpl send_raw - function as other plugins listening to the signal see them. * purple_buddy_destroy * purple_buddy_get_protocol_data * purple_buddy_set_protocol_data @@ -42,6 +39,7 @@ * purple_network_set_turn_server * purple_network_get_stun_ip * purple_network_get_turn_ip + * purple_proxy_connect_udp * purple_prpl_get_media_caps * purple_prpl_got_account_actions * purple_prpl_initiate_media @@ -60,6 +58,13 @@ which was completely non-deterministic. If you want to remove the attribute with no namespace, then use NULL with xmlnode_remove_with_namespace. + * Plugins may now emit the jabber-sending-xmlnode signal in order + to send stanzas; this method is preferred to the prpl send_raw + function as other plugins listening to the signal see them. + * The conversation-updated signal with a PURPLE_CONV_UPDATE_TYPING + update type is emitted when receiving an IM. Previously, the + typing state was modified (and the buddy-typing-stopped signal + emitted), but this signal was not emitted. Deprecated: * buddy-added and buddy-removed blist signals diff -r 005d20d58ac7 -r b58672890b3f libpurple/conversation.c --- a/libpurple/conversation.c Fri Jun 05 04:13:10 2009 +0000 +++ b/libpurple/conversation.c Fri Jun 05 04:27:53 2009 +0000 @@ -55,7 +55,6 @@ im = PURPLE_CONV_IM(c); purple_conv_im_set_typing_state(im, PURPLE_NOT_TYPING); - purple_conv_im_update_typing(im); purple_conv_im_stop_typing_timeout(im); return FALSE; @@ -1050,6 +1049,8 @@ "buddy-typing-stopped", im->conv->account, im->conv->name); break; } + + purple_conv_im_update_typing(im); } } diff -r 005d20d58ac7 -r b58672890b3f libpurple/plugins/psychic.c --- a/libpurple/plugins/psychic.c Fri Jun 05 04:13:10 2009 +0000 +++ b/libpurple/plugins/psychic.c Fri Jun 05 04:27:53 2009 +0000 @@ -74,6 +74,7 @@ time(NULL)); } + /* Necessary because we may be creating a new conversation window. */ purple_conv_im_set_typing_state(PURPLE_CONV_IM(gconv), PURPLE_TYPING); } } diff -r 005d20d58ac7 -r b58672890b3f libpurple/proxy.c --- a/libpurple/proxy.c Fri Jun 05 04:13:10 2009 +0000 +++ b/libpurple/proxy.c Fri Jun 05 04:27:53 2009 +0000 @@ -47,6 +47,7 @@ gchar *host; int port; int fd; + int socket_type; guint inpa; PurpleProxyInfo *gpi; PurpleDnsQueryData *query_data; @@ -676,6 +677,68 @@ } static void +proxy_connect_udp_none(PurpleProxyConnectData *connect_data, struct sockaddr *addr, socklen_t addrlen) +{ + int flags; + + purple_debug_info("proxy", "UDP Connecting to %s:%d with no proxy\n", + connect_data->host, connect_data->port); + + connect_data->fd = socket(addr->sa_family, SOCK_DGRAM, 0); + if (connect_data->fd < 0) + { + purple_proxy_connect_data_disconnect_formatted(connect_data, + _("Unable to create socket:\n%s"), g_strerror(errno)); + return; + } + + flags = fcntl(connect_data->fd, F_GETFL); + fcntl(connect_data->fd, F_SETFL, flags | O_NONBLOCK); +#ifndef _WIN32 + fcntl(connect_data->fd, F_SETFD, FD_CLOEXEC); +#endif + + if (connect(connect_data->fd, addr, addrlen) != 0) + { + if ((errno == EINPROGRESS) || (errno == EINTR)) + { + purple_debug_info("proxy", "UDP Connection in progress\n"); + connect_data->inpa = purple_input_add(connect_data->fd, + PURPLE_INPUT_WRITE, socket_ready_cb, connect_data); + } + else + { + purple_proxy_connect_data_disconnect(connect_data, g_strerror(errno)); + } + } + else + { + /* + * The connection happened IMMEDIATELY... strange, but whatever. + */ + int error = ETIMEDOUT; + int ret; + + purple_debug_info("proxy", "UDP Connected immediately.\n"); + + ret = purple_input_get_error(connect_data->fd, &error); + if ((ret != 0) || (error != 0)) + { + if (ret != 0) + error = errno; + purple_proxy_connect_data_disconnect(connect_data, g_strerror(error)); + return; + } + + /* + * We want to call the "connected" callback eventually, but we + * don't want to call it before we return, just in case. + */ + purple_timeout_add(10, clean_connect, connect_data); + } +} + +static void proxy_connect_none(PurpleProxyConnectData *connect_data, struct sockaddr *addr, socklen_t addrlen) { int flags; @@ -2042,6 +2105,12 @@ #endif purple_debug_info("proxy", "Attempting connection to %s\n", ipaddr); + if (connect_data->socket_type == SOCK_DGRAM) { + proxy_connect_udp_none(connect_data, addr, addrlen); + g_free(addr); + return; + } + switch (purple_proxy_info_get_type(connect_data->gpi)) { case PURPLE_PROXY_NONE: proxy_connect_none(connect_data, addr, addrlen); @@ -2193,6 +2262,7 @@ connect_data = g_new0(PurpleProxyConnectData, 1); connect_data->fd = -1; + connect_data->socket_type = SOCK_STREAM; connect_data->handle = handle; connect_data->connect_cb = connect_cb; connect_data->data = data; @@ -2243,6 +2313,71 @@ return connect_data; } +PurpleProxyConnectData * +purple_proxy_connect_udp(void *handle, PurpleAccount *account, + const char *host, int port, + PurpleProxyConnectFunction connect_cb, gpointer data) +{ + const char *connecthost = host; + int connectport = port; + PurpleProxyConnectData *connect_data; + + g_return_val_if_fail(host != NULL, NULL); + g_return_val_if_fail(port > 0, NULL); + g_return_val_if_fail(connect_cb != NULL, NULL); + + connect_data = g_new0(PurpleProxyConnectData, 1); + connect_data->fd = -1; + connect_data->socket_type = SOCK_DGRAM; + connect_data->handle = handle; + connect_data->connect_cb = connect_cb; + connect_data->data = data; + connect_data->host = g_strdup(host); + connect_data->port = port; + connect_data->gpi = purple_proxy_get_setup(account); + + if ((purple_proxy_info_get_type(connect_data->gpi) != PURPLE_PROXY_NONE) && + (purple_proxy_info_get_host(connect_data->gpi) == NULL || + purple_proxy_info_get_port(connect_data->gpi) <= 0)) { + + purple_notify_error(NULL, NULL, _("Invalid proxy settings"), _("Either the host name or port number specified for your given proxy type is invalid.")); + purple_proxy_connect_data_destroy(connect_data); + return NULL; + } + + switch (purple_proxy_info_get_type(connect_data->gpi)) + { + case PURPLE_PROXY_NONE: + break; + + case PURPLE_PROXY_HTTP: + case PURPLE_PROXY_SOCKS4: + case PURPLE_PROXY_SOCKS5: + case PURPLE_PROXY_USE_ENVVAR: + purple_debug_info("proxy", "Ignoring Proxy type (%d) for UDP.\n", + purple_proxy_info_get_type(connect_data->gpi)); + break; + + default: + purple_debug_error("proxy", "Invalid Proxy type (%d) specified.\n", + purple_proxy_info_get_type(connect_data->gpi)); + purple_proxy_connect_data_destroy(connect_data); + return NULL; + } + + connect_data->query_data = purple_dnsquery_a(connecthost, + connectport, connection_host_resolved, connect_data); + if (connect_data->query_data == NULL) + { + purple_proxy_connect_data_destroy(connect_data); + return NULL; + } + + handles = g_slist_prepend(handles, connect_data); + + return connect_data; +} + /* * Combine some of this code with purple_proxy_connect() */ @@ -2260,6 +2395,7 @@ connect_data = g_new0(PurpleProxyConnectData, 1); connect_data->fd = -1; + connect_data->socket_type = SOCK_STREAM; connect_data->handle = handle; connect_data->connect_cb = connect_cb; connect_data->data = data; diff -r 005d20d58ac7 -r b58672890b3f libpurple/proxy.h --- a/libpurple/proxy.h Fri Jun 05 04:13:10 2009 +0000 +++ b/libpurple/proxy.h Fri Jun 05 04:27:53 2009 +0000 @@ -257,6 +257,35 @@ PurpleProxyConnectFunction connect_cb, gpointer data); /** + * Makes a connection to the specified host and port. Note that this + * function name can be misleading--although it is called "proxy + * connect," it is used for establishing any outgoing UDP connection, + * whether through a proxy or not. + * + * @param handle A handle that should be associated with this + * connection attempt. The handle can be used + * to cancel the connection attempt using the + * purple_proxy_connect_cancel_with_handle() + * function. + * @param account The account making the connection. + * @param host The destination host. + * @param port The destination port. + * @param connect_cb The function to call when the connection is + * established. If the connection failed then + * fd will be -1 and error message will be set + * to something descriptive (hopefully). + * @param data User-defined data. + * + * @return NULL if there was an error, or a reference to an + * opaque data structure that can be used to cancel + * the pending connection, if needed. + */ +PurpleProxyConnectData *purple_proxy_connect_udp(void *handle, + PurpleAccount *account, + const char *host, int port, + PurpleProxyConnectFunction connect_cb, gpointer data); + +/** * Makes a connection through a SOCKS5 proxy. * * @param handle A handle that should be associated with this diff -r 005d20d58ac7 -r b58672890b3f libpurple/server.c --- a/libpurple/server.c Fri Jun 05 04:13:10 2009 +0000 +++ b/libpurple/server.c Fri Jun 05 04:27:53 2009 +0000 @@ -728,7 +728,6 @@ im = PURPLE_CONV_IM(conv); purple_conv_im_set_typing_state(im, state); - purple_conv_im_update_typing(im); } else { switch (state) { @@ -766,7 +765,6 @@ purple_conv_im_stop_typing_timeout(im); purple_conv_im_set_typing_state(im, PURPLE_NOT_TYPING); - purple_conv_im_update_typing(im); } else { diff -r 005d20d58ac7 -r b58672890b3f pidgin/plugins/disco/xmppdisco.c --- a/pidgin/plugins/disco/xmppdisco.c Fri Jun 05 04:13:10 2009 +0000 +++ b/pidgin/plugins/disco/xmppdisco.c Fri Jun 05 04:27:53 2009 +0000 @@ -18,13 +18,15 @@ */ /* TODO list (a little bit of a brain dump): - * Support more actions than "register" and "add" based on context. - - Subscribe to pubsub nodes (just...because?) + * Support more actions than "register" and "add" based on context. + - Subscribe to pubsub nodes (just...because?) - Execute ad-hoc commands - Change 'Register' to 'Unregister' if we're registered? - Administer MUCs - * See if we can better handle the ad-hoc commands that ejabberd returns - when disco'ing a server as an administrator: + * Enumerate pubsub node contents. + - PEP too? (useful development tool at times) + * See if we can better handle the ad-hoc commands that ejabberd returns + when disco'ing a server as an administrator: from disco#items: disco#info: