Search in sources :

Example 1 with GenericTransportInfo

use of eu.siacs.conversations.xmpp.jingle.stanzas.GenericTransportInfo in project Conversations by siacs.

the class JingleFileTransferConnection method receiveAccept.

private void receiveAccept(JinglePacket packet) {
    if (responding()) {
        Log.d(Config.LOGTAG, id.account.getJid().asBareJid() + ": received out of order session-accept (we were responding)");
        respondToIqWithOutOfOrder(packet);
        return;
    }
    if (this.mJingleStatus != JINGLE_STATUS_INITIATED) {
        Log.d(Config.LOGTAG, id.account.getJid().asBareJid() + ": received out of order session-accept");
        respondToIqWithOutOfOrder(packet);
        return;
    }
    this.mJingleStatus = JINGLE_STATUS_ACCEPTED;
    xmppConnectionService.markMessage(message, Message.STATUS_UNSEND);
    final Content content = packet.getJingleContent();
    final GenericTransportInfo transportInfo = content.getTransport();
    // TODO we want to fail if transportInfo doesn’t match our intialTransport and/or our id
    if (transportInfo instanceof S5BTransportInfo) {
        final S5BTransportInfo s5BTransportInfo = (S5BTransportInfo) transportInfo;
        respondToIq(packet, true);
        // TODO calling merge is probably a bug because that might eliminate candidates of the other party and lead to us not sending accept/deny
        // TODO: we probably just want to call add
        mergeCandidates(s5BTransportInfo.getCandidates());
        this.connectNextCandidate();
    } else if (transportInfo instanceof IbbTransportInfo) {
        final IbbTransportInfo ibbTransportInfo = (IbbTransportInfo) transportInfo;
        final int remoteBlockSize = ibbTransportInfo.getBlockSize();
        if (remoteBlockSize > 0) {
            this.ibbBlockSize = Math.min(ibbBlockSize, remoteBlockSize);
        }
        respondToIq(packet, true);
        this.transport = new JingleInBandTransport(this, this.transportId, this.ibbBlockSize);
        this.transport.connect(onIbbTransportConnected);
    } else {
        respondToIq(packet, false);
    }
}
Also used : Content(eu.siacs.conversations.xmpp.jingle.stanzas.Content) GenericTransportInfo(eu.siacs.conversations.xmpp.jingle.stanzas.GenericTransportInfo) S5BTransportInfo(eu.siacs.conversations.xmpp.jingle.stanzas.S5BTransportInfo) IbbTransportInfo(eu.siacs.conversations.xmpp.jingle.stanzas.IbbTransportInfo)

Example 2 with GenericTransportInfo

use of eu.siacs.conversations.xmpp.jingle.stanzas.GenericTransportInfo in project Conversations by siacs.

the class JingleFileTransferConnection method receiveTransportAccept.

private void receiveTransportAccept(JinglePacket packet) {
    if (responding()) {
        Log.d(Config.LOGTAG, id.account.getJid().asBareJid() + ": received out of order transport-accept (we were responding)");
        respondToIqWithOutOfOrder(packet);
        return;
    }
    final boolean validState = mJingleStatus == JINGLE_STATUS_ACCEPTED || (proxyActivationFailed && mJingleStatus == JINGLE_STATUS_TRANSMITTING);
    if (!validState) {
        Log.d(Config.LOGTAG, id.account.getJid().asBareJid() + ": received out of order transport-accept");
        respondToIqWithOutOfOrder(packet);
        return;
    }
    // fallback accepted; now we no longer need to accept another one;
    this.proxyActivationFailed = false;
    final Content content = packet.getJingleContent();
    final GenericTransportInfo transportInfo = content == null ? null : content.getTransport();
    if (transportInfo instanceof IbbTransportInfo) {
        final IbbTransportInfo ibbTransportInfo = (IbbTransportInfo) transportInfo;
        final int remoteBlockSize = ibbTransportInfo.getBlockSize();
        if (remoteBlockSize > 0) {
            this.ibbBlockSize = Math.min(MAX_IBB_BLOCK_SIZE, remoteBlockSize);
        }
        final String sid = ibbTransportInfo.getTransportId();
        this.transport = new JingleInBandTransport(this, this.transportId, this.ibbBlockSize);
        if (sid == null || !sid.equals(this.transportId)) {
            Log.w(Config.LOGTAG, String.format("%s: sid in transport-accept (%s) did not match our sid (%s) ", id.account.getJid().asBareJid(), sid, transportId));
        }
        respondToIq(packet, true);
        // might be receive instead if we are not initiating
        if (isInitiator()) {
            this.transport.connect(onIbbTransportConnected);
        }
    } else {
        Log.d(Config.LOGTAG, id.account.getJid().asBareJid() + ": received invalid transport-accept");
        respondToIq(packet, false);
    }
}
Also used : Content(eu.siacs.conversations.xmpp.jingle.stanzas.Content) GenericTransportInfo(eu.siacs.conversations.xmpp.jingle.stanzas.GenericTransportInfo) IbbTransportInfo(eu.siacs.conversations.xmpp.jingle.stanzas.IbbTransportInfo)

Example 3 with GenericTransportInfo

use of eu.siacs.conversations.xmpp.jingle.stanzas.GenericTransportInfo in project Conversations by siacs.

the class JingleFileTransferConnection method receiveTransportInfo.

private void receiveTransportInfo(JinglePacket packet) {
    final Content content = packet.getJingleContent();
    final GenericTransportInfo transportInfo = content.getTransport();
    if (transportInfo instanceof S5BTransportInfo) {
        final S5BTransportInfo s5BTransportInfo = (S5BTransportInfo) transportInfo;
        if (s5BTransportInfo.hasChild("activated")) {
            respondToIq(packet, true);
            if ((this.transport != null) && (this.transport instanceof JingleSocks5Transport)) {
                onProxyActivated.success();
            } else {
                String cid = s5BTransportInfo.findChild("activated").getAttribute("cid");
                Log.d(Config.LOGTAG, "received proxy activated (" + cid + ")prior to choosing our own transport");
                JingleSocks5Transport connection = this.connections.get(cid);
                if (connection != null) {
                    connection.setActivated(true);
                } else {
                    Log.d(Config.LOGTAG, "activated connection not found");
                    sendSessionTerminate(Reason.FAILED_TRANSPORT);
                    this.fail();
                }
            }
        } else if (s5BTransportInfo.hasChild("proxy-error")) {
            respondToIq(packet, true);
            onProxyActivated.failed();
        } else if (s5BTransportInfo.hasChild("candidate-error")) {
            Log.d(Config.LOGTAG, id.account.getJid().asBareJid() + ": received candidate error");
            respondToIq(packet, true);
            this.receivedCandidate = true;
            if (mJingleStatus == JINGLE_STATUS_ACCEPTED && this.sentCandidate) {
                this.connect();
            }
        } else if (s5BTransportInfo.hasChild("candidate-used")) {
            String cid = s5BTransportInfo.findChild("candidate-used").getAttribute("cid");
            if (cid != null) {
                Log.d(Config.LOGTAG, "candidate used by counterpart:" + cid);
                JingleCandidate candidate = getCandidate(cid);
                if (candidate == null) {
                    Log.d(Config.LOGTAG, "could not find candidate with cid=" + cid);
                    respondToIq(packet, false);
                    return;
                }
                respondToIq(packet, true);
                candidate.flagAsUsedByCounterpart();
                this.receivedCandidate = true;
                if (mJingleStatus == JINGLE_STATUS_ACCEPTED && this.sentCandidate) {
                    this.connect();
                } else {
                    Log.d(Config.LOGTAG, "ignoring because file is already in transmission or we haven't sent our candidate yet status=" + mJingleStatus + " sentCandidate=" + sentCandidate);
                }
            } else {
                respondToIq(packet, false);
            }
        } else {
            respondToIq(packet, false);
        }
    } else {
        respondToIq(packet, true);
    }
}
Also used : Content(eu.siacs.conversations.xmpp.jingle.stanzas.Content) GenericTransportInfo(eu.siacs.conversations.xmpp.jingle.stanzas.GenericTransportInfo) S5BTransportInfo(eu.siacs.conversations.xmpp.jingle.stanzas.S5BTransportInfo)

Example 4 with GenericTransportInfo

use of eu.siacs.conversations.xmpp.jingle.stanzas.GenericTransportInfo in project Conversations by siacs.

the class JingleFileTransferConnection method init.

private void init(JinglePacket packet) {
    // should move to deliverPacket
    // TODO if not 'OFFERED' reply with out-of-order
    this.mJingleStatus = JINGLE_STATUS_INITIATED;
    final Conversation conversation = this.xmppConnectionService.findOrCreateConversation(id.account, id.with.asBareJid(), false, false);
    this.message = new Message(conversation, "", Message.ENCRYPTION_NONE);
    this.message.setStatus(Message.STATUS_RECEIVED);
    this.mStatus = Transferable.STATUS_OFFER;
    this.message.setTransferable(this);
    this.message.setCounterpart(this.id.with);
    this.responder = this.id.account.getJid();
    final Content content = packet.getJingleContent();
    final GenericTransportInfo transportInfo = content.getTransport();
    this.contentCreator = content.getCreator();
    Content.Senders senders;
    try {
        senders = content.getSenders();
    } catch (final Exception e) {
        senders = Content.Senders.INITIATOR;
    }
    this.contentSenders = senders;
    this.contentName = content.getAttribute("name");
    if (transportInfo instanceof S5BTransportInfo) {
        final S5BTransportInfo s5BTransportInfo = (S5BTransportInfo) transportInfo;
        this.transportId = s5BTransportInfo.getTransportId();
        this.initialTransport = s5BTransportInfo.getClass();
        this.mergeCandidates(s5BTransportInfo.getCandidates());
    } else if (transportInfo instanceof IbbTransportInfo) {
        final IbbTransportInfo ibbTransportInfo = (IbbTransportInfo) transportInfo;
        this.initialTransport = ibbTransportInfo.getClass();
        this.transportId = ibbTransportInfo.getTransportId();
        final int remoteBlockSize = ibbTransportInfo.getBlockSize();
        if (remoteBlockSize <= 0) {
            Log.d(Config.LOGTAG, id.account.getJid().asBareJid() + ": remote party requested invalid ibb block size");
            respondToIq(packet, false);
            this.fail();
        }
        this.ibbBlockSize = Math.min(MAX_IBB_BLOCK_SIZE, ibbTransportInfo.getBlockSize());
    } else {
        Log.d(Config.LOGTAG, id.account.getJid().asBareJid() + ": remote tried to use unknown transport " + transportInfo.getNamespace());
        respondToIq(packet, false);
        this.fail();
        return;
    }
    this.description = (FileTransferDescription) content.getDescription();
    final Element fileOffer = this.description.getFileOffer();
    if (fileOffer != null) {
        boolean remoteIsUsingJet = false;
        Element encrypted = fileOffer.findChild("encrypted", AxolotlService.PEP_PREFIX);
        if (encrypted == null) {
            final Element security = content.findChild("security", Namespace.JINGLE_ENCRYPTED_TRANSPORT);
            if (security != null && AxolotlService.PEP_PREFIX.equals(security.getAttribute("type"))) {
                Log.d(Config.LOGTAG, id.account.getJid().asBareJid() + ": received jingle file offer with JET");
                encrypted = security.findChild("encrypted", AxolotlService.PEP_PREFIX);
                remoteIsUsingJet = true;
            }
        }
        if (encrypted != null) {
            this.mXmppAxolotlMessage = XmppAxolotlMessage.fromElement(encrypted, packet.getFrom().asBareJid());
        }
        Element fileSize = fileOffer.findChild("size");
        final String path = fileOffer.findChildContent("name");
        if (path != null) {
            AbstractConnectionManager.Extension extension = AbstractConnectionManager.Extension.of(path);
            if (VALID_IMAGE_EXTENSIONS.contains(extension.main)) {
                message.setType(Message.TYPE_IMAGE);
                message.setRelativeFilePath(message.getUuid() + "." + extension.main);
            } else if (VALID_CRYPTO_EXTENSIONS.contains(extension.main)) {
                if (VALID_IMAGE_EXTENSIONS.contains(extension.secondary)) {
                    message.setType(Message.TYPE_IMAGE);
                    message.setRelativeFilePath(message.getUuid() + "." + extension.secondary);
                } else {
                    message.setType(Message.TYPE_FILE);
                    message.setRelativeFilePath(message.getUuid() + (extension.secondary != null ? ("." + extension.secondary) : ""));
                }
                message.setEncryption(Message.ENCRYPTION_PGP);
            } else {
                message.setType(Message.TYPE_FILE);
                message.setRelativeFilePath(message.getUuid() + (extension.main != null ? ("." + extension.main) : ""));
            }
            long size = parseLong(fileSize, 0);
            message.setBody(Long.toString(size));
            conversation.add(message);
            jingleConnectionManager.updateConversationUi(true);
            this.file = this.xmppConnectionService.getFileBackend().getFile(message, false);
            if (mXmppAxolotlMessage != null) {
                XmppAxolotlMessage.XmppAxolotlKeyTransportMessage transportMessage = id.account.getAxolotlService().processReceivingKeyTransportMessage(mXmppAxolotlMessage, false);
                if (transportMessage != null) {
                    message.setEncryption(Message.ENCRYPTION_AXOLOTL);
                    this.file.setKey(transportMessage.getKey());
                    this.file.setIv(transportMessage.getIv());
                    message.setFingerprint(transportMessage.getFingerprint());
                } else {
                    Log.d(Config.LOGTAG, "could not process KeyTransportMessage");
                }
            }
            message.resetFileParams();
            // legacy OMEMO encrypted file transfers reported the file size after encryption
            // JET reports the plain text size. however lower levels of our receiving code still
            // expect the cipher text size. so we just + 16 bytes (auth tag size) here
            this.file.setExpectedSize(size + (remoteIsUsingJet ? 16 : 0));
            respondToIq(packet, true);
            if (id.account.getRoster().getContact(id.with).showInContactList() && jingleConnectionManager.hasStoragePermission() && size < this.jingleConnectionManager.getAutoAcceptFileSize() && xmppConnectionService.isDataSaverDisabled()) {
                Log.d(Config.LOGTAG, "auto accepting file from " + id.with);
                this.acceptedAutomatically = true;
                this.sendAccept();
            } else {
                message.markUnread();
                Log.d(Config.LOGTAG, "not auto accepting new file offer with size: " + size + " allowed size:" + this.jingleConnectionManager.getAutoAcceptFileSize());
                this.xmppConnectionService.getNotificationService().push(message);
            }
            Log.d(Config.LOGTAG, "receiving file: expecting size of " + this.file.getExpectedSize());
            return;
        }
        respondToIq(packet, false);
    }
}
Also used : XmppAxolotlMessage(eu.siacs.conversations.crypto.axolotl.XmppAxolotlMessage) Message(eu.siacs.conversations.entities.Message) Element(eu.siacs.conversations.xml.Element) Conversation(eu.siacs.conversations.entities.Conversation) AbstractConnectionManager(eu.siacs.conversations.services.AbstractConnectionManager) XmppAxolotlMessage(eu.siacs.conversations.crypto.axolotl.XmppAxolotlMessage) IOException(java.io.IOException) FileNotFoundException(java.io.FileNotFoundException) S5BTransportInfo(eu.siacs.conversations.xmpp.jingle.stanzas.S5BTransportInfo) Content(eu.siacs.conversations.xmpp.jingle.stanzas.Content) GenericTransportInfo(eu.siacs.conversations.xmpp.jingle.stanzas.GenericTransportInfo) IbbTransportInfo(eu.siacs.conversations.xmpp.jingle.stanzas.IbbTransportInfo)

Aggregations

Content (eu.siacs.conversations.xmpp.jingle.stanzas.Content)4 GenericTransportInfo (eu.siacs.conversations.xmpp.jingle.stanzas.GenericTransportInfo)4 IbbTransportInfo (eu.siacs.conversations.xmpp.jingle.stanzas.IbbTransportInfo)3 S5BTransportInfo (eu.siacs.conversations.xmpp.jingle.stanzas.S5BTransportInfo)3 XmppAxolotlMessage (eu.siacs.conversations.crypto.axolotl.XmppAxolotlMessage)1 Conversation (eu.siacs.conversations.entities.Conversation)1 Message (eu.siacs.conversations.entities.Message)1 AbstractConnectionManager (eu.siacs.conversations.services.AbstractConnectionManager)1 Element (eu.siacs.conversations.xml.Element)1 FileNotFoundException (java.io.FileNotFoundException)1 IOException (java.io.IOException)1