pidgin.vv.yahoo.voice: bad95bf7: Initial commit of Yahoo Voice code. It c...
maiku at pidgin.im
maiku at pidgin.im
Wed Aug 19 22:10:38 EDT 2009
-----------------------------------------------------------------
Revision: bad95bf79c54addda84101885ba9fc4b2f17c12d
Ancestor: 68bb82df03e74d8e33d5c334880a9b5bbab6a5d8
Author: maiku at pidgin.im
Date: 2009-08-20T02:04:54
Branch: im.pidgin.pidgin.vv.yahoo.voice
URL: http://d.pidgin.im/viewmtn/revision/info/bad95bf79c54addda84101885ba9fc4b2f17c12d
Added files:
libpurple/protocols/yahoo/yahoo_sip.c
libpurple/protocols/yahoo/yahoo_sip.h
Modified files:
configure.ac libpurple/protocols/yahoo/Makefile.am
libpurple/protocols/yahoo/libymsg.c
libpurple/protocols/yahoo/libymsg.h
ChangeLog:
Initial commit of Yahoo Voice code. It connects to and disconnects from the
Yahoo SIP server when connecting to and disconnecting from a Yahoo account.
libsofia-sip-ua and libsofia-sip-ua-glib are required to run this.
-------------- next part --------------
============================================================
--- libpurple/protocols/yahoo/yahoo_sip.c e7371b3954a1b79de94601ab7b89f2bae32a39dc
+++ libpurple/protocols/yahoo/yahoo_sip.c e7371b3954a1b79de94601ab7b89f2bae32a39dc
@@ -0,0 +1,222 @@
+/**
+ * @file yahoo_sip.c The Yahoo! protocol plugin SIP functions
+ *
+ * purple
+ *
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+ */
+
+#include "internal.h"
+
+#include "cipher.h"
+#include "debug.h"
+
+#include "yahoo_sip.h"
+#include "libymsg.h"
+
+#include <glib.h>
+#include <sofia-sip/nua.h>
+#include <sofia-sip/su_glib.h>
+#include <sofia-sip/sip_header.h>
+
+/* This is the y64 alphabet... it's like base64, but has a . and a _ */
+static const char base64digits[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789._";
+
+/* This is taken from Sylpheed by Hiroyuki Yamamoto. We have our own tobase64 function
+ * in util.c, but it has a bug I don't feel like finding right now ;) */
+static void to_y64(char *out, const unsigned char *in, gsize inlen)
+ /* raw bytes in quasi-big-endian order to base 64 string (NUL-terminated) */
+{
+ for (; inlen >= 3; inlen -= 3)
+ {
+ *out++ = base64digits[in[0] >> 2];
+ *out++ = base64digits[((in[0] << 4) & 0x30) | (in[1] >> 4)];
+ *out++ = base64digits[((in[1] << 2) & 0x3c) | (in[2] >> 6)];
+ *out++ = base64digits[in[2] & 0x3f];
+ in += 3;
+ }
+ if (inlen > 0)
+ {
+ unsigned char fragment;
+
+ *out++ = base64digits[in[0] >> 2];
+ fragment = (in[0] << 4) & 0x30;
+ if (inlen > 1)
+ fragment |= in[1] >> 4;
+ *out++ = base64digits[fragment];
+ *out++ = (inlen < 2) ? '-' : base64digits[(in[1] << 2) & 0x3c];
+ *out++ = '-';
+ }
+ *out = '\0';
+}
+
+static gboolean
+send_yahooref(gpointer nh)
+{
+ nua_method(nh, NUTAG_METHOD("YAHOOREF"), TAG_END());
+ return TRUE;
+}
+
+static void
+event_callback(nua_event_t event, int status, const gchar *phrase, nua_t *nua,
+ nua_magic_t *magic, nua_handle_t *nh, nua_hmagic_t *hmagic,
+ const sip_t *sip, tagi_t tags[])
+{
+ purple_debug_info("yahoo", "sofia-sip: event %s status %d %s\n",
+ nua_event_name(event), status, phrase);
+ if (event == nua_r_register && status == 401) {
+ PurpleAccount *account = magic;
+ PurpleConnection *pc = purple_account_get_connection(account);
+ YahooData *yd = pc->proto_data;
+ const sip_www_authenticate_t *wa = sip->sip_www_authenticate;
+ const gchar *method = NULL, *realm = NULL, *nonce = NULL;
+ gchar *auth, *cookie;
+ PurpleCipher *cipher;
+ PurpleCipherContext *context;
+ gchar *to_hash, response[25];
+ guchar digest[16];
+
+ if (!wa) {
+ purple_debug_error("yahoo", "sip www authenticate "
+ "structure is NULL\n");
+ return;
+ }
+
+ realm = msg_params_find(wa->au_params, "realm=");
+ method = wa->au_scheme;
+ nonce = msg_params_find(wa->au_params, "nonce=");
+ if (!realm || !method || !nonce) {
+ purple_debug_error("yahoo", "sip: unable to retrieve "
+ "authentication parameters\n");
+ return;
+ }
+
+ cipher = purple_ciphers_find_cipher("md5");
+ context = purple_cipher_context_new(cipher, NULL);
+ to_hash = g_strdup_printf("%s\"%s\"", yd->cookie_crumb, nonce);
+ purple_cipher_context_append(context, (const guchar*)to_hash,
+ strlen(to_hash));
+ g_free(to_hash);
+ purple_cipher_context_digest(context, sizeof(digest),
+ digest, NULL);
+ purple_cipher_context_destroy(context);
+ to_y64(response, digest, 16);
+
+ auth = g_strdup_printf("%s:%s:%s:%s", method, realm,
+ purple_account_get_username(account),
+ purple_connection_get_password(pc));
+ /*
+ * Should this be used instead?
+ * "Y-Cookie: Y=%s; path=/; domain=.yahoo.com; T=%s; path=/;"
+ * " domain=.yahoo.com; AT=2; CRUMB=%s"
+ */
+ cookie = g_strdup_printf("Y-Cookie: Y=%s; T=%s; AT=2; CRUMB=%s",
+ yd->cookie_y, yd->cookie_t, response);
+
+ nua_authenticate(nh, NUTAG_AUTH(auth),
+ SIPTAG_HEADER_STR(cookie),
+ SIPTAG_HEADER_STR("Y-User-Agent: intl=us; "
+ "os-version=w-2-5-1; internet-connection=lan; "
+ "cpu-speed=2390; pstn-call-enable=true; "
+ "appid=9.0.0.2034"),
+ TAG_END());
+
+ g_free(auth);
+ g_free(cookie);
+ } else if (event == nua_r_register && status == 200) {
+ nua_subscribe(nh,
+ SIPTAG_EVENT_STR("billing"),
+ TAG_END());
+ purple_timeout_add_seconds(60, send_yahooref, nh);
+ } else if (event == nua_r_unregister && status == 200) {
+ nua_shutdown(nua);
+ } else if (event == nua_r_shutdown && status == 200) {
+ nua_destroy(nua);
+ }
+}
+
+void
+yahoo_sip_init(PurpleAccount *account)
+{
+ PurpleConnection *pc = purple_account_get_connection(account);
+ YahooData *yd = purple_connection_get_protocol_data(pc);
+ GSource *gsource;
+ su_root_t *sofia_event_loop;
+ su_timer_t *timer;
+ gchar *sip_str;
+
+ purple_debug_info("yahoo", "Starting Sofia-SIP\n");
+
+ sofia_event_loop = su_glib_root_create(NULL);
+
+ gsource = su_glib_root_gsource(sofia_event_loop);
+ g_source_attach(gsource, g_main_context_default());
+
+ timer = su_timer_create(su_root_task(sofia_event_loop), 200L);
+
+
+ yd->nua = nua_create(sofia_event_loop, event_callback, account,
+ NUTAG_URL("sip:*:*;transport=tcp"),
+ NUTAG_M_PARAMS("transport=tcp"),
+ NUTAG_MEDIA_ENABLE(1),
+#if 0
+ /*
+ * This is supposed to stop it from sending an OPTIONS
+ * message, but it doesn't...
+ */
+ NUTAG_OUTBOUND("no-options-keepalive"),
+ NUTAG_KEEPALIVE(0),
+#endif
+ TAG_END());
+
+ /* XXX: Use the real address here or resolve it */
+ sip_str = g_strdup_printf("sip:%s at 68.142.233.179:443;transport=tcp",
+ purple_url_encode(purple_account_get_username(account)));
+ yd->nh = nua_handle(yd->nua, NULL,
+ SIPTAG_TO_STR(sip_str),
+ TAG_END());
+ g_free(sip_str);
+
+ nua_register(yd->nh,
+#if 0
+ /* Possibly needed for actual invitations? */
+ NUTAG_M_DISPLAY("1"),
+ NUTAG_M_USERNAME("line-1"),
+ NUTAG_M_PARAMS("user=phone"),
+ NUTAG_M_FEATURES("audio"),
+ NUTAG_CALLEE_CAPS(0),
+#endif
+ TAG_END());
+}
+
+void
+yahoo_sip_uninit(PurpleAccount *account)
+{
+ PurpleConnection *pc = purple_account_get_connection(account);
+ YahooData *yd = purple_connection_get_protocol_data(pc);
+
+ /*
+ * XXX: These don't always finish when shutting down.
+ * I don't know if that's a problem or not...
+ */
+ if (nua_handle_has_registrations(yd->nh) == 1)
+ nua_unregister(yd->nh, TAG_NULL());
+ else
+ nua_shutdown(yd->nua);
+}
============================================================
--- libpurple/protocols/yahoo/yahoo_sip.h c0d485a2bc5210d9db0424c227a898f66475d1f7
+++ libpurple/protocols/yahoo/yahoo_sip.h c0d485a2bc5210d9db0424c227a898f66475d1f7
@@ -0,0 +1,33 @@
+/**
+ * @file yahoo_sip.h The Yahoo! protocol plugin SIP functions
+ *
+ * purple
+ *
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+ */
+
+#ifndef _YAHOO_SIP_H_
+#define _YAHOO_SIP_H_
+
+#include "account.h"
+
+void yahoo_sip_init(PurpleAccount *account);
+void yahoo_sip_uninit(PurpleAccount *account);
+
+#endif /* _YAHOO_SIP_H_ */
============================================================
--- configure.ac 25d35a51d820754c8e2468e3058657dcf4cd4c8b
+++ configure.ac c5324dfaaca8f124dd55bd725cf7716f87f913b9
@@ -797,6 +797,21 @@ if test "x$enable_vv" != "xno"; then
if test "x$enable_vv" != "xno"; then
if test "x$enable_gstreamer" != "xno" -a "x$enable_gstinterfaces" != "xno" -a "x$enable_farsight" != "xno"; then
AC_DEFINE(USE_VV, 1, [Use voice and video])
+ PKG_CHECK_MODULES(SOFIASIP, [sofia-sip-ua], [
+ AC_DEFINE(USE_SOFIASIP, 1, [Use Sofia-SIP for SIP voice and video])
+ AC_SUBST(SOFIASIP_CFLAGS)
+ AC_SUBST(SOFIASIP_LIBS)
+
+ PKG_CHECK_MODULES(SOFIASIPGLIB, [sofia-sip-ua-glib], [
+ AC_DEFINE(USE_SOFIASIPGLIB, 1, [Use GLib utils for Sofia-SIP for SIP voice and video])
+ AC_SUBST(SOFIASIPGLIB_CFLAGS)
+ AC_SUBST(SOFIASIPGLIB_LIBS)
+ ], [
+ enable_sofiasip="no"
+ ])
+ ], [
+ enable_sofiasip="no"
+ ])
else
enable_vv="no"
if test "x$force_vv" = "xyes"; then
============================================================
--- libpurple/protocols/yahoo/Makefile.am e9d9993f55ec5505a065b7892b98df4be11a6288
+++ libpurple/protocols/yahoo/Makefile.am e10f377addb9008955e3875562a763c4d6443d92
@@ -22,6 +22,8 @@ YAHOOSOURCES = \
yahoo_picture.c \
yahoo_picture.h \
yahoo_profile.c \
+ yahoo_sip.h \
+ yahoo_sip.c \
ycht.c \
ycht.h
@@ -43,7 +45,9 @@ libymsg_la_SOURCES = $(YAHOOSOURCES)
pkg_LTLIBRARIES = libymsg.la libyahoo.la libyahoojp.la
libymsg_la_SOURCES = $(YAHOOSOURCES)
-libymsg_la_LIBADD = $(GLIB_LIBS)
+libymsg_la_LIBADD = $(GLIB_LIBS) \
+ $(SOFIASIP_LIBS) \
+ $(SOFIASIPGLIB_LIBS)
libyahoo_la_SOURCES = libyahoo.c
libyahoo_la_LIBADD = libymsg.la
@@ -57,4 +61,6 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/libpurple \
-I$(top_builddir)/libpurple \
$(GLIB_CFLAGS) \
+ $(SOFIASIP_CFLAGS) \
+ $(SOFIASIPGLIB_CFLAGS) \
$(DEBUG_CFLAGS)
============================================================
--- libpurple/protocols/yahoo/libymsg.c e15c747098a033957affc608406029519a9efc6d
+++ libpurple/protocols/yahoo/libymsg.c 9a094aced8948ca727f018c2acb7802c09638aa3
@@ -49,6 +49,7 @@
#include "yahoo_friend.h"
#include "yahoo_packet.h"
#include "yahoo_picture.h"
+#include "yahoo_sip.h"
#include "ycht.h"
/* #define YAHOO_DEBUG */
@@ -742,6 +743,7 @@ static void yahoo_process_list(PurpleCon
}
/* Now that we've got the list, request aliases */
yahoo_fetch_aliases(gc);
+ yahoo_sip_init(account);
}
/* pkt_type is YAHOO_PKT_TYPE_SERVER if pkt arrives from yahoo server, YAHOO_PKT_TYPE_P2P if pkt arrives through p2p */
@@ -1676,7 +1678,6 @@ static void yahoo_auth16_stage2(PurpleUt
gchar **split_data = g_strsplit(ret_data, "\r\n", -1);
int totalelements = 0;
int response_no = -1;
- char *crumb = NULL;
char *crypt = NULL;
#if GLIB_CHECK_VERSION(2,6,0)
@@ -1686,7 +1687,7 @@ static void yahoo_auth16_stage2(PurpleUt
#endif
if (totalelements >= 4) {
response_no = strtol(split_data[0], NULL, 10);
- crumb = g_strdup(split_data[1] + strlen("crumb="));
+ yd->cookie_crumb = g_strdup(split_data[1] + strlen("crumb="));
yd->cookie_y = g_strdup(split_data[2] + strlen("Y="));
yd->cookie_t = g_strdup(split_data[3] + strlen("T="));
}
@@ -1711,7 +1712,7 @@ static void yahoo_auth16_stage2(PurpleUt
break;
default:
/* if we have everything we need, why not try to login irrespective of response */
- if((crumb != NULL) && (yd->cookie_y != NULL) && (yd->cookie_t != NULL)) {
+ if((yd->cookie_crumb != NULL) && (yd->cookie_y != NULL) && (yd->cookie_t != NULL)) {
try_login_on_error = TRUE;
break;
}
@@ -1730,10 +1731,9 @@ static void yahoo_auth16_stage2(PurpleUt
}
}
- crypt = g_strconcat(crumb, auth_data->seed, NULL);
+ crypt = g_strconcat(yd->cookie_crumb, auth_data->seed, NULL);
yahoo_auth16_stage3(gc, crypt);
g_free(crypt);
- g_free(crumb);
}
g_free(auth_data->seed);
g_free(auth_data);
@@ -3465,6 +3465,8 @@ void yahoo_close(PurpleConnection *gc) {
YahooData *yd = (YahooData *)gc->proto_data;
GSList *l;
+ yahoo_sip_uninit(purple_connection_get_account(gc));
+
if (gc->inpa)
purple_input_remove(gc->inpa);
@@ -3517,6 +3519,7 @@ void yahoo_close(PurpleConnection *gc) {
g_free(yd->cookie_y);
g_free(yd->cookie_t);
+ g_free(yd->cookie_crumb);
if (yd->txhandler)
purple_input_remove(yd->txhandler);
============================================================
--- libpurple/protocols/yahoo/libymsg.h 22e537c8bea812721238661dda7ebf4fe877a8dd
+++ libpurple/protocols/yahoo/libymsg.h f95356261bc098a01ea0d90e67f758fd05e39238
@@ -42,6 +42,7 @@
#define YAHOO_XFER_PORT 80
#define YAHOO_XFER_RELAY_HOST "relay.msg.yahoo.com"
#define YAHOO_XFER_RELAY_PORT 80
+#define YAHOO_SIP_HOST "voipa.sip.yahoo.com"
#define YAHOO_ROOMLIST_URL "http://insider.msg.yahoo.com/ycontent/"
#define YAHOO_ROOMLIST_LOCALE "us"
/* really we should get the list of servers from
@@ -149,6 +150,8 @@ struct _YchtConn;
};
struct _YchtConn;
+struct nua_s;
+struct nua_handle_s;
typedef struct _YahooPersonalDetails {
char *id;
@@ -204,6 +207,7 @@ typedef struct {
gsize auth_written;
char *cookie_y;
char *cookie_t;
+ char *cookie_crumb;
int session_id;
gboolean jp;
gboolean wm; /* connected w/ web messenger method */
@@ -239,6 +243,10 @@ typedef struct {
int yahoo_p2p_server_watcher;
GHashTable *sms_carrier; /* sms carrier data */
guint yahoo_p2p_server_timeout_handle;
+
+ /* SIP variables */
+ struct nua_s *nua;
+ struct nua_handle_s *nh;
} YahooData;
#define YAHOO_MAX_STATUS_MESSAGE_LENGTH (255)
More information about the Commits
mailing list