Current section
Files
Jump to
Current section
Files
src/n2o_signaling.erl
-module(n2o_signaling).
-behaviour('Elixir.WebSock').
-export([init/1, handle_in/2, handle_info/2, terminate/2]).
-record(state, {
user_id :: binary(),
room_id :: binary(),
role :: binary(),
peer_id :: binary(),
room_pid :: pid()
}).
init({UserId, RoomId, Role, Token}) ->
PeerId = <<"peer_", (integer_to_binary(erlang:unique_integer([positive])))/binary>>,
{ok, RoomPid} = room_coordinator:ensure_started(RoomId),
case Token of
undefined -> ok;
<<>> -> ok;
_ -> session_token:update_device(Token, PeerId)
end,
State = #state{
user_id = UserId,
room_id = RoomId,
role = Role,
peer_id = PeerId,
room_pid = RoomPid
},
ok = syn:register(rooms, PeerId, self()),
self() ! send_init_msg,
{ok, State}.
handle_in({Msg, Opts} = Frame, State) ->
error_logger:info_msg("Signaling handler received frame: ~p, state=~p~n", [Frame, State]),
Opcode = proplists:get_value(opcode, Opts, text),
case Opcode of
text ->
Data = jsone:decode(Msg),
Type = maps:get(<<"type">>, Data, <<>>),
PeerId = State#state.peer_id,
case Type of
<<"ready">> ->
case room_coordinator:originate_video(State#state.room_pid, PeerId, self()) of
{ok, StartedAt} ->
self() ! {send_room_info, StartedAt};
{pending, _StartedAt} ->
ok
end;
_ ->
case Data of
#{<<"sdp">> := #{<<"type">> := <<"answer">>, <<"sdp">> := Sdp}} ->
room_coordinator:sdp_answer(State#state.room_pid, PeerId, Sdp);
#{<<"candidate">> := Candidate} ->
room_coordinator:ice_candidate(State#state.room_pid, PeerId, Candidate);
_ ->
ok
end
end;
_ ->
ok
end,
{ok, State};
handle_in(Frame, State) ->
error_logger:info_msg("Signaling handler received fallback frame: ~p, state=~p~n", [Frame, State]),
{ok, State}.
handle_info(send_init_msg, State) ->
InitMsg = jsone:encode(#{
<<"type">> => <<"init">>,
<<"peer_id">> => State#state.peer_id
}),
{push, {text, InitMsg}, State};
handle_info({send_room_info, StartedAt}, State) ->
HlsFormat = application:get_env(rtp, hls_format, fmp4),
RoomInfoMsg = jsone:encode(#{
<<"type">> => <<"room_info">>,
<<"started_at">> => StartedAt,
<<"hls_format">> => HlsFormat
}),
{push, {text, RoomInfoMsg}, State};
handle_info({sdp_offer, Sdp}, State) ->
Payload = jsone:encode(#{
<<"sdp">> => #{
<<"type">> => <<"offer">>,
<<"sdp">> => Sdp
}
}),
{push, {text, Payload}, State};
handle_info({ice_candidate, Candidate}, State) ->
Payload = jsone:encode(#{
<<"candidate">> => Candidate
}),
{push, {text, Payload}, State};
handle_info(_Info, State) ->
{ok, State}.
terminate(_Reason, State) ->
PeerId = State#state.peer_id,
room_coordinator:peer_left(State#state.room_pid, PeerId),
syn:unregister(rooms, PeerId),
ok.