This script is still in beta.
Naive implementation of BitTorrent Client (in Elixir), quick and dirty.
Run iex exbt.exs
to load the module into interactive shell
Create a new download job by providing:
- The .torrent file
- An non-exist dir for storing job's data
iex> myjob = Job.create("/tmp/test_job", "test/centos.torrent")
...
...
iex> Job.start(myjob)
Or from existing job dir:
iex> myjob = Job.load("/tmp/test_job")
...
...
iex> Job.start(myjob)
myjob = Job.create(<job_dir>, <path_of_torrent_file>)
myjob = Job.load(<job_dir>)
This will stop all process that relates to this job
Job.close(myjob)
Start connecting to peers and start downloading
Job.start(myjob)
Disconnect from peers. Stop all actions.
Job.stop(myjob)
Stop download/uploading data, but keep current connections
Job.pause(myjob)
Start download/uploading data
Job.resume(myjob)
iex(5)> Job.progress(job)
%{finished: 1105, percentage: 100.0, unfinished: 0}
OR
iex(6)> Job.finished?(myjob)
true
Job.set_max_connections(myjob, 5)
iex(8)> Job.files(myjob)
[
%{
"length" => 578813952,
"offset_start" => 0,
"path" => "CentOS-7-x86_64-NetInstall-1908/CentOS-7-x86_64-NetInstall-1908.iso",
"piece_index_range" => 0..1104
},
%{
"length" => 598,
"offset_start" => 578813952,
"path" => "CentOS-7-x86_64-NetInstall-1908/sha256sum.txt",
"piece_index_range" => 1104..1104
},
%{
"length" => 1458,
"offset_start" => 578814550,
"path" => "CentOS-7-x86_64-NetInstall-1908/sha256sum.txt.asc",
"piece_index_range" => 1104..1104
}
]
iex(9)> Job.status(myjob)
%{
connections: 0,
files: [
%{
"length" => 578813952,
"offset_start" => 0,
"path" => "CentOS-7-x86_64-NetInstall-1908/CentOS-7-x86_64-NetInstall-1908.iso",
"piece_index_range" => 0..1104
},
%{
"length" => 598,
"offset_start" => 578813952,
"path" => "CentOS-7-x86_64-NetInstall-1908/sha256sum.txt",
"piece_index_range" => 1104..1104
},
%{
"length" => 1458,
"offset_start" => 578814550,
"path" => "CentOS-7-x86_64-NetInstall-1908/sha256sum.txt.asc",
"piece_index_range" => 1104..1104
}
],
job_dir: "/tmp/test_bt",
progress: %{finished: 1105, percentage: 100.0, unfinished: 0}
}
iex(10)> Job.dir(myjob)
"/tmp/test_bt"
https://www.bittorrent.org/beps/bep_0003.html
Official spec of Bittorrent DHT Protocol (Mainline DHT)
http://www.bittorrent.org/beps/bep_0009.html
https://www.libtorrent.org/dht_store.html
- init_from_new_torrent
- init_from_torrent_info_hash
- init_from_new_metadata
- init_from_existing_job
- capacity
- nodes
- candidates
- last_changed
Bucket <id>
contains node with distance falls between
[2^<id-1>, 2^<id> - 1]
For example a DHT table with 4-bit node-space should have buckets:
bucket0: 0000 ~ 0000 (current node)
bucket1: 0001 ~ 0001
bucket2: 0010 ~ 0011
bucket3: 0100 ~ 0111
- new_bucket
- add_node
- add_candidate
- delete_node
- get_node_by_id
- get_nodes
- get_n_nodes
- has_node?
- has_candidate?
- without_node(node_id)
- get_most_trusty_node
- get_trusty_nodes
- get_most_questionable_node
- get_questionable_nodes
- size
- size_info
- is_full?
- is_fresh?
- refresh_node
- insert_to_sorted_nodes
- healthcheck_threshold
- buckets
- reference_node_id
- new_table
- get_node
- get_nodes
- reference_node_id
- set_bucket
- get_k_nearest_nodes
- get_bucket_num_by_distance(distance)
- get_corresponding_bucket
- get_corresponding_bucket_num
- size
General functions:
- get_error_types
- get_sender_id
- error_code
- to_bin
- from_bin
- from_buffer
- gen_transaction_id
- get_query_type
Functions that build KRPC messages:
- ping
- ping_response
- find_node
- find_node_response
- get_peers
- get_peers_response
- announce_peer
- announce_peer_response
- response
- error
- @ping_response_threshold
- @ping_response_threshold_sec
- @krpc_query_timeout
- @api_general_timeout
- @api_search_nodes_timeout
- node_id: node_id
- table: DHTTable
- peer_info: %{info_hash => compact_peer_list}
- token_server: token server pid
- waiting_response: %{transaction_id => {req_msg, req_pid} }
- socket: udp socket
- start_link
- init
- ping
- find_node
- node_id
- search_peers
- search_nodes
- schedule_node_check
- send_krpc_msg!
- do_add_node
- do_on_krpc_msg
- :node_id
- :ping
- :add_node
- :find_node
- :get_peers
- :stored_nearest_nodes
- :send_krpc_msg
- :bootstrap
- :udp
- :krpc
- :check_node_aliveness
- :krpc_query_timeout
- secret
- old_secret
- start_link
- init
- is_valid_token?
- request_token
- random_secret
- calculate_token
- :is_valid_token/2
- :request_token/1
- :loop_renew_secret
- id
- ip
- port
- last_active
- compact_info
- contact_info
- count_0_prefix_length
- node_distance_binary
- gen_random_bitstring
- gen_random_string
- gen_node_id
- parse_peers_val
- parse_nodes_val
- get_magnet_info_hash