-
Notifications
You must be signed in to change notification settings - Fork 12
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Don't accept streams until server is ready to read them #94
Changes from 22 commits
e358e26
a9166de
85e49c2
7018f7a
44f1690
6089407
52ff895
db779f3
2ddc8f3
6b79c2a
54b6e50
b61aad8
fcffb0d
8283bdc
614ec22
d068af2
0579cfb
ff54122
b3a0720
9bd3632
859550b
29709ae
c3357ce
9aa29b7
032b5e2
76d45d1
ca181ea
b5f8263
938fb06
ed16832
0fa80b1
b31bbd3
822aa2e
81d30d9
b2a21c6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -1,6 +1,14 @@ | ||||||
defmodule Membrane.RTMP.Server do | ||||||
@moduledoc """ | ||||||
A simple RTMP server, which handles each new incoming connection. | ||||||
A simple RTMP server, which handles each new incoming connection. When a new client connects, the new_client_callback is invoked. | ||||||
varsill marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
New connections remain in an incomplete RTMP handshake state until another process makes demand for dara data. | ||||||
varsill marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
If no data is demanded within the client_timeout period, the connection is closed. | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Perhaps it's good to emphasise that it's a client TCP socket that is closed under such circumstances? |
||||||
|
||||||
Options: | ||||||
- client_timeout: Time (ms) after which an unused connection is automatically closed. | ||||||
varsill marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
- new_client_callback: An anonymous function called when a new client connects. | ||||||
It receives the client reference, app and stream_key, allowing custom processing, | ||||||
like sending the reference to another process. | ||||||
""" | ||||||
use GenServer | ||||||
|
||||||
|
@@ -15,7 +23,12 @@ defmodule Membrane.RTMP.Server do | |||||
handler: ClientHandlerBehaviour.t(), | ||||||
port: :inet.port_number(), | ||||||
use_ssl?: boolean(), | ||||||
name: atom() | nil | ||||||
name: atom() | nil, | ||||||
new_client_callback: (client_ref :: pid(), | ||||||
app :: String.t(), | ||||||
stream_key :: String.t() -> | ||||||
any()), | ||||||
client_timeout: non_neg_integer() | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In most plugins we use
Suggested change
|
||||||
] | ||||||
|
||||||
@type server_identifier :: pid() | atom() | ||||||
|
@@ -30,33 +43,6 @@ defmodule Membrane.RTMP.Server do | |||||
GenServer.start_link(__MODULE__, server_options, gen_server_opts) | ||||||
end | ||||||
|
||||||
@doc """ | ||||||
Subscribes for the given app and stream key. | ||||||
When a client connects (or has already connected) to the server with given app and stream key, | ||||||
the subscriber will be informed. | ||||||
""" | ||||||
@spec subscribe(server_identifier(), String.t(), String.t()) :: :ok | ||||||
def subscribe(server_identifier, app, stream_key) do | ||||||
GenServer.cast(server_identifier, {:subscribe, app, stream_key, self()}) | ||||||
:ok | ||||||
end | ||||||
|
||||||
@doc """ | ||||||
Awaits for the client reference of the connection to which the user has previously subscribed. | ||||||
|
||||||
Note: this function call is blocking! | ||||||
Note: first you need to call `#{__MODULE__}.subscribe/3` to subscribe | ||||||
for a given `app` and `stream_key`. | ||||||
""" | ||||||
@spec await_subscription(String.t(), String.t(), non_neg_integer()) :: {:ok, pid()} | :error | ||||||
def await_subscription(app, stream_key, timeout \\ 5_000) do | ||||||
receive do | ||||||
{:client_ref, client_ref, ^app, ^stream_key} -> {:ok, client_ref} | ||||||
after | ||||||
timeout -> :error | ||||||
end | ||||||
end | ||||||
|
||||||
@doc """ | ||||||
Returns the port on which the server listens for connection. | ||||||
""" | ||||||
|
@@ -74,8 +60,6 @@ defmodule Membrane.RTMP.Server do | |||||
|
||||||
{:ok, | ||||||
%{ | ||||||
subscriptions: %{}, | ||||||
client_reference_mapping: %{}, | ||||||
listener: pid, | ||||||
port: nil, | ||||||
to_reply: [], | ||||||
|
@@ -92,33 +76,9 @@ defmodule Membrane.RTMP.Server do | |||||
end | ||||||
end | ||||||
|
||||||
@impl true | ||||||
def handle_cast({:subscribe, app, stream_key, subscriber_pid}, state) do | ||||||
state = put_in(state, [:subscriptions, {app, stream_key}], subscriber_pid) | ||||||
maybe_send_subscription(app, stream_key, state) | ||||||
{:noreply, state} | ||||||
end | ||||||
|
||||||
@impl true | ||||||
def handle_info({:register_client, app, stream_key, client_reference_pid}, state) do | ||||||
state = put_in(state, [:client_reference_mapping, {app, stream_key}], client_reference_pid) | ||||||
maybe_send_subscription(app, stream_key, state) | ||||||
{:noreply, state} | ||||||
end | ||||||
|
||||||
@impl true | ||||||
def handle_info({:port, port}, state) do | ||||||
Enum.each(state.to_reply, &GenServer.reply(&1, port)) | ||||||
{:noreply, %{state | port: port, to_reply: []}} | ||||||
end | ||||||
|
||||||
defp maybe_send_subscription(app, stream_key, state) do | ||||||
if state.subscriptions[{app, stream_key}] != nil and | ||||||
state.client_reference_mapping[{app, stream_key}] != nil do | ||||||
send( | ||||||
state.subscriptions[{app, stream_key}], | ||||||
{:client_ref, state.client_reference_mapping[{app, stream_key}], app, stream_key} | ||||||
) | ||||||
end | ||||||
end | ||||||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.