[jitsi-dev] GTalk FileShare feature in Jitsi with pseudoTCP


#1

Hi,

I was looking how to start with Talk file transfers in Jitsi and after few
attempts I'm not sure where to start. My goal was to get some sample "xmpp"
conversation trace log of that how the files are transferred.

First I tried to transfer files with "pcp" client included in libjingle,
however it have few bugs and I wasn't able to fix them all. Probably in
current version Talk uses not exacly the same method as in "pcp" client. In
few places I've found info that it has been discontinued.

My second approach was to capture conversation between two GTalk clients
with Wireshark. Finally that exchange is unreadable because of SSL
encryption and I don't know how to decode this without private keys.
Probably I won't be able to print them out with GTalk client.

In libjingle dev
documentation<https://developers.google.com/talk/libjingle/file_share>
there
is description how file sharing feature works. However I'm not sure if I
understand it correctly. There's something about creation of "share"
session and I'd like to start implmenting it.

The first problem is that GTalk won't even try to share files with jitsi
until I won't provide required capabilities. I've extracted GTalk client's
capabilities from .pcap file created by jitsi:

<iq
  id=“5f6RW-8”
  to="paweldomas@gmail.com/jitsi-2blfA1992B32"
  from="pawelgawel293@gmail.com/Talk.v104E70C19D9"
  type=“result”>
    <query
    xmlns=“http://jabber.org/protocol/disco#info
    node=“http://www.google.com/xmpp/client/caps#1.0.0.104”>
        <identity category=“client” name=“null” type=“pc”/>
        <feature var=“http://jabber.org/protocol/disco#info”/>
        <feature var=“http://www.google.com/xmpp/protocol/session”/>
    </query>
</iq>

Probably GTalk will require from me to provide <feature var="
http://www.google.com/xmpp/protocol/session"/>. I suppose this feature
describes that client is able to establish sessions compatible with this
namespace ? Is it compilant with XMPP ? Or maybe it is implemented
partially in jitsi somewhere?

Regards, Paweł Domas


#2

Hey Pawel,

Hi,

I was looking how to start with Talk file transfers in Jitsi and after
few attempts I'm not sure where to start. My goal was to get some sample
"xmpp" conversation trace log of that how the files are transferred.

First I tried to transfer files with "pcp" client included in libjingle,
however it have few bugs and I wasn't able to fix them all. Probably in
current version Talk uses not exacly the same method as in "pcp" client.
In few places I've found info that it has been discontinued.

My second approach was to capture conversation between two GTalk clients
with Wireshark. Finally that exchange is unreadable because of SSL
encryption and I don't know how to decode this without private keys.
Probably I won't be able to print them out with GTalk client.

I believe empathy are supposed to have support for that. You may want to
try with them. This would allow you to track the xmpp flow through their
debug console.

In libjingle dev documentation
<https://developers.google.com/talk/libjingle/file_share> there is
description how file sharing feature works. However I'm not sure if I
understand it correctly. There's something about creation of "share"
session and I'd like to start implmenting it.

The first problem is that GTalk won't even try to share files with jitsi
until I won't provide required capabilities. I've extracted GTalk
client's capabilities from .pcap file created by jitsi:

<iq
  id=“5f6RW-8”
  to="paweldomas@gmail.com/jitsi-2blfA1992B32
<http://paweldomas@gmail.com/jitsi-2blfA1992B32>"
  from="pawelgawel293@gmail.com/Talk.v104E70C19D9
<http://pawelgawel293@gmail.com/Talk.v104E70C19D9>"
  type=“result”>
    <query
    xmlns=“http://jabber.org/protocol/disco#info
    node=“http://www.google.com/xmpp/client/caps#1.0.0.104”>
        <identity category=“client” name=“null” type=“pc”/>
        <feature var=“http://jabber.org/protocol/disco#info”/>
        <feature var=“http://www.google.com/xmpp/protocol/session”/>
    </query>
</iq>

Eeer ... this doesn't look right. There should be a lot more. Or did you
strip something?

Emil

···

On 24.07.12 20:06, Paweł Domas wrote:


#3

Hi Emil,

I believe empathy are supposed to have support for that. You may want to
try with them. This would allow you to track the xmpp flow through their
debug console.

Thanks. Yes I was able to extract some conversation info from empathy debug
console. I won't be posting it here for now.

> The first problem is that GTalk won’t even try to share files with jitsi
> until I won’t provide required capabilities. I’ve extracted GTalk
> client’s capabilities from .pcap file created by jitsi:
>
> <iq
> id=“5f6RW-8”
> to="paweldomas@gmail.com/jitsi-2blfA1992B32
> <http://paweldomas@gmail.com/jitsi-2blfA1992B32>"
> from="pawelgawel293@gmail.com/Talk.v104E70C19D9
> <http://pawelgawel293@gmail.com/Talk.v104E70C19D9>"
> type=“result”>
> <query
> xmlns=“http://jabber.org/protocol/disco#info
> node=“http://www.google.com/xmpp/client/caps#1.0.0.104”>
> <identity category=“client” name=“null” type=“pc”/>
> <feature var=“http://jabber.org/protocol/disco#info”/>
> <feature var=“http://www.google.com/xmpp/protocol/session”/>
> </query>
> </iq>

Eeer ... this doesn't look right. There should be a lot more. Or did you
strip something?

I missed some info from the presence response. Here's full log contaning
capabilities:

// Presence response

<presence
  id="5f6RW-4"
  to="paweldomas@gmail.com/jitsi-2blfA1992B32"
  from="pawelgawel293@gmail.com/Talk.v104E70C19D9" >
  <status></status>
  <priority>24</priority>
  <show>away</show>
  <c xmlns='http://jabber.org/protocol/caps'
    ext='share-v1 voice-v1'
    hash='null'
    node='http://www.google.com/xmpp/client/caps'
    ver='1.0.0.104'/>
  <x xmlns="jabber:x:delay" stamp="20120724T10:54:21"></x>
  <x xmlns="vcard-temp:x:update">
    <photo></photo>
  </x>
</presence>

// Query for capabilities
<iq
  id="5f6RW-8"
  to="pawelgawel293@gmail.com/Talk.v104E70C19D9"
  type="get" >
    <query
      xmlns="http://jabber.org/protocol/disco#info"
      node="http://www.google.com/xmpp/client/caps#1.0.0.104" >
    </query>
</iq>

//Response
<iq
  id=“5f6RW-8”
  to="paweldomas@gmail.com/jitsi-2blfA1992B32"
  from="pawelgawel293@gmail.com/Talk.v104E70C19D9"
  type=“result” >
    <query
    xmlns=“http://jabber.org/protocol/disco#info
    node=“http://www.google.com/xmpp/client/caps#1.0.0.104”>
        <identity category=“client” name=“null” type=“pc”/>
        <feature var=“http://jabber.org/protocol/disco#info”/>
        <feature var=“http://www.google.com/xmpp/protocol/session”/>
    </query>
</iq>

Now I see that there is feature in "ext" attribute called "share-v1". So
this must be that share feature, but it probably should be listed with
features.

For instance Jitsi is sending pretty long list for such request (but other
clients don't):

  <feature var=“http://jabber.org/protocol/xhtml-im”/>
  <feature var=“http://jabber.org/protocol/muc”/>
  <feature var=“http://jabber.org/protocol/bytestreams”/>
  <feature var=“http://jabber.org/protocol/si/profile/file-transfer”/>
  <feature var=“http://jabber.org/protocol/si”/>
  <feature var=“http://jabber.org/protocol/ibb”/>
  <feature var=“http://jabber.org/protocol/caps”/>
  <feature var=“http://jabber.org/protocol/disco#info”/>
  <feature var=“http://www.xmpp.org/extensions/xep-0168.html#ns”/>
  <feature var=“urn:xmpp:thumbs:0”/>
  <feature var=“urn:xmpp:bob”/>
  <feature var=“http://jabber.org/protocol/muc#rooms”/>
  <feature var=“http://jabber.org/protocol/muc#traffic”/>
  <feature var=“urn:xmpp:jingle:apps:rtp:rtp-hdrext:0”/>
  <feature var=“urn:xmpp:coin”/>
  <feature var=“urn:xmpp:jingle:1”/>
  <feature var=“urn:xmpp:jingle:apps:rtp:1”/>
  <feature var=“urn:xmpp:jingle:transports:raw-udp:1”/>
  <feature var=“urn:xmpp:jingle:transports:ice-udp:1”/>
  <feature var=“urn:xmpp:jingle:apps:rtp:audio”/>
  <feature var=“urn:xmpp:jingle:apps:rtp:video”/>
  <feature var=“urn:xmpp:jingle:apps:rtp:zrtp:1”/>
  <feature var=“http://jabber.org/protocol/jinglenodes”/>
  <feature var=“urn:xmpp:jingle:transfer:0”/>
  <feature var=“http://jitsi.org/protocol/inputevt/sharer”/>
  <feature var=“http://jitsi.org/protocol/inputevt/sharee”/>
  <feature var=“jabber:iq:version”/>
  <feature var=“urn:xmpp:message-correct:0”/>
  <feature var=“http://www.google.com/xmpp/protocol/voice/v1”/>
  <feature var=“http://www.google.com/xmpp/protocol/video/v1”/>
  <feature var=“http://www.google.com/xmpp/protocol/camera/v1”/>
  <feature var=“http://www.google.com/transport/p2p”/>

Also I've captured log for communication between jitsi and empathy and I've
finally figured out these capabilities:

<iq id="NhEdK-16" type="result">
  <query
    xmlns="http://jabber.org/protocol/disco#info"
    node="http://telepathy.freedesktop.org/caps#IBvnFRPBz1L4P5RBbtU4m2EODbA="

    <identity category=“client” name=“Telepathy Gabble 0.16.0” type=“pc”/>
    <feature var=“http://www.google.com/xmpp/protocol/session”/>
    <feature var=“urn:xmpp:jingle:transports:raw-udp:1”/>
    <feature var=“http://jabber.org/protocol/jingle”/>
    <feature var=“urn:xmpp:jingle:1”/>
    <feature var=“http://jabber.org/protocol/chatstates”/>
    <feature var=“http://jabber.org/protocol/nick”/>
    <feature var=“http://jabber.org/protocol/nick+notify”/>
    <feature var=“http://jabber.org/protocol/si”/>
    <feature var=“http://jabber.org/protocol/ibb”/>
    <feature var=“http://telepathy.freedesktop.org/xmpp/tubes”/>
    <feature var=“http://jabber.org/protocol/bytestreams”/>
    <feature var=“jabber:iq:version”/>
    <feature var=“http://jabber.org/protocol/si/profile/file-transfer”/>
    <feature var="
http://telepathy.freedesktop.org/xmpp/file-transfer-metadata"/>
    <feature var=“http://www.google.com/transport/p2p”/>
    <feature var=“urn:xmpp:jingle:transports:ice-udp:1”/>
    <feature var=“http://google.com/xmpp/protocol/share/v1”/>
    <feature var=“http://www.google.com/xmpp/protocol/voice/v1”/>
    <feature var=“http://www.google.com/xmpp/protocol/video/v1”/>
    <feature var=“http://jabber.org/protocol/jingle/description/audio”/>
    <feature var=“http://jabber.org/protocol/jingle/description/video”/>
    <feature var=“urn:xmpp:jingle:apps:rtp:1”/>
    <feature var=“urn:xmpp:jingle:apps:rtp:audio”/>
    <feature var=“urn:xmpp:jingle:apps:rtp:video”/>
    <feature var=“http://telepathy.freedesktop.org/xmpp/tubes/stream#rfb”/>
    <feature var=“urn:xmpp:jingle:apps:rtp:rtp-hdrext:0”/>
    <feature var=“urn:xmpp:jingle:apps:rtp:rtcp-fb:0”/>
  </query>
</iq>

So what I need to do know is to implement <feature var="
http://www.google.com/xmpp/protocol/session"/> and <feature var="
http://google.com/xmpp/protocol/share/v1"/> capabilities. I’d like to ask
here for some guidance how capabilities are added into Jitsi ? In which
classes should I start ?

Regards, Paweł Domas

···

2012/7/24 Emil Ivov <emcho@sip-communicator.org>


#4

Paweł, you could try looking at the references to the net.java.sip.communicator.impl.protocol.jabber.ProtocolProviderServiceJabberImpl#supportedFeatures field and to whatever gets added to that java.util.List. You may as well be interested in the net.java.sip.communicator.impl.protocol.jabber.ScServiceDiscoveryManager class, the net.java.sip.communicator.impl.protocol.jabber.extensions package and the org.jivesoftware.smack.packet.IQ and org.jivesoftware.smack.provider.IQProvider implementations in it.

···

On Jul 25, 2012, at 1:30 PM, Paweł Domas wrote:

I'd like to ask here for some guidance how capabilities are added into Jitsi ? In which classes should I start ?


#5

Hi,

Paweł, you could try looking at the references to the
net.java.sip.communicator.impl.protocol.jabber.ProtocolProviderServiceJabberImpl#supportedFeatures
field and to whatever gets added to that java.util.List. You may as well be
interested in the
net.java.sip.communicator.impl.protocol.jabber.ScServiceDiscoveryManager
class, the net.java.sip.communicator.impl.protocol.jabber.extensions
package and the org.jivesoftware.smack.packet.IQ and
org.jivesoftware.smack.provider.IQProvider implementations in it.

Thanks it helped a lot.

I have some progress in implementation, but now I need to know something
about FileTransferOperationSet. At the moment there
is OperationSetFileTransferJabberImpl defined for Jabber protocol. After
reading it I assume that it is a glue layer between GUI and Smack's file
transfer implementation for Jabber.

Is it possible to have two file transfer operation sets defined for one
protocol ? It looks like no, but I'm not sure.

If there will be only one file transfer operation set I plan to create two
additional operation sets. One which will decide if Smack or GTalk transfer
should be used based on capabilities and second one which will implement
GTalk file transfer operation set. What do you think about that ?

In situation when user wants to initiate a file transfer and if
capabilities are met for both Jabber and GTalk file transfers which one
should be preferred ?

Regards, Paweł Domas

···

2012/7/25 Lyubomir Marinov <lubo@jitsi.org>


#6

Hey Pawel,

Apologies for the delay

(inline)

Hi,

2012/7/25 Lyubomir Marinov <lubo@jitsi.org <mailto:lubo@jitsi.org>>

    Paweł, you could try looking at the references to the
    net.java.sip.communicator.impl.protocol.jabber.ProtocolProviderServiceJabberImpl#supportedFeatures
    field and to whatever gets added to that java.util.List. You may as
    well be interested in the
    net.java.sip.communicator.impl.protocol.jabber.ScServiceDiscoveryManager
    class, the net.java.sip.communicator.impl.protocol.jabber.extensions
    package and the org.jivesoftware.smack.packet.IQ
    <http://org.jivesoftware.smack.packet.IQ> and
    org.jivesoftware.smack.provider.IQProvider implementations in it.

Thanks it helped a lot.

I have some progress in implementation, but now I need to know something
about FileTransferOperationSet. At the moment there
is OperationSetFileTransferJabberImpl defined for Jabber protocol. After
reading it I assume that it is a glue layer between GUI and Smack's file
transfer implementation for Jabber.

Is it possible to have two file transfer operation sets defined for one
protocol ? It looks like no, but I'm not sure.

This is correct. Any op set can only have one implementation per protocol.

If there will be only one file transfer operation set I plan to create
two additional operation sets.

Mmmm ... what if there could be two :slight_smile: ?

One which will decide if Smack or GTalk
transfer should be used based on capabilities and second one which will
implement GTalk file transfer operation set. What do you think about that ?

OK, so first there are three alternatives. There's what we currently
have, then there's standard Jingle file transfer and then there's the
GTalk thing.

I am not sure I got your design plans though. Do you mean that you'll
split the FileTransfer opset into two layers and that you'll then have
the first layer handle requests from the GUI and choose one of several
implementations from the second layer?

In situation when user wants to initiate a file transfer and if
capabilities are met for both Jabber and GTalk file transfers which one
should be preferred ?

If all three are supported, I guess we'd have Jingle, GTalk, current
version. But this may change as we gain experience from your implementation.

Cheers,
Emil

···

On 27.07.12, 08:45, Paweł Domas wrote:


#7

Hi,

···

2012/7/31 Emil Ivov <emcho@jitsi.org>

> If there will be only one file transfer operation set I plan to create
> two additional operation sets.

Mmmm ... what if there could be two :slight_smile: ?

> One which will decide if Smack or GTalk
> transfer should be used based on capabilities and second one which will
> implement GTalk file transfer operation set. What do you think about
that ?

OK, so first there are three alternatives. There's what we currently
have, then there's standard Jingle file transfer and then there's the
GTalk thing.

I am not sure I got your design plans though. Do you mean that you'll
split the FileTransfer opset into two layers and that you'll then have
the first layer handle requests from the GUI and choose one of several
implementations from the second layer?

Yes that's exactly what I meant to write :slight_smile:

I'm still working on that and it will take some time probably.

Regards, Pawel Domas


#8

Hi,

I haven't tried it yet, but does Jitsi support multiple simultaneous file
transfer from one contact ?
In GTalk there are sometimes multiple files shared in one session. So I
will be creating few IncomingFileTransferRequest instances - one for each
file shared. Will GUI handle this properly ?

Regards, Paweł Domas


#9

Hi Pawel,

Hi,

I haven't tried it yet, but does Jitsi support multiple simultaneous file

transfer from one contact ?

It is supported yes.

In GTalk there are sometimes multiple files shared in one session. So I

will be creating few IncomingFileTransferRequest instances - one for each
file shared. Will GUI handle this properly ?

Normally the gui should also work correctly in such case. Let me know if
you encounter any problems.

Cheers,
*Yana*

···

On Aug 2, 2012 10:49 AM, "Paweł Domas" <paweldomas@gmail.com> wrote:

Regards, Paweł Domas


#10

Confirmed. Works as expected all files are displayed in chat window with
accept and reject actions available.

···

2012/8/2 Yana Stamcheva <yana@jitsi.org>

Hi Pawel,

On Aug 2, 2012 10:49 AM, "Paweł Domas" <paweldomas@gmail.com> wrote:
>
> Hi,
>
> I haven't tried it yet, but does Jitsi support multiple simultaneous
file transfer from one contact ?

It is supported yes.

> In GTalk there are sometimes multiple files shared in one session. So I
will be creating few IncomingFileTransferRequest instances - one for each
file shared. Will GUI handle this properly ?

Normally the gui should also work correctly in such case. Let me know if
you encounter any problems.

--
Regards, Paweł Domas


#11

Hi,

I'm at the point where ICE negotiations are performed. I've copied class
P2PTransportManager and modified it to create only one IceMediaStream for
UDP. Also I removed dependencies for CallPeer. Also some modifications
regards stream comonents were required. As result I have new
TransportManager class which I use to negotiate connection for file
sharing. I have few problems with it.

First I use method start startCandidateHarvest(CandidatesSender
candidatesSender) and when it finish the candidates are sent with message:

<iq id="03Scy-48" to="pawelgawel293@gmail.com/Talk.v1046E1595C3"
  from="paweldomas@gmail.com/jitsi-17e2D6823090"
  type="set">
<session xmlns='http://www.google.com/session' type='transport-info'
  initiator='pawelgawel293@gmail.com/Talk.v1046E1595C3' id='4244206756'>
<transport xmlns='http://www.google.com/transport/p2p'>
<candidate generation='0' username='fm0bradfsmdr45uu' password=''
address='192.168.1.203'
  port='50000' protocol='udp' network='0' foundation='0' component='1'
type='local' preference='0.95'
  name='transport4244206756'/>
<candidate generation='0' username='s9vqjdei9g6t5s2g' password=''
address='192.168.0.203'
  port='50000' protocol='udp' network='0' foundation='0' component='1'
type='local' preference='0.95'
  name='transport4244206756'/>
<candidate generation='0' username='42k0qqb0un7u9n65' password=''
address='10.42.43.1' port='50000'
  protocol='udp' network='0' foundation='0' component='1' type='local'
preference='0.95'
  name='transport4244206756'/>
<candidate generation='0' username='3dvrhs27gm617g78' password=''
address='81.219.122.3'
  port='50000' protocol='udp' network='0' foundation='0' component='1'
type='stun' preference='0.9'
  name='transport4244206756'/>
<candidate generation='0' username='58l1ao4urok0rfuu' password=''
address='192.168.1.203'
  port='50000' protocol='tcp' network='0' foundation='0' component='1'
type='local' preference='0.75'
  name='transport4244206756'/>
<candidate generation='0' username='5ks6q7i07rscp3ms' password=''
address='192.168.0.203'
  port='50000' protocol='tcp' network='0' foundation='0' component='1'
type='local' preference='0.75'
  name='transport4244206756'/>
<candidate generation='0' username='2ijtmodp5da7lkbq' password=''
address='10.42.43.1' port='50000'
  protocol='tcp' network='0' foundation='0' component='1' type='local'
preference='0.75'
  name='transport4244206756'/>
<candidate generation='0' username='p7ZHXsFhtRPt7XPO' password=''
address='173.194.70.127'
  port='19305' protocol='udp' network='0' foundation='0' component='1'
type='relay' preference='0.5'
  name='transport4244206756'/>
<candidate generation='0' username='p7ZHXsFhtRPt7XPO' password=''
address='173.194.70.127'
  port='19305' protocol='tcp' network='0' foundation='0' component='1'
type='relay' preference='0.5'
  name='transport4244206756'/>
<candidate generation='0' username='p7ZHXsFhtRPt7XPO' password=''
address='173.194.70.127'
  port='443' protocol='ssltcp' network='0' foundation='0' component='1'
type='relay' preference='0.5'
  name='transport4244206756'/>
</transport>
</session>
</iq>

I don't understand why TCP candidates are created when my media stream uses
UDP transport ? Is it related to STUN or TURN ?

Next I wait to receive remote candidates:

<iq id="99" to="paweldomas@gmail.com/jitsi-17e2D6823090"

···

from="pawelgawel293@gmail.com/Talk.v1046E1595C3" type="set"> <session xmlns='http://www.google.com/session' type='transport-info' initiator='pawelgawel293@gmail.com/Talk.v1046E1595C3' id='4244206756'>
<transport xmlns='http://www.google.com/transport/p2p'>
<candidate xmlns='http://www.google.com/transport/p2p'
name='transport4244206756'
  address='10.42.43.1' port='53530' preference='1'
username='GfLRNgE07OSBySKI' protocol='udp'
  generation='0' password='OnN3b9dXFawZPHDT' type='local' network='0'/>
</transport>
</session>
</iq>

<iq id="100" to="paweldomas@gmail.com/jitsi-17e2D6823090"
from="pawelgawel293@gmail.com/Talk.v1046E1595C3" type="set"> <session xmlns='http://www.google.com/session' type='transport-info' initiator='pawelgawel293@gmail.com/Talk.v1046E1595C3' id='4244206756'>
<transport xmlns='http://www.google.com/transport/p2p'>
<candidate xmlns='http://www.google.com/transport/p2p'
name='transport4244206756' address='10.42.43.1' port='53519' preference='1'
username='nHuQYpuisQJdX0uC'
protocol='udp' generation='1' password='stefOg+WndrfcINQ' type='local'
network='0'/>
</transport>
</session>
</iq>

When each one of candidates is received I call
startConnectivityEstablishment(Iterable<GTalkCandidatePacketExtension>
remote) method to start connectivity establishment or update remote
candidates. When it start I get a lot of messages about credentials and
after some time connectivity establishement fails:

10:33:08.882 INFO:
org.ice4j.ice.ConnectivityCheckClient.processErrorResponse() stale
credentials for GTalk check for /192.168.1.203:50000/udp -> /
10.42.43.1:53530/udp (PTCP-DATA.1)
10:33:08.884 INFO:
org.ice4j.ice.ConnectivityCheckClient.processErrorResponse() stale
credentials for GTalk check for /81.219.122.3:50000/udp -> /
10.42.43.1:53530/udp (PTCP-DATA.1)
10:33:08.885 INFO:
org.ice4j.ice.ConnectivityCheckClient.processErrorResponse() stale
credentials for GTalk check for /192.168.0.203:50000/udp -> /
10.42.43.1:53530/udp (PTCP-DATA.1)
10:33:08.887 INFO:
org.ice4j.ice.ConnectivityCheckClient.processErrorResponse() stale
credentials for GTalk check for /10.42.43.1:50000/udp -> /
10.42.43.1:53530/udp (PTCP-DATA.1)
10:33:08.888 INFO:
org.ice4j.ice.ConnectivityCheckClient.processErrorResponse() stale
credentials for GTalk check for /192.168.1.203:50000/udp -> /
10.42.43.1:53530/udp (PTCP-DATA.1)
10:33:08.889 INFO:
org.ice4j.ice.ConnectivityCheckClient.processErrorResponse() stale
credentials for GTalk check for /81.219.122.3:50000/udp -> /
10.42.43.1:53530/udp (PTCP-DATA.1)
10:33:08.891 INFO:
org.ice4j.ice.ConnectivityCheckClient.processErrorResponse() stale
credentials for GTalk check for /192.168.0.203:50000/udp -> /
10.42.43.1:53530/udp (PTCP-DATA.1)

In method org.ice4j.ice.ConnectivityCheckClient.processErrorResponse()
there is comment about it:

// it may be an error due to remote peer that does not processed
// our candidates IQ and we start connectivity checks too quickly
// (that's why we get a STALE CREDENTIALS because remote peer does
// not know the candidate ufrag). So let's send another check for
// that pair

Do I have to set ufrag and password somewhere when I receive candidates ?
Any ideas how this may be fixed ?

Regards, Pawel Domas


#12

Hi,

Hi,

I'm at the point where ICE negotiations are performed. I've copied class
P2PTransportManager and modified it to create only one IceMediaStream for
UDP. Also I removed dependencies for CallPeer. Also some modifications
regards stream comonents were required. As result I have new
TransportManager class which I use to negotiate connection for file
sharing. I have few problems with it.

First I use method start startCandidateHarvest(CandidatesSender
candidatesSender) and when it finish the candidates are sent with message:

<iq id="03Scy-48" to="pawelgawel293@gmail.com/Talk.v1046E1595C3"
  from="paweldomas@gmail.com/jitsi-17e2D6823090"
  type="set">
<session xmlns='http://www.google.com/session' type='transport-info'
  initiator='pawelgawel293@gmail.com/Talk.v1046E1595C3' id='4244206756'>
<transport xmlns='http://www.google.com/transport/p2p'>
<candidate generation='0' username='fm0bradfsmdr45uu' password=''
address='192.168.1.203'
  port='50000' protocol='udp' network='0' foundation='0' component='1'
type='local' preference='0.95'
  name='transport4244206756'/>
<candidate generation='0' username='s9vqjdei9g6t5s2g' password=''
address='192.168.0.203'
  port='50000' protocol='udp' network='0' foundation='0' component='1'
type='local' preference='0.95'
  name='transport4244206756'/>
<candidate generation='0' username='42k0qqb0un7u9n65' password=''
address='10.42.43.1' port='50000'
  protocol='udp' network='0' foundation='0' component='1' type='local'
preference='0.95'
  name='transport4244206756'/>
<candidate generation='0' username='3dvrhs27gm617g78' password=''
address='81.219.122.3'
  port='50000' protocol='udp' network='0' foundation='0' component='1'
type='stun' preference='0.9'
  name='transport4244206756'/>
<candidate generation='0' username='58l1ao4urok0rfuu' password=''
address='192.168.1.203'
  port='50000' protocol='tcp' network='0' foundation='0' component='1'
type='local' preference='0.75'
  name='transport4244206756'/>
<candidate generation='0' username='5ks6q7i07rscp3ms' password=''
address='192.168.0.203'
  port='50000' protocol='tcp' network='0' foundation='0' component='1'
type='local' preference='0.75'
  name='transport4244206756'/>
<candidate generation='0' username='2ijtmodp5da7lkbq' password=''
address='10.42.43.1' port='50000'
  protocol='tcp' network='0' foundation='0' component='1' type='local'
preference='0.75'
  name='transport4244206756'/>
<candidate generation='0' username='p7ZHXsFhtRPt7XPO' password=''
address='173.194.70.127'
  port='19305' protocol='udp' network='0' foundation='0' component='1'
type='relay' preference='0.5'
  name='transport4244206756'/>
<candidate generation='0' username='p7ZHXsFhtRPt7XPO' password=''
address='173.194.70.127'
  port='19305' protocol='tcp' network='0' foundation='0' component='1'
type='relay' preference='0.5'
  name='transport4244206756'/>
<candidate generation='0' username='p7ZHXsFhtRPt7XPO' password=''
address='173.194.70.127'
  port='443' protocol='ssltcp' network='0' foundation='0' component='1'
type='relay' preference='0.5'
  name='transport4244206756'/>
</transport>
</session>
</iq>

I don't understand why TCP candidates are created when my media stream
uses UDP transport ? Is it related to STUN or TURN ?

Next I wait to receive remote candidates:

<iq id="99" to="paweldomas@gmail.com/jitsi-17e2D6823090"
  from="pawelgawel293@gmail.com/Talk.v1046E1595C3" type="set">
<session xmlns='http://www.google.com/session' type='transport-info'
  initiator='pawelgawel293@gmail.com/Talk.v1046E1595C3' id='4244206756'>
<transport xmlns='http://www.google.com/transport/p2p'>
<candidate xmlns='http://www.google.com/transport/p2p'
name='transport4244206756'
  address='10.42.43.1' port='53530' preference='1'
username='GfLRNgE07OSBySKI' protocol='udp'
  generation='0' password='OnN3b9dXFawZPHDT' type='local' network='0'/>
</transport>
</session>
</iq>

<iq id="100" to="paweldomas@gmail.com/jitsi-17e2D6823090"
from="pawelgawel293@gmail.com/Talk.v1046E1595C3" type="set">
<session xmlns='http://www.google.com/session' type='transport-info'
initiator='pawelgawel293@gmail.com/Talk.v1046E1595C3' id='4244206756'>
<transport xmlns='http://www.google.com/transport/p2p'>
<candidate xmlns='http://www.google.com/transport/p2p'
name='transport4244206756' address='10.42.43.1' port='53519'
preference='1' username='nHuQYpuisQJdX0uC'
protocol='udp' generation='1' password='stefOg+WndrfcINQ' type='local'
network='0'/>
</transport>
</session>
</iq>

When each one of candidates is received I call
startConnectivityEstablishment(Iterable<GTalkCandidatePacketExtension>
remote) method to start connectivity establishment or update remote
candidates. When it start I get a lot of messages about credentials and
after some time connectivity establishement fails:

10:33:08.882 INFO:
org.ice4j.ice.ConnectivityCheckClient.processErrorResponse() stale
credentials for GTalk check for /192.168.1.203:50000/udp -> /
10.42.43.1:53530/udp (PTCP-DATA.1)
10:33:08.884 INFO:
org.ice4j.ice.ConnectivityCheckClient.processErrorResponse() stale
credentials for GTalk check for /81.219.122.3:50000/udp -> /
10.42.43.1:53530/udp (PTCP-DATA.1)
10:33:08.885 INFO:
org.ice4j.ice.ConnectivityCheckClient.processErrorResponse() stale
credentials for GTalk check for /192.168.0.203:50000/udp -> /
10.42.43.1:53530/udp (PTCP-DATA.1)
10:33:08.887 INFO:
org.ice4j.ice.ConnectivityCheckClient.processErrorResponse() stale
credentials for GTalk check for /10.42.43.1:50000/udp -> /
10.42.43.1:53530/udp (PTCP-DATA.1)
10:33:08.888 INFO:
org.ice4j.ice.ConnectivityCheckClient.processErrorResponse() stale
credentials for GTalk check for /192.168.1.203:50000/udp -> /
10.42.43.1:53530/udp (PTCP-DATA.1)
10:33:08.889 INFO:
org.ice4j.ice.ConnectivityCheckClient.processErrorResponse() stale
credentials for GTalk check for /81.219.122.3:50000/udp -> /
10.42.43.1:53530/udp (PTCP-DATA.1)
10:33:08.891 INFO:
org.ice4j.ice.ConnectivityCheckClient.processErrorResponse() stale
credentials for GTalk check for /192.168.0.203:50000/udp -> /
10.42.43.1:53530/udp (PTCP-DATA.1)

In method org.ice4j.ice.ConnectivityCheckClient.processErrorResponse()
there is comment about it:

// it may be an error due to remote peer that does not processed
// our candidates IQ and we start connectivity checks too quickly
// (that's why we get a STALE CREDENTIALS because remote peer does
// not know the candidate ufrag). So let's send another check for
// that pair

Do I have to set ufrag and password somewhere when I receive candidates ?
Any ideas how this may be fixed ?

Regards, Pawel Domas

Issue solved.

The problem was that my packet with candidates never arrived to the GTalk
client.

Regards the TCP components they are created when ice4j Agent class is
created in GTalk compatibility mode. To solve it I just don't send those
TCP components.

Regards, Paweł Domas

···

2012/8/4 Paweł Domas <paweldomas@gmail.com>


#13

Hey Pawel,

Hi,

Hi,

I'm at the point where ICE negotiations are performed. I've copied class
P2PTransportManager and modified it to create only one IceMediaStream for
UDP. Also I removed dependencies for CallPeer. Also some modifications
regards stream comonents were required. As result I have new
TransportManager class which I use to negotiate connection for file sharing.
I have few problems with it.

First I use method start startCandidateHarvest(CandidatesSender
candidatesSender) and when it finish the candidates are sent with message:

<iq id="03Scy-48" to="pawelgawel293@gmail.com/Talk.v1046E1595C3"
  from="paweldomas@gmail.com/jitsi-17e2D6823090"
  type="set">
<session xmlns='http://www.google.com/session' type='transport-info'
  initiator='pawelgawel293@gmail.com/Talk.v1046E1595C3' id='4244206756'>
<transport xmlns='http://www.google.com/transport/p2p'>
<candidate generation='0' username='fm0bradfsmdr45uu' password=''
address='192.168.1.203'
  port='50000' protocol='udp' network='0' foundation='0' component='1'
type='local' preference='0.95'
  name='transport4244206756'/>
<candidate generation='0' username='s9vqjdei9g6t5s2g' password=''
address='192.168.0.203'
  port='50000' protocol='udp' network='0' foundation='0' component='1'
type='local' preference='0.95'
  name='transport4244206756'/>
<candidate generation='0' username='42k0qqb0un7u9n65' password=''
address='10.42.43.1' port='50000'
  protocol='udp' network='0' foundation='0' component='1' type='local'
preference='0.95'
  name='transport4244206756'/>
<candidate generation='0' username='3dvrhs27gm617g78' password=''
address='81.219.122.3'
  port='50000' protocol='udp' network='0' foundation='0' component='1'
type='stun' preference='0.9'
  name='transport4244206756'/>
<candidate generation='0' username='58l1ao4urok0rfuu' password=''
address='192.168.1.203'
  port='50000' protocol='tcp' network='0' foundation='0' component='1'
type='local' preference='0.75'
  name='transport4244206756'/>
<candidate generation='0' username='5ks6q7i07rscp3ms' password=''
address='192.168.0.203'
  port='50000' protocol='tcp' network='0' foundation='0' component='1'
type='local' preference='0.75'
  name='transport4244206756'/>
<candidate generation='0' username='2ijtmodp5da7lkbq' password=''
address='10.42.43.1' port='50000'
  protocol='tcp' network='0' foundation='0' component='1' type='local'
preference='0.75'
  name='transport4244206756'/>
<candidate generation='0' username='p7ZHXsFhtRPt7XPO' password=''
address='173.194.70.127'
  port='19305' protocol='udp' network='0' foundation='0' component='1'
type='relay' preference='0.5'
  name='transport4244206756'/>
<candidate generation='0' username='p7ZHXsFhtRPt7XPO' password=''
address='173.194.70.127'
  port='19305' protocol='tcp' network='0' foundation='0' component='1'
type='relay' preference='0.5'
  name='transport4244206756'/>
<candidate generation='0' username='p7ZHXsFhtRPt7XPO' password=''
address='173.194.70.127'
  port='443' protocol='ssltcp' network='0' foundation='0' component='1'
type='relay' preference='0.5'
  name='transport4244206756'/>
</transport>
</session>
</iq>

I don't understand why TCP candidates are created when my media stream
uses UDP transport ? Is it related to STUN or TURN ?

Next I wait to receive remote candidates:

<iq id="99" to="paweldomas@gmail.com/jitsi-17e2D6823090"
  from="pawelgawel293@gmail.com/Talk.v1046E1595C3" type="set">
<session xmlns='http://www.google.com/session' type='transport-info'
  initiator='pawelgawel293@gmail.com/Talk.v1046E1595C3' id='4244206756'>
<transport xmlns='http://www.google.com/transport/p2p'>
<candidate xmlns='http://www.google.com/transport/p2p'
name='transport4244206756'
  address='10.42.43.1' port='53530' preference='1'
username='GfLRNgE07OSBySKI' protocol='udp'
  generation='0' password='OnN3b9dXFawZPHDT' type='local' network='0'/>
</transport>
</session>
</iq>

<iq id="100" to="paweldomas@gmail.com/jitsi-17e2D6823090"
from="pawelgawel293@gmail.com/Talk.v1046E1595C3" type="set">
<session xmlns='http://www.google.com/session' type='transport-info'
initiator='pawelgawel293@gmail.com/Talk.v1046E1595C3' id='4244206756'>
<transport xmlns='http://www.google.com/transport/p2p'>
<candidate xmlns='http://www.google.com/transport/p2p'
name='transport4244206756' address='10.42.43.1' port='53519'
preference='1' username='nHuQYpuisQJdX0uC'
protocol='udp' generation='1' password='stefOg+WndrfcINQ' type='local'
network='0'/>
</transport>
</session>
</iq>

When each one of candidates is received I call
startConnectivityEstablishment(Iterable<GTalkCandidatePacketExtension>
remote) method to start connectivity establishment or update remote
candidates. When it start I get a lot of messages about credentials and
after some time connectivity establishement fails:

10:33:08.882 INFO:
org.ice4j.ice.ConnectivityCheckClient.processErrorResponse() stale
credentials for GTalk check for /192.168.1.203:50000/udp ->
/10.42.43.1:53530/udp (PTCP-DATA.1)
10:33:08.884 INFO:
org.ice4j.ice.ConnectivityCheckClient.processErrorResponse() stale
credentials for GTalk check for /81.219.122.3:50000/udp ->
/10.42.43.1:53530/udp (PTCP-DATA.1)
10:33:08.885 INFO:
org.ice4j.ice.ConnectivityCheckClient.processErrorResponse() stale
credentials for GTalk check for /192.168.0.203:50000/udp ->
/10.42.43.1:53530/udp (PTCP-DATA.1)
10:33:08.887 INFO:
org.ice4j.ice.ConnectivityCheckClient.processErrorResponse() stale
credentials for GTalk check for /10.42.43.1:50000/udp ->
/10.42.43.1:53530/udp (PTCP-DATA.1)
10:33:08.888 INFO:
org.ice4j.ice.ConnectivityCheckClient.processErrorResponse() stale
credentials for GTalk check for /192.168.1.203:50000/udp ->
/10.42.43.1:53530/udp (PTCP-DATA.1)
10:33:08.889 INFO:
org.ice4j.ice.ConnectivityCheckClient.processErrorResponse() stale
credentials for GTalk check for /81.219.122.3:50000/udp ->
/10.42.43.1:53530/udp (PTCP-DATA.1)
10:33:08.891 INFO:
org.ice4j.ice.ConnectivityCheckClient.processErrorResponse() stale
credentials for GTalk check for /192.168.0.203:50000/udp ->
/10.42.43.1:53530/udp (PTCP-DATA.1)

In method org.ice4j.ice.ConnectivityCheckClient.processErrorResponse()
there is comment about it:

// it may be an error due to remote peer that does not processed
// our candidates IQ and we start connectivity checks too quickly
// (that's why we get a STALE CREDENTIALS because remote peer does
// not know the candidate ufrag). So let's send another check for
// that pair

Do I have to set ufrag and password somewhere when I receive candidates ?
Any ideas how this may be fixed ?

Regards, Pawel Domas

Issue solved.

The problem was that my packet with candidates never arrived to the GTalk
client.

Any idea why?

Regards the TCP components they are created when ice4j Agent class is
created in GTalk compatibility mode. To solve it I just don't send those TCP
components.

This doesn't sound right ;). GTalk can send RTP over TCP during an
audio/video call to improve firewall traversal so I don't see why they
would want to avoid that in an application where TCP fits better. Have
you tried generating an offer from within GTalk. Do they include TCP
among their candidates?

Emil

···

On Mon, Aug 6, 2012 at 9:08 PM, Paweł Domas <paweldomas@gmail.com> wrote:

2012/8/4 Paweł Domas <paweldomas@gmail.com>


#14

Hi,

Hey Pawel,

Hi,

Hi,

I'm at the point where ICE negotiations are performed. I've copied class
P2PTransportManager and modified it to create only one IceMediaStream for
UDP. Also I removed dependencies for CallPeer. Also some modifications
regards stream comonents were required. As result I have new
TransportManager class which I use to negotiate connection for file sharing.
I have few problems with it.

First I use method start startCandidateHarvest(CandidatesSender
candidatesSender) and when it finish the candidates are sent with message:

<iq id="03Scy-48" to="pawelgawel293@gmail.com/Talk.v1046E1595C3"
  from="paweldomas@gmail.com/jitsi-17e2D6823090"
  type="set">
<session xmlns='http://www.google.com/session' type='transport-info'
  initiator='pawelgawel293@gmail.com/Talk.v1046E1595C3' id='4244206756'>
<transport xmlns='http://www.google.com/transport/p2p'>
<candidate generation='0' username='fm0bradfsmdr45uu' password=''
address='192.168.1.203'
  port='50000' protocol='udp' network='0' foundation='0' component='1'
type='local' preference='0.95'
  name='transport4244206756'/>
<candidate generation='0' username='s9vqjdei9g6t5s2g' password=''
address='192.168.0.203'
  port='50000' protocol='udp' network='0' foundation='0' component='1'
type='local' preference='0.95'
  name='transport4244206756'/>
<candidate generation='0' username='42k0qqb0un7u9n65' password=''
address='10.42.43.1' port='50000'
  protocol='udp' network='0' foundation='0' component='1' type='local'
preference='0.95'
  name='transport4244206756'/>
<candidate generation='0' username='3dvrhs27gm617g78' password=''
address='81.219.122.3'
  port='50000' protocol='udp' network='0' foundation='0' component='1'
type='stun' preference='0.9'
  name='transport4244206756'/>
<candidate generation='0' username='58l1ao4urok0rfuu' password=''
address='192.168.1.203'
  port='50000' protocol='tcp' network='0' foundation='0' component='1'
type='local' preference='0.75'
  name='transport4244206756'/>
<candidate generation='0' username='5ks6q7i07rscp3ms' password=''
address='192.168.0.203'
  port='50000' protocol='tcp' network='0' foundation='0' component='1'
type='local' preference='0.75'
  name='transport4244206756'/>
<candidate generation='0' username='2ijtmodp5da7lkbq' password=''
address='10.42.43.1' port='50000'
  protocol='tcp' network='0' foundation='0' component='1' type='local'
preference='0.75'
  name='transport4244206756'/>
<candidate generation='0' username='p7ZHXsFhtRPt7XPO' password=''
address='173.194.70.127'
  port='19305' protocol='udp' network='0' foundation='0' component='1'
type='relay' preference='0.5'
  name='transport4244206756'/>
<candidate generation='0' username='p7ZHXsFhtRPt7XPO' password=''
address='173.194.70.127'
  port='19305' protocol='tcp' network='0' foundation='0' component='1'
type='relay' preference='0.5'
  name='transport4244206756'/>
<candidate generation='0' username='p7ZHXsFhtRPt7XPO' password=''
address='173.194.70.127'
  port='443' protocol='ssltcp' network='0' foundation='0' component='1'
type='relay' preference='0.5'
  name='transport4244206756'/>
</transport>
</session>
</iq>

I don't understand why TCP candidates are created when my media stream
uses UDP transport ? Is it related to STUN or TURN ?

Next I wait to receive remote candidates:

<iq id="99" to="paweldomas@gmail.com/jitsi-17e2D6823090"
  from="pawelgawel293@gmail.com/Talk.v1046E1595C3" type="set">
<session xmlns='http://www.google.com/session' type='transport-info'
  initiator='pawelgawel293@gmail.com/Talk.v1046E1595C3' id='4244206756'>
<transport xmlns='http://www.google.com/transport/p2p'>
<candidate xmlns='http://www.google.com/transport/p2p'
name='transport4244206756'
  address='10.42.43.1' port='53530' preference='1'
username='GfLRNgE07OSBySKI' protocol='udp'
  generation='0' password='OnN3b9dXFawZPHDT' type='local' network='0'/>
</transport>
</session>
</iq>

<iq id="100" to="paweldomas@gmail.com/jitsi-17e2D6823090"
from="pawelgawel293@gmail.com/Talk.v1046E1595C3" type="set">
<session xmlns='http://www.google.com/session' type='transport-info'
initiator='pawelgawel293@gmail.com/Talk.v1046E1595C3' id='4244206756'>
<transport xmlns='http://www.google.com/transport/p2p'>
<candidate xmlns='http://www.google.com/transport/p2p'
name='transport4244206756' address='10.42.43.1' port='53519'
preference='1' username='nHuQYpuisQJdX0uC'
protocol='udp' generation='1' password='stefOg+WndrfcINQ' type='local'
network='0'/>
</transport>
</session>
</iq>

When each one of candidates is received I call
startConnectivityEstablishment(Iterable<GTalkCandidatePacketExtension>
remote) method to start connectivity establishment or update remote
candidates. When it start I get a lot of messages about credentials and
after some time connectivity establishement fails:

10:33:08.882 INFO:
org.ice4j.ice.ConnectivityCheckClient.processErrorResponse() stale
credentials for GTalk check for /192.168.1.203:50000/udp ->
/10.42.43.1:53530/udp (PTCP-DATA.1)
10:33:08.884 INFO:
org.ice4j.ice.ConnectivityCheckClient.processErrorResponse() stale
credentials for GTalk check for /81.219.122.3:50000/udp ->
/10.42.43.1:53530/udp (PTCP-DATA.1)
10:33:08.885 INFO:
org.ice4j.ice.ConnectivityCheckClient.processErrorResponse() stale
credentials for GTalk check for /192.168.0.203:50000/udp ->
/10.42.43.1:53530/udp (PTCP-DATA.1)
10:33:08.887 INFO:
org.ice4j.ice.ConnectivityCheckClient.processErrorResponse() stale
credentials for GTalk check for /10.42.43.1:50000/udp ->
/10.42.43.1:53530/udp (PTCP-DATA.1)
10:33:08.888 INFO:
org.ice4j.ice.ConnectivityCheckClient.processErrorResponse() stale
credentials for GTalk check for /192.168.1.203:50000/udp ->
/10.42.43.1:53530/udp (PTCP-DATA.1)
10:33:08.889 INFO:
org.ice4j.ice.ConnectivityCheckClient.processErrorResponse() stale
credentials for GTalk check for /81.219.122.3:50000/udp ->
/10.42.43.1:53530/udp (PTCP-DATA.1)
10:33:08.891 INFO:
org.ice4j.ice.ConnectivityCheckClient.processErrorResponse() stale
credentials for GTalk check for /192.168.0.203:50000/udp ->
/10.42.43.1:53530/udp (PTCP-DATA.1)

In method org.ice4j.ice.ConnectivityCheckClient.processErrorResponse()
there is comment about it:

// it may be an error due to remote peer that does not processed
// our candidates IQ and we start connectivity checks too quickly
// (that's why we get a STALE CREDENTIALS because remote peer does
// not know the candidate ufrag). So let's send another check for
// that pair

Do I have to set ufrag and password somewhere when I receive candidates ?
Any ideas how this may be fixed ?

Regards, Pawel Domas

Issue solved.

The problem was that my packet with candidates never arrived to the GTalk
client.

Any idea why?

Regards the TCP components they are created when ice4j Agent class is
created in GTalk compatibility mode. To solve it I just don't send those TCP
components.

This doesn't sound right ;). GTalk can send RTP over TCP during an
audio/video call to improve firewall traversal so I don't see why they
would want to avoid that in an application where TCP fits better. Have
you tried generating an offer from within GTalk. Do they include TCP
among their candidates?

Emil

For now I'm not sending TCP packets, as I don't know how should I deal
with them as Pseudo Tcp is used with DatagramSockets.

I'm attaching a patch which will add support for Google Talk file
transfers in Jitsi. To enable it property
net.java.sip.communicator.impl.protocol.jabber.GOOGLE_FILE_TRANSFER_ENABLED
must be set to true.

In case of any troubles I may be not available between 6.09.2012 and 17.09.2012.

GTalkFileTransfer.patch (198 KB)

···

2012/8/7 Emil Ivov <emcho@jitsi.org>:

On Mon, Aug 6, 2012 at 9:08 PM, Paweł Domas <paweldomas@gmail.com> wrote:

2012/8/4 Paweł Domas <paweldomas@gmail.com>

--
Regards, Paweł Domas


#15

Hey Paweł,

Congrats for all the hard work! I hope you are enjoying your vacation!

In the mean time I had a quick look at your patch and have a few comments.

* there seems to be an issue with the patch itself. It contains
modifications on a file called GTalkFileShareTransportManager.java,
while the file itself does not insist in Jitsi.

* there are a number of methods that have incomplete, or entirely
missing javadoc comments:

There's for example this:

+ * Creates new instance of<tt>GTalkIncomingFileTransfer</tt>
+ *
+ * @param fileName
+ * @param fileSize
+ * @param ID
+ * @param contact
+ * @param session
+ * @param file

or this:

+ }

···

+
+ @Override
+ public long getTransferedBytes()

All of the above are of course just examples, and there are more so
you'd best walk over the entire patch.

* There are also some indentation problems like this:

+ */
+abstract class AbstractGTalkFileTransfer
+extends AbstractFileTransfer
+{

or this:

+ public static SessionIQ createSessionComplete(String from,
+ String to,
+ String sid,
+ String initiator)
+{
+SessionIQ complete = new SessionIQ();
+
+complete.setTo(to);
+complete.setFrom(from);
+complete.setInitiator(initiator);
+complete.setType(IQ.Type.SET);
+
+complete.setID(sid);
+complete.setGTalkType(GTalkType.INFO);
+
+complete.addExtension(new FileShareCompletePacketExt());
+
+return complete;
+}

Could you please have a look at those when you get a chance?

Thanks,
Emil

On 04.09.12, 21:51, Paweł Domas wrote:

Hi,

2012/8/7 Emil Ivov <emcho@jitsi.org>:

Hey Pawel,

On Mon, Aug 6, 2012 at 9:08 PM, Paweł Domas <paweldomas@gmail.com> wrote:

Hi,

2012/8/4 Paweł Domas <paweldomas@gmail.com>

Hi,

I'm at the point where ICE negotiations are performed. I've copied class
P2PTransportManager and modified it to create only one IceMediaStream for
UDP. Also I removed dependencies for CallPeer. Also some modifications
regards stream comonents were required. As result I have new
TransportManager class which I use to negotiate connection for file sharing.
I have few problems with it.

First I use method start startCandidateHarvest(CandidatesSender
candidatesSender) and when it finish the candidates are sent with message:

<iq id="03Scy-48" to="pawelgawel293@gmail.com/Talk.v1046E1595C3"
  from="paweldomas@gmail.com/jitsi-17e2D6823090"
  type="set">
<session xmlns='http://www.google.com/session' type='transport-info'
  initiator='pawelgawel293@gmail.com/Talk.v1046E1595C3' id='4244206756'>
<transport xmlns='http://www.google.com/transport/p2p'>
<candidate generation='0' username='fm0bradfsmdr45uu' password=''
address='192.168.1.203'
  port='50000' protocol='udp' network='0' foundation='0' component='1'
type='local' preference='0.95'
  name='transport4244206756'/>
<candidate generation='0' username='s9vqjdei9g6t5s2g' password=''
address='192.168.0.203'
  port='50000' protocol='udp' network='0' foundation='0' component='1'
type='local' preference='0.95'
  name='transport4244206756'/>
<candidate generation='0' username='42k0qqb0un7u9n65' password=''
address='10.42.43.1' port='50000'
  protocol='udp' network='0' foundation='0' component='1' type='local'
preference='0.95'
  name='transport4244206756'/>
<candidate generation='0' username='3dvrhs27gm617g78' password=''
address='81.219.122.3'
  port='50000' protocol='udp' network='0' foundation='0' component='1'
type='stun' preference='0.9'
  name='transport4244206756'/>
<candidate generation='0' username='58l1ao4urok0rfuu' password=''
address='192.168.1.203'
  port='50000' protocol='tcp' network='0' foundation='0' component='1'
type='local' preference='0.75'
  name='transport4244206756'/>
<candidate generation='0' username='5ks6q7i07rscp3ms' password=''
address='192.168.0.203'
  port='50000' protocol='tcp' network='0' foundation='0' component='1'
type='local' preference='0.75'
  name='transport4244206756'/>
<candidate generation='0' username='2ijtmodp5da7lkbq' password=''
address='10.42.43.1' port='50000'
  protocol='tcp' network='0' foundation='0' component='1' type='local'
preference='0.75'
  name='transport4244206756'/>
<candidate generation='0' username='p7ZHXsFhtRPt7XPO' password=''
address='173.194.70.127'
  port='19305' protocol='udp' network='0' foundation='0' component='1'
type='relay' preference='0.5'
  name='transport4244206756'/>
<candidate generation='0' username='p7ZHXsFhtRPt7XPO' password=''
address='173.194.70.127'
  port='19305' protocol='tcp' network='0' foundation='0' component='1'
type='relay' preference='0.5'
  name='transport4244206756'/>
<candidate generation='0' username='p7ZHXsFhtRPt7XPO' password=''
address='173.194.70.127'
  port='443' protocol='ssltcp' network='0' foundation='0' component='1'
type='relay' preference='0.5'
  name='transport4244206756'/>
</transport>
</session>
</iq>

I don't understand why TCP candidates are created when my media stream
uses UDP transport ? Is it related to STUN or TURN ?

Next I wait to receive remote candidates:

<iq id="99" to="paweldomas@gmail.com/jitsi-17e2D6823090"
  from="pawelgawel293@gmail.com/Talk.v1046E1595C3" type="set">
<session xmlns='http://www.google.com/session' type='transport-info'
  initiator='pawelgawel293@gmail.com/Talk.v1046E1595C3' id='4244206756'>
<transport xmlns='http://www.google.com/transport/p2p'>
<candidate xmlns='http://www.google.com/transport/p2p'
name='transport4244206756'
  address='10.42.43.1' port='53530' preference='1'
username='GfLRNgE07OSBySKI' protocol='udp'
  generation='0' password='OnN3b9dXFawZPHDT' type='local' network='0'/>
</transport>
</session>
</iq>

<iq id="100" to="paweldomas@gmail.com/jitsi-17e2D6823090"
from="pawelgawel293@gmail.com/Talk.v1046E1595C3" type="set">
<session xmlns='http://www.google.com/session' type='transport-info'
initiator='pawelgawel293@gmail.com/Talk.v1046E1595C3' id='4244206756'>
<transport xmlns='http://www.google.com/transport/p2p'>
<candidate xmlns='http://www.google.com/transport/p2p'
name='transport4244206756' address='10.42.43.1' port='53519'
preference='1' username='nHuQYpuisQJdX0uC'
protocol='udp' generation='1' password='stefOg+WndrfcINQ' type='local'
network='0'/>
</transport>
</session>
</iq>

When each one of candidates is received I call
startConnectivityEstablishment(Iterable<GTalkCandidatePacketExtension>
remote) method to start connectivity establishment or update remote
candidates. When it start I get a lot of messages about credentials and
after some time connectivity establishement fails:

10:33:08.882 INFO:
org.ice4j.ice.ConnectivityCheckClient.processErrorResponse() stale
credentials for GTalk check for /192.168.1.203:50000/udp ->
/10.42.43.1:53530/udp (PTCP-DATA.1)
10:33:08.884 INFO:
org.ice4j.ice.ConnectivityCheckClient.processErrorResponse() stale
credentials for GTalk check for /81.219.122.3:50000/udp ->
/10.42.43.1:53530/udp (PTCP-DATA.1)
10:33:08.885 INFO:
org.ice4j.ice.ConnectivityCheckClient.processErrorResponse() stale
credentials for GTalk check for /192.168.0.203:50000/udp ->
/10.42.43.1:53530/udp (PTCP-DATA.1)
10:33:08.887 INFO:
org.ice4j.ice.ConnectivityCheckClient.processErrorResponse() stale
credentials for GTalk check for /10.42.43.1:50000/udp ->
/10.42.43.1:53530/udp (PTCP-DATA.1)
10:33:08.888 INFO:
org.ice4j.ice.ConnectivityCheckClient.processErrorResponse() stale
credentials for GTalk check for /192.168.1.203:50000/udp ->
/10.42.43.1:53530/udp (PTCP-DATA.1)
10:33:08.889 INFO:
org.ice4j.ice.ConnectivityCheckClient.processErrorResponse() stale
credentials for GTalk check for /81.219.122.3:50000/udp ->
/10.42.43.1:53530/udp (PTCP-DATA.1)
10:33:08.891 INFO:
org.ice4j.ice.ConnectivityCheckClient.processErrorResponse() stale
credentials for GTalk check for /192.168.0.203:50000/udp ->
/10.42.43.1:53530/udp (PTCP-DATA.1)

In method org.ice4j.ice.ConnectivityCheckClient.processErrorResponse()
there is comment about it:

// it may be an error due to remote peer that does not processed
// our candidates IQ and we start connectivity checks too quickly
// (that's why we get a STALE CREDENTIALS because remote peer does
// not know the candidate ufrag). So let's send another check for
// that pair

Do I have to set ufrag and password somewhere when I receive candidates ?
Any ideas how this may be fixed ?

Regards, Pawel Domas

Issue solved.

The problem was that my packet with candidates never arrived to the GTalk
client.

Any idea why?

Regards the TCP components they are created when ice4j Agent class is
created in GTalk compatibility mode. To solve it I just don't send those TCP
components.

This doesn't sound right ;). GTalk can send RTP over TCP during an
audio/video call to improve firewall traversal so I don't see why they
would want to avoid that in an application where TCP fits better. Have
you tried generating an offer from within GTalk. Do they include TCP
among their candidates?

Emil

For now I'm not sending TCP packets, as I don't know how should I deal
with them as Pseudo Tcp is used with DatagramSockets.

I'm attaching a patch which will add support for Google Talk file
transfers in Jitsi. To enable it property
net.java.sip.communicator.impl.protocol.jabber.GOOGLE_FILE_TRANSFER_ENABLED
must be set to true.

In case of any troubles I may be not available between 6.09.2012 and 17.09.2012.

--
Emil Ivov, Ph.D. 67000 Strasbourg,
Project Lead France
Jitsi
emcho@jitsi.org PHONE: +33.1.77.62.43.30
http://jitsi.org FAX: +33.1.77.62.47.31


#16

Hi,

GTalkFileTransfer.patch (171 KB)

···

2012/9/14 Emil Ivov <emcho@jitsi.org>:

Hey Paweł,

Congrats for all the hard work! I hope you are enjoying your vacation!

In the mean time I had a quick look at your patch and have a few comments.

* there seems to be an issue with the patch itself. It contains
modifications on a file called GTalkFileShareTransportManager.java,
while the file itself does not insist in Jitsi.

* there are a number of methods that have incomplete, or entirely
missing javadoc comments:

There's for example this:

+ * Creates new instance of<tt>GTalkIncomingFileTransfer</tt>
+ *
+ * @param fileName
+ * @param fileSize
+ * @param ID
+ * @param contact
+ * @param session
+ * @param file

or this:

+ }
+
+ @Override
+ public long getTransferedBytes()

All of the above are of course just examples, and there are more so
you'd best walk over the entire patch.

* There are also some indentation problems like this:

+ */
+abstract class AbstractGTalkFileTransfer
+extends AbstractFileTransfer
+{

or this:

+ public static SessionIQ createSessionComplete(String from,
+ String to,
+ String sid,
+ String initiator)
+{
+SessionIQ complete = new SessionIQ();
+
+complete.setTo(to);
+complete.setFrom(from);
+complete.setInitiator(initiator);
+complete.setType(IQ.Type.SET);
+
+complete.setID(sid);
+complete.setGTalkType(GTalkType.INFO);
+
+complete.addExtension(new FileShareCompletePacketExt());
+
+return complete;
+}

Could you please have a look at those when you get a chance?

Thanks,
Emil

On 04.09.12, 21:51, Paweł Domas wrote:

Hi,

2012/8/7 Emil Ivov <emcho@jitsi.org>:

Hey Pawel,

On Mon, Aug 6, 2012 at 9:08 PM, Paweł Domas <paweldomas@gmail.com> wrote:

Hi,

2012/8/4 Paweł Domas <paweldomas@gmail.com>

Hi,

I'm at the point where ICE negotiations are performed. I've copied class
P2PTransportManager and modified it to create only one IceMediaStream for
UDP. Also I removed dependencies for CallPeer. Also some modifications
regards stream comonents were required. As result I have new
TransportManager class which I use to negotiate connection for file sharing.
I have few problems with it.

First I use method start startCandidateHarvest(CandidatesSender
candidatesSender) and when it finish the candidates are sent with message:

<iq id="03Scy-48" to="pawelgawel293@gmail.com/Talk.v1046E1595C3"
  from="paweldomas@gmail.com/jitsi-17e2D6823090"
  type="set">
<session xmlns='http://www.google.com/session' type='transport-info'
  initiator='pawelgawel293@gmail.com/Talk.v1046E1595C3' id='4244206756'>
<transport xmlns='http://www.google.com/transport/p2p'>
<candidate generation='0' username='fm0bradfsmdr45uu' password=''
address='192.168.1.203'
  port='50000' protocol='udp' network='0' foundation='0' component='1'
type='local' preference='0.95'
  name='transport4244206756'/>
<candidate generation='0' username='s9vqjdei9g6t5s2g' password=''
address='192.168.0.203'
  port='50000' protocol='udp' network='0' foundation='0' component='1'
type='local' preference='0.95'
  name='transport4244206756'/>
<candidate generation='0' username='42k0qqb0un7u9n65' password=''
address='10.42.43.1' port='50000'
  protocol='udp' network='0' foundation='0' component='1' type='local'
preference='0.95'
  name='transport4244206756'/>
<candidate generation='0' username='3dvrhs27gm617g78' password=''
address='81.219.122.3'
  port='50000' protocol='udp' network='0' foundation='0' component='1'
type='stun' preference='0.9'
  name='transport4244206756'/>
<candidate generation='0' username='58l1ao4urok0rfuu' password=''
address='192.168.1.203'
  port='50000' protocol='tcp' network='0' foundation='0' component='1'
type='local' preference='0.75'
  name='transport4244206756'/>
<candidate generation='0' username='5ks6q7i07rscp3ms' password=''
address='192.168.0.203'
  port='50000' protocol='tcp' network='0' foundation='0' component='1'
type='local' preference='0.75'
  name='transport4244206756'/>
<candidate generation='0' username='2ijtmodp5da7lkbq' password=''
address='10.42.43.1' port='50000'
  protocol='tcp' network='0' foundation='0' component='1' type='local'
preference='0.75'
  name='transport4244206756'/>
<candidate generation='0' username='p7ZHXsFhtRPt7XPO' password=''
address='173.194.70.127'
  port='19305' protocol='udp' network='0' foundation='0' component='1'
type='relay' preference='0.5'
  name='transport4244206756'/>
<candidate generation='0' username='p7ZHXsFhtRPt7XPO' password=''
address='173.194.70.127'
  port='19305' protocol='tcp' network='0' foundation='0' component='1'
type='relay' preference='0.5'
  name='transport4244206756'/>
<candidate generation='0' username='p7ZHXsFhtRPt7XPO' password=''
address='173.194.70.127'
  port='443' protocol='ssltcp' network='0' foundation='0' component='1'
type='relay' preference='0.5'
  name='transport4244206756'/>
</transport>
</session>
</iq>

I don't understand why TCP candidates are created when my media stream
uses UDP transport ? Is it related to STUN or TURN ?

Next I wait to receive remote candidates:

<iq id="99" to="paweldomas@gmail.com/jitsi-17e2D6823090"
  from="pawelgawel293@gmail.com/Talk.v1046E1595C3" type="set">
<session xmlns='http://www.google.com/session' type='transport-info'
  initiator='pawelgawel293@gmail.com/Talk.v1046E1595C3' id='4244206756'>
<transport xmlns='http://www.google.com/transport/p2p'>
<candidate xmlns='http://www.google.com/transport/p2p'
name='transport4244206756'
  address='10.42.43.1' port='53530' preference='1'
username='GfLRNgE07OSBySKI' protocol='udp'
  generation='0' password='OnN3b9dXFawZPHDT' type='local' network='0'/>
</transport>
</session>
</iq>

<iq id="100" to="paweldomas@gmail.com/jitsi-17e2D6823090"
from="pawelgawel293@gmail.com/Talk.v1046E1595C3" type="set">
<session xmlns='http://www.google.com/session' type='transport-info'
initiator='pawelgawel293@gmail.com/Talk.v1046E1595C3' id='4244206756'>
<transport xmlns='http://www.google.com/transport/p2p'>
<candidate xmlns='http://www.google.com/transport/p2p'
name='transport4244206756' address='10.42.43.1' port='53519'
preference='1' username='nHuQYpuisQJdX0uC'
protocol='udp' generation='1' password='stefOg+WndrfcINQ' type='local'
network='0'/>
</transport>
</session>
</iq>

When each one of candidates is received I call
startConnectivityEstablishment(Iterable<GTalkCandidatePacketExtension>
remote) method to start connectivity establishment or update remote
candidates. When it start I get a lot of messages about credentials and
after some time connectivity establishement fails:

10:33:08.882 INFO:
org.ice4j.ice.ConnectivityCheckClient.processErrorResponse() stale
credentials for GTalk check for /192.168.1.203:50000/udp ->
/10.42.43.1:53530/udp (PTCP-DATA.1)
10:33:08.884 INFO:
org.ice4j.ice.ConnectivityCheckClient.processErrorResponse() stale
credentials for GTalk check for /81.219.122.3:50000/udp ->
/10.42.43.1:53530/udp (PTCP-DATA.1)
10:33:08.885 INFO:
org.ice4j.ice.ConnectivityCheckClient.processErrorResponse() stale
credentials for GTalk check for /192.168.0.203:50000/udp ->
/10.42.43.1:53530/udp (PTCP-DATA.1)
10:33:08.887 INFO:
org.ice4j.ice.ConnectivityCheckClient.processErrorResponse() stale
credentials for GTalk check for /10.42.43.1:50000/udp ->
/10.42.43.1:53530/udp (PTCP-DATA.1)
10:33:08.888 INFO:
org.ice4j.ice.ConnectivityCheckClient.processErrorResponse() stale
credentials for GTalk check for /192.168.1.203:50000/udp ->
/10.42.43.1:53530/udp (PTCP-DATA.1)
10:33:08.889 INFO:
org.ice4j.ice.ConnectivityCheckClient.processErrorResponse() stale
credentials for GTalk check for /81.219.122.3:50000/udp ->
/10.42.43.1:53530/udp (PTCP-DATA.1)
10:33:08.891 INFO:
org.ice4j.ice.ConnectivityCheckClient.processErrorResponse() stale
credentials for GTalk check for /192.168.0.203:50000/udp ->
/10.42.43.1:53530/udp (PTCP-DATA.1)

In method org.ice4j.ice.ConnectivityCheckClient.processErrorResponse()
there is comment about it:

// it may be an error due to remote peer that does not processed
// our candidates IQ and we start connectivity checks too quickly
// (that's why we get a STALE CREDENTIALS because remote peer does
// not know the candidate ufrag). So let's send another check for
// that pair

Do I have to set ufrag and password somewhere when I receive candidates ?
Any ideas how this may be fixed ?

Regards, Pawel Domas

Issue solved.

The problem was that my packet with candidates never arrived to the GTalk
client.

Any idea why?

Regards the TCP components they are created when ice4j Agent class is
created in GTalk compatibility mode. To solve it I just don't send those TCP
components.

This doesn't sound right ;). GTalk can send RTP over TCP during an
audio/video call to improve firewall traversal so I don't see why they
would want to avoid that in an application where TCP fits better. Have
you tried generating an offer from within GTalk. Do they include TCP
among their candidates?

Emil

For now I'm not sending TCP packets, as I don't know how should I deal
with them as Pseudo Tcp is used with DatagramSockets.

I'm attaching a patch which will add support for Google Talk file
transfers in Jitsi. To enable it property
net.java.sip.communicator.impl.protocol.jabber.GOOGLE_FILE_TRANSFER_ENABLED
must be set to true.

In case of any troubles I may be not available between 6.09.2012 and 17.09.2012.

--
Emil Ivov, Ph.D. 67000 Strasbourg,
Project Lead France
Jitsi
emcho@jitsi.org PHONE: +33.1.77.62.43.30
http://jitsi.org FAX: +33.1.77.62.47.31

I've attached fixed patch version. Please let me know if there are
still any issues.

--
Regards, Paweł Domas


#17

Hi,

AbstractGTalkFileTransfer.java (5.04 KB)

GTalkFileShareManager.java (22.4 KB)

···

2012/9/19 Paweł Domas <paweldomas@gmail.com>:

Hi,

2012/9/14 Emil Ivov <emcho@jitsi.org>:

Hey Paweł,

Congrats for all the hard work! I hope you are enjoying your vacation!

In the mean time I had a quick look at your patch and have a few comments.

* there seems to be an issue with the patch itself. It contains
modifications on a file called GTalkFileShareTransportManager.java,
while the file itself does not insist in Jitsi.

* there are a number of methods that have incomplete, or entirely
missing javadoc comments:

There's for example this:

+ * Creates new instance of<tt>GTalkIncomingFileTransfer</tt>
+ *
+ * @param fileName
+ * @param fileSize
+ * @param ID
+ * @param contact
+ * @param session
+ * @param file

or this:

+ }
+
+ @Override
+ public long getTransferedBytes()

All of the above are of course just examples, and there are more so
you'd best walk over the entire patch.

* There are also some indentation problems like this:

+ */
+abstract class AbstractGTalkFileTransfer
+extends AbstractFileTransfer
+{

or this:

+ public static SessionIQ createSessionComplete(String from,
+ String to,
+ String sid,
+ String initiator)
+{
+SessionIQ complete = new SessionIQ();
+
+complete.setTo(to);
+complete.setFrom(from);
+complete.setInitiator(initiator);
+complete.setType(IQ.Type.SET);
+
+complete.setID(sid);
+complete.setGTalkType(GTalkType.INFO);
+
+complete.addExtension(new FileShareCompletePacketExt());
+
+return complete;
+}

Could you please have a look at those when you get a chance?

Thanks,
Emil

On 04.09.12, 21:51, Paweł Domas wrote:

Hi,

2012/8/7 Emil Ivov <emcho@jitsi.org>:

Hey Pawel,

On Mon, Aug 6, 2012 at 9:08 PM, Paweł Domas <paweldomas@gmail.com> wrote:

Hi,

2012/8/4 Paweł Domas <paweldomas@gmail.com>

Hi,

I'm at the point where ICE negotiations are performed. I've copied class
P2PTransportManager and modified it to create only one IceMediaStream for
UDP. Also I removed dependencies for CallPeer. Also some modifications
regards stream comonents were required. As result I have new
TransportManager class which I use to negotiate connection for file sharing.
I have few problems with it.

First I use method start startCandidateHarvest(CandidatesSender
candidatesSender) and when it finish the candidates are sent with message:

<iq id="03Scy-48" to="pawelgawel293@gmail.com/Talk.v1046E1595C3"
  from="paweldomas@gmail.com/jitsi-17e2D6823090"
  type="set">
<session xmlns='http://www.google.com/session' type='transport-info'
  initiator='pawelgawel293@gmail.com/Talk.v1046E1595C3' id='4244206756'>
<transport xmlns='http://www.google.com/transport/p2p'>
<candidate generation='0' username='fm0bradfsmdr45uu' password=''
address='192.168.1.203'
  port='50000' protocol='udp' network='0' foundation='0' component='1'
type='local' preference='0.95'
  name='transport4244206756'/>
<candidate generation='0' username='s9vqjdei9g6t5s2g' password=''
address='192.168.0.203'
  port='50000' protocol='udp' network='0' foundation='0' component='1'
type='local' preference='0.95'
  name='transport4244206756'/>
<candidate generation='0' username='42k0qqb0un7u9n65' password=''
address='10.42.43.1' port='50000'
  protocol='udp' network='0' foundation='0' component='1' type='local'
preference='0.95'
  name='transport4244206756'/>
<candidate generation='0' username='3dvrhs27gm617g78' password=''
address='81.219.122.3'
  port='50000' protocol='udp' network='0' foundation='0' component='1'
type='stun' preference='0.9'
  name='transport4244206756'/>
<candidate generation='0' username='58l1ao4urok0rfuu' password=''
address='192.168.1.203'
  port='50000' protocol='tcp' network='0' foundation='0' component='1'
type='local' preference='0.75'
  name='transport4244206756'/>
<candidate generation='0' username='5ks6q7i07rscp3ms' password=''
address='192.168.0.203'
  port='50000' protocol='tcp' network='0' foundation='0' component='1'
type='local' preference='0.75'
  name='transport4244206756'/>
<candidate generation='0' username='2ijtmodp5da7lkbq' password=''
address='10.42.43.1' port='50000'
  protocol='tcp' network='0' foundation='0' component='1' type='local'
preference='0.75'
  name='transport4244206756'/>
<candidate generation='0' username='p7ZHXsFhtRPt7XPO' password=''
address='173.194.70.127'
  port='19305' protocol='udp' network='0' foundation='0' component='1'
type='relay' preference='0.5'
  name='transport4244206756'/>
<candidate generation='0' username='p7ZHXsFhtRPt7XPO' password=''
address='173.194.70.127'
  port='19305' protocol='tcp' network='0' foundation='0' component='1'
type='relay' preference='0.5'
  name='transport4244206756'/>
<candidate generation='0' username='p7ZHXsFhtRPt7XPO' password=''
address='173.194.70.127'
  port='443' protocol='ssltcp' network='0' foundation='0' component='1'
type='relay' preference='0.5'
  name='transport4244206756'/>
</transport>
</session>
</iq>

I don't understand why TCP candidates are created when my media stream
uses UDP transport ? Is it related to STUN or TURN ?

Next I wait to receive remote candidates:

<iq id="99" to="paweldomas@gmail.com/jitsi-17e2D6823090"
  from="pawelgawel293@gmail.com/Talk.v1046E1595C3" type="set">
<session xmlns='http://www.google.com/session' type='transport-info'
  initiator='pawelgawel293@gmail.com/Talk.v1046E1595C3' id='4244206756'>
<transport xmlns='http://www.google.com/transport/p2p'>
<candidate xmlns='http://www.google.com/transport/p2p'
name='transport4244206756'
  address='10.42.43.1' port='53530' preference='1'
username='GfLRNgE07OSBySKI' protocol='udp'
  generation='0' password='OnN3b9dXFawZPHDT' type='local' network='0'/>
</transport>
</session>
</iq>

<iq id="100" to="paweldomas@gmail.com/jitsi-17e2D6823090"
from="pawelgawel293@gmail.com/Talk.v1046E1595C3" type="set">
<session xmlns='http://www.google.com/session' type='transport-info'
initiator='pawelgawel293@gmail.com/Talk.v1046E1595C3' id='4244206756'>
<transport xmlns='http://www.google.com/transport/p2p'>
<candidate xmlns='http://www.google.com/transport/p2p'
name='transport4244206756' address='10.42.43.1' port='53519'
preference='1' username='nHuQYpuisQJdX0uC'
protocol='udp' generation='1' password='stefOg+WndrfcINQ' type='local'
network='0'/>
</transport>
</session>
</iq>

When each one of candidates is received I call
startConnectivityEstablishment(Iterable<GTalkCandidatePacketExtension>
remote) method to start connectivity establishment or update remote
candidates. When it start I get a lot of messages about credentials and
after some time connectivity establishement fails:

10:33:08.882 INFO:
org.ice4j.ice.ConnectivityCheckClient.processErrorResponse() stale
credentials for GTalk check for /192.168.1.203:50000/udp ->
/10.42.43.1:53530/udp (PTCP-DATA.1)
10:33:08.884 INFO:
org.ice4j.ice.ConnectivityCheckClient.processErrorResponse() stale
credentials for GTalk check for /81.219.122.3:50000/udp ->
/10.42.43.1:53530/udp (PTCP-DATA.1)
10:33:08.885 INFO:
org.ice4j.ice.ConnectivityCheckClient.processErrorResponse() stale
credentials for GTalk check for /192.168.0.203:50000/udp ->
/10.42.43.1:53530/udp (PTCP-DATA.1)
10:33:08.887 INFO:
org.ice4j.ice.ConnectivityCheckClient.processErrorResponse() stale
credentials for GTalk check for /10.42.43.1:50000/udp ->
/10.42.43.1:53530/udp (PTCP-DATA.1)
10:33:08.888 INFO:
org.ice4j.ice.ConnectivityCheckClient.processErrorResponse() stale
credentials for GTalk check for /192.168.1.203:50000/udp ->
/10.42.43.1:53530/udp (PTCP-DATA.1)
10:33:08.889 INFO:
org.ice4j.ice.ConnectivityCheckClient.processErrorResponse() stale
credentials for GTalk check for /81.219.122.3:50000/udp ->
/10.42.43.1:53530/udp (PTCP-DATA.1)
10:33:08.891 INFO:
org.ice4j.ice.ConnectivityCheckClient.processErrorResponse() stale
credentials for GTalk check for /192.168.0.203:50000/udp ->
/10.42.43.1:53530/udp (PTCP-DATA.1)

In method org.ice4j.ice.ConnectivityCheckClient.processErrorResponse()
there is comment about it:

// it may be an error due to remote peer that does not processed
// our candidates IQ and we start connectivity checks too quickly
// (that's why we get a STALE CREDENTIALS because remote peer does
// not know the candidate ufrag). So let's send another check for
// that pair

Do I have to set ufrag and password somewhere when I receive candidates ?
Any ideas how this may be fixed ?

Regards, Pawel Domas

Issue solved.

The problem was that my packet with candidates never arrived to the GTalk
client.

Any idea why?

Regards the TCP components they are created when ice4j Agent class is
created in GTalk compatibility mode. To solve it I just don't send those TCP
components.

This doesn't sound right ;). GTalk can send RTP over TCP during an
audio/video call to improve firewall traversal so I don't see why they
would want to avoid that in an application where TCP fits better. Have
you tried generating an offer from within GTalk. Do they include TCP
among their candidates?

Emil

For now I'm not sending TCP packets, as I don't know how should I deal
with them as Pseudo Tcp is used with DatagramSockets.

I'm attaching a patch which will add support for Google Talk file
transfers in Jitsi. To enable it property
net.java.sip.communicator.impl.protocol.jabber.GOOGLE_FILE_TRANSFER_ENABLED
must be set to true.

In case of any troubles I may be not available between 6.09.2012 and 17.09.2012.

--
Emil Ivov, Ph.D. 67000 Strasbourg,
Project Lead France
Jitsi
emcho@jitsi.org PHONE: +33.1.77.62.43.30
http://jitsi.org FAX: +33.1.77.62.47.31

I've attached fixed patch version. Please let me know if there are
still any issues.

--
Regards, Paweł Domas

It would be great if someone could take a look on these two attached
files if they do match the Jitsi code style convention. I tried to
keep them comaptible as much as possible, but still I might have
missed something. When they will be ok I will know how to fix the rest
of them.

--
Regards, Paweł Domas


#18

Hi Pawel,

It would be great if someone could take a look on these two attached
files if they do match the Jitsi code style convention. I tried to
keep them comaptible as much as possible, but still I might have
missed something. When they will be ok I will know how to fix the rest
of them.

I've just had a look. They are pretty much ok, except for the following:

- there are some lines exceeding (both in code and javadocs) the 80th column.

- there are some trailing spaces too. You should be able to show them using your IDE. In Eclipse you can find the option in Preferences > General > Editors > Text Editors - "Show whitespace characters"

Something that's not in the code convention, but can help code readability is to put some empty lines between unrelated code snippets. For example in GTalkFileShareManager.processPacket you can put a new line between consecutive ifs and declarations. Like here:

if (logger.isDebugEnabled())
                {
                    logger.debug("Terminate/reject request for: "
                        + sessionIQ.getInitiator() + ":" + sessionIQ.getID());
                }
                String sessionID = sessionIQ.getID();
                GTalkFileShareSession transferSession = sessions.get(sessionID);
                if (transferSession == null)
                {
                    logger.warn("Session " + sessionID + " not found");
                    return;
                }
                // ACK received IQ
                ackIQ(sessionIQ);
                transferSession.remoteTerminateReceived();
                sessions.remove(sessionID);

But this is just my personal feeling :slight_smile:

Cheers,
Yana

···

--
Regards, Paweł Domas
<AbstractGTalkFileTransfer.java><GTalkFileShareManager.java>


#19

Hi,

Hi Pawel,

It would be great if someone could take a look on these two attached
files if they do match the Jitsi code style convention. I tried to
keep them comaptible as much as possible, but still I might have
missed something. When they will be ok I will know how to fix the rest
of them.

I've just had a look. They are pretty much ok, except for the following:

- there are some lines exceeding (both in code and javadocs) the 80th column.

- there are some trailing spaces too. You should be able to show them using your IDE. In Eclipse you can find the option in Preferences > General > Editors > Text Editors - "Show whitespace characters"

Something that's not in the code convention, but can help code readability is to put some empty lines between unrelated code snippets. For example in GTalkFileShareManager.processPacket you can put a new line between consecutive ifs and declarations. Like here:

if (logger.isDebugEnabled())
                {
                    logger.debug("Terminate/reject request for: "
                        + sessionIQ.getInitiator() + ":" + sessionIQ.getID());
                }
                String sessionID = sessionIQ.getID();
                GTalkFileShareSession transferSession = sessions.get(sessionID);
                if (transferSession == null)
                {
                    logger.warn("Session " + sessionID + " not found");
                    return;
                }
                // ACK received IQ
                ackIQ(sessionIQ);
                transferSession.remoteTerminateReceived();
                sessions.remove(sessionID);

But this is just my personal feeling :slight_smile:

Cheers,
Yana

--
Regards, Paweł Domas
<AbstractGTalkFileTransfer.java><GTalkFileShareManager.java>

Thanks for help ! I've fixed the rest of files to match these rules.

So regards the patch description.

I had to modify two manifest files to export Pseudo TCP functionality
to jabber package. These are:

net.java.sip.communicator.impl.netaddr.netaddr.manifest.mf <- added
export org.ice4j.pseudotcp
net.java.sip.communicator.impl.protocol.jabber.jabber.provider.manifest.mf
<-- added import here

The packages that I modify are:

net.java.sip.communicator.impl.protocol.jabber - here are contained
all logic classes

net.java.sip.communicator.impl.protocol.jabber.extensions.gtalk - here
are classes responible for creating/parsing XMPP packets extensions

First thing that enables GTalk file transfers is property named
net.java.sip.communicator.impl.protocol.jabber.GOOGLE_FILE_TRANSFER_ENABLED
which have to be set to "true" to enable file transfers. The code
responsible for that is in class ProtocolProviderServiceJabberImpl.

General class hierarchy

The main class is GtalkFileShareManager. It exposes method to create
new transfer sessions and these are used from
OperationSetFileTransferJabberImpl to send a file. It also listens to
XMPP packets that initiate file transfer sessions and creates new
incoming sessions.

For each session we can have multiple transfers. For incoming sessions
there are also transfer requests which are converted into transfers
once the user accepts the transfer. Session are active as long as
there are any valid transfers/requests or until remote peer cancels
the session. We have following classes which create this hierarchy:

GTalkFileShareSession - base class for both incoming and outgoing sessions

GTalkIncomingFileSession - class represents incoming sessions and it manages:
    GTalkIncomingFileTransferRequest - transfer request
    GTalkIncomingFileTransfer - incoming file transfers

GTalkOutgoingFileSession - class for outgoing sessions that consits of many:
    GTalkOutgoingFileTransfer - outgoing transfers

Now regards the connectivity establishement. Eeach file sharing
session uses the GTalkFileShareTransportManager. This class was
created out of the P2PTransportManager class which extends
IceUdpTransportManager.

I've been trying to extract some base class that could be used by both
file share sessions and P2PTransportManager however it is too much
dependent from CallPeer class. This class would have to encapsulate
basic ICE connectivity functions. However it ended up that I've
extracted methods for harvesting candidates and establishing
connectivity to GTalkFileShareTransportManager.

It uses common method for creating ICE agent that is
TransportManagerGTalkImpl.createAgent() so that I do not duplcate code
responsible for gathering harvesters.

I've created static utility methods in IceUdpTransportManager for
retrieving ICE datagram sockets and target addresses selected by ICE.
These are getStreamConnectorSockets and getStreamTargetAddresses in
IceUdpTransportManager. They are now shared with
GTalkFileShareTransportManager.

For now I am using only UDP candidates as I don't know how to handle
TCP socket with current Pseudo TCP implementation. Also I filtered out
IPv6 candidates as I had errors when transferring files with Empathy.
The code responsible for that is in
GTalkFileShareSession.sendCandidates().

Once the ICE connectivity is established files are transferred over
Psuedo TCP using some parts of HTTP protocol. For incoming file share
session this is done by GTalkIncomingFileTransfer class in method
httpGetFile(). Outgoing session are sharing single instance of
GTalkHTTPFileServer which sends all transfer files over HTTP.

The issue here is special characters encoding in URLs. I haven't found
appropriate method to convert them the same way as the GTalk client
does it. I've been trying some java URL classes and some Apache Http
methods, but with no luck. Currently the only thing I do is changing
spaces to %20.

That's all regards the logic. Now how are GTalk file sharing XMPP
packets plugged into the system.

This is done in SessionIQProvider. File sharing IQs are recognized by
the namespace: http://www.google.com/session/share
When "initiate" session IQ is received with that namespace it is
marked as a "filesharing" one. This is done in
SessionIQProvider.parseIQ method. I had to add a check for this
condition in OperationSetBasicTelephonyJabberImpl.acceptPacket() so
that telephony will reject these packets.
All extensions used by file sharing feature are parsed in SessionIQProvider.

Capabilities

The required capabilities are

"http://google.com/xmpp/protocol/share/v1" as a feature
and "share-v1" as an ext feature.

These are added in ProtocolProviderServiceJabberImpl if GTalk sharing
feature property is enabled.
To decide if remote peer supports file sharing I check if it support
at least one of these. That is probably wrong for the "ext" feature,
but the problem is that GTalk client is not propagating
http://google.com/xmpp/protocol/share/v1 feature at all, but it
requires it from other clients. It's only propagates only "ext"
feature as far as I've been able to check.

There is one issuse regards the capabilities. When Jitsi is started
and GTalk client will login after that, Jitsi will not cache this
"ext" feature properly. This may be because GTalk client is sending
these feature list 2 times. First time something like "voice-v1" and
immidiately after that "voice-v1 share-v1". When Jitsi logins after
GTalk client everything is ok.

That would be all regards the patch description. To sum it up there
are the following known issues:

- special characters are not encoded as they are in GTalk client, but
it will work with Jitsi<->Jitsi communication

- when GTalk client will login after the Jitsi, there is a problem
with detecting correct capabilities(as described above)

- when communicating with Empathy it sometimes sends invalid Pseudo
TCP packet and it occurs only when communicating with Jitsi (it's ok
between Empathy <-> GTalk as I checked it on Wireshark). The problem
is that first hello packet has 4 bytes of data when there should be
only 1. My stack considers this packet invalid. I checked that on
Empathy log and Pseudo TCP stack sends hello with single byte of data,
but there are 4 going out to the network.

GTalkFileTransfer.patch (185 KB)

···

2012/9/20 Yana Stamcheva <yana@jitsi.org>:

--
Regards, Paweł Domas


#20

Hi,

I'm sending new version of patch that will apply to the current build.

The description from previous post is valid except one change. I wrote:

Now regards the connectivity establishement. Eeach file sharing
session uses the GTalkFileShareTransportManager. This class was
created out of the P2PTransportManager class which extends
IceUdpTransportManager.

I've been trying to extract some base class that could be used by both
file share sessions and P2PTransportManager however it is too much
dependent from CallPeer class. This class would have to encapsulate
basic ICE connectivity functions. However it ended up that I've
extracted methods for harvesting candidates and establishing
connectivity to GTalkFileShareTransportManager.

It uses common method for creating ICE agent that is
TransportManagerGTalkImpl.createAgent() so that I do not duplcate code
responsible for gathering harvesters.

I've created static utility methods in IceUdpTransportManager for
retrieving ICE datagram sockets and target addresses selected by ICE.
These are getStreamConnectorSockets and getStreamTargetAddresses in
IceUdpTransportManager. They are now shared with
GTalkFileShareTransportManager.

Instead of what I wrote now I created class GTalkICEManager which consists
of shared parts extracted from
TransportManagerGTalkImpl so the code won't duplicate in
GTalkFileShareTransportManager.
It can't be abstract class because GTalkICEManager extends TransportManager
which is no use for file share manager because of dependency from the
CallPeer. To make it work I had to create interface which I called
GTalkICEInfoProvider. This interface handles ice stream components. This is
different for file sharing as there is only RTP component present.

GTalkFileTransfers.patch (262 KB)

···

2012/9/21 Paweł Domas <paweldomas@gmail.com>

--
Regards, Paweł Domas