Don't attempt to stop the full client on peers' IOExceptions

Recoverable IOExceptions from single peers actually can happen if a
message is being sent to a peer at the same time it disconnects. The
previous way of handling this was to kill the client in the belief that
the IOException resulted from a local, unrecoverable error, and could
actually result in a dead lock trying to stop the client.

Signed-off-by: Maxime Petazzoni <mpetazzoni@turn.com>
Logging improvements

Rewording and improving some messages and some tweaks to logging levels.

Signed-off-by: Maxime Petazzoni <mpetazzoni@turn.com>
Correctly report RuntimeExceptions during data hashing

Signed-off-by: Maxime Petazzoni <mpetazzoni@turn.com>
Use a single pre-allocated direct byte buffer for receiving

This greatly reduces non-heap memory usage.

Signed-off-by: Maxime Petazzoni <mpetazzoni@turn.com>
Fix HAVE announce bug

When a peer completes the download of a piece, it sends a HAVE message
to all connected peers to inform them that it now has this piece.
Because the same created message was used to send to all peers, all
sending threads were accessing the same ByteBuffer when sending and
some threads would see the buffer has containing no data because the
buffer's position was changed by other threads.

This fixes the problem by always returning a new ByteBuffer view from
the message's underlying data buffer. They are backed by the same data,
but the buffer's position, mark and limit are independent.

Signed-off-by: Maxime Petazzoni <mpetazzoni@turn.com>
Implement a basic end-game scenario

Implement a end-game by making the best use of all ready peers even if
pieces have already been requested from other peers. Right now this is
not limited to the end of the download and can happen at anytime, trying
to make the most of the network bandwidth.

The first peer that gets the full piece back wins, the rest of the
blocks will be discarded.

This change required a bit more synchronization plumbing around pieces
and ongoing requests.

Signed-off-by: Maxime Petazzoni <mpetazzoni@turn.com>
Fix torrent creation time

Date.getTime() returns milliseconds but the creation date in the torrent
metainfo structure should be a timestamp in seconds since Epoch. This
caused the date of torrents created by the Torrent utility to be
invalid.

Signed-off-by: Maxime Petazzoni <mpetazzoni@turn.com>
Use JArgs for argument parsing in Torrent utility

Rework the command-line interface of the Torrent reader/creator utility
to use JArgs for argument parsing.

Initial patch provided by David Millar <david.w.millar@gmail.com>.

Signed-off-by: Maxime Petazzoni <mpetazzoni@turn.com>
Removed useless parent parameter from Torrent constructor

Signed-off-by: Maxime Petazzoni <mpetazzoni@turn.com>
ttorrent release 1.2

New major release of ttorrent, now in version 1.2. This version includes
recent work on the client code:

  - switch to NIO sockets and zero-copy buffers, with great performance
    improvements;
  - correct handling of tracker error messages in the client (#26);
  - correct handling of IOExceptions when reading from/writing to peers;
  - fixed an important bug in HAVE message broadcast that would lead to
    peers not being sent the HAVE message, resulting in incomplete piece
    availability information in the swarm;
  - implemented basic eng-game type scenario that allows the same piece
    to be requested from multiple peers if peers are ready;
  - fixed the creation time placed in the torrent meta-info structure
    when creating a torrent with Torrent.create()
  - use JArgs for command-line option parsing in the Torrent utility.

Signed-off-by: Maxime Petazzoni <mpetazzoni@turn.com>
Access to a synchronizedSet must be synchronized (#28).

Reported by Le Wang <larrie.wang@gmail.com>.

Signed-off-by: Maxime Petazzoni <mpetazzoni@turn.com>
Restrict end-game behavior to end of download

Signed-off-by: Maxime Petazzoni <mpetazzoni@turn.com>
Use buffer.rewind() instead of buffer.clear() in Piece._read()

Buffer.clear() was a confusing call as it felt like the data read into
the buffer was discarded (although it's not). Buffer.rewind() is a much
better use of the Buffer API.

Suggested-by: Carl Ericsson <carl.ericsson@gmail.com>
Signed-off-by: Maxime Petazzoni <mpetazzoni@turn.com>
Optimization: avoid creating too much buffers, use the inherited torrentHash instead of separate byte buffer in every Piece object
pass SharedTorrent to the individual Piece objects, so a lot's of unnecessary data duplication can be avoided.