qBittorrent should be remotely controlable

Registered by Christophe Dumez

It would be nice if qBittorrent could be remotely controllable using a web interface.

Blueprint information

Status:
Complete
Approver:
Christophe Dumez
Priority:
High
Drafter:
Ishan Arora
Direction:
Approved
Assignee:
Ishan Arora
Definition:
Approved
Series goal:
None
Implementation:
Implemented
Milestone target:
milestone icon 1.1.0
Started by
Ishan Arora
Completed by
Christophe Dumez

Related branches

Sprints

Whiteboard

This will be done in two parts.

1) A tiny HTTP server programmed in qBittorrent (backend)
2) An AJAX based web UI ie. static content (frontend)

Part 1 - HTTP Server (backend)

See RFC2616 for details on HTTP. This server will serve static content from Part 2, as well as dynamic JSON content from inside the program.

When a client logins, it will be given a session id and stored as a cookie. When ever

The JSON content will have a specific URL (eg. http://server:port/json.js) and it will look something like this

{
 dl_speed:x,
 up_speed:x,
 ratio:x
 torrents:[
  {
   name:torrent 1,
   hash:x,
   size:x,
   progress:x
   status:x
   dl_speed:x
   up_speed:x
   ratio:x
  },
  {
   name:torrent 2
   hash:x
   size:x
   progress:x
   status:x
   dl_speed:x
   up_speed:x
   ratio:x
  }
 ]
}

The above format will get defined as the development advances. Consequtive calls (from the same session) for JSON data will only return the contents that are modified. The JSON data will keep waiting until some content is modified.

The commands will have a scpecified URL (eg. http://server:port/command) and the command name and parameters will be passed as GET or POST variables (open for discussion).

Examples of commands URL will be
http://server:port/command?command=pause&hash=x
http://server:port/command?command=start&hash=x
http://server:port/command?command=del&hash=x
http://server:port/command?command=add&url=x

The response to any command will be JSON parsable. The format will be decided for each command, but as a general rule, the value will be falsy if the command was unsuccessful, and truthy otherwise.

Part 2 - Web UI (frontend)

This is the HTML, CSS, JS part. Using the above 2 mentioned URLs for dynamic data, An AJAX based UI will be made. The two dynamic URLs should be used asyncronously. The application should always have an asyncronous call for JSON data (http://server:port/json.js), ie as soon as a call for JSON data reponses, a new call should be made. This is how we mimic persistent connections.

We can have multiple frontends using the same backend. (open for discussion)

Authentification

A login/pass should be set in qBittorrent to restrict access to the web interface. Later, we could probably work on users management.

Chris:
Looks good to me :)
I like the GET method for passing parameters (command & hash variables).

Concerning the Web server, please make it as light as possible. Create a class called "WebServer" for example that I would instanciate only when the Web interface is enabled in program preferences (to save memory).

Communication between the Web server and qbittorrent core could be achieved in two ways:
 * Qt Signals/Slots
 * Socket

I think that Ishan took interest in the first method. Personnally I think the second one is more interesting because it is more reusable (for example, if we want to create a version of qBittorrent without GUI). Moreover, qBittorrent is already listening on a socket: at the moment it is using the socket to determine if there is already an instance of qbittorrent running, but we could extend that and add commands like :
 * DEL <torrent_hash>
 * ADD <url>
 * PAU <hash> // Pause
 * RES <hash> // Resume
 * ...

Communication from qBittorrent core to the Web interface. I think it should be enough to send the Bittorrent session (libtorrent class type) to the WebServer and it would be the web server that would give the info to the Web interface through JSON? is that right?

Authentication is definitely necessary. Just a Username/password in qbittorrent preferences should be enough at first, I agree.

Ishan:
Lightness and security of the webserver are the top priorities. My idea was to make a webserver class that would be part of qBittorrent core once GUI is separated. In that case using sockets doesn't sound good to me; we have signals and slots for that. In my opinion when GUI will be removed, a socketlistener will be added (like webserver) and it will use signals/slots to interact with the BTsession class. In that case our common interface will be the signals/slots used by BTsession. Using the socketlistener is adding a dependency on the webserver. What if I want to run qbittorrent only as a webinterface, as in i dont need any GUI client. Secondly if we use socket here and in next version we decide to change the socket protocol, the same change will be needed in webserver class. I think this model will introduce more redundancy then reuse of code. Another idea I am in favor of is that webserver could be inherited from the socket listener, reusing the signals/slots. But it seems that socket listener isn't a high priority now, so we could modify the code when it will be introduced.

About the communication, Chris is right. The webserver will use signals and slots to interact with BTsession. And all of the JSON, HTTP headers parsing and generation will be part of webserver.

Chris: It is applied in trunk. v1.1.0 will be the first one to get the Web interface. Great work guys :)
* It would be nice to split downloading and uploading torrents into separate lists though.

(?)

Work Items

This blueprint contains Public information 
Everyone can see this information.