Skip to content

Instantly share code, notes, and snippets.

@yehohanan7
Created May 25, 2014 18:13
Show Gist options
  • Save yehohanan7/e18663ff8dfea376b7d6 to your computer and use it in GitHub Desktop.
Save yehohanan7/e18663ff8dfea376b7d6 to your computer and use it in GitHub Desktop.
#Supervisor
defmodule Torrentex.TrackerSupervisor do
use Supervisor.Behaviour
@udp_port 9998
@tcp_port 9999
def start_link do
:supervisor.start_link(__MODULE__, [])
end
def init(_) do
IO.inspect "starting tracker supervisor..."
supervise([], strategy: :one_for_one)
end
def start_tracker(:tcp, torrent) do
:supervisor.start_child(__MODULE__, worker(Torrentex.TCPTracker, [@tcp_port, torrent], []))
end
def start_tracker(:udp, torrent) do
IO.inspect "starting udp tracker..."
IO.inspect worker(Torrentex.UDPTracker, [@udp_port, torrent], [])
:supervisor.start_child(__MODULE__, worker(Torrentex.UDPTracker, [@udp_port, torrent], []))
end
end
#Gen_Server
defmodule Torrentex.UDPTracker do
use GenServer.Behaviour
alias Torrentex.Url
@actions %{:connect => 0,
:announce => 1,
:scrape => 2,
:error => 3}
#External API
def start_link(port, torrent) do
:gen_server.start_link(__MODULE__, [port, torrent], [])
end
#GenServer Callbacks
def init([port, torrent]) do
{:ok, socket} = :gen_udp.open(port, [:binary, {:active, true}])
{:ok, %{:socket => socket, :torrent => torrent}, 0}
end
#Utilities
defp generate_transaction_id do
:crypto.rand_bytes(4)
end
#Outgoing messages
defp send_message({socket, torrent}, :announce) do
[domain, port] = Url.host(torrent[:announce])
:ok = :gen_udp.send(socket, domain, port, "data")
end
defp send_message({socket, torrent}, :connect) do
[domain, port] = Url.host(torrent[:announce])
:ok = :gen_udp.send(socket, domain, port, <<4497486125440::64,@actions[:connect]::32, generate_transaction_id::binary>>)
end
#initializer
def handle_info(:timeout, %{:socket => socket, :torrent => torrent} = state) do
send_message({socket, torrent}, :connect)
{:noreply, state}
end
#Incoming messages from socket
def handle_info({:udp, _, _ip, _port, packet}, state) do
{:noreply, state}
end
end
@sasa1977
Copy link

Hi.
I wasn't at irc when you sent this. I took a look, and I think your problem is in how you call start_child. Take a look at erlang docs for the function.

Essentially, you need to send supervisor pid to the function, and the child specification.

So your function should look like:

def start_tracker(supervisor_pid, :udp, torrent) do
  IO.inspect "starting udp tracker..."
  IO.inspect worker(Torrentex.UDPTracker, [@udp_port, torrent], [])
  :supervisor.start_child(supervisor_pid, worker(Torrentex.UDPTracker, [@udp_port, torrent], []))
end

You'd then do:

{:ok, pid} = Torrentex.TrackerSupervisor.start_link
Torrentex.TrackerSupervisor.start_tracker(pid, ...)

If you don't want to keep track of the supervisor pid, you can register it with a local alias, and use that alias as first argument to start_child.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment