diff --git a/API.md b/API.md index 02f65d1..601c448 100644 --- a/API.md +++ b/API.md @@ -45,6 +45,7 @@ return: "id": 1, "name": "网络1", "ipaddr": "192.168.0.1/24", + "domain": "punchnet.cn", "owner_id": 1234, "disabled_clients": ["client_id_xyz", "client_id_xyz1"] } @@ -78,6 +79,31 @@ return: code = 2, Client Connection Disable ``` +### 3.网络校验 +```text +url: /api/check_network +method: post +params: + client_id: string + code: string, + version: int // 当前客户端版本 +return: + + {"result": + { + "network_id": 8, + "upgrade_type": 0, // 升级类型,0: 不升级,1: 普通升级,2: 强制升级 + "upgrade_prompt": "升级提升语" + "upgrade_address": "升级提升语" + } + } + + {"error": {"code": 1, "message": "错误描述"}} + code = 1, Token does not exists + code = 2, Client Connection Disable +``` + + ### 4.设置节点的状态 ```text url: /api/set_node_status diff --git a/apps/sdlan/include/dns_proxy.hrl b/apps/sdlan/include/dns_proxy.hrl new file mode 100644 index 0000000..7000b7f --- /dev/null +++ b/apps/sdlan/include/dns_proxy.hrl @@ -0,0 +1,24 @@ +%%%------------------------------------------------------------------- +%%% @author anlicheng +%%% @copyright (C) 2025, +%%% @doc +%%% +%%% @end +%%% Created : 04. 12月 2025 11:41 +%%%------------------------------------------------------------------- +-author("anlicheng"). + +-define(PENDING_TAB, ets_dns_pending_queries). +-define(PENDING_INDEX_TAB, ets_dns_expire_index). + +-record(dns_cache, { + %% {Qname, QType, QClass} + key, + answers = [], + authority = [], + additional = [], + rc :: integer(), + flags = #{}, + % unix time + expire_at :: integer() +}). \ No newline at end of file diff --git a/apps/sdlan/include/sdlan_pb.hrl b/apps/sdlan/include/sdlan_pb.hrl index d7c149a..2a1f09f 100644 --- a/apps/sdlan/include/sdlan_pb.hrl +++ b/apps/sdlan/include/sdlan_pb.hrl @@ -31,7 +31,8 @@ {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 + net_bit_len = 0 :: non_neg_integer() | undefined, % = 4, optional, 32 bits + network_domain = <<>> :: unicode:chardata() | undefined % = 5, optional }). -endif. @@ -50,7 +51,9 @@ 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 + token = <<>> :: unicode:chardata() | undefined, % = 6, optional + network_code = <<>> :: unicode:chardata() | undefined, % = 7, optional + hostname = <<>> :: unicode:chardata() | undefined % = 8, optional }). -endif. diff --git a/apps/sdlan/include/sdlan_tables.hrl b/apps/sdlan/include/sdlan_tables.hrl index 355670f..7bafce0 100644 --- a/apps/sdlan/include/sdlan_tables.hrl +++ b/apps/sdlan/include/sdlan_tables.hrl @@ -13,6 +13,7 @@ client_id :: binary(), mac :: binary(), ip :: integer(), + host_name :: binary(), %% 当前状态 status = normal :: normal | disabled }). \ No newline at end of file diff --git a/apps/sdlan/src/dns_proxy/dns_cache.erl b/apps/sdlan/src/dns_proxy/dns_cache.erl new file mode 100644 index 0000000..da597c0 --- /dev/null +++ b/apps/sdlan/src/dns_proxy/dns_cache.erl @@ -0,0 +1,59 @@ +-module(dns_cache). +-include_lib("dns_proxy.hrl"). +-include_lib("dns_erlang/include/dns.hrl"). +-include_lib("dns_erlang/include/dns_records.hrl"). +-include_lib("dns_erlang/include/dns_terms.hrl"). + +-export([init/0, lookup/1, insert/2]). + +-define(TABLE, dns_cache). + +init() -> + ets:new(?TABLE, [named_table, set, public, {keypos, 2}, {read_concurrency, true}]). + +lookup(#dns_query{name = Qname, type = QType, class = QClass}) -> + Key = {Qname, QType, QClass}, + case ets:lookup(?TABLE, Key) of + [Cache = #dns_cache{expire_at = ExpireAt}] -> + Now = os:system_time(second), + case ExpireAt > Now of + true -> + {hit, Cache}; + false -> + true = ets:delete(?TABLE, Key), + miss + end; + [] -> + miss + end. + +insert(#dns_query{name = Qname, type = QType, class = QClass}, + #dns_message{answers = Answers, authority = Authority, additional = Additional, rc = RCode, aa = AA}) -> + TTLs = lists:foldl(fun(Term, Acc) -> + case Term of + #dns_rr{ttl = TTL} -> + [TTL|Acc]; + _ -> + Acc + end + end, [], Answers ++ Authority ++ Additional), + case length(TTLs) > 0 of + true -> + TTL = lists:min(TTLs), + ExpireAt = os:system_time(second) + TTL, + lager:debug("min ttl is: ~p, expire_at: ~p", [TTL, ExpireAt]), + Key = {Qname, QType, QClass}, + Cache = #dns_cache{ + key = Key, + answers = Answers, + authority = Authority, + additional = Additional, + rc = RCode, + flags = #{aa => AA}, + % unix time + expire_at = ExpireAt + }, + true = ets:insert(?TABLE, Cache); + false -> + ok + end. \ No newline at end of file diff --git a/apps/sdlan/src/dns_proxy/dns_handler.erl b/apps/sdlan/src/dns_proxy/dns_handler.erl new file mode 100644 index 0000000..d889ee2 --- /dev/null +++ b/apps/sdlan/src/dns_proxy/dns_handler.erl @@ -0,0 +1,263 @@ +%%%------------------------------------------------------------------- +%%% @author anlicheng +%%% @copyright (C) 2025, +%%% @doc +%%% +%%% @end +%%% Created : 03. 12月 2025 23:00 +%%%------------------------------------------------------------------- +-module(dns_handler). +-author("anlicheng"). + +-behaviour(gen_server). + +-include_lib("dns_erlang/include/dns.hrl"). +-include_lib("pkt/include/pkt.hrl"). +-include("dns_proxy.hrl"). + +%% API +-export([start_link/0]). + +%% gen_server callbacks +-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). +-export([handle_ip_packet/5]). + +-define(SERVER, ?MODULE). +-define(RESOLVER_POOL, dns_resolver_pool). + +%% 协议部分 +-define(TCP_PROTOCOL, 6). +-define(UDP_PROTOCOL, 17). + +-record(state, {}). + +%%%=================================================================== +%%% API +%%%=================================================================== + +start_link() -> + gen_server:start_link(?MODULE, [], []). + +handle_ip_packet(Pid, Sock, SrcIp, SrcPort, Packet) when is_pid(Pid) -> + gen_server:cast(Pid, {handle_ip_packet, Sock, SrcIp, SrcPort, Packet}). + +%%%=================================================================== +%%% 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, #state{}}. + +%% @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{}}). +handle_cast({handle_ip_packet, Sock, SrcIp, SrcPort, IpPacket}, State) -> + {#ipv4{saddr = ReqSAddr, daddr = ReqDAddr, p = Protocol}, ReqIpPayload} = pkt:ipv4(IpPacket), + case Protocol =:= ?UDP_PROTOCOL of + true -> + {#udp{sport = ReqSPort, dport = ReqDPort}, UdpPayload} = pkt:udp(ReqIpPayload), + case resolver(UdpPayload) of + {ok, DnsResp} -> + RespIpPacket = build_ip_packet(ReqDAddr, ReqSAddr, ReqDPort, ReqSPort, DnsResp), + gen_udp:send(Sock, SrcIp, SrcPort, RespIpPacket); + {error, Reason} -> + lager:notice("[dns_handler] resolver get error: ~p", [Reason]) + end; + false -> + lager:notice("[dns_handler] resolver invalid protocol: ~p", [Protocol]) + end, + {stop, normal, State}. + +%% @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) -> + {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 +%%%=================================================================== + +-spec resolver(Packet :: binary()) -> {ok, Resp :: binary()} | {error, Reason :: any()}. +resolver(Packet) when is_binary(Packet) -> + resolver0(Packet, dns:decode_message(Packet)). +resolver0(Packet, QueryMsg = #dns_message{qc = 1, questions = [Question = #dns_query{name = QName, type = QType, class = QClass}|_]}) -> + %% 查找是否是内置的域名 + case sdlan_hostname_regedit:lookup(QName) of + {ok, Ip} -> + Answer = #dns_rr { + name = QName, + type = QType, + class = QClass, + ttl = 300, + data = #dns_rrdata_a { + ip = Ip + } + }, + RespMsg = QueryMsg#dns_message{ + qr = true, + ra = true, + anc = 1, + auc = 0, + adc = 0, + answers = [Answer], + authority = [], + additional = [] + }, + lager:debug("[dns_handler] punchnet inbuilt qnanme: ~p, ip: ~p", [QName, Ip]), + {ok, dns:encode_message(RespMsg)}; + error -> + %% 是否命中内部的域名后缀 + EmptyDnsResp = dns:encode_message(build_nxdomain_response(QueryMsg)), + case sdlan_domain_regedit:maybe_domain(QName) of + true -> + lager:debug("[dns_handler] punchnet inbuilt qnanme: ~p, nxdomain", [QName]), + {ok, EmptyDnsResp}; + false -> + case dns_cache:lookup(Question) of + {hit, Cache} -> + lager:debug("[dns_handler] qname: ~p, hit cache answers: ~p", [QName, Cache#dns_cache.answers]), + RespMsg = build_response(QueryMsg, Cache), + {ok, dns:encode_message(RespMsg)}; + miss -> + Ref = make_ref(), + forward_to_upstream(Ref, Packet, QueryMsg), + lager:debug("[dns_handler] cache is miss, forward_to_upstream"), + receive + {dns_resolver_reply, Ref, Resp} -> + case dns:decode_message(Resp) of + RespMsg = #dns_message{answers = Answers} -> + lager:debug("[dns_handler] get a response answers: ~p", [Answers]), + dns_cache:insert(Question, RespMsg), + {ok, Resp}; + Error -> + lager:debug("[dns_handler] parse reply get error: ~p", [Error]), + {ok, EmptyDnsResp} + end + after 5000 -> + lager:debug("[dns_handler] forward_to_upstream timeout"), + {ok, EmptyDnsResp} + end + end + end + end; +resolver0(_, Error) -> + lager:warning("[dns_handler] decode dns_query get error: ~p", [Error]), + {error, Error}. + +-spec forward_to_upstream(Ref :: reference(), Request :: binary(), QueryMsg :: #dns_message{}) -> no_return(). +forward_to_upstream(Ref, Request, QueryMsg) -> + ReceiverPid = self(), + poolboy:transaction(?RESOLVER_POOL, fun(Pid) -> dns_resolver:forward(Pid, ReceiverPid, Ref, Request, QueryMsg) end). + +-spec build_response(QueryMsg :: #dns_message{}, Dns_cache :: #dns_cache{}) -> RespMsg :: #dns_message{}. +build_response(QueryMsg, #dns_cache{expire_at = ExpireAt, answers = Answers, authority = Authority, additional = Additional, rc = RCode, flags = #{aa := AA}}) -> + Now = os:system_time(second), + RemainingTTL = ExpireAt - Now, + + Answers2 = [adjust_ttl(RR, RemainingTTL) || RR <- Answers], + Authority2 = [adjust_ttl(RR, RemainingTTL) || RR <- Authority], + Additional2 = [adjust_ttl(RR, RemainingTTL) || RR <- Additional], + + QueryMsg#dns_message{ + qr = true, + ra = true, + aa = AA, + rc = RCode, + anc = length(Answers2), + auc = length(Authority2), + adc = length(Additional2), + answers = Answers2, + authority = Authority2, + additional = Additional2 + }. + +-spec adjust_ttl(RR :: any(), RemainingTTL :: integer()) -> any(). +adjust_ttl(RR = #dns_rr{}, RemainingTTL) -> + RR#dns_rr{ttl = max(0, RemainingTTL)}; +adjust_ttl(RR, _RemainingTTL) -> + RR. + +-spec build_nxdomain_response(QueryMsg :: #dns_message{}) -> EmptyResp :: #dns_message{}. +build_nxdomain_response(QueryMsg) -> + QueryMsg#dns_message{ + qr = true, + aa = true, + ra = true, + rc = ?DNS_RCODE_NXDOMAIN, + anc = 0, + auc = 0, + adc = 0, + answers = [], + authority = [], + additional = [] + }. + +-spec build_ip_packet(SAddr :: inet:ip4_address(), DAddr :: inet:ip4_address(), SPort :: integer(), DPort :: integer(), Payload :: binary()) -> IpPacket :: binary(). +build_ip_packet(SAddr, DAddr, SPort, DPort, UdpPayload) when is_integer(SPort), is_integer(DPort), is_binary(UdpPayload) -> + ULen = 8 + byte_size(UdpPayload), + RespUdpHeader = pkt:udp(#udp{ + sport = SPort, + dport = DPort, + ulen = ULen, + sum = dns_utils:udp_checksum(SAddr, DAddr, SPort, DPort, UdpPayload) + }), + IpPayload = <>, + + IpPacket0 = #ipv4{ + len = 20 + ULen, + ttl = 64, + off = 0, + mf = 0, + sum = 0, + p = ?UDP_PROTOCOL, + saddr = SAddr, + daddr = DAddr, + opt = <<>> + }, + IpCheckSum = dns_utils:ip_checksum(IpPacket0), + IpHeader = pkt:ipv4(IpPacket0#ipv4{sum = IpCheckSum}), + + <>. \ No newline at end of file diff --git a/apps/sdlan/src/dns_proxy/dns_handler_sup.erl b/apps/sdlan/src/dns_proxy/dns_handler_sup.erl new file mode 100644 index 0000000..009395d --- /dev/null +++ b/apps/sdlan/src/dns_proxy/dns_handler_sup.erl @@ -0,0 +1,66 @@ +%%%------------------------------------------------------------------- +%%% @author anlicheng +%%% @copyright (C) 2025, +%%% @doc +%%% +%%% @end +%%% Created : 03. 12月 2025 17:29 +%%%------------------------------------------------------------------- +-module(dns_handler_sup). +-author("anlicheng"). + +-behaviour(supervisor). + +%% API +-export([start_link/0]). + +%% Supervisor callbacks +-export([init/1]). +-export([start_handler/0]). + +-define(SERVER, ?MODULE). + +%%%=================================================================== +%%% API functions +%%%=================================================================== + +%% @doc Starts the supervisor +-spec(start_link() -> {ok, Pid :: pid()} | ignore | {error, Reason :: term()}). +start_link() -> + supervisor:start_link({local, ?SERVER}, ?MODULE, []). + +%%%=================================================================== +%%% Supervisor callbacks +%%%=================================================================== + +%% @private +%% @doc Whenever a supervisor is started using supervisor:start_link/[2,3], +%% this function is called by the new process to find out about +%% restart strategy, maximum restart frequency and child +%% specifications. +init([]) -> + SupFlags = #{strategy => simple_one_for_one, intensity => 0, period => 1}, + Spec = #{ + id => dns_handler, + start => {'dns_handler', start_link, []}, + restart => temporary, + shutdown => 2000, + type => worker, + modules => ['dns_handler'] + }, + + {ok, {SupFlags, [Spec]}}. + +%%%=================================================================== +%%% Internal functions +%%%=================================================================== + +start_handler() -> + case supervisor:start_child(?MODULE, []) of + {ok, Pid} -> + {ok, Pid}; + {error, {already_started, Pid}} -> + {ok, Pid}; + StartError -> + StartError + end. \ No newline at end of file diff --git a/apps/sdlan/src/dns_proxy/dns_pending_wheel.erl b/apps/sdlan/src/dns_proxy/dns_pending_wheel.erl new file mode 100644 index 0000000..ad72903 --- /dev/null +++ b/apps/sdlan/src/dns_proxy/dns_pending_wheel.erl @@ -0,0 +1,64 @@ +-module(dns_pending_wheel). + +-export([start/0, insert/2, lookup/1, delete/1]). + +-define(TTL, 5). +-define(TICK_MS, 1000). +-define(WHEEL_SIZE, (?TTL + 1)). + +%%% ===================================================== +%%% Public API +%%% ===================================================== + +start() -> + ets:new(dns_pending_data, [ordered_set, public, named_table, {read_concurrency, true}, {write_concurrency, true}]), + ets:new(dns_pending_wheel, [bag, public, named_table, {read_concurrency, true}, {write_concurrency, true}]), + start_scanner(). + +-spec insert(Key :: any(), Val :: any()) -> ok. +insert(Key, Val) -> + Tick = now_tick(), + Slot = Tick rem ?WHEEL_SIZE, + ets:insert(dns_pending_data, {Key, {Val, Tick}}), + ets:insert(dns_pending_wheel, {Slot, {Key, Tick}}), + ok. + +-spec lookup(Key :: any()) -> [term()]. +lookup(Key) -> + ets:lookup(dns_pending_data, Key). + +-spec delete(Key :: any()) -> ok. +delete(Key) -> + ets:delete(dns_pending_data, Key), + ok. + +%%% ===================================================== +%%% Internal +%%% ===================================================== + +start_scanner() -> + {ok, spawn_link(fun tick_loop/0)}. + +%% 当前插入数据是在Tick, 而清理是从 Tick + 1 开始的,没有问题 +tick_loop() -> + Tick = now_tick(), + CleanSlot = (Tick + 1) rem ?WHEEL_SIZE, + spawn(fun() -> clean_slot(CleanSlot) end), + timer:sleep(?TICK_MS), + tick_loop(). + +clean_slot(Slot) -> + Items = ets:lookup(dns_pending_wheel, Slot), + true = ets:delete(dns_pending_wheel, Slot), + lists:foreach(fun({_, {Key, InsertTick}}) -> + case ets:lookup(dns_pending_data, Key) of + [{Key, {_Val, InsertTick}}] -> + ets:delete(dns_pending_data, Key); + _ -> + ok + end + end, Items). + +-spec now_tick() -> integer(). +now_tick() -> + erlang:system_time(second). \ No newline at end of file diff --git a/apps/sdlan/src/dns_proxy/dns_proxy_sup.erl b/apps/sdlan/src/dns_proxy/dns_proxy_sup.erl new file mode 100644 index 0000000..9882fb7 --- /dev/null +++ b/apps/sdlan/src/dns_proxy/dns_proxy_sup.erl @@ -0,0 +1,50 @@ +%%%------------------------------------------------------------------- +%% @doc dns_proxy top level supervisor. +%% @end +%%%------------------------------------------------------------------- + +-module(dns_proxy_sup). + +-behaviour(supervisor). + +-export([start_link/0]). +-export([init/1]). + +-define(SERVER, ?MODULE). + +start_link() -> + supervisor:start_link({local, ?SERVER}, ?MODULE, []). + +%% sup_flags() = #{strategy => strategy(), % optional +%% intensity => non_neg_integer(), % optional +%% period => pos_integer()} % optional +%% child_spec() = #{id => child_id(), % mandatory +%% start => mfargs(), % mandatory +%% restart => restart(), % optional +%% shutdown => shutdown(), % optional +%% type => worker(), % optional +%% modules => modules()} % optional +init([]) -> + SupFlags = #{strategy => one_for_one, intensity => 1000, period => 3600}, + + Port = 15353, + Specs = [ + #{ + id => dns_handler_sup, + start => {dns_handler_sup, start_link, []}, + restart => permanent, + shutdown => 2000, + type => supervisor, + modules => ['dns_handler_sup'] + }, + #{ + id => dns_server, + start => {dns_server, start_link, [Port]}, + restart => permanent, + shutdown => 2000, + type => worker, + modules => ['dns_server'] + } + ], + + {ok, {SupFlags, Specs}}. \ No newline at end of file diff --git a/apps/sdlan/src/dns_proxy/dns_resolver.erl b/apps/sdlan/src/dns_proxy/dns_resolver.erl new file mode 100644 index 0000000..7058800 --- /dev/null +++ b/apps/sdlan/src/dns_proxy/dns_resolver.erl @@ -0,0 +1,141 @@ +%%%------------------------------------------------------------------- +%%% @author anlicheng +%%% @copyright (C) 2025, +%%% @doc +%%% +%%% @end +%%% Created : 03. 12月 2025 18:26 +%%%------------------------------------------------------------------- +-module(dns_resolver). +-author("anlicheng"). +-include_lib("dns_erlang/include/dns.hrl"). + +-behaviour(gen_server). + +%% API +-export([start_link/1]). + +%% gen_server callbacks +-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). + +-export([forward/5]). + +-define(SERVER, ?MODULE). + +-record(state, { + socket, + idx :: integer(), + dns_servers = [] +}). + +%%%=================================================================== +%%% API +%%%=================================================================== + +forward(Pid, ReceiverPid, Ref, Request, QueryMsg) -> + gen_server:cast(Pid, {forward, ReceiverPid, Ref, Request, QueryMsg}). + +%% @doc Spawns the server and registers the local name (unique) +-spec(start_link(Args :: list()) -> + {ok, Pid :: pid()} | ignore | {error, Reason :: term()}). +start_link(Args) when is_list(Args) -> + gen_server:start_link(?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, DnsServers} = application:get_env(sdlan, public_dns_servers), + {ok, Sock} = gen_udp:open(0, [binary, {active, true}]), + Idx = erlang:unique_integer([monotonic, positive]), + {ok, #state{socket = Sock, idx = Idx, dns_servers = DnsServers}}. + +%% @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{}}). +handle_cast({forward, ReceiverPid, Ref, Request, #dns_message{id = TxId, questions = [#dns_query{name = QName, type = QType, class = QClass}|_]}}, + State = #state{socket = Socket, idx = Idx, dns_servers = DnsServers}) -> + + lists:foreach(fun({DnsIp, DnsPort}) -> + ok = gen_udp:send(Socket, DnsIp, DnsPort, Request), + Key = {Idx, TxId, DnsIp, DnsPort, QName, QType, QClass}, + lager:debug("[dns_resolver] key: ~p, send to: ~p, packet: ~p", [Key, {DnsIp, DnsPort}, Request]), + dns_pending_wheel:insert(Key, {Ref, ReceiverPid}) + end, DnsServers), + + {noreply, State}. + +%% @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({udp, Socket, TargetIp, TargetPort, Resp}, State = #state{socket = Socket, idx = Idx}) -> + try dns:decode_message(Resp) of + #dns_message{id = TxId, questions = [#dns_query{name = QName, type = QType, class = QClass}|_]} -> + Key = {Idx, TxId, TargetIp, TargetPort, QName, QType, QClass}, + Records = dns_pending_wheel:lookup(Key), + dns_pending_wheel:delete(Key), + resolver_reply(Records, Resp); + _ -> + ok + catch error:_ -> + ok + end, + {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 +%%%=================================================================== + +-spec resolver_reply(list(), Resp :: binary()) -> no_return(). +resolver_reply(Records, Resp) when is_binary(Resp) -> + lists:foreach(fun({_, {Ref, ReceiverPid}}) -> + case is_process_alive(ReceiverPid) of + true -> + ReceiverPid ! {dns_resolver_reply, Ref, Resp}; + false -> + ok + end + end, Records). \ No newline at end of file diff --git a/apps/sdlan/src/dns_proxy/dns_server.erl b/apps/sdlan/src/dns_proxy/dns_server.erl new file mode 100644 index 0000000..d624a77 --- /dev/null +++ b/apps/sdlan/src/dns_proxy/dns_server.erl @@ -0,0 +1,24 @@ +-module(dns_server). +-export([start_link/1, init/1]). + +start_link(Port) when is_integer(Port) -> + {ok, spawn_link(?MODULE, init, [Port])}. + +init(Port) -> + dns_cache:init(), + {ok, Sock} = gen_udp:open(Port, [binary, {active, true}]), + lager:debug("[dns_server] DNS Forwarder started on UDP port ~p~n", [Port]), + loop(Sock). + +loop(Sock) -> + receive + {udp, Sock, Ip, Port, Packet} -> + lager:debug("[dns_server] ip: ~p, get a packet: ~p", [{Ip, Port}, Packet]), + case dns_handler_sup:start_handler() of + {ok, HandlerPid} -> + dns_handler:handle_ip_packet(HandlerPid, Sock, Ip, Port, Packet); + Error -> + lager:debug("[dns_server] start handler get error: ~p", [Error]) + end, + loop(Sock) + end. \ No newline at end of file diff --git a/apps/sdlan/src/dns_proxy/dns_utils.erl b/apps/sdlan/src/dns_proxy/dns_utils.erl new file mode 100644 index 0000000..2d07524 --- /dev/null +++ b/apps/sdlan/src/dns_proxy/dns_utils.erl @@ -0,0 +1,131 @@ +%%%------------------------------------------------------------------- +%%% @author anlicheng +%%% @copyright (C) 2025, +%%% @doc +%%% +%%% @end +%%% Created : 05. 12月 2025 18:06 +%%%------------------------------------------------------------------- +-module(dns_utils). +-author("anlicheng"). + +-include_lib("pkt/include/pkt.hrl"). + +%% API +-export([ends_with/2, parse_address/1, checksum/1, udp_checksum/5, ip_checksum/1]). +-export([test/0]). + +-spec ends_with(Bin :: binary(), Suffix :: binary()) -> boolean(). +ends_with(Bin, Suffix) when is_binary(Bin), is_binary(Suffix) -> + case binary:match(Bin, Suffix) of + {Pos, Len} -> + Pos + Len =:= byte_size(Bin); + nomatch -> + false + end. + +-spec parse_address(Ip :: any()) -> {ok, IpAddress :: inet:ip4_address()} | {error, Reason :: any()}. +parse_address(Ip = {Ip0, Ip1, Ip2, Ip3}) when is_integer(Ip0), is_integer(Ip1), is_integer(Ip2), is_integer(Ip3) -> + {ok, Ip}; +parse_address(Bin) when is_binary(Bin) -> + inet:parse_address(binary_to_list(Bin)). + + +%%-------------------------------------------------------------------- +%% @doc +%% Calculate 16-bit one's-complement checksum. +%% +%% Input: +%% Bin :: binary() +%% +%% Output: +%% Checksum :: 0..16#FFFF +%% +%% Usage: +%% Checksum = checksum(Bin). +%% +%% Notes: +%% - Bin is treated as big-endian 16-bit words +%% - If Bin length is odd, a zero byte is padded +%%-------------------------------------------------------------------- +-spec checksum(binary()) -> non_neg_integer(). +checksum(Bin) when is_binary(Bin) -> + Sum = checksum_sum(Bin, 0), + %% fold carry bits + Folded = fold16(Sum), + %% one's complement + (bnot Folded) band 16#FFFF. +checksum_sum(<<>>, Acc) -> + Acc; +checksum_sum(<>, Acc) -> + checksum_sum(Rest, Acc + Word); +checksum_sum(<>, Acc) -> + %% odd length: pad low byte with zero + checksum_sum(<<>>, Acc + (Byte bsl 8)). + +fold16(S) when S > 16#FFFF -> + fold16((S band 16#FFFF) + (S bsr 16)); +fold16(S) -> + S. + +-spec udp_checksum(SAddr :: inet:ip4_address(), DAddr :: inet:ip4_address(), SPort :: integer(), DPort :: integer(), UDPPayload :: binary()) -> non_neg_integer(). +udp_checksum({SA1, SA2, SA3, SA4}, {DA1, DA2, DA3, DA4}, SPort, DPort, UDPPayload) when is_integer(SPort), is_integer(DPort), is_binary(UDPPayload) -> + ULen = 8 + byte_size(UDPPayload), + PseudoHeader = <>, + UDPHeader = <>, + CheckSum = checksum(<>), + case CheckSum of + 0 -> + 16#FFFF; + _ -> + CheckSum + end. + +-spec ip_checksum(Ipv4 :: #ipv4{}) -> non_neg_integer(). +ip_checksum(#ipv4{hl = HL, tos = ToS, len = Len, + id = Id, df = DF, mf = MF, + off = Off, ttl = TTL, p = P, + saddr = {SA1, SA2, SA3, SA4}, + daddr = {DA1, DA2, DA3, DA4}, + opt = Opt}) -> + + IPBinForChecksum = + <<4:4, HL:4, %% Version=4 + IHL + ToS:8, %% Type of Service + Len:16/big, %% Total Length + Id:16/big, %% Identification + DF:1, MF:1, Off:14, %% Flags + Fragment offset + TTL:8, %% TTL + P:8, %% Protocol + 0:16, %% checksum field set to 0 for calculation + SA1:8, SA2:8, SA3:8, SA4:8, %% Source IP + DA1:8, DA2:8, DA3:8, DA4:8, %% Dest IP + Opt/binary>>, %% Options (可选) + CheckSum = checksum(IPBinForChecksum), + case CheckSum of + 0 -> + 16#FFFF; + _ -> + CheckSum + end. + +test() -> + %Bin = <<69,0,0,77,48,179,0,0,64,17,28,168,100,123,0,2,100,100,100,100,252,230,0,53,0,57,6,92,152,24,1,0,0,1,0,0,0,0,0,0,2,100,98,7,95,100,110,115,45,115,100,4,95,117,100,112,8,112,117,110,99,104,110,101,116,2,116,115,3,110,101,116,0,0,12,0,1>>, + Bin = <<69,0,0,93,0,0,0,0,64,6,77,86,100,100,100,100,100,123,0,2,0,53,196,102,0,73,39,7,215,192,129,128,0,1,0,1,0,0,0,0,2,108,98,7,95,100,110,115,45,115,100,4,95,117,100,112,8,112,117,110,99,104,110,101,116,2,116,115,3,110,101,116,0,0,12,0,1,192,12,0,12,0,1,0,0,1,44,0,4,192,168,1,101>>, + + {IPPacket = #ipv4{ + saddr = SAddr, + daddr = DAddr, + sum = IpSum + }, UdpPacket} = pkt:ipv4(Bin), + + {UDP = #udp{sport = SPort, dport = DPort, sum = CheckSum}, UDPPayload} = pkt:udp(UdpPacket), + + X = udp_checksum(SAddr, DAddr, SPort, DPort, UDPPayload), + + lager:debug("ip_sum: ~p, =: ~p, udp: ~p, checkSum: ~p, =: ~p", [IpSum, ip_checksum(IPPacket), UDP, CheckSum, X]), + + dns:decode_message(UDPPayload). \ No newline at end of file diff --git a/apps/sdlan/src/http_handler/node_handler.erl b/apps/sdlan/src/http_handler/node_handler.erl index 9a68acb..e85c13f 100644 --- a/apps/sdlan/src/http_handler/node_handler.erl +++ b/apps/sdlan/src/http_handler/node_handler.erl @@ -45,8 +45,8 @@ handle_request("POST", "/node/move", _, #{<<"client_id">> := ClientId, <<"from_n case {sdlan_network:get_pid(FromNetworkId), sdlan_network:get_pid(ToNetworkId)} of {FromPid, ToPid} when is_pid(FromPid), is_pid(ToPid) -> case sdlan_network:dropout_client(FromPid, ClientId) of - {ok, ChannelPid} -> - Ref = sdlan_channel:move_network(ChannelPid, self(), ToPid), + {ok, ChannelPid, HostName} -> + Ref = sdlan_channel:move_network(ChannelPid, self(), ToPid, HostName), receive {command_reply, Ref, {error, Reason}} -> lager:warning("[node_handler] client_id: ~p, move network from: ~p, to: ~p, get error: ~p", [ClientId, FromPid, ToPid, Reason]), diff --git a/apps/sdlan/src/mnesia/client_model.erl b/apps/sdlan/src/mnesia/client_model.erl index 26738cf..306d3d4 100644 --- a/apps/sdlan/src/mnesia/client_model.erl +++ b/apps/sdlan/src/mnesia/client_model.erl @@ -13,7 +13,7 @@ %% API -export([create_table/1, get_table_name/1]). --export([get_clients/1, delete_clients/1, delete_client/2, disable_client/2, alloc_ip/5]). +-export([get_clients/1, get_client/2, delete_clients/1, delete_client/2, disable_client/2, alloc_ip/6]). -export([debug/1]). create_table(Tab) when is_atom(Tab) -> @@ -28,6 +28,16 @@ create_table(Tab) when is_atom(Tab) -> get_table_name(NetworkId) when is_integer(NetworkId) -> list_to_atom("client_" ++ integer_to_list(NetworkId)). +-spec get_client(NetworkId :: integer(), ClientId :: binary()) -> error | {ok, Client :: #client{}} . +get_client(NetworkId, ClientId) when is_integer(NetworkId), is_binary(ClientId) -> + Tab = get_table_name(NetworkId), + case mnesia:dirty_read(Tab, ClientId) of + [] -> + error; + [Client|_] -> + {ok, Client} + end. + -spec get_clients(NetworkId :: integer()) -> [Client :: #client{}]. get_clients(NetworkId) when is_integer(NetworkId) -> Tab = get_table_name(NetworkId), @@ -48,12 +58,23 @@ delete_clients(NetworkId) when is_integer(NetworkId) -> {error, Reason} end. --spec delete_client(NetworkId :: integer(), ClientId :: binary()) -> ok | {error, Reason :: any()}. +-spec delete_client(NetworkId :: integer(), ClientId :: binary()) -> {ok, Client :: #client{}} | {error, Reason :: any()}. delete_client(NetworkId, ClientId) when is_integer(NetworkId), is_binary(ClientId) -> Tab = get_table_name(NetworkId), - case mnesia:transaction(fun() -> mnesia:delete(Tab, ClientId, write) end) of - {'atomic', ok} -> - ok; + + Fun = fun() -> + case mnesia:read(Tab, ClientId, write) of + [] -> + mnesia:abort(not_found); + [Record] -> + mnesia:delete(Tab, ClientId, write), + {ok, Record} + end + end, + + case mnesia:transaction(Fun) of + {'atomic', {ok, Client}} -> + {ok, Client}; {'aborted', Reason} -> {error, Reason} end. @@ -78,16 +99,16 @@ disable_client(NetworkId, ClientId) when is_integer(NetworkId), is_binary(Client end. %% 分配ip地址的时候,以mac地址为唯一基准 --spec alloc_ip(NetworkId :: integer(), Ips :: list(), ClientId :: binary(), Mac :: binary(), NetAddr0 :: integer()) -> +-spec alloc_ip(NetworkId :: integer(), Ips :: list(), ClientId :: binary(), Mac :: binary(), NetAddr0 :: integer(), HostName :: binary()) -> {ok, Ip :: integer()} | {error, Reason :: any()}. -alloc_ip(NetworkId, Ips, ClientId, Mac, NetAddr0) when is_binary(ClientId), is_integer(NetAddr0), is_binary(Mac) -> - case mnesia:transaction(fun() -> alloc_ip0(NetworkId, Ips, ClientId, Mac, NetAddr0) end) of +alloc_ip(NetworkId, Ips, ClientId, Mac, NetAddr0, HostName) when is_binary(ClientId), is_integer(NetAddr0), is_binary(Mac), is_binary(HostName) -> + case mnesia:transaction(fun() -> alloc_ip0(NetworkId, Ips, ClientId, Mac, NetAddr0, HostName) end) of {'atomic', Res} -> {ok, Res}; {'aborted', Reason} -> {error, Reason} end. -alloc_ip0(NetworkId, Ips, ClientId, Mac, NetAddr0) -> +alloc_ip0(NetworkId, Ips, ClientId, Mac, NetAddr0, HostName) -> Tab = get_table_name(NetworkId), case mnesia:read(Tab, ClientId) of @@ -97,21 +118,28 @@ alloc_ip0(NetworkId, Ips, ClientId, Mac, NetAddr0) -> [#client{status = disabled}] -> mnesia:abort(client_disabled); [] -> - UsedIps = mnesia:foldl(fun(#client{ip = Ip0}, Acc) -> [Ip0|Acc] end, [], Tab), - case lists:member(NetAddr0, Ips) andalso not lists:member(NetAddr0, UsedIps) of + {UsedIps, UsedHostNames} = mnesia:foldl(fun(#client{ip = Ip0, host_name = HostName0}, {IpAcc, HostNameAcc}) -> + {[Ip0|IpAcc], [HostName0|HostNameAcc]} + end, {[], []}, Tab), + case HostName =/= <<>> andalso lists:member(HostName, UsedHostNames) of true -> - %% 如果ip没有被占用,则分配給当前请求 - Client = #client{client_id = ClientId, mac = Mac, ip = NetAddr0}, - ok = mnesia:write(Tab, Client, write), - NetAddr0; + mnesia:abort(host_name_used); false -> - case Ips -- UsedIps of - [] -> - mnesia:abort(no_ip); - [Ip|_] -> - Client = #client{client_id = ClientId, mac = Mac, ip = Ip, status = normal}, + case lists:member(NetAddr0, Ips) andalso not lists:member(NetAddr0, UsedIps) of + true -> + %% 如果ip没有被占用,则分配給当前请求 + Client = #client{client_id = ClientId, mac = Mac, ip = NetAddr0, host_name = HostName, status = normal}, ok = mnesia:write(Tab, Client, write), - Ip + NetAddr0; + false -> + case Ips -- UsedIps of + [] -> + mnesia:abort(no_ip); + [Ip|_] -> + Client = #client{client_id = ClientId, mac = Mac, ip = Ip, host_name = HostName, status = normal}, + ok = mnesia:write(Tab, Client, write), + Ip + end end end end. diff --git a/apps/sdlan/src/sdlan.app.src b/apps/sdlan/src/sdlan.app.src index 645a6b8..be8ab20 100644 --- a/apps/sdlan/src/sdlan.app.src +++ b/apps/sdlan/src/sdlan.app.src @@ -11,11 +11,12 @@ ranch, poolboy, mysql, - esockd, jiffy, hackney, gpb, throttle, + dns_erlang, + pkt, parse_trans, mnesia, erts, diff --git a/apps/sdlan/src/sdlan_api.erl b/apps/sdlan/src/sdlan_api.erl index 5628a76..8b671a4 100644 --- a/apps/sdlan/src/sdlan_api.erl +++ b/apps/sdlan/src/sdlan_api.erl @@ -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]). +-export([auth_token/3, node_online/3, node_offline/2, flow_report/5, network_forward_report/2, auth_network_code/3]). -spec get_all_networks() -> {ok, [NetworkId :: integer()]} | {error, Reason :: any()}. get_all_networks() -> @@ -61,6 +61,20 @@ auth_token(ClientId, Token, Version) when is_binary(ClientId), is_binary(Token), 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 + {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 node_online(ClientId :: binary(), NetworkId :: integer(), IpAddr :: binary()) -> {ok, Resp :: map()} | {error, Reason :: any()}. node_online(ClientId, NetworkId, IpAddr) when is_binary(ClientId), is_integer(NetworkId), is_binary(IpAddr) -> case catch do_post("set_node_status", #{<<"client_id">> => ClientId, <<"network_id">> => NetworkId, <<"ip_addr">> => IpAddr, <<"status">> => 1}) of diff --git a/apps/sdlan/src/sdlan_app.erl b/apps/sdlan/src/sdlan_app.erl index c5f4400..92ac12d 100644 --- a/apps/sdlan/src/sdlan_app.erl +++ b/apps/sdlan/src/sdlan_app.erl @@ -15,6 +15,12 @@ start(_StartType, _StartArgs) -> mnesia:start(), %% 加速内存的回收 erlang:system_flag(fullsweep_after, 16), + + %% 启动注册表 + sdlan_hostname_regedit:init(), + sdlan_domain_regedit:init(), + dns_pending_wheel:start(), + start_http_server(), start_tcp_server(), sdlan_sup:start_link(). @@ -61,18 +67,15 @@ start_tcp_server() -> Backlog = proplists:get_value(backlog, Props, 1024), Port = proplists:get_value(port, Props), - TransOpts = [ - {tcp_options, [ - binary, - {reuseaddr, true}, - {active, false}, - {packet, 2}, + TransOpts = #{ + num_acceptors => Acceptors, + max_connections => MaxConnections, + socket_opts => [ + {port, Port}, {nodelay, false}, {backlog, Backlog} - ]}, - {acceptors, Acceptors}, - {max_connections, MaxConnections} - ], - {ok, _} = esockd:open('sdlan/tcp_server', Port, TransOpts, {sdlan_channel, start_link, []}), + ] + }, + {ok, _} = ranch:start_listener('sdlan/tcp_server', ranch_tcp, TransOpts, sdlan_channel, []), lager:debug("[sdlan_app] the tcp server start at: ~p", [Port]). \ No newline at end of file diff --git a/apps/sdlan/src/sdlan_channel.erl b/apps/sdlan/src/sdlan_channel.erl index 096d8be..5187442 100644 --- a/apps/sdlan/src/sdlan_channel.erl +++ b/apps/sdlan/src/sdlan_channel.erl @@ -28,6 +28,8 @@ -define(NAK_NETWORK_FAULT, 4). %% 内部错误 -define(NAK_INTERNAL_FAULT, 5). +%% hostname被占用 +-define(NAK_HOSTNAME_USED, 6). %% 升级策略 -define(UPGRADE_NONE, 0). @@ -35,8 +37,8 @@ -define(UPGRADE_FORCE, 2). %% API --export([start_link/2]). --export([publish_command/4, send_event/3, stop/2, move_network/3]). +-export([start_link/4]). +-export([publish_command/4, send_event/3, stop/2, move_network/4]). -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). @@ -75,10 +77,10 @@ publish_command(Pid, ReceiverPid, CommandType, Msg) when is_pid(Pid), is_pid(Rec Ref. %% 网络迁移是一种特殊的指令信息,需要单独处理 --spec move_network(Pid :: pid(), ReceiverPid :: pid(), NetworkPid :: pid()) -> Ref :: reference(). -move_network(Pid, ReceiverPid, NetworkPid) when is_pid(Pid), is_pid(ReceiverPid), is_pid(NetworkPid) -> +-spec move_network(Pid :: pid(), ReceiverPid :: pid(), NetworkPid :: pid(), HostName :: binary()) -> Ref :: reference(). +move_network(Pid, ReceiverPid, NetworkPid, HostName) when is_pid(Pid), is_pid(ReceiverPid), is_pid(NetworkPid), is_binary(HostName) -> Ref = make_ref(), - Pid ! {move_network, ReceiverPid, Ref, NetworkPid}, + Pid ! {move_network, ReceiverPid, Ref, NetworkPid, HostName}, Ref. %% 向通道中写入消息 @@ -97,19 +99,15 @@ stop(Pid, Reason) when is_pid(Pid) -> %% esockd callback %%-------------------------------------------------------------------- -start_link(Transport, Sock) -> - {ok, proc_lib:spawn_link(?MODULE, init, [[Transport, Sock]])}. +start_link(Ref, _Socket, Transport, Opts) -> + {ok, proc_lib:spawn_link(?MODULE, init, [[Ref, Transport, Opts]])}. -init([Transport, Sock]) -> - lager:debug("[sdlan_channel] get a new connection: ~p", [Sock]), - case Transport:wait(Sock) of - {ok, NewSock} -> - Transport:setopts(Sock, [{active, true}]), - erlang:start_timer(?PING_TICKER, self(), ping_ticker), - gen_server:enter_loop(?MODULE, [], #state{transport = Transport, socket = NewSock}); - {error, Reason} -> - {stop, Reason} - end. +init([Ref, Transport, _Opts = []]) -> + {ok, Socket} = ranch:handshake(Ref), + lager:debug("[sdlan_channel] get a new connection: ~p", [Socket]), + Transport:setopts(Socket, [{active, true}, {packet, 2}]), + erlang:start_timer(?PING_TICKER, self(), ping_ticker), + gen_server:enter_loop(?MODULE, [], #state{transport = Transport, socket = Socket}). handle_call(_Request, _From, State) -> {reply, ok, State}. @@ -117,23 +115,33 @@ handle_call(_Request, _From, State) -> handle_cast(_Msg, State) -> {noreply, State}. +%% 带上token或者网络id来注册 handle_info({tcp, Sock, <>}, State=#state{transport = Transport, socket = Sock}) -> - #sdl_register_super{version = Version, client_id = ClientId, dev_addr = #sdl_dev_addr{net_addr = NetAddr0, mac = Mac}, token = Token, pub_key = PubKey} = sdlan_pb:decode_msg(Body, sdl_register_super), + #sdl_register_super{version = Version, client_id = ClientId, hostname = HostName, dev_addr = #sdl_dev_addr{net_addr = NetAddr0, mac = Mac}, network_code = NetworkCode, token = Token, pub_key = PubKey} = sdlan_pb:decode_msg(Body, sdl_register_super), %% 参数检查 - lager:debug("[sdlan_channel] client_id: ~p, public_key: ~p", [ClientId, PubKey]), + lager:debug("[sdlan_channel] client_id: ~p, public_key: ~p, token: ~p, network_code: ~p", [ClientId, PubKey, Token, NetworkCode]), true = (Mac =/= <<>> andalso PubKey =/= <<>> andalso ClientId =/= <<>>), %% Mac地址不能是广播地址 true = not (sdlan_util:is_multicast_mac(Mac) orelse sdlan_util:is_broadcast_mac(Mac)), - case sdlan_api:auth_token(ClientId, Token, Version) of + AuthResult = if + Token /= <<>> -> + lager:debug("[sdlan_channel] auth token: ~p", [Token]), + sdlan_api:auth_token(ClientId, Token, Version); + NetworkCode /= <<>> -> + lager:debug("[sdlan_channel] auth network code: ~p", [NetworkCode]), + sdlan_api:auth_network_code(ClientId, NetworkCode, Version) + end, + + case AuthResult of {ok, #{<<"result">> := #{<<"network_id">> := NetworkId, <<"upgrade_type">> := UpgradeType, <<"upgrade_prompt">> := UpgradePrompt, <<"upgrade_address">> := UpgradeAddress}}} when is_integer(NetworkId) -> lager: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]), %% 建立到network的对应关系 case sdlan_network:get_pid(NetworkId) of NetworkPid when is_pid(NetworkPid) -> - try sdlan_network:assign_ip_addr(NetworkPid, self(), ClientId, Mac, NetAddr0) of - {ok, NetAddr, NetBitLen, AesKey} -> + try sdlan_network:assign_ip_addr(NetworkPid, self(), ClientId, Mac, NetAddr0, HostName) of + {ok, Domain, NetAddr, NetBitLen, AesKey} -> RsaPubKey = sdlan_cipher:rsa_pem_decode(PubKey), EncodedAesKey = rsa_encode(AesKey, RsaPubKey), @@ -142,7 +150,8 @@ handle_info({tcp, Sock, <>}, S network_id = NetworkId, net_addr = NetAddr, mac = Mac, - net_bit_len = NetBitLen + net_bit_len = NetBitLen, + network_domain = Domain }, aes_key = EncodedAesKey, upgrade_type = UpgradeType, @@ -167,34 +176,38 @@ handle_info({tcp, Sock, <>}, S {noreply, State#state{client_id = ClientId, mac = Mac, assign_ip = NetAddr, network_pid = NetworkPid, pub_key = PubKey, is_registered = true}} end; {error, no_ip} -> - lager:debug("[sdlan_channel] client_id: ~p, token: ~p, register get error: no_ip", [ClientId, Token]), + lager:warning("[sdlan_channel] client_id: ~p, token: ~p, register get error: no_ip", [ClientId, Token]), Transport:send(Sock, register_nak_reply(PacketId, ?NAK_NO_IP, <<"No Ip address">>)), {stop, normal, State}; + {error, host_name_used} -> + lager:warning("[sdlan_channel] client_id: ~p, token: ~p, register get error: host_name_used", [ClientId, Token]), + Transport:send(Sock, register_nak_reply(PacketId, ?NAK_HOSTNAME_USED, <<"Host Name Used">>)), + {stop, normal, State}; {error, client_disabled} -> - lager:debug("[sdlan_channel] client_id: ~p, token: ~p, register get error: client_disabled", [ClientId, Token]), + lager:warning("[sdlan_channel] client_id: ~p, token: ~p, register get error: client_disabled", [ClientId, Token]), Transport:send(Sock, register_nak_reply(PacketId, ?NAK_NODE_DISABLE, <<"Client Connection Disable">>)), {stop, normal, State} catch _:Error:Stack -> - lager:debug("[sdlan_channel] get error: ~p, stack: ~p", [Error, Stack]) + lager:warning("[sdlan_channel] get error: ~p, stack: ~p", [Error, Stack]) end; undefined -> - lager:debug("[sdlan_channel] client_id: ~p, token: ~p, register get error: network not found", [ClientId, Token]), + lager:warning("[sdlan_channel] client_id: ~p, token: ~p, register get error: network not found", [ClientId, Token]), Transport:send(Sock, register_nak_reply(PacketId, ?NAK_INTERNAL_FAULT, <<"Internal Error">>)), {stop, normal, State} end; {ok, #{<<"error">> := #{<<"code">> := 1, <<"message">> := Message}}} -> - lager:debug("[sdlan_channel] client_id: ~p, token: ~p, register get error: ~p, error_code: 1", [ClientId, Token, Message]), + lager:warning("[sdlan_channel] client_id: ~p, token: ~p, register get error: ~ts, error_code: 1", [ClientId, Token, Message]), Transport:send(Sock, register_nak_reply(PacketId, ?NAK_INVALID_TOKEN, Message)), {stop, normal, State}; {ok, #{<<"error">> := #{<<"code">> := 2, <<"message">> := Message}}} -> - lager:debug("[sdlan_channel] client_id: ~p, token: ~p, register get error: ~p, error_code: 2", [ClientId, Token, Message]), + lager:warning("[sdlan_channel] client_id: ~p, token: ~p, register get error: ~p, error_code: 2", [ClientId, Token, Message]), Transport:send(Sock, register_nak_reply(PacketId, ?NAK_NODE_DISABLE, Message)), {stop, normal, State}; {error, Reason} -> - lager:debug("[sdlan_channel] client_id: ~p, token: ~p, register get error: ~p", [ClientId, Token, Reason]), + lager:warning("[sdlan_channel] client_id: ~p, token: ~p, register get error: ~p", [ClientId, Token, Reason]), Transport:send(Sock, register_nak_reply(PacketId, ?NAK_NETWORK_FAULT, <<"Network Error">>)), {stop, normal, State} end; @@ -225,8 +238,8 @@ handle_info({tcp, Sock, <>}, State {noreply, State} end; -handle_info({tcp, _Sock, <<0:32, ?PACKET_PING>>}, State = #state{transport = Transport, socket = Sock, client_id = ClientId, ping_counter = PingCounter}) -> - lager:debug("[sdlan_channel] client_id: ~p, get ping", [ClientId]), +handle_info({tcp, _Sock, <<0:32, ?PACKET_PING>>}, State = #state{transport = Transport, socket = Sock, ping_counter = PingCounter}) -> + %lager:debug("[sdlan_channel] client_id: ~p, get ping", [ClientId]), Transport:send(Sock, <<0:32, ?PACKET_PONG>>), {noreply, State#state{ping_counter = PingCounter + 1}}; @@ -242,12 +255,12 @@ handle_info({timeout, _, ping_ticker}, State = #state{client_id = ClientId, ping end; %% 重新加入网络 -handle_info({move_network, ReceiverPid, Ref, NetworkPid}, +handle_info({move_network, ReceiverPid, Ref, NetworkPid, HostName}, State = #state{transport = Transport, socket = Sock, client_id = ClientId, mac = Mac, pub_key = PubKey, packet_id = PacketId, inflight = Inflight, is_registered = true}) -> %% 建立到network的对应关系 - case sdlan_network:assign_ip_addr(NetworkPid, self(), ClientId, Mac, 0) of - {ok, NetAddr, NetBitLen, AesKey} -> + case sdlan_network:assign_ip_addr(NetworkPid, self(), ClientId, Mac, 0, HostName) of + {ok, Domain, NetAddr, NetBitLen, AesKey} -> RsaPubKey = sdlan_cipher:rsa_pem_decode(PubKey), EncodedAesKey = rsa_encode(AesKey, RsaPubKey), @@ -257,7 +270,8 @@ handle_info({move_network, ReceiverPid, Ref, NetworkPid}, dev_addr = #sdl_dev_addr { network_id = NetworkId, net_addr = NetAddr, - net_bit_len = NetBitLen + net_bit_len = NetBitLen, + network_domain = Domain }, aes_key = EncodedAesKey }), diff --git a/apps/sdlan/src/sdlan_domain_regedit.erl b/apps/sdlan/src/sdlan_domain_regedit.erl new file mode 100644 index 0000000..7fe64df --- /dev/null +++ b/apps/sdlan/src/sdlan_domain_regedit.erl @@ -0,0 +1,36 @@ +%%%------------------------------------------------------------------- +%%% @author anlicheng +%%% @copyright (C) 2025, +%%% @doc +%%% 内部地址协议注册表 +%%% @end +%%% Created : 13. 12月 2025 21:09 +%%%------------------------------------------------------------------- +-module(sdlan_domain_regedit). +-author("anlicheng"). + +%% API +-export([init/0, insert/1, maybe_domain/1]). + +-define(TABLE, sdlan_domain_regedit). + +init() -> + ets:new(?TABLE, [named_table, ordered_set, public, {read_concurrency, true}, {write_concurrency, true}]). + +-spec maybe_domain(QName :: binary()) -> boolean(). +maybe_domain(QName) when is_binary(QName) -> + case binary:split(QName, <<".">>) of + [_, Domain] -> + case ets:lookup(?TABLE, Domain) of + [{Domain}] -> + true; + [] -> + false + end; + _ -> + false + end. + +-spec insert(Domain :: binary()) -> no_return(). +insert(Domain) when is_binary(Domain) -> + true = ets:insert(?TABLE, {Domain}). \ No newline at end of file diff --git a/apps/sdlan/src/sdlan_hostname_regedit.erl b/apps/sdlan/src/sdlan_hostname_regedit.erl new file mode 100644 index 0000000..c934516 --- /dev/null +++ b/apps/sdlan/src/sdlan_hostname_regedit.erl @@ -0,0 +1,32 @@ +%%%------------------------------------------------------------------- +%%% @author anlicheng +%%% @copyright (C) 2025, +%%% @doc +%%% 内部地址协议注册表 +%%% @end +%%% Created : 13. 12月 2025 21:09 +%%%------------------------------------------------------------------- +-module(sdlan_hostname_regedit). +-author("anlicheng"). + +%% API +-export([init/0, lookup/1, insert/2]). + +-define(TABLE, sdlan_hostname_regedit). + +init() -> + ets:new(?TABLE, [named_table, set, public, {read_concurrency, true}, {write_concurrency, true}]). + +-spec lookup(FullHostname :: binary()) -> error | {ok, Ip :: inet:ip4_address()}. +lookup(FullHostname) when is_binary(FullHostname) -> + case ets:lookup(?TABLE, FullHostname) of + [{_, Ip}] -> + {ok, Ip}; + [] -> + error + end. + +-spec insert(FullHostname :: binary(), Ip :: integer()) -> no_return(). +insert(FullHostname, Ip) when is_binary(FullHostname), is_integer(Ip) -> + <> = <>, + true = ets:insert(?TABLE, {FullHostname, {Ip0, Ip1, Ip2, Ip3}}). \ No newline at end of file diff --git a/apps/sdlan/src/sdlan_network.erl b/apps/sdlan/src/sdlan_network.erl index f5e4f85..5672296 100644 --- a/apps/sdlan/src/sdlan_network.erl +++ b/apps/sdlan/src/sdlan_network.erl @@ -21,7 +21,7 @@ %% API -export([start_link/2]). --export([get_name/1, get_pid/1, assign_ip_addr/5, peer_info/3, unregister/3, debug_info/1, get_network_id/1, get_used_map/1]). +-export([get_name/1, get_pid/1, assign_ip_addr/6, peer_info/3, unregister/3, debug_info/1, get_network_id/1, get_used_map/1]). -export([forward/5, update_hole/6, disable_client/2, get_channel/2, dropout_client/2, reload/1]). -export([test_event/1]). @@ -33,11 +33,9 @@ nat_type :: integer() }). -%% ip的使用信息 +%% ip的使用信息, 记录主机的动态信息 -record(host, { client_id :: binary(), - mac :: binary(), - ip :: integer(), channel_pid :: undefined | pid(), monitor_ref :: undefined | reference(), hole :: undefined | #hole{}, @@ -48,6 +46,7 @@ -record(state, { network_id :: integer(), name :: binary(), + domain :: binary(), ipaddr :: binary(), mask_len :: integer(), owner_id :: integer(), @@ -89,10 +88,10 @@ get_name(Id) when is_integer(Id) -> reload(Pid) when is_pid(Pid) -> gen_server:call(Pid, reload). --spec assign_ip_addr(Pid :: pid(), ChannelPid :: pid(), ClientId :: binary(), Mac :: binary(), NetAddr :: integer()) -> - {ok, NetAddr :: integer(), MaskLen :: integer(), AesKey :: binary()} | {error, Reason :: any()}. -assign_ip_addr(Pid, ChannelPid, ClientId, Mac, NetAddr) when is_pid(Pid), is_pid(ChannelPid), is_binary(ClientId), is_binary(Mac), is_integer(NetAddr) -> - gen_server:call(Pid, {assign_ip_addr, ChannelPid, ClientId, Mac, NetAddr}). +-spec assign_ip_addr(Pid :: pid(), ChannelPid :: pid(), ClientId :: binary(), Mac :: binary(), NetAddr :: integer(), HostName :: binary()) -> + {ok, Domain :: binary(), NetAddr :: integer(), MaskLen :: integer(), AesKey :: binary()} | {error, Reason :: any()}. +assign_ip_addr(Pid, ChannelPid, ClientId, Mac, NetAddr, HostName) when is_pid(Pid), is_pid(ChannelPid), is_binary(ClientId), is_binary(Mac), is_integer(NetAddr) -> + gen_server:call(Pid, {assign_ip_addr, ChannelPid, ClientId, Mac, NetAddr, HostName}). -spec get_network_id(Pid :: pid()) -> {ok, NetworkId :: integer()}. get_network_id(Pid) when is_pid(Pid) -> @@ -125,7 +124,7 @@ 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()} | error. +-spec dropout_client(Pid :: pid(), ClientId :: binary()) -> {ok, ChannelPid :: pid(), HostName :: binary()} | error. dropout_client(Pid, ClientId) when is_pid(Pid), is_binary(ClientId) -> gen_server:call(Pid, {dropout_client, ClientId}). @@ -159,7 +158,7 @@ init([Id]) when is_integer(Id) -> case sdlan_api:get_network(Id) of {ok, #{<<"ipaddr">> := Null}} when Null == <<"null">>; Null == <<"NULL">> -> ignore; - {ok, #{<<"id">> := Id, <<"name">> := Name, <<"ipaddr">> := IpAddr0, <<"owner_id">> := OwnerId}} -> + {ok, #{<<"id">> := Id, <<"name">> := Name, <<"domain">> := Domain, <<"ipaddr">> := IpAddr0, <<"owner_id">> := OwnerId}} -> {IpAddr, MaskLen} = parse_ipaddr(IpAddr0), Ips = sdlan_ipaddr:ips(IpAddr, MaskLen), AesKey = sdlan_util:rand_byte(32), @@ -176,7 +175,9 @@ init([Id]) when is_integer(Id) -> lager:debug("[sdlan_network] network: ~p, ips: ~p", [Id, lists:map(fun sdlan_ipaddr:int_to_ipv4/1, Ips)]), - {ok, #state{network_id = Id, name = Name, ipaddr = IpAddr, owner_id = OwnerId, mask_len = MaskLen, ips = Ips, aes_key = AesKey, throttle_key = ThrottleKey}}; + sdlan_domain_regedit:insert(Domain), + + {ok, #state{network_id = Id, name = Name, domain = Domain, ipaddr = IpAddr, owner_id = OwnerId, mask_len = MaskLen, ips = Ips, aes_key = AesKey, throttle_key = ThrottleKey}}; {error, Reason} -> lager:warning("[sdlan_network] load network: ~p, get error: ~p", [Id, Reason]), ignore @@ -220,23 +221,32 @@ handle_call(reload, _From, State = #state{network_id = Id, ipaddr = OldIpAddr, m end; %% 给客户端分配ip地址 -handle_call({assign_ip_addr, ChannelPid, ClientId, Mac, NetAddr0}, _From, - State = #state{network_id = NetworkId, ips = Ips, used_map = UsedMap, mask_len = MaskLen, aes_key = AesKey}) -> +handle_call({assign_ip_addr, ChannelPid, ClientId, Mac, NetAddr0, HostName}, _From, + State = #state{network_id = NetworkId, domain = Domain, ips = Ips, used_map = UsedMap, mask_len = MaskLen, aes_key = AesKey}) -> %% 分配ip地址的时候,以mac地址为唯一基准 lager:debug("[sdlan_network] alloc_ip, network_id: ~p, ips: ~p, client_id: ~p, mac: ~p, net_addr: ~p", [NetworkId, Ips, ClientId, sdlan_util:format_mac(Mac), sdlan_ipaddr:int_to_ipv4(NetAddr0)]), - case client_model:alloc_ip(NetworkId, Ips, ClientId, Mac, NetAddr0) of + case client_model:alloc_ip(NetworkId, Ips, ClientId, Mac, NetAddr0, HostName) of {ok, Ip} -> %% 关闭之前的channel maybe_close_channel(maps:get(Mac, UsedMap, undefined)), + %% 添加域名->ip的映射关系 + case HostName =/= <<>> of + true -> + FullHostname = <>, + sdlan_hostname_regedit:insert(FullHostname, Ip); + false -> + ok + end, + %% 建立到新的channel之间的关系 MRef = monitor(process, ChannelPid), - NUsedMap = maps:put(Mac, #host{client_id = ClientId, mac = Mac, ip = Ip, channel_pid = ChannelPid, monitor_ref = MRef}, UsedMap), + NUsedMap = maps:put(Mac, #host{client_id = ClientId, channel_pid = ChannelPid, monitor_ref = MRef}, UsedMap), - {reply, {ok, Ip, MaskLen, AesKey}, State#state{used_map = NUsedMap}}; + {reply, {ok, Domain, Ip, MaskLen, AesKey}, State#state{used_map = NUsedMap}}; {error, Reason} -> {reply, {error, Reason}, State} end; @@ -297,9 +307,12 @@ handle_call({dropout_client, ClientId}, _From, State = #state{network_id = Netwo is_reference(MRef) andalso demonitor(MRef), NUsedMap = maps:remove(Mac, UsedMap), %% 从数据库删除 - client_model:delete_client(NetworkId, ClientId), - - {reply, {ok, ChannelPid}, State#state{used_map = NUsedMap}}; + case client_model:delete_client(NetworkId, ClientId) of + {ok, #client{host_name = HostName}} -> + {reply, {ok, ChannelPid, HostName}, State#state{used_map = NUsedMap}}; + {error, _} -> + {reply, error, State} + end; false -> {reply, error, State} end; @@ -337,7 +350,14 @@ handle_call(debug_info, _From, State = #state{network_id = NetworkId, ipaddr = I <<"mask_len">> => MaskLen, <<"owner_id">> => OwnerId, <<"ips">> => lists:map(fun sdlan_ipaddr:int_to_ipv4/1, Ips), - <<"used_ips">> => lists:map(fun({_, Host}) -> format_host(Host) end, maps:to_list(UsedMap)) + <<"used_ips">> => lists:map(fun({_, Host = #host{client_id = ClientId}}) -> + case client_model:get_client(NetworkId, ClientId) of + error -> + #{}; + {ok, #client{mac = Mac, ip = Ip}} -> + format_host(Host, Ip, Mac) + end + end, maps:to_list(UsedMap)) }, {reply, Reply, State}. @@ -434,12 +454,12 @@ handle_cast({unregister, _ClientId, Mac}, State = #state{network_id = NetworkId, end; %% 需要判断,client是属于当前网络的 -handle_cast({update_hole, _ClientId, Mac, Peer, NatType, V6Info}, State = #state{used_map = UsedMap}) -> - case maps:find(Mac, UsedMap) of - {ok, Host0 = #host{hole = OldHole, ip = Ip}} -> +handle_cast({update_hole, ClientId, Mac, Peer, NatType, V6Info}, State = #state{network_id = NetworkId, used_map = UsedMap}) -> + case {maps:find(Mac, UsedMap), client_model:get_client(NetworkId, ClientId)} of + {{ok, Host0 = #host{client_id = ClientId0, hole = OldHole}}, {ok, #client{ip = Ip}}} when ClientId =:= ClientId0 -> case OldHole =:= undefined orelse (OldHole#hole.peer =/= Peer orelse OldHole#hole.nat_type =/= NatType) of true -> - NatChangedEvent = sdlan_pb:encode_msg(#sdl_nat_changed_event { + NatChangedEvent = sdlan_pb:encode_msg(#sdl_nat_changed_event{ mac = Mac, ip = Ip }), @@ -450,7 +470,7 @@ handle_cast({update_hole, _ClientId, Mac, Peer, NatType, V6Info}, State = #state Host = Host0#host{hole = #hole{peer = Peer, nat_type = NatType}, v6_info = V6Info}, {noreply, State#state{used_map = maps:put(Mac, Host, UsedMap)}}; - error -> + _ -> {noreply, State} end. @@ -560,8 +580,8 @@ parse_ipaddr(IpAddr0) when is_binary(IpAddr0) -> {IpAddr0, 24} end. --spec format_host(Host :: #host{}) -> map(). -format_host(#host{client_id = ClientId, mac = Mac, ip = Ip, hole = Hole, v6_info = V6Info}) -> +-spec format_host(Host :: #host{}, Ip :: integer(), Mac :: binary()) -> map(). +format_host(#host{client_id = ClientId, hole = Hole, v6_info = V6Info}, Ip, Mac) when is_integer(Ip), is_binary(Mac) -> HoleMap = case Hole of undefined -> #{}; diff --git a/apps/sdlan/src/sdlan_pb.erl b/apps/sdlan/src/sdlan_pb.erl index f3ddf96..a7c4c8c 100644 --- a/apps/sdlan/src/sdlan_pb.erl +++ b/apps/sdlan/src/sdlan_pb.erl @@ -213,7 +213,7 @@ encode_msg_sdl_v6_info(#sdl_v6_info{port = F1, v6 = F2}, Bin, TrUserData) -> encode_msg_sdl_dev_addr(Msg, TrUserData) -> encode_msg_sdl_dev_addr(Msg, <<>>, TrUserData). -encode_msg_sdl_dev_addr(#sdl_dev_addr{network_id = F1, mac = F2, net_addr = F3, net_bit_len = F4}, Bin, TrUserData) -> +encode_msg_sdl_dev_addr(#sdl_dev_addr{network_id = F1, mac = F2, net_addr = F3, net_bit_len = F4, network_domain = F5}, Bin, TrUserData) -> B1 = if F1 == undefined -> Bin; true -> begin @@ -242,12 +242,22 @@ encode_msg_sdl_dev_addr(#sdl_dev_addr{network_id = F1, mac = F2, net_addr = F3, end end end, - if F4 == undefined -> B3; + B4 = if F4 == undefined -> B3; + true -> + begin + TrF4 = id(F4, TrUserData), + if TrF4 =:= 0 -> B3; + true -> e_varint(TrF4, <>, TrUserData) + end + end + end, + if F5 == undefined -> B4; true -> begin - TrF4 = id(F4, TrUserData), - if TrF4 =:= 0 -> B3; - true -> e_varint(TrF4, <>, TrUserData) + TrF5 = id(F5, TrUserData), + case is_empty_string(TrF5) of + true -> B4; + false -> e_type_string(TrF5, <>, TrUserData) end end end. @@ -257,7 +267,7 @@ encode_msg_sdl_empty(_Msg, _TrUserData) -> <<>>. encode_msg_sdl_register_super(Msg, TrUserData) -> encode_msg_sdl_register_super(Msg, <<>>, TrUserData). -encode_msg_sdl_register_super(#sdl_register_super{version = F1, installed_channel = F2, client_id = F3, dev_addr = F4, pub_key = F5, token = F6}, Bin, TrUserData) -> +encode_msg_sdl_register_super(#sdl_register_super{version = F1, installed_channel = F2, client_id = F3, dev_addr = F4, pub_key = F5, token = F6, network_code = F7, hostname = F8}, Bin, TrUserData) -> B1 = if F1 == undefined -> Bin; true -> begin @@ -306,13 +316,33 @@ encode_msg_sdl_register_super(#sdl_register_super{version = F1, installed_channe end end end, - if F6 == undefined -> B5; + B6 = if F6 == undefined -> B5; + true -> + begin + TrF6 = id(F6, TrUserData), + case is_empty_string(TrF6) of + true -> B5; + false -> e_type_string(TrF6, <>, TrUserData) + end + end + end, + B7 = if F7 == undefined -> B6; + true -> + begin + TrF7 = id(F7, TrUserData), + case is_empty_string(TrF7) of + true -> B6; + false -> e_type_string(TrF7, <>, TrUserData) + end + end + end, + if F8 == undefined -> B7; true -> begin - TrF6 = id(F6, TrUserData), - case is_empty_string(TrF6) of - true -> B5; - false -> e_type_string(TrF6, <>, TrUserData) + TrF8 = id(F8, TrUserData), + case is_empty_string(TrF8) of + true -> B7; + false -> e_type_string(TrF8, <>, TrUserData) end end end. @@ -1149,70 +1179,77 @@ skip_32_sdl_v6_info(<<_:32, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, TrUserData) -> skip_64_sdl_v6_info(<<_:64, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, TrUserData) -> dfp_read_field_def_sdl_v6_info(Rest, Z1, Z2, F, F@_1, F@_2, TrUserData). -decode_msg_sdl_dev_addr(Bin, TrUserData) -> dfp_read_field_def_sdl_dev_addr(Bin, 0, 0, 0, id(0, TrUserData), id(<<>>, TrUserData), id(0, TrUserData), id(0, TrUserData), TrUserData). +decode_msg_sdl_dev_addr(Bin, TrUserData) -> dfp_read_field_def_sdl_dev_addr(Bin, 0, 0, 0, id(0, TrUserData), id(<<>>, TrUserData), id(0, TrUserData), id(0, TrUserData), id(<<>>, TrUserData), TrUserData). -dfp_read_field_def_sdl_dev_addr(<<8, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, TrUserData) -> d_field_sdl_dev_addr_network_id(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, TrUserData); -dfp_read_field_def_sdl_dev_addr(<<18, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, TrUserData) -> d_field_sdl_dev_addr_mac(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, TrUserData); -dfp_read_field_def_sdl_dev_addr(<<24, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, TrUserData) -> d_field_sdl_dev_addr_net_addr(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, TrUserData); -dfp_read_field_def_sdl_dev_addr(<<32, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, TrUserData) -> d_field_sdl_dev_addr_net_bit_len(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, TrUserData); -dfp_read_field_def_sdl_dev_addr(<<>>, 0, 0, _, F@_1, F@_2, F@_3, F@_4, _) -> #sdl_dev_addr{network_id = F@_1, mac = F@_2, net_addr = F@_3, net_bit_len = F@_4}; -dfp_read_field_def_sdl_dev_addr(Other, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, TrUserData) -> dg_read_field_def_sdl_dev_addr(Other, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, TrUserData). +dfp_read_field_def_sdl_dev_addr(<<8, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData) -> d_field_sdl_dev_addr_network_id(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData); +dfp_read_field_def_sdl_dev_addr(<<18, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData) -> d_field_sdl_dev_addr_mac(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData); +dfp_read_field_def_sdl_dev_addr(<<24, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData) -> d_field_sdl_dev_addr_net_addr(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData); +dfp_read_field_def_sdl_dev_addr(<<32, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData) -> d_field_sdl_dev_addr_net_bit_len(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData); +dfp_read_field_def_sdl_dev_addr(<<42, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData) -> d_field_sdl_dev_addr_network_domain(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData); +dfp_read_field_def_sdl_dev_addr(<<>>, 0, 0, _, F@_1, F@_2, F@_3, F@_4, F@_5, _) -> #sdl_dev_addr{network_id = F@_1, mac = F@_2, net_addr = F@_3, net_bit_len = F@_4, network_domain = F@_5}; +dfp_read_field_def_sdl_dev_addr(Other, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData) -> dg_read_field_def_sdl_dev_addr(Other, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData). -dg_read_field_def_sdl_dev_addr(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, TrUserData) when N < 32 - 7 -> dg_read_field_def_sdl_dev_addr(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, F@_4, TrUserData); -dg_read_field_def_sdl_dev_addr(<<0:1, X:7, Rest/binary>>, N, Acc, _, F@_1, F@_2, F@_3, F@_4, TrUserData) -> +dg_read_field_def_sdl_dev_addr(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData) when N < 32 - 7 -> dg_read_field_def_sdl_dev_addr(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData); +dg_read_field_def_sdl_dev_addr(<<0:1, X:7, Rest/binary>>, N, Acc, _, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData) -> Key = X bsl N + Acc, case Key of - 8 -> d_field_sdl_dev_addr_network_id(Rest, 0, 0, 0, F@_1, F@_2, F@_3, F@_4, TrUserData); - 18 -> d_field_sdl_dev_addr_mac(Rest, 0, 0, 0, F@_1, F@_2, F@_3, F@_4, TrUserData); - 24 -> d_field_sdl_dev_addr_net_addr(Rest, 0, 0, 0, F@_1, F@_2, F@_3, F@_4, TrUserData); - 32 -> d_field_sdl_dev_addr_net_bit_len(Rest, 0, 0, 0, F@_1, F@_2, F@_3, F@_4, TrUserData); + 8 -> d_field_sdl_dev_addr_network_id(Rest, 0, 0, 0, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData); + 18 -> d_field_sdl_dev_addr_mac(Rest, 0, 0, 0, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData); + 24 -> d_field_sdl_dev_addr_net_addr(Rest, 0, 0, 0, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData); + 32 -> d_field_sdl_dev_addr_net_bit_len(Rest, 0, 0, 0, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData); + 42 -> d_field_sdl_dev_addr_network_domain(Rest, 0, 0, 0, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData); _ -> case Key band 7 of - 0 -> skip_varint_sdl_dev_addr(Rest, 0, 0, Key bsr 3, F@_1, F@_2, F@_3, F@_4, TrUserData); - 1 -> skip_64_sdl_dev_addr(Rest, 0, 0, Key bsr 3, F@_1, F@_2, F@_3, F@_4, TrUserData); - 2 -> skip_length_delimited_sdl_dev_addr(Rest, 0, 0, Key bsr 3, F@_1, F@_2, F@_3, F@_4, TrUserData); - 3 -> skip_group_sdl_dev_addr(Rest, 0, 0, Key bsr 3, F@_1, F@_2, F@_3, F@_4, TrUserData); - 5 -> skip_32_sdl_dev_addr(Rest, 0, 0, Key bsr 3, F@_1, F@_2, F@_3, F@_4, TrUserData) + 0 -> skip_varint_sdl_dev_addr(Rest, 0, 0, Key bsr 3, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData); + 1 -> skip_64_sdl_dev_addr(Rest, 0, 0, Key bsr 3, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData); + 2 -> skip_length_delimited_sdl_dev_addr(Rest, 0, 0, Key bsr 3, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData); + 3 -> skip_group_sdl_dev_addr(Rest, 0, 0, Key bsr 3, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData); + 5 -> skip_32_sdl_dev_addr(Rest, 0, 0, Key bsr 3, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData) end end; -dg_read_field_def_sdl_dev_addr(<<>>, 0, 0, _, F@_1, F@_2, F@_3, F@_4, _) -> #sdl_dev_addr{network_id = F@_1, mac = F@_2, net_addr = F@_3, net_bit_len = F@_4}. +dg_read_field_def_sdl_dev_addr(<<>>, 0, 0, _, F@_1, F@_2, F@_3, F@_4, F@_5, _) -> #sdl_dev_addr{network_id = F@_1, mac = F@_2, net_addr = F@_3, net_bit_len = F@_4, network_domain = F@_5}. -d_field_sdl_dev_addr_network_id(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, TrUserData) when N < 57 -> d_field_sdl_dev_addr_network_id(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, F@_4, TrUserData); -d_field_sdl_dev_addr_network_id(<<0:1, X:7, Rest/binary>>, N, Acc, F, _, F@_2, F@_3, F@_4, TrUserData) -> +d_field_sdl_dev_addr_network_id(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData) when N < 57 -> d_field_sdl_dev_addr_network_id(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData); +d_field_sdl_dev_addr_network_id(<<0:1, X:7, Rest/binary>>, N, Acc, F, _, F@_2, F@_3, F@_4, F@_5, TrUserData) -> {NewFValue, RestF} = {id((X bsl N + Acc) band 4294967295, TrUserData), Rest}, - dfp_read_field_def_sdl_dev_addr(RestF, 0, 0, F, NewFValue, F@_2, F@_3, F@_4, TrUserData). + dfp_read_field_def_sdl_dev_addr(RestF, 0, 0, F, NewFValue, F@_2, F@_3, F@_4, F@_5, TrUserData). -d_field_sdl_dev_addr_mac(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, TrUserData) when N < 57 -> d_field_sdl_dev_addr_mac(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, F@_4, TrUserData); -d_field_sdl_dev_addr_mac(<<0:1, X:7, Rest/binary>>, N, Acc, F, F@_1, _, F@_3, F@_4, TrUserData) -> +d_field_sdl_dev_addr_mac(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData) when N < 57 -> d_field_sdl_dev_addr_mac(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData); +d_field_sdl_dev_addr_mac(<<0:1, X:7, Rest/binary>>, N, Acc, F, F@_1, _, F@_3, F@_4, F@_5, TrUserData) -> {NewFValue, RestF} = begin Len = X bsl N + Acc, <> = Rest, Bytes2 = binary:copy(Bytes), {id(Bytes2, TrUserData), Rest2} end, - dfp_read_field_def_sdl_dev_addr(RestF, 0, 0, F, F@_1, NewFValue, F@_3, F@_4, TrUserData). + dfp_read_field_def_sdl_dev_addr(RestF, 0, 0, F, F@_1, NewFValue, F@_3, F@_4, F@_5, TrUserData). -d_field_sdl_dev_addr_net_addr(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, TrUserData) when N < 57 -> d_field_sdl_dev_addr_net_addr(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, F@_4, TrUserData); -d_field_sdl_dev_addr_net_addr(<<0:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, _, F@_4, TrUserData) -> +d_field_sdl_dev_addr_net_addr(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData) when N < 57 -> d_field_sdl_dev_addr_net_addr(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData); +d_field_sdl_dev_addr_net_addr(<<0:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, _, F@_4, F@_5, TrUserData) -> {NewFValue, RestF} = {id((X bsl N + Acc) band 4294967295, TrUserData), Rest}, - dfp_read_field_def_sdl_dev_addr(RestF, 0, 0, F, F@_1, F@_2, NewFValue, F@_4, TrUserData). + dfp_read_field_def_sdl_dev_addr(RestF, 0, 0, F, F@_1, F@_2, NewFValue, F@_4, F@_5, TrUserData). -d_field_sdl_dev_addr_net_bit_len(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, TrUserData) when N < 57 -> d_field_sdl_dev_addr_net_bit_len(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, F@_4, TrUserData); -d_field_sdl_dev_addr_net_bit_len(<<0:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, _, TrUserData) -> +d_field_sdl_dev_addr_net_bit_len(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData) when N < 57 -> d_field_sdl_dev_addr_net_bit_len(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData); +d_field_sdl_dev_addr_net_bit_len(<<0:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, _, F@_5, TrUserData) -> {NewFValue, RestF} = {id((X bsl N + Acc) band 4294967295, TrUserData), Rest}, - dfp_read_field_def_sdl_dev_addr(RestF, 0, 0, F, F@_1, F@_2, F@_3, NewFValue, TrUserData). + dfp_read_field_def_sdl_dev_addr(RestF, 0, 0, F, F@_1, F@_2, F@_3, NewFValue, F@_5, TrUserData). -skip_varint_sdl_dev_addr(<<1:1, _:7, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, TrUserData) -> skip_varint_sdl_dev_addr(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, TrUserData); -skip_varint_sdl_dev_addr(<<0:1, _:7, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, TrUserData) -> dfp_read_field_def_sdl_dev_addr(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, TrUserData). +d_field_sdl_dev_addr_network_domain(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData) when N < 57 -> d_field_sdl_dev_addr_network_domain(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData); +d_field_sdl_dev_addr_network_domain(<<0:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, _, TrUserData) -> + {NewFValue, RestF} = begin Len = X bsl N + Acc, <> = Rest, Bytes2 = binary:copy(Bytes), {id(Bytes2, TrUserData), Rest2} end, + dfp_read_field_def_sdl_dev_addr(RestF, 0, 0, F, F@_1, F@_2, F@_3, F@_4, NewFValue, TrUserData). -skip_length_delimited_sdl_dev_addr(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, TrUserData) when N < 57 -> skip_length_delimited_sdl_dev_addr(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, F@_4, TrUserData); -skip_length_delimited_sdl_dev_addr(<<0:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, TrUserData) -> +skip_varint_sdl_dev_addr(<<1:1, _:7, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData) -> skip_varint_sdl_dev_addr(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData); +skip_varint_sdl_dev_addr(<<0:1, _:7, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData) -> dfp_read_field_def_sdl_dev_addr(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData). + +skip_length_delimited_sdl_dev_addr(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData) when N < 57 -> skip_length_delimited_sdl_dev_addr(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData); +skip_length_delimited_sdl_dev_addr(<<0:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData) -> Length = X bsl N + Acc, <<_:Length/binary, Rest2/binary>> = Rest, - dfp_read_field_def_sdl_dev_addr(Rest2, 0, 0, F, F@_1, F@_2, F@_3, F@_4, TrUserData). + dfp_read_field_def_sdl_dev_addr(Rest2, 0, 0, F, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData). -skip_group_sdl_dev_addr(Bin, _, Z2, FNum, F@_1, F@_2, F@_3, F@_4, TrUserData) -> +skip_group_sdl_dev_addr(Bin, _, Z2, FNum, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData) -> {_, Rest} = read_group(Bin, FNum), - dfp_read_field_def_sdl_dev_addr(Rest, 0, Z2, FNum, F@_1, F@_2, F@_3, F@_4, TrUserData). + dfp_read_field_def_sdl_dev_addr(Rest, 0, Z2, FNum, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData). -skip_32_sdl_dev_addr(<<_:32, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, TrUserData) -> dfp_read_field_def_sdl_dev_addr(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, TrUserData). +skip_32_sdl_dev_addr(<<_:32, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData) -> dfp_read_field_def_sdl_dev_addr(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData). -skip_64_sdl_dev_addr(<<_:64, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, TrUserData) -> dfp_read_field_def_sdl_dev_addr(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, TrUserData). +skip_64_sdl_dev_addr(<<_:64, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData) -> dfp_read_field_def_sdl_dev_addr(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, TrUserData). decode_msg_sdl_empty(Bin, TrUserData) -> dfp_read_field_def_sdl_empty(Bin, 0, 0, 0, TrUserData). @@ -1248,59 +1285,68 @@ skip_32_sdl_empty(<<_:32, Rest/binary>>, Z1, Z2, F, TrUserData) -> dfp_read_fiel skip_64_sdl_empty(<<_:64, Rest/binary>>, Z1, Z2, F, TrUserData) -> dfp_read_field_def_sdl_empty(Rest, Z1, Z2, F, TrUserData). -decode_msg_sdl_register_super(Bin, TrUserData) -> dfp_read_field_def_sdl_register_super(Bin, 0, 0, 0, id(0, TrUserData), id(<<>>, TrUserData), id(<<>>, TrUserData), id(undefined, TrUserData), id(<<>>, TrUserData), id(<<>>, TrUserData), TrUserData). +decode_msg_sdl_register_super(Bin, TrUserData) -> + dfp_read_field_def_sdl_register_super(Bin, 0, 0, 0, id(0, TrUserData), id(<<>>, TrUserData), id(<<>>, TrUserData), id(undefined, TrUserData), id(<<>>, TrUserData), id(<<>>, TrUserData), id(<<>>, TrUserData), id(<<>>, TrUserData), TrUserData). -dfp_read_field_def_sdl_register_super(<<8, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, TrUserData) -> d_field_sdl_register_super_version(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, TrUserData); -dfp_read_field_def_sdl_register_super(<<18, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, TrUserData) -> d_field_sdl_register_super_installed_channel(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, TrUserData); -dfp_read_field_def_sdl_register_super(<<26, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, TrUserData) -> d_field_sdl_register_super_client_id(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, TrUserData); -dfp_read_field_def_sdl_register_super(<<34, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, TrUserData) -> d_field_sdl_register_super_dev_addr(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, TrUserData); -dfp_read_field_def_sdl_register_super(<<42, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, TrUserData) -> d_field_sdl_register_super_pub_key(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, TrUserData); -dfp_read_field_def_sdl_register_super(<<50, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, TrUserData) -> d_field_sdl_register_super_token(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, TrUserData); -dfp_read_field_def_sdl_register_super(<<>>, 0, 0, _, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, _) -> #sdl_register_super{version = F@_1, installed_channel = F@_2, client_id = F@_3, dev_addr = F@_4, pub_key = F@_5, token = F@_6}; -dfp_read_field_def_sdl_register_super(Other, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, TrUserData) -> dg_read_field_def_sdl_register_super(Other, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, TrUserData). +dfp_read_field_def_sdl_register_super(<<8, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, TrUserData) -> d_field_sdl_register_super_version(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, TrUserData); +dfp_read_field_def_sdl_register_super(<<18, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, TrUserData) -> + d_field_sdl_register_super_installed_channel(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, TrUserData); +dfp_read_field_def_sdl_register_super(<<26, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, TrUserData) -> d_field_sdl_register_super_client_id(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, TrUserData); +dfp_read_field_def_sdl_register_super(<<34, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, TrUserData) -> d_field_sdl_register_super_dev_addr(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, TrUserData); +dfp_read_field_def_sdl_register_super(<<42, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, TrUserData) -> d_field_sdl_register_super_pub_key(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, TrUserData); +dfp_read_field_def_sdl_register_super(<<50, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, TrUserData) -> d_field_sdl_register_super_token(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, TrUserData); +dfp_read_field_def_sdl_register_super(<<58, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, TrUserData) -> d_field_sdl_register_super_network_code(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, TrUserData); +dfp_read_field_def_sdl_register_super(<<66, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, TrUserData) -> d_field_sdl_register_super_hostname(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, TrUserData); +dfp_read_field_def_sdl_register_super(<<>>, 0, 0, _, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, _) -> + #sdl_register_super{version = F@_1, installed_channel = F@_2, client_id = F@_3, dev_addr = F@_4, pub_key = F@_5, token = F@_6, network_code = F@_7, hostname = F@_8}; +dfp_read_field_def_sdl_register_super(Other, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, TrUserData) -> dg_read_field_def_sdl_register_super(Other, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, TrUserData). -dg_read_field_def_sdl_register_super(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, TrUserData) when N < 32 - 7 -> - dg_read_field_def_sdl_register_super(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, TrUserData); -dg_read_field_def_sdl_register_super(<<0:1, X:7, Rest/binary>>, N, Acc, _, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, TrUserData) -> +dg_read_field_def_sdl_register_super(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, TrUserData) when N < 32 - 7 -> + dg_read_field_def_sdl_register_super(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, TrUserData); +dg_read_field_def_sdl_register_super(<<0:1, X:7, Rest/binary>>, N, Acc, _, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, TrUserData) -> Key = X bsl N + Acc, case Key of - 8 -> d_field_sdl_register_super_version(Rest, 0, 0, 0, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, TrUserData); - 18 -> d_field_sdl_register_super_installed_channel(Rest, 0, 0, 0, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, TrUserData); - 26 -> d_field_sdl_register_super_client_id(Rest, 0, 0, 0, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, TrUserData); - 34 -> d_field_sdl_register_super_dev_addr(Rest, 0, 0, 0, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, TrUserData); - 42 -> d_field_sdl_register_super_pub_key(Rest, 0, 0, 0, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, TrUserData); - 50 -> d_field_sdl_register_super_token(Rest, 0, 0, 0, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, TrUserData); + 8 -> d_field_sdl_register_super_version(Rest, 0, 0, 0, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, TrUserData); + 18 -> d_field_sdl_register_super_installed_channel(Rest, 0, 0, 0, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, TrUserData); + 26 -> d_field_sdl_register_super_client_id(Rest, 0, 0, 0, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, TrUserData); + 34 -> d_field_sdl_register_super_dev_addr(Rest, 0, 0, 0, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, TrUserData); + 42 -> d_field_sdl_register_super_pub_key(Rest, 0, 0, 0, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, TrUserData); + 50 -> d_field_sdl_register_super_token(Rest, 0, 0, 0, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, TrUserData); + 58 -> d_field_sdl_register_super_network_code(Rest, 0, 0, 0, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, TrUserData); + 66 -> d_field_sdl_register_super_hostname(Rest, 0, 0, 0, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, TrUserData); _ -> case Key band 7 of - 0 -> skip_varint_sdl_register_super(Rest, 0, 0, Key bsr 3, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, TrUserData); - 1 -> skip_64_sdl_register_super(Rest, 0, 0, Key bsr 3, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, TrUserData); - 2 -> skip_length_delimited_sdl_register_super(Rest, 0, 0, Key bsr 3, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, TrUserData); - 3 -> skip_group_sdl_register_super(Rest, 0, 0, Key bsr 3, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, TrUserData); - 5 -> skip_32_sdl_register_super(Rest, 0, 0, Key bsr 3, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, TrUserData) + 0 -> skip_varint_sdl_register_super(Rest, 0, 0, Key bsr 3, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, TrUserData); + 1 -> skip_64_sdl_register_super(Rest, 0, 0, Key bsr 3, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, TrUserData); + 2 -> skip_length_delimited_sdl_register_super(Rest, 0, 0, Key bsr 3, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, TrUserData); + 3 -> skip_group_sdl_register_super(Rest, 0, 0, Key bsr 3, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, TrUserData); + 5 -> skip_32_sdl_register_super(Rest, 0, 0, Key bsr 3, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, TrUserData) end end; -dg_read_field_def_sdl_register_super(<<>>, 0, 0, _, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, _) -> #sdl_register_super{version = F@_1, installed_channel = F@_2, client_id = F@_3, dev_addr = F@_4, pub_key = F@_5, token = F@_6}. +dg_read_field_def_sdl_register_super(<<>>, 0, 0, _, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, _) -> + #sdl_register_super{version = F@_1, installed_channel = F@_2, client_id = F@_3, dev_addr = F@_4, pub_key = F@_5, token = F@_6, network_code = F@_7, hostname = F@_8}. -d_field_sdl_register_super_version(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, TrUserData) when N < 57 -> d_field_sdl_register_super_version(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, TrUserData); -d_field_sdl_register_super_version(<<0:1, X:7, Rest/binary>>, N, Acc, F, _, F@_2, F@_3, F@_4, F@_5, F@_6, TrUserData) -> +d_field_sdl_register_super_version(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, TrUserData) when N < 57 -> + d_field_sdl_register_super_version(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, TrUserData); +d_field_sdl_register_super_version(<<0:1, X:7, Rest/binary>>, N, Acc, F, _, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, TrUserData) -> {NewFValue, RestF} = {id((X bsl N + Acc) band 4294967295, TrUserData), Rest}, - dfp_read_field_def_sdl_register_super(RestF, 0, 0, F, NewFValue, F@_2, F@_3, F@_4, F@_5, F@_6, TrUserData). + dfp_read_field_def_sdl_register_super(RestF, 0, 0, F, NewFValue, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, TrUserData). -d_field_sdl_register_super_installed_channel(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, TrUserData) when N < 57 -> - d_field_sdl_register_super_installed_channel(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, TrUserData); -d_field_sdl_register_super_installed_channel(<<0:1, X:7, Rest/binary>>, N, Acc, F, F@_1, _, F@_3, F@_4, F@_5, F@_6, TrUserData) -> +d_field_sdl_register_super_installed_channel(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, TrUserData) when N < 57 -> + d_field_sdl_register_super_installed_channel(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, TrUserData); +d_field_sdl_register_super_installed_channel(<<0:1, X:7, Rest/binary>>, N, Acc, F, F@_1, _, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, TrUserData) -> {NewFValue, RestF} = begin Len = X bsl N + Acc, <> = Rest, Bytes2 = binary:copy(Bytes), {id(Bytes2, TrUserData), Rest2} end, - dfp_read_field_def_sdl_register_super(RestF, 0, 0, F, F@_1, NewFValue, F@_3, F@_4, F@_5, F@_6, TrUserData). + dfp_read_field_def_sdl_register_super(RestF, 0, 0, F, F@_1, NewFValue, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, TrUserData). -d_field_sdl_register_super_client_id(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, TrUserData) when N < 57 -> - d_field_sdl_register_super_client_id(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, TrUserData); -d_field_sdl_register_super_client_id(<<0:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, _, F@_4, F@_5, F@_6, TrUserData) -> +d_field_sdl_register_super_client_id(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, TrUserData) when N < 57 -> + d_field_sdl_register_super_client_id(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, TrUserData); +d_field_sdl_register_super_client_id(<<0:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, _, F@_4, F@_5, F@_6, F@_7, F@_8, TrUserData) -> {NewFValue, RestF} = begin Len = X bsl N + Acc, <> = Rest, Bytes2 = binary:copy(Bytes), {id(Bytes2, TrUserData), Rest2} end, - dfp_read_field_def_sdl_register_super(RestF, 0, 0, F, F@_1, F@_2, NewFValue, F@_4, F@_5, F@_6, TrUserData). + dfp_read_field_def_sdl_register_super(RestF, 0, 0, F, F@_1, F@_2, NewFValue, F@_4, F@_5, F@_6, F@_7, F@_8, TrUserData). -d_field_sdl_register_super_dev_addr(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, TrUserData) when N < 57 -> - d_field_sdl_register_super_dev_addr(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, TrUserData); -d_field_sdl_register_super_dev_addr(<<0:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, Prev, F@_5, F@_6, TrUserData) -> +d_field_sdl_register_super_dev_addr(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, TrUserData) when N < 57 -> + d_field_sdl_register_super_dev_addr(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, TrUserData); +d_field_sdl_register_super_dev_addr(<<0:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, Prev, F@_5, F@_6, F@_7, F@_8, TrUserData) -> {NewFValue, RestF} = begin Len = X bsl N + Acc, <> = Rest, {id(decode_msg_sdl_dev_addr(Bs, TrUserData), TrUserData), Rest2} end, dfp_read_field_def_sdl_register_super(RestF, 0, @@ -1314,35 +1360,51 @@ d_field_sdl_register_super_dev_addr(<<0:1, X:7, Rest/binary>>, N, Acc, F, F@_1, end, F@_5, F@_6, + F@_7, + F@_8, TrUserData). -d_field_sdl_register_super_pub_key(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, TrUserData) when N < 57 -> d_field_sdl_register_super_pub_key(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, TrUserData); -d_field_sdl_register_super_pub_key(<<0:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, _, F@_6, TrUserData) -> +d_field_sdl_register_super_pub_key(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, TrUserData) when N < 57 -> + d_field_sdl_register_super_pub_key(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, TrUserData); +d_field_sdl_register_super_pub_key(<<0:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, _, F@_6, F@_7, F@_8, TrUserData) -> {NewFValue, RestF} = begin Len = X bsl N + Acc, <> = Rest, Bytes2 = binary:copy(Bytes), {id(Bytes2, TrUserData), Rest2} end, - dfp_read_field_def_sdl_register_super(RestF, 0, 0, F, F@_1, F@_2, F@_3, F@_4, NewFValue, F@_6, TrUserData). + dfp_read_field_def_sdl_register_super(RestF, 0, 0, F, F@_1, F@_2, F@_3, F@_4, NewFValue, F@_6, F@_7, F@_8, TrUserData). -d_field_sdl_register_super_token(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, TrUserData) when N < 57 -> d_field_sdl_register_super_token(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, TrUserData); -d_field_sdl_register_super_token(<<0:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, _, TrUserData) -> +d_field_sdl_register_super_token(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, TrUserData) when N < 57 -> + d_field_sdl_register_super_token(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, TrUserData); +d_field_sdl_register_super_token(<<0:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, _, F@_7, F@_8, TrUserData) -> {NewFValue, RestF} = begin Len = X bsl N + Acc, <> = Rest, Bytes2 = binary:copy(Bytes), {id(Bytes2, TrUserData), Rest2} end, - dfp_read_field_def_sdl_register_super(RestF, 0, 0, F, F@_1, F@_2, F@_3, F@_4, F@_5, NewFValue, TrUserData). + dfp_read_field_def_sdl_register_super(RestF, 0, 0, F, F@_1, F@_2, F@_3, F@_4, F@_5, NewFValue, F@_7, F@_8, TrUserData). -skip_varint_sdl_register_super(<<1:1, _:7, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, TrUserData) -> skip_varint_sdl_register_super(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, TrUserData); -skip_varint_sdl_register_super(<<0:1, _:7, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, TrUserData) -> dfp_read_field_def_sdl_register_super(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, TrUserData). +d_field_sdl_register_super_network_code(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, TrUserData) when N < 57 -> + d_field_sdl_register_super_network_code(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, TrUserData); +d_field_sdl_register_super_network_code(<<0:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, _, F@_8, TrUserData) -> + {NewFValue, RestF} = begin Len = X bsl N + Acc, <> = Rest, Bytes2 = binary:copy(Bytes), {id(Bytes2, TrUserData), Rest2} end, + dfp_read_field_def_sdl_register_super(RestF, 0, 0, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, NewFValue, F@_8, TrUserData). -skip_length_delimited_sdl_register_super(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, TrUserData) when N < 57 -> - skip_length_delimited_sdl_register_super(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, TrUserData); -skip_length_delimited_sdl_register_super(<<0:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, TrUserData) -> +d_field_sdl_register_super_hostname(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, TrUserData) when N < 57 -> + d_field_sdl_register_super_hostname(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, TrUserData); +d_field_sdl_register_super_hostname(<<0:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, _, TrUserData) -> + {NewFValue, RestF} = begin Len = X bsl N + Acc, <> = Rest, Bytes2 = binary:copy(Bytes), {id(Bytes2, TrUserData), Rest2} end, + dfp_read_field_def_sdl_register_super(RestF, 0, 0, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, NewFValue, TrUserData). + +skip_varint_sdl_register_super(<<1:1, _:7, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, TrUserData) -> skip_varint_sdl_register_super(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, TrUserData); +skip_varint_sdl_register_super(<<0:1, _:7, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, TrUserData) -> dfp_read_field_def_sdl_register_super(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, TrUserData). + +skip_length_delimited_sdl_register_super(<<1:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, TrUserData) when N < 57 -> + skip_length_delimited_sdl_register_super(Rest, N + 7, X bsl N + Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, TrUserData); +skip_length_delimited_sdl_register_super(<<0:1, X:7, Rest/binary>>, N, Acc, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, TrUserData) -> Length = X bsl N + Acc, <<_:Length/binary, Rest2/binary>> = Rest, - dfp_read_field_def_sdl_register_super(Rest2, 0, 0, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, TrUserData). + dfp_read_field_def_sdl_register_super(Rest2, 0, 0, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, TrUserData). -skip_group_sdl_register_super(Bin, _, Z2, FNum, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, TrUserData) -> +skip_group_sdl_register_super(Bin, _, Z2, FNum, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, TrUserData) -> {_, Rest} = read_group(Bin, FNum), - dfp_read_field_def_sdl_register_super(Rest, 0, Z2, FNum, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, TrUserData). + dfp_read_field_def_sdl_register_super(Rest, 0, Z2, FNum, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, TrUserData). -skip_32_sdl_register_super(<<_:32, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, TrUserData) -> dfp_read_field_def_sdl_register_super(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, TrUserData). +skip_32_sdl_register_super(<<_:32, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, TrUserData) -> dfp_read_field_def_sdl_register_super(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, TrUserData). -skip_64_sdl_register_super(<<_:64, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, TrUserData) -> dfp_read_field_def_sdl_register_super(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, TrUserData). +skip_64_sdl_register_super(<<_:64, Rest/binary>>, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, TrUserData) -> dfp_read_field_def_sdl_register_super(Rest, Z1, Z2, F, F@_1, F@_2, F@_3, F@_4, F@_5, F@_6, F@_7, F@_8, TrUserData). decode_msg_sdl_register_super_ack(Bin, TrUserData) -> dfp_read_field_def_sdl_register_super_ack(Bin, 0, 0, 0, id(undefined, TrUserData), id(<<>>, TrUserData), id(0, TrUserData), id(undefined, TrUserData), id(undefined, TrUserData), TrUserData). @@ -2523,7 +2585,8 @@ merge_msg_sdl_v6_info(#sdl_v6_info{port = PFport, v6 = PFv6}, #sdl_v6_info{port end}. -compile({nowarn_unused_function,merge_msg_sdl_dev_addr/3}). -merge_msg_sdl_dev_addr(#sdl_dev_addr{network_id = PFnetwork_id, mac = PFmac, net_addr = PFnet_addr, net_bit_len = PFnet_bit_len}, #sdl_dev_addr{network_id = NFnetwork_id, mac = NFmac, net_addr = NFnet_addr, net_bit_len = NFnet_bit_len}, _) -> +merge_msg_sdl_dev_addr(#sdl_dev_addr{network_id = PFnetwork_id, mac = PFmac, net_addr = PFnet_addr, net_bit_len = PFnet_bit_len, network_domain = PFnetwork_domain}, + #sdl_dev_addr{network_id = NFnetwork_id, mac = NFmac, net_addr = NFnet_addr, net_bit_len = NFnet_bit_len, network_domain = NFnetwork_domain}, _) -> #sdl_dev_addr{network_id = if NFnetwork_id =:= undefined -> PFnetwork_id; true -> NFnetwork_id @@ -2539,14 +2602,19 @@ merge_msg_sdl_dev_addr(#sdl_dev_addr{network_id = PFnetwork_id, mac = PFmac, net net_bit_len = if NFnet_bit_len =:= undefined -> PFnet_bit_len; true -> NFnet_bit_len + end, + network_domain = + if NFnetwork_domain =:= undefined -> PFnetwork_domain; + true -> NFnetwork_domain end}. -compile({nowarn_unused_function,merge_msg_sdl_empty/3}). merge_msg_sdl_empty(_Prev, New, _TrUserData) -> New. -compile({nowarn_unused_function,merge_msg_sdl_register_super/3}). -merge_msg_sdl_register_super(#sdl_register_super{version = PFversion, installed_channel = PFinstalled_channel, client_id = PFclient_id, dev_addr = PFdev_addr, pub_key = PFpub_key, token = PFtoken}, - #sdl_register_super{version = NFversion, installed_channel = NFinstalled_channel, client_id = NFclient_id, dev_addr = NFdev_addr, pub_key = NFpub_key, token = NFtoken}, TrUserData) -> +merge_msg_sdl_register_super(#sdl_register_super{version = PFversion, installed_channel = PFinstalled_channel, client_id = PFclient_id, dev_addr = PFdev_addr, pub_key = PFpub_key, token = PFtoken, network_code = PFnetwork_code, + hostname = PFhostname}, + #sdl_register_super{version = NFversion, installed_channel = NFinstalled_channel, client_id = NFclient_id, dev_addr = NFdev_addr, pub_key = NFpub_key, token = NFtoken, network_code = NFnetwork_code, hostname = NFhostname}, TrUserData) -> #sdl_register_super{version = if NFversion =:= undefined -> PFversion; true -> NFversion @@ -2571,6 +2639,14 @@ merge_msg_sdl_register_super(#sdl_register_super{version = PFversion, installed_ token = if NFtoken =:= undefined -> PFtoken; true -> NFtoken + end, + network_code = + if NFnetwork_code =:= undefined -> PFnetwork_code; + true -> NFnetwork_code + end, + hostname = + if NFhostname =:= undefined -> PFhostname; + true -> NFhostname end}. -compile({nowarn_unused_function,merge_msg_sdl_register_super_ack/3}). @@ -2916,7 +2992,7 @@ v_submsg_sdl_dev_addr(Msg, Path, TrUserData) -> v_msg_sdl_dev_addr(Msg, Path, Tr -compile({nowarn_unused_function,v_msg_sdl_dev_addr/3}). -dialyzer({nowarn_function,v_msg_sdl_dev_addr/3}). -v_msg_sdl_dev_addr(#sdl_dev_addr{network_id = F1, mac = F2, net_addr = F3, net_bit_len = F4}, Path, TrUserData) -> +v_msg_sdl_dev_addr(#sdl_dev_addr{network_id = F1, mac = F2, net_addr = F3, net_bit_len = F4, network_domain = F5}, Path, TrUserData) -> if F1 == undefined -> ok; true -> v_type_uint32(F1, [network_id | Path], TrUserData) end, @@ -2929,6 +3005,9 @@ v_msg_sdl_dev_addr(#sdl_dev_addr{network_id = F1, mac = F2, net_addr = F3, net_b if F4 == undefined -> ok; true -> v_type_uint32(F4, [net_bit_len | Path], TrUserData) end, + if F5 == undefined -> ok; + true -> v_type_string(F5, [network_domain | Path], TrUserData) + end, ok; v_msg_sdl_dev_addr(X, Path, _TrUserData) -> mk_type_error({expected_msg, sdl_dev_addr}, X, Path). @@ -2939,7 +3018,7 @@ v_msg_sdl_empty(X, Path, _TrUserData) -> mk_type_error({expected_msg, sdl_empty} -compile({nowarn_unused_function,v_msg_sdl_register_super/3}). -dialyzer({nowarn_function,v_msg_sdl_register_super/3}). -v_msg_sdl_register_super(#sdl_register_super{version = F1, installed_channel = F2, client_id = F3, dev_addr = F4, pub_key = F5, token = F6}, Path, TrUserData) -> +v_msg_sdl_register_super(#sdl_register_super{version = F1, installed_channel = F2, client_id = F3, dev_addr = F4, pub_key = F5, token = F6, network_code = F7, hostname = F8}, Path, TrUserData) -> if F1 == undefined -> ok; true -> v_type_uint32(F1, [version | Path], TrUserData) end, @@ -2958,6 +3037,12 @@ v_msg_sdl_register_super(#sdl_register_super{version = F1, installed_channel = F if F6 == undefined -> ok; true -> v_type_string(F6, [token | Path], TrUserData) end, + if F7 == undefined -> ok; + true -> v_type_string(F7, [network_code | Path], TrUserData) + end, + if F8 == undefined -> ok; + true -> v_type_string(F8, [hostname | Path], TrUserData) + end, ok; v_msg_sdl_register_super(X, Path, _TrUserData) -> mk_type_error({expected_msg, sdl_register_super}, X, Path). @@ -3294,7 +3379,8 @@ get_msg_defs() -> [#field{name = network_id, fnum = 1, rnum = 2, type = uint32, occurrence = defaulty, opts = []}, #field{name = mac, fnum = 2, rnum = 3, type = bytes, occurrence = defaulty, opts = []}, #field{name = net_addr, fnum = 3, rnum = 4, type = uint32, occurrence = defaulty, opts = []}, - #field{name = net_bit_len, fnum = 4, rnum = 5, type = uint32, occurrence = defaulty, opts = []}]}, + #field{name = net_bit_len, fnum = 4, rnum = 5, type = uint32, occurrence = defaulty, opts = []}, + #field{name = network_domain, fnum = 5, rnum = 6, type = string, occurrence = defaulty, opts = []}]}, {{msg, sdl_empty}, []}, {{msg, sdl_register_super}, [#field{name = version, fnum = 1, rnum = 2, type = uint32, occurrence = defaulty, opts = []}, @@ -3302,7 +3388,9 @@ get_msg_defs() -> #field{name = client_id, fnum = 3, rnum = 4, type = string, occurrence = defaulty, opts = []}, #field{name = dev_addr, fnum = 4, rnum = 5, type = {msg, sdl_dev_addr}, occurrence = defaulty, opts = []}, #field{name = pub_key, fnum = 5, rnum = 6, type = string, occurrence = defaulty, opts = []}, - #field{name = token, fnum = 6, rnum = 7, type = string, occurrence = defaulty, opts = []}]}, + #field{name = token, fnum = 6, rnum = 7, type = string, occurrence = defaulty, opts = []}, + #field{name = network_code, fnum = 7, rnum = 8, type = string, occurrence = defaulty, opts = []}, + #field{name = hostname, fnum = 8, rnum = 9, type = string, occurrence = defaulty, opts = []}]}, {{msg, sdl_register_super_ack}, [#field{name = dev_addr, fnum = 1, rnum = 2, type = {msg, sdl_dev_addr}, occurrence = defaulty, opts = []}, #field{name = aes_key, fnum = 2, rnum = 3, type = bytes, occurrence = defaulty, opts = []}, @@ -3436,7 +3524,8 @@ find_msg_def(sdl_dev_addr) -> [#field{name = network_id, fnum = 1, rnum = 2, type = uint32, occurrence = defaulty, opts = []}, #field{name = mac, fnum = 2, rnum = 3, type = bytes, occurrence = defaulty, opts = []}, #field{name = net_addr, fnum = 3, rnum = 4, type = uint32, occurrence = defaulty, opts = []}, - #field{name = net_bit_len, fnum = 4, rnum = 5, type = uint32, occurrence = defaulty, opts = []}]; + #field{name = net_bit_len, fnum = 4, rnum = 5, type = uint32, occurrence = defaulty, opts = []}, + #field{name = network_domain, fnum = 5, rnum = 6, type = string, occurrence = defaulty, opts = []}]; find_msg_def(sdl_empty) -> []; find_msg_def(sdl_register_super) -> [#field{name = version, fnum = 1, rnum = 2, type = uint32, occurrence = defaulty, opts = []}, @@ -3444,7 +3533,9 @@ find_msg_def(sdl_register_super) -> #field{name = client_id, fnum = 3, rnum = 4, type = string, occurrence = defaulty, opts = []}, #field{name = dev_addr, fnum = 4, rnum = 5, type = {msg, sdl_dev_addr}, occurrence = defaulty, opts = []}, #field{name = pub_key, fnum = 5, rnum = 6, type = string, occurrence = defaulty, opts = []}, - #field{name = token, fnum = 6, rnum = 7, type = string, occurrence = defaulty, opts = []}]; + #field{name = token, fnum = 6, rnum = 7, type = string, occurrence = defaulty, opts = []}, + #field{name = network_code, fnum = 7, rnum = 8, type = string, occurrence = defaulty, opts = []}, + #field{name = hostname, fnum = 8, rnum = 9, type = string, occurrence = defaulty, opts = []}]; find_msg_def(sdl_register_super_ack) -> [#field{name = dev_addr, fnum = 1, rnum = 2, type = {msg, sdl_dev_addr}, occurrence = defaulty, opts = []}, #field{name = aes_key, fnum = 2, rnum = 3, type = bytes, occurrence = defaulty, opts = []}, diff --git a/apps/sdlan/src/sdlan_stun.erl b/apps/sdlan/src/sdlan_stun.erl index 16cc9ee..f45da2d 100644 --- a/apps/sdlan/src/sdlan_stun.erl +++ b/apps/sdlan/src/sdlan_stun.erl @@ -103,7 +103,7 @@ handle_info({udp, Sock, Ip, Port, <>}, Stat case sdlan_network:get_pid(NetworkId) of undefined -> - lager:debug("call me here stun request 11: ~p", [NetworkId]), + lager:debug("[sdlan_stun] stun_request network_id: ~p, client_id: ~p, not found", [NetworkId, ClientId]), {noreply, State}; NetworkPid when is_pid(NetworkPid) -> sdlan_network:update_hole(NetworkPid, ClientId, Mac, {Ip, Port}, NatType, V6Info), @@ -111,7 +111,7 @@ handle_info({udp, Sock, Ip, Port, <>}, Stat cookie = Cookie }), ok = gen_udp:send(Sock, Ip, Port, <>), - lager:debug("call me here stun request 12"), + lager:debug("[sdlan_stun] stun_request network_id: ~p, client_id: ~p, hole: ~p", [NetworkId, ClientId, {Ip, Port}]), {noreply, State} end; diff --git a/apps/sdlan/src/sdlan_sup.erl b/apps/sdlan/src/sdlan_sup.erl index fad7687..1361b3e 100644 --- a/apps/sdlan/src/sdlan_sup.erl +++ b/apps/sdlan/src/sdlan_sup.erl @@ -29,6 +29,14 @@ init([]) -> SupFlags = #{strategy => one_for_one, intensity => 1000, period => 3600}, Specs = [ + #{ + id => dns_proxy_sup, + start => {dns_proxy_sup, start_link, []}, + restart => permanent, + shutdown => 2000, + type => supervisor, + modules => ['dns_proxy_sup'] + }, #{ id => sdlan_network_coordinator, start => {sdlan_network_coordinator, start_link, []}, diff --git a/config/sys-dev.config b/config/sys-dev.config index e29ade5..d6cee1f 100644 --- a/config/sys-dev.config +++ b/config/sys-dev.config @@ -23,6 +23,12 @@ % {stun_servers, [{'sdlan_stun:2:1', 1265}, {'sdlan_stun:2:2', 1266}]}, + %% 公共的dns域名解析服务 + {public_dns_servers, [ + {{114, 114, 114, 114}, 53}, + {{8,8,8,8}, 53} + ]}, + {pools, [ %% mysql连接池配置 {mysql_sdlan, @@ -37,6 +43,11 @@ {database, "sdlan"}, {queries, [<<"set names utf8">>]} ] + }, + + {dns_resolver_pool, + [{size, 20}, {max_overflow, 100}, {worker_module, dns_resolver}], + [] } ]}, diff --git a/config/sys-prod.config b/config/sys-prod.config index eb26687..c798636 100644 --- a/config/sys-prod.config +++ b/config/sys-prod.config @@ -23,6 +23,12 @@ % {stun_servers, [{'sdlan_stun:2:1', 1265}, {'sdlan_stun:2:2', 1266}]}, + %% 公共的dns域名解析服务 + {public_dns_servers, [ + {{114, 114, 114, 114}, 53}, + {{8,8,8,8}, 53} + ]}, + {pools, [ %% mysql连接池配置 {mysql_sdlan, @@ -37,7 +43,13 @@ {database, "sdlan"}, {queries, [<<"set names utf8">>]} ] + }, + + {dns_resolver_pool, + [{size, 20}, {max_overflow, 100}, {worker_module, dns_resolver}], + [] } + ]}, {api_url, "https://punchnet.aioe.tech/api/"} diff --git a/message.proto b/message.proto index ddc66e6..96eb93c 100644 --- a/message.proto +++ b/message.proto @@ -19,6 +19,7 @@ message SDLDevAddr { bytes mac = 2; uint32 net_addr = 3; uint32 net_bit_len = 4; + string network_domain = 5; } // tcp通讯消息 @@ -33,6 +34,8 @@ message SDLRegisterSuper { SDLDevAddr dev_addr = 4; string pub_key = 5; string token = 6; + string network_code = 7; + string hostname = 8; } message SDLRegisterSuperAck { diff --git a/rebar.config b/rebar.config index 3c9e869..19b784d 100644 --- a/rebar.config +++ b/rebar.config @@ -2,13 +2,14 @@ {deps, [ {poolboy, ".*", {git, "https://github.com/devinus/poolboy.git", {tag, "1.5.1"}}}, {hackney, ".*", {git, "https://github.com/benoitc/hackney.git", {tag, "1.16.0"}}}, - {sync, ".*", {git, "https://github.com/rustyio/sync.git", {branch, "master"}}}, - {esockd, ".*", {git, "https://github.com/emqx/esockd.git", {tag, "v5.7.3"}}}, {jiffy, ".*", {git, "https://github.com/davisp/jiffy.git", {tag, "1.1.1"}}}, {cowboy, ".*", {git, "https://github.com/ninenines/cowboy.git", {tag, "2.12.0"}}}, {mysql, ".*", {git, "https://github.com/mysql-otp/mysql-otp", {tag, "1.8.0"}}}, {gpb, ".*", {git, "https://github.com/tomas-abrahamsson/gpb.git", {tag, "4.21.1"}}}, {throttle, ".*", {git, "https://github.com/lambdaclass/throttle.git", {tag, "0.3.0"}}}, + {dns_erlang, ".*", {git, "https://github.com/dnsimple/dns_erlang.git", {tag, "v4.4.0"}}}, + {pkt, ".*", {git, "https://github.com/msantos/pkt.git", {tag, "0.6.0"}}}, + {sync, ".*", {git, "https://github.com/rustyio/sync.git", {branch, "master"}}}, {parse_trans, ".*", {git, "https://github.com/uwiger/parse_trans", {tag, "3.0.0"}}}, {lager, ".*", {git,"https://github.com/erlang-lager/lager.git", {tag, "3.9.2"}}} ]}. diff --git a/rebar.lock b/rebar.lock index 7566f8a..6fb10ed 100644 --- a/rebar.lock +++ b/rebar.lock @@ -1,5 +1,6 @@ {"1.2.0", -[{<<"certifi">>,{pkg,<<"certifi">>,<<"2.5.2">>},1}, +[{<<"base32">>,{pkg,<<"base32">>,<<"1.0.0">>},2}, + {<<"certifi">>,{pkg,<<"certifi">>,<<"2.5.2">>},1}, {<<"cowboy">>, {git,"https://github.com/ninenines/cowboy.git", {ref,"3ea8395eb8f53a57acb5d3c00b99c70296e7cdbd"}}, @@ -8,9 +9,13 @@ {git,"https://github.com/ninenines/cowlib", {ref,"1eb7f4293a652adcfe43b1835d22c58d8def839f"}}, 1}, - {<<"esockd">>, - {git,"https://github.com/emqx/esockd.git", - {ref,"d9ce4024cc42a65e9a05001997031e743442f955"}}, + {<<"dns_erlang">>, + {git,"https://github.com/dnsimple/dns_erlang.git", + {ref,"e1149a2dd6f49c6560aa245bc6f3d40a5cbe70e1"}}, + 1}, + {<<"dns_proxy">>, + {git,"https://gitea.s5s8.com/anlicheng/dns_proxy.git", + {ref,"5ed832359e42ec99d148bf2ada1729b540017ab8"}}, 0}, {<<"fs">>,{pkg,<<"fs">>,<<"6.1.1">>},1}, {<<"goldrush">>,{pkg,<<"goldrush">>,<<"0.1.9">>},1}, @@ -41,6 +46,10 @@ {git,"https://github.com/uwiger/parse_trans", {ref,"6f3645afb43c7c57d61b54ef59aecab288ce1013"}}, 0}, + {<<"pkt">>, + {git,"https://github.com/msantos/pkt.git", + {ref,"67a4a14f596fded5ad5f2d8f94318faa8ad2c288"}}, + 1}, {<<"poolboy">>, {git,"https://github.com/devinus/poolboy.git", {ref,"3bb48a893ff5598f7c73731ac17545206d259fac"}}, @@ -52,7 +61,7 @@ {<<"ssl_verify_fun">>,{pkg,<<"ssl_verify_fun">>,<<"1.1.6">>},1}, {<<"sync">>, {git,"https://github.com/rustyio/sync.git", - {ref,"7dc303ed4ce8d26db82e171dbbd7c41067852c65"}}, + {ref,"4e909f69d3d0db21a6d7128b20748819e415c9eb"}}, 0}, {<<"throttle">>, {git,"https://github.com/lambdaclass/throttle.git", @@ -61,6 +70,7 @@ {<<"unicode_util_compat">>,{pkg,<<"unicode_util_compat">>,<<"0.5.0">>},2}]}. [ {pkg_hash,[ + {<<"base32">>, <<"1AB331F812FCC254C8F7D4348E1E5A6F2B9B32B7A260BF2BC3358E3BF14C841A">>}, {<<"certifi">>, <<"B7CFEAE9D2ED395695DD8201C57A2D019C0C43ECAF8B8BCB9320B40D6662F340">>}, {<<"fs">>, <<"9D147B944D60CFA48A349F12D06C8EE71128F610C90870BDF9A6773206452ED0">>}, {<<"goldrush">>, <<"F06E5D5F1277DA5C413E84D5A2924174182FB108DABB39D5EC548B27424CD106">>}, @@ -70,6 +80,7 @@ {<<"ssl_verify_fun">>, <<"CF344F5692C82D2CD7554F5EC8FD961548D4FD09E7D22F5B62482E5AEAEBD4B0">>}, {<<"unicode_util_compat">>, <<"8516502659002CEC19E244EBD90D312183064BE95025A319A6C7E89F4BCCD65B">>}]}, {pkg_hash_ext,[ + {<<"base32">>, <<"0449285348ED0C4CD83C7198E76C5FD5A0451C4EF18695B9FD43792A503E551A">>}, {<<"certifi">>, <<"3B3B5F36493004AC3455966991EAF6E768CE9884693D9968055AEEEB1E575040">>}, {<<"fs">>, <<"EF94E95FFE79916860649FED80AC62B04C322B0BB70F5128144C026B4D171F8B">>}, {<<"goldrush">>, <<"99CB4128CFFCB3227581E5D4D803D5413FA643F4EB96523F77D9E6937D994CEB">>},