view libervia/backend/bridge/bridge_constructor/constructors/dbus-xml/constructor.py @ 4231:e11b13418ba6

plugin XEP-0353, XEP-0234, jingle: WebRTC data channel signaling implementation: Implement XEP-0343: Signaling WebRTC Data Channels in Jingle. The current version of the XEP (0.3.1) has no implementation and contains some flaws. After discussing this on xsf@, Daniel (from Conversations) mentioned that they had a sprint with Larma (from Dino) to work on another version and provided me with this link: https://gist.github.com/iNPUTmice/6c56f3e948cca517c5fb129016d99e74 . I have used it for my implementation. This implementation reuses work done on Jingle A/V call (notably XEP-0176 and XEP-0167 plugins), with adaptations. When used, XEP-0234 will not handle the file itself as it normally does. This is because WebRTC has several implementations (browser for web interface, GStreamer for others), and file/data must be handled directly by the frontend. This is particularly important for web frontends, as the file is not sent from the backend but from the end-user's browser device. Among the changes, there are: - XEP-0343 implementation. - `file_send` bridge method now use serialised dict as output. - New `BaseTransportHandler.is_usable` method which get content data and returns a boolean (default to `True`) to tell if this transport can actually be used in this context (when we are initiator). Used in webRTC case to see if call data are available. - Support of `application` media type, and everything necessary to handle data channels. - Better confirmation message, with file name, size and description when available. - When file is accepted in preflight, it is specified in following `action_new` signal for actual file transfer. This way, frontend can avoid the display or 2 confirmation messages. - XEP-0166: when not specified, default `content` name is now its index number instead of a UUID. This follows the behaviour of browsers. - XEP-0353: better handling of events such as call taken by another device. - various other updates. rel 441
author Goffi <goffi@goffi.org>
date Sat, 06 Apr 2024 12:57:23 +0200
parents 4b842c1fb686
children
line wrap: on
line source

#!/usr/bin/env python3


# Libervia: an XMPP client
# Copyright (C) 2009-2021 Jérôme Poisson (goffi@goffi.org)

# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 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 Affero General Public License for more details.

# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

from libervia.backend.bridge.bridge_constructor import base_constructor
from xml.dom import minidom
import sys


class DbusXmlConstructor(base_constructor.Constructor):
    """Constructor for DBus XML syntaxt (used by Qt frontend)"""

    def __init__(self, bridge_template, options):
        base_constructor.Constructor.__init__(self, bridge_template, options)

        self.template = "dbus_xml_template.xml"
        self.core_dest = "org.libervia.sat.xml"
        self.default_annotation = {
            "a{ss}": "StringDict",
            "a(sa{ss}as)": "QList<Contact>",
            "a{i(ss)}": "HistoryT",
            "a(sss)": "QList<MenuT>",
            "a{sa{s(sia{ss})}}": "PresenceStatusT",
        }

    def generate_core_side(self):
        try:
            doc = minidom.parse(self.get_template_path(self.template))
            interface_elt = doc.getElementsByTagName("interface")[0]
        except IOError:
            print("Can't access template")
            sys.exit(1)
        except IndexError:
            print("Template error")
            sys.exit(1)

        sections = self.bridge_template.sections()
        sections.sort()
        for section in sections:
            function = self.getValues(section)
            print(("Adding %s %s" % (section, function["type"])))
            new_elt = doc.createElement(
                "method" if function["type"] == "method" else "signal"
            )
            new_elt.setAttribute("name", section)

            idx = 0
            args_doc = self.get_arguments_doc(section)
            for arg in self.arguments_parser(function["sig_in"] or ""):
                arg_elt = doc.createElement("arg")
                arg_elt.setAttribute(
                    "name", args_doc[idx][0] if idx in args_doc else "arg_%i" % idx
                )
                arg_elt.setAttribute("type", arg)
                _direction = "in" if function["type"] == "method" else "out"
                arg_elt.setAttribute("direction", _direction)
                new_elt.appendChild(arg_elt)
                if "annotation" in self.args.flags:
                    if arg in self.default_annotation:
                        annot_elt = doc.createElement("annotation")
                        annot_elt.setAttribute(
                            "name", "com.trolltech.QtDBus.QtTypeName.In%d" % idx
                        )
                        annot_elt.setAttribute("value", self.default_annotation[arg])
                        new_elt.appendChild(annot_elt)
                idx += 1

            if function["sig_out"]:
                arg_elt = doc.createElement("arg")
                arg_elt.setAttribute("type", function["sig_out"])
                arg_elt.setAttribute("direction", "out")
                new_elt.appendChild(arg_elt)
                if "annotation" in self.args.flags:
                    if function["sig_out"] in self.default_annotation:
                        annot_elt = doc.createElement("annotation")
                        annot_elt.setAttribute(
                            "name", "com.trolltech.QtDBus.QtTypeName.Out0"
                        )
                        annot_elt.setAttribute(
                            "value", self.default_annotation[function["sig_out"]]
                        )
                        new_elt.appendChild(annot_elt)

            interface_elt.appendChild(new_elt)

        # now we write to final file
        self.final_write(self.core_dest, [doc.toprettyxml()])