Mercurial > libervia-backend
diff libervia/backend/plugins/plugin_misc_file.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 diff
--- a/libervia/backend/plugins/plugin_misc_file.py Sat Apr 06 12:21:04 2024 +0200 +++ b/libervia/backend/plugins/plugin_misc_file.py Sat Apr 06 12:57:23 2024 +0200 @@ -17,15 +17,19 @@ # 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 functools import partial import os import os.path -from functools import partial +from pathlib import Path + from twisted.internet import defer from twisted.words.protocols.jabber import jid -from libervia.backend.core.i18n import _, D_ + +from libervia.backend.core import exceptions from libervia.backend.core.constants import Const as C +from libervia.backend.core.core_types import SatXMPPEntity +from libervia.backend.core.i18n import D_, _ from libervia.backend.core.log import getLogger -from libervia.backend.core import exceptions from libervia.backend.tools import xml_tools from libervia.backend.tools import stream from libervia.backend.tools import utils @@ -73,7 +77,7 @@ "file_send", ".plugin", in_sign="ssssss", - out_sign="a{ss}", + out_sign="s", method=self._file_send, async_=True, ) @@ -96,31 +100,40 @@ profile: str = C.PROF_KEY_NONE ) -> defer.Deferred: client = self.host.get_client(profile) - return defer.ensureDeferred(self.file_send( + d = defer.ensureDeferred(self.file_send( client, jid.JID(peer_jid_s), filepath, name or None, file_desc or None, data_format.deserialise(extra_s) )) + d.addCallback(data_format.serialise) + return d async def file_send( - self, client, peer_jid, filepath, filename=None, file_desc=None, extra=None - ): + self, + client: SatXMPPEntity, + peer_jid: jid.JID, + filepath: str|Path, + filename: str|None=None, + file_desc: str|None=None, + extra: dict|None=None + ) -> dict: """Send a file using best available method - @param peer_jid(jid.JID): jid of the destinee - @param filepath(str): absolute path to the file - @param filename(unicode, None): name to use, or None to find it from filepath - @param file_desc(unicode, None): description of the file + @param peer_jid: jid of the destinee + @param filepath: absolute path to the file + @param filename: name to use, or None to find it from filepath + @param file_desc: description of the file @param profile: %(doc_profile)s - @return (dict): action dictionary, with progress id in case of success, else + @return: action dictionary, with progress id in case of success, else xmlui message """ - if not os.path.isfile(filepath): + filepath = Path(filepath) + if not filepath.is_file(): raise exceptions.DataError("The given path doesn't link to a file") if not filename: - filename = os.path.basename(filepath) or "_" - for manager, priority in self._file_managers: + filename = filepath.name + for manager, __ in self._file_managers: if await utils.as_deferred(manager.can_handle_file_send, - client, peer_jid, filepath): + client, peer_jid, str(filepath)): try: method_name = manager.name except AttributeError: @@ -131,8 +144,8 @@ ) ) try: - progress_id = await utils.as_deferred( - manager.file_send, client, peer_jid, filepath, filename, file_desc, + file_data= await utils.as_deferred( + manager.file_send, client, peer_jid, str(filepath), filename, file_desc, extra ) except Exception as e: @@ -146,7 +159,11 @@ ) ) continue - return {"progress": progress_id} + if "progress" not in file_data: + raise exceptions.InternalError( + '"progress" should be set in "file_send" returned file data dict.' + ) + return file_data msg = "Can't find any method to send file to {jid}".format(jid=peer_jid.full()) log.warning(msg) return {