JingleFT in main branch

Jingle file transfer has finally been merged into Gajim's default branch. Feel free to check it out, and report any bugs you find.

EDIT: Actually it is not yet merged right now, give it one week.

Stalled

I'm still working on jingleFT for Gajim (not much progress there). The changes for xep-135 (no progress at all there). A secret project involving i2p (I don't talk about projects before having done a beta. No much progress there either).


The jingleFT branch of Gajim does need some refactoring. I made a state diagram of the file transfer, and it looks awful.



Clearly there are unnecessary states like transport info and proxy activated. The events are somewhat ambiguous, and the states accepted and initialized should be merged into one.

I'll fix it. See if I can shake off being so stalled.

Getting into I2P

For a long time I have heard of I2P and I thought it was a good idea, but never actually tried to install it. Today I installed I2P and I have to say that I'm amazed by it. I was expecting a barely functioning app, very slow response times and crappy ported apps running on top of it. I was wrong.

The I2P router console is simply great. It include many apps, such as its own web, email and BitTorrent servers. I'm not very good at describing stuff, and reading about it's probably too dry. I would recommend anybody to try it first if they are interested. It is like discovering a new internet inside of the internet.

It is true that it lacks a lot of services, and that's why I want to know more about developing apps for I2P.

Jingle Bells, Jingle all the way

What have I been doing? I used the holidays to finally get some work done in the jingle_FT branch of gajim. It's progressing just fine. I would hope that before my vacations ends it will be stable enough to be merged into the main branch.




It would be a really good help if you check out the branch and report some bugs.

It is easy to do just follow these steps:

1- Check out the latest jingleFT branch

hg clone http://hg.gajim.org/gajim gajim

cd gajim

hg update jingleFT

2- Report any bugs you find.

Go to https://trac.gajim.org/newticket

Proposed changes to XEP-0135

Hi, I been working on some changes to XEP-0135.

* Replacing SI file transfer with jingle FT

* Replacing section 6, with a link pointing to section 5 of XEP-0234,
which already covers the same function.

* Adding support for pubsub, only for finding files using the method I
introduce bellow. It doesn't make much sense to traverse the directory
of every user subscribed to a pubsub, but it will make a lot of sense
searching for specific files. (XEP-0137 does not suffice for this)

For example:

A user is subscribed to the books pubsub channel. It sends a query,
looking for a book "Romeo and Juliet - By Shakespeare". The
subscribers reply if they get a match with information about their
files. The initiator requests the file from whoever has what he wants
and file transfer starts.


* A new section should be added to cover finding files by providing a
criteria, instead of just asking for all the files.

For example:

5.5 Finding Specific Files

Finding files by asking for a file list is not very practical if there
are too many files being shared. It is very resource intensive and it
is understood that the user may not be interested in all of the files,
but rather he or she would be interested in finding one specific file
or one specific kind of file (text, image or videos).

In order to do this, the identity stanza is used to match files by one
or more fields i.e. 'name', 'date', 'size', etc...

Example XX. Finding Specific Files


<iq type='get'

    from='hag66 at shakespeare.lit/pda'

    to='darkcave at shakespeare.lit'

    id='find45'>

<query xmlns='http://jabber.org/protocol/disco#info'

         node='files'>

<identity category='filesys' type='file' name='file1' />

</query>

</iq>




The fields in the identity stanza, are optional, but at least one
field MUST be provided. In this example, the responders will match its
files looking for the file names that contain 'file1' and are of the
size 1024..

Example XX. Returning with Matched Files


<iq type='result'

    from='darkcave at macbeth.shakespeare.lit'

    to='hag66 at shakespeare.lit/pda'

    id='find45'>

<query xmlns='http://jabber.org/protocol/disco#info'

         node='files/somefile'>

<identity category='filesys' type='file' name='file1'

hash='552da749930852c69ae5d2141d3766b1'/>

</query>

</iq>




A responding entity MUST include the name and the hash of the file.
Since more than one responder may respond with the same file, it is
strongly suggested that the initiator makes use of ranged file
transfers (as defined in XEP-0234), to speed up the file transfer.

Example XX. Finding files using Regular Expressions

Regular expressions may be use to find files that match the
expression. One or more fields can be used. The label attribute is
optional.


<iq type='get'

from='hag66 at shakespeare.lit/pda'

    to='darkcave at shakespeare.lit'

    id='find46'>

<query xmlns='http://jabber.org/protocol/disco#info'

         node='files'>

<identity category='filesys' type='file' name='file1'/>

<x xmlns='jabber:x:data' type='get'>

<field var='ssn' type='text-single' label='Social Security Number'>

<regex>([0-9]{3})-([0-9]{2})-([0-9]{4})</regex>

</field>

</query>

</iq>




The XML character data of this element is the pattern to apply. The
syntax of this content MUST be that defined for POSIX extended regular
expressions, including support for Unicode.

The element MUST contain character data only (i.e., not
contain any child elements) and MUST NOT possess any attributes.


Any feedback would be greatly appreciated, I just want to know if I am
on the right track here.

GSOC is over, now what?

Let's review what I did this summer:

* Stream Management

* IBB fallback for jingleFT

* Bidirectional Socks5 for jingleFT

I'm satisfied with what I have accomplished this summer. It was a wonderful experience. I would like to thank Yann (my mentor), Kevin (for putting up with all my annoying questions), Matt and Tobias.

My journey doesn't end here. I will continue to work in gajim. My goal is to have a full working implementation of jingle in gajim. For the bidirectional socks5, I had to rewrite a lot of stuff to make it work. Currently OpenSSL and proxies aren't working, but they will be fixed soon.


I've been a little distant this month because I've been partying like it is 1999


Jingle Relay Nodes

A couple of weeks ago, Thiago helped me out understand the basics of JIngle Relay Nodes. He explained that, the server needs to open 4 ports and transfer data coming into them with each one of the other. His exact email

In fact your server will have to open 4 ports in total, 1rtp+ 1rtcp
for each end point.
Lets call them A, A', B, B' respectively.

Every packet that arrives at A needs to be sent through B to whichever
address(IP:Port) is sending to B.
Every packet that arrives at A' needs to be sent through B' to
whichever address(IP:Port) is sending to B'.
Every packet that arrives at B needs to be sent through A to whichever
address(IP:Port) is sending to A.
Every packet that arrives at B' needs to be sent through A' to
whichever address(IP:Port) is sending to A'.

Exception:
* If no packet was received in a given port, packets to be sent
through that port should be discarded.

Remarks:
* There is no process to verify that a sender to a given port is the
real sender of the stream. The recommended mitigation is to create a
race of packets, for the latest 10 received packets in a given port,
only relay and update Address to the one sender holding the majority
of the packets.

I ended up implementing the same in TCP. mod_jinglerelaynodes.lua and mod_jinglechannel.lua

Permalink | Leave a comment  »

SOCKS5 and Peer-to-Peer File-Transfer in Swift

Here another update on the progress of my current Google Summer of Code project, adding file-transfer support to Swift.

I've finished my implementation of SOCKS5 bytestreams, which is the basis for peer-to-peer file transfer via TCP with Jingle.

The protocol for Jingle describes that both sides of a file-transfer start a SOCKS5 server and send each other a list of IP/port combinations which the other side can then try to connect to. This alone leads to direct peer-to-peer connection as long as only one side is behind a firewall/NAT, or in other words, at least one side is publicly accessible from the internet. Sadly most users are behind some kind of NAT at home (due to WLAN and DSL routers).

Here assisted candidates, IP/port combinations which were acquired with help of UPnP or NAT-PMP, come into play. A lot of home routers and similar devices support one of those protocols, and if enabled they allow a program like Swift to forward certain ports to itself and request the real public IP from the router.
The plan is to use the libraries from the MiniUPnP project. This turned out to be harder than expected, because the library doesn't provide an asynchronous API. I'll still use those libs but will have to change the design and move those API calls to a dedicated thread.

Kind of as a last resort, there are also SOCKS5 proxies. They are used if it's impossible to establish a direct peer-to-peer connection via TCP. This could be due to firewalls or NATs on both sides with no UPnP/NAT-PMP technologies being available at either end.

While this year's Summer of Code nears its end, my next tasks are basically implementing SOCKS5 proxy support, verification of received data using SHA-1 hash, some GUI work and general testing/cleanup.

Bidirectional jingle socks5 file transfer in Gajim

I've been busy these couple of weeks trying to make bidirectional jingle socks5 file transfer in Gajim. Currently in Gajim, it is the receiver who connects to the sender.

There are several class of interest here: SocksQueue, Socks5, Socks5Sender, Socks5Listener, and Socks5Receiver

Socks5Listener is the class in charge of binding to a port and accepting connections.  SocksQueue manages the file transfer, it keeps track of when a transfer is completed or canceled.

 Socks5Sender and Socks5Receiver, are in charge of sending and receiving the file, both of them are derived from the class Socks5. So, they are basically the same object with some minor differences.




As it can be seen from this picture, both objects are fairly similar, except for the receiver having the connect, do_connect, is_connected methods and the sender having the send_file method.

 Those objects are also in charged of the socks5 negotiation and they keep track of it by using this state machine:

StatusOperation
0 About to connect
1send version and auth types  / initial read
2 read auth response / reply with desired auth type
3 send 'connect' request /  read connect request
4 get approve of our request / approve connect
5????? / read file
6 retrieve file / ????


There are more states, but these are the most important. What I have been doing so far is that have been modifying the objects so that they can emulate each other. Each object, for every state, will only do the thing that's after the "/" or before it. As I wrote the table, the operation in the left side of the "/" is what the receiver does and in the the right side of it, is what the sender does.

So far in my code, the receiver and the sender, do the operations in from state 0-2 . But then I realized that my approach was wrong all along. Instead of making the objects do both operations, Socks5 should be able to do both operations, and then the receiver and the sender can just inherit that behavior.

Swift's New File Transfer UI

Here a short update on the UI. The following 4 pictures will roughly show the workflow of sending a file with Swift.

First you right-click on the contact you want to transfer a file to and select "Send File". That item will only be available if the client your contact uses supports Jingle File-Transfer.

Screenshot showing popup menu on the roster.

A chat view to that contact will appear showing you a chat bubble for the intended transfer. Here you can actually initiate the transfer or cancel it.

Screenshot showing send and cancel buttons in the normal chat view.

After you clicked the send button a input dialog for the description will appear at as soon as you've entered your description the transfer will be negotiated and started.

Screenshot showing input dialog to enter a description of what the user wants to transfer.

During the transfer the progress will be shown as a progress bar, like in many other chat applications. The actual presentation could be a bit smoother but this works for starters.

Screenshot of the chat view showing the progress of the current transfer.

Thanks go out to Jefry, who brought Gajim's file transfer implementation up-to-date, so I could test against it.