解决udp数据包的转发问题
This commit is contained in:
parent
7cd645eb17
commit
f5a07e41f7
@ -25,46 +25,26 @@
|
||||
}).
|
||||
-endif.
|
||||
|
||||
-ifndef('SDL_DEV_ADDR_PB_H').
|
||||
-define('SDL_DEV_ADDR_PB_H', true).
|
||||
-record(sdl_dev_addr,
|
||||
{network_id = 0 :: non_neg_integer() | undefined, % = 1, optional, 32 bits
|
||||
mac = <<>> :: iodata() | undefined, % = 2, optional
|
||||
net_addr = 0 :: non_neg_integer() | undefined, % = 3, optional, 32 bits
|
||||
net_bit_len = 0 :: non_neg_integer() | undefined, % = 4, optional, 32 bits
|
||||
network_domain = <<>> :: unicode:chardata() | undefined % = 5, optional
|
||||
}).
|
||||
-endif.
|
||||
|
||||
-ifndef('SDL_EMPTY_PB_H').
|
||||
-define('SDL_EMPTY_PB_H', true).
|
||||
-record(sdl_empty,
|
||||
{
|
||||
}).
|
||||
-endif.
|
||||
|
||||
-ifndef('SDL_REGISTER_SUPER_PB_H').
|
||||
-define('SDL_REGISTER_SUPER_PB_H', true).
|
||||
-record(sdl_register_super,
|
||||
{version = 0 :: non_neg_integer() | undefined, % = 1, optional, 32 bits
|
||||
installed_channel = <<>> :: unicode:chardata() | undefined, % = 2, optional
|
||||
client_id = <<>> :: unicode:chardata() | undefined, % = 3, optional
|
||||
dev_addr = undefined :: sdlan_pb:sdl_dev_addr() | undefined, % = 4, optional
|
||||
pub_key = <<>> :: unicode:chardata() | undefined, % = 5, optional
|
||||
token = <<>> :: unicode:chardata() | undefined, % = 6, optional
|
||||
network_code = <<>> :: unicode:chardata() | undefined, % = 7, optional
|
||||
hostname = <<>> :: unicode:chardata() | undefined % = 8, optional
|
||||
client_id = <<>> :: unicode:chardata() | undefined, % = 2, optional
|
||||
network_id = 0 :: non_neg_integer() | undefined, % = 3, optional, 32 bits
|
||||
mac = <<>> :: iodata() | undefined, % = 4, optional
|
||||
ip = 0 :: non_neg_integer() | undefined, % = 5, optional, 32 bits
|
||||
mask_len = 0 :: non_neg_integer() | undefined, % = 6, optional, 32 bits
|
||||
hostname = <<>> :: unicode:chardata() | undefined, % = 7, optional
|
||||
pub_key = <<>> :: unicode:chardata() | undefined, % = 8, optional
|
||||
access_token = <<>> :: unicode:chardata() | undefined % = 9, optional
|
||||
}).
|
||||
-endif.
|
||||
|
||||
-ifndef('SDL_REGISTER_SUPER_ACK_PB_H').
|
||||
-define('SDL_REGISTER_SUPER_ACK_PB_H', true).
|
||||
-record(sdl_register_super_ack,
|
||||
{dev_addr = undefined :: sdlan_pb:sdl_dev_addr() | undefined, % = 1, optional
|
||||
aes_key = <<>> :: iodata() | undefined, % = 2, optional
|
||||
upgrade_type = 0 :: non_neg_integer() | undefined, % = 3, optional, 32 bits
|
||||
upgrade_prompt :: unicode:chardata() | undefined, % = 4, optional
|
||||
upgrade_address :: unicode:chardata() | undefined % = 5, optional
|
||||
{aes_key = <<>> :: iodata() | undefined, % = 1, optional
|
||||
session_token = <<>> :: iodata() | undefined % = 2, optional
|
||||
}).
|
||||
-endif.
|
||||
|
||||
@ -79,87 +59,61 @@
|
||||
-ifndef('SDL_QUERY_INFO_PB_H').
|
||||
-define('SDL_QUERY_INFO_PB_H', true).
|
||||
-record(sdl_query_info,
|
||||
{dst_mac = <<>> :: iodata() | undefined % = 1, optional
|
||||
{network_id = 0 :: non_neg_integer() | undefined, % = 1, optional, 32 bits
|
||||
dst_mac = <<>> :: iodata() | undefined, % = 2, optional
|
||||
session_token = <<>> :: iodata() | undefined % = 3, optional
|
||||
}).
|
||||
-endif.
|
||||
|
||||
-ifndef('SDL_PEER_INFO_PB_H').
|
||||
-define('SDL_PEER_INFO_PB_H', true).
|
||||
-record(sdl_peer_info,
|
||||
{dst_mac = <<>> :: iodata() | undefined, % = 1, optional
|
||||
v4_info = undefined :: sdlan_pb:sdl_v4_info() | undefined, % = 2, optional
|
||||
v6_info :: sdlan_pb:sdl_v6_info() | undefined % = 3, optional
|
||||
{network_id = 0 :: non_neg_integer() | undefined, % = 1, optional, 32 bits
|
||||
dst_mac = <<>> :: iodata() | undefined, % = 2, optional
|
||||
v4_info = undefined :: sdlan_pb:sdl_v4_info() | undefined, % = 3, optional
|
||||
v6_info :: sdlan_pb:sdl_v6_info() | undefined % = 4, optional
|
||||
}).
|
||||
-endif.
|
||||
|
||||
-ifndef('SDL_NAT_CHANGED_EVENT_PB_H').
|
||||
-define('SDL_NAT_CHANGED_EVENT_PB_H', true).
|
||||
-record(sdl_nat_changed_event,
|
||||
{mac = <<>> :: iodata() | undefined, % = 1, optional
|
||||
ip = 0 :: non_neg_integer() | undefined % = 2, optional, 32 bits
|
||||
{network_id = 0 :: non_neg_integer() | undefined, % = 1, optional, 32 bits
|
||||
mac = <<>> :: iodata() | undefined, % = 2, optional
|
||||
ip = 0 :: non_neg_integer() | undefined % = 3, optional, 32 bits
|
||||
}).
|
||||
-endif.
|
||||
|
||||
-ifndef('SDL_SEND_REGISTER_EVENT_PB_H').
|
||||
-define('SDL_SEND_REGISTER_EVENT_PB_H', true).
|
||||
-record(sdl_send_register_event,
|
||||
{dst_mac = <<>> :: iodata() | undefined, % = 1, optional
|
||||
nat_ip = 0 :: non_neg_integer() | undefined, % = 2, optional, 32 bits
|
||||
nat_port = 0 :: non_neg_integer() | undefined, % = 3, optional, 32 bits
|
||||
nat_type = 0 :: non_neg_integer() | undefined, % = 4, optional, 32 bits
|
||||
v6_info :: sdlan_pb:sdl_v6_info() | undefined % = 5, optional
|
||||
{network_id = 0 :: non_neg_integer() | undefined, % = 1, optional, 32 bits
|
||||
dst_mac = <<>> :: iodata() | undefined, % = 2, optional
|
||||
nat_ip = 0 :: non_neg_integer() | undefined, % = 3, optional, 32 bits
|
||||
nat_port = 0 :: non_neg_integer() | undefined, % = 4, optional, 32 bits
|
||||
nat_type = 0 :: non_neg_integer() | undefined, % = 5, optional, 32 bits
|
||||
v6_info :: sdlan_pb:sdl_v6_info() | undefined % = 6, optional
|
||||
}).
|
||||
-endif.
|
||||
|
||||
-ifndef('SDL_NETWORK_SHUTDOWN_EVENT_PB_H').
|
||||
-define('SDL_NETWORK_SHUTDOWN_EVENT_PB_H', true).
|
||||
-record(sdl_network_shutdown_event,
|
||||
{message = <<>> :: unicode:chardata() | undefined % = 1, optional
|
||||
}).
|
||||
-endif.
|
||||
|
||||
-ifndef('SDL_CHANGE_NETWORK_COMMAND_PB_H').
|
||||
-define('SDL_CHANGE_NETWORK_COMMAND_PB_H', true).
|
||||
-record(sdl_change_network_command,
|
||||
{dev_addr = undefined :: sdlan_pb:sdl_dev_addr() | undefined, % = 1, optional
|
||||
aes_key = <<>> :: iodata() | undefined % = 2, optional
|
||||
}).
|
||||
-endif.
|
||||
|
||||
-ifndef('SDL_COMMAND_ACK_PB_H').
|
||||
-define('SDL_COMMAND_ACK_PB_H', true).
|
||||
-record(sdl_command_ack,
|
||||
{status = false :: boolean() | 0 | 1 | undefined, % = 1, optional
|
||||
message :: unicode:chardata() | undefined % = 2, optional
|
||||
}).
|
||||
-endif.
|
||||
|
||||
-ifndef('SDL_FLOWS_PB_H').
|
||||
-define('SDL_FLOWS_PB_H', true).
|
||||
-record(sdl_flows,
|
||||
{forward_num = 0 :: non_neg_integer() | undefined, % = 1, optional, 32 bits
|
||||
p2p_num = 0 :: non_neg_integer() | undefined, % = 2, optional, 32 bits
|
||||
inbound_num = 0 :: non_neg_integer() | undefined % = 3, optional, 32 bits
|
||||
{network_id = 0 :: non_neg_integer() | undefined, % = 1, optional, 32 bits
|
||||
message = <<>> :: unicode:chardata() | undefined % = 2, optional
|
||||
}).
|
||||
-endif.
|
||||
|
||||
-ifndef('SDL_STUN_REQUEST_PB_H').
|
||||
-define('SDL_STUN_REQUEST_PB_H', true).
|
||||
-record(sdl_stun_request,
|
||||
{cookie = 0 :: non_neg_integer() | undefined, % = 1, optional, 32 bits
|
||||
client_id = <<>> :: unicode:chardata() | undefined, % = 2, optional
|
||||
network_id = 0 :: non_neg_integer() | undefined, % = 3, optional, 32 bits
|
||||
mac = <<>> :: iodata() | undefined, % = 4, optional
|
||||
ip = 0 :: non_neg_integer() | undefined, % = 5, optional, 32 bits
|
||||
nat_type = 0 :: non_neg_integer() | undefined, % = 6, optional, 32 bits
|
||||
v6_info :: sdlan_pb:sdl_v6_info() | undefined % = 7, optional
|
||||
}).
|
||||
-endif.
|
||||
|
||||
-ifndef('SDL_STUN_REPLY_PB_H').
|
||||
-define('SDL_STUN_REPLY_PB_H', true).
|
||||
-record(sdl_stun_reply,
|
||||
{cookie = 0 :: non_neg_integer() | undefined % = 1, optional, 32 bits
|
||||
{client_id = <<>> :: unicode:chardata() | undefined, % = 1, optional
|
||||
network_id = 0 :: non_neg_integer() | undefined, % = 2, optional, 32 bits
|
||||
mac = <<>> :: iodata() | undefined, % = 3, optional
|
||||
ip = 0 :: non_neg_integer() | undefined, % = 4, optional, 32 bits
|
||||
nat_type = 0 :: non_neg_integer() | undefined, % = 5, optional, 32 bits
|
||||
v6_info :: sdlan_pb:sdl_v6_info() | undefined, % = 6, optional
|
||||
session_token = <<>> :: iodata() | undefined % = 7, optional
|
||||
}).
|
||||
-endif.
|
||||
|
||||
@ -171,7 +125,8 @@
|
||||
dst_mac = <<>> :: iodata() | undefined, % = 3, optional
|
||||
is_p2p = false :: boolean() | 0 | 1 | undefined, % = 4, optional
|
||||
ttl = 0 :: non_neg_integer() | undefined, % = 5, optional, 32 bits
|
||||
data = <<>> :: iodata() | undefined % = 6, optional
|
||||
data = <<>> :: iodata() | undefined, % = 6, optional
|
||||
session_token = <<>> :: iodata() | undefined % = 7, optional
|
||||
}).
|
||||
-endif.
|
||||
|
||||
@ -214,7 +169,8 @@
|
||||
-define('SDL_ARP_REQUEST_PB_H', true).
|
||||
-record(sdl_arp_request,
|
||||
{network_id = 0 :: non_neg_integer() | undefined, % = 1, optional, 32 bits
|
||||
target_ip = 0 :: non_neg_integer() | undefined % = 2, optional, 32 bits
|
||||
target_ip = 0 :: non_neg_integer() | undefined, % = 2, optional, 32 bits
|
||||
session_token = <<>> :: iodata() | undefined % = 3, optional
|
||||
}).
|
||||
-endif.
|
||||
|
||||
|
||||
@ -13,7 +13,7 @@
|
||||
|
||||
%% API
|
||||
-export([get_all_networks/0, get_network/1]).
|
||||
-export([auth_token/3, node_online/3, node_offline/2, flow_report/5, network_forward_report/2, auth_network_code/3]).
|
||||
-export([auth_access_token/1, node_online/3, node_offline/2, flow_report/5, network_forward_report/2]).
|
||||
|
||||
-export([assign_ip_address/3]).
|
||||
|
||||
@ -49,23 +49,9 @@ get_network(Id) when is_integer(Id) ->
|
||||
Error
|
||||
end.
|
||||
|
||||
-spec auth_token(ClientId :: binary(), Token :: binary(), Version :: integer()) -> {ok, Resp :: map()} | {error, Reason :: any()}.
|
||||
auth_token(ClientId, Token, Version) when is_binary(ClientId), is_binary(Token), is_integer(Version) ->
|
||||
case catch do_post("auth_token", #{<<"client_id">> => ClientId, <<"token">> => Token, <<"version">> => Version}) of
|
||||
{ok, Resp} ->
|
||||
case catch jiffy:decode(Resp, [return_maps]) of
|
||||
Result when is_map(Result) ->
|
||||
{ok, Result};
|
||||
{error, Reason} ->
|
||||
{error, Reason}
|
||||
end;
|
||||
Error ->
|
||||
Error
|
||||
end.
|
||||
|
||||
-spec auth_network_code(ClientId :: binary(), NetworkCode :: binary(), Version :: integer()) -> {ok, Resp :: map()} | {error, Reason :: any()}.
|
||||
auth_network_code(ClientId, NetworkCode, Version) when is_binary(ClientId), is_binary(NetworkCode), is_integer(Version) ->
|
||||
case catch do_post("check_network", #{<<"client_id">> => ClientId, <<"code">> => NetworkCode, <<"version">> => Version}) of
|
||||
-spec auth_access_token(Params :: map()) -> {ok, Resp :: map()} | {error, Reason :: any()}.
|
||||
auth_access_token(Params) when is_map(Params) ->
|
||||
case catch do_post("auth_token", Params) of
|
||||
{ok, Resp} ->
|
||||
case catch jiffy:decode(Resp, [return_maps]) of
|
||||
Result when is_map(Result) ->
|
||||
|
||||
@ -24,7 +24,7 @@
|
||||
%% API
|
||||
-export([start_link/2]).
|
||||
-export([get_name/1, get_pid/1, lookup_pid/1, assign_ip_addr/4, peer_info/3, unregister/3, debug_info/1, get_network_id/1, get_used_map/1, arp_query/2]).
|
||||
-export([forward/5, update_hole/6, disable_client/2, get_channel/2, dropout_client/2]).
|
||||
-export([forward/5, update_hole/6, disable_client/2, dropout_client/2]).
|
||||
-export([test_event/1]).
|
||||
|
||||
%% gen_server callbacks
|
||||
@ -39,7 +39,6 @@
|
||||
-record(endpoint, {
|
||||
client_id :: binary(),
|
||||
ip :: integer(),
|
||||
channel_pid :: pid(),
|
||||
monitor_ref :: reference(),
|
||||
hole :: undefined | #hole{},
|
||||
%% 记录ip和ip_v6的映射关系, #{ip_addr :: integer() => {}}
|
||||
@ -92,10 +91,11 @@ lookup_pid(Id) when is_integer(Id) ->
|
||||
get_name(Id) when is_integer(Id) ->
|
||||
list_to_atom("sdlan_network:" ++ integer_to_list(Id)).
|
||||
|
||||
-spec assign_ip_addr(Pid :: pid(), ChannelPid :: pid(), ClientId :: binary(), Mac :: binary()) ->
|
||||
-spec attach(Pid :: pid(), ChannelPid :: pid(), ClientId :: binary(), Mac :: binary()) ->
|
||||
{ok, Domain :: binary(), NetAddr :: integer(), MaskLen :: integer(), AesKey :: binary()} | {error, Reason :: any()}.
|
||||
assign_ip_addr(Pid, ChannelPid, ClientId, Mac) when is_pid(Pid), is_pid(ChannelPid), is_binary(ClientId), is_binary(Mac) ->
|
||||
gen_server:call(Pid, {assign_ip_addr, ChannelPid, ClientId, Mac}).
|
||||
|
||||
attach(Pid, ChannelPid, ClientId, Mac, Ip, HostName) when is_pid(Pid), is_pid(ChannelPid), is_binary(ClientId), is_binary(Mac) ->
|
||||
gen_server:call(Pid, {attach, ChannelPid, ClientId, Mac, Ip, HostName}).
|
||||
|
||||
-spec get_network_id(Pid :: pid()) -> {ok, NetworkId :: integer()}.
|
||||
get_network_id(Pid) when is_pid(Pid) ->
|
||||
@ -127,10 +127,6 @@ update_hole(Pid, ClientId, Mac, Peer, NatType, V6Info) when is_pid(Pid), is_bina
|
||||
disable_client(Pid, ClientId) when is_pid(Pid), is_binary(ClientId) ->
|
||||
gen_server:call(Pid, {disable_client, ClientId}).
|
||||
|
||||
-spec get_channel(Pid :: pid(), ClientId :: binary()) -> error | {ok, ChannelPid :: pid()}.
|
||||
get_channel(Pid, ClientId) when is_pid(Pid), is_binary(ClientId) ->
|
||||
gen_server:call(Pid, {get_channel, ClientId}).
|
||||
|
||||
%% 剔除client_id,channel不关闭; channel会被重新绑定到其他的network里面
|
||||
-spec dropout_client(Pid :: pid(), ClientId :: binary()) -> {ok, ChannelPid :: pid(), HostName :: binary()} | error.
|
||||
dropout_client(Pid, ClientId) when is_pid(Pid), is_binary(ClientId) ->
|
||||
@ -195,12 +191,10 @@ init([Id]) when is_integer(Id) ->
|
||||
{noreply, NewState :: #state{}, timeout() | hibernate} |
|
||||
{stop, Reason :: term(), Reply :: term(), NewState :: #state{}} |
|
||||
{stop, Reason :: term(), NewState :: #state{}}).
|
||||
%% 给客户端分配ip地址
|
||||
handle_call({assign_ip_addr, ChannelPid, ClientId, Mac}, _From,
|
||||
%% 给客户端分配ip地址, TODO 这里要绑定hole
|
||||
handle_call({attach, ClientId, Mac, Ip, HostName}, _From,
|
||||
State = #state{network_id = NetworkId, domain = Domain, endpoints = Endpoints, mask_len = MaskLen, aes_key = AesKey}) ->
|
||||
|
||||
case sdlan_api:assign_ip_address(NetworkId, ClientId, Mac) of
|
||||
{ok, #{<<"ip">> := Ip, <<"host_name">> := HostName}} ->
|
||||
%% 分配ip地址的时候,以mac地址为唯一基准
|
||||
logger:debug("[sdlan_network] alloc_ip, network_id: ~p, client_id: ~p, mac: ~p, net_addr: ~p",
|
||||
[NetworkId, ClientId, sdlan_util:format_mac(Mac), sdlan_ipaddr:int_to_ipv4(Ip)]),
|
||||
@ -209,14 +203,9 @@ handle_call({assign_ip_addr, ChannelPid, ClientId, Mac}, _From,
|
||||
%% 添加域名->ip的映射关系
|
||||
sdlan_hostname_regedit:insert(HostName, Domain, Ip),
|
||||
|
||||
%% 建立到新的channel之间的关系
|
||||
MRef = monitor(process, ChannelPid),
|
||||
NEndpoints = maps:put(Mac, #endpoint{client_id = ClientId, ip = Ip, channel_pid = ChannelPid, monitor_ref = MRef}, Endpoints),
|
||||
NEndpoints = maps:put(Mac, #endpoint{client_id = ClientId, ip = Ip}, Endpoints),
|
||||
|
||||
{reply, {ok, Domain, Ip, MaskLen, AesKey}, State#state{endpoints = NEndpoints}};
|
||||
{error, Reason} ->
|
||||
{reply, {error, Reason}, State}
|
||||
end;
|
||||
|
||||
handle_call(get_used_map, _From, State = #state{endpoints = Endpoints}) ->
|
||||
UsedInfos = maps:map(fun(_, #endpoint{hole = Hole, v6_info = V6Info}) ->
|
||||
@ -247,32 +236,12 @@ handle_call(get_used_map, _From, State = #state{endpoints = Endpoints}) ->
|
||||
%% client设置为禁止状态,不允许重连
|
||||
handle_call({disable_client, ClientId}, _From, State = #state{endpoints = Endpoints}) ->
|
||||
case lists:search(fun({_, #endpoint{client_id = ClientId0}}) -> ClientId =:= ClientId0 end, maps:to_list(Endpoints)) of
|
||||
{value, {Mac, #endpoint{channel_pid = ChannelPid, monitor_ref = MRef}}} ->
|
||||
is_reference(MRef) andalso demonitor(MRef),
|
||||
sdlan_channel:stop(ChannelPid, disable),
|
||||
{value, {Mac, #endpoint{}}} ->
|
||||
{reply, ok, State#state{endpoints = maps:remove(Mac, Endpoints)}};
|
||||
false ->
|
||||
{reply, error, State}
|
||||
end;
|
||||
|
||||
handle_call({get_channel, ClientId}, _From, State = #state{endpoints = Endpoints}) ->
|
||||
case lists:search(fun({_, #endpoint{client_id = ClientId0}}) -> ClientId =:= ClientId0 end, maps:to_list(Endpoints)) of
|
||||
{value, {_Ip, #endpoint{channel_pid = ChannelPid}}} ->
|
||||
{reply, {ok, ChannelPid}, State};
|
||||
false ->
|
||||
{reply, error, State}
|
||||
end;
|
||||
|
||||
%% 区别在于是否关闭掉channel, 这里是在网络迁移中的功能; drop的时候需要从当前网络中移除
|
||||
handle_call({dropout_client, ClientId}, _From, State = #state{endpoints = Endpoints}) ->
|
||||
case lists:search(fun({_, #endpoint{client_id = ClientId0}}) -> ClientId =:= ClientId0 end, maps:to_list(Endpoints)) of
|
||||
{value, {Mac, #endpoint{channel_pid = ChannelPid, monitor_ref = MRef}}} ->
|
||||
is_reference(MRef) andalso demonitor(MRef),
|
||||
{reply, {ok, ChannelPid}, State#state{endpoints = maps:remove(Mac, Endpoints)}};
|
||||
false ->
|
||||
{reply, error, State}
|
||||
end;
|
||||
|
||||
handle_call(get_network_id, _From, State = #state{network_id = NetworkId}) ->
|
||||
{reply, {ok, NetworkId}, State};
|
||||
|
||||
@ -393,9 +362,8 @@ handle_cast({unregister, _ClientId, Mac}, State = #state{network_id = NetworkId,
|
||||
case maps:take(Mac, Endpoints) of
|
||||
error ->
|
||||
{noreply, State};
|
||||
{#endpoint{channel_pid = ChannelPid, monitor_ref = MRef}, NEndpoints} ->
|
||||
{#endpoint{monitor_ref = MRef}, NEndpoints} ->
|
||||
is_reference(MRef) andalso demonitor(MRef),
|
||||
sdlan_channel:stop(ChannelPid, normal),
|
||||
{noreply, State#state{endpoints = NEndpoints}}
|
||||
end;
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -32,63 +32,58 @@ start_link(Sock, Ip, Port, Packet) ->
|
||||
{ok, erlang:spawn_link(?MODULE, do_work, [Sock, Ip, Port, Packet])}.
|
||||
|
||||
do_work(Sock, Ip, Port, <<PacketId:32, Body/binary>>) ->
|
||||
#sdl_register_super{version = Version, client_id = ClientId, dev_addr = #sdl_dev_addr{mac = Mac}, network_code = NetworkCode, token = Token, pub_key = PubKey} = sdlan_pb:decode_msg(Body, sdl_register_super),
|
||||
#sdl_register_super{
|
||||
version = Version,
|
||||
client_id = ClientId,
|
||||
network_id = NetworkId,
|
||||
mac = Mac,
|
||||
ip = Ip,
|
||||
mask_len = MaskLen,
|
||||
hostname = HostName,
|
||||
pub_key = PubKey,
|
||||
access_token = AccessToken
|
||||
} = sdlan_pb:decode_msg(Body, sdl_register_super),
|
||||
|
||||
%% 参数检查
|
||||
logger:debug("[sdlan_channel] client_id: ~p, public_key: ~p, token: ~p, network_code: ~p", [ClientId, PubKey, Token, NetworkCode]),
|
||||
logger:debug("[sdlan_channel] client_id: ~p, ip: ~p, mac: ~p, host_name: ~p, access_token: ~p, network_id: ~p", [ClientId, Ip, Mac, HostName, AccessToken, NetworkId]),
|
||||
true = (Mac =/= <<>> andalso PubKey =/= <<>> andalso ClientId =/= <<>>),
|
||||
%% Mac地址不能是广播地址
|
||||
true = not (sdlan_util:is_multicast_mac(Mac) orelse sdlan_util:is_broadcast_mac(Mac)),
|
||||
|
||||
AuthResult = if
|
||||
Token /= <<>> ->
|
||||
logger:debug("[sdlan_channel] auth token: ~p", [Token]),
|
||||
sdlan_api:auth_token(ClientId, Token, Version);
|
||||
NetworkCode /= <<>> ->
|
||||
logger:debug("[sdlan_channel] auth network code: ~p", [NetworkCode]),
|
||||
sdlan_api:auth_network_code(ClientId, NetworkCode, Version)
|
||||
end,
|
||||
Params = #{
|
||||
<<"network_id">> => NetworkId,
|
||||
<<"client_id">> => ClientId,
|
||||
<<"mac">> => Mac,
|
||||
<<"ip">> => Ip,
|
||||
<<"mask_len">> => MaskLen,
|
||||
<<"hostname">> => HostName,
|
||||
<<"access_token">> => AccessToken
|
||||
},
|
||||
|
||||
case AuthResult of
|
||||
{ok, #{<<"result">> := #{<<"network_id">> := NetworkId, <<"upgrade_type">> := UpgradeType, <<"upgrade_prompt">> := UpgradePrompt, <<"upgrade_address">> := UpgradeAddress}}} when is_integer(NetworkId) ->
|
||||
logger:debug("[sdlan_channel] client_id: ~p, mac: ~p, token: ~p, version: ~p, registerd, alloc network_id: ~p", [ClientId, sdlan_util:format_mac(Mac), Token, Version, NetworkId]),
|
||||
case sdlan_api:auth_access_token(Params) of
|
||||
{ok, #{<<"result">> := <<"ok">>}} ->
|
||||
%% 建立到network的对应关系
|
||||
case sdlan_network:get_pid(NetworkId) of
|
||||
NetworkPid when is_pid(NetworkPid) ->
|
||||
try sdlan_network:assign_ip_addr(NetworkPid, self(), ClientId, Mac) of
|
||||
{ok, Domain, NetAddr, NetBitLen, AesKey} ->
|
||||
try sdlan_network:attach(NetworkPid, self(), ClientId, Mac, Ip, HostName) of
|
||||
{ok, AesKey, SessionToken} ->
|
||||
RsaPubKey = sdlan_cipher:rsa_pem_decode(PubKey),
|
||||
EncodedAesKey = rsa_encode(AesKey, RsaPubKey),
|
||||
|
||||
RegisterSuperAck = sdlan_pb:encode_msg(#sdl_register_super_ack {
|
||||
dev_addr = #sdl_dev_addr{
|
||||
network_id = NetworkId,
|
||||
net_addr = NetAddr,
|
||||
mac = Mac,
|
||||
net_bit_len = NetBitLen,
|
||||
network_domain = Domain
|
||||
},
|
||||
aes_key = EncodedAesKey,
|
||||
upgrade_type = UpgradeType,
|
||||
upgrade_prompt = UpgradePrompt,
|
||||
upgrade_address = UpgradeAddress
|
||||
session_token = SessionToken
|
||||
}),
|
||||
|
||||
%% 发送确认信息
|
||||
Reply = <<?PACKET_REGISTER_SUPER_ACK, PacketId:32, RegisterSuperAck/binary>>,
|
||||
gen_udp:send(Sock, Ip, Port, Reply),
|
||||
|
||||
logger:debug("[sdlan_channel] client_id: ~p, mac: ~p, alloc ip: ~p, register will send ack, aes_key: ~p, enc_aes_key: ~p",
|
||||
[ClientId, sdlan_util:format_mac(Mac), sdlan_ipaddr:int_to_ipv4(NetAddr), AesKey, EncodedAesKey]),
|
||||
|
||||
%% 设置节点的在线状态
|
||||
Result = sdlan_api:node_online(ClientId, NetworkId, sdlan_ipaddr:int_to_ipv4(NetAddr)),
|
||||
logger:debug("[sdlan_channel] client_id: ~p, set none online, result is: ~p", [ClientId, Result]),
|
||||
|
||||
%% TODO 这里要处理session_token的逻辑
|
||||
ok;
|
||||
Result = sdlan_api:node_online(ClientId, NetworkId, sdlan_ipaddr:int_to_ipv4(Ip)),
|
||||
logger:debug("[sdlan_channel] client_id: ~p, set none online result is: ~p", [ClientId, Result]);
|
||||
{error, no_ip} ->
|
||||
logger:warning("[sdlan_channel] client_id: ~p, token: ~p, register get error: no_ip", [ClientId, Token]),
|
||||
logger:warning("[sdlan_channel] client_id: ~p, register get error: no_ip", [ClientId, Token]),
|
||||
gen_udp:send(Sock, Ip, Port, register_nak_reply(PacketId, ?NAK_NO_IP, <<"No Ip address">>));
|
||||
{error, host_name_used} ->
|
||||
logger:warning("[sdlan_channel] client_id: ~p, token: ~p, register get error: host_name_used", [ClientId, Token]),
|
||||
@ -103,14 +98,11 @@ do_work(Sock, Ip, Port, <<PacketId:32, Body/binary>>) ->
|
||||
logger:warning("[sdlan_channel] client_id: ~p, token: ~p, register get error: network not found", [ClientId, Token]),
|
||||
gen_udp:send(Sock, Ip, Port, register_nak_reply(PacketId, ?NAK_INTERNAL_FAULT, <<"Internal Error">>))
|
||||
end;
|
||||
{ok, #{<<"error">> := #{<<"code">> := 1, <<"message">> := Message}}} ->
|
||||
logger:warning("[sdlan_channel] client_id: ~p, token: ~p, register get error: ~ts, error_code: 1", [ClientId, Token, Message]),
|
||||
gen_udp:send(Sock, Ip, Port, register_nak_reply(PacketId, ?NAK_INVALID_TOKEN, Message));
|
||||
{ok, #{<<"error">> := #{<<"code">> := 2, <<"message">> := Message}}} ->
|
||||
logger:warning("[sdlan_channel] client_id: ~p, token: ~p, register get error: ~p, error_code: 2", [ClientId, Token, Message]),
|
||||
gen_udp:send(Sock, Ip, Port, register_nak_reply(PacketId, ?NAK_NODE_DISABLE, Message));
|
||||
{ok, #{<<"error">> := #{<<"code">> := Code, <<"message">> := Message}}} ->
|
||||
logger:warning("[sdlan_channel] network_id: ~p, client_id: ~p, register get error: ~ts, error_code: ~p", [NetworkId, ClientId, Message, Code]),
|
||||
gen_udp:send(Sock, Ip, Port, register_nak_reply(PacketId, Code, Message));
|
||||
{error, Reason} ->
|
||||
logger:warning("[sdlan_channel] client_id: ~p, token: ~p, register get error: ~p", [ClientId, Token, Reason]),
|
||||
logger:warning("[sdlan_channel] network_id: ~p, client_id: ~p, register get error: ~p", [NetworkId, ClientId, Reason]),
|
||||
gen_udp:send(Sock, Ip, Port, register_nak_reply(PacketId, ?NAK_NETWORK_FAULT, <<"Network Error">>))
|
||||
end,
|
||||
exit(normal).
|
||||
|
||||
@ -37,10 +37,10 @@ get_name(Id) when is_integer(Id) ->
|
||||
list_to_atom("sdlan_stun:" ++ integer_to_list(Id)).
|
||||
|
||||
%% @doc Spawns the server and registers the local name (unique)
|
||||
-spec(start_link(Name :: atom(), Port :: integer()) ->
|
||||
-spec(start_link(Name :: atom(), Socket :: inet:socket()) ->
|
||||
{ok, Pid :: pid()} | ignore | {error, Reason :: term()}).
|
||||
start_link(Name, Port) when is_atom(Name), is_integer(Port) ->
|
||||
gen_server:start_link({local, Name}, ?MODULE, [Port], []).
|
||||
start_link(Name, Socket) when is_atom(Name) ->
|
||||
gen_server:start_link({local, Name}, ?MODULE, [Socket], []).
|
||||
|
||||
%%%===================================================================
|
||||
%%% gen_server callbacks
|
||||
@ -51,22 +51,10 @@ start_link(Name, Port) when is_atom(Name), is_integer(Port) ->
|
||||
-spec(init(Args :: term()) ->
|
||||
{ok, State :: #state{}} | {ok, State :: #state{}, timeout() | hibernate} |
|
||||
{stop, Reason :: term()} | ignore).
|
||||
init([Port]) ->
|
||||
init([Socket]) ->
|
||||
%% 需要提高进程的调度优先级
|
||||
erlang:process_flag(priority, high),
|
||||
Opts = [
|
||||
binary,
|
||||
{reuseaddr, true},
|
||||
{reuseport, true},
|
||||
{active, true},
|
||||
{recbuf, 5 * 1024 * 1024},
|
||||
{sndbuf, 5 * 1024 * 1024}
|
||||
],
|
||||
|
||||
{ok, Socket} = gen_udp:open(Port, Opts),
|
||||
inet_udp:controlling_process(Socket, self()),
|
||||
logger:debug("[sdlan_stun] start at port: ~p", [Port]),
|
||||
|
||||
{ok, #state{socket = Socket}}.
|
||||
|
||||
%% @private
|
||||
|
||||
134
apps/sdlan/src/sdlan_stun_pool.erl
Normal file
134
apps/sdlan/src/sdlan_stun_pool.erl
Normal file
@ -0,0 +1,134 @@
|
||||
%%%-------------------------------------------------------------------
|
||||
%%% @author anlicheng
|
||||
%%% @copyright (C) 2024, <COMPANY>
|
||||
%%% @doc
|
||||
%%%
|
||||
%%% @end
|
||||
%%% Created : 09. 4月 2024 17:37
|
||||
%%%-------------------------------------------------------------------
|
||||
-module(sdlan_stun_pool).
|
||||
-feature(maybe_expr, enable).
|
||||
|
||||
-author("anlicheng").
|
||||
-include("sdlan.hrl").
|
||||
-include("sdlan_pb.hrl").
|
||||
|
||||
-behaviour(gen_server).
|
||||
|
||||
%% API
|
||||
-export([start_link/0, send_packets/1]).
|
||||
|
||||
%% gen_server callbacks
|
||||
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).
|
||||
|
||||
-define(SERVER, ?MODULE).
|
||||
|
||||
-record(state, {
|
||||
workers :: tuple(),
|
||||
idx = 1,
|
||||
num = 0
|
||||
}).
|
||||
|
||||
%%%===================================================================
|
||||
%%% API
|
||||
%%%===================================================================
|
||||
|
||||
send_packets(Packets) when is_list(Packets) ->
|
||||
gen_server:cast(?SERVER, {send_packets, Packets}).
|
||||
|
||||
%% @doc Spawns the server and registers the local name (unique)
|
||||
-spec(start_link() ->
|
||||
{ok, Pid :: pid()} | ignore | {error, Reason :: term()}).
|
||||
start_link() ->
|
||||
gen_server:start_link({local, ?SERVER}, ?MODULE, [], []).
|
||||
|
||||
%%%===================================================================
|
||||
%%% gen_server callbacks
|
||||
%%%===================================================================
|
||||
|
||||
%% @private
|
||||
%% @doc Initializes the server
|
||||
-spec(init(Args :: term()) ->
|
||||
{ok, State :: #state{}} | {ok, State :: #state{}, timeout() | hibernate} |
|
||||
{stop, Reason :: term()} | ignore).
|
||||
init([]) ->
|
||||
{ok, StunServerProps} = application:get_env(sdlan, stun_servers),
|
||||
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) ->
|
||||
Name = sdlan_stun:get_name(Id),
|
||||
{ok, Socket} = gen_udp:open(Port, Opts),
|
||||
{ok, Pid} = sdlan_stun:start_link(Name, Socket),
|
||||
{Socket, Pid}
|
||||
end, lists:seq(1, AcceptorNums)),
|
||||
{ok, #state{workers = list_to_tuple(Workers), idx = 1, num = length(Workers)}}.
|
||||
|
||||
%% @private
|
||||
%% @doc Handling call messages
|
||||
-spec(handle_call(Request :: term(), From :: {pid(), Tag :: term()},
|
||||
State :: #state{}) ->
|
||||
{reply, Reply :: term(), NewState :: #state{}} |
|
||||
{reply, Reply :: term(), NewState :: #state{}, timeout() | hibernate} |
|
||||
{noreply, NewState :: #state{}} |
|
||||
{noreply, NewState :: #state{}, timeout() | hibernate} |
|
||||
{stop, Reason :: term(), Reply :: term(), NewState :: #state{}} |
|
||||
{stop, Reason :: term(), NewState :: #state{}}).
|
||||
handle_call(_Request, _From, State = #state{}) ->
|
||||
{reply, ok, State}.
|
||||
|
||||
%% @private
|
||||
%% @doc Handling cast messages
|
||||
-spec(handle_cast(Request :: term(), State :: #state{}) ->
|
||||
{noreply, NewState :: #state{}} |
|
||||
{noreply, NewState :: #state{}, timeout() | hibernate} |
|
||||
{stop, Reason :: term(), NewState :: #state{}}).
|
||||
|
||||
%% 当前node下的转发,基于进程间的通讯
|
||||
handle_cast({send_packets, Packets}, State = #state{workers = Workers, idx = Idx, num = Num}) ->
|
||||
{Sock, _} = element(Idx, Workers),
|
||||
lists:foreach(fun({Ip, Port, Data}) -> gen_udp:send(Sock, Ip, Port, Data) end, Packets),
|
||||
NewIdx = (Idx rem Num) + 1,
|
||||
|
||||
{noreply, State#state{idx = NewIdx}}.
|
||||
|
||||
%% @private
|
||||
%% @doc Handling all non call/cast messages
|
||||
-spec(handle_info(Info :: timeout() | term(), State :: #state{}) ->
|
||||
{noreply, NewState :: #state{}} |
|
||||
{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]),
|
||||
{noreply, State}.
|
||||
|
||||
%% @private
|
||||
%% @doc This function is called by a gen_server when it is about to
|
||||
%% terminate. It should be the opposite of Module:init/1 and do any
|
||||
%% necessary cleaning up. When it returns, the gen_server terminates
|
||||
%% with Reason. The return value is ignored.
|
||||
-spec(terminate(Reason :: (normal | shutdown | {shutdown, term()} | term()),
|
||||
State :: #state{}) -> term()).
|
||||
terminate(_Reason, _State = #state{}) ->
|
||||
ok.
|
||||
|
||||
%% @private
|
||||
%% @doc Convert process state when code is changed
|
||||
-spec(code_change(OldVsn :: term() | {down, term()}, State :: #state{},
|
||||
Extra :: term()) ->
|
||||
{ok, NewState :: #state{}} | {error, Reason :: term()}).
|
||||
code_change(_OldVsn, State = #state{}, _Extra) ->
|
||||
{ok, State}.
|
||||
|
||||
%%%===================================================================
|
||||
%%% Internal functions
|
||||
%%%===================================================================
|
||||
@ -26,12 +26,16 @@ start_link() ->
|
||||
%% modules => modules()} % optional
|
||||
init([]) ->
|
||||
SupFlags = #{strategy => one_for_one, intensity => 1000, period => 3600},
|
||||
|
||||
{ok, StunServerProps} = application:get_env(sdlan, stun_servers),
|
||||
Port = proplists:get_value(port, StunServerProps),
|
||||
AcceptorNums = proplists:get_value(acceptor_nums, StunServerProps),
|
||||
|
||||
Specs = [
|
||||
#{
|
||||
id => sdlan_stun_pool,
|
||||
start => {sdlan_stun_pool, start_link, []},
|
||||
restart => permanent,
|
||||
shutdown => 2000,
|
||||
type => worker,
|
||||
modules => ['sdlan_stun_pool']
|
||||
},
|
||||
|
||||
#{
|
||||
id => sdlan_stun_port_assist,
|
||||
start => {sdlan_stun_port_assist, start_link, []},
|
||||
@ -50,16 +54,4 @@ init([]) ->
|
||||
}
|
||||
],
|
||||
|
||||
StunSpecs = lists:map(fun(Id) ->
|
||||
Name = sdlan_stun:get_name(Id),
|
||||
#{
|
||||
id => Name,
|
||||
start => {sdlan_stun, start_link, [Name, Port]},
|
||||
restart => permanent,
|
||||
shutdown => 2000,
|
||||
type => worker,
|
||||
modules => ['sdlan_stun']
|
||||
}
|
||||
end, lists:seq(1, AcceptorNums)),
|
||||
|
||||
{ok, {SupFlags, Specs ++ StunSpecs}}.
|
||||
{ok, {SupFlags, Specs}}.
|
||||
Loading…
x
Reference in New Issue
Block a user