diff --git a/apps/sdlan/src/sdlan_stun.erl b/apps/sdlan/src/sdlan_stun.erl index da9764c..e6c99ab 100644 --- a/apps/sdlan/src/sdlan_stun.erl +++ b/apps/sdlan/src/sdlan_stun.erl @@ -17,6 +17,7 @@ %% API -export([start_link/1]). +-export([send_packets/3]). %% gen_server callbacks -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). @@ -31,11 +32,15 @@ %%% API %%%=================================================================== +-spec send_packets(Pid :: pid(), Peers :: [{Ip :: inet:ip4_address(), Port :: integer()}], Packet :: binary()) -> no_return(). +send_packets(Pid, Peers, Packet) when is_pid(Pid), is_list(Peers), is_binary(Packet) -> + gen_server:cast(Pid, {send_packets, Peers, Packet}). + %% @doc Spawns the server and registers the local name (unique) --spec(start_link(Socket :: inet:socket()) -> +-spec(start_link(Port :: integer()) -> {ok, Pid :: pid()} | ignore | {error, Reason :: term()}). -start_link(Socket) -> - gen_server:start_link(?MODULE, [Socket], []). +start_link(Port) -> + gen_server:start_link(?MODULE, [Port], []). %%%=================================================================== %%% gen_server callbacks @@ -46,7 +51,17 @@ start_link(Socket) -> -spec(init(Args :: term()) -> {ok, State :: #state{}} | {ok, State :: #state{}, timeout() | hibernate} | {stop, Reason :: term()} | ignore). -init([Socket]) -> +init([Port]) -> + Opts = [ + binary, + {reuseaddr, true}, + {reuseport, true}, + {active, true}, + {recbuf, 5 * 1024 * 1024}, + {sndbuf, 5 * 1024 * 1024} + ], + + {ok, Socket} = gen_udp:open(Port, Opts), %% 需要提高进程的调度优先级 erlang:process_flag(priority, high), inet_udp:controlling_process(Socket, self()), @@ -71,7 +86,10 @@ handle_call(_Request, _From, State = #state{}) -> {noreply, NewState :: #state{}} | {noreply, NewState :: #state{}, timeout() | hibernate} | {stop, Reason :: term(), NewState :: #state{}}). - +%% 转发数据 +handle_cast({send_packets, Peers, Packet}, State = #state{socket = Sock}) -> + lists:foreach(fun({Ip, Port}) -> gen_udp:send(Sock, Ip, Port, Packet) end, Peers), + {noreply, State}; %% 当前node下的转发,基于进程间的通讯 handle_cast({stun_relay, Ip, Port, Reply}, State = #state{socket = Sock}) -> ok = gen_udp:send(Sock, Ip, Port, Reply), @@ -89,7 +107,7 @@ handle_info({udp, Sock, PeerIp, PeerPort, Packet}, State = #state{socket = Sock} handle_info({udp_error , Sock, Reason}, State = #state{socket = Sock}) -> {stop, Reason, State}; handle_info(Info, State) -> - logger:error("[sdlan_stun] get a unknown message: ~p, channel will closed", [Info]), + logger:error("[sdlan_stun] get a unknown message?: ~p, channel will closed, state: ~p", [Info, State]), {noreply, State}. %% @private diff --git a/apps/sdlan/src/sdlan_stun_pool.erl b/apps/sdlan/src/sdlan_stun_pool.erl index c40028d..1946563 100644 --- a/apps/sdlan/src/sdlan_stun_pool.erl +++ b/apps/sdlan/src/sdlan_stun_pool.erl @@ -35,7 +35,7 @@ -spec send_packet(Peer :: {Ip :: inet:ip4_address(), Port :: integer()}, Packet :: binary()) -> no_return(). send_packet(Peer, Packet) -> - gen_server:cast(?SERVER, {send_packet, Peer, Packet}). + gen_server:cast(?SERVER, {send_packets, [Peer], Packet}). -spec send_packets(Peers :: [{Ip :: inet:ip4_address(), Port :: integer()}], Packet :: binary()) -> no_return(). send_packets(Peers, Packet) when is_list(Peers), is_binary(Packet) -> @@ -61,19 +61,9 @@ init([]) -> Port = proplists:get_value(port, StunServerProps), AcceptorNums = proplists:get_value(acceptor_nums, StunServerProps), - Opts = [ - binary, - {reuseaddr, true}, - {reuseport, true}, - {active, true}, - {recbuf, 5 * 1024 * 1024}, - {sndbuf, 5 * 1024 * 1024} - ], - Workers = lists:map(fun(_Id) -> - {ok, Socket} = gen_udp:open(Port, Opts), - {ok, Pid} = sdlan_stun:start_link(Socket), - {Socket, Pid} + {ok, Pid} = sdlan_stun:start_link(Port), + Pid end, lists:seq(1, AcceptorNums)), {ok, #state{workers = list_to_tuple(Workers), idx = 1, num = length(Workers)}}. @@ -98,15 +88,9 @@ handle_call(_Request, _From, State = #state{}) -> {stop, Reason :: term(), NewState :: #state{}}). %% 当前node下的转发,基于进程间的通讯 -handle_cast({send_packet, {Ip, Port}, Packet}, State = #state{workers = Workers, idx = Idx, num = Num}) -> - {Sock, _} = element(Idx, Workers), - gen_udp:send(Sock, Ip, Port, Packet), - NewIdx = (Idx rem Num) + 1, - {noreply, State#state{idx = NewIdx}}; - handle_cast({send_packets, Peers, Packet}, State = #state{workers = Workers, idx = Idx, num = Num}) -> - {Sock, _} = element(Idx, Workers), - lists:foreach(fun({Ip, Port}) -> gen_udp:send(Sock, Ip, Port, Packet) end, Peers), + WorkerPid = element(Idx, Workers), + sdlan_stun:send_packets(WorkerPid, Peers, Packet), NewIdx = (Idx rem Num) + 1, {noreply, State#state{idx = NewIdx}}. @@ -117,7 +101,7 @@ handle_cast({send_packets, Peers, Packet}, State = #state{workers = Workers, idx {noreply, NewState :: #state{}, timeout() | hibernate} | {stop, Reason :: term(), NewState :: #state{}}). handle_info(Info, State) -> - logger:error("[sdlan_stun] get a unknown message: ~p, channel will closed", [Info]), + logger:error("[sdlan_stun] get a unknown message:xx ~p, channel will closed", [Info]), {noreply, State}. %% @private diff --git a/apps/sdlan/src/test/stun_client.erl b/apps/sdlan/src/test/stun_client.erl index 89c21fe..bf4b305 100644 --- a/apps/sdlan/src/test/stun_client.erl +++ b/apps/sdlan/src/test/stun_client.erl @@ -81,7 +81,9 @@ start_link() -> {stop, Reason :: term()} | ignore). init([]) -> {ok, TunSocket} = gen_udp:open(0, [binary, {active, true}]), - {ok, #state{tun_socket = TunSocket, network_id = 8, mac = <<11, 12, 13, 14, 15, 16>>, ip = x, mask_len = 24, client_id = <<"22222222222222222222222222222222">>}}. + Ip = sdlan_ipaddr:ipv4_to_int({10, 211, 179, 1}), + + {ok, #state{tun_socket = TunSocket, network_id = 8, mac = <<11, 12, 13, 14, 15, 16>>, ip = Ip, mask_len = 24, client_id = <<"22222222222222222222222222222222">>}}. %% @private %% @doc Handling call messages