This time, the process of processing publish MSG is analyzed.
Started by protocol
The processing of publish types of packet is:
1Process (Packet =?) Publish_packet (_qos, Topic, _packetid, _payload), state),2 %%ACL Check3 ...4 Publish (Packet, state);5 ...6Publish (Packet =?) Publish_packet (?Qos_0, _packetid),7#proto_state {client_id = ClientId, username = Username, session = Session})8 %%processing packet Get msg9MSG =Emqttd_message:from_packet (Username, ClientId, packet),Ten %%Call the PUBLISH/2 function of the Emqttd_session module One %%Subscribe is also the Emqttd_session module that was entered by protocol . AEmqttd_session:publish (session, MSG);
1. ACL Check
2, processing packet get MSG
3. Call session module for processing
Emqttd_session Module Processing
Similar to the subscribe process, EMQTTD_SESSION:PUBLISH/2 is just an interface function that, depending on the QoS, decides
- Call a subsequent function to complete processing
- Call session process completes subsequent processing
1 %%@doc Publish Message2-spec (Publish (PID (), Mqtt_message ())-ok |{error, any ()}).3Publish (_sesspid, MSG = #mqtt_message {QoS =? QOS_0})4 %%Publish Qos0 directly5 emqttd:publish (MSG);6Publish (_sesspid, MSG = #mqtt_message {QoS =? Qos_1})7 %%publish qos1 directly, and client would puback automatically8 emqttd:publish (MSG);9Publish (sesspid, MSG = #mqtt_message {QoS =? Qos_2})Ten %%Publish Qos2 by session OneGen_server2:call (Sesspid, {publish, Msg},? Pubsub_timeout).
Direct processing
If the subsequent function is called to finish processing, continue calling EMQTTD:PUBLISH/2, then continue calling EMQTTD_SERVER:PUBLISH/1 in the EMQTTD module:
%% @doc Publish a Message-spec (Publish (MSG:: Mqtt_message ())= #mqtt_message {from = from})->
...
%%
Handling Topic
...
%%
Pulish
emqttd_pubsub:publish (Topic, MSG2), ...
or the Subscribe treatment routines:
Emqttd_protocol---> emqttd_session---> Emqttd---> Emqttd_server---> Emqttd_pubsub
The processing in the Emqttd_pubsub module is:
1 %%@doc Publish message to Topic.2-spec (Publish () (binary (), any ())Any ()).3Publish (Topic, MSG)4 Lists:foreach (5 Fun(#mqtt_route {topic = to, node = node}) whenNode =:= node ()6?Module:dispatch (to, MSG);7(#mqtt_route {topic = to, node = node})8Rpc:cast (Node,?MODULE, Dispatch, [to, MSG])9 End, Emqttd_router:lookup (Topic)).Ten OneDispatch (Topic, MSG) A CaseSubscribers (TOPIC) of -[] - dropped (Topic); the[Subpid] -Subpid!{Dispatch, Topic, MSG}; -Subpids -Lists:foreach ( Fun(Subpid) +Subpid!{Dispatch, Topic, MSG} - End, Subpids) + End. A %%@private at %%@doc Find all Subscribers -Subscribers (TOPIC) - CaseEts:member (subscriber, Topic) of - true-%%faster then lookup? - TryEts:lookup_element (subscriber, Topic, 2)CatchError:badarg []End; - false- in [] - End.
At this point, MSG has been sent to the ClientID corresponding session process in the form of {dispatch, Topic, MSG}.
Then, you need to process the Handle_info callback function in the Emqttd_session module:
1 %%Dispatch Message2Handle_info ({Dispatch, Topic, Msg}, Session = #session {subscriptions =subscriptions})3 whenIs_record (MSG, Mqtt_message)4 Dispatch (Tune_qos (Topic, MSG, subscriptions), Session);5 6 %%deliver QOS0 message directly to client7Dispatch (MSG = #mqtt_message {QoS =? QOS0}, Session = #session {client_pid = clientpid})8clientPID!{deliver, Msg},9 hibernate (Session);TenDispatch (MSG = #mqtt_message {QoS = QoS}, Session = #session {message_queue =Msgq}) One whenQoS =:=? QOS1OrElseQoS =:=? QOS2 A CaseCheck_inflight (Session) of - true- - noreply (Deliver (MSG, Session)); the false- -Hibernate (Session#session{message_queue =emqttd_mqueue:in (MSG, Msgq)}) - End.
The message is then sent to the socket controlling process, and then, depending on the QoS, it is determined whether the ACK needs to wait.
Summarize
(Process to be mended)
Emqtt 4 (I'm going to publish the news)