Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 11 additions & 8 deletions lib/jellyfish/peer.ex
Original file line number Diff line number Diff line change
Expand Up @@ -39,17 +39,20 @@ defmodule Jellyfish.Peer do
end
end

@spec new(peer(), map()) :: t()
@spec new(peer(), map()) :: {:ok, t()} | {:error, term()}
def new(type, options) do
id = UUID.uuid4()
options = Map.put(options, :peer_id, id)

{:ok, endpoint} = type.config(options)

%__MODULE__{
id: id,
type: type,
engine_endpoint: endpoint
}
with {:ok, endpoint} <- type.config(options) do
{:ok,
%__MODULE__{
id: id,
type: type,
engine_endpoint: endpoint
}}
else
{:error, _reason} = error -> error
end
end
end
71 changes: 38 additions & 33 deletions lib/jellyfish/peer/webrtc.ex
Original file line number Diff line number Diff line change
Expand Up @@ -18,44 +18,49 @@ defmodule Jellyfish.Peer.WebRTC do
"WebRTC peers can be used only if WEBRTC_USED environmental variable is not set to \"false\""
)

handshake_options = [
client_mode: false,
dtls_srtp: true
]
with {:ok, valid_opts} <-
OpenApiSpex.cast_value(options, JellyfishWeb.ApiSpec.Peer.WebRTC.schema()) do
handshake_options = [
client_mode: false,
dtls_srtp: true
]

simulcast? = true
webrtc_extensions = [Mid, Rid, RepairedRid, TWCC]
network_options = options.network_options
simulcast? = valid_opts.enableSimulcast
webrtc_extensions = [Mid, Rid, RepairedRid, TWCC]
network_options = options.network_options

filter_codecs =
case options.video_codec do
:h264 ->
&filter_codecs_h264/1
filter_codecs =
case options.video_codec do
:h264 ->
&filter_codecs_h264/1

:vp8 ->
&filter_codecs_vp8/1
:vp8 ->
&filter_codecs_vp8/1

nil ->
&any_codecs/1
end
nil ->
&any_codecs/1
end

{:ok,
%WebRTC{
rtc_engine: options.engine_pid,
ice_name: options.peer_id,
owner: self(),
integrated_turn_options: network_options[:integrated_turn_options],
integrated_turn_domain: network_options[:integrated_turn_domain],
handshake_opts: handshake_options,
filter_codecs: filter_codecs,
log_metadata: [peer_id: options.peer_id],
trace_context: nil,
webrtc_extensions: webrtc_extensions,
simulcast_config: %SimulcastConfig{
enabled: simulcast?,
initial_target_variant: fn _track -> :medium end
}
}}
{:ok,
%WebRTC{
rtc_engine: options.engine_pid,
ice_name: options.peer_id,
owner: self(),
integrated_turn_options: network_options[:integrated_turn_options],
integrated_turn_domain: network_options[:integrated_turn_domain],
handshake_opts: handshake_options,
filter_codecs: filter_codecs,
log_metadata: [peer_id: options.peer_id],
trace_context: nil,
webrtc_extensions: webrtc_extensions,
simulcast_config: %SimulcastConfig{
enabled: simulcast?,
initial_target_variant: fn _track -> :medium end
}
}}
else
{:error, _reason} = error -> error
end
end

defp filter_codecs_h264(%Encoding{name: "H264", format_params: fmtp}) do
Expand Down
48 changes: 29 additions & 19 deletions lib/jellyfish/room.ex
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,10 @@ defmodule Jellyfish.Room do
end
end

@spec add_peer(id(), Peer.peer()) :: {:ok, Peer.t()} | {:error, :reached_peers_limit}
def add_peer(room_id, peer_type) do
GenServer.call(registry_id(room_id), {:add_peer, peer_type})
@spec add_peer(id(), Peer.peer(), map()) ::
{:ok, Peer.t()} | :error | {:error, :reached_peers_limit}
def add_peer(room_id, peer_type, options \\ %{}) do
GenServer.call(registry_id(room_id), {:add_peer, peer_type, options})
end

@spec set_peer_connected(id(), Peer.id()) ::
Expand All @@ -95,9 +96,9 @@ defmodule Jellyfish.Room do
GenServer.call(registry_id(room_id), {:remove_peer, peer_id})
end

@spec add_component(id(), Component.component(), map() | nil) ::
@spec add_component(id(), Component.component(), map()) ::
{:ok, Component.t()} | :error | {:error, :incompatible_codec}
def add_component(room_id, component_type, options) do
def add_component(room_id, component_type, options \\ %{}) do
GenServer.call(registry_id(room_id), {:add_component, component_type, options})
end

Expand Down Expand Up @@ -126,23 +127,32 @@ defmodule Jellyfish.Room do
end

@impl true
def handle_call({:add_peer, peer_type}, _from, state) do
def handle_call({:add_peer, peer_type, options}, _from, state) do
{reply, state} =
if Enum.count(state.peers) == state.config.max_peers do
{{:error, :reached_peers_limit}, state}
else
options = %{
engine_pid: state.engine_pid,
network_options: state.network_options,
video_codec: state.config.video_codec
}

peer = Peer.new(peer_type, options)
state = put_in(state, [:peers, peer.id], peer)

Logger.info("Added peer #{inspect(peer.id)}")

{{:ok, peer}, state}
options =
Map.merge(
%{
engine_pid: state.engine_pid,
network_options: state.network_options,
video_codec: state.config.video_codec
},
options
)

with {:ok, peer} <- Peer.new(peer_type, options) do
state = put_in(state, [:peers, peer.id], peer)

Logger.info("Added peer #{inspect(peer.id)}")

{{:ok, peer}, state}
else
{:error, reason} ->
Logger.warn("Unable to add peer: #{inspect(reason)}")
{:error, state}
end
end

{:reply, reply, state}
Expand Down Expand Up @@ -214,7 +224,7 @@ defmodule Jellyfish.Room do
options =
Map.merge(
%{engine_pid: state.engine_pid, room_id: state.id},
if(is_nil(options), do: %{}, else: options)
options
)

with :ok <- check_video_codec(video_codec, component_type),
Expand Down
18 changes: 17 additions & 1 deletion lib/jellyfish_web/api_spec/peer.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ defmodule JellyfishWeb.ApiSpec.Peer do
@moduledoc false

require OpenApiSpex

alias OpenApiSpex.Schema

alias JellyfishWeb.ApiSpec.Peer.WebRTC

defmodule Type do
@moduledoc false

Expand All @@ -18,6 +19,21 @@ defmodule JellyfishWeb.ApiSpec.Peer do
})
end

defmodule Options do
@moduledoc false

require OpenApiSpex

OpenApiSpex.schema(%{
title: "PeerOptions",
description: "Peer-specific options",
type: :object,
oneOf: [
WebRTC
]
})
end

defmodule Status do
@moduledoc false

Expand Down
19 changes: 19 additions & 0 deletions lib/jellyfish_web/api_spec/peer/webrtc.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
defmodule JellyfishWeb.ApiSpec.Peer.WebRTC do
@moduledoc false

require OpenApiSpex
alias OpenApiSpex.Schema

OpenApiSpex.schema(%{
title: "PeerOptionsWebRTC",
description: "Options specific to the WebRTC peer",
type: :object,
properties: %{
enableSimulcast: %Schema{
type: :boolean,
description: "Enables the peer to use simulcast",
default: true
}
}
})
end
2 changes: 1 addition & 1 deletion lib/jellyfish_web/controllers/component_controller.ex
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ defmodule JellyfishWeb.ComponentController do
]

def create(conn, %{"room_id" => room_id} = params) do
with component_options <- Map.get(params, "options"),
with component_options <- Map.get(params, "options", %{}),
{:ok, component_type_string} <- Map.fetch(params, "type"),
{:ok, component_type} <- Component.parse_type(component_type_string),
{:ok, _room_pid} <- RoomService.find_room(room_id),
Expand Down
8 changes: 5 additions & 3 deletions lib/jellyfish_web/controllers/peer_controller.ex
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,10 @@ defmodule JellyfishWeb.PeerController do
%Schema{
type: :object,
properties: %{
options: ApiSpec.Peer.Options,
type: ApiSpec.Peer.Type
},
required: [:type]
required: [:type, :options]
}},
responses: [
created: ApiSpec.data("Peer successfully created", ApiSpec.PeerDetailsResponse),
Expand Down Expand Up @@ -64,10 +65,11 @@ defmodule JellyfishWeb.PeerController do
# pid and adding a new peer to it
# in such a case, the controller will fail
# and Phoenix will return 500
with {:ok, peer_type_string} <- Map.fetch(params, "type"),
with peer_options <- Map.get(params, "options", %{}),
{:ok, peer_type_string} <- Map.fetch(params, "type"),
{:ok, peer_type} <- Peer.parse_type(peer_type_string),
{:ok, _room_pid} <- RoomService.find_room(room_id),
{:ok, peer} <- Room.add_peer(room_id, peer_type) do
{:ok, peer} <- Room.add_peer(room_id, peer_type, peer_options) do
assigns = [peer: peer, token: PeerToken.generate(%{peer_id: peer.id, room_id: room_id})]

conn
Expand Down
38 changes: 21 additions & 17 deletions openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,23 @@ components:
title: PeerDetailsResponse
type: object
x-struct: Elixir.JellyfishWeb.ApiSpec.PeerDetailsResponse
PeerOptions:
description: Peer-specific options
oneOf:
- $ref: '#/components/schemas/PeerOptionsWebRTC'
title: PeerOptions
type: object
x-struct: Elixir.JellyfishWeb.ApiSpec.Peer.Options
PeerOptionsWebRTC:
description: Options specific to the WebRTC peer
properties:
enableSimulcast:
default: true
description: Enables the peer to use simulcast
type: boolean
title: PeerOptionsWebRTC
type: object
x-struct: Elixir.JellyfishWeb.ApiSpec.Peer.WebRTC
PeerStatus:
description: Informs about the peer status
enum:
Expand Down Expand Up @@ -203,22 +220,6 @@ components:
title: RoomConfig
type: object
x-struct: Elixir.JellyfishWeb.ApiSpec.Room.Config
RoomCreateDetailsResponse:
description: Response containing room details
properties:
data:
properties:
room:
$ref: '#/components/schemas/Room'
jellyfish_address:
description: Jellyfish instance address where the room was created. This might be different than the address of Jellyfish where the request was sent only when running a cluster of Jellyfishes.
example: "jellyfish1:5003"
type: string
required:
- data
title: RoomDetailsResponse
type: object
x-struct: Elixir.JellyfishWeb.ApiSpec.RoomDetailsResponse
RoomDetailsResponse:
description: Response containing room details
properties:
Expand Down Expand Up @@ -287,7 +288,7 @@ paths:
content:
application/json:
schema:
$ref: '#/components/schemas/RoomCreateDetailsResponse'
$ref: '#/components/schemas/RoomDetailsResponse'
description: Room successfully created
'400':
content:
Expand Down Expand Up @@ -470,10 +471,13 @@ paths:
application/json:
schema:
properties:
options:
$ref: '#/components/schemas/PeerOptions'
type:
$ref: '#/components/schemas/PeerType'
required:
- type
- options
type: object
description: Peer specification
required: false
Expand Down