Smack 4.4. FaultToleranceNegotiator for Sock5ByteStream file transfer with IBB fall-back implementation error

aTalk has implemented Sock5ByteStream file transfer; but would like to have IBB fall-back on failure.
Base on the Smack 4.4.0-alpha2-SNAPSHOT implementation (see captured log), it is found that smack actually auto start the IBB Initiation request protocol when it detects Sock5ByteStream failure.

Not sure if there is an option to set at the start of the file transfer negotiation to get smack to handle everything i.e. fall-back to IBB on failure to continue receive the file. Otherwise, what are the proper steps require to get aTalk to accept IBB Initiation request to continue receive the file. Any help is much appreciated.

2018-12-07 17:14:13.742 15557-16149/org.atalk.android D/SMACK: RECV (0): <iq xml:lang='en' to='swordfish@atalk.org/atalk' from='leopard@atalk.org/atalk' type='set' id='2fuCV-190'><si xmlns='http://jabber.org/protocol/si' id='jsi_509263050' mime-type='image/png' profile='http://jabber.org/protocol/si/profile/file-transfer'><file xmlns='http://jabber.org/protocol/si/profile/file-transfer' name='586431100-1.png' size='39315'><thumbnail xmlns='urn:xmpp:thumbs:0' cid='sha1+7b6f3cd32d439be60af27841c2890b4395aca994@atalk.org' mime-type='image/png' width='64' height='64'/></file><feature xmlns='http://jabber.org/protocol/feature-neg'><x xmlns='jabber:x:data' type='form'><field var='stream-method' type='list-single'><option><value>http://jabber.org/protocol/bytestreams</value></option><option><value>http://jabber.org/protocol/ibb</value></option></field></x></feature></si></iq>
2018-12-07 17:14:15.095 15557-16148/org.atalk.android D/SMACK: SENT (0): <iq to='leopard@atalk.org/atalk' id='2fuCV-190' type='result'><si xmlns='http://jabber.org/protocol/si'><feature xmlns="http://jabber.org/protocol/feature-neg"><x xmlns='jabber:x:data' type='submit'><field var='stream-method'><value>http://jabber.org/protocol/bytestreams</value><value>http://jabber.org/protocol/ibb</value></field></x></feature></si></iq>
2018-12-07 17:14:15.250 15557-16149/org.atalk.android D/SMACK: RECV (0): <iq xml:lang='en' to='swordfish@atalk.org/atalk' from='leopard@atalk.org/atalk' type='set' id='2fuCV-195'><query xmlns='http://jabber.org/protocol/bytestreams' sid='jsi_509263050' mode='tcp'><streamhost jid='leopard@atalk.org/atalk' host='fe80::f025:b7ff:fe9c:3c5%p2p0' port='7777'/><streamhost jid='leopard@atalk.org/atalk' host='fe80::f225:b7ff:fe9c:3c5%wlan0' port='7777'/><streamhost jid='leopard@atalk.org/atalk' host='192.168.1.12' port='7777'/></query></iq>
2018-12-07 17:14:18.616 15557-16148/org.atalk.android D/SMACK: SENT (0): <iq to='leopard@atalk.org/atalk' id='2fuCV-195' type='error'><error type='cancel'><item-not-found xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/><text xml:lang='en'>Could not establish socket with any provided host</text></error></iq>
2018-12-07 17:14:18.634 15557-17528/org.atalk.android E/aTalk: [3669] impl.protocol.jabber.OperationSetFileTransferJabberImpl.run().492 An exception occurred while transferring file: 
     org.jivesoftware.smack.XMPPException$XMPPErrorException: XMPPError: item-not-found - cancel
         at org.jivesoftware.smackx.bytestreams.socks5.Socks5BytestreamRequest.cancelRequest(Socks5BytestreamRequest.java:289)
         at org.jivesoftware.smackx.bytestreams.socks5.Socks5BytestreamRequest.accept(Socks5BytestreamRequest.java:255)
         at org.jivesoftware.smackx.filetransfer.Socks5TransferNegotiator.negotiateIncomingStream(Socks5TransferNegotiator.java:102)
         at org.jivesoftware.smackx.filetransfer.FaultTolerantNegotiator.createIncomingStream(FaultTolerantNegotiator.java:72)
         at org.jivesoftware.smackx.filetransfer.IncomingFileTransfer$2.call(IncomingFileTransfer.java:179)
         at org.jivesoftware.smackx.filetransfer.IncomingFileTransfer$2.call(IncomingFileTransfer.java:174)
         at java.util.concurrent.FutureTask.run(FutureTask.java:266)
         at org.jivesoftware.smackx.filetransfer.IncomingFileTransfer.negotiateStream(IncomingFileTransfer.java:182)
         at org.jivesoftware.smackx.filetransfer.IncomingFileTransfer.access$100(IncomingFileTransfer.java:58)
         at org.jivesoftware.smackx.filetransfer.IncomingFileTransfer$1.run(IncomingFileTransfer.java:132)
         at java.lang.Thread.run(Thread.java:764)
 2018-12-07 17:14:18.824 15557-16149/org.atalk.android D/SMACK: RECV (0): <iq xml:lang='en' to='swordfish@atalk.org/atalk' from='leopard@atalk.org/atalk' type='set' id='2fuCV-197'><open xmlns='http://jabber.org/protocol/ibb' block-size='4096' sid='jsi_509263050' stanza='iq'/></iq>

After more investigation, Smack 4.4 actually implements FaultToleranceNegotiator to support IBB fallback in the event Socks5ByteStream failed due to negotiation error i.e.

<item-not-found xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/><text xml:lang='en'>Could not establish socket with any provided host</text></error></iq>

Under this fault condition, the sender negotiator actually re-initializes with IBB negotiation. However during the Socks5Bytestream negotiation process, it blocks the IBBStreamNegotiation with the following call and the ignoredBytestreamRequests is not clear upon the above fault condition i.e.

    @Override
    public void newStreamInitiation(final Jid from, String streamID) {
        /*
         * this method is always called prior to #negotiateIncomingStream() so the SOCKS5
         * InitiationListener must ignore the next SOCKS5 Bytestream request with the given session
         * ID
         */
        this.manager.ignoreBytestreamRequestOnce(streamID);
    }

aTalk adds an addIncomingBytestreamListener() when detected Socks5Bytestream negotiation error, however it is not being called due to the above blocking. To verify this point, aTalk implements the following patches:

InBandBytestreamManager.patch (969 Bytes)
Socks5BytestreamRequest.patch (1.8 KB)

Below is the debug log with the patch i.e. IBB fallback is working:

2018-12-14 12:28:30.375 22061-22199/org.atalk.android D/SMACK: RECV (0): <iq xml:lang='en' to='swordfish@atalk.org/atalk' from='leopard@atalk.org/atalk' type='set' id='oK7gw-544'><si xmlns='http://jabber.org/protocol/si' id='jsi_-1166856721' mime-type='image/png' profile='http://jabber.org/protocol/si/profile/file-transfer'><file xmlns='http://jabber.org/protocol/si/profile/file-transfer' name='586431100-1.png' size='39315'><thumbnail xmlns='urn:xmpp:thumbs:0' cid='sha1+7b6f3cd32d439be60af27841c2890b4395aca994@bob.xmpp.org' mime-type='image/png' width='64' height='64'/></file><feature xmlns='http://jabber.org/protocol/feature-neg'><x xmlns='jabber:x:data' type='form'><field var='stream-method' type='list-single'><option><value>http://jabber.org/protocol/bytestreams</value></option><option><value>http://jabber.org/protocol/ibb</value></option></field></x></feature></si></iq>

2018-12-14 12:28:32.420 22061-22198/org.atalk.android D/SMACK: SENT (0): <iq to='leopard@atalk.org/atalk' id='oK7gw-544' type='result'><si xmlns='http://jabber.org/protocol/si'><feature xmlns="http://jabber.org/protocol/feature-neg"><x xmlns='jabber:x:data' type='submit'><field var='stream-method'><value>http://jabber.org/protocol/bytestreams</value><value>http://jabber.org/protocol/ibb</value></field></x></feature></si></iq>
2018-12-14 12:28:32.611 22061-22199/org.atalk.android D/SMACK: RECV (0): <iq xml:lang='en' to='swordfish@atalk.org/atalk' from='leopard@atalk.org/atalk' type='set' id='oK7gw-548'><query xmlns='http://jabber.org/protocol/bytestreams' sid='jsi_-1166856721' mode='tcp'><streamhost jid='leopard@atalk.org/atalk' host='fe80::f025:b7ff:fe9c:3c5%p2p0' port='7777'/><streamhost jid='leopard@atalk.org/atalk' host='fe80::f225:b7ff:fe9c:3c5%wlan0' port='7777'/><streamhost jid='leopard@atalk.org/atalk' host='192.168.1.12' port='7777'/></query></iq>
2018-12-14 12:28:35.979 22061-22198/org.atalk.android D/SMACK: SENT (0): <iq to='leopard@atalk.org/atalk' id='oK7gw-548' type='error'><error type='cancel'><item-not-found xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/><text xml:lang='en'>Could not establish socket with any provided host</text></error></iq>
2018-12-14 12:28:35.982 22061-22297/org.atalk.android E/aTalk: [10576] impl.protocol.jabber.OperationSetFileTransferJabberImpl.run().492 An exception occurred while transferring file: 
   org.jivesoftware.smack.XMPPException$XMPPErrorException: XMPPError: item-not-found - cancel
       at org.jivesoftware.smackx.bytestreams.socks5.Socks5BytestreamRequest.cancelRequest(Socks5BytestreamRequest.java:292)
       at org.jivesoftware.smackx.bytestreams.socks5.Socks5BytestreamRequest.accept(Socks5BytestreamRequest.java:256)
       at org.jivesoftware.smackx.filetransfer.Socks5TransferNegotiator.negotiateIncomingStream(Socks5TransferNegotiator.java:102)
       at org.jivesoftware.smackx.filetransfer.FaultTolerantNegotiator.createIncomingStream(FaultTolerantNegotiator.java:72)
       at org.jivesoftware.smackx.filetransfer.IncomingFileTransfer$2.call(IncomingFileTransfer.java:179)
       at org.jivesoftware.smackx.filetransfer.IncomingFileTransfer$2.call(IncomingFileTransfer.java:174)
       at java.util.concurrent.FutureTask.run(FutureTask.java:266)
       at org.jivesoftware.smackx.filetransfer.IncomingFileTransfer.negotiateStream(IncomingFileTransfer.java:182)
       at org.jivesoftware.smackx.filetransfer.IncomingFileTransfer.access$100(IncomingFileTransfer.java:58)
       at org.jivesoftware.smackx.filetransfer.IncomingFileTransfer$1.run(IncomingFileTransfer.java:132)
       at java.lang.Thread.run(Thread.java:764)
2018-12-14 12:28:35.990 22061-22297/org.atalk.android E/aTalk: [10576] org.atalk.android.gui.chat.filetransfer.ReceiveFileConversation.statusChanged().254 Add IBB listener; Error in incoming file transfer: Could not establish socket with any provided host
2018-12-14 12:28:36.212 22061-22199/org.atalk.android D/SMACK: RECV (0): <iq xml:lang='en' to='swordfish@atalk.org/atalk' from='leopard@atalk.org/atalk' type='set' id='oK7gw-550'><open xmlns='http://jabber.org/protocol/ibb' block-size='4096' sid='jsi_-1166856721' stanza='iq'/></iq>
2018-12-14 12:28:36.233 22061-22303/org.atalk.android W/aTalk: [10581] org.atalk.android.gui.chat.filetransfer.ReceiveFileConversation.incomingBytestreamRequest().459 Received IBB Request: leopard@atalk.org/atalk
2018-12-14 12:28:36.244 22061-22198/org.atalk.android D/SMACK: SENT (0): <iq to='leopard@atalk.org/atalk' id='oK7gw-550' type='result'></iq>
2018-12-14 12:28:36.258 22061-22198/org.atalk.android D/SMACK: SENT (0): <iq to='leopard@atalk.org/atalk' id='oK7gw-544' type='result'><si xmlns='http://jabber.org/protocol/si'><feature xmlns="http://jabber.org/protocol/feature-neg"><x xmlns='jabber:x:data' type='submit'><field var='stream-method'><value>http://jabber.org/protocol/bytestreams</value><value>http://jabber.org/protocol/ibb</value></field></x></feature></si></iq>
2018-12-14 12:28:36.409 22061-22199/org.atalk.android D/SMACK: RECV (0): <iq xml:lang='en' to='swordfish@atalk.org/atalk' from='leopard@atalk.org/atalk' type='set' id='oK7gw-552'><data xmlns='http://jabber.org/protocol/ibb' seq='0' sid='jsi_-1166856721'>iVBORw0KGgoAAAANSUhEUgAAAXcAAAELCAMAAAAV/jZ2AAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAMAUExURf///y8vNerfzzIyNMzMzP7//isrMP/4sP///v7///3//y0tMufcyikpLv//++rezB4eI+XayajI1xobHyAhJhcXHCQkKKzL2DIzOezg0uvayScnLNrItqbG1N/KtqPD03iKpKHB0Z6+0One0unZxufWw////+jdzRITF+TSv+LUw+ffzqFDRbzY6sPb7dXFtZy/0+bbzujr8Mu5qDo7Qs62oOzu8t7Hsn6juuTXx7nM2v39+5u9ztzLuu/x9ebn7D0+R5/C1tK7pcWxoOHOu9W/qtzOvq/.....

There are more work to be done, as the acceptance of IBB is currently being triggered by aTalk; Although the sender transfers the whole file via IBB protocol, FaultTolerantNegotiator is not designed to fall back to receive IBB stream data and throws the following exception on timeout.

2018-12-14 12:28:46.266 22061-22305/org.atalk.android E/aTalk: [10583] impl.protocol.jabber.OperationSetFileTransferJabberImpl.run().492 An exception occurred while transferring file: 
    org.jivesoftware.smack.SmackException$NoResponseException: No response received within reply timeout. Timeout was 10000ms (~10s). While waiting for stream initiation
        at org.jivesoftware.smackx.filetransfer.StreamNegotiator.initiateIncomingStream(StreamNegotiator.java:123)
        at org.jivesoftware.smackx.filetransfer.FaultTolerantNegotiator.createIncomingStream(FaultTolerantNegotiator.java:68)
        at org.jivesoftware.smackx.filetransfer.IncomingFileTransfer$2.call(IncomingFileTransfer.java:179)
        at org.jivesoftware.smackx.filetransfer.IncomingFileTransfer$2.call(IncomingFileTransfer.java:174)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at org.jivesoftware.smackx.filetransfer.IncomingFileTransfer.negotiateStream(IncomingFileTransfer.java:182)
        at org.jivesoftware.smackx.filetransfer.IncomingFileTransfer.access$100(IncomingFileTransfer.java:58)
        at org.jivesoftware.smackx.filetransfer.IncomingFileTransfer$1.run(IncomingFileTransfer.java:132)
        at java.lang.Thread.run(Thread.java:764)

aTalk has enhanced the Smack FaultTolerantNegotiator to support incoming file transfer with IBB fallback. The patches are attached below. These patches applied to the latest Smack 4.4.-alpha2 source Revision 4127.

FaultTolerantNegotiator.patch (1.6 KB)
InBandBytestreamManager.patch (1.3 KB)
IBBTransferNegotiator.patch (3.6 KB)
InBandBytestreamSession.patch (2.1 KB)

Below is a debug log of the IBB fallback on Socks5Bystream failure:
Appreciate if Smack team would consider the implementation for smack libraries future release.

2018-12-16 19:51:51.759 25974-26623/org.atalk.android D/SMACK: RECV (0): <iq xml:lang='en' to='swordfish@atalk.org/atalk' from='leopard@atalk.org/atalk' type='set' id='3YU3s-118'><si xmlns='http://jabber.org/protocol/si' id='jsi_1240632326' mime-type='image/png' profile='http://jabber.org/protocol/si/profile/file-transfer'><file xmlns='http://jabber.org/protocol/si/profile/file-transfer' name='586431100-1.png' size='39315'><thumbnail xmlns='urn:xmpp:thumbs:0' cid='sha1+7b6f3cd32d439be60af27841c2890b4395aca994@bob.xmpp.org' mime-type='image/png' width='64' height='64'/></file><feature xmlns='http://jabber.org/protocol/feature-neg'><x xmlns='jabber:x:data' type='form'><field var='stream-method' type='list-single'><option><value>http://jabber.org/protocol/bytestreams</value></option><option><value>http://jabber.org/protocol/ibb</value></option></field></x></feature></si></iq>
2018-12-16 19:51:55.842 25974-26622/org.atalk.android D/SMACK: SENT (0): <iq to='leopard@atalk.org/atalk' id='3YU3s-118' type='result'><si xmlns='http://jabber.org/protocol/si'><feature xmlns="http://jabber.org/protocol/feature-neg"><x xmlns='jabber:x:data' type='submit'><field var='stream-method'><value>http://jabber.org/protocol/bytestreams</value><value>http://jabber.org/protocol/ibb</value></field></x></feature></si></iq>
2018-12-16 19:51:56.241 25974-26623/org.atalk.android D/SMACK: RECV (0): <iq xml:lang='en' to='swordfish@atalk.org/atalk' from='leopard@atalk.org/atalk' type='set' id='3YU3s-133'><query xmlns='http://jabber.org/protocol/bytestreams' sid='jsi_1240632326' mode='tcp'><streamhost jid='leopard@atalk.org/atalk' host='fe80::f025:b7ff:fe9c:3c5%p2p0' port='7777'/><streamhost jid='leopard@atalk.org/atalk' host='fe80::f225:b7ff:fe9c:3c5%wlan0' port='7777'/><streamhost jid='leopard@atalk.org/atalk' host='192.168.1.12' port='7777'/></query></iq>

2018-12-16 19:51:59.611 25974-26622/org.atalk.android D/SMACK: SENT (0): <iq to='leopard@atalk.org/atalk' id='3YU3s-133' type='error'><error type='cancel'><item-not-found xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/><text xml:lang='en'>Could not establish socket with any provided host</text></error></iq>

2018-12-16 19:51:59.884 25974-26623/org.atalk.android D/SMACK: RECV (0): <iq xml:lang='en' to='swordfish@atalk.org/atalk' from='leopard@atalk.org/atalk' type='set' id='3YU3s-135'><open xmlns='http://jabber.org/protocol/ibb' block-size='4096' sid='jsi_1240632326' stanza='iq'/></iq>
2018-12-16 19:51:59.902 25974-26622/org.atalk.android D/SMACK: SENT (0): <iq to='leopard@atalk.org/atalk' id='3YU3s-135' type='result'></iq>
2018-12-16 19:52:00.078 25974-26623/org.atalk.android D/SMACK: RECV (0): <iq xml:lang='en' to='swordfish@atalk.org/atalk' from='leopard@atalk.org/atalk' type='set' id='3YU3s-137'><data xmlns='http://jabber.org/protocol/ibb' seq='0' sid='jsi_1240632326'>iVBORw0KGgoAAAANSUhEUgAAAXcAAAELCAMAAAAV/jZ2AAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAMAUExURf///y8vNerfzzIyNMzMzP7//isrMP/4sP///v7///3//y0tMufcyikpLv//++rezB4eI+XayajI1xobHyAhJhcXHCQkKKzL2DIzOezg0uvayScnLNrItqbG1N/KtqPD03iKpKHB0Z6+0One0unZxufWw////+jdzRITF+TSv+LUw+ffzqFDRbzY6sPb7dXFtZy/0+bbzujr8Mu5qDo7Qs62oOzu8t7Hsn6juuTXx7nM2v39+5u9ztzLuu/x9ebn7D0+R5/C1tK7pcWxoOHOu9W/qtzOvq/
....
2018-12-16 19:52:00.117 25974-26622/org.atalk.android D/SMACK: SENT (0): <iq to='leopard@atalk.org/atalk' id='3YU3s-137' type='result'></iq><r xmlns='urn:xmpp:sm:3'/>

....
....

2018-12-16 19:52:01.426 25974-26623/org.atalk.android D/SMACK: RECV (0): <iq xml:lang='en' to='swordfish@atalk.org/atalk' from='leopard@atalk.org/atalk' type='set' id='3YU3s-155'><data xmlns='http://jabber.org/protocol/ibb' seq='9' sid='jsi_1240632326'>eKm4QMKdb4B5zbRMbU8z+eLQJ8Bu8gcKf8Tu7SbTSi5CvpXvVSp4yH9AJ94V9Y2/GXeV14nL1i5xMvzDs4vyOOInSQ/wmRQyCphVuZ20nk3AoWYy51tyNoGfvJW9m5izCYq1wGTIFPR2rOBdhTrhLq88ClMDjpcM/LPCPEhozzDlu/B30pSUtBj3HLZ1cyJ7Z1GfP4CfdSrYyue7444MGmkdaSGUOGuUgjZQfvkeCuGqoyAcvx/R4VBTI+vrgP1od1l1SMRvjLvpoSWYRGC1Vgs8NH6JiRcKKl9DdCN0zj15jCURDfG85hneXoDiCOFKcZamYPdwGaP3gmxMEDwxEIVMzbrTxx2hVAvVV9KYtU/v/bF48rvjfjmfEw8HG7pPiXWyk1zhS
....
/Y2E8COa7GA3zF3kf2IcBfuwl1EuAt3EeEu3EWEu3AXEe7CXSTiLrJvQe4iTyDC/WnkXyIa3wt49QLVAAAAAElFTkSuQmCC</data></iq>
2018-12-16 19:52:01.433 25974-26622/org.atalk.android D/SMACK: SENT (0): <iq to='leopard@atalk.org/atalk' id='3YU3s-155' type='result'></iq>

2018-12-16 19:52:01.566 25974-26623/org.atalk.android D/SMACK: RECV (0): <iq xml:lang='en' to='swordfish@atalk.org/atalk' from='leopard@atalk.org/atalk' type='set' id='3YU3s-157'><close xmlns='http://jabber.org/protocol/ibb' sid='jsi_1240632326'/></iq>
2018-12-16 19:52:01.571 25974-26622/org.atalk.android D/SMACK: SENT (0): <iq to='leopard@atalk.org/atalk' id='3YU3s-157' type='result'></iq><r xmlns='urn:xmpp:sm:3'/>

Thanks for your contribution. :slight_smile:

Are those patches the same that can be found in

?

Yes, the patches here are exactly the same as in the PR.

This topic was automatically closed 31 days after the last reply. New replies are no longer allowed.

I’m curious whether this fix has now been implemented in the main code branch?

From a 50,000 foot view - if we use the stock standard File Transfer classes, does it default to Socks5 and falls back to IBB automatically?

What is the “best practice” approach if both fail (ex: double-NAT in place and no TURN server support) - should we implement a file upload to server from sending client and file download to receiving client instead of peer-to-peer?

The patch is still pending and has not release in any official smack releases.

To my understanding, if both socks5 and IBB file transfers are being offered in negotiation, the File Transfer Manger will attempt to use socks5 as first choice, it falls back to IBB on socks5 failure if the patch is applied on both sender and recipient devices.

Without the patch the file transfer will be aborted on sock5 failure. App needs to provide an user IBB only option in this case. If you are able to send chat messages over symmetric NAT, then IBB should also work without problem.

Current xmpp file transfer protocol does not support sending file to an offline contact. Uploading file to server is used to send file to an offline buddy, or the app does not support the xmpp file transfer protocol.

Thanks for the reply. Is there a way to set up a listener so I can tell which mechanism is actually being employed? i.e. if the Chat ends up going through the XMPP server instead of peer-to-peer, I want to know this. If the file transfer is using IBB instead of SOCKS5 I want to know this.

Based on your answer, if I wanted to offer the ability to handle file transfer from client A to client B that is offline (or effectively “offline” because routing isn’t working due to NAT issues) by uploading to a server, I need to handle this completely outside of XMPP protocol, correct? For example, set up a separate “file upload/download server” that my app would fall back to in the case of connection errors.

Also - curious what you are doing for clients on iOS. Which client library are you using?

Thanks!

I do not believe Smack provides hook to find out what is the protocol used for file transfer.

(or effectively “offline” because routing isn’t working due to NAT issues)

If the offline condition is due to NAT issues, even if you are able to perform file upload to the server, how do you inform the recipient that is an awaiting file for download.

I need to handle this completely outside of XMPP protocol, correct?

Some xmpp server e.g. ejabberd provides http file upload option. Smack provides api call to check for such http_upload service support on server. You can then send file via smack and smack will handle the rest.

Forget to mention that http_upload is also used for one-to-many file sharing (Group Chat). Currently XMPP file transfer protocol cannot send file in group chat.

I am the developer for aTalk (android only xmpp client) which uses smack library. aTalk is an open source and aTalk is available on playStore and to be offered on F-Droid in near future.

When I say “effectively offline due to NAT”, I mean offline from being able to do peer-to-peer - i.e. for some network config reason the direct connection isn’t possible, or perhaps has been working but now something is causing the peer-to-peer activity to be blocked. However in my scenario, client A and client B both still have access to the Internet, can both still ping my associated website. I envision this type of architecture:

Website “front end” server(s) - hosts general information about company and service, contains back-end data and processing - for example fronts initial registration to the XMPP Server, and fronts access to a temporary storage server.

XMPP Server(s) - facilitates communication between clients, also communicates with Website back-end. This is not publicly available, it is a private XMPP Server only available to those that have registered for the service.

Storage Server(s) - used to temporarily store content that is desired to be sent from client A to client B in the case of peer-to-peer file transfer failure.

Client App - performs communication and under the covers communicates via REST API with website as needed and XMPP Server as needed using Smack.

So if Client A and Client B who have both registered through the website (and thus been set up on the XMPP Server) are somehow blocked from normal peer-to-peer operations, yet they can still communicate to website, I would use an Exception thrown from Smack after attempting the file transfer to:

  1. Use API on my website to have website push info to client A to let her know that client B is trying to reach peer-to-peer but can’t,
  2. Offer a choice to client B send file up to temporary storage.
  3. Assuming client B agrees, initiate file upload to temporary storage server, acknowledge to B when file upload is complete.
  4. Let client A know when file is there and initiate download from temporary storage to A
  5. Remove file from temporary storage when file download is complete.

Hi,

Thanks for sharing the info. The project seems to cover an extensive job scope. Base on your description, I see no problem in the implementation.

If the implementation offers IBB as one of the file transfer protocols, except for the slow IBB file transfer speed, IBB should work even under symmetric NAT.

IBB transfer is not P2P, but similar to chat messages using xmpp as ‘proxy’. Any failure in IBB transfer is usually temporary.

Regards,

CM Eng