diff --git a/include/iris/jingle.h b/include/iris/jingle.h
new file mode 100644
index 0000000..7355178
--- /dev/null
+++ b/include/iris/jingle.h
@@ -0,0 +1 @@
+#include "../../src/xmpp/xmpp-im/jingle.h"
diff --git a/src/xmpp/jid/jid.cpp b/src/xmpp/jid/jid.cpp
index d1d33be..9fd001d 100644
--- a/src/xmpp/jid/jid.cpp
+++ b/src/xmpp/jid/jid.cpp
@@ -18,7 +18,6 @@
  *
  */
 
-//#undef IRIS_XMPP_JID_DEPRECATED
 #include "xmpp/jid/jid.h"
 
 #include <QCoreApplication>
diff --git a/src/xmpp/jid/jid.h b/src/xmpp/jid/jid.h
index 591cca2..fba722d 100644
--- a/src/xmpp/jid/jid.h
+++ b/src/xmpp/jid/jid.h
@@ -23,12 +23,6 @@
 
 #include <QString>
 
-#ifdef IRIS_XMPP_JID_DEPRECATED
-#define IRIS_XMPP_JID_DECL_DEPRECATED Q_DECL_DEPRECATED
-#else
-#define IRIS_XMPP_JID_DECL_DEPRECATED
-#endif
-
 namespace XMPP 
 {
     class Jid
diff --git a/src/xmpp/xmpp-core/protocol.cpp b/src/xmpp/xmpp-core/protocol.cpp
index fe51eb7..7a66aff 100644
--- a/src/xmpp/xmpp-core/protocol.cpp
+++ b/src/xmpp/xmpp-core/protocol.cpp
@@ -57,18 +57,6 @@ static QString printArray(const QByteArray &a)
     return s;
 }
 
-// firstChildElement
-//
-// Get an element's first child element
-static QDomElement firstChildElement(const QDomElement &e)
-{
-    for(QDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling()) {
-        if(n.isElement())
-            return n.toElement();
-    }
-    return QDomElement();
-}
-
 //----------------------------------------------------------------------------
 // Version
 //----------------------------------------------------------------------------
@@ -298,7 +286,7 @@ void BasicProtocol::extractStreamError(const QDomElement &e)
     QString text;
     QDomElement appSpec;
 
-    QDomElement t = firstChildElement(e);
+    QDomElement t = e.firstChildElement();
     if(t.isNull() || t.namespaceURI() != NS_STREAMS) {
         // probably old-style error
         errCond = -1;
@@ -1453,7 +1441,7 @@ bool CoreProtocol::normalStep(const QDomElement &e)
                 return true;
             }
             else if(e.tagName() == "failure") {
-                QDomElement t = firstChildElement(e);
+                QDomElement t = e.firstChildElement();
                 if(t.isNull() || t.namespaceURI() != NS_SASL)
                     errCond = -1;
                 else
diff --git a/src/xmpp/xmpp-core/xmpp_stanza.cpp b/src/xmpp/xmpp-core/xmpp_stanza.cpp
index 99b4c01..2dba0a6 100644
--- a/src/xmpp/xmpp-core/xmpp_stanza.cpp
+++ b/src/xmpp/xmpp-core/xmpp_stanza.cpp
@@ -53,6 +53,8 @@ using namespace XMPP;
     both type/condition and code.
     Error text in output XML is always presented in XMPP-style only.
 
+    WARNING: XEP-0086 is DEPRECATED. but this class is still very handy.
+
     All functions will always try to guess missing information based on mappings defined in the JEP.
 */
 
@@ -319,23 +321,21 @@ bool Stanza::Error::fromXml(const QDomElement &e, const QString &baseNS)
     type = Private::stringToErrorType(e.attribute("type"));
 
     // condition
-    QDomNodeList nl = e.childNodes();
     QDomElement t;
     condition = -1;
-    int n;
-    for(n = 0; n < nl.count(); ++n) {
-        QDomNode i = nl.item(n);
-        t = i.toElement();
-        if(!t.isNull()) {
-            // FIX-ME: this shouldn't be needed
-            if(t.namespaceURI() == NS_STANZAS || t.attribute("xmlns") == NS_STANZAS) {
-                condition = Private::stringToErrorCond(t.tagName());
-                if (condition != -1)
-                    break;
-            }
+    for (t = e.firstChildElement(); !t.isNull(); t = t.nextSiblingElement()) {
+        // FIX-ME: this shouldn't be needed
+        if(t.namespaceURI() == NS_STANZAS || t.attribute("xmlns") == NS_STANZAS) {
+            condition = Private::stringToErrorCond(t.tagName());
+            if (condition != -1)
+                if (condition == Redirect) {
+                    text = t.text().trimmed();
+                }
+                break;
         }
     }
 
+
     // code
     originalCode = e.attribute("code").toInt();
 
@@ -352,19 +352,19 @@ bool Stanza::Error::fromXml(const QDomElement &e, const QString &baseNS)
     }
 
     // text
-    t = e.elementsByTagNameNS(NS_STANZAS, "text").item(0).toElement();
-    if(!t.isNull())
-        text = t.text().trimmed();
-    else
-        text = e.text().trimmed();
+    if (condition != Redirect) {
+        t = e.elementsByTagNameNS(NS_STANZAS, "text").item(0).toElement();
+        if(!t.isNull())
+            text = t.text().trimmed();
+        else
+            text = e.text().trimmed();
+    }
 
     // appspec: find first non-standard namespaced element
     appSpec = QDomElement();
-    nl = e.childNodes();
-    for(n = 0; n < nl.count(); ++n) {
-        QDomNode i = nl.item(n);
-        if(i.isElement() && i.namespaceURI() != NS_STANZAS) {
-            appSpec = i.toElement();
+    for (t = e.firstChildElement(); !t.isNull(); t = t.nextSiblingElement()) {
+        if(t.namespaceURI() != NS_STANZAS) {
+            appSpec = t;
             break;
         }
     }
@@ -396,6 +396,9 @@ QDomElement Stanza::Error::toXml(QDomDocument &doc, const QString &baseNS) const
     errElem.setAttribute("type", stype);
     errElem.appendChild(t = doc.createElementNS(NS_STANZAS, scond));
     t.setAttribute("xmlns", NS_STANZAS);    // FIX-ME: this shouldn't be needed
+    if (condition == Redirect) {
+        t.appendChild(doc.createTextNode(text));
+    }
 
     // old code
     int scode = code();
@@ -403,7 +406,7 @@ QDomElement Stanza::Error::toXml(QDomDocument &doc, const QString &baseNS) const
         errElem.setAttribute("code", scode);
 
     // text
-    if(!text.isEmpty()) {
+    if(!text.isEmpty() && condition != Redirect) {
         t = doc.createElementNS(NS_STANZAS, "text");
         t.setAttribute("xmlns", NS_STANZAS);    // FIX-ME: this shouldn't be needed
         t.appendChild(doc.createTextNode(text));
diff --git a/src/xmpp/xmpp-im/client.cpp b/src/xmpp/xmpp-im/client.cpp
index aa077a4..ba88e2d 100644
--- a/src/xmpp/xmpp-im/client.cpp
+++ b/src/xmpp/xmpp-im/client.cpp
@@ -70,14 +70,14 @@
 //!  \endcode
 
 #include <stdarg.h>
-#include <qobject.h>
+#include <QObject>
 #include <QMap>
-#include <qtimer.h>
-#include <qpointer.h>
-//Added by qt3to4:
+#include <QTimer>
+#include <QPointer>
 #include <QList>
 #include "xmpp_tasks.h"
 #include "xmpp_xmlcommon.h"
+#include "jingle.h"
 #include "s5b.h"
 #include "xmpp_ibb.h"
 #include "xmpp_bitsofbinary.h"
@@ -139,6 +139,7 @@ public:
 
     LiveRoster roster;
     ResourceList resourceList;
+    Jingle::Manager *jingleman;
     S5BManager *s5bman;
     IBBManager *ibbman;
     BoBManager *bobman;
@@ -167,6 +168,8 @@ Client::Client(QObject *par)
 
     d->stream = 0;
 
+    d->jingleman = new Jingle::Manager(this);
+
     d->s5bman = new S5BManager(this);
     connect(d->s5bman, SIGNAL(incomingReady()), SLOT(s5b_incomingReady()));
 
@@ -251,6 +254,11 @@ FileTransferManager *Client::fileTransferManager() const
     return d->ftman;
 }
 
+Jingle::Manager *Client::jingleManager() const
+{
+    return d->jingleman;
+}
+
 S5BManager *Client::s5bManager() const
 {
     return d->s5bman;
diff --git a/src/xmpp/xmpp-im/filetransfer.cpp b/src/xmpp/xmpp-im/filetransfer.cpp
index 88edce6..8d6984a 100644
--- a/src/xmpp/xmpp-im/filetransfer.cpp
+++ b/src/xmpp/xmpp-im/filetransfer.cpp
@@ -33,18 +33,6 @@
 
 using namespace XMPP;
 
-// firstChildElement
-//
-// Get an element's first child element
-static QDomElement firstChildElement(const QDomElement &e)
-{
-    for(QDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling()) {
-        if(n.isElement())
-            return n.toElement();
-    }
-    return QDomElement();
-}
-
 //----------------------------------------------------------------------------
 // FileTransfer
 //----------------------------------------------------------------------------
@@ -625,7 +613,7 @@ bool JT_FT::take(const QDomElement &x)
         return false;
 
     if(x.attribute("type") == "result") {
-        QDomElement si = firstChildElement(x);
+        QDomElement si = x.firstChildElement();
         if(si.attribute("xmlns") != "http://jabber.org/protocol/si" || si.tagName() != "si") {
             setError(900, "");
             return true;
@@ -764,7 +752,7 @@ bool JT_PushFT::take(const QDomElement &e)
     if(e.attribute("type") != "set")
         return false;
 
-    QDomElement si = firstChildElement(e);
+    QDomElement si = e.firstChildElement();
     if(si.attribute("xmlns") != "http://jabber.org/protocol/si" || si.tagName() != "si")
         return false;
     if(si.attribute("profile") != "http://jabber.org/protocol/si/profile/file-transfer")
diff --git a/src/xmpp/xmpp-im/jingle.cpp b/src/xmpp/xmpp-im/jingle.cpp
new file mode 100644
index 0000000..e8fbbd8
--- /dev/null
+++ b/src/xmpp/xmpp-im/jingle.cpp
@@ -0,0 +1,161 @@
+/*
+ * jingle.cpp - "Jingle" session management
+ * Copyright (C) 2003  Justin Karneges, rion
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "jingle.h"
+#include "xmpp_xmlcommon.h"
+#include "im.h"
+
+namespace XMPP {
+namespace Jingle {
+
+//------------------------------------------------------------------------
+// Session
+//------------------------------------------------------------------------
+Session::Session(Manager *manager, const QString &sid, const Jid &peer)
+    : QObject(manager)
+    , _sid(sid)
+    , _peer(peer)
+{
+
+}
+
+//------------------------------------------------------------------------
+// Transport
+//------------------------------------------------------------------------
+Transport::Transport(Client *client) : QObject(client) { }
+
+
+//------------------------------------------------------------------------
+// Manager
+//------------------------------------------------------------------------
+class Manager::Private
+{
+public:
+    QScopedPointer<Tasks::JT_Push> pushTask;
+    QHash<QString, Session::Ptr> sessions;
+    Jid redirectTo;
+
+    QHash<QString, QSharedPointer<Tasks::DescriptionFactory> > descrFactories;
+    QHash<QString, QSharedPointer<Tasks::TransportFactory> > transportFactories;
+    QHash<QString, QSharedPointer<Tasks::DetailedReasonFactory> > reasonHandlers;
+    QHash<QString, QSharedPointer<Tasks::SecurityFactory> > securityLayers;
+};
+
+Manager::Manager(XMPP::Client *client)
+    : QObject(client)
+    , d(new Manager::Private)
+{
+    d->pushTask.reset(new Tasks::JT_Push(client->rootTask()));
+    connect(d->pushTask.data(),
+            SIGNAL(incomingRequest(const XMPP::Jid &from, const QString &iq_id, Tasks::Envelope::Ptr envelope)),
+            SLOT(pushTaskIncomingRequest(const XMPP::Jid &from, const QString &iq_id, Tasks::Envelope::Ptr envelope)));
+}
+
+Manager::~Manager()
+{
+
+}
+
+void Manager::setRedirection(const Jid &to)
+{
+    d->redirectTo = to;
+}
+
+void Manager::registerApp(const QString &ns, Tasks::DescriptionFactory *app)
+{
+    d->descrFactories.insert(ns, QSharedPointer<Tasks::DescriptionFactory>(app));
+}
+
+void Manager::registerTransport(const QString &ns, Tasks::TransportFactory *transport)
+{
+    d->transportFactories.insert(ns, QSharedPointer<Tasks::TransportFactory>(transport));
+}
+
+void Manager::registerSecurity(const QString &ns, Tasks::SecurityFactory *security)
+{
+    d->securityLayers.insert(ns, QSharedPointer<Tasks::SecurityFactory>(security));
+}
+
+void Manager::registerDetailedReason(const QString &ns, Tasks::DetailedReasonFactory *r)
+{
+    d->reasonHandlers.insert(ns, QSharedPointer<Tasks::DetailedReasonFactory>(r));
+}
+
+Tasks::Xmlable* Manager::descriptionFromXml(const QDomElement &e)
+{
+    QSharedPointer<Tasks::DescriptionFactory> df = d->descrFactories.value(e.namespaceURI());
+    return df.isNull() ? 0 : df->descriptionFromXml(e);
+}
+
+Tasks::Xmlable* Manager::transportFromXml(const QDomElement &e)
+{
+    QSharedPointer<Tasks::TransportFactory> transport = d->transportFactories.value(e.namespaceURI());
+    return transport.isNull() ? 0 : transport->transportFromXml(e);
+}
+
+Tasks::Xmlable* Manager::securityFromXml(const QDomElement &e)
+{
+    QSharedPointer<Tasks::SecurityFactory> sec = d->securityLayers.value(e.namespaceURI());
+    return sec.isNull() ? 0 : sec->securityFromXml(e);
+}
+
+Tasks::Xmlable* Manager::detailedReasonFromXml(const QDomElement &e)
+{
+    QSharedPointer<Tasks::DetailedReasonFactory> dr = d->reasonHandlers.value(e.namespaceURI());
+    return dr.isNull() ? 0 : dr->detailedReasonFromXml(e);
+}
+
+void Manager::pushTaskIncomingRequest(const XMPP::Jid &from, const QString &iq_id,
+                                      Tasks::Envelope::Ptr envelope)
+{
+    if (envelope->action == Tasks::Envelope::SessionInitiate) {
+        if (!d->redirectTo.isNull()) {
+            d->pushTask->respondError(from, iq_id, Stanza::Error::Redirect, d->redirectTo.full());
+            return;
+        }
+        if (d->sessions.count() >= MaxSessions) {
+            d->pushTask->respondError(from, iq_id, Stanza::Error::ResourceConstraint);
+            return;
+        }
+        Session::Ptr session = d->sessions.value(envelope->sid);
+        if (!session.isNull()) {
+            d->pushTask->respondError(from, iq_id, Stanza::Error::Conflict);
+            return;
+        }
+        if (envelope->contentList.isEmpty()) {
+            d->pushTask->respondError(from, iq_id, Stanza::Error::BadRequest);
+            return;
+        }
+        // more checks on conflicts should be done in jingle applications (ft, rtp etc)
+        Jid initiator = envelope->initiator.isNull()? from : envelope->initiator;
+
+        d->pushTask->respondSuccess(from, iq_id);
+        session = Session::Ptr(new Session(this, envelope->sid, initiator));
+        d->sessions.insert(envelope->sid, session);
+//        foreach (Content::Ptr c, envelope->contentList) {
+
+//        }
+    }
+}
+
+
+
+} // namespace Jingle
+} // namespace XMPP
diff --git a/src/xmpp/xmpp-im/jingle.h b/src/xmpp/xmpp-im/jingle.h
new file mode 100644
index 0000000..96bc519
--- /dev/null
+++ b/src/xmpp/xmpp-im/jingle.h
@@ -0,0 +1,133 @@
+/*
+ * jingle.h - "Jingle" session management
+ * Copyright (C) 2003  Justin Karneges, rion
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef JINGLE_H
+#define JINGLE_H
+
+#include <QObject>
+
+#include "jingle_task.h"
+
+namespace XMPP {
+namespace Jingle {
+
+const char* JINGLE_NS = "urn:xmpp:jingle:1";
+class Manager;
+
+// examples: ft, rtp, wb etc
+class App : public QObject
+{
+    Q_OBJECT
+    Q_DISABLE_COPY(App)
+
+public:
+
+
+};
+
+// examples: s5b, ibb, ice-udp etc
+class Transport : public QObject
+{
+    Q_OBJECT
+    Q_DISABLE_COPY(Transport)
+
+public:
+    Transport(Client *client);
+
+};
+
+// base class for all jingle security managers
+class Security : public QObject
+{
+    Q_OBJECT
+    Q_DISABLE_COPY(Security)
+
+public:
+
+};
+
+
+class Session : public QObject
+{
+    Q_OBJECT
+    Q_DISABLE_COPY(Session)
+
+public:
+    typedef QSharedPointer<Session> Ptr;
+
+    Session(Manager *manager, const QString &sid, const Jid &peer);
+
+
+    inline const QString &sid() const { return _sid; }
+    inline const Jid &peer() const { return _peer; }
+
+private:
+    QString _sid;
+    Jid _peer;
+};
+
+class Manager : public QObject
+{
+    Q_OBJECT
+
+    friend class Tasks::Content;
+    friend class Tasks::Reason;
+
+    static const int MaxSessions = 1000; //1000? just to have some limit
+
+public:
+    explicit Manager(XMPP::Client *client = 0);
+    ~Manager();
+
+    void setRedirection(const Jid &to);
+
+    void registerApp(const QString &ns, Tasks::DescriptionFactory *app);
+    void registerTransport(const QString &ns, Tasks::TransportFactory *transport);
+    void registerSecurity(const QString &ns, Tasks::SecurityFactory *security);
+    void registerDetailedReason(const QString &ns, Tasks::DetailedReasonFactory *r);
+
+private:
+
+    Tasks::Xmlable* descriptionFromXml(const QDomElement &e);
+    Tasks::Xmlable* transportFromXml(const QDomElement &e);
+    Tasks::Xmlable* securityFromXml(const QDomElement &e);
+    Tasks::Xmlable* detailedReasonFromXml(const QDomElement &e);
+
+signals:
+
+public slots:
+
+private slots:
+    void pushTaskIncomingRequest(const XMPP::Jid &from, const QString &iq_id, Tasks::Envelope::Ptr envelope);
+
+private:
+    class Private;
+    QScopedPointer<Private> d;
+};
+
+
+
+
+
+
+} // namespace Jingle
+} // namespace XMPP
+
+#endif // JINGLE_H
diff --git a/src/xmpp/xmpp-im/jingle_task.cpp b/src/xmpp/xmpp-im/jingle_task.cpp
new file mode 100644
index 0000000..12e6442
--- /dev/null
+++ b/src/xmpp/xmpp-im/jingle_task.cpp
@@ -0,0 +1,450 @@
+/*
+ * jingle_task.cpp - "Jingle" support classes
+ * Copyright (C) 2011  Justin Karneges, rion
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "jingle_task.h"
+#include "jingle.h"
+#include "xmpp_xmlcommon.h"
+#include "im.h"
+
+namespace XMPP {
+namespace Jingle {
+namespace Tasks {
+
+//------------------------------------------------------------------------
+// Reason
+//------------------------------------------------------------------------
+
+Reason::CondEntry Reason::CondTable[] =
+{
+    { "alternative-session",      Reason::AlternativeSession },
+    { "busy",                     Reason::Busy },
+    { "cancel",                   Reason::Cancel },
+    { "connectivity-error",       Reason::ConnectivityError },
+    { "decline",                  Reason::Decline },
+    { "expired",                  Reason::Expired },
+    { "failed-application",       Reason::FailedApplication },
+    { "failed-transport",         Reason::FailedTransport },
+    { "general-error",            Reason::GeneralError },
+    { "gone",                     Reason::Gone },
+    { "incompatible-parameters",  Reason::IncompatibleParameters },
+    { "media-error",              Reason::MediaError },
+    { "security-error",           Reason::SecurityError },
+    { "success",                  Reason::Success },
+    { "timeout",                  Reason::Timeout },
+    { "unsupported-applications", Reason::UnsupportedApplications },
+    { "unsupported-transports",   Reason::UnsupportedTransports },
+};
+
+Reason* Reason::fromXml(const QDomElement &e, Client *client)
+{
+    if(e.tagName() != QLatin1String("reason"))
+        return NULL;
+
+    bool valid = false;
+    Condition condition = (Condition)-1;
+    QString text;
+    QSharedPointer<Xmlable> detailed;
+
+    for (QDomElement c = e.firstChildElement(); !c.isNull(); c = c.nextSiblingElement()) {
+        if (c.tagName() == QLatin1String("text")) {
+            text = c.text();
+        }
+        else if (!c.namespaceURI().isEmpty()) {
+            detailed = QSharedPointer<Xmlable>(client->jingleManager()->detailedReasonFromXml(c));
+            if (detailed.isNull()) {
+                return NULL;
+            }
+        }
+        else {
+            for(int n = 0; sizeof(CondTable) / sizeof(CondEntry); ++n) {
+                if(c.tagName() == QLatin1String(CondTable[n].str)) {
+                    condition = CondTable[n].cond;
+                    valid = true;
+                    break;
+                }
+            }
+        }
+    }
+
+    if (valid) {
+        return new Reason(condition, text, detailed);
+    }
+
+    return NULL;
+}
+
+QDomElement Reason::toXml(QDomDocument *doc) const
+{
+    for(int n = 0; sizeof(CondTable) / sizeof(CondEntry); ++n) {
+        if(CondTable[n].cond == condition) {
+            QDomElement e = doc->createElement(QLatin1String("reason"));
+            e.appendChild(doc->createElement(QLatin1String(CondTable[n].str)));
+            if (!text.isEmpty()) {
+                e.appendChild(textTag(doc, QLatin1String("text"), text));
+            }
+            if (!detailed.isNull()) {
+                e.appendChild(detailed->toXml(doc));
+            }
+            return e;
+        }
+    }
+    return QDomElement();
+}
+
+//------------------------------------------------------------
+// Content
+//------------------------------------------------------------
+Content::Content(Creator creator, const QString &name,
+                             Xmlable *description, Xmlable *transport)
+    : creator(creator)
+    , name(name)
+    , senders(SendersBoth)
+    , disposition(QLatin1String("session"))
+    , description(description)
+    , transport(transport)
+{
+
+}
+
+void Content::setSecurity(Xmlable *security_)
+{
+    security.reset(security_);
+}
+
+Content* Content::fromXml(QDomElement content, XMPP::Client *client)
+{
+    QString name;
+    QString disposition = QLatin1String("session");
+    Creator creator;
+    Senders senders = SendersBoth;
+    Xmlable *description = 0, *transport = 0, *security = 0;
+
+    name = content.attribute(QLatin1String("name"));
+    QDomElement descriptionEl = content.elementsByTagName(QLatin1String("description")).at(0).toElement();
+    QDomElement transportEl = content.elementsByTagName(QLatin1String("transport")).at(0).toElement();
+    QDomElement securityEl = content.elementsByTagName(QLatin1String("security")).at(0).toElement();
+    if (name.isEmpty() || descriptionEl.isNull() || transportEl.isNull()) {
+        return NULL;
+    }
+    QString creatorStr = content.attribute(QLatin1String("name"));
+    if (creatorStr == QLatin1String("initiator")) {
+        creator = CreatorInitiator;
+    }
+    else if (creatorStr == QLatin1String("responder")) {
+        creator = CreatorResponder;
+    }
+    else {
+        return NULL;
+    }
+    QString sendersStr = content.attribute(QLatin1String("senders"));
+    if (sendersStr == QLatin1String("initiator")) {
+        senders = SendersInitiator;
+    }
+    else if (sendersStr == QLatin1String("none")) {
+        senders = SendersNone;
+    }
+    else if (sendersStr == QLatin1String("responder")) {
+        senders = SendersResponder;
+    }
+    else if (sendersStr == QLatin1String("both")) {
+        senders = SendersBoth;
+    }
+    else {
+        return NULL;
+    }
+    disposition = content.attribute(QLatin1String("disposition"));
+    description = client->jingleManager()->descriptionFromXml(descriptionEl);
+    transport = client->jingleManager()->transportFromXml(transportEl);
+    if (!securityEl.isNull()) {
+        security = client->jingleManager()->securityFromXml(securityEl);
+        // if security == 0 then then its unsupported? just ignore it atm
+        // according to xtls draft responder may omit security when unsupported.
+    }
+    Content *c = new Content(creator, name, description, transport);
+    c->setSecurity(security);
+    c->senders = senders;
+    c->disposition = disposition;
+    return c;
+}
+
+QDomElement Content::toXml(QDomDocument *doc) const
+{
+    QString creatorStr;
+    QString sendersStr;
+
+    switch (creator) {
+    case CreatorInitiator:
+        creatorStr = QLatin1String("initiator");
+        break;
+    case CreatorResponder:
+        creatorStr = QLatin1String("responder");
+        break;
+    }
+    if (creatorStr.isEmpty() || name.isEmpty() || description.isNull() || transport.isNull()) {
+        qDebug("invalid jingle content");
+        return QDomElement();
+    }
+
+    switch (senders) {
+        case SendersNone:
+            sendersStr = QLatin1String("none");
+            break;
+
+        case SendersInitiator:
+            sendersStr = QLatin1String("initiator");
+            break;
+
+        case SendersResponder:
+            sendersStr = QLatin1String("responder");
+            break;
+
+        case SendersBoth:
+        default:
+            break;
+    }
+
+    QDomElement content = doc->createElement(QLatin1String("content"));
+    content.setAttribute(QLatin1String("creator"), creatorStr);
+    content.setAttribute(QLatin1String("name"), name);
+    if (disposition != QLatin1String("session")) {
+        content.setAttribute(QLatin1String("disposition"), disposition);
+    }
+    if (!sendersStr.isEmpty()) {
+        content.setAttribute(QLatin1String("senders"), senders);
+    }
+
+    content.appendChild(description->toXml(doc));
+    content.appendChild(transport->toXml(doc));
+    if (!security.isNull()) {
+        content.appendChild(security->toXml(doc));
+    }
+    return content;
+}
+
+
+//----------------------------------------------------------------------------
+// Envelope
+//----------------------------------------------------------------------------
+Envelope::ActionEntry Envelope::actionTable[] = {
+    { "content-accept",        Envelope::ContentAccept },
+    { "content-add",        Envelope::ContentAdd },
+    { "content-modify",        Envelope::ContentModify },
+    { "content-reject",        Envelope::ContentReject },
+    { "content-remove",        Envelope::ContentRemove },
+    { "description-info",    Envelope::DescriptionInfo },
+    { "security-info",        Envelope::SecurityInfo },
+    { "session-accept",        Envelope::SessionAccept },
+    { "session-info",        Envelope::SessionInfo },
+    { "session-initiate",    Envelope::SessionInitiate },
+    { "session-terminate",    Envelope::SessionTerminate },
+    { "transport-accept",    Envelope::TransportAccept },
+    { "transport-info",        Envelope::TransportInfo },
+    { "transport-reject",    Envelope::TransportReject },
+    { "transport-replace",    Envelope::TransportReplace }
+};
+
+
+Envelope::Ptr Envelope::fromXml(QDomElement &e, Client *client)
+{
+    QString actionStr = e.attribute(QLatin1String("action"));
+    Action action;
+    QString sid = e.attribute(QLatin1String("sid"));
+
+    bool found = false;
+    for (unsigned int i = 0; i < sizeof(actionTable) / sizeof(ActionEntry); i++) {
+        if (actionStr == actionTable[i].str) {
+            found = true;
+            action = actionTable[i].action;
+            break;
+        }
+    }
+    if (!found || sid.isEmpty()) {
+        return Envelope::Ptr();
+    }
+    Envelope::Ptr envelope(new Envelope(action, sid));
+
+    QDomElement re = e.firstChildElement(QLatin1String("reason"));
+    if(!re.isNull()) {
+        envelope->reason = QSharedPointer<Reason>(Reason::fromXml(re, client));
+        if (envelope->reason.isNull()) {
+            return Envelope::Ptr();
+        }
+    }
+    for(QDomElement ce = e.firstChildElement(QLatin1String("content"));
+        !e.isNull(); e = e.nextSiblingElement(QLatin1String("content"))) {
+
+        Content::Ptr c(Content::fromXml(ce, client));
+        if (c.isNull()) {
+            return Envelope::Ptr();
+        }
+        envelope->contentList += c;
+    }
+    if (!e.attribute(QLatin1String("initiator")).isEmpty()) {
+        envelope->initiator = Jid(e.attribute(QLatin1String("initiator")));
+        if (envelope->initiator.isNull()) {
+            return Envelope::Ptr();
+        }
+    }
+    if (!e.attribute(QLatin1String("responder")).isEmpty()) {
+        envelope->responder = Jid(e.attribute(QLatin1String("responder")));
+        if (envelope->responder.isNull()) {
+            return Envelope::Ptr();
+        }
+    }
+    return envelope;
+}
+
+QDomElement Envelope::toXml(QDomDocument *doc) const
+{
+    QDomElement query = doc->createElementNS(QLatin1String(JINGLE_NS), QLatin1String("jingle"));
+    //query.setAttribute("xmlns", JINGLE_NS);
+    for (unsigned int i = 0; i < sizeof(actionTable) / sizeof(ActionEntry); i++) {
+        if (actionTable[i].action == action) {
+            query.setAttribute(QLatin1String("action"), QLatin1String(actionTable[i].str));
+            break;
+        }
+    }
+
+    if(!initiator.isNull())
+        query.setAttribute(QLatin1String("initiator"), initiator.full());
+    if(!responder.isNull())
+        query.setAttribute(QLatin1String("responder"), responder.full());
+    query.setAttribute(QLatin1String("sid"), sid);
+
+    if(action != SessionTerminate) {
+        // for session terminate, there is no content list, just
+        //   a reason for termination
+        foreach(const Content::Ptr &c, contentList) {
+            QDomElement content = c->toXml(doc);
+            query.appendChild(content);
+        }
+    }
+    if (!reason.isNull()) {
+        query.appendChild(reason->toXml(doc));
+    }
+    return query;
+}
+
+void Envelope::setReason(Reason::Condition cond, const QString &text)
+{
+    reason = QSharedPointer<Reason>(new Reason(cond, text));
+}
+
+void Envelope::setReason(Reason::Condition cond, Xmlable *detailed)
+{
+    reason = QSharedPointer<Reason>(new Reason(cond, "", QSharedPointer<Xmlable>(detailed)));
+}
+
+
+
+//----------------------------------------------------------------------------
+// JT
+//----------------------------------------------------------------------------
+JT::JT(XMPP::Task *parent) :
+    XMPP::Task(parent)
+{
+}
+
+JT::~JT()
+{
+}
+
+void JT::request(const XMPP::Jid &to, const Envelope &envelope)
+{
+    to_ = to;
+    iq_ = createIQ(doc(), QLatin1String("set"), to.full(), id());
+    iq_.appendChild(envelope.toXml(client()->doc()));
+}
+
+void JT::onGo()
+{
+    send(iq_);
+}
+
+bool JT::take(const QDomElement &x)
+{
+    if(!iqVerify(x, to_, id()))
+        return false;
+
+    if(x.attribute("type") == QLatin1String("result"))
+        setSuccess();
+    else
+        setError(x);
+
+    return true;
+}
+
+//----------------------------------------------------------------------------
+// JT_Push
+//----------------------------------------------------------------------------
+JT_Push::JT_Push(XMPP::Task *parent) :
+    XMPP::Task(parent)
+{
+}
+
+JT_Push::~JT_Push()
+{
+}
+
+void JT_Push::respondSuccess(const XMPP::Jid &to, const QString &id)
+{
+    QDomElement iq = createIQ(doc(), QLatin1String("result"), to.full(), id);
+    send(iq);
+}
+
+void JT_Push::respondError(const XMPP::Jid &to, const QString &id,
+                           Stanza::Error::ErrorCond cond, const QString &str)
+{
+    QDomElement iq = createIQ(doc(), QLatin1String("error"), to.full(), id);
+    Stanza::Error error(Stanza::Error::Cancel, cond, str);
+    iq.appendChild(error.toXml(*client()->doc(), client()->stream().baseNS()));
+    send(iq);
+}
+
+bool JT_Push::take(const QDomElement &e)
+{
+    if(e.tagName() != QLatin1String("iq") || e.attribute("type") != QLatin1String("set")) {
+        return false;
+    }
+
+    QDomElement je = e.firstChildElement(QLatin1String("jingle"));
+    if (je.isNull() || je.namespaceURI() != QLatin1String(JINGLE_NS)) {
+        return false;
+    }
+
+    XMPP::Jid from = e.attribute(QLatin1String("from"));
+    QString iq_id = e.attribute(QLatin1String("id"));
+
+    Envelope::Ptr envelope = Envelope::fromXml(je, client());
+    if (!envelope) {
+        respondError(from, iq_id, Stanza::Error::BadRequest);
+    }
+    else {
+        emit incomingRequest(from, iq_id, envelope);
+    }
+
+    return true;
+}
+
+
+
+} // Task
+} // Jingle
+} // XMPP
diff --git a/src/xmpp/xmpp-im/jingle_task.h b/src/xmpp/xmpp-im/jingle_task.h
new file mode 100644
index 0000000..da21534
--- /dev/null
+++ b/src/xmpp/xmpp-im/jingle_task.h
@@ -0,0 +1,246 @@
+/*
+ * jingle_task.h - "Jingle" support classes
+ * Copyright (C) 2011  Justin Karneges, rion
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef JINGLE_TASK_H
+#define JINGLE_TASK_H
+
+
+#include <QObject>
+#include <QDomElement>
+#include <QSharedPointer>
+#include <QHash>
+
+#include "xmpp_task.h"
+#include "xmpp_stanza.h"
+#include "xmpp/jid/jid.h"
+
+namespace XMPP {
+namespace Jingle {
+namespace Tasks {
+
+// INTERFACES
+class Xmlable
+{
+public:
+    virtual QDomElement toXml(QDomDocument *doc) const = 0;
+};
+
+class DescriptionFactory
+{
+public:
+    virtual Xmlable* descriptionFromXml(const QDomElement &) = 0;
+};
+
+class TransportFactory
+{
+public:
+    virtual Xmlable* transportFromXml(const QDomElement &) = 0;
+};
+
+class DetailedReasonFactory
+{
+public:
+    virtual Xmlable* detailedReasonFromXml(const QDomElement &) { return 0; };
+};
+
+class SecurityFactory
+{
+public:
+    virtual Xmlable* securityFromXml(const QDomElement &) { return 0; };
+};
+// END OF INTERFACES
+
+class Content : public Xmlable
+{
+public:
+    typedef QSharedPointer<Content> Ptr;
+
+    enum Creator {
+        CreatorInitiator,
+        CreatorResponder
+    };
+
+    enum Senders {
+        SendersNone,
+        SendersInitiator,
+        SendersResponder,
+        SendersBoth
+    };
+
+    Content(Creator creator, const QString &name,
+                  Xmlable *description, Xmlable *transport);
+
+    void setSecurity(Xmlable *security_);
+
+    static Content* fromXml(QDomElement content, Client *client);
+    QDomElement toXml(QDomDocument *doc) const;
+
+    Creator creator;
+    QString name;
+    Senders senders;
+    QString disposition;
+
+    QScopedPointer<Xmlable> description;
+    QScopedPointer<Xmlable> transport;
+    QScopedPointer<Xmlable> security;
+};
+
+class Reason : public Xmlable
+{
+public:
+    enum Condition
+    {
+        AlternativeSession,
+        Busy,
+        Cancel,
+        ConnectivityError,
+        Decline,
+        Expired,
+        FailedApplication,
+        FailedTransport,
+        GeneralError,
+        Gone,
+        IncompatibleParameters,
+        MediaError,
+        SecurityError,
+        Success,
+        Timeout,
+        UnsupportedApplications,
+        UnsupportedTransports
+    };
+
+    Condition condition;
+    QString text;
+    QSharedPointer<Xmlable> detailed;
+
+    Reason(Condition condition = (Condition)-1, const QString &text = QString(),
+           QSharedPointer<Xmlable> detailed = QSharedPointer<Xmlable>())
+        : condition(condition)
+        , text(text)
+        , detailed(detailed)
+    {
+    }
+
+    static Reason* fromXml(const QDomElement &e, Client *client);
+    QDomElement toXml(QDomDocument *doc) const;
+
+private:
+    struct CondEntry
+    {
+        const char *str;
+        Condition cond;
+    };
+
+    static CondEntry CondTable[];
+};
+
+class Envelope : public Xmlable
+{
+public:
+    typedef QSharedPointer<Envelope> Ptr;
+
+    enum Action {
+        ContentAccept,
+        ContentAdd,
+        ContentModify,
+        ContentReject,
+        ContentRemove,
+        DescriptionInfo,
+        SecurityInfo,
+        SessionAccept,
+        SessionInfo,
+        SessionInitiate,
+        SessionTerminate,
+        TransportAccept,
+        TransportInfo,
+        TransportReject,
+        TransportReplace
+    };
+
+    Envelope(Action action, const QString &sid)
+        : action(action)
+        , sid(sid)
+    {}
+
+    static Envelope::Ptr fromXml(QDomElement &e, Client *client);
+    QDomElement toXml(QDomDocument *doc) const;
+    void setReason(Reason::Condition, const QString &text = QString());
+    void setReason(Reason::Condition, Xmlable *detailed);
+
+    Action action;
+    Jid initiator;
+    Jid responder;
+    QString sid;
+
+    QList<Content::Ptr> contentList;
+
+    QSharedPointer<Reason> reason;
+
+private:
+    struct ActionEntry
+    {
+        const char *str;
+        Action action;
+    };
+    static ActionEntry actionTable[];
+};
+
+class JT : public XMPP::Task
+{
+    Q_OBJECT
+
+public:
+    JT(XMPP::Task *parent);
+    ~JT();
+
+    void request(const XMPP::Jid &to, const Envelope &envelope);
+
+    virtual void onGo();
+    virtual bool take(const QDomElement &x);
+
+private:
+    QDomElement iq_;
+    XMPP::Jid to_;
+};
+
+class JT_Push : public XMPP::Task
+{
+    Q_OBJECT
+
+public:
+    JT_Push(XMPP::Task *parent);
+    ~JT_Push();
+
+    void respondSuccess(const XMPP::Jid &to, const QString &id);
+    void respondError(const XMPP::Jid &to, const QString &id,
+                      Stanza::Error::ErrorCond cond, const QString &str = QString());
+
+    virtual bool take(const QDomElement &e);
+
+signals:
+    void incomingRequest(const XMPP::Jid &from, const QString &iq_id, Envelope::Ptr envelope);
+};
+
+
+} // namespace Task
+} // namespace Jingle
+} // namespace XMPP
+
+#endif
diff --git a/src/xmpp/xmpp-im/jingle_transport_iceudp.cpp b/src/xmpp/xmpp-im/jingle_transport_iceudp.cpp
new file mode 100644
index 0000000..f6782b6
--- /dev/null
+++ b/src/xmpp/xmpp-im/jingle_transport_iceudp.cpp
@@ -0,0 +1,124 @@
+/*
+ * jingle_tranport_iceudp.cpp - "Jingle" transport ICE-UDP
+ * Copyright (C) 2011  rion
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <QHostAddress>
+#include "jingle_transport_iceudp.h"
+#include "xmpp_xmlcommon.h"
+#include "ice176.h"
+#include "xmpp_client.h"
+
+namespace XMPP {
+namespace Jingle {
+
+const char *ICEUDP_NS = "urn:xmpp:jingle:transports:ice-udp:1";
+
+class ICEUDPTransport : public Tasks::Xmlable
+{
+public:
+    ICEUDPTransport(const QString &pwd, const QString &ufrag,
+                    const QList<Ice176::Candidate> &canidates = QList<Ice176::Candidate>())
+        : pwd(pwd)
+        , ufrag(ufrag)
+        , canidates(canidates)
+    {
+
+    }
+
+    QDomElement toXml(QDomDocument *doc) const
+    {
+        QDomElement transport = doc->createElementNS(ICEUDP_NS, "transport");
+        if (canidates.count()) {
+            if (ufrag.isEmpty()) {
+                return QDomElement();
+            }
+            transport.setAttribute("pwd", pwd);
+            transport.setAttribute("ufrag", ufrag);
+            foreach (const Ice176::Candidate &c, canidates) {
+                QDomElement e = doc->createElement("candidate");
+                e.setAttribute("component", QString::number(c.component));
+                e.setAttribute("foundation", c.foundation);
+                e.setAttribute("generation", QString::number(c.generation));
+                if(!c.id.isEmpty()) {
+                    e.setAttribute("id", c.id);
+                }
+                e.setAttribute("ip", c.ip.toString());
+                if(c.network != -1) {
+                    e.setAttribute("network", QString::number(c.network));
+                }
+                else {
+                    e.setAttribute("network", QString::number(0));
+                }
+                e.setAttribute("port", QString::number(c.port));
+                e.setAttribute("priority", QString::number(c.priority));
+                e.setAttribute("protocol", c.protocol);
+                if(!c.rel_addr.isNull()) {
+                    e.setAttribute("rel-addr", c.rel_addr.toString());
+                }
+                if(c.rel_port != -1) {
+                    e.setAttribute("rel-port", QString::number(c.rel_port));
+                }
+                e.setAttribute("type", c.type);
+                transport.appendChild(e);
+            }
+        }
+        return transport;
+    }
+
+    static ICEUDPTransport* fromXml(const QDomElement &e) {
+        QList<Ice176::Candidate> canidates;
+        for (QDomElement n = e.firstChildElement("candidate"); !n.isNull(); n = n.nextSiblingElement("candidate")) {
+            XMPP::Ice176::Candidate c;
+            c.component = e.attribute("component").toInt();
+            c.foundation = e.attribute("foundation");
+            c.generation = e.attribute("generation").toInt();
+            c.id = e.attribute("id");
+            c.ip = QHostAddress(e.attribute("ip"));
+            c.network = e.attribute("network").toInt();
+            c.port = e.attribute("port").toInt();
+            c.priority = e.attribute("priority").toInt();
+            c.protocol = e.attribute("protocol");
+            c.rel_addr = QHostAddress(e.attribute("rel-addr"));
+            c.rel_port = e.attribute("rel-port").toInt();
+            c.type = e.attribute("type");
+            canidates.append(c);
+        }
+        return new ICEUDPTransport(e.attribute("pwd"), e.attribute("ufrag"), canidates);
+    }
+
+    QString pwd;
+    QString ufrag;
+    QList<Ice176::Candidate> canidates;
+};
+
+//--------------------------------------------------------------------------
+// ICEUDPTransportManager
+//--------------------------------------------------------------------------
+ICEUDPTransportManager::ICEUDPTransportManager(Client *client)
+    : Transport(client)
+{
+    client->jingleManager()->registerTransport(ICEUDP_NS, this);
+}
+
+Tasks::Xmlable* ICEUDPTransportManager::transportFromXml(const QDomElement &e)
+{
+    return ICEUDPTransport::fromXml(e);
+}
+
+} // Jingle
+} // XMPP
diff --git a/src/xmpp/xmpp-im/jingle_transport_iceudp.h b/src/xmpp/xmpp-im/jingle_transport_iceudp.h
new file mode 100644
index 0000000..23c8eff
--- /dev/null
+++ b/src/xmpp/xmpp-im/jingle_transport_iceudp.h
@@ -0,0 +1,42 @@
+/*
+ * jingle_tranport_iceudp.h - "Jingle" transport ICE-UDP
+ * Copyright (C) 2011  rion
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef JINGLE_TRANSPORT_ICEUDP
+#define JINGLE_TRANSPORT_ICEUDP
+
+#include "jingle.h"
+
+namespace XMPP {
+    class Client;
+
+namespace Jingle {
+
+class ICEUDPTransportManager : public Transport, Tasks::TransportFactory
+{
+    ICEUDPTransportManager(Client *client);
+
+    Tasks::Xmlable* transportFromXml(const QDomElement &);
+};
+
+} // Jingle
+} // XMPP
+
+
+#endif
diff --git a/src/xmpp/xmpp-im/xmpp_client.h b/src/xmpp/xmpp-im/xmpp_client.h
index 63dc054..d8cc546 100644
--- a/src/xmpp/xmpp-im/xmpp_client.h
+++ b/src/xmpp/xmpp-im/xmpp_client.h
@@ -32,6 +32,9 @@ class QDomElement;
 class QDomDocument;
 class ByteStream;
 namespace XMPP {
+namespace Jingle {
+    class Manager;
+}
     class ClientStream;
     class Features;
     class FileTransferManager;
@@ -117,6 +120,7 @@ namespace XMPP
         const Features& extension(const QString& ext) const;
         QStringList extensions() const;
         
+        Jingle::Manager *jingleManager() const;
         S5BManager *s5bManager() const;
         IBBManager *ibbManager() const;
         BoBManager *bobManager() const;
diff --git a/src/xmpp/xmpp-im/xmpp_xmlcommon.cpp b/src/xmpp/xmpp-im/xmpp_xmlcommon.cpp
index 4569127..dcfca3d 100644
--- a/src/xmpp/xmpp-im/xmpp_xmlcommon.cpp
+++ b/src/xmpp/xmpp-im/xmpp_xmlcommon.cpp
@@ -208,7 +208,6 @@ XDomNodeList childElementsByTagNameNS(const QDomElement &e, const QString &nsURI
     return out;
 }
 
-
 /**
  * \brief create a new IQ stanza
  * \param doc 
diff --git a/src/xmpp/xmpp.pri b/src/xmpp/xmpp.pri
index 8948fb7..596d80d 100644
--- a/src/xmpp/xmpp.pri
+++ b/src/xmpp/xmpp.pri
@@ -37,6 +37,9 @@ HEADERS += \
     $$PWD/xmpp-im/xmpp_discoinfotask.h \
     $$PWD/xmpp-im/xmpp_xmlcommon.h \
     $$PWD/xmpp-im/xmpp_vcard.h \
+    $$PWD/xmpp-im/jingle.h \
+    $$PWD/xmpp-im/jingle_task.h \
+    $$PWD/xmpp-im/jingle_transport_iceudp.h \
     $$PWD/xmpp-im/xmpp_bytestream.h \
     $$PWD/xmpp-im/s5b.h \
     $$PWD/xmpp-im/xmpp_ibb.h \
@@ -91,6 +94,9 @@ SOURCES += \
     $$PWD/xmpp-im/xmpp_task.cpp \
     $$PWD/xmpp-im/xmpp_tasks.cpp \
     $$PWD/xmpp-im/xmpp_xmlcommon.cpp \
+    $$PWD/xmpp-im/jingle.cpp \
+    $$PWD/xmpp-im/jingle_task.cpp \
+    $$PWD/xmpp-im/jingle_transport_iceudp.cpp \
     $$PWD/xmpp-im/xmpp_vcard.cpp \
     $$PWD/xmpp-im/xmpp_bytestream.cpp \
     $$PWD/xmpp-im/s5b.cpp \
