File Transfer negotiation problems

Hi guys,

We’ve been working on file transfer for SIP Communicator lately and have been using the corresponding features from smack. Most of the
time the lib is doing a really nice job, so thank you guys for your work! Smack is really one fine piece of software!

We did come across a few minor problems though so we thought we’d share them here.

Sometimes, after sending a SI request and after the receiver accepts it, the negotiation would fail in the following way:

The FaultTolerantNegotiator on the receiving side creates the following initiation accept packet :

<iq id="6j5Lo-10" to="yana_stamcheva@jabber.org/sip-comm" from="yana.stamcheva@jabber.org/sip-comm" 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>

The PacketCollector on the sending side (in FileTransferNegotiator.negotiateOutgoingTransfer()) gets the following packet:

<iq id="6j5Lo-10" to="yana_stamcheva@jabber.org/sip-comm" from="yana.stamcheva@jabber.org/sip-comm" type="result"></iq>

This however results in a ClassCastException, because smack expects a StreamInitiation packet instead. Here’s the corresponding code:

public StreamNegotiator negotiateOutgoingTransfer(final String userID, final String streamID, final String fileName, final long  size, final String desc, int responseTimeout) throws  XMPPException {
....      if (iqResponse.getType().equals(IQ.Type.RESULT)) {
          StreamInitiation response = (StreamInitiation)  siResponse;
          ....      }
}

And here is the exception we get: java.lang.ClassCastException: org.jivesoftware.smack.PacketReader$4:

java.lang.ClassCastException: org.jivesoftware.smack.PacketReader$4
     [java]      at org.jivesoftware.smackx.filetransfer.FileTransferNegotiator.negotiateOutgoingTransfer(FileTransferNegotiator.java:402)
     [java]      at org.jivesoftware.smackx.filetransfer.OutgoingFileTransfer.negotiateStream(OutgoingFileTransfer.java:359)
     [java]      at org.jivesoftware.smackx.filetransfer.OutgoingFileTransfer.access$100(OutgoingFileTransfer.java:35)
     [java]      at org.jivesoftware.smackx.filetransfer.OutgoingFileTransfer$2.run(OutgoingFileTransfer.java:214)
     [java]      at java.lang.Thread.run(Thread.java:613)

At that point the receiver would also get the following exception :

[java] Error in execution:      [java]   -- caused by: java.util.concurrent.ExecutionException:      [java]   -- caused by: No response from remote client:      [java]      at org.jivesoftware.smackx.filetransfer.IncomingFileTransfer.negotiateStream(IncomingFileTransfer.java:199)
     [java]      at org.jivesoftware.smackx.filetransfer.IncomingFileTransfer.access$100(IncomingFileTransfer.java:47)
     [java]      at org.jivesoftware.smackx.filetransfer.IncomingFileTransfer$1.run(IncomingFileTransfer.java:124)
     [java]      at java.lang.Thread.run(Thread.java:613)
     [java] Nested Exception:      [java] java.util.concurrent.ExecutionException:      [java]   -- caused by: No response from remote client:      [java]      at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:215)
     [java]      at java.util.concurrent.FutureTask.get(FutureTask.java:85)
     [java]      at org.jivesoftware.smackx.filetransfer.IncomingFileTransfer.negotiateStream(IncomingFileTransfer.java:193)
     [java]      at org.jivesoftware.smackx.filetransfer.IncomingFileTransfer.access$100(IncomingFileTransfer.java:47)
     [java]      at org.jivesoftware.smackx.filetransfer.IncomingFileTransfer$1.run(IncomingFileTransfer.java:124)
     [java]      at java.lang.Thread.run(Thread.java:613)
     [java] Caused by:      [java]   -- caused by: No response from remote client:      [java]      at org.jivesoftware.smackx.filetransfer.FaultTolerantNegotiator.createIncomingStream(FaultTolerantNegotiator.java:115)
     [java]      at org.jivesoftware.smackx.filetransfer.IncomingFileTransfer$2.call(IncomingFileTransfer.java:186)
     [java]      at org.jivesoftware.smackx.filetransfer.IncomingFileTransfer$2.call(IncomingFileTransfer.java:185)
     [java]      at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:269)
     [java]      at java.util.concurrent.FutureTask.run(FutureTask.java:123)
     [java]      at org.jivesoftware.smackx.filetransfer.IncomingFileTransfer.negotiateStream(IncomingFileTransfer.java:190)
     [java]      ... 3 more

I’d appreciate some advice here as to what would be the proper way to fix this.

On a completely different note, we are also experiencing some other problems with Jabber.org’s ejabberd. Attempts to initiate a file transfer would sometimes fail because the server would respond with a feature-not-implemented error.

feature-not-implemented(501)
     [java]      at org.jivesoftware.smackx.filetransfer.FileTransferNegotiator.negotiateOutgoingTransfer(FileTransferNegotiator.java:407)
     [java]      at org.jivesoftware.smackx.filetransfer.OutgoingFileTransfer.negotiateStream(OutgoingFileTransfer.java:359)
     [java]      at org.jivesoftware.smackx.filetransfer.OutgoingFileTransfer.access$100(OutgoingFileTransfer.java:35)
     [java]      at org.jivesoftware.smackx.filetransfer.OutgoingFileTransfer$2.run(OutgoingFileTransfer.java:214)
     [java]      at java.lang.Thread.run(Thread.java:613)

We don’t think this is a problem with smack (we witnessed similar behavior with Adium) but we thought we’d mention it anyway in case someone here would have an explanation.

Cheers
Yana

Hi Yana,

we experience the same problems with FileTransfers and it seems to me that the patch attached in

http://www.igniterealtime.org/community/message/194404#194404

prevents the issue. It is not really a fix, because if the Socks5 server is really not available then the FileTransfer will fail even though IBB could be used (I guess this has to do with timeouts being set incorrectly).

I am planning of creating a zip with new jars and attach them to

http://www.igniterealtime.org/community/thread/38048

Maybe you could give them a spin or use the community patch repo over at

http://repo.or.cz/w/Smack.git?a=shortlog;h=refs/heads/smack-3.1.1

directly.

Regards,

Christopher