first workable

This commit is contained in:
erylee 2012-12-21 13:24:48 +08:00
parent fcb5ac6df3
commit 6245fb4aa9
5 changed files with 53 additions and 22 deletions

View File

@ -12,6 +12,7 @@
terminate/2]). terminate/2]).
-include("emqtt.hrl"). -include("emqtt.hrl").
-include("emqtt_frame.hrl").
-define(CLIENT_ID_MAXLEN, 23). -define(CLIENT_ID_MAXLEN, 23).
@ -53,20 +54,38 @@ handle_call({go, Sock}, _From, _State) ->
inet_error, fun () -> emqtt_net:tune_buffer_size(Sock) end), inet_error, fun () -> emqtt_net:tune_buffer_size(Sock) end),
{ok, ConnStr} = emqtt_net:connection_string(Sock, inbound), {ok, ConnStr} = emqtt_net:connection_string(Sock, inbound),
error_logger:info_msg("accepting MQTT connection (~s)~n", [ConnStr]), error_logger:info_msg("accepting MQTT connection (~s)~n", [ConnStr]),
control_throttle( {reply, ok,
control_throttle(
#state{ socket = Sock, #state{ socket = Sock,
conn_name = ConnStr, conn_name = ConnStr,
await_recv = false, await_recv = false,
connection_state = running, connection_state = running,
conserve = false, conserve = false,
parse_state = emqtt_frame:initial_state(), parse_state = emqtt_frame:initial_state(),
proc_state = emqtt_processor:initial_state(Sock) }). proc_state = emqtt_processor:initial_state(Sock) })}.
handle_cast(Msg, State) -> handle_cast(Msg, State) ->
{stop, {badmsg, Msg}, State}. {stop, {badmsg, Msg}, State}.
handle_info({route, Msg}, State) -> handle_info({route, Msg}, #state{proc_state=PState} = State) ->
emqtt_processor:send_client(Msg), #mqtt_msg{ retain = Retain,
qos = Qos,
topic = Topic,
dup = Dup,
message_id = MessageId,
payload = Payload } = Msg,
Frame = #mqtt_frame{fixed = #mqtt_frame_fixed{
type = ?PUBLISH,
qos = Qos,
retain = Retain,
dup = Dup },
variable = #mqtt_frame_publish{
topic_name = Topic,
message_id = 1},
payload = Payload },
emqtt_processor:send_client(Frame, PState),
{noreply, State}; {noreply, State};
handle_info({inet_reply, _Ref, ok}, State) -> handle_info({inet_reply, _Ref, ok}, State) ->

View File

@ -19,7 +19,7 @@
-module(emqtt_processor). -module(emqtt_processor).
-export([info/2, initial_state/1, -export([info/2, initial_state/1,
process_frame/2, send_will/1]). process_frame/2, send_client/2, send_will/1]).
-include("emqtt.hrl"). -include("emqtt.hrl").
-include("emqtt_frame.hrl"). -include("emqtt_frame.hrl").
@ -53,11 +53,6 @@ initial_state(Socket) ->
info(client_id, #proc_state{ client_id = ClientId }) -> ClientId. info(client_id, #proc_state{ client_id = ClientId }) -> ClientId.
process_frame(#mqtt_frame{ fixed = #mqtt_frame_fixed{ type = Type }},
PState = #proc_state{ connection = undefined } )
when Type =/= ?CONNECT ->
{err, connect_expected, PState};
process_frame(Frame = #mqtt_frame{ fixed = #mqtt_frame_fixed{ type = Type }}, process_frame(Frame = #mqtt_frame{ fixed = #mqtt_frame_fixed{ type = Type }},
PState ) -> PState ) ->
process_request(Type, Frame, PState). process_request(Type, Frame, PState).
@ -69,6 +64,7 @@ process_request(?CONNECT,
proto_ver = ProtoVersion, proto_ver = ProtoVersion,
clean_sess = CleanSess, clean_sess = CleanSess,
client_id = ClientId } = Var}, PState) -> client_id = ClientId } = Var}, PState) ->
error_logger:info_msg("connect frame: ~p~n", [Var]),
{ReturnCode, PState1} = {ReturnCode, PState1} =
case {ProtoVersion =:= ?MQTT_PROTO_MAJOR, case {ProtoVersion =:= ?MQTT_PROTO_MAJOR,
emqtt_util:valid_client_id(ClientId)} of emqtt_util:valid_client_id(ClientId)} of
@ -110,7 +106,7 @@ process_request(?PUBLISH,
dup = Dup }, dup = Dup },
variable = #mqtt_frame_publish{ topic_name = Topic, variable = #mqtt_frame_publish{ topic_name = Topic,
message_id = MessageId }, message_id = MessageId },
payload = Payload }, PState) -> payload = Payload }, #proc_state{ message_id = MsgId } = PState) ->
Msg = #mqtt_msg{ retain = Retain, Msg = #mqtt_msg{ retain = Retain,
qos = Qos, qos = Qos,
topic = Topic, topic = Topic,
@ -121,7 +117,7 @@ process_request(?PUBLISH,
send_client( send_client(
#mqtt_frame{ fixed = #mqtt_frame_fixed{ type = ?PUBACK }, #mqtt_frame{ fixed = #mqtt_frame_fixed{ type = ?PUBACK },
variable = #mqtt_frame_publish{ message_id = MessageId }}, variable = #mqtt_frame_publish{ message_id = MsgId}},
PState), PState),
{ok, PState}; {ok, PState};
@ -141,7 +137,7 @@ process_request(?SUBSCRIBE,
[emqtt_topic:insert(Name) || #mqtt_topic{name=Name} <- Topics], [emqtt_topic:insert(Name) || #mqtt_topic{name=Name} <- Topics],
[emqtt_router:insert(#subscriber{topic=Name, pid=self()}) [emqtt_router:insert(#subscriber{topic=emqtt_util:binary(Name), pid=self()})
|| #mqtt_topic{name=Name} <- Topics], || #mqtt_topic{name=Name} <- Topics],
send_client(#mqtt_frame{ fixed = #mqtt_frame_fixed{ type = ?SUBACK }, send_client(#mqtt_frame{ fixed = #mqtt_frame_fixed{ type = ?SUBACK },

View File

@ -1,10 +1,12 @@
-module(emqtt_router). -module(emqtt_router).
-include("emqtt.hrl"). -include("emqtt.hrl").
-include("emqtt_frame.hrl").
-export([start_link/0]). -export([start_link/0]).
-export([route/2, -export([route/1,
route/2,
insert/1, insert/1,
delete/1]). delete/1]).
@ -22,6 +24,16 @@
start_link() -> start_link() ->
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []). gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
binary(S) when is_list(S) ->
list_to_binary(S);
binary(B) when is_binary(B) ->
B.
route(#mqtt_msg{topic=Topic}=Msg) when is_record(Msg, mqtt_msg) ->
error_logger:info_msg("route msg: ~p~n", [Msg]),
[ Pid ! {route, Msg} || #subscriber{pid=Pid} <- ets:lookup(subscriber, binary(Topic)) ].
route(Topic, Msg) -> route(Topic, Msg) ->
[ Pid ! {route, Msg} || #subscriber{pid=Pid} <- ets:lookup(subscriber, Topic) ]. [ Pid ! {route, Msg} || #subscriber{pid=Pid} <- ets:lookup(subscriber, Topic) ].
@ -32,8 +44,8 @@ delete(Sub) when is_record(Sub, subscriber) ->
gen_server:cast(?MODULE, {delete, Sub}). gen_server:cast(?MODULE, {delete, Sub}).
init([]) -> init([]) ->
ets:new(subscriber, [bag, protected, {keypos, 2}]), Res = ets:new(subscriber, [bag, protected, named_table, {keypos, 2}]),
error_logger:info_msg("emqtt_router is started."), error_logger:info_msg("emqtt_router is started: ~p~n", [Res]),
{ok, #state{}}. {ok, #state{}}.
handle_call({insert, Sub}, _From, State) -> handle_call({insert, Sub}, _From, State) ->

View File

@ -22,7 +22,8 @@
start_link() -> start_link() ->
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []). gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
match(Topic) when is_binary(Topic) -> match(Topic0) ->
Topic = emqtt_util:binary(Topic0),
Words = topic_split(Topic), Words = topic_split(Topic),
DirectMatches = mnesia:dirty_read(direct_topic, Words), DirectMatches = mnesia:dirty_read(direct_topic, Words),
WildcardMatches = lists:append([ WildcardMatches = lists:append([
@ -32,11 +33,11 @@ match(Topic) when is_binary(Topic) ->
]), ]),
DirectMatches ++ WildcardMatches. DirectMatches ++ WildcardMatches.
insert(Topic) when is_binary(Topic) -> insert(Topic) ->
gen_server:call(?MODULE, {insert, Topic}). gen_server:call(?MODULE, {insert, emqtt_util:binary(Topic)}).
delete(Topic) when is_binary(Topic) -> delete(Topic) ->
gen_server:cast(?MODULE, {delete, Topic}). gen_server:cast(?MODULE, {delete, emqtt_util:binary(Topic)}).
init([]) -> init([]) ->
{atomic, ok} = mnesia:create_table( {atomic, ok} = mnesia:create_table(

View File

@ -6,6 +6,9 @@
-compile(export_all). -compile(export_all).
binary(L) when is_list(L) -> list_to_binary(L);
binary(B) when is_binary(B) -> B.
subcription_queue_name(ClientId) -> subcription_queue_name(ClientId) ->
Base = "mqtt-subscription-" ++ ClientId ++ "qos", Base = "mqtt-subscription-" ++ ClientId ++ "qos",
{list_to_binary(Base ++ "0"), list_to_binary(Base ++ "1")}. {list_to_binary(Base ++ "0"), list_to_binary(Base ++ "1")}.