Search in sources :

Example 11 with Content

use of eu.siacs.conversations.xmpp.jingle.stanzas.Content 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 12 with Content

use of eu.siacs.conversations.xmpp.jingle.stanzas.Content 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 13 with Content

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

the class JingleConnection method init.

public void init(Account account, JinglePacket packet) {
    this.mJingleStatus = JINGLE_STATUS_INITIATED;
    Conversation conversation = this.mXmppConnectionService.findOrCreateConversation(account, packet.getFrom().toBareJid(), false);
    this.message = new Message(conversation, "", Message.ENCRYPTION_NONE);
    this.message.setStatus(Message.STATUS_RECEIVED);
    this.mStatus = Transferable.STATUS_OFFER;
    this.message.setTransferable(this);
    final Jid from = packet.getFrom();
    this.message.setCounterpart(from);
    this.account = account;
    this.initiator = packet.getFrom();
    this.responder = this.account.getJid();
    this.sessionId = packet.getSessionId();
    Content content = packet.getJingleContent();
    this.contentCreator = content.getAttribute("creator");
    this.contentName = content.getAttribute("name");
    this.transportId = content.getTransportId();
    this.mergeCandidates(JingleCandidate.parse(content.socks5transport().getChildren()));
    this.ftVersion = content.getVersion();
    if (ftVersion == null) {
        this.sendCancel();
        this.fail();
        return;
    }
    this.fileOffer = content.getFileOffer(this.ftVersion);
    mXmppConnectionService.sendIqPacket(account, packet.generateResponse(IqPacket.TYPE.RESULT), null);
    if (fileOffer != null) {
        Element encrypted = fileOffer.findChild("encrypted", AxolotlService.PEP_PREFIX);
        if (encrypted != null) {
            this.mXmppAxolotlMessage = XmppAxolotlMessage.fromElement(encrypted, packet.getFrom().toBareJid());
        }
        Element fileSize = fileOffer.findChild("size");
        Element fileNameElement = fileOffer.findChild("name");
        if (fileNameElement != null) {
            String[] filename = fileNameElement.getContent().toLowerCase(Locale.US).toLowerCase().split("\\.");
            String extension = filename[filename.length - 1];
            if (VALID_IMAGE_EXTENSIONS.contains(extension)) {
                message.setType(Message.TYPE_IMAGE);
                message.setRelativeFilePath(message.getUuid() + "." + extension);
            } else if (VALID_CRYPTO_EXTENSIONS.contains(filename[filename.length - 1])) {
                if (filename.length == 3) {
                    extension = filename[filename.length - 2];
                    if (VALID_IMAGE_EXTENSIONS.contains(extension)) {
                        message.setType(Message.TYPE_IMAGE);
                        message.setRelativeFilePath(message.getUuid() + "." + extension);
                    } else {
                        message.setType(Message.TYPE_FILE);
                    }
                    if (filename[filename.length - 1].equals("otr")) {
                        message.setEncryption(Message.ENCRYPTION_OTR);
                    } else {
                        message.setEncryption(Message.ENCRYPTION_PGP);
                    }
                }
            } else {
                message.setType(Message.TYPE_FILE);
            }
            if (message.getType() == Message.TYPE_FILE) {
                String suffix = "";
                if (!fileNameElement.getContent().isEmpty()) {
                    String[] parts = fileNameElement.getContent().split("/");
                    suffix = parts[parts.length - 1];
                    if (message.getEncryption() == Message.ENCRYPTION_OTR && suffix.endsWith(".otr")) {
                        suffix = suffix.substring(0, suffix.length() - 4);
                    } else if (message.getEncryption() == Message.ENCRYPTION_PGP && (suffix.endsWith(".pgp") || suffix.endsWith(".gpg"))) {
                        suffix = suffix.substring(0, suffix.length() - 4);
                    }
                }
                message.setRelativeFilePath(message.getUuid() + "_" + suffix);
            }
            long size = Long.parseLong(fileSize.getContent());
            message.setBody(Long.toString(size));
            conversation.add(message);
            mJingleConnectionManager.updateConversationUi(true);
            if (mJingleConnectionManager.hasStoragePermission() && size < this.mJingleConnectionManager.getAutoAcceptFileSize() && mXmppConnectionService.isDataSaverDisabled()) {
                Log.d(Config.LOGTAG, "auto accepting file from " + packet.getFrom());
                this.acceptedAutomatically = true;
                this.sendAccept();
            } else {
                message.markUnread();
                Log.d(Config.LOGTAG, "not auto accepting new file offer with size: " + size + " allowed size:" + this.mJingleConnectionManager.getAutoAcceptFileSize());
                this.mXmppConnectionService.getNotificationService().push(message);
            }
            this.file = this.mXmppConnectionService.getFileBackend().getFile(message, false);
            if (mXmppAxolotlMessage != null) {
                XmppAxolotlMessage.XmppAxolotlKeyTransportMessage transportMessage = account.getAxolotlService().processReceivingKeyTransportMessage(mXmppAxolotlMessage);
                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");
                }
            } else if (message.getEncryption() == Message.ENCRYPTION_OTR) {
                byte[] key = conversation.getSymmetricKey();
                if (key == null) {
                    this.sendCancel();
                    this.fail();
                    return;
                } else {
                    this.file.setKeyAndIv(key);
                }
            }
            this.mFileOutputStream = AbstractConnectionManager.createOutputStream(this.file, message.getEncryption() == Message.ENCRYPTION_AXOLOTL);
            if (message.getEncryption() == Message.ENCRYPTION_OTR && Config.REPORT_WRONG_FILESIZE_IN_OTR_JINGLE) {
                this.file.setExpectedSize((size / 16 + 1) * 16);
            } else {
                this.file.setExpectedSize(size);
            }
            Log.d(Config.LOGTAG, "receiving file: expecting size of " + this.file.getExpectedSize());
        } else {
            this.sendCancel();
            this.fail();
        }
    } else {
        this.sendCancel();
        this.fail();
    }
}
Also used : XmppAxolotlMessage(eu.siacs.conversations.crypto.axolotl.XmppAxolotlMessage) Message(eu.siacs.conversations.entities.Message) Jid(eu.siacs.conversations.xmpp.jid.Jid) Content(eu.siacs.conversations.xmpp.jingle.stanzas.Content) Element(eu.siacs.conversations.xml.Element) Conversation(eu.siacs.conversations.entities.Conversation) XmppAxolotlMessage(eu.siacs.conversations.crypto.axolotl.XmppAxolotlMessage)

Example 14 with Content

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

the class JingleConnection method sendInitRequest.

private void sendInitRequest() {
    JinglePacket packet = this.bootstrapPacket("session-initiate");
    Content content = new Content(this.contentCreator, this.contentName);
    if (message.getType() == Message.TYPE_IMAGE || message.getType() == Message.TYPE_FILE) {
        content.setTransportId(this.transportId);
        this.file = this.mXmppConnectionService.getFileBackend().getFile(message, false);
        Pair<InputStream, Integer> pair;
        try {
            if (message.getEncryption() == Message.ENCRYPTION_OTR) {
                Conversation conversation = this.message.getConversation();
                if (!this.mXmppConnectionService.renewSymmetricKey(conversation)) {
                    Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": could not set symmetric key");
                    cancel();
                }
                this.file.setKeyAndIv(conversation.getSymmetricKey());
                pair = AbstractConnectionManager.createInputStream(this.file, false);
                this.file.setExpectedSize(pair.second);
                content.setFileOffer(this.file, true, this.ftVersion);
            } else if (message.getEncryption() == Message.ENCRYPTION_AXOLOTL) {
                this.file.setKey(mXmppAxolotlMessage.getInnerKey());
                this.file.setIv(mXmppAxolotlMessage.getIV());
                pair = AbstractConnectionManager.createInputStream(this.file, true);
                this.file.setExpectedSize(pair.second);
                content.setFileOffer(this.file, false, this.ftVersion).addChild(mXmppAxolotlMessage.toElement());
            } else {
                pair = AbstractConnectionManager.createInputStream(this.file, false);
                this.file.setExpectedSize(pair.second);
                content.setFileOffer(this.file, false, this.ftVersion);
            }
        } catch (FileNotFoundException e) {
            cancel();
            return;
        }
        this.mFileInputStream = pair.first;
        content.setTransportId(this.transportId);
        content.socks5transport().setChildren(getCandidatesAsElements());
        packet.setContent(content);
        this.sendJinglePacket(packet, new OnIqPacketReceived() {

            @Override
            public void onIqPacketReceived(Account account, IqPacket packet) {
                if (packet.getType() == IqPacket.TYPE.RESULT) {
                    Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": other party received offer");
                    mJingleStatus = JINGLE_STATUS_INITIATED;
                    mXmppConnectionService.markMessage(message, Message.STATUS_OFFERED);
                } else {
                    fail(IqParser.extractErrorMessage(packet));
                }
            }
        });
    }
}
Also used : Account(eu.siacs.conversations.entities.Account) JinglePacket(eu.siacs.conversations.xmpp.jingle.stanzas.JinglePacket) OnIqPacketReceived(eu.siacs.conversations.xmpp.OnIqPacketReceived) Content(eu.siacs.conversations.xmpp.jingle.stanzas.Content) InputStream(java.io.InputStream) FileNotFoundException(java.io.FileNotFoundException) Conversation(eu.siacs.conversations.entities.Conversation) IqPacket(eu.siacs.conversations.xmpp.stanzas.IqPacket)

Example 15 with Content

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

the class JingleConnection method sendCandidateUsed.

private void sendCandidateUsed(final String cid) {
    JinglePacket packet = bootstrapPacket("transport-info");
    Content content = new Content(this.contentCreator, this.contentName);
    content.setTransportId(this.transportId);
    content.socks5transport().addChild("candidate-used").setAttribute("cid", cid);
    packet.setContent(content);
    this.sentCandidate = true;
    if ((receivedCandidate) && (mJingleStatus == JINGLE_STATUS_ACCEPTED)) {
        connect();
    }
    this.sendJinglePacket(packet);
}
Also used : JinglePacket(eu.siacs.conversations.xmpp.jingle.stanzas.JinglePacket) Content(eu.siacs.conversations.xmpp.jingle.stanzas.Content)

Aggregations

Content (eu.siacs.conversations.xmpp.jingle.stanzas.Content)25 JinglePacket (eu.siacs.conversations.xmpp.jingle.stanzas.JinglePacket)18 S5BTransportInfo (eu.siacs.conversations.xmpp.jingle.stanzas.S5BTransportInfo)9 Element (eu.siacs.conversations.xml.Element)7 IbbTransportInfo (eu.siacs.conversations.xmpp.jingle.stanzas.IbbTransportInfo)7 GenericTransportInfo (eu.siacs.conversations.xmpp.jingle.stanzas.GenericTransportInfo)4 Conversation (eu.siacs.conversations.entities.Conversation)3 FileNotFoundException (java.io.FileNotFoundException)3 XmppAxolotlMessage (eu.siacs.conversations.crypto.axolotl.XmppAxolotlMessage)2 Account (eu.siacs.conversations.entities.Account)2 Message (eu.siacs.conversations.entities.Message)2 OnIqPacketReceived (eu.siacs.conversations.xmpp.OnIqPacketReceived)2 IqPacket (eu.siacs.conversations.xmpp.stanzas.IqPacket)2 ImmutableMap (com.google.common.collect.ImmutableMap)1 AbstractConnectionManager (eu.siacs.conversations.services.AbstractConnectionManager)1 Jid (eu.siacs.conversations.xmpp.Jid)1 Jid (eu.siacs.conversations.xmpp.jid.Jid)1 FileInputStream (java.io.FileInputStream)1 IOException (java.io.IOException)1 InputStream (java.io.InputStream)1