fix message

This commit is contained in:
anlicheng 2026-01-26 21:42:07 +08:00
parent 8bdc5868c3
commit 388096a29a
9 changed files with 841 additions and 420 deletions

View File

@ -28,7 +28,7 @@
-ifndef('SDL_REGISTER_SUPER_PB_H').
-define('SDL_REGISTER_SUPER_PB_H', true).
-record(sdl_register_super,
{version = 0 :: non_neg_integer() | undefined, % = 1, optional, 32 bits
{pkt_id = 0 :: non_neg_integer() | undefined, % = 1, optional, 32 bits
client_id = <<>> :: unicode:chardata() | undefined, % = 2, optional
network_id = 0 :: non_neg_integer() | undefined, % = 3, optional, 32 bits
mac = <<>> :: iodata() | undefined, % = 4, optional
@ -43,36 +43,49 @@
-ifndef('SDL_REGISTER_SUPER_ACK_PB_H').
-define('SDL_REGISTER_SUPER_ACK_PB_H', true).
-record(sdl_register_super_ack,
{aes_key = <<>> :: iodata() | undefined, % = 1, optional
session_token = <<>> :: iodata() | undefined % = 2, optional
{pkt_id = 0 :: non_neg_integer() | undefined, % = 1, optional, 32 bits
aes_key = <<>> :: iodata() | undefined, % = 2, optional
session_token = <<>> :: iodata() | undefined % = 3, optional
}).
-endif.
-ifndef('SDL_REGISTER_SUPER_NAK_PB_H').
-define('SDL_REGISTER_SUPER_NAK_PB_H', true).
-record(sdl_register_super_nak,
{error_code = 0 :: non_neg_integer() | undefined, % = 1, optional, 32 bits
error_message = <<>> :: unicode:chardata() | undefined % = 2, optional
{pkt_id = 0 :: non_neg_integer() | undefined, % = 1, optional, 32 bits
error_code = 0 :: non_neg_integer() | undefined, % = 2, optional, 32 bits
error_message = <<>> :: unicode:chardata() | undefined % = 3, optional
}).
-endif.
-ifndef('SDL_QUERY_INFO_PB_H').
-define('SDL_QUERY_INFO_PB_H', true).
-record(sdl_query_info,
{network_id = 0 :: non_neg_integer() | undefined, % = 1, optional, 32 bits
src_mac = <<>> :: iodata() | undefined, % = 2, optional
dst_mac = <<>> :: iodata() | undefined, % = 3, optional
session_token = <<>> :: iodata() | undefined % = 4, optional
{pkt_id = 0 :: non_neg_integer() | undefined, % = 1, optional, 32 bits
network_id = 0 :: non_neg_integer() | undefined, % = 2, optional, 32 bits
src_mac = <<>> :: iodata() | undefined, % = 3, optional
dst_mac = <<>> :: iodata() | undefined, % = 4, optional
session_token = <<>> :: iodata() | undefined % = 5, optional
}).
-endif.
-ifndef('SDL_PEER_INFO_PB_H').
-define('SDL_PEER_INFO_PB_H', true).
-record(sdl_peer_info,
{network_id = 0 :: non_neg_integer() | undefined, % = 1, optional, 32 bits
dst_mac = <<>> :: iodata() | undefined, % = 2, optional
v4_info = undefined :: sdlan_pb:sdl_v4_info() | undefined, % = 3, optional
v6_info :: sdlan_pb:sdl_v6_info() | undefined % = 4, optional
{pkt_id = 0 :: non_neg_integer() | undefined, % = 1, optional, 32 bits
network_id = 0 :: non_neg_integer() | undefined, % = 2, optional, 32 bits
dst_mac = <<>> :: iodata() | undefined, % = 3, optional
v4_info = undefined :: sdlan_pb:sdl_v4_info() | undefined, % = 4, optional
v6_info :: sdlan_pb:sdl_v6_info() | undefined % = 5, optional
}).
-endif.
-ifndef('SDL_EMPTY_PEER_INFO_PB_H').
-define('SDL_EMPTY_PEER_INFO_PB_H', true).
-record(sdl_empty_peer_info,
{pkt_id = 0 :: non_neg_integer() | undefined, % = 1, optional, 32 bits
network_id = 0 :: non_neg_integer() | undefined, % = 2, optional, 32 bits
dst_mac = <<>> :: iodata() | undefined % = 3, optional
}).
-endif.
@ -133,6 +146,15 @@
}).
-endif.
-ifndef('SDL_STUN_REPLY_PB_H').
-define('SDL_STUN_REPLY_PB_H', true).
-record(sdl_stun_reply,
{network_id = 0 :: non_neg_integer() | undefined, % = 1, optional, 32 bits
code = 0 :: non_neg_integer() | undefined, % = 2, optional, 32 bits
message = <<>> :: unicode:chardata() | undefined % = 3, optional
}).
-endif.
-ifndef('SDL_DATA_PB_H').
-define('SDL_DATA_PB_H', true).
-record(sdl_data,

View File

@ -8,19 +8,12 @@
%%%-------------------------------------------------------------------
-module(sdlan_cipher).
-author("anlicheng").
-include_lib("public_key/include/public_key.hrl").
%% API
-export([rsa_encrypt/2, rsa_pem_decode/1]).
-export([rsa_encrypt/2, rsa_pem_decode/1, rsa_decrypt/2]).
-export([aes_encrypt/3, aes_decrypt/3]).
-export([test/0]).
test() ->
Key = <<"abcdabcdabcdabcd">>,
X = aes_encrypt(Key, Key, <<"hello world">>),
logger:debug("x is: ~p, raw: ~p", [X, aes_decrypt(Key, Key, X)]),
ok.
-export([rsa_generate_key/0]).
-spec rsa_pem_decode(PubKey :: binary()) -> public_key:rsa_public_key().
rsa_pem_decode(PubKey) when is_binary(PubKey) ->
@ -32,6 +25,23 @@ rsa_pem_decode(PubKey) when is_binary(PubKey) ->
rsa_encrypt(BinData, PublicKey) when is_binary(BinData) ->
public_key:encrypt_public(BinData, PublicKey, [{rsa_padding, rsa_pkcs1_padding}]).
-spec rsa_decrypt(EncData :: binary(), PrivateKey :: public_key:rsa_private_key()) -> binary().
rsa_decrypt(EncData, PrivateKey) when is_binary(EncData) ->
public_key:decrypt_private(EncData, PrivateKey, [{rsa_padding, rsa_pkcs1_padding}]).
rsa_generate_key() ->
PrivateKey = public_key:generate_key({rsa, 2048, 65537}),
PublicKey = #'RSAPublicKey'{
modulus = PrivateKey#'RSAPrivateKey'.modulus,
publicExponent = PrivateKey#'RSAPrivateKey'.publicExponent
},
PemBin = public_key:pem_encode([
public_key:pem_entry_encode('RSAPublicKey', PublicKey)
]),
PK = binary_to_list(PemBin),
{PK, PrivateKey}.
%% aes的加密算法
-spec aes_encrypt(binary(), binary(), binary()) -> binary().
aes_encrypt(Key, IVec, PlainText) when is_binary(Key), is_binary(IVec), is_binary(PlainText) ->
@ -40,4 +50,5 @@ aes_encrypt(Key, IVec, PlainText) when is_binary(Key), is_binary(IVec), is_binar
%% aes的解密算法
-spec aes_decrypt(binary(), binary(), binary()) -> binary().
aes_decrypt(Key, IVec, CipherText) when is_binary(Key), is_binary(IVec), is_binary(CipherText) ->
crypto:crypto_one_time(aes_128_ofb, Key, IVec, CipherText, [{encrypt, false}, {padding, pkcs_padding}]).
crypto:crypto_one_time(aes_128_ofb, Key, IVec, CipherText, [{encrypt, false}, {padding, pkcs_padding}]).

View File

@ -24,7 +24,7 @@
%% API
-export([start_link/2]).
-export([get_name/1, get_pid/1, lookup_pid/1, attach/6, peer_info/5, unregister/3, debug_info/1, get_network_id/1, arp_query/2]).
-export([get_name/1, get_pid/1, lookup_pid/1, attach/6, peer_info/4, unregister/3, debug_info/1, get_network_id/1, arp_query/2]).
-export([forward/5, stun_request/4, disable_client/2, dropout_client/2]).
-export([test_event/1]).
@ -107,9 +107,9 @@ arp_query(Pid, TargetIp) when is_pid(Pid), is_integer(TargetIp) ->
unregister(Pid, ClientId, Mac) when is_pid(Pid), is_binary(ClientId), is_binary(Mac) ->
gen_server:cast(Pid, {unregister, ClientId, Mac}).
-spec peer_info(Pid :: pid(), Sock :: inet:socket(), Peer :: {inet:ip4_address(), integer()}, PacketId :: integer(), Query :: #sdl_query_info{}) -> no_return().
peer_info(Pid, Sock, ClientPeer, PacketId, Query) when is_pid(Pid) ->
gen_server:cast(Pid, {peer_info, Sock, ClientPeer, PacketId, Query}).
-spec peer_info(Pid :: pid(), Sock :: inet:socket(), Peer :: {inet:ip4_address(), integer()}, Query :: #sdl_query_info{}) -> no_return().
peer_info(Pid, Sock, ClientPeer, Query) when is_pid(Pid) ->
gen_server:cast(Pid, {peer_info, Sock, ClientPeer, Query}).
-spec forward(pid(), Sock :: any(), SrcMac :: binary(), DstMac :: binary(), Packet :: binary()) -> no_return().
forward(Pid, Sock, SrcMac, DstMac, Packet) when is_pid(Pid), is_binary(SrcMac), is_binary(DstMac), is_binary(Packet) ->
@ -253,13 +253,17 @@ handle_call(debug_info, _From, State = #state{network_id = NetworkId, ipaddr = I
%% nat_peer信息
%% TODO SrcMac不存在的时候需要重新校验
handle_cast({peer_info, Sock, {ClientIp, ClientPort}, PacketId, #sdl_query_info{src_mac = SrcMac, dst_mac = DstMac}}, State = #state{endpoints = Endpoints}) ->
handle_cast({peer_info, Sock, {ClientIp, ClientPort}, #sdl_query_info{pkt_id = PktId, src_mac = SrcMac, dst_mac = DstMac}},
State = #state{network_id = NetworkId, endpoints = Endpoints}) ->
case maps:find(DstMac, Endpoints) of
{ok, #endpoint{hole = #hole{peer = DstNatPeer = {{Ip0, Ip1, Ip2, Ip3}, DstNatPort}, nat_type = DstNatType}, v6_info = DstV6Info}} ->
%% sendRegister事件(2024-06-25 )
maybe_preload_hole(DstNatPeer, maps:get(SrcMac, Endpoints, undefined)),
PeerInfo = sdlan_pb:encode_msg(#sdl_peer_info{
pkt_id = PktId,
network_id = NetworkId,
dst_mac = DstMac,
v4_info = #sdl_v4_info {
port = DstNatPort,
@ -268,10 +272,15 @@ handle_cast({peer_info, Sock, {ClientIp, ClientPort}, PacketId, #sdl_query_info{
},
v6_info = DstV6Info
}),
PeerPacket = <<?PACKET_PEER_INFO, PacketId:32, PeerInfo/binary>>,
PeerPacket = <<?PACKET_PEER_INFO, PeerInfo/binary>>,
gen_udp:send(Sock, ClientIp, ClientPort, PeerPacket);
_ ->
EmptyPeerPacket = <<?PACKET_PEER_INFO, PacketId:32>>,
EmptyPeerInfo = sdlan_pb:encode_msg(#sdl_empty_peer_info{
pkt_id = PktId,
network_id = NetworkId,
dst_mac = DstMac
}),
EmptyPeerPacket = <<?PACKET_PEER_INFO, EmptyPeerInfo/binary>>,
gen_udp:send(Sock, ClientIp, ClientPort, EmptyPeerPacket)
end,
{noreply, State};

File diff suppressed because it is too large Load Diff

View File

@ -27,22 +27,13 @@
%% API
-export([start_link/4, do_register/4]).
-spec start_link(Sock :: inet:socket(), Ip :: inet:ip4_address(), Port :: integer(), Packet :: binary()) -> {ok, pid()}.
-spec start_link(Sock :: inet:socket(), Ip :: inet:ip4_address(), Port :: integer(), Packet :: #sdl_register_super{}) -> {ok, pid()}.
start_link(Sock, Ip, Port, Packet) ->
{ok, erlang:spawn_link(?MODULE, do_register, [Sock, Ip, Port, Packet])}.
do_register(Sock, SrcIp, SrcPort, <<PacketId:32, Body/binary>>) ->
#sdl_register_super{
version = _Version,
client_id = ClientId,
network_id = NetworkId,
mac = Mac,
ip = Ip,
mask_len = MaskLen,
hostname = HostName,
pub_key = PubKey,
access_token = AccessToken
} = sdlan_pb:decode_msg(Body, sdl_register_super),
do_register(Sock, SrcIp, SrcPort, #sdl_register_super{
pkt_id = PktId, client_id = ClientId, network_id = NetworkId, mac = Mac, ip = Ip, mask_len = MaskLen,
hostname = HostName, pub_key = PubKey, access_token = AccessToken}) ->
%%
logger:debug("[sdlan_channel] client_id: ~p, ip: ~p, mac: ~p, host_name: ~p, access_token: ~p, network_id: ~p",
@ -73,12 +64,13 @@ do_register(Sock, SrcIp, SrcPort, <<PacketId:32, Body/binary>>) ->
EncodedAesKey = rsa_encode(AesKey, RsaPubKey),
RegisterSuperAck = sdlan_pb:encode_msg(#sdl_register_super_ack {
pkt_id = PktId,
aes_key = EncodedAesKey,
session_token = SessionToken
}),
%%
Reply = <<?PACKET_REGISTER_SUPER_ACK, PacketId:32, RegisterSuperAck/binary>>,
Reply = <<?PACKET_REGISTER_SUPER_ACK, RegisterSuperAck/binary>>,
gen_udp:send(Sock, SrcIp, SrcPort, Reply),
%% 线
@ -86,34 +78,35 @@ do_register(Sock, SrcIp, SrcPort, <<PacketId:32, Body/binary>>) ->
logger:debug("[sdlan_channel] client_id: ~p, set none online result is: ~p", [ClientId, Result]);
{error, no_ip} ->
logger:warning("[sdlan_channel] client_id: ~p, register get error: no_ip", [ClientId]),
gen_udp:send(Sock, SrcIp, SrcPort, register_nak_reply(PacketId, ?NAK_NO_IP, <<"No Ip address">>));
gen_udp:send(Sock, SrcIp, SrcPort, register_nak_reply(PktId, ?NAK_NO_IP, <<"No Ip address">>));
{error, host_name_used} ->
logger:warning("[sdlan_channel] client_id: ~p, register get error: host_name_used", [ClientId]),
gen_udp:send(Sock, SrcIp, SrcPort, register_nak_reply(PacketId, ?NAK_HOSTNAME_USED, <<"Host Name Used">>));
gen_udp:send(Sock, SrcIp, SrcPort, register_nak_reply(PktId, ?NAK_HOSTNAME_USED, <<"Host Name Used">>));
{error, client_disabled} ->
logger:warning("[sdlan_channel] client_id: ~p, register get error: client_disabled", [ClientId]),
gen_udp:send(Sock, SrcIp, SrcPort, register_nak_reply(PacketId, ?NAK_NODE_DISABLE, <<"Client Connection Disable">>))
gen_udp:send(Sock, SrcIp, SrcPort, register_nak_reply(PktId, ?NAK_NODE_DISABLE, <<"Client Connection Disable">>))
end;
undefined ->
logger:warning("[sdlan_channel] client_id: ~p, register get error: network not found", [ClientId]),
gen_udp:send(Sock, SrcIp, SrcPort, register_nak_reply(PacketId, ?NAK_INTERNAL_FAULT, <<"Internal Error">>))
gen_udp:send(Sock, SrcIp, SrcPort, register_nak_reply(PktId, ?NAK_INTERNAL_FAULT, <<"Internal Error">>))
end;
{ok, #{<<"error">> := #{<<"code">> := Code, <<"message">> := Message}}} ->
logger:warning("[sdlan_channel] network_id: ~p, client_id: ~p, register get error: ~ts, error_code: ~p", [NetworkId, ClientId, Message, Code]),
gen_udp:send(Sock, SrcIp, SrcPort, register_nak_reply(PacketId, Code, Message));
gen_udp:send(Sock, SrcIp, SrcPort, register_nak_reply(PktId, Code, Message));
{error, Reason} ->
logger:warning("[sdlan_channel] network_id: ~p, client_id: ~p, register get error: ~p", [NetworkId, ClientId, Reason]),
gen_udp:send(Sock, SrcIp, SrcPort, register_nak_reply(PacketId, ?NAK_NETWORK_FAULT, <<"Network Error">>))
gen_udp:send(Sock, SrcIp, SrcPort, register_nak_reply(PktId, ?NAK_NETWORK_FAULT, <<"Network Error">>))
end,
exit(normal).
-spec register_nak_reply(PacketId :: integer(), ErrorCode :: integer(), ErrorMsg :: binary()) -> binary().
register_nak_reply(PacketId, ErrorCode, ErrorMsg) when is_integer(PacketId), is_integer(ErrorCode), is_binary(ErrorMsg) ->
RegisterNakReply = sdlan_pb:encode_msg(#sdl_register_super_nak {
pkt_id = PacketId,
error_code = ErrorCode,
error_message = ErrorMsg
}),
<<?PACKET_REGISTER_SUPER_NAK, PacketId:32, RegisterNakReply/binary>>.
<<?PACKET_REGISTER_SUPER_NAK, RegisterNakReply/binary>>.
-spec rsa_encode(PlainText :: binary(), RsaPubKey :: public_key:rsa_public_key()) -> binary().
rsa_encode(PlainText, RsaPubKey) when is_binary(PlainText) ->

View File

@ -8,6 +8,7 @@
%%%-------------------------------------------------------------------
-module(sdlan_register_worker_sup).
-author("anlicheng").
-include("sdlan_pb.hrl").
-behaviour(supervisor).
@ -59,7 +60,7 @@ init([]) ->
%%% Internal functions
%%%===================================================================
-spec start_worker(Sock :: inet:socket(), Ip :: inet:ip4_address(), Port :: integer(), Packet :: binary()) -> supervisor:startchild_ret().
-spec start_worker(Sock :: inet:socket(), Ip :: inet:ip4_address(), Port :: integer(), Packet :: #sdl_register_super{}) -> supervisor:startchild_ret().
start_worker(Sock, Ip, Port, Packet) ->
%% Start a temporary worker under the supervisor
supervisor:start_child(?SERVER, [Sock, Ip, Port, Packet]).

View File

@ -117,16 +117,20 @@ code_change(_OldVsn, State = #state{}, _Extra) ->
-spec handle_packet(Sock :: inet:socket(), Ip :: inet:ip4_address(), Port :: integer(), Packet :: binary()) -> no_return().
%% token或者网络id来注册
handle_packet(Sock, Ip, Port, <<?PACKET_REGISTER_SUPER, Body/binary>>) ->
sdlan_register_worker_sup:start_worker(Sock, Ip, Port, Body);
maybe
Register = catch sdlan_pb:decode_msg(Body, sdl_register_super),
#sdl_register_super{} ?= Register,
sdlan_register_worker_sup:start_worker(Sock, Ip, Port, Register)
end;
%%
handle_packet(Sock, ClientIp, ClientPort, <<?PACKET_QUERY_INFO, PacketId:32, Body/binary>>) ->
handle_packet(Sock, ClientIp, ClientPort, <<?PACKET_QUERY_INFO, Body/binary>>) ->
maybe
Query = catch sdlan_pb:decode_msg(Body, sdl_query_info),
#sdl_query_info{network_id = NetworkId} ?= Query,
{ok, NetworkPid} ?= sdlan_network:lookup_pid(NetworkId),
sdlan_network:peer_info(NetworkPid, Sock, {ClientIp, ClientPort}, PacketId, Query)
sdlan_network:peer_info(NetworkPid, Sock, {ClientIp, ClientPort}, Query)
end;
%%

View File

@ -9,12 +9,14 @@
-module(stun_client).
-author("anlicheng").
-include("sdlan_pb.hrl").
-include("sdlan.hrl").
-behaviour(gen_server).
%% API
-export([start_link/0]).
-export([register/1, debug_info/1]).
-export([test/0]).
%% gen_server callbacks
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2,
@ -25,19 +27,25 @@
-define(STUN_REGISTER, 3).
%%
-define(STUN_REGISTER_ACK, 4).
-define(STUN_DATA, 5).
-define(SUPER_HOST, "127.0.0.1").
-define(SUPER_PORT, 1265).
-record(state, {
socket,
tun_socket,
client_id :: binary(),
mac :: binary(),
network_id,
net_addr,
ip,
mask_len,
aes_key,
cookie = 1,
session_token :: binary(),
private_key,
sessions = #{}
}).
@ -45,6 +53,11 @@
%%% API
%%%===================================================================
test() ->
{ok, Pid} = start_link(),
register(Pid),
ok.
register(Pid) when is_pid(Pid) ->
gen_server:call(Pid, register).
@ -67,11 +80,8 @@ start_link() ->
{ok, State :: #state{}} | {ok, State :: #state{}, timeout() | hibernate} |
{stop, Reason :: term()} | ignore).
init([]) ->
{ok, Socket} = gen_tcp:connect("localhost", 18083, [binary, {packet, 2}, {active, true}]),
inet_tcp:controlling_process(Socket, self()),
{ok, TunSocket} = gen_udp:open(12345, [binary, {active, true}]),
{ok, #state{socket = Socket, tun_socket = TunSocket, client_id = <<"22222222222222222222222222222222">>}}.
{ok, TunSocket} = gen_udp:open(0, [binary, {active, true}]),
{ok, #state{tun_socket = TunSocket, network_id = 8, mac = <<11, 12, 13, 14, 15, 16>>, ip = x, mask_len = 24, client_id = <<"22222222222222222222222222222222">>}}.
%% @private
%% @doc Handling call messages
@ -86,35 +96,26 @@ init([]) ->
handle_call(debug_info, _From, State) ->
{reply, {ok, State}, State};
handle_call(register, _From, State = #state{socket = Socket, client_id = ClientId}) ->
Req = #{
<<"version">> => 1,
<<"client_id">> => ClientId,
<<"dev_addr">> => #{
<<"net_addr">> => 0,
<<"net_bit_len">> => 0
},
<<"token">> => <<"1234567890">>
},
handle_call(register, _From, State = #state{tun_socket = Socket, network_id = NId, client_id = ClientId, ip = Ip, mac = Mac, mask_len = MaskLen}) ->
{PublicKeyBin, PrivateKey} = sdlan_cipher:rsa_generate_key(),
Register = #sdl_register_super {
version = 0,
pkt_id = 1,
client_id = ClientId,
network_id = 8,
mac = <<11, 12, 13, 14, 15, 16>>,
ip = 0,
mask_len = 0,
network_id = NId,
mac = Mac,
ip = Ip,
mask_len = MaskLen,
hostname = <<"mysql1">>,
pub_key = <<>>,
pub_key = PublicKeyBin,
access_token = <<"access_token1234">>
},
logger:debug("register is: ~p", [Register]),
Packet = jiffy:encode(Req, [force_utf8]),
ok = gen_tcp:send(Socket, <<1:32, 101, Packet/binary>>),
Pkt = sdlan_pb:encode_msg(Register),
ok = gen_udp:send(Socket, ?SUPER_HOST, ?SUPER_PORT, <<?PACKET_REGISTER_SUPER, Pkt/binary>>),
{reply, ok, State}.
{reply, ok, State#state{private_key = PrivateKey}}.
%% @private
%% @doc Handling cast messages
@ -131,56 +132,33 @@ handle_cast(_Request, State = #state{}) ->
{noreply, NewState :: #state{}} |
{noreply, NewState :: #state{}, timeout() | hibernate} |
{stop, Reason :: term(), NewState :: #state{}}).
handle_info({tcp, Socket, <<1:32, 5, Data/binary>>}, State = #state{socket = Socket, tun_socket = TunSocket, client_id = ClientId, cookie = Cookie}) ->
Response = jiffy:decode(Data, [return_maps]),
#{
<<"dev_addr">> := #{
<<"network_id">> := NetworkId,
<<"net_addr">> := NetAddr,
<<"net_bit_len">> := NetBitLen
},
<<"aes_key">> := AesKey,
<<"lifetime">> := Lifetime
} = Response,
handle_info({udp, _Socket, _ServerIp, _ServerPort, <<?PACKET_REGISTER_SUPER_ACK, Data/binary>>}, State = #state{private_key = PrivateKey}) ->
SuperAck = #sdl_register_super_ack{session_token = SessionToken, aes_key = EncAesKey} = sdlan_pb:decode_msg(Data, sdl_register_super_ack),
logger:debug("[stun_client] get a register super response: ~p, alloc ip addr: ~p", [Response, sdlan_ipaddr:int_to_ipv4(NetAddr)]),
AesKey = sdlan_cipher:rsa_decrypt(EncAesKey, PrivateKey),
logger:debug("[stun_client] get a register super ack: ~p, aes_key: ~p", [SuperAck, AesKey]),
%% tun信息
gen_udp:send(TunSocket, "localhost", 1265, <<1, Cookie:32, ClientId/binary, NetworkId:32, NetAddr:32>>),
erlang:start_timer(5000, self(), stun_request_ticker),
{noreply, State#state{network_id = NetworkId, net_addr = NetAddr, mask_len = NetBitLen, aes_key = AesKey, cookie = Cookie + 1}};
{noreply, State#state{session_token = SessionToken}};
handle_info({udp, _, _, _, <<2, Cookie:32, Family, Port:16, Ip0, Ip1, Ip2, Ip3>>}, State = #state{}) ->
logger:debug("[stun_client] tun register ack, cookie: ~p, ack: ~p", [Cookie, {Family, Port, {Ip0, Ip1, Ip2, Ip3}}]),
{noreply, State};
handle_info({udp, _Socket, _ServerIp, _ServerPort, <<?PACKET_REGISTER_SUPER_NAK, Data/binary>>}, State) ->
SuperNak = #sdl_register_super_nak{} = sdlan_pb:decode_msg(Data, sdl_register_super_nak),
logger:debug("[stun_client] get a register super nak: ~p", [SuperNak]),
{noreply, State#state{}};
handle_info({udp, _, Ip, Port, <<?STUN_REGISTER:8, NetworkId:32, SrcIp:32, DstIp:32>>}, State = #state{tun_socket = TunSocket, sessions = Sessions}) ->
Packet = <<?STUN_REGISTER_ACK, NetworkId:32, DstIp:32, SrcIp:32>>,
logger:debug("[stun_client] will send stun reply: ~p, peer: ~p", [Packet, {Ip, Port}]),
ok = gen_udp:send(TunSocket, Ip, Port, Packet),
handle_info({timeout, _, stun_request_ticker}, State = #state{tun_socket = TunSocket, client_id = ClientId, mac = Mac, ip = Ip, session_token = SessionToken}) ->
Packet = sdlan_pb:encode_msg(#sdl_stun_request{
client_id = ClientId,
network_id = 8,
mac = Mac,
ip = Ip,
nat_type = 0,
session_token = SessionToken
}),
gen_udp:send(TunSocket, ?SUPER_HOST, ?SUPER_PORT, <<?PACKET_STUN_REQUEST, Packet/binary>>),
erlang:start_timer(5000, self(), stun_request_ticker),
NSessions = maps:put(SrcIp, {Ip, Port}, Sessions),
{noreply, State#state{sessions = NSessions}};
handle_info({udp, _, Ip, Port, <<?STUN_REGISTER_ACK, NetworkId:32, SrcIp:32, DstIp:32>>}, State = #state{sessions = Sessions}) ->
logger:debug("[stun_client] stun_data: network_id: ~p, src: ~p, dst: ~p, register_ack!!!", [NetworkId, SrcIp, DstIp]),
NSessions = maps:put(SrcIp, {Ip, Port}, Sessions),
{noreply, State#state{sessions = NSessions}};
handle_info({udp, _, _Ip0, _Port0, <<?STUN_DATA, NetworkId:32, SrcIp:32, DstIp:32, TTL:8, Data/binary>>}, State = #state{tun_socket = TunSocket, sessions = Sessions}) ->
logger:debug("[stun_client] stun_data: network_id: ~p, src: ~p, dst: ~p, data!!!", [NetworkId, SrcIp, DstIp]),
case maps:is_key(SrcIp, Sessions) of
true ->
{Ip, Port} = maps:get(SrcIp, Sessions),
ok = gen_udp:send(TunSocket, Ip, Port, <<?STUN_DATA, NetworkId:32, DstIp:32, SrcIp:32, 255, Data/binary>>),
logger:debug("[stun_client] stun_data: network_id: ~p, src: ~p, dst: ~p, reply data!!!", [NetworkId, SrcIp, DstIp]);
false ->
logger:debug("[stun_client] stun_data: network_id: ~p, src: ~p, dst: ~p, no session", [NetworkId, SrcIp, DstIp])
end,
{noreply, State};
handle_info(Info, State = #state{}) ->
logger:debug("[stun_client] get info: ~p", [Info]),
{noreply, State}.
%% @private

View File

@ -19,7 +19,7 @@ message SDLV6Info {
// (access_token)
// ,
message SDLRegisterSuper {
uint32 version = 1;
uint32 pkt_id = 1;
string client_id = 2;
uint32 network_id = 3;
bytes mac = 4;
@ -32,29 +32,39 @@ message SDLRegisterSuper {
// udp的方式: session_token
message SDLRegisterSuperAck {
bytes aes_key = 1;
bytes session_token = 2;
uint32 pkt_id = 1;
bytes aes_key = 2;
bytes session_token = 3;
}
//
message SDLRegisterSuperNak {
uint32 error_code = 1;
string error_message = 2;
uint32 pkt_id = 1;
uint32 error_code = 2;
string error_message = 3;
}
//
message SDLQueryInfo {
uint32 network_id = 1;
bytes src_mac = 2;
bytes dst_mac = 3;
bytes session_token = 4;
uint32 pkt_id = 1;
uint32 network_id = 2;
bytes src_mac = 3;
bytes dst_mac = 4;
bytes session_token = 5;
}
message SDLPeerInfo {
uint32 network_id = 1;
bytes dst_mac = 2;
SDLV4Info v4_info = 3;
optional SDLV6Info v6_info = 4;
uint32 pkt_id = 1;
uint32 network_id = 2;
bytes dst_mac = 3;
SDLV4Info v4_info = 4;
optional SDLV6Info v6_info = 5;
}
message SDLEmptyPeerInfo {
uint32 pkt_id = 1;
uint32 network_id = 2;
bytes dst_mac = 3;
}
// ,