pidgin.vv.msn.webcam: 1deb79e2: Initial commit of msn webcam code. Suppo...
maiku at pidgin.im
maiku at pidgin.im
Tue Aug 25 04:45:46 EDT 2009
-----------------------------------------------------------------
Revision: 1deb79e27c3967647d508217efaaa277fc229713
Ancestor: cf52f515f41f2668c92606c9ad852fb55460da9c
Author: maiku at pidgin.im
Date: 2009-08-25T08:42:33
Branch: im.pidgin.pidgin.vv.msn.webcam
URL: http://d.pidgin.im/viewmtn/revision/info/1deb79e27c3967647d508217efaaa277fc229713
Added files:
libpurple/protocols/msn/webcam.c
libpurple/protocols/msn/webcam.h
Modified files:
libpurple/protocols/msn/Makefile.am
libpurple/protocols/msn/Makefile.mingw
libpurple/protocols/msn/msn.c libpurple/protocols/msn/slp.c
libpurple/protocols/msn/slpcall.c
libpurple/protocols/msn/slpcall.h
libpurple/protocols/msn/slplink.c
ChangeLog:
Initial commit of msn webcam code. Supports initiating and requesting the
remote webcam only. It can't receive any invitations. It requires a
prerelease of gst-plugins-bad (0.10.14) and a version of Farsight2 with the
fsmsnconference plugin in order to work.
-------------- next part --------------
============================================================
--- libpurple/protocols/msn/webcam.c ce5a585a3998500ffd8859bcbb4f847fafed7faf
+++ libpurple/protocols/msn/webcam.c ce5a585a3998500ffd8859bcbb4f847fafed7faf
@@ -0,0 +1,536 @@
+/**
+ * @file webcam.c MSN Webcam 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 "webcam.h"
+
+#include "mediamanager.h"
+/*
+ * This one shouldn't be necessary, but fsmsnwebcam doesn't get external
+ * IP addresses correctly yet
+ */
+#include "network.h"
+
+#include "msn.h"
+#include "msnutils.h"
+#include "slp.h"
+#include "slpcall.h"
+#include "slpmsg.h"
+
+static void
+msn_webcam_session_init_cb(MsnSlpCall *slpcall)
+{
+ purple_debug_info("msn", "slpcall %p, session_id %ld\n",
+ slpcall, slpcall->session_id);
+}
+
+static void
+msn_webcam_completed_cb(MsnSlpCall *slpcall, const guchar *body,
+ gsize size)
+{
+ purple_debug_info("msn", "completed: size: %"
+ G_GSIZE_FORMAT " %s\n", size, body);
+}
+
+static void
+msn_webcam_end_cb(MsnSlpCall *slpcall, MsnSession *session)
+{
+ purple_debug_info("msn", "webcam end; slpcall wasted %s \n",
+ slpcall->wasted ? "TRUE" : "FALSE");
+ if (slpcall->media) {
+ purple_media_set_prpl_data(slpcall->media, NULL);
+ if (slpcall->wasted == TRUE)
+ purple_media_end(slpcall->media, NULL, NULL);
+ }
+}
+
+static void
+msn_webcam_codecs_changed_cb(PurpleMedia *media, gchar *sid,
+ gchar *name, gpointer *data)
+{
+ purple_debug_info("msn", "codecs changed - sid: %s name: %s\n", sid, name);
+}
+
+static void
+msn_webcam_state_changed_cb(PurpleMedia *media, PurpleMediaState state,
+ gchar *sid, gchar *name, MsnSlpCall *slpcall)
+{
+ purple_debug_info("msn", "state changed - state: %d sid: %s "
+ "name: %s\n", state, sid, name);
+ if (state == PURPLE_MEDIA_STATE_END) {
+ slpcall = purple_media_get_prpl_data(media);
+ if (!slpcall)
+ return;
+ slpcall->media = NULL;
+ if (purple_media_is_initiator(media, NULL, NULL) &&
+ slpcall->started == FALSE)
+ {
+ msn_slpcall_close(slpcall);
+ }
+ else
+ {
+ send_bye(slpcall, "application/x-msnmsgr-sessionclosebody");
+ msn_slplink_send_queued_slpmsgs(slpcall->slplink);
+ msn_slpcall_destroy(slpcall);
+ }
+ }
+}
+
+static void
+msn_webcam_stream_info_cb(PurpleMedia *media, PurpleMediaInfoType type,
+ gchar *sid, gchar *name, gboolean local, gpointer *data)
+{
+ purple_debug_info("msn", "stream-info: type: %d sid: %s name: %s local: %s\n",
+ type, sid, name, local ? "TRUE" : "FALSE");
+}
+
+static void
+msn_webcam_candidates_prepared_cb(PurpleMedia *media,
+ gchar *sid, gchar *name, gpointer *data)
+{
+ PurpleAccount *account;
+ PurpleConnection *pc;
+ MsnSession *session;
+ MsnSlpLink *slplink;
+ MsnSlpCall *slpcall;
+ GList *candidates;
+ const gchar *context = "{B8BE70DE-E2CA-4400-AE03-88FF85B9F4E8}";
+ gunichar2 *utf16_context;
+ gchar *base64_context;
+ glong written;
+
+ purple_debug_info("msn", "candidates prepared - sid: %s name: %s\n", sid, name);
+
+ account = purple_media_get_account(media);
+ pc = purple_account_get_connection(account);
+ session = pc->proto_data;
+ slplink = msn_session_get_slplink(session, name);
+ slpcall = msn_slpcall_new(slplink);
+
+ msn_slpcall_init(slpcall, MSN_SLPCALL_ANY);
+
+ slpcall->media = media;
+ slpcall->cb = msn_webcam_completed_cb;
+ slpcall->session_init_cb = msn_webcam_session_init_cb;
+ slpcall->end_cb = msn_webcam_end_cb;
+ slpcall->app_id = 4;
+ purple_media_set_prpl_data(media, slpcall);
+
+ g_signal_connect(G_OBJECT(media), "codecs-changed",
+ G_CALLBACK(msn_webcam_codecs_changed_cb), slpcall);
+ g_signal_connect(G_OBJECT(media), "state-changed",
+ G_CALLBACK(msn_webcam_state_changed_cb), slpcall);
+ g_signal_connect(G_OBJECT(media), "stream-info",
+ G_CALLBACK(msn_webcam_stream_info_cb), slpcall);
+
+ candidates = purple_media_get_local_candidates(media, sid, name);
+ if (candidates) {
+ PurpleMediaCandidate *candidate = candidates->data;
+ gchar *username = purple_media_candidate_get_username(candidate);
+ purple_debug_info("msn", "webcam session-id %s\n", username);
+ slpcall->session_id = atoi(username);
+ g_free(username);
+ } else {
+ purple_debug_error("msn", "Failed find candidates for msnwebcam\n");
+ }
+ g_list_free(candidates);
+
+ utf16_context = g_utf8_to_utf16(context, -1, NULL, &written, NULL);
+ base64_context = purple_base64_encode((guchar*)utf16_context,
+ written*sizeof(gunichar2));
+ g_free(utf16_context);
+ if (purple_media_get_session_type(media, sid) == PURPLE_MEDIA_SEND_VIDEO)
+ msn_slpcall_invite(slpcall, MSN_CAM_GUID, 4, base64_context);
+ if (purple_media_get_session_type(media, sid) == PURPLE_MEDIA_RECV_VIDEO)
+ msn_slpcall_invite(slpcall, MSN_CAM_REQUEST_GUID, 4, base64_context);
+ g_free(base64_context);
+}
+
+void
+msn_webcam_send_syn(MsnSlpCall *slpcall, const gchar *content)
+{
+ MsnSlpMessage *slpmsg;
+ gchar *body;
+ guint16 *r;
+
+ /*
+ * The SlpCall object has a different instance here,
+ * but aMSN doesn't include a SessionID in the SlpMsg
+ */
+#if 0
+ glong session_id = 0;
+ char *temp;
+ temp = get_token(content, "SessionID: ", "\r\n");
+ long session_id;
+ if (temp != NULL)
+ session_id = atoi(temp);
+ g_free(temp);
+#endif
+
+ GList *iter = purple_media_manager_get_media_by_account(
+ purple_media_manager_get(),
+ slpcall->slplink->session->account);
+ for (; iter; iter = g_list_delete_link(iter, iter)) {
+ MsnSlpCall *slpcall_media =
+ purple_media_get_prpl_data(iter->data);
+ if (slpcall_media && slpcall_media->id &&
+ !strcmp(slpcall_media->id, slpcall->id)) {
+ slpcall->session_id = slpcall_media->session_id;
+ slpcall->media = slpcall_media->media;
+ break;
+ }
+ }
+ g_list_free(iter);
+
+ body = g_memdup("\x80\x00\x00\x01\x08\x00\x08\x00\x00\x00"
+ "s\x00y\x00n\x00\x00\x00", 18);
+ r = (guint16*)(body+1);
+ *r = GINT16_TO_LE(rand() % 0xFFFF0000);
+
+ slpmsg = msn_slpmsg_new(slpcall->slplink);
+ slpmsg->slpcall = slpcall;
+
+ slpmsg->session_id = slpcall->session_id;
+ msn_slpmsg_set_body(slpmsg, body, 18);
+ g_free(body);
+ msn_slplink_queue_slpmsg(slpcall->slplink, slpmsg);
+}
+
+void
+msn_webcam_send_ack(MsnSlpLink *slplink, MsnSlpMessage *slpmsg)
+{
+ MsnSlpMessage *slpmsg2;
+ gchar *body = g_memdup("\x80\xea\00\x00\x08\x00\x08\x00\x00\0"
+ "a\0c\0k\x00\x00\x00", 18);
+ slpmsg2 = msn_slpmsg_new(slplink);
+ slpmsg2->slpcall = slpmsg->slpcall;
+ slpmsg2->session_id = slpmsg->session_id;
+ msn_slpmsg_set_body(slpmsg2, body, 18);
+ g_free(body);
+ msn_slplink_queue_slpmsg(slplink, slpmsg2);
+ purple_media_stream_info(slpmsg->slpcall->media,
+ PURPLE_MEDIA_INFO_ACCEPT, "msncam-send",
+ slplink->remote_user, FALSE);
+}
+
+void
+msn_webcam_send_xml(MsnSlpLink *slplink, MsnSlpMessage *slpmsg)
+{
+ MsnSlpMessage *slpmsg2;
+ PurpleMedia *media = slpmsg->slpcall->media;
+ GList *session_ids, *candidates = NULL;
+ xmlnode *node, *child, *tcp;
+ gchar *session_id = NULL, *rid = NULL, *port = NULL, *xml;
+ const gchar *public_ip = NULL;
+ gunichar2 *xmlutf;
+ guint count = 1;
+
+ glong written;
+ gchar *body;
+ guint32 *len;
+ gboolean is_producer = FALSE;
+
+ /* Get candidates */
+ session_ids = purple_media_get_session_ids(media);
+ if (session_ids->data != NULL) {
+ candidates = purple_media_get_local_candidates(media,
+ session_ids->data, slplink->remote_user);
+ is_producer = (strcmp(session_ids->data, "msncam-send") == 0);
+ }
+ g_list_free(session_ids);
+
+ if (candidates == NULL) {
+ purple_debug_error("msn", "Could not retrieve candidates "
+ "for msn webcam\n");
+ return;
+ } else if (g_list_length(candidates) >= 1) {
+ PurpleMediaCandidate *candidate = candidates->data;
+ port = g_strdup_printf("%d",
+ purple_media_candidate_get_port(candidate));
+ rid = purple_media_candidate_get_foundation(candidate);
+ }
+
+ session_id = g_strdup_printf("%lu", slpmsg->session_id);
+
+ /* Construct xml message */
+ node = xmlnode_new(is_producer ? "producer" : "viewer");
+ child = xmlnode_new_child(node, "version");
+ xmlnode_insert_data(child, "2.0", -1);
+ child = xmlnode_new_child(node, "rid");
+ xmlnode_insert_data(child, rid, -1);
+ child = xmlnode_new_child(node, "session");
+ xmlnode_insert_data(child, session_id, -1);
+
+ tcp = xmlnode_new_child(node, "tcp");
+ child = xmlnode_new_child(tcp, "tcpport");
+ xmlnode_insert_data(child, port, -1);
+ child = xmlnode_new_child(tcp, "tcplocalport");
+ xmlnode_insert_data(child, port, -1);
+ child = xmlnode_new_child(tcp, "tcpexternalport");
+ xmlnode_insert_data(child, port, -1);
+
+ public_ip = purple_network_get_my_ip(-1);
+ for (; candidates; candidates =
+ g_list_delete_link(candidates, candidates)) {
+ PurpleMediaCandidate *candidate = candidates->data;
+ gchar *ip = purple_media_candidate_get_ip(candidate);
+ gchar *name = g_strdup_printf("tcpipaddress%d", count);
+ child = xmlnode_new_child(tcp, name);
+ xmlnode_insert_data(child, ip, -1);
+
+ if (public_ip && !strcmp(ip, public_ip))
+ public_ip = NULL;
+
+ g_free(name);
+ g_free(ip);
+ ++count;
+ }
+ if (public_ip) {
+ /*
+ * This one shouldn't be necessary, but fsmsnwebcam doesn't
+ * get external IP addresses correctly yet
+ */
+ gchar *name = g_strdup_printf("tcpipaddress%d", count);
+ child = xmlnode_new_child(tcp, name);
+ xmlnode_insert_data(child, public_ip, -1);
+ g_free(name);
+ }
+
+ child = xmlnode_new_child(node, "codec");
+ child = xmlnode_new_child(node, "channelmode");
+ xmlnode_insert_data(child, "1", -1);
+ xml = xmlnode_to_str(node, NULL);
+ xmlnode_free(node);
+
+ g_free(session_id);
+ g_free(port);
+ g_free(rid);
+
+ xmlutf = g_utf8_to_utf16(xml, strlen(xml) + 1, NULL, &written, NULL);
+ g_free(xml);
+ written *= sizeof(gunichar2);
+
+ body = g_malloc(written + 10);
+ memcpy(body, "\x80\x00\x00\x00\x08\x00", 6);
+ len = (guint32*)(body+6);
+ *len = GUINT32_TO_LE((guint32)written);
+ memcpy(body + 10, xmlutf, written);
+ g_free(xmlutf);
+
+ slpmsg2 = msn_slpmsg_new(slplink);
+ slpmsg2->slpcall = slpmsg->slpcall;
+ slpmsg2->session_id = slpmsg->session_id;
+ msn_slpmsg_set_body(slpmsg2, body, written + 10);
+ g_free(body);
+ msn_slplink_queue_slpmsg(slplink, slpmsg2);
+}
+
+void
+msn_webcam_recv_xml(MsnSlpLink *slplink, MsnSlpMessage *slpmsg, const guchar *body, gsize body_len)
+{
+ MsnSlpMessage *slpmsg2;
+ glong bytes_written;
+ gchar *xml = g_utf16_to_utf8((const gunichar2*)body + 5,
+ body_len - 5, NULL, &bytes_written, NULL);
+ gchar *body_str;
+ gboolean is_producer = FALSE;
+
+ if (!strncmp(xml, "<producer>", 10))
+ is_producer = TRUE;
+
+ if (is_producer) {
+ GList *candidates = NULL;
+ guint port, local_port, external_port;
+ xmlnode *node, *childnode, *tcpnode;
+ gchar *rid, *session_id, *ip, *port_str;
+ guint count = 1;
+
+ node = xmlnode_from_str(xml, bytes_written);
+ childnode = xmlnode_get_child(node, "rid");
+ rid = xmlnode_get_data(childnode);
+ childnode = xmlnode_get_child(node, "session");
+ session_id = xmlnode_get_data(childnode);
+ tcpnode = xmlnode_get_child(node, "tcp");
+ childnode = xmlnode_get_child(tcpnode, "tcpport");
+ port_str = xmlnode_get_data(childnode);
+ port = port_str ? atoi(port_str) : -1;
+ g_free(port_str);
+ childnode = xmlnode_get_child(tcpnode, "tcplocalport");
+ port_str = xmlnode_get_data(childnode);
+ local_port = port_str ? atoi(port_str) : -1;
+ g_free(port_str);
+ childnode = xmlnode_get_child(tcpnode, "tcpexternalport");
+ port_str = xmlnode_get_data(childnode);
+ external_port = port_str ? atoi(port_str) : -1;
+ g_free(port_str);
+
+ if (rid == NULL || session_id == NULL || port == -1) {
+ purple_debug_error("msn", "Unable to parse webcam xml\n");
+ g_free(rid);
+ g_free(session_id);
+ return;
+ }
+
+ while (TRUE) {
+ gchar *name = g_strdup_printf("tcpipaddress%d", count);
+ ++count;
+ childnode = xmlnode_get_child(tcpnode, name);
+ g_free(name);
+ if (childnode == NULL)
+ break;
+ ip = xmlnode_get_data(childnode);
+ if (ip == NULL)
+ continue;
+
+ candidates = g_list_prepend(candidates,
+ purple_media_candidate_new(rid, 1,
+ PURPLE_MEDIA_CANDIDATE_TYPE_HOST,
+ PURPLE_MEDIA_NETWORK_PROTOCOL_TCP, ip, port));
+ g_object_set(candidates->data, "username", session_id, NULL);
+
+
+ if (local_port > 0) {
+ candidates = g_list_prepend(candidates,
+ purple_media_candidate_new(rid, 1,
+ PURPLE_MEDIA_CANDIDATE_TYPE_HOST,
+ PURPLE_MEDIA_NETWORK_PROTOCOL_TCP,
+ ip, local_port));
+ g_object_set(candidates->data, "username", session_id, NULL);
+ }
+ if (external_port > 0) {
+ candidates = g_list_prepend(candidates,
+ purple_media_candidate_new(rid, 1,
+ PURPLE_MEDIA_CANDIDATE_TYPE_HOST,
+ PURPLE_MEDIA_NETWORK_PROTOCOL_TCP,
+ ip, external_port));
+ g_object_set(candidates->data, "username", session_id, NULL);
+ }
+ g_free(ip);
+ }
+
+ g_free(rid);
+ g_free(session_id);
+ xmlnode_free(node);
+
+ candidates = g_list_reverse(candidates);
+ purple_media_add_remote_candidates(slpmsg->slpcall->media,
+ "msncam-recv", slplink->remote_user, candidates);
+ } else {
+ slpmsg2 = msn_slpmsg_new(slplink);
+ slpmsg2->slpcall = slpmsg->slpcall;
+ slpmsg2->session_id = slpmsg->session_id;
+ body_str = g_memdup(
+ "\x80\xec\x00\x03\x08\x00" /* magic string */
+ "\x16\0\0\0" /* length of following */
+ "r\0e\0c\0e\0i\0v\0e\0d\0V\0i\0e\0w\0e\0r\0D\0a\0t\0a\0\0\0", 48);
+ msn_slpmsg_set_body(slpmsg2, body_str, 48);
+ g_free(body_str);
+ msn_slplink_queue_slpmsg(slplink, slpmsg2);
+ }
+ g_free(xml);
+}
+
+void
+msn_webcam_process_msg(MsnSlpLink *slplink, MsnSlpMessage *slpmsg)
+{
+ const guchar *body = slpmsg->buffer;
+ gsize body_len = slpmsg->size;
+
+ if (body_len >= 18 && !memcmp(body + 10, "s\0y\0n\0", 6)) {
+ purple_debug_info("msn", "webcam: got syn %s\n", body + 10);
+ msn_webcam_send_ack(slplink, slpmsg);
+ } else if (body_len >= 18 && !memcmp(body + 10, "a\0c\0k\0", 6)) {
+ purple_debug_info("msn", "webcam: got ack\n");
+ msn_webcam_send_xml(slplink, slpmsg);
+ } else if (body_len >= 26 &&
+ (!memcmp(body + 10, "<\0v\0i\0e\0w\0e\0r\0>\0", 16) ||
+ !memcmp(body + 10, "<\0p\0r\0o\0d\0u\0c\0e\0r\0>\0", 20))) {
+ purple_debug_info("msn", "webcam: got xml\n");
+ msn_webcam_recv_xml(slplink, slpmsg, body, body_len);
+ }
+}
+
+void
+msn_webcam_recv(MsnSlpCall *slpcall)
+{
+ PurpleMedia *media;
+ media = purple_media_manager_create_media(purple_media_manager_get(),
+ slpcall->slplink->session->account,
+ "fsmsncamrecvconference",
+ slpcall->slplink->remote_user, FALSE);
+ purple_media_set_prpl_data(media, slpcall);
+
+ slpcall->media = media;
+ slpcall->cb = msn_webcam_completed_cb;
+ slpcall->end_cb = msn_webcam_end_cb;
+
+ /* connect callbacks */
+ g_signal_connect(G_OBJECT(media), "codecs-changed",
+ G_CALLBACK(msn_webcam_codecs_changed_cb), slpcall);
+ g_signal_connect(G_OBJECT(media), "state-changed",
+ G_CALLBACK(msn_webcam_state_changed_cb), slpcall);
+ g_signal_connect(G_OBJECT(media), "stream-info",
+ G_CALLBACK(msn_webcam_stream_info_cb), slpcall);
+
+ purple_media_add_stream(media, "msncam-send",
+ slpcall->slplink->remote_user,
+ PURPLE_MEDIA_RECV_VIDEO, FALSE, "", 0, NULL);
+}
+
+gboolean
+msn_initiate_media(PurpleAccount *account, const gchar *who, PurpleMediaSessionType type)
+{
+ PurpleMedia *media;
+
+ /* Hack until there are menu entries for this */
+ if (type == PURPLE_MEDIA_VIDEO)
+ type = PURPLE_MEDIA_SEND_VIDEO;
+ if (type == PURPLE_MEDIA_AUDIO)
+ type = PURPLE_MEDIA_RECV_VIDEO;
+
+ if (type & PURPLE_MEDIA_SEND_VIDEO) {
+ media = purple_media_manager_create_media(purple_media_manager_get(),
+ account, "fsmsncamsendconference", who, TRUE);
+ g_signal_connect(G_OBJECT(media), "candidates-prepared",
+ G_CALLBACK(msn_webcam_candidates_prepared_cb), NULL);
+ purple_media_add_stream(media, "msncam-send", who,
+ PURPLE_MEDIA_SEND_VIDEO, TRUE, "", 0, NULL);
+ }
+ if (type & PURPLE_MEDIA_RECV_VIDEO) {
+ media = purple_media_manager_create_media(purple_media_manager_get(),
+ account, "fsmsncamrecvconference", who, TRUE);
+ g_signal_connect(G_OBJECT(media), "candidates-prepared",
+ G_CALLBACK(msn_webcam_candidates_prepared_cb), NULL);
+ purple_media_add_stream(media, "msncam-recv", who,
+ PURPLE_MEDIA_RECV_VIDEO, TRUE, "", 0, NULL);
+ }
+
+ return TRUE;
+}
+
+PurpleMediaCaps
+msn_get_media_caps(PurpleAccount *account, const gchar *who)
+{
+ return PURPLE_MEDIA_CAPS_VIDEO | PURPLE_MEDIA_CAPS_AUDIO;
+}
+
============================================================
--- libpurple/protocols/msn/webcam.h f29281d5038691636ebe1438a302d54794d88a2b
+++ libpurple/protocols/msn/webcam.h f29281d5038691636ebe1438a302d54794d88a2b
@@ -0,0 +1,44 @@
+/**
+ * @file webcam.h MSN Webcam 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 _MSN_WEBCAM_H_
+#define _MSN_WEBCAM_H_
+#include "internal.h"
+#include "slpcall.h"
+#include "slplink.h"
+#include "slpmsg.h"
+#include "media.h"
+
+void msn_webcam_send_syn(MsnSlpCall *slpcall, const gchar *content);
+void msn_webcam_send_ack(MsnSlpLink *slplink, MsnSlpMessage *slpmsg);
+void msn_webcam_send_xml(MsnSlpLink *slplink, MsnSlpMessage *slpmsg);
+void msn_webcam_recv_xml(MsnSlpLink *slplink, MsnSlpMessage *slpmsg,
+ const guchar *body, gsize body_len);
+void msn_webcam_process_msg(MsnSlpLink *slplink, MsnSlpMessage *slpmsg);
+void msn_webcam_recv(MsnSlpCall *slpcall);
+gboolean msn_initiate_media(PurpleAccount *account, const gchar *who,
+ PurpleMediaSessionType type);
+PurpleMediaCaps msn_get_media_caps(PurpleAccount *account, const gchar *who);
+
+#endif /* _MSN_WEBCAM_H_ */
============================================================
--- libpurple/protocols/msn/Makefile.am bc0d9535367c5da381e6515af27b49fb54888e96
+++ libpurple/protocols/msn/Makefile.am 7518c72758fc40863c4c9b386521b0dcff495709
@@ -64,6 +64,8 @@ MSNSOURCES = \
user.h \
userlist.c \
userlist.h \
+ webcam.c \
+ webcam.h \
msnutils.c \
msnutils.h
============================================================
--- libpurple/protocols/msn/Makefile.mingw 2fc5eab590015d1ba8b3e3effb4896a0338d7d7a
+++ libpurple/protocols/msn/Makefile.mingw 490ec256199cc38690a1684dd47658119e515066
@@ -66,6 +66,7 @@ C_SRC = cmdproc.c \
transaction.c \
user.c \
userlist.c \
+ webcam.c \
msnutils.c
OBJECTS = $(C_SRC:%.c=%.o)
============================================================
--- libpurple/protocols/msn/msn.c db1ea88fe86a348e57fe2dc47b8a2a790d8b27eb
+++ libpurple/protocols/msn/msn.c 632fa936c6a04c6586b497b65926ab0c9d3a4a61
@@ -47,6 +47,7 @@
#include "notification.h"
#include "sync.h"
#include "slplink.h"
+#include "webcam.h"
#if PHOTO_SUPPORT
#define MAX_HTTP_BUDDYICON_BYTES (200 * 1024)
@@ -2688,8 +2689,8 @@ static PurplePluginProtocolInfo prpl_inf
msn_attention_types, /* attention_types */
sizeof(PurplePluginProtocolInfo), /* struct_size */
msn_get_account_text_table, /* get_account_text_table */
- NULL, /* initiate_media */
- NULL /* can_do_media */
+ msn_initiate_media, /* initiate_media */
+ msn_get_media_caps /* get_media_caps */
};
static PurplePluginInfo info =
============================================================
--- libpurple/protocols/msn/slp.c d4d55a95ef034912d98e641c87d391961de24a7f
+++ libpurple/protocols/msn/slp.c ebef464d91b6515e4d8be1cebe58b1a75faba895
@@ -31,6 +31,7 @@
#include "switchboard.h"
#include "smiley.h"
+#include "webcam.h"
/* ms to delay between sending buddy icon requests to the server. */
#define BUDDY_ICON_DELAY 20
@@ -489,9 +490,10 @@ got_invite(MsnSlpCall *slpcall,
else if (!strcmp(type, "application/x-msnmsgr-transreqbody"))
{
/* A direct connection? */
-
+#if 0
char *listening, *nonce;
char *content;
+#endif
if (FALSE)
{
@@ -527,6 +529,14 @@ got_invite(MsnSlpCall *slpcall,
port);
#endif
}
+ else if (1)
+ {
+ send_decline(slpcall, branch, "application/x-msnmsgr-session-failure-respbody",
+ NULL);
+ msn_webcam_send_syn(slpcall, content);
+ return;
+ }
+#if 0
else
{
listening = "false";
@@ -546,6 +556,7 @@ got_invite(MsnSlpCall *slpcall,
g_free(content);
g_free(nonce);
+#endif
}
else if (!strcmp(type, "application/x-msnmsgr-transrespbody"))
{
============================================================
--- libpurple/protocols/msn/slpcall.c c5cffd20e8282ade7b1d83051ffa9deb5756e5b6
+++ libpurple/protocols/msn/slpcall.c 108dc85beb58837b1c9aa4d114d7119f89d6eb6b
@@ -24,6 +24,7 @@
#include "msn.h"
#include "msnutils.h"
#include "slpcall.h"
+#include "webcam.h"
#include "slp.h"
@@ -200,7 +201,7 @@ msn_slp_process_msg(MsnSlpLink *slplink,
if (slpmsg->flags == 0x0 || slpmsg->flags == 0x1000000)
{
- char *body_str;
+ char *body_str = NULL;
if (slpmsg->session_id == 64)
{
@@ -252,6 +253,9 @@ msn_slp_process_msg(MsnSlpLink *slplink,
slplink->remote_user,
body_str);
}
+ else if (slpmsg->slpcall && slpmsg->slpcall->app_id == 4) {
+ msn_webcam_process_msg(slplink, slpmsg);
+ }
else
{
body_str = g_strndup((const char *)body, body_len);
============================================================
--- libpurple/protocols/msn/slpcall.h 13863cc3a700579662279fdb70c9fb520d5c2adf
+++ libpurple/protocols/msn/slpcall.h 726c02cc5e9eb33e9967ad5e67241c075815f438
@@ -72,6 +72,7 @@ struct _MsnSlpCall
char *data_info;
PurpleXfer *xfer;
+ PurpleMedia *media;
MsnSlpCb cb;
void (*end_cb)(MsnSlpCall *slpcall, MsnSession *session);
============================================================
--- libpurple/protocols/msn/slplink.c a1d28636ade1b68f9bbbee806ca0ff5904635a55
+++ libpurple/protocols/msn/slplink.c 695292089ba3f2738c405cbccf9eea8948a60cd3
@@ -349,11 +349,17 @@ msn_slplink_release_slpmsg(MsnSlpLink *s
slpmsg->msg = msg = msn_message_new_msnslp();
- if (slpmsg->flags == 0x0)
+ if (slpmsg->slpcall && slpmsg->slpcall->app_id == 4)
{
msg->msnslp_header.session_id = slpmsg->session_id;
msg->msnslp_header.ack_id = rand() % 0xFFFFFF00;
+ msg->msnslp_footer.value = slpmsg->slpcall->app_id;
}
+ else if (slpmsg->flags == 0x0)
+ {
+ msg->msnslp_header.session_id = slpmsg->session_id;
+ msg->msnslp_header.ack_id = rand() % 0xFFFFFF00;
+ }
else if (slpmsg->flags == 0x2)
{
msg->msnslp_header.session_id = slpmsg->session_id;
More information about the Commits
mailing list